func()

in resolve/resolve.go [485:585]


func (r *resolver) stmt(stmt syntax.Stmt) {
	switch stmt := stmt.(type) {
	case *syntax.ExprStmt:
		r.expr(stmt.X)

	case *syntax.BranchStmt:
		if r.loops == 0 && (stmt.Token == syntax.BREAK || stmt.Token == syntax.CONTINUE) {
			r.errorf(stmt.TokenPos, "%s not in a loop", stmt.Token)
		}

	case *syntax.IfStmt:
		if !AllowGlobalReassign && r.container().function == nil {
			r.errorf(stmt.If, "if statement not within a function")
		}
		r.expr(stmt.Cond)
		r.ifstmts++
		r.stmts(stmt.True)
		r.stmts(stmt.False)
		r.ifstmts--

	case *syntax.AssignStmt:
		r.expr(stmt.RHS)
		isAugmented := stmt.Op != syntax.EQ
		r.assign(stmt.LHS, isAugmented)

	case *syntax.DefStmt:
		r.bind(stmt.Name)
		fn := &Function{
			Name:   stmt.Name.Name,
			Pos:    stmt.Def,
			Params: stmt.Params,
			Body:   stmt.Body,
		}
		stmt.Function = fn
		r.function(fn, stmt.Def)

	case *syntax.ForStmt:
		if !AllowGlobalReassign && r.container().function == nil {
			r.errorf(stmt.For, "for loop not within a function")
		}
		r.expr(stmt.X)
		const isAugmented = false
		r.assign(stmt.Vars, isAugmented)
		r.loops++
		r.stmts(stmt.Body)
		r.loops--

	case *syntax.WhileStmt:
		if !AllowRecursion {
			r.errorf(stmt.While, doesnt+"support while loops")
		}
		if !AllowGlobalReassign && r.container().function == nil {
			r.errorf(stmt.While, "while loop not within a function")
		}
		r.expr(stmt.Cond)
		r.loops++
		r.stmts(stmt.Body)
		r.loops--

	case *syntax.ReturnStmt:
		if r.container().function == nil {
			r.errorf(stmt.Return, "return statement not within a function")
		}
		if stmt.Result != nil {
			r.expr(stmt.Result)
		}

	case *syntax.LoadStmt:
		// A load statement may not be nested in any other statement.
		if r.container().function != nil {
			r.errorf(stmt.Load, "load statement within a function")
		} else if r.loops > 0 {
			r.errorf(stmt.Load, "load statement within a loop")
		} else if r.ifstmts > 0 {
			r.errorf(stmt.Load, "load statement within a conditional")
		}

		for i, from := range stmt.From {
			if from.Name == "" {
				r.errorf(from.NamePos, "load: empty identifier")
				continue
			}
			if from.Name[0] == '_' {
				r.errorf(from.NamePos, "load: names with leading underscores are not exported: %s", from.Name)
			}

			id := stmt.To[i]
			if LoadBindsGlobally {
				r.bind(id)
			} else if r.bindLocal(id) && !AllowGlobalReassign {
				// "Global" in AllowGlobalReassign is a misnomer for "toplevel".
				// Sadly we can't report the previous declaration
				// as id.Binding may not be set yet.
				r.errorf(id.NamePos, "cannot reassign top-level %s", id.Name)
			}
		}

	default:
		log.Panicf("unexpected stmt %T", stmt)
	}
}