Beispiel #1
0
func buildIdent(b *builder, ident *lex8.Token) tast.Expr {
	s := b.scope.Query(ident.Lit)
	if s == nil {
		b.Errorf(ident.Pos, "undefined identifier %s", ident.Lit)
		return nil
	}

	b.refSym(s, ident.Pos)

	t := s.ObjType.(types.T)
	switch s.Type {
	case tast.SymVar, tast.SymField:
		ref := tast.NewAddressableRef(t)
		return &tast.Ident{ident, ref, s}
	case tast.SymConst, tast.SymStruct, tast.SymType, tast.SymImport:
		ref := tast.NewRef(t)
		return &tast.Ident{ident, ref, s}
	case tast.SymFunc:
		if t, ok := t.(*types.Func); ok {
			if t.MethodFunc == nil {
				return &tast.Ident{ident, tast.NewRef(t), s}
			}
			if b.this == nil {
				panic("this missing")
			}
			ref := &tast.Ref{T: t.MethodFunc, Recv: b.this}
			return &tast.Ident{ident, ref, s}
		}
		return &tast.Ident{ident, tast.NewRef(t), s}
	default:
		b.Errorf(ident.Pos, "todo: token type: %s", tast.SymStr(s.Type))
		return nil
	}
}
Beispiel #2
0
func buildPkgSym(
	b *builder, m *ast.MemberExpr, pkg *types.Pkg,
) (*tast.Ref, *sym8.Symbol) {
	sym := findPackageSym(b, m.Sub, pkg)
	if sym == nil {
		return nil, nil
	}

	if pkg.Lang == "asm8" {
		switch sym.Type {
		case asm8.SymVar:
			return tast.NewRef(types.Uint), sym
		case asm8.SymFunc:
			return tast.NewRef(types.VoidFunc), sym
		}

		b.Errorf(m.Sub.Pos, "invalid symbol %s in %s: %s",
			m.Sub.Lit, pkg, asm8.SymStr(sym.Type),
		)
		return nil, nil
	}
	t := sym.ObjType.(types.T)
	switch sym.Type {
	case tast.SymConst, tast.SymStruct, tast.SymFunc:
		return tast.NewRef(t), sym
	case tast.SymVar:
		return tast.NewAddressableRef(t), sym
	}

	b.Errorf(m.Sub.Pos, "bug: invalid symbol %s in %s: %s",
		m.Sub.Lit, pkg, tast.SymStr(sym.Type),
	)
	return nil, nil
}
Beispiel #3
0
func buildStarExpr(b *builder, expr *ast.StarExpr) tast.Expr {
	opPos := expr.Star.Pos

	addr := b.buildExpr(expr.Expr)
	if addr == nil {
		return nil
	}

	addrRef := addr.R()
	if !addrRef.IsSingle() {
		b.Errorf(opPos, "* on %s", addrRef)
		return nil
	}
	if t, ok := addrRef.T.(*types.Type); ok {
		return tast.NewType(&types.Pointer{t.T})
	}

	t, ok := addrRef.T.(*types.Pointer)
	if !ok {
		b.Errorf(opPos, "* on non-pointer")
		return nil
	}

	r := tast.NewAddressableRef(t.T)
	return &tast.StarExpr{addr, r}
}
Beispiel #4
0
func buildMethod(b *builder, f *pkgFunc) *tast.Func {
	this := f.recv.pt
	b.thisType = this
	if f.f.Recv != nil { // go-like, explicit receiver
		b.this = tast.NewAddressableRef(this)
	} else { // inlined
		b.this = tast.NewRef(this)
		b.scope.PushTable(f.recv.t.Syms)
		defer b.scope.Pop()
	}

	return buildFunc(b, f)
}
Beispiel #5
0
func buildArrayGet(
	b *builder, expr *ast.IndexExpr, array tast.Expr,
) tast.Expr {
	t := array.R().T
	et := elementType(t)
	if et == nil {
		b.Errorf(expr.Lbrack.Pos, "index on neither array nor slice")
		return nil
	}

	index := buildArrayIndex(b, expr.Index, expr.Lbrack.Pos)
	if index == nil {
		return nil
	}

	ref := tast.NewAddressableRef(et)
	return &tast.IndexExpr{
		Array: array,
		Index: index,
		Ref:   ref,
	}
}
Beispiel #6
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
}