Skip to content

Commit

Permalink
save
Browse files Browse the repository at this point in the history
  • Loading branch information
petar-dambovaliev committed Jun 12, 2024
1 parent 3f7bf5c commit 813b7e1
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 22 deletions.
74 changes: 52 additions & 22 deletions gnovm/pkg/gnolang/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -2816,7 +2816,7 @@ func findUndefined(store Store, last BlockNode, x Expr) (un Name) {
}

// finds the next undefined identifier and returns it if it is global
func findUndefined2SkipLocals(store Store, last BlockNode, x Expr, t Type) Name {
func findUndefined2SkipLocals(store Store, last BlockNode, x Expr, t Type, st *SymbolTable) Name {
name := findUndefined2(store, last, x, t)

if name != "" {
Expand All @@ -2826,122 +2826,151 @@ func findUndefined2SkipLocals(store Store, last BlockNode, x Expr, t Type) Name
// skip it if it's a local identifier
return ""
}

isLocal := st.IdentifierExists(string(name))

if isLocal {
return ""
}
}

return name
}

func findUndefinedStmt(store Store, last BlockNode, stmt Stmt, t Type) Name {
func findUndefinedStmt(store Store, last BlockNode, stmt Stmt, t Type, st *SymbolTable) Name {
switch s := stmt.(type) {
case *ValueDecl:
for _, rh := range s.Values {
un := findUndefined2SkipLocals(store, last, rh, t, st)

if un != "" {
return un
}
}

for _, rh := range s.NameExprs {
st.AddIdentifier(string(rh.Name))
}
case *DeclStmt:
for _, rh := range s.Body {
un := findUndefinedStmt(store, last, rh, t, st)

if un != "" {
return un
}
}
case *IncDecStmt:
un := findUndefined2SkipLocals(store, last, s.X, t)
un := findUndefined2SkipLocals(store, last, s.X, t, st)

if un != "" {
return un
}
case *PanicStmt:
un := findUndefined2SkipLocals(store, last, s.Exception, t)
un := findUndefined2SkipLocals(store, last, s.Exception, t, st)

if un != "" {
return un
}
case *BlockStmt:
for _, rh := range s.Body {
un := findUndefinedStmt(store, last, rh, t)
un := findUndefinedStmt(store, last, rh, t, st)

if un != "" {
return un
}
}
case *DeferStmt:
un := findUndefined2SkipLocals(store, last, s.Call.Func, t)
un := findUndefined2SkipLocals(store, last, s.Call.Func, t, st)

if un != "" {
return un
}

for _, rh := range s.Call.Args {
un = findUndefined2SkipLocals(store, last, rh, t)
un = findUndefined2SkipLocals(store, last, rh, t, st)

if un != "" {
return un
}
}
case *SwitchStmt:
un := findUndefined2SkipLocals(store, last, s.X, t)
un := findUndefined2SkipLocals(store, last, s.X, t, st)
if un != "" {
return un
}

un = findUndefinedStmt(store, last, s.Init, t)
un = findUndefinedStmt(store, last, s.Init, t, st)
if un != "" {
return un
}

for _, b := range s.Clauses {
b := b
un = findUndefinedStmt(store, last, &b, t)
un = findUndefinedStmt(store, last, &b, t, st)

if un != "" {
return un
}
}
case *SwitchClauseStmt:
for _, rh := range s.Cases {
un := findUndefined2SkipLocals(store, last, rh, t)
un := findUndefined2SkipLocals(store, last, rh, t, st)

if un != "" {
return un
}
}
case *ExprStmt:
return findUndefined2SkipLocals(store, last, s.X, t)
return findUndefined2SkipLocals(store, last, s.X, t, st)
case *AssignStmt:
for _, rh := range s.Rhs {
un := findUndefined2SkipLocals(store, last, rh, t)
for i, rh := range s.Rhs {
if s.Op == DEFINE {
st.AddIdentifier(string(s.Lhs[i].(*NameExpr).Name))
}
un := findUndefined2SkipLocals(store, last, rh, t, st)

if un != "" {
return un
}
}
case *IfStmt:
un := findUndefined2SkipLocals(store, last, s.Cond, t)
un := findUndefined2SkipLocals(store, last, s.Cond, t, st)
if un != "" {
return un
}

un = findUndefinedStmt(store, last, &s.Else, t)
un = findUndefinedStmt(store, last, &s.Else, t, st)
if un != "" {
return un
}

un = findUndefinedStmt(store, last, &s.Then, t)
un = findUndefinedStmt(store, last, &s.Then, t, st)
if un != "" {
return un
}
case *IfCaseStmt:
for _, b := range s.Body {
un := findUndefinedStmt(store, last, b, t)
un := findUndefinedStmt(store, last, b, t, st)

if un != "" {
return un
}
}
case *ReturnStmt:
for _, b := range s.Results {
un := findUndefined2SkipLocals(store, last, b, t)
un := findUndefined2SkipLocals(store, last, b, t, st)
if un != "" {
return un
}
}
case *RangeStmt:
un := findUndefined2SkipLocals(store, last, s.X, t)
un := findUndefined2SkipLocals(store, last, s.X, t, st)
if un != "" {
return un
}

for _, b := range s.Body {
un := findUndefinedStmt(store, last, b, t)
un := findUndefinedStmt(store, last, b, t, st)
if un != "" {
return un
}
Expand Down Expand Up @@ -3066,8 +3095,9 @@ func findUndefined2(store Store, last BlockNode, x Expr, t Type) (un Name) {
ct.String()))
}
case *FuncLitExpr:
st := NewSymbolTable()
for _, stmt := range cx.Body {
un = findUndefinedStmt(store, last, stmt, t)
un = findUndefinedStmt(store, last, stmt, t, st)

if un != "" {
return
Expand Down
46 changes: 46 additions & 0 deletions gnovm/pkg/gnolang/symbols_table.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package gnolang

type SymbolTable struct {
scopes []*Scope
}

type Scope struct {
symbols map[string]struct{}
}

func NewSymbolTable() *SymbolTable {
return &SymbolTable{
scopes: []*Scope{newScope()},
}
}

func newScope() *Scope {
return &Scope{
symbols: make(map[string]struct{}),
}
}

func (st *SymbolTable) EnterScope() {
st.scopes = append(st.scopes, newScope())
}

func (st *SymbolTable) ExitScope() {
if len(st.scopes) > 1 {
st.scopes = st.scopes[:len(st.scopes)-1]
}
}

func (st *SymbolTable) AddIdentifier(name string) {
if len(st.scopes) > 0 {
st.scopes[len(st.scopes)-1].symbols[name] = struct{}{}
}
}

func (st *SymbolTable) IdentifierExists(name string) bool {
for i := len(st.scopes) - 1; i >= 0; i-- {
if _, exists := st.scopes[i].symbols[name]; exists {
return true
}
}
return false
}
9 changes: 9 additions & 0 deletions gnovm/tests/files/var21.gno
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,12 @@ var myVar3 = func() {
}

var myDep3 string

var v1 = func() int {
v2 := 11
return v2
}()

var v2 = func() int {
return v1
}()

0 comments on commit 813b7e1

Please sign in to comment.