// TODO(mdempsky): Split expr into addr, for lvalues.
const (
exprConst codeExpr = iota
- exprType // type expression
exprLocal // local variable
exprGlobal // global variable or function
exprCompLit
exprBinaryOp
exprCall
exprConvert
+ exprNew
+ exprMake
)
type codeAssign int
// TODO(mdempsky): Handle builtins directly in exprCall, like method calls?
return typecheck.Callee(r.obj())
- case exprType:
- return r.exprType(false)
-
case exprConst:
pos := r.pos()
typ := r.typ()
return r.funcLit()
case exprSelector:
- x := r.expr()
+ var x ir.Node
+ if r.Bool() { // MethodExpr
+ x = r.exprType(false)
+
+ // Method expression with derived receiver type.
+ if x.Op() == ir.ODYNAMICTYPE {
+ // TODO(mdempsky): Handle with runtime dictionary lookup.
+ n := ir.TypeNode(x.Type())
+ n.SetTypecheck(1)
+ x = n
+ }
+ } else { // FieldVal, MethodVal
+ x = r.expr()
+ }
pos := r.pos()
_, sym := r.selector()
- // Method expression with derived receiver type.
- if x.Op() == ir.ODYNAMICTYPE {
- // TODO(mdempsky): Handle with runtime dictionary lookup.
- n := ir.TypeNode(x.Type())
- n.SetTypecheck(1)
- x = n
- }
-
n := typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)).(*ir.SelectorExpr)
if n.Op() == ir.OMETHVALUE {
wrapper := methodValueWrapper{
dots := r.Bool()
return typecheck.Call(pos, fun, args, dots)
+ case exprMake:
+ pos := r.pos()
+ typ := r.exprType(false)
+ extra := r.exprs()
+ return typecheck.Expr(ir.NewCallExpr(pos, ir.OMAKE, nil, append([]ir.Node{typ}, extra...)))
+
+ case exprNew:
+ pos := r.pos()
+ typ := r.exprType(false)
+ return typecheck.Expr(ir.NewUnaryExpr(pos, ir.ONEW, typ))
+
case exprConvert:
typ := r.typ()
pos := r.pos()
}
// typExpr writes the type represented by the given expression.
+//
+// TODO(mdempsky): Document how this differs from exprType.
func (w *writer) typExpr(expr syntax.Expr) {
tv, ok := w.p.info.Types[expr]
assert(ok)
}
if tv.IsType() {
- w.Code(exprType)
- w.exprType(nil, expr, false)
- return
+ w.p.fatalf(expr, "unexpected type expression %v", syntax.String(expr))
}
if tv.Value != nil {
assert(ok)
w.Code(exprSelector)
- w.expr(expr.X)
+ if w.Bool(sel.Kind() == types2.MethodExpr) {
+ w.exprType(nil, expr.X, false)
+ } else {
+ w.expr(expr.X)
+ }
w.pos(expr)
w.selector(sel.Obj())
break
}
+ if name, ok := unparen(expr.Fun).(*syntax.Name); ok && tv.IsBuiltin() {
+ switch name.Value {
+ case "make":
+ assert(len(expr.ArgList) >= 1)
+ assert(!expr.HasDots)
+
+ w.Code(exprMake)
+ w.pos(expr)
+ w.exprType(nil, expr.ArgList[0], false)
+ w.exprs(expr.ArgList[1:])
+ return
+
+ case "new":
+ assert(len(expr.ArgList) == 1)
+ assert(!expr.HasDots)
+
+ w.Code(exprNew)
+ w.pos(expr)
+ w.exprType(nil, expr.ArgList[0], false)
+ return
+ }
+ }
+
writeFunExpr := func() {
if selector, ok := unparen(expr.Fun).(*syntax.SelectorExpr); ok {
if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal {
}
func (w *writer) exprs(exprs []syntax.Expr) {
- if len(exprs) == 0 {
- assert(exprs == nil)
- }
-
w.Sync(pkgbits.SyncExprs)
w.Len(len(exprs))
for _, expr := range exprs {