Beispiel #1
0
func buildMember(b *builder, m *tast.MemberExpr) *ref {
	obj := b.buildExpr(m.Expr)
	if !obj.IsSingle() {
		panic("not single")
	}

	t := obj.Type()
	if pkg, ok := t.(*types.Pkg); ok {
		return buildPkgSym(b, m, pkg)
	}

	pt := types.PointerOf(t)
	var tstruct *types.Struct
	if pt != nil {
		tstruct = pt.(*types.Struct)
	} else {
		tstruct = t.(*types.Struct)
	}

	addr := b.newPtr()
	if pt != nil {
		b.b.Assign(addr, obj.IR())
		if obj != b.this {
			nilPointerPanic(b, addr)
		}
	} else {
		b.b.Arith(addr, nil, "&", obj.IR())
	}

	sym := m.Symbol
	if sym.Type == tast.SymField {
		return buildField(b, addr, sym.Obj.(*types.Field))
	} else if sym.Type == tast.SymFunc {
		recv := newRef(types.NewPointer(tstruct), addr)
		method := sym.Obj.(*objFunc)
		ft := method.Type().(*types.Func)
		return newRecvRef(ft, recv, method.IR())
	}

	panic("bug")
}
Beispiel #2
0
func buildCallMake(b *builder, expr *ast.CallExpr, f tast.Expr) tast.Expr {
	args := buildExprList(b, expr.Args)
	if args == nil {
		return nil
	}

	n := args.R().Len()
	if n == 0 {
		b.Errorf(expr.Lparen.Pos, "make() takes at least one argument")
		return nil
	}

	argsList, ok := tast.MakeExprList(args)
	if !ok {
		b.Errorf(expr.Lparen.Pos, "make() only takes a literal list")
		return nil
	}

	arg0 := argsList.Exprs[0]
	t, ok := arg0.R().T.(*types.Type)
	if !ok {
		b.Errorf(expr.Lparen.Pos, "make() takes a type as the 1st argument")
		return nil
	}
	switch st := t.T.(type) {
	case *types.Slice:
		if n != 3 {
			b.Errorf(expr.Lparen.Pos, "make() slice takes 3 arguments")
			return nil
		}

		size := argsList.Exprs[1]
		pos := ast.ExprPos(expr.Args.Exprs[1])
		size = checkArrayIndex(b, size, pos)
		if size == nil {
			return nil
		}

		start := argsList.Exprs[2]
		startType := start.R().T
		startPos := ast.ExprPos(expr.Args.Exprs[2])
		if v, ok := types.NumConst(startType); ok {
			start = constCastUint(b, startPos, v, start)
			if start == nil {
				return nil
			}
		} else if !types.IsBasic(startType, types.Uint) {
			pt := types.PointerOf(startType)
			if pt == nil || !types.SameType(pt, st.T) {
				b.Errorf(startPos,
					"make() takes an uint or a typed pointer as the 3rd arg",
				)
				return nil
			}
		}

		callArgs := tast.NewExprList()
		callArgs.Append(arg0)
		callArgs.Append(size)
		callArgs.Append(start)

		r := tast.NewRef(st)
		return &tast.CallExpr{f, callArgs, r}
	}

	b.Errorf(expr.Lparen.Pos, "cannot make() type %s", t.T)
	return nil
}
Beispiel #3
0
func buildMember(b *builder, m *ast.MemberExpr) tast.Expr {
	obj := b.buildExpr(m.Expr)
	if obj == nil {
		return nil
	}

	ref := obj.R()
	if !ref.IsSingle() {
		b.Errorf(m.Dot.Pos, "%s does not have any member", ref)
		return nil
	}

	t := ref.T
	if pkg, ok := t.(*types.Pkg); ok {
		r, sym := buildPkgSym(b, m, pkg)
		if r == nil {
			return nil
		}
		// TODO: this can be further optimized
		return &tast.MemberExpr{obj, m.Sub, r, sym}
	}

	pt := types.PointerOf(t)
	var tstruct *types.Struct
	var ok bool
	if pt != nil {
		if tstruct, ok = pt.(*types.Struct); !ok {
			b.Errorf(m.Dot.Pos, "*%s is not a pointer of struct", t)
			return nil
		}
	} else {
		if tstruct, ok = t.(*types.Struct); !ok {
			b.Errorf(m.Dot.Pos, "%s is not a struct", t)
			return nil
		}
	}

	symTable := tstruct.Syms
	name := m.Sub.Lit
	sym := symTable.Query(name)
	if sym == nil {
		b.Errorf(m.Sub.Pos, "struct %s has no member named %s",
			tstruct, name,
		)
		return nil
	} else if !sym8.IsPublic(name) && sym.Pkg() != b.path {
		b.Errorf(m.Sub.Pos, "symbol %s is not public", name)
		return nil
	}

	b.refSym(sym, m.Sub.Pos)

	if sym.Type == tast.SymField {
		t := sym.ObjType.(types.T)
		r := tast.NewAddressableRef(t)
		return &tast.MemberExpr{obj, m.Sub, r, sym}
	} else if sym.Type == tast.SymFunc {
		ft := sym.ObjType.(*types.Func)
		r := tast.NewRef(ft.MethodFunc)
		r.Recv = ref
		return &tast.MemberExpr{obj, m.Sub, r, sym}
	}

	b.Errorf(m.Sub.Pos, "invalid sym type: %s", tast.SymStr(sym.Type))
	return nil
}