func (s *Styler) Ident(id *ast.Ident) (text []byte, tag printer.HTMLTag) { text = strings.Bytes(id.Name()) if s.highlight == id.Name() { tag = printer.HTMLTag{"<span class=highlight>", "</span>"} } return }
func (a *typeCompiler) compileIdent(x *ast.Ident, allowRec bool) Type { _, _, def := a.block.Lookup(x.Name()) if def == nil { a.diagAt(x, "%s: undefined", x.Name()) return nil } switch def := def.(type) { case *Constant: a.diagAt(x, "constant %v used as type", x.Name()) return nil case *Variable: a.diagAt(x, "variable %v used as type", x.Name()) return nil case *NamedType: if !allowRec && def.incomplete { a.diagAt(x, "illegal recursive type") return nil } if !def.incomplete && def.Def == nil { // Placeholder type from an earlier error return nil } return def case Type: return def } log.Crashf("name %s has unknown type %T", x.Name(), def) return nil }
func (s *snippetStyler) Ident(id *ast.Ident) (text []byte, tag printer.HTMLTag) { text = []byte(id.Name()) if s.highlight == id { tag = printer.HTMLTag{"<span class=highlight>", "</span>"} } return }
func (a *stmtCompiler) findLexicalLabel(name *ast.Ident, pred func(*label) bool, errOp, errCtx string) *label { bc := a.blockCompiler for ; bc != nil; bc = bc.parent { if bc.label == nil { continue } l := bc.label if name == nil && pred(l) { return l } if name != nil && l.name == name.Name() { if !pred(l) { a.diag("cannot %s to %s %s", errOp, l.desc, l.name) return nil } return l } } if name == nil { a.diag("%s outside %s", errOp, errCtx) } else { a.diag("%s label %s not defined", errOp, name.Name()) } return nil }
func (p *parser) declIdent(scope *ast.Scope, id *ast.Ident) { decl := scope.Declare(id.Obj) if p.checkDecl && decl != id.Obj { if decl.Kind == ast.Err { // declared object is a forward declaration - update it *decl = *id.Obj id.Obj = decl return } p.Error(id.Pos(), "'"+id.Name()+"' declared already at "+decl.Pos.String()) } }
// NewSnippet creates a text snippet from a declaration decl containing an // identifier id. Parts of the declaration not containing the identifier // may be removed for a more compact snippet. // func NewSnippet(decl ast.Decl, id *ast.Ident) (s *Snippet) { switch d := decl.(type) { case *ast.GenDecl: s = genSnippet(d, id) case *ast.FuncDecl: s = funcSnippet(d, id) } // handle failure gracefully if s == nil { s = &Snippet{ id.Pos().Line, fmt.Sprintf(`could not generate a snippet for <span class="highlight">%s</span>`, id.Name()), } } return }
func checkForBuiltinFuncs(typ *ast.Ident, c *ast.CallExpr) ast.Expr { if strings.HasPrefix(typ.Name(), "func(") { if t, ok := c.Fun.(*ast.Ident); ok { switch t.Name() { case "new": e := new(ast.StarExpr) e.X = c.Args[0] return e case "make": return c.Args[0] case "cmplx": return ast.NewIdent("complex") case "closed": return ast.NewIdent("bool") } } } return nil }
func (a *stmtCompiler) defineVar(ident *ast.Ident, t Type) *Variable { v, prev := a.block.DefineVar(ident.Name(), ident.Pos(), t) if prev != nil { // TODO(austin) It's silly that we have to capture // Pos() in a variable. pos := prev.Pos() if pos.IsValid() { a.diagAt(ident, "variable %s redeclared in this block\n\tprevious declaration at %s", ident.Name(), &pos) } else { a.diagAt(ident, "variable %s redeclared in this block", ident.Name()) } return nil } // Initialize the variable index := v.Index if v.Index >= 0 { a.push(func(v *Thread) { v.f.Vars[index] = t.Zero() }) } return v }
func makeFunDeclFromFuncLit(name *ast.Ident, f *ast.FuncLit) *ast.FuncDecl { if name.Name != "main" { numArgs := strconv.Itoa(len(f.Type.Params.List[0].Names)) name.Name = name.Name + numArgs } return &ast.FuncDecl{ Name: name, Type: f.Type, Body: f.Body, } }
func (x *Indexer) visitIdent(kind SpotKind, id *ast.Ident) { if id != nil { lists, found := x.words[id.Name()] if !found { lists = new(IndexResult) x.words[id.Name()] = lists } if kind == Use || x.decl == nil { // not a declaration or no snippet required info := makeSpotInfo(kind, id.Pos().Line, false) lists.Others.Push(Spot{x.file, info}) } else { // a declaration with snippet index := x.addSnippet(NewSnippet(x.decl, id)) info := makeSpotInfo(kind, index, true) lists.Decls.Push(Spot{x.file, info}) } x.nspots++ } }
func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token, declTypeExpr ast.Expr) { nerr := a.numError() // Compile right side first so we have the types when // compiling the left side and so we don't see definitions // made on the left side. rs := make([]*expr, len(rhs)) for i, re := range rhs { rs[i] = a.compileExpr(a.block, false, re) } errOp := "assignment" if tok == token.DEFINE || tok == token.VAR { errOp = "declaration" } ac, ok := a.checkAssign(a.pos, rs, errOp, "value") ac.allowMapForms(len(lhs)) // If this is a definition and the LHS is too big, we won't be // able to produce the usual error message because we can't // begin to infer the types of the LHS. if (tok == token.DEFINE || tok == token.VAR) && len(lhs) > len(ac.rmt.Elems) { a.diag("not enough values for definition") } // Compile left type if there is one var declType Type if declTypeExpr != nil { declType = a.compileType(a.block, declTypeExpr) } // Compile left side ls := make([]*expr, len(lhs)) nDefs := 0 for i, le := range lhs { // If this is a definition, get the identifier and its type var ident *ast.Ident var lt Type switch tok { case token.DEFINE: // Check that it's an identifier ident, ok = le.(*ast.Ident) if !ok { a.diagAt(le, "left side of := must be a name") // Suppress new defitions errors nDefs++ continue } // Is this simply an assignment? if _, ok := a.block.defs[ident.Name()]; ok { ident = nil break } nDefs++ case token.VAR: ident = le.(*ast.Ident) } // If it's a definition, get or infer its type. if ident != nil { // Compute the identifier's type from the RHS // type. We use the computed MultiType so we // don't have to worry about unpacking. switch { case declTypeExpr != nil: // We have a declaration type, use it. // If declType is nil, we gave an // error when we compiled it. lt = declType case i >= len(ac.rmt.Elems): // Define a placeholder. We already // gave the "not enough" error above. lt = nil case ac.rmt.Elems[i] == nil: // We gave the error when we compiled // the RHS. lt = nil case ac.rmt.Elems[i].isIdeal(): // If the type is absent and the // corresponding expression is a // constant expression of ideal // integer or ideal float type, the // type of the declared variable is // int or float respectively. switch { case ac.rmt.Elems[i].isInteger(): lt = IntType case ac.rmt.Elems[i].isFloat(): lt = FloatType default: log.Crashf("unexpected ideal type %v", rs[i].t) } default: lt = ac.rmt.Elems[i] } } // If it's a definition, define the identifier if ident != nil { if a.defineVar(ident, lt) == nil { continue } } // Compile LHS ls[i] = a.compileExpr(a.block, false, le) if ls[i] == nil { continue } if ls[i].evalMapValue != nil { // Map indexes are not generally addressable, // but they are assignable. // // TODO(austin) Now that the expression // compiler uses semantic values, this might // be easier to implement as a function call. sub := ls[i] ls[i] = ls[i].newExpr(sub.t, sub.desc) ls[i].evalMapValue = sub.evalMapValue mvf := sub.evalMapValue et := sub.t ls[i].evalAddr = func(t *Thread) Value { m, k := mvf(t) e := m.Elem(t, k) if e == nil { e = et.Zero() m.SetElem(t, k, e) } return e } } else if ls[i].evalAddr == nil { ls[i].diag("cannot assign to %s", ls[i].desc) continue } } // A short variable declaration may redeclare variables // provided they were originally declared in the same block // with the same type, and at least one of the variables is // new. if tok == token.DEFINE && nDefs == 0 { a.diag("at least one new variable must be declared") return } // If there have been errors, our arrays are full of nil's so // get out of here now. if nerr != a.numError() { return } // Check for 'a[x] = r, ok' if len(ls) == 1 && len(rs) == 2 && ls[0].evalMapValue != nil { a.diag("a[x] = r, ok form not implemented") return } // Create assigner var lt Type n := len(lhs) if n == 1 { lt = ls[0].t } else { lts := make([]Type, len(ls)) for i, l := range ls { if l != nil { lts[i] = l.t } } lt = NewMultiType(lts) } bc := a.enterChild() defer bc.exit() assign := ac.compile(bc.block, lt) if assign == nil { return } // Compile if n == 1 { // Don't need temporaries and can avoid []Value. lf := ls[0].evalAddr a.push(func(t *Thread) { assign(lf(t), t) }) } else if tok == token.VAR || (tok == token.DEFINE && nDefs == n) { // Don't need temporaries lfs := make([]func(*Thread) Value, n) for i, l := range ls { lfs[i] = l.evalAddr } a.push(func(t *Thread) { dest := make([]Value, n) for i, lf := range lfs { dest[i] = lf(t) } assign(multiV(dest), t) }) } else { // Need temporaries lmt := lt.(*MultiType) lfs := make([]func(*Thread) Value, n) for i, l := range ls { lfs[i] = l.evalAddr } a.push(func(t *Thread) { temp := lmt.Zero().(multiV) assign(temp, t) // Copy to destination for i := 0; i < n; i++ { // TODO(austin) Need to evaluate LHS // before RHS lfs[i](t).Assign(t, temp[i]) } }) } }
func OmitFunctionCalls(node ast.Node, f *ast.File, writeMutation func()) { if ce, ok := node.(*ast.CallExpr); ok { var ident *ast.Ident if se, ok := ce.Fun.(*ast.SelectorExpr); ok { ident = se.Sel } else if ident, ok = ce.Fun.(*ast.Ident); ok { } if ident != nil && ident.Obj != nil { if ident.Obj.Decl != nil { if fun_decl, ok := ident.Obj.Decl.(*ast.FuncDecl); ok { original_func_name := ident.Name fmt.Println(ident.Name) fake_func_name := original_func_name + "FakeMugoFunction" ident.Name = fake_func_name fake_func_ident := ast.NewIdent(fake_func_name) var numReturnValues uint var returnTypes []ast.Expr if fun_decl.Type.Results.NumFields() > 0 { for _, field := range fun_decl.Type.Results.List { if len(field.Names) == 0 { numReturnValues++ returnTypes = append(returnTypes, field.Type) } else { for _, _ = range field.Names { numReturnValues++ returnTypes = append(returnTypes, field.Type) } } } } // Anropa originalmetoden i fakemetoden och returnera alla utom ett som ersätts med default value (?) var stmt_list []ast.Stmt var returnVariables []string for i, rt := range returnTypes { var returnVariable string returnVariable = fmt.Sprintf("rv%d", i+1) ident := ast.NewIdent(returnVariable) if se, ok := rt.(*ast.StarExpr); ok { // Make it a non-star expression rt = se.X // Return the address of the variable returnVariable = fmt.Sprintf("&rv%d", i+1) } returnVariables = append(returnVariables, returnVariable) vs := ast.ValueSpec{Names: []*ast.Ident{ident}, Type: rt} gd := ast.GenDecl{Tok: token.VAR, Specs: []ast.Spec{&vs}} ds := ast.DeclStmt{Decl: &gd} stmt_list = append(stmt_list, &ds) } var returnExpressions []ast.Expr for _, rv := range returnVariables { expr, _ := parser.ParseExpr(rv) returnExpressions = append(returnExpressions, expr) } rs := ast.ReturnStmt{Results: returnExpressions} stmt_list = append(stmt_list, &rs) //stmt_list = append(stmt_list, ¶ms_to_blank_asgn_stmt) // Body is a list of statements body := ast.BlockStmt{List: stmt_list} fake_func_decl := ast.FuncDecl{Name: fake_func_ident, Type: fun_decl.Type, Body: &body, Recv: fun_decl.Recv} f.Decls = append(f.Decls, &fake_func_decl) defer func() { // Return function name of call expression ident.Name = original_func_name // Remove the inserted function d := len(f.Decls) - 1 f.Decls = append(f.Decls[:d], f.Decls[d+1:]...) }() writeMutation() } } } } }