Example #1
0
func (fr *frame) callBuiltin(typ types.Type, builtin *ssa.Builtin, args []ssa.Value) []*govalue {
	switch builtin.Name() {
	case "print", "println":
		llargs := make([]*govalue, len(args))
		for i, arg := range args {
			llargs[i] = fr.value(arg)
		}
		fr.printValues(builtin.Name() == "println", llargs...)
		return nil

	case "panic":
		fr.callPanic(fr.value(args[0]), false)
		return nil

	case "recover":
		return []*govalue{fr.callRecover(false)}

	case "append":
		return []*govalue{fr.callAppend(fr.value(args[0]), fr.value(args[1]))}

	case "close":
		fr.chanClose(fr.value(args[0]))
		return nil

	case "cap":
		return []*govalue{fr.callCap(fr.value(args[0]))}

	case "len":
		return []*govalue{fr.callLen(fr.value(args[0]))}

	case "copy":
		return []*govalue{fr.callCopy(fr.value(args[0]), fr.value(args[1]))}

	case "delete":
		fr.mapDelete(fr.value(args[0]), fr.value(args[1]))
		return nil

	case "real":
		return []*govalue{fr.extractRealValue(fr.value(args[0]))}

	case "imag":
		return []*govalue{fr.extractImagValue(fr.value(args[0]))}

	case "complex":
		r := fr.llvmvalue(args[0])
		i := fr.llvmvalue(args[1])
		cmplx := llvm.Undef(fr.llvmtypes.ToLLVM(typ))
		cmplx = fr.builder.CreateInsertValue(cmplx, r, 0, "")
		cmplx = fr.builder.CreateInsertValue(cmplx, i, 1, "")
		return []*govalue{newValue(cmplx, typ)}

	case "ssa:wrapnilchk":
		ptr := fr.value(args[0])
		fr.nilCheck(args[0], ptr.value)
		return []*govalue{ptr}

	default:
		panic("unimplemented: " + builtin.Name())
	}
}
Example #2
0
// callBuiltin interprets a call to builtin fn with arguments args,
// returning its result.
func callBuiltin(caller *frame, callpos token.Pos, fn *ssa.Builtin, args []value) value {
	switch fn.Name() {
	case "append":
		if len(args) == 1 {
			return args[0]
		}
		if s, ok := args[1].(string); ok {
			// append([]byte, ...string) []byte
			arg0 := args[0].([]value)
			for i := 0; i < len(s); i++ {
				arg0 = append(arg0, s[i])
			}
			return arg0
		}
		// append([]T, ...[]T) []T
		return append(args[0].([]value), args[1].([]value)...)

	case "copy": // copy([]T, []T) int or copy([]byte, string) int
		src := args[1]
		if _, ok := src.(string); ok {
			params := fn.Type().(*types.Signature).Params()
			src = conv(params.At(0).Type(), params.At(1).Type(), src)
		}
		return copy(args[0].([]value), src.([]value))

	case "close": // close(chan T)
		close(args[0].(chan value))
		return nil

	case "delete": // delete(map[K]value, K)
		switch m := args[0].(type) {
		case map[value]value:
			delete(m, args[1])
		case *hashmap:
			m.delete(args[1].(hashable))
		default:
			panic(fmt.Sprintf("illegal map type: %T", m))
		}
		return nil

	case "print", "println": // print(any, ...)
		ln := fn.Name() == "println"
		var buf bytes.Buffer
		for i, arg := range args {
			if i > 0 && ln {
				buf.WriteRune(' ')
			}
			buf.WriteString(toString(arg))
		}
		if ln {
			buf.WriteRune('\n')
		}
		write(1, buf.Bytes())
		return nil

	case "len":
		switch x := args[0].(type) {
		case string:
			return len(x)
		case array:
			return len(x)
		case *value:
			return len((*x).(array))
		case []value:
			return len(x)
		case map[value]value:
			return len(x)
		case *hashmap:
			return x.len()
		case chan value:
			return len(x)
		default:
			panic(fmt.Sprintf("len: illegal operand: %T", x))
		}

	case "cap":
		switch x := args[0].(type) {
		case array:
			return cap(x)
		case *value:
			return cap((*x).(array))
		case []value:
			return cap(x)
		case chan value:
			return cap(x)
		default:
			panic(fmt.Sprintf("cap: illegal operand: %T", x))
		}

	case "real":
		switch c := args[0].(type) {
		case complex64:
			return real(c)
		case complex128:
			return real(c)
		default:
			panic(fmt.Sprintf("real: illegal operand: %T", c))
		}

	case "imag":
		switch c := args[0].(type) {
		case complex64:
			return imag(c)
		case complex128:
			return imag(c)
		default:
			panic(fmt.Sprintf("imag: illegal operand: %T", c))
		}

	case "complex":
		switch f := args[0].(type) {
		case float32:
			return complex(f, args[1].(float32))
		case float64:
			return complex(f, args[1].(float64))
		default:
			panic(fmt.Sprintf("complex: illegal operand: %T", f))
		}

	case "panic":
		// ssa.Panic handles most cases; this is only for "go
		// panic" or "defer panic".
		panic(targetPanic{args[0]})

	case "recover":
		return doRecover(caller)

	case "ssa:wrapnilchk":
		recv := args[0]
		if recv.(*value) == nil {
			recvType := args[1]
			methodName := args[2]
			panic(fmt.Sprintf("value method (%s).%s called using nil *%s pointer",
				recvType, methodName, recvType))
		}
		return recv
	}

	panic("unknown built-in: " + fn.Name())
}