Ejemplo n.º 1
0
func getNewNames(callExpr *ast.CallExpr, funSym *st.FunctionSymbol, destScope map[st.Symbol]bool) map[st.Symbol]ast.Expr {
	newNames := make(map[st.Symbol]ast.Expr)
	bt, _ := st.GetBaseType(funSym.FunctionType)
	ftype := bt.(*st.FunctionTypeSymbol)
	//Reciever
	if ftype.Reciever != nil {
		ftype.Reciever.ForEach(func(sym st.Symbol) {
			newNames[sym] = getRecieverExpr(callExpr)
		})
	}
	//Parameters
	i := 0
	ftype.Parameters.ForEach(func(sym st.Symbol) {
		newNames[sym] = callExpr.Args[i]
		i++
	})
	//Locals
	usedNames := make(map[string]bool)
	for dest, _ := range destScope {
		usedNames[dest.Name()] = true
	}
	funSym.Locals.ForEach(func(sym st.Symbol) {
		if _, ok := usedNames[sym.Name()]; ok {
			j := 0
			for {
				nn := sym.Name() + strconv.Itoa(j)
				if _, ok := usedNames[nn]; !ok {
					newNames[sym] = ast.NewIdent(nn)
					usedNames[nn] = true
					break
				}
			}
		}
	})
	return newNames
}
Ejemplo n.º 2
0
func (pp *packageParser) openMethodsAndFields(sym st.Symbol) {

	if pp.checkIsVisited(sym) {
		return
	}
	// 	fmt.Printf("opening %s %T from %s\n", sym.Name(), sym, func(p *st.Package) string {
	// 		if p == nil {
	// 			return "nil"
	// 		}
	// 		return p.AstPackage.Name
	// 	}(sym.PackageFrom()))

	if st.IsPredeclaredIdentifier(sym.Name()) {
		return
	}

	switch t := sym.(type) {
	case *st.ArrayTypeSymbol:
		pp.openMethodsAndFields(t.ElemType)
	case *st.ChanTypeSymbol:
		pp.openMethodsAndFields(t.ValueType)
	case *st.FunctionTypeSymbol:
		if t.Parameters != nil {
			t.Parameters.ForEachNoLock(func(sym st.Symbol) {
				v := sym.(*st.VariableSymbol)
				pp.openMethodsAndFields(v.VariableType)
			})
		}
		if t.Results != nil {
			t.Results.ForEachNoLock(func(sym st.Symbol) {
				v := sym.(*st.VariableSymbol)
				pp.openMethodsAndFields(v.VariableType)
			})
		}
	case *st.InterfaceTypeSymbol:
		if t.Meths != nil {
			t.Meths.ForEachNoLock(func(sym st.Symbol) {
				if _, ok := sym.(*st.FunctionSymbol); !ok {
					//EmbeddedInterface
					pp.openMethodsAndFields(sym)

					ts := sym.(*st.InterfaceTypeSymbol)
					t.Meths.AddOpenedScope(ts.Meths)
					//Delete functionSymbol which is now useles from interface
					t.Meths.RemoveSymbol(sym.Name())
				}
			})
		}
	case *st.MapTypeSymbol:
		pp.openMethodsAndFields(t.KeyType)
		pp.openMethodsAndFields(t.ValueType)
	case *st.StructTypeSymbol:
		// 		if t.Name() == "Package" {
		// 			fmt.Printf("YEAHHH YEAHHH %p\n", t)
		// 		}
		t.Fields.ForEachNoLock(func(variable st.Symbol) {
			if _, ok := variable.(*st.VariableSymbol); !ok {

				ts := variable.(st.ITypeSymbol)
				pp.openMethodsAndFields(ts)
				//Methods
				if ts.Methods() != nil {
					t.Methods().AddOpenedScope(ts.Methods())
				}
				//Fields
				switch ttt := ts.(type) {
				case *st.StructTypeSymbol:
					t.Fields.AddOpenedScope(ttt.Fields)
				case *st.PointerTypeSymbol:
					t.Fields.AddOpenedScope(ttt.Fields)

				}
				//No longer need in type thumb, replace with var
				typeVar := st.MakeVariable(ts.Name(), t.Fields, ts)
				typeVar.Idents = ts.Identifiers()
				typeVar.Posits = ts.Positions()
				t.Fields.ReplaceSymbol(ts.Name(), typeVar) //replaces old one
			}

		})
	case *st.PointerTypeSymbol:
		//fmt.Printf("%v %T \n", t.BaseType.Name(), t.BaseType)
		pp.openMethodsAndFields(t.BaseType)
		switch str := t.BaseType.(type) {
		case *st.StructTypeSymbol:
			t.Fields = str.Fields
		case *st.PointerTypeSymbol:
			t.Fields = str.Fields
		}

		if _, cyc := st.GetBaseType(t); cyc {
			// 			fmt.Printf("%s from %s\n", t.Name(), t.PackageFrom().AstPackage.Name)
			panic("cycle, don't work with that")
		}

		if t.BaseType.Methods() != nil {
			t.Methods().AddOpenedScope(t.BaseType.Methods())
		}
		// 		if t.BaseType.Name() == "Package" {
		// 			fmt.Printf("YEAHHH YEAHHH %p %p\n", t, t.BaseType)
		// 			fmt.Println(*t.Methods().String());
		// 		}
		pp.openMethodsAndFields(t.BaseType)
	}
}
Ejemplo n.º 3
0
func (mv *methodsVisitor) Visit(node ast.Node) (w ast.Visitor) {
	w = mv
	switch f := node.(type) {
	case *ast.FuncDecl:

		fft, cyc := st.GetBaseType(mv.Parser.parseTypeSymbol(f.Type))
		if cyc {
			panic("unexpected cycle")
		}
		ft := fft.(*st.FunctionTypeSymbol)
		locals := st.NewSymbolTable(mv.Parser.Package)

		locals.AddOpenedScope(ft.Parameters)
		locals.AddOpenedScope(ft.Results)
		locals.AddOpenedScope(ft.Reciever)

		var basertype, rtype st.ITypeSymbol
		if f.Recv != nil {

			e_count := 0
			for _, field := range f.Recv.List {
				basertype = mv.Parser.parseTypeSymbol(field.Type)
				if prtype, ok := basertype.(*st.PointerTypeSymbol); ok {
					rtype = prtype.BaseType
				} else {
					rtype = basertype
				}

				if mv.Parser.Package.AstPackage.Name == "os" {
					// 					fmt.Printf("###@@@### (%s) %s\n", rtype.Name(), f.Name.Name)
				}
				if rtype.Methods() == nil {
					panic("ok, this is a test panic")
					rtype.SetMethods(st.NewSymbolTable(mv.Parser.Package))
				}

				if len(field.Names) == 0 {
					toAdd := st.MakeVariable("$unnamed receiver"+strconv.Itoa(e_count), ft.Reciever, basertype)
					ft.Reciever.AddSymbol(toAdd)
					e_count += 1
				}

				for _, name := range field.Names {

					toAdd := st.MakeVariable(name.Name, ft.Reciever, basertype)
					mv.Parser.registerIdent(toAdd, name)
					ft.Reciever.AddSymbol(toAdd)
				}
			}
		}

		toAdd := st.MakeFunction(f.Name.Name, nil, ft) // Scope is set 5 lines down
		toAdd.Locals = locals

		mv.Parser.registerIdent(toAdd, f.Name)

		if f.Recv != nil {
			rtype.AddMethod(toAdd)
			toAdd.Scope_ = rtype.Methods()
		} else {
			mv.Parser.RootSymbolTable.AddSymbol(toAdd)
			toAdd.Scope_ = mv.Parser.RootSymbolTable
		}
	}
	return
}
Ejemplo n.º 4
0
func (lv *innerScopeVisitor) parseBlockStmt(node interface{}) (w ast.Visitor) {
	if node == nil {
		return nil
	}
	w = lv
	table := st.NewSymbolTable(lv.Parser.Package)
	// 	fmt.Printf(" %p %p %p \n", lv.Parser.CurrentSymbolTable, lv.Current, lv.Method.Locals)
	table.AddOpenedScope(lv.Current)
	ww := &innerScopeVisitor{lv.Method, table, lv.Parser, nil, lv.LabelsData}

	temp := lv.Parser.CurrentSymbolTable
	lv.Parser.CurrentSymbolTable = table
	defer func() { lv.Parser.CurrentSymbolTable = temp }()

	switch inNode := node.(type) {
	case *ast.ForStmt:
		ww.parseStmt(inNode.Init)
		ww.Parser.parseExpr(inNode.Cond)
		ww.parseStmt(inNode.Post)
		ast.Walk(ww, inNode.Body)
		w = nil
	case *ast.IfStmt:
		ww.parseStmt(inNode.Init)
		ww.Parser.parseExpr(inNode.Cond)
		ww1 := &innerScopeVisitor{lv.Method, st.NewSymbolTable(lv.Parser.Package), lv.Parser, nil, lv.LabelsData}
		ww2 := &innerScopeVisitor{lv.Method, st.NewSymbolTable(lv.Parser.Package), lv.Parser, nil, lv.LabelsData}
		ww1.Current.AddOpenedScope(ww.Current)
		ww2.Current.AddOpenedScope(ww.Current)
		ast.Walk(ww1, inNode.Body)
		ast.Walk(ww2, inNode.Else)
		w = nil
	case *ast.RangeStmt:
		rangeType := ww.Parser.parseExpr(inNode.X).At(0).(st.ITypeSymbol)
		// 		fmt.Printf("range type = %s, %T\n", rangeType.Name(), rangeType)
		switch inNode.Tok {
		case token.DEFINE:
			if rangeType, _ = st.GetBaseType(rangeType); rangeType == nil {
				panic("unexpected cycle")
			}

			var kT, vT st.ITypeSymbol
			switch rT := rangeType.(type) {
			case *st.ArrayTypeSymbol:
				kT = st.PredeclaredTypes["int"]
				vT = rT.ElemType
			case *st.MapTypeSymbol:
				kT = rT.KeyType
				vT = rT.ValueType
			case *st.BasicTypeSymbol: //string
				kT = st.PredeclaredTypes["int"]
				vT = st.PredeclaredTypes["byte"]
			case *st.ChanTypeSymbol:
				kT = rT.ValueType
			case *st.UnresolvedTypeSymbol:
				panic("unresolved at range")
			}
			iK := inNode.Key.(*ast.Ident)
			if iK.Name != "_" {

				toAdd := st.MakeVariable(iK.Name, ww.Current, kT)
				ww.Parser.registerIdent(toAdd, iK)
				ww.Current.AddSymbol(toAdd)

				// 				fmt.Printf("range key added %s %T\n", toAdd.Name(), toAdd)
			}
			if inNode.Value != nil { // not channel, two range vars
				iV := inNode.Value.(*ast.Ident)
				if iV.Name != "_" {
					toAdd := st.MakeVariable(iV.Name, ww.Current, vT)
					ww.Parser.registerIdent(toAdd, iV)
					ww.Current.AddSymbol(toAdd)
					// 					fmt.Printf("range value added %s %T\n", toAdd.Name(), toAdd)
				}
			}
		case token.ASSIGN:
			ww.Parser.parseExpr(inNode.Key)
			if inNode.Value != nil {
				ww.Parser.parseExpr(inNode.Value)
			}
		}
		ast.Walk(ww, inNode.Body)
		// 		fmt.Printf("end of range\n")
		w = nil
	case *ast.SelectStmt:
		w = ww
	case *ast.SwitchStmt:
		ww.parseStmt(inNode.Init)
		ww.Parser.parseExpr(inNode.Tag)
		ast.Walk(ww, inNode.Body)
		w = nil
	case *ast.TypeSwitchStmt:
		ww.parseStmt(inNode.Init)
		switch tsT := inNode.Assign.(type) {
		case *ast.AssignStmt:
			tsVar := tsT.Lhs[0].(*ast.Ident)
			tsTypeAss := tsT.Rhs[0].(*ast.TypeAssertExpr)
			tsType := ww.Parser.parseExpr(tsTypeAss.X).At(0).(st.ITypeSymbol)

			toAdd := st.MakeVariable(tsVar.Name, ww.Current, tsType)
			toAdd.IsTypeSwitchVar = true
			ww.Parser.registerIdent(toAdd, tsVar)
			ww.Current.AddSymbol(toAdd)
		case *ast.ExprStmt:
			tsTypeAss := tsT.X.(*ast.TypeAssertExpr)
			ww.Parser.parseExpr(tsTypeAss.X)
		}
		ast.Walk(ww, inNode.Body)
		w = nil
	case *ast.CaseClause:

		if inNode.List != nil {
			s := ww.Parser.parseExpr(inNode.List[0]).At(0)
			_, isTypeSwitch := s.(st.ITypeSymbol)

			if isTypeSwitch {
				switch {
				case len(inNode.List) == 1:
					tsType := ww.Parser.parseExpr(inNode.List[0]).At(0).(st.ITypeSymbol)
					if tsVar, ok := lv.Current.FindTypeSwitchVar(); ok {

						toAdd := st.MakeVariable(tsVar.Name(), ww.Current, tsType)
						toAdd.Idents = tsVar.Idents
						toAdd.Posits = tsVar.Posits
						//No position, just register symbol
						ww.Current.AddSymbol(toAdd)
					}
				case len(inNode.List) > 1:
					for _, t := range inNode.List {
						ww.Parser.parseExpr(t)
					}
				}
			} else {
				for _, v := range inNode.List {
					ww.Parser.parseExpr(v)
				}
			}
		}

		for _, stmt := range inNode.Body {
			ast.Walk(ww, stmt)
		}
		w = nil
	case *ast.CommClause:
		ww.parseStmt(inNode.Comm)

		for _, stmt := range inNode.Body {
			ast.Walk(ww, stmt)
		}
		w = nil
	case *ast.FuncLit:
		meth := st.MakeFunction("#", ww.Current, lv.Parser.parseTypeSymbol(inNode.Type))
		meth.Locals = st.NewSymbolTable(ww.Parser.Package)
		meth.Locals.AddOpenedScope(lv.Current)
		if meth.FunctionType.(*st.FunctionTypeSymbol).Parameters != nil {
			meth.Locals.AddOpenedScope(meth.FunctionType.(*st.FunctionTypeSymbol).Parameters)
		}
		if meth.FunctionType.(*st.FunctionTypeSymbol).Results != nil {
			meth.Locals.AddOpenedScope(meth.FunctionType.(*st.FunctionTypeSymbol).Results)
		}
		w = &innerScopeVisitor{meth, meth.Locals, lv.Parser, nil, lv.LabelsData}
	}
	return w
}