當前位置: 首頁>>代碼示例>>Golang>>正文


Golang types.Underlying函數代碼示例

本文整理匯總了Golang中github.com/axw/llgo/types.Underlying函數的典型用法代碼示例。如果您正苦於以下問題:Golang Underlying函數的具體用法?Golang Underlying怎麽用?Golang Underlying使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。


在下文中一共展示了Underlying函數的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。

示例1: Convert

func (v ConstValue) Convert(dst_typ types.Type) Value {
	// Get the underlying type, if any.
	if name, isname := dst_typ.(*types.Name); isname {
		dst_typ = types.Underlying(name)
	}

	if !types.Identical(v.typ, dst_typ) {
		// Get the Basic type.
		isBasic := false
		if name, isname := types.Underlying(dst_typ).(*types.Name); isname {
			_, isBasic = name.Underlying.(*types.Basic)
		}

		compiler := v.compiler
		if isBasic {
			return ConstValue{*v.Const.Convert(&dst_typ), compiler, dst_typ}
		} else {
			return compiler.NewLLVMValue(v.LLVMValue(), v.Type()).Convert(dst_typ)
			//panic(fmt.Errorf("unhandled conversion from %v to %v", v.typ, dst_typ))
		}
	} else {
		// TODO convert to dst type. ConstValue may need to change to allow
		// storage of types other than Basic.
	}
	return v
}
開發者ID:prattmic,項目名稱:llgo,代碼行數:26,代碼來源:value.go

示例2: UnaryOp

func (v *LLVMValue) UnaryOp(op token.Token) Value {
	b := v.compiler.builder
	switch op {
	case token.SUB:
		var value llvm.Value
		isfp := types.Identical(types.Underlying(v.typ), types.Float32) ||
			types.Identical(types.Underlying(v.typ), types.Float64)
		if isfp {
			zero := llvm.ConstNull(v.compiler.types.ToLLVM(v.Type()))
			value = b.CreateFSub(zero, v.LLVMValue(), "")
		} else {
			value = b.CreateNeg(v.LLVMValue(), "")
		}
		return v.compiler.NewLLVMValue(value, v.typ)
	case token.ADD:
		return v // No-op
	case token.AND:
		return v.pointer
	case token.NOT:
		value := b.CreateNot(v.LLVMValue(), "")
		return v.compiler.NewLLVMValue(value, v.typ)
	case token.XOR:
		lhs := v.LLVMValue()
		rhs := llvm.ConstAllOnes(lhs.Type())
		value := b.CreateXor(lhs, rhs, "")
		return v.compiler.NewLLVMValue(value, v.typ)
	default:
		panic("Unhandled operator: ") // + expr.Op)
	}
	panic("unreachable")
}
開發者ID:spate,項目名稱:llgo,代碼行數:31,代碼來源:value.go

示例3: VisitSliceExpr

func (c *compiler) VisitSliceExpr(expr *ast.SliceExpr) Value {
	// expr.X, expr.Low, expr.High
	value := c.VisitExpr(expr.X)
	var low, high llvm.Value
	if expr.Low != nil {
		low = c.VisitExpr(expr.Low).Convert(types.Int32).LLVMValue()
	} else {
		low = llvm.ConstNull(llvm.Int32Type())
	}
	if expr.High != nil {
		high = c.VisitExpr(expr.High).Convert(types.Int32).LLVMValue()
	} else {
		high = llvm.ConstAllOnes(llvm.Int32Type()) // -1
	}

	if _, ok := types.Underlying(value.Type()).(*types.Pointer); ok {
		value = value.(*LLVMValue).makePointee()
	}

	switch typ := types.Underlying(value.Type()).(type) {
	case *types.Array:
		sliceslice := c.NamedFunction("runtime.sliceslice", "func f(t uintptr, s slice, low, high int32) slice")
		i8slice := sliceslice.Type().ElementType().ReturnType()
		sliceValue := llvm.Undef(i8slice) // temporary slice
		arrayptr := value.(*LLVMValue).pointer.LLVMValue()
		arrayptr = c.builder.CreateBitCast(arrayptr, i8slice.StructElementTypes()[0], "")
		arraylen := llvm.ConstInt(llvm.Int32Type(), typ.Len, false)
		sliceValue = c.builder.CreateInsertValue(sliceValue, arrayptr, 0, "")
		sliceValue = c.builder.CreateInsertValue(sliceValue, arraylen, 1, "")
		sliceValue = c.builder.CreateInsertValue(sliceValue, arraylen, 2, "")
		sliceTyp := &types.Slice{Elt: typ.Elt}
		runtimeTyp := c.types.ToRuntime(sliceTyp)
		runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "")
		args := []llvm.Value{runtimeTyp, sliceValue, low, high}
		result := c.builder.CreateCall(sliceslice, args, "")
		llvmSliceTyp := c.types.ToLLVM(sliceTyp)
		return c.NewLLVMValue(c.coerceSlice(result, llvmSliceTyp), sliceTyp)
	case *types.Slice:
		sliceslice := c.NamedFunction("runtime.sliceslice", "func f(t uintptr, s slice, low, high int32) slice")
		i8slice := sliceslice.Type().ElementType().ReturnType()
		sliceValue := value.LLVMValue()
		sliceTyp := sliceValue.Type()
		sliceValue = c.coerceSlice(sliceValue, i8slice)
		runtimeTyp := c.types.ToRuntime(value.Type())
		runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "")
		args := []llvm.Value{runtimeTyp, sliceValue, low, high}
		result := c.builder.CreateCall(sliceslice, args, "")
		return c.NewLLVMValue(c.coerceSlice(result, sliceTyp), value.Type())
	case *types.Name: // String
		stringslice := c.NamedFunction("runtime.stringslice", "func f(a string, low, high int32) string")
		args := []llvm.Value{value.LLVMValue(), low, high}
		result := c.builder.CreateCall(stringslice, args, "")
		return c.NewLLVMValue(result, value.Type())
	default:
		panic("unimplemented")
	}
	panic("unreachable")
}
開發者ID:kelsieflynn,項目名稱:llgo,代碼行數:58,代碼來源:slice.go

示例4: VisitLen

func (c *compiler) VisitLen(expr *ast.CallExpr) Value {
	if len(expr.Args) > 1 {
		panic("Expecting only one argument to len")
	}

	value := c.VisitExpr(expr.Args[0])
	typ := value.Type()
	if name, ok := types.Underlying(typ).(*types.Name); ok {
		typ = name.Underlying
	}

	switch typ := types.Underlying(typ).(type) {
	case *types.Pointer:
		// XXX Converting to a string to be converted back to an int is
		// silly. The values need an overhaul? Perhaps have types based
		// on fundamental types, with the additional methods to make
		// them llgo.Value's.
		if a, isarray := typ.Base.(*types.Array); isarray {
			return c.NewConstValue(token.INT,
				strconv.FormatUint(a.Len, 10))
		}
		v := strconv.FormatUint(uint64(unsafe.Sizeof(uintptr(0))), 10)
		return c.NewConstValue(token.INT, v)

	case *types.Slice:
		sliceval := value.LLVMValue()
		lenval := c.builder.CreateExtractValue(sliceval, 1, "")
		return c.NewLLVMValue(lenval, types.Int32).Convert(types.Int)

	case *types.Map:
		mapval := value.LLVMValue()
		f := c.NamedFunction("runtime.maplen", "func f(m uintptr) int")
		lenval := c.builder.CreateCall(f, []llvm.Value{mapval}, "")
		return c.NewLLVMValue(lenval, types.Int)

	case *types.Array:
		v := strconv.FormatUint(typ.Len, 10)
		return c.NewConstValue(token.INT, v)

	case *types.Basic:
		if typ == types.String.Underlying {
			switch value := value.(type) {
			case *LLVMValue:
				ptr := value.pointer
				len_field := c.builder.CreateStructGEP(ptr.LLVMValue(), 1, "")
				len_value := c.builder.CreateLoad(len_field, "")
				return c.NewLLVMValue(len_value, types.Int32).Convert(types.Int)
			case ConstValue:
				s := value.Val.(string)
				n := uint64(len(s))
				return c.NewConstValue(token.INT, strconv.FormatUint(n, 10))
			}
		}
	}
	panic(fmt.Sprint("Unhandled value type: ", value.Type()))
}
開發者ID:kelsieflynn,項目名稱:llgo,代碼行數:56,代碼來源:len.go

示例5: VisitIndexExpr

func (c *compiler) VisitIndexExpr(expr *ast.IndexExpr) Value {
	value := c.VisitExpr(expr.X)
	index := c.VisitExpr(expr.Index)

	typ := types.Underlying(value.Type())
	if typ == types.String {
		ptr := c.builder.CreateExtractValue(value.LLVMValue(), 0, "")
		gepindices := []llvm.Value{index.LLVMValue()}
		ptr = c.builder.CreateGEP(ptr, gepindices, "")
		result := c.NewLLVMValue(ptr, &types.Pointer{Base: types.Byte})
		return result.makePointee()
	}

	// We can index a pointer to an array.
	if _, ok := typ.(*types.Pointer); ok {
		value = value.(*LLVMValue).makePointee()
		typ = value.Type()
	}

	switch typ := types.Underlying(typ).(type) {
	case *types.Array:
		index := index.LLVMValue()
		var ptr llvm.Value
		value := value.(*LLVMValue)
		if value.pointer != nil {
			ptr = value.pointer.LLVMValue()
		} else {
			init := value.LLVMValue()
			ptr = c.builder.CreateAlloca(init.Type(), "")
			c.builder.CreateStore(init, ptr)
		}
		zero := llvm.ConstNull(llvm.Int32Type())
		element := c.builder.CreateGEP(ptr, []llvm.Value{zero, index}, "")
		result := c.NewLLVMValue(element, &types.Pointer{Base: typ.Elt})
		return result.makePointee()

	case *types.Slice:
		index := index.LLVMValue()
		ptr := c.builder.CreateExtractValue(value.LLVMValue(), 0, "")
		element := c.builder.CreateGEP(ptr, []llvm.Value{index}, "")
		result := c.NewLLVMValue(element, &types.Pointer{Base: typ.Elt})
		return result.makePointee()

	case *types.Map:
		value, _ = c.mapLookup(value.(*LLVMValue), index, false)
		return value
	}
	panic(fmt.Sprintf("unreachable (%s)", typ))
}
開發者ID:kisielk,項目名稱:llgo,代碼行數:49,代碼來源:expr.go

示例6: VisitMake

func (c *compiler) VisitMake(expr *ast.CallExpr) Value {
	typ := c.types.expr[expr]
	switch utyp := types.Underlying(typ).(type) {
	case *types.Slice:
		var length, capacity Value
		switch len(expr.Args) {
		case 3:
			capacity = c.VisitExpr(expr.Args[2])
			fallthrough
		case 2:
			length = c.VisitExpr(expr.Args[1])
		}
		slice := c.makeSlice(utyp.Elt, length, capacity)
		return c.NewLLVMValue(slice, typ)
	case *types.Chan:
		f := c.NamedFunction("runtime.makechan", "func f(t uintptr, cap uint32) uintptr")
		dyntyp := c.types.ToRuntime(typ)
		dyntyp = c.builder.CreatePtrToInt(dyntyp, c.target.IntPtrType(), "")
		var cap_ llvm.Value
		if len(expr.Args) > 1 {
			cap_ = c.VisitExpr(expr.Args[1]).LLVMValue()
		}
		args := []llvm.Value{dyntyp, cap_}
		ptr := c.builder.CreateCall(f, args, "")
		return c.NewLLVMValue(ptr, typ)
	case *types.Map:
		f := c.NamedFunction("runtime.makemap", "func f(t uintptr) uintptr")
		dyntyp := c.types.ToRuntime(typ)
		dyntyp = c.builder.CreatePtrToInt(dyntyp, c.target.IntPtrType(), "")
		mapval := c.builder.CreateCall(f, []llvm.Value{dyntyp}, "")
		return c.NewLLVMValue(mapval, typ)
	}
	panic(fmt.Sprintf("unhandled type: %s", typ))
}
開發者ID:kelsieflynn,項目名稱:llgo,代碼行數:34,代碼來源:make.go

示例7: destructureExpr

// destructureExpr evaluates the right-hand side of a
// multiple assignment where the right-hand side is a single expression.
func (c *compiler) destructureExpr(x ast.Expr) []Value {
	var values []Value
	switch x := x.(type) {
	case *ast.IndexExpr:
		// value, ok := m[k]
		m := c.VisitExpr(x.X).(*LLVMValue)
		index := c.VisitExpr(x.Index)
		value, notnull := c.mapLookup(m, index, false)
		values = []Value{value, notnull}
	case *ast.CallExpr:
		value := c.VisitExpr(x)
		aggregate := value.LLVMValue()
		struct_type := value.Type().(*types.Struct)
		values = make([]Value, len(struct_type.Fields))
		for i, f := range struct_type.Fields {
			t := f.Type.(types.Type)
			value_ := c.builder.CreateExtractValue(aggregate, i, "")
			values[i] = c.NewLLVMValue(value_, t)
		}
	case *ast.TypeAssertExpr:
		lhs := c.VisitExpr(x.X).(*LLVMValue)
		typ := c.types.expr[x]
		switch typ := types.Underlying(typ).(type) {
		case *types.Interface:
			value, ok := lhs.convertI2I(typ)
			values = []Value{value, ok}
		default:
			value, ok := lhs.convertI2V(typ)
			values = []Value{value, ok}
		}
	}
	return values
}
開發者ID:kisielk,項目名稱:llgo,代碼行數:35,代碼來源:stmt.go

示例8: VisitIndexExpr

func (c *compiler) VisitIndexExpr(expr *ast.IndexExpr) Value {
	value := c.VisitExpr(expr.X).(*LLVMValue)
	index := c.VisitExpr(expr.Index)

	typ := value.Type()
	if typ == types.String {
		ptr := c.builder.CreateExtractValue(value.LLVMValue(), 0, "")
		gepindices := []llvm.Value{index.LLVMValue()}
		ptr = c.builder.CreateGEP(ptr, gepindices, "")
		result := c.NewLLVMValue(ptr, &types.Pointer{Base: types.Byte})
		return result.makePointee()
	}

	// We can index a pointer to an array.
	if _, ok := types.Underlying(typ).(*types.Pointer); ok {
		value = value.makePointee()
		typ = value.Type()
	}

	switch types.Underlying(typ).(type) {
	case *types.Array, *types.Slice:
		var gep_indices []llvm.Value
		var ptr llvm.Value
		var result_type types.Type
		switch typ := types.Underlying(typ).(type) {
		case *types.Array:
			// FIXME what to do if value is not addressable?
			// Do we have to load the array onto the stack?
			result_type = typ.Elt
			ptr = value.pointer.LLVMValue()
			gep_indices = append(gep_indices, llvm.ConstNull(llvm.Int32Type()))
		case *types.Slice:
			result_type = typ.Elt
			ptr = c.builder.CreateExtractValue(value.LLVMValue(), 0, "")
		}

		gep_indices = append(gep_indices, index.LLVMValue())
		element := c.builder.CreateGEP(ptr, gep_indices, "")
		result := c.NewLLVMValue(element, &types.Pointer{Base: result_type})
		return result.makePointee()

	case *types.Map:
		value, _ = c.mapLookup(value, index, false)
		return value
	}
	panic(fmt.Sprintf("unreachable (%s)", typ))
}
開發者ID:spate,項目名稱:llgo,代碼行數:47,代碼來源:expr.go

示例9: LLVMValue

func (v ConstValue) LLVMValue() llvm.Value {
	typ := types.Underlying(v.Type())
	switch typ {
	case types.Int, types.Uint:
		return llvm.ConstInt(llvm.Int32Type(), uint64(v.Int64()), true)
		// TODO 32/64bit (probably wait for gc)
		//int_val := v.Val.(*big.Int)
		//if int_val.Cmp(maxBigInt32) > 0 || int_val.Cmp(minBigInt32) < 0 {
		//	panic(fmt.Sprint("const ", int_val, " overflows int"))
		//}
		//return llvm.ConstInt(v.compiler.target.IntPtrType(), uint64(v.Int64()), true)
	case types.Uint:
		return llvm.ConstInt(llvm.Int32Type(), uint64(v.Int64()), false)

	case types.Int8:
		return llvm.ConstInt(llvm.Int8Type(), uint64(v.Int64()), true)
	case types.Uint8, types.Byte:
		return llvm.ConstInt(llvm.Int8Type(), uint64(v.Int64()), false)

	case types.Int16:
		return llvm.ConstInt(llvm.Int16Type(), uint64(v.Int64()), true)
	case types.Uint16:
		return llvm.ConstInt(llvm.Int16Type(), uint64(v.Int64()), false)

	case types.Int32, types.Rune:
		return llvm.ConstInt(llvm.Int32Type(), uint64(v.Int64()), true)
	case types.Uint32:
		return llvm.ConstInt(llvm.Int32Type(), uint64(v.Int64()), false)

	case types.Int64:
		return llvm.ConstInt(llvm.Int64Type(), uint64(v.Int64()), true)
	case types.Uint64:
		return llvm.ConstInt(llvm.Int64Type(), uint64(v.Int64()), true)

	case types.Float32:
		return llvm.ConstFloat(llvm.FloatType(), float64(v.Float64()))
	case types.Float64:
		return llvm.ConstFloat(llvm.DoubleType(), float64(v.Float64()))

	case types.UnsafePointer, types.Uintptr:
		inttype := v.compiler.target.IntPtrType()
		return llvm.ConstInt(inttype, uint64(v.Int64()), false)

	case types.String:
		strval := (v.Val).(string)
		ptr := v.compiler.builder.CreateGlobalStringPtr(strval, "")
		len_ := llvm.ConstInt(llvm.Int32Type(), uint64(len(strval)), false)
		return llvm.ConstStruct([]llvm.Value{ptr, len_}, false)

	case types.Bool:
		if v := v.Val.(bool); v {
			return llvm.ConstAllOnes(llvm.Int1Type())
		}
		return llvm.ConstNull(llvm.Int1Type())
	}
	panic(fmt.Errorf("Unhandled type: %v", typ)) //v.typ.Kind))
}
開發者ID:spate,項目名稱:llgo,代碼行數:57,代碼來源:value.go

示例10: chanRecv

func (v *LLVMValue) chanRecv() *LLVMValue {
	c := v.compiler
	elttyp := types.Underlying(v.typ).(*types.Chan).Elt
	ptr := c.builder.CreateAlloca(c.types.ToLLVM(elttyp), "")
	uintptr_ := c.builder.CreatePtrToInt(ptr, c.target.IntPtrType(), "")
	f := c.NamedFunction("runtime.chanrecv", "func f(c, ptr uintptr)")
	c.builder.CreateCall(f, []llvm.Value{v.LLVMValue(), uintptr_}, "")
	value := c.builder.CreateLoad(ptr, "")
	return c.NewLLVMValue(value, elttyp)
}
開發者ID:kelsieflynn,項目名稱:llgo,代碼行數:10,代碼來源:channels.go

示例11: convertI2I

// convertI2I converts an interface to another interface.
func (v *LLVMValue) convertI2I(iface *types.Interface) (result Value, success Value) {
	c := v.compiler
	builder := v.compiler.builder
	src_typ := types.Underlying(v.Type())
	vptr := v.pointer.LLVMValue()

	zero_iface_struct := llvm.ConstNull(c.types.ToLLVM(iface))
	iface_struct := zero_iface_struct
	dynamicType := builder.CreateLoad(builder.CreateStructGEP(vptr, 0, ""), "")
	receiver := builder.CreateLoad(builder.CreateStructGEP(vptr, 1, ""), "")

	// TODO check whether the functions in the struct take
	// value or pointer receivers.

	// TODO handle dynamic interface conversion (non-subset).
	methods := src_typ.(*types.Interface).Methods
	for i, m := range iface.Methods {
		// TODO make this loop linear by iterating through the
		// interface methods and type methods together.
		mi := sort.Search(len(methods), func(i int) bool {
			return methods[i].Name >= m.Name
		})
		if mi >= len(methods) || methods[mi].Name != m.Name {
			//panic("Failed to locate method: " + m.Name)
			goto check_dynamic
		} else {
			method := builder.CreateStructGEP(vptr, mi+2, "")
			fptr := builder.CreateLoad(method, "")
			iface_struct = builder.CreateInsertValue(iface_struct, fptr, i+2, "")
		}
	}
	iface_struct = builder.CreateInsertValue(iface_struct, dynamicType, 0, "")
	iface_struct = builder.CreateInsertValue(iface_struct, receiver, 1, "")
	result = c.NewLLVMValue(iface_struct, iface)
	success = ConstValue{types.Const{true}, c, types.Bool}
	return result, success

check_dynamic:
	runtimeConvertI2I := c.NamedFunction("runtime.convertI2I", "func f(typ, from, to uintptr) bool")
	llvmUintptr := runtimeConvertI2I.Type().ElementType().ParamTypes()[0]

	runtimeType := c.builder.CreatePtrToInt(c.types.ToRuntime(iface), llvmUintptr, "")
	from := c.builder.CreatePtrToInt(vptr, llvmUintptr, "")
	to := c.builder.CreateAlloca(iface_struct.Type(), "")
	c.builder.CreateStore(iface_struct, to)
	toUintptr := c.builder.CreatePtrToInt(to, llvmUintptr, "")
	args := []llvm.Value{runtimeType, from, toUintptr}
	ok := c.builder.CreateCall(runtimeConvertI2I, args, "")

	value := c.builder.CreateLoad(to, "")
	value = c.builder.CreateSelect(ok, value, zero_iface_struct, "")
	result = c.NewLLVMValue(value, iface)
	success = c.NewLLVMValue(ok, types.Bool)
	return result, success
}
開發者ID:kisielk,項目名稱:llgo,代碼行數:56,代碼來源:interfaces.go

示例12: VisitTypeSpec

func (c *compiler) VisitTypeSpec(spec *ast.TypeSpec) {
	obj := spec.Name.Obj
	type_, istype := (obj.Type).(types.Type)
	if !istype {
		type_ = c.GetType(spec.Type)
		if name, isname := type_.(*types.Name); isname {
			type_ = types.Underlying(name)
		}
		obj.Type = &types.Name{Underlying: type_, Obj: obj}
	}
}
開發者ID:c0der007,項目名稱:llgo,代碼行數:11,代碼來源:decl.go

示例13: ToLLVM

func (tm *TypeMap) ToLLVM(t types.Type) llvm.Type {
	t = types.Underlying(t)
	lt, ok := tm.types[t]
	if !ok {
		lt = tm.makeLLVMType(t)
		if lt.IsNil() {
			panic(fmt.Sprint("Failed to create LLVM type for: ", t))
		}
		tm.types[t] = lt
	}
	return lt
}
開發者ID:c0der007,項目名稱:llgo,代碼行數:12,代碼來源:llvmtypes.go

示例14: ToRuntime

func (tm *TypeMap) ToRuntime(t types.Type) llvm.Value {
	t = types.Underlying(t)
	r, ok := tm.runtime[t]
	if !ok {
		_, r = tm.makeRuntimeType(t)
		if r.IsNil() {
			panic(fmt.Sprint("Failed to create runtime type for: ", t))
		}
		tm.runtime[t] = r
	}
	return r
}
開發者ID:c0der007,項目名稱:llgo,代碼行數:12,代碼來源:llvmtypes.go

示例15: Convert

func (v ConstValue) Convert(dstTyp types.Type) Value {
	// Get the underlying type, if any.
	origDstTyp := dstTyp
	dstTyp = types.Underlying(dstTyp)

	if !types.Identical(v.typ, dstTyp) {
		isBasic := false
		if name, isname := types.Underlying(dstTyp).(*types.Name); isname {
			_, isBasic = name.Underlying.(*types.Basic)
		}

		compiler := v.compiler
		if isBasic {
			return ConstValue{v.Const.Convert(&dstTyp), compiler, origDstTyp}
		} else {
			return compiler.NewLLVMValue(v.LLVMValue(), v.Type()).Convert(origDstTyp)
			//panic(fmt.Errorf("unhandled conversion from %v to %v", v.typ, dstTyp))
		}
	} else {
		v.typ = origDstTyp
	}
	return v
}
開發者ID:spate,項目名稱:llgo,代碼行數:23,代碼來源:value.go


注:本文中的github.com/axw/llgo/types.Underlying函數示例由純淨天空整理自Github/MSDocs等開源代碼及文檔管理平台,相關代碼片段篩選自各路編程大神貢獻的開源項目,源碼版權歸原作者所有,傳播和使用請參考對應項目的License;未經允許,請勿轉載。