Пример #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
	}
}
Пример #2
0
func buildIdent(b *builder, id *tast.Ident) *ref {
	s := id.Symbol
	switch s.Type {
	case tast.SymVar:
		return s.Obj.(*objVar).ref
	case tast.SymFunc:
		v := s.Obj.(*objFunc)
		if !v.isMethod {
			return v.ref
		}
		if b.this == nil {
			panic("this missing")
		}
		return newRecvRef(v.Type().(*types.Func), b.this, v.IR())
	case tast.SymConst:
		return s.Obj.(*objConst).ref
	case tast.SymField:
		v := s.Obj.(*types.Field)
		return buildField(b, b.this.IR(), v)
	case tast.SymImport:
		t := s.ObjType.(types.T)
		return newRef(t, nil)
	}
	panic(fmt.Errorf("unhandled token type: %s", tast.SymStr(s.Type)))
}
Пример #3
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
}
Пример #4
0
func buildConstIdent(b *builder, id *tast.Ident) *ref {
	s := id.Symbol
	switch s.Type {
	case tast.SymConst:
		return s.Obj.(*objConst).ref
	}
	panic(fmt.Errorf("not a const: %s", tast.SymStr(s.Type)))
}
Пример #5
0
func scopePopAndCheck(b *builder) {
	tab := b.scope.Pop()
	syms := tab.List()
	for _, sym := range syms {
		if !sym.Used {
			b.Errorf(
				sym.Pos,
				"unused %s %q", tast.SymStr(sym.Type), sym.Name(),
			)
		}
	}
}
Пример #6
0
func declareVar(b *builder, tok *lex8.Token, t types.T) *sym8.Symbol {
	name := tok.Lit
	s := sym8.Make(b.path, name, tast.SymVar, nil, t, tok.Pos)
	conflict := b.scope.Declare(s)
	if conflict != nil {
		b.Errorf(tok.Pos, "%q already defined as a %s",
			name, tast.SymStr(conflict.Type),
		)
		b.Errorf(conflict.Pos, "previously defined here")
		return nil
	}
	return s
}
Пример #7
0
func declareFuncSym(b *builder, f *ast.Func, t types.T) *sym8.Symbol {
	name := f.Name.Lit
	s := sym8.Make(b.path, name, tast.SymFunc, nil, t, f.Name.Pos)
	conflict := b.scope.Declare(s)
	if conflict != nil {
		b.Errorf(f.Name.Pos, "%q already defined as a %s",
			name, tast.SymStr(conflict.Type),
		)
		b.Errorf(conflict.Pos, "previously defined here")
		return nil
	}
	return s
}
Пример #8
0
func declareStruct(b *builder, s *ast.Struct) *pkgStruct {
	ret := newPkgStruct(s)
	name := ret.name.Lit
	pos := ret.name.Pos
	t := &types.Type{ret.t}
	sym := sym8.Make(b.path, name, tast.SymStruct, nil, t, pos)
	conflict := b.scope.Declare(sym)
	if conflict != nil {
		b.Errorf(pos, "%s already defined", name)
		b.Errorf(conflict.Pos, "previously defined here as a %s",
			tast.SymStr(conflict.Type),
		)
		return nil
	}

	ret.sym = sym
	return ret
}
Пример #9
0
func buildConstIdent(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.SymConst:
		ref := tast.NewRef(t)
		return &tast.Const{ref}
	case tast.SymStruct, tast.SymType, tast.SymImport:
		ref := tast.NewRef(t)
		return &tast.Ident{ident, ref, s}
	}

	b.Errorf(ident.Pos, "%s is a %s; expect a const",
		ident.Lit, tast.SymStr(s.Type),
	)
	return nil
}
Пример #10
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
}
Пример #11
0
func buildType(b *builder, expr ast.Expr) types.T {
	if expr == nil {
		panic("bug")
	}

	switch expr := expr.(type) {
	case *ast.Operand:
		ret := buildOperand(b, expr)
		if ret == nil {
			return nil
		}
		ref := ret.R()
		t, ok := ref.T.(*types.Type)
		if !ok {
			b.Errorf(ast.ExprPos(expr), "expect a type, got %s", ref.T)
			return nil
		}
		return t.T
	case *ast.StarExpr:
		t := buildType(b, expr.Expr)
		if t == nil {
			return nil
		}
		return &types.Pointer{t}
	case *ast.ArrayTypeExpr:
		return buildArrayType(b, expr)
	case *ast.ParenExpr:
		return buildType(b, expr.Expr)
	case *ast.FuncTypeExpr:
		return buildFuncType(b, nil, expr.FuncSig)
	case *ast.MemberExpr:
		op, ok := expr.Expr.(*ast.Operand)
		if !ok {
			b.Errorf(ast.ExprPos(expr.Expr), "expect a package")
			return nil
		}
		pkg := buildPkgRef(b, op.Token)
		if pkg == nil {
			return nil
		}
		name := expr.Sub.Lit
		s := pkg.Syms.Query(name)
		if s == nil {
			b.Errorf(expr.Sub.Pos, "symbol %s not found", name)
			return nil
		}
		if !sym8.IsPublic(name) && s.Pkg() != b.path {
			b.Errorf(expr.Sub.Pos, "symbol %s is not public", name)
			return nil
		}

		if s.Type != tast.SymStruct {
			b.Errorf(expr.Sub.Pos, "symbol %s is a %s, not a struct",
				name, tast.SymStr(s.Type),
			)
			return nil
		}

		return s.ObjType.(*types.Type).T
	}

	b.Errorf(ast.ExprPos(expr), "expect a type")
	return nil
}