Best Syzkaller code snippet using compiler.checkUnused
noder.go
Source:noder.go
...195 imported_unsafe = false196 p.setlineno(p.file.PkgName)197 mkpackage(p.file.PkgName.Value)198 if pragma, ok := p.file.Pragma.(*Pragma); ok {199 p.checkUnused(pragma)200 }201 xtop = append(xtop, p.decls(p.file.DeclList)...)202 for _, n := range p.linknames {203 if !imported_unsafe {204 p.yyerrorpos(n.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")205 continue206 }207 s := lookup(n.local)208 if n.remote != "" {209 s.Linkname = n.remote210 } else {211 // Use the default object symbol name if the212 // user didn't provide one.213 if myimportpath == "" {214 p.yyerrorpos(n.pos, "//go:linkname requires linkname argument or -p compiler flag")215 } else {216 s.Linkname = objabi.PathToPrefix(myimportpath) + "." + n.local217 }218 }219 }220 // The linker expects an ABI0 wrapper for all cgo-exported221 // functions.222 for _, prag := range p.pragcgobuf {223 switch prag[0] {224 case "cgo_export_static", "cgo_export_dynamic":225 if symabiRefs == nil {226 symabiRefs = make(map[string]obj.ABI)227 }228 symabiRefs[prag[1]] = obj.ABI0229 }230 }231 pragcgobuf = append(pragcgobuf, p.pragcgobuf...)232 lineno = src.NoXPos233 clearImports()234}235func (p *noder) decls(decls []syntax.Decl) (l []*Node) {236 var cs constState237 for _, decl := range decls {238 p.setlineno(decl)239 switch decl := decl.(type) {240 case *syntax.ImportDecl:241 p.importDecl(decl)242 case *syntax.VarDecl:243 l = append(l, p.varDecl(decl)...)244 case *syntax.ConstDecl:245 l = append(l, p.constDecl(decl, &cs)...)246 case *syntax.TypeDecl:247 l = append(l, p.typeDecl(decl))248 case *syntax.FuncDecl:249 l = append(l, p.funcDecl(decl))250 default:251 panic("unhandled Decl")252 }253 }254 return255}256func (p *noder) importDecl(imp *syntax.ImportDecl) {257 if imp.Path.Bad {258 return // avoid follow-on errors if there was a syntax error259 }260 if pragma, ok := imp.Pragma.(*Pragma); ok {261 p.checkUnused(pragma)262 }263 val := p.basicLit(imp.Path)264 ipkg := importfile(&val)265 if ipkg == nil {266 if nerrors == 0 {267 Fatalf("phase error in import")268 }269 return270 }271 ipkg.Direct = true272 var my *types.Sym273 if imp.LocalPkgName != nil {274 my = p.name(imp.LocalPkgName)275 } else {276 my = lookup(ipkg.Name)277 }278 pack := p.nod(imp, OPACK, nil, nil)279 pack.Sym = my280 pack.Name.Pkg = ipkg281 switch my.Name {282 case ".":283 importdot(ipkg, pack)284 return285 case "init":286 yyerrorl(pack.Pos, "cannot import package as init - init must be a func")287 return288 case "_":289 return290 }291 if my.Def != nil {292 redeclare(pack.Pos, my, "as imported package name")293 }294 my.Def = asTypesNode(pack)295 my.Lastlineno = pack.Pos296 my.Block = 1 // at top level297}298func (p *noder) varDecl(decl *syntax.VarDecl) []*Node {299 names := p.declNames(decl.NameList)300 typ := p.typeExprOrNil(decl.Type)301 var exprs []*Node302 if decl.Values != nil {303 exprs = p.exprList(decl.Values)304 }305 if pragma, ok := decl.Pragma.(*Pragma); ok {306 p.checkUnused(pragma)307 }308 p.setlineno(decl)309 return variter(names, typ, exprs)310}311// constState tracks state between constant specifiers within a312// declaration group. This state is kept separate from noder so nested313// constant declarations are handled correctly (e.g., issue 15550).314type constState struct {315 group *syntax.Group316 typ *Node317 values []*Node318 iota int64319}320func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []*Node {321 if decl.Group == nil || decl.Group != cs.group {322 *cs = constState{323 group: decl.Group,324 }325 }326 if pragma, ok := decl.Pragma.(*Pragma); ok {327 p.checkUnused(pragma)328 }329 names := p.declNames(decl.NameList)330 typ := p.typeExprOrNil(decl.Type)331 var values []*Node332 if decl.Values != nil {333 values = p.exprList(decl.Values)334 cs.typ, cs.values = typ, values335 } else {336 if typ != nil {337 yyerror("const declaration cannot have type without expression")338 }339 typ, values = cs.typ, cs.values340 }341 nn := make([]*Node, 0, len(names))342 for i, n := range names {343 if i >= len(values) {344 yyerror("missing value in const declaration")345 break346 }347 v := values[i]348 if decl.Values == nil {349 v = treecopy(v, n.Pos)350 }351 n.Op = OLITERAL352 declare(n, dclcontext)353 n.Name.Param.Ntype = typ354 n.Name.Defn = v355 n.SetIota(cs.iota)356 nn = append(nn, p.nod(decl, ODCLCONST, n, nil))357 }358 if len(values) > len(names) {359 yyerror("extra expression in const declaration")360 }361 cs.iota++362 return nn363}364func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {365 n := p.declName(decl.Name)366 n.Op = OTYPE367 declare(n, dclcontext)368 // decl.Type may be nil but in that case we got a syntax error during parsing369 typ := p.typeExprOrNil(decl.Type)370 param := n.Name.Param371 param.Ntype = typ372 param.Alias = decl.Alias373 if pragma, ok := decl.Pragma.(*Pragma); ok {374 if !decl.Alias {375 param.Pragma = pragma.Flag & TypePragmas376 pragma.Flag &^= TypePragmas377 }378 p.checkUnused(pragma)379 }380 nod := p.nod(decl, ODCLTYPE, n, nil)381 if param.Alias && !langSupported(1, 9, localpkg) {382 yyerrorl(nod.Pos, "type aliases only supported as of -lang=go1.9")383 }384 return nod385}386func (p *noder) declNames(names []*syntax.Name) []*Node {387 nodes := make([]*Node, 0, len(names))388 for _, name := range names {389 nodes = append(nodes, p.declName(name))390 }391 return nodes392}393func (p *noder) declName(name *syntax.Name) *Node {394 n := dclname(p.name(name))395 n.Pos = p.pos(name)396 return n397}398func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node {399 name := p.name(fun.Name)400 t := p.signature(fun.Recv, fun.Type)401 f := p.nod(fun, ODCLFUNC, nil, nil)402 if fun.Recv == nil {403 if name.Name == "init" {404 name = renameinit()405 if t.List.Len() > 0 || t.Rlist.Len() > 0 {406 yyerrorl(f.Pos, "func init must have no arguments and no return values")407 }408 }409 if localpkg.Name == "main" && name.Name == "main" {410 if t.List.Len() > 0 || t.Rlist.Len() > 0 {411 yyerrorl(f.Pos, "func main must have no arguments and no return values")412 }413 }414 } else {415 f.Func.Shortname = name416 name = nblank.Sym // filled in by typecheckfunc417 }418 f.Func.Nname = newfuncnamel(p.pos(fun.Name), name)419 f.Func.Nname.Name.Defn = f420 f.Func.Nname.Name.Param.Ntype = t421 if pragma, ok := fun.Pragma.(*Pragma); ok {422 f.Func.Pragma = pragma.Flag & FuncPragmas423 if pragma.Flag&Systemstack != 0 && pragma.Flag&Nosplit != 0 {424 yyerrorl(f.Pos, "go:nosplit and go:systemstack cannot be combined")425 }426 pragma.Flag &^= FuncPragmas427 p.checkUnused(pragma)428 }429 if fun.Recv == nil {430 declare(f.Func.Nname, PFUNC)431 }432 p.funcBody(f, fun.Body)433 if fun.Body != nil {434 if f.Func.Pragma&Noescape != 0 {435 yyerrorl(f.Pos, "can only use //go:noescape with external func implementations")436 }437 } else {438 if pure_go || strings.HasPrefix(f.funcname(), "init.") {439 // Linknamed functions are allowed to have no body. Hopefully440 // the linkname target has a body. See issue 23311.441 isLinknamed := false442 for _, n := range p.linknames {443 if f.funcname() == n.local {444 isLinknamed = true445 break446 }447 }448 if !isLinknamed {449 yyerrorl(f.Pos, "missing function body")450 }451 }452 }453 return f454}455func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *Node {456 n := p.nod(typ, OTFUNC, nil, nil)457 if recv != nil {458 n.Left = p.param(recv, false, false)459 }460 n.List.Set(p.params(typ.ParamList, true))461 n.Rlist.Set(p.params(typ.ResultList, false))462 return n463}464func (p *noder) params(params []*syntax.Field, dddOk bool) []*Node {465 nodes := make([]*Node, 0, len(params))466 for i, param := range params {467 p.setlineno(param)468 nodes = append(nodes, p.param(param, dddOk, i+1 == len(params)))469 }470 return nodes471}472func (p *noder) param(param *syntax.Field, dddOk, final bool) *Node {473 var name *types.Sym474 if param.Name != nil {475 name = p.name(param.Name)476 }477 typ := p.typeExpr(param.Type)478 n := p.nodSym(param, ODCLFIELD, typ, name)479 // rewrite ...T parameter480 if typ.Op == ODDD {481 if !dddOk {482 // We mark these as syntax errors to get automatic elimination483 // of multiple such errors per line (see yyerrorl in subr.go).484 yyerror("syntax error: cannot use ... in receiver or result parameter list")485 } else if !final {486 if param.Name == nil {487 yyerror("syntax error: cannot use ... with non-final parameter")488 } else {489 p.yyerrorpos(param.Name.Pos(), "syntax error: cannot use ... with non-final parameter %s", param.Name.Value)490 }491 }492 typ.Op = OTARRAY493 typ.Right = typ.Left494 typ.Left = nil495 n.SetIsDDD(true)496 if n.Left != nil {497 n.Left.SetIsDDD(true)498 }499 }500 return n501}502func (p *noder) exprList(expr syntax.Expr) []*Node {503 if list, ok := expr.(*syntax.ListExpr); ok {504 return p.exprs(list.ElemList)505 }506 return []*Node{p.expr(expr)}507}508func (p *noder) exprs(exprs []syntax.Expr) []*Node {509 nodes := make([]*Node, 0, len(exprs))510 for _, expr := range exprs {511 nodes = append(nodes, p.expr(expr))512 }513 return nodes514}515func (p *noder) expr(expr syntax.Expr) *Node {516 p.setlineno(expr)517 switch expr := expr.(type) {518 case nil, *syntax.BadExpr:519 return nil520 case *syntax.Name:521 return p.mkname(expr)522 case *syntax.BasicLit:523 n := nodlit(p.basicLit(expr))524 n.SetDiag(expr.Bad) // avoid follow-on errors if there was a syntax error525 return n526 case *syntax.CompositeLit:527 n := p.nod(expr, OCOMPLIT, nil, nil)528 if expr.Type != nil {529 n.Right = p.expr(expr.Type)530 }531 l := p.exprs(expr.ElemList)532 for i, e := range l {533 l[i] = p.wrapname(expr.ElemList[i], e)534 }535 n.List.Set(l)536 lineno = p.makeXPos(expr.Rbrace)537 return n538 case *syntax.KeyValueExpr:539 // use position of expr.Key rather than of expr (which has position of ':')540 return p.nod(expr.Key, OKEY, p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value)))541 case *syntax.FuncLit:542 return p.funcLit(expr)543 case *syntax.ParenExpr:544 return p.nod(expr, OPAREN, p.expr(expr.X), nil)545 case *syntax.SelectorExpr:546 // parser.new_dotname547 obj := p.expr(expr.X)548 if obj.Op == OPACK {549 obj.Name.SetUsed(true)550 return oldname(restrictlookup(expr.Sel.Value, obj.Name.Pkg))551 }552 n := nodSym(OXDOT, obj, p.name(expr.Sel))553 n.Pos = p.pos(expr) // lineno may have been changed by p.expr(expr.X)554 return n555 case *syntax.IndexExpr:556 return p.nod(expr, OINDEX, p.expr(expr.X), p.expr(expr.Index))557 case *syntax.SliceExpr:558 op := OSLICE559 if expr.Full {560 op = OSLICE3561 }562 n := p.nod(expr, op, p.expr(expr.X), nil)563 var index [3]*Node564 for i, x := range &expr.Index {565 if x != nil {566 index[i] = p.expr(x)567 }568 }569 n.SetSliceBounds(index[0], index[1], index[2])570 return n571 case *syntax.AssertExpr:572 return p.nod(expr, ODOTTYPE, p.expr(expr.X), p.typeExpr(expr.Type))573 case *syntax.Operation:574 if expr.Op == syntax.Add && expr.Y != nil {575 return p.sum(expr)576 }577 x := p.expr(expr.X)578 if expr.Y == nil {579 return p.nod(expr, p.unOp(expr.Op), x, nil)580 }581 return p.nod(expr, p.binOp(expr.Op), x, p.expr(expr.Y))582 case *syntax.CallExpr:583 n := p.nod(expr, OCALL, p.expr(expr.Fun), nil)584 n.List.Set(p.exprs(expr.ArgList))585 n.SetIsDDD(expr.HasDots)586 return n587 case *syntax.ArrayType:588 var len *Node589 if expr.Len != nil {590 len = p.expr(expr.Len)591 } else {592 len = p.nod(expr, ODDD, nil, nil)593 }594 return p.nod(expr, OTARRAY, len, p.typeExpr(expr.Elem))595 case *syntax.SliceType:596 return p.nod(expr, OTARRAY, nil, p.typeExpr(expr.Elem))597 case *syntax.DotsType:598 return p.nod(expr, ODDD, p.typeExpr(expr.Elem), nil)599 case *syntax.StructType:600 return p.structType(expr)601 case *syntax.InterfaceType:602 return p.interfaceType(expr)603 case *syntax.FuncType:604 return p.signature(nil, expr)605 case *syntax.MapType:606 return p.nod(expr, OTMAP, p.typeExpr(expr.Key), p.typeExpr(expr.Value))607 case *syntax.ChanType:608 n := p.nod(expr, OTCHAN, p.typeExpr(expr.Elem), nil)609 n.SetTChanDir(p.chanDir(expr.Dir))610 return n611 case *syntax.TypeSwitchGuard:612 n := p.nod(expr, OTYPESW, nil, p.expr(expr.X))613 if expr.Lhs != nil {614 n.Left = p.declName(expr.Lhs)615 if n.Left.isBlank() {616 yyerror("invalid variable name %v in type switch", n.Left)617 }618 }619 return n620 }621 panic("unhandled Expr")622}623// sum efficiently handles very large summation expressions (such as624// in issue #16394). In particular, it avoids left recursion and625// collapses string literals.626func (p *noder) sum(x syntax.Expr) *Node {627 // While we need to handle long sums with asymptotic628 // efficiency, the vast majority of sums are very small: ~95%629 // have only 2 or 3 operands, and ~99% of string literals are630 // never concatenated.631 adds := make([]*syntax.Operation, 0, 2)632 for {633 add, ok := x.(*syntax.Operation)634 if !ok || add.Op != syntax.Add || add.Y == nil {635 break636 }637 adds = append(adds, add)638 x = add.X639 }640 // nstr is the current rightmost string literal in the641 // summation (if any), and chunks holds its accumulated642 // substrings.643 //644 // Consider the expression x + "a" + "b" + "c" + y. When we645 // reach the string literal "a", we assign nstr to point to646 // its corresponding Node and initialize chunks to {"a"}.647 // Visiting the subsequent string literals "b" and "c", we648 // simply append their values to chunks. Finally, when we649 // reach the non-constant operand y, we'll join chunks to form650 // "abc" and reassign the "a" string literal's value.651 //652 // N.B., we need to be careful about named string constants653 // (indicated by Sym != nil) because 1) we can't modify their654 // value, as doing so would affect other uses of the string655 // constant, and 2) they may have types, which we need to656 // handle correctly. For now, we avoid these problems by657 // treating named string constants the same as non-constant658 // operands.659 var nstr *Node660 chunks := make([]string, 0, 1)661 n := p.expr(x)662 if Isconst(n, CTSTR) && n.Sym == nil {663 nstr = n664 chunks = append(chunks, strlit(nstr))665 }666 for i := len(adds) - 1; i >= 0; i-- {667 add := adds[i]668 r := p.expr(add.Y)669 if Isconst(r, CTSTR) && r.Sym == nil {670 if nstr != nil {671 // Collapse r into nstr instead of adding to n.672 chunks = append(chunks, strlit(r))673 continue674 }675 nstr = r676 chunks = append(chunks, strlit(nstr))677 } else {678 if len(chunks) > 1 {679 nstr.SetVal(Val{U: strings.Join(chunks, "")})680 }681 nstr = nil682 chunks = chunks[:0]683 }684 n = p.nod(add, OADD, n, r)685 }686 if len(chunks) > 1 {687 nstr.SetVal(Val{U: strings.Join(chunks, "")})688 }689 return n690}691func (p *noder) typeExpr(typ syntax.Expr) *Node {692 // TODO(mdempsky): Be stricter? typecheck should handle errors anyway.693 return p.expr(typ)694}695func (p *noder) typeExprOrNil(typ syntax.Expr) *Node {696 if typ != nil {697 return p.expr(typ)698 }699 return nil700}701func (p *noder) chanDir(dir syntax.ChanDir) types.ChanDir {702 switch dir {703 case 0:704 return types.Cboth705 case syntax.SendOnly:706 return types.Csend707 case syntax.RecvOnly:708 return types.Crecv709 }710 panic("unhandled ChanDir")711}712func (p *noder) structType(expr *syntax.StructType) *Node {713 l := make([]*Node, 0, len(expr.FieldList))714 for i, field := range expr.FieldList {715 p.setlineno(field)716 var n *Node717 if field.Name == nil {718 n = p.embedded(field.Type)719 } else {720 n = p.nodSym(field, ODCLFIELD, p.typeExpr(field.Type), p.name(field.Name))721 }722 if i < len(expr.TagList) && expr.TagList[i] != nil {723 n.SetVal(p.basicLit(expr.TagList[i]))724 }725 l = append(l, n)726 }727 p.setlineno(expr)728 n := p.nod(expr, OTSTRUCT, nil, nil)729 n.List.Set(l)730 return n731}732func (p *noder) interfaceType(expr *syntax.InterfaceType) *Node {733 l := make([]*Node, 0, len(expr.MethodList))734 for _, method := range expr.MethodList {735 p.setlineno(method)736 var n *Node737 if method.Name == nil {738 n = p.nodSym(method, ODCLFIELD, oldname(p.packname(method.Type)), nil)739 } else {740 mname := p.name(method.Name)741 sig := p.typeExpr(method.Type)742 sig.Left = fakeRecv()743 n = p.nodSym(method, ODCLFIELD, sig, mname)744 ifacedcl(n)745 }746 l = append(l, n)747 }748 n := p.nod(expr, OTINTER, nil, nil)749 n.List.Set(l)750 return n751}752func (p *noder) packname(expr syntax.Expr) *types.Sym {753 switch expr := expr.(type) {754 case *syntax.Name:755 name := p.name(expr)756 if n := oldname(name); n.Name != nil && n.Name.Pack != nil {757 n.Name.Pack.Name.SetUsed(true)758 }759 return name760 case *syntax.SelectorExpr:761 name := p.name(expr.X.(*syntax.Name))762 def := asNode(name.Def)763 if def == nil {764 yyerror("undefined: %v", name)765 return name766 }767 var pkg *types.Pkg768 if def.Op != OPACK {769 yyerror("%v is not a package", name)770 pkg = localpkg771 } else {772 def.Name.SetUsed(true)773 pkg = def.Name.Pkg774 }775 return restrictlookup(expr.Sel.Value, pkg)776 }777 panic(fmt.Sprintf("unexpected packname: %#v", expr))778}779func (p *noder) embedded(typ syntax.Expr) *Node {780 op, isStar := typ.(*syntax.Operation)781 if isStar {782 if op.Op != syntax.Mul || op.Y != nil {783 panic("unexpected Operation")784 }785 typ = op.X786 }787 sym := p.packname(typ)788 n := p.nodSym(typ, ODCLFIELD, oldname(sym), lookup(sym.Name))789 n.SetEmbedded(true)790 if isStar {791 n.Left = p.nod(op, ODEREF, n.Left, nil)792 }793 return n794}795func (p *noder) stmts(stmts []syntax.Stmt) []*Node {796 return p.stmtsFall(stmts, false)797}798func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []*Node {799 var nodes []*Node800 for i, stmt := range stmts {801 s := p.stmtFall(stmt, fallOK && i+1 == len(stmts))802 if s == nil {803 } else if s.Op == OBLOCK && s.Ninit.Len() == 0 {804 nodes = append(nodes, s.List.Slice()...)805 } else {806 nodes = append(nodes, s)807 }808 }809 return nodes810}811func (p *noder) stmt(stmt syntax.Stmt) *Node {812 return p.stmtFall(stmt, false)813}814func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) *Node {815 p.setlineno(stmt)816 switch stmt := stmt.(type) {817 case *syntax.EmptyStmt:818 return nil819 case *syntax.LabeledStmt:820 return p.labeledStmt(stmt, fallOK)821 case *syntax.BlockStmt:822 l := p.blockStmt(stmt)823 if len(l) == 0 {824 // TODO(mdempsky): Line number?825 return nod(OEMPTY, nil, nil)826 }827 return liststmt(l)828 case *syntax.ExprStmt:829 return p.wrapname(stmt, p.expr(stmt.X))830 case *syntax.SendStmt:831 return p.nod(stmt, OSEND, p.expr(stmt.Chan), p.expr(stmt.Value))832 case *syntax.DeclStmt:833 return liststmt(p.decls(stmt.DeclList))834 case *syntax.AssignStmt:835 if stmt.Op != 0 && stmt.Op != syntax.Def {836 n := p.nod(stmt, OASOP, p.expr(stmt.Lhs), p.expr(stmt.Rhs))837 n.SetImplicit(stmt.Rhs == syntax.ImplicitOne)838 n.SetSubOp(p.binOp(stmt.Op))839 return n840 }841 n := p.nod(stmt, OAS, nil, nil) // assume common case842 rhs := p.exprList(stmt.Rhs)843 lhs := p.assignList(stmt.Lhs, n, stmt.Op == syntax.Def)844 if len(lhs) == 1 && len(rhs) == 1 {845 // common case846 n.Left = lhs[0]847 n.Right = rhs[0]848 } else {849 n.Op = OAS2850 n.List.Set(lhs)851 n.Rlist.Set(rhs)852 }853 return n854 case *syntax.BranchStmt:855 var op Op856 switch stmt.Tok {857 case syntax.Break:858 op = OBREAK859 case syntax.Continue:860 op = OCONTINUE861 case syntax.Fallthrough:862 if !fallOK {863 yyerror("fallthrough statement out of place")864 }865 op = OFALL866 case syntax.Goto:867 op = OGOTO868 default:869 panic("unhandled BranchStmt")870 }871 n := p.nod(stmt, op, nil, nil)872 if stmt.Label != nil {873 n.Sym = p.name(stmt.Label)874 }875 return n876 case *syntax.CallStmt:877 var op Op878 switch stmt.Tok {879 case syntax.Defer:880 op = ODEFER881 case syntax.Go:882 op = OGO883 default:884 panic("unhandled CallStmt")885 }886 return p.nod(stmt, op, p.expr(stmt.Call), nil)887 case *syntax.ReturnStmt:888 var results []*Node889 if stmt.Results != nil {890 results = p.exprList(stmt.Results)891 }892 n := p.nod(stmt, ORETURN, nil, nil)893 n.List.Set(results)894 if n.List.Len() == 0 && Curfn != nil {895 for _, ln := range Curfn.Func.Dcl {896 if ln.Class() == PPARAM {897 continue898 }899 if ln.Class() != PPARAMOUT {900 break901 }902 if asNode(ln.Sym.Def) != ln {903 yyerror("%s is shadowed during return", ln.Sym.Name)904 }905 }906 }907 return n908 case *syntax.IfStmt:909 return p.ifStmt(stmt)910 case *syntax.ForStmt:911 return p.forStmt(stmt)912 case *syntax.SwitchStmt:913 return p.switchStmt(stmt)914 case *syntax.SelectStmt:915 return p.selectStmt(stmt)916 }917 panic("unhandled Stmt")918}919func (p *noder) assignList(expr syntax.Expr, defn *Node, colas bool) []*Node {920 if !colas {921 return p.exprList(expr)922 }923 defn.SetColas(true)924 var exprs []syntax.Expr925 if list, ok := expr.(*syntax.ListExpr); ok {926 exprs = list.ElemList927 } else {928 exprs = []syntax.Expr{expr}929 }930 res := make([]*Node, len(exprs))931 seen := make(map[*types.Sym]bool, len(exprs))932 newOrErr := false933 for i, expr := range exprs {934 p.setlineno(expr)935 res[i] = nblank936 name, ok := expr.(*syntax.Name)937 if !ok {938 p.yyerrorpos(expr.Pos(), "non-name %v on left side of :=", p.expr(expr))939 newOrErr = true940 continue941 }942 sym := p.name(name)943 if sym.IsBlank() {944 continue945 }946 if seen[sym] {947 p.yyerrorpos(expr.Pos(), "%v repeated on left side of :=", sym)948 newOrErr = true949 continue950 }951 seen[sym] = true952 if sym.Block == types.Block {953 res[i] = oldname(sym)954 continue955 }956 newOrErr = true957 n := newname(sym)958 declare(n, dclcontext)959 n.Name.Defn = defn960 defn.Ninit.Append(nod(ODCL, n, nil))961 res[i] = n962 }963 if !newOrErr {964 yyerrorl(defn.Pos, "no new variables on left side of :=")965 }966 return res967}968func (p *noder) blockStmt(stmt *syntax.BlockStmt) []*Node {969 p.openScope(stmt.Pos())970 nodes := p.stmts(stmt.List)971 p.closeScope(stmt.Rbrace)972 return nodes973}974func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node {975 p.openScope(stmt.Pos())976 n := p.nod(stmt, OIF, nil, nil)977 if stmt.Init != nil {978 n.Ninit.Set1(p.stmt(stmt.Init))979 }980 if stmt.Cond != nil {981 n.Left = p.expr(stmt.Cond)982 }983 n.Nbody.Set(p.blockStmt(stmt.Then))984 if stmt.Else != nil {985 e := p.stmt(stmt.Else)986 if e.Op == OBLOCK && e.Ninit.Len() == 0 {987 n.Rlist.Set(e.List.Slice())988 } else {989 n.Rlist.Set1(e)990 }991 }992 p.closeAnotherScope()993 return n994}995func (p *noder) forStmt(stmt *syntax.ForStmt) *Node {996 p.openScope(stmt.Pos())997 var n *Node998 if r, ok := stmt.Init.(*syntax.RangeClause); ok {999 if stmt.Cond != nil || stmt.Post != nil {1000 panic("unexpected RangeClause")1001 }1002 n = p.nod(r, ORANGE, nil, p.expr(r.X))1003 if r.Lhs != nil {1004 n.List.Set(p.assignList(r.Lhs, n, r.Def))1005 }1006 } else {1007 n = p.nod(stmt, OFOR, nil, nil)1008 if stmt.Init != nil {1009 n.Ninit.Set1(p.stmt(stmt.Init))1010 }1011 if stmt.Cond != nil {1012 n.Left = p.expr(stmt.Cond)1013 }1014 if stmt.Post != nil {1015 n.Right = p.stmt(stmt.Post)1016 }1017 }1018 n.Nbody.Set(p.blockStmt(stmt.Body))1019 p.closeAnotherScope()1020 return n1021}1022func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node {1023 p.openScope(stmt.Pos())1024 n := p.nod(stmt, OSWITCH, nil, nil)1025 if stmt.Init != nil {1026 n.Ninit.Set1(p.stmt(stmt.Init))1027 }1028 if stmt.Tag != nil {1029 n.Left = p.expr(stmt.Tag)1030 }1031 tswitch := n.Left1032 if tswitch != nil && tswitch.Op != OTYPESW {1033 tswitch = nil1034 }1035 n.List.Set(p.caseClauses(stmt.Body, tswitch, stmt.Rbrace))1036 p.closeScope(stmt.Rbrace)1037 return n1038}1039func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node, rbrace syntax.Pos) []*Node {1040 nodes := make([]*Node, 0, len(clauses))1041 for i, clause := range clauses {1042 p.setlineno(clause)1043 if i > 0 {1044 p.closeScope(clause.Pos())1045 }1046 p.openScope(clause.Pos())1047 n := p.nod(clause, OCASE, nil, nil)1048 if clause.Cases != nil {1049 n.List.Set(p.exprList(clause.Cases))1050 }1051 if tswitch != nil && tswitch.Left != nil {1052 nn := newname(tswitch.Left.Sym)1053 declare(nn, dclcontext)1054 n.Rlist.Set1(nn)1055 // keep track of the instances for reporting unused1056 nn.Name.Defn = tswitch1057 }1058 // Trim trailing empty statements. We omit them from1059 // the Node AST anyway, and it's easier to identify1060 // out-of-place fallthrough statements without them.1061 body := clause.Body1062 for len(body) > 0 {1063 if _, ok := body[len(body)-1].(*syntax.EmptyStmt); !ok {1064 break1065 }1066 body = body[:len(body)-1]1067 }1068 n.Nbody.Set(p.stmtsFall(body, true))1069 if l := n.Nbody.Len(); l > 0 && n.Nbody.Index(l-1).Op == OFALL {1070 if tswitch != nil {1071 yyerror("cannot fallthrough in type switch")1072 }1073 if i+1 == len(clauses) {1074 yyerror("cannot fallthrough final case in switch")1075 }1076 }1077 nodes = append(nodes, n)1078 }1079 if len(clauses) > 0 {1080 p.closeScope(rbrace)1081 }1082 return nodes1083}1084func (p *noder) selectStmt(stmt *syntax.SelectStmt) *Node {1085 n := p.nod(stmt, OSELECT, nil, nil)1086 n.List.Set(p.commClauses(stmt.Body, stmt.Rbrace))1087 return n1088}1089func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*Node {1090 nodes := make([]*Node, 0, len(clauses))1091 for i, clause := range clauses {1092 p.setlineno(clause)1093 if i > 0 {1094 p.closeScope(clause.Pos())1095 }1096 p.openScope(clause.Pos())1097 n := p.nod(clause, OCASE, nil, nil)1098 if clause.Comm != nil {1099 n.List.Set1(p.stmt(clause.Comm))1100 }1101 n.Nbody.Set(p.stmts(clause.Body))1102 nodes = append(nodes, n)1103 }1104 if len(clauses) > 0 {1105 p.closeScope(rbrace)1106 }1107 return nodes1108}1109func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) *Node {1110 lhs := p.nodSym(label, OLABEL, nil, p.name(label.Label))1111 var ls *Node1112 if label.Stmt != nil { // TODO(mdempsky): Should always be present.1113 ls = p.stmtFall(label.Stmt, fallOK)1114 }1115 lhs.Name.Defn = ls1116 l := []*Node{lhs}1117 if ls != nil {1118 if ls.Op == OBLOCK && ls.Ninit.Len() == 0 {1119 l = append(l, ls.List.Slice()...)1120 } else {1121 l = append(l, ls)1122 }1123 }1124 return liststmt(l)1125}1126var unOps = [...]Op{1127 syntax.Recv: ORECV,1128 syntax.Mul: ODEREF,1129 syntax.And: OADDR,1130 syntax.Not: ONOT,1131 syntax.Xor: OBITNOT,1132 syntax.Add: OPLUS,1133 syntax.Sub: ONEG,1134}1135func (p *noder) unOp(op syntax.Operator) Op {1136 if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 {1137 panic("invalid Operator")1138 }1139 return unOps[op]1140}1141var binOps = [...]Op{1142 syntax.OrOr: OOROR,1143 syntax.AndAnd: OANDAND,1144 syntax.Eql: OEQ,1145 syntax.Neq: ONE,1146 syntax.Lss: OLT,1147 syntax.Leq: OLE,1148 syntax.Gtr: OGT,1149 syntax.Geq: OGE,1150 syntax.Add: OADD,1151 syntax.Sub: OSUB,1152 syntax.Or: OOR,1153 syntax.Xor: OXOR,1154 syntax.Mul: OMUL,1155 syntax.Div: ODIV,1156 syntax.Rem: OMOD,1157 syntax.And: OAND,1158 syntax.AndNot: OANDNOT,1159 syntax.Shl: OLSH,1160 syntax.Shr: ORSH,1161}1162func (p *noder) binOp(op syntax.Operator) Op {1163 if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 {1164 panic("invalid Operator")1165 }1166 return binOps[op]1167}1168// checkLangCompat reports an error if the representation of a numeric1169// literal is not compatible with the current language version.1170func checkLangCompat(lit *syntax.BasicLit) {1171 s := lit.Value1172 if len(s) <= 2 || langSupported(1, 13, localpkg) {1173 return1174 }1175 // len(s) > 21176 if strings.Contains(s, "_") {1177 yyerrorv("go1.13", "underscores in numeric literals")1178 return1179 }1180 if s[0] != '0' {1181 return1182 }1183 base := s[1]1184 if base == 'b' || base == 'B' {1185 yyerrorv("go1.13", "binary literals")1186 return1187 }1188 if base == 'o' || base == 'O' {1189 yyerrorv("go1.13", "0o/0O-style octal literals")1190 return1191 }1192 if lit.Kind != syntax.IntLit && (base == 'x' || base == 'X') {1193 yyerrorv("go1.13", "hexadecimal floating-point literals")1194 }1195}1196func (p *noder) basicLit(lit *syntax.BasicLit) Val {1197 // We don't use the errors of the conversion routines to determine1198 // if a literal string is valid because the conversion routines may1199 // accept a wider syntax than the language permits. Rely on lit.Bad1200 // instead.1201 switch s := lit.Value; lit.Kind {1202 case syntax.IntLit:1203 checkLangCompat(lit)1204 x := new(Mpint)1205 if !lit.Bad {1206 x.SetString(s)1207 }1208 return Val{U: x}1209 case syntax.FloatLit:1210 checkLangCompat(lit)1211 x := newMpflt()1212 if !lit.Bad {1213 x.SetString(s)1214 }1215 return Val{U: x}1216 case syntax.ImagLit:1217 checkLangCompat(lit)1218 x := newMpcmplx()1219 if !lit.Bad {1220 x.Imag.SetString(strings.TrimSuffix(s, "i"))1221 }1222 return Val{U: x}1223 case syntax.RuneLit:1224 x := new(Mpint)1225 x.Rune = true1226 if !lit.Bad {1227 u, _ := strconv.Unquote(s)1228 var r rune1229 if len(u) == 1 {1230 r = rune(u[0])1231 } else {1232 r, _ = utf8.DecodeRuneInString(u)1233 }1234 x.SetInt64(int64(r))1235 }1236 return Val{U: x}1237 case syntax.StringLit:1238 var x string1239 if !lit.Bad {1240 if len(s) > 0 && s[0] == '`' {1241 // strip carriage returns from raw string1242 s = strings.Replace(s, "\r", "", -1)1243 }1244 x, _ = strconv.Unquote(s)1245 }1246 return Val{U: x}1247 default:1248 panic("unhandled BasicLit kind")1249 }1250}1251func (p *noder) name(name *syntax.Name) *types.Sym {1252 return lookup(name.Value)1253}1254func (p *noder) mkname(name *syntax.Name) *Node {1255 // TODO(mdempsky): Set line number?1256 return mkname(p.name(name))1257}1258func (p *noder) newname(name *syntax.Name) *Node {1259 // TODO(mdempsky): Set line number?1260 return newname(p.name(name))1261}1262func (p *noder) wrapname(n syntax.Node, x *Node) *Node {1263 // These nodes do not carry line numbers.1264 // Introduce a wrapper node to give them the correct line.1265 switch x.Op {1266 case OTYPE, OLITERAL:1267 if x.Sym == nil {1268 break1269 }1270 fallthrough1271 case ONAME, ONONAME, OPACK:1272 x = p.nod(n, OPAREN, x, nil)1273 x.SetImplicit(true)1274 }1275 return x1276}1277func (p *noder) nod(orig syntax.Node, op Op, left, right *Node) *Node {1278 return nodl(p.pos(orig), op, left, right)1279}1280func (p *noder) nodSym(orig syntax.Node, op Op, left *Node, sym *types.Sym) *Node {1281 n := nodSym(op, left, sym)1282 n.Pos = p.pos(orig)1283 return n1284}1285func (p *noder) pos(n syntax.Node) src.XPos {1286 // TODO(gri): orig.Pos() should always be known - fix package syntax1287 xpos := lineno1288 if pos := n.Pos(); pos.IsKnown() {1289 xpos = p.makeXPos(pos)1290 }1291 return xpos1292}1293func (p *noder) setlineno(n syntax.Node) {1294 if n != nil {1295 lineno = p.pos(n)1296 }1297}1298// error is called concurrently if files are parsed concurrently.1299func (p *noder) error(err error) {1300 p.err <- err.(syntax.Error)1301}1302// pragmas that are allowed in the std lib, but don't have1303// a syntax.Pragma value (see lex.go) associated with them.1304var allowedStdPragmas = map[string]bool{1305 "go:cgo_export_static": true,1306 "go:cgo_export_dynamic": true,1307 "go:cgo_import_static": true,1308 "go:cgo_import_dynamic": true,1309 "go:cgo_ldflag": true,1310 "go:cgo_dynamic_linker": true,1311 "go:generate": true,1312}1313// *Pragma is the value stored in a syntax.Pragma during parsing.1314type Pragma struct {1315 Flag PragmaFlag // collected bits1316 Pos []PragmaPos // position of each individual flag1317}1318type PragmaPos struct {1319 Flag PragmaFlag1320 Pos syntax.Pos1321}1322func (p *noder) checkUnused(pragma *Pragma) {1323 for _, pos := range pragma.Pos {1324 if pos.Flag&pragma.Flag != 0 {1325 p.yyerrorpos(pos.Pos, "misplaced compiler directive")1326 }1327 }1328}1329func (p *noder) checkUnusedDuringParse(pragma *Pragma) {1330 for _, pos := range pragma.Pos {1331 if pos.Flag&pragma.Flag != 0 {1332 p.error(syntax.Error{Pos: pos.Pos, Msg: "misplaced compiler directive"})1333 }1334 }1335}1336// pragma is called concurrently if files are parsed concurrently.1337func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.Pragma) syntax.Pragma {1338 pragma, _ := old.(*Pragma)1339 if pragma == nil {1340 pragma = new(Pragma)1341 }1342 if text == "" {1343 // unused pragma; only called with old != nil.1344 p.checkUnusedDuringParse(pragma)1345 return nil1346 }1347 if strings.HasPrefix(text, "line ") {1348 // line directives are handled by syntax package1349 panic("unreachable")1350 }1351 if !blankLine {1352 // directive must be on line by itself1353 p.error(syntax.Error{Pos: pos, Msg: "misplaced compiler directive"})1354 return pragma1355 }1356 switch {1357 case strings.HasPrefix(text, "go:linkname "):1358 f := strings.Fields(text)...
compiler.go
Source:compiler.go
1/*---------------------------------------------------------------------------------------------2 * Copyright (c) Peter Bjorklund. All rights reserved.3 * Licensed under the MIT License. See LICENSE in the project root for license information.4 *--------------------------------------------------------------------------------------------*/5package swampcompiler6import (7 "fmt"8 "log"9 "os"10 "path"11 "path/filepath"12 deccy "github.com/swamp/compiler/src/decorated"13 "github.com/swamp/compiler/src/decorated/decshared"14 decorated "github.com/swamp/compiler/src/decorated/expression"15 dectype "github.com/swamp/compiler/src/decorated/types"16 "github.com/swamp/compiler/src/environment"17 "github.com/swamp/compiler/src/file"18 "github.com/swamp/compiler/src/generate"19 "github.com/swamp/compiler/src/generate_ir"20 "github.com/swamp/compiler/src/generate_sp"21 "github.com/swamp/compiler/src/loader"22 "github.com/swamp/compiler/src/parser"23 "github.com/swamp/compiler/src/resourceid"24 "github.com/swamp/compiler/src/solution"25 "github.com/swamp/compiler/src/verbosity"26)27func CheckUnused(world *loader.Package) decshared.DecoratedError {28 var appendedError decshared.DecoratedError29 for _, module := range world.AllModules() {30 if module.IsInternal() {31 continue32 }33 for _, def := range module.LocalDefinitions().Definitions() {34 if !def.WasReferenced() {35 warning := decorated.NewUnusedWarning(def)36 appendedError = decorated.AppendError(appendedError, warning)37 }38 }39 for _, def := range module.LocalTypes().AllInOrderTypes() {40 if !def.RealType().WasReferenced() {41 warning := decorated.NewUnusedTypeWarning(def.RealType())42 appendedError = decorated.AppendError(appendedError, warning)43 }44 }45 for _, importModule := range module.ImportedModules().AllInOrderModules() {46 if !importModule.ImportStatementInModule().WasReferenced() && importModule.ImportStatementInModule().AstImport().ModuleName().ModuleName() != "" {47 //warning := decorated.NewUnusedImportStatementWarning(importModule.ImportStatementInModule())48 //module.AddWarning(warning)49 }50 }51 }52 return appendedError53}54type Target uint855const (56 SwampOpcode Target = iota57 LlvmIr58)59func BuildMain(mainSourceFile string, absoluteOutputDirectory string, enforceStyle bool, showAssembler bool, target Target, verboseFlag verbosity.Verbosity) ([]*loader.Package, error) {60 statInfo, statErr := os.Stat(mainSourceFile)61 if statErr != nil {62 return nil, statErr63 }64 config, _, configErr := environment.LoadFromConfig()65 if configErr != nil {66 return nil, configErr67 }68 if statInfo.IsDir() {69 resourceNameLookup := resourceid.NewResourceNameLookupImpl()70 if solutionSettings, err := solution.LoadIfExists(mainSourceFile); err == nil {71 var packages []*loader.Package72 var errors decshared.DecoratedError73 var gen generate.Generator74 if target == LlvmIr {75 gen = generate_ir.NewGenerator()76 } else {77 gen = generate_sp.NewGenerator()78 }79 for _, packageSubDirectoryName := range solutionSettings.Packages {80 absoluteSubDirectory := path.Join(mainSourceFile, packageSubDirectoryName)81 compiledPackage, compileAndLinkErr := CompileAndLink(gen, resourceNameLookup, config, packageSubDirectoryName, absoluteSubDirectory, absoluteOutputDirectory, enforceStyle, verboseFlag)82 errors = decorated.AppendError(errors, compileAndLinkErr)83 if parser.IsCompileError(compileAndLinkErr) {84 return packages, errors85 }86 packages = append(packages, compiledPackage)87 }88 return packages, errors89 } else {90 return nil, fmt.Errorf("must have a solution file in this version")91 }92 }93 return nil, fmt.Errorf("must be directory in this version %v %v", mainSourceFile, absoluteOutputDirectory)94}95func BuildMainOnlyCompile(mainSourceFile string, enforceStyle bool, verboseFlag verbosity.Verbosity) ([]*loader.Package, error) {96 statInfo, statErr := os.Stat(mainSourceFile)97 if statErr != nil {98 return nil, statErr99 }100 config, _, configErr := environment.LoadFromConfig()101 if configErr != nil {102 return nil, configErr103 }104 if !statInfo.IsDir() {105 return nil, fmt.Errorf("must have a solution file in this version")106 } else {107 if solutionSettings, err := solution.LoadIfExists(mainSourceFile); err == nil {108 var packages []*loader.Package109 for _, packageSubDirectoryName := range solutionSettings.Packages {110 absoluteSubDirectory := path.Join(mainSourceFile, packageSubDirectoryName)111 compiledPackage, err := CompileMainDefaultDocumentProvider(packageSubDirectoryName, absoluteSubDirectory, config, enforceStyle, verboseFlag)112 if parser.IsCompileError(err) {113 return packages, err114 }115 packages = append(packages, compiledPackage)116 }117 return packages, nil118 }119 }120 return nil, fmt.Errorf("must be directory in this version %v", mainSourceFile)121}122func CompileMain(name string, mainSourceFile string, documentProvider loader.DocumentProvider, configuration environment.Environment, enforceStyle bool, verboseFlag verbosity.Verbosity) (*loader.Package, *decorated.Module, decshared.DecoratedError) {123 mainPrefix := mainSourceFile124 if file.IsDir(mainSourceFile) {125 } else {126 mainPrefix = path.Dir(mainSourceFile)127 }128 world := loader.NewPackage(loader.LocalFileSystemRoot(mainPrefix), name)129 worldDecorator, worldDecoratorErr := loader.NewWorldDecorator(enforceStyle, verboseFlag)130 if parser.IsCompileErr(worldDecoratorErr) {131 return nil, nil, worldDecoratorErr132 }133 var appendedError decshared.DecoratedError134 appendedError = decorated.AppendError(appendedError, worldDecoratorErr)135 /*136 for _, rootModule := range worldDecorator.ImportModules() {137 world.AddModule(rootModule.FullyQualifiedModuleName(), rootModule)138 }139 */140 mainNamespace := dectype.MakePackageRootModuleName(nil)141 rootPackage := NewPackageLoader(mainPrefix, documentProvider, mainNamespace, world, worldDecorator)142 libraryReader := loader.NewLibraryReaderAndDecorator()143 libraryModule, libErr := libraryReader.ReadLibraryModule(decorated.ModuleTypeNormal, world, rootPackage.repository, mainSourceFile, mainNamespace, documentProvider, configuration)144 if parser.IsCompileErr(libErr) {145 return nil, nil, libErr146 }147 appendedError = decorated.AppendError(appendedError, libErr)148 unusedErrors := CheckUnused(world)149 appendedError = decorated.AppendError(appendedError, unusedErrors)150 rootModule, err := deccy.CreateDefaultRootModule(true)151 if parser.IsCompileError(err) {152 return nil, nil, err153 }154 appendedError = decorated.AppendError(appendedError, err)155 for _, importedRootSubModule := range rootModule.ImportedModules().AllInOrderModules() {156 world.AddModule(importedRootSubModule.ReferencedModule().FullyQualifiedModuleName(), importedRootSubModule.ReferencedModule())157 }158 // world.AddModule(dectype.MakeArtifactFullyQualifiedModuleName(nil), rootModule)159 return world, libraryModule, appendedError160}161func CompileMainFindLibraryRoot(mainSource string, documentProvider loader.DocumentProvider, configuration environment.Environment, enforceStyle bool, verboseFlag verbosity.Verbosity) (*loader.Package, *decorated.Module, error) {162 if !file.IsDir(mainSource) {163 mainSource = filepath.Dir(mainSource)164 }165 libraryDirectory, libraryErr := loader.FindSettingsDirectory(mainSource)166 if libraryErr != nil {167 return nil, nil, fmt.Errorf("couldn't find settings directory when compiling %w", libraryErr)168 }169 return CompileMain(mainSource, libraryDirectory, documentProvider, configuration, enforceStyle, verboseFlag)170}171type CoreFunctionInfo struct {172 Name string173 ParamCount uint174}175func align(offset dectype.MemoryOffset, memoryAlign dectype.MemoryAlign) dectype.MemoryOffset {176 rest := dectype.MemoryAlign(uint32(offset) % uint32(memoryAlign))177 if rest != 0 {178 offset += dectype.MemoryOffset(memoryAlign - rest)179 }180 return offset181}182func GenerateAndLink(gen generate.Generator, resourceNameLookup resourceid.ResourceNameLookup, compiledPackage *loader.Package, outputDirectory string, packageSubDirectory string, verboseFlag verbosity.Verbosity) decshared.DecoratedError {183 for _, module := range compiledPackage.AllModules() {184 if verboseFlag >= verbosity.High {185 log.Printf(">>> has module %v\n", module.FullyQualifiedModuleName())186 }187 }188 genErr := gen.GenerateFromPackageAndWriteOutput(compiledPackage, resourceNameLookup, outputDirectory, packageSubDirectory, verboseFlag)189 if genErr != nil {190 return decorated.NewInternalError(genErr)191 }192 return nil193}194func CompileMainDefaultDocumentProvider(name string, filename string, configuration environment.Environment,195 enforceStyle bool, verboseFlag verbosity.Verbosity) (*loader.Package, decshared.DecoratedError) {196 defaultDocumentProvider := loader.NewFileSystemDocumentProvider()197 compiledPackage, _, moduleErr := CompileMain(name, filename, defaultDocumentProvider, configuration, enforceStyle, verboseFlag)198 if moduleErr != nil {199 return compiledPackage, moduleErr200 }201 return compiledPackage, nil202}203func CompileAndLink(gen generate.Generator, resourceNameLookup resourceid.ResourceNameLookup, configuration environment.Environment, name string,204 filename string, outputFilename string, enforceStyle bool, verboseFlag verbosity.Verbosity) (*loader.Package, decshared.DecoratedError) {205 var errors decshared.DecoratedError206 compiledPackage, compileErr := CompileMainDefaultDocumentProvider(name, filename, configuration, enforceStyle, verboseFlag)207 if parser.IsCompileError(compileErr) {208 return nil, compileErr209 }210 errors = decorated.AppendError(errors, compileErr)211 if compiledPackage == nil {212 panic("not possible")213 }214 linkErr := GenerateAndLink(gen, resourceNameLookup, compiledPackage, outputFilename, name, verboseFlag)215 errors = decorated.AppendError(errors, linkErr)216 return compiledPackage, errors217}...
checkUnused
Using AI Code Generation
1import (2func main() {3 import "fmt"4 func main() {5 fmt.Println("Hello, playground")6 }7 f, err := parser.ParseFile(fset, "", src, parser.ImportsOnly)8 if err != nil {9 log.Fatal(err)10 }11 for _, s := range f.Imports {12 fmt.Println(s.Path.Value)13 }14}15import (16func main() {17 import "fmt"18 func main() {19 fmt.Println("Hello, playground")20 }21 f, err := parser.ParseFile(fset, "", src, parser.ImportsOnly)22 if err != nil {23 log.Fatal(err)24 }25 for _, s := range f.Imports {26 fmt.Println(s.Path.Value)27 }28}29import (30func main() {31 import "fmt"32 func main() {33 fmt.Println("Hello, playground")34 }35 f, err := parser.ParseFile(fset, "", src, parser.ImportsOnly)36 if err != nil {37 log.Fatal(err)38 }39 for _, s := range f.Imports {40 fmt.Println(s.Path.Value)41 }42}43import (
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!