コード例 #1
0
ファイル: print_op.go プロジェクト: NickDaison/e8vm
func printOp(p io.Writer, op op) {
	switch op := op.(type) {
	case *comment:
		fmt.Fprintf(p, "// %s\n", op.s)
	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:
		var args string
		if op.args != nil {
			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))
	}
}
コード例 #2
0
ファイル: ref.go プロジェクト: 272489711/e8vm
func (r *Ref) String() string {
	if r == nil {
		return "<error>"
	}
	if r.Void {
		return "void"
	}
	if len(r.List) == 0 {
		return r.T.String()
	}
	return fmt8.Join(r.List, ",")
}
コード例 #3
0
ファイル: ref.go プロジェクト: NickDaison/e8vm
func (r *ref) String() string {
	if r == nil {
		return "void"
	}

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

	return fmt8.Join(r.TypeList(), ",")
}
コード例 #4
0
ファイル: func.go プロジェクト: 272489711/e8vm
// String returns the function signature (without the argument names).
func (t *Func) String() string {
	// TODO: this is kind of ugly, need some refactoring
	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, " ")
		fmt.Fprint(buf, t.Rets[0])
	}

	if t.IsBond {
		fmt.Fprint(buf, " (bond)")
	}

	return buf.String()
}
コード例 #5
0
ファイル: return.go プロジェクト: 272489711/e8vm
func buildReturnStmt(b *builder, stmt *ast.ReturnStmt) tast.Stmt {
	pos := stmt.Kw.Pos
	if stmt.Exprs == nil {
		if b.retType == nil || b.retNamed {
			return &tast.ReturnStmt{}
		}
		b.Errorf(pos, "expects return %s", fmt8.Join(b.retType, ","))
		return nil
	}

	if b.retType == nil {
		b.Errorf(pos, "function expects no return value")
		return nil
	}

	src := b.buildExpr(stmt.Exprs)
	if src == nil {
		return nil
	}

	srcRef := src.R()
	nret := len(b.retType)
	nsrc := srcRef.Len()
	if nret != nsrc {
		b.Errorf(pos, "expect (%s), returning (%s)",
			fmt8.Join(b.retType, ","), srcRef,
		)
		return nil
	}

	for i := 0; i < nret; i++ {
		t := b.retType[i]
		srcType := srcRef.At(i).Type()
		if !types.CanAssign(t, srcType) {
			b.Errorf(pos, "expect (%s), returning (%s)",
				fmt8.Join(b.retType, ","), srcRef,
			)
			return nil
		}
	}

	// insert implicit type casts
	if srcList, ok := tast.MakeExprList(src); ok {
		newList := tast.NewExprList()
		for i, e := range srcList.Exprs {
			t := e.Type()
			if types.IsNil(t) {
				e = tast.NewCast(e, b.retType[i])
			} else if v, ok := types.NumConst(t); ok {
				e = constCast(b, nil, v, e, b.retType[i])
				if e == nil {
					panic("bug")
				}
			}
			newList.Append(e)
		}
		src = newList
	}

	return &tast.ReturnStmt{src}
}
コード例 #6
0
ファイル: call.go プロジェクト: NickDaison/e8vm
func buildCallExpr(b *builder, expr *ast.CallExpr) tast.Expr {
	f := b.buildExpr(expr.Func)
	if f == nil {
		return nil
	}

	pos := ast.ExprPos(expr.Func)
	fref := f.R()
	if !fref.IsSingle() {
		b.Errorf(pos, "%s is not callable", fref)
		return nil
	}
	if t, ok := fref.T.(*types.Type); ok {
		return buildCast(b, expr, t.T)
	}

	builtin, ok := fref.T.(*types.BuiltInFunc)
	if ok {
		switch builtin.Name {
		case "len":
			return buildCallLen(b, expr, f)
		case "make":
			return buildCallMake(b, expr, f)
		}
		b.Errorf(pos, "builtin %s() not implemented", builtin.Name)
		return nil
	}

	funcType, ok := fref.T.(*types.Func)
	if !ok {
		b.Errorf(pos, "function call on non-callable: %s", fref)
		return nil
	}

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

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

	// type check on each argument
	for i := 0; i < nargs; i++ {
		argType := argsRef.At(i).Type()
		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,
			)
			return nil
		}
	}

	// insert casting when it is a literal expression list.
	callArgs, ok := tast.MakeExprList(args)
	if ok {
		castedArgs := tast.NewExprList()
		for i := 0; i < nargs; i++ {
			argExpr := callArgs.Exprs[i]
			argType := argExpr.Type()
			expect := funcType.Args[i].T

			// insert auto casts for consts
			if types.IsNil(argType) {
				castedArgs.Append(tast.NewCast(argExpr, expect))
			} else if _, ok := types.NumConst(argType); ok {
				castedArgs.Append(tast.NewCast(argExpr, expect))
			} else {
				castedArgs.Append(argExpr)
			}
		}
		args = castedArgs
	}

	retRef := tast.Void
	for _, t := range funcType.RetTypes {
		retRef = tast.AppendRef(retRef, tast.NewRef(t))
	}

	return &tast.CallExpr{f, args, retRef}
}