Beispiel #1
0
func (pp *packageParser) tParseInterfaceType(t *ast.InterfaceType) (result *st.InterfaceTypeSymbol) {
	result = st.MakeInterfaceType(st.NO_NAME, pp.CurrentSymbolTable)
	if len(t.Methods.List) > 0 {
		for _, method := range t.Methods.List {
			if len(method.Names) == 0 { //Embeded interface
				ft := pp.parseTypeSymbol(method.Type)
				result.AddMethod(ft)
			}
			for _, name := range method.Names {
				ft := pp.parseTypeSymbol(method.Type).(*st.FunctionTypeSymbol)

				toAdd := st.MakeFunction(name.Name, result.Methods(), ft)
				toAdd.IsInterfaceMethod = true

				pp.registerIdent(toAdd, name)

				result.AddMethod(toAdd)
			}
		}
	}
	return
}
Beispiel #2
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
}
Beispiel #3
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
}