예제 #1
0
//ast.Visitor.Visit(). Looks for ast.TypeSpec nodes of ast.Tree to register new types
func (tv *typesVisitor) Visit(node ast.Node) (w ast.Visitor) {
	if tsp, ok := node.(*ast.TypeSpec); ok {
		ts := tv.Parser.parseTypeSymbol(tsp.Type)

		if ts.Name() == st.NO_NAME {
			//No such symbol in CurrentSymbolTable
			ts.SetName(tsp.Name.Name)
		} else {
			//There is an equal type symbol with different name => create alias
			ts = st.MakeAliasType(tsp.Name.Name, tv.Parser.CurrentSymbolTable, ts)
		}

		tv.Parser.registerIdent(ts, tsp.Name)

		tv.Parser.RootSymbolTable.AddSymbol(ts)

	}
	return tv
}
예제 #2
0
func (lv *innerScopeVisitor) parseStmt(node interface{}) (w ast.Visitor) {
	if node == nil {
		return nil
	}
	w = lv
	// 	fmt.Printf("ps %p %p %p %T ", lv.Parser.CurrentSymbolTable, lv.Current, lv.Method.Locals, node)
	// 	if id, ok := node.(*ast.Ident); ok {
	// 		fmt.Printf("%s ", id.Name)
	// 	}
	// 	println()
	temp := lv.Parser.CurrentSymbolTable
	lv.Parser.CurrentSymbolTable = lv.Current
	defer func() { lv.Parser.CurrentSymbolTable = temp }()
	switch s := node.(type) {

	case *ast.GenDecl:
		var IotaType st.ITypeSymbol = nil
		if len(s.Specs) > 0 {
			if vs, ok := s.Specs[0].(*ast.ValueSpec); ok {
				switch {
				case vs.Type != nil:
					ts := lv.Parser.parseTypeSymbol(vs.Type)
					if _, ok := ts.(*st.UnresolvedTypeSymbol); (ts == nil) || ok {
						panic("unresolved type at locals scope: " + ts.Name())
					}
					IotaType = ts
				case vs.Values != nil && len(vs.Values) > 0:
					ts := lv.Parser.parseExpr(vs.Values[0]).At(0).(st.ITypeSymbol)
					IotaType = ts
				default:
					panic("decl without either type or value????")
				}
			}
		}
		w = &innerScopeVisitor{lv.Method, lv.Current, lv.Parser, IotaType, lv.LabelsData}

	case *ast.ValueSpec: //Specify a new variable

		ts := lv.Parser.parseTypeSymbol(s.Type)

		if ts == nil {
			ts = lv.IotaType
		}
		valuesTypes := lv.getValuesTypesValSpec(s)
		for i, n := range s.Names {
			curTs := ts
			if ts == nil {
				curTs = valuesTypes.At(i).(st.ITypeSymbol)
			}
			toAdd := st.MakeVariable(n.Name, lv.Current, curTs)
			lv.Parser.registerIdent(toAdd, n)
			lv.Parser.CurrentSymbolTable.AddSymbol(toAdd)
		}

	case *ast.AssignStmt:
		valuesTypes := lv.getValuesTypesAss(s)
		switch s.Tok {
		case token.DEFINE: //Specify a new variable

			for i, nn := range s.Lhs {
				n := nn.(*ast.Ident)
				if n.Name != "_" {

					toAdd := st.MakeVariable(n.Name, lv.Current, valuesTypes.At(i).(st.ITypeSymbol))
					lv.Parser.registerIdent(toAdd, n)
					lv.Current.AddSymbol(toAdd)
					// 					fmt.Printf("DEFINED %s\n", toAdd.Name())
				}
			}
		case token.ASSIGN: //Pos
			for _, nn := range s.Lhs {
				// 				fmt.Printf("<!>")
				lv.Parser.parseExpr(nn)
			}
			w = nil
		}
	case *ast.TypeSpec: //Specify a new type
		ts := lv.Parser.parseTypeSymbol(s.Type)

		switch ts.(type) {
		case *st.PointerTypeSymbol, *st.ArrayTypeSymbol, *st.StructTypeSymbol, *st.InterfaceTypeSymbol, *st.MapTypeSymbol, *st.ChanTypeSymbol, *st.FunctionTypeSymbol:

			if ts.Name() == st.NO_NAME {
				//No such symbol in CurrentSymbolTable
				ts.SetName(s.Name.Name)
			} else {
				//There is an equal type symbol with different name => create alias
				ts = st.MakeAliasType(s.Name.Name, lv.Current, ts)
			}
			lv.Parser.registerIdent(ts, s.Name)
			lv.Current.AddSymbol(ts)
		default:
			panic("no type symbol returned")
		}
	case *ast.ExprStmt:
		lv.Parser.parseExpr(s.X)
	case *ast.DeferStmt:
		lv.Parser.parseExpr(s.Call)
	case *ast.GoStmt:
		lv.Parser.parseExpr(s.Call)
	case *ast.IncDecStmt:
		lv.Parser.parseExpr(s.X)
	//labels beg
	case *ast.LabeledStmt:
		l := st.MakeLabel(s.Label.Name, lv.Current)
		for id, _ := range lv.LabelsData {
			if id.Name == s.Label.Name {
				lv.Parser.registerIdent(l, id)
			}
		}
		for id, _ := range l.Idents {
			lv.LabelsData[id] = false, false
		}
		lv.Parser.registerIdent(l, s.Label)
		lv.Current.AddSymbol(l)
		ast.Walk(lv, s.Stmt)
		w = nil //prevent from usual ident registration
	case *ast.BranchStmt:
		if s.Label != nil {
			if l, ok := lv.Current.LookUpLabel(s.Label.Name); ok {
				lv.Parser.registerIdent(l, s.Label)
			} else {
				lv.LabelsData[s.Label] = true
			}
		}
		w = nil //prevent from usual ident registration
		//labels end
	case *ast.ReturnStmt:
		if s.Results != nil { //mb not needed
			for _, exp := range s.Results {
				lv.Parser.parseExpr(exp)
			}
		}
	case *ast.SendStmt:
		lv.Parser.parseExpr(s.Chan)
		lv.Parser.parseExpr(s.Value)
	case *ast.SwitchStmt, *ast.IfStmt, *ast.ForStmt, *ast.RangeStmt, *ast.FuncLit, *ast.SelectStmt, *ast.TypeSwitchStmt, *ast.CaseClause, *ast.CommClause:

		w = lv.parseBlockStmt(node)
	}
	return
}