Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,32 @@
- Don't add comments explaining each line of code. If you need to add comments to describe a block of statements then you should extract them to
a function with meaningful name.

- Each bal/go file should have the correct license header

## Symbols

- IMPORTANT: never store `model.Symbol` as the key in a map, always use a `model.SymbolRef`
- Don't call operations on symbols directly instead call them via compiler context

## Interpreter stages

1. Generate Syntax Tree
2. Do symbol resolution
3. Do type resolution
4. Generate Control Flow Graph (CFG)
5. Do semantic analysis
6. Analyze CFG
2. Generate Abstract syntax tree (AST)
3. Do symbol resolution
4. Do type resolution
5. Type Narrowing
6. Semantic analysis
7. Generate Control Flow Graph (CFG)
8. Analyze CFG
- Reachability analysis
- Explicit return analysis
7. Generate BIR
8. Interpret generated BIR
9. Desugar AST
10. Generate BIR
11. Interpret generated BIR

Stages up to 10 are considered front end, and stage 11 is backend

Stages up to 7 are considered front end.
Execution of these stages is defined in `module_context.go` (and `testphases/phases.go` for corpus tests)

## Tests

Expand All @@ -51,9 +59,11 @@ Stages up to 7 are considered front end.

- You can run interpreter as `go run ./cli/cmd run [flags] <path to bal file>`

## Profiling
## Profiling

- In order to profile a `.bal` file first you need to get a debug build (`go build -tags debug -o bal-debug ./cli/cmd`)
- Then run the debug build against the bal file `./bal-debug [flag] -prof <path to bal file>`.

### Opening interactive profiler on log running processes

- After running the interpreter with profiling flags run `go tool pprof -http=:8080 http://localhost:6060/debug/pprof/profile?seconds=30` and open `localhost:8080` in the browser
10 changes: 3 additions & 7 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ func UnMask(mask Flags) common.Set[model.Flag] {

type BNodeWithSymbol interface {
model.NodeWithSymbol
BLangNode
SetSymbol(symbolRef model.SymbolRef)
}

Expand Down Expand Up @@ -237,13 +238,8 @@ type (
BLangNodeBase struct {
ty model.TypeData
DeterminedType semtypes.SemType

parent BLangNode

pos Location
desugared bool
constantPropagated bool
internal bool
parent BLangNode
pos Location
}

// TODO: look into what is the difference between the public TypeData fields and ty
Expand Down
40 changes: 13 additions & 27 deletions ast/corpus_ast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
// specific language governing permissions and limitations
// under the License.

package ast
package ast_test

import (
debugcommon "ballerina-lang-go/common"
"ballerina-lang-go/ast"
"ballerina-lang-go/context"
"ballerina-lang-go/model"
"ballerina-lang-go/parser"
"ballerina-lang-go/semtypes"
"ballerina-lang-go/test_util"
"ballerina-lang-go/test_util/testphases"
"flag"
"fmt"
"testing"
Expand Down Expand Up @@ -50,20 +50,14 @@ func testASTGeneration(t *testing.T, testCase test_util.TestCase) {
}
}()

debugCtx := debugcommon.DebugContext{
Channel: make(chan string),
}
cx := context.NewCompilerContext(semtypes.CreateTypeEnv())
syntaxTree, err := parser.GetSyntaxTree(cx, &debugCtx, testCase.InputPath)
result, err := testphases.RunPipeline(cx, testphases.PhaseAST, testCase.InputPath)
if err != nil {
t.Errorf("error getting syntax tree for %s: %v", testCase.InputPath, err)
}
compilationUnit := GetCompilationUnit(cx, syntaxTree)
if compilationUnit == nil {
t.Errorf("compilation unit is nil for %s", testCase.InputPath)
t.Errorf("pipeline failed for %s: %v", testCase.InputPath, err)
return
}
prettyPrinter := PrettyPrinter{}
actualAST := prettyPrinter.Print(compilationUnit)
prettyPrinter := ast.PrettyPrinter{}
actualAST := prettyPrinter.Print(result.CompilationUnit)

// If update flag is set, update expected file
if *update {
Expand Down Expand Up @@ -99,7 +93,7 @@ type walkTestVisitor struct {
nodeCount int
}

func (v *walkTestVisitor) Visit(node BLangNode) Visitor {
func (v *walkTestVisitor) Visit(node ast.BLangNode) ast.Visitor {
if node == nil {
return nil
}
Expand All @@ -109,7 +103,7 @@ func (v *walkTestVisitor) Visit(node BLangNode) Visitor {
return v
}

func (v *walkTestVisitor) VisitTypeData(typeData *model.TypeData) Visitor {
func (v *walkTestVisitor) VisitTypeData(typeData *model.TypeData) ast.Visitor {
return v
}

Expand All @@ -133,23 +127,15 @@ func testWalkTraversal(t *testing.T, testCase test_util.TestCase) {
}
}()

debugCtx := debugcommon.DebugContext{
Channel: make(chan string),
}
cx := context.NewCompilerContext(semtypes.CreateTypeEnv())
syntaxTree, err := parser.GetSyntaxTree(cx, &debugCtx, testCase.InputPath)
result, err := testphases.RunPipeline(cx, testphases.PhaseAST, testCase.InputPath)
if err != nil {
t.Errorf("error getting syntax tree for %s: %v", testCase.InputPath, err)
return
}
compilationUnit := GetCompilationUnit(cx, syntaxTree)
if compilationUnit == nil {
t.Errorf("compilation unit is nil for %s", testCase.InputPath)
t.Errorf("pipeline failed for %s: %v", testCase.InputPath, err)
return
}

visitor := &walkTestVisitor{visitedTypes: make(map[string]int)}
Walk(visitor, compilationUnit)
ast.Walk(visitor, result.CompilationUnit)

if visitor.nodeCount == 0 {
t.Errorf("Walk visited 0 nodes for %s", testCase.InputPath)
Expand Down
29 changes: 29 additions & 0 deletions ast/expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,13 @@
PositionalArgs []BLangExpression
// TODO: Add support for NamedArgs
}

BLangTypeTestExpr struct {
BLangExpressionBase
Expr BLangExpression
Type model.TypeData
isNegation bool
}
)

var (
Expand Down Expand Up @@ -316,6 +323,8 @@
_ BLangExpression = &BLangTypeConversionExpr{}
_ BLangExpression = &BLangErrorConstructorExpr{}
_ BLangNode = &BLangErrorConstructorExpr{}
_ BLangExpression = &BLangTypeTestExpr{}
_ model.TypeTestExpressionNode = &BLangTypeTestExpr{}
)

var (
Expand Down Expand Up @@ -954,6 +963,26 @@
panic("not implemented")
}

func (this *BLangTypeTestExpr) GetKind() model.NodeKind {
return model.NodeKind_TYPE_TEST_EXPR

Check warning on line 967 in ast/expressions.go

View check run for this annotation

Codecov / codecov/patch

ast/expressions.go#L966-L967

Added lines #L966 - L967 were not covered by tests
}

func (this *BLangTypeTestExpr) IsNegation() bool {
return this.isNegation
}

func (this *BLangTypeTestExpr) GetExpression() model.ExpressionNode {
return this.Expr

Check warning on line 975 in ast/expressions.go

View check run for this annotation

Codecov / codecov/patch

ast/expressions.go#L974-L975

Added lines #L974 - L975 were not covered by tests
}

func (this *BLangTypeTestExpr) GetType() model.TypeData {
return this.Type

Check warning on line 979 in ast/expressions.go

View check run for this annotation

Codecov / codecov/patch

ast/expressions.go#L978-L979

Added lines #L978 - L979 were not covered by tests
}

func (this *BLangTypeTestExpr) SetTypeCheckedType(ty BType) {
panic("not implemented")

Check warning on line 983 in ast/expressions.go

View check run for this annotation

Codecov / codecov/patch

ast/expressions.go#L982-L983

Added lines #L982 - L983 were not covered by tests
}

func createBLangUnaryExpr(location Location, operator model.OperatorKind, expr BLangExpression) *BLangUnaryExpr {
exprNode := &BLangUnaryExpr{}
exprNode.pos = location
Expand Down
83 changes: 77 additions & 6 deletions ast/match_patterns.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,48 @@

package ast

import "ballerina-lang-go/model"
import (
"ballerina-lang-go/model"
"ballerina-lang-go/semtypes"
)

type BLangMatchPattern interface {
model.MatchPatternNode
SetAcceptedType(semtypes.SemType)
}

type BLangMatchGuard BLangExpression

type (
BLangMatchPatternBase struct {
BLangMatchClause struct {
BLangNodeBase
Guard BLangExpression
Body BLangBlockStmt
Patterns []BLangMatchPattern
AcceptedType semtypes.SemType
}

MatchExpr BLangExpression
MatchGuardIsAvailable bool
IsLastPattern bool
bLangMatchPatternBase struct {
BLangNodeBase
AcceptedType semtypes.SemType
}
BLangConstPattern struct {
BLangMatchPatternBase
bLangMatchPatternBase
Expr BLangExpression
}

BLangWildCardMatchPattern struct {
bLangMatchPatternBase
}
)

var _ model.ConstPatternNode = &BLangConstPattern{}
var _ model.MatchClause = &BLangMatchClause{}
var _ BLangMatchPattern = &BLangConstPattern{}
var _ BLangMatchPattern = &BLangWildCardMatchPattern{}

var _ BLangNode = &BLangConstPattern{}
var _ BLangNode = &BLangMatchClause{}

func (this *BLangConstPattern) GetKind() model.NodeKind {
// migrated from BLangConstPattern.java:53:5
Expand All @@ -54,3 +77,51 @@
panic("Expected BLangExpression")
}
}

func (this *BLangWildCardMatchPattern) GetKind() model.NodeKind {
return model.NodeKind_WILDCARD_MATCH_PATTERN

Check warning on line 82 in ast/match_patterns.go

View check run for this annotation

Codecov / codecov/patch

ast/match_patterns.go#L81-L82

Added lines #L81 - L82 were not covered by tests
}

func (this *BLangMatchClause) GetKind() model.NodeKind {
return model.NodeKind_MATCH_CLAUSE

Check warning on line 86 in ast/match_patterns.go

View check run for this annotation

Codecov / codecov/patch

ast/match_patterns.go#L85-L86

Added lines #L85 - L86 were not covered by tests
}

func (this *BLangMatchClause) GetMatchGuard() model.MatchGuard {
return this.Guard

Check warning on line 90 in ast/match_patterns.go

View check run for this annotation

Codecov / codecov/patch

ast/match_patterns.go#L89-L90

Added lines #L89 - L90 were not covered by tests
}

func (this *BLangMatchClause) GetBlockStatementNode() model.BlockStatementNode {
return &this.Body

Check warning on line 94 in ast/match_patterns.go

View check run for this annotation

Codecov / codecov/patch

ast/match_patterns.go#L93-L94

Added lines #L93 - L94 were not covered by tests
}

func (this *BLangMatchClause) GetMatchPatterns() []model.MatchPatternNode {
result := make([]model.MatchPatternNode, len(this.Patterns))
for i, p := range this.Patterns {
result[i] = p

Check warning on line 100 in ast/match_patterns.go

View check run for this annotation

Codecov / codecov/patch

ast/match_patterns.go#L97-L100

Added lines #L97 - L100 were not covered by tests
}
return result

Check warning on line 102 in ast/match_patterns.go

View check run for this annotation

Codecov / codecov/patch

ast/match_patterns.go#L102

Added line #L102 was not covered by tests
}

func (this *BLangMatchClause) SetMatchClause(node BLangMatchGuard) {
this.Guard = node

Check warning on line 106 in ast/match_patterns.go

View check run for this annotation

Codecov / codecov/patch

ast/match_patterns.go#L105-L106

Added lines #L105 - L106 were not covered by tests
}

func (this *BLangMatchClause) SetBlockStatementNode(node BLangBlockStmt) {
this.Body = node

Check warning on line 110 in ast/match_patterns.go

View check run for this annotation

Codecov / codecov/patch

ast/match_patterns.go#L109-L110

Added lines #L109 - L110 were not covered by tests
}

func (this *BLangMatchClause) SetMatchPatterns(nodes []BLangMatchPattern) {
this.Patterns = nodes

Check warning on line 114 in ast/match_patterns.go

View check run for this annotation

Codecov / codecov/patch

ast/match_patterns.go#L113-L114

Added lines #L113 - L114 were not covered by tests
}

func (this *BLangMatchClause) GetAcceptedType() semtypes.SemType {
return this.AcceptedType

Check warning on line 118 in ast/match_patterns.go

View check run for this annotation

Codecov / codecov/patch

ast/match_patterns.go#L117-L118

Added lines #L117 - L118 were not covered by tests
}

func (this *bLangMatchPatternBase) GetAcceptedType() semtypes.SemType {
return this.AcceptedType

Check warning on line 122 in ast/match_patterns.go

View check run for this annotation

Codecov / codecov/patch

ast/match_patterns.go#L121-L122

Added lines #L121 - L122 were not covered by tests
}

func (this *bLangMatchPatternBase) SetAcceptedType(t semtypes.SemType) {
this.AcceptedType = t
}
Loading