func (tc *templateChecker) recurse(parent ast.ParentNode) { var initialForVars = len(tc.forVars) var initialLetVars = len(tc.letVars) var initialUsedKeys = len(tc.usedKeys) for _, child := range parent.Children() { tc.checkTemplate(child) } tc.forVars = tc.forVars[:initialForVars] // quick return if there were no {let}s if initialLetVars == len(tc.letVars) { return } // "pop" the {let} variables, as well as their usages. // (this is necessary to handle shadowing of @params by {let} vars) var letVarsGoingOutOfScope = tc.letVars[initialLetVars:] var usedKeysToKeep, usedLets []string for _, key := range tc.usedKeys[initialUsedKeys:] { if contains(letVarsGoingOutOfScope, key) { usedLets = append(usedLets, key) } else { usedKeysToKeep = append(usedKeysToKeep, key) } } // check that any let variables leaving scope have been used for _, letVar := range letVarsGoingOutOfScope { if !contains(usedLets, letVar) { panic(fmt.Errorf("{let} variable %q is not used.", letVar)) } } tc.usedKeys = append(tc.usedKeys[:initialUsedKeys], usedKeysToKeep...) tc.letVars = tc.letVars[:initialLetVars] }
func (s *state) op(symbol string, node ast.ParentNode) { var children = node.Children() s.js("(", children[0], " ", symbol, " ", children[1], ")") }
func (s *state) visitChildren(parent ast.ParentNode) { for _, child := range parent.Children() { s.walk(child) } }