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 } }
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 }
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} }
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) }
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, } }
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 }