Example #1
0
func buildCallExpr(b *builder, expr *ast.CallExpr) *ref {
	f := b.buildExpr(expr.Func)
	if f == nil {
		return nil
	}

	pos := ast.ExprPos(expr.Func)

	if !f.IsSingle() {
		b.Errorf(pos, "expression list is not callable")
		return nil
	}

	funcType, ok := f.Type().(*types.Func) // the func sig in the builder
	if !ok {
		// not a function
		b.Errorf(pos, "function call on non-callable")
		return nil
	}

	args := buildExprList(b, expr.Args)
	if args == nil {
		return nil
	}

	if args.Len() != len(funcType.Args) {
		b.Errorf(ast.ExprPos(expr), "argument expects (%s), got (%s)",
			fmt8.Join(funcType.Args, ","), fmt8.Join(args.typ, ","),
		)
		return nil
	}

	// type check on parameters
	for i, argType := range args.typ {
		expect := funcType.Args[i].T
		if !types.CanAssign(expect, argType) {
			pos := ast.ExprPos(expr.Args.Exprs[i])
			b.Errorf(pos, "argument %d expects %s, got %s",
				i+1, expect, argType,
			)
		}
	}

	ret := new(ref)
	ret.typ = funcType.RetTypes
	for _, t := range funcType.RetTypes {
		ret.ir = append(ret.ir, b.f.NewTemp(t.Size(), types.IsByte(t)))
	}

	// call the func in IR
	b.b.Call(ret.ir, f.IR(), funcType.Sig, args.ir...)

	return ret
}
Example #2
0
File: ref.go Project: yingmsky/e8vm
func (r *ref) String() string {
	if r == nil {
		return "void"
	}

	if len(r.typ) == 0 {
		return "<nil>"
	}

	return fmt8.Join(r.typ, ",")
}
Example #3
0
func printVarDecl(p *fmt8.Printer, d *VarDecl) {
	ss := make([]string, len(d.Idents.Idents))
	for i, id := range d.Idents.Idents {
		ss[i] = id.Lit
	}

	fmt.Fprint(p, fmt8.Join(ss, ","))
	if d.Type != nil {
		fmt.Fprint(p, " ")
		printExpr(p, d.Type)
	}

	if d.Eq != nil {
		fmt.Fprint(p, " = ")
		printExpr(p, d.Exprs)
	}
}
Example #4
0
// String returns the function signature (without the argument names).
func (t *Func) String() string {
	// TODO: this is kind of ugly, need some refactor
	buf := new(bytes.Buffer)
	fmt.Fprintf(buf, "func (%s) ", fmt8.Join(t.Args, ","))
	if len(t.Rets) > 1 {
		fmt.Fprintf(buf, "(")
		for i, ret := range t.Rets {
			if i > 0 {
				fmt.Fprint(buf, ",")
			}
			fmt.Fprint(buf, ret)
		}
		fmt.Fprint(buf, ")")
	} else if len(t.Rets) == 1 {
		fmt.Fprint(buf, t.Rets[0])
	}

	return buf.String()
}
Example #5
0
func printOp(p *fmt8.Printer, op op) {
	switch op := op.(type) {
	case *arithOp:
		if op.a == nil {
			if op.op == "" {
				fmt.Fprintf(p, "%s = %s\n", op.dest, op.b)
			} else if op.op == "0" {
				fmt.Fprintf(p, "%s = 0\n", op.dest)
			} else {
				fmt.Fprintf(p, "%s = %s %s\n", op.dest, op.op, op.b)
			}
		} else {
			fmt.Fprintf(p, "%s = %s %s %s\n",
				op.dest, op.a, op.op, op.b,
			)
		}
	case *callOp:
		args := fmt8.Join(op.args, ",")
		fmt.Fprintf(p, "%s = %s(%s)\n", op.dest, op.f, args)
	default:
		panic(fmt.Errorf("invalid or unknown IR op: %T", op))
	}
}