github.com/jmigpin/editor@v1.6.0/core/godebug/annotatorctx.go (about) 1 package godebug 2 3 import ( 4 "go/ast" 5 ) 6 7 type Ctx struct { 8 pctx *Ctx 9 id ctxId 10 value interface{} 11 } 12 13 func (ctx *Ctx) WithValue(id ctxId, value interface{}) *Ctx { 14 return &Ctx{ctx, id, value} 15 } 16 func (ctx *Ctx) Value(id ctxId) (interface{}, *Ctx) { 17 for c := ctx; c != nil; c = c.pctx { 18 if c.id == id { 19 return c.value, c 20 } 21 } 22 return nil, nil 23 } 24 func (ctx *Ctx) SetValue(value interface{}) { 25 ctx.value = value 26 } 27 28 //---------- 29 30 func (ctx *Ctx) withBoolean(id ctxId, v bool) *Ctx { 31 return ctx.WithValue(id, v) 32 } 33 func (ctx *Ctx) boolean(id ctxId) bool { 34 v, _ := ctx.Value(id) 35 if v == nil { 36 return false 37 } 38 return v.(bool) 39 } 40 41 //---------- 42 43 func (ctx *Ctx) withExpr(e *ast.Expr) *Ctx { 44 return ctx.WithValue(ctxIdExpr, e) 45 } 46 func (ctx *Ctx) replaceExpr(e ast.Expr) { 47 v, _ := ctx.Value(ctxIdExpr) 48 if v == nil { 49 panic("ctx: missing expr") 50 } 51 u := v.(*ast.Expr) 52 *u = e 53 } 54 55 //---------- 56 57 func (ctx *Ctx) withExprs(es *[]ast.Expr) *Ctx { 58 return ctx.WithValue(ctxIdExprs, es) 59 } 60 func (ctx *Ctx) replaceExprs(es []ast.Expr) { 61 v, _ := ctx.Value(ctxIdExprs) 62 if v == nil { 63 panic("ctx: missing exprs") 64 } 65 u := v.(*[]ast.Expr) 66 *u = es 67 } 68 69 //---------- 70 71 func (ctx *Ctx) withCallExpr(cep **ast.CallExpr) *Ctx { 72 return ctx.WithValue(ctxIdCallExpr, cep) 73 } 74 func (ctx *Ctx) replaceCallExpr(ce *ast.CallExpr) { 75 v, _ := ctx.Value(ctxIdCallExpr) 76 if v == nil { 77 panic("ctx: missing call expr") 78 } 79 u := v.(**ast.CallExpr) 80 *u = ce 81 } 82 83 //---------- 84 85 func (ctx *Ctx) withStmtsIter(si *StmtsIter) *Ctx { 86 return ctx.WithValue(ctxIdStmtsIter, si) 87 } 88 func (ctx *Ctx) stmtsIter() *StmtsIter { 89 v, _ := ctx.Value(ctxIdStmtsIter) 90 if v == nil { 91 panic("ctx: stmtsiter not set") 92 } 93 return v.(*StmtsIter) 94 } 95 96 //---------- 97 98 func (ctx *Ctx) withStmts(stmts *[]ast.Stmt) *Ctx { 99 si := &StmtsIter{stmts: stmts} 100 return ctx.withStmtsIter(si) 101 } 102 func (ctx *Ctx) insertStmt(stmt ast.Stmt) { 103 si := ctx.stmtsIter() 104 if ctx.insertStmtAfter() { 105 si.after++ 106 k := si.index + si.after 107 *si.stmts = insertStmtAt(*si.stmts, k, stmt) 108 return 109 } 110 *si.stmts = insertStmtAt(*si.stmts, si.index, stmt) 111 si.index++ 112 } 113 func (ctx *Ctx) replaceStmt(stmt ast.Stmt) { 114 si := ctx.stmtsIter() 115 (*si.stmts)[si.index] = stmt 116 } 117 func (ctx *Ctx) nilifyStmt(stmt *ast.Stmt) { 118 *stmt = nil 119 } 120 func (ctx *Ctx) curStmt() ast.Stmt { // can be nil 121 si := ctx.stmtsIter() 122 if si.index >= len(*si.stmts) { 123 return nil 124 } 125 return (*si.stmts)[si.index] 126 } 127 func (ctx *Ctx) nextStmt() ast.Stmt { // can be nil 128 si := ctx.stmtsIter() 129 130 // advance 131 si.index += si.after + 1 132 si.after = 0 133 134 return ctx.curStmt() 135 } 136 137 //---------- 138 139 func (ctx *Ctx) withInsertStmtAfter(v bool) *Ctx { 140 return ctx.withBoolean(ctxIdStmtsIterInsertAfter, v) 141 } 142 func (ctx *Ctx) insertStmtAfter() bool { 143 return ctx.boolean(ctxIdStmtsIterInsertAfter) 144 } 145 146 //---------- 147 148 func (ctx *Ctx) withNResults(n int) *Ctx { 149 return ctx.WithValue(ctxIdNResults, n) 150 } 151 func (ctx *Ctx) nResults() int { 152 v, _ := ctx.Value(ctxIdNResults) 153 if v == nil { 154 return 0 155 } 156 u := v.(int) 157 return u 158 } 159 160 //---------- 161 162 func (ctx *Ctx) withDebugIndex(v int) *Ctx { 163 return ctx.WithValue(ctxIdDebugIndex, &v) 164 } 165 func (ctx *Ctx) debugIndex() *int { 166 v, _ := ctx.Value(ctxIdDebugIndex) 167 if v == nil { 168 panic("ctx: debugindex not set") 169 } 170 return v.(*int) 171 } 172 func (ctx *Ctx) nextDebugIndex() int { 173 u := ctx.debugIndex() 174 r := *u 175 176 fdi, ok := ctx.fixedDebugIndex() 177 if ok { 178 if fdi.added { 179 return fdi.index 180 } 181 fdi.added = true 182 fdi.index = r 183 } 184 185 *u++ 186 return r 187 } 188 189 //---------- 190 191 func (ctx *Ctx) withFixedDebugIndex() *Ctx { 192 if _, ok := ctx.fixedDebugIndex(); ok { 193 return ctx 194 } 195 v := &FixedDebugIndex{} 196 return ctx.WithValue(ctxIdFixedDebugIndex, v) 197 } 198 func (ctx *Ctx) fixedDebugIndex() (*FixedDebugIndex, bool) { 199 v, _ := ctx.Value(ctxIdFixedDebugIndex) 200 if v == nil { 201 return nil, false 202 } 203 return v.(*FixedDebugIndex), true 204 } 205 func (ctx *Ctx) withNilFixedDebugIndex() *Ctx { 206 return ctx.WithValue(ctxIdFixedDebugIndex, nil) 207 } 208 209 //---------- 210 211 func (ctx *Ctx) withFuncType(ft *ast.FuncType) *Ctx { 212 return ctx.WithValue(ctxIdFuncType, ft) 213 } 214 func (ctx *Ctx) funcType() (*ast.FuncType, bool) { 215 v, _ := ctx.Value(ctxIdFuncType) 216 if v == nil { 217 return nil, false 218 } 219 u := v.(*ast.FuncType) 220 return u, true 221 } 222 223 //---------- 224 225 func (ctx *Ctx) withTakingVarAddress(e ast.Expr) *Ctx { 226 return ctx.WithValue(ctxIdTakingVarAddress, e) 227 } 228 func (ctx *Ctx) takingVarAddress() (ast.Expr, bool) { 229 v, _ := ctx.Value(ctxIdTakingVarAddress) 230 if v == nil { 231 return nil, false 232 } 233 return v.(ast.Expr), true 234 } 235 236 //---------- 237 238 func (ctx *Ctx) withTypeInsteadOfValue(e *ast.Expr) *Ctx { 239 return ctx.WithValue(ctxIdTypeInsteadOfValue, e) 240 } 241 func (ctx *Ctx) typeInsteadOfValue() (*ast.Expr, bool) { 242 v, _ := ctx.Value(ctxIdTypeInsteadOfValue) 243 if v == nil { 244 return nil, false 245 } 246 return v.(*ast.Expr), true 247 } 248 249 //---------- 250 251 func (ctx *Ctx) withLabeledStmt(ls *ast.LabeledStmt) *Ctx { 252 return ctx.WithValue(ctxIdLabeledStmt, ls) 253 } 254 func (ctx *Ctx) labeledStmt() (*ast.LabeledStmt, bool) { 255 v, _ := ctx.Value(ctxIdLabeledStmt) 256 if v == nil { 257 return nil, false 258 } 259 return v.(*ast.LabeledStmt), true 260 } 261 262 //---------- 263 264 func (ctx *Ctx) withResetForFuncLit() *Ctx { 265 ctx2 := &Ctx{} // new ctx (full reset) 266 267 v, _ := ctx.Value(ctxIdDebugIndex) 268 ctx2 = ctx2.WithValue(ctxIdDebugIndex, v) 269 270 v2 := ctx.boolean(ctxIdNoAnnotations) 271 if v2 { 272 ctx2 = ctx2.withBoolean(ctxIdNoAnnotations, v2) 273 } 274 275 return ctx2 276 } 277 278 //---------- 279 //---------- 280 //---------- 281 282 type ctxId int 283 284 const ( 285 ctxIdNone ctxId = iota 286 ctxIdFuncType 287 ctxIdTakingVarAddress 288 ctxIdTypeInsteadOfValue 289 ctxIdLabeledStmt 290 ctxIdNResults // int 291 ctxIdStmtsIter 292 ctxIdStmtsIterInsertAfter // bool 293 ctxIdExpr 294 ctxIdExprs 295 ctxIdCallExpr // pointer 296 ctxIdDebugIndex // int 297 ctxIdFixedDebugIndex // struct 298 299 ctxIdExprInLhs // bool 300 ctxIdNoAnnotations // bool 301 ctxIdNameInsteadOfValue // bool 302 ctxIdFirstArgIsType // bool 303 ctxIdInTypeArg // bool 304 ctxIdInDeclStmt // bool 305 ) 306 307 //---------- 308 309 type StmtsIter struct { 310 stmts *[]ast.Stmt 311 index int // current 312 after int // n inserted after 313 } 314 315 //---------- 316 317 type DebugIndex struct { 318 index int 319 } 320 type FixedDebugIndex struct { 321 index int 322 added bool 323 } 324 325 //---------- 326 327 func insertStmtAt(ss []ast.Stmt, index int, stmt ast.Stmt) []ast.Stmt { 328 if len(ss) <= index { // nil or empty slice or after last element 329 return append(ss, stmt) 330 } 331 ss = append(ss[:index+1], ss[index:]...) // get space, index < len(a) 332 ss[index] = stmt 333 return ss 334 }