diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000..e2397bd080 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,22 @@ +version: 2 +jobs: + build: + working_directory: ~/dlang.org + docker: + - image: cimg/base:current-20.04 + resource_class: medium+ + parallelism: 1 + steps: + - checkout + - run: + command: ./.circleci/run.sh install-deps + name: Install DMD + - run: + command: ./.circleci/run.sh install-make + name: Compile & install GNUmake + - run: + command: ./.circleci/run.sh setup-repos + name: Clone DMD + DRuntime + Phobos + - run: + command: ./.circleci/run.sh run-make + name: Make the release target diff --git a/.circleci/run.sh b/.circleci/run.sh new file mode 100755 index 0000000000..4b64d8d6be --- /dev/null +++ b/.circleci/run.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +set -uexo pipefail + +HOST_DMD_VER=2.078.1 +CURL_USER_AGENT="CirleCI $(curl --version | head -n 1)" +DUB=${DUB:-$HOME/dlang/dub/dub} +N=2 +CIRCLE_NODE_INDEX=${CIRCLE_NODE_INDEX:-0} + +case $CIRCLE_NODE_INDEX in + 0) MODEL=64 ;; + 1) MODEL=32 ;; +esac + +install_deps() { + if [ $MODEL -eq 32 ]; then + sudo apt-get update + sudo apt-get install g++-multilib + fi + + for i in {0..4}; do + if curl -fsS -A "$CURL_USER_AGENT" --max-time 5 https://dlang.org/install.sh -O || + curl -fsS -A "$CURL_USER_AGENT" --max-time 5 https://nightlies.dlang.org/install.sh -O || + curl -fsS -A "$CURL_USER_AGENT" --max-time 5 https://raw.githubusercontent.com/dlang/installer/master/script/install.sh -O ; then + break + elif [ $i -ge 4 ]; then + sleep $((1 << $i)) + else + echo 'Failed to download install script' 1>&2 + exit 1 + fi + done + + source "$(CURL_USER_AGENT=\"$CURL_USER_AGENT\" bash install.sh dmd-$HOST_DMD_VER --activate)" + $DC --version + env +} + +# clone dmd and druntime +clone() { + local url="$1" + local path="$2" + local branch="$3" + for i in {0..4}; do + if git clone --branch "$branch" "$url" "$path" "${@:4}"; then + break + elif [ $i -lt 4 ]; then + sleep $((1 << $i)) + else + echo "Failed to clone: ${url}" + exit 1 + fi + done +} + +install_make() +{ + mkdir -p make + cd make + curl -L http://ftp.gnu.org/gnu/make/make-4.1.tar.gz | tar -zxf - --strip-components=1 && ./configure && make && ./make -v + export PATH="$(pwd):${PATH}" + cd .. +} + +setup_repos() +{ + # Set a default in case we run into rate limit restrictions + local base_branch="" + if [ -n "${CIRCLE_PR_NUMBER:-}" ]; then + base_branch=$((curl -fsSL https://api.github.com/repos/dlang/dlang.org/pulls/$CIRCLE_PR_NUMBER || echo) | jq -r '.base.ref') + else + base_branch=$CIRCLE_BRANCH + fi + base_branch=${base_branch:-"master"} + + # Merge upstream branch with changes, s.t. we check with the latest changes + if [ -n "${CIRCLE_PR_NUMBER:-}" ]; then + local current_branch=$(git rev-parse --abbrev-ref HEAD) + # work around weird CircleCi bug, see https://github.com/dlang/dlang.org/pull/1952 + git remote remove upstream || true + git config user.name dummyuser + git config user.email dummyuser@dummyserver.com + git remote add upstream https://github.com/dlang/dlang.org.git + git fetch upstream + git checkout -f upstream/$base_branch + git merge -m "Automatic merge" $current_branch + fi + + for proj in dmd phobos ; do + if [ $base_branch != master ] && [ $base_branch != stable ] && + ! git ls-remote --exit-code --heads https://github.com/dlang/$proj.git $base_branch > /dev/null; then + # use master as fallback for other repos to test feature branches + clone https://github.com/dlang/$proj.git ../$proj master --depth 1 + else + clone https://github.com/dlang/$proj.git ../$proj $base_branch --depth 1 + fi + done + + # Install the bootstrap compiler + CURL_USER_AGENT=\"$CURL_USER_AGENT\" bash ~/dlang/install.sh dmd-$HOST_DMD_VER --activate +} + +run_make() +{ + # Load environment for bootstrap compiler + source "$(CURL_USER_AGENT=\"$CURL_USER_AGENT\" bash ~/dlang/install.sh dmd-$HOST_DMD_VER --activate)" + export PATH="$(pwd)/make:$PATH" + make -v + + # -j1 is used for a better error log + make -f posix.mak -j1 DIFFABLE=1 BUILD_JOBS=3 release +} + +case $1 in + install-deps) install_deps ;; + install-make) install_make ;; + setup-repos) setup_repos ;; + run-make) run_make;; + *) echo "Unknown command"; exit 1;; +esac diff --git a/.dpl_rewrite_map.txt b/.dpl_rewrite_map.txt new file mode 100644 index 0000000000..ec93e79a3b --- /dev/null +++ b/.dpl_rewrite_map.txt @@ -0,0 +1,7522 @@ +/library/core/atomic/atomicFence.html /library/core/atomic/atomic_fence.html +/library/core/atomic/atomicLoad.html /library/core/atomic/atomic_load.html +/library/core/atomic/atomicOp.html /library/core/atomic/atomic_op.html +/library/core/atomic/atomicStore.html /library/core/atomic/atomic_store.html +/library/core/atomic/MemoryOrder.acq.html /library/core/atomic/memory_order.acq.html +/library/core/atomic/MemoryOrder.html /library/core/atomic/memory_order.html +/library/core/atomic/MemoryOrder.raw.html /library/core/atomic/memory_order.raw.html +/library/core/atomic/MemoryOrder.rel.html /library/core/atomic/memory_order.rel.html +/library/core/atomic/MemoryOrder.seq.html /library/core/atomic/memory_order.seq.html +/library/core/bitop/volatileLoad.html /library/core/bitop/volatile_load.html +/library/core/bitop/volatileStore.html /library/core/bitop/volatile_store.html +/library/core/cpuid/amd3dnowExt.html /library/core/cpuid/amd3dnow_ext.html +/library/core/cpuid/amdMmx.html /library/core/cpuid/amd_mmx.html +/library/core/cpuid/CacheInfo.associativity.html /library/core/cpuid/cache_info.associativity.html +/library/core/cpuid/CacheInfo.html /library/core/cpuid/cache_info.html +/library/core/cpuid/CacheInfo.lineSize.html /library/core/cpuid/cache_info.line_size.html +/library/core/cpuid/CacheInfo.size.html /library/core/cpuid/cache_info.size.html +/library/core/cpuid/cacheLevels.html /library/core/cpuid/cache_levels.html +/library/core/cpuid/coresPerCPU.html /library/core/cpuid/cores_per_cpu.html +/library/core/cpuid/dataCaches.html /library/core/cpuid/data_caches.html +/library/core/cpuid/has3dnowPrefetch.html /library/core/cpuid/has3dnow_prefetch.html +/library/core/cpuid/hasCmov.html /library/core/cpuid/has_cmov.html +/library/core/cpuid/hasCmpxchg16b.html /library/core/cpuid/has_cmpxchg16b.html +/library/core/cpuid/hasCmpxchg8b.html /library/core/cpuid/has_cmpxchg8b.html +/library/core/cpuid/hasFxsr.html /library/core/cpuid/has_fxsr.html +/library/core/cpuid/hasLahfSahf.html /library/core/cpuid/has_lahf_sahf.html +/library/core/cpuid/hasLzcnt.html /library/core/cpuid/has_lzcnt.html +/library/core/cpuid/hasPclmulqdq.html /library/core/cpuid/has_pclmulqdq.html +/library/core/cpuid/hasPopcnt.html /library/core/cpuid/has_popcnt.html +/library/core/cpuid/hasRdrand.html /library/core/cpuid/has_rdrand.html +/library/core/cpuid/hasRdseed.html /library/core/cpuid/has_rdseed.html +/library/core/cpuid/hasRdtsc.html /library/core/cpuid/has_rdtsc.html +/library/core/cpuid/hasSha.html /library/core/cpuid/has_sha.html +/library/core/cpuid/hasSysEnterSysExit.html /library/core/cpuid/has_sys_enter_sys_exit.html +/library/core/cpuid/hasVpclmulqdq.html /library/core/cpuid/has_vpclmulqdq.html +/library/core/cpuid/hyperThreading.html /library/core/cpuid/hyper_threading.html +/library/core/cpuid/isItanium.html /library/core/cpuid/is_itanium.html +/library/core/cpuid/isX86_64.html /library/core/cpuid/is_x86_64.html +/library/core/cpuid/numCacheLevels.html /library/core/cpuid/num_cache_levels.html +/library/core/cpuid/preferAthlon.html /library/core/cpuid/prefer_athlon.html +/library/core/cpuid/preferPentium1.html /library/core/cpuid/prefer_pentium1.html +/library/core/cpuid/preferPentium4.html /library/core/cpuid/prefer_pentium4.html +/library/core/cpuid/threadsPerCPU.html /library/core/cpuid/threads_per_cpu.html +/library/core/cpuid/x87onChip.html /library/core/cpuid/x87on_chip.html +/library/core/demangle/demangleType.html /library/core/demangle/demangle_type.html +/library/core/demangle/mangleC.html /library/core/demangle/mangle.html +/library/core/demangle/mangleFunc.html /library/core/demangle/mangle_func.html +/library/core/exception/AssertError.html /library/core/exception/assert_error.html +/library/core/exception/assertHandler.html /library/core/exception/assert_handler.html +/library/core/exception/AssertHandler.html /library/core/exception/assert_handler.html +/library/core/exception/Error.bypassedException.html /library/core/exception/error.bypassed_exception.html +/library/core/exception/FinalizeError.html /library/core/exception/finalize_error.html +/library/core/exception/HiddenFuncError.html /library/core/exception/hidden_func_error.html +/library/core/exception/InvalidMemoryOperationError.html /library/core/exception/invalid_memory_operation_error.html +/library/core/exception/Object.factory.html /library/core/exception/object.factory.html +/library/core/exception/Object.opCmp.html /library/core/exception/object.op_cmp.html +/library/core/exception/Object.opEquals.html /library/core/exception/object.op_equals.html +/library/core/exception/Object.toHash.html /library/core/exception/object.to_hash.html +/library/core/exception/onAssertError.html /library/core/exception/on_assert_error.html +/library/core/exception/onAssertErrorMsg.html /library/core/exception/on_assert_error_msg.html +/library/core/exception/onFinalizeError.html /library/core/exception/on_finalize_error.html +/library/core/exception/onHiddenFuncError.html /library/core/exception/on_hidden_func_error.html +/library/core/exception/onInvalidMemoryOperationError.html /library/core/exception/on_invalid_memory_operation_error.html +/library/core/exception/onOutOfMemoryError.html /library/core/exception/on_out_of_memory_error.html +/library/core/exception/onRangeError.html /library/core/exception/on_range_error.html +/library/core/exception/onSwitchError.html /library/core/exception/on_switch_error.html +/library/core/exception/onUnicodeError.html /library/core/exception/on_unicode_error.html +/library/core/exception/onUnittestErrorMsg.html /library/core/exception/on_unittest_error_msg.html +/library/core/exception/OutOfMemoryError.html /library/core/exception/out_of_memory_error.html +/library/core/exception/RangeError.html /library/core/exception/range_error.html +/library/core/exception/setAssertHandler.html /library/core/exception/set_assert_handler.html +/library/core/exception/SwitchError.html /library/core/exception/switch_error.html +/library/core/exception/Throwable.file.html /library/core/exception/throwable.file.html +/library/core/exception/Throwable.info.html /library/core/exception/throwable.info.html +/library/core/exception/Throwable.line.html /library/core/exception/throwable.line.html +/library/core/exception/Throwable.msg.html /library/core/exception/throwable.msg.html +/library/core/exception/Throwable.next.html /library/core/exception/throwable.next.html +/library/core/exception/Throwable.toString.html /library/core/exception/throwable.to_string.html +/library/core/exception/UnicodeException.html /library/core/exception/unicode_exception.html +/library/core/memory/GC.addRange.html /library/core/memory/gc.add_range.html +/library/core/memory/GC.addrOf.html /library/core/memory/gc.addr_of.html +/library/core/memory/GC.addRoot.html /library/core/memory/gc.add_root.html +/library/core/memory/GC.BlkAttr.APPENDABLE.html /library/core/memory/gc.blk_attr.appendable.html +/library/core/memory/GC.BlkAttr.FINALIZE.html /library/core/memory/gc.blk_attr.finalize.html +/library/core/memory/GC.BlkAttr.html /library/core/memory/gc.blk_attr.html +/library/core/memory/GC.BlkAttr.NO_INTERIOR.html /library/core/memory/gc.blk_attr.n_o_interior.html +/library/core/memory/GC.BlkAttr.NO_MOVE.html /library/core/memory/gc.blk_attr.n_o_move.html +/library/core/memory/GC.BlkAttr.NONE.html /library/core/memory/gc.blk_attr.none.html +/library/core/memory/GC.BlkAttr.NO_SCAN.html /library/core/memory/gc.blk_attr.n_o_scan.html +/library/core/memory/GC.BlkInfo.html /library/core/memory/gc.blk_info.html +/library/core/memory/GC.calloc.html /library/core/memory/gc.calloc.html +/library/core/memory/GC.clrAttr.html /library/core/memory/gc.clr_attr.html +/library/core/memory/GC.collect.html /library/core/memory/gc.collect.html +/library/core/memory/GC.disable.html /library/core/memory/gc.disable.html +/library/core/memory/GC.enable.html /library/core/memory/gc.enable.html +/library/core/memory/GC.extend.html /library/core/memory/gc.extend.html +/library/core/memory/GC.free.html /library/core/memory/gc.free.html +/library/core/memory/GC.getAttr.html /library/core/memory/gc.get_attr.html +/library/core/memory/GC.html /library/core/memory/gc.html +/library/core/memory/GC.malloc.html /library/core/memory/gc.malloc.html +/library/core/memory/GC.minimize.html /library/core/memory/gc.minimize.html +/library/core/memory/GC.qalloc.html /library/core/memory/gc.qalloc.html +/library/core/memory/GC.query.html /library/core/memory/gc.query.html +/library/core/memory/GC.realloc.html /library/core/memory/gc.realloc.html +/library/core/memory/GC.removeRange.html /library/core/memory/gc.remove_range.html +/library/core/memory/GC.removeRoot.html /library/core/memory/gc.remove_root.html +/library/core/memory/GC.reserve.html /library/core/memory/gc.reserve.html +/library/core/memory/GC.runFinalizers.html /library/core/memory/gc.run_finalizers.html +/library/core/memory/GC.setAttr.html /library/core/memory/gc.set_attr.html +/library/core/memory/GC.sizeOf.html /library/core/memory/gc.size_of.html +/library/core/runtime/CArgs.argc.html /library/core/runtime/c_args.argc.html +/library/core/runtime/CArgs.argv.html /library/core/runtime/c_args.argv.html +/library/core/runtime/CArgs.html /library/core/runtime/c_args.html +/library/core/runtime/rt_loadLibrary.html /library/core/runtime/rt_load_library.html +/library/core/runtime/rt_unloadLibrary.html /library/core/runtime/rt_unload_library.html +/library/core/runtime/runModuleUnitTests.html /library/core/runtime/run_module_unit_tests.html +/library/core/runtime/Runtime.args.html /library/core/runtime/runtime.args.html +/library/core/runtime/Runtime.cArgs.html /library/core/runtime/runtime.c_args.html +/library/core/runtime/Runtime.collectHandler.html /library/core/runtime/runtime.collect_handler.html +/library/core/runtime/Runtime.html /library/core/runtime/runtime.html +/library/core/runtime/Runtime.initialize.html /library/core/runtime/runtime.initialize.html +/library/core/runtime/Runtime.loadLibrary.html /library/core/runtime/runtime.load_library.html +/library/core/runtime/Runtime.moduleUnitTester.html /library/core/runtime/runtime.module_unit_tester.html +/library/core/runtime/Runtime.terminate.html /library/core/runtime/runtime.terminate.html +/library/core/runtime/Runtime.traceHandler.html /library/core/runtime/runtime.trace_handler.html +/library/core/runtime/Runtime.unloadLibrary.html /library/core/runtime/runtime.unload_library.html +/library/core/simd/Vector.html /library/core/simd/vector.html +/library/core/simd/XMM.html /library/core/simd/xmm.html +/library/core/stdc/errno/E2BIG.html /library/core/stdc/errno/e2big.html +/library/core/stdc/errno/EACCES.html /library/core/stdc/errno/eacces.html +/library/core/stdc/errno/EADDRINUSE.html /library/core/stdc/errno/eaddrinuse.html +/library/core/stdc/errno/EADDRNOTAVAIL.html /library/core/stdc/errno/eaddrnotavail.html +/library/core/stdc/errno/EADV.html /library/core/stdc/errno/eadv.html +/library/core/stdc/errno/EAFNOSUPPORT.html /library/core/stdc/errno/eafnosupport.html +/library/core/stdc/errno/EAGAIN.html /library/core/stdc/errno/eagain.html +/library/core/stdc/errno/EALREADY.html /library/core/stdc/errno/ealready.html +/library/core/stdc/errno/EBADE.html /library/core/stdc/errno/ebade.html +/library/core/stdc/errno/EBADFD.html /library/core/stdc/errno/ebadfd.html +/library/core/stdc/errno/EBADF.html /library/core/stdc/errno/ebadf.html +/library/core/stdc/errno/EBADMSG.html /library/core/stdc/errno/ebadmsg.html +/library/core/stdc/errno/EBADR.html /library/core/stdc/errno/ebadr.html +/library/core/stdc/errno/EBADRQC.html /library/core/stdc/errno/ebadrqc.html +/library/core/stdc/errno/EBADSLT.html /library/core/stdc/errno/ebadslt.html +/library/core/stdc/errno/EBFONT.html /library/core/stdc/errno/ebfont.html +/library/core/stdc/errno/EBUSY.html /library/core/stdc/errno/ebusy.html +/library/core/stdc/errno/ECANCELED.html /library/core/stdc/errno/ecanceled.html +/library/core/stdc/errno/ECHILD.html /library/core/stdc/errno/echild.html +/library/core/stdc/errno/ECHRNG.html /library/core/stdc/errno/echrng.html +/library/core/stdc/errno/ECOMM.html /library/core/stdc/errno/ecomm.html +/library/core/stdc/errno/ECONNABORTED.html /library/core/stdc/errno/econnaborted.html +/library/core/stdc/errno/ECONNREFUSED.html /library/core/stdc/errno/econnrefused.html +/library/core/stdc/errno/ECONNRESET.html /library/core/stdc/errno/econnreset.html +/library/core/stdc/errno/EDEADLK.html /library/core/stdc/errno/edeadlk.html +/library/core/stdc/errno/EDEADLOCK.html /library/core/stdc/errno/edeadlock.html +/library/core/stdc/errno/EDESTADDRREQ.html /library/core/stdc/errno/edestaddrreq.html +/library/core/stdc/errno/EDOM.html /library/core/stdc/errno/edom.html +/library/core/stdc/errno/EDOTDOT.html /library/core/stdc/errno/edotdot.html +/library/core/stdc/errno/EDQUOT.html /library/core/stdc/errno/edquot.html +/library/core/stdc/errno/EEXIST.html /library/core/stdc/errno/eexist.html +/library/core/stdc/errno/EFAULT.html /library/core/stdc/errno/efault.html +/library/core/stdc/errno/EFBIG.html /library/core/stdc/errno/efbig.html +/library/core/stdc/errno/EHOSTDOWN.html /library/core/stdc/errno/ehostdown.html +/library/core/stdc/errno/EHOSTUNREACH.html /library/core/stdc/errno/ehostunreach.html +/library/core/stdc/errno/EIDRM.html /library/core/stdc/errno/eidrm.html +/library/core/stdc/errno/EILSEQ.html /library/core/stdc/errno/eilseq.html +/library/core/stdc/errno/EINPROGRESS.html /library/core/stdc/errno/einprogress.html +/library/core/stdc/errno/EINTR.html /library/core/stdc/errno/eintr.html +/library/core/stdc/errno/EINVAL.html /library/core/stdc/errno/einval.html +/library/core/stdc/errno/EIO.html /library/core/stdc/errno/eio.html +/library/core/stdc/errno/EISCONN.html /library/core/stdc/errno/eisconn.html +/library/core/stdc/errno/EISDIR.html /library/core/stdc/errno/eisdir.html +/library/core/stdc/errno/EISNAM.html /library/core/stdc/errno/eisnam.html +/library/core/stdc/errno/EKEYEXPIRED.html /library/core/stdc/errno/ekeyexpired.html +/library/core/stdc/errno/EKEYREJECTED.html /library/core/stdc/errno/ekeyrejected.html +/library/core/stdc/errno/EKEYREVOKED.html /library/core/stdc/errno/ekeyrevoked.html +/library/core/stdc/errno/EL2HLT.html /library/core/stdc/errno/e_l2hlt.html +/library/core/stdc/errno/EL2NSYNC.html /library/core/stdc/errno/e_l2nsync.html +/library/core/stdc/errno/EL3HLT.html /library/core/stdc/errno/e_l3hlt.html +/library/core/stdc/errno/EL3RST.html /library/core/stdc/errno/e_l3rst.html +/library/core/stdc/errno/ELIBACC.html /library/core/stdc/errno/elibacc.html +/library/core/stdc/errno/ELIBBAD.html /library/core/stdc/errno/elibbad.html +/library/core/stdc/errno/ELIBEXEC.html /library/core/stdc/errno/elibexec.html +/library/core/stdc/errno/ELIBMAX.html /library/core/stdc/errno/elibmax.html +/library/core/stdc/errno/ELIBSCN.html /library/core/stdc/errno/elibscn.html +/library/core/stdc/errno/ELNRNG.html /library/core/stdc/errno/elnrng.html +/library/core/stdc/errno/ELOOP.html /library/core/stdc/errno/eloop.html +/library/core/stdc/errno/EMEDIUMTYPE.html /library/core/stdc/errno/emediumtype.html +/library/core/stdc/errno/EMFILE.html /library/core/stdc/errno/emfile.html +/library/core/stdc/errno/EMLINK.html /library/core/stdc/errno/emlink.html +/library/core/stdc/errno/EMSGSIZE.html /library/core/stdc/errno/emsgsize.html +/library/core/stdc/errno/EMULTIHOP.html /library/core/stdc/errno/emultihop.html +/library/core/stdc/errno/ENAMETOOLONG.html /library/core/stdc/errno/enametoolong.html +/library/core/stdc/errno/ENAVAIL.html /library/core/stdc/errno/enavail.html +/library/core/stdc/errno/ENETDOWN.html /library/core/stdc/errno/enetdown.html +/library/core/stdc/errno/ENETRESET.html /library/core/stdc/errno/enetreset.html +/library/core/stdc/errno/ENETUNREACH.html /library/core/stdc/errno/enetunreach.html +/library/core/stdc/errno/ENFILE.html /library/core/stdc/errno/enfile.html +/library/core/stdc/errno/ENOANO.html /library/core/stdc/errno/enoano.html +/library/core/stdc/errno/ENOBUFS.html /library/core/stdc/errno/enobufs.html +/library/core/stdc/errno/ENOCSI.html /library/core/stdc/errno/enocsi.html +/library/core/stdc/errno/ENODATA.html /library/core/stdc/errno/enodata.html +/library/core/stdc/errno/ENODEV.html /library/core/stdc/errno/enodev.html +/library/core/stdc/errno/ENOENT.html /library/core/stdc/errno/enoent.html +/library/core/stdc/errno/ENOEXEC.html /library/core/stdc/errno/enoexec.html +/library/core/stdc/errno/ENOKEY.html /library/core/stdc/errno/enokey.html +/library/core/stdc/errno/ENOLCK.html /library/core/stdc/errno/enolck.html +/library/core/stdc/errno/ENOLINK.html /library/core/stdc/errno/enolink.html +/library/core/stdc/errno/ENOMEDIUM.html /library/core/stdc/errno/enomedium.html +/library/core/stdc/errno/ENOMEM.html /library/core/stdc/errno/enomem.html +/library/core/stdc/errno/ENOMSG.html /library/core/stdc/errno/enomsg.html +/library/core/stdc/errno/ENONET.html /library/core/stdc/errno/enonet.html +/library/core/stdc/errno/ENOPKG.html /library/core/stdc/errno/enopkg.html +/library/core/stdc/errno/ENOPROTOOPT.html /library/core/stdc/errno/enoprotoopt.html +/library/core/stdc/errno/ENOSPC.html /library/core/stdc/errno/enospc.html +/library/core/stdc/errno/ENOSR.html /library/core/stdc/errno/enosr.html +/library/core/stdc/errno/ENOSTR.html /library/core/stdc/errno/enostr.html +/library/core/stdc/errno/ENOSYS.html /library/core/stdc/errno/enosys.html +/library/core/stdc/errno/ENOTBLK.html /library/core/stdc/errno/enotblk.html +/library/core/stdc/errno/ENOTCONN.html /library/core/stdc/errno/enotconn.html +/library/core/stdc/errno/ENOTDIR.html /library/core/stdc/errno/enotdir.html +/library/core/stdc/errno/ENOTEMPTY.html /library/core/stdc/errno/enotempty.html +/library/core/stdc/errno/ENOTNAM.html /library/core/stdc/errno/enotnam.html +/library/core/stdc/errno/ENOTRECOVERABLE.html /library/core/stdc/errno/enotrecoverable.html +/library/core/stdc/errno/ENOTSOCK.html /library/core/stdc/errno/enotsock.html +/library/core/stdc/errno/ENOTSUP.html /library/core/stdc/errno/enotsup.html +/library/core/stdc/errno/ENOTTY.html /library/core/stdc/errno/enotty.html +/library/core/stdc/errno/ENOTUNIQ.html /library/core/stdc/errno/enotuniq.html +/library/core/stdc/errno/ENXIO.html /library/core/stdc/errno/enxio.html +/library/core/stdc/errno/EOPNOTSUPP.html /library/core/stdc/errno/eopnotsupp.html +/library/core/stdc/errno/EOVERFLOW.html /library/core/stdc/errno/eoverflow.html +/library/core/stdc/errno/EOWNERDEAD.html /library/core/stdc/errno/eownerdead.html +/library/core/stdc/errno/EPERM.html /library/core/stdc/errno/eperm.html +/library/core/stdc/errno/EPFNOSUPPORT.html /library/core/stdc/errno/epfnosupport.html +/library/core/stdc/errno/EPIPE.html /library/core/stdc/errno/epipe.html +/library/core/stdc/errno/EPROTO.html /library/core/stdc/errno/eproto.html +/library/core/stdc/errno/EPROTONOSUPPORT.html /library/core/stdc/errno/eprotonosupport.html +/library/core/stdc/errno/EPROTOTYPE.html /library/core/stdc/errno/eprototype.html +/library/core/stdc/errno/ERANGE.html /library/core/stdc/errno/erange.html +/library/core/stdc/errno/EREMCHG.html /library/core/stdc/errno/eremchg.html +/library/core/stdc/errno/EREMOTE.html /library/core/stdc/errno/eremote.html +/library/core/stdc/errno/EREMOTEIO.html /library/core/stdc/errno/eremoteio.html +/library/core/stdc/errno/ERESTART.html /library/core/stdc/errno/erestart.html +/library/core/stdc/errno/EROFS.html /library/core/stdc/errno/erofs.html +/library/core/stdc/errno/ESHUTDOWN.html /library/core/stdc/errno/eshutdown.html +/library/core/stdc/errno/ESOCKTNOSUPPORT.html /library/core/stdc/errno/esocktnosupport.html +/library/core/stdc/errno/ESPIPE.html /library/core/stdc/errno/espipe.html +/library/core/stdc/errno/ESRCH.html /library/core/stdc/errno/esrch.html +/library/core/stdc/errno/ESRMNT.html /library/core/stdc/errno/esrmnt.html +/library/core/stdc/errno/ESTALE.html /library/core/stdc/errno/estale.html +/library/core/stdc/errno/ESTRPIPE.html /library/core/stdc/errno/estrpipe.html +/library/core/stdc/errno/ETIMEDOUT.html /library/core/stdc/errno/etimedout.html +/library/core/stdc/errno/ETIME.html /library/core/stdc/errno/etime.html +/library/core/stdc/errno/ETOOMANYREFS.html /library/core/stdc/errno/etoomanyrefs.html +/library/core/stdc/errno/ETXTBSY.html /library/core/stdc/errno/etxtbsy.html +/library/core/stdc/errno/EUCLEAN.html /library/core/stdc/errno/euclean.html +/library/core/stdc/errno/EUNATCH.html /library/core/stdc/errno/eunatch.html +/library/core/stdc/errno/EUSERS.html /library/core/stdc/errno/eusers.html +/library/core/stdc/errno/EWOULDBLOCK.html /library/core/stdc/errno/ewouldblock.html +/library/core/stdc/errno/EXDEV.html /library/core/stdc/errno/exdev.html +/library/core/stdc/errno/EXFULL.html /library/core/stdc/errno/exfull.html +/library/core/stdc/fenv/FE_DENORMAL.html /library/core/stdc/fenv/f_e_denormal.html +/library/core/sync/barrier/Barrier.html /library/core/sync/barrier/barrier.html +/library/core/sync/barrier/Barrier.this.html /library/core/sync/barrier/barrier.this.html +/library/core/sync/barrier/Barrier.wait.html /library/core/sync/barrier/barrier.wait.html +/library/core/sync/barrier/Object.factory.html /library/core/sync/barrier/object.factory.html +/library/core/sync/barrier/Object.opCmp.html /library/core/sync/barrier/object.op_cmp.html +/library/core/sync/barrier/Object.opEquals.html /library/core/sync/barrier/object.op_equals.html +/library/core/sync/barrier/Object.toHash.html /library/core/sync/barrier/object.to_hash.html +/library/core/sync/barrier/Object.toString.html /library/core/sync/barrier/object.to_string.html +/library/core/sync/condition/Condition.html /library/core/sync/condition/condition.html +/library/core/sync/condition/Condition.mutex.html /library/core/sync/condition/condition.mutex.html +/library/core/sync/condition/Condition.notifyAll.html /library/core/sync/condition/condition.notify_all.html +/library/core/sync/condition/Condition.notify.html /library/core/sync/condition/condition.notify.html +/library/core/sync/condition/Condition.this.html /library/core/sync/condition/condition.this.html +/library/core/sync/condition/Condition.wait.html /library/core/sync/condition/condition.wait.html +/library/core/sync/condition/Object.factory.html /library/core/sync/condition/object.factory.html +/library/core/sync/condition/Object.opCmp.html /library/core/sync/condition/object.op_cmp.html +/library/core/sync/condition/Object.opEquals.html /library/core/sync/condition/object.op_equals.html +/library/core/sync/condition/Object.toHash.html /library/core/sync/condition/object.to_hash.html +/library/core/sync/condition/Object.toString.html /library/core/sync/condition/object.to_string.html +/library/core/sync/exception/Error.bypassedException.html /library/core/sync/exception/error.bypassed_exception.html +/library/core/sync/exception/Object.factory.html /library/core/sync/exception/object.factory.html +/library/core/sync/exception/Object.opCmp.html /library/core/sync/exception/object.op_cmp.html +/library/core/sync/exception/Object.opEquals.html /library/core/sync/exception/object.op_equals.html +/library/core/sync/exception/Object.toHash.html /library/core/sync/exception/object.to_hash.html +/library/core/sync/exception/SyncError.html /library/core/sync/exception/sync_error.html +/library/core/sync/exception/Throwable.file.html /library/core/sync/exception/throwable.file.html +/library/core/sync/exception/Throwable.info.html /library/core/sync/exception/throwable.info.html +/library/core/sync/exception/Throwable.line.html /library/core/sync/exception/throwable.line.html +/library/core/sync/exception/Throwable.msg.html /library/core/sync/exception/throwable.msg.html +/library/core/sync/exception/Throwable.next.html /library/core/sync/exception/throwable.next.html +/library/core/sync/exception/Throwable.toString.html /library/core/sync/exception/throwable.to_string.html +/library/core/sync/mutex/Mutex.html /library/core/sync/mutex/mutex.html +/library/core/sync/mutex/Mutex.lock.html /library/core/sync/mutex/mutex.lock.html +/library/core/sync/mutex/Mutex.this.html /library/core/sync/mutex/mutex.this.html +/library/core/sync/mutex/Mutex.tryLock.html /library/core/sync/mutex/mutex.try_lock.html +/library/core/sync/mutex/Mutex.unlock.html /library/core/sync/mutex/mutex.unlock.html +/library/core/sync/mutex/Object.factory.html /library/core/sync/mutex/object.factory.html +/library/core/sync/mutex/Object.opCmp.html /library/core/sync/mutex/object.op_cmp.html +/library/core/sync/mutex/Object.opEquals.html /library/core/sync/mutex/object.op_equals.html +/library/core/sync/mutex/Object.toHash.html /library/core/sync/mutex/object.to_hash.html +/library/core/sync/mutex/Object.toString.html /library/core/sync/mutex/object.to_string.html +/library/core/sync/rwmutex/Object.factory.html /library/core/sync/rwmutex/object.factory.html +/library/core/sync/rwmutex/Object.opCmp.html /library/core/sync/rwmutex/object.op_cmp.html +/library/core/sync/rwmutex/Object.opEquals.html /library/core/sync/rwmutex/object.op_equals.html +/library/core/sync/rwmutex/Object.toHash.html /library/core/sync/rwmutex/object.to_hash.html +/library/core/sync/rwmutex/Object.toString.html /library/core/sync/rwmutex/object.to_string.html +/library/core/sync/rwmutex/ReadWriteMutex.html /library/core/sync/rwmutex/read_write_mutex.html +/library/core/sync/rwmutex/ReadWriteMutex.policy.html /library/core/sync/rwmutex/read_write_mutex.policy.html +/library/core/sync/rwmutex/ReadWriteMutex.Policy.html /library/core/sync/rwmutex/read_write_mutex.policy.html +/library/core/sync/rwmutex/ReadWriteMutex.Policy.PREFER_READERS.html /library/core/sync/rwmutex/read_write_mutex.policy.prefe_r_readers.html +/library/core/sync/rwmutex/ReadWriteMutex.Policy.PREFER_WRITERS.html /library/core/sync/rwmutex/read_write_mutex.policy.prefe_r_writers.html +/library/core/sync/rwmutex/ReadWriteMutex.reader.html /library/core/sync/rwmutex/read_write_mutex.reader.html +/library/core/sync/rwmutex/ReadWriteMutex.Reader.html /library/core/sync/rwmutex/read_write_mutex.reader.html +/library/core/sync/rwmutex/ReadWriteMutex.Reader.lock.html /library/core/sync/rwmutex/read_write_mutex.reader.lock.html +/library/core/sync/rwmutex/ReadWriteMutex.Reader.this.html /library/core/sync/rwmutex/read_write_mutex.reader.this.html +/library/core/sync/rwmutex/ReadWriteMutex.Reader.tryLock.html /library/core/sync/rwmutex/read_write_mutex.reader.try_lock.html +/library/core/sync/rwmutex/ReadWriteMutex.Reader.unlock.html /library/core/sync/rwmutex/read_write_mutex.reader.unlock.html +/library/core/sync/rwmutex/ReadWriteMutex.this.html /library/core/sync/rwmutex/read_write_mutex.this.html +/library/core/sync/rwmutex/ReadWriteMutex.writer.html /library/core/sync/rwmutex/read_write_mutex.writer.html +/library/core/sync/rwmutex/ReadWriteMutex.Writer.html /library/core/sync/rwmutex/read_write_mutex.writer.html +/library/core/sync/rwmutex/ReadWriteMutex.Writer.lock.html /library/core/sync/rwmutex/read_write_mutex.writer.lock.html +/library/core/sync/rwmutex/ReadWriteMutex.Writer.this.html /library/core/sync/rwmutex/read_write_mutex.writer.this.html +/library/core/sync/rwmutex/ReadWriteMutex.Writer.tryLock.html /library/core/sync/rwmutex/read_write_mutex.writer.try_lock.html +/library/core/sync/rwmutex/ReadWriteMutex.Writer.unlock.html /library/core/sync/rwmutex/read_write_mutex.writer.unlock.html +/library/core/sync/semaphore/Object.factory.html /library/core/sync/semaphore/object.factory.html +/library/core/sync/semaphore/Object.opCmp.html /library/core/sync/semaphore/object.op_cmp.html +/library/core/sync/semaphore/Object.opEquals.html /library/core/sync/semaphore/object.op_equals.html +/library/core/sync/semaphore/Object.toHash.html /library/core/sync/semaphore/object.to_hash.html +/library/core/sync/semaphore/Object.toString.html /library/core/sync/semaphore/object.to_string.html +/library/core/sync/semaphore/Semaphore.html /library/core/sync/semaphore/semaphore.html +/library/core/sync/semaphore/Semaphore.notify.html /library/core/sync/semaphore/semaphore.notify.html +/library/core/sync/semaphore/Semaphore.this.html /library/core/sync/semaphore/semaphore.this.html +/library/core/sync/semaphore/Semaphore.tryWait.html /library/core/sync/semaphore/semaphore.try_wait.html +/library/core/sync/semaphore/Semaphore.wait.html /library/core/sync/semaphore/semaphore.wait.html +/library/core/thread/Error.bypassedException.html /library/core/thread/error.bypassed_exception.html +/library/core/thread/Fiber.call.html /library/core/thread/fiber.call.html +/library/core/thread/Fiber.getThis.html /library/core/thread/fiber.get_this.html +/library/core/thread/Fiber.html /library/core/thread/fiber.html +/library/core/thread/Fiber.reset.html /library/core/thread/fiber.reset.html +/library/core/thread/Fiber.Rethrow.html /library/core/thread/fiber.rethrow.html +/library/core/thread/Fiber.state.html /library/core/thread/fiber.state.html +/library/core/thread/Fiber.State.html /library/core/thread/fiber.state.html +/library/core/thread/Fiber.this.html /library/core/thread/fiber.this.html +/library/core/thread/Fiber.yieldAndThrow.html /library/core/thread/fiber.yield_and_throw.html +/library/core/thread/Fiber.yield.html /library/core/thread/fiber.yield.html +/library/core/thread/IsMarkedDg.html /library/core/thread/is_marked_dg.html +/library/core/thread/IsMarked.html /library/core/thread/is_marked.html +/library/core/thread/IsMarked.no.html /library/core/thread/is_marked.no.html +/library/core/thread/IsMarked.unknown.html /library/core/thread/is_marked.unknown.html +/library/core/thread/IsMarked.yes.html /library/core/thread/is_marked.yes.html +/library/core/thread/Object.factory.html /library/core/thread/object.factory.html +/library/core/thread/Object.opCmp.html /library/core/thread/object.op_cmp.html +/library/core/thread/Object.opEquals.html /library/core/thread/object.op_equals.html +/library/core/thread/Object.toHash.html /library/core/thread/object.to_hash.html +/library/core/thread/Object.toString.html /library/core/thread/object.to_string.html +/library/core/thread/ScanAllThreadsFn.html /library/core/thread/scan_all_threads_fn.html +/library/core/thread/ScanAllThreadsTypeFn.html /library/core/thread/scan_all_threads_type_fn.html +/library/core/thread/ScanType.html /library/core/thread/scan_type.html +/library/core/thread/ScanType.stack.html /library/core/thread/scan_type.stack.html +/library/core/thread/ScanType.tls.html /library/core/thread/scan_type.tls.html +/library/core/thread/thread_attachThis.html /library/core/thread/thread_attach_this.html +/library/core/thread/thread_detachByAddr.html /library/core/thread/thread_detach_by_addr.html +/library/core/thread/thread_detachInstance.html /library/core/thread/thread_detach_instance.html +/library/core/thread/thread_detachThis.html /library/core/thread/thread_detach_this.html +/library/core/thread/thread_enterCriticalRegion.html /library/core/thread/thread_enter_critical_region.html +/library/core/thread/ThreadError.html /library/core/thread/thread_error.html +/library/core/thread/ThreadException.html /library/core/thread/thread_exception.html +/library/core/thread/thread_exitCriticalRegion.html /library/core/thread/thread_exit_critical_region.html +/library/core/thread/thread_findByAddr.html /library/core/thread/thread_find_by_addr.html +/library/core/thread/Thread.getAll.html /library/core/thread/thread.get_all.html +/library/core/thread/Thread.getThis.html /library/core/thread/thread.get_this.html +/library/core/thread/ThreadGroup.add.html /library/core/thread/thread_group.add.html +/library/core/thread/ThreadGroup.create.html /library/core/thread/thread_group.create.html +/library/core/thread/ThreadGroup.html /library/core/thread/thread_group.html +/library/core/thread/ThreadGroup.joinAll.html /library/core/thread/thread_group.join_all.html +/library/core/thread/ThreadGroup.opApply.html /library/core/thread/thread_group.op_apply.html +/library/core/thread/ThreadGroup.remove.html /library/core/thread/thread_group.remove.html +/library/core/thread/Thread.html /library/core/thread/thread.html +/library/core/thread/thread_inCriticalRegion.html /library/core/thread/thread_in_critical_region.html +/library/core/thread/Thread.isDaemon.html /library/core/thread/thread.is_daemon.html +/library/core/thread/Thread.isRunning.html /library/core/thread/thread.is_running.html +/library/core/thread/thread_joinAll.html /library/core/thread/thread_join_all.html +/library/core/thread/Thread.join.html /library/core/thread/thread.join.html +/library/core/thread/Thread.name.html /library/core/thread/thread.name.html +/library/core/thread/Thread.opApply.html /library/core/thread/thread.op_apply.html +/library/core/thread/Thread.PRIORITY_DEFAULT.html /library/core/thread/thread.priorit_y_default.html +/library/core/thread/Thread.priority.html /library/core/thread/thread.priority.html +/library/core/thread/Thread.PRIORITY_MAX.html /library/core/thread/thread.priorit_y_max.html +/library/core/thread/Thread.PRIORITY_MIN.html /library/core/thread/thread.priorit_y_min.html +/library/core/thread/thread_processGCMarks.html /library/core/thread/thread_process_gc_marks.html +/library/core/thread/thread_resumeAll.html /library/core/thread/thread_resume_all.html +/library/core/thread/thread_scanAll.html /library/core/thread/thread_scan_all.html +/library/core/thread/thread_scanAllType.html /library/core/thread/thread_scan_all_type.html +/library/core/thread/thread_setGCSignals.html /library/core/thread/thread_set_gc_signals.html +/library/core/thread/thread_setThis.html /library/core/thread/thread_set_this.html +/library/core/thread/Thread.sleep.html /library/core/thread/thread.sleep.html +/library/core/thread/thread_stackBottom.html /library/core/thread/thread_stack_bottom.html +/library/core/thread/thread_stackTop.html /library/core/thread/thread_stack_top.html +/library/core/thread/Thread.start.html /library/core/thread/thread.start.html +/library/core/thread/thread_suspendAll.html /library/core/thread/thread_suspend_all.html +/library/core/thread/Thread.this.html /library/core/thread/thread.this.html +/library/core/thread/Thread.yield.html /library/core/thread/thread.yield.html +/library/core/thread/Throwable.file.html /library/core/thread/throwable.file.html +/library/core/thread/Throwable.info.html /library/core/thread/throwable.info.html +/library/core/thread/Throwable.line.html /library/core/thread/throwable.line.html +/library/core/thread/Throwable.msg.html /library/core/thread/throwable.msg.html +/library/core/thread/Throwable.next.html /library/core/thread/throwable.next.html +/library/core/thread/Throwable.toString.html /library/core/thread/throwable.to_string.html +/library/core/time/convClockFreq.html /library/core/time/conv_clock_freq.html +/library/core/time/Duration.days.html /library/core/time/duration.days.html +/library/core/time/Duration.fracSec.html /library/core/time/duration.frac_sec.html +/library/core/time/Duration.get.html /library/core/time/duration.get.html +/library/core/time/Duration.hours.html /library/core/time/duration.hours.html +/library/core/time/Duration.html /library/core/time/duration.html +/library/core/time/Duration.isNegative.html /library/core/time/duration.is_negative.html +/library/core/time/Duration.max.html /library/core/time/duration.max.html +/library/core/time/Duration.min.html /library/core/time/duration.min.html +/library/core/time/Duration.minutes.html /library/core/time/duration.minutes.html +/library/core/time/Duration.opBinary.html /library/core/time/duration.op_binary.html +/library/core/time/Duration.opBinaryRight.html /library/core/time/duration.op_binary_right.html +/library/core/time/Duration.opCast.html /library/core/time/duration.op_cast.html +/library/core/time/Duration.opCmp.html /library/core/time/duration.op_cmp.html +/library/core/time/Duration.opOpAssign.html /library/core/time/duration.op_op_assign.html +/library/core/time/Duration.opUnary.html /library/core/time/duration.op_unary.html +/library/core/time/Duration.seconds.html /library/core/time/duration.seconds.html +/library/core/time/Duration.split.html /library/core/time/duration.split.html +/library/core/time/Duration.split.split.html /library/core/time/duration.split.split.html +/library/core/time/Duration.toString.html /library/core/time/duration.to_string.html +/library/core/time/Duration.total.html /library/core/time/duration.total.html +/library/core/time/Duration.weeks.html /library/core/time/duration.weeks.html +/library/core/time/Duration.zero.html /library/core/time/duration.zero.html +/library/core/time/FracSec.from.html /library/core/time/frac_sec.from.html +/library/core/time/FracSec.hnsecs.html /library/core/time/frac_sec.hnsecs.html +/library/core/time/FracSec.html /library/core/time/frac_sec.html +/library/core/time/FracSec.msecs.html /library/core/time/frac_sec.msecs.html +/library/core/time/FracSec.nsecs.html /library/core/time/frac_sec.nsecs.html +/library/core/time/FracSec.opUnary.html /library/core/time/frac_sec.op_unary.html +/library/core/time/FracSec.toString.html /library/core/time/frac_sec.to_string.html +/library/core/time/FracSec.usecs.html /library/core/time/frac_sec.usecs.html +/library/core/time/FracSec.zero.html /library/core/time/frac_sec.zero.html +/library/core/time/MonoTime.currTime.html /library/core/time/mono_time.curr_time.html +/library/core/time/MonoTime.html /library/core/time/mono_time.html +/library/core/time/MonoTime.max.html /library/core/time/mono_time.max.html +/library/core/time/MonoTime.min.html /library/core/time/mono_time.min.html +/library/core/time/MonoTime.opBinary.html /library/core/time/mono_time.op_binary.html +/library/core/time/MonoTime.opCmp.html /library/core/time/mono_time.op_cmp.html +/library/core/time/MonoTime.opOpAssign.html /library/core/time/mono_time.op_op_assign.html +/library/core/time/MonoTime.ticks.html /library/core/time/mono_time.ticks.html +/library/core/time/MonoTime.ticksPerSecond.html /library/core/time/mono_time.ticks_per_second.html +/library/core/time/MonoTime.zero.html /library/core/time/mono_time.zero.html +/library/core/time/nsecsToTicks.html /library/core/time/nsecs_to_ticks.html +/library/core/time/Object.factory.html /library/core/time/object.factory.html +/library/core/time/Object.opCmp.html /library/core/time/object.op_cmp.html +/library/core/time/Object.opEquals.html /library/core/time/object.op_equals.html +/library/core/time/Object.toHash.html /library/core/time/object.to_hash.html +/library/core/time/Throwable.file.html /library/core/time/throwable.file.html +/library/core/time/Throwable.info.html /library/core/time/throwable.info.html +/library/core/time/Throwable.line.html /library/core/time/throwable.line.html +/library/core/time/Throwable.msg.html /library/core/time/throwable.msg.html +/library/core/time/Throwable.next.html /library/core/time/throwable.next.html +/library/core/time/Throwable.toString.html /library/core/time/throwable.to_string.html +/library/core/time/TickDuration.appOrigin.html /library/core/time/tick_duration.app_origin.html +/library/core/time/TickDuration.currSystemTick.html /library/core/time/tick_duration.curr_system_tick.html +/library/core/time/TickDuration.from.html /library/core/time/tick_duration.from.html +/library/core/time/TickDuration.hnsecs.html /library/core/time/tick_duration.hnsecs.html +/library/core/time/TickDuration.html /library/core/time/tick_duration.html +/library/core/time/TickDuration.length.html /library/core/time/tick_duration.length.html +/library/core/time/TickDuration.max.html /library/core/time/tick_duration.max.html +/library/core/time/TickDuration.min.html /library/core/time/tick_duration.min.html +/library/core/time/TickDuration.msecs.html /library/core/time/tick_duration.msecs.html +/library/core/time/TickDuration.nsecs.html /library/core/time/tick_duration.nsecs.html +/library/core/time/TickDuration.opBinary.html /library/core/time/tick_duration.op_binary.html +/library/core/time/TickDuration.opCast.html /library/core/time/tick_duration.op_cast.html +/library/core/time/TickDuration.opCmp.html /library/core/time/tick_duration.op_cmp.html +/library/core/time/TickDuration.opOpAssign.html /library/core/time/tick_duration.op_op_assign.html +/library/core/time/TickDuration.opUnary.html /library/core/time/tick_duration.op_unary.html +/library/core/time/TickDuration.seconds.html /library/core/time/tick_duration.seconds.html +/library/core/time/TickDuration.this.html /library/core/time/tick_duration.this.html +/library/core/time/TickDuration.ticksPerSec.html /library/core/time/tick_duration.ticks_per_sec.html +/library/core/time/TickDuration.to.html /library/core/time/tick_duration.to.html +/library/core/time/TickDuration.usecs.html /library/core/time/tick_duration.usecs.html +/library/core/time/TickDuration.zero.html /library/core/time/tick_duration.zero.html +/library/core/time/ticksToNSecs.html /library/core/time/ticks_ton_secs.html +/library/core/time/TimeException.html /library/core/time/time_exception.html +/library/core/time/TimeException.this.html /library/core/time/time_exception.this.html +/library/etc/c/curl/CurlCallbackInfo.html /library/etc/c/curl/curl_callback_info.html +/library/etc/c/curl/CurlChunkBgnFunc.fail.html /library/etc/c/curl/curl_chunk_bgn_func.fail.html +/library/etc/c/curl/CurlChunkBgnFunc.html /library/etc/c/curl/curl_chunk_bgn_func.html +/library/etc/c/curl/CurlChunkBgnFunc.skip.html /library/etc/c/curl/curl_chunk_bgn_func.skip.html +/library/etc/c/curl/CurlChunkEndFunc.html /library/etc/c/curl/curl_chunk_end_func.html +/library/etc/c/curl/CurlError.aborted_by_callback.html /library/etc/c/curl/curl_error.aborted_by_callback.html +/library/etc/c/curl/CurlError.again.html /library/etc/c/curl/curl_error.again.html +/library/etc/c/curl/CurlError.bad_content_encoding.html /library/etc/c/curl/curl_error.bad_content_encoding.html +/library/etc/c/curl/CurlError.bad_download_resume.html /library/etc/c/curl/curl_error.bad_download_resume.html +/library/etc/c/curl/CurlError.bad_function_argument.html /library/etc/c/curl/curl_error.bad_function_argument.html +/library/etc/c/curl/CurlError.chunk_failed.html /library/etc/c/curl/curl_error.chunk_failed.html +/library/etc/c/curl/CurlError.conv_failed.html /library/etc/c/curl/curl_error.conv_failed.html +/library/etc/c/curl/CurlError.conv_reqd.html /library/etc/c/curl/curl_error.conv_reqd.html +/library/etc/c/curl/CurlError.couldnt_connect.html /library/etc/c/curl/curl_error.couldnt_connect.html +/library/etc/c/curl/CurlError.couldnt_resolve_host.html /library/etc/c/curl/curl_error.couldnt_resolve_host.html +/library/etc/c/curl/CurlError.couldnt_resolve_proxy.html /library/etc/c/curl/curl_error.couldnt_resolve_proxy.html +/library/etc/c/curl/CurlError.curl_last.html /library/etc/c/curl/curl_error.curl_last.html +/library/etc/c/curl/CurlError.failed_init.html /library/etc/c/curl/curl_error.failed_init.html +/library/etc/c/curl/CurlError.file_couldnt_read_file.html /library/etc/c/curl/curl_error.file_couldnt_read_file.html +/library/etc/c/curl/CurlError.filesize_exceeded.html /library/etc/c/curl/curl_error.filesize_exceeded.html +/library/etc/c/curl/CurlError.ftp_bad_file_list.html /library/etc/c/curl/curl_error.ftp_bad_file_list.html +/library/etc/c/curl/CurlError.ftp_cant_get_host.html /library/etc/c/curl/curl_error.ftp_cant_get_host.html +/library/etc/c/curl/CurlError.ftp_couldnt_retr_file.html /library/etc/c/curl/curl_error.ftp_couldnt_retr_file.html +/library/etc/c/curl/CurlError.ftp_couldnt_set_type.html /library/etc/c/curl/curl_error.ftp_couldnt_set_type.html +/library/etc/c/curl/CurlError.ftp_couldnt_use_rest.html /library/etc/c/curl/curl_error.ftp_couldnt_use_rest.html +/library/etc/c/curl/CurlError.ftp_port_failed.html /library/etc/c/curl/curl_error.ftp_port_failed.html +/library/etc/c/curl/CurlError.ftp_pret_failed.html /library/etc/c/curl/curl_error.ftp_pret_failed.html +/library/etc/c/curl/CurlError.ftp_weird_227_format.html /library/etc/c/curl/curl_error.ftp_weird_227_format.html +/library/etc/c/curl/CurlError.ftp_weird_pass_reply.html /library/etc/c/curl/curl_error.ftp_weird_pass_reply.html +/library/etc/c/curl/CurlError.ftp_weird_pasv_reply.html /library/etc/c/curl/curl_error.ftp_weird_pasv_reply.html +/library/etc/c/curl/CurlError.ftp_weird_server_reply.html /library/etc/c/curl/curl_error.ftp_weird_server_reply.html +/library/etc/c/curl/CurlError.function_not_found.html /library/etc/c/curl/curl_error.function_not_found.html +/library/etc/c/curl/CurlError.got_nothing.html /library/etc/c/curl/curl_error.got_nothing.html +/library/etc/c/curl/CurlError.html /library/etc/c/curl/curl_error.html +/library/etc/c/curl/CurlError.http_post_error.html /library/etc/c/curl/curl_error.http_post_error.html +/library/etc/c/curl/CurlError.http_returned_error.html /library/etc/c/curl/curl_error.http_returned_error.html +/library/etc/c/curl/CurlError.interface_failed.html /library/etc/c/curl/curl_error.interface_failed.html +/library/etc/c/curl/CurlError.ldap_cannot_bind.html /library/etc/c/curl/curl_error.ldap_cannot_bind.html +/library/etc/c/curl/CurlError.ldap_invalid_url.html /library/etc/c/curl/curl_error.ldap_invalid_url.html +/library/etc/c/curl/CurlError.ldap_search_failed.html /library/etc/c/curl/curl_error.ldap_search_failed.html +/library/etc/c/curl/CurlError.login_denied.html /library/etc/c/curl/curl_error.login_denied.html +/library/etc/c/curl/CurlError.obsolete10.html /library/etc/c/curl/curl_error.obsolete10.html +/library/etc/c/curl/CurlError.obsolete12.html /library/etc/c/curl/curl_error.obsolete12.html +/library/etc/c/curl/CurlError.obsolete16.html /library/etc/c/curl/curl_error.obsolete16.html +/library/etc/c/curl/CurlError.obsolete20.html /library/etc/c/curl/curl_error.obsolete20.html +/library/etc/c/curl/CurlError.obsolete24.html /library/etc/c/curl/curl_error.obsolete24.html +/library/etc/c/curl/CurlError.obsolete29.html /library/etc/c/curl/curl_error.obsolete29.html +/library/etc/c/curl/CurlError.obsolete32.html /library/etc/c/curl/curl_error.obsolete32.html +/library/etc/c/curl/CurlError.obsolete40.html /library/etc/c/curl/curl_error.obsolete40.html +/library/etc/c/curl/CurlError.obsolete44.html /library/etc/c/curl/curl_error.obsolete44.html +/library/etc/c/curl/CurlError.obsolete46.html /library/etc/c/curl/curl_error.obsolete46.html +/library/etc/c/curl/CurlError.obsolete4.html /library/etc/c/curl/curl_error.obsolete4.html +/library/etc/c/curl/CurlError.obsolete50.html /library/etc/c/curl/curl_error.obsolete50.html +/library/etc/c/curl/CurlError.obsolete57.html /library/etc/c/curl/curl_error.obsolete57.html +/library/etc/c/curl/CurlError.operation_timedout.html /library/etc/c/curl/curl_error.operation_timedout.html +/library/etc/c/curl/CurlError.out_of_memory.html /library/etc/c/curl/curl_error.out_of_memory.html +/library/etc/c/curl/CurlError.partial_file.html /library/etc/c/curl/curl_error.partial_file.html +/library/etc/c/curl/CurlError.peer_failed_verification.html /library/etc/c/curl/curl_error.peer_failed_verification.html +/library/etc/c/curl/CurlError.quote_error.html /library/etc/c/curl/curl_error.quote_error.html +/library/etc/c/curl/CurlError.range_error.html /library/etc/c/curl/curl_error.range_error.html +/library/etc/c/curl/CurlError.read_error.html /library/etc/c/curl/curl_error.read_error.html +/library/etc/c/curl/CurlError.recv_error.html /library/etc/c/curl/curl_error.recv_error.html +/library/etc/c/curl/CurlError.remote_access_denied.html /library/etc/c/curl/curl_error.remote_access_denied.html +/library/etc/c/curl/CurlError.remote_disk_full.html /library/etc/c/curl/curl_error.remote_disk_full.html +/library/etc/c/curl/CurlError.remote_file_exists.html /library/etc/c/curl/curl_error.remote_file_exists.html +/library/etc/c/curl/CurlError.remote_file_not_found.html /library/etc/c/curl/curl_error.remote_file_not_found.html +/library/etc/c/curl/CurlError.rtsp_cseq_error.html /library/etc/c/curl/curl_error.rtsp_cseq_error.html +/library/etc/c/curl/CurlError.rtsp_session_error.html /library/etc/c/curl/curl_error.rtsp_session_error.html +/library/etc/c/curl/CurlError.send_error.html /library/etc/c/curl/curl_error.send_error.html +/library/etc/c/curl/CurlError.send_fail_rewind.html /library/etc/c/curl/curl_error.send_fail_rewind.html +/library/etc/c/curl/CurlError.ssh.html /library/etc/c/curl/curl_error.ssh.html +/library/etc/c/curl/CurlError.ssl_cacert_badfile.html /library/etc/c/curl/curl_error.ssl_cacert_badfile.html +/library/etc/c/curl/CurlError.ssl_cacert.html /library/etc/c/curl/curl_error.ssl_cacert.html +/library/etc/c/curl/CurlError.ssl_certproblem.html /library/etc/c/curl/curl_error.ssl_certproblem.html +/library/etc/c/curl/CurlError.ssl_cipher.html /library/etc/c/curl/curl_error.ssl_cipher.html +/library/etc/c/curl/CurlError.ssl_connect_error.html /library/etc/c/curl/curl_error.ssl_connect_error.html +/library/etc/c/curl/CurlError.ssl_crl_badfile.html /library/etc/c/curl/curl_error.ssl_crl_badfile.html +/library/etc/c/curl/CurlError.ssl_engine_initfailed.html /library/etc/c/curl/curl_error.ssl_engine_initfailed.html +/library/etc/c/curl/CurlError.ssl_engine_notfound.html /library/etc/c/curl/curl_error.ssl_engine_notfound.html +/library/etc/c/curl/CurlError.ssl_engine_setfailed.html /library/etc/c/curl/curl_error.ssl_engine_setfailed.html +/library/etc/c/curl/CurlError.ssl_issuer_error.html /library/etc/c/curl/curl_error.ssl_issuer_error.html +/library/etc/c/curl/CurlError.ssl_shutdown_failed.html /library/etc/c/curl/curl_error.ssl_shutdown_failed.html +/library/etc/c/curl/CurlError.telnet_option_syntax.html /library/etc/c/curl/curl_error.telnet_option_syntax.html +/library/etc/c/curl/CurlError.tftp_illegal.html /library/etc/c/curl/curl_error.tftp_illegal.html +/library/etc/c/curl/CurlError.tftp_nosuchuser.html /library/etc/c/curl/curl_error.tftp_nosuchuser.html +/library/etc/c/curl/CurlError.tftp_notfound.html /library/etc/c/curl/curl_error.tftp_notfound.html +/library/etc/c/curl/CurlError.tftp_perm.html /library/etc/c/curl/curl_error.tftp_perm.html +/library/etc/c/curl/CurlError.tftp_unknownid.html /library/etc/c/curl/curl_error.tftp_unknownid.html +/library/etc/c/curl/CurlError.too_many_redirects.html /library/etc/c/curl/curl_error.too_many_redirects.html +/library/etc/c/curl/CurlError.unknown_telnet_option.html /library/etc/c/curl/curl_error.unknown_telnet_option.html +/library/etc/c/curl/CurlError.unsupported_protocol.html /library/etc/c/curl/curl_error.unsupported_protocol.html +/library/etc/c/curl/CurlError.upload_failed.html /library/etc/c/curl/curl_error.upload_failed.html +/library/etc/c/curl/CurlError.url_malformat.html /library/etc/c/curl/curl_error.url_malformat.html +/library/etc/c/curl/CurlError.use_ssl_failed.html /library/etc/c/curl/curl_error.use_ssl_failed.html +/library/etc/c/curl/CurlError.write_error.html /library/etc/c/curl/curl_error.write_error.html +/library/etc/c/curl/CurlFileType.html /library/etc/c/curl/curl_file_type.html +/library/etc/c/curl/CurlFileType.unknown.html /library/etc/c/curl/curl_file_type.unknown.html +/library/etc/c/curl/CurlFnMAtchFunc.html /library/etc/c/curl/curl_fnm_atch_func.html +/library/etc/c/curl/CurlFormAdd.disabled.html /library/etc/c/curl/curl_form_add.disabled.html +/library/etc/c/curl/CurlFormAdd.html /library/etc/c/curl/curl_form_add.html +/library/etc/c/curl/CurlFormAdd.ok.html /library/etc/c/curl/curl_form_add.ok.html +/library/etc/c/curl/CurlFtpAuth.defaultauth.html /library/etc/c/curl/curl_ftp_auth.defaultauth.html +/library/etc/c/curl/CurlFtpAuth.html /library/etc/c/curl/curl_ftp_auth.html +/library/etc/c/curl/CurlFtpAuth.last.html /library/etc/c/curl/curl_ftp_auth.last.html +/library/etc/c/curl/CurlFtpAuth.ssl.html /library/etc/c/curl/curl_ftp_auth.ssl.html +/library/etc/c/curl/CurlFtpAuth.tls.html /library/etc/c/curl/curl_ftp_auth.tls.html +/library/etc/c/curl/CurlFtp.create_dir.html /library/etc/c/curl/curl_ftp.create_dir.html +/library/etc/c/curl/CurlFtp.create_dir_last.html /library/etc/c/curl/curl_ftp.create_dir_last.html +/library/etc/c/curl/CurlFtp.create_dir_none.html /library/etc/c/curl/curl_ftp.create_dir_none.html +/library/etc/c/curl/CurlFtp.create_dir_retry.html /library/etc/c/curl/curl_ftp.create_dir_retry.html +/library/etc/c/curl/CurlFtp.html /library/etc/c/curl/curl_ftp.html +/library/etc/c/curl/CurlFtpMethod.defaultmethod.html /library/etc/c/curl/curl_ftp_method.defaultmethod.html +/library/etc/c/curl/CurlFtpMethod.html /library/etc/c/curl/curl_ftp_method.html +/library/etc/c/curl/CurlFtpMethod.last.html /library/etc/c/curl/curl_ftp_method.last.html +/library/etc/c/curl/CurlFtpMethod.multicwd.html /library/etc/c/curl/curl_ftp_method.multicwd.html +/library/etc/c/curl/CurlFtpMethod.nocwd.html /library/etc/c/curl/curl_ftp_method.nocwd.html +/library/etc/c/curl/CurlFtpMethod.singlecwd.html /library/etc/c/curl/curl_ftp_method.singlecwd.html +/library/etc/c/curl/CurlFtpSSL.ccc_active.html /library/etc/c/curl/curl_ftp_ssl.ccc_active.html +/library/etc/c/curl/CurlFtpSSL.ccc_last.html /library/etc/c/curl/curl_ftp_ssl.ccc_last.html +/library/etc/c/curl/CurlFtpSSL.ccc_none.html /library/etc/c/curl/curl_ftp_ssl.ccc_none.html +/library/etc/c/curl/CurlFtpSSL.ccc_passive.html /library/etc/c/curl/curl_ftp_ssl.ccc_passive.html +/library/etc/c/curl/CurlFtpSSL.html /library/etc/c/curl/curl_ftp_ssl.html +/library/etc/c/curl/CurlHttpVersion.html /library/etc/c/curl/curl_http_version.html +/library/etc/c/curl/CurlHttpVersion.last.html /library/etc/c/curl/curl_http_version.last.html +/library/etc/c/curl/CurlHttpVersion.none.html /library/etc/c/curl/curl_http_version.none.html +/library/etc/c/curl/CurlHttpVersion.v1_0.html /library/etc/c/curl/curl_http_version.v1_0.html +/library/etc/c/curl/CurlHttpVersion.v1_1.html /library/etc/c/curl/curl_http_version.v1_1.html +/library/etc/c/curl/CURLINFO_HTTP_CODE.html /library/etc/c/curl/curlinf_o_htt_p_code.html +/library/etc/c/curl/CurlIpResolve.html /library/etc/c/curl/curl_ip_resolve.html +/library/etc/c/curl/CurlIpResolve.v4.html /library/etc/c/curl/curl_ip_resolve.v4.html +/library/etc/c/curl/CurlIpResolve.v6.html /library/etc/c/curl/curl_ip_resolve.v6.html +/library/etc/c/curl/CurlIpResolve.whatever.html /library/etc/c/curl/curl_ip_resolve.whatever.html +/library/etc/c/curl/CurlKHMatch.html /library/etc/c/curl/curl_kh_match.html +/library/etc/c/curl/CurlKHMatch.last.html /library/etc/c/curl/curl_kh_match.last.html +/library/etc/c/curl/CurlKHMatch.mismatch.html /library/etc/c/curl/curl_kh_match.mismatch.html +/library/etc/c/curl/CurlKHMatch.missing.html /library/etc/c/curl/curl_kh_match.missing.html +/library/etc/c/curl/CurlKHMatch.ok.html /library/etc/c/curl/curl_kh_match.ok.html +/library/etc/c/curl/CurlKHStat.defer.html /library/etc/c/curl/curl_kh_stat.defer.html +/library/etc/c/curl/CurlKHStat.html /library/etc/c/curl/curl_kh_stat.html +/library/etc/c/curl/CurlKHStat.last.html /library/etc/c/curl/curl_kh_stat.last.html +/library/etc/c/curl/CurlKHStat.reject.html /library/etc/c/curl/curl_kh_stat.reject.html +/library/etc/c/curl/CurlKHType.html /library/etc/c/curl/curl_kh_type.html +/library/etc/c/curl/CurlLockAccess.html /library/etc/c/curl/curl_lock_access.html +/library/etc/c/curl/CurlLockAccess.last.html /library/etc/c/curl/curl_lock_access.last.html +/library/etc/c/curl/CurlLockAccess.none.html /library/etc/c/curl/curl_lock_access.none.html +/library/etc/c/curl/CurlLockAccess.shared_access.html /library/etc/c/curl/curl_lock_access.shared_access.html +/library/etc/c/curl/CurlLockAccess.single.html /library/etc/c/curl/curl_lock_access.single.html +/library/etc/c/curl/CurlLockData.html /library/etc/c/curl/curl_lock_data.html +/library/etc/c/curl/CurlLockData.share.html /library/etc/c/curl/curl_lock_data.share.html +/library/etc/c/curl/CURL_MAX_HTTP_HEADER.html /library/etc/c/curl/cur_l_ma_x_htt_p_header.html +/library/etc/c/curl/CURL_MAX_WRITE_SIZE.html /library/etc/c/curl/cur_l_ma_x_writ_e_size.html +/library/etc/c/curl/CURLM_CALL_MULTI_SOCKET.html /library/etc/c/curl/curl_m_cal_l_mult_i_socket.html +/library/etc/c/curl/CurlNetRcOption.html /library/etc/c/curl/curl_net_rc_option.html +/library/etc/c/curl/CurlNetRcOption.ignored.html /library/etc/c/curl/curl_net_rc_option.ignored.html +/library/etc/c/curl/CurlNetRcOption.optional.html /library/etc/c/curl/curl_net_rc_option.optional.html +/library/etc/c/curl/CurlNetRcOption.required.html /library/etc/c/curl/curl_net_rc_option.required.html +/library/etc/c/curl/CURLOPT_HEADERDATA.html /library/etc/c/curl/curlop_t_headerdata.html +/library/etc/c/curl/CURLOPT_READDATA.html /library/etc/c/curl/curlop_t_readdata.html +/library/etc/c/curl/CURLOPT_RTSPHEADER.html /library/etc/c/curl/curlop_t_rtspheader.html +/library/etc/c/curl/CURLOPTTYPE_FUNCTIONPOINT.html /library/etc/c/curl/curlopttyp_e_functionpoint.html +/library/etc/c/curl/CURLOPTTYPE_LONG.html /library/etc/c/curl/curlopttyp_e_long.html +/library/etc/c/curl/CURLOPTTYPE_OBJECTPOINT.html /library/etc/c/curl/curlopttyp_e_objectpoint.html +/library/etc/c/curl/CURLOPTTYPE_OFF_T.html /library/etc/c/curl/curlopttyp_e_of_f_t.html +/library/etc/c/curl/CURLOPT_WRITEDATA.html /library/etc/c/curl/curlop_t_writedata.html +/library/etc/c/curl/CurlPoll.html /library/etc/c/curl/curl_poll.html +/library/etc/c/curl/CurlPoll.none_.html /library/etc/c/curl/curl_poll.none_.html +/library/etc/c/curl/CurlProto.all.html /library/etc/c/curl/curl_proto.all.html +/library/etc/c/curl/CurlProto.html /library/etc/c/curl/curl_proto.html +/library/etc/c/curl/CurlRedir.html /library/etc/c/curl/curl_redir.html +/library/etc/c/curl/CurlRtspReq.html /library/etc/c/curl/curl_rtsp_req.html +/library/etc/c/curl/CurlSeek.cantseek.html /library/etc/c/curl/curl_seek.cantseek.html +/library/etc/c/curl/CurlSeek.fail.html /library/etc/c/curl/curl_seek.fail.html +/library/etc/c/curl/CurlSeek.html /library/etc/c/curl/curl_seek.html +/library/etc/c/curl/CurlSeekPos.html /library/etc/c/curl/curl_seek_pos.html +/library/etc/c/curl/CurlShOption.html /library/etc/c/curl/curl_sh_option.html +/library/etc/c/curl/CurlShOption.last.html /library/etc/c/curl/curl_sh_option.last.html +/library/etc/c/curl/CurlShOption.lockfunc.html /library/etc/c/curl/curl_sh_option.lockfunc.html +/library/etc/c/curl/CurlShOption.none.html /library/etc/c/curl/curl_sh_option.none.html +/library/etc/c/curl/CurlShOption.share.html /library/etc/c/curl/curl_sh_option.share.html +/library/etc/c/curl/CurlShOption.unlockfunc.html /library/etc/c/curl/curl_sh_option.unlockfunc.html +/library/etc/c/curl/CurlShOption.unshare.html /library/etc/c/curl/curl_sh_option.unshare.html +/library/etc/c/curl/CurlShOption.userdata.html /library/etc/c/curl/curl_sh_option.userdata.html +/library/etc/c/curl/CurlUseSSL.all.html /library/etc/c/curl/curl_use_ssl.all.html +/library/etc/c/curl/CurlUseSSL.control.html /library/etc/c/curl/curl_use_ssl.control.html +/library/etc/c/curl/CurlUseSSL.html /library/etc/c/curl/curl_use_ssl.html +/library/etc/c/curl/CurlUseSSL.last.html /library/etc/c/curl/curl_use_ssl.last.html +/library/etc/c/curl/CurlUseSSL.none.html /library/etc/c/curl/curl_use_ssl.none.html +/library/etc/c/curl/CurlUseSSL.tryssl.html /library/etc/c/curl/curl_use_ssl.tryssl.html +/library/etc/c/curl/CurlVer.html /library/etc/c/curl/curl_ver.html +/library/etc/c/curl/CURLVERSION_NOW.html /library/etc/c/curl/curlversio_n_now.html +/library/etc/c/curl/CURL_WRITEFUNC_PAUSE.html /library/etc/c/curl/cur_l_writefun_c_pause.html +/library/etc/c/curl/FUNCTIONPOINT.html /library/etc/c/curl/functionpoint.html +/library/etc/c/curl/HTTPPOST_BUFFER.html /library/etc/c/curl/httppos_t_buffer.html +/library/etc/c/curl/HTTPPOST_CALLBACK.html /library/etc/c/curl/httppos_t_callback.html +/library/etc/c/curl/HTTPPOST_FILENAME.html /library/etc/c/curl/httppos_t_filename.html +/library/etc/c/curl/HTTPPOST_PTRBUFFER.html /library/etc/c/curl/httppos_t_ptrbuffer.html +/library/etc/c/curl/HTTPPOST_PTRCONTENTS.html /library/etc/c/curl/httppos_t_ptrcontents.html +/library/etc/c/curl/HTTPPOST_PTRNAME.html /library/etc/c/curl/httppos_t_ptrname.html +/library/etc/c/curl/HTTPPOST_READFILE.html /library/etc/c/curl/httppos_t_readfile.html +/library/etc/c/curl/LIBCURL_COPYRIGHT.html /library/etc/c/curl/libcur_l_copyright.html +/library/etc/c/curl/LIBCURL_TIMESTAMP.html /library/etc/c/curl/libcur_l_timestamp.html +/library/etc/c/curl/LIBCURL_VERSION.html /library/etc/c/curl/libcur_l_version.html +/library/etc/c/curl/LIBCURL_VERSION_MAJOR.html /library/etc/c/curl/libcur_l_versio_n_major.html +/library/etc/c/curl/LIBCURL_VERSION_MINOR.html /library/etc/c/curl/libcur_l_versio_n_minor.html +/library/etc/c/curl/LIBCURL_VERSION_NUM.html /library/etc/c/curl/libcur_l_versio_n_num.html +/library/etc/c/curl/LIBCURL_VERSION_PATCH.html /library/etc/c/curl/libcur_l_versio_n_patch.html +/library/etc/c/curl/LONG.html /library/etc/c/curl/long.html +/library/etc/c/curl/_N2.html /library/etc/c/curl/__n2.html +/library/etc/c/curl/_N2.target.html /library/etc/c/curl/__n2.target.html +/library/etc/c/curl/OBJECTPOINT.html /library/etc/c/curl/objectpoint.html +/library/etc/c/curl/OFF_T.html /library/etc/c/curl/of_f_t.html +/library/object/_ArrayEq.html /library/object/__array_eq.html +/library/object/assumeSafeAppend.html /library/object/assume_safe_append.html +/library/object/Classinfo.html /library/object/classinfo.html +/library/object/_d_traceContext.html /library/object/_d_trace_context.html +/library/object/Error.bypassedException.html /library/object/error.bypassed_exception.html +/library/object/Error.html /library/object/error.html +/library/object/Error.this.html /library/object/error.this.html +/library/object/Exception.html /library/object/exception.html +/library/object/Exception.this.html /library/object/exception.this.html +/library/object/Interface.classinfo.html /library/object/interface.classinfo.html +/library/object/Interface.html /library/object/interface.html +/library/object/Interface.offset.html /library/object/interface.offset.html +/library/object/Object.factory.html /library/object/object.factory.html +/library/object/Object.html /library/object/object.html +/library/object/Object.opCmp.html /library/object/object.op_cmp.html +/library/object/Object.opEquals.html /library/object/object.op_equals.html +/library/object/Object.toHash.html /library/object/object.to_hash.html +/library/object/Object.toString.html /library/object/object.to_string.html +/library/object/OffsetTypeInfo.html /library/object/offset_type_info.html +/library/object/OffsetTypeInfo.offset.html /library/object/offset_type_info.offset.html +/library/object/OffsetTypeInfo.ti.html /library/object/offset_type_info.ti.html +/library/object/opEquals.html /library/object/op_equals.html +/library/object/rt_getTraceHandler.html /library/object/rt_get_trace_handler.html +/library/object/RTInfo.html /library/object/rt_info.html +/library/object/rt_setTraceHandler.html /library/object/rt_set_trace_handler.html +/library/object/Throwable.file.html /library/object/throwable.file.html +/library/object/Throwable.html /library/object/throwable.html +/library/object/Throwable.info.html /library/object/throwable.info.html +/library/object/Throwable.line.html /library/object/throwable.line.html +/library/object/Throwable.msg.html /library/object/throwable.msg.html +/library/object/Throwable.next.html /library/object/throwable.next.html +/library/object/Throwable.toString.html /library/object/throwable.to_string.html +/library/object/TypeInfo.argTypes.html /library/object/type_info.arg_types.html +/library/object/TypeInfo_Class.base.html /library/object/type_info__class.base.html +/library/object/TypeInfo_Class.create.html /library/object/type_info__class.create.html +/library/object/TypeInfo_Class.find.html /library/object/type_info__class.find.html +/library/object/TypeInfo_Class.html /library/object/type_info__class.html +/library/object/TypeInfo_Class.init.html /library/object/type_info__class.init.html +/library/object/TypeInfo_Class.interfaces.html /library/object/type_info__class.interfaces.html +/library/object/TypeInfo_Class.name.html /library/object/type_info__class.name.html +/library/object/TypeInfo_Class.vtbl.html /library/object/type_info__class.vtbl.html +/library/object/TypeInfo.compare.html /library/object/type_info.compare.html +/library/object/TypeInfo.destroy.html /library/object/type_info.destroy.html +/library/object/TypeInfo.equals.html /library/object/type_info.equals.html +/library/object/TypeInfo.flags.html /library/object/type_info.flags.html +/library/object/TypeInfo.getHash.html /library/object/type_info.get_hash.html +/library/object/TypeInfo.html /library/object/type_info.html +/library/object/TypeInfo.init.html /library/object/type_info.init.html +/library/object/TypeInfo.next.html /library/object/type_info.next.html +/library/object/TypeInfo.offTi.html /library/object/type_info.off_ti.html +/library/object/TypeInfo.postblit.html /library/object/type_info.postblit.html +/library/object/TypeInfo.rtInfo.html /library/object/type_info.rt_info.html +/library/object/TypeInfo.swap.html /library/object/type_info.swap.html +/library/object/TypeInfo.talign.html /library/object/type_info.talign.html +/library/object/TypeInfo.tsize.html /library/object/type_info.tsize.html +/library-prerelease/core/atomic/atomicFence.html /library-prerelease/core/atomic/atomic_fence.html +/library-prerelease/core/atomic/atomicLoad.html /library-prerelease/core/atomic/atomic_load.html +/library-prerelease/core/atomic/atomicOp.html /library-prerelease/core/atomic/atomic_op.html +/library-prerelease/core/atomic/atomicStore.html /library-prerelease/core/atomic/atomic_store.html +/library-prerelease/core/atomic/MemoryOrder.acq.html /library-prerelease/core/atomic/memory_order.acq.html +/library-prerelease/core/atomic/MemoryOrder.html /library-prerelease/core/atomic/memory_order.html +/library-prerelease/core/atomic/MemoryOrder.raw.html /library-prerelease/core/atomic/memory_order.raw.html +/library-prerelease/core/atomic/MemoryOrder.rel.html /library-prerelease/core/atomic/memory_order.rel.html +/library-prerelease/core/atomic/MemoryOrder.seq.html /library-prerelease/core/atomic/memory_order.seq.html +/library-prerelease/core/bitop/volatileLoad.html /library-prerelease/core/bitop/volatile_load.html +/library-prerelease/core/bitop/volatileStore.html /library-prerelease/core/bitop/volatile_store.html +/library-prerelease/core/cpuid/amd3dnowExt.html /library-prerelease/core/cpuid/amd3dnow_ext.html +/library-prerelease/core/cpuid/amdMmx.html /library-prerelease/core/cpuid/amd_mmx.html +/library-prerelease/core/cpuid/CacheInfo.associativity.html /library-prerelease/core/cpuid/cache_info.associativity.html +/library-prerelease/core/cpuid/CacheInfo.html /library-prerelease/core/cpuid/cache_info.html +/library-prerelease/core/cpuid/CacheInfo.lineSize.html /library-prerelease/core/cpuid/cache_info.line_size.html +/library-prerelease/core/cpuid/CacheInfo.size.html /library-prerelease/core/cpuid/cache_info.size.html +/library-prerelease/core/cpuid/cacheLevels.html /library-prerelease/core/cpuid/cache_levels.html +/library-prerelease/core/cpuid/coresPerCPU.html /library-prerelease/core/cpuid/cores_per_cpu.html +/library-prerelease/core/cpuid/dataCaches.html /library-prerelease/core/cpuid/data_caches.html +/library-prerelease/core/cpuid/has3dnowPrefetch.html /library-prerelease/core/cpuid/has3dnow_prefetch.html +/library-prerelease/core/cpuid/hasCmov.html /library-prerelease/core/cpuid/has_cmov.html +/library-prerelease/core/cpuid/hasCmpxchg16b.html /library-prerelease/core/cpuid/has_cmpxchg16b.html +/library-prerelease/core/cpuid/hasCmpxchg8b.html /library-prerelease/core/cpuid/has_cmpxchg8b.html +/library-prerelease/core/cpuid/hasFxsr.html /library-prerelease/core/cpuid/has_fxsr.html +/library-prerelease/core/cpuid/hasLahfSahf.html /library-prerelease/core/cpuid/has_lahf_sahf.html +/library-prerelease/core/cpuid/hasLzcnt.html /library-prerelease/core/cpuid/has_lzcnt.html +/library-prerelease/core/cpuid/hasPclmulqdq.html /library-prerelease/core/cpuid/has_pclmulqdq.html +/library-prerelease/core/cpuid/hasPopcnt.html /library-prerelease/core/cpuid/has_popcnt.html +/library-prerelease/core/cpuid/hasRdrand.html /library-prerelease/core/cpuid/has_rdrand.html +/library-prerelease/core/cpuid/hasRdseed.html /library-prerelease/core/cpuid/has_rdseed.html +/library-prerelease/core/cpuid/hasRdtsc.html /library-prerelease/core/cpuid/has_rdtsc.html +/library-prerelease/core/cpuid/hasSha.html /library-prerelease/core/cpuid/has_sha.html +/library-prerelease/core/cpuid/hasSysEnterSysExit.html /library-prerelease/core/cpuid/has_sys_enter_sys_exit.html +/library-prerelease/core/cpuid/hasVpclmulqdq.html /library-prerelease/core/cpuid/has_vpclmulqdq.html +/library-prerelease/core/cpuid/hyperThreading.html /library-prerelease/core/cpuid/hyper_threading.html +/library-prerelease/core/cpuid/isItanium.html /library-prerelease/core/cpuid/is_itanium.html +/library-prerelease/core/cpuid/isX86_64.html /library-prerelease/core/cpuid/is_x86_64.html +/library-prerelease/core/cpuid/numCacheLevels.html /library-prerelease/core/cpuid/num_cache_levels.html +/library-prerelease/core/cpuid/preferAthlon.html /library-prerelease/core/cpuid/prefer_athlon.html +/library-prerelease/core/cpuid/preferPentium1.html /library-prerelease/core/cpuid/prefer_pentium1.html +/library-prerelease/core/cpuid/preferPentium4.html /library-prerelease/core/cpuid/prefer_pentium4.html +/library-prerelease/core/cpuid/threadsPerCPU.html /library-prerelease/core/cpuid/threads_per_cpu.html +/library-prerelease/core/cpuid/x87onChip.html /library-prerelease/core/cpuid/x87on_chip.html +/library-prerelease/core/demangle/demangleType.html /library-prerelease/core/demangle/demangle_type.html +/library-prerelease/core/demangle/mangleC.html /library-prerelease/core/demangle/mangle.html +/library-prerelease/core/demangle/mangleFunc.html /library-prerelease/core/demangle/mangle_func.html +/library-prerelease/core/exception/AssertError.html /library-prerelease/core/exception/assert_error.html +/library-prerelease/core/exception/assertHandler.html /library-prerelease/core/exception/assert_handler.html +/library-prerelease/core/exception/AssertHandler.html /library-prerelease/core/exception/assert_handler.html +/library-prerelease/core/exception/Error.bypassedException.html /library-prerelease/core/exception/error.bypassed_exception.html +/library-prerelease/core/exception/FinalizeError.html /library-prerelease/core/exception/finalize_error.html +/library-prerelease/core/exception/HiddenFuncError.html /library-prerelease/core/exception/hidden_func_error.html +/library-prerelease/core/exception/InvalidMemoryOperationError.html /library-prerelease/core/exception/invalid_memory_operation_error.html +/library-prerelease/core/exception/Object.factory.html /library-prerelease/core/exception/object.factory.html +/library-prerelease/core/exception/Object.opCmp.html /library-prerelease/core/exception/object.op_cmp.html +/library-prerelease/core/exception/Object.opEquals.html /library-prerelease/core/exception/object.op_equals.html +/library-prerelease/core/exception/Object.toHash.html /library-prerelease/core/exception/object.to_hash.html +/library-prerelease/core/exception/onAssertError.html /library-prerelease/core/exception/on_assert_error.html +/library-prerelease/core/exception/onAssertErrorMsg.html /library-prerelease/core/exception/on_assert_error_msg.html +/library-prerelease/core/exception/onFinalizeError.html /library-prerelease/core/exception/on_finalize_error.html +/library-prerelease/core/exception/onHiddenFuncError.html /library-prerelease/core/exception/on_hidden_func_error.html +/library-prerelease/core/exception/onInvalidMemoryOperationError.html /library-prerelease/core/exception/on_invalid_memory_operation_error.html +/library-prerelease/core/exception/onOutOfMemoryError.html /library-prerelease/core/exception/on_out_of_memory_error.html +/library-prerelease/core/exception/onRangeError.html /library-prerelease/core/exception/on_range_error.html +/library-prerelease/core/exception/onSwitchError.html /library-prerelease/core/exception/on_switch_error.html +/library-prerelease/core/exception/onUnicodeError.html /library-prerelease/core/exception/on_unicode_error.html +/library-prerelease/core/exception/onUnittestErrorMsg.html /library-prerelease/core/exception/on_unittest_error_msg.html +/library-prerelease/core/exception/OutOfMemoryError.html /library-prerelease/core/exception/out_of_memory_error.html +/library-prerelease/core/exception/RangeError.html /library-prerelease/core/exception/range_error.html +/library-prerelease/core/exception/setAssertHandler.html /library-prerelease/core/exception/set_assert_handler.html +/library-prerelease/core/exception/SwitchError.html /library-prerelease/core/exception/switch_error.html +/library-prerelease/core/exception/Throwable.file.html /library-prerelease/core/exception/throwable.file.html +/library-prerelease/core/exception/Throwable.info.html /library-prerelease/core/exception/throwable.info.html +/library-prerelease/core/exception/Throwable.line.html /library-prerelease/core/exception/throwable.line.html +/library-prerelease/core/exception/Throwable.msg.html /library-prerelease/core/exception/throwable.msg.html +/library-prerelease/core/exception/Throwable.next.html /library-prerelease/core/exception/throwable.next.html +/library-prerelease/core/exception/Throwable.toString.html /library-prerelease/core/exception/throwable.to_string.html +/library-prerelease/core/exception/UnicodeException.html /library-prerelease/core/exception/unicode_exception.html +/library-prerelease/core/memory/GC.addRange.html /library-prerelease/core/memory/gc.add_range.html +/library-prerelease/core/memory/GC.addrOf.html /library-prerelease/core/memory/gc.addr_of.html +/library-prerelease/core/memory/GC.addRoot.html /library-prerelease/core/memory/gc.add_root.html +/library-prerelease/core/memory/GC.BlkAttr.APPENDABLE.html /library-prerelease/core/memory/gc.blk_attr.appendable.html +/library-prerelease/core/memory/GC.BlkAttr.FINALIZE.html /library-prerelease/core/memory/gc.blk_attr.finalize.html +/library-prerelease/core/memory/GC.BlkAttr.html /library-prerelease/core/memory/gc.blk_attr.html +/library-prerelease/core/memory/GC.BlkAttr.NO_INTERIOR.html /library-prerelease/core/memory/gc.blk_attr.n_o_interior.html +/library-prerelease/core/memory/GC.BlkAttr.NO_MOVE.html /library-prerelease/core/memory/gc.blk_attr.n_o_move.html +/library-prerelease/core/memory/GC.BlkAttr.NONE.html /library-prerelease/core/memory/gc.blk_attr.none.html +/library-prerelease/core/memory/GC.BlkAttr.NO_SCAN.html /library-prerelease/core/memory/gc.blk_attr.n_o_scan.html +/library-prerelease/core/memory/GC.BlkInfo.html /library-prerelease/core/memory/gc.blk_info.html +/library-prerelease/core/memory/GC.calloc.html /library-prerelease/core/memory/gc.calloc.html +/library-prerelease/core/memory/GC.clrAttr.html /library-prerelease/core/memory/gc.clr_attr.html +/library-prerelease/core/memory/GC.collect.html /library-prerelease/core/memory/gc.collect.html +/library-prerelease/core/memory/GC.disable.html /library-prerelease/core/memory/gc.disable.html +/library-prerelease/core/memory/GC.enable.html /library-prerelease/core/memory/gc.enable.html +/library-prerelease/core/memory/GC.extend.html /library-prerelease/core/memory/gc.extend.html +/library-prerelease/core/memory/GC.free.html /library-prerelease/core/memory/gc.free.html +/library-prerelease/core/memory/GC.getAttr.html /library-prerelease/core/memory/gc.get_attr.html +/library-prerelease/core/memory/GC.html /library-prerelease/core/memory/gc.html +/library-prerelease/core/memory/GC.malloc.html /library-prerelease/core/memory/gc.malloc.html +/library-prerelease/core/memory/GC.minimize.html /library-prerelease/core/memory/gc.minimize.html +/library-prerelease/core/memory/GC.qalloc.html /library-prerelease/core/memory/gc.qalloc.html +/library-prerelease/core/memory/GC.query.html /library-prerelease/core/memory/gc.query.html +/library-prerelease/core/memory/GC.realloc.html /library-prerelease/core/memory/gc.realloc.html +/library-prerelease/core/memory/GC.removeRange.html /library-prerelease/core/memory/gc.remove_range.html +/library-prerelease/core/memory/GC.removeRoot.html /library-prerelease/core/memory/gc.remove_root.html +/library-prerelease/core/memory/GC.reserve.html /library-prerelease/core/memory/gc.reserve.html +/library-prerelease/core/memory/GC.runFinalizers.html /library-prerelease/core/memory/gc.run_finalizers.html +/library-prerelease/core/memory/GC.setAttr.html /library-prerelease/core/memory/gc.set_attr.html +/library-prerelease/core/memory/GC.sizeOf.html /library-prerelease/core/memory/gc.size_of.html +/library-prerelease/core/runtime/CArgs.argc.html /library-prerelease/core/runtime/c_args.argc.html +/library-prerelease/core/runtime/CArgs.argv.html /library-prerelease/core/runtime/c_args.argv.html +/library-prerelease/core/runtime/CArgs.html /library-prerelease/core/runtime/c_args.html +/library-prerelease/core/runtime/rt_loadLibrary.html /library-prerelease/core/runtime/rt_load_library.html +/library-prerelease/core/runtime/rt_unloadLibrary.html /library-prerelease/core/runtime/rt_unload_library.html +/library-prerelease/core/runtime/runModuleUnitTests.html /library-prerelease/core/runtime/run_module_unit_tests.html +/library-prerelease/core/runtime/Runtime.args.html /library-prerelease/core/runtime/runtime.args.html +/library-prerelease/core/runtime/Runtime.cArgs.html /library-prerelease/core/runtime/runtime.c_args.html +/library-prerelease/core/runtime/Runtime.collectHandler.html /library-prerelease/core/runtime/runtime.collect_handler.html +/library-prerelease/core/runtime/Runtime.html /library-prerelease/core/runtime/runtime.html +/library-prerelease/core/runtime/Runtime.initialize.html /library-prerelease/core/runtime/runtime.initialize.html +/library-prerelease/core/runtime/Runtime.loadLibrary.html /library-prerelease/core/runtime/runtime.load_library.html +/library-prerelease/core/runtime/Runtime.moduleUnitTester.html /library-prerelease/core/runtime/runtime.module_unit_tester.html +/library-prerelease/core/runtime/Runtime.terminate.html /library-prerelease/core/runtime/runtime.terminate.html +/library-prerelease/core/runtime/Runtime.traceHandler.html /library-prerelease/core/runtime/runtime.trace_handler.html +/library-prerelease/core/runtime/Runtime.unloadLibrary.html /library-prerelease/core/runtime/runtime.unload_library.html +/library-prerelease/core/simd/Vector.html /library-prerelease/core/simd/vector.html +/library-prerelease/core/simd/XMM.html /library-prerelease/core/simd/xmm.html +/library-prerelease/core/sync/barrier/Barrier.html /library-prerelease/core/sync/barrier/barrier.html +/library-prerelease/core/sync/barrier/Barrier.this.html /library-prerelease/core/sync/barrier/barrier.this.html +/library-prerelease/core/sync/barrier/Barrier.wait.html /library-prerelease/core/sync/barrier/barrier.wait.html +/library-prerelease/core/sync/barrier/Object.factory.html /library-prerelease/core/sync/barrier/object.factory.html +/library-prerelease/core/sync/barrier/Object.opCmp.html /library-prerelease/core/sync/barrier/object.op_cmp.html +/library-prerelease/core/sync/barrier/Object.opEquals.html /library-prerelease/core/sync/barrier/object.op_equals.html +/library-prerelease/core/sync/barrier/Object.toHash.html /library-prerelease/core/sync/barrier/object.to_hash.html +/library-prerelease/core/sync/barrier/Object.toString.html /library-prerelease/core/sync/barrier/object.to_string.html +/library-prerelease/core/sync/condition/Condition.html /library-prerelease/core/sync/condition/condition.html +/library-prerelease/core/sync/condition/Condition.mutex.html /library-prerelease/core/sync/condition/condition.mutex.html +/library-prerelease/core/sync/condition/Condition.notifyAll.html /library-prerelease/core/sync/condition/condition.notify_all.html +/library-prerelease/core/sync/condition/Condition.notify.html /library-prerelease/core/sync/condition/condition.notify.html +/library-prerelease/core/sync/condition/Condition.this.html /library-prerelease/core/sync/condition/condition.this.html +/library-prerelease/core/sync/condition/Condition.wait.html /library-prerelease/core/sync/condition/condition.wait.html +/library-prerelease/core/sync/condition/Object.factory.html /library-prerelease/core/sync/condition/object.factory.html +/library-prerelease/core/sync/condition/Object.opCmp.html /library-prerelease/core/sync/condition/object.op_cmp.html +/library-prerelease/core/sync/condition/Object.opEquals.html /library-prerelease/core/sync/condition/object.op_equals.html +/library-prerelease/core/sync/condition/Object.toHash.html /library-prerelease/core/sync/condition/object.to_hash.html +/library-prerelease/core/sync/condition/Object.toString.html /library-prerelease/core/sync/condition/object.to_string.html +/library-prerelease/core/sync/exception/Error.bypassedException.html /library-prerelease/core/sync/exception/error.bypassed_exception.html +/library-prerelease/core/sync/exception/Object.factory.html /library-prerelease/core/sync/exception/object.factory.html +/library-prerelease/core/sync/exception/Object.opCmp.html /library-prerelease/core/sync/exception/object.op_cmp.html +/library-prerelease/core/sync/exception/Object.opEquals.html /library-prerelease/core/sync/exception/object.op_equals.html +/library-prerelease/core/sync/exception/Object.toHash.html /library-prerelease/core/sync/exception/object.to_hash.html +/library-prerelease/core/sync/exception/SyncError.html /library-prerelease/core/sync/exception/sync_error.html +/library-prerelease/core/sync/exception/Throwable.file.html /library-prerelease/core/sync/exception/throwable.file.html +/library-prerelease/core/sync/exception/Throwable.info.html /library-prerelease/core/sync/exception/throwable.info.html +/library-prerelease/core/sync/exception/Throwable.line.html /library-prerelease/core/sync/exception/throwable.line.html +/library-prerelease/core/sync/exception/Throwable.msg.html /library-prerelease/core/sync/exception/throwable.msg.html +/library-prerelease/core/sync/exception/Throwable.next.html /library-prerelease/core/sync/exception/throwable.next.html +/library-prerelease/core/sync/exception/Throwable.toString.html /library-prerelease/core/sync/exception/throwable.to_string.html +/library-prerelease/core/sync/mutex/Mutex.html /library-prerelease/core/sync/mutex/mutex.html +/library-prerelease/core/sync/mutex/Mutex.lock.html /library-prerelease/core/sync/mutex/mutex.lock.html +/library-prerelease/core/sync/mutex/Mutex.this.html /library-prerelease/core/sync/mutex/mutex.this.html +/library-prerelease/core/sync/mutex/Mutex.tryLock.html /library-prerelease/core/sync/mutex/mutex.try_lock.html +/library-prerelease/core/sync/mutex/Mutex.unlock.html /library-prerelease/core/sync/mutex/mutex.unlock.html +/library-prerelease/core/sync/mutex/Object.factory.html /library-prerelease/core/sync/mutex/object.factory.html +/library-prerelease/core/sync/mutex/Object.opCmp.html /library-prerelease/core/sync/mutex/object.op_cmp.html +/library-prerelease/core/sync/mutex/Object.opEquals.html /library-prerelease/core/sync/mutex/object.op_equals.html +/library-prerelease/core/sync/mutex/Object.toHash.html /library-prerelease/core/sync/mutex/object.to_hash.html +/library-prerelease/core/sync/mutex/Object.toString.html /library-prerelease/core/sync/mutex/object.to_string.html +/library-prerelease/core/sync/rwmutex/Object.factory.html /library-prerelease/core/sync/rwmutex/object.factory.html +/library-prerelease/core/sync/rwmutex/Object.opCmp.html /library-prerelease/core/sync/rwmutex/object.op_cmp.html +/library-prerelease/core/sync/rwmutex/Object.opEquals.html /library-prerelease/core/sync/rwmutex/object.op_equals.html +/library-prerelease/core/sync/rwmutex/Object.toHash.html /library-prerelease/core/sync/rwmutex/object.to_hash.html +/library-prerelease/core/sync/rwmutex/Object.toString.html /library-prerelease/core/sync/rwmutex/object.to_string.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.html /library-prerelease/core/sync/rwmutex/read_write_mutex.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.policy.html /library-prerelease/core/sync/rwmutex/read_write_mutex.policy.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.Policy.html /library-prerelease/core/sync/rwmutex/read_write_mutex.policy.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.Policy.PREFER_READERS.html /library-prerelease/core/sync/rwmutex/read_write_mutex.policy.prefe_r_readers.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.Policy.PREFER_WRITERS.html /library-prerelease/core/sync/rwmutex/read_write_mutex.policy.prefe_r_writers.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.reader.html /library-prerelease/core/sync/rwmutex/read_write_mutex.reader.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.Reader.html /library-prerelease/core/sync/rwmutex/read_write_mutex.reader.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.Reader.lock.html /library-prerelease/core/sync/rwmutex/read_write_mutex.reader.lock.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.Reader.this.html /library-prerelease/core/sync/rwmutex/read_write_mutex.reader.this.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.Reader.tryLock.html /library-prerelease/core/sync/rwmutex/read_write_mutex.reader.try_lock.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.Reader.unlock.html /library-prerelease/core/sync/rwmutex/read_write_mutex.reader.unlock.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.this.html /library-prerelease/core/sync/rwmutex/read_write_mutex.this.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.writer.html /library-prerelease/core/sync/rwmutex/read_write_mutex.writer.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.Writer.html /library-prerelease/core/sync/rwmutex/read_write_mutex.writer.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.Writer.lock.html /library-prerelease/core/sync/rwmutex/read_write_mutex.writer.lock.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.Writer.this.html /library-prerelease/core/sync/rwmutex/read_write_mutex.writer.this.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.Writer.tryLock.html /library-prerelease/core/sync/rwmutex/read_write_mutex.writer.try_lock.html +/library-prerelease/core/sync/rwmutex/ReadWriteMutex.Writer.unlock.html /library-prerelease/core/sync/rwmutex/read_write_mutex.writer.unlock.html +/library-prerelease/core/sync/semaphore/Object.factory.html /library-prerelease/core/sync/semaphore/object.factory.html +/library-prerelease/core/sync/semaphore/Object.opCmp.html /library-prerelease/core/sync/semaphore/object.op_cmp.html +/library-prerelease/core/sync/semaphore/Object.opEquals.html /library-prerelease/core/sync/semaphore/object.op_equals.html +/library-prerelease/core/sync/semaphore/Object.toHash.html /library-prerelease/core/sync/semaphore/object.to_hash.html +/library-prerelease/core/sync/semaphore/Object.toString.html /library-prerelease/core/sync/semaphore/object.to_string.html +/library-prerelease/core/sync/semaphore/Semaphore.html /library-prerelease/core/sync/semaphore/semaphore.html +/library-prerelease/core/sync/semaphore/Semaphore.notify.html /library-prerelease/core/sync/semaphore/semaphore.notify.html +/library-prerelease/core/sync/semaphore/Semaphore.this.html /library-prerelease/core/sync/semaphore/semaphore.this.html +/library-prerelease/core/sync/semaphore/Semaphore.tryWait.html /library-prerelease/core/sync/semaphore/semaphore.try_wait.html +/library-prerelease/core/sync/semaphore/Semaphore.wait.html /library-prerelease/core/sync/semaphore/semaphore.wait.html +/library-prerelease/core/thread/Error.bypassedException.html /library-prerelease/core/thread/error.bypassed_exception.html +/library-prerelease/core/thread/Fiber.call.html /library-prerelease/core/thread/fiber.call.html +/library-prerelease/core/thread/Fiber.getThis.html /library-prerelease/core/thread/fiber.get_this.html +/library-prerelease/core/thread/Fiber.html /library-prerelease/core/thread/fiber.html +/library-prerelease/core/thread/Fiber.reset.html /library-prerelease/core/thread/fiber.reset.html +/library-prerelease/core/thread/Fiber.Rethrow.html /library-prerelease/core/thread/fiber.rethrow.html +/library-prerelease/core/thread/Fiber.state.html /library-prerelease/core/thread/fiber.state.html +/library-prerelease/core/thread/Fiber.State.html /library-prerelease/core/thread/fiber.state.html +/library-prerelease/core/thread/Fiber.this.html /library-prerelease/core/thread/fiber.this.html +/library-prerelease/core/thread/Fiber.yieldAndThrow.html /library-prerelease/core/thread/fiber.yield_and_throw.html +/library-prerelease/core/thread/Fiber.yield.html /library-prerelease/core/thread/fiber.yield.html +/library-prerelease/core/thread/IsMarkedDg.html /library-prerelease/core/thread/is_marked_dg.html +/library-prerelease/core/thread/IsMarked.html /library-prerelease/core/thread/is_marked.html +/library-prerelease/core/thread/IsMarked.no.html /library-prerelease/core/thread/is_marked.no.html +/library-prerelease/core/thread/IsMarked.unknown.html /library-prerelease/core/thread/is_marked.unknown.html +/library-prerelease/core/thread/IsMarked.yes.html /library-prerelease/core/thread/is_marked.yes.html +/library-prerelease/core/thread/Object.factory.html /library-prerelease/core/thread/object.factory.html +/library-prerelease/core/thread/Object.opCmp.html /library-prerelease/core/thread/object.op_cmp.html +/library-prerelease/core/thread/Object.opEquals.html /library-prerelease/core/thread/object.op_equals.html +/library-prerelease/core/thread/Object.toHash.html /library-prerelease/core/thread/object.to_hash.html +/library-prerelease/core/thread/Object.toString.html /library-prerelease/core/thread/object.to_string.html +/library-prerelease/core/thread/ScanAllThreadsFn.html /library-prerelease/core/thread/scan_all_threads_fn.html +/library-prerelease/core/thread/ScanAllThreadsTypeFn.html /library-prerelease/core/thread/scan_all_threads_type_fn.html +/library-prerelease/core/thread/ScanType.html /library-prerelease/core/thread/scan_type.html +/library-prerelease/core/thread/ScanType.stack.html /library-prerelease/core/thread/scan_type.stack.html +/library-prerelease/core/thread/ScanType.tls.html /library-prerelease/core/thread/scan_type.tls.html +/library-prerelease/core/thread/thread_attachThis.html /library-prerelease/core/thread/thread_attach_this.html +/library-prerelease/core/thread/thread_detachByAddr.html /library-prerelease/core/thread/thread_detach_by_addr.html +/library-prerelease/core/thread/thread_detachInstance.html /library-prerelease/core/thread/thread_detach_instance.html +/library-prerelease/core/thread/thread_detachThis.html /library-prerelease/core/thread/thread_detach_this.html +/library-prerelease/core/thread/thread_enterCriticalRegion.html /library-prerelease/core/thread/thread_enter_critical_region.html +/library-prerelease/core/thread/ThreadError.html /library-prerelease/core/thread/thread_error.html +/library-prerelease/core/thread/ThreadException.html /library-prerelease/core/thread/thread_exception.html +/library-prerelease/core/thread/thread_exitCriticalRegion.html /library-prerelease/core/thread/thread_exit_critical_region.html +/library-prerelease/core/thread/thread_findByAddr.html /library-prerelease/core/thread/thread_find_by_addr.html +/library-prerelease/core/thread/Thread.getAll.html /library-prerelease/core/thread/thread.get_all.html +/library-prerelease/core/thread/Thread.getThis.html /library-prerelease/core/thread/thread.get_this.html +/library-prerelease/core/thread/ThreadGroup.add.html /library-prerelease/core/thread/thread_group.add.html +/library-prerelease/core/thread/ThreadGroup.create.html /library-prerelease/core/thread/thread_group.create.html +/library-prerelease/core/thread/ThreadGroup.html /library-prerelease/core/thread/thread_group.html +/library-prerelease/core/thread/ThreadGroup.joinAll.html /library-prerelease/core/thread/thread_group.join_all.html +/library-prerelease/core/thread/ThreadGroup.opApply.html /library-prerelease/core/thread/thread_group.op_apply.html +/library-prerelease/core/thread/ThreadGroup.remove.html /library-prerelease/core/thread/thread_group.remove.html +/library-prerelease/core/thread/Thread.html /library-prerelease/core/thread/thread.html +/library-prerelease/core/thread/thread_inCriticalRegion.html /library-prerelease/core/thread/thread_in_critical_region.html +/library-prerelease/core/thread/Thread.isDaemon.html /library-prerelease/core/thread/thread.is_daemon.html +/library-prerelease/core/thread/Thread.isRunning.html /library-prerelease/core/thread/thread.is_running.html +/library-prerelease/core/thread/thread_joinAll.html /library-prerelease/core/thread/thread_join_all.html +/library-prerelease/core/thread/Thread.join.html /library-prerelease/core/thread/thread.join.html +/library-prerelease/core/thread/Thread.name.html /library-prerelease/core/thread/thread.name.html +/library-prerelease/core/thread/Thread.opApply.html /library-prerelease/core/thread/thread.op_apply.html +/library-prerelease/core/thread/Thread.PRIORITY_DEFAULT.html /library-prerelease/core/thread/thread.priorit_y_default.html +/library-prerelease/core/thread/Thread.priority.html /library-prerelease/core/thread/thread.priority.html +/library-prerelease/core/thread/Thread.PRIORITY_MAX.html /library-prerelease/core/thread/thread.priorit_y_max.html +/library-prerelease/core/thread/Thread.PRIORITY_MIN.html /library-prerelease/core/thread/thread.priorit_y_min.html +/library-prerelease/core/thread/thread_processGCMarks.html /library-prerelease/core/thread/thread_process_gc_marks.html +/library-prerelease/core/thread/thread_resumeAll.html /library-prerelease/core/thread/thread_resume_all.html +/library-prerelease/core/thread/thread_scanAll.html /library-prerelease/core/thread/thread_scan_all.html +/library-prerelease/core/thread/thread_scanAllType.html /library-prerelease/core/thread/thread_scan_all_type.html +/library-prerelease/core/thread/thread_setGCSignals.html /library-prerelease/core/thread/thread_set_gc_signals.html +/library-prerelease/core/thread/thread_setThis.html /library-prerelease/core/thread/thread_set_this.html +/library-prerelease/core/thread/Thread.sleep.html /library-prerelease/core/thread/thread.sleep.html +/library-prerelease/core/thread/thread_stackBottom.html /library-prerelease/core/thread/thread_stack_bottom.html +/library-prerelease/core/thread/thread_stackTop.html /library-prerelease/core/thread/thread_stack_top.html +/library-prerelease/core/thread/Thread.start.html /library-prerelease/core/thread/thread.start.html +/library-prerelease/core/thread/thread_suspendAll.html /library-prerelease/core/thread/thread_suspend_all.html +/library-prerelease/core/thread/Thread.this.html /library-prerelease/core/thread/thread.this.html +/library-prerelease/core/thread/Thread.yield.html /library-prerelease/core/thread/thread.yield.html +/library-prerelease/core/thread/Throwable.file.html /library-prerelease/core/thread/throwable.file.html +/library-prerelease/core/thread/Throwable.info.html /library-prerelease/core/thread/throwable.info.html +/library-prerelease/core/thread/Throwable.line.html /library-prerelease/core/thread/throwable.line.html +/library-prerelease/core/thread/Throwable.msg.html /library-prerelease/core/thread/throwable.msg.html +/library-prerelease/core/thread/Throwable.next.html /library-prerelease/core/thread/throwable.next.html +/library-prerelease/core/thread/Throwable.toString.html /library-prerelease/core/thread/throwable.to_string.html +/library-prerelease/core/time/convClockFreq.html /library-prerelease/core/time/conv_clock_freq.html +/library-prerelease/core/time/Duration.days.html /library-prerelease/core/time/duration.days.html +/library-prerelease/core/time/Duration.fracSec.html /library-prerelease/core/time/duration.frac_sec.html +/library-prerelease/core/time/Duration.get.html /library-prerelease/core/time/duration.get.html +/library-prerelease/core/time/Duration.hours.html /library-prerelease/core/time/duration.hours.html +/library-prerelease/core/time/Duration.html /library-prerelease/core/time/duration.html +/library-prerelease/core/time/Duration.isNegative.html /library-prerelease/core/time/duration.is_negative.html +/library-prerelease/core/time/Duration.max.html /library-prerelease/core/time/duration.max.html +/library-prerelease/core/time/Duration.min.html /library-prerelease/core/time/duration.min.html +/library-prerelease/core/time/Duration.minutes.html /library-prerelease/core/time/duration.minutes.html +/library-prerelease/core/time/Duration.opBinary.html /library-prerelease/core/time/duration.op_binary.html +/library-prerelease/core/time/Duration.opBinaryRight.html /library-prerelease/core/time/duration.op_binary_right.html +/library-prerelease/core/time/Duration.opCast.html /library-prerelease/core/time/duration.op_cast.html +/library-prerelease/core/time/Duration.opCmp.html /library-prerelease/core/time/duration.op_cmp.html +/library-prerelease/core/time/Duration.opOpAssign.html /library-prerelease/core/time/duration.op_op_assign.html +/library-prerelease/core/time/Duration.opUnary.html /library-prerelease/core/time/duration.op_unary.html +/library-prerelease/core/time/Duration.seconds.html /library-prerelease/core/time/duration.seconds.html +/library-prerelease/core/time/Duration.split.html /library-prerelease/core/time/duration.split.html +/library-prerelease/core/time/Duration.split.split.html /library-prerelease/core/time/duration.split.split.html +/library-prerelease/core/time/Duration.toString.html /library-prerelease/core/time/duration.to_string.html +/library-prerelease/core/time/Duration.total.html /library-prerelease/core/time/duration.total.html +/library-prerelease/core/time/Duration.weeks.html /library-prerelease/core/time/duration.weeks.html +/library-prerelease/core/time/Duration.zero.html /library-prerelease/core/time/duration.zero.html +/library-prerelease/core/time/FracSec.from.html /library-prerelease/core/time/frac_sec.from.html +/library-prerelease/core/time/FracSec.hnsecs.html /library-prerelease/core/time/frac_sec.hnsecs.html +/library-prerelease/core/time/FracSec.html /library-prerelease/core/time/frac_sec.html +/library-prerelease/core/time/FracSec.msecs.html /library-prerelease/core/time/frac_sec.msecs.html +/library-prerelease/core/time/FracSec.nsecs.html /library-prerelease/core/time/frac_sec.nsecs.html +/library-prerelease/core/time/FracSec.opUnary.html /library-prerelease/core/time/frac_sec.op_unary.html +/library-prerelease/core/time/FracSec.toString.html /library-prerelease/core/time/frac_sec.to_string.html +/library-prerelease/core/time/FracSec.usecs.html /library-prerelease/core/time/frac_sec.usecs.html +/library-prerelease/core/time/FracSec.zero.html /library-prerelease/core/time/frac_sec.zero.html +/library-prerelease/core/time/MonoTime.currTime.html /library-prerelease/core/time/mono_time.curr_time.html +/library-prerelease/core/time/MonoTime.html /library-prerelease/core/time/mono_time.html +/library-prerelease/core/time/MonoTime.max.html /library-prerelease/core/time/mono_time.max.html +/library-prerelease/core/time/MonoTime.min.html /library-prerelease/core/time/mono_time.min.html +/library-prerelease/core/time/MonoTime.opBinary.html /library-prerelease/core/time/mono_time.op_binary.html +/library-prerelease/core/time/MonoTime.opCmp.html /library-prerelease/core/time/mono_time.op_cmp.html +/library-prerelease/core/time/MonoTime.opOpAssign.html /library-prerelease/core/time/mono_time.op_op_assign.html +/library-prerelease/core/time/MonoTime.ticks.html /library-prerelease/core/time/mono_time.ticks.html +/library-prerelease/core/time/MonoTime.ticksPerSecond.html /library-prerelease/core/time/mono_time.ticks_per_second.html +/library-prerelease/core/time/MonoTime.zero.html /library-prerelease/core/time/mono_time.zero.html +/library-prerelease/core/time/nsecsToTicks.html /library-prerelease/core/time/nsecs_to_ticks.html +/library-prerelease/core/time/Object.factory.html /library-prerelease/core/time/object.factory.html +/library-prerelease/core/time/Object.opCmp.html /library-prerelease/core/time/object.op_cmp.html +/library-prerelease/core/time/Object.opEquals.html /library-prerelease/core/time/object.op_equals.html +/library-prerelease/core/time/Object.toHash.html /library-prerelease/core/time/object.to_hash.html +/library-prerelease/core/time/Throwable.file.html /library-prerelease/core/time/throwable.file.html +/library-prerelease/core/time/Throwable.info.html /library-prerelease/core/time/throwable.info.html +/library-prerelease/core/time/Throwable.line.html /library-prerelease/core/time/throwable.line.html +/library-prerelease/core/time/Throwable.msg.html /library-prerelease/core/time/throwable.msg.html +/library-prerelease/core/time/Throwable.next.html /library-prerelease/core/time/throwable.next.html +/library-prerelease/core/time/Throwable.toString.html /library-prerelease/core/time/throwable.to_string.html +/library-prerelease/core/time/TickDuration.appOrigin.html /library-prerelease/core/time/tick_duration.app_origin.html +/library-prerelease/core/time/TickDuration.currSystemTick.html /library-prerelease/core/time/tick_duration.curr_system_tick.html +/library-prerelease/core/time/TickDuration.from.html /library-prerelease/core/time/tick_duration.from.html +/library-prerelease/core/time/TickDuration.hnsecs.html /library-prerelease/core/time/tick_duration.hnsecs.html +/library-prerelease/core/time/TickDuration.html /library-prerelease/core/time/tick_duration.html +/library-prerelease/core/time/TickDuration.length.html /library-prerelease/core/time/tick_duration.length.html +/library-prerelease/core/time/TickDuration.max.html /library-prerelease/core/time/tick_duration.max.html +/library-prerelease/core/time/TickDuration.min.html /library-prerelease/core/time/tick_duration.min.html +/library-prerelease/core/time/TickDuration.msecs.html /library-prerelease/core/time/tick_duration.msecs.html +/library-prerelease/core/time/TickDuration.nsecs.html /library-prerelease/core/time/tick_duration.nsecs.html +/library-prerelease/core/time/TickDuration.opBinary.html /library-prerelease/core/time/tick_duration.op_binary.html +/library-prerelease/core/time/TickDuration.opCast.html /library-prerelease/core/time/tick_duration.op_cast.html +/library-prerelease/core/time/TickDuration.opCmp.html /library-prerelease/core/time/tick_duration.op_cmp.html +/library-prerelease/core/time/TickDuration.opOpAssign.html /library-prerelease/core/time/tick_duration.op_op_assign.html +/library-prerelease/core/time/TickDuration.opUnary.html /library-prerelease/core/time/tick_duration.op_unary.html +/library-prerelease/core/time/TickDuration.seconds.html /library-prerelease/core/time/tick_duration.seconds.html +/library-prerelease/core/time/TickDuration.this.html /library-prerelease/core/time/tick_duration.this.html +/library-prerelease/core/time/TickDuration.ticksPerSec.html /library-prerelease/core/time/tick_duration.ticks_per_sec.html +/library-prerelease/core/time/TickDuration.usecs.html /library-prerelease/core/time/tick_duration.usecs.html +/library-prerelease/core/time/TickDuration.zero.html /library-prerelease/core/time/tick_duration.zero.html +/library-prerelease/core/time/ticksToNSecs.html /library-prerelease/core/time/ticks_ton_secs.html +/library-prerelease/core/time/TimeException.html /library-prerelease/core/time/time_exception.html +/library-prerelease/core/time/TimeException.this.html /library-prerelease/core/time/time_exception.this.html +/library-prerelease/etc/c/curl/CurlCallbackInfo.html /library-prerelease/etc/c/curl/curl_callback_info.html +/library-prerelease/etc/c/curl/CurlChunkBgnFunc.fail.html /library-prerelease/etc/c/curl/curl_chunk_bgn_func.fail.html +/library-prerelease/etc/c/curl/CurlChunkBgnFunc.html /library-prerelease/etc/c/curl/curl_chunk_bgn_func.html +/library-prerelease/etc/c/curl/CurlChunkBgnFunc.skip.html /library-prerelease/etc/c/curl/curl_chunk_bgn_func.skip.html +/library-prerelease/etc/c/curl/CurlChunkEndFunc.html /library-prerelease/etc/c/curl/curl_chunk_end_func.html +/library-prerelease/etc/c/curl/CurlError.aborted_by_callback.html /library-prerelease/etc/c/curl/curl_error.aborted_by_callback.html +/library-prerelease/etc/c/curl/CurlError.again.html /library-prerelease/etc/c/curl/curl_error.again.html +/library-prerelease/etc/c/curl/CurlError.bad_content_encoding.html /library-prerelease/etc/c/curl/curl_error.bad_content_encoding.html +/library-prerelease/etc/c/curl/CurlError.bad_download_resume.html /library-prerelease/etc/c/curl/curl_error.bad_download_resume.html +/library-prerelease/etc/c/curl/CurlError.bad_function_argument.html /library-prerelease/etc/c/curl/curl_error.bad_function_argument.html +/library-prerelease/etc/c/curl/CurlError.chunk_failed.html /library-prerelease/etc/c/curl/curl_error.chunk_failed.html +/library-prerelease/etc/c/curl/CurlError.conv_failed.html /library-prerelease/etc/c/curl/curl_error.conv_failed.html +/library-prerelease/etc/c/curl/CurlError.conv_reqd.html /library-prerelease/etc/c/curl/curl_error.conv_reqd.html +/library-prerelease/etc/c/curl/CurlError.couldnt_connect.html /library-prerelease/etc/c/curl/curl_error.couldnt_connect.html +/library-prerelease/etc/c/curl/CurlError.couldnt_resolve_host.html /library-prerelease/etc/c/curl/curl_error.couldnt_resolve_host.html +/library-prerelease/etc/c/curl/CurlError.couldnt_resolve_proxy.html /library-prerelease/etc/c/curl/curl_error.couldnt_resolve_proxy.html +/library-prerelease/etc/c/curl/CurlError.curl_last.html /library-prerelease/etc/c/curl/curl_error.curl_last.html +/library-prerelease/etc/c/curl/CurlError.failed_init.html /library-prerelease/etc/c/curl/curl_error.failed_init.html +/library-prerelease/etc/c/curl/CurlError.file_couldnt_read_file.html /library-prerelease/etc/c/curl/curl_error.file_couldnt_read_file.html +/library-prerelease/etc/c/curl/CurlError.filesize_exceeded.html /library-prerelease/etc/c/curl/curl_error.filesize_exceeded.html +/library-prerelease/etc/c/curl/CurlError.ftp_bad_file_list.html /library-prerelease/etc/c/curl/curl_error.ftp_bad_file_list.html +/library-prerelease/etc/c/curl/CurlError.ftp_cant_get_host.html /library-prerelease/etc/c/curl/curl_error.ftp_cant_get_host.html +/library-prerelease/etc/c/curl/CurlError.ftp_couldnt_retr_file.html /library-prerelease/etc/c/curl/curl_error.ftp_couldnt_retr_file.html +/library-prerelease/etc/c/curl/CurlError.ftp_couldnt_set_type.html /library-prerelease/etc/c/curl/curl_error.ftp_couldnt_set_type.html +/library-prerelease/etc/c/curl/CurlError.ftp_couldnt_use_rest.html /library-prerelease/etc/c/curl/curl_error.ftp_couldnt_use_rest.html +/library-prerelease/etc/c/curl/CurlError.ftp_port_failed.html /library-prerelease/etc/c/curl/curl_error.ftp_port_failed.html +/library-prerelease/etc/c/curl/CurlError.ftp_pret_failed.html /library-prerelease/etc/c/curl/curl_error.ftp_pret_failed.html +/library-prerelease/etc/c/curl/CurlError.ftp_weird_227_format.html /library-prerelease/etc/c/curl/curl_error.ftp_weird_227_format.html +/library-prerelease/etc/c/curl/CurlError.ftp_weird_pass_reply.html /library-prerelease/etc/c/curl/curl_error.ftp_weird_pass_reply.html +/library-prerelease/etc/c/curl/CurlError.ftp_weird_pasv_reply.html /library-prerelease/etc/c/curl/curl_error.ftp_weird_pasv_reply.html +/library-prerelease/etc/c/curl/CurlError.ftp_weird_server_reply.html /library-prerelease/etc/c/curl/curl_error.ftp_weird_server_reply.html +/library-prerelease/etc/c/curl/CurlError.function_not_found.html /library-prerelease/etc/c/curl/curl_error.function_not_found.html +/library-prerelease/etc/c/curl/CurlError.got_nothing.html /library-prerelease/etc/c/curl/curl_error.got_nothing.html +/library-prerelease/etc/c/curl/CurlError.html /library-prerelease/etc/c/curl/curl_error.html +/library-prerelease/etc/c/curl/CurlError.http_post_error.html /library-prerelease/etc/c/curl/curl_error.http_post_error.html +/library-prerelease/etc/c/curl/CurlError.http_returned_error.html /library-prerelease/etc/c/curl/curl_error.http_returned_error.html +/library-prerelease/etc/c/curl/CurlError.interface_failed.html /library-prerelease/etc/c/curl/curl_error.interface_failed.html +/library-prerelease/etc/c/curl/CurlError.ldap_cannot_bind.html /library-prerelease/etc/c/curl/curl_error.ldap_cannot_bind.html +/library-prerelease/etc/c/curl/CurlError.ldap_invalid_url.html /library-prerelease/etc/c/curl/curl_error.ldap_invalid_url.html +/library-prerelease/etc/c/curl/CurlError.ldap_search_failed.html /library-prerelease/etc/c/curl/curl_error.ldap_search_failed.html +/library-prerelease/etc/c/curl/CurlError.login_denied.html /library-prerelease/etc/c/curl/curl_error.login_denied.html +/library-prerelease/etc/c/curl/CurlError.obsolete10.html /library-prerelease/etc/c/curl/curl_error.obsolete10.html +/library-prerelease/etc/c/curl/CurlError.obsolete12.html /library-prerelease/etc/c/curl/curl_error.obsolete12.html +/library-prerelease/etc/c/curl/CurlError.obsolete16.html /library-prerelease/etc/c/curl/curl_error.obsolete16.html +/library-prerelease/etc/c/curl/CurlError.obsolete20.html /library-prerelease/etc/c/curl/curl_error.obsolete20.html +/library-prerelease/etc/c/curl/CurlError.obsolete24.html /library-prerelease/etc/c/curl/curl_error.obsolete24.html +/library-prerelease/etc/c/curl/CurlError.obsolete29.html /library-prerelease/etc/c/curl/curl_error.obsolete29.html +/library-prerelease/etc/c/curl/CurlError.obsolete32.html /library-prerelease/etc/c/curl/curl_error.obsolete32.html +/library-prerelease/etc/c/curl/CurlError.obsolete40.html /library-prerelease/etc/c/curl/curl_error.obsolete40.html +/library-prerelease/etc/c/curl/CurlError.obsolete44.html /library-prerelease/etc/c/curl/curl_error.obsolete44.html +/library-prerelease/etc/c/curl/CurlError.obsolete46.html /library-prerelease/etc/c/curl/curl_error.obsolete46.html +/library-prerelease/etc/c/curl/CurlError.obsolete4.html /library-prerelease/etc/c/curl/curl_error.obsolete4.html +/library-prerelease/etc/c/curl/CurlError.obsolete50.html /library-prerelease/etc/c/curl/curl_error.obsolete50.html +/library-prerelease/etc/c/curl/CurlError.obsolete57.html /library-prerelease/etc/c/curl/curl_error.obsolete57.html +/library-prerelease/etc/c/curl/CurlError.operation_timedout.html /library-prerelease/etc/c/curl/curl_error.operation_timedout.html +/library-prerelease/etc/c/curl/CurlError.out_of_memory.html /library-prerelease/etc/c/curl/curl_error.out_of_memory.html +/library-prerelease/etc/c/curl/CurlError.partial_file.html /library-prerelease/etc/c/curl/curl_error.partial_file.html +/library-prerelease/etc/c/curl/CurlError.peer_failed_verification.html /library-prerelease/etc/c/curl/curl_error.peer_failed_verification.html +/library-prerelease/etc/c/curl/CurlError.quote_error.html /library-prerelease/etc/c/curl/curl_error.quote_error.html +/library-prerelease/etc/c/curl/CurlError.range_error.html /library-prerelease/etc/c/curl/curl_error.range_error.html +/library-prerelease/etc/c/curl/CurlError.read_error.html /library-prerelease/etc/c/curl/curl_error.read_error.html +/library-prerelease/etc/c/curl/CurlError.recv_error.html /library-prerelease/etc/c/curl/curl_error.recv_error.html +/library-prerelease/etc/c/curl/CurlError.remote_access_denied.html /library-prerelease/etc/c/curl/curl_error.remote_access_denied.html +/library-prerelease/etc/c/curl/CurlError.remote_disk_full.html /library-prerelease/etc/c/curl/curl_error.remote_disk_full.html +/library-prerelease/etc/c/curl/CurlError.remote_file_exists.html /library-prerelease/etc/c/curl/curl_error.remote_file_exists.html +/library-prerelease/etc/c/curl/CurlError.remote_file_not_found.html /library-prerelease/etc/c/curl/curl_error.remote_file_not_found.html +/library-prerelease/etc/c/curl/CurlError.rtsp_cseq_error.html /library-prerelease/etc/c/curl/curl_error.rtsp_cseq_error.html +/library-prerelease/etc/c/curl/CurlError.rtsp_session_error.html /library-prerelease/etc/c/curl/curl_error.rtsp_session_error.html +/library-prerelease/etc/c/curl/CurlError.send_error.html /library-prerelease/etc/c/curl/curl_error.send_error.html +/library-prerelease/etc/c/curl/CurlError.send_fail_rewind.html /library-prerelease/etc/c/curl/curl_error.send_fail_rewind.html +/library-prerelease/etc/c/curl/CurlError.ssh.html /library-prerelease/etc/c/curl/curl_error.ssh.html +/library-prerelease/etc/c/curl/CurlError.ssl_cacert_badfile.html /library-prerelease/etc/c/curl/curl_error.ssl_cacert_badfile.html +/library-prerelease/etc/c/curl/CurlError.ssl_cacert.html /library-prerelease/etc/c/curl/curl_error.ssl_cacert.html +/library-prerelease/etc/c/curl/CurlError.ssl_certproblem.html /library-prerelease/etc/c/curl/curl_error.ssl_certproblem.html +/library-prerelease/etc/c/curl/CurlError.ssl_cipher.html /library-prerelease/etc/c/curl/curl_error.ssl_cipher.html +/library-prerelease/etc/c/curl/CurlError.ssl_connect_error.html /library-prerelease/etc/c/curl/curl_error.ssl_connect_error.html +/library-prerelease/etc/c/curl/CurlError.ssl_crl_badfile.html /library-prerelease/etc/c/curl/curl_error.ssl_crl_badfile.html +/library-prerelease/etc/c/curl/CurlError.ssl_engine_initfailed.html /library-prerelease/etc/c/curl/curl_error.ssl_engine_initfailed.html +/library-prerelease/etc/c/curl/CurlError.ssl_engine_notfound.html /library-prerelease/etc/c/curl/curl_error.ssl_engine_notfound.html +/library-prerelease/etc/c/curl/CurlError.ssl_engine_setfailed.html /library-prerelease/etc/c/curl/curl_error.ssl_engine_setfailed.html +/library-prerelease/etc/c/curl/CurlError.ssl_issuer_error.html /library-prerelease/etc/c/curl/curl_error.ssl_issuer_error.html +/library-prerelease/etc/c/curl/CurlError.ssl_shutdown_failed.html /library-prerelease/etc/c/curl/curl_error.ssl_shutdown_failed.html +/library-prerelease/etc/c/curl/CurlError.telnet_option_syntax.html /library-prerelease/etc/c/curl/curl_error.telnet_option_syntax.html +/library-prerelease/etc/c/curl/CurlError.tftp_illegal.html /library-prerelease/etc/c/curl/curl_error.tftp_illegal.html +/library-prerelease/etc/c/curl/CurlError.tftp_nosuchuser.html /library-prerelease/etc/c/curl/curl_error.tftp_nosuchuser.html +/library-prerelease/etc/c/curl/CurlError.tftp_notfound.html /library-prerelease/etc/c/curl/curl_error.tftp_notfound.html +/library-prerelease/etc/c/curl/CurlError.tftp_perm.html /library-prerelease/etc/c/curl/curl_error.tftp_perm.html +/library-prerelease/etc/c/curl/CurlError.tftp_unknownid.html /library-prerelease/etc/c/curl/curl_error.tftp_unknownid.html +/library-prerelease/etc/c/curl/CurlError.too_many_redirects.html /library-prerelease/etc/c/curl/curl_error.too_many_redirects.html +/library-prerelease/etc/c/curl/CurlError.unknown_telnet_option.html /library-prerelease/etc/c/curl/curl_error.unknown_telnet_option.html +/library-prerelease/etc/c/curl/CurlError.unsupported_protocol.html /library-prerelease/etc/c/curl/curl_error.unsupported_protocol.html +/library-prerelease/etc/c/curl/CurlError.upload_failed.html /library-prerelease/etc/c/curl/curl_error.upload_failed.html +/library-prerelease/etc/c/curl/CurlError.url_malformat.html /library-prerelease/etc/c/curl/curl_error.url_malformat.html +/library-prerelease/etc/c/curl/CurlError.use_ssl_failed.html /library-prerelease/etc/c/curl/curl_error.use_ssl_failed.html +/library-prerelease/etc/c/curl/CurlError.write_error.html /library-prerelease/etc/c/curl/curl_error.write_error.html +/library-prerelease/etc/c/curl/CurlFileType.html /library-prerelease/etc/c/curl/curl_file_type.html +/library-prerelease/etc/c/curl/CurlFileType.unknown.html /library-prerelease/etc/c/curl/curl_file_type.unknown.html +/library-prerelease/etc/c/curl/CurlFnMAtchFunc.html /library-prerelease/etc/c/curl/curl_fnm_atch_func.html +/library-prerelease/etc/c/curl/CurlFormAdd.disabled.html /library-prerelease/etc/c/curl/curl_form_add.disabled.html +/library-prerelease/etc/c/curl/CurlFormAdd.html /library-prerelease/etc/c/curl/curl_form_add.html +/library-prerelease/etc/c/curl/CurlFormAdd.ok.html /library-prerelease/etc/c/curl/curl_form_add.ok.html +/library-prerelease/etc/c/curl/CurlFtpAuth.defaultauth.html /library-prerelease/etc/c/curl/curl_ftp_auth.defaultauth.html +/library-prerelease/etc/c/curl/CurlFtpAuth.html /library-prerelease/etc/c/curl/curl_ftp_auth.html +/library-prerelease/etc/c/curl/CurlFtpAuth.last.html /library-prerelease/etc/c/curl/curl_ftp_auth.last.html +/library-prerelease/etc/c/curl/CurlFtpAuth.ssl.html /library-prerelease/etc/c/curl/curl_ftp_auth.ssl.html +/library-prerelease/etc/c/curl/CurlFtpAuth.tls.html /library-prerelease/etc/c/curl/curl_ftp_auth.tls.html +/library-prerelease/etc/c/curl/CurlFtp.create_dir.html /library-prerelease/etc/c/curl/curl_ftp.create_dir.html +/library-prerelease/etc/c/curl/CurlFtp.create_dir_last.html /library-prerelease/etc/c/curl/curl_ftp.create_dir_last.html +/library-prerelease/etc/c/curl/CurlFtp.create_dir_none.html /library-prerelease/etc/c/curl/curl_ftp.create_dir_none.html +/library-prerelease/etc/c/curl/CurlFtp.create_dir_retry.html /library-prerelease/etc/c/curl/curl_ftp.create_dir_retry.html +/library-prerelease/etc/c/curl/CurlFtp.html /library-prerelease/etc/c/curl/curl_ftp.html +/library-prerelease/etc/c/curl/CurlFtpMethod.defaultmethod.html /library-prerelease/etc/c/curl/curl_ftp_method.defaultmethod.html +/library-prerelease/etc/c/curl/CurlFtpMethod.html /library-prerelease/etc/c/curl/curl_ftp_method.html +/library-prerelease/etc/c/curl/CurlFtpMethod.last.html /library-prerelease/etc/c/curl/curl_ftp_method.last.html +/library-prerelease/etc/c/curl/CurlFtpMethod.multicwd.html /library-prerelease/etc/c/curl/curl_ftp_method.multicwd.html +/library-prerelease/etc/c/curl/CurlFtpMethod.nocwd.html /library-prerelease/etc/c/curl/curl_ftp_method.nocwd.html +/library-prerelease/etc/c/curl/CurlFtpMethod.singlecwd.html /library-prerelease/etc/c/curl/curl_ftp_method.singlecwd.html +/library-prerelease/etc/c/curl/CurlFtpSSL.ccc_active.html /library-prerelease/etc/c/curl/curl_ftp_ssl.ccc_active.html +/library-prerelease/etc/c/curl/CurlFtpSSL.ccc_last.html /library-prerelease/etc/c/curl/curl_ftp_ssl.ccc_last.html +/library-prerelease/etc/c/curl/CurlFtpSSL.ccc_none.html /library-prerelease/etc/c/curl/curl_ftp_ssl.ccc_none.html +/library-prerelease/etc/c/curl/CurlFtpSSL.ccc_passive.html /library-prerelease/etc/c/curl/curl_ftp_ssl.ccc_passive.html +/library-prerelease/etc/c/curl/CurlFtpSSL.html /library-prerelease/etc/c/curl/curl_ftp_ssl.html +/library-prerelease/etc/c/curl/CurlHttpVersion.html /library-prerelease/etc/c/curl/curl_http_version.html +/library-prerelease/etc/c/curl/CurlHttpVersion.last.html /library-prerelease/etc/c/curl/curl_http_version.last.html +/library-prerelease/etc/c/curl/CurlHttpVersion.none.html /library-prerelease/etc/c/curl/curl_http_version.none.html +/library-prerelease/etc/c/curl/CurlHttpVersion.v1_0.html /library-prerelease/etc/c/curl/curl_http_version.v1_0.html +/library-prerelease/etc/c/curl/CurlHttpVersion.v1_1.html /library-prerelease/etc/c/curl/curl_http_version.v1_1.html +/library-prerelease/etc/c/curl/CURLINFO_HTTP_CODE.html /library-prerelease/etc/c/curl/curlinf_o_htt_p_code.html +/library-prerelease/etc/c/curl/CurlIpResolve.html /library-prerelease/etc/c/curl/curl_ip_resolve.html +/library-prerelease/etc/c/curl/CurlIpResolve.v4.html /library-prerelease/etc/c/curl/curl_ip_resolve.v4.html +/library-prerelease/etc/c/curl/CurlIpResolve.v6.html /library-prerelease/etc/c/curl/curl_ip_resolve.v6.html +/library-prerelease/etc/c/curl/CurlIpResolve.whatever.html /library-prerelease/etc/c/curl/curl_ip_resolve.whatever.html +/library-prerelease/etc/c/curl/CurlKHMatch.html /library-prerelease/etc/c/curl/curl_kh_match.html +/library-prerelease/etc/c/curl/CurlKHMatch.last.html /library-prerelease/etc/c/curl/curl_kh_match.last.html +/library-prerelease/etc/c/curl/CurlKHMatch.mismatch.html /library-prerelease/etc/c/curl/curl_kh_match.mismatch.html +/library-prerelease/etc/c/curl/CurlKHMatch.missing.html /library-prerelease/etc/c/curl/curl_kh_match.missing.html +/library-prerelease/etc/c/curl/CurlKHMatch.ok.html /library-prerelease/etc/c/curl/curl_kh_match.ok.html +/library-prerelease/etc/c/curl/CurlKHStat.defer.html /library-prerelease/etc/c/curl/curl_kh_stat.defer.html +/library-prerelease/etc/c/curl/CurlKHStat.html /library-prerelease/etc/c/curl/curl_kh_stat.html +/library-prerelease/etc/c/curl/CurlKHStat.last.html /library-prerelease/etc/c/curl/curl_kh_stat.last.html +/library-prerelease/etc/c/curl/CurlKHStat.reject.html /library-prerelease/etc/c/curl/curl_kh_stat.reject.html +/library-prerelease/etc/c/curl/CurlKHType.html /library-prerelease/etc/c/curl/curl_kh_type.html +/library-prerelease/etc/c/curl/CurlLockAccess.html /library-prerelease/etc/c/curl/curl_lock_access.html +/library-prerelease/etc/c/curl/CurlLockAccess.last.html /library-prerelease/etc/c/curl/curl_lock_access.last.html +/library-prerelease/etc/c/curl/CurlLockAccess.none.html /library-prerelease/etc/c/curl/curl_lock_access.none.html +/library-prerelease/etc/c/curl/CurlLockAccess.shared_access.html /library-prerelease/etc/c/curl/curl_lock_access.shared_access.html +/library-prerelease/etc/c/curl/CurlLockAccess.single.html /library-prerelease/etc/c/curl/curl_lock_access.single.html +/library-prerelease/etc/c/curl/CurlLockData.html /library-prerelease/etc/c/curl/curl_lock_data.html +/library-prerelease/etc/c/curl/CurlLockData.share.html /library-prerelease/etc/c/curl/curl_lock_data.share.html +/library-prerelease/etc/c/curl/CURL_MAX_HTTP_HEADER.html /library-prerelease/etc/c/curl/cur_l_ma_x_htt_p_header.html +/library-prerelease/etc/c/curl/CURL_MAX_WRITE_SIZE.html /library-prerelease/etc/c/curl/cur_l_ma_x_writ_e_size.html +/library-prerelease/etc/c/curl/CURLM_CALL_MULTI_SOCKET.html /library-prerelease/etc/c/curl/curl_m_cal_l_mult_i_socket.html +/library-prerelease/etc/c/curl/CurlNetRcOption.html /library-prerelease/etc/c/curl/curl_net_rc_option.html +/library-prerelease/etc/c/curl/CurlNetRcOption.ignored.html /library-prerelease/etc/c/curl/curl_net_rc_option.ignored.html +/library-prerelease/etc/c/curl/CurlNetRcOption.optional.html /library-prerelease/etc/c/curl/curl_net_rc_option.optional.html +/library-prerelease/etc/c/curl/CurlNetRcOption.required.html /library-prerelease/etc/c/curl/curl_net_rc_option.required.html +/library-prerelease/etc/c/curl/CURLOPT_HEADERDATA.html /library-prerelease/etc/c/curl/curlop_t_headerdata.html +/library-prerelease/etc/c/curl/CURLOPT_READDATA.html /library-prerelease/etc/c/curl/curlop_t_readdata.html +/library-prerelease/etc/c/curl/CURLOPT_RTSPHEADER.html /library-prerelease/etc/c/curl/curlop_t_rtspheader.html +/library-prerelease/etc/c/curl/CURLOPTTYPE_FUNCTIONPOINT.html /library-prerelease/etc/c/curl/curlopttyp_e_functionpoint.html +/library-prerelease/etc/c/curl/CURLOPTTYPE_LONG.html /library-prerelease/etc/c/curl/curlopttyp_e_long.html +/library-prerelease/etc/c/curl/CURLOPTTYPE_OBJECTPOINT.html /library-prerelease/etc/c/curl/curlopttyp_e_objectpoint.html +/library-prerelease/etc/c/curl/CURLOPTTYPE_OFF_T.html /library-prerelease/etc/c/curl/curlopttyp_e_of_f_t.html +/library-prerelease/etc/c/curl/CURLOPT_WRITEDATA.html /library-prerelease/etc/c/curl/curlop_t_writedata.html +/library-prerelease/etc/c/curl/CurlPoll.html /library-prerelease/etc/c/curl/curl_poll.html +/library-prerelease/etc/c/curl/CurlPoll.none_.html /library-prerelease/etc/c/curl/curl_poll.none_.html +/library-prerelease/etc/c/curl/CurlProto.all.html /library-prerelease/etc/c/curl/curl_proto.all.html +/library-prerelease/etc/c/curl/CurlProto.html /library-prerelease/etc/c/curl/curl_proto.html +/library-prerelease/etc/c/curl/CurlRedir.html /library-prerelease/etc/c/curl/curl_redir.html +/library-prerelease/etc/c/curl/CurlRtspReq.html /library-prerelease/etc/c/curl/curl_rtsp_req.html +/library-prerelease/etc/c/curl/CurlSeek.cantseek.html /library-prerelease/etc/c/curl/curl_seek.cantseek.html +/library-prerelease/etc/c/curl/CurlSeek.fail.html /library-prerelease/etc/c/curl/curl_seek.fail.html +/library-prerelease/etc/c/curl/CurlSeek.html /library-prerelease/etc/c/curl/curl_seek.html +/library-prerelease/etc/c/curl/CurlSeekPos.html /library-prerelease/etc/c/curl/curl_seek_pos.html +/library-prerelease/etc/c/curl/CurlShOption.html /library-prerelease/etc/c/curl/curl_sh_option.html +/library-prerelease/etc/c/curl/CurlShOption.last.html /library-prerelease/etc/c/curl/curl_sh_option.last.html +/library-prerelease/etc/c/curl/CurlShOption.lockfunc.html /library-prerelease/etc/c/curl/curl_sh_option.lockfunc.html +/library-prerelease/etc/c/curl/CurlShOption.none.html /library-prerelease/etc/c/curl/curl_sh_option.none.html +/library-prerelease/etc/c/curl/CurlShOption.share.html /library-prerelease/etc/c/curl/curl_sh_option.share.html +/library-prerelease/etc/c/curl/CurlShOption.unlockfunc.html /library-prerelease/etc/c/curl/curl_sh_option.unlockfunc.html +/library-prerelease/etc/c/curl/CurlShOption.unshare.html /library-prerelease/etc/c/curl/curl_sh_option.unshare.html +/library-prerelease/etc/c/curl/CurlShOption.userdata.html /library-prerelease/etc/c/curl/curl_sh_option.userdata.html +/library-prerelease/etc/c/curl/CurlUseSSL.all.html /library-prerelease/etc/c/curl/curl_use_ssl.all.html +/library-prerelease/etc/c/curl/CurlUseSSL.control.html /library-prerelease/etc/c/curl/curl_use_ssl.control.html +/library-prerelease/etc/c/curl/CurlUseSSL.html /library-prerelease/etc/c/curl/curl_use_ssl.html +/library-prerelease/etc/c/curl/CurlUseSSL.last.html /library-prerelease/etc/c/curl/curl_use_ssl.last.html +/library-prerelease/etc/c/curl/CurlUseSSL.none.html /library-prerelease/etc/c/curl/curl_use_ssl.none.html +/library-prerelease/etc/c/curl/CurlUseSSL.tryssl.html /library-prerelease/etc/c/curl/curl_use_ssl.tryssl.html +/library-prerelease/etc/c/curl/CurlVer.html /library-prerelease/etc/c/curl/curl_ver.html +/library-prerelease/etc/c/curl/CURLVERSION_NOW.html /library-prerelease/etc/c/curl/curlversio_n_now.html +/library-prerelease/etc/c/curl/CURL_WRITEFUNC_PAUSE.html /library-prerelease/etc/c/curl/cur_l_writefun_c_pause.html +/library-prerelease/etc/c/curl/FUNCTIONPOINT.html /library-prerelease/etc/c/curl/functionpoint.html +/library-prerelease/etc/c/curl/HTTPPOST_BUFFER.html /library-prerelease/etc/c/curl/httppos_t_buffer.html +/library-prerelease/etc/c/curl/HTTPPOST_CALLBACK.html /library-prerelease/etc/c/curl/httppos_t_callback.html +/library-prerelease/etc/c/curl/HTTPPOST_FILENAME.html /library-prerelease/etc/c/curl/httppos_t_filename.html +/library-prerelease/etc/c/curl/HTTPPOST_PTRBUFFER.html /library-prerelease/etc/c/curl/httppos_t_ptrbuffer.html +/library-prerelease/etc/c/curl/HTTPPOST_PTRCONTENTS.html /library-prerelease/etc/c/curl/httppos_t_ptrcontents.html +/library-prerelease/etc/c/curl/HTTPPOST_PTRNAME.html /library-prerelease/etc/c/curl/httppos_t_ptrname.html +/library-prerelease/etc/c/curl/HTTPPOST_READFILE.html /library-prerelease/etc/c/curl/httppos_t_readfile.html +/library-prerelease/etc/c/curl/LIBCURL_COPYRIGHT.html /library-prerelease/etc/c/curl/libcur_l_copyright.html +/library-prerelease/etc/c/curl/LIBCURL_TIMESTAMP.html /library-prerelease/etc/c/curl/libcur_l_timestamp.html +/library-prerelease/etc/c/curl/LIBCURL_VERSION.html /library-prerelease/etc/c/curl/libcur_l_version.html +/library-prerelease/etc/c/curl/LIBCURL_VERSION_MAJOR.html /library-prerelease/etc/c/curl/libcur_l_versio_n_major.html +/library-prerelease/etc/c/curl/LIBCURL_VERSION_MINOR.html /library-prerelease/etc/c/curl/libcur_l_versio_n_minor.html +/library-prerelease/etc/c/curl/LIBCURL_VERSION_NUM.html /library-prerelease/etc/c/curl/libcur_l_versio_n_num.html +/library-prerelease/etc/c/curl/LIBCURL_VERSION_PATCH.html /library-prerelease/etc/c/curl/libcur_l_versio_n_patch.html +/library-prerelease/etc/c/curl/LONG.html /library-prerelease/etc/c/curl/long.html +/library-prerelease/etc/c/curl/_N2.html /library-prerelease/etc/c/curl/__n2.html +/library-prerelease/etc/c/curl/_N2.target.html /library-prerelease/etc/c/curl/__n2.target.html +/library-prerelease/etc/c/curl/OBJECTPOINT.html /library-prerelease/etc/c/curl/objectpoint.html +/library-prerelease/etc/c/curl/OFF_T.html /library-prerelease/etc/c/curl/of_f_t.html +/library-prerelease/object/_ArrayEq.html /library-prerelease/object/__array_eq.html +/library-prerelease/object/assumeSafeAppend.html /library-prerelease/object/assume_safe_append.html +/library-prerelease/object/Classinfo.html /library-prerelease/object/classinfo.html +/library-prerelease/object/_d_traceContext.html /library-prerelease/object/_d_trace_context.html +/library-prerelease/object/Error.bypassedException.html /library-prerelease/object/error.bypassed_exception.html +/library-prerelease/object/Error.html /library-prerelease/object/error.html +/library-prerelease/object/Error.this.html /library-prerelease/object/error.this.html +/library-prerelease/object/Exception.html /library-prerelease/object/exception.html +/library-prerelease/object/Exception.this.html /library-prerelease/object/exception.this.html +/library-prerelease/object/Interface.classinfo.html /library-prerelease/object/interface.classinfo.html +/library-prerelease/object/Interface.html /library-prerelease/object/interface.html +/library-prerelease/object/Interface.offset.html /library-prerelease/object/interface.offset.html +/library-prerelease/object/Object.factory.html /library-prerelease/object/object.factory.html +/library-prerelease/object/Object.html /library-prerelease/object/object.html +/library-prerelease/object/Object.opCmp.html /library-prerelease/object/object.op_cmp.html +/library-prerelease/object/Object.opEquals.html /library-prerelease/object/object.op_equals.html +/library-prerelease/object/Object.toHash.html /library-prerelease/object/object.to_hash.html +/library-prerelease/object/Object.toString.html /library-prerelease/object/object.to_string.html +/library-prerelease/object/OffsetTypeInfo.html /library-prerelease/object/offset_type_info.html +/library-prerelease/object/OffsetTypeInfo.offset.html /library-prerelease/object/offset_type_info.offset.html +/library-prerelease/object/OffsetTypeInfo.ti.html /library-prerelease/object/offset_type_info.ti.html +/library-prerelease/object/opEquals.html /library-prerelease/object/op_equals.html +/library-prerelease/object/rt_getTraceHandler.html /library-prerelease/object/rt_get_trace_handler.html +/library-prerelease/object/RTInfo.html /library-prerelease/object/rt_info.html +/library-prerelease/object/rt_setTraceHandler.html /library-prerelease/object/rt_set_trace_handler.html +/library-prerelease/object/Throwable.file.html /library-prerelease/object/throwable.file.html +/library-prerelease/object/Throwable.html /library-prerelease/object/throwable.html +/library-prerelease/object/Throwable.info.html /library-prerelease/object/throwable.info.html +/library-prerelease/object/Throwable.line.html /library-prerelease/object/throwable.line.html +/library-prerelease/object/Throwable.msg.html /library-prerelease/object/throwable.msg.html +/library-prerelease/object/Throwable.next.html /library-prerelease/object/throwable.next.html +/library-prerelease/object/Throwable.toString.html /library-prerelease/object/throwable.to_string.html +/library-prerelease/object/TypeInfo.argTypes.html /library-prerelease/object/type_info.arg_types.html +/library-prerelease/object/TypeInfo_Class.base.html /library-prerelease/object/type_info__class.base.html +/library-prerelease/object/TypeInfo_Class.create.html /library-prerelease/object/type_info__class.create.html +/library-prerelease/object/TypeInfo_Class.find.html /library-prerelease/object/type_info__class.find.html +/library-prerelease/object/TypeInfo_Class.html /library-prerelease/object/type_info__class.html +/library-prerelease/object/TypeInfo_Class.init.html /library-prerelease/object/type_info__class.init.html +/library-prerelease/object/TypeInfo_Class.interfaces.html /library-prerelease/object/type_info__class.interfaces.html +/library-prerelease/object/TypeInfo_Class.name.html /library-prerelease/object/type_info__class.name.html +/library-prerelease/object/TypeInfo_Class.vtbl.html /library-prerelease/object/type_info__class.vtbl.html +/library-prerelease/object/TypeInfo.compare.html /library-prerelease/object/type_info.compare.html +/library-prerelease/object/TypeInfo.destroy.html /library-prerelease/object/type_info.destroy.html +/library-prerelease/object/TypeInfo.equals.html /library-prerelease/object/type_info.equals.html +/library-prerelease/object/TypeInfo.flags.html /library-prerelease/object/type_info.flags.html +/library-prerelease/object/TypeInfo.getHash.html /library-prerelease/object/type_info.get_hash.html +/library-prerelease/object/TypeInfo.html /library-prerelease/object/type_info.html +/library-prerelease/object/TypeInfo.init.html /library-prerelease/object/type_info.init.html +/library-prerelease/object/TypeInfo.next.html /library-prerelease/object/type_info.next.html +/library-prerelease/object/TypeInfo.offTi.html /library-prerelease/object/type_info.off_ti.html +/library-prerelease/object/TypeInfo.postblit.html /library-prerelease/object/type_info.postblit.html +/library-prerelease/object/TypeInfo.rtInfo.html /library-prerelease/object/type_info.rt_info.html +/library-prerelease/object/TypeInfo.swap.html /library-prerelease/object/type_info.swap.html +/library-prerelease/object/TypeInfo.talign.html /library-prerelease/object/type_info.talign.html +/library-prerelease/object/TypeInfo.tsize.html /library-prerelease/object/type_info.tsize.html +/library-prerelease/std/algorithm/comparison/castSwitch.html /library-prerelease/std/algorithm/comparison/cast_switch.html +/library-prerelease/std/algorithm/comparison/EditOp.html /library-prerelease/std/algorithm/comparison/edit_op.html +/library-prerelease/std/algorithm/comparison/EditOp.insert.html /library-prerelease/std/algorithm/comparison/edit_op.insert.html +/library-prerelease/std/algorithm/comparison/EditOp.none.html /library-prerelease/std/algorithm/comparison/edit_op.none.html +/library-prerelease/std/algorithm/comparison/EditOp.remove.html /library-prerelease/std/algorithm/comparison/edit_op.remove.html +/library-prerelease/std/algorithm/comparison/EditOp.substitute.html /library-prerelease/std/algorithm/comparison/edit_op.substitute.html +/library-prerelease/std/algorithm/comparison/levenshteinDistanceAndPath.html /library-prerelease/std/algorithm/comparison/levenshtein_distance_and_path.html +/library-prerelease/std/algorithm/comparison/levenshteinDistance.html /library-prerelease/std/algorithm/comparison/levenshtein_distance.html +/library-prerelease/std/algorithm/comparison/predSwitch.html /library-prerelease/std/algorithm/comparison/pred_switch.html +/library-prerelease/std/algorithm/iteration/cacheBidirectional.html /library-prerelease/std/algorithm/iteration/cache_bidirectional.html +/library-prerelease/std/algorithm/iteration/chunkBy.html /library-prerelease/std/algorithm/iteration/chunk_by.html +/library-prerelease/std/algorithm/iteration/filterBidirectional.filterBidirectional.html /library-prerelease/std/algorithm/iteration/filter_bidirectional.filter_bidirectional.html +/library-prerelease/std/algorithm/iteration/filterBidirectional.html /library-prerelease/std/algorithm/iteration/filter_bidirectional.html +/library-prerelease/std/algorithm/mutation/bringToFront.html /library-prerelease/std/algorithm/mutation/bring_to_front.html +/library-prerelease/std/algorithm/mutation/initializeAll.html /library-prerelease/std/algorithm/mutation/initialize_all.html +/library-prerelease/std/algorithm/mutation/moveAll.html /library-prerelease/std/algorithm/mutation/move_all.html +/library-prerelease/std/algorithm/mutation/moveSome.html /library-prerelease/std/algorithm/mutation/move_some.html +/library-prerelease/std/algorithm/mutation/stripLeft.html /library-prerelease/std/algorithm/mutation/strip_left.html +/library-prerelease/std/algorithm/mutation/stripRight.html /library-prerelease/std/algorithm/mutation/strip_right.html +/library-prerelease/std/algorithm/mutation/swapRanges.html /library-prerelease/std/algorithm/mutation/swap_ranges.html +/library-prerelease/std/algorithm/mutation/SwapStrategy.html /library-prerelease/std/algorithm/mutation/swap_strategy.html +/library-prerelease/std/algorithm/mutation/SwapStrategy.semistable.html /library-prerelease/std/algorithm/mutation/swap_strategy.semistable.html +/library-prerelease/std/algorithm/mutation/SwapStrategy.stable.html /library-prerelease/std/algorithm/mutation/swap_strategy.stable.html +/library-prerelease/std/algorithm/mutation/SwapStrategy.unstable.html /library-prerelease/std/algorithm/mutation/swap_strategy.unstable.html +/library-prerelease/std/algorithm/mutation/uninitializedFill.html /library-prerelease/std/algorithm/mutation/uninitialized_fill.html +/library-prerelease/std/algorithm/searching/balancedParens.html /library-prerelease/std/algorithm/searching/balanced_parens.html +/library-prerelease/std/algorithm/searching/boyerMooreFinder.html /library-prerelease/std/algorithm/searching/boyer_moore_finder.html +/library-prerelease/std/algorithm/searching/BoyerMooreFinder.html /library-prerelease/std/algorithm/searching/boyer_moore_finder.html +/library-prerelease/std/algorithm/searching/canFind.canFind.html /library-prerelease/std/algorithm/searching/can_find.can_find.html +/library-prerelease/std/algorithm/searching/canFind.html /library-prerelease/std/algorithm/searching/can_find.html +/library-prerelease/std/algorithm/searching/commonPrefix.html /library-prerelease/std/algorithm/searching/common_prefix.html +/library-prerelease/std/algorithm/searching/countUntil.html /library-prerelease/std/algorithm/searching/count_until.html +/library-prerelease/std/algorithm/searching/endsWith.html /library-prerelease/std/algorithm/searching/ends_with.html +/library-prerelease/std/algorithm/searching/findAdjacent.html /library-prerelease/std/algorithm/searching/find_adjacent.html +/library-prerelease/std/algorithm/searching/findAmong.html /library-prerelease/std/algorithm/searching/find_among.html +/library-prerelease/std/algorithm/searching/findSkip.html /library-prerelease/std/algorithm/searching/find_skip.html +/library-prerelease/std/algorithm/searching/findSplitAfter.html /library-prerelease/std/algorithm/searching/find_split_after.html +/library-prerelease/std/algorithm/searching/findSplitBefore.html /library-prerelease/std/algorithm/searching/find_split_before.html +/library-prerelease/std/algorithm/searching/findSplit.html /library-prerelease/std/algorithm/searching/find_split.html +/library-prerelease/std/algorithm/searching/minCount.html /library-prerelease/std/algorithm/searching/min_count.html +/library-prerelease/std/algorithm/searching/minPos.html /library-prerelease/std/algorithm/searching/min_pos.html +/library-prerelease/std/algorithm/searching/OpenRight.html /library-prerelease/std/algorithm/searching/open_right.html +/library-prerelease/std/algorithm/searching/OpenRight.no.html /library-prerelease/std/algorithm/searching/open_right.no.html +/library-prerelease/std/algorithm/searching/OpenRight.yes.html /library-prerelease/std/algorithm/searching/open_right.yes.html +/library-prerelease/std/algorithm/searching/skipOver.html /library-prerelease/std/algorithm/searching/skip_over.html +/library-prerelease/std/algorithm/searching/startsWith.html /library-prerelease/std/algorithm/searching/starts_with.html +/library-prerelease/std/algorithm/setops/cartesianProduct.html /library-prerelease/std/algorithm/setops/cartesian_product.html +/library-prerelease/std/algorithm/setops/largestPartialIntersection.html /library-prerelease/std/algorithm/setops/largest_partial_intersection.html +/library-prerelease/std/algorithm/setops/largestPartialIntersectionWeighted.html /library-prerelease/std/algorithm/setops/largest_partial_intersection_weighted.html +/library-prerelease/std/algorithm/setops/nWayUnion.html /library-prerelease/std/algorithm/setops/n_way_union.html +/library-prerelease/std/algorithm/setops/NWayUnion.html /library-prerelease/std/algorithm/setops/n_way_union.html +/library-prerelease/std/algorithm/setops/setDifference.html /library-prerelease/std/algorithm/setops/set_difference.html +/library-prerelease/std/algorithm/setops/SetDifference.html /library-prerelease/std/algorithm/setops/set_difference.html +/library-prerelease/std/algorithm/setops/setIntersection.html /library-prerelease/std/algorithm/setops/set_intersection.html +/library-prerelease/std/algorithm/setops/SetIntersection.html /library-prerelease/std/algorithm/setops/set_intersection.html +/library-prerelease/std/algorithm/setops/setSymmetricDifference.html /library-prerelease/std/algorithm/setops/set_symmetric_difference.html +/library-prerelease/std/algorithm/setops/SetSymmetricDifference.html /library-prerelease/std/algorithm/setops/set_symmetric_difference.html +/library-prerelease/std/algorithm/setops/setUnion.html /library-prerelease/std/algorithm/setops/set_union.html +/library-prerelease/std/algorithm/setops/SetUnion.html /library-prerelease/std/algorithm/setops/set_union.html +/library-prerelease/std/algorithm/sorting/completeSort.html /library-prerelease/std/algorithm/sorting/complete_sort.html +/library-prerelease/std/algorithm/sorting/isPartitioned.html /library-prerelease/std/algorithm/sorting/is_partitioned.html +/library-prerelease/std/algorithm/sorting/isSorted.html /library-prerelease/std/algorithm/sorting/is_sorted.html +/library-prerelease/std/algorithm/sorting/makeIndex.html /library-prerelease/std/algorithm/sorting/make_index.html +/library-prerelease/std/algorithm/sorting/multiSort.html /library-prerelease/std/algorithm/sorting/multi_sort.html +/library-prerelease/std/algorithm/sorting/multiSort.multiSort.html /library-prerelease/std/algorithm/sorting/multi_sort.multi_sort.html +/library-prerelease/std/algorithm/sorting/nextEvenPermutation.html /library-prerelease/std/algorithm/sorting/next_even_permutation.html +/library-prerelease/std/algorithm/sorting/nextPermutation.html /library-prerelease/std/algorithm/sorting/next_permutation.html +/library-prerelease/std/algorithm/sorting/partialSort.html /library-prerelease/std/algorithm/sorting/partial_sort.html +/library-prerelease/std/algorithm/sorting/schwartzSort.html /library-prerelease/std/algorithm/sorting/schwartz_sort.html +/library-prerelease/std/algorithm/sorting/SortOutput.html /library-prerelease/std/algorithm/sorting/sort_output.html +/library-prerelease/std/algorithm/sorting/SortOutput.no.html /library-prerelease/std/algorithm/sorting/sort_output.no.html +/library-prerelease/std/algorithm/sorting/SortOutput.yes.html /library-prerelease/std/algorithm/sorting/sort_output.yes.html +/library-prerelease/std/algorithm/sorting/topNCopy.html /library-prerelease/std/algorithm/sorting/top_n_copy.html +/library-prerelease/std/algorithm/sorting/topN.html /library-prerelease/std/algorithm/sorting/top.html +/library-prerelease/std/algorithm/sorting/topNIndex.html /library-prerelease/std/algorithm/sorting/top_n_index.html +/library-prerelease/std/array/Appender.capacity.html /library-prerelease/std/array/appender.capacity.html +/library-prerelease/std/array/Appender.data.html /library-prerelease/std/array/appender.data.html +/library-prerelease/std/array/Appender.html /library-prerelease/std/array/appender.html +/library-prerelease/std/array/Appender.opOpAssign.html /library-prerelease/std/array/appender.op_op_assign.html +/library-prerelease/std/array/Appender.opOpAssign.opOpAssign.html /library-prerelease/std/array/appender.op_op_assign.op_op_assign.html +/library-prerelease/std/array/Appender.put.html /library-prerelease/std/array/appender.put.html +/library-prerelease/std/array/Appender.put.put.html /library-prerelease/std/array/appender.put.put.html +/library-prerelease/std/array/Appender.reserve.html /library-prerelease/std/array/appender.reserve.html +/library-prerelease/std/array/Appender.this.html /library-prerelease/std/array/appender.this.html +/library-prerelease/std/array/assocArray.html /library-prerelease/std/array/assoc_array.html +/library-prerelease/std/array/byPair.html /library-prerelease/std/array/by_pair.html +/library-prerelease/std/array/insertInPlace.html /library-prerelease/std/array/insert_in_place.html +/library-prerelease/std/array/minimallyInitializedArray.html /library-prerelease/std/array/minimally_initialized_array.html +/library-prerelease/std/array/RefAppender.capacity.html /library-prerelease/std/array/ref_appender.capacity.html +/library-prerelease/std/array/RefAppender.data.html /library-prerelease/std/array/ref_appender.data.html +/library-prerelease/std/array/RefAppender.html /library-prerelease/std/array/ref_appender.html +/library-prerelease/std/array/RefAppender.opOpAssign.html /library-prerelease/std/array/ref_appender.op_op_assign.html +/library-prerelease/std/array/RefAppender.opOpAssign.opOpAssign.html /library-prerelease/std/array/ref_appender.op_op_assign.op_op_assign.html +/library-prerelease/std/array/RefAppender.this.html /library-prerelease/std/array/ref_appender.this.html +/library-prerelease/std/array/replaceFirst.html /library-prerelease/std/array/replace_first.html +/library-prerelease/std/array/replaceInPlace.html /library-prerelease/std/array/replace_in_place.html +/library-prerelease/std/array/replaceInto.html /library-prerelease/std/array/replace_into.html +/library-prerelease/std/array/replaceLast.html /library-prerelease/std/array/replace_last.html +/library-prerelease/std/array/replaceSlice.html /library-prerelease/std/array/replace_slice.html +/library-prerelease/std/array/sameHead.html /library-prerelease/std/array/same_head.html +/library-prerelease/std/array/sameTail.html /library-prerelease/std/array/same_tail.html +/library-prerelease/std/array/uninitializedArray.html /library-prerelease/std/array/uninitialized_array.html +/library-prerelease/std/ascii/fullHexDigits.html /library-prerelease/std/ascii/full_hex_digits.html +/library-prerelease/std/ascii/hexDigits.html /library-prerelease/std/ascii/hex_digits.html +/library-prerelease/std/ascii/isAlpha.html /library-prerelease/std/ascii/is_alpha.html +/library-prerelease/std/ascii/isAlphaNum.html /library-prerelease/std/ascii/is_alpha_num.html +/library-prerelease/std/ascii/isASCII.html /library-prerelease/std/ascii/is_ascii.html +/library-prerelease/std/ascii/isControl.html /library-prerelease/std/ascii/is_control.html +/library-prerelease/std/ascii/isDigit.html /library-prerelease/std/ascii/is_digit.html +/library-prerelease/std/ascii/isGraphical.html /library-prerelease/std/ascii/is_graphical.html +/library-prerelease/std/ascii/isHexDigit.html /library-prerelease/std/ascii/is_hex_digit.html +/library-prerelease/std/ascii/isLower.html /library-prerelease/std/ascii/is_lower.html +/library-prerelease/std/ascii/isOctalDigit.html /library-prerelease/std/ascii/is_octal_digit.html +/library-prerelease/std/ascii/isPrintable.html /library-prerelease/std/ascii/is_printable.html +/library-prerelease/std/ascii/isPunctuation.html /library-prerelease/std/ascii/is_punctuation.html +/library-prerelease/std/ascii/isUpper.html /library-prerelease/std/ascii/is_upper.html +/library-prerelease/std/ascii/isWhite.html /library-prerelease/std/ascii/is_white.html +/library-prerelease/std/ascii/LetterCase.html /library-prerelease/std/ascii/letter_case.html +/library-prerelease/std/ascii/LetterCase.lower.html /library-prerelease/std/ascii/letter_case.lower.html +/library-prerelease/std/ascii/LetterCase.upper.html /library-prerelease/std/ascii/letter_case.upper.html +/library-prerelease/std/ascii/lowerHexDigits.html /library-prerelease/std/ascii/lower_hex_digits.html +/library-prerelease/std/ascii/octalDigits.html /library-prerelease/std/ascii/octal_digits.html +/library-prerelease/std/ascii/toLower.html /library-prerelease/std/ascii/to_lower.html +/library-prerelease/std/ascii/toUpper.html /library-prerelease/std/ascii/to_upper.html +/library-prerelease/std/base64/Base64Exception.html /library-prerelease/std/base64/base64_exception.html +/library-prerelease/std/base64/Base64.html /library-prerelease/std/base64/base64.html +/library-prerelease/std/base64/Base64Impl.decode.html /library-prerelease/std/base64/base64_impl.decode.html +/library-prerelease/std/base64/Base64Impl.decodeLength.html /library-prerelease/std/base64/base64_impl.decode_length.html +/library-prerelease/std/base64/Base64Impl.Decoder.empty.html /library-prerelease/std/base64/base64_impl.decoder.empty.html +/library-prerelease/std/base64/Base64Impl.Decoder.front.html /library-prerelease/std/base64/base64_impl.decoder.front.html +/library-prerelease/std/base64/Base64Impl.decoder.html /library-prerelease/std/base64/base64_impl.decoder.html +/library-prerelease/std/base64/Base64Impl.Decoder.html /library-prerelease/std/base64/base64_impl.decoder.html +/library-prerelease/std/base64/Base64Impl.Decoder.popFront.html /library-prerelease/std/base64/base64_impl.decoder.pop_front.html +/library-prerelease/std/base64/Base64Impl.encode.html /library-prerelease/std/base64/base64_impl.encode.html +/library-prerelease/std/base64/Base64Impl.encodeLength.html /library-prerelease/std/base64/base64_impl.encode_length.html +/library-prerelease/std/base64/Base64Impl.Encoder.empty.html /library-prerelease/std/base64/base64_impl.encoder.empty.html +/library-prerelease/std/base64/Base64Impl.Encoder.front.html /library-prerelease/std/base64/base64_impl.encoder.front.html +/library-prerelease/std/base64/Base64Impl.encoder.html /library-prerelease/std/base64/base64_impl.encoder.html +/library-prerelease/std/base64/Base64Impl.Encoder.html /library-prerelease/std/base64/base64_impl.encoder.html +/library-prerelease/std/base64/Base64Impl.Encoder.popFront.html /library-prerelease/std/base64/base64_impl.encoder.pop_front.html +/library-prerelease/std/base64/Base64Impl.html /library-prerelease/std/base64/base64_impl.html +/library-prerelease/std/base64/Base64Impl.NoPadding.html /library-prerelease/std/base64/base64_impl.no_padding.html +/library-prerelease/std/base64/Base64URL.html /library-prerelease/std/base64/base64_url.html +/library-prerelease/std/base64/Object.factory.html /library-prerelease/std/base64/object.factory.html +/library-prerelease/std/base64/Object.opCmp.html /library-prerelease/std/base64/object.op_cmp.html +/library-prerelease/std/base64/Object.opEquals.html /library-prerelease/std/base64/object.op_equals.html +/library-prerelease/std/base64/Object.toHash.html /library-prerelease/std/base64/object.to_hash.html +/library-prerelease/std/base64/Throwable.file.html /library-prerelease/std/base64/throwable.file.html +/library-prerelease/std/base64/Throwable.info.html /library-prerelease/std/base64/throwable.info.html +/library-prerelease/std/base64/Throwable.line.html /library-prerelease/std/base64/throwable.line.html +/library-prerelease/std/base64/Throwable.msg.html /library-prerelease/std/base64/throwable.msg.html +/library-prerelease/std/base64/Throwable.next.html /library-prerelease/std/base64/throwable.next.html +/library-prerelease/std/base64/Throwable.toString.html /library-prerelease/std/base64/throwable.to_string.html +/library-prerelease/std/bigint/absUnsign.html /library-prerelease/std/bigint/abs_unsign.html +/library-prerelease/std/bigint/BigInt.html /library-prerelease/std/bigint/big_int.html +/library-prerelease/std/bigint/BigInt.opAssign.html /library-prerelease/std/bigint/big_int.op_assign.html +/library-prerelease/std/bigint/BigInt.opBinary.html /library-prerelease/std/bigint/big_int.op_binary.html +/library-prerelease/std/bigint/BigInt.opBinaryRight.html /library-prerelease/std/bigint/big_int.op_binary_right.html +/library-prerelease/std/bigint/BigInt.opCast.html /library-prerelease/std/bigint/big_int.op_cast.html +/library-prerelease/std/bigint/BigInt.opCmp.html /library-prerelease/std/bigint/big_int.op_cmp.html +/library-prerelease/std/bigint/BigInt.opEquals.html /library-prerelease/std/bigint/big_int.op_equals.html +/library-prerelease/std/bigint/BigInt.opOpAssign.html /library-prerelease/std/bigint/big_int.op_op_assign.html +/library-prerelease/std/bigint/BigInt.opUnary.html /library-prerelease/std/bigint/big_int.op_unary.html +/library-prerelease/std/bigint/BigInt.this.html /library-prerelease/std/bigint/big_int.this.html +/library-prerelease/std/bigint/BigInt.toHash.html /library-prerelease/std/bigint/big_int.to_hash.html +/library-prerelease/std/bigint/BigInt.toInt.html /library-prerelease/std/bigint/big_int.to_int.html +/library-prerelease/std/bigint/BigInt.toLong.html /library-prerelease/std/bigint/big_int.to_long.html +/library-prerelease/std/bigint/BigInt.toString.html /library-prerelease/std/bigint/big_int.to_string.html +/library-prerelease/std/bigint/BigInt.uintLength.html /library-prerelease/std/bigint/big_int.uint_length.html +/library-prerelease/std/bigint/BigInt.ulongLength.html /library-prerelease/std/bigint/big_int.ulong_length.html +/library-prerelease/std/bigint/toDecimalString.html /library-prerelease/std/bigint/to_decimal_string.html +/library-prerelease/std/bigint/toHex.html /library-prerelease/std/bigint/to_hex.html +/library-prerelease/std/bitmanip/bigEndianToNative.html /library-prerelease/std/bitmanip/big_endian_to_native.html +/library-prerelease/std/bitmanip/BitArray.bitsSet.html /library-prerelease/std/bitmanip/bit_array.bits_set.html +/library-prerelease/std/bitmanip/BitArray.dim.html /library-prerelease/std/bitmanip/bit_array.dim.html +/library-prerelease/std/bitmanip/BitArray.dup.html /library-prerelease/std/bitmanip/bit_array.dup.html +/library-prerelease/std/bitmanip/BitArray.html /library-prerelease/std/bitmanip/bit_array.html +/library-prerelease/std/bitmanip/BitArray.init.html /library-prerelease/std/bitmanip/bit_array.init.html +/library-prerelease/std/bitmanip/BitArray.length.html /library-prerelease/std/bitmanip/bit_array.length.html +/library-prerelease/std/bitmanip/BitArray.opApply.html /library-prerelease/std/bitmanip/bit_array.op_apply.html +/library-prerelease/std/bitmanip/BitArray.opBinary.html /library-prerelease/std/bitmanip/bit_array.op_binary.html +/library-prerelease/std/bitmanip/BitArray.opCast.html /library-prerelease/std/bitmanip/bit_array.op_cast.html +/library-prerelease/std/bitmanip/BitArray.opCatAssign.html /library-prerelease/std/bitmanip/bit_array.op_cat_assign.html +/library-prerelease/std/bitmanip/BitArray.opCat.html /library-prerelease/std/bitmanip/bit_array.op_cat.html +/library-prerelease/std/bitmanip/BitArray.opCat_r.html /library-prerelease/std/bitmanip/bit_array.op_cat_r.html +/library-prerelease/std/bitmanip/BitArray.opCmp.html /library-prerelease/std/bitmanip/bit_array.op_cmp.html +/library-prerelease/std/bitmanip/BitArray.opCom.html /library-prerelease/std/bitmanip/bit_array.op_com.html +/library-prerelease/std/bitmanip/BitArray.opEquals.html /library-prerelease/std/bitmanip/bit_array.op_equals.html +/library-prerelease/std/bitmanip/BitArray.opIndexAssign.html /library-prerelease/std/bitmanip/bit_array.op_index_assign.html +/library-prerelease/std/bitmanip/BitArray.opIndex.html /library-prerelease/std/bitmanip/bit_array.op_index.html +/library-prerelease/std/bitmanip/BitArray.opOpAssign.html /library-prerelease/std/bitmanip/bit_array.op_op_assign.html +/library-prerelease/std/bitmanip/BitArray.reverse.html /library-prerelease/std/bitmanip/bit_array.reverse.html +/library-prerelease/std/bitmanip/BitArray.sort.html /library-prerelease/std/bitmanip/bit_array.sort.html +/library-prerelease/std/bitmanip/BitArray.this.html /library-prerelease/std/bitmanip/bit_array.this.html +/library-prerelease/std/bitmanip/BitArray.toHash.html /library-prerelease/std/bitmanip/bit_array.to_hash.html +/library-prerelease/std/bitmanip/BitArray.toString.html /library-prerelease/std/bitmanip/bit_array.to_string.html +/library-prerelease/std/bitmanip/bitsSet.html /library-prerelease/std/bitmanip/bits_set.html +/library-prerelease/std/bitmanip/DoubleRep.html /library-prerelease/std/bitmanip/double_rep.html +/library-prerelease/std/bitmanip/FloatRep.html /library-prerelease/std/bitmanip/float_rep.html +/library-prerelease/std/bitmanip/littleEndianToNative.html /library-prerelease/std/bitmanip/little_endian_to_native.html +/library-prerelease/std/bitmanip/nativeToBigEndian.html /library-prerelease/std/bitmanip/native_to_big_endian.html +/library-prerelease/std/bitmanip/nativeToLittleEndian.html /library-prerelease/std/bitmanip/native_to_little_endian.html +/library-prerelease/std/bitmanip/swapEndian.html /library-prerelease/std/bitmanip/swap_endian.html +/library-prerelease/std/bitmanip/taggedClassRef.html /library-prerelease/std/bitmanip/tagged_class_ref.html +/library-prerelease/std/bitmanip/taggedPointer.html /library-prerelease/std/bitmanip/tagged_pointer.html +/library-prerelease/std/compiler/D_major.html /library-prerelease/std/compiler/d_major.html +/library-prerelease/std/compiler/Vendor.digitalMars.html /library-prerelease/std/compiler/vendor.digital_mars.html +/library-prerelease/std/compiler/Vendor.dotNET.html /library-prerelease/std/compiler/vendor.dot_net.html +/library-prerelease/std/compiler/Vendor.gnu.html /library-prerelease/std/compiler/vendor.gnu.html +/library-prerelease/std/compiler/Vendor.html /library-prerelease/std/compiler/vendor.html +/library-prerelease/std/compiler/Vendor.llvm.html /library-prerelease/std/compiler/vendor.llvm.html +/library-prerelease/std/compiler/Vendor.sdc.html /library-prerelease/std/compiler/vendor.sdc.html +/library-prerelease/std/compiler/Vendor.unknown.html /library-prerelease/std/compiler/vendor.unknown.html +/library-prerelease/std/complex/Complex.html /library-prerelease/std/complex/complex.html +/library-prerelease/std/complex/Complex.im.html /library-prerelease/std/complex/complex.im.html +/library-prerelease/std/complex/Complex.re.html /library-prerelease/std/complex/complex.re.html +/library-prerelease/std/complex/Complex.toString.html /library-prerelease/std/complex/complex.to_string.html +/library-prerelease/std/complex/Complex.toString.toString.html /library-prerelease/std/complex/complex.to_string.to_string.html +/library-prerelease/std/complex/fromPolar.html /library-prerelease/std/complex/from_polar.html +/library-prerelease/std/complex/sqAbs.html /library-prerelease/std/complex/sq_abs.html +/library-prerelease/std/concurrency/FiberScheduler.html /library-prerelease/std/concurrency/fiber_scheduler.html +/library-prerelease/std/concurrency/FiberScheduler.newCondition.html /library-prerelease/std/concurrency/fiber_scheduler.new_condition.html +/library-prerelease/std/concurrency/FiberScheduler.spawn.html /library-prerelease/std/concurrency/fiber_scheduler.spawn.html +/library-prerelease/std/concurrency/FiberScheduler.start.html /library-prerelease/std/concurrency/fiber_scheduler.start.html +/library-prerelease/std/concurrency/FiberScheduler.thisInfo.html /library-prerelease/std/concurrency/fiber_scheduler.this_info.html +/library-prerelease/std/concurrency/FiberScheduler.yield.html /library-prerelease/std/concurrency/fiber_scheduler.yield.html +/library-prerelease/std/concurrency/Generator.empty.html /library-prerelease/std/concurrency/generator.empty.html +/library-prerelease/std/concurrency/Generator.front.html /library-prerelease/std/concurrency/generator.front.html +/library-prerelease/std/concurrency/Generator.html /library-prerelease/std/concurrency/generator.html +/library-prerelease/std/concurrency/Generator.popFront.html /library-prerelease/std/concurrency/generator.pop_front.html +/library-prerelease/std/concurrency/Generator.this.html /library-prerelease/std/concurrency/generator.this.html +/library-prerelease/std/concurrency/initOnce.html /library-prerelease/std/concurrency/init_once.html +/library-prerelease/std/concurrency/LinkTerminated.html /library-prerelease/std/concurrency/link_terminated.html +/library-prerelease/std/concurrency/MailboxFull.html /library-prerelease/std/concurrency/mailbox_full.html +/library-prerelease/std/concurrency/MessageMismatch.html /library-prerelease/std/concurrency/message_mismatch.html +/library-prerelease/std/concurrency/Object.factory.html /library-prerelease/std/concurrency/object.factory.html +/library-prerelease/std/concurrency/Object.opCmp.html /library-prerelease/std/concurrency/object.op_cmp.html +/library-prerelease/std/concurrency/Object.opEquals.html /library-prerelease/std/concurrency/object.op_equals.html +/library-prerelease/std/concurrency/Object.toHash.html /library-prerelease/std/concurrency/object.to_hash.html +/library-prerelease/std/concurrency/Object.toString.html /library-prerelease/std/concurrency/object.to_string.html +/library-prerelease/std/concurrency/OnCrowding.block.html /library-prerelease/std/concurrency/on_crowding.block.html +/library-prerelease/std/concurrency/OnCrowding.html /library-prerelease/std/concurrency/on_crowding.html +/library-prerelease/std/concurrency/OnCrowding.ignore.html /library-prerelease/std/concurrency/on_crowding.ignore.html +/library-prerelease/std/concurrency/OnCrowding.throwException.html /library-prerelease/std/concurrency/on_crowding.throw_exception.html +/library-prerelease/std/concurrency/OwnerTerminated.html /library-prerelease/std/concurrency/owner_terminated.html +/library-prerelease/std/concurrency/ownerTid.html /library-prerelease/std/concurrency/owner_tid.html +/library-prerelease/std/concurrency/PriorityMessageException.html /library-prerelease/std/concurrency/priority_message_exception.html +/library-prerelease/std/concurrency/PriorityMessageException.message.html /library-prerelease/std/concurrency/priority_message_exception.message.html +/library-prerelease/std/concurrency/prioritySend.html /library-prerelease/std/concurrency/priority_send.html +/library-prerelease/std/concurrency/receiveOnly.html /library-prerelease/std/concurrency/receive_only.html +/library-prerelease/std/concurrency/receiveTimeout.html /library-prerelease/std/concurrency/receive_timeout.html +/library-prerelease/std/concurrency/Scheduler.html /library-prerelease/std/concurrency/scheduler.html +/library-prerelease/std/concurrency/Scheduler.newCondition.html /library-prerelease/std/concurrency/scheduler.new_condition.html +/library-prerelease/std/concurrency/Scheduler.spawn.html /library-prerelease/std/concurrency/scheduler.spawn.html +/library-prerelease/std/concurrency/Scheduler.start.html /library-prerelease/std/concurrency/scheduler.start.html +/library-prerelease/std/concurrency/Scheduler.thisInfo.html /library-prerelease/std/concurrency/scheduler.this_info.html +/library-prerelease/std/concurrency/Scheduler.yield.html /library-prerelease/std/concurrency/scheduler.yield.html +/library-prerelease/std/concurrency/setMaxMailboxSize.html /library-prerelease/std/concurrency/set_max_mailbox_size.html +/library-prerelease/std/concurrency/spawnLinked.html /library-prerelease/std/concurrency/spawn_linked.html +/library-prerelease/std/concurrency/thisTid.html /library-prerelease/std/concurrency/this_tid.html +/library-prerelease/std/concurrency/ThreadInfo.cleanup.html /library-prerelease/std/concurrency/thread_info.cleanup.html +/library-prerelease/std/concurrency/ThreadInfo.html /library-prerelease/std/concurrency/thread_info.html +/library-prerelease/std/concurrency/ThreadInfo.thisInfo.html /library-prerelease/std/concurrency/thread_info.this_info.html +/library-prerelease/std/concurrency/ThreadScheduler.html /library-prerelease/std/concurrency/thread_scheduler.html +/library-prerelease/std/concurrency/ThreadScheduler.newCondition.html /library-prerelease/std/concurrency/thread_scheduler.new_condition.html +/library-prerelease/std/concurrency/ThreadScheduler.spawn.html /library-prerelease/std/concurrency/thread_scheduler.spawn.html +/library-prerelease/std/concurrency/ThreadScheduler.start.html /library-prerelease/std/concurrency/thread_scheduler.start.html +/library-prerelease/std/concurrency/ThreadScheduler.thisInfo.html /library-prerelease/std/concurrency/thread_scheduler.this_info.html +/library-prerelease/std/concurrency/ThreadScheduler.yield.html /library-prerelease/std/concurrency/thread_scheduler.yield.html +/library-prerelease/std/concurrency/Throwable.file.html /library-prerelease/std/concurrency/throwable.file.html +/library-prerelease/std/concurrency/Throwable.info.html /library-prerelease/std/concurrency/throwable.info.html +/library-prerelease/std/concurrency/Throwable.line.html /library-prerelease/std/concurrency/throwable.line.html +/library-prerelease/std/concurrency/Throwable.msg.html /library-prerelease/std/concurrency/throwable.msg.html +/library-prerelease/std/concurrency/Throwable.next.html /library-prerelease/std/concurrency/throwable.next.html +/library-prerelease/std/concurrency/Throwable.toString.html /library-prerelease/std/concurrency/throwable.to_string.html +/library-prerelease/std/concurrency/Tid.html /library-prerelease/std/concurrency/tid.html +/library-prerelease/std/concurrency/TidMissingException.html /library-prerelease/std/concurrency/tid_missing_exception.html +/library-prerelease/std/concurrency/Tid.toString.html /library-prerelease/std/concurrency/tid.to_string.html +/library-prerelease/std/container/array/Array.back.html /library-prerelease/std/container/array/array.back.html +/library-prerelease/std/container/array/Array.capacity.html /library-prerelease/std/container/array/array.capacity.html +/library-prerelease/std/container/array/Array.clear.html /library-prerelease/std/container/array/array.clear.html +/library-prerelease/std/container/array/Array.ConstRange.html /library-prerelease/std/container/array/array.const_range.html +/library-prerelease/std/container/array/Array.dup.html /library-prerelease/std/container/array/array.dup.html +/library-prerelease/std/container/array/Array.empty.html /library-prerelease/std/container/array/array.empty.html +/library-prerelease/std/container/array/Array.front.html /library-prerelease/std/container/array/array.front.html +/library-prerelease/std/container/array/Array.html /library-prerelease/std/container/array/array.html +/library-prerelease/std/container/array/Array.ImmutableRange.html /library-prerelease/std/container/array/array.immutable_range.html +/library-prerelease/std/container/array/Array.insertAfter.html /library-prerelease/std/container/array/array.insert_after.html +/library-prerelease/std/container/array/Array.insertAfter.insertAfter.html /library-prerelease/std/container/array/array.insert_after.insert_after.html +/library-prerelease/std/container/array/Array.insertBack.html /library-prerelease/std/container/array/array.insert_back.html +/library-prerelease/std/container/array/Array.insertBack.insertBack.html /library-prerelease/std/container/array/array.insert_back.insert_back.html +/library-prerelease/std/container/array/Array.insertBefore.html /library-prerelease/std/container/array/array.insert_before.html +/library-prerelease/std/container/array/Array.insertBefore.insertBefore.html /library-prerelease/std/container/array/array.insert_before.insert_before.html +/library-prerelease/std/container/array/Array.insert.html /library-prerelease/std/container/array/array.insert.html +/library-prerelease/std/container/array/Array.length.html /library-prerelease/std/container/array/array.length.html +/library-prerelease/std/container/array/Array.linearInsert.html /library-prerelease/std/container/array/array.linear_insert.html +/library-prerelease/std/container/array/Array.linearRemove.html /library-prerelease/std/container/array/array.linear_remove.html +/library-prerelease/std/container/array/Array.moveAt.html /library-prerelease/std/container/array/array.move_at.html +/library-prerelease/std/container/array/Array.opBinary.html /library-prerelease/std/container/array/array.op_binary.html +/library-prerelease/std/container/array/Array.opBinary.opBinary.html /library-prerelease/std/container/array/array.op_binary.op_binary.html +/library-prerelease/std/container/array/Array.opDollar.html /library-prerelease/std/container/array/array.op_dollar.html +/library-prerelease/std/container/array/Array.opEquals.html /library-prerelease/std/container/array/array.op_equals.html +/library-prerelease/std/container/array/Array.opIndexAssign.html /library-prerelease/std/container/array/array.op_index_assign.html +/library-prerelease/std/container/array/Array.opIndex.html /library-prerelease/std/container/array/array.op_index.html +/library-prerelease/std/container/array/Array.opIndexOpAssign.html /library-prerelease/std/container/array/array.op_index_op_assign.html +/library-prerelease/std/container/array/Array.opIndexOpAssign.opIndexOpAssign.html /library-prerelease/std/container/array/array.op_index_op_assign.op_index_op_assign.html +/library-prerelease/std/container/array/Array.opOpAssign.html /library-prerelease/std/container/array/array.op_op_assign.html +/library-prerelease/std/container/array/Array.opOpAssign.opOpAssign.html /library-prerelease/std/container/array/array.op_op_assign.op_op_assign.html +/library-prerelease/std/container/array/Array.opSliceAssign.html /library-prerelease/std/container/array/array.op_slice_assign.html +/library-prerelease/std/container/array/Array.opSlice.html /library-prerelease/std/container/array/array.op_slice.html +/library-prerelease/std/container/array/Array.opSliceOpAssign.html /library-prerelease/std/container/array/array.op_slice_op_assign.html +/library-prerelease/std/container/array/Array.opSliceOpAssign.opSliceOpAssign.html /library-prerelease/std/container/array/array.op_slice_op_assign.op_slice_op_assign.html +/library-prerelease/std/container/array/Array.opSliceUnary.html /library-prerelease/std/container/array/array.op_slice_unary.html +/library-prerelease/std/container/array/Array.opSliceUnary.opSliceUnary.html /library-prerelease/std/container/array/array.op_slice_unary.op_slice_unary.html +/library-prerelease/std/container/array/Array.Range.back.html /library-prerelease/std/container/array/array.range.back.html +/library-prerelease/std/container/array/Array.Range.empty.html /library-prerelease/std/container/array/array.range.empty.html +/library-prerelease/std/container/array/Array.Range.front.html /library-prerelease/std/container/array/array.range.front.html +/library-prerelease/std/container/array/Array.Range.html /library-prerelease/std/container/array/array.range.html +/library-prerelease/std/container/array/Array.Range.length.html /library-prerelease/std/container/array/array.range.length.html +/library-prerelease/std/container/array/Array.Range.moveAt.html /library-prerelease/std/container/array/array.range.move_at.html +/library-prerelease/std/container/array/Array.Range.moveBack.html /library-prerelease/std/container/array/array.range.move_back.html +/library-prerelease/std/container/array/Array.Range.moveFront.html /library-prerelease/std/container/array/array.range.move_front.html +/library-prerelease/std/container/array/Array.Range.opIndexAssign.html /library-prerelease/std/container/array/array.range.op_index_assign.html +/library-prerelease/std/container/array/Array.Range.opIndex.html /library-prerelease/std/container/array/array.range.op_index.html +/library-prerelease/std/container/array/Array.Range.opSlice.html /library-prerelease/std/container/array/array.range.op_slice.html +/library-prerelease/std/container/array/Array.Range.popBack.html /library-prerelease/std/container/array/array.range.pop_back.html +/library-prerelease/std/container/array/Array.Range.popFront.html /library-prerelease/std/container/array/array.range.pop_front.html +/library-prerelease/std/container/array/Array.Range.save.html /library-prerelease/std/container/array/array.range.save.html +/library-prerelease/std/container/array/Array.removeAny.html /library-prerelease/std/container/array/array.remove_any.html +/library-prerelease/std/container/array/Array.removeBack.html /library-prerelease/std/container/array/array.remove_back.html +/library-prerelease/std/container/array/Array.replace.html /library-prerelease/std/container/array/array.replace.html +/library-prerelease/std/container/array/Array.replace.replace.html /library-prerelease/std/container/array/array.replace.replace.html +/library-prerelease/std/container/array/Array.reserve.html /library-prerelease/std/container/array/array.reserve.html +/library-prerelease/std/container/array/Array.stableInsertAfter.html /library-prerelease/std/container/array/array.stable_insert_after.html +/library-prerelease/std/container/array/Array.stableInsertBack.html /library-prerelease/std/container/array/array.stable_insert_back.html +/library-prerelease/std/container/array/Array.stableInsertBefore.html /library-prerelease/std/container/array/array.stable_insert_before.html +/library-prerelease/std/container/array/Array.stableInsert.html /library-prerelease/std/container/array/array.stable_insert.html +/library-prerelease/std/container/array/Array.stableLinearInsert.html /library-prerelease/std/container/array/array.stable_linear_insert.html +/library-prerelease/std/container/array/Array.stableRemoveAny.html /library-prerelease/std/container/array/array.stable_remove_any.html +/library-prerelease/std/container/array/Array.stableRemoveBack.html /library-prerelease/std/container/array/array.stable_remove_back.html +/library-prerelease/std/container/array/Array.stableReplace.html /library-prerelease/std/container/array/array.stable_replace.html +/library-prerelease/std/container/array/Array.this.html /library-prerelease/std/container/array/array.this.html +/library-prerelease/std/container/array/Array.this.this.html /library-prerelease/std/container/array/array.this.this.html +/library-prerelease/std/container/binaryheap/BinaryHeap.acquire.html /library-prerelease/std/container/binaryheap/binary_heap.acquire.html +/library-prerelease/std/container/binaryheap/BinaryHeap.assume.html /library-prerelease/std/container/binaryheap/binary_heap.assume.html +/library-prerelease/std/container/binaryheap/BinaryHeap.capacity.html /library-prerelease/std/container/binaryheap/binary_heap.capacity.html +/library-prerelease/std/container/binaryheap/BinaryHeap.clear.html /library-prerelease/std/container/binaryheap/binary_heap.clear.html +/library-prerelease/std/container/binaryheap/BinaryHeap.conditionalInsert.html /library-prerelease/std/container/binaryheap/binary_heap.conditional_insert.html +/library-prerelease/std/container/binaryheap/BinaryHeap.dup.html /library-prerelease/std/container/binaryheap/binary_heap.dup.html +/library-prerelease/std/container/binaryheap/BinaryHeap.empty.html /library-prerelease/std/container/binaryheap/binary_heap.empty.html +/library-prerelease/std/container/binaryheap/BinaryHeap.front.html /library-prerelease/std/container/binaryheap/binary_heap.front.html +/library-prerelease/std/container/binaryheap/BinaryHeap.html /library-prerelease/std/container/binaryheap/binary_heap.html +/library-prerelease/std/container/binaryheap/BinaryHeap.insert.html /library-prerelease/std/container/binaryheap/binary_heap.insert.html +/library-prerelease/std/container/binaryheap/BinaryHeap.length.html /library-prerelease/std/container/binaryheap/binary_heap.length.html +/library-prerelease/std/container/binaryheap/BinaryHeap.popFront.html /library-prerelease/std/container/binaryheap/binary_heap.pop_front.html +/library-prerelease/std/container/binaryheap/BinaryHeap.release.html /library-prerelease/std/container/binaryheap/binary_heap.release.html +/library-prerelease/std/container/binaryheap/BinaryHeap.removeAny.html /library-prerelease/std/container/binaryheap/binary_heap.remove_any.html +/library-prerelease/std/container/binaryheap/BinaryHeap.removeFront.html /library-prerelease/std/container/binaryheap/binary_heap.remove_front.html +/library-prerelease/std/container/binaryheap/BinaryHeap.replaceFront.html /library-prerelease/std/container/binaryheap/binary_heap.replace_front.html +/library-prerelease/std/container/binaryheap/BinaryHeap.this.html /library-prerelease/std/container/binaryheap/binary_heap.this.html +/library-prerelease/std/container/dlist/DList.back.html /library-prerelease/std/container/dlist/d_list.back.html +/library-prerelease/std/container/dlist/DList.clear.html /library-prerelease/std/container/dlist/d_list.clear.html +/library-prerelease/std/container/dlist/DList.dup.html /library-prerelease/std/container/dlist/d_list.dup.html +/library-prerelease/std/container/dlist/DList.empty.html /library-prerelease/std/container/dlist/d_list.empty.html +/library-prerelease/std/container/dlist/DList.front.html /library-prerelease/std/container/dlist/d_list.front.html +/library-prerelease/std/container/dlist/DList.html /library-prerelease/std/container/dlist/d_list.html +/library-prerelease/std/container/dlist/DList.insertAfter.html /library-prerelease/std/container/dlist/d_list.insert_after.html +/library-prerelease/std/container/dlist/DList.insertAfter.insertAfter.html /library-prerelease/std/container/dlist/d_list.insert_after.insert_after.html +/library-prerelease/std/container/dlist/DList.insertBack.html /library-prerelease/std/container/dlist/d_list.insert_back.html +/library-prerelease/std/container/dlist/DList.insertBack.insertBack.html /library-prerelease/std/container/dlist/d_list.insert_back.insert_back.html +/library-prerelease/std/container/dlist/DList.insertBefore.html /library-prerelease/std/container/dlist/d_list.insert_before.html +/library-prerelease/std/container/dlist/DList.insertBefore.insertBefore.html /library-prerelease/std/container/dlist/d_list.insert_before.insert_before.html +/library-prerelease/std/container/dlist/DList.insertFront.html /library-prerelease/std/container/dlist/d_list.insert_front.html +/library-prerelease/std/container/dlist/DList.insertFront.insertFront.html /library-prerelease/std/container/dlist/d_list.insert_front.insert_front.html +/library-prerelease/std/container/dlist/DList.insert.html /library-prerelease/std/container/dlist/d_list.insert.html +/library-prerelease/std/container/dlist/DList.linearRemove.html /library-prerelease/std/container/dlist/d_list.linear_remove.html +/library-prerelease/std/container/dlist/DList.opBinary.html /library-prerelease/std/container/dlist/d_list.op_binary.html +/library-prerelease/std/container/dlist/DList.opBinary.opBinary.html /library-prerelease/std/container/dlist/d_list.op_binary.op_binary.html +/library-prerelease/std/container/dlist/DList.opBinaryRight.html /library-prerelease/std/container/dlist/d_list.op_binary_right.html +/library-prerelease/std/container/dlist/DList.opBinaryRight.opBinaryRight.html /library-prerelease/std/container/dlist/d_list.op_binary_right.op_binary_right.html +/library-prerelease/std/container/dlist/DList.opEquals.html /library-prerelease/std/container/dlist/d_list.op_equals.html +/library-prerelease/std/container/dlist/DList.opEquals.opEquals.html /library-prerelease/std/container/dlist/d_list.op_equals.op_equals.html +/library-prerelease/std/container/dlist/DList.opOpAssign.html /library-prerelease/std/container/dlist/d_list.op_op_assign.html +/library-prerelease/std/container/dlist/DList.opOpAssign.opOpAssign.html /library-prerelease/std/container/dlist/d_list.op_op_assign.op_op_assign.html +/library-prerelease/std/container/dlist/DList.opSlice.html /library-prerelease/std/container/dlist/d_list.op_slice.html +/library-prerelease/std/container/dlist/DList.Range.html /library-prerelease/std/container/dlist/d_list.range.html +/library-prerelease/std/container/dlist/DList.removeAny.html /library-prerelease/std/container/dlist/d_list.remove_any.html +/library-prerelease/std/container/dlist/DList.removeBack.html /library-prerelease/std/container/dlist/d_list.remove_back.html +/library-prerelease/std/container/dlist/DList.removeFront.html /library-prerelease/std/container/dlist/d_list.remove_front.html +/library-prerelease/std/container/dlist/DList.remove.html /library-prerelease/std/container/dlist/d_list.remove.html +/library-prerelease/std/container/dlist/DList.stableInsertAfter.html /library-prerelease/std/container/dlist/d_list.stable_insert_after.html +/library-prerelease/std/container/dlist/DList.stableInsertBack.html /library-prerelease/std/container/dlist/d_list.stable_insert_back.html +/library-prerelease/std/container/dlist/DList.stableInsertBefore.html /library-prerelease/std/container/dlist/d_list.stable_insert_before.html +/library-prerelease/std/container/dlist/DList.stableInsertFront.html /library-prerelease/std/container/dlist/d_list.stable_insert_front.html +/library-prerelease/std/container/dlist/DList.stableInsert.html /library-prerelease/std/container/dlist/d_list.stable_insert.html +/library-prerelease/std/container/dlist/DList.stableLinearRemove.html /library-prerelease/std/container/dlist/d_list.stable_linear_remove.html +/library-prerelease/std/container/dlist/DList.stableRemoveAny.html /library-prerelease/std/container/dlist/d_list.stable_remove_any.html +/library-prerelease/std/container/dlist/DList.stableRemoveBack.html /library-prerelease/std/container/dlist/d_list.stable_remove_back.html +/library-prerelease/std/container/dlist/DList.stableRemoveFront.html /library-prerelease/std/container/dlist/d_list.stable_remove_front.html +/library-prerelease/std/container/dlist/DList.stableRemove.html /library-prerelease/std/container/dlist/d_list.stable_remove.html +/library-prerelease/std/container/dlist/DList.this.html /library-prerelease/std/container/dlist/d_list.this.html +/library-prerelease/std/container/dlist/DList.this.this.html /library-prerelease/std/container/dlist/d_list.this.this.html +/library-prerelease/std/container/rbtree/Object.factory.html /library-prerelease/std/container/rbtree/object.factory.html +/library-prerelease/std/container/rbtree/Object.opCmp.html /library-prerelease/std/container/rbtree/object.op_cmp.html +/library-prerelease/std/container/rbtree/Object.toHash.html /library-prerelease/std/container/rbtree/object.to_hash.html +/library-prerelease/std/container/rbtree/Object.toString.html /library-prerelease/std/container/rbtree/object.to_string.html +/library-prerelease/std/container/rbtree/RedBlackTree.back.html /library-prerelease/std/container/rbtree/red_black_tree.back.html +/library-prerelease/std/container/rbtree/RedBlackTree.clear.html /library-prerelease/std/container/rbtree/red_black_tree.clear.html +/library-prerelease/std/container/rbtree/RedBlackTree.dup.html /library-prerelease/std/container/rbtree/red_black_tree.dup.html +/library-prerelease/std/container/rbtree/RedBlackTree.Elem.html /library-prerelease/std/container/rbtree/red_black_tree.elem.html +/library-prerelease/std/container/rbtree/RedBlackTree.empty.html /library-prerelease/std/container/rbtree/red_black_tree.empty.html +/library-prerelease/std/container/rbtree/RedBlackTree.equalRange.html /library-prerelease/std/container/rbtree/red_black_tree.equal_range.html +/library-prerelease/std/container/rbtree/RedBlackTree.front.html /library-prerelease/std/container/rbtree/red_black_tree.front.html +/library-prerelease/std/container/rbtree/redBlackTree.html /library-prerelease/std/container/rbtree/red_black_tree.html +/library-prerelease/std/container/rbtree/RedBlackTree.html /library-prerelease/std/container/rbtree/red_black_tree.html +/library-prerelease/std/container/rbtree/RedBlackTree.insert.html /library-prerelease/std/container/rbtree/red_black_tree.insert.html +/library-prerelease/std/container/rbtree/RedBlackTree.length.html /library-prerelease/std/container/rbtree/red_black_tree.length.html +/library-prerelease/std/container/rbtree/RedBlackTree.lowerBound.html /library-prerelease/std/container/rbtree/red_black_tree.lower_bound.html +/library-prerelease/std/container/rbtree/RedBlackTree.opBinaryRight.html /library-prerelease/std/container/rbtree/red_black_tree.op_binary_right.html +/library-prerelease/std/container/rbtree/RedBlackTree.opBinaryRight.opBinaryRight.html /library-prerelease/std/container/rbtree/red_black_tree.op_binary_right.op_binary_right.html +/library-prerelease/std/container/rbtree/RedBlackTree.opEquals.html /library-prerelease/std/container/rbtree/red_black_tree.op_equals.html +/library-prerelease/std/container/rbtree/RedBlackTree.opSlice.html /library-prerelease/std/container/rbtree/red_black_tree.op_slice.html +/library-prerelease/std/container/rbtree/RedBlackTree.Range.back.html /library-prerelease/std/container/rbtree/red_black_tree.range.back.html +/library-prerelease/std/container/rbtree/RedBlackTree.Range.empty.html /library-prerelease/std/container/rbtree/red_black_tree.range.empty.html +/library-prerelease/std/container/rbtree/RedBlackTree.Range.front.html /library-prerelease/std/container/rbtree/red_black_tree.range.front.html +/library-prerelease/std/container/rbtree/RedBlackTree.Range.html /library-prerelease/std/container/rbtree/red_black_tree.range.html +/library-prerelease/std/container/rbtree/RedBlackTree.Range.popBack.html /library-prerelease/std/container/rbtree/red_black_tree.range.pop_back.html +/library-prerelease/std/container/rbtree/RedBlackTree.Range.popFront.html /library-prerelease/std/container/rbtree/red_black_tree.range.pop_front.html +/library-prerelease/std/container/rbtree/RedBlackTree.Range.save.html /library-prerelease/std/container/rbtree/red_black_tree.range.save.html +/library-prerelease/std/container/rbtree/RedBlackTree.removeAny.html /library-prerelease/std/container/rbtree/red_black_tree.remove_any.html +/library-prerelease/std/container/rbtree/RedBlackTree.removeBack.html /library-prerelease/std/container/rbtree/red_black_tree.remove_back.html +/library-prerelease/std/container/rbtree/RedBlackTree.removeFront.html /library-prerelease/std/container/rbtree/red_black_tree.remove_front.html +/library-prerelease/std/container/rbtree/RedBlackTree.remove.html /library-prerelease/std/container/rbtree/red_black_tree.remove.html +/library-prerelease/std/container/rbtree/RedBlackTree.removeKey.html /library-prerelease/std/container/rbtree/red_black_tree.remove_key.html +/library-prerelease/std/container/rbtree/RedBlackTree.removeKey.removeKey.html /library-prerelease/std/container/rbtree/red_black_tree.remove_key.remove_key.html +/library-prerelease/std/container/rbtree/RedBlackTree.stableInsert.html /library-prerelease/std/container/rbtree/red_black_tree.stable_insert.html +/library-prerelease/std/container/rbtree/RedBlackTree.stableInsert.stableInsert.html /library-prerelease/std/container/rbtree/red_black_tree.stable_insert.stable_insert.html +/library-prerelease/std/container/rbtree/RedBlackTree.this.html /library-prerelease/std/container/rbtree/red_black_tree.this.html +/library-prerelease/std/container/rbtree/RedBlackTree.this.this.html /library-prerelease/std/container/rbtree/red_black_tree.this.this.html +/library-prerelease/std/container/rbtree/RedBlackTree.upperBound.html /library-prerelease/std/container/rbtree/red_black_tree.upper_bound.html +/library-prerelease/std/container/slist/SList.clear.html /library-prerelease/std/container/slist/s_list.clear.html +/library-prerelease/std/container/slist/SList.dup.html /library-prerelease/std/container/slist/s_list.dup.html +/library-prerelease/std/container/slist/SList.empty.html /library-prerelease/std/container/slist/s_list.empty.html +/library-prerelease/std/container/slist/SList.front.html /library-prerelease/std/container/slist/s_list.front.html +/library-prerelease/std/container/slist/SList.html /library-prerelease/std/container/slist/s_list.html +/library-prerelease/std/container/slist/SList.insertAfter.html /library-prerelease/std/container/slist/s_list.insert_after.html +/library-prerelease/std/container/slist/SList.insertAfter.insertAfter.html /library-prerelease/std/container/slist/s_list.insert_after.insert_after.html +/library-prerelease/std/container/slist/SList.insertFront.html /library-prerelease/std/container/slist/s_list.insert_front.html +/library-prerelease/std/container/slist/SList.insertFront.insertFront.html /library-prerelease/std/container/slist/s_list.insert_front.insert_front.html +/library-prerelease/std/container/slist/SList.insert.html /library-prerelease/std/container/slist/s_list.insert.html +/library-prerelease/std/container/slist/SList.linearRemove.html /library-prerelease/std/container/slist/s_list.linear_remove.html +/library-prerelease/std/container/slist/SList.opBinary.html /library-prerelease/std/container/slist/s_list.op_binary.html +/library-prerelease/std/container/slist/SList.opBinary.opBinary.html /library-prerelease/std/container/slist/s_list.op_binary.op_binary.html +/library-prerelease/std/container/slist/SList.opBinaryRight.html /library-prerelease/std/container/slist/s_list.op_binary_right.html +/library-prerelease/std/container/slist/SList.opBinaryRight.opBinaryRight.html /library-prerelease/std/container/slist/s_list.op_binary_right.op_binary_right.html +/library-prerelease/std/container/slist/SList.opEquals.html /library-prerelease/std/container/slist/s_list.op_equals.html +/library-prerelease/std/container/slist/SList.opSlice.html /library-prerelease/std/container/slist/s_list.op_slice.html +/library-prerelease/std/container/slist/SList.Range.empty.html /library-prerelease/std/container/slist/s_list.range.empty.html +/library-prerelease/std/container/slist/SList.Range.front.html /library-prerelease/std/container/slist/s_list.range.front.html +/library-prerelease/std/container/slist/SList.Range.html /library-prerelease/std/container/slist/s_list.range.html +/library-prerelease/std/container/slist/SList.Range.popFront.html /library-prerelease/std/container/slist/s_list.range.pop_front.html +/library-prerelease/std/container/slist/SList.Range.save.html /library-prerelease/std/container/slist/s_list.range.save.html +/library-prerelease/std/container/slist/SList.removeAny.html /library-prerelease/std/container/slist/s_list.remove_any.html +/library-prerelease/std/container/slist/SList.removeFront.html /library-prerelease/std/container/slist/s_list.remove_front.html +/library-prerelease/std/container/slist/SList.stableInsertAfter.html /library-prerelease/std/container/slist/s_list.stable_insert_after.html +/library-prerelease/std/container/slist/SList.stableInsertFront.html /library-prerelease/std/container/slist/s_list.stable_insert_front.html +/library-prerelease/std/container/slist/SList.stableInsert.html /library-prerelease/std/container/slist/s_list.stable_insert.html +/library-prerelease/std/container/slist/SList.stableLinearRemove.html /library-prerelease/std/container/slist/s_list.stable_linear_remove.html +/library-prerelease/std/container/slist/SList.stableRemoveAny.html /library-prerelease/std/container/slist/s_list.stable_remove_any.html +/library-prerelease/std/container/slist/SList.stableRemoveFront.html /library-prerelease/std/container/slist/s_list.stable_remove_front.html +/library-prerelease/std/container/slist/SList.this.html /library-prerelease/std/container/slist/s_list.this.html +/library-prerelease/std/container/slist/SList.this.this.html /library-prerelease/std/container/slist/s_list.this.this.html +/library-prerelease/std/conv/castFrom.html /library-prerelease/std/conv/cast_from.html +/library-prerelease/std/conv/ConvException.html /library-prerelease/std/conv/conv_exception.html +/library-prerelease/std/conv/ConvOverflowException.html /library-prerelease/std/conv/conv_overflow_exception.html +/library-prerelease/std/conv/Object.factory.html /library-prerelease/std/conv/object.factory.html +/library-prerelease/std/conv/Object.opCmp.html /library-prerelease/std/conv/object.op_cmp.html +/library-prerelease/std/conv/Object.opEquals.html /library-prerelease/std/conv/object.op_equals.html +/library-prerelease/std/conv/Object.toHash.html /library-prerelease/std/conv/object.to_hash.html +/library-prerelease/std/conv/roundTo.html /library-prerelease/std/conv/round_to.html +/library-prerelease/std/conv/roundTo.roundTo.html /library-prerelease/std/conv/round_to.round_to.html +/library-prerelease/std/conv/Throwable.file.html /library-prerelease/std/conv/throwable.file.html +/library-prerelease/std/conv/Throwable.info.html /library-prerelease/std/conv/throwable.info.html +/library-prerelease/std/conv/Throwable.line.html /library-prerelease/std/conv/throwable.line.html +/library-prerelease/std/conv/Throwable.msg.html /library-prerelease/std/conv/throwable.msg.html +/library-prerelease/std/conv/Throwable.next.html /library-prerelease/std/conv/throwable.next.html +/library-prerelease/std/conv/Throwable.toString.html /library-prerelease/std/conv/throwable.to_string.html +/library-prerelease/std/conv/toImpl.html /library-prerelease/std/conv/to_impl.html +/library-prerelease/std/cstream/CFile.close.html /library-prerelease/std/cstream/c_file.close.html +/library-prerelease/std/cstream/CFile.eof.html /library-prerelease/std/cstream/c_file.eof.html +/library-prerelease/std/cstream/CFile.file.html /library-prerelease/std/cstream/c_file.file.html +/library-prerelease/std/cstream/CFile.flush.html /library-prerelease/std/cstream/c_file.flush.html +/library-prerelease/std/cstream/CFile.getc.html /library-prerelease/std/cstream/c_file.getc.html +/library-prerelease/std/cstream/CFile.html /library-prerelease/std/cstream/c_file.html +/library-prerelease/std/cstream/CFile.readBlock.html /library-prerelease/std/cstream/c_file.read_block.html +/library-prerelease/std/cstream/CFile.seek.html /library-prerelease/std/cstream/c_file.seek.html +/library-prerelease/std/cstream/CFile.this.html /library-prerelease/std/cstream/c_file.this.html +/library-prerelease/std/cstream/CFile.ungetc.html /library-prerelease/std/cstream/c_file.ungetc.html +/library-prerelease/std/cstream/CFile.writeBlock.html /library-prerelease/std/cstream/c_file.write_block.html +/library-prerelease/std/cstream/CFile.writeLine.html /library-prerelease/std/cstream/c_file.write_line.html +/library-prerelease/std/cstream/CFile.writeLineW.html /library-prerelease/std/cstream/c_file.write_line.html +/library-prerelease/std/cstream/InputStream.available.html /library-prerelease/std/cstream/input_stream.available.html +/library-prerelease/std/cstream/InputStream.eof.html /library-prerelease/std/cstream/input_stream.eof.html +/library-prerelease/std/cstream/InputStream.getcw.html /library-prerelease/std/cstream/input_stream.getcw.html +/library-prerelease/std/cstream/InputStream.isOpen.html /library-prerelease/std/cstream/input_stream.is_open.html +/library-prerelease/std/cstream/InputStream.opApply.html /library-prerelease/std/cstream/input_stream.op_apply.html +/library-prerelease/std/cstream/InputStream.readExact.html /library-prerelease/std/cstream/input_stream.read_exact.html +/library-prerelease/std/cstream/InputStream.readf.html /library-prerelease/std/cstream/input_stream.readf.html +/library-prerelease/std/cstream/InputStream.read.html /library-prerelease/std/cstream/input_stream.read.html +/library-prerelease/std/cstream/InputStream.readLine.html /library-prerelease/std/cstream/input_stream.read_line.html +/library-prerelease/std/cstream/InputStream.readLineW.html /library-prerelease/std/cstream/input_stream.read_line.html +/library-prerelease/std/cstream/InputStream.readString.html /library-prerelease/std/cstream/input_stream.read_string.html +/library-prerelease/std/cstream/InputStream.readStringW.html /library-prerelease/std/cstream/input_stream.read_string.html +/library-prerelease/std/cstream/InputStream.ungetcw.html /library-prerelease/std/cstream/input_stream.ungetcw.html +/library-prerelease/std/cstream/InputStream.vreadf.html /library-prerelease/std/cstream/input_stream.vreadf.html +/library-prerelease/std/cstream/Object.factory.html /library-prerelease/std/cstream/object.factory.html +/library-prerelease/std/cstream/Object.opCmp.html /library-prerelease/std/cstream/object.op_cmp.html +/library-prerelease/std/cstream/Object.opEquals.html /library-prerelease/std/cstream/object.op_equals.html +/library-prerelease/std/cstream/OutputStream.printf.html /library-prerelease/std/cstream/output_stream.printf.html +/library-prerelease/std/cstream/OutputStream.vprintf.html /library-prerelease/std/cstream/output_stream.vprintf.html +/library-prerelease/std/cstream/OutputStream.writeExact.html /library-prerelease/std/cstream/output_stream.write_exact.html +/library-prerelease/std/cstream/OutputStream.writef.html /library-prerelease/std/cstream/output_stream.writef.html +/library-prerelease/std/cstream/OutputStream.writefln.html /library-prerelease/std/cstream/output_stream.writefln.html +/library-prerelease/std/cstream/OutputStream.writefx.html /library-prerelease/std/cstream/output_stream.writefx.html +/library-prerelease/std/cstream/OutputStream.write.html /library-prerelease/std/cstream/output_stream.write.html +/library-prerelease/std/cstream/OutputStream.writeString.html /library-prerelease/std/cstream/output_stream.write_string.html +/library-prerelease/std/cstream/OutputStream.writeStringW.html /library-prerelease/std/cstream/output_stream.write_string.html +/library-prerelease/std/cstream/Stream.copyFrom.html /library-prerelease/std/cstream/stream.copy_from.html +/library-prerelease/std/cstream/Stream.isopen.html /library-prerelease/std/cstream/stream.isopen.html +/library-prerelease/std/cstream/Stream.position.html /library-prerelease/std/cstream/stream.position.html +/library-prerelease/std/cstream/Stream.prevCr.html /library-prerelease/std/cstream/stream.prev_cr.html +/library-prerelease/std/cstream/Stream.readable.html /library-prerelease/std/cstream/stream.readable.html +/library-prerelease/std/cstream/Stream.readEOF.html /library-prerelease/std/cstream/stream.read_eof.html +/library-prerelease/std/cstream/Stream.seekable.html /library-prerelease/std/cstream/stream.seekable.html +/library-prerelease/std/cstream/Stream.seekCur.html /library-prerelease/std/cstream/stream.seek_cur.html +/library-prerelease/std/cstream/Stream.seekEnd.html /library-prerelease/std/cstream/stream.seek_end.html +/library-prerelease/std/cstream/Stream.seekSet.html /library-prerelease/std/cstream/stream.seek_set.html +/library-prerelease/std/cstream/Stream.size.html /library-prerelease/std/cstream/stream.size.html +/library-prerelease/std/cstream/Stream.toHash.html /library-prerelease/std/cstream/stream.to_hash.html +/library-prerelease/std/cstream/Stream.toString.html /library-prerelease/std/cstream/stream.to_string.html +/library-prerelease/std/cstream/Stream.writeable.html /library-prerelease/std/cstream/stream.writeable.html +/library-prerelease/std/csv/CSVException.html /library-prerelease/std/csv/csv_exception.html +/library-prerelease/std/csv/csvNextToken.html /library-prerelease/std/csv/csv_next_token.html +/library-prerelease/std/csv/csvReader.html /library-prerelease/std/csv/csv_reader.html +/library-prerelease/std/csv/HeaderMismatchException.html /library-prerelease/std/csv/header_mismatch_exception.html +/library-prerelease/std/csv/IncompleteCellException.html /library-prerelease/std/csv/incomplete_cell_exception.html +/library-prerelease/std/csv/IncompleteCellException.partialData.html /library-prerelease/std/csv/incomplete_cell_exception.partial_data.html +/library-prerelease/std/csv/Malformed.html /library-prerelease/std/csv/malformed.html +/library-prerelease/std/csv/Malformed.ignore.html /library-prerelease/std/csv/malformed.ignore.html +/library-prerelease/std/csv/Malformed.throwException.html /library-prerelease/std/csv/malformed.throw_exception.html +/library-prerelease/std/csv/Object.factory.html /library-prerelease/std/csv/object.factory.html +/library-prerelease/std/csv/Object.opCmp.html /library-prerelease/std/csv/object.op_cmp.html +/library-prerelease/std/csv/Object.opEquals.html /library-prerelease/std/csv/object.op_equals.html +/library-prerelease/std/csv/Object.toHash.html /library-prerelease/std/csv/object.to_hash.html +/library-prerelease/std/csv/Throwable.file.html /library-prerelease/std/csv/throwable.file.html +/library-prerelease/std/csv/Throwable.info.html /library-prerelease/std/csv/throwable.info.html +/library-prerelease/std/csv/Throwable.line.html /library-prerelease/std/csv/throwable.line.html +/library-prerelease/std/csv/Throwable.msg.html /library-prerelease/std/csv/throwable.msg.html +/library-prerelease/std/csv/Throwable.next.html /library-prerelease/std/csv/throwable.next.html +/library-prerelease/std/csv/Throwable.toString.html /library-prerelease/std/csv/throwable.to_string.html +/library-prerelease/std/datetime/AllowDayOverflow.html /library-prerelease/std/datetime/allow_day_overflow.html +/library-prerelease/std/datetime/AllowDayOverflow.no.html /library-prerelease/std/datetime/allow_day_overflow.no.html +/library-prerelease/std/datetime/AllowDayOverflow.yes.html /library-prerelease/std/datetime/allow_day_overflow.yes.html +/library-prerelease/std/datetime/AutoStart.html /library-prerelease/std/datetime/auto_start.html +/library-prerelease/std/datetime/AutoStart.no.html /library-prerelease/std/datetime/auto_start.no.html +/library-prerelease/std/datetime/AutoStart.yes.html /library-prerelease/std/datetime/auto_start.yes.html +/library-prerelease/std/datetime/clearTZEnvVar.html /library-prerelease/std/datetime/clear_tz_env_var.html +/library-prerelease/std/datetime/Clock.currAppTick.html /library-prerelease/std/datetime/clock.curr_app_tick.html +/library-prerelease/std/datetime/Clock.currStdTime.html /library-prerelease/std/datetime/clock.curr_std_time.html +/library-prerelease/std/datetime/Clock.currSystemTick.html /library-prerelease/std/datetime/clock.curr_system_tick.html +/library-prerelease/std/datetime/Clock.currTime.html /library-prerelease/std/datetime/clock.curr_time.html +/library-prerelease/std/datetime/Clock.html /library-prerelease/std/datetime/clock.html +/library-prerelease/std/datetime/cmpTimeUnits.html /library-prerelease/std/datetime/cmp_time_units.html +/library-prerelease/std/datetime/CmpTimeUnits.html /library-prerelease/std/datetime/cmp_time_units.html +/library-prerelease/std/datetime/comparingBenchmark.html /library-prerelease/std/datetime/comparing_benchmark.html +/library-prerelease/std/datetime/ComparingBenchmarkResult.baseTime.html /library-prerelease/std/datetime/comparing_benchmark_result.base_time.html +/library-prerelease/std/datetime/ComparingBenchmarkResult.html /library-prerelease/std/datetime/comparing_benchmark_result.html +/library-prerelease/std/datetime/ComparingBenchmarkResult.point.html /library-prerelease/std/datetime/comparing_benchmark_result.point.html +/library-prerelease/std/datetime/ComparingBenchmarkResult.targetTime.html /library-prerelease/std/datetime/comparing_benchmark_result.target_time.html +/library-prerelease/std/datetime/Date.add.html /library-prerelease/std/datetime/date.add.html +/library-prerelease/std/datetime/Date.day.html /library-prerelease/std/datetime/date.day.html +/library-prerelease/std/datetime/Date.dayOfGregorianCal.html /library-prerelease/std/datetime/date.day_of_gregorian_cal.html +/library-prerelease/std/datetime/Date.dayOfWeek.html /library-prerelease/std/datetime/date.day_of_week.html +/library-prerelease/std/datetime/Date.dayOfYear.html /library-prerelease/std/datetime/date.day_of_year.html +/library-prerelease/std/datetime/Date.daysInMonth.html /library-prerelease/std/datetime/date.days_in_month.html +/library-prerelease/std/datetime/Date.diffMonths.html /library-prerelease/std/datetime/date.diff_months.html +/library-prerelease/std/datetime/Date.endOfMonth.html /library-prerelease/std/datetime/date.end_of_month.html +/library-prerelease/std/datetime/Date.fromISOExtString.html /library-prerelease/std/datetime/date.from_iso_ext_string.html +/library-prerelease/std/datetime/Date.fromISOString.html /library-prerelease/std/datetime/date.from_iso_string.html +/library-prerelease/std/datetime/Date.fromSimpleString.html /library-prerelease/std/datetime/date.from_simple_string.html +/library-prerelease/std/datetime/Date.html /library-prerelease/std/datetime/date.html +/library-prerelease/std/datetime/Date.isAD.html /library-prerelease/std/datetime/date.is_ad.html +/library-prerelease/std/datetime/Date.isLeapYear.html /library-prerelease/std/datetime/date.is_leap_year.html +/library-prerelease/std/datetime/Date.isoWeek.html /library-prerelease/std/datetime/date.iso_week.html +/library-prerelease/std/datetime/Date.julianDay.html /library-prerelease/std/datetime/date.julian_day.html +/library-prerelease/std/datetime/Date.max.html /library-prerelease/std/datetime/date.max.html +/library-prerelease/std/datetime/Date.min.html /library-prerelease/std/datetime/date.min.html +/library-prerelease/std/datetime/Date.modJulianDay.html /library-prerelease/std/datetime/date.mod_julian_day.html +/library-prerelease/std/datetime/Date.month.html /library-prerelease/std/datetime/date.month.html +/library-prerelease/std/datetime/Date.opBinary.html /library-prerelease/std/datetime/date.op_binary.html +/library-prerelease/std/datetime/Date.opCmp.html /library-prerelease/std/datetime/date.op_cmp.html +/library-prerelease/std/datetime/Date.opOpAssign.html /library-prerelease/std/datetime/date.op_op_assign.html +/library-prerelease/std/datetime/Date.roll.html /library-prerelease/std/datetime/date.roll.html +/library-prerelease/std/datetime/Date.this.html /library-prerelease/std/datetime/date.this.html +/library-prerelease/std/datetime/DateTime.add.html /library-prerelease/std/datetime/date_time.add.html +/library-prerelease/std/datetime/DateTime.date.html /library-prerelease/std/datetime/date_time.date.html +/library-prerelease/std/datetime/DateTime.day.html /library-prerelease/std/datetime/date_time.day.html +/library-prerelease/std/datetime/DateTime.dayOfGregorianCal.html /library-prerelease/std/datetime/date_time.day_of_gregorian_cal.html +/library-prerelease/std/datetime/DateTime.dayOfWeek.html /library-prerelease/std/datetime/date_time.day_of_week.html +/library-prerelease/std/datetime/DateTime.dayOfYear.html /library-prerelease/std/datetime/date_time.day_of_year.html +/library-prerelease/std/datetime/DateTime.daysInMonth.html /library-prerelease/std/datetime/date_time.days_in_month.html +/library-prerelease/std/datetime/DateTime.diffMonths.html /library-prerelease/std/datetime/date_time.diff_months.html +/library-prerelease/std/datetime/DateTime.endOfMonth.html /library-prerelease/std/datetime/date_time.end_of_month.html +/library-prerelease/std/datetime/DateTimeException.html /library-prerelease/std/datetime/date_time_exception.html +/library-prerelease/std/datetime/DateTime.fromISOExtString.html /library-prerelease/std/datetime/date_time.from_iso_ext_string.html +/library-prerelease/std/datetime/DateTime.fromISOString.html /library-prerelease/std/datetime/date_time.from_iso_string.html +/library-prerelease/std/datetime/DateTime.fromSimpleString.html /library-prerelease/std/datetime/date_time.from_simple_string.html +/library-prerelease/std/datetime/DateTime.hour.html /library-prerelease/std/datetime/date_time.hour.html +/library-prerelease/std/datetime/DateTime.html /library-prerelease/std/datetime/date_time.html +/library-prerelease/std/datetime/DateTime.isAD.html /library-prerelease/std/datetime/date_time.is_ad.html +/library-prerelease/std/datetime/DateTime.isLeapYear.html /library-prerelease/std/datetime/date_time.is_leap_year.html +/library-prerelease/std/datetime/DateTime.isoWeek.html /library-prerelease/std/datetime/date_time.iso_week.html +/library-prerelease/std/datetime/DateTime.julianDay.html /library-prerelease/std/datetime/date_time.julian_day.html +/library-prerelease/std/datetime/DateTime.max.html /library-prerelease/std/datetime/date_time.max.html +/library-prerelease/std/datetime/DateTime.min.html /library-prerelease/std/datetime/date_time.min.html +/library-prerelease/std/datetime/DateTime.minute.html /library-prerelease/std/datetime/date_time.minute.html +/library-prerelease/std/datetime/DateTime.modJulianDay.html /library-prerelease/std/datetime/date_time.mod_julian_day.html +/library-prerelease/std/datetime/DateTime.month.html /library-prerelease/std/datetime/date_time.month.html +/library-prerelease/std/datetime/DateTime.opBinary.html /library-prerelease/std/datetime/date_time.op_binary.html +/library-prerelease/std/datetime/DateTime.opCmp.html /library-prerelease/std/datetime/date_time.op_cmp.html +/library-prerelease/std/datetime/DateTime.opOpAssign.html /library-prerelease/std/datetime/date_time.op_op_assign.html +/library-prerelease/std/datetime/DateTime.roll.html /library-prerelease/std/datetime/date_time.roll.html +/library-prerelease/std/datetime/DateTime.second.html /library-prerelease/std/datetime/date_time.second.html +/library-prerelease/std/datetime/DateTime.this.html /library-prerelease/std/datetime/date_time.this.html +/library-prerelease/std/datetime/DateTime.timeOfDay.html /library-prerelease/std/datetime/date_time.time_of_day.html +/library-prerelease/std/datetime/DateTime.toISOExtString.html /library-prerelease/std/datetime/date_time.to_iso_ext_string.html +/library-prerelease/std/datetime/DateTime.toISOString.html /library-prerelease/std/datetime/date_time.to_iso_string.html +/library-prerelease/std/datetime/DateTime.toSimpleString.html /library-prerelease/std/datetime/date_time.to_simple_string.html +/library-prerelease/std/datetime/DateTime.toString.html /library-prerelease/std/datetime/date_time.to_string.html +/library-prerelease/std/datetime/DateTime.yearBC.html /library-prerelease/std/datetime/date_time.year_bc.html +/library-prerelease/std/datetime/DateTime.year.html /library-prerelease/std/datetime/date_time.year.html +/library-prerelease/std/datetime/Date.toISOExtString.html /library-prerelease/std/datetime/date.to_iso_ext_string.html +/library-prerelease/std/datetime/Date.toISOString.html /library-prerelease/std/datetime/date.to_iso_string.html +/library-prerelease/std/datetime/Date.toSimpleString.html /library-prerelease/std/datetime/date.to_simple_string.html +/library-prerelease/std/datetime/Date.toString.html /library-prerelease/std/datetime/date.to_string.html +/library-prerelease/std/datetime/Date.yearBC.html /library-prerelease/std/datetime/date.year_bc.html +/library-prerelease/std/datetime/Date.year.html /library-prerelease/std/datetime/date.year.html +/library-prerelease/std/datetime/DayOfWeek.html /library-prerelease/std/datetime/day_of_week.html +/library-prerelease/std/datetime/daysToDayOfWeek.html /library-prerelease/std/datetime/days_to_day_of_week.html +/library-prerelease/std/datetime/Direction.both.html /library-prerelease/std/datetime/direction.both.html +/library-prerelease/std/datetime/Direction.bwd.html /library-prerelease/std/datetime/direction.bwd.html +/library-prerelease/std/datetime/Direction.fwd.html /library-prerelease/std/datetime/direction.fwd.html +/library-prerelease/std/datetime/Direction.html /library-prerelease/std/datetime/direction.html +/library-prerelease/std/datetime/DosFileTime.html /library-prerelease/std/datetime/dos_file_time.html +/library-prerelease/std/datetime/DosFileTimeToSysTime.html /library-prerelease/std/datetime/dos_file_time_to_sys_time.html +/library-prerelease/std/datetime/enforceValid.html /library-prerelease/std/datetime/enforce_valid.html +/library-prerelease/std/datetime/everyDayOfWeek.html /library-prerelease/std/datetime/every_day_of_week.html +/library-prerelease/std/datetime/everyDuration.html /library-prerelease/std/datetime/every_duration.html +/library-prerelease/std/datetime/everyMonth.html /library-prerelease/std/datetime/every_month.html +/library-prerelease/std/datetime/FILETIMEToStdTime.html /library-prerelease/std/datetime/filetime_to_std_time.html +/library-prerelease/std/datetime/FILETIMEToSysTime.html /library-prerelease/std/datetime/filetime_to_sys_time.html +/library-prerelease/std/datetime/Interval.begin.html /library-prerelease/std/datetime/interval.begin.html +/library-prerelease/std/datetime/Interval.bwdRange.html /library-prerelease/std/datetime/interval.bwd_range.html +/library-prerelease/std/datetime/Interval.contains.html /library-prerelease/std/datetime/interval.contains.html +/library-prerelease/std/datetime/Interval.empty.html /library-prerelease/std/datetime/interval.empty.html +/library-prerelease/std/datetime/Interval.end.html /library-prerelease/std/datetime/interval.end.html +/library-prerelease/std/datetime/Interval.expand.expand.html /library-prerelease/std/datetime/interval.expand.expand.html +/library-prerelease/std/datetime/Interval.expand.html /library-prerelease/std/datetime/interval.expand.html +/library-prerelease/std/datetime/Interval.fwdRange.html /library-prerelease/std/datetime/interval.fwd_range.html +/library-prerelease/std/datetime/Interval.html /library-prerelease/std/datetime/interval.html +/library-prerelease/std/datetime/Interval.intersection.html /library-prerelease/std/datetime/interval.intersection.html +/library-prerelease/std/datetime/Interval.intersects.html /library-prerelease/std/datetime/interval.intersects.html +/library-prerelease/std/datetime/Interval.isAdjacent.html /library-prerelease/std/datetime/interval.is_adjacent.html +/library-prerelease/std/datetime/Interval.isAfter.html /library-prerelease/std/datetime/interval.is_after.html +/library-prerelease/std/datetime/Interval.isBefore.html /library-prerelease/std/datetime/interval.is_before.html +/library-prerelease/std/datetime/Interval.length.html /library-prerelease/std/datetime/interval.length.html +/library-prerelease/std/datetime/Interval.merge.html /library-prerelease/std/datetime/interval.merge.html +/library-prerelease/std/datetime/Interval.opAssign.html /library-prerelease/std/datetime/interval.op_assign.html +/library-prerelease/std/datetime/IntervalRange.direction.html /library-prerelease/std/datetime/interval_range.direction.html +/library-prerelease/std/datetime/IntervalRange.empty.html /library-prerelease/std/datetime/interval_range.empty.html +/library-prerelease/std/datetime/IntervalRange.front.html /library-prerelease/std/datetime/interval_range.front.html +/library-prerelease/std/datetime/IntervalRange.func.html /library-prerelease/std/datetime/interval_range.func.html +/library-prerelease/std/datetime/IntervalRange.html /library-prerelease/std/datetime/interval_range.html +/library-prerelease/std/datetime/IntervalRange.interval.html /library-prerelease/std/datetime/interval_range.interval.html +/library-prerelease/std/datetime/IntervalRange.opAssign.html /library-prerelease/std/datetime/interval_range.op_assign.html +/library-prerelease/std/datetime/IntervalRange.popFront.html /library-prerelease/std/datetime/interval_range.pop_front.html +/library-prerelease/std/datetime/IntervalRange.save.html /library-prerelease/std/datetime/interval_range.save.html +/library-prerelease/std/datetime/Interval.shift.html /library-prerelease/std/datetime/interval.shift.html +/library-prerelease/std/datetime/Interval.shift.shift.html /library-prerelease/std/datetime/interval.shift.shift.html +/library-prerelease/std/datetime/Interval.span.html /library-prerelease/std/datetime/interval.span.html +/library-prerelease/std/datetime/Interval.this.html /library-prerelease/std/datetime/interval.this.html +/library-prerelease/std/datetime/Interval.this.this.html /library-prerelease/std/datetime/interval.this.this.html +/library-prerelease/std/datetime/Interval.toString.html /library-prerelease/std/datetime/interval.to_string.html +/library-prerelease/std/datetime/isTimePoint.html /library-prerelease/std/datetime/is_time_point.html +/library-prerelease/std/datetime/LocalTime.dstInEffect.html /library-prerelease/std/datetime/local_time.dst_in_effect.html +/library-prerelease/std/datetime/LocalTime.dstName.html /library-prerelease/std/datetime/local_time.dst_name.html +/library-prerelease/std/datetime/LocalTime.hasDST.html /library-prerelease/std/datetime/local_time.has_dst.html +/library-prerelease/std/datetime/LocalTime.html /library-prerelease/std/datetime/local_time.html +/library-prerelease/std/datetime/LocalTime.name.html /library-prerelease/std/datetime/local_time.name.html +/library-prerelease/std/datetime/LocalTime.opCall.html /library-prerelease/std/datetime/local_time.op_call.html +/library-prerelease/std/datetime/LocalTime.stdName.html /library-prerelease/std/datetime/local_time.std_name.html +/library-prerelease/std/datetime/LocalTime.tzToUTC.html /library-prerelease/std/datetime/local_time.tz_toutc.html +/library-prerelease/std/datetime/LocalTime.utcToTZ.html /library-prerelease/std/datetime/local_time.utc_totz.html +/library-prerelease/std/datetime/measureTime.html /library-prerelease/std/datetime/measure_time.html +/library-prerelease/std/datetime/Month.html /library-prerelease/std/datetime/month.html +/library-prerelease/std/datetime/monthsToMonth.html /library-prerelease/std/datetime/months_to_month.html +/library-prerelease/std/datetime/NegInfInterval.bwdRange.html /library-prerelease/std/datetime/neg_inf_interval.bwd_range.html +/library-prerelease/std/datetime/NegInfInterval.contains.html /library-prerelease/std/datetime/neg_inf_interval.contains.html +/library-prerelease/std/datetime/NegInfInterval.empty.html /library-prerelease/std/datetime/neg_inf_interval.empty.html +/library-prerelease/std/datetime/NegInfInterval.end.html /library-prerelease/std/datetime/neg_inf_interval.end.html +/library-prerelease/std/datetime/NegInfInterval.expand.expand.html /library-prerelease/std/datetime/neg_inf_interval.expand.expand.html +/library-prerelease/std/datetime/NegInfInterval.expand.html /library-prerelease/std/datetime/neg_inf_interval.expand.html +/library-prerelease/std/datetime/NegInfInterval.html /library-prerelease/std/datetime/neg_inf_interval.html +/library-prerelease/std/datetime/NegInfInterval.intersection.html /library-prerelease/std/datetime/neg_inf_interval.intersection.html +/library-prerelease/std/datetime/NegInfInterval.intersects.html /library-prerelease/std/datetime/neg_inf_interval.intersects.html +/library-prerelease/std/datetime/NegInfInterval.isAdjacent.html /library-prerelease/std/datetime/neg_inf_interval.is_adjacent.html +/library-prerelease/std/datetime/NegInfInterval.isAfter.html /library-prerelease/std/datetime/neg_inf_interval.is_after.html +/library-prerelease/std/datetime/NegInfInterval.isBefore.html /library-prerelease/std/datetime/neg_inf_interval.is_before.html +/library-prerelease/std/datetime/NegInfInterval.merge.html /library-prerelease/std/datetime/neg_inf_interval.merge.html +/library-prerelease/std/datetime/NegInfInterval.opAssign.html /library-prerelease/std/datetime/neg_inf_interval.op_assign.html +/library-prerelease/std/datetime/NegInfIntervalRange.empty.html /library-prerelease/std/datetime/neg_inf_interval_range.empty.html +/library-prerelease/std/datetime/NegInfIntervalRange.front.html /library-prerelease/std/datetime/neg_inf_interval_range.front.html +/library-prerelease/std/datetime/NegInfIntervalRange.func.html /library-prerelease/std/datetime/neg_inf_interval_range.func.html +/library-prerelease/std/datetime/NegInfIntervalRange.html /library-prerelease/std/datetime/neg_inf_interval_range.html +/library-prerelease/std/datetime/NegInfIntervalRange.interval.html /library-prerelease/std/datetime/neg_inf_interval_range.interval.html +/library-prerelease/std/datetime/NegInfIntervalRange.opAssign.html /library-prerelease/std/datetime/neg_inf_interval_range.op_assign.html +/library-prerelease/std/datetime/NegInfIntervalRange.popFront.html /library-prerelease/std/datetime/neg_inf_interval_range.pop_front.html +/library-prerelease/std/datetime/NegInfIntervalRange.save.html /library-prerelease/std/datetime/neg_inf_interval_range.save.html +/library-prerelease/std/datetime/NegInfInterval.shift.html /library-prerelease/std/datetime/neg_inf_interval.shift.html +/library-prerelease/std/datetime/NegInfInterval.shift.shift.html /library-prerelease/std/datetime/neg_inf_interval.shift.shift.html +/library-prerelease/std/datetime/NegInfInterval.span.html /library-prerelease/std/datetime/neg_inf_interval.span.html +/library-prerelease/std/datetime/NegInfInterval.this.html /library-prerelease/std/datetime/neg_inf_interval.this.html +/library-prerelease/std/datetime/NegInfInterval.toString.html /library-prerelease/std/datetime/neg_inf_interval.to_string.html +/library-prerelease/std/datetime/Object.factory.html /library-prerelease/std/datetime/object.factory.html +/library-prerelease/std/datetime/Object.opCmp.html /library-prerelease/std/datetime/object.op_cmp.html +/library-prerelease/std/datetime/Object.opEquals.html /library-prerelease/std/datetime/object.op_equals.html +/library-prerelease/std/datetime/Object.toHash.html /library-prerelease/std/datetime/object.to_hash.html +/library-prerelease/std/datetime/Object.toString.html /library-prerelease/std/datetime/object.to_string.html +/library-prerelease/std/datetime/parseRFC822DateTime.html /library-prerelease/std/datetime/parse_rf_c822_date_time.html +/library-prerelease/std/datetime/PopFirst.html /library-prerelease/std/datetime/pop_first.html +/library-prerelease/std/datetime/PopFirst.no.html /library-prerelease/std/datetime/pop_first.no.html +/library-prerelease/std/datetime/PopFirst.yes.html /library-prerelease/std/datetime/pop_first.yes.html +/library-prerelease/std/datetime/PosInfInterval.begin.html /library-prerelease/std/datetime/pos_inf_interval.begin.html +/library-prerelease/std/datetime/PosInfInterval.contains.html /library-prerelease/std/datetime/pos_inf_interval.contains.html +/library-prerelease/std/datetime/PosInfInterval.empty.html /library-prerelease/std/datetime/pos_inf_interval.empty.html +/library-prerelease/std/datetime/PosInfInterval.expand.expand.html /library-prerelease/std/datetime/pos_inf_interval.expand.expand.html +/library-prerelease/std/datetime/PosInfInterval.expand.html /library-prerelease/std/datetime/pos_inf_interval.expand.html +/library-prerelease/std/datetime/PosInfInterval.fwdRange.html /library-prerelease/std/datetime/pos_inf_interval.fwd_range.html +/library-prerelease/std/datetime/PosInfInterval.html /library-prerelease/std/datetime/pos_inf_interval.html +/library-prerelease/std/datetime/PosInfInterval.intersection.html /library-prerelease/std/datetime/pos_inf_interval.intersection.html +/library-prerelease/std/datetime/PosInfInterval.intersects.html /library-prerelease/std/datetime/pos_inf_interval.intersects.html +/library-prerelease/std/datetime/PosInfInterval.isAdjacent.html /library-prerelease/std/datetime/pos_inf_interval.is_adjacent.html +/library-prerelease/std/datetime/PosInfInterval.isAfter.html /library-prerelease/std/datetime/pos_inf_interval.is_after.html +/library-prerelease/std/datetime/PosInfInterval.isBefore.html /library-prerelease/std/datetime/pos_inf_interval.is_before.html +/library-prerelease/std/datetime/PosInfInterval.merge.html /library-prerelease/std/datetime/pos_inf_interval.merge.html +/library-prerelease/std/datetime/PosInfInterval.opAssign.html /library-prerelease/std/datetime/pos_inf_interval.op_assign.html +/library-prerelease/std/datetime/PosInfIntervalRange.empty.html /library-prerelease/std/datetime/pos_inf_interval_range.empty.html +/library-prerelease/std/datetime/PosInfIntervalRange.front.html /library-prerelease/std/datetime/pos_inf_interval_range.front.html +/library-prerelease/std/datetime/PosInfIntervalRange.func.html /library-prerelease/std/datetime/pos_inf_interval_range.func.html +/library-prerelease/std/datetime/PosInfIntervalRange.html /library-prerelease/std/datetime/pos_inf_interval_range.html +/library-prerelease/std/datetime/PosInfIntervalRange.interval.html /library-prerelease/std/datetime/pos_inf_interval_range.interval.html +/library-prerelease/std/datetime/PosInfIntervalRange.opAssign.html /library-prerelease/std/datetime/pos_inf_interval_range.op_assign.html +/library-prerelease/std/datetime/PosInfIntervalRange.popFront.html /library-prerelease/std/datetime/pos_inf_interval_range.pop_front.html +/library-prerelease/std/datetime/PosInfIntervalRange.save.html /library-prerelease/std/datetime/pos_inf_interval_range.save.html +/library-prerelease/std/datetime/PosInfInterval.shift.html /library-prerelease/std/datetime/pos_inf_interval.shift.html +/library-prerelease/std/datetime/PosInfInterval.shift.shift.html /library-prerelease/std/datetime/pos_inf_interval.shift.shift.html +/library-prerelease/std/datetime/PosInfInterval.span.html /library-prerelease/std/datetime/pos_inf_interval.span.html +/library-prerelease/std/datetime/PosInfInterval.this.html /library-prerelease/std/datetime/pos_inf_interval.this.html +/library-prerelease/std/datetime/PosInfInterval.toString.html /library-prerelease/std/datetime/pos_inf_interval.to_string.html +/library-prerelease/std/datetime/PosixTimeZone.defaultTZDatabaseDir.html /library-prerelease/std/datetime/posix_time_zone.default_tz_database_dir.html +/library-prerelease/std/datetime/PosixTimeZone.dstInEffect.html /library-prerelease/std/datetime/posix_time_zone.dst_in_effect.html +/library-prerelease/std/datetime/PosixTimeZone.getInstalledTZNames.html /library-prerelease/std/datetime/posix_time_zone.get_installed_tz_names.html +/library-prerelease/std/datetime/PosixTimeZone.getTimeZone.html /library-prerelease/std/datetime/posix_time_zone.get_time_zone.html +/library-prerelease/std/datetime/PosixTimeZone.hasDST.html /library-prerelease/std/datetime/posix_time_zone.has_dst.html +/library-prerelease/std/datetime/PosixTimeZone.html /library-prerelease/std/datetime/posix_time_zone.html +/library-prerelease/std/datetime/PosixTimeZone.tzToUTC.html /library-prerelease/std/datetime/posix_time_zone.tz_toutc.html +/library-prerelease/std/datetime/PosixTimeZone.utcToTZ.html /library-prerelease/std/datetime/posix_time_zone.utc_totz.html +/library-prerelease/std/datetime/setTZEnvVar.html /library-prerelease/std/datetime/set_tz_env_var.html +/library-prerelease/std/datetime/SimpleTimeZone.dstInEffect.html /library-prerelease/std/datetime/simple_time_zone.dst_in_effect.html +/library-prerelease/std/datetime/SimpleTimeZone.hasDST.html /library-prerelease/std/datetime/simple_time_zone.has_dst.html +/library-prerelease/std/datetime/SimpleTimeZone.html /library-prerelease/std/datetime/simple_time_zone.html +/library-prerelease/std/datetime/SimpleTimeZone.this.html /library-prerelease/std/datetime/simple_time_zone.this.html +/library-prerelease/std/datetime/SimpleTimeZone.tzToUTC.html /library-prerelease/std/datetime/simple_time_zone.tz_toutc.html +/library-prerelease/std/datetime/SimpleTimeZone.utcOffsetAt.html /library-prerelease/std/datetime/simple_time_zone.utc_offset_at.html +/library-prerelease/std/datetime/SimpleTimeZone.utcOffset.html /library-prerelease/std/datetime/simple_time_zone.utc_offset.html +/library-prerelease/std/datetime/SimpleTimeZone.utcToTZ.html /library-prerelease/std/datetime/simple_time_zone.utc_totz.html +/library-prerelease/std/datetime/stdTimeToFILETIME.html /library-prerelease/std/datetime/std_time_tofiletime.html +/library-prerelease/std/datetime/stdTimeToUnixTime.html /library-prerelease/std/datetime/std_time_to_unix_time.html +/library-prerelease/std/datetime/StopWatch.html /library-prerelease/std/datetime/stop_watch.html +/library-prerelease/std/datetime/StopWatch.opEquals.html /library-prerelease/std/datetime/stop_watch.op_equals.html +/library-prerelease/std/datetime/StopWatch.peek.html /library-prerelease/std/datetime/stop_watch.peek.html +/library-prerelease/std/datetime/StopWatch.reset.html /library-prerelease/std/datetime/stop_watch.reset.html +/library-prerelease/std/datetime/StopWatch.running.html /library-prerelease/std/datetime/stop_watch.running.html +/library-prerelease/std/datetime/StopWatch.setMeasured.html /library-prerelease/std/datetime/stop_watch.set_measured.html +/library-prerelease/std/datetime/StopWatch.start.html /library-prerelease/std/datetime/stop_watch.start.html +/library-prerelease/std/datetime/StopWatch.stop.html /library-prerelease/std/datetime/stop_watch.stop.html +/library-prerelease/std/datetime/StopWatch.this.html /library-prerelease/std/datetime/stop_watch.this.html +/library-prerelease/std/datetime/SYSTEMTIMEToSysTime.html /library-prerelease/std/datetime/systemtime_to_sys_time.html +/library-prerelease/std/datetime/SysTime.add.html /library-prerelease/std/datetime/sys_time.add.html +/library-prerelease/std/datetime/SysTime.day.html /library-prerelease/std/datetime/sys_time.day.html +/library-prerelease/std/datetime/SysTime.dayOfGregorianCal.html /library-prerelease/std/datetime/sys_time.day_of_gregorian_cal.html +/library-prerelease/std/datetime/SysTime.dayOfWeek.html /library-prerelease/std/datetime/sys_time.day_of_week.html +/library-prerelease/std/datetime/SysTime.dayOfYear.html /library-prerelease/std/datetime/sys_time.day_of_year.html +/library-prerelease/std/datetime/SysTime.daysInMonth.html /library-prerelease/std/datetime/sys_time.days_in_month.html +/library-prerelease/std/datetime/SysTime.diffMonths.html /library-prerelease/std/datetime/sys_time.diff_months.html +/library-prerelease/std/datetime/SysTime.dstInEffect.html /library-prerelease/std/datetime/sys_time.dst_in_effect.html +/library-prerelease/std/datetime/SysTime.endOfMonth.html /library-prerelease/std/datetime/sys_time.end_of_month.html +/library-prerelease/std/datetime/SysTime.fracSec.html /library-prerelease/std/datetime/sys_time.frac_sec.html +/library-prerelease/std/datetime/SysTime.fracSecs.html /library-prerelease/std/datetime/sys_time.frac_secs.html +/library-prerelease/std/datetime/SysTime.fromISOExtString.html /library-prerelease/std/datetime/sys_time.from_iso_ext_string.html +/library-prerelease/std/datetime/SysTime.fromISOString.html /library-prerelease/std/datetime/sys_time.from_iso_string.html +/library-prerelease/std/datetime/SysTime.fromSimpleString.html /library-prerelease/std/datetime/sys_time.from_simple_string.html +/library-prerelease/std/datetime/SysTime.hour.html /library-prerelease/std/datetime/sys_time.hour.html +/library-prerelease/std/datetime/SysTime.html /library-prerelease/std/datetime/sys_time.html +/library-prerelease/std/datetime/SysTime.isAD.html /library-prerelease/std/datetime/sys_time.is_ad.html +/library-prerelease/std/datetime/SysTime.isLeapYear.html /library-prerelease/std/datetime/sys_time.is_leap_year.html +/library-prerelease/std/datetime/SysTime.isoWeek.html /library-prerelease/std/datetime/sys_time.iso_week.html +/library-prerelease/std/datetime/SysTime.julianDay.html /library-prerelease/std/datetime/sys_time.julian_day.html +/library-prerelease/std/datetime/SysTime.max.html /library-prerelease/std/datetime/sys_time.max.html +/library-prerelease/std/datetime/SysTime.min.html /library-prerelease/std/datetime/sys_time.min.html +/library-prerelease/std/datetime/SysTime.minute.html /library-prerelease/std/datetime/sys_time.minute.html +/library-prerelease/std/datetime/SysTime.modJulianDay.html /library-prerelease/std/datetime/sys_time.mod_julian_day.html +/library-prerelease/std/datetime/SysTime.month.html /library-prerelease/std/datetime/sys_time.month.html +/library-prerelease/std/datetime/SysTime.opAssign.html /library-prerelease/std/datetime/sys_time.op_assign.html +/library-prerelease/std/datetime/SysTime.opBinary.html /library-prerelease/std/datetime/sys_time.op_binary.html +/library-prerelease/std/datetime/SysTime.opCast.html /library-prerelease/std/datetime/sys_time.op_cast.html +/library-prerelease/std/datetime/SysTime.opCmp.html /library-prerelease/std/datetime/sys_time.op_cmp.html +/library-prerelease/std/datetime/SysTime.opEquals.html /library-prerelease/std/datetime/sys_time.op_equals.html +/library-prerelease/std/datetime/SysTime.opOpAssign.html /library-prerelease/std/datetime/sys_time.op_op_assign.html +/library-prerelease/std/datetime/SysTime.roll.html /library-prerelease/std/datetime/sys_time.roll.html +/library-prerelease/std/datetime/SysTime.second.html /library-prerelease/std/datetime/sys_time.second.html +/library-prerelease/std/datetime/SysTime.stdTime.html /library-prerelease/std/datetime/sys_time.std_time.html +/library-prerelease/std/datetime/SysTime.this.html /library-prerelease/std/datetime/sys_time.this.html +/library-prerelease/std/datetime/SysTime.timezone.html /library-prerelease/std/datetime/sys_time.timezone.html +/library-prerelease/std/datetime/SysTimeToDosFileTime.html /library-prerelease/std/datetime/sys_time_to_dos_file_time.html +/library-prerelease/std/datetime/SysTimeToFILETIME.html /library-prerelease/std/datetime/sys_time_tofiletime.html +/library-prerelease/std/datetime/SysTime.toISOExtString.html /library-prerelease/std/datetime/sys_time.to_iso_ext_string.html +/library-prerelease/std/datetime/SysTime.toISOString.html /library-prerelease/std/datetime/sys_time.to_iso_string.html +/library-prerelease/std/datetime/SysTime.toLocalTime.html /library-prerelease/std/datetime/sys_time.to_local_time.html +/library-prerelease/std/datetime/SysTime.toOtherTZ.html /library-prerelease/std/datetime/sys_time.to_other_tz.html +/library-prerelease/std/datetime/SysTime.toSimpleString.html /library-prerelease/std/datetime/sys_time.to_simple_string.html +/library-prerelease/std/datetime/SysTime.toString.html /library-prerelease/std/datetime/sys_time.to_string.html +/library-prerelease/std/datetime/SysTimeToSYSTEMTIME.html /library-prerelease/std/datetime/sys_time_tosystemtime.html +/library-prerelease/std/datetime/SysTime.toTimeVal.html /library-prerelease/std/datetime/sys_time.to_time_val.html +/library-prerelease/std/datetime/SysTime.toTM.html /library-prerelease/std/datetime/sys_time.to_tm.html +/library-prerelease/std/datetime/SysTime.toUnixTime.html /library-prerelease/std/datetime/sys_time.to_unix_time.html +/library-prerelease/std/datetime/SysTime.toUTC.html /library-prerelease/std/datetime/sys_time.to_utc.html +/library-prerelease/std/datetime/SysTime.utcOffset.html /library-prerelease/std/datetime/sys_time.utc_offset.html +/library-prerelease/std/datetime/SysTime.yearBC.html /library-prerelease/std/datetime/sys_time.year_bc.html +/library-prerelease/std/datetime/SysTime.year.html /library-prerelease/std/datetime/sys_time.year.html +/library-prerelease/std/datetime/TimeOfDay.fromISOExtString.html /library-prerelease/std/datetime/time_of_day.from_iso_ext_string.html +/library-prerelease/std/datetime/TimeOfDay.fromISOString.html /library-prerelease/std/datetime/time_of_day.from_iso_string.html +/library-prerelease/std/datetime/TimeOfDay.hour.html /library-prerelease/std/datetime/time_of_day.hour.html +/library-prerelease/std/datetime/TimeOfDay.html /library-prerelease/std/datetime/time_of_day.html +/library-prerelease/std/datetime/TimeOfDay.max.html /library-prerelease/std/datetime/time_of_day.max.html +/library-prerelease/std/datetime/TimeOfDay.min.html /library-prerelease/std/datetime/time_of_day.min.html +/library-prerelease/std/datetime/TimeOfDay.minute.html /library-prerelease/std/datetime/time_of_day.minute.html +/library-prerelease/std/datetime/TimeOfDay.opBinary.html /library-prerelease/std/datetime/time_of_day.op_binary.html +/library-prerelease/std/datetime/TimeOfDay.opCmp.html /library-prerelease/std/datetime/time_of_day.op_cmp.html +/library-prerelease/std/datetime/TimeOfDay.opOpAssign.html /library-prerelease/std/datetime/time_of_day.op_op_assign.html +/library-prerelease/std/datetime/TimeOfDay.roll.html /library-prerelease/std/datetime/time_of_day.roll.html +/library-prerelease/std/datetime/TimeOfDay.second.html /library-prerelease/std/datetime/time_of_day.second.html +/library-prerelease/std/datetime/TimeOfDay.this.html /library-prerelease/std/datetime/time_of_day.this.html +/library-prerelease/std/datetime/TimeOfDay.toISOExtString.html /library-prerelease/std/datetime/time_of_day.to_iso_ext_string.html +/library-prerelease/std/datetime/TimeOfDay.toISOString.html /library-prerelease/std/datetime/time_of_day.to_iso_string.html +/library-prerelease/std/datetime/TimeOfDay.toString.html /library-prerelease/std/datetime/time_of_day.to_string.html +/library-prerelease/std/datetime/timeStrings.html /library-prerelease/std/datetime/time_strings.html +/library-prerelease/std/datetime/TimeZone.dstInEffect.html /library-prerelease/std/datetime/time_zone.dst_in_effect.html +/library-prerelease/std/datetime/TimeZone.dstName.html /library-prerelease/std/datetime/time_zone.dst_name.html +/library-prerelease/std/datetime/TimeZone.getInstalledTZNames.html /library-prerelease/std/datetime/time_zone.get_installed_tz_names.html +/library-prerelease/std/datetime/TimeZone.getTimeZone.html /library-prerelease/std/datetime/time_zone.get_time_zone.html +/library-prerelease/std/datetime/TimeZone.hasDST.html /library-prerelease/std/datetime/time_zone.has_dst.html +/library-prerelease/std/datetime/TimeZone.html /library-prerelease/std/datetime/time_zone.html +/library-prerelease/std/datetime/TimeZone.name.html /library-prerelease/std/datetime/time_zone.name.html +/library-prerelease/std/datetime/TimeZone.stdName.html /library-prerelease/std/datetime/time_zone.std_name.html +/library-prerelease/std/datetime/TimeZone.tzToUTC.html /library-prerelease/std/datetime/time_zone.tz_toutc.html +/library-prerelease/std/datetime/TimeZone.utcOffsetAt.html /library-prerelease/std/datetime/time_zone.utc_offset_at.html +/library-prerelease/std/datetime/TimeZone.utcToTZ.html /library-prerelease/std/datetime/time_zone.utc_totz.html +/library-prerelease/std/datetime/tzDatabaseNameToWindowsTZName.html /library-prerelease/std/datetime/tz_database_name_to_windows_tz_name.html +/library-prerelease/std/datetime/unixTimeToStdTime.html /library-prerelease/std/datetime/unix_time_to_std_time.html +/library-prerelease/std/datetime/UTC.dstInEffect.html /library-prerelease/std/datetime/utc.dst_in_effect.html +/library-prerelease/std/datetime/UTC.hasDST.html /library-prerelease/std/datetime/utc.has_dst.html +/library-prerelease/std/datetime/UTC.html /library-prerelease/std/datetime/utc.html +/library-prerelease/std/datetime/UTC.opCall.html /library-prerelease/std/datetime/utc.op_call.html +/library-prerelease/std/datetime/UTC.tzToUTC.html /library-prerelease/std/datetime/utc.tz_toutc.html +/library-prerelease/std/datetime/UTC.utcOffsetAt.html /library-prerelease/std/datetime/utc.utc_offset_at.html +/library-prerelease/std/datetime/UTC.utcToTZ.html /library-prerelease/std/datetime/utc.utc_totz.html +/library-prerelease/std/datetime/validTimeUnits.html /library-prerelease/std/datetime/valid_time_units.html +/library-prerelease/std/datetime/WindowsTimeZone.dstInEffect.html /library-prerelease/std/datetime/windows_time_zone.dst_in_effect.html +/library-prerelease/std/datetime/WindowsTimeZone.getInstalledTZNames.html /library-prerelease/std/datetime/windows_time_zone.get_installed_tz_names.html +/library-prerelease/std/datetime/WindowsTimeZone.getTimeZone.html /library-prerelease/std/datetime/windows_time_zone.get_time_zone.html +/library-prerelease/std/datetime/WindowsTimeZone.hasDST.html /library-prerelease/std/datetime/windows_time_zone.has_dst.html +/library-prerelease/std/datetime/WindowsTimeZone.html /library-prerelease/std/datetime/windows_time_zone.html +/library-prerelease/std/datetime/WindowsTimeZone.tzToUTC.html /library-prerelease/std/datetime/windows_time_zone.tz_toutc.html +/library-prerelease/std/datetime/WindowsTimeZone.utcToTZ.html /library-prerelease/std/datetime/windows_time_zone.utc_totz.html +/library-prerelease/std/datetime/windowsTZNameToTZDatabaseName.html /library-prerelease/std/datetime/windows_tz_name_totz_database_name.html +/library-prerelease/std/datetime/yearIsLeapYear.html /library-prerelease/std/datetime/year_is_leap_year.html +/library-prerelease/std/digest/crc/CRC32Digest.html /library-prerelease/std/digest/crc/cr_c32_digest.html +/library-prerelease/std/digest/crc/CRC32.finish.html /library-prerelease/std/digest/crc/cr_c32.finish.html +/library-prerelease/std/digest/crc/CRC32.html /library-prerelease/std/digest/crc/cr_c32.html +/library-prerelease/std/digest/crc/crc32Of.html /library-prerelease/std/digest/crc/crc32_of.html +/library-prerelease/std/digest/crc/CRC32.peek.html /library-prerelease/std/digest/crc/cr_c32.peek.html +/library-prerelease/std/digest/crc/CRC32.put.html /library-prerelease/std/digest/crc/cr_c32.put.html +/library-prerelease/std/digest/crc/CRC32.start.html /library-prerelease/std/digest/crc/cr_c32.start.html +/library-prerelease/std/digest/crc/crcHexString.html /library-prerelease/std/digest/crc/crc_hex_string.html +/library-prerelease/std/digest/digest/Digest.digest.html /library-prerelease/std/digest/digest/digest.digest.html +/library-prerelease/std/digest/digest/Digest.finish.html /library-prerelease/std/digest/digest/digest.finish.html +/library-prerelease/std/digest/digest/Digest.html /library-prerelease/std/digest/digest/digest.html +/library-prerelease/std/digest/digest/digestLength.html /library-prerelease/std/digest/digest/digest_length.html +/library-prerelease/std/digest/digest/Digest.length.html /library-prerelease/std/digest/digest/digest.length.html +/library-prerelease/std/digest/digest/Digest.put.html /library-prerelease/std/digest/digest/digest.put.html +/library-prerelease/std/digest/digest/Digest.reset.html /library-prerelease/std/digest/digest/digest.reset.html +/library-prerelease/std/digest/digest/DigestType.html /library-prerelease/std/digest/digest/digest_type.html +/library-prerelease/std/digest/digest/ExampleDigest.finish.html /library-prerelease/std/digest/digest/example_digest.finish.html +/library-prerelease/std/digest/digest/ExampleDigest.html /library-prerelease/std/digest/digest/example_digest.html +/library-prerelease/std/digest/digest/ExampleDigest.put.html /library-prerelease/std/digest/digest/example_digest.put.html +/library-prerelease/std/digest/digest/ExampleDigest.start.html /library-prerelease/std/digest/digest/example_digest.start.html +/library-prerelease/std/digest/digest/hasPeek.html /library-prerelease/std/digest/digest/has_peek.html +/library-prerelease/std/digest/digest/hexDigest.html /library-prerelease/std/digest/digest/hex_digest.html +/library-prerelease/std/digest/digest/isDigest.html /library-prerelease/std/digest/digest/is_digest.html +/library-prerelease/std/digest/digest/makeDigest.html /library-prerelease/std/digest/digest/make_digest.html +/library-prerelease/std/digest/digest/Object.factory.html /library-prerelease/std/digest/digest/object.factory.html +/library-prerelease/std/digest/digest/Object.opCmp.html /library-prerelease/std/digest/digest/object.op_cmp.html +/library-prerelease/std/digest/digest/Object.opEquals.html /library-prerelease/std/digest/digest/object.op_equals.html +/library-prerelease/std/digest/digest/Object.toHash.html /library-prerelease/std/digest/digest/object.to_hash.html +/library-prerelease/std/digest/digest/Object.toString.html /library-prerelease/std/digest/digest/object.to_string.html +/library-prerelease/std/digest/digest/Order.html /library-prerelease/std/digest/digest/order.html +/library-prerelease/std/digest/digest/toHexString.html /library-prerelease/std/digest/digest/to_hex_string.html +/library-prerelease/std/digest/digest/WrapperDigest.finish.html /library-prerelease/std/digest/digest/wrapper_digest.finish.html +/library-prerelease/std/digest/digest/WrapperDigest.html /library-prerelease/std/digest/digest/wrapper_digest.html +/library-prerelease/std/digest/digest/WrapperDigest.length.html /library-prerelease/std/digest/digest/wrapper_digest.length.html +/library-prerelease/std/digest/digest/WrapperDigest.peek.html /library-prerelease/std/digest/digest/wrapper_digest.peek.html +/library-prerelease/std/digest/digest/WrapperDigest.put.html /library-prerelease/std/digest/digest/wrapper_digest.put.html +/library-prerelease/std/digest/digest/WrapperDigest.reset.html /library-prerelease/std/digest/digest/wrapper_digest.reset.html +/library-prerelease/std/digest/digest/WrapperDigest.this.html /library-prerelease/std/digest/digest/wrapper_digest.this.html +/library-prerelease/std/digest/md/MD5Digest.html /library-prerelease/std/digest/md/m_d5_digest.html +/library-prerelease/std/digest/md/MD5.finish.html /library-prerelease/std/digest/md/m_d5.finish.html +/library-prerelease/std/digest/md/MD5.html /library-prerelease/std/digest/md/m_d5.html +/library-prerelease/std/digest/md/md5Of.html /library-prerelease/std/digest/md/md5_of.html +/library-prerelease/std/digest/md/MD5.put.html /library-prerelease/std/digest/md/m_d5.put.html +/library-prerelease/std/digest/md/MD5.start.html /library-prerelease/std/digest/md/m_d5.start.html +/library-prerelease/std/digest/ripemd/RIPEMD160Digest.html /library-prerelease/std/digest/ripemd/ripem_d160_digest.html +/library-prerelease/std/digest/ripemd/RIPEMD160.finish.html /library-prerelease/std/digest/ripemd/ripem_d160.finish.html +/library-prerelease/std/digest/ripemd/RIPEMD160.html /library-prerelease/std/digest/ripemd/ripem_d160.html +/library-prerelease/std/digest/ripemd/ripemd160Of.html /library-prerelease/std/digest/ripemd/ripemd160_of.html +/library-prerelease/std/digest/ripemd/RIPEMD160.put.html /library-prerelease/std/digest/ripemd/ripem_d160.put.html +/library-prerelease/std/digest/ripemd/RIPEMD160.start.html /library-prerelease/std/digest/ripemd/ripem_d160.start.html +/library-prerelease/std/digest/sha/SHA1Digest.html /library-prerelease/std/digest/sha/sh_a1_digest.html +/library-prerelease/std/digest/sha/SHA1.html /library-prerelease/std/digest/sha/sh_a1.html +/library-prerelease/std/digest/sha/sha1Of.html /library-prerelease/std/digest/sha/sha1_of.html +/library-prerelease/std/digest/sha/SHA224Digest.html /library-prerelease/std/digest/sha/sh_a224_digest.html +/library-prerelease/std/digest/sha/SHA224.html /library-prerelease/std/digest/sha/sh_a224.html +/library-prerelease/std/digest/sha/sha224Of.html /library-prerelease/std/digest/sha/sha224_of.html +/library-prerelease/std/digest/sha/SHA256Digest.html /library-prerelease/std/digest/sha/sh_a256_digest.html +/library-prerelease/std/digest/sha/SHA256.html /library-prerelease/std/digest/sha/sh_a256.html +/library-prerelease/std/digest/sha/sha256Of.html /library-prerelease/std/digest/sha/sha256_of.html +/library-prerelease/std/digest/sha/SHA384Digest.html /library-prerelease/std/digest/sha/sh_a384_digest.html +/library-prerelease/std/digest/sha/SHA384.html /library-prerelease/std/digest/sha/sh_a384.html +/library-prerelease/std/digest/sha/sha384Of.html /library-prerelease/std/digest/sha/sha384_of.html +/library-prerelease/std/digest/sha/SHA512_224Digest.html /library-prerelease/std/digest/sha/sh_a512_224_digest.html +/library-prerelease/std/digest/sha/SHA512_224.html /library-prerelease/std/digest/sha/sh_a512_224.html +/library-prerelease/std/digest/sha/sha512_224Of.html /library-prerelease/std/digest/sha/sha512_224_of.html +/library-prerelease/std/digest/sha/SHA512_256Digest.html /library-prerelease/std/digest/sha/sh_a512_256_digest.html +/library-prerelease/std/digest/sha/SHA512_256.html /library-prerelease/std/digest/sha/sh_a512_256.html +/library-prerelease/std/digest/sha/sha512_256Of.html /library-prerelease/std/digest/sha/sha512_256_of.html +/library-prerelease/std/digest/sha/SHA512Digest.html /library-prerelease/std/digest/sha/sh_a512_digest.html +/library-prerelease/std/digest/sha/SHA512.html /library-prerelease/std/digest/sha/sh_a512.html +/library-prerelease/std/digest/sha/sha512Of.html /library-prerelease/std/digest/sha/sha512_of.html +/library-prerelease/std/digest/sha/SHA.finish.html /library-prerelease/std/digest/sha/sha.finish.html +/library-prerelease/std/digest/sha/SHA.html /library-prerelease/std/digest/sha/sha.html +/library-prerelease/std/digest/sha/SHA.put.html /library-prerelease/std/digest/sha/sha.put.html +/library-prerelease/std/digest/sha/SHA.start.html /library-prerelease/std/digest/sha/sha.start.html +/library-prerelease/std/encoding/AsciiChar.html /library-prerelease/std/encoding/ascii_char.html +/library-prerelease/std/encoding/AsciiString.html /library-prerelease/std/encoding/ascii_string.html +/library-prerelease/std/encoding/canEncode.html /library-prerelease/std/encoding/can_encode.html +/library-prerelease/std/encoding/codePoints.html /library-prerelease/std/encoding/code_points.html +/library-prerelease/std/encoding/codeUnits.html /library-prerelease/std/encoding/code_units.html +/library-prerelease/std/encoding/decodeReverse.html /library-prerelease/std/encoding/decode_reverse.html +/library-prerelease/std/encoding/encodedLength.html /library-prerelease/std/encoding/encoded_length.html +/library-prerelease/std/encoding/EncodingException.html /library-prerelease/std/encoding/encoding_exception.html +/library-prerelease/std/encoding/encodingName.html /library-prerelease/std/encoding/encoding_name.html +/library-prerelease/std/encoding/EncodingSchemeASCII.html /library-prerelease/std/encoding/encoding_scheme_ascii.html +/library-prerelease/std/encoding/EncodingScheme.canEncode.html /library-prerelease/std/encoding/encoding_scheme.can_encode.html +/library-prerelease/std/encoding/EncodingScheme.count.html /library-prerelease/std/encoding/encoding_scheme.count.html +/library-prerelease/std/encoding/EncodingScheme.create.html /library-prerelease/std/encoding/encoding_scheme.create.html +/library-prerelease/std/encoding/EncodingScheme.decode.html /library-prerelease/std/encoding/encoding_scheme.decode.html +/library-prerelease/std/encoding/EncodingScheme.encodedLength.html /library-prerelease/std/encoding/encoding_scheme.encoded_length.html +/library-prerelease/std/encoding/EncodingScheme.encode.html /library-prerelease/std/encoding/encoding_scheme.encode.html +/library-prerelease/std/encoding/EncodingScheme.firstSequence.html /library-prerelease/std/encoding/encoding_scheme.first_sequence.html +/library-prerelease/std/encoding/EncodingScheme.html /library-prerelease/std/encoding/encoding_scheme.html +/library-prerelease/std/encoding/EncodingScheme.index.html /library-prerelease/std/encoding/encoding_scheme.index.html +/library-prerelease/std/encoding/EncodingScheme.isValid.html /library-prerelease/std/encoding/encoding_scheme.is_valid.html +/library-prerelease/std/encoding/EncodingSchemeLatin1.html /library-prerelease/std/encoding/encoding_scheme_latin1.html +/library-prerelease/std/encoding/EncodingScheme.names.html /library-prerelease/std/encoding/encoding_scheme.names.html +/library-prerelease/std/encoding/EncodingScheme.register.html /library-prerelease/std/encoding/encoding_scheme.register.html +/library-prerelease/std/encoding/EncodingScheme.replacementSequence.html /library-prerelease/std/encoding/encoding_scheme.replacement_sequence.html +/library-prerelease/std/encoding/EncodingScheme.safeDecode.html /library-prerelease/std/encoding/encoding_scheme.safe_decode.html +/library-prerelease/std/encoding/EncodingScheme.sanitize.html /library-prerelease/std/encoding/encoding_scheme.sanitize.html +/library-prerelease/std/encoding/EncodingScheme.toString.html /library-prerelease/std/encoding/encoding_scheme.to_string.html +/library-prerelease/std/encoding/EncodingSchemeUtf16Native.html /library-prerelease/std/encoding/encoding_scheme_utf16_native.html +/library-prerelease/std/encoding/EncodingSchemeUtf32Native.html /library-prerelease/std/encoding/encoding_scheme_utf32_native.html +/library-prerelease/std/encoding/EncodingSchemeUtf8.html /library-prerelease/std/encoding/encoding_scheme_utf8.html +/library-prerelease/std/encoding/EncodingScheme.validLength.html /library-prerelease/std/encoding/encoding_scheme.valid_length.html +/library-prerelease/std/encoding/EncodingSchemeWindows1252.html /library-prerelease/std/encoding/encoding_scheme_windows1252.html +/library-prerelease/std/encoding/firstSequence.html /library-prerelease/std/encoding/first_sequence.html +/library-prerelease/std/encoding/INVALID_SEQUENCE.html /library-prerelease/std/encoding/invali_d_sequence.html +/library-prerelease/std/encoding/isValidCodePoint.html /library-prerelease/std/encoding/is_valid_code_point.html +/library-prerelease/std/encoding/isValidCodeUnit.html /library-prerelease/std/encoding/is_valid_code_unit.html +/library-prerelease/std/encoding/isValid.html /library-prerelease/std/encoding/is_valid.html +/library-prerelease/std/encoding/lastSequence.html /library-prerelease/std/encoding/last_sequence.html +/library-prerelease/std/encoding/Latin1Char.html /library-prerelease/std/encoding/latin1_char.html +/library-prerelease/std/encoding/Latin1String.html /library-prerelease/std/encoding/latin1_string.html +/library-prerelease/std/encoding/Object.factory.html /library-prerelease/std/encoding/object.factory.html +/library-prerelease/std/encoding/Object.opCmp.html /library-prerelease/std/encoding/object.op_cmp.html +/library-prerelease/std/encoding/Object.opEquals.html /library-prerelease/std/encoding/object.op_equals.html +/library-prerelease/std/encoding/Object.toHash.html /library-prerelease/std/encoding/object.to_hash.html +/library-prerelease/std/encoding/Object.toString.html /library-prerelease/std/encoding/object.to_string.html +/library-prerelease/std/encoding/safeDecode.html /library-prerelease/std/encoding/safe_decode.html +/library-prerelease/std/encoding/Throwable.file.html /library-prerelease/std/encoding/throwable.file.html +/library-prerelease/std/encoding/Throwable.info.html /library-prerelease/std/encoding/throwable.info.html +/library-prerelease/std/encoding/Throwable.line.html /library-prerelease/std/encoding/throwable.line.html +/library-prerelease/std/encoding/Throwable.msg.html /library-prerelease/std/encoding/throwable.msg.html +/library-prerelease/std/encoding/Throwable.next.html /library-prerelease/std/encoding/throwable.next.html +/library-prerelease/std/encoding/Throwable.toString.html /library-prerelease/std/encoding/throwable.to_string.html +/library-prerelease/std/encoding/validLength.html /library-prerelease/std/encoding/valid_length.html +/library-prerelease/std/encoding/Windows1252Char.html /library-prerelease/std/encoding/windows1252_char.html +/library-prerelease/std/encoding/Windows1252String.html /library-prerelease/std/encoding/windows1252_string.html +/library-prerelease/std/exception/assertNotThrown.html /library-prerelease/std/exception/assert_not_thrown.html +/library-prerelease/std/exception/assertThrown.html /library-prerelease/std/exception/assert_thrown.html +/library-prerelease/std/exception/assumeUnique.html /library-prerelease/std/exception/assume_unique.html +/library-prerelease/std/exception/assumeWontThrow.html /library-prerelease/std/exception/assume_wont_throw.html +/library-prerelease/std/exception/collectException.html /library-prerelease/std/exception/collect_exception.html +/library-prerelease/std/exception/collectExceptionMsg.html /library-prerelease/std/exception/collect_exception_msg.html +/library-prerelease/std/exception/doesPointTo.html /library-prerelease/std/exception/does_point_to.html +/library-prerelease/std/exception/emptyExceptionMsg.html /library-prerelease/std/exception/empty_exception_msg.html +/library-prerelease/std/exception/enforceEx.enforceEx.html /library-prerelease/std/exception/enforce_ex.enforce_ex.html +/library-prerelease/std/exception/enforceEx.html /library-prerelease/std/exception/enforce_ex.html +/library-prerelease/std/exception/errnoEnforce.html /library-prerelease/std/exception/errno_enforce.html +/library-prerelease/std/exception/ErrnoException.errno.html /library-prerelease/std/exception/errno_exception.errno.html +/library-prerelease/std/exception/ErrnoException.html /library-prerelease/std/exception/errno_exception.html +/library-prerelease/std/exception/ifThrown.html /library-prerelease/std/exception/if_thrown.html +/library-prerelease/std/exception/Object.factory.html /library-prerelease/std/exception/object.factory.html +/library-prerelease/std/exception/Object.opCmp.html /library-prerelease/std/exception/object.op_cmp.html +/library-prerelease/std/exception/Object.opEquals.html /library-prerelease/std/exception/object.op_equals.html +/library-prerelease/std/exception/Object.toHash.html /library-prerelease/std/exception/object.to_hash.html +/library-prerelease/std/exception/RangePrimitive.access.html /library-prerelease/std/exception/range_primitive.access.html +/library-prerelease/std/exception/RangePrimitive.back.html /library-prerelease/std/exception/range_primitive.back.html +/library-prerelease/std/exception/RangePrimitive.empty.html /library-prerelease/std/exception/range_primitive.empty.html +/library-prerelease/std/exception/RangePrimitive.html /library-prerelease/std/exception/range_primitive.html +/library-prerelease/std/exception/RangePrimitive.length.html /library-prerelease/std/exception/range_primitive.length.html +/library-prerelease/std/exception/RangePrimitive.opDollar.html /library-prerelease/std/exception/range_primitive.op_dollar.html +/library-prerelease/std/exception/RangePrimitive.opIndex.html /library-prerelease/std/exception/range_primitive.op_index.html +/library-prerelease/std/exception/RangePrimitive.opSlice.html /library-prerelease/std/exception/range_primitive.op_slice.html +/library-prerelease/std/exception/RangePrimitive.popBack.html /library-prerelease/std/exception/range_primitive.pop_back.html +/library-prerelease/std/exception/RangePrimitive.popFront.html /library-prerelease/std/exception/range_primitive.pop_front.html +/library-prerelease/std/exception/RangePrimitive.pop.html /library-prerelease/std/exception/range_primitive.pop.html +/library-prerelease/std/exception/RangePrimitive.save.html /library-prerelease/std/exception/range_primitive.save.html +/library-prerelease/std/exception/Throwable.file.html /library-prerelease/std/exception/throwable.file.html +/library-prerelease/std/exception/Throwable.info.html /library-prerelease/std/exception/throwable.info.html +/library-prerelease/std/exception/Throwable.line.html /library-prerelease/std/exception/throwable.line.html +/library-prerelease/std/exception/Throwable.msg.html /library-prerelease/std/exception/throwable.msg.html +/library-prerelease/std/exception/Throwable.next.html /library-prerelease/std/exception/throwable.next.html +/library-prerelease/std/exception/Throwable.toString.html /library-prerelease/std/exception/throwable.to_string.html +/library-prerelease/std/file/attrIsDir.html /library-prerelease/std/file/attr_is_dir.html +/library-prerelease/std/file/attrIsFile.html /library-prerelease/std/file/attr_is_file.html +/library-prerelease/std/file/attrIsSymlink.html /library-prerelease/std/file/attr_is_symlink.html +/library-prerelease/std/file/dirEntries.html /library-prerelease/std/file/dir_entries.html +/library-prerelease/std/file/DirEntry.attributes.html /library-prerelease/std/file/dir_entry.attributes.html +/library-prerelease/std/file/DirEntry.html /library-prerelease/std/file/dir_entry.html +/library-prerelease/std/file/DirEntry.isDir.html /library-prerelease/std/file/dir_entry.is_dir.html +/library-prerelease/std/file/DirEntry.isFile.html /library-prerelease/std/file/dir_entry.is_file.html +/library-prerelease/std/file/DirEntry.isSymlink.html /library-prerelease/std/file/dir_entry.is_symlink.html +/library-prerelease/std/file/DirEntry.linkAttributes.html /library-prerelease/std/file/dir_entry.link_attributes.html +/library-prerelease/std/file/DirEntry.name.html /library-prerelease/std/file/dir_entry.name.html +/library-prerelease/std/file/DirEntry.size.html /library-prerelease/std/file/dir_entry.size.html +/library-prerelease/std/file/DirEntry.statBuf.html /library-prerelease/std/file/dir_entry.stat_buf.html +/library-prerelease/std/file/DirEntry.this.html /library-prerelease/std/file/dir_entry.this.html +/library-prerelease/std/file/DirEntry.timeCreated.html /library-prerelease/std/file/dir_entry.time_created.html +/library-prerelease/std/file/DirEntry.timeLastAccessed.html /library-prerelease/std/file/dir_entry.time_last_accessed.html +/library-prerelease/std/file/DirEntry.timeLastModified.html /library-prerelease/std/file/dir_entry.time_last_modified.html +/library-prerelease/std/file/FileException.errno.html /library-prerelease/std/file/file_exception.errno.html +/library-prerelease/std/file/FileException.html /library-prerelease/std/file/file_exception.html +/library-prerelease/std/file/FileException.this.html /library-prerelease/std/file/file_exception.this.html +/library-prerelease/std/file/getAttributes.html /library-prerelease/std/file/get_attributes.html +/library-prerelease/std/file/getLinkAttributes.html /library-prerelease/std/file/get_link_attributes.html +/library-prerelease/std/file/getSize.html /library-prerelease/std/file/get_size.html +/library-prerelease/std/file/getTimes.html /library-prerelease/std/file/get_times.html +/library-prerelease/std/file/getTimesWin.html /library-prerelease/std/file/get_times_win.html +/library-prerelease/std/file/isDir.html /library-prerelease/std/file/is_dir.html +/library-prerelease/std/file/isFile.html /library-prerelease/std/file/is_file.html +/library-prerelease/std/file/isSymlink.html /library-prerelease/std/file/is_symlink.html +/library-prerelease/std/file/mkdirRecurse.html /library-prerelease/std/file/mkdir_recurse.html +/library-prerelease/std/file/Object.factory.html /library-prerelease/std/file/object.factory.html +/library-prerelease/std/file/Object.opCmp.html /library-prerelease/std/file/object.op_cmp.html +/library-prerelease/std/file/Object.opEquals.html /library-prerelease/std/file/object.op_equals.html +/library-prerelease/std/file/Object.toHash.html /library-prerelease/std/file/object.to_hash.html +/library-prerelease/std/file/preserveAttributesDefault.html /library-prerelease/std/file/preserve_attributes_default.html +/library-prerelease/std/file/readLink.html /library-prerelease/std/file/read_link.html +/library-prerelease/std/file/readText.html /library-prerelease/std/file/read_text.html +/library-prerelease/std/file/rmdirRecurse.html /library-prerelease/std/file/rmdir_recurse.html +/library-prerelease/std/file/setAttributes.html /library-prerelease/std/file/set_attributes.html +/library-prerelease/std/file/setTimes.html /library-prerelease/std/file/set_times.html +/library-prerelease/std/file/SpanMode.breadth.html /library-prerelease/std/file/span_mode.breadth.html +/library-prerelease/std/file/SpanMode.depth.html /library-prerelease/std/file/span_mode.depth.html +/library-prerelease/std/file/SpanMode.html /library-prerelease/std/file/span_mode.html +/library-prerelease/std/file/SpanMode.shallow.html /library-prerelease/std/file/span_mode.shallow.html +/library-prerelease/std/file/tempDir.html /library-prerelease/std/file/temp_dir.html +/library-prerelease/std/file/thisExePath.html /library-prerelease/std/file/this_exe_path.html +/library-prerelease/std/file/Throwable.file.html /library-prerelease/std/file/throwable.file.html +/library-prerelease/std/file/Throwable.info.html /library-prerelease/std/file/throwable.info.html +/library-prerelease/std/file/Throwable.line.html /library-prerelease/std/file/throwable.line.html +/library-prerelease/std/file/Throwable.msg.html /library-prerelease/std/file/throwable.msg.html +/library-prerelease/std/file/Throwable.next.html /library-prerelease/std/file/throwable.next.html +/library-prerelease/std/file/Throwable.toString.html /library-prerelease/std/file/throwable.to_string.html +/library-prerelease/std/file/timeLastModified.html /library-prerelease/std/file/time_last_modified.html +/library-prerelease/std/functional/binaryFun.html /library-prerelease/std/functional/binary_fun.html +/library-prerelease/std/functional/binaryReverseArgs.binaryReverseArgs.html /library-prerelease/std/functional/binary_reverse_args.binary_reverse_args.html +/library-prerelease/std/functional/binaryReverseArgs.html /library-prerelease/std/functional/binary_reverse_args.html +/library-prerelease/std/functional/equalTo.html /library-prerelease/std/functional/equal_to.html +/library-prerelease/std/functional/greaterThan.html /library-prerelease/std/functional/greater_than.html +/library-prerelease/std/functional/lessThan.html /library-prerelease/std/functional/less_than.html +/library-prerelease/std/functional/reverseArgs.html /library-prerelease/std/functional/reverse_args.html +/library-prerelease/std/functional/reverseArgs.reverseArgs.html /library-prerelease/std/functional/reverse_args.reverse_args.html +/library-prerelease/std/functional/toDelegate.html /library-prerelease/std/functional/to_delegate.html +/library-prerelease/std/functional/unaryFun.html /library-prerelease/std/functional/unary_fun.html +/library-prerelease/std/getopt/arraySep.html /library-prerelease/std/getopt/array_sep.html +/library-prerelease/std/getopt/assignChar.html /library-prerelease/std/getopt/assign_char.html +/library-prerelease/std/getopt/config.caseInsensitive.html /library-prerelease/std/getopt/config.case_insensitive.html +/library-prerelease/std/getopt/config.caseSensitive.html /library-prerelease/std/getopt/config.case_sensitive.html +/library-prerelease/std/getopt/config.keepEndOfOptions.html /library-prerelease/std/getopt/config.keep_end_of_options.html +/library-prerelease/std/getopt/config.noBundling.html /library-prerelease/std/getopt/config.no_bundling.html +/library-prerelease/std/getopt/config.noPassThrough.html /library-prerelease/std/getopt/config.no_pass_through.html +/library-prerelease/std/getopt/config.passThrough.html /library-prerelease/std/getopt/config.pass_through.html +/library-prerelease/std/getopt/config.stopOnFirstNonOption.html /library-prerelease/std/getopt/config.stop_on_first_non_option.html +/library-prerelease/std/getopt/defaultGetoptFormatter.html /library-prerelease/std/getopt/default_getopt_formatter.html +/library-prerelease/std/getopt/defaultGetoptPrinter.html /library-prerelease/std/getopt/default_getopt_printer.html +/library-prerelease/std/getopt/endOfOptions.html /library-prerelease/std/getopt/end_of_options.html +/library-prerelease/std/getopt/GetOptException.html /library-prerelease/std/getopt/get_opt_exception.html +/library-prerelease/std/getopt/GetoptResult.helpWanted.html /library-prerelease/std/getopt/getopt_result.help_wanted.html +/library-prerelease/std/getopt/GetoptResult.html /library-prerelease/std/getopt/getopt_result.html +/library-prerelease/std/getopt/GetoptResult.options.html /library-prerelease/std/getopt/getopt_result.options.html +/library-prerelease/std/getopt/Object.factory.html /library-prerelease/std/getopt/object.factory.html +/library-prerelease/std/getopt/Object.opCmp.html /library-prerelease/std/getopt/object.op_cmp.html +/library-prerelease/std/getopt/Object.opEquals.html /library-prerelease/std/getopt/object.op_equals.html +/library-prerelease/std/getopt/Object.toHash.html /library-prerelease/std/getopt/object.to_hash.html +/library-prerelease/std/getopt/optionChar.html /library-prerelease/std/getopt/option_char.html +/library-prerelease/std/getopt/Option.help.html /library-prerelease/std/getopt/option.help.html +/library-prerelease/std/getopt/Option.html /library-prerelease/std/getopt/option.html +/library-prerelease/std/getopt/Option.optLong.html /library-prerelease/std/getopt/option.opt_long.html +/library-prerelease/std/getopt/Option.optShort.html /library-prerelease/std/getopt/option.opt_short.html +/library-prerelease/std/getopt/Option.required.html /library-prerelease/std/getopt/option.required.html +/library-prerelease/std/getopt/Throwable.file.html /library-prerelease/std/getopt/throwable.file.html +/library-prerelease/std/getopt/Throwable.info.html /library-prerelease/std/getopt/throwable.info.html +/library-prerelease/std/getopt/Throwable.line.html /library-prerelease/std/getopt/throwable.line.html +/library-prerelease/std/getopt/Throwable.msg.html /library-prerelease/std/getopt/throwable.msg.html +/library-prerelease/std/getopt/Throwable.next.html /library-prerelease/std/getopt/throwable.next.html +/library-prerelease/std/getopt/Throwable.toString.html /library-prerelease/std/getopt/throwable.to_string.html +/library-prerelease/std/json/JSONException.html /library-prerelease/std/json/json_exception.html +/library-prerelease/std/json/JSON_TYPE.ARRAY.html /library-prerelease/std/json/jso_n_type.array.html +/library-prerelease/std/json/JSON_TYPE.FALSE.html /library-prerelease/std/json/jso_n_type.false.html +/library-prerelease/std/json/JSON_TYPE.FLOAT.html /library-prerelease/std/json/jso_n_type.float.html +/library-prerelease/std/json/JSON_TYPE.html /library-prerelease/std/json/jso_n_type.html +/library-prerelease/std/json/JSON_TYPE.INTEGER.html /library-prerelease/std/json/jso_n_type.integer.html +/library-prerelease/std/json/JSON_TYPE.NULL.html /library-prerelease/std/json/jso_n_type.null.html +/library-prerelease/std/json/JSON_TYPE.OBJECT.html /library-prerelease/std/json/jso_n_type.object.html +/library-prerelease/std/json/JSON_TYPE.STRING.html /library-prerelease/std/json/jso_n_type.string.html +/library-prerelease/std/json/JSON_TYPE.TRUE.html /library-prerelease/std/json/jso_n_type.true.html +/library-prerelease/std/json/JSON_TYPE.UINTEGER.html /library-prerelease/std/json/jso_n_type.uinteger.html +/library-prerelease/std/json/JSONValue.array.html /library-prerelease/std/json/json_value.array.html +/library-prerelease/std/json/JSONValue.floating.html /library-prerelease/std/json/json_value.floating.html +/library-prerelease/std/json/JSONValue.html /library-prerelease/std/json/json_value.html +/library-prerelease/std/json/JSONValue.integer.html /library-prerelease/std/json/json_value.integer.html +/library-prerelease/std/json/JSONValue.isNull.html /library-prerelease/std/json/json_value.is_null.html +/library-prerelease/std/json/JSONValue.object.html /library-prerelease/std/json/json_value.object.html +/library-prerelease/std/json/JSONValue.opApply.html /library-prerelease/std/json/json_value.op_apply.html +/library-prerelease/std/json/JSONValue.opIndexAssign.html /library-prerelease/std/json/json_value.op_index_assign.html +/library-prerelease/std/json/JSONValue.opIndex.html /library-prerelease/std/json/json_value.op_index.html +/library-prerelease/std/json/JSONValue.str.html /library-prerelease/std/json/json_value.str.html +/library-prerelease/std/json/JSONValue.this.html /library-prerelease/std/json/json_value.this.html +/library-prerelease/std/json/JSONValue.toPrettyString.html /library-prerelease/std/json/json_value.to_pretty_string.html +/library-prerelease/std/json/JSONValue.toString.html /library-prerelease/std/json/json_value.to_string.html +/library-prerelease/std/json/JSONValue.type.html /library-prerelease/std/json/json_value.type.html +/library-prerelease/std/json/JSONValue.uinteger.html /library-prerelease/std/json/json_value.uinteger.html +/library-prerelease/std/json/Object.factory.html /library-prerelease/std/json/object.factory.html +/library-prerelease/std/json/Object.opCmp.html /library-prerelease/std/json/object.op_cmp.html +/library-prerelease/std/json/Object.opEquals.html /library-prerelease/std/json/object.op_equals.html +/library-prerelease/std/json/Object.toHash.html /library-prerelease/std/json/object.to_hash.html +/library-prerelease/std/json/parseJSON.html /library-prerelease/std/json/parse_json.html +/library-prerelease/std/json/Throwable.file.html /library-prerelease/std/json/throwable.file.html +/library-prerelease/std/json/Throwable.info.html /library-prerelease/std/json/throwable.info.html +/library-prerelease/std/json/Throwable.line.html /library-prerelease/std/json/throwable.line.html +/library-prerelease/std/json/Throwable.msg.html /library-prerelease/std/json/throwable.msg.html +/library-prerelease/std/json/Throwable.next.html /library-prerelease/std/json/throwable.next.html +/library-prerelease/std/json/Throwable.toString.html /library-prerelease/std/json/throwable.to_string.html +/library-prerelease/std/json/toJSON.html /library-prerelease/std/json/to_json.html +/library-prerelease/std/math/approxEqual.html /library-prerelease/std/math/approx_equal.html +/library-prerelease/std/math/E.html /library-prerelease/std/math/e.html +/library-prerelease/std/math/FloatingPointControl.disableExceptions.html /library-prerelease/std/math/floating_point_control.disable_exceptions.html +/library-prerelease/std/math/FloatingPointControl.enabledExceptions.html /library-prerelease/std/math/floating_point_control.enabled_exceptions.html +/library-prerelease/std/math/FloatingPointControl.enableExceptions.html /library-prerelease/std/math/floating_point_control.enable_exceptions.html +/library-prerelease/std/math/FloatingPointControl.hasExceptionTraps.html /library-prerelease/std/math/floating_point_control.has_exception_traps.html +/library-prerelease/std/math/FloatingPointControl.html /library-prerelease/std/math/floating_point_control.html +/library-prerelease/std/math/FloatingPointControl.rounding.html /library-prerelease/std/math/floating_point_control.rounding.html +/library-prerelease/std/math/FloatingPointControl.severeExceptions.html /library-prerelease/std/math/floating_point_control.severe_exceptions.html +/library-prerelease/std/math/getNaNPayload.html /library-prerelease/std/math/get_nan_payload.html +/library-prerelease/std/math/IeeeFlags.divByZero.html /library-prerelease/std/math/ieee_flags.div_by_zero.html +/library-prerelease/std/math/ieeeFlags.html /library-prerelease/std/math/ieee_flags.html +/library-prerelease/std/math/IeeeFlags.html /library-prerelease/std/math/ieee_flags.html +/library-prerelease/std/math/IeeeFlags.inexact.html /library-prerelease/std/math/ieee_flags.inexact.html +/library-prerelease/std/math/IeeeFlags.invalid.html /library-prerelease/std/math/ieee_flags.invalid.html +/library-prerelease/std/math/IeeeFlags.overflow.html /library-prerelease/std/math/ieee_flags.overflow.html +/library-prerelease/std/math/IeeeFlags.underflow.html /library-prerelease/std/math/ieee_flags.underflow.html +/library-prerelease/std/math/isFinite.html /library-prerelease/std/math/is_finite.html +/library-prerelease/std/math/isIdentical.html /library-prerelease/std/math/is_identical.html +/library-prerelease/std/math/isInfinity.html /library-prerelease/std/math/is_infinity.html +/library-prerelease/std/math/isNaN.html /library-prerelease/std/math/is_nan.html +/library-prerelease/std/math/isNormal.html /library-prerelease/std/math/is_normal.html +/library-prerelease/std/math/isSubnormal.html /library-prerelease/std/math/is_subnormal.html +/library-prerelease/std/math/LN10.html /library-prerelease/std/math/l_n10.html +/library-prerelease/std/math/LN2.html /library-prerelease/std/math/l_n2.html +/library-prerelease/std/math/LOG10E.html /library-prerelease/std/math/lo_g10.html +/library-prerelease/std/math/LOG2E.html /library-prerelease/std/math/lo_g2e.html +/library-prerelease/std/math/LOG2.html /library-prerelease/std/math/lo_g2.html +/library-prerelease/std/math/LOG2T.html /library-prerelease/std/math/lo_g2t.html +/library-prerelease/std/math/M_1_PI.html /library-prerelease/std/math/m_1__pi.html +/library-prerelease/std/math/M_2_PI.html /library-prerelease/std/math/m_2__pi.html +/library-prerelease/std/math/M_2_SQRTPI.html /library-prerelease/std/math/m_2__sqrtpi.html +/library-prerelease/std/math/NaN.html /library-prerelease/std/math/nan.html +/library-prerelease/std/math/nextDown.html /library-prerelease/std/math/next_down.html +/library-prerelease/std/math/nextUp.html /library-prerelease/std/math/next_up.html +/library-prerelease/std/math/PI_2.html /library-prerelease/std/math/p_i_2.html +/library-prerelease/std/math/PI_4.html /library-prerelease/std/math/p_i_4.html +/library-prerelease/std/math/PI.html /library-prerelease/std/math/pi.html +/library-prerelease/std/math/resetIeeeFlags.html /library-prerelease/std/math/reset_ieee_flags.html +/library-prerelease/std/mathspecial/betaIncomplete.html /library-prerelease/std/mathspecial/beta_incomplete.html +/library-prerelease/std/mathspecial/betaIncompleteInverse.html /library-prerelease/std/mathspecial/beta_incomplete_inverse.html +/library-prerelease/std/mathspecial/gammaIncompleteCompl.html /library-prerelease/std/mathspecial/gamma_incomplete_compl.html +/library-prerelease/std/mathspecial/gammaIncompleteComplInverse.html /library-prerelease/std/mathspecial/gamma_incomplete_compl_inverse.html +/library-prerelease/std/mathspecial/gammaIncomplete.html /library-prerelease/std/mathspecial/gamma_incomplete.html +/library-prerelease/std/mathspecial/logGamma.html /library-prerelease/std/mathspecial/log_gamma.html +/library-prerelease/std/mathspecial/logmdigammaInverse.html /library-prerelease/std/mathspecial/logmdigamma_inverse.html +/library-prerelease/std/mathspecial/normalDistribution.html /library-prerelease/std/mathspecial/normal_distribution.html +/library-prerelease/std/mathspecial/normalDistributionInverse.html /library-prerelease/std/mathspecial/normal_distribution_inverse.html +/library-prerelease/std/mathspecial/sgnGamma.html /library-prerelease/std/mathspecial/sgn_gamma.html +/library-prerelease/std/math/SQRT1_2.html /library-prerelease/std/math/sqr_t1_2.html +/library-prerelease/std/math/SQRT2.html /library-prerelease/std/math/sqr_t2.html +/library-prerelease/std/mmfile/MmFile.html /library-prerelease/std/mmfile/mm_file.html +/library-prerelease/std/mmfile/MmFile.length.html /library-prerelease/std/mmfile/mm_file.length.html +/library-prerelease/std/mmfile/MmFile.mode.html /library-prerelease/std/mmfile/mm_file.mode.html +/library-prerelease/std/mmfile/MmFile.Mode.html /library-prerelease/std/mmfile/mm_file.mode.html +/library-prerelease/std/mmfile/MmFile.Mode.readCopyOnWrite.html /library-prerelease/std/mmfile/mm_file.mode.read_copy_on_write.html +/library-prerelease/std/mmfile/MmFile.Mode.read.html /library-prerelease/std/mmfile/mm_file.mode.read.html +/library-prerelease/std/mmfile/MmFile.Mode.readWrite.html /library-prerelease/std/mmfile/mm_file.mode.read_write.html +/library-prerelease/std/mmfile/MmFile.Mode.readWriteNew.html /library-prerelease/std/mmfile/mm_file.mode.read_write_new.html +/library-prerelease/std/mmfile/MmFile.opIndexAssign.html /library-prerelease/std/mmfile/mm_file.op_index_assign.html +/library-prerelease/std/mmfile/MmFile.opIndex.html /library-prerelease/std/mmfile/mm_file.op_index.html +/library-prerelease/std/mmfile/MmFile.opSlice.html /library-prerelease/std/mmfile/mm_file.op_slice.html +/library-prerelease/std/mmfile/MmFile.this.html /library-prerelease/std/mmfile/mm_file.this.html +/library-prerelease/std/mmfile/Object.factory.html /library-prerelease/std/mmfile/object.factory.html +/library-prerelease/std/mmfile/Object.opCmp.html /library-prerelease/std/mmfile/object.op_cmp.html +/library-prerelease/std/mmfile/Object.opEquals.html /library-prerelease/std/mmfile/object.op_equals.html +/library-prerelease/std/mmfile/Object.toHash.html /library-prerelease/std/mmfile/object.to_hash.html +/library-prerelease/std/mmfile/Object.toString.html /library-prerelease/std/mmfile/object.to_string.html +/library-prerelease/std/net/curl/AutoProtocol.html /library-prerelease/std/net/curl/auto_protocol.html +/library-prerelease/std/net/curl/byChunkAsync.html /library-prerelease/std/net/curl/by_chunk_async.html +/library-prerelease/std/net/curl/byChunk.html /library-prerelease/std/net/curl/by_chunk.html +/library-prerelease/std/net/curl/byLineAsync.html /library-prerelease/std/net/curl/by_line_async.html +/library-prerelease/std/net/curl/byLine.html /library-prerelease/std/net/curl/by_line.html +/library-prerelease/std/net/curl/Curl.clear.html /library-prerelease/std/net/curl/curl.clear.html +/library-prerelease/std/net/curl/Curl.clearIfSupported.html /library-prerelease/std/net/curl/curl.clear_if_supported.html +/library-prerelease/std/net/curl/CurlCode.html /library-prerelease/std/net/curl/curl_code.html +/library-prerelease/std/net/curl/Curl.dup.html /library-prerelease/std/net/curl/curl.dup.html +/library-prerelease/std/net/curl/CurlException.html /library-prerelease/std/net/curl/curl_exception.html +/library-prerelease/std/net/curl/CurlException.this.html /library-prerelease/std/net/curl/curl_exception.this.html +/library-prerelease/std/net/curl/Curl.html /library-prerelease/std/net/curl/curl.html +/library-prerelease/std/net/curl/Curl.initialize.html /library-prerelease/std/net/curl/curl.initialize.html +/library-prerelease/std/net/curl/Curl.onProgress.html /library-prerelease/std/net/curl/curl.on_progress.html +/library-prerelease/std/net/curl/Curl.onReceiveHeader.html /library-prerelease/std/net/curl/curl.on_receive_header.html +/library-prerelease/std/net/curl/Curl.onReceive.html /library-prerelease/std/net/curl/curl.on_receive.html +/library-prerelease/std/net/curl/Curl.onSeek.html /library-prerelease/std/net/curl/curl.on_seek.html +/library-prerelease/std/net/curl/Curl.onSend.html /library-prerelease/std/net/curl/curl.on_send.html +/library-prerelease/std/net/curl/Curl.onSocketOption.html /library-prerelease/std/net/curl/curl.on_socket_option.html +/library-prerelease/std/net/curl/Curl.pause.html /library-prerelease/std/net/curl/curl.pause.html +/library-prerelease/std/net/curl/Curl.perform.html /library-prerelease/std/net/curl/curl.perform.html +/library-prerelease/std/net/curl/Curl.set.html /library-prerelease/std/net/curl/curl.set.html +/library-prerelease/std/net/curl/Curl.shutdown.html /library-prerelease/std/net/curl/curl.shutdown.html +/library-prerelease/std/net/curl/CurlTimeoutException.html /library-prerelease/std/net/curl/curl_timeout_exception.html +/library-prerelease/std/net/curl/CurlTimeoutException.this.html /library-prerelease/std/net/curl/curl_timeout_exception.this.html +/library-prerelease/std/net/curl/FTP.addCommand.html /library-prerelease/std/net/curl/ftp.add_command.html +/library-prerelease/std/net/curl/FTP.clearCommands.html /library-prerelease/std/net/curl/ftp.clear_commands.html +/library-prerelease/std/net/curl/FTP.connectTimeout.html /library-prerelease/std/net/curl/ftp.connect_timeout.html +/library-prerelease/std/net/curl/FTP.contentLength.html /library-prerelease/std/net/curl/ftp.content_length.html +/library-prerelease/std/net/curl/FTP.CurlProxy.html /library-prerelease/std/net/curl/ftp.curl_proxy.html +/library-prerelease/std/net/curl/FTP.dataTimeout.html /library-prerelease/std/net/curl/ftp.data_timeout.html +/library-prerelease/std/net/curl/FTP.dnsTimeout.html /library-prerelease/std/net/curl/ftp.dns_timeout.html +/library-prerelease/std/net/curl/FTP.encoding.html /library-prerelease/std/net/curl/ftp.encoding.html +/library-prerelease/std/net/curl/FTP.html /library-prerelease/std/net/curl/ftp.html +/library-prerelease/std/net/curl/FTP.isStopped.html /library-prerelease/std/net/curl/ftp.is_stopped.html +/library-prerelease/std/net/curl/FTP.localPort.html /library-prerelease/std/net/curl/ftp.local_port.html +/library-prerelease/std/net/curl/FTP.localPortRange.html /library-prerelease/std/net/curl/ftp.local_port_range.html +/library-prerelease/std/net/curl/FTP.netInterface.html /library-prerelease/std/net/curl/ftp.net_interface.html +/library-prerelease/std/net/curl/FTP.onProgress.html /library-prerelease/std/net/curl/ftp.on_progress.html +/library-prerelease/std/net/curl/FTP.onReceive.html /library-prerelease/std/net/curl/ftp.on_receive.html +/library-prerelease/std/net/curl/FTP.onSend.html /library-prerelease/std/net/curl/ftp.on_send.html +/library-prerelease/std/net/curl/FTP.opCall.html /library-prerelease/std/net/curl/ftp.op_call.html +/library-prerelease/std/net/curl/FTP.operationTimeout.html /library-prerelease/std/net/curl/ftp.operation_timeout.html +/library-prerelease/std/net/curl/FTP.perform.html /library-prerelease/std/net/curl/ftp.perform.html +/library-prerelease/std/net/curl/FTP.proxy.html /library-prerelease/std/net/curl/ftp.proxy.html +/library-prerelease/std/net/curl/FTP.proxyPort.html /library-prerelease/std/net/curl/ftp.proxy_port.html +/library-prerelease/std/net/curl/FTP.proxyType.html /library-prerelease/std/net/curl/ftp.proxy_type.html +/library-prerelease/std/net/curl/FTP.requestAbort.html /library-prerelease/std/net/curl/ftp.request_abort.html +/library-prerelease/std/net/curl/FTP.requestPause.html /library-prerelease/std/net/curl/ftp.request_pause.html +/library-prerelease/std/net/curl/FTP.setAuthentication.html /library-prerelease/std/net/curl/ftp.set_authentication.html +/library-prerelease/std/net/curl/FTP.setProxyAuthentication.html /library-prerelease/std/net/curl/ftp.set_proxy_authentication.html +/library-prerelease/std/net/curl/FTP.shutdown.html /library-prerelease/std/net/curl/ftp.shutdown.html +/library-prerelease/std/net/curl/FTP.tcpNoDelay.html /library-prerelease/std/net/curl/ftp.tcp_no_delay.html +/library-prerelease/std/net/curl/FTP.url.html /library-prerelease/std/net/curl/ftp.url.html +/library-prerelease/std/net/curl/FTP.verbose.html /library-prerelease/std/net/curl/ftp.verbose.html +/library-prerelease/std/net/curl/HTTP.addRequestHeader.html /library-prerelease/std/net/curl/http.add_request_header.html +/library-prerelease/std/net/curl/HTTP.authenticationMethod.html /library-prerelease/std/net/curl/http.authentication_method.html +/library-prerelease/std/net/curl/HTTP.AuthMethod.html /library-prerelease/std/net/curl/http.auth_method.html +/library-prerelease/std/net/curl/HTTP.caInfo.html /library-prerelease/std/net/curl/http.ca_info.html +/library-prerelease/std/net/curl/HTTP.clearAllCookies.html /library-prerelease/std/net/curl/http.clear_all_cookies.html +/library-prerelease/std/net/curl/HTTP.clearRequestHeaders.html /library-prerelease/std/net/curl/http.clear_request_headers.html +/library-prerelease/std/net/curl/HTTP.clearSessionCookies.html /library-prerelease/std/net/curl/http.clear_session_cookies.html +/library-prerelease/std/net/curl/HTTP.connectTimeout.html /library-prerelease/std/net/curl/http.connect_timeout.html +/library-prerelease/std/net/curl/HTTP.contentLength.html /library-prerelease/std/net/curl/http.content_length.html +/library-prerelease/std/net/curl/HTTP.CurlProxy.html /library-prerelease/std/net/curl/http.curl_proxy.html +/library-prerelease/std/net/curl/HTTP.dataTimeout.html /library-prerelease/std/net/curl/http.data_timeout.html +/library-prerelease/std/net/curl/HTTP.defaultUserAgent.html /library-prerelease/std/net/curl/http.default_user_agent.html +/library-prerelease/std/net/curl/HTTP.dnsTimeout.html /library-prerelease/std/net/curl/http.dns_timeout.html +/library-prerelease/std/net/curl/HTTP.flushCookieJar.html /library-prerelease/std/net/curl/http.flush_cookie_jar.html +/library-prerelease/std/net/curl/HTTP.html /library-prerelease/std/net/curl/http.html +/library-prerelease/std/net/curl/HTTP.isStopped.html /library-prerelease/std/net/curl/http.is_stopped.html +/library-prerelease/std/net/curl/HTTP.localPort.html /library-prerelease/std/net/curl/http.local_port.html +/library-prerelease/std/net/curl/HTTP.localPortRange.html /library-prerelease/std/net/curl/http.local_port_range.html +/library-prerelease/std/net/curl/HTTP.maxRedirects.html /library-prerelease/std/net/curl/http.max_redirects.html +/library-prerelease/std/net/curl/HTTP.method.html /library-prerelease/std/net/curl/http.method.html +/library-prerelease/std/net/curl/HTTP.Method.html /library-prerelease/std/net/curl/http.method.html +/library-prerelease/std/net/curl/HTTP.netInterface.html /library-prerelease/std/net/curl/http.net_interface.html +/library-prerelease/std/net/curl/HTTP.onProgress.html /library-prerelease/std/net/curl/http.on_progress.html +/library-prerelease/std/net/curl/HTTP.onReceiveHeader.html /library-prerelease/std/net/curl/http.on_receive_header.html +/library-prerelease/std/net/curl/HTTP.onReceive.html /library-prerelease/std/net/curl/http.on_receive.html +/library-prerelease/std/net/curl/HTTP.onReceiveStatusLine.html /library-prerelease/std/net/curl/http.on_receive_status_line.html +/library-prerelease/std/net/curl/HTTP.onSend.html /library-prerelease/std/net/curl/http.on_send.html +/library-prerelease/std/net/curl/HTTP.opCall.html /library-prerelease/std/net/curl/http.op_call.html +/library-prerelease/std/net/curl/HTTP.operationTimeout.html /library-prerelease/std/net/curl/http.operation_timeout.html +/library-prerelease/std/net/curl/HTTP.perform.html /library-prerelease/std/net/curl/http.perform.html +/library-prerelease/std/net/curl/HTTP.postData.html /library-prerelease/std/net/curl/http.post_data.html +/library-prerelease/std/net/curl/HTTP.proxy.html /library-prerelease/std/net/curl/http.proxy.html +/library-prerelease/std/net/curl/HTTP.proxyPort.html /library-prerelease/std/net/curl/http.proxy_port.html +/library-prerelease/std/net/curl/HTTP.proxyType.html /library-prerelease/std/net/curl/http.proxy_type.html +/library-prerelease/std/net/curl/HTTP.requestAbort.html /library-prerelease/std/net/curl/http.request_abort.html +/library-prerelease/std/net/curl/HTTP.requestPause.html /library-prerelease/std/net/curl/http.request_pause.html +/library-prerelease/std/net/curl/HTTP.responseHeaders.html /library-prerelease/std/net/curl/http.response_headers.html +/library-prerelease/std/net/curl/HTTP.setAuthentication.html /library-prerelease/std/net/curl/http.set_authentication.html +/library-prerelease/std/net/curl/HTTP.setCookie.html /library-prerelease/std/net/curl/http.set_cookie.html +/library-prerelease/std/net/curl/HTTP.setCookieJar.html /library-prerelease/std/net/curl/http.set_cookie_jar.html +/library-prerelease/std/net/curl/HTTP.setPostData.html /library-prerelease/std/net/curl/http.set_post_data.html +/library-prerelease/std/net/curl/HTTP.setProxyAuthentication.html /library-prerelease/std/net/curl/http.set_proxy_authentication.html +/library-prerelease/std/net/curl/HTTP.setTimeCondition.html /library-prerelease/std/net/curl/http.set_time_condition.html +/library-prerelease/std/net/curl/HTTP.setUserAgent.html /library-prerelease/std/net/curl/http.set_user_agent.html +/library-prerelease/std/net/curl/HTTP.shutdown.html /library-prerelease/std/net/curl/http.shutdown.html +/library-prerelease/std/net/curl/HTTP.StatusLine.code.html /library-prerelease/std/net/curl/http.status_line.code.html +/library-prerelease/std/net/curl/HTTP.statusLine.html /library-prerelease/std/net/curl/http.status_line.html +/library-prerelease/std/net/curl/HTTP.StatusLine.html /library-prerelease/std/net/curl/http.status_line.html +/library-prerelease/std/net/curl/HTTP.StatusLine.majorVersion.html /library-prerelease/std/net/curl/http.status_line.major_version.html +/library-prerelease/std/net/curl/HTTP.StatusLine.minorVersion.html /library-prerelease/std/net/curl/http.status_line.minor_version.html +/library-prerelease/std/net/curl/HTTP.StatusLine.reason.html /library-prerelease/std/net/curl/http.status_line.reason.html +/library-prerelease/std/net/curl/HTTP.StatusLine.reset.html /library-prerelease/std/net/curl/http.status_line.reset.html +/library-prerelease/std/net/curl/HTTP.tcpNoDelay.html /library-prerelease/std/net/curl/http.tcp_no_delay.html +/library-prerelease/std/net/curl/HTTP.TimeCond.html /library-prerelease/std/net/curl/http.time_cond.html +/library-prerelease/std/net/curl/HTTP.url.html /library-prerelease/std/net/curl/http.url.html +/library-prerelease/std/net/curl/HTTP.verbose.html /library-prerelease/std/net/curl/http.verbose.html +/library-prerelease/std/net/curl/Object.factory.html /library-prerelease/std/net/curl/object.factory.html +/library-prerelease/std/net/curl/Object.opCmp.html /library-prerelease/std/net/curl/object.op_cmp.html +/library-prerelease/std/net/curl/Object.opEquals.html /library-prerelease/std/net/curl/object.op_equals.html +/library-prerelease/std/net/curl/Object.toHash.html /library-prerelease/std/net/curl/object.to_hash.html +/library-prerelease/std/net/curl/SMTP.connectTimeout.html /library-prerelease/std/net/curl/smtp.connect_timeout.html +/library-prerelease/std/net/curl/SMTP.CurlProxy.html /library-prerelease/std/net/curl/smtp.curl_proxy.html +/library-prerelease/std/net/curl/SMTP.dataTimeout.html /library-prerelease/std/net/curl/smtp.data_timeout.html +/library-prerelease/std/net/curl/SMTP.dnsTimeout.html /library-prerelease/std/net/curl/smtp.dns_timeout.html +/library-prerelease/std/net/curl/SMTP.html /library-prerelease/std/net/curl/smtp.html +/library-prerelease/std/net/curl/SMTP.isStopped.html /library-prerelease/std/net/curl/smtp.is_stopped.html +/library-prerelease/std/net/curl/SMTP.localPort.html /library-prerelease/std/net/curl/smtp.local_port.html +/library-prerelease/std/net/curl/SMTP.localPortRange.html /library-prerelease/std/net/curl/smtp.local_port_range.html +/library-prerelease/std/net/curl/SMTP.mailFrom.html /library-prerelease/std/net/curl/smtp.mail_from.html +/library-prerelease/std/net/curl/SMTP.mailTo.html /library-prerelease/std/net/curl/smtp.mail_to.html +/library-prerelease/std/net/curl/SMTP.message.html /library-prerelease/std/net/curl/smtp.message.html +/library-prerelease/std/net/curl/SMTP.netInterface.html /library-prerelease/std/net/curl/smtp.net_interface.html +/library-prerelease/std/net/curl/SMTP.onProgress.html /library-prerelease/std/net/curl/smtp.on_progress.html +/library-prerelease/std/net/curl/SMTP.onReceive.html /library-prerelease/std/net/curl/smtp.on_receive.html +/library-prerelease/std/net/curl/SMTP.onSend.html /library-prerelease/std/net/curl/smtp.on_send.html +/library-prerelease/std/net/curl/SMTP.opCall.html /library-prerelease/std/net/curl/smtp.op_call.html +/library-prerelease/std/net/curl/SMTP.operationTimeout.html /library-prerelease/std/net/curl/smtp.operation_timeout.html +/library-prerelease/std/net/curl/SMTP.perform.html /library-prerelease/std/net/curl/smtp.perform.html +/library-prerelease/std/net/curl/SMTP.proxy.html /library-prerelease/std/net/curl/smtp.proxy.html +/library-prerelease/std/net/curl/SMTP.proxyPort.html /library-prerelease/std/net/curl/smtp.proxy_port.html +/library-prerelease/std/net/curl/SMTP.proxyType.html /library-prerelease/std/net/curl/smtp.proxy_type.html +/library-prerelease/std/net/curl/SMTP.requestAbort.html /library-prerelease/std/net/curl/smtp.request_abort.html +/library-prerelease/std/net/curl/SMTP.requestPause.html /library-prerelease/std/net/curl/smtp.request_pause.html +/library-prerelease/std/net/curl/SMTP.setAuthentication.html /library-prerelease/std/net/curl/smtp.set_authentication.html +/library-prerelease/std/net/curl/SMTP.setProxyAuthentication.html /library-prerelease/std/net/curl/smtp.set_proxy_authentication.html +/library-prerelease/std/net/curl/SMTP.shutdown.html /library-prerelease/std/net/curl/smtp.shutdown.html +/library-prerelease/std/net/curl/SMTP.tcpNoDelay.html /library-prerelease/std/net/curl/smtp.tcp_no_delay.html +/library-prerelease/std/net/curl/SMTP.url.html /library-prerelease/std/net/curl/smtp.url.html +/library-prerelease/std/net/curl/SMTP.verbose.html /library-prerelease/std/net/curl/smtp.verbose.html +/library-prerelease/std/net/curl/Throwable.file.html /library-prerelease/std/net/curl/throwable.file.html +/library-prerelease/std/net/curl/Throwable.info.html /library-prerelease/std/net/curl/throwable.info.html +/library-prerelease/std/net/curl/Throwable.line.html /library-prerelease/std/net/curl/throwable.line.html +/library-prerelease/std/net/curl/Throwable.msg.html /library-prerelease/std/net/curl/throwable.msg.html +/library-prerelease/std/net/curl/Throwable.next.html /library-prerelease/std/net/curl/throwable.next.html +/library-prerelease/std/net/curl/Throwable.toString.html /library-prerelease/std/net/curl/throwable.to_string.html +/library-prerelease/std/net/curl/ThrowOnError.html /library-prerelease/std/net/curl/throw_on_error.html +/library-prerelease/std/net/isemail/CheckDns.html /library-prerelease/std/net/isemail/check_dns.html +/library-prerelease/std/net/isemail/CheckDns.no.html /library-prerelease/std/net/isemail/check_dns.no.html +/library-prerelease/std/net/isemail/CheckDns.yes.html /library-prerelease/std/net/isemail/check_dns.yes.html +/library-prerelease/std/net/isemail/EmailStatusCode.any.html /library-prerelease/std/net/isemail/email_status_code.any.html +/library-prerelease/std/net/isemail/EmailStatusCode.cFoldingWhitespace.html /library-prerelease/std/net/isemail/email_status_code.c_folding_whitespace.html +/library-prerelease/std/net/isemail/EmailStatusCode.comment.html /library-prerelease/std/net/isemail/email_status_code.comment.html +/library-prerelease/std/net/isemail/EmailStatusCode.deprecatedCommentFoldingWhitespaceNearAt.html /library-prerelease/std/net/isemail/email_status_code.deprecated_comment_folding_whitespace_near_at.html +/library-prerelease/std/net/isemail/EmailStatusCode.deprecatedComment.html /library-prerelease/std/net/isemail/email_status_code.deprecated_comment.html +/library-prerelease/std/net/isemail/EmailStatusCode.deprecatedCommentText.html /library-prerelease/std/net/isemail/email_status_code.deprecated_comment_text.html +/library-prerelease/std/net/isemail/EmailStatusCode.deprecatedFoldingWhitespace.html /library-prerelease/std/net/isemail/email_status_code.deprecated_folding_whitespace.html +/library-prerelease/std/net/isemail/EmailStatusCode.deprecated_.html /library-prerelease/std/net/isemail/email_status_code.deprecated_.html +/library-prerelease/std/net/isemail/EmailStatusCode.deprecatedLocalPart.html /library-prerelease/std/net/isemail/email_status_code.deprecated_local_part.html +/library-prerelease/std/net/isemail/EmailStatusCode.deprecatedQuotedPair.html /library-prerelease/std/net/isemail/email_status_code.deprecated_quoted_pair.html +/library-prerelease/std/net/isemail/EmailStatusCode.deprecatedQuotedText.html /library-prerelease/std/net/isemail/email_status_code.deprecated_quoted_text.html +/library-prerelease/std/net/isemail/EmailStatusCode.dnsWarning.html /library-prerelease/std/net/isemail/email_status_code.dns_warning.html +/library-prerelease/std/net/isemail/EmailStatusCode.dnsWarningNoMXRecord.html /library-prerelease/std/net/isemail/email_status_code.dns_warning_nomx_record.html +/library-prerelease/std/net/isemail/EmailStatusCode.dnsWarningNoRecord.html /library-prerelease/std/net/isemail/email_status_code.dns_warning_no_record.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorBackslashEnd.html /library-prerelease/std/net/isemail/email_status_code.error_backslash_end.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorConsecutiveDots.html /library-prerelease/std/net/isemail/email_status_code.error_consecutive_dots.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorCrNoLf.html /library-prerelease/std/net/isemail/email_status_code.error_cr_no_lf.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorDomainHyphenEnd.html /library-prerelease/std/net/isemail/email_status_code.error_domain_hyphen_end.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorDomainHyphenStart.html /library-prerelease/std/net/isemail/email_status_code.error_domain_hyphen_start.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorDotEnd.html /library-prerelease/std/net/isemail/email_status_code.error_dot_end.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorDotStart.html /library-prerelease/std/net/isemail/email_status_code.error_dot_start.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorExpectingCommentText.html /library-prerelease/std/net/isemail/email_status_code.error_expecting_comment_text.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorExpectingDomainText.html /library-prerelease/std/net/isemail/email_status_code.error_expecting_domain_text.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorExpectingQuotedPair.html /library-prerelease/std/net/isemail/email_status_code.error_expecting_quoted_pair.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorExpectingQuotedText.html /library-prerelease/std/net/isemail/email_status_code.error_expecting_quoted_text.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorExpectingText.html /library-prerelease/std/net/isemail/email_status_code.error_expecting_text.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorFoldingWhitespaceCrflX2.html /library-prerelease/std/net/isemail/email_status_code.error_folding_whitespace_crfl_x2.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorFoldingWhitespaceCrLfEnd.html /library-prerelease/std/net/isemail/email_status_code.error_folding_whitespace_cr_lf_end.html +/library-prerelease/std/net/isemail/EmailStatusCode.error.html /library-prerelease/std/net/isemail/email_status_code.error.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorNoDomain.html /library-prerelease/std/net/isemail/email_status_code.error_no_domain.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorNoLocalPart.html /library-prerelease/std/net/isemail/email_status_code.error_no_local_part.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorTextAfterCommentFoldingWhitespace.html /library-prerelease/std/net/isemail/email_status_code.error_text_after_comment_folding_whitespace.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorTextAfterDomainLiteral.html /library-prerelease/std/net/isemail/email_status_code.error_text_after_domain_literal.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorTextAfterQuotedString.html /library-prerelease/std/net/isemail/email_status_code.error_text_after_quoted_string.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorUnclosedComment.html /library-prerelease/std/net/isemail/email_status_code.error_unclosed_comment.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorUnclosedDomainLiteral.html /library-prerelease/std/net/isemail/email_status_code.error_unclosed_domain_literal.html +/library-prerelease/std/net/isemail/EmailStatusCode.errorUnclosedQuotedString.html /library-prerelease/std/net/isemail/email_status_code.error_unclosed_quoted_string.html +/library-prerelease/std/net/isemail/EmailStatusCode.foldingWhitespace.html /library-prerelease/std/net/isemail/email_status_code.folding_whitespace.html +/library-prerelease/std/net/isemail/EmailStatusCode.html /library-prerelease/std/net/isemail/email_status_code.html +/library-prerelease/std/net/isemail/EmailStatusCode.none.html /library-prerelease/std/net/isemail/email_status_code.none.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5321AddressLiteral.html /library-prerelease/std/net/isemail/email_status_code.rfc5321_address_literal.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5321.html /library-prerelease/std/net/isemail/email_status_code.rfc5321.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5321IpV6Deprecated.html /library-prerelease/std/net/isemail/email_status_code.rfc5321_ip_v6_deprecated.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5321QuotedString.html /library-prerelease/std/net/isemail/email_status_code.rfc5321_quoted_string.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5321TopLevelDomain.html /library-prerelease/std/net/isemail/email_status_code.rfc5321_top_level_domain.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5321TopLevelDomainNumeric.html /library-prerelease/std/net/isemail/email_status_code.rfc5321_top_level_domain_numeric.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322Domain.html /library-prerelease/std/net/isemail/email_status_code.rfc5322_domain.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322DomainLiteral.html /library-prerelease/std/net/isemail/email_status_code.rfc5322_domain_literal.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322DomainLiteralObsoleteText.html /library-prerelease/std/net/isemail/email_status_code.rfc5322_domain_literal_obsolete_text.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322DomainTooLong.html /library-prerelease/std/net/isemail/email_status_code.rfc5322_domain_too_long.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322.html /library-prerelease/std/net/isemail/email_status_code.rfc5322.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322IpV6BadChar.html /library-prerelease/std/net/isemail/email_status_code.rfc5322_ip_v6_bad_char.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322IpV6ColonEnd.html /library-prerelease/std/net/isemail/email_status_code.rfc5322_ip_v6_colon_end.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322IpV6ColonStart.html /library-prerelease/std/net/isemail/email_status_code.rfc5322_ip_v6_colon_start.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322IpV6GroupCount.html /library-prerelease/std/net/isemail/email_status_code.rfc5322_ip_v6_group_count.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322IpV6MaxGroups.html /library-prerelease/std/net/isemail/email_status_code.rfc5322_ip_v6_max_groups.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322IpV6TooManyDoubleColons.html /library-prerelease/std/net/isemail/email_status_code.rfc5322_ip_v6_too_many_double_colons.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322LabelTooLong.html /library-prerelease/std/net/isemail/email_status_code.rfc5322_label_too_long.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322LocalTooLong.html /library-prerelease/std/net/isemail/email_status_code.rfc5322_local_too_long.html +/library-prerelease/std/net/isemail/EmailStatusCode.rfc5322TooLong.html /library-prerelease/std/net/isemail/email_status_code.rfc5322_too_long.html +/library-prerelease/std/net/isemail/EmailStatusCode.validCategory.html /library-prerelease/std/net/isemail/email_status_code.valid_category.html +/library-prerelease/std/net/isemail/EmailStatusCode.valid.html /library-prerelease/std/net/isemail/email_status_code.valid.html +/library-prerelease/std/net/isemail/EmailStatusCode.warning.html /library-prerelease/std/net/isemail/email_status_code.warning.html +/library-prerelease/std/net/isemail/EmailStatus.domainPart.html /library-prerelease/std/net/isemail/email_status.domain_part.html +/library-prerelease/std/net/isemail/EmailStatus.html /library-prerelease/std/net/isemail/email_status.html +/library-prerelease/std/net/isemail/EmailStatus.localPart.html /library-prerelease/std/net/isemail/email_status.local_part.html +/library-prerelease/std/net/isemail/EmailStatus.statusCode.html /library-prerelease/std/net/isemail/email_status.status_code.html +/library-prerelease/std/net/isemail/EmailStatus.status.html /library-prerelease/std/net/isemail/email_status.status.html +/library-prerelease/std/net/isemail/EmailStatus.toString.html /library-prerelease/std/net/isemail/email_status.to_string.html +/library-prerelease/std/net/isemail/EmailStatus.valid.html /library-prerelease/std/net/isemail/email_status.valid.html +/library-prerelease/std/net/isemail/isEmail.html /library-prerelease/std/net/isemail/is_email.html +/library-prerelease/std/net/isemail/statusCodeDescription.html /library-prerelease/std/net/isemail/status_code_description.html +/library-prerelease/std/numeric/cosineSimilarity.html /library-prerelease/std/numeric/cosine_similarity.html +/library-prerelease/std/numeric/CustomFloat.dig.html /library-prerelease/std/numeric/custom_float.dig.html +/library-prerelease/std/numeric/CustomFloat.epsilon.html /library-prerelease/std/numeric/custom_float.epsilon.html +/library-prerelease/std/numeric/CustomFloatFlags.allowDenorm.html /library-prerelease/std/numeric/custom_float_flags.allow_denorm.html +/library-prerelease/std/numeric/CustomFloatFlags.allowDenormZeroOnly.html /library-prerelease/std/numeric/custom_float_flags.allow_denorm_zero_only.html +/library-prerelease/std/numeric/CustomFloatFlags.html /library-prerelease/std/numeric/custom_float_flags.html +/library-prerelease/std/numeric/CustomFloatFlags.ieee.html /library-prerelease/std/numeric/custom_float_flags.ieee.html +/library-prerelease/std/numeric/CustomFloatFlags.infinity.html /library-prerelease/std/numeric/custom_float_flags.infinity.html +/library-prerelease/std/numeric/CustomFloatFlags.nan.html /library-prerelease/std/numeric/custom_float_flags.nan.html +/library-prerelease/std/numeric/CustomFloatFlags.negativeUnsigned.html /library-prerelease/std/numeric/custom_float_flags.negative_unsigned.html +/library-prerelease/std/numeric/CustomFloatFlags.none.html /library-prerelease/std/numeric/custom_float_flags.none.html +/library-prerelease/std/numeric/CustomFloatFlags.probability.html /library-prerelease/std/numeric/custom_float_flags.probability.html +/library-prerelease/std/numeric/CustomFloatFlags.signed.html /library-prerelease/std/numeric/custom_float_flags.signed.html +/library-prerelease/std/numeric/CustomFloatFlags.storeNormalized.html /library-prerelease/std/numeric/custom_float_flags.store_normalized.html +/library-prerelease/std/numeric/CustomFloat.get.get.html /library-prerelease/std/numeric/custom_float.get.get.html +/library-prerelease/std/numeric/CustomFloat.get.html /library-prerelease/std/numeric/custom_float.get.html +/library-prerelease/std/numeric/CustomFloat.html /library-prerelease/std/numeric/custom_float.html +/library-prerelease/std/numeric/CustomFloat.im.html /library-prerelease/std/numeric/custom_float.im.html +/library-prerelease/std/numeric/CustomFloat.mant_dig.html /library-prerelease/std/numeric/custom_float.mant_dig.html +/library-prerelease/std/numeric/CustomFloat.max_10_exp.html /library-prerelease/std/numeric/custom_float.max_10_exp.html +/library-prerelease/std/numeric/CustomFloat.max_exp.html /library-prerelease/std/numeric/custom_float.max_exp.html +/library-prerelease/std/numeric/CustomFloat.max.html /library-prerelease/std/numeric/custom_float.max.html +/library-prerelease/std/numeric/CustomFloat.min_10_exp.html /library-prerelease/std/numeric/custom_float.min_10_exp.html +/library-prerelease/std/numeric/CustomFloat.min_exp.html /library-prerelease/std/numeric/custom_float.min_exp.html +/library-prerelease/std/numeric/CustomFloat.min_normal.html /library-prerelease/std/numeric/custom_float.min_normal.html +/library-prerelease/std/numeric/CustomFloat.opAssign.html /library-prerelease/std/numeric/custom_float.op_assign.html +/library-prerelease/std/numeric/CustomFloat.opAssign.opAssign.html /library-prerelease/std/numeric/custom_float.op_assign.op_assign.html +/library-prerelease/std/numeric/CustomFloat.opBinary.html /library-prerelease/std/numeric/custom_float.op_binary.html +/library-prerelease/std/numeric/CustomFloat.opBinary.opBinary.html /library-prerelease/std/numeric/custom_float.op_binary.op_binary.html +/library-prerelease/std/numeric/CustomFloat.opBinaryRight.html /library-prerelease/std/numeric/custom_float.op_binary_right.html +/library-prerelease/std/numeric/CustomFloat.opBinaryRight.opBinaryRight.html /library-prerelease/std/numeric/custom_float.op_binary_right.op_binary_right.html +/library-prerelease/std/numeric/CustomFloat.opCast.html /library-prerelease/std/numeric/custom_float.op_cast.html +/library-prerelease/std/numeric/CustomFloat.opCast.opCast.html /library-prerelease/std/numeric/custom_float.op_cast.op_cast.html +/library-prerelease/std/numeric/CustomFloat.opCmp.html /library-prerelease/std/numeric/custom_float.op_cmp.html +/library-prerelease/std/numeric/CustomFloat.opCmp.opCmp.html /library-prerelease/std/numeric/custom_float.op_cmp.op_cmp.html +/library-prerelease/std/numeric/CustomFloat.opOpAssign.html /library-prerelease/std/numeric/custom_float.op_op_assign.html +/library-prerelease/std/numeric/CustomFloat.opOpAssign.opOpAssign.html /library-prerelease/std/numeric/custom_float.op_op_assign.op_op_assign.html +/library-prerelease/std/numeric/CustomFloat.opUnary.html /library-prerelease/std/numeric/custom_float.op_unary.html +/library-prerelease/std/numeric/CustomFloat.opUnary.opUnary.html /library-prerelease/std/numeric/custom_float.op_unary.op_unary.html +/library-prerelease/std/numeric/CustomFloat.re.html /library-prerelease/std/numeric/custom_float.re.html +/library-prerelease/std/numeric/CustomFloat.this.html /library-prerelease/std/numeric/custom_float.this.html +/library-prerelease/std/numeric/CustomFloat.this.this.html /library-prerelease/std/numeric/custom_float.this.this.html +/library-prerelease/std/numeric/CustomFloat.toString.html /library-prerelease/std/numeric/custom_float.to_string.html +/library-prerelease/std/numeric/CustomFloat.toString.toString.html /library-prerelease/std/numeric/custom_float.to_string.to_string.html +/library-prerelease/std/numeric/CustomFloat.toString.toString.toString.html /library-prerelease/std/numeric/custom_float.to_string.to_string.to_string.html +/library-prerelease/std/numeric/dotProduct.html /library-prerelease/std/numeric/dot_product.html +/library-prerelease/std/numeric/euclideanDistance.html /library-prerelease/std/numeric/euclidean_distance.html +/library-prerelease/std/numeric/Fft.fft.html /library-prerelease/std/numeric/fft.fft.html +/library-prerelease/std/numeric/Fft.html /library-prerelease/std/numeric/fft.html +/library-prerelease/std/numeric/Fft.inverseFft.html /library-prerelease/std/numeric/fft.inverse_fft.html +/library-prerelease/std/numeric/Fft.this.html /library-prerelease/std/numeric/fft.this.html +/library-prerelease/std/numeric/findRoot.html /library-prerelease/std/numeric/find_root.html +/library-prerelease/std/numeric/FPTemporary.html /library-prerelease/std/numeric/fp_temporary.html +/library-prerelease/std/numeric/gapWeightedSimilarity.html /library-prerelease/std/numeric/gap_weighted_similarity.html +/library-prerelease/std/numeric/GapWeightedSimilarityIncremental.empty.html /library-prerelease/std/numeric/gap_weighted_similarity_incremental.empty.html +/library-prerelease/std/numeric/GapWeightedSimilarityIncremental.front.html /library-prerelease/std/numeric/gap_weighted_similarity_incremental.front.html +/library-prerelease/std/numeric/gapWeightedSimilarityIncremental.html /library-prerelease/std/numeric/gap_weighted_similarity_incremental.html +/library-prerelease/std/numeric/GapWeightedSimilarityIncremental.html /library-prerelease/std/numeric/gap_weighted_similarity_incremental.html +/library-prerelease/std/numeric/GapWeightedSimilarityIncremental.opSlice.html /library-prerelease/std/numeric/gap_weighted_similarity_incremental.op_slice.html +/library-prerelease/std/numeric/GapWeightedSimilarityIncremental.popFront.html /library-prerelease/std/numeric/gap_weighted_similarity_incremental.pop_front.html +/library-prerelease/std/numeric/GapWeightedSimilarityIncremental.this.html /library-prerelease/std/numeric/gap_weighted_similarity_incremental.this.html +/library-prerelease/std/numeric/gapWeightedSimilarityNormalized.html /library-prerelease/std/numeric/gap_weighted_similarity_normalized.html +/library-prerelease/std/numeric/inverseFft.html /library-prerelease/std/numeric/inverse_fft.html +/library-prerelease/std/numeric/jensenShannonDivergence.html /library-prerelease/std/numeric/jensen_shannon_divergence.html +/library-prerelease/std/numeric/kullbackLeiblerDivergence.html /library-prerelease/std/numeric/kullback_leibler_divergence.html +/library-prerelease/std/numeric/Object.factory.html /library-prerelease/std/numeric/object.factory.html +/library-prerelease/std/numeric/Object.opCmp.html /library-prerelease/std/numeric/object.op_cmp.html +/library-prerelease/std/numeric/Object.opEquals.html /library-prerelease/std/numeric/object.op_equals.html +/library-prerelease/std/numeric/Object.toHash.html /library-prerelease/std/numeric/object.to_hash.html +/library-prerelease/std/numeric/Object.toString.html /library-prerelease/std/numeric/object.to_string.html +/library-prerelease/std/numeric/secantMethod.html /library-prerelease/std/numeric/secant_method.html +/library-prerelease/std/numeric/secantMethod.secantMethod.html /library-prerelease/std/numeric/secant_method.secant_method.html +/library-prerelease/std/numeric/sumOfLog2s.html /library-prerelease/std/numeric/sum_of_log2s.html +/library-prerelease/std/outbuffer/Object.factory.html /library-prerelease/std/outbuffer/object.factory.html +/library-prerelease/std/outbuffer/Object.opCmp.html /library-prerelease/std/outbuffer/object.op_cmp.html +/library-prerelease/std/outbuffer/Object.opEquals.html /library-prerelease/std/outbuffer/object.op_equals.html +/library-prerelease/std/outbuffer/Object.toHash.html /library-prerelease/std/outbuffer/object.to_hash.html +/library-prerelease/std/outbuffer/Object.toString.html /library-prerelease/std/outbuffer/object.to_string.html +/library-prerelease/std/outbuffer/OutBuffer.align2.html /library-prerelease/std/outbuffer/out_buffer.align2.html +/library-prerelease/std/outbuffer/OutBuffer.align4.html /library-prerelease/std/outbuffer/out_buffer.align4.html +/library-prerelease/std/outbuffer/OutBuffer.alignSize.html /library-prerelease/std/outbuffer/out_buffer.align_size.html +/library-prerelease/std/outbuffer/OutBuffer.fill0.html /library-prerelease/std/outbuffer/out_buffer.fill0.html +/library-prerelease/std/outbuffer/OutBuffer.html /library-prerelease/std/outbuffer/out_buffer.html +/library-prerelease/std/outbuffer/OutBuffer.printf.html /library-prerelease/std/outbuffer/out_buffer.printf.html +/library-prerelease/std/outbuffer/OutBuffer.put.html /library-prerelease/std/outbuffer/out_buffer.put.html +/library-prerelease/std/outbuffer/OutBuffer.reserve.html /library-prerelease/std/outbuffer/out_buffer.reserve.html +/library-prerelease/std/outbuffer/OutBuffer.spread.html /library-prerelease/std/outbuffer/out_buffer.spread.html +/library-prerelease/std/outbuffer/OutBuffer.toBytes.html /library-prerelease/std/outbuffer/out_buffer.to_bytes.html +/library-prerelease/std/outbuffer/OutBuffer.toString.html /library-prerelease/std/outbuffer/out_buffer.to_string.html +/library-prerelease/std/outbuffer/OutBuffer.vprintf.html /library-prerelease/std/outbuffer/out_buffer.vprintf.html +/library-prerelease/std/outbuffer/OutBuffer.writef.html /library-prerelease/std/outbuffer/out_buffer.writef.html +/library-prerelease/std/outbuffer/OutBuffer.writefln.html /library-prerelease/std/outbuffer/out_buffer.writefln.html +/library-prerelease/std/outbuffer/OutBuffer.write.html /library-prerelease/std/outbuffer/out_buffer.write.html +/library-prerelease/std/parallelism/defaultPoolThreads.html /library-prerelease/std/parallelism/default_pool_threads.html +/library-prerelease/std/parallelism/Object.factory.html /library-prerelease/std/parallelism/object.factory.html +/library-prerelease/std/parallelism/Object.opCmp.html /library-prerelease/std/parallelism/object.op_cmp.html +/library-prerelease/std/parallelism/Object.opEquals.html /library-prerelease/std/parallelism/object.op_equals.html +/library-prerelease/std/parallelism/Object.toHash.html /library-prerelease/std/parallelism/object.to_hash.html +/library-prerelease/std/parallelism/Object.toString.html /library-prerelease/std/parallelism/object.to_string.html +/library-prerelease/std/parallelism/scopedTask.html /library-prerelease/std/parallelism/scoped_task.html +/library-prerelease/std/parallelism/Task.done.html /library-prerelease/std/parallelism/task.done.html +/library-prerelease/std/parallelism/Task.executeInNewThread.html /library-prerelease/std/parallelism/task.execute_in_new_thread.html +/library-prerelease/std/parallelism/Task.html /library-prerelease/std/parallelism/task.html +/library-prerelease/std/parallelism/TaskPool.asyncBuf.html /library-prerelease/std/parallelism/task_pool.async_buf.html +/library-prerelease/std/parallelism/TaskPool.finish.html /library-prerelease/std/parallelism/task_pool.finish.html +/library-prerelease/std/parallelism/taskPool.html /library-prerelease/std/parallelism/task_pool.html +/library-prerelease/std/parallelism/TaskPool.html /library-prerelease/std/parallelism/task_pool.html +/library-prerelease/std/parallelism/TaskPool.isDaemon.html /library-prerelease/std/parallelism/task_pool.is_daemon.html +/library-prerelease/std/parallelism/TaskPool.parallel.html /library-prerelease/std/parallelism/task_pool.parallel.html +/library-prerelease/std/parallelism/TaskPool.priority.html /library-prerelease/std/parallelism/task_pool.priority.html +/library-prerelease/std/parallelism/TaskPool.put.html /library-prerelease/std/parallelism/task_pool.put.html +/library-prerelease/std/parallelism/TaskPool.size.html /library-prerelease/std/parallelism/task_pool.size.html +/library-prerelease/std/parallelism/TaskPool.stop.html /library-prerelease/std/parallelism/task_pool.stop.html +/library-prerelease/std/parallelism/TaskPool.this.html /library-prerelease/std/parallelism/task_pool.this.html +/library-prerelease/std/parallelism/TaskPool.workerIndex.html /library-prerelease/std/parallelism/task_pool.worker_index.html +/library-prerelease/std/parallelism/TaskPool.WorkerLocalStorage.get.html /library-prerelease/std/parallelism/task_pool.worker_local_storage.get.html +/library-prerelease/std/parallelism/TaskPool.workerLocalStorage.html /library-prerelease/std/parallelism/task_pool.worker_local_storage.html +/library-prerelease/std/parallelism/TaskPool.WorkerLocalStorage.html /library-prerelease/std/parallelism/task_pool.worker_local_storage.html +/library-prerelease/std/parallelism/TaskPool.WorkerLocalStorageRange.html /library-prerelease/std/parallelism/task_pool.worker_local_storage_range.html +/library-prerelease/std/parallelism/TaskPool.WorkerLocalStorage.toRange.html /library-prerelease/std/parallelism/task_pool.worker_local_storage.to_range.html +/library-prerelease/std/parallelism/Task.ReturnType.html /library-prerelease/std/parallelism/task.return_type.html +/library-prerelease/std/parallelism/Task.spinForce.html /library-prerelease/std/parallelism/task.spin_force.html +/library-prerelease/std/parallelism/Task.workForce.html /library-prerelease/std/parallelism/task.work_force.html +/library-prerelease/std/parallelism/Task.yieldForce.html /library-prerelease/std/parallelism/task.yield_force.html +/library-prerelease/std/parallelism/totalCPUs.html /library-prerelease/std/parallelism/total_cp_us.html +/library-prerelease/std/path/absolutePath.html /library-prerelease/std/path/absolute_path.html +/library-prerelease/std/path/baseName.html /library-prerelease/std/path/base_name.html +/library-prerelease/std/path/buildNormalizedPath.html /library-prerelease/std/path/build_normalized_path.html +/library-prerelease/std/path/buildPath.html /library-prerelease/std/path/build_path.html +/library-prerelease/std/path/CaseSensitive.html /library-prerelease/std/path/case_sensitive.html +/library-prerelease/std/path/CaseSensitive.no.html /library-prerelease/std/path/case_sensitive.no.html +/library-prerelease/std/path/CaseSensitive.osDefault.html /library-prerelease/std/path/case_sensitive.os_default.html +/library-prerelease/std/path/CaseSensitive.yes.html /library-prerelease/std/path/case_sensitive.yes.html +/library-prerelease/std/path/defaultExtension.html /library-prerelease/std/path/default_extension.html +/library-prerelease/std/path/dirName.html /library-prerelease/std/path/dir_name.html +/library-prerelease/std/path/dirSeparator.html /library-prerelease/std/path/dir_separator.html +/library-prerelease/std/path/driveName.html /library-prerelease/std/path/drive_name.html +/library-prerelease/std/path/expandTilde.html /library-prerelease/std/path/expand_tilde.html +/library-prerelease/std/path/filenameCharCmp.html /library-prerelease/std/path/filename_char_cmp.html +/library-prerelease/std/path/filenameCmp.html /library-prerelease/std/path/filename_cmp.html +/library-prerelease/std/path/globMatch.html /library-prerelease/std/path/glob_match.html +/library-prerelease/std/path/isAbsolute.html /library-prerelease/std/path/is_absolute.html +/library-prerelease/std/path/isDirSeparator.html /library-prerelease/std/path/is_dir_separator.html +/library-prerelease/std/path/isRooted.html /library-prerelease/std/path/is_rooted.html +/library-prerelease/std/path/isValidFilename.html /library-prerelease/std/path/is_valid_filename.html +/library-prerelease/std/path/isValidPath.html /library-prerelease/std/path/is_valid_path.html +/library-prerelease/std/path/pathSeparator.html /library-prerelease/std/path/path_separator.html +/library-prerelease/std/path/pathSplitter.html /library-prerelease/std/path/path_splitter.html +/library-prerelease/std/path/relativePath.html /library-prerelease/std/path/relative_path.html +/library-prerelease/std/path/rootName.html /library-prerelease/std/path/root_name.html +/library-prerelease/std/path/setExtension.html /library-prerelease/std/path/set_extension.html +/library-prerelease/std/path/stripDrive.html /library-prerelease/std/path/strip_drive.html +/library-prerelease/std/path/stripExtension.html /library-prerelease/std/path/strip_extension.html +/library-prerelease/std/process/Config.html /library-prerelease/std/process/config.html +/library-prerelease/std/process/Config.inheritFDs.html /library-prerelease/std/process/config.inherit_f_ds.html +/library-prerelease/std/process/Config.newEnv.html /library-prerelease/std/process/config.new_env.html +/library-prerelease/std/process/Config.retainStderr.html /library-prerelease/std/process/config.retain_stderr.html +/library-prerelease/std/process/Config.retainStdin.html /library-prerelease/std/process/config.retain_stdin.html +/library-prerelease/std/process/Config.retainStdout.html /library-prerelease/std/process/config.retain_stdout.html +/library-prerelease/std/process/Config.suppressConsole.html /library-prerelease/std/process/config.suppress_console.html +/library-prerelease/std/process/environment.opIndexAssign.html /library-prerelease/std/process/environment.op_index_assign.html +/library-prerelease/std/process/environment.opIndex.html /library-prerelease/std/process/environment.op_index.html +/library-prerelease/std/process/environment.toAA.html /library-prerelease/std/process/environment.to_aa.html +/library-prerelease/std/process/escapeShellCommand.html /library-prerelease/std/process/escape_shell_command.html +/library-prerelease/std/process/escapeShellFileName.html /library-prerelease/std/process/escape_shell_file_name.html +/library-prerelease/std/process/escapeWindowsArgument.html /library-prerelease/std/process/escape_windows_argument.html +/library-prerelease/std/process/executeShell.html /library-prerelease/std/process/execute_shell.html +/library-prerelease/std/process/Object.factory.html /library-prerelease/std/process/object.factory.html +/library-prerelease/std/process/Object.opCmp.html /library-prerelease/std/process/object.op_cmp.html +/library-prerelease/std/process/Object.opEquals.html /library-prerelease/std/process/object.op_equals.html +/library-prerelease/std/process/Object.toHash.html /library-prerelease/std/process/object.to_hash.html +/library-prerelease/std/process/Object.toString.html /library-prerelease/std/process/object.to_string.html +/library-prerelease/std/process/Pid.html /library-prerelease/std/process/pid.html +/library-prerelease/std/process/Pid.osHandle.html /library-prerelease/std/process/pid.os_handle.html +/library-prerelease/std/process/Pid.processID.html /library-prerelease/std/process/pid.process_id.html +/library-prerelease/std/process/Pipe.close.html /library-prerelease/std/process/pipe.close.html +/library-prerelease/std/process/Pipe.html /library-prerelease/std/process/pipe.html +/library-prerelease/std/process/pipeProcess.html /library-prerelease/std/process/pipe_process.html +/library-prerelease/std/process/Pipe.readEnd.html /library-prerelease/std/process/pipe.read_end.html +/library-prerelease/std/process/pipeShell.html /library-prerelease/std/process/pipe_shell.html +/library-prerelease/std/process/Pipe.writeEnd.html /library-prerelease/std/process/pipe.write_end.html +/library-prerelease/std/process/ProcessException.html /library-prerelease/std/process/process_exception.html +/library-prerelease/std/process/ProcessPipes.html /library-prerelease/std/process/process_pipes.html +/library-prerelease/std/process/ProcessPipes.pid.html /library-prerelease/std/process/process_pipes.pid.html +/library-prerelease/std/process/ProcessPipes.stderr.html /library-prerelease/std/process/process_pipes.stderr.html +/library-prerelease/std/process/ProcessPipes.stdin.html /library-prerelease/std/process/process_pipes.stdin.html +/library-prerelease/std/process/ProcessPipes.stdout.html /library-prerelease/std/process/process_pipes.stdout.html +/library-prerelease/std/process/Redirect.all.html /library-prerelease/std/process/redirect.all.html +/library-prerelease/std/process/Redirect.html /library-prerelease/std/process/redirect.html +/library-prerelease/std/process/Redirect.stderr.html /library-prerelease/std/process/redirect.stderr.html +/library-prerelease/std/process/Redirect.stderrToStdout.html /library-prerelease/std/process/redirect.stderr_to_stdout.html +/library-prerelease/std/process/Redirect.stdin.html /library-prerelease/std/process/redirect.stdin.html +/library-prerelease/std/process/Redirect.stdout.html /library-prerelease/std/process/redirect.stdout.html +/library-prerelease/std/process/Redirect.stdoutToStderr.html /library-prerelease/std/process/redirect.stdout_to_stderr.html +/library-prerelease/std/process/spawnProcess.html /library-prerelease/std/process/spawn_process.html +/library-prerelease/std/process/spawnShell.html /library-prerelease/std/process/spawn_shell.html +/library-prerelease/std/process/thisProcessID.html /library-prerelease/std/process/this_process_id.html +/library-prerelease/std/process/Throwable.file.html /library-prerelease/std/process/throwable.file.html +/library-prerelease/std/process/Throwable.info.html /library-prerelease/std/process/throwable.info.html +/library-prerelease/std/process/Throwable.line.html /library-prerelease/std/process/throwable.line.html +/library-prerelease/std/process/Throwable.msg.html /library-prerelease/std/process/throwable.msg.html +/library-prerelease/std/process/Throwable.next.html /library-prerelease/std/process/throwable.next.html +/library-prerelease/std/process/Throwable.toString.html /library-prerelease/std/process/throwable.to_string.html +/library-prerelease/std/process/tryWait.html /library-prerelease/std/process/try_wait.html +/library-prerelease/std/process/userShell.html /library-prerelease/std/process/user_shell.html +/library-prerelease/std/random/isSeedable.html /library-prerelease/std/random/is_seedable.html +/library-prerelease/std/random/isUniformRNG.html /library-prerelease/std/random/is_uniform_rng.html +/library-prerelease/std/random/LinearCongruentialEngine.empty.html /library-prerelease/std/random/linear_congruential_engine.empty.html +/library-prerelease/std/random/LinearCongruentialEngine.front.html /library-prerelease/std/random/linear_congruential_engine.front.html +/library-prerelease/std/random/LinearCongruentialEngine.hasFixedRange.html /library-prerelease/std/random/linear_congruential_engine.has_fixed_range.html +/library-prerelease/std/random/LinearCongruentialEngine.html /library-prerelease/std/random/linear_congruential_engine.html +/library-prerelease/std/random/LinearCongruentialEngine.increment.html /library-prerelease/std/random/linear_congruential_engine.increment.html +/library-prerelease/std/random/LinearCongruentialEngine.isUniformRandom.html /library-prerelease/std/random/linear_congruential_engine.is_uniform_random.html +/library-prerelease/std/random/LinearCongruentialEngine.max.html /library-prerelease/std/random/linear_congruential_engine.max.html +/library-prerelease/std/random/LinearCongruentialEngine.min.html /library-prerelease/std/random/linear_congruential_engine.min.html +/library-prerelease/std/random/LinearCongruentialEngine.modulus.html /library-prerelease/std/random/linear_congruential_engine.modulus.html +/library-prerelease/std/random/LinearCongruentialEngine.multiplier.html /library-prerelease/std/random/linear_congruential_engine.multiplier.html +/library-prerelease/std/random/LinearCongruentialEngine.opEquals.html /library-prerelease/std/random/linear_congruential_engine.op_equals.html +/library-prerelease/std/random/LinearCongruentialEngine.popFront.html /library-prerelease/std/random/linear_congruential_engine.pop_front.html +/library-prerelease/std/random/LinearCongruentialEngine.seed.html /library-prerelease/std/random/linear_congruential_engine.seed.html +/library-prerelease/std/random/LinearCongruentialEngine.this.html /library-prerelease/std/random/linear_congruential_engine.this.html +/library-prerelease/std/random/MersenneTwisterEngine.defaultSeed.html /library-prerelease/std/random/mersenne_twister_engine.default_seed.html +/library-prerelease/std/random/MersenneTwisterEngine.empty.html /library-prerelease/std/random/mersenne_twister_engine.empty.html +/library-prerelease/std/random/MersenneTwisterEngine.front.html /library-prerelease/std/random/mersenne_twister_engine.front.html +/library-prerelease/std/random/MersenneTwisterEngine.html /library-prerelease/std/random/mersenne_twister_engine.html +/library-prerelease/std/random/MersenneTwisterEngine.isUniformRandom.html /library-prerelease/std/random/mersenne_twister_engine.is_uniform_random.html +/library-prerelease/std/random/MersenneTwisterEngine.maskBits.html /library-prerelease/std/random/mersenne_twister_engine.mask_bits.html +/library-prerelease/std/random/MersenneTwisterEngine.max.html /library-prerelease/std/random/mersenne_twister_engine.max.html +/library-prerelease/std/random/MersenneTwisterEngine.min.html /library-prerelease/std/random/mersenne_twister_engine.min.html +/library-prerelease/std/random/MersenneTwisterEngine.popFront.html /library-prerelease/std/random/mersenne_twister_engine.pop_front.html +/library-prerelease/std/random/MersenneTwisterEngine.seed.html /library-prerelease/std/random/mersenne_twister_engine.seed.html +/library-prerelease/std/random/MersenneTwisterEngine.seed.seed.html /library-prerelease/std/random/mersenne_twister_engine.seed.seed.html +/library-prerelease/std/random/MersenneTwisterEngine.shiftSize.html /library-prerelease/std/random/mersenne_twister_engine.shift_size.html +/library-prerelease/std/random/MersenneTwisterEngine.stateSize.html /library-prerelease/std/random/mersenne_twister_engine.state_size.html +/library-prerelease/std/random/MersenneTwisterEngine.temperingB.html /library-prerelease/std/random/mersenne_twister_engine.tempering.html +/library-prerelease/std/random/MersenneTwisterEngine.temperingC.html /library-prerelease/std/random/mersenne_twister_engine.tempering.html +/library-prerelease/std/random/MersenneTwisterEngine.temperingL.html /library-prerelease/std/random/mersenne_twister_engine.tempering.html +/library-prerelease/std/random/MersenneTwisterEngine.temperingS.html /library-prerelease/std/random/mersenne_twister_engine.tempering.html +/library-prerelease/std/random/MersenneTwisterEngine.temperingT.html /library-prerelease/std/random/mersenne_twister_engine.tempering.html +/library-prerelease/std/random/MersenneTwisterEngine.temperingU.html /library-prerelease/std/random/mersenne_twister_engine.tempering.html +/library-prerelease/std/random/MersenneTwisterEngine.this.html /library-prerelease/std/random/mersenne_twister_engine.this.html +/library-prerelease/std/random/MersenneTwisterEngine.wordSize.html /library-prerelease/std/random/mersenne_twister_engine.word_size.html +/library-prerelease/std/random/MersenneTwisterEngine.xorMask.html /library-prerelease/std/random/mersenne_twister_engine.xor_mask.html +/library-prerelease/std/random/MinstdRand0.html /library-prerelease/std/random/minstd_rand0.html +/library-prerelease/std/random/MinstdRand.html /library-prerelease/std/random/minstd_rand.html +/library-prerelease/std/random/Mt19937.html /library-prerelease/std/random/mt19937.html +/library-prerelease/std/random/partialShuffle.html /library-prerelease/std/random/partial_shuffle.html +/library-prerelease/std/random/randomCover.html /library-prerelease/std/random/random_cover.html +/library-prerelease/std/random/RandomCover.html /library-prerelease/std/random/random_cover.html +/library-prerelease/std/random/Random.html /library-prerelease/std/random/random.html +/library-prerelease/std/random/RandomSample.empty.html /library-prerelease/std/random/random_sample.empty.html +/library-prerelease/std/random/randomSample.html /library-prerelease/std/random/random_sample.html +/library-prerelease/std/random/RandomSample.html /library-prerelease/std/random/random_sample.html +/library-prerelease/std/random/RandomSample.index.html /library-prerelease/std/random/random_sample.index.html +/library-prerelease/std/random/RandomSample.length.html /library-prerelease/std/random/random_sample.length.html +/library-prerelease/std/random/RandomSample.popFront.html /library-prerelease/std/random/random_sample.pop_front.html +/library-prerelease/std/random/randomShuffle.html /library-prerelease/std/random/random_shuffle.html +/library-prerelease/std/random/rndGen.html /library-prerelease/std/random/rnd_gen.html +/library-prerelease/std/random/uniformDistribution.html /library-prerelease/std/random/uniform_distribution.html +/library-prerelease/std/random/unpredictableSeed.html /library-prerelease/std/random/unpredictable_seed.html +/library-prerelease/std/random/Xorshift128.html /library-prerelease/std/random/xorshift128.html +/library-prerelease/std/random/Xorshift160.html /library-prerelease/std/random/xorshift160.html +/library-prerelease/std/random/Xorshift192.html /library-prerelease/std/random/xorshift192.html +/library-prerelease/std/random/Xorshift32.html /library-prerelease/std/random/xorshift32.html +/library-prerelease/std/random/Xorshift64.html /library-prerelease/std/random/xorshift64.html +/library-prerelease/std/random/Xorshift96.html /library-prerelease/std/random/xorshift96.html +/library-prerelease/std/random/XorshiftEngine.empty.html /library-prerelease/std/random/xorshift_engine.empty.html +/library-prerelease/std/random/XorshiftEngine.front.html /library-prerelease/std/random/xorshift_engine.front.html +/library-prerelease/std/random/XorshiftEngine.html /library-prerelease/std/random/xorshift_engine.html +/library-prerelease/std/random/XorshiftEngine.isUniformRandom.html /library-prerelease/std/random/xorshift_engine.is_uniform_random.html +/library-prerelease/std/random/XorshiftEngine.max.html /library-prerelease/std/random/xorshift_engine.max.html +/library-prerelease/std/random/XorshiftEngine.min.html /library-prerelease/std/random/xorshift_engine.min.html +/library-prerelease/std/random/XorshiftEngine.opEquals.html /library-prerelease/std/random/xorshift_engine.op_equals.html +/library-prerelease/std/random/XorshiftEngine.popFront.html /library-prerelease/std/random/xorshift_engine.pop_front.html +/library-prerelease/std/random/XorshiftEngine.save.html /library-prerelease/std/random/xorshift_engine.save.html +/library-prerelease/std/random/XorshiftEngine.seed.html /library-prerelease/std/random/xorshift_engine.seed.html +/library-prerelease/std/random/XorshiftEngine.this.html /library-prerelease/std/random/xorshift_engine.this.html +/library-prerelease/std/random/Xorshift.html /library-prerelease/std/random/xorshift.html +/library-prerelease/std/range/assumeSorted.html /library-prerelease/std/range/assume_sorted.html +/library-prerelease/std/range/Chunks.front.html /library-prerelease/std/range/chunks.front.html +/library-prerelease/std/range/Chunks.html /library-prerelease/std/range/chunks.html +/library-prerelease/std/range/Chunks.popFront.html /library-prerelease/std/range/chunks.pop_front.html +/library-prerelease/std/range/Chunks.save.html /library-prerelease/std/range/chunks.save.html +/library-prerelease/std/range/Chunks.this.html /library-prerelease/std/range/chunks.this.html +/library-prerelease/std/range/Cycle.html /library-prerelease/std/range/cycle.html +/library-prerelease/std/range/dropBackExactly.html /library-prerelease/std/range/drop_back_exactly.html +/library-prerelease/std/range/dropBack.html /library-prerelease/std/range/drop_back.html +/library-prerelease/std/range/dropBackOne.html /library-prerelease/std/range/drop_back_one.html +/library-prerelease/std/range/dropExactly.html /library-prerelease/std/range/drop_exactly.html +/library-prerelease/std/range/dropOne.html /library-prerelease/std/range/drop_one.html +/library-prerelease/std/range/FrontTransversal.front.html /library-prerelease/std/range/front_transversal.front.html +/library-prerelease/std/range/frontTransversal.html /library-prerelease/std/range/front_transversal.html +/library-prerelease/std/range/FrontTransversal.html /library-prerelease/std/range/front_transversal.html +/library-prerelease/std/range/FrontTransversal.popFront.html /library-prerelease/std/range/front_transversal.pop_front.html +/library-prerelease/std/range/FrontTransversal.this.html /library-prerelease/std/range/front_transversal.this.html +/library-prerelease/std/range/Indexed.front.html /library-prerelease/std/range/indexed.front.html +/library-prerelease/std/range/Indexed.html /library-prerelease/std/range/indexed.html +/library-prerelease/std/range/Indexed.indices.html /library-prerelease/std/range/indexed.indices.html +/library-prerelease/std/range/Indexed.popFront.html /library-prerelease/std/range/indexed.pop_front.html +/library-prerelease/std/range/Indexed.source.html /library-prerelease/std/range/indexed.source.html +/library-prerelease/std/range/interfaces/BidirectionalAssignable.html /library-prerelease/std/range/interfaces/bidirectional_assignable.html +/library-prerelease/std/range/interfaces/BidirectionalRange.html /library-prerelease/std/range/interfaces/bidirectional_range.html +/library-prerelease/std/range/interfaces/ForwardAssignable.html /library-prerelease/std/range/interfaces/forward_assignable.html +/library-prerelease/std/range/interfaces/ForwardRange.html /library-prerelease/std/range/interfaces/forward_range.html +/library-prerelease/std/range/interfaces/InputAssignable.html /library-prerelease/std/range/interfaces/input_assignable.html +/library-prerelease/std/range/interfaces/InputRange.html /library-prerelease/std/range/interfaces/input_range.html +/library-prerelease/std/range/interfaces/inputRangeObject.html /library-prerelease/std/range/interfaces/input_range_object.html +/library-prerelease/std/range/interfaces/InputRangeObject.html /library-prerelease/std/range/interfaces/input_range_object.html +/library-prerelease/std/range/interfaces/InputRange.opApply.html /library-prerelease/std/range/interfaces/input_range.op_apply.html +/library-prerelease/std/range/interfaces/MostDerivedInputRange.html /library-prerelease/std/range/interfaces/most_derived_input_range.html +/library-prerelease/std/range/interfaces/Object.factory.html /library-prerelease/std/range/interfaces/object.factory.html +/library-prerelease/std/range/interfaces/Object.opCmp.html /library-prerelease/std/range/interfaces/object.op_cmp.html +/library-prerelease/std/range/interfaces/Object.opEquals.html /library-prerelease/std/range/interfaces/object.op_equals.html +/library-prerelease/std/range/interfaces/Object.toHash.html /library-prerelease/std/range/interfaces/object.to_hash.html +/library-prerelease/std/range/interfaces/Object.toString.html /library-prerelease/std/range/interfaces/object.to_string.html +/library-prerelease/std/range/interfaces/OutputRange.html /library-prerelease/std/range/interfaces/output_range.html +/library-prerelease/std/range/interfaces/outputRangeObject.html /library-prerelease/std/range/interfaces/output_range_object.html +/library-prerelease/std/range/interfaces/OutputRangeObject.html /library-prerelease/std/range/interfaces/output_range_object.html +/library-prerelease/std/range/interfaces/outputRangeObject.outputRangeObject.html /library-prerelease/std/range/interfaces/output_range_object.output_range_object.html +/library-prerelease/std/range/interfaces/RandomAccessFinite.html /library-prerelease/std/range/interfaces/random_access_finite.html +/library-prerelease/std/range/interfaces/RandomAccessInfinite.html /library-prerelease/std/range/interfaces/random_access_infinite.html +/library-prerelease/std/range/interfaces/RandomFiniteAssignable.html /library-prerelease/std/range/interfaces/random_finite_assignable.html +/library-prerelease/std/range/isTwoWayCompatible.html /library-prerelease/std/range/is_two_way_compatible.html +/library-prerelease/std/range/Lockstep.html /library-prerelease/std/range/lockstep.html +/library-prerelease/std/range/NullSink.html /library-prerelease/std/range/null_sink.html +/library-prerelease/std/range/primitives/ElementEncodingType.html /library-prerelease/std/range/primitives/element_encoding_type.html +/library-prerelease/std/range/primitives/ElementType.html /library-prerelease/std/range/primitives/element_type.html +/library-prerelease/std/range/primitives/hasAssignableElements.html /library-prerelease/std/range/primitives/has_assignable_elements.html +/library-prerelease/std/range/primitives/hasLength.html /library-prerelease/std/range/primitives/has_length.html +/library-prerelease/std/range/primitives/hasLvalueElements.html /library-prerelease/std/range/primitives/has_lvalue_elements.html +/library-prerelease/std/range/primitives/hasMobileElements.html /library-prerelease/std/range/primitives/has_mobile_elements.html +/library-prerelease/std/range/primitives/hasSlicing.html /library-prerelease/std/range/primitives/has_slicing.html +/library-prerelease/std/range/primitives/hasSwappableElements.html /library-prerelease/std/range/primitives/has_swappable_elements.html +/library-prerelease/std/range/primitives/isBidirectionalRange.html /library-prerelease/std/range/primitives/is_bidirectional_range.html +/library-prerelease/std/range/primitives/isForwardRange.html /library-prerelease/std/range/primitives/is_forward_range.html +/library-prerelease/std/range/primitives/isInfinite.html /library-prerelease/std/range/primitives/is_infinite.html +/library-prerelease/std/range/primitives/isInputRange.html /library-prerelease/std/range/primitives/is_input_range.html +/library-prerelease/std/range/primitives/isOutputRange.html /library-prerelease/std/range/primitives/is_output_range.html +/library-prerelease/std/range/primitives/isRandomAccessRange.html /library-prerelease/std/range/primitives/is_random_access_range.html +/library-prerelease/std/range/primitives/moveAt.html /library-prerelease/std/range/primitives/move_at.html +/library-prerelease/std/range/primitives/moveBack.html /library-prerelease/std/range/primitives/move_back.html +/library-prerelease/std/range/primitives/moveFront.html /library-prerelease/std/range/primitives/move_front.html +/library-prerelease/std/range/primitives/popBackExactly.html /library-prerelease/std/range/primitives/pop_back_exactly.html +/library-prerelease/std/range/primitives/popBack.html /library-prerelease/std/range/primitives/pop_back.html +/library-prerelease/std/range/primitives/popBackN.html /library-prerelease/std/range/primitives/pop_back.html +/library-prerelease/std/range/primitives/popFrontExactly.html /library-prerelease/std/range/primitives/pop_front_exactly.html +/library-prerelease/std/range/primitives/popFront.html /library-prerelease/std/range/primitives/pop_front.html +/library-prerelease/std/range/primitives/popFrontN.html /library-prerelease/std/range/primitives/pop_front.html +/library-prerelease/std/range/primitives/walkLength.html /library-prerelease/std/range/primitives/walk_length.html +/library-prerelease/std/range/Recurrence.html /library-prerelease/std/range/recurrence.html +/library-prerelease/std/range/refRange.html /library-prerelease/std/range/ref_range.html +/library-prerelease/std/range/RefRange.html /library-prerelease/std/range/ref_range.html +/library-prerelease/std/range/RefRange.opAssign.html /library-prerelease/std/range/ref_range.op_assign.html +/library-prerelease/std/range/RefRange.ptr.html /library-prerelease/std/range/ref_range.ptr.html +/library-prerelease/std/range/Repeat.html /library-prerelease/std/range/repeat.html +/library-prerelease/std/range/roundRobin.html /library-prerelease/std/range/round_robin.html +/library-prerelease/std/range/SearchPolicy.binarySearch.html /library-prerelease/std/range/search_policy.binary_search.html +/library-prerelease/std/range/SearchPolicy.gallopBackwards.html /library-prerelease/std/range/search_policy.gallop_backwards.html +/library-prerelease/std/range/SearchPolicy.gallop.html /library-prerelease/std/range/search_policy.gallop.html +/library-prerelease/std/range/SearchPolicy.html /library-prerelease/std/range/search_policy.html +/library-prerelease/std/range/SearchPolicy.linear.html /library-prerelease/std/range/search_policy.linear.html +/library-prerelease/std/range/SearchPolicy.trotBackwards.html /library-prerelease/std/range/search_policy.trot_backwards.html +/library-prerelease/std/range/SearchPolicy.trot.html /library-prerelease/std/range/search_policy.trot.html +/library-prerelease/std/range/Sequence.html /library-prerelease/std/range/sequence.html +/library-prerelease/std/range/SortedRange.contains.contains.html /library-prerelease/std/range/sorted_range.contains.contains.html +/library-prerelease/std/range/SortedRange.contains.html /library-prerelease/std/range/sorted_range.contains.html +/library-prerelease/std/range/SortedRange.empty.html /library-prerelease/std/range/sorted_range.empty.html +/library-prerelease/std/range/SortedRange.equalRange.equalRange.html /library-prerelease/std/range/sorted_range.equal_range.equal_range.html +/library-prerelease/std/range/SortedRange.equalRange.html /library-prerelease/std/range/sorted_range.equal_range.html +/library-prerelease/std/range/SortedRange.front.html /library-prerelease/std/range/sorted_range.front.html +/library-prerelease/std/range/SortedRange.groupBy.groupBy.html /library-prerelease/std/range/sorted_range.group_by.group_by.html +/library-prerelease/std/range/SortedRange.groupBy.html /library-prerelease/std/range/sorted_range.group_by.html +/library-prerelease/std/range/SortedRange.html /library-prerelease/std/range/sorted_range.html +/library-prerelease/std/range/SortedRange.lowerBound.html /library-prerelease/std/range/sorted_range.lower_bound.html +/library-prerelease/std/range/SortedRange.lowerBound.lowerBound.html /library-prerelease/std/range/sorted_range.lower_bound.lower_bound.html +/library-prerelease/std/range/SortedRange.popFront.html /library-prerelease/std/range/sorted_range.pop_front.html +/library-prerelease/std/range/SortedRange.release.html /library-prerelease/std/range/sorted_range.release.html +/library-prerelease/std/range/SortedRange.trisect.html /library-prerelease/std/range/sorted_range.trisect.html +/library-prerelease/std/range/SortedRange.trisect.trisect.html /library-prerelease/std/range/sorted_range.trisect.trisect.html +/library-prerelease/std/range/SortedRange.upperBound.html /library-prerelease/std/range/sorted_range.upper_bound.html +/library-prerelease/std/range/SortedRange.upperBound.upperBound.html /library-prerelease/std/range/sorted_range.upper_bound.upper_bound.html +/library-prerelease/std/range/StoppingPolicy.html /library-prerelease/std/range/stopping_policy.html +/library-prerelease/std/range/StoppingPolicy.longest.html /library-prerelease/std/range/stopping_policy.longest.html +/library-prerelease/std/range/StoppingPolicy.requireSameLength.html /library-prerelease/std/range/stopping_policy.require_same_length.html +/library-prerelease/std/range/StoppingPolicy.shortest.html /library-prerelease/std/range/stopping_policy.shortest.html +/library-prerelease/std/range/takeExactly.html /library-prerelease/std/range/take_exactly.html +/library-prerelease/std/range/Take.html /library-prerelease/std/range/take.html +/library-prerelease/std/range/takeNone.html /library-prerelease/std/range/take_none.html +/library-prerelease/std/range/takeOne.html /library-prerelease/std/range/take_one.html +/library-prerelease/std/range/Transversal.front.html /library-prerelease/std/range/transversal.front.html +/library-prerelease/std/range/Transversal.html /library-prerelease/std/range/transversal.html +/library-prerelease/std/range/Transversal.popFront.html /library-prerelease/std/range/transversal.pop_front.html +/library-prerelease/std/range/Transversal.this.html /library-prerelease/std/range/transversal.this.html +/library-prerelease/std/range/TransverseOptions.assumeJagged.html /library-prerelease/std/range/transverse_options.assume_jagged.html +/library-prerelease/std/range/TransverseOptions.assumeNotJagged.html /library-prerelease/std/range/transverse_options.assume_not_jagged.html +/library-prerelease/std/range/TransverseOptions.enforceNotJagged.html /library-prerelease/std/range/transverse_options.enforce_not_jagged.html +/library-prerelease/std/range/TransverseOptions.html /library-prerelease/std/range/transverse_options.html +/library-prerelease/std/range/Zip.front.html /library-prerelease/std/range/zip.front.html +/library-prerelease/std/range/Zip.html /library-prerelease/std/range/zip.html +/library-prerelease/std/range/Zip.popFront.html /library-prerelease/std/range/zip.pop_front.html +/library-prerelease/std/range/Zip.this.html /library-prerelease/std/range/zip.this.html +/library-prerelease/std/regex/Captures.back.html /library-prerelease/std/regex/captures.back.html +/library-prerelease/std/regex/Captures.captures.html /library-prerelease/std/regex/captures.captures.html +/library-prerelease/std/regex/Captures.empty.html /library-prerelease/std/regex/captures.empty.html +/library-prerelease/std/regex/Captures.front.html /library-prerelease/std/regex/captures.front.html +/library-prerelease/std/regex/Captures.hit.html /library-prerelease/std/regex/captures.hit.html +/library-prerelease/std/regex/Captures.html /library-prerelease/std/regex/captures.html +/library-prerelease/std/regex/Captures.length.html /library-prerelease/std/regex/captures.length.html +/library-prerelease/std/regex/Captures.opCast.html /library-prerelease/std/regex/captures.op_cast.html +/library-prerelease/std/regex/Captures.opCast.opCast.html /library-prerelease/std/regex/captures.op_cast.op_cast.html +/library-prerelease/std/regex/Captures.opIndex.html /library-prerelease/std/regex/captures.op_index.html +/library-prerelease/std/regex/Captures.opIndex.opIndex.html /library-prerelease/std/regex/captures.op_index.op_index.html +/library-prerelease/std/regex/Captures.popBack.html /library-prerelease/std/regex/captures.pop_back.html +/library-prerelease/std/regex/Captures.popFront.html /library-prerelease/std/regex/captures.pop_front.html +/library-prerelease/std/regex/Captures.post.html /library-prerelease/std/regex/captures.post.html +/library-prerelease/std/regex/Captures.pre.html /library-prerelease/std/regex/captures.pre.html +/library-prerelease/std/regex/ctRegex.html /library-prerelease/std/regex/ct_regex.html +/library-prerelease/std/regex/matchAll.html /library-prerelease/std/regex/match_all.html +/library-prerelease/std/regex/matchFirst.html /library-prerelease/std/regex/match_first.html +/library-prerelease/std/regex/RegexException.html /library-prerelease/std/regex/regex_exception.html +/library-prerelease/std/regex/Regex.html /library-prerelease/std/regex/regex.html +/library-prerelease/std/regex/RegexMatch.captures.html /library-prerelease/std/regex/regex_match.captures.html +/library-prerelease/std/regex/RegexMatch.empty.html /library-prerelease/std/regex/regex_match.empty.html +/library-prerelease/std/regex/RegexMatch.front.html /library-prerelease/std/regex/regex_match.front.html +/library-prerelease/std/regex/RegexMatch.hit.html /library-prerelease/std/regex/regex_match.hit.html +/library-prerelease/std/regex/RegexMatch.html /library-prerelease/std/regex/regex_match.html +/library-prerelease/std/regex/RegexMatch.opCast.html /library-prerelease/std/regex/regex_match.op_cast.html +/library-prerelease/std/regex/RegexMatch.opCast.opCast.html /library-prerelease/std/regex/regex_match.op_cast.op_cast.html +/library-prerelease/std/regex/RegexMatch.popFront.html /library-prerelease/std/regex/regex_match.pop_front.html +/library-prerelease/std/regex/RegexMatch.post.html /library-prerelease/std/regex/regex_match.post.html +/library-prerelease/std/regex/RegexMatch.pre.html /library-prerelease/std/regex/regex_match.pre.html +/library-prerelease/std/regex/RegexMatch.save.html /library-prerelease/std/regex/regex_match.save.html +/library-prerelease/std/regex/replaceAll.html /library-prerelease/std/regex/replace_all.html +/library-prerelease/std/regex/replaceAllInto.html /library-prerelease/std/regex/replace_all_into.html +/library-prerelease/std/regex/replaceFirst.html /library-prerelease/std/regex/replace_first.html +/library-prerelease/std/regex/replaceFirstInto.html /library-prerelease/std/regex/replace_first_into.html +/library-prerelease/std/regex/Splitter.empty.html /library-prerelease/std/regex/splitter.empty.html +/library-prerelease/std/regex/Splitter.front.html /library-prerelease/std/regex/splitter.front.html +/library-prerelease/std/regex/Splitter.html /library-prerelease/std/regex/splitter.html +/library-prerelease/std/regex/Splitter.popFront.html /library-prerelease/std/regex/splitter.pop_front.html +/library-prerelease/std/regex/Splitter.save.html /library-prerelease/std/regex/splitter.save.html +/library-prerelease/std/regex/StaticRegex.html /library-prerelease/std/regex/static_regex.html +/library-prerelease/std/signals/Signal.connect.html /library-prerelease/std/signals/signal.connect.html +/library-prerelease/std/signals/Signal.disconnect.html /library-prerelease/std/signals/signal.disconnect.html +/library-prerelease/std/signals/Signal.emit.html /library-prerelease/std/signals/signal.emit.html +/library-prerelease/std/signals/Signal.html /library-prerelease/std/signals/signal.html +/library-prerelease/std/signals/Signal.slot_t.html /library-prerelease/std/signals/signal.slot_t.html +/library-prerelease/std/socket/Address.addressFamily.html /library-prerelease/std/socket/address.address_family.html +/library-prerelease/std/socket/AddressException.html /library-prerelease/std/socket/address_exception.html +/library-prerelease/std/socket/AddressFamily.APPLETALK.html /library-prerelease/std/socket/address_family.appletalk.html +/library-prerelease/std/socket/AddressFamily.html /library-prerelease/std/socket/address_family.html +/library-prerelease/std/socket/AddressFamily.INET6.html /library-prerelease/std/socket/address_family.ine_t6.html +/library-prerelease/std/socket/AddressFamily.INET.html /library-prerelease/std/socket/address_family.inet.html +/library-prerelease/std/socket/AddressFamily.IPX.html /library-prerelease/std/socket/address_family.ipx.html +/library-prerelease/std/socket/AddressFamily.UNIX.html /library-prerelease/std/socket/address_family.unix.html +/library-prerelease/std/socket/AddressFamily.UNSPEC.html /library-prerelease/std/socket/address_family.unspec.html +/library-prerelease/std/socket/Address.html /library-prerelease/std/socket/address.html +/library-prerelease/std/socket/AddressInfo.address.html /library-prerelease/std/socket/address_info.address.html +/library-prerelease/std/socket/AddressInfo.canonicalName.html /library-prerelease/std/socket/address_info.canonical_name.html +/library-prerelease/std/socket/AddressInfo.family.html /library-prerelease/std/socket/address_info.family.html +/library-prerelease/std/socket/AddressInfoFlags.CANONNAME.html /library-prerelease/std/socket/address_info_flags.canonname.html +/library-prerelease/std/socket/AddressInfoFlags.html /library-prerelease/std/socket/address_info_flags.html +/library-prerelease/std/socket/AddressInfoFlags.NUMERICHOST.html /library-prerelease/std/socket/address_info_flags.numerichost.html +/library-prerelease/std/socket/AddressInfoFlags.PASSIVE.html /library-prerelease/std/socket/address_info_flags.passive.html +/library-prerelease/std/socket/AddressInfo.html /library-prerelease/std/socket/address_info.html +/library-prerelease/std/socket/AddressInfo.protocol.html /library-prerelease/std/socket/address_info.protocol.html +/library-prerelease/std/socket/AddressInfo.type.html /library-prerelease/std/socket/address_info.type.html +/library-prerelease/std/socket/Address.name.html /library-prerelease/std/socket/address.name.html +/library-prerelease/std/socket/Address.nameLen.html /library-prerelease/std/socket/address.name_len.html +/library-prerelease/std/socket/Address.toAddrString.html /library-prerelease/std/socket/address.to_addr_string.html +/library-prerelease/std/socket/Address.toHostNameString.html /library-prerelease/std/socket/address.to_host_name_string.html +/library-prerelease/std/socket/Address.toPortString.html /library-prerelease/std/socket/address.to_port_string.html +/library-prerelease/std/socket/Address.toServiceNameString.html /library-prerelease/std/socket/address.to_service_name_string.html +/library-prerelease/std/socket/Address.toString.html /library-prerelease/std/socket/address.to_string.html +/library-prerelease/std/socket/getAddress.html /library-prerelease/std/socket/get_address.html +/library-prerelease/std/socket/getAddressInfo.html /library-prerelease/std/socket/get_address_info.html +/library-prerelease/std/socket/HostException.html /library-prerelease/std/socket/host_exception.html +/library-prerelease/std/socket/Internet6Address.ADDR_ANY.html /library-prerelease/std/socket/internet6_address.add_r_any.html +/library-prerelease/std/socket/Internet6Address.addr.html /library-prerelease/std/socket/internet6_address.addr.html +/library-prerelease/std/socket/Internet6Address.html /library-prerelease/std/socket/internet6_address.html +/library-prerelease/std/socket/Internet6Address.parse.html /library-prerelease/std/socket/internet6_address.parse.html +/library-prerelease/std/socket/Internet6Address.PORT_ANY.html /library-prerelease/std/socket/internet6_address.por_t_any.html +/library-prerelease/std/socket/Internet6Address.port.html /library-prerelease/std/socket/internet6_address.port.html +/library-prerelease/std/socket/Internet6Address.this.html /library-prerelease/std/socket/internet6_address.this.html +/library-prerelease/std/socket/InternetAddress.ADDR_ANY.html /library-prerelease/std/socket/internet_address.add_r_any.html +/library-prerelease/std/socket/InternetAddress.addr.html /library-prerelease/std/socket/internet_address.addr.html +/library-prerelease/std/socket/InternetAddress.ADDR_NONE.html /library-prerelease/std/socket/internet_address.add_r_none.html +/library-prerelease/std/socket/InternetAddress.addrToString.html /library-prerelease/std/socket/internet_address.addr_to_string.html +/library-prerelease/std/socket/InternetAddress.html /library-prerelease/std/socket/internet_address.html +/library-prerelease/std/socket/InternetAddress.opEquals.html /library-prerelease/std/socket/internet_address.op_equals.html +/library-prerelease/std/socket/InternetAddress.parse.html /library-prerelease/std/socket/internet_address.parse.html +/library-prerelease/std/socket/InternetAddress.PORT_ANY.html /library-prerelease/std/socket/internet_address.por_t_any.html +/library-prerelease/std/socket/InternetAddress.port.html /library-prerelease/std/socket/internet_address.port.html +/library-prerelease/std/socket/InternetAddress.this.html /library-prerelease/std/socket/internet_address.this.html +/library-prerelease/std/socket/InternetAddress.toAddrString.html /library-prerelease/std/socket/internet_address.to_addr_string.html +/library-prerelease/std/socket/InternetAddress.toHostNameString.html /library-prerelease/std/socket/internet_address.to_host_name_string.html +/library-prerelease/std/socket/InternetAddress.toPortString.html /library-prerelease/std/socket/internet_address.to_port_string.html +/library-prerelease/std/socket/InternetHost.addrList.html /library-prerelease/std/socket/internet_host.addr_list.html +/library-prerelease/std/socket/InternetHost.aliases.html /library-prerelease/std/socket/internet_host.aliases.html +/library-prerelease/std/socket/InternetHost.getHostByAddr.html /library-prerelease/std/socket/internet_host.get_host_by_addr.html +/library-prerelease/std/socket/InternetHost.getHostByName.html /library-prerelease/std/socket/internet_host.get_host_by_name.html +/library-prerelease/std/socket/InternetHost.html /library-prerelease/std/socket/internet_host.html +/library-prerelease/std/socket/InternetHost.name.html /library-prerelease/std/socket/internet_host.name.html +/library-prerelease/std/socket/lastSocketError.html /library-prerelease/std/socket/last_socket_error.html +/library-prerelease/std/socket/Linger.html /library-prerelease/std/socket/linger.html +/library-prerelease/std/socket/Linger.on.html /library-prerelease/std/socket/linger.on.html +/library-prerelease/std/socket/Linger.time.html /library-prerelease/std/socket/linger.time.html +/library-prerelease/std/socket/Object.factory.html /library-prerelease/std/socket/object.factory.html +/library-prerelease/std/socket/Object.opCmp.html /library-prerelease/std/socket/object.op_cmp.html +/library-prerelease/std/socket/Object.opEquals.html /library-prerelease/std/socket/object.op_equals.html +/library-prerelease/std/socket/Object.toHash.html /library-prerelease/std/socket/object.to_hash.html +/library-prerelease/std/socket/Object.toString.html /library-prerelease/std/socket/object.to_string.html +/library-prerelease/std/socket/parseAddress.html /library-prerelease/std/socket/parse_address.html +/library-prerelease/std/socket/Protocol.aliases.html /library-prerelease/std/socket/protocol.aliases.html +/library-prerelease/std/socket/Protocol.getProtocolByName.html /library-prerelease/std/socket/protocol.get_protocol_by_name.html +/library-prerelease/std/socket/Protocol.getProtocolByType.html /library-prerelease/std/socket/protocol.get_protocol_by_type.html +/library-prerelease/std/socket/Protocol.html /library-prerelease/std/socket/protocol.html +/library-prerelease/std/socket/Protocol.name.html /library-prerelease/std/socket/protocol.name.html +/library-prerelease/std/socket/ProtocolType.GGP.html /library-prerelease/std/socket/protocol_type.ggp.html +/library-prerelease/std/socket/Protocol.type.html /library-prerelease/std/socket/protocol.type.html +/library-prerelease/std/socket/ProtocolType.html /library-prerelease/std/socket/protocol_type.html +/library-prerelease/std/socket/ProtocolType.ICMP.html /library-prerelease/std/socket/protocol_type.icmp.html +/library-prerelease/std/socket/ProtocolType.IDP.html /library-prerelease/std/socket/protocol_type.idp.html +/library-prerelease/std/socket/ProtocolType.IGMP.html /library-prerelease/std/socket/protocol_type.igmp.html +/library-prerelease/std/socket/ProtocolType.IP.html /library-prerelease/std/socket/protocol_type.ip.html +/library-prerelease/std/socket/ProtocolType.IPV6.html /library-prerelease/std/socket/protocol_type.ip_v6.html +/library-prerelease/std/socket/ProtocolType.PUP.html /library-prerelease/std/socket/protocol_type.pup.html +/library-prerelease/std/socket/ProtocolType.RAW.html /library-prerelease/std/socket/protocol_type.raw.html +/library-prerelease/std/socket/ProtocolType.TCP.html /library-prerelease/std/socket/protocol_type.tcp.html +/library-prerelease/std/socket/ProtocolType.UDP.html /library-prerelease/std/socket/protocol_type.udp.html +/library-prerelease/std/socket/Service.aliases.html /library-prerelease/std/socket/service.aliases.html +/library-prerelease/std/socket/Service.getServiceByName.html /library-prerelease/std/socket/service.get_service_by_name.html +/library-prerelease/std/socket/Service.getServiceByPort.html /library-prerelease/std/socket/service.get_service_by_port.html +/library-prerelease/std/socket/Service.html /library-prerelease/std/socket/service.html +/library-prerelease/std/socket/Service.name.html /library-prerelease/std/socket/service.name.html +/library-prerelease/std/socket/Service.port.html /library-prerelease/std/socket/service.port.html +/library-prerelease/std/socket/Service.protocolName.html /library-prerelease/std/socket/service.protocol_name.html +/library-prerelease/std/socket/SocketAcceptException.html /library-prerelease/std/socket/socket_accept_exception.html +/library-prerelease/std/socket/Socket.accept.html /library-prerelease/std/socket/socket.accept.html +/library-prerelease/std/socket/Socket.accepting.html /library-prerelease/std/socket/socket.accepting.html +/library-prerelease/std/socket/Socket.addressFamily.html /library-prerelease/std/socket/socket.address_family.html +/library-prerelease/std/socket/Socket.bind.html /library-prerelease/std/socket/socket.bind.html +/library-prerelease/std/socket/Socket.blocking.html /library-prerelease/std/socket/socket.blocking.html +/library-prerelease/std/socket/Socket.close.html /library-prerelease/std/socket/socket.close.html +/library-prerelease/std/socket/Socket.connect.html /library-prerelease/std/socket/socket.connect.html +/library-prerelease/std/socket/Socket.createAddress.html /library-prerelease/std/socket/socket.create_address.html +/library-prerelease/std/socket/Socket.ERROR.html /library-prerelease/std/socket/socket.error.html +/library-prerelease/std/socket/SocketException.html /library-prerelease/std/socket/socket_exception.html +/library-prerelease/std/socket/SocketFeatureException.html /library-prerelease/std/socket/socket_feature_exception.html +/library-prerelease/std/socket/SocketFlags.DONTROUTE.html /library-prerelease/std/socket/socket_flags.dontroute.html +/library-prerelease/std/socket/SocketFlags.html /library-prerelease/std/socket/socket_flags.html +/library-prerelease/std/socket/SocketFlags.NONE.html /library-prerelease/std/socket/socket_flags.none.html +/library-prerelease/std/socket/SocketFlags.OOB.html /library-prerelease/std/socket/socket_flags.oob.html +/library-prerelease/std/socket/SocketFlags.PEEK.html /library-prerelease/std/socket/socket_flags.peek.html +/library-prerelease/std/socket/Socket.getErrorText.html /library-prerelease/std/socket/socket.get_error_text.html +/library-prerelease/std/socket/Socket.getOption.html /library-prerelease/std/socket/socket.get_option.html +/library-prerelease/std/socket/Socket.handle.html /library-prerelease/std/socket/socket.handle.html +/library-prerelease/std/socket/Socket.hostName.html /library-prerelease/std/socket/socket.host_name.html +/library-prerelease/std/socket/Socket.html /library-prerelease/std/socket/socket.html +/library-prerelease/std/socket/Socket.isAlive.html /library-prerelease/std/socket/socket.is_alive.html +/library-prerelease/std/socket/Socket.listen.html /library-prerelease/std/socket/socket.listen.html +/library-prerelease/std/socket/Socket.localAddress.html /library-prerelease/std/socket/socket.local_address.html +/library-prerelease/std/socket/SocketOption.ACCEPTCONN.html /library-prerelease/std/socket/socket_option.acceptconn.html +/library-prerelease/std/socket/SocketOption.BROADCAST.html /library-prerelease/std/socket/socket_option.broadcast.html +/library-prerelease/std/socket/SocketOption.DEBUG.html /library-prerelease/std/socket/socket_option.debug.html +/library-prerelease/std/socket/SocketOption.DONTROUTE.html /library-prerelease/std/socket/socket_option.dontroute.html +/library-prerelease/std/socket/SocketOption.ERROR.html /library-prerelease/std/socket/socket_option.error.html +/library-prerelease/std/socket/SocketOption.html /library-prerelease/std/socket/socket_option.html +/library-prerelease/std/socket/SocketOption.IPV6_JOIN_GROUP.html /library-prerelease/std/socket/socket_option.ip_v6__joi_n_group.html +/library-prerelease/std/socket/SocketOption.IPV6_LEAVE_GROUP.html /library-prerelease/std/socket/socket_option.ip_v6__leav_e_group.html +/library-prerelease/std/socket/SocketOption.IPV6_MULTICAST_HOPS.html /library-prerelease/std/socket/socket_option.ip_v6__multicas_t_hops.html +/library-prerelease/std/socket/SocketOption.IPV6_MULTICAST_IF.html /library-prerelease/std/socket/socket_option.ip_v6__multicas_t_if.html +/library-prerelease/std/socket/SocketOption.IPV6_MULTICAST_LOOP.html /library-prerelease/std/socket/socket_option.ip_v6__multicas_t_loop.html +/library-prerelease/std/socket/SocketOption.IPV6_UNICAST_HOPS.html /library-prerelease/std/socket/socket_option.ip_v6__unicas_t_hops.html +/library-prerelease/std/socket/SocketOption.IPV6_V6ONLY.html /library-prerelease/std/socket/socket_option.ip_v6__v6only.html +/library-prerelease/std/socket/SocketOption.KEEPALIVE.html /library-prerelease/std/socket/socket_option.keepalive.html +/library-prerelease/std/socket/SocketOptionLevel.GGP.html /library-prerelease/std/socket/socket_option_level.ggp.html +/library-prerelease/std/socket/SocketOptionLevel.html /library-prerelease/std/socket/socket_option_level.html +/library-prerelease/std/socket/SocketOptionLevel.ICMP.html /library-prerelease/std/socket/socket_option_level.icmp.html +/library-prerelease/std/socket/SocketOptionLevel.IDP.html /library-prerelease/std/socket/socket_option_level.idp.html +/library-prerelease/std/socket/SocketOptionLevel.IGMP.html /library-prerelease/std/socket/socket_option_level.igmp.html +/library-prerelease/std/socket/SocketOptionLevel.IP.html /library-prerelease/std/socket/socket_option_level.ip.html +/library-prerelease/std/socket/SocketOptionLevel.IPV6.html /library-prerelease/std/socket/socket_option_level.ip_v6.html +/library-prerelease/std/socket/SocketOptionLevel.PUP.html /library-prerelease/std/socket/socket_option_level.pup.html +/library-prerelease/std/socket/SocketOptionLevel.RAW.html /library-prerelease/std/socket/socket_option_level.raw.html +/library-prerelease/std/socket/SocketOptionLevel.SOCKET.html /library-prerelease/std/socket/socket_option_level.socket.html +/library-prerelease/std/socket/SocketOptionLevel.TCP.html /library-prerelease/std/socket/socket_option_level.tcp.html +/library-prerelease/std/socket/SocketOptionLevel.UDP.html /library-prerelease/std/socket/socket_option_level.udp.html +/library-prerelease/std/socket/SocketOption.LINGER.html /library-prerelease/std/socket/socket_option.linger.html +/library-prerelease/std/socket/SocketOption.OOBINLINE.html /library-prerelease/std/socket/socket_option.oobinline.html +/library-prerelease/std/socket/SocketOption.RCVBUF.html /library-prerelease/std/socket/socket_option.rcvbuf.html +/library-prerelease/std/socket/SocketOption.RCVLOWAT.html /library-prerelease/std/socket/socket_option.rcvlowat.html +/library-prerelease/std/socket/SocketOption.RCVTIMEO.html /library-prerelease/std/socket/socket_option.rcvtimeo.html +/library-prerelease/std/socket/SocketOption.REUSEADDR.html /library-prerelease/std/socket/socket_option.reuseaddr.html +/library-prerelease/std/socket/SocketOption.SNDBUF.html /library-prerelease/std/socket/socket_option.sndbuf.html +/library-prerelease/std/socket/SocketOption.SNDLOWAT.html /library-prerelease/std/socket/socket_option.sndlowat.html +/library-prerelease/std/socket/SocketOption.SNDTIMEO.html /library-prerelease/std/socket/socket_option.sndtimeo.html +/library-prerelease/std/socket/SocketOption.TCP_NODELAY.html /library-prerelease/std/socket/socket_option.tc_p_nodelay.html +/library-prerelease/std/socket/SocketOption.TYPE.html /library-prerelease/std/socket/socket_option.type.html +/library-prerelease/std/socket/SocketOSException.errorCode.html /library-prerelease/std/socket/socket_os_exception.error_code.html +/library-prerelease/std/socket/SocketOSException.html /library-prerelease/std/socket/socket_os_exception.html +/library-prerelease/std/socket/socketPair.html /library-prerelease/std/socket/socket_pair.html +/library-prerelease/std/socket/SocketParameterException.html /library-prerelease/std/socket/socket_parameter_exception.html +/library-prerelease/std/socket/Socket.receiveFrom.html /library-prerelease/std/socket/socket.receive_from.html +/library-prerelease/std/socket/Socket.receive.html /library-prerelease/std/socket/socket.receive.html +/library-prerelease/std/socket/Socket.remoteAddress.html /library-prerelease/std/socket/socket.remote_address.html +/library-prerelease/std/socket/Socket.select.html /library-prerelease/std/socket/socket.select.html +/library-prerelease/std/socket/Socket.send.html /library-prerelease/std/socket/socket.send.html +/library-prerelease/std/socket/Socket.sendTo.html /library-prerelease/std/socket/socket.send_to.html +/library-prerelease/std/socket/SocketSet.add.html /library-prerelease/std/socket/socket_set.add.html +/library-prerelease/std/socket/SocketSet.html /library-prerelease/std/socket/socket_set.html +/library-prerelease/std/socket/SocketSet.isSet.html /library-prerelease/std/socket/socket_set.is_set.html +/library-prerelease/std/socket/Socket.setKeepAlive.html /library-prerelease/std/socket/socket.set_keep_alive.html +/library-prerelease/std/socket/SocketSet.max.html /library-prerelease/std/socket/socket_set.max.html +/library-prerelease/std/socket/Socket.setOption.html /library-prerelease/std/socket/socket.set_option.html +/library-prerelease/std/socket/SocketSet.remove.html /library-prerelease/std/socket/socket_set.remove.html +/library-prerelease/std/socket/SocketSet.reset.html /library-prerelease/std/socket/socket_set.reset.html +/library-prerelease/std/socket/SocketSet.this.html /library-prerelease/std/socket/socket_set.this.html +/library-prerelease/std/socket/SocketShutdown.BOTH.html /library-prerelease/std/socket/socket_shutdown.both.html +/library-prerelease/std/socket/Socket.shutdown.html /library-prerelease/std/socket/socket.shutdown.html +/library-prerelease/std/socket/SocketShutdown.html /library-prerelease/std/socket/socket_shutdown.html +/library-prerelease/std/socket/SocketShutdown.RECEIVE.html /library-prerelease/std/socket/socket_shutdown.receive.html +/library-prerelease/std/socket/SocketShutdown.SEND.html /library-prerelease/std/socket/socket_shutdown.send.html +/library-prerelease/std/socket/Socket.this.html /library-prerelease/std/socket/socket.this.html +/library-prerelease/std/socket/SocketType.DGRAM.html /library-prerelease/std/socket/socket_type.dgram.html +/library-prerelease/std/socket/SocketType.html /library-prerelease/std/socket/socket_type.html +/library-prerelease/std/socket/SocketType.RAW.html /library-prerelease/std/socket/socket_type.raw.html +/library-prerelease/std/socket/SocketType.RDM.html /library-prerelease/std/socket/socket_type.rdm.html +/library-prerelease/std/socket/SocketType.SEQPACKET.html /library-prerelease/std/socket/socket_type.seqpacket.html +/library-prerelease/std/socket/SocketType.STREAM.html /library-prerelease/std/socket/socket_type.stream.html +/library-prerelease/std/socketstream/InputStream.available.html /library-prerelease/std/socketstream/input_stream.available.html +/library-prerelease/std/socketstream/InputStream.eof.html /library-prerelease/std/socketstream/input_stream.eof.html +/library-prerelease/std/socketstream/InputStream.getc.html /library-prerelease/std/socketstream/input_stream.getc.html +/library-prerelease/std/socketstream/InputStream.getcw.html /library-prerelease/std/socketstream/input_stream.getcw.html +/library-prerelease/std/socketstream/InputStream.isOpen.html /library-prerelease/std/socketstream/input_stream.is_open.html +/library-prerelease/std/socketstream/InputStream.opApply.html /library-prerelease/std/socketstream/input_stream.op_apply.html +/library-prerelease/std/socketstream/InputStream.readExact.html /library-prerelease/std/socketstream/input_stream.read_exact.html +/library-prerelease/std/socketstream/InputStream.readf.html /library-prerelease/std/socketstream/input_stream.readf.html +/library-prerelease/std/socketstream/InputStream.read.html /library-prerelease/std/socketstream/input_stream.read.html +/library-prerelease/std/socketstream/InputStream.readLine.html /library-prerelease/std/socketstream/input_stream.read_line.html +/library-prerelease/std/socketstream/InputStream.readLineW.html /library-prerelease/std/socketstream/input_stream.read_line.html +/library-prerelease/std/socketstream/InputStream.readString.html /library-prerelease/std/socketstream/input_stream.read_string.html +/library-prerelease/std/socketstream/InputStream.readStringW.html /library-prerelease/std/socketstream/input_stream.read_string.html +/library-prerelease/std/socketstream/InputStream.ungetc.html /library-prerelease/std/socketstream/input_stream.ungetc.html +/library-prerelease/std/socketstream/InputStream.ungetcw.html /library-prerelease/std/socketstream/input_stream.ungetcw.html +/library-prerelease/std/socketstream/InputStream.vreadf.html /library-prerelease/std/socketstream/input_stream.vreadf.html +/library-prerelease/std/socketstream/Object.factory.html /library-prerelease/std/socketstream/object.factory.html +/library-prerelease/std/socketstream/Object.opCmp.html /library-prerelease/std/socketstream/object.op_cmp.html +/library-prerelease/std/socketstream/Object.opEquals.html /library-prerelease/std/socketstream/object.op_equals.html +/library-prerelease/std/socketstream/OutputStream.flush.html /library-prerelease/std/socketstream/output_stream.flush.html +/library-prerelease/std/socketstream/OutputStream.printf.html /library-prerelease/std/socketstream/output_stream.printf.html +/library-prerelease/std/socketstream/OutputStream.vprintf.html /library-prerelease/std/socketstream/output_stream.vprintf.html +/library-prerelease/std/socketstream/OutputStream.writeExact.html /library-prerelease/std/socketstream/output_stream.write_exact.html +/library-prerelease/std/socketstream/OutputStream.writef.html /library-prerelease/std/socketstream/output_stream.writef.html +/library-prerelease/std/socketstream/OutputStream.writefln.html /library-prerelease/std/socketstream/output_stream.writefln.html +/library-prerelease/std/socketstream/OutputStream.writefx.html /library-prerelease/std/socketstream/output_stream.writefx.html +/library-prerelease/std/socketstream/OutputStream.write.html /library-prerelease/std/socketstream/output_stream.write.html +/library-prerelease/std/socketstream/OutputStream.writeLine.html /library-prerelease/std/socketstream/output_stream.write_line.html +/library-prerelease/std/socketstream/OutputStream.writeLineW.html /library-prerelease/std/socketstream/output_stream.write_line.html +/library-prerelease/std/socketstream/OutputStream.writeString.html /library-prerelease/std/socketstream/output_stream.write_string.html +/library-prerelease/std/socketstream/OutputStream.writeStringW.html /library-prerelease/std/socketstream/output_stream.write_string.html +/library-prerelease/std/socketstream/SocketStream.close.html /library-prerelease/std/socketstream/socket_stream.close.html +/library-prerelease/std/socketstream/SocketStream.html /library-prerelease/std/socketstream/socket_stream.html +/library-prerelease/std/socketstream/SocketStream.readBlock.html /library-prerelease/std/socketstream/socket_stream.read_block.html +/library-prerelease/std/socketstream/SocketStream.seek.html /library-prerelease/std/socketstream/socket_stream.seek.html +/library-prerelease/std/socketstream/SocketStream.socket.html /library-prerelease/std/socketstream/socket_stream.socket.html +/library-prerelease/std/socketstream/SocketStream.this.html /library-prerelease/std/socketstream/socket_stream.this.html +/library-prerelease/std/socketstream/SocketStream.toString.html /library-prerelease/std/socketstream/socket_stream.to_string.html +/library-prerelease/std/socketstream/SocketStream.writeBlock.html /library-prerelease/std/socketstream/socket_stream.write_block.html +/library-prerelease/std/socketstream/Stream.copyFrom.html /library-prerelease/std/socketstream/stream.copy_from.html +/library-prerelease/std/socketstream/Stream.isopen.html /library-prerelease/std/socketstream/stream.isopen.html +/library-prerelease/std/socketstream/Stream.position.html /library-prerelease/std/socketstream/stream.position.html +/library-prerelease/std/socketstream/Stream.prevCr.html /library-prerelease/std/socketstream/stream.prev_cr.html +/library-prerelease/std/socketstream/Stream.readable.html /library-prerelease/std/socketstream/stream.readable.html +/library-prerelease/std/socketstream/Stream.readEOF.html /library-prerelease/std/socketstream/stream.read_eof.html +/library-prerelease/std/socketstream/Stream.seekable.html /library-prerelease/std/socketstream/stream.seekable.html +/library-prerelease/std/socketstream/Stream.seekCur.html /library-prerelease/std/socketstream/stream.seek_cur.html +/library-prerelease/std/socketstream/Stream.seekEnd.html /library-prerelease/std/socketstream/stream.seek_end.html +/library-prerelease/std/socketstream/Stream.seekSet.html /library-prerelease/std/socketstream/stream.seek_set.html +/library-prerelease/std/socketstream/Stream.size.html /library-prerelease/std/socketstream/stream.size.html +/library-prerelease/std/socketstream/Stream.toHash.html /library-prerelease/std/socketstream/stream.to_hash.html +/library-prerelease/std/socketstream/Stream.writeable.html /library-prerelease/std/socketstream/stream.writeable.html +/library-prerelease/std/socket/TcpSocket.html /library-prerelease/std/socket/tcp_socket.html +/library-prerelease/std/socket/TcpSocket.this.html /library-prerelease/std/socket/tcp_socket.this.html +/library-prerelease/std/socket/Throwable.file.html /library-prerelease/std/socket/throwable.file.html +/library-prerelease/std/socket/Throwable.info.html /library-prerelease/std/socket/throwable.info.html +/library-prerelease/std/socket/Throwable.line.html /library-prerelease/std/socket/throwable.line.html +/library-prerelease/std/socket/Throwable.msg.html /library-prerelease/std/socket/throwable.msg.html +/library-prerelease/std/socket/Throwable.next.html /library-prerelease/std/socket/throwable.next.html +/library-prerelease/std/socket/Throwable.toString.html /library-prerelease/std/socket/throwable.to_string.html +/library-prerelease/std/socket/TimeVal.html /library-prerelease/std/socket/time_val.html +/library-prerelease/std/socket/TimeVal.microseconds.html /library-prerelease/std/socket/time_val.microseconds.html +/library-prerelease/std/socket/TimeVal.seconds.html /library-prerelease/std/socket/time_val.seconds.html +/library-prerelease/std/socket/UdpSocket.html /library-prerelease/std/socket/udp_socket.html +/library-prerelease/std/socket/UdpSocket.this.html /library-prerelease/std/socket/udp_socket.this.html +/library-prerelease/std/socket/UnixAddress.html /library-prerelease/std/socket/unix_address.html +/library-prerelease/std/socket/UnixAddress.path.html /library-prerelease/std/socket/unix_address.path.html +/library-prerelease/std/socket/UnixAddress.this.html /library-prerelease/std/socket/unix_address.this.html +/library-prerelease/std/socket/UnixAddress.toString.html /library-prerelease/std/socket/unix_address.to_string.html +/library-prerelease/std/socket/UnknownAddress.html /library-prerelease/std/socket/unknown_address.html +/library-prerelease/std/socket/UnknownAddressReference.html /library-prerelease/std/socket/unknown_address_reference.html +/library-prerelease/std/socket/UnknownAddressReference.this.html /library-prerelease/std/socket/unknown_address_reference.this.html +/library-prerelease/std/socket/wouldHaveBlocked.html /library-prerelease/std/socket/would_have_blocked.html +/library-prerelease/std/stdio/File.byChunk.html /library-prerelease/std/stdio/file.by_chunk.html +/library-prerelease/std/stdio/File.byLineCopy.html /library-prerelease/std/stdio/file.by_line_copy.html +/library-prerelease/std/stdio/File.byLine.html /library-prerelease/std/stdio/file.by_line.html +/library-prerelease/std/stdio/File.clearerr.html /library-prerelease/std/stdio/file.clearerr.html +/library-prerelease/std/stdio/File.close.html /library-prerelease/std/stdio/file.close.html +/library-prerelease/std/stdio/File.detach.html /library-prerelease/std/stdio/file.detach.html +/library-prerelease/std/stdio/File.eof.html /library-prerelease/std/stdio/file.eof.html +/library-prerelease/std/stdio/File.error.html /library-prerelease/std/stdio/file.error.html +/library-prerelease/std/stdio/File.fdopen.html /library-prerelease/std/stdio/file.fdopen.html +/library-prerelease/std/stdio/File.fileno.html /library-prerelease/std/stdio/file.fileno.html +/library-prerelease/std/stdio/File.flush.html /library-prerelease/std/stdio/file.flush.html +/library-prerelease/std/stdio/File.getFP.html /library-prerelease/std/stdio/file.get_fp.html +/library-prerelease/std/stdio/File.html /library-prerelease/std/stdio/file.html +/library-prerelease/std/stdio/File.isOpen.html /library-prerelease/std/stdio/file.is_open.html +/library-prerelease/std/stdio/File.lock.html /library-prerelease/std/stdio/file.lock.html +/library-prerelease/std/stdio/File.lockingTextWriter.html /library-prerelease/std/stdio/file.locking_text_writer.html +/library-prerelease/std/stdio/File.name.html /library-prerelease/std/stdio/file.name.html +/library-prerelease/std/stdio/File.opAssign.html /library-prerelease/std/stdio/file.op_assign.html +/library-prerelease/std/stdio/File.open.html /library-prerelease/std/stdio/file.open.html +/library-prerelease/std/stdio/File.popen.html /library-prerelease/std/stdio/file.popen.html +/library-prerelease/std/stdio/File.rawRead.html /library-prerelease/std/stdio/file.raw_read.html +/library-prerelease/std/stdio/File.rawWrite.html /library-prerelease/std/stdio/file.raw_write.html +/library-prerelease/std/stdio/File.readf.html /library-prerelease/std/stdio/file.readf.html +/library-prerelease/std/stdio/File.readln.html /library-prerelease/std/stdio/file.readln.html +/library-prerelease/std/stdio/File.rewind.html /library-prerelease/std/stdio/file.rewind.html +/library-prerelease/std/stdio/File.scratchFile.html /library-prerelease/std/stdio/file.scratch_file.html +/library-prerelease/std/stdio/File.seek.html /library-prerelease/std/stdio/file.seek.html +/library-prerelease/std/stdio/File.setvbuf.html /library-prerelease/std/stdio/file.setvbuf.html +/library-prerelease/std/stdio/File.size.html /library-prerelease/std/stdio/file.size.html +/library-prerelease/std/stdio/File.tell.html /library-prerelease/std/stdio/file.tell.html +/library-prerelease/std/stdio/File.this.html /library-prerelease/std/stdio/file.this.html +/library-prerelease/std/stdio/File.tmpfile.html /library-prerelease/std/stdio/file.tmpfile.html +/library-prerelease/std/stdio/File.tryLock.html /library-prerelease/std/stdio/file.try_lock.html +/library-prerelease/std/stdio/File.unlock.html /library-prerelease/std/stdio/file.unlock.html +/library-prerelease/std/stdio/File.windowsHandle.html /library-prerelease/std/stdio/file.windows_handle.html +/library-prerelease/std/stdio/File.windowsHandleOpen.html /library-prerelease/std/stdio/file.windows_handle_open.html +/library-prerelease/std/stdio/File.wrapFile.html /library-prerelease/std/stdio/file.wrap_file.html +/library-prerelease/std/stdio/File.writef.html /library-prerelease/std/stdio/file.writef.html +/library-prerelease/std/stdio/File.writefln.html /library-prerelease/std/stdio/file.writefln.html +/library-prerelease/std/stdio/File.write.html /library-prerelease/std/stdio/file.write.html +/library-prerelease/std/stdio/File.writeln.html /library-prerelease/std/stdio/file.writeln.html +/library-prerelease/std/stdio/isFileHandle.html /library-prerelease/std/stdio/is_file_handle.html +/library-prerelease/std/stdio/isStreamingDevice.html /library-prerelease/std/stdio/is_streaming_device.html +/library-prerelease/std/stdio/KeepTerminator.html /library-prerelease/std/stdio/keep_terminator.html +/library-prerelease/std/stdio/LockType.html /library-prerelease/std/stdio/lock_type.html +/library-prerelease/std/stdio/LockType.read.html /library-prerelease/std/stdio/lock_type.read.html +/library-prerelease/std/stdio/LockType.readWrite.html /library-prerelease/std/stdio/lock_type.read_write.html +/library-prerelease/std/stdio/Object.factory.html /library-prerelease/std/stdio/object.factory.html +/library-prerelease/std/stdio/Object.opCmp.html /library-prerelease/std/stdio/object.op_cmp.html +/library-prerelease/std/stdio/Object.opEquals.html /library-prerelease/std/stdio/object.op_equals.html +/library-prerelease/std/stdio/Object.toHash.html /library-prerelease/std/stdio/object.to_hash.html +/library-prerelease/std/stdio/openNetwork.html /library-prerelease/std/stdio/open_network.html +/library-prerelease/std/stdio/StdioException.errno.html /library-prerelease/std/stdio/stdio_exception.errno.html +/library-prerelease/std/stdio/StdioException.html /library-prerelease/std/stdio/stdio_exception.html +/library-prerelease/std/stdio/StdioException.opCall.html /library-prerelease/std/stdio/stdio_exception.op_call.html +/library-prerelease/std/stdio/StdioException.this.html /library-prerelease/std/stdio/stdio_exception.this.html +/library-prerelease/std/stdio/Throwable.file.html /library-prerelease/std/stdio/throwable.file.html +/library-prerelease/std/stdio/Throwable.info.html /library-prerelease/std/stdio/throwable.info.html +/library-prerelease/std/stdio/Throwable.line.html /library-prerelease/std/stdio/throwable.line.html +/library-prerelease/std/stdio/Throwable.msg.html /library-prerelease/std/stdio/throwable.msg.html +/library-prerelease/std/stdio/Throwable.next.html /library-prerelease/std/stdio/throwable.next.html +/library-prerelease/std/stdio/Throwable.toString.html /library-prerelease/std/stdio/throwable.to_string.html +/library-prerelease/std/stream/BOM.html /library-prerelease/std/stream/bom.html +/library-prerelease/std/stream/BOM.UTF16BE.html /library-prerelease/std/stream/bom.ut_f16_be.html +/library-prerelease/std/stream/BOM.UTF16LE.html /library-prerelease/std/stream/bom.ut_f16_le.html +/library-prerelease/std/stream/BOM.UTF32BE.html /library-prerelease/std/stream/bom.ut_f32_be.html +/library-prerelease/std/stream/BOM.UTF32LE.html /library-prerelease/std/stream/bom.ut_f32_le.html +/library-prerelease/std/stream/BOM.UTF8.html /library-prerelease/std/stream/bom.ut_f8.html +/library-prerelease/std/stream/BufferedFile.create.html /library-prerelease/std/stream/buffered_file.create.html +/library-prerelease/std/stream/BufferedFile.html /library-prerelease/std/stream/buffered_file.html +/library-prerelease/std/stream/BufferedFile.open.html /library-prerelease/std/stream/buffered_file.open.html +/library-prerelease/std/stream/BufferedFile.this.html /library-prerelease/std/stream/buffered_file.this.html +/library-prerelease/std/stream/BufferedStream.html /library-prerelease/std/stream/buffered_stream.html +/library-prerelease/std/stream/BufferedStream.this.html /library-prerelease/std/stream/buffered_stream.this.html +/library-prerelease/std/stream/EndianStream.endian.html /library-prerelease/std/stream/endian_stream.endian.html +/library-prerelease/std/stream/EndianStream.fixBlockBO.html /library-prerelease/std/stream/endian_stream.fix_block_bo.html +/library-prerelease/std/stream/EndianStream.fixBO.html /library-prerelease/std/stream/endian_stream.fix_bo.html +/library-prerelease/std/stream/EndianStream.html /library-prerelease/std/stream/endian_stream.html +/library-prerelease/std/stream/EndianStream.readBOM.html /library-prerelease/std/stream/endian_stream.read_bom.html +/library-prerelease/std/stream/EndianStream.this.html /library-prerelease/std/stream/endian_stream.this.html +/library-prerelease/std/stream/EndianStream.writeBOM.html /library-prerelease/std/stream/endian_stream.write_bom.html +/library-prerelease/std/stream/File.available.html /library-prerelease/std/stream/file.available.html +/library-prerelease/std/stream/File.close.html /library-prerelease/std/stream/file.close.html +/library-prerelease/std/stream/File.create.html /library-prerelease/std/stream/file.create.html +/library-prerelease/std/stream/File.html /library-prerelease/std/stream/file.html +/library-prerelease/std/stream/FileMode.Append.html /library-prerelease/std/stream/file_mode.append.html +/library-prerelease/std/stream/FileMode.html /library-prerelease/std/stream/file_mode.html +/library-prerelease/std/stream/FileMode.In.html /library-prerelease/std/stream/file_mode.in.html +/library-prerelease/std/stream/FileMode.Out.html /library-prerelease/std/stream/file_mode.out.html +/library-prerelease/std/stream/FileMode.OutNew.html /library-prerelease/std/stream/file_mode.out_new.html +/library-prerelease/std/stream/File.open.html /library-prerelease/std/stream/file.open.html +/library-prerelease/std/stream/File.this.html /library-prerelease/std/stream/file.this.html +/library-prerelease/std/stream/FilterStream.html /library-prerelease/std/stream/filter_stream.html +/library-prerelease/std/stream/FilterStream.nestClose.html /library-prerelease/std/stream/filter_stream.nest_close.html +/library-prerelease/std/stream/FilterStream.resetSource.html /library-prerelease/std/stream/filter_stream.reset_source.html +/library-prerelease/std/stream/FilterStream.source.html /library-prerelease/std/stream/filter_stream.source.html +/library-prerelease/std/stream/FilterStream.this.html /library-prerelease/std/stream/filter_stream.this.html +/library-prerelease/std/stream/InputStream.available.html /library-prerelease/std/stream/input_stream.available.html +/library-prerelease/std/stream/InputStream.eof.html /library-prerelease/std/stream/input_stream.eof.html +/library-prerelease/std/stream/InputStream.getc.html /library-prerelease/std/stream/input_stream.getc.html +/library-prerelease/std/stream/InputStream.getcw.html /library-prerelease/std/stream/input_stream.getcw.html +/library-prerelease/std/stream/InputStream.html /library-prerelease/std/stream/input_stream.html +/library-prerelease/std/stream/InputStream.isOpen.html /library-prerelease/std/stream/input_stream.is_open.html +/library-prerelease/std/stream/InputStream.opApply.html /library-prerelease/std/stream/input_stream.op_apply.html +/library-prerelease/std/stream/InputStream.readExact.html /library-prerelease/std/stream/input_stream.read_exact.html +/library-prerelease/std/stream/InputStream.readf.html /library-prerelease/std/stream/input_stream.readf.html +/library-prerelease/std/stream/InputStream.read.html /library-prerelease/std/stream/input_stream.read.html +/library-prerelease/std/stream/InputStream.readLine.html /library-prerelease/std/stream/input_stream.read_line.html +/library-prerelease/std/stream/InputStream.readLineW.html /library-prerelease/std/stream/input_stream.read_line.html +/library-prerelease/std/stream/InputStream.readString.html /library-prerelease/std/stream/input_stream.read_string.html +/library-prerelease/std/stream/InputStream.readStringW.html /library-prerelease/std/stream/input_stream.read_string.html +/library-prerelease/std/stream/InputStream.ungetc.html /library-prerelease/std/stream/input_stream.ungetc.html +/library-prerelease/std/stream/InputStream.ungetcw.html /library-prerelease/std/stream/input_stream.ungetcw.html +/library-prerelease/std/stream/InputStream.vreadf.html /library-prerelease/std/stream/input_stream.vreadf.html +/library-prerelease/std/stream/MemoryStream.html /library-prerelease/std/stream/memory_stream.html +/library-prerelease/std/stream/MemoryStream.reserve.html /library-prerelease/std/stream/memory_stream.reserve.html +/library-prerelease/std/stream/MemoryStream.this.html /library-prerelease/std/stream/memory_stream.this.html +/library-prerelease/std/stream/MmFileStream.html /library-prerelease/std/stream/mm_file_stream.html +/library-prerelease/std/stream/MmFileStream.this.html /library-prerelease/std/stream/mm_file_stream.this.html +/library-prerelease/std/stream/Object.factory.html /library-prerelease/std/stream/object.factory.html +/library-prerelease/std/stream/Object.opCmp.html /library-prerelease/std/stream/object.op_cmp.html +/library-prerelease/std/stream/Object.opEquals.html /library-prerelease/std/stream/object.op_equals.html +/library-prerelease/std/stream/Object.toHash.html /library-prerelease/std/stream/object.to_hash.html +/library-prerelease/std/stream/Object.toString.html /library-prerelease/std/stream/object.to_string.html +/library-prerelease/std/stream/OpenException.html /library-prerelease/std/stream/open_exception.html +/library-prerelease/std/stream/OpenException.this.html /library-prerelease/std/stream/open_exception.this.html +/library-prerelease/std/stream/OutputStream.close.html /library-prerelease/std/stream/output_stream.close.html +/library-prerelease/std/stream/OutputStream.flush.html /library-prerelease/std/stream/output_stream.flush.html +/library-prerelease/std/stream/OutputStream.html /library-prerelease/std/stream/output_stream.html +/library-prerelease/std/stream/OutputStream.isOpen.html /library-prerelease/std/stream/output_stream.is_open.html +/library-prerelease/std/stream/OutputStream.printf.html /library-prerelease/std/stream/output_stream.printf.html +/library-prerelease/std/stream/OutputStream.vprintf.html /library-prerelease/std/stream/output_stream.vprintf.html +/library-prerelease/std/stream/OutputStream.writeExact.html /library-prerelease/std/stream/output_stream.write_exact.html +/library-prerelease/std/stream/OutputStream.writef.html /library-prerelease/std/stream/output_stream.writef.html +/library-prerelease/std/stream/OutputStream.writefln.html /library-prerelease/std/stream/output_stream.writefln.html +/library-prerelease/std/stream/OutputStream.writefx.html /library-prerelease/std/stream/output_stream.writefx.html +/library-prerelease/std/stream/OutputStream.write.html /library-prerelease/std/stream/output_stream.write.html +/library-prerelease/std/stream/OutputStream.writeLine.html /library-prerelease/std/stream/output_stream.write_line.html +/library-prerelease/std/stream/OutputStream.writeLineW.html /library-prerelease/std/stream/output_stream.write_line.html +/library-prerelease/std/stream/OutputStream.writeString.html /library-prerelease/std/stream/output_stream.write_string.html +/library-prerelease/std/stream/OutputStream.writeStringW.html /library-prerelease/std/stream/output_stream.write_string.html +/library-prerelease/std/stream/ReadException.html /library-prerelease/std/stream/read_exception.html +/library-prerelease/std/stream/ReadException.this.html /library-prerelease/std/stream/read_exception.this.html +/library-prerelease/std/stream/SeekException.html /library-prerelease/std/stream/seek_exception.html +/library-prerelease/std/stream/SeekException.this.html /library-prerelease/std/stream/seek_exception.this.html +/library-prerelease/std/stream/SliceStream.html /library-prerelease/std/stream/slice_stream.html +/library-prerelease/std/stream/SliceStream.this.html /library-prerelease/std/stream/slice_stream.this.html +/library-prerelease/std/stream/Stream.copyFrom.html /library-prerelease/std/stream/stream.copy_from.html +/library-prerelease/std/stream/StreamException.html /library-prerelease/std/stream/stream_exception.html +/library-prerelease/std/stream/StreamException.this.html /library-prerelease/std/stream/stream_exception.this.html +/library-prerelease/std/stream/StreamFileException.html /library-prerelease/std/stream/stream_file_exception.html +/library-prerelease/std/stream/StreamFileException.this.html /library-prerelease/std/stream/stream_file_exception.this.html +/library-prerelease/std/stream/Stream.html /library-prerelease/std/stream/stream.html +/library-prerelease/std/stream/Stream.isopen.html /library-prerelease/std/stream/stream.isopen.html +/library-prerelease/std/stream/Stream.position.html /library-prerelease/std/stream/stream.position.html +/library-prerelease/std/stream/Stream.prevCr.html /library-prerelease/std/stream/stream.prev_cr.html +/library-prerelease/std/stream/Stream.readable.html /library-prerelease/std/stream/stream.readable.html +/library-prerelease/std/stream/Stream.readBlock.html /library-prerelease/std/stream/stream.read_block.html +/library-prerelease/std/stream/Stream.readEOF.html /library-prerelease/std/stream/stream.read_eof.html +/library-prerelease/std/stream/Stream.seekable.html /library-prerelease/std/stream/stream.seekable.html +/library-prerelease/std/stream/Stream.seekCur.html /library-prerelease/std/stream/stream.seek_cur.html +/library-prerelease/std/stream/Stream.seekEnd.html /library-prerelease/std/stream/stream.seek_end.html +/library-prerelease/std/stream/Stream.seek.html /library-prerelease/std/stream/stream.seek.html +/library-prerelease/std/stream/Stream.seekSet.html /library-prerelease/std/stream/stream.seek_set.html +/library-prerelease/std/stream/Stream.size.html /library-prerelease/std/stream/stream.size.html +/library-prerelease/std/stream/Stream.toHash.html /library-prerelease/std/stream/stream.to_hash.html +/library-prerelease/std/stream/Stream.toString.html /library-prerelease/std/stream/stream.to_string.html +/library-prerelease/std/stream/Stream.writeable.html /library-prerelease/std/stream/stream.writeable.html +/library-prerelease/std/stream/Stream.writeBlock.html /library-prerelease/std/stream/stream.write_block.html +/library-prerelease/std/stream/TArrayStream.data.html /library-prerelease/std/stream/t_array_stream.data.html +/library-prerelease/std/stream/TArrayStream.html /library-prerelease/std/stream/t_array_stream.html +/library-prerelease/std/stream/TArrayStream.this.html /library-prerelease/std/stream/t_array_stream.this.html +/library-prerelease/std/stream/Throwable.file.html /library-prerelease/std/stream/throwable.file.html +/library-prerelease/std/stream/Throwable.info.html /library-prerelease/std/stream/throwable.info.html +/library-prerelease/std/stream/Throwable.line.html /library-prerelease/std/stream/throwable.line.html +/library-prerelease/std/stream/Throwable.msg.html /library-prerelease/std/stream/throwable.msg.html +/library-prerelease/std/stream/Throwable.next.html /library-prerelease/std/stream/throwable.next.html +/library-prerelease/std/stream/Throwable.toString.html /library-prerelease/std/stream/throwable.to_string.html +/library-prerelease/std/stream/WriteException.html /library-prerelease/std/stream/write_exception.html +/library-prerelease/std/stream/WriteException.this.html /library-prerelease/std/stream/write_exception.this.html +/library-prerelease/std/string/assumeUTF.html /library-prerelease/std/string/assume_utf.html +/library-prerelease/std/string/CaseSensitive.html /library-prerelease/std/string/case_sensitive.html +/library-prerelease/std/string/chompPrefix.html /library-prerelease/std/string/chomp_prefix.html +/library-prerelease/std/string/fromStringz.html /library-prerelease/std/string/from_stringz.html +/library-prerelease/std/string/indexOfAny.html /library-prerelease/std/string/index_of_any.html +/library-prerelease/std/string/indexOf.html /library-prerelease/std/string/index_of.html +/library-prerelease/std/string/indexOfNeither.html /library-prerelease/std/string/index_of_neither.html +/library-prerelease/std/string/inPattern.html /library-prerelease/std/string/in_pattern.html +/library-prerelease/std/string/isNumeric.html /library-prerelease/std/string/is_numeric.html +/library-prerelease/std/string/KeepTerminator.html /library-prerelease/std/string/keep_terminator.html +/library-prerelease/std/string/lastIndexOfAny.html /library-prerelease/std/string/last_index_of_any.html +/library-prerelease/std/string/lastIndexOf.html /library-prerelease/std/string/last_index_of.html +/library-prerelease/std/string/lastIndexOfNeither.html /library-prerelease/std/string/last_index_of_neither.html +/library-prerelease/std/string/leftJustify.html /library-prerelease/std/string/left_justify.html +/library-prerelease/std/string/lineSplitter.html /library-prerelease/std/string/line_splitter.html +/library-prerelease/std/string/makeTrans.html /library-prerelease/std/string/make_trans.html +/library-prerelease/std/string/Object.factory.html /library-prerelease/std/string/object.factory.html +/library-prerelease/std/string/Object.opCmp.html /library-prerelease/std/string/object.op_cmp.html +/library-prerelease/std/string/Object.opEquals.html /library-prerelease/std/string/object.op_equals.html +/library-prerelease/std/string/Object.toHash.html /library-prerelease/std/string/object.to_hash.html +/library-prerelease/std/string/rightJustify.html /library-prerelease/std/string/right_justify.html +/library-prerelease/std/string/splitLines.html /library-prerelease/std/string/split_lines.html +/library-prerelease/std/string/StringException.html /library-prerelease/std/string/string_exception.html +/library-prerelease/std/string/StringException.this.html /library-prerelease/std/string/string_exception.this.html +/library-prerelease/std/string/stripLeft.html /library-prerelease/std/string/strip_left.html +/library-prerelease/std/string/stripRight.html /library-prerelease/std/string/strip_right.html +/library-prerelease/std/string/Throwable.file.html /library-prerelease/std/string/throwable.file.html +/library-prerelease/std/string/Throwable.info.html /library-prerelease/std/string/throwable.info.html +/library-prerelease/std/string/Throwable.line.html /library-prerelease/std/string/throwable.line.html +/library-prerelease/std/string/Throwable.msg.html /library-prerelease/std/string/throwable.msg.html +/library-prerelease/std/string/Throwable.next.html /library-prerelease/std/string/throwable.next.html +/library-prerelease/std/string/Throwable.toString.html /library-prerelease/std/string/throwable.to_string.html +/library-prerelease/std/string/toStringz.html /library-prerelease/std/string/to_stringz.html +/library-prerelease/std/system/Endian.bigEndian.html /library-prerelease/std/system/endian.big_endian.html +/library-prerelease/std/system/Endian.html /library-prerelease/std/system/endian.html +/library-prerelease/std/system/Endian.littleEndian.html /library-prerelease/std/system/endian.little_endian.html +/library-prerelease/std/system/OS.android.html /library-prerelease/std/system/os.android.html +/library-prerelease/std/system/OS.freeBSD.html /library-prerelease/std/system/os.free_bsd.html +/library-prerelease/std/system/OS.html /library-prerelease/std/system/os.html +/library-prerelease/std/system/OS.linux.html /library-prerelease/std/system/os.linux.html +/library-prerelease/std/system/OS.osx.html /library-prerelease/std/system/os.osx.html +/library-prerelease/std/system/OS.otherPosix.html /library-prerelease/std/system/os.other_posix.html +/library-prerelease/std/system/OS.solaris.html /library-prerelease/std/system/os.solaris.html +/library-prerelease/std/system/OS.win32.html /library-prerelease/std/system/os.win32.html +/library-prerelease/std/system/OS.win64.html /library-prerelease/std/system/os.win64.html +/library-prerelease/std/traits/areAllSafe.html /library-prerelease/std/traits/are_all_safe.html +/library-prerelease/std/traits/BaseClassesTuple.html /library-prerelease/std/traits/base_classes_tuple.html +/library-prerelease/std/traits/BaseTypeTuple.html /library-prerelease/std/traits/base_type_tuple.html +/library-prerelease/std/traits/classInstanceAlignment.html /library-prerelease/std/traits/class_instance_alignment.html +/library-prerelease/std/traits/CommonType.html /library-prerelease/std/traits/common_type.html +/library-prerelease/std/traits/EnumMembers.html /library-prerelease/std/traits/enum_members.html +/library-prerelease/std/traits/FieldNameTuple.html /library-prerelease/std/traits/field_name_tuple.html +/library-prerelease/std/traits/FieldTypeTuple.html /library-prerelease/std/traits/field_type_tuple.html +/library-prerelease/std/traits/ForeachType.html /library-prerelease/std/traits/foreach_type.html +/library-prerelease/std/traits/fullyQualifiedName.html /library-prerelease/std/traits/fully_qualified_name.html +/library-prerelease/std/traits/FunctionAttribute.const_.html /library-prerelease/std/traits/function_attribute.const_.html +/library-prerelease/std/traits/FunctionAttribute.html /library-prerelease/std/traits/function_attribute.html +/library-prerelease/std/traits/FunctionAttribute.immutable_.html /library-prerelease/std/traits/function_attribute.immutable_.html +/library-prerelease/std/traits/FunctionAttribute.inout_.html /library-prerelease/std/traits/function_attribute.inout_.html +/library-prerelease/std/traits/FunctionAttribute.nogc.html /library-prerelease/std/traits/function_attribute.nogc.html +/library-prerelease/std/traits/FunctionAttribute.none.html /library-prerelease/std/traits/function_attribute.none.html +/library-prerelease/std/traits/FunctionAttribute.nothrow_.html /library-prerelease/std/traits/function_attribute.nothrow_.html +/library-prerelease/std/traits/FunctionAttribute.property.html /library-prerelease/std/traits/function_attribute.property.html +/library-prerelease/std/traits/FunctionAttribute.pure_.html /library-prerelease/std/traits/function_attribute.pure_.html +/library-prerelease/std/traits/FunctionAttribute.ref_.html /library-prerelease/std/traits/function_attribute.ref_.html +/library-prerelease/std/traits/FunctionAttribute.return_.html /library-prerelease/std/traits/function_attribute.return_.html +/library-prerelease/std/traits/FunctionAttribute.safe.html /library-prerelease/std/traits/function_attribute.safe.html +/library-prerelease/std/traits/FunctionAttribute.shared_.html /library-prerelease/std/traits/function_attribute.shared_.html +/library-prerelease/std/traits/functionAttributes.html /library-prerelease/std/traits/function_attributes.html +/library-prerelease/std/traits/FunctionAttribute.system.html /library-prerelease/std/traits/function_attribute.system.html +/library-prerelease/std/traits/FunctionAttribute.trusted.html /library-prerelease/std/traits/function_attribute.trusted.html +/library-prerelease/std/traits/functionLinkage.html /library-prerelease/std/traits/function_linkage.html +/library-prerelease/std/traits/FunctionTypeOf.html /library-prerelease/std/traits/function_type_of.html +/library-prerelease/std/traits/hasAliasing.html /library-prerelease/std/traits/has_aliasing.html +/library-prerelease/std/traits/hasElaborateAssign.html /library-prerelease/std/traits/has_elaborate_assign.html +/library-prerelease/std/traits/hasElaborateCopyConstructor.html /library-prerelease/std/traits/has_elaborate_copy_constructor.html +/library-prerelease/std/traits/hasElaborateDestructor.html /library-prerelease/std/traits/has_elaborate_destructor.html +/library-prerelease/std/traits/hasIndirections.html /library-prerelease/std/traits/has_indirections.html +/library-prerelease/std/traits/hasMember.html /library-prerelease/std/traits/has_member.html +/library-prerelease/std/traits/hasNested.html /library-prerelease/std/traits/has_nested.html +/library-prerelease/std/traits/hasUnsharedAliasing.html /library-prerelease/std/traits/has_unshared_aliasing.html +/library-prerelease/std/traits/ImplicitConversionTargets.html /library-prerelease/std/traits/implicit_conversion_targets.html +/library-prerelease/std/traits/InterfacesTuple.html /library-prerelease/std/traits/interfaces_tuple.html +/library-prerelease/std/traits/isAbstractClass.html /library-prerelease/std/traits/is_abstract_class.html +/library-prerelease/std/traits/isAbstractFunction.html /library-prerelease/std/traits/is_abstract_function.html +/library-prerelease/std/traits/isAggregateType.html /library-prerelease/std/traits/is_aggregate_type.html +/library-prerelease/std/traits/isArray.html /library-prerelease/std/traits/is_array.html +/library-prerelease/std/traits/isAssignable.html /library-prerelease/std/traits/is_assignable.html +/library-prerelease/std/traits/isAssociativeArray.html /library-prerelease/std/traits/is_associative_array.html +/library-prerelease/std/traits/isBasicType.html /library-prerelease/std/traits/is_basic_type.html +/library-prerelease/std/traits/isBoolean.html /library-prerelease/std/traits/is_boolean.html +/library-prerelease/std/traits/isBuiltinType.html /library-prerelease/std/traits/is_builtin_type.html +/library-prerelease/std/traits/isCallable.html /library-prerelease/std/traits/is_callable.html +/library-prerelease/std/traits/isCovariantWith.html /library-prerelease/std/traits/is_covariant_with.html +/library-prerelease/std/traits/isDelegate.html /library-prerelease/std/traits/is_delegate.html +/library-prerelease/std/traits/isDynamicArray.html /library-prerelease/std/traits/is_dynamic_array.html +/library-prerelease/std/traits/isExpressionTuple.html /library-prerelease/std/traits/is_expression_tuple.html +/library-prerelease/std/traits/isFinalClass.html /library-prerelease/std/traits/is_final_class.html +/library-prerelease/std/traits/isFinalFunction.html /library-prerelease/std/traits/is_final_function.html +/library-prerelease/std/traits/isFloatingPoint.html /library-prerelease/std/traits/is_floating_point.html +/library-prerelease/std/traits/isFunctionPointer.html /library-prerelease/std/traits/is_function_pointer.html +/library-prerelease/std/traits/isImplicitlyConvertible.html /library-prerelease/std/traits/is_implicitly_convertible.html +/library-prerelease/std/traits/isInstanceOf.html /library-prerelease/std/traits/is_instance_of.html +/library-prerelease/std/traits/isIntegral.html /library-prerelease/std/traits/is_integral.html +/library-prerelease/std/traits/isIterable.html /library-prerelease/std/traits/is_iterable.html +/library-prerelease/std/traits/isMutable.html /library-prerelease/std/traits/is_mutable.html +/library-prerelease/std/traits/isNestedFunction.html /library-prerelease/std/traits/is_nested_function.html +/library-prerelease/std/traits/isNested.html /library-prerelease/std/traits/is_nested.html +/library-prerelease/std/traits/isNumeric.html /library-prerelease/std/traits/is_numeric.html +/library-prerelease/std/traits/isPointer.html /library-prerelease/std/traits/is_pointer.html +/library-prerelease/std/traits/isSafe.html /library-prerelease/std/traits/is_safe.html +/library-prerelease/std/traits/isScalarType.html /library-prerelease/std/traits/is_scalar_type.html +/library-prerelease/std/traits/isSigned.html /library-prerelease/std/traits/is_signed.html +/library-prerelease/std/traits/isSIMDVector.html /library-prerelease/std/traits/is_simd_vector.html +/library-prerelease/std/traits/isSomeChar.html /library-prerelease/std/traits/is_some_char.html +/library-prerelease/std/traits/isSomeFunction.html /library-prerelease/std/traits/is_some_function.html +/library-prerelease/std/traits/isSomeString.html /library-prerelease/std/traits/is_some_string.html +/library-prerelease/std/traits/isStaticArray.html /library-prerelease/std/traits/is_static_array.html +/library-prerelease/std/traits/isTypeTuple.html /library-prerelease/std/traits/is_type_tuple.html +/library-prerelease/std/traits/isUnsafe.html /library-prerelease/std/traits/is_unsafe.html +/library-prerelease/std/traits/isUnsigned.html /library-prerelease/std/traits/is_unsigned.html +/library-prerelease/std/traits/KeyType.html /library-prerelease/std/traits/key_type.html +/library-prerelease/std/traits/Largest.html /library-prerelease/std/traits/largest.html +/library-prerelease/std/traits/lvalueOf.html /library-prerelease/std/traits/lvalue_of.html +/library-prerelease/std/traits/mangledName.html /library-prerelease/std/traits/mangled_name.html +/library-prerelease/std/traits/MemberFunctionsTuple.html /library-prerelease/std/traits/member_functions_tuple.html +/library-prerelease/std/traits/moduleName.html /library-prerelease/std/traits/module_name.html +/library-prerelease/std/traits/mostNegative.html /library-prerelease/std/traits/most_negative.html +/library-prerelease/std/traits/OriginalType.html /library-prerelease/std/traits/original_type.html +/library-prerelease/std/traits/packageName.html /library-prerelease/std/traits/package_name.html +/library-prerelease/std/traits/ParameterDefaultValueTuple.html /library-prerelease/std/traits/parameter_default_value_tuple.html +/library-prerelease/std/traits/ParameterIdentifierTuple.html /library-prerelease/std/traits/parameter_identifier_tuple.html +/library-prerelease/std/traits/ParameterStorageClass.html /library-prerelease/std/traits/parameter_storage_class.html +/library-prerelease/std/traits/ParameterStorageClass.lazy_.html /library-prerelease/std/traits/parameter_storage_class.lazy_.html +/library-prerelease/std/traits/ParameterStorageClass.none.html /library-prerelease/std/traits/parameter_storage_class.none.html +/library-prerelease/std/traits/ParameterStorageClass.out_.html /library-prerelease/std/traits/parameter_storage_class.out_.html +/library-prerelease/std/traits/ParameterStorageClass.ref_.html /library-prerelease/std/traits/parameter_storage_class.ref_.html +/library-prerelease/std/traits/ParameterStorageClass.return_.html /library-prerelease/std/traits/parameter_storage_class.return_.html +/library-prerelease/std/traits/ParameterStorageClass.scope_.html /library-prerelease/std/traits/parameter_storage_class.scope_.html +/library-prerelease/std/traits/ParameterStorageClassTuple.html /library-prerelease/std/traits/parameter_storage_class_tuple.html +/library-prerelease/std/traits/ParameterTypeTuple.html /library-prerelease/std/traits/parameter_type_tuple.html +/library-prerelease/std/traits/pointerTarget.html /library-prerelease/std/traits/pointer_target.html +/library-prerelease/std/traits/PointerTarget.html /library-prerelease/std/traits/pointer_target.html +/library-prerelease/std/traits/RepresentationTypeTuple.html /library-prerelease/std/traits/representation_type_tuple.html +/library-prerelease/std/traits/ReturnType.html /library-prerelease/std/traits/return_type.html +/library-prerelease/std/traits/rvalueOf.html /library-prerelease/std/traits/rvalue_of.html +/library-prerelease/std/traits/Select.html /library-prerelease/std/traits/select.html +/library-prerelease/std/traits/SetFunctionAttributes.html /library-prerelease/std/traits/set_function_attributes.html +/library-prerelease/std/traits/Signed.html /library-prerelease/std/traits/signed.html +/library-prerelease/std/traits/TemplateArgsOf.html /library-prerelease/std/traits/template_args_of.html +/library-prerelease/std/traits/TemplateOf.html /library-prerelease/std/traits/template_of.html +/library-prerelease/std/traits/TransitiveBaseTypeTuple.html /library-prerelease/std/traits/transitive_base_type_tuple.html +/library-prerelease/std/traits/Unqual.html /library-prerelease/std/traits/unqual.html +/library-prerelease/std/traits/Unsigned.html /library-prerelease/std/traits/unsigned.html +/library-prerelease/std/traits/ValueType.html /library-prerelease/std/traits/value_type.html +/library-prerelease/std/traits/Variadic.c.html /library-prerelease/std/traits/variadic.c.html +/library-prerelease/std/traits/Variadic.d.html /library-prerelease/std/traits/variadic.d.html +/library-prerelease/std/traits/variadicFunctionStyle.html /library-prerelease/std/traits/variadic_function_style.html +/library-prerelease/std/traits/Variadic.html /library-prerelease/std/traits/variadic.html +/library-prerelease/std/traits/Variadic.no.html /library-prerelease/std/traits/variadic.no.html +/library-prerelease/std/traits/Variadic.typesafe.html /library-prerelease/std/traits/variadic.typesafe.html +/library-prerelease/std/typecons/alignForSize.html /library-prerelease/std/typecons/align_for_size.html +/library-prerelease/std/typecons/AutoImplement.html /library-prerelease/std/typecons/auto_implement.html +/library-prerelease/std/typecons/BitFlags.html /library-prerelease/std/typecons/bit_flags.html +/library-prerelease/std/typecons/BlackHole.html /library-prerelease/std/typecons/black_hole.html +/library-prerelease/std/typecons/Flag.html /library-prerelease/std/typecons/flag.html +/library-prerelease/std/typecons/Flag.no.html /library-prerelease/std/typecons/flag.no.html +/library-prerelease/std/typecons/Flag.yes.html /library-prerelease/std/typecons/flag.yes.html +/library-prerelease/std/typecons/generateAssertTrap.html /library-prerelease/std/typecons/generate_assert_trap.html +/library-prerelease/std/typecons/generateEmptyFunction.html /library-prerelease/std/typecons/generate_empty_function.html +/library-prerelease/std/typecons/isBitFlagEnum.html /library-prerelease/std/typecons/is_bit_flag_enum.html +/library-prerelease/std/typecons/isTuple.html /library-prerelease/std/typecons/is_tuple.html +/library-prerelease/std/typecons/No.html /library-prerelease/std/typecons/no.html +/library-prerelease/std/typecons/Nullable.get.html /library-prerelease/std/typecons/nullable.get.html +/library-prerelease/std/typecons/Nullable.html /library-prerelease/std/typecons/nullable.html +/library-prerelease/std/typecons/Nullable.isNull.html /library-prerelease/std/typecons/nullable.is_null.html +/library-prerelease/std/typecons/Nullable.nullify.html /library-prerelease/std/typecons/nullable.nullify.html +/library-prerelease/std/typecons/Nullable.nullify.nullify.html /library-prerelease/std/typecons/nullable.nullify.nullify.html +/library-prerelease/std/typecons/Nullable.opAssign.html /library-prerelease/std/typecons/nullable.op_assign.html +/library-prerelease/std/typecons/Nullable.opAssign.opAssign.html /library-prerelease/std/typecons/nullable.op_assign.op_assign.html +/library-prerelease/std/typecons/NullableRef.bind.html /library-prerelease/std/typecons/nullable_ref.bind.html +/library-prerelease/std/typecons/NullableRef.get.html /library-prerelease/std/typecons/nullable_ref.get.html +/library-prerelease/std/typecons/NullableRef.html /library-prerelease/std/typecons/nullable_ref.html +/library-prerelease/std/typecons/NullableRef.isNull.html /library-prerelease/std/typecons/nullable_ref.is_null.html +/library-prerelease/std/typecons/NullableRef.nullify.html /library-prerelease/std/typecons/nullable_ref.nullify.html +/library-prerelease/std/typecons/NullableRef.opAssign.html /library-prerelease/std/typecons/nullable_ref.op_assign.html +/library-prerelease/std/typecons/NullableRef.opAssign.opAssign.html /library-prerelease/std/typecons/nullable_ref.op_assign.op_assign.html +/library-prerelease/std/typecons/NullableRef.this.html /library-prerelease/std/typecons/nullable_ref.this.html +/library-prerelease/std/typecons/Nullable.this.html /library-prerelease/std/typecons/nullable.this.html +/library-prerelease/std/typecons/Object.factory.html /library-prerelease/std/typecons/object.factory.html +/library-prerelease/std/typecons/Object.opCmp.html /library-prerelease/std/typecons/object.op_cmp.html +/library-prerelease/std/typecons/Object.opEquals.html /library-prerelease/std/typecons/object.op_equals.html +/library-prerelease/std/typecons/Object.toHash.html /library-prerelease/std/typecons/object.to_hash.html +/library-prerelease/std/typecons/Object.toString.html /library-prerelease/std/typecons/object.to_string.html +/library-prerelease/std/typecons/Proxy.html /library-prerelease/std/typecons/proxy.html +/library-prerelease/std/typecons/Rebindable.html /library-prerelease/std/typecons/rebindable.html +/library-prerelease/std/typecons/RefCountedAutoInitialize.html /library-prerelease/std/typecons/ref_counted_auto_initialize.html +/library-prerelease/std/typecons/RefCountedAutoInitialize.no.html /library-prerelease/std/typecons/ref_counted_auto_initialize.no.html +/library-prerelease/std/typecons/RefCountedAutoInitialize.yes.html /library-prerelease/std/typecons/ref_counted_auto_initialize.yes.html +/library-prerelease/std/typecons/RefCounted.html /library-prerelease/std/typecons/ref_counted.html +/library-prerelease/std/typecons/RefCounted.opAssign.html /library-prerelease/std/typecons/ref_counted.op_assign.html +/library-prerelease/std/typecons/RefCounted.refCountedPayload.html /library-prerelease/std/typecons/ref_counted.ref_counted_payload.html +/library-prerelease/std/typecons/RefCounted.RefCountedStore.ensureInitialized.html /library-prerelease/std/typecons/ref_counted.ref_counted_store.ensure_initialized.html +/library-prerelease/std/typecons/RefCounted.refCountedStore.html /library-prerelease/std/typecons/ref_counted.ref_counted_store.html +/library-prerelease/std/typecons/RefCounted.RefCountedStore.html /library-prerelease/std/typecons/ref_counted.ref_counted_store.html +/library-prerelease/std/typecons/RefCounted.RefCountedStore.isInitialized.html /library-prerelease/std/typecons/ref_counted.ref_counted_store.is_initialized.html +/library-prerelease/std/typecons/RefCounted.RefCountedStore.refCount.html /library-prerelease/std/typecons/ref_counted.ref_counted_store.ref_count.html +/library-prerelease/std/typecons/RefCounted.this.html /library-prerelease/std/typecons/ref_counted.this.html +/library-prerelease/std/typecons/RefCounted.this.this.html /library-prerelease/std/typecons/ref_counted.this.this.html +/library-prerelease/std/typecons/Tuple.expand.html /library-prerelease/std/typecons/tuple.expand.html +/library-prerelease/std/typecons/Tuple.fieldNames.html /library-prerelease/std/typecons/tuple.field_names.html +/library-prerelease/std/typecons/Tuple.html /library-prerelease/std/typecons/tuple.html +/library-prerelease/std/typecons/Tuple.opAssign.html /library-prerelease/std/typecons/tuple.op_assign.html +/library-prerelease/std/typecons/Tuple.opAssign.opAssign.html /library-prerelease/std/typecons/tuple.op_assign.op_assign.html +/library-prerelease/std/typecons/Tuple.opCmp.html /library-prerelease/std/typecons/tuple.op_cmp.html +/library-prerelease/std/typecons/Tuple.opCmp.opCmp.html /library-prerelease/std/typecons/tuple.op_cmp.op_cmp.html +/library-prerelease/std/typecons/Tuple.opEquals.html /library-prerelease/std/typecons/tuple.op_equals.html +/library-prerelease/std/typecons/Tuple.opEquals.opEquals.html /library-prerelease/std/typecons/tuple.op_equals.op_equals.html +/library-prerelease/std/typecons/Tuple.slice.html /library-prerelease/std/typecons/tuple.slice.html +/library-prerelease/std/typecons/Tuple.slice.slice.html /library-prerelease/std/typecons/tuple.slice.slice.html +/library-prerelease/std/typecons/Tuple.this.html /library-prerelease/std/typecons/tuple.this.html +/library-prerelease/std/typecons/Tuple.this.this.html /library-prerelease/std/typecons/tuple.this.this.html +/library-prerelease/std/typecons/Tuple.toHash.html /library-prerelease/std/typecons/tuple.to_hash.html +/library-prerelease/std/typecons/Tuple.toString.html /library-prerelease/std/typecons/tuple.to_string.html +/library-prerelease/std/typecons/Tuple.toString.toString.html /library-prerelease/std/typecons/tuple.to_string.to_string.html +/library-prerelease/std/typecons/Tuple.Types.html /library-prerelease/std/typecons/tuple.types.html +/library-prerelease/std/typecons/Typedef.html /library-prerelease/std/typecons/typedef.html +/library-prerelease/std/typecons/TypedefType.html /library-prerelease/std/typecons/typedef_type.html +/library-prerelease/std/typecons/Unique.html /library-prerelease/std/typecons/unique.html +/library-prerelease/std/typecons/Unique.isEmpty.html /library-prerelease/std/typecons/unique.is_empty.html +/library-prerelease/std/typecons/Unique.opAssign.html /library-prerelease/std/typecons/unique.op_assign.html +/library-prerelease/std/typecons/Unique.opAssign.opAssign.html /library-prerelease/std/typecons/unique.op_assign.op_assign.html +/library-prerelease/std/typecons/Unique.opDot.html /library-prerelease/std/typecons/unique.op_dot.html +/library-prerelease/std/typecons/Unique.release.html /library-prerelease/std/typecons/unique.release.html +/library-prerelease/std/typecons/Unique.this.html /library-prerelease/std/typecons/unique.this.html +/library-prerelease/std/typecons/Unique.this.this.html /library-prerelease/std/typecons/unique.this.this.html +/library-prerelease/std/typecons/UnqualRef.html /library-prerelease/std/typecons/unqual_ref.html +/library-prerelease/std/typecons/WhiteHole.html /library-prerelease/std/typecons/white_hole.html +/library-prerelease/std/typecons/Yes.html /library-prerelease/std/typecons/yes.html +/library-prerelease/std/typetuple/allSatisfy.html /library-prerelease/std/typetuple/all_satisfy.html +/library-prerelease/std/typetuple/anySatisfy.html /library-prerelease/std/typetuple/any_satisfy.html +/library-prerelease/std/typetuple/DerivedToFront.html /library-prerelease/std/typetuple/derived_to_front.html +/library-prerelease/std/typetuple/EraseAll.html /library-prerelease/std/typetuple/erase_all.html +/library-prerelease/std/typetuple/Erase.html /library-prerelease/std/typetuple/erase.html +/library-prerelease/std/typetuple/Filter.html /library-prerelease/std/typetuple/filter.html +/library-prerelease/std/typetuple/IndexOf.html /library-prerelease/std/typetuple/index_of.html +/library-prerelease/std/typetuple/MostDerived.html /library-prerelease/std/typetuple/most_derived.html +/library-prerelease/std/typetuple/NoDuplicates.html /library-prerelease/std/typetuple/no_duplicates.html +/library-prerelease/std/typetuple/ReplaceAll.html /library-prerelease/std/typetuple/replace_all.html +/library-prerelease/std/typetuple/Replace.html /library-prerelease/std/typetuple/replace.html +/library-prerelease/std/typetuple/Reverse.html /library-prerelease/std/typetuple/reverse.html +/library-prerelease/std/typetuple/staticIndexOf.html /library-prerelease/std/typetuple/static_index_of.html +/library-prerelease/std/typetuple/staticMap.html /library-prerelease/std/typetuple/static_map.html +/library-prerelease/std/typetuple/templateAnd.html /library-prerelease/std/typetuple/template_and.html +/library-prerelease/std/typetuple/templateNot.html /library-prerelease/std/typetuple/template_not.html +/library-prerelease/std/typetuple/templateNot.templateNot.html /library-prerelease/std/typetuple/template_not.template_not.html +/library-prerelease/std/typetuple/templateOr.html /library-prerelease/std/typetuple/template_or.html +/library-prerelease/std/typetuple/TypeTuple.html /library-prerelease/std/typetuple/type_tuple.html +/library-prerelease/std/uni/allowedIn.html /library-prerelease/std/uni/allowed_in.html +/library-prerelease/std/uni/byCodePoint.html /library-prerelease/std/uni/by_code_point.html +/library-prerelease/std/uni/byGrapheme.html /library-prerelease/std/uni/by_grapheme.html +/library-prerelease/std/uni/CodepointInterval.html /library-prerelease/std/uni/codepoint_interval.html +/library-prerelease/std/uni/CodepointSet.html /library-prerelease/std/uni/codepoint_set.html +/library-prerelease/std/uni/codepointSetTrie.codepointSetTrie.html /library-prerelease/std/uni/codepoint_set_trie.codepoint_set_trie.html +/library-prerelease/std/uni/codepointSetTrie.html /library-prerelease/std/uni/codepoint_set_trie.html +/library-prerelease/std/uni/CodepointSetTrie.html /library-prerelease/std/uni/codepoint_set_trie.html +/library-prerelease/std/uni/codepointTrie.codepointTrie.html /library-prerelease/std/uni/codepoint_trie.codepoint_trie.html +/library-prerelease/std/uni/codepointTrie.html /library-prerelease/std/uni/codepoint_trie.html +/library-prerelease/std/uni/CodepointTrie.html /library-prerelease/std/uni/codepoint_trie.html +/library-prerelease/std/uni/combiningClass.html /library-prerelease/std/uni/combining_class.html +/library-prerelease/std/uni/composeJamo.html /library-prerelease/std/uni/compose_jamo.html +/library-prerelease/std/uni/decodeGrapheme.html /library-prerelease/std/uni/decode_grapheme.html +/library-prerelease/std/uni/decomposeHangul.html /library-prerelease/std/uni/decompose_hangul.html +/library-prerelease/std/uni/Grapheme.html /library-prerelease/std/uni/grapheme.html +/library-prerelease/std/uni/Grapheme.length.html /library-prerelease/std/uni/grapheme.length.html +/library-prerelease/std/uni/Grapheme.opIndexAssign.html /library-prerelease/std/uni/grapheme.op_index_assign.html +/library-prerelease/std/uni/Grapheme.opIndex.html /library-prerelease/std/uni/grapheme.op_index.html +/library-prerelease/std/uni/Grapheme.opOpAssign.html /library-prerelease/std/uni/grapheme.op_op_assign.html +/library-prerelease/std/uni/Grapheme.opSlice.html /library-prerelease/std/uni/grapheme.op_slice.html +/library-prerelease/std/uni/graphemeStride.html /library-prerelease/std/uni/grapheme_stride.html +/library-prerelease/std/uni/Grapheme.valid.html /library-prerelease/std/uni/grapheme.valid.html +/library-prerelease/std/uni/InversionList.add.add.html /library-prerelease/std/uni/inversion_list.add.add.html +/library-prerelease/std/uni/InversionList.add.html /library-prerelease/std/uni/inversion_list.add.html +/library-prerelease/std/uni/InversionList.byCodepoint.html /library-prerelease/std/uni/inversion_list.by_codepoint.html +/library-prerelease/std/uni/InversionList.byInterval.html /library-prerelease/std/uni/inversion_list.by_interval.html +/library-prerelease/std/uni/InversionList.empty.html /library-prerelease/std/uni/inversion_list.empty.html +/library-prerelease/std/uni/InversionList.html /library-prerelease/std/uni/inversion_list.html +/library-prerelease/std/uni/InversionList.inverted.html /library-prerelease/std/uni/inversion_list.inverted.html +/library-prerelease/std/uni/InversionList.length.html /library-prerelease/std/uni/inversion_list.length.html +/library-prerelease/std/uni/InversionList.opBinary.html /library-prerelease/std/uni/inversion_list.op_binary.html +/library-prerelease/std/uni/InversionList.opBinary.opBinary.html /library-prerelease/std/uni/inversion_list.op_binary.op_binary.html +/library-prerelease/std/uni/InversionList.opBinaryRight.html /library-prerelease/std/uni/inversion_list.op_binary_right.html +/library-prerelease/std/uni/InversionList.opBinaryRight.opBinaryRight.html /library-prerelease/std/uni/inversion_list.op_binary_right.op_binary_right.html +/library-prerelease/std/uni/InversionList.opIndex.html /library-prerelease/std/uni/inversion_list.op_index.html +/library-prerelease/std/uni/InversionList.opOpAssign.html /library-prerelease/std/uni/inversion_list.op_op_assign.html +/library-prerelease/std/uni/InversionList.opOpAssign.opOpAssign.html /library-prerelease/std/uni/inversion_list.op_op_assign.op_op_assign.html +/library-prerelease/std/uni/InversionList.opUnary.html /library-prerelease/std/uni/inversion_list.op_unary.html +/library-prerelease/std/uni/InversionList.opUnary.opUnary.html /library-prerelease/std/uni/inversion_list.op_unary.op_unary.html +/library-prerelease/std/uni/InversionList.this.html /library-prerelease/std/uni/inversion_list.this.html +/library-prerelease/std/uni/InversionList.this.this.html /library-prerelease/std/uni/inversion_list.this.this.html +/library-prerelease/std/uni/InversionList.toSourceCode.html /library-prerelease/std/uni/inversion_list.to_source_code.html +/library-prerelease/std/uni/InversionList.toString.html /library-prerelease/std/uni/inversion_list.to_string.html +/library-prerelease/std/uni/isAlpha.html /library-prerelease/std/uni/is_alpha.html +/library-prerelease/std/uni/isCodepointSet.html /library-prerelease/std/uni/is_codepoint_set.html +/library-prerelease/std/uni/isControl.html /library-prerelease/std/uni/is_control.html +/library-prerelease/std/uni/isFormat.html /library-prerelease/std/uni/is_format.html +/library-prerelease/std/uni/isGraphical.html /library-prerelease/std/uni/is_graphical.html +/library-prerelease/std/uni/isIntegralPair.html /library-prerelease/std/uni/is_integral_pair.html +/library-prerelease/std/uni/isLower.html /library-prerelease/std/uni/is_lower.html +/library-prerelease/std/uni/isMark.html /library-prerelease/std/uni/is_mark.html +/library-prerelease/std/uni/isNonCharacter.html /library-prerelease/std/uni/is_non_character.html +/library-prerelease/std/uni/isNumber.html /library-prerelease/std/uni/is_number.html +/library-prerelease/std/uni/isPrivateUse.html /library-prerelease/std/uni/is_private_use.html +/library-prerelease/std/uni/isPunctuation.html /library-prerelease/std/uni/is_punctuation.html +/library-prerelease/std/uni/isSpace.html /library-prerelease/std/uni/is_space.html +/library-prerelease/std/uni/isSurrogateHi.html /library-prerelease/std/uni/is_surrogate_hi.html +/library-prerelease/std/uni/isSurrogate.html /library-prerelease/std/uni/is_surrogate.html +/library-prerelease/std/uni/isSurrogateLo.html /library-prerelease/std/uni/is_surrogate_lo.html +/library-prerelease/std/uni/isSymbol.html /library-prerelease/std/uni/is_symbol.html +/library-prerelease/std/uni/isUpper.html /library-prerelease/std/uni/is_upper.html +/library-prerelease/std/uni/isUtfMatcher.html /library-prerelease/std/uni/is_utf_matcher.html +/library-prerelease/std/uni/isWhite.html /library-prerelease/std/uni/is_white.html +/library-prerelease/std/uni/lineSep.html /library-prerelease/std/uni/line_sep.html +/library-prerelease/std/uni/MatcherConcept.html /library-prerelease/std/uni/matcher_concept.html +/library-prerelease/std/uni/MatcherConcept.match.html /library-prerelease/std/uni/matcher_concept.match.html +/library-prerelease/std/uni/MatcherConcept.skip.html /library-prerelease/std/uni/matcher_concept.skip.html +/library-prerelease/std/uni/MatcherConcept.test.html /library-prerelease/std/uni/matcher_concept.test.html +/library-prerelease/std/uni/nelSep.html /library-prerelease/std/uni/nel_sep.html +/library-prerelease/std/uni/NFC.html /library-prerelease/std/uni/nfc.html +/library-prerelease/std/uni/NFD.html /library-prerelease/std/uni/nfd.html +/library-prerelease/std/uni/NFKC.html /library-prerelease/std/uni/nfkc.html +/library-prerelease/std/uni/NFKD.html /library-prerelease/std/uni/nfkd.html +/library-prerelease/std/uni/NormalizationForm.html /library-prerelease/std/uni/normalization_form.html +/library-prerelease/std/uni/paraSep.html /library-prerelease/std/uni/para_sep.html +/library-prerelease/std/uni/toDelegate.html /library-prerelease/std/uni/to_delegate.html +/library-prerelease/std/uni/toLowerCase.html /library-prerelease/std/uni/to_lower_case.html +/library-prerelease/std/uni/toLower.html /library-prerelease/std/uni/to_lower.html +/library-prerelease/std/uni/toLowerInPlace.html /library-prerelease/std/uni/to_lower_in_place.html +/library-prerelease/std/uni/toTrie.html /library-prerelease/std/uni/to_trie.html +/library-prerelease/std/uni/toUpperCase.html /library-prerelease/std/uni/to_upper_case.html +/library-prerelease/std/uni/toUpper.html /library-prerelease/std/uni/to_upper.html +/library-prerelease/std/uni/toUpperInPlace.html /library-prerelease/std/uni/to_upper_in_place.html +/library-prerelease/std/uni/UnicodeDecomposition.Canonical.html /library-prerelease/std/uni/unicode_decomposition.canonical.html +/library-prerelease/std/uni/UnicodeDecomposition.Compatibility.html /library-prerelease/std/uni/unicode_decomposition.compatibility.html +/library-prerelease/std/uni/UnicodeDecomposition.html /library-prerelease/std/uni/unicode_decomposition.html +/library-prerelease/std/uni/unicode.hangulSyllableType.html /library-prerelease/std/uni/unicode.hangul_syllable_type.html +/library-prerelease/std/uni/unicode.opCall.html /library-prerelease/std/uni/unicode.op_call.html +/library-prerelease/std/uni/unicode.opDispatch.html /library-prerelease/std/uni/unicode.op_dispatch.html +/library-prerelease/std/uni/utfMatcher.html /library-prerelease/std/uni/utf_matcher.html +/library-prerelease/std/uri/decodeComponent.html /library-prerelease/std/uri/decode_component.html +/library-prerelease/std/uri/emailLength.html /library-prerelease/std/uri/email_length.html +/library-prerelease/std/uri/encodeComponent.html /library-prerelease/std/uri/encode_component.html +/library-prerelease/std/uri/Object.factory.html /library-prerelease/std/uri/object.factory.html +/library-prerelease/std/uri/Object.opCmp.html /library-prerelease/std/uri/object.op_cmp.html +/library-prerelease/std/uri/Object.opEquals.html /library-prerelease/std/uri/object.op_equals.html +/library-prerelease/std/uri/Object.toHash.html /library-prerelease/std/uri/object.to_hash.html +/library-prerelease/std/uri/Throwable.file.html /library-prerelease/std/uri/throwable.file.html +/library-prerelease/std/uri/Throwable.info.html /library-prerelease/std/uri/throwable.info.html +/library-prerelease/std/uri/Throwable.line.html /library-prerelease/std/uri/throwable.line.html +/library-prerelease/std/uri/Throwable.msg.html /library-prerelease/std/uri/throwable.msg.html +/library-prerelease/std/uri/Throwable.next.html /library-prerelease/std/uri/throwable.next.html +/library-prerelease/std/uri/Throwable.toString.html /library-prerelease/std/uri/throwable.to_string.html +/library-prerelease/std/uri/URIException.html /library-prerelease/std/uri/uri_exception.html +/library-prerelease/std/uri/uriLength.html /library-prerelease/std/uri/uri_length.html +/library-prerelease/std/utf/byChar.html /library-prerelease/std/utf/by_char.html +/library-prerelease/std/utf/byCodeUnit.html /library-prerelease/std/utf/by_code_unit.html +/library-prerelease/std/utf/byDchar.html /library-prerelease/std/utf/by_dchar.html +/library-prerelease/std/utf/byUTF.html /library-prerelease/std/utf/by_utf.html +/library-prerelease/std/utf/byWchar.html /library-prerelease/std/utf/by_wchar.html +/library-prerelease/std/utf/codeLength.html /library-prerelease/std/utf/code_length.html +/library-prerelease/std/utf/decodeFront.html /library-prerelease/std/utf/decode_front.html +/library-prerelease/std/utf/isValidDchar.html /library-prerelease/std/utf/is_valid_dchar.html +/library-prerelease/std/utf/Object.factory.html /library-prerelease/std/utf/object.factory.html +/library-prerelease/std/utf/Object.opCmp.html /library-prerelease/std/utf/object.op_cmp.html +/library-prerelease/std/utf/Object.opEquals.html /library-prerelease/std/utf/object.op_equals.html +/library-prerelease/std/utf/Object.toHash.html /library-prerelease/std/utf/object.to_hash.html +/library-prerelease/std/utf/replacementDchar.html /library-prerelease/std/utf/replacement_dchar.html +/library-prerelease/std/utf/strideBack.html /library-prerelease/std/utf/stride_back.html +/library-prerelease/std/utf/Throwable.file.html /library-prerelease/std/utf/throwable.file.html +/library-prerelease/std/utf/Throwable.info.html /library-prerelease/std/utf/throwable.info.html +/library-prerelease/std/utf/Throwable.line.html /library-prerelease/std/utf/throwable.line.html +/library-prerelease/std/utf/Throwable.msg.html /library-prerelease/std/utf/throwable.msg.html +/library-prerelease/std/utf/Throwable.next.html /library-prerelease/std/utf/throwable.next.html +/library-prerelease/std/utf/Throwable.toString.html /library-prerelease/std/utf/throwable.to_string.html +/library-prerelease/std/utf/toUCSindex.html /library-prerelease/std/utf/to_uc_sindex.html +/library-prerelease/std/utf/toUTF16.html /library-prerelease/std/utf/to_ut_f16.html +/library-prerelease/std/utf/toUTF16z.html /library-prerelease/std/utf/to_ut_f16z.html +/library-prerelease/std/utf/toUTF32.html /library-prerelease/std/utf/to_ut_f32.html +/library-prerelease/std/utf/toUTF8.html /library-prerelease/std/utf/to_ut_f8.html +/library-prerelease/std/utf/toUTFindex.html /library-prerelease/std/utf/to_ut_findex.html +/library-prerelease/std/utf/toUTFz.html /library-prerelease/std/utf/to_ut_fz.html +/library-prerelease/std/utf/toUTFz.toUTFz.html /library-prerelease/std/utf/to_ut_fz.to_ut_fz.html +/library-prerelease/std/utf/UTFException.html /library-prerelease/std/utf/utf_exception.html +/library-prerelease/std/uuid/dnsNamespace.html /library-prerelease/std/uuid/dns_namespace.html +/library-prerelease/std/uuid/md5UUID.html /library-prerelease/std/uuid/md5_uuid.html +/library-prerelease/std/uuid/Object.factory.html /library-prerelease/std/uuid/object.factory.html +/library-prerelease/std/uuid/Object.opCmp.html /library-prerelease/std/uuid/object.op_cmp.html +/library-prerelease/std/uuid/Object.opEquals.html /library-prerelease/std/uuid/object.op_equals.html +/library-prerelease/std/uuid/Object.toHash.html /library-prerelease/std/uuid/object.to_hash.html +/library-prerelease/std/uuid/oidNamespace.html /library-prerelease/std/uuid/oid_namespace.html +/library-prerelease/std/uuid/parseUUID.html /library-prerelease/std/uuid/parse_uuid.html +/library-prerelease/std/uuid/randomUUID.html /library-prerelease/std/uuid/random_uuid.html +/library-prerelease/std/uuid/sha1UUID.html /library-prerelease/std/uuid/sha1_uuid.html +/library-prerelease/std/uuid/Throwable.file.html /library-prerelease/std/uuid/throwable.file.html +/library-prerelease/std/uuid/Throwable.info.html /library-prerelease/std/uuid/throwable.info.html +/library-prerelease/std/uuid/Throwable.line.html /library-prerelease/std/uuid/throwable.line.html +/library-prerelease/std/uuid/Throwable.msg.html /library-prerelease/std/uuid/throwable.msg.html +/library-prerelease/std/uuid/Throwable.next.html /library-prerelease/std/uuid/throwable.next.html +/library-prerelease/std/uuid/Throwable.toString.html /library-prerelease/std/uuid/throwable.to_string.html +/library-prerelease/std/uuid/urlNamespace.html /library-prerelease/std/uuid/url_namespace.html +/library-prerelease/std/uuid/UUIDParsingException.html /library-prerelease/std/uuid/uuid_parsing_exception.html +/library-prerelease/std/uuid/UUIDParsingException.input.html /library-prerelease/std/uuid/uuid_parsing_exception.input.html +/library-prerelease/std/uuid/UUIDParsingException.position.html /library-prerelease/std/uuid/uuid_parsing_exception.position.html +/library-prerelease/std/uuid/UUIDParsingException.reason.html /library-prerelease/std/uuid/uuid_parsing_exception.reason.html +/library-prerelease/std/uuid/UUIDParsingException.Reason.html /library-prerelease/std/uuid/uuid_parsing_exception.reason.html +/library-prerelease/std/uuid/UUIDParsingException.Reason.invalidChar.html /library-prerelease/std/uuid/uuid_parsing_exception.reason.invalid_char.html +/library-prerelease/std/uuid/UUIDParsingException.Reason.tooLittle.html /library-prerelease/std/uuid/uuid_parsing_exception.reason.too_little.html +/library-prerelease/std/uuid/UUIDParsingException.Reason.tooMuch.html /library-prerelease/std/uuid/uuid_parsing_exception.reason.too_much.html +/library-prerelease/std/uuid/uuidRegex.html /library-prerelease/std/uuid/uuid_regex.html +/library-prerelease/std/uuid/x500Namespace.html /library-prerelease/std/uuid/x500_namespace.html +/library-prerelease/std/variant/Algebraic.html /library-prerelease/std/variant/algebraic.html +/library-prerelease/std/variant/maxSize.html /library-prerelease/std/variant/max_size.html +/library-prerelease/std/variant/Object.factory.html /library-prerelease/std/variant/object.factory.html +/library-prerelease/std/variant/Object.opCmp.html /library-prerelease/std/variant/object.op_cmp.html +/library-prerelease/std/variant/Object.opEquals.html /library-prerelease/std/variant/object.op_equals.html +/library-prerelease/std/variant/Object.toHash.html /library-prerelease/std/variant/object.to_hash.html +/library-prerelease/std/variant/Throwable.file.html /library-prerelease/std/variant/throwable.file.html +/library-prerelease/std/variant/Throwable.info.html /library-prerelease/std/variant/throwable.info.html +/library-prerelease/std/variant/Throwable.line.html /library-prerelease/std/variant/throwable.line.html +/library-prerelease/std/variant/Throwable.msg.html /library-prerelease/std/variant/throwable.msg.html +/library-prerelease/std/variant/Throwable.next.html /library-prerelease/std/variant/throwable.next.html +/library-prerelease/std/variant/Throwable.toString.html /library-prerelease/std/variant/throwable.to_string.html +/library-prerelease/std/variant/tryVisit.html /library-prerelease/std/variant/try_visit.html +/library-prerelease/std/variant/tryVisit.tryVisit.html /library-prerelease/std/variant/try_visit.try_visit.html +/library-prerelease/std/variant/variantArray.html /library-prerelease/std/variant/variant_array.html +/library-prerelease/std/variant/VariantException.html /library-prerelease/std/variant/variant_exception.html +/library-prerelease/std/variant/VariantException.source.html /library-prerelease/std/variant/variant_exception.source.html +/library-prerelease/std/variant/VariantException.target.html /library-prerelease/std/variant/variant_exception.target.html +/library-prerelease/std/variant/Variant.html /library-prerelease/std/variant/variant.html +/library-prerelease/std/variant/VariantN.allowed.allowed.html /library-prerelease/std/variant/variant.allowed.allowed.html +/library-prerelease/std/variant/VariantN.allowed.html /library-prerelease/std/variant/variant.allowed.html +/library-prerelease/std/variant/VariantN.coerce.coerce.html /library-prerelease/std/variant/variant.coerce.coerce.html +/library-prerelease/std/variant/VariantN.coerce.html /library-prerelease/std/variant/variant.coerce.html +/library-prerelease/std/variant/VariantN.convertsTo.convertsTo.html /library-prerelease/std/variant/variant.converts_to.converts_to.html +/library-prerelease/std/variant/VariantN.convertsTo.html /library-prerelease/std/variant/variant.converts_to.html +/library-prerelease/std/variant/VariantN.get.get.html /library-prerelease/std/variant/variant.get.get.html +/library-prerelease/std/variant/VariantN.get.html /library-prerelease/std/variant/variant.get.html +/library-prerelease/std/variant/VariantN.hasValue.html /library-prerelease/std/variant/variant.has_value.html +/library-prerelease/std/variant/VariantN.html /library-prerelease/std/variant/variant.html +/library-prerelease/std/variant/VariantN.length.html /library-prerelease/std/variant/variant.length.html +/library-prerelease/std/variant/VariantN.opAddAssign.html /library-prerelease/std/variant/variant.op_add_assign.html +/library-prerelease/std/variant/VariantN.opAddAssign.opAddAssign.html /library-prerelease/std/variant/variant.op_add_assign.op_add_assign.html +/library-prerelease/std/variant/VariantN.opAdd.html /library-prerelease/std/variant/variant.op_add.html +/library-prerelease/std/variant/VariantN.opAdd.opAdd.html /library-prerelease/std/variant/variant.op_add.op_add.html +/library-prerelease/std/variant/VariantN.opAndAssign.html /library-prerelease/std/variant/variant.op_and_assign.html +/library-prerelease/std/variant/VariantN.opAndAssign.opAndAssign.html /library-prerelease/std/variant/variant.op_and_assign.op_and_assign.html +/library-prerelease/std/variant/VariantN.opAnd.html /library-prerelease/std/variant/variant.op_and.html +/library-prerelease/std/variant/VariantN.opAnd.opAnd.html /library-prerelease/std/variant/variant.op_and.op_and.html +/library-prerelease/std/variant/VariantN.opApply.html /library-prerelease/std/variant/variant.op_apply.html +/library-prerelease/std/variant/VariantN.opApply.opApply.html /library-prerelease/std/variant/variant.op_apply.op_apply.html +/library-prerelease/std/variant/VariantN.opAssign.html /library-prerelease/std/variant/variant.op_assign.html +/library-prerelease/std/variant/VariantN.opAssign.opAssign.html /library-prerelease/std/variant/variant.op_assign.op_assign.html +/library-prerelease/std/variant/VariantN.opCatAssign.html /library-prerelease/std/variant/variant.op_cat_assign.html +/library-prerelease/std/variant/VariantN.opCatAssign.opCatAssign.html /library-prerelease/std/variant/variant.op_cat_assign.op_cat_assign.html +/library-prerelease/std/variant/VariantN.opCat.html /library-prerelease/std/variant/variant.op_cat.html +/library-prerelease/std/variant/VariantN.opCat.opCat.html /library-prerelease/std/variant/variant.op_cat.op_cat.html +/library-prerelease/std/variant/VariantN.opCmp.html /library-prerelease/std/variant/variant.op_cmp.html +/library-prerelease/std/variant/VariantN.opCmp.opCmp.html /library-prerelease/std/variant/variant.op_cmp.op_cmp.html +/library-prerelease/std/variant/VariantN.opDivAssign.html /library-prerelease/std/variant/variant.op_div_assign.html +/library-prerelease/std/variant/VariantN.opDivAssign.opDivAssign.html /library-prerelease/std/variant/variant.op_div_assign.op_div_assign.html +/library-prerelease/std/variant/VariantN.opDiv.html /library-prerelease/std/variant/variant.op_div.html +/library-prerelease/std/variant/VariantN.opDiv.opDiv.html /library-prerelease/std/variant/variant.op_div.op_div.html +/library-prerelease/std/variant/VariantN.opEquals.html /library-prerelease/std/variant/variant.op_equals.html +/library-prerelease/std/variant/VariantN.opEquals.opEquals.html /library-prerelease/std/variant/variant.op_equals.op_equals.html +/library-prerelease/std/variant/VariantN.opIndexAssign.html /library-prerelease/std/variant/variant.op_index_assign.html +/library-prerelease/std/variant/VariantN.opIndexAssign.opIndexAssign.html /library-prerelease/std/variant/variant.op_index_assign.op_index_assign.html +/library-prerelease/std/variant/VariantN.opIndex.html /library-prerelease/std/variant/variant.op_index.html +/library-prerelease/std/variant/VariantN.opIndex.opIndex.html /library-prerelease/std/variant/variant.op_index.op_index.html +/library-prerelease/std/variant/VariantN.opModAssign.html /library-prerelease/std/variant/variant.op_mod_assign.html +/library-prerelease/std/variant/VariantN.opModAssign.opModAssign.html /library-prerelease/std/variant/variant.op_mod_assign.op_mod_assign.html +/library-prerelease/std/variant/VariantN.opMod.html /library-prerelease/std/variant/variant.op_mod.html +/library-prerelease/std/variant/VariantN.opMod.opMod.html /library-prerelease/std/variant/variant.op_mod.op_mod.html +/library-prerelease/std/variant/VariantN.opMulAssign.html /library-prerelease/std/variant/variant.op_mul_assign.html +/library-prerelease/std/variant/VariantN.opMulAssign.opMulAssign.html /library-prerelease/std/variant/variant.op_mul_assign.op_mul_assign.html +/library-prerelease/std/variant/VariantN.opMul.html /library-prerelease/std/variant/variant.op_mul.html +/library-prerelease/std/variant/VariantN.opMul.opMul.html /library-prerelease/std/variant/variant.op_mul.op_mul.html +/library-prerelease/std/variant/VariantN.opOrAssign.html /library-prerelease/std/variant/variant.op_or_assign.html +/library-prerelease/std/variant/VariantN.opOrAssign.opOrAssign.html /library-prerelease/std/variant/variant.op_or_assign.op_or_assign.html +/library-prerelease/std/variant/VariantN.opOr.html /library-prerelease/std/variant/variant.op_or.html +/library-prerelease/std/variant/VariantN.opOr.opOr.html /library-prerelease/std/variant/variant.op_or.op_or.html +/library-prerelease/std/variant/VariantN.opShlAssign.html /library-prerelease/std/variant/variant.op_shl_assign.html +/library-prerelease/std/variant/VariantN.opShlAssign.opShlAssign.html /library-prerelease/std/variant/variant.op_shl_assign.op_shl_assign.html +/library-prerelease/std/variant/VariantN.opShl.html /library-prerelease/std/variant/variant.op_shl.html +/library-prerelease/std/variant/VariantN.opShl.opShl.html /library-prerelease/std/variant/variant.op_shl.op_shl.html +/library-prerelease/std/variant/VariantN.opShrAssign.html /library-prerelease/std/variant/variant.op_shr_assign.html +/library-prerelease/std/variant/VariantN.opShrAssign.opShrAssign.html /library-prerelease/std/variant/variant.op_shr_assign.op_shr_assign.html +/library-prerelease/std/variant/VariantN.opShr.html /library-prerelease/std/variant/variant.op_shr.html +/library-prerelease/std/variant/VariantN.opShr.opShr.html /library-prerelease/std/variant/variant.op_shr.op_shr.html +/library-prerelease/std/variant/VariantN.opSubAssign.html /library-prerelease/std/variant/variant.op_sub_assign.html +/library-prerelease/std/variant/VariantN.opSubAssign.opSubAssign.html /library-prerelease/std/variant/variant.op_sub_assign.op_sub_assign.html +/library-prerelease/std/variant/VariantN.opSub.html /library-prerelease/std/variant/variant.op_sub.html +/library-prerelease/std/variant/VariantN.opSub.opSub.html /library-prerelease/std/variant/variant.op_sub.op_sub.html +/library-prerelease/std/variant/VariantN.opUShrAssign.html /library-prerelease/std/variant/variant.op_u_shr_assign.html +/library-prerelease/std/variant/VariantN.opUShrAssign.opUShrAssign.html /library-prerelease/std/variant/variant.op_u_shr_assign.op_u_shr_assign.html +/library-prerelease/std/variant/VariantN.opUShr.html /library-prerelease/std/variant/variant.op_u_shr.html +/library-prerelease/std/variant/VariantN.opUShr.opUShr.html /library-prerelease/std/variant/variant.op_u_shr.op_u_shr.html +/library-prerelease/std/variant/VariantN.opXorAssign.html /library-prerelease/std/variant/variant.op_xor_assign.html +/library-prerelease/std/variant/VariantN.opXorAssign.opXorAssign.html /library-prerelease/std/variant/variant.op_xor_assign.op_xor_assign.html +/library-prerelease/std/variant/VariantN.opXor.html /library-prerelease/std/variant/variant.op_xor.html +/library-prerelease/std/variant/VariantN.opXor.opXor.html /library-prerelease/std/variant/variant.op_xor.op_xor.html +/library-prerelease/std/variant/VariantN.peek.html /library-prerelease/std/variant/variant.peek.html +/library-prerelease/std/variant/VariantN.peek.peek.html /library-prerelease/std/variant/variant.peek.peek.html +/library-prerelease/std/variant/VariantN.this.html /library-prerelease/std/variant/variant.this.html +/library-prerelease/std/variant/VariantN.this.this.html /library-prerelease/std/variant/variant.this.this.html +/library-prerelease/std/variant/VariantN.toHash.html /library-prerelease/std/variant/variant.to_hash.html +/library-prerelease/std/variant/VariantN.toString.html /library-prerelease/std/variant/variant.to_string.html +/library-prerelease/std/variant/VariantN.type.html /library-prerelease/std/variant/variant.type.html +/library-prerelease/std/xml/CDataException.html /library-prerelease/std/xml/c_data_exception.html +/library-prerelease/std/xml/CData.html /library-prerelease/std/xml/c_data.html +/library-prerelease/std/xml/CData.isEmptyXML.html /library-prerelease/std/xml/c_data.is_empty_xml.html +/library-prerelease/std/xml/CData.opCmp.html /library-prerelease/std/xml/c_data.op_cmp.html +/library-prerelease/std/xml/CData.opEquals.html /library-prerelease/std/xml/c_data.op_equals.html +/library-prerelease/std/xml/CData.this.html /library-prerelease/std/xml/c_data.this.html +/library-prerelease/std/xml/CData.toHash.html /library-prerelease/std/xml/c_data.to_hash.html +/library-prerelease/std/xml/CData.toString.html /library-prerelease/std/xml/c_data.to_string.html +/library-prerelease/std/xml/CheckException.column.html /library-prerelease/std/xml/check_exception.column.html +/library-prerelease/std/xml/CheckException.err.html /library-prerelease/std/xml/check_exception.err.html +/library-prerelease/std/xml/CheckException.html /library-prerelease/std/xml/check_exception.html +/library-prerelease/std/xml/CheckException.line.html /library-prerelease/std/xml/check_exception.line.html +/library-prerelease/std/xml/CheckException.msg.html /library-prerelease/std/xml/check_exception.msg.html +/library-prerelease/std/xml/CommentException.html /library-prerelease/std/xml/comment_exception.html +/library-prerelease/std/xml/Comment.html /library-prerelease/std/xml/comment.html +/library-prerelease/std/xml/Comment.isEmptyXML.html /library-prerelease/std/xml/comment.is_empty_xml.html +/library-prerelease/std/xml/Comment.opCmp.html /library-prerelease/std/xml/comment.op_cmp.html +/library-prerelease/std/xml/Comment.opEquals.html /library-prerelease/std/xml/comment.op_equals.html +/library-prerelease/std/xml/Comment.this.html /library-prerelease/std/xml/comment.this.html +/library-prerelease/std/xml/Comment.toHash.html /library-prerelease/std/xml/comment.to_hash.html +/library-prerelease/std/xml/Comment.toString.html /library-prerelease/std/xml/comment.to_string.html +/library-prerelease/std/xml/DecodeException.html /library-prerelease/std/xml/decode_exception.html +/library-prerelease/std/xml/DecodeMode.html /library-prerelease/std/xml/decode_mode.html +/library-prerelease/std/xml/Document.epilog.html /library-prerelease/std/xml/document.epilog.html +/library-prerelease/std/xml/Document.html /library-prerelease/std/xml/document.html +/library-prerelease/std/xml/Document.opCmp.html /library-prerelease/std/xml/document.op_cmp.html +/library-prerelease/std/xml/Document.opEquals.html /library-prerelease/std/xml/document.op_equals.html +/library-prerelease/std/xml/DocumentParser.html /library-prerelease/std/xml/document_parser.html +/library-prerelease/std/xml/DocumentParser.this.html /library-prerelease/std/xml/document_parser.this.html +/library-prerelease/std/xml/Document.prolog.html /library-prerelease/std/xml/document.prolog.html +/library-prerelease/std/xml/Document.this.html /library-prerelease/std/xml/document.this.html +/library-prerelease/std/xml/Document.toHash.html /library-prerelease/std/xml/document.to_hash.html +/library-prerelease/std/xml/Document.toString.html /library-prerelease/std/xml/document.to_string.html +/library-prerelease/std/xml/Element.cdatas.html /library-prerelease/std/xml/element.cdatas.html +/library-prerelease/std/xml/Element.comments.html /library-prerelease/std/xml/element.comments.html +/library-prerelease/std/xml/Element.elements.html /library-prerelease/std/xml/element.elements.html +/library-prerelease/std/xml/Element.html /library-prerelease/std/xml/element.html +/library-prerelease/std/xml/Element.items.html /library-prerelease/std/xml/element.items.html +/library-prerelease/std/xml/Element.opCatAssign.html /library-prerelease/std/xml/element.op_cat_assign.html +/library-prerelease/std/xml/Element.opCmp.html /library-prerelease/std/xml/element.op_cmp.html +/library-prerelease/std/xml/Element.opEquals.html /library-prerelease/std/xml/element.op_equals.html +/library-prerelease/std/xml/ElementParser.html /library-prerelease/std/xml/element_parser.html +/library-prerelease/std/xml/ElementParser.onCData.html /library-prerelease/std/xml/element_parser.on_c_data.html +/library-prerelease/std/xml/ElementParser.onComment.html /library-prerelease/std/xml/element_parser.on_comment.html +/library-prerelease/std/xml/ElementParser.onEndTag.html /library-prerelease/std/xml/element_parser.on_end_tag.html +/library-prerelease/std/xml/ElementParser.onPI.html /library-prerelease/std/xml/element_parser.on_pi.html +/library-prerelease/std/xml/ElementParser.onStartTag.html /library-prerelease/std/xml/element_parser.on_start_tag.html +/library-prerelease/std/xml/ElementParser.onText.html /library-prerelease/std/xml/element_parser.on_text.html +/library-prerelease/std/xml/ElementParser.onTextRaw.html /library-prerelease/std/xml/element_parser.on_text_raw.html +/library-prerelease/std/xml/ElementParser.onXI.html /library-prerelease/std/xml/element_parser.on_xi.html +/library-prerelease/std/xml/ElementParser.parse.html /library-prerelease/std/xml/element_parser.parse.html +/library-prerelease/std/xml/ElementParser.tag.html /library-prerelease/std/xml/element_parser.tag.html +/library-prerelease/std/xml/ElementParser.toString.html /library-prerelease/std/xml/element_parser.to_string.html +/library-prerelease/std/xml/Element.pis.html /library-prerelease/std/xml/element.pis.html +/library-prerelease/std/xml/Element.pretty.html /library-prerelease/std/xml/element.pretty.html +/library-prerelease/std/xml/Element.tag.html /library-prerelease/std/xml/element.tag.html +/library-prerelease/std/xml/Element.text.html /library-prerelease/std/xml/element.text.html +/library-prerelease/std/xml/Element.texts.html /library-prerelease/std/xml/element.texts.html +/library-prerelease/std/xml/Element.this.html /library-prerelease/std/xml/element.this.html +/library-prerelease/std/xml/Element.toHash.html /library-prerelease/std/xml/element.to_hash.html +/library-prerelease/std/xml/Element.toString.html /library-prerelease/std/xml/element.to_string.html +/library-prerelease/std/xml/InvalidTypeException.html /library-prerelease/std/xml/invalid_type_exception.html +/library-prerelease/std/xml/isBaseChar.html /library-prerelease/std/xml/is_base_char.html +/library-prerelease/std/xml/isChar.html /library-prerelease/std/xml/is_char.html +/library-prerelease/std/xml/isCombiningChar.html /library-prerelease/std/xml/is_combining_char.html +/library-prerelease/std/xml/isDigit.html /library-prerelease/std/xml/is_digit.html +/library-prerelease/std/xml/isExtender.html /library-prerelease/std/xml/is_extender.html +/library-prerelease/std/xml/isIdeographic.html /library-prerelease/std/xml/is_ideographic.html +/library-prerelease/std/xml/isLetter.html /library-prerelease/std/xml/is_letter.html +/library-prerelease/std/xml/isSpace.html /library-prerelease/std/xml/is_space.html +/library-prerelease/std/xml/Item.html /library-prerelease/std/xml/item.html +/library-prerelease/std/xml/Item.isEmptyXML.html /library-prerelease/std/xml/item.is_empty_xml.html +/library-prerelease/std/xml/Item.opCmp.html /library-prerelease/std/xml/item.op_cmp.html +/library-prerelease/std/xml/Item.opEquals.html /library-prerelease/std/xml/item.op_equals.html +/library-prerelease/std/xml/Item.pretty.html /library-prerelease/std/xml/item.pretty.html +/library-prerelease/std/xml/Item.toHash.html /library-prerelease/std/xml/item.to_hash.html +/library-prerelease/std/xml/Item.toString.html /library-prerelease/std/xml/item.to_string.html +/library-prerelease/std/xml/Object.factory.html /library-prerelease/std/xml/object.factory.html +/library-prerelease/std/xml/Object.opCmp.html /library-prerelease/std/xml/object.op_cmp.html +/library-prerelease/std/xml/Object.opEquals.html /library-prerelease/std/xml/object.op_equals.html +/library-prerelease/std/xml/Object.toHash.html /library-prerelease/std/xml/object.to_hash.html +/library-prerelease/std/xml/Object.toString.html /library-prerelease/std/xml/object.to_string.html +/library-prerelease/std/xml/PIException.html /library-prerelease/std/xml/pi_exception.html +/library-prerelease/std/xml/ProcessingInstruction.html /library-prerelease/std/xml/processing_instruction.html +/library-prerelease/std/xml/ProcessingInstruction.isEmptyXML.html /library-prerelease/std/xml/processing_instruction.is_empty_xml.html +/library-prerelease/std/xml/ProcessingInstruction.opCmp.html /library-prerelease/std/xml/processing_instruction.op_cmp.html +/library-prerelease/std/xml/ProcessingInstruction.opEquals.html /library-prerelease/std/xml/processing_instruction.op_equals.html +/library-prerelease/std/xml/ProcessingInstruction.this.html /library-prerelease/std/xml/processing_instruction.this.html +/library-prerelease/std/xml/ProcessingInstruction.toHash.html /library-prerelease/std/xml/processing_instruction.to_hash.html +/library-prerelease/std/xml/ProcessingInstruction.toString.html /library-prerelease/std/xml/processing_instruction.to_string.html +/library-prerelease/std/xml/Tag.attr.html /library-prerelease/std/xml/tag.attr.html +/library-prerelease/std/xml/TagException.html /library-prerelease/std/xml/tag_exception.html +/library-prerelease/std/xml/Tag.html /library-prerelease/std/xml/tag.html +/library-prerelease/std/xml/Tag.isEmpty.html /library-prerelease/std/xml/tag.is_empty.html +/library-prerelease/std/xml/Tag.isEnd.html /library-prerelease/std/xml/tag.is_end.html +/library-prerelease/std/xml/Tag.isStart.html /library-prerelease/std/xml/tag.is_start.html +/library-prerelease/std/xml/Tag.name.html /library-prerelease/std/xml/tag.name.html +/library-prerelease/std/xml/Tag.opCmp.html /library-prerelease/std/xml/tag.op_cmp.html +/library-prerelease/std/xml/Tag.opEquals.html /library-prerelease/std/xml/tag.op_equals.html +/library-prerelease/std/xml/Tag.this.html /library-prerelease/std/xml/tag.this.html +/library-prerelease/std/xml/Tag.toHash.html /library-prerelease/std/xml/tag.to_hash.html +/library-prerelease/std/xml/Tag.toString.html /library-prerelease/std/xml/tag.to_string.html +/library-prerelease/std/xml/Tag.type.html /library-prerelease/std/xml/tag.type.html +/library-prerelease/std/xml/TagType.html /library-prerelease/std/xml/tag_type.html +/library-prerelease/std/xml/TextException.html /library-prerelease/std/xml/text_exception.html +/library-prerelease/std/xml/Text.html /library-prerelease/std/xml/text.html +/library-prerelease/std/xml/Text.isEmptyXML.html /library-prerelease/std/xml/text.is_empty_xml.html +/library-prerelease/std/xml/Text.opCmp.html /library-prerelease/std/xml/text.op_cmp.html +/library-prerelease/std/xml/Text.opEquals.html /library-prerelease/std/xml/text.op_equals.html +/library-prerelease/std/xml/Text.this.html /library-prerelease/std/xml/text.this.html +/library-prerelease/std/xml/Text.toHash.html /library-prerelease/std/xml/text.to_hash.html +/library-prerelease/std/xml/Text.toString.html /library-prerelease/std/xml/text.to_string.html +/library-prerelease/std/xml/Throwable.file.html /library-prerelease/std/xml/throwable.file.html +/library-prerelease/std/xml/Throwable.info.html /library-prerelease/std/xml/throwable.info.html +/library-prerelease/std/xml/Throwable.line.html /library-prerelease/std/xml/throwable.line.html +/library-prerelease/std/xml/Throwable.msg.html /library-prerelease/std/xml/throwable.msg.html +/library-prerelease/std/xml/Throwable.next.html /library-prerelease/std/xml/throwable.next.html +/library-prerelease/std/xml/Throwable.toString.html /library-prerelease/std/xml/throwable.to_string.html +/library-prerelease/std/xml/XIException.html /library-prerelease/std/xml/xi_exception.html +/library-prerelease/std/xml/XMLException.html /library-prerelease/std/xml/xml_exception.html +/library-prerelease/std/xml/XMLInstruction.html /library-prerelease/std/xml/xml_instruction.html +/library-prerelease/std/xml/XMLInstruction.isEmptyXML.html /library-prerelease/std/xml/xml_instruction.is_empty_xml.html +/library-prerelease/std/xml/XMLInstruction.opCmp.html /library-prerelease/std/xml/xml_instruction.op_cmp.html +/library-prerelease/std/xml/XMLInstruction.opEquals.html /library-prerelease/std/xml/xml_instruction.op_equals.html +/library-prerelease/std/xml/XMLInstruction.this.html /library-prerelease/std/xml/xml_instruction.this.html +/library-prerelease/std/xml/XMLInstruction.toHash.html /library-prerelease/std/xml/xml_instruction.to_hash.html +/library-prerelease/std/xml/XMLInstruction.toString.html /library-prerelease/std/xml/xml_instruction.to_string.html +/library-prerelease/std/zip/ArchiveMember.comment.html /library-prerelease/std/zip/archive_member.comment.html +/library-prerelease/std/zip/ArchiveMember.compressedData.html /library-prerelease/std/zip/archive_member.compressed_data.html +/library-prerelease/std/zip/ArchiveMember.compressedSize.html /library-prerelease/std/zip/archive_member.compressed_size.html +/library-prerelease/std/zip/ArchiveMember.compressionMethod.html /library-prerelease/std/zip/archive_member.compression_method.html +/library-prerelease/std/zip/ArchiveMember.crc32.html /library-prerelease/std/zip/archive_member.crc32.html +/library-prerelease/std/zip/ArchiveMember.diskNumber.html /library-prerelease/std/zip/archive_member.disk_number.html +/library-prerelease/std/zip/ArchiveMember.expandedData.html /library-prerelease/std/zip/archive_member.expanded_data.html +/library-prerelease/std/zip/ArchiveMember.expandedSize.html /library-prerelease/std/zip/archive_member.expanded_size.html +/library-prerelease/std/zip/ArchiveMember.extractVersion.html /library-prerelease/std/zip/archive_member.extract_version.html +/library-prerelease/std/zip/ArchiveMember.extra.html /library-prerelease/std/zip/archive_member.extra.html +/library-prerelease/std/zip/ArchiveMember.fileAttributes.html /library-prerelease/std/zip/archive_member.file_attributes.html +/library-prerelease/std/zip/ArchiveMember.flags.html /library-prerelease/std/zip/archive_member.flags.html +/library-prerelease/std/zip/ArchiveMember.html /library-prerelease/std/zip/archive_member.html +/library-prerelease/std/zip/ArchiveMember.internalAttributes.html /library-prerelease/std/zip/archive_member.internal_attributes.html +/library-prerelease/std/zip/ArchiveMember.name.html /library-prerelease/std/zip/archive_member.name.html +/library-prerelease/std/zip/ArchiveMember.time.html /library-prerelease/std/zip/archive_member.time.html +/library-prerelease/std/zip/CompressionMethod.deflate.html /library-prerelease/std/zip/compression_method.deflate.html +/library-prerelease/std/zip/CompressionMethod.html /library-prerelease/std/zip/compression_method.html +/library-prerelease/std/zip/CompressionMethod.none.html /library-prerelease/std/zip/compression_method.none.html +/library-prerelease/std/zip/Object.factory.html /library-prerelease/std/zip/object.factory.html +/library-prerelease/std/zip/Object.opCmp.html /library-prerelease/std/zip/object.op_cmp.html +/library-prerelease/std/zip/Object.opEquals.html /library-prerelease/std/zip/object.op_equals.html +/library-prerelease/std/zip/Object.toHash.html /library-prerelease/std/zip/object.to_hash.html +/library-prerelease/std/zip/Object.toString.html /library-prerelease/std/zip/object.to_string.html +/library-prerelease/std/zip/Throwable.file.html /library-prerelease/std/zip/throwable.file.html +/library-prerelease/std/zip/Throwable.info.html /library-prerelease/std/zip/throwable.info.html +/library-prerelease/std/zip/Throwable.line.html /library-prerelease/std/zip/throwable.line.html +/library-prerelease/std/zip/Throwable.msg.html /library-prerelease/std/zip/throwable.msg.html +/library-prerelease/std/zip/Throwable.next.html /library-prerelease/std/zip/throwable.next.html +/library-prerelease/std/zip/Throwable.toString.html /library-prerelease/std/zip/throwable.to_string.html +/library-prerelease/std/zip/ZipArchive.addMember.html /library-prerelease/std/zip/zip_archive.add_member.html +/library-prerelease/std/zip/ZipArchive.build.html /library-prerelease/std/zip/zip_archive.build.html +/library-prerelease/std/zip/ZipArchive.comment.html /library-prerelease/std/zip/zip_archive.comment.html +/library-prerelease/std/zip/ZipArchive.data.html /library-prerelease/std/zip/zip_archive.data.html +/library-prerelease/std/zip/ZipArchive.deleteMember.html /library-prerelease/std/zip/zip_archive.delete_member.html +/library-prerelease/std/zip/ZipArchive.directory.html /library-prerelease/std/zip/zip_archive.directory.html +/library-prerelease/std/zip/ZipArchive.diskNumber.html /library-prerelease/std/zip/zip_archive.disk_number.html +/library-prerelease/std/zip/ZipArchive.diskStartDir.html /library-prerelease/std/zip/zip_archive.disk_start_dir.html +/library-prerelease/std/zip/ZipArchive.expand.html /library-prerelease/std/zip/zip_archive.expand.html +/library-prerelease/std/zip/ZipArchive.html /library-prerelease/std/zip/zip_archive.html +/library-prerelease/std/zip/ZipArchive.isZip64.html /library-prerelease/std/zip/zip_archive.is_zip64.html +/library-prerelease/std/zip/ZipArchive.numEntries.html /library-prerelease/std/zip/zip_archive.num_entries.html +/library-prerelease/std/zip/ZipArchive.this.html /library-prerelease/std/zip/zip_archive.this.html +/library-prerelease/std/zip/ZipArchive.totalEntries.html /library-prerelease/std/zip/zip_archive.total_entries.html +/library-prerelease/std/zip/ZipException.html /library-prerelease/std/zip/zip_exception.html +/library-prerelease/std/zlib/Compress.compress.html /library-prerelease/std/zlib/compress.compress.html +/library-prerelease/std/zlib/Compress.flush.html /library-prerelease/std/zlib/compress.flush.html +/library-prerelease/std/zlib/Compress.html /library-prerelease/std/zlib/compress.html +/library-prerelease/std/zlib/Compress.this.html /library-prerelease/std/zlib/compress.this.html +/library-prerelease/std/zlib/HeaderFormat.deflate.html /library-prerelease/std/zlib/header_format.deflate.html +/library-prerelease/std/zlib/HeaderFormat.determineFromData.html /library-prerelease/std/zlib/header_format.determine_from_data.html +/library-prerelease/std/zlib/HeaderFormat.gzip.html /library-prerelease/std/zlib/header_format.gzip.html +/library-prerelease/std/zlib/HeaderFormat.html /library-prerelease/std/zlib/header_format.html +/library-prerelease/std/zlib/Object.factory.html /library-prerelease/std/zlib/object.factory.html +/library-prerelease/std/zlib/Object.opCmp.html /library-prerelease/std/zlib/object.op_cmp.html +/library-prerelease/std/zlib/Object.opEquals.html /library-prerelease/std/zlib/object.op_equals.html +/library-prerelease/std/zlib/Object.toHash.html /library-prerelease/std/zlib/object.to_hash.html +/library-prerelease/std/zlib/Object.toString.html /library-prerelease/std/zlib/object.to_string.html +/library-prerelease/std/zlib/Throwable.file.html /library-prerelease/std/zlib/throwable.file.html +/library-prerelease/std/zlib/Throwable.info.html /library-prerelease/std/zlib/throwable.info.html +/library-prerelease/std/zlib/Throwable.line.html /library-prerelease/std/zlib/throwable.line.html +/library-prerelease/std/zlib/Throwable.msg.html /library-prerelease/std/zlib/throwable.msg.html +/library-prerelease/std/zlib/Throwable.next.html /library-prerelease/std/zlib/throwable.next.html +/library-prerelease/std/zlib/Throwable.toString.html /library-prerelease/std/zlib/throwable.to_string.html +/library-prerelease/std/zlib/UnCompress.flush.html /library-prerelease/std/zlib/un_compress.flush.html +/library-prerelease/std/zlib/UnCompress.html /library-prerelease/std/zlib/un_compress.html +/library-prerelease/std/zlib/UnCompress.this.html /library-prerelease/std/zlib/un_compress.this.html +/library-prerelease/std/zlib/UnCompress.uncompress.html /library-prerelease/std/zlib/un_compress.uncompress.html +/library-prerelease/std/zlib/ZlibException.html /library-prerelease/std/zlib/zlib_exception.html +/library/std/algorithm/comparison/castSwitch.html /library/std/algorithm/comparison/cast_switch.html +/library/std/algorithm/comparison/EditOp.html /library/std/algorithm/comparison/edit_op.html +/library/std/algorithm/comparison/EditOp.insert.html /library/std/algorithm/comparison/edit_op.insert.html +/library/std/algorithm/comparison/EditOp.none.html /library/std/algorithm/comparison/edit_op.none.html +/library/std/algorithm/comparison/EditOp.remove.html /library/std/algorithm/comparison/edit_op.remove.html +/library/std/algorithm/comparison/EditOp.substitute.html /library/std/algorithm/comparison/edit_op.substitute.html +/library/std/algorithm/comparison/levenshteinDistanceAndPath.html /library/std/algorithm/comparison/levenshtein_distance_and_path.html +/library/std/algorithm/comparison/levenshteinDistance.html /library/std/algorithm/comparison/levenshtein_distance.html +/library/std/algorithm/comparison/predSwitch.html /library/std/algorithm/comparison/pred_switch.html +/library/std/algorithm/iteration/cacheBidirectional.html /library/std/algorithm/iteration/cache_bidirectional.html +/library/std/algorithm/iteration/filterBidirectional.filterBidirectional.html /library/std/algorithm/iteration/filter_bidirectional.filter_bidirectional.html +/library/std/algorithm/iteration/filterBidirectional.html /library/std/algorithm/iteration/filter_bidirectional.html +/library/std/algorithm/iteration/groupBy.html /library/std/algorithm/iteration/group_by.html +/library/std/algorithm/mutation/bringToFront.html /library/std/algorithm/mutation/bring_to_front.html +/library/std/algorithm/mutation/initializeAll.html /library/std/algorithm/mutation/initialize_all.html +/library/std/algorithm/mutation/moveAll.html /library/std/algorithm/mutation/move_all.html +/library/std/algorithm/mutation/moveSome.html /library/std/algorithm/mutation/move_some.html +/library/std/algorithm/mutation/stripLeft.html /library/std/algorithm/mutation/strip_left.html +/library/std/algorithm/mutation/stripRight.html /library/std/algorithm/mutation/strip_right.html +/library/std/algorithm/mutation/swapRanges.html /library/std/algorithm/mutation/swap_ranges.html +/library/std/algorithm/mutation/SwapStrategy.html /library/std/algorithm/mutation/swap_strategy.html +/library/std/algorithm/mutation/SwapStrategy.semistable.html /library/std/algorithm/mutation/swap_strategy.semistable.html +/library/std/algorithm/mutation/SwapStrategy.stable.html /library/std/algorithm/mutation/swap_strategy.stable.html +/library/std/algorithm/mutation/SwapStrategy.unstable.html /library/std/algorithm/mutation/swap_strategy.unstable.html +/library/std/algorithm/mutation/uninitializedFill.html /library/std/algorithm/mutation/uninitialized_fill.html +/library/std/algorithm/searching/balancedParens.html /library/std/algorithm/searching/balanced_parens.html +/library/std/algorithm/searching/boyerMooreFinder.html /library/std/algorithm/searching/boyer_moore_finder.html +/library/std/algorithm/searching/BoyerMooreFinder.html /library/std/algorithm/searching/boyer_moore_finder.html +/library/std/algorithm/searching/canFind.canFind.html /library/std/algorithm/searching/can_find.can_find.html +/library/std/algorithm/searching/canFind.html /library/std/algorithm/searching/can_find.html +/library/std/algorithm/searching/commonPrefix.html /library/std/algorithm/searching/common_prefix.html +/library/std/algorithm/searching/countUntil.html /library/std/algorithm/searching/count_until.html +/library/std/algorithm/searching/endsWith.html /library/std/algorithm/searching/ends_with.html +/library/std/algorithm/searching/findAdjacent.html /library/std/algorithm/searching/find_adjacent.html +/library/std/algorithm/searching/findAmong.html /library/std/algorithm/searching/find_among.html +/library/std/algorithm/searching/findSkip.html /library/std/algorithm/searching/find_skip.html +/library/std/algorithm/searching/findSplitAfter.html /library/std/algorithm/searching/find_split_after.html +/library/std/algorithm/searching/findSplitBefore.html /library/std/algorithm/searching/find_split_before.html +/library/std/algorithm/searching/findSplit.html /library/std/algorithm/searching/find_split.html +/library/std/algorithm/searching/minCount.html /library/std/algorithm/searching/min_count.html +/library/std/algorithm/searching/minPos.html /library/std/algorithm/searching/min_pos.html +/library/std/algorithm/searching/OpenRight.html /library/std/algorithm/searching/open_right.html +/library/std/algorithm/searching/OpenRight.no.html /library/std/algorithm/searching/open_right.no.html +/library/std/algorithm/searching/OpenRight.yes.html /library/std/algorithm/searching/open_right.yes.html +/library/std/algorithm/searching/skipOver.html /library/std/algorithm/searching/skip_over.html +/library/std/algorithm/searching/startsWith.html /library/std/algorithm/searching/starts_with.html +/library/std/algorithm/setops/cartesianProduct.html /library/std/algorithm/setops/cartesian_product.html +/library/std/algorithm/setops/largestPartialIntersection.html /library/std/algorithm/setops/largest_partial_intersection.html +/library/std/algorithm/setops/largestPartialIntersectionWeighted.html /library/std/algorithm/setops/largest_partial_intersection_weighted.html +/library/std/algorithm/setops/nWayUnion.html /library/std/algorithm/setops/n_way_union.html +/library/std/algorithm/setops/NWayUnion.html /library/std/algorithm/setops/n_way_union.html +/library/std/algorithm/setops/setDifference.html /library/std/algorithm/setops/set_difference.html +/library/std/algorithm/setops/SetDifference.html /library/std/algorithm/setops/set_difference.html +/library/std/algorithm/setops/setIntersection.html /library/std/algorithm/setops/set_intersection.html +/library/std/algorithm/setops/SetIntersection.html /library/std/algorithm/setops/set_intersection.html +/library/std/algorithm/setops/setSymmetricDifference.html /library/std/algorithm/setops/set_symmetric_difference.html +/library/std/algorithm/setops/SetSymmetricDifference.html /library/std/algorithm/setops/set_symmetric_difference.html +/library/std/algorithm/setops/setUnion.html /library/std/algorithm/setops/set_union.html +/library/std/algorithm/setops/SetUnion.html /library/std/algorithm/setops/set_union.html +/library/std/algorithm/sorting/completeSort.html /library/std/algorithm/sorting/complete_sort.html +/library/std/algorithm/sorting/isPartitioned.html /library/std/algorithm/sorting/is_partitioned.html +/library/std/algorithm/sorting/isSorted.html /library/std/algorithm/sorting/is_sorted.html +/library/std/algorithm/sorting/makeIndex.html /library/std/algorithm/sorting/make_index.html +/library/std/algorithm/sorting/multiSort.html /library/std/algorithm/sorting/multi_sort.html +/library/std/algorithm/sorting/multiSort.multiSort.html /library/std/algorithm/sorting/multi_sort.multi_sort.html +/library/std/algorithm/sorting/nextEvenPermutation.html /library/std/algorithm/sorting/next_even_permutation.html +/library/std/algorithm/sorting/nextPermutation.html /library/std/algorithm/sorting/next_permutation.html +/library/std/algorithm/sorting/partialSort.html /library/std/algorithm/sorting/partial_sort.html +/library/std/algorithm/sorting/schwartzSort.html /library/std/algorithm/sorting/schwartz_sort.html +/library/std/algorithm/sorting/SortOutput.html /library/std/algorithm/sorting/sort_output.html +/library/std/algorithm/sorting/SortOutput.no.html /library/std/algorithm/sorting/sort_output.no.html +/library/std/algorithm/sorting/SortOutput.yes.html /library/std/algorithm/sorting/sort_output.yes.html +/library/std/algorithm/sorting/topNCopy.html /library/std/algorithm/sorting/top_n_copy.html +/library/std/algorithm/sorting/topN.html /library/std/algorithm/sorting/top.html +/library/std/algorithm/sorting/topNIndex.html /library/std/algorithm/sorting/top_n_index.html +/library/std/array/Appender.capacity.html /library/std/array/appender.capacity.html +/library/std/array/Appender.data.html /library/std/array/appender.data.html +/library/std/array/Appender.html /library/std/array/appender.html +/library/std/array/Appender.opOpAssign.html /library/std/array/appender.op_op_assign.html +/library/std/array/Appender.opOpAssign.opOpAssign.html /library/std/array/appender.op_op_assign.op_op_assign.html +/library/std/array/Appender.put.html /library/std/array/appender.put.html +/library/std/array/Appender.put.put.html /library/std/array/appender.put.put.html +/library/std/array/Appender.reserve.html /library/std/array/appender.reserve.html +/library/std/array/Appender.this.html /library/std/array/appender.this.html +/library/std/array/assocArray.html /library/std/array/assoc_array.html +/library/std/array/byPair.html /library/std/array/by_pair.html +/library/std/array/insertInPlace.html /library/std/array/insert_in_place.html +/library/std/array/minimallyInitializedArray.html /library/std/array/minimally_initialized_array.html +/library/std/array/RefAppender.capacity.html /library/std/array/ref_appender.capacity.html +/library/std/array/RefAppender.data.html /library/std/array/ref_appender.data.html +/library/std/array/RefAppender.html /library/std/array/ref_appender.html +/library/std/array/RefAppender.opOpAssign.html /library/std/array/ref_appender.op_op_assign.html +/library/std/array/RefAppender.opOpAssign.opOpAssign.html /library/std/array/ref_appender.op_op_assign.op_op_assign.html +/library/std/array/RefAppender.this.html /library/std/array/ref_appender.this.html +/library/std/array/replaceFirst.html /library/std/array/replace_first.html +/library/std/array/replaceInPlace.html /library/std/array/replace_in_place.html +/library/std/array/replaceInto.html /library/std/array/replace_into.html +/library/std/array/replaceLast.html /library/std/array/replace_last.html +/library/std/array/replaceSlice.html /library/std/array/replace_slice.html +/library/std/array/sameHead.html /library/std/array/same_head.html +/library/std/array/sameTail.html /library/std/array/same_tail.html +/library/std/array/uninitializedArray.html /library/std/array/uninitialized_array.html +/library/std/ascii/fullHexDigits.html /library/std/ascii/full_hex_digits.html +/library/std/ascii/hexDigits.html /library/std/ascii/hex_digits.html +/library/std/ascii/isAlpha.html /library/std/ascii/is_alpha.html +/library/std/ascii/isAlphaNum.html /library/std/ascii/is_alpha_num.html +/library/std/ascii/isASCII.html /library/std/ascii/is_ascii.html +/library/std/ascii/isControl.html /library/std/ascii/is_control.html +/library/std/ascii/isDigit.html /library/std/ascii/is_digit.html +/library/std/ascii/isGraphical.html /library/std/ascii/is_graphical.html +/library/std/ascii/isHexDigit.html /library/std/ascii/is_hex_digit.html +/library/std/ascii/isLower.html /library/std/ascii/is_lower.html +/library/std/ascii/isOctalDigit.html /library/std/ascii/is_octal_digit.html +/library/std/ascii/isPrintable.html /library/std/ascii/is_printable.html +/library/std/ascii/isPunctuation.html /library/std/ascii/is_punctuation.html +/library/std/ascii/isUpper.html /library/std/ascii/is_upper.html +/library/std/ascii/isWhite.html /library/std/ascii/is_white.html +/library/std/ascii/LetterCase.html /library/std/ascii/letter_case.html +/library/std/ascii/LetterCase.lower.html /library/std/ascii/letter_case.lower.html +/library/std/ascii/LetterCase.upper.html /library/std/ascii/letter_case.upper.html +/library/std/ascii/lowerHexDigits.html /library/std/ascii/lower_hex_digits.html +/library/std/ascii/octalDigits.html /library/std/ascii/octal_digits.html +/library/std/ascii/toLower.html /library/std/ascii/to_lower.html +/library/std/ascii/toUpper.html /library/std/ascii/to_upper.html +/library/std/base64/Base64Exception.html /library/std/base64/base64_exception.html +/library/std/base64/Base64.html /library/std/base64/base64.html +/library/std/base64/Base64Impl.decode.html /library/std/base64/base64_impl.decode.html +/library/std/base64/Base64Impl.decodeLength.html /library/std/base64/base64_impl.decode_length.html +/library/std/base64/Base64Impl.Decoder.empty.html /library/std/base64/base64_impl.decoder.empty.html +/library/std/base64/Base64Impl.Decoder.front.html /library/std/base64/base64_impl.decoder.front.html +/library/std/base64/Base64Impl.decoder.html /library/std/base64/base64_impl.decoder.html +/library/std/base64/Base64Impl.Decoder.html /library/std/base64/base64_impl.decoder.html +/library/std/base64/Base64Impl.Decoder.popFront.html /library/std/base64/base64_impl.decoder.pop_front.html +/library/std/base64/Base64Impl.encode.html /library/std/base64/base64_impl.encode.html +/library/std/base64/Base64Impl.encodeLength.html /library/std/base64/base64_impl.encode_length.html +/library/std/base64/Base64Impl.Encoder.empty.html /library/std/base64/base64_impl.encoder.empty.html +/library/std/base64/Base64Impl.Encoder.front.html /library/std/base64/base64_impl.encoder.front.html +/library/std/base64/Base64Impl.encoder.html /library/std/base64/base64_impl.encoder.html +/library/std/base64/Base64Impl.Encoder.html /library/std/base64/base64_impl.encoder.html +/library/std/base64/Base64Impl.Encoder.popFront.html /library/std/base64/base64_impl.encoder.pop_front.html +/library/std/base64/Base64Impl.html /library/std/base64/base64_impl.html +/library/std/base64/Base64Impl.NoPadding.html /library/std/base64/base64_impl.no_padding.html +/library/std/base64/Base64URL.html /library/std/base64/base64_url.html +/library/std/base64/Object.factory.html /library/std/base64/object.factory.html +/library/std/base64/Object.opCmp.html /library/std/base64/object.op_cmp.html +/library/std/base64/Object.opEquals.html /library/std/base64/object.op_equals.html +/library/std/base64/Object.toHash.html /library/std/base64/object.to_hash.html +/library/std/base64/Throwable.file.html /library/std/base64/throwable.file.html +/library/std/base64/Throwable.info.html /library/std/base64/throwable.info.html +/library/std/base64/Throwable.line.html /library/std/base64/throwable.line.html +/library/std/base64/Throwable.msg.html /library/std/base64/throwable.msg.html +/library/std/base64/Throwable.next.html /library/std/base64/throwable.next.html +/library/std/base64/Throwable.toString.html /library/std/base64/throwable.to_string.html +/library/std/bigint/absUnsign.html /library/std/bigint/abs_unsign.html +/library/std/bigint/BigInt.html /library/std/bigint/big_int.html +/library/std/bigint/BigInt.this.html /library/std/bigint/big_int.this.html +/library/std/bigint/BigInt.toInt.html /library/std/bigint/big_int.to_int.html +/library/std/bigint/BigInt.toLong.html /library/std/bigint/big_int.to_long.html +/library/std/bigint/BigInt.toString.html /library/std/bigint/big_int.to_string.html +/library/std/bigint/BigInt.uintLength.html /library/std/bigint/big_int.uint_length.html +/library/std/bigint/BigInt.ulongLength.html /library/std/bigint/big_int.ulong_length.html +/library/std/bigint/toDecimalString.html /library/std/bigint/to_decimal_string.html +/library/std/bigint/toHex.html /library/std/bigint/to_hex.html +/library/std/bitmanip/bigEndianToNative.html /library/std/bitmanip/big_endian_to_native.html +/library/std/bitmanip/BitArray.bitsSet.html /library/std/bitmanip/bit_array.bits_set.html +/library/std/bitmanip/BitArray.dim.html /library/std/bitmanip/bit_array.dim.html +/library/std/bitmanip/BitArray.dup.html /library/std/bitmanip/bit_array.dup.html +/library/std/bitmanip/BitArray.html /library/std/bitmanip/bit_array.html +/library/std/bitmanip/BitArray.init.html /library/std/bitmanip/bit_array.init.html +/library/std/bitmanip/BitArray.length.html /library/std/bitmanip/bit_array.length.html +/library/std/bitmanip/BitArray.opApply.html /library/std/bitmanip/bit_array.op_apply.html +/library/std/bitmanip/BitArray.opBinary.html /library/std/bitmanip/bit_array.op_binary.html +/library/std/bitmanip/BitArray.opCast.html /library/std/bitmanip/bit_array.op_cast.html +/library/std/bitmanip/BitArray.opCatAssign.html /library/std/bitmanip/bit_array.op_cat_assign.html +/library/std/bitmanip/BitArray.opCat.html /library/std/bitmanip/bit_array.op_cat.html +/library/std/bitmanip/BitArray.opCat_r.html /library/std/bitmanip/bit_array.op_cat_r.html +/library/std/bitmanip/BitArray.opCmp.html /library/std/bitmanip/bit_array.op_cmp.html +/library/std/bitmanip/BitArray.opCom.html /library/std/bitmanip/bit_array.op_com.html +/library/std/bitmanip/BitArray.opEquals.html /library/std/bitmanip/bit_array.op_equals.html +/library/std/bitmanip/BitArray.opIndexAssign.html /library/std/bitmanip/bit_array.op_index_assign.html +/library/std/bitmanip/BitArray.opIndex.html /library/std/bitmanip/bit_array.op_index.html +/library/std/bitmanip/BitArray.opOpAssign.html /library/std/bitmanip/bit_array.op_op_assign.html +/library/std/bitmanip/BitArray.reverse.html /library/std/bitmanip/bit_array.reverse.html +/library/std/bitmanip/BitArray.sort.html /library/std/bitmanip/bit_array.sort.html +/library/std/bitmanip/BitArray.this.html /library/std/bitmanip/bit_array.this.html +/library/std/bitmanip/BitArray.toHash.html /library/std/bitmanip/bit_array.to_hash.html +/library/std/bitmanip/BitArray.toString.html /library/std/bitmanip/bit_array.to_string.html +/library/std/bitmanip/bitsSet.html /library/std/bitmanip/bits_set.html +/library/std/bitmanip/DoubleRep.html /library/std/bitmanip/double_rep.html +/library/std/bitmanip/FloatRep.html /library/std/bitmanip/float_rep.html +/library/std/bitmanip/littleEndianToNative.html /library/std/bitmanip/little_endian_to_native.html +/library/std/bitmanip/nativeToBigEndian.html /library/std/bitmanip/native_to_big_endian.html +/library/std/bitmanip/nativeToLittleEndian.html /library/std/bitmanip/native_to_little_endian.html +/library/std/bitmanip/swapEndian.html /library/std/bitmanip/swap_endian.html +/library/std/bitmanip/taggedClassRef.html /library/std/bitmanip/tagged_class_ref.html +/library/std/bitmanip/taggedPointer.html /library/std/bitmanip/tagged_pointer.html +/library/std/compiler/D_major.html /library/std/compiler/d_major.html +/library/std/compiler/Vendor.digitalMars.html /library/std/compiler/vendor.digital_mars.html +/library/std/compiler/Vendor.dotNET.html /library/std/compiler/vendor.dot_net.html +/library/std/compiler/Vendor.gnu.html /library/std/compiler/vendor.gnu.html +/library/std/compiler/Vendor.html /library/std/compiler/vendor.html +/library/std/compiler/Vendor.llvm.html /library/std/compiler/vendor.llvm.html +/library/std/compiler/Vendor.sdc.html /library/std/compiler/vendor.sdc.html +/library/std/compiler/Vendor.unknown.html /library/std/compiler/vendor.unknown.html +/library/std/complex/Complex.html /library/std/complex/complex.html +/library/std/complex/Complex.im.html /library/std/complex/complex.im.html +/library/std/complex/Complex.re.html /library/std/complex/complex.re.html +/library/std/complex/Complex.toString.html /library/std/complex/complex.to_string.html +/library/std/complex/Complex.toString.toString.html /library/std/complex/complex.to_string.to_string.html +/library/std/complex/fromPolar.html /library/std/complex/from_polar.html +/library/std/complex/sqAbs.html /library/std/complex/sq_abs.html +/library/std/concurrency/FiberScheduler.html /library/std/concurrency/fiber_scheduler.html +/library/std/concurrency/FiberScheduler.newCondition.html /library/std/concurrency/fiber_scheduler.new_condition.html +/library/std/concurrency/FiberScheduler.spawn.html /library/std/concurrency/fiber_scheduler.spawn.html +/library/std/concurrency/FiberScheduler.start.html /library/std/concurrency/fiber_scheduler.start.html +/library/std/concurrency/FiberScheduler.thisInfo.html /library/std/concurrency/fiber_scheduler.this_info.html +/library/std/concurrency/FiberScheduler.yield.html /library/std/concurrency/fiber_scheduler.yield.html +/library/std/concurrency/Generator.empty.html /library/std/concurrency/generator.empty.html +/library/std/concurrency/Generator.front.html /library/std/concurrency/generator.front.html +/library/std/concurrency/Generator.html /library/std/concurrency/generator.html +/library/std/concurrency/Generator.popFront.html /library/std/concurrency/generator.pop_front.html +/library/std/concurrency/Generator.this.html /library/std/concurrency/generator.this.html +/library/std/concurrency/initOnce.html /library/std/concurrency/init_once.html +/library/std/concurrency/LinkTerminated.html /library/std/concurrency/link_terminated.html +/library/std/concurrency/MailboxFull.html /library/std/concurrency/mailbox_full.html +/library/std/concurrency/MessageMismatch.html /library/std/concurrency/message_mismatch.html +/library/std/concurrency/Object.factory.html /library/std/concurrency/object.factory.html +/library/std/concurrency/Object.opCmp.html /library/std/concurrency/object.op_cmp.html +/library/std/concurrency/Object.opEquals.html /library/std/concurrency/object.op_equals.html +/library/std/concurrency/Object.toHash.html /library/std/concurrency/object.to_hash.html +/library/std/concurrency/Object.toString.html /library/std/concurrency/object.to_string.html +/library/std/concurrency/OnCrowding.block.html /library/std/concurrency/on_crowding.block.html +/library/std/concurrency/OnCrowding.html /library/std/concurrency/on_crowding.html +/library/std/concurrency/OnCrowding.ignore.html /library/std/concurrency/on_crowding.ignore.html +/library/std/concurrency/OnCrowding.throwException.html /library/std/concurrency/on_crowding.throw_exception.html +/library/std/concurrency/OwnerTerminated.html /library/std/concurrency/owner_terminated.html +/library/std/concurrency/ownerTid.html /library/std/concurrency/owner_tid.html +/library/std/concurrency/PriorityMessageException.html /library/std/concurrency/priority_message_exception.html +/library/std/concurrency/PriorityMessageException.message.html /library/std/concurrency/priority_message_exception.message.html +/library/std/concurrency/prioritySend.html /library/std/concurrency/priority_send.html +/library/std/concurrency/receiveOnly.html /library/std/concurrency/receive_only.html +/library/std/concurrency/receiveTimeout.html /library/std/concurrency/receive_timeout.html +/library/std/concurrency/Scheduler.html /library/std/concurrency/scheduler.html +/library/std/concurrency/Scheduler.newCondition.html /library/std/concurrency/scheduler.new_condition.html +/library/std/concurrency/Scheduler.spawn.html /library/std/concurrency/scheduler.spawn.html +/library/std/concurrency/Scheduler.start.html /library/std/concurrency/scheduler.start.html +/library/std/concurrency/Scheduler.thisInfo.html /library/std/concurrency/scheduler.this_info.html +/library/std/concurrency/Scheduler.yield.html /library/std/concurrency/scheduler.yield.html +/library/std/concurrency/setMaxMailboxSize.html /library/std/concurrency/set_max_mailbox_size.html +/library/std/concurrency/spawnLinked.html /library/std/concurrency/spawn_linked.html +/library/std/concurrency/thisTid.html /library/std/concurrency/this_tid.html +/library/std/concurrency/ThreadInfo.cleanup.html /library/std/concurrency/thread_info.cleanup.html +/library/std/concurrency/ThreadInfo.html /library/std/concurrency/thread_info.html +/library/std/concurrency/ThreadInfo.thisInfo.html /library/std/concurrency/thread_info.this_info.html +/library/std/concurrency/ThreadScheduler.html /library/std/concurrency/thread_scheduler.html +/library/std/concurrency/ThreadScheduler.newCondition.html /library/std/concurrency/thread_scheduler.new_condition.html +/library/std/concurrency/ThreadScheduler.spawn.html /library/std/concurrency/thread_scheduler.spawn.html +/library/std/concurrency/ThreadScheduler.start.html /library/std/concurrency/thread_scheduler.start.html +/library/std/concurrency/ThreadScheduler.thisInfo.html /library/std/concurrency/thread_scheduler.this_info.html +/library/std/concurrency/ThreadScheduler.yield.html /library/std/concurrency/thread_scheduler.yield.html +/library/std/concurrency/Throwable.file.html /library/std/concurrency/throwable.file.html +/library/std/concurrency/Throwable.info.html /library/std/concurrency/throwable.info.html +/library/std/concurrency/Throwable.line.html /library/std/concurrency/throwable.line.html +/library/std/concurrency/Throwable.msg.html /library/std/concurrency/throwable.msg.html +/library/std/concurrency/Throwable.next.html /library/std/concurrency/throwable.next.html +/library/std/concurrency/Throwable.toString.html /library/std/concurrency/throwable.to_string.html +/library/std/concurrency/Tid.html /library/std/concurrency/tid.html +/library/std/concurrency/TidMissingException.html /library/std/concurrency/tid_missing_exception.html +/library/std/concurrency/Tid.toString.html /library/std/concurrency/tid.to_string.html +/library/std/container/array/Array.back.html /library/std/container/array/array.back.html +/library/std/container/array/Array.capacity.html /library/std/container/array/array.capacity.html +/library/std/container/array/Array.clear.html /library/std/container/array/array.clear.html +/library/std/container/array/Array.ConstRange.html /library/std/container/array/array.const_range.html +/library/std/container/array/Array.dup.html /library/std/container/array/array.dup.html +/library/std/container/array/Array.empty.html /library/std/container/array/array.empty.html +/library/std/container/array/Array.front.html /library/std/container/array/array.front.html +/library/std/container/array/Array.html /library/std/container/array/array.html +/library/std/container/array/Array.ImmutableRange.html /library/std/container/array/array.immutable_range.html +/library/std/container/array/Array.insertAfter.html /library/std/container/array/array.insert_after.html +/library/std/container/array/Array.insertAfter.insertAfter.html /library/std/container/array/array.insert_after.insert_after.html +/library/std/container/array/Array.insertBack.html /library/std/container/array/array.insert_back.html +/library/std/container/array/Array.insertBack.insertBack.html /library/std/container/array/array.insert_back.insert_back.html +/library/std/container/array/Array.insertBefore.html /library/std/container/array/array.insert_before.html +/library/std/container/array/Array.insertBefore.insertBefore.html /library/std/container/array/array.insert_before.insert_before.html +/library/std/container/array/Array.insert.html /library/std/container/array/array.insert.html +/library/std/container/array/Array.length.html /library/std/container/array/array.length.html +/library/std/container/array/Array.linearInsert.html /library/std/container/array/array.linear_insert.html +/library/std/container/array/Array.linearRemove.html /library/std/container/array/array.linear_remove.html +/library/std/container/array/Array.moveAt.html /library/std/container/array/array.move_at.html +/library/std/container/array/Array.opBinary.html /library/std/container/array/array.op_binary.html +/library/std/container/array/Array.opBinary.opBinary.html /library/std/container/array/array.op_binary.op_binary.html +/library/std/container/array/Array.opDollar.html /library/std/container/array/array.op_dollar.html +/library/std/container/array/Array.opEquals.html /library/std/container/array/array.op_equals.html +/library/std/container/array/Array.opIndexAssign.html /library/std/container/array/array.op_index_assign.html +/library/std/container/array/Array.opIndex.html /library/std/container/array/array.op_index.html +/library/std/container/array/Array.opIndexOpAssign.html /library/std/container/array/array.op_index_op_assign.html +/library/std/container/array/Array.opIndexOpAssign.opIndexOpAssign.html /library/std/container/array/array.op_index_op_assign.op_index_op_assign.html +/library/std/container/array/Array.opOpAssign.html /library/std/container/array/array.op_op_assign.html +/library/std/container/array/Array.opOpAssign.opOpAssign.html /library/std/container/array/array.op_op_assign.op_op_assign.html +/library/std/container/array/Array.opSliceAssign.html /library/std/container/array/array.op_slice_assign.html +/library/std/container/array/Array.opSlice.html /library/std/container/array/array.op_slice.html +/library/std/container/array/Array.opSliceOpAssign.html /library/std/container/array/array.op_slice_op_assign.html +/library/std/container/array/Array.opSliceOpAssign.opSliceOpAssign.html /library/std/container/array/array.op_slice_op_assign.op_slice_op_assign.html +/library/std/container/array/Array.opSliceUnary.html /library/std/container/array/array.op_slice_unary.html +/library/std/container/array/Array.opSliceUnary.opSliceUnary.html /library/std/container/array/array.op_slice_unary.op_slice_unary.html +/library/std/container/array/Array.Range.back.html /library/std/container/array/array.range.back.html +/library/std/container/array/Array.Range.empty.html /library/std/container/array/array.range.empty.html +/library/std/container/array/Array.Range.front.html /library/std/container/array/array.range.front.html +/library/std/container/array/Array.Range.html /library/std/container/array/array.range.html +/library/std/container/array/Array.Range.length.html /library/std/container/array/array.range.length.html +/library/std/container/array/Array.Range.moveAt.html /library/std/container/array/array.range.move_at.html +/library/std/container/array/Array.Range.moveBack.html /library/std/container/array/array.range.move_back.html +/library/std/container/array/Array.Range.moveFront.html /library/std/container/array/array.range.move_front.html +/library/std/container/array/Array.Range.opIndexAssign.html /library/std/container/array/array.range.op_index_assign.html +/library/std/container/array/Array.Range.opIndex.html /library/std/container/array/array.range.op_index.html +/library/std/container/array/Array.Range.opSlice.html /library/std/container/array/array.range.op_slice.html +/library/std/container/array/Array.Range.popBack.html /library/std/container/array/array.range.pop_back.html +/library/std/container/array/Array.Range.popFront.html /library/std/container/array/array.range.pop_front.html +/library/std/container/array/Array.Range.save.html /library/std/container/array/array.range.save.html +/library/std/container/array/Array.removeAny.html /library/std/container/array/array.remove_any.html +/library/std/container/array/Array.removeBack.html /library/std/container/array/array.remove_back.html +/library/std/container/array/Array.replace.html /library/std/container/array/array.replace.html +/library/std/container/array/Array.replace.replace.html /library/std/container/array/array.replace.replace.html +/library/std/container/array/Array.reserve.html /library/std/container/array/array.reserve.html +/library/std/container/array/Array.stableInsertAfter.html /library/std/container/array/array.stable_insert_after.html +/library/std/container/array/Array.stableInsertBack.html /library/std/container/array/array.stable_insert_back.html +/library/std/container/array/Array.stableInsertBefore.html /library/std/container/array/array.stable_insert_before.html +/library/std/container/array/Array.stableInsert.html /library/std/container/array/array.stable_insert.html +/library/std/container/array/Array.stableLinearInsert.html /library/std/container/array/array.stable_linear_insert.html +/library/std/container/array/Array.stableRemoveAny.html /library/std/container/array/array.stable_remove_any.html +/library/std/container/array/Array.stableRemoveBack.html /library/std/container/array/array.stable_remove_back.html +/library/std/container/array/Array.stableReplace.html /library/std/container/array/array.stable_replace.html +/library/std/container/array/Array.this.html /library/std/container/array/array.this.html +/library/std/container/array/Array.this.this.html /library/std/container/array/array.this.this.html +/library/std/container/binaryheap/BinaryHeap.acquire.html /library/std/container/binaryheap/binary_heap.acquire.html +/library/std/container/binaryheap/BinaryHeap.assume.html /library/std/container/binaryheap/binary_heap.assume.html +/library/std/container/binaryheap/BinaryHeap.capacity.html /library/std/container/binaryheap/binary_heap.capacity.html +/library/std/container/binaryheap/BinaryHeap.clear.html /library/std/container/binaryheap/binary_heap.clear.html +/library/std/container/binaryheap/BinaryHeap.conditionalInsert.html /library/std/container/binaryheap/binary_heap.conditional_insert.html +/library/std/container/binaryheap/BinaryHeap.dup.html /library/std/container/binaryheap/binary_heap.dup.html +/library/std/container/binaryheap/BinaryHeap.empty.html /library/std/container/binaryheap/binary_heap.empty.html +/library/std/container/binaryheap/BinaryHeap.front.html /library/std/container/binaryheap/binary_heap.front.html +/library/std/container/binaryheap/BinaryHeap.html /library/std/container/binaryheap/binary_heap.html +/library/std/container/binaryheap/BinaryHeap.insert.html /library/std/container/binaryheap/binary_heap.insert.html +/library/std/container/binaryheap/BinaryHeap.length.html /library/std/container/binaryheap/binary_heap.length.html +/library/std/container/binaryheap/BinaryHeap.popFront.html /library/std/container/binaryheap/binary_heap.pop_front.html +/library/std/container/binaryheap/BinaryHeap.release.html /library/std/container/binaryheap/binary_heap.release.html +/library/std/container/binaryheap/BinaryHeap.removeAny.html /library/std/container/binaryheap/binary_heap.remove_any.html +/library/std/container/binaryheap/BinaryHeap.removeFront.html /library/std/container/binaryheap/binary_heap.remove_front.html +/library/std/container/binaryheap/BinaryHeap.replaceFront.html /library/std/container/binaryheap/binary_heap.replace_front.html +/library/std/container/binaryheap/BinaryHeap.this.html /library/std/container/binaryheap/binary_heap.this.html +/library/std/container/dlist/DList.back.html /library/std/container/dlist/d_list.back.html +/library/std/container/dlist/DList.clear.html /library/std/container/dlist/d_list.clear.html +/library/std/container/dlist/DList.dup.html /library/std/container/dlist/d_list.dup.html +/library/std/container/dlist/DList.empty.html /library/std/container/dlist/d_list.empty.html +/library/std/container/dlist/DList.front.html /library/std/container/dlist/d_list.front.html +/library/std/container/dlist/DList.html /library/std/container/dlist/d_list.html +/library/std/container/dlist/DList.insertAfter.html /library/std/container/dlist/d_list.insert_after.html +/library/std/container/dlist/DList.insertAfter.insertAfter.html /library/std/container/dlist/d_list.insert_after.insert_after.html +/library/std/container/dlist/DList.insertBack.html /library/std/container/dlist/d_list.insert_back.html +/library/std/container/dlist/DList.insertBack.insertBack.html /library/std/container/dlist/d_list.insert_back.insert_back.html +/library/std/container/dlist/DList.insertBefore.html /library/std/container/dlist/d_list.insert_before.html +/library/std/container/dlist/DList.insertBefore.insertBefore.html /library/std/container/dlist/d_list.insert_before.insert_before.html +/library/std/container/dlist/DList.insertFront.html /library/std/container/dlist/d_list.insert_front.html +/library/std/container/dlist/DList.insertFront.insertFront.html /library/std/container/dlist/d_list.insert_front.insert_front.html +/library/std/container/dlist/DList.insert.html /library/std/container/dlist/d_list.insert.html +/library/std/container/dlist/DList.linearRemove.html /library/std/container/dlist/d_list.linear_remove.html +/library/std/container/dlist/DList.opBinary.html /library/std/container/dlist/d_list.op_binary.html +/library/std/container/dlist/DList.opBinary.opBinary.html /library/std/container/dlist/d_list.op_binary.op_binary.html +/library/std/container/dlist/DList.opBinaryRight.html /library/std/container/dlist/d_list.op_binary_right.html +/library/std/container/dlist/DList.opBinaryRight.opBinaryRight.html /library/std/container/dlist/d_list.op_binary_right.op_binary_right.html +/library/std/container/dlist/DList.opEquals.html /library/std/container/dlist/d_list.op_equals.html +/library/std/container/dlist/DList.opEquals.opEquals.html /library/std/container/dlist/d_list.op_equals.op_equals.html +/library/std/container/dlist/DList.opOpAssign.html /library/std/container/dlist/d_list.op_op_assign.html +/library/std/container/dlist/DList.opOpAssign.opOpAssign.html /library/std/container/dlist/d_list.op_op_assign.op_op_assign.html +/library/std/container/dlist/DList.opSlice.html /library/std/container/dlist/d_list.op_slice.html +/library/std/container/dlist/DList.Range.html /library/std/container/dlist/d_list.range.html +/library/std/container/dlist/DList.removeAny.html /library/std/container/dlist/d_list.remove_any.html +/library/std/container/dlist/DList.removeBack.html /library/std/container/dlist/d_list.remove_back.html +/library/std/container/dlist/DList.removeFront.html /library/std/container/dlist/d_list.remove_front.html +/library/std/container/dlist/DList.remove.html /library/std/container/dlist/d_list.remove.html +/library/std/container/dlist/DList.stableInsertAfter.html /library/std/container/dlist/d_list.stable_insert_after.html +/library/std/container/dlist/DList.stableInsertBack.html /library/std/container/dlist/d_list.stable_insert_back.html +/library/std/container/dlist/DList.stableInsertBefore.html /library/std/container/dlist/d_list.stable_insert_before.html +/library/std/container/dlist/DList.stableInsertFront.html /library/std/container/dlist/d_list.stable_insert_front.html +/library/std/container/dlist/DList.stableInsert.html /library/std/container/dlist/d_list.stable_insert.html +/library/std/container/dlist/DList.stableLinearRemove.html /library/std/container/dlist/d_list.stable_linear_remove.html +/library/std/container/dlist/DList.stableRemoveAny.html /library/std/container/dlist/d_list.stable_remove_any.html +/library/std/container/dlist/DList.stableRemoveBack.html /library/std/container/dlist/d_list.stable_remove_back.html +/library/std/container/dlist/DList.stableRemoveFront.html /library/std/container/dlist/d_list.stable_remove_front.html +/library/std/container/dlist/DList.stableRemove.html /library/std/container/dlist/d_list.stable_remove.html +/library/std/container/dlist/DList.this.html /library/std/container/dlist/d_list.this.html +/library/std/container/dlist/DList.this.this.html /library/std/container/dlist/d_list.this.this.html +/library/std/container/rbtree/Object.factory.html /library/std/container/rbtree/object.factory.html +/library/std/container/rbtree/Object.opCmp.html /library/std/container/rbtree/object.op_cmp.html +/library/std/container/rbtree/Object.toHash.html /library/std/container/rbtree/object.to_hash.html +/library/std/container/rbtree/Object.toString.html /library/std/container/rbtree/object.to_string.html +/library/std/container/rbtree/RedBlackTree.back.html /library/std/container/rbtree/red_black_tree.back.html +/library/std/container/rbtree/RedBlackTree.clear.html /library/std/container/rbtree/red_black_tree.clear.html +/library/std/container/rbtree/RedBlackTree.dup.html /library/std/container/rbtree/red_black_tree.dup.html +/library/std/container/rbtree/RedBlackTree.Elem.html /library/std/container/rbtree/red_black_tree.elem.html +/library/std/container/rbtree/RedBlackTree.empty.html /library/std/container/rbtree/red_black_tree.empty.html +/library/std/container/rbtree/RedBlackTree.equalRange.html /library/std/container/rbtree/red_black_tree.equal_range.html +/library/std/container/rbtree/RedBlackTree.front.html /library/std/container/rbtree/red_black_tree.front.html +/library/std/container/rbtree/redBlackTree.html /library/std/container/rbtree/red_black_tree.html +/library/std/container/rbtree/RedBlackTree.html /library/std/container/rbtree/red_black_tree.html +/library/std/container/rbtree/RedBlackTree.insert.html /library/std/container/rbtree/red_black_tree.insert.html +/library/std/container/rbtree/RedBlackTree.length.html /library/std/container/rbtree/red_black_tree.length.html +/library/std/container/rbtree/RedBlackTree.lowerBound.html /library/std/container/rbtree/red_black_tree.lower_bound.html +/library/std/container/rbtree/RedBlackTree.opBinaryRight.html /library/std/container/rbtree/red_black_tree.op_binary_right.html +/library/std/container/rbtree/RedBlackTree.opBinaryRight.opBinaryRight.html /library/std/container/rbtree/red_black_tree.op_binary_right.op_binary_right.html +/library/std/container/rbtree/RedBlackTree.opEquals.html /library/std/container/rbtree/red_black_tree.op_equals.html +/library/std/container/rbtree/RedBlackTree.opSlice.html /library/std/container/rbtree/red_black_tree.op_slice.html +/library/std/container/rbtree/RedBlackTree.Range.back.html /library/std/container/rbtree/red_black_tree.range.back.html +/library/std/container/rbtree/RedBlackTree.Range.empty.html /library/std/container/rbtree/red_black_tree.range.empty.html +/library/std/container/rbtree/RedBlackTree.Range.front.html /library/std/container/rbtree/red_black_tree.range.front.html +/library/std/container/rbtree/RedBlackTree.Range.html /library/std/container/rbtree/red_black_tree.range.html +/library/std/container/rbtree/RedBlackTree.Range.popBack.html /library/std/container/rbtree/red_black_tree.range.pop_back.html +/library/std/container/rbtree/RedBlackTree.Range.popFront.html /library/std/container/rbtree/red_black_tree.range.pop_front.html +/library/std/container/rbtree/RedBlackTree.Range.save.html /library/std/container/rbtree/red_black_tree.range.save.html +/library/std/container/rbtree/RedBlackTree.removeAny.html /library/std/container/rbtree/red_black_tree.remove_any.html +/library/std/container/rbtree/RedBlackTree.removeBack.html /library/std/container/rbtree/red_black_tree.remove_back.html +/library/std/container/rbtree/RedBlackTree.removeFront.html /library/std/container/rbtree/red_black_tree.remove_front.html +/library/std/container/rbtree/RedBlackTree.remove.html /library/std/container/rbtree/red_black_tree.remove.html +/library/std/container/rbtree/RedBlackTree.removeKey.html /library/std/container/rbtree/red_black_tree.remove_key.html +/library/std/container/rbtree/RedBlackTree.removeKey.removeKey.html /library/std/container/rbtree/red_black_tree.remove_key.remove_key.html +/library/std/container/rbtree/RedBlackTree.stableInsert.html /library/std/container/rbtree/red_black_tree.stable_insert.html +/library/std/container/rbtree/RedBlackTree.stableInsert.stableInsert.html /library/std/container/rbtree/red_black_tree.stable_insert.stable_insert.html +/library/std/container/rbtree/RedBlackTree.this.html /library/std/container/rbtree/red_black_tree.this.html +/library/std/container/rbtree/RedBlackTree.this.this.html /library/std/container/rbtree/red_black_tree.this.this.html +/library/std/container/rbtree/RedBlackTree.upperBound.html /library/std/container/rbtree/red_black_tree.upper_bound.html +/library/std/container/slist/SList.clear.html /library/std/container/slist/s_list.clear.html +/library/std/container/slist/SList.dup.html /library/std/container/slist/s_list.dup.html +/library/std/container/slist/SList.empty.html /library/std/container/slist/s_list.empty.html +/library/std/container/slist/SList.front.html /library/std/container/slist/s_list.front.html +/library/std/container/slist/SList.html /library/std/container/slist/s_list.html +/library/std/container/slist/SList.insertAfter.html /library/std/container/slist/s_list.insert_after.html +/library/std/container/slist/SList.insertAfter.insertAfter.html /library/std/container/slist/s_list.insert_after.insert_after.html +/library/std/container/slist/SList.insertFront.html /library/std/container/slist/s_list.insert_front.html +/library/std/container/slist/SList.insertFront.insertFront.html /library/std/container/slist/s_list.insert_front.insert_front.html +/library/std/container/slist/SList.insert.html /library/std/container/slist/s_list.insert.html +/library/std/container/slist/SList.linearRemove.html /library/std/container/slist/s_list.linear_remove.html +/library/std/container/slist/SList.opBinary.html /library/std/container/slist/s_list.op_binary.html +/library/std/container/slist/SList.opBinary.opBinary.html /library/std/container/slist/s_list.op_binary.op_binary.html +/library/std/container/slist/SList.opBinaryRight.html /library/std/container/slist/s_list.op_binary_right.html +/library/std/container/slist/SList.opBinaryRight.opBinaryRight.html /library/std/container/slist/s_list.op_binary_right.op_binary_right.html +/library/std/container/slist/SList.opEquals.html /library/std/container/slist/s_list.op_equals.html +/library/std/container/slist/SList.opSlice.html /library/std/container/slist/s_list.op_slice.html +/library/std/container/slist/SList.Range.empty.html /library/std/container/slist/s_list.range.empty.html +/library/std/container/slist/SList.Range.front.html /library/std/container/slist/s_list.range.front.html +/library/std/container/slist/SList.Range.html /library/std/container/slist/s_list.range.html +/library/std/container/slist/SList.Range.popFront.html /library/std/container/slist/s_list.range.pop_front.html +/library/std/container/slist/SList.Range.save.html /library/std/container/slist/s_list.range.save.html +/library/std/container/slist/SList.removeAny.html /library/std/container/slist/s_list.remove_any.html +/library/std/container/slist/SList.removeFront.html /library/std/container/slist/s_list.remove_front.html +/library/std/container/slist/SList.stableInsertAfter.html /library/std/container/slist/s_list.stable_insert_after.html +/library/std/container/slist/SList.stableInsertFront.html /library/std/container/slist/s_list.stable_insert_front.html +/library/std/container/slist/SList.stableInsert.html /library/std/container/slist/s_list.stable_insert.html +/library/std/container/slist/SList.stableLinearRemove.html /library/std/container/slist/s_list.stable_linear_remove.html +/library/std/container/slist/SList.stableRemoveAny.html /library/std/container/slist/s_list.stable_remove_any.html +/library/std/container/slist/SList.stableRemoveFront.html /library/std/container/slist/s_list.stable_remove_front.html +/library/std/container/slist/SList.this.html /library/std/container/slist/s_list.this.html +/library/std/container/slist/SList.this.this.html /library/std/container/slist/s_list.this.this.html +/library/std/conv/castFrom.html /library/std/conv/cast_from.html +/library/std/conv/ConvException.html /library/std/conv/conv_exception.html +/library/std/conv/ConvOverflowException.html /library/std/conv/conv_overflow_exception.html +/library/std/conv/Object.factory.html /library/std/conv/object.factory.html +/library/std/conv/Object.opCmp.html /library/std/conv/object.op_cmp.html +/library/std/conv/Object.opEquals.html /library/std/conv/object.op_equals.html +/library/std/conv/Object.toHash.html /library/std/conv/object.to_hash.html +/library/std/conv/roundTo.html /library/std/conv/round_to.html +/library/std/conv/roundTo.roundTo.html /library/std/conv/round_to.round_to.html +/library/std/conv/Throwable.file.html /library/std/conv/throwable.file.html +/library/std/conv/Throwable.info.html /library/std/conv/throwable.info.html +/library/std/conv/Throwable.line.html /library/std/conv/throwable.line.html +/library/std/conv/Throwable.msg.html /library/std/conv/throwable.msg.html +/library/std/conv/Throwable.next.html /library/std/conv/throwable.next.html +/library/std/conv/Throwable.toString.html /library/std/conv/throwable.to_string.html +/library/std/conv/toImpl.html /library/std/conv/to_impl.html +/library/std/cstream/CFile.close.html /library/std/cstream/c_file.close.html +/library/std/cstream/CFile.eof.html /library/std/cstream/c_file.eof.html +/library/std/cstream/CFile.file.html /library/std/cstream/c_file.file.html +/library/std/cstream/CFile.flush.html /library/std/cstream/c_file.flush.html +/library/std/cstream/CFile.getc.html /library/std/cstream/c_file.getc.html +/library/std/cstream/CFile.html /library/std/cstream/c_file.html +/library/std/cstream/CFile.readBlock.html /library/std/cstream/c_file.read_block.html +/library/std/cstream/CFile.seek.html /library/std/cstream/c_file.seek.html +/library/std/cstream/CFile.this.html /library/std/cstream/c_file.this.html +/library/std/cstream/CFile.ungetc.html /library/std/cstream/c_file.ungetc.html +/library/std/cstream/CFile.writeBlock.html /library/std/cstream/c_file.write_block.html +/library/std/cstream/CFile.writeLine.html /library/std/cstream/c_file.write_line.html +/library/std/cstream/CFile.writeLineW.html /library/std/cstream/c_file.write_line.html +/library/std/cstream/InputStream.available.html /library/std/cstream/input_stream.available.html +/library/std/cstream/InputStream.eof.html /library/std/cstream/input_stream.eof.html +/library/std/cstream/InputStream.getcw.html /library/std/cstream/input_stream.getcw.html +/library/std/cstream/InputStream.isOpen.html /library/std/cstream/input_stream.is_open.html +/library/std/cstream/InputStream.opApply.html /library/std/cstream/input_stream.op_apply.html +/library/std/cstream/InputStream.readExact.html /library/std/cstream/input_stream.read_exact.html +/library/std/cstream/InputStream.readf.html /library/std/cstream/input_stream.readf.html +/library/std/cstream/InputStream.read.html /library/std/cstream/input_stream.read.html +/library/std/cstream/InputStream.readLine.html /library/std/cstream/input_stream.read_line.html +/library/std/cstream/InputStream.readLineW.html /library/std/cstream/input_stream.read_line.html +/library/std/cstream/InputStream.readString.html /library/std/cstream/input_stream.read_string.html +/library/std/cstream/InputStream.readStringW.html /library/std/cstream/input_stream.read_string.html +/library/std/cstream/InputStream.ungetcw.html /library/std/cstream/input_stream.ungetcw.html +/library/std/cstream/InputStream.vreadf.html /library/std/cstream/input_stream.vreadf.html +/library/std/cstream/Object.factory.html /library/std/cstream/object.factory.html +/library/std/cstream/Object.opCmp.html /library/std/cstream/object.op_cmp.html +/library/std/cstream/Object.opEquals.html /library/std/cstream/object.op_equals.html +/library/std/cstream/OutputStream.printf.html /library/std/cstream/output_stream.printf.html +/library/std/cstream/OutputStream.vprintf.html /library/std/cstream/output_stream.vprintf.html +/library/std/cstream/OutputStream.writeExact.html /library/std/cstream/output_stream.write_exact.html +/library/std/cstream/OutputStream.writef.html /library/std/cstream/output_stream.writef.html +/library/std/cstream/OutputStream.writefln.html /library/std/cstream/output_stream.writefln.html +/library/std/cstream/OutputStream.writefx.html /library/std/cstream/output_stream.writefx.html +/library/std/cstream/OutputStream.write.html /library/std/cstream/output_stream.write.html +/library/std/cstream/OutputStream.writeString.html /library/std/cstream/output_stream.write_string.html +/library/std/cstream/OutputStream.writeStringW.html /library/std/cstream/output_stream.write_string.html +/library/std/cstream/Stream.copyFrom.html /library/std/cstream/stream.copy_from.html +/library/std/cstream/Stream.isopen.html /library/std/cstream/stream.isopen.html +/library/std/cstream/Stream.position.html /library/std/cstream/stream.position.html +/library/std/cstream/Stream.prevCr.html /library/std/cstream/stream.prev_cr.html +/library/std/cstream/Stream.readable.html /library/std/cstream/stream.readable.html +/library/std/cstream/Stream.readEOF.html /library/std/cstream/stream.read_eof.html +/library/std/cstream/Stream.seekable.html /library/std/cstream/stream.seekable.html +/library/std/cstream/Stream.seekCur.html /library/std/cstream/stream.seek_cur.html +/library/std/cstream/Stream.seekEnd.html /library/std/cstream/stream.seek_end.html +/library/std/cstream/Stream.seekSet.html /library/std/cstream/stream.seek_set.html +/library/std/cstream/Stream.size.html /library/std/cstream/stream.size.html +/library/std/cstream/Stream.toHash.html /library/std/cstream/stream.to_hash.html +/library/std/cstream/Stream.toString.html /library/std/cstream/stream.to_string.html +/library/std/cstream/Stream.writeable.html /library/std/cstream/stream.writeable.html +/library/std/csv/CSVException.html /library/std/csv/csv_exception.html +/library/std/csv/csvNextToken.html /library/std/csv/csv_next_token.html +/library/std/csv/csvReader.html /library/std/csv/csv_reader.html +/library/std/csv/HeaderMismatchException.html /library/std/csv/header_mismatch_exception.html +/library/std/csv/IncompleteCellException.html /library/std/csv/incomplete_cell_exception.html +/library/std/csv/IncompleteCellException.partialData.html /library/std/csv/incomplete_cell_exception.partial_data.html +/library/std/csv/Malformed.html /library/std/csv/malformed.html +/library/std/csv/Malformed.ignore.html /library/std/csv/malformed.ignore.html +/library/std/csv/Malformed.throwException.html /library/std/csv/malformed.throw_exception.html +/library/std/csv/Object.factory.html /library/std/csv/object.factory.html +/library/std/csv/Object.opCmp.html /library/std/csv/object.op_cmp.html +/library/std/csv/Object.opEquals.html /library/std/csv/object.op_equals.html +/library/std/csv/Object.toHash.html /library/std/csv/object.to_hash.html +/library/std/csv/Throwable.file.html /library/std/csv/throwable.file.html +/library/std/csv/Throwable.info.html /library/std/csv/throwable.info.html +/library/std/csv/Throwable.line.html /library/std/csv/throwable.line.html +/library/std/csv/Throwable.msg.html /library/std/csv/throwable.msg.html +/library/std/csv/Throwable.next.html /library/std/csv/throwable.next.html +/library/std/csv/Throwable.toString.html /library/std/csv/throwable.to_string.html +/library/std/datetime/AllowDayOverflow.html /library/std/datetime/allow_day_overflow.html +/library/std/datetime/AllowDayOverflow.no.html /library/std/datetime/allow_day_overflow.no.html +/library/std/datetime/AllowDayOverflow.yes.html /library/std/datetime/allow_day_overflow.yes.html +/library/std/datetime/AutoStart.html /library/std/datetime/auto_start.html +/library/std/datetime/AutoStart.no.html /library/std/datetime/auto_start.no.html +/library/std/datetime/AutoStart.yes.html /library/std/datetime/auto_start.yes.html +/library/std/datetime/clearTZEnvVar.html /library/std/datetime/clear_tz_env_var.html +/library/std/datetime/Clock.currAppTick.html /library/std/datetime/clock.curr_app_tick.html +/library/std/datetime/Clock.currStdTime.html /library/std/datetime/clock.curr_std_time.html +/library/std/datetime/Clock.currSystemTick.html /library/std/datetime/clock.curr_system_tick.html +/library/std/datetime/Clock.currTime.html /library/std/datetime/clock.curr_time.html +/library/std/datetime/Clock.html /library/std/datetime/clock.html +/library/std/datetime/cmpTimeUnits.html /library/std/datetime/cmp_time_units.html +/library/std/datetime/CmpTimeUnits.html /library/std/datetime/cmp_time_units.html +/library/std/datetime/comparingBenchmark.html /library/std/datetime/comparing_benchmark.html +/library/std/datetime/ComparingBenchmarkResult.baseTime.html /library/std/datetime/comparing_benchmark_result.base_time.html +/library/std/datetime/ComparingBenchmarkResult.html /library/std/datetime/comparing_benchmark_result.html +/library/std/datetime/ComparingBenchmarkResult.point.html /library/std/datetime/comparing_benchmark_result.point.html +/library/std/datetime/ComparingBenchmarkResult.targetTime.html /library/std/datetime/comparing_benchmark_result.target_time.html +/library/std/datetime/Date.add.html /library/std/datetime/date.add.html +/library/std/datetime/Date.day.html /library/std/datetime/date.day.html +/library/std/datetime/Date.dayOfGregorianCal.html /library/std/datetime/date.day_of_gregorian_cal.html +/library/std/datetime/Date.dayOfWeek.html /library/std/datetime/date.day_of_week.html +/library/std/datetime/Date.dayOfYear.html /library/std/datetime/date.day_of_year.html +/library/std/datetime/Date.daysInMonth.html /library/std/datetime/date.days_in_month.html +/library/std/datetime/Date.diffMonths.html /library/std/datetime/date.diff_months.html +/library/std/datetime/Date.endOfMonth.html /library/std/datetime/date.end_of_month.html +/library/std/datetime/Date.fromISOExtString.html /library/std/datetime/date.from_iso_ext_string.html +/library/std/datetime/Date.fromISOString.html /library/std/datetime/date.from_iso_string.html +/library/std/datetime/Date.fromSimpleString.html /library/std/datetime/date.from_simple_string.html +/library/std/datetime/Date.html /library/std/datetime/date.html +/library/std/datetime/Date.isAD.html /library/std/datetime/date.is_ad.html +/library/std/datetime/Date.isLeapYear.html /library/std/datetime/date.is_leap_year.html +/library/std/datetime/Date.isoWeek.html /library/std/datetime/date.iso_week.html +/library/std/datetime/Date.julianDay.html /library/std/datetime/date.julian_day.html +/library/std/datetime/Date.max.html /library/std/datetime/date.max.html +/library/std/datetime/Date.min.html /library/std/datetime/date.min.html +/library/std/datetime/Date.modJulianDay.html /library/std/datetime/date.mod_julian_day.html +/library/std/datetime/Date.month.html /library/std/datetime/date.month.html +/library/std/datetime/Date.opBinary.html /library/std/datetime/date.op_binary.html +/library/std/datetime/Date.opCmp.html /library/std/datetime/date.op_cmp.html +/library/std/datetime/Date.opOpAssign.html /library/std/datetime/date.op_op_assign.html +/library/std/datetime/Date.roll.html /library/std/datetime/date.roll.html +/library/std/datetime/Date.this.html /library/std/datetime/date.this.html +/library/std/datetime/DateTime.add.html /library/std/datetime/date_time.add.html +/library/std/datetime/DateTime.date.html /library/std/datetime/date_time.date.html +/library/std/datetime/DateTime.day.html /library/std/datetime/date_time.day.html +/library/std/datetime/DateTime.dayOfGregorianCal.html /library/std/datetime/date_time.day_of_gregorian_cal.html +/library/std/datetime/DateTime.dayOfWeek.html /library/std/datetime/date_time.day_of_week.html +/library/std/datetime/DateTime.dayOfYear.html /library/std/datetime/date_time.day_of_year.html +/library/std/datetime/DateTime.daysInMonth.html /library/std/datetime/date_time.days_in_month.html +/library/std/datetime/DateTime.diffMonths.html /library/std/datetime/date_time.diff_months.html +/library/std/datetime/DateTime.endOfMonth.html /library/std/datetime/date_time.end_of_month.html +/library/std/datetime/DateTimeException.html /library/std/datetime/date_time_exception.html +/library/std/datetime/DateTime.fromISOExtString.html /library/std/datetime/date_time.from_iso_ext_string.html +/library/std/datetime/DateTime.fromISOString.html /library/std/datetime/date_time.from_iso_string.html +/library/std/datetime/DateTime.fromSimpleString.html /library/std/datetime/date_time.from_simple_string.html +/library/std/datetime/DateTime.hour.html /library/std/datetime/date_time.hour.html +/library/std/datetime/DateTime.html /library/std/datetime/date_time.html +/library/std/datetime/DateTime.isAD.html /library/std/datetime/date_time.is_ad.html +/library/std/datetime/DateTime.isLeapYear.html /library/std/datetime/date_time.is_leap_year.html +/library/std/datetime/DateTime.isoWeek.html /library/std/datetime/date_time.iso_week.html +/library/std/datetime/DateTime.julianDay.html /library/std/datetime/date_time.julian_day.html +/library/std/datetime/DateTime.max.html /library/std/datetime/date_time.max.html +/library/std/datetime/DateTime.min.html /library/std/datetime/date_time.min.html +/library/std/datetime/DateTime.minute.html /library/std/datetime/date_time.minute.html +/library/std/datetime/DateTime.modJulianDay.html /library/std/datetime/date_time.mod_julian_day.html +/library/std/datetime/DateTime.month.html /library/std/datetime/date_time.month.html +/library/std/datetime/DateTime.opBinary.html /library/std/datetime/date_time.op_binary.html +/library/std/datetime/DateTime.opCmp.html /library/std/datetime/date_time.op_cmp.html +/library/std/datetime/DateTime.opOpAssign.html /library/std/datetime/date_time.op_op_assign.html +/library/std/datetime/DateTime.roll.html /library/std/datetime/date_time.roll.html +/library/std/datetime/DateTime.second.html /library/std/datetime/date_time.second.html +/library/std/datetime/DateTime.this.html /library/std/datetime/date_time.this.html +/library/std/datetime/DateTime.timeOfDay.html /library/std/datetime/date_time.time_of_day.html +/library/std/datetime/DateTime.toISOExtString.html /library/std/datetime/date_time.to_iso_ext_string.html +/library/std/datetime/DateTime.toISOString.html /library/std/datetime/date_time.to_iso_string.html +/library/std/datetime/DateTime.toSimpleString.html /library/std/datetime/date_time.to_simple_string.html +/library/std/datetime/DateTime.toString.html /library/std/datetime/date_time.to_string.html +/library/std/datetime/DateTime.yearBC.html /library/std/datetime/date_time.year_bc.html +/library/std/datetime/DateTime.year.html /library/std/datetime/date_time.year.html +/library/std/datetime/Date.toISOExtString.html /library/std/datetime/date.to_iso_ext_string.html +/library/std/datetime/Date.toISOString.html /library/std/datetime/date.to_iso_string.html +/library/std/datetime/Date.toSimpleString.html /library/std/datetime/date.to_simple_string.html +/library/std/datetime/Date.toString.html /library/std/datetime/date.to_string.html +/library/std/datetime/Date.yearBC.html /library/std/datetime/date.year_bc.html +/library/std/datetime/Date.year.html /library/std/datetime/date.year.html +/library/std/datetime/DayOfWeek.html /library/std/datetime/day_of_week.html +/library/std/datetime/daysToDayOfWeek.html /library/std/datetime/days_to_day_of_week.html +/library/std/datetime/Direction.both.html /library/std/datetime/direction.both.html +/library/std/datetime/Direction.bwd.html /library/std/datetime/direction.bwd.html +/library/std/datetime/Direction.fwd.html /library/std/datetime/direction.fwd.html +/library/std/datetime/Direction.html /library/std/datetime/direction.html +/library/std/datetime/DosFileTime.html /library/std/datetime/dos_file_time.html +/library/std/datetime/DosFileTimeToSysTime.html /library/std/datetime/dos_file_time_to_sys_time.html +/library/std/datetime/enforceValid.html /library/std/datetime/enforce_valid.html +/library/std/datetime/everyDayOfWeek.html /library/std/datetime/every_day_of_week.html +/library/std/datetime/everyDuration.html /library/std/datetime/every_duration.html +/library/std/datetime/everyMonth.html /library/std/datetime/every_month.html +/library/std/datetime/FILETIMEToStdTime.html /library/std/datetime/filetime_to_std_time.html +/library/std/datetime/FILETIMEToSysTime.html /library/std/datetime/filetime_to_sys_time.html +/library/std/datetime/Interval.begin.html /library/std/datetime/interval.begin.html +/library/std/datetime/Interval.bwdRange.html /library/std/datetime/interval.bwd_range.html +/library/std/datetime/Interval.contains.html /library/std/datetime/interval.contains.html +/library/std/datetime/Interval.empty.html /library/std/datetime/interval.empty.html +/library/std/datetime/Interval.end.html /library/std/datetime/interval.end.html +/library/std/datetime/Interval.expand.expand.html /library/std/datetime/interval.expand.expand.html +/library/std/datetime/Interval.expand.html /library/std/datetime/interval.expand.html +/library/std/datetime/Interval.fwdRange.html /library/std/datetime/interval.fwd_range.html +/library/std/datetime/Interval.html /library/std/datetime/interval.html +/library/std/datetime/Interval.intersection.html /library/std/datetime/interval.intersection.html +/library/std/datetime/Interval.intersects.html /library/std/datetime/interval.intersects.html +/library/std/datetime/Interval.isAdjacent.html /library/std/datetime/interval.is_adjacent.html +/library/std/datetime/Interval.isAfter.html /library/std/datetime/interval.is_after.html +/library/std/datetime/Interval.isBefore.html /library/std/datetime/interval.is_before.html +/library/std/datetime/Interval.length.html /library/std/datetime/interval.length.html +/library/std/datetime/Interval.merge.html /library/std/datetime/interval.merge.html +/library/std/datetime/Interval.opAssign.html /library/std/datetime/interval.op_assign.html +/library/std/datetime/IntervalRange.direction.html /library/std/datetime/interval_range.direction.html +/library/std/datetime/IntervalRange.empty.html /library/std/datetime/interval_range.empty.html +/library/std/datetime/IntervalRange.front.html /library/std/datetime/interval_range.front.html +/library/std/datetime/IntervalRange.func.html /library/std/datetime/interval_range.func.html +/library/std/datetime/IntervalRange.html /library/std/datetime/interval_range.html +/library/std/datetime/IntervalRange.interval.html /library/std/datetime/interval_range.interval.html +/library/std/datetime/IntervalRange.opAssign.html /library/std/datetime/interval_range.op_assign.html +/library/std/datetime/IntervalRange.popFront.html /library/std/datetime/interval_range.pop_front.html +/library/std/datetime/IntervalRange.save.html /library/std/datetime/interval_range.save.html +/library/std/datetime/Interval.shift.html /library/std/datetime/interval.shift.html +/library/std/datetime/Interval.shift.shift.html /library/std/datetime/interval.shift.shift.html +/library/std/datetime/Interval.span.html /library/std/datetime/interval.span.html +/library/std/datetime/Interval.this.html /library/std/datetime/interval.this.html +/library/std/datetime/Interval.this.this.html /library/std/datetime/interval.this.this.html +/library/std/datetime/Interval.toString.html /library/std/datetime/interval.to_string.html +/library/std/datetime/isTimePoint.html /library/std/datetime/is_time_point.html +/library/std/datetime/LocalTime.dstInEffect.html /library/std/datetime/local_time.dst_in_effect.html +/library/std/datetime/LocalTime.dstName.html /library/std/datetime/local_time.dst_name.html +/library/std/datetime/LocalTime.hasDST.html /library/std/datetime/local_time.has_dst.html +/library/std/datetime/LocalTime.html /library/std/datetime/local_time.html +/library/std/datetime/LocalTime.name.html /library/std/datetime/local_time.name.html +/library/std/datetime/LocalTime.opCall.html /library/std/datetime/local_time.op_call.html +/library/std/datetime/LocalTime.stdName.html /library/std/datetime/local_time.std_name.html +/library/std/datetime/LocalTime.tzToUTC.html /library/std/datetime/local_time.tz_toutc.html +/library/std/datetime/LocalTime.utcToTZ.html /library/std/datetime/local_time.utc_totz.html +/library/std/datetime/measureTime.html /library/std/datetime/measure_time.html +/library/std/datetime/Month.html /library/std/datetime/month.html +/library/std/datetime/monthsToMonth.html /library/std/datetime/months_to_month.html +/library/std/datetime/NegInfInterval.bwdRange.html /library/std/datetime/neg_inf_interval.bwd_range.html +/library/std/datetime/NegInfInterval.contains.html /library/std/datetime/neg_inf_interval.contains.html +/library/std/datetime/NegInfInterval.empty.html /library/std/datetime/neg_inf_interval.empty.html +/library/std/datetime/NegInfInterval.end.html /library/std/datetime/neg_inf_interval.end.html +/library/std/datetime/NegInfInterval.expand.expand.html /library/std/datetime/neg_inf_interval.expand.expand.html +/library/std/datetime/NegInfInterval.expand.html /library/std/datetime/neg_inf_interval.expand.html +/library/std/datetime/NegInfInterval.html /library/std/datetime/neg_inf_interval.html +/library/std/datetime/NegInfInterval.intersection.html /library/std/datetime/neg_inf_interval.intersection.html +/library/std/datetime/NegInfInterval.intersects.html /library/std/datetime/neg_inf_interval.intersects.html +/library/std/datetime/NegInfInterval.isAdjacent.html /library/std/datetime/neg_inf_interval.is_adjacent.html +/library/std/datetime/NegInfInterval.isAfter.html /library/std/datetime/neg_inf_interval.is_after.html +/library/std/datetime/NegInfInterval.isBefore.html /library/std/datetime/neg_inf_interval.is_before.html +/library/std/datetime/NegInfInterval.merge.html /library/std/datetime/neg_inf_interval.merge.html +/library/std/datetime/NegInfInterval.opAssign.html /library/std/datetime/neg_inf_interval.op_assign.html +/library/std/datetime/NegInfIntervalRange.empty.html /library/std/datetime/neg_inf_interval_range.empty.html +/library/std/datetime/NegInfIntervalRange.front.html /library/std/datetime/neg_inf_interval_range.front.html +/library/std/datetime/NegInfIntervalRange.func.html /library/std/datetime/neg_inf_interval_range.func.html +/library/std/datetime/NegInfIntervalRange.html /library/std/datetime/neg_inf_interval_range.html +/library/std/datetime/NegInfIntervalRange.interval.html /library/std/datetime/neg_inf_interval_range.interval.html +/library/std/datetime/NegInfIntervalRange.opAssign.html /library/std/datetime/neg_inf_interval_range.op_assign.html +/library/std/datetime/NegInfIntervalRange.popFront.html /library/std/datetime/neg_inf_interval_range.pop_front.html +/library/std/datetime/NegInfIntervalRange.save.html /library/std/datetime/neg_inf_interval_range.save.html +/library/std/datetime/NegInfInterval.shift.html /library/std/datetime/neg_inf_interval.shift.html +/library/std/datetime/NegInfInterval.shift.shift.html /library/std/datetime/neg_inf_interval.shift.shift.html +/library/std/datetime/NegInfInterval.span.html /library/std/datetime/neg_inf_interval.span.html +/library/std/datetime/NegInfInterval.this.html /library/std/datetime/neg_inf_interval.this.html +/library/std/datetime/NegInfInterval.toString.html /library/std/datetime/neg_inf_interval.to_string.html +/library/std/datetime/Object.factory.html /library/std/datetime/object.factory.html +/library/std/datetime/Object.opCmp.html /library/std/datetime/object.op_cmp.html +/library/std/datetime/Object.opEquals.html /library/std/datetime/object.op_equals.html +/library/std/datetime/Object.toHash.html /library/std/datetime/object.to_hash.html +/library/std/datetime/Object.toString.html /library/std/datetime/object.to_string.html +/library/std/datetime/parseRFC822DateTime.html /library/std/datetime/parse_rf_c822_date_time.html +/library/std/datetime/PopFirst.html /library/std/datetime/pop_first.html +/library/std/datetime/PopFirst.no.html /library/std/datetime/pop_first.no.html +/library/std/datetime/PopFirst.yes.html /library/std/datetime/pop_first.yes.html +/library/std/datetime/PosInfInterval.begin.html /library/std/datetime/pos_inf_interval.begin.html +/library/std/datetime/PosInfInterval.contains.html /library/std/datetime/pos_inf_interval.contains.html +/library/std/datetime/PosInfInterval.empty.html /library/std/datetime/pos_inf_interval.empty.html +/library/std/datetime/PosInfInterval.expand.expand.html /library/std/datetime/pos_inf_interval.expand.expand.html +/library/std/datetime/PosInfInterval.expand.html /library/std/datetime/pos_inf_interval.expand.html +/library/std/datetime/PosInfInterval.fwdRange.html /library/std/datetime/pos_inf_interval.fwd_range.html +/library/std/datetime/PosInfInterval.html /library/std/datetime/pos_inf_interval.html +/library/std/datetime/PosInfInterval.intersection.html /library/std/datetime/pos_inf_interval.intersection.html +/library/std/datetime/PosInfInterval.intersects.html /library/std/datetime/pos_inf_interval.intersects.html +/library/std/datetime/PosInfInterval.isAdjacent.html /library/std/datetime/pos_inf_interval.is_adjacent.html +/library/std/datetime/PosInfInterval.isAfter.html /library/std/datetime/pos_inf_interval.is_after.html +/library/std/datetime/PosInfInterval.isBefore.html /library/std/datetime/pos_inf_interval.is_before.html +/library/std/datetime/PosInfInterval.merge.html /library/std/datetime/pos_inf_interval.merge.html +/library/std/datetime/PosInfInterval.opAssign.html /library/std/datetime/pos_inf_interval.op_assign.html +/library/std/datetime/PosInfIntervalRange.empty.html /library/std/datetime/pos_inf_interval_range.empty.html +/library/std/datetime/PosInfIntervalRange.front.html /library/std/datetime/pos_inf_interval_range.front.html +/library/std/datetime/PosInfIntervalRange.func.html /library/std/datetime/pos_inf_interval_range.func.html +/library/std/datetime/PosInfIntervalRange.html /library/std/datetime/pos_inf_interval_range.html +/library/std/datetime/PosInfIntervalRange.interval.html /library/std/datetime/pos_inf_interval_range.interval.html +/library/std/datetime/PosInfIntervalRange.opAssign.html /library/std/datetime/pos_inf_interval_range.op_assign.html +/library/std/datetime/PosInfIntervalRange.popFront.html /library/std/datetime/pos_inf_interval_range.pop_front.html +/library/std/datetime/PosInfIntervalRange.save.html /library/std/datetime/pos_inf_interval_range.save.html +/library/std/datetime/PosInfInterval.shift.html /library/std/datetime/pos_inf_interval.shift.html +/library/std/datetime/PosInfInterval.shift.shift.html /library/std/datetime/pos_inf_interval.shift.shift.html +/library/std/datetime/PosInfInterval.span.html /library/std/datetime/pos_inf_interval.span.html +/library/std/datetime/PosInfInterval.this.html /library/std/datetime/pos_inf_interval.this.html +/library/std/datetime/PosInfInterval.toString.html /library/std/datetime/pos_inf_interval.to_string.html +/library/std/datetime/PosixTimeZone.defaultTZDatabaseDir.html /library/std/datetime/posix_time_zone.default_tz_database_dir.html +/library/std/datetime/PosixTimeZone.dstInEffect.html /library/std/datetime/posix_time_zone.dst_in_effect.html +/library/std/datetime/PosixTimeZone.getInstalledTZNames.html /library/std/datetime/posix_time_zone.get_installed_tz_names.html +/library/std/datetime/PosixTimeZone.getTimeZone.html /library/std/datetime/posix_time_zone.get_time_zone.html +/library/std/datetime/PosixTimeZone.hasDST.html /library/std/datetime/posix_time_zone.has_dst.html +/library/std/datetime/PosixTimeZone.html /library/std/datetime/posix_time_zone.html +/library/std/datetime/PosixTimeZone.tzToUTC.html /library/std/datetime/posix_time_zone.tz_toutc.html +/library/std/datetime/PosixTimeZone.utcToTZ.html /library/std/datetime/posix_time_zone.utc_totz.html +/library/std/datetime/setTZEnvVar.html /library/std/datetime/set_tz_env_var.html +/library/std/datetime/SimpleTimeZone.dstInEffect.html /library/std/datetime/simple_time_zone.dst_in_effect.html +/library/std/datetime/SimpleTimeZone.hasDST.html /library/std/datetime/simple_time_zone.has_dst.html +/library/std/datetime/SimpleTimeZone.html /library/std/datetime/simple_time_zone.html +/library/std/datetime/SimpleTimeZone.this.html /library/std/datetime/simple_time_zone.this.html +/library/std/datetime/SimpleTimeZone.tzToUTC.html /library/std/datetime/simple_time_zone.tz_toutc.html +/library/std/datetime/SimpleTimeZone.utcOffsetAt.html /library/std/datetime/simple_time_zone.utc_offset_at.html +/library/std/datetime/SimpleTimeZone.utcOffset.html /library/std/datetime/simple_time_zone.utc_offset.html +/library/std/datetime/SimpleTimeZone.utcToTZ.html /library/std/datetime/simple_time_zone.utc_totz.html +/library/std/datetime/stdTimeToFILETIME.html /library/std/datetime/std_time_tofiletime.html +/library/std/datetime/stdTimeToUnixTime.html /library/std/datetime/std_time_to_unix_time.html +/library/std/datetime/StopWatch.html /library/std/datetime/stop_watch.html +/library/std/datetime/StopWatch.opEquals.html /library/std/datetime/stop_watch.op_equals.html +/library/std/datetime/StopWatch.peek.html /library/std/datetime/stop_watch.peek.html +/library/std/datetime/StopWatch.reset.html /library/std/datetime/stop_watch.reset.html +/library/std/datetime/StopWatch.running.html /library/std/datetime/stop_watch.running.html +/library/std/datetime/StopWatch.setMeasured.html /library/std/datetime/stop_watch.set_measured.html +/library/std/datetime/StopWatch.start.html /library/std/datetime/stop_watch.start.html +/library/std/datetime/StopWatch.stop.html /library/std/datetime/stop_watch.stop.html +/library/std/datetime/StopWatch.this.html /library/std/datetime/stop_watch.this.html +/library/std/datetime/SYSTEMTIMEToSysTime.html /library/std/datetime/systemtime_to_sys_time.html +/library/std/datetime/SysTime.add.html /library/std/datetime/sys_time.add.html +/library/std/datetime/SysTime.day.html /library/std/datetime/sys_time.day.html +/library/std/datetime/SysTime.dayOfGregorianCal.html /library/std/datetime/sys_time.day_of_gregorian_cal.html +/library/std/datetime/SysTime.dayOfWeek.html /library/std/datetime/sys_time.day_of_week.html +/library/std/datetime/SysTime.dayOfYear.html /library/std/datetime/sys_time.day_of_year.html +/library/std/datetime/SysTime.daysInMonth.html /library/std/datetime/sys_time.days_in_month.html +/library/std/datetime/SysTime.diffMonths.html /library/std/datetime/sys_time.diff_months.html +/library/std/datetime/SysTime.dstInEffect.html /library/std/datetime/sys_time.dst_in_effect.html +/library/std/datetime/SysTime.endOfMonth.html /library/std/datetime/sys_time.end_of_month.html +/library/std/datetime/SysTime.fracSec.html /library/std/datetime/sys_time.frac_sec.html +/library/std/datetime/SysTime.fracSecs.html /library/std/datetime/sys_time.frac_secs.html +/library/std/datetime/SysTime.fromISOExtString.html /library/std/datetime/sys_time.from_iso_ext_string.html +/library/std/datetime/SysTime.fromISOString.html /library/std/datetime/sys_time.from_iso_string.html +/library/std/datetime/SysTime.fromSimpleString.html /library/std/datetime/sys_time.from_simple_string.html +/library/std/datetime/SysTime.hour.html /library/std/datetime/sys_time.hour.html +/library/std/datetime/SysTime.html /library/std/datetime/sys_time.html +/library/std/datetime/SysTime.isAD.html /library/std/datetime/sys_time.is_ad.html +/library/std/datetime/SysTime.isLeapYear.html /library/std/datetime/sys_time.is_leap_year.html +/library/std/datetime/SysTime.isoWeek.html /library/std/datetime/sys_time.iso_week.html +/library/std/datetime/SysTime.julianDay.html /library/std/datetime/sys_time.julian_day.html +/library/std/datetime/SysTime.max.html /library/std/datetime/sys_time.max.html +/library/std/datetime/SysTime.min.html /library/std/datetime/sys_time.min.html +/library/std/datetime/SysTime.minute.html /library/std/datetime/sys_time.minute.html +/library/std/datetime/SysTime.modJulianDay.html /library/std/datetime/sys_time.mod_julian_day.html +/library/std/datetime/SysTime.month.html /library/std/datetime/sys_time.month.html +/library/std/datetime/SysTime.opAssign.html /library/std/datetime/sys_time.op_assign.html +/library/std/datetime/SysTime.opBinary.html /library/std/datetime/sys_time.op_binary.html +/library/std/datetime/SysTime.opCast.html /library/std/datetime/sys_time.op_cast.html +/library/std/datetime/SysTime.opCmp.html /library/std/datetime/sys_time.op_cmp.html +/library/std/datetime/SysTime.opEquals.html /library/std/datetime/sys_time.op_equals.html +/library/std/datetime/SysTime.opOpAssign.html /library/std/datetime/sys_time.op_op_assign.html +/library/std/datetime/SysTime.roll.html /library/std/datetime/sys_time.roll.html +/library/std/datetime/SysTime.second.html /library/std/datetime/sys_time.second.html +/library/std/datetime/SysTime.stdTime.html /library/std/datetime/sys_time.std_time.html +/library/std/datetime/SysTime.this.html /library/std/datetime/sys_time.this.html +/library/std/datetime/SysTime.timezone.html /library/std/datetime/sys_time.timezone.html +/library/std/datetime/SysTimeToDosFileTime.html /library/std/datetime/sys_time_to_dos_file_time.html +/library/std/datetime/SysTimeToFILETIME.html /library/std/datetime/sys_time_tofiletime.html +/library/std/datetime/SysTime.toISOExtString.html /library/std/datetime/sys_time.to_iso_ext_string.html +/library/std/datetime/SysTime.toISOString.html /library/std/datetime/sys_time.to_iso_string.html +/library/std/datetime/SysTime.toLocalTime.html /library/std/datetime/sys_time.to_local_time.html +/library/std/datetime/SysTime.toOtherTZ.html /library/std/datetime/sys_time.to_other_tz.html +/library/std/datetime/SysTime.toSimpleString.html /library/std/datetime/sys_time.to_simple_string.html +/library/std/datetime/SysTime.toString.html /library/std/datetime/sys_time.to_string.html +/library/std/datetime/SysTimeToSYSTEMTIME.html /library/std/datetime/sys_time_tosystemtime.html +/library/std/datetime/SysTime.toTimeVal.html /library/std/datetime/sys_time.to_time_val.html +/library/std/datetime/SysTime.toTM.html /library/std/datetime/sys_time.to_tm.html +/library/std/datetime/SysTime.toUnixTime.html /library/std/datetime/sys_time.to_unix_time.html +/library/std/datetime/SysTime.toUTC.html /library/std/datetime/sys_time.to_utc.html +/library/std/datetime/SysTime.utcOffset.html /library/std/datetime/sys_time.utc_offset.html +/library/std/datetime/SysTime.yearBC.html /library/std/datetime/sys_time.year_bc.html +/library/std/datetime/SysTime.year.html /library/std/datetime/sys_time.year.html +/library/std/datetime/TimeOfDay.fromISOExtString.html /library/std/datetime/time_of_day.from_iso_ext_string.html +/library/std/datetime/TimeOfDay.fromISOString.html /library/std/datetime/time_of_day.from_iso_string.html +/library/std/datetime/TimeOfDay.hour.html /library/std/datetime/time_of_day.hour.html +/library/std/datetime/TimeOfDay.html /library/std/datetime/time_of_day.html +/library/std/datetime/TimeOfDay.max.html /library/std/datetime/time_of_day.max.html +/library/std/datetime/TimeOfDay.min.html /library/std/datetime/time_of_day.min.html +/library/std/datetime/TimeOfDay.minute.html /library/std/datetime/time_of_day.minute.html +/library/std/datetime/TimeOfDay.opBinary.html /library/std/datetime/time_of_day.op_binary.html +/library/std/datetime/TimeOfDay.opCmp.html /library/std/datetime/time_of_day.op_cmp.html +/library/std/datetime/TimeOfDay.opOpAssign.html /library/std/datetime/time_of_day.op_op_assign.html +/library/std/datetime/TimeOfDay.roll.html /library/std/datetime/time_of_day.roll.html +/library/std/datetime/TimeOfDay.second.html /library/std/datetime/time_of_day.second.html +/library/std/datetime/TimeOfDay.this.html /library/std/datetime/time_of_day.this.html +/library/std/datetime/TimeOfDay.toISOExtString.html /library/std/datetime/time_of_day.to_iso_ext_string.html +/library/std/datetime/TimeOfDay.toISOString.html /library/std/datetime/time_of_day.to_iso_string.html +/library/std/datetime/TimeOfDay.toString.html /library/std/datetime/time_of_day.to_string.html +/library/std/datetime/timeStrings.html /library/std/datetime/time_strings.html +/library/std/datetime/TimeZone.dstInEffect.html /library/std/datetime/time_zone.dst_in_effect.html +/library/std/datetime/TimeZone.dstName.html /library/std/datetime/time_zone.dst_name.html +/library/std/datetime/TimeZone.getInstalledTZNames.html /library/std/datetime/time_zone.get_installed_tz_names.html +/library/std/datetime/TimeZone.getTimeZone.html /library/std/datetime/time_zone.get_time_zone.html +/library/std/datetime/TimeZone.hasDST.html /library/std/datetime/time_zone.has_dst.html +/library/std/datetime/TimeZone.html /library/std/datetime/time_zone.html +/library/std/datetime/TimeZone.name.html /library/std/datetime/time_zone.name.html +/library/std/datetime/TimeZone.stdName.html /library/std/datetime/time_zone.std_name.html +/library/std/datetime/TimeZone.tzToUTC.html /library/std/datetime/time_zone.tz_toutc.html +/library/std/datetime/TimeZone.utcOffsetAt.html /library/std/datetime/time_zone.utc_offset_at.html +/library/std/datetime/TimeZone.utcToTZ.html /library/std/datetime/time_zone.utc_totz.html +/library/std/datetime/tzDatabaseNameToWindowsTZName.html /library/std/datetime/tz_database_name_to_windows_tz_name.html +/library/std/datetime/unixTimeToStdTime.html /library/std/datetime/unix_time_to_std_time.html +/library/std/datetime/UTC.dstInEffect.html /library/std/datetime/utc.dst_in_effect.html +/library/std/datetime/UTC.hasDST.html /library/std/datetime/utc.has_dst.html +/library/std/datetime/UTC.html /library/std/datetime/utc.html +/library/std/datetime/UTC.opCall.html /library/std/datetime/utc.op_call.html +/library/std/datetime/UTC.tzToUTC.html /library/std/datetime/utc.tz_toutc.html +/library/std/datetime/UTC.utcOffsetAt.html /library/std/datetime/utc.utc_offset_at.html +/library/std/datetime/UTC.utcToTZ.html /library/std/datetime/utc.utc_totz.html +/library/std/datetime/validTimeUnits.html /library/std/datetime/valid_time_units.html +/library/std/datetime/WindowsTimeZone.dstInEffect.html /library/std/datetime/windows_time_zone.dst_in_effect.html +/library/std/datetime/WindowsTimeZone.getInstalledTZNames.html /library/std/datetime/windows_time_zone.get_installed_tz_names.html +/library/std/datetime/WindowsTimeZone.getTimeZone.html /library/std/datetime/windows_time_zone.get_time_zone.html +/library/std/datetime/WindowsTimeZone.hasDST.html /library/std/datetime/windows_time_zone.has_dst.html +/library/std/datetime/WindowsTimeZone.html /library/std/datetime/windows_time_zone.html +/library/std/datetime/WindowsTimeZone.tzToUTC.html /library/std/datetime/windows_time_zone.tz_toutc.html +/library/std/datetime/WindowsTimeZone.utcToTZ.html /library/std/datetime/windows_time_zone.utc_totz.html +/library/std/datetime/windowsTZNameToTZDatabaseName.html /library/std/datetime/windows_tz_name_totz_database_name.html +/library/std/datetime/yearIsLeapYear.html /library/std/datetime/year_is_leap_year.html +/library/std/digest/crc/CRC32Digest.html /library/std/digest/crc/cr_c32_digest.html +/library/std/digest/crc/CRC32.finish.html /library/std/digest/crc/cr_c32.finish.html +/library/std/digest/crc/CRC32.html /library/std/digest/crc/cr_c32.html +/library/std/digest/crc/crc32Of.html /library/std/digest/crc/crc32_of.html +/library/std/digest/crc/CRC32.peek.html /library/std/digest/crc/cr_c32.peek.html +/library/std/digest/crc/CRC32.put.html /library/std/digest/crc/cr_c32.put.html +/library/std/digest/crc/CRC32.start.html /library/std/digest/crc/cr_c32.start.html +/library/std/digest/crc/crcHexString.html /library/std/digest/crc/crc_hex_string.html +/library/std/digest/digest/Digest.digest.html /library/std/digest/digest/digest.digest.html +/library/std/digest/digest/Digest.finish.html /library/std/digest/digest/digest.finish.html +/library/std/digest/digest/Digest.html /library/std/digest/digest/digest.html +/library/std/digest/digest/digestLength.html /library/std/digest/digest/digest_length.html +/library/std/digest/digest/Digest.length.html /library/std/digest/digest/digest.length.html +/library/std/digest/digest/Digest.put.html /library/std/digest/digest/digest.put.html +/library/std/digest/digest/Digest.reset.html /library/std/digest/digest/digest.reset.html +/library/std/digest/digest/DigestType.html /library/std/digest/digest/digest_type.html +/library/std/digest/digest/ExampleDigest.finish.html /library/std/digest/digest/example_digest.finish.html +/library/std/digest/digest/ExampleDigest.html /library/std/digest/digest/example_digest.html +/library/std/digest/digest/ExampleDigest.put.html /library/std/digest/digest/example_digest.put.html +/library/std/digest/digest/ExampleDigest.start.html /library/std/digest/digest/example_digest.start.html +/library/std/digest/digest/hasPeek.html /library/std/digest/digest/has_peek.html +/library/std/digest/digest/hexDigest.html /library/std/digest/digest/hex_digest.html +/library/std/digest/digest/isDigest.html /library/std/digest/digest/is_digest.html +/library/std/digest/digest/makeDigest.html /library/std/digest/digest/make_digest.html +/library/std/digest/digest/Object.factory.html /library/std/digest/digest/object.factory.html +/library/std/digest/digest/Object.opCmp.html /library/std/digest/digest/object.op_cmp.html +/library/std/digest/digest/Object.opEquals.html /library/std/digest/digest/object.op_equals.html +/library/std/digest/digest/Object.toHash.html /library/std/digest/digest/object.to_hash.html +/library/std/digest/digest/Object.toString.html /library/std/digest/digest/object.to_string.html +/library/std/digest/digest/Order.html /library/std/digest/digest/order.html +/library/std/digest/digest/toHexString.html /library/std/digest/digest/to_hex_string.html +/library/std/digest/digest/WrapperDigest.finish.html /library/std/digest/digest/wrapper_digest.finish.html +/library/std/digest/digest/WrapperDigest.html /library/std/digest/digest/wrapper_digest.html +/library/std/digest/digest/WrapperDigest.length.html /library/std/digest/digest/wrapper_digest.length.html +/library/std/digest/digest/WrapperDigest.peek.html /library/std/digest/digest/wrapper_digest.peek.html +/library/std/digest/digest/WrapperDigest.put.html /library/std/digest/digest/wrapper_digest.put.html +/library/std/digest/digest/WrapperDigest.reset.html /library/std/digest/digest/wrapper_digest.reset.html +/library/std/digest/digest/WrapperDigest.this.html /library/std/digest/digest/wrapper_digest.this.html +/library/std/digest/md/MD5Digest.html /library/std/digest/md/m_d5_digest.html +/library/std/digest/md/MD5.finish.html /library/std/digest/md/m_d5.finish.html +/library/std/digest/md/MD5.html /library/std/digest/md/m_d5.html +/library/std/digest/md/md5Of.html /library/std/digest/md/md5_of.html +/library/std/digest/md/MD5.put.html /library/std/digest/md/m_d5.put.html +/library/std/digest/md/MD5.start.html /library/std/digest/md/m_d5.start.html +/library/std/digest/ripemd/RIPEMD160Digest.html /library/std/digest/ripemd/ripem_d160_digest.html +/library/std/digest/ripemd/RIPEMD160.finish.html /library/std/digest/ripemd/ripem_d160.finish.html +/library/std/digest/ripemd/RIPEMD160.html /library/std/digest/ripemd/ripem_d160.html +/library/std/digest/ripemd/ripemd160Of.html /library/std/digest/ripemd/ripemd160_of.html +/library/std/digest/ripemd/RIPEMD160.put.html /library/std/digest/ripemd/ripem_d160.put.html +/library/std/digest/ripemd/RIPEMD160.start.html /library/std/digest/ripemd/ripem_d160.start.html +/library/std/digest/sha/SHA1Digest.html /library/std/digest/sha/sh_a1_digest.html +/library/std/digest/sha/SHA1.html /library/std/digest/sha/sh_a1.html +/library/std/digest/sha/sha1Of.html /library/std/digest/sha/sha1_of.html +/library/std/digest/sha/SHA224Digest.html /library/std/digest/sha/sh_a224_digest.html +/library/std/digest/sha/SHA224.html /library/std/digest/sha/sh_a224.html +/library/std/digest/sha/sha224Of.html /library/std/digest/sha/sha224_of.html +/library/std/digest/sha/SHA256Digest.html /library/std/digest/sha/sh_a256_digest.html +/library/std/digest/sha/SHA256.html /library/std/digest/sha/sh_a256.html +/library/std/digest/sha/sha256Of.html /library/std/digest/sha/sha256_of.html +/library/std/digest/sha/SHA384Digest.html /library/std/digest/sha/sh_a384_digest.html +/library/std/digest/sha/SHA384.html /library/std/digest/sha/sh_a384.html +/library/std/digest/sha/sha384Of.html /library/std/digest/sha/sha384_of.html +/library/std/digest/sha/SHA512_224Digest.html /library/std/digest/sha/sh_a512_224_digest.html +/library/std/digest/sha/SHA512_224.html /library/std/digest/sha/sh_a512_224.html +/library/std/digest/sha/sha512_224Of.html /library/std/digest/sha/sha512_224_of.html +/library/std/digest/sha/SHA512_256Digest.html /library/std/digest/sha/sh_a512_256_digest.html +/library/std/digest/sha/SHA512_256.html /library/std/digest/sha/sh_a512_256.html +/library/std/digest/sha/sha512_256Of.html /library/std/digest/sha/sha512_256_of.html +/library/std/digest/sha/SHA512Digest.html /library/std/digest/sha/sh_a512_digest.html +/library/std/digest/sha/SHA512.html /library/std/digest/sha/sh_a512.html +/library/std/digest/sha/sha512Of.html /library/std/digest/sha/sha512_of.html +/library/std/digest/sha/SHA.finish.html /library/std/digest/sha/sha.finish.html +/library/std/digest/sha/SHA.html /library/std/digest/sha/sha.html +/library/std/digest/sha/SHA.put.html /library/std/digest/sha/sha.put.html +/library/std/digest/sha/SHA.start.html /library/std/digest/sha/sha.start.html +/library/std/encoding/AsciiChar.html /library/std/encoding/ascii_char.html +/library/std/encoding/AsciiString.html /library/std/encoding/ascii_string.html +/library/std/encoding/canEncode.html /library/std/encoding/can_encode.html +/library/std/encoding/codePoints.html /library/std/encoding/code_points.html +/library/std/encoding/codeUnits.html /library/std/encoding/code_units.html +/library/std/encoding/decodeReverse.html /library/std/encoding/decode_reverse.html +/library/std/encoding/encodedLength.html /library/std/encoding/encoded_length.html +/library/std/encoding/EncodingException.html /library/std/encoding/encoding_exception.html +/library/std/encoding/encodingName.html /library/std/encoding/encoding_name.html +/library/std/encoding/EncodingSchemeASCII.html /library/std/encoding/encoding_scheme_ascii.html +/library/std/encoding/EncodingScheme.canEncode.html /library/std/encoding/encoding_scheme.can_encode.html +/library/std/encoding/EncodingScheme.count.html /library/std/encoding/encoding_scheme.count.html +/library/std/encoding/EncodingScheme.create.html /library/std/encoding/encoding_scheme.create.html +/library/std/encoding/EncodingScheme.decode.html /library/std/encoding/encoding_scheme.decode.html +/library/std/encoding/EncodingScheme.encodedLength.html /library/std/encoding/encoding_scheme.encoded_length.html +/library/std/encoding/EncodingScheme.encode.html /library/std/encoding/encoding_scheme.encode.html +/library/std/encoding/EncodingScheme.firstSequence.html /library/std/encoding/encoding_scheme.first_sequence.html +/library/std/encoding/EncodingScheme.html /library/std/encoding/encoding_scheme.html +/library/std/encoding/EncodingScheme.index.html /library/std/encoding/encoding_scheme.index.html +/library/std/encoding/EncodingScheme.isValid.html /library/std/encoding/encoding_scheme.is_valid.html +/library/std/encoding/EncodingSchemeLatin1.html /library/std/encoding/encoding_scheme_latin1.html +/library/std/encoding/EncodingScheme.names.html /library/std/encoding/encoding_scheme.names.html +/library/std/encoding/EncodingScheme.register.html /library/std/encoding/encoding_scheme.register.html +/library/std/encoding/EncodingScheme.replacementSequence.html /library/std/encoding/encoding_scheme.replacement_sequence.html +/library/std/encoding/EncodingScheme.safeDecode.html /library/std/encoding/encoding_scheme.safe_decode.html +/library/std/encoding/EncodingScheme.sanitize.html /library/std/encoding/encoding_scheme.sanitize.html +/library/std/encoding/EncodingScheme.toString.html /library/std/encoding/encoding_scheme.to_string.html +/library/std/encoding/EncodingSchemeUtf16Native.html /library/std/encoding/encoding_scheme_utf16_native.html +/library/std/encoding/EncodingSchemeUtf32Native.html /library/std/encoding/encoding_scheme_utf32_native.html +/library/std/encoding/EncodingSchemeUtf8.html /library/std/encoding/encoding_scheme_utf8.html +/library/std/encoding/EncodingScheme.validLength.html /library/std/encoding/encoding_scheme.valid_length.html +/library/std/encoding/EncodingSchemeWindows1252.html /library/std/encoding/encoding_scheme_windows1252.html +/library/std/encoding/firstSequence.html /library/std/encoding/first_sequence.html +/library/std/encoding/INVALID_SEQUENCE.html /library/std/encoding/invali_d_sequence.html +/library/std/encoding/isValidCodePoint.html /library/std/encoding/is_valid_code_point.html +/library/std/encoding/isValidCodeUnit.html /library/std/encoding/is_valid_code_unit.html +/library/std/encoding/isValid.html /library/std/encoding/is_valid.html +/library/std/encoding/lastSequence.html /library/std/encoding/last_sequence.html +/library/std/encoding/Latin1Char.html /library/std/encoding/latin1_char.html +/library/std/encoding/Latin1String.html /library/std/encoding/latin1_string.html +/library/std/encoding/Object.factory.html /library/std/encoding/object.factory.html +/library/std/encoding/Object.opCmp.html /library/std/encoding/object.op_cmp.html +/library/std/encoding/Object.opEquals.html /library/std/encoding/object.op_equals.html +/library/std/encoding/Object.toHash.html /library/std/encoding/object.to_hash.html +/library/std/encoding/Object.toString.html /library/std/encoding/object.to_string.html +/library/std/encoding/safeDecode.html /library/std/encoding/safe_decode.html +/library/std/encoding/Throwable.file.html /library/std/encoding/throwable.file.html +/library/std/encoding/Throwable.info.html /library/std/encoding/throwable.info.html +/library/std/encoding/Throwable.line.html /library/std/encoding/throwable.line.html +/library/std/encoding/Throwable.msg.html /library/std/encoding/throwable.msg.html +/library/std/encoding/Throwable.next.html /library/std/encoding/throwable.next.html +/library/std/encoding/Throwable.toString.html /library/std/encoding/throwable.to_string.html +/library/std/encoding/validLength.html /library/std/encoding/valid_length.html +/library/std/encoding/Windows1252Char.html /library/std/encoding/windows1252_char.html +/library/std/encoding/Windows1252String.html /library/std/encoding/windows1252_string.html +/library/std/exception/assertNotThrown.html /library/std/exception/assert_not_thrown.html +/library/std/exception/assertThrown.html /library/std/exception/assert_thrown.html +/library/std/exception/assumeUnique.html /library/std/exception/assume_unique.html +/library/std/exception/assumeWontThrow.html /library/std/exception/assume_wont_throw.html +/library/std/exception/collectException.html /library/std/exception/collect_exception.html +/library/std/exception/collectExceptionMsg.html /library/std/exception/collect_exception_msg.html +/library/std/exception/doesPointTo.html /library/std/exception/does_point_to.html +/library/std/exception/emptyExceptionMsg.html /library/std/exception/empty_exception_msg.html +/library/std/exception/enforceEx.enforceEx.html /library/std/exception/enforce_ex.enforce_ex.html +/library/std/exception/enforceEx.html /library/std/exception/enforce_ex.html +/library/std/exception/errnoEnforce.html /library/std/exception/errno_enforce.html +/library/std/exception/ErrnoException.errno.html /library/std/exception/errno_exception.errno.html +/library/std/exception/ErrnoException.html /library/std/exception/errno_exception.html +/library/std/exception/ifThrown.html /library/std/exception/if_thrown.html +/library/std/exception/Object.factory.html /library/std/exception/object.factory.html +/library/std/exception/Object.opCmp.html /library/std/exception/object.op_cmp.html +/library/std/exception/Object.opEquals.html /library/std/exception/object.op_equals.html +/library/std/exception/Object.toHash.html /library/std/exception/object.to_hash.html +/library/std/exception/RangePrimitive.access.html /library/std/exception/range_primitive.access.html +/library/std/exception/RangePrimitive.back.html /library/std/exception/range_primitive.back.html +/library/std/exception/RangePrimitive.empty.html /library/std/exception/range_primitive.empty.html +/library/std/exception/RangePrimitive.html /library/std/exception/range_primitive.html +/library/std/exception/RangePrimitive.length.html /library/std/exception/range_primitive.length.html +/library/std/exception/RangePrimitive.opDollar.html /library/std/exception/range_primitive.op_dollar.html +/library/std/exception/RangePrimitive.opIndex.html /library/std/exception/range_primitive.op_index.html +/library/std/exception/RangePrimitive.opSlice.html /library/std/exception/range_primitive.op_slice.html +/library/std/exception/RangePrimitive.popBack.html /library/std/exception/range_primitive.pop_back.html +/library/std/exception/RangePrimitive.popFront.html /library/std/exception/range_primitive.pop_front.html +/library/std/exception/RangePrimitive.pop.html /library/std/exception/range_primitive.pop.html +/library/std/exception/RangePrimitive.save.html /library/std/exception/range_primitive.save.html +/library/std/exception/Throwable.file.html /library/std/exception/throwable.file.html +/library/std/exception/Throwable.info.html /library/std/exception/throwable.info.html +/library/std/exception/Throwable.line.html /library/std/exception/throwable.line.html +/library/std/exception/Throwable.msg.html /library/std/exception/throwable.msg.html +/library/std/exception/Throwable.next.html /library/std/exception/throwable.next.html +/library/std/exception/Throwable.toString.html /library/std/exception/throwable.to_string.html +/library/std/file/attrIsDir.html /library/std/file/attr_is_dir.html +/library/std/file/attrIsFile.html /library/std/file/attr_is_file.html +/library/std/file/attrIsSymlink.html /library/std/file/attr_is_symlink.html +/library/std/file/dirEntries.html /library/std/file/dir_entries.html +/library/std/file/DirEntry.attributes.html /library/std/file/dir_entry.attributes.html +/library/std/file/DirEntry.html /library/std/file/dir_entry.html +/library/std/file/DirEntry.isDir.html /library/std/file/dir_entry.is_dir.html +/library/std/file/DirEntry.isFile.html /library/std/file/dir_entry.is_file.html +/library/std/file/DirEntry.isSymlink.html /library/std/file/dir_entry.is_symlink.html +/library/std/file/DirEntry.linkAttributes.html /library/std/file/dir_entry.link_attributes.html +/library/std/file/DirEntry.name.html /library/std/file/dir_entry.name.html +/library/std/file/DirEntry.size.html /library/std/file/dir_entry.size.html +/library/std/file/DirEntry.statBuf.html /library/std/file/dir_entry.stat_buf.html +/library/std/file/DirEntry.this.html /library/std/file/dir_entry.this.html +/library/std/file/DirEntry.timeCreated.html /library/std/file/dir_entry.time_created.html +/library/std/file/DirEntry.timeLastAccessed.html /library/std/file/dir_entry.time_last_accessed.html +/library/std/file/DirEntry.timeLastModified.html /library/std/file/dir_entry.time_last_modified.html +/library/std/file/FileException.errno.html /library/std/file/file_exception.errno.html +/library/std/file/FileException.html /library/std/file/file_exception.html +/library/std/file/FileException.this.html /library/std/file/file_exception.this.html +/library/std/file/getAttributes.html /library/std/file/get_attributes.html +/library/std/file/getLinkAttributes.html /library/std/file/get_link_attributes.html +/library/std/file/getSize.html /library/std/file/get_size.html +/library/std/file/getTimes.html /library/std/file/get_times.html +/library/std/file/getTimesWin.html /library/std/file/get_times_win.html +/library/std/file/isDir.html /library/std/file/is_dir.html +/library/std/file/isFile.html /library/std/file/is_file.html +/library/std/file/isSymlink.html /library/std/file/is_symlink.html +/library/std/file/mkdirRecurse.html /library/std/file/mkdir_recurse.html +/library/std/file/Object.factory.html /library/std/file/object.factory.html +/library/std/file/Object.opCmp.html /library/std/file/object.op_cmp.html +/library/std/file/Object.opEquals.html /library/std/file/object.op_equals.html +/library/std/file/Object.toHash.html /library/std/file/object.to_hash.html +/library/std/file/preserveAttributesDefault.html /library/std/file/preserve_attributes_default.html +/library/std/file/readLink.html /library/std/file/read_link.html +/library/std/file/readText.html /library/std/file/read_text.html +/library/std/file/rmdirRecurse.html /library/std/file/rmdir_recurse.html +/library/std/file/setAttributes.html /library/std/file/set_attributes.html +/library/std/file/setTimes.html /library/std/file/set_times.html +/library/std/file/SpanMode.breadth.html /library/std/file/span_mode.breadth.html +/library/std/file/SpanMode.depth.html /library/std/file/span_mode.depth.html +/library/std/file/SpanMode.html /library/std/file/span_mode.html +/library/std/file/SpanMode.shallow.html /library/std/file/span_mode.shallow.html +/library/std/file/tempDir.html /library/std/file/temp_dir.html +/library/std/file/thisExePath.html /library/std/file/this_exe_path.html +/library/std/file/Throwable.file.html /library/std/file/throwable.file.html +/library/std/file/Throwable.info.html /library/std/file/throwable.info.html +/library/std/file/Throwable.line.html /library/std/file/throwable.line.html +/library/std/file/Throwable.msg.html /library/std/file/throwable.msg.html +/library/std/file/Throwable.next.html /library/std/file/throwable.next.html +/library/std/file/Throwable.toString.html /library/std/file/throwable.to_string.html +/library/std/file/timeLastModified.html /library/std/file/time_last_modified.html +/library/std/functional/binaryFun.html /library/std/functional/binary_fun.html +/library/std/functional/binaryReverseArgs.binaryReverseArgs.html /library/std/functional/binary_reverse_args.binary_reverse_args.html +/library/std/functional/binaryReverseArgs.html /library/std/functional/binary_reverse_args.html +/library/std/functional/equalTo.html /library/std/functional/equal_to.html +/library/std/functional/greaterThan.html /library/std/functional/greater_than.html +/library/std/functional/lessThan.html /library/std/functional/less_than.html +/library/std/functional/reverseArgs.html /library/std/functional/reverse_args.html +/library/std/functional/reverseArgs.reverseArgs.html /library/std/functional/reverse_args.reverse_args.html +/library/std/functional/toDelegate.html /library/std/functional/to_delegate.html +/library/std/functional/unaryFun.html /library/std/functional/unary_fun.html +/library/std/getopt/arraySep.html /library/std/getopt/array_sep.html +/library/std/getopt/assignChar.html /library/std/getopt/assign_char.html +/library/std/getopt/config.caseInsensitive.html /library/std/getopt/config.case_insensitive.html +/library/std/getopt/config.caseSensitive.html /library/std/getopt/config.case_sensitive.html +/library/std/getopt/config.keepEndOfOptions.html /library/std/getopt/config.keep_end_of_options.html +/library/std/getopt/config.noBundling.html /library/std/getopt/config.no_bundling.html +/library/std/getopt/config.noPassThrough.html /library/std/getopt/config.no_pass_through.html +/library/std/getopt/config.passThrough.html /library/std/getopt/config.pass_through.html +/library/std/getopt/config.stopOnFirstNonOption.html /library/std/getopt/config.stop_on_first_non_option.html +/library/std/getopt/defaultGetoptFormatter.html /library/std/getopt/default_getopt_formatter.html +/library/std/getopt/defaultGetoptPrinter.html /library/std/getopt/default_getopt_printer.html +/library/std/getopt/endOfOptions.html /library/std/getopt/end_of_options.html +/library/std/getopt/GetOptException.html /library/std/getopt/get_opt_exception.html +/library/std/getopt/GetoptResult.helpWanted.html /library/std/getopt/getopt_result.help_wanted.html +/library/std/getopt/GetoptResult.html /library/std/getopt/getopt_result.html +/library/std/getopt/GetoptResult.options.html /library/std/getopt/getopt_result.options.html +/library/std/getopt/Object.factory.html /library/std/getopt/object.factory.html +/library/std/getopt/Object.opCmp.html /library/std/getopt/object.op_cmp.html +/library/std/getopt/Object.opEquals.html /library/std/getopt/object.op_equals.html +/library/std/getopt/Object.toHash.html /library/std/getopt/object.to_hash.html +/library/std/getopt/optionChar.html /library/std/getopt/option_char.html +/library/std/getopt/Option.help.html /library/std/getopt/option.help.html +/library/std/getopt/Option.html /library/std/getopt/option.html +/library/std/getopt/Option.optLong.html /library/std/getopt/option.opt_long.html +/library/std/getopt/Option.optShort.html /library/std/getopt/option.opt_short.html +/library/std/getopt/Option.required.html /library/std/getopt/option.required.html +/library/std/getopt/Throwable.file.html /library/std/getopt/throwable.file.html +/library/std/getopt/Throwable.info.html /library/std/getopt/throwable.info.html +/library/std/getopt/Throwable.line.html /library/std/getopt/throwable.line.html +/library/std/getopt/Throwable.msg.html /library/std/getopt/throwable.msg.html +/library/std/getopt/Throwable.next.html /library/std/getopt/throwable.next.html +/library/std/getopt/Throwable.toString.html /library/std/getopt/throwable.to_string.html +/library/std/json/JSONException.html /library/std/json/json_exception.html +/library/std/json/JSON_TYPE.ARRAY.html /library/std/json/jso_n_type.array.html +/library/std/json/JSON_TYPE.FALSE.html /library/std/json/jso_n_type.false.html +/library/std/json/JSON_TYPE.FLOAT.html /library/std/json/jso_n_type.float.html +/library/std/json/JSON_TYPE.html /library/std/json/jso_n_type.html +/library/std/json/JSON_TYPE.INTEGER.html /library/std/json/jso_n_type.integer.html +/library/std/json/JSON_TYPE.NULL.html /library/std/json/jso_n_type.null.html +/library/std/json/JSON_TYPE.OBJECT.html /library/std/json/jso_n_type.object.html +/library/std/json/JSON_TYPE.STRING.html /library/std/json/jso_n_type.string.html +/library/std/json/JSON_TYPE.TRUE.html /library/std/json/jso_n_type.true.html +/library/std/json/JSON_TYPE.UINTEGER.html /library/std/json/jso_n_type.uinteger.html +/library/std/json/JSONValue.array.html /library/std/json/json_value.array.html +/library/std/json/JSONValue.floating.html /library/std/json/json_value.floating.html +/library/std/json/JSONValue.html /library/std/json/json_value.html +/library/std/json/JSONValue.integer.html /library/std/json/json_value.integer.html +/library/std/json/JSONValue.isNull.html /library/std/json/json_value.is_null.html +/library/std/json/JSONValue.object.html /library/std/json/json_value.object.html +/library/std/json/JSONValue.opApply.html /library/std/json/json_value.op_apply.html +/library/std/json/JSONValue.opIndexAssign.html /library/std/json/json_value.op_index_assign.html +/library/std/json/JSONValue.opIndex.html /library/std/json/json_value.op_index.html +/library/std/json/JSONValue.str.html /library/std/json/json_value.str.html +/library/std/json/JSONValue.this.html /library/std/json/json_value.this.html +/library/std/json/JSONValue.toPrettyString.html /library/std/json/json_value.to_pretty_string.html +/library/std/json/JSONValue.toString.html /library/std/json/json_value.to_string.html +/library/std/json/JSONValue.type.html /library/std/json/json_value.type.html +/library/std/json/JSONValue.uinteger.html /library/std/json/json_value.uinteger.html +/library/std/json/Object.factory.html /library/std/json/object.factory.html +/library/std/json/Object.opCmp.html /library/std/json/object.op_cmp.html +/library/std/json/Object.opEquals.html /library/std/json/object.op_equals.html +/library/std/json/Object.toHash.html /library/std/json/object.to_hash.html +/library/std/json/parseJSON.html /library/std/json/parse_json.html +/library/std/json/Throwable.file.html /library/std/json/throwable.file.html +/library/std/json/Throwable.info.html /library/std/json/throwable.info.html +/library/std/json/Throwable.line.html /library/std/json/throwable.line.html +/library/std/json/Throwable.msg.html /library/std/json/throwable.msg.html +/library/std/json/Throwable.next.html /library/std/json/throwable.next.html +/library/std/json/Throwable.toString.html /library/std/json/throwable.to_string.html +/library/std/json/toJSON.html /library/std/json/to_json.html +/library/std/math/approxEqual.html /library/std/math/approx_equal.html +/library/std/math/E.html /library/std/math/e.html +/library/std/math/FloatingPointControl.disableExceptions.html /library/std/math/floating_point_control.disable_exceptions.html +/library/std/math/FloatingPointControl.enabledExceptions.html /library/std/math/floating_point_control.enabled_exceptions.html +/library/std/math/FloatingPointControl.enableExceptions.html /library/std/math/floating_point_control.enable_exceptions.html +/library/std/math/FloatingPointControl.hasExceptionTraps.html /library/std/math/floating_point_control.has_exception_traps.html +/library/std/math/FloatingPointControl.html /library/std/math/floating_point_control.html +/library/std/math/FloatingPointControl.rounding.html /library/std/math/floating_point_control.rounding.html +/library/std/math/FloatingPointControl.severeExceptions.html /library/std/math/floating_point_control.severe_exceptions.html +/library/std/math/getNaNPayload.html /library/std/math/get_nan_payload.html +/library/std/math/IeeeFlags.divByZero.html /library/std/math/ieee_flags.div_by_zero.html +/library/std/math/ieeeFlags.html /library/std/math/ieee_flags.html +/library/std/math/IeeeFlags.html /library/std/math/ieee_flags.html +/library/std/math/IeeeFlags.inexact.html /library/std/math/ieee_flags.inexact.html +/library/std/math/IeeeFlags.invalid.html /library/std/math/ieee_flags.invalid.html +/library/std/math/IeeeFlags.overflow.html /library/std/math/ieee_flags.overflow.html +/library/std/math/IeeeFlags.underflow.html /library/std/math/ieee_flags.underflow.html +/library/std/math/isFinite.html /library/std/math/is_finite.html +/library/std/math/isIdentical.html /library/std/math/is_identical.html +/library/std/math/isInfinity.html /library/std/math/is_infinity.html +/library/std/math/isNaN.html /library/std/math/is_nan.html +/library/std/math/isNormal.html /library/std/math/is_normal.html +/library/std/math/isSubnormal.html /library/std/math/is_subnormal.html +/library/std/math/LN10.html /library/std/math/l_n10.html +/library/std/math/LN2.html /library/std/math/l_n2.html +/library/std/math/LOG10E.html /library/std/math/lo_g10.html +/library/std/math/LOG2E.html /library/std/math/lo_g2e.html +/library/std/math/LOG2.html /library/std/math/lo_g2.html +/library/std/math/LOG2T.html /library/std/math/lo_g2t.html +/library/std/math/M_1_PI.html /library/std/math/m_1__pi.html +/library/std/math/M_2_PI.html /library/std/math/m_2__pi.html +/library/std/math/M_2_SQRTPI.html /library/std/math/m_2__sqrtpi.html +/library/std/math/NaN.html /library/std/math/nan.html +/library/std/math/nextDown.html /library/std/math/next_down.html +/library/std/math/nextUp.html /library/std/math/next_up.html +/library/std/math/PI_2.html /library/std/math/p_i_2.html +/library/std/math/PI_4.html /library/std/math/p_i_4.html +/library/std/math/PI.html /library/std/math/pi.html +/library/std/math/resetIeeeFlags.html /library/std/math/reset_ieee_flags.html +/library/std/mathspecial/betaIncomplete.html /library/std/mathspecial/beta_incomplete.html +/library/std/mathspecial/betaIncompleteInverse.html /library/std/mathspecial/beta_incomplete_inverse.html +/library/std/mathspecial/gammaIncompleteCompl.html /library/std/mathspecial/gamma_incomplete_compl.html +/library/std/mathspecial/gammaIncompleteComplInverse.html /library/std/mathspecial/gamma_incomplete_compl_inverse.html +/library/std/mathspecial/gammaIncomplete.html /library/std/mathspecial/gamma_incomplete.html +/library/std/mathspecial/logGamma.html /library/std/mathspecial/log_gamma.html +/library/std/mathspecial/normalDistribution.html /library/std/mathspecial/normal_distribution.html +/library/std/mathspecial/normalDistributionInverse.html /library/std/mathspecial/normal_distribution_inverse.html +/library/std/mathspecial/sgnGamma.html /library/std/mathspecial/sgn_gamma.html +/library/std/math/SQRT1_2.html /library/std/math/sqr_t1_2.html +/library/std/math/SQRT2.html /library/std/math/sqr_t2.html +/library/std/mmfile/MmFile.html /library/std/mmfile/mm_file.html +/library/std/mmfile/MmFile.length.html /library/std/mmfile/mm_file.length.html +/library/std/mmfile/MmFile.mode.html /library/std/mmfile/mm_file.mode.html +/library/std/mmfile/MmFile.Mode.html /library/std/mmfile/mm_file.mode.html +/library/std/mmfile/MmFile.Mode.readCopyOnWrite.html /library/std/mmfile/mm_file.mode.read_copy_on_write.html +/library/std/mmfile/MmFile.Mode.read.html /library/std/mmfile/mm_file.mode.read.html +/library/std/mmfile/MmFile.Mode.readWrite.html /library/std/mmfile/mm_file.mode.read_write.html +/library/std/mmfile/MmFile.Mode.readWriteNew.html /library/std/mmfile/mm_file.mode.read_write_new.html +/library/std/mmfile/MmFile.opIndexAssign.html /library/std/mmfile/mm_file.op_index_assign.html +/library/std/mmfile/MmFile.opIndex.html /library/std/mmfile/mm_file.op_index.html +/library/std/mmfile/MmFile.opSlice.html /library/std/mmfile/mm_file.op_slice.html +/library/std/mmfile/MmFile.this.html /library/std/mmfile/mm_file.this.html +/library/std/mmfile/Object.factory.html /library/std/mmfile/object.factory.html +/library/std/mmfile/Object.opCmp.html /library/std/mmfile/object.op_cmp.html +/library/std/mmfile/Object.opEquals.html /library/std/mmfile/object.op_equals.html +/library/std/mmfile/Object.toHash.html /library/std/mmfile/object.to_hash.html +/library/std/mmfile/Object.toString.html /library/std/mmfile/object.to_string.html +/library/std/net/curl/AutoProtocol.html /library/std/net/curl/auto_protocol.html +/library/std/net/curl/byChunkAsync.html /library/std/net/curl/by_chunk_async.html +/library/std/net/curl/byChunk.html /library/std/net/curl/by_chunk.html +/library/std/net/curl/byLineAsync.html /library/std/net/curl/by_line_async.html +/library/std/net/curl/byLine.html /library/std/net/curl/by_line.html +/library/std/net/curl/Curl.clear.html /library/std/net/curl/curl.clear.html +/library/std/net/curl/Curl.clearIfSupported.html /library/std/net/curl/curl.clear_if_supported.html +/library/std/net/curl/CurlCode.html /library/std/net/curl/curl_code.html +/library/std/net/curl/Curl.dup.html /library/std/net/curl/curl.dup.html +/library/std/net/curl/CurlException.html /library/std/net/curl/curl_exception.html +/library/std/net/curl/CurlException.this.html /library/std/net/curl/curl_exception.this.html +/library/std/net/curl/Curl.html /library/std/net/curl/curl.html +/library/std/net/curl/Curl.initialize.html /library/std/net/curl/curl.initialize.html +/library/std/net/curl/Curl.onProgress.html /library/std/net/curl/curl.on_progress.html +/library/std/net/curl/Curl.onReceiveHeader.html /library/std/net/curl/curl.on_receive_header.html +/library/std/net/curl/Curl.onReceive.html /library/std/net/curl/curl.on_receive.html +/library/std/net/curl/Curl.onSeek.html /library/std/net/curl/curl.on_seek.html +/library/std/net/curl/Curl.onSend.html /library/std/net/curl/curl.on_send.html +/library/std/net/curl/Curl.onSocketOption.html /library/std/net/curl/curl.on_socket_option.html +/library/std/net/curl/Curl.pause.html /library/std/net/curl/curl.pause.html +/library/std/net/curl/Curl.perform.html /library/std/net/curl/curl.perform.html +/library/std/net/curl/Curl.set.html /library/std/net/curl/curl.set.html +/library/std/net/curl/Curl.shutdown.html /library/std/net/curl/curl.shutdown.html +/library/std/net/curl/CurlTimeoutException.html /library/std/net/curl/curl_timeout_exception.html +/library/std/net/curl/CurlTimeoutException.this.html /library/std/net/curl/curl_timeout_exception.this.html +/library/std/net/curl/FTP.addCommand.html /library/std/net/curl/ftp.add_command.html +/library/std/net/curl/FTP.clearCommands.html /library/std/net/curl/ftp.clear_commands.html +/library/std/net/curl/FTP.connectTimeout.html /library/std/net/curl/ftp.connect_timeout.html +/library/std/net/curl/FTP.contentLength.html /library/std/net/curl/ftp.content_length.html +/library/std/net/curl/FTP.CurlProxy.html /library/std/net/curl/ftp.curl_proxy.html +/library/std/net/curl/FTP.dataTimeout.html /library/std/net/curl/ftp.data_timeout.html +/library/std/net/curl/FTP.dnsTimeout.html /library/std/net/curl/ftp.dns_timeout.html +/library/std/net/curl/FTP.encoding.html /library/std/net/curl/ftp.encoding.html +/library/std/net/curl/FTP.html /library/std/net/curl/ftp.html +/library/std/net/curl/FTP.isStopped.html /library/std/net/curl/ftp.is_stopped.html +/library/std/net/curl/FTP.localPort.html /library/std/net/curl/ftp.local_port.html +/library/std/net/curl/FTP.localPortRange.html /library/std/net/curl/ftp.local_port_range.html +/library/std/net/curl/FTP.netInterface.html /library/std/net/curl/ftp.net_interface.html +/library/std/net/curl/FTP.onProgress.html /library/std/net/curl/ftp.on_progress.html +/library/std/net/curl/FTP.onReceive.html /library/std/net/curl/ftp.on_receive.html +/library/std/net/curl/FTP.onSend.html /library/std/net/curl/ftp.on_send.html +/library/std/net/curl/FTP.opCall.html /library/std/net/curl/ftp.op_call.html +/library/std/net/curl/FTP.operationTimeout.html /library/std/net/curl/ftp.operation_timeout.html +/library/std/net/curl/FTP.perform.html /library/std/net/curl/ftp.perform.html +/library/std/net/curl/FTP.proxy.html /library/std/net/curl/ftp.proxy.html +/library/std/net/curl/FTP.proxyPort.html /library/std/net/curl/ftp.proxy_port.html +/library/std/net/curl/FTP.proxyType.html /library/std/net/curl/ftp.proxy_type.html +/library/std/net/curl/FTP.requestAbort.html /library/std/net/curl/ftp.request_abort.html +/library/std/net/curl/FTP.requestPause.html /library/std/net/curl/ftp.request_pause.html +/library/std/net/curl/FTP.setAuthentication.html /library/std/net/curl/ftp.set_authentication.html +/library/std/net/curl/FTP.setProxyAuthentication.html /library/std/net/curl/ftp.set_proxy_authentication.html +/library/std/net/curl/FTP.shutdown.html /library/std/net/curl/ftp.shutdown.html +/library/std/net/curl/FTP.tcpNoDelay.html /library/std/net/curl/ftp.tcp_no_delay.html +/library/std/net/curl/FTP.url.html /library/std/net/curl/ftp.url.html +/library/std/net/curl/FTP.verbose.html /library/std/net/curl/ftp.verbose.html +/library/std/net/curl/HTTP.addRequestHeader.html /library/std/net/curl/http.add_request_header.html +/library/std/net/curl/HTTP.authenticationMethod.html /library/std/net/curl/http.authentication_method.html +/library/std/net/curl/HTTP.AuthMethod.html /library/std/net/curl/http.auth_method.html +/library/std/net/curl/HTTP.caInfo.html /library/std/net/curl/http.ca_info.html +/library/std/net/curl/HTTP.clearAllCookies.html /library/std/net/curl/http.clear_all_cookies.html +/library/std/net/curl/HTTP.clearRequestHeaders.html /library/std/net/curl/http.clear_request_headers.html +/library/std/net/curl/HTTP.clearSessionCookies.html /library/std/net/curl/http.clear_session_cookies.html +/library/std/net/curl/HTTP.connectTimeout.html /library/std/net/curl/http.connect_timeout.html +/library/std/net/curl/HTTP.contentLength.html /library/std/net/curl/http.content_length.html +/library/std/net/curl/HTTP.CurlProxy.html /library/std/net/curl/http.curl_proxy.html +/library/std/net/curl/HTTP.dataTimeout.html /library/std/net/curl/http.data_timeout.html +/library/std/net/curl/HTTP.defaultUserAgent.html /library/std/net/curl/http.default_user_agent.html +/library/std/net/curl/HTTP.dnsTimeout.html /library/std/net/curl/http.dns_timeout.html +/library/std/net/curl/HTTP.flushCookieJar.html /library/std/net/curl/http.flush_cookie_jar.html +/library/std/net/curl/HTTP.html /library/std/net/curl/http.html +/library/std/net/curl/HTTP.isStopped.html /library/std/net/curl/http.is_stopped.html +/library/std/net/curl/HTTP.localPort.html /library/std/net/curl/http.local_port.html +/library/std/net/curl/HTTP.localPortRange.html /library/std/net/curl/http.local_port_range.html +/library/std/net/curl/HTTP.maxRedirects.html /library/std/net/curl/http.max_redirects.html +/library/std/net/curl/HTTP.method.html /library/std/net/curl/http.method.html +/library/std/net/curl/HTTP.Method.html /library/std/net/curl/http.method.html +/library/std/net/curl/HTTP.netInterface.html /library/std/net/curl/http.net_interface.html +/library/std/net/curl/HTTP.onProgress.html /library/std/net/curl/http.on_progress.html +/library/std/net/curl/HTTP.onReceiveHeader.html /library/std/net/curl/http.on_receive_header.html +/library/std/net/curl/HTTP.onReceive.html /library/std/net/curl/http.on_receive.html +/library/std/net/curl/HTTP.onReceiveStatusLine.html /library/std/net/curl/http.on_receive_status_line.html +/library/std/net/curl/HTTP.onSend.html /library/std/net/curl/http.on_send.html +/library/std/net/curl/HTTP.opCall.html /library/std/net/curl/http.op_call.html +/library/std/net/curl/HTTP.operationTimeout.html /library/std/net/curl/http.operation_timeout.html +/library/std/net/curl/HTTP.perform.html /library/std/net/curl/http.perform.html +/library/std/net/curl/HTTP.postData.html /library/std/net/curl/http.post_data.html +/library/std/net/curl/HTTP.proxy.html /library/std/net/curl/http.proxy.html +/library/std/net/curl/HTTP.proxyPort.html /library/std/net/curl/http.proxy_port.html +/library/std/net/curl/HTTP.proxyType.html /library/std/net/curl/http.proxy_type.html +/library/std/net/curl/HTTP.requestAbort.html /library/std/net/curl/http.request_abort.html +/library/std/net/curl/HTTP.requestPause.html /library/std/net/curl/http.request_pause.html +/library/std/net/curl/HTTP.responseHeaders.html /library/std/net/curl/http.response_headers.html +/library/std/net/curl/HTTP.setAuthentication.html /library/std/net/curl/http.set_authentication.html +/library/std/net/curl/HTTP.setCookie.html /library/std/net/curl/http.set_cookie.html +/library/std/net/curl/HTTP.setCookieJar.html /library/std/net/curl/http.set_cookie_jar.html +/library/std/net/curl/HTTP.setPostData.html /library/std/net/curl/http.set_post_data.html +/library/std/net/curl/HTTP.setProxyAuthentication.html /library/std/net/curl/http.set_proxy_authentication.html +/library/std/net/curl/HTTP.setTimeCondition.html /library/std/net/curl/http.set_time_condition.html +/library/std/net/curl/HTTP.setUserAgent.html /library/std/net/curl/http.set_user_agent.html +/library/std/net/curl/HTTP.shutdown.html /library/std/net/curl/http.shutdown.html +/library/std/net/curl/HTTP.StatusLine.code.html /library/std/net/curl/http.status_line.code.html +/library/std/net/curl/HTTP.statusLine.html /library/std/net/curl/http.status_line.html +/library/std/net/curl/HTTP.StatusLine.html /library/std/net/curl/http.status_line.html +/library/std/net/curl/HTTP.StatusLine.majorVersion.html /library/std/net/curl/http.status_line.major_version.html +/library/std/net/curl/HTTP.StatusLine.minorVersion.html /library/std/net/curl/http.status_line.minor_version.html +/library/std/net/curl/HTTP.StatusLine.reason.html /library/std/net/curl/http.status_line.reason.html +/library/std/net/curl/HTTP.StatusLine.reset.html /library/std/net/curl/http.status_line.reset.html +/library/std/net/curl/HTTP.tcpNoDelay.html /library/std/net/curl/http.tcp_no_delay.html +/library/std/net/curl/HTTP.TimeCond.html /library/std/net/curl/http.time_cond.html +/library/std/net/curl/HTTP.url.html /library/std/net/curl/http.url.html +/library/std/net/curl/HTTP.verbose.html /library/std/net/curl/http.verbose.html +/library/std/net/curl/Object.factory.html /library/std/net/curl/object.factory.html +/library/std/net/curl/Object.opCmp.html /library/std/net/curl/object.op_cmp.html +/library/std/net/curl/Object.opEquals.html /library/std/net/curl/object.op_equals.html +/library/std/net/curl/Object.toHash.html /library/std/net/curl/object.to_hash.html +/library/std/net/curl/SMTP.connectTimeout.html /library/std/net/curl/smtp.connect_timeout.html +/library/std/net/curl/SMTP.CurlProxy.html /library/std/net/curl/smtp.curl_proxy.html +/library/std/net/curl/SMTP.dataTimeout.html /library/std/net/curl/smtp.data_timeout.html +/library/std/net/curl/SMTP.dnsTimeout.html /library/std/net/curl/smtp.dns_timeout.html +/library/std/net/curl/SMTP.html /library/std/net/curl/smtp.html +/library/std/net/curl/SMTP.isStopped.html /library/std/net/curl/smtp.is_stopped.html +/library/std/net/curl/SMTP.localPort.html /library/std/net/curl/smtp.local_port.html +/library/std/net/curl/SMTP.localPortRange.html /library/std/net/curl/smtp.local_port_range.html +/library/std/net/curl/SMTP.mailFrom.html /library/std/net/curl/smtp.mail_from.html +/library/std/net/curl/SMTP.mailTo.html /library/std/net/curl/smtp.mail_to.html +/library/std/net/curl/SMTP.message.html /library/std/net/curl/smtp.message.html +/library/std/net/curl/SMTP.netInterface.html /library/std/net/curl/smtp.net_interface.html +/library/std/net/curl/SMTP.onProgress.html /library/std/net/curl/smtp.on_progress.html +/library/std/net/curl/SMTP.onReceive.html /library/std/net/curl/smtp.on_receive.html +/library/std/net/curl/SMTP.onSend.html /library/std/net/curl/smtp.on_send.html +/library/std/net/curl/SMTP.opCall.html /library/std/net/curl/smtp.op_call.html +/library/std/net/curl/SMTP.operationTimeout.html /library/std/net/curl/smtp.operation_timeout.html +/library/std/net/curl/SMTP.perform.html /library/std/net/curl/smtp.perform.html +/library/std/net/curl/SMTP.proxy.html /library/std/net/curl/smtp.proxy.html +/library/std/net/curl/SMTP.proxyPort.html /library/std/net/curl/smtp.proxy_port.html +/library/std/net/curl/SMTP.proxyType.html /library/std/net/curl/smtp.proxy_type.html +/library/std/net/curl/SMTP.requestAbort.html /library/std/net/curl/smtp.request_abort.html +/library/std/net/curl/SMTP.requestPause.html /library/std/net/curl/smtp.request_pause.html +/library/std/net/curl/SMTP.setAuthentication.html /library/std/net/curl/smtp.set_authentication.html +/library/std/net/curl/SMTP.setProxyAuthentication.html /library/std/net/curl/smtp.set_proxy_authentication.html +/library/std/net/curl/SMTP.shutdown.html /library/std/net/curl/smtp.shutdown.html +/library/std/net/curl/SMTP.tcpNoDelay.html /library/std/net/curl/smtp.tcp_no_delay.html +/library/std/net/curl/SMTP.url.html /library/std/net/curl/smtp.url.html +/library/std/net/curl/SMTP.verbose.html /library/std/net/curl/smtp.verbose.html +/library/std/net/curl/Throwable.file.html /library/std/net/curl/throwable.file.html +/library/std/net/curl/Throwable.info.html /library/std/net/curl/throwable.info.html +/library/std/net/curl/Throwable.line.html /library/std/net/curl/throwable.line.html +/library/std/net/curl/Throwable.msg.html /library/std/net/curl/throwable.msg.html +/library/std/net/curl/Throwable.next.html /library/std/net/curl/throwable.next.html +/library/std/net/curl/Throwable.toString.html /library/std/net/curl/throwable.to_string.html +/library/std/net/curl/ThrowOnError.html /library/std/net/curl/throw_on_error.html +/library/std/net/isemail/CheckDns.html /library/std/net/isemail/check_dns.html +/library/std/net/isemail/CheckDns.no.html /library/std/net/isemail/check_dns.no.html +/library/std/net/isemail/CheckDns.yes.html /library/std/net/isemail/check_dns.yes.html +/library/std/net/isemail/EmailStatusCode.any.html /library/std/net/isemail/email_status_code.any.html +/library/std/net/isemail/EmailStatusCode.cFoldingWhitespace.html /library/std/net/isemail/email_status_code.c_folding_whitespace.html +/library/std/net/isemail/EmailStatusCode.comment.html /library/std/net/isemail/email_status_code.comment.html +/library/std/net/isemail/EmailStatusCode.deprecatedCommentFoldingWhitespaceNearAt.html /library/std/net/isemail/email_status_code.deprecated_comment_folding_whitespace_near_at.html +/library/std/net/isemail/EmailStatusCode.deprecatedComment.html /library/std/net/isemail/email_status_code.deprecated_comment.html +/library/std/net/isemail/EmailStatusCode.deprecatedCommentText.html /library/std/net/isemail/email_status_code.deprecated_comment_text.html +/library/std/net/isemail/EmailStatusCode.deprecatedFoldingWhitespace.html /library/std/net/isemail/email_status_code.deprecated_folding_whitespace.html +/library/std/net/isemail/EmailStatusCode.deprecated_.html /library/std/net/isemail/email_status_code.deprecated_.html +/library/std/net/isemail/EmailStatusCode.deprecatedLocalPart.html /library/std/net/isemail/email_status_code.deprecated_local_part.html +/library/std/net/isemail/EmailStatusCode.deprecatedQuotedPair.html /library/std/net/isemail/email_status_code.deprecated_quoted_pair.html +/library/std/net/isemail/EmailStatusCode.deprecatedQuotedText.html /library/std/net/isemail/email_status_code.deprecated_quoted_text.html +/library/std/net/isemail/EmailStatusCode.dnsWarning.html /library/std/net/isemail/email_status_code.dns_warning.html +/library/std/net/isemail/EmailStatusCode.dnsWarningNoMXRecord.html /library/std/net/isemail/email_status_code.dns_warning_nomx_record.html +/library/std/net/isemail/EmailStatusCode.dnsWarningNoRecord.html /library/std/net/isemail/email_status_code.dns_warning_no_record.html +/library/std/net/isemail/EmailStatusCode.errorBackslashEnd.html /library/std/net/isemail/email_status_code.error_backslash_end.html +/library/std/net/isemail/EmailStatusCode.errorConsecutiveDots.html /library/std/net/isemail/email_status_code.error_consecutive_dots.html +/library/std/net/isemail/EmailStatusCode.errorCrNoLf.html /library/std/net/isemail/email_status_code.error_cr_no_lf.html +/library/std/net/isemail/EmailStatusCode.errorDomainHyphenEnd.html /library/std/net/isemail/email_status_code.error_domain_hyphen_end.html +/library/std/net/isemail/EmailStatusCode.errorDomainHyphenStart.html /library/std/net/isemail/email_status_code.error_domain_hyphen_start.html +/library/std/net/isemail/EmailStatusCode.errorDotEnd.html /library/std/net/isemail/email_status_code.error_dot_end.html +/library/std/net/isemail/EmailStatusCode.errorDotStart.html /library/std/net/isemail/email_status_code.error_dot_start.html +/library/std/net/isemail/EmailStatusCode.errorExpectingCommentText.html /library/std/net/isemail/email_status_code.error_expecting_comment_text.html +/library/std/net/isemail/EmailStatusCode.errorExpectingDomainText.html /library/std/net/isemail/email_status_code.error_expecting_domain_text.html +/library/std/net/isemail/EmailStatusCode.errorExpectingQuotedPair.html /library/std/net/isemail/email_status_code.error_expecting_quoted_pair.html +/library/std/net/isemail/EmailStatusCode.errorExpectingQuotedText.html /library/std/net/isemail/email_status_code.error_expecting_quoted_text.html +/library/std/net/isemail/EmailStatusCode.errorExpectingText.html /library/std/net/isemail/email_status_code.error_expecting_text.html +/library/std/net/isemail/EmailStatusCode.errorFoldingWhitespaceCrflX2.html /library/std/net/isemail/email_status_code.error_folding_whitespace_crfl_x2.html +/library/std/net/isemail/EmailStatusCode.errorFoldingWhitespaceCrLfEnd.html /library/std/net/isemail/email_status_code.error_folding_whitespace_cr_lf_end.html +/library/std/net/isemail/EmailStatusCode.error.html /library/std/net/isemail/email_status_code.error.html +/library/std/net/isemail/EmailStatusCode.errorNoDomain.html /library/std/net/isemail/email_status_code.error_no_domain.html +/library/std/net/isemail/EmailStatusCode.errorNoLocalPart.html /library/std/net/isemail/email_status_code.error_no_local_part.html +/library/std/net/isemail/EmailStatusCode.errorTextAfterCommentFoldingWhitespace.html /library/std/net/isemail/email_status_code.error_text_after_comment_folding_whitespace.html +/library/std/net/isemail/EmailStatusCode.errorTextAfterDomainLiteral.html /library/std/net/isemail/email_status_code.error_text_after_domain_literal.html +/library/std/net/isemail/EmailStatusCode.errorTextAfterQuotedString.html /library/std/net/isemail/email_status_code.error_text_after_quoted_string.html +/library/std/net/isemail/EmailStatusCode.errorUnclosedComment.html /library/std/net/isemail/email_status_code.error_unclosed_comment.html +/library/std/net/isemail/EmailStatusCode.errorUnclosedDomainLiteral.html /library/std/net/isemail/email_status_code.error_unclosed_domain_literal.html +/library/std/net/isemail/EmailStatusCode.errorUnclosedQuotedString.html /library/std/net/isemail/email_status_code.error_unclosed_quoted_string.html +/library/std/net/isemail/EmailStatusCode.foldingWhitespace.html /library/std/net/isemail/email_status_code.folding_whitespace.html +/library/std/net/isemail/EmailStatusCode.html /library/std/net/isemail/email_status_code.html +/library/std/net/isemail/EmailStatusCode.none.html /library/std/net/isemail/email_status_code.none.html +/library/std/net/isemail/EmailStatusCode.rfc5321AddressLiteral.html /library/std/net/isemail/email_status_code.rfc5321_address_literal.html +/library/std/net/isemail/EmailStatusCode.rfc5321.html /library/std/net/isemail/email_status_code.rfc5321.html +/library/std/net/isemail/EmailStatusCode.rfc5321IpV6Deprecated.html /library/std/net/isemail/email_status_code.rfc5321_ip_v6_deprecated.html +/library/std/net/isemail/EmailStatusCode.rfc5321QuotedString.html /library/std/net/isemail/email_status_code.rfc5321_quoted_string.html +/library/std/net/isemail/EmailStatusCode.rfc5321TopLevelDomain.html /library/std/net/isemail/email_status_code.rfc5321_top_level_domain.html +/library/std/net/isemail/EmailStatusCode.rfc5321TopLevelDomainNumeric.html /library/std/net/isemail/email_status_code.rfc5321_top_level_domain_numeric.html +/library/std/net/isemail/EmailStatusCode.rfc5322Domain.html /library/std/net/isemail/email_status_code.rfc5322_domain.html +/library/std/net/isemail/EmailStatusCode.rfc5322DomainLiteral.html /library/std/net/isemail/email_status_code.rfc5322_domain_literal.html +/library/std/net/isemail/EmailStatusCode.rfc5322DomainLiteralObsoleteText.html /library/std/net/isemail/email_status_code.rfc5322_domain_literal_obsolete_text.html +/library/std/net/isemail/EmailStatusCode.rfc5322DomainTooLong.html /library/std/net/isemail/email_status_code.rfc5322_domain_too_long.html +/library/std/net/isemail/EmailStatusCode.rfc5322.html /library/std/net/isemail/email_status_code.rfc5322.html +/library/std/net/isemail/EmailStatusCode.rfc5322IpV6BadChar.html /library/std/net/isemail/email_status_code.rfc5322_ip_v6_bad_char.html +/library/std/net/isemail/EmailStatusCode.rfc5322IpV6ColonEnd.html /library/std/net/isemail/email_status_code.rfc5322_ip_v6_colon_end.html +/library/std/net/isemail/EmailStatusCode.rfc5322IpV6ColonStart.html /library/std/net/isemail/email_status_code.rfc5322_ip_v6_colon_start.html +/library/std/net/isemail/EmailStatusCode.rfc5322IpV6GroupCount.html /library/std/net/isemail/email_status_code.rfc5322_ip_v6_group_count.html +/library/std/net/isemail/EmailStatusCode.rfc5322IpV6MaxGroups.html /library/std/net/isemail/email_status_code.rfc5322_ip_v6_max_groups.html +/library/std/net/isemail/EmailStatusCode.rfc5322IpV6TooManyDoubleColons.html /library/std/net/isemail/email_status_code.rfc5322_ip_v6_too_many_double_colons.html +/library/std/net/isemail/EmailStatusCode.rfc5322LabelTooLong.html /library/std/net/isemail/email_status_code.rfc5322_label_too_long.html +/library/std/net/isemail/EmailStatusCode.rfc5322LocalTooLong.html /library/std/net/isemail/email_status_code.rfc5322_local_too_long.html +/library/std/net/isemail/EmailStatusCode.rfc5322TooLong.html /library/std/net/isemail/email_status_code.rfc5322_too_long.html +/library/std/net/isemail/EmailStatusCode.validCategory.html /library/std/net/isemail/email_status_code.valid_category.html +/library/std/net/isemail/EmailStatusCode.valid.html /library/std/net/isemail/email_status_code.valid.html +/library/std/net/isemail/EmailStatusCode.warning.html /library/std/net/isemail/email_status_code.warning.html +/library/std/net/isemail/EmailStatus.domainPart.html /library/std/net/isemail/email_status.domain_part.html +/library/std/net/isemail/EmailStatus.html /library/std/net/isemail/email_status.html +/library/std/net/isemail/EmailStatus.localPart.html /library/std/net/isemail/email_status.local_part.html +/library/std/net/isemail/EmailStatus.statusCode.html /library/std/net/isemail/email_status.status_code.html +/library/std/net/isemail/EmailStatus.status.html /library/std/net/isemail/email_status.status.html +/library/std/net/isemail/EmailStatus.toString.html /library/std/net/isemail/email_status.to_string.html +/library/std/net/isemail/EmailStatus.valid.html /library/std/net/isemail/email_status.valid.html +/library/std/net/isemail/isEmail.html /library/std/net/isemail/is_email.html +/library/std/net/isemail/statusCodeDescription.html /library/std/net/isemail/status_code_description.html +/library/std/numeric/cosineSimilarity.html /library/std/numeric/cosine_similarity.html +/library/std/numeric/CustomFloat.dig.html /library/std/numeric/custom_float.dig.html +/library/std/numeric/CustomFloat.epsilon.html /library/std/numeric/custom_float.epsilon.html +/library/std/numeric/CustomFloatFlags.allowDenorm.html /library/std/numeric/custom_float_flags.allow_denorm.html +/library/std/numeric/CustomFloatFlags.allowDenormZeroOnly.html /library/std/numeric/custom_float_flags.allow_denorm_zero_only.html +/library/std/numeric/CustomFloatFlags.html /library/std/numeric/custom_float_flags.html +/library/std/numeric/CustomFloatFlags.ieee.html /library/std/numeric/custom_float_flags.ieee.html +/library/std/numeric/CustomFloatFlags.infinity.html /library/std/numeric/custom_float_flags.infinity.html +/library/std/numeric/CustomFloatFlags.nan.html /library/std/numeric/custom_float_flags.nan.html +/library/std/numeric/CustomFloatFlags.negativeUnsigned.html /library/std/numeric/custom_float_flags.negative_unsigned.html +/library/std/numeric/CustomFloatFlags.none.html /library/std/numeric/custom_float_flags.none.html +/library/std/numeric/CustomFloatFlags.probability.html /library/std/numeric/custom_float_flags.probability.html +/library/std/numeric/CustomFloatFlags.signed.html /library/std/numeric/custom_float_flags.signed.html +/library/std/numeric/CustomFloatFlags.storeNormalized.html /library/std/numeric/custom_float_flags.store_normalized.html +/library/std/numeric/CustomFloat.get.get.html /library/std/numeric/custom_float.get.get.html +/library/std/numeric/CustomFloat.get.html /library/std/numeric/custom_float.get.html +/library/std/numeric/CustomFloat.html /library/std/numeric/custom_float.html +/library/std/numeric/CustomFloat.im.html /library/std/numeric/custom_float.im.html +/library/std/numeric/CustomFloat.mant_dig.html /library/std/numeric/custom_float.mant_dig.html +/library/std/numeric/CustomFloat.max_10_exp.html /library/std/numeric/custom_float.max_10_exp.html +/library/std/numeric/CustomFloat.max_exp.html /library/std/numeric/custom_float.max_exp.html +/library/std/numeric/CustomFloat.max.html /library/std/numeric/custom_float.max.html +/library/std/numeric/CustomFloat.min_10_exp.html /library/std/numeric/custom_float.min_10_exp.html +/library/std/numeric/CustomFloat.min_exp.html /library/std/numeric/custom_float.min_exp.html +/library/std/numeric/CustomFloat.min_normal.html /library/std/numeric/custom_float.min_normal.html +/library/std/numeric/CustomFloat.opAssign.html /library/std/numeric/custom_float.op_assign.html +/library/std/numeric/CustomFloat.opAssign.opAssign.html /library/std/numeric/custom_float.op_assign.op_assign.html +/library/std/numeric/CustomFloat.opBinary.html /library/std/numeric/custom_float.op_binary.html +/library/std/numeric/CustomFloat.opBinary.opBinary.html /library/std/numeric/custom_float.op_binary.op_binary.html +/library/std/numeric/CustomFloat.opBinaryRight.html /library/std/numeric/custom_float.op_binary_right.html +/library/std/numeric/CustomFloat.opBinaryRight.opBinaryRight.html /library/std/numeric/custom_float.op_binary_right.op_binary_right.html +/library/std/numeric/CustomFloat.opCast.html /library/std/numeric/custom_float.op_cast.html +/library/std/numeric/CustomFloat.opCast.opCast.html /library/std/numeric/custom_float.op_cast.op_cast.html +/library/std/numeric/CustomFloat.opCmp.html /library/std/numeric/custom_float.op_cmp.html +/library/std/numeric/CustomFloat.opCmp.opCmp.html /library/std/numeric/custom_float.op_cmp.op_cmp.html +/library/std/numeric/CustomFloat.opOpAssign.html /library/std/numeric/custom_float.op_op_assign.html +/library/std/numeric/CustomFloat.opOpAssign.opOpAssign.html /library/std/numeric/custom_float.op_op_assign.op_op_assign.html +/library/std/numeric/CustomFloat.opUnary.html /library/std/numeric/custom_float.op_unary.html +/library/std/numeric/CustomFloat.opUnary.opUnary.html /library/std/numeric/custom_float.op_unary.op_unary.html +/library/std/numeric/CustomFloat.re.html /library/std/numeric/custom_float.re.html +/library/std/numeric/CustomFloat.this.html /library/std/numeric/custom_float.this.html +/library/std/numeric/CustomFloat.this.this.html /library/std/numeric/custom_float.this.this.html +/library/std/numeric/CustomFloat.toString.html /library/std/numeric/custom_float.to_string.html +/library/std/numeric/CustomFloat.toString.toString.html /library/std/numeric/custom_float.to_string.to_string.html +/library/std/numeric/CustomFloat.toString.toString.toString.html /library/std/numeric/custom_float.to_string.to_string.to_string.html +/library/std/numeric/dotProduct.html /library/std/numeric/dot_product.html +/library/std/numeric/euclideanDistance.html /library/std/numeric/euclidean_distance.html +/library/std/numeric/Fft.fft.html /library/std/numeric/fft.fft.html +/library/std/numeric/Fft.html /library/std/numeric/fft.html +/library/std/numeric/Fft.inverseFft.html /library/std/numeric/fft.inverse_fft.html +/library/std/numeric/Fft.this.html /library/std/numeric/fft.this.html +/library/std/numeric/findRoot.html /library/std/numeric/find_root.html +/library/std/numeric/FPTemporary.html /library/std/numeric/fp_temporary.html +/library/std/numeric/gapWeightedSimilarity.html /library/std/numeric/gap_weighted_similarity.html +/library/std/numeric/GapWeightedSimilarityIncremental.empty.html /library/std/numeric/gap_weighted_similarity_incremental.empty.html +/library/std/numeric/GapWeightedSimilarityIncremental.front.html /library/std/numeric/gap_weighted_similarity_incremental.front.html +/library/std/numeric/gapWeightedSimilarityIncremental.html /library/std/numeric/gap_weighted_similarity_incremental.html +/library/std/numeric/GapWeightedSimilarityIncremental.html /library/std/numeric/gap_weighted_similarity_incremental.html +/library/std/numeric/GapWeightedSimilarityIncremental.opSlice.html /library/std/numeric/gap_weighted_similarity_incremental.op_slice.html +/library/std/numeric/GapWeightedSimilarityIncremental.popFront.html /library/std/numeric/gap_weighted_similarity_incremental.pop_front.html +/library/std/numeric/GapWeightedSimilarityIncremental.this.html /library/std/numeric/gap_weighted_similarity_incremental.this.html +/library/std/numeric/gapWeightedSimilarityNormalized.html /library/std/numeric/gap_weighted_similarity_normalized.html +/library/std/numeric/inverseFft.html /library/std/numeric/inverse_fft.html +/library/std/numeric/jensenShannonDivergence.html /library/std/numeric/jensen_shannon_divergence.html +/library/std/numeric/kullbackLeiblerDivergence.html /library/std/numeric/kullback_leibler_divergence.html +/library/std/numeric/Object.factory.html /library/std/numeric/object.factory.html +/library/std/numeric/Object.opCmp.html /library/std/numeric/object.op_cmp.html +/library/std/numeric/Object.opEquals.html /library/std/numeric/object.op_equals.html +/library/std/numeric/Object.toHash.html /library/std/numeric/object.to_hash.html +/library/std/numeric/Object.toString.html /library/std/numeric/object.to_string.html +/library/std/numeric/secantMethod.html /library/std/numeric/secant_method.html +/library/std/numeric/secantMethod.secantMethod.html /library/std/numeric/secant_method.secant_method.html +/library/std/numeric/sumOfLog2s.html /library/std/numeric/sum_of_log2s.html +/library/std/outbuffer/Object.factory.html /library/std/outbuffer/object.factory.html +/library/std/outbuffer/Object.opCmp.html /library/std/outbuffer/object.op_cmp.html +/library/std/outbuffer/Object.opEquals.html /library/std/outbuffer/object.op_equals.html +/library/std/outbuffer/Object.toHash.html /library/std/outbuffer/object.to_hash.html +/library/std/outbuffer/Object.toString.html /library/std/outbuffer/object.to_string.html +/library/std/outbuffer/OutBuffer.align2.html /library/std/outbuffer/out_buffer.align2.html +/library/std/outbuffer/OutBuffer.align4.html /library/std/outbuffer/out_buffer.align4.html +/library/std/outbuffer/OutBuffer.alignSize.html /library/std/outbuffer/out_buffer.align_size.html +/library/std/outbuffer/OutBuffer.fill0.html /library/std/outbuffer/out_buffer.fill0.html +/library/std/outbuffer/OutBuffer.html /library/std/outbuffer/out_buffer.html +/library/std/outbuffer/OutBuffer.printf.html /library/std/outbuffer/out_buffer.printf.html +/library/std/outbuffer/OutBuffer.put.html /library/std/outbuffer/out_buffer.put.html +/library/std/outbuffer/OutBuffer.reserve.html /library/std/outbuffer/out_buffer.reserve.html +/library/std/outbuffer/OutBuffer.spread.html /library/std/outbuffer/out_buffer.spread.html +/library/std/outbuffer/OutBuffer.toBytes.html /library/std/outbuffer/out_buffer.to_bytes.html +/library/std/outbuffer/OutBuffer.toString.html /library/std/outbuffer/out_buffer.to_string.html +/library/std/outbuffer/OutBuffer.vprintf.html /library/std/outbuffer/out_buffer.vprintf.html +/library/std/outbuffer/OutBuffer.writef.html /library/std/outbuffer/out_buffer.writef.html +/library/std/outbuffer/OutBuffer.writefln.html /library/std/outbuffer/out_buffer.writefln.html +/library/std/outbuffer/OutBuffer.write.html /library/std/outbuffer/out_buffer.write.html +/library/std/parallelism/defaultPoolThreads.html /library/std/parallelism/default_pool_threads.html +/library/std/parallelism/Object.factory.html /library/std/parallelism/object.factory.html +/library/std/parallelism/Object.opCmp.html /library/std/parallelism/object.op_cmp.html +/library/std/parallelism/Object.opEquals.html /library/std/parallelism/object.op_equals.html +/library/std/parallelism/Object.toHash.html /library/std/parallelism/object.to_hash.html +/library/std/parallelism/Object.toString.html /library/std/parallelism/object.to_string.html +/library/std/parallelism/scopedTask.html /library/std/parallelism/scoped_task.html +/library/std/parallelism/Task.done.html /library/std/parallelism/task.done.html +/library/std/parallelism/Task.executeInNewThread.html /library/std/parallelism/task.execute_in_new_thread.html +/library/std/parallelism/Task.html /library/std/parallelism/task.html +/library/std/parallelism/TaskPool.asyncBuf.html /library/std/parallelism/task_pool.async_buf.html +/library/std/parallelism/TaskPool.finish.html /library/std/parallelism/task_pool.finish.html +/library/std/parallelism/taskPool.html /library/std/parallelism/task_pool.html +/library/std/parallelism/TaskPool.html /library/std/parallelism/task_pool.html +/library/std/parallelism/TaskPool.isDaemon.html /library/std/parallelism/task_pool.is_daemon.html +/library/std/parallelism/TaskPool.parallel.html /library/std/parallelism/task_pool.parallel.html +/library/std/parallelism/TaskPool.priority.html /library/std/parallelism/task_pool.priority.html +/library/std/parallelism/TaskPool.put.html /library/std/parallelism/task_pool.put.html +/library/std/parallelism/TaskPool.size.html /library/std/parallelism/task_pool.size.html +/library/std/parallelism/TaskPool.stop.html /library/std/parallelism/task_pool.stop.html +/library/std/parallelism/TaskPool.this.html /library/std/parallelism/task_pool.this.html +/library/std/parallelism/TaskPool.workerIndex.html /library/std/parallelism/task_pool.worker_index.html +/library/std/parallelism/TaskPool.WorkerLocalStorage.get.html /library/std/parallelism/task_pool.worker_local_storage.get.html +/library/std/parallelism/TaskPool.workerLocalStorage.html /library/std/parallelism/task_pool.worker_local_storage.html +/library/std/parallelism/TaskPool.WorkerLocalStorage.html /library/std/parallelism/task_pool.worker_local_storage.html +/library/std/parallelism/TaskPool.WorkerLocalStorageRange.html /library/std/parallelism/task_pool.worker_local_storage_range.html +/library/std/parallelism/TaskPool.WorkerLocalStorage.toRange.html /library/std/parallelism/task_pool.worker_local_storage.to_range.html +/library/std/parallelism/Task.ReturnType.html /library/std/parallelism/task.return_type.html +/library/std/parallelism/Task.spinForce.html /library/std/parallelism/task.spin_force.html +/library/std/parallelism/Task.workForce.html /library/std/parallelism/task.work_force.html +/library/std/parallelism/Task.yieldForce.html /library/std/parallelism/task.yield_force.html +/library/std/parallelism/totalCPUs.html /library/std/parallelism/total_cp_us.html +/library/std/path/absolutePath.html /library/std/path/absolute_path.html +/library/std/path/baseName.html /library/std/path/base_name.html +/library/std/path/buildNormalizedPath.html /library/std/path/build_normalized_path.html +/library/std/path/buildPath.html /library/std/path/build_path.html +/library/std/path/CaseSensitive.html /library/std/path/case_sensitive.html +/library/std/path/CaseSensitive.no.html /library/std/path/case_sensitive.no.html +/library/std/path/CaseSensitive.osDefault.html /library/std/path/case_sensitive.os_default.html +/library/std/path/CaseSensitive.yes.html /library/std/path/case_sensitive.yes.html +/library/std/path/defaultExtension.html /library/std/path/default_extension.html +/library/std/path/dirName.html /library/std/path/dir_name.html +/library/std/path/dirSeparator.html /library/std/path/dir_separator.html +/library/std/path/driveName.html /library/std/path/drive_name.html +/library/std/path/expandTilde.html /library/std/path/expand_tilde.html +/library/std/path/filenameCharCmp.html /library/std/path/filename_char_cmp.html +/library/std/path/filenameCmp.html /library/std/path/filename_cmp.html +/library/std/path/globMatch.html /library/std/path/glob_match.html +/library/std/path/isAbsolute.html /library/std/path/is_absolute.html +/library/std/path/isDirSeparator.html /library/std/path/is_dir_separator.html +/library/std/path/isRooted.html /library/std/path/is_rooted.html +/library/std/path/isValidFilename.html /library/std/path/is_valid_filename.html +/library/std/path/isValidPath.html /library/std/path/is_valid_path.html +/library/std/path/pathSeparator.html /library/std/path/path_separator.html +/library/std/path/pathSplitter.html /library/std/path/path_splitter.html +/library/std/path/relativePath.html /library/std/path/relative_path.html +/library/std/path/rootName.html /library/std/path/root_name.html +/library/std/path/setExtension.html /library/std/path/set_extension.html +/library/std/path/stripDrive.html /library/std/path/strip_drive.html +/library/std/path/stripExtension.html /library/std/path/strip_extension.html +/library/std/process/Config.html /library/std/process/config.html +/library/std/process/Config.inheritFDs.html /library/std/process/config.inherit_f_ds.html +/library/std/process/Config.newEnv.html /library/std/process/config.new_env.html +/library/std/process/Config.retainStderr.html /library/std/process/config.retain_stderr.html +/library/std/process/Config.retainStdin.html /library/std/process/config.retain_stdin.html +/library/std/process/Config.retainStdout.html /library/std/process/config.retain_stdout.html +/library/std/process/Config.suppressConsole.html /library/std/process/config.suppress_console.html +/library/std/process/environment.opIndexAssign.html /library/std/process/environment.op_index_assign.html +/library/std/process/environment.opIndex.html /library/std/process/environment.op_index.html +/library/std/process/environment.toAA.html /library/std/process/environment.to_aa.html +/library/std/process/escapeShellCommand.html /library/std/process/escape_shell_command.html +/library/std/process/escapeShellFileName.html /library/std/process/escape_shell_file_name.html +/library/std/process/escapeWindowsArgument.html /library/std/process/escape_windows_argument.html +/library/std/process/executeShell.html /library/std/process/execute_shell.html +/library/std/process/Object.factory.html /library/std/process/object.factory.html +/library/std/process/Object.opCmp.html /library/std/process/object.op_cmp.html +/library/std/process/Object.opEquals.html /library/std/process/object.op_equals.html +/library/std/process/Object.toHash.html /library/std/process/object.to_hash.html +/library/std/process/Object.toString.html /library/std/process/object.to_string.html +/library/std/process/Pid.html /library/std/process/pid.html +/library/std/process/Pid.osHandle.html /library/std/process/pid.os_handle.html +/library/std/process/Pid.processID.html /library/std/process/pid.process_id.html +/library/std/process/Pipe.close.html /library/std/process/pipe.close.html +/library/std/process/Pipe.html /library/std/process/pipe.html +/library/std/process/pipeProcess.html /library/std/process/pipe_process.html +/library/std/process/Pipe.readEnd.html /library/std/process/pipe.read_end.html +/library/std/process/pipeShell.html /library/std/process/pipe_shell.html +/library/std/process/Pipe.writeEnd.html /library/std/process/pipe.write_end.html +/library/std/process/ProcessException.html /library/std/process/process_exception.html +/library/std/process/ProcessPipes.html /library/std/process/process_pipes.html +/library/std/process/ProcessPipes.pid.html /library/std/process/process_pipes.pid.html +/library/std/process/ProcessPipes.stderr.html /library/std/process/process_pipes.stderr.html +/library/std/process/ProcessPipes.stdin.html /library/std/process/process_pipes.stdin.html +/library/std/process/ProcessPipes.stdout.html /library/std/process/process_pipes.stdout.html +/library/std/process/Redirect.all.html /library/std/process/redirect.all.html +/library/std/process/Redirect.html /library/std/process/redirect.html +/library/std/process/Redirect.stderr.html /library/std/process/redirect.stderr.html +/library/std/process/Redirect.stderrToStdout.html /library/std/process/redirect.stderr_to_stdout.html +/library/std/process/Redirect.stdin.html /library/std/process/redirect.stdin.html +/library/std/process/Redirect.stdout.html /library/std/process/redirect.stdout.html +/library/std/process/Redirect.stdoutToStderr.html /library/std/process/redirect.stdout_to_stderr.html +/library/std/process/spawnProcess.html /library/std/process/spawn_process.html +/library/std/process/spawnShell.html /library/std/process/spawn_shell.html +/library/std/process/thisProcessID.html /library/std/process/this_process_id.html +/library/std/process/Throwable.file.html /library/std/process/throwable.file.html +/library/std/process/Throwable.info.html /library/std/process/throwable.info.html +/library/std/process/Throwable.line.html /library/std/process/throwable.line.html +/library/std/process/Throwable.msg.html /library/std/process/throwable.msg.html +/library/std/process/Throwable.next.html /library/std/process/throwable.next.html +/library/std/process/Throwable.toString.html /library/std/process/throwable.to_string.html +/library/std/process/tryWait.html /library/std/process/try_wait.html +/library/std/process/userShell.html /library/std/process/user_shell.html +/library/std/random/isSeedable.html /library/std/random/is_seedable.html +/library/std/random/isUniformRNG.html /library/std/random/is_uniform_rng.html +/library/std/random/LinearCongruentialEngine.empty.html /library/std/random/linear_congruential_engine.empty.html +/library/std/random/LinearCongruentialEngine.front.html /library/std/random/linear_congruential_engine.front.html +/library/std/random/LinearCongruentialEngine.hasFixedRange.html /library/std/random/linear_congruential_engine.has_fixed_range.html +/library/std/random/LinearCongruentialEngine.html /library/std/random/linear_congruential_engine.html +/library/std/random/LinearCongruentialEngine.increment.html /library/std/random/linear_congruential_engine.increment.html +/library/std/random/LinearCongruentialEngine.isUniformRandom.html /library/std/random/linear_congruential_engine.is_uniform_random.html +/library/std/random/LinearCongruentialEngine.max.html /library/std/random/linear_congruential_engine.max.html +/library/std/random/LinearCongruentialEngine.min.html /library/std/random/linear_congruential_engine.min.html +/library/std/random/LinearCongruentialEngine.modulus.html /library/std/random/linear_congruential_engine.modulus.html +/library/std/random/LinearCongruentialEngine.multiplier.html /library/std/random/linear_congruential_engine.multiplier.html +/library/std/random/LinearCongruentialEngine.opEquals.html /library/std/random/linear_congruential_engine.op_equals.html +/library/std/random/LinearCongruentialEngine.popFront.html /library/std/random/linear_congruential_engine.pop_front.html +/library/std/random/LinearCongruentialEngine.seed.html /library/std/random/linear_congruential_engine.seed.html +/library/std/random/LinearCongruentialEngine.this.html /library/std/random/linear_congruential_engine.this.html +/library/std/random/MersenneTwisterEngine.defaultSeed.html /library/std/random/mersenne_twister_engine.default_seed.html +/library/std/random/MersenneTwisterEngine.empty.html /library/std/random/mersenne_twister_engine.empty.html +/library/std/random/MersenneTwisterEngine.front.html /library/std/random/mersenne_twister_engine.front.html +/library/std/random/MersenneTwisterEngine.html /library/std/random/mersenne_twister_engine.html +/library/std/random/MersenneTwisterEngine.isUniformRandom.html /library/std/random/mersenne_twister_engine.is_uniform_random.html +/library/std/random/MersenneTwisterEngine.maskBits.html /library/std/random/mersenne_twister_engine.mask_bits.html +/library/std/random/MersenneTwisterEngine.max.html /library/std/random/mersenne_twister_engine.max.html +/library/std/random/MersenneTwisterEngine.min.html /library/std/random/mersenne_twister_engine.min.html +/library/std/random/MersenneTwisterEngine.popFront.html /library/std/random/mersenne_twister_engine.pop_front.html +/library/std/random/MersenneTwisterEngine.seed.html /library/std/random/mersenne_twister_engine.seed.html +/library/std/random/MersenneTwisterEngine.seed.seed.html /library/std/random/mersenne_twister_engine.seed.seed.html +/library/std/random/MersenneTwisterEngine.shiftSize.html /library/std/random/mersenne_twister_engine.shift_size.html +/library/std/random/MersenneTwisterEngine.stateSize.html /library/std/random/mersenne_twister_engine.state_size.html +/library/std/random/MersenneTwisterEngine.temperingB.html /library/std/random/mersenne_twister_engine.tempering.html +/library/std/random/MersenneTwisterEngine.temperingC.html /library/std/random/mersenne_twister_engine.tempering.html +/library/std/random/MersenneTwisterEngine.temperingL.html /library/std/random/mersenne_twister_engine.tempering.html +/library/std/random/MersenneTwisterEngine.temperingS.html /library/std/random/mersenne_twister_engine.tempering.html +/library/std/random/MersenneTwisterEngine.temperingT.html /library/std/random/mersenne_twister_engine.tempering.html +/library/std/random/MersenneTwisterEngine.temperingU.html /library/std/random/mersenne_twister_engine.tempering.html +/library/std/random/MersenneTwisterEngine.this.html /library/std/random/mersenne_twister_engine.this.html +/library/std/random/MersenneTwisterEngine.wordSize.html /library/std/random/mersenne_twister_engine.word_size.html +/library/std/random/MersenneTwisterEngine.xorMask.html /library/std/random/mersenne_twister_engine.xor_mask.html +/library/std/random/MinstdRand0.html /library/std/random/minstd_rand0.html +/library/std/random/MinstdRand.html /library/std/random/minstd_rand.html +/library/std/random/Mt19937.html /library/std/random/mt19937.html +/library/std/random/partialShuffle.html /library/std/random/partial_shuffle.html +/library/std/random/randomCover.html /library/std/random/random_cover.html +/library/std/random/RandomCover.html /library/std/random/random_cover.html +/library/std/random/Random.html /library/std/random/random.html +/library/std/random/RandomSample.empty.html /library/std/random/random_sample.empty.html +/library/std/random/randomSample.html /library/std/random/random_sample.html +/library/std/random/RandomSample.html /library/std/random/random_sample.html +/library/std/random/RandomSample.index.html /library/std/random/random_sample.index.html +/library/std/random/RandomSample.length.html /library/std/random/random_sample.length.html +/library/std/random/RandomSample.popFront.html /library/std/random/random_sample.pop_front.html +/library/std/random/randomShuffle.html /library/std/random/random_shuffle.html +/library/std/random/rndGen.html /library/std/random/rnd_gen.html +/library/std/random/uniformDistribution.html /library/std/random/uniform_distribution.html +/library/std/random/unpredictableSeed.html /library/std/random/unpredictable_seed.html +/library/std/random/Xorshift128.html /library/std/random/xorshift128.html +/library/std/random/Xorshift160.html /library/std/random/xorshift160.html +/library/std/random/Xorshift192.html /library/std/random/xorshift192.html +/library/std/random/Xorshift32.html /library/std/random/xorshift32.html +/library/std/random/Xorshift64.html /library/std/random/xorshift64.html +/library/std/random/Xorshift96.html /library/std/random/xorshift96.html +/library/std/random/XorshiftEngine.empty.html /library/std/random/xorshift_engine.empty.html +/library/std/random/XorshiftEngine.front.html /library/std/random/xorshift_engine.front.html +/library/std/random/XorshiftEngine.html /library/std/random/xorshift_engine.html +/library/std/random/XorshiftEngine.isUniformRandom.html /library/std/random/xorshift_engine.is_uniform_random.html +/library/std/random/XorshiftEngine.max.html /library/std/random/xorshift_engine.max.html +/library/std/random/XorshiftEngine.min.html /library/std/random/xorshift_engine.min.html +/library/std/random/XorshiftEngine.opEquals.html /library/std/random/xorshift_engine.op_equals.html +/library/std/random/XorshiftEngine.popFront.html /library/std/random/xorshift_engine.pop_front.html +/library/std/random/XorshiftEngine.save.html /library/std/random/xorshift_engine.save.html +/library/std/random/XorshiftEngine.seed.html /library/std/random/xorshift_engine.seed.html +/library/std/random/XorshiftEngine.this.html /library/std/random/xorshift_engine.this.html +/library/std/random/Xorshift.html /library/std/random/xorshift.html +/library/std/range/assumeSorted.html /library/std/range/assume_sorted.html +/library/std/range/Chunks.front.html /library/std/range/chunks.front.html +/library/std/range/Chunks.html /library/std/range/chunks.html +/library/std/range/Chunks.popFront.html /library/std/range/chunks.pop_front.html +/library/std/range/Chunks.save.html /library/std/range/chunks.save.html +/library/std/range/Chunks.this.html /library/std/range/chunks.this.html +/library/std/range/Cycle.html /library/std/range/cycle.html +/library/std/range/dropBackExactly.html /library/std/range/drop_back_exactly.html +/library/std/range/dropBack.html /library/std/range/drop_back.html +/library/std/range/dropBackOne.html /library/std/range/drop_back_one.html +/library/std/range/dropExactly.html /library/std/range/drop_exactly.html +/library/std/range/dropOne.html /library/std/range/drop_one.html +/library/std/range/FrontTransversal.front.html /library/std/range/front_transversal.front.html +/library/std/range/frontTransversal.html /library/std/range/front_transversal.html +/library/std/range/FrontTransversal.html /library/std/range/front_transversal.html +/library/std/range/FrontTransversal.popFront.html /library/std/range/front_transversal.pop_front.html +/library/std/range/FrontTransversal.this.html /library/std/range/front_transversal.this.html +/library/std/range/Indexed.front.html /library/std/range/indexed.front.html +/library/std/range/Indexed.html /library/std/range/indexed.html +/library/std/range/Indexed.indices.html /library/std/range/indexed.indices.html +/library/std/range/Indexed.popFront.html /library/std/range/indexed.pop_front.html +/library/std/range/Indexed.source.html /library/std/range/indexed.source.html +/library/std/range/interfaces/BidirectionalAssignable.html /library/std/range/interfaces/bidirectional_assignable.html +/library/std/range/interfaces/BidirectionalRange.html /library/std/range/interfaces/bidirectional_range.html +/library/std/range/interfaces/ForwardAssignable.html /library/std/range/interfaces/forward_assignable.html +/library/std/range/interfaces/ForwardRange.html /library/std/range/interfaces/forward_range.html +/library/std/range/interfaces/InputAssignable.html /library/std/range/interfaces/input_assignable.html +/library/std/range/interfaces/InputRange.html /library/std/range/interfaces/input_range.html +/library/std/range/interfaces/inputRangeObject.html /library/std/range/interfaces/input_range_object.html +/library/std/range/interfaces/InputRangeObject.html /library/std/range/interfaces/input_range_object.html +/library/std/range/interfaces/InputRange.opApply.html /library/std/range/interfaces/input_range.op_apply.html +/library/std/range/interfaces/MostDerivedInputRange.html /library/std/range/interfaces/most_derived_input_range.html +/library/std/range/interfaces/Object.factory.html /library/std/range/interfaces/object.factory.html +/library/std/range/interfaces/Object.opCmp.html /library/std/range/interfaces/object.op_cmp.html +/library/std/range/interfaces/Object.opEquals.html /library/std/range/interfaces/object.op_equals.html +/library/std/range/interfaces/Object.toHash.html /library/std/range/interfaces/object.to_hash.html +/library/std/range/interfaces/Object.toString.html /library/std/range/interfaces/object.to_string.html +/library/std/range/interfaces/OutputRange.html /library/std/range/interfaces/output_range.html +/library/std/range/interfaces/outputRangeObject.html /library/std/range/interfaces/output_range_object.html +/library/std/range/interfaces/OutputRangeObject.html /library/std/range/interfaces/output_range_object.html +/library/std/range/interfaces/outputRangeObject.outputRangeObject.html /library/std/range/interfaces/output_range_object.output_range_object.html +/library/std/range/interfaces/RandomAccessFinite.html /library/std/range/interfaces/random_access_finite.html +/library/std/range/interfaces/RandomAccessInfinite.html /library/std/range/interfaces/random_access_infinite.html +/library/std/range/interfaces/RandomFiniteAssignable.html /library/std/range/interfaces/random_finite_assignable.html +/library/std/range/isTwoWayCompatible.html /library/std/range/is_two_way_compatible.html +/library/std/range/Lockstep.html /library/std/range/lockstep.html +/library/std/range/NullSink.html /library/std/range/null_sink.html +/library/std/range/primitives/ElementEncodingType.html /library/std/range/primitives/element_encoding_type.html +/library/std/range/primitives/ElementType.html /library/std/range/primitives/element_type.html +/library/std/range/primitives/hasAssignableElements.html /library/std/range/primitives/has_assignable_elements.html +/library/std/range/primitives/hasLength.html /library/std/range/primitives/has_length.html +/library/std/range/primitives/hasLvalueElements.html /library/std/range/primitives/has_lvalue_elements.html +/library/std/range/primitives/hasMobileElements.html /library/std/range/primitives/has_mobile_elements.html +/library/std/range/primitives/hasSlicing.html /library/std/range/primitives/has_slicing.html +/library/std/range/primitives/hasSwappableElements.html /library/std/range/primitives/has_swappable_elements.html +/library/std/range/primitives/isBidirectionalRange.html /library/std/range/primitives/is_bidirectional_range.html +/library/std/range/primitives/isForwardRange.html /library/std/range/primitives/is_forward_range.html +/library/std/range/primitives/isInfinite.html /library/std/range/primitives/is_infinite.html +/library/std/range/primitives/isInputRange.html /library/std/range/primitives/is_input_range.html +/library/std/range/primitives/isOutputRange.html /library/std/range/primitives/is_output_range.html +/library/std/range/primitives/isRandomAccessRange.html /library/std/range/primitives/is_random_access_range.html +/library/std/range/primitives/moveAt.html /library/std/range/primitives/move_at.html +/library/std/range/primitives/moveBack.html /library/std/range/primitives/move_back.html +/library/std/range/primitives/moveFront.html /library/std/range/primitives/move_front.html +/library/std/range/primitives/popBackExactly.html /library/std/range/primitives/pop_back_exactly.html +/library/std/range/primitives/popBack.html /library/std/range/primitives/pop_back.html +/library/std/range/primitives/popBackN.html /library/std/range/primitives/pop_back.html +/library/std/range/primitives/popFrontExactly.html /library/std/range/primitives/pop_front_exactly.html +/library/std/range/primitives/popFront.html /library/std/range/primitives/pop_front.html +/library/std/range/primitives/popFrontN.html /library/std/range/primitives/pop_front.html +/library/std/range/primitives/walkLength.html /library/std/range/primitives/walk_length.html +/library/std/range/Recurrence.html /library/std/range/recurrence.html +/library/std/range/refRange.html /library/std/range/ref_range.html +/library/std/range/RefRange.html /library/std/range/ref_range.html +/library/std/range/RefRange.opAssign.html /library/std/range/ref_range.op_assign.html +/library/std/range/RefRange.ptr.html /library/std/range/ref_range.ptr.html +/library/std/range/Repeat.html /library/std/range/repeat.html +/library/std/range/roundRobin.html /library/std/range/round_robin.html +/library/std/range/SearchPolicy.binarySearch.html /library/std/range/search_policy.binary_search.html +/library/std/range/SearchPolicy.gallopBackwards.html /library/std/range/search_policy.gallop_backwards.html +/library/std/range/SearchPolicy.gallop.html /library/std/range/search_policy.gallop.html +/library/std/range/SearchPolicy.html /library/std/range/search_policy.html +/library/std/range/SearchPolicy.linear.html /library/std/range/search_policy.linear.html +/library/std/range/SearchPolicy.trotBackwards.html /library/std/range/search_policy.trot_backwards.html +/library/std/range/SearchPolicy.trot.html /library/std/range/search_policy.trot.html +/library/std/range/Sequence.html /library/std/range/sequence.html +/library/std/range/SortedRange.contains.contains.html /library/std/range/sorted_range.contains.contains.html +/library/std/range/SortedRange.contains.html /library/std/range/sorted_range.contains.html +/library/std/range/SortedRange.empty.html /library/std/range/sorted_range.empty.html +/library/std/range/SortedRange.equalRange.equalRange.html /library/std/range/sorted_range.equal_range.equal_range.html +/library/std/range/SortedRange.equalRange.html /library/std/range/sorted_range.equal_range.html +/library/std/range/SortedRange.front.html /library/std/range/sorted_range.front.html +/library/std/range/SortedRange.html /library/std/range/sorted_range.html +/library/std/range/SortedRange.lowerBound.html /library/std/range/sorted_range.lower_bound.html +/library/std/range/SortedRange.lowerBound.lowerBound.html /library/std/range/sorted_range.lower_bound.lower_bound.html +/library/std/range/SortedRange.popFront.html /library/std/range/sorted_range.pop_front.html +/library/std/range/SortedRange.release.html /library/std/range/sorted_range.release.html +/library/std/range/SortedRange.trisect.html /library/std/range/sorted_range.trisect.html +/library/std/range/SortedRange.trisect.trisect.html /library/std/range/sorted_range.trisect.trisect.html +/library/std/range/SortedRange.upperBound.html /library/std/range/sorted_range.upper_bound.html +/library/std/range/SortedRange.upperBound.upperBound.html /library/std/range/sorted_range.upper_bound.upper_bound.html +/library/std/range/StoppingPolicy.html /library/std/range/stopping_policy.html +/library/std/range/StoppingPolicy.longest.html /library/std/range/stopping_policy.longest.html +/library/std/range/StoppingPolicy.requireSameLength.html /library/std/range/stopping_policy.require_same_length.html +/library/std/range/StoppingPolicy.shortest.html /library/std/range/stopping_policy.shortest.html +/library/std/range/takeExactly.html /library/std/range/take_exactly.html +/library/std/range/Take.html /library/std/range/take.html +/library/std/range/takeNone.html /library/std/range/take_none.html +/library/std/range/takeOne.html /library/std/range/take_one.html +/library/std/range/Transversal.front.html /library/std/range/transversal.front.html +/library/std/range/Transversal.html /library/std/range/transversal.html +/library/std/range/Transversal.popFront.html /library/std/range/transversal.pop_front.html +/library/std/range/Transversal.this.html /library/std/range/transversal.this.html +/library/std/range/TransverseOptions.assumeJagged.html /library/std/range/transverse_options.assume_jagged.html +/library/std/range/TransverseOptions.assumeNotJagged.html /library/std/range/transverse_options.assume_not_jagged.html +/library/std/range/TransverseOptions.enforceNotJagged.html /library/std/range/transverse_options.enforce_not_jagged.html +/library/std/range/TransverseOptions.html /library/std/range/transverse_options.html +/library/std/range/Zip.front.html /library/std/range/zip.front.html +/library/std/range/Zip.html /library/std/range/zip.html +/library/std/range/Zip.popFront.html /library/std/range/zip.pop_front.html +/library/std/range/Zip.this.html /library/std/range/zip.this.html +/library/std/regex/Captures.back.html /library/std/regex/captures.back.html +/library/std/regex/Captures.captures.html /library/std/regex/captures.captures.html +/library/std/regex/Captures.empty.html /library/std/regex/captures.empty.html +/library/std/regex/Captures.front.html /library/std/regex/captures.front.html +/library/std/regex/Captures.hit.html /library/std/regex/captures.hit.html +/library/std/regex/Captures.html /library/std/regex/captures.html +/library/std/regex/Captures.length.html /library/std/regex/captures.length.html +/library/std/regex/Captures.opCast.html /library/std/regex/captures.op_cast.html +/library/std/regex/Captures.opCast.opCast.html /library/std/regex/captures.op_cast.op_cast.html +/library/std/regex/Captures.opIndex.html /library/std/regex/captures.op_index.html +/library/std/regex/Captures.opIndex.opIndex.html /library/std/regex/captures.op_index.op_index.html +/library/std/regex/Captures.popBack.html /library/std/regex/captures.pop_back.html +/library/std/regex/Captures.popFront.html /library/std/regex/captures.pop_front.html +/library/std/regex/Captures.post.html /library/std/regex/captures.post.html +/library/std/regex/Captures.pre.html /library/std/regex/captures.pre.html +/library/std/regex/ctRegex.html /library/std/regex/ct_regex.html +/library/std/regex/matchAll.html /library/std/regex/match_all.html +/library/std/regex/matchFirst.html /library/std/regex/match_first.html +/library/std/regex/RegexException.html /library/std/regex/regex_exception.html +/library/std/regex/Regex.html /library/std/regex/regex.html +/library/std/regex/RegexMatch.captures.html /library/std/regex/regex_match.captures.html +/library/std/regex/RegexMatch.empty.html /library/std/regex/regex_match.empty.html +/library/std/regex/RegexMatch.front.html /library/std/regex/regex_match.front.html +/library/std/regex/RegexMatch.hit.html /library/std/regex/regex_match.hit.html +/library/std/regex/RegexMatch.html /library/std/regex/regex_match.html +/library/std/regex/RegexMatch.opCast.html /library/std/regex/regex_match.op_cast.html +/library/std/regex/RegexMatch.opCast.opCast.html /library/std/regex/regex_match.op_cast.op_cast.html +/library/std/regex/RegexMatch.popFront.html /library/std/regex/regex_match.pop_front.html +/library/std/regex/RegexMatch.post.html /library/std/regex/regex_match.post.html +/library/std/regex/RegexMatch.pre.html /library/std/regex/regex_match.pre.html +/library/std/regex/RegexMatch.save.html /library/std/regex/regex_match.save.html +/library/std/regex/replaceAll.html /library/std/regex/replace_all.html +/library/std/regex/replaceAllInto.html /library/std/regex/replace_all_into.html +/library/std/regex/replaceFirst.html /library/std/regex/replace_first.html +/library/std/regex/replaceFirstInto.html /library/std/regex/replace_first_into.html +/library/std/regex/Splitter.empty.html /library/std/regex/splitter.empty.html +/library/std/regex/Splitter.front.html /library/std/regex/splitter.front.html +/library/std/regex/Splitter.html /library/std/regex/splitter.html +/library/std/regex/Splitter.popFront.html /library/std/regex/splitter.pop_front.html +/library/std/regex/Splitter.save.html /library/std/regex/splitter.save.html +/library/std/regex/StaticRegex.html /library/std/regex/static_regex.html +/library/std/signals/Signal.connect.html /library/std/signals/signal.connect.html +/library/std/signals/Signal.disconnect.html /library/std/signals/signal.disconnect.html +/library/std/signals/Signal.emit.html /library/std/signals/signal.emit.html +/library/std/signals/Signal.html /library/std/signals/signal.html +/library/std/signals/Signal.slot_t.html /library/std/signals/signal.slot_t.html +/library/std/socket/Address.addressFamily.html /library/std/socket/address.address_family.html +/library/std/socket/AddressException.html /library/std/socket/address_exception.html +/library/std/socket/AddressFamily.APPLETALK.html /library/std/socket/address_family.appletalk.html +/library/std/socket/AddressFamily.html /library/std/socket/address_family.html +/library/std/socket/AddressFamily.INET6.html /library/std/socket/address_family.ine_t6.html +/library/std/socket/AddressFamily.INET.html /library/std/socket/address_family.inet.html +/library/std/socket/AddressFamily.IPX.html /library/std/socket/address_family.ipx.html +/library/std/socket/AddressFamily.UNIX.html /library/std/socket/address_family.unix.html +/library/std/socket/AddressFamily.UNSPEC.html /library/std/socket/address_family.unspec.html +/library/std/socket/Address.html /library/std/socket/address.html +/library/std/socket/AddressInfo.address.html /library/std/socket/address_info.address.html +/library/std/socket/AddressInfo.canonicalName.html /library/std/socket/address_info.canonical_name.html +/library/std/socket/AddressInfo.family.html /library/std/socket/address_info.family.html +/library/std/socket/AddressInfoFlags.CANONNAME.html /library/std/socket/address_info_flags.canonname.html +/library/std/socket/AddressInfoFlags.html /library/std/socket/address_info_flags.html +/library/std/socket/AddressInfoFlags.NUMERICHOST.html /library/std/socket/address_info_flags.numerichost.html +/library/std/socket/AddressInfoFlags.PASSIVE.html /library/std/socket/address_info_flags.passive.html +/library/std/socket/AddressInfo.html /library/std/socket/address_info.html +/library/std/socket/AddressInfo.protocol.html /library/std/socket/address_info.protocol.html +/library/std/socket/AddressInfo.type.html /library/std/socket/address_info.type.html +/library/std/socket/Address.name.html /library/std/socket/address.name.html +/library/std/socket/Address.nameLen.html /library/std/socket/address.name_len.html +/library/std/socket/Address.toAddrString.html /library/std/socket/address.to_addr_string.html +/library/std/socket/Address.toHostNameString.html /library/std/socket/address.to_host_name_string.html +/library/std/socket/Address.toPortString.html /library/std/socket/address.to_port_string.html +/library/std/socket/Address.toServiceNameString.html /library/std/socket/address.to_service_name_string.html +/library/std/socket/Address.toString.html /library/std/socket/address.to_string.html +/library/std/socket/getAddress.html /library/std/socket/get_address.html +/library/std/socket/getAddressInfo.html /library/std/socket/get_address_info.html +/library/std/socket/HostException.html /library/std/socket/host_exception.html +/library/std/socket/Internet6Address.ADDR_ANY.html /library/std/socket/internet6_address.add_r_any.html +/library/std/socket/Internet6Address.addr.html /library/std/socket/internet6_address.addr.html +/library/std/socket/Internet6Address.html /library/std/socket/internet6_address.html +/library/std/socket/Internet6Address.parse.html /library/std/socket/internet6_address.parse.html +/library/std/socket/Internet6Address.PORT_ANY.html /library/std/socket/internet6_address.por_t_any.html +/library/std/socket/Internet6Address.port.html /library/std/socket/internet6_address.port.html +/library/std/socket/Internet6Address.this.html /library/std/socket/internet6_address.this.html +/library/std/socket/InternetAddress.ADDR_ANY.html /library/std/socket/internet_address.add_r_any.html +/library/std/socket/InternetAddress.addr.html /library/std/socket/internet_address.addr.html +/library/std/socket/InternetAddress.ADDR_NONE.html /library/std/socket/internet_address.add_r_none.html +/library/std/socket/InternetAddress.addrToString.html /library/std/socket/internet_address.addr_to_string.html +/library/std/socket/InternetAddress.html /library/std/socket/internet_address.html +/library/std/socket/InternetAddress.opEquals.html /library/std/socket/internet_address.op_equals.html +/library/std/socket/InternetAddress.parse.html /library/std/socket/internet_address.parse.html +/library/std/socket/InternetAddress.PORT_ANY.html /library/std/socket/internet_address.por_t_any.html +/library/std/socket/InternetAddress.port.html /library/std/socket/internet_address.port.html +/library/std/socket/InternetAddress.this.html /library/std/socket/internet_address.this.html +/library/std/socket/InternetAddress.toAddrString.html /library/std/socket/internet_address.to_addr_string.html +/library/std/socket/InternetAddress.toHostNameString.html /library/std/socket/internet_address.to_host_name_string.html +/library/std/socket/InternetAddress.toPortString.html /library/std/socket/internet_address.to_port_string.html +/library/std/socket/InternetHost.addrList.html /library/std/socket/internet_host.addr_list.html +/library/std/socket/InternetHost.aliases.html /library/std/socket/internet_host.aliases.html +/library/std/socket/InternetHost.getHostByAddr.html /library/std/socket/internet_host.get_host_by_addr.html +/library/std/socket/InternetHost.getHostByName.html /library/std/socket/internet_host.get_host_by_name.html +/library/std/socket/InternetHost.html /library/std/socket/internet_host.html +/library/std/socket/InternetHost.name.html /library/std/socket/internet_host.name.html +/library/std/socket/lastSocketError.html /library/std/socket/last_socket_error.html +/library/std/socket/Linger.html /library/std/socket/linger.html +/library/std/socket/Linger.on.html /library/std/socket/linger.on.html +/library/std/socket/Linger.time.html /library/std/socket/linger.time.html +/library/std/socket/Object.factory.html /library/std/socket/object.factory.html +/library/std/socket/Object.opCmp.html /library/std/socket/object.op_cmp.html +/library/std/socket/Object.opEquals.html /library/std/socket/object.op_equals.html +/library/std/socket/Object.toHash.html /library/std/socket/object.to_hash.html +/library/std/socket/Object.toString.html /library/std/socket/object.to_string.html +/library/std/socket/parseAddress.html /library/std/socket/parse_address.html +/library/std/socket/Protocol.aliases.html /library/std/socket/protocol.aliases.html +/library/std/socket/Protocol.getProtocolByName.html /library/std/socket/protocol.get_protocol_by_name.html +/library/std/socket/Protocol.getProtocolByType.html /library/std/socket/protocol.get_protocol_by_type.html +/library/std/socket/Protocol.html /library/std/socket/protocol.html +/library/std/socket/Protocol.name.html /library/std/socket/protocol.name.html +/library/std/socket/ProtocolType.GGP.html /library/std/socket/protocol_type.ggp.html +/library/std/socket/Protocol.type.html /library/std/socket/protocol.type.html +/library/std/socket/ProtocolType.html /library/std/socket/protocol_type.html +/library/std/socket/ProtocolType.ICMP.html /library/std/socket/protocol_type.icmp.html +/library/std/socket/ProtocolType.IDP.html /library/std/socket/protocol_type.idp.html +/library/std/socket/ProtocolType.IGMP.html /library/std/socket/protocol_type.igmp.html +/library/std/socket/ProtocolType.IP.html /library/std/socket/protocol_type.ip.html +/library/std/socket/ProtocolType.IPV6.html /library/std/socket/protocol_type.ip_v6.html +/library/std/socket/ProtocolType.PUP.html /library/std/socket/protocol_type.pup.html +/library/std/socket/ProtocolType.RAW.html /library/std/socket/protocol_type.raw.html +/library/std/socket/ProtocolType.TCP.html /library/std/socket/protocol_type.tcp.html +/library/std/socket/ProtocolType.UDP.html /library/std/socket/protocol_type.udp.html +/library/std/socket/Service.aliases.html /library/std/socket/service.aliases.html +/library/std/socket/Service.getServiceByName.html /library/std/socket/service.get_service_by_name.html +/library/std/socket/Service.getServiceByPort.html /library/std/socket/service.get_service_by_port.html +/library/std/socket/Service.html /library/std/socket/service.html +/library/std/socket/Service.name.html /library/std/socket/service.name.html +/library/std/socket/Service.port.html /library/std/socket/service.port.html +/library/std/socket/Service.protocolName.html /library/std/socket/service.protocol_name.html +/library/std/socket/SocketAcceptException.html /library/std/socket/socket_accept_exception.html +/library/std/socket/Socket.accept.html /library/std/socket/socket.accept.html +/library/std/socket/Socket.accepting.html /library/std/socket/socket.accepting.html +/library/std/socket/Socket.addressFamily.html /library/std/socket/socket.address_family.html +/library/std/socket/Socket.bind.html /library/std/socket/socket.bind.html +/library/std/socket/Socket.blocking.html /library/std/socket/socket.blocking.html +/library/std/socket/Socket.close.html /library/std/socket/socket.close.html +/library/std/socket/Socket.connect.html /library/std/socket/socket.connect.html +/library/std/socket/Socket.createAddress.html /library/std/socket/socket.create_address.html +/library/std/socket/Socket.ERROR.html /library/std/socket/socket.error.html +/library/std/socket/SocketException.html /library/std/socket/socket_exception.html +/library/std/socket/SocketFeatureException.html /library/std/socket/socket_feature_exception.html +/library/std/socket/SocketFlags.DONTROUTE.html /library/std/socket/socket_flags.dontroute.html +/library/std/socket/SocketFlags.html /library/std/socket/socket_flags.html +/library/std/socket/SocketFlags.NONE.html /library/std/socket/socket_flags.none.html +/library/std/socket/SocketFlags.OOB.html /library/std/socket/socket_flags.oob.html +/library/std/socket/SocketFlags.PEEK.html /library/std/socket/socket_flags.peek.html +/library/std/socket/Socket.getErrorText.html /library/std/socket/socket.get_error_text.html +/library/std/socket/Socket.getOption.html /library/std/socket/socket.get_option.html +/library/std/socket/Socket.handle.html /library/std/socket/socket.handle.html +/library/std/socket/Socket.hostName.html /library/std/socket/socket.host_name.html +/library/std/socket/Socket.html /library/std/socket/socket.html +/library/std/socket/Socket.isAlive.html /library/std/socket/socket.is_alive.html +/library/std/socket/Socket.listen.html /library/std/socket/socket.listen.html +/library/std/socket/Socket.localAddress.html /library/std/socket/socket.local_address.html +/library/std/socket/SocketOption.ACCEPTCONN.html /library/std/socket/socket_option.acceptconn.html +/library/std/socket/SocketOption.BROADCAST.html /library/std/socket/socket_option.broadcast.html +/library/std/socket/SocketOption.DEBUG.html /library/std/socket/socket_option.debug.html +/library/std/socket/SocketOption.DONTROUTE.html /library/std/socket/socket_option.dontroute.html +/library/std/socket/SocketOption.ERROR.html /library/std/socket/socket_option.error.html +/library/std/socket/SocketOption.html /library/std/socket/socket_option.html +/library/std/socket/SocketOption.IPV6_JOIN_GROUP.html /library/std/socket/socket_option.ip_v6__joi_n_group.html +/library/std/socket/SocketOption.IPV6_LEAVE_GROUP.html /library/std/socket/socket_option.ip_v6__leav_e_group.html +/library/std/socket/SocketOption.IPV6_MULTICAST_HOPS.html /library/std/socket/socket_option.ip_v6__multicas_t_hops.html +/library/std/socket/SocketOption.IPV6_MULTICAST_IF.html /library/std/socket/socket_option.ip_v6__multicas_t_if.html +/library/std/socket/SocketOption.IPV6_MULTICAST_LOOP.html /library/std/socket/socket_option.ip_v6__multicas_t_loop.html +/library/std/socket/SocketOption.IPV6_UNICAST_HOPS.html /library/std/socket/socket_option.ip_v6__unicas_t_hops.html +/library/std/socket/SocketOption.IPV6_V6ONLY.html /library/std/socket/socket_option.ip_v6__v6only.html +/library/std/socket/SocketOption.KEEPALIVE.html /library/std/socket/socket_option.keepalive.html +/library/std/socket/SocketOptionLevel.GGP.html /library/std/socket/socket_option_level.ggp.html +/library/std/socket/SocketOptionLevel.html /library/std/socket/socket_option_level.html +/library/std/socket/SocketOptionLevel.ICMP.html /library/std/socket/socket_option_level.icmp.html +/library/std/socket/SocketOptionLevel.IDP.html /library/std/socket/socket_option_level.idp.html +/library/std/socket/SocketOptionLevel.IGMP.html /library/std/socket/socket_option_level.igmp.html +/library/std/socket/SocketOptionLevel.IP.html /library/std/socket/socket_option_level.ip.html +/library/std/socket/SocketOptionLevel.IPV6.html /library/std/socket/socket_option_level.ip_v6.html +/library/std/socket/SocketOptionLevel.PUP.html /library/std/socket/socket_option_level.pup.html +/library/std/socket/SocketOptionLevel.RAW.html /library/std/socket/socket_option_level.raw.html +/library/std/socket/SocketOptionLevel.SOCKET.html /library/std/socket/socket_option_level.socket.html +/library/std/socket/SocketOptionLevel.TCP.html /library/std/socket/socket_option_level.tcp.html +/library/std/socket/SocketOptionLevel.UDP.html /library/std/socket/socket_option_level.udp.html +/library/std/socket/SocketOption.LINGER.html /library/std/socket/socket_option.linger.html +/library/std/socket/SocketOption.OOBINLINE.html /library/std/socket/socket_option.oobinline.html +/library/std/socket/SocketOption.RCVBUF.html /library/std/socket/socket_option.rcvbuf.html +/library/std/socket/SocketOption.RCVLOWAT.html /library/std/socket/socket_option.rcvlowat.html +/library/std/socket/SocketOption.RCVTIMEO.html /library/std/socket/socket_option.rcvtimeo.html +/library/std/socket/SocketOption.REUSEADDR.html /library/std/socket/socket_option.reuseaddr.html +/library/std/socket/SocketOption.SNDBUF.html /library/std/socket/socket_option.sndbuf.html +/library/std/socket/SocketOption.SNDLOWAT.html /library/std/socket/socket_option.sndlowat.html +/library/std/socket/SocketOption.SNDTIMEO.html /library/std/socket/socket_option.sndtimeo.html +/library/std/socket/SocketOption.TCP_NODELAY.html /library/std/socket/socket_option.tc_p_nodelay.html +/library/std/socket/SocketOption.TYPE.html /library/std/socket/socket_option.type.html +/library/std/socket/SocketOSException.errorCode.html /library/std/socket/socket_os_exception.error_code.html +/library/std/socket/SocketOSException.html /library/std/socket/socket_os_exception.html +/library/std/socket/socketPair.html /library/std/socket/socket_pair.html +/library/std/socket/SocketParameterException.html /library/std/socket/socket_parameter_exception.html +/library/std/socket/Socket.receiveFrom.html /library/std/socket/socket.receive_from.html +/library/std/socket/Socket.receive.html /library/std/socket/socket.receive.html +/library/std/socket/Socket.remoteAddress.html /library/std/socket/socket.remote_address.html +/library/std/socket/Socket.select.html /library/std/socket/socket.select.html +/library/std/socket/Socket.send.html /library/std/socket/socket.send.html +/library/std/socket/Socket.sendTo.html /library/std/socket/socket.send_to.html +/library/std/socket/SocketSet.add.html /library/std/socket/socket_set.add.html +/library/std/socket/SocketSet.html /library/std/socket/socket_set.html +/library/std/socket/SocketSet.isSet.html /library/std/socket/socket_set.is_set.html +/library/std/socket/Socket.setKeepAlive.html /library/std/socket/socket.set_keep_alive.html +/library/std/socket/SocketSet.max.html /library/std/socket/socket_set.max.html +/library/std/socket/Socket.setOption.html /library/std/socket/socket.set_option.html +/library/std/socket/SocketSet.remove.html /library/std/socket/socket_set.remove.html +/library/std/socket/SocketSet.reset.html /library/std/socket/socket_set.reset.html +/library/std/socket/SocketSet.this.html /library/std/socket/socket_set.this.html +/library/std/socket/SocketShutdown.BOTH.html /library/std/socket/socket_shutdown.both.html +/library/std/socket/Socket.shutdown.html /library/std/socket/socket.shutdown.html +/library/std/socket/SocketShutdown.html /library/std/socket/socket_shutdown.html +/library/std/socket/SocketShutdown.RECEIVE.html /library/std/socket/socket_shutdown.receive.html +/library/std/socket/SocketShutdown.SEND.html /library/std/socket/socket_shutdown.send.html +/library/std/socket/Socket.this.html /library/std/socket/socket.this.html +/library/std/socket/SocketType.DGRAM.html /library/std/socket/socket_type.dgram.html +/library/std/socket/SocketType.html /library/std/socket/socket_type.html +/library/std/socket/SocketType.RAW.html /library/std/socket/socket_type.raw.html +/library/std/socket/SocketType.RDM.html /library/std/socket/socket_type.rdm.html +/library/std/socket/SocketType.SEQPACKET.html /library/std/socket/socket_type.seqpacket.html +/library/std/socket/SocketType.STREAM.html /library/std/socket/socket_type.stream.html +/library/std/socketstream/InputStream.available.html /library/std/socketstream/input_stream.available.html +/library/std/socketstream/InputStream.eof.html /library/std/socketstream/input_stream.eof.html +/library/std/socketstream/InputStream.getc.html /library/std/socketstream/input_stream.getc.html +/library/std/socketstream/InputStream.getcw.html /library/std/socketstream/input_stream.getcw.html +/library/std/socketstream/InputStream.isOpen.html /library/std/socketstream/input_stream.is_open.html +/library/std/socketstream/InputStream.opApply.html /library/std/socketstream/input_stream.op_apply.html +/library/std/socketstream/InputStream.readExact.html /library/std/socketstream/input_stream.read_exact.html +/library/std/socketstream/InputStream.readf.html /library/std/socketstream/input_stream.readf.html +/library/std/socketstream/InputStream.read.html /library/std/socketstream/input_stream.read.html +/library/std/socketstream/InputStream.readLine.html /library/std/socketstream/input_stream.read_line.html +/library/std/socketstream/InputStream.readLineW.html /library/std/socketstream/input_stream.read_line.html +/library/std/socketstream/InputStream.readString.html /library/std/socketstream/input_stream.read_string.html +/library/std/socketstream/InputStream.readStringW.html /library/std/socketstream/input_stream.read_string.html +/library/std/socketstream/InputStream.ungetc.html /library/std/socketstream/input_stream.ungetc.html +/library/std/socketstream/InputStream.ungetcw.html /library/std/socketstream/input_stream.ungetcw.html +/library/std/socketstream/InputStream.vreadf.html /library/std/socketstream/input_stream.vreadf.html +/library/std/socketstream/Object.factory.html /library/std/socketstream/object.factory.html +/library/std/socketstream/Object.opCmp.html /library/std/socketstream/object.op_cmp.html +/library/std/socketstream/Object.opEquals.html /library/std/socketstream/object.op_equals.html +/library/std/socketstream/OutputStream.flush.html /library/std/socketstream/output_stream.flush.html +/library/std/socketstream/OutputStream.printf.html /library/std/socketstream/output_stream.printf.html +/library/std/socketstream/OutputStream.vprintf.html /library/std/socketstream/output_stream.vprintf.html +/library/std/socketstream/OutputStream.writeExact.html /library/std/socketstream/output_stream.write_exact.html +/library/std/socketstream/OutputStream.writef.html /library/std/socketstream/output_stream.writef.html +/library/std/socketstream/OutputStream.writefln.html /library/std/socketstream/output_stream.writefln.html +/library/std/socketstream/OutputStream.writefx.html /library/std/socketstream/output_stream.writefx.html +/library/std/socketstream/OutputStream.write.html /library/std/socketstream/output_stream.write.html +/library/std/socketstream/OutputStream.writeLine.html /library/std/socketstream/output_stream.write_line.html +/library/std/socketstream/OutputStream.writeLineW.html /library/std/socketstream/output_stream.write_line.html +/library/std/socketstream/OutputStream.writeString.html /library/std/socketstream/output_stream.write_string.html +/library/std/socketstream/OutputStream.writeStringW.html /library/std/socketstream/output_stream.write_string.html +/library/std/socketstream/SocketStream.close.html /library/std/socketstream/socket_stream.close.html +/library/std/socketstream/SocketStream.html /library/std/socketstream/socket_stream.html +/library/std/socketstream/SocketStream.readBlock.html /library/std/socketstream/socket_stream.read_block.html +/library/std/socketstream/SocketStream.seek.html /library/std/socketstream/socket_stream.seek.html +/library/std/socketstream/SocketStream.socket.html /library/std/socketstream/socket_stream.socket.html +/library/std/socketstream/SocketStream.this.html /library/std/socketstream/socket_stream.this.html +/library/std/socketstream/SocketStream.toString.html /library/std/socketstream/socket_stream.to_string.html +/library/std/socketstream/SocketStream.writeBlock.html /library/std/socketstream/socket_stream.write_block.html +/library/std/socketstream/Stream.copyFrom.html /library/std/socketstream/stream.copy_from.html +/library/std/socketstream/Stream.isopen.html /library/std/socketstream/stream.isopen.html +/library/std/socketstream/Stream.position.html /library/std/socketstream/stream.position.html +/library/std/socketstream/Stream.prevCr.html /library/std/socketstream/stream.prev_cr.html +/library/std/socketstream/Stream.readable.html /library/std/socketstream/stream.readable.html +/library/std/socketstream/Stream.readEOF.html /library/std/socketstream/stream.read_eof.html +/library/std/socketstream/Stream.seekable.html /library/std/socketstream/stream.seekable.html +/library/std/socketstream/Stream.seekCur.html /library/std/socketstream/stream.seek_cur.html +/library/std/socketstream/Stream.seekEnd.html /library/std/socketstream/stream.seek_end.html +/library/std/socketstream/Stream.seekSet.html /library/std/socketstream/stream.seek_set.html +/library/std/socketstream/Stream.size.html /library/std/socketstream/stream.size.html +/library/std/socketstream/Stream.toHash.html /library/std/socketstream/stream.to_hash.html +/library/std/socketstream/Stream.writeable.html /library/std/socketstream/stream.writeable.html +/library/std/socket/TcpSocket.html /library/std/socket/tcp_socket.html +/library/std/socket/TcpSocket.this.html /library/std/socket/tcp_socket.this.html +/library/std/socket/Throwable.file.html /library/std/socket/throwable.file.html +/library/std/socket/Throwable.info.html /library/std/socket/throwable.info.html +/library/std/socket/Throwable.line.html /library/std/socket/throwable.line.html +/library/std/socket/Throwable.msg.html /library/std/socket/throwable.msg.html +/library/std/socket/Throwable.next.html /library/std/socket/throwable.next.html +/library/std/socket/Throwable.toString.html /library/std/socket/throwable.to_string.html +/library/std/socket/TimeVal.html /library/std/socket/time_val.html +/library/std/socket/TimeVal.microseconds.html /library/std/socket/time_val.microseconds.html +/library/std/socket/TimeVal.seconds.html /library/std/socket/time_val.seconds.html +/library/std/socket/UdpSocket.html /library/std/socket/udp_socket.html +/library/std/socket/UdpSocket.this.html /library/std/socket/udp_socket.this.html +/library/std/socket/UnixAddress.html /library/std/socket/unix_address.html +/library/std/socket/UnixAddress.path.html /library/std/socket/unix_address.path.html +/library/std/socket/UnixAddress.this.html /library/std/socket/unix_address.this.html +/library/std/socket/UnixAddress.toString.html /library/std/socket/unix_address.to_string.html +/library/std/socket/UnknownAddress.html /library/std/socket/unknown_address.html +/library/std/socket/UnknownAddressReference.html /library/std/socket/unknown_address_reference.html +/library/std/socket/UnknownAddressReference.this.html /library/std/socket/unknown_address_reference.this.html +/library/std/socket/wouldHaveBlocked.html /library/std/socket/would_have_blocked.html +/library/std/stdio/File.byChunk.html /library/std/stdio/file.by_chunk.html +/library/std/stdio/File.byLineCopy.html /library/std/stdio/file.by_line_copy.html +/library/std/stdio/File.byLine.html /library/std/stdio/file.by_line.html +/library/std/stdio/File.clearerr.html /library/std/stdio/file.clearerr.html +/library/std/stdio/File.close.html /library/std/stdio/file.close.html +/library/std/stdio/File.detach.html /library/std/stdio/file.detach.html +/library/std/stdio/File.eof.html /library/std/stdio/file.eof.html +/library/std/stdio/File.error.html /library/std/stdio/file.error.html +/library/std/stdio/File.fdopen.html /library/std/stdio/file.fdopen.html +/library/std/stdio/File.fileno.html /library/std/stdio/file.fileno.html +/library/std/stdio/File.flush.html /library/std/stdio/file.flush.html +/library/std/stdio/File.getFP.html /library/std/stdio/file.get_fp.html +/library/std/stdio/File.html /library/std/stdio/file.html +/library/std/stdio/File.isOpen.html /library/std/stdio/file.is_open.html +/library/std/stdio/File.lock.html /library/std/stdio/file.lock.html +/library/std/stdio/File.lockingTextWriter.html /library/std/stdio/file.locking_text_writer.html +/library/std/stdio/File.name.html /library/std/stdio/file.name.html +/library/std/stdio/File.opAssign.html /library/std/stdio/file.op_assign.html +/library/std/stdio/File.open.html /library/std/stdio/file.open.html +/library/std/stdio/File.popen.html /library/std/stdio/file.popen.html +/library/std/stdio/File.rawRead.html /library/std/stdio/file.raw_read.html +/library/std/stdio/File.rawWrite.html /library/std/stdio/file.raw_write.html +/library/std/stdio/File.readf.html /library/std/stdio/file.readf.html +/library/std/stdio/File.readln.html /library/std/stdio/file.readln.html +/library/std/stdio/File.rewind.html /library/std/stdio/file.rewind.html +/library/std/stdio/File.seek.html /library/std/stdio/file.seek.html +/library/std/stdio/File.setvbuf.html /library/std/stdio/file.setvbuf.html +/library/std/stdio/File.size.html /library/std/stdio/file.size.html +/library/std/stdio/File.tell.html /library/std/stdio/file.tell.html +/library/std/stdio/File.this.html /library/std/stdio/file.this.html +/library/std/stdio/File.tmpfile.html /library/std/stdio/file.tmpfile.html +/library/std/stdio/File.tryLock.html /library/std/stdio/file.try_lock.html +/library/std/stdio/File.unlock.html /library/std/stdio/file.unlock.html +/library/std/stdio/File.windowsHandle.html /library/std/stdio/file.windows_handle.html +/library/std/stdio/File.windowsHandleOpen.html /library/std/stdio/file.windows_handle_open.html +/library/std/stdio/File.wrapFile.html /library/std/stdio/file.wrap_file.html +/library/std/stdio/File.writef.html /library/std/stdio/file.writef.html +/library/std/stdio/File.writefln.html /library/std/stdio/file.writefln.html +/library/std/stdio/File.write.html /library/std/stdio/file.write.html +/library/std/stdio/File.writeln.html /library/std/stdio/file.writeln.html +/library/std/stdio/isFileHandle.html /library/std/stdio/is_file_handle.html +/library/std/stdio/isStreamingDevice.html /library/std/stdio/is_streaming_device.html +/library/std/stdio/KeepTerminator.html /library/std/stdio/keep_terminator.html +/library/std/stdio/LockType.html /library/std/stdio/lock_type.html +/library/std/stdio/LockType.read.html /library/std/stdio/lock_type.read.html +/library/std/stdio/LockType.readWrite.html /library/std/stdio/lock_type.read_write.html +/library/std/stdio/Object.factory.html /library/std/stdio/object.factory.html +/library/std/stdio/Object.opCmp.html /library/std/stdio/object.op_cmp.html +/library/std/stdio/Object.opEquals.html /library/std/stdio/object.op_equals.html +/library/std/stdio/Object.toHash.html /library/std/stdio/object.to_hash.html +/library/std/stdio/openNetwork.html /library/std/stdio/open_network.html +/library/std/stdio/StdioException.errno.html /library/std/stdio/stdio_exception.errno.html +/library/std/stdio/StdioException.html /library/std/stdio/stdio_exception.html +/library/std/stdio/StdioException.opCall.html /library/std/stdio/stdio_exception.op_call.html +/library/std/stdio/StdioException.this.html /library/std/stdio/stdio_exception.this.html +/library/std/stdio/Throwable.file.html /library/std/stdio/throwable.file.html +/library/std/stdio/Throwable.info.html /library/std/stdio/throwable.info.html +/library/std/stdio/Throwable.line.html /library/std/stdio/throwable.line.html +/library/std/stdio/Throwable.msg.html /library/std/stdio/throwable.msg.html +/library/std/stdio/Throwable.next.html /library/std/stdio/throwable.next.html +/library/std/stdio/Throwable.toString.html /library/std/stdio/throwable.to_string.html +/library/std/stream/BOM.html /library/std/stream/bom.html +/library/std/stream/BOM.UTF16BE.html /library/std/stream/bom.ut_f16_be.html +/library/std/stream/BOM.UTF16LE.html /library/std/stream/bom.ut_f16_le.html +/library/std/stream/BOM.UTF32BE.html /library/std/stream/bom.ut_f32_be.html +/library/std/stream/BOM.UTF32LE.html /library/std/stream/bom.ut_f32_le.html +/library/std/stream/BOM.UTF8.html /library/std/stream/bom.ut_f8.html +/library/std/stream/BufferedFile.create.html /library/std/stream/buffered_file.create.html +/library/std/stream/BufferedFile.html /library/std/stream/buffered_file.html +/library/std/stream/BufferedFile.open.html /library/std/stream/buffered_file.open.html +/library/std/stream/BufferedFile.this.html /library/std/stream/buffered_file.this.html +/library/std/stream/BufferedStream.html /library/std/stream/buffered_stream.html +/library/std/stream/BufferedStream.this.html /library/std/stream/buffered_stream.this.html +/library/std/stream/EndianStream.endian.html /library/std/stream/endian_stream.endian.html +/library/std/stream/EndianStream.fixBlockBO.html /library/std/stream/endian_stream.fix_block_bo.html +/library/std/stream/EndianStream.fixBO.html /library/std/stream/endian_stream.fix_bo.html +/library/std/stream/EndianStream.html /library/std/stream/endian_stream.html +/library/std/stream/EndianStream.readBOM.html /library/std/stream/endian_stream.read_bom.html +/library/std/stream/EndianStream.this.html /library/std/stream/endian_stream.this.html +/library/std/stream/EndianStream.writeBOM.html /library/std/stream/endian_stream.write_bom.html +/library/std/stream/File.available.html /library/std/stream/file.available.html +/library/std/stream/File.close.html /library/std/stream/file.close.html +/library/std/stream/File.create.html /library/std/stream/file.create.html +/library/std/stream/File.html /library/std/stream/file.html +/library/std/stream/FileMode.Append.html /library/std/stream/file_mode.append.html +/library/std/stream/FileMode.html /library/std/stream/file_mode.html +/library/std/stream/FileMode.In.html /library/std/stream/file_mode.in.html +/library/std/stream/FileMode.Out.html /library/std/stream/file_mode.out.html +/library/std/stream/FileMode.OutNew.html /library/std/stream/file_mode.out_new.html +/library/std/stream/File.open.html /library/std/stream/file.open.html +/library/std/stream/File.this.html /library/std/stream/file.this.html +/library/std/stream/FilterStream.html /library/std/stream/filter_stream.html +/library/std/stream/FilterStream.nestClose.html /library/std/stream/filter_stream.nest_close.html +/library/std/stream/FilterStream.resetSource.html /library/std/stream/filter_stream.reset_source.html +/library/std/stream/FilterStream.source.html /library/std/stream/filter_stream.source.html +/library/std/stream/FilterStream.this.html /library/std/stream/filter_stream.this.html +/library/std/stream/InputStream.available.html /library/std/stream/input_stream.available.html +/library/std/stream/InputStream.eof.html /library/std/stream/input_stream.eof.html +/library/std/stream/InputStream.getc.html /library/std/stream/input_stream.getc.html +/library/std/stream/InputStream.getcw.html /library/std/stream/input_stream.getcw.html +/library/std/stream/InputStream.html /library/std/stream/input_stream.html +/library/std/stream/InputStream.isOpen.html /library/std/stream/input_stream.is_open.html +/library/std/stream/InputStream.opApply.html /library/std/stream/input_stream.op_apply.html +/library/std/stream/InputStream.readExact.html /library/std/stream/input_stream.read_exact.html +/library/std/stream/InputStream.readf.html /library/std/stream/input_stream.readf.html +/library/std/stream/InputStream.read.html /library/std/stream/input_stream.read.html +/library/std/stream/InputStream.readLine.html /library/std/stream/input_stream.read_line.html +/library/std/stream/InputStream.readLineW.html /library/std/stream/input_stream.read_line.html +/library/std/stream/InputStream.readString.html /library/std/stream/input_stream.read_string.html +/library/std/stream/InputStream.readStringW.html /library/std/stream/input_stream.read_string.html +/library/std/stream/InputStream.ungetc.html /library/std/stream/input_stream.ungetc.html +/library/std/stream/InputStream.ungetcw.html /library/std/stream/input_stream.ungetcw.html +/library/std/stream/InputStream.vreadf.html /library/std/stream/input_stream.vreadf.html +/library/std/stream/MemoryStream.html /library/std/stream/memory_stream.html +/library/std/stream/MemoryStream.reserve.html /library/std/stream/memory_stream.reserve.html +/library/std/stream/MemoryStream.this.html /library/std/stream/memory_stream.this.html +/library/std/stream/MmFileStream.html /library/std/stream/mm_file_stream.html +/library/std/stream/MmFileStream.this.html /library/std/stream/mm_file_stream.this.html +/library/std/stream/Object.factory.html /library/std/stream/object.factory.html +/library/std/stream/Object.opCmp.html /library/std/stream/object.op_cmp.html +/library/std/stream/Object.opEquals.html /library/std/stream/object.op_equals.html +/library/std/stream/Object.toHash.html /library/std/stream/object.to_hash.html +/library/std/stream/Object.toString.html /library/std/stream/object.to_string.html +/library/std/stream/OpenException.html /library/std/stream/open_exception.html +/library/std/stream/OpenException.this.html /library/std/stream/open_exception.this.html +/library/std/stream/OutputStream.close.html /library/std/stream/output_stream.close.html +/library/std/stream/OutputStream.flush.html /library/std/stream/output_stream.flush.html +/library/std/stream/OutputStream.html /library/std/stream/output_stream.html +/library/std/stream/OutputStream.isOpen.html /library/std/stream/output_stream.is_open.html +/library/std/stream/OutputStream.printf.html /library/std/stream/output_stream.printf.html +/library/std/stream/OutputStream.vprintf.html /library/std/stream/output_stream.vprintf.html +/library/std/stream/OutputStream.writeExact.html /library/std/stream/output_stream.write_exact.html +/library/std/stream/OutputStream.writef.html /library/std/stream/output_stream.writef.html +/library/std/stream/OutputStream.writefln.html /library/std/stream/output_stream.writefln.html +/library/std/stream/OutputStream.writefx.html /library/std/stream/output_stream.writefx.html +/library/std/stream/OutputStream.write.html /library/std/stream/output_stream.write.html +/library/std/stream/OutputStream.writeLine.html /library/std/stream/output_stream.write_line.html +/library/std/stream/OutputStream.writeLineW.html /library/std/stream/output_stream.write_line.html +/library/std/stream/OutputStream.writeString.html /library/std/stream/output_stream.write_string.html +/library/std/stream/OutputStream.writeStringW.html /library/std/stream/output_stream.write_string.html +/library/std/stream/ReadException.html /library/std/stream/read_exception.html +/library/std/stream/ReadException.this.html /library/std/stream/read_exception.this.html +/library/std/stream/SeekException.html /library/std/stream/seek_exception.html +/library/std/stream/SeekException.this.html /library/std/stream/seek_exception.this.html +/library/std/stream/SliceStream.html /library/std/stream/slice_stream.html +/library/std/stream/SliceStream.this.html /library/std/stream/slice_stream.this.html +/library/std/stream/Stream.copyFrom.html /library/std/stream/stream.copy_from.html +/library/std/stream/StreamException.html /library/std/stream/stream_exception.html +/library/std/stream/StreamException.this.html /library/std/stream/stream_exception.this.html +/library/std/stream/StreamFileException.html /library/std/stream/stream_file_exception.html +/library/std/stream/StreamFileException.this.html /library/std/stream/stream_file_exception.this.html +/library/std/stream/Stream.html /library/std/stream/stream.html +/library/std/stream/Stream.isopen.html /library/std/stream/stream.isopen.html +/library/std/stream/Stream.position.html /library/std/stream/stream.position.html +/library/std/stream/Stream.prevCr.html /library/std/stream/stream.prev_cr.html +/library/std/stream/Stream.readable.html /library/std/stream/stream.readable.html +/library/std/stream/Stream.readBlock.html /library/std/stream/stream.read_block.html +/library/std/stream/Stream.readEOF.html /library/std/stream/stream.read_eof.html +/library/std/stream/Stream.seekable.html /library/std/stream/stream.seekable.html +/library/std/stream/Stream.seekCur.html /library/std/stream/stream.seek_cur.html +/library/std/stream/Stream.seekEnd.html /library/std/stream/stream.seek_end.html +/library/std/stream/Stream.seek.html /library/std/stream/stream.seek.html +/library/std/stream/Stream.seekSet.html /library/std/stream/stream.seek_set.html +/library/std/stream/Stream.size.html /library/std/stream/stream.size.html +/library/std/stream/Stream.toHash.html /library/std/stream/stream.to_hash.html +/library/std/stream/Stream.toString.html /library/std/stream/stream.to_string.html +/library/std/stream/Stream.writeable.html /library/std/stream/stream.writeable.html +/library/std/stream/Stream.writeBlock.html /library/std/stream/stream.write_block.html +/library/std/stream/TArrayStream.data.html /library/std/stream/t_array_stream.data.html +/library/std/stream/TArrayStream.html /library/std/stream/t_array_stream.html +/library/std/stream/TArrayStream.this.html /library/std/stream/t_array_stream.this.html +/library/std/stream/Throwable.file.html /library/std/stream/throwable.file.html +/library/std/stream/Throwable.info.html /library/std/stream/throwable.info.html +/library/std/stream/Throwable.line.html /library/std/stream/throwable.line.html +/library/std/stream/Throwable.msg.html /library/std/stream/throwable.msg.html +/library/std/stream/Throwable.next.html /library/std/stream/throwable.next.html +/library/std/stream/Throwable.toString.html /library/std/stream/throwable.to_string.html +/library/std/stream/WriteException.html /library/std/stream/write_exception.html +/library/std/stream/WriteException.this.html /library/std/stream/write_exception.this.html +/library/std/string/assumeUTF.html /library/std/string/assume_utf.html +/library/std/string/CaseSensitive.html /library/std/string/case_sensitive.html +/library/std/string/chompPrefix.html /library/std/string/chomp_prefix.html +/library/std/string/fromStringz.html /library/std/string/from_stringz.html +/library/std/string/indexOfAny.html /library/std/string/index_of_any.html +/library/std/string/indexOf.html /library/std/string/index_of.html +/library/std/string/indexOfNeither.html /library/std/string/index_of_neither.html +/library/std/string/inPattern.html /library/std/string/in_pattern.html +/library/std/string/isNumeric.html /library/std/string/is_numeric.html +/library/std/string/KeepTerminator.html /library/std/string/keep_terminator.html +/library/std/string/lastIndexOfAny.html /library/std/string/last_index_of_any.html +/library/std/string/lastIndexOf.html /library/std/string/last_index_of.html +/library/std/string/lastIndexOfNeither.html /library/std/string/last_index_of_neither.html +/library/std/string/leftJustify.html /library/std/string/left_justify.html +/library/std/string/lineSplitter.html /library/std/string/line_splitter.html +/library/std/string/makeTrans.html /library/std/string/make_trans.html +/library/std/string/Object.factory.html /library/std/string/object.factory.html +/library/std/string/Object.opCmp.html /library/std/string/object.op_cmp.html +/library/std/string/Object.opEquals.html /library/std/string/object.op_equals.html +/library/std/string/Object.toHash.html /library/std/string/object.to_hash.html +/library/std/string/rightJustify.html /library/std/string/right_justify.html +/library/std/string/splitLines.html /library/std/string/split_lines.html +/library/std/string/StringException.html /library/std/string/string_exception.html +/library/std/string/StringException.this.html /library/std/string/string_exception.this.html +/library/std/string/stripLeft.html /library/std/string/strip_left.html +/library/std/string/stripRight.html /library/std/string/strip_right.html +/library/std/string/Throwable.file.html /library/std/string/throwable.file.html +/library/std/string/Throwable.info.html /library/std/string/throwable.info.html +/library/std/string/Throwable.line.html /library/std/string/throwable.line.html +/library/std/string/Throwable.msg.html /library/std/string/throwable.msg.html +/library/std/string/Throwable.next.html /library/std/string/throwable.next.html +/library/std/string/Throwable.toString.html /library/std/string/throwable.to_string.html +/library/std/string/toStringz.html /library/std/string/to_stringz.html +/library/std/system/Endian.bigEndian.html /library/std/system/endian.big_endian.html +/library/std/system/Endian.html /library/std/system/endian.html +/library/std/system/Endian.littleEndian.html /library/std/system/endian.little_endian.html +/library/std/system/OS.android.html /library/std/system/os.android.html +/library/std/system/OS.freeBSD.html /library/std/system/os.free_bsd.html +/library/std/system/OS.html /library/std/system/os.html +/library/std/system/OS.linux.html /library/std/system/os.linux.html +/library/std/system/OS.osx.html /library/std/system/os.osx.html +/library/std/system/OS.otherPosix.html /library/std/system/os.other_posix.html +/library/std/system/OS.solaris.html /library/std/system/os.solaris.html +/library/std/system/OS.win32.html /library/std/system/os.win32.html +/library/std/system/OS.win64.html /library/std/system/os.win64.html +/library/std/traits/areAllSafe.html /library/std/traits/are_all_safe.html +/library/std/traits/BaseClassesTuple.html /library/std/traits/base_classes_tuple.html +/library/std/traits/BaseTypeTuple.html /library/std/traits/base_type_tuple.html +/library/std/traits/classInstanceAlignment.html /library/std/traits/class_instance_alignment.html +/library/std/traits/CommonType.html /library/std/traits/common_type.html +/library/std/traits/EnumMembers.html /library/std/traits/enum_members.html +/library/std/traits/FieldNameTuple.html /library/std/traits/field_name_tuple.html +/library/std/traits/FieldTypeTuple.html /library/std/traits/field_type_tuple.html +/library/std/traits/ForeachType.html /library/std/traits/foreach_type.html +/library/std/traits/fullyQualifiedName.html /library/std/traits/fully_qualified_name.html +/library/std/traits/FunctionAttribute.const_.html /library/std/traits/function_attribute.const_.html +/library/std/traits/FunctionAttribute.html /library/std/traits/function_attribute.html +/library/std/traits/FunctionAttribute.immutable_.html /library/std/traits/function_attribute.immutable_.html +/library/std/traits/FunctionAttribute.inout_.html /library/std/traits/function_attribute.inout_.html +/library/std/traits/FunctionAttribute.nogc.html /library/std/traits/function_attribute.nogc.html +/library/std/traits/FunctionAttribute.none.html /library/std/traits/function_attribute.none.html +/library/std/traits/FunctionAttribute.nothrow_.html /library/std/traits/function_attribute.nothrow_.html +/library/std/traits/FunctionAttribute.property.html /library/std/traits/function_attribute.property.html +/library/std/traits/FunctionAttribute.pure_.html /library/std/traits/function_attribute.pure_.html +/library/std/traits/FunctionAttribute.ref_.html /library/std/traits/function_attribute.ref_.html +/library/std/traits/FunctionAttribute.return_.html /library/std/traits/function_attribute.return_.html +/library/std/traits/FunctionAttribute.safe.html /library/std/traits/function_attribute.safe.html +/library/std/traits/FunctionAttribute.shared_.html /library/std/traits/function_attribute.shared_.html +/library/std/traits/functionAttributes.html /library/std/traits/function_attributes.html +/library/std/traits/FunctionAttribute.system.html /library/std/traits/function_attribute.system.html +/library/std/traits/FunctionAttribute.trusted.html /library/std/traits/function_attribute.trusted.html +/library/std/traits/functionLinkage.html /library/std/traits/function_linkage.html +/library/std/traits/FunctionTypeOf.html /library/std/traits/function_type_of.html +/library/std/traits/hasAliasing.html /library/std/traits/has_aliasing.html +/library/std/traits/hasElaborateAssign.html /library/std/traits/has_elaborate_assign.html +/library/std/traits/hasElaborateCopyConstructor.html /library/std/traits/has_elaborate_copy_constructor.html +/library/std/traits/hasElaborateDestructor.html /library/std/traits/has_elaborate_destructor.html +/library/std/traits/hasIndirections.html /library/std/traits/has_indirections.html +/library/std/traits/hasMember.html /library/std/traits/has_member.html +/library/std/traits/hasNested.html /library/std/traits/has_nested.html +/library/std/traits/hasUnsharedAliasing.html /library/std/traits/has_unshared_aliasing.html +/library/std/traits/ImplicitConversionTargets.html /library/std/traits/implicit_conversion_targets.html +/library/std/traits/InterfacesTuple.html /library/std/traits/interfaces_tuple.html +/library/std/traits/isAbstractClass.html /library/std/traits/is_abstract_class.html +/library/std/traits/isAbstractFunction.html /library/std/traits/is_abstract_function.html +/library/std/traits/isAggregateType.html /library/std/traits/is_aggregate_type.html +/library/std/traits/isArray.html /library/std/traits/is_array.html +/library/std/traits/isAssignable.html /library/std/traits/is_assignable.html +/library/std/traits/isAssociativeArray.html /library/std/traits/is_associative_array.html +/library/std/traits/isBasicType.html /library/std/traits/is_basic_type.html +/library/std/traits/isBoolean.html /library/std/traits/is_boolean.html +/library/std/traits/isBuiltinType.html /library/std/traits/is_builtin_type.html +/library/std/traits/isCallable.html /library/std/traits/is_callable.html +/library/std/traits/isCovariantWith.html /library/std/traits/is_covariant_with.html +/library/std/traits/isDelegate.html /library/std/traits/is_delegate.html +/library/std/traits/isDynamicArray.html /library/std/traits/is_dynamic_array.html +/library/std/traits/isExpressionTuple.html /library/std/traits/is_expression_tuple.html +/library/std/traits/isFinalClass.html /library/std/traits/is_final_class.html +/library/std/traits/isFinalFunction.html /library/std/traits/is_final_function.html +/library/std/traits/isFloatingPoint.html /library/std/traits/is_floating_point.html +/library/std/traits/isFunctionPointer.html /library/std/traits/is_function_pointer.html +/library/std/traits/isImplicitlyConvertible.html /library/std/traits/is_implicitly_convertible.html +/library/std/traits/isInstanceOf.html /library/std/traits/is_instance_of.html +/library/std/traits/isIntegral.html /library/std/traits/is_integral.html +/library/std/traits/isIterable.html /library/std/traits/is_iterable.html +/library/std/traits/isMutable.html /library/std/traits/is_mutable.html +/library/std/traits/isNestedFunction.html /library/std/traits/is_nested_function.html +/library/std/traits/isNested.html /library/std/traits/is_nested.html +/library/std/traits/isNumeric.html /library/std/traits/is_numeric.html +/library/std/traits/isPointer.html /library/std/traits/is_pointer.html +/library/std/traits/isSafe.html /library/std/traits/is_safe.html +/library/std/traits/isScalarType.html /library/std/traits/is_scalar_type.html +/library/std/traits/isSigned.html /library/std/traits/is_signed.html +/library/std/traits/isSIMDVector.html /library/std/traits/is_simd_vector.html +/library/std/traits/isSomeChar.html /library/std/traits/is_some_char.html +/library/std/traits/isSomeFunction.html /library/std/traits/is_some_function.html +/library/std/traits/isSomeString.html /library/std/traits/is_some_string.html +/library/std/traits/isStaticArray.html /library/std/traits/is_static_array.html +/library/std/traits/isTypeTuple.html /library/std/traits/is_type_tuple.html +/library/std/traits/isUnsafe.html /library/std/traits/is_unsafe.html +/library/std/traits/isUnsigned.html /library/std/traits/is_unsigned.html +/library/std/traits/KeyType.html /library/std/traits/key_type.html +/library/std/traits/Largest.html /library/std/traits/largest.html +/library/std/traits/lvalueOf.html /library/std/traits/lvalue_of.html +/library/std/traits/mangledName.html /library/std/traits/mangled_name.html +/library/std/traits/MemberFunctionsTuple.html /library/std/traits/member_functions_tuple.html +/library/std/traits/moduleName.html /library/std/traits/module_name.html +/library/std/traits/mostNegative.html /library/std/traits/most_negative.html +/library/std/traits/OriginalType.html /library/std/traits/original_type.html +/library/std/traits/packageName.html /library/std/traits/package_name.html +/library/std/traits/ParameterDefaultValueTuple.html /library/std/traits/parameter_default_value_tuple.html +/library/std/traits/ParameterIdentifierTuple.html /library/std/traits/parameter_identifier_tuple.html +/library/std/traits/ParameterStorageClass.html /library/std/traits/parameter_storage_class.html +/library/std/traits/ParameterStorageClass.lazy_.html /library/std/traits/parameter_storage_class.lazy_.html +/library/std/traits/ParameterStorageClass.none.html /library/std/traits/parameter_storage_class.none.html +/library/std/traits/ParameterStorageClass.out_.html /library/std/traits/parameter_storage_class.out_.html +/library/std/traits/ParameterStorageClass.ref_.html /library/std/traits/parameter_storage_class.ref_.html +/library/std/traits/ParameterStorageClass.return_.html /library/std/traits/parameter_storage_class.return_.html +/library/std/traits/ParameterStorageClass.scope_.html /library/std/traits/parameter_storage_class.scope_.html +/library/std/traits/ParameterStorageClassTuple.html /library/std/traits/parameter_storage_class_tuple.html +/library/std/traits/ParameterTypeTuple.html /library/std/traits/parameter_type_tuple.html +/library/std/traits/pointerTarget.html /library/std/traits/pointer_target.html +/library/std/traits/PointerTarget.html /library/std/traits/pointer_target.html +/library/std/traits/RepresentationTypeTuple.html /library/std/traits/representation_type_tuple.html +/library/std/traits/ReturnType.html /library/std/traits/return_type.html +/library/std/traits/rvalueOf.html /library/std/traits/rvalue_of.html +/library/std/traits/Select.html /library/std/traits/select.html +/library/std/traits/SetFunctionAttributes.html /library/std/traits/set_function_attributes.html +/library/std/traits/Signed.html /library/std/traits/signed.html +/library/std/traits/TemplateArgsOf.html /library/std/traits/template_args_of.html +/library/std/traits/TemplateOf.html /library/std/traits/template_of.html +/library/std/traits/TransitiveBaseTypeTuple.html /library/std/traits/transitive_base_type_tuple.html +/library/std/traits/Unqual.html /library/std/traits/unqual.html +/library/std/traits/Unsigned.html /library/std/traits/unsigned.html +/library/std/traits/ValueType.html /library/std/traits/value_type.html +/library/std/traits/Variadic.c.html /library/std/traits/variadic.c.html +/library/std/traits/Variadic.d.html /library/std/traits/variadic.d.html +/library/std/traits/variadicFunctionStyle.html /library/std/traits/variadic_function_style.html +/library/std/traits/Variadic.html /library/std/traits/variadic.html +/library/std/traits/Variadic.no.html /library/std/traits/variadic.no.html +/library/std/traits/Variadic.typesafe.html /library/std/traits/variadic.typesafe.html +/library/std/typecons/alignForSize.html /library/std/typecons/align_for_size.html +/library/std/typecons/AutoImplement.html /library/std/typecons/auto_implement.html +/library/std/typecons/BitFlags.html /library/std/typecons/bit_flags.html +/library/std/typecons/BlackHole.html /library/std/typecons/black_hole.html +/library/std/typecons/Flag.html /library/std/typecons/flag.html +/library/std/typecons/Flag.no.html /library/std/typecons/flag.no.html +/library/std/typecons/Flag.yes.html /library/std/typecons/flag.yes.html +/library/std/typecons/generateAssertTrap.html /library/std/typecons/generate_assert_trap.html +/library/std/typecons/generateEmptyFunction.html /library/std/typecons/generate_empty_function.html +/library/std/typecons/isBitFlagEnum.html /library/std/typecons/is_bit_flag_enum.html +/library/std/typecons/isTuple.html /library/std/typecons/is_tuple.html +/library/std/typecons/No.html /library/std/typecons/no.html +/library/std/typecons/Nullable.get.html /library/std/typecons/nullable.get.html +/library/std/typecons/Nullable.html /library/std/typecons/nullable.html +/library/std/typecons/Nullable.isNull.html /library/std/typecons/nullable.is_null.html +/library/std/typecons/Nullable.nullify.html /library/std/typecons/nullable.nullify.html +/library/std/typecons/Nullable.nullify.nullify.html /library/std/typecons/nullable.nullify.nullify.html +/library/std/typecons/Nullable.opAssign.html /library/std/typecons/nullable.op_assign.html +/library/std/typecons/Nullable.opAssign.opAssign.html /library/std/typecons/nullable.op_assign.op_assign.html +/library/std/typecons/NullableRef.bind.html /library/std/typecons/nullable_ref.bind.html +/library/std/typecons/NullableRef.get.html /library/std/typecons/nullable_ref.get.html +/library/std/typecons/NullableRef.html /library/std/typecons/nullable_ref.html +/library/std/typecons/NullableRef.isNull.html /library/std/typecons/nullable_ref.is_null.html +/library/std/typecons/NullableRef.nullify.html /library/std/typecons/nullable_ref.nullify.html +/library/std/typecons/NullableRef.opAssign.html /library/std/typecons/nullable_ref.op_assign.html +/library/std/typecons/NullableRef.opAssign.opAssign.html /library/std/typecons/nullable_ref.op_assign.op_assign.html +/library/std/typecons/NullableRef.this.html /library/std/typecons/nullable_ref.this.html +/library/std/typecons/Nullable.this.html /library/std/typecons/nullable.this.html +/library/std/typecons/Object.factory.html /library/std/typecons/object.factory.html +/library/std/typecons/Object.opCmp.html /library/std/typecons/object.op_cmp.html +/library/std/typecons/Object.opEquals.html /library/std/typecons/object.op_equals.html +/library/std/typecons/Object.toHash.html /library/std/typecons/object.to_hash.html +/library/std/typecons/Object.toString.html /library/std/typecons/object.to_string.html +/library/std/typecons/Proxy.html /library/std/typecons/proxy.html +/library/std/typecons/Rebindable.html /library/std/typecons/rebindable.html +/library/std/typecons/RefCountedAutoInitialize.html /library/std/typecons/ref_counted_auto_initialize.html +/library/std/typecons/RefCountedAutoInitialize.no.html /library/std/typecons/ref_counted_auto_initialize.no.html +/library/std/typecons/RefCountedAutoInitialize.yes.html /library/std/typecons/ref_counted_auto_initialize.yes.html +/library/std/typecons/RefCounted.html /library/std/typecons/ref_counted.html +/library/std/typecons/RefCounted.opAssign.html /library/std/typecons/ref_counted.op_assign.html +/library/std/typecons/RefCounted.refCountedPayload.html /library/std/typecons/ref_counted.ref_counted_payload.html +/library/std/typecons/RefCounted.RefCountedStore.ensureInitialized.html /library/std/typecons/ref_counted.ref_counted_store.ensure_initialized.html +/library/std/typecons/RefCounted.refCountedStore.html /library/std/typecons/ref_counted.ref_counted_store.html +/library/std/typecons/RefCounted.RefCountedStore.html /library/std/typecons/ref_counted.ref_counted_store.html +/library/std/typecons/RefCounted.RefCountedStore.isInitialized.html /library/std/typecons/ref_counted.ref_counted_store.is_initialized.html +/library/std/typecons/RefCounted.RefCountedStore.refCount.html /library/std/typecons/ref_counted.ref_counted_store.ref_count.html +/library/std/typecons/RefCounted.this.html /library/std/typecons/ref_counted.this.html +/library/std/typecons/RefCounted.this.this.html /library/std/typecons/ref_counted.this.this.html +/library/std/typecons/Tuple.expand.html /library/std/typecons/tuple.expand.html +/library/std/typecons/Tuple.fieldNames.html /library/std/typecons/tuple.field_names.html +/library/std/typecons/Tuple.html /library/std/typecons/tuple.html +/library/std/typecons/Tuple.opAssign.html /library/std/typecons/tuple.op_assign.html +/library/std/typecons/Tuple.opAssign.opAssign.html /library/std/typecons/tuple.op_assign.op_assign.html +/library/std/typecons/Tuple.opCmp.html /library/std/typecons/tuple.op_cmp.html +/library/std/typecons/Tuple.opCmp.opCmp.html /library/std/typecons/tuple.op_cmp.op_cmp.html +/library/std/typecons/Tuple.opEquals.html /library/std/typecons/tuple.op_equals.html +/library/std/typecons/Tuple.opEquals.opEquals.html /library/std/typecons/tuple.op_equals.op_equals.html +/library/std/typecons/Tuple.slice.html /library/std/typecons/tuple.slice.html +/library/std/typecons/Tuple.slice.slice.html /library/std/typecons/tuple.slice.slice.html +/library/std/typecons/Tuple.this.html /library/std/typecons/tuple.this.html +/library/std/typecons/Tuple.this.this.html /library/std/typecons/tuple.this.this.html +/library/std/typecons/Tuple.toString.html /library/std/typecons/tuple.to_string.html +/library/std/typecons/Tuple.toString.toString.html /library/std/typecons/tuple.to_string.to_string.html +/library/std/typecons/Tuple.Types.html /library/std/typecons/tuple.types.html +/library/std/typecons/Typedef.html /library/std/typecons/typedef.html +/library/std/typecons/TypedefType.html /library/std/typecons/typedef_type.html +/library/std/typecons/Unique.html /library/std/typecons/unique.html +/library/std/typecons/Unique.isEmpty.html /library/std/typecons/unique.is_empty.html +/library/std/typecons/Unique.opAssign.html /library/std/typecons/unique.op_assign.html +/library/std/typecons/Unique.opAssign.opAssign.html /library/std/typecons/unique.op_assign.op_assign.html +/library/std/typecons/Unique.opDot.html /library/std/typecons/unique.op_dot.html +/library/std/typecons/Unique.release.html /library/std/typecons/unique.release.html +/library/std/typecons/Unique.this.html /library/std/typecons/unique.this.html +/library/std/typecons/Unique.this.this.html /library/std/typecons/unique.this.this.html +/library/std/typecons/UnqualRef.html /library/std/typecons/unqual_ref.html +/library/std/typecons/WhiteHole.html /library/std/typecons/white_hole.html +/library/std/typecons/Yes.html /library/std/typecons/yes.html +/library/std/typetuple/allSatisfy.html /library/std/typetuple/all_satisfy.html +/library/std/typetuple/anySatisfy.html /library/std/typetuple/any_satisfy.html +/library/std/typetuple/DerivedToFront.html /library/std/typetuple/derived_to_front.html +/library/std/typetuple/EraseAll.html /library/std/typetuple/erase_all.html +/library/std/typetuple/Erase.html /library/std/typetuple/erase.html +/library/std/typetuple/Filter.html /library/std/typetuple/filter.html +/library/std/typetuple/IndexOf.html /library/std/typetuple/index_of.html +/library/std/typetuple/MostDerived.html /library/std/typetuple/most_derived.html +/library/std/typetuple/NoDuplicates.html /library/std/typetuple/no_duplicates.html +/library/std/typetuple/ReplaceAll.html /library/std/typetuple/replace_all.html +/library/std/typetuple/Replace.html /library/std/typetuple/replace.html +/library/std/typetuple/Reverse.html /library/std/typetuple/reverse.html +/library/std/typetuple/staticIndexOf.html /library/std/typetuple/static_index_of.html +/library/std/typetuple/staticMap.html /library/std/typetuple/static_map.html +/library/std/typetuple/templateAnd.html /library/std/typetuple/template_and.html +/library/std/typetuple/templateNot.html /library/std/typetuple/template_not.html +/library/std/typetuple/templateNot.templateNot.html /library/std/typetuple/template_not.template_not.html +/library/std/typetuple/templateOr.html /library/std/typetuple/template_or.html +/library/std/typetuple/TypeTuple.html /library/std/typetuple/type_tuple.html +/library/std/uni/allowedIn.html /library/std/uni/allowed_in.html +/library/std/uni/byCodePoint.html /library/std/uni/by_code_point.html +/library/std/uni/byGrapheme.html /library/std/uni/by_grapheme.html +/library/std/uni/CodepointInterval.html /library/std/uni/codepoint_interval.html +/library/std/uni/CodepointSet.html /library/std/uni/codepoint_set.html +/library/std/uni/codepointSetTrie.codepointSetTrie.html /library/std/uni/codepoint_set_trie.codepoint_set_trie.html +/library/std/uni/codepointSetTrie.html /library/std/uni/codepoint_set_trie.html +/library/std/uni/CodepointSetTrie.html /library/std/uni/codepoint_set_trie.html +/library/std/uni/codepointTrie.codepointTrie.html /library/std/uni/codepoint_trie.codepoint_trie.html +/library/std/uni/codepointTrie.html /library/std/uni/codepoint_trie.html +/library/std/uni/CodepointTrie.html /library/std/uni/codepoint_trie.html +/library/std/uni/combiningClass.html /library/std/uni/combining_class.html +/library/std/uni/composeJamo.html /library/std/uni/compose_jamo.html +/library/std/uni/decodeGrapheme.html /library/std/uni/decode_grapheme.html +/library/std/uni/decomposeHangul.html /library/std/uni/decompose_hangul.html +/library/std/uni/Grapheme.html /library/std/uni/grapheme.html +/library/std/uni/Grapheme.length.html /library/std/uni/grapheme.length.html +/library/std/uni/Grapheme.opIndexAssign.html /library/std/uni/grapheme.op_index_assign.html +/library/std/uni/Grapheme.opIndex.html /library/std/uni/grapheme.op_index.html +/library/std/uni/Grapheme.opOpAssign.html /library/std/uni/grapheme.op_op_assign.html +/library/std/uni/Grapheme.opSlice.html /library/std/uni/grapheme.op_slice.html +/library/std/uni/graphemeStride.html /library/std/uni/grapheme_stride.html +/library/std/uni/Grapheme.valid.html /library/std/uni/grapheme.valid.html +/library/std/uni/InversionList.add.add.html /library/std/uni/inversion_list.add.add.html +/library/std/uni/InversionList.add.html /library/std/uni/inversion_list.add.html +/library/std/uni/InversionList.byCodepoint.html /library/std/uni/inversion_list.by_codepoint.html +/library/std/uni/InversionList.byInterval.html /library/std/uni/inversion_list.by_interval.html +/library/std/uni/InversionList.empty.html /library/std/uni/inversion_list.empty.html +/library/std/uni/InversionList.html /library/std/uni/inversion_list.html +/library/std/uni/InversionList.inverted.html /library/std/uni/inversion_list.inverted.html +/library/std/uni/InversionList.length.html /library/std/uni/inversion_list.length.html +/library/std/uni/InversionList.opBinary.html /library/std/uni/inversion_list.op_binary.html +/library/std/uni/InversionList.opBinary.opBinary.html /library/std/uni/inversion_list.op_binary.op_binary.html +/library/std/uni/InversionList.opBinaryRight.html /library/std/uni/inversion_list.op_binary_right.html +/library/std/uni/InversionList.opBinaryRight.opBinaryRight.html /library/std/uni/inversion_list.op_binary_right.op_binary_right.html +/library/std/uni/InversionList.opIndex.html /library/std/uni/inversion_list.op_index.html +/library/std/uni/InversionList.opOpAssign.html /library/std/uni/inversion_list.op_op_assign.html +/library/std/uni/InversionList.opOpAssign.opOpAssign.html /library/std/uni/inversion_list.op_op_assign.op_op_assign.html +/library/std/uni/InversionList.opUnary.html /library/std/uni/inversion_list.op_unary.html +/library/std/uni/InversionList.opUnary.opUnary.html /library/std/uni/inversion_list.op_unary.op_unary.html +/library/std/uni/InversionList.this.html /library/std/uni/inversion_list.this.html +/library/std/uni/InversionList.this.this.html /library/std/uni/inversion_list.this.this.html +/library/std/uni/InversionList.toSourceCode.html /library/std/uni/inversion_list.to_source_code.html +/library/std/uni/InversionList.toString.html /library/std/uni/inversion_list.to_string.html +/library/std/uni/isAlpha.html /library/std/uni/is_alpha.html +/library/std/uni/isCodepointSet.html /library/std/uni/is_codepoint_set.html +/library/std/uni/isControl.html /library/std/uni/is_control.html +/library/std/uni/isFormat.html /library/std/uni/is_format.html +/library/std/uni/isGraphical.html /library/std/uni/is_graphical.html +/library/std/uni/isIntegralPair.html /library/std/uni/is_integral_pair.html +/library/std/uni/isLower.html /library/std/uni/is_lower.html +/library/std/uni/isMark.html /library/std/uni/is_mark.html +/library/std/uni/isNonCharacter.html /library/std/uni/is_non_character.html +/library/std/uni/isNumber.html /library/std/uni/is_number.html +/library/std/uni/isPrivateUse.html /library/std/uni/is_private_use.html +/library/std/uni/isPunctuation.html /library/std/uni/is_punctuation.html +/library/std/uni/isSpace.html /library/std/uni/is_space.html +/library/std/uni/isSurrogateHi.html /library/std/uni/is_surrogate_hi.html +/library/std/uni/isSurrogate.html /library/std/uni/is_surrogate.html +/library/std/uni/isSurrogateLo.html /library/std/uni/is_surrogate_lo.html +/library/std/uni/isSymbol.html /library/std/uni/is_symbol.html +/library/std/uni/isUpper.html /library/std/uni/is_upper.html +/library/std/uni/isUtfMatcher.html /library/std/uni/is_utf_matcher.html +/library/std/uni/isWhite.html /library/std/uni/is_white.html +/library/std/uni/lineSep.html /library/std/uni/line_sep.html +/library/std/uni/MatcherConcept.html /library/std/uni/matcher_concept.html +/library/std/uni/MatcherConcept.match.html /library/std/uni/matcher_concept.match.html +/library/std/uni/MatcherConcept.skip.html /library/std/uni/matcher_concept.skip.html +/library/std/uni/MatcherConcept.test.html /library/std/uni/matcher_concept.test.html +/library/std/uni/NFC.html /library/std/uni/nfc.html +/library/std/uni/NFD.html /library/std/uni/nfd.html +/library/std/uni/NFKC.html /library/std/uni/nfkc.html +/library/std/uni/NFKD.html /library/std/uni/nfkd.html +/library/std/uni/NormalizationForm.html /library/std/uni/normalization_form.html +/library/std/uni/paraSep.html /library/std/uni/para_sep.html +/library/std/uni/toDelegate.html /library/std/uni/to_delegate.html +/library/std/uni/toLower.html /library/std/uni/to_lower.html +/library/std/uni/toLowerInPlace.html /library/std/uni/to_lower_in_place.html +/library/std/uni/toTrie.html /library/std/uni/to_trie.html +/library/std/uni/toUpper.html /library/std/uni/to_upper.html +/library/std/uni/toUpperInPlace.html /library/std/uni/to_upper_in_place.html +/library/std/uni/UnicodeDecomposition.Canonical.html /library/std/uni/unicode_decomposition.canonical.html +/library/std/uni/UnicodeDecomposition.Compatibility.html /library/std/uni/unicode_decomposition.compatibility.html +/library/std/uni/UnicodeDecomposition.html /library/std/uni/unicode_decomposition.html +/library/std/uni/unicode.hangulSyllableType.html /library/std/uni/unicode.hangul_syllable_type.html +/library/std/uni/unicode.opCall.html /library/std/uni/unicode.op_call.html +/library/std/uni/unicode.opDispatch.html /library/std/uni/unicode.op_dispatch.html +/library/std/uni/utfMatcher.html /library/std/uni/utf_matcher.html +/library/std/uri/decodeComponent.html /library/std/uri/decode_component.html +/library/std/uri/emailLength.html /library/std/uri/email_length.html +/library/std/uri/encodeComponent.html /library/std/uri/encode_component.html +/library/std/uri/Object.factory.html /library/std/uri/object.factory.html +/library/std/uri/Object.opCmp.html /library/std/uri/object.op_cmp.html +/library/std/uri/Object.opEquals.html /library/std/uri/object.op_equals.html +/library/std/uri/Object.toHash.html /library/std/uri/object.to_hash.html +/library/std/uri/Throwable.file.html /library/std/uri/throwable.file.html +/library/std/uri/Throwable.info.html /library/std/uri/throwable.info.html +/library/std/uri/Throwable.line.html /library/std/uri/throwable.line.html +/library/std/uri/Throwable.msg.html /library/std/uri/throwable.msg.html +/library/std/uri/Throwable.next.html /library/std/uri/throwable.next.html +/library/std/uri/Throwable.toString.html /library/std/uri/throwable.to_string.html +/library/std/uri/URIException.html /library/std/uri/uri_exception.html +/library/std/uri/uriLength.html /library/std/uri/uri_length.html +/library/std/utf/byChar.html /library/std/utf/by_char.html +/library/std/utf/byCodeUnit.html /library/std/utf/by_code_unit.html +/library/std/utf/byDchar.html /library/std/utf/by_dchar.html +/library/std/utf/byWchar.html /library/std/utf/by_wchar.html +/library/std/utf/codeLength.html /library/std/utf/code_length.html +/library/std/utf/decodeFront.html /library/std/utf/decode_front.html +/library/std/utf/isValidDchar.html /library/std/utf/is_valid_dchar.html +/library/std/utf/Object.factory.html /library/std/utf/object.factory.html +/library/std/utf/Object.opCmp.html /library/std/utf/object.op_cmp.html +/library/std/utf/Object.opEquals.html /library/std/utf/object.op_equals.html +/library/std/utf/Object.toHash.html /library/std/utf/object.to_hash.html +/library/std/utf/replacementDchar.html /library/std/utf/replacement_dchar.html +/library/std/utf/strideBack.html /library/std/utf/stride_back.html +/library/std/utf/Throwable.file.html /library/std/utf/throwable.file.html +/library/std/utf/Throwable.info.html /library/std/utf/throwable.info.html +/library/std/utf/Throwable.line.html /library/std/utf/throwable.line.html +/library/std/utf/Throwable.msg.html /library/std/utf/throwable.msg.html +/library/std/utf/Throwable.next.html /library/std/utf/throwable.next.html +/library/std/utf/Throwable.toString.html /library/std/utf/throwable.to_string.html +/library/std/utf/toUCSindex.html /library/std/utf/to_uc_sindex.html +/library/std/utf/toUTF16.html /library/std/utf/to_ut_f16.html +/library/std/utf/toUTF16z.html /library/std/utf/to_ut_f16z.html +/library/std/utf/toUTF32.html /library/std/utf/to_ut_f32.html +/library/std/utf/toUTF8.html /library/std/utf/to_ut_f8.html +/library/std/utf/toUTFindex.html /library/std/utf/to_ut_findex.html +/library/std/utf/toUTFz.html /library/std/utf/to_ut_fz.html +/library/std/utf/toUTFz.toUTFz.html /library/std/utf/to_ut_fz.to_ut_fz.html +/library/std/utf/UTFException.html /library/std/utf/utf_exception.html +/library/std/uuid/dnsNamespace.html /library/std/uuid/dns_namespace.html +/library/std/uuid/md5UUID.html /library/std/uuid/md5_uuid.html +/library/std/uuid/Object.factory.html /library/std/uuid/object.factory.html +/library/std/uuid/Object.opCmp.html /library/std/uuid/object.op_cmp.html +/library/std/uuid/Object.opEquals.html /library/std/uuid/object.op_equals.html +/library/std/uuid/Object.toHash.html /library/std/uuid/object.to_hash.html +/library/std/uuid/oidNamespace.html /library/std/uuid/oid_namespace.html +/library/std/uuid/parseUUID.html /library/std/uuid/parse_uuid.html +/library/std/uuid/randomUUID.html /library/std/uuid/random_uuid.html +/library/std/uuid/sha1UUID.html /library/std/uuid/sha1_uuid.html +/library/std/uuid/Throwable.file.html /library/std/uuid/throwable.file.html +/library/std/uuid/Throwable.info.html /library/std/uuid/throwable.info.html +/library/std/uuid/Throwable.line.html /library/std/uuid/throwable.line.html +/library/std/uuid/Throwable.msg.html /library/std/uuid/throwable.msg.html +/library/std/uuid/Throwable.next.html /library/std/uuid/throwable.next.html +/library/std/uuid/Throwable.toString.html /library/std/uuid/throwable.to_string.html +/library/std/uuid/urlNamespace.html /library/std/uuid/url_namespace.html +/library/std/uuid/UUIDParsingException.html /library/std/uuid/uuid_parsing_exception.html +/library/std/uuid/UUIDParsingException.input.html /library/std/uuid/uuid_parsing_exception.input.html +/library/std/uuid/UUIDParsingException.position.html /library/std/uuid/uuid_parsing_exception.position.html +/library/std/uuid/UUIDParsingException.reason.html /library/std/uuid/uuid_parsing_exception.reason.html +/library/std/uuid/UUIDParsingException.Reason.html /library/std/uuid/uuid_parsing_exception.reason.html +/library/std/uuid/UUIDParsingException.Reason.invalidChar.html /library/std/uuid/uuid_parsing_exception.reason.invalid_char.html +/library/std/uuid/UUIDParsingException.Reason.tooLittle.html /library/std/uuid/uuid_parsing_exception.reason.too_little.html +/library/std/uuid/UUIDParsingException.Reason.tooMuch.html /library/std/uuid/uuid_parsing_exception.reason.too_much.html +/library/std/uuid/uuidRegex.html /library/std/uuid/uuid_regex.html +/library/std/uuid/x500Namespace.html /library/std/uuid/x500_namespace.html +/library/std/variant/Algebraic.html /library/std/variant/algebraic.html +/library/std/variant/maxSize.html /library/std/variant/max_size.html +/library/std/variant/Object.factory.html /library/std/variant/object.factory.html +/library/std/variant/Object.opCmp.html /library/std/variant/object.op_cmp.html +/library/std/variant/Object.opEquals.html /library/std/variant/object.op_equals.html +/library/std/variant/Object.toHash.html /library/std/variant/object.to_hash.html +/library/std/variant/Throwable.file.html /library/std/variant/throwable.file.html +/library/std/variant/Throwable.info.html /library/std/variant/throwable.info.html +/library/std/variant/Throwable.line.html /library/std/variant/throwable.line.html +/library/std/variant/Throwable.msg.html /library/std/variant/throwable.msg.html +/library/std/variant/Throwable.next.html /library/std/variant/throwable.next.html +/library/std/variant/Throwable.toString.html /library/std/variant/throwable.to_string.html +/library/std/variant/tryVisit.html /library/std/variant/try_visit.html +/library/std/variant/tryVisit.tryVisit.html /library/std/variant/try_visit.try_visit.html +/library/std/variant/variantArray.html /library/std/variant/variant_array.html +/library/std/variant/VariantException.html /library/std/variant/variant_exception.html +/library/std/variant/VariantException.source.html /library/std/variant/variant_exception.source.html +/library/std/variant/VariantException.target.html /library/std/variant/variant_exception.target.html +/library/std/variant/Variant.html /library/std/variant/variant.html +/library/std/variant/VariantN.allowed.allowed.html /library/std/variant/variant.allowed.allowed.html +/library/std/variant/VariantN.allowed.html /library/std/variant/variant.allowed.html +/library/std/variant/VariantN.coerce.coerce.html /library/std/variant/variant.coerce.coerce.html +/library/std/variant/VariantN.coerce.html /library/std/variant/variant.coerce.html +/library/std/variant/VariantN.convertsTo.convertsTo.html /library/std/variant/variant.converts_to.converts_to.html +/library/std/variant/VariantN.convertsTo.html /library/std/variant/variant.converts_to.html +/library/std/variant/VariantN.get.get.html /library/std/variant/variant.get.get.html +/library/std/variant/VariantN.get.html /library/std/variant/variant.get.html +/library/std/variant/VariantN.hasValue.html /library/std/variant/variant.has_value.html +/library/std/variant/VariantN.html /library/std/variant/variant.html +/library/std/variant/VariantN.length.html /library/std/variant/variant.length.html +/library/std/variant/VariantN.opAddAssign.html /library/std/variant/variant.op_add_assign.html +/library/std/variant/VariantN.opAddAssign.opAddAssign.html /library/std/variant/variant.op_add_assign.op_add_assign.html +/library/std/variant/VariantN.opAdd.html /library/std/variant/variant.op_add.html +/library/std/variant/VariantN.opAdd.opAdd.html /library/std/variant/variant.op_add.op_add.html +/library/std/variant/VariantN.opAndAssign.html /library/std/variant/variant.op_and_assign.html +/library/std/variant/VariantN.opAndAssign.opAndAssign.html /library/std/variant/variant.op_and_assign.op_and_assign.html +/library/std/variant/VariantN.opAnd.html /library/std/variant/variant.op_and.html +/library/std/variant/VariantN.opAnd.opAnd.html /library/std/variant/variant.op_and.op_and.html +/library/std/variant/VariantN.opApply.html /library/std/variant/variant.op_apply.html +/library/std/variant/VariantN.opApply.opApply.html /library/std/variant/variant.op_apply.op_apply.html +/library/std/variant/VariantN.opAssign.html /library/std/variant/variant.op_assign.html +/library/std/variant/VariantN.opAssign.opAssign.html /library/std/variant/variant.op_assign.op_assign.html +/library/std/variant/VariantN.opCatAssign.html /library/std/variant/variant.op_cat_assign.html +/library/std/variant/VariantN.opCatAssign.opCatAssign.html /library/std/variant/variant.op_cat_assign.op_cat_assign.html +/library/std/variant/VariantN.opCat.html /library/std/variant/variant.op_cat.html +/library/std/variant/VariantN.opCat.opCat.html /library/std/variant/variant.op_cat.op_cat.html +/library/std/variant/VariantN.opCmp.html /library/std/variant/variant.op_cmp.html +/library/std/variant/VariantN.opCmp.opCmp.html /library/std/variant/variant.op_cmp.op_cmp.html +/library/std/variant/VariantN.opDivAssign.html /library/std/variant/variant.op_div_assign.html +/library/std/variant/VariantN.opDivAssign.opDivAssign.html /library/std/variant/variant.op_div_assign.op_div_assign.html +/library/std/variant/VariantN.opDiv.html /library/std/variant/variant.op_div.html +/library/std/variant/VariantN.opDiv.opDiv.html /library/std/variant/variant.op_div.op_div.html +/library/std/variant/VariantN.opEquals.html /library/std/variant/variant.op_equals.html +/library/std/variant/VariantN.opEquals.opEquals.html /library/std/variant/variant.op_equals.op_equals.html +/library/std/variant/VariantN.opIndexAssign.html /library/std/variant/variant.op_index_assign.html +/library/std/variant/VariantN.opIndexAssign.opIndexAssign.html /library/std/variant/variant.op_index_assign.op_index_assign.html +/library/std/variant/VariantN.opIndex.html /library/std/variant/variant.op_index.html +/library/std/variant/VariantN.opIndex.opIndex.html /library/std/variant/variant.op_index.op_index.html +/library/std/variant/VariantN.opModAssign.html /library/std/variant/variant.op_mod_assign.html +/library/std/variant/VariantN.opModAssign.opModAssign.html /library/std/variant/variant.op_mod_assign.op_mod_assign.html +/library/std/variant/VariantN.opMod.html /library/std/variant/variant.op_mod.html +/library/std/variant/VariantN.opMod.opMod.html /library/std/variant/variant.op_mod.op_mod.html +/library/std/variant/VariantN.opMulAssign.html /library/std/variant/variant.op_mul_assign.html +/library/std/variant/VariantN.opMulAssign.opMulAssign.html /library/std/variant/variant.op_mul_assign.op_mul_assign.html +/library/std/variant/VariantN.opMul.html /library/std/variant/variant.op_mul.html +/library/std/variant/VariantN.opMul.opMul.html /library/std/variant/variant.op_mul.op_mul.html +/library/std/variant/VariantN.opOrAssign.html /library/std/variant/variant.op_or_assign.html +/library/std/variant/VariantN.opOrAssign.opOrAssign.html /library/std/variant/variant.op_or_assign.op_or_assign.html +/library/std/variant/VariantN.opOr.html /library/std/variant/variant.op_or.html +/library/std/variant/VariantN.opOr.opOr.html /library/std/variant/variant.op_or.op_or.html +/library/std/variant/VariantN.opShlAssign.html /library/std/variant/variant.op_shl_assign.html +/library/std/variant/VariantN.opShlAssign.opShlAssign.html /library/std/variant/variant.op_shl_assign.op_shl_assign.html +/library/std/variant/VariantN.opShl.html /library/std/variant/variant.op_shl.html +/library/std/variant/VariantN.opShl.opShl.html /library/std/variant/variant.op_shl.op_shl.html +/library/std/variant/VariantN.opShrAssign.html /library/std/variant/variant.op_shr_assign.html +/library/std/variant/VariantN.opShrAssign.opShrAssign.html /library/std/variant/variant.op_shr_assign.op_shr_assign.html +/library/std/variant/VariantN.opShr.html /library/std/variant/variant.op_shr.html +/library/std/variant/VariantN.opShr.opShr.html /library/std/variant/variant.op_shr.op_shr.html +/library/std/variant/VariantN.opSubAssign.html /library/std/variant/variant.op_sub_assign.html +/library/std/variant/VariantN.opSubAssign.opSubAssign.html /library/std/variant/variant.op_sub_assign.op_sub_assign.html +/library/std/variant/VariantN.opSub.html /library/std/variant/variant.op_sub.html +/library/std/variant/VariantN.opSub.opSub.html /library/std/variant/variant.op_sub.op_sub.html +/library/std/variant/VariantN.opUShrAssign.html /library/std/variant/variant.op_u_shr_assign.html +/library/std/variant/VariantN.opUShrAssign.opUShrAssign.html /library/std/variant/variant.op_u_shr_assign.op_u_shr_assign.html +/library/std/variant/VariantN.opUShr.html /library/std/variant/variant.op_u_shr.html +/library/std/variant/VariantN.opUShr.opUShr.html /library/std/variant/variant.op_u_shr.op_u_shr.html +/library/std/variant/VariantN.opXorAssign.html /library/std/variant/variant.op_xor_assign.html +/library/std/variant/VariantN.opXorAssign.opXorAssign.html /library/std/variant/variant.op_xor_assign.op_xor_assign.html +/library/std/variant/VariantN.opXor.html /library/std/variant/variant.op_xor.html +/library/std/variant/VariantN.opXor.opXor.html /library/std/variant/variant.op_xor.op_xor.html +/library/std/variant/VariantN.peek.html /library/std/variant/variant.peek.html +/library/std/variant/VariantN.peek.peek.html /library/std/variant/variant.peek.peek.html +/library/std/variant/VariantN.this.html /library/std/variant/variant.this.html +/library/std/variant/VariantN.this.this.html /library/std/variant/variant.this.this.html +/library/std/variant/VariantN.toHash.html /library/std/variant/variant.to_hash.html +/library/std/variant/VariantN.toString.html /library/std/variant/variant.to_string.html +/library/std/variant/VariantN.type.html /library/std/variant/variant.type.html +/library/std/xml/CDataException.html /library/std/xml/c_data_exception.html +/library/std/xml/CData.html /library/std/xml/c_data.html +/library/std/xml/CData.isEmptyXML.html /library/std/xml/c_data.is_empty_xml.html +/library/std/xml/CData.opCmp.html /library/std/xml/c_data.op_cmp.html +/library/std/xml/CData.opEquals.html /library/std/xml/c_data.op_equals.html +/library/std/xml/CData.this.html /library/std/xml/c_data.this.html +/library/std/xml/CData.toHash.html /library/std/xml/c_data.to_hash.html +/library/std/xml/CData.toString.html /library/std/xml/c_data.to_string.html +/library/std/xml/CheckException.column.html /library/std/xml/check_exception.column.html +/library/std/xml/CheckException.err.html /library/std/xml/check_exception.err.html +/library/std/xml/CheckException.html /library/std/xml/check_exception.html +/library/std/xml/CheckException.line.html /library/std/xml/check_exception.line.html +/library/std/xml/CheckException.msg.html /library/std/xml/check_exception.msg.html +/library/std/xml/CommentException.html /library/std/xml/comment_exception.html +/library/std/xml/Comment.html /library/std/xml/comment.html +/library/std/xml/Comment.isEmptyXML.html /library/std/xml/comment.is_empty_xml.html +/library/std/xml/Comment.opCmp.html /library/std/xml/comment.op_cmp.html +/library/std/xml/Comment.opEquals.html /library/std/xml/comment.op_equals.html +/library/std/xml/Comment.this.html /library/std/xml/comment.this.html +/library/std/xml/Comment.toHash.html /library/std/xml/comment.to_hash.html +/library/std/xml/Comment.toString.html /library/std/xml/comment.to_string.html +/library/std/xml/DecodeException.html /library/std/xml/decode_exception.html +/library/std/xml/DecodeMode.html /library/std/xml/decode_mode.html +/library/std/xml/Document.epilog.html /library/std/xml/document.epilog.html +/library/std/xml/Document.html /library/std/xml/document.html +/library/std/xml/Document.opCmp.html /library/std/xml/document.op_cmp.html +/library/std/xml/Document.opEquals.html /library/std/xml/document.op_equals.html +/library/std/xml/DocumentParser.html /library/std/xml/document_parser.html +/library/std/xml/DocumentParser.this.html /library/std/xml/document_parser.this.html +/library/std/xml/Document.prolog.html /library/std/xml/document.prolog.html +/library/std/xml/Document.this.html /library/std/xml/document.this.html +/library/std/xml/Document.toHash.html /library/std/xml/document.to_hash.html +/library/std/xml/Document.toString.html /library/std/xml/document.to_string.html +/library/std/xml/Element.cdatas.html /library/std/xml/element.cdatas.html +/library/std/xml/Element.comments.html /library/std/xml/element.comments.html +/library/std/xml/Element.elements.html /library/std/xml/element.elements.html +/library/std/xml/Element.html /library/std/xml/element.html +/library/std/xml/Element.items.html /library/std/xml/element.items.html +/library/std/xml/Element.opCatAssign.html /library/std/xml/element.op_cat_assign.html +/library/std/xml/Element.opCmp.html /library/std/xml/element.op_cmp.html +/library/std/xml/Element.opEquals.html /library/std/xml/element.op_equals.html +/library/std/xml/ElementParser.html /library/std/xml/element_parser.html +/library/std/xml/ElementParser.onCData.html /library/std/xml/element_parser.on_c_data.html +/library/std/xml/ElementParser.onComment.html /library/std/xml/element_parser.on_comment.html +/library/std/xml/ElementParser.onEndTag.html /library/std/xml/element_parser.on_end_tag.html +/library/std/xml/ElementParser.onPI.html /library/std/xml/element_parser.on_pi.html +/library/std/xml/ElementParser.onStartTag.html /library/std/xml/element_parser.on_start_tag.html +/library/std/xml/ElementParser.onText.html /library/std/xml/element_parser.on_text.html +/library/std/xml/ElementParser.onTextRaw.html /library/std/xml/element_parser.on_text_raw.html +/library/std/xml/ElementParser.onXI.html /library/std/xml/element_parser.on_xi.html +/library/std/xml/ElementParser.parse.html /library/std/xml/element_parser.parse.html +/library/std/xml/ElementParser.tag.html /library/std/xml/element_parser.tag.html +/library/std/xml/ElementParser.toString.html /library/std/xml/element_parser.to_string.html +/library/std/xml/Element.pis.html /library/std/xml/element.pis.html +/library/std/xml/Element.pretty.html /library/std/xml/element.pretty.html +/library/std/xml/Element.tag.html /library/std/xml/element.tag.html +/library/std/xml/Element.text.html /library/std/xml/element.text.html +/library/std/xml/Element.texts.html /library/std/xml/element.texts.html +/library/std/xml/Element.this.html /library/std/xml/element.this.html +/library/std/xml/Element.toHash.html /library/std/xml/element.to_hash.html +/library/std/xml/Element.toString.html /library/std/xml/element.to_string.html +/library/std/xml/InvalidTypeException.html /library/std/xml/invalid_type_exception.html +/library/std/xml/isBaseChar.html /library/std/xml/is_base_char.html +/library/std/xml/isChar.html /library/std/xml/is_char.html +/library/std/xml/isCombiningChar.html /library/std/xml/is_combining_char.html +/library/std/xml/isDigit.html /library/std/xml/is_digit.html +/library/std/xml/isExtender.html /library/std/xml/is_extender.html +/library/std/xml/isIdeographic.html /library/std/xml/is_ideographic.html +/library/std/xml/isLetter.html /library/std/xml/is_letter.html +/library/std/xml/isSpace.html /library/std/xml/is_space.html +/library/std/xml/Item.html /library/std/xml/item.html +/library/std/xml/Item.isEmptyXML.html /library/std/xml/item.is_empty_xml.html +/library/std/xml/Item.opCmp.html /library/std/xml/item.op_cmp.html +/library/std/xml/Item.opEquals.html /library/std/xml/item.op_equals.html +/library/std/xml/Item.pretty.html /library/std/xml/item.pretty.html +/library/std/xml/Item.toHash.html /library/std/xml/item.to_hash.html +/library/std/xml/Item.toString.html /library/std/xml/item.to_string.html +/library/std/xml/Object.factory.html /library/std/xml/object.factory.html +/library/std/xml/Object.opCmp.html /library/std/xml/object.op_cmp.html +/library/std/xml/Object.opEquals.html /library/std/xml/object.op_equals.html +/library/std/xml/Object.toHash.html /library/std/xml/object.to_hash.html +/library/std/xml/Object.toString.html /library/std/xml/object.to_string.html +/library/std/xml/PIException.html /library/std/xml/pi_exception.html +/library/std/xml/ProcessingInstruction.html /library/std/xml/processing_instruction.html +/library/std/xml/ProcessingInstruction.isEmptyXML.html /library/std/xml/processing_instruction.is_empty_xml.html +/library/std/xml/ProcessingInstruction.opCmp.html /library/std/xml/processing_instruction.op_cmp.html +/library/std/xml/ProcessingInstruction.opEquals.html /library/std/xml/processing_instruction.op_equals.html +/library/std/xml/ProcessingInstruction.this.html /library/std/xml/processing_instruction.this.html +/library/std/xml/ProcessingInstruction.toHash.html /library/std/xml/processing_instruction.to_hash.html +/library/std/xml/ProcessingInstruction.toString.html /library/std/xml/processing_instruction.to_string.html +/library/std/xml/Tag.attr.html /library/std/xml/tag.attr.html +/library/std/xml/TagException.html /library/std/xml/tag_exception.html +/library/std/xml/Tag.html /library/std/xml/tag.html +/library/std/xml/Tag.isEmpty.html /library/std/xml/tag.is_empty.html +/library/std/xml/Tag.isEnd.html /library/std/xml/tag.is_end.html +/library/std/xml/Tag.isStart.html /library/std/xml/tag.is_start.html +/library/std/xml/Tag.name.html /library/std/xml/tag.name.html +/library/std/xml/Tag.opCmp.html /library/std/xml/tag.op_cmp.html +/library/std/xml/Tag.opEquals.html /library/std/xml/tag.op_equals.html +/library/std/xml/Tag.this.html /library/std/xml/tag.this.html +/library/std/xml/Tag.toHash.html /library/std/xml/tag.to_hash.html +/library/std/xml/Tag.toString.html /library/std/xml/tag.to_string.html +/library/std/xml/Tag.type.html /library/std/xml/tag.type.html +/library/std/xml/TagType.html /library/std/xml/tag_type.html +/library/std/xml/TextException.html /library/std/xml/text_exception.html +/library/std/xml/Text.html /library/std/xml/text.html +/library/std/xml/Text.isEmptyXML.html /library/std/xml/text.is_empty_xml.html +/library/std/xml/Text.opCmp.html /library/std/xml/text.op_cmp.html +/library/std/xml/Text.opEquals.html /library/std/xml/text.op_equals.html +/library/std/xml/Text.this.html /library/std/xml/text.this.html +/library/std/xml/Text.toHash.html /library/std/xml/text.to_hash.html +/library/std/xml/Text.toString.html /library/std/xml/text.to_string.html +/library/std/xml/Throwable.file.html /library/std/xml/throwable.file.html +/library/std/xml/Throwable.info.html /library/std/xml/throwable.info.html +/library/std/xml/Throwable.line.html /library/std/xml/throwable.line.html +/library/std/xml/Throwable.msg.html /library/std/xml/throwable.msg.html +/library/std/xml/Throwable.next.html /library/std/xml/throwable.next.html +/library/std/xml/Throwable.toString.html /library/std/xml/throwable.to_string.html +/library/std/xml/XIException.html /library/std/xml/xi_exception.html +/library/std/xml/XMLException.html /library/std/xml/xml_exception.html +/library/std/xml/XMLInstruction.html /library/std/xml/xml_instruction.html +/library/std/xml/XMLInstruction.isEmptyXML.html /library/std/xml/xml_instruction.is_empty_xml.html +/library/std/xml/XMLInstruction.opCmp.html /library/std/xml/xml_instruction.op_cmp.html +/library/std/xml/XMLInstruction.opEquals.html /library/std/xml/xml_instruction.op_equals.html +/library/std/xml/XMLInstruction.this.html /library/std/xml/xml_instruction.this.html +/library/std/xml/XMLInstruction.toHash.html /library/std/xml/xml_instruction.to_hash.html +/library/std/xml/XMLInstruction.toString.html /library/std/xml/xml_instruction.to_string.html +/library/std/zip/ArchiveMember.comment.html /library/std/zip/archive_member.comment.html +/library/std/zip/ArchiveMember.compressedData.html /library/std/zip/archive_member.compressed_data.html +/library/std/zip/ArchiveMember.compressedSize.html /library/std/zip/archive_member.compressed_size.html +/library/std/zip/ArchiveMember.compressionMethod.html /library/std/zip/archive_member.compression_method.html +/library/std/zip/ArchiveMember.crc32.html /library/std/zip/archive_member.crc32.html +/library/std/zip/ArchiveMember.diskNumber.html /library/std/zip/archive_member.disk_number.html +/library/std/zip/ArchiveMember.expandedData.html /library/std/zip/archive_member.expanded_data.html +/library/std/zip/ArchiveMember.expandedSize.html /library/std/zip/archive_member.expanded_size.html +/library/std/zip/ArchiveMember.extractVersion.html /library/std/zip/archive_member.extract_version.html +/library/std/zip/ArchiveMember.extra.html /library/std/zip/archive_member.extra.html +/library/std/zip/ArchiveMember.fileAttributes.html /library/std/zip/archive_member.file_attributes.html +/library/std/zip/ArchiveMember.flags.html /library/std/zip/archive_member.flags.html +/library/std/zip/ArchiveMember.html /library/std/zip/archive_member.html +/library/std/zip/ArchiveMember.internalAttributes.html /library/std/zip/archive_member.internal_attributes.html +/library/std/zip/ArchiveMember.name.html /library/std/zip/archive_member.name.html +/library/std/zip/ArchiveMember.time.html /library/std/zip/archive_member.time.html +/library/std/zip/CompressionMethod.deflate.html /library/std/zip/compression_method.deflate.html +/library/std/zip/CompressionMethod.html /library/std/zip/compression_method.html +/library/std/zip/CompressionMethod.none.html /library/std/zip/compression_method.none.html +/library/std/zip/Object.factory.html /library/std/zip/object.factory.html +/library/std/zip/Object.opCmp.html /library/std/zip/object.op_cmp.html +/library/std/zip/Object.opEquals.html /library/std/zip/object.op_equals.html +/library/std/zip/Object.toHash.html /library/std/zip/object.to_hash.html +/library/std/zip/Object.toString.html /library/std/zip/object.to_string.html +/library/std/zip/Throwable.file.html /library/std/zip/throwable.file.html +/library/std/zip/Throwable.info.html /library/std/zip/throwable.info.html +/library/std/zip/Throwable.line.html /library/std/zip/throwable.line.html +/library/std/zip/Throwable.msg.html /library/std/zip/throwable.msg.html +/library/std/zip/Throwable.next.html /library/std/zip/throwable.next.html +/library/std/zip/Throwable.toString.html /library/std/zip/throwable.to_string.html +/library/std/zip/ZipArchive.addMember.html /library/std/zip/zip_archive.add_member.html +/library/std/zip/ZipArchive.build.html /library/std/zip/zip_archive.build.html +/library/std/zip/ZipArchive.comment.html /library/std/zip/zip_archive.comment.html +/library/std/zip/ZipArchive.data.html /library/std/zip/zip_archive.data.html +/library/std/zip/ZipArchive.deleteMember.html /library/std/zip/zip_archive.delete_member.html +/library/std/zip/ZipArchive.directory.html /library/std/zip/zip_archive.directory.html +/library/std/zip/ZipArchive.diskNumber.html /library/std/zip/zip_archive.disk_number.html +/library/std/zip/ZipArchive.diskStartDir.html /library/std/zip/zip_archive.disk_start_dir.html +/library/std/zip/ZipArchive.expand.html /library/std/zip/zip_archive.expand.html +/library/std/zip/ZipArchive.html /library/std/zip/zip_archive.html +/library/std/zip/ZipArchive.isZip64.html /library/std/zip/zip_archive.is_zip64.html +/library/std/zip/ZipArchive.numEntries.html /library/std/zip/zip_archive.num_entries.html +/library/std/zip/ZipArchive.this.html /library/std/zip/zip_archive.this.html +/library/std/zip/ZipArchive.totalEntries.html /library/std/zip/zip_archive.total_entries.html +/library/std/zip/ZipException.html /library/std/zip/zip_exception.html +/library/std/zlib/Compress.compress.html /library/std/zlib/compress.compress.html +/library/std/zlib/Compress.flush.html /library/std/zlib/compress.flush.html +/library/std/zlib/Compress.html /library/std/zlib/compress.html +/library/std/zlib/Compress.this.html /library/std/zlib/compress.this.html +/library/std/zlib/HeaderFormat.deflate.html /library/std/zlib/header_format.deflate.html +/library/std/zlib/HeaderFormat.determineFromData.html /library/std/zlib/header_format.determine_from_data.html +/library/std/zlib/HeaderFormat.gzip.html /library/std/zlib/header_format.gzip.html +/library/std/zlib/HeaderFormat.html /library/std/zlib/header_format.html +/library/std/zlib/Object.factory.html /library/std/zlib/object.factory.html +/library/std/zlib/Object.opCmp.html /library/std/zlib/object.op_cmp.html +/library/std/zlib/Object.opEquals.html /library/std/zlib/object.op_equals.html +/library/std/zlib/Object.toHash.html /library/std/zlib/object.to_hash.html +/library/std/zlib/Object.toString.html /library/std/zlib/object.to_string.html +/library/std/zlib/Throwable.file.html /library/std/zlib/throwable.file.html +/library/std/zlib/Throwable.info.html /library/std/zlib/throwable.info.html +/library/std/zlib/Throwable.line.html /library/std/zlib/throwable.line.html +/library/std/zlib/Throwable.msg.html /library/std/zlib/throwable.msg.html +/library/std/zlib/Throwable.next.html /library/std/zlib/throwable.next.html +/library/std/zlib/Throwable.toString.html /library/std/zlib/throwable.to_string.html +/library/std/zlib/UnCompress.flush.html /library/std/zlib/un_compress.flush.html +/library/std/zlib/UnCompress.html /library/std/zlib/un_compress.html +/library/std/zlib/UnCompress.this.html /library/std/zlib/un_compress.this.html +/library/std/zlib/UnCompress.uncompress.html /library/std/zlib/un_compress.uncompress.html +/library/std/zlib/ZlibException.html /library/std/zlib/zlib_exception.html diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..58b64686a1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*.{c,h,d,di,dd,ddoc}] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true +charset = utf-8 diff --git a/.gitignore b/.gitignore index b67a414b94..174e8c106a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,27 @@ -GNUmakefile - -!appendices.html -!articles.html -!dcompiler.html -!howtos.html -!language-reference.html *.html +Thumbs.db + # CHM -chm +/chm *.chm -*.hhk -*.hhc -*.hhp *.exe *.obj +/chmgen +*.o + +images/*.pdf + +/web + +.dub/ +dpl-docs/dpl-docs + +/chm-nav*.json +/d-*.tag +/d-tags-*.json +/.generated + +# Generated changelogs +changelog/*_pre.dd +changelog/pending.dd diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000000..23cd2d1974 --- /dev/null +++ b/.htaccess @@ -0,0 +1,240 @@ +# dlang.org .htaccess file (local Apache configuration) + +# Enable mod_rewrite +RewriteEngine On + +# Indicate that this directory maps to the root +# directory of the domain. +RewriteBase / + +# Phobos rewrites: + +# Package files are now generated to std_foo.html +# instead of std_foo_package.html. This change was +# done to preserve the links to std.algorithm, +# std.range etc. after they were split into packages. +# However, we need redirects for packages in +# previous stable releases (namely, std.container). + +RewriteRule ^(phobos(-prerelease)?/std_container)_package\.html $1.html [R=301,L] + +Redirect 301 /appendices.html https://dlang.org/dstyle.html +Redirect 301 /COM.html http://wiki.dlang.org/COM_Programming +Redirect 301 /dll.html http://wiki.dlang.org/Win32_DLLs_in_D +Redirect 301 /how-tos.html https://wiki.dlang.org/Tutorials +Redirect 301 /htomodule.html http://wiki.dlang.org/Converting_C_.h_Files_to_D_Modules +Redirect 301 /language-reference.html https://dlang.org/spec/spec.html +Redirect 301 /memory.html http://wiki.dlang.org/Memory_Management +Redirect 301 /windows.html http://wiki.dlang.org/D_for_Win32 +Redirect 301 /getstarted.html http://wiki.dlang.org/Getting_Started +Redirect 301 /tools.html http://wiki.dlang.org/Development_tools + +Redirect 301 /bugstats.php /bugstats.html +Redirect 301 /bugstats.php.html /bugstats.html + +RewriteRule ^changelog(.html)?$ changelog/index.html [R=301,L] + +# OS detection for CLI manual +RewriteCond %{HTTP_USER_AGENT} Windows +RewriteRule ^dmd.html dmd-windows.html [R] + +RewriteCond %{HTTP_USER_AGENT} Mac +RewriteRule ^dmd.html dmd-osx.html [R] + +RewriteCond %{HTTP_USER_AGENT} Linux +RewriteRule ^dmd.html dmd-linux.html [R] + +RewriteCond %{HTTP_USER_AGENT} FreeBSD +RewriteRule ^dmd.html dmd-freebsd.html [R] + +# soft-fail to windows +RewriteRule ^dmd.html dmd-windows.html [L,R] + +# legacy URLs of /spec/ pages +RewriteRule ^(spec|intro|lex|grammar|module|declaration|type|property|\ +attribute|pragma|expression|statement|arrays|hash-map|struct|class|interface|\ +enum|const3|function|operatoroverloading|template|template-mixin|contracts|\ +version|traits|errors|unittest|garbage|float|iasm|ddoc|interfaceToC|\ +cpp_interface|objc_interface|portability|entity|memory-safe-d|abi|simd|\ +glossary)\ +(\.html)?$ \ +spec/$1.html [R=301,L] + +# Foundation pages +Redirect 301 /foundation_overview.html https://dlang.org/foundation/index.html +Redirect 301 /foundation.html https://dlang.org/foundation/about.html +Redirect 301 /contributors.html https://dlang.org/foundation/contributors.html +Redirect 301 /sponsors.html https://dlang.org/foundation/sponsors.html +Redirect 301 /dlangupb-scholarship.html https://dlang.org/foundation/updscholarship.html +Redirect 301 /donate.html https://dlang.org/foundation/donate.html + +# Legacy article pages +Redirect 301 /articles.html /articles/index.html +Redirect 301 /builtin.html /articles/builtin.html +Redirect 301 /code_coverage.html /articles/code_coverage.html +Redirect 301 /concepts.html /articles/constraints.html +Redirect 301 /const-faq.html /articles/const-faq.html +Redirect 301 /cppcontracts.html /articles/cppcontracts.html +Redirect 301 /cpptod.html /articles/cpptod.html +Redirect 301 /ctarguments.html /articles/ctarguments.html +Redirect 301 /ctod.html /articles/ctod.html +Redirect 301 /d-array-article.html /articles/d-array-article.html +Redirect 301 /d-floating-point.html /articles/d-floating-point.html +Redirect 301 /dll-linux.html /articles/dll-linux.html +Redirect 301 /exception-safe.html /articles/exception-safe.html +Redirect 301 /faq.html /articles/faq.html +Redirect 301 /hijack.html /articles/hijack.html +Redirect 301 /intro-to-datetime.html /articles/intro-to-datetime.html +Redirect 301 /lazy-evaluation.html /articles/lazy-evaluation.html +Redirect 301 /migrate-to-shared.html /articles/migrate-to-shared.html +Redirect 301 /mixin.html /articles/mixin.html +Redirect 301 /pretod.html /articles/pretod.html +Redirect 301 /regular-expression.html /articles/regular-expression.html +Redirect 301 /safed.html /articles/safed.html +Redirect 301 /template-comparison.html /articles/template-comparison.html +Redirect 301 /templates-revisited.html /articles/templates-revisited.html +Redirect 301 /variadic-function-templates.html /articles/variadic-function-templates.html +Redirect 301 /warnings.html /articles/warnings.html +Redirect 301 /rationale.html /articles/rationale.html + +# Error pages +ErrorDocument 404 /404.html + +# Permanent links to DIPs +Redirect 301 /dips/1 https://wiki.dlang.org/DIP1 +Redirect 301 /dips/2 https://wiki.dlang.org/DIP2 +Redirect 301 /dips/3 https://wiki.dlang.org/DIP3 +Redirect 301 /dips/4 https://wiki.dlang.org/DIP4 +Redirect 301 /dips/5 https://wiki.dlang.org/DIP5 +Redirect 301 /dips/6 https://wiki.dlang.org/DIP6 +Redirect 301 /dips/7 https://wiki.dlang.org/DIP7 +Redirect 301 /dips/8 https://wiki.dlang.org/DIP8 +Redirect 301 /dips/9 https://wiki.dlang.org/DIP9 +Redirect 301 /dips/10 https://wiki.dlang.org/DIP10 +Redirect 301 /dips/11 https://wiki.dlang.org/DIP11 +Redirect 301 /dips/12 https://wiki.dlang.org/DIP12 +Redirect 301 /dips/13 https://wiki.dlang.org/DIP13 +Redirect 301 /dips/14 https://wiki.dlang.org/DIP14 +Redirect 301 /dips/15 https://wiki.dlang.org/DIP15 +Redirect 301 /dips/16 https://wiki.dlang.org/DIP16 +Redirect 301 /dips/17 https://wiki.dlang.org/DIP17 +Redirect 301 /dips/18 https://wiki.dlang.org/DIP18 +Redirect 301 /dips/19 https://wiki.dlang.org/DIP19 +Redirect 301 /dips/20 https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP20.md +Redirect 301 /dips/21 https://wiki.dlang.org/DIP21 +Redirect 301 /dips/22 https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP22.md +Redirect 301 /dips/23 https://wiki.dlang.org/DIP23 +Redirect 301 /dips/24 https://wiki.dlang.org/DIP24 +Redirect 301 /dips/25 https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md +Redirect 301 /dips/26 https://wiki.dlang.org/DIP26 +Redirect 301 /dips/27 https://wiki.dlang.org/DIP27 +Redirect 301 /dips/28 https://wiki.dlang.org/DIP28 +Redirect 301 /dips/29 https://wiki.dlang.org/DIP29 +Redirect 301 /dips/30 https://wiki.dlang.org/DIP30 +Redirect 301 /dips/31 https://wiki.dlang.org/DIP31 +Redirect 301 /dips/32 https://wiki.dlang.org/DIP32 +Redirect 301 /dips/33 https://wiki.dlang.org/DIP33 +Redirect 301 /dips/34 https://wiki.dlang.org/DIP34 +Redirect 301 /dips/35 https://wiki.dlang.org/DIP35 +Redirect 301 /dips/36 https://wiki.dlang.org/DIP36 +Redirect 301 /dips/37 https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP37.md +Redirect 301 /dips/38 https://wiki.dlang.org/DIP38 +Redirect 301 /dips/39 https://wiki.dlang.org/DIP39 +Redirect 301 /dips/40 https://wiki.dlang.org/DIP40 +Redirect 301 /dips/41 https://wiki.dlang.org/DIP41 +Redirect 301 /dips/42 https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP42.md +Redirect 301 /dips/43 https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP43.md +Redirect 301 /dips/44 https://wiki.dlang.org/DIP44 +Redirect 301 /dips/45 https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP45.md +Redirect 301 /dips/46 https://wiki.dlang.org/DIP46 +Redirect 301 /dips/47 https://wiki.dlang.org/DIP47 +Redirect 301 /dips/48 https://wiki.dlang.org/DIP48 +Redirect 301 /dips/49 https://wiki.dlang.org/DIP49 +Redirect 301 /dips/50 https://wiki.dlang.org/DIP50 +Redirect 301 /dips/51 https://wiki.dlang.org/DIP51 +Redirect 301 /dips/52 https://wiki.dlang.org/DIP52 +Redirect 301 /dips/53 https://wiki.dlang.org/DIP53 +Redirect 301 /dips/54 https://wiki.dlang.org/DIP54 +Redirect 301 /dips/55 https://wiki.dlang.org/DIP55 +Redirect 301 /dips/56 https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP56.md +Redirect 301 /dips/57 https://wiki.dlang.org/DIP57 +Redirect 301 /dips/58 https://wiki.dlang.org/DIP58 +Redirect 301 /dips/59 https://wiki.dlang.org/DIP59 +Redirect 301 /dips/60 https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP60.md +Redirect 301 /dips/61 https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP61.md +Redirect 301 /dips/62 https://wiki.dlang.org/DIP62 +Redirect 301 /dips/63 https://wiki.dlang.org/DIP63 +Redirect 301 /dips/64 https://wiki.dlang.org/DIP64 +Redirect 301 /dips/65 https://wiki.dlang.org/DIP65 +Redirect 301 /dips/66 https://wiki.dlang.org/DIP66 +Redirect 301 /dips/67 https://wiki.dlang.org/DIP67 +Redirect 301 /dips/68 https://wiki.dlang.org/DIP68 +Redirect 301 /dips/69 https://wiki.dlang.org/DIP69 +Redirect 301 /dips/70 https://wiki.dlang.org/DIP70 +Redirect 301 /dips/71 https://wiki.dlang.org/DIP71 +Redirect 301 /dips/72 https://wiki.dlang.org/DIP72 +Redirect 301 /dips/73 https://wiki.dlang.org/DIP73 +Redirect 301 /dips/74 https://wiki.dlang.org/DIP74 +Redirect 301 /dips/75 https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP75.md +Redirect 301 /dips/76 https://wiki.dlang.org/DIP76 +Redirect 301 /dips/77 https://wiki.dlang.org/DIP77 +Redirect 301 /dips/78 https://wiki.dlang.org/DIP78 +Redirect 301 /dips/79 https://wiki.dlang.org/DIP79 +Redirect 301 /dips/80 https://wiki.dlang.org/DIP80 +Redirect 301 /dips/81 https://wiki.dlang.org/DIP81 +Redirect 301 /dips/82 https://wiki.dlang.org/DIP82 +Redirect 301 /dips/83 https://wiki.dlang.org/DIP83 +Redirect 301 /dips/84 https://wiki.dlang.org/DIP84 +Redirect 301 /dips/85 https://wiki.dlang.org/DIP85 +Redirect 301 /dips/86 https://wiki.dlang.org/DIP86 +Redirect 301 /dips/87 https://wiki.dlang.org/DIP87 +Redirect 301 /dips/88 https://wiki.dlang.org/DIP88 +Redirect 301 /dips/89 https://wiki.dlang.org/DIP89 +Redirect 301 /dips/90 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1000.md +Redirect 301 /dips/1000 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1000.md +Redirect 301 /dips/1001 https://github.com/dlang/DIPs/tree/master/DIPs/rejected/DIP1001.md +Redirect 301 /dips/1002 https://github.com/dlang/DIPs/tree/master/DIPs/rejected/DIP1002.md +Redirect 301 /dips/1003 https://github.com/dlang/DIPs/tree/master/DIPs/accepted/DIP1003.md +Redirect 301 /dips/1004 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1004.md +Redirect 301 /dips/1005 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1005.md +Redirect 301 /dips/1006 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1006.md +Redirect 301 /dips/1007 https://github.com/dlang/DIPs/tree/master/DIPs/accepted/DIP1007.md +Redirect 301 /dips/1008 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1008.md +Redirect 301 /dips/1009 https://github.com/dlang/DIPs/tree/master/DIPs/accepted/DIP1009.md +Redirect 301 /dips/1010 https://github.com/dlang/DIPs/tree/master/DIPs/accepted/DIP1010.md +Redirect 301 /dips/1011 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1011.md +Redirect 301 /dips/1012 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1012.md +Redirect 301 /dips/1013 https://github.com/dlang/DIPs/tree/master/DIPs/accepted/DIP1013.md +Redirect 301 /dips/1014 https://github.com/dlang/DIPs/tree/master/DIPs/accepted/DIP1014.md +Redirect 301 /dips/1015 https://github.com/dlang/DIPs/tree/master/DIPs/rejected/DIP1015.md +Redirect 301 /dips/1016 https://github.com/dlang/DIPs/tree/master/DIPs/rejected/DIP1016.md +Redirect 301 /dips/1017 https://github.com/dlang/DIPs/tree/master/DIPs/rejected/DIP1017.md +Redirect 301 /dips/1018 https://github.com/dlang/DIPs/tree/master/DIPs/accepted/DIP1018.md +Redirect 301 /dips/1019 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1019.md +Redirect 301 /dips/1020 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1020.md +Redirect 301 /dips/1021 https://github.com/dlang/DIPs/tree/master/DIPs/accepted/DIP1021.md +Redirect 301 /dips/1022 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1022.md +Redirect 301 /dips/1023 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1023.md +Redirect 301 /dips/1024 https://github.com/dlang/DIPs/tree/master/DIPs/accepted/DIP1024.md +Redirect 301 /dips/1025 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1025.md +Redirect 301 /dips/1026 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1026.md +Redirect 301 /dips/1027 https://github.com/dlang/DIPs/tree/master/DIPs/rejected/DIP1027.md +Redirect 301 /dips/1028 https://github.com/dlang/DIPs/tree/master/DIPs/rejected/DIP1028.md +Redirect 301 /dips/1029 https://github.com/dlang/DIPs/tree/master/DIPs/accepted/DIP1029.md +Redirect 301 /dips/1030 https://github.com/dlang/DIPs/tree/master/DIPs/accepted/DIP1030.md +Redirect 301 /dips/1031 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1031.md +Redirect 301 /dips/1032 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1032.md +Redirect 301 /dips/1033 https://github.com/dlang/DIPs/tree/master/DIPs/other/DIP1033.md +Redirect 301 /dips/1034 https://github.com/dlang/DIPs/tree/master/DIPs/accepted/DIP1034.md +Redirect 301 /dips/1035 https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1035.md +Redirect 301 /dips/1036 https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1036.md +Redirect 301 /dips/1037 https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1037.md +Redirect 301 /dips/1038 https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1038.md +Redirect 301 /dips/1039 https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1039.md +Redirect 301 /dips/1040 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1040.md +Redirect 301 /dips/1041 https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1041.md +Redirect 301 /dips/1042 https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1042.md +Redirect 301 /dips/1043 https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1043.md +Redirect 301 /dips/1044 https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1044.md +Redirect 301 /dips/1045 https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1045.md +Redirect 301 /dips/1046 https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1046.md diff --git a/32-64-portability.dd b/32-64-portability.dd deleted file mode 100644 index 72a322764a..0000000000 --- a/32-64-portability.dd +++ /dev/null @@ -1,131 +0,0 @@ -Ddoc - -$(SPEC_S $(TITLE), - - $(P Although D is designed to make it easy to port code between - 32 and 64 bit modes, being a systems programming language, - dependencies can creep in. This guide points out what changes - between the two. - ) - -$(SECTION2 Versions, - $(P Not all code can be made portable between 32 and 64 bits, - and must be versioned. The following works: - ) - ---- -version (X86) - ... 32 bit code ... -else version (X86_64) - ... 64 bit code ... -else - static assert("unsupported target") ---- - - $(P It is best to write versioning in that manner to give a compile - time error on a new target, rather than guessing in advance what, for example, - a 64 bit ARM target might require. - Experience shows that guesses about how an unfamiliar platform might work - always get it wrong. - Save those decisions for when one is actually working on a 64 bit ARM. - ) -) - -$(SECTION2 Size Changes, - - $(P The size of pointers and references will increase from 4 - to 8 bytes. The $(D size_t) alias moves from $(D uint) to - $(D ulong), and the $(D ptrdiff_t) alias moves from $(D int) - to $(D long). - ) - - $(P The sizes of compound types based on these will also increase. - This includes dynamic arrays, associative arrays, delegates, - and class references. - ) -) - -$(SECTION2 Structs, - - $(P The size of the struct and the alignment of its fields - will change, in order to match the C ABI of the equivalent - C struct. - ) -) - -$(SECTION2 Classes, - - $(P The size of the class and the alignment of its fields - will change, in order to match the alignment most suitable - for the 64 bit mode, and in order to accommodate the increased - size of pointers and references. - ) -) - -$(SECTION2 printf, - - $(P Since $(D printf) is a C function, it follows C typing rules. - This can have consequences for using them with D types. - ) - - $(TABLE1 - $(TR D Type printf format) - $(TR $(TH 32 bit) $(TH 64 bit)) - $(TR $(TD $(I T)*) $(TD %p) $(TD %p)) - $(TR $(TD long) $(TD %lld) $(TD %d)) - $(TR $(TD ulong) $(TD %llu) $(TD %u)) - $(TR $(TD ptrdiff_t) $(TD %td) $(TD %td)) - $(TR $(TD size_t) $(TD %zu) $(TD %zu)) - ) - - $(P For 32 bit code, it was common to use the $(D %.*s) format - to print strings. This relied on the 32 bit C ABI interpreting the - components of a dynamic array as separate length and pointer arguments. - 64 bit parameter passing is different, and so the length and pointer - should be done explicitly: - ) - ---- -string s; -... -printf("s = '%.*s'\n", s); // 32 bit only -printf("s = '%.*s'\n", s.length, s.ptr); // 32 and 64 bit ---- -) - -$(SECTION2 Inline Assembly, - - $(P Naturally, inline assembly for 32 bit code won't work for 64 bit code. - The versioning statements to use are: - ) - ---- -version (D_InlineAsm_X86) - ... 32 bit assembler ... -version (D_InlineAsm_X86_64) - ... 64 bit assembler ... -else - static assert("unsupported target"); ---- - - $(P The 64 bit inline assembler uses the syntax found in the Intel - and AMD instruction set references. - ) -) - -$(SECTION2 Variadic Arguments, - - $(P How variadic arguments work in 64 bits is radically different from - 32 bits. They are not a simple array on the stack. You will need to use - the functions and templates in $(D std.c.stdarg) to access them. - ) - -) - -) - -Macros: - TITLE=Porting 32 Bit Code to 64 Bits - WIKI=32To64 - CATEGORY_HOWTOS=$0 - diff --git a/404.dd b/404.dd new file mode 100644 index 0000000000..99843c1c4a --- /dev/null +++ b/404.dd @@ -0,0 +1,17 @@ +Ddoc + +$(DIV class="center-children", +$(D_S $(TITLE), + +$(HTMLTAG3 img, src="https://github.com/$(STATIC%20images/dman-scared.jpg)") + +$(P +If you think there should be something here, please $(LINK2 $(BUGZILLA_NEW_BUG_URL)$(AMP)label=Severity:normal, report a bug). +))) + +Macros: + TITLE=Oh No! Page Not Found + EXTRA_HEADERS=$(T style, + .center-children, h1 { text-align: center; } + img { max-width: 100%; } + ) diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000000..f282b5b16f --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,24 @@ +# See also: +# - https://github.com/blog/2392-introducing-code-owners +# - https://help.github.com/articles/about-codeowners/ + +# Each line is a file pattern followed by one or more owners (sorted alphabetically). +# Please feel free to add yourself to a module or create a new mapping. +# Ideally each module should have two or more owners. + +# Code owners are automatically requested for review +# when someone opens a pull request that modifies code that they own. +# Later matches take precedence. + +spec/* @andralex @WalterBright @maxhaton @mdparker +foundation.dd @andralex @acehreli @WalterBright + +posix.mak @andralex @CyberShadow @MartinNowak @wilzbach +css/* @CyberShadow @MartinNowak @wilzbach +js/* @CyberShadow @MartinNowak @wilzbach + +assert_writeln_magic.d @wilzbach +orgs-using-d.d @wilzbach +chm* @CyberShadow + +dpl-docs/ @s-ludwig diff --git a/COM.dd b/COM.dd deleted file mode 100644 index 28a8316c1d..0000000000 --- a/COM.dd +++ /dev/null @@ -1,13 +0,0 @@ -Ddoc - -$(SPEC_S COM Programming, - - $(P COM interfaces are all derived from $(D std.c.windows.com.IUnknown). - ) -) - -Macros: - TITLE=COM Programming - WIKI=COM - CATEGORY_HOWTOS=$0 - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..66cc21fc47 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,109 @@ +How to Fork and Build `dlang.org` +-- + +This guide is for Posix users (Unix variants, OSX). + +Make sure you have these prerequisites working: + +* A github account +* The `git` command line utility +* The `make` utility (GNU version) +* The C++ compiler for your platform (invokable as `gcc`) +* Optional: `kindlegen` for building the Kindle documentation + +## Getting the code + +If you already have a [working directory for the D language](https://wiki.dlang.org/Building_under_Posix#Fetch_repositories_from_GitHub), +e.g. `~/dlang`, change to it. + +To get the code, run: + +``` +git clone https://github.com/dlang/dlang.org +cd dlang.org +``` + +The remainder of this document assumes that is your current working directory. + +## Building the main site + +To build the main site, run: + +``` +make -f posix.mak html +``` + +This builds the `dmd` compiler itself first and then uses it to build the +website pages. You may see warnings while the compiler is built. After `make` +ends with error code 0, directory `web` should contain the produced HTML +files. Take a moment to open `web/index.html` in a browser. + +## Building the standard library documentation + +Now that the main site is in place, the standard library documentation would be +a good next step. + +There is a small complicating factor: the standard library has two versions to +build. One is the "release" version, i.e. the library for the currently released +version of D. The other is the "prerelease" version, i.e. the library that is +currently being worked on. The "release" version is built with the "release" +compiler, and the current version is built with the current compiler (which we +already have from the previous step). + +### Building the `prerelease` libraries + +The more interesting stuff to build is the prerelease libraries because in all +likelihood that's what needs looking at and testing. + +``` +make -f posix.mak docs-prerelease +``` + +If you only want to build a specific part (e.g. Phobos), run: + +``` +make -f posix.mak phobos-prerelease +``` + +(`docs-prerelease` is a shorthand for `dmd-prerelease`, `druntime-prerelease`, `phobos-releas` and `apidocs-prerelease`) + +The output is in `web/phobos-prerelease` and `library-prerelease`. + +### Building the `latest` release libraries + +Fortunately there's no need to fumble with version numbers and git tags etc.; +all is automated. Run this command: + +``` +make -f posix.mak docs-latest +``` + +If you only want to build a specific part (e.g. Phobos), run: + +``` +make -f posix.mak phobos-latest +``` + +(`docs-latest` is a shorthand for `dmd-latest`, `druntime-latest`, `phobos-latest` and `apidocs-latest`) + +These commands tell you the release being built in their first line of output. +Then they proceed and clone the appropriate release for `dmd`, `druntime`, and +`phobos`. After all commands have been executed, the following directories will +be present in `$R`: `dlang.org`, `dmd`, `dmd-2.083.2`, `druntime-2.083.2`, and +`phobos-2.083.2`. Note that the actual release number may not be `2.083.2`, but +should be the same for all three directories. + +The output is in `web/phobos` and `web/library`. + +### Avoid building dmd + +By default, the dlang.org build downloads a stable DMD compiler which is used to build the documentation pages. +If you prefer to use an installed `dmd` binary, set `STABLE_DMD` and `STABLE_DMD_CONF`: + +``` +make -f posix.mak html -j4 STABLE_DMD=dmd STABLE_DMD_CONF=/etc/dmd.conf +``` + +### Learning more about DDoc + +Please see the [Ddoc fundamentals](https://wiki.dlang.org/Contributing_to_dlang.org). diff --git a/D1toD2.dd b/D1toD2.dd deleted file mode 100644 index c84216f33c..0000000000 --- a/D1toD2.dd +++ /dev/null @@ -1,104 +0,0 @@ -Ddoc - -$(D_S $(TITLE), - - $(P There are many changes to the D programming language that affect - migrating source code from D1 to D2. - This is an outline of changes to look for and a guide to how to modify - the code. - See $(LINK2 features2.html, D 2.0 Enhancements) for a complete list - of changes to the language. - ) - - $(P This document is incomplete.) - -$(UL - $(LI Core Language - $(UL - $(ITEMR new_keywords, New Keywords) - $(ITEMR global_variables, Global Variables) - $(ITEMR static_arrays, Static Arrays are now Value Types) - $(ITEMR immutable_string, String Literals are Immutable) - ) - ) - - $(LI Phobos Library - $(UL - ) - ) -) - -$(ITEM new_keywords, New Keywords) - - $(P D2 adds the following keywords: - $(D_KEYWORD pure), - $(D_KEYWORD nothrow), - $(D_KEYWORD shared), and - $(D_KEYWORD immutable). - Any use of them in D1 code must be renamed. - Any variable names starting with two underscores - should be renamed. - ) - -$(ITEM global_variables, Global Variables) - - $(P Global variables are now, by default, stored in thread local - storage. To put them back in global storage, use the $(D_KEYWORD __gshared) - storage class:) - ---- -int foo = 7; // D1 code -$(B __gshared) int foo = 7; // D2 equivalent ---- - - $(P Carefully consider whether or not those variables actually should - go into thread local storage, rather than being implicitly shared - among all threads. - ) - -$(ITEM static_arrays, Static Arrays are now Value Types) - - $(P In D1, a static array function parameter is passed by - reference, meaning a pointer to the start of the static array - is passed as an argument. - This means that any changes to the array contents made by the - function will be visible to the function's caller. - In D2, a copy of the whole static - array is passed as an argument. Changes to the array contents by - the function are not visible to the function's caller, as it is - a separate copy.) - - $(P To migrate, add the keyword $(D_KEYWORD ref) to the parameter - declaration:) - ---- -void foo(int[3] array); // D1 code -void foo($(B ref) int[3] array); // D2 equivalent ---- - -$(ITEM immutable_string, String Literals are Immutable) - - $(P String literals in D1 have type $(D char[]), but in D2 they - have type $(D immutable(char)[]), which is aliased for convenience - under the name $(D string). To migrate usually involves doing a - global search replace: ) - - $(TABLE1 - $(TR $(TH from)$(TH to)) - $(TR $(TD char[])$(TD string)) - $(TR $(TD wchar[])$(TD wstring)) - $(TR $(TD dchar[])$(TD dstring)) - ) - - $(P This will take care of most of the issues. - For the rest, where mutable strings are desired, there will - be some work necessary. - ) - -) - -Macros: - TITLE=Migrating D1 Code to D2 - WIKI=D1toD2 - ITEMR=$(LI $(LINK2 #$1, $+)) - ITEM=

$+

diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000000..36b7cd93cd --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..7b558491ea --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +![D Logo](https://dlang.org/images/dlogo.svg) D Language Website +=============================================================== + +[![GitHub tag](https://img.shields.io/github/tag/dlang/dlang.org.svg?maxAge=86400)](https://github.com/dlang/dlang.org/releases) +[![Bugzilla Issues](https://img.shields.io/badge/issues-Bugzilla-green.svg)](https://issues.dlang.org/buglist.cgi?component=dlang.org&list_id=220150&product=D&resolution=---) +[![license](https://img.shields.io/github/license/dlang/dlang.org.svg)](https://github.com/dlang/dlang.org/blob/master/LICENSE.txt) + +This repository contains the source files for the [D Language +Website](https://dlang.org), including the language specifications, +documentation, and some articles. + +* [Bugzilla bug tracker](https://issues.dlang.org/) +* [Forum](https://forum.dlang.org/) +* [Wiki](https://wiki.dlang.org/) + +If you wish to contribute to the website or language documentation, please see +the [CONTRIBUTING.md file](CONTRIBUTING.md) and [wiki entry](https://wiki.dlang.org/Contributing_to_dlang.org). diff --git a/VERSION b/VERSION new file mode 100644 index 0000000000..93ec7bfe88 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +2.111.0 diff --git a/abi.dd b/abi.dd deleted file mode 100644 index 244fefc2ca..0000000000 --- a/abi.dd +++ /dev/null @@ -1,1083 +0,0 @@ -Ddoc - -$(SPEC_S Application Binary Interface, - - $(P A D implementation that conforms to the D ABI (Application Binary - Interface) - will be able to generate libraries, DLL's, etc., that can interoperate - with - D binaries built by other implementations. - ) - -$(SECTION3 C ABI, - - $(P The C ABI referred to in this specification means the C Application - Binary Interface of the target system. - C and D code should be freely linkable together, in particular, D - code shall have access to the entire C ABI runtime library. - ) -) - -$(SECTION3 Endianness, - - $(P The $(LINK2 http://en.wikipedia.org/wiki/Endianness, endianness) - (byte order) of the layout of the data - will conform to the endianness of the target machine. - The Intel x86 CPUs are $(I little endian) meaning that - the value 0x0A0B0C0D is stored in memory as: - $(CODE 0D 0C 0B 0A). - ) -) - -$(SECTION3 Basic Types, - - $(TABLE1 - $(TROW bool, 8 bit byte with the values 0 for false and 1 for true) - $(TROW byte, 8 bit signed value) - $(TROW ubyte, 8 bit unsigned value) - $(TROW short, 16 bit signed value) - $(TROW ushort, 16 bit unsigned value) - $(TROW int, 32 bit signed value) - $(TROW uint, 32 bit unsigned value) - $(TROW long, 64 bit signed value) - $(TROW ulong, 64 bit unsigned value) - $(TROW cent, 128 bit signed value) - $(TROW ucent, 128 bit unsigned value) - $(TROW float, 32 bit IEEE 754 floating point value) - $(TROW double, 64 bit IEEE 754 floating point value) - $(TROW real, implementation defined floating point value$(COMMA) for x86 it is - 80 bit IEEE 754 extended real) - ) -) - -$(SECTION3 Delegates, - - $(P Delegates are $(I fat pointers) with two parts:) - - $(TABLE2 Delegate Layout, - $(TR $(TH offset) $(TH property) $(TH contents)) - $(TR $(TD 0) $(TD $(CODE .ptr)) $(TD context pointer)) - $(TR $(TD $(I ptrsize)) $(TD $(CODE .funcptr)) $(TD pointer to function)) - ) - - $(P The $(I context pointer) can be a class $(I this) - reference, a struct $(I this) pointer, a pointer to - a closure (nested functions) or a pointer to an enclosing - function's stack frame (nested functions). - ) -) - -$(SECTION3 Structs, - - $(P Conforms to the target's C ABI struct layout.) -) - -$(SECTION3 Classes, - - $(P An object consists of:) - -$(TABLE2 Class Object Layout, -$(TR $(TH size) $(TH property) $(TH contents)) -$(TR $(TD $(I ptrsize)) $(TD $(CODE .__vptr)) $(TD pointer to vtable)) -$(TR $(TD $(I ptrsize)) $(TD $(CODE .__monitor)) $(TD monitor)) -$(TR $(TD ...) $(TD ...) $(TD super's non-static fields and super's interface vptrs, from least to most derived)) -$(TR $(TD ...) $(TD named fields) $(TD non-static fields)) -$(TR $(TD $(I ptrsize)...) $(TD  ) $(TD vptr's for any interfaces implemented by this class in left to right, most to least derived, order)) -) - - $(P The vtable consists of:) - -$(TABLE2 Virtual Function Pointer Table Layout, -$(TR $(TH size) $(TH contents)) -$(TR $(TD $(I ptrsize)) $(TD pointer to instance of $(V1 ClassInfo)$(V2 TypeInfo))) -$(TR $(TD $(I ptrsize)...) $(TD pointers to virtual member functions)) -) - - $(P Casting a class object to an interface consists of adding the offset of - the interface's corresponding vptr to the address of the base of the object. - Casting an interface ptr back to the class type it came from involves getting - the correct offset to subtract from it from the object.Interface entry at vtbl[0]. - Adjustor thunks are created and pointers to them stored in the method entries in the vtbl[] - in order to set the this pointer to the start of the object instance corresponding - to the implementing method. - ) - - $(P An adjustor thunk looks like:) - -$(CCODE - ADD EAX,offset - JMP method -) - - $(P The leftmost side of the inheritance graph of the interfaces all share - their vptrs, this is the single inheritance model. - Every time the inheritance graph forks (for multiple inheritance) a new vptr is created - and stored in the class' instance. - Every time a virtual method is overridden, a new vtbl[] must be created with - the updated method pointers in it. - ) - - $(P The class definition:) - ---------- -class XXXX { - .... -}; ---------- - - $(P Generates the following:) - - $(UL - $(LI An instance of Class called ClassXXXX.) - - $(LI A type called StaticClassXXXX which defines all the static members.) - - $(LI An instance of StaticClassXXXX called StaticXXXX for the static members.) - ) -) - -$(SECTION3 Interfaces, - - $(P An interface is a pointer to a pointer to a vtbl[]. - The vtbl[0] entry is a pointer to the corresponding - instance of the object.Interface class. - The rest of the vtbl[1..$] entries are pointers to the - virtual functions implemented by that interface, in the - order that they were declared. - ) - - $(P A COM interface differs from a regular interface in that - there is no object.Interface entry in vtbl[0]; the entries - vtbl[0..$] are all the virtual function pointers, in the order - that they were declared. - This matches the COM object layout used by Windows. - ) - $(V2 - $(P A C++ interface differs from a regular interface in that - it matches the layout of a C++ class using single inheritance - on the target machine. - ) - ) -) - -$(SECTION3 Arrays, - - $(P A dynamic array consists of:) - -$(TABLE2 Dynamic Array Layout, -$(TR $(TH offset) $(TH property) $(TH contents)) -$(TR $(TD 0) $(TD $(CODE .length)) $(TD array dimension)) -$(TR $(TD $(I size_t)) $(TD $(CODE .ptr)) $(TD pointer to array data)) -) - - $(P A dynamic array is declared as:) - ---------- -type[] array; ---------- - - $(P whereas a static array is declared as:) - ---------- -type[dimension] array; ---------- - - $(P Thus, a static array always has the dimension statically available as part of the type, and - so it is implemented like in C. Static array's and Dynamic arrays can be easily converted back - and forth to each other. - ) -) - -$(SECTION3 Associative Arrays, - - $(P Associative arrays consist of a pointer to an opaque, implementation - defined type. - $(V1 The current implementation is contained in and defined by - $(PHOBOSSRC internal/aaA.d).) - $(V2 The current implementation is contained in and defined by - $(DRUNTIMESRC rt/aaA.d).) - ) -) - -$(SECTION3 Reference Types, - - $(P D has reference types, but they are implicit. For example, classes are always - referred to by reference; this means that class instances can never reside on the stack - or be passed as function parameters. - ) - - $(P When passing a static array to a function, the result, although declared as a static array, will - actually be a reference to a static array. For example: - ) - ---------- -int[3] abc; ---------- - - $(P Passing abc to functions results in these implicit conversions:) - ---------- -void func(int[3] array); // actually -void func(int* p); // abc is converted to a pointer - // to the first element -void func(int[] array); // abc is converted to a dynamic array ---------- -) - - -$(SECTION3 Name Mangling, - - $(P D accomplishes typesafe linking by $(I mangling) a D identifier - to include scope and type information. - ) - -$(GRAMMAR -$(I MangledName): - $(B _D) $(I QualifiedName) $(I Type) - $(B _D) $(I QualifiedName) $(B M) $(I Type) - -$(I QualifiedName): - $(I SymbolName) - $(I SymbolName) $(I QualifiedName) - -$(I SymbolName): - $(I LName) - $(I TemplateInstanceName) -) - - $(P The $(B M) means that the symbol is a function that requires - a $(D this) pointer.) - - $(P Template Instance Names have the types and values of its parameters - encoded into it: - ) - -$(GRAMMAR -$(I TemplateInstanceName): - $(Number) $(B __T) $(I LName) $(I TemplateArgs) $(B Z) - -$(I TemplateArgs): - $(I TemplateArg) - $(I TemplateArg) $(I TemplateArgs) - -$(I TemplateArg): - $(B T) $(I Type) - $(B V) $(I Type) $(I Value) - $(B S) $(I LName) - -$(I Value): - $(B n) - $(I Number) - $(B i) $(I Number) - $(B N) $(I Number) - $(B e) $(I HexFloat) - $(B c) $(I HexFloat) $(B c) $(I HexFloat) - $(B A) $(I Number) $(I Value)... - $(B S) $(I Number) $(I Value)... - -$(I HexFloat): - $(B NAN) - $(B INF) - $(B NINF) - $(B N) $(I HexDigits) $(B P) $(I Exponent) - $(I HexDigits) $(B P) $(I Exponent) - -$(I Exponent): - $(B N) $(I Number) - $(I Number) - -$(I HexDigits): - $(I HexDigit) - $(I HexDigit) $(I HexDigits) - -$(I HexDigit): - $(I Digit) - $(B A) - $(B B) - $(B C) - $(B D) - $(B E) - $(B F) -) - -$(DL - $(DT $(B n)) - $(DD is for $(B null) arguments.) - - $(DT $(I Number)) - $(DD is for positive numeric literals (including - character literals).) - - $(DT $(B N) $(I Number)) - $(DD is for negative numeric literals.) - - $(DT $(B e) $(I HexFloat)) - $(DD is for real and imaginary floating point literals.) - - $(DT $(B c) $(I HexFloat) $(B c) $(I HexFloat)) - $(DD is for complex floating point literals.) - - $(DT $(I Width) $(I Number) $(B _) $(I HexDigits)) - $(DD $(I Width) is whether the characters - are 1 byte ($(B a)), 2 bytes ($(B w)) or 4 bytes ($(B d)) in size. - $(I Number) is the number of characters in the string. - The $(I HexDigits) are the hex data for the string. - ) - - $(DT $(B A) $(I Number) $(I Value)...) - $(DD An array or asssociative array literal. - $(I Number) is the length of the array. - $(I Value) is repeated $(I Number) times for a normal array, - and 2 * $(I Number) times for an associative array. - ) - - $(DT $(B S) $(I Number) $(I Value)...) - $(DD A struct literal. $(I Value) is repeated $(I Number) times. - ) - -) - -$(GRAMMAR -$(I Name): - $(I Namestart) - $(I Namestart) $(I Namechars) - -$(I Namestart): - $(B _) - $(I Alpha) - -$(I Namechar): - $(I Namestart) - $(I Digit) - -$(I Namechars): - $(I Namechar) - $(I Namechar) $(I Namechars) -) - - $(P A $(I Name) is a standard D identifier.) - -$(GRAMMAR -$(I LName): - $(I Number) $(I Name) - -$(I Number): - $(I Digit) - $(I Digit) $(I Number) - -$(I Digit): - $(B 0) - $(B 1) - $(B 2) - $(B 3) - $(B 4) - $(B 5) - $(B 6) - $(B 7) - $(B 8) - $(B 9) -) - - $(P An $(I LName) is a name preceded by a $(I Number) giving - the number of characters in the $(I Name). - ) -) - -$(SECTION3 Type Mangling, - - $(P Types are mangled using a simple linear scheme:) - -$(GRAMMAR -$(I Type): - $(I Shared) - $(I Const) - $(I Immutable) - $(I Wild) - $(I TypeArray) -$(V2 $(I TypeNewArray) -) $(I TypeStaticArray) - $(I TypeAssocArray) - $(I TypePointer) - $(I TypeFunction) - $(I TypeIdent) - $(I TypeClass) - $(I TypeStruct) - $(I TypeEnum) - $(I TypeTypedef) - $(I TypeDelegate) - $(I TypeNone) - $(I TypeVoid) - $(I TypeByte) - $(I TypeUbyte) - $(I TypeShort) - $(I TypeUshort) - $(I TypeInt) - $(I TypeUint) - $(I TypeLong) - $(I TypeUlong) - $(I TypeFloat) - $(I TypeDouble) - $(I TypeReal) - $(I TypeIfloat) - $(I TypeIdouble) - $(I TypeIreal) - $(I TypeCfloat) - $(I TypeCdouble) - $(I TypeCreal) - $(I TypeBool) - $(I TypeChar) - $(I TypeWchar) - $(I TypeDchar) - $(I TypeTuple) - -$(I Shared): - $(B O) $(I Type) - -$(I Const): - $(B x) $(I Type) - -$(I Immutable): - $(B y) $(I Type) - -$(I Wild): - $(B Ng) $(I Type) - -$(I TypeArray): - $(B A) $(I Type) - -$(V2 $(I TypeNewArray): - $(B Ne) $(I Type) -) -$(I TypeStaticArray): - $(B G) $(I Number) $(I Type) - -$(I TypeAssocArray): - $(B H) $(I Type) $(I Type) - -$(I TypePointer): - $(B P) $(I Type) - -$(I TypeFunction): - $(I CallConvention) $(V2 $(I FuncAttrs) )$(I Arguments) $(I ArgClose) $(I Type) - -$(I CallConvention): - $(B F) $(GREEN // D) - $(B U) $(GREEN // C) - $(B W) $(GREEN // Windows) - $(B V) $(GREEN // Pascal) - $(B R) $(GREEN // C++) - -$(V2 $(I FuncAttrs): - $(I FuncAttr) - $(I FuncAttr) $(I FuncAttrs) - -$(I FuncAttr): - $(I empty) - $(I FuncAttrPure) - $(I FuncAttrNothrow) - $(I FuncAttrProperty) - $(I FuncAttrRef) - $(I FuncAttrTrusted) - $(I FuncAttrSafe) - -$(I FuncAttrPure): - $(B Na) - -$(I FuncAttrNothrow): - $(B Nb) - -$(I FuncAttrRef): - $(B Nc) - -$(I FuncAttrProperty): - $(B Nd) - -$(I FuncAttrTrusted): - $(B Ne) - -$(I FuncAttrSafe): - $(B Nf) -) - -$(I Arguments): - $(I Argument) - $(I Argument) $(I Arguments) - -$(I Argument:) -$(V2 - $(I Argument2) - $(B M) $(I Argument2) $(GREEN // scope) - -$(I Argument2:) -) $(I Type) - $(B J) $(I Type) $(GREEN // out) - $(B K) $(I Type) $(GREEN // ref) - $(B L) $(I Type) $(GREEN // lazy) - -$(I ArgClose) - $(B X) $(GREEN // variadic T t...$(RPAREN) style) - $(B Y) $(GREEN // variadic T t,...$(RPAREN) style) - $(B Z) $(GREEN // not variadic) - -$(I TypeIdent): - $(B I) $(I LName) - -$(I TypeClass): - $(B C) $(I LName) - -$(I TypeStruct): - $(B S) $(I LName) - -$(I TypeEnum): - $(B E) $(I LName) - -$(I TypeTypedef): - $(B T) $(I LName) - -$(I TypeDelegate): - $(B D) $(I TypeFunction) - -$(I TypeNone): - $(B n) - -$(I TypeVoid): - $(B v) - -$(I TypeByte): - $(B g) - -$(I TypeUbyte): - $(B h) - -$(I TypeShort): - $(B s) - -$(I TypeUshort): - $(B t) - -$(I TypeInt): - $(B i) - -$(I TypeUint): - $(B k) - -$(I TypeLong): - $(B l) - -$(I TypeUlong): - $(B m) - -$(I TypeFloat): - $(B f) - -$(I TypeDouble): - $(B d) - -$(I TypeReal): - $(B e) - -$(I TypeIfloat): - $(B o) - -$(I TypeIdouble): - $(B p) - -$(I TypeIreal): - $(B j) - -$(I TypeCfloat): - $(B q) - -$(I TypeCdouble): - $(B r) - -$(I TypeCreal): - $(B c) - -$(I TypeBool): - $(B b) - -$(I TypeChar): - $(B a) - -$(I TypeWchar): - $(B u) - -$(I TypeDchar): - $(B w) - -$(I TypeTuple): - $(B B) $(I Number) $(I Arguments) -) -) - -$(SECTION3 Function Calling Conventions, - - $(P The $(D extern (C)) and $(D extern (D)) calling convention matches the C - calling convention - used by the supported C compiler on the host system. - Except that the extern (D) calling convention for Windows x86 is described here. - ) - -$(SECTION4 Register Conventions, - - $(UL - - $(LI EAX, ECX, EDX are scratch registers and can be destroyed - by a function.) - - $(LI EBX, ESI, EDI, EBP must be preserved across function calls.) - - $(LI EFLAGS is assumed destroyed across function calls, except - for the direction flag which must be forward.) - - $(LI The FPU stack must be empty when calling a function.) - - $(LI The FPU control word must be preserved across function calls.) - - $(LI Floating point return values are returned on the FPU stack. - These must be cleaned off by the caller, even if they are not used.) - - ) -) - -$(SECTION4 Return Value, - - $(UL - - $(LI The types bool, byte, ubyte, short, ushort, int, uint, - pointer, Object, and interfaces - are returned in EAX.) - - $(LI long and ulong - are returned in EDX,EAX, where EDX gets the most significant - half.) - - $(LI float, double, real, ifloat, idouble, ireal are returned - in ST0.) - - $(LI cfloat, cdouble, creal are returned in ST1,ST0 where ST1 - is the real part and ST0 is the imaginary part.) - - $(LI Dynamic arrays are returned with the pointer in EDX - and the length in EAX.) - - $(LI Associative arrays are returned in EAX with garbage - returned in EDX. The EDX value will probably be removed in - the future; it's there for backwards compatibility with - an earlier implementation of AA's.) - - $(V2 $(LI References are returned as pointers in EAX.)) - - $(LI Delegates are returned with the pointer to the function - in EDX and the context pointer in EAX.) - - $(LI 1, 2 and 4 byte structs are returned in EAX.) - - $(LI 8 byte structs are returned in EDX,EAX, where - EDX gets the most significant half.) - - $(LI For other struct sizes, - the return value is stored through a hidden pointer passed as - an argument to the function.) - - $(LI Constructors return the this pointer in EAX.) - - ) -) - -$(SECTION4 Parameters, - - $(P The parameters to the non-variadic function:) - ---- - foo(a1, a2, ..., an); ---- - - $(P are passed as follows:) - - $(TABLE - $(TR $(TD a1)) - $(TR $(TD a2)) - $(TR $(TD ...)) - $(TR $(TD an)) - $(TR $(TD hidden)) - $(TR $(TD this)) - ) - - $(P where $(I hidden) is present if needed to return a struct - value, and $(I this) is present if needed as the this pointer - for a member function or the context pointer for a nested - function.) - - $(P The last parameter is passed in EAX rather than being pushed - on the stack if the following conditions are met:) - - $(UL - $(LI It fits in EAX.) - $(LI It is not a 3 byte struct.) - $(LI It is not a floating point type.) - ) - - $(P Parameters are always pushed as multiples of 4 bytes, - rounding upwards, - so the stack is always aligned on 4 byte boundaries. - They are pushed most significant first. - $(B out) and $(B ref) are passed as pointers. - Static arrays are passed as pointers to their first element. - On Windows, a real is pushed as a 10 byte quantity, - a creal is pushed as a 20 byte quantity. - On Linux, a real is pushed as a 12 byte quantity, - a creal is pushed as two 12 byte quantities. - The extra two bytes of pad occupy the $(SINGLEQUOTE most significant) position. - ) - - $(P The callee cleans the stack.) - - $(P The parameters to the variadic function:) - ---- - void foo(int p1, int p2, int[] p3...) - foo(a1, a2, ..., an); ---- - - $(P are passed as follows:) - - $(TABLE - $(TR $(TD p1)) - $(TR $(TD p2)) - $(TR $(TD a3)) - $(TR $(TD hidden)) - $(TR $(TD this)) - ) - - $(P The variadic part is converted to a dynamic array and the - rest is the same as for non-variadic functions.) - - $(P The parameters to the variadic function:) - ---- - void foo(int p1, int p2, ...) - foo(a1, a2, a3, ..., an); ---- - - $(P are passed as follows:) - - $(TABLE - $(TR $(TD an)) - $(TR $(TD ...)) - $(TR $(TD a3)) - $(TR $(TD a2)) - $(TR $(TD a1)) - $(TR $(TD _arguments)) - $(TR $(TD hidden)) - $(TR $(TD this)) - ) - - $(P The caller is expected to clean the stack. - $(B _argptr) is not - passed, it is computed by the callee.) -) - -) - -$(SECTION3 Exception Handling, - - $(SECTION4 Windows, - - $(P Conforms to the Microsoft Windows Structured Exception Handling - conventions. - ) - ) - - $(SECTION4 Linux, FreeBSD and OS X, - - $(P Uses static address range/handler tables. - It is not compatible with the ELF/Mach-O exception handling tables. - The stack is walked assuming it uses the EBP/RBP stack frame - convention. The EBP/RBP convention must be used for every - function that has an associated EH (Exception Handler) table. - ) - - $(P For each function that has exception handlers, - an EH table entry is generated. - ) - - $(TABLE2 EH Table Entry, - $(TR $(TH field) $(TH description)) - $(TR $(TD void*) $(TD pointer to start of function)) - $(TR $(TD DHandlerTable*) $(TD pointer to corresponding EH data)) - $(TR $(TD uint) $(TD size in bytes of the function)) - ) - - $(P The EH table entries are placed into the following special - segments, which are concatenated by the linker. - ) - - $(TABLE2 EH Table Segment, - $(TR $(TH Operating System) $(TH Segment Name)) - $(TR $(TD Windows) $(TD FI)) - $(TR $(TD Linux) $(TD .deh_eh)) - $(TROW FreeBSD, .deh_eh) - $(TR $(TD OS X) $(TD __deh_eh, __DATA)) - ) - $(BR) - - $(P The rest of the EH data can be placed anywhere, - it is immutable.) - - $(TABLE2 DHandlerTable, - $(TR $(TH field) $(TH description)) - $(TR $(TD void*) $(TD pointer to start of function)) - $(TR $(TD uint) $(TD offset of ESP/RSP from EBP/RBP)) - $(TR $(TD uint) $(TD offset from start of function to return code)) - $(TR $(TD uint) $(TD number of entries in DHandlerInfo[])) - $(TR $(TD DHandlerInfo[]) $(TD array of handler information)) - ) - $(BR) - - $(TABLE2 DHandlerInfo, - $(TR $(TH field) $(TH description)) - $(TR $(TD uint) $(TD offset from function address to start of guarded section)) - $(TR $(TD uint) $(TD offset of end of guarded section)) - $(TR $(TD int) $(TD previous table index)) - $(TR $(TD uint) $(TD if != 0 offset to DCatchInfo data from start of table)) - $(TR $(TD void*) $(TD if not null, pointer to finally code to execute)) - ) - $(BR) - - $(TABLE2 DCatchInfo, - $(TR $(TH field) $(TH description)) - $(TR $(TD uint) $(TD number of entries in DCatchBlock[])) - $(TR $(TD DCatchBlock[]) $(TD array of catch information)) - ) - $(BR) - - $(TABLE2 DCatchBlock, - $(TR $(TH field) $(TH description)) - $(TR $(TD ClassInfo) $(TD catch type)) - $(TR $(TD uint) $(TD offset from EBP/RBP to catch variable)) - $(TR $(TD void*) $(TD catch handler code)) - ) - ) -) - -$(SECTION3 Garbage Collection, - - $(P The interface to this is found in $(D phobos/internal/gc).) -) - -$(SECTION3 Runtime Helper Functions, - - $(P These are found in $(D phobos/internal).) -) - -$(SECTION3 Module Initialization and Termination, - - $(P All the static constructors for a module are aggregated into a - single function, and a pointer to that function is inserted - into the ctor member of the ModuleInfo instance for that - module. - ) - - $(P All the static denstructors for a module are aggregated into a - single function, and a pointer to that function is inserted - into the dtor member of the ModuleInfo instance for that - module. - ) -) - -$(SECTION3 Unit Testing, - - $(P All the unit tests for a module are aggregated into a - single function, and a pointer to that function is inserted - into the unitTest member of the ModuleInfo instance for that - module. - ) -) - -$(SECTION2 Symbolic Debugging, - - $(P D has types that are not represented in existing C or C++ debuggers. - These are dynamic arrays, associative arrays, and delegates. - Representing these types as structs causes problems because function - calling conventions for structs are often different than that for - these types, which causes C/C++ debuggers to misrepresent things. - For these debuggers, they are represented as a C type which - does match the calling conventions for the type. - The $(B dmd) compiler will generate only C symbolic type info with the - $(B -gc) compiler switch. - ) - - $(TABLE2 Types for C Debuggers, - $(TR - $(TH D type) - $(TH C representation) - ) - $(TR - $(TD dynamic array) - $(TD unsigned long long) - ) - $(TR - $(TD associative array) - $(TD void*) - ) - $(TR - $(TD delegate) - $(TD long long) - ) - $(TR - $(TD dchar) - $(TD unsigned long) - ) - ) - - $(P For debuggers that can be modified to accept new types, the - following extensions help them fully support the types. - ) - -$(SECTION3 Codeview Debugger Extensions, - - $(P The D $(B dchar) type is represented by the special - primitive type 0x78.) - - $(P D makes use of the Codeview OEM generic type record - indicated by $(B LF_OEM) (0x0015). The format is:) - - $(TABLE2 Codeview OEM Extensions for D, - $(TR - $(TD field size) - $(TD 2) - $(TD 2) - $(TD 2) - $(TD 2) - $(TD 2) - $(TD 2) - ) - $(TR - $(TH D Type) - $(TH Leaf Index) - $(TH OEM Identifier) - $(TH recOEM) - $(TH num indices) - $(TH type index) - $(TH type index) - ) - $(TR - $(TD dynamic array) - $(TD LF_OEM) - $(TD $(I OEM)) - $(TD 1) - $(TD 2) - $(TD @$(I index)) - $(TD @$(I element)) - ) - $(TR - $(TD associative array) - $(TD LF_OEM) - $(TD $(I OEM)) - $(TD 2) - $(TD 2) - $(TD @$(I key)) - $(TD @$(I element)) - ) - $(TR - $(TD delegate) - $(TD LF_OEM) - $(TD $(I OEM)) - $(TD 3) - $(TD 2) - $(TD @$(I this)) - $(TD @$(I function)) - ) - ) - - $(P Where:) - - $(TABLE - $(TR - $(TD $(I OEM)) - $(TD 0x42) - ) - $(TR - $(TD $(I index)) - $(TD type index of array index) - ) - $(TR - $(TD $(I key)) - $(TD type index of key) - ) - $(TR - $(TD $(I element)) - $(TD type index of array element) - ) - $(TR - $(TD $(I this)) - $(TD type index of context pointer) - ) - $(TR - $(TD $(I function)) - $(TD type index of function) - ) - ) - - $(P These extensions can be pretty-printed - by $(LINK2 http://www.digitalmars.com/ctg/obj2asm.html, obj2asm). - - $(P The $(LINK2 http://ddbg.mainia.de/releases.html, Ddbg) debugger - supports them.) - ) -) - -$(SECTION3 $(LNAME2 dwarf, Dwarf Debugger Extensions), - $(P The following leaf types are added:) - - $(TABLE2 Dwarf Extensions for D, - $(TR - $(TH D type) - $(TH Identifier) - $(TH Value) - $(TH Format) - ) - $(TR - $(TD dynamic array) - $(TD DW_TAG_darray_type) - $(TD 0x41) - $(TD DW_AT_type is element type) - ) - $(TR - $(TD associative array) - $(TD DW_TAG_aarray_type) - $(TD 0x42) - $(TD DW_AT_type, is element type, DW_AT_containing_type key type) - ) - $(TR - $(TD delegate) - $(TD DW_TAG_delegate_type) - $(TD 0x43) - $(TD DW_AT_type, is function type, DW_AT_containing_type is $(SINGLEQUOTE this) type) - ) - ) - - $(P These extensions can be pretty-printed - by $(LINK2 http://www.digitalmars.com/ctg/dumpobj.html, dumpobj). - - $(P The $(LINK2 http://www.zerobugs.org/, ZeroBUGS) - debugger supports them.) - ) - - $(P Note that these Dwarf extensions have been removed as they conflict with - recent gcc additions. - ) -) - - -) - -) - -Macros: - TITLE=Application Binary Interface - WIKI=ABI - CATEGORY_SPEC=$0 - diff --git a/acknowledgements.dd b/acknowledgements.dd index 452698a52e..dabe9baaa6 100644 --- a/acknowledgements.dd +++ b/acknowledgements.dd @@ -10,44 +10,43 @@ and moral support. ) $(P - $(LINK2 http://erdani.org/, Andrei Alexandrescu), - Kris Bell, - Don Clugston, - Hauke Duden, - Bruce Eckel, - Eric Engstrom, - Dave Fladebo, - David Friedman, - Stewart Gordon, + $(LINK2 http://erdani.org/, Andrei Alexandrescu), + Kris Bell, + Don Clugston, + Hauke Duden, + Bruce Eckel, + Eric Engstrom, + Dave Fladebo, + David Friedman, + Stewart Gordon, Kenji Hara, - Christian Hartung, - David Held, - Ben Hinkle, - Kazuhiro Inaba, - $(LINK2 http://www.janknepper.com, Jan Knepper), - Thomas Kuehne, - Helmut Leitner, - Lubomir Litchev, - $(LINK2 http://www.relisoft.com/, Bartosz Milewski), - Christopher E. Miller, - Pavel Minayev, - Antonio Monteiro, - Paul Nash, - Pat Nelson, - Derek Parnell, - Burton Radons, - Tim Rentsch, - Fabio Riccardi, - Brad Roberts, - Bob Taniguchi, - Bob W, - John Whited, - Matthew Wilson, - Peter Zatloukal + Christian Hartung, + David Held, + Ben Hinkle, + Kazuhiro Inaba, + $(LINK2 http://www.janknepper.com, Jan Knepper), + Thomas Kuehne, + Helmut Leitner, + Lubomir Litchev, + $(LINK2 https://bartoszmilewski.com/, Bartosz Milewski), + Christopher E. Miller, + Pavel Minayev, + Antonio Monteiro, + Paul Nash, + Pat Nelson, + Derek Parnell, + Burton Radons, + Tim Rentsch, + Fabio Riccardi, + Brad Roberts, + Bob Taniguchi, + Bob W, + John Whited, + Matthew Wilson, + Peter Zatloukal ) ) Macros: - TITLE=Acknowledgements - WIKI=Acknowledgements + TITLE=Acknowledgements diff --git a/ads.txt b/ads.txt new file mode 100644 index 0000000000..6282536280 --- /dev/null +++ b/ads.txt @@ -0,0 +1 @@ +google.com, pub-7775438694241734, DIRECT, f08c47fec0942fa0 \ No newline at end of file diff --git a/appendices.html b/appendices.html deleted file mode 100644 index a5c4934187..0000000000 --- a/appendices.html +++ /dev/null @@ -1,9 +0,0 @@ - - - -D Runtime Library - - - - - diff --git a/areas-of-d-usage.dd b/areas-of-d-usage.dd new file mode 100644 index 0000000000..901cc2e657 --- /dev/null +++ b/areas-of-d-usage.dd @@ -0,0 +1,330 @@ +Ddoc + +$(D_S $(TITLE), + +$(DIVC page-contents quickindex, + $(DIVC page-contents-header, + $(H3 Contents) + ) + $(OL + $(LI $(RELATIVE_LINK2 industry, Industry)) $(OL + $(LI $(RELATIVE_LINK2 games, Games)) + $(LI $(RELATIVE_LINK2 web, Web applications)) + $(LI $(RELATIVE_LINK2 gui, GUI applications)) + ) + $(LI $(RELATIVE_LINK2 system-programming, Systems Programming)) $(OL + $(LI $(RELATIVE_LINK2 operating_systems, Operating systems)) + $(LI $(RELATIVE_LINK2 compilers, Compilers)) + $(LI $(RELATIVE_LINK2 embedded, Embedded applications)) + ) + $(LI $(RELATIVE_LINK2 cutting-edge, Cutting edge research)) $(OL + $(LI $(RELATIVE_LINK2 numerical, Numerical computing)) + $(LI $(RELATIVE_LINK2 gpu, GPU programming)) + $(LI $(RELATIVE_LINK2 data_science, Data science)) + ) + $(LI $(RELATIVE_LINK2 academia, Academia)) $(OL + $(LI $(RELATIVE_LINK2 teaching, Teaching)) + ) + ) +) + +$(DIVC start-icons, + $(START_ICONS_ENTRY Industry, industry, industry) + $(START_ICONS_ENTRY Systems Programming, gears, system-programming) + $(START_ICONS_ENTRY Research, flask, cutting-edge) + $(START_ICONS_ENTRY Academia, graduation-cap, academia) +) + +$(DIV, + $(P This list highlights a selection of applications written in D from various areas. + For an overview of D's differentiating features, have a look at the + $(LINK2 $(ROOT_DIR)overview.html, D Overview page). + ) + +) + +$(DIV style="clear:both") + +$(SECTION2 $(LNAME2 industry, Industry), $(SECTION_FA_ICON industry) + +$(DIVC area-section2, + $(P + Companies usually have codebases that are considerably larger than most + hobbyist projects, thus an important goal is to write elegant code + that is easy to understand, and therefore maintain. In comparison to other languages, + D has many features that help keep a codebase clean and + boilerplate-free - thus increasing $(LINK2 $(ROOT_DIR)overview.html#productivity, productivity). + Some examples of simple and yet powerful D features are + $(LINK2 https://dlang.org/spec/template.html, templates) + and $(LINK2 https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax, Uniform + Function Call Syntax). + ) + + $(P $(LINK2 https://dlang.org/spec/function.html#pure-functions, Pure functions), + the memory-safe subset $(LINK2 $(ROOT_DIR)safed.html, SafeD), + $(LINK2 $(ROOT_DIR)spec/unittest.html, special unittest blocks), + $(LINK2 $(ROOT_DIR)spec/contracts.html, contracts) and a sane approach to + $(LINK2 $(ROOT_DIR)spec/errors.html, error handling) aid in + shipping a bug-free product. + If at the end of the day $(LINK2 $(ROOT_DIR)overview.html#performance, performance) + matters $(MDASH) D has you covered! + You can tune your code with tools starting from + $(LINK2 https://dlang.org/spec/version.html, conditional compilation) over + $(LINK2 https://dlang.org/spec/simd.html, SIMD vector optimizations) to + $(LINK2 https://dlang.org/spec/iasm.html, inline assembler), + and $(LINK2 https://wiki.dlang.org/Development_tools#Profiling, many more). + ) + $(P D has been used in numerous diverse domains. A short selection is presented below. + For a complete overview, see the list of + $(LINK2 $(ROOT_DIR)orgs-using-d.html, organizations using the D Language). + ) +) + +$(AREA_SECTION3 $(LNAME2 games, Games), $(ARTICLE_FA_ICON gamepad), + + Binary compatibility with existing libraries is important in large-scale + projects. + Remedy Entertainment has successfully shipped the first $(HTTPS www.remedygames.com/games/quantum-break, + AAA game) to use D code for XBox One and Windows 10. + For more details, see Ethan Watson's + $(HTTP dconf.org/2016/talks/watson.html, presentation). + + Many pure-D open source projects show the rising popularity + of D among game developers. + Examples are the 3D game engine + $(HTTPS github.com/gecko0307/dagon, Dagon) and the cross-platform D game development engine + $(HTTPS github.com/MrcSnm/HipremeEngine, HipremeEngine). +) + +$(AREA_SECTION3 $(LNAME2 web, Web applications), $(ARTICLE_FA_ICON cloud), + + D's ability to combine low and high-level code in one language, asynchronous + features like Fibers, and compile-time function execution, makes it well suited + for high-performance asynchronous I/O, concurrency and web applications. + The $(HTTPS github.com/rejectedsoftware/vibe.d, vibe.d) framework is D's + flagship solution for all needs pertaining to networking and asynchronous + event handling. + + For an example success story, see the DConf presentation + $(HTTPS www.youtube.com/watch?v=qimgioXwLUo, Mobile Game Server Backend in D). +) + +$(AREA_SECTION3 $(LNAME2 gui, GUI Applications), $(ARTICLE_FA_ICON desktop), + + D's high productivity is also beneficial when creating GUI applications. + + Some examples are the Linux tiling terminal emulator + $(HTTP github.com/gnunn1/tilix, tilix), + the D development environment + $(HTTPS github.com/buggins/dlangide, DLangIDE), which is itself based + on the cross-platform D library $(HTTPS github.com/buggins/dlangui, dlangui). + + Thanks to binary compatibility, all existing GUI libraries written in C, C++, + and other languages can be + $(HTTPS wiki.dlang.org/GUI_Libraries, easily accessed). + +)) + +$(SECTION2 $(LNAME2 system-programming, Systems Programming), + +$(AREA_SECTION3 $(LNAME2 compilers, Compilers), $(ARTICLE_FA_ICON code), + + $(P D is used in the reference DMD compiler itself, Facebook's fast C/C++ preprocessor + $(HTTPS github.com/facebookarchive/warp, warp), the $(HTTPS github.com/higgsjs/Higgs, + Higgs JavaScript Virtual Machine), and more. + D's compile time function execution allows generating custom grammar parsers + at compile time - see e.g. $(HTTPS github.com/PhilippeSigaud/Pegged, Pegged) + as an example. + ) +) + +$(AREA_SECTION3 $(LNAME2 operating_systems, Operating systems), $(ARTICLE_FA_ICON linux), + + $(DIV, + D is a systems programming language and is well suited for bare metal + or kernel development. It's easy to write an Operating System in D, and many + project have proven so. To name a few: + + $(UL + $(LI $(HTTPS github.com/Vild/PowerNex, PowerNex) - A kernel written in D) + $(LI $(HTTPS github.com/xomboverlord/xomb/tree/unborn, XOmB) - Exokernel operating system) + $(LI $(HTTPS github.com/Rikarin/Trinix, Trinix) - Hybrid operating system for x64 PC) + ) + ) +) + +$(AREA_SECTION3 $(LNAME2 embedded, Embedded applications), $(ARTICLE_FA_ICON gears), + + Using $(HTTPS github.com/ldc-developers/ldc, LDC) (the LLVM D compiler) + enables targeting most popular CPU architectures, + starting from ARM, RISC-V and MIPS-based embedded systems and smartphones, + ranging to server systems based on POWER and Sparc, and up to the "big iron" z Systems. + +)) + +$(SECTION2 $(LNAME2 cutting-edge, Cutting-edge research), $(SECTION_FA_ICON space-shuttle) + +$(DIVC area-section2, + D is similar to popular scientific languages like Python in that it provides + the conveniences of a modern language with a friendly syntax, and is + garbage collected by default. Convenience features allow spending time on rapid prototyping, + rather than fighting memory issues that few scientific programmers need to worry about. + However, it is also a compiled, statically typed language that can produce code as fast as C, + allows easily parallelizing algorithms and pipelines, + and, as a system language, provides complete control (including manual memory management) + to get those last few extra cycles. + + A few specific spotlights: +) + +$(AREA_SECTION3 $(LNAME2 numerical, Numerical computing), $(ARTICLE_FA_ICON calculator), + + Like NumPy, D is convenient and offers the ability to bind to existing C libraries. + Unlike NumPy, D does not become slow for computations not covered by preexisting libraries, + and does not force its user to escape into another language. + Additionally, due to its compile-time introspection capabilities, D enables + further optimizations for superior performance. See Andrei's talk + $(HTTPS www.youtube.com/watch?v=AxnotgLql0k, Fastware) on this topic. + There is excellent support for multidimensional arrays with third-party libraries + such as $(HTTPS github.com/libmir/mir-algorithm, mir). +) + +$(AREA_SECTION3 $(LNAME2 gpu, GPU Programming), $(ARTICLE_FA_ICON flash), + + For most programmers used to developing for a modern CPU, + working with GPUs for general purpose computation can appear daunting and laborious. + Even seasoned users will admit that the performance improvements are often not worth the extra effort. + + Thanks to the power of D’s type system and static introspection, + $(HTTP dconf.org/2016/talks/colvin.html, GPU Programming) is + safer and easier to use than traditional APIs with no compromise in performance. + +) + +$(AREA_SECTION3 $(LNAME2 data_science, Data science), $(ARTICLE_FA_ICON area-chart), + + D's high-level abstraction and fast execution make it well-suited for scientific + analysis. For example, $(LINK2 http://ddili.org/ders/d.en/ranges.html, D's ranges) + are a natural fit for pipes and data streams. + One can start from a small D script with a small subset of data for + an analysis, and easily switch to the full set by enabling optimizations + for superior performance. + Read Adroll's testimonial + $(HTTP tech.adroll.com/blog/data/2014/11/17/d-is-for-data-science.html, "D is for Data Science") + on why D is a keystone language for their critical infrastructure. + eBay recently open-sourced their internal $(HTTPS github.com/eBay/tsv-utils, data processing utilities) + used in their large-scale data mining environment. +)) + +$(SECTION2 $(LNAME2 academia, Academia), + +$(AREA_SECTION3 $(LNAME2 teaching, Teaching), $(ARTICLE_FA_ICON graduation-cap), + + $(P D's multi-paradigm (imperative, structured, object oriented, generic, functional programming + purity, and even assembly) approach allows teaching in one language and gradually + explaining new features without needing to switch to a different language. + ) + $(P At universities, interpreted languages are commonly taught because of their memory safety. + $(LINK2 $(ROOT_DIR)safed.html, SafeD), a memory-safe subset of D, provides + safety and ease of use comparable to interpreted and JIT-compiled languages + while retaining the efficiency of native code. + Beginners will also benefit from garbage collection, which helps + write simple code without requiring any knowledge of explicit memory management. + $(LINK2 $(ROOT_DIR)phobos/std_experimental_allocator.html, More sophisticated memory management) can be introduced in an advanced + learning stage. + ) + $(P D's blazingly fast compilation allows it to be used as a high level, + productive scripting language, but with the + advantages of $(I static) type checking. + ) + $(P Last but not least, there are $(LINK2 http://ddili.org/ders/d.en/index.html, + books) and $(LINK2 https://tour.dlang.org/, tutorials) freely available online + which can be used as resources. + ) +)) + +) + +Macros: + TITLE=Areas of D usage + ARTICLE_FA_ICON= + SECTION_FA_ICON= + START_ICONS_ENTRY=$(DIVC start-icons-el, $(LINK2 #$3, )$(DIV, $1)) + AREA_SECTION_INLINE=$1 $(DIVC area-section3, $+) + AREA_SECTION3=$(TC h3, area-section3, $1) $(AREA_SECTION_INLINE $+) + COLON=: + _= Single word inline CSS needs to be escaped _= + EXTRA_HEADERS=$(T style, + .start-icons { + text-align: center; + padding-bottom: 30px; + padding-top: 20px; + } + .start-icons-el > div { + hyphens: none; + margin: 0 -1em; + text-align: center; + } + .start-icons-el { + vertical-align: top; + display: inline-block; + padding-right: 5%; + padding-bottom: 20px; + font-size: 1.2em; + width: 100px; + } + .start-icons i { + font-size: 80px; + padding-bottom: 10px; + } + h2 { + padding-top: 1.0em; + } + h2 a$(COLON)hover$(COLON)$(COLON)after { + content: '' !important; + } + @media only screen and (min-width: 50em) + { + .area-section3, .area-section2 { + padding-left: 120px; + } + } + .fa.article-icon, .fa.section-icon { + float: left; + padding-right: 15px; + font-size: 80px; + width: 100px; + text-align: center; + padding-bottom: 15px; + } + @media only screen and (max-width: 50em) + { + .fa.article-icon, .fa-section-icon { + font-size: 60px; + width: 80px; + } + #dman { + height: 200px; + } + } + @media only screen and (max-width: 30em) { + .page-contents { + width: 80%; + margin: 0 auto; + margin-bottom: 1em; + } + } + @media only screen and (min-width: 30em) { + #dman { + margin-top: -80px; + } + } + @media only screen and (min-width: 45em) { + #dman { + margin-top: -200px; + } + } + h2 { + text-align: center; + } + ) diff --git a/arrays.dd b/arrays.dd deleted file mode 100644 index 5d2a639788..0000000000 --- a/arrays.dd +++ /dev/null @@ -1,1095 +0,0 @@ -Ddoc - -$(SPEC_S Arrays, - - $(P There are four kinds of arrays:) - - $(TABLE2 Kinds of Arrays, - $(TR $(TH Syntax) $(TH Description)) - $(TR $(TD $(I type)*) $(TD $(LINK2 #pointers, Pointers to data))) - - $(TR $(TD $(I type)[$(I integer)]) $(TD $(LINK2 #static-arrays, Static arrays))) - - $(TR $(TD $(I type)[]) $(TD $(LINK2 #dynamic-arrays, Dynamic arrays))) - - $(TR $(TD $(I type)[$(I type)]) $(TD $(DDLINK hash-map, Associative Arrays, Associative arrays))) - ) - -

$(LNAME2 pointers, Pointers)

- ---------- -int* p; ---------- - - $(P These are simple pointers to data, analogous to C pointers. - Pointers are provided for interfacing with C and for - specialized systems work. - There - is no length associated with it, and so there is no way for the - compiler or runtime to do bounds checking, etc., on it. - Most conventional uses for pointers can be replaced with - dynamic arrays, $(D out) and $(D ref) parameters, - and reference types. - ) - -

$(LNAME2 static-arrays, Static Arrays)

- ---------- -int[3] s; ---------- - - $(P These are analogous to C arrays. Static arrays are distinguished - by having a length fixed at compile time. - ) - - $(P The total size of a static array cannot exceed 16Mb. - A dynamic array should be used instead for such large arrays. - ) - - $(P A static array with a dimension of 0 is allowed, but no - space is allocated for it. It's useful as the last member - of a variable length struct, or as the degenerate case of - a template expansion. - ) - -$(V1 - $(P Static arrays are value types, but as in C - static arrays are passed to functions by reference - and cannot be returned from functions. - ) -) -$(V2 - $(P Static arrays are value types. Unlike in C and D version 1, - static arrays are passed to functions by value. - Static arrays can also be returned by functions. - ) -) - -

$(LNAME2 dynamic-arrays, Dynamic Arrays)

- ---------- -int[] a; ---------- - - $(P Dynamic arrays consist of a length and a pointer to the array data. - Multiple dynamic arrays can share all or parts of the array data. - ) - -

Array Declarations

- - $(P There are two ways to declare arrays, prefix and postfix. - The prefix form is the preferred method, especially for - non-trivial types. - ) - -

Prefix Array Declarations

- - $(P Prefix declarations appear before the identifier being - declared and read right to left, so: - ) - ---------- -int[] a; // dynamic array of ints -int[4][3] b; // array of 3 arrays of 4 ints each -int[][5] c; // array of 5 dynamic arrays of ints. -int*[]*[3] d; // array of 3 pointers to dynamic arrays of pointers to ints -int[]* e; // pointer to dynamic array of ints ---------- - - -

Postfix Array Declarations

- - $(P Postfix declarations appear after the identifier being - declared and read left to right. - Each group lists equivalent declarations: - ) - ---------- -// dynamic array of ints -int[] a; -int a[]; - -// array of 3 arrays of 4 ints each -int[4][3] b; -int[4] b[3]; -int b[3][4]; - -// array of 5 dynamic arrays of ints. -int[][5] c; -int[] c[5]; -int c[5][]; - -// array of 3 pointers to dynamic arrays of pointers to ints -int*[]*[3] d; -int*[]* d[3]; -int* (*d[3])[]; - -// pointer to dynamic array of ints -int[]* e; -int (*e)[]; ---------- - - $(P $(B Rationale:) The postfix form matches the way arrays are - declared in C and C++, and supporting this form provides an - easy migration path for programmers used to it. - ) - -

$(LNAME2 usage, Usage)

- - $(P There are two broad kinds of operations to do on an array - - affecting - the handle to the array, - and affecting the contents of the array. - C only has - operators to affect the handle. In D, both are accessible. - ) - - $(P The handle to an array is specified by naming the array, as - in p, s or a: - ) - ---------- -int* p; -int[3] s; -int[] a; - -int* q; -int[3] t; -int[] b; - -p = q; // p points to the same thing q does. -p = s.ptr; // p points to the first element of the array s. -p = a.ptr; // p points to the first element of the array a. - -s = ...; // error, since s is a compiled in static - // reference to an array. - -a = p; // error, since the length of the array pointed - // to by p is unknown -a = s; // a is initialized to point to the s array -a = b; // a points to the same array as b does ---------- - -

$(LNAME2 slicing, Slicing)

- - $(P $(I Slicing) an array means to specify a subarray of it. - An array slice does not copy the data, it is only another - reference to it. - For example: - ) - ---------- -int[10] a; // declare array of 10 ints -int[] b; - -b = a[1..3]; // a[1..3] is a 2 element array consisting of - // a[1] and a[2] -foo(b[1]); // equivalent to foo(0) -a[2] = 3; -foo(b[1]); // equivalent to foo(3) ---------- - - $(P The [] is shorthand for a slice of the entire array. - For example, the assignments to b: - ) - ---------- -int[10] a; -int[] b; - -b = a; -b = a[]; -b = a[0 .. a.length]; ---------- - - $(P are all semantically equivalent. - ) - - $(P Slicing - is not only handy for referring to parts of other arrays, - but for converting pointers into bounds-checked arrays: - ) - ---------- -int* p; -int[] b = p[0..8]; ---------- - -

$(LNAME2 array-copying, Array Copying)

- - $(P When the slice operator appears as the lvalue of an assignment - expression, it means that the contents of the array are the - target of the assignment rather than a reference to the array. - Array copying happens when the lvalue is a slice, and the rvalue - is an array of or pointer to the same type. - ) - ---------- -int[3] s; -int[3] t; - -s[] = t; // the 3 elements of t[3] are copied into s[3] -s[] = t[]; // the 3 elements of t[3] are copied into s[3] -s[1..2] = t[0..1]; // same as s[1] = t[0] -s[0..2] = t[1..3]; // same as s[0] = t[1], s[1] = t[2] -s[0..4] = t[0..4]; // error, only 3 elements in s -s[0..2] = t; // error, different lengths for lvalue and rvalue ---------- - - $(P Overlapping copies are an error:) - ---------- -s[0..2] = s[1..3]; // error, overlapping copy -s[1..3] = s[0..2]; // error, overlapping copy ---------- - - $(P Disallowing overlapping makes it possible for more aggressive - parallel code optimizations than possible with the serial - semantics of C. - ) - -

$(LNAME2 array-setting, Array Setting)

- - $(P If a slice operator appears as the lvalue of an assignment - expression, and the type of the rvalue is the same as the element - type of the lvalue, then the lvalue's array contents - are set to the rvalue. - ) - ---------- -int[3] s; -int* p; - -s[] = 3; // same as s[0] = 3, s[1] = 3, s[2] = 3 -p[0..2] = 3; // same as p[0] = 3, p[1] = 3 ---------- - -

$(LNAME2 array-concatenation, Array Concatenation)

- - $(P The binary operator ~ is the $(I cat) operator. It is used - to concatenate arrays: - ) - ---------- -int[] a; -int[] b; -int[] c; - -a = b ~ c; // Create an array from the concatenation - // of the b and c arrays ---------- - - $(P Many languages overload the + operator to mean concatenation. - This confusingly leads to, does: - ) - ---------- -"10" + 3 + 4 ---------- - - $(P produce the number 17, the string "1034" or the string "107" as the - result? It isn't obvious, and the language designers wind up carefully - writing rules to disambiguate it - rules that get incorrectly - implemented, overlooked, forgotten, and ignored. It's much better to - have + mean addition, and a separate operator to be array - concatenation. - ) - - $(P Similarly, the ~= operator means append, as in: - ) - ---------- -a ~= b; // a becomes the concatenation of a and b ---------- - - $(P Concatenation always creates a copy of its operands, even - if one of the operands is a 0 length array, so: - ) - ---------- -a = b; // a refers to b -a = b ~ c[0..0]; // a refers to a copy of b ---------- - - $(P Appending does not always create a copy, see $(LINK2 #resize, - setting dynamic array length) for details. - ) - -

$(LNAME2 array-operations, Array Operations)

- - $(P Many array operations, also known as vector operations, - can be expressed at a high level rather than as a loop. - For example, the loop: - ) - ---- -T[] a, b; -... -for (size_t i = 0; i < a.length; i++) - a[i] = b[i] + 4; ---- - - $(P assigns to the elements of $(CODE a) the elements of $(CODE b) - with $(CODE 4) added to each. This can also be expressed in - vector notation as: - ) - ---- -T[] a, b; -... -a[] = b[] + 4; ---- - - $(P A vector operation is indicated by the slice operator appearing - as the lvalue of an =, +=, -=, *=, /=, %=, ^=, &= or |= operator. - The rvalue can be an expression consisting either of an array - slice of the same length and type as the lvalue or an expression - of the element type of the lvalue, in any combination. - The operators supported for vector operations are the binary - operators +, -, *, /, %, ^, & and |, and the unary operators - - and ~. - ) - - $(P The lvalue slice and any rvalue slices must not overlap. - The vector assignment operators are evaluated right to left, - and the other binary operators are evaluated left to right. - All operands are evaluated exactly once, even if the array slice - has zero elements in it. - ) - - $(P The order in which the array elements are computed - is implementation defined, and may even occur in parallel. - An application must not depend on this order. - ) - - $(P Implementation note: many of the more common vector - operations are expected to take advantage of any vector - math instructions available on the target computer. - ) - -

$(LNAME2 pointer-arithmetic, Pointer Arithmetic)

- ---------- -int[3] abc; // static array of 3 ints -int[] def = [ 1, 2, 3 ]; // dynamic array of 3 ints - -void dibb(int* array) { - array[2]; // means same thing as *(array + 2) - *(array + 2); // get 3rd element -} - -void diss(int[] array) { - array[2]; // ok - *(array + 2); // error, array is not a pointer -} - -void ditt(int[3] array) { - array[2]; // ok - *(array + 2); // error, array is not a pointer -} ---------- - -

$(LNAME2 rectangular-arrays, Rectangular Arrays)

- - $(P Experienced FORTRAN numerics programmers know that multidimensional - "rectangular" arrays for things like matrix operations are much faster than trying to - access them via pointers to pointers resulting from "array of pointers to array" semantics. - For example, the D syntax: - ) - ---------- -double[][] matrix; ---------- - - $(P declares matrix as an array of pointers to arrays. (Dynamic arrays are implemented as - pointers to the array data.) Since the arrays can have varying sizes (being dynamically - sized), this is sometimes called "jagged" arrays. Even worse for optimizing the code, the - array rows can sometimes point to each other! Fortunately, D static arrays, while using - the same syntax, are implemented as a fixed rectangular layout: - ) - ---------- -double[3][3] matrix; ---------- - - $(P declares a rectangular matrix with 3 rows and 3 columns, all contiguously in memory. In - other languages, this would be called a multidimensional array and be declared as: - ) ---------- -double matrix[3,3]; ---------- - -

$(LNAME2 array-length, Array Length)

- -$(V1 - $(P Within the [ ] of a static or a dynamic array, - the variable $(B length) - is implicitly declared and set to the length of the array. - The symbol $(B $) can also be so used. - ) -) -$(V2 - $(P Within the [ ] of a static or a dynamic array, - the symbol $(B $) - represents the length of the array. - ) -) - ---------- -int[4] foo; -int[] bar = foo; -int* p = &foo[0]; - -// These expressions are equivalent: -bar[] -bar[0 .. 4] -$(V1 bar[0 .. $(B length)] -)bar[0 .. $(B $)] -bar[0 .. bar.length] - -$(V1 p[0 .. length] // 'length' is not defined, since p is not an array -bar[0]+length // 'length' is not defined, out of scope of [ ] - -bar[$(B length)-1] // retrieves last element of the array -) -$(V2 p[0 .. $(DOLLAR)] // '$' is not defined, since p is not an array -bar[0]+$(DOLLAR) // '$' is not defined, out of scope of [ ] - -bar[$(B $(DOLLAR))-1] // retrieves last element of the array -) ---------- - -

$(LNAME2 array-properties, Array Properties)

- - $(P Static array properties are:) - - $(TABLE2 Static Array Properties, - $(TR $(TH Property) $(TH Description)) - - $(TR - $(TD $(B .init)) -$(V1 $(TD returns the default initializer for the element type.) -) -$(V2 $(TD Returns an array literal with each element of the literal being the $(B .init) - property of the array element type. -) - ) - ) - - $(TR - $(TD $(B .sizeof)) - $(TD Returns the array length multiplied by the number of - bytes per array element. - ) - ) - - $(TR - $(TD $(B .length)) - $(TD Returns the number of elements in the array. - This is a fixed quantity for static arrays. - It is of type $(B size_t). - ) - ) - - $(TR - $(TD $(B .ptr)) - $(TD Returns a pointer to the first element of the array. - ) - ) - - $(TR - $(TD $(B .dup)) - $(TD Create a dynamic array of the same size - and copy the contents of the array into it. - ) - ) - - $(TR - $(TD $(B .idup)) - $(TD Create a dynamic array of the same size - and copy the contents of the array into it. - The copy is typed as being immutable. - $(I D 2.0 only) - ) - ) - - $(TR - $(TD $(B .reverse)) - $(TD Reverses in place the order of the elements in the array. - Returns the array. - ) - ) - - $(TR - $(TD $(B .sort)) - $(TD Sorts in place the order of the elements in the array. - Returns the array. - ) - ) - - ) - - $(P Dynamic array properties are:) - - $(TABLE2 Dynamic Array Properties, - $(TR $(TH Property) $(TH Description)) - - $(TR - $(TD $(B .init)) - $(TD Returns null.) - ) - - $(TR - $(TD $(B .sizeof)) - $(TD Returns the size of the dynamic array reference, - which is 8 in 32-bit builds and 16 on 64-bit builds. - ) - ) - - $(TR - $(TD $(B .length)) - $(TD Get/set number of elements in the array. - It is of type $(B size_t). - ) - ) - - $(TR - $(TD $(B .ptr)) - $(TD Returns a pointer to the first element of the array. - ) - ) - - $(TR - $(TD $(B .dup)) - $(TD Create a dynamic array of the same size - and copy the contents of the array into it. - ) - ) - - $(TR - $(TD $(B .idup)) - $(TD Create a dynamic array of the same size - and copy the contents of the array into it. - The copy is typed as being immutable. - $(I D 2.0 only) - ) - ) - - $(TR - $(TD $(B .reverse)) - $(TD Reverses in place the order of the elements in the array. - Returns the array. - ) - ) - - $(TR - $(TD $(B .sort)) - $(TD Sorts in place the order of the elements in the array. - Returns the array. - ) - ) - - ) - - $(P For the $(B .sort) property to work on arrays of class - objects, the class definition must define the function: - $(D int opCmp(Object)). This is used to determine the - ordering of the class objects. Note that the parameter - is of type $(D Object), not the type of the class.) - - $(P For the $(B .sort) property to work on arrays of - structs or unions, the struct or union definition must - define the function: -$(V1 - $(D int opCmp(S)) or - $(D int opCmp(S*)). -) -$(V2 - $(D int opCmp(ref const S) const). -) - The type $(D S) is the type of the struct or union. - This function will determine the sort ordering. - ) - - $(P Examples:) - ---------- -int* p; -int[3] s; -int[] a; - -p.length; // error, length not known for pointer -s.length; // compile time constant 3 -a.length; // runtime value - -p.dup; // error, length not known -s.dup; // creates an array of 3 elements, copies - // elements s into it -a.dup; // creates an array of a.length elements, copies - // elements of a into it ---------- - -

$(LNAME2 resize, Setting Dynamic Array Length)

- - $(P The $(B $(D .length)) property of a dynamic array can be set - as the lvalue of an = operator: - ) - ---------- -array.length = 7; ---------- - - $(P This causes the array to be reallocated in place, and the existing - contents copied over to the new array. If the new array length is - shorter, the array is not reallocated, and no data is copied. It is - equivalent to slicing the array: - ---------- -array = array[0..7]; ---------- - - If the new array length is longer, the remainder is filled out with the - default initializer. - ) - - $(P To maximize efficiency, the runtime always tries to resize the - array in place to avoid extra copying. - $(V1 It will always do a copy if the new size is larger and the array - was not allocated via the new operator or a previous resize operation.) - $(V2 It will always do a copy if the new size is larger and the array - was not allocated via the new operator or resizing in place would - overwrite valid data in the array.) - ) - -$(V1 $(P This means that if there is an array slice immediately following the - array being resized, the resized array could overlap the slice; i.e.: - ) - ---------- -char[] a = new char[20]; -char[] b = a[0..10]; -char[] c = a[10..20]; - -b.length = 15; // always resized in place because it is sliced - // from a[] which has enough memory for 15 chars -b[11] = 'x'; // a[11] and c[1] are also affected - -a.length = 1; -a.length = 20; // no net change to memory layout - -c.length = 12; // always does a copy because c[] is not at the - // start of a gc allocation block -c[5] = 'y'; // does not affect contents of a[] or b[] - -a.length = 25; // may or may not do a copy -a[3] = 'z'; // may or may not affect b[3] which still overlaps - // the old a[3] ---------- -) - -$(V2 - For example: - ---------- -char[] a = new char[20]; -char[] b = a[0..10]; -char[] c = a[10..20]; -char[] d = a; - -b.length = 15; // always reallocates because extending in place would - // overwrite other data in a. -b[11] = 'x'; // a[11] and c[1] are not affected - -d.length = 1; -d.length = 20; // also reallocates, because doing this will overwrite a and - // c - -c.length = 12; // may reallocate in place if space allows, because nothing - // was allocated after c. -c[5] = 'y'; // may affect contents of a, but not b or d because those - // were reallocated. - -a.length = 25; // This always reallocates because if c extended in place, - // then extending a would overwrite c. If c didn't - // reallocate in place, it means there was not enough space, - // which will still be true for a. -a[15] = 'z'; // does not affect c, because either a or c has reallocated. ---------- -) - - $(P To guarantee copying behavior, use the .dup property to ensure - a unique array that can be resized. $(V2 Also, one may use the phobos - $(D .capacity) property to determine how many elements can be appended - to the array without reallocating.) - ) - - $(P These issues also apply to appending arrays with the ~= operator. - Concatenation using the ~ operator is not affected since it always - reallocates. - ) - - $(P Resizing a dynamic array is a relatively expensive operation. - So, while the following method of filling an array: - ) - ---------- -int[] array; -while (1) { - c = getinput(); - if (!c) - break; - $(V2 ++array.length;)$(V1 array.length = array.length + 1;) - array[array.length - 1] = c; -} ---------- - - $(P will work, it will be inefficient. A more practical - approach would be to minimize the number of resizes: - ) - ---------- -int[] array; -array.length = 100; // guess -for (i = 0; ; i++) { - c = getinput(); - if (!c) - break; - if (i == array.length) - $(V2 array.length *= 2;)$(V1 array.length = array.length * 2;) - array[i] = c; -} -array.length = i; ---------- - - $(P Picking a good initial guess is an art, but you usually can - pick a value covering 99% of the cases. - For example, when gathering user - input from the console - it's unlikely to be longer than 80. - ) - - $(V2 $(P Also, you may wish to utilize the phobos $(D reserve) - function to pre-allocate array data to use with the append operator.)) - -

$(LNAME2 func-as-property, Functions as Array Properties)

- - $(P If the first parameter to a function is an array, the - function can be called as if it were a property of the array: - ) - ---- -int[] array; -void foo(int[] a, int x); - -foo(array, 3); -array.foo(3); // means the same thing ---- - -

$(LNAME2 bounds, Array Bounds Checking)

- - $(P It is an error to index an array with an index that is less than - 0 or greater than or equal to the array length. If an index is - out of bounds, $(V1 an ArrayBoundsError)$(V2 a RangeError) exception is - raised if detected at runtime, and an error if detected at compile - time. A program may not rely on array bounds checking happening, for - example, the following program is incorrect: - ) - ---------- -try { - for (i = 0; ; i++) { - array[i] = 5; - } -} -catch (RangeError) { - // terminate loop -} ---------- - - The loop is correctly written: - ---------- -for (i = 0; i < array.length; i++) { - array[i] = 5; -} ---------- - - $(P $(B Implementation Note:) Compilers should attempt to detect - array bounds errors at compile time, for example: - ) - ---------- -int[3] foo; -int x = foo[3]; // error, out of bounds ---------- - - $(P Insertion of array bounds checking code at runtime should be - turned on and off - with a compile time switch. - ) - -

$(LNAME2 array-initialization, Array Initialization)

- -

$(LNAME2 default-initialization, Default Initialization)

- - $(UL - $(LI Pointers are initialized to $(B null).) - $(LI Static array contents are initialized to the default - initializer for the array element type.) - $(LI Dynamic arrays are initialized to having 0 elements.) - $(LI Associative arrays are initialized to having 0 elements.) - ) - -

$(LNAME2 void-initialization, Void Initialization)

- - $(P Void initialization happens when the $(I Initializer) for - an array is $(B void). What it means is that no initialization - is done, i.e. the contents of the array will be undefined. - This is most useful as an efficiency optimization. - Void initializations are an advanced technique and should only be used - when profiling indicates that it matters. - ) - -

$(LNAME2 static-init-static, Static Initialization of Statically Allocated Arrays)

- - $(P Static initalizations are supplied by a list of array - element values enclosed in [ ]. The values can be optionally - preceded by an index and a :. - If an index is not supplied, it is set to the previous index - plus 1, or 0 if it is the first value. - ) - ---------- -int[3] a = [ 1:2, 3 ]; // a[0] = 0, a[1] = 2, a[2] = 3 ---------- - - $(P This is most handy when the array indices are given by enums:) - ---------- -enum Color { red, blue, green }; - -int value[Color.max + 1] = - [ Color.blue :6, - Color.green:2, - Color.red :5 ]; ---------- - - $(P These arrays are statically allocated when they appear in global scope. - Otherwise, they need to be marked with $(B const) or $(B static) - storage classes to make them statically allocated arrays.) - - -

$(LNAME2 special-array, Special Array Types)

- -

$(LNAME2 strings, Strings)

- - $(P A string is - an array of characters. String literals are just - an easy way to write character arrays. - String literals are immutable (read only). - ) - -$(V1 ---------- -char[] str; -char[] str1 = "abc"; -str[0] = 'b'; // error, "abc" is read only, may crash ---------- - - $(P The name $(CODE string) is aliased to $(CODE char[]), - so the above declarations could be equivalently written as: - ) - ---------- -string str; -string str1 = "abc"; ---------- -) -$(V2 ---------- -char[] str1 = "abc"; // error, "abc" is not mutable -char[] str2 = "abc".dup; // ok, make mutable copy -immutable(char)[] str3 = "abc"; // ok -immutable(char)[] str4 = str1; // error, str4 is not mutable -immutable(char)[] str5 = str1.idup; // ok, make immutable copy ---------- - - $(P The name $(CODE string) is aliased to $(CODE immutable(char)[]), - so the above declarations could be equivalently written as: - ) ---------- -char[] str1 = "abc"; // error, "abc" is not mutable -char[] str2 = "abc".dup; // ok, make mutable copy -string str3 = "abc"; // ok -string str4 = str1; // error, str4 is not mutable -string str5 = str1.idup; // ok, make immutable copy ---------- -) - $(P $(CODE char[]) strings are in UTF-8 format. - $(CODE wchar[]) strings are in UTF-16 format. - $(CODE dchar[]) strings are in UTF-32 format. - ) - - $(P Strings can be copied, compared, concatenated, and appended:) - ---------- -str1 = str2; -if (str1 < str3) ... -func(str3 ~ str4); -str4 ~= str1; ---------- - - $(P with the obvious semantics. Any generated temporaries get cleaned up - by the garbage collector (or by using $(CODE alloca())). - Not only that, this works with any - array not just a special String array. - ) - - $(P A pointer to a char can be generated: - ) - ---------- -char* p = &str[3]; // pointer to 4th element -char* p = str; // pointer to 1st element ---------- - - $(P Since strings, however, are not 0 terminated in D, - when transferring a pointer - to a string to C, add a terminating 0: - ) - ---------- -str ~= "\0"; ---------- - - $(P or use the function $(D std.string.toStringz).) - - $(P The type of a string is determined by the semantic phase of - compilation. The type is - one of: char[], wchar[], dchar[], and is determined by - implicit conversion rules. - If there are two equally applicable implicit conversions, - the result is an error. To - disambiguate these cases, a cast or a postfix of $(B c), - $(B w) or $(B d) can be used: - ) - ---------- -$(V1 -cast(wchar [])"abc" // this is an array of wchar characters -"abc"w // so is this -) -$(V2 -cast(immutable(wchar) [])"abc" // this is an array of wchar characters -"abc"w // so is this -) ---------- - - $(P String literals that do not have a postfix character and that - have not been cast can be implicitly converted between - string, wstring, and dstring as necessary. - ) - ---------- -char c; -wchar w; -dchar d; - -c = 'b'; // c is assigned the character 'b' -w = 'b'; // w is assigned the wchar character 'b' -w = 'bc'; // error - only one wchar character at a time -w = "b"[0]; // w is assigned the wchar character 'b' -w = "\r"[0]; // w is assigned the carriage return wchar character -d = 'd'; // d is assigned the character 'd' ---------- - -

$(LNAME2 printf, C's printf() and Strings)

- - $(P $(B printf()) is a C function and is not part of D. $(B printf()) - will print C strings, which are 0 terminated. There are two ways - to use $(B printf()) with D strings. The first is to add a - terminating 0, and cast the result to a char*: - ) - ---------- -str ~= "\0"; -printf("the string is '%s'\n", cast(char*)str); ---------- - - $(P or:) - ---------- -import std.string; -printf("the string is '%s'\n", std.string.toStringz(str)); ---------- - - $(P String literals already have a 0 appended to them, so - can be used directly:) - ------------ -printf("the string is '%s'\n", cast(char*)"string literal"); ------------ - - $(P So, why does the first string literal to printf not need - the cast? The first parameter is prototyped as a const(char)*, and - a string literal can be implicitly cast to a const(char)*. - The rest of the arguments to printf, however, are variadic - (specified by ...), - and a string literal is passed as a (length,pointer) combination - to variadic parameters.) - - $(P The second way is to use the precision specifier. - The length comes first, followed by the pointer:) - ---------- -printf("the string is '%.*s'\n", str.length, str.ptr); ---------- - - $(P The best way is to use std.stdio.writefln, which can handle - D strings:) - ---------- -import std.stdio; -writefln("the string is '%s'", str); ---------- - -

$(LNAME2 implicit-conversions, Implicit Conversions)

- - $(P A pointer $(D $(I T)*) can be implicitly converted to - one of the following:) - - $(UL - $(LI $(D void*)) - ) - - $(P A static array $(D $(I T)[$(I dim)]) can be implicitly - converted to - one of the following: - ) - - $(UL - $(LI $(D $(I T)[])) - $(V1 $(LI $(D $(I U)[]))) - $(V2 $(LI $(D const($(I U))[]))) - $(LI $(D void[])) - ) - - $(P A dynamic array $(D $(I T)[]) can be implicitly converted to - one of the following: - ) - - $(UL - $(V1 $(LI $(D $(I U)[]))) - $(V2 $(LI $(D const($(I U))[]))) - $(LI $(D void[])) - ) - - $(P Where $(I U) is a base class of $(I T).) -) - -Macros: - TITLE=Arrays - WIKI=Arrays - CATEGORY_SPEC=$0 - STD_UNI=std.uni - FOO= - diff --git a/articles.html b/articles.html deleted file mode 100644 index abf324bdf5..0000000000 --- a/articles.html +++ /dev/null @@ -1,9 +0,0 @@ - - - -D Runtime Library - - - - - diff --git a/articles/RefReturnScope.dd b/articles/RefReturnScope.dd new file mode 100644 index 0000000000..9ff5e4e358 --- /dev/null +++ b/articles/RefReturnScope.dd @@ -0,0 +1,207 @@ +Ddoc + +$(D_S $(TITLE), + +$(P A wild pointer is a pointer that escapes its corral, or in other words, +escapes its scope. A pointer within its scope is valid, and outside +its scope is not valid. Attempting to read or write using an out-of-scope pointer +will produce undefined behavior. Undefined behavior can lead to crashes, corruption, +malware, and other costly problems. D uses `ref`, `return` and `scope` keywords to +prevent pointer escapes.) + + +$(H3 What is a Scope?) + +$(P The scope of a declaration is closely related to its lifetime. +Thread local variables have a lifetime that's the life of the thread they are +in. Global variables have a lifetime from the program start to its finish. +A local variable has a lifetime from its initialization to its closing curly brace.) + +$(P Note on examples: `@safe` annotation is assumed) + +--- +int x; // thread local lifetime +__gshared int y; // global lifetime + +void mars(int i /* lifetime of i is from function call to function return */) +{ + { // open new scope + int* q = &i; // lifetime starts after q is set to the address of i + *q = 3; // sets i to 3 + } // q's lifetime ends with the end of the scope + *q = 4; // oops, can't use q here + int* p = &i; // lifetime starts after p is set to the address of i + *p = 5; // sets i to 5 +} // lifetimes of i and p end when function returns +--- + + +$(H3 What is an Escaping Pointer?) + +$(P A pointer escapes when its value becomes available outside the scope of the pointer. +An example of an escaping pointer:) + +--- +int* escape() +{ + int i; + int* p = &i; // create pointer to local variable + return p; // return pointer to a local variable that is no longer live +} + +void crash() +{ + int* q = escape(); + *q = 5; // unleash the Hounds of Hell +} +--- + +$(P Pointer escapes can occur in many, often not-so-obvious, cases. The compiler is +the perfect tool to detect all the cases and report them as errors. Even if a +particular pointer escape is benign, if a function interface makes clear that +a function arguments cannot escape, it improves user understanding of the function.) + + +$(H3 The Role of `scope`) + +$(P `scope` is a storage class. When it is applied to a pointer variable, then the pointer's +value is mechanically (i.e. enforced by the compiler) prevented from outlasting the scope +of the pointer variable. The previous example is modified with the addition of `scope`:) + +--- +int* escape() +{ + int i; + scope int* p = &i; // p is a scoped pointer + return p; // error: scoped pointer p is escaping +} +--- + +The compiler, for this case, helpfully goes one better: + +--- +int* escape() +{ + int i; + int* p = &i; // p is inferred to be a scoped pointer + return p; // error: scoped pointer p is escaping +} +--- + +$(P I.e. if a pointer variable is set to be the address of a local variable, or to the contents of +scope pointer, then that pointer variable is automatically set to be a scope pointer. +The compiler is pretty good at inferring scope, thus relieving the programmer of adding +a lot of annotations.) + +$(P Note that as `scope` is a storage class, not a type constructor, it is not possible to specify +a scope pointer to a scope pointer. It surprisingly turns out to not be necessary to support that.) + + +$(H3 The Role of `return scope`) + +$(P Consider the following:) + +--- +void f() +{ + int i; + *process(&i) = 4; +} + +int* process(scope int* p) { return p; } +--- + +$(P This is perfectly legitimate code, there is no pointer escaping bug. But it won't compile. +Without `scope` on the parameter `p`, the call to `process(&i)` would be disallowed. +But with `scope` on `p`, the `return p;` is disallowed.) + +$(P The solution is adding a `return` annotation:) + +--- +int* process(return scope int* p) { return p; } +--- + +$(P which allows the scope pointer value to be returned by the function.) + +$(P If a function returns `void`, `return scope` also allows returning the scope value +through the first parameter:) + +--- +void mun(ref int* v, return scope int* p) +{ + v = p; // ok +} +--- + +$(P And that's it for pointers. Remember that pointer scoping is concerned with the value +of the pointer variable.) + + +$(H3 The Role of `ref`) + +$(P A `ref` is a reference to a value, a fancy way of representing a pointer to a value. +It is distinguished from a pointer:) + +$(OL +$(LI by not allowing arithmetic on the address) +$(LI whenever the `ref` variable is used an automatic dereference is performed) +$(LI a ref cannot escape from a function) +) + +--- +ref int fin(ref int i) +{ + return i; // error, cannot return ref variable i by ref +} +--- + + +$(H3 The role of `return ref`) + +$(P But it will be allowed if `return` is applied:) + +--- +ref int fin(return ref int i) +{ + return i; // ok +} +--- + + +$(H3 The role of `ref scope`) + +$(P The storage classes `ref` and `scope` together are orthogonal, they do not affect each other. +`ref` refers to the address of the variable, `scope` refers to the contents of the variable.) + + +$(H3 The role of `return ref scope`) + +$(P The `return` here applies to the `ref`, not the `scope`.) + +$(P Let's try tricking the compiler:) + +--- +ref int* fin(return ref scope int* p) { return p; } // ok + +int* tricky() +{ + int i; + int* p = &i; // p is now inferred to be scope + auto q = fin(p); // q now contains the address of i, and so scope is also inferred + return q; // error: scope variable `q` may not be returned +} +--- + +$(P Curses! Foiled again!) + +$(P The operational idea here is, while compiling `@safe` code, it is not be possible to escape +a scoped value, no matter how twisty the code is.) + +) + +Macros: + TITLE=Coralling Wild Pointers With ref return scope + ITEMR=$(LI $(RELATIVE_LINK2 $1, $+)) + ITEM=
$(H3 $+) + SUBNAV=$(SUBNAV_ARTICLES) + diff --git a/articles/articles.ddoc b/articles/articles.ddoc new file mode 100644 index 0000000000..79f6f5ac89 --- /dev/null +++ b/articles/articles.ddoc @@ -0,0 +1 @@ +ROOT_DIR = ../ diff --git a/articles/builtin.dd b/articles/builtin.dd new file mode 100644 index 0000000000..df793d1948 --- /dev/null +++ b/articles/builtin.dd @@ -0,0 +1,177 @@ +Ddoc + +$(COMMUNITY Core Language Features vs Library Implementation, + + + $(P D offers several capabilities built in to the core language + that are implemented as libraries in other languages such + as C++: + ) + + $(OL + $(LI Dynamic Arrays) + $(LI Strings) + $(LI Associative Arrays) + ) + + $(P Some consider this as evidence of language bloat, rather than + a useful feature. + So why not implement each of these as standardized library types? + ) + + $(P Some general initial observations: + ) + + $(OL + + $(LI Each of them is heavily used. This means that even small + improvements in usability are worth reaching for. + ) + + $(LI Being a core language feature means that the compiler can + issue better and more to the point error messages when a type + is used incorrectly. + Library implementations tend to give notoriously obtuse messages + based on the internal details of those implementations. + ) + + $(LI Library features cannot invent new syntax, new operators, + or new tokens. + ) + + $(LI Library implementations tend to require a lot of compile + time processing of the implementation, over and over for each compile, + that slows down compilation. + ) + + $(LI Library implementations are supposed to provide flexibility + to the end user. But if they are standardized, to the + point of the compiler being allowed to recognize them as special + (the C++ Standard allows this), then they become just as inflexible + as builtin core features. + ) + + $(LI The ability to define new library types, while having greatly + advanced in the last few years, still leaves a lot to be desired + in smoothly integrating it into the existing language. + Rough edges, clumsy syntax, and odd corner cases abound. + ) + + ) + + $(P More specific comments: + ) + +$(SECTION2 Dynamic Arrays, + + $(P C++ has builtin core arrays. It's just that they don't work very + well. Rather than fix them, several different array types were + created as part of the C++ Standard Template Library, each covering + a different deficiency in the builtin arrays. These + include: + ) + + $(UL + $(LI $(D basic_string)) + $(LI $(D vector)) + $(LI $(D valarray)) + $(LI $(D deque)) + $(LI $(D slice_array)) + $(LI $(D gslice_array)) + $(LI $(D mask_array)) + $(LI $(D indirect_array)) + ) + + $(P Fixing the builtin array support means the need for each of these + variations just evaporates. There's one array type that covers + it all, only one thing to learn, and no problems getting one array + type to work with another array type. + ) + + $(P As usual, a builtin type lets us create syntactic sugar for it. + This starts with having an array literal, and follows with some + new operators specific to arrays. A library array implementation + has to make due with overloading existing operators. + The indexing operator, $(D a[i]), it shares with C++. + Added are the array concatenation operator $(D ~), array append operator + $(D ~=), array slice operator $(D a[i..j]), + and the array vector operator + $(D a[]). + ) + + $(P The ~ and ~= concatenation operators resolve a problem that comes + up when only existing operators can be overloaded. Usually, + is + pressed into service as concatenation for library array + implementations. But that winds up precluding having + mean + array vector addition. Furthermore, concatenation has nothing in + common with addition, and using the same operator for both is + confusing. + ) +) + + +$(SECTION2 Strings, + + $(P C++ has, of course, builtin string support in the form of string + literals and char arrays. It's just that they suffer from all + the weaknesses of C++ builtin arrays. + ) + + $(P But after all, what is a string if not an array of characters? + If the builtin array problems are fixed, doesn't that resolve + the string problems as well? It does. It seems odd at first that + D doesn't have a string class, but since manipulating strings + is nothing more than manipulating arrays of characters, if arrays + work, there's nothing a class adds to it. + ) + + $(P Furthermore, the oddities resulting from builtin string literals + not being of the same type as the library string class type go + away. + ) +) + + +$(SECTION2 Associative Arrays, + + $(P The main benefit for this is, once again, syntactic sugar. + An associative array keying off of a type $(D T) and storing an + $(D int) value is naturally written + as: + ) + +--------------- +int[T] foo; +--------------- + + $(P rather than: + ) + +--------------- +import std.associativeArray; +... +std.associativeArray.AA!(T, int) foo; +--------------- + + $(P Builtin associative arrays also offer the possibility of having + associative array literals, which are an often requested additional + feature. + ) +) + + +$(SECTION2 Please Note, + + $(P D currently has a built-in complex type that is being phased + out in favor of a library implementation. Advances in D language + semantics and compiler implementation have obviated the need for a + built-in complex type.) + +) + +) + +Macros: + TITLE=D Builtin Rationale + SUBNAV=$(SUBNAV_ARTICLES) + diff --git a/code_coverage.dd b/articles/code_coverage.dd similarity index 56% rename from code_coverage.dd rename to articles/code_coverage.dd index 7b7bb830a8..2ab0e79cfd 100644 --- a/code_coverage.dd +++ b/articles/code_coverage.dd @@ -7,8 +7,8 @@ is creating a test suite for it. Without some sort of test suite, it is impossible to know if the software works at all. The D language has many features to aid in the creation of test suites, such as -$(LINK2 unittest.html, unit tests) and -$(LINK2 dbc.html, contract programming). +$(DDLINK spec/unittest, Unit Tests, unit tests) and +$(DDLINK spec/contracts, Contract Programming, contract programming). But there's the issue of how thoroughly the test suite tests the code. The $(LINK2 http://www.digitalmars.com/ctg/trace.html, profiler) @@ -34,13 +34,15 @@ $(LI It can be used to track down why a particular section of code $(LI Since execution counts are given for each line, it is possible to use the coverage analysis to reorder the basic blocks in - a function to minimize jmps in the most used path, thus - optimizing it.) -) + a function to minimize branches in the most used path, reducing stress + on the processor's pipeline (a run-of-the-mill X86 processor can usually handle 48 branches in its pipeline). This technique + is a special case of $(LINK2 https://en.wikipedia.org/wiki/Profile-guided_optimization, profile-guided optimization), which can + be performed automatically if either the `LLVM` or `GCC` backend is utilized. +)) $(P Experience with code coverage analyzers show that they dramatically reduce the number of bugs in shipping code. -But it isn't a panacea, a code coverage analyzer won't help with:) +But it isn't a panacea, a code coverage analyzer won't help (unlike Valgrind or the sanitizers available in GCC and LLVM) with:) $(OL $(LI Identifying race conditions.) @@ -49,23 +51,24 @@ $(LI Pointer bugs.) $(LI Verifying that the program got the correct result.) ) -$(P Code coverage analysers are available for many popular languages -such as C++, but they are often third party products that integrate -poorly with the compiler, and are often very expensive. +$(P Code coverage analysers are available for many popular languages, +but they are often third party products that integrate +poorly with the compiler. A big problem with third party products is, in order to instrument -the source code, they must include what is essentially a full blown +the source code, they must include what is essentially a full-blown compiler front end for the same language. Not only is this an expensive proposition, it often winds up out of step with the various compiler vendors as their implementations change and as they evolve various extensions. ($(LINK2 http://gcc.gnu.org/onlinedocs/gcc-3.0/gcc_8.html, gcov), -the Gnu coverage analyzer, is an exception as it is both free +the Gnu coverage analyzer is an exception as it is both free and is integrated into gcc.) ) -$(P The D code coverage analyser is built in as part of the D compiler. +$(P The D code coverage analyser is part of the D compiler. Therefore, it is always in perfect synchronization with the language implementation. It's implemented by establishing a counter for each -line in each module compiled with the $(B -cov) switch. Code is inserted +line in each module compiled with the $(DDSUBLINK dmd,switch-cov, $(B -cov)) switch. +Code is inserted at the beginning of each statement to increment the corresponding counter. When the program finishes, the runtime collects all the counters, merges it with the source files, and writes the reports out @@ -77,27 +80,31 @@ $(P For example, consider the Sieve program:) import std.stdio; -bit flags[8191]; +bool[8191] flags; int main() -{ int i, prime, k, count, iter; +{ + int i, prime, k, count, iter; - writefln("10 iterations"); + writeln("10 iterations"); for (iter = 1; iter <= 10; iter++) - { count = 0; - flags[] = true; - for (i = 0; i < flags.length; i++) - { if (flags[i]) - { prime = i + i + 3; - k = i + prime; - while (k < flags.length) - { - flags[k] = false; - k += prime; - } - count += 1; - } - } + { + count = 0; + flags[] = true; + for (i = 0; i < flags.length; i++) + { + if (flags[i]) + { + prime = i + i + 3; + k = i + prime; + while (k < flags.length) + { + flags[k] = false; + k += prime; + } + count += 1; + } + } } writefln("%d primes", count); return 0; @@ -119,18 +126,22 @@ $(CONSOLE | |import std.stdio; | - |bit flags[8191]; + |bool[8191] flags; | |int main() - 5|{ int i, prime, k, count, iter; + |{ + 5| int i, prime, k, count, iter; | - 1| writefln("10 iterations"); + 1| writeln("10 iterations"); 22| for (iter = 1; iter <= 10; iter++) - 10| { count = 0; + | { + 10| count = 0; 10| flags[] = true; 163840| for (i = 0; i < flags.length; i++) - 81910| { if (flags[i]) - 18990| { prime = i + i + 3; + | { + 81910| if (flags[i]) + | { + 18990| prime = i + i + 3; 18990| k = i + prime; 168980| while (k < flags.length) | { @@ -154,13 +165,13 @@ as the execution count. At the end of the .lst file, the percent coverage is given. ) -$(P There are 3 lines with an exection count +$(P There are 3 lines with an execution count of 1, these were each executed once. The declaration line for $(D i, prime), etc., has 5 because there are 5 declarations, and the initialization of each declaration counts as one statement.) $(P The first $(D for) loop shows 22. This is the sum of the 3 parts -of the for header. If the for header is broken up into 3 lines, the +of the for-header. If the for-header is broken up into 3 lines, the data is similarly divided:) $(CONSOLE @@ -172,51 +183,92 @@ $(CONSOLE $(P which adds up to 22.) $(P $(D e1&&e2) and $(D e1||e2) expressions conditionally -execute the rvalue $(D e2). -Therefore, the rvalue is treated as a separate statement with its own -counter:) +execute the right-hand operand $(D e2). +Therefore, the right-hand operand is treated as a separate statement with its +own counter:) $(CONSOLE |void foo(int a, int b) |{ 5| bar(a); 8| if (a && b) - 1| bar(b); + 1| bar(b); |} ) -$(P By putting the rvalue on a separate line, this illuminates things:) +$(P By putting the right-hand operand on a separate line, this illuminates +things:) $(CONSOLE |void foo(int a, int b) |{ 5| bar(a); 5| if (a && - 3| b) - 1| bar(b); + 3| b) + 1| bar(b); |} ) $(P Similarly, for the $(D e?e1:e2) expressions, $(D e1) and $(D e2) are treated as separate statements.) -

Controlling the Coverage Analyser

+$(H3 Controlling the Coverage Analyser) $(COMMENT The behavior of the coverage analyser can be controlled through the $(DRUNTIMESRC rt/cover.d) module.) -$(P When the $(B -cov) switch is thrown, the version identifier +$(P When the $(DDSUBLINK dmd,switch-cov, $(B -cov)) switch is thrown, +the $(DDSUBLINK spec/version, PredefinedVersions, version identifier) $(B D_Coverage) is defined.) -

References

+$(P The standard runtime option passing mechanism can also be used to control how +code coverage reports are generated at runtime. The command-line option $(D +--DRT-covopt) or the environment variable $(D DRT_COVOPT) can be used to pass +options. Options are passed separated by spaces as key,value with the following +format: $(D key:value). Current options are:) + +$(DL + $(SWITCH $(SWNAME merge), + Merge the current run with existing reports if `1`, or overwrite the existing reports if `0`. + ) + $(SWITCH $(SWNAME srcpath), + Set path to where source files are located. + ) + $(SWITCH $(SWNAME dstpath), + Set path to where listing files are to be written (must exist). + ) +) -$(LINK2 http://en.wikipedia.org/wiki/Code_coverage, Wikipedia) +$(H4 Example:) +$(CONSOLE +sieve --DRT-covopt="merge:1" +mkdir reports +sieve --DRT-covopt="merge:1 dstpath:reports" ) -Macros: - TITLE=Code Coverage Analysis - WIKI=Dcover - CATEGORY_DOWNLOAD=$0 - RPAREN=) +$(P Will merge the results of this run with the previous run in the $(D +sieve.lst) file in the current directory. While:) +$(CONSOLE +mkdir reports +sieve --DRT-covopt="dstpath:reports" +) + +$(P Will create a new report in $(D reports/sieve.lst). Another run adding $(D +merge) will add to the new report:) + +$(CONSOLE +sieve --DRT-covopt="merge:1 dstpath:reports" +) + + +$(H3 References) + +$(LINK2 https://en.wikipedia.org/wiki/Code_coverage, Wikipedia: "Code Coverage") + +) + +Macros: + TITLE=Code Coverage Analysis + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/articles/const-faq.dd b/articles/const-faq.dd new file mode 100644 index 0000000000..bde033ac80 --- /dev/null +++ b/articles/const-faq.dd @@ -0,0 +1,296 @@ +Ddoc + +$(D_S const(FAQ), + + $(P D's $(D const)/$(D immutable) system is unique, and so there + are a lot of questions about it. ) + + $(UL + + $(ITEMR const, Why does D have const?) + $(ITEMR principles, What principles drove the D const design?) + $(ITEMR transitive-const, What is $(I transitive const)?) + $(ITEMR head-const, What is $(I head const)?) + $(ITEMR tail-const, What is $(I tail const)?) + $(ITEMR logical-const, What is $(I logical const)?) + $(ITEMR readonly, Why not use $(I readonly) to mean read only view?) + $(ITEMR java-const, Why did Java reject const?) + $(ITEMR cpp-const, How does const differ in C++?) + $(ITEMR invariant-strings, Why are strings immutable?) + $(ITEMR const-parameters, Why aren't function parameters const by default?) + $(ITEMR static-members, Are static class members covered by transitive const?) + $(ITEMR invariant, What is $(I immutable) good for?) + ) + +$(ITEM const, Why does D have const?) + + $(P People often express frustration with const and immutable + in D 2.0 and wonder if it is worth it. + ) + + $(OL + + $(LI It makes function interfaces more self-documenting. Without + transitive const, for all pointer/reference parameters one must rely on + the documentation (which may be missing, out of date, or wrong). Note + that without transitivity, C++ const is nearly useless for such + self-documentation, which is why C++ programmers tend to rely on + convention instead. + ) + + $(LI It makes for interfaces that can be relied upon, which becomes + increasingly important as more people become involved with the code. + In other words, it scales very well. People working on + projects with large teams of programmers say that lack of const + makes their lives difficult because they cannot rely on the compiler to + enforce convention. The larger the team, the worse it gets. Managing + APIs is critical to a large project - it's why BASIC doesn't scale (as + an extreme example). + ) + + $(LI Const transitivity makes for some interesting optimization + opportunities. The value of this has not been explored or exploited. + ) + + $(LI Here's the biggie. Points 1..3 are insignificant in comparison. The + future of programming will be multicore, multithreaded. Languages that + make it easy to program them will supplant languages that don't. + Transitive const is key to bringing D into this paradigm. The surge in + use of Haskell and Erlang is evidence of this coming trend (the killer + feature of those languages is they make it easy to do multiprogramming). + C++ cannot be retrofitted to supporting multiprogramming in a manner + that makes it accessible. D isn't there yet, but it will be, and + transitive const will be absolutely fundamental to making it work. + ) + ) + + $(P Of course, for writing single-threaded one developer programs of + fairly modest size, const is not particularly useful. + And in D const can be effectively ignored by just not using it. + The only place const is imposed is with the immutable + string type. + ) + +$(ITEM principles, What principles drove the D const design?) + + $(OL + $(LI It must be mathematically sound. That means there + are no legal escapes from it.) + $(LI Any type can be wrapped in a struct and the resulting + struct can still exhibit the same const behavior - in other + words, no magic behavior for certain types.) + $(LI Const behavior must be transitive.) + $(LI Const behavior for type T must be equivalent for all types T.) + ) + +$(ITEM transitive-const, What is $(I transitive const)?) + + $(P Transitive const means that once const is applied to a type, + it applies recursively to every sub-component of that type. Hence: + ) + +--- +const(int*)** p; +p += 1; // ok, p is mutable +*p += 1; // ok, *p is mutable +**p += 1; // error, **p is const +***p += 1; // error, ***p is const +--- + + $(P With transitivity, there is no way to have a + $(I const pointer to mutable int). + ) + + $(P C++ const is not transitive.) + +$(ITEM head-const, What is $(I head const)?) + + $(P Head const is where the const applies only to the component + of the type adjacent to the const. For example: + ) + +--- +headconst(int**) p; +--- + $(P would be read as p being a: $(I const pointer to mutable pointer + to mutable int.) D does not have head const (the $(CODE headconst) is + there just for illustrative purposes), but C++ const is + a head const system. + ) + +$(ITEM tail-const, What is $(I tail const)?) + + $(P Tail const is the complement of head const - everything reachable + from the const type is also const except for the top level. For + example: + ) + +--- +tailconst(int**) p; +--- + $(P would be read as p being a: $(I mutable pointer to const pointer + to const int.) Head const combined with tail const yields transitive + const. + D doesn't have $(CODE tailconst) (the keyword is there just for + illustrative purposes) as a distinct type constructor. + ) + +$(ITEM logical-const, What is $(I logical const)?) + + $(P $(I Logical const) refers to data that appears to be constant + to an observer, but is not actually const. An example would be + an object that does lazy evaluation:) + +--- +struct Foo +{ + mutable int len; + mutable bool len_done; + const char* str; + int length() + { + if (!len_done) + { + len = strlen(str); + len_done = true; + } + return len; + } + this(char* str) { this.str = str; } +} +const Foo f = Foo("hello"); +bar(f.length); +--- + + $(P The example evaluates $(CODE f.len) only if it is needed. + $(CODE Foo) is logically const, because to the observer of the object + its return values never change after construction. + The $(CODE mutable) qualifier says that even if an instance + of $(CODE Foo) is const, those fields can still change. + While C++ supports the notion of logical const, D does not, + and D does not have a $(CODE mutable) qualifier. + ) + + $(P The problem with logical const is that const is no longer + transitive. Not being transitive means there is the potential + for threading race conditions, and there is no way to determine + if an opaque const type has mutable members or not. + ) + + $(P Reference: + $(LINK2 http://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter08_025.html, mutable: bitwise vs. logical const) + ) + +$(ITEM readonly, Why not use $(I readonly) to mean read only view?) + + $(P $(I Readonly) has a well established meaning in software to + mean ROM, or Read Only Memory that can never be changed. + For computers with hardware protection for memory pages, readonly + also means that the memory contents cannot be altered. + Using readonly in D to mean a read only view of memory that could + be altered by another alias or thread runs counter to this. + ) + +$(ITEM java-const, Why did Java reject const?) + + $(P $(LINK https://bugs.java.com/bugdatabase/view_bug?bug_id=4211070) + ) + +$(ITEM cpp-const, How does const differ in C++?) + + $(P C++ has a const system that is closer to D's than any other + language, but it still has huge differences:) + + $(OL + $(LI const is not transitive) + $(LI no immutables) + $(LI const objects can have mutable members) + $(LI const can be legally cast away and the data modified) + $(LI $(CODE const T) and $(CODE T) are not always distinct types) + ) + +$(ITEM invariant-strings, Why are strings immutable?) + + $(P $(LINK2 https://www.digitalmars.com/articles/b01.html, Immutable Strings) + ) + +$(ITEM const-parameters, Why aren't function parameters const by default?) + + $(P Since most (nearly all?) function parameters will not be modified, + it would seem to make sense to make them all const by default, + and one would have to specifically mark as mutable those that would + be changed. The problems with this are: + ) + + $(OL + + $(LI It would be a huge break from past D practice, and practice + in C, C++, Java, C#, etc.) + $(LI It would require a new keyword, say $(CODE mutable).) + $(LI And worst, it would make declarations inconsistent: +--- +void foo(int* p) +{ + int* q; + ... +} +--- + $(CODE p) points to const, and $(CODE q) points to mutable. + This kind of inconsistency leads to all sorts of mistakes. + It also makes it very hard to write generic code that deals with + types. + ) + ) + + $(P Using $(CODE in) can mitigate the ugliness of having to annotate + with $(CODE const):) +--- +void str_replace(in char[] haystack, in char[] needle); +--- + +$(ITEM static-members, Are static class members covered by transitive const?) + + $(P A static class member is part of the global state of a program, + not part of the state of an object. Thus, a class having a mutable + static member does not violate the transitive constness of an object + of that class. + ) + +$(ITEM invariant, What is $(I immutable) good for?) + + $(P Immutable data, once initialized, is never changed. + This has many uses: + ) + + $(UL + $(LI Access to immutable data need not be synchronized + when multiple threads read it.) + $(LI Data races, tearing, sequential consistency, and + cache consistency are all non-issues when working with + immutable data.) + $(LI When doing a $(I deep copy) of a data structure, + the immutable portions need not be copied.) + $(LI Invariance allows a large chunk of data to be treated + as a value type even if it is passed around by reference + (strings are the most common case of this).) + $(LI Immutable types provide more self-documenting information + to the programmer.) + $(LI Immutable data can be placed in hardware protected read-only + memory, or even in ROMs.) + $(LI If immutable data does change, it is a sure sign of a memory + corruption bug, and it is possible to automatically check for + such data integrity.) + $(LI Immutable types provide for many program optimization + opportunities.) + ) + + $(P $(I const) acts as a bridge between the mutable and immutable + worlds, so a single function can be used to accept both types + of arguments.) +) + +Macros: + TITLE=const(FAQ) + ITEMR=$(LI $(RELATIVE_LINK2 $1, $+)) + ITEM=
$(H3 $+) + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/articles/constraints.dd b/articles/constraints.dd new file mode 100644 index 0000000000..1c014ec6cd --- /dev/null +++ b/articles/constraints.dd @@ -0,0 +1,317 @@ +Ddoc + +$(D_S Template Constraints, + + $(P Templates are normally overloaded and matched based on the + template arguments being matched to the template parameters. + The template parameters can specify + $(DDSUBLINK spec/template, parameters_specialization, specializations), so that + the template argument must match particular type patterns. + Similarly, template value arguments can be constrained to + match particular types.) + +--- +template Foo(T) { ... } +template Foo(T : T*) { ... } +template Foo(T : T[]) { ... } + +alias f1 = Foo!(int); // picks Foo(T) +alias f2 = Foo!(int*); // picks Foo(T : T*) +alias f3 = Foo!(int[]); // picks Foo(T : T[]) +--- + + $(P But this has its limitations. Many times there are + arbitrarily more + complex criteria for what should be accepted by the template. + Such criteria could be to: + ) + + $(UL + $(LI more finely discriminate about which + template gets instantiated for given arguments) + $(LI provide better self-documentation about what + characteristics template parameters must have) + $(LI provide better diagnostics when arguments don't match, + rather than an obscure error message based on the irrelevant + (to the user) internal details of the template implementation) + ) + + $(P Constraints address this by simply providing a boolean + expression that is evaluated at compile-time, + after the arguments are matched to the parameters. + If that boolean is true, then the template is a valid match for + the arguments, if not, then the template does not match and + is passed over during overload matching.) + + $(P The constraint expression follows the template declaration + and the $(CODE if) keyword:) + +--- +template Foo(int N) + if (N & 1) +{ + ... +} +--- + + $(P which constrains the template $(CODE Foo) to match only if its + argument + is an odd integer.) + +$(H2 $(LNAME2 predicates, Predicate Functions)) + + $(P Arbitrarily complex criteria can be used, as + long as it can be computed at compile time. For example, here's + a template that only accepts prime numbers: + ) + +$(RUNNABLE_EXAMPLE_COMPILE +--- +bool isPrime(int n) +{ + if (n == 2) + return true; + // 0, negative and even numbers are not prime + if (n < 1 || (n & 1) == 0) + return false; + if (n > 3) + { + // check possible odd integer denominators + for (auto i = 3; i * i <= n; i += 2) + { + if ((n % i) == 0) + return false; + } + } + return true; +} + +template Foo(int N) + if (isPrime(N)) +{ + // ... +} + +alias f1 = Foo!(5); // ok, 5 is prime +//alias f2 = Foo!(6); // error: no match for Foo +//alias f3 = Foo!(9); // error: no match for Foo +--- +) + + $(NOTE `isPrime` is called using $(DDSUBLINK spec/function, interpretation, Compile-Time Function Evaluation).) + +$(H2 $(LNAME2 is, `is` Expressions)) + + $(P Type constraints can be complex, too. With type specialization alone, a template + `Bar` that will accept any type that implicitly converts to a built-in floating + point type must use template overloads: + ) +--- +template Bar(T:float) +{ + ... +} +template Bar(T:double) +{ + ... +} +template Bar(T:real) +{ + ... +} +--- + $(P and the template implementation body must be duplicated + three times. But with constraints, this can be specified + with one template: + ) +--- +template Bar(T) + if (is(T : float) || is(T : double) || is(T : real)) +{ + ... +} +--- + $(P Unlike with parameter specialization, types with implicit conversion to + floating point can be ruled out with a different constraint:) + +$(RUNNABLE_EXAMPLE_COMPILE +--- +template Bar(T) + if (is(T == float) || is(T == double) || is(T == real)) +{ + // ... +} + +alias b1 = Bar!float; // OK +//alias b2 = Bar!int; // error +--- +) + $(P See $(GLINK2 expression, IsExpression) for more tests.) + + $(P The above example can be simplified by using the $(CODE isFloatingPoint) + template in library module $(MREF std, traits): + ) +--- +import std.traits; + +template Bar(T) + if (isFloatingPoint!(T)) +{ + ... +} +--- + +$(H2 $(LNAME2 traits, `__traits`)) + + $(P Characteristics of types can be tested, such as if + a type instance can be added: + ) + +$(RUNNABLE_EXAMPLE +--- +// Returns true if instances of type T can be added +// Works by attempting to add two instances of type T +const isAddable(T) = __traits(compiles, (T t) { return t + t; }); + +auto twice(T)(T t) + if (isAddable!(T)) +{ + return t + t; +} + +// an addable struct type +struct S +{ + int i; + + S opBinary(string op : "+")(S s) + { + return S(i + s.i); + } +} + +void main() +{ + assert(twice(4) == 8); + S s = {2}; + assert(twice(s).i == 4); + //twice("a"); // fails to match +} +--- +) + + $(P $(DDSUBLINK spec/traits, compiles, `__traits(compiles)`) is + used to check if a function literal successfully compiles. Other + expressions can be used instead of a function literal. The expression + is not evaluated. + Other compile-time `__traits` $(DDLINK spec/traits, Traits, are available).) + + $(NOTE The function literal above declares an argument of type + `T` to obtain an instance of `T` without having to construct it.) + + $(P Since any expression that can be computed at compile time + is allowed as a constraint, constraints can be composed: + ) + +--- +T foo(T)(T t) + if (isAddable!(T) && isMultipliable!(T)) +{ + return t + t * t; +} +--- + + $(P Constraints can deal with multiple parameters:) + +--- +template Foo(T, int N) + if (isAddable!(T) && isPrime(N)) +{ + ... +} +--- + + $(P A more complex constraint can specify a list of operations + that must be doable with the type, such as evaluating template $(CODE isStack) which + requires that the type has a type property `ValueType`, and that 4 functions + exist which take an instance of the type, 2 of which return certain + values:) + +---- +const isStack(T) = + __traits(compiles, + (T t) + { + T.ValueType v = top(t); + push(t, v); + pop(t); + if (empty(t)) { } + }); + +template Foo(T) + if (isStack!(T)) +{ + ... +} +---- + +$(H2 $(LNAME2 overloading, Overloading based on Constraints)) + + $(P Given a list of overloaded templates with the same name, + constraints act as a yes/no filter to determine the list + of candidates for a match. + Overloading based on constraints can thus be achieved by + setting up constraint expressions that are mutually exclusive. + For example, overloading template $(CODE Foo) so that one + takes odd integers and the other even: + ) +--- +template Foo(int N) if (N & 1) { ... } // A +template Foo(int N) if (!(N & 1)) { ... } // B +... +Foo!(3) // instantiates A +Foo!(64) // instantiates B +--- + + $(P Note the above 2 templates could be combined using + $(DDSUBLINK spec/version, staticif, `static if`):) +--- +template Foo(int N) +{ + static if (N & 1) + // body of A + else + // body of B +} +--- + $(P Constraints are not involved with determining which + template is more specialized than another. + ) + +--- +void foo(T, int N)() if (N & 1) { ... } // A +void foo(T : int, int N)() if (N > 3) { ... } // B +... +foo!(int, 7)(); // picks B, more specialized +foo!(int, 1)(); // picks A, as it fails B's constraint +foo!("a", 7)(); // picks A +foo!("a", 4)(); // error, no match +--- + +$(H2 References) + + $(UL + $(LI $(LINK2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2081.pdf, Concepts (Revision 1)) + by Douglas Gregor and Bjarne Stroustrup + ) + ) + +) + +Macros: + TITLE=Template Constraints +META_KEYWORDS=D Programming Language, constraints, template, concepts, C++ +META_DESCRIPTION=Going beyond type patterns to constrain template instantiations. + + + diff --git a/articles/cppcontracts.dd b/articles/cppcontracts.dd new file mode 100644 index 0000000000..9ecd43675e --- /dev/null +++ b/articles/cppcontracts.dd @@ -0,0 +1,503 @@ +Ddoc + +$(COMMUNITY D's Contract Programming vs C++'s, + +$(HEADERNAV_TOC) + + $(P Many people have written me saying that D's Contract Programming + does not add anything that C++ does not already support. + They go on to illustrate their point with a technique for doing Contracts in + C++.) + + $(P It makes sense to review what Contract Programming is, how it is done in D, + and stack that up with what each of the various C++ Contract techniques + can do.) + + $(P Digital Mars C++ adds + extensions to C++ + to support Contracts, but they are not covered here because they are not + part of standard C++ and are not supported by any other C++ compiler.) + +$(H2 $(LNAME2 contract-programming-d, Contract Programming in D)) + + This is more fully documented in the D + $(DDLINK spec/contracts, Contract Programming, Contract Programming) + document. + To sum up, Contract Programming in D has the following characteristics: + + $(OL + + $(LI The $(I assert) is the basic contract. + ) + + $(LI When an assert contract fails, it throws an exception. + Such exceptions can be caught and handled, or allowed to + terminate the program. + ) + + $(LI Classes can have $(I class invariants) which are + checked upon entry and exit of each public class member function, + the exit of each constructor, and the entry of the destructor. + ) + + $(LI Assert contracts on object references check the class + invariant for that object. + ) + + $(LI Class invariants are inherited, that means that a derived + class invariant will implicitly call the base class invariant. + ) + + $(LI Functions can have $(I preconditions) and $(I postconditions). + ) + + $(LI For member functions in a class inheritance hierarchy, the + precondition of a derived class function are OR'd together + with the preconditions of all the functions it overrides. + The postconditions are AND'd together. + ) + + $(LI By throwing a compiler switch, Contracts code can be enabled + or can be withdrawn from the compiled code. + ) + + $(LI Code works semantically the same with or without Contracts + checking enabled. + ) + + ) + +$(H2 $(LNAME2 contract-progamming-cpp, Contract Programming in C++)) + +$(H3 $(LNAME2 assert-macro, The $(D assert) Macro)) + + $(P C++ does have the basic $(D assert) macro, which tests its argument + and if it fails, aborts the program. $(D assert) can be turned + on and off with the $(D NDEBUG) macro.) + + $(P $(D assert) does not know anything about class invariants, + and does not throw an exception when it fails. It just aborts + the program after writing a message. $(D assert) relies on + a macro text preprocessor to work.) + + $(P $(D assert) is where explicit support for Contracts in Standard C++ + begins and ends.) + +$(H3 $(LNAME2 class-invariant, Class Invariants)) + + Consider a class invariant in D: + +---------- +class A +{ + $(CODE_HIGHLIGHT invariant)() { ...contracts... } + + this() { ... } // constructor + ~this() { ... } // destructor + + void foo() { ... } // public member function +} + +class B : A +{ + $(CODE_HIGHLIGHT invariant)() { ...contracts... } + ... +} +---------- + + To accomplish the equivalent in C++ (thanks to Bob Bell for providing + this): + +$(CCODE +template +inline void check_invariant(T& iX) +{ +#ifdef DBC + iX.invariant(); +#endif +} + +// A.h: + +class A { + public: +#ifdef DBG + virtual void invariant() { ...contracts... } +#endif + void foo(); +}; + +// A.cpp: + +void A::foo() +{ + check_invariant(*this); + ... + check_invariant(*this); +} + +// B.h: + +#include "A.h" + +class B : public A { + public: +#ifdef DBG + virtual void invariant() + { ...contracts... + A::invariant(); + } +#endif + void bar(); +}; + +// B.cpp: + +void B::barG() +{ + check_invariant(*this); + ... + check_invariant(*this); +} +) + + There's an additional complication with $(D A::foo()). Upon every + normal exit from the function, the $(D invariant()) should be + called. + This means that code that looks like: + +$(CCODE +int A::foo() +{ + ... + if (...) + return bar(); + return 3; +} +) + + would need to be written as: + +$(CCODE +int A::foo() +{ + int result; + check_invariant(*this); + ... + if (...) + { + result = bar(); + check_invariant(*this); + return result; + } + check_invariant(*this); + return 3; +} +) + + Or recode the function so it has a single exit point. + One possibility to mitigate this is to use RAII techniques: + +$(CCODE +int A::foo() +{ +#if DBC + struct Sentry { + Sentry(A& iA) : mA(iA) { check_invariants(iA); } + ~Sentry() { check_invariants(mA); } + A& mA; + } sentry(*this); +#endif + ... + if (...) + return bar(); + return 3; +} +) + + The #if DBC is still there because some compilers may not + optimize the whole thing away if check_invariants compiles to nothing. + +$(H3 Preconditions and Postconditions) + + Consider the following in D: + +---------- +void foo() +in { ...preconditions... } +out { ...postconditions... } +body +{ + ...implementation... +} +---------- + + This is nicely handled in C++ with the nested Sentry struct: + +$(CCODE +void foo() +{ + struct Sentry + { + Sentry() { ...preconditions... } + ~Sentry() { ...postconditions... } + } sentry; + ...implementation... +} +) + + $(P If the preconditions and postconditions consist of nothing + more than $(D assert) macros, the whole doesn't need to + be wrapped in a $(D #ifdef) pair, since a good C++ compiler will + optimize the whole thing away if the $(D assert)s are turned off.) + + $(P But suppose $(D foo()) sorts an array, and the postcondition needs + to walk the array and verify that it really is sorted. Now + the shebang needs to be wrapped in $(D #ifdef):) + +$(CCODE +void foo() +{ +#ifdef DBC + struct Sentry + { + Sentry() { ...preconditions... } + ~Sentry() { ...postconditions... } + } sentry; +#endif + ...implementation... +} +) + + $(P (One can make use of the C++ rule that templates are only + instantiated when used can be used to avoid the $(D #ifdef), by + putting the conditions into a template function referenced + by the $(D assert).)) + + $(P Let's add a return value to $(D foo()) that needs to be checked in + the postconditions. In D:) + +---------- +int foo() +in { ...preconditions... } +out (result) { ...postconditions... } +body +{ + ...implementation... + if (...) + return bar(); + return 3; +} +---------- + + In C++: + +$(CCODE +int foo() +{ +#ifdef DBC + struct Sentry + { + int result; + Sentry() { ...preconditions... } + ~Sentry() { ...postconditions... } + } sentry; +#endif + ...implementation... + if (...) + { + int i = bar(); +#ifdef DBC + sentry.result = i; +#endif + return i; + } +#ifdef DBC + sentry.result = 3; +#endif + return 3; +} +) + + Now add a couple parameters to $(D foo()). In D: + +---------- +int foo(int a, int b) +in { ...preconditions... } +out (result) { ...postconditions... } +body +{ + ...implementation... + if (...) + return bar(); + return 3; +} +---------- + + In C++: + +$(CCODE +int foo(int a, int b) +{ +#ifdef DBC + struct Sentry + { + int a, b; + int result; + Sentry(int a, int b) + { + this->a = a; + this->b = b; + ...preconditions... + } + ~Sentry() { ...postconditions... } + } sentry(a, b); +#endif + ...implementation... + if (...) + { + int i = bar(); +#ifdef DBC + sentry.result = i; +#endif + return i; + } +#ifdef DBC + sentry.result = 3; +#endif + return 3; +} +) + +$(H3 $(LNAME2 pre-post-conditions, Preconditions and Postconditions for Member Functions)) + + Consider the use of preconditions and postconditions for a + polymorphic function in D: + +---------- +class A +{ + void foo() + in { ...Apreconditions... } + out { ...Apostconditions... } + body + { + ...implementation... + } +} + +class B : A +{ + void foo() + in { ...Bpreconditions... } + out { ...Bpostconditions... } + body + { + ...implementation... + } +} +---------- + + The semantics for a call to $(D B.foo()) are: + + $(UL + $(LI Either Apreconditions or Bpreconditions must be satisfied.) + $(LI Both Apostconditions and Bpostconditions must be satisfied.) + ) + + Let's get this to work in C++: + +$(CCODE +class A +{ +protected: + #if DBC + int foo_preconditions() { ...Apreconditions... } + void foo_postconditions() { ...Apostconditions... } + #else + int foo_preconditions() { return 1; } + void foo_postconditions() { } + #endif + + void foo_internal() + { + ...implementation... + } + +public: + virtual void foo() + { + foo_preconditions(); + foo_internal(); + foo_postconditions(); + } +}; + +class B : A +{ +protected: + #if DBC + int foo_preconditions() { ...Bpreconditions... } + void foo_postconditions() { ...Bpostconditions... } + #else + int foo_preconditions() { return 1; } + void foo_postconditions() { } + #endif + + void foo_internal() + { + ...implementation... + } + +public: + virtual void foo() + { + assert(foo_preconditions() || A::foo_preconditions()); + foo_internal(); + A::foo_postconditions(); + foo_postconditions(); + } +}; +) + + Something interesting has happened here. The preconditions can + no longer be done using $(D assert), since the results need + to be OR'd together. I'll leave as a reader exercise adding + in a class invariant, function return values for $(D foo()), + and parameters + for $(D foo()). + +$(H2 $(LNAME2 conclusion, Conclusion)) + + $(P These C++ techniques can work up to a point. But, aside from + $(D assert), they are not standardized and so will vary from + project to project. Furthermore, they require much tedious + adhesion to a particular convention, and add significant clutter + to the code. Perhaps that's why it's rarely seen in practice.) + + $(P By adding support for Contracts into the language, D offers an easy + way to use Contracts and get it right. Being in the language standardizes + the way it will be used from project to project.) + +$(H2 $(LNAME2 references, References)) + + $(P Chapter C.11 introduces the theory and rationale of + Contract Programming in + + Object-Oriented Software Construction +
+ Bertrand Meyer, Prentice Hall) + + $(P Chapters 24.3.7.1 to 24.3.7.3 discuss Contract Programming in C++ in + + The C++ Programming Language Special Edition +
+ Bjarne Stroustrup, Addison-Wesley) + +) + +Macros: + TITLE=D's Contract Programming vs C++'s + SUBNAV=$(SUBNAV_ARTICLES) + + diff --git a/articles/cpptod.dd b/articles/cpptod.dd new file mode 100644 index 0000000000..0d2b9f7fad --- /dev/null +++ b/articles/cpptod.dd @@ -0,0 +1,962 @@ +Ddoc + +$(COMMUNITY Programming in D for C++ Programmers, + +$(COMMENT img src="https://github.com/images/cpp1.gif" border="0" align="right" alt="C++") + +$(P Every experienced C++ programmer accumulates a series of idioms and techniques +which become second nature. Sometimes, when learning a new language, those +idioms can be so comfortable it's hard to see how to do the equivalent in the +new language. So here's a collection of common C++ techniques, and how to do the +corresponding task in D.) + +See also: Programming in D for C Programmers + +$(HEADERNAV_TOC) + +
$(COMMENT -------------------------------------------- ) + +$(H2 $(LNAME2 constructors, Defining constructors)) + +$(H4 The C++ Way) + + Constructors have the same name as the class: + +$(CPPCODE +class Foo +{ + Foo(int x); +}; +) + +$(H4 The D Way) + + Constructors are defined with the `this` keyword: + +------ +class Foo +{ + this(int x) { } +} +------ + + which reflects how they are used in D. + +
$(COMMENT -------------------------------------------- ) +$(H2 $(LNAME2 baseclass, Base class initialization)) + +$(H4 The C++ Way) + + Base constructors are called using the base initializer syntax. + +$(CPPCODE +class A { A() {... } }; +class B : A +{ + B(int x) + : A() // call base constructor + { + ... + } +};) + +$(H4 The D Way) + + The base class constructor is called with the `super` syntax: + +------ +class A { this() { ... } } +class B : A +{ + this(int x) + { + ... + super(); // call base constructor + ... + } +} +------ + + It's superior to C++ in that the base constructor call can be flexibly placed anywhere in the derived + constructor. D can also have one constructor call another one: + +------ +class A +{ + int a; + int b; + this() { a = 7; b = foo(); } + this(int x) + { + this(); + a = x; + } +} +------ + + Members can also be initialized to constants before the constructor is ever called, so the above example is + equivalently written as: + +------ +class A +{ + int a = 7; + int b; + this() { b = foo(); } + this(int x) + { + this(); + a = x; + } +} +------ + +
$(COMMENT -------------------------------------------- ) +$(H2 $(LNAME2 structcmp, Comparing structs)) + +$(H4 The C++ Way) + + While C++ defines struct assignment in a simple, convenient manner: + +$(CPPCODE +struct A x, y; +... +x = y; +) + + it does not for struct comparisons. Hence, to compare two struct + instances for equality: + +$(CPPCODE +#include <string.h> + +struct A x, y; + +inline bool operator==(const A& x, const A& y) +{ + return (memcmp(&x, &y, sizeof(struct A)) == 0); +} +... +if (x == y) + ... +) + + $(P Note that the operator overload must be done for every struct + needing to be compared, and the implementation of that overloaded + operator is free of any language help with type checking. + The C++ way has an additional problem in that just inspecting the + (x == y) does not give a clue what is actually happening, you have + to go and find the particular overloaded operator==() that applies + to verify what it really does.) + + $(P There's a nasty bug lurking in the memcmp() implementation of operator==(). + The layout of a struct, due to alignment, can have $(SINGLEQUOTE holes) in it. + C++ does not guarantee those holes are assigned any values, and so + two different struct instances can have the same value for each member, + but compare different because the holes contain different garbage.) + + $(P To address this, the operator==() can be implemented to do a memberwise + compare. Unfortunately, this is unreliable because (1) if a member is added + to the struct definition one may forget to add it to operator==(), and + (2) floating point nan values compare unequal even if their bit patterns + match.) + + There just is no robust solution in C++. + +$(H4 The D Way) + + D does it the obvious, straightforward way: + +------ +A x, y; +... +if (x == y) + ... +------ + +
$(COMMENT -------------------------------------------- ) +$(H2 $(LNAME2 typedefs, Creating a new typedef'd type)) + +$(H4 The C++ Way) + + Typedefs in C++ are weak, that is, they really do not introduce + a new type. The compiler doesn't distinguish between a typedef + and its underlying type. + +$(CPPCODE +#define HANDLE_INIT ((Handle)(-1)) +typedef void *Handle; +void foo(void *); +void bar(Handle); + +Handle h = HANDLE_INIT; +foo(h); // coding bug not caught +bar(h); // ok +) + + The C++ solution is to create a dummy struct whose sole + purpose is to get type checking and overloading on the new type. + +$(CPPCODE +#define HANDLE_INIT ((void *)(-1)) +struct Handle +{ + void *ptr; + + // default initializer + Handle() { ptr = HANDLE_INIT; } + + Handle(int i) { ptr = (void *)i; } + + // conversion to underlying type + operator void*() { return ptr; } +}; +void bar(Handle); + +Handle h; +bar(h); +h = func(); +if (h != HANDLE_INIT) + ... +) + +$(H4 The D Way) + + No need for idiomatic constructions like the above. + You can use $(REF Typedef, std,typecons): + +------ +alias Handle = Typedef!(void*, cast(void*)-1); +void bar(Handle); + +Handle h; +bar(h); +h = func(); +if (h != Handle.init) + ... +------ + + Unlike a bare $(D alias), using $(REF Typedef, std,typecons) + ensures the two types are not considered as equals. Note how a + default initializer can be supplied to $(REF Typedef, std,typecons) + as a value of the underlying type. + +
$(COMMENT -------------------------------------------- ) +$(H2 $(LNAME2 friends, Friends)) + +$(H4 The C++ Way) + + Sometimes two classes are tightly related but not by inheritance, + but need to access each other's private members. This is done + using $(D friend) declarations: + +$(CPPCODE +class A +{ + private: + int a; + + public: + int foo(B *j); + friend class B; + friend int abc(A *); +}; + +class B +{ + private: + int b; + + public: + int bar(A *j); + friend class A; +}; + +int A::foo(B *j) { return j->b; } +int B::bar(A *j) { return j->a; } + +int abc(A *p) { return p->a; } +) + +$(H4 The D Way) + + In D, friend access is implicit in being a member of the same + module. It makes sense that tightly related classes should be + in the same module, so implicitly granting friend access to + other module members solves the problem neatly: + +------ +module X; + +class A +{ + private: + static int a; + + public: + int foo(B j) { return j.b; } +} + +class B +{ + private: + static int b; + + public: + int bar(A j) { return j.a; } +} + +int abc(A p) { return p.a; } +------ + + The $(D private) attribute prevents other modules from + accessing the members. + +
$(COMMENT -------------------------------------------- ) +$(H2 $(LNAME2 operatoroverloading, Operator overloading)) + +$(H4 The C++ Way) + + Given a struct that creates a new arithmetic data type, + it's convenient to overload the comparison operators so + it can be compared against integers: + +$(CPPCODE +struct A +{ + int operator < (int i); + int operator <= (int i); + int operator > (int i); + int operator >= (int i); +}; + +int operator < (int i, A &a) { return a > i; } +int operator <= (int i, A &a) { return a >= i; } +int operator > (int i, A &a) { return a < i; } +int operator >= (int i, A &a) { return a <= i; } +) + + A total of 8 functions are necessary. + +$(H4 The D Way) + + D recognizes that the comparison operators are all fundamentally + related to each other. So only one function is necessary: + +------ +struct A +{ + int opCmp(int i); +} +------ + + $(P The compiler automatically interprets all the + <, <=, > and >= + operators in terms of the $(D cmp) function, as well + as handling the cases where the left operand is not an + object reference.) + + $(P Similar sensible rules hold for other operator overloads, + making using operator overloading in D much less tedious and less + error prone. Far less code needs to be written to accomplish + the same effect.) + +
$(COMMENT -------------------------------------------- ) +$(H2 $(LNAME2 usingdeclaration, Namespace using declarations)) + +$(H4 The C++ Way) + + A $(I using-declaration) in C++ is used to bring a name from + a namespace scope into the current scope: + +$(CPPCODE +namespace foo +{ + int x; +} +using foo::x; +) + +$(H4 The D Way) + + D uses modules instead of namespaces and #include files, and + alias declarations take the place of using declarations: + +------ +/** Module foo.d **/ +module foo; +int x; + +/** Another module **/ +import foo; +alias x = foo.x; +------ + + Alias is a much more flexible than the single purpose using + declaration. Alias can be used to rename symbols, refer to + template members, refer to nested class types, etc. + +
$(COMMENT -------------------------------------------- ) +$(H2 $(LNAME2 raii, RAII (Resource Acquisition Is Initialization))) + +$(H4 The C++ Way) + + In C++, resources like memory, etc., all need to be handled + explicitly. Since destructors automatically get called when + leaving a scope, RAII is implemented by putting the resource + release code into the destructor: + +$(CPPCODE +class File +{ + Handle *h; + + ~File() + { + h->release(); + } +}; +) + +$(H4 The D Way) + + $(P The bulk of resource release problems are simply keeping track + of and freeing memory. This is handled automatically in D by + the garbage collector. The second common resources used are semaphores + and locks, handled automatically with D's $(D synchronized) + declarations and statements.) + + $(P The few RAII issues left are handled by $(D struct)s. + A $(D struct) gets its destructor run when it goes out of scope.) + +------ +struct File +{ + Handle h; + + ~this() + { + h.release(); + } +} + +void test() +{ + if (...) + { + auto f = File(); + ... + } // f.~this() gets run at closing brace, even if + // scope was exited via a thrown exception +} +------ + +$(P $(D class)es are typically managed by the garbage collector which doesn't +lend itself to RAII. If you need deterministic destruction with $(D class)es +you can use $(REF scoped, std,typecons) (which will also allocate the +$(D class) on the stack instead of the garbage collector managed heap).) + +$(P See also $(GLINK2 statement, ScopeGuardStatement) for a more generalized +mechanism that lets you run arbitrary statements whenever leaving the current +scope.) + + +
$(COMMENT -------------------------------------------- ) +$(H2 $(LNAME2 properties, Properties)) + +$(H4 The C++ Way) + + It is common practice to define a field, + along with object-oriented + get and set functions for it: + +$(CPPCODE +class Abc +{ + public: + void setProperty(int newproperty) { property = newproperty; } + int getProperty() { return property; } + + private: + int property; +}; + +Abc a; +a.setProperty(3); +int x = a.getProperty(); +) + + All this is quite a bit of typing, and it tends to make + code unreadable by filling + it with getProperty() and setProperty() calls. + +$(H4 The D Way) + + Properties can be get and set using the normal field syntax, + yet the get and set will invoke methods instead. + +$(RUNNABLE_EXAMPLE +------ +class Abc +{ + // set + @property void property(int newproperty) { myprop = newproperty; } + + // get + @property int property() { return myprop; } + + private: + int myprop; +} + +Abc a = new Abc; +a.property = 3; +int x = a.property; +assert(x == 3); +------ +) + + Thus, in D a property is treated like it was a simple field name. + A property can start out actually being a simple field name, + but if later it becomes + necessary to make getting and setting it function calls, + no code needs to be modified other + than the class definition. + It obviates the wordy practice of defining get and set properties + $(SINGLEQUOTE just in case) a derived class should need to override them. + It's also a way to have interface classes, which do not have + data fields, behave syntactically as if they did. + +
$(COMMENT -------------------------------------------- ) +$(H2 $(LNAME2 recursivetemplates, Recursive Templates)) + +$(H4 The C++ Way) + + An advanced use of templates is to recursively expand + them, relying on specialization to end it. A template + to compute a factorial would be: + +$(CPPCODE +template<int n> class factorial +{ + public: + enum { result = n * factorial<n - 1>::result }; +}; + +template<> class factorial<1> +{ + public: + enum { result = 1 }; +}; + +void test() +{ + printf("%d\n", factorial<4>::result); // prints 24 +} +) + +$(H4 The D Way) + + The D version is analogous, though a little simpler, taking + advantage of + $(HTTPS dlang.org/spec/template.html#implicit_template_properties, + Eponymous Templates) - promotion of single template members to the + enclosing name space: + +$(RUNNABLE_EXAMPLE_COMPILE +------ +template factorial(int n) +{ + enum factorial = n * .factorial!(n-1); +} + +template factorial(int n : 1) +{ + enum factorial = 1; +} + +unittest +{ + import std.stdio; + writeln(factorial!(4)); // prints 24 +} +------ +) + The template blocks can be made shorter using + $(HTTPS dlang.org/spec/template.html#variable-template, + Enum Template) syntax: + +$(RUNNABLE_EXAMPLE_COMPILE +------ +enum factorial(int n) = n * .factorial!(n-1); + +enum factorial(int n : 1) = 1; + +static assert(factorial!(4) == 24); +------ +) + +
$(COMMENT -------------------------------------------- ) + +$(H2 $(LNAME2 metatemplates, Meta Templates)) + + The problem: create a typedef for a signed integral type that is at + least $(I nbits) in size. + +$(H4 The C++ Way) + + $(P This example is simplified and adapted from one written by + Dr. Carlo Pescio in + + Template Metaprogramming: Make parameterized integers portable with this novel technique.) + + $(P There is no way in C++ to do conditional compilation based + on the result of an expression based on template parameters, so + all control flow follows from pattern matching of the template + argument against various explicit template specializations. + Even worse, there is no way to do template specializations based + on relationships like "less than or equal to", so the example + uses a clever technique where the template is recursively expanded, + incrementing the template value argument by one each time, until + a specialization matches. + If there is no match, the result is an unhelpful recursive compiler + stack overflow or internal error, or at best a strange syntax + error.) + + A preprocessor macro is also needed to make up for the lack + of template typedefs. + +$(CPPCODE +#include <limits.h> + +template< int nbits > struct Integer +{ + typedef Integer< nbits + 1 > :: int_type int_type ; +}; + +struct Integer< 8 > +{ + typedef signed char int_type ; +}; + +struct Integer< 16 > +{ + typedef short int_type ; +}; + +struct Integer< 32 > +{ + typedef long int_type ; +}; + +struct Integer< 64 > +{ + typedef long long int_type ; +}; + +// If the required size is not supported, the metaprogram +// will increase the counter until an internal error is +// signaled, or INT_MAX is reached. The INT_MAX +// specialization does not define a int_type, so a +// compiling error is always generated +struct Integer< INT_MAX > +{ +}; + +// A bit of syntactic sugar +#define Integer( nbits ) Integer< nbits > :: int_type + +#include <stdio.h> + +int main() +{ + Integer( 8 ) i ; + Integer( 16 ) j ; + Integer( 29 ) k ; + Integer( 64 ) l ; + printf("%d %d %d %d\n", + sizeof(i), sizeof(j), sizeof(k), sizeof(l)); + return 0 ; +} +) + +$(H4 The C++ Boost Way) + + This version uses the C++ Boost library. It was provided + by David Abrahams. + +$(CPPCODE +#include <boost/mpl/if.hpp> +#include <boost/mpl/assert.hpp> + +template <int nbits> struct Integer + : mpl::if_c<(nbits <= 8), signed char + , mpl::if_c<(nbits <= 16), short + , mpl::if_c<(nbits <= 32), long + , long long>::type >::type > +{ + BOOST_MPL_ASSERT_RELATION(nbits, <=, 64); +} + +#include <stdio.h> + +int main() +{ + Integer< 8 > i ; + Integer< 16 > j ; + Integer< 29 > k ; + Integer< 64 > l ; + printf("%d %d %d %d\n", sizeof(i), sizeof(j), sizeof(k), sizeof(l)); + return 0 ; +} +) + +$(H4 The D Way) + + The D version could also be written with recursive templates, + but there's a better way. + Unlike the C++ example, this one is fairly easy to + figure out what is going on. + It compiles quickly, and gives a sensible compile time message + if it fails. + +$(RUNNABLE_EXAMPLE +------ +import std.stdio; + +template Integer(int nbits) +{ + static if (nbits <= 8) + alias Integer = byte; + else static if (nbits <= 16) + alias Integer = short; + else static if (nbits <= 32) + alias Integer = int; + else static if (nbits <= 64) + alias Integer = long; + else + static assert(0); +} + +int main() +{ + Integer!(8) i ; + Integer!(16) j ; + Integer!(29) k ; + Integer!(64) l ; + writefln("%d %d %d %d", i.sizeof, j.sizeof, k.sizeof, l.sizeof); + return 0; +} +------ +) + +
$(COMMENT -------------------------------------------- ) + +$(H2 $(LNAME2 typetraits, Type Traits)) + + Type traits are another term for being able to find out + properties of a type at compile time. + +$(H4 The C++ Way) + + The following template comes from + + C++ Templates: The Complete Guide, David Vandevoorde, Nicolai M. Josuttis + pg. 353 which determines if the template's argument type + is a function: + +$(CPPCODE +template<typename T> class IsFunctionT +{ + private: + typedef char One; + typedef struct { char a[2]; } Two; + template<typename U> static One test(...); + template<typename U> static Two test(U (*)[1]); + public: + enum { Yes = sizeof(IsFunctionT<T>::test<T>(0)) == 1 }; +}; + +void test() +{ + typedef int (fp)(int); + + assert(IsFunctionT<fp>::Yes == 1); +} +) + + This template relies on the $(SFINAE) principle. + Why it works is a fairly advanced template topic. + +$(H4 The D Way) + + $(ACRONYM SFINAE, Substitution Failure Is Not An Error) + can be done in D without resorting to template argument + pattern matching: + +$(RUNNABLE_EXAMPLE_COMPILE +------ +template IsFunctionT(T) +{ + static if ( is(T[]) ) + const int IsFunctionT = 0; + else + const int IsFunctionT = 1; +} + +unittest +{ + alias int fp(int); + + static assert(IsFunctionT!(fp) == 1); +} +------ +) + + The task of discovering if a type is a function doesn't need a + template at all, nor does it need the subterfuge of attempting to + create the invalid array of functions type. + The $(ISEXPRESSION) expression can test it directly: + +$(RUNNABLE_EXAMPLE_COMPILE +------ +unittest +{ + alias int fp(int); + + static assert( is(fp == function) ); +} +------ +) + +$(HR) + +$(H2 $(LNAME2 interfaces, Interfaces)) + + +Interfaces in C++ are used to describe the behaviour or capabilities of any class +that implements the interface, without committing to a particular implementation +of the interface's declared methods. + +$(H4 Interfaces in C++) + + "C++ interfaces are implemented by means of $(I abstract classes). An abstract class + defines interface methods as pure virtual functions. A class implementing the interface + inherits from the abstract class and implements its pure virtual functions." + +$(CPPCODE +class Interface { + public: + virtual int method() = 0; +}; + +class FirstVariant : public Interface { + public: + int method() { + ... + } +}; + +class SecondVariant : public Interface { + public: + int method() { + ... + } +}; +) + +The interface is used as follows: + +$(CPPCODE +FirstVariant FirstVariant; +SecondVariant SecondVariant; + +FirstVariant.method(); +SecondVariant.method(); +) + +$(H4 Interfaces in D) + + In D, interfaces $(HTTPS wiki.dlang.org/Books, Alexandrescu 2010$(COMMA) p. 212; Cehreli 2017$(COMMA) p. 347) + are implemented with the help of the `interface` keyword, which introduces a class containing + mainly unimplemented method declarations (non-static method definitions and non-static data + members are not allowed). The implementation class inherits one or more interfaces and + implements the interface methods. + +------ +interface Interface { + int method(); +} + +class FirstVariant : Interface { + int method() { + ... + } +} + +class SecondVariant : Interface { + int method() { + ... + } +} +------ + + The interface is used as follows: + +------ +FirstVariant FirstVariant = new FirstVariant(); +SecondVariant SecondVariant = new SecondVariant(); + +FirstVariant.method(); +SecondVariant.method(); +------ + + +
$(COMMENT -------------------------------------------- ) + +$(H2 $(LNAME2 references, References in D)) + + + D doesn't have a (C++-style) concept of references as part of the type. Arguments can be passed by reference - hence the `ref` keyword, but "free" references don't exist in the language. + + The `ref` in `foreach` loop variables can be conceptually thought of as a parameter to the loop body as well. (For `opApply` based iteration, the loop body indeed gets turned into a function; for "plain" iteration the compiler AST internally has special `ref` variables, but they are not visible to the language.) + + In the below code, `d2` is a value copy of `gallery[0]` and is not a reference. + +$(RUNNABLE_EXAMPLE +------ +module test; + +void main() +{ + struct Data + { + int id; + } + + import std.container.array : Array; + Array!Data gallery; + + Data d1; + gallery.insertBack(d1); + + auto d2 = gallery[0]; + d2.id = 1; + assert(d2.id != gallery[0].id); // d2 is neither ref nor pointer +} +------ +) + + Instead of trying to get a reference in such a case, get a pointer. After all, you don't have to use `->` operator in D, which is nice in syntax. + +------ + auto d2 = &gallery[0]; + d2.id = 1; + assert(d2.id == gallery[0].id); +------ + +) + +Macros: + TITLE=Programming in D for C++ Programmers + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/articles/ctarguments.dd b/articles/ctarguments.dd new file mode 100644 index 0000000000..a891c2aed0 --- /dev/null +++ b/articles/ctarguments.dd @@ -0,0 +1,295 @@ +Ddoc + +$(D_S $(TITLE), + +$(HEADERNAV_TOC) + + $(H2 $(LNAME2 Background, Background)) + + $(P Compile-time sequences are an important metaprogramming concept that comes naturally + from D support for $(LINK2 variadic-function-templates.html, variadic templates). They + allow a programmer to operate on types, symbols and values, enabling the ability to define + compile-time algorithms that operate on types, symbols and values. + ) + + $(P $(B Note:) For historical reasons these sequences can sometimes be called tuples in documentation or compiler + internals, but don't get confused - they don't have much in common with tuples that + commonly exist in other languages. Sequences of values of different types that can be + returned from functions are provided by $(REF Tuple, std, typecons). + Using the term "tuple" to mean compile-time sequences is discouraged to avoid confusion, and if encountered + should result in a $(LINK2 https://issues.dlang.org, documentation bug report). + ) + + $(P Consider this simple variadic template:) + + --- + template Variadic(T...) { /* ... */ } + --- + + $(P `T` here is a $(DDSUBLINK spec/template, variadic-templates, TemplateParameterSequence), + which is a core language feature. It has its own special semantics, + and, from the programmer's point of view, is most similar to an array of compile-time entities - types, + symbols (names) and values. One can check the length of this sequence + and access any individual element: + ) + + --- + template Variadic(T...) + { + static assert(T.length > 1); + pragma(msg, T[0]); + pragma(msg, T[1]); + } + + alias dummy = Variadic!(int, 42); + --- + $(P Output during compilation:) +$(CONSOLE +int +42 +) + + $(H2 $(LNAME2 AliasSeq, AliasSeq)) + + $(P The language itself does not provide any means to define such sequences outside of + a template parameter declaration. Instead, there is a + $(REF_ALTTEXT simple template, AliasSeq, std,meta) provided by the standard + library: + ) + + --- + alias AliasSeq(T...) = T; + --- + + $(P All it does is give a specific variadic argument sequence an externally accessible name so + that it can be worked with in any other context: + ) + + --- + import std.meta; + // can alias to some other name + alias Name = AliasSeq!(int, 42); + pragma(msg, Name[0]); // int + pragma(msg, Name[1]); // 42 + // or work with a sequence directly + pragma(msg, AliasSeq!("aaa", 0, double)[2]); // double + --- + +$(H2 $(LNAME2 available-operations, Available operations)) + + $(H3 $(LNAME2 checking-length, Checking the length)) + + --- + import std.meta; + static assert(AliasSeq!(1, 2, 3, 4).length == 4); + --- + + $(H3 $(LNAME2 indexing-slicing, Indexing and slicing)) + + $(P Indexes must be known at compile-time) + + --- + import std.meta; + + alias nums = AliasSeq!(1, 2, 3, 4); + static assert(nums[1] == 2); + + // slice last 3 elements + alias tail = nums[1 .. $]; + static assert(tail[0] == 2); + static assert(tail.length == 3); + --- + + $(H4 $(LNAME2 assignment, Element assignment)) + + $(P Works only if the sequence element is a symbol that refers to a mutable variable) + + --- + import std.meta; + + void main() + { + int x; + alias seq = AliasSeq!(10, x); + seq[1] = 42; + assert(x == 42); + // seq[0] = 42; // won't compile, can't assign to a constant + } + --- + + $(H3 $(LNAME2 loops, `foreach`)) + + $(P D's $(DDSUBLINK spec/statement, ForeachStatement, foreach statement) has special + semantics when iterating over compile-time sequences. It repeats the body of the loop + for each of the sequence elements, with the loop iteration symbol being an alias + for each compile-time sequence element in turn. + ) + + --- + import std.meta; + + void main() + { + foreach (sym; AliasSeq!(int, "literal", main)) + { + static if (is(sym)) + pragma (msg, sym); + else + pragma (msg, typeof(sym)); + } + } + --- + $(P Output during compilation:) +$(CONSOLE +int +string +void() +) + + $(P $(B Note:) $(DDSUBLINK spec/version, staticforeach, Static foreach) + should be preferred in new code.) + +$(H2 $(LNAME2 auto-expansion, Auto-expansion)) + + $(P One less obvious property of compile-time argument sequences is that when used + as an argument to a function or template, they are automatically treated as a sequence + of comma-separated arguments: + ) + + --- + import std.meta; + + template Print0(T...) + { + pragma(msg, T[0]); + } + + alias Dummy = Print0!(AliasSeq!(int, double)); + --- + + $(P This will only print `int` during compilation because the last line gets rewritten + as `alias Dummy = Print0!(int, double)`. If auto-expansion didn't happen, + `AliasSeq!(int, double)` would be printed instead. This is an inherent part of + the language semantics for variadic sequences, and thus also preserved by `AliasSeq`. + ) + +$(H2 $(LEGACY_LNAME2 homogenous-lists, homogenous-sequences, Homogenous sequences)) + + $(P An $(ALOCAL AliasSeq, AliasSeq) that consists of only type or value elements are + commonly called "type sequences" or "value sequences" respectively. The concept of + a "symbol sequence" is used less frequently but fits the same pattern. + ) + +$(H3 $(LNAME2 type-seq, Type sequences)) + + $(P It is possible to use homogenous type sequences in declarations:) + + --- + import std.meta; + alias Params = AliasSeq!(int, double, string); + void foo(Params); // void foo(int, double, string); + + foo(7, 6.5, "hi"); + --- + +$(H3 $(LNAME2 type-seq-instantiation, Type sequence instantiation)) + + $(P D supports a special variable declaration syntax where a type sequence acts as a type:) + + --- + import std.meta; + + void foo() + { + AliasSeq!(int, double, string) variables; + variables[0] = 42; + variables[1] = 42.0; + variables[2] = "just a normal variable"; + } + --- + $(P The compiler will rewrite such a declaration to something like this:) + --- + int __var1; + double __var2; + string __var3; + alias variables = AliasSeq!(__var1, __var2, __var3); + --- + + $(P So a type sequence instance is a kind of symbol sequence that only aliases + variables, known as an $(I lvalue sequence).) + + $(P $(DDSUBLINK spec/template, variadic-templates, Variadic template functions) + use a type sequence instance to declare function parameters:) + + --- + void foo(T...)(T args) + { + // 'T' is a type sequence of argument types. + // 'args' is an instance of T whose elements are the function parameters + static assert(is(typeof(args) == T)); + args[0] = T[0].init; + } + --- + +$(H3 $(LNAME2 value-seq, Value sequences)) + + $(P It is possible to use a sequence of values of the same type to declare an array literal:) + + --- + import std.meta; + enum e = 3; + enum arr = [ AliasSeq!(1, 2, e) ]; + static assert(arr == [ 1, 2, 3 ]); + --- + + $(P The above sequence is an $(I rvalue sequence), as it is comprised only of literal values + and manifest constants. Each element's value is known at compile-time.) + + $(P The following demonstrates use of an $(I lvalue sequence):) + --- + import std.meta, std.algorithm; + auto x = 3, y = 7; + alias pair = AliasSeq!(x, y); + swap(pair); + assert(x == 7 && y == 3); + --- + $(P As above, such sequences may use + $(ALOCAL assignment, element assignment).) + + $(P $(DDSUBLINK spec/class, class_properties, `.tupleof`) is a + class/struct instance property that provides an lvalue sequence + of each field.) + + $(P A function cannot return a value sequence. Instead, + $(REF Tuple, std, typecons) can be used. It wraps an lvalue + sequence in a struct, preventing auto-expansion.) + +$(H3 $(LNAME2 symbol-seq, Symbol sequences)) + +$(P A symbol sequence aliases any named symbol - types, variables, functions and templates - +but not literals. +Like an alias sequence, the kind of elements can be mixed.) + +--- +import std.meta : AliasSeq; + +void f(T)(T v) +{ + pragma(msg, T); +} +alias syms = AliasSeq!(f, f!byte); +syms[0](42); // call f!int with IFTI +syms[1](42); // call f!byte +--- +$(P Output during compilation:) +$(CONSOLE +byte +int +) +$(P Note that function `f!byte` is instantiated when the sequence is +created, not at the call-site.) +) + +Macros: + TITLE=Compile-time Sequences + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/articles/ctod.dd b/articles/ctod.dd new file mode 100644 index 0000000000..63aa02924c --- /dev/null +++ b/articles/ctod.dd @@ -0,0 +1,1639 @@ +Ddoc + +$(COMMUNITY Programming in D for C Programmers, + +$(HEADERNAV_TOC) + +$(COMMENT $(BLOCKQUOTE_BY William Nerdspeare, +Et tu, D? Then fall, C! +)) + +$(COMMENT img src="https://github.com/images/c1.gif" border="0" align="right" alt="ouch!") + +$(P Every experienced C programmer accumulates a series of idioms and techniques +which become second nature. Sometimes, when learning a new language, those +idioms can be so comfortable it's hard to see how to do the equivalent in the +new language. So here's a collection of common C techniques, and how to do the +corresponding task in D. +) + +$(P Since C does not have object-oriented features, there's a separate section +for object-oriented issues +Programming in D for C++ Programmers. +) + +$(P The C preprocessor is covered in +$(LINK2 pretod.html, The C Preprocessor vs D). +) + +
$(COMMENT -------------------------------------------- ) +$(H2 $(LNAME2 sizeof, Getting the Size of a Type)) + +$(H4 The C Way) + +$(CCODE +sizeof(int) +sizeof(char *) +sizeof(double) +sizeof(struct Foo) +) + +$(H4 The D Way) + +$(P Use the `sizeof` property:) + +---------------------------- +int.sizeof +(char *).sizeof +double.sizeof +Foo.sizeof +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 maxmin, Get the max and min values of a type)) + +$(H4 The C Way) + +$(CCODE +#include <limits.h> +#include <math.h> + +CHAR_MAX +CHAR_MIN +ULONG_MAX +DBL_MIN +) + +$(H4 The D Way) + +---------------------------- +char.max +char.min +ulong.max +double.min +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 types, Primitive Types)) + +$(H4 C to D types) + +$(CCODE +bool => bool +char => char +signed char => byte +unsigned char => ubyte +short => short +unsigned short => ushort +wchar_t => core.stdc.stddef.wchar_t +int => int +unsigned => uint +long => core.stdc.config.c_long +unsigned long => core.stdc.config.c_ulong +long long => long +unsigned long long => ulong +float => float +double => double +long double => real +_Imaginary long double => ireal +_Complex long double => creal +) +$(P + Although `char` is an unsigned 8-bit type, and + `wchar` is an unsigned 16-bit type, they have their own separate types + in order to aid overloading and type safety. +) +$(P Ints and unsigneds in C are of varying size; not so in D.) + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 floating, Special Floating Point Values)) + +$(H4 The C Way) + +$(CCODE +#include <fp.h> + +NAN +INFINITY + +#include <float.h> + +DBL_DIG +DBL_EPSILON +DBL_MANT_DIG +DBL_MAX_10_EXP +DBL_MAX_EXP +DBL_MIN_10_EXP +DBL_MIN_EXP +) + +$(H4 The D Way) + +---------------------------- +double.nan +double.infinity +double.dig +double.epsilon +double.mant_dig +double.max_10_exp +double.max_exp +double.min_10_exp +double.min_exp +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 modulus, Remainder after division of floating point numbers)) + +$(H4 The C Way) + +$(CCODE +#include <math.h> + +float f = fmodf(x,y); +double d = fmod(x,y); +long double r = fmodl(x,y); +) + +$(H4 The D Way) + +D supports the remainder (`%`) operator on floating point operands: + +---------------------------- +float f = x % y; +double d = x % y; +real r = x % y; +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 nans, Dealing with NANs in floating point compares)) + +$(H4 The C Way) + + C doesn't define what happens if an operand to a compare + is `NAN`, and few C compilers check for it (the Digital Mars + C compiler is an exception, DM's compilers do check for `NAN` operands). + +$(CCODE +#include <math.h> + +if (isnan(x) || isnan(y)) + result = false; +else + result = (x < y); +) + +$(H4 The D Way) + + D offers a full complement of comparisons and operators + that work with NAN arguments. + +---------------------------- +result = (x < y); // false if x or y is nan +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 assert, Asserts are a necessary part of any good defensive coding strategy)) + +$(H4 The C Way) +$(P C doesn't directly support assert in the language, but does define a macro +in the standard library header assert.h. That macro writes a diagnostic message +on stderr when the condition given as parameter is not true. The message will +use __FILE__, __LINE__ and __func__ (C99) to localize the failing assertion.) + +$(CCODE +#include <assert.h> + +assert(e == 0); +) + +$(H4 The D Way) + +D simply builds assert into the language: + +---------------------------- +assert(e == 0); +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 arrayinit, Initializing all elements of an array)) + +$(H4 The C Way) + +$(CCODE +#define ARRAY_LENGTH 17 +int array[ARRAY_LENGTH]; +for (i = 0; i < ARRAY_LENGTH; i++) + array[i] = value; +) + +$(H4 The D Way) + +---------------------------- +int[17] array; +array[] = value; +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 arrayloop, Looping through an array)) + +$(H4 The C Way) +$(P + The array length is defined separately, or a clumsy and error prone + `sizeof()` expression is used to get the length.) + +$(CCODE +#define ARRAY_LENGTH 17 +int array[ARRAY_LENGTH]; +for (size_t i = 0; i < ARRAY_LENGTH; i++) + func(array[i]); +) + +or: + +$(CCODE +int array[17]; +for (size_t i = 0; i < sizeof(array) / sizeof(array[0]); i++) + func(array[i]); +) + +$(H4 The D Way) + +The length of an array is accessible through the `length` property. + +---------------------------- +int[17] array; +foreach (i; 0 .. array.length) + func(array[i]); +---------------------------- + +or even better (for value access): + +---------------------------- +int[17] array; +foreach (int value; array) + func(value); +---------------------------- + +In D, the element type can be inferred even without using an explicit type qualifier: + +---------------------------- +int[17] array; +foreach (value; array) + func(value); +---------------------------- + +or through the `ref` keyword (for reference access): + +---------------------------- +int[17] array; +foreach (ref value; array) + value += 42; +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 arraycreate, Creating an array of variable size)) + +$(H4 The C Way) + + C cannot do this with arrays. It is necessary to create a separate + variable for the length, and then explicitly manage the size of + the array: + +$(CCODE +#include <stdlib.h> + +int array_length; +int *array; +int *newarray; + +newarray = realloc(array, (array_length + 1) * sizeof(int)); +if (!newarray) + error("out of memory"); +array = newarray; +array[array_length++] = x; +) + +$(H4 The D Way) + + D supports dynamic arrays, which can be easily resized. D supports + all the requisite memory management. + +---------------------------- +int[] array; +int x; +array.length = array.length + 1; +array[array.length - 1] = x; +---------------------------- + +or simply: + +---------------------------- +int[] array; +int x; +array ~= x; +---------------------------- + + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 strcat, String Concatenation)) + +$(H4 The C Way) + + There are several difficulties to be resolved, like + when can storage be freed, dealing with null pointers, + finding the length of the strings, and memory allocation: + +$(CCODE +#include <string.h> + +char *s1; +char *s2; +char *s; + +// Concatenate s1 and s2, and put result in s +s = malloc((s1 ? strlen(s1) : 0) + + (s2 ? strlen(s2) : 0) + 1); +if (!s) + error("out of memory"); +if (s1) + strcpy(s, s1); +else + *s = 0; +if (s2) + strcpy(s + strlen(s), s2); + +// Append "hello" to s +char hello[] = "hello"; +size_t lens = s ? strlen(s) : 0; +char *news = realloc(s, lens + sizeof(hello) + 1); +if (!news) + error("out of memory"); +s = news; +memcpy(s + lens, hello, sizeof(hello)); +) + +$(H4 The D Way) + + D overloads the operators `~` and `~=` for char and wchar arrays to mean + concatenate and append, respectively: + +---------------------------- +string s1; +string s2; +string s; + +s = s1 ~ s2; +s ~= "hello"; +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 printf, Formatted printing)) + +$(H4 The C Way) + + printf() is the general purpose formatted print routine: + +$(CCODE +#include <stdio.h> + +printf("Calling all cars %d times!\n", ntimes); +) + +$(H4 The D Way) + + What can we say? printf() rules: + +---------------------------- +printf("Calling all cars %d times!\n", ntimes); +---------------------------- + + writefln() improves on printf() by being type-aware and type-safe: + +----------------------- +import std.stdio; + +writefln("Calling all cars %s times!", ntimes); +----------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 forwardfunc, Forward referencing functions)) + +$(H4 The C Way) + + Functions cannot be forward referenced. Hence, to call a function + not yet encountered in the source file, it is necessary to insert + a function declaration lexically preceding the call. + +$(CCODE +void forwardfunc(); + +void myfunc() +{ + forwardfunc(); +} + +void forwardfunc() +{ + ... +} +) + +$(H4 The D Way) + + The program is looked at as a whole, and so not only is it not + necessary to code forward declarations, it is not even allowed! + D avoids the tedium and errors associated with writing forward + referenced function declarations twice. + Functions can be defined in any order. + +---------------------------- +void myfunc() +{ + forwardfunc(); +} + +void forwardfunc() +{ + ... +} +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 funcvoid, Functions that have no arguments)) + +$(H4 The C Way) + +$(CCODE +void foo(void); +) + +$(H4 The D Way) + + D is a strongly typed language, so there is no need to explicitly + say a function takes no arguments, just don't declare it as having + arguments. + +---------------------------- +void foo() +{ + ... +} +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 labeledbreak, Labeled break and continue statements)) + +$(H4 The C Way) + + Break and continue statements only apply to the innermost nested loop or + switch, so a multilevel break must use a goto: + +$(CCODE + for (i = 0; i < 10; i++) + { + for (j = 0; j < 10; j++) + { + if (j == 3) + goto Louter; + if (j == 4) + goto L2; + } + L2: + ; + } + +Louter: + ; +) + +$(H4 The D Way) + + Break and continue statements can be followed by a label. The label + is the label for an enclosing loop or switch, and the break applies + to that loop. + +---------------------------- +Louter: + for (i = 0; i < 10; i++) + { + for (j = 0; j < 10; j++) + { + if (j == 3) + break Louter; + if (j == 4) + continue Louter; + } + } + // break Louter goes here +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 goto, Goto Statements)) + +$(H4 The C Way) + + The much maligned goto statement is a staple for professional C coders. + It's + necessary to make up for sometimes inadequate control flow statements. + +$(H4 The D Way) + + Many C-way goto statements can be eliminated with the D feature of + labeled + break and continue statements. But D is a practical language for + practical + programmers who know when the rules need to be broken. So of course D + supports goto statements. + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 tagspace, Struct tag name space)) + +$(H4 The C Way) + + It's annoying to have to use the `struct` keyword every time a type is specified, + so a common idiom is to use: + +$(CCODE +typedef struct ABC { ... } ABC; +) + +$(H4 The D Way) + + Struct tag names are not in a separate name space, they are in the same name + space as ordinary names. Hence: + +---------------------------- +struct ABC { ... } +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 stringlookup, Looking up strings)) + +$(H4 The C Way) + + Given a string, compare the string against a list of possible + values and take action based on which one it is. A typical use + for this might be command line argument processing. + +$(CCODE +#include <string.h> +void dostring(char *s) +{ + enum Strings { Hello, Goodbye, Maybe, Max }; + static char *table[] = { [Hello] ="hello", + [Goodbye]="goodbye", + [Maybe] ="maybe" }; + int i; + + for (i = 0; i < Max; i++) + { + if (strcmp(s, table[i]) == 0) + break; + } + switch (i) + { + case Hello: ... + case Goodbye: ... + case Maybe: ... + default: ... + } +} +) + + The problem with this is trying to maintain 3 parallel data + structures, the enum, the table, and the switch cases. If there + are a lot of values, the connection between the 3 may not be so + obvious when doing maintenance, and so the situation is ripe for + bugs. Designated initializers as were introduced with C99 allow + to link correctly 2 of the 3 data structures, but at the cost of + a lot of typing. + + Additionally, if the number of values becomes large, a binary or + hash lookup will yield a considerable performance increase over + a simple linear search. But coding these can be time consuming, + and they need to be debugged. It's typical that such just never + gets done. + +$(H4 The D Way) + + D extends the concept of switch statements to be able to handle + strings as well as numbers. Then, the way to code the string + lookup becomes straightforward: + +---------------------------- +void dostring(string s) +{ + switch (s) + { + case "hello": ... + case "goodbye": ... + case "maybe": ... + default: ... + } +} +---------------------------- + + Adding new cases becomes easy. The compiler can be relied on + to generate a fast lookup scheme for it, eliminating the bugs + and time required in hand-coding one. + + Another possibility of associating a string to a number is to + use an associative array. + +$(RUNNABLE_EXAMPLE_COMPILE +---------------------------- +ulong[string] map = ["hello" : 1616515, + "goodbye" : 42, + "maybe" : ulong.max + ]; +unittest +{ + import std.stdio; + writeln("number is ", map["goodbye"]); + writeln(i"map contains $(map.length) elements"); + writeln("map is ", map); +} +---------------------------- +) + + Any type can be used as key or as value. + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 align, Setting struct member alignment)) + +$(H4 The C Way) + + It's done through a command line switch which affects the entire + program, and woe results if any modules or libraries didn't get + recompiled. To address this, $(D #pragma)s are used: + +$(CCODE +#pragma pack(1) +struct ABC +{ + ... +}; +#pragma pack() +) + + But $(D #pragma)s are nonportable both in theory and in practice from + compiler to compiler. + +$(H4 The D Way) + + $(P D has a syntax for setting the alignment that is common + to all D compilers. The actual alignment done is compatible + with the companion C compiler's alignment, for ABI compatibility. + To match a particular layout across architectures, use + $(D align(1)) and manually specify it. + ) + +---------------------------- +struct ABC +{ + int z; // z is aligned to the default + + align (1) int x; // x is byte aligned + align (4) + { + ... // declarations in {} are 32-bit aligned + } + align (2): // switch to 16-bit alignment from here on + + int y; // y is 16-bit aligned +} +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 anonymous, Anonymous Structs and Unions)) + +Sometimes, it's nice to control the layout of a struct with nested structs and unions. + +$(H4 The C Way) + + Before C11 C didn't allow for anonymous structs or unions, which meant that + dummy member names were necessary: + +$(CCODE +struct Foo +{ + int i; + union + { + struct { int x; long y; } abc; + char *p; + } bar; +}; + +#define x bar.abc.x +#define y bar.abc.y +#define p bar.p + +struct Foo f; + +f.i; +f.x; +f.y; +f.p; +) + + Not only is it clumsy, but using macros means a symbolic debugger won't understand + what is being done, and the macros have global scope instead of struct scope. + +$(H4 The D Way) + + Anonymous structs and unions are used to control the layout in a + more natural manner: + +---------------------------- +struct Foo +{ + int i; + union + { + struct { int x; long y; } + char* p; + } +} + +Foo f; + +f.i; +f.x; +f.y; +f.p; +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 declaring, Declaring struct types and variables)) + +$(H4 The C Way) + + $(P Is to do it in one statement ending with a semicolon:) + +$(CCODE +struct Foo { int x; int y; } foo; +) + + $(P Or to separate the two:) + +$(CCODE +struct Foo { int x; int y; }; // note terminating ; +struct Foo foo; +) + +$(H4 The D Way) + + $(P Struct definitions and declarations can't be done in the same + statement: + ) + +---------------------------- +struct Foo { int x; int y; } // note there is no terminating ; +Foo foo; +---------------------------- + + $(P which means that the terminating ; can be dispensed with, + eliminating the confusing difference between struct {} and function + block {} in how semicolons are used. + ) + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 fieldoffset, Getting the offset of a struct member)) + +$(H4 The C Way) + + Naturally, another macro is used: + +$(CCODE +#include <stddef> +struct Foo { int x; int y; }; + +off = offsetof(Foo, y); +) + +$(H4 The D Way) + + An offset is just another property: + +---------------------------- +struct Foo { int x; int y; } + +off = Foo.y.offsetof; +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 unioninit, Union Initializations)) + +$(H4 The C Way) + + Unions are initialized using the "first member" rule: + +$(CCODE +union U { int a; long b; }; +union U x = { 5 }; // initialize member 'a' to 5 +union U y = { .b = 42l }; // initialize member 'b' to 42 (C99) + +) + + Adding union members or rearranging them can have disastrous consequences + for any initializers. Designated initializers in C99 fix that issue. + +$(H4 The D Way) + + In D, which member is being initialized is mentioned explicitly: + +---------------------------- +union U { int a; long b; } +U x = { a:5 }; +---------------------------- + + avoiding the confusion and maintenance problems. + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 structinit, Struct Initializations)) + +$(H4 The C Way) + + Members are initialized by their position within the { }s: + +$(CCODE +struct S { int a; int b; }; +struct S x = { 5, 3 }; +struct S y = { .b=3, .a=5 }; /* C99 */ +) + + This isn't much of a problem with small structs, but when there + are numerous members, it becomes tedious to get the initializers + carefully lined up with the field declarations. Then, if members are + added or rearranged, all the initializations have to be found and + modified appropriately. This is a minefield for bugs. Designated + initializers in C99 fix that issue. + +$(H4 The D Way) + + Member initialization can be done explicitly: + +---------------------------- +struct S { int a; int b; } +S x = { b:3, a:5 }; +---------------------------- + + The meaning is clear, and there no longer is a positional dependence. + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 arrayinit2, Array Initializations)) + +$(H4 The C Way) + + C initializes arrays by positional dependence. C99 fixes the issue: +$(CCODE +int a[3] = { 3,2,1 }; +int a[3] = { [2]=1, [0]=3, [1]=2 }; /* C99 designated initializer \*/ +int a[3] = { [2]=1, [0]=3, 2 }; /* C99 designated initializer \*/ +) + Nested arrays may or may not have the { }: +$(CCODE +int b[3][2] = { 2,3, {6,5}, 3,4 }; +) + +$(H4 The D Way) + + D does it by positional dependence too, but an index can be used as well. + The D syntax is lighter than C99 designated initializers. + The following all produce the same result: + +---------------------------- +int[3] a = [ 3, 2, 0 ]; +int[3] a = [ 3, 2 ]; // unsupplied initializers are 0, just like in C +int[3] a = [ 2:0, 0:3, 1:2 ]; +int[3] a = [ 2:0, 0:3, 2 ]; // if not supplied, the index is the + // previous one plus one. +---------------------------- + + This can be handy if the array will be indexed by an enum, and the order of + enums may be changed or added to: + +---------------------------- +enum color { black, red, green } +int[3] c = [ black:3, green:2, red:5 ]; +---------------------------- + + Nested array initializations must be explicit and consistent with the + array types: + +---------------------------- +int[2][3] b = [ [2,3], [6,5], [3,4] ]; + +int[2][3] b = [[2,6,3],[3,5,4]]; // error +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 stringlit, Escaped String Literals)) + +$(H4 The C Way) + + C has problems with the DOS file system because a \ is an escape in a string. + To specifiy the file c:\root\file.c you would use: +```c +char file[] = "c:\\root\\file.c"; +``` +This gets even more unpleasant with regular expressions. +Consider the escape sequence to match a quoted string: +```c +/"[^\\]*(\\.[^\\]*)*"/ +``` +$(P In C, this horror is expressed as:) +```c +char quoteString[] = "\"[^\\\\]*(\\\\.[^\\\\]*)*\""; +``` +$(H4 The D Way) + + D has both C-style string literals which can use escaping, + and WYSIWYG (what you see is what you get) raw strings, + usable with the `$(BACKTICK)foo$(BACKTICK)` and `r"bar"` syntax: + +---------------------------- +string file = r"c:\root\file.c"; // c:\root\file.c +string quotedString = `"[^\\]*(\\.[^\\]*)*"`; // "[^\\]*(\\.[^\\]*)*" +---------------------------- + + The famous hello world string becomes: + +---------------------------- +string hello = "hello world\n"; +---------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 ascii, ASCII versus Wide Characters)) + +$(P Modern programming requires that wchar strings be supported in an easy way, for internationalization of the programs.) + +$(H4 The C Way) + + C uses the wchar_t and the L prefix on strings: +$(CCODE +#include <wchar.h> +char foo_ascii[] = "hello"; +wchar_t foo_wchar[] = L"hello"; +) +Things get worse if code is written to be both ascii and wchar compatible. +A macro is used to switch strings from ascii to wchar: +$(CCODE +#include <tchar.h> +tchar string[] = TEXT("hello"); +) + Furthermore, in practice `wchar_t` is not usable in portable code as its size + is implementation dependent. On POSIX conforming machines it generally + represents an UTF-32 codeunit, on Windows an UTF-16 code unit. C11 introduced + C++11 types char16_t and char32_t to overcome this issue. + +$(H4 The D Way) + + The type of a string is determined by semantic analysis, so there is no need + to wrap strings in a macro call. Alternatively, if type inference is used, the + string can have a `c`, `w` or `d` suffix, representing UTF-8, + UTF-16 and UTF-32 encoding, respectively. If no suffix is used the type is + inferred to be a UTF-8 string: +----------------------------- +string utf8 = "hello"; // UTF-8 string +wstring utf16 = "hello"; // UTF-16 string +dstring utf32 = "hello"; // UTF-32 string + +auto str = "hello"; // UTF-8 string +auto _utf8 = "hello"c; // UTF-8 string +auto _utf16 = "hello"w; // UTF-16 string +auto _utf32 = "hello"d; // UTF-32 string +----------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 arrayenum, Arrays that parallel an enum)) + +$(H4 The C Way) + + Consider: +$(CCODE +enum COLORS { red, blue, green, max }; +char *cstring[max] = {"red", "blue", "green" }; +char *cstring[max] = {[red]="red", [blue]="blue", [green]="green" }; /\* C99 \*/ +) + This is fairly easy to get right because the number of entries is small. + But suppose it gets to be fairly large. Then it can get difficult to + maintain correctly when new entries are added. C99 added designated + initializers to solve that problem. + +$(H4 The D Way) +----------------------------- +enum COLORS { red, blue, green } + +string[COLORS.max + 1] cstring = +[ + COLORS.red : "red", + COLORS.blue : "blue", + COLORS.green : "green", +]; +----------------------------- + +Not perfect, but better. + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 typedefs, Creating a new type with typedef)) + +$(H4 The C Way) + + Typedefs in C are weak, that is, they really do not introduce + a new type. The compiler doesn't distinguish between a typedef + and its underlying type. + +$(CCODE +typedef void *Handle; +void foo(void *); +void bar(Handle); + +Handle h; +foo(h); // coding bug not caught +bar(h); // ok +) + + The C solution is to create a dummy struct whose sole + purpose is to get type checking and overloading on the new type. + +$(CCODE +struct Handle__ { void *value; } +typedef struct Handle__ *Handle; +void foo(void *); +void bar(Handle); + +Handle h; +foo(h); // syntax error +bar(h); // ok +) + + Having a default value for the type involves defining a macro, + a naming convention, and then pedantically following that convention: + +$(CCODE +#define HANDLE_INIT ((Handle)-1) + +Handle h = HANDLE_INIT; +h = func(); +if (h != HANDLE_INIT) + ... +) + + For the struct solution, things get even more complex: + +$(CCODE +struct Handle__ HANDLE_INIT; + +void init_handle(void) // call this function upon startup +{ + HANDLE_INIT.value = (void *)-1; +} + +Handle h = HANDLE_INIT; +h = func(); +if (memcmp(&h,&HANDLE_INIT,sizeof(Handle)) != 0) + ... +) + + There are 4 names to remember: $(D Handle, HANDLE_INIT, + struct Handle__, value). + +$(H4 The D Way) + + D has powerful metaprogramming abilities which allow it to implement + $(D typedef) as a library feature. Simply import `std.typecons` and + use the `Typedef` template: + +----------------------------- +import std.typecons; + +alias Handle = Typedef!(void*); +void foo(void*); +void bar(Handle); + +Handle h; +foo(h); // syntax error +bar(h); // ok +----------------------------- + + To handle a default value, pass the initializer to the `Typedef` + template as the second argument and refer to it with the + $(D .init) property: + +----------------------------- +alias Handle = Typedef!(void*, cast(void*)-1); +Handle h; +h = func(); +if (h != Handle.init) + ... +----------------------------- + + Now there's only one name to remember: $(D Handle). + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 structcmp, Comparing structs)) + +$(H4 The C Way) + + While C defines struct assignment in a simple, convenient manner: + +$(CCODE +struct A x, y; +... +x = y; +) + + it does not for struct comparisons. Hence, to compare two struct + instances for equality: + +$(CCODE +#include <string.h> + +struct A x, y; +... +if (memcmp(&x, &y, sizeof(struct A)) == 0) + ... +) + + $(P Note the obtuseness of this, coupled with the lack of any kind + of help from the language with type checking.) + + $(P There's a nasty bug lurking in the memcmp(). + The layout of a struct, due to alignment, can have 'holes' in it. + C does not guarantee those holes are assigned any values, and so + two different struct instances can have the same value for each member, + but compare different because the holes contain different garbage.) + +$(H4 The D Way) + + D does it the obvious, straightforward way: + +----------------------------- +A x, y; +... +if (x == y) + ... +----------------------------- + + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 stringcmp, Comparing strings)) + +$(H4 The C Way) + + The library function strcmp() is used: +$(CCODE +char str[] = "hello"; + +if (strcmp(str, "betty") == 0) // do strings match? + ... +) + + C uses 0 terminated strings, so the C way has an inherent + inefficiency in constantly scanning for the terminating 0. + +$(H4 The D Way) + + Why not use the `==` operator? + +----------------------------- +string str = "hello"; + +if (str == "betty") + ... +----------------------------- + + $(P D strings have the length stored separately from the string. + Thus, the implementation of string compares can be much faster + than in C (the difference being equivalent to the difference + in speed between the C memcmp() and strcmp()).) + + $(P D supports comparison operators on strings, too:) + +----------------------------- +string str = "hello"; + +if (str < "betty") + ... +----------------------------- + + which is useful for sorting/searching. + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 sort, Sorting arrays)) + +$(H4 The C Way) + + Although many C programmers tend to reimplement bubble sorts + over and over, the right way to sort in C is to use qsort(): + +$(CCODE +int compare(const void *p1, const void *p2) +{ + type *t1 = (type *)p1; + type *t2 = (type *)p2; + + return *t1 - *t2; +} + +type array[10]; +... +qsort(array, sizeof(array)/sizeof(array[0]), + sizeof(array[0]), compare); +) + + A compare() must be written for each type, and much careful + typo-prone code needs to be written to make it work. The indirect function + call required for each comparison limits the achievable performance of the + `qsort()` routine. + + +$(H4 The D Way) + + D has a powerful `std.algorithm` module with optimized + sorting routines, which work for any built-in or user-defined + type which can be compared: + +----------------------------- +import std.algorithm; +type[] array; +... +sort(array); // sort array in-place +----------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 strings, String literals)) + +$(H4 The C Way) + + String literals in C cannot span multiple lines, so to have + a block of text it is necessary to use \ line splicing: + +$(CCODE +"This text spans\n\ +multiple\n\ +lines\n" +) + + C's string literal concatenation doesn't really solve the problem: + +$(CCODE +"This text spans\n" +"multiple\n" +"lines\n" +) + + If there is a lot of text, this can wind up being tedious. + +$(H4 The D Way) + + String literals can span multiple lines, as in: + +----------------------------- +"This text spans +multiple +lines +" +----------------------------- + + So blocks of text can just be cut and pasted into the D + source. + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 traversal, Data Structure Traversal)) + +$(H4 The C Way) + + $(P Consider a function to traverse a recursive data structure. + In this example, there's a simple symbol table of strings. + The data structure is an array of binary trees. + The code needs to do an exhaustive search of it to find + a particular string in it, and determine if it is a unique + instance.) + + $(P To make this work, a helper function $(D membersearchx) + is needed to recursively + walk the trees. The helper function needs to read and write + some context outside of the trees, so a custom $(D struct Paramblock) + is created and a pointer to it is used to maximize efficiency.) + +$(CCODE +struct Symbol +{ + char *id; + struct Symbol *left; + struct Symbol *right; +}; + +struct Paramblock +{ + char *id; + struct Symbol *sm; +}; + +static void membersearchx(struct Paramblock *p, struct Symbol *s) +{ + while (s) + { + if (strcmp(p->id,s->id) == 0) + { + if (p->sm) + error("ambiguous member %s\n",p->id); + p->sm = s; + } + + if (s->left) + membersearchx(p,s->left); + s = s->right; + } +} + +struct Symbol *symbol_membersearch(Symbol *table[], int tablemax, char *id) +{ + struct Paramblock pb; + int i; + + pb.id = id; + pb.sm = NULL; + for (i = 0; i < tablemax; i++) + { + membersearchx(pb, table[i]); + } + return pb.sm; +} +) + +$(H4 The D Way) + + $(P This is the same algorithm in D, and it shrinks dramatically. + Since nested functions have access to the lexically enclosing + function's variables, there's no need for a Paramblock or + to deal with its bookkeeping details. The nested helper function + is contained wholly within the function that needs it, + improving locality and maintainability.) + + $(P The performance of the two versions is indistinguishable.) + +----------------------------- +class Symbol +{ + string id; + Symbol left; + Symbol right; +} + +Symbol symbol_membersearch(Symbol[] table, string id) +{ + Symbol sm; + + void membersearchx(Symbol s) + { + while (s) + { + if (id == s.id) + { + if (sm) + error("ambiguous member %s\n", id); + sm = s; + } + + if (s.left) + membersearchx(s.left); + s = s.right; + } + } + + for (int i = 0; i < table.length; i++) + { + membersearchx(table[i]); + } + + return sm; +} +----------------------------- + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 ushr, Unsigned Right Shift)) + +$(H4 The C Way) + + The right shift operators `>>` and `>>=` are signed + shifts if the left operand is a signed integral type, and + are unsigned right shifts if the left operand is an unsigned + integral type. To produce an unsigned right shift on an int, + a cast is necessary: + +$(CCODE +int i, j; +... +j = (unsigned)i >> 3; +) + + If $(D i) is an $(D int), this works fine. But if $(D i) is + of a type created with typedef, + +$(CCODE +myint i, j; +... +j = (unsigned)i >> 3; +) + + and $(D myint) happens to be a $(D long int), then the cast to + unsigned + will silently throw away the most significant bits, corrupting + the answer. + +$(H4 The D Way) + + D has the right shift operators `>>` and `>>=` which + behave as they do in C. But D also has explicitly unsigned + right shift operators `>>>` and `>>>=` which will + do an unsigned right shift regardless of the sign of the left + operand. Hence, + +----------------------------- +myint i, j; +... +j = i >>> 3; +----------------------------- + + avoids the unsafe cast and will work as expected with any integral + type. + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 closures, Dynamic Closures)) + +$(H4 The C Way) + + $(P Consider a reusable container type. In order to be reusable, + it must support a way to apply arbitrary code to each element + of the container. This is done by creating an $(I apply) function + that accepts a function pointer to which is passed each + element of the container contents.) + + $(P A generic context pointer is also needed, represented here by + $(D void *p). The example here is of a trivial container + class that holds an array of ints, and a user of that container + that computes the maximum of those ints.) + +$(CCODE +void apply(void *p, int *array, int dim, void (*fp)(void *, int)) +{ + for (int i = 0; i < dim; i++) + fp(p, array[i]); +} + +struct Collection +{ + int array[10]; +}; + +void comp_max(void *p, int i) +{ + int *pmax = (int *)p; + + if (i > *pmax) + *pmax = i; +} + +void func(struct Collection *c) +{ + int max = INT_MIN; + + apply(&max, c->array, sizeof(c->array)/sizeof(c->array[0]), comp_max); +} +) + + $(P While this works, it isn't very flexible.) + +$(H4 The D Way) + + The D version makes use of $(I delegates) to transmit + context information for the $(I apply) function, + and $(I nested functions) both to capture context + information and to improve locality. + +---------------------------- +class Collection +{ + int[10] array; + + void apply(void delegate(int) fp) + { + for (int i = 0; i < array.length; i++) + fp(array[i]); + } +} + +void func(Collection c) +{ + int max = int.min; + + void comp_max(int i) + { + if (i > max) + max = i; + } + + c.apply(&comp_max); +} +----------------------------- + + Pointers are eliminated, as well as casting and generic + pointers. The D version is fully type safe. + An alternate method in D makes use of $(I function literals): + +----------------------------- +void func(Collection c) +{ + int max = int.min; + + c.apply(delegate(int i) { if (i > max) max = i; } ); +} +----------------------------- + + eliminating the need to create irrelevant function names. + +
$(COMMENT ============================================ ) +$(H2 $(LNAME2 variadic, Variadic Function Parameters)) + + The task is to write a function that takes a varying + number of arguments, such as a function that sums + its arguments. + +$(H4 The C Way) + +$(CCODE +#include <stdio.h> +#include <stdarg.h> + +int $(B sum)(int dim, ...) +{ + int i; + int s = 0; + va_list ap; + + va_start(ap, dim); + for (i = 0; i < dim; i++) + s += va_arg(ap, int); + va_end(ap); + return s; +} + +int main() +{ + int i; + + i = $(B sum)(3, 8,7,6); + printf("sum = %d\n", i); + + return 0; +} +) + + There are two problems with this. The first is that the + $(D sum) function needs to know how many arguments were + supplied. It has to be explicitly written, and it can get + out of sync with respect to the actual number of arguments + written. + The second is that there's no way to check that the + types of the arguments provided really were ints, and not + doubles, strings, structs, etc. + +$(H4 The D Way) + + The `...` following an array parameter declaration means that + the trailing arguments are collected together to form + an array. The arguments are type checked against the array + type, and the number of arguments becomes a property + of the array: + +----------------------------- +import std.stdio; + +int $(B sum)(int[] values ...) +{ + int s = 0; + + foreach (int x; values) + s += x; + return s; +} + +int main() +{ + int i; + + i = $(B sum)(8,7,6); + writefln("sum = %d", i); + + return 0; +} +----------------------------- +) + +Macros: + TITLE=Programming in D for C Programmers + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/articles/d-array-article.dd b/articles/d-array-article.dd new file mode 100644 index 0000000000..0af7ef0a27 --- /dev/null +++ b/articles/d-array-article.dd @@ -0,0 +1,263 @@ +Ddoc + +$(D_S $(TITLE), + +$(HEADERNAV_TOC) + +$(P $(I by Steven Schveighoffer)) + +$(P One of the most pleasant features of the D language is its implementation of slices. Every time I use a programming language that isn't D, I find myself lamenting for D's slice syntax. Not only is it concise and efficient, but things "just work" when you are dealing with slices. +) + +$(P I'll go over some of the background and internals of D slices and arrays, and hopefully after reading this, you will have a clearer understanding of the proper ways to use D slices, as well as an idea of how fundamentally different they are than normal arrays! +) + +$(H2 $(LNAME2 an-overflowing-problem, An Overflowing Problem)) + +$(P In most languages, an array is a built-in type which manages its own data, and is passed around by reference. One refers to the entire thing as an "Array", and associates all the operations for the array (such as setting values, appending data for dynamic arrays, obtaining the length) to that type. +) + +$(P However, D takes its lineage from C, where an array is simply a chunk of contiguous data. In C, a reference to an array or array segment is as simple as a pointer (an explicit reference). C's arrays are distinctly unmanaged by the type that refers to them -- the pointer. The only operations supported are to retrieve and set data using an offset from the pointer. +) + +$(P For those of you unfamiliar with C, here are some examples of array usage in C (these also work in D): +) + +------ +arr[0] = 4; /* sets the first element of the array 'arr' to 4 */ +x = arr[1]; /* retrieves the second element of the array 'arr' into x */ +------ + +$(P Everything else (length, appending, allocation, destruction) is left up to library functions and assumption/documentation. So what is so wrong with this concept? One of the largest problems with C arrays is the ability to access any data via the pointer, even data that doesn't belong to the array. You can even use negative indexes! Not to mention that the array uses the exact same type as a pointer to a single item. When you get a pointer as a parameter to a function, that could be an array, or it could be just a pointer to a single item. Cue buffer overflow attacks. You can read more about this in Walter Bright's article, $(LINK2 https://digitalmars.com/articles/C-biggest-mistake.html, "C's biggest mistake") +) + +$(H2 $(LNAME2 introducing-slices, Introducing Slices)) + +$(P So how does D improve things? In many ways, D's arrays are similar to C's arrays. In fact, D supports C's array syntax using pointers. However, D provides a new type that builds on C array syntax called a slice. A slice is a segment of an array (dynamic or otherwise) that tracks both the pointer $(I and) the length of the segment. With the combined protection of having the length of the data, and the garbage collector to manage the memory backing the data, slices are an extremely powerful, dynamic concept that is safe from most memory corruption issues. In addition, D slices support extending with simple functions which take a slice as the first parameter. This allows one to add any functionality you want to a built-in type via properties or methods. With D slices, one can write high-performance code with elegant and concise syntax that is awkward or inefficient in almost any other language. +) + +$(P Let's see some D slices in action:) + +$(RUNNABLE_EXAMPLE +------ +import std.stdio; + +void main() +{ + int[] a; // a is a slice + + a = new int[5]; // allocate a dynamic array of integers that has at least 5 + // elements, and give me a slice to the first 5. Note + // that all data in D is default assigned, int's are + // defaulted to 0, so this array contains five 0's + + int[] b = a[0..2]; // This is a 'slicing' operation. b now refers to the + // first two elements of a. Note that D uses open interval + // for the upper limit, so a[2] is not included in b. + + int[] c = a[$-2..$]; // c refers to the last two elements of a + // ($ stands for length inside a slice or index operation). + + c[0] = 4; // this also assigns a[3] + c[1] = 5; // this also assigns a[4] + + b[] = c[]; // assign the first two elements of a[] to the value from + // the last two elements (4, 5). + + writeln(a); // prints "[4, 5, 0, 4, 5]" + + int[5] d; // d is a fixed sized array, allocated on the stack + b = d[0..2]; // slices can point at fixed sized arrays too! +} +------ +) + +$(P You may notice something puzzling about the description of the allocation of the array: "allocate a dynamic array of integers that has at least 5 elements, and give me a slice to the first 5." Why isn't it just "allocate a dynamic array of 5 elements"? Even experienced D coders have trouble with D's array concepts sometimes, and for quite good reason. D's slices are $(I not) proper dynamic array types (at least not under the hood) even though they appear to be. What they do is provide a safe and easy $(I interface) to arrays of any type (dynamic or otherwise). So let's discuss probably the most common misconception of D slices. +) + +$(H2 $(LNAME2 responsibility, Who's Responsible?)) + +$(P A slice in D seems like a dynamic array in almost all aspects of the concept -- when passed without adornments, the data referred to is passed by reference, and it supports all the properties and functions one would expect a dynamic array type to support. But there is one very important difference. A slice does not $(I own) the array, it $(I references) the array. That is, the slice is not responsible for allocation or deallocation of its data. The responsible party for managing a dynamic array's memory is the D runtime. +) + +$(P So where is the true dynamic array type in D? It's hidden by the runtime, and in fact, has no formal type. Slices are good enough, and as it turns out, the runtime is smart enough about what you want to do with the data, that you almost never notice dynamic arrays are missing as a full-fledged type. In fact, most D coders consider the D slice to $(I be) the dynamic array type -- it's even listed as a dynamic array type in the spec! The lack of ownership is very subtle and easy to miss. +) + +$(P Another consequence of this is that the length is not an array property, it's a slice property. This means the length field is not necessarily the length of the array, it's the length of the slice. This can be confusing to newcomers to the language. For instance, this code has a large flaw in it: +) + +$(RUNNABLE_EXAMPLE +------ +import std.stdio; + +void shrinkTo2(int[] arr) +{ + if (arr.length > 2) + arr.length = 2; +} + +void main() +{ + int[] arr = new int[5]; + arr.shrinkTo2(); // note the ability to call shrinkTo2 as a method + writeln(arr.length); // outputs 5 +} +------ +) + +$(P This might look like you changed the passed $(D arr)'s length to 2, but it actually did not affect anything (as is proven by the output from $(D writeln)). This is because even though the data is passed by reference, the actual pointer and length are passed by value. Many languages have an array type whose properties are all passed by reference. Notably, C# and Java arrays are actually fully referenced Objects. C++'s vector either passes both its data and properties by reference or by value.) + +$(P To fix this problem, you can do one of two things. Either you explicitly pass the slice by reference via the $(D ref) keyword, or you return the resulting slice to be reassigned. For example, here is how the signature would look if the slice is passed by reference:) + +------ +void shrinkTo2(ref int[] arr) +------ + +$(P Let's say you make this change, what happens to the data beyond the second element? In D, since slices don't own the data, it's still there, managed by the nebulous dynamic array type. The reason is fundamental: some other slice may still be referencing that data! The fact that no $(I single) slice is the true owner of the data means no single slice can make any assumptions about what else references the array data.) + +$(P What happens when no slices reference that data? Enter D's garbage collector. The garbage collector is responsible for cleaning up dynamic arrays that no longer are referenced by any slices. In fact, it is the garbage collector that makes much of D's slice usage possible. You can slice and serve up segments of dynamic arrays, and never have to worry that you are leaking memory, clobbering other slices, or worry about managing the lifetime of the array.) + +$(H2 $(LNAME2 append-on, A Slice You Can Append On)) + +$(P D's slices support appending more data to the end of the slice, much like a true dynamic array type. The language has a specific operator used for concatenation and appending, the tilde ($(D ~)). Here are some operations that append and concatenate arrays:) + +$(RUNNABLE_EXAMPLE +------ +int[] a; // an empty slice references no data, but still can be appended to +a ~= 1; // append some integers, this automatically allocates a new +a ~= 2; // array to hold the elements. + +a ~= [3, 4]; // append another array (this time, an array literal) +a = a ~ a; // concatenate a with itself, a is now [1, 2, 3, 4, 1, 2, 3, 4] +writeln(a); + +int[5] b; // a fixed-size array on the stack +a = b[1..$]; // a is a slice of b +a ~= 5; // since a was pointing to stack data, appending always reallocates, + // but works! +writeln(a); // [0, 0, 0, 0, 5] +------ +) + +$(P Anyone who cares about performance will wonder what happens when you append the four elements. The slice does not own its data, so how does one avoid reallocating a new array on each append operation? One of the main requirements of D slices are that they are efficient. Otherwise, coders would not use them. D has solved this problem in a way that is virtually transparent to the programmer, and this is one of the reasons slices seem more like true dynamic arrays.) + +$(H2 $(LNAME2 how-it-works, How it Works)) + +$(P Remember before when we allocated a new array, I said $(I allocate a dynamic array of $(B at least) n elements and give me a slice)? Here is where the runtime earns its keep. The allocator only allocates blocks in powers of 2 up to a page of data (in 32-bit x86, a page of data is 4096 bytes), or in multiples of pages. So when you allocate an array, you can easily get a block that's larger than requested. For instance, allocating a block of five 32 bit integers (which consumes 20 bytes) provides you a block of 32 bytes. This leaves space for 3 more integers.) + +$(P It's clearly possible to append more integers into the array without reallocating, but the trick is to prevent "stomping" on data that is valid and in use. Remember, the slice doesn't know what other slices refer to that data, or really where it is in the array (it could be a segment at the beginning or the middle). To make the whole thing work, the runtime stores the number of $(I used) bytes inside the block itself (a minor drawback is that the usable space in the block is not as big as it could be. In our example, for instance, we can truly only store 7 integers before needing to reallocate into another block). +) + +$(P When we request the runtime to append to a slice, it first checks to see that both the block is appendable (which means the $(I used) field is valid), and the slice $(I ends) at the same point valid data ends (it is not important where the slice begins). The runtime then checks to see if the new data will fit into the unused block space. If all of these checks pass, the data is written into the array block, and the stored $(I used) field is updated to include the new data. If any of these checks fail, a new array block is allocated that will hold the existing and new data, which is then populated with all the data. What happens to the old block? If there were other slices referencing it, it stays in place without being changed. If nothing else is referencing it, it becomes garbage and is reclaimed on the next collection cycle. This allows you to safely reallocate one slice without invalidating any others. This is a huge departure from C/C++, where reallocating an array, or appending to a vector can invalidate other references to that data (pointers or iterators).) + +$(P The result is an append operation which is not only efficient, but universally handy. Whenever you want to append a slice, you can, without worry about performance or corruption issues. You don't even have to worry about whether a slice's data is heap allocated, stack allocated, in ROM, or even if it's null. The append operation always succeeds (given you have enough memory), and the runtime takes care of all the dirty work in the background.) + +$(H2 $(LNAME2 determinism, Determinism)) + +$(P There is one caveat with slice appending that can bite inexperienced, and even experienced D coders: the apparent non-deterministic behavior of appending.) + +$(P Let's say we have a function which is passed a buffer, and writes some number of 'A's to the buffer (appending if necessary), returning the filled buffer:) + +------ +import std.stdio; + +char[] fillAs(char[] buf, size_t num) +{ + if (buf.length < num) + buf.length = num; // increase buffer length to be able to hold the 'A's + buf[0..num] = 'A'; // assign A to all the elements + return buf[0..num]; // return the result +} +------ + +$(P What's wrong with the $(D fillAs) function? Nothing really, but what happens if increasing the length forces the buffer to be reallocated? In that case, the buffer passed in is $(I not) overwritten with 'A's, only the reallocated buffer is. This can be surprising if you were expecting to continue to use the same buffer in further operations, or if you expected the original buffer to be filled with 'A's. The end result, depending on whether the block referenced by $(D buf[]) can be appended in place, is the caller's slice might be overwritten with 'A's, or it might not be.) + +------ +// continued example... +void main() +{ + char[] str = new char[10]; // Note, the block capacity allocated for this is + // 15 elements + str[] = 'B'; + fillAs(str, 20); // buffer must be reallocated (20 > 15) + writeln(str); // "BBBBBBBBBB" + fillAs(str, 12); // buffer can be extended in place (12 <= 15)! + writeln(str); // "AAAAAAAAAA"; +} +------ + + +$(P If you give this some thought, you should come to the conclusion that such a situation is unavoidable without costly copy-on-append semantics -- the system cannot keep track of every slice that references the data, and you have to put the new data somewhere. However, there are a couple options we have to mitigate the problem:) + +$(OL +$(LI Re-assign the slice to the return value of the function. Note that the most important result of this function is the return value, not whether the buffer was used or not.) +$(LI Don't use the passed in buffer again. If you don't use the source slice again, then you can't experience any issues with it.) +) + +$(P As the function author, there are some things we can do to avoid causing these problems. It's important to note that the only time this situation can occur is when the function appends to, or increases the length of, a passed in slice $(B and then) writes data to the original portion of the slice. Avoiding this specific situation where possible can reduce the perception of non-determinism. Later we will discuss some properties you can use to predict how the runtime will affect your slice. It is a good idea to note in the documentation how the passed in slice might or might not be overwritten.) + +$(P A final option is to use $(D ref) to make sure the source slice is updated. This is sometimes not an option as a slice can easily be an rvalue (input only). However, this does not fix the problem for any aliases to the same data elsewhere.) + +$(H2 $(LNAME2 caching, Caching)) + +$(P One of the issues with appending to a slice is that the operation is quick, but not quick enough. Every time we append, we need to fetch the metadata for the block (its starting address, size, and $(I used) data). Doing this means an O(lg(n)) lookup in the GC's memory pool for every append (not to mention acquiring the global GC lock). However, what we want is amortized constant appending. To achieve this lofty goal, we employ a caching technique that is, as far as I know, unique to D.) + +$(P Since D has the concept of default thread local storage, the type system can tell us whether heap data is local to the thread (and most data is), or shared amongst all threads. Using this knowledge, we can achieve lock-free caching of this metadata for thread-local appends, with one cache per thread. The cache stores the most recent $(D N) lookups of metadata, giving us quick access to whether a slice can be appended.) + +$(H2 $(LNAME2 slice-members-appender, Slice Members and the Appender)) + +$(P With D slices having such interesting behavior, there is a need sometimes to be able to predict the behavior of slices and appending. To that end, several properties and methods have been added to the slice.) + +$(P $(REF1_ALTTEXT $(D size_t reserve(size_t n)), reserve, object): Reserves n elements for appending to a slice. If a slice can already be appended in place, and there is already space in the array for at least n elements (n represents both existing slice elements and appendable space), nothing is modified. It returns the resulting capacity.) + +------ +int[] slice; +slice.reserve(50); +foreach (int i; 0..50) + slice ~= i; // does not reallocate +------ + +$(P $(REF1_ALTTEXT $(D size_t capacity), capacity, object): A property which gives you the number of elements the slice can hold via appending. If the slice cannot be appended in place, this returns 0. Note that capacity (if non-zero) includes the current slice elements.) + +$(RUNNABLE_EXAMPLE +------ +int[] slice = new int[5]; +assert(slice.capacity == 7); // includes the 5 pre-allocated elements + +int[] slice2 = slice; +slice.length = 6; +assert(slice.capacity == 7); // appending in place doesn't change the capacity. +assert(slice2.capacity == 0); // cannot append slice2 because it would stomp on + // slice's 6th element +------ +) + +$(P $(REF1_ALTTEXT $(D assumeSafeAppend()), assumeSafeAppend, object): This method forces the runtime to assume it is safe to append a slice. Essentially this adjusts the $(I used) field of the array to end at the same spot the slice ends.) + +$(RUNNABLE_EXAMPLE +------ +int[] slice = new int[5]; +slice = slice[0..2]; +assert(slice.capacity == 0); // not safe to append, there is other valid data in the block. +slice.assumeSafeAppend(); +assert(slice.capacity == 7); // force the used data to 2 elements +------ +) + +$(P If D slices' append performance just isn't up to snuff for your performance requirements, there is another alternative. The $(REF Appender, std,array) type will append data to an array as fast as possible, without any need to look up metadata from the runtime. $(REF Appender, std,array) also supports the $(REF_ALTTEXT output range, isOutputRange, std,range,primitives) idiom via an append operation (normal slices only support the output range by overwriting their own data).) + +$(H2 $(LNAME2 conclusion, Conclusion)) + +$(P Whether you are a seasoned programmer or a novice, the array and slice concepts in D provide an extremely rich feature set that allows for almost anything you would want to do with an array type. With a large focus on performance and usability, the D slice type is one of those things that you don't notice how great it is until you work with another language that doesn't have it.) + +$(P $(I Thanks to David Gileadi, Andrej Mitrovic, Jesse Phillips, Alex Dovhal, Johann !MacDonagh, and Jonathan Davis for their reviews and suggestions for this article)) + +© 2011-2012 by Steven Schveighoffer
+Creative Commons License
This work is licensed under a Creative Commons Attribution-NoDerivs 3.0 Unported License. + +) + +Macros: + TITLE=D Slices + SUBNAV=$(SUBNAV_ARTICLES) + _= diff --git a/d-floating-point.dd b/articles/d-floating-point.dd similarity index 85% rename from d-floating-point.dd rename to articles/d-floating-point.dd index dfcbb7391d..ad44fdc9e7 100644 --- a/d-floating-point.dd +++ b/articles/d-floating-point.dd @@ -2,7 +2,9 @@ Ddoc $(D_S $(TITLE), -$(H2 Introduction) +$(HEADERNAV_TOC) + +$(H2 $(LNAME2 introduction, Introduction)) $(P $(I by Don Clugston)) @@ -19,9 +21,10 @@ $(P My first floating-point nightmare occurred in a C++ program which hung once double q[8]; ... int x = 0; -while (x < 8) { - if ( q[x] >= 0 ) return true; - if ( q[x] < 0 ) ++x; +while (x < 8) +{ + if (q[x] >= 0) return true; + if (q[x] < 0) ++x; } return false; ------ @@ -36,7 +39,7 @@ Easy access to the "strange" features of floating point results in better educat This article will provide a brief overview of the support for floating point in the D programming language. ) -$(H2 Demystifying Floating-Point) +$(H2 $(LNAME2 deemystifying-floating-point, Demystifying Floating-Point)) $(P D guarantees that all built-in floating-point types conform to IEEE 754 arithmetic, making behaviour entirely predictable (note that this is $(I not) the same as producing identical results on all platforms). IEEE 754-2008 is the latest revision of the IEEE 754 Standard for Floating-Point Arithmetic. D is progressing towards full compliance with 754-2008.) @@ -63,7 +66,7 @@ $(P Why does NaN exist? It serves a valuable role: it $(I eradicates undefined b $(P Subnormals are necessary to prevent certain anomalies, and preserve important relationships such as: "x - y == 0 if and only if x == y".) -$(P Since $(INFIN) can be produced by overflow, both +$(INFIN) and -$(INFIN) are required. Both +0 and -0 are required in order to preserve identities such as: if $(D x>0), then $(D 1/(1/x) > 0). In almost all other cases, however, there is no difference between +0 and -0.) +$(P Since $(INFIN) can be produced by overflow, both +$(INFIN) and -$(INFIN) are required. Both +0 and -0 are required in order to ensure $(D x) and $(D 1/(1/x)) always have the same sign bit. In almost all other cases, however, there is no difference between +0 and -0.) $(P It's worth noting that these $(SINGLEQUOTE special values) are usually not very efficient. On x86 machines, for example, a multiplication involving a NaN, an infinity, or a subnormal can be twenty to fifty times slower than an operation on normal numbers. If your numerical code is unexpectedly slow, it's possible that you are inadvertently creating many of these special values. Enabling floating-point exception trapping, described later, is a quick way to confirm this.) @@ -78,7 +81,7 @@ $(D nextDown(x)) gives the next representable number which is less than x. $(P Numerical analysts often describe errors in terms of "units in the last place"(ulp), a surprisingly subtle term which is often used rather carelessly. [footnote: The most formal definition is found in [J.-M. Muller, "On the definition of ulp(x)",INRIA Technical Report 5504 (2005).]: If $(D x) is a real number that lies between two finite consecutive floating-point numbers a and b of type F, without being equal to one of them, then ulp(x)=abs(b-a); otherwise ulp(x) = $(D x*F.epsilon). Moreover, ulp(NaN) is NaN, and ulp($(PLUSMN)F.infinity) = $(PLUSMN)$(D F.max*F.epsilon).] -I prefer a far simpler definition: The difference in ulps between two numbers x and y is is the number of times which you need to call nextUp() or nextDown() to move from x to y. [Footnote: This will not be an integer if either x or y is a real number, rather than a floating point number.] +I prefer a far simpler definition: The difference in ulps between two numbers x and y is the number of times which you need to call nextUp() or nextDown() to move from x to y. [Footnote: This will not be an integer if either x or y is a real number, rather than a floating point number.] The D library function $(D feqrel(x, y)) gives the number of bits which are equal between x and y; it is an easy way to check for loss-of-precision problems. ) @@ -91,7 +94,7 @@ equivalent to [-$(INFIN), $(INFIN)]).) $(LI A naive binary chop doesn't work correctly. The fact that there are hundreds or thousands of times as many representable numbers between 0 and 1, as there are between 1 and 2, is problematic for divide-and-conquer algorithms. A naive binary chop would divide the interval [0 .. 2] into [0 .. 1] and [1 .. 2]. Unfortunately, this is not a true binary chop, because the interval [0 .. 1] contains more than 99% of the representable numbers from the original interval!) ) -$(H2 Condition number) +$(H2 $(LNAME2 condition-number, Condition number)) $(P Using nextUp, it's easy to approximately calculate the condition number.) @@ -133,7 +136,7 @@ $(P A key design goal is: it should be possible to write code such that, regardl $(P (Footnote: $(D real) is close to $(SINGLEQUOTE indigenous) in the Borneo proposal for the Java programming language[Ref Borneo]).) -$(P Consider evaluating $(D x*y + z*w), where $(D x, y, z) and $(D w) are double.) +$(P Consider evaluating `x*y + z*w`, where $(D x, y, z) and $(D w) are double.) $(OL $(LI double r1 = x * y + z * w;) @@ -157,23 +160,23 @@ $(H2 Properties of the Built-in Types) $(P The fundamental floating-point properties are $(D epsilon), $(D min_normal) and $(D max). The six integral properties are simply the log2 or log10 of these three.) -$(TABLE1 +$(TABLE $(TR $(TH  ) $(TH float) $(TH double) $(TH real80) $(TH quadruple) $(TH decimal64) $(TH decimal128)) $(TR $(TD epsilon) $(TD 0x1p-23) $(TD 0x1p-52) $(TD 0x1p-63) $(TD 0x1p-112) $(TD 1e-16 (1p-54)) $(TD 1e-34 (1p-113))) $(TR $(TD [min_normal) $(TD 0x1p-126) $(TD 0x1p-1022) $(TD 0x1p-16382) $(TD 0x1p-16382) $(TD 1e-383) $(TD 1e-6143)) $(TR $(TD ..max$(RPAREN)) $(TD 0x1p+128) $(TD 0x1p+1024) $(TD 0x1p+16384) $(TD 0x1p+16384) $(TD 1e+385) $(TD 1e+6145)) -$(TR binary properties) +$(TR binary properties) $(TR $(TD mant_dig) $(TD 24) $(TD 53) $(TD 64) $(TD 113) $(TD 53) $(TD 112)) $(TR $(TD min_exp) $(TD -125) $(TD -1021) $(TD -16381) $(TD -16381) $(TD  ) $(TD  )) $(TR $(TD max_exp) $(TD +128) $(TD +1024) $(TD +16384) $(TD +16384) $(TD  ) $(TD  )) -$(TR decimal properties) +$(TR decimal properties) $(TR $(TD dig) $(TD 6) $(TD 15) $(TD 18) $(TD 33) $(TD 16) $(TD 34)) $(TR $(TD min_10_exp) $(TD -37) $(TD -307) $(TD -4932) $(TD -4932) $(TD -382) $(TD -6142)) $(TR $(TD max_10_exp) $(TD +38) $(TD +308) $(TD +4932) $(TD +4932) $(TD 385) $(TD +6145)) ) $(P When writing code which should adapt to different CPUs at compile time, use $(D static if) with the $(D mant_dig) property. For example, $(D static if (real.mant_dig==64)) is true if 80-bit reals are available. -For binary types, the $(D dig) property gives only the $(I minimum) number of valid decimal digits. To ensure that that every representable number has a unique decimal representation, two additional digits are required. Similarly, for decimal numbers, $(D mant_dig) is a lower bound on the number of valid binary digits. +For binary types, the $(D dig) property gives only the $(I minimum) number of valid decimal digits. To ensure that every representable number has a unique decimal representation, two additional digits are required. Similarly, for decimal numbers, $(D mant_dig) is a lower bound on the number of valid binary digits. ) $(H2 Useful relations for a floating point type $(D F), where $(D x) and $(D y) are of type $(D F)) @@ -189,9 +192,9 @@ $(LI If $(D x-y==0), then $(D x==y && isFinite(x) && isFinite(y)). Note that if $(LI $(D F.max * F.min_normal = 4.0) for binary types, $(D 10.0) for decimal types.) ) -$(H3 Addition and subtraction) +$(H3 $(LNAME2 addition-subtraction, Addition and subtraction)) -$(UL +$(UL $(LI Some loss of precision occurs with x$(PLUSMN)y if exponent(x)!=exponent(y). The number of digits of precision which are lost is abs(exponent(x)-exponent(y)).) $(LI x$(PLUSMN)y has total loss of precision, if and only if (1) $(D abs(x * F.epsilon) > abs(y)), in which case x+y == x, x-y == x @@ -201,9 +204,9 @@ $(LI Subtraction is not quite commutative: $(D a - b == -(b - a)), but produce + $(LI Addition is not associative at all.) ) -$(H3 Multiplication and division) - -$(UL +$(H3 $(LNAME2 multiplication-division, Multiplication and division)) + +$(UL $(LI Multiplication and division are $(I always) at risk of overflow or underflow. For any $(D abs(x) > F.epsilon), there is at least one finite $(D y) such that $(D x/y) will overflow to $(INFIN). For any $(D abs(x) < F.epsilon), there is at least one finite $(D y) such that $(D x/y) will underflow to zero. @@ -212,17 +215,17 @@ $(LI Multiplication and division are $(I always) at risk of overflow or underflo ) $(LI $(D x*x) will overflow if $(D abs(x)>sqrt(F.max)), and underflow to zero if $(D abs(x) < sqrt(F.min_normal*F.epsilon)) ) $(LI Multiplication is commutative. $(D a * b == b * a)). -$(LI Multiplication is not associative in general: $(D a*(b*c) != (a*b)*c), because (1) there is a risk of overflow or underflow and (2) $(D b*c) may be an exact calculation, so that $(D a*(b*c)) contains only one round-off error, whereas $(D (a*b)*c) contains two. The roundoff errors may therefore accumulate at the rate of just under 1 ulp per multiplication.) -$(LI However, a limited form of associativity is possible if the type used for intermediate results is larger than any of the operands (which happens on x87 and Itanium machines). If $(D R) is the intermediate type, and $(D F) is the type being multiplied, up to $(D min(R.max_exp/F.max_exp, R.epsilon/F.epsilon)) values of type $(D F) can be multiplied together in any order without influencing the result. For example, if $(D R) is $(D double), multiplication of 8 floats $(D f1*f2*f3*f4*f5*f6*f7*f8) is completely associative. On x87, 130 floats can be safely multiplied together in any order, and 16 doubles can similarly be multiplied together safely. +$(LI Multiplication is not associative in general: `a*(b*c) != (a*b)*c`, because (1) there is a risk of overflow or underflow and (2) $(D b*c) may be an exact calculation, so that $(D a*(b*c)) contains only one round-off error, whereas $(D (a*b)*c) contains two. The roundoff errors may therefore accumulate at the rate of just under 1 ulp per multiplication.) +$(LI However, a limited form of associativity is possible if the type used for intermediate results is larger than any of the operands (which happens on x87 and Itanium machines). If $(D R) is the intermediate type, and $(D F) is the type being multiplied, up to $(D min(R.max_exp/F.max_exp, R.epsilon/F.epsilon)) values of type $(D F) can be multiplied together in any order without influencing the result. For example, if $(D R) is $(D double), multiplication of 8 floats `f1*f2*f3*f4*f5*f6*f7*f8` is completely associative. On x87, 130 floats can be safely multiplied together in any order, and 16 doubles can similarly be multiplied together safely. Strict distributivity does not hold even under these circumstances, as it may destroy the sign of -0.) -$(LI The distributive law almost never holds. For example, $(D 4*x + 6*x != 10*x) if $(D x==nextDown(1.5)). $(D a*x + b*x == (a+b)*x) for all $(D x) only if the operations $(D a*x, b*x), and $(D (a+b)) are all exact operations, which is true only if $(D a) and $(D b) are exact powers of 2. Even then, if $(D a==-b) and $(D x==-0), then $(D a*x+b*x==0.0, (a+b)*x==-0.0).) +$(LI The distributive law almost never holds. For example, `4*x + 6*x != 10*x` if $(D x==nextDown(1.5)). `a*x + b*x == (a+b)*x` for all $(D x) only if the operations `a*x, b*x`, and $(D (a+b)) are all exact operations, which is true only if $(D a) and $(D b) are exact powers of 2. Even then, if $(D a==-b) and $(D x==-0), then `a*x+b*x==0.0, (a+b)*x==-0.0`.) $(LI Performing a division by multiplication by the reciprocal returns a result which (in round-to-nearest mode) is at most 1.5 ulps from the correctly rounded result. For almost any denominator, the rounding is incorrect (>0.5ulps) for 27% of numerators. [Ref: N. Brisebarre, J-M Muller, and S.K. Raina, "Accelerating Correctly Rounded Floating-Point Division when the Divisor Is Known in Advance", IEEE Trans. on Computers, Vol 53, pp 1069-1072 (2004)].) ) -$(H3 Powers and logarithms) +$(H3 $(LNAME2 powers-logarithm, Powers and logarithms)) -$(UL +$(UL $(LI $(D F.mant_dig = -log2(F.epsilon)) for binary types;) $(LI $(D F.dig = -log10(F.epsilon)) for decimal types.) $(LI $(D F.max = exp2(F.max_exp*(1-F.epsilon))) for binary types;) @@ -232,39 +235,24 @@ $(LI For any positive finite $(D x), $(D F.min_exp - F.mant_dig <= log2(x) < F.m $(LI $(D exp2(x) == 0) if $(D x < F.min_exp - F.mant_dig), $(D exp2(x) == infinity) if $(D x >= F.max_exp)) ) -$(H2 NaN payloads) +$(H2 $(LNAME2 nan, NaN payloads)) $(P According to the IEEE 754 standard, a $(SINGLEQUOTE payload) can be stored in the mantissa of a NaN. This payload can contain information about how or why it was generated. Historically, almost no programming languages have ever made use of this potentially powerful feature. In D, this payload consists of a positive integer.) -$(UL +$(UL $(LI $(D real NaN(ulong payload)) -- create a NaN with a "payload", where the payload is a $(D ulong).) $(LI $(D ulong getNaNPayload(real x)) -- returns the integer payload. Note that if narrowing conversions have occured, the high-order bits may have changed.) ) $(P $(I Never) store a pointer as an integer payload inside a NaN. The garbage collector will not be able to find it!) -$(H2 NCEG comparison operations) - -$(P As well as the usual $(D <), $(D >), $(D <=), and $(D >=) comparison operators, D also supports the "NCEG" operators. Most of them are the direct negation of the ordinary operators. Additionally, $(D <>), $(D <>=), $(D !<>), and $(D !<>=) are provided. These 8 new operators are different from the normal operators only when a NaN is involved, so for the most part they are quite obscure. They are useful mainly in eliminating the possibility of NaN before beginning a calculation. -The most useful relationships are probably: -$(UL -$(LI $(D x <>= y) is the same as $(D !isNaN(x) && !isNaN(y)), (except that signalling NaNs may be triggered by <>=).) -$(LI $(D x !<>= y) is the same as $(D isNaN(x) || isNaN(y)).) -) -If $(D y) is any compile-time constant (eg 0), these reduce to $(D !isNaN(x) and isNaN(x)). -Note that $(D x==x) is the same as $(D !isNaN(x)), and $(D x!=x) is the same as $(D isNaN(x)). -$(D abs(x) !< x.infinity) is the same as $(D isNaN(x) || isInfinity(x)) -The above relationships are useful primarily because they can be used in compile time functions. -Very few uses are known for the remaining NCEG operators. -) - -$(H2 The IEEE Rounding Modes) +$(H2 $(LNAME2 iee-rounding-modes, The IEEE Rounding Modes)) -$(P The rounding mode is controlled within a scope. Rounding mode will be restored to its previous state at the end of that scope. +$(P The rounding mode is controlled within a scope. Rounding mode will be restored to its previous state at the end of that scope. Four rounding modes can be set. The default mode, $(I Round to nearest), is the most statistically accurate, but the least intuitive. In the event of tie, the result is rounded to an even number. ) -$(TABLE1 +$(TABLE $(TR $(TH Rounding mode) $(TH rndint(4.5)) $(TH rndint(5.5)) $(TH rndint(-4.5)) $(TH Notes)) $(TR $(TD Round to nearest) $(TD 4) $(TD 6) $(TD -4) $(TD Ties round to an even number)) $(TR $(TD Round down) $(TD 4) $(TD 5) $(TD -5) $(TD  )) @@ -279,14 +267,14 @@ The round-to-zero mode is used for casting floating-point numbers to integers. S $(P The only other commonly cited reason for changing the rounding mode is as a simple check for numerical stability: if the calculation produces wildly different results when the rounding mode is changed, it's a clear sign that it is suffering from round-off errors. ) -$(H2 The IEEE Exception Status Flags) +$(H2 $(LNAME2 iee-exception-status-flags, The IEEE Exception Status Flags)) $(P All IEEE-compiliant processors include special status bits that indicate when "weird" things have happened that programs might want to know about. For example, $(D ieeeFlags.divideByZero) tells if any infinities have been created by dividing by zero. They are 'sticky' bits: once they have been set, they remain set until explicitly cleared. By only checking this once at the end of a calculation, it may be possible to avoid comparing thousands of comparisions that are almost never going to fail.) $(P Here's a list of the weird things that can be detected:) $(DL -$(DT invalid) $(DD This is set if any NaN's have been generated. This can happen with $(INFIN) - $(INFIN), $(INFIN) * 0, 0 * $(INFIN), 0/0, $(INFIN)/$(INFIN), $(INFIN)%$(INFIN), or $(D x%0), for any number $(D x). Several other operations, such as sqrt(-1), can also generate a NaN. The $(I invalid) condition is also set when a 'signalling NaN' is accessed, indicating use of an uninitialized variable. This almost always indicates a programming error.) +$(DT invalid) $(DD This is set if any NaNs have been generated. This can happen with $(INFIN) - $(INFIN), $(INFIN) * 0, 0 * $(INFIN), 0/0, $(INFIN)/$(INFIN), $(INFIN)%$(INFIN), or $(D x%0), for any number $(D x). Several other operations, such as sqrt(-1), can also generate a NaN. The $(I invalid) condition is also set when a 'signalling NaN' is accessed, indicating use of an uninitialized variable. This almost always indicates a programming error.) $(DT overflow) $(DD Set if $(INFIN) was generated by adding or multiplying two numbers that were so large that the sum was greater than $(D real.max). This almost always indicates that the result is incorrect; and corrective action needs to be taken.) @@ -304,21 +292,21 @@ This can be an invaluable debugging aid. A more advanced usage, not yet supported on any platform(!) is to provide a nested function to be used as a hardware exception handler. This is most useful for the overflow and underflow exceptions. ) -$(H2 Floating point and $(SINGLEQUOTE pure nothrow)) +$(H2 $(LNAME2 pure-nothrow, Floating point and $(SINGLEQUOTE pure nothrow))) $(P Every floating point operation, even the most trivial, is affected by the floating-point rounding state, and writes to the sticky flags. The status flags and control state are thus 'hidden variables', potentially affecting every $(D pure) function; and if the floating point traps are enabled, any floating point operation can generate a hardware exception. D provides a facility for the floating-point control mode and exception flags to be usable in limited circumstances even when $(D pure) and $(D nothrow) functions are called. ) -$(P [TODO: I've made two proposals, but I haven't persauded Walter yet!].) +$(P [TODO: I've made two proposals, but I haven't persuaded Walter yet!].) -$(H2 Conclusion) +$(H2 $(LNAME2 conclusion, Conclusion)) $(P Although D is a general-purpose programming language and supports many high-level concepts, it gives direct and convenient access to almost all features of modern floating-point hardware. This makes it an excellent language for development of robust, high-performance numerical code. It is also a language which encourages a deep understanding of the machine, making it fertile ground for innovation and for developing new algorithms.) -$(H2 References and Further Reading) +$(H2 $(LNAME2 references-further-reading, References and Further Reading)) $(OL $(LI @@ -341,7 +329,7 @@ $(LINK2 http://www.sonic.net/~jddarcy/Borneo/, ) Macros: - TABLE = + TABLE =
$0
CAPTION = $0 SVH = $(TR $(TH $1) $(TH $2)) @@ -356,14 +344,7 @@ Macros: INFIN = ∞ PLUSMNINF = ±∞ PI = π - LT = < - GT = > SQRT = &radix; HALF = ½ - D = $0 - D = $0 - H2=

$0

- H3=

$0

- TITLE=Real Close to the Machine: Floating Point in D - WIKI=FloatingPointInD - CATEGORY_ARTICLES=$0 + TITLE=Real Close to the Machine: Floating Point in D + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/articles/dll-linux.dd b/articles/dll-linux.dd new file mode 100644 index 0000000000..f4b7bb120c --- /dev/null +++ b/articles/dll-linux.dd @@ -0,0 +1,539 @@ +Ddoc + +$(D_S Writing Shared Libraries With D On Linux, + +$(HEADERNAV_TOC) + +$(P For comparison purposes and looking at the mechanics, here's how it's done in C first. +) + +$(H2 $(LNAME2 dso1, Statically Linking C)) + +$(P To statically link a C module with a C program, +) + +main.c: + +$(CCODE +#include <stdio.h> + +extern int dll(); + +int main() +{ + printf("+main()\n"); + dll(); + printf("-main()\n"); + return 0; +} +) + +dll.c: + +$(CCODE +#include <stdio.h> + +int dll() +{ + printf("dll()\n"); + return 0; +} +) + +Build: + +$(CONSOLE +gcc -c dll.c +gcc -c main.c +gcc -o main main.o dll.o + +./main +) + +Results: + +$(CONSOLE ++main() +dll() +-main() +) + +$(H2 $(LNAME2 dso2, Statically Loading a Shared library in C)) + +Build: + +$(CONSOLE +gcc -c dll.c -fpic +gcc -shared -o libdll.so dll.o +gcc -c main.c +gcc -L/home/username/tmp -Wl,-rpath=/home/username/tmp main.o -o main -ldll +) + +$(P (The source files, run, and results should be identical.) +) + +$(P -rpath is used to embed the path to libdll.so into main, so that it can be found +at runtime. Other ways to do it are (but are not discussed further here): +) + +$(OL +$(LI Setting the environment variable LD_LIBRARY_PATH.) +$(LI Copy shared library to a standard location and use ldconfig to modify ld.so.) +) + + +$(H2 $(LNAME2 dso3, Dynamically Loading a Shared library in C)) + +$(P Add code to main.c to load the library at runtime: +) + +main.c: + +$(CCODE +#include <stdio.h> +#include <stdlib.h> +#include <dlfcn.h> + +int main() +{ + printf("+main()\n"); + + void *lh = dlopen("/home/walter/tmp/libdll.so", RTLD_LAZY); + if (!lh) + { + fprintf(stderr, "dlopen error: %s\n", dlerror()); + exit(1); + } + printf("libdll.so is loaded\n"); + + int (*fn)() = dlsym(lh, "dll"); + char *error = dlerror(); + if (error) + { + fprintf(stderr, "dlsym error: %s\n", error); + exit(1); + } + printf("dll() function is found\n"); + + (*fn)(); + + printf("unloading libdll.so\n"); + dlclose(lh); + + printf("-main()\n"); + return 0; +} +) + +Build: + +$(CONSOLE +gcc -c dll.c -fpic +gcc -shared -o libdll.so dll.o +gcc -c main.c +gcc -rdynamic main.o -o main -ldl + +./main +) + +Results: + +$(CONSOLE ++main() +libdll.so is loaded +dll() function is found +dll() +unloading libdll.so +-main() +) + +$(H2 $(LNAME2 dso4, Dynamically Loading a C++ Shared library in C)) + +$(P The complication here is noting when the shared library's static constructors +and destructors are run. Instrument dll.c, which is now C++ code, with those +static constructors and destructors: +) + +dll.c: + +$(CCODE +#include <stdio.h> + +extern "C" int dll() +{ + printf("dll()\n"); + return 0; +} + +struct S +{ + S() { printf("libdll.so construction\n"); } + ~S() { printf("~libdll.so destruction\n"); } +}; + +S ss; +) + +Build: + +$(CONSOLE +g++ -c dll.c -fpic +g++ -shared -o libdll.so dll.o +gcc -c main.c +gcc -rdynamic main.o -o main -ldl + +./main +) + +Results: + +$(CONSOLE ++main() +libdll.so construction +libdll.so is loaded +dll() function is found +dll() +unloading libdll.so +libdll.so destruction +-main() +) + +$(H2 $(LNAME2 dso5, Statically Linking D Program With libphobos2.a)) + +main.d: + +--- +import core.stdc.stdio; +import dll; + +int main() +{ + printf("+main()\n"); + dll.dll(); + printf("-main()\n"); + return 0; +} +--- + +dll.d: + +--- +import core.stdc.stdio; + +extern (C) int dll() +{ + printf("dll()\n"); + return 0; +} +--- + +Build: + +$(CONSOLE +dmd -c dll.d +dmd -c main.d +dmd main.o dll.o + +./main +) + +Results: + +$(CONSOLE ++main() +dll() +-main() +) + +$(H2 $(LNAME2 dso6, Statically Linking D Program With libphobos2.so)) + +Build: + +$(CONSOLE +dmd -c dll.d +dmd -c main.d +dmd main.o dll.o -defaultlib=libphobos2.so -L-rpath=/path/to/where/shared/library/is + +./main +) + +$(H2 $(LNAME2 dso7, Creating a D Shared Library and Statically Linking With libphobos2.so)) + +$(P When using D shared libraries, the code must be linked with libphobos2.so, +not libphobos2.a. This is so that there will be only one instance of the +garbage collector. +) + +Build: + +$(CONSOLE +dmd -c dll.d -fPIC +dmd -oflibdll.so dll.o -shared -defaultlib=libphobos2.so -L-rpath=/path/to/where/shared/library/is +dmd -c main.d +dmd main.o -L-l:libdll.so -defaultlib=libphobos2.so -L-rpath=.:/path/to/where/shared/library/is + +./main +) + +$(H2 $(LNAME2 dso8, Dynamically Loading a C++ DLL From a D Program)) + +main.d: + +--- +import core.stdc.stdio; +import core.stdc.stdlib; +import core.sys.posix.dlfcn; + +extern (C) int dll(); + +int main() +{ + printf("+main()\n"); + + void* lh = dlopen("libdll.so", RTLD_LAZY); + if (!lh) + { + fprintf(stderr, "dlopen error: %s\n", dlerror()); + exit(1); + } + printf("libdll.so is loaded\n"); + + int function() fn = cast(int function())dlsym(lh, "dll"); + char* error = dlerror(); + if (error) + { + fprintf(stderr, "dlsym error: %s\n", error); + exit(1); + } + printf("dll() function is found\n"); + + fn(); + + printf("unloading libdll.so\n"); + dlclose(lh); + + printf("-main()\n"); + return 0; +} +--- + +dll.c: + +$(CCODE +#include <stdio.h> + +extern "C" int dll() +{ + printf("dll()\n"); + return 0; +} + +struct S +{ + S() { printf("libdll.so construction\n"); } + ~S() { printf("libdll.so destruction\n"); } +}; + +S ss; +) + +Build: + +$(CONSOLE +g++ -c dll.c -fpic +g++ -shared -o libdll.so dll.o +dmd -c main.d +dmd main.o -L-ldl -L-rpath=. + +./main +) + +Results: + +$(CONSOLE ++main() +libdll.so construction +libdll.so is loaded +dll() function is found +dll() +unloading libdll.so +libdll.so destruction +-main() +) + +$(H2 $(LNAME2 dso9, Dynamically Loading a D DLL From a C Program)) + +main.c: + +$(CCODE +#include <stdio.h> +#include <stdlib.h> +#include <dlfcn.h> + +int main() +{ + printf("+main()\n"); + + void *lh = dlopen("/home/walter/tmp/libdll.so", RTLD_LAZY); + if (!lh) + { + fprintf(stderr, "dlopen error: %s\n", dlerror()); + exit(1); + } + printf("libdll.so is loaded\n"); + + int (*fn)() = dlsym(lh, "dll"); + char *error = dlerror(); + if (error) + { + fprintf(stderr, "dlsym error: %s\n", error); + exit(1); + } + printf("dll() function is found\n"); + + (*fn)(); + + printf("unloading libdll.so\n"); + dlclose(lh); + + printf("-main()\n"); + return 0; +} +) + +dll.d: + +--- +import core.stdc.stdio; + +extern (C) int dll() +{ + printf("dll()\n"); + return 0; +} + +shared static this() +{ + printf("libdll.so shared static this\n"); +} + +shared static ~this() +{ + printf("libdll.so shared static ~this\n"); +} +--- + +Build: + +$(CONSOLE +dmd -c dll.d -fPIC +dmd -oflibdll.so dll.o -shared -defaultlib=libphobos2.so -L-rpath=/path/to/where/shared/library/is + +gcc -c main.c +gcc -rdynamic main.o -o main -ldl + +./main +) + +Results: + +$(CONSOLE ++main() +libdll.so shared static this +libdll.so is loaded +dll() function is found +dll() +unloading libdll.so +libdll.so shared static ~this +-main() +) + +$(P Note that libphobos2.so gets automatically dynamically loaded as well. +) + +$(H2 $(LNAME2 dso10, Dynamically Loading a D DLL From a D Program)) + +$(P It is important to link the main program with libphobos2.so, not libphobos2.a. Otherwise, +the result will be multiple instances of the D runtime conflicting with each other. +) + +main.d: + +--- +import core.stdc.stdio; +import core.stdc.stdlib; +import core.sys.posix.dlfcn; + +extern (C) int dll(); + +int main() +{ + printf("+main()\n"); + + void* lh = dlopen("libdll.so", RTLD_LAZY); + if (!lh) + { + fprintf(stderr, "dlopen error: %s\n", dlerror()); + exit(1); + } + printf("libdll.so is loaded\n"); + + int function() fn = cast(int function())dlsym(lh, "dll"); + char* error = dlerror(); + if (error) + { + fprintf(stderr, "dlsym error: %s\n", error); + exit(1); + } + printf("dll() function is found\n"); + + fn(); + + printf("unloading libdll.so\n"); + dlclose(lh); + + printf("-main()\n"); + return 0; +} + +shared static this() { printf("main shared static this\n"); } + +shared static ~this() { printf("main shared static ~this\n"); } +--- + +Build: + +$(CONSOLE +dmd -c dll.d -fPIC +dmd -oflibdll.so dll.o -shared -defaultlib=libphobos2.so -L-rpath=/path/to/where/shared/library/is + +dmd -c main.d +dmd main.o -L-ldl -defaultlib=libphobos2.so -L-rpath=.:/path/to/where/shared/library/is -map + +./main +) + +Results: + +$(CONSOLE +main shared static this ++main() +libdll.so shared static this +libdll.so is loaded +dll() function is found +dll() +unloading libdll.so +libdll.so shared static ~this +-main() +main shared static ~this +) + +$(P Note how the DLL's static constructors are called before dlopen() returns, +and the static destructors are called by dlclose(). +) + +) + +Macros: + TITLE=Writing Shared Libraries With D On Linux + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/articles/dll-windows.dd b/articles/dll-windows.dd new file mode 100644 index 0000000000..7f2fb65a5b --- /dev/null +++ b/articles/dll-windows.dd @@ -0,0 +1,222 @@ +Ddoc + +$(D_S $(TITLE), + +$(HEADERNAV_TOC) + +Windows DLLs (aka shared libraries) are a method of sharing instances of executable +code and data between processes. Although they perform the same role as shared libraries +in other systems like Linux, OSX, and FreeBSD, they are implemented quite differently. +The information in this article is specific to Windows DLLs. + + +$(H2 Build a DLL) + +$(H3 Code for the DLL) + +$(OL +$(LI Create the file mydll.d: + +--- +module mydll; + +import core.sys.windows.dll; +import core.stdc.stdio; + +mixin SimpleDllMain; + +export void entry() +{ + printf("called mydll.entry()\n"); +} +--- +) + +$(LI Compile and link the DLL: + +$(CONSOLE +dmd -shared mydll +) + +which will create the files $(TT mydll.lib) (the $(I import library)) and +$(TT mydll.dll) (the $(I dll)). +) + + +$(LI Create the file mydll.di: + +--- +module mydll; + +export void entry(); +--- +) + +$(LI Create the file myexe.d: + +--- +module myexe; + +import mydll; + +int main() +{ + mydll.entry(); + return 0; +} +--- +) + +$(LI Compile the $(TT myexe.d) file and link is with the $(TT mydll.lib) +file to create the $(TT myexe.exe) file: +$(CONSOLE +dmd myexe.d mydll.lib +) +) + +$(LI Run myexe: + +$(CONSOLE +C:> myexe +called mydll.entry() +) +) + + +$(H2 DllMain - Entry Point) + +A Windows DLL must have an entry point, much like the `main` function in an executable. +It looks like: + +--- +module dllmain; // nice to always name it this + +import core.sys.windows.windef : HINSTANCE, BOOL, DWORD, LPVOID; +import core.sys.windows.winnt; +import core.sys.windows.dll : dll_process_attach, dll_process_detach, + dll_thread_attach, dll_thread_detach; + +__gshared HINSTANCE g_hInst; // saved instance handle for the DLL + +/*********************************** + * DLL entry point. + * Params: + * hInstance = instance handle for the DLL + * ulReason = why the DllMain is being called + * fImpLoad = null if Dll is explicitly loaded, !null if implicitly loaded + * Returns: + * true for success, false for failure + */ +extern (Windows) +BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID fImpLoad) +{ + switch (ulReason) + { + case DLL_PROCESS_ATTACH: // when the DLL is first loaded + g_hInst = hInstance; // save it for later + return dll_process_attach(hInstance, true); // perform process-relative initialization + + case DLL_PROCESS_DETACH: // when DLL is being unloaded + return dll_process_detach(hInstance, true); // perform process-relative teardown + + case DLL_THREAD_ATTACH: // new thread initialization + return dll_thread_attach(true, true); // perform thread-relative initialization + + case DLL_THREAD_DETACH: // thread is ending + return dll_thread_detach(true, true); // perform thread teardown + + default: + assert(0); + } +} +--- + +Or, since this is just boilerplate code, this will do nicely: + +--- +module dllmain; + +import core.sys.windows.dll; + +mixin SimpleDllMain; +--- + +The compiler recognizes `DllMain`, and emits a reference to `__acrtused_dll` which will +pull in the DLL support code from the C runtime library. It will also cause the addition +of the debug runtime library +(for symbolic debug compiles) or the default runtime library (otherwise) to be searched +by the linker. + + +$(H2 Exporting Definitions) + +In order for an executable to reference a name in the DLL, that name must be $(I exported) +by the DLL. For example, to export the symbol `func` from this module: + +--- +module mydll; +export int func() { return 3; } +--- + +the compiler inserts the following Export Definition directive into the object file: + + +$(CONSOLE +EXPDEF expflag=x00, export '__D5mydll4funcFZi', internal '', ordinal=x0 +) + +for OMF files, and the equivalent in MSCOFF object files. +$(TT EXPDEF) informs the linker that `mydll.func` is to be put in the export +table of the DLL being linked. That's the only addition to the object file. + + +$(H2 Importing Declarations) + +The EXE file, when a DLL is attached to it, needs to know how to call it. This is +called importing a declaration from the DLL. Prepare an import file $(TT mydll.di): + +--- +module mydll; +export int func(); // note no function body +--- + +--- +module myexe; +import mydll; + +int test() { return func(); } +--- + +Compiling $(TT myexe.d) uncovers the magic: + +--- +extrn __imp___D5mydll4funcFZi + +__D5myexe4testFZi comdat + call dword ptr __imp___D5mydll4funcFZi + ret +--- + +A direct call is not made to `mydll.func()`, instead an indirect call to `mydll.func()` is +made via a pointer to `mydll.func()`, and the pointer’s name is `__imp___D5mydll4func`. +) + +$(H2 Import Library) + +$(P Exporting the definitions from the dll's object file, and hooking the exe file up to +the dll's exports requires an additional file, the import library. The import library is +automatically created by the linker when the dll is linked. This library then must be added +to the link step when linking the executable file.) + +$(H2 $(LNAME2 references, References)) + +$(OL +$(LI $(LINK2 https://wiki.dlang.org/Win32_DLLs_in_D, Win32 DLLs in D)) +$(LI $(LINK2 https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices, Dynamic-Link Library Best Practices)) +) + +) + +Macros: + TITLE=Creating Windows DLLs + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/exception-safe.dd b/articles/exception-safe.dd similarity index 66% rename from exception-safe.dd rename to articles/exception-safe.dd index e0525fe877..8805693fef 100644 --- a/exception-safe.dd +++ b/articles/exception-safe.dd @@ -11,23 +11,23 @@ is either buggy or simply ignored for the sake of expediency. -

Example

+$(H3 Example) -For example, if there's a Mutex m that must be acquired and held +Here there's a mutex $(D m) that must be acquired and held for a few statements, then released: --- -void abc() +void locked_foo() { Mutex m = new Mutex; - lock(m); // lock the mutex - foo(); // do processing - unlock(m); // unlock the mutex + lock(m); // lock the mutex + foo(); // do processing + unlock(m); // unlock the mutex } --- -$(P If foo() throws an exception, then abc() exits via exception unwinding, -unlock(m) is never called and the Mutex is not released. This is a fatal +$(P If $(D foo()) throws an exception, then $(D locked_foo()) exits via exception unwinding, +$(D unlock(m)) is never called and the mutex is not released. This is a fatal problem with this code. ) @@ -37,57 +37,57 @@ the traditional approaches to writing exception safe programming. ) $(P RAII is scoped destruction, and the example can be fixed by providing -a Lock class with a destructor that gets called upon the exit of the scope: +a $(D Lock) struct with a destructor that gets called upon the exit of the scope: ) --- -class Lock +struct Lock { Mutex m; this(Mutex m) { - this.m = m; - lock(m); + this.m = m; + lock(m); } ~this() { - unlock(m); + unlock(m); } } -void abc() +void locked_foo() { Mutex m = new Mutex; - scope L = new Lock(m); - foo(); // do processing + auto l = Lock(m); + foo(); // do processing } --- -If abc() is exited normally or via an exception thrown from foo(), L gets +If $(D locked_foo()) is exited normally or via an exception thrown from $(D foo()), $(D l) gets its destructor called and the mutex is unlocked. The try-finally solution to the same problem looks like: --- -void abc() +void locked_foo() { Mutex m = new Mutex; - lock(m); // lock the mutex + lock(m); // lock the mutex try { - foo(); // do processing + foo(); // do processing } finally { - unlock(m); // unlock the mutex + unlock(m); // unlock the mutex } } --- $(P Both solutions work, but both have drawbacks. The RAII solution often requires -the creation of an extra dummy class, which is both a lot of lines of code to +the creation of an extra dummy struct, which is both a lot of lines of code to write and a lot of clutter obscuring the control flow logic. This is worthwhile to manage resources that must be cleaned up and that appear more than once in a program, but it is clutter when it only needs to be @@ -97,158 +97,147 @@ solution separates the unwinding code from the setup, and it can often be a visually large separation. Closely related code should be grouped together. ) -$(P The $(LINK2 statement.html#ScopeGuardStatement, scope exit) statement is an easier -approach: +$(P The $(DDSUBLINK spec/statement, ScopeGuardStatement, scope guard statement) +is a better approach: ) --- -void abc() +void locked_foo() { Mutex m = new Mutex; - lock(m); // lock the mutex - scope(exit) unlock(m); // unlock on leaving the scope + lock(m); // lock the mutex + scope(exit) unlock(m); // unlock on leaving the scope - foo(); // do processing + foo(); // do processing } --- -The $(D_KEYWORD scope)(exit) statement is executed at the closing curly +The $(D $(D_KEYWORD scope)(exit)) statement is executed at the closing curly brace upon normal execution, or when the scope is left due to an exception having been thrown. It places the unwinding code where it aesthetically belongs, next to the creation of the state that needs unwinding. It's far less code to write than either the RAII or try-finally solutions, and doesn't require the -creation of dummy classes. +creation of dummy structs. -

Example

+$(H3 Example) The next example is in a class of problems known as transaction processing: --- -Transaction abc() +Transaction transaction() { - Foo f; - Bar b; - - f = dofoo(); - b = dobar(); + Foo f = dofoo(); + Bar b = dobar(); return Transaction(f, b); } --- -$(P Both dofoo() and dobar() must succeed, or the transaction has failed. +$(P Both $(D dofoo()) and $(D dobar()) must succeed, or the transaction has failed. If the transaction failed, the data must be restored to the state -where neither dofoo() nor dobar() have happened. To support that, -dofoo() has an unwind operation, dofoo_undo(Foo f) which will roll back -the creation of a Foo. +where neither $(D dofoo()) nor $(D dobar()) have happened. To support that, +$(D dofoo()) has an unwind operation, $(D dofoo_undo(Foo f)) which will roll back +the creation of a $(D Foo). ) $(P With the RAII approach: ) --- -class FooX +struct FooX { Foo f; bool commit; - this() + @disable this(); + + static FooX create() { - f = dofoo(); + auto fx = FooX.init; + fx.f = dofoo(); + return fx; } ~this() { - if (!commit) - dofoo_undo(f); + if (!commit) + dofoo_undo(f); } } -Transaction abc() +Transaction transaction() { - scope f = new FooX(); + auto fx = FooX.create(); Bar b = dobar(); - f.commit = true; - return Transaction(f.f, b); + fx.commit = true; + return Transaction(fx.f, b); } --- -With the try-finally approach: +With the try-catch approach: --- -Transaction abc() +Transaction transaction() { - Foo f; - Bar b; - - f = dofoo(); + Foo f = dofoo(); try { - b = dobar(); - return Transaction(f, b); + Bar b = dobar(); + return Transaction(f, b); } - catch (Object o) + catch (Exception o) { - dofoo_undo(f); - throw o; + dofoo_undo(f); + throw o; } } --- $(P These work too, but have the same problems. -The RAII approach involves the creation of dummy classes, and the obtuseness -of moving some of the logic out of the abc() function. +The RAII approach involves the creation of dummy structs, and the obtuseness +of moving some of the logic out of the $(D transaction()) function. The try-finally approach is wordy even with this simple example; try writing it if there are more than two components of the transaction that must succeed. It scales poorly. ) -$(P The $(D_KEYWORD scope)(failure) statement solution looks like: +$(P The $(D $(D_KEYWORD scope)(failure)) solution looks like: ) --- -Transaction abc() +Transaction transaction() { - Foo f; - Bar b; - - f = dofoo(); + Foo f = dofoo(); scope(failure) dofoo_undo(f); - b = dobar(); - + Bar b = dobar(); return Transaction(f, b); } --- -The dofoo_undo(f) only is executed if the scope is exited via an +$(D dofoo_undo(f)) is only executed if the scope is exited via an exception. The unwinding code is minimal and kept aesthetically where it belongs. It scales up in a natural way to more complex transactions: --- -Transaction abc() +Transaction transaction() { - Foo f; - Bar b; - Def d; - - f = dofoo(); + Foo f = dofoo(); scope(failure) dofoo_undo(f); - b = dobar(); + Bar b = dobar(); scope(failure) dobar_unwind(b); - d = dodef(); - + Def d = dodef(); return Transaction(f, b, d); } --- -

Example

+$(H3 Example) The next example involves temporarily changing the state of some object. Suppose there's a class data member $(D verbose), which controls the @@ -259,34 +248,34 @@ there's a loop that would otherwise cause a blizzard of messages to be output: --- class Foo { - bool verbose; // true means print messages, false means silence + bool verbose; // true means print messages, false means silence ... bar() { - auto verbose_save = verbose; - verbose = false; - ... lots of code ... - verbose = verbose_save; + auto verbose_save = verbose; + verbose = false; + ... lots of code ... + verbose = verbose_save; } } --- There's a problem if $(D Foo.bar()) exits via an exception - the verbose flag state is not restored. -That's easily fixed with $(D_KEYWORD scope)(exit): +That's easily fixed with $(D $(D_KEYWORD scope)(exit)): --- class Foo { - bool verbose; // true means print messages, false means silence + bool verbose; // true means print messages, false means silence ... bar() { - auto verbose_save = verbose; - verbose = false; - scope(exit) verbose = verbose_save; + auto verbose_save = verbose; + verbose = false; + scope(exit) verbose = verbose_save; - ...lots of code... + ...lots of code... } } --- @@ -308,7 +297,7 @@ the conceptually linked set and reset code, besides requiring the addition of an irrelevant scope. ) -

Example

+$(H3 Example) Here's another example of a multi-step transaction, this time for an email program. @@ -352,15 +341,15 @@ class Mailer { void Send(Message msg) { - { - char[] origTitle = msg.Title(); - scope(exit) msg.SetTitle(origTitle); - msg.SetTitle("[Sending] " ~ origTitle); - Copy(msg, "Sent"); - } - scope(success) SetTitle(msg.ID(), "Sent", msg.Title); - scope(failure) Remove(msg.ID(), "Sent"); - SmtpSend(msg); // do the least reliable part last + { + const origTitle = msg.Title(); + scope(exit) msg.SetTitle(origTitle); + msg.SetTitle("[Sending] " ~ origTitle); + Copy(msg, "Sent"); + } + scope(success) SetTitle(msg.ID(), "Sent", msg.Title); + scope(failure) Remove(msg.ID(), "Sent"); + SmtpSend(msg); // do the least reliable part last } } --- @@ -371,12 +360,12 @@ MessageTitleSaver and MessageRemover. Rewriting the example with try-finally would require nested try-finally statements or use of an extra variable to track state evolution. -

Example

+$(H3 Example) Consider giving feedback to the user about a lengthy operation (mouse changes to an hourglass, window title is red/italicized, ...). -With $(D_KEYWORD scope)(exit) that can be easily done without +With $(D $(D_KEYWORD scope)(exit)) that can be easily done without needing to make an artificial resource out of whatever UI state element used for the cues: @@ -389,7 +378,7 @@ void LongFunction() } -------------- -Even more so, $(D_KEYWORD scope)(success) and $(D_KEYWORD scope)(failure) +Even more so, $(D $(D_KEYWORD scope)(success)) and $(D $(D_KEYWORD scope)(failure)) can be used to give an indication if the operation succeeded or if an error occurred: @@ -403,19 +392,19 @@ void LongFunction() } --- -

When to use RAII, try-catch-finally, and Scope

+$(H2 When to use RAII, try-catch-finally, and Scope) RAII is for managing resources, which is different from managing state or transactions. try-catch is still needed, as scope doesn't catch exceptions. It's try-finally that becomes redundant. -

Acknowledgements

+$(H2 Acknowledgements) $(P Andrei Alexandrescu argued about the usefulness of these constructs on the Usenet and also defined their semantics in terms of try/catch/finally in a series of posts to comp.lang.c++.moderated under the title -$(LINK2 http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/60117e9c1cd1c510/b8cbe52786b0f506, A safer/better C++?) +$(LINK2 https://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/60117e9c1cd1c510/b8cbe52786b0f506, A safer/better C++?) starting Dec 6, 2005. D implements the idea with a slightly modified syntax following its creator's experiments with the @@ -429,7 +418,7 @@ $(P I am indebted to Scott Meyers for teaching me about exception safe programming. ) -

References:

+$(H2 References:) $(OL @@ -440,7 +429,7 @@ by Andrei Alexandrescu and Petru Marginean ) $(LI "Item 29: Strive for exception-safe code" in -$(LINK2 http://www.amazon.com/exec/obidos/ASIN/0321334876/classicempire, +$(LINK2 https://www.amazon.com/exec/obidos/ASIN/0321334876/classicempire, Effective C++ Third Edition), pg. 127 by Scott Meyers ) @@ -450,7 +439,5 @@ $(LINK2 http://www.amazon.com/exec/obidos/ASIN/0321334876/classicempire, ) Macros: - TITLE=Exception Safety - WIKI=ExceptionSafe - CATEGORY_ARTICLES=$0 - + TITLE=Exception Safety + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/articles/faq.dd b/articles/faq.dd new file mode 100644 index 0000000000..eb112add0c --- /dev/null +++ b/articles/faq.dd @@ -0,0 +1,935 @@ +Ddoc + +$(D_S $(TITLE), + + $(P The same questions keep cropping up, so the obvious thing to do is + prepare a FAQ.) + + $(P See also:) + + * $(DDLINK articles/const-faq, const(FAQ), const(FAQ)) for `const` and `immutable`. + * $(LINK2 http://www.prowiki.org/wiki4d/wiki.cgi?FaqRoadmap, The D wiki FAQ page) + * $(LINK2 http://www.digitalmars.com/d/1.0/faq.html, D 1.0 FAQ) + * $(LINK2 http://www.digitalmars.com/faq.html, C++ FAQ) + +$(H2 D 2.0 FAQ) + + $(UL + $(LI Where is my simple language?) + + $(LI What other cool features are in the plans for D 2.0?) + + $(LI I suggested a great feature. Why was the suggestion ignored?) + + $(LI I want to contribute to D 2.0. How can I effect that?) + + $(ITEMR case_range, Why doesn't the case range statement + use the $(D case X..Y:) syntax?) + + $(ITEMR shared_guarantees, What guarantees is shared supposed to provide?) + + $(ITEMR shared_synchronized, What does shared have to do with synchronization?) + + $(ITEMR shared_memory_barriers, What does shared have to do with memory barriers?) + + $(ITEMR casting_to_shared, What are the semantics of casting FROM unshared TO shared?) + + $(ITEMR casting_from_shared, What are the semantics of casting FROM shared TO unshared?) + + $(ITEMR bss, Why does a large static array bloat my executable file size?) + ) + +$(H2 General D FAQ) + + $(UL + $(LI $(LINK2 $(ROOT_DIR)comparison.html, What does D have that C++ doesn't?)) + $(ITEMR q1, Why the name D?) + $(ITEMR q1_1, Could you change the name? D is kind of hard to search for on search engines.) + $(LI $(LINK2 http://dlang.org/download.html, Where can I get a D compiler?)) + $(ITEMR q1_2, Is there linux port of D?) + $(ITEMR gdc, Is there a GNU version of D?) + $(ITEMR backend, How do I write my own D compiler for CPU X?) + $(ITEMR gui, Where can I get a GUI library for D?) + $(ITEMR ide, Where can I get an IDE for D?) + $(ITEMR q4, Why is [expletive deleted] printf left in?) + $(ITEMR q5, Is D open source?) + $(ITEMR q5_2, Why does the standard library use the boost license? Why not public domain?) + $(ITEMR q6, Why $(I no) fall through on switch statements?) + $(ITEMR q7, Why should I use D instead of Java?) + $(ITEMR q7_2, Doesn't C++ support strings, etc. with STL?) + $(ITEMR q7_3, Can't garbage collection be done in C++ with an add-on library?) + $(ITEMR q7_4, Can't unit testing be done in C++ with an add-on library?) + $(ITEMR q8, Why have an asm statement in a portable language?) + $(ITEMR real, What is the point of 80 bit reals?) + $(ITEMR anonymous, How do I do anonymous struct/unions in D?) + $(ITEMR printf, How do I get printf() to work with strings?) + $(ITEMR nan, Why are floating point values default initialized to NaN rather than 0?) + $(ITEMR assignmentoverloading, Why is overloading of the assignment operator not supported?) + $(ITEMR keys, The $(SINGLEQUOTE ~) is not on my keyboard?) + $(ITEMR omf, Can I link in C object files created with another compiler?) + $(ITEMR regexp_literals, Why not support regular expression literals + with the /foo/g syntax?) + $(ITEMR cpp_to_D, Why aren't all Digital Mars programs translated to D?) + $(ITEMR foreach, When should I use a foreach loop rather than a for?) + $(ITEMR cpp_interface, Why doesn't D have an interface to C++ as well as C?) + $(ITEMR reference-counting, Why doesn't D use reference counting for garbage collection?) + $(ITEMR gc_1, Isn't garbage collection slow and non-deterministic?) + $(ITEMR pure, Can't a sufficiently smart compiler figure out that a function is pure automatically?) + $(ITEMR minimum precision, Why allow $(D cast(float)) if it isn't supposed to work?) + $(ITEMR nested_forward_references, Why can't nested functions be forward referenced?) + ) + +$(ITEM case_range, Why doesn't the case range statement + use the $(D case X..Y:) syntax?) + + $(P See the $(DDSUBLINK spec/statement, CaseRangeStatement, case range statement).) + + $(P The usages of .. would then be: + $(OL + $(LI $(D case X..Y:)) + $(LI $(D foreach(e; X..Y))) + $(LI $(D array[X..Y])) + ) + Case (1) has a VERY DIFFERENT meaning from (2) and (3). + (1) is inclusive of Y, and (2) and (3) are exclusive of Y. + Having a very different meaning means it should have a distinctly different syntax. + ) + +$(ITEM shared_guarantees, What guarantees is shared supposed to provide?) + + $(P Shared means that multiple threads can access the data. The guarantee is that if it is + not shared, and not immutable, that only the current thread can see it. + ) + +$(ITEM shared_synchronized, What does shared have to do with synchronization?) + + $(P Only shared data can be synchronized. It makes no sense to synchronize thread local + data. + ) + +$(ITEM shared_memory_barriers, What does shared have to do with memory barriers?) + + $(P Currently the compiler does not insert memory barriers around shared variables. + ) + +$(ITEM casting_to_shared, What are the semantics of casting FROM unshared TO shared?) + + $(P Make sure there are no other unshared references to that same data. + ) + +$(ITEM casting_from_shared, What are the semantics of casting FROM shared TO unshared?) + + $(P Make sure there are no other shared references to that same data. + ) + +$(ITEM bss, Why does a large static array bloat my executable file size?) + + $(P Given the declaration:) +--- +char[1024 * 1024] arr; +--- + $(P the executable size increases by a megabyte in size. In C, this would not + as $(CODE arr) would be stored in the BSS segment. + In D, $(CODE arr) is not stored in the BSS segment because: + ) + + $(UL + $(LI The $(CODE char) type is initialized to 0xFF, not 0. Non-zero data + cannot be placed in BSS.) + $(LI Statically allocated data is placed in thread local storage. The BSS + segment is not thread local, and there is no thread local equivalent of BSS.) + ) + + $(P The following will be placed in BSS:) + +--- +__gshared byte[1024 * 1024] arr; +--- + + $(P as $(CODE byte)s are 0 initialized and $(CODE __gshared) puts it in the + global data.) + + $(P There are similiar issues for $(CODE float), $(CODE double), and $(CODE real) + static arrays. They are initialized to NaN (Not A Number) values, not 0. + ) + + $(P The easiest way to deal with this issue is to allocate the array dynamically + at run time rather than statically allocate it. + ) + +$(ITEM q1, Why the name D?) + + $(P The original name was the Mars Programming Language. But my friends + kept calling it D, and I found myself starting to call it D. + The idea of D being a successor to C goes back at least as far as 1988, + as in this + $(LINK2 https://groups.google.com/group/comp.lang.c/browse_thread/thread/cb4b868fab477b61/d4b5407644d16806, thread). + ) + +$(ITEM q1_1, Could you change the name? D is kind of hard to search for on search engines.) + + $(P No. We understand it can be frustrating but it's far too late for a + name change at this point. We recommend using "dlang", "d programming", + "d language", or "d programming language" in your search terms. Doing so + should yield substantially better search results. + ) + + $(P Most publicly available D code has "// Written in the D programming + language" as its first comment. + ) + +$(ITEM q1_2, Is there a linux port of D?) + + $(P Yes, the D compiler includes a $(DDLINK dmd-linux, + DMD Compiler for Linux, linux version). + ) + +$(ITEM gdc, Is there a GNU version of D?) + + $(P Yes, + $(LINK2 https://bitbucket.org/goshawk/gdc/wiki/Home, gdc - the D frontend with GCC). + ) + +$(ITEM backend, How do I write my own D compiler for CPU X?) + + $(P Burton Radons has written a + $(LINK2 http://www.opend.org/dli/DLinux.html, back end). + You can use as a guide. + ) + +$(ITEM gui, Where can I get a GUI library for D?) + + $(P Since D can call C functions, any GUI library with a C interface is + accessible from D. Various D GUI libraries and ports can be found at + $(LINK2 https://wiki.dlang.org/GUI_Libraries, the D wiki). + ) + +$(ITEM ide, Where can I get an IDE for D?) + + $(P Lists of $(LINK2 https://wiki.dlang.org/Editors, editors) and + $(LINK2 https://wiki.dlang.org/IDEs, IDEs) that support D can be found on + the D wiki. + ) + +$(ITEM q4, Why is printf in D?) + + $(P $(LINK2 http://www.digitalmars.com/rtl/stdio.html#printf, printf) + is not part of D, it is part of C's standard + runtime library which is accessible from D. + D's standard runtime library has + $(REF writef, std,stdio) + which is as powerful as $(LINK2 http://www.digitalmars.com/rtl/stdio.html#printf, printf) + but is much easier to use. + ) + + +$(ITEM q5, Is D open source?) + + $(P The $(LINK2 http://dlang.org/download.html, $(B dmd)) D + compiler and the runtime library are completely open source using + the $(LINK2 http://boost.org/LICENSE_1_0.txt, Boost License 1.0). + All development takes place publicly on + $(LINK2 https://github.com/dlang, github). + There are also the $(LINK2 http://dlang.org/download.html, $(B gdc)) + and the $(LINK2 http://dlang.org/download.html, $(B ldc)) D compilers + who come with the GCC- or LLVM-backend and the DMD front end. + ) + +$(ITEM q5_2, Why does the standard library use the boost license? Why not public domain?) + + $(P Although most jurisdictions use the concept of Public Domain, some + (eg, Japan) do not. + The $(LINK2 http://boost.org/LICENSE_1_0.txt, Boost License) + avoids this problem. It was chosen because, unlike almost all other open + source licenses, it does not demand that the license text be included on + distributions in binary form. + ) + +$(ITEM q6, Why $(I no) fall through on switch statements?) + + $(P Many people have asked for a requirement that there be a break between + cases in a switch statement, that C's behavior of silently falling through + is the cause of many bugs. + ) + + $(P In D2, implicit fall through is disallowed. You have to add a + $(DDSUBLINK spec/statement, GotoStatement, goto case;) statement to explicitly + state the intention of falling through. + ) + + $(P There was further request that the $(B break) statement be made + implicit. + The reason D doesn't change this is for the same reason that integral + promotion rules and operator precedence rules were kept the same - to + make code that looks the same as in C operate the same. If it had subtly + different semantics, it will cause frustratingly subtle bugs. + ) + + +$(ITEM q7, Why should I use D instead of Java?) + + $(P D is distinct from Java in purpose, philosophy and reality. + See this $(LINK2 $(ROOT_DIR)comparison.html, comparison). + ) + + $(P Java is designed to be write once, run everywhere. D is designed for writing + efficient native system apps. Although D and Java share the notion that + garbage collection is good and multiple inheritance is bad, their + different design goals mean the languages have very different feels. + ) + +$(ITEM q7_2, Doesn't C++ support strings, etc. with STL?) + + $(P In the C++ standard library are mechanisms for doing strings, + dynamic arrays, associative arrays, and bounds-checked + arrays. + ) + + $(P Sure, all this stuff can be done with libraries, + following certain coding disciplines, etc. But + object oriented programming can also be done in C (it's been done). + Isn't it incongruous that something like strings, + supported by the simplest BASIC interpreter, requires a very + large and complicated infrastructure to support? + Just the implementation of a string type in STL is over two + thousand lines of code, using every advanced feature of templates. + How much confidence can you have that this is all working + correctly, how do you fix it if it is not, what do you do with the + notoriously inscrutable error messages when there's an error + using it, how can you be sure you are using it correctly + (so there are no memory leaks, etc.)? + ) + + $(P D's implementation of strings is simple and straightforward. + There's little doubt about how to use it, no worries about memory leaks, + error messages are to the point, and it isn't hard to see if it + is working as expected or not. + ) + +$(ITEM q7_3, Can't garbage collection be done in C++ with an add-on library?) + + $(P Yes, I use one myself. It isn't part of the language, though, and + requires some subverting of the language to make it work. + Using gc with C++ isn't for the standard or casual C++ programmer. + Building it into the + language, like in D, makes it practical for everyday programming chores.) + + $(P GC isn't that hard to implement, either, unless you're building one + of the more advanced ones. But a more advanced one is like building + a better optimizer - the language still works 100% correctly even + with a simple, basic one. The programming community is better served + by multiple implementations competing on quality of code generated + rather than by which corners of the spec are implemented at all.) + +$(ITEM q7_4, Can't unit testing be done in C++ with an add-on library?) + + Sure. Try one out and then compare it with how D does it. + It'll be quickly obvious what an improvement building it into + the language is. + +$(ITEM q8, Why have an asm statement in a portable language?) + + $(P An asm statement allows assembly code to be inserted directly into a D + function. Assembler code will obviously be inherently non-portable. D is + intended, however, to be a useful language for developing systems apps. + Systems apps almost invariably wind up with system dependent code in them + anyway, inline asm isn't much different. Inline asm will be useful for + things like accessing special CPU instructions, accessing flag bits, special + computational situations, and super optimizing a piece of code.) + + $(P Before the C compiler had an inline assembler, I used external assemblers. + There was constant grief because many, many different versions of the + assembler were out there, the vendors kept changing the syntax of the + assemblers, there were many different bugs in different versions, and even + the command line syntax kept changing. What it all meant was that users + could not reliably rebuild any code that needed assembler. An inline + assembler provided reliability and consistency.) + +$(ITEM real, What is the point of 80 bit reals?) + + More precision enables more accurate floating point computations + to be done, especially when adding together large numbers of small + real numbers. Prof. Kahan, who designed the Intel floating point + unit, has an eloquent + paper + on the subject. + +$(ITEM anonymous, How do I do anonymous struct/unions in D?) + +$(RUNNABLE_EXAMPLE +----------------------- +import std.stdio; + +struct Foo +{ + union { int a; int b; } + struct { int c; int d; } +} + +void main() +{ + writefln( + "Foo.sizeof = %d, a.offset = %d, b.offset = %d, c.offset = %d, d.offset = %d", + Foo.sizeof, + Foo.a.offsetof, + Foo.b.offsetof, + Foo.c.offsetof, + Foo.d.offsetof); +} +----------------------- +) + +$(ITEM printf, How do I get printf() to work with strings?) + + $(P In C, the normal way to printf a string is to use the $(D %s) + format:) + +$(CCODE +char s[8]; +strcpy(s, "foo"); +printf("string = '%s'\n", s); +) + + $(P Attempting this in D:) + +$(RUNNABLE_EXAMPLE_FAIL +--------------------------------- +import core.stdc.stdio; +string s; +s = "foo"; +printf("string = '%s'\n", s); // Error +--------------------------------- +) + $(P The call gets flagged at compile-time (see + $(DDSUBLINK spec/pragma, printf, `pragma(printf)`)) + because in general, `string` is not compatible with the `%s` specifier. + This prevents garbage being printed, or an access violation.) + + $(P In D, a string is an array, so it has a length and a pointer. + In C, a string is a pointer to memory terminated by a 0 character. + The $(D %s) format prints until a 0 is encountered. + In D, strings in general are not 0-terminated, the size is determined + by a separate length value. So, strings are printf'd using the + $(D %.*s) format:) + +$(RUNNABLE_EXAMPLE +--------------------------------- +import core.stdc.stdio; +string s; +s = "foo"; +printf("string = '%.*s'\n", cast(int) s.length, s.ptr); +--------------------------------- +) + $(P which will behave as expected, for that input data. + There are pitfalls:) + * printf's $(D %.*s) will print until the length + is reached or a 0 is encountered, so D strings with embedded 0's + will only print up to the first 0. + * printf's length argument is an int, so ensure `s.length <= int.max`. + + $(P D string literals are actually 0-terminated, so `%s` can be used + with the `.ptr` property and printf will work for those. + However, non-literal strings often are not 0-terminated:) + + $(RUNNABLE_EXAMPLE + --- + import core.stdc.stdio; + printf("string = '%s'\n", "bar".ptr); // OK, 0-terminated + + string s = "food"; + s = s[0..3]; // foo, not 0-terminated + printf("string = '%.*s'\n", cast(int) s.length, s.ptr); + + s ~= "ie"; // s is still not 0-terminated + --- + ) + + $(P Of course, the easier solution is just to use $(REF writef, std, stdio) + which works correctly with D strings. + ) + +$(ITEM nan, Why are floating point values default initialized to NaN rather than 0?) + + A floating point value, if no explicit initializer is given, + is initialized to NaN (Not A Number): + +--------------------------------- +double d; // d is set to double.nan +--------------------------------- + + $(P NaNs have the interesting property in that whenever a NaN is + used as an operand in a computation, the result is a NaN. Therefore, + NaNs will propagate and appear in the output whenever a computation + made use of one. This implies that a NaN appearing in the output + is an unambiguous indication of the use of an uninitialized + variable.) + + $(P If 0.0 was used as the default initializer for floating point + values, its effect could easily be unnoticed in the output, and so + if the default initializer was unintended, the bug may go + unrecognized.) + + $(P The default initializer value is not meant to be a useful value, + it is meant to expose bugs. Nan fills that role well.) + + $(P But surely the compiler can detect and issue an error message + for variables used that are not initialized? Most of the time, + it can, but not always, and what it can do is dependent on the + sophistication of the compiler's internal data flow analysis. + Hence, relying on such is unportable and unreliable.) + + $(P Because of the way CPUs are designed, there is no NaN value for + integers, so D uses 0 instead. It doesn't have the advantages of + error detection that NaN has, but at least errors resulting from + unintended default initializations will be consistent and therefore more + debuggable.) + +$(ITEM assignmentoverloading, Why is overloading of the assignment operator not supported?) + + $(P Overloading of the assignment operator for structs is supported + in D 2.0.) + +$(ITEM keys, The $(SINGLEQUOTE ~) is not on my keyboard?) + + $(P On PC keyboards, hold down the [Alt] key and press the 1, 2, and 6 + keys in sequence on the numeric pad. That will generate a $(SINGLEQUOTE ~) + character. + ) + +$(ITEM omf, Can I link in C object files created with another compiler?) + + + $(P DMD produces OMF (Microsoft Object Module Format) object + files while other compilers such as VC++ produce COFF object + files. + DMD's output is designed to work with DMC, the Digital Mars C + compiler, which also produces object files in OMF format.) + + $(P The OMF format that DMD uses is a Microsoft defined format based on an + earlier Intel designed one. Microsoft at one point decided to abandon it + in favor of a Microsoft defined variant on COFF.) + + $(P Using the same object format doesn't mean that any C library in that + format will successfully link and run. There is a lot more compatibility + required - such as calling conventions, name mangling, compiler helper + functions, and hidden assumptions about the way things work. If DMD + produced Microsoft COFF output files, there is still little chance that + they would work successfully with object files designed and tested for + use with VC. There were a lot of problems with this back when + Microsoft's compilers did generate OMF.) + + $(P Having a different object file format makes it helpful in identifying + library files that were not tested to work with DMD. If they are not, + weird problems would result even if they successfully managed to link + them together. It really takes an expert to get a binary built with a + compiler from one vendor to work with the output of another vendor's + compiler.) + + $(P That said, the linux version of DMD produces object files in the ELF + format which is standard on linux, and it is specifically designed to + work with the standard linux C compiler, gcc.) + + $(P There is one case where using existing C libraries does work - when + those libraries come in the form of a DLL conforming to the usual C ABI + interface. The linkable part of this is called an "import library", and + Microsoft COFF format import libraries can be successfully converted to + DMD OMF using the + coff2omf + tool.) + +$(ITEM regexp_literals, Why not support regular expression literals + with the $(D /foo/g) syntax?) + + $(P There are two reasons: + ) + + $(OL + + $(LI The $(D /foo/g) syntax would make it impossible to separate + the lexer from the parser, as / is the divide token.) + + $(LI There are already 3 string types; adding the regex literals + would add 3 more. This would proliferate through much of the compiler, + debugger info, and library, and is not worth it.) + + ) + +$(ITEM cpp_to_D, Why aren't all Digital Mars programs translated to D?) + + $(P There is little benefit to translating a complex, debugged, working + application from one language to another. But new Digital Mars apps are + implemented in D.) + + +$(ITEM foreach, When should I use a foreach loop rather than a for?) + + $(P Is it just performance or readability? + ) + + $(P By using foreach, you are letting the compiler decide on the + optimization rather than worrying about it yourself. For example - are + pointers or indices better? + Should I cache the termination condition or not? + Should I rotate the loop or not? + The answers to these questions are not easy, and can vary from machine + to machine. Like register assignment, let the compiler do the + optimization.) + +--- +for (int i = 0; i < foo.length; i++) +--- + +or: + +--- +for (int i = 0; i < foo.length; ++i) +--- + +or: + +--- +for (T* p = &foo[0]; p < &foo[length]; p++) +--- + +or: + +--- +T* pend = &foo[length]; +for (T* p = &foo[0]; p < pend; ++p) +--- + +or: + +--- +T* pend = &foo[length]; +T* p = &foo[0]; +if (p < pend) +{ + do + { + ... + } while (++p < pend); +} +--- + +and, of course, should I use size_t or int? + +--- +for (size_t i = 0; i < foo.length; i++) +--- + +Let the compiler pick! + +--- +foreach (v; foo) + ... +--- + +$(P Note that we don't even need to know what the type T needs to be, thus +avoiding bugs when T changes. I don't even have to know if foo is an array, or +an associative array, or a struct, or a collection class. This will also avoid +the common fencepost bug:) + +--- +for (int i = 0; i <= foo.length; i++) +--- + +$(P And it also avoids the need to manually create a temporary if foo is a +function call.) + +$(P The only reason to use a for loop is if your loop does not fit in the +conventional form, like if you want to change +the termination condition on the fly.) + + +$(ITEM cpp_interface, Why doesn't D have an interface to C++ as well as C?) + + $(P D 2.0 does have a + $(DDLINK spec/cpp_interface, Interfacing to C++, + limited interface to C++ code.) + ) Here are some reasons why it isn't a full interface: + + + $(P Attempting to have D interface with C++ is + nearly as complicated as writing a C++ compiler, which would destroy the + goal of having D be a reasonably easy language to implement. + For people with an existing C++ code base that they must work with, they are + stuck with C++ (they can't move it to any other language, either).) + + $(P There are many issues that would have to be resolved in order for D + code to call some arbitrary C++ code that is presumed to be unmodifiable. This + list certainly isn't complete, it's just to show the scope of the + difficulties involved. + ) + + $(OL + $(LI D source code is unicode, C++'s is ASCII with code pages. Or not. + It's unspecified. This impacts the contents of string literals.) + + $(LI std::string cannot deal with multibyte UTF.) + + $(LI C++ has a tag name space. D does not. Some sort of renaming would + have to happen.) + + $(LI C++ code often relies on compiler specific extensions.) + + $(LI C++ has namespaces. D has modules. There is no obvious mapping + between the two.) + + $(LI C++ views source code as one gigantic file (after preprocessing). D + sees source code as a hierarchy of modules and packages.) + + $(LI Enum name scoping rules behave differently.) + + $(LI C++ code, despite decades of attempts to replace macro features + with inbuilt ones, relies more heavily than ever on layer after layer of + arbitrary macros. D does not always have an analog for token pasting and + stringizing.) + + $(LI Macro names have global scope across #include files, but are local + to the gigantic source files.) + + $(LI C++ has arbitrary multiple inheritance and virtual base classes. D + does not.) + + $(LI C++ does not distinguish between in, out and ref (i.e. inout) parameters.) + + $(LI The C++ name mangling varies from compiler to compiler.) + + $(LI C++ throws exceptions of arbitrary type, not just descendants of + Object.) + + $(LI C++ overloads based on const and volatile. D overloads + based on const and immutable.) + + $(LI C++ overloads operators in significantly different ways - for + example, `operator[]()` overloading for lvalue and rvalue is based on + const overloading and a proxy class.) + + $(LI C++ overloads operators like < completely independently of + >.) + + $(LI C++ does not distinguish between a class and a struct object.) + + $(LI The vtbl[] location and layout is different between C++ and D.) + + $(LI The way RTTI is done is completely different. C++ has no + classinfo.) + + $(LI D does not have two phase lookup, nor does it have Koenig (ADL) + lookup.) + + $(LI C++ relates classes with the 'friend' system, D uses packages and + modules.) + + $(LI C++ class design tends to revolve around explicit memory allocation + issues, D's do not.) + + $(LI D's template system is very different.) + + $(LI C++ has 'exception specifications'.) + + $(LI C++ has global operator overloading.) + + $(LI C++ name mangling depends on const and volatile being type + modifiers. + D name mangling depends on const and immutable being type modifiers. + D's const is also transitive, unlike C++. One cannot have a const + pointer to mutable in D. + ) + + ) + + $(P The bottom line is the language features affect the design of the code. C++ + designs just don't fit with D. Even if you could find a way to automatically + adapt between the two, the result will be about as enticing as the left side of + a honda welded to the right side of a camaro. + ) + +$(ITEM reference-counting, Why doesn't D use reference counting for garbage collection?) + + $(P Reference counting has its advantages, but some severe + disadvantages: + ) + + $(UL + + $(LI Cyclical data structures won't get freed.) + + $(LI Every pointer copy requires an increment and a corresponding + decrement - including when simply passing a reference to a function.) + + $(LI In a multithreaded app, the incs and decs must be synchronized.) + + $(LI Exception handlers (finally blocks) must be inserted to handle all the + decs so there are no leaks. Contrary to assertions otherwise, there is + no such thing as "zero overhead exceptions.") + + $(LI In order to support slicing and interior pointers, as well as + supporting reference counting on arbitrary allocations of non-object + data, a separate "wrapper" object must be allocated for each allocation + to be ref counted. This essentially doubles the number of allocations + needed.) + + $(LI The wrapper object will mean that all pointers will need to be + double-dereferenced to access the data.) + + $(LI Fixing the compiler to hide all this stuff from the programmer will + make it difficult to interface cleanly with C.) + + $(LI Ref counting can fragment the heap thereby consuming more memory + just like the gc can, though the gc typically will consume more memory + overall.) + + $(LI Ref counting does not eliminate latency problems, it just reduces + them.) + + ) + + $(P The proposed C++ shared_ptr<>, which implements ref counting, + suffers from all these faults. I haven't seen a heads up benchmark of + shared_ptr<> vs mark/sweep, but I wouldn't be surprised if shared_ptr<> + turned out to be a significant loser in terms of both performance and + memory consumption. + ) + + $(P That said, D may in the future optionally support some form of ref + counting, as rc is better for managing scarce resources like file + handles. + Furthermore, if ref counting is a must, Phobos has the + $(REF RefCounted, std,typecons) type + which implements it as a library, similar to C++'s shared_ptr<>. + ) + +$(ITEM gc_1, Isn't garbage collection slow and non-deterministic?) + + $(P Yes, but $(B all) dynamic memory management is slow and + non-deterministic, including malloc/free. + If you talk to the people who actually do real time + software, they don't use malloc/free precisely because they are not + deterministic. They preallocate all data. + However, the use of GC instead of malloc enables advanced language + constructs (especially, more powerful array syntax), which greatly + reduce the number of memory allocations which need to be made. + This can mean that GC is actually faster than explicit management. + ) + +$(ITEM pure, Can't a sufficiently smart compiler figure out that a function is pure automatically?) + + $(P The compiler infers purity (and safety, and nothrow) for delegate and function + literals. It doesn't do this for normal functions for several reasons: + ) + + $(OL + $(LI most functions call other functions, which call other functions, + until one of them calls a library routine whose source is not available + to the compiler. So it will have to assume it is not pure. + With a pure function attribute, external library functions that are pure + can be marked as pure, and then the analysis can work for enough cases + to be useful. + ) + + $(LI Since virtual functions (and by extension delegates and function + pointers) can be extended by the user at times the compiler won't see + it, they have to be assumed to be impure. + ) + + $(LI If the programmer intends for a particular function to be pure + and the compiler detects it is not, this may go unnoticed by the + programmer. Even worse, if the programmer does notice it, it may + be arbitrarily difficult to determine why the compiler thinks it is + impure - is it a programming mistake or a compiler bug? + ) + + ) + +$(ITEM minimum precision, Why allow $(D cast(float)) if it isn't supposed to work?) + + $(P The floating point rules are such that transforming $(D cast(real)cast(float)) to + $(D cast(real)) is a valid transformation. + This is because the floating point rules are written with the following principle in + mind: + ) + + $(BLOCKQUOTE An algorithm is invalid if it breaks if the floating point precision is + increased. Floating point precision is always a minimum, not a maximum.) + + $(P Programs that legitimately depended on maximum precision are:) + + $(OL + $(LI compiler/library validation test suites) + $(LI ones trying to programmatically test the precision) + ) + + $(P (1) is not of value to user programming, and there are alternate ways to test + the precision.) + + $(P (2) D has .properties that take care of that.) + + $(P Programs that rely on a maximum accuracy need to be rethought and reengineered.) + + +$(ITEM nested_forward_references, Why can't nested functions be forward referenced?) + + $(P Declarations within a function are different from declarations at module scope. + Within a function, initializers for variable declarations are guaranteed to run in + sequential order. Allowing arbitrary forward references to nested functions would + break this, because nested functions can reference any variables declared above them. + ) +---- +int first() { return second(); } +int x = first(); // x depends on y, which hasn't been declared yet. +int y = x + 1; +int second() { return y; } +---- + + $(P But, forward references of nested functions are sometimes required (eg, for + mutually recursive nested functions). The most general solution is to declare a local, + nested struct. Any member functions (and variables!) of that struct have + non-sequential semantics, so they can forward reference each other. + ) + + +$(COMMENT + > Single inheritance may be easier to implement, but you are losing + >something. It's a little concerning how often folks here take the + >opinion that "Feature X has problems and I never use it anyway, so no + >body else 'really' needs it." I'm not specificly blaming you, but i've + >lost track of how many time if seen that reasoning tonight. I'm afraid + >I'll see it a lot in the 275 I still have to read. + + + Your reasoning has merit. The counterargument (and I've discussed + this at length with my colleagues) is that C++ gives you a dozen ways + and styles to do X. Programmers tend to develop specific styles and do + things in certain ways. This leads to one programmer's use of C++ to + be radically different than another's, almost to the point where + they are different languages. C++ is a huge language, and C++ + programmers tend to learn particular "islands" in the language + and not be too familiar with the rest of it. + + Hence one idea behind D is to *reduce* the number of ways X can be + accomplished, and reduce the balkanization of programmer expertise. + Then, one programmer's coding style will look more like another's, + with the intended result that legacy D code will be more maintainable. + For example, over the years I've seen dozens of different ways that + debug code was inserted into a program, all very different. D has one + way - with the debug attribute/statement. C++ has a dozen string + classes plus the native C way of doing strings. D has one way of + doing strings. + + I intend to further help this along by writing a D style guide, + "The D Way". There's a start on it all ready with the document + on how to do error handling: + + www.digitalmars.com/d/errors.html + +) + +) + +Macros: + TITLE=D 2.0 FAQ + ITEMR=$(LI $(RELATIVE_LINK2 $1, $+)) + ITEM=
$(H3 $+) + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/hijack.dd b/articles/hijack.dd similarity index 95% rename from hijack.dd rename to articles/hijack.dd index 651ff952ff..9a87a0272e 100644 --- a/hijack.dd +++ b/articles/hijack.dd @@ -2,7 +2,7 @@ Ddoc $(D_S Function Hijacking Mitigation, -
$(DIGG)
+$(HEADERNAV_TOC) $(P As software becomes more complex, we become more reliant on module @@ -21,7 +21,7 @@ programming language. ) -$(SECTION2 Global Function Hijacking, +$(SECTION2 $(LNAME2 global-function-hijacking, Global Function Hijacking), $(P Let's say we are developing an application that imports two modules: X from the XXX Corporation, and Y from the YYY Corporation. @@ -130,7 +130,7 @@ to add the rules: $(OL $(LI by default functions can only overload against other functions in the same module) -$(LI if a name is found in more than one scope, in order to use it it must +$(LI if a name is found in more than one scope, in order to use it, it must be fully qualified) $(LI in order to overload functions from multiple modules together, an alias statement is used to merge the overloads) @@ -149,7 +149,7 @@ complain about it? The solution turned out to be to introduce the notion of overload sets. ) -$(SECTION3 Overload Sets, +$(SECTION2 $(LNAME2 overload-sets, Overload Sets), $(P An overload set is formed by a group of functions with the same name declared @@ -203,8 +203,8 @@ $(P If overloading of $(CODE foo) between X and Y is desired, the following can import X; import Y; -alias X.foo foo; -alias Y.foo foo; +alias foo = X.foo; +alias foo = Y.foo; void abc() { @@ -214,7 +214,7 @@ void abc() $(P and no error is generated. The difference here is that the user deliberately combined the overload sets in X and Y, and so presumably -both knows what he's doing and is willing to check the $(CODE foo)'s when +both knows what he's doing and is willing to check the $(CODE foo)s when X or Y is updated. ) @@ -222,7 +222,7 @@ X or Y is updated. ) -$(SECTION2 Derived Class Member Function Hijacking, +$(SECTION2 $(LNAME2 derived-class-members, Derived Class Member Function Hijacking), $(P There are more cases of function hijacking. Imagine a class $(CODE A) coming from AAA Corporation: @@ -300,7 +300,7 @@ an analogous alias declaration. ) -$(SECTION2 Base Class Member Function Hijacking, +$(SECTION2 $(LNAME2 base-class-member, Base Class Member Function Hijacking), $(P I bet you suspected there was more to it than that, and you'd be right. Hijacking can go the other way, too. A derived class can hijack a base @@ -397,7 +397,7 @@ a base class member function. ) -$(SECTION2 Derived Class Member Function Hijacking #2, +$(SECTION2 $(LNAME2 derived-class-member-function-2, Derived Class Member Function Hijacking #2), $(P There's one last case of base member function hijacking a derived member function. Consider: @@ -451,7 +451,7 @@ class A { void def() { - foo(1); + foo(1); } void foo(long); @@ -534,7 +534,7 @@ vtbl[] gets an error entry.) ) -$(SECTION2 Conclusion, +$(SECTION2 $(LNAME2 conclusion, Conclusion), $(P Function hijacking is a pernicious and particularly nasty problem in complex C++ and Java programs because there is no defense against it @@ -544,7 +544,7 @@ semantics can defend against it without sacrificing any power or performance. ) -$(SECTION2 References, +$(SECTION2 $(LNAME2 references, References), $(UL $(LI $(LINK2 http://www.digitalmars.com/d/archives/digitalmars/D/Hijacking_56458.html, digitalmars.D - Hijacking)) @@ -566,6 +566,5 @@ $(LI Andrei Alexandrescu) ) Macros: - TITLE=Hijack - WIKI=Hijack - CATEGORY_ARTICLES=$0 + TITLE=Hijack + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/articles/index.dd b/articles/index.dd new file mode 100644 index 0000000000..5d71e31192 --- /dev/null +++ b/articles/index.dd @@ -0,0 +1,212 @@ +Ddoc + +$(D_S Articles, + $(P + More articles can be found on the corresponding + $(LINK2 https://wiki.dlang.org/Articles, wiki page). + ) + + $(DIVC boxes, + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/faq.html, FAQ)) + $(P Frequently answered questions about D.) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/const-faq.html, const(FAQ))) + $(P Frequently answered questions about D's $(D const) and + $(D immutable).) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/d-floating-point.html, Floating Point)) + $(P Don Clugston goes into detail about floating point + numbers in D and the pitfalls one may encounter.) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/warnings.html, Warnings)) + $(P This is about compiler warnings in general, and dmd's + warnings in particular.) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/rationale.html, Rationale)) + $(P Questions about the reasons for various design decisions for + D often come up. This addresses many of them.) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/builtin.html, Builtin Rationale)) + $(P D offers several capabilities built in to the core language + that are implemented as libraries in other languages. This + article answers why.) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/ctod.html, C to D)) + $(P Coming from C? Here are various examples comparing $(I the D + way) to $(I the C way).) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/cpptod.html, C++ to D)) + $(P Coming from C++? Here are various examples comparing $(I the + D way) to $(I the C++ way).) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/pretod.html, C Preprocessor vs D)) + $(P D doesn't have a preprocessor. This article shows how to do + in D what would be a task for the preprocessor in C.) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/code_coverage.html, Code coverage analysis)) + $(P D compilers come with a builtin code coverage analyzer. + This article explains why and how to use it.) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/exception-safe.html, Exception Safety)) + $(P This article is about exceptions and how RAII and scope + guard statements relate to them.) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/hijack.html, Hijacking)) + $(P Function hijacking is when old code accidentally calls + a newly added or changed function because it shadows the + intended one. This article is about how D prevents + different kinds of hijacking.) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/intro-to-datetime.html, Introduction to + std.datetime)) + $(P Jonathan M Davis presents $(D std.datetime) which was added + in version 2.052 (Jul 10, 2011), and compares it to the + superseded $(D std.date).) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/lazy-evaluation.html, Lazy Evaluation)) + $(P Walter Bright goes into the details of lazy parameters in + D.) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/migrate-to-shared.html, Migrating to Shared)) + $(P Since version 2.030 (May 11, 2009) D uses thread local + storage (TLS) by default for static and global variables. + The article shows the alternatives to TLS that are available + in D.) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/mixin.html, String Mixins)) + $(P A short article about D's $(D mixin) statement which allows + to insert arbitrary code from a string, and how it compares + to the C preprocessor.) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/regular-expression.html, Regular Expressions)) + $(P Dmitry Olshansky shows how to use regular expressions in D + with $(D std.regex).) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/safed.html, SafeD)) + $(P Bartosz Milewski writes about SafeD, the memory-safe + subset of D.) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/templates-revisited.html, Templates Revisited)) + $(P Walter Bright writes about how D improves upon C++ + templates.) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/constraints.html, + Template Constraints)) + $(P A template can be constrained to only apply when a compile-time + evaluable boolean expression is true.) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/ctarguments.html, Compile-time Sequences)) + $(P A compile-time sequence is a sequence of compile-time entities - + types, symbols (names) and values. This + article shows how to work with them.) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/variadic-function-templates.html, + Variadic Templates)) + $(P This article is about the D idiom of implementing variadic + functions with variadic templates.) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/template-comparison.html, + Template Comparison)) + $(P + A comparison between D's and C++'s templates. + ) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/d-array-article.html, D Slices)) + $(P Steven Schveighoffer writes about slices and dynamic arrays + in D. Unfortunately, this article uses slightly different + terminology than the language reference: What the article + calls a $(I slice) is a $(I dynamic array) in the language + reference, and what the article calls a $(I dynamic array) + is not named specifically by the language reference. Still, + the article is a great help in getting a good understanding + of D's array semantics.) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/cppcontracts.html, + D's Contract Programming vs C++'s)) + $(P + A comparison between D's and C++'s contract programming. + ) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/dll-linux.html, + Writing Shared Libraries on Linux)) + $(P + A guide to writing shared libraries with D on Linux. + ) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/RefReturnScope.html, + Coralling Wild Pointers with `ref return scope`)) + $(P + How to use the `ref`, `return` and `scope` annotations + to prevent the escape of pointers. Escaping pointers can + cause memory corruption and other problems. + ) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)articles/dll-windows.html, + Creating Windows DLLs)) + $(P + Windows DLLs are quite different from shared libraries + on other platforms. This article shows how to do them. + ) + ) + ) + ) +) + +Macros: + TITLE=Articles + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/intro-to-datetime.dd b/articles/intro-to-datetime.dd similarity index 87% rename from intro-to-datetime.dd rename to articles/intro-to-datetime.dd index d99f60df5c..8041f8dffd 100644 --- a/intro-to-datetime.dd +++ b/articles/intro-to-datetime.dd @@ -2,6 +2,8 @@ Ddoc $(D_S $(TITLE), +Clock within D Man + $(P $(I by Jonathan M Davis)) $(H2 Introduction) @@ -35,7 +37,7 @@ $(D_S $(TITLE), $(P $(STD_DATETIME), on the other hand, is very much an object-oriented solution, and it's not C-based at all. Rather, its API is based on - $(WEB www.boost.org/doc/libs/release/doc/html/date_time.html, Boost)'s + $(HTTP www.boost.org/doc/libs/release/doc/html/date_time.html, Boost)'s types for handling dates and times (though they're far from identical). So, it's a bit of a paradigm shift to move from $(STD_DATE) to $(STD_DATETIME). Don't expect much to be the same between the two. @@ -64,9 +66,9 @@ $(D_S $(TITLE), $(P The duration types can actually be found in $(CORE_TIME). They are $(DURATION) and $(TICK_DURATION). $(TICK_DURATION) is intended for - precision timing and is used primarily with $(XREF datetime, StopWatch) + precision timing and is used primarily with $(REF_SHORT StopWatch, std,datetime) and the benchmarking functions found in $(STD_DATETIME) - such as - $(XREF datetime, benchmark) - and you're unlikely to use it outside of + $(REF_SHORT benchmark, std,datetime) - and you're unlikely to use it outside of using them. $(DURATION), on the other hand, you're likely to use quite a bit.) @@ -78,7 +80,7 @@ $(D_S $(TITLE), (the $(D total) function).) $(P Generally, a $(DURATION) is created in one of two ways: by subtracting - two time points or with the $(FULL_CXREF time, dur) function. So, for + two time points or with the $(REF dur, core,time) function. So, for instance, if you subtracted a time point which represented 17:02 from a time point which represented 6:07, you'd get a $(DURATION) which represented 10 hours and 55 minutes. Or, if you wanted to create a @@ -102,8 +104,8 @@ assert(duration.total!"hnsecs"() == 393_000_000_000); Phobos which take a duration of time take an actual $(DURATION) rather than a naked number (most currently take both, though the versions which take a naked number are going to be deprecated). For instance, - $(FULL_CXREF thread, sleep) takes a $(DURATION), as does - $(FULL_XREF concurrency, receiveTimeout). So, durations are used outside + $(REF sleep, core,thread) takes a $(DURATION), as does + $(REF receiveTimeout, std,concurrency). So, durations are used outside of just interacting with $(CORE_TIME) and $(STD_DATETIME).) $(P One particular thing to note here is how both $(D dur) and $(D total) @@ -115,7 +117,7 @@ assert(duration.total!"hnsecs"() == 393_000_000_000); however that very few functions take $(D "nsecs"), because nothing in $(STD_DATETIME), and very little in $(CORE_TIME), has precision greater than hnsecs (100 ns). Also, a number of functions (such as - $(FULL_CXREF time, dur)) do not take $(D "years") or $(D "months"), + $(REF dur, core,time)) do not take $(D "years") or $(D "months"), because it is not possible to convert between years or months and smaller units without a specific date. So, while you can add a $(DURATION) to a time point, if you want to add years or months to one, @@ -170,13 +172,13 @@ assert(tod == dateTime.timeOfDay); them, but you do risk problems with DST when creating a $(SYSTIME) from the other 3 time points unless you specifically create the $(SYSTIME) with a $(TIMEZONE) which doesn't have DST (such as - $(FULL_XREF datetime, UTC)), since when a time zone has DST, one hour of + $(REF UTC, std,datetime)), since when a time zone has DST, one hour of the year does not exist, and another exists twice. You can also convert to and from unix time, which is what you're dealing with in C with $(D time_t).) $(P The one other related type which I should mention at this point is - $(FULL_CXREF time, FracSec). It holds fractional seconds, and it is + $(REF FracSec, core,time). It holds fractional seconds, and it is what you get from a $(DURATION) or $(SYSTIME) when you specifically ask for the fractional portion of the time.) @@ -234,7 +236,7 @@ assert(stdTime == st.stdTime); C# uses, so if you need to interface with C# for any reason, converting between its representation of time and $(STD_DATETIME)'s representation is extremely easy, since no conversion is necessary. - $(WEB msdn.microsoft.com/en-us/library/system.datetime.aspx, + $(HTTP msdn.microsoft.com/en-us/library/system.datetime.aspx, C#'s $(D DateTime)) uses both the same units and epoch for its internal representation (which it calls $(D Ticks)) as $(SYSTIME), though unlike $(SYSTIME), it doesn't work with negative values (which would be B.C.) @@ -253,7 +255,7 @@ assert(stdTime == st.stdTime); at all or are dealing with anything which needs to worry about DST, you should use $(SYSTIME). Because it keeps its time internally in UTC, it avoids problems with DST. And while it does have a time zone - component, it defaults to $(FULL_XREF datetime, LocalTime) (which + component, it defaults to $(REF LocalTime, std,datetime) (which is the time zone type for the local time of the system), so you don't generally have to deal directly with time zones if you don't want to.) @@ -264,7 +266,7 @@ assert(stdTime == st.stdTime); That's unlikely to be necessary, however (and if you think that you have come up with such a class which would be generally useful, please bring it up in the - $(WEB www.digitalmars.com/NewsGroup.html, digitalmars.D newsgroup), + $(HTTP www.digitalmars.com/NewsGroup.html, digitalmars.D newsgroup), since if it's truly generally useful, we may want some version of it in $(STD_DATETIME)). Read their documentation for more details. Most applications shouldn't have to worry about time zones though, beyond @@ -499,8 +501,8 @@ setTimes("yourfile.txt", sysTime, sysTime + dur!"msecs"(5)); use as discussed previously (such as its std time or its ISO string), or you're going to have be converting between $(D d_time) and $(SYSTIME). At present, the functions - $(FULL_XREF datetime, sysTimeToDTime) and - $(FULL_XREF datetime, dTimeToSysTime) will do those conversions for you. + $(REF sysTimeToDTime, std,datetime) and + $(REF dTimeToSysTime, std,datetime) will do those conversions for you. So, converting between the two formats is easy. However, because $(D d_time) is going away, those functions will be going away. That means that you either need to refactor your code so that those functions @@ -538,8 +540,8 @@ setTimes("yourfile.txt", sysTime, sysTime + dur!"msecs"(5)); Simply calculate the total UTC offset (so add in the DST offset if it applies for the date in question) in minutes and create a $(SIMPLETZ) with that. Note that $(STD_DATETIME) treats west of UTC as - $(I negative) (for some reason, some systems - particularly Posix stuff - - use a positive offset from UTC when west of UTC, in spite of the fact + $(I negative) (for some reason, some systems - particularly Posix stuff - + use a positive offset from UTC when west of UTC, in spite of the fact that when talking about time zones, negative is always used for west of UTC, and that's what the ISO standard strings do). So, you may have to adjust your values accordingly. Regardless, be very careful to make @@ -560,20 +562,20 @@ immutable tzWithoutDST = new SimpleTimeZone(utcOffset); $(P The last thing that I have to note is some differences in numerical values between $(STD_DATE) and $(STD_DATETIME). - $(FULL_XREF date, Date)'s $(D weekday) property gives Sunday a value of - 1, but $(FULL_XREF date, weekDay) gives Sunday a value of 0. - $(FULL_XREF datetime, DayOfWeek) gives Sunday a value of 0. So, + $(D std.date.Date)'s $(D weekday) property gives Sunday a value of + 1, but $(D std.date.weekDay) gives Sunday a value of 0. + $(REF DayOfWeek, std,datetime) gives Sunday a value of 0. So, depending on which part of $(STD_DATE) you're dealing with it, it may or may not match what $(STD_DATETIME) is doing for the numerical values of weekdays. Months have a similar problem. - $(FULL_XREF date, Date)'s $(D month) property gives January a value of - 1 - which matches what $(FULL_XREF datetime, Month) does - but - $(FULL_XREF date, monthFromTime) gives January a value of 0. So, + $(D std.date.Date)'s $(D month) property gives January a value of + 1 - which matches what $(REF Month, std,datetime) does - but + $(D std.date.monthFromTime) gives January a value of 0. So, just as with the days of the week, you have to be careful with the numerical values of the months. Whether $(STD_DATETIME) matches what $(STD_DATE) is doing depends on which part of $(STD_DATE) you're using. And as you'll notice, it's not even consistent as to whether - $(FULL_XREF date, Date) or the free function in $(STD_DATE) is the one + $(D std.date.Date) or the free function in $(STD_DATE) is the one which matches $(STD_DATETIME). So, you should be very careful when converting code which uses numerical values for either the days of the week or the months of the year.) @@ -581,9 +583,9 @@ immutable tzWithoutDST = new SimpleTimeZone(utcOffset); $(BOOKTABLE $(H3 std.date symbols and their std.datetime counterparts), $(TR $(TD $(B $(STD_DATE))) $(TD $(B $(STD_DATETIME) Equivalent))) - $(TR $(TD $(XREF date, d_time)) + $(TR $(TD $(D d_time)) $(TD The closest would be $(SYSTIME).)) - $(TR $(TD $(XREF date, d_time_nan)) + $(TR $(TD $(D d_time_nan)) $(TD There is no equivalent. $(SYSTIME).$(D init), which has a $(D null) $(TIMEZONE) object, would be the closest, but once CTFE advances to the point that you can new up class objects @@ -592,26 +594,26 @@ immutable tzWithoutDST = new SimpleTimeZone(utcOffset); invalid. $(STD_DATETIME) in general tries to avoid having any invalid states for any of its types. It's intended that creating such values be impossible.)) - $(TR $(TD $(XREF date, Date)) + $(TR $(TD $(D Date)) $(TD $(SYSTIME))) - $(TR $(TD $(XREF date, Date).$(D year)) + $(TR $(TD $(D Date).$(D year)) $(TD $(SYSTIME).$(D year))) - $(TR $(TD $(XREF date, Date).$(D month)) + $(TR $(TD $(D Date).$(D month)) $(TD $(SYSTIME).$(D month))) - $(TR $(TD $(XREF date, Date).$(D day)) + $(TR $(TD $(D Date).$(D day)) $(TD $(SYSTIME).$(D day))) - $(TR $(TD $(XREF date, Date).$(D hour)) + $(TR $(TD $(D Date).$(D hour)) $(TD $(SYSTIME).$(D hour))) - $(TR $(TD $(XREF date, Date).$(D minute)) + $(TR $(TD $(D Date).$(D minute)) $(TD $(SYSTIME).$(D minute))) - $(TR $(TD $(XREF date, Date).$(D second)) + $(TR $(TD $(D Date).$(D second)) $(TD $(SYSTIME).$(D second))) - $(TR $(TD $(XREF date, Date).$(D ms)) + $(TR $(TD $(D Date).$(D ms)) $(TD $(SYSTIME).$(D fracSec.msecs))) - $(TR $(TD $(XREF date, Date).$(D weekday)) + $(TR $(TD $(D Date).$(D weekday)) $(TD $(SYSTIME).$(D dayOfWeek) - but note that the values are off by 1.)) - $(TR $(TD $(XREF date, Date).$(D tzcorrection)) + $(TR $(TD $(D Date).$(D tzcorrection)) $(TD -------------------- immutable tz = sysTime.timezone; @@ -621,40 +623,40 @@ auto tzcorrection = convert!("hnsecs", "minutes")(diff); However, it looks like $(D tzcorrection) is broken, so you're probably not using it in your code anyway. )) - $(TR $(TD $(XREF date, Date).$(D parse)) + $(TR $(TD $(D Date).$(D parse)) $(TD $(SYSTIME).$(D fromISOString), $(SYSTIME).$(D fromISOExtString), and $(SYSTIME).$(D fromSimpleString), but the formats of the - strings differ from what $(FULL_XREF date, Date).$(D parse) + strings differ from what $(D std.date.Date).$(D parse) accepts.)) - $(TR $(TD $(XREF date, ticksPerSecond)) + $(TR $(TD $(D ticksPerSecond)) $(TD There is no equivalent. It's only relevant to $(D d_time).)) - $(TR $(TD $(XREF date, toISO8601YearWeek)) + $(TR $(TD $(D toISO8601YearWeek)) $(TD $(SYSTIME).$(D isoWeek))) - $(TR $(TD $(XREF date, hourFromTime)) + $(TR $(TD $(D hourFromTime)) $(TD $(SYSTIME).$(D hour))) - $(TR $(TD $(XREF date, minFromTime)) + $(TR $(TD $(D minFromTime)) $(TD $(SYSTIME).$(D minute))) - $(TR $(TD $(XREF date, secFromTime)) + $(TR $(TD $(D secFromTime)) $(TD $(SYSTIME).$(D second))) - $(TR $(TD $(XREF date, daysInYear)) + $(TR $(TD $(D daysInYear)) $(TD $(D sysTime.isLeapYear ? 366 : 365))) - $(TR $(TD $(XREF date, dayFromYear)) + $(TR $(TD $(D dayFromYear)) $(TD $(D (sysTime - SysTime(Date(1970, 1, 1), UTC())).total!"days"()))) - $(TR $(TD $(XREF date, yearFromTime)) + $(TR $(TD $(D yearFromTime)) $(TD $(SYSTIME).$(D year))) - $(TR $(TD $(XREF date, inLeapYear)) + $(TR $(TD $(D inLeapYear)) $(TD $(SYSTIME).$(D isLeapYear))) - $(TR $(TD $(XREF date, monthFromTime)) + $(TR $(TD $(D monthFromTime)) $(TD $(SYSTIME).$(D month) - but note that the values are off by 1.)) - $(TR $(TD $(XREF date, dateFromTime)) + $(TR $(TD $(D dateFromTime)) $(TD $(SYSTIME).$(D day))) - $(TR $(TD $(XREF date, weekDay)) + $(TR $(TD $(D weekDay)) $(TD $(SYSTIME).$(D dayOfWeek))) - $(TR $(TD $(XREF date, UTCtoLocalTime)) + $(TR $(TD $(D UTCtoLocalTime)) $(TD $(SYSTIME).$(D toUTC))) - $(TR $(TD $(XREF date, dateFromNthWeekdayOfMonth)) + $(TR $(TD $(D dateFromNthWeekdayOfMonth)) $(TD -------------------- //There is no equivalent. This is a possible implementation. @@ -665,9 +667,9 @@ int dateFromNthWeekdayOfMonth(int year, Month month, auto target = first; immutable targetDOTW = target.dayOfWeek; - if(targetDOTW != dow) + if (targetDOTW != dow) { - if(targetDOTW < dow) + if (targetDOTW < dow) target += dur!"days"(dow - targetDOTW); else { @@ -678,60 +680,60 @@ int dateFromNthWeekdayOfMonth(int year, Month month, target += dur!"weeks"(n - 1); - if(target.month != first.month) + if (target.month != first.month) target -= dur!"weeks"(1); return cast(int)((target - first).total!"days"()) + 1; } -------------------- )) - $(TR $(TD $(XREF date, daysInMonth)) + $(TR $(TD $(D daysInMonth)) $(TD $(SYSTIME).$(D endOfMonthDay); Actually, this name is overly easy to confuse with $(D endOfMonth) - which returns a $(SYSTIME) of the last day of the month. I will probably rename this to $(D daysInMonth). But if I do, it won't be until the next release (2.054), and this name will be around until it's gone through the full deprecation cycle.)) - $(TR $(TD $(XREF date, UTCtoString)) + $(TR $(TD $(D UTCtoString)) $(TD There is no equivalent. You could probably parse and recombine $(D core.stdc.time.ctime) and $(SYSTIME).$(D toISOExtString) to create it though. However, this function appears to be fairly buggy in the first place, so odds are that your code isn't using it anyway.)) - $(TR $(TD $(XREF date, toUTCString)) + $(TR $(TD $(D toUTCString)) $(TD There is no equivalent. You could probably parse and recombine $(D core.stdc.time.ctime) and $(SYSTIME).$(D toISOExtString) to create it though.)) - $(TR $(TD $(XREF date, toDateString)) + $(TR $(TD $(D toDateString)) $(TD There is no equivalent. You could probably parse and recombine $(D core.stdc.time.ctime) and $(SYSTIME).$(D toISOExtString) to create it though. However, this function appears to be fairly buggy in the first place, so odds are that your code isn't using it anyway.)) - $(TR $(TD $(XREF date, toTimeString)) + $(TR $(TD $(D toTimeString)) $(TD There is no equivalent. You could probably parse and recombine $(D core.stdc.time.ctime) and $(SYSTIME).$(D toISOExtString) to create it though. However, this function appears to be fairly buggy in the first place, so odds are that your code isn't using it anyway.)) - $(TR $(TD $(XREF date, parse).$(D parse)) + $(TR $(TD $(D parse).$(D parse)) $(TD $(SYSTIME).$(D fromISOString), $(SYSTIME).$(D fromISOExtString), and $(SYSTIME).$(D fromSimpleString), but the formats of the - strings differ from what $(FULL_XREF date, parse) accepts.)) - $(TR $(TD $(XREF date, getUTCtime)) + strings differ from what $(D std.date.parse) accepts.)) + $(TR $(TD $(D getUTCtime)) $(TD $(D Clock.currTime(UTC())) if you want the $(SYSTIME) to have its time zone be $(UTC). More likely though, you'll just use $(D Clock.currTime()). Its internal time is in UTC regardless.)) - $(TR $(TD $(XREF date, DosFileTime)) - $(TD $(XREF datetime, DosFileTime))) - $(TR $(TD $(XREF date, toDtime)) - $(TD $(XREF datetime, DosFileTimeToSysTime))) - $(TR $(TD $(XREF date, toDosFileTime)) - $(TD $(XREF datetime, SysTimeToDosFileTime))) - $(TR $(TD $(XREF date, benchmark)) - $(TD $(XREF datetime, benchmark))) + $(TR $(TD $(D DosFileTime)) + $(TD $(REF_SHORT DosFileTime, std,datetime))) + $(TR $(TD $(D toDtime)) + $(TD $(REF_SHORT DosFileTimeToSysTime, std,datetime))) + $(TR $(TD $(D toDosFileTime)) + $(TD $(REF_SHORT SysTimeToDosFileTime, std,datetime))) + $(TR $(TD $(D benchmark)) + $(TD $(REF_SHORT benchmark, std,datetime))) ) $(P Note that I'm not an expert on what does and doesn't work in @@ -751,49 +753,41 @@ int dateFromNthWeekdayOfMonth(int year, Month month, $(STD_DATETIME) and will get you well on your way to being able to migrate your code from $(STD_DATE) to $(STD_DATETIME). If you have any further questions, please ask them on the - $(WEB www.digitalmars.com/NewsGroup.html, digitalmars.D.learn newsgroup). + $(HTTP www.digitalmars.com/NewsGroup.html, digitalmars.D.learn newsgroup). And if there's a major use case of $(STD_DATE) which is not easy to convert over to $(STD_DATETIME) which I missed in this article and you think should be in it, please feel free to bring it up on the - $(WEB www.digitalmars.com/NewsGroup.html, digitalmars.D newsgroup), + $(HTTP www.digitalmars.com/NewsGroup.html, digitalmars.D newsgroup), and if need be, I'll update this article with the relevant information.) ) Macros: - CATEGORY_ARTICLES=$0 - BOOKTABLE =
$2
$1
- D = $0 - D = $0 - H2 =

$0

- H3 =

$0

+ BOOKTABLE =
$2
$1
RED = $0 TITLE = Introduction to std.datetime - WEB = $(LINK2 http://$1,$2) - - CXREF = $(D $2) - FULL_CXREF = $(D core.$1.$2) - XREF = $(D $2) - FULL_XREF = $(D std.$1.$2) - CORE_TIME=$(D core.time) - STD_DATETIME=$(D std.datetime) - STD_DATE=$(D std.date) - STD_FILE=$(D std.file) - - DATE=$(XREF datetime, Date) - DATETIME=$(XREF datetime, DateTime) - DURATION=$(CXREF time, Duration) - FRACSEC=$(CXREF time, FracSec) - INTERVAL=$(XREF datetime, Interval) - LOCALTIME=$(XREF datetime, LocalTime) - NEGINF_INTERVAL=$(XREF datetime, NegInfInterval) - POSINF_INTERVAL=$(XREF datetime, PosInfInterval) - POSIXTZ=$(XREF datetime, PosixTimeZone) - STOPWATCH=$(XREF datetime, StopWatch) - SIMPLETZ=$(XREF datetime, SimpleTimeZone) - SYSTIME=$(XREF datetime, SysTime) - TIMEOFDAY=$(XREF datetime, TimeOfDay) - TICK_DURATION=$(CXREF time, TickDuration) - TIMEZONE=$(XREF datetime, TimeZone) - UTC=$(XREF datetime, UTC) - WINDOWSTZ=$(XREF datetime, WindowsTimeZone) + + CORE_TIME=$(MREF core,time) + STD_DATETIME=$(MREF std,datetime) + STD_DATE=$(D std.date) + STD_FILE=$(MREF std,file) + + DATE=$(REF_SHORT Date, std,datetime) + DATETIME=$(REF_SHORT DateTime, std,datetime) + DURATION=$(REF_SHORT Duration, core,time) + FRACSEC=$(REF_SHORT FracSec, core,time) + INTERVAL=$(REF_SHORT Interval, std,datetime) + LOCALTIME=$(REF_SHORT LocalTime, std,datetime) + NEGINF_INTERVAL=$(REF_SHORT NegInfInterval, std,datetime) + POSINF_INTERVAL=$(REF_SHORT PosInfInterval, std,datetime) + POSIXTZ=$(REF_SHORT PosixTimeZone, std,datetime) + STOPWATCH=$(REF_SHORT StopWatch, std,datetime) + SIMPLETZ=$(REF_SHORT SimpleTimeZone, std,datetime) + SUBNAV=$(SUBNAV_ARTICLES) + SYSTIME=$(REF_SHORT SysTime, std,datetime) + TIMEOFDAY=$(REF_SHORT TimeOfDay, std,datetime) + TICK_DURATION=$(REF_SHORT TickDuration, core,time) + TIMEZONE=$(REF_SHORT TimeZone, std,datetime) + UTC=$(REF_SHORT UTC, std,datetime) + WINDOWSTZ=$(REF_SHORT WindowsTimeZone, std,datetime) + _= diff --git a/lazy-evaluation.dd b/articles/lazy-evaluation.dd similarity index 75% rename from lazy-evaluation.dd rename to articles/lazy-evaluation.dd index 17500614be..1187146a35 100644 --- a/lazy-evaluation.dd +++ b/articles/lazy-evaluation.dd @@ -17,14 +17,14 @@ do lazy evaluation: void test(int* p) { if (p && p[0]) - ... + ... } --- $(P The second expression $(D p[0]) is not evaluated unless $(D p) -is not $(B null). +is not $(D null). If the second expression was not lazily evaluated, it would -generate a runtime fault if $(D p) was $(B null). +generate a runtime fault if $(D p) was $(D null). ) $(P While invaluable, the lazy evaluation operators have significant @@ -34,10 +34,10 @@ value: ) --- -void log(char[] message) +void log(const(char)[] message) { if (logging) - fwritefln(logfile, message); + fwritefln(logfile, message); } --- @@ -63,7 +63,8 @@ $(P One way to fix it is by using lazy evaluation: --- void foo(int i) { - if (logging) log("Entering foo() with i set to " ~ toString(i)); + if (logging) + log("Entering foo() with i set to " ~ toString(i)); } --- @@ -94,10 +95,10 @@ is possible in the D programming language using a delegate parameter: ) --- -void log(char[] delegate() dg) +void log(const(char)[] delegate() dg) { if (logging) - fwritefln(logfile, dg()); + fwritefln(logfile, dg()); } void foo(int i) @@ -122,10 +123,10 @@ The functions then become: ) --- -void log(lazy char[] dg) +void log(lazy const(char)[] dg) { if (logging) - fwritefln(logfile, dg()); + fwritefln(logfile, dg()); } void foo(int i) @@ -152,7 +153,7 @@ times. The pattern is: --- for (int i = 0; i < count; i++) - exp; + exp; --- $(P This pattern can be encapsulated in a function using lazy evaluation: @@ -162,7 +163,7 @@ $(P This pattern can be encapsulated in a function using lazy evaluation: void dotimes(int count, lazy void exp) { for (int i = 0; i < count; i++) - exp(); + exp(); } --- @@ -173,7 +174,7 @@ $(P It can be used like: void foo() { int x = 0; - dotimes(10, writef(x++)); + dotimes(10, write(x++)); } --- @@ -184,7 +185,7 @@ $(CONSOLE 0123456789 ) -$(P More complex user defined control structures are possible. +$(P More complex user-defined control structures are possible. Here's a method to create a switch like structure: ) @@ -192,7 +193,7 @@ Here's a method to create a switch like structure: bool scase(bool b, lazy void dg) { if (b) - dg(); + dg(); return b; } @@ -202,8 +203,9 @@ bool scase(bool b, lazy void dg) void cond(bool delegate()[] cases ...) { foreach (c; cases) - { if (c()) - break; + { + if (c()) + break; } } --- @@ -217,10 +219,10 @@ void foo() int v = 2; cond ( - scase(v == 1, writefln("it is 1")), - scase(v == 2, writefln("it is 2")), - scase(v == 3, writefln("it is 3")), - scase(true, writefln("it is the default")) + scase(v == 1, writeln("it is 1")), + scase(v == 2, writeln("it is 2")), + scase(v == 3, writeln("it is 3")), + scase(true, writeln("it is the default")) ); } --- @@ -244,24 +246,19 @@ Abc p; p = foo(); if (!p) throw new Exception("foo() failed"); -p.bar(); // now use p +p.bar(); // now use p --- -$(P Because throw is a statement, not an expression, expressions that -need to do this need to be broken up into multiple statements, -and extra variables are introduced. -(For a thorough treatment of this issue, see Andrei Alexandrescu and -Petru Marginean's paper -$(LINK2 http://erdani.org/publications/cuj-06-2003.html, Enforcements)). +$(P With lazy evaluation, this can all be encapsulated into a single function: ) --- -Abc Enforce(Abc p, lazy char[] msg) +Abc Enforce(Abc p, lazy const(char)[] msg) { if (!p) - throw new Exception(msg()); + throw new Exception(msg()); return p; } --- @@ -278,15 +275,15 @@ template function: ) --- -T Enforce(T)(T p, lazy char[] msg) +T Enforce(T)(T p, lazy const(char)[] msg) { if (!p) - throw new Exception(msg()); + throw new Exception(msg()); return p; } --- -

Conclusion

+$(H2 Conclusion) $(P Lazy evaluation of function arguments dramatically extends the expressive power of functions. It enables the encapsulation into functions of many @@ -294,21 +291,19 @@ common coding patterns and idioms that previously were too clumsy or impractical to do. ) -

Acknowledgements

+$(H2 Acknowledgements) - $(P I gratefully acknowledge the inspiration and assistance - of Andrei Alexandrescu, Bartosz Milewski, and David Held. - The D community helped a lot with much constructive - criticism, such as the thread starting with - Tomasz Stachowiak in $(NG_digitalmars_D 41633). - ) + $(P I gratefully acknowledge the inspiration and assistance + of Andrei Alexandrescu, Bartosz Milewski, and David Held. + The D community helped a lot with much constructive + criticism, such as the thread starting with + Tomasz Stachowiak in $(NG_digitalmars_D 41633). + ) ) Macros: - TITLE=LazyEvaluationOfFunctionArguments - WIKI=LazyEvaluation - CATEGORY_ARTICLES=$0 - - NG_digitalmars_D = D/$0 + TITLE=Lazy Evaluation Of Function Arguments + SUBNAV=$(SUBNAV_ARTICLES) + NG_digitalmars_D = D/$0 diff --git a/articles/migrate-to-shared.dd b/articles/migrate-to-shared.dd new file mode 100644 index 0000000000..5799815dac --- /dev/null +++ b/articles/migrate-to-shared.dd @@ -0,0 +1,231 @@ +Ddoc + +$(D_S $(TITLE), + +$(HEADERNAV_TOC) + + $(P Starting with + $(DDLINK changelog/2.030, Change Log: 2.030, dmd version 2.030), + the default storage class + for statics and globals will be + $(DDSUBLINK spec/glossary, tls, thread local storage (TLS)), rather + than the classic global data segment. + While most D code should just compile and run successfully without + change, there can be some issues. + ) + +$(H2 $(LNAME2 performance, Performance of TLS variables)) + + $(P Reading or writing TLS variables is potentially slower than for + classic global variables. The exact difference depends, among others, + on compiler code generation settings and the target architecture. + The performance difference ranges from negligible (Windows) to a call + to a special function (PIC on Linux, macOS, *BSD. Search for example + for $(D __tls_get_address) online). For non-PIC, the performance + difference is much smaller or even negligible. + If you find that TLS access is slower than classic global variables, + what can you do about it? + ) + + $(OL + $(LI Minimize use of global variables. Reducing the use + of globals can improve the modularization and maintainability + of the code anyway, so this is a worthy goal.) + $(LI Group related global variables into a struct. The TLS-related + overhead is (often) proportional to the number of variables accessed. + Because a global struct variable is just one single variable, after + accessing one member of the struct, accessing another member is + "for free" (does not incur the extra TLS-related overhead). + Of course when you've grouped the data into a struct, perhaps you + should remove the global altogether by passing around a reference to + the struct as context...) + $(LI Make global variables immutable. Immutable data doesn't have + synchronization problems, so the compiler doesn't place it + in TLS.) + $(LI Cache a reference to the global. Making a local cache + of it, and then accessing the cached value rather than the + original, can speed things up especially if the cached value + gets enregistered by the compiler.) + $(LI Cowboy it with $(D __gshared).) + ) + +$(H2 $(LNAME2 vtls, Identifying TLS variables)) + + $(P The first step is to find all the global variables, + so they can be reviewed for disposition. + ) + + $(P Given the complexity of source code, it isn't always + easy to identify the global variables. Since it (used to be) + implicit, there's no way to grep for them. It's hard + to be sure you've found them all. + ) + + $(P A new dmd compiler switch was added, $(B -vtls). + Compiling with it on will print a list of all the global + variables that are now defaulting to thread local storage. + ) + +--- +int x; + +void main() +{ + static int y; +} +--- + +$(CONSOLE +dmd test $(B -vtls) +test.d(2): x is thread local +test.d(6): y is thread local +) + +$(H2 $(LNAME2 immutable, Switch to Immutable)) + + $(P Immutable data, once initialized, never changes. + This means that there are no synchronization issues + with multithreading, and so no need to put immutable data + into TLS. The compiler will put immutable data into + classic global storage, not TLS. + ) + + $(P A good chunk of global data falls into this category. + Just mark it as $(D immutable) and it's done. + ) + +--- +int[3] table = [6, 123, 0x87]; +--- + $(P becomes:) +--- +immutable int[3] table = [6, 123, 0x87]; +--- + + $(P Immutability is also nice because it opens the door + for further compiler optimizations. + ) + +$(H2 $(LNAME2 shared, Marking As Shared)) + + $(P Global data that is meant to be shared among multiple + threads should be marked with the $(D shared) keyword: + ) + +--- +shared int flag; +--- + + $(P Not only does this cause $(CODE flag) to be put into + classic global storage, it is also typed as being shared: + ) + +--- +int* p = &flag; // error, flag is shared +shared(int)* q = &flag; // ok +--- + + $(P The $(CODE shared) type attribute is transitive (like + $(CODE const) and $(CODE immutable)) are. This enables + static checking and sharing correctness. + ) + +$(H2 $(LNAME2 gshared, Cowboying With __gshared)) + + $(P Sometimes, none of the above solutions will be + acceptable: + ) + + $(OL + $(LI interfacing with C code that uses classic globals) + $(LI just get it working, and go back and fix it later) + $(LI the app is single threaded only, so no sharing issues) + $(LI you need every erg of performance) + $(LI you want to handle all the synchronization issues + yourself) + ) + + $(P As D is a systems language, of course there's a way to + do this. Use the storage class $(D __gshared): + ) + +--- +__gshared int x; + +void main() +{ + __gshared int y; +} +--- + + $(P $(D __gshared) stores the variable in the classic global + data segment. + ) + + $(P Naturally, $(D __gshared) is not allowed in safe mode. + ) + + $(P Using $(D __gshared) makes such code easily searchable + when doing QA code reviews or when going back later to + fix any workarounds. + ) + +$(H2 $(LNAME2 compile-errors, Compile Errors)) + + $(P The most common compiler error related to TLS will be: + ) + +--- +int x; +int* p = &x; +--- +$(CONSOLE +test.d(2): Error: non-constant expression & x +) + + $(P While this works with classic global variables, it + won't work with TLS variables. The reason is because + TLS variables don't have a location in memory known to + either the linker or the loader. It's a runtime computed + value.) + + $(P The solution is to initialize such things in + a static constructor.) + +$(H2 $(LNAME2 link-errors, Link Errors)) + + $(P Sometimes you may encounter strange error messages from the linker + about the global variables. + These are nearly always caused by one module putting the variable + in TLS, and another putting that same variable in classic global + storage. + This can happen when linking code with libraries that were built + with earlier versions of dmd. Check that libphobos2.a was properly + replaced with the latest. + It can also happen when interfacing with C. C globals default + to being classic global, although C does support TLS declarations. + Make sure the corresponding D declarations match the C ones in + terms of TLS or classic global. + ) + +$(CCODE +int x; +extern int y; +__thread int z; +) + +--- +extern (C) +{ + extern shared int x; + shared int y; + extern int z; +} +--- + +) + +Macros: + TITLE=Migrating to Shared + SUBNAV=$(SUBNAV_ARTICLES) + diff --git a/articles/mixin.dd b/articles/mixin.dd new file mode 100644 index 0000000000..d061663cb3 --- /dev/null +++ b/articles/mixin.dd @@ -0,0 +1,95 @@ +Ddoc + +$(D_S String Mixins, + + $(P String Mixins (not to be confused with + $(DDLINK spec/template-mixin, Template Mixins, template mixins)) + enable string constants to be compiled as regular D code + and inserted into the program. + Combining this with compile time manipulation of strings + enables the creation of domain-specific languages. + ) + + $(P For example, here we can create a template that generates + a struct with the named members: + ) + +--- +template GenStruct(string Name, string M1) +{ + const char[] GenStruct = "struct " ~ Name ~ "{ int " ~ M1 ~ "; }"; +} + +mixin(GenStruct!("Foo", "bar")); +--- + $(P which generates:) +--- +struct Foo { int bar; } +--- + + + $(P Superficially, since D mixins can manipulate text and compile + the result, it has some similar properties to the C preprocessor. + But there are major, fundamental differences: + ) + +$(UL + + $(LI The C preprocessing step occurs $(B before) lexical analysis. + This makes it impossible to lex or parse C without access to + all of the context, including all #include'd files, paths and all + relevant compiler switches. + + Mixins occur during semantic analysis, and do not affect + the lexing or parsing process. + Lexing and parsing can still occur without semantic analysis. + ) + + + $(LI The C preprocessor can be used to create what appears to + be different syntax: + +$(CCODE +#define BEGIN { +#define END } + +BEGIN + int x = 3; + foo(x); +END +) + + This monkey business is impossible with mixins. + Mixed in text must form complete declarations, + statements, or expressions. + ) + + $(LI C macros will affect everything following that has + the same name, even if they are in nested scopes. + C macros cut across all scopes. + This problem is called being not "coding hygenic". + + Mixins follow the usual scoping rules, and is + hygenic. + ) + + $(LI C preprocessing expressions follow a different syntax + and have different semantic rules than the C language. + The C preprocessor is technically a different language. + + Mixins are in the same language. + ) + + $(LI C const declarations and C++ templates are invisible + to C preprocessing. + + Mixins can be manipulated using templates and const + declarations. + ) +) + +) + +Macros: + TITLE=String Mixins + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/articles/pretod.dd b/articles/pretod.dd new file mode 100644 index 0000000000..3feee0bddf --- /dev/null +++ b/articles/pretod.dd @@ -0,0 +1,719 @@ +Ddoc + +$(COMMUNITY The C Preprocessor Versus D, + +$(HEADERNAV_TOC) + + $(P Back when C was invented, compiler technology was primitive. + Installing a text + macro preprocessor onto the front end was a straightforward + and easy way to add many + powerful features. The increasing size & complexity of programs + have illustrated + that these features come with many inherent problems. + D doesn't have a preprocessor; but + D provides a more scalable means to solve the same problems. + ) + +
+$(H2 $(LNAME2 headerfiles, Header Files)) + +$(CWAY + + $(P C and C++ rely heavily on textual inclusion of header files. + This frequently results in the compiler having to recompile tens of thousands + of lines of code over and over again for every source file, an obvious + source of slow compile times. What header files are normally used for is + more appropriately done doing a symbolic, rather than textual, insertion. + This is done with the import statement. Symbolic inclusion means the compiler + just loads an already compiled symbol table. The needs for macro "wrappers" to + prevent multiple #inclusion, funky #pragma once syntax, and incomprehensible + fragile syntax for precompiled headers are simply unnecessary and irrelevant to + D. + ) + +$(CCODE +#include <stdio.h> +) +) + +$(DWAY + + $(P D uses symbolic imports:) + +--------- +import core.stdc.stdio; +--------- +) + +
+$(H2 $(LNAME2 pragmaonce, #pragma once)) + +$(CWAY + + $(P C header files frequently need to be protected against + being #include'd multiple times. + To do it, a header file will contain the line: + ) + +$(CCODE +#pragma once +) + + $(P or the more portable:) + +$(CCODE +#ifndef __STDIO_INCLUDE +#define __STDIO_INCLUDE +... header file contents +#endif +) +) + +$(DWAY + $(P Completely unnecessary since D does a symbolic include of import + files; they only get imported once no matter how many times + the import declaration appears. + ) +) + +
+$(H2 $(LNAME2 pragmapack, #pragma pack)) + +$(CWAY + $(P This is used in C to adjust the alignment for structs.) +) + +$(DWAY + $(P For D classes, there is no need to adjust the alignment (in fact, the + compiler is free to rearrange the data fields to get the optimum layout, + much as the compiler will rearrange local variables on the stack frame). + For D structs that get mapped onto externally defined data structures, + there is a need, and it is handled with: + ) + +--------- +struct Foo +{ + align (4): // use 4 byte alignment + ... +} +--------- +) + +
+$(H2 $(LNAME2 macros, Macros)) + + $(P Preprocessor macros add powerful features and flexibility to C. But + they have a downside: + ) + +$(UL + $(LI Macros have no concept of scope; they are valid from the point of definition + to the end of the source. They cut a swath across .h files, nested code, etc. When + #include'ing tens of thousands of lines of macro definitions, it becomes + problematical to avoid inadvertent macro expansions. + ) + + $(LI Macros are unknown to the debugger. Trying to debug a program with + symbolic data is undermined by the debugger only knowing about macro + expansions, not the macros themselves. + ) + + $(LI Macros make it impossible to tokenize source code, as an earlier macro change + can arbitrarily redo tokens. + ) + + $(LI The purely textual basis of macros leads to arbitrary and inconsistent usage, + making code using macros error prone. (Some attempt to resolve this was + introduced with templates in C++.) + ) + + $(LI Macros are still used to make up for deficits in the language's expressive + capability, such as for "wrappers" around header files. + ) +) + + + $(P Here's an enumeration of the common uses for macros, and the + corresponding feature in D: + ) + +$(OL + $(LI Defining literal constants: + + $(CWAY + +$(CCODE +#define VALUE 5 +) + ) + + $(DWAY + +--------- +enum int VALUE = 5; +--------- + ) + ) + + $(LI Creating a list of values or flags: + + $(CWAY + +$(CCODE +int flags: +#define FLAG_X 0x1 +#define FLAG_Y 0x2 +#define FLAG_Z 0x4 +... +flags |= FLAG_X; +) + ) + + $(DWAY + +--------- +enum FLAGS { X = 0x1, Y = 0x2, Z = 0x4 }; +FLAGS flags; +... +flags |= FLAGS.X; +--------- + ) + ) + + $(LI Distinguishing between ascii chars and wchar chars: + + $(CWAY + +$(CCODE +#if UNICODE + #define dchar wchar_t + #define TEXT(s) L##s +#else + #define dchar char + #define TEXT(s) s +#endif + +... +dchar h[] = TEXT("hello"); +) + ) + + $(DWAY + +--------- +dstring h = "hello"; +--------- + + + $(P D's optimizer will inline the function, and will do the conversion of the + string constant at compile time.) + ) + ) + + $(LI Supporting legacy compilers: + + $(CWAY + +$(CCODE +#if PROTOTYPES +#define P(p) p +#else +#define P(p) () +#endif +int func P((int x, int y)); +) + ) + + $(DWAY + By making the D compiler open source, it will largely + avoid the problem of syntactical backwards compatibility. + ) + ) + + $(LI Type aliasing: + + $(CWAY + +$(CCODE +#define INT int +) + ) + + $(DWAY + +--------- +alias INT = int; +--------- + ) + ) + + $(LI Using one header file for both declaration and definition: + + $(CWAY + +$(CCODE +#define EXTERN extern +#include "declarations.h" +#undef EXTERN +#define EXTERN +#include "declarations.h" +) + + In declarations.h: + +$(CCODE +EXTERN int foo; +) + ) + + $(DWAY + + The declaration and the definition are the same, so there is no need + to muck with the storage class to generate both a declaration and a definition + from the same source. + ) + ) + + $(LI Lightweight inline functions: + + $(CWAY + +$(CCODE +#define X(i) ((i) = (i) / 3) +) + ) + + $(DWAY + +--------- +int X(ref int i) { return i = i / 3; } +--------- + + The compiler optimizer will inline it; no efficiency is lost. + ) + ) + + $(LI Assert function file and line number information: + + $(CWAY + +$(CCODE +#define assert(e) ((e) || _assert(__LINE__, __FILE__)) +) + ) + + $(DWAY + + assert() is a built-in expression primitive. Giving the compiler + such knowledge of assert() also enables the optimizer to know about things + like the _assert() function never returns. + ) + ) + + $(LI Setting function calling conventions: + + $(CWAY + +$(CCODE +#ifndef _CRTAPI1 +#define _CRTAPI1 __cdecl +#endif +#ifndef _CRTAPI2 +#define _CRTAPI2 __cdecl +#endif + +int _CRTAPI2 func(); +) + ) + + $(DWAY + + Calling conventions can be specified in blocks, so there's no + need to change it for every function: + +--------- +extern (Windows) +{ + int onefunc(); + int anotherfunc(); +} +--------- + ) + ) + + $(LI Hiding __near or __far pointer weirdness: + + $(CWAY + +$(CCODE +#define LPSTR char FAR * +) + ) + + $(DWAY + + D doesn't support 16 bit code, mixed pointer sizes, and different + kinds of pointers, and so the problem is just + irrelevant. + ) + ) + + $(LI Simple generic programming: + + $(CWAY + + Selecting which function to use based on text substitution: + +$(CCODE +#ifdef UNICODE +int getValueW(wchar_t *p); +#define getValue getValueW +#else +int getValueA(char *p); +#define getValue getValueA +#endif +) + ) + + $(DWAY + + D enables declarations of symbols that are $(I aliases) of + other symbols: + +--------- +version (UNICODE) +{ + int getValueW(wchar[] p); + alias getValue = getValueW; +} +else +{ + int getValueA(char[] p); + alias getValue = getValueA; +} +--------- + ) + ) + +) + +
+$(H2 $(LNAME2 conditionalcompilation, Conditional Compilation)) + + +$(CWAY + + $(P Conditional compilation is a powerful feature of the C preprocessor, + but it has its downside:) + + $(UL + $(LI The preprocessor has no concept of scope. #if/#endif can be + interleaved with code in a completely unstructured and disorganized + fashion, making things difficult to follow. + ) + + $(LI Conditional compilation triggers off of macros - macros that + can conflict with identifiers used in the program. + ) + + $(LI #if expressions are evaluated in subtly different ways than + C expressions are. + ) + + $(LI The preprocessor language is fundamentally different in concept + than C, for example, whitespace and line terminators mean things to + the preprocessor that they do not in C. + ) + ) +) + +$(DWAY + + $(P D supports conditional compilation:) + + $(OL + $(LI Separating version specific functionality into separate modules. + ) + + $(LI The debug statement for enabling/disabling debug harnesses, + extra printing, etc. + ) + + $(LI The version statement for dealing with multiple versions + of the program generated from a single set of sources. + ) + + $(LI The if (0) statement. + ) + + $(LI The /+ +/ nesting comment can be used to comment out blocks + of code. + ) + ) +) + +
+$(H2 $(LNAME2 codefactoring, Code Factoring)) + +$(CWAY + + $(P It's common in a function to have a repetitive sequence + of code to be executed in multiple places. Performance + considerations preclude factoring it out into a separate + function, so it is implemented as a macro. For example, + consider this fragment from a byte code interpreter: + ) + +$(CCODE +unsigned char *ip; // byte code instruction pointer +int *stack; +int spi; // stack pointer +... +#define pop() (stack[--spi]) +#define push(i) (stack[spi++] = (i)) +while (1) +{ + switch (*ip++) + { + case ADD: + op1 = pop(); + op2 = pop(); + result = op1 + op2; + push(result); + break; + + case SUB: + ... + } +} +) + + $(P This suffers from numerous problems: + ) + + $(OL + $(LI The macros must evaluate to expressions and cannot declare + any variables. Consider the difficulty of extending them to + check for stack overflow/underflow. + ) + $(LI The macros exist outside of the semantic symbol table, so + remain in scope even outside of the function they are declared in. + ) + $(LI Parameters to macros are passed textually, not by value, + meaning that the macro implementation needs to be careful to not + use the parameter more than once, and must protect it with (). + ) + $(LI Macros are invisible to the debugger, which sees only the + expanded expressions. + ) + ) +) + +$(DWAY + + $(P D neatly addresses this with nested functions:) + +--------- +ubyte* ip; // byte code instruction pointer +int[] stack; // operand stack +int spi; // stack pointer +... + +int pop() { return stack[--spi]; } +void push(int i) { stack[spi++] = i; } + +while (1) +{ + switch (*ip++) + { + case ADD: + op1 = pop(); + op2 = pop(); + push(op1 + op2); + break; + + case SUB: + ... + } +} +--------- + + $(P The problems addressed are:) + + $(OL + $(LI The nested functions have available the full expressive + power of D functions. The array accesses already are bounds + checked (adjustable by compile time switch). + ) + $(LI Nested function names are scoped just like any other name. + ) + $(LI Parameters are passed by value, so no need to worry about + side effects in the parameter expressions. + ) + $(LI Nested functions are visible to the debugger. + ) + ) + + $(P Additionally, nested functions can be inlined by the implementation + resulting in the same high performance that the C macro version + exhibits. + ) +) + +
+$(H2 $(LNAME2 staticassert, #error and Static Asserts)) + + $(P Static asserts are user-defined checks made at compile time; + if the check fails the compile issues an error and fails. + ) + +$(CWAY + + $(P The first way is to use the $(D #error) preprocessing directive: + ) + +$(CCODE +#if FOO || BAR + ... code to compile ... +#else +#error "there must be either FOO or BAR" +#endif +) + + $(P This has the limitations inherent in preprocessor expressions + (i.e. integer constant expressions only, no casts, no $(D sizeof), + no symbolic constants, etc.). + ) + + $(P These problems can be circumvented to some extent by defining a + $(D static_assert) macro (thanks to M. Wilson): + ) + +$(CCODE +#define static_assert(_x) do { typedef int ai[(_x) ? 1 : 0]; } while(0) +) + + $(P and using it like:) + +$(CCODE +void foo(T t) +{ + static_assert(sizeof(T) < 4); + ... +} +) + + $(P This works by causing a compile time semantic error if the condition + evaluates + to false. The limitations of this technique are a sometimes very + confusing error message from the compiler, along with an inability + to use a $(D static_assert) outside of a function body. + ) +) + +$(DWAY + + $(P D has the $(DDSUBLINK spec/version, StaticAssert, static assert), + which can be used anywhere a declaration + or a statement can be used. For example: + ) + +--------- +version (FOO) +{ + class Bar + { + const int x = 5; + static assert(Bar.x == 5 || Bar.x == 6); + + void foo(T t) + { + static assert(T.sizeof < 4); + ... + } + } +} +else version (BAR) +{ + ... +} +else +{ + static assert(0); // unsupported version +} +--------- +) + +
+$(H2 $(LNAME2 mixins, Template Mixins)) + + $(P D $(DDLINK spec/template-mixin, Template Mixins, template mixins) + superficially look just + like using C's preprocessor to insert blocks of code and + parse them in the scope of where they are instantiated. + But the advantages of mixins over macros are: + ) + + $(OL + $(LI Mixins substitute in parsed declaration trees that pass muster with + the language syntax, macros substitute in arbitrary preprocessor tokens + that have no organization. + ) + + $(LI Mixins are in the same language. Macros are a separate and + distinct language layered on top of C++, with its own expression rules, + its own types, its distinct symbol table, its own scoping rules, etc. + ) + + $(LI Mixins are selected based on partial specialization rules, macros + have no overloading. + ) + + $(LI Mixins create a scope, macros do not. + ) + + $(LI Mixins are compatible with syntax parsing tools, macros are not. + ) + + $(LI Mixin semantic information and symbol tables are passed through to + the debugger, macros are lost in translation. + ) + + $(LI Mixins have override conflict resolution rules, macros just + collide. + ) + + $(LI Mixins automatically create unique identifiers as required using a + standard algorithm, macros have to do it manually with kludgy token + pasting. + ) + + $(LI Mixin value arguments with side effects are evaluated once, macro + value arguments get evaluated each time they are used in the expansion + (leading to weird bugs). + ) + + $(LI Mixin argument replacements don't need to be $(SINGLEQUOTE protected) with + parentheses to avoid operator precedence regrouping. + ) + + $(LI Mixins can be typed as normal D code of arbitrary length, multiline + macros have to be backslash line-spliced, can't use // to end of line + comments, etc. + ) + + $(LI Mixins can define other mixins. Macros cannot create other macros. + ) + + ) + +) + +Macros: + TITLE=The C Preprocessor vs D + CWAY=$(SECTION4 The C Preprocessor Way, $0) + DWAY=$(SECTION4 The D Way, $0) + SUBNAV=$(SUBNAV_ARTICLES) + diff --git a/articles/rationale.dd b/articles/rationale.dd new file mode 100644 index 0000000000..c545cc8dd8 --- /dev/null +++ b/articles/rationale.dd @@ -0,0 +1,249 @@ +Ddoc + +$(HEADERNAV_TOC) + +$(D_S Rationale, + + $(P Questions about the reasons for various design decisions for + D often come up. This addresses many of them. + ) + +$(H2 $(LNAME2 operator-overloading, Operator Overloading)) + +$(H3 $(LNAME2 why-not-operator, Why not name them operator+(), operator*(), etc.?)) + + $(P This is the way C++ does it, and it is appealing to be able + to refer to overloading $(SINGLEQUOTE +) with $(SINGLEQUOTE operator+). The trouble is + things don't quite fit. For example, there are the + comparison operators <, <=, >, and >=. In C++, all four must + be overloaded to get complete coverage. In D, only an opCmp() + function must be defined, and the comparison operations are + derived from that by semantic analysis. + ) + + $(P Further, binary operators on number-based types are largely uniformly + implemented so a single opBinary template allows one to just mixin the + operator the user used, whereas in C++ each operator will need to be separately + defined. For example:) + +------ +import std.stdio; +struct MyInt +{ + int i; + MyInt opBinary(string op)(in MyInt other) if(op == "+" || op == "-") + { + mixin ("return MyInt(i " ~ op ~ "other.i);"); + } +} +void main() +{ + MyInt a = MyInt(3), b = MyInt(1), c = a + b, d = a - b; + writeln(a.i, ' ', b.i, ' ', c.i, ' ', d.i); // prints 3 1 4 2 +} +------ + + $(P Overloading operator/() also provides no symmetric way, as a member + function, to overload the reverse operation. For example, + ) + +------ +class A +{ + int operator/(int i); // overloads (a/i) + static operator/(int i, A a) // overloads (i/a) +} +------ + + $(P The second overload does the reverse overload, but + it cannot be virtual, and so has a confusing asymmetry with + the first overload. + ) + +$(H3 $(LNAME2 why-no-global-operator-functions, Why not allow globally defined operator overload functions?)) + + $(OL + $(LI Operator overloading can only be done with an argument + as an object, so they logically belong as member functions + of that object. That does leave the case of what to do + when the operands are objects of different types: + +------ +class A { } +class B { } +int opAdd(class A, class B); +------ + + Should opAdd() be in class A or B? The obvious stylistic solution + would be to put it in the class of the first operand, + +------ +class A +{ + int opAdd(class B) { } +} +------ + ) + + $(LI Operator overloads usually need access to private members + of a class, and making them global breaks the object oriented + encapsulation of a class. + ) + + $(LI (2) can be addressed by operator overloads automatically gaining + "friend" access, but such unusual behavior is at odds with D + being simple. + ) + + ) + +$(H3 $(LNAME2 no-user-definable-operators, Why not allow user definable operators?)) + + $(P These can be very useful for attaching new infix operations + to various unicode symbols. The trouble is that in D, + the tokens are supposed to be completely independent of the + semantic analysis. User definable operators would break that. + ) + +$(H3 $(LNAME2 no-user-defined-precedence, Why not allow user definable operator precedence?)) + + $(P The trouble is this affects the syntax analysis, and the syntax + analysis is supposed to be completely independent of the + semantic analysis in D. + ) + +$(H3 $(LNAME2 no-operator-names, Why not use operator names like __add__ and __div__ instead + of opAdd, opDiv, etc.?)) + + $(P __ keywords should indicate a proprietary language extension, + not a basic part of the language. + ) + +$(H3 $(LNAME2 binary-operator-overloads, Why not have binary operator overloads be static members, so both +arguments are specified, and there no longer is any issue with the reverse +operations?)) + + $(P This means that the operator overload cannot be virtual, and + so likely would be implemented as a shell around another + virtual function to do the real work. This will wind up looking + like an ugly hack. Secondly, the opCmp() function is already + an operator overload in Object, it needs to be virtual for several + reasons, and making it asymmetric with the way other operator + overloads are done is unnecessary confusion. + ) + +$(H2 $(LNAME2 properties, Properties)) + +$(H3 $(LNAME2 properties-infinity, Why does D have properties like T.infinity in the core language to give the +infinity of a floating point type, rather than doing it in a library like C++: + $(CODE std::numeric_limits$(LT)T$(GT)::infinity) +?)) + + Let's rephrase that as $(DOUBLEQUOTE if there's a way to express it in the existing + language, why build it in to the core language?) + In regards to T.infinity: + + $(OL + $(LI Building it in to the core language means the core language knows + what a floating point infinity is. Being layered in templates, typedefs, + casts, const bit patterns, etc., it doesn't know what it is, and is + unlikely to give sensible error messages if misused. + ) + + $(LI A side effect of (1) is it is unlikely to be able to use it + effectively in constant folding and other optimizations. + ) + + $(LI Instantiating templates, loading $(CODE #include) files, etc., all costs + compile time and memory. + ) + + $(LI The worst, though, is the lengths gone to just to get at infinity, + implying $(DOUBLEQUOTE the language and compiler don't know anything about IEEE 754 + floating point - so it cannot be relied on.) And in fact + many otherwise excellent C++ compilers + do not handle NaNs correctly in floating point comparisons. + (Digital Mars C++ does do it correctly.) + C++98 doesn't say anything about NaN or Infinity handling in expressions + or library functions. So it must be assumed it doesn't work. + ) + + ) + + $(P To sum up, there's a lot more to supporting NaNs and infinities than + having a template that returns a bit pattern. It has to be built in to + the compiler's core logic, and it has to permeate all the library code + that deals with floating point. And it has to be in the Standard. + ) + + $(P To illustrate, if either op1 or op2 or both are NaN, then:) + +------ +(op1 < op2) +------ + $(P does not yield the same result as:) +------ +!(op1 >= op2) +------ + $(P if the NaNs are done correctly.) + +$(H2 $(LNAME2 static-if-0, Why use $(D static if(0)) rather than $(D if (0)?))) + + $(P Some limitations are:) + + $(OL + $(LI if (0) introduces a new scope, static if(...) does not. Why does this + matter? It matters if one wants to conditionally declare a new variable: + +------ +static if (...) int x; else long x; +x = 3; +------ + + whereas: + +------ +if (...) int x; else long x; +x = 3; // error, x is not defined +------ + ) + + $(LI False static if conditionals don't have to semantically work. For + example, it may depend on a conditionally compiled declaration somewhere + else: + +------ +static if (...) int x; +int test() +{ + static if (...) return x; + else return 0; +} +------ + ) + + $(LI Static ifs can appear where only declarations are allowed: + +------ +class Foo +{ + static if (...) + int x; +} +------ + ) + + $(LI Static ifs can declare new type aliases: + +------ +static if (0 || is(int T)) T x; +------ + ) + ) + +) + +Macros: + TITLE=Rationale + SUBNAV=$(SUBNAV_ARTICLES) + diff --git a/articles/regular-expression.dd b/articles/regular-expression.dd new file mode 100644 index 0000000000..bcec979f35 --- /dev/null +++ b/articles/regular-expression.dd @@ -0,0 +1,333 @@ +Ddoc + +$(D_S $(TITLE), + + $(HEADERNAV_TOC) + + $(P + $(SMALL by Dmitry Olshansky, the author of std.regex ) + ) + $(H2 $(LNAME2 introduction, Introduction)) + $(P String processing is a daily routine that most applications have to deal with in a one way or another. + It should come as no surprise that many programming languages have standard libraries equipped + with a variety of specialized functions for common string manipulation needs. + The D programming language standard library among others offers a nice assortment in $(STD string), + as well as generic functions from $(STD algorithm) that work with strings. + Still no amount of fixed functionality could cover all needs, as naturally flexible text data + needs flexible solutions. + ) + $(P This is where $(LUCKY regular expressions), often succinctly called regexes, come in handy. + Regexes are simple yet powerful language for defining patterns for sets of strings. + Combined with pattern matching, data extraction and substitution, they form a Swiss Army knife of text processing. + They are considered so important that a number of programming languages provide built-in support for regular expressions. Being built-in however does $(B not) necessary + imply $(B faster processing) or having more features. It's just a matter of providing + $(B convenient and friendly syntax) for typical operations, and integrating it well. + ) + $(P The D programming language provides a standard library module $(STD regex). + Being a highly expressive systems language, D allows regexes to be $(I implemented efficiently) + within the language itself, yet have good level of readability and usability. + And there a few things a pure D implementation brings to the table that are completely unbelievable + in a traditional compiled language, more on that at the end of article. + ) + $(P By the end of article you'll have a good understanding of regular expression capabilities in this library, + and how to utilize its API in a most straightforward and efficient way. Examples in this article assume + that the reader has fair understanding of regex elements, but it's not required. + ) + + $(H2 $(LNAME2 warm-up, A warm up)) + + $(P How do you check if something is a phone number by looking at it? ) + $(P Yes, it's something with numbers, and there may be a country code in front of that... + Sticking to an international format should make it more strict. As this is the first time, let's + put together a full program:) + $(RUNNABLE_EXAMPLE + $(RUNNABLE_EXAMPLE_STDIN +1 555 123 4567) + --- + import std.stdio, std.regex; + + void main() + { + string phone = readln(); // assume phone is passed as the first line of stdin + if (matchFirst(phone, r"^\+[1-9][0-9]* [0-9 ]*$")) + writeln("It looks like a phone number."); + else + writeln("Nope, it's not a phone number."); + } + --- + ) + $(P + And that's it! Let us however keep in mind the boundaries of regular expressions power - to truly establish a + validness of a phone number, one has to try dialing it or contact the authority. + ) + $(P Let's drill down into this tiny example because it actually showcases a lot of interesting things:) + $(UL + $(LI A raw string literal of form `r"..."`, that allows writing a regex pattern in its natural notation. ) + $(LI $(D matchFirst) function to find the first match in a string if any. To check if there was a match just + test the return value explicitly in a boolean context, such as an $(D if) statement. ) + $(LI When matching special regex characters like +, *, (, ), [, ] and $ don't forget to use escaping with backslash, e.g. `\+`. ) + $(LI Unless there is a lot of text processing going on, it's perfectly fine to pass a plain string as a pattern. + The internal representation used to do the actual work is cached, to speed up subsequent calls. ) + ) + $(P Continuing with the phone number example, it would be useful to get the exact value of + the country code, as well as the whole number. For the sake of experiment let's also explicitly obtain + compiled regex pattern via $(D regex) to see how it works. + ) + $(RUNNABLE_EXAMPLE + --- + import std.regex; + + string phone = "+31 650 903 7158"; // fictional, any coincidence is just that + auto phoneReg = regex(r"^\+([1-9][0-9]*) [0-9 ]*$"); + auto m = matchFirst(phone, phoneReg); + assert(m); // also boolean context - test for non-empty + assert(!m.empty); // same as the line above + assert(m[0] == "+31 650 903 7158"); + assert(m[1] == "31"); + // you shouldn't need the regex object type all too often + // but here it is for the curious + static assert(is(typeof(phoneReg) : Regex!char)); + --- + ) + $(H2 $(LNAME2 search-replace, Search and replace)) + + $(P While getting first match is a common theme in string validation, another frequent need is + to extract all matches found in a piece of text. Picking an easy task, let's see how to + filter out all white space-only lines. There is no special routine for looping over input + like $(D search()) or similar as found in some libraries. + Instead $(D std.regex) provides a natural syntax for looping via plain foreach. + ) + --- + auto buffer = std.file.readText("regex.d"); + foreach (m; matchAll(buffer, regex(r"^.*[^\p{WhiteSpace}]+.*$","m"))) + { + writeln(m.hit); // hit is an alias for m[0] + } + --- + $(P It may look and feel like a built-in but it just follows the common conventions to do that. + In this case `matchAll` returns an object that follows the right "protocol" of an input range + simply by having the right set of methods. An input range is a lot like an iterator found + in other languages. Likewise the result of `matchFirst` and each element of `matchAll` + is a random access range, a thing that behaves like a "view" of an array. + ) + $(RUNNABLE_EXAMPLE + --- + import std.regex; + + auto m = matchAll("Ranges are hot!", r"(\w)\w+(\w)"); // at least 3 "word" symbols + assert(m.front[0] == "Ranges"); // front - first of input range + // m.captures is a historical alias for the first element of match range (.front). + assert(m.captures[1] == m.front[1]); + auto sub = m.front; + assert(sub[2] == "s"); + foreach (item; sub) + writeln(item); // will show lines: Ranges, R, s + --- + ) + $(P By playing by the rules $(STD regex) gets some nice benefits in interaction with other modules e.g. + this is how one could count non-empty lines in a text buffer: + ) + --- + import std.algorithm, std.file, std.regex; + + auto buffer = std.file.readText(r"std\typecons.d"); + int count = count(matchAll(buffer, regex(r"^.*\P{WhiteSpace}+.*$", "m"))); + --- + $(P + A seasoned regex user catches instantly that Unicode properties are supported with perl-style \p{xxx}, + to spice that all of Scripts and Blocks are supported as well. Let us duly note that \P{xxx} means not + having an xxx property, i.e. here not a white space character. Unicode is a vital subject to know, and it won't suffice + to try to cover it here. For details see the accessible $(STD uni) documentation and level 1 of conformance + as per Unicode standard $(LINK2 http://Unicode.org/reports/tr18/, UTS 18). + ) + + $(P Another thing of importance is the option string - "m", where m stands for multi-line mode. + Historically utilities that supported regex patterns (unix grep, sed, etc.) processed text line by line. + At that time anchors like ^, $ meant the start of the whole input buffer that has been same as that of the line. + As regular expressions got more ubiquitous the need to recognize multiple lines in a chunk of text became apparent. + In such a mode with anchors ^ & $ were defined to match before and after line break literally. + For the curious, modern (Unicode) line break is defined as (\n | \v | \r | \f | \u0085 | \u2028 | \u2029 | \r\n). + Needless to say, one need not turn on multi-line mode if not using any of ^, $. + ) + +$(H3 $(LNAME2 replacing, Replacing)) + + $(P Now that search was covered, let's do some replacements. + For instance, to replace all dates with "MM/dd/YYYY" format in a text to a sortable format of "YYYY-MM-dd": + ) + $(RUNNABLE_EXAMPLE + --- + import std.regex; + + auto text = "2/31/1998"; + auto replaced = replaceAll(text, r"([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})".regex, "$3-$1-$2"); + assert(replaced == "1998-2-31"); + --- + ) + $(P $(D r"pattern".regex) is just another notation of writing $(D regex("pattern")) called + $(DDSUBLINK spec/function, pseudo-member, UFCS) that some may find more + slick. + As can be seen the replacement is controlled by a format string not unlike one in C's famous `printf`. + The $(D \$1), $(D \$2), $(D \$3) are substituted with the content of sub-expressions. + Aside from referencing sub-matches, one can include the whole part of input preceding the match via $(D $\`) and `$'` for the content following right after the match. + ) + $(P Now let's aim for something bigger, this time to show that $(STD regex) can do things that + are unattainable by classic textual substitution alone. Imagine you want to translate a web shop catalog so + that it displays prices in your currency. Yes, one can use calculator or estimate it in his/her head, + given the current ratio. Being programmers we can do better, so let's wrap up a simple program that + converts text to use correct prices everywhere. For example, UK pounds to US dollars. + ) + $(RUNNABLE_EXAMPLE + $(RUNNABLE_EXAMPLE_STDIN Bottles for £1, or £3 for 4.) + --- + import std.conv, std.regex, std.range, std.stdio; + import std.string : format; + + void main() + { + immutable ratio = 1.5824; // UK pounds to US dollar as of this writing + auto toDollars(Captures!string price) + { + real value = to!real(price["integer"]); + if (!price["fraction"].empty) + value += 0.01 * to!real(price["fraction"]); + return format("$%.2f", value * ratio); + } + string text = readln(); + auto converted = replaceAll!toDollars(text, + regex(r"£\s*(?P[0-9]+)(\.(?P[0-9]{2}))?", "g")); + write(converted); + } + --- + ) + $(P Getting current conversion rates and supporting more currencies is left as an exercise for the reader. + What's at work here is called *replace with delegate*, which is analogous to a callout ability found in other languages + and regex libraries. The magic is simple: whenever `replaceAll` finds a match it calls a user supplied callback `toDollars` + on the captured piece, then it uses the return value to make the replacement. + ) + + $(P And I just couldn't resist spicing that example up with yet another feature - named groups. + The syntax for a named group is `(?Pregex)`. + Names work just like aliases for numbers of captured subexpressions, + meaning that with the exact same regular expression one could just as well change the affected lines to:) + --- + real value = to!real(price[1]); + if (!price[3].empty) + value += 0.01*to!real(price[3]); + --- + $(P + Though that lacks readability and is not as future proof. + ) + + $(P Also note that optional captures are still represented, it's just they can be an empty string if not matched. + ) + + $(H2 $(LNAME2 split-up, Split it up)) + + $(P Now core functionality has been presented, let's move on to some extras. + Sometimes it's useful to do almost the opposite of searching - split up input using a regex as separator. + The following sample outputs text by sentences: + ) + $(RUNNABLE_EXAMPLE + $(RUNNABLE_EXAMPLE_STDIN This is sample text! It has several sentences. Did it work?!) + --- + import std.regex, std.stdio; + + auto text = readln('\0'); // read all stdin + foreach (sentence; splitter(text, regex(r"(?<=[.?!]+(?![?!]))\s*"))) + writeln(sentence); + --- + ) + $(P Again the type `splitter` returns is a range, thus allowing foreach iteration. + Notice the usage of lookaround in the regex, it's a neat trick here as stripping off final punctuation is + not our intention. `(?=regex)` is lookahead and `(?<=regex)` is lookbehind.) + $(P + Breaking down this example, the `(?<=[.?!])` part looks behind for first `.`, `?` or `!`. + This gets us halfway to our goal because `\s*` also matches between elements of punctuation like "?!", + so a negative lookahead `(?!regex)` is introduced $(I inside a lookbehind) to make sure there are no more punctuation marks.) + $(P + Admittedly, the barrage of ? and ! makes this regex rather obscure, more then it actually is. + Observe that there are no restrictions on the contents of lookaround expressions, + one can go for lookahead inside lookbehind and so on. + However in general it's recommended to use them sparingly, keeping them as the weapon of last resort. + ) + + $(H2 $(LNAME2 static-regex, Static regex)) + + $(P Let's stop going for features and start thinking performance. D has something to offer here. + For one, there is an ability to precompile a constant regex at compile-time: + ) + $(RUNNABLE_EXAMPLE + --- + import std.regex; + + static r = regex("Boo-hoo"); + assert(match("What was that? Boo-hoo?", r)); + --- + ) + $(P Importantly it's the exact same `Regex` object that works through all of the API we've seen so far. + It takes next to no time to initialize, just copy over a ready-made structure from the data segment - + roughly 1 μs of run-time to initialize on my machine. Conversely, compiling the regex at run-time took around 10-20 μs - and keep in mind that it was a trivial pattern. + ) + + $(P Now stepping further in this direction there is an ability to construct specialized + D code to match a given regex instead of using the default run-time engine. + Isn't it so often the case that code starts with regular expressions only to be later re-written + to heaps of scary-looking code to match speed requirements? No need to rewrite - we got you covered. + ) + $(P Recalling the phone number example: + ) + $(RUNNABLE_EXAMPLE + --- + import std.regex; + + string phone = "+31 650 903 7158"; + // It's only a 5 characters difference! + auto phoneReg = ctRegex!r"^\+([1-9][0-9]*) [0-9 ]*$"; + auto m = match(phone, phoneReg); + assert(m); + assert(m.captures[0] == "+31 650 903 7158"); + assert(m.captures[1] == "31"); + --- + ) + $(P Interestingly, the code looks almost exactly the same (a total of 5 letters changed), yet it does all of + the hard work, generating equivalent D code for the regex pattern. `ctRegex` produces a `StaticRegex` object which supports the same API as the runtime `Regex`. + This is the key point - the API stays consistent, yet gets us the significant speed up we sought after. + This fosters quick development speed using the regex engine, and then, if desired, a decent runtime speed by switching to $(D ctRegex) in the release build (at the cost of slower builds). + ) + $(P In this particular case it matched roughly 50% faster for me though I haven't + done comprehensive analysis of this case. + That being said, there is no doubt `ctRegex` is going to improve immensely over time. + We only scratched the surface of exciting new possibilities. + More data on real-world patterns, performance of CT-regex and other benchmarks is + $(LINK2 https://github.com/DmitryOlshansky/FReD, here). + ) + + $(H2 $(LNAME2 conclusion, Conclusion)) + + $(P The article represents a walk-through of $(D std.regex) focused on showcasing the API. + By following a series of easy yet meaningful tasks, its features were exposed in combination, + that underline the elegance and flexibility of this library solution. + The good thing is not only that the API is natural, but it also follows established + standards and integrates well with the rest of Phobos. + Putting its major features together, $(STD regex) is: + ) + $(UL + $(LI Fully Unicode-aware, qualifies to standard full level 1 Unicode support) + $(LI Replete with lots of modern extensions, including unlimited generalized lookaround. + That makes porting regexes from other libraries a breeze.) + $(LI Designed with a lean API that consists of a few flexible tools: $(D matchFirst)/$(D matchAll), $(D replaceFirst)/$(D replaceAll) and $(D splitter).) + $(LI Uniform and powerful, with unique abilities like precompiling a regex or generating + specially tailored code at compile-time with ctRegex. All of this fits within the common interface without a hitch.) + ) + $(P The format of this article is intentionally more of an overview, it doesn't stop to talk in-depth about + certain capabilities like case-insensitive matching (simple casefolding rules of Unicode), + backreferences, lazy quantifiers. And even more features are coming to add more expressive power + and reach greater performance. + ) + +) +Macros: +DOLLAR = $ +STD = $(LINK2 /phobos/std_$0.html, std.$0) +SUBNAV=$(SUBNAV_ARTICLES) +TITLE=Regular Expressions diff --git a/articles/safed.dd b/articles/safed.dd new file mode 100644 index 0000000000..42499664a3 --- /dev/null +++ b/articles/safed.dd @@ -0,0 +1,266 @@ +Ddoc + +$(D_S SafeD—The Safe Subset of D, + + $(HEADERNAV_TOC) + + $(P + $(SMALL by Bartosz Milewski, a member of the D design team) + ) + + $(P + I've seen some very good programmers move away from C++ in favor of languages like Java or C#. Being a hard-core C++ programmer myself, I wondered why anyone would want to switch to a less powerful and less efficient language. Mind you, I could understand why a newcomer would opt for a simpler, flatter-learning-curve language but, once somebody invested the time and effort to become proficient in C++, why in the world would they want to abandon it? + ) + +D-man in rain + + $(P + The universal reason I've heard from the turncoats was $(DOUBLEQUOTE productivity.) The consensus seems to be that programmers are more productive using Java, C#, Ruby, or Python than they are using C++. + ) + + $(P + What are the major impediments to productive programming in C++? + ) + + $(P + $(B Horrible syntax) is one. This is actually more serious than it sounds. A good programmer can probably master some pretty horrible syntaxes given enough time. The problem is that C++ syntax and grammar is not only human-unfriendly but also parser-hostile. The fact that the Java market is saturated with productivity boosting tools is the reflection of the language's parseability. I have to yet see a C++ programming environment that would offer such powerful refactoring tools as are commonplace in Java. + ) + + $(P + Language safety is the other major factor. C++ is notorious for presenting a never ending gallery of opportunities to shoot yourself in the foot. In fact C++ not only provides the opportunity to write dangerous code, it $(I encourages ) it. At some point a major C++ compiler vendor marked a portion of STL algorithms as "deprecated" because of safety concerns. In particular the C++ Standard Library, in accordance with the spirit of C++, extends the number of ways a buffer overflow bug might sneak into your program. + ) + + $(P + One notorious example is the $(CODE std::swap_ranges) algorithm, which takes three iterators. The first two iterators are supposed to delimit one range, the third one marks the beginning of the second range. No testing is done whether the second range doesn't extend past the end of the container. When it does, virus writers rejoice! + ) + + $(P + The pipe dream of programming language designers is to be able to guarantee that if a program compiles successfully, it will work. Of course you have to be reasonable about your definition of a "working" program. For instance, you might require that the program will never get "stuck"—a term which has a precise meaning in computer science, but loosely means that the program will not GP-fault on you (it is stuck in the sense that there is no well-defined system-independent next step). Languages that have such a property are called "sound". + ) + + $(P + Guess what, there is a well-defined (and meaningful) subset of Java that is sound. Real-life Java programs, for practical reasons, stray outside of this sound subset; but at least the use of unsafe features is less prevalent and easier to spot in a Java program than it is in a C++ program. In practice, a Java compiler will detect more bugs in your program than a C++ compiler, and that translates directly into less time spent debugging—ergo, higher productivity. + ) + + $(P + So what are the good features of C++? + ) + + $(P + Performance is one. It's really hard to beat C++ performance. If your program has to be fast and responsive you have little choice but to write it in C++ (or, in rare cases, in C or assembly). + ) + + $(P + Then there are the low-level features of C++ that let you write programs interacting directly with hardware. For instance, C and C++ are still kings of embedded programming. + ) + + $(P + C++ offers powerful abstractions, in particular the ability to write generic code. Java and C# have their own generics but they are feeble compared to what C++ has to offer. + ) + + $(P + All these features make C++ an ideal language for writing operating + systems. Operating systems are huge programs that have to be fast and + interact directly with hardware. But even outside operating systems + there are a lot of applications that have to be large and fast. + ) + + $(P + So it looks like the programming world could be nicely partitioned between C++, Java, C# and the likes. And it all makes sense as long as you believe in the unavoidability of tradeoffs. But there is no law of nature that says, $(I You have to trade productivity for power). + ) + + $(P + What about a language that is built like an onion. It has a reasonably simple and safe core, which is not unlike Java or C#. A programmer can quickly master a safe subset of it and be as productive as a Java programmer (if not more). And what if the safe subset offered performance that was comparable to C++? + ) + + $(P + And then, the same language has outer layers that can be mastered gradually, as the need arises. It offers low-level features to grind the hardware, and high-level features to generate code on demand. It offers modularity and implementation hiding. It has unrivaled compile time features that enable lightning fast runtime performance. + ) + + $(P + I'll let you in on a secret, this language is D. + ) + + $(SECTION2 $(LNAME2 pitfalls, Programming Pitfalls), + + + $(P + Did you know that the famous $(CODE"Hello World!") program, which is usually the first program people write in C, exposes some of the most dangerous features of the language? It contains this statement: + ) + + $(CCODE +printf ("Hello World!\n");) + + Consider the signature of $(CODE printf): + + $(CCODE +int printf (const char * restrict format, ...); ) + + $(P + ($(CODE restrict) is a new C keyword.) First of all, it's a function that takes a variable number of arguments. The number and the types of arguments are encoded in the format string. + ) + + $(P + When is the match between the format and the argument list checked? Not at compile time—the compiler has no understanding of the format string (although some compilers may issue warnings if the string is statically known). At runtime then? Well, guess again. Consider this: If the programmer makes a mistake of calling printf with too few arguments, he or she will not get a nice error code or exception. Here's what the C Standard says about this situation: + ) + +
+ If there are insufficient arguments for the format, the behavior is undefined. +
+ + $(P + Undefined behavior is the worst thing that may happen to a program. If you're lucky, the program will fault and terminate without prejudice. If you're not so lucky, the program will continue in a compromised state and, in the worst case, it will execute malicious code that will take over your computer. + ) + + $(P + The second dangerous feature of $(CODE printf) is its use of a pointer. It is up to the diligence of the programmer to ensure that a pointer points to a valid piece of data. In the $(CODE"Hello World!") example, the pointer points to a null-terminated static string, so we're fine. But the following program will compile too: + ) + + + $(CCODE +char * format = 0; +printf (format); ) + + $(P + Guess what happens. Inside $(CODE printf) the pointer is dereferenced and then all bets are off. Again, citing the C Standard, + ) + +
+ If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined. +
+ + $(P + Let's talk about pointers some more. Every memory allocation returns a valid pointer (unless the program runs out of memory). You might think that dereferencing such a pointer would be safe. That is correct as long as your program doesn't free the allocated memory thus ending the lifetime of the object. After that, you are dealing with a dangling pointer and all bets are off. Again, the C Standard is pretty upfront about it. + ) + +
+ Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime. +
+ + $(P + As you can see, C was not designed for the faint of heart. It's a low-level language and the programmer better know what he or she is doing or suffer the consequences. + ) + + $(P + C++ is different though, right? + ) + + $(P + Throughout its history, C++ has been struggling with C legacy. A lot of constructs have been provided to patch the unsafe features of C. For instance, the $(CODE"Hello World!") program in C++ might be transformed to a safer version. + ) + + + $(CCODE +std:cout << "Hello World!" << std::endl; ) + + $(P + There is no variable argument count, and the $(CODE std::cout) object is smart enough to understand the types of arguments passed to it (still, many programmers continue using $(CODE printf) in C++, if only for its syntactic simplicity). + ) + + $(P + Unlike in C, memory allocation in C++ is typed and combined with object construction (as long as you stay away from $(CODE malloc) and $(CODE free)). That's the good part. However, objects still have to be explicitly recycled (deleted). And after recycling, the program is still left with dangling pointers, whose dereferencing—you guessed it—leads to undefined behavior. + ) + + $(P + Whereas pointers were important in C, C++ embraced them as the main vehicle for the Standard Library. STL algorithms use iterators, objects that are either pointers themselves or imitate the behavior (and the pitfalls) of pointers. Just like with pointers, a programmer's error in using iterators leads to undefined behavior (see the $(CODE swap_ranges) example). + ) + + $(P + In response to C/C++'s inherent lack of safety, languages like Java and C# took a different path. They either ban pointers altogether or relegate them to special "unsafe" blocks. Memory management, with its risk of accessing recycled data, is taken away from the programmer and dealt with by automatic garbage collection. There are many other simplifications and safety improvements over C++. Unfortunately they all come at the expense of expressive power and performance. + ) +) + + +$(SECTION2 $(LNAME2 safed-subset, The SafeD Subset), + + + $(P + In D, we expect the vast majority of programmers to operate within the safe subset of D, which we call SafeD. The safety and the ease of use of SafeD is comparable to Java—in fact Java programs can be machine-translated into this safe subset of D. SafeD is easy to learn and it keeps the programmers away from undefined behaviors. It is also very efficient. + ) + + $(P + When you enter SafeD, you leave your pointers, unchecked casts and unions at the door. Memory management is provided to you courtesy of Garbage Collection. Class objects are passed around using opaque handles. Arrays and strings are bound-checked (it's possible to turn the checks off with a compiler switch, but then you're no longer in SafeD). You may still write code that will throw a runtime exception (e.g., array out-of-bounds error, or uninitialized-class-object error), but you won't be able to overwrite memory that hasn't been allocated to you or that has already been recycled. + ) + + $(P + Let's look at the $(CODE "Hello World!") program in D. On the face of it, it's not much different than its C counterpart: + ) + +--- +writeln("Hello Safe World!"); +--- + + $(P + The function $(CODE writeln) is the equivalent of the C $(CODE printf) (more precisely, it's the representative of a family of output functions including $(CODE write) and its formatting versions, $(CODE writef) and $(CODE writefln)). Just like $(CODE printf), $(CODE writeln) accepts a variable number of arguments of arbitrary types. But here the similarity ends. As long as you pass SafeD-arguments to $(CODE writeln), you are guaranteed not to encounter any undefined behavior. Here, $(CODE writeln) is called with a single argument of the type $(CODE string). In contrast to C, a D $(CODE string) is not a pointer. It is an array of $(CODE immutable char), and arrays are built into the safe subset of D. + ) + + $(P + You might be interested to know how the safety of $(CODE writeln) is accomplished in D. One possible approach would have been to make $(CODE writeln) a compiler intrinsic, so that correct code would be generated on a case-by-case basis. The beauty of D is that it gives a sophisticated programmer tools that allow such case-by-case code generation of code. The advanced features used in the implementation of writeln are: + $(UL + $(LI Compile-time code generation using templates, and) + $(LI A safe mechanism for dealing with a variable number of arguments using tuples.) + ) + +) + +$(SECTION2 $(LNAME2 safed-libraries, SafeD Libraries), + + $(P + One of the major differences between Java and D is that D has enough power to let an advanced programmer implement libraries that can be used within SafeD. + ) + + $(P + A lot of advanced features of D are compatible with SafeD, as long as they don't force the user to use unsafe types. For instance, a library may provide the implementation of a generic list. The list can be instantiated with any type, in particular with a pointer type. A list of pointers, by definition, cannot be safe, because pointer arithmetic is unsound. However, a list of ints or class objects can and should be safe. That's why such generic lists can be used in SafeD, even though their usage outside of SafeD may be unsafe. + ) + + $(P + Moreover, it might be more efficient to base the internal implementation of a list on pointers. As long as these pointers are not exposed to the client, such an implementation might be certified to be SafeD compatible1. You can have a cake (advanced features of D) and eat it too (take advantage of them in SafeD). + ) +) + + +$(SECTION2 $(LNAME2 user-experience, One User's Experience), + + $(P + Even before I came up with the idea of SafeD2, I tried to + restrict myself to the safe subset of D for most of my projects. I was + surprised how much could be accomplished and how my productivity soared. + I also showed SafeD to my co-worker, a C++ programmer, and he was able + to learn it in a very short time. + ) + + $(P + So far my experience has been that if a SafeD program compiles without + errors then, in a vast majority of cases, it runs without errors, and + does what I want it to do. That definitely hasn't been my experience + with C++. + ) + + $(P + What is even more surprising to me is that I was able to accomplish all + that with almost non-existing support from tools and with a compiler + that excels in cryptic error messages. D is still lacking a lot of + infrastructure, but I can imagine how easy programming will be when a + critical mass of productivity tools sprouts around it. And unlike C++, D + is easy to parse and its front end is open source. So there are no + barriers to entry for tool writers. + ) + +$(SECTION2 $(LNAME2 footnotes, Footnotes), + $(P + $(OL + $(LI There is no central authority to issue such certifications, each library provider has to establish a level of trust with its clients. In particular, you should expect the D standard library to be SafeD certified by the compiler provider.) + $(LI The name, SafeD, was proposed by David B. Held.) + ) + ) +) +) +$(SECTION2 $(LNAME2 acknowledgments, Acknowledgments), +$(P Many thanks go to the rest of the D design team for valuable feedback and corrections to this article) +) +) +) + +Macros: + TITLE=SafeD + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/articles/template-comparison.dd b/articles/template-comparison.dd new file mode 100644 index 0000000000..201902a711 --- /dev/null +++ b/articles/template-comparison.dd @@ -0,0 +1,974 @@ +Ddoc + +$(COMMENT BE CAREFUL TO USE < AND > INSIDE CPPCODE2) + +$(COMMUNITY Template Comparison, + +$(P C++ pioneered templates and template metaprogramming and has continued +to improve on it. +The D programming language is the first to comprehensively reengineer +templates based on the C++ experience. +) + + + + + + $(TR + $(TH Feature) + $(TH D) + $(TH C++) + ) + + + + + $(TR + $(TD Argument list delineation) + $(TD Uses `!( )`, as in `Foo!(int)`. $(BR)Can omit parens when the argument is a single lexical token: `Foo!int`) + $(TD Uses `< >` as in `Foo`) + ) + + $(TR + $(TD Class Templates) + $(TD Yes: +--- +class Foo(T) +{ + T x; +} +--- + ) + $(TD Yes: +$(CPPCODE2 +template<class T> +class Foo +{ + T x; +}; +) + ) + ) + + $(TR + $(TD Function Templates) + $(TD Yes: +--- +T foo(T)(T i) +{ + ... +} +--- + ) + $(TD Yes: +$(CPPCODE2 +template<class T> +T foo(T i) +{ + ... +} +) + ) + ) + + $(TR + $(TD Member Templates) + $(TD Yes) + $(TD Yes) + ) + + $(TR + $(TD Constructor Templates) + $(TD Yes) + $(TD Yes) + ) + + $(TR + $(TD Parameterize any Declaration) + $(TD Yes, classes, functions, any + $(DDSUBLINK spec/declaration, alias, alias), + variables, any enum, etc. can be parameterized, + such as this variable: +--- +template Foo(T) +{ + static T* p; +} +--- + ) + $(TD + $(B$(U C++98))$(BR) + No, only classes and functions + $(BR)$(B$(U C++11))$(BR) + Added `using` type aliases: +$(CPPCODE2 +template<class T> +using ptr = T*; +ptr<int> p; +) + $(B$(U C++14))$(BR) + Added `constexpr` constant: +$(CPPCODE2 +template<class T> +constexpr T pi = T(3.1415926535897932385L); +) + ) + ) + + $(TR + $(TD Template Typedefs: Create an alias that binds to some but not all + of the template parameters) + $(TD Yes: +--- +class Foo(T, U) { } +template MyFoo(T) +{ + alias MyFoo = Foo!(T, int); +} +MyFoo!(uint) f; +--- + ) + $(TD + $(B$(U C++98))$(BR) + No + $(BR)$(B$(U C++11))$(BR) + Yes: +$(CPPCODE2 +template<class T, class U> class Foo { }; +template<class T> using MyFoo = Foo<T, int>; +MyFoo<unsigned> f; +) + ) + ) + + $(TR + $(TD Sequence Constructors) + $(TD No, use a + $(DDSUBLINK spec/function, typesafe_variadic_functions, variadic parameter) instead) + $(TD + $(B$(U C++98))$(BR) + No + $(BR)$(B$(U C++11))$(BR) + Yes: +$(CPPCODE2 +template <class T> +class Foo { + Foo(std::initializer_list<T>); +}; + +Foo<double> f = { 1.2, 3.0, 6.8 }; +) + ) + ) + + $(TR + $(TD Concepts) + + $(TD Yes: $(DDSUBLINK spec/template, template_constraints, Constraints)) + $(TD + $(B$(U C++98))$(BR) + No + $(BR)$(B$(U C++20))$(BR) + Yes: $(LINK2 https://en.cppreference.com/w/cpp/language/constraints, Constraints and Concepts) + ) + ) + + $(TR + $(TD Recursive Templates) + $(TD Yes: +--- +template factorial(int n) +{ + const factorial = n * factorial!(n-1); +} +template factorial(int n : 1) +{ + const factorial = 1; +} +--- + ) + $(TD Yes: +$(CPPCODE2 +template<int n> class factorial +{ + public: + enum { result = n * factorial<n-1>::result }; +}; +template<> class factorial<1> +{ + public: + enum { result = 1 }; +}; +) + ) + ) + + $(TR + $(TD Conditional Compilation + based on Template Arguments) + $(TD Yes: +--- +void foo(T)(T i) +{ + static if (can_fast_foo!(T)) + FastFoo f = fast_foo(i); + else + SlowFoo f = slow_foo(i); + use_foo(f); +} +--- +--- +class HashTable(T, int maxLength) +{ + static if (maxLength < 0xFFFE) + alias CellIdx = ushort; + else + alias CellIdx = uint; + CellIdx index; +} +--- + ) + $(TD + $(B$(U C++98))$(BR) + No, but workarounds exist: +$(CPPCODE2 +template<class T> void foo(T i) +{ + // Differentiate using a + // Helper<bool> specialization + Helper<can_fast_foo<T>>::use_foo(i); +}; + +template<class T, int maxLength> class HashTable { + typedef typename std::conditional< + maxLength < 0xFFFE, uint16_t, uint32_t> + ::type CellIdx; + CellIdx index; +}; +) + $(BR)$(B$(U C++17))$(BR) + Yes, but it's limited to block scope: +$(CPPCODE2 +template<class T> void foo(T i) +{ + if constexpr (can_fast_foo<T>) + FastFoo foo = fast_foo(i); + else + SlowFoo foo = slow_foo(i); + use_foo(foo); // $(ERROR foo is undeclared) +} + +template<class T, int maxLength> class HashTable { + // $(ERROR cannot use 'if' outside of a function) + if constexpr (maxLength < 0xFFFE) + using CellIdx = ushort; + else + using CellIdx = uint; + CellIdx index; +}; +) + ) + ) + + $(TR + $(TD Template Forward Declarations) + $(TD Not necessary) + $(TD Yes: +$(CPPCODE2 +template<class T> +class Foo; +) + ) + ) + + $(TR + $(TD Grouping templates with the same parameters together) + $(TD Yes: +--- +template Foo(T, U) +{ + class Bar { ... } + T foo(T t, U u) { ... } +} +Foo!(int,long).Bar b; +return Foo!(char,int).foo('c',3); +--- + ) + $(TD $(I Sort of), using a class' members: +$(CPPCODE2 +template<class T, class U> +class Foo { + class Bar { ... }; + static T foo(T t, U u) { ... } +}; +Foo<int, long>::bar b; +return Foo<char, int>::foo('c', 3); +) + ) + ) + + $(TR + $(TD Deducing `this` parameter type) + $(TD $(DDSUBLINK spec/template, template_this_parameter, Yes)) + $(TD $(B$(U C++23))$(BR)Yes) + ) + + $(TR + $(TD Compile time execution of functions) + $(TD $(DDSUBLINK spec/function, interpretation, Yes): + +$(RUNNABLE_EXAMPLE_COMPILE +--- +int factorial(int i) +{ + if (i == 0) + return 1; + else + return i * factorial(i - 1); +} +pragma(msg, factorial(6)); +--- +) + ) + $(TD + $(B$(U C++98))$(BR) + No + $(BR)$(B$(U C++11))$(BR) + Yes, but only for $(LINK2 https://en.cppreference.com/w/cpp/language/constexpr, constexpr) functions.$(BR) + constexpr was highly restricted in C++11, but each subsequent standard has eased these restrictions. + ) + ) + + $(TR + $(TH Parameters) + $(TH D) + $(TH C++) + ) + + $(TR + $(TD Type Parameters) + $(TD Yes: +--- +class Foo(T) +{ + T x; +} +Foo!(int) f; +--- +) + $(TD Yes: +$(CPPCODE2 +template<class T> +class Foo +{ + T x; +}; +Foo<int> f; +) + ) + ) + + $(TR + $(TD Integral Parameters) + $(TD Yes: +--- +void foo(int i)() +{ + int v = i; +} +--- + ) + $(TD Yes: +$(CPPCODE2 +template<int i> +void foo() +{ + int v = i; +} +) + ) + ) + + $(TR + $(TD Pointer Parameters) + $(TD Yes, a pointer to object or function) + $(TD Yes, a pointer to object or function) + ) + + $(TR + $(TD Reference Parameters) + $(TD No, but an alias parameter can be used instead (see below).) + $(TD Yes: +$(CPPCODE2 +template<double& D> +void foo() +{ + double y = D; +} +) + ) + ) + + $(TR + $(TD Pointer to Member Parameters) + $(TD No, D does not have pointers to members. It does + have $(DDSUBLINK spec/type, delegates, delegates) however, + which can be used as parameters) + $(TD Yes) + ) + + $(TR + $(TD Template Template Parameters) + $(TD Yes: +--- +class Foo(T, alias C) +{ + C!(T) x; +} +--- + ) + $(TD Yes: +$(CPPCODE2 +template<class T, + template<class U> class C> +class Foo +{ + C<T> x; +}; +) + ) + ) + + $(TR + $(TD Alias Parameters) + $(TD Yes, any symbol can be passed to a template as an alias: +--- +void bar(int); +void bar(double); +void foo(T, alias S)(T t) +{ + S(t); +} +// calls bar(double) +foo!(double, bar)(1); +--- + ) + $(TD No) + ) + + $(TR + $(TD Floating Point Parameters) + $(TD Yes: +--- +class Foo(double D) +{ + double x = D; +} +... +Foo!(1.6) F; +--- + ) + $(TD + $(B$(U C++98))$(BR) + No + $(BR)$(B$(U C++11))$(BR) + Yes: +$(CPPCODE2 +template<float f> +void foo() +{ + int v = f; +} +) + ) + ) + + $(TR + $(TD String Parameters) + $(TD Yes: +--- +void foo(string format)(int i) +{ + writefln(format, i); +} +... +foo!("i = %s")(3); +--- + ) + $(TD + $(B$(U C++98))$(BR) + No + $(BR)$(B$(U C++17))$(BR) + Only indirectly: +$(CPPCODE2 +template <const char *str> +struct S {}; + +S<"Foo"> foo1; // $(ERROR A string literal argument is still illegal) +const char foo_str[] = "foo"; +S<foo_str> foo2; // Literal types are allowed, including arrays. +) + ) + ) + + $(TR + $(TD Local Class Parameters) + $(TD Yes) + $(TD + $(B$(U C++98))$(BR) + No + $(BR)$(B$(U C++17))$(BR) + Yes + ) + ) + + $(TR + $(TD Local Variable Parameters) + $(TD Yes) + $(TD No) + ) + + $(TR + $(TD Parameter Default Values) + $(TD Yes: +--- +class Foo(T = int) +{ + T x; +} +--- + ) + $(TD Yes: +$(CPPCODE2 +template<class T = int> +class Foo +{ + T x; +}; +) + ) + ) + + $(TR + $(TD Variadic Parameters) + $(TD Yes, $(LINK2 variadic-function-templates.html, Variadic Templates): +--- +void print(A...)(A a) +{ + foreach(t; a) + writeln(t); +} +--- + ) + $(TD + $(B$(U C++98))$(BR) + No + $(BR)$(B$(U C++11))$(BR) + Yes: +$(CPPCODE2 +// Need a zero- or one-argument version +// to handle the final argument. +void print() {}; + +template <class Arg, class... Args> +void print(const Arg& arg, Args&&... args) +{ + writeln(arg); + print(std::forward<Args>(args)...); +} +) + Note that the example above was + improved somewhat in C++17 using + $(LINK2 https://en.cppreference.com/w/cpp/language/fold, Fold Expressions): +$(CPPCODE2 +template <class Args...> +void print(Args...&& args) +{ + (writeln(std::forward<Args.>(args)), ...); +} +) + ) + ) + + $(TR + $(TH Specializations) + $(TH D) + $(TH C++) + ) + + $(TR + $(TD Explicit Specialization) + $(TD Yes: +--- +class Foo(T : int) +{ + T x; +} +--- + ) + $(TD Yes: +$(CPPCODE2 +template<> +class Foo<int> +{ + int x; +}; +) + ) + ) + + $(TR + $(TD Partial Specialization) + $(TD Yes: +--- +class Foo(T : T*, U) +{ + T x; +} +--- + ) + $(TD Yes: +$(CPPCODE2 +template<class T, class U> +class Foo<T*, U> +{ + T x; +}; +) + ) + ) + + $(TR + $(TD Partial specialization derived from multiple parameters) + $(TD Yes: +--- +class Foo(T : Bar!(T, U), U) +{ + ... +} +--- + ) + $(TD Yes: +$(CPPCODE2 +template<class T, class U> +class Foo< Bar<T,U> > +{ + ... +}; +) + ) + ) + + $(TR + $(TD Can specializations exist without a primary template?) + $(TD Yes) + $(TD No) + ) + + $(TR + $(TH Other) + $(TH D) + $(TH C++) + ) + + $(TR + $(TD Exported Templates) + $(TD Yes, it falls out as a natural consequence of modules) + $(TD + $(B$(U C++98))$(BR) + Yes, but was only support in compilers based on EDG's front end. + $(BR)$(B$(U C++11))$(BR) + Was removed from the language due to a lack of support. + ) + ) + + $(TR + $(TD $(SFINAE)) + $(TD No) + $(TD Yes) + ) + + $(TR + $(TD Parse Template Definition Bodies before Instantiation) + $(TD Yes) + $(TD Not required by the Standard, but some implementations do) + ) + + $(TR + $(TD Overloading Function Templates with Functions) + $(TD Yes: +--- +void foo(T)(T t) { } +void foo(int i) { } +--- + ) + $(TD Yes: +$(CPPCODE2 +template<class T> +void foo(T t) { } +void foo(int i) { } +) + ) + ) + + $(TR + $(TD Implicit Function Template Instantiation) + $(TD Yes) + $(TD Yes) + ) + + $(TR + $(TD Templates can be evaluated in scope + of instantiation rather than definition) + $(TD Yes, $(DDLINK spec/template-mixin, Template Mixins, Template Mixins)) + $(TD No, but can be faked using macros) + ) + + $(TR + $(TD Can extract arguments of + template instance) + $(TD Yes: + +$(RUNNABLE_EXAMPLE_COMPILE +--- +struct Bar(T1, T2) { } +alias BarInst = Bar!(int, float); + +static if (is(BarInst : Template!Args, alias Template, Args...)) +{ + pragma(msg, Args); // (int, float) +} +--- +) + See $(DDSUBLINK spec/expression, IsExpression, is expressions).) + $(TD No) + ) + + $(TR + $(TH Parsing Idiosyncracies) + $(TH D) + $(TH C++) + ) + + $(TR + $(TD Context-Free Grammar) + $(TD Yes: +--- +class Foo(int i) +{ + ... +} +Foo!(3 $(B >) 4) f; +--- + ) + $(TD No: +$(CPPCODE2 +template<int i> class Foo +{ + ... +}; +Foo<3 $(B >) 4> f; // $(ERROR) +) + ) + ) + + $(TR + $(TD Distinguish template arguments from other operators) + $(TD Yes: +--- +class Foo(T) +{ + ... +} +class Bar(int i) +{ + ... +} +Foo!(Bar!(1)) x1; +--- + ) + $(TD + $(B$(U C++98))$(BR) + No: +$(CPPCODE2 +template<class T> class Foo +{ + ... +}; +template<int i> class Bar +{ + ... +}; +Foo<Bar<1>> x1; // $(ERROR) +Foo<Bar<1> > x2; +) + $(BR)$(B$(U C++11))$(BR) + Partially fixed by $(LINK2 http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1757.html, Right Angle Brackets N1757) + ) + ) + + + $(TR + $(TD Redeclaration of Template Parameter) + $(TD Yes: +--- +class Foo(T) +{ + int T; + void foo() + { + int T; + } +} +--- + ) + $(TD No: +$(CPPCODE2 +template<class T> +class Foo +{ + int T; // $(ERROR) + void foo() + { + int T; // $(ERROR) + } +}; +) + ) + ) + + $(TR + $(TD Dependent Base Class Lookup) + $(TD Yes: +--- +class Foo(T) +{ + alias $(B A) = int; +} +class Bar(T) : Foo(T) +{ + $(B A) x; +} +--- + ) + $(TD No: +$(CPPCODE2 +template<class T> +class Foo +{ + public: + typedef int $(B A); +}; +template<class T> +class Bar : Foo<T> +{ + public: + $(B A) x; // $(ERROR) +}; +) + ) + ) + + $(TR + $(TD Forward Referencing) + $(TD Yes: +--- +int $(B g)(void *); + +class Foo(T) +{ + int foo() + { + return $(B g)(1); + } +} + +int $(B g)(int i); +--- + ) + $(TD No: +$(CPPCODE2 +int $(B g)(void *); + +template<class T> +class Foo +{ + int foo() + { + return $(B g)(1); // $(ERROR) + } +}; + +int $(B g)(int i); +) + ) + ) + + $(TR + $(TD Member templates parseable without hints) + $(TD Yes: +--- +class Foo +{ + Foo bar!(int I)(); +} +void abd(T)(T f) +{ + T f1 = f.bar!(3)(); +} +--- + ) + $(TD No: +$(CPPCODE2 +class Foo +{ + public: + template<int> Foo *bar(); +}; +template<class T> void abc(T *f) +{ + T *f1 = f->bar<3>(); // $(ERROR) + T *f2 = f->$(B template) bar<3>(); +} +) + ) + ) + + $(TR + $(TD Dependent type members parseable without hints) + $(TD Yes: +--- +class Foo(T) +{ + T.A* a1; +} +--- + ) + $(TD No: +$(CPPCODE2 +template$(LT)class T$(GT) class Foo +{ + public: + T::A *a1; // $(ERROR) + $(B typename) T::A *a2; +}; +) + ) + ) + + +
Template Comparison Table
+) + +Macros: + TITLE=Template Comparison + NO=No + NO1=No + D_CODE =
$0
+ CPPCODE2 =
$0
+ ERROR = $(RED $(B error) $0) + SUBNAV=$(SUBNAV_ARTICLES) +META_KEYWORDS=D Programming Language, template metaprogramming, +variadic templates, type deduction, dependent base class +META_DESCRIPTION=Comparison of templates between the +D programming language and C++ diff --git a/templates-revisited.dd b/articles/templates-revisited.dd similarity index 52% rename from templates-revisited.dd rename to articles/templates-revisited.dd index 08358710ce..9d6e5869c5 100644 --- a/templates-revisited.dd +++ b/articles/templates-revisited.dd @@ -8,7 +8,7 @@ $(I by Walter Bright, $(LINK http://www.digitalmars.com/d))

-$(BLOCKQUOTE Richard Deeman, +$(BLOCKQUOTE_BY Richard Deeman, What I am going to tell you about is what we teach our programming students in the third or fourth year of graduate school... It is my task to convince you not to turn away because you don't understand it. You see my programming students @@ -16,7 +16,9 @@ don't understand it... That is because I don't understand it. Nobody does. ) -

Abstract

+$(HEADERNAV_TOC) + +$(H2 $(LNAME2 abstract, Abstract)) $(P Templates in C++ have evolved from little more than token substitution into a @@ -31,7 +33,7 @@ This article takes a look at an alternative design of templates in the D Programming Language [1]. ) -

Similarities

+$(H2 $(LNAME2 similarities, Similarities)) $(UL $(LI compile time semantics) @@ -47,7 +49,7 @@ $(LI $(ACRONYM SFINAE, Substitution Failure Is Not An Error)) ) -

Argument Syntax

+$(H2 $(LNAME2 argument-syntax, Argument Syntax)) $(P The first thing that comes to mind is the use of < > to enclose parameter @@ -99,7 +101,7 @@ code to determine that yes, $(D a) must be a template. ) -

Template Definition Syntax

+$(H2 $(LNAME2 template-definition-syntax, Template Definition Syntax)) $(P C++ can define two broad types of templates: class templates, and function @@ -126,13 +128,13 @@ In D, we can write: ---- template Foo(T, U) { - class Bar { ... } + class Bar { ... } - T foo(T t, U u) { ... } + T foo(T t, U u) { ... } - T abc; + T abc; - typedef T* Footype; // any declarations can be templated + typedef T* Footype; // any declarations can be templated } ---- @@ -153,7 +155,7 @@ for a particular instantiation: ) --- -alias Foo!(int,char) f; +alias f = Foo!(int,char); f.Bar b; f.foo(1,2); f.abc = 3; @@ -185,7 +187,7 @@ class Abc(T) --- -

Template Declaration, Definition, and Export

+$(H2 $(LNAME2 template-declaration, Template Declaration, Definition, and Export)) $(P C++ templates can be in the form of a template declaration, a template @@ -228,7 +230,7 @@ As usual, an alias can be used to simplify access: module B; import A; -alias A.Foo!(int).bar bar; +alias bar = A.Foo!(int).bar; void test() { @@ -237,7 +239,7 @@ void test() --- -

Template Parameters

+$(H2 $(LNAME2 template-parameters, Template Parameters)) $(P C++ template parameters can be:) @@ -269,27 +271,28 @@ class B { ... } interface I { ... } class Foo( - R, // R can be any type - P:P*, // P must be a pointer type - T:int, // T must be int type - S:T*, // S must be pointer to T - C:B, // C must be of class B or derived - // from B - U:I, // U must be a class that - // implements interface I - string str = "hello", - // string literal, - // default is "hello" - alias A = B // A is any symbol - // (including template symbols), - // defaulting to B - ) + R, // R can be any type + P:P*, // P must be a pointer type + T:int, // T must be int type + S:T*, // S must be pointer to T + C:B, // C must be of class B or derived + // from B + U:I, // U must be interface I, or any interface + // or class which has interface I in its + // inheritance tree + string str = "hello", + // string literal, + // default is "hello" + alias A = B // A is any symbol + // (including template symbols), + // defaulting to B + ) { ... } --- -

Specialization

+$(H2 $(LNAME2 specialization, Specialization)) $(P Partial and explicit specialization work as they do in C++, except that @@ -308,14 +311,17 @@ template Foo(T, U:int) ... Foo!(long) // picks Foo(T) Foo!(long[]) // picks Foo(T), T is long[] Foo!(int*) // picks Foo(T*), T is int -Foo!(long,long) // picks Foo(T, T) +Foo!(long,long) // picks Foo(T, U:T) Foo!(long,short) // picks Foo(T, U) Foo!(long,int) // picks Foo(T, U:int) Foo!(int,int) // ambiguous - Foo(T, U:T) // or Foo(T, U:int) --- -

Two Level Name Lookup

+$(P A template can also have a $(DDLINK articles/constraints, Template Constraints, boolean constraint) +evaluated at compile-time.) + +$(H2 $(LNAME2 two-level-name-lookups, Two Level Name Lookup)) $(P C++ has some unusual rules for name lookup inside templates, such @@ -330,22 +336,23 @@ int g(double d) { return 1; } typedef double A; -template<class T> B +template<class T> struct B { - typedef int A; + typedef int A; }; template<class T> struct X : B<T> { - A a; // a has type double - int T; // error, T redeclared - int foo() - { char T; // error, T redeclared - return g(1); // always returns 1 - } + A a; // a has type double + int T; // error, T redeclared + int foo() + { + char T; // error, T redeclared + return g(1); // always returns 1 + } }; -int g(int i) { return 2; } // this definition not seen by X +int g(int i) { return 2; } // this definition not seen by X ) $(P @@ -355,29 +362,30 @@ Scoped lookup rules in D match the rules for the rest of the language: --- int g(double d) { return 1; } -typedef double A; +alias A = double; class B(T) { - typedef int A; + alias A = int; } class X(T) : B!(T) { - A a; // a has type int - int T; // ok, T redeclared as int - int foo() - { char T; // ok, T redeclared as char - return g(1); // always returns 2 - } + A a; // a has type int + int T; // ok, T redeclared as int + int foo() + { + char T; // ok, T redeclared as char + return g(1); // always returns 2 + } }; -int g(int i) { return 2; } // functions can be forward referenced +int g(int i) { return 2; } // functions can be forward referenced --- -

Template Recursion

+$(H2 $(LNAME2 template-recursion, Template Recursion)) $(P Template recursion combined with specialization means that C++ templates @@ -390,23 +398,23 @@ of template metaprogramming: $(CCODE template<int n> class factorial { - public: - enum - { - result = n * factorial<n - 1>::result - }; + public: + enum + { + result = n * factorial<n - 1>::result + }; }; template<> class factorial<1> { - public: - enum { result = 1 }; + public: + enum { result = 1 }; }; void test() { - // prints 24 - printf("%d\n", factorial<4>::result); + // prints 24 + printf("%d\n", factorial<4>::result); } ) @@ -417,17 +425,17 @@ Recursion works as well in D, though with significantly less typing: --- template factorial(int n) { - const factorial = n * factorial!(n-1); + const factorial = n * factorial!(n-1); } template factorial(int n : 1) { - const factorial = 1; + const factorial = 1; } void test() { - writefln(factorial!(4)); // prints 24 + writeln(factorial!(4)); // prints 24 } --- @@ -439,16 +447,16 @@ template: --- template factorial(int n) { - static if (n == 1) - const factorial = 1; - else - const factorial = n * factorial!(n-1); + static if (n == 1) + const factorial = 1; + else + const factorial = n * factorial!(n-1); } --- $(P reducing 13 lines of code to an arguably much cleaner 7 lines. -$(D static if)'s are the equivalent of C++'s $(D #if). +$(D static if)s are the equivalent of C++'s $(D #if). But $(D #if) cannot access template arguments, so all template conditional compilation must be handled with partial and explicitly specialized templates. @@ -463,16 +471,16 @@ a function that can be computed at compile time:) --- int factorial(int n) { - if (n == 1) - return 1; - else - return n * factorial(n - 1); + if (n == 1) + return 1; + else + return n * factorial(n - 1); } static int x = factorial(5); // x is statically initialized to 120 --- -

$(ACRONYM SFINAE, Substitution Failure Is Not An Error)

+$(H2 $(LNAME2 sfinae, Substitution Failure Is Not An Error (SFINAE))) $(P This determines if the template's argument type is a function, @@ -483,22 +491,23 @@ Vandevoorde & Josuttis pg. 353: $(CCODE template<U> class IsFunctionT { - private: - typedef char One; - typedef struct { char a[2]; } Two; - template static One test(...); - template static Two test(U (*)[1]); - public: - enum { - Yes = sizeof(IsFunctionT::test(0)) == 1 - }; + private: + typedef char One; + typedef struct { char a[2]; } Two; + template static One test(...); + template static Two test(U (*)[1]); + public: + enum + { + Yes = sizeof(IsFunctionT::test(0)) == 1 + }; }; void test() { - typedef int (fp)(int); + typedef int (fp)(int); - assert(IsFunctionT<fp>::Yes == 1); + assert(IsFunctionT<fp>::Yes == 1); } ) @@ -522,17 +531,17 @@ In D this can be written: --- template IsFunctionT(T) { - static if ( is(T[]) ) - const int IsFunctionT = 0; - else - const int IsFunctionT = 1; + static if (is(T[])) + const int IsFunctionT = 0; + else + const int IsFunctionT = 1; } void test() { - alias int fp(int); + alias int fp(int); - assert(IsFunctionT!(fp) == 1); + assert(IsFunctionT!(fp) == 1); } --- @@ -544,20 +553,22 @@ an invalid type, the $(D T[]) fails and $(D is(T[])) returns false. ) $(P -Although $(SFINAE) can be used, the is expressions can test a type directly, -so it isn't even necessary to use a template to ask questions about a type: +Although $(SFINAE) can be used, the +$(DDSUBLINK spec/expression, IsExpression, is expressions) can test a type +directly, so it isn't even necessary to use a template to ask questions about a +type: ) --- void test() { - alias int fp(int); + alias int fp(int); - assert( is(fp == function) ); + assert(is(fp == function)); } --- -

Template Metaprogramming With Floats

+$(H2 $(LNAME2 template-metaprogramming-floats, Template Metaprogramming With Floats)) $(P Let's move on to things that are impractical with templates in C++. @@ -570,15 +581,15 @@ import std.stdio; template sqrt(real x, real root = x/2, int ntries = 0) { - static if (ntries == 5) - // precision doubles with each iteration, - // 5 should be enough - const sqrt = root; - else static if (root * root - x == 0) - const sqrt = root; // exact match - else - // iterate again - const sqrt = sqrt!(x, (root+x/root)/2, ntries+1); + static if (ntries == 5) + // precision doubles with each iteration, + // 5 should be enough + const sqrt = root; + else static if (root * root - x == 0) + const sqrt = root; // exact match + else + // iterate again + const sqrt = sqrt!(x, (root+x/root)/2, ntries+1); } void main() @@ -609,16 +620,16 @@ real sqrt(real x) real root = x / 2; for (int ntries = 0; ntries < 5; ntries++) { - if (root * root - x == 0) - break; - root = (root + x / root) / 2; + if (root * root - x == 0) + break; + root = (root + x / root) / 2; } return root; } static y = sqrt(10); // y is statically initialized to 3.16228 --- -

Template Metaprogramming With Strings

+$(H2 $(LNAME2 template-metaprogramming-strings, Template Metaprogramming With Strings)) $(P Even more interesting things can be done with strings. This example @@ -626,24 +637,24 @@ converts an integer to a string at compile time: ) --- -template decimalDigit(int n) // [3] +template decimalDigit(int n) // [3] { - const string decimalDigit = "0123456789"[n..n+1]; + const string decimalDigit = "0123456789"[n..n+1]; } template itoa(long n) { - static if (n < 0) - const string itoa = "-" ~ itoa!(-n); - else static if (n < 10) - const string itoa = decimalDigit!(n); - else - const string itoa = itoa!(n/10L) ~ decimalDigit!(n%10L); + static if (n < 0) + const string itoa = "-" ~ itoa!(-n); + else static if (n < 10) + const string itoa = decimalDigit!(n); + else + const string itoa = itoa!(n/10L) ~ decimalDigit!(n%10L); } string foo() { - return itoa!(264); // returns "264" + return itoa!(264); // returns "264" } --- @@ -654,10 +665,10 @@ This template will compute the hash of a string literal: --- template hash(char [] s, uint sofar=0) { - static if (s.length == 0) - const hash = sofar; - else - const hash = hash!(s[1 .. length], sofar * 11 + s[0]); + static if (s.length == 0) + const hash = sofar; + else + const hash = hash!(s[1 .. $], sofar * 11 + s[0]); } uint foo() @@ -666,7 +677,7 @@ uint foo() } --- -

Regular Expression Compiler

+$(H2 $(LNAME2 regular-expression-compiler, Regular Expression Compiler)) $(P How do D templates fare with something much more significant, like @@ -728,14 +739,14 @@ const int testFail = -1; template regexMatch(string pattern) { - string[] regexMatch(string str) - { - string[] results; - int n = regexCompile!(pattern).fn(str); - if (n != testFail && n > 0) - results ~= str[0..n]; - return results; - } + string[] regexMatch(string str) + { + string[] results; + int n = regexCompile!(pattern).fn(str); + if (n != testFail && n > 0) + results ~= str[0..n]; + return results; + } } /****************************** @@ -743,109 +754,110 @@ template regexMatch(string pattern) * to match each predicate of the regular expression. * * Params: - * string str the input string to match against + * string str the input string to match against * * Returns: - * testFail failed to have a match - * n >= 0 matched n characters + * testFail failed to have a match + * n >= 0 matched n characters */ /// Always match template testEmpty() { - int testEmpty(string str) { return 0; } + int testEmpty(string str) { return 0; } } /// Match if testFirst(str) and testSecond(str) match template testUnion(alias testFirst, alias testSecond) { - int testUnion(string str) - { - int n1 = testFirst(str); - if (n1 != testFail) + int testUnion(string str) { - int n2 = testSecond(str[n1 .. $]); - if (n2 != testFail) - return n1 + n2; + int n1 = testFirst(str); + if (n1 != testFail) + { + int n2 = testSecond(str[n1 .. $]); + if (n2 != testFail) + return n1 + n2; + } + return testFail; } - return testFail; - } } /// Match if first part of str[] matches text[] template testText(string text) { - int testText(string str) - { - if (str.length && - text.length <= str.length && - str[0..text.length] == text - ) - return text.length; - return testFail; - } + int testText(string str) + { + if (str.length && + text.length <= str.length && + str[0..text.length] == text) + { + return text.length; + } + return testFail; + } } /// Match if testPredicate(str) matches 0 or more times template testZeroOrMore(alias testPredicate) { - int testZeroOrMore(string str) - { - if (str.length == 0) - return 0; - int n = testPredicate(str); - if (n != testFail) + int testZeroOrMore(string str) { - int n2 = testZeroOrMore!(testPredicate)(str[n .. $]); - if (n2 != testFail) - return n + n2; - return n; + if (str.length == 0) + return 0; + int n = testPredicate(str); + if (n != testFail) + { + int n2 = testZeroOrMore!(testPredicate)(str[n .. $]); + if (n2 != testFail) + return n + n2; + return n; + } + return 0; } - return 0; - } } /// Match if term1[0] <= str[0] <= term2[0] template testRange(string term1, string term2) { - int testRange(string str) - { - if (str.length && str[0] >= term1[0] - && str[0] <= term2[0]) - return 1; - return testFail; - } + int testRange(string str) + { + if (str.length && str[0] >= term1[0] + && str[0] <= term2[0]) + return 1; + return testFail; + } } /// Match if ch[0]==str[0] template testChar(string ch) { - int testChar(string str) - { - if (str.length && str[0] == ch[0]) - return 1; - return testFail; - } + int testChar(string str) + { + if (str.length && str[0] == ch[0]) + return 1; + return testFail; + } } /// Match if str[0] is a word character template testWordChar() { - int testWordChar(string str) - { - if (str.length && - ( - (str[0] >= 'a' && str[0] <= 'z') || - (str[0] >= 'A' && str[0] <= 'Z') || - (str[0] >= '0' && str[0] <= '9') || - str[0] == '_' - ) - ) + int testWordChar(string str) { - return 1; + if (str.length && + ( + (str[0] >= 'a' && str[0] <= 'z') || + (str[0] >= 'A' && str[0] <= 'Z') || + (str[0] >= '0' && str[0] <= '9') || + str[0] == '_' + ) + ) + { + return 1; + } + return testFail; } - return testFail; - } } /*****************************************************/ @@ -857,68 +869,68 @@ template testWordChar() template parseTextToken(string pattern) { - static if (pattern.length > 0) - { - static if (isSpecial!(pattern)) - const string parseTextToken = ""; + static if (pattern.length > 0) + { + static if (isSpecial!(pattern)) + const string parseTextToken = ""; + else + const string parseTextToken = + pattern[0..1] ~ parseTextToken!(pattern[1..$]); + } else - const string parseTextToken = - pattern[0..1] ~ parseTextToken!(pattern[1..$]); - } - else - const string parseTextToken=""; + const string parseTextToken=""; } /** * Parses pattern[] up to and including terminator. * Returns: - * token[] everything up to terminator. - * consumed number of characters in pattern[] parsed + * token[] everything up to terminator. + * consumed number of characters in pattern[] parsed */ template parseUntil(string pattern,char terminator,bool fuzzy=false) { - static if (pattern.length > 0) - { - static if (pattern[0] == '\\') + static if (pattern.length > 0) { - static if (pattern.length > 1) - { - const string nextSlice = pattern[2 .. $]; - alias parseUntil!(nextSlice,terminator,fuzzy) next; - const string token = pattern[0 .. 2] ~ next.token; - const uint consumed = next.consumed+2; - } - else - { - pragma(msg,"Error: expected character to follow \\"); - static assert(false); - } + static if (pattern[0] == '\\') + { + static if (pattern.length > 1) + { + const string nextSlice = pattern[2 .. $]; + alias next = parseUntil!(nextSlice,terminator,fuzzy); + const string token = pattern[0 .. 2] ~ next.token; + const uint consumed = next.consumed+2; + } + else + { + pragma(msg,"Error: expected character to follow \\"); + static assert(false); + } + } + else static if (pattern[0] == terminator) + { + const string token=""; + const uint consumed = 1; + } + else + { + const string nextSlice = pattern[1 .. $]; + alias next = parseUntil!(nextSlice,terminator,fuzzy); + const string token = pattern[0..1] ~ next.token; + const uint consumed = next.consumed+1; + } } - else static if (pattern[0] == terminator) + else static if (fuzzy) { - const string token=""; - const uint consumed = 1; + const string token = ""; + const uint consumed = 0; } else { - const string nextSlice = pattern[1 .. $]; - alias parseUntil!(nextSlice,terminator,fuzzy) next; - const string token = pattern[0..1] ~ next.token; - const uint consumed = next.consumed+1; + pragma(msg, "Error: expected " ~ + terminator ~ + " to terminate group expression"); + static assert(false); } - } - else static if (fuzzy) - { - const string token = ""; - const uint consumed = 0; - } - else - { - pragma(msg,"Error: expected " ~ - terminator ~ - " to terminate group expression"); - static assert(false); - } } /** @@ -932,47 +944,47 @@ template parseUntil(string pattern,char terminator,bool fuzzy=false) template regexCompileCharClass2(string pattern) { - static if (pattern.length > 0) - { - static if (pattern.length > 1) + static if (pattern.length > 0) { - static if (pattern[1] == '-') - { - static if (pattern.length > 2) + static if (pattern.length > 1) { - alias testRange!(pattern[0..1], pattern[2..3]) termFn; - const uint thisConsumed = 3; - const string remaining = pattern[3 .. $]; + static if (pattern[1] == '-') + { + static if (pattern.length > 2) + { + alias termFn = testRange!(pattern[0..1], pattern[2..3]); + const uint thisConsumed = 3; + const string remaining = pattern[3 .. $]; + } + else // length is 2 + { + pragma(msg, + "Error: expected char following '-' in char class"); + static assert(false); + } + } + else // not '-' + { + alias termFn = testChar!(pattern[0..1]); + const uint thisConsumed = 1; + const string remaining = pattern[1 .. $]; + } } - else // length is 2 + else { - pragma(msg, - "Error: expected char following '-' in char class"); - static assert(false); + alias termFn = testChar!(pattern[0..1]); + const uint thisConsumed = 1; + const string remaining = pattern[1 .. $]; } - } - else // not '-' - { - alias testChar!(pattern[0..1]) termFn; - const uint thisConsumed = 1; - const string remaining = pattern[1 .. $]; - } + alias recurse = regexCompileCharClassRecurse!(termFn,remaining); + alias fn = recurse.fn; + const uint consumed = recurse.consumed + thisConsumed; } else { - alias testChar!(pattern[0..1]) termFn; - const uint thisConsumed = 1; - const string remaining = pattern[1 .. $]; + alias fn = testEmpty!(); + const uint consumed = 0; } - alias regexCompileCharClassRecurse!(termFn,remaining) recurse; - alias recurse.fn fn; - const uint consumed = recurse.consumed + thisConsumed; - } - else - { - alias testEmpty!() fn; - const uint consumed = 0; - } } /** @@ -988,17 +1000,17 @@ template regexCompileCharClass2(string pattern) template regexCompileCharClassRecurse(alias termFn,string pattern) { - static if (pattern.length > 0 && pattern[0] != ']') - { - alias regexCompileCharClass2!(pattern) next; - alias testOr!(termFn,next.fn,pattern) fn; - const uint consumed = next.consumed; - } - else - { - alias termFn fn; - const uint consumed = 0; - } + static if (pattern.length > 0 && pattern[0] != ']') + { + alias next = regexCompileCharClass2!(pattern); + alias fn = testOr!(termFn,next.fn,pattern); + const uint consumed = next.consumed; + } + else + { + alias fn = termFn; + const uint consumed = 0; + } } /** @@ -1012,25 +1024,25 @@ template regexCompileCharClassRecurse(alias termFn,string pattern) template regexCompileCharClass(string pattern) { - static if (pattern.length > 0) - { - static if (pattern[0] == ']') + static if (pattern.length > 0) { - alias testEmpty!() fn; - const uint consumed = 0; + static if (pattern[0] == ']') + { + alias fn = testEmpty!(); + const uint consumed = 0; + } + else + { + alias charClass = regexCompileCharClass2!(pattern); + alias fn = charClass.fn; + const uint consumed = charClass.consumed; + } } else { - alias regexCompileCharClass2!(pattern) charClass; - alias charClass.fn fn; - const uint consumed = charClass.consumed; + pragma(msg,"Error: expected closing ']' for character class"); + static assert(false); } - } - else - { - pragma(msg,"Error: expected closing ']' for character class"); - static assert(false); - } } /** @@ -1045,16 +1057,16 @@ template regexCompileCharClass(string pattern) template regexCompilePredicate(alias test, string pattern) { - static if (pattern.length > 0 && pattern[0] == '*') - { - alias testZeroOrMore!(test) fn; - const uint consumed = 1; - } - else - { - alias test fn; - const uint consumed = 0; - } + static if (pattern.length > 0 && pattern[0] == '*') + { + alias fn = testZeroOrMore!(test); + const uint consumed = 1; + } + else + { + alias fn = test; + const uint consumed = 0; + } } /** @@ -1068,29 +1080,29 @@ template regexCompilePredicate(alias test, string pattern) template regexCompileEscape(string pattern) { - static if (pattern.length > 0) - { - static if (pattern[0] == 's') - { - // whitespace char - alias testRange!("\x00","\x20") fn; - } - else static if (pattern[0] == 'w') + static if (pattern.length > 0) { - //word char - alias testWordChar!() fn; + static if (pattern[0] == 's') + { + // whitespace char + alias fn = testRange!("\x00","\x20"); + } + else static if (pattern[0] == 'w') + { + // word char + alias fn = testWordChar!(); + } + else + { + alias fn = testChar!(pattern[0 .. 1]); + } + const uint consumed = 1; } else { - alias testChar!(pattern[0 .. 1]) fn; + pragma(msg,"Error: expected char following '\\'"); + static assert(false); } - const uint consumed = 1; - } - else - { - pragma(msg,"Error: expected char following '\\'"); - static assert(false); - } } /** @@ -1103,106 +1115,107 @@ template regexCompileEscape(string pattern) template regexCompile(string pattern) { - static if (pattern.length > 0) - { - static if (pattern[0] == '[') - { - const string charClassToken = - parseUntil!(pattern[1 .. $],']').token; - alias regexCompileCharClass!(charClassToken) charClass; - const string token = pattern[0 .. charClass.consumed+2]; - const string next = pattern[charClass.consumed+2 .. $]; - alias charClass.fn test; - } - else static if (pattern[0] == '\\') + static if (pattern.length > 0) { - alias regexCompileEscape!(pattern[1..pattern.length]) escapeSequence; - const string token = pattern[0 .. escapeSequence.consumed+1]; - const string next = - pattern[escapeSequence.consumed+1 .. $]; - alias escapeSequence.fn test; - } - else - { - const string token = parseTextToken!(pattern); - static assert(token.length > 0); - const string next = pattern[token.length .. $]; - alias testText!(token) test; - } + static if (pattern[0] == '[') + { + const string charClassToken = + parseUntil!(pattern[1 .. $],']').token; + alias charClass = regexCompileCharClass!(charClassToken); + const string token = pattern[0 .. charClass.consumed+2]; + const string next = pattern[charClass.consumed+2 .. $]; + alias test = charClass.fn; + } + else static if (pattern[0] == '\\') + { + alias escapeSequence = + regexCompileEscape!(pattern[1 .. pattern.length]); + const string token = pattern[0 .. escapeSequence.consumed+1]; + const string next = + pattern[escapeSequence.consumed+1 .. $]; + alias test = escapeSequence.fn; + } + else + { + const string token = parseTextToken!(pattern); + static assert(token.length > 0); + const string next = pattern[token.length .. $]; + alias test = testText!(token); + } - alias regexCompilePredicate!(test, next) term; - const string remaining = next[term.consumed .. next.length]; + alias term = regexCompilePredicate!(test, next); + const string remaining = next[term.consumed .. next.length]; - alias regexCompileRecurse!(term,remaining).fn fn; - } - else - alias testEmpty!() fn; + alias fn = regexCompileRecurse!(term,remaining).fn; + } + else + alias fn = testEmpty!(); } template regexCompileRecurse(alias term,string pattern) { - static if (pattern.length > 0) - { - alias regexCompile!(pattern) next; - alias testUnion!(term.fn, next.fn) fn; - } - else - alias term.fn fn; + static if (pattern.length > 0) + { + alias next = regexCompile!(pattern); + alias fn = testUnion!(term.fn, next.fn); + } + else + alias fn = term.fn; } /// Utility function for parsing template isSpecial(string pattern) { - static if ( - pattern[0] == '*' || - pattern[0] == '+' || - pattern[0] == '?' || - pattern[0] == '.' || - pattern[0] == '[' || - pattern[0] == '{' || - pattern[0] == '(' || - pattern[0] == ')' || - pattern[0] == '$' || - pattern[0] == '^' || - pattern[0] == '\\' - ) - const isSpecial = true; - else - const isSpecial = false; + static if ( + pattern[0] == '*' || + pattern[0] == '+' || + pattern[0] == '?' || + pattern[0] == '.' || + pattern[0] == '[' || + pattern[0] == '{' || + pattern[0] == '(' || + pattern[0] == ')' || + pattern[0] == '$' || + pattern[0] == '^' || + pattern[0] == '\\' + ) + const isSpecial = true; + else + const isSpecial = false; } --- -

More Template Metaprogramming

+$(H2 $(LNAME2 more-template-metaprogramming, More Template Metaprogramming)) $(OL - $(LI Tomasz Stachowiak's compile time $(LINK2 http://h3.gd/ctrace/, raytracer).) + $(LI Tomasz Stachowiak's compile time $(LINK2 http://h3.gd/ctrace/, raytracer).) - $(LI Don Clugston's compile time $(LINK2 http://www.99-bottles-of-beer.net/language-d-1212.html, 99 Bottles of Beer).) + $(LI Don Clugston's compile time $(LINK2 http://www.99-bottles-of-beer.net/language-d-1212.html, 99 Bottles of Beer).) ) -

References

+$(H2 $(LNAME2 references, References)) - $(P [1] D programming language, - see $(LINK http://www.digitalmars.com/d/) - ) + $(P [1] D programming language, + see $(LINK http://www.digitalmars.com/d/) + ) - $(P [2] Don Clugston's π calculator, see - $(LINK http://trac.dsource.org/projects/ddl/browser/trunk/meta/demo/calcpi.d) - ) + $(P [2] Don Clugston's π calculator, see + $(LINK http://trac.dsource.org/projects/ddl/browser/trunk/meta/demo/calcpi.d) + ) - $(P [3] Don Clugston's decimaldigit and itoa, - see $(LINK http://trac.dsource.org/projects/ddl/browser/trunk/meta/conv.d) - ) + $(P [3] Don Clugston's decimaldigit and itoa, + see $(LINK http://trac.dsource.org/projects/ddl/browser/trunk/meta/conv.d) + ) - $(P [4] Eric Niebler's Boost.Xpressive regular expression template - library is at $(LINK http://boost-sandbox.sourceforge.net/libs/xpressive/doc/html/index.html) - ) + $(P [4] Eric Niebler's Boost.Xpressive regular expression template + library is at $(LINK http://boost-sandbox.sourceforge.net/libs/xpressive/doc/html/index.html) + ) - $(P [5] Eric Anderton's Regular Expression template library - for D is at $(LINK http://trac.dsource.org/projects/ddl/browser/trunk/meta/regex.d) - ) + $(P [5] Eric Anderton's Regular Expression template library + for D is at $(LINK http://trac.dsource.org/projects/ddl/browser/trunk/meta/regex.d) + ) -

Acknowledgements

+$(H2 $(LNAME2 acknowledgments, Acknowledgements)) $(P I gratefully acknowledge the inspiration and assistance @@ -1212,8 +1225,5 @@ of Don Clugston, Eric Anderton and Matthew Wilson. ) Macros: - TITLE=Templates Revisited - WIKI=TemplatesRevisited - CATEGORY_ARTICLES=$0 - - + TITLE=Templates Revisited + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/articles/variadic-function-templates.dd b/articles/variadic-function-templates.dd new file mode 100644 index 0000000000..9dbfe25ba5 --- /dev/null +++ b/articles/variadic-function-templates.dd @@ -0,0 +1,257 @@ +Ddoc + +$(D_S Variadic Templates, + +$(HEADERNAV_TOC) + + $(P The problem statement is simple: write a function that + takes an arbitrary number of values of arbitrary types, + and print those values out one per line in a manner + appropriate to the type. For example, the code: + ) + +---- +print(7, 'a', 6.8); +---- + + $(P should output: + ) + +$(CONSOLE +7 +'a' +6.8 +) + + $(P We'll explore how this can + be done in C++. + Then, we'll do it the various ways the D programming + language makes possible. + ) + +$(H2 $(LNAME2 cpp-solutions, C++ Solutions)) + +$(H3 The Overload Solution) + + $(P The straightforward way to do this in standard C++ + is to use a series of function templates, one for + each number of arguments: + ) + +$(CCODE +#include <iostream> +using namespace::std; + +void print() +{ +} + +template<class T1> void print(T1 a1) +{ + cout << a1 << endl; +} + +template<class T1, class T2> void print(T1 a1, T2 a2) +{ + cout << a1 << endl; + cout << a2 << endl; +} + +template<class T1, class T2, class T3> void print(T1 a1, T2 a2, T3 a3) +{ + cout << a1 << endl; + cout << a2 << endl; + cout << a3 << endl; +} + +... etc ... +) + + $(P This poses significant problems: + ) + + $(P One, the function + implementor must decide in advance what the maximum number + of arguments the function will have. The implementor will + usually err on the side of excess, and ten, or even twenty + overloads of print() will be written. Yet inevitably, some + user somewhere will require just one more argument. + So this solution is never quite thoroughly right. + ) + + $(P Two, the logic of the function template body must be + cut and paste duplicated, then carefully modified, + for every one of those function templates. If the logic + needs to be adjusted, all of those function templates must + receive the same adjustment, which is tedious and error + prone. + ) + + $(P Three, as is typical for function overloads, there is no + obvious visual connection between them, they stand independently. + This makes it more difficult to understand the code, + especially if the implementor isn't careful to place them + and format them in a consistent style. + ) + + $(P Four, it leads to source code bloat which slows down + compilation. + ) + +$(H3 C++ Variadic Templates) + + $(P C++11 supports variadic templates: + ) + +$(CCODE +void print() +{ +} + +template<class T, class... U> void print(T a1, U... an) +{ + cout << a1 << newline; + print(an...); +} +) + + $(P It uses recursive function template instantiation + to pick off the arguments one by one. + A specialization with no arguments ends the recursion. + ) + +$(H2 $(LNAME2 d-solutions, D Programming Language Solutions)) + +$(H3 The D Look Ma No Templates Solution) + + $(P The current best practice, e.g. as espoused by the standard library, favours + the variadic template solution. However, if the template solution is not practical, D provides a runtime solution + utilizing the $(D TypeInfo) system (An example is shown below). There is a lexical similarity with the + non-template variadic functions provided by C and C++ ($(D va_list)), however the solution D provides is + typesafe whereas the aforementioned alternative is not. + ) + +------ +import core.vararg; +import core.stdc.stdio; +/* +This function was part of D1.0, but does not exist anymore, it has been +resurrected here to give a realistic example of how this feature could be used. +*/ +void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr); +void print(...) +{ + void putc(dchar c) + { + fputc(c, stdout); + } + + doFormat(&putc, _arguments, _argptr); +} +------ + +$(H3 Translating the Variadic C++ Solution into D) + + $(P Variadic templates in D enable a straightforward translation + of the C++11 variadic solution: + ) + +--- +void print() +{ +} + +void print(T, A...)(T t, A a) +{ + import std.stdio; + writeln(t); + print(a); +} +--- + + $(P There are two overloads. The first provides the + degenerate case of no arguments, and a terminus for the + recursion of the second. The second has two arguments: + `t` for the first value and `a` for any remaining values. + `A...` says the parameter is a sequence, and + $(GLOSSARY2 ifti, Implicit Function Template Instantiation) + will fill in `A` with all the types of any + arguments supplied following `t`. So, `print(7, 'a', 6.8)` will + fill in `int` for `T`, and a type sequence `(char, double)` for `A`. + The parameter `a` is an lvalue sequence of any + arguments supplied after `t`. See + $(DDLINK articles/ctarguments, Compile-time Sequences, Compile-time Sequences) + for more information. + ) + + $(P The function works by printing the first parameter `t`, + and then recursively calling itself with the remaining arguments + `a`. The recursion terminates when there are no longer any + arguments by calling `print()`. + ) + +$(H3 The Static If Solution) + + $(P It would be nice to encapsulate all the logic into a + single function. One way to do that is by using + $(D static if)s, which provide for conditional compilation: + ) + +--- +void print(A...)(A a) +{ + static if (a.length) + { + writeln(a[0]); + static if (a.length > 1) + print(a[1 .. $]); + } +} +--- + + $(P Sequences can be manipulated much like arrays. + So `a.length` resolves to the number of elements + in the sequence `a`. `a[0]` gives the first element + in the sequence. `a[1 .. $]` creates a new sequence + from any remaining elements in the original sequence. + ) + +$(H3 The Foreach Solution) + + $(P But since sequences can be manipulated like arrays, + we can use a `foreach` statement to iterate over + the sequence's elements: + ) + +--- +void print(A...)(A a) +{ + foreach(t; a) + writeln(t); +} +--- + + $(P The end result is remarkably simple, self-contained, compact + and efficient. + ) + +$(H3 Acknowledgments) + + $(OL + + $(LI Thanks to Andrei Alexandrescu for explaining to me how + variadic templates need to work and why they are so important. + ) + + $(LI Thanks to Douglas Gregor, Jaakko Jaervi, and Gary Powell + for their inspirational work + on C++ variadic templates. + ) + + ) + +) + +Macros: + TITLE=Variadic Templates + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/articles/warnings.dd b/articles/warnings.dd new file mode 100644 index 0000000000..728e7d7e34 --- /dev/null +++ b/articles/warnings.dd @@ -0,0 +1,94 @@ +Ddoc + +$(D_S Warnings, + + $(P Depending on one's point of view, warnings are either a symptom + of broken language design or a useful $(SINGLEQUOTE lint) like tool to analyze + code and look for potential trouble spots. + Most of the time, those trouble spots will be legitimate code + intended to be that way. More rarely, it may indicate an + unintentional error on the part of the programmer. + ) + + $(P Warnings are not a defined part of the D Programming Language. + They exist at the discretion of the compiler vendor, and + will most likely vary from vendor to vendor. + All constructs for which an implementation may generate a warning + message are legal D code. + ) + + $(P These are the warnings generated by the Digital Mars D compiler + when the $(B -w) switch is thrown. This mode also forces compiler + to stop if any warning is produced. + Most have generated some spirited debate as to whether it should + be a warning, an error, and what the correct way to write D code + in these situations should be. Since no consensus emerged, + they appear as optional warnings, with alternatives on how to + write correct code. + ) + + + + + + + + + +$(H3 warning - statement is not reachable) + + $(P Consider the following code:) + +--- +int foo(int i) +{ + return i; + $(B return i + 1;) +} +--- + + $(P The second return statement is not reachable, i.e. it is dead + code. While dead code is poor style in released code, it can + legitimately + happen a lot when rapidly trying to isolate down a bug or experiment + with different bits of code. + ) + + $(P The warning can be resolved by: + ) + + $(OL + $(LI Commenting out the dead code with /+ ... +/ comments: +--- +int foo(int i) +{ + return i; + /+ + return i + 1; + +/ +} +--- + ) + + $(LI Putting the dead code inside a $(D version(none)) conditional: +--- +int foo(int i) +{ + return i; + $(B version (none)) + { + return i + 1; + } +} +--- + ) + + $(LI Only compile with warnings enabled when doing release builds. + ) + ) + +) + +Macros: + TITLE=Warnings + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/ascii-table.dd b/ascii-table.dd index bbb62e78d1..55ce99b3c8 100644 --- a/ascii-table.dd +++ b/ascii-table.dd @@ -2,30 +2,10 @@ Ddoc $(D_S ASCII Table, -$(COMMENT - 00 10 20 30 40 50 60 70 -00 NUL DLE SPC 0 @ P ` p -01 SOH DC1 ! 1 A Q a q -02 STX DC2 " 2 B R b r -03 ETX DC3 # 3 C S c s -04 EOT DC4 $ 4 D T d t -05 ENQ NAK % 5 E U e u -06 ACK SYN & 6 F V f v -07 BEL ETB ' 7 G W g w -08 BS CAN ( 8 H X h x -09 TAB EM ) 9 I Y i y -0A LF SUB * : J Z j z -0B VT ESC + ; K [ k { -0C FF FS , < L \ l | -0D CR GS - = M ] m } -0E SO RS . > N ^ n ~ -0F SI US / ? O _ o DEL -) - -
+$(PRE
       00  10  20  30  40  50  60  70
 
- 00  NUL DLE SPC   0   @   P   `   p
+ 00  NUL DLE SPC   0   @   P   $(BACKTICK)   p
  01  SOH DC1   !   1   A   Q   a   q
  02  STX DC2   "   2   B   R   b   r
  03  ETX DC3   #   3   C   S   c   s
@@ -33,20 +13,17 @@ $(COMMENT
  05  ENQ NAK   %   5   E   U   e   u
  06  ACK SYN   &   6   F   V   f   v
  07  BEL ETB   '   7   G   W   g   w
- 08  BS  CAN   (   8   H   X   h   x
- 09  TAB EM    )   9   I   Y   i   y
+ 08  BS  CAN   $(LPAREN)   8   H   X   h   x
+ 09  TAB EM    $(RPAREN)   9   I   Y   i   y
  0A  LF  SUB   *   :   J   Z   j   z
  0B  VT  ESC   +   ;   K   [   k   {
  0C  FF  FS    ,   <   L   \   l   |
  0D  CR  GS    -   =   M   ]   m   }
  0E  SO  RS    .   >   N   ^   n   ~
  0F  SI  US    /   ?   O   _   o DEL
-
+) ) Macros: - TITLE=ASCII Table - WIKI=AsciiTable - CATEGORY_APPENDICES=$0 - + TITLE=ASCII Table diff --git a/attribute.dd b/attribute.dd deleted file mode 100644 index 0e8e2c20a6..0000000000 --- a/attribute.dd +++ /dev/null @@ -1,523 +0,0 @@ -Ddoc - -$(SPEC_S Attributes, - -$(GRAMMAR -$(GNAME AttributeSpecifier): - $(GLINK Attribute) $(B :) - $(GLINK Attribute) $(GLINK DeclarationBlock) - -$(GNAME Attribute): - $(LINK2 #linkage, $(I LinkageAttribute)) - $(LINK2 #align, $(I AlignAttribute)) - $(GLINK2 pragma, Pragma) - $(LINK2 #deprecated, $(B deprecated)) - $(GLINK ProtectionAttribute) - $(B static) - $(B extern) - $(B final) - $(B synchronized) - $(LINK2 #override, $(B override)) - $(LINK2 #abstract, $(B abstract)) - $(LINK2 #const, $(B const)) - $(LINK2 #auto, $(B auto)) - $(LINK2 #scope, $(B scope)) -$(V2 $(LINK2 #gshared, $(B __gshared)) - $(LINK2 #shared, $(B shared)) - $(LINK2 #immutable, $(B immutable)) - $(LINK2 #inout, $(B inout)) - $(LINK2 #disable, $(B @disable)) -) - -$(GNAME DeclarationBlock): - $(GLINK2 module, DeclDef) - $(B {) $(GLINK2 module, DeclDefs)$(OPT) $(B }) -) - - $(P Attributes are a way to modify one or more declarations. - The general forms are: - ) - ---- -attribute declaration; // affects the declaration - -attribute: // affects all declarations until the end of - // the current scope - declaration; - declaration; - ... - -attribute { // affects all declarations in the block - declaration; - declaration; - ... -} ---- - -

$(LNAME2 linkage, Linkage Attribute)

- -$(GRAMMAR -$(GNAME LinkageAttribute): - $(B extern) $(B $(LPAREN)) $(GLINK LinkageType) $(B $(RPAREN)) - -$(GNAME LinkageType): - $(B C) - $(B C++) - $(B D) - $(B Windows) - $(B Pascal) - $(B System) -) - - $(P D provides an easy way to call C functions and operating - system API functions, as compatibility with both is essential. - The $(I LinkageType) is case sensitive, and is meant to be - extensible by the implementation ($(B they are not keywords)). - $(B C) and $(B D) must be supplied, the others are what - makes sense for the implementation. - $(B C++) is reserved for future use. - $(B System) is the same as $(B Windows) on Windows platforms, - and $(B C) on other platforms. - $(B Implementation Note:) - for Win32 platforms, $(B Windows) and $(B Pascal) should exist. - ) - - $(P C function calling conventions are - specified by: - ) - ---------------- -extern (C): - int foo(); // call foo() with C conventions ---------------- - - $(P D conventions are:) - ---------------- -extern (D): ---------------- - - $(P or:) - ---------------- -extern: ---------------- - - - $(P Windows API conventions are:) - ---------------- -extern (Windows): - void *VirtualAlloc( - void *lpAddress, - uint dwSize, - uint flAllocationType, - uint flProtect - ); ---------------- - -

$(LNAME2 align, Align Attribute)

- -$(GRAMMAR -$(GNAME AlignAttribute): - $(B align) - $(B align) $(B $(LPAREN)) $(GLINK2 lex, IntegerLiteral) $(B $(RPAREN)) -) - - $(P Specifies the alignment of struct members. $(B align) by itself - sets it to the default, which matches the default member alignment - of the companion C compiler. $(I Integer) specifies the alignment - which matches the behavior of the companion C compiler when non-default - alignments are used. - ) - - $(P Matching the behavior of the companion C compiler can have some - surprising results, such as the following for Digital Mars C++: - ) - ---------------- -struct S { - align(4) byte a; // placed at offset 0 - align(4) byte b; // placed at offset 1 -} ---------------- - - $(P $(I AlignAttribute) is meant for C ABI compatiblity, which is not - the same thing as binary compatibility across diverse platforms. - For that, use packed structs: - ) - ---------------- -align (1) struct S { - byte a; // placed at offset 0 - byte[3] filler1; - byte b; // placed at offset 4 - byte[3] filler2; -} ---------------- - - $(P A value of 1 means that no alignment is done; - members are packed together. - ) - - $(P Do not align references or pointers that were allocated - using $(I NewExpression) on boundaries that are not - a multiple of $(D size_t). The garbage collector assumes that pointers - and references to gc allocated objects will be on $(D size_t) - byte boundaries. If they are not, undefined behavior will - result. - ) - - $(P $(I AlignAttribute) is ignored when applied to declarations - that are not struct members. - Whether it applies to class members or not is implementation defined. - ) - - $(P The $(I AlignAttribute) is reset to the default when - entering a struct, union, class, or function scope, and restored - when exiting that scope. - It is not inherited from a base class. - ) - -

$(LNAME2 deprecated, Deprecated Attribute)

- - $(P It is often necessary to deprecate a feature in a library, - yet retain it for backwards compatibility. Such - declarations can be marked as deprecated, which means - that the compiler can be set to produce an error - if any code refers to deprecated - declarations: - ) - ---------------- -deprecated -{ - void oldFoo(); -} ---------------- - - $(P $(B Implementation Note:) The compiler should have a switch - specifying if deprecated declarations should be compiled with - out complaint or not. - ) - - -

Protection Attribute

- -$(GRAMMAR -$(GNAME ProtectionAttribute): - $(B private) - $(B package) - $(B protected) - $(B public) - $(B export) -) - - $(P Protection is an attribute that is one of - $(B private), $(B package), $(B protected), - $(B public) or $(B export). - ) - - $(P Private means that only members of the enclosing class can access - the member, or members and functions in the same module as the - enclosing class. - Private members cannot be overridden. - Private module members are equivalent to $(B static) declarations - in C programs. - ) - - $(P Package extends private so that package members can be accessed - from code in other modules that are in the same package. - This applies to the innermost package only, if a module is in - nested packages. - ) - - $(P Protected means that only members of the enclosing class or any - classes derived from that class, - or members and functions in the same module - as the enclosing class, can access the member. - If accessing a protected instance member through a derived class member - function, - that member can only be accessed for the object instance - which can be implicitly cast to the same type as $(SINGLEQUOTE this). - Protected module members are illegal. - ) - - $(P Public means that any code within the executable can access the member. - ) - - $(P Export means that any code outside the executable can access the - member. Export - is analogous to exporting definitions from a DLL. - ) - -

$(LNAME2 const, Const Attribute)

- - $(P The $(B const) attribute declares constants that can be - evaluated at compile time. For example: - ) - ---------------- -const int foo = 7; - -const { - double bar = foo + 6; -} ---------------- - -$(V1 - $(P A const declaration without an initializer must be initialized - in a constructor (for class fields) or in a static constructor - (for static class members, or module variable declarations). - ) - ---------------- -const int x; -const int y; - -static this() -{ - x = 3; // ok - // error: y not initialized -} - -void foo() -{ - x = 4; // error, x is const and not in static constructor -} - -class C -{ - const int a; - const int b; - static const int c; - static const int d; - - this() { - a = 3; // ok - a = 4; // ok, multiple initialization allowed - C p = this; - p.a = 4; // error, only members of this instance - c = 5; // error, should initialize in static constructor - // error, b is not initialized - } - - this(int x) { - this(); // ok, forwarding constructor - } - - static this() { - c = 3; // ok - // error, d is not initialized - } -} ---------------- - - $(P It is not an error to have const module variable declarations without - initializers if there is no constructor. This is to support the practice - of having modules serve only as declarations that are not linked in, - the implementation of it will be in another module that is linked in. - ) -) - -$(V2 -

$(LNAME2 immutable, immutable Attribute)

- -

$(LNAME2 gshared, __gshared Attribute)

- - $(P By default, non-immutable global declarations reside in thread local - storage. When a global variable is marked with the $(B __gshared) - attribute, its value is shared across all threads.) - ---- -int foo; // Each thread has its own exclusive copy of foo. -__gshared int bar; // bar is shared by all threads. ---- - - $(P $(B __gshared) may also be applied to member variables and local - variables. In these cases, $(B __gshared) is equivalent to $(B static), - except that the variable is shared by all threads rather than being - thread local.) - ---- -class Foo { - __gshared int bar; -} - -int foo() { - __gshared int bar = 0; - return bar++; // Not thread safe. -} ---- - - $(P Unlike the $(B shared) attribute, $(B __gshared) provides no - safe-guards against data races or other multi-threaded synchronization - issues. It is the responsibility of the programmer to ensure that - access to variables marked $(B __gshared) is synchronized correctly.) - - $(P $(B __gshared) is disallowed in safe mode.) - -

$(LNAME2 shared, shared Attribute)

- -

$(LNAME2 inout, inout Attribute)

- -

$(LNAME2 disable, @disable Attribute)

- - $(P A reference to a declaration marked with the $(CODE @disable) attribute causes - a compile time error. - This can be used to explicitly disallow certain operations or overloads - at compile time rather than relying on generating a runtime error. - ) - ---- -struct T { - @disable this(this) { } // disabling this makes T not copyable -} - -struct S { - T t; // uncopyable member makes S also not copyable -} - -@disable void foo() { } - -void main() { - S s; - S t = s; // error, S is not copyable - foo(); // error, foo is disabled -} ---- -) - -

$(LNAME2 override, Override Attribute)

- - $(P The $(B override) attribute applies to virtual functions. - It means that the function must override a function with the - same name and parameters in a base class. The override attribute - is useful for catching errors when a base class's member function - gets its parameters changed, and all derived classes need to have - their overriding functions updated. - ) - ---------------- -class Foo { - int bar(); - int abc(int x); -} - -class Foo2 : Foo { - override { - int bar(char c); // error, no bar(char) in Foo - int abc(int x); // ok - } -} ---------------- - -

Static Attribute

- - $(P The $(B static) attribute applies to functions and data. - It means that the declaration does not apply to a particular - instance of an object, but to the type of the object. In - other words, it means there is no $(B this) reference. - $(B static) is ignored when applied to other declarations. - ) - ---------------- -class Foo { - static int bar() { return 6; } - int foobar() { return 7; } -} - -... - -Foo f = new Foo; -Foo.bar(); // produces 6 -Foo.foobar(); // error, no instance of Foo -f.bar(); // produces 6; -f.foobar(); // produces 7; ---------------- - -$(P - Static functions are never virtual. -) -$(P - Static data has only one instance for the entire program, - not once per object. -) -$(P - Static does not have the additional C meaning of being local - to a file. Use the $(B private) attribute in D to achieve that. - For example: -) - ---------------- -module foo; -int x = 3; // x is global -private int y = 4; // y is local to module foo ---------------- - - -

$(LNAME2 auto, Auto Attribute)

- - $(P The $(B auto) attribute is used when there are no other attributes - and type inference is desired. - ) - ---- -auto i = 6.8; // declare i as a double ---- - -

$(LNAME2 scope, Scope Attribute)

- -$(P - The $(B scope) attribute is used for local variables and for class - declarations. For class declarations, the $(B scope) attribute creates - a $(I scope) class. - For local declarations, $(B scope) implements the RAII (Resource - Acquisition Is Initialization) protocol. This means that the - destructor for an object is automatically called when the - reference to it goes out of scope. The destructor is called even - if the scope is exited via a thrown exception, thus $(B scope) - is used to guarantee cleanup. -) -$(P - If there is more than one $(B scope) variable going out of scope - at the same point, then the destructors are called in the reverse - order that the variables were constructed. -) -$(P - $(B scope) cannot be applied to globals, statics, data members, ref - or out parameters. Arrays of $(B scope)s are not allowed, and $(B scope) - function return values are not allowed. Assignment to a $(B scope), - other than initialization, is not allowed. - $(B Rationale:) These restrictions may get relaxed in the future - if a compelling reason to appears. -) - -

$(LNAME2 abstract, Abstract Attribute)

- -$(P - If a class is abstract, it cannot be instantiated - directly. It can only be instantiated as a base class of - another, non-abstract, class. -) -$(P - Classes become abstract if they are defined within an - abstract attribute, or if any of the virtual member functions - within it are declared as abstract. -) -$(P - Non-virtual functions cannot be declared as abstract. -) -$(P - Functions declared as abstract can still have function - bodies. This is so that even though they must be overridden, - they can still provide $(SINGLEQUOTE base class functionality.) -) - -) - -Macros: - TITLE=Attributes - WIKI=Attribute - CATEGORY_SPEC=$0 - diff --git a/book/README.md b/book/README.md new file mode 100644 index 0000000000..0f8483bc00 --- /dev/null +++ b/book/README.md @@ -0,0 +1,14 @@ +# Ali Cehreli's book + +This is (currently) just the English version of the book. + +To build, run `rdmd build.d`, files will be emitted to `web/book`. + +Of note: The index currently does not work, and thus has been omitted for now. + +``` +CODE_NAME= +CODE_XREF= +CODE_DONT_TEST= +CODE_COMMENT_OUT= +``` diff --git a/book/aliBook.ddoc b/book/aliBook.ddoc new file mode 100644 index 0000000000..857055e936 --- /dev/null +++ b/book/aliBook.ddoc @@ -0,0 +1,218 @@ +ROOT_DIR=../ +DOCTYPE = +CODE_NAME= +CODE_XREF= +CODE_DONT_TEST= +CODE_COMMENT_OUT= +WORK_IN_PROCESS= +COMMENTED_OUT= +new= +Ergin= +P1= $(I $0) +katma= +sablon= +XXX= + +DEL = $0 +TITLE = $(RED $0) +H1 =

$0

+H2 =

$0

+H3 =

$0

+H4 =

$0

+H5 =
$0
+H5_FRONTMATTER =
$0
+H6 =
$0
+SMALL=$0 +HR =
+BR =
+SUP= $0 +SUB= $0 +CENTER =
$0
+MONO =
$0
+MONO_NOBOLD =
$0
+CODE = $0 +CODE_SMALL = $0 +C=$(CODE $0) +CH4=$(C $0) +c=$(CODE_SMALL $0) +INDEX_KEYWORDS=    $(c $0) + +LINK_TARGET=$3 +LINK_DOWNLOAD = $+ + +SHELL =
$0
+SHELL_SMALL = $(SHELL $0) +SHELL_NOTE = ← $0 +SHELL_NOTE_WRONG = ← $0 + +SHELL_OBSERVED= $0 + +C_CODE =
$0
+UL_FARK=
    $0
+UL_CLASS=
    $+
+FARK_INDEX=
  • $(LINK2 #$1, $2)
  • +FARK=$(BR)$(HR)
    $2
    +FARK_C=$(H6 C)$(C_CODE $0) +FARK_CPP=$(H6 C++)$(C_CODE $0) +FARK_D=$(H6 D)$0 + +HEADER_INDEX=$(FARK_INDEX $1, $2) +HEADER=
    $2
    + +STEPS =
      $0
    + +QUOTE =
    $0
    + +RED = $0 +BLUE = $0 +GREEN = $0 +YELLOW = $0 +BLACK = $0 +WHITE = $0 +DARKRED= $0 +ORANGE= $0 +GRAY= $0 +LIGHT_GRAY= $0 +DARK_GRAY= $0 +HILITE= $0 +COLOR= $+ + +STRING = $(CODE $0) +COMMENT = $0 +KEYWORD = $0 + +D_COMMENT = $0 +D_STRING = $0 +D_KEYWORD = $0 +D_PSYMBOL = $0 +D_PARAM = $0 + +UNORDERED_FALSE = $0 +UNORDERED_TRUE = $0 +UNORDERED_NO = $0 +UNORDERED_YES = $0 + +GULEN = $(DARKRED $(B :)o)) +PERCENT = % +PARANTEZ_AC = ( +PARANTEZ_KAPA = ) +VIRGUL = , +DOLAR = $ +BACK_TICK = ` +HYPHEN = ‑ +ASIL = ($0) + +DERLEME_HATASI_METIN=derleme HATASI +DERLEME_HATASI = // ← $(DERLEME_HATASI_METIN) +CODE_NOTE = $(COMMENT // ← $0) +CODE_NOTE_WRONG = $(COMMENT // ← $0) +CODE_COMMENT = $(COMMENT // $0) + +IMG_D = D harfi + +BREADCRUMBS=$(BREADCRUMBS_FULL) + +BREADCRUMBS_DIV=
     $(BREADCRUMBS)
    + +FOOTER_DIV= + +HEADER_SECONDARY_DIV=
    $(HORIZNAV_CONTENT)
    + +VERTINAV_DIV=
    + $(BR) + $(VERTINAV_CONTENT) + $(BR) +
    + +CLASS=chapter +DIV_CLASS=
    $+
    + +HEADER1_ID=header1 + +DERSHANE_LINK2=$(LINK2 $1, $2) + +IMG= + +DERS_BOLUMU = +DERS_BOLUMU_CLASS = +COZUM_BOLUMU = $(H4 $0 Dersi Problem Çözümleri) + +UYARI=
    + UYARI:  $0
    + +TABLE=$+
    +HEAD=$0 +HEAD2=$(ROW $(HEAD $1) $(HEAD $2)) +HEAD3=$(ROW $(HEAD $1) $(HEAD $2) $(HEAD $3)) +HEAD4=$(ROW $(HEAD $1) $(HEAD $2) $(HEAD $3) $(HEAD $4)) +HEAD5=$(ROW $(HEAD $1) $(HEAD $2) $(HEAD $3) $(HEAD $4) $(HEAD $5)) +HEAD6=$(ROW $(HEAD $1) $(HEAD $2) $(HEAD $3) $(HEAD $4) $(HEAD $5) $(HEAD $6)) +ROW2=$(ROW $(DATA $1) $(DATA $2)) +ROW3=$(ROW $(DATA $1) $(DATA $2) $(DATA $3)) +ROW4=$(ROW $(DATA $1) $(DATA $2) $(DATA $3) $(DATA $4)) +ROW5=$(ROW $(DATA $1) $(DATA $2) $(DATA $3) $(DATA $4) $(DATA $5)) +ROW6=$(ROW $(DATA $1) $(DATA $2) $(DATA $3) $(DATA $4) $(DATA $5) $(DATA $6)) +ROW=$0 +DATA=$0 + +ESKI_KARSILASTIRMA=$(P $(CENTER $(HILITE $(I $(B Not:) Bu bir D1 karşılaştırmasıdır. Modern D'nin başka farklılıkları da var.)))) + + +MAIN_TITLE=D.ershane + +SUB_MAIN_TITLE=$(SUB_MAIN_TITLE_DERSE_OZEL) + +HEADER_ID=header_ders + +BREADCRUMBS_ID=breadcrumbs_ders + +CONTAINER_ID=container + +PROBLEM= $(LI $0) + +IX= + +GERI_METIN=Geri +ILERI_METIN=İleri +PROBLEM_METIN=Problem +PROBLEM_COK_METIN=Problemler +PROBLEM_TEK_COZUMSUZ_METIN=çözümü sonra gelecek +PROBLEM_COK_COZUMSUZ_METIN=çözümler sonra gelecek +COZUM_METIN=çözüm +COZUMLER_METIN=çözümler + +PROBLEM_TEK_IMPL=$(H5 $(PROBLEM_METIN)) + $+ $1 + +PROBLEM_TEK=$(PROBLEM_TEK_IMPL $(DIV_CLASS cozum_link_tek, $(P $(LINK_TARGET ddili_cozum, $(COZUM_HTML), $(I ... $(COZUM_METIN))))), $0) +PROBLEM_TEK_COZUMSUZ=$(PROBLEM_TEK_IMPL $(P $(I ($(PROBLEM_TEK_COZUMSUZ_METIN ...)))), $0) + + +PROBLEM_COK_IMPL=$(H5 $(PROBLEM_COK_METIN)) + $(OL $+) $1 + +PROBLEM_COK=$(PROBLEM_COK_IMPL $(DIV_CLASS cozum_link_cok, $(P $(LINK_TARGET ddili_cozum, $(COZUM_HTML), $(I ... $(COZUMLER_METIN))))), $0) + +PROBLEM_COK_COZUMSUZ=$(PROBLEM_COK_IMPL $(P $(I ($(PROBLEM_COK_COZUMSUZ_METIN ...)))), $0) + + +VERTINAV_CONTENT=$(MINI_SOZLUK $(SOZLER)) + $(DUSEY_NAVIGASYON) + +HORIZNAV_CONTENT=$(HORIZNAV_CONTENT_DERSE_OZEL) + +DERS_NAV_BAS=
    + $(DERS_NAV_GERI)   $(DERS_NAV_ILERI) +
    + +DERS_NAV_SON=
    + $(DERS_NAV_GERI)   $(DERS_NAV_ILERI) +
    + +MINI_SOZLUK=
    $0
    + $(I $(LINK_TARGET ddili_sozluk, $(ROOT_DIR)/sozluk.html, ... bütün sözlük)) +$(BR)$(BR) + +DERSHANE_LINK2=$2 + +D_CODE =
    $0
    diff --git a/book/build.d b/book/build.d new file mode 100644 index 0000000000..4a0c38f5b1 --- /dev/null +++ b/book/build.d @@ -0,0 +1,73 @@ +module book.build; +import std.string; +import std.process; +import std.algorithm; +import std.file; +import std.stdio; +import std.exception; +import std.path; + +void compileToPath(string compileThis, string outputPath, string extraFiles, bool loud = false) +{ + import std.compiler; + import core.stdc.stdlib; + string[string] contextMacros; + contextMacros["DVER"] = format!"%u.%03u"(version_major, version_minor); + if(outputPath.indexOf("cozum") == -1) + { + //We need to build a little .ddoc file to set the right predefined build macros - these are context dependant. + + const cozumHtml = outputPath.baseName.replace(".html", ".cozum.html"); + contextMacros["COZUM_HTML"] = cozumHtml; + //exit(0); + } + auto macroOut = File("contextMacros.ddoc", "w"); + scope(exit) + { + import std.file : remove; // conflicts with `core.stdc.stdio.remove` otherwise + remove("contextMacros.ddoc"); + } + + foreach(key, value; contextMacros) + { + macroOut.writefln!"%s = %s"(key, value); + } + macroOut.flush(); + + const compileString = format!"dmd -D contextMacros.ddoc macros.ddoc html.ddoc dlang.org.ddoc doc.ddoc aliBook.ddoc %s %s -Df%s "(extraFiles, compileThis, outputPath); + if(loud) + writefln!"%s:%s |> %s"(compileThis, outputPath, compileString); + const res = executeShell(compileString); + + if(res.status != 0) { + write(res.output); + + exit(0); + } +} +int main(string[] args) +{ + import std.typecons; + import std.path; + import std.parallelism; + import std.conv : to; + const jobs = args.length == 2 ? args[1].to!ubyte : 1; + const outDir = "../web/book"; + writeln("Building the book at ", outDir); + + enforce(executeShell("which dmd").output != "", "dmd doesn't seem to be present"); + if(outDir.exists) { + executeShell("rm -rf " ~ outDir); + } + + const diffable = environment.get("DIFFABLE", "0") == "1"; + const noTimestamp = diffable ? "../nodatetime.ddoc" : ""; + + dirEntries("d.en", "*.d", SpanMode.shallow) + .map!(dFile => tuple(dFile.name, buildPath(outDir, baseName(dFile).setExtension("html")))) + //.parallel(jobs) + .each!(elem => compileToPath(elem.tupleof, noTimestamp)); + dirEntries("d.en", "*.png", SpanMode.shallow) + .each!(p => copy(p, buildPath(outDir, baseName(p).setExtension("png")))); + return 0; +} diff --git a/book/common.ddoc b/book/common.ddoc new file mode 100644 index 0000000000..ca4f127433 --- /dev/null +++ b/book/common.ddoc @@ -0,0 +1,145 @@ + DOCTYPE = + + DEL = $0 + + H1 =

    $0

    + H2 =

    $0

    + H3 =

    $0

    + H4 =

    $0

    + H5 =
    $0
    + H5_FRONTMATTER =
    $0
    + H6 =
    $0
    + SMALL=$0 + HR =
    + BR =
    + SUP= $0 + SUB= $0 + CENTER =
    $0
    + MONO =
    $0
    + MONO_NOBOLD =
    $0
    + CODE = $0 + CODE_SMALL = $0 + C=$(CODE $0) + CH4=$(C $0) + c=$(CODE_SMALL $0) + INDEX_KEYWORDS=    $(c $0) + + LINK_TARGET=$3 + LINK_DOWNLOAD = $+ + + SHELL =
    $0
    + SHELL_SMALL = $(SHELL $0) + SHELL_NOTE = ← $0 + SHELL_NOTE_WRONG = ← $0 + + SHELL_OBSERVED= $0 + + C_CODE =
    $0
    + UL_FARK=
      $0
    + UL_CLASS=
      $+
    + FARK_INDEX=
  • $(LINK2 #$1, $2)
  • + FARK=$(BR)$(HR)
    $2
    + FARK_C=$(H6 C)$(C_CODE $0) + FARK_CPP=$(H6 C++)$(C_CODE $0) + FARK_D=$(H6 D)$0 + + HEADER_INDEX=$(FARK_INDEX $1, $2) + HEADER=
    $2
    + + STEPS =
      $0
    + + QUOTE =
    $0
    + + RED = $0 + BLUE = $0 + GREEN = $0 + YELLOW = $0 + BLACK = $0 + WHITE = $0 + DARKRED= $0 + ORANGE= $0 + GRAY= $0 + LIGHT_GRAY= $0 + DARK_GRAY= $0 + HILITE= $0 + COLOR= $+ + + STRING = $(CODE $0) + COMMENT = $0 + KEYWORD = $0 + + D_COMMENT = $0 + D_STRING = $0 + D_KEYWORD = $0 + D_PSYMBOL = $0 + D_PARAM = $0 + + UNORDERED_FALSE = $0 + UNORDERED_TRUE = $0 + UNORDERED_NO = $0 + UNORDERED_YES = $0 + + GULEN = $(DARKRED $(B :)o)) + PERCENT = % + PARANTEZ_AC = ( + PARANTEZ_KAPA = ) + VIRGUL = , + DOLAR = $ + BACK_TICK = ` + HYPHEN = ‑ + ASIL = ($0) + + DERLEME_HATASI_METIN=derleme HATASI + DERLEME_HATASI = // ← $(DERLEME_HATASI_METIN) + CODE_NOTE = $(COMMENT // ← $0) + CODE_NOTE_WRONG = $(COMMENT // ← $0) + CODE_COMMENT = $(COMMENT // $0) + + IMG_D = D harfi + + BREADCRUMBS=$(BREADCRUMBS_FULL) + + BREADCRUMBS_DIV=
     $(BREADCRUMBS)
    + + FOOTER_DIV= + + HEADER_SECONDARY_DIV=
    $(HORIZNAV_CONTENT)
    + +VERTINAV_DIV=
    + $(BR) + $(VERTINAV_CONTENT) + $(BR) +
    + +CLASS=chapter +DIV_CLASS=
    $+
    + +HEADER1_ID=header1 + +DERSHANE_LINK2=$(LINK2 $1, $2) + +IMG= + +DERS_BOLUMU =

    $0

    +DERS_BOLUMU_CLASS =

    $+

    +COZUM_BOLUMU = $(H4 $0 Dersi Problem Çözümleri) + +UYARI=
    + UYARI:  $0
    + +TABLE=$+
    +HEAD=$0 +HEAD2=$(ROW $(HEAD $1) $(HEAD $2)) +HEAD3=$(ROW $(HEAD $1) $(HEAD $2) $(HEAD $3)) +HEAD4=$(ROW $(HEAD $1) $(HEAD $2) $(HEAD $3) $(HEAD $4)) +HEAD5=$(ROW $(HEAD $1) $(HEAD $2) $(HEAD $3) $(HEAD $4) $(HEAD $5)) +HEAD6=$(ROW $(HEAD $1) $(HEAD $2) $(HEAD $3) $(HEAD $4) $(HEAD $5) $(HEAD $6)) +ROW2=$(ROW $(DATA $1) $(DATA $2)) +ROW3=$(ROW $(DATA $1) $(DATA $2) $(DATA $3)) +ROW4=$(ROW $(DATA $1) $(DATA $2) $(DATA $3) $(DATA $4)) +ROW5=$(ROW $(DATA $1) $(DATA $2) $(DATA $3) $(DATA $4) $(DATA $5)) +ROW6=$(ROW $(DATA $1) $(DATA $2) $(DATA $3) $(DATA $4) $(DATA $5) $(DATA $6)) +ROW=$0 +DATA=$0 + +ESKI_KARSILASTIRMA=$(P $(CENTER $(HILITE $(I $(B Not:) Bu bir D1 karşılaştırmasıdır. Modern D'nin başka farklılıkları da var.)))) diff --git a/book/d.en/404.d b/book/d.en/404.d new file mode 100644 index 0000000000..4f422de8c1 --- /dev/null +++ b/book/d.en/404.d @@ -0,0 +1,17 @@ +Ddoc + +$(DIV class="center-children", +$(D_S $(TITLE), + +$(HTMLTAG3 img, src="https://github.com/$(STATIC%20images/dman-scared.jpg)") + +$(P +If you think there should be something here, please $(LINK2 $(BUGZILLA_NEW_BUG_URL)$(AMP)label=Severity:normal, report a bug). +))) +$(RED Some text here) +Macros: + TITLE=Oh No! Page Not Found + EXTRA_HEADERS=$(T style, + .center-children, h1 { text-align: center; } + img { max-width: 100%; } + ) diff --git a/book/d.en/Makefile.in b/book/d.en/Makefile.in new file mode 100644 index 0000000000..068a559125 --- /dev/null +++ b/book/d.en/Makefile.in @@ -0,0 +1,151 @@ +DERS_SON_D=to_be_continued.d + +# Taken out for the draft release +# foreword1.d \ + +DERS_D_BOLUMLER= \ + foreword2.d \ + preface.d \ + hello_world.d \ + writeln.d \ + compiler.d \ + types.d \ + assignment.d \ + variables.d \ + io.d \ + input.d \ + logical_expressions.d \ + if.d \ + while.d \ + arithmetic.d \ + floating_point.d \ + arrays.d \ + characters.d \ + slices.d \ + strings.d \ + stream_redirect.d \ + files.d \ + auto_and_typeof.d \ + name_space.d \ + for.d \ + ternary.d \ + literals.d \ + formatted_output.d \ + formatted_input.d \ + do_while.d \ + aa.d \ + foreach.d \ + switch_case.d \ + enum.d \ + functions.d \ + const_and_immutable.d \ + value_vs_reference.d \ + function_parameters.d \ + lvalue_rvalue.d \ + lazy_operators.d \ + main.d \ + exceptions.d \ + scope.d \ + assert.d \ + unit_testing.d \ + contracts.d \ + lifetimes.d \ + null_is.d \ + cast.d \ + struct.d \ + parameter_flexibility.d \ + function_overloading.d \ + member_functions.d \ + const_member_functions.d \ + special_functions.d \ + operator_overloading.d \ + class.d \ + inheritance.d \ + object.d \ + interface.d \ + destroy.d \ + modules.d \ + encapsulation.d \ + ufcs.d \ + property.d \ + invariant.d \ + templates.d \ + pragma.d \ + alias.d \ + alias_this.d \ + pointers.d \ + bit_operations.d \ + cond_comp.d \ + is_expr.d \ + lambda.d \ + foreach_opapply.d \ + nested.d \ + union.d \ + goto.d \ + tuples.d \ + templates_more.d \ + functions_more.d \ + mixin.d \ + ranges.d \ + ranges_more.d \ + static_foreach.d \ + parallelism.d \ + concurrency.d \ + concurrency_shared.d \ + fibers.d \ + memory.d \ + uda.d \ + operator_precedence.d \ + +DERS_D_KAYNAK= \ + index.d \ + $(DERS_D_BOLUMLER) \ + +COZUM_D_KAYNAK= \ + hello_world.cozum.d \ + writeln.cozum.d \ + types.cozum.d \ + assignment.cozum.d \ + variables.cozum.d \ + io.cozum.d \ + input.cozum.d \ + logical_expressions.cozum.d \ + if.cozum.d \ + while.cozum.d \ + arithmetic.cozum.d \ + floating_point.cozum.d \ + arrays.cozum.d \ + slices.cozum.d \ + strings.cozum.d \ + stream_redirect.cozum.d \ + files.cozum.d \ + auto_and_typeof.cozum.d \ + for.cozum.d \ + ternary.cozum.d \ + literals.cozum.d \ + formatted_output.cozum.d \ + formatted_input.cozum.d \ + do_while.cozum.d \ + aa.cozum.d \ + foreach.cozum.d \ + switch_case.cozum.d \ + enum.cozum.d \ + functions.cozum.d \ + function_parameters.cozum.d \ + main.cozum.d \ + assert.cozum.d \ + unit_testing.cozum.d \ + contracts.cozum.d \ + struct.cozum.d \ + parameter_flexibility.cozum.d \ + function_overloading.cozum.d \ + member_functions.cozum.d \ + operator_overloading.cozum.d \ + inheritance.cozum.d \ + object.cozum.d \ + pointers.cozum.d \ + bit_operations.cozum.d \ + foreach_opapply.cozum.d \ + +include Makefile.ders.in +$(eval $(call derse_ozel,d.en,Programming_in_D,english)) diff --git a/book/d.en/aa.cozum.d b/book/d.en/aa.cozum.d new file mode 100644 index 0000000000..38ed04e7da --- /dev/null +++ b/book/d.en/aa.cozum.d @@ -0,0 +1,117 @@ +Ddoc + +$(COZUM_BOLUMU Associative Arrays) + +$(OL + +$(LI + +$(UL + +$(LI +The $(C .keys) property returns a slice (i.e. dynamic array) that includes all of the keys of the associative array. Iterating over this slice and removing the element for each key by calling $(C .remove) would result in an empty associative array: + +--- +import std.stdio; + +void main() { + string[int] names = + [ + 1 : "one", + 10 : "ten", + 100 : "hundred", + ]; + + writeln("Initial length: ", names.length); + + int[] keys = names.keys; + + /* 'foreach' is similar but superior to 'for'. We will + * see the 'foreach' loop in the next chapter. */ + foreach (key; keys) { + writefln("Removing the element %s", key); + names.remove(key); + } + + writeln("Final length: ", names.length); +} +--- + +$(P +That solution may be slow especially for large arrays. The following methods would empty the array in a single step. +) + +) + +$(LI +Another solution is to assign an empty array: + +--- + string[int] emptyAA; + names = emptyAA; +--- + +) + +$(LI +Since the initial value of an array is an empty array anyway, the following technique would achieve the same result: + +--- + names = names.init; +--- + +) + +) + +) + +$(LI +The goal is to store multiple grades per student. Since multiple grades can be stored in a dynamic array, an associative array that maps from $(C string) to $(C int[]) would work here. The grades can be appended to the dynamic arrays that are stored in the associative array: + +--- +import std.stdio; + +void main() { + /* The key type of this associative array is string and + * the value type is int[], i.e. an array of ints. The + * associative array is being defined with an extra + * space in between to help distinguish the value type: */ + int[] [string] grades; + + /* The array of ints that correspond to "emre" is being + * used for appending the new grade to that array: */ + grades["emre"] ~= 90; + grades["emre"] ~= 85; + + /* Printing the grades of "emre": */ + writeln(grades["emre"]); +} +--- + +$(P +The grades can also be assigned in one go with an array literal: +) + +--- +import std.stdio; + +void main() { + int[][string] grades; + + grades["emre"] = [ 90, 85, 95 ]; + + writeln(grades["emre"]); +} +--- + +) + +) + +Macros: + TITLE=Associative Arrays Solutions + + DESCRIPTION=Programming in D exercise solutions: Associative Arrays + + KEYWORDS=programming in d tutorial associative arrays diff --git a/book/d.en/aa.d b/book/d.en/aa.d new file mode 100644 index 0000000000..159da81562 --- /dev/null +++ b/book/d.en/aa.d @@ -0,0 +1,323 @@ +Ddoc + +$(DERS_BOLUMU $(IX associative array) $(IX AA) Associative Arrays) + +$(P +Associative arrays are a feature that is found in most modern high-level languages. They are very fast data structures that work like mini databases and are used in many programs. +) + +$(P +We saw in the $(LINK2 arrays.html, Arrays chapter) that plain arrays are containers that store their elements side-by-side and provide access to them by index. An array that stores the names of the days of the week can be defined like this: +) + +--- + string[] dayNames = + [ "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", "Sunday" ]; +--- + +$(P +The name of a specific day can be accessed by its index in that array: +) + +--- + writeln(dayNames[1]); // prints "Tuesday" +--- + +$(P +The fact that plain arrays provide access to their values through index numbers can be described as an $(I association) of indexes with values. In other words, arrays map indexes to values. Plain arrays can use only integers as indexes. +) + +$(P +Associative arrays allow indexing not only using integers but also using any other type. They map the values of one type to the values of another type. The values of the type that associative arrays $(I map from) are called $(I keys), rather than indexes. Associative arrays store their elements as key-value pairs. +) + +$(P +Associative arrays are implemented in D using a $(I hash table). Hash tables are among the fastest collections for storing and accessing elements. Other than in rare pathological cases, the time it takes to store or access an element is independent of the number of elements that are in the associative array. +) + +$(P +The high performance of hash tables comes at the expense of storing the elements in an unordered way. Also, unlike arrays, the elements of hash tables are not stored side-by-side. +) + +$(P +For plain arrays, index values are not stored at all. Because array elements are stored side-by-side in memory, index values are implicitly the relative positions of elements from the beginning of the array. +) + +$(P +On the other hand, associative arrays do store both the keys and the values of elements. Although this difference makes associative arrays use more memory, it also allows them to use $(I sparse) key values. For example, when there are just two elements to store for keys 0 and 999, an associative array stores just two elements, not 1000 as a plain array has to. +) + +$(H5 Definition) + +$(P +The syntax of associative arrays is similar to the array syntax. The difference is that it is the type of the key that is specified within the square brackets, not the length of the array: +) + +--- + $(I value_type)[$(I key_type)] $(I associative_array_name); +--- + +$(P +For example, an associative array that maps day names of type $(C string) to day numbers of type $(C int) can be defined like this: +) + +--- + int[string] dayNumbers; +--- + +$(P +The $(C dayNumbers) variable above is an associative array that can be used as a table that provides a mapping from day names to day numbers. In other words, it can be used as the opposite of the $(C dayNames) array at the beginning of this chapter. We will use the $(C dayNumbers) associative array in the examples below. +) + +$(P +The keys of associative arrays can be of any type, including user-defined $(C struct) and $(C class) types. We will see user-defined types in later chapters. +) + +$(P +The length of associative arrays cannot be specified when defined. They grow automatically as key-value pairs are added. +) + +$(P +$(I $(B Note:) An associative array that is defined without any element is $(LINK2 null_is.html, $(C null)), not empty. This distinction has an important consequence when $(LINK2 function_parameters.html, passing associative arrays to functions). We will cover these concepts in later chapters.) +) + +$(H5 Adding key-value pairs) + +$(P +Using the assignment operator is sufficient to build the association between a key and a value: +) + +--- + // associates value 0 with key "Monday" + dayNumbers["Monday"] $(HILITE =) 0; + + // associates value 1 with key "Tuesday" + dayNumbers["Tuesday"] $(HILITE =) 1; +--- + +$(P +The table grows automatically with each association. For example, $(C dayNumbers) would have two key-value pairs after the operations above. This can be demonstrated by printing the entire table: +) + +--- + writeln(dayNumbers); +--- + +$(P +The output indicates that the values 0 and 1 correspond to keys "Monday" and "Tuesday", respectively: +) + +$(SHELL +["Monday":0, "Tuesday":1] +) + +$(P +There can be only one value per key. For that reason, when we assign a new key-value pair and the key already exists, the table does not grow; instead, the value of the existing key changes: +) + +--- + dayNumbers["Tuesday"] = 222; + writeln(dayNumbers); +--- + +$(P +The output: +) + +$(SHELL +["Monday":0, "Tuesday":222] +) + + +$(H5 Initialization) + +$(P +$(IX :, associative array) Sometimes some of the mappings between the keys and the values are already known at the time of the definition of the associative array. Associative arrays are initialized similarly to regular arrays, using a colon to separate each key from its respective value: +) + +--- + // key : value + int[string] dayNumbers = + [ "Monday" : 0, "Tuesday" : 1, "Wednesday" : 2, + "Thursday" : 3, "Friday" : 4, "Saturday" : 5, + "Sunday" : 6 ]; + + writeln(dayNumbers["Tuesday"]); // prints 1 +--- + +$(H5 Removing key-value pairs) + +$(P +Key-value pairs can be removed by using $(C .remove()): +) + +--- + dayNumbers.remove("Tuesday"); + writeln(dayNumbers["Tuesday"]); // ← run-time ERROR +--- + +$(P +The first line above removes the key-value pair "Tuesday" / $(C 1). Since that key is not in the container anymore, the second line would cause an exception to be thrown and the program to be terminated if that exception is not caught. We will see exceptions in $(LINK2 exceptions.html, a later chapter). +) + +$(P +$(C .clear) removes all elements: +) + +--- + dayNumbers.clear; // The associative array becomes empty +--- + +$(H5 $(IX in, associative array) Determining the presence of a key) + +$(P +The $(C in) operator determines whether a given key exists in the associative array: +) + +--- + int[string] colorCodes = [ /* ... */ ]; + + if ("purple" $(HILITE in) colorCodes) { + // key "purple" exists in the table + + } else { + // key "purple" does not exist in the table + } +--- + +$(P +Sometimes it makes sense to use a default value if a key does not exist in the associative array. For example, the special value of -1 can be used as the code for colors that are not in $(C colorCodes). $(C .get()) is useful in such cases: it returns the value associated with the specified key if that key exists, otherwise it returns the default value. The default value is specified as the second parameter of $(C .get()): +) + +--- + int[string] colorCodes = [ "blue" : 10, "green" : 20 ]; + writeln(colorCodes.get("purple", $(HILITE -1))); +--- + +$(P +Since the array does not contain a value for the key $(STRING "purple"), $(C .get()) returns -1: +) + +$(SHELL +-1 +) + +$(H5 Properties) + +$(UL + +$(LI $(IX .length) $(C .length) returns the number of key-value pairs.) + +$(LI $(IX .keys) $(C .keys) returns a copy of all keys as a dynamic array.) + +$(LI $(IX .byKey) $(C .byKey) provides access to the keys without copying them; we will see how $(C .byKey) is used in $(C foreach) loops in the next chapter.) + +$(LI $(IX .values) $(C .values) returns a copy of all values as a dynamic array.) + +$(LI $(IX .byValue) $(C .byValue) provides access to the values without copying them.) + +$(LI $(IX .byKeyValue) $(C .byKeyValue) provides access to the key-value pairs without copying them.) + +$(LI $(IX .rehash) $(C .rehash) may make the array more efficient in some cases, such as after inserting a large number of key-value pairs.) + +$(LI $(IX .sizeof, associative array) $(C .sizeof) is the size of the array $(I reference) (it has nothing to do with the number of key-value pairs in the table and is the same value for all associative arrays).) + +$(LI $(IX .get) $(C .get) returns the value if it exists, the default value otherwise.) + +$(LI $(IX .remove, associative array) $(C .remove) removes the specified key and its value from the array.) + +$(LI $(IX .clear) $(C .clear) removes all elements.) + +) + +$(H5 Example) + +$(P +Here is a program that prints the Turkish names of colors that are specified in English: +) + +--- +import std.stdio; +import std.string; + +void main() { + string[string] colors = [ "black" : "siyah", + "white" : "beyaz", + "red" : "kırmızı", + "green" : "yeşil", + "blue" : "mavi" ]; + + writefln("I know the Turkish names of these %s colors: %s", + colors.length, colors.keys); + + write("Please ask me one: "); + string inEnglish = strip(readln()); + + if (inEnglish in colors) { + writefln("\"%s\" is \"%s\" in Turkish.", + inEnglish, colors[inEnglish]); + + } else { + writeln("I don't know that one."); + } +} +--- + +$(PROBLEM_COK + +$(PROBLEM +How can all of the key-value pairs of an associative array be removed other than calling $(C .clear)? ($(C .clear) is the most natural method.) There are at least three methods: + +$(UL + +$(LI Removing them one-by-one from the associative array.) + +$(LI Assigning an empty associative array.) + +$(LI Similar to the previous method, assigning the array's $(C .init) property. + +$(P +$(IX .init, clearing a variable) $(I $(B Note:) The $(C .init) property of any variable or type is the initial value of that type:) +) + +--- + number = int.init; // 0 for int +--- +) + +) + +) + +$(PROBLEM +Just like with arrays, there can be only one value for each key. This may be seen as a limitation for some applications. + +$(P +Assume that an associative array is used for storing student grades. For example, let's assume that the grades 90, 85, 95, etc. are to be stored for the student named "emre". +) + +$(P +Associative arrays make it easy to access the grades by the name of the student as in $(C grades["emre"]). However, the grades cannot be inserted as in the following code because each grade would overwrite the previous one: +) + +--- + int[string] grades; + grades["emre"] = 90; + grades["emre"] = 85; // ← Overwrites the previous grade! +--- + +$(P +How can you solve this problem? Define an associative array that can store multiple grades per student. +) + +) + +) + +Macros: + TITLE=Associative Arrays + + DESCRIPTION=The associative arrays of the d programming language. + + KEYWORDS=d programming language tutorial book associative arrays diff --git a/book/d.en/alias.d b/book/d.en/alias.d new file mode 100644 index 0000000000..56a39acadf --- /dev/null +++ b/book/d.en/alias.d @@ -0,0 +1,447 @@ +Ddoc + +$(DERS_BOLUMU $(IX Alias) $(CH4 alias) and $(CH4 with)) + +$(H5 $(C alias)) + +$(P +The $(C alias) keyword assigns aliases to existing names. $(C alias) is different from and unrelated to $(C alias this). +) + +$(H6 Shortening a long name) + +$(P +As we have encountered in the previous chapter, some names may become too long to be convenient. Let's consider the following function from that chapter: +) + +--- +Stack!(Point!double) randomPoints(size_t count) { + auto points = new Stack!(Point!double); + // ... +} +--- + +$(P +Having to type $(C Stack!(Point!double)) explicitly in multiple places in the program has a number of drawbacks: +) + +$(UL +$(LI +Longer names can make the code harder to read. +) + +$(LI +It is unnecessary to be reminded at every point that the type is the $(C Stack) data structure that contains objects of the $(C double) instantiations of the $(C Point) struct template. +) + +$(LI +If the requirements of the program change and e.g. $(C double) needs to be changed to $(C real), this change must be carried out in multiple places. +) + +) + +$(P +These drawbacks can be eliminated by giving a new name to $(C Stack!(Point!double)): +) + +--- +alias $(HILITE Points) = Stack!(Point!double); + +// ... + +$(HILITE Points) randomPoints(size_t count) { + auto points = new $(HILITE Points); + // ... +} +--- + +$(P +It may make sense to go further and define two aliases, one taking advantage of the other: +) + +--- +alias PrecisePoint = Point!double; +alias Points = Stack!PrecisePoint; +--- + +$(P +The syntax of $(C alias) is the following: +) + +--- + alias $(I new_name) = $(I existing_name); +--- + +$(P +After that definition, the new name and the existing name become synonymous: They mean the same thing in the program. +) + +$(P +You may encounter the older syntax of this feature in some programs: +) + +$(MONO + // Use of old syntax is discouraged: + alias $(I existing_name) $(I new_name); +) + +$(P +$(C alias) is also useful when shortening names which otherwise need to be spelled out along with their module names. Let's assume that the name $(C Queen) appears in two separate modules: $(C chess) and $(C palace). When both modules are imported, typing merely $(C Queen) would cause a compilation error: +) + +--- +import chess; +import palace; + +// ... + + Queen person; $(DERLEME_HATASI) +--- + +$(P +The compiler cannot decide which $(C Queen) has been meant: +) + +$(SHELL_SMALL +Error: $(HILITE chess.Queen) at chess.d(1) conflicts with +$(HILITE palace.Queen) at palace.d(1) +) + +$(P +A convenient way of resolving this conflict is to assign aliases to one or more of the names: +) + +--- +import palace; + +alias $(HILITE PalaceQueen) = palace.Queen; + +void main() { + $(HILITE PalaceQueen) person; + // ... + $(HILITE PalaceQueen) anotherPerson; +} +--- + +$(P +$(C alias) works with other names as well. The following code gives a new name to a variable: +) + +--- + int variableWithALongName = 42; + + alias var = variableWithALongName; + var = 43; + + assert(variableWithALongName == 43); +--- + +$(H6 Design flexibility) + +$(P +For flexibility, even fundamental types like $(C int) can have aliases: +) + +--- +alias CustomerNumber = int; +alias CompanyName = string; +// ... + +struct Customer { + CustomerNumber number; + CompanyName company; + // ... +} +--- + +$(P +If the users of this struct always type $(C CustomerNumber) and $(C CompanyName) instead of $(C int) and $(C string), then the design can be changed in the future to some extent, without affecting user code. +) + +$(P +This helps with the readability of code as well. Having the type of a variable as $(C CustomerNumber) conveys more information about the meaning of that variable than $(C int). +) + +$(P +Sometimes such type aliases are defined inside structs and classes and become parts of the interfaces of those types. The following class has a $(C weight) property: +) + +--- +class Box { +private: + + double weight_; + +public: + + double weight() const { + return weight_; + } + // ... +} +--- + +$(P +Because the member variable and the property of that class is defined as $(C double), the users would have to use $(C double) as well: +) + +--- + $(HILITE double) totalWeight = 0; + + foreach (box; boxes) { + totalWeight += box.weight; + } +--- + +$(P +Let's compare it to another design where the type of $(C weight) is defined as an $(C alias): +) + +--- +class Box { +private: + + $(HILITE Weight) weight_; + +public: + + alias $(HILITE Weight) = double; + + $(HILITE Weight) weight() const { + return weight_; + } + // ... +} +--- + +$(P +Now the user code would normally use $(C Weight) as well: +) + +--- + $(HILITE Box.Weight) totalWeight = 0; + + foreach (box; boxes) { + totalWeight += box.weight; + } +--- + +$(P +With this design, changing the actual type of $(C Weight) in the future would not affect user code. (That is, if the new type supports the $(C +=) operator as well.) +) + +$(H6 $(IX name hiding) $(IX hiding, name) Revealing hidden names of superclasses) + +$(P +When the same name appears both in the superclass and in the subclass, the matching names that are in the superclass are hidden. Even a single name in the subclass is sufficient to hide all of the names of the superclass that match that name: +) + +--- +class Super { + void foo(int x) { + // ... + } +} + +class Sub : Super { + void foo() { + // ... + } +} + +void main() { + auto object = new Sub; + object.foo(42); $(DERLEME_HATASI) +} +--- + +$(P +Since the argument is 42, an $(C int) value, one might expect that the $(C Super.foo) function that takes an $(C int) would be called for that use. However, even though their parameter lists are different, $(C Sub.foo) $(I hides) $(C Super.foo) and causes a compilation error. The compiler disregards $(C Super.foo) altogether and reports that $(C Sub.foo) cannot be called by an $(C int): +) + +$(SHELL_SMALL +Error: function $(HILITE deneme.Sub.foo ()) is not callable +using argument types $(HILITE (int)) +) + +$(P + Note that this is not the same as overriding a function of the superclass. For that, the function signatures would be the same and the function would be overridden by the $(C override) keyword. (The $(C override) keyword has been explained in $(LINK2 inheritance.html, the Inheritance chapter).) +) + +$(P +Here, not overriding, but a language feature called $(I name hiding) is in effect. If there were not name hiding, functions that happen to have the same name $(C foo) that are added to or removed from these classes might silently change the function that would get called. Name hiding prevents such surprises. It is a feature of other OOP languages as well. +) + +$(P +$(C alias) can reveal the hidden names when desired: +) + +--- +class Super { + void foo(int x) { + // ... + } +} + +class Sub : Super { + void foo() { + // ... + } + + alias $(HILITE foo) = Super.foo; +} +--- + +$(P +The $(C alias) above brings the $(C foo) names from the superclass into the subclass interface. As a result, the code now compiles and $(C Super.foo) gets called. +) + +$(P +When it is more appropriate, it is possible to bring the names under a different name as well: +) + +--- +class Super { + void foo(int x) { + // ... + } +} + +class Sub : Super { + void foo() { + // ... + } + + alias $(HILITE generalFoo) = Super.foo; +} + +// ... + +void main() { + auto object = new Sub; + object.$(HILITE generalFoo)(42); +} +--- + +$(P +Name hiding affects member variables as well. $(C alias) can bring those names to the subclass interface as well: +) + +--- +class Super { + int city; +} + +class Sub : Super { + string city() const { + return "Kayseri"; + } +} +--- + +$(P +Regardless of one being a member variable and the other a member function, the name $(C city) of the subclass hides the name $(C city) of the superclass: +) + +--- +void main() { + auto object = new Sub; + object.city = 42; $(DERLEME_HATASI) +} +--- + +$(P +Similarly, the names of the member variables of the superclass can be brought to the subclass interface by $(C alias), possibly under a different name: +) + +--- +class Super { + int city; +} + +class Sub : Super { + string city() const { + return "Kayseri"; + } + + alias $(HILITE cityCode) = Super.city; +} + +void main() { + auto object = new Sub; + object.$(HILITE cityCode) = 42; +} +--- + +$(H5 $(IX with) $(C with)) + +$(P +$(C with) is for removing repeated references to an object or symbol. It takes an expression or a symbol in parentheses and uses that expression or symbol when looking up other symbols that are used inside the scope of $(C with): +) + +--- +struct S { + int i; + int j; +} + +void main() { + auto s = S(); + + with ($(HILITE s)) { + $(HILITE i) = 1; // means s.i + $(HILITE j) = 2; // means s.j + } +} +--- + +$(P +It is possible to create a temporary object inside the parentheses. In that case, the temporary object becomes $(LINK2 lvalue_rvalue.html, an lvalue), lifetime of which ends upon leaving the scope: +) + +--- + with (S()) { + i = 1; // the i member of the temporary object + j = 2; // the j member of the temporary object + } +--- + +$(P +As we will see later in $(LINK2 pointers.html, the Pointers chapter), it is possible to construct the temporary object with the $(C new) keyword, in which case its lifetime can be extended beyond the scope. +) + +$(P +$(C with) is especially useful with $(C case) sections for removing repeated references to e.g. an $(C enum) type: +) + +--- +enum Color { red, orange } + +// ... + + final switch (c) $(HILITE with (Color)) { + + case red: // means Color.red + // ... + + case orange: // means Color.orange + // ... + } +--- + +$(H5 Summary) + +$(UL + +$(LI $(C alias) assigns aliases to existing names.) + +$(LI $(C with) removes repeated references to the same object or symbol.) + +) + +Macros: + SUBTITLE=alias + + DESCRIPTION=The alias keyword that enables giving new names to existing names. + + KEYWORDS=d programming lesson book tutorial encapsulation diff --git a/book/d.en/alias_this.d b/book/d.en/alias_this.d new file mode 100644 index 0000000000..5f8d577e02 --- /dev/null +++ b/book/d.en/alias_this.d @@ -0,0 +1,76 @@ +Ddoc + +$(DERS_BOLUMU $(IX alias this) $(CH4 alias this)) + +$(P +We have seen the individual meanings of the $(C alias) and the $(C this) keywords in previous chapters. These two keywords have a completely different meaning when used together as $(C alias this). +) + +$(P +$(IX automatic type conversion) $(IX type conversion, automatic) $(IX implicit type conversion) $(IX type conversion, implicit) $(C alias this) enables $(I automatic type conversions) (also known as $(I implicit type conversions)) of user-defined types. As we have seen in $(LINK2 operator_overloading.html, the Operator Overloading chapter), another way of providing type conversions for a type is by defining $(C opCast) for that type. The difference is that, while $(C opCast) is for explicit type conversions, $(C alias this) is for automatic type conversions. +) + +$(P +The keywords $(C alias) and $(C this) are written separately where the name of a member variable or a member function is specified between them: +) + +--- + alias $(I member_variable_or_member_function) this; +--- + +$(P +$(C alias this) enables the specific conversion from the user-defined type to the type of that member. The value of the member becomes the resulting value of the conversion . +) + +$(P +The following $(C Fraction) example uses $(C alias this) with a $(I member function). The $(C TeachingAssistant) example that is further below will use it with $(I member variables). +) + +$(P +Since the return type of $(C value()) below is $(C double), the following $(C alias this) enables automatic conversion of $(C Fraction) objects to $(C double) values: +) + +--- +import std.stdio; + +struct Fraction { + long numerator; + long denominator; + + $(HILITE double value()) const { + return double(numerator) / denominator; + } + + alias $(HILITE value) this; + + // ... +} + +double calculate(double lhs, double rhs) { + return 2 * lhs + rhs; +} + +void main() { + auto fraction = Fraction(1, 4); // meaning 1/4 + writeln(calculate($(HILITE fraction), 0.75)); +} +--- + +$(P +$(C value()) gets called automatically to produce a $(C double) value when $(C Fraction) objects appear in places where a $(C double) value is expected. That is why the variable $(C fraction) can be passed to $(C calculate()) as an argument. $(C value()) returns 0.25 as the value of 1/4 and the program prints the result of 2 * 0.25 + 0.75: +) + +$(SHELL +1.25 +) + +Macros: + TITLE=alias this + + DESCRIPTION=Nesnelerin otomatik olarak başka tür olarak kullanılmalarını sağlayan 'alias this'. + + KEYWORDS=d programlama dili ders dersler öğrenmek tutorial alias takma isim alias this + +SOZLER= +$(kalitim) + diff --git a/book/d.en/arithmetic.cozum.d b/book/d.en/arithmetic.cozum.d new file mode 100644 index 0000000000..120a9a03d7 --- /dev/null +++ b/book/d.en/arithmetic.cozum.d @@ -0,0 +1,160 @@ +Ddoc + +$(COZUM_BOLUMU Integers and Arithmetic Operations) + +$(OL + +$(LI +We can use the $(C /) operator for the division and the $(C %) operator for the remainder: + +--- +import std.stdio; + +void main() { + int first; + write("Please enter the first number: "); + readf(" %s", &first); + + int second; + write("Please enter the second number: "); + readf(" %s", &second); + + int quotient = first / second; + int remainder = first % second; + + writeln(first, " = ", + second, " * ", quotient, " + ", remainder); +} +--- + +) + +$(LI +We can determine whether the remainder is 0 or not with an $(C if) statement: + +--- +import std.stdio; + +void main() { + int first; + write("Please enter the first number: "); + readf(" %s", &first); + + int second; + write("Please enter the second number: "); + readf(" %s", &second); + + int quotient = first / second; + int remainder = first % second; + + // We cannot call writeln up front before determining + // whether the remainder is 0 or not. We must terminate + // the line later with a writeln. + write(first, " = ", second, " * ", quotient); + + // The remainder must be printed only if nonzero. + if (remainder != 0) { + write(" + ", remainder); + } + + // We are now ready to terminate the line. + writeln(); +} +--- + +) + +$(LI + +--- +import std.stdio; + +void main() { + while (true) { + write("0: Exit, 1: Add, 2: Subtract, 3: Multiply,", + " 4: Divide - Please enter the operation: "); + + int operation; + readf(" %s", &operation); + + // Let's first validate the operation + if ((operation < 0) || (operation > 4)) { + writeln("I don't know this operation"); + continue; + } + + if (operation == 0){ + writeln("Goodbye!"); + break; + } + + // If we are here, we know that we are dealing with + // one of the four operations. Now is the time to read + // two integers from the user: + + int first; + int second; + + write(" First number: "); + readf(" %s", &first); + + write("Second number: "); + readf(" %s", &second); + + int result; + + if (operation == 1) { + result = first + second; + + } else if (operation == 2) { + result = first - second; + + } else if (operation == 3) { + result = first * second; + + } else if (operation == 4) { + result = first / second; + + } else { + writeln( + "There is an error! ", + "This condition should have never occurred."); + break; + } + + writeln(" Result: ", result); + } +} +--- + +) + +$(LI + +--- +import std.stdio; + +void main() { + int value = 1; + + while (value <= 10) { + if (value != 7) { + writeln(value); + } + + ++value; + } +} +--- + +) + +) +$(Ergin) + +Macros: + TITLE=Integers and Arithmetic Operations Solutions + + DESCRIPTION=Programming in D exercise solutions: integers and arithmetic operations + + KEYWORDS=programming in d tutorial arithmetic operations diff --git a/book/d.en/arithmetic.d b/book/d.en/arithmetic.d new file mode 100644 index 0000000000..76d3f5ea58 --- /dev/null +++ b/book/d.en/arithmetic.d @@ -0,0 +1,883 @@ +Ddoc + +$(DERS_BOLUMU $(IX arithmetic operation) Integers and Arithmetic Operations) + +$(P +We have seen that the $(C if) and $(C while) statements allow programs to make decisions by using the $(C bool) type in the form of logical expressions. In this chapter, we will see arithmetic operations on the $(I integer) types of D. These features will allow us to write much more useful programs. +) + +$(P +Although arithmetic operations are a part of our daily lives and are actually simple, there are very important concepts that a programmer must be aware of in order to produce correct programs: the $(I bit length of a type), $(I overflow) (wrap), and $(I truncation). +) + +$(P +Before going further, I would like to summarize the arithmetic operations in the following table as a reference: +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Operator Effect Sample
    ++increments by one++variable
    --decrements by one--variable
    +the result of adding two valuesfirst + second
    -the result of subtracting 'second' from 'first'first - second
    *the result of multiplying two valuesfirst * second
    /the result of dividing 'first' by 'second'first / second
    %the remainder of dividing 'first' by 'second'first % second
    ^^the result of raising 'first' to the power of 'second'$(BR)(multiplying 'first' by itself 'second' times)first ^^ second
    + +$(P +$(IX +=) $(IX -=) $(IX *=) $(IX /=) $(IX %=) $(IX ^^=) Most of those operators have counterparts that have an $(C =) sign attached: $(C +=), $(C -=), $(C *=), $(C /=), $(C %=), and $(C ^^=). The difference with these operators is that they assign the result to the left-hand side: +) + +--- + variable += 10; +--- + +$(P +That expression adds the value of $(C variable) and 10 and assigns the result to $(C variable). In the end, the value of $(C variable) would be increased by 10. It is the equivalent of the following expression: +) + +--- + variable = variable + 10; +--- + +$(P +I would like also to summarize two important concepts here before elaborating on them below. +) + +$(P +$(IX wrap) $(B Overflow:) Not all values can fit in a variable of a given type. If the value is too big for the variable we say that the variable $(I overflows). For example, a variable of type $(C ubyte) can have values only in the range of 0 to 255; so when assigned 260, the variable overflows, wraps around, and its value becomes 4. ($(I $(B Note:) Unlike some other languages like C and C++, overflow for signed types is legal in D. It has the same wrap around behavior of unsigned types.)) +) + +$(P +Similarly, a variable cannot have a value that is less than the minimum value of its type. +) + +$(P +$(B Truncation:) Integer types cannot have values with fractional parts. For example, the value of the $(C int) expression $(C 3/2) is 1, not 1.5. +) + +$(P +We encounter arithmetic operations daily without many surprises: if a bagel is $1, two bagels are $2; if four sandwiches are $15, one sandwich is $3.75, etc. +) + +$(P +Unfortunately, things are not as simple with arithmetic operations in computers. If we don't understand how values are stored in a computer, we may be surprised to see that a company's debt is $(I reduced) to $1.7 billion when it borrows $3 billion more on top of its existing debt of $3 billion! Or when a box of ice cream serves 4 kids, an arithmetic operation may claim that 2 boxes would be sufficient for 11 kids! +) + +$(P +Programmers must understand how integers are stored in computers.) + +$(H6 $(IX integer) Integer types) + +$(P +Integer types are the types that can have only whole values like -2, 0, 10, etc. These types cannot have fractional parts, as in 2.5. All of the integer types that we saw in the $(LINK2 types.html, Fundamental Types chapter) are the following: +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    $(BR)Type Number of$(BR)Bits Initial$(BR)Value
    byte80
    ubyte80
    short160
    ushort160
    int320
    uint320
    long640L
    ulong640LU
    + +$(P +The $(C u) at the beginning of the type names stands for "unsigned" and indicates that such types cannot have values less than zero. +) + +$(P +Although they are equal to $(C 0); $(C 0L) and $(C 0LU) are $(I manifest constants) typed as $(C long) and $(C ulong), respectively. +) + +$(H6 $(IX bit) Number of bits of a type) + +$(P +In today's computer systems, the smallest unit of information is called a $(I bit). At the physical level, a bit is represented by electrical signals around certain points in the circuitry of a computer. A bit can be in one of two states that correspond to different voltages in the area that defines that particular bit. These two states are arbitrarily defined to have the values 0 and 1. As a result, a bit can have one of these two values. +) + +$(P +As there aren't many concepts that can be represented by just two states, a bit is not a very useful type. It can only be useful for concepts with two states like heads or tails or whether a light switch is on or off. +) + +$(P +If we consider two bits together, the total amount of information that can be represented multiplies. Based on each bit having a value of 0 or 1 individually, there are a total of 4 possible states. Assuming that the left and right digits represent the first and second bit respectively, these states are 00, 01, 10, and 11. Let's add one more bit to see this effect better; three bits can be in 8 different states: 000, 001, 010, 011, 100, 101, 110, 111. As can be seen, each added bit doubles the total number of states that can be represented. +) + +$(P +The values to which these eight states correspond are defined by conventions. The following table shows these values for the signed and unsigned representations of 3 bits: +) + + + + + + + + + + + +
    Bit State Unsigned Value Signed Value
    000 0 0
    001 1 1
    010 2 2
    011 3 3
    100 4 -4
    101 5 -3
    110 6 -2
    111 7 -1
    + +$(P +We can construct the following table by adding more bits: +) + + + + + + + + + + + + + + + + + + +
    Bits Number of Distinct ValuesD TypeMinimum ValueMaximum Value
    12
    24
    38
    416
    532
    664
    7128
    8256 byte$(BR)ubyte-128$(BR)0127$(BR)255
    ......
    1665536 short$(BR)ushort-32768$(BR)032767$(BR)65535
    ......
    324294967296 int$(BR)uint-2147483648$(BR)02147483647$(BR)4294967295
    ......
    6418446744073709551616 long$(BR)ulong-9223372036854775808$(BR)09223372036854775807$(BR)18446744073709551615
    ......
    + +$(P +I skipped many rows in the table and indicated the signed and unsigned versions of the D types that have the same number of bits on the same row (e.g. $(C int) and $(C uint) are both on the 32-bit row). +) + +$(H6 Choosing a type) + +$(P +D has no 3-bit type. But such a hypothetical type could only have 8 distinct values. It could only represent concepts such as the value of a die, or the week's day number. +) + +$(P +On the other hand, although $(C uint) is a very large type, it cannot represent the concept of an ID number for each living person, as its maximum value is less than the world population of 7 billion. $(C long) and $(C ulong) would be more than enough to represent many concepts. +) + +$(P +As a general rule, as long as there is no specific reason not to, you can use $(C int) for integer values. +) + +$(H6 $(IX overflow) Overflow) + +$(P +The fact that types can only hold values within a limited range may cause unexpected results. For example, although adding two $(C uint) variables with values of 3 billion each should produce 6 billion, because that sum is greater than the maximum value that a $(C uint) variable can hold (about 4 billion), this sum $(I overflows). Without any warning, only the difference of 6 and 4 billion gets stored. (A little more accurately, 6 minus 4.3 billion.) +) + +$(H6 $(IX truncation) Truncation) + +$(P +Since integers cannot have values with fractional parts, they lose the part after the decimal point. For example, assuming that a box of ice cream serves 4 kids, although 11 kids would actually need 2.75 boxes, the fractional part of that value cannot be stored in an integer type, so the value becomes 2. +) + +$(P +I will show limited techniques to help reduce the risk of overflow and truncation later in the chapter. +) + +$(H6 $(C .min) and $(C .max)) + +$(P +I will take advantage of the $(C .min) and $(C .max) properties below, which we have seen in the $(LINK2 types.html, Fundamental Types chapter). These properties provide the minimum and maximum values that an integer type can have. +) + +$(H6 $(IX ++, pre-increment) $(IX increment) Increment: $(C ++)) + +$(P +This operator is used with a single variable (more generally, with a single expression) and is written before the name of that variable. It increments the value of that variable by 1: +) + +--- +import std.stdio; + +void main() { + int number = 10; + $(HILITE ++)number; + writeln("New value: ", number); +} +--- + +$(SHELL +New value: 11 +) + +$(P +The increment operator is the equivalent of using the $(I add-and-assign) operator with the value of 1: +) + +--- + number += 1; // same as ++number +--- + +$(P +If the result of the increment operation is greater than the maximum value of that type, the result $(I overflows) and becomes the minimum value. We can see this effect by incrementing a variable that initially has the value $(C int.max): +) + +--- +import std.stdio; + +void main() { + writeln("minimum int value : ", int.min); + writeln("maximum int value : ", int.max); + + int number = int.max; + writeln("before the increment: ", number); + ++number; + writeln("after the increment : ", number); +} +--- + +$(P +The value becomes $(C int.min) after the increment: +) + +$(SHELL +minimum int value : -2147483648 +maximum int value : 2147483647 +before the increment: 2147483647 +after the increment : -2147483648 +) + +$(P +This is a very important observation because the value changes from the maximum to the minimum as a result of $(I incrementing) and without any warning! This effect is called $(I overflow). We will see similar effects with other operations. +) + +$(H6 $(IX --, pre-decrement) $(IX decrement) Decrement: $(C --)) + +$(P +This operator is similar to the increment operator; the difference is that the value is decreased by 1: +) + +--- + --number; // the value decreases by 1 +--- + +$(P +The decrement operation is the equivalent of using the $(I subtract-and-assign) operator with the value of 1: +) + +--- + number -= 1; // same as --number +--- + + +$(P +Similar to the $(C ++) operator, if the value is the minimum value to begin with, it becomes the maximum value. This effect is called $(I overflow) as well. +) + +$(H6 $(IX +, addition) $(IX addition) Addition: +) + +$(P +This operator is used with two expressions and adds their values: +) + +--- +import std.stdio; + +void main() { + int number_1 = 12; + int number_2 = 100; + + writeln("Result: ", number_1 $(HILITE +) number_2); + writeln("With a constant expression: ", 1000 $(HILITE +) number_2); +} +--- + +$(SHELL +Result: 112 +With a constant expression: 1100 +) + +$(P +If the sum of the two expressions is greater than the maximum value of that type, it overflows and becomes a value that is less than both of the expressions: +) + +--- +import std.stdio; + +void main() { + // 3 billion each + uint number_1 = 3000000000; + uint number_2 = 3000000000; + + writeln("maximum value of uint: ", uint.max); + writeln(" number_1: ", number_1); + writeln(" number_2: ", number_2); + writeln(" sum: ", number_1 + number_2); + writeln("OVERFLOW! The result is not 6 billion!"); +} +--- + +$(SHELL +maximum value of uint: 4294967295 + number_1: 3000000000 + number_2: 3000000000 + sum: 1705032704 +OVERFLOW! The result is not 6 billion! +) + +$(H6 $(IX -, subtraction) $(IX subtraction) Subtraction: $(C -)) + +$(P +This operator is used with two expressions and gives the difference between the first and the second: +) + +--- +import std.stdio; + +void main() { + int number_1 = 10; + int number_2 = 20; + + writeln(number_1 $(HILITE -) number_2); + writeln(number_2 $(HILITE -) number_1); +} +--- + +$(SHELL +-10 +10 +) + +$(P +It is again surprising if the actual result is less than zero and is stored in an unsigned type. Let's rewrite the program using the $(C uint) type: +) + +--- +import std.stdio; + +void main() { + uint number_1 = 10; + uint number_2 = 20; + + writeln("PROBLEM! uint cannot have negative values:"); + writeln(number_1 - number_2); + writeln(number_2 - number_1); +} +--- + +$(SHELL +PROBLEM! uint cannot have negative values: +4294967286 +10 +) + +$(P +It is a good guideline to use signed types to represent concepts that may ever be subtracted. As long as there is no specific reason not to, you can choose $(C int). +) + +$(H6 $(IX *, multiplication) $(IX multiplication) Multiplication: $(C *)) + +$(P +This operator multiplies the values of two expressions; the result is again subject to overflow: +) + +--- +import std.stdio; + +void main() { + uint number_1 = 6; + uint number_2 = 7; + + writeln(number_1 $(HILITE *) number_2); +} +--- + +$(SHELL +42 +) + +$(H6 $(IX /) $(IX division) Division: $(C /)) + +$(P +This operator divides the first expression by the second expression. Since integer types cannot have fractional values, the fractional part of the value is discarded. This effect is called $(I truncation). As a result, the following program prints 3, not 3.5: +) + +--- +import std.stdio; + +void main() { + writeln(7 $(HILITE /) 2); +} +--- + +$(SHELL +3 +) + +$(P +For calculations where fractional parts matter, $(I floating point types) must be used instead of integers. We will see floating point types in the next chapter. +) + +$(H6 $(IX %) $(IX remainder) $(IX modulus) Remainder (modulus): %) + +$(P +This operator divides the first expression by the second expression and produces the remainder of the division: +) + +--- +import std.stdio; + +void main() { + writeln(10 $(HILITE %) 6); +} +--- + +$(SHELL +4 +) + +$(P +A common application of this operator is to determine whether a value is odd or even. Since the remainder of dividing an even number by 2 is always 0, comparing the result against 0 is sufficient to make that distinction: +) + +--- + if ((number % 2) == 0) { + writeln("even number"); + + } else { + writeln("odd number"); + } +--- + +$(H6 $(IX ^^) $(IX power of) Power: ^^) + +$(P +This operator raises the first expression to the power of the second expression. For example, raising 3 to the power of 4 is multiplying 3 by itself 4 times: +) + +--- +import std.stdio; + +void main() { + writeln(3 $(HILITE ^^) 4); +} +--- + +$(SHELL +81 +) + +$(H6 $(IX assignment, operation result) Arithmetic operations with assignment) + +$(P +All of the operators that take two expressions have $(I assignment) counterparts. These operators assign the result back to the expression that is on the left-hand side: +) + +--- +import std.stdio; + +void main() { + int number = 10; + + number += 20; // same as number = number + 20; now 30 + number -= 5; // same as number = number - 5; now 25 + number *= 2; // same as number = number * 2; now 50 + number /= 3; // same as number = number / 3; now 16 + number %= 7; // same as number = number % 7; now 2 + number ^^= 6; // same as number = number ^^ 6; now 64 + + writeln(number); +} +--- + +$(SHELL +64 +) + +$(H6 $(IX -, negation) $(IX negation) Negation: $(C -)) + +$(P +This operator converts the value of the expression from negative to positive or positive to negative: +) + +--- +import std.stdio; + +void main() { + int number_1 = 1; + int number_2 = -2; + + writeln($(HILITE -)number_1); + writeln($(HILITE -)number_2); +} +--- + +$(SHELL +-1 +2 +) + +$(P +The type of the result of this operation is the same as the type of the expression. Since unsigned types cannot have negative values, the result of using this operator with unsigned types can be surprising: +) + +--- + $(HILITE uint) number = 1; + writeln("negation: ", -number); +--- + +$(P +The type of $(C -number) is $(C uint) as well, which cannot have negative values: +) + +$(SHELL +negation: 4294967295 +) + +$(H6 $(IX +, plus sign) $(IX plus sign) Plus sign: $(C +)) + +$(P +This operator has no effect and exists only for symmetry with the negation operator. Positive values stay positive and negative values stay negative: +) + +--- +import std.stdio; + +void main() { + int number_1 = 1; + int number_2 = -2; + + writeln($(HILITE +)number_1); + writeln($(HILITE +)number_2); +} +--- + +$(SHELL +1 +-2 +) + +$(H6 $(IX ++, post-increment) $(IX post-increment) $(IX increment, post) Post-increment: $(C ++)) + +$(P +$(I $(B Note:) Unless there is a strong reason not to, always use the regular increment operator (which is sometimes called the pre-increment operator).) +) + +$(P +Contrary to the regular increment operator, it is written after the expression and still increments the value of the expression by 1. The difference is that the post-increment operation produces the old value of the expression. To see this difference, let's compare it with the regular increment operator: +) + +--- +import std.stdio; + +void main() { + int incremented_regularly = 1; + writeln(++incremented_regularly); // prints 2 + writeln(incremented_regularly); // prints 2 + + int post_incremented = 1; + + // Gets incremented, but its old value is used: + writeln(post_incremented$(HILITE ++)); // prints 1 + writeln(post_incremented); // prints 2 +} +--- + +$(SHELL +2 +2 +1 +2 +) + +$(P +The $(C writeln(post_incremented++);) statement above is the equivalent of the following code: +) + +--- + int old_value = post_incremented; + ++post_incremented; + writeln(old_value); // prints 1 +--- + +$(H6 $(IX --, post-decrement) $(IX post-decrement) $(IX decrement, post) Post-decrement: $(C --)) + +$(P +$(I $(B Note:) Unless there is a strong reason not to, always use the regular decrement operator (which is sometimes called the pre-decrement operator).) +) + +$(P +This operator behaves the same way as the post-increment operator except that it decrements. +) + +$(H6 Operator precedence) + +$(P +The operators we've discussed above have all been used in operations on their own with only one or two expressions. However, similar to logical expressions, it is common to combine these operators to form more complex arithmetic expressions: +) + +--- + int value = 77; + int result = (((value + 8) * 3) / (value - 1)) % 5; +--- + +$(P +As with logical operators, arithmetic operators also obey operator precedence rules. For example, the $(C *) operator has precedence over the $(C +) operator. For that reason, when parentheses are not used (e.g. in the $(C value + 8 * 3) expression), the $(C *) operator is evaluated before the $(C +) operator. As a result, that expression becomes the equivalent of $(C value + 24), which is quite different from $(C (value + 8) * 3). +) + +$(P +Using parentheses is useful both for ensuring correct results and for communicating the intent of the code to programmers who may work on it in the future. +) + +$(P +The operator precedence table will be presented $(LINK2 operator_precedence.html, later in the book). +) + +$(H6 Detecting overflow) + +$(P +$(IX core.checkedint) $(IX checkedint) $(IX adds) $(IX addu) $(IX subs) $(IX subu) $(IX muls) $(IX mulu) $(IX negs) Although it uses $(LINK2 functions.html, functions) and $(LINK2 function_parameters.html, $(C ref) parameters), which we have not covered yet, I would like to mention here that $(LINK2 http://dlang.org/phobos/core_checkedint.html, the $(C core.checkedint) module) contains arithmetic functions that detect overflow. Instead of operators like $(C +) and $(C -), this module uses functions: $(C adds) and $(C addu) for signed and unsigned addition, $(C muls) and $(C mulu) for signed and unsigned multiplication, $(C subs) and $(C subu) for signed and unsigned subtraction, and $(C negs) for negation. +) + +$(P +For example, assuming that $(C a) and $(C b) are two $(C int) variables, the following code would detect whether adding them has caused an overflow: +) + +--- +import core.checkedint; + +void main() { + // Let's cause overflow for test purposes + int a = int.max - 1; + int b = 2; + + // This variable will become 'true' if the addition + // operation inside the 'adds' function overflows: + bool hasOverflowed = false; + int result = adds(a, b, $(HILITE hasOverflowed)); + + if (hasOverflowed) { + // We must not use 'result' because it has overflowed + // ... + + } else { + // We can use 'result' + // ... + } +} +--- + +$(P +$(IX experimental.checkedint) $(IX Checked) There is also $(LINK2 https://dlang.org/phobos/std_experimental_checkedint.html, the std.experimental.checkedint) module that defines the $(C Checked) template but both its usage and its implementation are too advanced at this point in the book. +) + +$(H6 Preventing overflow) + +$(P +If the result of an operation cannot fit in the type of the result, then there is nothing that can be done. Sometimes, although the ultimate result would fit in a certain type, the intermediate calculations may overflow and cause incorrect results. +) + +$(P +As an example, let's assume that we need to plant an apple tree per 1000 square meters of an area that is 40 by 60 kilometers. How many trees are needed? +) + +$(P +When we solve this problem on paper, we see that the result is 40000 times 60000 divided by 1000, being equal to 2.4 million trees. Let's write a program that executes this calculation: +) + +--- +import std.stdio; + +void main() { + int width = 40000; + int length = 60000; + int areaPerTree = 1000; + + int treesNeeded = width * length / areaPerTree; + + writeln("Number of trees needed: ", treesNeeded); +} +--- + +$(SHELL +Number of trees needed: -1894967 +) + +$(P +Not to mention it is not even close, the result is also less than zero! In this case, the intermediate calculation $(C width * length) overflows and the subsequent calculation of $(C / areaPerTree) produces an incorrect result. +) + +$(P +One way of avoiding the overflow in this example is to change the order of operations: +) + +--- + int treesNeeded = width / areaPerTree * length ; +--- + +$(P +The result would now be correct: +) + +$(SHELL +Number of trees needed: 2400000 +) + +$(P +The reason this method works is the fact that all of the steps of the calculation now fit the $(C int) type. +) + +$(P +Please note that this is not a complete solution because this time the intermediate value is prone to truncation, which may affect the result significantly in certain other calculations. Another solution might be to use a floating point type instead of an integer type: $(C float), $(C double), or $(C real). +) + +$(H6 Preventing truncation) + +$(P +Changing the order of operations may be a solution to truncation as well. An interesting example of truncation can be seen by dividing and multiplying a value with the same number. We would expect the result of 10/9*9 to be 10, but it comes out as 9: +) + +--- +import std.stdio; + +void main() { + writeln(10 / 9 * 9); +} +--- + +$(SHELL +9 +) + +$(P +The result is correct when truncation is avoided by changing the order of operations: +) + +--- + writeln(10 * 9 / 9); +--- + +$(SHELL +10 +) + +$(P +This too is not a complete solution: This time the intermediate calculation could be prone to overflow. Using a floating point type may be another solution to truncation in certain calculations. +) + +$(PROBLEM_COK + +$(PROBLEM +Write a program that takes two integers from the user, prints the integer quotient resulting from the division of the first by the second, and also prints the remainder. For example, when 7 and 3 are entered, have the program print the following equation: + +$(SHELL +7 = 3 * 2 + 1 +) + +) + +$(PROBLEM +Modify the program to print a shorter output when the remainder is 0. For example, when 10 and 5 are entered, it should not print "10 = 5 * 2 + 0" but just the following: + +$(SHELL +10 = 5 * 2 +) + +) + +$(PROBLEM +Write a simple calculator that supports the four basic arithmetic operations. Have the program let the operation to be selected from a menu and apply that operation to the two values that are entered. You can ignore overflow and truncation in this program. +) + +$(PROBLEM +Write a program that prints the values from 1 to 10, each on a separate line, with the exception of value 7. Do not use repeated lines as in the following code: + +--- +import std.stdio; + +void main() { + // Do not do this! + writeln(1); + writeln(2); + writeln(3); + writeln(4); + writeln(5); + writeln(6); + writeln(8); + writeln(9); + writeln(10); +} +--- + +$(P +Instead, imagine a variable whose value is incremented in a loop. You may need to take advantage of the $(I is not equal to) operator $(C !=) here. +) + +) + +) + +Macros: + TITLE=Integers and Arithmetic Operations + + DESCRIPTION=The integer arithmetic operations of the D language + + KEYWORDS=d programming language tutorial book integer arithmetic operations + +MINI_SOZLUK= +$(Ergin) diff --git a/book/d.en/arrays.cozum.d b/book/d.en/arrays.cozum.d new file mode 100644 index 0000000000..23d90cd1ca --- /dev/null +++ b/book/d.en/arrays.cozum.d @@ -0,0 +1,133 @@ +Ddoc + +$(COZUM_BOLUMU Arrays) + +$(OL + +$(LI + +--- +import std.stdio; +import std.algorithm; + +void main() { + write("How many values will be entered? "); + int count; + readf(" %s", &count); + + double[] values; + values.length = count; + + // The counter is commonly named as 'i' + int i; + while (i < count) { + write("Value ", i, ": "); + readf(" %s", &values[i]); + ++i; + } + + writeln("In sorted order:"); + sort(values); + + i = 0; + while (i < count) { + write(values[i], " "); + ++i; + } + writeln(); + + writeln("In reverse order:"); + reverse(values); + + i = 0; + while (i < count) { + write(values[i], " "); + ++i; + } + writeln(); +} +--- + +) + +$(LI +The explanations are included as code comments: + +--- +import std.stdio; +import std.algorithm; + +void main() { + // Using dynamic arrays because it is not known how many + // values are going to be read from the input + int[] odds; + int[] evens; + + writeln("Please enter integers (-1 to terminate):"); + + while (true) { + + // Reading the value + int value; + readf(" %s", &value); + + // The special value of -1 breaks the loop + if (value == -1) { + break; + } + + // Adding to the corresponding array, depending on + // whether the value is odd or even. It is an even + // number if there is no remainder when divided by 2. + if ((value % 2) == 0) { + evens ~= value; + + } else { + odds ~= value; + } + } + + // The odds and evens arrays are sorted separately + sort(odds); + sort(evens); + + // The two arrays are then appended to form a new array + int[] result; + result = odds ~ evens; + + writeln("First the odds then the evens, sorted:"); + + // Printing the array elements in a loop + int i; + while (i < result.length) { + write(result[i], " "); + ++i; + } + + writeln(); +} +--- + +) + +$(LI +There are three mistakes (bugs) in this program. The first two are with the $(C while) loops: Both of the loop conditions use the $(C <=) operator instead of the $(C <) operator. As a result, the program uses invalid indexes and attempts to access elements that are not parts of the arrays. + +$(P +Since it is more beneficial for you to debug the third mistake yourself, I would like you to first run the program after fixing the previous two bugs. You will notice that the program will not print the results. Can you figure out the remaining problem before reading the following paragraph? +) + +$(P +The value of $(C i) is 5 when the first $(C while) loop terminates, and that value is causing the logical expression of the second loop to be $(C false), which in turn is preventing the second loop to be entered. The solution is to reset $(C i) to 0 before the second $(C while) loop, for example with the statement $(C i = 0;) +) + +) + +) + +Macros: + TITLE=Arrays Solutions + + DESCRIPTION=Programming in D exercise solutions: arrays + + KEYWORDS=programming in d tutorial arrays solution diff --git a/book/d.en/arrays.d b/book/d.en/arrays.d new file mode 100644 index 0000000000..b796ca502a --- /dev/null +++ b/book/d.en/arrays.d @@ -0,0 +1,601 @@ +Ddoc + +$(DERS_BOLUMU $(IX array) Arrays) + +$(P +We have defined five variables in one of the exercises of the last chapter, and used them in certain calculations. The definitions of those variables were the following: +) + +--- + double value_1; + double value_2; + double value_3; + double value_4; + double value_5; +--- + +$(P +This method of defining variables individually does not scale to cases where even more variables are needed. Imagine needing a thousand values; it is almost impossible to define a thousand variables from $(C value_1) to $(C value_1000). +) + +$(P +Arrays are useful in such cases: the array feature allows us to define a single variable that stores multiple values together. Although simple, arrays are the most common data structure used to store a collection of values. +) + +$(P +This chapter covers only some of the features of arrays. More features will be introduced later in $(LINK2 slices.html, the Slices and Other Array Features chapter). +) + +$(H5 Definition) + +$(P +The definition of array variables is very similar to the definition of normal variables. The only difference is that the number of values associated with the variable is specified in square brackets. We can contrast the two definitions as follows: +) + +--- + int singleValue; + int[10] arrayOfTenValues; +--- + +$(P +The first line above is the definition of a variable which stores a single value, just like the variables that we have defined so far. The second line is the definition of a variable which stores ten consecutive values. In other words, it stores an array of ten integer values. You can also think of it as defining ten variables of the same type, or as defining an array, for short. +) + +$(P +Accordingly, the equivalent of the five separate variables above can be defined as an array of five values using the following syntax: +) + +--- + double[5] values; +--- + +$(P +$(IX scalar) That definition can be read as $(I 5 double values). Note that I have chosen the name of the array variable as plural to avoid confusing it with a single-valued variable. Variables which only store a single value are called scalar variables. +) + +$(P +In summary, the definition of an array variable consists of the type of the values, the number of values, and the name of the variable that refers to the array of values: +) + +--- + $(I type_name)[$(I value_count)] $(I variable_name); +--- + +$(P +The type of the values can also be a user-defined type. (We will see user-defined types later.) For example: +) + +--- + // An array that holds the weather information of all + // cities. Here, the bool values may mean + // false: overcast + // true : sunny + bool[cityCount] weatherConditions; + + // An array that holds the weights of a hundred boxes + double[100] boxWeights; + + // Information about the students of a school + StudentInformation[studentCount] studentInformation; +--- + +$(H5 $(IX container) $(IX element) Containers and elements) + +$(P +Data structures that bring elements of a certain type together are called $(I containers). According to this definition, arrays are containers. For example, an array that holds the air temperatures of the days in July can bring 31 $(C double) values together and form $(I a container of elements of type $(C double)). +) + +$(P +The variables of a container are called $(I elements). The number of elements of an array is called the $(I length) of the array. +) + +$(H5 $(IX []) Accessing the elements) + +$(P +In order to differentiate the variables in the exercise of the previous chapter, we appended an underscore and a number to their names as in $(C value_1). This is not possible nor necessary when a single array stores all the values under a single name. Instead, the elements are accessed by specifying the $(I element number) within square brackets: +) + +--- + values[0] +--- + +$(P +That expression can be read as $(I the element with the number 0 of the array named values). In other words, instead of typing $(C value_1) one must type $(C values[0]) with arrays. +) + +$(P +There are two important points worth stressing here: +) + +$(UL + +$(LI $(B The numbers start with zero:) Although humans assign numbers to items starting with 1, the numbers in arrays start at 0. The values that we have numbered as 1, 2, 3, 4, and 5 before are numbered as 0, 1, 2, 3, and 4 in the array. This variation can confuse new programmers. +) + +$(LI $(B Two different uses of the $(C[]) characters:) Don't confuse the two separate uses of the $(C []) characters. When defining arrays, the $(C []) characters are written after the type of the elements and specify the number of elements. When accessing elements, the $(C []) characters are written after the name of the array and specify the number of the element that is being accessed: + +--- + // This is a definition. It defines an array that consists + // of 12 elements. This array is used to hold the number + // of days in each month. + int[12] monthDays; + + // This is an access. It accesses the element that + // corresponds to December and sets its value to 31. + monthDays[11] = 31; + + // This is another access. It accesses the element that + // corresponds to January, the value of which is passed to + // writeln. + writeln("January has ", monthDays[0], " days."); +--- + +$(P +$(B Reminder:) The element numbers of January and December are 0 and 11 respectively; not 1 and 12. +) + +) + +) + +$(H5 $(IX index) Index) + +$(P +The number of an element is called its $(I index) and the act of accessing an element is called $(I indexing). +) + +$(P +An index need not be a constant value; the value of a variable can also be used as an index, making arrays even more useful. For example, the month can be determined by the value of the $(C monthIndex) variable below: +) + +--- + writeln("This month has ", monthDays[monthIndex], " days."); +--- + +$(P +When the value of $(C monthIndex) is 2, the expression above would print the value of $(C monthDays[2]), the number of days in March. +) + +$(P +Only the index values between zero and one less than the length of the array are valid. For example, the valid indexes of a three-element array are 0, 1, and 2. Accessing an array with an invalid index causes the program to be terminated with an error. +) + +$(P +Arrays are containers where the elements are placed side by side in the computer's memory. For example, the elements of the array holding the number of days in each month can be shown as follows (assuming a year when February has 28 days): +) + +$(MONO + indexes → 0 1 2 3 4 5 6 7 8 9 10 11 + elements → | 31 | 28 | 31 | 30 | 31 | 30 | 31 | 31 | 30 | 31 | 30 | 31 | +) + +$(P +$(I $(B Note:) The indexes above are for demonstration purposes only; they are not stored in the computer's memory.) +) + +$(P +The element at index 0 has the value 31 (number of days in January); the element at index 1 has the value of 28 (number of days in February), etc. +) + +$(H5 $(IX fixed-length array) $(IX dynamic array) $(IX static array) Fixed-length arrays vs. dynamic arrays) + +$(P +When the length of an array is specified when the program is written, that array is a $(I fixed-length array). When the length can change during the execution of the program, that array is a $(I dynamic array). +) + +$(P +Both of the arrays that we have defined above are fixed-length arrays because their element counts are specified as 5 and 12 at the time when the program is written. The lengths of those arrays cannot be changed during the execution of the program. To change their lengths, the source code must be modified and the program must be recompiled. +) + +$(P +Defining dynamic arrays is simpler than defining fixed-length arrays because omitting the length makes a dynamic array: +) + +--- + int[] dynamicArray; +--- + +$(P +The length of such an array can increase or decrease during the execution of the program. +) + +$(P +Fixed-length arrays are also known as static arrays. +) + +$(H5 $(IX .length) Using $(C .length) to get or set the number of elements) + +$(P +Arrays have properties as well, of which we will see only $(C .length) here. $(C .length) returns the number of elements of the array: +) + +--- + writeln("The array has ", array.length, " elements."); +--- + +$(P +Additionally, the length of dynamic arrays can be changed by assigning a value to this property: +) + +--- + int[] array; // initially empty + array.length = 5; // now has 5 elements +--- + +$(H5 An array example) + +$(P +Let's now revisit the exercise with the five values and write it again by using an array: +) + +--- +import std.stdio; + +void main() { + // This variable is used as a loop counter + int counter; + + // The definition of a fixed-length array of five + // elements of type double + double[5] values; + + // Reading the values in a loop + while (counter < values.length) { + write("Value ", counter + 1, ": "); + readf(" %s", &values[counter]); + ++counter; + } + + writeln("Twice the values:"); + counter = 0; + while (counter < values.length) { + writeln(values[counter] * 2); + ++counter; + } + + // The loop that calculates the fifths of the values would + // be written similarly +} +--- + +$(P $(B Observations:) The value of $(C counter) determines how many times the loops are repeated (iterated). Iterating the loop while its value is less than $(C values.length) ensures that the loops are executed once per element. As the value of that variable is incremented at the end of each iteration, the $(C values[counter]) expression refers to the elements of the array one by one: $(C values[0]), $(C values[1]), etc. +) + +$(P +To see how this program is better than the previous one, imagine needing to read 20 values. The program above would require a single change: replacing 5 with 20. On the other hand, a program that did not use an array would have to have 20 variable definitions. Furthermore, since you would be unable to use a loop to iterate the 20 values, you would also have to repeat several lines 20 times, one time for each single-valued variable. +) + +$(H5 $(IX initialization, array) Initializing the elements) + +$(P +Like every variable in D, the elements of arrays are automatically initialized. The initial value of the elements depends on the type of the elements: 0 for $(C int), $(C double.nan) for $(C double), etc. +) + +$(P +All of the elements of the $(C values) array above are initialized to $(C double.nan): +) + +--- + double[5] values; // elements are all double.nan +--- + +$(P +Obviously, the values of the elements can be changed later during the execution of the program. We have already seen this above when assigning to an element of an array: +) + +--- + monthDays[11] = 31; +--- + +$(P +That also happened when reading a value from the input: +) + +--- + readf(" %s", &values[counter]); +--- + +$(P +Sometimes the desired values of the elements are known at the time when the array is defined. In such cases, the initial values of the elements can be specified on the right-hand side of the assignment operator, within square brackets. Let's see this in a program that reads the number of the month from the user, and prints the number of days in that month: +) + +--- +import std.stdio; + +void main() { + // Assuming that February has 28 days + int[12] monthDays = + [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; + + write("Please enter the number of the month: "); + int monthNumber; + readf(" %s", &monthNumber); + + int index = monthNumber - 1; + writeln("Month ", monthNumber, " has ", + monthDays[index], " days."); +} +--- + +$(P +As you can see, the $(C monthDays) array is defined and initialized at the same time. Also note that the number of the month, which is in the range 1-12, is converted to a valid array index in the range 0-11. Any value that is entered outside of the 1-12 range would cause the program to be terminated with an error. +) + +$(P +When initializing arrays, it is possible to use a single value on the right-hand side. In that case all of the elements of the array are initialized to that value: +) + +--- + int[10] allOnes = 1; // All of the elements are set to 1 +--- + +$(H5 Basic array operations) + +$(P +Arrays provide convenience operations that apply to all of their elements. +) + +$(H6 $(IX copy, array) Copying fixed-length arrays) + +$(P +The assignment operator copies all of the elements from the right-hand side to the left-hand side: +) +--- + int[5] source = [ 10, 20, 30, 40, 50 ]; + int[5] destination; + + destination $(HILITE =) source; +--- + +$(P +$(I $(B Note:) The meaning of the assignment operation is completely different for dynamic arrays. We will see this in a later chapter.) +) + +$(H6 $(IX ~=) $(IX append, array) $(IX add element, array) Adding elements to dynamic arrays) + +$(P +The $(C ~=) operator adds new elements to the end of a dynamic array: +) + +--- + int[] array; // empty + array ~= 7; // array is now equal to [7] + array ~= 360; // array is now equal to [7, 360] + array ~= [ 30, 40 ]; // array is now equal to [7, 360, 30, 40] +--- + +$(P +It is not possible to add elements to fixed-length arrays: +) + +--- + int[$(HILITE 10)] array; + array ~= 7; $(DERLEME_HATASI) +--- + +$(H6 $(IX remove, array) Removing elements from dynamic arrays) + +$(P +Array elements can be removed with the $(C remove()) function from the $(C std.algorithm) module. Because there may be more than one $(I slice) to the same elements, $(C remove()) cannot actually change the number of element of the array. Rather, it has to move some of the elements of the array one or more positions to the left. For that reason, the result of the remove operation must be assigned back to the same array variable. +) + +$(P +There are two different ways of using $(C remove()): +) + +$(OL +$(LI +Providing the index of the element to remove. For example, the following code removes the element at index 1. + +--- +import std.stdio; +import std.algorithm; + +void main() { + int[] array = [ 10, 20, 30, 40 ]; + $(HILITE array =) array.remove($(HILITE 1)); // Assigned back to array + writeln(array); +} +--- + +$(SHELL +[10, 30, 40] +) +) + +$(LI +Specifying the elements to remove with a $(I lambda function), which we will cover in $(LINK2 lambda.html, a later chapter). For example, the following code removes the elements of the array that are equal to 42. + +--- +import std.stdio; +import std.algorithm; + +void main() { + int[] array = [ 10, 42, 20, 30, 42, 40 ]; + $(HILITE array =) array.remove!(a => $(HILITE a == 42)); // Assigned back to array + writeln(array); +} +--- + +$(SHELL +[10, 20, 30, 40] +) +) + +) + +$(H6 $(IX ~, concatenation) $(IX concatenation, array) Combining arrays) + +$(P +The $(C ~) operator creates a new array by combining two arrays. Its $(C ~=) counterpart combines the two arrays and assigns the result back to the left-hand side array: +) + +--- +import std.stdio; + +void main() { + int[10] first = 1; + int[10] second = 2; + int[] result; + + result = first ~ second; + writeln(result.length); // prints 20 + + result ~= first; + writeln(result.length); // prints 30 +} +--- + +$(P +The $(C ~=) operator cannot be used when the left-hand side array is a fixed-length array: +) + +--- + int[20] result; + // ... + result $(HILITE ~=) first; $(DERLEME_HATASI) +--- + +$(P +If the array sizes are not equal, the program is terminated with an error during assignment: +) + +--- + int[10] first = 1; + int[10] second = 2; + int[$(HILITE 21)] result; + + result = first ~ second; +--- + +$(SHELL +object.Error@(0): Array lengths don't match for copy: $(HILITE 20 != 21) +) + +$(H6 $(IX sort) Sorting the elements) + +$(P +$(C std.algorithm.sort) can sort the elements of many types of collections. In the case of integers, the elements get sorted from the smallest value to the greatest value. In order to use the $(C sort()) function, one must import the $(C std.algorithm) module first. (We will see functions in a later chapter.) +) + +--- +import std.stdio; +import std.algorithm; + +void main() { + int[] array = [ 4, 3, 1, 5, 2 ]; + $(HILITE sort)(array); + writeln(array); +} +--- + +$(P +The output: +) + +$(SHELL +[1, 2, 3, 4, 5] +) + +$(H6 $(IX reverse) Reversing the elements) + +$(P +$(C std.algorithm.reverse) reverses the elements in place (the first element becomes the last element, etc.): +) + +--- +import std.stdio; +import std.algorithm; + +void main() { + int[] array = [ 4, 3, 1, 5, 2 ]; + $(HILITE reverse)(array); + writeln(array); +} +--- + +$(P +The output: +) + +$(SHELL +[2, 5, 1, 3, 4] +) + +$(PROBLEM_COK + +$(PROBLEM +Write a program that asks the user how many values will be entered and then reads all of them. Have the program sort the elements using $(C sort()) and then reverse the sorted elements using $(C reverse()). +) + +$(PROBLEM +Write a program that reads numbers from the input, and prints the odd and even ones separately but in order. Treat the value -1 specially to determine the end of the numbers; do not process that value. + +$(P +For example, when the following numbers are entered, +) + +$(SHELL +1 4 7 2 3 8 11 -1 +) + +$(P +have the program print the following: +) + +$(SHELL +1 3 7 11 2 4 8 +) + +$(P +$(B Hint:) You may want to put the elements in separate arrays. You can determine whether a number is odd or even using the $(C %) (remainder) operator. +) + +) + +$(PROBLEM +The following is a program that does not work as expected. The program is written to read five numbers from the input and to place the squares of those numbers into an array. The program then attempts to print the squares to the output. Instead, the program terminates with an error. + +$(P +Fix the bugs of this program and make it work as expected: +) + +--- +import std.stdio; + +void main() { + int[5] squares; + + writeln("Please enter 5 numbers"); + + int i = 0; + while (i <= 5) { + int number; + write("Number ", i + 1, ": "); + readf(" %s", &number); + + squares[i] = number * number; + ++i; + } + + writeln("=== The squares of the numbers ==="); + while (i <= squares.length) { + write(squares[i], " "); + ++i; + } + + writeln(); +} +--- + +) + +) + +Macros: + TITLE=Arrays + + DESCRIPTION=Basic array operations of the D programming language + + KEYWORDS=d programming language tutorial book arrays fixed-length dynamic + diff --git a/book/d.en/assert.cozum.d b/book/d.en/assert.cozum.d new file mode 100644 index 0000000000..0b92428f18 --- /dev/null +++ b/book/d.en/assert.cozum.d @@ -0,0 +1,135 @@ +Ddoc +$(COZUM_BOLUMU $(CH4 assert) and $(CH4 enforce)) + +$(OL + +$(LI +You will notice that the program terminates normally when you enter $(C 06:09) and $(C 1:2). However, you may notice that the start time is not what has been entered by the user: + +$(SHELL +1 hours and 2 minutes after 09:06 is 10:08. +) + +$(P +As you can see, although the time that has been entered as $(C 06:09), the output contains $(C 09:06). This error will be caught by the help of an $(C assert) in the next problem. +) + +) + +$(LI +The $(C assert) failure after entering $(C 06:09) and $(C 15:2) takes us to the following line: + +--- +string timeToString(int hour, int minute) { + $(HILITE assert((hour >= 0) && (hour <= 23));) + // ... +} +--- + +$(P +For this $(C assert) check to fail, this function must have been called with invalid $(C hour) value. +) + +$(P +The only two calls to $(C timeToString()) in the program do not appear to have any problems: +) + +--- + writefln("%s hours and %s minutes after %s is %s.", + durationHour, durationMinute, + $(HILITE timeToString)(startHour, startMinute), + $(HILITE timeToString)(endHour, endMinute)); +--- + +$(P +A little more investigation should reveal the actual cause of the bug: The hour and minute variables are swapped when reading the start time: +) + +--- + readTime("Start time", start$(HILITE Minute), start$(HILITE Hour)); +--- + +$(P +That programming error causes the time to be interpreted as $(C 09:06) and incrementing it by duration $(C 15:2) causes an invalid hour value. +) + +$(P +An obvious correction is to pass the hour and minute variables in the right order: +) + +--- + readTime("Start time", startHour, startMinute); +--- + +$(P +The output: +) + +$(SHELL +Start time? (HH:MM) 06:09 +Duration? (HH:MM) 15:2 +15 hours and 2 minutes after 06:09 is 21:11. +) + +) + +$(LI +It is again the same $(C assert) check: + +--- + assert((hour >= 0) && (hour <= 23)); +--- + +$(P +The reason is that $(C addDuration()) can produce hour values that are greater than 23. Adding a $(I remainder) operation at the end would ensure one of the $(I output guarantees) of the function: +) + +--- +void addDuration(int startHour, int startMinute, + int durationHour, int durationMinute, + out int resultHour, out int resultMinute) { + resultHour = startHour + durationHour; + resultMinute = startMinute + durationMinute; + + if (resultMinute > 59) { + ++resultHour; + } + + $(HILITE resultHour %= 24;) +} +--- + +$(P +Observe that the function has other problems. For example, $(C resultMinute) may end up being greater than 59. The following function calculates the minute value correctly and makes sure that the function's output guarantees are enforced: +) + +--- +void addDuration(int startHour, int startMinute, + int durationHour, int durationMinute, + out int resultHour, out int resultMinute) { + resultHour = startHour + durationHour; + resultMinute = startMinute + durationMinute; + + resultHour += resultMinute / 60; + resultHour %= 24; + resultMinute %= 60; + + assert((resultHour >= 0) && (resultHour <= 23)); + assert((resultMinute >= 0) && (resultMinute <= 59)); +} +--- + +) + +$(LI +Good luck. +) + +) + +Macros: + TITLE=assert and enforce Solutions + + DESCRIPTION=Programming in D exercise solutions: assert and enforce + + KEYWORDS=programming in d tutorial functions diff --git a/book/d.en/assert.d b/book/d.en/assert.d new file mode 100644 index 0000000000..af3eb6777e --- /dev/null +++ b/book/d.en/assert.d @@ -0,0 +1,419 @@ +Ddoc + +$(DERS_BOLUMU $(IX assert) $(IX enforce) $(CH4 assert) and $(CH4 enforce)) + +$(P +In the previous two chapters we have seen how exceptions and $(C scope) statements are used toward program correctness. $(C assert) is another powerful tool to achieve the same goal by ensuring that certain assumptions that the program is based on are valid. +) + +$(P +It may sometimes be difficult to decide whether to throw an exception or to call $(C assert). I will use $(C assert) in all of the examples below without much justification. I will explain the differences later in the chapter. +) + +$(P +Although not always obvious, programs are full of assumptions. For example, the following function is written under the assumption that both age parameters are greater than or equal to zero: +) + +--- +double averageAge(double first, double second) { + return (first + second) / 2; +} +--- + +$(P +Although it may be invalid for the program to ever have an age value that is negative, the function would still produce an average, which may be used in the program unnoticed, resulting in the program's continuing with incorrect data. +) + +$(P +As another example, the following function assumes that it will always be called with two commands: "sing" or "dance": +) + +--- +void applyCommand(string command) { + if (command == "sing") { + robotSing(); + + } else { + robotDance(); + } +} +--- + +$(P +Because of that assumption, the $(C robotDance()) function would be called for every command other than "sing", valid or invalid. +) + +$(P +When such assumptions are kept only in the programmer's mind, the program may end up working incorrectly. $(C assert) statements check assumptions and terminate programs immediately when they are not valid. +) + +$(H5 Syntax) + +$(P +$(C assert) can be used in two ways: +) + +--- + assert($(I logical_expression)); + assert($(I logical_expression), $(I message)); +--- + +$(P +The logical expression represents an assumption about the program. $(C assert) evaluates that expression to validate that assumption. If the value of the logical expression is $(C true) then the assumption is considered to be valid. Otherwise the assumption is invalid and an $(C AssertError) is thrown. +) + +$(P +As its name suggests, this exception is inherited from $(C Error), and as you may remember from the $(LINK2 exceptions.html, Exceptions chapter), exceptions that are inherited from $(C Error) must never be caught. It is important for the program to be terminated right away instead of continuing under invalid assumptions. +) + +$(P +The two implicit assumptions of $(C averageAge()) above may be spelled out by two $(C assert) calls as in the following function: +) + +--- +double averageAge(double first, double second) { + assert(first >= 0); + assert(second >= 0); + + return (first + second) / 2; +} + +void main() { + auto result = averageAge($(HILITE -1), 10); +} +--- + +$(P +Those $(C assert) checks carry the meaning "assuming that both of the ages are greater than or equal to zero". It can also be thought of as meaning "this function can work correctly only if both of the ages are greater than or equal to zero". +) + +$(P +Each $(C assert) checks its assumption and terminates the program with an $(C AssertError) when it is not valid: +) + +$(SHELL +core.exception.$(HILITE AssertError)@deneme(2): Assertion failure +) + +$(P +The part after the $(C @) character in the message indicates the source file and the line number of the $(C assert) check that failed. According to the output above, the $(C assert) that failed is on line 2 of file $(C deneme.d). +) + +$(P +The other syntax of $(C assert) allows printing a custom message when the $(C assert) check fails: +) + +--- + assert(first >= 0, "Age cannot be negative."); +--- + +$(P +The output: +) + +$(SHELL +core.exception.AssertError@deneme.d(2): $(HILITE Age cannot be negative.) +) + +$(P +Sometimes it is thought to be impossible for the program to ever enter a code path. In such cases it is common to use the literal $(C false) as the logical expression to fail an $(C assert) check. For example, to indicate that $(C applyCommand()) function is never expected to be called with a command other than "sing" and "dance", and to guard against such a possibility, an $(C assert(false)) can be inserted into the $(I impossible) branch: +) + +--- +void applyCommand(string command) { + if (command == "sing") { + robotSing(); + + } else if (command == "dance") { + robotDance(); + + } else { + $(HILITE assert(false)); + } +} +--- + +$(P +The function is guaranteed to work with the only two commands that it knows about. ($(I $(B Note:) An alternative choice here would be to use a $(LINK2 switch_case.html, $(C final switch) statement).)) +) + +$(H5 $(IX static assert) $(C static assert)) + +$(P +Since $(C assert) checks are for correct execution of programs, they are applied when the program is actually running. There can be other checks that are about the structure of the program, which can be applied even at compile time. +) + +$(P +$(C static assert) is the counterpart of $(C assert) that is applied at compile time. The advantage is that it does not allow even compiling a program that would have otherwise run incorrectly. A natural requirement is that it must be possible to evaluate the logical expression at compile time. +) + +$(P +For example, assuming that the title of a menu will be printed on an output device that has limited width, the following $(C static assert) ensures that it will never be wider than that limit: +) + +--- + enum dstring menuTitle = "Command Menu"; + static assert(menuTitle.length <= 16); +--- + +$(P +Note that the string is defined as $(C enum) so that its length can be evaluated at compile time. +) + +$(P +Let's assume that a programmer changes that title to make it more descriptive: +) + +--- + enum dstring menuTitle = "Directional Commands Menu"; + static assert(menuTitle.length <= 16); +--- + +$(P +The $(C static assert) check prevents compiling the program: +) + +$(SHELL +Error: static assert (25u <= 16u) is false +) + +$(P +This would remind the programmer of the limitation of the output device. +) + +$(P +$(C static assert) is even more useful when used in templates. We will see templates in later chapters. +) + +$(H5 $(C assert) even if $(I absolutely true)) + +$(P +I emphasize "absolutely true" because assumptions about the program are never expected to be false anyway. A large set of program errors are caused by assumptions that are thought to be absolutely true. +) + +$(P +For that reason, take advantage of $(C assert) checks even if they feel unnecessary. Let's look at the following function that returns the days of months in a given year: +) + +--- +int[] monthDays(int year) { + int[] days = [ + 31, februaryDays(year), + 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + ]; + + assert((sum(days) == 365) || + (sum(days) == 366)); + + return days; +} +--- + +$(P +That $(C assert) check may be seen as unnecessary because the function would naturally return either 365 or 366. However, those checks are guarding against potential mistakes even in the $(C februaryDays()) function. For example, the program would be terminated if $(C februaryDays()) returned 30. +) + +$(P +Another seemingly unnecessary check can ensure that the length of the slice would always be 12: +) + +--- + assert(days.length == 12); +--- + +$(P +That way, deleting or adding elements to the slice unintentionally would also be caught. Such checks are important tools toward program correctness. +) + +$(P +$(C assert) is also the fundamental tool that is used in $(I unit testing) and $(I contract programming), both of which will be covered in later chapters. +) + +$(H5 No value nor side effect) + +$(P +We have seen that expressions produce values or make side effects. $(C assert) checks do not have values nor $(I should) they have any side effects. +) + +$(P +The D language requires that the evaluation of the logical expression must not have any side effect. $(C assert) must remain as a passive observer of program state. +) + +$(H5 $(IX -release, compiler switch) Disabling $(C assert) checks) + +$(P +Since $(C assert) is about program correctness, they can be seen as unnecessary once the program has been tested sufficiently. Further, since $(C assert) checks produce no values nor they have side effects, removing them from the program should not make any difference. +) + +$(P +The compiler switch $(C -release) causes the $(C assert) checks to be ignored as if they have never been included in the program: +) + +$(SHELL +$ dmd deneme.d -release +) + +$(P +This would allow programs to run faster by not evaluating potentially slow logical expressions of the $(C assert) checks. +) + +$(P +As an exception, the $(C assert) checks that have the literal $(C false) (or 0) as the logical expression are not disabled even when the program is compiled with $(C ‑release). This is because $(C assert(false)) is for ensuring that a block of code is never reached, and that should be prevented even for the $(C ‑release) compilations. +) + +$(H5 $(C enforce) for throwing exceptions) + +$(P +Not every unexpected situation is an indication of a program error. Programs may also experience unexpected inputs and unexpected environmental state. For example, the data that is entered by the user should not be validated by an $(C assert) check because invalid data has nothing to do with the correctness of the program itself. In such cases it is appropriate to throw exceptions like we have been doing in previous programs. +) + +$(P +$(C std.exception.enforce) is a convenient way of throwing exceptions. For example, let's assume that an exception must be thrown when a specific condition is not met: +) + +--- + if (count < 3) { + throw new Exception("Must be at least 3."); + } +--- + +$(P +$(C enforce()) is a wrapper around the condition check and the $(C throw) statement. The following is the equivalent of the previous code: +) + +--- +import std.exception; +// ... + enforce(count >= 3, "Must be at least 3."); +--- + +$(P +Note how the logical expression is negated compared to the $(C if) statement. It now spells out what is being $(I enforced). +) + +$(H5 How to use) + +$(P +$(C assert) is for catching programmer errors. The conditions that $(C assert) guards against in the $(C monthDays()) function and the $(C menuTitle) variable above are all about programmer mistakes. +) + +$(P +Sometimes it is difficult to decide whether to rely on an $(C assert) check or to throw an exception. The decision should be based on whether the unexpected situation is due to a problem with how the program has been coded. +) + +$(P +Otherwise, the program must throw an exception when it is not possible to accomplish a task. $(C enforce()) is expressive and convenient when throwing exceptions. +) + +$(P +Another point to consider is whether the unexpected situation can be remedied in some way. If the program can not do anything special, even by simply printing an error message about the problem with some input data, then it is appropriate to throw an exception. That way, callers of the code that threw the exception can catch it to do something special to recover from the error condition. +) + +$(PROBLEM_COK + +$(PROBLEM +The following program includes a number of $(C assert) checks. Compile and run the program to discover its bugs that are revealed by those $(C assert) checks. + +$(P +The program takes a start time and a duration from the user and calculates the end time by adding the duration to the start time: +) + +$(SHELL +10 hours and 8 minutes after 06:09 is 16:17. +) + +$(P +Note that this problem can be written in a much cleaner way by defining $(C struct) types. We will refer to this program in later chapters. +) + +--- +import std.stdio; +import std.string; +import std.exception; + +/* Reads the time as hour and minute after printing a + * message. */ +void readTime(string message, + out int hour, + out int minute) { + write(message, "? (HH:MM) "); + + readf(" %s:%s", &hour, &minute); + + enforce((hour >= 0) && (hour <= 23) && + (minute >= 0) && (minute <= 59), + "Invalid time!"); +} + +/* Returns the time in string format. */ +string timeToString(int hour, int minute) { + assert((hour >= 0) && (hour <= 23)); + assert((minute >= 0) && (minute <= 59)); + + return format("%02s:%02s", hour, minute); +} + +/* Adds duration to start time and returns the result as the + * third pair of parameters. */ +void addDuration(int startHour, int startMinute, + int durationHour, int durationMinute, + out int resultHour, out int resultMinute) { + resultHour = startHour + durationHour; + resultMinute = startMinute + durationMinute; + + if (resultMinute > 59) { + ++resultHour; + } +} + +void main() { + int startHour; + int startMinute; + readTime("Start time", startMinute, startHour); + + int durationHour; + int durationMinute; + readTime("Duration", durationHour, durationMinute); + + int endHour; + int endMinute; + addDuration(startHour, startMinute, + durationHour, durationMinute, + endHour, endMinute); + + writefln("%s hours and %s minutes after %s is %s.", + durationHour, durationMinute, + timeToString(startHour, startMinute), + timeToString(endHour, endMinute)); +} +--- + +$(P +Run the program and enter $(C 06:09) as the start time and $(C 1:2) as the duration. Observe that the program terminates normally. +) + +$(P $(I $(B Note:) You may notice a problem with the output. Ignore that problem for now as you will discover it by the help of $(C assert) checks soon.) +) + +) + +$(PROBLEM +This time enter $(C 06:09) and $(C 15:2). Observe that the program is terminated by an $(C AssertError). Go to the line of the program that is indicated in the assert message and see which one of the $(C assert) checks have failed. It may take a while to discover the cause of this particular failure. +) + +$(PROBLEM +Enter $(C 06:09) and $(C 20:0) and observe that the same $(C assert) check still fails and fix that bug as well. +) + +$(PROBLEM +Modify the program to print the times in 12-hour format with an "am" or "pm" indicator. +) + +) + +Macros: + TITLE=assert and enforce + + DESCRIPTION=assert checks for program correctness, enforce() for throwing exception conveniently, and their differences. + + KEYWORDS=d programming language tutorial book assert enforce diff --git a/book/d.en/assignment.cozum.d b/book/d.en/assignment.cozum.d new file mode 100644 index 0000000000..5bd8889ee0 --- /dev/null +++ b/book/d.en/assignment.cozum.d @@ -0,0 +1,25 @@ +Ddoc + +$(COZUM_BOLUMU Assignment and Order of Evaluation) + +$(P +The values of $(C a), $(C b), and $(C c) are printed on the right-hand side of each operation. The value that changes at every operation is highlighted: +) + +$(MONO +at the beginning → a 1, b 2, c irrelevant +c = a → a 1, b 2, $(HILITE c 1) +a = b → $(HILITE a 2), b 2, c 1 +b = c → a 2, $(HILITE b 1), c 1 +) + +$(P +At the end, the values of $(C a) and $(C b) have been swapped. +) + +Macros: + TITLE=Assignment and Order of Evaluation Solutions + + DESCRIPTION=Assignment and Order of Evaluation chapter exercise solutions + + KEYWORDS=programming in d tutorial assignment and order of evaluation exercise solution diff --git a/book/d.en/assignment.d b/book/d.en/assignment.d new file mode 100644 index 0000000000..2817694af7 --- /dev/null +++ b/book/d.en/assignment.d @@ -0,0 +1,82 @@ +Ddoc + +$(DERS_BOLUMU Assignment and Order of Evaluation) + +$(P +The first two difficulties that most students face when learning to program involve the assignment operation and the order of evaluation. +) + +$(H5 The assignment operation) + +$(P +You will see lines similar to the following in almost every program in almost every programming language: +) + +--- + a = 10; +--- + +$(P +The meaning of that line is "make $(C a)'s value become 10". Similarly, the following line means "make $(C b)'s value become 20": +) + +--- + b = 20; +--- + +$(P +Based on that information, what can be said about the following line? +) + +--- + a = b; +--- + +$(P +Unfortunately, that line is not about the equality concept of mathematics that we all know. The expression above $(B does not) mean "a is equal to b"! When we apply the same logic from the earlier two lines, the expression above must mean "make $(C a)'s value become the same as $(C b)'s value". +) + +$(P +The well-known $(C =) symbol of mathematics has a completely different meaning in programming: make the left side's value the same as the right side's value. +) + +$(H5 Order of evaluation) + +$(P +In general, the operations of a program are applied step by step in the order that they appear in the program. (There are exceptions to this rule, which we will see in later chapters.) We may see the previous three expressions in a program in the following order: +) + +--- + a = 10; + b = 20; + a = b; +--- + +$(P +The meaning of those three lines altogether is this: "make $(C a)'s value become 10, $(I then) make $(C b)'s value become 20, $(I then) make $(C a)'s value become the same as $(C b)'s value". Accordingly, after those three operations are performed, the value of both $(C a) and $(C b) would be 20. +) + +$(PROBLEM_TEK + +$(P +Observe that the following three operations swap the values of $(C a) and $(C b). If at the beginning their values are 1 and 2 respectively, after the operations the values become 2 and 1: +) + +--- + c = a; + a = b; + b = c; +--- + +) + +$(Ergin) + +Macros: + TITLE=Assignment and Order of Evaluation + + DESCRIPTION=The very first two hurdles that a student faces when learning to program + + KEYWORDS=d programming language tutorial book + +MINI_SOZLUK= diff --git a/book/d.en/auto_and_typeof.cozum.d b/book/d.en/auto_and_typeof.cozum.d new file mode 100644 index 0000000000..4eb5d16682 --- /dev/null +++ b/book/d.en/auto_and_typeof.cozum.d @@ -0,0 +1,30 @@ +Ddoc + +$(COZUM_BOLUMU $(C auto) and $(C typeof)) + +$(P +We can use $(C typeof) to determine the type of the literal and $(C .stringof) to get the name of that type as $(C string): +) + +--- +import std.stdio; + +void main() { + writeln(typeof(1.2).stringof); +} +--- + +$(P +The output: +) + +$(SHELL +double +) + +Macros: + TITLE=auto and typeof Solutions + + DESCRIPTION=auto and typeof chapter solutions + + KEYWORDS=programming in d tutorial files diff --git a/book/d.en/auto_and_typeof.d b/book/d.en/auto_and_typeof.d new file mode 100644 index 0000000000..ecbfab4ea8 --- /dev/null +++ b/book/d.en/auto_and_typeof.d @@ -0,0 +1,97 @@ +Ddoc + +$(DERS_BOLUMU $(CH4 auto) and $(CH4 typeof)) + +$(H5 $(IX auto, variable) $(C auto)) + +$(P +When defining $(C File) variables in the previous chapter, we have repeated the name of the type on both sides of the $(C =) operator: +) + +--- + $(HILITE File) file = $(HILITE File)("student_records", "w"); +--- + +$(P +It feels redundant. It would also be cumbersome and especially error-prone if the type name were longer: +) + +--- + VeryLongTypeName var = VeryLongTypeName(/* ... */); +--- + +$(P +Fortunately, the type name on the left-hand side is not necessary because the compiler can infer the type of the left-hand side from the expression on the right-hand side. For the compiler to infer the type, the $(C auto) keyword can be used: +) + +--- + $(HILITE auto) var = VeryLongTypeName(/* ... */); +--- + +$(P +$(C auto) can be used with any type even when the type is not spelled out on the right-hand side: +) + +--- + auto duration = 42; + auto distance = 1.2; + auto greeting = "Hello"; + auto vehicle = BeautifulBicycle("blue"); +--- + +$(P +Although "auto" is the abbreviation of $(I automatic), it does not come from $(I automatic type inference). It comes from $(I automatic storage class), which is a concept about the life times of variables. $(C auto) is used when no other specifier is appropriate. For example, the following definition does not use $(C auto): +) + +--- + immutable i = 42; +--- + +$(P +The compiler infers the type of $(C i) as $(C immutable int) above. (We will see $(C immutable) in a later chapter.) +) + +$(H5 $(IX typeof) $(C typeof)) + +$(P +$(C typeof) provides the type of an expression (including single variables, objects, literals, etc.) without actually evaluating that expression. +) + +$(P +The following is an example of how $(C typeof) can be used to specify a type without explicitly spelling it out: +) + +--- + int value = 100; // already defined as 'int' + + typeof(value) value2; // means "type of value" + typeof(100) value3; // means "type of literal 100" +--- + +$(P +The last two variable definitions above are equivalent to the following: +) + +--- + int value2; + int value3; +--- + +$(P +It is obvious that $(C typeof) is not needed in situations like above when the actual types are known. Instead, you would typically use it in more elaborate scenarios, where you want the type of your variables to be consistent with some other piece of code whose type can vary. This keyword is especially useful in $(LINK2 templates.html, templates) and $(LINK2 mixin.html, mixins), both of which will be covered in later chapters. +) + +$(PROBLEM_TEK + +$(P +As we have seen above, the type of literals like 100 is $(C int) (as opposed to $(C short), $(C long), or any other type). Write a program to determine the type of floating point literals like 1.2. $(C typeof) and $(C .stringof) would be useful in this program. +) + +) + +Macros: + TITLE=auto and typeof keywords + + DESCRIPTION=The 'auto' keyword which is commonly used for D's implicit type inference feature, and 'typeof' which yields type of expressions. + + KEYWORDS=d programming language tutorial book auto typeof diff --git a/book/d.en/bit_operations.cozum.d b/book/d.en/bit_operations.cozum.d new file mode 100644 index 0000000000..ff8485e603 --- /dev/null +++ b/book/d.en/bit_operations.cozum.d @@ -0,0 +1,84 @@ +Ddoc + +$(COZUM_BOLUMU Bit Operations) + +$(OL + +$(LI +It may be acceptable to use magic constants in such a short function. Otherwise, the code may get too complicated. + +--- +string dotted(uint address) { + return format("%s.%s.%s.%s", + (address >> 24) & 0xff, + (address >> 16) & 0xff, + (address >> 8) & 0xff, + (address >> 0) & 0xff); +} +--- + +$(P +Because the type is an unsigned type, the bits that are inserted into the value from the left-hand side will all have 0 values. For that reason, there is no need to mask the value that is shifted by 24 bits. Additionally, since shifting by 0 bits has no effect, that operation can be eliminated as well: +) + +--- +string dotted(uint address) { + return format("%s.%s.%s.%s", + address >> 24, + (address >> 16) & 0xff, + (address >> 8) & 0xff, + address & 0xff); +} +--- + +) + +$(LI +Each octet can be shifted to its proper position in the IPv4 address and then these expressions can be "$(I orred)": + +--- +uint ipAddress(ubyte octet3, // most significant octet + ubyte octet2, + ubyte octet1, + ubyte octet0) { // least significant octet + return + (octet3 << 24) | + (octet2 << 16) | + (octet1 << 8) | + (octet0 << 0); +} +--- + +) + +$(LI +The following method starts with a value where all of the bits are 1. First, the value is shifted to the right so that the upper bits become 0, and then it is shifted to the left so that the lower bits become 0: + +--- +uint mask(int lowestBit, int width) { + uint result = uint.max; + result >>= (uint.sizeof * 8) - width; + result <<= lowestBit; + return result; +} +--- + +$(P +$(C uint.max) is the value where all of the bits are 1. Alternatively, the calculation can start with the value that is the complement of 0, which is the same as $(C uint.max): +) + +--- + uint result = ~0; + // ... +--- + +) + +) + +Macros: + TITLE=Bit Operations Solutions + + DESCRIPTION=Bit Operations chapter exercise solutions + + KEYWORDS=programming in d tutorial bit operations exercise solution diff --git a/book/d.en/bit_operations.d b/book/d.en/bit_operations.d new file mode 100644 index 0000000000..debfa7943a --- /dev/null +++ b/book/d.en/bit_operations.d @@ -0,0 +1,1089 @@ +Ddoc + +$(DERS_BOLUMU $(IX bit operation) Bit Operations) + +$(P +This chapter covers operations on bits, the smallest data units. Bit operations are among the most fundamental features of microprocessors. +) + +$(P +System programmers must understand bit operations at least to use $(I flag) parameters correctly. +) + +$(H5 Representation of data at the lowest level) + +$(P +Programming languages are abstractions. A user type like $(C Student) defined in a programming language is not directly related to the internals of the computer. Programming languages are tools that help humans use the hardware without needing to know the details of the hardware. +) + +$(P +Although it is usually not necessary to deal with the hardware directly, it is helpful to understand how data is represented at hardware level. +) + +$(H6 $(IX transistor) Transistor) + +$(P +The processing abilities of modern electronic devices are mostly based on the electronic element called $(I the transistor). A significant ability of the transistor is that it can be controlled by other parts of the electronic circuit that the transistor is a part of. In a way, it allows the electronic circuit be aware of itself and be able to change its own state. +) + +$(H6 $(IX bit) Bit) + +$(P +The smallest unit of information is a bit. A bit can be represented by any two-state system (e.g. by a special arrangement of a few transistors of an electronic circuit). A bit can have one of two values: 0 or 1. In the computer's memory, the information that is stored in a bit persists until a new value is stored or until the energy source is disconnected. +) + +$(P +Computers do not provide direct access to bits. One reason is that doing so would complicate the design of the computer and as a consequence make the computer more expensive. Another reason is that there are not many concepts that can be represented by a single bit. +) + +$(H6 $(IX byte) Byte) + +$(P +A byte is a combination of 8 bits. The smallest unit of information that can be addressed uniquely is a byte. Computers read from or write to memory at least one byte at a time. +) + +$(P +For that reason, although it carries one bit of information ($(C false) or $(C true)), even $(C bool) must be implemented as one byte: +) + +--- + writefln("%s is %s byte(s)", bool.stringof, bool.sizeof); +--- + +$(SHELL_SMALL +bool is 1 byte(s) +) + +$(H6 $(IX register, CPU) Register) + +$(P +Data that are being operated on in a microprocessor are stored in registers. Registers provide very limited but very fast operations. +) + +$(P +The size of the registers depend on the architecture of the microprocessor. For example, 32-bit microprocessors commonly have 4-byte registers and 64-bit microprocessors commonly have 8-byte registers. The size of the registers determine how much information the microprocessor can process efficiently at a time and how many memory addresses that it can support. +) + +$(P +Every task that is achieved by a programming language ends up being executed by one or more registers of the microprocessor. +) + +$(H5 $(IX binary system) Binary number system) + +$(P +The decimal number system which is used in daily life consists of 10 numerals: 0123456789. In contrast, the binary number system which is used by computer hardware consists of 2 numerals: 0 and 1. This is a direct consequence of a bit consisting of two values. If bits had three values then the computers would use a number system based on three numerals. +) + +$(P +The digits of the decimal system are named incrementally as $(I ones), $(I tens), $(I hundreds), $(I thousands), etc. For example, the number 1023 can be expanded as in the following way: +) + +$(MONO +1023 == 1 count of thousand, no hundred, 2 counts of ten, and 3 counts of one +) + +$(P +Naturally, moving one digit to the left multiplies the value of that digit by 10: 1, 10, 100, 1000, etc. +) + +$(P +When the same rules are applied to a system that has two numerals, we arrive at the binary number system. The digits are named incrementally as $(I ones), $(I twos), $(I fours), $(I eights), etc. In other words, moving one digit to the left would multiply the value of that digit by 2: 1, 2, 4, 8, etc. For example, the $(I binary) number 1011 can be expanded as in the following way: +) + +$(MONO +1011 == 1 count of eight, no four, 1 count of two, and 1 count of one +) + +$(P +To make it easy to refer to digits, they are numbered from the rightmost digit to the leftmost digit, starting by 0. The following table lists the values of all of the digits of a 32-bit unsigned number in the binary system: +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Digit Value
    312,147,483,648
    301,073,741,824
    29536,870,912
    28268,435,456
    27134,217,728
    2667,108,864
    2533,554,432
    2416,777,216
    238,388,608
    224,194,304
    212,097,152
    201,048,576
    19524,288
    18262,144
    17131,072
    1665,536
    1532,768
    1416,384
    138,192
    124,096
    112,048
    101,024
    9512
    8256
    7128
    664
    532
    416
    38
    24
    12
    01
    + +$(P +The bits that have higher values are called the $(I upper) bits and the bits that have lower values are called the $(I lower) bits. +) + +$(P +Remembering from $(LINK2 literals.html, the Literals chapter) that binary literals are specified by the $(C 0b) prefix, the following program demonstrates how the value of a literal would correspond to the rows of the previous table: +) + +--- +import std.stdio; + +void main() { + // 1073741824 4 1 + // ↓ ↓ ↓ + int number = 0b_01000000_00000000_00000000_00000101; + writeln(number); +} +--- + +$(P +The output: +) + +$(SHELL_SMALL +1073741829 +) + +$(P +Note that the literal consists of only three nonzero bits. The value that is printed is the sum of the values that correspond to those bits from the previous table: 1073741824 + 4 + 1 == 1073741829. +) + +$(H6 $(IX sign bit) The $(I sign) bit of signed integer types) + +$(P +The uppermost bit of a signed type determines whether the value is positive or negative: +) + +--- + int number = 0b_$(HILITE 1)0000000_00000000_00000000_00000000; + writeln(number); +--- + +$(SHELL_SMALL +-2147483648 +) + +$(P +However, the uppermost bit is not entirely separate from the value. For example, as evidenced above, the fact that all of the other bits of the number being 0 does not mean that the value is -0. (In fact, -0 is not a valid value for integers.) I will not get into more detail in this chapter other than noting that this is due to the $(I twos complement) representation, which is used by D as well. +) + +$(P +What is important here is that 2,147,483,648; the highest value in the previous table, is only for unsigned integer types. The same experiment with $(C uint) would print that exact value: +) + +--- + $(HILITE uint) number = 0b_10000000_00000000_00000000_00000000; + writeln(number); +--- + +$(SHELL_SMALL +2147483648 +) + +$(P +Partly for that reason, unless there is a reason not to, bit operations must always be executed on unsigned types: $(C ubyte), $(C ushort), $(C uint), and $(C ulong). +) + +$(H5 $(IX hexadecimal system) Hexadecimal number system) + +$(P +As can be seen in the literals above, consisting only of 0s and 1s, the binary system may not be readable especially when the numbers are large. For that reason, the more readable hexadecimal system has been widely adopted especially in computer technologies. +) + +$(P +The hexadecimal system has 16 numerals. Since alphabets do not have more than 10 numerals, this system borrows 6 letters from the Latin alphabet and uses them along with regular numerals: 0123456789abcdef. The numerals a, b, c, d, e, and f have the values 10, 11, 12, 13, 14, and 15, respectively. The letters ABCDEF can be used as well. +) + +$(P +Similar to other number systems, the value of every digit is 16 times the value of the digit on its right-hand side: 1, 16, 256, 4096, etc. For example, the values of all of the digits of an 8-digit unsigned hexadecimal number are the following: +) + + + + + + + + + + +
    Digit Value
    7268,435,456
    616,777,216
    51,048,576
    465,536
    34,096
    2256
    116
    01
    + +$(P +Remembering that hexadecimal literals are specified by the $(C 0x) prefix, we can see how the values of the digits contribute to the overall value of a number: +) + +--- + // 1048576 4096 1 + // ↓ ↓ ↓ + uint number = 0x_0030_a00f; + writeln(number); +--- + +$(SHELL_SMALL +3186703 +) + +$(P +The value that is printed is by the contributions of all of the nonzero digits: 3 count of 1048576, $(C a) count of 4096, and $(C f) count of 1. Remembering that $(C a) represents 10 and $(C f) represents 15, the value is 3145728 + 40960 + 15 == 3186703. +) + +$(P +It is straightforward to convert between binary and hexadecimal numbers. In order to convert a hexadecimal number to binary, the digits of the hexadecimal number are converted to their binary representations individually. The corresponding representations in the three number systems are as in the following table: +) + + + + + + + + + + + + + + + + + + +
    Hexadecimal Binary Decimal
    000000
    100011
    200102
    300113
    401004
    501015
    601106
    701117
    810008
    910019
    a101010
    b101111
    c110012
    d110113
    e111014
    f111115
    + +$(P +For example, the hexadecimal number 0x0030a00f can be written in the binary form by converting its digits individually according to the previous table: +) + +--- + // hexadecimal: 0 0 3 0 a 0 0 f + uint binary = 0b_0000_0000_0011_0000_1010_0000_0000_1111; +--- + +$(P +Converting from binary to hexadecimal is the reverse: The digits of the binary number are converted to their hexadecimal representations four digits at a time. For example, here is how to write in hexadecimal the same binary value that we have used earlier: +) +--- + // binary: 0100 0000 0000 0000 0000 0000 0000 0101 + uint hexadecimal = 0x___4____0____0____0____0____0____0____5; +--- + +$(H5 Bit operations) + +$(P +After going over how values are represented by bits and how numbers are represented in binary and hexadecimal, we can now see operations that change values at bit-level. +) + +$(P +Because there is no direct access to individual bits, even though these operations are at bit-level, they affect at least 8 bits at a time. For example, for a variable of type $(C ubyte), a bit operation would be applied to all of the 8 bits of that variable. +) + +$(P +As the uppermost bit is the sign bit for signed types, I will ignore signed types and use only $(C uint) in the examples below. You can repeat these operations with $(C ubyte), $(C ushort), and $(C ulong); as well as $(C byte), $(C short), $(C int), and $(C long) as long as you remember the special meaning of the uppermost bit. +) + +$(P +Let's first define a function which will be useful later when examining how bit operators work. This function will print a value in binary, hexadecimal, and decimal systems: +) + +--- +import std.stdio; + +void print(uint number) { + writefln(" %032b %08x %10s", number, number, number); +} + +void main() { + print(123456789); +} +--- + +$(P +Here is the same value printed in the binary, hexadecimal, and decimal number systems: +) + +$(SHELL_SMALL + 00000111010110111100110100010101 075bcd15 123456789 +) + +$(H6 $(IX ~, bitwise complement) $(IX complement, bitwise operator) Complement operator: $(C ~)) + +$(P +$(I Not to be confused with the $(I binary) $(C ~) operator that is used for array concatenation, this is the unary $(C ~) operator.) +) + +$(P +This operator converts each bit of a value to its opposite: The bits that are 0 become 1, and the bits that are 1 become 0. +) + +--- + uint value = 123456789; + print(value); + writeln("~ --------------------------------"); + print($(HILITE ~)value); +--- + +$(P +The effect is obvious in the binary representation. Every bit has been reversed (under the dashed line): +) + +$(SHELL_SMALL + 00000111010110111100110100010101 075bcd15 123456789 +~ -------------------------------- + 11111000101001000011001011101010 f8a432ea 4171510506 +) + +$(P +Here is the summary of how the unary $(C ~) operator works: +) + +$(MONO +~0 → 1 +~1 → 0 +) + +$(H6 $(IX &, bitwise and) $(IX and, bitwise operator) $(I And) operator: $(C &)) + +$(P +$(C &) is a binary operator, written between two expressions. The microprocessor considers two corresponding bits of the two expressions separately from all of the other bits: Bits 31, 30, 29, etc. of the expressions are evaluated separately. The value of each resultant bit is 1 if both of the corresponding bits of the expressions are 1; 0 otherwise. +) + +--- + uint lhs = 123456789; + uint rhs = 987654321; + + print(lhs); + print(rhs); + writeln("& --------------------------------"); + print(lhs $(HILITE &) rhs); +--- + +$(P +The following output contains first the left-hand side expression (lhs) and then the right-hand side expression (rhs). The result of the $(C &) operation is under the dashed line: +) + +$(SHELL_SMALL + 00000111010110111100110100010101 075bcd15 123456789 + 00111010110111100110100010110001 3ade68b1 987654321 +& -------------------------------- + 00000010010110100100100000010001 025a4811 39471121 +) + +$(P +Note that the bits of the result that have the value 1 are the ones where the corresponding bits of the expressions are both 1. +) + +$(P +This operator is called the $(I and) operator because it produces 1 when both the left-hand side $(I and) the right-hand side bits are 1. Among the four possible combinations of 0 and 1 values, only the one where both of the values are 1 produces 1: +) + +$(MONO +0 & 0 → 0 +0 & 1 → 0 +1 & 0 → 0 +1 & 1 → 1 +) + +$(P +Observations: +) + +$(UL + +$(LI When one of the bits is 0, regardless of the other bit the result is always 0. Accordingly, "$(I anding) a bit by 0" means to clear that bit.) + +$(LI When one of the bits is 1, the result is the value of the other bit; $(I anding) by 1 has no effect.) + +) + +$(H6 $(IX |) $(IX or, bitwise operator) $(I Or) operator: $(C |)) + +$(P +$(C |) is a binary operator, written between two expressions. The microprocessor considers two corresponding bits of the two expressions separately from all of the other bits. The value of each resultant bit is 0 if both of the corresponding bits of the expressions are 0; 1 otherwise. +) + +--- + uint lhs = 123456789; + uint rhs = 987654321; + + print(lhs); + print(rhs); + writeln("| --------------------------------"); + print(lhs $(HILITE |) rhs); +--- + +$(SHELL_SMALL + 00000111010110111100110100010101 075bcd15 123456789 + 00111010110111100110100010110001 3ade68b1 987654321 +| -------------------------------- + 00111111110111111110110110110101 3fdfedb5 1071639989 +) + +$(P +Note that the bits of the result that have the value 0 are the ones where the corresponding bits of the expressions are both 0. When the corresponding bit in the left-hand side or in the right-hand side is 1, then the result is 1: +) + +$(MONO +0 | 0 → 0 +0 | 1 → 1 +1 | 0 → 1 +1 | 1 → 1 +) + +$(P +Observations: +) + +$(UL + +$(LI When one of the bits is 1, regardless of the other bit the result is always 1. Accordingly, "$(I orring) a bit by 1" means to set it.) + +$(LI When one of the bits is 0, the result is the value of the other bit; $(I orring) by 0 has no effect.) + +) + +$(H6 $(IX ^, bitwise exclusive or) $(IX xor, bitwise operator) $(IX exclusive or, bitwise operator) $(I Xor) operator: $(C ^)) + +$(P +$(I Xor) is the short for $(I exclusive or). This is a binary operator as well. It produces 1 if the corresponding bits of the two expressions are different: +) + +--- + uint lhs = 123456789; + uint rhs = 987654321; + + print(lhs); + print(rhs); + writeln("^ --------------------------------"); + print(lhs $(HILITE ^) rhs); +--- + +$(SHELL_SMALL + 00000111010110111100110100010101 075bcd15 123456789 + 00111010110111100110100010110001 3ade68b1 987654321 +^ -------------------------------- + 00111101100001011010010110100100 3d85a5a4 1032168868 +) + +$(P +Note that the bits of the result that have the value 1 are the ones where the corresponding bits of the expressions are different from each other. +) + +$(MONO +0 ^ 0 → 0 +0 ^ 1 → 1 +1 ^ 0 → 1 +1 ^ 1 → 0 +) + +$(P +Observation: +) + +$(UL +$(LI "$(I Xorring) a bit" with itself means to clear that bit.) +) + +$(P +Regardless of its value, $(I xorring) a variable with itself always produces 0: +) + +--- + uint value = 123456789; + + print(value ^ value); +--- + +$(SHELL_SMALL + 00000000000000000000000000000000 00000000 0 +) + +$(H6 $(IX >>) $(IX right shift, bitwise operator) Right-shift operator: $(C >>)) + +$(P +This operator shifts the bits of an expression by the specified number of bits to the right. The rightmost bits, which do not have room to shift into, get $(I dropped) from the value. For unsigned types, the leftmost bits are filled with zeros. +) + +$(P +The following example produces a result by shifting a value by two bits to the right: +) + +--- + uint value = 123456789; + print(value); + print(value $(HILITE >>) 2); +--- + +$(P +In the following output, I highlighted both the bits that are going to be lost due to dropping off from the right-hand side and the leftmost bits that get the value 0: +) + +$(SHELL_SMALL + 000001110101101111001101000101$(HILITE 01) 075bcd15 123456789 + $(HILITE 00)000001110101101111001101000101 01d6f345 30864197 +) + +$(P +Note that the bits that are not highlighted have been shifted two bit positions to the right. +) + +$(P +$(IX sign extension) The new bits that enter from the left-hand side are 0 only for unsigned types. For signed types, the value of the leftmost bits are determined by a process called $(I sign extension). Sign extension preserves the value of the sign bit of the original expression. The value of that bit is used for all of the bits that $(I enter) from the left. +) + +$(P +Let's see this effect on a value of a signed type where the sign bit is 1 (i.e. the value is negative): +) + +--- + $(HILITE int) value = 0x80010300; + print(value); + print(value >> 3); +--- + +$(P +Because the leftmost bit of the original value is 1, all of the new bits of the result are 1 as well: +) + +$(SHELL_SMALL + $(U 1)0000000000000010000001100000$(HILITE 000) 80010300 2147549952 + $(HILITE 111)10000000000000010000001100000 f0002060 4026540128 +) + +$(P +When the leftmost bit is 0, then all new bits are 0: +) + +--- + $(HILITE int) value = 0x40010300; + print(value); + print(value >> 3); +--- + +$(SHELL_SMALL + $(U 0)1000000000000010000001100000$(HILITE 000) 40010300 1073808128 + $(HILITE 000)01000000000000010000001100000 08002060 134226016 +) + +$(H6 $(IX >>>) $(IX unsigned right shift, bitwise operator) Unsigned right-shift operator: $(C >>>)) + +$(P +This operator works similarly to the regular right-shift operator. The difference is that the new leftmost bits are always 0 regardless of the type of the expression and the value of the leftmost bit: +) + +--- + int value = 0x80010300; + print(value); + print(value $(HILITE >>>) 3); +--- + +$(SHELL_SMALL + 10000000000000010000001100000$(HILITE 000) 80010300 2147549952 + $(HILITE 000)10000000000000010000001100000 10002060 268443744 +) + +$(H6 $(IX <<) $(IX left shift, bitwise operator) Left-shift operator: $(C <<)) + +$(P +This operator works as the reverse of the right-shift operator. The bits are shifted to the left: +) + +--- + uint value = 123456789; + print(value); + print(value $(HILITE <<) 4); +--- + +$(P +The bits on the left-hand side are lost and the new bits on the right-hand side are 0: +) + +$(SHELL_SMALL + $(HILITE 0000)0111010110111100110100010101 075bcd15 123456789 + 0111010110111100110100010101$(HILITE 0000) 75bcd150 1975308624 +) + +$(H6 $(IX assignment, operation result) Operators with assignment) + +$(P +All of the binary operators above have assignment counterparts: $(C &=), $(C |=), $(C ^=), $(C >>=), $(C >>>=), and $(C <<=). Similar to the operators that we saw in $(LINK2 arithmetic.html, the Integers and Arithmetic Operations chapter), these operators assign the result back to the left-hand operand. +) + +$(P +Let's see this on the $(C &=) operator: +) + +--- + value = value & 123; + value &= 123; // the same as above +--- + +$(H5 Semantics) + +$(P +Merely understanding how these operators work at bit-level may not be sufficient to see how they are useful in programs. The following sections describe common ways that these operators are used in. +) + +$(H6 $(C |) is a union set) + +$(P +The $(C |) operator produces the union of the 1 bits in the two expressions. +) + +$(P +As an extreme example, let's consider two values that both have alternating bits set to 1. The union of these values would produce a result where all of the bits are 1: +) + +--- + uint lhs = 0xaaaaaaaa; + uint rhs = 0x55555555; + + print(lhs); + print(rhs); + writeln("| --------------------------------"); + print(lhs | rhs); +--- + +$(SHELL_SMALL + 10101010101010101010101010101010 aaaaaaaa 2863311530 + 01010101010101010101010101010101 55555555 1431655765 +| -------------------------------- + 11111111111111111111111111111111 ffffffff 4294967295 +) + +$(H6 $(C &) is an intersection set) + +$(P +The $(C &) operator produces the intersection of the 1 bits in the two expressions. +) + +$(P +As an extreme example, let's consider the last two values again. Since none of the 1 bits of the previous two expressions match the ones in the other expression, all of the bits of the result are 0: +) + +--- + uint lhs = 0xaaaaaaaa; + uint rhs = 0x55555555; + + print(lhs); + print(rhs); + writeln("& --------------------------------"); + print(lhs & rhs); +--- + +$(SHELL_SMALL + 10101010101010101010101010101010 aaaaaaaa 2863311530 + 01010101010101010101010101010101 55555555 1431655765 +& -------------------------------- + 00000000000000000000000000000000 00000000 0 +) + +$(H6 $(C |=) sets selected bits to 1) + +$(P +To understand how this works, it helps to see one of the expressions as the $(I actual) expression and the other expression as a $(I selector) for the bits to set to 1: +) + +--- + uint expression = 0x00ff00ff; + uint bitsToSet = 0x10001000; + + write("before :"); print(expression); + write("to set to 1:"); print(bitsToSet); + + expression $(HILITE |=) bitsToSet; + write("after :"); print(expression); +--- + +$(P +The before and after values of the bits that are affected are highlighted: +) + +$(SHELL_SMALL +before : 000$(HILITE 0)000011111111000$(HILITE 0)000011111111 00ff00ff 16711935 +to set to 1: 00010000000000000001000000000000 10001000 268439552 +after : 000$(HILITE 1)000011111111000$(HILITE 1)000011111111 10ff10ff 285151487 +) + +$(P +In a sense, $(C bitsToSet) determines which bits to set to 1. The other bits are not affected. +) + +$(H6 $(C &=) clears selected bits) + +$(P +One of the expressions can be seen as the $(I actual) expression and the other expression can be seen as a $(I selector) for the bits to clear (to set to 0): +) + +--- + uint expression = 0x00ff00ff; + uint bitsToClear = 0xffefffef; + + write("before :"); print(expression); + write("bits to clear:"); print(bitsToClear); + + expression $(HILITE &=) bitsToClear; + write("after :"); print(expression); +--- + +$(P +The before and after values of the bits that are affected are highlighted: +) + +$(SHELL_SMALL +before : 00000000111$(HILITE 1)111100000000111$(HILITE 1)1111 00ff00ff 16711935 +bits to clear: 11111111111011111111111111101111 ffefffef 4293918703 +after : 00000000111$(HILITE 0)111100000000111$(HILITE 0)1111 00ef00ef 15663343 +) + +$(P +In a sense, $(C bitsToClear) determines which bits to set to 0. The other bits are not affected. +) + +$(H6 $(C &) determines whether a bit is 1 or not) + +$(P +If one of the expressions has only one bit set to 1, then it can be used to query whether the corresponding bit of the other expression is 1: +) + +--- + uint expression = 123456789; + uint bitToQuery = 0x00010000; + + print(expression); + print(bitToQuery); + writeln(expression $(HILITE &) bitToQuery ? "yes, 1" : "not 1"); +--- + +$(P +The bit that is being $(I queried) is highlighted: +) + +$(SHELL_SMALL + 000001110101101$(HILITE 1)1100110100010101 075bcd15 123456789 + 00000000000000010000000000000000 00010000 65536 +yes, 1 +) + +$(P +Let's query another bit of the same expression by this time having another bit of $(C bitToQuery) set to 1: +) + +--- + uint bitToQuery = 0x00001000; +--- + +$(SHELL_SMALL +0000011101011011110$(HILITE 0)110100010101 075bcd15 123456789 +00000000000000000001000000000000 00001000 4096 +not 1 +) + +$(P +When the query expression has more than one bit set to 1, then the query would determine whether $(I any) of the corresponding bits in the other expression are 1. +) + +$(H6 Right-shifting by one is the equivalent of dividing by two) + +$(P +Shifting all of the bits of a value by one position to the right produces half of the original value. The reason for this can be seen in the digit-value table above: In that table, every bit has half the value of the bit that is on its left. +) + +$(P +Shifting a value to the right multiple bits at a time means dividing by 2 for that many times. For example, right-shifting by 3 bits would divide a value by 8: +) + +--- + uint value = 8000; + + writeln(value >> 3); +--- + +$(SHELL_SMALL +1000 +) + +$(P +According to how the $(I twos complement) system works, right-shifting has the same effect on signed values: +) + +--- + $(HILITE int) value = -8000; + + writeln(value >> 3); +--- + +$(SHELL_SMALL +-1000 +) + +$(H6 Left-shifting by one is the equivalent of multiplying by two) + +$(P +Because each bit is two times the value of the bit on its right, shifting a value one bit to the left means multiplying that value by two: +) + +--- + uint value = 10; + + writeln(value << 5); +--- + +$(P +Multiplying by 2 a total of 5 times is the same as multiplying by 32: +) + +$(SHELL_SMALL +320 +) + +$(H5 Common uses) + +$(H6 $(IX flag, bit) Flags) + +$(P +Flags are single-bit independent data that are kept together in the same variable. As they are only one bit wide each, they are suitable for representing binary concepts like enabled/disabled, valid/invalid, etc. +) + +$(P +Such one-bit concepts are sometimes encountered in D modules that are based on C libraries. +) + +$(P +Flags are usually defined as non-overlapping values of an $(C enum) type. +) + +$(P +As an example, let's consider a car racing game where the realism of the game is configurable: +) + +$(UL +$(LI The fuel consumption is realistic or not.) +$(LI Collisions can damage the cars or not.) +$(LI Tires can deteriorate by use or not.) +$(LI Skid marks are left on the road surface or not.) +) + +$(P +These configuration options can be specified at run time by the following $(C enum) values: +) + +--- +enum Realism { + fuelUse = 1 << 0, + bodyDamage = 1 << 1, + tireUse = 1 << 2, + skidMarks = 1 << 3 +} +--- + +$(P +Note that all of those values consist of single bits that do not conflict with each other. Each value is determined by left-shifting 1 by a different number of bits. The corresponding bit representations are the following: +) + +$(MONO +fuelUse : 0001 +bodyDamage: 0010 +tireUse : 0100 +skidMarks : 1000 +) + +$(P +Since their 1 bits do not match others', these values can be combined by the $(C |) operator to be kept in the same variable. For example, the two configuration options that are related to tires can be combined as in the following code: +) + +--- + Realism flags = Realism.tireUse | Realism.skidMarks; + writefln("%b", flags); +--- + +$(P +The bits of these two flags would be side-by-side in the variable $(C flags): +) + +$(SHELL_SMALL +1100 +) + +$(P +Later, these flags can be queried by the $(C &) operator: +) + +--- + if (flags & Realism.fuelUse) { + // ... code related to fuel consumption ... + } + + if (flags & Realism.tireUse) { + // ... code related to tire consumption ... + } +--- + +$(P +The $(C &) operator produces 1 only if the specified flag is set in $(C flags). +) + +$(P +Also note that the result is usable in the $(C if) condition due to automatic conversion of the nonzero value to $(C true). The conditional expression is $(C false) when the result of $(C &) is 0 and $(C true) otherwise. As a result, the corresponding code block is executed only if the flag is enabled. +) + +$(H6 $(IX mask, bit) Masking) + +$(P +In some libraries and some protocols an integer value may carry more than one piece of information. For example, the upper 3 bits of a 32-bit value may have a certain meaning, while the lower 29 bits may have another meaning. These separate parts of data can be extracted from the variable by masking. +) + +$(P +The four octets of an IPv4 address are an example of this concept. The octets are the individual values that make up the common dotted representation of an IPv4 address. They are all kept in a single 32-bit value. For example, the IPv4 address 192.168.1.2 is the 32-bit value 0xc0a80102: +) + +$(MONO +c0 == 12 * 16 + 0 = 192 +a8 == 10 * 16 + 8 = 168 +01 == 0 * 16 + 1 = 1 +02 == 0 * 16 + 2 = 2 +) + +$(P +A mask consists of a number of 1 bits that would $(I cover) the specific part of a variable. $(I "And"ing) the value by the mask extracts the part of the variable that is covered by that mask. For example, the mask value of 0x000000ff would cover the lower 8 bits of a value: +) + +--- + uint value = 123456789; + uint mask = 0x000000ff; + + write("value :"); print(value); + write("mask :"); print(mask); + write("result:"); print(value & mask); +--- + +$(P +The bits that are covered by the mask are highlighted. All of the other bits are cleared: +) + +$(SHELL_SMALL +value : 000001110101101111001101$(HILITE 00010101) 075bcd15 123456789 +mask : 00000000000000000000000011111111 000000ff 255 +result: 000000000000000000000000$(HILITE 00010101) 00000015 21 +) + +$(P +Let's apply the same method to the 0xc0a80102 IPv4 address with a mask that would cover the uppermost 8 bits: +) + +--- + uint value = 0xc0a80102; + uint mask = 0xff000000; + + write("value :"); print(value); + write("mask :"); print(mask); + write("result:"); print(value & mask); +--- + +$(P +This mask covers the uppermost 8 bits of the value: +) + +$(SHELL_SMALL +value : $(HILITE 11000000)101010000000000100000010 c0a80102 3232235778 +mask : 11111111000000000000000000000000 ff000000 4278190080 +result: $(HILITE 11000000)000000000000000000000000 c0000000 3221225472 +) + +$(P +However, note that the printed result is not the expected 192 but 3221225472. That is because the masked value must also be shifted all the way to the right-hand side. Shifting the value 24 bit positions to the right would produce the value that those 8 bits represent: +) + +--- + uint value = 0xc0a80102; + uint mask = 0xff000000; + + write("value :"); print(value); + write("mask :"); print(mask); + write("result:"); print((value & mask) $(HILITE >> 24)); +--- + +$(SHELL_SMALL +value : $(HILITE 11000000)101010000000000100000010 c0a80102 3232235778 +mask : 11111111000000000000000000000000 ff000000 4278190080 +result: 000000000000000000000000$(HILITE 11000000) 000000c0 $(HILITE 192) +) + +$(PROBLEM_COK + +$(PROBLEM +Write a function that returns an IPv4 address in its dotted form: + +--- +string dotted(uint address) { + // ... +} + +unittest { + assert(dotted(0xc0a80102) == "192.168.1.2"); +} +--- + +) + +$(PROBLEM +Write a function that converts four octet values to the corresponding 32-bit IPv4 address: + +--- +uint ipAddress(ubyte octet3, // most significant octet + ubyte octet2, + ubyte octet1, + ubyte octet0) { // least significant octet + // ... +} + +unittest { + assert(ipAddress(192, 168, 1, 2) == 0xc0a80102); +} +--- + +) + +$(PROBLEM +Write a function that can be used for making a mask. It should start with the specified bit and have the specified width: + +--- +uint mask(int lowestBit, int width) { + // ... +} + +unittest { + assert(mask(2, 5) == + 0b_0000_0000_0000_0000_0000_0000_0111_1100); + // ↑ + // lowest bit is 2, + // and the mask is 5-bit wide +} +--- + +) + +) + +Macros: + TITLE=Bit Operations + + DESCRIPTION=The low-level features of D that allow manipulating values at bit-level. + + KEYWORDS=d programming language tutorial book bit operations diff --git a/book/d.en/blurbs.d b/book/d.en/blurbs.d new file mode 100644 index 0000000000..aeefb624f9 --- /dev/null +++ b/book/d.en/blurbs.d @@ -0,0 +1,42 @@ +Ddoc + +$(COMMENTED_OUT + + +"Ali's explanations are succinct and on target. I like that he provides rationale for why D was designed in a particular way and how I can use it most effectively. This is the best computer language book I've read." -- Robbin Carlson, Luthier and Enterprise Architect + + + +“I have been using Ali’s online D book to teach D at the university level. It is up-to-date, complete, and most importantly, extremely readable. Having a print version is even better! This is now the 'go-to’ book for learning D programming.” -- Chuck Allison, Professor and Chair, Computer Science Department, Utah Valley University + + + +"This book is one of the best guides through the language that I've seen." -- Andrew Wray, D Enthusiast + +(w0rp devw0rp@gmail.com) +http://forum.dlang.org/thread/lqqf2l$b1u$1@digitalmars.com#post-rngxsnyvdkererhdtmhh:40forum.dlang.org + + + +"I encourage anyone considering D to read this book. Not exactly "D for Dummies" but it's easy to follow even if you don't have much experience with compiled languages." -- bachmeier, Reddit user + + + +"Having worked through the book, I have to say this is one of the easiest to follow and distraction free read there is and the fact that it made learning a new language a total breeze really impressed me." -- Imran Khan, Student + +imrankhan4587@gmail.com +http://www.reddit.com/r/programming/comments/2bl51j/programming_in_d_a_great_online_book_for_learning/cj6qveg + + + + +"I taught a CS2 Data Structures class in D with more success and student appreciation than when using either C++ or Java as it's an ideal language to express the relevant concepts at all scales, from detailed to big picture, without needless complexity. + +Ali Çehreli's tutorial played a central role supporting students especially during the first half of the course --- without it the course simply would not have worked, so "many thanks Ali" --- and an important part of that is its linearity --- it can be read with only backward dependencies. This meant that with hard work even students of little experience and only moderate current abilities could get up to speed, and we saw just that. It is hard to overstate this factor. I unreservedly recommend this book to all." -- Dr. Carl Sturtivant, University of Minnesota Department of Computer Science & Engineering + + + +"D is pristine, clean, immensely powerful, and arguably the actual state-of-the-art programming language. Ali's book is a gem. Clear, concise, and complete." -- Olivier Henley + + +) diff --git a/book/d.en/breadcrumbs.ddoc b/book/d.en/breadcrumbs.ddoc new file mode 100644 index 0000000000..a5255d4178 --- /dev/null +++ b/book/d.en/breadcrumbs.ddoc @@ -0,0 +1,4 @@ + +BREADCRUMBS_INDEX=$(LINK2 index.html, Main Page) > $(LINK2 ders/index.html, Books) > Prg in D + +BREADCRUMBS_FULL=$(LINK2 index.html, Main Page) > $(LINK2 ders/index.html, Books) > $(LINK2 index.html, Prg in D) diff --git a/book/d.en/cast.d b/book/d.en/cast.d new file mode 100644 index 0000000000..4dc5c1fca9 --- /dev/null +++ b/book/d.en/cast.d @@ -0,0 +1,715 @@ +Ddoc + +$(DERS_BOLUMU $(IX type conversion) $(IX conversion, type) Type Conversions) + +$(P +Variables must be compatible with the expressions that they take part in. As it has probably been obvious from the programs that we have seen so far, D is a $(I statically typed language), meaning that the compatibility of types is validated at compile time. +) + +$(P +All of the expressions that we have written so far always had compatible types because otherwise the code would be rejected by the compiler. The following is an example of code that has incompatible types: +) + +--- + char[] slice; + writeln(slice + 5); $(DERLEME_HATASI) +--- + +$(P +The compiler rejects the code due to the incompatible types $(C char[]) and $(C int) for the addition operation: +) + +$(SHELL +Error: $(HILITE incompatible types) for ((slice) + (5)): 'char[]' and 'int' +) + +$(P +Type incompatibility does not mean that the types are different; different types can indeed be used in expressions safely. For example, an $(C int) variable can safely be used in place of a $(C double) value: +) + +--- + double sum = 1.25; + int increment = 3; + sum += increment; +--- + +$(P +Even though $(C sum) and $(C increment) are of different types, the code above is valid because incrementing a $(C double) variable by an $(C int) value is legal. +) + +$(H5 $(IX automatic type conversion) $(IX implicit type conversion) Automatic type conversions) + +$(P +Automatic type conversions are also called $(I implicit type conversions). +) + +$(P +Although $(C double) and $(C int) are compatible types in the expression above, the addition operation must still be evaluated as a specific type at the microprocessor level. As you would remember from the $(LINK2 floating_point.html, Floating Point Types chapter), the 64-bit type $(C double) is $(I wider) (or $(I larger)) than the 32-bit type $(C int). Additionally, any value that fits in an $(C int) also fits in a $(C double). +) + +$(P +When the compiler encounters an expression that involves mismatched types, it first converts the parts of the expressions to a common type and then evaluates the overall expression. The automatic conversions that are performed by the compiler are in the direction that avoids data loss. For example, $(C double) can hold any value that $(C int) can hold but the opposite is not true. The $(C +=) operation above can work because any $(C int) value can safely be converted to $(C double). +) + +$(P +The value that has been generated automatically as a result of a conversion is always an anonymous (and often temporary) variable. The original value does not change. For example, the automatic conversion during $(C +=) above does not change the type of $(C increment); it is always an $(C int). Rather, a temporary value of type $(C double) is constructed with the value of $(C increment). The conversion that takes place in the background is equivalent to the following code: +) + +--- + { + double $(I an_anonymous_double_value) = increment; + sum += $(I an_anonymous_double_value); + } +--- + +$(P +The compiler converts the $(C int) value to a temporary $(C double) value and uses that value in the operation. In this example, the temporary variable lives only during the $(C +=) operation. +) + +$(P +Automatic conversions are not limited to arithmetic operations. There are other cases where types are converted to other types automatically. As long as the conversions are valid, the compiler takes advantage of type conversions to be able to use values in expressions. For example, a $(C byte) value can be passed for an $(C int) parameter: +) + +--- +void func(int number) { + // ... +} + +void main() { + byte smallValue = 7; + func(smallValue); // automatic type conversion +} +--- + +$(P +In the code above, first a temporary $(C int) value is constructed and the function is called with that value. +) + +$(H6 $(IX integer promotion) $(IX promotion, integer) Integer promotions) + +$(P +Values of types that are on the left-hand side of the following table never take part in arithmetic expressions as their actual types. Each type is first promoted to the type that is on the right-hand side of the table. +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    From To
    boolint
    byteint
    ubyteint
    shortint
    ushortint
    charint
    wcharint
    dcharuint
    + +$(P +Integer promotions are applied to $(C enum) values as well. +) + +$(P +The reasons for integer promotions are both historical (where the rules come from C) and the fact that the natural arithmetic type for the microprocessor is $(C int). For example, although the following two variables are both $(C ubyte), the addition operation is performed only after both of the values are individually promoted to $(C int): +) + +--- + ubyte a = 1; + ubyte b = 2; + writeln(typeof(a + b).stringof); // the addition is not in ubyte +--- + +$(P +The output: +) + +$(SHELL +int +) + +$(P +Note that the types of the variables $(C a) and $(C b) do not change; only their values are temporarily promoted to $(C int) for the duration of the addition operation. +) + +$(H6 $(IX arithmetic conversion) Arithmetic conversions) + +$(P +There are other conversion rules that are applied for arithmetic operations. In general, automatic arithmetic conversions are applied in the safe direction: from the $(I narrower) type to the $(I wider) type. Although this rule is easy to remember and is correct in most cases, automatic conversion rules are very complicated and in the case of signed-to-unsigned conversions, carry some risk of bugs. +) + +$(P +The arithmetic conversion rules are the following: +) + +$(OL + +$(LI If one of the values is $(C real), then the other value is converted to $(C real)) + +$(LI Else, if one of the values is $(C double), then the other value is converted to $(C double)) + +$(LI Else, if one of the values is $(C float), then the other value is converted to $(C float)) + +$(LI Else, first $(I integer promotions) are applied according to the table above, and then the following rules are followed: + +$(OL +$(LI If both types are the same, then no more steps needed) +$(LI If both types are signed or both types are unsigned, then the narrower value is converted to the wider type) +$(LI If the signed type is wider than the unsigned type, then the unsigned value is converted to the signed type) +$(LI Otherwise the signed type is converted to the unsigned type) +) +) +) + +$(P +Unfortunately, the last rule above can cause subtle bugs: +) + +--- + int a = 0; + int b = 1; + size_t c = 0; + writeln(a - b + c); // Surprising result! +--- + +$(P +Surprisingly, the output is not -1, but $(C size_t.max): +) + +$(SHELL +18446744073709551615 +) + +$(P +Although one would expect $(C (0 - 1 + 0)) to be calculated as -1, according to the rules above, the type of the entire expression is $(C size_t), not $(C int); and since $(C size_t) cannot hold negative values, the result overflows and becomes $(C size_t.max). +) + +$(H6 Slice conversions) + +$(P +$(IX fixed-length array, conversion to slice) $(IX static array, conversion to slice) As a convenience, fixed-length arrays can automatically be converted to slices when calling a function: +) + +--- +import std.stdio; + +void foo() { + $(HILITE int[2]) array = [ 1, 2 ]; + bar(array); // Passes fixed-length array as a slice +} + +void bar($(HILITE int[]) slice) { + writeln(slice); +} + +void main() { + foo(); +} +--- + +$(P +$(C bar()) receives a slice to all elements of the fixed-length array and prints it: +) + +$(SHELL +[1, 2] +) + +$(P +$(B Warning:) A $(I local) fixed-length array must not be passed as a slice if the function stores the slice for later use. For example, the following program has a bug because the slice that $(C bar()) stores would not be valid after $(C foo()) exits: +) + +--- +import std.stdio; + +void foo() { + int[2] array = [ 1, 2 ]; + bar(array); // Passes fixed-length array as a slice + +} // ← NOTE: 'array' is not valid beyond this point + +int[] sliceForLaterUse; + +void bar(int[] slice) { + // Saves a slice that is about to become invalid + sliceForLaterUse = slice; + writefln("Inside bar : %s", sliceForLaterUse); +} + +void main() { + foo(); + + /* BUG: Accesses memory that is not array elements anymore */ + writefln("Inside main: %s", sliceForLaterUse); +} +--- + +$(P +The result of such a bug is undefined behavior. A sample execution can prove that the memory that used to be the elements of $(C array) has already been reused for other purposes: +) + +$(SHELL +Inside bar : [1, 2] $(SHELL_NOTE actual elements) +Inside main: [4396640, 0] $(SHELL_NOTE_WRONG a manifestation of undefined behavior) +) + +$(H6 $(C const) conversions) + +$(P +As we have seen earlier in the $(LINK2 function_parameters.html, Function Parameters chapter), reference types can automatically be converted to the $(C const) of the same type. Conversion to $(C const) is safe because the width of the type does not change and $(C const) is a promise to not modify the variable: +) + +--- +char[] parenthesized($(HILITE const char[]) text) { + return "{" ~ text ~ "}"; +} + +void main() { + $(HILITE char[]) greeting; + greeting ~= "hello world"; + parenthesized(greeting); +} +--- + +$(P +The mutable $(C greeting) above is automatically converted to a $(C const char[]) as it is passed to $(C parenthesized()). +) + +$(P +As we have also seen earlier, the opposite conversion is not automatic. A $(C const) reference is not automatically converted to a mutable reference: +) + +--- +char[] parenthesized(const char[] text) { + char[] argument = text; $(DERLEME_HATASI) +// ... +} +--- + +$(P +Note that this topic is only about references; since variables of value types are copied, it is not possible to affect the original through the copy anyway: +) + +--- + const int totalCorners = 4; + int theCopy = totalCorners; // compiles (value type) +--- + +$(P +The conversion from $(C const) to mutable above is legal because the copy is not a reference to the original. +) + +$(H6 $(C immutable) conversions) + +$(P +Because $(C immutable) specifies that a variable can never change, neither conversion from $(C immutable) nor to $(C immutable) are automatic: +) + +--- + string a = "hello"; // immutable characters + char[] b = a; $(DERLEME_HATASI) + string c = b; $(DERLEME_HATASI) +--- + +$(P +As with $(C const) conversions above, this topic is also only about reference types. Since variables of value types are copied anyway, conversions to and from $(C immutable) are valid: +) + +--- + immutable a = 10; + int b = a; // compiles (value type) +--- + +$(H6 $(C enum) conversions) + +$(P +As we have seen in the $(LINK2 enum.html, $(C enum) chapter), $(C enum) is for defining $(I named constants): +) + +--- + enum Suit { spades, hearts, diamonds, clubs } +--- + +$(P +Remember that since no values are specified explicitly above, the values of the $(C enum) members start with zero and are automatically incremented by one. Accordingly, the value of $(C Suit.clubs) is 3. +) + +$(P +$(C enum) values are atomatically converted to integral types. For example, the value of $(C Suit.hearts) is taken to be 1 in the following calculation and the result becomes 11: +) + +--- + int result = 10 + Suit.hearts; + assert(result == 11); +--- + +$(P +The opposite conversion is not automatic: Integer values are not automatically converted to corresponding $(C enum) values. For example, the $(C suit) variable below might be expected to become $(C Suit.diamonds), but the code cannot be compiled: +) + +--- + Suit suit = 2; $(DERLEME_HATASI) +--- + +$(P +As we will see below, conversions from integers to $(C enum) values are still possible but they must be explicit. +) + +$(H6 $(IX bool, automatic conversion) $(C bool) conversions) + +$(P +$(IX bool, 1-bit integer) $(IX 1-bit integer) $(IX one-bit integer) Although $(C bool) is the natural type of logical expressions, as it has only two values, it can be seen as a 1-bit integer and does behave like one in some cases. $(C false) and $(C true) are automatically converted to 0 and 1, respectively: +) + +--- + int a = false; + assert(a == 0); + + int b = true; + assert(b == 1); +--- + +$(P +Regarding $(I literal values), the opposite conversion is automatic only for two special literal values: 0 and 1 are converted automatically to $(C false) and $(C true), respectively: +) + +--- + bool a = 0; + assert(!a); // false + + bool b = 1; + assert(b); // true +--- + +$(P +Other literal values cannot be converted to $(C bool) automatically: +) + +--- + bool b = 2; $(DERLEME_HATASI) +--- + +$(P +Some statements make use of logical expressions: $(C if), $(C while), etc. For the logical expressions of such statements, not only $(C bool) but most other types can be used as well. The value zero is automatically converted to $(C false) and the nonzero values are automatically converted to $(C true). +) + +--- + int i; + // ... + + if (i) { // ← int value is being used as a logical expression + // ... 'i' is not zero + + } else { + // ... 'i' is zero + } +--- + +$(P +Similarly, $(C null) references are automatically converted to $(C false) and non-$(C null) references are automatically converted to $(C true). This makes it easy to ensure that a reference is non-$(C null) before actually using it: +) + +--- + int[] a; + // ... + + if (a) { // ← automatic bool conversion + // ... not null; 'a' can be used ... + + } else { + // ... null; 'a' cannot be used ... + } +--- + +$(H5 $(IX explicit type conversion) $(IX type conversion, explicit) Explicit type conversions) + +$(P +As we have seen above, there are cases where automatic conversions are not available: +) + +$(UL +$(LI Conversions from wider types to narrower types) +$(LI Conversions from $(C const) to mutable) +$(LI $(C immutable) conversions) +$(LI Conversions from integers to $(C enum) values) +$(LI etc.) +) + +$(P +If such a conversion is known to be safe, the programmer can explicitly ask for a type conversion by one of the following methods: +) + +$(UL +$(LI Construction syntax) +$(LI $(C std.conv.to) function) +$(LI $(C std.exception.assumeUnique) function) +$(LI $(C cast) operator) +) + +$(H6 $(IX construction, type conversion) Construction syntax) + +$(P +The $(C struct) and $(C class) construction syntax is available for other types as well: +) + +--- + $(I DestinationType)(value) +--- + +$(P +For example, the following $(I conversion) makes a $(C double) value from an $(C int) value, presumably to preserve the fractional part of the division operation: +) + +--- + int i; + // ... + const result = $(HILITE double(i)) / 2; +--- + +$(H6 $(IX to, std.conv) $(C to()) for most conversions) + +$(P +The $(C to()) function, which we have already used mostly to convert values to $(C string), can actually be used for many other types. Its complete syntax is the following: +) + +--- + to!($(I DestinationType))(value) +--- + +$(P +Being a template, $(C to()) can take advantage of the shortcut template parameter notation: When the destination type consists only of a single token (generally, $(I a single word)), it can be called without the first pair of parentheses: +) + +--- + to!$(I DestinationType)(value) +--- + +$(P +The following program is trying to convert a $(C double) value to $(C short) and a $(C string) value to $(C int): +) + +--- +void main() { + double d = -1.75; + + short s = d; $(DERLEME_HATASI) + int i = "42"; $(DERLEME_HATASI) +} +--- + +$(P +Since not every $(C double) value can be represented as a $(C short) and not every $(C string) can be represented as an $(C int), those conversions are not automatic. When it is known by the programmer that the conversions are in fact safe or that the potential consequences are acceptable, then the types can be converted by $(C to()): +) + +--- +import std.conv; + +void main() { + double d = -1.75; + + short s = to!short(d); + assert(s == -1); + + int i = to!int("42"); + assert(i == 42); +} +--- + +$(P +Note that because $(C short) cannot carry fractional values, the converted value is -1. +) + +$(P +$(C to()) is safe: It throws an exception when a conversion is not possible. +) + +$(H6 $(IX assumeUnique, std.exception) $(C assumeUnique()) for fast $(C immutable) conversions) + +$(P +$(C to()) can perform $(C immutable) conversions as well: +) + +--- + int[] slice = [ 10, 20, 30 ]; + auto immutableSlice = to!($(HILITE immutable int[]))(slice); +--- + +$(P +In order to guarantee that the elements of $(C immutableSlice) will never change, it cannot share the same elements with $(C slice). For that reason, $(C to()) creates an additional slice with $(C immutable) elements above. Otherwise, modifications to the elements of $(C slice) would cause the elements of $(C immutableSlice) change as well. This behavior is the same with the $(C .idup) property of arrays. +) + +$(P +We can see that the elements of $(C immutableSlice) are indeed copies of the elements of $(C slice) by looking at the addresses of their first elements: +) + +--- + assert(&(slice[0]) $(HILITE !=) &(immutableSlice[0])); +--- + +$(P +Sometimes this copy is unnecessary and may slow the speed of the program noticeably in certain cases. As an example of this, let's look at the following function that takes an $(C immutable) slice: +) + +--- +void calculate(immutable int[] coordinates) { + // ... +} + +void main() { + int[] numbers; + numbers ~= 10; + // ... various other modifications ... + numbers[0] = 42; + + calculate(numbers); $(DERLEME_HATASI) +} +--- + +$(P +The program above cannot be compiled because the caller is not passing an $(C immutable) argument to $(C calculate()). As we have seen above, an $(C immutable) slice can be created by $(C to()): +) + +--- +import std.conv; +// ... + auto immutableNumbers = to!(immutable int[])(numbers); + calculate(immutableNumbers); // ← now compiles +--- + +$(P +However, if $(C numbers) is needed only to produce this argument and will never be used after the function is called, copying its elements to $(C immutableNumbers) would be unnecessary. $(C assumeUnique()) makes the elements of a slice $(C immutable) without copying: +) + +--- +import std.exception; +// ... + auto immutableNumbers = assumeUnique(numbers); + calculate(immutableNumbers); + assert(numbers is null); // the original slice becomes null +--- + +$(P +$(C assumeUnique()) returns a new slice that provides $(C immutable) access to the existing elements. It also makes the original slice $(C null) to prevent the elements from accidentally being modified through it. +) + +$(H6 $(IX cast) The $(C cast) operator) + +$(P +Both $(C to()) and $(C assumeUnique()) make use of the conversion operator $(C cast), which is available to the programmer as well. +) + +$(P +The $(C cast) operator takes the destination type in parentheses: +) + +--- + cast($(I DestinationType))value +--- + +$(P +$(C cast) is powerful even for conversions that $(C to()) cannot safely perform. For example, $(C to()) fails for the following conversions at runtime: +) + +--- + Suit suit = to!Suit(7); $(CODE_NOTE_WRONG throws exception) + bool b = to!bool(2); $(CODE_NOTE_WRONG throws exception) +--- + +$(SHELL +std.conv.ConvException@phobos/std/conv.d(1778): Value (7) +$(HILITE does not match any member) value of enum 'Suit' +) + +$(P +Sometimes only the programmer can know whether an integer value corresponds to a valid $(C enum) value or that it makes sense to treat an integer value as a $(C bool). The $(C cast) operator can be used when the conversion is known to be correct according the program's logic: +) + +--- + // Probably incorrect but possible: + Suit suit = cast(Suit)7; + + bool b = cast(bool)2; + assert(b); +--- + +$(P +$(C cast) is the only option when converting to and from pointer types: +) + +--- + $(HILITE void *) v; + // ... + int * p = cast($(HILITE int*))v; +--- + +$(P +Although rare, some C library interfaces make it necessary to store a pointer value as a non-pointer type. If it is guaranteed that the conversion will preserve the actual value, $(C cast) can convert between pointer and non-pointer types as well: +) + +--- + size_t savedPointerValue = cast($(HILITE size_t))p; + // ... + int * p2 = cast($(HILITE int*))savedPointerValue; +--- + +$(H5 Summary) + +$(UL + +$(LI Automatic type conversions are mostly in the safe direction: From the narrower type to the wider type and from mutable to $(C const).) + +$(LI However, conversions to unsigned types may have surprising effects because unsigned types cannot have negative values.) + +$(LI $(C enum) types can automatically be converted to integer values but the opposite conversion is not automatic.) + +$(LI $(C false) and $(C true) are automatically converted to 0 and 1 respectively. Similarly, zero values are automatically converted to $(C false) and nonzero values are automatically converted to $(C true).) + +$(LI $(C null) references are automatically converted to $(C false) and non-$(C null) references are automatically converted to $(C true).) + +$(LI The construction syntax can be used for explicit conversions.) + +$(LI $(C to()) covers most of the explicit conversions.) + +$(LI $(C assumeUnique()) converts to $(C immutable) without copying.) + +$(LI The $(C cast) operator is the most powerful conversion tool.) + +) + +Macros: + TITLE=Type Conversions + + DESCRIPTION=The automatic and explicit type conversions in the D programming language. + + + KEYWORDS=d programming lesson book tutorial type conversions diff --git a/book/d.en/characters.d b/book/d.en/characters.d new file mode 100644 index 0000000000..7edbfe960d --- /dev/null +++ b/book/d.en/characters.d @@ -0,0 +1,594 @@ +Ddoc + +$(DERS_BOLUMU $(IX character) Characters) + +$(P +Characters are building blocks of strings. Any symbol of a writing system is called a character: letters of alphabets, numerals, punctuation marks, the space character, etc. Confusingly, building blocks of characters themselves are called characters as well. +) + +$(P +Arrays of characters make up $(I strings). We have seen arrays in the previous chapter; strings will be covered two chapters later. +) + +$(P +Like any other data, characters are also represented as integer values that are made up of bits. For example, the integer value of the lowercase $(C 'a') is 97 and the integer value of the numeral $(C '1') is 49. These values are merely a convention, assigned when the ASCII standard was designed. +) + +$(P +In many programming languages, characters are represented by the $(C char) type, which can hold only 256 distinct values. If you are familiar with the $(C char) type from other languages, you may already know that it is not large enough to support the symbols of many writing systems. Before getting to the three distinct character types of D, let's first take a look at the history of characters in computer systems. +) + +$(H5 History) + +$(H6 $(IX ASCII) ASCII Table) + +$(P +The ASCII table was designed at a time when computer hardware was very limited compared to modern systems. Having been based on 7 bits, the ASCII table can have 128 distinct code values. That many distinct values are sufficient to represent the lowercase and uppercase versions of the 26 letters of the basic Latin alphabet, numerals, commonly used punctuation marks, and some terminal control characters. +) + +$(P +As an example, the ASCII codes of the characters of the string $(STRING "hello") are the following (the commas are inserted just to make it easier to read): +) + +$(MONO +104, 101, 108, 108, 111 +) + +$(P +Every code above represents a single letter of $(STRING "hello"). For example, there are two 108 values corresponding to the two $(C 'l') letters. +) + +$(P +The codes of the ASCII table were later increased to 8 bits to become the Extended ASCII table. The Extended ASCII table has 256 distinct codes. +) + +$(H6 $(IX code page) IBM Code Pages) + +$(P +IBM Corporation has defined a set of tables, each one of which assign the codes of the Extended ASCII table from 128 to 255 to one or more writing systems. These code tables allowed supporting the letters of many more alphabets. For example, the special letters of the Turkish alphabet are a part of IBM's code page 857. +) + +$(P +Despite being much more useful than ASCII, code pages have some problems and limitations: In order to display text correctly, it must be known what code page a given text was originally written in. This is because the same code corresponds to a different character in most other tables. For example, the code that represents $(C 'Ğ') in table 857 corresponds to $(C 'ª') in table 437. +) + +$(P +In addition to the difficulty in supporting multiple alphabets in a single document, alphabets that have more than 128 non-ASCII characters cannot be supported by an IBM table at all. +) + +$(H6 ISO/IEC 8859 Code Pages) + +$(P +The ISO/IEC 8859 code pages are a result of international standardization efforts. They are similar to IBM's code pages in how they assign codes to characters. As an example, the special letters of the Turkish alphabet appear in code page 8859-9. These tables have the same problems and limitations as IBM's tables. For example, the Dutch digraph ij does not appear in any of these tables. +) + +$(H6 $(IX unicode) Unicode) + +$(P +Unicode solves all problems and limitations of previous solutions. Unicode includes more than a hundred thousand characters and symbols of the writing systems of many human languages, current and old. (New ones are constanly under review for addition to the table.) Each of these characters has a unique code. Documents that are encoded in Unicode can include all characters of separate writing systems without any confusion or limitation. +) + +$(H5 $(IX encoding, unicode) Unicode encodings) + +$(P +Unicode assigns a unique code for each character. Since there are more Unicode characters than an 8-bit value can hold, some characters must be represented by at least two 8-bit values. For example, the Unicode character code of $(C 'Ğ') (286) is greater than the maximum value of a $(C ubyte). +) + +$(P +The way characters are represented in electronic mediums is called their $(I encoding). We have seen above how the string $(STRING "hello") is encoded in ASCII. We will now see three Unicode encodings that correspond to D's character types. +) + +$(P +$(IX UTF-32) $(B UTF-32:) This encoding uses 32 bits (4 bytes) for every Unicode character. The UTF-32 encoding of $(STRING "hello") is similar to its ASCII encoding, but every character is represented with 4 bytes: +) + +$(MONO +0,0,0,104, 0,0,0,101, 0,0,0,108, 0,0,0,108, 0,0,0,111 +) + +$(P +As another example, the UTF-32 encoding of $(STRING "aĞ") is the following: +) + +$(MONO +0,0,0,97, 0,0,1,30 +) + +$(P +$(I $(B Note:) The order of the bytes of UTF-32 may be different on different computer systems.) +) + +$(P +$(C 'a') and $(C 'Ğ') are represented by 1 and 2 significant bytes respectively, and the values of the other 5 bytes are all zeros. These zeros can be thought of as filler bytes to make every Unicode character occupy 4 bytes each. +) + +$(P +For documents based on the basic Latin alphabet, this encoding always uses 4 times as many bytes as the ASCII encoding. When most of the characters of a given document have ASCII equivalents, the 3 filler bytes for each of those characters make this encoding more wasteful compared to other encodings. +) + +$(P +On the other hand, there are benefits of representing every character by an equal number of bytes. For example, the next Unicode character is always exactly four bytes away. +) + +$(P +$(IX UTF-16) $(B UTF-16:) This encoding uses 16 bits (2 bytes) to represent most of the Unicode characters. Since 16 bits can have about 65 thousand unique values, the other (less commonly used) 35 thousand Unicode characters must be represented using additional bytes. +) + +$(P +As an example, $(STRING "aĞ") is encoded by 4 bytes in UTF-16: +) + +$(MONO +0,97, 1,30 +) + +$(P +$(I $(B Note:) The order of the bytes of UTF-16 may be different on different computer systems.) +) + +$(P +Compared to UTF-32, this encoding takes less space for most documents, but because some characters must be represented by more than 2 bytes, UTF-16 is more complicated to process. +) + +$(P +$(IX UTF-8) $(B UTF-8:) This encoding uses 1 to 4 bytes for every character. If a character has an equivalent in the ASCII table, it is represented by 1 byte, with the same numeric code as in the ASCII table. The rest of the Unicode characters are represented by 2, 3, or 4 bytes. Most of the special characters of the European writing systems are among the group of characters that are represented by 2 bytes. +) + +$(P +For most documents in western countries, UTF-8 is the encoding that takes the least amount of space. Another benefit of UTF-8 is that the documents that were produced using ASCII can be opened directly (without conversion) as UTF-8 documents. UTF-8 also does not waste any space with filler bytes, as every character is represented by significant bytes. As an example, the UTF-8 encoding of $(STRING "aĞ") is: +) + +$(MONO +97, 196,158 +) + +$(H5 The character types of D) + +$(P +$(IX char) +$(IX wchar) +$(IX dchar) +There are three D types to represent characters. These characters correspond to the three Unicode encodings mentioned above. Copying from $(LINK2 types.html, the Fundamental Types chapter): +) + + + + + + + + + + + + + + + + + + +
    Type Definition Initial Value
    charUTF-8 code unit0xFF
    wcharUTF-16 code unit0xFFFF
    dcharUTF-32 code unit and Unicode code point0x0000FFFF
    + +$(P +Contrary to some other programming languages, characters in D may consist of different numbers of bytes. For example, because $(C 'Ğ') must be represented by at least 2 bytes in Unicode, it doesn't fit in a variable of type $(C char). On the other hand, because $(C dchar) consists of 4 bytes, it can hold any Unicode character. +) + +$(H5 $(IX literal, character) Character literals) + +$(P +Literals are constant values that are written in the program as a part of the source code. In D, character literals are specified within single quotes: +) + +--- + char letter_a = 'a'; + wchar letter_e_acute = 'é'; +--- + +$(P +Double quotes are not valid for characters because double quotes are used when specifying $(I strings), which we will see in $(LINK2 strings.html, a later chapter). $(C 'a') is a character literal and $(STRING "a") is a string literal that consists of a single character. +) + +$(P +Variables of type $(C char) can only hold letters that are in the ASCII table. +) + +$(P +There are many ways of inserting characters in code: +) + +$(UL +$(LI Most naturally, typing them on the keyboard. +) + +$(LI Copying from another program or another text. For example, you can copy and paste from a web site, or from a program that is specifically for displaying Unicode characters. (One such program in most Linux environments is $(I Character Map) ($(C charmap) on the terminal).) +) + +$(LI Using short names of the characters. The syntax for this feature is $(C \&$(I character_name);). For example, the name of the Euro sign is $(C euro) and it can be specified in the program as follows: + +--- + wchar currencySymbol = '\€'; +--- + +$(P +See $(LINK2 http://dlang.org/entity.html, the list of named characters) for all characters that can be specified this way. +) + +) + +$(LI Specifying characters by their integer Unicode values: + +--- + char a = 97; + wchar Ğ = 286; +--- + +) + +$(LI Specifying the codes of the characters of the ASCII table either by $(C \$(I value_in_octal)) or $(C \x$(I value_in_hexadecimal)) syntax: + +--- + char questionMarkOctal = '\77'; + char questionMarkHexadecimal = '\x3f'; +--- + +) + +$(LI Specifying the Unicode values of the characters by using the $(C \u$(I four_digit_value)) syntax for $(C wchar), and the $(C \U$(I eight_digit_value)) syntax for $(C dchar) (note $(C u) versus $(C U)). The Unicode values must be specified in hexadecimal: + +--- + wchar Ğ_w = '\u011e'; + dchar Ğ_d = '\U0000011e'; +--- + +) + +) + +$(P +These methods can be used to specify the characters within strings as well. For example, the following two lines have the same string literals: +) +--- + writeln("Résumé preparation: 10.25€"); + writeln("\x52\ésum\u00e9 preparation: 10.25\€"); +--- + +$(H5 $(IX control character) Control characters) + +$(P +Some characters only affect the formatting of the text, they don't have a visual representation themselves. For example, the $(I new-line) character, which specifies that the output should continue on a new line, does not have a visual representation. Such characters are called $(I control characters). Some common control characters can be specified with the $(C \$(I control_character)) syntax. +) + + + + + + + + + + + + + + + + + + + + +
    Syntax Name Definition
    \nnew lineMoves the printing to a new line
    \rcarriage returnMoves the printing to the beginning of the current line
    \ttabMoves the printing to the next tab stop
    + +$(P +For example, the $(C write()) function, which does not start a new line automatically, would do so for every $(C \n) character. Every occurrence of the $(C \n) control character within the following literal represents the start of a new line: +) + +--- + write("first line\nsecond line\nthird line\n"); +--- + +$(P +The output: +) + +$(SHELL +first line +second line +third line +) + +$(H5 $(IX ') $(IX \) Single quote and backslash) + +$(P +The single quote character itself cannot be written within single quotes because the compiler would take the second one as the closing character of the first one: $(C '''). The first two would be the opening and closing quotes, and the third one would be left alone, causing a compilation error. +) + +$(P +Similarly, since the backslash character has a special meaning in the control character and literal syntaxes, the compiler would take it as the start of such a syntax: $(C '\'). The compiler then would be looking for a closing single quote character, not finding one, and emitting a compilation error. +) + +$(P +For those reasons, the single quote and the backslash characters are $(I escaped) by a preceding backslash character: +) + + + + + + + + + + + + + + + +
    Syntax Name Definition
    \'single quoteAllows specifying the single quote character:'\''
    \\backslashAllows specifying the backslash character: '\\' or "\\"
    + +$(H5 $(IX std.uni) The std.uni module) + +$(P +The $(C std.uni) module includes functions that are useful for working with Unicode characters. You can see this module at $(LINK2 http://dlang.org/phobos/std_uni.html, its documentation). +) + +$(P +The functions that start with $(C is) answer certain questions about characters. The result is $(C false) or $(C true) depending on whether the answer is no or yes, respectively. These functions are useful in logical expressions: +) + +$(UL +$(LI $(C isLower): is it a lowercase character? +) +$(LI $(C isUpper): is it an uppercase character? +) +$(LI $(C isAlpha): is it a Unicode alphabetic character? +) +$(LI $(C isWhite): is it a whitespace character? +) +) + +$(P +The functions that start with $(C to) produce new characters from existing ones: +) + +$(UL +$(LI $(C toLower): produces the lowercase version of the given character +) +$(LI $(C toUpper): produces the uppercase version of the given character +) +) + +$(P +Here is a program that uses all those functions: +) + +--- +import std.stdio; +import std.uni; + +void main() { + writeln("Is ğ lowercase? ", isLower('ğ')); + writeln("Is Ş lowercase? ", isLower('Ş')); + + writeln("Is İ uppercase? ", isUpper('İ')); + writeln("Is ç uppercase? ", isUpper('ç')); + + writeln("Is z alphabetic? ", isAlpha('z')); + writeln("Is \€ alphabetic? ", isAlpha('\€')); + + writeln("Is new-line whitespace? ", isWhite('\n')); + writeln("Is the underscore whitespace? ", isWhite('_')); + + writeln("The lowercase of Ğ: ", toLower('Ğ')); + writeln("The lowercase of İ: ", toLower('İ')); + + writeln("The uppercase of ş: ", toUpper('ş')); + writeln("The uppercase of ı: ", toUpper('ı')); +} +--- + +$(P +The output: +) + +$(SHELL +Is ğ lowercase? true +Is Ş lowercase? false +Is İ uppercase? true +Is ç uppercase? false +Is z alphabetic? true +Is € alphabetic? false +Is new-line whitespace? true +Is the underscore whitespace? false +The lowercase of Ğ: ğ +The lowercase of İ: i +The uppercase of ş: Ş +The uppercase of ı: I +) + +$(H5 Limited support for ı and i) + +$(P +The lowercase and uppercase versions of the letters $(C 'ı') and $(C 'i') are consistently dotted or undotted in some alphabets (e.g. the Turkish alphabet). Most other aphabets are inconsistent in this regard: the uppercase of the dotted $(C 'i') is undotted $(C 'I'). +) + +$(P +Because the computer systems have started with the ASCII table, traditionally the uppercase of $(C 'i') is $(C 'I') and the lowercase of $(C 'I') is $(C 'i'). For that reason, these two letters may need special attention. The following program demonstrates this problem: +) + +--- +import std.stdio; +import std.uni; + +void main() { + writeln("The uppercase of i: ", toUpper('i')); + writeln("The lowercase of I: ", toLower('I')); +} +--- + +$(P +The output is according to the basic Latin alphabet: +) + +$(SHELL +The uppercase of i: I +The lowercase of I: i +) + +$(P +Characters are converted between their uppercase and lowercase versions normally by their Unicode character codes. This method is problematic for many alphabets. For example, the Azeri and Celt alphabets are subject to the same problem of producing the lowercase of $(C 'I') as $(C 'i'). +) + +$(P +There are similar problems with sorting: Many letters like $(C 'ğ') and $(C 'á') may be sorted after $(C 'z') even for the basic Latin alphabet. +) + +$(H5 $(IX read, character) Problems with reading characters) + +$(P +The flexibility and power of D's Unicode characters may cause unexpected results when reading characters from an input stream. This contradiction is due to the multiple meanings of the term $(I character). Before expanding on this further, let's look at a program that exhibits this problem: +) + +--- +import std.stdio; + +void main() { + char letter; + write("Please enter a letter: "); + readf(" %s", &letter); + writeln("The letter that has been read: ", letter); +} +--- + +$(P +If you try that program in an environment that does not use Unicode, you may see that even the non-ASCII characters are read and printed correctly. +) + +$(P +On the other hand, if you start the same program in a Unicode environment (e.g. a Linux terminal), you may see that the character printed on the output is not the same character that has been entered. To see this, let's enter a non-ASCII character in a terminal that uses the UTF-8 encoding (like most Linux terminals): +) + +$(SHELL +Please enter a letter: ğ +The letter that has been read: $(SHELL_NOTE no letter on the output) +) + +$(P +The reason for this problem is that the non-ASCII characters like $(C 'ğ') are represented by two codes, and reading a $(C char) from the input reads only the first one of those codes. Since that single $(C char) is not sufficient to represent the whole Unicode character, the program does not have a complete character to display. +) + +$(P +To show that the UTF-8 codes that make up a character are indeed read one $(C char) at a time, let's read two $(C char) variables and print them one after the other: +) + +--- +import std.stdio; + +void main() { + char firstCode; + char secondCode; + + write("Please enter a letter: "); + readf(" %s", &firstCode); + readf(" %s", &secondCode); + + writeln("The letter that has been read: ", + firstCode, secondCode); +} +--- + +$(P +The program reads two $(C char) variables from the input and prints them in the same order that they are read. When those codes are sent to the terminal in that same order, they complete the UTF-8 encoding of the Unicode character on the terminal and this time the Unicode character is printed correctly: +) + +$(SHELL +Please enter a letter: ğ +The letter that has been read: ğ +) + +$(P +These results are also related to the fact that the standard inputs and outputs of programs are $(C char) streams. +) + +$(P +We will see later in $(LINK2 strings.html, the Strings chapter) that it is easier to read characters as strings, instead of dealing with UTF codes individually. +) + +$(H5 D's Unicode support) + +$(P +Unicode is a large and complicated standard. D supports a very useful subset of it. +) + +$(P +A Unicode-encoded document consists of the following levels of concepts, from the lowermost to the uppermost: +) + +$(UL + +$(LI $(IX code unit) $(B Code unit): The values that make up the UTF encodings are called code units. Depending on the encoding and the characters themselves, Unicode characters are made up of one or more code units. For example, in the UTF-8 encoding the letter $(C 'a') is made up of a single code unit and the letter $(C 'ğ') is made up of two code units. + +$(P +D's character types $(C char), $(C wchar), and $(C dchar) correspond to UTF-8, UTF-16, and UTF-32 code units, respectively. +) + +) + +$(LI $(IX code point) $(B Code point): Every letter, numeral, symbol, etc. that the Unicode standard defines is called a code point. For example, the Unicode code values of $(C 'a') and $(C 'ğ') are two distinct code points. + +$(P +Depending on the encoding, code points are represented by one or more code units. As mentioned above, in the UTF-8 encoding $(C 'a') is represented by a single code unit, and $(C 'ğ') is represented by two code units. On the other hand, both $(C 'a') and $(C 'ğ') are represented by a single code unit in both UTF-16 and UTF-32 encodings. +) + +$(P +The D type that supports code points is $(C dchar). $(C char) and $(C wchar) can only be used as code units. +) + +) + +$(LI $(B Character): Any symbol that the Unicode standard defines and what we call "character" or "letter" in daily talk is a character. + +$(P +$(IX combined code point) This definition of character is flexible in Unicode, which brings a complication. Some characters can be formed by more than one code point. For example, the letter $(C 'ğ') can be specified in two ways: +) + +$(UL + +$(LI as the single code point for $(C 'ğ')) + +$(LI as the two code points for $(C 'g') and $(C '˘') (combining breve) + +) + +) + +$(P +Although they would mean the same character to a human reader, the single code point $(C 'ğ') is different from the two consecutive code points $(C 'g') and $(C '˘'). +) + +) + +) + +$(H5 Summary) + +$(UL + +$(LI Unicode supports all characters of all writing systems.) + +$(LI $(C char) is for UTF-8 encoding; although it is not suitable to represent characters in general, it supports the ASCII table.) + +$(LI $(C wchar) is for UTF-16 encoding; although it is not suitable to represent characters in general, it can support letters of multiple alphabets.) + +$(LI $(C dchar) is for UTF-32 encoding; as it is 32 bits, it can also represent code points.) + +) + +Macros: + TITLE=Characters + + DESCRIPTION=The character types of D and Unicode encodings + + KEYWORDS=d programming language tutorial book characters encoding char wchar dchar utf-8 utf-16 utf-32 unicode ascii diff --git a/book/d.en/class.d b/book/d.en/class.d new file mode 100644 index 0000000000..c6fce86c46 --- /dev/null +++ b/book/d.en/class.d @@ -0,0 +1,453 @@ +Ddoc + +$(DERS_BOLUMU $(IX class) Classes) + +$(P +$(IX OOP) $(IX object oriented programming) $(IX user defined type) Similar to structs, $(C class) is a feature for defining new types. By this definition, classes are $(I user defined types). Different from structs, classes provide the $(I object oriented programming) (OOP) paradigm in D. The major aspects of OOP are the following: +) + +$(UL + +$(LI +$(B Encapsulation:) Controlling access to members ($(I Encapsulation is available for structs as well but it has not been mentioned until this chapter.)) +) + +$(LI +$(B Inheritance:) Acquiring members of another type +) + +$(LI +$(B Polymorphism:) Being able to use a more special type in place of a more general type +) + +) + +$(P +Encapsulation is achieved by $(I protection attributes), which we will see in $(LINK2 encapsulation.html, a later chapter). Inheritance is for acquiring $(I implementations) of other types. $(LINK2 inheritance.html, Polymorphism) is for abstracting parts of programs from each other and is achieved by class $(I interfaces). +) + +$(P +This chapter will introduce classes at a high level, underlining the fact that they are reference types. Classes will be explained in more detail in later chapters. +) + +$(H5 Comparing with structs) + +$(P +In general, classes are very similar to structs. Most of the features that we have seen for structs in the following chapters apply to classes as well: +) + +$(UL +$(LI $(LINK2 struct.html, Structs)) +$(LI $(LINK2 member_functions.html, Member Functions)) +$(LI $(LINK2 const_member_functions.html, $(CH4 const ref) Parameters and $(CH4 const) Member Functions)) +$(LI $(LINK2 special_functions.html, Constructor and Other Special Functions)) +$(LI $(LINK2 operator_overloading.html, Operator Overloading)) +) + +$(P +However, there are important differences between classes and structs. +) + +$(H6 Classes are reference types) + +$(P +The biggest difference from structs is that structs are $(I value types) and classes are $(I reference types). The other differences outlined below are mostly due to this fact. +) + +$(H6 $(IX null, class) $(new, class) Class variables may be $(C null)) + +$(P +As it has been mentioned briefly in $(LINK2 null_is.html, The $(CH4 null) Value and the $(CH4 is) Operator chapter), class variables can be $(C null). In other words, class variables may not be providing access to any object. Class variables do not have values themselves; the actual class objects must be constructed by the $(C new) keyword. +) + +$(P +As you would also remember, comparing a reference to $(C null) by the $(C ==) or the $(C !=) operator is an error. Instead, the comparison must be done by the $(C is) or the $(C !is) operator, accordingly: +) + +--- + MyClass referencesAnObject = new MyClass; + assert(referencesAnObject $(HILITE !is) null); + + MyClass variable; // does not reference an object + assert(variable $(HILITE is) null); +--- + +$(P +The reason is that, the $(C ==) operator may need to consult the values of the members of the objects and that attempting to access the members through a potentially $(C null) variable would cause a memory access error. For that reason, class variables must always be compared by the $(C is) and $(C !is) operators. +) + +$(H6 $(IX variable, class) $(IX object, class) Class variables versus class objects) + +$(P +Class variable and class object are separate concepts. +) + +$(P +Class objects are constructed by the $(C new) keyword; they do not have names. The actual concept that a class type represents in a program is provided by a class object. For example, assuming that a $(C Student) class represents students by their names and grades, such information would be stored by the members of $(C Student) $(I objects). Partly because they are anonymous, it is not possible to access class objects directly. +) + +$(P +A class variable on the other hand is a language feature for accessing class objects. Although it may seem syntactically that operations are being performed on a class $(I variable), the operations are actually dispatched to a class $(I object). +) + +$(P +Let's consider the following code that we saw previously in the $(LINK2 value_vs_reference.html, Value Types and Reference Types chapter): +) + +--- + auto variable1 = new MyClass; + auto variable2 = variable1; +--- + +$(P +The $(C new) keyword constructs an anonymous class object. $(C variable1) and $(C variable2) above merely provide access to that anonymous object: +) + +$(MONO + (anonymous MyClass object) variable1 variable2 + ───┬───────────────────┬─── ───┬───┬─── ───┬───┬─── + │ ... │ │ o │ │ o │ + ───┴───────────────────┴─── ───┴─│─┴─── ───┴─│─┴─── + ▲ │ │ + │ │ │ + └────────────────────┴────────────┘ +) + +$(H6 $(IX copy, class) Copying) + +$(P +Copying affects only the variables, not the object. +) + +$(P +Because classes are reference types, defining a new class variable as a copy of another makes two variables that provide access to the same object. The actual object is not copied. +) + +$(P +Since no object gets copied, the postblit function $(C this(this)) is not available for classes. +) + +--- + auto variable2 = variable1; +--- + +$(P +In the code above, $(C variable2) is being initialized by $(C variable1). The two variables start providing access to the same object. +) + +$(P +When the actual object needs to be copied, the class must have a member function for that purpose. To be compatible with arrays, this function may be named $(C dup()). This function must create and return a new class object. Let's see this on a class that has various types of members: +) + +--- +class Foo { + S o; // assume S is a struct type + char[] s; + int i; + +// ... + + this(S o, const char[] s, int i) { + this.o = o; + this.s = s.dup; + this.i = i; + } + + Foo dup() const { + return new Foo(o, s, i); + } +} +--- + +$(P +The $(C dup()) member function makes a new object by taking advantage of the constructor of $(C Foo) and returns the new object. Note that the constructor copies the $(C s) member explicitly by the $(C .dup) property of arrays. Being value types, $(C o) and $(C i) are copied automatically. +) + +$(P +The following code makes use of $(C dup()) to create a new object: +) + +--- + auto var1 = new Foo(S(1.5), "hello", 42); + auto var2 = var1.dup(); +--- + +$(P +As a result, the objects that are associated with $(C var1) and $(C var2) are different. +) + +$(P +Similarly, an $(C immutable) copy of an object can be provided by a member function appropriately named $(C idup()). In this case, the constructor must be defined as $(C pure) as well. We will cover the $(C pure) keyword in $(LINK2 functions_more.html, a later chapter). +) + +--- +class Foo { +// ... + this(S o, const char[] s, int i) $(HILITE pure) { + // ... + + } + immutable(Foo) idup() const { + return new immutable(Foo)(o, s, i); + } +} + +// ... + + immutable(Foo) imm = var1.idup(); +--- + +$(H6 $(IX assignment, class) Assignment) + +$(P +Just like copying, assignment affects only the variables. +) + +$(P +Assigning to a class variable disassociates that variable from its current object and associates it with a new object. +) + +$(P +If there is no other class variable that still provides access to the object that has been disassociated from, then that object is going to be destroyed some time in the future by the garbage collector. +) + +--- + auto variable1 = new MyClass(); + auto variable2 = new MyClass(); + variable1 $(HILITE =) variable2; +--- + +$(P +The assignment above makes $(C variable1) leave its object and start providing access to $(C variable2)'s object. Since there is no other variable for $(C variable1)'s original object, that object will be destroyed by the garbage collector. +) + +$(P +The behavior of assignment cannot be changed for classes. In other words, $(C opAssign) cannot be overloaded for them. +) + +$(H6 Definition) + +$(P +Classes are defined by the $(C class) keyword instead of the $(C struct) keyword: +) + +--- +$(HILITE class) ChessPiece { + // ... +} +--- + +$(H6 Construction) + +$(P +As with structs, the name of the constructor is $(C this). Unlike structs, class objects cannot be constructed by the $(C { }) syntax. +) + +--- +class ChessPiece { + dchar shape; + + this(dchar shape) { + this.shape = shape; + } +} +--- + +$(P +Unlike structs, there is no automatic object construction where the constructor parameters are assigned to members sequentially: +) + +--- +class ChessPiece { + dchar shape; + size_t value; +} + +void main() { + auto king = new ChessPiece('♔', 100); $(DERLEME_HATASI) +} +--- + +$(SHELL +Error: no constructor for ChessPiece +) + +$(P +For that syntax to work, a constructor must be defined explicitly by the programmer. +) + +$(H6 Destruction) + +$(P +As with structs, the name of the destructor is $(C ~this): +) + +--- + ~this() { + // ... + } +--- + +$(P +$(IX finalizer versus destructor) However, different from structs, class destructors are not executed at the time when the lifetime of a class object ends. As we have seen above, the destructor is executed some time in the future during a garbage collection cycle. (By this distinction, class destructors should have more accurately been called $(I finalizers)). +) + +$(P +As we will see later in $(LINK2 memory.html, the Memory Management chapter), class destructors must observe the following rules: +) + +$(UL + +$(LI A class destructor must not access a member that is managed by the garbage collector. This is because garbage collectors are not required to guarantee that the object and its members are finalized in any specific order. All members may have already been finalized when the destructor is executing.) + +$(LI A class destructor must not allocate new memory that is managed by the garbage collector. This is because garbage collectors are not required to guarantee that they can allocate new objects during a garbage collection cycle.) + +) + +$(P +Violating these rules is undefined behavior. It is easy to see an example of such a problem simply by trying to allocate an object in a class destructor: +) + +--- +class C { + ~this() { + auto c = new C(); // ← WRONG: Allocates explicitly + // in a class destructor + } +} + +void main() { + auto c = new C(); +} +--- + +$(P +The program is terminated with an exception: +) + +$(SHELL +core.exception.$(HILITE InvalidMemoryOperationError)@(0) +) + +$(P +It is equally wrong to allocate new memory $(I indirectly) from the garbage collector in a destructor. For example, memory used for the elements of a dynamic array is allocated by the garbage collector as well. Using an array in a way that would require allocating a new memory block for the elements is undefined behavior as well: +) + +--- + ~this() { + auto arr = [ 1 ]; // ← WRONG: Allocates indirectly + // in a class destructor + } +--- + +$(SHELL +core.exception.$(HILITE InvalidMemoryOperationError)@(0) +) + +$(H6 Member access) + +$(P +Same as structs, the members are accessed by the $(I dot) operator: +) + +--- + auto king = new ChessPiece('♔'); + writeln(king$(HILITE .shape)); +--- + +$(P +Although the syntax makes it look as if a member of the $(I variable) is being accessed, it is actually the member of the $(I object). Class variables do not have members, the class objects do. The $(C king) variable does not have a $(C shape) member, the anonymous object does. +) + +$(P +$(I $(B Note:) It is usually not proper to access members directly as in the code above. When that exact syntax is desired, properties should be preferred, which will be explained in $(LINK2 property.html, a later chapter).) +) + +$(H6 Operator overloading) + +$(P +Other than the fact that $(C opAssign) cannot be overloaded for classes, operator overloading is the same as structs. For classes, the meaning of $(C opAssign) is always $(I associating a class variable with a class object). +) + +$(H6 Member functions) + +$(P +Although member functions are defined and used the same way as structs, there is an important difference: Class member functions can be and by-default are $(I overridable). We will see this concept later in $(LINK2 inheritance.html, the Inheritance chapter). +) + +$(P +$(IX final) As overridable member functions have a runtime performance cost, without going into more detail, I recommend that you define all $(C class) functions that do not need to be overridden with the $(C final) keyword. You can apply this guideline blindly unless there are compilation errors: +) + +--- +class C { + $(HILITE final) int func() { $(CODE_NOTE Recommended) + // ... + } +} +--- + +$(P +Another difference from structs is that some member functions are automatically inherited from the $(C Object) class. We will see in $(LINK2 inheritance.html, the next chapter) how the definition of $(C toString) can be changed by the $(C override) keyword. +) + +$(H6 $(IX is, operator) $(IX !is) The $(C is) and $(C !is) operators) + +$(P +These operators operate on class variables. +) + +$(P +$(C is) specifies whether two class variables provide access to the same class object. It returns $(C true) if the object is the same and $(C false) otherwise. $(C !is) is the opposite of $(C is). +) + +--- + auto myKing = new ChessPiece('♔'); + auto yourKing = new ChessPiece('♔'); + assert(myKing !is yourKing); +--- + +$(P +Since the objects of $(C myKing) and $(C yourKing) variables are different, the $(C !is) operator returns $(C true). Even though the two objects are constructed by the same character $(C'♔'), they are still two separate objects. +) + +$(P +When the variables provide access to the same object, $(C is) returns $(C true): +) + +--- + auto myKing2 = myKing; + assert(myKing2 is myKing); +--- + +$(P +Both of the variables above provide access to the same object. +) + +$(H5 Summary) + +$(UL + +$(LI Classes and structs share common features but have big differences. +) + +$(LI Classes are reference types. The $(C new) keyword constructs an anonymous $(I class object) and returns a $(I class variable). +) + +$(LI Class variables that are not associated with any object are $(C null). Checking against $(C null) must be done by $(C is) or $(C !is), not by $(C ==) or $(C !=). +) + +$(LI The act of copying associates an additional variable with an object. In order to copy class objects, the type must have a special function likely named $(C dup()). +) + +$(LI Assignment associates a variable with an object. This behavior cannot be changed. +) + +) + +Macros: + TITLE=Classes + + DESCRIPTION=The basic object oriented programming (OOP) feature of the D programming language. + + KEYWORDS=d programming lesson book tutorial class diff --git a/book/d.en/code/README b/book/d.en/code/README new file mode 100644 index 0000000000..698cff6a33 --- /dev/null +++ b/book/d.en/code/README @@ -0,0 +1,22 @@ +This directory contains most of the code samples that appear in the book +"Programming in D": + + http://ddili.org/ + +The names of the sample programs are in chapterName.N.d format. The programs +are extracted from the chapter files and named automatically. + + chapterName - The name of the chapter file without the .html extension, from + which the program was extracted (e.g. hello_world for + hello_world.html) + + N - The order in which the program was extracted from that chapter + file (e.g. 1) + +For example, hello_world.1.d is the first program that was extracted from +hello_world.html. + +The word 'cozum' (transliteration of Turkish "çözüm") that appears in some of +the chapter file names has been replaced with its English translation +(solution). Accordingly, unit_testing.solution.2.d is the second program that +was extracted from unit_testing.cozum.html. diff --git a/book/d.en/compiler.d b/book/d.en/compiler.d new file mode 100644 index 0000000000..5f64e448e5 --- /dev/null +++ b/book/d.en/compiler.d @@ -0,0 +1,101 @@ +Ddoc + +$(DERS_BOLUMU $(IX compilation) Compilation) + +$(P +We have seen that the two tools that are used most in D programming are $(I the text editor) and $(I the compiler). D programs are written in text editors. +) + +$(P +The concept of compilation and the function of the compiler must also be understood when using $(I compiled) languages like D. +) + +$(H5 $(IX machine code) Machine code) + +$(P +$(IX CPU) $(IX microprocessor) The brain of the computer is the microprocessor (or the CPU, short for $(I central processing unit)). Telling the CPU what to do is called $(I coding), and the instructions that are used when doing so are called $(I machine code). +) + +$(P +Most CPU architectures use machine code specific to that particular architecture. These machine code instructions are determined under hardware constraints during the design stage of the architecture. At the lowest level these machine code instructions are implemented as electrical signals. Because the ease of coding is not a primary consideration at this level, writing programs directly in the form of the machine code of the CPU is a very difficult task. +) + +$(P +These machine code instructions are special numbers, which represent various operations supported by the CPU. For example, for an imaginary 8-bit CPU, the number 4 might represent the operation of loading, the number 5 might represent the operation of storing, and the number 6 might represent the operation of incrementing. Assuming that the leftmost 3 bits are the operation number and the rightmost 5 bits are the value that is used in that operation, a sample program in machine code for this CPU might look like the following: +) + +$(MONO +$(B +Operation Value Meaning) + 100 11110 LOAD 11110 + 101 10100 STORE 10100 + 110 10100 INCREMENT 10100 + 000 00000 PAUSE +) + +$(P +Being so close to hardware, machine code is not suitable for representing higher level concepts like $(I a playing card) or $(I a student record). +) + +$(H5 $(IX programming language) Programming language) + +$(P +Programming languages are designed as efficient ways of programming a CPU, capable of representing higher-level concepts. Programming languages do not have to deal with hardware constraints; their main purposes are ease of use and expressiveness. Programming languages are easier for humans to understand, closer to natural languages: +) + +$(MONO +if (a_card_has_been_played()) { + display_the_card(); +} +) + +$(P +However, programming languages adhere to much more strict and formal rules than any spoken language. +) + +$(H5 $(IX interpreter) Interpreter) + +$(P +An interpreter is a tool (a program) that reads the instructions from source code and executes them. For example, for the code above, an interpreter would understand to first execute $(C a_card_has_been_played()) and then conditionally execute $(C display_the_card()). From the point of view of the programmer, executing with an interpreter involves just two steps: writing the source code and giving it to the interpreter. +) + +$(P +The interpreter must read and understand the instructions every time the program is executed. For that reason, running a program with an interpreter is usually slower than running the compiled version of the same program. Additionally, interpreters usually perform very little analysis on the code before executing it. As a result, most interpreters discover programming errors only after they start executing the program. +) + +$(P +Some languages like Perl, Python and Ruby have been designed to be very flexible and dynamic, making code analysis harder. These languages have traditionally been used with an interpreter. +) + +$(H5 $(IX compiler) Compiler) + +$(P +A compiler is another tool that reads the instructions of a program from source code. Different from an interpreter, it does not execute the code; rather, it produces a program written in another language (usually machine code). This produced program is responsible for the execution of the instructions that were written by the programmer. From the point of view of the programmer, executing with a compiler involves three steps: writing the source code, compiling it, and running the produced program. +) + +$(P +Unlike an interpreter, the compiler reads and understands the source code only once, during compilation. For that reason and in general, a compiled program runs faster compared to executing that program with an interpreter. Compilers usually perform advanced analysis on the code, which help with producing fast programs and catching programming errors before the program even starts running. On the other hand, having to compile the program every time it is changed is a complication and a potential source of human errors. Moreover, the programs that are produced by a compiler can usually run only on a specific platform; to run on a different kind of processor or on a different operating system, the program would have to be recompiled. Additionally, the languages that are easy to compile are usually less dynamic than those that run in an interpreter. +) + +$(P +For reasons like safety and performance, some languages have been designed to be compiled. Ada, C, C++, and D are some of them. +) + +$(H6 $(IX error, compilation) $(IX compilation error) Compilation error) + +$(P +As the compiler compiles a program according to the rules of the language, it stops the compilation as soon as it comes across $(I illegal) instructions. Illegal instructions are the ones that are outside the specifications of the language. Problems like a mismatched parenthesis, a missing semicolon, a misspelled keyword, etc. all cause compilation errors. +) + +$(P +The compiler may also emit a $(I compilation warning) when it sees a suspicious piece of code that may cause concern but not necessarily an error. However, warnings almost always indicate an actual error or bad style, so it is a common practice to consider most or all warnings as errors. The $(C dmd) compiler switch to enable warnings as errors is $(C -w). +) + +$(Ergin) + +Macros: + TITLE=Compiler + + DESCRIPTION=The introduction of the compiler and compiled languages + + KEYWORDS=d programming language tutorial book diff --git a/book/d.en/concurrency.d b/book/d.en/concurrency.d new file mode 100644 index 0000000000..91c54c0172 --- /dev/null +++ b/book/d.en/concurrency.d @@ -0,0 +1,1343 @@ +Ddoc + +$(DERS_BOLUMU $(IX concurrency, message passing) $(IX message passing concurrency) Message Passing Concurrency) + +$(P +Concurrency is similar to but different from the topic of the previous chapter, parallelism. As these two concepts both involve executing programs on threads, and as parallelism is based on concurrency, they are sometimes confused with each other. +) + +$(P +$(IX parallelism vs. concurrency) $(IX concurrency vs. parallelism) The following are the differences between parallelism and concurrency: +) + +$(UL + +$(LI +The main purpose of parallelism is to take advantage of microprocessor cores to improve the performance of programs. Concurrency on the other hand, is a concept that may be needed even on a single-core environment. Concurrency is about making a program run on more than one thread at a time. An example of a concurrent program would be a server program that is responding to requests of more than one client at the same time. +) + +$(LI +In parallelism, tasks are independent from each other. In fact, it would be a bug if they did depend on results of other tasks that are running at the same time. In concurrency, it is normal for threads to depend on results of other threads. +) + +$(LI +Although both programming models use operating system threads, in parallelism threads are encapsulated by the concept of task. Concurrency makes use of threads explicitly. +) + +$(LI +Parallelism is easy to use, and as long as tasks are independent it is easy to produce programs that work correctly. Concurrency is easy only when it is based on $(I message passing). It is very difficult to write correct concurrent programs if they are based on the traditional model of concurrency that involves lock-based data sharing. +) + +) + +$(P +D supports both models of concurrency: message passing and data sharing. We will cover message passing in this chapter and data sharing in the next chapter. +) + +$(H5 Concepts) + +$(P +$(IX thread) $(B Thread): Operating systems execute programs as work units called $(I threads). D programs start executing with $(C main()) on a thread that has been assigned to that program by the operating system. All of the operations of the program are normally executed on that thread. The program is free to start other threads to be able to work on multiple tasks at the same time. In fact, tasks that have been covered in the previous chapter are based on threads that are started automatically by $(C std.parallelism). +) + +$(P +The operating system can pause threads at unpredictable times for unpredictable durations. As a result, even operations as simple as incrementing a variable may be paused mid operation: +) + +--- + ++i; +--- + +$(P +The operation above involves three steps: Reading the value of the variable, incrementing the value, and assigning the new value back to the variable. The thread may be paused at any point between these steps to be continued after an unpredictable time. +) + +$(P +$(IX message) $(B Message): Data that is passed between threads are called messages. Messages may be composed of any type and any number of variables. +) + +$(P +$(IX thread id) $(B Thread identifier): Every thread has an id, which is used for specifying recipients of messages. +) + +$(P +$(IX owner) $(B Owner): Any thread that starts another thread is called the owner of the new thread. +) + +$(P +$(IX worker) $(B Worker): Any thread that is started by an owner is called a worker. +) + +$(H5 $(IX spawn) Starting threads) + +$(P +$(C spawn()) takes a function pointer as a parameter and starts a new thread from that function. Any operations that are carried out by that function, including other functions that it may call, would be executed on the new thread. The main difference between a thread that is started with $(C spawn()) and a thread that is started with $(LINK2 parallelism.html, $(C task())) is the fact that $(C spawn()) makes it possible for threads to send messages to each other. +) + +$(P +As soon as a new thread is started, the owner and the worker start executing separately as if they were independent programs: +) + +--- +import std.stdio; +import std.concurrency; +import core.thread; + +void worker() { + foreach (i; 0 .. 5) { + Thread.sleep(500.msecs); + writeln(i, " (worker)"); + } +} + +void main() { + $(HILITE spawn(&worker)); + + foreach (i; 0 .. 5) { + Thread.sleep(300.msecs); + writeln(i, " (main)"); + } + + writeln("main is done."); +} +--- + +$(P +The examples in this chapter call $(C Thread.sleep) to slow down threads to demonstrate that they run at the same time. The output of the program shows that the two threads, one that runs $(C main()) and the other that has been started by $(C spawn()), execute independently at the same time: +) + +$(SHELL +0 (main) +0 (worker) +1 (main) +2 (main) +1 (worker) +3 (main) +2 (worker) +4 (main) +main is done. +3 (worker) +4 (worker) +) + +$(P +The program automatically waits for all of the threads to finish executing. We can see this in the output above by the fact that $(C worker()) continues executing even after $(C main()) exits after printing "main is done." +) + +$(P +The parameters that the thread function takes are passed to $(C spawn()) as its second and later arguments. The two worker threads in the following program print four numbers each. They take the starting number as the thread function parameter: +) + +--- +import std.stdio; +import std.concurrency; +import core.thread; + +void worker($(HILITE int firstNumber)) { + foreach (i; 0 .. 4) { + Thread.sleep(500.msecs); + writeln(firstNumber + i); + } +} + +void main() { + foreach (i; 1 .. 3) { + spawn(&worker, $(HILITE i * 10)); + } +} +--- + +$(P +The output of one of the threads is highlighted: +) + +$(SHELL +10 +$(HILITE 20) +11 +$(HILITE 21) +12 +$(HILITE 22) +13 +$(HILITE 23) +) + +$(P +The lines of the output may be different at different times depending on how the threads are paused and resumed by the operating system. +) + +$(P +$(IX CPU bound) $(IX I/O bound) $(IX thread performance) Every operating system puts limits on the number of threads that can exist at one time. These limits can be set for each user, for the whole system, or for something else. The overall performance of the system can be reduced if there are more threads that are busily working than the number of cores in the system. A thread that is busily working at a given time is said to be $(I CPU bound) at that point in time. On the other hand, some threads spend considerable amount of their time waiting for some event to occur like input from a user, data from a network connection, the completion of a $(C Thread.sleep) call, etc. Such threads are said to be $(I I/O bound) at those times. If the majority of its threads are I/O bound, then a program can afford to start more threads than the number of cores without any degradation of performance. As it should be in every design decision that concerns program performance, one must take actual measurements to be exactly sure whether that really is the case. +) + +$(H5 $(IX Tid) $(IX thisTid) $(IX ownerTid) Thread identifiers) + +$(P +$(C thisTid()) returns the identifier of the $(I current) thread. It is commonly called without the function parentheses: +) + +--- +import std.stdio; +import std.concurrency; + +void printTid(string tag) { + writefln("%s: %s", tag, $(HILITE thisTid)); +} + +void worker() { + printTid("Worker"); +} + +void main() { + spawn(&worker); + printTid("Owner "); +} +--- + +$(P +The return type of $(C thisTid()) is $(C Tid), which has no significance for the program. Even its $(C toString()) function is not overloaded: +) + +$(SHELL +Owner : Tid(std.concurrency.MessageBox) +Worker: Tid(std.concurrency.MessageBox) +) + +$(P +The return value of $(C spawn()), which I have been ignoring until this point, is the id of the worker thread: +) + +--- + $(HILITE Tid myWorker) = spawn(&worker); +--- + +$(P +Conversely, the owner of a worker thread is obtained by the $(C ownerTid()) function. +) + +$(P +In summary, the owner is identified by $(C ownerTid) and the worker is identified by the return value of $(C spawn()). +) + +$(H5 $(IX send) $(IX receiveOnly) Message Passing) + +$(P +$(C send()) sends messages and $(C receiveOnly()) waits for a message of a particular type. (There is also $(C prioritySend()), $(C receive()), and $(C receiveTimeout()), which will be explained later below.) +) + +$(P +The owner in the following program sends its worker a message of type $(C int) and waits for a message from the worker of type $(C double). The threads continue sending messages back and forth until the owner sends a negative $(C int). This is the owner thread: +) + +--- +void $(CODE_DONT_TEST)main() { + Tid worker = spawn(&workerFunc); + + foreach (value; 1 .. 5) { + $(HILITE worker.send)(value); + double result = $(HILITE receiveOnly!double)(); + writefln("sent: %s, received: %s", value, result); + } + + /* Sending a negative value to the worker so that it + * terminates. */ + $(HILITE worker.send)(-1); +} +--- + +$(P +$(C main()) stores the return value of $(C spawn()) under the name $(C worker) and uses that variable when sending messages to the worker. +) + +$(P +On the other side, the worker receives the message that it needs as an $(C int), uses that value in a calculation, and sends the result as type $(C double) to its owner: +) + +--- +void workerFunc() { + int value = 0; + + while (value >= 0) { + value = $(HILITE receiveOnly!int)(); + double result = to!double(value) / 5; + $(HILITE ownerTid.send)(result); + } +} +--- + +$(P +The main thread reports the messages that it sends and the messages that it receives: +) + +$(SHELL +sent: 1, received: 0.2 +sent: 2, received: 0.4 +sent: 3, received: 0.6 +sent: 4, received: 0.8 +) + +$(P +It is possible to send more than one value as a part of the same message. The following message consists of three parts: +) + +--- + ownerTid.send($(HILITE thisTid, 42, 1.5)); +--- + +$(P +Values that are passed as parts of a single message appear as a tuple on the receiver's side. In such cases the template parameters of $(C receiveOnly()) must match the types of the tuple members: +) + +--- + /* Wait for a message composed of Tid, int, and double. */ + auto message = receiveOnly!($(HILITE Tid, int, double))(); + + auto sender = message[0]; // of type Tid + auto integer = message[1]; // of type int + auto floating = message[2]; // of type double +--- + +$(P +$(IX MessageMismatch) If the types do not match, a $(C MessageMismatch) exception is thrown: +) + +--- +import std.concurrency; + +void workerFunc() { + ownerTid.send("hello"); $(CODE_NOTE Sending $(HILITE string)) +} + +void main() { + spawn(&workerFunc); + + auto message = receiveOnly!double(); $(CODE_NOTE Expecting $(HILITE double)) +} +--- + +$(P +The output: +) + +$(SHELL +std.concurrency.$(HILITE MessageMismatch)@std/concurrency.d(235): +Unexpected message type: expected 'double', got 'immutable(char)[]' +) + +$(P +The exceptions that the worker may throw cannot be caught by the owner. One solution is to have the worker catch the exception to be sent as a message. We will see this below. +) + +$(H6 Example) + +$(P +Let's use what we have seen so far in a simulation program. +) + +$(P +The following program simulates independent robots moving around randomly in a two dimensional space. The movement of each robot is handled by a separate thread that takes three pieces of information when started: +) + +$(UL + +$(LI The number (id) of the robot: This information is sent back to the owner to identify the robot that the message is related to. +) + +$(LI The origin: This is where the robot starts moving from. +) + +$(LI The duration between each step: This information is used for determining when the robot's next step will be. +) + +) + +$(P +That information can be stored in the following $(C Job) struct: +) + +--- +struct Job { + size_t robotId; + Position origin; + Duration restDuration; +} +--- + +$(P +The thread function that moves each robot sends the id of the robot and its movement to the owner thread continuously: +) + +--- +void robotMover(Job job) { + Position from = job.origin; + + while (true) { + Thread.sleep(job.restDuration); + + Position to = randomNeighbor(from); + Movement movement = Movement(from, to); + from = to; + + ownerTid.send($(HILITE MovementMessage)(job.robotId, movement)); + } +} +--- + +$(P +The owner simply waits for these messages in an unconditional loop. It identifies the robots by the robot ids that are sent as parts of the messages. The owner simply prints every movement: +) + +--- + while (true) { + auto message = receiveOnly!$(HILITE MovementMessage)(); + + writefln("%s %s", + robots[message.robotId], message.movement); + } +--- + +$(P +All of the messages in this simple program go from the worker to the owner. Message passing normally involves more complicated communication in many kinds of programs. +) + +$(P +Here is the complete program: +) + +--- +import std.stdio; +import std.random; +import std.string; +import std.concurrency; +import core.thread; + +struct Position { + int line; + int column; + + string toString() { + return format("%s,%s", line, column); + } +} + +struct Movement { + Position from; + Position to; + + string toString() { + return ((from == to) + ? format("%s (idle)", from) + : format("%s -> %s", from, to)); + } +} + +class Robot { + string image; + Duration restDuration; + + this(string image, Duration restDuration) { + this.image = image; + this.restDuration = restDuration; + } + + override string toString() { + return format("%s(%s)", image, restDuration); + } +} + +/* Returns a random position around 0,0. */ +Position randomPosition() { + return Position(uniform!"[]"(-10, 10), + uniform!"[]"(-10, 10)); +} + +/* Returns at most one step from the specified coordinate. */ +int randomStep(int current) { + return current + uniform!"[]"(-1, 1); +} + +/* Returns a neighbor of the specified Position. It may be one + * of the neighbors at eight directions, or the specified + * position itself. */ +Position randomNeighbor(Position position) { + return Position(randomStep(position.line), + randomStep(position.column)); +} + +struct Job { + size_t robotId; + Position origin; + Duration restDuration; +} + +struct MovementMessage { + size_t robotId; + Movement movement; +} + +void robotMover(Job job) { + Position from = job.origin; + + while (true) { + Thread.sleep(job.restDuration); + + Position to = randomNeighbor(from); + Movement movement = Movement(from, to); + from = to; + + ownerTid.send(MovementMessage(job.robotId, movement)); + } +} + +void main() { + /* Robots with various restDurations. */ + Robot[] robots = [ new Robot("A", 600.msecs), + new Robot("B", 2000.msecs), + new Robot("C", 5000.msecs) ]; + + /* Start a mover thread for each robot. */ + foreach (robotId, robot; robots) { + spawn(&robotMover, Job(robotId, + randomPosition(), + robot.restDuration)); + } + + /* Ready to collect information about the movements of the + * robots. */ + while (true) { + auto message = receiveOnly!MovementMessage(); + + /* Print the movement of this robot. */ + writefln("%s %s", + robots[message.robotId], message.movement); + } +} +--- + +$(P +The program prints every movement until terminated: +) + +$(SHELL +A(600 ms) 6,2 -> 7,3 +A(600 ms) 7,3 -> 8,3 +A(600 ms) 8,3 -> 7,3 +B(2 secs) -7,-4 -> -6,-3 +A(600 ms) 7,3 -> 6,2 +A(600 ms) 6,2 -> 7,1 +A(600 ms) 7,1 (idle) +B(2 secs) -6,-3 (idle) +A(600 ms) 7,1 -> 7,2 +A(600 ms) 7,2 -> 7,3 +C(5 secs) -4,-4 -> -3,-5 +A(600 ms) 7,3 -> 6,4 +... +) + +$(P +This program demonstrates how helpful message passing concurrency can be: Movements of robots are calculated independently by separate threads without knowledge of each other. It is the owner thread that $(I serializes) the printing process simply by receiving messages from its message box one by one. +) + +$(H5 $(IX delegate, message passing) Expecting different types of messages) + +$(P +$(C receiveOnly()) can expect only one type of message. $(C receive()) on the other hand can wait for more than one type of message. It dispatches messages to message handling delegates. When a message arrives, it is compared to the message type of each delegate. The delegate that matches the type of the particular message handles it. +) + +$(P +For example, the following $(C receive()) call specifies two message handlers that handle messages of types $(C int) and $(C string), respectively: +) + +--- +$(CODE_NAME workerFunc)void workerFunc() { + bool isDone = false; + + while (!isDone) { + void intHandler($(HILITE int) message) { + writeln("handling int message: ", message); + + if (message == -1) { + writeln("exiting"); + isDone = true; + } + } + + void stringHandler($(HILITE string) message) { + writeln("handling string message: ", message); + } + + receive($(HILITE &intHandler), $(HILITE &stringHandler)); + } +} +--- + +$(P +Messages of type $(C int) would match $(C intHandler()) and messages of type $(C string) would match $(C stringHandler()). The worker thread above can be tested by the following program: +) + +--- +$(CODE_XREF workerFunc)import std.stdio; +import std.concurrency; + +// ... + +void main() { + auto worker = spawn(&workerFunc); + + worker.send(10); + worker.send(42); + worker.send("hello"); + worker.send(-1); // ← to terminate the worker +} +--- + +$(P +The output of the program indicates that the messages are handled by matching functions on the receiver's side: +) + +$(SHELL +handling int message: 10 +handling int message: 42 +handling string message: hello +handling int message: -1 +exiting +) + +$(P +Lambda functions and objects of types that define the $(C opCall()) member function can also be passed to $(C receive()) as message handlers. The following worker handles messages by lambda functions. The following program also defines a special type named $(C Exit) used for communicating to the thread that it is time for it to exit. Using such a specific type is more expressive than sending the arbitrary value of -1 like it was done in the previous example. +) + +$(P +There are three anonymous functions below that are passed to $(C receive()) as message handlers. Their curly brackets are highlighted: +) + +--- +import std.stdio; +import std.concurrency; + +struct Exit { +} + +void workerFunc() { + bool isDone = false; + + while (!isDone) { + receive( + (int message) $(HILITE {) + writeln("int message: ", message); + $(HILITE }), + + (string message) $(HILITE {) + writeln("string message: ", message); + $(HILITE }), + + (Exit message) $(HILITE {) + writeln("exiting"); + isDone = true; + $(HILITE })); + } +} + +void main() { + auto worker = spawn(&workerFunc); + + worker.send(10); + worker.send(42); + worker.send("hello"); + worker.send($(HILITE Exit())); +} +--- + +$(H6 Receiving any type of message) + +$(P +$(IX Variant, concurrency) $(C std.variant.Variant) is a type that can encapsulate any type of data. Messages that do not match the handlers that are specified earlier in the argument list always match a $(C Variant) handler: +) + +--- +import std.stdio; +import std.concurrency; + +void workerFunc() { + receive( + (int message) { /* ... */ }, + + (double message) { /* ... */ }, + + ($(HILITE Variant) message) { + writeln("Unexpected message: ", message); + }); +} + +struct SpecialMessage { + // ... +} + +void main() { + auto worker = spawn(&workerFunc); + worker.send(SpecialMessage()); +} +--- + +$(P +The output: +) + +$(SHELL +Unexpected message: SpecialMessage() +) + +$(P +The details of $(C Variant) are outside of the scope of this chapter. +) + +$(H5 $(IX receiveTimeout) Waiting for messages up to a certain time) + +$(P +It may not make sense to wait for messages beyond a certain time. The sender may have been busy temporarily or may have terminated with an exception. $(C receiveTimeout()) prevents blocking the receiving thread indefinitely. +) + +$(P +The first parameter of $(C receiveTimeout()) determines how long the message should be waited for. Its return value is $(C true) if a message has been received within that time, $(C false) otherwise. +) + +--- +import std.stdio; +import std.concurrency; +import core.thread; + +void workerFunc() { + Thread.sleep(3.seconds); + ownerTid.send("hello"); +} + +void main() { + spawn(&workerFunc); + + writeln("Waiting for a message"); + bool received = false; + while (!received) { + received = $(HILITE receiveTimeout)(600.msecs, + (string message) { + writeln("received: ", message); + }); + + if (!received) { + writeln("... no message yet"); + + /* ... other operations may be executed here ... */ + } + } +} +--- + +$(P +The owner above waits for a message for up to 600 milliseconds. It can continue working on other things if a message does not arrive within that time: +) + +$(SHELL +Waiting for a message +... no message yet +... no message yet +... no message yet +... no message yet +received: hello +) + +$(H5 $(IX exception, concurrency) Exceptions during the execution of the worker) + +$(P +As we have seen in the previous chapter, the facilities of the $(C std.parallelism) module automatically catch exceptions that have been thrown during the execution of tasks and rethrow them in the context of the owner. This allows the owner to catch such exceptions: +) + +--- + try { + theTask.yieldForce(); + + } catch (Exception exc) { + writefln("Detected an error in the task: '%s'", + exc.msg); + } +--- + +$(P +$(C std.concurrency) does not provide such a convenience for general exception types. However, the exceptions can be caught and sent explicitly by the worker. As we will see below, it is also possible to receive $(C OwnerTerminated) and $(C LinkTerminated) exceptions as messages. +) + +$(P +The $(C calculate()) function below receives $(C string) messages, converts them to $(C double), adds 0.5, and sends the result back as a message: +) + +--- +$(CODE_NAME calculate)void calculate() { + while (true) { + auto message = receiveOnly!string(); + ownerTid.send(to!double(message) + 0.5); + } +} +--- + +$(P +The $(C to!double()) call above would throw an exception if the string cannot be converted to a $(C double) value. Because such an exception would terminate the worker thread right away, the owner in the following program can receive a response only for the first message: +) + +--- +$(CODE_XREF calculate)import std.stdio; +import std.concurrency; +import std.conv; + +// ... + +void main() { + Tid calculator = spawn(&calculate); + + calculator.send("1.2"); + calculator.send("hello"); // ← incorrect input + calculator.send("3.4"); + + foreach (i; 0 .. 3) { + auto message = receiveOnly!double(); + writefln("result %s: %s", i, message); + } +} +--- + +$(P +The owner receives the response for "1.2" as 1.7 but because the worker has been terminated, the owner would be blocked waiting for a message that would never arrive: +) + +$(SHELL +result 0: 1.7 + $(SHELL_NOTE waiting for a message that will never arrive) +) + +$(P +One thing that the worker can do is to catch the exception explicitly and to send it as a special error message. The following program sends the reason of the failure as a $(C CalculationFailure) message. Additionally, this program takes advantage of a special message type to signal to the worker when it is time to exit: +) + +--- +import std.stdio; +import std.concurrency; +import std.conv; + +struct CalculationFailure { + string reason; +} + +struct Exit { +} + +void calculate() { + bool isDone = false; + + while (!isDone) { + receive( + (string message) { + try { + ownerTid.send(to!double(message) + 0.5); + + } $(HILITE catch) (Exception exc) { + ownerTid.send(CalculationFailure(exc.msg)); + } + }, + + (Exit message) { + isDone = true; + }); + } +} + +void main() { + Tid calculator = spawn(&calculate); + + calculator.send("1.2"); + calculator.send("hello"); // ← incorrect input + calculator.send("3.4"); + calculator.send(Exit()); + + foreach (i; 0 .. 3) { + writef("result %s: ", i); + + receive( + (double message) { + writeln(message); + }, + + (CalculationFailure message) { + writefln("ERROR! '%s'", message.reason); + }); + } +} +--- + +$(P +This time the reason of the failure is printed by the owner: +) + +$(SHELL +result 0: 1.7 +result 1: ERROR! 'no digits seen' +result 2: 3.9 +) + +$(P +Another method would be to send the actual exception object itself to the owner. The owner can use the exception object or simply rethrow it: +) + +--- +// ... at the worker ... + try { + // ... + + } catch ($(HILITE shared(Exception)) exc) { + ownerTid.send(exc); + }}, + +// ... at the owner ... + receive( + // ... + + ($(HILITE shared(Exception)) exc) { + throw exc; + }); +--- + +$(P +The reason why the $(C shared) specifiers are necessary is explained in the next chapter. +) + +$(H5 Detecting thread termination) + +$(P +Threads can detect that the receiver of a message has terminated. +) + +$(H6 $(IX OwnerTerminated) $(C OwnerTerminated) exception) + +$(P +This exception is thrown when receiving a message from the owner if the owner has been terminated. The intermediate owner thread below simply exits after sending two messages to its worker. This causes an $(C OwnerTerminated) exception to be thrown at the worker thread: +) + +--- +import std.stdio; +import std.concurrency; + +void main() { + spawn(&intermediaryFunc); +} + +void intermediaryFunc() { + auto worker = spawn(&workerFunc); + worker.send(1); + worker.send(2); +} // ← Terminates after sending two messages + +void workerFunc() { + while (true) { + auto m = receiveOnly!int(); // ← An exception is + // thrown if the owner + // has terminated. + writeln("Message: ", m); + } +} +--- + +$(P +The output: +) + +$(SHELL +Message: 1 +Message: 2 +std.concurrency.$(HILITE OwnerTerminated)@std/concurrency.d(248): +Owner terminated +) + +$(P +The worker can catch that exception to exit gracefully: +) + +--- +void workerFunc() { + bool isDone = false; + + while (!isDone) { + try { + auto m = receiveOnly!int(); + writeln("Message: ", m); + + } catch ($(HILITE OwnerTerminated) exc) { + writeln("The owner has terminated."); + isDone = true; + } + } +} +--- + +$(P +The output: +) + +$(SHELL +Message: 1 +Message: 2 +The owner has terminated. +) + +$(P +We will see below that this exception can be received as a message as well. +) + +$(H6 $(IX LinkTerminated) $(IX spawnLinked) $(C LinkTerminated) exception) + +$(P +$(C spawnLinked()) is used in the same way as $(C spawn()). When a worker that has been started by $(C spawnLinked()) terminates, a $(C LinkTerminated) exception is thrown at the owner: +) + +--- +import std.stdio; +import std.concurrency; + +void main() { + auto worker = $(HILITE spawnLinked)(&workerFunc); + + while (true) { + auto m = receiveOnly!int(); // ← An exception is + // thrown if the worker + // has terminated. + writeln("Message: ", m); + } +} + +void workerFunc() { + ownerTid.send(10); + ownerTid.send(20); +} // ← Terminates after sending two messages +--- + +$(P +The worker above terminates after sending two messages. Since the worker has been started by $(C spawnLinked()), the owner is notified of the worker's termination by a $(C LinkTerminated) exception: +) + +$(SHELL +Message: 10 +Message: 20 +std.concurrency.$(HILITE LinkTerminated)@std/concurrency.d(263): +Link terminated +) + +$(P +The owner can catch the exception to do something special like terminating gracefully: +) + +--- + bool isDone = false; + + while (!isDone) { + try { + auto m = receiveOnly!int(); + writeln("Message: ", m); + + } catch ($(HILITE LinkTerminated) exc) { + writeln("The worker has terminated."); + isDone = true; + } + } +--- + +$(P +The output: +) + +$(SHELL +Message: 10 +Message: 20 +The worker has terminated. +) + +$(P +This exception can be received as a message as well. +) + +$(H6 Receiving exceptions as messages) + +$(P +The $(C OwnerTerminated) and $(C LinkTerminated) exceptions can be received as messages as well. The following code demonstrates this for the $(C OwnerTerminated) exception: +) + +--- + bool isDone = false; + + while (!isDone) { + receive( + (int message) { + writeln("Message: ", message); + }, + + ($(HILITE OwnerTerminated exc)) { + writeln("The owner has terminated; exiting."); + isDone = true; + } + ); + } +--- + +$(H5 Mailbox management) + +$(P +Every thread has a private mailbox that holds the messages that are sent to that thread. The number of messages in a mailbox may increase or decrease depending on how long it takes for the thread to receive and respond to each message. A continuously growing mailbox puts stress on the entire system and may point to a design flaw in the program. It may also mean that the thread may never get to the most recent messages. +) + +$(P +$(IX setMaxMailboxSize) $(C setMaxMailboxSize()) is used for limiting the number of messages that a mailbox can hold. Its three parameters specify the mailbox, the maximum number of messages that it can hold, and what should happen when the mailbox is full, in that order. There are four choices for the last parameter: +) + +$(UL + +$(LI $(IX OnCrowding) $(C OnCrowding.block): The sender waits until there is room in the mailbox.) + +$(LI $(C OnCrowding.ignore): The message is discarded.) + +$(LI $(IX MailboxFull) $(C OnCrowding.throwException): A $(C MailboxFull) exception is thrown when sending the message.) + +$(LI A function pointer of type $(C bool function(Tid)): The specified function is called.) + +) + +$(P +Before seeing an example of $(C setMaxMailboxSize()), let's first cause a mailbox to grow continuously. The worker in the following program sends messages back to back but the owner spends some time for each message: +) + +--- +/* WARNING: Your system may become unresponsive when this + * program is running. */ +import std.concurrency; +import core.thread; + +void workerFunc() { + while (true) { + ownerTid.send(42); // ← Produces messages continuously + } +} + +void main() { + spawn(&workerFunc); + + while (true) { + receive( + (int message) { + // Spends time for each message + Thread.sleep(1.seconds); + }); + } +} +--- + +$(P +Because the consumer is slower than the producer, the memory that the program above uses would grow continuously. To prevent that, the owner may limit the size of its mailbox before starting the worker: +) + +--- +void $(CODE_DONT_TEST)main() { + setMaxMailboxSize(thisTid, 1000, OnCrowding.block); + + spawn(&workerFunc); +// ... +} +--- + +$(P +The $(C setMaxMailboxSize()) call above sets the main thread's mailbox size to 1000. $(C OnCrowding.block) causes the sender to wait until there is room in the mailbox. +) + +$(P +The following example uses $(C OnCrowding.throwException), which causes a $(C MailboxFull) exception to be thrown when sending a message to a mailbox that is full: +) + +--- +import std.concurrency; +import core.thread; + +void workerFunc() { + while (true) { + try { + ownerTid.send(42); + + } catch ($(HILITE MailboxFull) exc) { + /* Failed to send; will try again later. */ + Thread.sleep(1.msecs); + } + } +} + +void main() { + setMaxMailboxSize(thisTid, 1000, $(HILITE OnCrowding.throwException)); + + spawn(&workerFunc); + + while (true) { + receive( + (int message) { + Thread.sleep(1.seconds); + }); + } +} +--- + +$(H5 $(IX prioritySend) $(IX PriorityMessageException) Priority messages) + +$(P +Messages can be sent with higher priority than regular messages by $(C prioritySend()). These messages are handled before the other messages that are already in the mailbox: +) + +--- + prioritySend(ownerTid, ImportantMessage(100)); +--- + +$(P +If the receiver does not have a message handler that matches the type of the priority message, then a $(C PriorityMessageException) is thrown: +) + +$(SHELL +std.concurrency.$(HILITE PriorityMessageException)@std/concurrency.d(280): +Priority message +) + +$(H5 Thread names) + +$(P +In the simple programs that we have used above, it was easy to pass the thread ids of owners and workers. Passing thread ids from thread to thread may be overly complicated in programs that use more than a couple of threads. To reduce this complexity, it is possible to assign names to threads, which are globally accessible from any thread. +) + +$(P +The following three functions define an interface to an associative array that every thread has access to: +) + +$(UL + +$(LI $(IX register, concurrency) $(C register()): Associates a thread with a name.) + +$(LI $(IX locate) $(C locate()): Returns the thread that is associated with the specified name. If there is no thread associated with that name, then $(C Tid.init) is returned.) + +$(LI $(IX unregister) $(C unregister()): Breaks the association between the specified name and the thread.) + +) + +$(P +The following program starts two threads that find each other by their names. These threads continuously send messages to each other until instructed to terminate by an $(C Exit) message: +) + +--- +import std.stdio; +import std.concurrency; +import core.thread; + +struct Exit { +} + +void main() { + // A thread whose partner is named "second" + auto first = spawn(&player, "second"); + $(HILITE register)("first", first); + scope(exit) $(HILITE unregister)("first"); + + // A thread whose partner is named "first" + auto second = spawn(&player, "first"); + $(HILITE register)("second", second); + scope(exit) $(HILITE unregister)("second"); + + Thread.sleep(2.seconds); + + prioritySend(first, Exit()); + prioritySend(second, Exit()); + + // For the unregister() calls to succeed, main() must wait + // until the workers terminate. + thread_joinAll(); +} + +void player(string nameOfPartner) { + Tid partner; + + while (partner == Tid.init) { + Thread.sleep(1.msecs); + partner = $(HILITE locate)(nameOfPartner); + } + + bool isDone = false; + + while (!isDone) { + partner.send("hello " ~ nameOfPartner); + receive( + (string message) { + writeln("Message: ", message); + Thread.sleep(500.msecs); + }, + + (Exit message) { + writefln("%s, I am exiting.", nameOfPartner); + isDone = true; + }); + } +} +--- + +$(P +$(IX thread_joinAll) The $(C thread_joinAll()) call that is seen at the end of $(C main()) is for making the owner to wait for all of its workers to terminate. +) + +$(P +The output: +) + +$(SHELL +Message: hello second +Message: hello first +Message: hello second +Message: hello first +Message: hello first +Message: hello second +Message: hello first +Message: hello second +second, I am exiting. +first, I am exiting. +) + +$(H5 Summary) + +$(UL + +$(LI When threads do not depend on other threads, prefer $(I parallelism), which has been the topic of the previous chapter. Consider $(I concurrency) only when threads depend on operations of other threads.) + +$(LI Because concurrency by data sharing is hard to implement correctly, prefer concurrency by message passing, which is the subject of this chapter.) + +$(LI $(C spawn()) and $(C spawnLinked()) start threads.) + +$(LI $(C thisTid) is the thread id of the current thread.) + +$(LI $(C ownerTid) is the thread id of the owner of the current thread.) + +$(LI $(C send()) and $(C prioritySend()) send messages.) + +$(LI $(C receiveOnly()), $(C receive()), and $(C receiveTimeout()) wait for messages.) + +$(LI $(C Variant) matches any type of message.) + +$(LI $(C setMaxMailboxSize()) limits the size of mailboxes.) + +$(LI $(C register()), $(C unregister()), and $(C locate()) allow referring to threads by name.) + +$(LI Exceptions may be thrown during message passing: $(C MessageMismatch), $(C OwnerTerminated), $(C LinkTerminated), $(C MailboxFull), and $(C PriorityMessageException).) + +$(LI The owner cannot automatically catch exceptions that are thrown from the worker.) + +) + +macros: + TITLE=Message Passing Concurrency + + DESCRIPTION=Starting multiple threads in the D programming language and the interactions of threads by message passing. + + KEYWORDS=d programming language tutorial book concurrency thread + +MINI_SOZLUK= diff --git a/book/d.en/concurrency_shared.d b/book/d.en/concurrency_shared.d new file mode 100644 index 0000000000..231b9ec7fc --- /dev/null +++ b/book/d.en/concurrency_shared.d @@ -0,0 +1,758 @@ +Ddoc + +$(DERS_BOLUMU $(IX data sharing concurrency) $(IX concurrency, data sharing) Data Sharing Concurrency) + +$(P +The previous chapter was about threads sharing information through message passing. As it has been mentioned in that chapter, message passing is a safe method of concurrency. +) + +$(P +Another method involves more than one thread reading from and writing to the same data. For example, the owner thread can start the worker with the address of a $(C bool) variable and the worker can determine whether to terminate or not by reading the current value of that variable. Another example would be where the owner starts multiple workers with the address of the same variable so that the variable gets modified by more than one worker. +) + +$(P +One of the reasons why data sharing is not safe is $(I race conditions). A race condition occurs when more than one thread accesses the same mutable data in an uncontrolled order. Since the operating system pauses and starts individual threads in unspecified ways, the behavior of a program that has race conditions is unpredictable. +) + +$(P +The examples in this chapter may look simplistic. However, the issues that they convey appear in real programs at greater scales. Also, although these examples use the $(C std.concurrency) module, the concepts of this chapter apply to the $(C core.thread) module as well. +) + +$(H5 Sharing is not automatic) + +$(P +Unlike most other programming languages, data is not automatically shared in D; data is thread-local by default. Although module-level variables may give the impression of being accessible by all threads, each thread actually gets its own copy: +) + +--- +import std.stdio; +import std.concurrency; +import core.thread; + +int $(HILITE variable); + +void printInfo(string message) { + writefln("%s: %s (@%s)", message, variable, &variable); +} + +void worker() { + variable = $(HILITE 42); + printInfo("Before the worker is terminated"); +} + +void main() { + spawn(&worker); + thread_joinAll(); + printInfo("After the worker is terminated"); +} +--- + +$(P +$(C variable) that is modified inside $(C worker()) is not the same $(C variable) that is seen by $(C main()). This fact can be observed by printing both the values and the addresses of the variables: +) + +$(SHELL +Before the worker is terminated: 42 (@7F26C6711670) +After the worker is terminated: 0 (@7F26C68127D0) +) + +$(P +Since each thread gets its own copy of data, $(C spawn()) does not allow passing references to thread-local variables. For example, the following program that tries to pass the address of a $(C bool) variable to another thread cannot be compiled: +) + +--- +import std.concurrency; + +void worker($(HILITE bool * isDone)) { + while (!(*isDone)) { + // ... + } +} + +void main() { + bool isDone = false; + spawn(&worker, $(HILITE &isDone)); $(DERLEME_HATASI) + + // ... + + // Hoping to signal the worker to terminate: + isDone = true; + + // ... +} +--- + +$(P +A $(C static assert) inside the $(C std.concurrency) module prevents accessing $(I mutable) data from another thread: +) + +$(SHELL +src/phobos/std/concurrency.d(329): Error: static assert +"Aliases to $(HILITE mutable thread-local data) not allowed." +) + +$(P +The address of the mutable variable $(C isDone) cannot be passed between threads. +) + +$(P +$(IX __gshared) An exception to this rule is a variable that is defined as $(C __gshared): +) + +--- +__gshared int globallyShared; +--- + +$(P +There is only one copy of such a variable in the entire program and all threads can share that variable. $(C __gshared) is necessary when interacting with libraries of languages like C and C++ where data sharing is automatic by default. +) + +$(H5 $(IX shared) $(C shared) to share mutable data between threads) + +$(P +Mutable variables that need to be shared must be defined with the $(C shared) keyword: +) + +--- +import std.concurrency; + +void worker($(HILITE shared(bool)) * isDone) { + while (*isDone) { + // ... + } +} + +void main() { + $(HILITE shared(bool)) isDone = false; + spawn(&worker, &isDone); + + // ... + + // Signalling the worker to terminate: + isDone = true; + + // ... +} +--- + +$(P +$(I $(B Note:) Prefer message-passing to signal a thread.) +) + +$(P +$(IX immutable, concurrency) On the other hand, since $(C immutable) variables cannot be modified, there is no problem with sharing them directly. For that reason, $(C immutable) implies $(C shared): +) + +--- +import std.stdio; +import std.concurrency; +import core.thread; + +void worker($(HILITE immutable(int)) * data) { + writeln("data: ", *data); +} + +void main() { + $(HILITE immutable(int)) i = 42; + spawn(&worker, &i); // ← compiles + + thread_joinAll(); +} +--- + +$(P +The output: +) + +$(SHELL +data: 42 +) + +$(P +Note that since the lifetime of $(C i) is defined by the scope of $(C main()), it is important that $(C main()) does not terminate before the worker thread. The call to $(C core.thread.thread_joinAll) above is to make a thread wait for all of its child threads to terminate. +) + +$(H5 A race condition example) + +$(P +The correctness of the program requires extra attention when mutable data is shared between threads. +) + +$(P +To see an example of a race condition let's consider multiple threads sharing the same mutable variable. The threads in the following program receive the addresses as two variables and swap their values a large number of times: +) + +--- +import std.stdio; +import std.concurrency; +import core.thread; + +void swapper($(HILITE shared(int)) * first, $(HILITE shared(int)) * second) { + foreach (i; 0 .. 10_000) { + int temp = *second; + *second = *first; + *first = temp; + } +} + +void main() { + $(HILITE shared(int)) i = 1; + $(HILITE shared(int)) j = 2; + + writefln("before: %s and %s", i, j); + + foreach (id; 0 .. 10) { + spawn(&swapper, &i, &j); + } + + // Wait for all threads to finish their tasks + thread_joinAll(); + + writefln("after : %s and %s", i, j); +} +--- + +$(P +Although the program above gets compiled successfully, in most cases it would work incorrectly. Observe that it starts ten threads that all access the same two variables $(C i) and $(C j). As a result of the $(I race conditions) that they are in, they inadvertently spoil the operations of other threads. +) + +$(P +Also observe that total number of swaps is 10 times 10 thousand. Since that amount is an even number, it is natural to expect that the variables end up having values 1 and 2, their initial values: +) + +$(SHELL +before: 1 and 2 +after : 1 and 2 $(SHELL_NOTE expected result) +) + +$(P +Although it is possible that the program can indeed produce that result, most of the time the actual outcome would be one of the following: +) + +$(SHELL +before: 1 and 2 +after : 1 and 1 $(SHELL_NOTE_WRONG incorrect result) +) + +$(SHELL +before: 1 and 2 +after : 2 and 2 $(SHELL_NOTE_WRONG incorrect result) +) + +$(P +It is possible but highly unlikely that the result may even end up being "2 and 1" as well. +) + +$(P +The reason why the program works incorrectly can be explained by the following scenario between just two threads that are in a race condition. As the operating system pauses and restarts the threads at indeterminate times, the following order of execution of the operations of the two threads is likely as well. +) + +$(P +Let's consider the state where $(C i) is 1 and $(C j) is 2. Although the two threads execute the same $(C swapper()) function, remember that the local variable $(C temp) is separate for each thread and it is independent from the other $(C temp) variables of other threads. To identify those separate variables, they are renamed as $(C tempA) and $(C tempB) below. +) + +$(P +The chart below demonstrates how the 3-line code inside the $(C for) loop may be executed by each thread over time, from top to bottom, operation 1 being the first operation and operation 6 being the last operation. Whether $(C i) or $(C j) is modified at each step is indicated by highlighting that variable: +) + +$(MONO +$(B Operation Thread A Thread B) +──────────────────────────────────────────────────────────────────────────── + + 1: int temp = *second; (tempA==2) + 2: *second = *first; (i==1, $(HILITE j==1)) + + $(I (Assume that A is paused and B is started at this point)) + + 3: int temp = *second; (tempB==1) + 4: *second = *first; (i==1, $(HILITE j==1)) + + $(I (Assume that B is paused and A is restarted at this point)) + + 5: *first = temp; ($(HILITE i==2), j==1) + + $(I (Assume that A is paused and B is restarted at this point)) + + 6: *first = temp; ($(HILITE i==1), j==1) +) + +$(P +As can be seen, at the end of the previous scenario both $(C i) and $(C j) end up having the value 1. It is not possible that they can ever have any other value after that point. +) + +$(P +The scenario above is just one example that is sufficient to explain the incorrect results of the program. Obviously, the race conditions would be much more complicated in the case of the ten threads of this example. +) + +$(H5 $(IX synchronized) $(C synchronized) to avoid race conditions) + +$(P +The incorrect program behavior above is due to more than one thread accessing the same mutable data (and at least one of them modifying it). One way of avoiding these race conditions is to mark the common code with the $(C synchronized) keyword. The program would work correctly with the following change: +) + +--- + foreach (i; 0 .. 10_000) { + $(HILITE synchronized {) + int temp = *b; + *b = *a; + *a = temp; + $(HILITE }) + } +--- + +$(P +The output: +) + +$(SHELL +before: 1 and 2 +after : 1 and 2 $(SHELL_NOTE correct result) +) + +$(P +$(IX lock) The effect of $(C synchronized) is to create a lock behind the scenes and to allow only one thread hold that lock at a given time. Only the thread that holds the lock can be executed and the others wait until the lock becomes available again when the executing thread completes its $(C synchronized) block. Since one thread executes the $(I synchronized) code at a time, each thread would now swap the values safely before another thread does the same. The state of the variables $(C i) and $(C j) would always be either "1 and 2" or "2 and 1" at the end of processing the synchronized block. +) + +$(P +$(I $(B Note:) It is a relatively expensive operation for a thread to wait for a lock, which may slow down the execution of the program noticeably. Fortunately, in some cases program correctness can be ensured without the use of a $(C synchronized) block, by taking advantage of $(I atomic operations) that will be explained below.) +) + +$(P +When it is needed to synchronize more than one block of code, it is possible to specify one or more locks with the $(C synchronized) keyword. +) + +$(P +Let's see an example of this in the following program that has two separate code blocks that access the same shared variable. The program calls two functions with the address of the same variable, one function incrementing and the other function decrementing it equal number of times: +) + +--- +void incrementer(shared(int) * value) { + foreach (i; 0 .. count) { + *value = *value + 1; + } +} + +void decrementer(shared(int) * value) { + foreach (i; 0 .. count) { + *value = *value - 1; + } +} +--- + +$(P +$(I $(B Note:) If the shorter equivalents of the expression above are used (i.e. $(C ++(*value)) and $(C ‑‑(*value))), then the compiler warns that such read-modify-write operations on $(C shared) variables are deprecated.) +) + +$(P +Unfortunately, marking those blocks individually with $(C synchronized) is not sufficient, because the anonymous locks of the two blocks would be independent. So, the two code blocks would still be accessing the same variable concurrently: +) + +--- +import std.stdio; +import std.concurrency; +import core.thread; + +enum count = 1000; + +void incrementer(shared(int) * value) { + foreach (i; 0 .. count) { + $(HILITE synchronized) { // ← This lock is different from the one below. + *value = *value + 1; + } + } +} + +void decrementer(shared(int) * value) { + foreach (i; 0 .. count) { + $(HILITE synchronized) { // ← This lock is different from the one above. + *value = *value - 1; + } + } +} + +void main() { + shared(int) number = 0; + + foreach (i; 0 .. 100) { + spawn(&incrementer, &number); + spawn(&decrementer, &number); + } + + thread_joinAll(); + writeln("Final value: ", number); +} +--- + +$(P +Since there are equal number of threads that increment and decrement the same variable equal number of times, one would expect the final value of $(C number) to be zero. However, that is almost never the case: +) + +$(SHELL +Final value: -672 $(SHELL_NOTE_WRONG not zero) +) + +$(P +For more than one block to use the same lock or locks, the lock objects must be specified within the $(C synchronized) parentheses: +) + +$(P +$(HILITE $(I $(B Note:) This feature is not supported by dmd $(DVER).)) +) + +--- + $(CODE_COMMENT Note: dmd $(DVER) does not support this feature.) + synchronized ($(I lock_object), $(I another_lock_object), ...) +--- + +$(P +There is no need for a special lock type in D because any class object can be used as a $(C synchronized) lock. The following program defines an empty class named $(C Lock) to use its objects as locks: +) + +--- +import std.stdio; +import std.concurrency; +import core.thread; + +enum count = 1000; + +$(HILITE class Lock { +}) + +void incrementer(shared(int) * value, $(HILITE shared(Lock) lock)) { + foreach (i; 0 .. count) { + synchronized $(HILITE (lock)) { + *value = *value + 1; + } + } +} + +void decrementer(shared(int) * value, $(HILITE shared(Lock) lock)) { + foreach (i; 0 .. count) { + synchronized $(HILITE (lock)) { + *value = *value - 1; + } + } +} + +void main() { + $(HILITE shared(Lock) lock = new shared(Lock)()); + shared(int) number = 0; + + foreach (i; 0 .. 100) { + spawn(&incrementer, &number, $(HILITE lock)); + spawn(&decrementer, &number, $(HILITE lock)); + } + + thread_joinAll(); + writeln("Final value: ", number); +} +--- + +$(P +Because this time both $(C synchronized) blocks are connected by the same lock, only one of them is executed at a given time and the result is zero as expected: +) + +$(SHELL +Final value: 0 $(SHELL_NOTE correct result) +) + +$(P +Class types can be defined as $(C synchronized) as well. This means that all of the non-static member functions of that type are synchronized on a given object of that class: +) + +--- +$(HILITE synchronized) class Class { + void foo() { + // ... + } + + void bar() { + // ... + } +} +--- + +$(P +The following is the equivalent of the class definition above: +) + +--- +class Class { + void foo() { + synchronized (this) { + // ... + } + } + + void bar() { + synchronized (this) { + // ... + } + } +} +--- + +$(P +When blocks of code need to be synchronized on more than one object, those objects must be specified together. Otherwise, it is possible that more than one thread may have locked objects that other threads are waiting for, in which case the program may be $(I deadlocked). +) + +$(P +A well known example of this problem is a function that tries to transfer money from one bank account to another. For this function to work correctly in a multi-threaded environment, both of the accounts must first be locked. However, the following attempt would be incorrect: +) + +--- +void transferMoney(shared BankAccount from, + shared BankAccount to) { + synchronized (from) { $(CODE_NOTE_WRONG INCORRECT) + synchronized (to) { + // ... + } + } +} +--- + +$(P +$(IX deadlock) The error can be explained by an example where one thread attempting to transfer money from account A to account to B while another thread attempting to transfer money in the reverse direction. It is possible that each thread may have just locked its respective $(C from) object, hoping next to lock its $(C to) object. Since the $(C from) objects correspond to A and B in the two threads respectively, the objects would be in locked state in separate threads, making it impossible for the other thread to ever lock its $(C to) object. This situation is called a $(I deadlock). +) + +$(P +The solution to this problem is to define an ordering relation between the objects and to lock them in that order, which is handled automatically by the $(C synchronized) statement. In D, it is sufficient to specify the objects in the same $(C synchronized) statement for the code to avoid such deadlocks: +) + +$(P +$(HILITE $(I $(B Note:) This feature is not supported by dmd $(DVER).)) +) + +--- +void transferMoney(shared BankAccount from, + shared BankAccount to) { + $(CODE_COMMENT Note: dmd $(DVER) does not support this feature.) + synchronized (from, to) { $(CODE_NOTE correct) + // ... + } +} +--- + +$(H5 $(IX shared static this) $(IX static this, shared) $(IX shared static ~this) $(IX static ~this, shared) $(IX this, shared static) $(IX ~this, shared static) $(IX module constructor, shared) $(C shared static this()) for single initialization and $(C shared static ~this()) for single finalization) + +$(P +We have already seen that $(C static this()) can be used for initializing modules, including their variables. Because data is thread-local by default, $(C static this()) must be executed by every thread so that module-level variables are initialized for all threads: +) + +--- +import std.stdio; +import std.concurrency; +import core.thread; + +static this() { + writeln("executing static this()"); +} + +void worker() { +} + +void main() { + spawn(&worker); + + thread_joinAll(); +} +--- + +$(P +The $(C static this()) block above would be executed once for the main thread and once for the worker thread: +) + +$(SHELL +executing static this() +executing static this() +) + +$(P +This would cause problems for $(C shared) module variables because initializing a variable more than once would be wrong especially in concurrency due to race conditions. (That applies to $(C immutable) variables as well because they are implicitly $(C shared).) The solution is to use $(C shared static this()) blocks, which are executed only once per program: +) + +--- +int a; // thread-local +immutable int b; // shared by all threads + +static this() { + writeln("Initializing per-thread variable at ", &a); + a = 42; +} + +$(HILITE shared) static this() { + writeln("Initializing per-program variable at ", &b); + b = 43; +} +--- + +$(P +The output: +) + +$(SHELL +Initializing per-program variable at 6B0120 $(SHELL_NOTE only once) +Initializing per-thread variable at 7FBDB36557D0 +Initializing per-thread variable at 7FBDB3554670 +) + +$(P +Similarly, $(C shared static ~this()) is for final operations that must be executed only once per program. +) + +$(H5 $(IX atomic operation) Atomic operations) + +$(P +Another way of ensuring that only one thread mutates a certain variable is by using atomic operations, functionality of which are provided by the microprocessor, the compiler, or the operating system. +) + +$(P +The atomic operations of D are in the $(C core.atomic) module. We will see only two of its functions in this chapter: +) + +$(H6 $(IX atomicOp, core.atomic) $(C atomicOp)) + +$(P +This function applies its template parameter to its two function parameters. The template parameter must be a $(I binary operator) like $(STRING "+"), $(STRING "+="), etc. +) + +--- +import core.atomic; + +// ... + + atomicOp!"+="(*value, 1); // atomic +--- + +$(P +The line above is the equivalent of the following line, with the difference that the $(C +=) operation would be executed without interruptions by other threads (i.e. it would be executed $(I atomically)): +) + +--- + *value += 1; // NOT atomic +--- + +$(P +Consequently, when it is only a binary operation that needs to be synchronized, then there is no need for a $(C synchronized) block, which is known to be slow because of needing to acquire a lock. The following equivalents of the $(C incrementer()) and $(C decrementer()) functions that use $(C atomicOp) are correct as well. Note that there is no need for the $(C Lock) class anymore either: +) + +--- +import core.atomic; + +//... + +void incrementer(shared(int) * value) { + foreach (i; 0 .. count) { + $(HILITE atomicOp!"+="(*value, 1)); + } +} + +void decrementer(shared(int) * value) { + foreach (i; 0 .. count) { + $(HILITE atomicOp!"-="(*value, 1)); + } +} +--- + +$(P +$(C atomicOp) can be used with other binary operators as well. +) + +$(H6 $(IX cas, core.atomic) $(C cas)) + +$(P +The name of this function is the abbreviation of "compare and swap". Its behavior can be described as $(I mutate the variable if it still has its currently known value). It is used by specifying the current and the desired values of the variable at the same time: +) + +--- + bool is_mutated = cas(address_of_variable, currentValue, newValue); +--- + +$(P +The fact that the value of the variable still equals $(C currentValue) when $(C cas()) is operating is an indication that no other thread has mutated the variable since it has last been read by this thread. If so, $(C cas()) assigns $(C newValue) to the variable and returns $(C true). On the other hand, if the variable's value is different from $(C currentValue) then $(C cas()) does not mutate the variable and returns $(C false). +) + +$(P +The following functions re-read the current value and call $(C cas()) until the operation succeeds. Again, these calls can be described as $(I if the value of the variable equals this old value, replace with this new value): +) + +--- +void incrementer(shared(int) * value) { + foreach (i; 0 .. count) { + int currentValue; + + do { + currentValue = *value; + } while (!$(HILITE cas(value, currentValue, currentValue + 1))); + } +} + +void decrementer(shared(int) * value) { + foreach (i; 0 .. count) { + int currentValue; + + do { + currentValue = *value; + } while (!$(HILITE cas(value, currentValue, currentValue - 1))); + } +} +--- + +$(P +The functions above work correctly without the need for $(C synchronized) blocks. +) + +$(P +In most cases, the features of the $(C core.atomic) module can be several times faster than using $(C synchronized) blocks. I recommend that you consider this module as long as the operations that need synchronization are less than a block of code. +) + +$(P +Atomic operations enable $(I lock-free data structures) as well, which are beyond the scope of this book. +) + +$(P +You may also want to investigate the $(C core.sync) package, which contains classic concurrency primitives in the following modules: +) + +$(UL + +$(LI $(C core.sync.barrier)) +$(LI $(C core.sync.condition)) +$(LI $(C core.sync.config)) +$(LI $(C core.sync.exception)) +$(LI $(C core.sync.mutex)) +$(LI $(C core.sync.rwmutex)) +$(LI $(C core.sync.semaphore)) + +) + +$(H5 Summary) + +$(UL + +$(LI When threads do not depend on other threads, prefer $(I parallelism). Consider $(I concurrency) only when threads depend on operations of other threads.) + +$(LI Even then, prefer $(I message passing concurrency), which has been the topic of the previous chapter.) + +$(LI Only $(C shared) data can be shared; $(C immutable) is implicitly $(C shared).) + +$(LI $(C __gshared) provides data sharing as in C and C++ languages.) + +$(LI $(C synchronized) is for preventing other threads from intervening when a thread is executing a certain piece of code.) + +$(LI A class can be defined as $(C synchronized) so that only one member function can be executed on a given object at a given time. In other words, a thread can execute a member function only if no other thread is executing a member function on the same object.) + +$(LI $(C static this()) is executed once for each thread; $(C shared static this()) is executed once for the entire program.) + +$(LI The $(C core.atomic) module enables safe data sharing that can be multiple times faster than $(C synchronized).) + +$(LI The $(C core.sync) package includes many other concurrency primitives.) + +) + +macros: + TITLE=Data Sharing Concurrency + + DESCRIPTION=Executing multiple threads that share data. + + KEYWORDS=d programming language tutorial book concurrency thread data sharing diff --git a/book/d.en/cond_comp.d b/book/d.en/cond_comp.d new file mode 100644 index 0000000000..36c6afc8c2 --- /dev/null +++ b/book/d.en/cond_comp.d @@ -0,0 +1,670 @@ +Ddoc + +$(DERS_BOLUMU $(IX conditional compilation) Conditional Compilation) + +$(P +Conditional compilation is for compiling parts of programs in special ways depending on certain compile time conditions. Sometimes, entire sections of a program may need to be taken out and not compiled at all. +) + +$(P +Conditional compilation involves condition checks that are evaluable at compile time. Runtime conditional statements like $(C if), $(C for), $(C while) are not conditional compilation features. +) + +$(P +We have already encountered some features in the previous chapters, which can be seen as conditional compilation: +) + +$(UL + +$(LI +$(C unittest) blocks are compiled and run only if the $(C -unittest) compiler switch is enabled. +) + +$(LI +The contract programming blocks $(C in), $(C out), and $(C invariant) are activated only if the $(C -release) compiler switch is $(I not) enabled. +) + +) + +$(P +Unit tests and contracts are about program correctness; whether they are included in the program should not change the behavior of the program. +) + +$(P +The following are the features of D that are specifically for conditional compilation: +) + +$(UL +$(LI $(C debug)) +$(LI $(C version)) +$(LI $(C static if)) +$(LI $(C is) expression) +$(LI $(C __traits)) +) + +$(P +We will see the $(C is) expression in the next chapter. +) + +$(H5 $(IX debug) debug) + +$(P +$(IX -debug, compiler switch) $(C debug) is useful during program development. The expressions and statements that are marked as $(C debug) are compiled into the program only when the $(C -debug) compiler switch is enabled: +) + +--- +debug $(I a_conditionally_compiled_expression); + +debug { + // ... conditionally compiled code ... + +} else { + // ... code that is compiled otherwise ... +} +--- + +$(P +The $(C else) clause is optional. +) + +$(P +Both the single expression and the code block above are compiled only when the $(C -debug) compiler switch is enabled. +) + +$(P +We have been adding statements into the programs, which printed messages like "adding", "subtracting", etc. to the output. Such messages (aka $(I logs) and $(I log) messages) are helpful in finding errors by visualizing the steps that are taken by the program. +) + +$(P +Remember the $(C binarySearch()) function from $(LINK2 templates.html, the Templates chapter). The following version of the function is intentionally incorrect: +) + +--- +import std.stdio; + +// WARNING! This algorithm is wrong +size_t binarySearch(const int[] values, int value) { + if (values.length == 0) { + return size_t.max; + } + + immutable midPoint = values.length / 2; + + if (value == values[midPoint]) { + return midPoint; + + } else if (value < values[midPoint]) { + return binarySearch(values[0 .. midPoint], value); + + } else { + return binarySearch(values[midPoint + 1 .. $], value); + } +} + +void main() { + auto numbers = [ -100, 0, 1, 2, 7, 10, 42, 365, 1000 ]; + + auto index = binarySearch(numbers, 42); + writeln("Index: ", index); +} +--- + +$(P +Although the index of 42 is 6, the program incorrectly reports 1: +) + +$(SHELL_SMALL +Index: 1 +) + +$(P +One way of locating the bug in the program is to insert lines that would print messages to the output: +) + +--- +size_t binarySearch(const int[] values, int value) { + $(HILITE writefln)("searching %s among %s", value, values); + + if (values.length == 0) { + $(HILITE writefln)("%s not found", value); + return size_t.max; + } + + immutable midPoint = values.length / 2; + + $(HILITE writefln)("considering index %s", midPoint); + + if (value == values[midPoint]) { + $(HILITE writefln)("found %s at index %s", value, midPoint); + return midPoint; + + } else if (value < values[midPoint]) { + $(HILITE writefln)("must be in the first half"); + return binarySearch(values[0 .. midPoint], value); + + } else { + $(HILITE writefln)("must be in the second half"); + return binarySearch(values[midPoint + 1 .. $], value); + } +} +--- + +$(P +The output of the program now includes steps that the program takes: +) + +$(SHELL_SMALL +searching 42 among [-100, 0, 1, 2, 7, 10, 42, 365, 1000] +considering index 4 +must be in the second half +searching 42 among [10, 42, 365, 1000] +considering index 2 +must be in the first half +searching 42 among [10, 42] +considering index 1 +found 42 at index 1 +Index: 1 +) + +$(P +Let's assume that the previous output does indeed help the programmer locate the bug. It is obvious that the $(C writefln()) expressions are not needed anymore once the bug has been located and fixed. However, removing those lines can also be seen as wasteful, because they might be useful again in the future. +) + +$(P +Instead of being removed altogether, the lines can be marked as $(C debug) instead: +) + +--- + $(HILITE debug) writefln("%s not found", value); +--- + +$(P +Such lines are included in the program only when the $(C -debug) compiler switch is enabled: +) + +$(SHELL_SMALL +$ dmd deneme.d -ofdeneme -w $(HILITE -debug) +) + +$(H6 $(C debug($(I tag)))) + +$(P +If there are many $(C debug) keywords in the program, possibly in unrelated parts, the output may become too crowded. To avoid that, the $(C debug) statements can be given names (tags) to be included in the program selectively: +) + +--- + $(HILITE debug(binarySearch)) writefln("%s not found", value); +--- + +$(P +The tagged $(C debug) statements are enabled by the $(C -debug=$(I tag)) compiler switch: +) + +$(SHELL_SMALL +$ dmd deneme.d -ofdeneme -w $(HILITE -debug=binarySearch) +) + +$(P +$(C debug) blocks can have tags as well: +) + +--- + debug(binarySearch) { + // ... + } +--- + +$(P +It is possible to enable more than one $(C debug) tag at a time: +) + +$(SHELL_SMALL +$ dmd deneme.d -w $(HILITE -debug=binarySearch) $(HILITE -debug=stackContainer) +) + +$(P +In that case both the $(C binarySearch) and the $(C stackContainer) debug statements and blocks would be included. +) + +$(H6 $(C debug($(I level)))) + +$(P +Sometimes it is more useful to associate $(C debug) statements by numerical levels. Increasing levels can provide more detailed information: +) + +--- +$(HILITE debug) import std.stdio; + +void myFunction(string fileName, int[] values) { + $(HILITE debug(1)) writeln("entered myFunction"); + + $(HILITE debug(2)) { + writeln("the arguments:"); + writeln(" file name: ", fileName); + + foreach (i, value; values) { + writefln(" %4s: %s", i, value); + } + } + + // ... the implementation of the function ... +} + +void main() { + myFunction("deneme.txt", [ 10, 4, 100 ]); +} +--- + +$(P +The $(C debug) expressions and blocks that are lower than or equal to the specified level would be compiled: +) + +$(SHELL_SMALL +$ dmd deneme.d -w $(HILITE -debug=1) +$ ./deneme +$(SHELL_OBSERVED entered myFunction) +) + +$(P +The following compilation would provide more information: +) + +$(SHELL_SMALL +$ dmd deneme.d -w $(HILITE -debug=2) +$ ./deneme +$(SHELL_OBSERVED entered myFunction +the arguments: + file name: deneme.txt + 0: 10 + 1: 4 + 2: 100) +) + +$(H5 $(IX version) $(C version($(I tag))) and $(C version($(I level)))) + +$(P +$(C version) is similar to $(C debug) and is used in the same way: +) + +--- + version(testRelease) /* ... an expression ... */; + + version(schoolRelease) { + /* ... expressions that are related to the version of + * this program that is presumably shipped to schools ... */ + + } else { + // ... code compiled otherwise ... + } + + version(1) aVariable = 5; + + version(2) { + // ... a feature of version 2 ... + } +--- + +$(P +The $(C else) clause is optional. +) + +$(P +Although $(C version) works essentially the same as $(C debug), having separate keywords helps distinguish their unrelated uses. +) + +$(P +$(IX -version, compiler switch) As with $(C debug), more than one $(C version) can be enabled: +) + +$(SHELL_SMALL +$ dmd deneme.d -w $(HILITE -version=record) $(HILITE -version=precise_calculation) +) + +$(P +There are many predefined $(C version) tags, the complete list of which is available at the $(LINK2 http://dlang.org/version.html, Conditional Compilation specification). The following short list is just a sampling: +) + + + + + + + + + + + + + +
    Predefined $(C version) tags
    The compiler $(B DigitalMars GNU LDC SDC)
    The operating system $(B Windows Win32 Win64 linux OSX Posix FreeBSD +OpenBSD +NetBSD +DragonFlyBSD +BSD +Solaris +AIX +Haiku +SkyOS +SysV3 +SysV4 +Hurd)
    CPU endianness$(B LittleEndian BigEndian)
    Enabled compiler switches $(B D_Coverage D_Ddoc D_InlineAsm_X86 D_InlineAsm_X86_64 D_LP64 D_PIC D_X32 +D_HardFloat +D_SoftFloat +D_SIMD +D_Version2 +D_NoBoundsChecks +unittest +assert +)
    CPU architecture $(B X86 X86_64)
    Platform $(B Android +Cygwin +MinGW +ARM +ARM_Thumb +ARM_Soft +ARM_SoftFP +ARM_HardFP +ARM64 +PPC +PPC_SoftFP +PPC_HardFP +PPC64 +IA64 +MIPS +MIPS32 +MIPS64 +MIPS_O32 +MIPS_N32 +MIPS_O64 +MIPS_N64 +MIPS_EABI +MIPS_NoFloat +MIPS_SoftFloat +MIPS_HardFloat +SPARC +SPARC_V8Plus +SPARC_SoftFP +SPARC_HardFP +SPARC64 +S390 +S390X +HPPA +HPPA64 +SH +SH64 +Alpha +Alpha_SoftFP +Alpha_HardFP +)
    ... ...
    + +$(P +In addition, there are the following two special $(C version) tags: +) + +$(UL +$(LI $(IX none, version) $(C none): This tag is never defined; it is useful for disabling code blocks.) +$(LI $(IX all, version) $(C all): This tag is always defined; it is useful for enabling code blocks.) +) + +$(P +As an example of how predefined $(C version) tags are used, the following is an excerpt (formatted differently here) from the $(C std.ascii) module, which is for determining the newline character sequence for the system ($(C static assert) will be explained later below): +) + +--- +version(Windows) { + immutable newline = "\r\n"; + +} else version(Posix) { + immutable newline = "\n"; + +} else { + static assert(0, "Unsupported OS"); +} +--- + +$(H5 Assigning identifiers to $(C debug) and $(C version)) + +$(P +Similar to variables, $(C debug) and $(C version) can be assigned identifiers. Unlike variables, this assignment does not change any value, it activates the specified identifier $(I as well). +) + +--- +import std.stdio; + +debug(everything) { + debug $(HILITE =) binarySearch; + debug $(HILITE =) stackContainer; + version $(HILITE =) testRelease; + version $(HILITE =) schoolRelease; +} + +void main() { + debug(binarySearch) writeln("binarySearch is active"); + debug(stackContainer) writeln("stackContainer is active"); + + version(testRelease) writeln("testRelease is active"); + version(schoolRelease) writeln("schoolRelease is active"); +} +--- + +$(P +The assignments inside the $(C debug(everything)) block above activates all of the specified identifiers: +) + +$(SHELL_SMALL +$ dmd deneme.d -w -debug=everything +$ ./deneme +$(SHELL_OBSERVED binarySearch is active +stackContainer is active +testRelease is active +schoolRelease is active) +) + +$(H5 $(IX static if) $(IX if, static) $(C static if)) + +$(P +$(C static if) is the compile time equivalent of the $(C if) statement. +) + +$(P +Just like the $(C if) statement, $(C static if) takes a logical expression and evaluates it. Unlike the $(C if) statement, $(C static if) is not about execution flow; rather, it determines whether a piece of code should be included in the program or not. +) + +$(P +The logical expression must be evaluable at compile time. If the logical expression evaluates to $(C true), the code inside the $(C static if) gets compiled. If the condition is $(C false), the code is not included in the program as if it has never been written. The logical expressions commonly take advantage of the $(C is) expression and $(C __traits). +) + +$(P +$(C static if) can appear at module scope or inside definitions of $(C struct), $(C class), template, etc. Optionally, there may be $(C else) clauses as well. +) + +$(P +Let's use $(C static if) with a simple template, making use of the $(C is) expression. We will see other examples of $(C static if) in the next chapter: +) + +--- +import std.stdio; + +struct MyType(T) { + static if (is (T == float)) { + alias ResultType = double; + + } $(HILITE else static if) (is (T == double)) { + alias ResultType = real; + + } else { + static assert(false, T.stringof ~ " is not supported"); + } + + ResultType doWork() { + writefln("The return type for %s is %s.", + T.stringof, ResultType.stringof); + ResultType result; + // ... + return result; + } +} + +void main() { + auto f = MyType!float(); + f.doWork(); + + auto d = MyType!double(); + d.doWork(); +} +--- + +$(P +According to the code, $(C MyType) can be used only with two types: $(C float) or $(C double). The return type of $(C doWork()) is chosen depending on whether the template is instantiated for $(C float) or $(C double): +) + +$(SHELL +The return type for float is double. +The return type for double is real. +) + +$(P +Note that one must write $(C else static if) when chaining $(C static if) clauses. Otherwise, writing $(C else if) would result in inserting that $(C if) conditional into the code, which would naturally be executed at run time. +) + +$(H5 $(IX static assert) $(C static assert)) + +$(P +Although it is not a conditional compilation feature, I have decided to introduce $(C static assert) here. +) + +$(P +$(C static assert) is the compile time equivalent of $(C assert). If the conditional expression is $(C false), the compilation gets aborted due to that assertion failure. +) + +$(P +Similar to $(C static if), $(C static assert) can appear in any scope in the program. +) + +$(P +We have seen an example of $(C static assert) in the program above: There, compilation gets aborted if $(C T) is any type other than $(C float) or $(C double): +) + +--- + auto i = MyType!$(HILITE int)(); +--- + +$(P +The compilation is aborted with the message that was given to $(C static assert): +) + +$(SHELL +Error: static assert "int is not supported" +) + +$(P +As another example, let's assume that a specific algorithm can work only with types that are a multiple of a certain size. Such a condition can be ensured at compile time by a $(C static assert): +) + +--- +T myAlgorithm(T)(T value) { + /* This algorithm requires that the size of type T is a + * multiple of 4. */ + static assert((T.sizeof % 4) == 0); + + // ... +} +--- + +$(P +If the function was called with a $(C char), the compilation would be aborted with the following error message: +) + +$(SHELL_SMALL +Error: static assert (1LU == 0LU) is false +) + +$(P +Such a test prevents the function from working with an incompatible type, potentially producing incorrect results. +) + +$(P +$(C static assert) can be used with any logical expression that is evaluable at compile time. +) + +$(H5 $(IX type trait) $(IX traits) Type traits) + +$(P +$(IX __traits) $(IX std.traits) The $(C __traits) keyword and the $(C std.traits) module provide information about types and expressions at compile time. +) + +$(P +Some information that is collected by the compiler is made available to the program by $(C __traits). Its syntax includes a traits $(I keyword) and $(I parameters) that are relevant to that keyword: +) + +--- + __traits($(I keyword), $(I parameters)) +--- + +$(P +$(I keyword) specifies the information that is being queried. The $(I parameters) are either types or expressions, meanings of which are determined by each particular keyword. +) + +$(P +The information that can be gathered by $(C __traits) is especially useful in templates. For example, the $(C isArithmetic) keyword can determine whether a particular template parameter $(C T) is an arithmetic type: +) + +--- + static if (__traits($(HILITE isArithmetic), T)) { + // ... an arithmetic type ... + + } else { + // ... not an arithmetic type ... + } +--- + +$(P +Similarly, the $(C std.traits) module provides information at compile time through its templates. For example, $(C std.traits.isSomeChar) returns $(C true) if its template parameter is a character type: +) + +--- +import std.traits; + +// ... + + static if ($(HILITE isSomeChar)!T) { + // ... char, wchar, or dchar ... + + } else { + // ... not a character type ... + } +--- + +$(P +Please refer to $(LINK2 http://dlang.org/traits.html, the $(C __traits) documentation) and $(LINK2 http://dlang.org/phobos/std_traits.html, the $(C std.traits) documentation) for more information. +) + +$(H5 Summary) + +$(UL + +$(LI +Code that is defined as $(C debug) is included to the program only if the $(C -debug) compiler switch is used. +) + +$(LI +Code that is defined as $(C version) is included to the program only if a corresponding $(C -version) compiler switch is used. +) + +$(LI +$(C static if) is similar to an $(C if) statement that is executed at compile time. It introduces code to the program depending on certain compile-time conditions. +) + +$(LI +$(C static assert) validates assumptions about code at compile time. +) + +$(LI $(C __traits) and $(C std.traits) provide information about types at compile time.) + +) + +Macros: + TITLE=Conditional Compilation + + DESCRIPTION=Specifying parts of a program conditionally depending on logical expressions that are evaluated at compile time. + + KEYWORDS=d programming language tutorial book conditional compilation diff --git a/book/d.en/const_and_immutable.d b/book/d.en/const_and_immutable.d new file mode 100644 index 0000000000..9014c6a5bc --- /dev/null +++ b/book/d.en/const_and_immutable.d @@ -0,0 +1,758 @@ +Ddoc + +$(DERS_BOLUMU $(IX const) $(IX immutable) Immutability) + +$(P +We have seen that variables represent concepts in programs. The interactions of these concepts are achieved by expressions that change the values of those variables: +) + +--- + // Pay the bill + totalPrice = calculateAmount(itemPrices); + moneyInWallet $(HILITE -=) totalPrice; + moneyAtMerchant $(HILITE +=) totalPrice; +--- + +$(P +Modifying a variable is called $(I mutating) that variable. The concept of mutability is essential for most tasks. However, there are some cases where mutability is not desirable: +) + +$(UL + +$(LI +Some concepts are immutable by definition. For example, there are always seven days in a week, the math constant $(I pi) (π) never changes, the list of natural languages supported by a program may be fixed and small (e.g. only English and Turkish), etc. +) + +$(LI +If every variable were modifiable, as we have seen so far, then every piece of code that used a variable could potentially modify it. Even if there was no reason to modify a variable in an operation there would be no guarantee that this would not happen by accident. Programs are difficult to read and maintain when there are no immutability guarantees. + +$(P +For example, consider a function call $(C retire(office, worker)) that retires a worker of an office. If both of those variables were mutable it would not be clear (just by looking at that function call) which of them would be modified by the function. It may be expected that the number of active employees of $(C office) would be decreased, but would the function call also modify $(C worker) in some way? +) + +) + +) + +$(P +The concept of immutability helps with understanding parts of programs by guaranteeing that certain operations do not change certain variables. It also reduces the risk of some types of programming errors. +) + +$(P +The $(I immutability) concept is expressed in D by the $(C const) and $(C immutable) keywords. Although the two words themselves are close in meaning, their responsibilities in programs are different and they are sometimes incompatible. +) + +$(P +$(IX type qualifier) $(IX qualifier, type) $(C const), $(C immutable), $(C inout), and $(C shared) are $(I type qualifiers). (We will see $(LINK2 function_parameters.html, $(C inout)) and $(LINK2 concurrency_shared.html, $(C shared)) in later chapters.) +) + +$(H5 Immutable variables) + +$(P +Both of the terms "immutable variable" and "constant variable" are nonsensical when the word "variable" is taken literally to mean $(I something that changes). In a broader sense, the word "variable" is often understood to mean any concept of a program which may be mutable or immutable. +) + +$(P +There are three ways of defining variables that can never be mutated. +) + +$(H6 $(IX enum) $(C enum) constants) + +$(P +We have seen earlier in the $(LINK2 enum.html, $(C enum) chapter) that $(C enum) defines named constant values: +) + +--- + enum fileName = "list.txt"; +--- + +$(P +As long as their values can be determined at compile time, $(C enum) variables can be initialized with return values of functions as well: +) + +--- +int totalLines() { + return 42; +} + +int totalColumns() { + return 7; +} + +string name() { + return "list"; +} + +void main() { + enum fileName = name() ~ ".txt"; + enum totalSquares = totalLines() * totalColumns(); +} +--- + +$(P +The D feature that enables such initialization is $(I compile time function execution) (CTFE), which we will see in $(LINK2 functions_more.html, a later chapter). +) + + +$(P +As expected, the values of $(C enum) constants cannot be modified: +) + +--- + ++totalSquares; $(DERLEME_HATASI) +--- + +$(P +Although it is a very effective way of representing immutable values, $(C enum) can only be used for compile-time values. +) + +$(P +An $(C enum) constant is $(I a manifest constant), meaning that the program is compiled as if every mention of that constant had been replaced by its value. As an example, let's consider the following $(C enum) definition and the two expressions that make use of it: +) + +--- + enum i = 42; + writeln(i); + foo(i); +--- + +$(P +The code above is completely equivalent to the one below, where we replace every use of $(C i) with its value of $(C 42): +) + +--- + writeln(42); + foo(42); +--- + +$(P +Although that replacement makes sense for simple types like $(C int) and makes no difference to the resulting program, $(C enum) constants can bring a hidden cost when they are used for arrays or associative arrays: +) + +--- + enum a = [ 42, 100 ]; + writeln(a); + foo(a); +--- + +$(P +After replacing $(C a) with its value, the equivalent code that the compiler would be compiling is the following: +) + +--- + writeln([ 42, 100 ]); // an array is created at run time + foo([ 42, 100 ]); // another array is created at run time +--- + +$(P +The hidden cost here is that there would be two separate arrays created for the two expressions above. For that reason, it may make more sense to define arrays and associative arrays as $(C immutable) variables if they are going to be used more than once in the program. +) + +$(H6 $(IX variable, immutable) $(C immutable) variables) + +$(P +Like $(C enum), this keyword specifies that the value of a variable will never change. Unlike $(C enum), an $(C immutable) variable is an actual variable with a memory address, which means that we can set its value during the execution of the program and that we can refer to its memory location. +) + +$(P +The following program compares the uses of $(C enum) and $(C immutable). The program asks for the user to guess a number that has been picked randomly. Since the random number cannot be determined at compile time, it cannot be defined as an $(C enum). Still, since the randomly picked value must never be changed after having been decided, it is suitable to specify that variable as $(C immutable). +) + +$(P +The program takes advantage of the $(C readInt()) function that was defined in the previous chapter: +) + +--- +import std.stdio; +import std.random; + +int readInt(string message) { + int result; + write(message, "? "); + readf(" %s", &result); + return result; +} + +void main() { + enum min = 1; + enum max = 10; + + $(HILITE immutable) number = uniform(min, max + 1); + + writefln("I am thinking of a number between %s and %s.", + min, max); + + auto isCorrect = false; + while (!isCorrect) { + $(HILITE immutable) guess = readInt("What is your guess"); + isCorrect = (guess == number); + } + + writeln("Correct!"); +} +--- + +$(P +Observations: +) + +$(UL + +$(LI $(C min) and $(C max) are integral parts of the behavior of this program and their values are known at compile time. For that reason they are defined as $(C enum) constants. +) + +$(LI $(C number) is specified as $(C immutable) because it would not be appropriate to modify it after its initialization at run time. Likewise for each user guess: once read, the guess should not be modified. +) + +$(LI Observe that the types of those variables are not specified explicitly. As with $(C auto) and $(C enum), the type of an $(C immutable) variable can be inferred from the expression on the right hand side. +) + +) + +$(P +Although it is not necessary to write the type fully, $(C immutable) normally takes the actual type within parentheses, e.g. $(C immutable(int)). The output of the following program demonstrates that the full names of the types of the three variables are in fact the same: +) + +--- +import std.stdio; + +void main() { + immutable inferredType = 0; + immutable int explicitType = 1; + immutable(int) wholeType = 2; + + writeln(typeof(inferredType).stringof); + writeln(typeof(explicitType).stringof); + writeln(typeof(wholeType).stringof); +} +--- + +$(P +The actual name of the type includes $(C immutable): +) + +$(SHELL +immutable(int) +immutable(int) +immutable(int) +) + +$(P +The use of parentheses has significance, and specifies which parts of the type are immutable. We will see this below when discussing the immutability of the whole slice vs. its elements. +) + +$(H6 $(IX variable, const) $(C const) variables) + +$(P +When defining variables the $(C const) keyword has the same effect as $(C immutable). $(C const) variables cannot be modified: +) + +--- + $(HILITE const) half = total / 2; + half = 10; $(DERLEME_HATASI) +--- + +$(P +I recommend that you prefer $(C immutable) over $(C const) for defining variables. The reason is that $(C immutable) variables can be passed to functions that have $(C immutable) parameters. We will see this below. +) + +$(H5 Immutable parameters) + +$(P +It is possible for functions to promise that they do not modify certain parameters that they take, and the compiler will enforce this promise. Before seeing how this is achieved, let's first see that functions can indeed modify the elements of slices that are passed as arguments to those functions. +) + +$(P +As you would remember from the $(LINK2 slices.html, Slices and Other Array Features chapter), slices do not own elements but provide access to them. There may be more than one slice at a given time that provides access to the same elements. +) + +$(P +Although the examples in this section focus only on slices, this topic is applicable to associative arrays and classes as well because they too are $(I reference types). +) + +$(P +A slice that is passed as a function argument is not the slice that the function is called with. The argument is a copy of the actual slice: +) + +--- +import std.stdio; + +void main() { + int[] slice = [ 10, 20, 30, 40 ]; // 1 + halve(slice); + writeln(slice); +} + +void halve(int[] numbers) { // 2 + foreach (ref number; numbers) { + number /= 2; + } +} +--- + +$(P +When program execution enters the $(C halve()) function, there are two slices that provide access to the same four elements: +) + +$(OL + +$(LI The slice named $(C slice) that is defined in $(C main()), which is passed to $(C halve()) as its argument +) + +$(LI The slice named $(C numbers) that $(C halve()) receives as its argument, which provides access to the same elements as $(C slice) +) + +) + +$(P +Since both slides refer to the same elements and given that we use the $(C ref) keyword in the $(C foreach) loop, the values of the elements get halved: +) + +$(SHELL +[5, 10, 15, 20] +) + +$(P +It is useful for functions to be able to modify the elements of the slices that are passed as arguments. Some functions exist just for that purpose, as has been seen in this example. +) + +$(P +The compiler does not allow passing $(C immutable) variables as arguments to such functions because we cannot modify an immutable variable: +) + +--- + $(HILITE immutable) int[] slice = [ 10, 20, 30, 40 ]; + halve(slice); $(DERLEME_HATASI) +--- + +$(P +The compilation error indicates that a variable of type $(C immutable(int[])) cannot be used as an argument of type $(C int[]): +) + +$(SHELL +Error: function deneme.halve ($(HILITE int[]) numbers) is not callable +using argument types ($(HILITE immutable(int[]))) +) + +$(H6 $(IX parameter, const) $(C const) parameters) + +$(P +It is important and natural that $(C immutable) variables be prevented from being passed to functions like $(C halve()), which modify their arguments. However, it would be a limitation if they could not be passed to functions that do not modify their arguments in any way: +) + +--- +import std.stdio; + +void main() { + immutable int[] slice = [ 10, 20, 30, 40 ]; + print(slice); $(DERLEME_HATASI) +} + +void print(int[] slice) { + writefln("%s elements: ", slice.length); + + foreach (i, element; slice) { + writefln("%s: %s", i, element); + } +} +--- + +$(P +It does not make sense above that a slice is prevented from being printed just because it is $(C immutable). The proper way of dealing with this situation is by using $(C const) parameters. +) + +$(P +The $(C const) keyword specifies that a variable is not modified through $(I that particular reference) (e.g. a slice) of that variable. Specifying a parameter as $(C const) guarantees that the elements of the slice are not modified inside the function. Once $(C print()) provides this guarantee, the program can now be compiled: +) + +--- + print(slice); // now compiles +// ... +void print($(HILITE const) int[] slice) +--- + +$(P +This guarantee allows passing both mutable and $(C immutable) variables as arguments: +) + +--- + immutable int[] slice = [ 10, 20, 30, 40 ]; + print(slice); // compiles + + int[] mutableSlice = [ 7, 8 ]; + print(mutableSlice); // compiles +--- + +$(P +A parameter that is not modified in a function but is not specified as $(C const) reduces the applicability of that function. Additionally, $(C const) parameters provide useful information to the programmer. Knowing that a variable will not be modified when passed to a function makes the code easier to understand. It also prevents potential errors because the compiler detects modifications to $(C const) parameters: +) + +--- +void print($(HILITE const) int[] slice) { + slice[0] = 42; $(DERLEME_HATASI) +--- + +$(P +The programmer would either realize the mistake in the function or would rethink the design and perhaps remove the $(C const) specifier. +) + +$(P +The fact that $(C const) parameters can accept both mutable and $(C immutable) variables has an interesting consequence. This is explained in the "Should a parameter be $(C const) or $(C immutable)?" section below. +) + +$(H6 $(IX parameter, immutable) $(C immutable) parameters) + +$(P +As we saw above, both mutable and $(C immutable) variables can be passed to functions as their $(C const) parameters. In a way, $(C const) parameters are welcoming. +) + +$(P +In contrast, $(C immutable) parameters bring a strong requirement: only $(C immutable) variables can be passed to functions as their $(C immutable) parameters: +) + +--- +void func($(HILITE immutable) int[] slice) { + // ... +} + +void main() { + immutable int[] immSlice = [ 1, 2 ]; + int[] slice = [ 8, 9 ]; + + func(immSlice); // compiles + func(slice); $(DERLEME_HATASI) +} +--- + +$(P +For that reason, the $(C immutable) specifier should be used only when this requirement is actually necessary. We have indeed been using the $(C immutable) specifier indirectly through certain string types. This will be covered below. +) + +$(P +We have seen that the parameters that are specified as $(C const) or $(C immutable) promise not to modify $(I the actual variable) that is passed as an argument. This is relevant only for reference types because only then there is $(I the actual variable) to talk about the immutability of. +) + +$(P +$(I Reference types) and $(I value types) will be covered in the next chapter. Among the types that we have seen so far, only slices and associative arrays are reference types; the others are value types. +) + +$(H6 $(IX parameter, const vs. immutable) Should a parameter be $(C const) or $(C immutable)?) + +$(P +The two sections above may give the impression that, being more flexible, $(C const) parameters should be preferred over $(C immutable) parameters. This is not always true. +) + +$(P +$(C const) $(I erases) the information about whether the original variable was mutable or $(C immutable). This information is hidden even from the compiler. +) + +$(P +A consequence of this fact is that $(C const) parameters cannot be passed as arguments to functions that take $(C immutable) parameters. For example, $(C foo()) below cannot pass its $(C const) parameter to $(C bar()): +) + +--- +void main() { + /* The original variable is immutable */ + immutable int[] slice = [ 10, 20, 30, 40 ]; + foo(slice); +} + +/* A function that takes its parameter as const, in order to + * be more useful. */ +void foo(const int[] slice) { + bar(slice); $(DERLEME_HATASI) +} + +/* A function that takes its parameter as immutable, for a + * plausible reason. */ +void bar(immutable int[] slice) { + // ... +} +--- + +$(P +$(C bar()) requires the parameter to be $(C immutable). However, it is not known (in general) whether the original variable that $(C foo())'s $(C const) parameter references was $(C immutable) or not. +) + +$(P +$(I $(B Note:) It is clear in the code above that the original variable in $(C main()) is $(C immutable). However, the compiler compiles functions individually, without regard to all of the places that function is called from. To the compiler, the $(C slice) parameter of $(C foo()) may refer to a mutable variable or an $(C immutable) one. +) +) + +$(P +A solution would be to call $(C bar()) with an immutable copy of the parameter: +) + +--- +void foo(const int[] slice) { + bar(slice$(HILITE .idup)); +} +--- + +$(P +Although that is a sensible solution, it does incur into the cost of copying the slice and its contents, which would be wasteful in the case where the original variable was $(C immutable) to begin with. +) + +$(P +After this analysis, it should be clear that always declaring parameters as $(C const) is not the best approach in every situation. After all, if $(C foo())'s parameter had been defined as $(C immutable) there would be no need to copy it before calling $(C bar()): +) + +--- +void foo(immutable int[] slice) { // This time immutable + bar(slice); // Copying is not needed anymore +} +--- + +$(P +Although the code compiles, defining the parameter as $(C immutable) has a similar cost: this time an immutable copy of the original variable is needed when calling $(C foo()), if that variable was not immutable to begin with: +) + +--- + foo(mutableSlice$(HILITE .idup)); +--- + +$(P +Templates can help. (We will see templates in later chapters.) Although I don't expect you to fully understand the following function at this point in the book, I will present it as a solution to this problem. The following function template $(C foo()) can be called both with mutable and $(C immutable) variables. The parameter would be copied only if the original variable was mutable; no copying would take place if it were $(C immutable): +) + +--- +import std.conv; +// ... + +/* Because it is a template, foo() can be called with both mutable + * and immutable variables. */ +void foo(T)(T[] slice) { + /* 'to()' does not make a copy if the original variable is + * already immutable. */ + bar(to!(immutable T[])(slice)); +} +--- + +$(H5 Immutability of the slice versus the elements) + +$(P +We have seen above that the type of an $(C immutable) slice has been printed as $(C immutable(int[])). As the parentheses after $(C immutable) indicate, it is the entire slice that is $(C immutable). Such a slice cannot be modified in any way: elements may not be added or removed, their values may not be modified, and the slice may not start providing access to a different set of elements: +) + +--- + immutable int[] immSlice = [ 1, 2 ]; + immSlice ~= 3; $(DERLEME_HATASI) + immSlice[0] = 3; $(DERLEME_HATASI) + immSlice.length = 1; $(DERLEME_HATASI) + + immutable int[] immOtherSlice = [ 10, 11 ]; + immSlice = immOtherSlice; $(DERLEME_HATASI) +--- + +$(P +Taking immutability to that extreme may not be suitable in every case. In most cases, what is important is the immutability of the elements themselves. Since a slice is just a tool to access the elements, it should not matter if we make changes to the slice itself as long as the elements are not modified. This is especially true in the cases we have seen so far, where the function receives a copy of the slice itself. +) + +$(P +To specify that only the elements are immutable we use the $(C immutable) keyword with parentheses that enclose just the element type. Modifying the code accordingly, now only the elements are immutable, not the slice itself: +) + +--- + immutable$(HILITE (int))[] immSlice = [ 1, 2 ]; + immSlice ~= 3; // can add elements + immSlice[0] = 3; $(DERLEME_HATASI) + immSlice.length = 1; // can drop elements + + immutable int[] immOtherSlice = [ 10, 11 ]; + immSlice = immOtherSlice; /* can provide access to + * other elements */ +--- + +$(P +Although the two syntaxes are very similar, they have different meanings. To summarize: +) + +--- + immutable int[] a = [1]; /* Neither the elements nor the + * slice can be modified */ + + immutable(int[]) b = [1]; /* The same meaning as above */ + + immutable(int)[] c = [1]; /* The elements cannot be + * modified but the slice can be */ +--- + +$(P +This distinction has been in effect in some of the programs that we have written so far. As you may remember, the three string aliases involve immutability: +) + +$(UL +$(LI $(C string) is an alias for $(C immutable(char)[])) +$(LI $(C wstring) is an alias for $(C immutable(wchar)[])) +$(LI $(C dstring) is an alias for $(C immutable(dchar)[])) +) + +$(P +Likewise, string literals are immutable as well: +) + +$(UL +$(LI The type of literal $(STRING "hello"c) is $(C string)) +$(LI The type of literal $(STRING "hello"w) is $(C wstring)) +$(LI The type of literal $(STRING "hello"d) is $(C dstring)) +) + +$(P +According to these definitions, D strings are normally arrays of $(I immutable characters). +) + +$(H6 $(IX transitive, immutability) $(C const) and $(C immutable) are transitive) + +$(P +As mentioned in the code comments of slices $(C a) and $(C b) above, both those slices and their elements are $(C immutable). +) + +$(P +This is true for $(LINK2 struct.html, structs) and $(LINK2 class.html, classes) as well, both of which will be covered in later chapters. For example, all members of a $(C const) $(C struct) variable are $(C const) and all members of an $(C immutable) $(C struct) variable are $(C immutable). (Likewise for classes.) +) + +$(H6 $(IX .dup) $(IX .idup) $(C .dup) and $(C .idup)) + +$(P +There may be mismatches in immutability when strings are passed to functions as parameters. The $(C .dup) and $(C .idup) properties make copies of arrays with the desired mutability: +) + +$(UL +$(LI $(C .dup) makes a mutable copy of the array; its name comes from "duplicate") +$(LI $(C .idup) makes an immutable copy of the array) +) + +$(P +For example, a function that insists on the immutability of a parameter may have to be called with an immutable copy of a mutable string: +) + +--- +void foo($(HILITE string) s) { + // ... +} + +void main() { + char[] salutation; + foo(salutation); $(DERLEME_HATASI) + foo(salutation$(HILITE .idup)); // ← this compiles +} +--- + +$(H5 How to use) + +$(UL + +$(LI +As a general rule, prefer immutable variables over mutable ones. +) + +$(LI +Define constant values as $(C enum) if their values can be calculated at compile time. For example, the constant value of $(I seconds per minute) can be an $(C enum): + +--- + enum int secondsPerMinute = 60; +--- + +$(P +There is no need to specify the type explicitly if it can be inferred from the right hand side: +) + +--- + enum secondsPerMinute = 60; +--- + +) + +$(LI +Consider the hidden cost of $(C enum) arrays and $(C enum) associative arrays. Define them as $(C immutable) variables if the arrays are large and they are used more than once in the program. +) + +$(LI +Specify variables as $(C immutable) if their values will never change but cannot be known at compile time. Again, the type can be inferred: + +--- + immutable guess = readInt("What is your guess"); +--- + +) + +$(LI +If a function does not modify a parameter, specify that parameter as $(C const). This would allow both mutable and $(C immutable) variables to be passed as arguments: + +--- +void foo(const char[] s) { + // ... +} + +void main() { + char[] mutableString; + string immutableString; + + foo(mutableString); // ← compiles + foo(immutableString); // ← compiles +} +--- + +) + +$(LI +Following from the previous guideline, consider that $(C const) parameters cannot be passed to functions taking $(C immutable). See the section titled "Should a parameter be $(C const) or $(C immutable)?" above. +) + +$(LI +If the function modifies a parameter, leave that parameter as mutable ($(C const) or $(C immutable) would not allow modifications anyway): + +--- +import std.stdio; + +void reverse(dchar[] s) { + foreach (i; 0 .. s.length / 2) { + immutable temp = s[i]; + s[i] = s[$ - 1 - i]; + s[$ - 1 - i] = temp; + } +} + +void main() { + dchar[] salutation = "hello"d.dup; + reverse(salutation); + writeln(salutation); +} +--- + +$(P +The output: +) + +$(SHELL +olleh +) + +) + +) + +$(H5 Summary) + +$(UL + +$(LI $(C enum) variables represent immutable concepts that are known at compile time.) + +$(LI $(C immutable) variables represent immutable concepts that must be calculated at run time, or that must have some memory location that we can refer to.) + +$(LI $(C const) parameters are the ones that functions do not modify. Both mutable and $(C immutable) variables can be passed as arguments of $(C const) parameters.) + +$(LI $(C immutable) parameters are the ones that functions specifically require them to be so. Only $(C immutable) variables can be passed as arguments of $(C immutable) parameters.) + +$(LI $(C immutable(int[])) specifies that neither the slice nor its elements can be modified.) + +$(LI $(C immutable(int)[]) specifies that only the elements cannot be modified.) + +) + +Macros: + TITLE=Immutability + + DESCRIPTION=The const and immutable keywords of D, which support the concept of immutability. + + KEYWORDS=d programming language tutorial book immutable const diff --git a/book/d.en/const_member_functions.d b/book/d.en/const_member_functions.d new file mode 100644 index 0000000000..9fa9dabd26 --- /dev/null +++ b/book/d.en/const_member_functions.d @@ -0,0 +1,289 @@ +Ddoc + +$(DERS_BOLUMU $(CH4 const ref) Parameters and $(CH4 const) Member Functions) + +$(P +This chapter is about how parameters and member functions are marked as $(C const) so that they can be used with $(C immutable) variables as well. As we have already covered $(C const) parameters in earlier chapters, some information in this chapter will be a review of some of the features that you already know. +) + +$(P +Although the examples in this chapter use only structs, $(C const) member functions apply to classes as well. +) + +$(H5 $(C immutable) objects) + +$(P +We have already seen that it is not possible to modify $(C immutable) variables: +) + +--- + immutable readingTime = TimeOfDay(15, 0); +--- + +$(P +$(C readingTime) cannot be modified: +) + +--- + readingTime = TimeOfDay(16, 0); $(DERLEME_HATASI) + readingTime.minute += 10; $(DERLEME_HATASI) +--- + +$(P +The compiler does not allow modifying $(C immutable) objects in any way. +) + +$(H5 $(C ref) parameters that are not $(C const)) + +$(P +We have seen this concept earlier in the $(LINK2 function_parameters.html, Function Parameters chapter). Parameters that are marked as $(C ref) can freely be modified by the function. For that reason, even if the function does not actually modify the parameter, the compiler does not allow passing $(C immutable) objects as that parameter: +) + +--- +/* Although not being modified by the function, 'duration' + * is not marked as 'const' */ +int totalSeconds(ref Duration duration) { + return 60 * duration.minute; +} +// ... + $(HILITE immutable) warmUpTime = Duration(3); + totalSeconds(warmUpTime); $(DERLEME_HATASI) +--- + +$(P +The compiler does not allow passing the $(C immutable) $(C warmUpTime) to $(C totalSeconds) because that function does not guarantee that the parameter will not be modified. +) + +$(H5 $(IX const ref) $(IX ref const) $(IX parameter, const ref) $(C const ref) parameters) + +$(P +$(C const ref) means that the parameter is not modified by the function: +) + +--- +int totalSeconds(const ref Duration duration) { + return 60 * duration.minute; +} +// ... + immutable warmUpTime = Duration(3); + totalSeconds(warmUpTime); // ← now compiles +--- + +$(P +Such functions can receive $(C immutable) objects as parameters because the immutability of the object is enforced by the compiler: +) + +--- +int totalSeconds(const ref Duration duration) { + duration.minute = 7; $(DERLEME_HATASI) +// ... +} +--- + +$(P +$(IX in ref) $(IX ref in) $(IX parameter, in ref) An alternative to $(C const ref) is $(C in ref). As we will see in $(LINK2 function_parameters.html, a later chapter), $(C in) means that the parameter is used only as input to the function, disallowing any modification to it. +) + +--- +int totalSeconds($(HILITE in ref) Duration duration) { + // ... +} +--- + +$(H5 Non-$(C const) member functions) + +$(P +As we have seen with the $(C TimeOfDay.increment) member function, objects can be modified through member functions as well. $(C increment()) modifies the members of the object that it is called on: +) + +--- +struct TimeOfDay { +// ... + void increment(Duration duration) { + minute += duration.minute; + + hour += minute / 60; + minute %= 60; + hour %= 24; + } +// ... +} +// ... + auto start = TimeOfDay(5, 30); + start.increment(Duration(30)); // 'start' gets modified +--- + +$(H5 $(IX const, member function) $(C const) member functions ) + +$(P +Some member functions do not make any modifications to the object that they are called on. An example of such a function is $(C toString()): +) + +--- +struct TimeOfDay { +// ... + string toString() { + return format("%02s:%02s", hour, minute); + } +// ... +} +--- + +$(P +Since the whole purpose of $(C toString()) is to represent the object in string format anyway, it should not modify the object. +) + +$(P +The fact that a member function does not modify the object is declared by the $(C const) keyword after the parameter list: +) + +--- +struct TimeOfDay { +// ... + string toString() $(HILITE const) { + return format("%02s:%02s", hour, minute); + } +} +--- + +$(P +That $(C const) guarantees that the object itself is not going to be modified by the member function. As a consequence, $(C toString()) member function is allowed to be called even on $(C immutable) objects. Otherwise, the struct's $(C toString()) would not be called: +) + +--- +struct TimeOfDay { +// ... + // Inferior design: Not marked as 'const' + string toString() { + return format("%02s:%02s", hour, minute); + } +} +// ... + $(HILITE immutable) start = TimeOfDay(5, 30); + writeln(start); // TimeOfDay.toString() is not called! +--- + +$(P +The output is not the expected $(C 05:30), indicating that a generic function gets called instead of $(C TimeOfDay.toString): +) + +$(SHELL +immutable(TimeOfDay)(5, 30) +) + +$(P +Further, calling $(C toString()) on an $(C immutable) object explicitly would cause a compilation error: +) + +--- + auto s = start.toString(); $(DERLEME_HATASI) +--- + +$(P +Accordingly, the $(C toString()) functions that we have defined in the previous chapter have all been designed incorrectly; they should have been marked as $(C const). +) + +$(P $(I $(B Note:) The $(C const) keyword can be specified before the definition of the function as well:) +) + +--- + // The same as above + $(HILITE const) string toString() { + return format("%02s:%02s", hour, minute); + } +--- + +$(P $(I Since this version may give the incorrect impression that the $(C const) is a part of the return type, I recommend that you specify it after the parameter list.) +) + +$(H5 $(IX inout, member function) $(C inout) member functions) + +$(P +As we have seen in $(LINK2 function_parameters.html, the Function Parameters chapter), $(C inout) transfers the mutability of a parameter to the return type. +) + +$(P +Similarly, an $(C inout) member function transfers the mutability of the $(I object) to the function's return type: +) + +--- +import std.stdio; + +struct Container { + int[] elements; + + $(HILITE inout)(int)[] firstPart(size_t n) $(HILITE inout) { + return elements[0 .. n]; + } +} + +void main() { + { + // An immutable container + auto container = $(HILITE immutable)(Container)([ 1, 2, 3 ]); + auto slice = container.firstPart(2); + writeln(typeof(slice).stringof); + } + { + // A const container + auto container = $(HILITE const)(Container)([ 1, 2, 3 ]); + auto slice = container.firstPart(2); + writeln(typeof(slice).stringof); + } + { + // A mutable container + auto container = Container([ 1, 2, 3 ]); + auto slice = container.firstPart(2); + writeln(typeof(slice).stringof); + } +} +--- + +$(P +The three slices that are returned by the three objects of different mutability are consistent with the objects that returned them: +) + +$(SHELL +$(HILITE immutable)(int)[] +$(HILITE const)(int)[] +int[] +) + +$(P +Because it must be called on $(C const) and $(C immutable) objects as well, an $(C inout) member function is compiled as if it were $(C const). +) + +$(H5 How to use) + +$(UL + +$(LI +To give the guarantee that a parameter is not modified by the function, mark that parameter as $(C in), $(C const), or $(C const ref). +) + +$(LI +Mark member functions that do not modify the object as $(C const): + +--- +struct TimeOfDay { +// ... + string toString() $(HILITE const) { + return format("%02s:%02s", hour, minute); + } +} +--- + +$(P +This would make the struct (or class) more useful by removing an unnecessary limitation. The examples in the rest of the book will observe this guideline. +) + +) + +) + +Macros: + TITLE=const ref Parameters and const Member Functions + + DESCRIPTION=The const ref parameters and the const member functions of the D programming language + + KEYWORDS=d programming lesson book tutorial const member functions diff --git a/book/d.en/contracts.cozum.d b/book/d.en/contracts.cozum.d new file mode 100644 index 0000000000..d5bd508054 --- /dev/null +++ b/book/d.en/contracts.cozum.d @@ -0,0 +1,91 @@ +Ddoc + +$(COZUM_BOLUMU Contract Programming) + +$(P +The $(C unittest) block can be implemented trivially by copying the checks that are already written in $(C main()). The only addition below is the test for the case when the second team wins: +) + +--- +int addPoints(int goals1, int goals2, + ref int points1, ref int points2) +in { + assert(goals1 >= 0); + assert(goals2 >= 0); + assert(points1 >= 0); + assert(points2 >= 0); + +} out (result) { + assert((result >= 0) && (result <= 2)); + +} do { + int winner; + + if (goals1 > goals2) { + points1 += 3; + winner = 1; + + } else if (goals1 < goals2) { + points2 += 3; + winner = 2; + + } else { + ++points1; + ++points2; + winner = 0; + } + + return winner; +} + +unittest { + int points1 = 10; + int points2 = 7; + int winner; + + // First team wins + winner = addPoints(3, 1, points1, points2); + assert(points1 == 13); + assert(points2 == 7); + assert(winner == 1); + + // Draw + winner = addPoints(2, 2, points1, points2); + assert(points1 == 14); + assert(points2 == 8); + assert(winner == 0); + + // Second team wins + winner = addPoints(0, 1, points1, points2); + assert(points1 == 14); + assert(points2 == 11); + assert(winner == 2); +} + +void main() { + // ... +} +--- + +$(P +Expression-based contracts can be useful for this function: +) + +--- +int addPoints(int goals1, int goals2, + ref int points1, ref int points2) +in (goals1 >= 0) +in (goals2 >= 0) +in (points1 >= 0) +in (points2 >= 0) +out (result; (result >= 0) && (result <= 2)) { + // ... +} +--- + +Macros: + TITLE=Contract Programming + + DESCRIPTION=The exercise solutions for the Contract Programming chapter, explaining the features of D that help with program correctness. + + KEYWORDS=programming in d tutorial unit testing diff --git a/book/d.en/contracts.d b/book/d.en/contracts.d new file mode 100644 index 0000000000..e0bb2431dd --- /dev/null +++ b/book/d.en/contracts.d @@ -0,0 +1,430 @@ +Ddoc + +$(DERS_BOLUMU $(IX contract programming) Contract Programming) + +$(P +Contract programming is a software design approach that treats parts of software as individual entities that provide services to each other. This approach realizes that software can work according to its specification as long as the provider and the consumer of the service both obey a $(I contract). +) + +$(P +D's contract programming features involve functions as the units of software services. Like in unit testing, contract programming is also based on $(C assert) checks. +) + +$(P +Contract programming in D is implemented by three types of code blocks: +) + +$(UL +$(LI Function $(C in) blocks) +$(LI Function $(C out) blocks) +$(LI Struct and class $(C invariant) blocks) +) + +$(P +We will see $(C invariant) blocks and $(I contract inheritance) in $(LINK2 invariant.html, a later chapter) after covering structs and classes. +) + +$(H5 $(IX in, contract) $(IX precondition) $(C in) blocks for preconditions) + +$(P +Correct execution of functions usually depend on whether the values of their parameters are valid. For example, a square root function may require that its parameter cannot be negative. A function that deals with dates may require that the number of the month must be between 1 and 12. Such requirements of a function are called its $(I preconditions). +) + +$(P +We have already seen such condition checks in the $(LINK2 assert.html, $(C assert) and $(C enforce) chapter). Conditions on parameter values can be enforced by $(C assert) checks within function definitions: +) + +--- +string timeToString(int hour, int minute) { + assert((hour >= 0) && (hour <= 23)); + assert((minute >= 0) && (minute <= 59)); + + return format("%02s:%02s", hour, minute); +} +--- + +$(P +$(IX do, contract programming) In contract programming, the same checks are written inside the $(C in) blocks of functions. When an $(C in) or $(C out) block is used, the actual body of the function must be specified as a $(C do) block: +) + +--- +import std.stdio; +import std.string; + +string timeToString(int hour, int minute) +$(HILITE in) { + assert((hour >= 0) && (hour <= 23)); + assert((minute >= 0) && (minute <= 59)); + +} $(HILITE do) { + return format("%02s:%02s", hour, minute); +} + +void main() { + writeln(timeToString(12, 34)); +} +--- + +$(P +$(IX body) $(I $(B Note:) In earlier versions of D, the $(C body) keyword was used for this purpose instead of $(C do).) +) + +$(P +A benefit of an $(C in) block is that all of the preconditions can be kept together and separate from the actual body of the function. This way, the function body would be free of $(C assert) checks about the preconditions. As needed, it is still possible and advisable to have other $(C assert) checks inside the function body as unrelated checks that guard against potential programming errors in the function body. +) + +$(P +The code that is inside the $(C in) block is executed automatically every time the function is called. The actual execution of the function starts only if all of the $(C assert) checks inside the $(C in) block pass. This prevents executing the function with invalid preconditions and as a consequence, avoids producing incorrect results. +) + +$(P +An $(C assert) check that fails inside the $(C in) block indicates that the contract has been violated by the caller. +) + +$(H5 $(IX out, contract) $(IX postcondition) $(C out) blocks for postconditions) + +$(P +The other side of the contract involves guarantees that the function provides. Such guarantees are called the function's $(I postconditions). An example of a function with a postcondition would be a function that returns the number of days in February: The function can guarantee that the returned value would always be either 28 or 29. +) + +$(P +The postconditions are checked inside the $(C out) blocks of functions. +) + +$(P +Because the value that a function returns by the $(C return) statement need not be defined as a variable inside the function, there is usually no name to refer to the return value. This can be seen as a problem because the $(C assert) checks inside the $(C out) block cannot refer to the returned variable by name. +) + +$(P +D solves this problem by providing a way of naming the return value right after the $(C out) keyword. That name represents the very value that the function is in the process of returning: +) + +--- +int daysInFebruary(int year) +$(HILITE out (result)) { + assert((result == 28) || (result == 29)); + +} do { + return isLeapYear(year) ? 29 : 28; +} +--- + +$(P +Although $(C result) is a reasonable name for the returned value, other valid names may also be used. +) + +$(P +Some functions do not have return values or the return value need not be checked. In that case the $(C out) block does not specify a name: +) + +--- +out { + // ... +} +--- + +$(P +Similar to $(C in) blocks, the $(C out) blocks are executed automatically after the body of the function is executed. +) + +$(P +An $(C assert) check that fails inside the $(C out) block indicates that the contract has been violated by the function. +) + +$(P +As it has been obvious, $(C in) and $(C out) blocks are optional. Considering the $(C unittest) blocks as well, which are also optional, D functions may consist of up to four blocks of code: +) + +$(UL +$(LI $(C in): Optional) + +$(LI $(C out): Optional) + +$(LI $(C do): Mandatory but the $(C do) keyword may be skipped if no $(C in) or $(C out) block is defined.) + +$(LI $(C unittest): Optional and technically not a part of a function's definition but commonly defined right after the function.) +) + +$(P +Here is an example that uses all of these blocks: +) + +--- +import std.stdio; + +/* Distributes the sum between two variables. + * + * Distributes to the first variable first, but never gives + * more than 7 to it. The rest of the sum is distributed to + * the second variable. */ +void distribute(int sum, out int first, out int second) +in { + assert(sum >= 0, "sum cannot be negative"); + +} out { + assert(sum == (first + second)); + +} do { + first = (sum >= 7) ? 7 : sum; + second = sum - first; +} + +unittest { + int first; + int second; + + // Both must be 0 if the sum is 0 + distribute(0, first, second); + assert(first == 0); + assert(second == 0); + + // If the sum is less than 7, then all of it must be given + // to first + distribute(3, first, second); + assert(first == 3); + assert(second == 0); + + // Testing a boundary condition + distribute(7, first, second); + assert(first == 7); + assert(second == 0); + + // If the sum is more than 7, then the first must get 7 + // and the rest must be given to second + distribute(8, first, second); + assert(first == 7); + assert(second == 1); + + // A random large value + distribute(1_000_007, first, second); + assert(first == 7); + assert(second == 1_000_000); +} + +void main() { + int first; + int second; + + distribute(123, first, second); + writeln("first: ", first, " second: ", second); +} +--- + +$(P +The program can be compiled and run on the terminal by the following commands: +) + +$(SHELL +$ dmd deneme.d -w -unittest +$ ./deneme +$(SHELL_OBSERVED first: 7 second: 116) +) + +$(P +Although the actual work of the function consists of only two lines, there are a total of 19 nontrivial lines that support its functionality. It may be argued that so much extra code is too much for such a short function. However, bugs are never intentional. The programmer always writes code that is $(I expected to work correctly), which commonly ends up containing various types of bugs. +) + +$(P +When expectations are laid out explicitly by unit tests and contracts, functions that are initially correct have a greater chance of staying correct. I recommend that you take full advantage of any feature that improves program correctness. Both unit tests and contracts are effective tools toward that goal. They help reduce time spent for debugging, effectively increasing time spent for actually writing code. +) + +$(H5 $(IX expression-based contracts) Expression-based contracts) + +$(P +Although $(C in) and $(C out) blocks are useful for allowing any D code, precondition and postcondition checks are usually not more than simple $(C assert) expressions. As a convenience in such cases, there is a shorter expression-based contract syntax. Let's consider the following function: +) + +--- +int func(int a, int b) +in { + assert(a >= 7, "a cannot be less than 7"); + assert(b < 10); + +} out (result) { + assert(result > 1000); + +} do { + // ... +} +--- + +$(P +The expression-based contract obviates curly brackets, explicit $(C assert) calls, and the $(C do) keyword: +) + +--- +int func(int a, int b) +in (a >= 7, "a cannot be less than 7") +in (b < 10) +out ($(HILITE result;) result > 1000) { + // ... +} +--- + +$(P +Note how the return value of the function is named before a semicolon in the $(C out) contract. When there is no return value or when the $(C out) contract does not refer to the return value, the semicolon must still be present: +) + +--- +out ($(HILITE ;) /* ... */) +--- + +$(H5 $(IX -release, compiler switch) Disabling contract programming) + +$(P +Contrary to unit testing, contract programming features are enabled by default. The $(C ‑release) compiler switch disables contract programming: +) + +$(SHELL +$ dmd deneme.d -w -release +) + +$(P +When the program is compiled with the $(C ‑release) switch, the contents of $(C in), $(C out), and $(C invariant) blocks are ignored. +) + +$(H5 $(IX in vs. enforce) $(IX enforce vs. in) $(IX assert vs. enforce) $(IX enforce vs. assert) $(C in) blocks versus $(C enforce) checks) + +$(P +We have seen in the $(LINK2 assert.html, $(C assert) and $(C enforce) chapter) that sometimes it is difficult to decide whether to use $(C assert) or $(C enforce) checks. Similarly, sometimes it is difficult to decide whether to use $(C assert) checks within $(C in) blocks versus $(C enforce) checks within function bodies. +) + +$(P +The fact that it is possible to disable contract programming is an indication that contract programming is for protecting against programmer errors. For that reason, the decision here should be based on the same guidelines that we saw in the $(LINK2 assert.html, $(C assert) and $(C enforce) chapter): +) + +$(UL + +$(LI +If the check is guarding against a coding error, then it should be in the $(C in) block. For example, if the function is called only from other parts of the program, likely to help with achieving a functionality of it, then the parameter values are entirely the responsibility of the programmer. For that reason, the preconditions of such a function should be checked in its $(C in) block. +) + +$(LI +If the function cannot achieve some task for any other reason, including invalid parameter values, then it must throw an exception, conveniently by $(C enforce). + +$(P +To see an example of this, let's define a function that returns a slice of the middle of another slice. Let's assume that this function is for the consumption of the users of the module, as opposed to being an internal function used by the module itself. Since the users of this module can call this function by various and potentially invalid parameter values, it would be appropriate to check the parameter values every time the function is called. It would be insufficient to only check them at program development time, after which contracts can be disabled by $(C ‑release). +) + +$(P +For that reason, the following function validates its parameters by calling $(C enforce) in the function body instead of an $(C assert) check in the $(C in) block: +) + +--- +import std.exception; + +inout(int)[] middle(inout(int)[] originalSlice, size_t width) +out (result) { + assert(result.length == width); + +} do { + $(HILITE enforce)(originalSlice.length >= width); + + immutable start = (originalSlice.length - width) / 2; + immutable end = start + width; + + return originalSlice[start .. end]; +} + +unittest { + auto slice = [1, 2, 3, 4, 5]; + + assert(middle(slice, 3) == [2, 3, 4]); + assert(middle(slice, 2) == [2, 3]); + assert(middle(slice, 5) == slice); +} + +void main() { +} +--- + +$(P +There isn't a similar problem with the $(C out) blocks. Since the return value of every function is the responsibility of the programmer, postconditions must always be checked in the $(C out) blocks. The function above follows this guideline. +) + +) + +$(LI +Another criterion to consider when deciding between $(C in) blocks versus $(C enforce) is to consider whether the condition is recoverable. If it is recoverable by the higher layers of code, then it may be more appropriate to throw an exception, conveniently by $(C enforce). +) + +) + +$(PROBLEM_TEK + +$(P +Write a program that increases the total points of two football (soccer) teams according to the result of a game. +) + +$(P +The first two parameters of this function are the goals that each team has scored. The other two parameters are the points of each team before the game. This function should adjust the points of the teams according to the goals that they have scored. As a reminder, the winner takes 3 points and the loser takes no point. In the event of a draw, both teams get 1 point each. +) + +$(P +Additionally, the function should indicate which team has been the winner: 1 if the first team has won, 2 if the second team has won, and 0 if the game has ended in a draw. +) + +$(P +Start with the following program and fill in the four blocks of the function appropriately. Do not remove the $(C assert) checks in $(C main()); they demonstrate how this function is expected to work. +) + +--- +int addPoints(int goals1, int goals2, + ref int points1, ref int points2) +in { + // ... + +} out (result) { + // ... + +} do { + int winner; + + // ... + + return winner; +} + +unittest { + // ... +} + +void main() { + int points1 = 10; + int points2 = 7; + int winner; + + winner = addPoints(3, 1, points1, points2); + assert(points1 == 13); + assert(points2 == 7); + assert(winner == 1); + + winner = addPoints(2, 2, points1, points2); + assert(points1 == 14); + assert(points2 == 8); + assert(winner == 0); +} +--- + +$(P +Although I chose to return an $(C int), it would be better to return an $(C enum) value from this function: +) + +--- +enum GameResult { + draw, firstWon, secondWon +} + +$(HILITE GameResult) addPoints(int goals1, int goals2, + ref int points1, ref int points2) +// ... +--- + +) + +Macros: + TITLE=Contract Programming + + DESCRIPTION=The contract programming features of D that help with program correctness. + + KEYWORDS=d programming language tutorial book in out dbc diff --git a/book/d.en/copyright.d b/book/d.en/copyright.d new file mode 100644 index 0000000000..498fa49ca6 --- /dev/null +++ b/book/d.en/copyright.d @@ -0,0 +1,110 @@ +Ddoc + +
    + +$(P +Programming in D, First Edition +) + +$(BR) + +$(P +D version: $(DVER) +) + +$(P +Book revision: $(LINK2 https://bitbucket.org/acehreli/ddili, ) +) + +$(BR) + +$(P +The most recent electronic versions of this book are available $(LINK2 http://ddili.org, online). +) + +$(BR) +$(BR) + +$(P +Copyleft (ɔ) 2009-2020 Ali Çehreli +) + +$(BR) + +$(P +Creative Commons License +) +$(BR) +

    +This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/. +

    + +$(BR) +$(BR) + +$(P +Edited by $(LINK2 http://www.luismarques.eu, Luís Marques) +) + +$(BR) + +$(P +Cover design by $(LINK2 http://izgiyapici.com, İzgi Yapıcı) +) + +$(BR) + +$(P +Cover illustration by $(LINK2 mailto:sarah@reeceweb.com, Sarah Reece) +) + +$(BR) + +$(P +Published by $(LINK2 mailto:acehreli@yahoo.com, Ali Çehreli) +) + +$(BR) +$(BR) + +$(P +Fonts: +) +
      +
    • +Andada by Carolina Giovagnoli for Huerta Tipográfica +
    • +
    • +Open Sans by Steve Matteson +
    • +
    • +DejaVu Mono by DejaVu Fonts +
    • +
    + +$(BR) +$(P +PDF version is generated with Prince XML +) +$(P +Other ebook versions are generated with Calibre +) +$(BR) +$(P +ISBNs: +) +
      +
    • 978-0-692-59943-3 hardcover by IngramSpark
    • +
    • 978-0-692-52957-7 paperback by IngramSpark
    • +
    • 978-1-515-07460-1 paperback by CreateSpace
    • +
    • 978-1-519-95441-1 ePUB by Draft2Digital
    • +
    + +
    + +Macros: + TITLE=Copyleft + + DESCRIPTION=The copyleft page of Programming in D + + KEYWORDS=copyright diff --git a/book/d.en/cover_CreateSpace.pdf b/book/d.en/cover_CreateSpace.pdf new file mode 100644 index 0000000000..91e55448e2 Binary files /dev/null and b/book/d.en/cover_CreateSpace.pdf differ diff --git a/book/d.en/cover_IngramSpark_hardcover.pdf b/book/d.en/cover_IngramSpark_hardcover.pdf new file mode 100644 index 0000000000..dcd6ff0fae Binary files /dev/null and b/book/d.en/cover_IngramSpark_hardcover.pdf differ diff --git a/book/d.en/cover_IngramSpark_paperback.pdf b/book/d.en/cover_IngramSpark_paperback.pdf new file mode 100644 index 0000000000..7e69500e7e Binary files /dev/null and b/book/d.en/cover_IngramSpark_paperback.pdf differ diff --git a/book/d.en/cover_ebook.png b/book/d.en/cover_ebook.png new file mode 100644 index 0000000000..f9ae6c6d3b Binary files /dev/null and b/book/d.en/cover_ebook.png differ diff --git a/book/d.en/cover_thumb.png b/book/d.en/cover_thumb.png new file mode 100644 index 0000000000..e7f4b7e17a Binary files /dev/null and b/book/d.en/cover_thumb.png differ diff --git a/book/d.en/cozum_ozel.ddoc b/book/d.en/cozum_ozel.ddoc new file mode 100644 index 0000000000..37123b9a03 --- /dev/null +++ b/book/d.en/cozum_ozel.ddoc @@ -0,0 +1,6 @@ +MAIN_TITLE=D.ershane Solutions +CLASS=solution +COZUM_BOLUMU = $(H4 $0) +LANG=en +LANGUAGE=english +SUB_AUTHOR= diff --git a/book/d.en/derse_ozel.ddoc b/book/d.en/derse_ozel.ddoc new file mode 100644 index 0000000000..4771110d97 --- /dev/null +++ b/book/d.en/derse_ozel.ddoc @@ -0,0 +1,47 @@ +MAIN_TITLE=Programming in D +SUB_MAIN_TITLE_DERSE_OZEL=– Tutorial and Reference +SUB_AUTHOR=Ali Çehreli +LANG=en +LANGUAGE=english + +HORIZNAV_CONTENT_DERSE_OZEL=$(LINK2 rss.xml, RSS Programming in D RSS Feed) +$(BR) +$(LINK2 index.html, +Download or buy $(IMG book.png)) + +DUSEY_NAVIGASYON= +
    Other D Resources
    +$(UL +$(LI $(LINK2 http://wiki.dlang.org/Books, $(IMG bullet_black.png) Books)) +$(LI $(LINK2 http://forum.dlang.org/, $(IMG bullet_black.png) Newsgroups)) +$(LI $(LINK2 http://dlang.org/lex.html, $(IMG bullet_black.png) Language spec)) +$(LI $(LINK2 http://dlang.org/phobos/index.html, $(IMG bullet_black.png) Standard library)) +) + +$(UL +$(LI $(LINK2 $(ROOT_DIR)/ders/d/, $(IMG bullet_black.png) This book in Turkish)) +$(LI $(LINK2 mailto:acehreli@yahoo.com, $(IMG bullet_black.png) Contact)) +$(BR) +$(LI $(LINK2 $(ROOT_DIR)/copyright.html, $(IMG cc_80x15.png) Rights)) +) + +MINIBASLIK = $0 + + +BASLIK =

    $0

    + +ALTBASLIK =
    $0
    + + +MINI_SOZLUK= + +GERI_METIN=Prev +ILERI_METIN=Next +PROBLEM_METIN=Exercise +PROBLEM_COK_METIN=Exercises +PROBLEM_TEK_COZUMSUZ_METIN=the solution will be posted later... +PROBLEM_COK_COZUMSUZ_METIN=the solutions will be posted later... +COZUM_METIN=the solution +COZUMLER_METIN=the solutions + +DERLEME_HATASI_METIN=compilation ERROR diff --git a/book/d.en/destroy.d b/book/d.en/destroy.d new file mode 100644 index 0000000000..0de7a319c4 --- /dev/null +++ b/book/d.en/destroy.d @@ -0,0 +1,468 @@ +Ddoc + +$(DERS_BOLUMU $(CH4 destroy) and $(CH4 scoped)) + +$(P +We have seen the lifetimes of objects in the $(LINK2 lifetimes.html, Lifetimes and Fundamental Operations chapter). +) + +$(P +In later chapters, we have seen that the objects are prepared for use in the constructor, which is called $(C this()); and the final operations of objects are applied in the destructor, which is called $(C ~this()). +) + +$(P +For structs and other value types, the destructor is executed at the time when the lifetime of an object ends. For classes and other reference types, it is executed by the garbage collector some time in the future. The important distinction is that the destructor of a class object is not executed when its lifetime ends. +) + +$(P +System resources are commonly returned back to the system in destructors. For example, $(C std.stdio.File) returns the file resource back to the operating system in its destructor. As it is not certain when the destructor of a class object will be called, the system resources that it holds may not be returned until too late when other objects cannot get a hold of the same resource. +) + +$(H5 An example of calling destructors late) + +$(P +Let's define a class to see the effects of executing class destructors late. The following constructor increments a $(C static) counter, and the destructor decrements it. As you remember, there is only one of each $(C static) member, which is shared by all of the objects of a type. Such a counter would indicate the number of objects that are yet to be destroyed. +) + +--- +$(CODE_NAME LifetimeObserved)class LifetimeObserved { + int[] array; // ← Belongs to each object + + static size_t counter; // ← Shared by all objects + + this() { + /* We are using a relatively large array to make each + * object consume a large amount of memory. Hopefully + * this will make the garbage collector call object + * destructors more frequently to open up space for + * more objects. */ + array.length = 30_000; + + /* Increment the counter for this object that is being + * constructed. */ + ++counter; + } + + ~this() { + /* Decrement the counter for this object that is being + * destroyed. */ + --counter; + } +} +--- + +$(P +The following program constructs objects of that class inside a loop: +) + +--- +$(CODE_XREF LifetimeObserved)import std.stdio; + +void main() { + foreach (i; 0 .. 20) { + auto variable = new LifetimeObserved; // ← start + write(LifetimeObserved.counter, ' '); + } // ← end + + writeln(); +} +--- + +$(P +The lifetime of each $(C LifetimeObserved) object is in fact very short: Its life starts when it is constructed by the $(C new) keyword and ends at the closing curly bracket of the $(C foreach) loop. Each object then becomes the responsibility of the garbage collector. The $(COMMENT start) and $(COMMENT end) comments indicate the start and end of the lifetimes. +) + +$(P +Even though there is up to one object alive at a given time, the value of the counter indicates that the destructor is not executed when the lifetime ends: +) + +$(SHELL +1 2 3 4 5 6 7 8 2 3 4 5 6 7 8 2 3 4 5 6 +) + +$(P +According to that output, the memory sweep algorithm of the garbage collector has delayed executing the destructor for up to 8 objects. ($(I Note: The output may be different depending on the garbage collection algorithm, available memory, and other factors.)) +) + +$(H5 $(IX destroy) $(IX destructor, execution) $(C destroy()) to execute the destructor) + +$(P +$(C destroy()) executes the destructor for an object: +) + +--- +$(CODE_XREF LifetimeObserved)void main() { + foreach (i; 0 .. 20) { + auto variable = new LifetimeObserved; + write(LifetimeObserved.counter, ' '); + $(HILITE destroy(variable)); + } + + writeln(); +} +--- + +$(P +Like before, the value of $(C LifetimeObserved.counter) is incremented by the constructor as a result of $(C new), and becomes 1. This time, right after it gets printed, $(C destroy()) executes the destructor for the object and the value of the counter is decremented again down to zero. For that reason, this time its value is always 1: +) + +$(SHELL +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +) + +$(P +Once destroyed, the object should be considered to be in an invalid state and must not be used anymore: +) + +--- + destroy(variable); + // ... + // Warning: Using a potentially invalid object + writeln(variable.array); +--- + +$(P +Although $(C destroy()) is primarily for reference types, it can also be called on $(C struct) objects to destroy them before the end of their normal lifetimes. +) + +$(H5 When to use) + +$(P +As has been seen in the previous example, $(C destroy()) is used when resources need to be released at a specific time without relying on the garbage collector. +) + +$(H5 Example) + +$(P +We had designed an $(C XmlElement) struct in the $(LINK2 special_functions.html, Constructor and Other Special Functions chapter). That struct was being used for printing XML elements in the format $(C <tag>value</tag>). Printing the closing tag has been the responsibility of the destructor: +) + +--- +struct XmlElement { + // ... + + ~this() { + writeln(indentation, "'); + } +} +--- + +$(P +The following output was produced by a program that used that struct. This time, I am replacing the word "class" with "course" to avoid confusing it with the $(C class) keyword: +) + +$(SHELL +<courses> + <course0> + <grade> + 72 + </grade> $(SHELL_NOTE The closing tags appear on correct lines) + <grade> + 97 + </grade> $(SHELL_NOTE) + <grade> + 90 + </grade> $(SHELL_NOTE) + </course0> $(SHELL_NOTE) + <course1> + <grade> + 77 + </grade> $(SHELL_NOTE) + <grade> + 87 + </grade> $(SHELL_NOTE) + <grade> + 56 + </grade> $(SHELL_NOTE) + </course1> $(SHELL_NOTE) +</courses> $(SHELL_NOTE) +) + +$(P +The previous output happens to be correct because $(C XmlElement) is a $(C struct). The desired output is achieved simply by placing the objects in appropriate scopes: +) + +--- +void $(CODE_DONT_TEST)main() { + const $(HILITE courses) = XmlElement("courses", 0); + + foreach (courseId; 0 .. 2) { + const courseTag = "course" ~ to!string(courseId); + const $(HILITE courseElement) = XmlElement(courseTag, 1); + + foreach (i; 0 .. 3) { + const $(HILITE gradeElement) = XmlElement("grade", 2); + const randomGrade = uniform(50, 101); + + writeln(indentationString(3), randomGrade); + + } // ← gradeElement is destroyed + + } // ← courseElement is destroyed + +} // ← courses is destroyed +--- + +$(P +The destructor prints the closing tags as the objects gets destroyed. +) + +$(P +To see how classes behave differently, let's convert $(C XmlElement) to a class: +) + +--- +import std.stdio; +import std.array; +import std.random; +import std.conv; + +string indentationString(int level) { + return replicate(" ", level * 2); +} + +$(HILITE class) XmlElement { + string name; + string indentation; + + this(string name, int level) { + this.name = name; + this.indentation = indentationString(level); + + writeln(indentation, '<', name, '>'); + } + + ~this() { + writeln(indentation, "'); + } +} + +void main() { + const courses = $(HILITE new) XmlElement("courses", 0); + + foreach (courseId; 0 .. 2) { + const courseTag = "course" ~ to!string(courseId); + const courseElement = $(HILITE new) XmlElement(courseTag, 1); + + foreach (i; 0 .. 3) { + const gradeElement = $(HILITE new) XmlElement("grade", 2); + const randomGrade = uniform(50, 101); + + writeln(indentationString(3), randomGrade); + } + } +} +--- + +$(P +As the responsibility of calling the destructors are now left to the garbage collector, the program does not produce the desired output: +) + +$(SHELL_SMALL +<courses> + <course0> + <grade> + 57 + <grade> + 98 + <grade> + 87 + <course1> + <grade> + 84 + <grade> + 60 + <grade> + 99 + </grade> $(SHELL_NOTE The closing tags appear at the end) + </grade> $(SHELL_NOTE) + </grade> $(SHELL_NOTE) + </course1> $(SHELL_NOTE) + </grade> $(SHELL_NOTE) + </grade> $(SHELL_NOTE) + </grade> $(SHELL_NOTE) + </course0> $(SHELL_NOTE) +</courses> $(SHELL_NOTE) +) + +$(P +The destructor is still executed for every object but this time at the end when the program is exiting. ($(I Note: The garbage collector does not guarantee that the destructor will be called for every object. In reality, it is possible that there are no closing tags printed at all.)) +) + +$(P +$(C destroy()) ensures that the destructor is called at desired points in the program: +) + +--- +void $(CODE_DONT_TEST)main() { + const courses = new XmlElement("courses", 0); + + foreach (courseId; 0 .. 2) { + const courseTag = "course" ~ to!string(courseId); + const courseElement = new XmlElement(courseTag, 1); + + foreach (i; 0 .. 3) { + const gradeElement = new XmlElement("grade", 2); + const randomGrade = uniform(50, 101); + + writeln(indentationString(3), randomGrade); + + $(HILITE destroy(gradeElement)); + } + + $(HILITE destroy(courseElement)); + } + + $(HILITE destroy(courses)); +} +--- + +$(P +With those changes, the output of the code now matches the output of the code that use structs: +) + +$(SHELL +<courses> + <course0> + <grade> + 66 + </grade> $(SHELL_NOTE The closing tags appear on correct lines) + <grade> + 75 + </grade> $(SHELL_NOTE) + <grade> + 68 + </grade> $(SHELL_NOTE) + </course0> $(SHELL_NOTE) + <course1> + <grade> + 73 + </grade> $(SHELL_NOTE) + <grade> + 62 + </grade> $(SHELL_NOTE) + <grade> + 100 + </grade> $(SHELL_NOTE) + </course1> $(SHELL_NOTE) +</courses> $(SHELL_NOTE) +) + +$(H5 $(IX scoped) $(C scoped()) to call the destructor automatically) + +$(P +The program above has a weakness: The scopes may be exited before the $(C destroy()) lines are executed, commonly by thrown exceptions. If the $(C destroy()) lines must be executed even when exceptions are thrown, a solution is to take advantage of $(C scope()) and other features that we saw in the $(LINK2 exceptions.html, Exceptions chapter). +) + +$(P +Another solution is to construct class objects by $(C std.typecons.scoped) instead of by the $(C new) keyword. $(C scoped()) wraps the class object inside a $(C struct) and the destructor of that $(C struct) object destroys the class object when itself goes out of scope. +) + +$(P +The effect of $(C scoped()) is to make class objects behave similar to struct objects regarding lifetimes. +) + +$(P +With the following changes, the program produces the expected output as before: +) + +--- +$(HILITE import std.typecons;) +// ... +void $(CODE_DONT_TEST)main() { + const courses = $(HILITE scoped!)XmlElement("courses", 0); + + foreach (courseId; 0 .. 2) { + const courseTag = "course" ~ to!string(courseId); + const courseElement = $(HILITE scoped!)XmlElement(courseTag, 1); + + foreach (i; 0 .. 3) { + const gradeElement = $(HILITE scoped!)XmlElement("grade", 2); + const randomGrade = uniform(50, 101); + + writeln(indentationString(3), randomGrade); + } + } +} +--- + +$(P +Note that there are no $(C destroy()) lines anymore. +) + +$(P +$(IX proxy) $(IX RAII) $(C scoped()) is a function that returns a special $(C struct) object encapsulating the actual $(C class) object. The returned object acts as a proxy to the encapsulated one. (In fact, the type of $(C courses) above is $(C Scoped), not $(C XmlElement).) +) + +$(P +When the destructor of the $(C struct) object is called automatically as its lifetime ends, it calls $(C destroy()) on the $(C class) object that it encapsulates. (This is an application of the $(I Resource Acquisition Is Initialization) (RAII) idiom. $(C scoped()) achieves this by the help of $(LINK2 templates.html, templates) and $(LINK2 alias_this.html, $(C alias this)), both of which we will see in later chapters.) +) + +$(P +It is desirable for a proxy object to be used as conveniently as possible. In fact, the object that $(C scoped()) returns can be used exactly like the actual $(C class) type. For example, the member functions of the actual type can be called on it: +) + +--- +import std.typecons; + +class C { + void foo() { + } +} + +void main() { + auto p = scoped!C(); + p$(HILITE .foo()); // Proxy object p is being used as type C +} +--- + +$(P +However, that convenience comes with a price: The proxy object may hand out a reference to the actual object right before destroying it. This can happen when the actual $(C class) type is specified explicitly on the left hand-side: +) + +--- + $(HILITE C) c = scoped!C(); $(CODE_NOTE_WRONG BUG) + c.foo(); $(CODE_NOTE_WRONG Accesses a destroyed object) +--- + +$(P +In that definition, $(C c) is not the proxy object; rather, as defined by the programmer, a $(C class) variable referencing the encapsulated object. Unfortunately, the proxy object that is constructed on the right-hand side gets terminated at the end of the expression that constructs it. As a result, using $(C c) in the program would be an error, likely causing a runtime error: +) + +$(SHELL +Segmentation fault +) + +$(P +For that reason, do not define $(C scoped()) variables by the actual type: +) + +--- + $(HILITE C) a = scoped!C(); $(CODE_NOTE_WRONG BUG) + auto b = scoped!C(); $(CODE_NOTE correct) + const c = scoped!C(); $(CODE_NOTE correct) + immutable d = scoped!C(); $(CODE_NOTE correct) +--- + +$(H5 Summary) + +$(UL + +$(LI +$(C destroy()) is for executing the destructor of a class object explicitly. +) + +$(LI +Objects that are constructed by $(C scoped()) are destroyed upon leaving their respective scopes. +) + +$(LI It is a bug to define $(C scoped()) variables by the actual type.) + +) + +Macros: + TITLE=destroy and scoped + + DESCRIPTION=destroy() to call destructors explicitly on class objects and std.typecons.scoped to have the destructors executed on class objects automatically. + + KEYWORDS=d programming language tutorial book destroy scoped diff --git a/book/d.en/do_while.cozum.d b/book/d.en/do_while.cozum.d new file mode 100644 index 0000000000..5b6e2f7ac9 --- /dev/null +++ b/book/d.en/do_while.cozum.d @@ -0,0 +1,22 @@ +Ddoc + +$(COZUM_BOLUMU The $(C do-while) Loop) + +$(P +This program is not directly related to the $(C do-while) loop, as any problem that is solved by the $(C do-while) loop can also be solved by the other loop statements. +) + +$(P +The program can guess the number that the user is thinking of by shortening the candidate range from top or bottom according to the user's answers. For example, if its first guess is 50 and the user's reply is that the secret number is greater, the program would then know that the number must be in the range [51,100]. If the program then guesses another number right in the middle of that range, this time the number would be known to be either in the range [51,75] or in the range [76,100]. +) + +$(P +When the size of the range is 1, the program would be sure that it must be the number that the user has guessed. +) + +Macros: + TITLE=The do-while Loop Solutions + + DESCRIPTION=Programming in D exercise solutions: the 'do-while' loop + + KEYWORDS=programming in d tutorial do-while solution diff --git a/book/d.en/do_while.d b/book/d.en/do_while.d new file mode 100644 index 0000000000..38fd3343ba --- /dev/null +++ b/book/d.en/do_while.d @@ -0,0 +1,91 @@ +Ddoc + +$(DERS_BOLUMU $(IX do-while) $(IX loop, do-while) $(CH4 do-while) Loop) + +$(P +In the $(LINK2 for.html, $(C for) Loop chapter) we saw the steps in which the $(LINK2 while.html, $(C while) loop) is executed: +) + +$(MONO +preparation + +condition check +actual work +iteration + +condition check +actual work +iteration + +... +) + +$(P +The $(C do-while) loop is very similar to the $(C while) loop. The difference is that the $(I condition check) is performed at the end of each iteration of the $(C do-while) loop, so that the $(I actual work) is performed at least once: +) + +$(MONO +preparation + +actual work +iteration +condition check $(SHELL_NOTE at the end of the iteration) + +actual work +iteration +condition check $(SHELL_NOTE at the end of the iteration) + +... +) + +$(P +For example, $(C do-while) may be more natural in the following program where the user guesses a number, as the user must guess at least once so that the number can be compared: +) + +--- +import std.stdio; +import std.random; + +void main() { + int number = uniform(1, 101); + + writeln("I am thinking of a number between 1 and 100."); + + int guess; + + do { + write("What is your guess? "); + + readf(" %s", &guess); + + if (number < guess) { + write("My number is less than that. "); + + } else if (number > guess) { + write("My number is greater than that. "); + } + + } while (guess != number); + + writeln("Correct!"); +} +--- + +$(P +The function $(C uniform()) that is used in the program is a part of the $(C std.random) module. It returns a random number in the specified range. The way it is used above, the second number is considered to be outside of the range. In other words, $(C uniform()) would not return 101 for that call. +) + +$(PROBLEM_TEK + +$(P +Write a program that plays the same game but have the program do the guessing. If the program is written correctly, it should be able to guess the user's number in at most 7 tries. +) + +) + +Macros: + TITLE=do-while Loop + + DESCRIPTION=The do-while loop of the D programming languageh and comparing it to the while loop + + KEYWORDS=d programming language tutorial book do while loop diff --git a/book/d.en/encapsulation.d b/book/d.en/encapsulation.d new file mode 100644 index 0000000000..41148f3f2e --- /dev/null +++ b/book/d.en/encapsulation.d @@ -0,0 +1,508 @@ +Ddoc + +$(DERS_BOLUMU Encapsulation and Protection Attributes) + +$(P +All of the structs and classes that we have defined so far have all been accessible from the $(I outside). +) + +$(P +Let's consider the following struct: +) + +--- +enum Gender { female, male } + +struct Student { + string name; + Gender gender; +} +--- + +$(P +The members of that struct is freely accessible to the rest of the program: +) + +--- + auto student = Student("Tim", Gender.male); + writefln("%s is a %s student.", student$(HILITE .name), student$(HILITE .gender)); +--- + +$(P +Such freedom is a convenience in programs. For example, the previous line has been useful to produce the following output: +) + +$(SHELL_SMALL +Tim is a male student. +) + +$(P +However, this freedom is also a liability. As an example, let's assume that perhaps by mistake, the name of a student object gets modified in the program: +) + +--- + student.name = "Anna"; +--- + +$(P +That assignment may put the object in an invalid state: +) + +$(SHELL_SMALL +$(HILITE Anna) is a $(HILITE male) student. +) + +$(P +As another example, let's consider a $(C School) class. Let's assume that this class has two member variables that store the numbers of the male and female students separately: +) + +--- +class School { + Student[] students; + size_t femaleCount; + size_t maleCount; + + void add(Student student) { + students ~= student; + + final switch (student.gender) { + + case Gender.female: + $(HILITE ++femaleCount); + break; + + case Gender.male: + $(HILITE ++maleCount); + break; + } + } + + override string toString() const { + return format("%s female, %s male; total %s students", + femaleCount, maleCount, students.length); + } +} +--- + +$(P +The $(C add()) member function adds students while ensuring that the counts are always correct: +) + +--- + auto school = new School; + school.add(Student("Lindsey", Gender.female)); + school.add(Student("Mark", Gender.male)); + writeln(school); +--- + +$(P +The program produces the following consistent output: +) + +$(SHELL_SMALL +1 female, 1 male; total 2 students +) + +$(P +However, being able to access the members of $(C School) freely would not guarantee that this consistency would always be maintained. Let's consider adding a new element to the $(C students) member, this time directly: +) + +--- + school$(HILITE .students) ~= Student("Nancy", Gender.female); +--- + +$(P +Because the new student has been added to the array directly, without going through the $(C add()) member function, the $(C School) object is now in an inconsistent state: +) + +$(SHELL_SMALL +$(HILITE 1) female, $(HILITE 1) male; total $(HILITE 3) students +) + +$(H5 $(IX encapsulation) Encapsulation) + +$(P +Encapsulation is a programming concept of restricting access to members to avoid problems similar to the one above. +) + +$(P +Another benefit of encapsulation is to eliminate the need to know the implementation details of types. In a sense, encapsulation allows presenting a type as a black box that is used only through its interface. +) + +$(P +Additionally, preventing users from accessing the members directly allows changing the members of a class freely in the future. As long as the functions that define the interface of a class is kept the same, its implementation can be changed freely. +) + +$(P +Encapsulation is not for restricting access to sensitive data like a credit card number or a password, and it cannot be used for that purpose. Encapsulation is a development tool: It allows using and coding types easily and safely. +) + +$(H5 $(IX protection) $(IX access protection) Protection attributes) + +$(P +Protection attributes limit access to members of structs, classes, and modules. There are two ways of specifying protection attributes: +) + +$(UL + +$(LI +At struct or class level to specify the protection of every struct or class member individually. +) + +$(LI +At module level to specify the protection of every feature of a module individually: class, struct, function, enum, etc. +) + +) + +$(P +Protection attributes can be specified by the following keywords. The default attribute is $(C public). +) + +$(UL + +$(LI +$(IX public) +$(C public): Specifies accessibility by any part of the program without any restriction. + +$(P +An example of this is $(C stdout). Merely importing $(C std.stdio) makes $(C stdout) available to every module that imported it. +) + +) + +$(LI +$(IX private) +$(C private): Specifies restricted accessibility. + +$(P +$(C private) class members and module members can only be accessed by the module that defines that member. +) + +$(P +Additionally, $(C private) member functions cannot be overridden by subclasses. +) + +) + +$(LI +$(IX package, protection) +$(C package): Specifies package-level accessibility. + +$(P +A feature that is marked as $(C package) can be accessed by all of the code that is a part of the same package. The $(C package) attribute involves only the inner-most package. +) + +$(P +For example, a $(C package) definition that is inside the $(C animal.vertebrate.cat) module can be accessed by any other module of the $(C vertebrate) package. +) + +$(P +Similar to the $(C private) attribute, $(C package) member functions cannot be overridden by subclasses. +) + +) + +$(LI +$(IX protected) +$(C protected): Specifies accessibility by derived classes. + +$(P +This attribute extends the $(C private) attribute: A $(C protected) member can be accessed not only by the module that defines it, but also by the classes that inherit from the class that defines that $(C protected) member. +) + +) + +) + +$(P +$(IX export) Additionally, the $(C export) attribute specifies accessibility from the outside of the program. +) + +$(H5 Definition) + +$(P +Protection attributes can be specified in three ways. +) + +$(P +When written in front of a single definition, it specifies the protection attribute of that definition only. This is similar to the Java programming language: +) + +--- +private int foo; + +private void bar() { + // ... +} +--- + +$(P +When specified by a colon, it specifies the protection attributes of all of the following definitions until the next specification of a protection attribute. This is similar to the C++ programming language: +) + +--- +private: + // ... + // ... all of the definitions here are private ... + // ... + +protected: + // ... + // ... all of the definitions here are protected ... + // ... +--- + +$(P +When specified for a block, the protection attribute is for all of the definitions that are inside that block: +) + +--- +private { + // ... + // ... all of the definitions here are private ... + // ... +} +--- + +$(H5 Module imports are private by default) + +$(P +A module that is imported by $(C import) is private to the module that imports it. It would not be visible to other modules that import it indirectly. For example, if a $(C school) module imports $(C std.stdio), modules that import $(C school) cannot automatically use the $(C std.stdio) module. +) + +$(P +Let's assume that the $(C school) module starts by the following lines: +) + +--- +module school.school; + +import std.stdio; // imported for this module's own use... + +// ... +--- + +$(P +The following program cannot be compiled because $(C writeln) is not visible to it: +) + +--- +import school.school; + +void main() { + writeln("hello"); $(DERLEME_HATASI) +} +--- + +$(P +$(C std.stdio) must be imported by that module as well: +) + +--- +import school.school; +$(HILITE import std.stdio;) + +void main() { + writeln("hello"); // now compiles +} +--- + +$(P +$(IX public import) $(IX import, public) Sometimes it is desired that a module presents other modules indirectly. For example, it would make sense for a $(C school) module to automatically import a $(C student) module for its users. This is achieved by marking the $(C import) as $(C public): +) + +--- +module school.school; + +$(HILITE public import) school.student; + +// ... +--- + +$(P +With that definition, modules that import $(C school) can use the definitions that are inside the $(C student) module without needing to import it: +) + +--- +import school.school; + +void main() { + auto student = Student("Tim", Gender.male); + + // ... +} +--- + +$(P +Although the program above imports only the $(C school) module, the $(C student.Student) struct is also available to it. +) + +$(H5 When to use encapsulation) + +$(P +Encapsulation avoids problems similar to the one we have seen in the introduction section of this chapter. It is an invaluable tool to ensure that objects are always in consistent states. Encapsulation helps preserve struct and class $(I invariants) by protecting members from direct modifications by the users of the type. +) + +$(P +Encapsulation provides freedom of implementation by abstracting implementations away from user code. Otherwise, if users had direct access to for example $(C School.students), it would be hard to modify the design of the class by changing that array e.g. to an associative array, because this would affect all user code that has been accessing that member. +) + +$(P +Encapsulation is one of the most powerful benefits of object oriented programming. +) + +$(H5 Example) + +$(P +Let's define the $(C Student) struct and the $(C School) class by taking advantage of encapsulation and let's use them in a short test program. +) + +$(P +This example program will consist of three files. As you remember from the previous chapter, being parts of the $(C school) package, two of these files will be under the "school" directory: +) + +$(UL +$(LI "school/student.d": The $(C student) module that defines the $(C Student) struct) +$(LI "school/school.d": The $(C school) module that defines the $(C School) class) +$(LI "deneme.d": A short test program) +) + +$(P +Here is the "school/student.d" file: +) + +--- +module school.student; + +import std.string; +import std.conv; + +enum Gender { female, male } + +struct Student { + $(HILITE package) string name; + $(HILITE package) Gender gender; + + string toString() const { + return format("%s is a %s student.", + name, to!string(gender)); + } +} +--- + +$(P +The members of this struct are marked as $(C package) to enable access only to modules of the same package. We will soon see that $(C School) will be accessing these members directly. (Note that even this should be considered as violating the principle of encapsulation. Still, let's stick with the $(C package) attribute in this example program.) +) + +$(P +The following is the "school/school.d" module that makes use of the previous one: +) + +--- +module school.school; + +$(HILITE public import) school.student; // 1 + +import std.string; + +class School { +$(HILITE private:) // 2 + + Student[] students; + size_t femaleCount; + size_t maleCount; + +$(HILITE public:) // 3 + + void add(Student student) { + students ~= student; + + final switch (student$(HILITE .gender)) { // 4a + + case Gender.female: + ++femaleCount; + break; + + case Gender.male: + ++maleCount; + break; + } + } + + override string toString() const { + string result = format( + "%s female, %s male; total %s students", + femaleCount, maleCount, students.length); + + foreach (i, student; students) { + result ~= (i == 0) ? ": " : ", "; + result ~= student$(HILITE .name); // 4b + } + + return result; + } +} +--- + +$(OL + +$(LI +$(C school.student) is being imported publicly so that the users of $(C school.school) will not need to import that module explicitly. In a sense, the $(C student) module is made available by the $(C school) module. +) + +$(LI +All of the member variables of $(C School) are marked as private. This is important to help protect the consistency of the member variables of this class. +) + +$(LI +For this class to be useful, it must present some member functions. $(C add()) and $(C toString()) are made available to the users of this class. +) + +$(LI +As the two member variables of $(C Student) have been marked as $(C package), being a part of the same package, $(C School) can access those variables. +) + +) + +$(P +Finally, the following is a test program that uses those types: +) + +--- +import std.stdio; +import school.school; + +void main() { + auto student = Student("Tim", Gender.male); + writeln(student); + + auto school = new School; + + school.add(Student("Lindsey", Gender.female)); + school.add(Student("Mark", Gender.male)); + school.add(Student("Nancy", Gender.female)); + + writeln(school); +} +--- + +$(P +This program can use $(C Student) and $(C School) only through their public interfaces. It cannot access the member variables of those types. As a result, the objects would always be consistent: +) + +$(SHELL_SMALL +Tim is a male student. +2 female, 1 male; total 3 students: Lindsey, Mark, Nancy +) + +$(P +Note that the program interacts with $(C School) only by its $(C add()) and $(C toString()) functions. As long as the interfaces of these functions are kept the same, changes in their implementations would not affect the program above. +) + +Macros: + TITLE=Encapsulation and Protection Attributes + + DESCRIPTION=Encapsulating data by the protection attributes of D. + + KEYWORDS=d programming lesson book tutorial encapsulation diff --git a/book/d.en/enum.cozum.d b/book/d.en/enum.cozum.d new file mode 100644 index 0000000000..7ce61d0a52 --- /dev/null +++ b/book/d.en/enum.cozum.d @@ -0,0 +1,94 @@ +Ddoc + +$(COZUM_BOLUMU $(C enum)) + +--- +import std.stdio; +import std.conv; + +enum Operation { exit, add, subtract, multiply, divide } + +void main() { + // Print the supported operations + write("Operations - "); + for (Operation operation; + operation <= Operation.max; + ++operation) { + + writef("%d:%s ", operation, operation); + } + writeln(); + + // Unconditional loop until the user wants to exit + while (true) { + write("Operation? "); + + // The input must be read in the actual type (int) of + // the enum + int operationCode; + readf(" %s", &operationCode); + + /* We will start using enum values instead of magic + * constants from this point on. So, the operation code + * that has been read in int must be converted to its + * corresponding enum value. + * + * (Type conversions will be covered in more detail in + * a later chapter.) */ + Operation operation = cast(Operation)operationCode; + + if ((operation < Operation.min) || + (operation > Operation.max)) { + writeln("ERROR: Invalid operation"); + continue; + } + + if (operation == Operation.exit) { + writeln("Goodbye!"); + break; + } + + double first; + double second; + double result; + + write(" First operand? "); + readf(" %s", &first); + + write("Second operand? "); + readf(" %s", &second); + + switch (operation) { + + case Operation.add: + result = first + second; + break; + + case Operation.subtract: + result = first - second; + break; + + case Operation.multiply: + result = first * second; + break; + + case Operation.divide: + result = first / second; + break; + + default: + throw new Exception( + "ERROR: This line should have never been reached."); + } + + writeln(" Result: ", result); + } +} +--- + +Macros: + TITLE=enum Solutions + + DESCRIPTION=Programming in D exercise solutions: enum + + KEYWORDS=programming in d tutorial enum diff --git a/book/d.en/enum.d b/book/d.en/enum.d new file mode 100644 index 0000000000..d391fe7804 --- /dev/null +++ b/book/d.en/enum.d @@ -0,0 +1,334 @@ +Ddoc + +$(DERS_BOLUMU $(IX enum) $(CH4 enum)) + +$(P +$(C enum) is the feature that enables defining named constant values. +) + +$(H5 $(IX magic constant) Effects of magic constants on code quality) + +$(P +The following code appeared in the $(LINK2 arithmetic.cozum.html, exercise solutions) of the Integers and Arithmetic Operations chapter: +) + +--- + if (operation == 1) { + result = first + second; + + } else if (operation == 2) { + result = first - second; + + } else if (operation == 3) { + result = first * second; + + } else if (operation == 4) { + result = first / second; + } +--- + +$(P +The integer literals $(C 1), $(C 2), $(C 3), and $(C 4) in that piece of code are called $(I magic constants). It is not easy to determine what each of those literals means in the program. One must examine the code in each scope to determine that $(C 1) means $(I addition), $(C 2) means $(I subtraction), etc. This task is relatively easy for the code above because all of the scopes contain just a single line. It would be considerably more difficult to decipher the meanings of magic constants in most other programs. +) + +$(P +Magic constants must be avoided because they impair two important qualities of source code: readability and maintainability. +) + +$(P +$(C enum) enables giving names to such constants and, as a consequence, making the code more readable and maintainable. Each condition would be readily understandable if the following $(C enum) constants were used: +) + +--- + if (operation == Operation.add) { + result = first + second; + + } else if (operation == Operation.subtract) { + result = first - second; + + } else if (operation == Operation.multiply) { + result = first * second; + + } else if (operation == Operation.divide) { + result = first / second; + } +--- + +$(P +The $(C enum) type $(C Operation) above that obviates the need for magic constants $(C 1), $(C 2), $(C 3), and $(C 4) can be defined like this: +) + +--- + enum Operation { add = 1, subtract, multiply, divide } +--- + +$(H5 The $(C enum) syntax) + +$(P +The common definition of an $(C enum) is the following: +) + +--- + enum $(I TypeName) { $(I ValueName_1), $(I ValueName_2), /* etc. */ } +--- + +$(P +Sometimes it is necessary to specify the actual type (the $(I base type)) of the values as well: +) + +--- + enum $(I TypeName) $(HILITE : $(I base_type)) { $(I ValueName_1), $(I ValueName_2), /* etc. */ } +--- + +$(P +We will see how this is used in the next section. +) + +$(P +$(I TypeName) defines what the constants collectively mean. All of the member constants of an $(C enum) $(I type) are listed within curly brackets. Here are some examples: +) + +--- + enum HeadsOrTails { heads, tails } + enum Suit { spades, hearts, diamonds, clubs } + enum Fare { regular, child, student, senior } +--- + +$(P +Each set of constants becomes part of a separate type. For example, $(C heads) and $(C tails) become members of the type $(C HeadsOrTails). The new type can be used like other fundamental types when defining variables: +) + +--- + HeadsOrTails result; // default initialized + auto ht = HeadsOrTails.heads; // inferred type +--- + +$(P +As has been seen in the pieces of code above, the members of $(C enum) types are always specified by the name of their $(C enum) type: +) + +--- + if (result == $(HILITE HeadsOrTails.)heads) { + // ... + } +--- + +$(H5 Actual values and base types) + +$(P +The member constants of $(C enum) types are by default implemented as $(C int) values. In other words, although on the surface they appear as just names such as $(C heads) and $(C tails), they also have numerical values. ($(I $(B Note:) It is possible to choose a type other than $(C int) when needed.)). +) + +$(P +Unless explicitly specified by the programmer, the numerical values of $(C enum) members start at $(C 0) and are incremented by one for each member. For example, the two members of the $(C HeadsOrTails) $(C enum) have the numerical values 0 and 1: +) + +--- + writeln("heads is 0: ", (HeadsOrTails.heads == 0)); + writeln("tails is 1: ", (HeadsOrTails.tails == 1)); +--- + +$(P +The output: +) + +$(SHELL +heads is 0: true +tails is 1: true +) + +$(P +It is possible to manually (re)set the values at any point in the $(C enum). That was the case when we specified the value of $(C Operation.add) as 1 above. The following example manually sets a new count twice: +) + +--- + enum Test { a, b, c, ç $(HILITE = 100), d, e, f $(HILITE = 222), g, ğ } + writefln("%d %d %d", Test.b, Test.ç, Test.ğ); +--- + +$(P +The output: +) + +$(SHELL +1 100 224 +) + +$(P +If $(C int) is not suitable as the base type of the $(C enum) values, the base type can be specified explicitly after the name of the $(C enum): +) + +--- + enum NaturalConstant $(HILITE : double) { pi = 3.14, e = 2.72 } + enum TemperatureUnit $(HILITE : string) { C = "Celsius", F = "Fahrenheit" } +--- + +$(H5 $(C enum) values that are not of an $(C enum) type) + +$(P +We have discussed that it is important to avoid magic constants and instead to take advantage of the $(C enum) feature. +) + +$(P +However, sometimes it may not be natural to come up with $(C enum) type names just to use named constants. Let's assume that a named constant is needed to represent the number of seconds per day. It should not be necessary to also define an $(C enum) $(I type) to contain this constant value. All that is needed is a constant value that can be referred to by its name. In such cases, the type name of the $(C enum) and the curly brackets are omitted: +) + +--- + enum secondsPerDay = 60 * 60 * 24; +--- + +$(P +The type of the constant can be specified explicitly, which would be required if the type cannot be inferred from the right hand side: +) + +--- + enum $(HILITE int) secondsPerDay = 60 * 60 * 24; +--- + +$(P +Since there is no $(C enum) type to refer to, such named constants can be used in code simply by their names: +) + +--- + totalSeconds = totalDays * $(HILITE secondsPerDay); +--- + +$(P +$(C enum) can be used for defining named constants of other types as well. For example, the type of the following constant would be $(C string): +) + +--- + enum fileName = "list.txt"; +--- + +$(P +$(IX manifest constant) $(IX constant, manifest) Such constants are $(LINK2 lvalue_rvalue.html, $(I rvalues)) and they are called $(I manifest constants). +) + +$(P +It is possible to create manifest constants of arrays and associative arrays as well. However, as we will see later in $(LINK2 const_and_immutable.html, the Immutability chapter), $(C enum) arrays and associative arrays may have hidden costs. +) + +$(H5 Properties) + +$(P +The $(C .min) and $(C .max) properties are the minimum and maximum values of an $(C enum) type. When the values of the $(C enum) type are consecutive, they can be iterated over in a $(C for) loop within these limits: +) + +--- + enum Suit { spades, hearts, diamonds, clubs } + + for (auto suit = Suit$(HILITE .min); suit <= Suit$(HILITE .max); ++suit) { + writefln("%s: %d", suit, suit); + } +--- + +$(P +Format specifiers $(STRING "%s") and $(STRING "%d") produce different outputs: +) + +$(SHELL +spades: 0 +hearts: 1 +diamonds: 2 +clubs: 3 +) + +$(P +Note that a $(C foreach) loop over that range would leave the $(C .max) value out of the iteration: +) + +--- + foreach (suit; Suit.min .. Suit.max) { + writefln("%s: %d", suit, suit); + } +--- + +$(P +The output: +) + +$(SHELL +spades: 0 +hearts: 1 +diamonds: 2 + $(SHELL_NOTE_WRONG clubs is missing) +) + +$(P +$(IX EnumMembers, std.traits) For that reason, a correct way of iterating over all values of an $(C enum) is using the $(C EnumMembers) template from the $(C std.traits) module: +) + +--- +import std.traits; +// ... + foreach (suit; $(HILITE EnumMembers!Suit)) { + writefln("%s: %d", suit, suit); + } +--- + +$(P +$(I $(B Note:) The $(C !) character above is for template instantiations, which will be covered in $(LINK2 templates.html, a later chapter).) +) + +$(SHELL +spades: 0 +hearts: 1 +diamonds: 2 +clubs: 3 $(SHELL_NOTE clubs is present) +) + +$(H5 Converting from the base type) + +$(P +As we saw in the formatted outputs above, an $(C enum) value can automatically be converted to its base type (e.g. to $(C int)). The reverse conversion is not automatic: +) + +--- + Suit suit = 1; $(DERLEME_HATASI) +--- + +$(P +One reason for this is to avoid ending up with invalid $(C enum) values: +) + +--- + suit = 100; // ← would be an invalid enum value +--- + +$(P +The values that are known to correspond to valid $(C enum) values of a particular $(C enum) type can still be converted to that type by an explicit $(I type cast): +) + +--- + suit = cast(Suit)1; // now hearts +--- + +$(P +It would be the programmer's responsibility to ensure the validity of the values when an explicit cast is used. We will see type casting in $(LINK2 cast.html, a later chapter). +) + +$(PROBLEM_TEK + +$(P +Modify the calculator program from the exercises of the $(LINK2 arithmetic.html, Integers and Arithmetic Operations chapter) to have the user select the arithmetic operation from a menu. +) + +$(P +This program should be different from the previous one in at least the following areas: +) + +$(UL +$(LI Use $(C enum) values, not magic constants.) +$(LI Use $(C double) instead of $(C int).) +$(LI Use a $(C switch) statement instead of an "if, else if, else" chain.) +) + +) + +Macros: + TITLE=enum + + DESCRIPTION=The enum feature and how it is used to define named constant values. + + KEYWORDS=d programming language tutorial book enum diff --git a/book/d.en/exceptions.d b/book/d.en/exceptions.d new file mode 100644 index 0000000000..d0cc5b967f --- /dev/null +++ b/book/d.en/exceptions.d @@ -0,0 +1,995 @@ +Ddoc + +$(DERS_BOLUMU $(IX exception) Exceptions) + +$(P +Unexpected situations are parts of programs: user mistakes, programming errors, changes in the program environment, etc. Programs must be written in ways to avoid producing incorrect results when faced with such $(I exceptional) conditions. +) + +$(P +Some of these conditions may be severe enough to stop the execution of the program. For example, a required piece of information may be missing or invalid, or a device may not be functioning correctly. The exception handling mechanism of D helps with stopping program execution when necessary, and to recover from the unexpected situations when possible. +) + +$(P +As an example of a severe condition, we can think of passing an unknown operator to a function that knows only the four arithmetic operators, as we have seen in the exercises of the previous chapter: +) + +--- + switch (operator) { + + case "+": + writeln(first + second); + break; + + case "-": + writeln(first - second); + break; + + case "x": + writeln(first * second); + break; + + case "/": + writeln(first / second); + break; + + default: + throw new Exception(format("Invalid operator: %s", operator)); + } +--- + +$(P +The $(C switch) statement above does not know what to do with operators that are not listed on the $(C case) statements; so throws an exception. +) + +$(P +There are many examples of thrown exceptions in Phobos. For example, $(C to!int), which can be used to convert a string representation of an integer to an $(C int) value throws an exception when that representation is not valid: +) + +--- +import std.conv; + +void main() { + const int value = to!int("hello"); +} +--- + +$(P +The program terminates with an exception that is thrown by $(C to!int): +) + +$(SHELL +std.conv.ConvException@std/conv.d(38): std.conv(1157): $(HILITE Can't +convert value) `hello' of type const(char)[] to type int +) + +$(P +$(C std.conv.ConvException) at the beginning of the message is the type of the thrown exception object. We can tell from the name that the type is $(C ConvException) that is defined in the $(C std.conv) module. +) + +$(H5 $(IX throw) The $(C throw) statement to throw exceptions) + +$(P +We've seen the $(C throw) statement both in the examples above and in the previous chapters. +) + +$(P +$(C throw) throws an $(I exception object) and this terminates the current operation of the program. The expressions and statements that are written after the $(C throw) statement are not executed. This behavior is according to the nature of exceptions: they must be thrown when the program cannot continue with its current task. +) + +$(P +Conversely, if the program could continue then the situation would not warrant throwing an exception. In such cases the function would find a way and continue. +) + +$(H6 $(IX Exception) $(IX Error) $(IX Throwable) The exception types $(C Exception) and $(C Error)) + +$(P +Only the types that are inherited from the $(C Throwable) class can be thrown. $(C Throwable) is almost never used directly in programs. The types that are actually thrown are types that are inherited from $(C Exception) or $(C Error), which themselves are the types that are inherited from $(C Throwable). For example, all of the exceptions that Phobos throws are inherited from either $(C Exception) or $(C Error). +) + +$(P +$(C Error) represents unrecoverable conditions and is not recommended to be $(I caught). For that reason, most of the exceptions that a program throws are the types that are inherited from $(C Exception). ($(I $(B Note:) Inheritance is a topic related to classes. We will see classes in a later chapter.)) +) + +$(P +$(C Exception) objects are constructed with a $(C string) value that represents an error message. You may find it easy to create this message with the $(C format()) function from the $(C std.string) module: +) + +--- +import std.stdio; +import std.random; +import std.string; + +int[] randomDiceValues(int count) { + if (count < 0) { + $(HILITE throw new Exception)( + format("Invalid dice count: %s", count)); + } + + int[] values; + + foreach (i; 0 .. count) { + values ~= uniform(1, 7); + } + + return values; +} + +void main() { + writeln(randomDiceValues(-5)); +} +--- + +$(SHELL +object.Exception...: Invalid dice count: -5 +) + +$(P +In most cases, instead of creating an exception object explicitly by $(C new) and throwing it explicitly by $(C throw), the $(C enforce()) function is called. For example, the equivalent of the error check above is the following $(C enforce()) call: +) + +--- + enforce(count >= 0, format("Invalid dice count: %s", count)); +--- + +$(P +We will see the differences between $(C enforce()) and $(C assert()) in a later chapter. +) + +$(H6 Thrown exception terminates all scopes) + +$(P +We have seen that the program execution starts from the $(C main) function and branches into other functions from there. This layered execution of going deeper into functions and eventually returning from them can be seen as the branches of a tree. +) + +$(P +For example, $(C main()) may call a function named $(C makeOmelet), which in turn may call another function named $(C prepareAll), which in turn may call another function named $(C prepareEggs), etc. Assuming that the arrows indicate function calls, the branching of such a program can be shown as in the following function call tree: +) + +$(MONO +main + │ + ├──▶ makeOmelet + │ │ + │ ├──▶ prepareAll + │ │ │ + │ │ ├─▶ prepareEggs + │ │ ├─▶ prepareButter + │ │ └─▶ preparePan + │ │ + │ ├──▶ cookEggs + │ └──▶ cleanAll + │ + └──▶ eatOmelet +) + +$(P +The following program demonstrates the branching above by using different levels of indentation in its output. The program doesn't do anything useful other than producing an output suitable to our purposes: +) + +--- +$(CODE_NAME all_functions)import std.stdio; + +void indent(int level) { + foreach (i; 0 .. level * 2) { + write(' '); + } +} + +void entering(string functionName, int level) { + indent(level); + writeln("▶ ", functionName, "'s first line"); +} + +void exiting(string functionName, int level) { + indent(level); + writeln("◁ ", functionName, "'s last line"); +} + +void main() { + entering("main", 0); + makeOmelet(); + eatOmelet(); + exiting("main", 0); +} + +void makeOmelet() { + entering("makeOmelet", 1); + prepareAll(); + cookEggs(); + cleanAll(); + exiting("makeOmelet", 1); +} + +void eatOmelet() { + entering("eatOmelet", 1); + exiting("eatOmelet", 1); +} + +void prepareAll() { + entering("prepareAll", 2); + prepareEggs(); + prepareButter(); + preparePan(); + exiting("prepareAll", 2); +} + +void cookEggs() { + entering("cookEggs", 2); + exiting("cookEggs", 2); +} + +void cleanAll() { + entering("cleanAll", 2); + exiting("cleanAll", 2); +} + +void prepareEggs() { + entering("prepareEggs", 3); + exiting("prepareEggs", 3); +} + +void prepareButter() { + entering("prepareButter", 3); + exiting("prepareButter", 3); +} + +void preparePan() { + entering("preparePan", 3); + exiting("preparePan", 3); +} +--- + +$(P +The program produces the following output: +) + +$(SHELL +▶ main, first line + ▶ makeOmelet, first line + ▶ prepareAll, first line + ▶ prepareEggs, first line + ◁ prepareEggs, last line + ▶ prepareButter, first line + ◁ prepareButter, last line + ▶ preparePan, first line + ◁ preparePan, last line + ◁ prepareAll, last line + ▶ cookEggs, first line + ◁ cookEggs, last line + ▶ cleanAll, first line + ◁ cleanAll, last line + ◁ makeOmelet, last line + ▶ eatOmelet, first line + ◁ eatOmelet, last line +◁ main, last line +) + +$(P +The functions $(C entering) and $(C exiting) are used to indicate the first and last lines of functions with the help of the $(C ▶) and $(C ◁) characters. The program starts with the first line of $(C main()), branches down to other functions, and finally ends with the last line of $(C main). +) + +$(P +Let's modify the $(C prepareEggs) function to take the number of eggs as a parameter. Since certain values of this parameter would be an error, let's have this function throw an exception when the number of eggs is less than one: +) + +--- +$(CODE_NAME prepareEggs_int)import std.string; + +// ... + +void prepareEggs($(HILITE int count)) { + entering("prepareEggs", 3); + + if (count < 1) { + throw new Exception( + format("Cannot take %s eggs from the fridge", count)); + } + + exiting("prepareEggs", 3); +} +--- + +$(P +In order to be able to compile the program, we must modify other lines of the program to be compatible with this change. The number of eggs to take out of the fridge can be handed down from function to function, starting with $(C main()). The parts of the program that need to change are the following. The invalid value of -8 is intentional to show how the output of the program will be different from the previous output when an exception is thrown: +) + +--- +$(CODE_NAME makeOmelet_int_etc)$(CODE_XREF all_functions)$(CODE_XREF prepareEggs_int)// ... + +void main() { + entering("main", 0); + makeOmelet($(HILITE -8)); + eatOmelet(); + exiting("main", 0); +} + +void makeOmelet($(HILITE int eggCount)) { + entering("makeOmelet", 1); + prepareAll($(HILITE eggCount)); + cookEggs(); + cleanAll(); + exiting("makeOmelet", 1); +} + +// ... + +void prepareAll($(HILITE int eggCount)) { + entering("prepareAll", 2); + prepareEggs($(HILITE eggCount)); + prepareButter(); + preparePan(); + exiting("prepareAll", 2); +} + +// ... +--- + +$(P +When we start the program now, we see that the lines that used to be printed after the point where the exception is thrown are missing: +) + +$(SHELL +▶ main, first line + ▶ makeOmelet, first line + ▶ prepareAll, first line + ▶ prepareEggs, first line +object.Exception: Cannot take -8 eggs from the fridge +) + +$(P +When the exception is thrown, the program execution exits the $(C prepareEggs), $(C prepareAll), $(C makeOmelet) and $(C main()) functions in that order, from the bottom level to the top level. No additional steps are executed as the program exits these functions. +) + +$(P +The rationale for such a drastic termination is that a failure in a lower level function would mean that the higher level functions that needed its successful completion should also be considered as failed. +) + +$(P +The exception object that is thrown from a lower level function is transferred to the higher level functions one level at a time and causes the program to finally exit the $(C main()) function. The path that the exception takes can be shown as the highlighted path in the following tree: +) + +$(MONO + $(HILITE ▲) + $(HILITE │) + $(HILITE │) +main $(HILITE  ◀───────────┐) + │ $(HILITE │) + │ $(HILITE │) + ├──▶ makeOmelet $(HILITE  ◀─────┐) + │ │ $(HILITE │) + │ │ $(HILITE │) + │ ├──▶ prepareAll $(HILITE  ◀──────────┐) + │ │ │ $(HILITE │) + │ │ │ $(HILITE │) + │ │ ├─▶ prepareEggs $(HILITE X) $(I thrown exception) + │ │ ├─▶ prepareButter + │ │ └─▶ preparePan + │ │ + │ ├──▶ cookEggs + │ └──▶ cleanAll + │ + └──▶ eatOmelet +) + +$(P +The point of the exception mechanism is precisely this behavior of exiting all of the layers of function calls right away. +) + +$(P +Sometimes it makes sense to $(I catch) the thrown exception to find a way to continue the execution of the program. I will introduce the $(C catch) keyword below. +) + +$(H6 When to use $(C throw)) + +$(P +Use $(C throw) in situations when it is not possible to continue. For example, a function that reads the number of students from a file may throw an exception if this information is not available or incorrect. +) + +$(P +On the other hand, if the problem is caused by some user action like entering invalid data, it may make more sense to validate the data instead of throwing an exception. Displaying an error message and asking the user to re-enter the data is more appropriate in many cases. +) + +$(H5 $(IX try) $(IX catch) The $(C try-catch) statement to catch exceptions) + +$(P +As we've seen above, a thrown exception causes the program execution to exit all functions and this finally terminates the whole program. +) + +$(P +The exception object can be caught by a $(C try-catch) statement at any point on its path as it exits the functions. The $(C try-catch) statement models the phrase "$(I try) to do something, and $(I catch) exceptions that may be thrown." Here is the syntax of $(C try-catch): +) + +--- + try { + // the code block that is being executed, where an + // exception may be thrown + + } catch ($(I an_exception_type)) { + // expressions to execute if an exception of this + // type is caught + + } catch ($(I another_exception_type)) { + // expressions to execute if an exception of this + // other type is caught + + // ... more catch blocks as appropriate ... + + } finally { + // expressions to execute regardless of whether an + // exception is thrown + } +--- + +$(P +Let's start with the following program that does not use a $(C try-catch) statement at this state. The program reads the value of a die from a file and prints it to the standard output: +) + +--- +import std.stdio; + +int readDieFromFile() { + auto file = File("the_file_that_contains_the_value", "r"); + + int die; + file.readf(" %s", &die); + + return die; +} + +void main() { + const int die = readDieFromFile(); + + writeln("Die value: ", die); +} +--- + +$(P +Note that the $(C readDieFromFile) function is written in a way that ignores error conditions, expecting that the file and the value that it contains are available. In other words, the function is dealing only with its own task instead of paying attention to error conditions. This is a benefit of exceptions: many functions can be written in ways that focus on their actual tasks, rather than focusing on error conditions. +) + +$(P +Let's start the program when $(C the_file_that_contains_the_value) is missing: +) + +$(SHELL +std.exception.ErrnoException@std/stdio.d(286): Cannot open +file $(BACK_TICK)the_file_that_contains_the_value' in mode $(BACK_TICK)r' (No such +file or directory) +) + +$(P +An exception of type $(C ErrnoException) is thrown and the program terminates without printing "Die value: ". +) + +$(P +Let's add an intermediate function to the program that calls $(C readDieFromFile) from within a $(C try) block and let's have $(C main()) call this new function: +) + +--- +import std.stdio; + +int readDieFromFile() { + auto file = File("the_file_that_contains_the_value", "r"); + + int die; + file.readf(" %s", &die); + + return die; +} + +int $(HILITE tryReadingFromFile)() { + int die; + + $(HILITE try) { + die = readDieFromFile(); + + } $(HILITE catch) (std.exception.ErrnoException exc) { + writeln("(Could not read from file; assuming 1)"); + die = 1; + } + + return die; +} + +void main() { + const int die = $(HILITE tryReadingFromFile)(); + + writeln("Die value: ", die); +} +--- + +$(P +When we start the program again when $(C the_file_that_contains_the_value) is still missing, this time the program does not terminate with an exception: +) + +$(SHELL +(Could not read from file; assuming 1) +Die value: 1 +) + +$(P +The new program $(I tries) executing $(C readDieFromFile) in a $(C try) block. If that block executes successfully, the function ends normally with the $(C return die;) statement. If the execution of the $(C try) block ends with the specified $(C std.exception.ErrnoException), then the program execution enters the $(C catch) block. +) + +$(P +The following is a summary of events when the program is started when the file is missing: +) + +$(UL +$(LI like in the previous program, a $(C std.exception.ErrnoException) object is thrown (by $(C File()), not by our code),) +$(LI this exception is caught by $(C catch),) +$(LI the value of 1 is assumed during the normal execution of the $(C catch) block,) +$(LI and the program continues its normal operations.) +) + +$(P +$(C catch) is to catch thrown exceptions to find a way to continue executing the program. +) + +$(P +As another example, let's go back to the omelet program and add a $(C try-catch) statement to its $(C main()) function: +) + +--- +$(CODE_XREF makeOmelet_int_etc)void main() { + entering("main", 0); + + try { + makeOmelet(-8); + eatOmelet(); + + } catch (Exception exc) { + write("Failed to eat omelet: "); + writeln('"', exc.msg, '"'); + writeln("Will eat at neighbor's..."); + } + + exiting("main", 0); +} +--- + +$(P +($(I $(B Note:) The $(C .msg) property will be explained below.)) +) + +$(P +That $(C try) block contains two lines of code. Any exception thrown from either of those lines would be caught by the $(C catch) block. +) + +$(SHELL +▶ main, first line + ▶ makeOmelet, first line + ▶ prepareAll, first line + ▶ prepareEggs, first line +Failed to eat omelet: "Cannot take -8 eggs from the fridge" +Will eat at neighbor's... +◁ main, last line +) + +$(P +As can be seen from the output, the program doesn't terminate because of the thrown exception anymore. It recovers from the error condition and continues executing normally till the end of the $(C main()) function. +) + +$(H6 $(C catch) blocks are considered sequentially) + +$(P +The type $(C Exception), which we have used so far in the examples is a general exception type. This type merely specifies that an error occurred in the program. It also contains a message that can explain the error further, but it does not contain information about the $(I type) of the error. +) + +$(P +$(C ConvException) and $(C ErrnoException) that we have seen earlier in this chapter are more specific exception types: the former is about a conversion error, and the latter is about a system error. Like many other exception types in Phobos and as their names suggest, $(C ConvException) and $(C ErrnoException) are both inherited from the $(C Exception) class. +) + +$(P +$(C Exception) and its sibling $(C Error) are further inherited from $(C Throwable), the most general exception type. +) + +$(P +Although possible, it is not recommended to catch objects of type $(C Error) and objects of types that are inherited from $(C Error). Since it is more general than $(C Error), it is not recommended to catch $(C Throwable) either. What should normally be caught are the types that are under the $(C Exception) hierarchy, including $(C Exception) itself. +) + +$(MONO + Throwable $(I (not recommended to catch)) + ↗ ↖ + Exception Error $(I (not recommended to catch)) + ↗ ↖ ↗ ↖ + ... ... ... ... +) + +$(P $(I $(B Note:) I will explain the hierarchy representations later in $(LINK2 inheritance.html, the Inheritance chapter). The tree above indicates that $(C Throwable) is the most general and $(C Exception) and $(C Error) are more specific.) +) + +$(P +It is possible to catch exception objects of a particular type. For example, it is possible to catch an $(C ErrnoException) object specifically to detect and handle a system error. +) + +$(P +Exceptions are caught only if they match a type that is specified in a $(C catch) block. For example, a catch block that is trying to catch a $(C SpecialExceptionType) would not catch an $(C ErrnoException). +) + +$(P +The type of the exception object that is thrown during the execution of a $(C try) block is matched to the types that are specified by the $(C catch) blocks, in the order in which the $(C catch) blocks are written. If the type of the object matches the type of the $(C catch) block, then the exception is considered to be caught by that $(C catch) block, and the code that is within that block is executed. Once a match is found, the remaining $(C catch) blocks are ignored. +) + +$(P +Because the $(C catch) blocks are matched in order from the first to the last, the $(C catch) blocks must be ordered from the most specific exception types to the most general exception types. Accordingly, and if it makes sense to catch that type of exceptions, the $(C Exception) type must be specified at the last $(C catch) block. +) + +$(P +For example, a $(C try-catch) statement that is trying to catch several specific types of exceptions about student records must order the $(C catch) blocks from the most specific to the most general as in the following code: +) + +--- + try { + // operations about student records that may throw ... + + } catch (StudentIdDigitException exc) { + + // an exception that is specifically about errors with + // the digits of student ids + + } catch (StudentIdException exc) { + + // a more general exception about student ids but not + // necessarily about their digits + + } catch (StudentRecordException exc) { + + // even more general exception about student records + + } catch (Exception exc) { + + // the most general exception that may not be related + // to student records + + } +--- + +$(H6 $(IX finally) The $(C finally) block) + +$(P +$(C finally) is an optional block of the $(C try-catch) statement. It includes expressions that should be executed regardless of whether an exception is thrown or not. +) + +$(P +To see how $(C finally) works, let's look at a program that throws an exception 50% of the time: +) + +--- +import std.stdio; +import std.random; + +void throwsHalfTheTime() { + if (uniform(0, 2) == 1) { + throw new Exception("the error message"); + } +} + +void foo() { + writeln("the first line of foo()"); + + try { + writeln("the first line of the try block"); + throwsHalfTheTime(); + writeln("the last line of the try block"); + + // ... there may be one or more catch blocks here ... + + } $(HILITE finally) { + writeln("the body of the finally block"); + } + + writeln("the last line of foo()"); +} + +void main() { + foo(); +} +--- + +$(P +The output of the program is the following when the function does not throw: +) + +$(SHELL +the first line of foo() +the first line of the try block +the last line of the try block +$(HILITE the body of the finally block) +the last line of foo() +) + +$(P +The output of the program is the following when the function does throw: +) + +$(SHELL +the first line of foo() +the first line of the try block +$(HILITE the body of the finally block) +object.Exception@deneme.d: the error message +) + +$(P +As can be seen, although "the last line of the try block" and "the last line of foo()" are not printed, the content of the $(C finally) block is still executed when an exception is thrown. +) + +$(H6 When to use the $(C try-catch) statement) + +$(P +The $(C try-catch) statement is useful to catch exceptions to do something special about them. +) + +$(P +For that reason, the $(C try-catch) statement should be used only when there is something special to be done. Do not catch exceptions otherwise and leave them to higher level functions that may want to catch them. +) + +$(H5 Exception properties) + +$(P +The information that is automatically printed on the output when the program terminates due to an exception is available as properties of exception objects as well. These properties are provided by the $(C Throwable) interface: +) + +$(UL + +$(LI $(IX .file) $(C .file): The source file where the exception was thrown from) + +$(LI $(IX .line) $(C .line): The line number where the exception was thrown from) + +$(LI $(IX .msg) $(C .msg): The error message) + +$(LI $(IX .info) $(C .info): The state of the program stack when the exception was thrown) + +$(LI $(IX .next) $(C .next): The next collateral exception) + +) + +$(P +We saw that $(C finally) blocks are executed when leaving scopes due to exceptions as well. (As we will see in later chapters, the same is true for $(C scope) statements and $(I destructors) as well.) +) + +$(P +$(IX collateral exception) Naturally, such code blocks can throw exceptions as well. Exceptions that are thrown when leaving scopes due to an already thrown exception are called $(I collateral exceptions). Both the main exception and the collateral exceptions are elements of a $(I linked list) data structure, where every exception object is accessible through the $(C .next) property of the previous exception object. The value of the $(C .next) property of the last exception is $(C null). (We will see $(C null) in a later chapter.) +) + +$(P +There are three exceptions that are thrown in the example below: The main exception that is thrown in $(C foo()) and the two collateral exceptions that are thrown in the $(C finally) blocks of $(C foo()) and $(C bar()). The program accesses the collateral exceptions through the $(C .next) properties. +) + +$(P +Some of the concepts that are used in this program will be explained in later chapters. For example, the continuation condition of the $(C for) loop that consists solely of $(C exc) means $(I as long as $(C exc) is not $(C null)). +) + +--- +import std.stdio; + +void foo() { + try { + throw new Exception("Exception thrown in foo"); + + } finally { + throw new Exception( + "Exception thrown in foo's finally block"); + } +} + +void bar() { + try { + foo(); + + } finally { + throw new Exception( + "Exception thrown in bar's finally block"); + } +} + +void main() { + try { + bar(); + + } catch (Exception caughtException) { + + for (Throwable exc = caughtException; + exc; // ← Meaning: as long as exc is not 'null' + exc = exc$(HILITE .next)) { + + writefln("error message: %s", exc$(HILITE .msg)); + writefln("source file : %s", exc$(HILITE .file)); + writefln("source line : %s", exc$(HILITE .line)); + writeln(); + } + } +} +--- + +$(P +The output: +) + +$(SHELL +error message: Exception thrown in foo +source file : deneme.d +source line : 6 + +error message: Exception thrown in foo's finally block +source file : deneme.d +source line : 9 + +error message: Exception thrown in bar's finally block +source file : deneme.d +source line : 20 +) + +$(H5 $(IX error, kinds of) Kinds of errors) + +$(P +We have seen how useful the exception mechanism is. It enables both the lower and higher level operations to be aborted right away, instead of the program continuing with incorrect or missing data, or behaving in any other incorrect way. +) + +$(P +This does not mean that every error condition warrants throwing an exception. There may be better things to do depending on the kinds of errors. +) + +$(H6 User errors) + +$(P +Some of the errors are caused by the user. As we have seen above, the user may have entered a string like "hello" even though the program has been expecting a number. It may be more appropriate to display an error message and ask the user to enter appropriate data again. +) + +$(P +Even so, it may be fine to accept and use the data directly without validating the data up front; as long as the code that uses the data would throw anyway. What is important is to be able to notify the user why the data is not suitable. +) + +$(P +For example, let's look at a program that takes a file name from the user. There are at least two ways of dealing with potentially invalid file names: +) + +$(UL +$(LI $(B Validating the data before use): We can determine whether the file with the given name exists by calling $(C exists()) of the $(C std.file) module: + +--- + if (exists(fileName)) { + // yes, the file exists + + } else { + // no, the file doesn't exist + } +--- + +$(P +This gives us the chance to be able to open the data only if it exists. Unfortunately, it is still possible that the file cannot be opened even if $(C exists()) returns $(C true), if for example another process on the system deletes or renames the file before this program actually opens it. +) + +$(P +For that reason, the following method may be more useful. +) + +) + +$(LI $(B Using the data without first validating it): We can assume that the data is valid and start using it right away, because $(C File) would throw an exception if the file cannot be opened anyway. + +--- +import std.stdio; +import std.string; + +void useTheFile(string fileName) { + auto file = File(fileName, "r"); + // ... +} + +string read_string(string prompt) { + write(prompt, ": "); + return strip(readln()); +} + +void main() { + bool is_fileUsed = false; + + while (!is_fileUsed) { + try { + useTheFile( + read_string("Please enter a file name")); + + /* If we are at this line, it means that + * useTheFile() function has been completed + * successfully. This indicates that the file + * name was valid. + * + * We can now set the value of the loop flag to + * terminate the while loop. */ + is_fileUsed = true; + writeln("The file has been used successfully"); + + } catch (std.exception.ErrnoException exc) { + stderr.writeln("This file could not be opened"); + } + } +} +--- + +) + +) + +$(H6 Programmer errors) + +$(P +Some errors are caused by programmer mistakes. For example, the programmer may think that a function that has just been written will always be called with a value greater than or equal to zero, and this may be true according to the design of the program. The function having still been called with a value less than zero would indicate either a mistake in the design of the program or in the implementation of that design. Both of these can be thought of as programming errors. +) + +$(P +It is more appropriate to use $(C assert) instead of the exception mechanism for errors that are caused by programmer mistakes. ($(I $(B Note:) We will cover $(C assert) in $(LINK2 assert.html, a later chapter).)) +) + +--- +void processMenuSelection(int selection) { + assert(selection >= 0); + // ... +} + +void main() { + processMenuSelection(-1); +} +--- + +$(P +The program terminates with an $(C assert) failure: +) + +$(SHELL_SMALL +core.exception.AssertError@$(HILITE deneme.d(2)): Assertion failure +) + +$(P +$(C assert) validates program state and prints the file name and line number of the validation if it fails. The message above indicates that the assertion at line 2 of $(C deneme.d) has failed. +) + +$(H6 Unexpected situations) + +$(P +For unexpected situations that are outside of the two general cases above, it is still appropriate to throw exceptions. If the program cannot continue its execution, there is nothing else to do but to throw. +) + +$(P +It is up to the higher layer functions that call this function to decide what to do with thrown exceptions. They may catch the exceptions that we throw to remedy the situation. +) + +$(H5 Summary) + +$(UL + +$(LI +When faced with a user error either warn the user right away or ensure that an exception is thrown; the exception may be thrown anyway by another function when using incorrect data, or you may throw directly. +) + +$(LI +Use $(C assert) to validate program logic and implementation. ($(I $(B Note:) $(C assert) will be explained in a later chapter.)) +) + +$(LI +When in doubt, throw an exception with $(C throw) or $(C enforce()). ($(I $(B Note:) $(C enforce()) will be explained in a later chapter.)) +) + +$(LI +Catch exceptions if and only if you can do something useful about that exception. Otherwise, do not encapsulate code with a $(C try-catch) statement; instead, leave the exceptions to higher layers of the code that may do something about them. +) + +$(LI +Order the $(C catch) blocks from the most specific to the most general. +) + +$(LI +Put the expressions that must always be executed when leaving a scope, in $(C finally) blocks. +) + +) + +Macros: + TITLE=Exceptions + + DESCRIPTION=The exception mechanism of D, which is used in unexpected situations. + + KEYWORDS=d programming language tutorial book exception try catch finally exit failure success + +MINI_SOZLUK= diff --git a/book/d.en/fibers.d b/book/d.en/fibers.d new file mode 100644 index 0000000000..7b1afe63ef --- /dev/null +++ b/book/d.en/fibers.d @@ -0,0 +1,1107 @@ +Ddoc + +$(DERS_BOLUMU $(IX fiber) Fibers) + +$(P +$(IX coroutine) $(IX green thread) $(IX thread, green) A fiber is a $(I thread of execution) enabling a single thread achieve multiple tasks. Compared to regular threads that are commonly used in parallelism and concurrency, it is more efficient to switch between fibers. Fibers are similar to $(I coroutines) and $(I green threads). +) + +$(P +Fibers enable multiple call stacks per thread. For that reason, to fully understand and appreciate fibers, one must first understand the $(I call stack) of a thread. +) + +$(H5 $(IX call stack) $(IX program stack) Call stack) + +$(P +$(IX local state) The parameters, non-static local variables, the return value, and temporary expressions of a function, as well as any additional information that may be needed during its execution, comprise the $(I local state) of that function. The local state of a function is allocated and initialized automatically at run time every time that function is called. +) + +$(P +$(IX stack frame) The storage space allocated for the local state of a function call is called a $(I frame) (or $(I stack frame)). As functions call other functions during the execution of a thread, their frames are conceptually placed on top of each other to form a stack of frames. The stack of frames of currently active function calls is the $(I call stack) of that thread. +) + +$(P +For example, at the time the main thread of the following program starts executing the $(C bar()) function, there would be three levels of active function calls due to $(C main()) calling $(C foo()) and $(C foo()) calling $(C bar()): +) + +--- +void main() { + int a; + int b; + + int c = $(HILITE foo)(a, b); +} + +int foo(int x, int y) { + $(HILITE bar)(x + y); + return 42; +} + +void bar(int param) { + string[] arr; + // ... +} +--- + +$(P +During the execution of $(C bar()), the call stack would consist of three frames storing the local states of those currently active function calls: +) + +$(MONO +The call stack grows upward +as function calls get deeper. ▲ ▲ + │ │ + Top of the call stack → ┌──────────────┐ + │ int param │ ← bar's frame + │ string[] arr │ + ├──────────────┤ + │ int x │ + │ int y │ ← foo's frame + │ return value │ + ├──────────────┤ + │ int a │ + │ int b │ ← main's frame + │ int c │ +Bottom of the call stack → └──────────────┘ +) + +$(P +As layers of function calls get deeper when functions call other functions and shallower when functions return, the size of the call stack increases and decreases accordingly. For example, once $(C bar()) returns, its frame would no longer be needed and its space would later be used for another function call in the future: +) + +$(MONO +$(LIGHT_GRAY ┌──────────────┐) +$(LIGHT_GRAY │ int param │) +$(LIGHT_GRAY │ string[] arr │) + Top of the call stack → ├──────────────┤ + │ int a │ + │ int b │ ← foo's frame + │ return value │ + ├──────────────┤ + │ int a │ + │ int b │ ← main's frame + │ int c │ +Bottom of the call stack → └──────────────┘ +) + +$(P +We have been taking advantage of the call stack in every program that we have written so far. The advantages of the call stack is especially clear for recursive functions. +) + +$(H6 $(IX recursion) Recursion) + +$(P +Recursion is the situation where a function calls itself either directly or indirectly. Recursion greatly simplifies certain kinds of algorithms like the ones that are classified as $(I divide-and-conquer). +) + +$(P +Let's consider the following function that calculates the sum of the elements of a slice. It achieves this task by calling itself recursively with a slice that is one element shorter than the one that it has received. The recursion continues until the slice becomes empty. The current result is carried over to the next recursion step as the second parameter: +) + +--- +import std.array; + +int sum(int[] arr, int currentSum = 0) { + if (arr.empty) { + /* No element to add. The result is what has been + * calculated so far. */ + return currentSum; + } + + /* Add the front element to the current sum and call self + * with the remaining elements. */ + return $(HILITE sum)(arr[1..$], currentSum + arr.front); +} + +void main() { + assert(sum([1, 2, 3]) == 6); +} +--- + +$(P +$(IX sum, std.algorithm) $(I $(B Note:) The code above is only for demonstration. Otherwise, the sum of the elements of a range should be calculated by $(C std.algorithm.sum), which uses special algorithms to achieve more accurate calculations for floating point types.) +) + +$(P +When $(C sum()) is eventually called with an empty slice for the initial argument of $(C [1, 2, 3]) above, the relevant parts of the call stack would consist of the following frames. The value of each parameter is indicated after an $(C ==) sign. Remember to read the frame contents from bottom to top: +) + +$(MONO + ┌─────────────────────────┐ + │ arr == [] │ ← final call to sum + │ currentSum == 6 │ + ├─────────────────────────┤ + │ arr == [3] │ ← third call to sum + │ currentSum == 3 │ + ├─────────────────────────┤ + │ arr == [2, 3] │ ← second call to sum + │ currentSum == 1 │ + ├─────────────────────────┤ + │ arr == [1, 2, 3] │ ← first call to sum + │ currentSum == 0 │ + ├─────────────────────────┤ + │ ... │ ← main's frame + └─────────────────────────┘ +) + +$(P +$(I $(B Note:) In practice, when the recursive function directly returns the result of calling itself, compilers use a technique called "tail-call optimization", which eliminates separate frames for each recursive call.) +) + +$(P +In a multithreaded program, since each thread would be working on its own task, every thread gets it own call stack to maintain its own execution state. +) + +$(P +The power of fibers is based on the fact that although a fiber is not a thread, it gets its own call stack, effectively enabling multiple call stacks per thread. Since one call stack maintains the execution state of one task, multiple call stacks enable a thread work on multiple tasks. +) + +$(H5 Usage) + +$(P +The following are common operations of fibers. We will see examples of these later below. +) + +$(UL + +$(LI $(IX fiber function) A fiber starts its execution from a callable entity (function pointer, delegate, etc.) that does not take any parameter and does not return anything. For example, the following function can be used as a fiber function: + +--- +void fiberFunction() { + // ... +} +--- + +) + +$(LI $(IX Fiber, core.thread) A fiber can be created as an object of class $(C core.thread.Fiber) with a callable entity: + +--- +import core.thread; + +// ... + + auto fiber = new Fiber($(HILITE &)fiberFunction); +--- + +$(P +Alternatively, a subclass of $(C Fiber) can be defined and the fiber function can be passed to the constructor of the superclass. In the following example, the fiber function is a member function: +) + +--- +class MyFiber : $(HILITE Fiber) { + this() { + super($(HILITE &)run); + } + + void run() { + // ... + } +} + +// ... + + auto fiber = new MyFiber(); +--- + +) + +$(LI $(IX call, Fiber) A fiber is started and resumed by its $(C call()) member function: + +--- + fiber.call(); +--- + +$(P +Unlike threads, the caller is paused while the fiber is executing. +) + +) + +$(LI $(IX yield, Fiber) A fiber pauses itself ($(I yields) execution to its caller) by $(C Fiber.yield()): + +--- +void fiberFunction() { + // ... + + Fiber.yield(); + + // ... +} +--- + +$(P +The caller's execution resumes when the fiber yields. +) + +) + +$(LI $(IX .state, Fiber) The execution state of a fiber is determined by its $(C .state) property: + +--- + if (fiber.state == Fiber.State.TERM) { + // ... + } +--- + +$(P +$(IX State, Fiber) $(C Fiber.State) is an enum with the following values: +) + +$(UL + +$(LI $(IX HOLD, Fiber.State) $(C HOLD): The fiber is paused, meaning that it can be started or resumed.) + +$(LI $(IX EXEC, Fiber.State) $(C EXEC): The fiber is currently executing.) + +$(LI $(IX TERM, Fiber.State) $(IX reset, Fiber) $(C TERM): The fiber has terminated. It must be $(C reset()) before it can be used again.) + +) + +) + +) + +$(H5 Fibers in range implementations) + +$(P +Almost every range needs to store some information to remember its state of iteration. This is necessary for it to know what to do when its $(C popFront()) is called next time. Most range examples that we saw in $(LINK2 ranges.html, the Ranges) and later chapters have been storing some kind of state to achieve their tasks. +) + +$(P +For example, $(C FibonacciSeries) that we have defined earlier was keeping two member variables to calculate the $(I next next) number in the series: +) + +--- +struct FibonacciSeries { + int $(HILITE current) = 0; + int $(HILITE next) = 1; + + enum empty = false; + + int front() const { + return current; + } + + void popFront() { + const nextNext = current + next; + current = next; + next = nextNext; + } +} +--- + +$(P +While maintaining the iteration state is trivial for some ranges like $(C FibonacciSeries), it is surprisingly harder for some others, e.g. recursive data structures like binary search trees. The reason why it is surprising is that for such data structures, the same algorithms are trivial when implemented recursively. +) + +$(P +For example, the following recursive implementations of $(C insert()) and $(C print()) do not define any variables and are independent of the number of elements contained in the tree. The recursive calls are highlighted. (Note that $(C insert()) is recursive indirectly through $(C insertOrSet()).) +) + +--- +import std.stdio; +import std.string; +import std.conv; +import std.random; +import std.range; +import std.algorithm; + +/* Represents the nodes of a binary tree. This type is used in + * the implementation of struct Tree below and should not be + * used directly. */ +struct Node { + int element; + Node * left; // Left sub-tree + Node * right; // Right sub-tree + + void $(HILITE insert)(int element) { + if (element < this.element) { + /* Smaller elements go under the left sub-tree. */ + insertOrSet(left, element); + + } else if (element > this.element) { + /* Larger elements go under the right sub-tree. */ + insertOrSet(right, element); + + } else { + throw new Exception(format("%s already exists", + element)); + } + } + + void $(HILITE print)() const { + /* First print the elements of the left sub-tree */ + if (left) { + left.$(HILITE print)(); + write(' '); + } + + /* Then print this element */ + write(element); + + /* Lastly, print the elements of the right sub-tree */ + if (right) { + write(' '); + right.$(HILITE print)(); + } + } +} + +/* Inserts the element to the specified sub-tree, potentially + * initializing its node. */ +void insertOrSet(ref Node * node, int element) { + if (!node) { + /* This is the first element of this sub-tree. */ + node = new Node(element); + + } else { + node.$(HILITE insert)(element); + } +} + +/* This is the actual Tree representation. It allows an empty + * tree by means of 'root' being equal to 'null'. */ +struct Tree { + Node * root; + + /* Inserts the element to this tree. */ + void insert(int element) { + insertOrSet(root, element); + } + + /* Prints the elements in sorted order. */ + void print() const { + if (root) { + root.print(); + } + } +} + +/* Populates the tree with 'n' random numbers picked out of a + * set of '10 * n' numbers. */ +Tree makeRandomTree(size_t n) { + auto numbers = iota((n * 10).to!int) + .randomSample(n, Random(unpredictableSeed)) + .array; + + randomShuffle(numbers); + + /* Populate the tree with those numbers. */ + auto tree = Tree(); + numbers.each!(e => tree.insert(e)); + + return tree; +} + +void main() { + auto tree = makeRandomTree(10); + tree.print(); +} +--- + +$(P +$(I $(B Note:) The program above uses the following features from Phobos:) +) + +$(UL + +$(LI +$(IX iota, std.range) $(C std.range.iota) generates the elements of a given value range lazily. (By default, the first element is the $(C .init) value). For example, $(C iota(10)) is a range of $(C int) elements from $(C 0) to $(C 9). +) + +$(LI +$(IX each, std.algorithm) $(IX map, vs. each) $(C std.algorithm.each) is similar to $(C std.algorithm.map). While $(C map()) generates a new result for each element, $(C each()) generates side effects for each element. Additionally, $(C map()) is lazy while $(C each()) is eager. +) + +$(LI +$(IX randomSample, std.random) $(C std.random.randomSample) picks a random sampling of elements from a given range without changing their order. +) + +$(LI +$(IX randomShuffle, std.random) $(C std.random.randomShuffle) shuffles the elements of a range randomly. +) + +) + +$(P +Like most containers, one would like this tree to provide a range interface so that its elements can be used with existing range algorithms. This can be done by defining an $(C opSlice()) member function: +) + +--- +struct Tree { +// ... + + /* Provides access to the elements of the tree in sorted + * order. */ + struct InOrderRange { + $(HILITE ... What should the implementation be? ...) + } + + InOrderRange opSlice() const { + return InOrderRange(root); + } +} +--- + +$(P +Although the $(C print()) member function above essentially achieves the same task of visiting every element in sorted order, it is not easy to implement an $(C InputRange) for a tree. I will not attempt to implement $(C InOrderRange) here but I encourage you to implement or at least research tree iterators. (Some implementations require that tree nodes have an additional $(C Node*) to point at each node's parent.) +) + +$(P +The reason why recursive tree algorithms like $(C print()) are trivial is due to the automatic management of the call stack. The call stack implicitly contains information not only about what the current element is, but also how the execution of the program arrived at that element (e.g. at what nodes did the execution follow the left node versus the right node). +) + +$(P +For example, when a recursive call to $(C left.print()) returns after printing the elements of the left sub-tree, the local state of the current $(C print()) call already implies that it is now time to print a space character: +) + +--- + void print() const { + if (left) { + left.print(); + write(' '); // ← Call stack implies this is next + } + + // ... + } +--- + +$(P +Fibers are useful for similar cases where using a call stack is much easier than maintaining state explicitly. +) + +$(P +Although the benefits of fibers would not be apparent on a simple task like generating the Fibonacci series, for simplicity let's cover common fiber operations on a fiber implementation of one. We will implement a tree range later below. +) + +--- +import core.thread; + +/* This is the fiber function that generates each element and + * then sets the 'ref' parameter to that element. */ +void fibonacciSeries($(HILITE ref) int current) { // (1) + current = 0; // Note that 'current' is the parameter + int next = 1; + + while (true) { + $(HILITE Fiber.yield()); // (2) + /* Next call() will continue from this point */ // (3) + + const nextNext = current + next; + current = next; + next = nextNext; + } +} + +void main() { + int current; // (1) + // (4) + Fiber fiber = new Fiber(() => fibonacciSeries(current)); + + foreach (_; 0 .. 10) { + fiber$(HILITE .call()); // (5) + + import std.stdio; + writef("%s ", current); + } +} +--- + +$(OL + +$(LI The fiber function above takes a reference to an $(C int). It uses this parameter to communicate the current element to its caller. (The parameter could be qualified as $(C out) instead of $(C ref) as well).) + +$(LI When the current element is ready for use, the fiber pauses itself by calling $(C Fiber.yield()).) + +$(LI A later $(C call()) will resume the function right after the fiber's last $(C Fiber.yield()) call. (The first $(C call()) starts the function.)) + +$(LI Because fiber functions do not take parameters, $(C fibonacciSeries()) cannot be used directly as a fiber function. Instead, a parameter-less $(LINK2 lambda.html, delegate) is used as an adaptor to be passed to the $(C Fiber) constructor.) + +$(LI The caller starts and resumes the fiber by its $(C call()) member function.) + +) + +$(P +As a result, $(C main()) receives the elements of the series through $(C current) and prints them: +) + +$(SHELL +0 1 1 2 3 5 8 13 21 34 +) + +$(H6 $(IX Generator, std.concurrency) $(C std.concurrency.Generator) for presenting fibers as ranges) + +$(P +Although we have achieved generating the Fibonacci series with a fiber, that implementation has the following shortcomings: +) + +$(UL + +$(LI The solution above does not provide a range interface, making it incompatible with existing range algorithms.) + +$(LI Presenting the elements by mutating a $(C ref) parameter is less desirable compared to a design where the elements are copied to the caller's context.) + +$(LI Constructing and using the fiber explicitly through its member functions exposes $(I lower level) implementation details, compared to alternative designs.) + +) + +$(P +The $(C std.concurrency.Generator) class addresses all of these issues. Note how $(C fibonacciSeries()) below is written as a simple function. The only difference is that instead of returning a single element by $(C return), it can make multiple elements available by $(C yield()) ($(I infinite elements) in this example). +) + +$(P +$(IX yield, std.concurrency) Also note that this time it is the $(C std.concurrency.yield) function, not the $(C Fiber.yield) member function that we used above. +) + +--- +import std.stdio; +import std.range; +import std.concurrency; + +/* This alias is used for resolving the name conflict with + * std.range.Generator. */ +alias FiberRange = std.concurrency.Generator; + +void fibonacciSeries() { + int current = 0; + int next = 1; + + while (true) { + $(HILITE yield(current)); + + const nextNext = current + next; + current = next; + next = nextNext; + } +} + +void main() { + auto series = new $(HILITE FiberRange!int)(&fibonacciSeries); + writefln("%(%s %)", series.take(10)); +} +--- + +$(P +As a result, the elements that are produced by a fiber function are used conveniently as an $(C InputRange): +) + +$(SHELL +0 1 1 2 3 5 8 13 21 34 +) + +$(P +Using $(C Generator), we can easily present the elements of a tree as an $(C InputRange) as well. Further, once the tree has an $(C InputRange) interface, the $(C print()) member function would not be needed anymore; hence it is removed. Especially note how $(C byNode()) is implemented as an adaptor over the recursive function $(C nextNode()): +) + +--- +import std.concurrency; + +alias FiberRange = std.concurrency.Generator; + +struct Node { +// ... + + /* Note: print() member function is removed because it is + * not needed anymore. */ + + auto opSlice() const { + return byNode(&this); + } +} + +/* This is the fiber function that yields the next tree node + * in sorted order. */ +void nextNode(const(Node) * node) { + if (!node) { + /* No element at or under this node */ + return; + } + + nextNode(node.left); // First, elements on the left + $(HILITE yield(node)); // Then, this element + nextNode(node.right); // Finally, elements on the right +} + +/* Returns an InputRange to the nodes of the tree. */ +auto byNode(const(Node) * node) { + return new FiberRange!(const(Node)*)( + () => nextNode(node)); +} + +// ... + +struct Tree { +// ... + + /* Note: print() member function is removed because it is + * not needed anymore. */ + + auto opSlice() const { + /* A translation from the nodes to the elements. */ + return byNode(this).map!(n => n.element); + } +} + +/* Returns an InputRange to the nodes of the tree. The + * returned range is empty if the tree has no elements (i.e. + * if 'root' is 'null'). */ +auto byNode(const(Tree) tree) { + if (tree.root) { + return byNode(tree.root); + + } else { + alias RangeType = typeof(return); + return new RangeType(() {}); $(CODE_NOTE Empty range) + } +} +--- + +$(P +$(C Tree) objects can now be sliced with $(C []) and the result can be used as an $(C InputRange): +) + +--- + writefln("%(%s %)", tree$(HILITE [])); +--- + +$(H5 $(IX asynchronous I/O, fiber) Fibers in asynchronous input and output) + +$(P +The call stack of a fiber can simplify asynchronous input and output tasks as well. +) + +$(P +As an example, let's imagine a system where users sign on to a service by connecting to a server and providing their $(I name), $(I email), and $(I age), in that order. This would be similar to the $(I sign-on user flow) of a website. To keep the example simple, instead of implementing an actual web service, let's simulate user interactions using data entered on the command line. Let's use the following simple sign-on protocol, where input data is highlighted: +) + +$(UL +$(LI $(HILITE $(C hi)): A user connects and a flow id is generated) +$(LI $(HILITE $(C $(I id data))): The user of flow that corresponds to $(C id) enters the next expected data. For example, if the expected data for flow $(C 42) is $(I name), then the command for Alice would be $(C 42 Alice).) +$(LI $(HILITE $(C bye)): Program exits) +) + +$(P +For example, the following can be the interactions of Alice and Bob, where the inputs to the simulation program are highlighted. Each user connects and then provides $(I name), $(I email), and $(I age): +) + +$(SHELL +> $(HILITE hi) $(SHELL_NOTE Alice connects) +Flow 0 started. +> $(HILITE 0 Alice) +> $(HILITE 0 alice@example.com) +> $(HILITE 0 20) +Flow 0 has completed. $(SHELL_NOTE Alice finishes) +Added user 'Alice'. +> $(HILITE hi) $(SHELL_NOTE Bob connects) +Flow 1 started. +> $(HILITE 1 Bob) +> $(HILITE 1 bob@example.com) +> $(HILITE 1 30) +Flow 1 has completed. $(SHELL_NOTE Bob finishes) +Added user 'Bob'. +> $(HILITE bye) +Goodbye. +Users: + User("Alice", "alice@example.com", 20) + User("Bob", "bob@example.com", 30) +) + +$(P +This program can be designed to wait for the command $(C hi) in a loop and then call a function to receive the input data of the connected user: +) + +--- + if (input == "hi") { + signOnNewUser(); $(CODE_NOTE_WRONG WARNING: Blocking design) + } +--- + +$(P +Unless the program had some kind of support for multitasking, such a design would be considered $(I blocking), meaning that all other users would be blocked until the current user completes their sign on flow. This would impact the responsiveness of even lightly-used services if users took several minutes to provide data. +) + +$(P +There can be several designs that makes this service $(I non-blocking), meaning that more than one user can sign on at the same time: +) + +$(UL + +$(LI Maintaining tasks explicitly: The main thread can spawn one thread per user sign-on and pass input data to that thread by means of messages. Although this method would work, it might involve thread synchronization and it can be slower than a fiber. (The reasons for this potential performance penalty will be explained in the $(I cooperative multitasking) section below.)) + +$(LI Maintaining state: The program can accept more than one sign-on and remember the state of each sign-on explicitly. For example, if Alice has entered only her name so far, her state would have to indicate that the next input data would be her email information.) + +) + +$(P +Alternatively, a design based on fibers can employ one fiber per sign-on flow. This would enable implementing the flow in a linear fashion, matching the protocol exactly: first the name, then the email, and finally the age. For example, $(C run()) below does not need to do anything special to remember the state of the sign-on flow. When it is $(C call())'ed next time, it continues right after the last $(C Fiber.yield()) call that had paused it. The next line to be executed is implied by the call stack. +) + +$(P +Differently from earlier examples, the following program uses a $(C Fiber) subclass: +) + +--- +import std.stdio; +import std.string; +import std.format; +import std.exception; +import std.conv; +import std.array; +import core.thread; + +struct User { + string name; + string email; + uint age; +} + +/* This Fiber subclass represents the sign-on flow of a + * user. */ +class SignOnFlow : Fiber { + /* The data read most recently for this flow. */ + string inputData_; + + /* The information to construct a User object. */ + string name; + string email; + uint age; + + this() { + /* Set our 'run' member function as the starting point + * of the fiber. */ + super(&run); + } + + void run() { + /* First input is name. */ + name = inputData_; + $(HILITE Fiber.yield()); + + /* Second input is email. */ + email = inputData_; + $(HILITE Fiber.yield()); + + /* Last input is age. */ + age = inputData_.to!uint; + + /* At this point we have collected all information to + * construct the user. We now "return" instead of + * 'Fiber.yield()'. As a result, the state of this + * fiber becomes Fiber.State.TERM. */ + } + + /* This property function is to receive data from the + * caller. */ + void inputData(string data) { + inputData_ = data; + } + + /* This property function is to construct a user and + * return it to the caller. */ + User user() const { + return User(name, email, age); + } +} + +/* Represents data read from the input for a specific flow. */ +struct FlowData { + size_t id; + string data; +} + +/* Parses data related to a flow. */ +FlowData parseFlowData(string line) { + size_t id; + string data; + + const items = line.formattedRead!" %s %s"(id, data); + enforce(items == 2, format("Bad input '%s'.", line)); + + return FlowData(id, data); +} + +void main() { + User[] users; + SignOnFlow[] flows; + + bool done = false; + + while (!done) { + write("> "); + string line = readln.strip; + + switch (line) { + case "hi": + /* Start a flow for the new connection. */ + flows ~= new SignOnFlow(); + + writefln("Flow %s started.", flows.length - 1); + break; + + case "bye": + /* Exit the program. */ + done = true; + break; + + default: + /* Try to use the input as flow data. */ + try { + auto user = handleFlowData(line, flows); + + if (!user.name.empty) { + users ~= user; + writefln("Added user '%s'.", user.name); + } + + } catch (Exception exc) { + writefln("Error: %s", exc.msg); + } + break; + } + } + + writeln("Goodbye."); + writefln("Users:\n%( %s\n%)", users); +} + +/* Identifies the owner fiber for the input, sets its input + * data, and resumes that fiber. Returns a user with valid + * fields if the flow has been completed. */ +User handleFlowData(string line, SignOnFlow[] flows) { + const input = parseFlowData(line); + const id = input.id; + + enforce(id < flows.length, format("Invalid id: %s.", id)); + + auto flow = flows[id]; + + enforce(flow.state == Fiber.State.HOLD, + format("Flow %s is not runnable.", id)); + + /* Set flow data. */ + flow.inputData = input.data; + + /* Resume the flow. */ + flow$(HILITE .call()); + + User user; + + if (flow.state == Fiber.State.TERM) { + writefln("Flow %s has completed.", id); + + /* Set the return value to the newly created user. */ + user = flow.user; + + /* TODO: This fiber's entry in the 'flows' array can + * be reused for a new flow in the future. However, it + * must first be reset by 'flow.reset()'. */ + } + + return user; +} +--- + +$(P +$(C main()) reads lines from the input, parses them, and dispatches flow data to the appropriate flow to be processed. The call stack of each flow maintains the flow state automatically. New users are added to the system when the complete user information becomes available. +) + +$(P +When you run the program above, you see that no matter how long a user takes to complete their individual sign-on flow, the system always accepts new user connections. As an example, Alice's interaction is highlighted: +) + +$(SHELL +> $(HILITE hi) $(SHELL_NOTE Alice connects) +Flow 0 started. +> $(HILITE 0 Alice) +> hi $(SHELL_NOTE Bob connects) +Flow 1 started. +> hi $(SHELL_NOTE Cindy connects) +Flow 2 started. +> $(HILITE 0 alice@example.com) +> 1 Bob +> 2 Cindy +> 2 cindy@example.com +> 2 40 $(SHELL_NOTE Cindy finishes) +Flow 2 has completed. +Added user 'Cindy'. +> 1 bob@example.com +> 1 30 $(SHELL_NOTE Bob finishes) +Flow 1 has completed. +Added user 'Bob'. +> $(HILITE 0 20) $(SHELL_NOTE Alice finishes) +Flow 0 has completed. +Added user 'Alice'. +> bye +Goodbye. +Users: + User("Cindy", "cindy@example.com", 40) + User("Bob", "bob@example.com", 30) + User("Alice", "alice@example.com", 20) +) + +$(P +Although Alice, Bob, and Cindy connect in that order, they complete their sign-on flows at different paces. As a result, the $(C users) array is populated in the order that the flows are completed. +) + +$(P +One benefit of using fibers in this program is that $(C SignOnFlow.run()) is written trivially without regard to how fast or slow a user's input has been. Additionally, no user is blocked when other sign-on flows are in progress. +) + +$(P +$(IX vibe.d) Many asynchronous input/output frameworks like $(LINK2 http://vibed.org, vibe.d) use similar designs based on fibers. +) + +$(H5 $(IX exception, fiber) Exceptions and fibers) + +$(P +In $(LINK2 exceptions.html, the Exceptions chapter) we saw how "an exception object that is thrown from a lower level function is transferred to the higher level functions one level at a time". We also saw that an uncaught exception "causes the program to finally exit the $(C main()) function." Although that chapter did not mention the call stack, the described behavior of the exception mechanism is achieved by the call stack as well. +) + +$(P +$(IX stack unwinding) Continuing with the first example in this chapter, if an exception is thrown inside $(C bar()), first the frame of $(C bar()) would be removed from the call stack, then $(C foo())'s, and finally $(C main())'s. As functions are exited and their frames are removed from the call stack, the destructors of local variables are executed for their final operations. The process of leaving functions and executing destructors of local variables due to a thrown exception is called $(I stack unwinding). +) + +$(P +Since fibers have their own stack, an exception that is thrown during the execution of the fiber unwinds the fiber's call stack, not its caller's. If the exception is not caught, the fiber function terminates and the fiber's state becomes $(C Fiber.State.TERM). +) + +$(P +$(IX yieldAndThrow, Fiber) Although that may be the desired behavior in some cases, sometimes a fiber may need to communicate an error condition to its caller without losing its execution state. $(C Fiber.yieldAndThrow) allows a fiber to yield and immediately throw an exception in the caller's context. +) + +$(P +To see how it can be used let's enter invalid age data to the sign-on program: +) + +$(SHELL +> hi +Flow 0 started. +> 0 Alice +> 0 alice@example.com +> 0 $(HILITE hello) $(SHELL_NOTE_WRONG the user enters invalid age) +Error: Unexpected 'h' when converting from type string to type uint +> 0 $(HILITE 20) $(SHELL_NOTE attempts to correct the error) +Error: Flow 0 is not runnable. $(SHELL_NOTE but the flow is terminated) +) + +$(P +Instead of terminating the fiber and losing the entire sign-on flow, the fiber can catch the conversion error and communicate it to the caller by $(C yieldAndThrow()). This can be done by replacing the following line of the program where the fiber converts age data: +) + +--- + age = inputData_.to!uint; +--- + +$(P +Wrapping that line with a $(C try-catch) statement inside an unconditional loop would be sufficient to keep the fiber alive until there is data that can be converted to a $(C uint): +) + +--- + while (true) { + try { + age = inputData_.to!uint; + break; // ← Conversion worked; leave the loop + + } catch (ConvException exc) { + Fiber.yieldAndThrow(exc); + } + } +--- + +$(P +This time the fiber remains in an unconditional loop until data is valid: +) + +$(SHELL +> hi +Flow 0 started. +> 0 Alice +> 0 alice@example.com +> 0 $(HILITE hello) $(SHELL_NOTE_WRONG the user enters invalid age) +Error: Unexpected 'h' when converting from type string to type uint +> 0 $(HILITE world) $(SHELL_NOTE_WRONG enters invalid age again) +Error: Unexpected 'w' when converting from type string to type uint +> 0 $(HILITE 20) $(SHELL_NOTE finally, enters valid data) +Flow 0 has completed. +Added user 'Alice'. +> bye +Goodbye. +Users: + User("Alice", "alice@example.com", 20) +) + +$(P +As can be seen from the output, this time the sign-on flow is not lost and the user is added to the system. +) + +$(H5 $(IX preemptive multitasking, vs. cooperative multitasking) $(IX cooperative multitasking) $(IX thread performance) Cooperative multitasking) + +$(P +Unlike operating system threads, which are paused (suspended) and resumed by the operating system at unknown points in time, a fiber pauses itself explicitly and is resumed by its caller explicitly. According to this distinction, the kind of multitasking that the operating system provides is called $(I preemptive multitasking) and the kind that fibers provide is called $(I cooperative multitasking). +) + +$(P +$(IX context switching) In preemptive multitasking, the operating system allots a certain amount of time to a thread when it starts or resumes its execution. When the time is up, that thread is paused and another one is resumed in its place. Moving from one thread to another is called $(I context switching). Context switching takes a relatively large amount of time, which could have better been spent doing actual work by threads. +) + +$(P +Considering that a system is usually busy with high number of threads, context switching is unavoidable and is actually desired. However, sometimes threads need to pause themselves voluntarily before they use up the entire time that was alloted to them. This can happen when a thread needs information from another thread or from a device. When a thread pauses itself, the operating system must spend time again to switch to another thread. As a result, time that could have been used for doing actual work ends up being used for context switching. +) + +$(P +With fibers, the caller and the fiber execute as parts of the same thread. (That is the reason why the caller and the fiber cannot execute at the same time.) As a benefit, there is no overhead of context switching between the caller and the fiber. (However, there is still some light overhead which is comparable to the overhead of a regular function call.) +) + +$(P +Another benefit of cooperative multitasking is that the data that the caller and the fiber exchange is more likely to be in the CPU's data cache. Because data that is in the CPU cache can be accessed hundreds of times faster than data that needs to be read back from system memory, this further improves the performance of fibers. +) + +$(P +Additionally, because the caller and the fiber are never executed at the same time, there is no possibility of race conditions, obviating the need for data synchronization. However, the programmer must still ensure that a fiber yields at the intended time (e.g. when data is actually ready). For example, the $(C func()) call below must not execute a $(C Fiber.yield()) call, even indirectly, as that would be premature, before the value of $(C sharedData) was doubled: +) + +--- +void fiberFunction() { + // ... + + func(); $(CODE_NOTE must not yield prematurely) + sharedData *= 2; + Fiber.yield(); $(CODE_NOTE intended point to yield) + + // ... +} +--- + +$(P +$(IX M:N, threading) One obvious shortcoming of fibers is that only one core of the CPU is used for the caller and its fibers. The other cores of the CPU might be sitting idle, effectively wasting resources. It is possible to use different designs like the $(I M:N threading model (hybrid threading)) that employ other cores as well. I encourage you to research and compare different threading models. +) + +$(H5 Summary) + +$(UL + +$(LI The call stack enables efficient allocation of local state and simplifies certain algorithms, especially the recursive ones.) + +$(LI Fibers enable multiple call stacks per thread instead of the default single call stack per thread.) + +$(LI A fiber and its caller are executed on the same thread (i.e. not at the same time).) + +$(LI A fiber pauses itself by $(I yielding) to its caller and the caller resumes its fiber by $(I calling) it again.) + +$(LI $(C Generator) presents a fiber as an $(C InputRange).) + +$(LI Fibers simplify algorithms that rely heavily on the call stack.) + +$(LI Fibers simplify asynchronous input/output operations.) + +$(LI Fibers provide cooperative multitasking, which has different trade-offs from preemptive multitasking.) + +) + +macros: + TITLE=Fibers + + DESCRIPTION=Generators and cooperative multitasking by fibers. + + KEYWORDS=d programming language tutorial book fiber cooperative multitasking diff --git a/book/d.en/files.cozum.d b/book/d.en/files.cozum.d new file mode 100644 index 0000000000..dc77a5d902 --- /dev/null +++ b/book/d.en/files.cozum.d @@ -0,0 +1,34 @@ +Ddoc + +$(COZUM_BOLUMU Files) + +--- +import std.stdio; +import std.string; + +void main() { + write("Please enter the name of the file to read from: "); + string inFileName = strip(readln()); + File inFile = File(inFileName, "r"); + + string outFileName = inFileName ~ ".out"; + File outFile = File(outFileName, "w"); + + while (!inFile.eof()) { + string line = strip(inFile.readln()); + + if (line.length != 0) { + outFile.writeln(line); + } + } + + writeln(outFileName, " has been created."); +} +--- + +Macros: + TITLE=Files Solutions + + DESCRIPTION=Programming in D exercise solutions: basic file operations + + KEYWORDS=programming in d tutorial files diff --git a/book/d.en/files.d b/book/d.en/files.d new file mode 100644 index 0000000000..abddf118fe --- /dev/null +++ b/book/d.en/files.d @@ -0,0 +1,226 @@ +Ddoc + +$(DERS_BOLUMU $(IX file) Files) + +$(P +We have seen in the previous chapter that the standard input and output streams can be redirected to and from files and other programs with the $(C >), $(C <), and $(C |) operators on the terminal. Despite being very powerful, these tools are not suitable in every situation because in many cases programs can not complete their tasks simply by reading from their input and writing to their output. +) + +$(P +For example, a program that deals with student records may use its standard output to display the program menu. Such a program would need to write the student records to an actual file instead of to $(C stdout). +) + +$(P +In this chapter, we will cover reading from and writing to files of file systems. +) + +$(H5 Fundamental concepts) + +$(P +Files are represented by the $(C File) $(I struct) of the $(C std.stdio) module. Since I haven't introduced structs yet, we will have to accept the syntax of struct construction as is for now. +) + +$(P +Before getting to code samples we have to go through fundamental concepts about files. +) + +$(H6 The producer and the consumer) + +$(P +Files that are created on one platform may not be readily usable on other platforms. Merely opening a file and writing data to it may not be sufficient for that data to be available on the consumer's side. The producer and the consumer of the data must have already agreed on the format of the data that is in the file. For example, if the producer has written the id and the name of the student records in a certain order, the consumer must read the data back in the same order. +) + +$(P +Additionally, the code samples below do not write a $(I byte order mark) (BOM) to the beginning of the file. This may make your files incompatible with systems that require a BOM. (The BOM specifies in what order the UTF code units of characters are arranged in a file.) +) + +$(H6 Access rights) + +$(P +File systems present files to programs under certain access rights. Access rights are important for both data integrity and performance. +) + +$(P +When it comes to reading, allowing multiple programs to read from the same file can improve performance, because the programs will not have to wait for each other to perform the read operation. On the other hand, when it comes to writing, it is often beneficial to prevent concurrent accesses to a file, even when only a single program wants to write to it. By locking the file, the operating system can prevent other programs from reading partially written files, from overwriting each other's data and so on. +) + +$(H6 Opening a file) + +$(P +The standard input and output streams $(C stdin) and $(C stdout) are already $(I open) when programs start running. They are ready to be used. +) + +$(P +On the other hand, normal files must first be opened by specifying the name of the file and the access rights that are needed. As we will see in the examples below, creating a $(C File) object is sufficient to open the file specified by its name: +) + +--- + File file = File("student_records", "r"); +--- + +$(H6 Closing a file) + +$(P +Any file that has been opened by a program must be closed when the program finishes using that file. In most cases the files need not be closed explicitly; they are closed automatically when $(C File) objects are terminated automatically: +) + +--- +if (aCondition) { + + // Assume a File object has been created and used here. + // ... + +} // ← The actual file would be closed automatically here + // when leaving this scope. No need to close explicitly. +--- + +$(P +In some cases a file object may need to be re-opened to access a different file or the same file with different access rights. In such cases the file must be closed and re-opened: +) + +--- + file.close(); + file.open("student_records", "r"); +--- + +$(H6 Writing to and reading from files) + +$(P +Since files are character streams, input and output functions $(C writeln), $(C readf), etc. are used exactly the same way with them. The only difference is that the name of the $(C File) variable and a dot must be typed: +) + +--- + writeln("hello"); // writes to the standard output + stdout.writeln("hello"); // same as above + $(HILITE file.)writeln("hello"); // writes to the specified file +--- + +$(H6 $(IX eof) $(C eof()) to determine the end of a file) + +$(P +The $(C eof()) member function determines whether the end of a file has been reached while reading from a file. It returns $(C true) if the end of the file has been reached. +) + +$(P +For example, the following loop will be active until the end of the file: +) + +--- + while (!file.eof()) { + // ... + } +--- + +$(H6 $(IX std.file) The $(C std.file) module) + +$(P +The $(LINK2 http://dlang.org/phobos/std_file.html, $(C std.file) module) contains functions and types that are useful when working with contents of directories. For example, $(C exists) can be used to determine whether a file or a directory exists on the file systems: +) + +--- +import std.file; + +// ... + + if (exists(fileName)) { + // there is a file or directory under that name + + } else { + // no file or directory under that name + } +--- + +$(H5 $(IX File) $(C std.stdio.File) struct) + +$(P +$(IX mode, file) The $(C File) struct is included in the $(LINK2 http://dlang.org/phobos/std_stdio.html, $(C std.stdio) module). To use it you specify the name of the file you want to open and the desired access rights, or mode. It uses the same mode characters that are used by $(C fopen) of the C programming language: +) + + + + + + + + + + + + + + + +
     Mode  Definition
    r$(B read) access$(BR)the file is opened to be read from the beginning
    r+$(B read and write) access$(BR)the file is opened to be read from and written at the beginning
    w$(B write) access$(BR)if the file does not exist, it is created as empty$(BR)if the file already exists, its contents are cleared
    w+$(B read and write) access$(BR)if the file does not exist, it is created as empty$(BR)if the file already exists, its contents are cleared
    a$(B append) access$(BR)if the file does not exist, it is created as empty$(BR)if the file already exists, its contents are preserved and it is opened to be written at the end
    a+$(B read and append) access$(BR)if the file does not exist, it is created as empty$(BR)if the file already exists, its contents are preserved and the file is opened to be read from the beginning and written at the end
    + +$(P +A 'b' character may be added to the mode string, as in "rb". This may have an effect on platforms that support the $(I binary mode), but it is ignored on all POSIX systems. +) + +$(H6 Writing to a file) + +$(P +The file must have been opened in one of the write modes first: +) + +--- +import std.stdio; + +void main() { + File file = File("student_records", $(HILITE "w")); + + file.writeln("Name : ", "Zafer"); + file.writeln("Number: ", 123); + file.writeln("Class : ", "1A"); +} +--- + +$(P +As you remember from the $(LINK2 strings.html, Strings chapter), the type of literals like $(STRING "student_records") is $(C string), consisting of immutable characters. For that reason, it is not possible to construct $(C File) objects by using mutable text to specify the file name (e.g. $(C char[])). When needed, call the $(C .idup) property of the mutable string to get an immutable copy. +) + +$(P +The program above creates or overwrites the contents of a file named $(C student_records) in the directory that it has been started under (in the program's $(I working directory)). +) + +$(P +$(I $(B Note:) File names can contain any character that is legal for that file system. To be portable, I will use only the commonly supported ASCII characters.) +) + +$(H6 Reading from a file) + +$(P +To read from a file the file must first have been opened in one of the read modes: +) + +--- +import std.stdio; +import std.string; + +void main() { + File file = File("student_records", $(HILITE "r")); + + while (!file.eof()) { + string line = strip(file.readln()); + writeln("read line -> |", line); + } +} +--- + +$(P +The program above reads all of the lines of the file named $(C student_records) and prints those lines to its standard output. +) + +$(PROBLEM_TEK + +$(P +Write a program that takes a file name from the user, opens that file, and writes all of the non-empty lines of that file to another file. The name of the new file can be based on the name of the original file. For example, if the original file is $(C foo.txt), the new file can be $(C foo.txt.out). +) + +) + +Macros: + TITLE=Files + + DESCRIPTION=Basic file operations. + + KEYWORDS=d programming language tutorial book file diff --git a/book/d.en/floating_point.cozum.d b/book/d.en/floating_point.cozum.d new file mode 100644 index 0000000000..38415a8837 --- /dev/null +++ b/book/d.en/floating_point.cozum.d @@ -0,0 +1,110 @@ +Ddoc + +$(COZUM_BOLUMU Floating Point Types) + +$(OL + +$(LI +Replacing $(C float) with $(C double) produces an outcome that is surprising in a different way: + +--- +// ... + + $(HILITE double) result = 0; + +// ... + + if ($(HILITE result == 1)) { + writeln("As expected: 1"); + + } else { + writeln("DIFFERENT: ", result); + } +--- + +$(P +Although the value fails the $(C result == 1) comparison, it is still printed as 1: +) + +$(SHELL +DIFFERENT: 1 +) + +$(P +That surprising outcome is related to the way floating point values are formatted for printing. A more accurate approximation of the value can be seen when the value is printed with more digits after the decimal point. (We will see formatted output in $(LINK2 formatted_output.html, a later chapter).): +) + +--- + write$(HILITE f)ln("DIFFERENT: %.20f", result); +--- + +$(SHELL +DIFFERENT: 1.00000000000000066613 +) + +) + +$(LI +Replacing the three $(C int)s with three $(C double)s is sufficient: + +--- + double first; + double second; + + // ... + + double result; +--- + +) + +$(LI +The following program demonstrates how much more complicated it would become if more than five variables were needed: + +--- +import std.stdio; + +void main() { + double value_1; + double value_2; + double value_3; + double value_4; + double value_5; + + write("Value 1: "); + readf(" %s", &value_1); + write("Value 2: "); + readf(" %s", &value_2); + write("Value 3: "); + readf(" %s", &value_3); + write("Value 4: "); + readf(" %s", &value_4); + write("Value 5: "); + readf(" %s", &value_5); + + writeln("Twice the values:"); + writeln(value_1 * 2); + writeln(value_2 * 2); + writeln(value_3 * 2); + writeln(value_4 * 2); + writeln(value_5 * 2); + + writeln("One fifth the values:"); + writeln(value_1 / 5); + writeln(value_2 / 5); + writeln(value_3 / 5); + writeln(value_4 / 5); + writeln(value_5 / 5); +} +--- + +) + +) + +Macros: + TITLE=Floating Point Types Solutions + + DESCRIPTION=The exercise solutions for the floating point types chapter + + KEYWORDS=programming in d tutorial floating point types exercise solution diff --git a/book/d.en/floating_point.d b/book/d.en/floating_point.d new file mode 100644 index 0000000000..c9251211fc --- /dev/null +++ b/book/d.en/floating_point.d @@ -0,0 +1,494 @@ +Ddoc + +$(DERS_BOLUMU $(IX floating point) Floating Point Types) + +$(P +In the previous chapter, we have seen that despite their ease of use, arithmetic operations on integers are prone to programming errors due to overflow and truncation. We have also seen that integers cannot have values with fractional parts, as in 1.25. +) + +$(P +Floating point types are designed to support fractional parts. The "point" in their name comes from the $(I radix point), which separates the integer part from the fractional part, and "floating" refers to a detail in how these types are implemented: the decimal point $(I floats) left and right as appropriate. (This detail is not important when using these types.) +) + +$(P +We must cover important details in this chapter as well. Before doing that, I would like to give a list of some of the interesting aspects of floating point types: +) + +$(UL + +$(LI Adding 0.001 a thousand times is not the same as adding 1.) + +$(LI Using the logical operators $(C ==) and $(C !=) with floating point types is erroneous in most cases.) + +$(LI The initial value of floating point types is $(C .nan), not 0. $(C .nan) may not be used in expressions in any meaningful way. When used in comparison operations, $(C .nan) is not less than nor greater than any value.) + +$(LI The two overflow values are $(C .infinity) and negative $(C .infinity).) +) + +$(P +Although floating point types are more useful in some cases, they have peculiarities that every programmer must know. Compared to integers, they are very good at avoiding truncation because their main purpose is to support fractional values. Like any other type, being based on a certain number of bits, they too are prone to overflow, but compared to integers, the range of values that they can support is vast. Additionally, instead of being silent in the case of overflow, they get the special values of positive and negative $(I infinity). +) + +$(P +$(IX float) +$(IX double) +$(IX real) +As a reminder, the floating point types are the following: +) + + + + + + + + + + + + + + + + + +
    Type Number of Bits Initial Value
    float32float.nan
    double64double.nan
    realat least 64, maybe more$(BR)(e.g. 80, depending on hardware support)real.nan
    + +$(H5 Floating point type properties) + +$(P +Floating point types have more properties than other types: +) + +$(UL + +$(LI $(C .stringof) is the name of the type.) + +$(LI $(C .sizeof) is the length of the type in terms of bytes. (In order to determine the bit count, this value must be multiplied by 8, the number of bits in a byte.)) + +$(LI $(IX .min, floating point) $(C .max) is the short for "maximum" and is the maximum value that the type can have. There is no separate $(C .min) property for floating types; the negative of $(C .max) is the minimum value that the type can have. For example, the minimum value of $(C double) is $(C -double.max).) + +$(LI $(IX .min_normal) $(IX underflow) $(C .min_normal) is the smallest positive value that this type can represent with its normal precision. (Precision is explained below.) The type can represent smaller values than $(C .min_normal) but those values cannot be as precise as other values of the type and are generally slower to compute. The condition of a floating point value being between negative $(C .min_normal) and positive $(C .min_normal) (excluding 0) is called $(I underflow).) + +$(LI $(IX .dig) $(C .dig) is short for "digits" and specifies the number of digits that signify the precision of the type.) + +$(LI $(IX .infinity) $(IX overflow, floating point) $(C .infinity) is the special value used to denote overflow.) + +) + +$(P +Other properties of floating point types are used less commonly. You can see all of them at $(LINK2 http://dlang.org/property.html, Properties for Floating Point Types at dlang.org). +) + +$(P +The properties of floating point types and their relations can be shown on a number line like the following: +) + +$(MONO + + +─────────+─────────+ ... + ... +─────────+─────────+ + + │ -max -1 │ 0 │ 1 max │ + │ │ │ │ +-infinity -min_normal min_normal infinity +) + +$(P +Other than the two special infinity values, the line above is to scale: the number of values that can be represented between $(C min_normal) and 1 is equal to the number of values that can be represented between 1 and $(C max). This means that the precision of the fractional parts of the values that are between $(C min_normal) and 1 is very high. (The same is true for the negative side as well.) +) + +$(H5 $(IX .nan) $(C .nan)) + +$(P +We have already seen that this is the default value of floating point variables. $(C .nan) may appear as a result of meaningless floating point expressions as well. For example, the floating point expressions in the following program all produce $(C double.nan): +) + +--- +import std.stdio; + +void main() { + double zero = 0; + double infinity = double.infinity; + + writeln("any expression with nan: ", double.nan + 1); + writeln("zero / zero : ", zero / zero); + writeln("zero * infinity : ", zero * infinity); + writeln("infinity / infinity : ", infinity / infinity); + writeln("infinity - infinity : ", infinity - infinity); +} +--- + +$(P +$(C .nan) is not useful just because it indicates an uninitialized value. It is also useful because it is propagated through computations, making it easier and earlier to detect errors. +) + +$(H5 Specifying floating point values) + +$(P +Floating point values can be built from integer values without a decimal point, like 123, or created directly with a decimal point, like 123.0. +) + +$(P +Floating point values can also be specified with the special floating point syntax, as in $(C 1.23e+4). The $(C e+) part in that syntax can be read as "times 10 to the power of". According to that reading, the previous value is "1.23 times 10 to the power of 4", which is the same as "1.23 times 10$(SUP 4)", which in turn is the same as 1.23x10000, being equal to 12300. +) + +$(P +If the value after $(C e) is negative, as in $(C 5.67e-3), then it is read as "divided by 10 to the power of". Accordingly, this example is "5.67 divided by 10$(SUP 3)", which in turn is the same as 5.67/1000, being equal to 0.00567. +) + +$(P +The floating point format is apparent in the output of the following program that prints the properties of the three floating point types: +) + +--- +import std.stdio; + +void main() { + writeln("Type : ", float.stringof); + writeln("Precision : ", float.dig); + writeln("Minimum normalized value: ", float.min_normal); + writeln("Minimum value : ", -float.max); + writeln("Maximum value : ", float.max); + writeln(); + + writeln("Type : ", double.stringof); + writeln("Precision : ", double.dig); + writeln("Minimum normalized value: ", double.min_normal); + writeln("Minimum value : ", -double.max); + writeln("Maximum value : ", double.max); + writeln(); + + writeln("Type : ", real.stringof); + writeln("Precision : ", real.dig); + writeln("Minimum normalized value: ", real.min_normal); + writeln("Minimum value : ", -real.max); + writeln("Maximum value : ", real.max); +} +--- + +$(P +The output of the program is the following in my environment. Since $(C real) depends on the hardware, you may get a different output: +) + +$(SHELL +Type : float +Precision : 6 +Minimum normalized value: 1.17549e-38 +Minimum value : -3.40282e+38 +Maximum value : 3.40282e+38 + +Type : double +Precision : 15 +Minimum normalized value: 2.22507e-308 +Minimum value : -1.79769e+308 +Maximum value : 1.79769e+308 + +Type : real +Precision : 18 +Minimum normalized value: 3.3621e-4932 +Minimum value : -1.18973e+4932 +Maximum value : 1.18973e+4932 +) + +$(P +$(I $(B Note:) Although $(C double) and $(C real) have more precision than $(C float), $(C writeln) prints all floating point values with 6 digits of precision. (Precision is explained below.)) +) + +$(H6 Observations) + +$(P +As you will remember from the previous chapter, the maximum value of $(C ulong) has 20 digits: 18,446,744,073,709,551,616. That value looks small when compared to even the smallest floating point type: $(C float) can have values up to the 10$(SUP 38) range, e.g. 340,282,000,000,000,000,000,000,000,000,000,000,000. The maximum value of $(C real) is in the range 10$(SUP 4932), a value with more than 4900 digits! +) + +$(P +As another observation, let's look at the minimum value that $(C double) can represent with 15-digit precision: +) + +$(MONO + 0.000...$(I (there are 300 more zeroes here))...0000222507385850720 +) + +$(H5 Overflow is not ignored) + +$(P +Despite being able to take very large values, floating point types are prone to overflow as well. The floating point types are safer than integer types in this regard because overflow is not ignored. The values that overflow on the positive side become $(C .infinity), and the values that overflow on the negative side become $(C ‑.infinity). To see this, let's increase the value of $(C .max) by 10%. Since the value is already at the maximum, increasing by 10% would overflow: +) + +--- +import std.stdio; + +void main() { + real value = real.max; + + writeln("Before : ", value); + + // Multiplying by 1.1 is the same as adding 10% + value *= 1.1; + writeln("Added 10% : ", value); + + // Let's try to reduce its value by dividing in half + value /= 2; + writeln("Divided in half: ", value); +} +--- + +$(P +Once the value overflows and becomes $(C real.infinity), it remains that way even after being divided in half: +) + +$(SHELL +Before : 1.18973e+4932 +Added 10% : inf +Divided in half: inf +) + +$(H5 $(IX precision) Precision) + +$(P +Precision is a concept that we come across in daily life but do not talk about much. Precision is the number of digits that is used when specifying a value. For example, when we say that the third of 100 is 33, the precision is 2 because 33 has 2 digits. When the value is specified more precisely as 33.33, then the precision is 4 digits. +) + +$(P +The number of bits that each floating type has, not only affects its maximum value, but also its precision. The greater the number of bits, the more precise the values are. +) + +$(H5 There is no truncation in division) + +$(P +As we have seen in the previous chapter, integer division cannot preserve the fractional part of a result: +) + +--- + int first = 3; + int second = 2; + writeln(first / second); +--- + +$(P +Output: +) + +$(SHELL +1 +) + +$(P +Floating point types don't have this $(I truncation) problem; they are specifically designed for preserving the fractional parts: +) + +--- + double first = 3; + double second = 2; + writeln(first / second); +--- + +$(P +Output: +) + +$(SHELL +1.5 +) + +$(P +The accuracy of the fractional part depends on the precision of the type: $(C real) has the highest precision and $(C float) has the lowest precision. +) + +$(H5 Which type to use) + +$(P +Unless there is a specific reason not to, you can choose $(C double) for floating point values. $(C float) has low precision but due to being smaller than the other types it may be useful when memory is limited. On the other hand, since the precision of $(C real) is higher than $(C double) on some hardware, it would be preferable for high precision calculations. +) + +$(H5 Cannot represent all values) + +$(P +We cannot represent certain values in our daily lives. In the decimal system that we use daily, the digits before the decimal point represent ones, tens, hundreds, etc. and the digits after the decimal point represent tenths, hundredths, thousandths, etc. +) + +$(P +If a value is created from a combination of these values, it can be represented exactly. For example, because the value 0.23 consists of 2 tenths and 3 hundredths it is represented exactly. On the other hand, the value 1/3 cannot be exactly represented in the decimal system because the number of digits is always insufficient, no matter how many are specified: 0.33333... +) + +$(P +The situation is very similar with the floating point types. Because these types are based on a certain number of bits, they cannot represent every value exactly. +) + +$(P +The difference with the binary system that the computers use is that the digits before the decimal point are ones, twos, fours, etc. and the digits after the decimal point are halves, quarters, eighths, etc. Only the values that are exact combinations of those digits can be represented exactly. +) + +$(P +A value that cannot be represented exactly in the binary system used by computers is 0.1, as in 10 cents. Although this value can be represented exactly in the decimal system, its binary representation never ends and continuously repeats four digits: 0.0001100110011... (Note that the value is written in binary system, not decimal.) It is always inaccurate at some level depending on the precision of the floating point type that is used. +) + +$(P +The following program demonstrates this problem. The value of a variable is being incremented by 0.001 a thousand times in a loop. Surprisingly, the result is not 1: +) + +--- +import std.stdio; + +void main() { + float result = 0; + + // Adding 0.001 for a thousand times: + int counter = 1; + while (counter <= 1000) { + result += 0.001; + ++counter; + } + + if (result == 1) { + writeln("As expected: 1"); + + } else { + writeln("DIFFERENT: ", result); + } +} +--- + +$(P +Because 0.001 cannot be represented exactly, that inaccuracy affects the result at every iteration: +) + +$(SHELL +DIFFERENT: 0.999991 +) + +$(P +$(I $(B Note:) The variable $(C counter) above is a loop counter. Defining a variable explicitly for that purpose is not recommended. Instead, a common approach is to use a $(C foreach) loop, which we will see in $(LINK2 foreach.html, a later chapter).) +) + +$(H5 $(IX unordered) Unorderedness) + +$(P +The same comparison operators that we have covered with integers are used with floating point types as well. However, since the special value $(C .nan) represents invalid floating point values, comparing $(C .nan) to other values is not meaningful. For example, it does not make sense to ask whether $(C .nan) or $(C 1) is greater. +) + +$(P +For that reason, floating point values introduce another comparison concept: unorderedness. Being unordered means that at least one of the values is $(C .nan). +) + +$(P +The following table lists all the floating point comparison operators. All of them are binary operators (meaning that they take two operands) and used as in $(C left == right). The columns that contain $(C false) and $(C true) are the results of the comparison operations. +) + +$(P +The last column indicates whether the operation is meaningful if one of the operands is $(C .nan). For example, even though the result of the expression $(C 1.2 < real.nan) is $(C false), that result is meaningless because one of the operands is $(C real.nan). The result of the reverse comparison $(C real.nan < 1.2) would produce $(C false) as well. The abreviation lhs stands for $(I left-hand side), indicating the expression on the left-hand side of each operator. +) + + + + + + + + + + + + + + + + + + + + + + + + + + +
    $(BR)Operator$(BR)MeaningIf lhs$(BR)is greaterIf lhs$(BR)is lessIf both$(BR)are equalIf at least$(BR)one is .nanMeaningful$(BR)with .nan
    ==is equal to $(UNORDERED_FALSE false)$(UNORDERED_FALSE false)$(UNORDERED_TRUE true)$(UNORDERED_FALSE false)$(UNORDERED_YES yes)
    !=is not equal to $(UNORDERED_TRUE true)$(UNORDERED_TRUE true)$(UNORDERED_FALSE false)$(UNORDERED_TRUE true)$(UNORDERED_YES yes)
    >is greater than $(UNORDERED_TRUE true)$(UNORDERED_FALSE false)$(UNORDERED_FALSE false)$(UNORDERED_FALSE false)$(UNORDERED_NO no)
    >=is greater than or equal to $(UNORDERED_TRUE true)$(UNORDERED_FALSE false)$(UNORDERED_TRUE true)$(UNORDERED_FALSE false)$(UNORDERED_NO no)
    <is less than $(UNORDERED_FALSE false)$(UNORDERED_TRUE true)$(UNORDERED_FALSE false)$(UNORDERED_FALSE false)$(UNORDERED_NO no)
    <=is less than or equal to $(UNORDERED_FALSE false)$(UNORDERED_TRUE true)$(UNORDERED_TRUE true)$(UNORDERED_FALSE false)$(UNORDERED_NO no)
    + +$(P +Although meaningful to use with $(C .nan), the $(C ==) operator always produces $(C false) when used with a $(C .nan) value. This is the case even when both values are $(C .nan): +) + +--- +import std.stdio; + +void main() { + if (double.nan == double.nan) { + writeln("equal"); + + } else { + writeln("not equal"); + } +} +--- + +$(P +Although one would expect $(C double.nan) to be equal to itself, the result of the comparison is $(C false): +) + +$(SHELL +not equal +) + +$(H6 $(IX isNan, std.math) $(C isNaN()) for $(C .nan) equality comparison) + +$(P +As we have seen above, it is not possible to use the $(C ==) operator to determine whether the value of a floating point variable is $(C .nan): +) + +--- + if (variable == double.nan) { $(CODE_NOTE_WRONG WRONG) + // ... + } +--- + +$(P +$(C isNaN()) function from the $(C std.math) module is for determining whether a value is $(C .nan): +) + +--- +import std.math; +// ... + if (isNaN(variable)) { $(CODE_NOTE correct) + // ... + } +--- + +$(P +Similarly, to determine whether a value is $(I not) $(C .nan), one must use $(C !isNaN()) because otherwise the $(C !=) operator would always produce $(C true). +) + +$(PROBLEM_COK + +$(PROBLEM +Instead of $(C float), use $(C double) (or $(C real)) in the program above which added 0.001 a thousand times: + +--- + $(HILITE double) result = 0; +--- + +$(P +This exercise demonstrates how misleading floating point equality comparisons can be. +) + +) + +$(PROBLEM +Modify the calculator from the previous chapter to support floating point types. The new calculator should work more accurately with that change. When trying the calculator, you can enter floating point values in various formats, as in 1000, 1.23, and 1.23e4. +) + +$(PROBLEM +Write a program that reads 5 floating point values from the input. Make the program first print twice of each value and then one fifth of each value. + +$(P +This exercise is a preparation for the array concept of the next chapter. If you write this program with what you have seen so far, you will understand arrays more easily and will better appreciate them. +) + +) + +) + +Macros: + TITLE=Floating Point Types + + DESCRIPTION=The floating point types of the D programming language. + + KEYWORDS=d programming language tutorial book floating point float double real numeric limits diff --git a/book/d.en/for.cozum.d b/book/d.en/for.cozum.d new file mode 100644 index 0000000000..41b7321fd2 --- /dev/null +++ b/book/d.en/for.cozum.d @@ -0,0 +1,86 @@ +Ddoc + +$(COZUM_BOLUMU The $(C for) Loop) + +$(OL + +$(LI + +--- +import std.stdio; + +void main() { + for (int line = 0; line != 9; ++line) { + for (int column = 0; column != 9; ++column) { + write(line, ',', column, ' '); + } + + writeln(); + } +} +--- + +) + +$(LI +Triangle: + +--- +import std.stdio; + +void main() { + for (int line = 0; line != 5; ++line) { + int length = line + 1; + + for (int i = 0; i != length; ++i) { + write('*'); + } + + writeln(); + } +} +--- + +$(P +Parallellogram: +) + +--- +import std.stdio; + +void main() { + for (int line = 0; line != 5; ++line) { + for (int i = 0; i != line; ++i) { + write(' '); + } + + writeln("********"); + } +} +--- + +$(P +Can you produce the diamond pattern? +) + +$(SHELL + * + *** + ***** +******* + ***** + *** + * +) + +) + +) + + +Macros: + TITLE=The for Loop Solutions + + DESCRIPTION=Programming in D exercise solutions: the for loop + + KEYWORDS=programming in d tutorial for loop solution diff --git a/book/d.en/for.d b/book/d.en/for.d new file mode 100644 index 0000000000..60eabf6a17 --- /dev/null +++ b/book/d.en/for.d @@ -0,0 +1,257 @@ +Ddoc + +$(DERS_BOLUMU $(IX for) $(IX loop, for) $(CH4 for) Loop) + +$(P +The $(C for) loop serves the same purpose as $(LINK2 while.html, the $(C while) loop). $(C for) makes it possible to put the definitions and expressions concerning the loop's iteration on the same line. +) + +$(P +Although $(C for) is used much less than $(C foreach) in practice, it is important to understand the $(C for) loop first. We will see $(C foreach) in $(LINK2 foreach.html, a later chapter). +) + +$(H5 The sections of the $(C while) loop) + +$(P +The $(C while) loop evaluates the loop condition and continues executing the loop as long as that condition is $(C true). For example, a loop to print the numbers between 1 and 10 may check the condition $(I less than 11): +) + +--- + while (number < 11) +--- + +$(P +$(I Iterating) the loop can be achieved by incrementing $(C number) at the end of the loop: +) + +--- + ++number; +--- + +$(P +To be compilable as D code, $(C number) must have been defined before its first use: +) + +--- + int number = 1; +--- + +$(P +Finally, there is the actual work within the loop body: +) + +--- + writeln(number); +--- + +$(P +These four sections can be combined into the desired loop as follows: +) + +--- + int number = 1; // ← preparation + + while (number < 11) { // ← condition check + writeln(number); // ← actual work + ++number; // ← iteration + } +--- + +$(P +The sections of the $(C while) loop are executed in the following order during the iteration of the $(C while) loop: +) + +$(MONO +preparation + +condition check +actual work +iteration + +condition check +actual work +iteration + +... +) + +$(P +A $(C break) statement or a thrown exception can terminate the loop as well. +) + +$(H5 The sections of the $(C for) loop) + +$(P +The $(C for) loop brings three of these sections onto a single line. They are written within the parentheses of the $(C for) loop, separated by semicolons. The loop body contains only the actual work: +) + +--- +for (/* preparation */; /* condition check */; /* iteration */) { + /* actual work */ +} +--- + +$(P +Here is the same code written as a $(C for) loop: +) + +--- + for (int number = 1; number < 11; ++number) { + writeln(number); + } +--- + +$(P +The benefits of the $(C for) loop are more obvious when the loop body has a large number of statements. The expression that increments the loop variable is visible on the $(C for) line instead of being mixed with the other statements of the loop. It is also more clear that the declared variable is used only as part of the loop, and not by any other surrounding code. +) + +$(P +The sections of the $(C for) loop are executed in the same order as in the $(C while) loop. The $(C break) and $(C continue) statements also work exactly the same way as they do in the $(C for) loop. The only difference between $(C while) and $(C for) loops is the name scope of the loop variable. This is explained below. +) + +$(P +Although very common, the iteration variable need not be an integer, nor it is modified only by incrementing. For example, the following loop is used to print the halves of the previous floating point values: +) + +--- + for (double value = 1; value > 0.001; value /= 2) { + writeln(value); + } +--- + +$(P +$(B Note:) The information above is technically incorrect but better captures the spirit of how the $(C for) loop is used in practice. In reality, D's $(C for) loop does not have $(I three sections that are separated by semicolons). It has two sections, the first of which consisting of the preparation and the loop condition. +) + +$(P +Without getting into the details of this syntax, here is how to define two variables of different types in the preparation section: +) + +--- + for ($(HILITE {) int i = 0; double d = 0.5; $(HILITE }) i < 10; ++i) { + writeln("i: ", i, ", d: ", d); + d /= 2; + } +--- + +$(P +Note that the preparation section is the area within the highlighted curly brackets and that there is no semicolon between the preparation section and the condition section. +) + +$(H5 The sections may be empty) + +$(P +All three of the $(C for) loop sections may be left empty: +) + +$(UL +$(LI Sometimes a special loop variable is not needed, possibly because an already-defined variable would be used. +) +$(LI Sometimes the loop would be exited by a $(C break) statement, instead of by relying on the loop condition. +) +$(LI Sometimes the iteration expressions depend on certain conditions that would be checked within the loop body. +) +) + +$(P +When all of the sections are emtpy, the $(C for) loop means $(I forever): +) + +--- + for ( ; ; ) { + // ... + } +--- + +$(P +Such a loop may be designed to never end or end with a $(C break) statement. +) + +$(H5 The name scope of the loop variable) + +$(P +The only difference between the $(C for) and $(C while) loops is the name scope of the variable defined during loop preparation: The variable is accessible only within the $(C for) loop, not outside of it: +) + +--- + for (int i = 0; i < 5; ++i) { + // ... + } + + writeln(i); $(DERLEME_HATASI) + // i is not accessible here +--- + + +$(P +In contrast, when using a $(C while) loop the variable is defined in the same name scope as that which contains the loop, and therefore the name is accessible even after the loop: +) + +--- + int i = 0; + + while (i < 5) { + // ... + ++i; + } + + writeln(i); // ← 'i' is accessible here +--- + +$(P +We have seen the guideline of $(I defining names closest to their first use) in the previous chapter. Similar to the rationale for that guideline, the smaller the name scope of a variable the better. In this regard, when the loop variable is not needed outside the loop, a $(C for) loop is better than a $(C while) loop. +) + +$(PROBLEM_COK + +$(PROBLEM + +Print the following 9x9 table by using two $(C for) loops, one inside the other: + +$(SHELL +0,0 0,1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 +1,0 1,1 1,2 1,3 1,4 1,5 1,6 1,7 1,8 +2,0 2,1 2,2 2,3 2,4 2,5 2,6 2,7 2,8 +3,0 3,1 3,2 3,3 3,4 3,5 3,6 3,7 3,8 +4,0 4,1 4,2 4,3 4,4 4,5 4,6 4,7 4,8 +5,0 5,1 5,2 5,3 5,4 5,5 5,6 5,7 5,8 +6,0 6,1 6,2 6,3 6,4 6,5 6,6 6,7 6,8 +7,0 7,1 7,2 7,3 7,4 7,5 7,6 7,7 7,8 +8,0 8,1 8,2 8,3 8,4 8,5 8,6 8,7 8,8 +) + +) + +$(PROBLEM + +Use one or more $(C for) loops to print the $(C *) character as needed to produce geometrical patterns: + + +$(SHELL +* +** +*** +**** +***** +) + +$(SHELL +******** + ******** + ******** + ******** + ******** +) + +etc. + +) + +) + +Macros: + TITLE=for Loop + + DESCRIPTION=The for loop of the D programming language and comparing it the while loop. + + KEYWORDS=d programming language tutorial book for loop diff --git a/book/d.en/foreach.cozum.d b/book/d.en/foreach.cozum.d new file mode 100644 index 0000000000..6fd0027f0e --- /dev/null +++ b/book/d.en/foreach.cozum.d @@ -0,0 +1,34 @@ +Ddoc + +$(COZUM_BOLUMU The $(C foreach) Loop) + +$(P +To have an associative array that works the opposite of $(C names), the types of the key and the value must be swapped. The new associative array must be defined as of type $(C int[string]). +) + +$(P +Iterating over the keys and the values of the original associative array while using keys as values and values as keys would populate the $(C values) table: +) + +--- +import std.stdio; + +void main() { + string[int] names = [ 1:"one", 7:"seven", 20:"twenty" ]; + + int[string] values; + + foreach (key, value; names) { + values[value] = key; + } + + writeln(values["twenty"]); +} +--- + +Macros: + TITLE=The foreach Loop Solutions + + DESCRIPTION=Programming in D exercise solutions: The foreach Loop + + KEYWORDS=programming in d tutorial foreach diff --git a/book/d.en/foreach.d b/book/d.en/foreach.d new file mode 100644 index 0000000000..dcddabd029 --- /dev/null +++ b/book/d.en/foreach.d @@ -0,0 +1,438 @@ +Ddoc + +$(DERS_BOLUMU $(IX foreach) $(IX loop, foreach) $(CH4 foreach) Loop) + +$(P +One of the most common statements in D is the $(C foreach) loop. It is used for applying the same operations to every element of a container (or a $(I range)). +) + +$(P +Operations that are applied to elements of containers are very common in programming. We have seen in the $(LINK2 for.html, $(C for) Loop chapter) that elements of an array are accessed in a $(C for) loop by an index value that is incremented at each iteration: +) + +--- + for (int i = 0; i != array.length; ++i) { + writeln(array[i]); + } +--- + +$(P +The following steps are involved in iterating over all the elements: +) + +$(UL +$(LI Defining a variable as a counter, which is conventionally named as $(C i)) + +$(LI Iterating the loop up to the value of the $(C .length) property of the array) + +$(LI Incrementing $(C i)) + +$(LI Accessing the element) +) + +$(P +$(C foreach) has essentially the same behavior but it simplifies the code by handling those steps automatically: +) + +--- + foreach (element; array) { + writeln(element); + } +--- + +$(P +Part of the power of $(C foreach) comes from the fact that it can be used the same way regardless of the type of the container. As we have seen in the previous chapter, one way of iterating over the values of an associative array in a $(C for) loop is by first calling the array's $(C .values) property: +) + +--- + auto values = aa$(HILITE .values); + for (int i = 0; i != values.length; ++i) { + writeln(values[i]); + } +--- + +$(P +$(C foreach) does not require anything special for associative arrays; it is used exactly the same as with arrays: +) + +--- + foreach (value; aa) { + writeln(value); + } +--- + +$(H5 The $(C foreach) syntax) + +$(P +$(C foreach) consists of three sections: +) + +--- + foreach ($(I names); $(I container_or_range)) { + $(I operations) + } +--- + +$(UL +$(LI $(B $(I container_or_range)) specifies where the elements are. +) + +$(LI $(B $(I operations)) specifies the operations to apply to each element. +) + +$(LI $(B $(I names)) specifies the name of the element and potentially other variables depending on the type of the container or the range. Although the choice of names is up to the programmer, the number of and the types of these names depend on the type of the container. +) +) + +$(H5 $(C continue) and $(C break)) + +$(P +These keywords have the same meaning as they do for the $(C for) loop: $(C continue) moves to the next iteration before completing the rest of the operations for the current element, and $(C break) terminates the loop altogether. +) + +$(H5 $(C foreach) with arrays) + +$(P +When using $(C foreach) with plain arrays and there is a single name specified in the $(I names) section, that name represents the value of the element at each iteration: +) + +--- + foreach (element; array) { + writeln(element); + } +--- + +$(P +When two names are specified in the $(I names) section, they represent an automatic counter and the value of the element, respectively: +) + +--- + foreach (i, element; array) { + writeln(i, ": ", element); + } +--- + +$(P +The counter is incremented automatically by $(C foreach). Although it can be named anything else, $(C i) is a very common name for the automatic counter. +) + +$(H5 $(IX stride, std.range) $(C foreach) with strings and $(C std.range.stride)) + +$(P +Since strings are arrays of characters, $(C foreach) works with strings the same way as it does with arrays: A single name refers to the character, two names refer to the counter and the character, respectively: +) + +--- + foreach (c; "hello") { + writeln(c); + } + + foreach (i, c; "hello") { + writeln(i, ": ", c); + } +--- + +$(P +However, being UTF code units, $(C char) and $(C wchar) iterate over UTF code units, not Unicode code points: +) + +--- + foreach (i, code; "abcçd") { + writeln(i, ": ", code); + } +--- + +$(P +The two UTF-8 code units that make up ç would be accessed as separate elements: +) + +$(SHELL +0: a +1: b +2: c +3: +4: � +5: d +) + +$(P +One way of iterating over Unicode characters of strings in a $(C foreach) loop is $(C stride) from the $(C std.range) module. $(C stride) presents the string as a container that consists of Unicode characters. Its second parameter is the number of steps that it should take as it $(I strides) over the characters: +) + +--- +import std.range; + +// ... + + foreach (c; stride("abcçd", 1)) { + writeln(c); + } +--- + +$(P +Regardless of the character type of the string, $(C stride) always presents its elements as Unicode characters: +) + +$(SHELL +a +b +c +ç +d +) + +$(P +I will explain below why this loop could not include an automatic counter. +) + +$(H5 $(C foreach) with associative arrays) + +$(P +When using $(C foreach) with associative arrays, a single name refers to the value, while two names refer to the key and the value, respectively: +) + +--- + foreach (value; aa) { + writeln(value); + } + + foreach (key, value; aa) { + writeln(key, ": ", value); + } +--- + +$(P +$(IX .byKey, foreach) $(IX .byValue, foreach) $(IX .byKeyValue, foreach) Associative arrays can provide their keys and values as $(I ranges) as well. We will see ranges in $(LINK2 ranges.html, a later chapter). $(C .byKey), $(C .byValue), and $(C .byKeyValue) return efficient range objects that are useful in contexts other than $(C foreach) loops as well. +) + +$(P +$(C .byValue) does not bring any benefit in $(C foreach) loops over the regular value iteration above. On the other hand, $(C .byKey) is the only efficient way of iterating over $(I just) the keys of an associative array: +) + +--- + foreach (key; aa$(HILITE .byKey)) { + writeln(key); + } +--- + +$(P +$(C .byKeyValue) provides each key-value element through a variable that is similar to a $(LINK2 tuples.html, tuple). The key and the value are accessed separately through the $(C .key) and $(C .value) properties of that variable: +) + +--- + foreach (element; aa$(HILITE .byKeyValue)) { + writefln("The value for key %s is %s", + element$(HILITE .key), element$(HILITE.value)); + } +--- + +$(H5 $(IX number range) $(IX .., number range) $(C foreach) with number ranges) + +$(P +We have seen number ranges before, in the $(LINK2 slices.html, Slices and Other Array Features chapter). It is possible to specify a number range in the $(I container_or_range) section: +) + +--- + foreach (number; 10..15) { + writeln(number); + } +--- + +$(P +Remember that 10 would be included in the range but 15 would not be. +) + +$(H5 $(C foreach) with structs, classes, and ranges) + +$(P +$(C foreach) can also be used with objects of user-defined types that define their own iteration in $(C foreach) loops. Structs and classes provide support for $(C foreach) iteration either by their $(C opApply()) member functions, or by a set of $(I range) member functions. We will see these features in later chapters. +) + +$(H5 $(IX counter, foreach) The counter is automatic only for arrays) + +$(P +The automatic counter is provided only when iterating over arrays. There are two options for other containers +) +$(UL +$(LI Taking advantage of $(C std.range.enumerate) as we will see later in $(LINK2 foreach_opapply.html, the $(C foreach) with Structs and Classes chapter).) + +$(LI Defining and incrementing a counter variable explicitly: + +--- + size_t $(HILITE i) = 0; + foreach (element; container) { + // ... + ++i; + } +--- +) +) + +$(P +Such a variable is needed when counting a specific condition as well. For example, the following code counts only the values that are divisible by 10: +) + +--- +import std.stdio; + +void main() { + auto numbers = [ 1, 0, 15, 10, 3, 5, 20, 30 ]; + + size_t count = 0; + foreach (number; numbers) { + if ((number % 10) == 0) { + $(HILITE ++count); + write(count); + + } else { + write(' '); + } + + writeln(": ", number); + } +} +--- + +$(P +The output: +) + +$(SHELL + + : 1 +1: 0 + : 15 +2: 10 + : 3 + : 5 +3: 20 +4: 30 +) + +$(H5 The copy of the element, not the element itself) + +$(P +The $(C foreach) loop normally provides a copy of the element, not the actual element that is stored in the container. This may be a cause of bugs. +) + +$(P +To see an example of this, let's have a look at the following program that is trying to double the values of the elements of an array: +) + +--- +import std.stdio; + +void main() { + double[] numbers = [ 1.2, 3.4, 5.6 ]; + + writefln("Before: %s", numbers); + + foreach (number; numbers) { + number *= 2; + } + + writefln("After : %s", numbers); +} +--- + +$(P +The output of the program indicates that the assignment made to each element inside the $(C foreach) body does not have any effect on the elements of the container: +) + +$(SHELL +Before: [1.2, 3.4, 5.6] +After : [1.2, 3.4, 5.6] +) + +$(P +$(IX ref, foreach) That is because $(C number) is not an actual element of the array, but a copy of each element. When the actual elements need to be operated on, the name must be defined as a $(I reference) of the actual element, by using the $(C ref) keyword: +) + +--- + foreach ($(HILITE ref) number; numbers) { + number *= 2; + } +--- + +$(P +The new output shows that the assignments now modify the actual elements of the array: +) + +$(SHELL +Before: [1.2, 3.4, 5.6] +After : [2.4, 6.8, 11.2] +) + +$(P +The $(C ref) keyword makes $(C number) an $(I alias) of the actual element at each iteration. As a result, the modifications through $(C number) modify that actual element of the container. +) + +$(H5 The integrity of the container must be preserved) + +$(P +Although it is fine to modify the elements of a container through $(C ref) variables, the structure of a container must not be changed during its iteration. For example, elements must not be removed nor added to the container during a $(C foreach) loop. +) + +$(P +Such modifications may confuse the inner workings of the loop iteration and result in incorrect program states. +) + +$(H5 $(IX foreach_reverse) $(IX loop, foreach_reverse) $(C foreach_reverse) to iterate in the reverse direction) + +$(P +$(C foreach_reverse) works the same way as $(C foreach) except it iterates in the reverse direction: +) + +--- + auto container = [ 1, 2, 3 ]; + + foreach_reverse (element; container) { + writefln("%s ", element); + } +--- + +$(P +The output: +) + +$(SHELL +3 +2 +1 +) + +$(P +The use of $(C foreach_reverse) is not common because the range function $(C retro()) achieves the same goal. We will see $(C retro()) in a later chapter. +) + +$(PROBLEM_TEK + +$(P +We know that associative arrays provide a mapping from keys to values. This mapping is unidirectional: values are accessed by keys but not the other way around. +) + +$(P +Assume that there is already the following associative array: +) + +--- + string[int] names = [ 1:"one", 7:"seven", 20:"twenty" ]; +--- + +$(P +Use that associative array and a $(C foreach) loop to fill another associative array named $(C values). The new associative array should provide values that correspond to names. For example, the following line should print 20: +) + +--- + writeln(values["twenty"]); +--- + +) + + +Macros: + TITLE=foreach Loop + + DESCRIPTION=The foreach loop that is used to iterate over the elements of containers. + + KEYWORDS=d programming language tutorial book foreach diff --git a/book/d.en/foreach_opapply.cozum.d b/book/d.en/foreach_opapply.cozum.d new file mode 100644 index 0000000000..995a6f849a --- /dev/null +++ b/book/d.en/foreach_opapply.cozum.d @@ -0,0 +1,203 @@ +Ddoc + +$(COZUM_BOLUMU $(CH4 foreach) with Structs and Classes) + +$(OL + +$(LI The step size must be stored alongside $(C begin) and $(C end), and the element value must be increased by that step size: + +--- +struct NumberRange { + int begin; + int end; + $(HILITE int stepSize;) + + int opApply(int delegate(ref int) dg) const { + int result; + + for (int number = begin; number != end; $(HILITE number += stepSize)) { + result = dg(number); + + if (result) { + break; + } + } + + return result; + } +} + +import std.stdio; + +void main() { + foreach (element; NumberRange(0, 10, 2)) { + write(element, ' '); + } +} +--- + +) + +$(LI + +--- +import std.stdio; +import std.string; + +class Student { + string name; + int id; + + this(string name, int id) { + this.name = name; + this.id = id; + } + + override string toString() { + return format("%s(%s)", name, id); + } +} + +class Teacher { + string name; + string subject; + + this(string name, string subject) { + this.name = name; + this.subject = subject; + } + + override string toString() { + return format("%s teacher %s", subject, name); + } +} + +class School { +private: + + Student[] students; + Teacher[] teachers; + +public: + + this(Student[] students, Teacher[] teachers) { + this.students = students; + this.teachers = teachers; + } + + /* This opApply override will be called when the foreach + * variable is a Student. */ + int opApply(int delegate(ref $(HILITE Student)) dg) { + int result; + + foreach (student; students) { + result = dg(student); + + if (result) { + break; + } + } + + return result; + } + + /* Similarly, this opApply will be called when the foreach + * variable is a Teacher. */ + int opApply(int delegate(ref $(HILITE Teacher)) dg) { + int result; + + foreach (teacher; teachers) { + result = dg(teacher); + + if (result) { + break; + } + } + + return result; + } +} + +void printIndented(T)(T value) { + writeln(" ", value); +} + +void main() { + auto school = new School( + [ new Student("Can", 1), + new Student("Canan", 10), + new Student("Cem", 42), + new Student("Cemile", 100) ], + + [ new Teacher("Nazmiye", "Math"), + new Teacher("Makbule", "Literature") ]); + + writeln("Student loop"); + foreach ($(HILITE Student) student; school) { + printIndented(student); + } + + writeln("Teacher loop"); + foreach ($(HILITE Teacher) teacher; school) { + printIndented(teacher); + } +} +--- + +$(P +The output: +) + +$(SHELL +Student loop + Can(1) + Canan(10) + Cem(42) + Cemile(100) +Teacher loop + Math teacher Nazmiye + Literature teacher Makbule +) + +$(P +As you can see, the implementations of both of the $(C opApply()) overrides are exactly the same, except the slice that they iterate on. To reduce code duplication, the common functionality can be moved to an implementation function template, which then gets called by the two $(C opApply()) overrides: +) + +--- +class School { +// ... + + int opApplyImpl$(HILITE (T))(T[] slice, int delegate(ref T) dg) { + int result; + + foreach (element; slice) { + result = dg(element); + + if (result) { + break; + } + } + + return result; + } + + int opApply(int delegate(ref Student) dg) { + return opApplyImpl(students, dg); + } + + int opApply(int delegate(ref Teacher) dg) { + return opApplyImpl(teachers, dg); + } +} +--- + +) + +) + +Macros: + TITLE=foreach with Structs and Classes Solutions + + DESCRIPTION=Programming in D exercise solutions: foreach with structs and classes. + + KEYWORDS=programming in d tutorial foreach opApply diff --git a/book/d.en/foreach_opapply.d b/book/d.en/foreach_opapply.d new file mode 100644 index 0000000000..f230e8292e --- /dev/null +++ b/book/d.en/foreach_opapply.d @@ -0,0 +1,666 @@ +Ddoc + +$(DERS_BOLUMU $(IX foreach, user defined type) $(IX struct, foreach) $(IX class, foreach) $(CH4 foreach) with Structs and Classes) + +$(P +As you remember from $(LINK2 foreach.html, the $(C foreach) Loop chapter), both how $(C foreach) works and the types and numbers of loop variables that it supports depend on the kind of collection: For slices, $(C foreach) provides access to elements with or without a counter; for associative arrays, to values with or without keys; for number ranges, to the individual values. For library types, $(C foreach) behaves in a way that is specific to that type; e.g. for $(C File), it provides the lines of a file. +) + +$(P +It is possible to define the behavior of $(C foreach) for user-defined types as well. There are two methods of providing this support: +) + +$(UL +$(LI Defining $(I range member functions), which allows using the user-defined type with other range algorithms as well) + +$(LI Defining one or more $(C opApply) member functions) +) + +$(P +Of the two methods, $(C opApply) has priority: If it is defined, the compiler uses $(C opApply), otherwise it considers the range member functions. However, in most cases range member functions are sufficient, easier, and more useful. +) + +$(P +$(C foreach) need not be supported for every type. Iterating over an object makes sense only if that object defines the concept of $(I a collection). +) + +$(P +For example, it may not be clear what elements should $(C foreach) provide when iterating over a class that represents a student, so the class better not support $(C foreach) at all. On the other hand, a design may require that $(C Student) is a collection of grades and $(C foreach) may provide individual grades of the student. +) + +$(P +It depends on the design of the program what types should provide this support and how. +) + +$(H5 $(IX range, foreach) $(C foreach) support by range member functions) + +$(P +$(IX empty) $(IX front) $(IX popFront) We know that $(C foreach) is very similar to $(C for), except that it is more useful and safer than $(C for). Consider the following loop: +) + +--- + foreach (element; myObject) { + // ... expressions ... + } +--- + +$(P +Behind the scenes, the compiler rewrites that $(C foreach) loop as a $(C for) loop, roughly an equivalent of the following one: +) + +--- + for ( ; /* while not done */; /* skip the front element */) { + + auto element = /* the front element */; + + // ... expressions ... + } +--- + +$(P +User-defined types that need to support $(C foreach) can provide three member functions that correspond to the three sections of the previous code: determining whether the loop is over, skipping the front element, and providing access to the front element. +) + +$(P +Those three member functions must be named as $(C empty), $(C popFront), and $(C front), respectively. The code that is generated by the compiler calls those functions: +) + +--- + for ( ; !myObject.empty(); myObject.popFront()) { + + auto element = myObject.front(); + + // ... expressions ... + } +--- + +$(P +These three functions must work according to the following expectations: +) + +$(UL + +$(LI $(C .empty()) must return $(C true) if the loop is over, $(C false) otherwise) + +$(LI $(C .popFront()) must move to the next element (in other words, skip the front element)) + +$(LI $(C .front()) must return the front element) + +) + +$(P +Any type that defines those member functions can be used with $(C foreach). +) + +$(H6 Example) + +$(P +Let's define a $(C struct) that produces numbers within a certain range. In order to be consistent with D's number ranges and slice indexes, let's have the last number be outside of the valid numbers. Under these requirements, the following $(C struct) would work exactly like D's number ranges: +) + +--- +struct NumberRange { + int begin; + int end; + + invariant() { + // There is a bug if begin is greater than end + assert(begin <= end); + } + + bool empty() const { + // The range is consumed when begin equals end + return begin == end; + } + + void popFront() { + // Skipping the first element is achieved by + // incrementing the beginning of the range + ++begin; + } + + int front() const { + // The front element is the one at the beginning + return begin; + } +} +--- + +$(P +$(I $(B Note:) The safety of that implementation depends solely on a single $(C invariant) block. Additional checks could be added to $(C front) and $(C popFront) to ensure that those functions are never called when the range is empty.) +) + +$(P +Objects of that $(C struct) can be used with $(C foreach): +) + +--- + foreach (element; NumberRange(3, 7)) { + write(element, ' '); + } +--- + +$(P +$(C foreach) uses those three functions behind the scenes and iterates until $(C empty()) returns $(C true): +) + +$(SHELL_SMALL +3 4 5 6 +) + +$(H6 $(IX retro, std.range) $(C std.range.retro) to iterate in reverse) + +$(P +$(IX save) $(IX back) $(IX popBack) The $(C std.range) module contains many range algorithms. $(C retro) is one of those algorithms, which iterates a range in reverse order. It requires two additional range member functions: +) + +$(UL + +$(LI $(C .popBack()) must move to the element that is one before the end (skips the last element)) + +$(LI $(C .back()) must return the last element) + +) + +$(P +However, although not directly related to reverse iteration, for $(C retro) to consider those functions at all, there must be one more function defined: +) + +$(UL +$(LI $(C .save()) must return a copy of this object) +) + +$(P +We will learn more about these member functions later in $(LINK2 ranges.html, the Ranges chapter). +) + +$(P +These three additional member functions can trivially be defined for $(C NumberRange): +) + +--- +struct NumberRange { +// ... + + void popBack() { + // Skipping the last element is achieved by + // decrementing the end of the range. + --end; + } + + int back() const { + // As the 'end' value is outside of the range, the + // last element is one less than that + return end - 1; + } + + NumberRange save() const { + // Returning a copy of this struct object + return this; + } +} +--- + +$(P +Objects of this type can now be used with $(C retro): +) + +--- +import std.range; + +// ... + + foreach (element; NumberRange(3, 7)$(HILITE .retro)) { + write(element, ' '); + } +--- + +$(P +The output of the program is now in reverse: +) + +$(SHELL_SMALL +6 5 4 3 +) + +$(H5 $(IX opApply) $(IX opApplyReverse) $(C foreach) support by $(C opApply) and $(C opApplyReverse) member functions) + +$(P +$(IX foreach_reverse) Everything that is said about $(C opApply) in this section is valid for $(C opApplyReverse) as well. $(C opApplyReverse) is for defining the behaviors of objects in the $(C foreach_reverse) loops. +) + +$(P +The member functions above allow using objects as ranges. That method is more suitable when there is only one sensible way of iterating over a range. For example, it would be easy to provide access to individual students of a $(C Students) type. +) + +$(P +On the other hand, sometimes it makes more sense to iterate over the same object in different ways. We know this from associative arrays where it is possible to access either only to the values or to both the keys and the values: +) + +--- + string[string] dictionary; // from English to Turkish + + // ... + + foreach (inTurkish; dictionary) { + // ... only values ... + } + + foreach (inEnglish, inTurkish; dictionary) { + // ... keys and values ... + } +--- + +$(P +$(C opApply) allows using user-defined types with $(C foreach) in various and sometimes more complex ways. Before learning how to define $(C opApply), we must first understand how it is called automatically by $(C foreach). +) + +$(P +The program execution alternates between the expressions inside the $(C foreach) block and the expressions inside the $(C opApply()) function. First the $(C opApply()) member function gets called, and then $(C opApply) makes an explicit call to the $(C foreach) block. They alternate in that way until the loop eventually terminates. This process is based on a $(I convention), which I will explain soon. +) + +$(P +Let's first observe the structure of the $(C foreach) loop one more time: +) + +--- +// The loop that is written by the programmer: + + foreach (/* loop variables */; myObject) { + // ... expressions inside the foreach block ... + } +--- + +$(P +$(IX delegate, foreach) If there is an $(C opApply()) member function that matches the loop variables, then the $(C foreach) block becomes a delegate, which is then passed to $(C opApply()). +) + +$(P +Accordingly, the loop above is converted to the following code behind the scenes. The curly brackets that define the body of the delegate are highlighted: +) + +--- +// The code that the compiler generates behind the scenes: + + myObject.opApply(delegate int(/* loop variables */) $(HILITE {) + // ... expressions inside the foreach block ... + return hasBeenTerminated; + $(HILITE })); +--- + +$(P +In other words, the $(C foreach) loop is replaced by a $(C delegate) that is passed to $(C opApply()). Before showing an example, here are the requirements and expectations of this convention that $(C opApply()) must observe: +) + +$(OL + +$(LI The body of the $(C foreach) loop becomes the body of the delegate. $(C opApply) must call this delegate for each iteration.) + +$(LI The loop variables become the parameters of the delegate. $(C opApply()) must define these parameters as $(C ref). (The variables may be defined without the $(C ref) keyword as well but doing that would prevent iterating over the elements $(LINK2 value_vs_reference.html, $(I by reference)).)) + +$(LI The return type of the delegate is $(C int). Accordingly, the compiler injects a $(C return) statement at the end of the delegate, which determines whether the loop has been terminated (by a $(C break) or a $(C return) statement): If the return value is zero, the iteration must continue, otherwise it must terminate.) + +$(LI The actual iteration happens inside $(C opApply()).) + +$(LI $(C opApply()) must return the same value that is returned by the delegate.) + +) + +$(P +The following is a definition of $(C NumberRange) that is implemented according to that convention: +) + +--- +struct NumberRange { + int begin; + int end; + // (2) (1) + int opApply(int delegate(ref int) operations) const { + int result = 0; + + for (int number = begin; number != end; ++number) { // (4) + result = operations(number); // (1) + + if (result) { + break; // (3) + } + } + + return result; // (5) + } +} +--- + +$(P +This definition of $(C NumberRange) can be used with $(C foreach) in exactly the same way as before: +) + +--- + foreach (element; NumberRange(3, 7)) { + write(element, ' '); + } +--- + +$(P +The output is the same as the one produced by range member functions: +) + +$(SHELL_SMALL +3 4 5 6 +) + +$(H6 Overloading $(C opApply) to iterate in different ways) + +$(P +It is possible to iterate over the same object in different ways by defining overloads of $(C opApply()) that take different types of delegates. The compiler calls the overload that matches the particular set of loop variables. +) + +$(P +As an example, let's make it possible to iterate over $(C NumberRange) by two loop variables as well: +) + +--- + foreach ($(HILITE first, second); NumberRange(0, 15)) { + writef("%s,%s ", first, second); + } +--- + +$(P +Note how it is similar to the way associative arrays are iterated over by both keys and values. +) + +$(P +For this example, let's require that when a $(C NumberRange) object is iterated by two variables, it should provide two consecutive values and that it arbitrarily increases the values by 5. So, the loop above should produce the following output: +) + +$(SHELL_SMALL +0,1 5,6 10,11 +) + +$(P +This is achieved by an additional definition of $(C opApply()) that takes a delegate that takes two parameters. $(C opApply()) must call that delegate with two values: +) + +--- + int opApply(int delegate$(HILITE (ref int, ref int)) dg) const { + int result = 0; + + for (int i = begin; (i + 1) < end; i += 5) { + int first = i; + int second = i + 1; + + result = dg($(HILITE first, second)); + + if (result) { + break; + } + } + + return result; + } +--- + +$(P +When there are two loop variables, this overload of $(C opApply()) gets called. +) + +$(P +There may be as many overloads of $(C opApply()) as needed. +) + +$(P +It is possible and sometimes necessary to give hints to the compiler on what overload to choose. This is done by specifying types of the loop variables explicitly. +) + +$(P +For example, let's assume that there is a $(C School) type that supports iterating over the teachers and the students separately: +) + +--- +class School { + int opApply(int delegate(ref $(HILITE Student)) dg) const { + // ... + } + + int opApply(int delegate(ref $(HILITE Teacher)) dg) const { + // ... + } +} +--- + +$(P +To indicate the desired overload, the loop variable must be specified: +) + +--- + foreach ($(HILITE Student) student; school) { + // ... + } + + foreach ($(HILITE Teacher) teacher; school) { + // ... + } +--- + +$(H5 $(IX loop counter) $(IX counter, loop) Loop counter) + +$(P +The convenient loop counter of slices is not automatic for other types. Loop counter can be achieved for user-defined types in different ways depending on whether the $(C foreach) support is provided by range member functions or by $(C opApply) overloads. +) + +$(H6 Loop counter with range functions) + +$(P +$(IX enumerate, std.range) If $(C foreach) support is provided by range member functions, then a loop counter can be achieved simply by $(C enumerate) from the $(C std.range) module: +) + +--- +import std.range; + +// ... + + foreach ($(HILITE i), element; NumberRange(42, 47)$(HILITE .enumerate)) { + writefln("%s: %s", i, element); + } +--- + +$(P +$(C enumerate) is a range that produces consecutive numbers starting by default from 0. $(C enumerate) pairs each number with the elements of the range that it is applied on. As a result, the numbers that $(C enumerate) generates and the elements of the actual range ($(C NumberRange) in this case) appear in lockstep as loop variables: +) + +$(SHELL_SMALL +0: 42 +1: 43 +2: 44 +3: 45 +4: 46 +) + +$(H6 Loop counter with $(C opApply)) + +$(P +On the other hand, if $(C foreach) support is provided by $(C opApply()), then the loop counter must be defined as a separate parameter of the delegate, suitably as type $(C size_t). Let's see this on a $(C struct) that represents a colored polygon. +) + +$(P +As we have already seen above, an $(C opApply()) that provides access to the points of this polygon can be implemented $(I without) a counter as in the following code: +) + +--- +import std.stdio; + +enum Color { blue, green, red } + +struct Point { + int x; + int y; +} + +struct Polygon { + Color color; + Point[] points; + + int $(HILITE opApply)(int delegate(ref const(Point)) dg) const { + int result = 0; + + foreach (point; points) { + result = dg(point); + + if (result) { + break; + } + } + + return result; + } +} + +void main() { + auto polygon = Polygon(Color.blue, + [ Point(0, 0), Point(1, 1) ] ); + + foreach (point; polygon) { + writeln(point); + } +} +--- + +$(P +Note that $(C opApply()) itself is implemented by a $(C foreach) loop. As a result, the $(C foreach) inside $(C main()) ends up making indirect use of a $(C foreach) over the $(C points) member. +) + +$(P +Also note that the type of the delegate parameter is $(C ref const(Point)). This means that this definition of $(C opApply()) does not allow modifying the $(C Point) elements of the polygon. In order to allow user code to modify the elements, both the $(C opApply()) function itself and the delegate parameter must be defined without the $(C const) specifier. +) + +$(P +The output: +) + +$(SHELL +const(Point)(0, 0) +const(Point)(1, 1) +) + +$(P +Naturally, trying to use this definition of $(C Polygon) with a loop counter would cause a compilation error: +) + +--- + foreach ($(HILITE i), point; polygon) { $(DERLEME_HATASI) + writefln("%s: %s", i, point); + } +--- + +$(P +The compilation error: +) + +$(SHELL +Error: cannot uniquely infer foreach argument types +) + +$(P +For that to work, another $(C opApply()) overload that supports a counter must be defined: +) + +--- + int opApply(int delegate($(HILITE ref size_t), + ref const(Point)) dg) const { + int result = 0; + + foreach ($(HILITE i), point; points) { + result = dg($(HILITE i), point); + + if (result) { + break; + } + } + + return result; + } +--- + +$(P +This time the $(C foreach) variables are matched to the new $(C opApply()) overload and the program prints the desired output: +) + +$(SHELL +0: const(Point)(0, 0) +1: const(Point)(1, 1) +) + +$(P +Note that this implementation of $(C opApply()) takes advantage of the automatic counter over the $(C points) member. ($(I Although the delegate variable is defined as $(C ref size_t), the $(C foreach) loop inside $(C main()) cannot modify the counter variable over $(C points))). +) + +$(P +When needed, the loop counter can be defined and incremented explicitly as well. For example, because the following $(C opApply()) is implemented by a $(C while) statement it must define a separate variable for the counter: +) + +--- + int opApply(int delegate(ref size_t, + ref const(Point)) dg) const { + int result = 0; + bool isDone = false; + + $(HILITE size_t counter = 0;) + while (!isDone) { + // ... + + result = dg(counter, nextElement); + + if (result) { + break; + } + + ++counter; + } + + return result; + } +--- + +$(H5 Warning: The collection must not mutate during the iteration) + +$(P +Regardless of whether the iteration support is provided by the range member functions or by $(C opApply()) functions, the collection itself must not mutate. New elements must not be added to the container and the existing elements must not be removed. (Mutating the existing elements is allowed.) +) + +$(P +Doing otherwise is undefined behavior. +) + +$(PROBLEM_COK + +$(PROBLEM +Design a $(C struct) that works similarly to $(C NumberRange), which also supports specifying the step size. The step size can be the third member: + +--- + foreach (element; NumberRange(0, 10, $(HILITE 2))) { + write(element, ' '); + } +--- + +$(P +The expected output of the code above is every second number from 0 to 10: +) + +$(SHELL_SMALL +0 2 4 6 8 +) + +) + +$(PROBLEM +Implement the $(C School) class that was mentioned in the text in a way that it provides access to students or teachers depending on the $(C foreach) variable. +) + +) + +Macros: + TITLE=Structs and Classes with foreach + + DESCRIPTION=Defining the way user-defined types behave with the foreach loop. + + KEYWORDS=d programming language tutorial book foreach opApply opApplyReverse diff --git a/book/d.en/foreword1.d b/book/d.en/foreword1.d new file mode 100644 index 0000000000..a5295d8611 --- /dev/null +++ b/book/d.en/foreword1.d @@ -0,0 +1,16 @@ +Ddoc + +$(DIV_CLASS foreword, + +$(DERS_BOLUMU_CLASS foreword, Foreword by Walter Bright) + +$(P +$(I by Walter Bright) +) + +) + +Macros: + TITLE= Foreword by Walter Bright + DESCRIPTION= + KEYWORDS= diff --git a/book/d.en/foreword2.d b/book/d.en/foreword2.d new file mode 100644 index 0000000000..1cd94dc8f8 --- /dev/null +++ b/book/d.en/foreword2.d @@ -0,0 +1,40 @@ +Ddoc + +$(DIV_CLASS foreword, + +$(DERS_BOLUMU_CLASS foreword, Foreword by Andrei Alexandrescu) + +$(P +Those of us who know Ali might notice his book on D is imbued with its author's personality: straightforward, patient, and nice without being pandering. +) + +$(P +There is purpose in every sentence, and with each, a step forward is being made; not too fast, and not too slow. "Note that $(C opApply()) itself is implemented by a $(C foreach) loop. As a result, the $(C foreach) inside $(C main()) ends up making indirect use of a $(C foreach) over the $(C points) member." And so it goes, in just as many words as needed. And in the right order, too; Ali does an admirable job at presenting language concepts – which especially to a beginner overwhelmingly come "in parallel" – in a sequential manner. +) + +$(P +But there's another thing I like most about "Programming in D": it's a good book for learning programming $(I in general). See, a good introductory book on Haskell implicitly teaches functional programming along the way; one on C would come with systems programming notions in tow; one on Python with scripting, and so on. What would, then, a good introductory text to D teach in subtext? At best, Programming with a capital P. +) + +$(P +D fosters a "use the right tool for the job" attitude, and allows its user to tap into a wide range of programming techniques, without throwing too many idiosyncrasies in the way. The most fun way to approach coding in D is with an open mind, because for each design that starts to get stilted there is opportunity to mold it into the right design choosing a different implementation, approach, or paradigm altogether. To best choose what's most fitting, the engineer must know the gamut of what's possible – and "Programming in D" is a great way to equip one's intellect with that knowledge. Internalizing it helps not only writing good code in D, but writing good code, period. +) + +$(P +There's good tactical advice, too, to complement the teaching of programming and language concepts. Timeless teaching on avoiding code duplication, choosing good names, aiming for good decomposition, and more – it's all there, quick-and-dirty hacks iteratively annealed into robust solutions, just as they should in normal practice. Instead of falling for getting things done quickly, "Programming in D" focuses on getting things done properly, to the lasting benefit of its reader. +) + +$(P +I've long suspected D is a good first programming language to learn. It exposes its user to a variety of concepts – systems, functional, object oriented, generic, generative – candidly and without pretense. And so does Ali's book, which seems to me an excellent realization of that opportunity. +$(BR) +$(BR) +Andrei Alexandrescu$(BR) +San Francisco, $(I May 2015) +) + +) + +Macros: + TITLE= Foreword by Andrei Alexandrescu + DESCRIPTION= + KEYWORDS= diff --git a/book/d.en/formatted_input.cozum.d b/book/d.en/formatted_input.cozum.d new file mode 100644 index 0000000000..fc883706a0 --- /dev/null +++ b/book/d.en/formatted_input.cozum.d @@ -0,0 +1,28 @@ +Ddoc + +$(COZUM_BOLUMU Formatted Input) + +$(P +Using a format string where the parts of the date are replaced with $(C %s) would be sufficient: +) + +--- +import std.stdio; + +void main() { + int year; + int month; + int day; + + readf("%s.%s.%s", &year, &month, &day); + + writeln("Month: ", month); +} +--- + +Macros: + TITLE=Formatted Input Solutions + + DESCRIPTION=Programming in D exercise solutions: Formatted input + + KEYWORDS=programming in d tutorial formatted input solution diff --git a/book/d.en/formatted_input.d b/book/d.en/formatted_input.d new file mode 100644 index 0000000000..843a0303af --- /dev/null +++ b/book/d.en/formatted_input.d @@ -0,0 +1,160 @@ +Ddoc + +$(DERS_BOLUMU $(IX input, formatted) $(IX formatted input) Formatted Input) + +$(P +It is possible to specify the format of the data that is expected at the input. The format specifies both the data that is to be read and the characters that should be ignored. +) + +$(P +D's input format specifiers are similar to the ones present in the C language. +) + +$(P +As we have already been using in the previous chapters, the format specifier $(STRING " %s") reads the data according to the type of the variable. For example, as the type of the following variable is $(C double), the characters at the input would be read as floating point number: +) + +--- + double number; + + readf(" %s", &number); +--- + +$(P +The format string can contain three types of information: +) + +$(UL +$(LI $(B The space character): Indicates $(I zero) or more whitespace characters at the input and specifies that all of those characters should be read and ignored.) + +$(LI $(B Format specifier): Similar to the output format specifiers, input format specifiers start with the $(C %) character and determine the format of the data that is to be read.) + +$(LI $(B Any other character): Indicates the characters that are expected at the input as is, which should be read and ignored.) + +) + +$(P +The format string makes it possible to select specific information from the input and ignore the others. +) + +$(P +Let's have a look at an example that uses all of the three types of information in the format string. Let's assume that the student number and the grade are expected to appear at the input in the following format: +) + +$(SHELL +number:123 grade:90 +) + +$(P +Let's further assume that the tags $(C number:) and $(C grade:) must be ignored. The following format string would $(I select) the values of number and grade and would ignore the other characters: +) + +--- + int number; + int grade; + readf("number:%s grade:%s", &number, &grade); +--- + +$(P +The characters that are highlighted in $(STRING "$(HILITE number:)%s $(HILITE grade:)%s") must appear at the input exactly as specified; $(C readf()) reads and ignores them. +) + +$(P +The single space character that appears in the format string above would cause all of the whitespace characters that appear exactly at that position to be read and ignored. +) + +$(P +As the $(C %) character has a special meaning in format strings, when that character itself needs to be read and ignored, it must be written twice in the format string as $(C %%). +) + +$(P +Reading a single line of data from the input has been recommended as $(C strip(readln())) in the $(LINK2 strings.html, Strings chapter). Instead of that method, a $(C \n) character at the end of the format string can achieve a similar goal: +) + +--- +import std.stdio; + +void main() { + write("First name: "); + string firstName; + readf(" %s\n", &firstName); // ← \n at the end + + write("Last name : "); + string lastName; + readf(" %s\n", &lastName); // ← \n at the end + + write("Age : "); + int age; + readf(" %s", &age); + + writefln("%s %s (%s)", firstName, lastName, age); +} +--- + +$(P +The $(C \n) characters at the ends of the format strings when reading $(C firstName) and $(C lastName) would cause the new-line characters to be read from the input and to be ignored. However, potential whitespace characters at the ends of the strings may still need to be removed by $(C strip()). +) + +$(H5 Format specifier characters) + +$(P +The way the data should be read is specified with the following format specifier characters: +) + +$(P $(IX %d, input) $(C d): Read an integer in the decimal system.) + +$(P $(IX %o, input) $(C o): Read an integer in the octal system.) + +$(P $(IX %x, input) $(C x): Read an integer in the hexadecimal system.) + +$(P $(IX %f, input) $(C f): Read a floating point number.) + +$(P $(IX %s, input) $(C s): Read according to the type of the variable. This is the most commonly used specifier.) + +$(P $(IX %c) $(C c): Read a single character. This specifier allows reading whitespace characters as well. (It cancels the ignore behavior.) +) + +$(P +For example, if the input contains "23 23 23", the values would be read differently according to different format specifiers: +) + +--- + int number_d; + int number_o; + int number_x; + + readf(" %d %o %x", &number_d, &number_o, &number_x); + + writeln("Read with %d: ", number_d); + writeln("Read with %o: ", number_o); + writeln("Read with %x: ", number_x); +--- + +$(P +Although the input contains three sets of "23" characters, the values of the variables are different: +) + +$(SHELL +Read with %d: 23 +Read with %o: 19 +Read with %x: 35 +) + +$(P +$(I $(B Note:) Very briefly, "23" is equal to 2x8+3=19 in the octal system and to 2x16+3=35 in the hexadecimal system.) +) + +$(PROBLEM_TEK + +$(P +Assume that the input contains the date in the format $(I year.month.day). Write a program that prints the number of the month. For example, if the input is $(C 2009.09.30), the output should be $(C 9). +) + +) + +Macros: + TITLE=Formatted Input + + DESCRIPTION=Reading the input in certain format. + + KEYWORDS=d programming language tutorial book format input diff --git a/book/d.en/formatted_output.cozum.d b/book/d.en/formatted_output.cozum.d new file mode 100644 index 0000000000..dff4381486 --- /dev/null +++ b/book/d.en/formatted_output.cozum.d @@ -0,0 +1,56 @@ +Ddoc + +$(COZUM_BOLUMU Formatted Output) + +$(OL + +$(LI We have already seen that this is trivial with format specifiers: + +--- +import std.stdio; + +void main() { + writeln("(Enter 0 to exit the program.)"); + + while (true) { + write("Please enter a number: "); + long number; + readf(" %s", &number); + + if (number == 0) { + break; + } + + writefln("%1$d <=> %1$#x", number); + } +} +--- + +) + +$(LI +Remembering that the $(C %) character must appear twice in the format string to be printed as itself: + +--- +import std.stdio; + +void main() { + write("Please enter the percentage value: "); + double percentage; + readf(" %s", &percentage); + + writefln("%%%.2f", percentage); +} +--- + +) + +) + + +Macros: + TITLE=Formatted Output Solutions + + DESCRIPTION=Programming in D exercise solutions: Formatted output + + KEYWORDS=programming in d tutorial formatted output solution diff --git a/book/d.en/formatted_output.d b/book/d.en/formatted_output.d new file mode 100644 index 0000000000..e9b22f5ed9 --- /dev/null +++ b/book/d.en/formatted_output.d @@ -0,0 +1,705 @@ +Ddoc + +$(DERS_BOLUMU $(IX output, formatted) $(IX formatted output) Formatted Output) + +$(P +This chapter is about features of the $(C std.format) module, not about the core features of the D language. +) + +$(P +$(IX std) $(IX Phobos) Like all modules that have the prefix $(C std), $(C std.format) is a module inside Phobos, the standard library of D. There is not enough space to fully explore Phobos in this book. +) + +$(P +D's input and output format specifiers are similar to the ones in the C language. +) + +$(P +Before going further, I would like to summarize the format specifiers and flags, for your reference: +) + +$(MONO +$(B Flags) (can be used together) + - flush left + + print the sign + # print in the alternative way + 0 print zero-filled + $(I space) print space-filled + +$(B Format Specifiers) + s default + b binary + d decimal + o octal + x,X hexadecimal + f,F floating point in the standard decimal notation + e,E floating point in scientific notation + a,A floating point in hexadecimal notation + g,G as e or f + + , digit separators + + ( element format start + ) element format end + | element delimiter +) + +$(P +We have been using functions like $(C writeln) with multiple parameters as necessary to print the desired output. The parameters would be converted to their string representations and then + sent to the output. +) + +$(P +Sometimes this is not sufficient. The output may have to be in a very specific format. Let's look at the following code that is used to print items of an invoice: +) + +--- + items ~= 1.23; + items ~= 45.6; + + for (int i = 0; i != items.length; ++i) { + writeln("Item ", i + 1, ": ", items[i]); + } +--- + +$(P +The output: +) + +$(SHELL +Item 1: 1.23 +Item 2: 45.6 +) + +$(P +Despite the information being correct, we may be required to print it in a different format. For example, maybe the decimal marks (the dots, in this case) must line up and we must ensure that there always are two digits after the decimal mark, as in the following output: +) + +$(SHELL +Item 1: 1.23 +Item 2: 45.60 +) + +$(P +Formatted output is useful in such cases. The output functions that we have been using so far have counterparts that contain the letter $(C f) in their names: $(C writef()) and $(C writefln()). The letter $(C f) is short for $(I formatted). The first parameter of these functions is a $(I format string) that describes how the other parameters should be printed. +) + +$(P +For example, $(C writefln()) can produce the desired output above with the following format string: +) + +--- + writefln("Item %d:%9.02f", i + 1, items[i]); +--- + +$(P +The format string contains regular characters that are passed to the output as is, as well as special format specifiers that correspond to each parameter that is to be printed. Format specifiers start with the $(C %) character and end with a $(I format character). The format string above has two format specifiers: $(C %d) and $(C %9.02f). +) + +$(P +Every specifier is associated with the respective parameter, usually in order of appearance. For example, $(C %d) is associated with $(C i + 1) and $(C %9.02f) is associated with $(C items[i]). Every specifier specifies the format of the parameter that it corresponds to. (Format specifiers may have parameter numbers as well. This will be explained later in the chapter.) +) + +$(P +All of the other characters of the format string that are not part of format specifiers are printed as is. Such $(I regular) characters of the format specifier above are highlighted in $(C "$(HILITE Item )%d$(HILITE :)%9.02f"). +) + +$(P +Format specifiers consist of several parts, most of which are optional. The part named $(I position) will be explained later below. The others are the following: ($(I $(B Note:) The spaces between these parts are inserted here to help with readability; they are not part of the specifiers.)) +) + +$(MONO + % $(I$(C flags width separator precision format_character)) +) + +$(P +The $(C %) character at the beginning and the format character at the end are required; the others are optional. +) + +$(P +Because $(C %) has a special meaning in format strings, when we need to print a $(C %) as a regular character, we must type it as $(C %%). +) + +$(H5 $(I format_character)) + +$(P $(IX %b) $(C b): An integer argument is printed in the binary system. +) + +$(P $(IX %o, output) $(C o): An integer argument is printed in the octal system. +) + +$(P $(IX %x, output) $(IX %X) $(C x) and $(C X): An integer argument is printed in the hexadecimal system; with lowercase letters when using $(C x) and with uppercase letters when using $(C X). +) + +$(P $(IX %d, output) $(C d): An integer argument is printed in the decimal system; a negative sign is also printed if it is a signed type and the value is less than zero. +) + +--- + int value = 12; + + writefln("Binary : %b", value); + writefln("Octal : %o", value); + writefln("Hexadecimal: %x", value); + writefln("Decimal : %d", value); +--- + +$(SHELL +Binary : 1100 +Octal : 14 +Hexadecimal: c +Decimal : 12 +) + +$(P $(IX %e) $(C e): A floating point argument is printed according to the following rules. +) + +$(UL +$(LI a single digit before the decimal mark) +$(LI a decimal mark if $(I precision) is nonzero) +$(LI the required digits after the decimal mark, the number of which is determined by $(I precision) (default precision is 6)) +$(LI the $(C e) character (meaning "10 to the power of")) +$(LI the $(C -) or $(C +) character, depending on whether the exponent is less than or greater than zero) +$(LI the exponent, consisting of at least two digits) +) + +$(P $(IX %E) $(C E): Same as $(C e), with the exception of outputting the character $(C E) instead of $(C e). +) + +$(P $(IX %f, output) $(IX %F) $(C f) and $(C F): A floating point argument is printed in the decimal system; there is at least one digit before the decimal mark and the default precision is 6 digits after the decimal mark. +) + +$(P $(IX %g) $(C g): Same as $(C f) if the exponent is between -5 and $(I precision); otherwise same as $(C e). $(I precision) does not specify the number of digits after the decimal mark, but the significant digits of the entire value. If there are no significant digits after the decimal mark, then the decimal mark is not printed. The rightmost zeros after the decimal mark are not printed. +) + +$(P $(IX %G) $(C G): Same as $(C g), with the exception of outputting the character $(C E). +) + +$(P $(IX %a) $(C a): A floating point argument is printed in the hexadecimal floating point notation: +) + +$(UL +$(LI the characters $(C 0x)) +$(LI a single hexadecimal digit) +$(LI a decimal mark if $(I precision) is nonzero) +$(LI the required digits after the decimal mark, the number of which is determined by $(I precision); if no $(I precision) is specified, then as many digits as necessary) +$(LI the $(C p) character (meaning "2 to the power of")) +$(LI the $(C -) or $(C +) character, depending on whether the exponent is less than or greater than zero) +$(LI the exponent, consisting of at least one digit (the exponent of the value 0 is 0)) +) + +$(P $(IX %A) $(C A): Same as $(C a), with the exception of outputting the characters $(C 0X) and $(C P). +) + +--- + double value = 123.456789; + + writefln("with e: %e", value); + writefln("with f: %f", value); + writefln("with g: %g", value); + writefln("with a: %a", value); +--- + +$(SHELL +with e: 1.234568e+02 +with f: 123.456789 +with g: 123.457 +with a: 0x1.edd3c07ee0b0bp+6 +) + +$(P $(IX %s, output) $(C s): The value is printed in the same way as in regular output, according to the type of the argument: +) + +$(UL + +$(LI $(C bool) values as $(C true) or $(C false) +) +$(LI integer values same as $(C %d) +) +$(LI floating point values same as $(C %g) +) +$(LI strings in UTF-8 encoding; $(I precision) determines the maximum number of bytes to use (remember that in UTF-8 encoding, the number of bytes is not the same as the number of characters; for example, the string "ağ" has 2 characters, consisting a total of 3 bytes) +) +$(LI struct and class objects as the return value of the $(C toString()) member functions of their types; $(I precision) determines the maximum number of bytes to use +) +$(LI arrays as their element values, side by side +) + +) + +--- + bool b = true; + int i = 365; + double d = 9.87; + string s = "formatted"; + auto o = File("test_file", "r"); + int[] a = [ 2, 4, 6, 8 ]; + + writefln("bool : %s", b); + writefln("int : %s", i); + writefln("double: %s", d); + writefln("string: %s", s); + writefln("object: %s", o); + writefln("array : %s", a); +--- + +$(SHELL +bool : true +int : 365 +double: 9.87 +string: formatted +object: File(55738FA0) +array : [2, 4, 6, 8] +) + +$(H5 $(IX width, output) $(I width)) + +$(P +$(IX *, formatted output) This part determines the width of the field that the argument is printed in. If the width is specified as the character $(C *), then the actual width value is read from the next argument (that argument must be an $(C int)). If width is a negative value, then the $(C -) flag is assumed. +) + +--- + int value = 100; + + writefln("In a field of 10 characters:%10s", value); + writefln("In a field of 5 characters :%5s", value); +--- + +$(SHELL +In a field of 10 characters: 100 +In a field of 5 characters : 100 +) + +$(H5 $(IX $(PERCENT),) $(IX separator) $(I separator)) + +$(P +$(IX , (comma), output) The comma character specifies to separate digits of a number in groups. The default number of digits in a group is 3 but it can be specified after the comma: +) + +--- + writefln("%,f", 1234.5678); // Groups of 3 + writefln("%,s", 1000000); // Groups of 3 + writefln("%,2s", 1000000); // Groups of 2 +--- + +$(SHELL +1,234.567,800 +1,000,000 +1,00,00,00 +) + +$(P +If the number of digits is specified as the character $(C *), then the actual number of digits is read from the next argument (that argument must be an $(C int)). +) + +--- + writefln("%,*s", $(HILITE 1), 1000000); // Groups of 1 +--- + +$(SHELL +1,0,0,0,0,0,0 +) + +$(P +Similarly, it is possible to specify the separator character by using a question mark after the comma and providing the character as an additional argument before the number: +) + +--- + writefln("%,?s", $(HILITE '.'), 1000000); // The separator is '.' +--- + +$(SHELL +1$(HILITE .)000$(HILITE .)000 +) + +$(H5 $(IX precision, output) $(I precision)) + +$(P +Precision is specified after a dot in the format specifier. For floating point types, it determines the precision of the printed representation of the values. If the precision is specified as the character $(C *), then the actual precision is read from the next argument (that argument must be an $(C int)). Negative precision values are ignored. +) + +--- + double value = 1234.56789; + + writefln("%.8g", value); + writefln("%.3g", value); + writefln("%.8f", value); + writefln("%.3f", value); +--- + +$(SHELL +1234.5679 +1.23e+03 +1234.56789000 +1234.568 +) + +--- + auto number = 0.123456789; + writefln("Number: %.*g", 4, number); +--- + +$(SHELL +Number: 0.1235 +) + +$(H5 $(IX flags, output) $(I flags)) + +$(P +More than one flag can be specified. +) + +$(P $(C -): the value is printed left-aligned in its field; this flag cancels the $(C 0) flag +) + +--- + int value = 123; + + writefln("Normally right-aligned:|%10d|", value); + writefln("Left-aligned :|%-10d|", value); +--- + +$(SHELL +Normally right-aligned:| 123| +Left-aligned :|123 | +) + +$(P $(C +): if the value is positive, it is prepended with the $(C +) character; this flag cancels the $(I space) flag +) + +--- + writefln("No effect for negative values : %+d", -50); + writefln("Positive value with the + flag : %+d", 50); + writefln("Positive value without the + flag: %d", 50); +--- + +$(SHELL +No effect for negative values : -50 +Positive value with the + flag : +50 +Positive value without the + flag: 50 +) + +$(P $(C #): prints the value in an $(I alternate) form depending on the $(I format_character) +) + +$(UL +$(LI $(C o): the first character of the octal value is always printed as 0) + +$(LI $(C x) and $(C X): if the value is not zero, it is prepended with $(C 0x) or $(C 0X)) + +$(LI floating points: a decimal mark is printed even if there are no significant digits after the decimal mark) + +$(LI $(C g) and $(C G): even the insignificant zero digits after the decimal mark are printed) +) + +--- + writefln("Octal starts with 0 : %#o", 1000); + writefln("Hexadecimal starts with 0x : %#x", 1000); + writefln("Contains decimal mark even when unnecessary: %#g", 1f); + writefln("Rightmost zeros are printed : %#g", 1.2); +--- + +$(SHELL +Octal starts with 0 : 01750 +Hexadecimal starts with 0x : 0x3e8 +Contains decimal mark even when unnecessary: 1.00000 +Rightmost zeros are printed : 1.20000 +) + +$(P $(C 0): the field is padded with zeros (unless the value is $(C nan) or $(C infinity)); if $(I precision) is also specified, this flag is ignored +) + +--- + writefln("In a field of 8 characters: %08d", 42); +--- + +$(SHELL +In a field of 8 characters: 00000042 +) + +$(P $(I space) character: if the value is positive, a space character is prepended to align the negative and positive values) + +--- + writefln("No effect for negative values: % d", -34); + writefln("Positive value with space : % d", 56); + writefln("Positive value without space : %d", 56); +--- + +$(SHELL +No effect for negative values: -34 +Positive value with space : 56 +Positive value without space : 56 +) + + +$(H5 $(IX %1$) $(IX positional parameter, output) $(IX $, formatted output) Positional parameters) + +$(P +We have seen above that the arguments are associated one by one with the specifiers in the format string. It is also possible to use position numbers within format specifiers. This enables associating the specifiers with specific arguments. Arguments are numbered in increasing fashion, starting with 1. The argument numbers are specified immediately after the $(C %) character, followed by a $(C $): +) + +$(MONO + % $(I$(C $(HILITE position$) flags width precision format_character)) +) + +$(P +An advantage of positional parameters is being able to use the same argument in more than one place in the same format string: +) + +--- + writefln("%1$d %1$x %1$o %1$b", 42); +--- + +$(P +The format string above uses the argument numbered 1 within four specifiers to print it in decimal, hexadecimal, octal, and binary formats: +) + +$(SHELL +42 2a 52 101010 +) + +$(P +Another application of positional parameters is supporting multiple natural languages. When referred by position numbers, arguments can be moved anywhere within the specific format string for a given human language. For example, the number of students of a given classroom can be printed as in the following: +) + +--- + writefln("There are %s students in room %s.", count, room); +--- + +$(SHELL +There are 20 students in room 1A. +) + +$(P +Let's assume that the program must also support Turkish. In this case the format string needs to be selected according to the active language. The following method takes advantage of the ternary operator: +) + +--- + auto format = (language == "en" + ? "There are %s students in room %s." + : "%s sınıfında %s öğrenci var."); + + writefln(format, count, room); +--- + +$(P +Unfortunately, when the arguments are associated one by one, the classroom and student count information appear in reverse order in the Turkish message; the room information is where the count should be and the count is where the room should be: +) + +$(SHELL +20 sınıfında 1A öğrenci var. $(SHELL_NOTE_WRONG Wrong: means "room 20", and "1A students"!) +) + +$(P +To avoid this, the arguments can be specified by numbers, such as $(C 1$) and $(C 2$), to associate each specifier with the exact argument: +) + +--- + auto format = (language == "en" + ? "There are %1$s students in room %2$s." + : "%2$s sınıfında %1$s öğrenci var."); + + writefln(format, count, room); +--- + +$(P +Now the arguments appear in the proper order, regardless of the language selected: +) + +$(SHELL +There are 20 students in room 1A. +) + +$(SHELL +1A sınıfında 20 öğrenci var. +) + +$(H5 $(IX %$(PARANTEZ_AC)) $(IX %$(PARANTEZ_KAPA)) Formatted element output) + +$(P +Format specifiers between $(STRING %$(PARANTEZ_AC)) and $(STRING %$(PARANTEZ_KAPA)) are applied to every element of a container (e.g. an array or a range): +) + +--- + auto numbers = [ 1, 2, 3, 4 ]; + writefln("%(%s%)", numbers); +--- + +$(P +The format string above consists of three parts: +) + +$(UL +$(LI $(STRING %$(PARANTEZ_AC)): Start of element format) +$(LI $(STRING %s): Format for each element) +$(LI $(STRING %$(PARANTEZ_KAPA)): End of element format) +) + +$(P +Each being printed with the $(STRING %s) format, the elements appear one after the other: +) + +$(SHELL +1234 +) + +$(P +The regular characters before and after the element format are repeated for each element. For example, the $(STRING {%s},) specifier would print each element between curly brackets separated by commas: +) + +--- + writefln("%({%s},%)", numbers); +--- + +$(P +However, regular characters to the right of the format specifier are considered to be element delimiters and are printed only between elements, not after the last one: +) + +$(SHELL +{1},{2},{3},{4 $(SHELL_NOTE '}' and ',' are not printed after the last element) +) + +$(P +$(IX %|) $(STRING %|) is used for specifying the characters that should be printed even for the last element. Characters that are to the right of $(STRING %|) are considered to be the delimiters and are not printed for the last element. Conversely, characters to the left of $(STRING %|) are printed even for the last element. +) + +$(P +For example, the following format specifier would print the closing curly bracket after the last element but not the comma: +) +--- + writefln("%({%s}%|,%)", numbers); +--- + +$(SHELL +{1},{2},{3},{4} $(SHELL_NOTE '}' is printed after the last element as well) +) + +$(P +Unlike strings that are printed individually, strings that are printed as elements appear within double quotes: +) + +--- + auto vegetables = [ "spinach", "asparagus", "artichoke" ]; + writefln("%(%s, %)", vegetables); +--- + +$(SHELL +"spinach", "asparagus", "artichoke" +) + +$(P +$(IX %-$(PARANTEZ_AC)) When the double quotes are not desired, the element format must be started with $(STRING %-$(PARANTEZ_AC)) instead of $(STRING %$(PARANTEZ_AC)): +) + +--- + writefln("%-(%s, %)", vegetables); +--- + +$(SHELL +spinach, asparagus, artichoke +) + +$(P +The same applies to characters as well. $(STRING %$(PARANTEZ_AC)) prints them within single quotes: +) + +--- + writefln("%(%s%)", "hello"); +--- + +$(SHELL +'h''e''l''l''o' +) + +$(P +$(STRING %-$(PARANTEZ_AC)) prints them without quotes: +) + +--- + writefln("%-(%s%)", "hello"); +--- + +$(SHELL +hello +) + +$(P +There must be two format specifiers for associative arrays: one for the keys and one for the values. For example, the following $(STRING %s (%s)) specifier would print first the key and then the value in parentheses: +) + +--- + auto spelled = [ 1 : "one", 10 : "ten", 100 : "hundred" ]; + writefln("%-(%s (%s)%|, %)", spelled); +--- + +$(P +Also note that, being specified to the right of $(STRING %|), the comma is not printed for the last element: +) + +$(SHELL +1 (one), 100 (hundred), 10 (ten) +) + +$(H5 $(IX format, std.string) $(C format)) + +$(P +Formatted output is available through the $(C format()) function of the $(C std.string) module as well. $(C format()) works the same as $(C writef()) but it $(I returns) the result as a $(C string) instead of printing it to the output: +) + +--- +import std.stdio; +import std.string; + +void main() { + write("What is your name? "); + auto name = strip(readln()); + + auto result = $(HILITE format)("Hello %s!", name); +} +--- + +$(P +The program can make use of that result in later expressions. +) + +$(H6 $(IX checked format string) Checked format string) + +$(P +There is an alternative syntax for functions like $(C format) in the standard library that take a format string ($(C writef), $(C writefln), $(C formattedWrite), $(C readf), $(C formattedRead), etc.). It is possible to provide the format string as a $(I template argument) to these functions so that the validity of the format string and the arguments are checked at compile time: +) + +--- +import std.stdio; + +void main() { + writefln!"%s %s"(1); $(DERLEME_HATASI) (extra %s) + writefln!"%s"(1, 2); $(DERLEME_HATASI) (extra 2) + writefln!"%s %d"(1, 2.5); $(DERLEME_HATASI) (mismatched %d and 2.5) +} +--- + +$(P +The $(C !) character above is the template instantiation operator, which we will see in $(LINK2 templates.html, a later chapter). +) + +$(P +($(I $(B Note:) Although this snytax is safer because it catches potential programmer errors at compile time, it may also make compilation times longer.)) +) + +$(PROBLEM_COK + +$(PROBLEM +Write a program that reads a value and prints it in the hexadecimal system. +) + +$(PROBLEM +Write a program that reads a floating point value and prints it as percentage value with two digits after the decimal mark. For example, if the value is 1.2345, it should print $(C %1.23). +) + +) + +Macros: + TITLE=Formatted Output + + DESCRIPTION=Printing values in certain formats. + + KEYWORDS=d programming language tutorial book format output diff --git a/book/d.en/frontispiece.d b/book/d.en/frontispiece.d new file mode 100644 index 0000000000..27f5200742 --- /dev/null +++ b/book/d.en/frontispiece.d @@ -0,0 +1,9 @@ +Ddoc + +
    + +
    + +
    + +
    diff --git a/book/d.en/function_overloading.cozum.d b/book/d.en/function_overloading.cozum.d new file mode 100644 index 0000000000..b20deff9db --- /dev/null +++ b/book/d.en/function_overloading.cozum.d @@ -0,0 +1,147 @@ +Ddoc + +$(COZUM_BOLUMU Function Overloading) + +$(P +The following two overloads take advantage of the existing $(C info()) overloads: +) + +--- +void info(Meal meal) { + info(meal.time); + write('-'); + info(addDuration(meal.time, TimeOfDay(1, 30))); + + write(" Meal, Address: ", meal.address); +} + +void info(DailyPlan plan) { + info(plan.amMeeting); + writeln(); + info(plan.lunch); + writeln(); + info(plan.pmMeeting); +} +--- + +$(P +Here is the entire program that uses all of these types: +) + +--- +import std.stdio; + +struct TimeOfDay { + int hour; + int minute; +} + +void info(TimeOfDay time) { + writef("%02s:%02s", time.hour, time.minute); +} + +TimeOfDay addDuration(TimeOfDay start, + TimeOfDay duration) { + TimeOfDay result; + + result.minute = start.minute + duration.minute; + result.hour = start.hour + duration.hour; + result.hour += result.minute / 60; + + result.minute %= 60; + result.hour %= 24; + + return result; +} + +struct Meeting { + string topic; + size_t attendanceCount; + TimeOfDay start; + TimeOfDay end; +} + +void info(Meeting meeting) { + info(meeting.start); + write('-'); + info(meeting.end); + + writef(" \"%s\" meeting with %s attendees", + meeting.topic, + meeting.attendanceCount); +} + +struct Meal { + TimeOfDay time; + string address; +} + +void info(Meal meal) { + info(meal.time); + write('-'); + info(addDuration(meal.time, TimeOfDay(1, 30))); + + write(" Meal, Address: ", meal.address); +} + +struct DailyPlan { + Meeting amMeeting; + Meal lunch; + Meeting pmMeeting; +} + +void info(DailyPlan plan) { + info(plan.amMeeting); + writeln(); + info(plan.lunch); + writeln(); + info(plan.pmMeeting); +} + +void main() { + immutable bikeRideMeeting = Meeting("Bike Ride", 4, + TimeOfDay(10, 30), + TimeOfDay(11, 45)); + + immutable lunch = Meal(TimeOfDay(12, 30), "İstanbul"); + + immutable budgetMeeting = Meeting("Budget", 8, + TimeOfDay(15, 30), + TimeOfDay(17, 30)); + + immutable todaysPlan = DailyPlan(bikeRideMeeting, + lunch, + budgetMeeting); + + info(todaysPlan); + writeln(); +} +--- + +$(P +That $(C main()) function can also be written with only object literals: +) + +--- +void $(CODE_DONT_TEST)main() { + info(DailyPlan(Meeting("Bike Ride", 4, + TimeOfDay(10, 30), + TimeOfDay(11, 45)), + + Meal(TimeOfDay(12, 30), "İstanbul"), + + Meeting("Budget", 8, + TimeOfDay(15, 30), + TimeOfDay(17, 30)))); + + writeln(); +} +--- + + +Macros: + TITLE=Function Overloading + + DESCRIPTION=Programming in D exercise solutions: Function Overloading + + KEYWORDS=d programming book tutorial function overloading exercise solutions diff --git a/book/d.en/function_overloading.d b/book/d.en/function_overloading.d new file mode 100644 index 0000000000..eaa94e3887 --- /dev/null +++ b/book/d.en/function_overloading.d @@ -0,0 +1,294 @@ +Ddoc + +$(DERS_BOLUMU $(IX function overloading) $(IX overloading, function) Function Overloading) + +$(P +Defining more than one function having the same name is $(I function overloading). In order to be able to differentiate these functions, their parameters must be different. +) + +$(P +The following code has multiple overloads of the $(C info()) function, each taking a different type of parameter: +) + +--- +import std.stdio; + +void info($(HILITE double) number) { + writeln("Floating point: ", number); +} + +void info($(HILITE int) number) { + writeln("Integer : ", number); +} + +void info($(HILITE string) str) { + writeln("String : ", str); +} + +void main() { + info(1.2); + info(3); + info("hello"); +} +--- + +$(P +Although all of the functions are named $(C info()), the compiler picks the one that matches the argument that is used when making the call. For example, because the literal $(C 1.2) is of type $(C double), the $(C info()) function that takes a $(C double) gets called for it. +) + +$(P +The choice of which function to call is made at compile time, which may not always be easy or clear. For example, because $(C int) can implicitly be converted to both $(C double) and $(C real), the compiler cannot decide which of the functions to call in the following program: +) + +--- +real sevenTimes(real value) { + return 7 * value; +} + +double sevenTimes(double value) { + return 7 * value; +} + +void main() { + int value = 5; + auto result = sevenTimes(value); $(DERLEME_HATASI) +} +--- + +$(P +$(I $(B Note:) It is usually unnecessary to write separate functions when the function bodies are exactly the same. We will see later in the $(LINK2 templates.html, Templates chapter) how a single definition can be used for multiple types.) +) + +$(P +However, if there is another function overload that takes a $(C long) parameter, then the ambiguity would be resolved because $(C long) is a $(I better match) for $(C int) than $(C double) or $(C real): +) + +--- +long sevenTimes(long value) { + return 7 * value; +} + +// ... + + auto result = sevenTimes(value); // now compiles +--- + +$(H5 Overload resolution) + +$(P +The compiler picks the overload that is the $(I best match) for the arguments. This is called overload resolution. +) + +$(P +Although overload resolution is simple and intuitive in most cases, it is sometimes complicated. The following are the rules of overload resolution. They are being presented in a simplified way in this book. +) + +$(P +There are four states of match, listed from the worst to the best: +) + +$(UL +$(LI mismatch) +$(LI match through automatic type conversion) +$(LI match through $(C const) qualification) +$(LI exact match) +) + +$(P +The compiler considers all of the overloads of a function during overload resolution. It first determines the match state of every parameter for every overload. For each overload, the least match state among the parameters is taken to be the match state of that overload. +) + +$(P +After all of the match states of the overloads are determined, then the overload with the best match is selected. If there are more than one overload that has the best match, then more complicated resolution rules are applied. I will not get into more details of these rules in this book. If your program is in a situation where it depends on complicated overload resolution rules, it may be an indication that it is time to change the design of the program. Another option is to take advantage of other features of D, like templates. An even simpler but not always desirable approach would be to abandon function overloading altogether by naming functions differently for each type e.g. like $(C sevenTimes_real()) and $(C sevenTimes_double()). +) + +$(H5 Function overloading for user-defined types) + +$(P +Function overloading is useful with structs and classes as well. Additionally, overload resolution ambiguities are much less frequent with user-defined types. Let's overload the $(C info()) function above for some of the types that we have defined in the $(LINK2 struct.html, Structs chapter): +) + +--- +struct TimeOfDay { + int hour; + int minute; +} + +void info(TimeOfDay time) { + writef("%02s:%02s", time.hour, time.minute); +} +--- + +$(P +That overload enables $(C TimeOfDay) objects to be used with $(C info()). As a result, variables of user-defined types can be printed in exactly the same way as fundamental types: +) + +--- + auto breakfastTime = TimeOfDay(7, 0); + info(breakfastTime); +--- + +$(P +The $(C TimeOfDay) objects would be matched with that overload of $(C info()): +) + +$(SHELL +07:00 +) + +$(P +The following is an overload of $(C info()) for the $(C Meeting) type: +) + +--- +struct Meeting { + string topic; + size_t attendanceCount; + TimeOfDay start; + TimeOfDay end; +} + +void info(Meeting meeting) { + info(meeting.start); + write('-'); + info(meeting.end); + + writef(" \"%s\" meeting with %s attendees", + meeting.topic, + meeting.attendanceCount); +} +--- + +$(P +Note that this overload makes use of the already-defined overload for $(C TimeOfDay). $(C Meeting) objects can now be printed in exactly the same way as fundamental types as well: +) + +--- + auto bikeRideMeeting = Meeting("Bike Ride", 3, + TimeOfDay(9, 0), + TimeOfDay(9, 10)); + info(bikeRideMeeting); +--- + +$(P +The output: +) + +$(SHELL +09:00-09:10 "Bike Ride" meeting with 3 attendees +) + +$(H5 Limitations) + +$(P +Although the $(C info()) function overloads above are a great convenience, this method has some limitations: +) + +$(UL + +$(LI +$(C info()) always prints to $(C stdout). It would be more useful if it could print to any $(C File). One way of achieving this is to pass the output stream as a parameter as well e.g. for the $(C TimeOfDay) type: + +--- +void info(File file, TimeOfDay time) { + file.writef("%02s:%02s", time.hour, time.minute); +} +--- + +$(P +That would enable printing $(C TimeOfDay) objects to any file, including $(C stdout): +) + +--- + info($(HILITE stdout), breakfastTime); + + auto file = File("a_file", "w"); + info($(HILITE file), breakfastTime); +--- + +$(P +$(I $(B Note:) The special objects $(C stdin), $(C stdout), and $(C stderr) are of type $(C File).) +) + +) + +$(LI +More importantly, $(C info()) does not solve the more general problem of producing the string representation of variables. For example, it does not help with passing objects of user-defined types to $(C writeln()): + +--- + writeln(breakfastTime); // Not useful: prints in generic format +--- + +$(P +The code above prints the object in a generic format that includes the name of the type and the values of its members, not in a way that would be useful in the program: +) + +$(SHELL +TimeOfDay(7, 0) +) + +$(P +It would be much more useful if there were a function that converted $(C TimeOfDay) objects to $(C string) in their special format as in $(STRING "12:34"). We will see how to define $(C string) representations of struct objects in the next chapter. +) + +) + +) + +$(PROBLEM_TEK + +$(P +Overload the $(C info()) function for the following structs as well: +) + +--- +struct Meal { + TimeOfDay time; + string address; +} + +struct DailyPlan { + Meeting amMeeting; + Meal lunch; + Meeting pmMeeting; +} +--- + +$(P +Since $(C Meal) has only the start time, add an hour and a half to determine its end time. You can use the $(C addDuration()) function that we have defined earlier in the structs chapter: +) + +--- +TimeOfDay addDuration(TimeOfDay start, + TimeOfDay duration) { + TimeOfDay result; + + result.minute = start.minute + duration.minute; + result.hour = start.hour + duration.hour; + result.hour += result.minute / 60; + + result.minute %= 60; + result.hour %= 24; + + return result; +} +--- + +$(P +Once the end times of $(C Meal) objects are calculated by $(C addDuration()), $(C DailyPlan) objects should be printed as in the following output: +) + +$(SHELL +10:30-11:45 "Bike Ride" meeting with 4 attendees +12:30-14:00 Meal, Address: İstanbul +15:30-17:30 "Budget" meeting with 8 attendees +) + +) + +Macros: + TITLE=Function Overloading + + DESCRIPTION=The function overloading feature of the D programming language, which increases the usability of functions by bringing uniformity through many types. + + KEYWORDS=d programming lesson book tutorial function overloading diff --git a/book/d.en/function_parameters.cozum.d b/book/d.en/function_parameters.cozum.d new file mode 100644 index 0000000000..ee65b02a5e --- /dev/null +++ b/book/d.en/function_parameters.cozum.d @@ -0,0 +1,38 @@ +Ddoc + +$(COZUM_BOLUMU Function Parameters) + +$(P +Because the parameters of this function are the kind that gets copied from the arguments, what gets swapped in the function are those copies. +) + +$(P +To make the function swap the arguments, both of the parameters must be passed by reference: +) + +--- +void swap($(HILITE ref) int first, $(HILITE ref) int second) { + const int temp = first; + first = second; + second = temp; +} +--- + +$(P +With that change, now the variables in $(C main()) would be swapped: +) + +$(SHELL +2 1 +) + +$(P +Although not related to the original problem, also note that $(C temp) is specified as $(C const) as it is not changed in the function. +) + +Macros: + TITLE=Function Parameters Solutions + + DESCRIPTION=Programming in D exercise solutions: Function Parameters + + KEYWORDS=programming in d tutorial function parameters diff --git a/book/d.en/function_parameters.d b/book/d.en/function_parameters.d new file mode 100644 index 0000000000..9db9db6716 --- /dev/null +++ b/book/d.en/function_parameters.d @@ -0,0 +1,988 @@ +Ddoc + +$(DERS_BOLUMU $(IX parameter) $(IX function parameter) Function Parameters) + +$(P +This chapter covers various kinds of function parameters. +) + +$(P +Some of the concepts of this chapter have already appeared earlier in the book. For example, the $(C ref) keyword that we saw in the $(LINK2 foreach.html, $(C foreach) Loop chapter) was making $(I actual elements) available in $(C foreach) loops as opposed to $(I copies) of those elements. +) + +$(P +Additionally, we covered the $(C const) and $(C immutable) keywords and the differences between value types and reference types in previous chapters. +) + +$(P +We have written functions that produced results by making use of their parameters. For example, the following function uses its parameters in a calculation: +) + +--- +double weightedAverage(double quizGrade, double finalGrade) { + return quizGrade * 0.4 + finalGrade * 0.6; +} +--- + +$(P +That function calculates the average grade by taking 40% of the quiz grade and 60% of the final grade. Here is how it may be used: +) + +--- + int quizGrade = 76; + int finalGrade = 80; + + writefln("Weighted average: %2.0f", + weightedAverage(quizGrade, finalGrade)); +--- + +$(H5 $(IX pass-by copy) $(IX copy, parameter) Parameters are always copied) + +$(P +In the code above, the two variables are passed as arguments to $(C weightedAverage()). The function $(I uses) its parameters. This fact may give the false impression that the function uses the actual variables that have been passed as arguments. In reality, what the function uses are $(I copies) of those variables. +) + +$(P +This distinction is important because modifying a parameter changes only the copy. This can be seen in the following function that is trying to modify its parameter (i.e. making a side effect). Let's assume that the following function is written for reducing the energy of a game character: +) + +--- +void reduceEnergy(double energy) { + energy /= 4; +} +--- + +$(P +Here is a program that tests $(C reduceEnergy()): +) + +--- +import std.stdio; + +void reduceEnergy(double energy) { + energy /= 4; +} + +void main() { + double energy = 100; + + reduceEnergy(energy); + writeln("New energy: ", energy); +} +--- + +$(P +The output: +) + +$(SHELL +New energy: 100 $(SHELL_NOTE_WRONG Not changed) +) + +$(P +Although $(C reduceEnergy()) drops the value of its parameter to a quarter of its original value, the variable $(C energy) in $(C main()) does not change. The reason for this is that the $(C energy) variable in $(C main()) and the $(C energy) parameter of $(C reduceEnergy()) are separate; the parameter is a copy of the variable in $(C main()). +) + +$(P +To observe this more closely, let's insert some $(C writeln()) expressions: +) + +--- +import std.stdio; + +void reduceEnergy(double energy) { + writeln("Entered the function : ", energy); + energy /= 4; + writeln("Leaving the function : ", energy); +} + +void main() { + double energy = 100; + + writeln("Calling the function : ", energy); + reduceEnergy(energy); + writeln("Returned from the function: ", energy); +} +--- + +$(P +The output: +) + +$(SHELL +Calling the function : 100 +Entered the function : 100 +Leaving the function : 25 $(SHELL_NOTE the parameter changes,) +Returned from the function: 100 $(SHELL_NOTE the variable remains the same) +) + +$(H5 $(IX pass-by reference) Referenced variables are not copied) + +$(P +Even parameters of reference types like slices, associative arrays, and class variables are copied to functions. However, the original variables that are referenced (i.e. elements of slices and associative arrays, and class objects) are not copied. Effectively, such variables are passed to functions as $(I references): the parameter becomes another reference to the original object. It means that a modification made through the reference modifies the original object as well. +) + +$(P +Being slices of characters, this applies to strings as well: +) + +--- +import std.stdio; + +void makeFirstLetterDot(dchar[] str) { + str[0] = '.'; +} + +void main() { + dchar[] str = "abc"d.dup; + makeFirstLetterDot(str); + writeln(str); +} +--- + +$(P +The change made to the first element of the parameter affects the actual element in $(C main()): +) + +$(SHELL +.bc +) + +$(P +However, the original slice and associative array variables are still passed by copy. This may have surprising and seemingly unpredictable results unless the parameters are qualified as $(C ref) themselves. +) + +$(H6 Surprising reference semantics of slices) + +$(P +As we saw in the $(LINK2 slices.html, Slices and Other Array Features chapter), adding elements to a slice $(I may) terminate element sharing. Obviously, once sharing ends, a slice parameter like $(C str) above would not be a reference to the elements of the passed-in original variable anymore. +) + +$(P +For example, the element that is appended by the following function will not be seen by the caller: +) + +--- +import std.stdio; + +void appendZero(int[] arr) { + arr $(HILITE ~= 0); + writefln("Inside appendZero() : %s", arr); +} + +void main() { + auto arr = [ 1, 2 ]; + appendZero(arr); + writefln("After appendZero() returns: %s", arr); +} +--- + +$(P +The element is appended only to the function parameter, not to the original slice: +) + +$(SHELL +Inside appendZero() : [1, 2, 0] +After appendZero() returns: [1, 2] $(SHELL_NOTE_WRONG No 0) +) + +$(P +If the new elements need to be appended to the original slice, then the slice must be passed as $(C ref): +) + +--- +void appendZero($(HILITE ref) int[] arr) { + // ... +} +--- + +$(P +The $(C ref) qualifier will be explained below. +) + +$(H6 Surprising reference semantics of associative arrays) + +$(P +Associative arrays that are passed as function parameters may cause surprises as well because associative arrays start their lives as $(C null), not empty. +) + +$(P +In this context, $(C null) means an uninitialized associative array. Associative arrays are initialized automatically when their first key-value pair is added. As a consequence, if a function adds an element to a $(C null) associative array, then that element cannot be seen in the original variable because although the parameter is initialized, the original variable remains $(C null): +) + +--- +import std.stdio; + +void appendElement(int[string] aa) { + aa$(HILITE ["red"] = 100); + writefln("Inside appendElement() : %s", aa); +} + +void main() { + int[string] aa; // ← null to begin with + appendElement(aa); + writefln("After appendElement() returns: %s", aa); +} +--- + +$(P +The original variable does not have the added element: +) + +$(SHELL +Inside appendElement() : ["red":100] +After appendElement() returns: [] $(SHELL_NOTE_WRONG Still null) +) + +$(P +On the other hand, if the associative array were not $(C null) to begin with, then the added element would be seen by the caller as well: +) + +--- + int[string] aa; + aa["blue"] = 10; // ← Not null before the call + appendElement(aa); +--- + +$(P +This time the added element is seen by the caller: +) + +$(SHELL +Inside appendElement() : ["red":100, "blue":10] +After appendElement() returns: [$(HILITE "red":100), "blue":10] +) + +$(P +For that reason, it may be better to pass the associative array as a $(C ref) parameter, which will be explained below. +) + +$(H5 Parameter qualifiers) + +$(P +Parameters are passed to functions according to the general rules described above: +) + +$(UL + +$(LI Value types are copied, after which the original variable and the copy are independent.) + +$(LI Reference types are copied as well but both the original reference and the parameter provide access to the same variable.) + +) + +$(P +Those are the default rules that are applied when parameter definitions have no qualifiers. The following qualifiers change the way parameters are passed and what operations are allowed on them. +) + +$(H6 $(IX in, parameter) $(C in)) + +$(P +We have seen that functions can produce values and can have side effects. The $(C in) keyword specifies that the parameter is going be used only as input: +) + +--- +import std.stdio; + +double weightedTotal($(HILITE in) double currentTotal, + $(HILITE in) double weight, + $(HILITE in) double addend) { + return currentTotal + (weight * addend); +} + +void main() { + writeln(weightedTotal(1.23, 4.56, 7.89)); +} +--- + +$(P +Like $(C const), $(C in) parameters cannot be modified: +) + +--- +void foo(in int value) { + value = 1; $(DERLEME_HATASI) +} +--- + +$(H6 $(IX out, parameter) $(C out)) + +$(P +We know that functions return what they produce as their return values. The fact that there is only one return value is sometimes limiting as some functions may need to produce more than one result. ($(I $(B Note:) It is possible to return more than one result by defining the return type as a $(C Tuple) or a $(C struct). We will see these features in later chapters.)) +) + +$(P +The $(C out) keyword makes it possible for functions to return results through their parameters. When $(C out) parameters are modified within the function, those modifications affect the original variable that has been passed to the function. In a sense, the assigned value goes $(I out) of the function through the $(C out) parameter. +) + +$(P +Let's have a look at a function that divides two numbers and produces both the quotient and the remainder. The return value is used for the quotient and the remainder is $(I returned) through the $(C out) parameter: +) + +--- +import std.stdio; + +int divide(int dividend, int divisor, $(HILITE out) int remainder) { + $(HILITE remainder = dividend % divisor); + return dividend / divisor; +} + +void main() { + int remainder; + int result = divide(7, 3, remainder); + + writeln("result: ", result, ", remainder: ", remainder); +} +--- + +$(P +Modifying the $(C remainder) parameter of the function modifies the $(C remainder) variable in $(C main()) (their names need not be the same): +) + +$(SHELL +result: 2, remainder: 1 +) + +$(P +Regardless of their values at the call site, $(C out) parameters are first assigned to the $(C .init) value of their types automatically: +) + +--- +import std.stdio; + +void foo(out int parameter) { + writeln("After entering the function : ", parameter); +} + +void main() { + int variable = 100; + + writeln("Before calling the function : ", variable); + foo(variable); + writeln("After returning from the function: ", variable); +} +--- + +$(P +Even though there is no explicit assignment to the parameter in the function, the value of the parameter automatically becomes the initial value of $(C int), affecting the variable in $(C main()): +) + +$(SHELL +Before calling the function : 100 +After entering the function : 0 $(SHELL_NOTE the value of int.init) +After returning from the function: 0 +) + +$(P +As this demonstrates, $(C out) parameters cannot pass values into functions; they are strictly for passing values out of functions. +) + +$(P +We will see in later chapters that returning $(C Tuple) or $(C struct) types are better alternatives to $(C out) parameters. +) + +$(H6 $(IX const, parameter) $(C const)) + +$(P +As we saw earlier, $(C const) guarantees that the parameter will not be modified inside the function. It is helpful for the programmers to know that certain variables will not be changed by a function. $(C const) also makes functions more useful by allowing $(C const), $(C immutable), and $(I mutable) variables to be passed through that parameter: +) + +--- +import std.stdio; + +dchar lastLetter($(HILITE const) dchar[] str) { + return str[$ - 1]; +} + +void main() { + writeln(lastLetter("constant")); +} +--- + +$(H6 $(IX immutable, parameter) $(C immutable)) + +$(P +As we saw earlier, $(C immutable) makes functions require that certain variables must be immutable. Because of such a requirement, the following function can only be called with strings with $(C immutable) elements (e.g. string literals): +) + +--- +import std.stdio; + +dchar[] mix($(HILITE immutable) dchar[] first, + $(HILITE immutable) dchar[] second) { + dchar[] result; + int i; + + for (i = 0; (i < first.length) && (i < second.length); ++i) { + result ~= first[i]; + result ~= second[i]; + } + + result ~= first[i..$]; + result ~= second[i..$]; + + return result; +} + +void main() { + writeln(mix("HELLO", "world")); +} +--- + +$(P +Since it forces a requirement on the parameter, $(C immutable) parameters should be used only when immutability is required. Otherwise, in general $(C const) is more useful because it accepts $(C immutable), $(C const), and $(I mutable) variables. +) + +$(H6 $(IX ref, parameter) $(C ref)) + +$(P +This keyword allows passing a variable by reference even though it would normally be passed as a copy (i.e. by value). +) + +$(P +For the $(C reduceEnergy()) function that we saw earlier to modify the original variable, it must take its parameter as $(C ref): +) + +--- +import std.stdio; + +void reduceEnergy($(HILITE ref) double energy) { + energy /= 4; +} + +void main() { + double energy = 100; + + reduceEnergy(energy); + writeln("New energy: ", energy); +} +--- + +$(P +This time, the modification that is made to the parameter changes the original variable in $(C main()): +) + +$(SHELL +New energy: 25 +) + +$(P +As can be seen, $(C ref) parameters can be used both as input and output. $(C ref) parameters can also be thought of as aliases of the original variables. The function parameter $(C energy) above is an alias of the variable $(C energy) in $(C main()). +) + +$(P +Similar to $(C out) parameters, $(C ref) parameters allow functions to have side effects as well. In fact, $(C reduceEnergy()) does not return a value; it only causes a side effect through its single parameter. +) + +$(P +The programming style called $(I functional programming) favors return values over side effects, so much so that some functional programming languages do not allow side effects at all. This is because functions that produce results $(I purely) through their return values are easier to understand, implement, and maintain. +) + +$(P +The same function can be written in a functional programming style by returning the result, instead of causing a side effect. The parts of the program that changed are highlighted: +) + +--- +import std.stdio; + +$(HILITE double reducedEnergy)(double energy) { + $(HILITE return energy / 4); +} + +void main() { + double energy = 100; + + $(HILITE energy = reducedEnergy(energy)); + writeln("New energy: ", energy); +} +--- + +$(P +Note the change in the name of the function as well. Now it is a noun as opposed to a verb. +) + +$(H6 $(C auto ref)) + +$(P +This qualifier can only be used with $(LINK2 templates.html, templates). As we will see in the next chapter, an $(C auto ref) parameter takes $(I lvalues) by reference and $(I rvalues) by copy. +) + +$(H6 $(IX inout, parameter) $(C inout)) + +$(P +Despite its name consisting of $(C in) and $(C out), this keyword does not mean $(I input and output); we have already seen that input and output is achieved by the $(C ref) keyword. +) + +$(P +$(C inout) carries the $(I mutability) of the parameter to the return type. If the parameter is $(C const), $(C immutable), or $(I mutable); then the return value is also $(C const), $(C immutable), or $(I mutable); respectively. +) + +$(P +To see how $(C inout) helps in programs, let's look at a function that returns a slice to the $(I inner) elements of its parameter: +) + +--- +import std.stdio; + +int[] inner(int[] slice) { + if (slice.length) { + --slice.length; // trim from the end + + if (slice.length) { + slice = slice[1 .. $]; // trim from the beginning + } + } + + return slice; +} + +void main() { + int[] numbers = [ 5, 6, 7, 8, 9 ]; + writeln(inner(numbers)); +} +--- + +$(P +The output: +) + +$(SHELL +[6, 7, 8] +) + +$(P +According to what we have established so far in the book, in order for the function to be more useful, its parameter should be $(C const(int)[]) because the elements are not being modified inside the function. (Note that there is no harm in modifying the parameter slice itself, as it is a copy of the original variable.) +) + +$(P +However, defining the function that way would cause a compilation error: +) + +--- +int[] inner($(HILITE const(int)[]) slice) { + // ... + return slice; $(DERLEME_HATASI) +} +--- + +$(P +The compilation error indicates that a slice of $(C const(int)) cannot be returned as a slice of $(I mutable) $(C int): +) + +$(SHELL +Error: cannot implicitly convert expression (slice) of type +const(int)[] to int[] +) + +$(P +One may think that specifying the return type as $(C const(int)[]) would be the solution: +) + +--- +$(HILITE const(int)[]) inner(const(int)[] slice) { + // ... + return slice; // now compiles +} +--- + +$(P +Although the code now compiles, it brings a limitation: even when the function is called with a slice of $(I mutable) elements, this time the returned slice ends up consisting of $(C const) elements. To see how limiting this would be, let's look at the following code, which tries to modify the inner elements of a slice: +) + +--- + int[] numbers = [ 5, 6, 7, 8, 9 ]; + int[] middle = inner(numbers); $(DERLEME_HATASI) + middle[] *= 10; +--- + +$(P +The returned slice of type $(C const(int)[]) cannot be assigned to a slice of type $(C int[]), resulting in an error: +) + +$(SHELL +Error: cannot implicitly convert expression (inner(numbers)) +of type const(int)[] to int[] +) + +$(P +However, since we started with a slice of mutable elements, this limitation is artificial and unfortunate. $(C inout) solves this mutability problem between parameters and return values. It is specified on both the parameter and the return type and carries the mutability of the former to the latter: +) + +--- +$(HILITE inout)(int)[] inner($(HILITE inout)(int)[] slice) { + // ... + return slice; +} +--- + +$(P +With that change, the same function can now be called with $(C const), $(C immutable), and $(I mutable) slices: +) + +--- + { + $(HILITE int[]) numbers = [ 5, 6, 7, 8, 9 ]; + // The return type is a slice of mutable elements + $(HILITE int[]) middle = inner(numbers); + middle[] *= 10; + writeln(middle); + } + { + $(HILITE immutable int[]) numbers = [ 10, 11, 12 ]; + // The return type is a slice of immutable elements + $(HILITE immutable int[]) middle = inner(numbers); + writeln(middle); + } + { + $(HILITE const int[]) numbers = [ 13, 14, 15, 16 ]; + // The return type is a slice of const elements + $(HILITE const int[]) middle = inner(numbers); + writeln(middle); + } +--- + +$(H6 $(IX lazy) $(C lazy)) + +$(P +It is natural to expect that arguments are evaluated $(I before) entering functions that use those arguments. For example, the function $(C add()) below is called with the return values of two other functions: +) + +--- + result = add(anAmount(), anotherAmount()); +--- + +$(P +In order for $(C add()) to be called, first $(C anAmount()) and $(C anotherAmount()) must be called. Otherwise, the values that $(C add()) needs would not be available. +) + +$(P +Evaluating arguments before calling a function is called $(I eager evaluation). +) + +$(P +However, depending on certain conditions, some parameters may not get a chance to be used in the function at all. In such cases, evaluating the arguments eagerly would be wasteful. +) + +$(P +A classic example of this situation is a $(I logging) function that outputs a message only if the importance of the message is above a certain configuration setting: +) + +--- +enum Level { low, medium, high } + +void log(Level level, string message) { + if (level >= interestedLevel) { + writeln(message); + } +} +--- + +$(P +For example, if the user is interested only in the messages that are $(C Level.high), a message with $(C Level.medium) would not be printed. However, the argument would still be evaluated before calling the function. For example, the entire $(C format()) expression below including the $(C getConnectionState()) call that it makes would be wasted if the message is never printed: +) + +--- + if (failedToConnect) { + log(Level.medium, + format("Failure. The connection state is '%s'.", + getConnectionState())); + } +--- + +$(P +The $(C lazy) keyword specifies that an expression that is passed as a parameter will be evaluated only if and when needed: +) + +--- +void log(Level level, $(HILITE lazy) string message) { + // ... the body of the function is the same as before ... +} +--- + +$(P +This time, the expression would be evaluated only if the $(C message) parameter is used. +) + +$(P +One thing to be careful about is that a $(C lazy) parameter is evaluated $(I every time) that parameter is used in the function. +) + +$(P +For example, because the $(C lazy) parameter of the following function is used three times in the function, the expression that provides its value is evaluated three times: +) + +--- +import std.stdio; + +int valueOfArgument() { + writeln("Calculating..."); + return 1; +} + +void functionWithLazyParameter(lazy int value) { + int result = $(HILITE value + value + value); + writeln(result); +} + +void main() { + functionWithLazyParameter(valueOfArgument()); +} +--- + +$(P +The output: +) + +$(SHELL +Calculating +Calculating +Calculating +3 +) + +$(H6 $(IX scope) $(C scope)) + +$(P +$(IX DIP) $(IX -dip1000) This keyword specifies that a parameter will not be used beyond the scope of the function. As of this writing, $(C scope) is effective only if the function is defined as $(LINK2 functions_more.html, $(C @safe)) and if $(C -dip1000) compiler switch is used. DIP is short for $(I D Improvement Proposal). DIP 1000 is experimental as of this writing; so it may not work as expected in all cases. +) + +$(SHELL +$(SHELL_OBSERVED $) dmd -dip1000 deneme.d +) + +--- +int[] globalSlice; + +$(HILITE @safe) int[] foo($(HILITE scope) int[] parameter) { + globalSlice = parameter; $(DERLEME_HATASI) + return parameter; $(DERLEME_HATASI) +} + +void main() { + int[] slice = [ 10, 20 ]; + int[] result = foo(slice); +} +--- + +$(P +The function above violates the promise of $(C scope) in two places: It assigns the parameter to a global variable, and it returns it. Both those actions would make it possible for the parameter to be accessed after the function finishes. +) + +$(H6 $(IX shared, parameter) $(C shared)) + +$(P +This keyword requires that the parameter is shareable between threads of execution: +) + +--- +void foo($(HILITE shared) int[] i) { + // ... +} + +void main() { + int[] numbers = [ 10, 20 ]; + foo(numbers); $(DERLEME_HATASI) +} +--- + +$(P +The program above cannot be compiled because the argument is not $(C shared). The following is the necessary change to make it compile: +) + +--- + $(HILITE shared) int[] numbers = [ 10, 20 ]; + foo(numbers); // now compiles +--- + +$(P +We will see the $(C shared) keyword later in the $(LINK2 concurrency_shared.html, Data Sharing Concurrency chapter). +) + +$(H6 $(IX return, parameter) $(C return)) + +$(P +Sometimes it is useful for a function to return one of its $(C ref) parameters directly. For example, the following $(C pick()) function picks and returns one of its parameters randomly so that the caller can mutate the lucky one directly: +) + +--- +import std.stdio; +import std.random; + +$(HILITE ref) int pick($(HILITE ref) int lhs, $(HILITE ref) int rhs) { + return uniform(0, 2) ? lhs : rhs; $(DERLEME_HATASI) +} + +void main() { + int a; + int b; + + pick(a, b) $(HILITE = 42); + + writefln("a: %s, b: %s", a, b); +} +--- + +$(P +As a result, either $(C a) or $(C b) inside $(C main()) is assigned the value $(C 42): +) + +$(SHELL +a: 42, b: 0 +) + +$(SHELL +a: 0, b: 42 +) + +$(P +Unfortunately, one of the arguments of $(C pick()) may have a shorter lifetime than the returned reference. For example, the following $(C foo()) function calls $(C pick()) with two local variables, effectively itself returning a reference to one of them: +) + +--- +import std.random; + +ref int pick(ref int lhs, ref int rhs) { + return uniform(0, 2) ? lhs : rhs; $(DERLEME_HATASI) +} + +ref int foo() { + int a; + int b; + + return pick(a, b); $(CODE_NOTE_WRONG BUG: returning invalid reference) +} + +void main() { + foo() = 42; $(CODE_NOTE_WRONG BUG: writing to invalid memory) +} +--- + +$(P +Since the lifetimes of both $(C a) and $(C b) end upon leaving $(C foo()), the assignment in $(C main()) cannot be made to a valid variable. This results in $(I undefined behavior). +) + +$(P +$(IX undefined behavior) The term $(I undefined behavior) describes situations where the behavior of the program is not defined by the programming language specification. Nothing can be said about the behavior of a program that contains undefined behavior. (In practice though, for the program above, the value $(C 42) would most likely be written to a memory location that used to be occupied by either $(C a) or $(C b), potentially currently a part of an unrelated variable, effectively corrupting the value of that unrelated variable.) +) + +$(P +The $(C return) keyword can be applied to a parameter to prevent such bugs. It specifies that a parameter must be a reference to a variable with a longer lifetime than the returned reference: +) + +--- +import std.random; + +ref int pick($(HILITE return) ref int lhs, $(HILITE return) ref int rhs) { + return uniform(0, 2) ? lhs : rhs; +} + +ref int foo() { + int a; + int b; + + return pick(a, b); $(DERLEME_HATASI) +} + +void main() { + foo() = 42; +} +--- + +$(P +This time the compiler sees that the arguments to $(C pick()) have a shorter lifetime than the reference that $(C foo()) is attempting to return: +) + +$(SHELL +Error: escaping reference to local variable a +Error: escaping reference to local variable b +) + +$(P +$(IX sealed reference) $(IX reference, sealed) This feature is called $(I sealed references). +) + +$(P +$(I $(B Note:) Although it is conceivable that the compiler could inspect $(C pick()) and detect the bug even without the $(C return) keyword, it cannot do so in general because the bodies of some functions may not be available to the compiler during every compilation.) +) + +$(H5 Summary) + +$(UL + +$(LI A $(I parameter) is what the function takes from its caller to accomplish its task.) + +$(LI An $(I argument) is an expression (e.g. a variable) that is passed to a function as a parameter.) + +$(LI +Every argument is passed by copy. However, for reference types, it is the reference that is copied, not the original variable. +) + +$(LI $(C in) specifies that the parameter is used only for data input.) + +$(LI $(C out) specifies that the parameter is used only for data output.) + +$(LI $(C ref) specifies that the parameter is used for data input and data output.) + +$(LI $(C auto ref) is used in templates only. It specifies that if the argument is an lvalue, then a reference to it is passed; if the argument is an rvalue, then it is passed by copy.) + +$(LI $(C const) guarantees that the parameter is not modified inside the function. (Remember that $(C const) is transitive: any data reached through a $(C const) variable is $(C const) as well.)) + +$(LI $(C immutable) requires the argument to be $(C immutable).) + +$(LI $(C inout) appears both at the parameter and the return type, and transfers the $(I mutability) of the parameter to the return type.) + +$(LI $(C lazy) is used to make a parameter be evaluated when (and every time) it is actually used.) + +$(LI $(C scope) guarantees that no reference to the parameter will be leaked from the function.) + +$(LI $(C shared) requires the parameter to be $(C shared).) + +$(LI $(C return) on a parameter requires the parameter to live longer than the returned reference.) + +) + +$(PROBLEM_TEK + +$(P +The following program is trying to swap the values of two arguments: +) + +--- +import std.stdio; + +void swap(int first, int second) { + int temp = first; + first = second; + second = temp; +} + +void main() { + int a = 1; + int b = 2; + + swap(a, b); + + writeln(a, ' ', b); +} +--- + +$(P +However, the program does not have any effect on $(C a) or $(C b): +) + +$(SHELL +1 2 $(SHELL_NOTE_WRONG not swapped) +) + +$(P +Fix the function so that the values of $(C a) and $(C b) are swapped. +) + +) + +Macros: + TITLE=Function Parameters + + DESCRIPTION=Kinds of function parameters in the D programmning language. + + KEYWORDS=d programming language tutorial book in out inout ref lazy const immutable scope shared diff --git a/book/d.en/functions.cozum.d b/book/d.en/functions.cozum.d new file mode 100644 index 0000000000..f9a7daa6b3 --- /dev/null +++ b/book/d.en/functions.cozum.d @@ -0,0 +1,57 @@ +Ddoc + +$(COZUM_BOLUMU Functions) + +$(OL + +$(LI + +--- +import std.stdio; + +void printMenu(string[] items, int firstNumber) { + foreach (i, item; items) { + writeln(' ', i + firstNumber, ' ', item); + } +} + +void main() { + string[] items = + [ "Black", "Red", "Green", "Blue", "White" ]; + printMenu(items, 1); +} +--- + +) + +$(LI +Here are some ideas: + +$(UL + +$(LI Write a function named $(C drawHorizontalLine()) to draw horizontal lines.) + +$(LI Write a function named $(C drawSquare()) to draw squares. This function could take advantage of $(C drawVerticalLine()) and $(C drawHorizontalLine()) when drawing the square.) + +$(LI Improve the functions to also take the character that is used when "drawing". This would allow drawing each shape with a different character: + +--- +void putDot(Canvas canvas, int line, int column$(HILITE , dchar dot)) { + canvas[line][column] = $(HILITE dot); +} +--- + +) + +) + +) + +) + +Macros: + TITLE=Functions Solutions + + DESCRIPTION=Programming in D exercise solutions: functions + + KEYWORDS=programming in d tutorial functions diff --git a/book/d.en/functions.d b/book/d.en/functions.d new file mode 100644 index 0000000000..31fbc7655a --- /dev/null +++ b/book/d.en/functions.d @@ -0,0 +1,744 @@ +Ddoc + +$(DERS_BOLUMU $(IX function) Functions) + +$(P +Similarly to how fundamental types are building blocks of program data, functions are building blocks of program behavior. +) + +$(P +Functions are also closely related to the craft aspect of programming. The functions that are written by experienced programmers are succinct, simple, and clear. This goes both ways: The mere act of trying to identify and write smaller building blocks of a program makes for a better programmer. +) + +$(P +We have covered basic statements and expressions in previous chapters. Although there will be many more that we will see in later chapters, what we have seen so far are commonly-used features of D. Still, they are not sufficient on their own to write large programs. The programs that we have written so far have all been very short, each demonstrating just a simple feature of the language. Trying to write a program with any level of complexity without functions would be very difficult and prone to bugs. +) + +$(P +This chapter covers only the basic features of functions. We will see more about functions later in the following chapters: +) + +$(UL +$(LI $(LINK2 function_parameters.html, Function Parameters)) +$(LI $(LINK2 function_overloading.html, Function Overloading)) +$(LI $(LINK2 lambda.html, Function Pointers, Delegates, and Lambdas)) +$(LI $(LINK2 functions_more.html, More Functions)) +) + +$(P +Functions are features that put statements and expressions together as units of program execution. Such statements and expressions altogether are given a name that describes what they collectively achieve. They can then be $(I called) (or $(I executed)) by using that name. +) + +$(P +The concept of $(I giving names to a group of steps) is common in our daily lives. For example, the act of cooking an omelet can be described in some level of detail by the following steps: +) + +$(UL +$(LI get a pan) +$(LI get butter) +$(LI get an egg) +$(LI turn on the stove) +$(LI put the pan on the fire) +$(LI put butter into the pan when it is hot) +$(LI put the egg into butter when it is melted) +$(LI remove the pan from the fire when the egg is cooked) +$(LI turn off the stove) +) + +$(P +Since that much detail is obviously excessive, steps that are related together would be combined under a single name: +) + +$(UL +$(LI $(HILITE make preparations) (get the pan, butter, and the egg)) +$(LI turn on the stove) +$(LI $(HILITE cook the egg) (put the pan on the fire, etc.)) +$(LI turn off the stove) +) + +$(P +Going further, there can be a single name for all of the steps: +) + +$(UL +$(LI $(HILITE make a one-egg omelet) (all of the steps)) +) + +$(P +Functions are based on the same concept: steps that can collectively be named as a whole are put together to form a function. As an example, let's start with the following lines of code that achieve the task of printing a menu: +) + +--- + writeln(" 0 Exit"); + writeln(" 1 Add"); + writeln(" 2 Subtract"); + writeln(" 3 Multiply"); + writeln(" 4 Divide"); +--- + +$(P +Since it would make sense to name those combined lines as $(C printMenu), they can be put together to form a function by using the following syntax: +) + +--- +$(CODE_NAME printMenu)void printMenu() { + writeln(" 0 Exit"); + writeln(" 1 Add"); + writeln(" 2 Subtract"); + writeln(" 3 Multiply"); + writeln(" 4 Divide"); +} +--- + +$(P +The contents of that function can now be executed from within $(C main()) simply by using its name: +) + +--- +$(CODE_XREF printMenu)void main() { + printMenu(); + + // ... +} +--- + +$(P +It may be obvious from the similarities of the definitions of $(C printMenu()) and $(C main()) that $(C main()) is a function as well. The execution of a D program starts with the function named $(C main()) and branches out to other functions from there. +) + +$(H5 $(IX parameter) Parameters) + +$(P +Some of the powers of functions come from the fact that their behaviors are adjustable through parameters. +) + +$(P +Let's continue with the omelet example by modifying it to make an omelet of five eggs instead of always one. The steps would exactly be the same, the only difference being the number of eggs to use. We can change the more general description above accordingly: +) + +$(UL +$(LI make preparations (get the pan, butter, and $(HILITE five eggs))) +$(LI turn on the stove) +$(LI cook $(HILITE the eggs) (put the pan on the fire, etc.)) +$(LI turn off the stove) +) + +$(P +Likewise, the most general single step would become the following: +) + +$(UL +$(LI make a $(HILITE five-egg) omelet (all of the steps)) +) + +$(P +This time there is an additional information that concerns some of the steps: "get five eggs", "cook the eggs", and "make a five-egg omelet". +) + +$(P +$(IX , (comma), function parameter list) The behaviors of functions can be adjusted similarly to the omelet example. The information that functions use to adjust their behavior are called $(I parameters). Parameters are specified in a comma separated $(I function parameter list). The parameter list rests inside of the parentheses that comes after the name of the function. +) + +$(P +The $(C printMenu()) function above was defined with an empty parameter list because that function always printed the same menu. Let's assume that sometimes the menu will need to be printed differently in different contexts. For example, it may make more sense to print the first entry as "Return" instead of "Exit" depending on the part of the program that is being executed at that time. +) + +$(P +In such a case, the first entry of the menu can be $(I parameterized) by having been defined in the parameter list. The function then uses the value of that parameter instead of the literal $(STRING "Exit"): +) + +--- +void printMenu($(HILITE string firstEntry)) { + writeln(" 0 ", firstEntry); + writeln(" 1 Add"); + writeln(" 2 Subtract"); + writeln(" 3 Multiply"); + writeln(" 4 Divide"); +} +--- + +$(P +Notice that since the information that the $(C firstEntry) parameter conveys is a piece of text, its type has been specified as $(C string) in the parameter list. This function can now be $(I called) with different parameter values to print menus having different first entries. All that needs to be done is to use the appropriate $(C string) values depending on where the function is being called from: +) + +--- + // At some place in the program: + printMenu("Exit"); + // ... + // At some other place in the program: + printMenu("Return"); +--- + +$(P +$(B Note:) When you write and use your own functions with parameters of type $(C string) you may encounter compilation errors. As written, $(C printMenu()) above cannot be called with parameter values of type $(C char[]). For example, the following code would cause a compilation error: +) + +--- + char[] anEntry; + anEntry ~= "Take square root"; + printMenu(anEntry); $(DERLEME_HATASI) +--- + +$(P +On the other hand, if $(C printMenu()) were defined to take its parameter as $(C char[]), then it could not be called with $(C string)s like $(STRING "Exit"). This is related to the concept of immutability and the $(C immutable) keyword, both of which will be covered in the next chapter. +) + +$(P +Let's continue with the menu function and assume that it is not appropriate to always start the menu selection numbers with zero. In that case the starting number can also be passed to the function as its second parameter. The parameters of the function must be separated by commas: +) + +--- +void printMenu(string firstEntry$(HILITE , int firstNumber)) { + writeln(' ', firstNumber + 0, ' ', firstEntry); + writeln(' ', firstNumber + 1, " Add"); + writeln(' ', firstNumber + 2, " Subtract"); + writeln(' ', firstNumber + 3, " Multiply"); + writeln(' ', firstNumber + 4, " Divide"); +} +--- + +$(P +It is now possible to tell the function what number to start from: +) + +--- + printMenu("Return"$(HILITE , 1)); +--- + +$(H5 Calling a function) + +$(P +Starting a function so that it achieves its task is called $(I calling a function). The function call syntax is the following: +) + +--- + $(I function_name)($(I parameter_values)) +--- + + +$(P +$(IX argument) The actual parameter values that are passed to functions are called $(I function arguments). Although the terms $(I parameter) and $(I argument) are sometimes used interchangeably in the literature, they signify different concepts. +) + +$(P +The arguments are matched to the parameters one by one in the order that the parameters are defined. For example, the last call of $(C printMenu()) above uses the $(I arguments) $(STRING "Return") and $(C 1), which correspond to the $(I parameters) $(C firstEntry) and $(C firstNumber), respectively. +) + +$(P +The type of each argument must match the type of the corresponding parameter. +) + +$(H5 Doing work) + +$(P +In previous chapters, we have defined expressions as entities that do work. Function calls are expressions as well: they do some work. Doing work means producing a value or having a side effect: +) + +$(UL + +$(LI +$(B Producing a value): Some operations only produce values. For example, a function that adds numbers would be producing the result of that addition. As another example, a function that makes a $(C Student) object by using the student's name and address would be producing a $(C Student) object. +) + +$(LI +$(IX side effect) +$(B Having side effects): Side effects are any change in the state of the program or its environment. Some operations have only side effects. An example is how the $(C printMenu()) function above changes $(C stdout) by printing to it. As another example, a function that adds a $(C Student) object to a student container would also have a side effect: it would be causing the container to grow. + +$(P +In summary, operations that cause a change in the state of the program have side effects. +) + +) + +$(LI +$(B Having side effects and producing a value:) Some operations do both. For example, a function that reads two values from $(C stdin) and returns their sum would be having side effects due to changing the state of $(C stdin) and also producing the sum of the two values. +) + +$(LI +$(B No operation:) Although every function is designed as one of the three categories above, depending on certain conditions at compile time or at run time, some functions end up doing no work at all. +) + +) + +$(H5 $(IX return value) The return value) + +$(P +The value that a function produces as a result of its work is called its $(I return value). This term comes from the observation that once the program execution branches into a function, it eventually $(I returns) back to where the function has been called. Functions get $(I called) and they $(I return) values. +) + +$(P +Just like any other value, return values have types. The type of the return value is specified right before the name of the function, at the point where the function is defined. For example, a function that adds two values of type $(C int) and returns their sum also as an $(C int) would be defined as follows: +) + +--- +$(HILITE int) add(int first, int second) { + // ... the actual work of the function ... +} +--- + +$(P +The value that a function returns takes the place of the function call itself. For example, assuming that the function call $(C add(5, 7)) produces the value $(C 12), then the following two lines would be equivalent: +) + +--- + writeln("Result: ", add(5, 7)); + writeln("Result: ", 12); +--- + +$(P +In the first line above, the $(C add()) function is called with the arguments $(C 5) and $(C 7) $(I before) $(C writeln()) gets called. The value $(C 12) that the function returns is in turn passed to $(C writeln()) as its second argument. +) + +$(P +This allows passing the return values of functions to other functions to form complex expressions: +) + +--- + writeln("Result: ", add(5, divide(100, studentCount()))); +--- + +$(P +In the line above, the return value of $(C studentCount()) is passed to $(C divide()) as its second argument, the return value of $(C divide()) is passed to $(C add()) as its second argument, and eventually the return value of $(C add()) is passed to $(C writeln()) as its second argument. +) + +$(H5 $(IX return, statement) The $(C return) statement) + +$(P +The return value of a function is specified by the $(C return) keyword: +) + +--- +int add(int first, int second) { + int result = first + second; + $(HILITE return) result; +} +--- + +$(P +A function produces its return value by taking advantage of statements, expressions, and potentially by calling other functions. The function would then return that value by the $(C return) keyword, at which point the execution of the function ends. +) + +$(P +It is possible to have more than one $(C return) statement in a function. The value of the first $(C return) statement that gets executed determines the return value of the function for a particular call: +) + +--- +int complexCalculation(int aParameter, int anotherParameter) { + if (aParameter == anotherParameter) { + return 0; + } + + return aParameter * anotherParameter; +} +--- + +$(P +The function above returns $(C 0) when the two parameters are equal, and the product of their values when they are different. +) + +$(H5 $(IX void, function) $(C void) functions) + +$(P +The return types of functions that do not produce values are specified as $(C void). We have seen this many times with the $(C main()) function so far, as well as the $(C printMenu()) function above. Since they do not return any value to the caller, their return types have been defined as $(C void). ($(I $(B Note:) $(C main()) can also be defined as returning $(C int). We will see this in $(LINK2 main.html, a later chapter).)) +) + +$(H5 The name of the function) + +$(P +The name of a function must be chosen to communicate the purpose of the function clearly. For example, the names $(C add) and $(C printMenu) were appropriate because their purposes were to add two values, and to print a menu, respectively. +) + +$(P +A common guideline for function names is that they contain a verb like $(I add) or $(I print). According to this guideline names like $(C addition()) and $(C menu()) would be less than ideal. +) + +$(P +However, it is acceptable to name functions simply as nouns if those functions do not have any side effects. For example, a function that returns the current temperature can be named as $(C currentTemperature()) instead of $(C getCurrentTemperature()). +) + +$(P +Coming up with names that are clear, short, and consistent is part of the subtle art of programming. +) + +$(H5 Code quality through functions) + +$(P +Functions can improve the quality of code. Smaller functions with fewer responsibilities lead to programs that are easier to maintain. +) + +$(H6 $(IX code duplication) Code duplication is harmful) + +$(P +One of the aspects that is highly detrimental to program quality is code duplication. Code duplication occurs when there is more than one piece of code in the program that performs the same task. +) + +$(P +Although this sometimes happens by copying lines of code around, it may also happen incidentally when writing separate pieces of code. +) + +$(P +One of the problems with pieces of code that duplicate essentially the same functionality is that they present multiple chances for bugs to crop up. When such bugs do occur and we need to fix them, it can be hard to make sure that we have fixed all places where we introduced the problem, as they may be spread around. Conversely, when the code appears in only one place in the program, then we only need to fix it at that one place to get rid of the bug once and for all. +) + +$(P +As I mentioned above, functions are closely related to the craft aspect of programming. Experienced programmers are always on the lookout for code duplication. They continually try to identify commonalities in code and move common pieces of code to separate functions (or to common structs, classes, templates, etc., as we will see in later chapters). +) + +$(P +$(IX refactor) Let's start with a program that contains some code duplication. Let's see how that duplication can be removed by moving code into functions (i.e. by $(I refactoring) the code). The following program reads numbers from the input and prints them first in the order that they have arrived and then in numerical order: +) + +--- +import std.stdio; +import std.algorithm; + +void main() { + int[] numbers; + + int count; + write("How many numbers are you going to enter? "); + readf(" %s", &count); + + // Read the numbers + foreach (i; 0 .. count) { + int number; + write("Number ", i, "? "); + readf(" %s", &number); + + numbers ~= number; + } + + // Print the numbers + writeln("Before sorting:"); + foreach (i, number; numbers) { + writefln("%3d:%5d", i, number); + } + + sort(numbers); + + // Print the numbers + writeln("After sorting:"); + foreach (i, number; numbers) { + writefln("%3d:%5d", i, number); + } +} +--- + +$(P +Some of the duplicated lines of code are obvious in that program. The last two $(C foreach) loops that are used for printing the numbers are exactly the same. Defining a function that might appropriately be named as $(C print()) would remove that duplication. The function could take a slice as a parameter and print it: +) + +--- +void print(int[] slice) { + foreach (i, element; slice) { + writefln("%3s:%5s", i, element); + } +} +--- + +$(P +Notice that the parameter is now referred to using the more general name $(C slice) instead of original and more specific name $(C numbers). The reason for that is the fact that the function would not know what the elements of the slice would specifically represent. That can only be known at the place where the function has been called from. The elements may be student IDs, parts of a password, etc. Since that cannot be known in the $(C print()) function, general names like $(C slice) and $(C element) are used in its implementation. +) + +$(P +The new function can be called from the two places where the slice needs to be printed: +) + +--- +import std.stdio; +import std.algorithm; + +void print(int[] slice) { + foreach (i, element; slice) { + writefln("%3s:%5s", i, element); + } +} + +void main() { + int[] numbers; + + int count; + write("How many numbers are you going to enter? "); + readf(" %s", &count); + + // Read the numbers + foreach (i; 0 .. count) { + int number; + write("Number ", i, "? "); + readf(" %s", &number); + + numbers ~= number; + } + + // Print the numbers + writeln("Before sorting:"); + $(HILITE print(numbers)); + + sort(numbers); + + // Print the numbers + writeln("After sorting:"); + $(HILITE print(numbers)); +} +--- + +$(P +There is more to do. Notice that there is always a title line printed right before printing the elements of the slice. Although the title is different, the task is the same. If printing the title can be seen as a part of printing the slice, the title too can be passed as a parameter. Here are the new changes: +) + +--- +void print($(HILITE string title,) int[] slice) { + $(HILITE writeln(title, ":");) + + foreach (i, element; slice) { + writefln("%3s:%5s", i, element); + } +} + +// ... + + // Print the numbers + print($(HILITE "Before sorting"), numbers); + +// ... + + // Print the numbers + print($(HILITE "After sorting"), numbers); +--- + +$(P +This step has the added benefit of obviating the comments that appear right before the two $(C print()) calls. Since the name of the function already clearly communicates what it does, those comments are unnecessary: +) + +--- + print("Before sorting", numbers); + sort(numbers); + print("After sorting", numbers); +--- + +$(P +Although subtle, there is more code duplication in this program: The values of $(C count) and $(C number) are read in exactly the same way. The only difference is the message that is printed to the user and the name of the variable: +) + +--- + int count; + write("How many numbers are you going to enter? "); + readf(" %s", &count); + +// ... + + int number; + write("Number ", i, "? "); + readf(" %s", &number); +--- + +$(P +The code would become even better if it took advantage of a new function that might be named appropriately as $(C readInt()). The new function can take the message as a parameter, print that message, read an $(C int) from the input, and return that $(C int): +) + +--- +int readInt(string message) { + int result; + write(message, "? "); + readf(" %s", &result); + return result; +} +--- + +$(P +$(C count) can now be initialized directly by the return value of a call to this new function: +) + +--- + int count = + readInt("How many numbers are you going to enter"); +--- + +$(P +$(C number) cannot be initialized in as straightforward a way because the loop counter $(C i) happens to be a part of the message that is displayed when reading $(C number). This can be overcome by taking advantage of $(C format): +) + +--- +import std.string; +// ... + int number = readInt(format("Number %s", i)); +--- + +$(P +Further, since $(C number) is used in only one place in the $(C foreach) loop, its definition can be eliminated altogether and the return value of $(C readInt()) can directly be used in its place: +) + +--- + foreach (i; 0 .. count) { + numbers ~= $(HILITE readInt)(format("Number %s", i)); + } +--- + +$(P +Let's make a final modification to this program by moving the lines that read the numbers to a separate function. This would also eliminate the need for the "Read the numbers" comment because the name of the new function would already carry that information. +) + +$(P +The new $(C readNumbers()) function does not need any parameter to complete its task. It reads some numbers and returns them as a slice. The following is the final version of the program: +) + +--- +import std.stdio; +import std.string; +import std.algorithm; + +void print(string title, int[] slice) { + writeln(title, ":"); + + foreach (i, element; slice) { + writefln("%3s:%5s", i, element); + } +} + +int readInt(string message) { + int result; + write(message, "? "); + readf(" %s", &result); + return result; +} + +int[] $(HILITE readNumbers)() { + int[] result; + + int count = + readInt("How many numbers are you going to enter"); + + foreach (i; 0 .. count) { + result ~= readInt(format("Number %s", i)); + } + + return result; +} + +void main() { + int[] numbers = readNumbers(); + print("Before sorting", numbers); + sort(numbers); + print("After sorting", numbers); +} +--- + +$(P +Compare this version of the program to the first one. The major steps of the program are very clear in the $(C main()) function of the new program. In contrast, the $(C main()) function of the first program had to be carefully examined to understand the purpose of that program. +) + +$(P +Although the total numbers of nontrivial lines of the two versions of the program ended up being equal in this example, functions make programs shorter in general. This effect is not apparent in this simple program. For example, before the $(C readInt()) function has been defined, reading an $(C int) from the input involved three lines of code. After the definition of $(C readInt()), the same goal is achieved by a single line of code. Further, the definition of $(C readInt()) allowed removing the definition of the variable $(C number) altogether. +) + +$(H6 Commented lines of code as functions) + +$(P +Sometimes the need to write a comment to describe the purpose of a group of lines of code is an indication that those lines could better be moved to a newly defined function. If the name of the function is descriptive enough then there will be no need for the comment either. +) + +$(P +The three commented groups of lines of the first version of the program have been used for defining new functions that achieved the same tasks. +) + +$(P +Another important benefit of removing comment lines is that comments tend to become outdated as the code gets modified over time. When updating code, programmers sometimes forget to update associated comments thus these comments become either useless or, even worse, misleading. For that reason, it is beneficial to try to write programs without the need for comments. +) + +$(PROBLEM_COK + +$(PROBLEM Modify the $(C printMenu()) function to take the entire set of menu items as a parameter. For example, the menu items can be passed to the function as in the following code: + +--- + string[] items = + [ "Black", "Red", "Green", "Blue", "White" ]; + printMenu(items, 1); +--- + +$(P +Have the program produce the following output: +) + +$(SHELL + 1 Black + 2 Red + 3 Green + 4 Blue + 5 White +) + +) + +$(PROBLEM +The following program uses a two dimensional array as a canvas. Start with that program and improve it by adding more functionality to it: + +--- +import std.stdio; + +enum totalLines = 20; +enum totalColumns = 60; + +/* The 'alias' in the next line makes 'Line' an alias of + * dchar[totalColumns]. Every 'Line' that is used in the rest + * of the program will mean dchar[totalColumns] from this + * point on. + * + * Also note that 'Line' is a fixed-length array. */ +alias Line = dchar[totalColumns]; + +/* A dynamic array of Lines is being aliased as 'Canvas'. */ +alias Canvas = Line[]; + +/* Prints the canvas line by line. */ +void print(Canvas canvas) { + foreach (line; canvas) { + writeln(line); + } +} + +/* Places a dot at the specified location on the canvas. In a + * sense, "paints" the canvas. */ +void putDot(Canvas canvas, int line, int column) { + canvas[line][column] = '#'; +} + +/* Draws a vertical line of the specified length from the + * specified position. */ +void drawVerticalLine(Canvas canvas, + int line, + int column, + int length) { + foreach (lineToPaint; line .. line + length) { + putDot(canvas, lineToPaint, column); + } +} + +void main() { + Line emptyLine = '.'; + + /* An empty canvas */ + Canvas canvas; + + /* Constructing the canvas by adding empty lines */ + foreach (i; 0 .. totalLines) { + canvas ~= emptyLine; + } + + /* Using the canvas */ + putDot(canvas, 7, 30); + drawVerticalLine(canvas, 5, 10, 4); + + print(canvas); +} +--- + +) + +) + +Macros: + TITLE=Functions + + DESCRIPTION=The function definitions in the D programming language + + KEYWORDS=d programming language tutorial book functions diff --git a/book/d.en/functions_more.d b/book/d.en/functions_more.d new file mode 100644 index 0000000000..e9f0b19f72 --- /dev/null +++ b/book/d.en/functions_more.d @@ -0,0 +1,959 @@ +Ddoc + +$(DERS_BOLUMU More Functions) + +$(P +Functions have been covered in the following chapters so far in the book: +) + +$(UL +$(LI $(LINK2 functions.html, Functions)) + +$(LI $(LINK2 function_parameters.html, Function Parameters)) + +$(LI $(LINK2 function_overloading.html, Function Overloading)) + +$(LI $(LINK2 lambda.html, Function Pointers, Delegates, and Lambdas)) + +) + +$(P +This chapter will cover more features of functions. +) + +$(H5 Return type attributes) + +$(P +Functions can be marked as $(C auto), $(C ref), $(C inout), and $(C auto ref). These attributes are about return types of functions. +) + +$(H6 $(IX auto, return type) $(IX auto function) $(C auto) functions) + +$(P +The return types of $(C auto) functions need not be specified: +) + +--- +$(HILITE auto) add(int first, double second) { + double result = first + second; + return result; +} +--- + +$(P +The return type is deduced by the compiler from the $(C return) expression. Since the type of $(C result) is $(C double), the return type of $(C add()) is $(C double). +) + +$(P +If there are more than one $(C return) statement, then the return type of the function is their $(I common type). (We have seen common type in $(LINK2 ternary.html, the Ternary Operator ?: chapter).) For example, because the common type of $(C int) and $(C double) is $(C double), the return type of the following $(C auto) function is $(C double) as well: +) + +--- +auto func(int i) { + if (i < 0) { + return i; // returns 'int' here + } + + return i * 1.5; // returns 'double' here +} + +void main() { + // The return type of the function is 'double' + auto result = func(42); + static assert(is (typeof(result) == $(HILITE double))); +} +--- + +$(H6 $(IX ref, return type) $(C ref) functions) + +$(P +Normally, the expression that is returned from a function is copied to the caller's context. $(C ref) specifies that the expression should be returned by-reference instead. +) + +$(P +For example, the following function returns the greater of its two parameters: +) + +--- +$(CODE_NAME greater)int greater(int first, int second) { + return (first > second) ? first : second; +} +--- + +$(P +Normally, both the parameters and the return value of that function are copied: +) + +--- +$(CODE_XREF greater)import std.stdio; + +void main() { + int a = 1; + int b = 2; + int result = greater(a, b); + result += 10; // ← neither a nor b changes + writefln("a: %s, b: %s, result: %s", a, b, result); +} +--- + +$(P +Because the return value of $(C greater()) is copied to $(C result), adding to $(C result) affects only that variable; neither $(C a) nor $(C b) changes: +) + +$(SHELL_SMALL +a: 1, b: 2, result: 12 +) + +$(P +$(C ref) parameters are passed by references instead of being copied. The same keyword has the same effect on return values: +) + +--- +$(HILITE ref) int greater($(HILITE ref) int first, $(HILITE ref) int second) { + return (first > second) ? first : second; +} +--- + +$(P +This time, the returned reference would be an alias to one of the arguments and mutating the returned reference would modify either $(C a) or $(C b): +) + +--- + int a = 1; + int b = 2; + greater(a, b) += 10; // ← either a or b changes + writefln("a: %s, b: %s", a, b); +--- + +$(P +Note that the returned reference is incremented directly. As a result, the greater of the two arguments changes: +) + +$(SHELL_SMALL +a: 1, b: $(HILITE 12) +) + +$(P +$(IX pointer) $(IX local variable) $(IX variable, local) $(B Local reference requires a pointer:) An important point is that although the return type is marked as $(C ref), $(C a) and $(C b) would still not change if the return value were assigned to a local variable: +) + +--- + int result = greater(a, b); + result += 10; // ← only result changes +--- + +$(P +Although $(C greater()) returns a reference to $(C a) or $(C b), that reference gets copied to the local variable $(C result), and again neither $(C a) nor $(C b) changes: +) + +$(SHELL_SMALL +a: 1, b: 2, result: 12 +) + +$(P +For $(C result) be a reference to $(C a) or $(C b), it has to be defined as a pointer: +) + +--- + int $(HILITE *) result = $(HILITE &)greater(a, b); + $(HILITE *)result += 10; + writefln("a: %s, b: %s, result: %s", a, b, $(HILITE *)result); +--- + +$(P +This time $(C result) would be a reference to either $(C a) or $(C b) and the mutation through it would affect the actual variable: +) + +$(SHELL_SMALL +a: 1, b: $(HILITE 12), result: 12 +) + +$(P +$(B It is not possible to return a reference to a local variable:) The $(C ref) return value is an alias to one of the arguments that start their lives even before the function is called. That means, regardless of whether a reference to $(C a) or $(C b) is returned, the returned reference refers to a variable that is still alive. +) + +$(P +Conversely, it is not possible to return a reference to a variable that is not going to be alive upon leaving the function: +) + +--- +$(HILITE ref) string parenthesized(string phrase) { + string result = '(' ~ phrase ~ ')'; + return result; $(DERLEME_HATASI) +} // ← the lifetime of result ends here +--- + +$(P +The lifetime of local $(C result) ends upon leaving the function. For that reason, it is not possible to return a reference to that variable: +) + +$(SHELL_SMALL +Error: escaping $(HILITE reference to local variable) result +) + +$(H6 $(IX auto ref, return type) $(C auto ref) functions) + +$(P +$(C auto ref) helps with functions like $(C parenthesized()) above. Similar to $(C auto), the return type of an $(C auto ref) function is deduced by the compiler. Additionally, if the returned expression can be a reference, that variable is returned by reference as opposed to being copied. +) + +$(P +$(C parenthesized()) can be compiled if the return type is $(C auto ref): +) + +--- +$(HILITE auto ref) string parenthesized(string phrase) { + string result = '(' ~ phrase ~ ')'; + return result; // ← compiles +} +--- + +$(P +The very first $(C return) statement of the function determines whether the function returns a copy or a reference. +) + +$(P +$(C auto ref) is more useful in function templates where template parameters may be references or copies depending on context. +) + +$(H6 $(IX inout, return type) $(C inout) functions) + +$(P +The $(C inout) keyword appears for parameter and return types of functions. It works like a template for $(C const), $(C immutable), and $(I mutable). +) + +$(P +Let's rewrite the previous function as taking $(C string) (i.e. $(C immutable(char)[])) and returning $(C string): +) + +--- +string parenthesized(string phrase) { + return '(' ~ phrase ~ ')'; +} + +// ... + + writeln(parenthesized("hello")); +--- + +$(P +As expected, the code works with that $(C string) argument: +) + +$(SHELL_SMALL +(hello) +) + +$(P +However, as it works only with $(C immutable) strings, the function can be seen as being less useful than it could have been: +) + +--- + char[] m; // has mutable elements + m ~= "hello"; + writeln(parenthesized(m)); $(DERLEME_HATASI) +--- + +$(SHELL_SMALL +Error: function deneme.parenthesized ($(HILITE string) phrase) +is not callable using argument types ($(HILITE char[])) +) + +$(P +The same limitation applies to $(C const(char)[]) strings as well. +) + +$(P +One solution for this usability issue is to overload the function for $(C const) and $(I mutable) strings: +) + +--- +char[] parenthesized(char[] phrase) { + return '(' ~ phrase ~ ')'; +} + +const(char)[] parenthesized(const(char)[] phrase) { + return '(' ~ phrase ~ ')'; +} +--- + +$(P +That design would be less than ideal due to the obvious code duplications. Another solution would be to define the function as a template: +) + +--- +T parenthesized(T)(T phrase) { + return '(' ~ phrase ~ ')'; +} +--- + +$(P +Although that would work, this time it may be seen as being too flexible and potentially requiring template constraints. +) + +$(P +$(C inout) is very similar to the template solution. The difference is that not the entire type but just the mutability attribute is deduced from the parameter: +) + +--- +$(HILITE inout)(char)[] parenthesized($(HILITE inout)(char)[] phrase) { + return '(' ~ phrase ~ ')'; +} +--- + +$(P +$(C inout) transfers the deduced mutability attribute to the return type. +) + +$(P +When the function is called with $(C char[]), it gets compiled as if $(C inout) is not specified at all. On the other hand, when called with $(C immutable(char)[]) or $(C const(char)[]), $(C inout) means $(C immutable) or $(C const), respectively. +) + +$(P +The following code demonstrates this by printing the type of the returned expression: +) + +--- + char[] m; + writeln(typeof(parenthesized(m)).stringof); + + const(char)[] c; + writeln(typeof(parenthesized(c)).stringof); + + immutable(char)[] i; + writeln(typeof(parenthesized(i)).stringof); +--- + +$(P +The output: +) + +$(SHELL_SMALL +char[] +const(char)[] +string +) + +$(H5 Behavioral attributes) + +$(P +$(C pure), $(C nothrow), and $(C @nogc) are about function behaviors. +) + +$(H6 $(IX pure) $(C pure) functions) + +$(P +As we have seen in $(LINK2 functions.html, the Functions chapter), functions can produce return values and side effects. When possible, return values should be preferred over side effects because functions that do not have side effects are easier to make sense of, which in turn helps with program correctness and maintainability. +) + +$(P +A similar concept is the purity of a function. Purity is defined differently in D from most other programming languages: In D, a function that does not access $(I mutable) global or $(C static) state is pure. (Since input and output streams are considered as mutable global state, pure functions cannot perform input or output operations either.) +) + +$(P +In other words, a function is pure if it produces its return value and side effects only by accessing its parameters, local variables, and $(I immutable) global state. +) + +$(P +An important aspect of purity in D is that pure functions can mutate their parameters. +) + +$(P +Additionally, the following operations that mutate the global state of the program are explicitly allowed in pure functions: +) + +$(UL +$(LI Allocate memory with the $(C new) expression) +$(LI Terminate the program) +$(LI Access the floating point processing flags) +$(LI Throw exceptions) +) + +$(P +The $(C pure) keyword specifies that a function should behave according to those conditions and the compiler guarantees that it does so. +) + +$(P +Naturally, since impure functions do not provide the same guarantees, a pure function cannot call impure functions. +) + +$(P +The following program demonstrates some of the operations that a pure function can and cannot perform: +) + +--- +import std.stdio; +import std.exception; + +int mutableGlobal; +const int constGlobal; +immutable int immutableGlobal; + +void impureFunction() { +} + +int pureFunction(ref int i, int[] slice) $(HILITE pure) { + // Can throw exceptions: + enforce(slice.length >= 1); + + // Can mutate its parameters: + i = 42; + slice[0] = 43; + + // Can access immutable global state: + i = constGlobal; + i = immutableGlobal; + + // Can use the new expression: + auto p = new int; + + // Cannot access mutable global state: + i = mutableGlobal; $(DERLEME_HATASI) + + // Cannot perform input and output operations: + writeln(i); $(DERLEME_HATASI) + + static int mutableStatic; + + // Cannot access mutable static state: + i = mutableStatic; $(DERLEME_HATASI) + + // Cannot call impure functions: + impureFunction(); $(DERLEME_HATASI) + + return 0; +} + +void main() { + int i; + int[] slice = [ 1 ]; + pureFunction(i, slice); +} +--- + +$(P +Although they are allowed to, some pure functions do not mutate their parameters. Following from the rules of purity, the only observable effect of such a function would be its return value. Further, since the function cannot access any mutable global state, the return value would be the same for a given set of arguments, regardless of when and how many times the function is called during the execution of the program. This fact gives both the compiler and the programmer optimization opportunities. For example, instead of calling the function a second time for a given set of arguments, its return value from the first call can be cached and used instead of actually calling the function again. +) + +$(P +$(IX inference, pure attribute) $(IX attribute inference, pure) Since the exact code that gets generated for a template instantiation depends on the actual template arguments, whether the generated code is pure depends on the arguments as well. For that reason, the purity of a template is inferred by the compiler from the generated code. (The $(C pure) keyword can still be specified by the programmer.) Similarly, the purity of an $(C auto) function is inferred. +) + +$(P +As a simple example, since the following function template would be impure when $(C N) is zero, it would not be possible to call $(C templ!0()) from a pure function: +) + +--- +import std.stdio; + +// This template is impure when N is zero +void templ(size_t N)() { + static if (N == 0) { + // Prints when N is zero: + writeln("zero"); + } +} + +void foo() $(HILITE pure) { + templ!0(); $(DERLEME_HATASI) +} + +void main() { + foo(); +} +--- + +$(P +The compiler infers that the $(C 0) instantiation of the template is impure and rejects calling it from the pure function $(C foo()): +) + +$(SHELL_SMALL +Error: pure function 'deneme.foo' $(HILITE cannot call impure function) +'deneme.templ!0.templ' +) + +$(P +However, since the instantiation of the template for values other than zero is pure, the program can be compiled for such values: +) + +--- +void foo() $(HILITE pure) { + templ!1(); // ← compiles +} +--- + +$(P +We have seen earlier above that input and output functions like $(C writeln()) cannot be used in pure functions because they access global state. Sometimes such limitations are too restrictive e.g. when needing to print a message temporarily during debugging. For that reason, the purity rules are relaxed for code that is marked as $(C debug): +) + +--- +import std.stdio; + +debug size_t fooCounter; + +void foo(int i) $(HILITE pure) { + $(HILITE debug) ++fooCounter; + + if (i == 0) { + $(HILITE debug) writeln("i is zero"); + i = 42; + } + + // ... +} + +void main() { + foreach (i; 0..100) { + if ((i % 10) == 0) { + foo(i); + } + } + + debug writefln("foo is called %s times", fooCounter); +} +--- + +$(P +The pure function above mutates the global state of the program by modifying a global variable and printing a message. Despite those impure operations, it still can be compiled because those operations are marked as $(C debug). +) + +$(P +$(I $(B Note:) Remember that those statements are included in the program only if the program is compiled with the $(C -debug) command line switch.) +) + +$(P +Member functions can be marked as $(C pure) as well. Subclasses can override impure functions as $(C pure) but the reverse is not allowed: +) + +--- +interface Iface { + void foo() pure; // Subclasses must define foo as pure. + + void bar(); // Subclasses may define bar as pure. +} + +class Class : Iface { + void foo() pure { // Required to be pure + // ... + } + + void bar() pure { // pure although not required + // ... + } +} +--- + +$(P +Delegates and anonymous functions can be pure as well. Similar to templates, whether a function or delegate literal, or $(C auto) function is pure is inferred by the compiler: +) + +--- +import std.stdio; + +void foo(int delegate(double) $(HILITE pure) dg) { + int i = dg(1.5); +} + +void main() { + foo(a => 42); // ← compiles + + foo((a) { $(DERLEME_HATASI) + writeln("hello"); + return 42; + }); +} +--- + +$(P +$(C foo()) above requires that its parameter be a pure delegate. The compiler infers that the lambda $(C a => 42) is pure and allows it as an argument for $(C foo()). However, since the other delegate is impure it cannot be passed to $(C foo()): +) + +$(SHELL_SMALL +Error: function deneme.foo (int delegate(double) $(HILITE pure) dg) +is $(HILITE not callable) using argument types (void) +) + +$(P +One benefit of $(C pure) functions is that their return values can be used to initialize $(C immutable) variables. Although the array produced by $(C makeNumbers()) below is mutable, it is not possible for its elements to be changed by any code outside of that function. For that reason, the initialization works. +) + +--- +int[] makeNumbers() pure { + int[] result; + result ~= 42; + return result; +} + +void main() { + $(HILITE immutable) array = makeNumbers(); +} +--- + +$(H6 $(IX nothrow) $(IX throw) $(C nothrow) functions) + +$(P +We saw the exception mechanism in $(LINK2 exceptions.html, the Exceptions chapter.) +) + +$(P +It would be good practice for functions to document the types of exceptions that they may throw under specific error conditions. However, as a general rule, callers should assume that any function can throw any exception. +) + +$(P +Sometimes it is more important to know that a function does not emit any exception at all. For example, some algorithms can take advantage of the fact that certain of their steps cannot be interrupted by an exception. +) + +$(P +$(C nothrow) guarantees that a function does not emit any exception: +) + +--- +int add(int lhs, int rhs) $(HILITE nothrow) { + // ... +} +--- + +$(P +$(I $(B Note:) Remember that it is not recommended to catch $(C Error) nor its base class $(C Throwable). What is meant here by "any exception" is "any exception that is defined under the $(C Exception) hierarchy." A $(C nothrow) function can still emit exceptions that are under the $(C Error) hierarchy, which represents irrecoverable error conditions that should preclude the program from continuing its execution.) +) + +$(P +Such a function can neither throw an exception itself nor can call a function that may throw an exception: +) + +--- +int add(int lhs, int rhs) nothrow { + writeln("adding"); $(DERLEME_HATASI) + return lhs + rhs; +} +--- + +$(P +The compiler rejects the code because $(C add()) violates the no-throw guarantee: +) + +$(SHELL_SMALL +Error: function 'deneme.add' is nothrow yet $(HILITE may throw) +) + +$(P +This is because $(C writeln) is not (and cannot be) a $(C nothrow) function. +) + +$(P +$(IX inference, nothrow attribute) $(IX attribute inference, nothrow) The compiler can infer that a function can never emit an exception. The following implementation of $(C add()) is $(C nothrow) because it is obvious to the compiler that the $(C try-catch) block prevents any exception from escaping the function: +) + +--- +int add(int lhs, int rhs) nothrow { + int result; + + try { + writeln("adding"); // ← compiles + result = lhs + rhs; + + } catch (Exception error) { // catches all exceptions + // ... + } + + return result; +} +--- + +$(P +As mentioned above, $(C nothrow) does not include exceptions that are under the $(C Error) hierarchy. For example, although accessing an element of an array with $(C []) can throw $(C RangeError), the following function can still be defined as $(C nothrow): +) + +--- +int foo(int[] arr, size_t i) $(HILITE nothrow) { + return 10 * arr$(HILITE [i]); +} +--- + +$(P +As with purity, the compiler automatically deduces whether a template, delegate, or anonymous function is $(C nothrow). +) + +$(H6 $(IX @nogc) $(C @nogc) functions) + +$(P +D is a garbage collected language. Many data structures and algorithms in most D programs take advantage of dynamic memory blocks that are managed by the garbage collector (GC). Such memory blocks are reclaimed again by the GC by an algorithm called $(I garbage collection). +) + +$(P +Some commonly used D operations take advantage of the GC as well. For example, elements of arrays live on dynamic memory blocks: +) + +--- +// A function that takes advantage of the GC indirectly +int[] append(int[] slice) { + slice $(HILITE ~=) 42; + return slice; +} +--- + +$(P +If the slice does not have sufficient capacity, the $(C ~=) operator above allocates a new memory block from the GC. +) + +$(P +Although the GC is a significant convenience for data structures and algorithms, memory allocation and garbage collection are costly operations that make the execution of some programs noticeably slow. +) + +$(P +$(C @nogc) means that a function cannot use the GC directly or indirectly: +) + +--- +void foo() $(HILITE @nogc) { + // ... +} +--- + +$(P +The compiler guarantees that a $(C @nogc) function does not involve GC operations. For example, the following function cannot call $(C append()) above, which does not provide the $(C @nogc) guarantee: +) + +--- +void foo() $(HILITE @nogc) { + int[] slice; + // ... + append(slice); $(DERLEME_HATASI) +} +--- + +$(SHELL_SMALL +Error: @nogc function 'deneme.foo' $(HILITE cannot call non-@nogc function) +'deneme.append' +) + +$(H5 Code safety attributes) + +$(P +$(IX inference, @safe attribute) $(IX attribute inference, @safe) $(C @safe), $(C @trusted), and $(C @system) are about the code safety that a function provides. As with purity, the compiler infers the safety level of templates, delegates, anonymous functions, and $(C auto) functions. +) + +$(H6 $(IX @safe) $(C @safe) functions) + +$(P +A class of programming errors involve $(I corrupting) data at unrelated locations in memory by writing at those locations unintentionally. Such errors are mostly due to mistakes made in using pointers and applying type casts. +) + +$(P +$(C @safe) functions guarantee that they do not contain any operation that may corrupt memory. The compiler does not allow the following operations in $(C @safe) functions: +) + +$(UL + +$(LI Pointers cannot be converted to other pointer types other than $(C void*).) + +$(LI A non-pointer expression cannot be converted to a pointer value.) + +$(LI Pointer values cannot be changed (no pointer $(I arithmetic); however, assigning a pointer to another pointer of the same type is safe).) + +$(LI Unions that have pointer or reference members cannot be used.) + +$(LI Functions marked as $(C @system) cannot be called.) + +$(LI Exceptions that are not descended from $(C Exception) cannot be caught.) + +$(LI $(I Inline assembler) cannot be used.) + +$(LI $(I Mutable) variables cannot be cast to $(C immutable).) + +$(LI $(C immutable) variables cannot be cast to $(I mutable).) + +$(LI Thread-local variables cannot be cast to $(C shared).) + +$(LI $(C shared) variables cannot be cast to thread-local.) + +$(LI Addresses of function-local variables cannot be taken.) + +$(LI $(C __gshared) variables cannot be accessed.) + +) + +$(H6 $(IX @trusted) $(C @trusted) functions) + +$(P +Some functions may actually be safe but cannot be marked as $(C @safe) for various reasons. For example, a function may have to call a library written in C, where no language support exists for safety in that language. +) + +$(P +Some other functions may actually perform operations that are not allowed in $(C @safe) code, but may be well tested and $(I trusted) to be correct. +) + +$(P +$(C @trusted) is an attribute that communicates to the compiler that $(I although the function cannot be marked as $(C @safe), consider it safe). The compiler trusts the programmer and treats $(C @trusted) code as if it is safe. For example, it allows $(C @safe) code to call $(C @trusted) code. +) + +$(H6 $(IX @system) $(C @system) functions) + +$(P +Any function that is not marked as $(C @safe) or $(C @trusted) is considered $(C @system), which is the default safety attribute. +) + +$(H5 $(IX CTFE) $(IX compile time function execution) Compile time function execution (CTFE)) + +$(P +In many programming languages, computations that are performed at compile time are very limited. Such computations are usually as simple as calculating the length of a fixed-length array or simple arithmetic operations: +) + +--- + writeln(1 + 2); +--- + +$(P +The $(C 1 + 2) expression above is compiled as if it has been written as $(C 3); there is no computation at runtime. +) + +$(P +D has CTFE, which allows any function to be executed at compile time as long as it is possible to do so. +) + +$(P +Let's consider the following program that prints a menu to the output: +) + +--- +import std.stdio; +import std.string; +import std.range; + +string menuLines(string[] choices) { + string result; + + foreach (i, choice; choices) { + result ~= format(" %s. %s\n", i + 1, choice); + } + + return result; +} + +string menu(string title, + string[] choices, + size_t width) { + return format("%s\n%s\n%s", + title.center(width), + '='.repeat(width), // horizontal line + menuLines(choices)); +} + +void main() { + $(HILITE enum) drinks = + menu("Drinks", + [ "Coffee", "Tea", "Hot chocolate" ], 20); + + writeln(drinks); +} +--- + +$(P +Although the same result can be achieved in different ways, the program above performs non-trivial operations to produce the following $(C string): +) + +$(SHELL_SMALL + Drinks +==================== + 1. Coffee + 2. Tea + 3. Hot chocolate +) + +$(P +Remember that the initial value of $(C enum) constants like $(C drinks) must be known at compile time. That fact is sufficient for $(C menu()) to be executed at compile time. The value that it returns at compile time is used as the initial value of $(C drinks). As a result, the program is compiled as if that value is written explicitly in the program: +) + +--- + // The equivalent of the code above: + enum drinks = " Drinks \n" + "====================\n" + " 1. Coffee\n" + " 2. Tea\n" + " 3. Hot chocolate\n"; +--- + +$(P +For a function to be executed at compile time, it must appear in an expression that in fact is needed at compile time: +) + +$(UL +$(LI Initializing a $(C static) variable) +$(LI Initializing an $(C enum) variable) +$(LI Calculating the length of a fixed-length array) +$(LI Calculating a template $(I value) argument) +) + +$(P +Clearly, it would not be possible to execute every function at compile time. For example, a function that accesses a global variable cannot be executed at compile time because the global variable does not start its life until run time. Similarly, since $(C stdout) is available only at run time, functions that print cannot be executed at compile time. +) + +$(H6 $(IX __ctfe) The $(C __ctfe) variable) + +$(P +It is a powerful aspect of CTFE that the same function is used for both compile time and run time depending on when its result is needed. Although the function need not be written in any special way for CTFE, some operations in the function may make sense only at compile time or run time. The special variable $(C __ctfe) can be used to differentiate the code that are only for compile time or only for run time. The value of this variable is $(C true) when the function is being executed for CTFE, $(C false) otherwise: +) + +--- +import std.stdio; + +size_t counter; + +int foo() { + if (!$(HILITE __ctfe)) { + // This code is for execution at run time + ++counter; + } + + return 42; +} + +void main() { + enum i = foo(); + auto j = foo(); + writefln("foo is called %s times.", counter); +} +--- + +$(P +As $(C counter) lives only at run time, it cannot be incremented at compile time. For that reason, the code above attempts to increment it only for run-time execution. Since the value of $(C i) is determined at compile time and the value of $(C j) is determined at run time, $(C foo()) is reported to have been called just once during the execution of the program: +) + +$(SHELL_SMALL +foo is called 1 times. +) + +$(H5 Summary) + +$(UL + +$(LI The return type of an $(C auto) function is deduced automatically.) + +$(LI The return value of a $(C ref) function is a reference to an existing variable.) + +$(LI The return value of an $(C auto ref) function is a reference if possible, a copy otherwise.) + +$(LI $(C inout) carries the $(C const), $(C immutable), or $(I mutable) attribute of the parameter to the return type.) + +$(LI A $(C pure) function cannot access $(I mutable) global or static state. The compiler infers the purity of templates, delegates, anonymous functions, and $(C auto) functions.) + +$(LI $(C nothrow) functions cannot emit exceptions. The compiler infers whether a template, delegate, anonymous function, or $(C auto) function is no-throw.) + +$(LI $(C @nogc) functions cannot involve GC operations.) + +$(LI $(C @safe) functions cannot corrupt memory. The compiler infers the safety attributes of templates, delegates, anonymous functions, and $(C auto) functions.) + +$(LI $(C @trusted) functions are indeed safe but cannot be specified as such; they are considered $(C @safe) both by the programmer and the compiler.) + +$(LI $(C @system) functions can use every D feature. $(C @system) is the default safety attribute.) + +$(LI Functions can be executed at compile time as well (CTFE). This can be differentiated by the value of the special variable $(C __ctfe).) + +) + +Macros: + TITLE=More Functions + + DESCRIPTION=Additional features of D functions that have not been mentioned up to this point: Automatic return type deduction, purity, not throwing exceptions, memory safety, and CTFE. + + KEYWORDS=d programming language tutorial book auto ref pure ctfe diff --git a/book/d.en/goto.d b/book/d.en/goto.d new file mode 100644 index 0000000000..861cc0cfee --- /dev/null +++ b/book/d.en/goto.d @@ -0,0 +1,263 @@ +Ddoc + +$(DERS_BOLUMU $(IX label) $(IX goto) Labels and $(CH4 goto)) + +$(P +$(IX :, label) Labels are names given to lines of code in order to direct program flow to those lines later on. +) + +$(P +A label consists of a name and the $(C :) character: +) + +--- +end: // ← a label +--- + +$(P +That label gives the name $(I end) to the line that it is defined on. +) + +$(P +$(I $(B Note:) In reality, a label can appear between statements on the same line to name the exact spot that it appears at, but this is not a common practice:) +) + +--- + anExpression(); $(HILITE end:) anotherExpression(); +--- + +$(H5 $(C goto)) + +$(P +$(C goto) directs program flow to the specified label: +) + +--- +void foo(bool condition) { + writeln("first"); + + if (condition) { + $(HILITE goto) end; + } + + writeln("second"); + +end: + + writeln("third"); +} +--- + +$(P +When $(C condition) is $(C true), the program flow $(I goes to) label $(C end), effectively skipping the line that prints "second": +) + +$(SHELL_SMALL +first +third +) + +$(P +$(C goto) works the same way as in the C and C++ programming languages. Being notorious for making it hard to understand the intent and flow of code, $(C goto) is discouraged even in those languages. Statements like $(C if), $(C while), $(C for) etc. should be used instead. +) + +$(P +For example, the previous code can be written without $(C goto) in a more $(I structured) way: +) + +--- +void foo(bool condition) { + writeln("first"); + + if (!condition) { + writeln("second"); + } + + writeln("third"); +} +--- + +$(P +However, there are two acceptable uses of $(C goto) in C, none of which is necessary in D. +) + +$(H6 Finalization area) + +$(P +One of the valid uses of $(C goto) in C is going to the finalization area where the cleanup operations of a function are performed (e.g. giving resources back, undoing certain operations, etc.): +) + +$(C_CODE +// --- C code --- + +int foo() { + // ... + + if (error) { + goto finally; + } + + // ... + +finally: + $(COMMENT // ... cleanup operations ...) + + return error; +} +) + +$(P +This use of $(C goto) is not necessary in D because there are other ways of managing resources: the garbage collector, destructors, the $(C catch) and $(C finally) blocks, $(C scope()) statements, etc. +) + +$(P $(I $(B Note:) This use of $(C goto) is not necessary in C++ either.) +) + +$(H6 $(C continue) and $(C break) for outer loops) + +$(P +The other valid use of $(C goto) in C is about outer loops. +) + +$(P +Since $(C continue) and $(C break) affect only the inner loop, one way of continuing or breaking out of the outer loop is by $(C goto) statements: +) + +$(C_CODE +// --- C code --- + + while (condition) { + + while (otherCondition) { + + $(COMMENT // affects the inner loop) + continue; + + $(COMMENT // affects the inner loop) + break; + + $(COMMENT // works like 'continue' for the outer loop) + goto continueOuter; + + $(COMMENT // works like 'break' for the outer loop) + goto breakOuter; + } + + continueOuter: + ; + } +breakOuter: +) + +$(P +The same technique can be used for outer $(C switch) statements as well. +) + +$(P +This use of $(C goto) is not needed in D because D has loop labels, which we will see below. +) + +$(P $(I $(B Note:) This use of $(C goto) can be encountered in C++ as well.) +) + +$(H6 The problem of skipping constructors) + +$(P +The constructor is called on an object exactly where that object is defined. This is mainly because the information that is needed to construct an object is usually not available until that point. Also, there is no need to construct an object if that object is not going to be used in the program at all. +) + +$(P +When $(C goto) skips a line that an object is constructed on, the program can be using an object that has not been prepared yet: +) + +--- + if (condition) { + goto aLabel; // skips the constructor + } + + auto s = S(42); // constructs the object properly + +aLabel: + + s.bar(); // BUG: 's' may not be ready for use +--- + +$(P +The compiler prevents this bug: +) + +$(SHELL +Error: goto skips declaration of variable deneme.main.s +) + +$(H5 $(IX loop label) Loop labels) + +$(P +Loops can have labels and $(C goto) statements can refer to those labels: +) + +--- +$(HILITE outerLoop:) + while (condition) { + + while (otherCondition) { + + // affects the inner loop + continue; + + // affects the inner loop + break; + + // continues the outer loop + continue $(HILITE outerLoop); + + // breaks the outer loop + break $(HILITE outerLoop); + } + } +--- + +$(P +$(C switch) statements can have labels as well. An inner $(C break) statement can refer to an outer $(C switch) to break out of the outer $(C switch) statement. +) + +$(H5 $(C goto) in $(C case) sections) + +$(P +We have already seen the use of $(C goto) in $(C case) sections in $(LINK2 switch_case.html, the $(C switch) and $(C case) chapter): +) + +$(UL + +$(LI $(IX goto case) $(IX case, goto) $(C goto case) causes the execution to continue to the next $(C case).) + +$(LI $(IX goto default) $(IX default, goto) $(C goto default) causes the execution to continue to the $(C default) section.) + +$(LI $(C goto case $(I expression)) causes the execution to continue to the $(C case) that matches that expression.) + +) + +$(H5 Summary) + +$(UL + +$(LI +Some of the uses of $(C goto) are not necessary in D. +) + +$(LI +$(C break) and $(C continue) can specify labels to affect outer loops and $(C switch) statements. +) + +$(LI +$(C goto) inside $(C case) sections can make the program flow jump to other $(C case) and $(C default) sections. +) + +) + +Macros: + TITLE=Labels and goto + + DESCRIPTION=Labels that are used for giving names to code lines, and goto that causes program flow to jump to those lines. + + KEYWORDS=d programming language tutorial book goto diff --git a/book/d.en/hello_world.cozum.d b/book/d.en/hello_world.cozum.d new file mode 100644 index 0000000000..69eeed3e18 --- /dev/null +++ b/book/d.en/hello_world.cozum.d @@ -0,0 +1,52 @@ +Ddoc + +$(COZUM_BOLUMU The Hello World Program) + +$(OL + +$(LI + +--- +import std.stdio; + +void main() { + writeln("Something else... :p"); +} +--- + +) + +$(LI + +--- +import std.stdio; + +void main() { + writeln("A line..."); + writeln("Another line..."); +} +--- + +) + +$(LI + +The following program cannot be compiled because the semicolon at the end of the $(C writeln) line is missing: + +--- +import std.stdio; + +void main() { + writeln("Hello, World!") $(DERLEME_HATASI) +} +--- +) + +) + +Macros: + TITLE=The Hello World Program Solutions + + DESCRIPTION=The exercise solutions for the first D program: Hello World! + + KEYWORDS=programming in d tutorial hello world program exercise solution diff --git a/book/d.en/hello_world.d b/book/d.en/hello_world.d new file mode 100644 index 0000000000..97ce0aef46 --- /dev/null +++ b/book/d.en/hello_world.d @@ -0,0 +1,215 @@ +Ddoc + +$(DIV_CLASS page_one, + +$(DERS_BOLUMU $(IX hello world) The Hello World Program) + +$(P +The first program to show in most programming language books is the $(I hello world) program. This very short and simple program merely writes "Hello, World!" and finishes. This program is important because it includes some of the essential concepts of that language. +) + +$(P +Here is a $(I hello world) program in D: +) + +--- +import std.stdio; + +void main() { + writeln("Hello, World!"); +} +--- + +$(P +The $(I source code) above needs to be compiled by a D compiler to produce an executable program. +) + +$(H5 $(IX compiler installation) $(IX installation, compiler) Compiler installation) + +$(P +$(IX gdc) $(IX ldc) At the time of writing this chapter, there are three D compilers to choose from: $(C dmd), the Digital Mars compiler; $(C gdc), the D compiler of GCC; and $(C ldc), the D compiler that targets the LLVM compiler infrastructure. +) + +$(P +$(IX dmd) $(C dmd) is the D compiler that has been used during the design and development of the language over the years. All of the examples in this book have been tested with $(C dmd). For that reason, it would be the easiest for you to start with $(C dmd) and try other compilers only if you have a specific need to. The code samples in this book were compiled with $(C dmd) version $(DVER). +) + +$(P +To install the latest version of $(C dmd), go to the $(LINK2 http://www.dlang.org/download.html, download page at Digital Mars) and select the compiler build that matches your computer environment. You must select the $(C dmd) build that is for your operating system and package management system, and whether you have a 32-bit or a 64-bit CPU and operating system. Do not install a D1 compiler. This book covers only $(I D version two). +) + +$(P +The installation steps are different on different environments but it should be as easy as following simple on-screen instructions and clicking a couple of buttons. +) + +$(H5 $(IX source file) Source file) + +$(P +The file that the programmer writes for the D compiler to compile is called the $(I source file). Since D is usually used as a compiled language, the source file itself is not an executable program. The source file must be converted to an executable program by the compiler. +) + +$(P +As with any file, the source file must have a name. Although the name can be anything that is legal on the file system, it is customary to use the $(C .d) $(I file extension) for D source files because development environments, programming tools, and programmers all expect this to be the case. For example, $(C test.d), $(C game.d), $(C invoice.d), etc. are appropriate D source file names. +) + +$(H5 Compiling the hello world program) + +$(P +$(IX text editor) $(IX editor, text) You will write the source file in a $(LINK2 http://wiki.dlang.org/Editors, text editor) (or an $(I IDE) as mentioned below). Copy or type the hello world program above into a text file and save it under the name $(C hello.d). +) + +$(P +The compiler will soon check that the syntax of this source code is correct (i.e. it is valid according to the language rules) and make a program out of it by translating it into machine code. Follow these steps to compile the program: +) + +$(OL + +$(LI Open a terminal window.) + +$(LI Go to the directory where you saved $(C hello.d).) + +$(LI Enter the following command. (Do not type the $(C $) character; it is there to indicate the command line prompt.)) + +) + +$(SHELL +$(SHELL_OBSERVED $) dmd hello.d +) + +$(P +If you did not make any mistake, you may think that nothing has happened. To the contrary, it means that everything went well. There should be an executable file named $(C hello) (or $(C hello.exe) under Windows) that has just been created by the compiler. +) + +$(P +If the compiler has instead printed some messages, you probably have made a mistake when copying the program code. Try to identify the mistake, correct it, and retry compiling. You will routinely make many mistakes when programming, so the process of correcting and compiling will become familiar to you. +) + +$(P +Once the program has been created successfully, type the name of the executable program to run it. You should see that the program prints "Hello, World!": +) + +$(SHELL +$(SHELL_OBSERVED $) ./hello $(SHELL_NOTE running the program) +Hello, World! $(SHELL_NOTE the message that it prints) +) + +$(P +Congratulations! Your first D program works as expected. +) + +$(H5 $(IX compiler switch) Compiler switches) + +$(P +The compiler has many command line switches that are used for influencing how it compiles the program. To see a list of compiler switches enter just the name of the compiler: +) + +$(SHELL +$(SHELL_OBSERVED $) dmd $(SHELL_NOTE enter just the name) +DMD64 D Compiler v$(DVER) +... + -de show use of deprecated features as errors (halt compilation) +... + -unittest compile in unit tests +... + -w warnings as errors (compilation will halt) +... +) + +$(P +The abbreviated output above shows only the command line switches that I recommend that you always use. Although it makes no difference with the hello world program in this chapter, the following command line would compile the program by enabling unit tests and not allowing any warnings or deprecated features. We will see these and other switches in more detail in later chapters: +) + +$(SHELL +$(SHELL_OBSERVED $) dmd hello.d -de -w -unittest +) + +$(P +The complete list of $(C dmd) command line switches can be found in the $(LINK2 http://dlang.org/dmd-linux.html, DMD Compiler documentation). +) + +$(P +One other command line switch that you may find useful is $(C -run). It compiles the source code, produces the executable program, and runs it with a single command. $(C -run) must be the last of compiler switches, specified right before the name of the source file: +) + +$(SHELL +$(SHELL_OBSERVED $) dmd -de -w -unittest $(HILITE -run) hello.d +Hello, World! $(SHELL_NOTE the program is automatically executed) +) + +$(H5 $(IX IDE) IDE) + +$(P +In addition to the compiler, you may also consider installing an IDE (integrated development environment). IDEs are designed to make program development easier by simplifying the steps of writing, compiling, and debugging. +) + +$(P +If you do install an IDE, compiling and running the program will be as simple as pressing a key or clicking a button on the IDE. I still recommend that you familiarize yourself with compiling programs manually in a terminal window. +) + +$(P +If you decide to install an IDE, go to $(LINK2 http://wiki.dlang.org/IDEs, the IDEs page at dlang.org) to see a list of available IDEs. +) + +$(H5 Contents of the hello world program) + +$(P +Here is a quick list of the many D concepts that have appeared in this short program: +) + +$(P $(B Core feature): Every language defines its syntax, fundamental types, keywords, rules, etc. All of these make the $(I core features) of that language. The parentheses, semicolons, and words like $(C main) and $(C void) are all placed according to the rules of D. These are similar to the rules of English: subject, verb, punctuation, sentence structure, etc. +) + +$(P $(B Library and function): The core features define only the structure of the language. They are used for defining functions and user types, and those in turn are used for building libraries. Libraries are collections of reusable program parts that get $(I linked) with your programs to help them achieve their purposes. +) + +$(P +$(C writeln) above is a $(I function) in D's standard $(I library). It is used for printing a line of text, as its name suggests: write line. +) + +$(P $(B Module): Library contents are grouped by types of tasks that they intend to help with. Such a group is called a module. The only module that this program uses is $(C std.stdio), which handles data input and output. +) + +$(P $(B Character and string): Expressions like $(STRING "Hello, World!") are called $(I strings), and the elements of strings are called $(I characters). The only string in this program contains characters $(STRING 'H'), $(STRING 'e'), $(STRING '!'), and others. +) + +$(P $(B Order of operations): Programs complete their tasks by executing operations in a certain order. These tasks start with the operations that are written in the function named $(C main). The only operation in this program writes "Hello world!". +) + +$(P $(B Significance of uppercase and lowercase letters): You can choose to type any character inside strings, but you must type the other characters exactly as they appear in the program. This is because lowercase vs. uppercase is significant in D programs. For example, $(C writeln) and $(C Writeln) are two different names. +) + +$(P +$(IX keyword) $(B Keyword): Special words that are a part of the core features of the language are $(I keywords). Such words are reserved for the language itself, and cannot be used for any other purpose in a D program. There are two keywords in this program: $(C import), which is used to introduce a module to the program; and $(C void), which here means "not returning anything". +) + +$(P +The complete list of D keywords is $(C abstract), $(C alias), $(C align), $(C asm), $(C assert), $(C auto), $(C body), $(C bool), $(C break), $(C byte), $(C case), $(C cast), $(C catch), $(C cdouble), $(C cent), $(C cfloat), $(C char), $(C class), $(C const), $(C continue), $(C creal), $(C dchar), $(C debug), $(C default), $(C delegate), $(C delete), $(C deprecated), $(C do), $(C double), $(C else), $(C enum), $(C export), $(C extern), $(C false), $(C final), $(C finally), $(C float), $(C for), $(C foreach), $(C foreach_reverse), $(C function), $(C goto), $(C idouble), $(C if), $(C ifloat), $(C immutable), $(C import), $(C in), $(C inout), $(C int), $(C interface), $(C invariant), $(C ireal), $(C is), $(C lazy), $(C long), $(C macro), $(C mixin), $(C module), $(C new), $(C nothrow), $(C null), $(C out), $(C override), $(C package), $(C pragma), $(C private), $(C protected), $(C public), $(C pure), $(C real), $(C ref), $(C return), $(C scope), $(C shared), $(C short), $(C static), $(C struct), $(C super), $(C switch), $(C synchronized), $(C template), $(C this), $(C throw), $(C true), $(C try), $(C typedef), $(C typeid), $(C typeof), $(C ubyte), $(C ucent), $(C uint), $(C ulong), $(C union), $(C unittest), $(C ushort), $(C version), $(C void), $(C volatile), $(C wchar), $(C while), $(C with), $(C __FILE__), $(C __FILE_FULL_PATH__), $(C __MODULE__), $(C __LINE__), $(C __FUNCTION__), $(C __PRETTY_FUNCTION__), $(C __gshared), $(C __traits), $(C __vector), and $(C __parameters). +) + +$(P +$(IX asm) $(IX body) $(IX __vector) $(IX delete) $(IX typedef) $(IX volatile) $(IX macro) We will cover these keywords in the upcoming chapters with the exception of the following ones: $(LINK2 http://dlang.org/statement.html#AsmStatement, $(C asm)) and $(LINK2 http://dlang.org/phobos/core_simd.html#.Vector, $(C __vector)) are outside of the scope of this book; $(C body), $(C delete), $(C typedef), and $(C volatile) are deprecated; and $(C macro) is unused by D at this time. +) + +$(PROBLEM_COK + +$(PROBLEM Make the program output something else.) + +$(PROBLEM Change the program to output more than one line. You can do this by adding one more $(C writeln) line to the program.) + +$(PROBLEM Try to compile the program after making other changes; e.g. remove the semicolon at the end of the line with $(C writeln) and observe a compilation error. +) + +) + +) + +$(Ergin) + +Macros: + TITLE=The Hello World Program + + DESCRIPTION=The first D program: Hello World! + + KEYWORDS=d programming language tutorial book + +SOZLER= diff --git a/book/d.en/if.cozum.d b/book/d.en/if.cozum.d new file mode 100644 index 0000000000..fa38f9c795 --- /dev/null +++ b/book/d.en/if.cozum.d @@ -0,0 +1,110 @@ +Ddoc + +$(COZUM_BOLUMU The if Statement) + +$(OL + +$(LI +The statement $(C writeln("Washing the plate")) is written indented as if to be within the $(C else) scope. However, because the scope of that $(C else) is not written with curly brackets, only the $(C writeln("Eating pie")) statement is actually inside the scope of that $(C else). + +$(P +Since whitespaces are not important in D programs, the $(I plate statement) is actually an independent statement within $(C main()) and is executed unconditionally. It confuses the reader as well because of having been indented more than usual. If the $(I plate statement) must really be within the $(C else) scope, there must be curly brackets around that scope: +) + +--- +import std.stdio; + +void main() { + bool existsLemonade = true; + + if (existsLemonade) { + writeln("Drinking lemonade"); + writeln("Washing the cup"); + + } else $(HILITE {) + writeln("Eating pie"); + writeln("Washing the plate"); + $(HILITE }) +} +--- + +) + +$(LI +We can come up with more than one design for the conditions of this game. I will show two examples. In the first one, we apply the information directly from the exercise: + +--- +import std.stdio; + +void main() { + write("What is the value of the die? "); + int die; + readf(" %s", &die); + + if (die == 1) { + writeln("You won"); + + } else if (die == 2) { + writeln("You won"); + + } else if (die == 3) { + writeln("You won"); + + } else if (die == 4) { + writeln("I won"); + + } else if (die == 5) { + writeln("I won"); + + } else if (die == 6) { + writeln("I won"); + + } else { + writeln("ERROR: ", die, " is invalid"); + } +} +--- + +$(P +Unfortunately, that program has many repetitions. We can achieve the same result by other designs. Here is one: +) + +--- +import std.stdio; + +void main() { + write("What is the value of the die? "); + int die; + readf(" %s", &die); + + if ((die == 1) || (die == 2) || (die == 3)) { + writeln("You won"); + + } else if ((die == 4) || (die == 5) || (die == 6)) { + writeln("I won"); + + } else { + writeln("ERROR: ", die, " is invalid"); + } +} +--- + +) + +$(LI +The previous designs cannot be used in this case. It is not practical to type 1000 different values in a program and expect them all be correct or readable. For that reason, it is better to determine whether the value of the die is $(I within a range): + +--- + if ((die >= 1) && (die <= 500)) +--- + +) + +) + +Macros: + TITLE=The if Statement Solutions + + DESCRIPTION=Programming in D exercise solutions: the 'if' statement and its optional 'else' clause + + KEYWORDS=programming in d tutorial if else solution diff --git a/book/d.en/if.d b/book/d.en/if.d new file mode 100644 index 0000000000..ffc82b1890 --- /dev/null +++ b/book/d.en/if.d @@ -0,0 +1,309 @@ +Ddoc + +$(DERS_BOLUMU $(IX if) $(CH4 if) Statement) + +$(P +We've learned that the actual work in a program is performed by expressions. All of the expressions of all of the programs that we've seen so far have started with the $(C main()) function and were executed until the end of $(C main). +) + +$(P +$(IX statement) $(I Statements), on the other hand, are features that affect the execution of expressions. Statements don't produce values and don't have side effects themselves. They determine whether and in what order the expressions are executed. Statements sometimes use logical expressions when making such decisions. +) + +$(P $(I $(B Note:) Other programming languages may have different definitions for expression and statement, while some others may not have a distinction at all. +) +) + +$(H5 The $(C if) block and its scope) + +$(P +The $(C if) statement determines whether one or more expressions would be executed. It makes this decision by evaluating a logical expression. It has the same meaning as the English word "if", as in the phrase "if there is coffee then I will drink coffee". +) + +$(P +$(C if) takes a logical expression in parentheses. If the value of that logical expression is $(C true), then it executes the expressions that are within the following curly brackets. Conversely, if the logical expression is $(C false), it does not execute the expressions within the curly brackets. +) + +$(P +The area within the curly brackets is called a $(I scope) and all of the code that is in that scope is called a $(I block of code). +) + +$(P +Here is the syntax of the $(C if) statement: +) + +--- + if (a_logical_expression) { + // ... expression(s) to execute if true + } +--- + +$(P +For example, the program construct that represents "if there is coffee then drink coffee and wash the cup" can be written as in the following program: +) + +--- +import std.stdio; + +void main() { + bool existsCoffee = true; + + if (existsCoffee) { + writeln("Drink coffee"); + writeln("Wash the cup"); + } +} +--- + +$(P +If the value of $(C existsCoffee) is $(C false), then the expressions that are within the block would be skipped and the program would not print anything. +) + +$(H5 $(IX else) The $(C else) block and its scope) + +$(P +Sometimes there are operations to execute for when the logical expression of the $(C if) statement is $(C false). For example, there is always an operation to execute in a decision like "if there is coffee I will drink coffee, else I will drink tea". +) + +$(P +The operations to execute in the $(C false) case are placed in a scope after the $(C else) keyword: +) + +--- + if (a_logical_expression) { + // ... expression(s) to execute if true + + } else { + // ... expression(s) to execute if false + } +--- + +$(P +For example, under the assumption that there is always tea: +) + +--- + if (existsCoffee) { + writeln("Drink coffee"); + + } else { + writeln("Drink tea"); + } +--- + +$(P +In that example, either the first or the second string would be printed depending on the value of $(C existsCoffee). +) + +$(P +$(C else) itself is not a statement but an optional $(I clause) of the $(C if) statement; it cannot be used alone. +) + +$(P +Note the placement of curly brackets of the $(C if) and $(C else) blocks above. Although it is $(LINK2 http://dlang.org/dstyle.html, official D style) to place curly brackets on separate lines, this book uses a common style of inline curly brackets throughout. +) + +$(H5 Always use the scope curly brackets) + +$(P +It is not recommended but is actually possible to omit the curly brackets if there is only one statement within a scope. As both the $(C if) and the $(C else) scopes have just one statement above, that code can also be written as the following: +) + +--- + if (existsCoffee) + writeln("Drink coffee"); + + else + writeln("Drink tea"); +--- + +$(P +Most experienced programmers use curly brackets even for single statements. (One of the exercises of this chapter is about omitting them.) Having said that, I will now show the only case where omitting the curly brackets is actually better. +) + +$(H5 $(IX else if) The "if, else if, else" chain) + +$(P +One of the powers of statements and expressions is the ability to use them in more complex ways. In addition to expressions, scopes can contain other statements. For example, an $(C else) scope can contain an $(C if) statement. Connecting statements and expressions in different ways allows us to make programs behave intelligently according to their purposes. +) + +$(P +The following is a more complex example written under the agreement that riding to a good coffee shop is preferred over walking to a bad one: +) + +--- + if (existsCoffee) { + writeln("Drink coffee at home"); + + } else { + + if (existsBicycle) { + writeln("Ride to the good place"); + + } else { + writeln("Walk to the bad place"); + } + } +--- + +$(P +The code above represents the sentences "If there is coffee, drink at home. Else, if there is a bicycle, ride to the good place. Otherwise, walk to the bad place." +) + +$(P +Let's complicate this decision process further: instead of having to walk to the bad place, let's first try the neighbor: +) + +--- + if (existsCoffee) { + writeln("Drink coffee at home"); + + } else { + + if (existsBicycle) { + writeln("Ride to the good place"); + + } else { + + if (neighborIsHome) { + writeln("Have coffee at neighbor's"); + + } else { + writeln("Walk to the bad place"); + } + } + } +--- + +$(P +Such decisions like "if this case, else if that other case, else if that even other case, etc." are common in programs. Unfortunately, when the guideline of always using curly brackets is followed obstinately, the code ends up having too much horizontal and vertical space: ignoring the empty lines, the 3 $(C if) statements and the 4 $(C writeln) expressions above occupy a total of 13 lines. +) + +$(P +In order to write such constructs in a more compact way, when an $(C else) scope contains only one $(C if) statement, then the curly brackets of that $(C else) scope are omitted as an exception to this guideline. +) + +$(P +I am leaving the following code untidy as an intermediate step before showing the better form of it. No code should be written in such an untidy way. +) + +$(P +The following is what the code looks like after removing the curly brackets of the two $(C else) scopes that contain just a single $(C if) statement: +) + +--- + if (existsCoffee) { + writeln("Drink coffee at home"); + + } else + + if (existsBicycle) { + writeln("Ride to the good place"); + + } else + + if (neighborIsHome) { + writeln("Have coffee at neighbor's"); + + } else { + writeln("Walk to the bad place"); + } +--- + +$(P +If we now move those $(C if) statements up to the same lines as their enclosing $(C else) clauses and tidy up the code, we end up with the following more readable format: +) + +--- + if (existsCoffee) { + writeln("Drink coffee at home"); + + } else if (existsBicycle) { + writeln("Ride to the good place"); + + } else if (neighborIsHome) { + writeln("Have coffee at neighbor's"); + + } else { + writeln("Walk to the bad place"); + } +--- + +$(P +Removing the curly brackets allows the code to be more compact and lines up all of the expressions for easier readability. The logical expressions, the order that they are evaluated, and the operations that are executed when they are true are now easier to see at a glance. +) + +$(P +This common programming construct is called the "if, else if, else" chain. +) + + +$(PROBLEM_COK + +$(PROBLEM + +Since the logical expression below is $(C true), we would expect this program to $(I drink lemonade and wash the cup): + +--- +import std.stdio; + +void main() { + bool existsLemonade = true; + + if (existsLemonade) { + writeln("Drinking lemonade"); + writeln("Washing the cup"); + + } else + writeln("Eating pie"); + writeln("Washing the plate"); +} +--- + +But when you run that program you will see that it $(I washes the plate) as well: + +$(SHELL +Drinking lemonade +Washing the cup +Washing the plate +) + +Why? Correct the program to wash the plate only when the logical expression is $(C false). +) + +$(PROBLEM +Write a program that plays a game with the user (obviously with trust). The user throws a die and enters its value. Either the user or the program wins according to the value of the die: + +$(MONO +$(B Value of the die Output of the program) + 1 You won + 2 You won + 3 You won + 4 I won + 5 I won + 6 I won + Any other value ERROR: Invalid value +) + +Bonus: Have the program also mention the value when the value is invalid. For example: + +$(SHELL +ERROR: 7 is invalid +) + +) + +$(PROBLEM +Let's change the game by having the user enter a value from 1 to 1000. Now the user wins when the value is in the range 1-500 and the computer wins when the value is in the range 501-1000. Can the previous program be easily modified to work in this way? +) + +) + +Macros: + TITLE=if Statement + + DESCRIPTION=The if statement, one of the conditional statements of the D programming language + + KEYWORDS=d programming language tutorial book if conditional statement + +MINI_SOZLUK= diff --git a/book/d.en/index.d b/book/d.en/index.d new file mode 100644 index 0000000000..3484351896 --- /dev/null +++ b/book/d.en/index.d @@ -0,0 +1,148 @@ +Ddoc + +$(I +This is Ali Çehreli's book on D programming. Ali's pedagogical skills are renowned in the D community, for good reason. This book has hooks for many +different fish - as well as being a careful and paced guide for programmers who are new to the D Programming language, it is also a useful reference +for D practitioners, and even a perspicacious tutorial for people new to programming entirely. If you enjoy this book and would like to +thank Ali financially, a Gumroad link is included below where you can buy this book on a pay-what-you-want basis. Enjoy! +) +$(DERS_BOLUMU Programming in D) + +
    + + + +$(H6 ISBNs) +$(P +978-0-692-59943-3 hardcover by IngramSpark$(BR) +978-0-692-52957-7 paperback by IngramSpark$(BR) +978-1-515-07460-1 paperback by CreateSpace$(BR) +978-1-519-95441-1 ePUB by Draft2Digital$(BR) +) + +$(P +These options have different prices, shipping times, shipping costs, customs and other fees, availability at local book stores, etc. +) + +
    + +$(P +Also available as $(LINK2 https://gumroad.com/l/PinD, $(I pay-what-you-want) eBooks at Gumroad) and $(I free) here as $(LINK_DOWNLOAD http://ddili.org/Programming_in_D.pdf, PDF), $(LINK_DOWNLOAD http://ddili.org/Programming_in_D.epub, EPUB), $(LINK_DOWNLOAD http://ddili.org/Programming_in_D.azw3, AZW3), and $(LINK_DOWNLOAD http://ddili.org/Programming_in_D.mobi, MOBI). +) + +$(P +$(LINK_DOWNLOAD /Programming_in_D_code_samples.zip, Click here to download code samples as a $(C .zip) file.) +) + +$(H5 Online version) + +$(UL +$(WORK_IN_PROCESS +$(LI $(LINK2 foreword1.html, Foreword by Walter Bright)) +) +$(LI $(LINK2 foreword2.html, Foreword by Andrei Alexandrescu)) +$(LI $(LINK2 preface.html, Preface)) +$(LI $(LINK2 hello_world.html, The Hello World Program) $(INDEX_KEYWORDS main)) +$(LI $(LINK2 writeln.html, writeln and write)) +$(LI $(LINK2 compiler.html, Compilation)) +$(LI $(LINK2 types.html, Fundamental Types) $(INDEX_KEYWORDS char int double (and more))) +$(LI $(LINK2 assignment.html, Assignment and Order of Evaluation) $(INDEX_KEYWORDS =)) +$(LI $(LINK2 variables.html, Variables)) +$(LI $(LINK2 io.html, Standard Input and Output Streams) $(INDEX_KEYWORDS stdin stdout)) +$(LI $(LINK2 input.html, Reading from the Standard Input)) +$(LI $(LINK2 logical_expressions.html, Logical Expressions) $(INDEX_KEYWORDS bool true false ! == != < <= > >= || &&)) +$(LI $(LINK2 if.html, if Statement) $(INDEX_KEYWORDS if else)) +$(LI $(LINK2 while.html, while Loop) $(INDEX_KEYWORDS while continue break)) +$(LI $(LINK2 arithmetic.html, Integers and Arithmetic Operations) $(INDEX_KEYWORDS ++ -- + - * / % ^^ += -= *= /= %= ^^=)) +$(LI $(LINK2 floating_point.html, Floating Point Types) $(INDEX_KEYWORDS .nan .infinity isNaN)) +$(LI $(LINK2 arrays.html, Arrays) $(INDEX_KEYWORDS [] .length ~ ~=)) +$(LI $(LINK2 characters.html, Characters) $(INDEX_KEYWORDS char wchar dchar)) +$(LI $(LINK2 slices.html, Slices and Other Array Features) $(INDEX_KEYWORDS .. $ .dup capacity)) +$(LI $(LINK2 strings.html, Strings) $(INDEX_KEYWORDS char[] wchar[] dchar[] string wstring dstring)) +$(LI $(LINK2 stream_redirect.html, Redirecting Standard Input and Output Streams)) +$(LI $(LINK2 files.html, Files) $(INDEX_KEYWORDS File)) +$(LI $(LINK2 auto_and_typeof.html, auto and typeof) $(INDEX_KEYWORDS auto typeof)) +$(LI $(LINK2 name_space.html, Name Scope)) +$(LI $(LINK2 for.html, for Loop) $(INDEX_KEYWORDS for)) +$(LI $(LINK2 ternary.html, Ternary Operator ?:) $(INDEX_KEYWORDS ?:)) +$(LI $(LINK2 literals.html, Literals)) +$(LI $(LINK2 formatted_output.html, Formatted Output) $(INDEX_KEYWORDS writef writefln)) +$(LI $(LINK2 formatted_input.html, Formatted Input)) +$(LI $(LINK2 do_while.html, do-while Loop) $(INDEX_KEYWORDS do while)) +$(LI $(LINK2 aa.html, Associative Arrays) $(INDEX_KEYWORDS .keys .values .byKey .byValue .byKeyValue .get .remove in)) +$(LI $(LINK2 foreach.html, foreach Loop) $(INDEX_KEYWORDS foreach .byKey .byValue .byKeyValue)) +$(LI $(LINK2 switch_case.html, switch and case) $(INDEX_KEYWORDS switch, case, default, final switch)) +$(LI $(LINK2 enum.html, enum) $(INDEX_KEYWORDS enum .min .max)) +$(LI $(LINK2 functions.html, Functions) $(INDEX_KEYWORDS return void)) +$(LI $(LINK2 const_and_immutable.html, Immutability) $(INDEX_KEYWORDS enum const immutable .dup .idup)) +$(LI $(LINK2 value_vs_reference.html, Value Types and Reference Types) $(INDEX_KEYWORDS &)) +$(LI $(LINK2 function_parameters.html, Function Parameters) $(INDEX_KEYWORDS in out ref inout lazy scope shared)) +$(LI $(LINK2 lvalue_rvalue.html, Lvalues and Rvalues) $(INDEX_KEYWORDS auto ref)) +$(LI $(LINK2 lazy_operators.html, Lazy Operators)) +$(LI $(LINK2 main.html, Program Environment) $(INDEX_KEYWORDS main stderr)) +$(LI $(LINK2 exceptions.html, Exceptions) $(INDEX_KEYWORDS throw try catch finally)) +$(LI $(LINK2 scope.html, scope) $(INDEX_KEYWORDS scope(exit) scope(success) scope(failure))) +$(LI $(LINK2 assert.html, assert and enforce) $(INDEX_KEYWORDS assert enforce)) +$(LI $(LINK2 unit_testing.html, Unit Testing) $(INDEX_KEYWORDS unittest)) +$(LI $(LINK2 contracts.html, Contract Programming) $(INDEX_KEYWORDS in out)) +$(LI $(LINK2 lifetimes.html, Lifetimes and Fundamental Operations)) +$(LI $(LINK2 null_is.html, The null Value and the is Operator) $(INDEX_KEYWORDS null is !is)) +$(LI $(LINK2 cast.html, Type Conversions) $(INDEX_KEYWORDS to assumeUnique cast)) +$(LI $(LINK2 struct.html, Structs) $(INDEX_KEYWORDS struct . {} static, static this, static ~this)) +$(LI $(LINK2 parameter_flexibility.html, Variable Number of Parameters) $(INDEX_KEYWORDS T[]... __MODULE__ __FILE__ __LINE__ __FUNCTION__ (and more))) +$(LI $(LINK2 function_overloading.html, Function Overloading)) +$(LI $(LINK2 member_functions.html, Member Functions) $(INDEX_KEYWORDS toString)) +$(LI $(LINK2 const_member_functions.html, const ref Parameters and const Member Functions) $(INDEX_KEYWORDS const ref, in ref, inout)) +$(LI $(LINK2 special_functions.html, Constructor and Other Special Functions) $(INDEX_KEYWORDS this ~this this(this) opAssign @disable)) +$(LI $(LINK2 operator_overloading.html, Operator Overloading) $(INDEX_KEYWORDS opUnary opBinary opEquals opCmp opIndex (and more))) +$(LI $(LINK2 class.html, Classes) $(INDEX_KEYWORDS class new)) +$(LI $(LINK2 inheritance.html, Inheritance) $(INDEX_KEYWORDS : super override abstract)) +$(LI $(LINK2 object.html, Object) $(INDEX_KEYWORDS toString opEquals opCmp toHash typeid TypeInfo)) +$(LI $(LINK2 interface.html, Interfaces) $(INDEX_KEYWORDS interface static final)) +$(LI $(LINK2 destroy.html, destroy and scoped) $(INDEX_KEYWORDS destroy scoped)) +$(LI $(LINK2 modules.html, Modules and Libraries) $(INDEX_KEYWORDS import, module, static this, static ~this)) +$(LI $(LINK2 encapsulation.html, Encapsulation and Protection Attributes) $(INDEX_KEYWORDS private protected public package)) +$(LI $(LINK2 ufcs.html, Universal Function Call Syntax (UFCS))) +$(LI $(LINK2 property.html, Properties)) +$(LI $(LINK2 invariant.html, Contract Programming for Structs and Classes) $(INDEX_KEYWORDS invariant)) +$(LI $(LINK2 templates.html, Templates)) +$(LI $(LINK2 pragma.html, Pragmas)) +$(LI $(LINK2 alias.html, alias and with) $(INDEX_KEYWORDS alias with)) +$(LI $(LINK2 alias_this.html, alias this) $(INDEX_KEYWORDS alias this)) +$(LI $(LINK2 pointers.html, Pointers) $(INDEX_KEYWORDS * &)) +$(LI $(LINK2 bit_operations.html, Bit Operations) $(INDEX_KEYWORDS ~ & | ^ >> >>> <<)) +$(LI $(LINK2 cond_comp.html, Conditional Compilation) $(INDEX_KEYWORDS debug, version, static if, static assert, __traits)) +$(LI $(LINK2 is_expr.html, is Expression) $(INDEX_KEYWORDS is())) +$(LI $(LINK2 lambda.html, Function Pointers, Delegates, and Lambdas) $(INDEX_KEYWORDS function delegate => toString)) +$(LI $(LINK2 foreach_opapply.html, foreach with Structs and Classes) $(INDEX_KEYWORDS opApply empty popFront front (and more))) +$(LI $(LINK2 nested.html, Nested Functions, Structs, and Classes) $(INDEX_KEYWORDS static)) +$(LI $(LINK2 union.html, Unions) $(INDEX_KEYWORDS union)) +$(LI $(LINK2 goto.html, Labels and goto) $(INDEX_KEYWORDS goto)) +$(LI $(LINK2 tuples.html, Tuples) $(INDEX_KEYWORDS tuple Tuple AliasSeq .tupleof foreach)) +$(LI $(LINK2 templates_more.html, More Templates) $(INDEX_KEYWORDS template opDollar opIndex opSlice)) +$(LI $(LINK2 functions_more.html, More Functions) $(INDEX_KEYWORDS inout pure nothrow @nogc @safe @trusted @system CTFE __ctfe)) +$(LI $(LINK2 mixin.html, Mixins) $(INDEX_KEYWORDS mixin)) +$(LI $(LINK2 ranges.html, Ranges) $(INDEX_KEYWORDS InputRange ForwardRange BidirectionalRange RandomAccessRange OutputRange)) +$(LI $(LINK2 ranges_more.html, More Ranges) $(INDEX_KEYWORDS isInputRange ElementType hasLength inputRangeObject (and more))) +$(LI $(LINK2 static_foreach.html, static foreach)) +$(LI $(LINK2 parallelism.html, Parallelism) $(INDEX_KEYWORDS parallel task asyncBuf map amap reduce)) +$(LI $(LINK2 concurrency.html, Message Passing Concurrency) $(INDEX_KEYWORDS spawn thisTid ownerTid send receive (and more))) +$(LI $(LINK2 concurrency_shared.html, Data Sharing Concurrency) $(INDEX_KEYWORDS synchronized, shared, shared static this, shared static ~this)) +$(LI $(LINK2 fibers.html, Fibers) $(INDEX_KEYWORDS call yield)) +$(LI $(LINK2 memory.html, Memory Management) $(INDEX_KEYWORDS calloc realloc emplace destroy .alignof)) +$(LI $(LINK2 uda.html, User Defined Attributes (UDA)) $(INDEX_KEYWORDS @)) +$(LI $(LINK2 operator_precedence.html, Operator Precedence)) +) + +Macros: + TITLE=Programming in D + + DESCRIPTION=D programming language tutorial from the ground up. + + KEYWORDS=d programming language tutorial book novice beginner + + BREADCRUMBS=$(BREADCRUMBS_INDEX) + +SOZLER= + +MINI_SOZLUK= diff --git a/book/d.en/inheritance.cozum.d b/book/d.en/inheritance.cozum.d new file mode 100644 index 0000000000..ee3b6a6eca --- /dev/null +++ b/book/d.en/inheritance.cozum.d @@ -0,0 +1,203 @@ +Ddoc + +$(COZUM_BOLUMU Inheritance) + +$(OL + +$(LI The member functions that are declared as $(C abstract) by superclasses must be defined by the $(C override) keyword by subclasses. + + +$(P +Ignoring the $(C Train) class for this exercise, $(C Locomotive.makeSound) and $(C RailwayCar.makeSound) can be implemented as in the following program: +) + +--- +import std.stdio; +import std.exception; + +class RailwayVehicle { + void advance(size_t kilometers) { + writefln("The vehicle is advancing %s kilometers", + kilometers); + + foreach (i; 0 .. kilometers / 100) { + writefln(" %s", makeSound()); + } + } + + abstract string makeSound(); +} + +class Locomotive : RailwayVehicle { + $(HILITE override) string makeSound() { + return "choo choo"; + } +} + +class RailwayCar : RailwayVehicle { + // ... + + $(HILITE override) string makeSound() { + return "clack clack"; + } +} + +class PassengerCar : RailwayCar { + // ... +} + +class FreightCar : RailwayCar { + // ... +} + +void main() { + auto railwayCar1 = new PassengerCar; + railwayCar1.advance(100); + + auto railwayCar2 = new FreightCar; + railwayCar2.advance(200); + + auto locomotive = new Locomotive; + locomotive.advance(300); +} +--- + +) + +$(LI +The following program uses the sounds of the components of $(C Train) to make the sound of $(C Train) itself: + +--- +import std.stdio; +import std.exception; + +class RailwayVehicle { + void advance(size_t kilometers) { + writefln("The vehicle is advancing %s kilometers", + kilometers); + + foreach (i; 0 .. kilometers / 100) { + writefln(" %s", makeSound()); + } + } + + abstract string makeSound(); +} + +class Locomotive : RailwayVehicle { + override string makeSound() { + return "choo choo"; + } +} + +class RailwayCar : RailwayVehicle { + abstract void load(); + abstract void unload(); + + override string makeSound() { + return "clack clack"; + } +} + +class PassengerCar : RailwayCar { + override void load() { + writeln("The passengers are getting on"); + } + + override void unload() { + writeln("The passengers are getting off"); + } +} + +class FreightCar : RailwayCar { + override void load() { + writeln("The crates are being loaded"); + } + + override void unload() { + writeln("The crates are being unloaded"); + } +} + +class Train : RailwayVehicle { + Locomotive locomotive; + RailwayCar[] cars; + + this(Locomotive locomotive) { + enforce(locomotive !is null, + "Locomotive cannot be null"); + this.locomotive = locomotive; + } + + void addCar(RailwayCar[] cars...) { + this.cars ~= cars; + } + + $(HILITE override) string makeSound() { + string result = locomotive.makeSound(); + + foreach (car; cars) { + result ~= ", " ~ car.makeSound(); + } + + return result; + } + + void departStation(string station) { + foreach (car; cars) { + car.load(); + } + + writefln("Departing from %s station", station); + } + + void arriveStation(string station) { + writefln("Arriving at %s station", station); + + foreach (car; cars) { + car.unload(); + } + } +} + +void main() { + auto locomotive = new Locomotive; + auto train = new Train(locomotive); + + train.addCar(new PassengerCar, new FreightCar); + + train.departStation("Ankara"); + train.advance(500); + train.arriveStation("Haydarpaşa"); +} +--- + +$(P +The output: +) + +$(SHELL +The passengers are getting on +The crates are being loaded +Departing from Ankara station +The vehicle is advancing 500 kilometers + choo choo, clack clack, clack clack + choo choo, clack clack, clack clack + choo choo, clack clack, clack clack + choo choo, clack clack, clack clack + choo choo, clack clack, clack clack +Arriving at Haydarpaşa station +The passengers are getting off +The crates are being unloaded +) + +) + +) + +Macros: + TITLE=Inheritance + + DESCRIPTION=The exercise solutions for the Inheritance chapter, explaining how to specify behaviors of classes in the D programming language. + + KEYWORDS=programming in d tutorial class inheritance diff --git a/book/d.en/inheritance.d b/book/d.en/inheritance.d new file mode 100644 index 0000000000..294e0b0182 --- /dev/null +++ b/book/d.en/inheritance.d @@ -0,0 +1,1049 @@ +Ddoc + +$(DERS_BOLUMU $(IX inheritance) Inheritance) + +$(P +Inheritance is defining a more specialized type based on an existing more general base type. The specialized type acquires the members of the base type and as a result can be substituted in place of the base type. +) + +$(P +$(IX superclass) $(IX subclass) Inheritance is available for classes, not structs. The class that inherits another class is called the $(I subclass), and the class that gets inherited is called the $(I superclass), also called the $(I base class). +) + +$(P +There are two types of inheritance in D. We will cover $(I implementation inheritance) in this chapter and leave $(I interface inheritance) to a later chapter. +) + +$(P +$(IX :, inheritance) When defining a subclass, the superclass is specified after a colon character: +) + +--- +class $(I SubClass) : $(I SuperClass) { + // ... +} +--- + +$(P +To see an example of this, let's assume that there is already the following class that represents a clock: +) + +--- +$(CODE_NAME Clock)$(CODE_COMMENT_OUT)class Clock { + int hour; + int minute; + int second; + + void adjust(int hour, int minute, int second = 0) { + this.hour = hour; + this.minute = minute; + this.second = second; + } +$(CODE_COMMENT_OUT)} +--- + +$(P +Apparently, the members of that class do not need special values during construction; so there is no constructor. Instead, the members are set by the $(C adjust()) member function: +) + +--- + auto deskClock = new Clock; + deskClock.adjust(20, 30); + writefln( + "%02s:%02s:%02s", + deskClock.hour, deskClock.minute, deskClock.second); +--- + +$(P +$(I $(B Note:) It would be more useful to produce the time string by a $(C toString()) function. It will be added later when explaining the $(C override) keyword below.) +) + +$(P +The output: +) + +$(SHELL +20:30:00 +) + +$(P +With only that much functionality, $(C Clock) could be a struct as well, and depending on the needs of the program, that could be sufficient. +) + +$(P +However, being a class makes it possible to inherit from $(C Clock). +) + +$(P +To see an example of inheritance, let's consider an $(C AlarmClock) that not only includes all of the functionality of $(C Clock), but also provides a way of setting the alarm. Let's first define this type without regard to $(C Clock). If we did that, we would have to include the same three members of $(C Clock) and the same $(C adjust()) function that adjusted them. $(C AlarmClock) would also have other members for its additional functionality: +) + +--- +class AlarmClock { + $(HILITE int hour;) + $(HILITE int minute;) + $(HILITE int second;) + int alarmHour; + int alarmMinute; + + $(HILITE void adjust(int hour, int minute, int second = 0) {) + $(HILITE this.hour = hour;) + $(HILITE this.minute = minute;) + $(HILITE this.second = second;) + $(HILITE }) + + void adjustAlarm(int hour, int minute) { + alarmHour = hour; + alarmMinute = minute; + } +} +--- + +$(P +The members that appear exactly in $(C Clock) are highlighted. As can be seen, defining $(C Clock) and $(C AlarmClock) separately results in code duplication. +) + +$(P +Inheritance is helpful in such cases. Inheriting $(C AlarmClock) from $(C Clock) simplifies the new class and reduces code duplication: +) + +--- +$(CODE_NAME AlarmClock)$(CODE_COMMENT_OUT)class AlarmClock $(HILITE : Clock) { + int alarmHour; + int alarmMinute; + + void adjustAlarm(int hour, int minute) { + alarmHour = hour; + alarmMinute = minute; + } +$(CODE_COMMENT_OUT)} +--- + +$(P +The new definition of $(C AlarmClock) is the equivalent of the previous one. The highlighted part of the new definition corresponds to the highlighted parts of the old definition. +) + +$(P +Because $(C AlarmClock) inherits the members of $(C Clock), it can be used just like a $(C Clock): +) + +--- + auto bedSideClock = new AlarmClock; + bedSideClock.$(HILITE adjust(20, 30)); + bedSideClock.adjustAlarm(7, 0); +--- + +$(P +The members that are inherited from the superclass can be accessed as if they were the members of the subclass: +) + +--- + writefln("%02s:%02s:%02s ♫%02s:%02s", + bedSideClock$(HILITE .hour), + bedSideClock$(HILITE .minute), + bedSideClock$(HILITE .second), + bedSideClock.alarmHour, + bedSideClock.alarmMinute); +--- + +$(P +The output: +) + +$(SHELL +20:30:00 ♫07:00 +) + +$(P $(I $(B Note:) An $(C AlarmClock.toString) function would be more useful in this case. It will be defined later below.) +) + +$(P +The inheritance used in this example is $(I implementation inheritance.) +) + +$(P +If we imagine the memory as a ribbon going from top to bottom, the placement of the members of $(C AlarmClock) in memory can be pictured as in the following illustration: +) + +$(MONO + │ . │ + │ . │ +the address of the object → ├─────────────┤ + │$(GRAY $(I (other data))) │ + │$(HILITE  hour )│ + │$(HILITE  minute )│ + │$(HILITE  second )│ + │ alarmHour │ + │ alarmMinute │ + ├─────────────┤ + │ . │ + │ . │ +) + +$(P +$(IX vtbl) The illustration above is just to give an idea on how the members of the superclass and the subclass may be combined together. The actual layout of the members depends on the implementation details of the compiler in use. For example, the part that is marked as $(I other data) typically includes the pointer to the $(I virtual function table) (vtbl) of that particular class type. The details of the object layout are outside the scope of this book. +) + +$(H5 $(IX is-a) Warning: Inherit only if "is a") + +$(P +We have seen that implementation inheritance is about acquiring members. Consider this kind of inheritance only if the subtype can be thought of being a kind of the supertype as in the phrase "alarm clock $(I is a) clock." +) + +$(P +$(IX has-a) "Is a" is not the only relationship between types; a more common relationship is the "has a" relationship. For example, let's assume that we want to add the concept of a $(C Battery) to the $(C Clock) class. It would not be appropriate to add $(C Battery) to $(C Clock) by inheritance because the statement "clock is a battery" is not true: +) + +--- +class Clock : Battery { $(CODE_NOTE_WRONG WRONG DESIGN) + // ... +} +--- + +$(P +A clock is not a battery; it $(I has a) battery. When there is such a relationship of containment, the type that is contained must be defined as a member of the type that contains it: +) + +--- +class Clock { + Battery battery; $(CODE_NOTE Correct design) + // ... +} +--- + +$(H5 $(IX single inheritance) $(IX inheritance, single) $(IX hierarchy) Inheritance from at most one class) + +$(P +Classes can only inherit from a single base class (which itself can potentially inherit from another single class). In other words, multiple inheritance is not supported in D. +) + +$(P +For example, assuming that there is also a $(C SoundEmitter) class, and even though "alarm clock is a sound emitting object" is also true, it is not possible to inherit $(C AlarmClock) both from $(C Clock) and $(C SoundEmitter): +) + +--- +class SoundEmitter { + // ... +} + +class AlarmClock : Clock$(HILITE , SoundEmitter) { $(DERLEME_HATASI) + // ... +} +--- + +$(P +On the other hand, there is no limit to the number of $(I interfaces) that a class can inherit from. We will see the $(C interface) keyword in a later chapter. +) + +$(P +Additionally, there is no limit to how deep the inheritance hierarchy can go: +) + +--- +class MusicalInstrument { + // ... +} + +class StringInstrument : MusicalInstrument { + // ... +} + +class Violin : StringInstrument { + // ... +} +--- + +$(P +The inheritance hierarchy above defines a relationship from the more general to the more specific: musical instrument, string instrument, and violin. +) + +$(H5 Hierarchy charts) + +$(P +Types that are related by the "is a" relationship form a $(I class hierarchy). +) + +$(P +According to OOP conventions, class hierarchies are represented by superclasses being on the top and the subclasses being at the bottom. The inheritance relationships are indicated by arrows pointing from the subclasses to the superclasses. +) + +$(P +For example, the following can be a hierarchy of musical instruments: +) + +$(MONO + MusicalInstrument + ↗ ↖ + StringInstrument WindInstrument + ↗ ↖ ↗ ↖ + Violin Guitar Flute Recorder +) + +$(H5 $(IX super, member access) Accessing superclass members) + +$(P +The $(C super) keyword allows referring to members that are inherited from the superclass. +) + +--- +class AlarmClock : Clock { + // ... + + void foo() { + super.minute = 10; // The inherited 'minute' member + minute = 10; // Same thing if there is no ambiguity + } +} +--- + +$(P +The $(C super) keyword is not always necessary; $(C minute) alone has the same meaning in the code above. The $(C super) keyword is needed when both the superclass and the subclass have members under the same names. We will see this below when we will need to write $(C super.reset()) and $(C super.toString()). +) + +$(P +If multiple classes in an inheritance tree define a symbol with the same name, one can use the specific name of the class in the inheritance tree to disambiguate between the symbols: +) + +--- +class Device { + string $(HILITE manufacturer); +} + +class Clock : Device { + string $(HILITE manufacturer); +} + +class AlarmClock : Clock { + // ... + + void foo() { + $(HILITE Device.)manufacturer = "Sunny Horology, Inc."; + $(HILITE Clock.)manufacturer = "Better Watches, Ltd."; + } +} +--- + +$(H5 $(IX super, construction) Constructing superclass members) + +$(P +The other use of the $(C super) keyword is to call the constructor of the superclass. This is similar to calling the overloaded constructors of the current class: $(C this) when calling constructors of the current class and $(C super) when calling constructors of the superclass. +) + +$(P +It is not required to call the superclass constructor explicitly. If the constructor of the subclass makes an explicit call to any overload of $(C super), then that constructor is executed by that call. Otherwise, and if the superclass has a default constructor, it is executed automatically before entering the body of the subclass. +) + +$(P +We have not defined constructors for the $(C Clock) and $(C AlarmClock) classes yet. For that reason, the members of both of those classes are initialized by the $(C .init) values of their respective types, which is 0 for $(C int). +) + +$(P +Let's assume that $(C Clock) has the following constructor: +) + +--- +$(CODE_NAME Clock_ctor)$(CODE_COMMENT_OUT)class Clock { + this(int hour, int minute, int second) { + this.hour = hour; + this.minute = minute; + this.second = second; + } + + // ... +$(CODE_COMMENT_OUT)} +--- + +$(P +That constructor must be used when constructing $(C Clock) objects: +) + +--- + auto clock = new Clock(17, 15, 0); +--- + +$(P +Naturally, the programmers who use the $(C Clock) type directly would have to use that syntax. However, when constructing an $(C AlarmClock) object, they cannot construct its $(C Clock) part separately. Besides, the users of $(C AlarmClock) need not even know that it inherits from $(C Clock). +) + +$(P +A user of $(C AlarmClock) should simply construct an $(C AlarmClock) object and use it in the program without needing to pay attention to its $(C Clock) heritage: +) + +--- + auto bedSideClock = new AlarmClock(/* ... */); + // ... use as an AlarmClock ... +--- + +$(P +For that reason, constructing the superclass part is the responsibility of the subclass. The subclass calls the constructor of the superclass with the $(C super()) syntax: +) + +--- +$(CODE_NAME AlarmClock_ctor)$(CODE_COMMENT_OUT)class AlarmClock : Clock { + this(int hour, int minute, int second, // for Clock's members + int alarmHour, int alarmMinute) { // for AlarmClock's members + $(HILITE super)(hour, minute, second); + this.alarmHour = alarmHour; + this.alarmMinute = alarmMinute; + } + + // ... +$(CODE_COMMENT_OUT)} +--- + +$(P +The constructor of $(C AlarmClock) takes arguments for both its own members and the members of its superclass. It then uses part of those arguments to construct its superclass part. +) + +$(H5 $(IX override) Overriding the definitions of member functions) + +$(P +One of the benefits of inheritance is being able to redefine the member functions of the superclass in the subclass. This is called $(I overriding): The existing definition of the member function of the superclass is overridden by the subclass with the $(C override) keyword. +) + +$(P +$(IX virtual function) Overridable functions are called $(I virtual functions). Virtual functions are implemented by the compiler through $(I virtual function pointer tables) (vtbl) and $(I vtbl pointers). The details of this mechanism are outside the scope of this book. However, it must be known by every system programmer that virtual function calls are more expensive than regular function calls. Every non-private $(C class) member function in D is virtual by default. For that reason, when a superclass function does not need to be overridden at all, it should be defined as $(C final) so that it is not virtual. We will see the $(C final) keyword later in $(LINK2 interface.html, the Interfaces chapter). +) + +$(P +Let's assume that $(C Clock) has a member function that is used for resetting its members all to zero: +) + +--- +class Clock { + void reset() { + hour = 0; + minute = 0; + second = 0; + } + + // ... +} +--- + +$(P +That function is inherited by $(C AlarmClock) and can be called on an $(C AlarmClock) object: +) + +--- + auto bedSideClock = new AlarmClock(20, 30, 0, 7, 0); + // ... + bedSideClock.reset(); +--- + +$(P +However, necessarily ignorant of the members of $(C AlarmClock), $(C Clock.reset) can only reset its own members. For that reason, to reset the members of the subclass as well, $(C reset()) must be overridden: +) + +--- +class AlarmClock : Clock { + $(HILITE override) void reset() { + super.reset(); + alarmHour = 0; + alarmMinute = 0; + } + + // ... +} +--- + +$(P +The subclass resets only its own members and dispatches the rest of the task to $(C Clock) by the $(C super.reset()) call. Note that writing just $(C reset()) would not work as it would call the $(C reset()) function of $(C AlarmClock) itself. Calling $(C reset()) from within itself would cause an infinite recursion. +) + +$(P +The reason that I have delayed the definition of $(C toString()) until this point is that it must be defined by the $(C override) keyword for classes. As we will see in the next chapter, every class is automatically inherited from a superclass called $(C Object) and $(C Object) already defines a $(C toString()) member function. +) + +$(P +For that reason, the $(C toString()) member function for classes must be defined by using the $(C override) keyword: +) + +--- +$(CODE_NAME Clock_AlarmClock)import std.string; + +class Clock { + $(HILITE override) string toString() const { + return format("%02s:%02s:%02s", hour, minute, second); + } + + // ... +$(CODE_XREF Clock)$(CODE_XREF Clock_ctor)} + +class AlarmClock : Clock { + $(HILITE override) string toString() const { + return format("%s ♫%02s:%02s", super.toString(), + alarmHour, alarmMinute); + } + + // ... +$(CODE_XREF AlarmClock)$(CODE_XREF AlarmClock_ctor)} +--- + +$(P +Note that $(C AlarmClock) is again dispatching some of the task to $(C Clock) by the $(C super.toString()) call. +) + +$(P +Those two overrides of $(C toString()) allow converting $(C AlarmClock) objects to strings: +) + +--- +$(CODE_XREF Clock_AlarmClock)void main() { + auto deskClock = new AlarmClock(10, 15, 0, 6, 45); + writeln($(HILITE deskClock)); +} +--- + +$(P +The output: +) + +$(SHELL +10:15:00 ♫06:45 +) + +$(H5 $(IX polymorphism, run-time) $(IX run-time polymorphism) Using the subclass in place of the superclass) + +$(P +Since the superclass is more $(I general) and the subclass is more $(I specialized), objects of a subclass can be used in places where an object of the superclass type is required. This is called $(I polymorphism). +) + +$(P +The concepts of general and specialized types can be seen in statements like "this type is of that type": "alarm clock is a clock", "student is a person", "cat is an animal", etc. Accordingly, an alarm clock can be used where a clock is needed, a student can be used where a person is needed, and a cat can be used where an animal is needed. +) + +$(P +When a subclass object is being used as a superclass object, it does not lose its own specialized type. This is similar to the examples in real life: Using an alarm clock simply as a clock does not change the fact that it is an alarm clock; it would still behave like an alarm clock. +) + +$(P +Let's assume that a function takes a $(C Clock) object as parameter, which it resets at some point during its execution: +) + +--- +void use(Clock clock) { + // ... + clock.reset(); + // ... +} +--- + +$(P +Polymorphism makes it possible to send an $(C AlarmClock) to such a function: +) + +--- + auto deskClock = new AlarmClock(10, 15, 0, 6, 45); + writeln("Before: ", deskClock); + $(HILITE use(deskClock)); + writeln("After : ", deskClock); +--- + +$(P +This is in accordance with the relationship "alarm clock is a clock." As a result, the members of the $(C deskClock) object get reset: +) + +$(SHELL +Before: 10:15:00 ♫06:45 +After : 00:00:00 ♫$(HILITE 00:00) +) + +$(P +The important observation here is that not only the members of $(C Clock) but also the members of $(C AlarmClock) have been reset. +) + +$(P +Although $(C use()) calls $(C reset()) on a $(C Clock) object, since the actual object is an $(C AlarmClock), the function that gets called is $(C AlarmClock.reset). According to its definition above, $(C AlarmClock.reset) resets the members of both $(C Clock) and $(C AlarmClock). +) + +$(P +In other words, although $(C use()) uses the object as a $(C Clock), the actual object may be an inherited type that behaves in its own special way. +) + +$(P +Let's add another class to the $(C Clock) hierarchy. The $(C reset()) function of this type sets its members to random values: +) + +--- +import std.random; + +class BrokenClock : Clock { + this() { + super(0, 0, 0); + } + + override void reset() { + hour = uniform(0, 24); + minute = uniform(0, 60); + second = uniform(0, 60); + } +} +--- + +$(P +When an object of $(C BrokenClock) is sent to $(C use()), then the special $(C reset()) function of $(C BrokenClock) would be called. Again, although it is passed as a $(C Clock), the actual object is still a $(C BrokenClock): +) + +--- + auto shelfClock = new BrokenClock; + use(shelfClock); + writeln(shelfClock); +--- + +$(P +The output shows random time values as a result of resetting a $(C BrokenClock): +) + +$(SHELL +22:46:37 +) + +$(H5 Inheritance is transitive) + +$(P +Polymorphism is not just limited to two classes. Subclasses of subclasses can also be used in place of any superclass in the hierarchy. +) + +$(P +Let's consider the $(C MusicalInstrument) hierarchy: +) + +--- +class MusicalInstrument { + // ... +} + +class StringInstrument : MusicalInstrument { + // ... +} + +class Violin : StringInstrument { + // ... +} +--- + +$(P +The inheritances above builds the following relationships: "string instrument is a musical instrument" and "violin is a string instrument." Therefore, it is also true that "violin is a musical instrument." Consequently, a $(C Violin) object can be used in place of a $(C MusicalInstrument). +) + +$(P +Assuming that all of the supporting code below has also been defined: +) + +--- +void playInTune(MusicalInstrument instrument, + MusicalPiece piece) { + instrument.tune(); + instrument.play(piece); +} + +// ... + +auto myViolin = new Violin; +playInTune(myViolin, improvisation); +--- + +$(P +Although $(C playInTune()) expects a $(C MusicalInstrument), it is being called with a $(C Violin) due to the relationship "violin is a musical instrument." +) + +$(P +Inheritance can be as deep as needed. +) + +$(H5 $(IX abstract) Abstract member functions and abstract classes) + +$(P +Sometimes there are member functions that are natural to appear in a class interface even though that class cannot provide its definition. When there is no $(I concrete) definition of a member function, that function is an $(I abstract) member function. A class that has at least one abstract member function is an abstract class. +) + +$(P +For example, the $(C ChessPiece) superclass in a hierarchy may have an $(C isValid()) member function that determines whether a given move is valid for that chess piece. Since validity of a move depends on the actual type of the chess piece, the $(C ChessPiece) general class cannot make this decision itself. The valid moves can only be known by the subclasses like $(C Pawn), $(C King), etc. +) + +$(P +The $(C abstract) keyword specifies that the inherited class must implement such a method itself: +) + +--- +class ChessPiece { + $(HILITE abstract) bool isValid(Square from, Square to); +} +--- + +$(P +It is not possible to construct objects of abstract classes: +) + +--- + auto piece = new ChessPiece; $(DERLEME_HATASI) +--- + +$(P +The subclass would have to override and implement all the abstract functions in order to make the class non-abstract and therefore constructible: +) + +--- +class Pawn : ChessPiece { + override bool isValid(Square from, Square to) { + // ... the implementation of isValid for pawn ... + return decision; + } +} +--- + +$(P +It is now possible to construct objects of $(C Pawn): +) + +--- + auto piece = new Pawn; // compiles +--- + +$(P +Note that an abstract function may have an implementation of its own, but it would still require the subclass to provide its own implementation of such a function. For example, the $(C ChessPiece)'es implementation may provide some useful checks of its own: +) + +--- +class ChessPiece { + $(HILITE abstract) bool isValid(Square from, Square to) { + // We require the 'to' position to be different than + // the 'from' position + return from != to; + } +} + +class Pawn : ChessPiece { + override bool isValid(Square from, Square to) { + // First verify if it is a valid move for any ChessPiece + if (!$(HILITE super.isValid)(from, to)) { + return false; + } + + // ... then check if it is valid for the Pawn ... + + return decision; + } +} +--- + +$(P +The $(C ChessPiece) class is still abstract even though $(C isValid()) was already implemented, but the $(C Pawn) class is non-abstract and can be instantiated. +) + +$(H5 Example) + +$(P +Let's consider a class hierarchy that represents railway vehicles: +) + +$(MONO + RailwayVehicle + / | \ + Locomotive Train RailwayCar { load()?, unload()? } + / \ + PassengerCar FreightCar +) + +$(P +The functions that $(C RailwayCar) will declare as $(C abstract) are indicated by question marks. +) + +$(P +Since my goal is only to present a class hierarchy and point out some of its design decisions, I will not fully implement these classes. Instead of doing actual work, they will simply print messages. +) + +$(P +The most general class of the hierarchy above is $(C RailwayVehicle). In this program, it will only know how to move itself: +) + +--- +$(CODE_NAME RailwayVehicle)class RailwayVehicle { + void advance(size_t kilometers) { + writefln("The vehicle is advancing %s kilometers", + kilometers); + } +} +--- + +$(P +A class that inherits from $(C RailwayVehicle) is $(C Locomotive), which does not have any special members yet: +) + +--- +$(CODE_NAME Locomotive)$(CODE_XREF RailwayVehicle)class Locomotive : RailwayVehicle { +} +--- + +$(P +We will add a special $(C makeSound()) member function to $(C Locomotive) later during one of the exercises. +) + +$(P +$(C RailwayCar) is a $(C RailwayVehicle) as well. However, if the hierarchy supports different types of railway cars, then certain behaviors like loading and unloading must be done according to their exact types. For that reason, $(C RailwayCar) can only declare these two functions as abstract: +) + +--- +$(CODE_NAME RailwayCar)class RailwayCar : RailwayVehicle { + $(HILITE abstract) void load(); + $(HILITE abstract) void unload(); +} +--- + +$(P +Loading and unloading a passenger car is as simple as opening the doors of the car, while loading and unloading a freight car may involve porters and winches. The following subclasses provide definitions for the abstract functions of $(C RailwayCar): +) + +--- +$(CODE_NAME PassengerCar_FreightCar)class PassengerCar : RailwayCar { + override void load() { + writeln("The passengers are getting on"); + } + + override void unload() { + writeln("The passengers are getting off"); + } +} + +class FreightCar : RailwayCar { + override void load() { + writeln("The crates are being loaded"); + } + + override void unload() { + writeln("The crates are being unloaded"); + } +} +--- + +$(P +Being an abstract class does not preclude the use of $(C RailwayCar) in the program. Objects of $(C RailwayCar) can not be constructed but $(C RailwayCar) can be used as an interface. As the subclasses define the two relationships "passenger car is a railway car" and "freight car is a railway car", the objects of $(C PassengerCar) and $(C FreightCar) can be used in places of $(C RailwayCar). This will be seen in the $(C Train) class below. +) + +$(P +The class that represents a train can consist of a locomotive and an array of railwaycars: +) + +--- +$(CODE_NAME Train_members)$(CODE_COMMENT_OUT)class Train : RailwayVehicle { + Locomotive locomotive; + RailwayCar[] cars; + + // ... +$(CODE_COMMENT_OUT)} +--- + +$(P +I would like to repeat an important point: Although both $(C Locomotive) and $(C RailwayCar) inherit from $(C RailwayVehicle), it would not be correct to inherit $(C Train) from either of them. Inheritance models the "is a" relationship and a train is neither a locomotive nor a passenger car. A train consists of them. +) + +$(P +If we require that every train must have a locomotive, the $(C Train) constructor must ensure that it takes a valid $(C Locomotive) object. Similarly, if the railway cars are optional, they can be added by a member function: +) + +--- +$(CODE_NAME Train_ctor)import std.exception; +// ... + +$(CODE_COMMENT_OUT)class Train : RailwayVehicle { + // ... + + this(Locomotive locomotive) { + enforce(locomotive !is null, + "Locomotive cannot be null"); + this.locomotive = locomotive; + } + + void addCar(RailwayCar[] cars...) { + this.cars ~= cars; + } + + // ... +$(CODE_COMMENT_OUT)} +--- + +$(P +Note that $(C addCar()) can validate the $(C RailwayCar) objects as well. I am ignoring that validation here. +) + +$(P +We can imagine that the departures and arrivals of trains should also be supported: +) + +--- +$(CODE_NAME Train)$(CODE_XREF RailwayCar)class Train : RailwayVehicle { + // ... + + void departStation(string station) { + foreach (car; cars) { + car.load(); + } + + writefln("Departing from %s station", station); + } + + void arriveStation(string station) { + writefln("Arriving at %s station", station); + + foreach (car; cars) { + car.unload(); + } + } +$(CODE_XREF Train_members)$(CODE_XREF Train_ctor)} +--- + +$(P +The following $(C main()) is making use of the $(C RailwayVehicle) hierarchy: +) + +--- +$(CODE_XREF Locomotive)$(CODE_XREF Train)$(CODE_XREF PassengerCar_FreightCar)import std.stdio; + +// ... + +void main() { + auto locomotive = new Locomotive; + auto train = new Train(locomotive); + + train.addCar(new PassengerCar, new FreightCar); + + train.departStation("Ankara"); + train.advance(500); + train.arriveStation("Haydarpaşa"); +} +--- + +$(P +The $(C Train) class is being used by functions that are provided by two separate interfaces: +) + +$(OL + +$(LI +When the $(C advance()) function is called, the $(C Train) object is being used as a $(C RailwayVehicle) because that function is declared by $(C RailwayVehicle). +) + +$(LI When the $(C departStation()) and $(C arriveStation()) functions are called, $(C train) is being used as a $(C Train) because those functions are declared by $(C Train).) + +) + +$(P +The arrows indicate that $(C load()) and $(C unload()) functions work according to the actual type of $(C RailwayCar): +) + +$(SHELL +The passengers are getting on $(SHELL_NOTE) +The crates are being loaded $(SHELL_NOTE) +Departing from Ankara station +The vehicle is advancing 500 kilometers +Arriving at Haydarpaşa station +The passengers are getting off $(SHELL_NOTE) +The crates are being unloaded $(SHELL_NOTE) +) + +$(H5 Summary) + +$(UL +$(LI Inheritance is used for the "is a" relationship.) +$(LI Every class can inherit from up to one $(C class).) +$(LI $(C super) has two uses: Calling the constructor of the superclass and accessing the members of the superclass.) +$(LI $(C override) is for redefining member functions of the superclass specially for the subclass.) +$(LI $(C abstract) requires that a member function must be overridden.) +) + +$(PROBLEM_COK + +$(PROBLEM +Let's modify $(C RailwayVehicle). In addition to reporting the distance that it advances, let's have it also make sounds. To keep the output short, let's print the sounds per 100 kilometers: + +--- +class RailwayVehicle { + void advance(size_t kilometers) { + writefln("The vehicle is advancing %s kilometers", + kilometers); + + foreach (i; 0 .. kilometers / 100) { + writefln(" %s", makeSound()); + } + } + + // ... +} +--- + +$(P +However, $(C makeSound()) cannot be defined by $(C RailwayVehicle) because vehicles may have different sounds: +) + +$(UL +$(LI "choo choo" for $(C Locomotive)) +$(LI "clack clack" for $(C RailwayCar)) +) + +$(P $(I $(B Note:) Leave $(C Train.makeSound) to the next exercise.) +) + +$(P +Because it must be overridden, $(C makeSound()) must be declared as $(C abstract) by the superclass: +) + +--- +class RailwayVehicle { + // ... + + abstract string makeSound(); +} +--- + +$(P +Implement $(C makeSound()) for the subclasses and try the code with the following $(C main()): +) + +--- +$(CODE_XREF Locomotive)$(CODE_XREF Train)$(CODE_XREF PassengerCar_FreightCar)void main() { + auto railwayCar1 = new PassengerCar; + railwayCar1.advance(100); + + auto railwayCar2 = new FreightCar; + railwayCar2.advance(200); + + auto locomotive = new Locomotive; + locomotive.advance(300); +} +--- + +$(P +Make the program produce the following output: +) + +$(SHELL +The vehicle is advancing 100 kilometers + clack clack +The vehicle is advancing 200 kilometers + clack clack + clack clack +The vehicle is advancing 300 kilometers + choo choo + choo choo + choo choo +) + +$(P +Note that there is no requirement that the sounds of $(C PassengerCar) and $(C FreightCar) be different. They can share the same implemention from $(C RailwayCar). +) + +) + +$(PROBLEM +Think about how $(C makeSound()) can be implemented for $(C Train). One idea is that $(C Train.makeSound) may return a $(C string) that consists of the sounds of the members of $(C Train). +) + +) + +Macros: + TITLE=Inheritance + + DESCRIPTION=Inheriting classes from classes in the D programming language. + + KEYWORDS=d programming lesson book tutorial class inheeritance diff --git a/book/d.en/input.cozum.d b/book/d.en/input.cozum.d new file mode 100644 index 0000000000..35e6ab7be7 --- /dev/null +++ b/book/d.en/input.cozum.d @@ -0,0 +1,14 @@ +Ddoc + +$(COZUM_BOLUMU Reading from the Standard Input) + +$(P +When the characters cannot be converted to the desired type, $(C stdin) gets in an unusable state. For example, entering "abc" when an $(C int) is expected would make $(C stdin) unusable. +) + +Macros: + TITLE=Reading from the Standard Input Solutions + + DESCRIPTION=Programming in D exercise solutions: reading from the standard input + + KEYWORDS=programming in d tutorial reading stdin solution diff --git a/book/d.en/input.d b/book/d.en/input.d new file mode 100644 index 0000000000..ad769afddb --- /dev/null +++ b/book/d.en/input.d @@ -0,0 +1,245 @@ +Ddoc + +$(DERS_BOLUMU $(IX input) Reading from the Standard Input) + +$(P +Any data that is read by the program must first be stored in a variable. For example, a program that reads the number of students from the input must store this information in a variable. The type of this specific variable can be $(C int). +) + +$(P +As we've seen in the previous chapter, we don't need to type $(C stdout) when printing to the output, because it is implied. Further, what is to be printed is specified as the argument. So, $(C write(studentCount)) is sufficient to print the value of $(C studentCount). To summarize: +) + +$(MONO +stream: stdout +operation: write +data: the value of the studentCount variable +target: commonly the terminal window +) + +$(P +$(IX readf) The reverse of $(C write) is $(C readf); it reads from the standard input. The "f" in its name comes from "formatted" as what it reads must always be presented in a certain format. +) + +$(P +We've also seen in the previous chapter that the standard input stream is $(C stdin). +) + +$(P +In the case of reading, one piece of the puzzle is still missing: where to store the data. To summarize: +) + +$(MONO +stream: stdin +operation: readf +data: some information +target: ? +) + +$(P +The location of where to store the data is specified by the address of a variable. The address of a variable is the exact location in the computer's memory where its value is stored. +) + +$(P +$(IX &, address of) In D, the $(C &) character that is typed before a name is the address of what that name represents. For example, the address of $(C studentCount) is $(C &studentCount). Here, $(C &studentCount) can be read as "the address of $(C studentCount)" and is the missing piece to replace the question mark above: +) + +$(MONO +stream: stdin +operation: readf +data: some information +target: the location of the studentCount variable +) + +$(P +Typing a $(C &) in front of a name means $(I pointing) at what that name represents. This concept is the foundation of references and pointers that we will see in later chapters. +) + +$(P +I will leave one peculiarity about the use of $(C readf) for later; for now, let's accept as a rule that the first argument to $(C readf) must be $(STRING "%s"): +) + +--- + readf("%s", &studentCount); +--- + +$(P +Actually, $(C readf) can work without the $(C &) character as well: +) + +--- + readf("%s", studentCount); // same as above +--- + +$(P +Although the code is cleaner and safer without the $(C &) character, I will continue to use $(C readf) with pointers partly to prepare you to the concepts of $(LINK2 value_vs_reference.html, references) and $(LINK2 function_parameters.html, reference function parameters). +) + +$(P +$(STRING "%s") indicates that the data should automatically be converted in a way that is suitable to the type of the variable. For example, when the '4' and '2' characters are read to a variable of type $(C int), they are converted to the integer value 42. +) + +$(P +The program below asks the user to enter the number of students. You must press the Enter key after typing the input: +) + +--- +import std.stdio; + +void main() { + write("How many students are there? "); + + /* The definition of the variable that will be used to + * store the information that is read from the input. */ + int studentCount; + + // Storing the input data to that variable + readf("%s", &studentCount); + + writeln("Got it: There are ", studentCount, " students."); +} +--- + +$(H5 $(IX %s, with whitespace) $(IX whitespace) Skipping the whitespace characters) + +$(P +Even the Enter key that we press after typing the data is stored as a special code and is placed into the $(C stdin) stream. This is useful to the programs to detect whether the information has been input on a single line or multiple lines. +) + +$(P +Although sometimes useful, such special codes are mostly not important for the program and must be filtered out from the input. Otherwise they $(I block) the input and prevent reading other data. +) + +$(P +To see this $(I problem) in a program, let's also read the number of teachers from the input: +) + +--- +import std.stdio; + +void main() { + write("How many students are there? "); + int studentCount; + readf("%s", &studentCount); + + write("How many teachers are there? "); + int teacherCount; + readf("%s", &teacherCount); + + writeln("Got it: There are ", studentCount, " students", + " and ", teacherCount, " teachers."); +} +--- + +$(P +Unfortunately, the program cannot use that special code when expecting an $(C int) value: +) + +$(SHELL +How many students are there? 100 +How many teachers are there? 20 + $(SHELL_NOTE_WRONG An exception is thrown here) +) + +$(P +Although the user enters the number of teachers as 20, the special code(s) that represents the Enter key that has been pressed when entering the previous 100 is still in the input stream and is blocking it. The characters that appeared in the input stream are similar to the following representation: +) + +$(MONO +100$(HILITE [EnterCode])20[EnterCode] +) + +$(P +I have highlighted the Enter code that is blocking the input. +) + +$(P +The solution is to use a space character before $(STRING %s) to indicate that the Enter code that appears before reading the number of teachers is not important: $(STRING " %s"). Spaces that are in the format strings are used to read and ignore zero or more invisible characters that would otherwise appear in the input. Such characters include the actual space character, the code(s) that represent the Enter key, the Tab character, etc. and are called the $(I whitespace characters). +) + +$(P +As a general rule, you can use $(STRING " %s") for every data that is read from the input. The program above works as expected with the following changes: +) + +--- +// ... + readf(" %s", &studentCount); +// ... + readf(" %s", &teacherCount); +// ... +--- + +$(P +The output: +) + +$(SHELL +How many students are there? 100 +How many teachers are there? 20 +Got it: There are 100 students and 20 teachers. +) + +$(H5 Additional information) + +$(UL + +$(LI +$(IX comment) $(IX /*) $(IX */) Lines that start with $(COMMENT //) are useful for single lines of comments. To write multiple lines as a single comment, enclose the lines within $(COMMENT /*) and $(COMMENT */) markers. + + +$(P +$(IX /+) $(IX +/) In order to be able to comment even other comments, use $(COMMENT /+) and $(COMMENT +/): + +) + +--- + /+ + // A single line of comment + + /* + A comment that spans + multiple lines + */ + + /+ + It can even include nested /+ comments +/ + +/ + + A comment block that includes other comments + +/ +--- + +) + +$(LI +Most of the whitespace in the source code is insignificant. It is good practice to write longer expressions as multiple lines or add extra whitespace to make the code more readable. Still, as long as the syntax rules of the language are observed, the programs can be written without any extra whitespace: + +--- +import std.stdio;void main(){writeln("Hard to read!");} +--- + +$(P +It can be hard to read source code with small amounts of whitespace. +) + +) + +) + +$(PROBLEM_TEK + +$(P +Enter non-numerical characters when the program is expecting integer values and observe that the program does not work correctly. +) + +) + + +Macros: + TITLE=Reading from the Standard Input + + DESCRIPTION=Getting information from the input in D + + KEYWORDS=d programming language tutorial book read stdin + +MINI_SOZLUK= diff --git a/book/d.en/interface.d b/book/d.en/interface.d new file mode 100644 index 0000000000..29b6454cca --- /dev/null +++ b/book/d.en/interface.d @@ -0,0 +1,657 @@ +Ddoc + +$(DERS_BOLUMU $(IX interface) Interfaces) + +$(P +The $(C interface) keyword is for defining interfaces in class hierarchies. $(C interface) is very similar to $(C class) with the following restrictions: +) + +$(UL + +$(LI +The member functions that it declares (but not implements) are abstract even without the $(C abstract) keyword. +) + +$(LI +The member functions that it implements must be $(C static) or $(C final). ($(C static) and $(C final) member functions are explained below.) +) + +$(LI +Its member variables must be $(C static). +) + +$(LI +Interfaces can inherit only interfaces. +) + +) + +$(P +Despite these restrictions, there is no limit on the number of $(C interface)s that a class can inherit from. (In contrast, a class can inherit from up to one $(C class).) +) + +$(H5 Definition) + +$(P +Interfaces are defined by the $(C interface) keyword, the same way as classes: +) + +--- +$(HILITE interface) SoundEmitter { + // ... +} +--- + +$(P +An $(C interface) is for declaring member functions that are implicitly abstract: +) + +--- +interface SoundEmitter { + string emitSound(); // Declared (not implemented) +} +--- + +$(P +Classes that inherit from that interface would have to provide the implementations of the abstract functions of the interface. +) + +$(P +Interface function declarations can have $(C in) and $(C out) contract blocks: +) + +--- +interface I { + int func(int i) + $(HILITE in) { + /* Strictest requirements that the callers of this + * function must meet. (Derived interfaces and classes + * can loosen these requirements.) */ + + } $(HILITE out) { // (optionally with (result) parameter) + /* Exit guarantees that the implementations of this + * function must give. (Derived interfaces and classes + * can give additional guarantees.) */ + } +} +--- + +$(P +We will see examples of contract inheritance later in $(LINK2 invariant.html, the Contract Programming for Structs and Classes chapter). +) + +$(H5 Inheriting from an $(C interface)) + +$(P +The $(C interface) inheritance syntax is the same as $(C class) inheritance: +) + +--- +class Violin : $(HILITE SoundEmitter) { + string emitSound() { + return "♩♪♪"; + } +} + +class Bell : $(HILITE SoundEmitter) { + string emitSound() { + return "ding"; + } +} +--- + +$(P +Interfaces support polymorphism: Functions that take interface parameters can use those parameters without needing to know the actual types of objects. For example, the following function that takes a parameter of $(C SoundEmitter) calls $(C emitSound()) on that parameter without needing to know the actual type of the object: +) + +--- +void useSoundEmittingObject(SoundEmitter object) { + // ... some operations ... + writeln(object.emitSound()); + // ... more operations ... +} +--- + +$(P +Just like with classes, that function can be called with any type of object that inherits from the $(C SoundEmitter) interface: +) + +--- + useSoundEmittingObject(new Violin); + useSoundEmittingObject(new Bell); +--- + +$(P +The special $(C emitSound()) function for each object would get called and the outputs of $(C Violin.emitSound) and $(C Bell.emitSound) would be printed: +) + +$(SHELL +♩♪♪ +ding +) + +$(H5 Inheriting from more than one $(C interface)) + +$(P +A class can be inherited from up to one $(C class). There is no limit on the number of $(C interface)s to inherit from. +) + +$(P +Let's consider the following interface that represents communication devices: +) + +--- +interface CommunicationDevice { + void talk(string message); + string listen(); +} +--- + +$(P +If a $(C Phone) class needs to be used both as a sound emitter and a communication device, it can inherit both of those interfaces: +) + +--- +class Phone : $(HILITE SoundEmitter, CommunicationDevice) { + // ... +} +--- + +$(P +That definition represents both of these relationships: "phone is a sound emitter" and "phone is a communication device." +) + +$(P +In order to construct objects of this class, $(C Phone) must implement the abstract functions of both of the interfaces: +) + +--- +class Phone : SoundEmitter, CommunicationDevice { + string emitSound() { // for SoundEmitter + return "rrring"; + } + + void talk(string message) { // for CommunicationDevice + // ... put the message on the line ... + } + + string listen() { // for CommunicationDevice + string soundOnTheLine; + // ... get the message from the line ... + return soundOnTheLine; + } +} +--- + +$(P +A class can inherit from any number of interfaces as it makes sense according to the design of the program. +) + +$(H5 Inheriting from $(C interface) and $(C class)) + +$(P +Classes can still inherit from up to one $(C class) as well: +) + +--- +$(HILITE class) Clock { + // ... clock implementation ... +} + +class AlarmClock : $(HILITE Clock), SoundEmitter { + string emitSound() { + return "beep"; + } +} +--- + +$(P +$(C AlarmClock) inherits the members of $(C Clock). Additionally, it also provides the $(C emitSound()) function that the $(C SoundEmitter) interface requires. +) + +$(H5 Inheriting $(C interface) from $(C interface)) + +$(P +An interface that is inherited from another interface effectively increases the number of functions that the subclasses must implement: +) + +--- +interface MusicalInstrument : SoundEmitter { + void adjustTuning(); +} +--- + +$(P +According to the definition above, in order to be a $(C MusicalInstrument), both the $(C emitSound()) function that $(C SoundEmitter) requires and the $(C adjustTuning()) function that $(C MusicalInstrument) requires must be implemented. +) + +$(P +For example, if $(C Violin) inherits from $(C MusicalInstrument) instead of $(C SoundEmitter), it must now also implement $(C adjustTuning()): +) + +--- +class Violin : MusicalInstrument { + string emitSound() { // for SoundEmitter + return "♩♪♪"; + } + + void adjustTuning() { // for MusicalInstrument + // ... special tuning of the violin ... + } +} +--- + +$(H5 $(IX static, member function) $(C static) member functions) + +$(P +I have delayed explaining $(C static) member functions until this chapter to keep the earlier chapters shorter. $(C static) member functions are available for structs, classes, and interfaces. +) + +$(P +Regular member functions are always called on an object. The member variables that are referenced inside the member function are the members of a particular object: +) + +--- +struct Foo { + int i; + + void modify(int value) { + $(HILITE i) = value; + } +} + +void main() { + auto object0 = Foo(); + auto object1 = Foo(); + + object0.modify(10); // object0.i changes + object1.modify(10); // object1.i changes +} +--- + +$(P +The members can also be referenced by $(C this): +) + +--- + void modify(int value) { + this.i = value; // equivalent of the previous one + } +--- + +$(P +A $(C static) member function does not operate on an object; there is no object that the $(C this) keyword would refer to, so $(C this) is not valid inside a $(C static) function. For that reason, none of the regular member variables are available inside $(C static) member functions: +) + +--- +struct Foo { + int i; + + $(HILITE static) void commonFunction(int value) { + i = value; $(DERLEME_HATASI) + this.i = value; $(DERLEME_HATASI) + } +} +--- + +$(P +$(C static) member functions can use only the $(C static) member variables. +) + +$(P +Let's redesign the $(C Point) struct that we have seen earlier in $(LINK2 struct.html, the Structs chapter), this time with a $(C static) member function. In the following code, every $(C Point) object gets a unique id, which is determined by a $(C static) member function: +) + +--- +import std.stdio; + +struct Point { + size_t id; // Object id + int line; + int column; + + // The id to be used for the next object + $(HILITE static) size_t nextId; + + this(int line, int column) { + this.line = line; + this.column = column; + this.id = makeNewId(); + } + + $(HILITE static) size_t makeNewId() { + immutable newId = nextId; + ++nextId; + return newId; + } +} + +void main() { + auto top = Point(7, 0); + auto middle = Point(8, 0); + auto bottom = Point(9, 0); + + writeln(top.id); + writeln(middle.id); + writeln(bottom.id); +} +--- + +$(P +The $(C static) $(C makeNewId()) function can use the common variable $(C nextId). As a result, every object gets a unique id: +) + +$(SHELL +0 +1 +2 +) + +$(P +Although the example above contains a $(C struct), $(C static) member functions are available for classes and interfaces as well. +) + +$(H5 $(IX final) $(C final) member functions) + +$(P +I have delayed explaining $(C final) member functions until this chapter to keep the earlier chapters shorter. $(C final) member functions are relevant only for classes and interfaces because structs do not support inheritance. +) + +$(P +$(C final) specifies that a member function cannot be redefined by a subclass. In a sense, the implementation that this $(C class) or $(C interface) provides is the $(I final) implementation of that function. An example of a case where this feature is useful is where the general steps of an algorithm are defined by an interface and the finer details are left to subclasses. +) + +$(P +Let's see an example of this with a $(C Game) interface. The general steps of playing a game is being determined by the $(C play()) function of the following $(C interface): +) + +--- +$(CODE_NAME Game)interface Game { + $(HILITE final) void play() { + string name = gameName(); + writefln("Starting %s", name); + + introducePlayers(); + prepare(); + begin(); + end(); + + writefln("Ending %s", name); + } + + string gameName(); + void introducePlayers(); + void prepare(); + void begin(); + void end(); +} +--- + +$(P +It is not possible for subclasses to modify the definition of the $(C play()) member function. The subclasses can (and must) provide the definitions of the five abstract member functions that are declared by the interface. By doing so, the subclasses complete the missing steps of the algorithm: +) + +--- +$(CODE_XREF Game)import std.stdio; +import std.string; +import std.random; +import std.conv; + +class DiceSummingGame : Game { + string player; + size_t count; + size_t sum; + + string gameName() { + return "Dice Summing Game"; + } + + void introducePlayers() { + write("What is your name? "); + player = strip(readln()); + } + + void prepare() { + write("How many times to throw the dice? "); + readf(" %s", &count); + sum = 0; + } + + void begin() { + foreach (i; 0 .. count) { + immutable dice = uniform(1, 7); + writefln("%s: %s", i, dice); + sum += dice; + } + } + + void end() { + writefln("Player: %s, Dice sum: %s, Average: %s", + player, sum, to!double(sum) / count); + } +} + +void useGame(Game game) { + game.play(); +} + +void main() { + useGame(new DiceSummingGame()); +} +--- + +$(P +Although the example above contains an $(C interface), $(C final) member functions are available for classes as well. +) + +$(H5 How to use) + +$(P +$(C interface) is a commonly used feature. There is one or more $(C interface) at the top of almost every class hierarchy. A kind of hierarchy that is commonly encountered in programs involves a single $(C interface) and a number of classes that implement that interface: +) + +$(MONO + $(I MusicalInstrument + (interface)) + / | \ \ + Violin Guitar Flute ... +) + +$(P +Although there are more complicated hierarchies in practice, the simple hierarchy above solves many problems. +) + +$(P +It is also common to move common implementation details of class hierarchies to intermediate classes. The subclasses inherit from these intermediate classes. The $(C StringInstrument) and $(C WindInstrument) classes below can contain the common members of their respective subclasses: +) + +$(MONO + $(I MusicalInstrument + (interface)) + / \ + StringInstrument WindInstrument + / | \ / | \ +Violin Viola ... Flute Clarinet ... +) + +$(P +The subclasses would implement their respective special definitions of member functions. +) + +$(H5 $(IX abstraction) Abstraction) + +$(P +Interfaces help make parts of programs independent from each other. This is called $(I abstraction). For example, a program that deals with musical instruments can be written primarily by using the $(C MusicalInstrument) interface, without ever specifying the actual types of the musical instruments. +) + +$(P +A $(C Musician) class can contain a $(C MusicalInstrument) without ever knowing the actual type of the instrument: +) + +--- +class Musician { + MusicalInstrument instrument; + // ... +} +--- + +$(P +Different types of musical instruments can be combined in a collection without regard to the actual types of these instruments: +) + +--- + MusicalInstrument[] orchestraInstruments; +--- + +$(P +Most of the functions of the program can be written only by using this interface: +) + +--- +bool needsTuning(MusicalInstrument instrument) { + bool result; + // ... + return result; +} + +void playInTune(MusicalInstrument instrument) { + if (needsTuning(instrument)) { + instrument.adjustTuning(); + } + + writeln(instrument.emitSound()); +} +--- + +$(P +$(I Abstracting away) parts of a program from each other allows making changes in one part of the program without needing to modify the other parts. When implementations of certain parts of the program are $(I behind) a particular interface, the code that uses only that interface does not get affected. +) + +$(H5 Example) + +$(P +The following program defines the $(C SoundEmitter), $(C MusicalInstrument), and $(C CommunicationDevice) interfaces: +) + +--- +import std.stdio; + +/* This interface requires emitSound(). */ +interface SoundEmitter { + string emitSound(); +} + +/* This class needs to implement only emitSound(). */ +class Bell : SoundEmitter { + string emitSound() { + return "ding"; + } +} + +/* This interface additionally requires adjustTuning(). */ +interface MusicalInstrument : SoundEmitter { + void adjustTuning(); +} + +/* This class needs to implement both emitSound() and + * adjustTuning(). */ +class Violin : MusicalInstrument { + string emitSound() { + return "♩♪♪"; + } + + void adjustTuning() { + // ... tuning of the violin ... + } +} + +/* This interface requires talk() and listen(). */ +interface CommunicationDevice { + void talk(string message); + string listen(); +} + +/* This class needs to implement emitSound(), talk(), and + * listen(). */ +class Phone : SoundEmitter, CommunicationDevice { + string emitSound() { + return "rrring"; + } + + void talk(string message) { + // ... put the message on the line ... + } + + string listen() { + string soundOnTheLine; + // ... get the message from the line ... + return soundOnTheLine; + } +} + +class Clock { + // ... the implementation of Clock ... +} + +/* This class needs to implement only emitSound(). */ +class AlarmClock : Clock, SoundEmitter { + string emitSound() { + return "beep"; + } + + // ... the implementation of AlarmClock ... +} + +void main() { + SoundEmitter[] devices; + + devices ~= new Bell; + devices ~= new Violin; + devices ~= new Phone; + devices ~= new AlarmClock; + + foreach (device; devices) { + writeln(device.emitSound()); + } +} +--- + +$(P +Because $(C devices) is a $(C SoundEmitter) slice, it can contain objects of any type that inherits from $(C SoundEmitter) (i.e. types that have an "is a" relationship with $(C SoundEmitter)). As a result, the output of the program consists of different sounds that are emitted by the different types of objects: +) + +$(SHELL +ding +♩♪♪ +rrring +beep +) + +$(H5 Summary) + +$(UL + +$(LI +$(C interface) is similar to a $(C class) that consists only of abstract functions. $(C interface) can have $(C static) member variables and $(C static) or $(C final) member functions. +) + +$(LI +For a class to be constructible, it must have implementations for all member functions of all interfaces that it inherits from. +) + +$(LI +It is possible to inherit from unlimited number of $(C interface)s. +) + +$(LI +A common hierarchy consists of a single $(C interface) and a number of subclasses that implement that interface. +) + +) + +Macros: + TITLE=Interfaces + + DESCRIPTION=The interfaces of the D programming language. + + KEYWORDS=d programming lesson book tutorial interface diff --git a/book/d.en/invariant.d b/book/d.en/invariant.d new file mode 100644 index 0000000000..ae68ff6d95 --- /dev/null +++ b/book/d.en/invariant.d @@ -0,0 +1,401 @@ +Ddoc + +$(DERS_BOLUMU $(IX contract programming) Contract Programming for Structs and Classes) + +$(P +Contract programming is very effective in reducing coding errors. We have seen two of the contract programming features earlier in $(LINK2 contracts.html, the Contract Programming chapter): The $(C in) and $(C out) blocks ensure input and output contracts of functions. +) + +$(P +$(I $(B Note:) It is very important that you consider the guidelines under the "$(C in) blocks versus $(C enforce) checks" section of that chapter. The examples in this chapter are based on the assumption that problems with object and parameter consistencies are due to programmer errors. Otherwise, you should use $(C enforce) checks inside function bodies.) +) + +$(P +As a reminder, let's write a function that calculates the area of a triangle by Heron's formula. We will soon move the $(C in) and $(C out) blocks of this function to the constructor of a struct. +) + +$(P +For this calculation to work correctly, the length of every side of the triangle must be greater than zero. Additionally, since it is impossible to have a triangle where one of the sides is greater than the sum of the other two, that condition must also be checked. +) + +$(P +Once these input conditions are satisfied, the area of the triangle would be greater than zero. The following function ensures that all of these requirements are satisfied: +) + +--- +private import std.math; + +double triangleArea(double a, double b, double c) +in { + // Every side must be greated than zero + assert(a > 0); + assert(b > 0); + assert(c > 0); + + // Every side must be less than the sum of the other two + assert(a < (b + c)); + assert(b < (a + c)); + assert(c < (a + b)); + +} out (result) { + assert(result > 0); + +} do { + immutable halfPerimeter = (a + b + c) / 2; + + return sqrt(halfPerimeter + * (halfPerimeter - a) + * (halfPerimeter - b) + * (halfPerimeter - c)); +} +--- + +$(H5 $(IX in, contract) $(IX out, contract) $(IX precondition) $(IX postcondition) Preconditions and postconditions for member functions) + +$(P +The $(C in) and $(C out) blocks can be used with member functions as well. +) + +$(P +Let's convert the function above to a member function of a $(C Triangle) struct: +) + +--- +import std.stdio; +import std.math; + +struct Triangle { +private: + + double a; + double b; + double c; + +public: + + double area() const + $(HILITE out (result)) { + assert(result > 0); + + } do { + immutable halfPerimeter = (a + b + c) / 2; + + return sqrt(halfPerimeter + * (halfPerimeter - a) + * (halfPerimeter - b) + * (halfPerimeter - c)); + } +} + +void main() { + auto threeFourFive = Triangle(3, 4, 5); + writeln(threeFourFive.area); +} +--- + +$(P +As the sides of the triangle are now member variables, the function does not take parameters anymore. That is why this function does not have an $(C in) block. Instead, it assumes that the members already have consistent values. +) + +$(P +The consistency of objects can be ensured by the following features. +) + +$(H5 Preconditions and postconditions for object consistency) + +$(P +The member function above is written under the assumption that the members of the object already have consistent values. One way of ensuring that assumption is to define an $(C in) block for the constructor so that the objects are guaranteed to start their lives in consistent states: +) + +--- +struct Triangle { +// ... + + this(double a, double b, double c) + $(HILITE in) { + // Every side must be greated than zero + assert(a > 0); + assert(b > 0); + assert(c > 0); + + // Every side must be less than the sum of the other two + assert(a < (b + c)); + assert(b < (a + c)); + assert(c < (a + b)); + + } do { + this.a = a; + this.b = b; + this.c = c; + } + +// ... +} +--- + +$(P +This prevents creating invalid $(C Triangle) objects at run time: +) + +--- + auto negativeSide = Triangle(-1, 1, 1); + auto sideTooLong = Triangle(1, 1, 10); +--- + +$(P +The $(C in) block of the constructor would prevent such invalid objects: +) + +$(SHELL +core.exception.AssertError@deneme.d: Assertion failure +) + +$(P +Although an $(C out) block has not been defined for the constructor above, it is possible to define one to ensure the consistency of members right after construction. +) + +$(H5 $(IX invariant) $(C invariant()) blocks for object consistency) + +$(P +The $(C in) and $(C out) blocks of constructors guarantee that the objects start their lives in consistent states and the $(C in) and $(C out) blocks of member functions guarantee that those functions themselves work correctly. +) + +$(P +However, these checks are not suitable for guaranteeing that the objects are always in consistent states. Repeating the $(C out) blocks for every member function would be excessive and error-prone. +) + +$(P +The conditions that define the consistency and validity of an object are called the $(I invariants) of that object. For example, if there is a one-to-one correspondence between the orders and the invoices of a customer class, then an invariant of that class would be that the lengths of the order and invoice arrays would be equal. When that condition is not satisfied for any object, then the object would be in an inconsistent state. +) + +$(P +As an example of an invariant, let's consider the $(C School) class from $(LINK2 encapsulation.html, the Encapsulation and Protection Attributes chapter): +) + +--- +class School { +private: + + Student[] students; + size_t femaleCount; + size_t maleCount; + +// ... +} +--- + +$(P +The objects of that class are consistent only if an invariant that involves its three members are satisfied. The length of the student array must be equal to the sum of the female and male students: +) + +--- + assert(students.length == (femaleCount + maleCount)); +--- + +$(P +If that condition is ever false, then there must be a bug in the implementation of this class. +) + +$(P +$(C invariant()) blocks are for guaranteeing the invariants of user-defined types. $(C invariant()) blocks are defined inside the body of a $(C struct) or a $(C class). They contain $(C assert) checks similar to $(C in) and $(C out) blocks: +) + +--- +class School { +private: + + Student[] students; + size_t femaleCount; + size_t maleCount; + + $(HILITE invariant()) { + assert(students.length == (femaleCount + maleCount)); + } + +// ... +} +--- + +$(P +As needed, there can be more than one $(C invariant()) block in a user-defined type. +) + +$(P +The $(C invariant()) blocks are executed automatically at the following times: +) + +$(UL + +$(LI After the execution of the constructor: This guarantees that every object starts its life in a consistent state.) + +$(LI Before the execution of the destructor: This guarantees that the destructor will be executed on a consistent object.) + +$(LI Before and after the execution of a $(C public) member function: This guarantees that the member functions do not invalidate the consistency of objects. + +$(P +$(IX export) $(I $(B Note:) $(C export) functions are the same as $(C public) functions in this regard. (Very briefly, $(C export) functions are functions that are exported on dynamic library interfaces.)) +) + +) + +) + +$(P +If an $(C assert) check inside an $(C invariant()) block fails, an $(C AssertError) is thrown. This ensures that the program does not continue executing with invalid objects. +) + +$(P +$(IX -release, compiler switch) As with $(C in) and $(C out) blocks, the checks inside $(C invariant()) blocks can be disabled by the $(C -release) command line option: +) + +$(SHELL +$ dmd deneme.d -w -release +) + +$(H5 $(IX contract inheritance) $(IX inheritance, contract) $(IX precondition, inherited) $(IX postcondition, inherited) $(IX in, inherited) $(IX out, inherited) Contract inheritance) + +$(P +Interface and class member functions can have $(C in) and $(C out) blocks as well. This allows an $(C interface) or a $(C class) to define preconditions for its derived types to depend on, as well as to define postconditions for its users to depend on. Derived types can define further $(C in) and $(C out) blocks for the overrides of those member functions. Overridden $(C in) blocks can loosen preconditions and overridden $(C out) blocks can offer more guarantees. +) + +$(P +User code is commonly $(I abstracted away) from the derived types, written in a way to satisfy the preconditions of the topmost type in a hierarchy. The user code does not even know about the derived types. Since user code would be written for the contracts of an interface, it would not be acceptable for a derived type to put stricter preconditions on an overridden member function. However, the preconditions of a derived type can be more permissive than the preconditions of its superclass. +) + +$(P +Upon entering a function, the $(C in) blocks are executed automatically from the topmost type to the bottom-most type in the hierarchy . If $(I any) $(C in) block succeeds without any $(C assert) failure, then the preconditions are considered to be fulfilled. +) + +$(P +Similarly, derived types can define $(C out) blocks as well. Since postconditions are about guarantees that a function provides, the member functions of the derived type must observe the postconditions of its ancestors as well. On the other hand, it can provide additional guarantees. +) + +$(P +Upon exiting a function, the $(C out) blocks are executed automatically from the topmost type to the bottom-most type. The function is considered to have fullfilled its postconditions only if $(I all) of the $(C out) blocks succeed. +) + +$(P +The following artificial program demonstrates these features on an $(C interface) and a $(C class). The $(C class) requires less from its callers while providing more guarantees: +) + +--- +interface Iface { + int[] func(int[] a, int[] b) + $(HILITE in) { + writeln("Iface.func.in"); + + /* This interface member function requires that the + * lengths of the two parameters are equal. */ + assert(a.length == b.length); + + } $(HILITE out) (result) { + writeln("Iface.func.out"); + + /* This interface member function guarantees that the + * result will have even number of elements. + * (Note that an empty slice is considered to have + * even number of elements.) */ + assert((result.length % 2) == 0); + } +} + +class Class : Iface { + int[] func(int[] a, int[] b) + $(HILITE in) { + writeln("Class.func.in"); + + /* This class member function loosens the ancestor's + * preconditions by allowing parameters with unequal + * lengths as long as at least one of them is empty. */ + assert((a.length == b.length) || + (a.length == 0) || + (b.length == 0)); + + } $(HILITE out) (result) { + writeln("Class.func.out"); + + /* This class member function provides additional + * guarantees: The result will not be empty and that + * the first and the last elements will be equal. */ + assert((result.length != 0) && + (result[0] == result[$ - 1])); + + } do { + writeln("Class.func.do"); + + /* This is just an artificial implementation to + * demonstrate how the 'in' and 'out' blocks are + * executed. */ + + int[] result; + + if (a.length == 0) { + a = b; + } + + if (b.length == 0) { + b = a; + } + + foreach (i; 0 .. a.length) { + result ~= a[i]; + result ~= b[i]; + } + + result[0] = result[$ - 1] = 42; + + return result; + } +} + +import std.stdio; + +void main() { + auto c = new Class(); + + /* Although the following call fails Iface's precondition, + * it is accepted because it fulfills Class' precondition. */ + writeln(c.func([1, 2, 3], $(HILITE []))); +} +--- + +$(P +The $(C in) block of $(C Class) is executed only because the parameters fail to satisfy the preconditions of $(C Iface): +) + +$(SHELL +Iface.func.in +Class.func.in $(SHELL_NOTE would not be executed if Iface.func.in succeeded) +Class.func.do +Iface.func.out +Class.func.out +[42, 1, 2, 2, 3, 42] +) + +$(H5 Summary) + +$(UL + +$(LI $(C in) and $(C out) blocks are useful in constructors as well. They ensure that objects are constructed in valid states. +) + +$(LI +$(C invariant()) blocks ensure that objects remain in valid states throughout their lifetimes. +) + +$(LI +Derived types can define $(C in) blocks for overridden member functions. Preconditions of a derived type should not be stricter than the preconditions of its superclasses. ($(I Note that not defining an $(C in) block means "no precondition at all", which may not be the intent of the programmer.)) +) + +$(LI +Derived types can define $(C out) blocks for overridden member functions. In addition to its own, a derived member function must observe the postconditions of its superclasses as well. +) + +) + +Macros: + TITLE=Contract Programming for Structs and Classes + + DESCRIPTION=The invariant keyword that ensures that struct and class objects are always in consistent states. + + KEYWORDS=d programming lesson book tutorial invariant diff --git a/book/d.en/io.cozum.d b/book/d.en/io.cozum.d new file mode 100644 index 0000000000..f064b0568b --- /dev/null +++ b/book/d.en/io.cozum.d @@ -0,0 +1,21 @@ +Ddoc + +$(COZUM_BOLUMU Standard Input and Output Streams) + +--- +import std.stdio; + +void main() { + stdout.write(1, ",", 2); + + // To complete the line if needed: + writeln(); +} +--- + +Macros: + TITLE=Standard Input and Output Streams Solutions + + DESCRIPTION=Programming in D exercise solutions: standard input and output streams + + KEYWORDS=programming in d tutorial standard input and output stream solution diff --git a/book/d.en/io.d b/book/d.en/io.d new file mode 100644 index 0000000000..420226338a --- /dev/null +++ b/book/d.en/io.d @@ -0,0 +1,58 @@ +Ddoc + +$(DERS_BOLUMU $(IX standard input) $(IX standard output) Standard Input and Output Streams) + +$(P +So far, the printed output of our programs has been appearing on the $(I terminal window) (or $(I screen)). Although the terminal is often the ultimate target of output, this is not always the case. The objects that can accept output are called $(I standard output streams). +) + +$(P +The standard output is character based; everything to be printed is first converted to the corresponding character representation and then sent to the output as characters. For example, the integer value 100 that we've printed in the last chapter is not sent to the output as the value 100, but as the three characters $(C 1), $(C 0), and $(C 0). +) + +$(P +Similarly, what we normally perceive as the $(I keyboard) is actually the $(I standard input stream) of a program and is also character based. The information always comes as characters to be converted to data. For example, the integer value 42 actually comes through the standard input as the characters $(C 4) and $(C 2). +) + +$(P +These conversions happen automatically. +) + +$(P +This concept of consecutive characters is called a $(I character stream). As D's standard input and standard output fit this description, they are character streams. +) + +$(P +$(IX stdin) $(IX stdout) The names of the standard input and output streams in D are $(C stdin) and $(C stdout), respectively. +) + +$(P +Operations on these streams normally require the name of the stream, a dot, and the operation; as in $(C stream.operation()). Because $(C stdin)'s reading methods and $(C stdout)'s writing methods are used very commonly, those operations can be called without the need of the stream name and the dot. +) + +$(P +$(C writeln) that we've been using in the previous chapters is actually short for $(C stdout.writeln). Similarly, $(C write) is short for $(C stdout.write). Accordingly, the $(I hello world) program can also be written as follows: +) + +--- +import std.stdio; + +void main() { + $(HILITE stdout.)writeln("Hello, World!"); +} +--- + +$(PROBLEM_TEK + +$(P +Observe that $(C stdout.write) works the same as $(C write). +) + +) + +Macros: + TITLE=Standard Input and Output Streams + + DESCRIPTION=D's standard input and output streams stdin and stdout. + + KEYWORDS=d programming language tutorial book stdin stdout diff --git a/book/d.en/is_expr.d b/book/d.en/is_expr.d new file mode 100644 index 0000000000..ace356856e --- /dev/null +++ b/book/d.en/is_expr.d @@ -0,0 +1,558 @@ +Ddoc + +$(DERS_BOLUMU $(IX is, expression) $(CH4 is) Expression) + +$(P +The $(C is) $(I expression) is not related to the $(C is) $(I operator) that we saw in $(LINK2 null_is.html, The $(CH4 null) Value and the $(CH4 is) Operator chapter), neither syntactically nor semantically: +) + +--- + a is b // is operator, which we have seen before + + is (/* ... */) // is expression +--- + +$(P +The $(C is) expression is evaluated at compile time. It produces an $(C int) value, either 0 or 1 depending on the expression specified in parentheses. Although the expression that it takes is not a logical expression, the $(C is) expression itself is used as a compile time logical expression. It is especially useful in $(C static if) conditionals and template constraints. +) + +$(P +The condition that it takes is always about types, which must be written in one of several syntaxes. +) + +$(H5 $(C is ($(I T)))) + +$(P +Determines whether $(C T) is valid as a type. +) + +$(P +It is difficult to come up with examples for this use at this point. We will take advantage of it in later chapters with template parameters. +) + +--- + static if (is (int)) { + writeln("valid"); + + } else { + writeln("invalid"); + } +--- + +$(P +$(C int) above is a valid type: +) + +$(SHELL_SMALL +valid +) + +$(P +As another example, because $(C void) is not valid as the key type of an associative array, the $(C else) block would be enabled below: +) + +--- + static if (is (string[void])) { + writeln("valid"); + + } else { + writeln("invalid"); + } +--- + +$(P +The output: +) + +$(SHELL_SMALL +invalid +) + + +$(H5 $(C is ($(I T Alias)))) + +$(P +Works in the same way as the previous syntax. Additionally, defines $(C Alias) as an alias of $(C T): +) + +--- + static if (is (int NewAlias)) { + writeln("valid"); + NewAlias var = 42; // int and NewAlias are the same + + } else { + writeln("invalid"); + } +--- + +$(P +Such aliases are useful especially in more complex $(C is) expressions as we will see below. +) + +$(H5 $(C is ($(I T) : $(I OtherT)))) + +$(P +Determines whether $(C T) can automatically be converted to $(C OtherT). +) + +$(P +It is used for detecting automatic type conversions which we have seen in $(LINK2 cast.html, the Type Conversions chapter), as well as relationships like "this type is of that type", which we have seen in $(LINK2 inheritance.html, the Inheritance chapter). +) + +--- +import std.stdio; + +interface Clock { + void tellTime(); +} + +class AlarmClock : Clock { + override void tellTime() { + writeln("10:00"); + } +} + +void myFunction(T)(T parameter) { + static if ($(HILITE is (T : Clock))) { + // If we are here then T can be used as a Clock + writeln("This is a Clock; we can tell the time"); + parameter.tellTime(); + + } else { + writeln("This is not a Clock"); + } +} + +void main() { + auto var = new AlarmClock; + myFunction(var); + myFunction(42); +} +--- + +$(P +When the $(C myFunction()) template is instantiated for a type that can be used like a $(C Clock), then the $(C tellTime()) member function is called on its parameter. Otherwise, the $(C else) clause gets compiled: +) + +$(SHELL_SMALL +This is a Clock; we can tell the time $(SHELL_NOTE for AlarmClock) +10:00 $(SHELL_NOTE for AlarmClock) +This is not a Clock $(SHELL_NOTE for int) +) + +$(H5 $(C is ($(I T Alias) : $(I OtherT)))) + +$(P +Works in the same way as the previous syntax. Additionally, defines $(C Alias) as an alias of $(C T). +) + +$(H5 $(C is ($(I T) == $(I Specifier)))) + +$(P +Determines whether $(C T) $(I is the same type) as $(C Specifier) or whether $(C T) $(I matches that specifier). +) + +$(H6 Whether the same type) + +$(P +When we change the previous example to use $(C ==) instead of $(C :), the condition would not be satisfied for $(C AlarmClock): +) + +--- + static if (is (T $(HILITE ==) Clock)) { + writeln("This is a Clock; we can tell the time"); + parameter.tellTime(); + + } else { + writeln("This is not a Clock"); + } +--- + +$(P +Although $(C AlarmClock) $(I is a) $(C Clock), it is not exactly the same type as $(C Clock). For that reason, now the condition is invalid for both $(C AlarmClock) and $(C int): +) + +$(SHELL_SMALL +This is not a Clock +This is not a Clock +) + +$(H6 Whether matches the same specifier) + +$(P +When $(C Specifier) is one of the following keywords, this use of $(C is) determines whether the type matches that specifier (we will see some of these keywords in later chapters): +) + +$(UL +$(LI $(IX struct, is expression) $(C struct)) +$(LI $(IX union, is expression) $(C union)) +$(LI $(IX class, is expression) $(C class)) +$(LI $(IX interface, is expression) $(C interface)) +$(LI $(IX enum, is expression) $(C enum)) +$(LI $(IX function, is expression) $(C function)) +$(LI $(IX delegate, is expression) $(C delegate)) +$(LI $(IX const, is expression) $(C const)) +$(LI $(IX immutable, is expression) $(C immutable)) +$(LI $(IX shared, is expression) $(C shared)) +) + +--- +void myFunction(T)(T parameter) { + static if (is (T == class)) { + writeln("This is a class type"); + + } else static if (is (T == enum)) { + writeln("This is an enum type"); + + } else static if (is (T == const)) { + writeln("This is a const type"); + + } else { + writeln("This is some other type"); + } +} +--- + +$(P +Function templates can take advantage of such information to behave differently depending on the type that the template is instantiated with. The following code demonstrates how different blocks of the template above get compiled for different types: +) + +--- + auto var = new AlarmClock; + myFunction(var); + + // (enum WeekDays will be defined below for another example) + myFunction(WeekDays.Monday); + + const double number = 1.2; + myFunction(number); + + myFunction(42); +--- + +$(P +The output: +) + +$(SHELL_SMALL +This is a class type +This is an enum type +This is a const type +This is some other type +) + +$(H5 $(C is ($(I T identifier) == $(I Specifier)))) + +$(P +$(IX super, is expression) +$(IX return, is expression) +$(IX __parameters, is expression) +Works in the same way as the previous syntax. $(C identifier) is either an alias of the type; or some other information depending on $(C Specifier): +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    $(C Specifier)The meaning of $(C identifier)
    $(C struct)alias of the type that satisfied the condition
    $(C union)alias of the type that satisfied the condition
    $(C class)alias of the type that satisfied the condition
    $(C interface)alias of the type that satisfied the condition
    $(C super)a $(I tuple) consisting of the base classes and the interfaces
    $(C enum)the actual implementation type of the $(C enum)
    $(C function)a $(I tuple) consisting of the function parameters
    $(C delegate)the type of the $(C delegate)
    $(C return)the return type of the regular function, the $(C delegate), or the function pointer
    $(C __parameters)a $(I tuple) consisting of the parameters of the regular function, the $(C delegate), or the function pointer
    $(C const)alias of the type that satisfied the condition
    $(C immutable)alias of the type that satisfied the condition
    $(C shared)alias of the type that satisfied the condition
    + +$(P +Let's first define various types before experimenting with this syntax: +) + +--- +struct Point { + // ... +} + +interface Clock { + // ... +} + +class AlarmClock : Clock { + // ... +} + +enum WeekDays { + Monday, Tuesday, Wednesday, Thursday, Friday, + Saturday, Sunday +} + +char foo(double d, int i, Clock c) { + return 'a'; +} +--- + +$(P +The following function template uses different specifiers with this syntax of the $(C is) expression: +) + +--- +void myFunction(T)(T parameter) { + static if (is (T LocalAlias == struct)) { + writefln("\n-- struct --"); + // LocalAlias is the same as T. 'parameter' is the + // struct object that has been passed to this + // function. + + writefln("Constructing a new %s object by copying it.", + LocalAlias.stringof); + LocalAlias theCopy = parameter; + } + + static if (is (T baseTypes == super)) { + writeln("\n-- super --"); + // The 'baseTypes' tuple contains all of the base + // types of T. 'parameter' is the class variable that + // has been passed to this function. + + writefln("class %s has %s base types.", + T.stringof, baseTypes.length); + + writeln("All of the bases: ", baseTypes.stringof); + writeln("The topmost base: ", baseTypes[0].stringof); + } + + static if (is (T ImplT == enum)) { + writeln("\n-- enum --"); + // 'ImplT' is the actual implementation type of this + // enum type. 'parameter' is the enum value that has + // been passed to this function. + + writefln("The implementation type of enum %s is %s", + T.stringof, ImplT.stringof); + } + + static if (is (T ReturnT == return)) { + writeln("\n-- return --"); + // 'ReturnT' is the return type of the function + // pointer that has been passed to this function. + + writefln("This is a function with a return type of %s:", + ReturnT.stringof); + writeln(" ", T.stringof); + write("calling it... "); + + // Note: Function pointers can be called like + // functions + ReturnT result = parameter(1.5, 42, new AlarmClock); + writefln("and the result is '%s'", result); + } +} +--- + +$(P +Let's now call that function template with various types that we have defined above: +) + +--- + // Calling with a struct object + myFunction(Point()); + + // Calling with a class reference + myFunction(new AlarmClock); + + // Calling with an enum value + myFunction(WeekDays.Monday); + + // Calling with a function pointer + myFunction(&foo); +--- + +$(P +The output: +) + +$(SHELL_SMALL +-- struct -- +Constructing a new Point object by copying it. + +-- super -- +class AlarmClock has 2 base types. +All of the bases: (Object, Clock) +The topmost base: Object + +-- enum -- +The implementation type of enum WeekDays is int + +-- return -- +This is a function with a return type of char: + char function(double d, int i, Clock c) +calling it... and the result is 'a' +) + +$(H5 $(C is (/* ... */ $(I Specifier), $(I TemplateParamList)))) + +$(P +There are four different syntaxes of the $(C is) expression that uses a template parameter list: +) + +$(UL + +$(LI $(C is ($(I T) : $(I Specifier), $(I TemplateParamList)))) + +$(LI $(C is ($(I T) == $(I Specifier), $(I TemplateParamList)))) + +$(LI $(C is ($(I T identifier) : $(I Specifier), $(I TemplateParamList)))) + +$(LI $(C is ($(I T identifier) == $(I Specifier), $(I TemplateParamList)))) + +) + +$(P +These syntaxes allow for more complex cases. +) + +$(P +$(C identifier), $(C Specifier), $(C :), and $(C ==) all have the same meanings as described above. +) + +$(P +$(C TemplateParamList) is both a part of the condition that needs to be satisfied and a facility to define additional aliases if the condition is indeed satisfied. It works in the same way as template type deduction. +) + +$(P +As a simple example, let's assume that an $(C is) expression needs to match associative arrays that have keys of type $(C string): +) + +--- + static if (is (T == Value[Key], // (1) + Value, // (2) + Key : string)) { // (3) +--- + +$(P +That condition can be explained in three parts where the last two are parts of the $(C TemplateParamList): +) + +$(OL +$(LI If $(C T) matches the syntax of $(C Value[Key])) +$(LI If $(C Value) is a type) +$(LI If $(C Key) is $(C string) (remember $(LINK2 templates.html, template specialization syntax))) +) + +$(P +Having $(C Value[Key]) as the $(C Specifier) requires that $(C T) is an associative array. Leaving $(C Value) $(I as is) means that it can be any type. Additionally, the key type of the associative array must be $(C string). As a result, the previous $(C is) expression means "if $(C T) is an associative array where the key type is $(C string)." +) + +$(P +The following program tests that $(C is) expression with four different types: +) + +--- +import std.stdio; + +void myFunction(T)(T parameter) { + writefln("\n-- Called with %s --", T.stringof); + + static if (is (T == Value[Key], + Value, + Key : string)) { + + writeln("Yes, the condition has been satisfied."); + + writeln("The value type: ", Value.stringof); + writeln("The key type : ", Key.stringof); + + } else { + writeln("No, the condition has not been satisfied."); + } +} + +void main() { + int number; + myFunction(number); + + int[string] intTable; + myFunction(intTable); + + double[string] doubleTable; + myFunction(doubleTable); + + dchar[long] dcharTable; + myFunction(dcharTable); +} +--- + +$(P +The condition is satisfied only if the key type is $(C string): +) + +$(SHELL_SMALL +-- Called with int -- +No, the condition has not been satisfied. + +-- Called with int[string] -- +Yes, the condition has been satisfied. +The value type: int +The key type : string + +-- Called with double[string] -- +Yes, the condition has been satisfied. +The value type: double +The key type : string + +-- Called with dchar[long] -- +No, the condition has not been satisfied. +) + +Macros: + TITLE=is Expression + + DESCRIPTION=The is expression, one of the introspection features of the D programming language. + + KEYWORDS=d programming language tutorial book is expression diff --git a/book/d.en/lambda.d b/book/d.en/lambda.d new file mode 100644 index 0000000000..7084d2e1da --- /dev/null +++ b/book/d.en/lambda.d @@ -0,0 +1,1196 @@ +Ddoc + +$(DERS_BOLUMU Function Pointers, Delegates, and Lambdas) + +$(P +Function pointers are for storing addresses of functions in order to execute those functions at a later time. Function pointers are similar to their counterparts in the C programming language. +) + +$(P +Delegates store both a function pointer and the context to execute that function pointer in. The stored context can either be the scope that the function execution will take place or a $(C struct) or $(C class) object. +) + +$(P +Delegates enable $(I closures) as well, a concept that is supported by most functional programming languages. +) + +$(H5 $(IX function pointer) $(IX pointer, function) Function pointers) + +$(P +$(IX &, function address) We have seen in the previous chapter that it is possible to take addresses of functions with the $(C &) operator. In one of those examples, we passed such an address to a function template. +) + +$(P +Taking advantage of the fact that template type parameters can match any type, let's pass a function pointer to a template to observe its type by printing its $(C .stringof) property: +) + +--- +import std.stdio; + +int myFunction(char c, double d) { + return 42; +} + +void main() { + myTemplate($(HILITE &myFunction)); // Taking the function's address and + // passing it as a parameter +} + +void myTemplate(T)(T parameter) { + writeln("type : ", T.stringof); + writeln("value: ", parameter); +} +--- + +$(P +The output of the program reveals the type and the address of $(C myFunction()): +) + +$(SHELL +type : int function(char c, double d) +value: 406948 +) + +$(H6 $(IX member function pointer) $(IX pointer, member function) Member function pointers) + +$(P +The address of a member function can be taken either on a type or on an object of a type, with different results: +) + +--- +struct MyStruct { + void func() { + } +} + +void main() { + auto o = MyStruct(); + + auto f = &$(HILITE MyStruct).func; // on a type + auto d = &$(HILITE o).func; // on an object + + static assert(is (typeof($(HILITE f)) == void $(HILITE function)())); + static assert(is (typeof($(HILITE d)) == void $(HILITE delegate)())); +} +--- + +$(P +As the two $(C static assert) lines above indicate, $(C f) is a $(C function) and $(C d) is a $(C delegate). We will see later below that $(C d) can be called directly but $(C f) needs an object to be called on. +) + +$(H6 Definition) + +$(P +$(IX function) Similar to regular pointers, each function pointer type can point exactly to a particular type of function; the parameter list and the return type of the function pointer and the function must match. Function pointers are defined by the $(C function) keyword between the return type and the parameter list of that particular type: +) + +--- + $(I return_type) function($(I parameters)) ptr; +--- + +$(P +The names of the parameters ($(C c) and $(C d) in the output above) are optional. Because $(C myFunction()) takes a $(C char) and a $(C double) and returns an $(C int), the type of a function pointer that can point at $(C myFunction()) must be defined accordingly: +) + +--- + int function(char, double) ptr = &myFunction; +--- + +$(P +The line above defines $(C ptr) as a function pointer taking two parameters ($(C char) and $(C double)) and returning $(C int). Its value is the address of $(C myFunction()). +) + +$(P +Function pointer syntax is relatively harder to read; it is common to make code more readable by an $(C alias): +) + +--- +alias CalculationFunc = int function(char, double); +--- + +$(P +That alias makes the code easier to read: +) + +--- + CalculationFunc ptr = &myFunction; +--- + +$(P +As with any type, $(C auto) can be used as well: +) + +--- + auto ptr = &myFunction; +--- + +$(H6 Calling a function pointer) + +$(P +Function pointers can be called exactly like functions: +) + +--- + int result = $(HILITE ptr)('a', 5.67); + assert(result == 42); +--- + +$(P +The call $(C ptr('a', 5.67)) above is the equivalent of calling the actual function by $(C myFunction('a', 5.67)). +) + +$(H6 When to use) + +$(P +Because function pointers store what function to call and they are called exactly like the functions that they point at, function pointers effectively store the behavior of the program for later. +) + +$(P +There are many other features of D that are about program behavior. For example, the appropriate function to call to calculate the wages of an $(C Employee) can be determined by the value of an $(C enum) member: +) + +--- + final switch (employee.type) { + + case EmployeeType.fullTime: + fullTimeEmployeeWages(); + break; + + case EmployeeType.hourly: + hourlyEmployeeWages(); + break; + } +--- + +$(P +Unfortunately, that method is relatively harder to maintain because it obviously has to support all known employee types. If a new type of employee is added to the program, then all such $(C switch) statements must be located so that a new $(C case) clause is added for the new employee type. +) + +$(P +A more common alternative of implementing behavior differences is polymorphism. An $(C Employee) interface can be defined and different wage calculations can be handled by different implementations of that interface: +) + +--- +interface Employee { + double wages(); +} + +class FullTimeEmployee : Employee { + double wages() { + double result; + // ... + return result; + } +} + +class HourlyEmployee : Employee { + double wages() { + double result; + // ... + return result; + } +} + +// ... + + double result = employee.wages(); +--- + +$(P +Function pointers are yet another alternative for implementing different behavior. They are more common in programming languages that do not support object oriented programming. +) + +$(H6 Function pointer as a parameter) + +$(P +Let's design a function that takes an array and returns another array. This function will filter out elements with values less than or equal to zero, and multiply the others by ten: +) + +--- +$(CODE_NAME filterAndConvert)int[] filterAndConvert(const int[] numbers) { + int[] result; + + foreach (e; numbers) { + if (e > 0) { // filtering, + immutable newNumber = e * 10; // and conversion + result ~= newNumber; + } + } + + return result; +} +--- + +$(P +The following program demonstrates its behavior with randomly generated values: +) + +--- +$(CODE_XREF filterAndConvert)import std.stdio; +import std.random; + +void main() { + int[] numbers; + + // Random numbers + foreach (i; 0 .. 10) { + numbers ~= uniform(0, 10) - 5; + } + + writeln("input : ", numbers); + writeln("output: ", filterAndConvert(numbers)); +} +--- + +$(P +The output contains numbers that are ten times the original numbers, which were greater than zero to begin with. The original numbers that have been selected are highlighted: +) + +$(SHELL +input : [-2, $(HILITE 2), -2, $(HILITE 3), -2, $(HILITE 2), -1, -4, 0, 0] +output: [20, 30, 20] +) + +$(P +$(C filterAndConvert()) is for a very specific task: It always selects numbers that are greater than zero and always multiplies them by ten. It could be more useful if the behaviors of filtering and conversion were parameterized. +) + +$(P +Noting that filtering is a form of conversion as well (from $(C int) to $(C bool)), $(C filterAndConvert()) performs two conversions: +) + +$(UL +$(LI $(C number > 0), which produces $(C bool) by considering an $(C int) value.) +$(LI $(C number * 10), which produces $(C int) from an $(C int) value.) +) + +$(P +Let's define convenient aliases for function pointers that would match the two conversions above: +) + +--- +alias Predicate = bool function(int); // makes bool from int +alias Convertor = int function(int); // makes int from int +--- + +$(P +$(C Predicate) is the type of functions that take $(C int) and return $(C bool), and $(C Convertor) is the type of functions that take $(C int) and return $(C int). +) + +$(P +If we provide such function pointers as parameters, we can have $(C filterAndConvert()) use those function pointers during its work: +) + +--- +int[] filterAndConvert(const int[] numbers, + $(HILITE Predicate predicate), + $(HILITE Convertor convertor)) { + int[] result; + + foreach (number; numbers) { + if ($(HILITE predicate(number))) { + immutable newNumber = $(HILITE convertor(number)); + result ~= newNumber; + } + } + + return result; +} +--- + +$(P +$(C filterAndConvert()) is now an algorithm that is independent of the actual filtering and conversion operations. When desired, its earlier behavior can be achieved by the following two simple functions: +) + +--- +bool isGreaterThanZero(int number) { + return number > 0; +} + +int tenTimes(int number) { + return number * 10; +} + +// ... + + writeln("output: ", filterAndConvert(numbers, + $(HILITE &isGreaterThanZero), + $(HILITE &tenTimes))); +--- + +$(P +This design allows calling $(C filterAndConvert()) with any filtering and conversion behaviors. For example, the following two functions would make $(C filterAndConvert()) produce $(I the negatives of the even numbers): +) + +--- +bool isEven(int number) { + return (number % 2) == 0; +} + +int negativeOf(int number) { + return -number; +} + +// ... + + writeln("output: ", filterAndConvert(numbers, + &isEven, + &negativeOf)); +--- + +$(P +The output: +) + +$(SHELL +input : [3, -3, 2, 1, -5, 1, 2, 3, 4, -4] +output: [-2, -2, -4, 4] +) + +$(P +As seen in these examples, sometimes such functions are so trivial that defining them as proper functions with name, return type, parameter list, and curly brackets is unnecessarily wordy. +) + +$(P +As we will see below, the $(C =>) syntax of anonymous functions makes the code more concise and more readable. The following line has anonymous functions that are the equivalents of $(C isEven()) and $(C negativeOf()), without proper function definitions: +) + +--- + writeln("output: ", filterAndConvert(numbers, + number => (number % 2) == 0, + number => -number)); +--- + +$(H6 Function pointer as a member) + +$(P +Function pointers can be stored as members of structs and classes as well. To see this, let's design a $(C class) that takes the predicate and convertor as constructor parameters in order to use them later on: +) + +--- +class NumberHandler { + $(HILITE Predicate predicate); + $(HILITE Convertor convertor); + + this(Predicate predicate, Convertor convertor) { + this.predicate = predicate; + this.convertor = convertor; + } + + int[] handle(const int[] numbers) { + int[] result; + + foreach (number; numbers) { + if (predicate(number)) { + immutable newNumber = convertor(number); + result ~= newNumber; + } + } + + return result; + } +} +--- + +$(P +An object of that type can be used similarly to $(C filterAndConvert()): +) + +--- + auto handler = new NumberHandler($(HILITE &isEven), $(HILITE &negativeOf)); + writeln("result: ", handler.handle(numbers)); +--- + +$(H5 $(IX anonymous function) $(IX function, anonymous) $(IX function, lambda) $(IX function literal) $(IX literal, function) $(IX lambda) Anonymous functions) + +$(P +The code can be more readable and concise when short functions are defined without proper function definitions. +) + +$(P +Anonymous functions, which are also knows as $(I function literals) or $(I lambdas), allow defining functions inside of expressions. Anonymous functions can be used at any point where a function pointer can be used. +) + +$(P +We will get to their shorter $(C =>) syntax later below. Let's first see their full syntax, which is usually too wordy especially when it appears inside of other expressions: +) + +--- + function $(I return_type)($(I parameters)) { /* operations */ } +--- + +$(P +For example, an object of $(C NumberHandler) that produces $(I 7 times the numbers that are greater than 2) can be constructed by anonymous functions as in the following code: +) + +--- + new NumberHandler(function bool(int number) { return number > 2; }, + function int(int number) { return number * 7; }); +--- + +$(P +Two advantages of the code above is that the functions are not defined as proper functions and that their implementations are visible right where the $(C NumberHandler) object is constructed. +) + +$(P +Note that the anonymous function syntax is very similar to regular function syntax. Although this consistency has benefits, the full syntax of anonymous functions makes code too wordy. +) + +$(P +For that reason, there are various shorter ways of defining anonymous functions. +) + +$(H6 Shorter syntax) + +$(P +When the return type can be deduced from the $(C return) statement inside the anonymous function, then the return type need not be specified (The place where the return type would normally appear is highlighted by code comments.): +) + +--- + new NumberHandler(function /**/(int number) { return number > 2; }, + function /**/(int number) { return number * 7; }); +--- + +$(P +Further, when the anonymous function does not take parameters, its parameter list need not be provided. Let's consider a function that takes a function pointer that takes $(I nothing) and returns $(C double): +) + +--- +void foo(double function$(HILITE ()) func) { + // ... +} +--- + +$(P +Anonymous functions that are passed to that function need not have the empty parameter list. Therefore, all three of the following anonymous function syntaxes are equivalent: +) + +--- + foo(function double() { return 42.42; }); + foo(function () { return 42.42; }); + foo(function { return 42.42; }); +--- + +$(P +The first one is written in the full syntax. The second one omits the return type, taking advantage of the return type deduction. The third one omits the unnecessary parameter list. +) + +$(P +Even further, the keyword $(C function) need not be provided either. In that case it is left to the compiler to determine whether it is an anonymous function or an anonymous delegate. Unless it uses a variable from one of the enclosing scopes, it is a function: +) + +--- + foo({ return 42.42; }); +--- + +$(P +Most anonymous functions can be defined even shorter by the $(I lambda syntax). +) + +$(H6 $(IX =>) Lambda syntax instead of a single $(C return) statement) + +$(P +In most cases even the shortest syntax above is unnecessarily cluttered. The curly brackets that are just inside the function parameter list make the code harder to read and a $(C return) statement as well as its semicolon inside a function argument looks out of place. +) + +$(P +Let's start with the full syntax of an anonymous function that has a single $(C return) statement: +) + +--- + function $(I return_type)($(I parameters)) { return $(I expression); } +--- + +$(P +We have already seen that the $(C function) keyword is not necessary and the return type can be deduced: +) + +--- + ($(I parameters)) { return $(I expression); } +--- + +$(P +The equivalent of that definition is the following $(C =>) syntax, where the $(C =>) characters replace the curly brackets, the $(C return) keyword, and the semicolon: +) + +--- + ($(I parameters)) => $(I expression) +--- + +$(P +The meaning of that syntax can be spelled out as "given those parameters, produce this expression (value)". +) + +$(P +Further, when there is a single parameter, the parentheses around the parameter list can be omitted as well: +) + +--- + $(I single_parameter) => $(I expression) +--- + +$(P +On the other hand, to avoid grammar ambiguities, the parameter list must still be written as empty parentheses when there is no parameter at all: +) + +--- + () => $(I expression) +--- + +$(P +Programmers who know lambdas from other languages may make a mistake of using curly brackets after the $(C =>) characters, which can be valid D syntax with a different meaning: +) + +--- + // A lambda that returns 'a + 1' + auto l0 = (int a) => a + 1 + + // A lambda that returns a parameter-less lambda that + // returns 'a + 1' + auto l1 = (int a) => $(HILITE {) return a + 1; $(HILITE }) + + assert(l0(42) == 43); + assert(l1(42)$(HILITE ()) == 43); // Executing what l1 returns +--- + +$(P +$(IX filter, std.algorithm) Let's use the lambda syntax in a predicate passed to $(C std.algorithm.filter). $(C filter()) takes a predicate as its template parameter and a range as its function parameter. It applies the predicate to each element of the range and returns the ones that satisfy the predicate. One of several ways of specifying the predicate is the lambda syntax. +) + +$(P +($(I Note: We will see ranges in a later chapter. At this point, it should be sufficient to know that D slices are ranges.)) +) + +$(P +The following lambda is a predicate that matches elements that are greater than 10: +) + +--- +import std.stdio; +import std.algorithm; + +void main() { + int[] numbers = [ 20, 1, 10, 300, -2 ]; + writeln(numbers.filter!($(HILITE number => number > 10))); +} +--- + +$(P +The output contains only the elements that satisfy the predicate: +) + +$(SHELL +[20, 300] +) + +$(P +For comparison, let's write the same lambda in the longest syntax. The curly brackets that define the body of the anonymous function are highlighted: +) + +--- + writeln(numbers.filter!(function bool(int number) $(HILITE {) + return number > 10; + $(HILITE }))); +--- + +$(P +As another example, this time let's define an anonymous function that takes two parameters. The following algorithm takes two slices and passes their corresponding elements one by one to a $(C function) that itself takes two parameters. It then collects and returns the results as another slice: +) + +--- +$(CODE_NAME binaryAlgorithm)import std.exception; + +int[] binaryAlgorithm(int function$(HILITE (int, int)) func, + const int[] slice1, + const int[] slice2) { + enforce(slice1.length == slice2.length); + + int[] results; + + foreach (i; 0 .. slice1.length) { + results ~= func(slice1[i], slice2[i]); + } + + return results; +} +--- + +$(P +Since the $(C function) parameter above takes two parameters, lambdas that can be passed to $(C binaryAlgorithm()) must take two parameters as well: +) + +--- +$(CODE_XREF binaryAlgorithm)import std.stdio; + +void main() { + writeln(binaryAlgorithm($(HILITE (a, b)) => (a * 10) + b, + [ 1, 2, 3 ], + [ 4, 5, 6 ])); +} +--- + +$(P +The output contains ten times the elements of the first array plus the elements of the second array (e.g. 14 is 10 * 1 + 4): +) + +$(SHELL +[14, 25, 36] +) + +$(H5 $(IX delegate) Delegates) + +$(P +$(IX context) $(IX closure) A delegate is a combination of a function pointer and the context that it should be executed in. Delegates also support $(I closures) in D. Closures are a feature supported by many functional programming languages. +) + +$(P +As we have seen in $(LINK2 lifetimes.html, the Lifetimes and Fundamental Operations chapter), the lifetime of a variable ends upon leaving the scope that it is defined in: +) + +--- +{ + int increment = 10; + // ... +} // ← the life of 'increment' ends here +--- + +$(P +That is why the address of such a local variable cannot be returned from a function. +) + +$(P +Let's imagine that $(C increment) is a local variable of a function that itself returns a $(C function). Let's make it so that the returned lambda happens to use that local variable: +) + +--- +alias Calculator = int function(int); + +Calculator makeCalculator() { + int increment = 10; + return value => $(HILITE increment) + value; $(DERLEME_HATASI) +} +--- + +$(P +That code is in error because the returned lambda makes use of a local variable that is about to go out of scope. If the code were allowed to compile, the lambda would be trying to access $(C increment), whose life has already ended. +) + +$(P +For that code to be compiled and work correctly, the lifetime of $(C increment) must at least be as long as the lifetime of the lambda that uses it. Delegates extend the lifetime of the context of a lambda so that the local state that the function uses remains valid. +) + +$(P +$(C delegate) syntax is similar to $(C function) syntax, the only difference being the keyword. That change is sufficient to make the previous code compile: +) + +--- +alias Calculator = int $(HILITE delegate)(int); + +Calculator makeCalculator() { + int increment = 10; + return value => increment + value; +} +--- + +$(P +Having been used by a delegate, the local variable $(C increment) will now live as long as that delegate lives. The variable is available to the delegate just as any other variable would be, mutable as needed. We will see examples of this in the next chapter when using delegates with $(C opApply()) member functions. +) + +$(P +The following is a test of the delegate above: +) + +--- + auto calculator = makeCalculator(); + writeln("The result of the calculation: ", calculator(3)); +--- + +$(P +Note that $(C makeCalculator()) returns an anonymous delegate. The code above assigns that delegate to the variable $(C calculator) and then calls it by $(C calculator(3)). Since the delegate is implemented to return the sum of its parameter and the variable $(C increment), the code outputs the sum of 3 and 10: +) + +$(SHELL +The result of the calculation: 13 +) + +$(H6 Shorter syntax) + +$(P +As we have already used in the previous example, delegates can take advantage of the shorter syntaxes as well. When neither $(C function) nor $(C delegate) is specified, the type of the lambda is decided by the compiler, depending on whether the lambda accesses local state. If so, then it is a $(C delegate). +) + +$(P +The following example has a delegate that does not take any parameters: +) + +--- +int[] delimitedNumbers(int count, int delegate$(HILITE ()) numberGenerator) { + int[] result = [ -1 ]; + result.reserve(count + 2); + + foreach (i; 0 .. count) { + result ~= numberGenerator(); + } + + result ~= -1; + + return result; +} +--- + +$(P +The function $(C delimitedNumbers()) generates a slice where the first and last elements are -1. It takes two parameters that specify the other elements that come between those first and last elements. +) + +$(P +Let's call that function with a trivial delegate that always returns the same value. Remember that when there is no parameter, the parameter list of a lambda must be specified as empty: +) + +--- + writeln(delimitedNumbers(3, $(HILITE () => 42))); +--- + +$(P +The output: +) + +$(SHELL +-1 42 42 42 -1 +) + +$(P +Let's call $(C delimitedNumbers()) this time with a delegate that makes use of a local variable: +) + +--- + int lastNumber; + writeln(delimitedNumbers( + 15, $(HILITE () => lastNumber += uniform(0, 3)))); + + writeln("Last number: ", lastNumber); +--- + +$(P +Although that delegate produces a random value, since the value is added to the last one, none of the generated values is less than its predecessor: +) + +$(SHELL +-1 0 2 3 4 6 6 8 9 9 9 10 12 14 15 17 -1 +Last number: 17 +) + +$(H6 $(IX &, object delegate) $(IX delegate, member function) $(IX object delegate) $(IX member function delegate) An object and a member function as a delegate) + +$(P +We have seen that a delegate is nothing but a function pointer and the context that it is to be executed in. Instead of those two, a delegate can also be composed of a member function and an existing object that that member function is to be called on. +) + +$(P +The syntax that defines such a delegate from an object is the following: +) + +--- + &$(I object).$(I member_function) +--- + +$(P +Let's first observe that such a syntax indeed defines a $(C delegate) by printing its $(C string) representation: +) + +--- +import std.stdio; + +struct Location { + long x; + long y; + + void moveHorizontally(long step) { x += step; } + void moveVertically(long step) { y += step; } +} + +void main() { + auto location = Location(); + writeln(typeof($(HILITE &location.moveHorizontally)).stringof); +} +--- + +$(P +According to the output, the type of $(C moveHorizontally()) called on $(C location) is indeed a $(C delegate): +) + +$(SHELL +void delegate(long step) +) + +$(P +Note that the $(C &) syntax is only for constructing the delegate. The delegate will be called later by the function call syntax: +) + +--- + // The definition of the delegate variable: + auto directionFunction = &location.moveHorizontally; + + // Calling the delegate by the function call syntax: + directionFunction$(HILITE (3)); + + writeln(location); +--- + +$(P +Since the $(C delegate) combines the $(C location) object and the $(C moveHorizontally()) member function, calling the delegate is the equivalent of calling $(C moveHorizontally()) on $(C location). The output indicates that the object has indeed moved 3 steps horizontally: +) + +$(SHELL +Location(3, 0) +) + +$(P +Function pointers, lambdas, and delegates are expressions. They can be used in places where a value of their type is expected. For example, a slice of $(C delegate) objects is initialized below from delegates constructed from an object and its various member functions. The $(C delegate) elements of the slice are later called just like functions: +) + +--- + auto location = Location(); + + void delegate(long)[] movements = + [ &location.moveHorizontally, + &location.moveVertically, + &location.moveHorizontally ]; + + foreach (movement; movements) { + movement$(HILITE (1)); + } + + writeln(location); +--- + +$(P +According to the elements of the slice, the location has been changed twice horizontally and once vertically: +) + +$(SHELL +Location(2, 1) +) + +$(H6 $(IX .ptr, delegate context) $(IX pointer, delegate context) $(IX .funcptr) $(IX function pointer, delegate) Delegate properties) + +$(P +The function and context pointers of a delegate can be accessed through its $(C .funcptr) and $(C .ptr) properties, respectively: +) + +--- +struct MyStruct { + void func() { + } +} + +void main() { + auto o = MyStruct(); + + auto d = &o.func; + + assert(d$(HILITE .funcptr) == &MyStruct.func); + assert(d$(HILITE .ptr) == &o); +} +--- + +$(P +It is possible to make a $(C delegate) from scratch by setting those properties explicitly: +) + +--- +struct MyStruct { + int i; + + void func() { + import std.stdio; + writeln(i); + } +} + +void main() { + auto o = MyStruct(42); + + void delegate() d; + assert(d is null); // null to begin with + + d$(HILITE .funcptr) = &MyStruct.func; + d$(HILITE .ptr) = &o; + + $(HILITE d()); +} +--- + +$(P +Calling the delegate above as $(C d()) is the equivalent of the expression $(C o.func()) (i.e. calling $(C MyStruct.func) on $(C o)): +) + +$(SHELL +42 +) + +$(H6 $(IX lazy parameter as delegate) Lazy parameters are delegates) + +$(P +We saw the $(C lazy) keyword in $(LINK2 function_parameters.html, the Function Parameters chapter): +) + +--- +void log(Level level, $(HILITE lazy) string message) { + if (level >= interestedLevel) { + writeln(message); + } +} + +// ... + + if (failedToConnect) { + log(Level.medium, + $(HILITE format)("Failure. The connection state is '%s'.", + getConnectionState())); + } +--- + +$(P +Because $(C message) is a $(C lazy) parameter above, the entire $(C format) expression (including the $(C getConnectionState()) call that it makes) would be evaluated if and when that parameter is used inside $(C log()). +) + +$(P +Behind the scenes, lazy parameters are in fact delegates and the arguments that are passed to lazy parameters are delegate objects that are created automatically by the compiler. The code below is the equivalent of the one above: +) + +--- +void log(Level level, string $(HILITE delegate)() lazyMessage) { // (1) + if (level >= interestedLevel) { + writefln("%s", $(HILITE lazyMessage())); // (2) + } +} + +// ... + + if (failedToConnect) { + log(Level.medium, + delegate string() $(HILITE {) // (3) + return format( + "Failure. The connection state is '%s'.", + getConnectionState()); + $(HILITE })); + } +--- + +$(OL + +$(LI The $(C lazy) parameter is not a $(C string) but a delegate that returns a $(C string).) + +$(LI The delegate is called to get its return value.) + +$(LI The entire expression is wrapped inside a delegate and returned from it.) + +) + +$(H6 $(IX lazy variadic functions) $(IX variadic function, lazy) Lazy variadic functions) + +$(P +When a function needs a variable number of lazy parameters, it is necessarily impossible to specify those $(I unknown number of) parameters as $(C lazy). +) + +$(P +The solution is to use variadic $(C delegate) parameters. Such parameters can receive any number of expressions that are the same as the $(I return type) of those delegates. The delegates cannot take parameters: +) + +--- +import std.stdio; + +void foo(double delegate()$(HILITE []) args$(HILITE ...)) { + foreach (arg; args) { + writeln($(HILITE arg())); // Calling each delegate + } +} + +void main() { + foo($(HILITE 1.5), () => 2.5); // 'double' passed as delegate +} +--- + +$(P +Note how both a $(C double) expression and a lambda are matched to the variadic parameter. The $(C double) expression is automatically wrapped inside a delegate and the function prints the values of all its $(I effectively-lazy) parameters: +) + +$(SHELL +1.5 +2.5 +) + +$(P +A limitation of this method is that all parameters must be the same type ($(C double) above). We will see later in the $(LINK2 templates_more.html, More Templates chapter) how to take advantage of $(I tuple template parameters) to remove that limitation. +) + +$(H5 $(IX sink) $(IX toString, delegate) $(C toString()) with a $(C delegate) parameter) + +$(P +We have defined many $(C toString()) functions up to this point in the book to represent objects as strings. Those $(C toString()) definitions all returned a $(C string) without taking any parameters. As noted by the comment lines below, structs and classes took advantage of $(C toString()) functions of their respective members by simply passing those members to $(C format()): +) + +--- +import std.stdio; +import std.string; + +struct Point { + int x; + int y; + + string toString() const { + return format("(%s,%s)", x, y); + } +} + +struct Color { + ubyte r; + ubyte g; + ubyte b; + + string toString() const { + return format("RGB:%s,%s,%s", r, g, b); + } +} + +struct ColoredPoint { + Color color; + Point point; + + string toString() const { + /* Taking advantage of Color.toString and + * Point.toString: */ + return format("{%s;%s}", color, point); + } +} + +struct Polygon { + ColoredPoint[] points; + + string toString() const { + /* Taking advantage of ColoredPoint.toString: */ + return format("%s", points); + } +} + +void main() { + auto polygon = Polygon( + [ ColoredPoint(Color(10, 10, 10), Point(1, 1)), + ColoredPoint(Color(20, 20, 20), Point(2, 2)), + ColoredPoint(Color(30, 30, 30), Point(3, 3)) ]); + + writeln(polygon); +} +--- + +$(P +In order for $(C polygon) to be sent to the output as a $(C string) on the last line of the program, all of the $(C toString()) functions of $(C Polygon), $(C ColoredPoint), $(C Color), and $(C Point) are called indirectly, creating a total of 10 strings in the process. Note that the strings that are constructed and returned by the lower-level functions are used only once by the respective higher-level function that called them. +) + +$(P +However, although a total of 10 strings get constructed, only the very last one is printed to the output: +) + +$(SHELL +[{RGB:10,10,10;(1,1)}, {RGB:20,20,20;(2,2)}, {RGB:30,30,30;(3,3)}] +) + +$(P +However practical, this method may degrade the performance of the program because of the many $(C string) objects that are constructed and promptly thrown away. +) + +$(P +An overload of $(C toString()) avoids this performance issue by taking a $(C delegate) parameter: +) + +--- + void toString(void delegate(const(char)[]) sink) const; +--- + +$(P +As seen in its declaration, this overload of $(C toString()) does not return a $(C string). Instead, the characters that are going to be printed are passed to its $(C delegate) parameter. It is the responsibility of the $(C delegate) to append those characters to the single $(C string) that is going to be printed to the output. +) + +$(P +$(IX formattedWrite, std.format) All the programmer needs to do differently is to call $(C std.format.formattedWrite) instead of $(C std.string.format) and pass the $(C delegate) parameter as its first parameter (in UFCS below). Also note that the following calls are providing the format strings as template arguments to take advantage of $(C formattedWrite)'s compile-time format string checks. +) + +--- +import std.stdio; +$(HILITE import std.format;) + +struct Point { + int x; + int y; + + void toString(void delegate(const(char)[]) sink) const { + sink.$(HILITE formattedWrite)!"(%s,%s)"(x, y); + } +} + +struct Color { + ubyte r; + ubyte g; + ubyte b; + + void toString(void delegate(const(char)[]) sink) const { + sink.$(HILITE formattedWrite)!"RGB:%s,%s,%s"(r, g, b); + } +} + +struct ColoredPoint { + Color color; + Point point; + + void toString(void delegate(const(char)[]) sink) const { + sink.$(HILITE formattedWrite)!"{%s;%s}"(color, point); + } +} + +struct Polygon { + ColoredPoint[] points; + + void toString(void delegate(const(char)[]) sink) const { + sink.$(HILITE formattedWrite)!"%s"(points); + } +} + +void main() { + auto polygon = Polygon( + [ ColoredPoint(Color(10, 10, 10), Point(1, 1)), + ColoredPoint(Color(20, 20, 20), Point(2, 2)), + ColoredPoint(Color(30, 30, 30), Point(3, 3)) ]); + + writeln(polygon); +} +--- + +$(P +The advantage of this program is that, even though there are still a total of 10 calls made to various $(C toString()) functions, those calls collectively produce a single $(C string), not 10. +) + +$(H5 Summary) + +$(UL +$(LI The $(C function) keyword is for defining function pointers to be called later just like a function.) + +$(LI The $(C delegate) keyword is for defining delegates. A delegate is the pair of a function pointer and the context that that function pointer to be executed in.) + +$(LI A $(C delegate) can be created from an object and a member function by the syntax $(C &object.member_function).) + +$(LI A delegate can be constructed explicitly by setting its $(C .funcptr) and $(C .ptr) properties.) + +$(LI Anonymous functions and anonymous delegates (lambdas) can be used in places of function pointers and delegates in expressions.) + +$(LI There are several syntaxes for lambdas, the shortest of which is for when the equivalent consists only of a single $(C return) statement: $(C parameter => expression).) + +$(LI A more efficient overload of $(C toString()) takes a $(C delegate).) + +) + +Macros: + TITLE=Function Pointers, Delegates, and Lambdas + + DESCRIPTION=C-like function pointers, delegates that are commonly found in functional programming languages, and anonymous functions (lambdas). + + KEYWORDS=d programming language tutorial book function pointer delegate anonymous function lambda diff --git a/book/d.en/lazy_operators.d b/book/d.en/lazy_operators.d new file mode 100644 index 0000000000..795e8ecc50 --- /dev/null +++ b/book/d.en/lazy_operators.d @@ -0,0 +1,92 @@ +Ddoc + +$(DERS_BOLUMU $(IX lazy evaluation) Lazy Operators) + +$(P +Lazy evaluation is the delaying of the execution of expressions until the results of those expressions are needed. Lazy evaluation is among the fundamental features of some programming languages. +) + +$(P +Naturally, this delaying may make programs run faster if the results end up not being needed. +) + +$(P +$(IX short-circuit evaluation) A concept that is similar to lazy evaluation is the short-circuit behavior of the following operators: +) + +$(UL + +$(LI $(IX ||, short-circuit) $(IX logical or operator) $(C ||) ($(I or)) operator: The second expression is evaluated only if the first expression is $(C false). + +--- + if (anExpression() || mayNotBeEvaluated()) { + // ... + } +--- + +$(P +If the result of $(C anExpression()) is $(C true) then the result of the $(C ||) expression is necessarily $(C true). Since we no longer need to evaluate the second expression to determine the result of the $(C ||) expression the second expression is not evaluated. +) + +) + +$(LI $(IX &&, short-circuit) $(IX logical and operator) $(C &&) ($(I and)) operator: The second expression is evaluated only if the first expression is $(C true). + +--- + if (anExpression() && mayNotBeEvaluated()) { + // ... + } +--- + +$(P +If the result of $(C anExpression()) is $(C false) then the result of the $(C &&) expression is necessarily $(C false), so the second expression is not evaluated. +) + +) + +$(LI $(IX ?:, short-circuit) $(IX ternary operator) $(IX conditional operator) $(C ?:) ($(I ternary)) operator: Either the first or the second expression is evaluated, depending on whether the condition is $(C true) or $(C false), respectively. + +--- + int i = condition() ? eitherThis() : orThis(); +--- + +) + +) + +$(P +The laziness of these operators matters not only to performance. Sometimes, evaluating one of the expressions can be an error. +) + +$(P +For example, the $(I is the first letter an A) condition check below would be an error when the string is empty: +) + +--- + dstring s; + // ... + if (s[0] == 'A') { + // ... + } +--- + +$(P +In order to access the first element of $(C s), we must first ensure that the string does have such an element. For that reason, the following condition check moves that potentially erroneous logical expression to the right-hand side of the $(C &&) operator, to ensure that it will be evaluated only when it is safe to do so: +) + +--- + if ((s.length >= 1) && (s[0] == 'A')) { + // ... + } +--- + +$(P +Lazy evaluations can be achieved by using $(LINK2 lambda.html, function pointers, delegates), and $(LINK2 ranges.html, ranges) as well. We will see these in later chapters. +) + +Macros: + TITLE=Lazy Operators + + DESCRIPTION=The lazy (short-circuit) operators of the D programming language. + + KEYWORDS=d programming language tutorial book lazy diff --git a/book/d.en/lifetimes.d b/book/d.en/lifetimes.d new file mode 100644 index 0000000000..e1cd58d8b7 --- /dev/null +++ b/book/d.en/lifetimes.d @@ -0,0 +1,341 @@ +Ddoc + +$(DERS_BOLUMU $(IX lifetime) Lifetimes and Fundamental Operations) + +$(P +We will soon cover structs, the basic feature that allows the programmer to define application-specific types. Structs are for combining fundamental types and other structs together to define higher-level types that behave according to special needs of programs. After structs, we will learn about classes, which are the basis of the object oriented programming features of D. +) + +$(P +Before getting to structs and classes, it will be better to talk about some important concepts first. These concepts will help understand structs and classes and some of their differences. +) + +$(P +We have been calling any piece of data that represented a concept in a program a $(I variable). In a few places we have referred to struct and class variables specifically as $(I objects). I will continue calling both of these concepts variables in this chapter. +) + +$(P +Although this chapter includes only fundamental types, slices, and associative arrays; these concepts apply to user-defined types as well. +) + +$(H5 $(IX variable, lifetime) Lifetime of a variable) + +$(P +The time between when a variable is defined and when it is $(I finalized) is the lifetime of that variable. Although it is the case for many types, $(I becoming unavailable) and $(I being finalized) need not be at the same time. +) + +$(P +You would remember from the $(LINK2 name_space.html, Name Scope chapter) how variables become unavailable. In simple cases, exiting the scope where a variable was defined would render that variable unavailable. +) + +$(P +Let's consider the following example as a reminder: +) + +--- +void speedTest() { + int speed; // Single variable ... + + foreach (i; 0 .. 10) { + speed = 100 + i; // ... takes 10 different values. + // ... + } +} // ← 'speed' is unavailable beyond this point. +--- + +$(P +The lifetime of the $(C speed) variable in that code ends upon exiting the $(C speedTest()) function. There is a single variable in the code above, which takes ten different values from 100 to 109. +) + +$(P +When it comes to variable lifetimes, the following code is very different compared to the previous one: +) + +--- +void speedTest() { + foreach (i; 0 .. 10) { + int speed = 100 + i; // Ten separate variables. + // ... + } // ← Lifetime of each variable ends here. +} +--- + +$(P +There are ten separate variables in that code, each taking a single value. Upon every iteration of the loop, a new variable starts its life, which eventually ends at the end of each iteration. +) + +$(H5 $(IX parameter, lifetime) Lifetime of a parameter) + +$(P +The lifetime of a parameter depends on its qualifiers: +) + +$(P +$(IX ref, parameter lifetime) $(C ref): The parameter is just an alias of the actual variable that is specified when calling the function. $(C ref) parameters do not affect the lifetimes of actual variables. +) + +$(P +$(IX in, parameter lifetime) $(C in): For $(I value types), the lifetime of the parameter starts upon entering the function and ends upon exiting it. For $(I reference types), the lifetime of the parameter is the same as with $(C ref). +) + +$(P +$(IX out, parameter lifetime) $(C out): Same with $(C ref), the parameter is just an alias of the actual variable that is specified when calling the function. The only difference is that the variable is set to its $(C .init) value automatically upon entering the function. +) + +$(P +$(IX lazy, parameter lifetime) $(C lazy): The life of the parameter starts when the parameter is actually used and ends right then. +) + +$(P +The following example uses these four types of parameters and explains their lifetimes in program comments: +) + +--- +void main() { + int main_in; /* The value of main_in is copied to the + * parameter. */ + + int main_ref; /* main_ref is passed to the function as + * itself. */ + + int main_out; /* main_out is passed to the function as + * itself. Its value is set to int.init + * upon entering the function. */ + + foo(main_in, main_ref, main_out, aCalculation()); +} + +void foo( + in int p_in, /* The lifetime of p_in starts upon + * entering the function and ends upon + * exiting the function. */ + + ref int p_ref, /* p_ref is an alias of main_ref. */ + + out int p_out, /* p_out is an alias of main_out. Its + * value is set to int.init upon + * entering the function. */ + + lazy int p_lazy) { /* The lifetime of p_lazy starts when + * it is used and ends when its use + * ends. Its value is calculated by + * calling aCalculation() every time + * p_lazy is used in the function. */ + // ... +} + +int aCalculation() { + int result; + // ... + return result; +} +--- + +$(H5 Fundamental operations) + +$(P +Regardless of its type, there are three fundamental operations throughout the lifetime of a variable: +) + +$(UL +$(LI $(B Initialization): The start of its life.) +$(LI $(B Finalization): The end of its life.) +$(LI $(B Assignment): Changing its value as a whole.) +) + +$(P +To be considered an object, it must first be initialized. There may be final operations for some types. The value of a variable may change during its lifetime. +) + +$(H6 $(IX initialization) Initialization) + +$(P +Every variable must be initialized before being used. Initialization involves two steps: +) + +$(OL + +$(LI $(B Reserving space for the variable): This space is where the value of the variable is stored in memory.) + +$(LI $(B Construction): Setting the first value of the variable on that space (or the first values of the members of structs and classes).) + +) + +$(P +Every variable lives in a place in memory that is reserved for it. Some of the code that the compiler generates is about reserving space for each variable. +) + +$(P +Let's consider the following variable: +) + +--- + int speed = 123; +--- + +$(P +As we have seen in $(LINK2 value_vs_reference.html, the Value Types and Reference Types chapter), we can imagine this variable living on some part of the memory: +) + +$(MONO + ──┬─────┬─────┬─────┬── + │ │ 123 │ │ + ──┴─────┴─────┴─────┴── +) + +$(P +The memory location that a variable is placed at is called its address. In a sense, the variable lives at that address. When the value of a variable is changed, the new value is stored at the same place: +) + +--- + ++speed; +--- + +$(P +The new value would be at the same place where the old value has been: +) + +$(MONO + ──┬─────┬─────┬─────┬── + │ │ 124 │ │ + ──┴─────┴─────┴─────┴── +) + +$(P +Construction is necessary to prepare variables for use. Since a variable cannot be used reliably before being constructed, it is performed by the compiler automatically. +) + +$(P +Variables can be constructed in three ways: +) + +$(UL +$(LI $(B By their default value): when the programmer does not specify a value explicitly) +$(LI $(B By copying): when the variable is constructed as a copy of another variable of the same type) +$(LI $(B By a specific value): when the programmer specifies a value explicitly) +) + +$(P +When a value is not specified, the value of the variable would be the $(I default) value of its type, i.e. its $(C .init) value. +) + +--- + int speed; +--- + +$(P +The value of $(C speed) above is $(C int.init), which happens to be zero. Naturally, a variable that is constructed by its default value may have other values during its lifetime (unless it is $(C immutable)). +) + +--- + File file; +--- + +$(P +With the definition above, the variable $(C file) is a $(C File) object that is not yet associated with an actual file on the file system. It is not usable until it is modified to be associated with a file. +) + +$(P +Variables are sometimes constructed as a copy of another variable: +) + +--- + int speed = otherSpeed; +--- + +$(P +$(C speed) above is constructed by the value of $(C otherSpeed). +) + +$(P +As we will see in later chapters, this operation has a different meaning for class variables: +) + +--- + auto classVariable = otherClassVariable; +--- + +$(P +Although $(C classVariable) starts its life as a copy of $(C otherClassVariable), there is a fundamental difference with classes: Although $(C speed) and $(C otherSpeed) are distinct values, $(C classVariable) and $(C otherClassVariable) both provide access to the same value. This is the fundamental difference between value types and reference types. +) + +$(P +Finally, variables can be constructed by the value of an expression of a compatible type: +) + +--- + int speed = someCalculation(); +--- + +$(P +$(C speed) above would be constructed by the return value of $(C someCalculation()). +) + +$(H6 $(IX finalization) $(IX destruction) Finalization) + +$(P +Finalizing is the final operations that are executed for a variable and reclaiming its memory: +) + +$(OL +$(LI $(B Destruction): The final operations that must be executed for the variable.) +$(LI $(B Reclaiming the variable's memory): Reclaiming the piece of memory that the variable has been living on.) +) + +$(P +For simple fundamental types, there are no final operations to execute. For example, the value of a variable of type $(C int) is not set back to zero. For such variables there is only reclaiming their memory, so that it will be used for other variables later. +) + +$(P +On the other hand, some types of variables require special operations during finalization. For example, a $(C File) object would need to write the characters that are still in its output buffer to disk and notify the file system that it no longer uses the file. These operations are the destruction of a $(C File) object. +) + +$(P +Final operations of arrays are at a little higher-level: Before finalizing the array, first its elements are destructed. If the elements are of a simple fundamental type like $(C int), then there are no special final operations for them. If the elements are of a struct or a class type that needs finalization, then those operations are executed for each element. +) + +$(P +Associative arrays are similar to arrays. Additionally, the keys may also be finalized if they are of a type that needs destruction. +) + +$(P $(B The garbage collector:) D is a $(I garbage-collected) language. In such languages finalizing an object need not be initiated explicitly by the programmer. When a variable's lifetime ends, its finalization is automatically handled by the garbage collector. We will cover the garbage collector and special memory management in $(LINK2 memory.html, a later chapter). +) + +$(P +Variables can be finalized in two ways: +) + +$(UL +$(LI $(B When the lifetime ends): Finalization happens at the end of the variable's life.) +$(LI $(B Some time in the future): Finalization happens at an indeterminate time in the future by the garbage collector.) +) + +$(P +Which of the two ways a variable will be finalized depends primarily on its type. Some types like arrays, associative arrays and classes are normally destructed by the garbage collector some time in the future. +) + +$(H6 $(IX assignment) Assignment) + +$(P +The other fundamental operation that a variable experiences during its lifetime is assignment. +) + +$(P +For simple fundamental types assignment is merely changing the value of the variable. As we have seen above on the memory representation, an $(C int) variable would start having the value 124 instead of 123. However, more generally, assignment consists of two steps, which are not necessarily executed in the following order: +) + +$(UL +$(LI $(B Destructing the old value)) +$(LI $(B Constructing the new value)) +) + +$(P +These two steps are not important for simple fundamental types that don't need destruction. For types that need destruction, it is important to remember that assignment is a combination of the two steps above. +) + +Macros: + TITLE=Lifetimes and Fundamental Operations + + DESCRIPTION=Introducing the concepts of initialization, finalization, construction, destruction, and assignment and defining the lifetimes of variables. + + KEYWORDS=d programming lesson book tutorial constructor destructor diff --git a/book/d.en/literals.cozum.d b/book/d.en/literals.cozum.d new file mode 100644 index 0000000000..edf1333d31 --- /dev/null +++ b/book/d.en/literals.cozum.d @@ -0,0 +1,76 @@ +Ddoc + +$(COZUM_BOLUMU Literals) + +$(OL + +$(LI +The problem here is that the value on the right-hand side is too large to fit in an $(C int). According to the rules about integer literals, its type is $(C long). For that reason it doesn't fit the type of the variable on the left-hand side. There are at least two solutions. + +$(P +One solution is to leave the type of the variable to the compiler for example by the $(C auto) keyword: +) + +--- + auto amount = 10_000_000_000; +--- + +$(P +The type of $(C amount) would be deduced to be $(C long) from its initial value from the right-hand side. +) + +$(P +Another solution is to make the type of the variable $(C long) as well: +) + +--- + long amount = 10_000_000_000; +--- + +) + +$(LI +We can take advantage of the special $(C '\r') character that takes the printing to the beginning of the line. + +--- +import std.stdio; + +void main() { + for (int number = 0; ; ++number) { + write("\rNumber: ", number); + } +} +--- + +$(P +The output of that program may be erratic due to its interactions with the output buffer. The following program flushes the output buffer and waits for 10 millisecond after each write: +) + +--- +import std.stdio; +import core.thread; + +void main() { + for (int number = 0; ; ++number) { + write("\rNumber: ", number); + stdout.flush(); + Thread.sleep(10.msecs); + } +} +--- + +$(P +Flushing the output is normally not necessary as it is flushed automatically before getting to the next line e.g. by $(C writeln), or before reading from $(C stdin). +) + +) + +) + + +Macros: + TITLE=Literals Solutions + + DESCRIPTION=Programming in D exercise solutions: Literals + + KEYWORDS=programming in d tutorial literals solution diff --git a/book/d.en/literals.d b/book/d.en/literals.d new file mode 100644 index 0000000000..16a7aaf080 --- /dev/null +++ b/book/d.en/literals.d @@ -0,0 +1,378 @@ +Ddoc + +$(DERS_BOLUMU $(IX literal) Literals) + +$(P +Programs achieve their tasks by manipulating the values of variables and objects. They produce new values and new objects by using them with functions and operators. +) + +$(P +Some values need not be produced during the execution of the program; they are instead written directly into the source code. For example, the floating point value $(C 0.75) and the $(C string) value $(STRING "Total price: ") below are not calculated by the program: +) + +--- + discountedPrice = actualPrice * 0.75; + totalPrice += count * discountedPrice; + writeln("Total price: ", totalPrice); +--- + +$(P +Such values that are directly typed into the source code are called literals. We have used many literals in the programs that we have written so far. We will cover all of the types of literals and their syntax rules. +) + +$(H5 Integer literals) + +$(P +Integer literals can be written in one of four ways: the decimal system that we use in our daily lives; the hexadecimal and binary systems, which are more suitable for certain computing tasks; and the octal system, which may be needed in very rare cases. +) + +$(P +In order to make the code more readable, it is possible to insert $(C _) characters anywhere after the first digit of integer literals. For example, we can use it to form groups of three digits, as in $(C 1_234_567). Another example would be if we measured some value in cents of a currency, and used it to separate the currency units from the cents, as in $(C 199_99). These characters are optional; they are ignored by the compiler. +) + +$(P +$(B In the decimal system:) The literals are specified by the decimal numerals in exactly the same way as we are used to in our daily lives, such as $(C 12). When using the decimal system in D the first digit cannot be $(C 0). Such a leading zero digit is often used in other programming languages to indicate the octal system, so this constraint helps to prevent bugs that are caused by this easily overlooked difference. This does not preclude $(C 0) on its own: $(C 0) is zero. +) + +$(P +$(B In the hexadecimal system:) The literals start with $(C 0x) or $(C 0X) and include the numerals of the hexadecimal system: "0123456789abcdef" and "ABCDEF" as in $(C 0x12ab00fe). +) + +$(P +$(B In the octal system:) The literals are specified using the $(C octal) template from the $(C std.conv) module and include the numerals of the octal system: "01234567" as in $(C octal!576). +) + +$(P +$(B In the binary system:) The literals start with $(C 0b) or $(C 0B) and include the numerals of the binary system: 0 and 1 as in $(C 0b01100011). +) + +$(H6 The types of integer literals) + +$(P +Just like any other value, every literal is of a certain type. The types of literals are not specified explicitly as $(C int), $(C double), etc. The compiler infers the type from the value and syntax of the literal itself. +) + +$(P +Although most of the time the types of literals are not important, sometimes the types may not match the expressions that they are used in. In such cases the type must be explicitly specified. +) + +$(P +By default, integer literals are inferred to be of type $(C int). When the value happens to be too large to be represented by an $(C int), the compiler uses the following logic to decide on the type of the literal: +) + +$(UL + +$(LI If the value of the literal does not fit an $(C int) and it is specified in the decimal system, then its type is $(C long). +) + +$(LI If the value of the literal does not fit an $(C int) and it is specified in any other system, then the type becomes the first of the following types that can accomodate the value: $(C uint), $(C long), and $(C ulong). +) + +) + +$(P +To see this logic in action, let's try the following program that takes advantage of $(C typeof) and $(C stringof): +) + +--- +import std.stdio; + +void main() { + writeln("\n-- these are written in decimal --"); + + // fits an int, so the type is int + writeln( 2_147_483_647, "\t\t", + typeof(2_147_483_647).stringof); + + // does not fit an int and is decimal, so the type is long + writeln( 2_147_483_648, "\t\t", + typeof(2_147_483_648).stringof); + + writeln("\n-- these are NOT written in decimal --"); + + // fits an int, so the type is int + writeln( 0x7FFF_FFFF, "\t\t", + typeof(0x7FFF_FFFF).stringof); + + // does not fit an int and is not decimal, so the type is uint + writeln( 0x8000_0000, "\t\t", + typeof(0x8000_0000).stringof); + + // does not fit a uint and is not decimal, so the type is long + writeln( 0x1_0000_0000, "\t\t", + typeof(0x1_0000_0000).stringof); + + // does not fit a long and is not decimal, so the type is ulong + writeln( 0x8000_0000_0000_0000, "\t\t", + typeof(0x8000_0000_0000_0000).stringof); +} +--- + +$(P +The output: +) + +$(SHELL +-- these are written in decimal -- +2147483647 int +2147483648 long + +-- these are NOT written in decimal -- +2147483647 int +2147483648 uint +4294967296 long +9223372036854775808 ulong +) + +$(H6 $(IX L, literal suffix) The $(C L) suffix) + +$(P +Regardless of the magnitude of the value, if it ends with $(C L) as in $(C 10L), the type is $(C long). +) + +$(H6 $(IX U, literal suffix) The $(C U) suffix) + +$(P +If the literal ends with $(C U) as in $(C 10U), then its type is an unsigned type. Lowercase $(C u) can also be used. +) + +$(P +$(IX LU, literal suffix) $(IX UL, literal suffix) The $(C L) and $(C U) specifiers can be used together in any order. For example, $(C 7UL) and $(C 8LU) are both of type $(C ulong). +) + +$(H5 Floating point literals) + +$(P +The floating point literals can be specified in either the decimal system, as in $(C 1.234), or in the hexadecimal system, as in $(C 0x9a.bc). +) + +$(P $(B In the decimal system:) An exponent may be appended after the character $(C e) or $(C E), meaning "times 10 to the power of". For example, $(C 3.4e5) means "3.4 times 10 to the power of 5", or 340000. +) + +$(P +The $(C -) character typed before the value of the exponent changes the meaning to be "divided by 10 to the power of". For example, $(C 7.8e-3) means "7.8 divided by 10 to the power of 3". A $(C +) character may also be specified before the value of the exponent, but it has no effect. For example, $(C 5.6e2) and $(C 5.6e+2) are the same. +) + +$(P $(B In the hexadecimal system:) The value starts with either $(C 0x) or $(C 0X) and the parts before and after the point are specified in the numerals of the hexadecimal system. Since $(C e) and $(C E) are valid numerals in this system, the exponent is specified by $(C p) or $(C P). +) + +$(P +Another difference is that the exponent does not mean "10 to the power of", but instead "2 to the power of". For example, the $(C P4) part in $(C 0xabc.defP4) means "2 to the power of 4". +) + +$(P +Floating point literals almost always have a point but it may be omitted if an exponent is specified. For example, $(C 2e3) is a floating point literal with the value 2000. +) + +$(P +The value before the point may be omitted if zero. For example, $(C .25) is a literal having the value "quarter". +) + +$(P +The optional $(C _) characters may be used with floating point literals as well, as in $(C 1_000.5). +) + +$(H6 The types of floating point literals) + +$(P +Unless explicitly specified, the type of a floating point literal is $(C double). The $(C f) and $(C F) specifiers mean $(C float), and the $(C L) specifier means $(C real). For example; $(C 1.2) is $(C double), $(C 3.4f) is $(C float), and $(C 5.6L) is $(C real). +) + +$(H5 Character literals) + +$(P +Character literals are specified within single quotes as in $(C 'a'), $(C '\n'), $(C '\x21'), etc. +) + +$(P $(B As the character itself:) The character may be typed directly by the keyboard or copied from a separate text: 'a', 'ş', etc. +) + +$(P $(IX specifier, character) $(IX control character) $(B As the character specifier:) The character literal may be specified by a backslash character followed by a special character. For example, the backslash character itself can be specified by $(C '\\'). The following character specifiers are accepted: +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     Syntax  Definition
    \'single quote
    \"double quote
    \?question mark
    \\backslash
    \aalert (bell sound on some terminals)
    \bdelete character
    \fnew page
    \nnew-line
    \rcarriage return
    \ttab
    \vvertical tab
    + +$(P $(B As the extended ASCII character code:) Character literals can also be specified by their codes. The codes can be specified either in the hexadecimal system or in the octal system. When using the hexadecimal system, the literal must start with $(C \x) and must use two digits for the code, and when using the octal system the literal must start with $(C \) and have up to three digits. For example, the literals $(C '\x21') and $(C '\41') are both the exclamation point. +) + +$(P $(IX \u) $(IX \U) $(B As the Unicode character code:) When the literal is specified with $(C u) followed by 4 hexadecimal digits, then its type is $(C wchar). When it is specified with $(C U) followed by 8 hexadecimal digits, then its type is $(C dchar). For example, $(C '\u011e') and $(C '\U0000011e') are both the Ğ character, having the type $(C wchar) and $(C dchar), respectively. +) + +$(P $(IX \&) $(B As named character entity:) Characters that have entity names can be specified by that name using the HTML character entity syntax $(C '\&$(I name);'). D supports $(LINK2 http://dlang.org/entity.html, all character entities from HTML 5). For example, $(C '\&euro;') is €, $(C '\&hearts;') is ♥, and $(C '\&copy;') is ©. +) + +$(H5 $(IX string literal) $(IX literal, string) String literals) + +$(P +String literals are a combination of character literals and can be specified in a variety of ways. +) + +$(H6 Double-quoted string literals) + +$(P +The most common way of specifying string literals is by typing their characters within double quotes as in $(C "hello"). Individual characters of string literals follow the rules of character literals. For example, the literal $(C "A4 ka\u011fıt: 3\&frac12;TL") is the same as $(C "A4 kağıt: 3½TL"). +) + +$(H6 $(IX wysiwyg) $(I Wysiwyg) $(IX `) string literals) + +$(P +When string literals are specified using back-quotes, the individual characters of the string do not obey the special syntax rules of character literals. For example, the literal $(STRING $(BACK_TICK)c:\nurten$(BACK_TICK)) can be a directory name on the Windows operating system. If it were written using double quotes, the $(C '\n') part would mean the $(I new-line) character: +) + +--- + writeln(`c:\nurten`); + writeln("c:\nurten"); +--- + +$(SHELL +c:\nurten $(SHELL_NOTE wysiwyg (what you see is what you get)) +c: $(SHELL_NOTE_WRONG the character literal is taken as new-line) +urten +) + +$(P +Wysiwyg string literals can alternatively be specified using double quotes but prepended with the $(C r) character: $(C r"c:\nurten") is also a wysiwyg string literal. +) + +$(H6 $(IX q"") $(IX delimited string literal) Delimited string literals) + +$(P +The string literal may contain delimiters that are typed right inside the double quotes. These delimiters are not considered to be parts of the value of the literal. Delimited string literals start with a $(C q) before the opening double quote. For example, the value of $(C q".hello.") is "hello"; the dots are not parts of the value. As long as it ends with a new-line, the delimiter can have more than one character: +) + +--- +writeln(q"MY_DELIMITER +first line +second line +MY_DELIMITER"); +--- + +$(P +MY_DELIMITER is not a part of the value: +) + +$(SHELL +first line +second line +) + +$(P +$(IX heredoc) Such a multi-line string literal including all the indentation is called a $(I heredoc). +) + +$(H6 $(IX q{}) $(IX token string literal) $(IX literal, token string) Token string literals) + +$(P +String literals that start with $(C q) and that use $(C {) and $(C }) as delimiters can contain only legal D source code: +) + +--- + auto str = q{int number = 42; ++number;}; + writeln(str); +--- + +$(P +The output: +) + +$(SHELL +int number = 42; ++number; +) + +$(P +This feature is particularly useful to help text editors display the contents of the string as syntax highlighted D code. +) + +$(H6 $(IX string) $(IX wstring) $(IX dstring) Types of string literals) + +$(P +By default the type of a string literal is $(C immutable(char)[]). An appended $(C c), $(C w), or $(C d) character specifies the type of the string explicitly as $(C immutable(char)[]), $(C immutable(wchar)[]), or $(C immutable(dchar)[]), respectively. For example, the characters of $(C "hello"d) are of type $(C immutable(dchar)). +) + +$(P +We have seen in the $(LINK2 strings.html, Strings chapter) that these three string types are aliased as $(C string), $(C wstring), and $(C dstring), respectively. +) + +$(H5 Literals are calculated at compile time) + +$(P +It is possible to specify literals as expressions. For example, instead of writing the total number of seconds in January as $(C 2678400) or $(C 2_678_400), it is possible to specify it by the terms that make up that value, namely $(C 60 * 60 * 24 * 31). The multiplication operations in that expression do not affect the run-time speed of the program; the program is compiled as if $(C 2678400) were written instead. +) + +$(P +The same applies to string literals. For example, the concatenation operation in $(C "hello " ~ "world") is executed at compile time, not at run time. The program is compiled as if the code contained the single string literal $(C "hello world"). +) + +$(PROBLEM_COK + +$(PROBLEM +The following line causes a compilation error: + +--- + int amount = 10_000_000_000; $(DERLEME_HATASI) +--- + +$(P +Change the program so that the line can be compiled and that $(C amount) equals ten billions. +) + +) + +$(PROBLEM +Write a program that increases the value of a variable and prints it continuously. Make the value always be printed on the same line, overwriting the previous value: + +$(SHELL +Number: 25774 $(SHELL_NOTE always on the same line) +) + +$(P +A special character literal other than $(C '\n') may be useful here. +) + +) + +) + +Macros: + TITLE=Literals + + DESCRIPTION=The values that are typed in the source code. + + KEYWORDS=d programming language tutorial book literals diff --git a/book/d.en/logical_expressions.cozum.d b/book/d.en/logical_expressions.cozum.d new file mode 100644 index 0000000000..67c00f56e8 --- /dev/null +++ b/book/d.en/logical_expressions.cozum.d @@ -0,0 +1,54 @@ +Ddoc + +$(COZUM_BOLUMU Logical Expressions) + +$(OL + +$(LI + +Because the compiler recognizes $(C 10 < value) already as an expression, it expects a comma after it to accept it as a legal argument to $(C writeln). Using parentheses around the whole expression would not work either, because this time a closing parenthesis would be expected after the same expression. +) + +$(LI +Grouping the expression as $(C (10 < value) < 20) removes the compilation error, because in this case first $(C 10 < value) is evaluated and then its result is used with $(C < 20). + +$(P +We know that the value of a logical expression like $(C 10 < value) is either $(C false) or $(C true). $(C false) and $(C true) take part in integer expressions as 0 and 1, respectively. (We will see automatic type conversions in a later chapter.) As a result, the whole expression is the equivalent of either $(C 0 < 20) or $(C 1 < 20), both of which evaluate to $(C true). +) + +) + +$(LI +The expression "greater than the lower value and less than the upper value" can be coded as follows: + +--- + writeln("Is between: ", (value > 10) && (value < 20)); +--- + +) + +$(LI +"There is a bicycle for everyone" can be coded as $(C personCount <= bicycleCount) or $(C bicycleCount >= personCount). The rest of the logical expression can directly be translated to D from the exercise: + +--- + writeln("We are going to the beach: ", + ((distance < 10) && (bicycleCount >= personCount)) + || + ((personCount <= 5) && existsCar && existsLicense) + ); +--- + +$(P +Note the placement of the $(C ||) operator to help with readability by separating the two main conditions. +) + +) + +) + +Macros: + TITLE=Logical Expressions Solutions + + DESCRIPTION=Logical Expressions chapter exercise solutions + + KEYWORDS=programming in d tutorial logical expressions exercise solution diff --git a/book/d.en/logical_expressions.d b/book/d.en/logical_expressions.d new file mode 100644 index 0000000000..ccc58ca3b2 --- /dev/null +++ b/book/d.en/logical_expressions.d @@ -0,0 +1,433 @@ +Ddoc + +$(DERS_BOLUMU $(IX logical expression) Logical Expressions) + +$(P +$(IX expression) The actual work that a program performs is accomplished by $(I expressions). Any part of a program that produces a value or a side effect is called an expression. It has a very wide definition because even a constant value like $(C 42) and a string like $(STRING "hello") are expressions, since they produce the respective constant values 42 and "hello". +) + +$(P +$(I $(B Note:) Don't confuse producing a value with defining a variable. Values need not be associated with variables. +) +) + +$(P +Function calls like $(C writeln) are expressions as well because they have side effects. In the case of $(C writeln), the effect is on the output stream by the placement of characters on it. Another example from the programs that we have written so far would be the assignment operation, which affects the variable that is on its left-hand side. +) + +$(P +Because of producing values, expressions can take part in other expressions. This allows us to form more complex expressions from simpler ones. For example, assuming that there is a function named $(C currentTemperature) that produces the value of the current air temperature, the value that it produces may directly be used in a $(C writeln) expression: +) + +--- + writeln("It's ", currentTemperature(), + " degrees at the moment."); +--- + +$(P +That line consists of four expressions: +) + +$(OL +$(LI $(STRING "It's ")) +$(LI $(C currentTemperature())) +$(LI $(STRING " degrees at the moment.")) +$(LI The $(C writeln()) expression that makes use of the other three) +) + +$(P +In this chapter we will cover the particular type of expression that is used in conditional statements. +) + +$(P +Before going further though, I would like to repeat the assignment operator once more, this time emphasizing the two expressions that appear on its left and right sides: the assignment operator ($(C =)) assigns the value of the expression on its right-hand side to the expression on its left-hand side (e.g. to a variable). +) + +--- + temperature $(HILITE =) 23 // temperature's value becomes 23 +--- + +$(H5 Logical Expressions) + +$(P +Logical expressions are the expressions that are used in Boolean arithmetic. Logical expressions are what makes computer programs make decisions like "if the answer is yes, I will save the file". +) + +$(P +Logical expressions can have one of only two values: $(C false) that indicates falsity, and $(C true) that indicates truth. +) + +$(P +I will use $(C writeln) expressions in the following examples. If a line has $(C true) printed at the end, it will mean that what is printed on the line is true. Similarly, $(C false) will mean that what is on the line is false. For example, if the output of a program is the following, +) + +$(SHELL +There is coffee: true +) + +$(P +then it will mean that "there is coffee". Similarly, +) + +$(SHELL +There is coffee: false +) + +$(P +will mean that "there is no coffee". I use the "... is ...: false" construct to mean "is not" or "is false". +) + +$(P +Logical expressions are used extensively in $(I conditional statements), $(I loops), $(I function parameters), etc. It is essential to understand how they work. Luckily, logical expressions are easy to explain and use. +) + +$(P +The logical operators that are used in logical expressions are the following: +) + +$(UL + +$(LI $(IX ==) $(IX equals, logical operator) The $(C ==) operator answers the question "is equal to?". It compares the expression on its left side to the one on its right side and produces $(C true) if they are equal and $(C false) if they are not. By definition, the value that $(C ==) produces is a logical expression. + +$(P +As an example, let's assume that we have the following two variables: +) + +--- + int daysInWeek = 7; + int monthsInYear = 12; +--- + +$(P +The following are two logical expressions that use those values: +) + +--- + daysInWeek == 7 // true + monthsInYear == 11 // false +--- + +) + +$(LI $(IX !=) $(IX not equals, logical operator) The $(C !=) operator answers the question "is not equal to?". It compares the two expressions on its sides and produces the opposite of $(C ==). + + +--- + daysInWeek != 7 // false + monthsInYear != 11 // true +--- + +) + +$(LI $(IX ||) $(IX or, logical operator) The $(C ||) operator means "or", and produces $(C true) if any one of the logical expressions is true. + +$(P +If the value of the left-hand expression is $(C true), it produces $(C true) without even looking at the expression that is on the right-hand side. If the left-hand side is $(C false), then it produces the value of the right-hand side. This operator is similar to the "or" in English: if the left one, the right one, or both are $(C true), then it produces $(C true). +) + +$(P +The following table presents all of the possible values for both sides of this operator and its result: +) + + + + + + + +
    Left expressionOperatorRight expressionResult
    false||falsefalse
    false||truetrue
    true||false (not evaluated)true
    true||true (not evaluated)true
    + +--- +import std.stdio; + +void main() { + // false means "no", true means "yes" + + bool existsCoffee = false; + bool existsTea = true; + + writeln("There is warm drink: ", + existsCoffee $(HILITE ||) existsTea); +} +--- + +$(P +Because at least one of the two expressions is $(C true), the logical expression above produces $(C true). +) + +) + +$(LI $(IX &&) $(IX and, logical operator) The $(C &&) operator means "and", and produces $(C true) if both of the expressions are true. + +$(P +If the value of the left-hand expression is $(C false), it produces $(C false) without even looking at the expression that is on the right-hand side. If the left-hand side is $(C true), then it produces the value of the right-hand side. This operator is similar to the "and" in English: if the left value and the right value are $(C true), then it produces $(C true). +) + + + + + + + +
    Left expressionOperatorRight expressionResult
    false&&false (not evaluated)false
    false&&true (not evaluated)false
    true&&falsefalse
    true&&truetrue
    + +--- + writeln("I will drink coffee: ", + wantToDrinkCoffee $(HILITE &&) existsCoffee); +--- + +$(P $(I +$(B Note:) The fact that the $(C ||) and $(C &&) operators may not evaluate the right-hand expression is called their) short-circuit behavior $(I. The ternary operator $(C ?:), which we will see in a later chapter, is similar in that it never evaluates one of its three expressions. All of the other operators always evaluate and use all of their expressions. +)) + +) + +$(LI $(IX ^, logical exclusive or) $(IX xor, logical operator) The $(C ^) operator answers the question "is one or the other but not both?". This operator produces $(C true) if only one expression is $(C true), but not both. + +$(P +$(B Warning:) In reality, this operator is not a logical operator but an arithmetic one. It behaves like a logical operator only if both of the expressions are $(C bool). +) + + + + + + + +
    Left expressionOperatorRight expressionResult
    false^falsefalse
    false^truetrue
    true^falsetrue
    true^truefalse
    + +$(P +For example, the logic that represents my playing chess if $(I only one) of my two friends shows up can be coded like this: +) + +--- + writeln("I will play chess: ", jimShowedUp $(HILITE ^) bobShowedUp); +--- + +) + +$(LI $(IX <, less than) $(IX less than, logical operator) The $(C <) operator answers the question "is less than?" (or "does come before in sort order?"). + +--- + writeln("We beat: ", theirScore $(HILITE <) ourScore); +--- + +) + +$(LI $(IX >, greater than) $(IX greater than, logical operator) The $(C >) operator answers the question "is greater than?" (or "does come after in sort order?"). + +--- + writeln("They beat: ", theirScore $(HILITE >) ourScore); +--- + +) + +$(LI $(IX <=) $(IX less than or equal to, logical operator) The $(C <=) operator answers the question "is less than or equal to?" (or "does come before or the same in sort order?"). This operator is the opposite of the $(C >) operator. + +--- + writeln("We were not beaten: ", theirScore $(HILITE <=) ourScore); +--- + +) + +$(LI $(IX >=) $(IX greater than or equal to, logical operator) The $(C >=) operator answers the question "is greater than or equal to?" (or "does come after or the same in sort order?"). This operator is the opposite of the $(C <) operator. + +--- + writeln("We did not beat: ", theirScore $(HILITE >=) ourScore); +--- + +) + +$(LI $(IX !, logical not) $(IX not, logical operator) The $(C !) operator means "the opposite of". Different from the other logical operators, it takes just one expression and produces $(C true) if that expression is $(C false), and $(C false) if that expression is $(C true). + +--- + writeln("I will walk: ", $(HILITE !)existsBicycle); +--- + +) + +) + +$(H5 Grouping expressions) + +$(P +The order in which the expressions are evaluated can be specified by using parentheses to group them. When parenthesized expressions appear in more complex expressions, the parenthesized expressions are evaluated before they can be used in the expressions that they appear in. For example, the expression "if there is coffee or tea, and also cookie or scone; then I am happy" can be coded as follows: +) + +--- +writeln("I am happy: ", +(existsCoffee || existsTea) && (existsCookie || existsScone)); +--- + +$(P +If the sub expressions were not parenthesized, the expressions would be evaluated according to $(I operator precedence) rules of D (which have been inherited from the C language). Since in these rules $(C &&) has a higher precedence than $(C ||), writing the expression without parentheses would not be evaluated as intended: +) + +--- +writeln("I am happy: ", +existsCoffee || existsTea && existsCookie || existsScone); +--- + +$(P +The $(C &&) operator would be evaluated first and the whole expression would be the semantic equivalent of the following expression: +) + +--- +writeln("I am happy: ", +existsCoffee || (existsTea && existsCookie) || existsScone); +--- + +$(P +That has a totally different meaning: "if there is coffee, or tea and cookie, or scone; then I am happy". +) + +$(P1 +Almost nobody can memorize all of the operator precedence rules. For that reason, for code correctness and clarity, it would be helpful to use parentheses even when not necessary. +) + +$(P +The operator precedence table will be presented $(LINK2 operator_precedence.html, later in the book). +) + +$(H5 $(IX input, bool) $(IX read, bool) Reading $(C bool) input) + +$(P +All of the $(C bool) values above are automatically printed as $(STRING "false") or $(STRING "true"). It is the same in the opposite direction: $(C readf()) automatically converts strings $(STRING "false") and $(STRING "true") to $(C bool) values $(C false) and $(C true), respectively. It accepts any combination of lower and uppercase letters as well. For example, $(STRING "False") and $(STRING "FALSE") are converted to $(C false) and $(STRING "True") and $(STRING "TRUE") are converted to $(C true). +) + +$(P +Note that this is the case only when reading into $(C bool) variables. Otherwise, the input would be read as-is without conversion when reading into a $(C string) variable. (As we will see later in the $(LINK2 strings.html, strings chapter), one must use $(C readln()) when reading strings.) +) + +$(PROBLEM_COK + +$(PROBLEM +We've seen above that the $(C <) and the $(C >) operators are used to determine whether a value is less than or greater than another value; but there is no operator that answers the question "is between?" to determine whether a value is between two other values. + +$(P +Let's assume that a programmer has written the following code to determine whether $(C value) is between 10 and 20. Observe that the program cannot be compiled as written: +) + +--- +import std.stdio; + +void main() { + int value = 15; + + writeln("Is between: ", + 10 < value < 20); $(DERLEME_HATASI) +} +--- + +$(P +Try using parentheses around the whole expression: +) + +--- + writeln("Is between: ", + (10 < value < 20)); $(DERLEME_HATASI) +--- + +$(P +Observe that it still cannot be compiled. +) + +) + +$(PROBLEM + +While searching for a solution to this problem, the same programmer discovers that the following use of parentheses now enables the code to be compiled: + +--- + writeln("Is between: ", + (10 < value) < 20); // ← compiles but WRONG +--- +$(P +Observe that the program now works as expected and prints "true". Unfortunately, that output is misleading because the program has a bug. To see the effect of that bug, replace 15 with a value greater than 20: +) + +--- + int value = 21; +--- + +$(P +Observe that the program still prints "true" even though 21 is not less than 20. +) + +$(P +$(B Hint:) Remember that the type of a logical expression is $(C bool). It shouldn't make sense whether a $(C bool) value is less than 20. The reason it compiles is due to the compiler converting the boolean expression to a 1 or 0, and then evaluating that against 20 to see if it is less. +) + +) + +$(PROBLEM +The logical expression that answers the question "is between?" must instead be coded like this: "is greater than the lower value and less than the upper value?". + +$(P +Change the expression in the program according to that logic and observe that it now prints "true" as expected. Additionally, test that the logical expression works correctly for other values as well: for example, when $(C value) is 50 or 1, the program should print "false"; and when it is 12, the program should print "true". +) + +) + +$(PROBLEM +Let's assume that we can go to the beach when one of the following conditions is true: + +$(UL + +$(LI If the distance to the beach is less than 10 miles and there is a bicycle for everyone) + +$(LI If there is fewer than 6 of us, and we have a car, and at least one of us has a driver license) + +) + +$(P +As written, the following program always prints "true". Construct a logical expression that will print "true" when one of the conditions above is true. (When trying the program, enter "false" or "true" for questions that start with "Is there a".). +) + +--- +import std.stdio; + +void main() { + write("How many are we? "); + int personCount; + readf(" %s", &personCount); + + write("How many bicycles are there? "); + int bicycleCount; + readf(" %s", &bicycleCount); + + write("What is the distance to the beach? "); + int distance; + readf(" %s", &distance); + + write("Is there a car? "); + bool existsCar; + readf(" %s", &existsCar); + + write("Is there a driver license? "); + bool existsLicense; + readf(" %s", &existsLicense); + + /* Replace the 'true' below with a logical expression that + * produces the value 'true' when one of the conditions + * listed in the question is satisfied: */ + writeln("We are going to the beach: ", true); +} +--- + +$(P +Enter various values and test that the logical expression that you wrote works correctly. +) + +) + +) + +Macros: + TITLE=Logical Expressions + + DESCRIPTION=The logical expressions and the logical operators of the D programming language + + KEYWORDS=d programming language tutorial book logical expression bool false true + +MINI_SOZLUK= diff --git a/book/d.en/lvalue_rvalue.d b/book/d.en/lvalue_rvalue.d new file mode 100644 index 0000000000..29c4a85722 --- /dev/null +++ b/book/d.en/lvalue_rvalue.d @@ -0,0 +1,218 @@ +Ddoc + +$(DERS_BOLUMU $(IX lvalue) $(IX rvalue) Lvalues and Rvalues) + +$(P +$(IX expression, lvalue vs rvalue) The value of every expression is classified as either an lvalue or an rvalue. A simple way of differentiating the two is thinking of lvalues as actual variables (including elements of arrays and associative arrays), and rvalues as temporary results of expressions (including literals). +) + +$(P +As a demonstration, the first $(C writeln()) expression below uses only lvalues and the other one uses only rvalues: +) + +--- +import std.stdio; + +void main() { + int i; + immutable(int) imm; + auto arr = [ 1 ]; + auto aa = [ 10 : "ten" ]; + + /* All of the following arguments are lvalues. */ + + writeln(i, // mutable variable + imm, // immutable variable + arr, // array + arr[0], // array element + aa[10]); // associative array element + // etc. + + enum message = "hello"; + + /* All of the following arguments are rvalues. */ + + writeln(42, // a literal + message, // a manifest constant + i + 1, // a temporary value + calculate(i)); // return value of a function + // etc. +} + +int calculate(int i) { + return i * 2; +} +--- + +$(H5 Limitations of rvalues) + +$(P +Compared to lvalues, rvalues have the following three limitations. +) + +$(H6 Rvalues don't have memory addresses) + +$(P +An lvalue has a memory location to which we can refer, while an rvalue does not. +) + +$(P +For example, it is not possible to take the address of the rvalue expression $(C a + b) in the following program: +) + +--- +import std.stdio; + +void main() { + int a; + int b; + + readf(" %s", &a); $(CODE_NOTE compiles) + readf(" %s", &(a + b)); $(DERLEME_HATASI) +} +--- + +$(SHELL +Error: a + b $(HILITE is not an lvalue) +) + +$(H6 Rvalues cannot be assigned new values) + +$(P +If mutable, an lvalue can be assigned a new value, while an rvalue cannot be: +) + +--- + a = 1; $(CODE_NOTE compiles) + (a + b) = 2; $(DERLEME_HATASI) +--- + +$(SHELL +Error: a + b $(HILITE is not an lvalue) +) + +$(H6 Rvalues cannot be passed to functions by reference) + +$(P +An lvalue can be passed to a function that takes a parameter by reference, while an rvalue cannot be: +) + +--- +void incrementByTen($(HILITE ref int) value) { + value += 10; +} + +// ... + + incrementByTen(a); $(CODE_NOTE compiles) + incrementByTen(a + b); $(DERLEME_HATASI) +--- + +$(SHELL +Error: function deneme.incrementByTen (ref int value) +$(HILITE is not callable) using argument types (int) +) + +$(P +The main reason for this limitation is the fact that a function taking a $(C ref) parameter can hold on to that reference for later use, at a time when the rvalue would not be available. +) + +$(P +Different from languages like C++, in D an rvalue cannot be passed to a function even if that function does $(I not) modify the argument: +) + +--- +void print($(HILITE ref const(int)) value) { + writeln(value); +} + +// ... + + print(a); $(CODE_NOTE compiles) + print(a + b); $(DERLEME_HATASI) +--- + +$(SHELL +Error: function deneme.print (ref const(int) value) +$(HILITE is not callable) using argument types (int) +) + +$(H5 $(IX auto ref, parameter) $(IX parameter, auto ref) Using $(C auto ref) parameters to accept both lvalues and rvalues) + +$(P +As it was mentioned in the previous chapter, $(C auto ref) parameters of $(LINK2 templates.html, function templates) can take both lvalues and rvalues. +) + +$(P +When the argument is an lvalue, $(C auto ref) means $(I by reference). On the other hand, since rvalues cannot be passed to functions by reference, when the argument is an rvalue, it means $(I by copy). For the compiler to generate code differently for these two distinct cases, the function must be a template. +) + +$(P +We will see templates in a later chapter. For now, please accept that the highlighted empty parentheses below make the following definition a $(I function template). +) + +--- +void incrementByTen$(HILITE ())($(HILITE auto ref) int value) { + /* WARNING: The parameter may be a copy if the argument is + * an rvalue. This means that the following modification + * may not be observable by the caller. */ + + value += 10; +} + +void main() { + int a; + int b; + + incrementByTen(a); $(CODE_NOTE lvalue; passed by reference) + incrementByTen(a + b); $(CODE_NOTE rvalue; copied) +} +--- + +$(P +$(IX isRef) It is possible to determine whether the parameter is an lvalue or an rvalue by using $(C __traits(isRef)) with $(C static if) : +) + +--- +void incrementByTen()(auto ref int value) { + $(HILITE static if) (__traits($(HILITE isRef), value)) { + // 'value' is passed by reference + } else { + // 'value' is copied + } +} +--- + +$(P +We will see $(C static if) and $(C __traits) later in $(LINK2 cond_comp.html, the Conditional Compilation chapter). +) + +$(H5 Terminology) + +$(P +The names "lvalue" and "rvalue" do not represent the characteristics of these two kinds of values accurately. The initial letters $(I l) and $(I r) come from $(I left) and $(I right), referring to the left- and the right-hand side expressions of the assignment operator: +) + +$(UL + +$(LI Assuming that it is mutable, an lvalue can be the left-hand expression of an assignment operation.) + +$(LI An rvalue cannot be the left-hand expression of an assignment operation.) + +) + +$(P +The terms "left value" and "right value" are confusing because in general both lvalues and rvalues can be on either side of an assignment operation: +) + +--- + // rvalue 'a + b' on the left, lvalue 'a' on the right: + array[a + b] = a; +--- + +Macros: + TITLE=Lvalues and Rvalues + + DESCRIPTION=Left-values and right-values and their differences. + + KEYWORDS=d programming language tutorial book lvalue rvalue diff --git a/book/d.en/main.cozum.d b/book/d.en/main.cozum.d new file mode 100644 index 0000000000..9a367a4032 --- /dev/null +++ b/book/d.en/main.cozum.d @@ -0,0 +1,76 @@ +Ddoc + +$(COZUM_BOLUMU Program Environment) + +$(OL + +$(LI + +--- +import std.stdio; +import std.conv; + +int main(string[] args) { + if (args.length != 4) { + stderr.writeln( + "ERROR! Usage: \n ", args[0], + " a_number operator another_number"); + return 1; + } + + immutable first = to!double(args[1]); + string op = args[2]; + immutable second = to!double(args[3]); + + switch (op) { + + case "+": + writeln(first + second); + break; + + case "-": + writeln(first - second); + break; + + case "x": + writeln(first * second); + break; + + case "/": + writeln(first / second); + break; + + default: + throw new Exception("Invalid operator: " ~ op); + } + + return 0; +} +--- + +) + +$(LI + +--- +import std.stdio; +import std.process; + +void main() { + write("Please enter the command line to execute: "); + string commandLine = readln(); + + writeln("The output: ", executeShell(commandLine)); +} +--- + +) + +) + +Macros: + TITLE=Program Environment Solutions + + DESCRIPTION=The exercise solutions for the Program Environment chapter. + + KEYWORDS=programming in d tutorial main environment diff --git a/book/d.en/main.d b/book/d.en/main.d new file mode 100644 index 0000000000..74a64da44e --- /dev/null +++ b/book/d.en/main.d @@ -0,0 +1,500 @@ +Ddoc + +$(DERS_BOLUMU $(IX program environment) Program Environment) + +$(P +$(IX main) We have seen that $(C main()) is a function. Program execution starts with $(C main()) and branches off to other functions from there. The definition of $(C main()) that we have used so far has been the following: +) + +--- +void main() { + // ... +} +--- + +$(P +According to that definition $(C main()) does not take any parameters and does not return a value. In reality, in most systems every program necessarily returns a value to its environment when it ends, which is called an exit status or return code. Because of this, although it is possible to specify the return type of $(C main()) as $(C void), it will actually return a value to the operating system or launch environment. +) + +$(H5 The return value of $(C main())) + +$(P +Programs are always started by an entity in a particular environment. The entity that starts the program may be the shell where the user types the name of the program and presses the Enter key, a development environment where the programmer clicks the [Run] button, and so on. +) + +$(P +In D and several other programming languages, the program communicates its exit status to its environment by the return value of $(C main()). +) + +$(P +The exact meaning of return codes depend on the application and the system. In almost all systems a return value of zero means a successful completion, while other values generally mean some type of failure. There are exceptions to this, though. For instance, in OpenVMS even values indicate failure, while odd values indicate success. Still, in most systems the values in the range [0, 125] can be used safely, with values 1 to 125 having a meaning specific to that program. +) + +$(P +For example, the common Unix program $(C ls), which is used for listing contents of directories, returns 0 for success, 1 for minor errors and 2 for serious ones. +) + +$(P +In many environments, the return value of the program that has been executed most recently in the terminal can be seen through the $(C $?) environment variable. For example, when we ask $(C ls) to list a file that does not exist, its nonzero return value can be observed with $(C $?) as seen below. +) + +$(P +$(I $(B Note:) In the command line interactions below, the lines that start with $(C #) indicate the lines that the user types. If you want to try the same commands, you must enter the contents of those lines except for the $(C #) character. Also, the commands below start a program named $(C deneme); replace that name with the name of your test program.) +) + +$(P +$(I Additionally, although the following examples show interactions in a Linux terminal, they would be similar but not exactly the same in terminals of other operating systems.) +) + +$(SHELL +# ls a_file_that_does_not_exist +$(SHELL_OBSERVED ls: cannot access a_file_that_does_not_exist: No such file +or directory) +# $(HILITE echo $?) +$(SHELL_OBSERVED 2) $(SHELL_NOTE the return value of ls) +) + +$(H6 $(C main()) always returns a value) + +$(P +Some of the programs that we have written so far threw exceptions when they could not continue with their tasks. As much as we have seen so far, when an exception is thrown, the program ends with an $(C object.Exception) error message. +) + +$(P +When that happens, even if $(C main()) has been defined as returning $(C void), a nonzero status code is automatically returned to the program's environment. Let's see this in action in the following simple program that terminates with an exception: +) + +--- +void main() { + throw new Exception("There has been an error."); +} +--- + +$(P +Although the return type is specified as $(C void), the return value is nonzero: +) + +$(SHELL +# ./deneme +$(SHELL_OBSERVED object.Exception: There has been an error. +...) +# echo $? +$(SHELL_OBSERVED $(HILITE 1)) +) + +$(P +Similarly, $(C void main()) functions that terminate successfully also automatically return zero as their return values. Let's see this with the following program that terminates $(I successfully): +) + +--- +import std.stdio; + +void main() { + writeln("Done!"); +} +--- + +$(P +The program returns zero: +) + +$(SHELL +# ./deneme +$(SHELL_OBSERVED Done!) +# echo $? +$(SHELL_OBSERVED $(HILITE 0)) +) + +$(H6 Specifying the return value) + +$(P +To choose a specific return code we return a value from $(C main()) in the same way as we would from any other function. The return type must be specified as $(C int) and the value must be returned by the $(C return) statement: +) + +--- +import std.stdio; + +$(HILITE int) main() { + int number; + write("Please enter a number between 3 and 6: "); + readf(" %s", &number); + + if ((number < 3) || (number > 6)) { + $(HILITE stderr).writefln("ERROR: %s is not valid!", number); + $(HILITE return 111); + } + + writefln("Thank you for %s.", number); + + $(HILITE return 0); +} +--- + +$(P +When the entered number is within the valid range, the return value of the program is zero: +) + +$(SHELL +# ./deneme +$(SHELL_OBSERVED Please enter a number between 3 and 6: 5 +Thank you for 5.) +# echo $? +$(SHELL_OBSERVED $(HILITE 0)) +) + +$(P +When the number is outside of the valid range, the return value of the program is 111: +) + +$(SHELL +# ./deneme +$(SHELL_OBSERVED Please enter a number between 3 and 6: 10 +ERROR: 10 is not valid!) +# echo $? +$(SHELL_OBSERVED $(HILITE 111)) +) + +$(P +The value of 111 in the above program is arbitrary; normally 1 is suitable as the failure code. +) + +$(H5 $(IX stderr) Standard error stream $(C stderr)) + +$(P +The program above uses the stream $(C stderr). That stream is the third of the standard streams. It is used for writing error messages: +) + +$(UL +$(LI $(C stdin): standard input stream) +$(LI $(C stdout): standard output stream) +$(LI $(C stderr): standard error stream) +) + +$(P +When a program is started in a terminal, normally the messages that are written to $(C stdout) and $(C stderr) both appear on the terminal window. When needed, it is possible to redirect these outputs individually. This subject is outside of the focus of this chapter and the details may vary for each shell program. +) + +$(H5 Parameters of $(C main())) + +$(P +It is common for programs to take parameters from the environment that started them. For example, we have already passed a file name as a command line option to $(C ls) above. There are two command line options in the following line: +) + +$(SHELL +# ls $(HILITE -l deneme) +$(SHELL_OBSERVED -rwxr-xr-x 1 acehreli users 460668 Nov 6 20:38 deneme) +) + +$(P +The set of command line parameters and their meanings are defined entirely by the program. Every program documents its usage, including what every parameter means. +) + +$(P +The arguments that are used when starting a D program are passed to that program's $(C main()) as a slice of $(C string)s. Defining $(C main()) as taking a parameter of type $(C string[]) is sufficient to have access to program arguments. The name of this parameter is commonly abbreviated as $(C args). The following program prints all of the arguments with which it is started: +) + +--- +import std.stdio; + +void main($(HILITE string[] args)) { + foreach (i, arg; args) { + writefln("Argument %-3s: %s", i, arg); + } +} +--- + +$(P +Let's start the program with arbitrary arguments: +) + +$(SHELL +# ./deneme some arguments on the command line 42 --an-option +$(SHELL_OBSERVED Argument 0 : ./deneme +Argument 1 : some +Argument 2 : arguments +Argument 3 : on +Argument 4 : the +Argument 5 : command +Argument 6 : line +Argument 7 : 42 +Argument 8 : --an-option) +) + +$(P +In almost all systems, the first argument is the name of the program, in the way it has been entered by the user. The other arguments appear in the order they were entered. +) + +$(P +It is completely up to the program how it makes use of the arguments. The following program prints its two arguments in reverse order: +) + +--- +import std.stdio; + +int main(string[] args) { + if (args.length != 3) { + stderr.writefln("ERROR! Correct usage:\n" ~ + " %s word1 word2", args[0]); + return 1; + } + + writeln(args[2], ' ', args[1]); + + return 0; +} +--- + +$(P +The program also shows its correct usage if you don't enter exactly two words: +) + +$(SHELL +# ./deneme +$(SHELL_OBSERVED ERROR! Correct usage: + ./deneme word1 word2) +# ./deneme world hello +$(SHELL_OBSERVED hello world) +) + +$(H5 $(IX command line options) $(IX getopt, std.getopt) Command line options and the $(C std.getopt) module) + +$(P +That is all there is to know about the parameters and the return value of $(C main()). However, parsing the arguments is a repetitive task. The $(C std.getopt) module is designed to help with parsing the command line options of programs. +) + +$(P +Some parameters like "world" and "hello" above are purely data for the program to use. Other kinds of parameters are called $(I command line options), and are used to change the behaviors of programs. An example of a command line option is the $(C -l) option that has been passed to $(C ls) above. +) + +$(P +Command line options make programs more useful by removing the need for a human user to interact with the program to have it behave in a certain way. With command line options, programs can be started from script programs and their behaviors can be specified through command line options. +) + +$(P +Although the syntax and meanings of command line arguments of every program is specific to that program, their format is somewhat standard. For example, in POSIX, command line options start with $(C --) followed by the name of the option, and values come after $(C =) characters: +) + +$(SHELL +# ./deneme --an-option=17 +) + +$(P +The $(C std.getopt) module simplifies parsing such options. It has more capabilities than what is covered in this section. +) + +$(P +Let's design a program that prints random numbers. Let's take the minimum, maximum, and total number of these numbers as program arguments. Let's require the following syntax to get these values from the command line: +) + +$(SHELL +# ./deneme --count=7 --minimum=10 --maximum=15 +) + +$(P +The $(C getopt()) function parses and assigns those values to variables. Similarly to $(C readf()), the addresses of variables must be specified by the $(C &) operator: +) + +--- +import std.stdio; +$(HILITE import std.getopt;) +import std.random; + +void main(string[] args) { + int count; + int minimum; + int maximum; + + $(HILITE getopt)(args, + "count", $(HILITE &)count, + "minimum", $(HILITE &)minimum, + "maximum", $(HILITE &)maximum); + + foreach (i; 0 .. count) { + write(uniform(minimum, maximum + 1), ' '); + } + + writeln(); +} +--- + +$(SHELL +# ./deneme --count=7 --minimum=10 --maximum=15 +$(SHELL_OBSERVED 11 11 13 11 14 15 10) +) + +$(P +Many command line options of most programs have a shorter syntax as well. For example, $(C -c) may have the same meaning as $(C --count). Such alternative syntax for each option is specified in $(C getopt()) after a $(C |) character. There may be more than one shortcut for each option: +) + +--- + getopt(args, + "count|c", &count, + "minimum|n", &minimum, + "maximum|x", &maximum); +--- + +$(P +It is common to use a single dash for the short versions and the $(C =) character is usually either omitted or substituted by a space: +) + +$(SHELL +# ./deneme -c7 -n10 -x15 +$(SHELL_OBSERVED 11 13 10 15 14 15 14) +# ./deneme -c 7 -n 10 -x 15 +$(SHELL_OBSERVED 11 13 10 15 14 15 14) +) + +$(P +$(C getopt()) converts the arguments from $(C string) to the type of each variable. For example, since $(C count) above is an $(C int), $(C getopt()) converts the value specified for the $(C --count) argument to an $(C int). When needed, such conversions may also be performed explicitly by $(C to). +) + +$(P +So far we have used $(C std.conv.to) only when converting to $(C string). $(C to) can, in fact, convert from any type to any type, as long as that conversion is possible. For example, the following program takes advantage of $(C to) when converting its argument to $(C size_t): +) + +--- +import std.stdio; +$(HILITE import std.conv); + +void main(string[] args) { + // The default count is 10 + size_t count = 10; + + if (args.length > 1) { + // There is an argument + count = $(HILITE to!size_t)(args[1]); + } + + foreach (i; 0 .. count) { + write(i * 2, ' '); + } + + writeln(); +} +--- + + +$(P +The program produces 10 numbers when no argument is specified: +) + +$(SHELL +# ./deneme +$(SHELL_OBSERVED 0 2 4 6 8 10 12 14 16 18) +# ./deneme 3 +$(SHELL_OBSERVED 0 2 4) +) + +$(H5 $(IX environment variable) Environment variables) + +$(P +The environment that a program is started in generally provides some variables that the program can make use of. The environment variables can be accessed through the associative array interface of $(C std.process.environment). For example, the following program prints the $(C PATH) environment variable: +) + +--- +import std.stdio; +$(HILITE import std.process;) + +void main() { + writeln($(HILITE environment["PATH"])); +} +--- + +$(P +The output: +) + +$(SHELL +# ./deneme +$(SHELL_OBSERVED /usr/local/bin:/usr/bin) +) + +$(P +$(C std.process.environment) provides access to the environment variables through the associative array syntax. However, $(C environment) itself is not an associative array. When needed, the environment variables can be converted to an associative array by using $(C toAA()): +) + +--- + string[string] envVars = environment.toAA(); +--- + +$(H5 $(IX executeShell, std.process) Starting other programs) + +$(P +Programs may start other programs and become the $(I environment) for those programs. A function that enables this is $(C executeShell), from the $(C std.process) module. +) + +$(P +$(C executeShell) executes its parameter as if the command was typed at the terminal. It then returns both the return code and the output of that command as a $(I tuple). Tuples are array-like structures, which we will see later in $(LINK2 tuples.html, the Tuples chapter): +) + +--- +import std.stdio; +import std.process; + +void main() { + const result = $(HILITE executeShell)("ls -l deneme"); + const returnCode = result[0]; + const output = result[1]; + + writefln("ls returned %s.", returnCode); + writefln("Its output:\n%s", output); +} +--- + +$(P +The output: +) + +$(SHELL +# ./deneme +$(SHELL_OBSERVED +ls returned 0. +Its output: +-rwxrwxr-x. 1 acehreli acehreli 1359178 Apr 21 15:01 deneme +) +) + +$(H5 Summary) + +$(UL + +$(LI Even when it is defined with a return type of $(C void), $(C main()) automatically returns zero for success and nonzero for failure.) + +$(LI $(C stderr) is suitable to print error messages.) + +$(LI $(C main) can take parameters as $(C string[]).) + +$(LI $(C std.getopt) helps with parsing command line options.) + +$(LI $(C std.process) helps with accessing environment variables and starting other programs.) + +) + +$(PROBLEM_COK + +$(PROBLEM +Write a calculator program that takes an operator and two operands as command line arguments. Have the program support the following usage: + +$(SHELL +# ./deneme 3.4 x 7.8 +$(SHELL_OBSERVED 26.52) +) + +$(P +$(I $(B Note:) Because the $(C *) character has a special meaning on most terminals (more accurately, on most $(I shells)), I have used $(C x) instead. You may still use $(C *) as long as it is $(I escaped) as $(C \*).) +) + +) + +$(PROBLEM +Write a program that asks the user which program to start, starts that program, and prints its output. +) + +) + +Macros: + TITLE=Program Environment + + DESCRIPTION=The return value and parameters of main(), environment variables, and starting other programs from D programs. + + KEYWORDS=d programming language tutorial book environment diff --git a/book/d.en/member_functions.cozum.d b/book/d.en/member_functions.cozum.d new file mode 100644 index 0000000000..2decb82e00 --- /dev/null +++ b/book/d.en/member_functions.cozum.d @@ -0,0 +1,170 @@ +Ddoc + +$(COZUM_BOLUMU Member Functions) + +$(OL + +$(LI +Potentially negative intermediate values make $(C decrement()) slightly more complicated than $(C increment()): + +--- +struct TimeOfDay { + // ... + + void decrement(Duration duration) { + auto minutesToSubtract = duration.minute % 60; + auto hoursToSubtract = duration.minute / 60; + + minute -= minutesToSubtract; + + if (minute < 0) { + minute += 60; + ++hoursToSubtract; + } + + hour -= hoursToSubtract; + + if (hour < 0) { + hour = 24 - (-hour % 24); + } + } + + // ... +} +--- + +) + +$(LI +To see how much easier it gets with $(C toString()) member functions, let's look at the $(C Meeting) overload of $(C info()) one more time: + +--- +void info(Meeting meeting) { + info(meeting.start); + write('-'); + info(meeting.end); + + writef(" \"%s\" meeting with %s attendees", + meeting.topic, + meeting.attendanceCount); +} +--- + +$(P +Taking advantage of the already-defined $(C TimeOfDay.toString), the implementation of $(C Meeting.toString) becomes trivial: +) + +--- + string toString() { + return format("%s-%s \"%s\" meeting with %s attendees", + start, end, topic, attendanceCount); + } +--- + +$(P +Here is the entire program: +) + +--- +import std.stdio; +import std.string; + +struct Duration { + int minute; +} + +struct TimeOfDay { + int hour; + int minute; + + string toString() { + return format("%02s:%02s", hour, minute); + } + + void increment(Duration duration) { + minute += duration.minute; + + hour += minute / 60; + minute %= 60; + hour %= 24; + } +} + +struct Meeting { + string topic; + int attendanceCount; + TimeOfDay start; + TimeOfDay end; + + string toString() { + return format("%s-%s \"%s\" meeting with %s attendees", + start, end, topic, attendanceCount); + } +} + +struct Meal { + TimeOfDay time; + string address; + + string toString() { + TimeOfDay end = time; + end.increment(Duration(90)); + + return format("%s-%s Meal, Address: %s", + time, end, address); + } +} + +struct DailyPlan { + Meeting amMeeting; + Meal lunch; + Meeting pmMeeting; + + string toString() { + return format("%s\n%s\n%s", + amMeeting, + lunch, + pmMeeting); + } +} + +void main() { + auto bikeRideMeeting = Meeting("Bike Ride", 4, + TimeOfDay(10, 30), + TimeOfDay(11, 45)); + + auto lunch = Meal(TimeOfDay(12, 30), "İstanbul"); + + auto budgetMeeting = Meeting("Budget", 8, + TimeOfDay(15, 30), + TimeOfDay(17, 30)); + + auto todaysPlan = DailyPlan(bikeRideMeeting, + lunch, + budgetMeeting); + + writeln(todaysPlan); + writeln(); +} +--- + +$(P +The output of the program is the same as the earlier one that has been using $(C info()) function overloads: +) + +$(SHELL +10:30-11:45 "Bike Ride" meeting with 4 attendees +12:30-14:00 Meal, Address: İstanbul +15:30-17:30 "Budget" meeting with 8 attendees +) + +) + +) + +Macros: + TITLE=Member Functions + + DESCRIPTION=Programming in D exercise solutions: Member Functions + + KEYWORDS=d programming book tutorial member functions exercise solutions diff --git a/book/d.en/member_functions.d b/book/d.en/member_functions.d new file mode 100644 index 0000000000..b6261c5831 --- /dev/null +++ b/book/d.en/member_functions.d @@ -0,0 +1,418 @@ +Ddoc + +$(DERS_BOLUMU $(IX member function) $(IX function, member) Member Functions) + +$(P +Although this chapter focuses only on structs, most of the information in this chapter is applicable to classes as well. +) + +$(P +In this chapter we will cover member functions of structs and define the special $(C toString()) member function that is used for representing objects in the $(C string) format. +) + +$(P +When a struct or class is defined, usually a number of functions are also defined alongside with it. We have seen examples of such functions in the earlier chapters: $(C addDuration()) and an overload of $(C info()) have been written specifically to be used with the $(C TimeOfDay) type. In a sense, these two functions define the $(I interface) of $(C TimeOfDay). +) + +$(P +The first parameter of both $(C addDuration()) and $(C info()) has been the $(C TimeOfDay) object that each function would be operating on. Additionally, just like all of the other functions that we have seen so far, both of the functions have been defined at the $(I module level), outside of any other scope. +) + +$(P +The concept of a set of functions determining the interface of a struct is very common. For that reason, functions that are closely related to a type can be defined within the body of that type. +) + +$(H5 Defining member functions) + +$(P +Functions that are defined within the curly brackets of a $(C struct) are called $(I member functions): +) + +--- +struct SomeStruct { + void $(I member_function)(/* the parameters of the function */) { + // ... the definition of the function ... + } + + // ... the other members of the struct ... +} +--- + +$(P +Member functions are accessed the same way as member variables, separated from the name of the object by a dot: +) + +--- + $(I object.member_function(arguments)); +--- + +$(P +We have used member functions before when specifying $(C stdin) and $(C stdout) explicitly during input and output operations: +) + +--- + stdin.readf(" %s", &number); + stdout.writeln(number); +--- + +$(P +The $(C readf()) and $(C writeln()) above are member function calls, operating on the objects $(C stdin) and $(C stdout), respectively. +) + +$(P +Let's define $(C info()) as a member function. Its previous definition has been the following: +) + +--- +void info(TimeOfDay time) { + writef("%02s:%02s", time.hour, time.minute); +} +--- + +$(P +Making $(C info()) a member function is not as simple as moving its definition inside the struct. The function must be modified in two ways: +) + +--- +struct TimeOfDay { + int hour; + int minute; + + void info() { // (1) + writef("%02s:%02s", hour, minute); // (2) + } +} +--- + +$(OL +$(LI The member function does not take the object explicitly as a parameter.) + +$(LI For that reason, it refers to the member variables simply as $(C hour) and $(C minute).) +) + +$(P +This is because member functions are always called on an existing object. The object is implicitly available to the member function: +) + +--- + auto time = TimeOfDay(10, 30); + $(HILITE time.)info(); +--- + +$(P +The $(C info()) member function is being called on the $(C time) object above. The members $(C hour) and $(C minute) that are referred to within the function definition correspond to the members of the $(C time) object, specifically $(C time.hour) and $(C time.minute). +) + +$(P +The member function call above is almost the equivalent of the following regular function call: +) + +--- + time.info(); // member function + info(time); // regular function (the previous definition) +--- + +$(P +Whenever a member function is called on an object, the members of the object are implicitly accessible by the function: +) + +--- + auto morning = TimeOfDay(10, 0); + auto evening = TimeOfDay(22, 0); + + $(HILITE morning.)info(); + write('-'); + $(HILITE evening.)info(); + writeln(); +--- + +$(P +When called on $(C morning), the $(C hour) and $(C minute) that are used inside the member function refer to $(C morning.hour) and $(C morning.minute). Similarly, when called on $(C evening), they refer to $(C evening.hour) and $(C evening.minute): +) + +$(SHELL +10:00-22:00 +) + +$(H6 $(IX toString) $(C toString()) for $(C string) representations) + +$(P +We have discussed the limitations of the $(C info()) function in the previous chapter. There is at least one more inconvenience with it: Although it prints the time in human-readable format, printing the $(C '-') character and terminating the line still needs to be done explicitly by the programmer. +) + +$(P +However, it would be more convenient if $(C TimeOfDay) objects could be used as easy as fundamental types as in the following code: +) + +--- + writefln("%s-%s", morning, evening); +--- + +$(P +In addition to reducing four lines of code to one, it would also allow printing objects to any stream: +) + +--- + auto file = File("time_information", "w"); + file.writefln("%s-%s", morning, evening); +--- + +$(P +The $(C toString()) member function of user-defined types is treated specially: It is called automatically to produce the $(C string) representations of objects. $(C toString()) must return the $(C string) representation of the object. +) + +$(P +Without getting into more detail, let's first see how the $(C toString()) function is defined: +) + +--- +import std.stdio; + +struct TimeOfDay { + int hour; + int minute; + + string toString() { + return "todo"; + } +} + +void main() { + auto morning = TimeOfDay(10, 0); + auto evening = TimeOfDay(22, 0); + + writefln("%s-%s", morning, evening); +} +--- + +$(P +$(C toString()) does not produce anything meaningful yet, but the output shows that it has been called by $(C writefln()) twice for the two object: +) + +$(SHELL +todo-todo +) + +$(P +Also note that $(C info()) is not needed anymore. $(C toString()) is replacing its functionality. +) + +$(P +The simplest implementation of $(C toString()) would be to call $(C format()) of the $(C std.string) module. $(C format()) works in the same way as the formatted output functions like $(C writef()). The only difference is that instead of printing variables, it returns the formatted result in $(C string) format. +) + +$(P +$(C toString()) can simply return the result of $(C format()) directly: +) + +--- +import std.string; +// ... +struct TimeOfDay { +// ... + string toString() { + return $(HILITE format)("%02s:%02s", hour, minute); + } +} +--- + +$(P +Note that $(C toString()) returns the representation of only $(I this) object. The rest of the output is handled by $(C writefln()): It calls the $(C toString()) member function for the two objects separately, prints the $(C '-') character in between, and finally terminates the line: +) + +$(SHELL +10:00-22:00 +) + +$(P +The definition of $(C toString()) that is explained above does not take any parameters; it simply produces a $(C string) and returns it. An alternative definition of $(C toString()) takes a $(C delegate) parameter. We will see that definition later in $(LINK2 lambda.html, the Function Pointers, Delegates, and Lambdas chapter). +) + +$(H6 Example: $(C increment()) member function) + +$(P +Let's define a member function that adds a duration to $(C TimeOfDay) objects. +) + +$(P +Before doing that, let's first correct a design flaw that we have been living with. We have seen in the $(LINK2 struct.html, Structs chapter) that adding two $(C TimeOfDay) objects in $(C addDuration()) is not a meaningful operation: +) + +--- +TimeOfDay addDuration(TimeOfDay start, + TimeOfDay duration) { // meaningless + // ... +} +--- + +$(P +What is natural to add to a point in time is $(I duration). For example, adding the travel duration to the departure time would result in the arrival time. +) + +$(P +On the other hand, subtracting two points in time is a natural operation, in which case the result would be a $(I duration). +) + +$(P +The following program defines a $(C Duration) struct with minute-precision, and an $(C addDuration()) function that uses it: +) + +--- +struct Duration { + int minute; +} + +TimeOfDay addDuration(TimeOfDay start, + Duration duration) { + // Begin with a copy of start + TimeOfDay result = start; + + // Add the duration to it + result.minute += duration.minute; + + // Take care of overflows + result.hour += result.minute / 60; + result.minute %= 60; + result.hour %= 24; + + return result; +} + +unittest { + // A trivial test + assert(addDuration(TimeOfDay(10, 30), Duration(10)) + == TimeOfDay(10, 40)); + + // A time at midnight + assert(addDuration(TimeOfDay(23, 9), Duration(51)) + == TimeOfDay(0, 0)); + + // A time in the next day + assert(addDuration(TimeOfDay(17, 45), Duration(8 * 60)) + == TimeOfDay(1, 45)); +} +--- + +$(P +Let's redefine a similar function this time as a member function. $(C addDuration()) has been producing a new object as its result. Let's define an $(C increment()) member function that will directly modify $(I this) object instead: +) + +--- +struct Duration { + int minute; +} + +struct TimeOfDay { + int hour; + int minute; + + string toString() { + return format("%02s:%02s", hour, minute); + } + + void $(HILITE increment)(Duration duration) { + minute += duration.minute; + + hour += minute / 60; + minute %= 60; + hour %= 24; + } + + unittest { + auto time = TimeOfDay(10, 30); + + // A trivial test + time$(HILITE .increment)(Duration(10)); + assert(time == TimeOfDay(10, 40)); + + // 15 hours later must be in the next day + time$(HILITE .increment)(Duration(15 * 60)); + assert(time == TimeOfDay(1, 40)); + + // 22 hours 20 minutes later must be midnight + time$(HILITE .increment)(Duration(22 * 60 + 20)); + assert(time == TimeOfDay(0, 0)); + } +} +--- + +$(P +$(C increment()) increments the value of the object by the specified amount of duration. In a later chapter we will see how the $(I operator overloading) feature of D will make it possible to add a duration by the $(C +=) operator syntax: +) + +--- + time += Duration(10); // to be explained in a later chapter +--- + +$(P +Also note that $(C unittest) blocks can be written inside $(C struct) definitions as well, mostly for testing member functions. It is still possible to move such $(C unittest) blocks outside of the body of the struct: +) + +--- +struct TimeOfDay { + // ... struct definition ... +} + +unittest { + // ... struct tests ... +} +--- + +$(PROBLEM_COK + +$(PROBLEM +Add a $(C decrement()) member function to $(C TimeOfDay), which should reduce the time by the specified amount of duration. Similar to $(C increment()), it should $(I overflow) to the previous day when there is not enough time in the current day. For example, subtracting 10 minutes from 00:05 should result in 23:55. + +$(P +In other words, implement $(C decrement()) to pass the following unit tests: +) + +--- +struct TimeOfDay { + // ... + + void decrement(Duration duration) { + // ... please implement this function ... + } + + unittest { + auto time = TimeOfDay(10, 30); + + // A trivial test + time.decrement(Duration(12)); + assert(time == TimeOfDay(10, 18)); + + // 3 days and 11 hours earlier + time.decrement(Duration(3 * 24 * 60 + 11 * 60)); + assert(time == TimeOfDay(23, 18)); + + // 23 hours and 18 minutes earlier must be midnight + time.decrement(Duration(23 * 60 + 18)); + assert(time == TimeOfDay(0, 0)); + + // 1 minute earlier + time.decrement(Duration(1)); + assert(time == TimeOfDay(23, 59)); + } +} +--- + +) + +$(PROBLEM +Convert $(C Meeting), $(C Meal), and $(C DailyPlan) overloads of $(C info()) to $(C toString()) member functions as well. (See $(LINK2 function_overloading.cozum.html, the exercise solutions of the Function Overloading chapter) for their $(C info()) overloads.) + +$(P +You will notice that in addition to making their respective structs more convenient, the implementations of the $(C toString()) member functions will all consist of single lines. +) + +) + +) + +Macros: + TITLE=Member Functions + + DESCRIPTION=Adding special functionality to structs (and classes) as member functions in the D programming language. + + KEYWORDS=d programming lesson book tutorial member functions diff --git a/book/d.en/memory.d b/book/d.en/memory.d new file mode 100644 index 0000000000..706f26a3c6 --- /dev/null +++ b/book/d.en/memory.d @@ -0,0 +1,1335 @@ +Ddoc + +$(DERS_BOLUMU $(IX memory management) Memory Management) + +$(P +D is a language that does not require explicit memory management. However, it is important for a system programmer to know how to manage memory when needed for special cases. +) + +$(P +Memory management is a very broad topic. This chapter will introduce only the garbage collector (GC), allocating memory from it, and constructing objects at specific memory locations. I encourage you to research various memory management methods as well as the $(C std.allocator) module, which was still at experimental stage at the time of writing this book. +) + +$(P +As in some of the previous chapters, when I write $(I variable) below, I mean any type of variable including $(C struct) and $(C class) objects. +) + +$(H5 $(IX memory) Memory) + +$(P +Memory is a more significant resource than other system resources because both the running program and its data are located in the memory. The memory belongs ultimately to the operating system, which makes it available to programs to satisfy their needs. The amount of memory that a program uses may increase or decrease according to the immediate needs of a program. When a program terminates, the memory areas that it has been using are automatically returned back to the operating system. +) + +$(P +The memory can be imagined like a large sheet of paper where the values of variables are noted down. Each variable is kept at a specific location where its value is written to and read from as needed. Once the lifetime of a variable ends, its place is used for another variable. +) + +$(P +$(IX &, address of) The $(C &) (address-of) operator is useful when experimenting with memory. For example, the following program prints the addresses of two variables that are defined next to each other: +) + +--- +import std.stdio; + +void main() { + int i; + int j; + + writeln("i: ", $(HILITE &)i); + writeln("j: ", $(HILITE &)j); +} +--- + +$(P +$(I $(B Note:) The addresses would likely be different every time the program is executed. Additionally, the mere act of taking the address of a variable disables the optimization that would otherwise make the variable live on a CPU register.) +) + +$(P +As can be seen from the output, the locations of the variables are four bytes apart: +) + +$(SHELL +i: 7FFF2B633E2$(HILITE 8) +j: 7FFF2B633E2$(HILITE C) +) + +$(P +The last digits of the two addresses indicate that $(C i) lives in a memory location that is right before the location of $(C j): 8 plus 4 (size of $(C int)) makes 12 (C in hexadecimal notation). +) + +$(H5 $(IX garbage collector) $(IX GC) The garbage collector) + +$(P +The dynamic variables that are used in D programs live on memory blocks that are owned by the garbage collector (GC). When the lifetime of a variable ends (i.e. it's no longer being used), that variable is subject to being finalized according to an algorithm that is executed by the GC. If nothing else needs the memory location containing the variable, the memory may be reclaimed to be used for other variables. This algorithm is called $(I garbage collection) and an execution of the algorithm is called a $(I garbage collection cycle). +) + +$(P +The algorithm that the GC executes can roughly be described as the following. All of the memory blocks that can be reached directly or indirectly by pointers (including references) that are in the program roots are scanned. Any memory block that can be reached is tagged as being still in use and all the others are tagged as not being used anymore. The finalizers of objects and structs that live on inaccessible blocks are executed and those memory blocks are reclaimed to be used for future variables. The roots are defined as all of the program stack for every thread, all global and thread-local variables, and any additional data added via $(C GC.addRoot) or $(C GC.addRange). +) + +$(P +Some GC algorithms can move objects around to keep them together in one place in memory. To preserve program correctness, all of the pointers (and references) that point to such objects are automatically modified to point to the new locations. D's current GC does not do this. +) + +$(P +A GC is said to be "precise" if it knows exactly which memory contains pointers and which doesn't. A GC is conservative if it scans all memory as if it were pointers. D's GC is partially conservative, scanning only blocks that contain pointers, but it will scan all data in those blocks. For this reason, in some cases blocks are not ever collected, thereby "leaking" that memory. Large blocks are more likely to be targeted by "false pointers". In some cases it may be recommended to manually free large blocks you are no longer using to avoid this problem. +) + +$(P +The order of executing the finalizers is unspecified. For example, a reference member of an object may be finalized before the object that contains that member. For that reason, no class member that refers to a dynamic variable should be accessed inside the destructor. Note that this is very different from the deterministic destruction order of languages like C++. +) + +$(P +A garbage collection cycle can be started for various reasons like needing to find space for more data. Depending on the GC implementation, because allocating new objects during a garbage collection cycle can interfere with the collection process itself, all of the running threads may have to be halted during collection cycles. Sometimes this can be observed as a hesitation in the execution of the program. +) + +$(P +In most cases the programmer does not need to interfere with the garbage collection process. However, it is possible to delay or dispatch garbage collection cycles as needed by the functions defined in the $(C core.memory) module. +) + +$(H6 $(IX GC.enable) $(IX GC.disable) $(IX GC.collect) Starting and delaying garbage collection cycles) + +$(P +It may be desired to delay the execution of garbage collection cycles during a part of the program where it is important for the program to be responsive. $(C GC.disable) disables garbage collection cycles and $(C GC.enable) enables them again: +) + +--- + GC.disable(); + +// ... a part of the program where responsiveness is important ... + + GC.enable(); +--- + +$(P +However, $(C GC.disable) is not guaranteed to prevent a garbage collection cycle from executing: If the GC needs to obtain more memory from the OS, but it cannot, it still goes ahead and runs a garbage collection cycle as a last-ditch effort to gain some available memory. +) + +$(P +Instead of relying on garbage collections happening automatically at unspecified times, a garbage collection cycle can be started explicitly using $(C GC.collect()): +) + +--- +import core.memory; + +// ... + + GC.collect(); // starts a garbage collection cycle +--- + +$(P +Normally, the GC does not return memory blocks back to the operating system; it holds on to those memory pages for future needs of the program. If desired, the GC can be asked to give unused memory back to the operating system using $(C GC.minimize()): +) + +--- + GC.minimize(); +--- + +$(H5 Allocating memory) + +$(P +System languages allow programmers to specify the memory areas where objects should live. Such memory areas are commonly called $(I buffers). +) + +$(P +There are several methods of allocating memory. The simplest method would be using a fixed-length array: +) + +--- + ubyte[100] buffer; // A memory area of 100 bytes +--- + +$(P +$(IX uninitialized array) $(IX array, uninitialized) $(IX = void) $(C buffer) is ready to be used as a 100-byte memory area. Instead of $(C ubyte), it is also possible to define such buffers as arrays of $(C void), without any association to any type. Since $(C void) cannot be assigned any value, it cannot have the $(C .init) value either. Such arrays must be initialized by the special syntax $(C =void): +) + +--- + void[100] buffer = void; // A memory area of 100 bytes +--- + +$(P +$(IX GC.calloc) We will use only $(C GC.calloc) from the $(C core.memory) module to reserve memory in this chapter. That module has many other features that are useful in various situations. Additionally, the memory allocation functions of the C standard library are avaliable in the $(C core.stdc.stdlib) module. +) + +$(P +$(C GC.calloc) allocates a memory area of the specified size pre-filled with all 0 values, and returns the beginning address of the allocated area: +) + +--- +import core.memory; +// ... + void * buffer = GC.calloc(100); + // A memory area of 100 zero bytes +--- + +$(P +$(IX void*) Normally, the returned $(C void*) value is cast to a pointer of the proper type: +) + +--- + int * intBuffer = cast(int*)buffer; +--- + +$(P +However, that intermediate step is usually skipped and the return value is cast directly: +) + +--- + int * intBuffer = $(HILITE cast(int*))GC.calloc(100); +--- + +$(P +Instead of arbitrary values like 100, the size of the memory area is usually calculated by multiplying the number of elements needed with the size of each element: +) + +--- + // Allocate room for 25 ints + int * intBuffer = cast(int*)GC.calloc($(HILITE int.sizeof * 25)); +--- + +$(P +$(IX classInstanceSize) $(IX .sizeof, class) There is an important difference for classes: The size of a class variable and the size of a class object are not the same. $(C .sizeof) is the size of a class variable and is always the same value: 8 on 64-bit systems and 4 on 32-bit systems. The size of a class object must be obtained by $(C __traits(classInstanceSize)): +) + +--- + // Allocate room for 10 MyClass objects + MyClass * buffer = + cast(MyClass*)GC.calloc( + $(HILITE __traits(classInstanceSize, MyClass)) * 10); +--- + +$(P +$(IX OutOfMemoryError) When there is not enough memory in the system for the requested size, then a $(C core.exception.OutOfMemoryError) exception is thrown: +) + +--- + void * buffer = GC.calloc(10_000_000_000); +--- + +$(P +The output on a system that does not have that much free space: +) + +$(SHELL +core.exception.OutOfMemoryError +) + +$(P +$(IX GC.free) The memory areas that are allocated from the GC can be returned back to it using $(C GC.free): +) + +--- + GC.free(buffer); +--- + +$(P +However, calling $(C free()) does not necessarily execute the destructors of the variables that live on that memory block. The destructors may be executed explicitly by calling $(C destroy()) for each variable. Note that various internal mechanisms are used to call finalizers on $(C class) and $(C struct) variables during GC collection or freeing. The best way to ensure these are called is to use the $(C new) operator when allocating variables. In that case, $(C GC.free) will call the destructors. +) + +$(P +$(IX GC.realloc) Sometimes the program may determine that a previously allocated memory area is all used up and does not have room for more data. It is possible to $(I extend) a previously allocated memory area by $(C GC.realloc). $(C realloc()) takes the previously allocated memory pointer and the newly requested size, and returns a new area: +) + +--- + void * oldBuffer = GC.calloc(100); +// ... + void * newBuffer = GC.realloc(oldBuffer, 200); +--- + +$(P +$(C realloc()) tries to be efficient by not actually allocating new memory unless it is really necessary: +) + +$(UL + +$(LI If the memory area following the old area is not in use for any other purpose and is large enough to satisfy the new request, $(C realloc()) adds that part of the memory to the old area, extending the buffer $(I in-place).) + +$(LI If the memory area following the old area is already in use or is not large enough, then $(C realloc()) allocates a new larger memory area and copies the contents of the old area to the new one.) + +$(LI It is possible to pass $(C null) as $(C oldBuffer), in which case $(C realloc()) simply allocates new memory.) + +$(LI It is possible to pass a size less than the previous one, in which case the remaining part of the old memory is returned back to the GC.) + +$(LI It is possible to pass 0 as the new size, in which case $(C realloc()) simply frees the memory.) + +) + +$(P +$(C GC.realloc) is adapted from the C standard library function $(C realloc()). For having such a complicated behavior, $(C realloc()) is considered to have a badly designed function interface. A potentially surprising aspect of $(C GC.realloc) is that even if the original memory has been allocated with $(C GC.calloc), the extended part is never cleared. For that reason, when it is important that the memory is zero-initialized, a function like $(C reallocCleared()) below would be useful. We will see the meaning of $(C blockAttributes) later below: +) + +--- +$(CODE_NAME reallocCleared)import core.memory; + +/* Works like GC.realloc but clears the extra bytes if memory + * is extended. */ +void * reallocCleared( + void * buffer, + size_t oldLength, + size_t newLength, + GC.BlkAttr blockAttributes = GC.BlkAttr.NONE, + const TypeInfo typeInfo = null) { + /* Dispatch the actual work to GC.realloc. */ + buffer = GC.realloc(buffer, newLength, + blockAttributes, typeInfo); + + /* Clear the extra bytes if extended. */ + if (newLength > oldLength) { + import core.stdc.string; + + auto extendedPart = buffer + oldLength; + const extendedLength = newLength - oldLength; + + memset(extendedPart, 0, extendedLength); + } + + return buffer; +} +--- + +$(P +$(IX memset, core.stdc.string) The function above uses $(C memset()) from the $(C core.stdc.string) module to clear the newly extended bytes. $(C memset()) assigns the specified value to the bytes of a memory area specified by a pointer and a length. In the example, it assigns $(C 0) to $(C extendedLength) number of bytes at $(C extendedPart). +) + +$(P +We will use $(C reallocCleared()) in an example below. +) + +$(P +$(IX GC.extend) The behavior of the similar function $(C GC.extend) is not complicated like $(C realloc()); it applies only the first item above: If the memory area cannot be extended in-place, $(C extend()) does not do anything and returns 0. +) + +$(H6 $(IX memory block attribute) $(IX BlkAttr) Memory block attributes) + +$(P +The concepts and the steps of a GC algorithm can be configured to some degree for each memory block by $(C enum BlkAttr). $(C BlkAttr) is an optional parameter of $(C GC.calloc) and other allocation functions. It consists of the following values: +) + +$(UL + +$(LI $(C NONE): The value zero; specifies $(I no attribute).) + +$(LI $(C FINALIZE): Specifies that the objects that live in the memory block should be finalized. + +$(P +Normally, the GC assumes that the lifetimes of objects that live on explicitly-allocated memory locations are under the control of the programmer; it does not finalize objects on such memory areas. $(C GC.BlkAttr.FINALIZE) is for requesting the GC to execute the destructors of objects: +) + +--- + Class * buffer = + cast(Class*)GC.calloc( + __traits(classInstanceSize, Class) * 10, + GC.BlkAttr.FINALIZE); +--- + +$(P +Note that $(C FINALIZE) depends on implementation details properly set up on the block. It is highly recommended to let the GC take care of setting up these details using the $(C new) operator. +) + +) + +$(LI $(C NO_SCAN): Specifies that the memory area should not be scanned by the GC. + +$(P +The byte values in a memory area may accidentally look like pointers to unrelated objects in other parts of the memory. When that happens, the GC would assume that those objects are still in use even after their actual lifetimes have ended. +) + +$(P +A memory block that is known to not contain any object pointers should be marked as $(C GC.BlkAttr.NO_SCAN): +) + +--- + int * intBuffer = + cast(int*)GC.calloc(100, GC.BlkAttr.NO_SCAN); +--- + +$(P +The $(C int) variables placed in that memory block can have any value without concern of being mistaken for object pointers. +) + +) + +$(LI $(C NO_MOVE): Specifies that objects in the memory block should not be moved to other places.) + +$(LI $(C APPENDABLE): This is an internal flag used by the D runtime to aid in fast appending. You should not use this flag when allocating memory.) + +$(LI $(C NO_INTERIOR): Specifies that only pointers to the block's first address exist. This allows one to cut down on "false pointers" because a pointer to the middle of the block does not count when tracing where a pointer goes.) + +) + +$(P +$(IX |) The values of $(C enum BlkAttr) are suitable to be used as bit flags that we saw in $(LINK2 bit_operations.html, the Bit Operations chapter). The following is how two attributes can be merged by the $(C |) operator: +) + +--- + const attributes = + GC.BlkAttr.NO_SCAN $(HILITE |) GC.BlkAttr.NO_INTERIOR; +--- + +$(P +Naturally, the GC would be aware only of memory blocks that are reserved by its own functions and scans only those memory blocks. For example, it would not know about a memory block allocated by $(C core.stdc.stdlib.calloc). +) + +$(P +$(IX GC.addRange) $(IX GC.removeRange) $(IX GC.addRoot) $(C GC.addRange) is for introducing unrelated memory blocks to the GC. The complement function $(C GC.removeRange) should be called before freeing a memory block by other means e.g. by $(C core.stdc.stdlib.free). +) + +$(P +In some cases, there may be no reference in the program to a memory block even if that memory block has been reserved by the GC. For example, if the only reference to a memory block lives inside a C library, the GC would normally not know about that reference and assume that the memory block is not in use anymore. +) + +$(P +$(C GC.addRoot) introduces a memory block to the GC as a $(I root), to be scanned during collection cycles. All of the variables that can be reached directly or indirectly through that memory block would be marked as alive. The complement function $(C GC.removeRoot) should be called when a memory block is not in use anymore. +) + +$(H6 Example of extending a memory area) + +$(P +Let's design a simple $(C struct) template that works like an array. To keep the example short, let's provide only the functionality of adding and accessing elements. Similar to arrays, let's increase the capacity as needed. The following program uses $(C reallocCleared()), which has been defined above: +) + +--- +$(CODE_NAME Array)$(CODE_XREF reallocCleared)struct Array(T) { + T * buffer; // Memory area that holds the elements + size_t capacity; // The element capacity of the buffer + size_t length; // The number of actual elements + + /* Returns the specified element */ + T element(size_t index) { + import std.string; + enforce(index < length, + format("Invalid index %s", index)); + + return *(buffer + index); + } + + /* Appends the element to the end */ + void append(T element) { + writefln("Appending element %s", length); + + if (length == capacity) { + /* There is no room for the new element; must + * increase capacity. */ + size_t newCapacity = capacity + (capacity / 2) + 1; + increaseCapacity(newCapacity); + } + + /* Place the element at the end */ + *(buffer + length) = element; + ++length; + } + + void increaseCapacity(size_t newCapacity) { + writefln("Increasing capacity from %s to %s", + capacity, newCapacity); + + size_t oldBufferSize = capacity * T.sizeof; + size_t newBufferSize = newCapacity * T.sizeof; + + /* Also specify that this memory block should not be + * scanned for pointers. */ + buffer = cast(T*)$(HILITE reallocCleared)( + buffer, oldBufferSize, newBufferSize, + GC.BlkAttr.NO_SCAN); + + capacity = newCapacity; + } +} +--- + +$(P +The capacity of the array grows by about 50%. For example, after the capacity for 100 elements is consumed, the new capacity would become 151. ($(I The extra 1 is for the case of 0 length, where adding 50% would not grow the array.)) +) + +$(P +The following program uses that template with the $(C double) type: +) + +--- +$(CODE_XREF Array)import std.stdio; +import core.memory; +import std.exception; + +// ... + +void main() { + auto array = Array!double(); + + const count = 10; + + foreach (i; 0 .. count) { + double elementValue = i * 1.1; + array.append(elementValue); + } + + writeln("The elements:"); + + foreach (i; 0 .. count) { + write(array.element(i), ' '); + } + + writeln(); +} +--- + +$(P +The output: +) + +$(SHELL +Adding element with index 0 +Increasing capacity from 0 to 1 +Adding element with index 1 +Increasing capacity from 1 to 2 +Adding element with index 2 +Increasing capacity from 2 to 4 +Adding element with index 3 +Adding element with index 4 +Increasing capacity from 4 to 7 +Adding element with index 5 +Adding element with index 6 +Adding element with index 7 +Increasing capacity from 7 to 11 +Adding element with index 8 +Adding element with index 9 +The elements: +0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 +) + +$(H5 $(IX alignment) Alignment) + +$(P +By default, every object is placed at memory locations that are multiples of an amount specific to the type of that object. That amount is called the $(I alignment) of that type. For example, the alignment of $(C int) is 4 because $(C int) variables are placed at memory locations that are multiples of 4 (4, 8, 12, etc.). +) + +$(P +Alignment is needed for CPU performance or requirements, because accessing misaligned memory addresses can be slower or cause a bus error. In addition, certain types of variables only work properly at aligned addresses. +) + +$(H6 $(IX .alignof) The $(C .alignof) property) + +$(P +$(IX classInstanceAlignment) The $(C .alignof) property of a type is its default alignment value. For classes, $(C .alignof) is the alignment of the class variable, not the class object. The alignment of a class object is obtained by $(C __traits(classInstanceAlignment)). +) + +$(P +The following program prints the alignments of various types: +) + +--- +import std.stdio; +import std.meta; +import std.traits; + +struct EmptyStruct { +} + +struct Struct { + char c; + double d; +} + +class EmptyClass { +} + +class Class { + char c; +} + +void main() { + alias Types = AliasSeq!(char, short, int, long, + double, real, + string, int[int], int*, + EmptyStruct, Struct, + EmptyClass, Class); + + writeln(" Size Alignment Type\n", + "========================="); + + foreach (Type; Types) { + static if (is (Type == class)) { + size_t size = __traits(classInstanceSize, Type); + size_t alignment = $(HILITE __traits(classInstanceAlignment, Type)); + + } else { + size_t size = Type.sizeof; + size_t alignment = $(HILITE Type.alignof); + } + + writefln("%4s%8s %s", + size, alignment, Type.stringof); + } +} +--- + +$(P +The output of the program may be different in different environments. The following is a sample output: +) + +$(SHELL + Size Alignment Type +========================= + 1 1 char + 2 2 short + 4 4 int + 8 8 long + 8 8 double + 16 16 real + 16 8 string + 8 8 int[int] + 8 8 int* + 1 1 EmptyStruct + 16 8 Struct + 16 8 EmptyClass + 17 8 Class +) + +$(P +We will see later below how variables can be constructed (emplaced) at specific memory locations. For correctness and efficiency, objects must be constructed at addresses that match their alignments. +) + +$(P +Let's consider two $(I consecutive) objects of $(C Class) type above, which are 17 bytes each. Although 0 is not a legal address for a variable on most platforms, to simplify the example let's assume that the first object is at address 0. The 17 bytes of this object would be at adresses from 0 to 16: +) + +$(MONO + $(HILITE 0) 1 16 + ┌────┬────┬─ ... ─┬────┬─ ... + │$(HILITE <────first object────>)│ + └────┴────┴─ ... ─┴────┴─ ... +) + +$(P +$(IX padding) Although the next available address is 17, that location cannot be used for a $(C Class) object because 17 is not a multiple of the alignment value 8 of that type. The nearest possible address for the second object is 24 because 24 is the next smallest multiple of 8. When the second object is placed at that address, there would be unused bytes between the two objects. Those bytes are called $(I padding bytes): +) + +$(P +) + +$(MONO + $(HILITE 0) 1 16 17 23 $(HILITE 24) 25 30 + ┌────┬────┬─ ... ─┬────┬────┬─ ... ─┬────┬────┬────┬─ ... ─┬────┬─ ... + │$(HILITE <────first object────>)│<────$(I padding)────>│$(HILITE <───second object────>)│ + └────┴────┴─ ... ─┴────┴────┴─ ... ─┴────┴────┴────┴─ ... ─┴────┴─ ... +) + +$(P +The following formula can determine the nearest address value that an object can be placed at: +) + +--- + (candidateAddress + alignmentValue - 1) + / alignmentValue + * alignmentValue +--- + +$(P +For that formula to work, the fractional part of the result of the division must be truncated. Since truncation is automatic for integral types, all of the variables above are assumed to be integral types. +) + +$(P +We will use the following function in the examples later below: +) + +--- +$(CODE_NAME nextAlignedAddress)T * nextAlignedAddress(T)(T * candidateAddr) { + import std.traits; + + static if (is (T == class)) { + const alignment = __traits(classInstanceAlignment, T); + } else { + const alignment = T.alignof; + } + + const result = (cast(size_t)candidateAddr + alignment - 1) + / alignment * alignment; + return cast(T*)result; +} +--- + +$(P +That function template deduces the type of the object from its template parameter. Since that is not possible when the type is $(C void*), the type must be provided as an explicit template argument for the $(C void*) overload. That overload can trivially forward the call to the function template above: +) + +--- +$(CODE_NAME nextAlignedAddress_void)void * nextAlignedAddress(T)(void * candidateAddr) { + return nextAlignedAddress(cast(T*)candidateAddr); +} +--- + +$(P +The function template above will be useful below when constructing $(I class) objects by $(C emplace()). +) + +$(P +Let's define one more function template to calculate the total size of an object including the padding bytes that must be placed between two objects of that type: +) + +--- +$(CODE_NAME sizeWithPadding)size_t sizeWithPadding(T)() { + static if (is (T == class)) { + const candidateAddr = __traits(classInstanceSize, T); + + } else { + const candidateAddr = T.sizeof; + } + + return cast(size_t)nextAlignedAddress(cast(T*)candidateAddr); +} +--- + +$(H6 $(IX .offsetof) The $(C .offsetof) property) + +$(P +Alignment is observed for members of user-defined types as well. There may be padding bytes $(I between) members so that the members are aligned according to their respective types. For that reason, the size of the following $(C struct) is not 6 bytes as one might expect, but 12: +) + +--- +struct A { + byte b; // 1 byte + int i; // 4 bytes + ubyte u; // 1 byte +} + +static assert($(HILITE A.sizeof == 12)); // More than 1 + 4 + 1 +--- + +$(P +This is due to padding bytes before the $(C int) member so that it is aligned at an address that is a multiple of 4, as well as padding bytes at the end for the alignment of the entire $(C struct) object itself. +) + +$(P +The $(C .offsetof) property gives the number of bytes a member variable is from the beginning of the object that it is a part of. The following function prints the layout of a type by determining the padding bytes by $(C .offsetof): +) + +--- +$(CODE_NAME printObjectLayout)void printObjectLayout(T)() + if (is (T == struct) || is (T == union)) { + import std.stdio; + import std.string; + + writefln("=== Memory layout of '%s'" ~ + " (.sizeof: %s, .alignof: %s) ===", + T.stringof, T.sizeof, T.alignof); + + /* Prints a single line of layout information. */ + void printLine(size_t offset, string info) { + writefln("%4s: %s", offset, info); + } + + /* Prints padding information if padding is actually + * observed. */ + void maybePrintPaddingInfo(size_t expectedOffset, + size_t actualOffset) { + if (expectedOffset < actualOffset) { + /* There is some padding because the actual offset + * is beyond the expected one. */ + + const paddingSize = actualOffset - expectedOffset; + + printLine(expectedOffset, + format("... %s-byte PADDING", + paddingSize)); + } + } + + /* This is the expected offset of the next member if there + * were no padding bytes before that member. */ + size_t noPaddingOffset = 0; + + /* Note: __traits(allMembers) is a 'string' collection of + * names of the members of a type. */ + foreach (memberName; __traits(allMembers, T)) { + mixin (format("alias member = %s.%s;", + T.stringof, memberName)); + + const offset = member$(HILITE .offsetof); + maybePrintPaddingInfo(noPaddingOffset, offset); + + const typeName = typeof(member).stringof; + printLine(offset, + format("%s %s", typeName, memberName)); + + noPaddingOffset = offset + member.sizeof; + } + + maybePrintPaddingInfo(noPaddingOffset, T.sizeof); +} +--- + +$(P +The following program prints the layout of the 12-byte $(C struct A) that was defined above: +) + +--- +$(CODE_XREF printObjectLayout)struct A { + byte b; + int i; + ubyte u; +} + +void main() { + printObjectLayout!A(); +} +--- + +$(P +The output of the program showns where the total of 6 padding bytes are located inside the object. The first column of the output is the offset from the beginning of the object: +) + +$(SHELL +=== Memory layout of 'A' (.sizeof: $(HILITE 12), .alignof: 4) === + 0: byte b + 1: ... 3-byte PADDING + 4: int i + 8: ubyte u + 9: ... 3-byte PADDING +) + +$(P +One technique of minimizing padding is ordering the members by their sizes from the largest to the smallest. For example, when the $(C int) member is moved to the beginning of the previous $(C struct) then the size of the object would be less: +) + +--- +$(CODE_XREF printObjectLayout)struct B { + $(HILITE int i;) // Moved up inside the struct definition + byte b; + ubyte u; +} + +void main() { + printObjectLayout!B(); +} +--- + +$(P +This time, the size of the object is down to 8 due to just 2 bytes of padding at the end: +) + +$(SHELL +=== Memory layout of 'B' (.sizeof: $(HILITE 8), .alignof: 4) === + 0: int i + 4: byte b + 5: ubyte u + 6: ... 2-byte PADDING +) + +$(H6 $(IX align) The $(C align) attribute) + +$(P +The $(C align) attribute is for specifying alignments of variables, user-defined types, and members of user-defined types. The value provided in parentheses specifies the alignment value. Every definition can be specified separately. For example, the following definition would align $(C S) objects at 2-byte boundaries and its $(C i) member at 1-byte boundaries (1-byte alignment always results in no padding at all): +) + +--- +$(CODE_XREF printObjectLayout)$(HILITE align (2)) // The alignment of 'S' objects +struct S { + byte b; + $(HILITE align (1)) int i; // The alignment of member 'i' + ubyte u; +} + +void main() { + printObjectLayout!S(); +} +--- + +$(P +When the $(C int) member is aligned at a 1-byte boundary, there is no padding before it and this time the size of the object ends up being exactly 6: +) + +$(SHELL +=== Memory layout of 'S' (.sizeof: $(HILITE 6), .alignof: 4) === + 0: byte b + 1: int i + 5: ubyte u +) + +$(P +Although $(C align) can reduce sizes of user-defined types, there can be $(I significant performance penalties) when default alignments of types are not observed (and on some CPUs, using misaligned data can actually crash the program). +) + +$(P +$(C align) can specify the alignment of variables as well: +) + +--- + $(HILITE align (32)) double d; // The alignment of a variable +--- + +$(P +However, objects that are allocated by $(C new) must always be aligned at multiples of the size of the $(C size_t) type because that is what the GC assumes. Doing otherwise is undefined behavior. For example, if $(C size_t) is 8 bytes long, than the alignments of variables allocated by $(C new) must be a multiple of 8. +) + +$(H5 $(IX construction, emplace) $(IX emplace) Constructing variables at specific memory locations) + +$(P +$(IX new) The $(C new) expression achieves three tasks: +) + +$(OL + +$(LI Allocates memory large enough for the object. The newly allocated memory area is considered to be $(I raw), not associated with any type or any object. +) + +$(LI Copies the $(C .init) value of that type on that memory area and executes the constructor of the object on that area. Only after this step the object becomes $(I placed) on that memory area. +) + +$(LI Configures the memory block so it has all the necessary flags and infrastructure to properly destroy the object when freed. +) + +) + +$(P +We have already seen that the first of these tasks can explicitly be achieved by memory allocation functions like $(C GC.calloc). Being a system language, D allows the programmer manage the second step as well. +) + +$(P +Variables can be constructed at specific locations with $(C std.conv.emplace). +) + +$(H6 $(IX emplace, struct) Constructing a struct object at a specific location) + +$(P +$(C emplace()) takes the address of a memory location as its first parameter and constructs an object at that location. If provided, it uses the remaining parameters as the object's constructor arguments: +) + +--- +import std.conv; +// ... + emplace($(I address), /* ... constructor arguments ... */); +--- + +$(P +It is not necessary to specify the type of the object explicitly when constructing a $(C struct) object because $(C emplace()) deduces the type of the object from the type of the pointer. For example, since the type of the following pointer is $(C Student*), $(C emplace()) constructs a $(C Student) object at that address: +) + +--- + Student * objectAddr = nextAlignedAddress(candidateAddr); +// ... + emplace(objectAddr, name, id); +--- + +$(P +The following program allocates a memory area large enough for three objects and constructs them one by one at aligned addresses inside that memory area: +) + +--- +$(CODE_XREF sizeWithPadding)$(CODE_XREF nextAlignedAddress)import std.stdio; +import std.string; +import core.memory; +import std.conv; + +// ... + +struct Student { + string name; + int id; + + string toString() { + return format("%s(%s)", name, id); + } +} + +void main() { + /* Some information about this type. */ + writefln("Student.sizeof: %#x (%s) bytes", + Student.sizeof, Student.sizeof); + writefln("Student.alignof: %#x (%s) bytes", + Student.alignof, Student.alignof); + + string[] names = [ "Amy", "Tim", "Joe" ]; + const totalSize = sizeWithPadding!Student() * names.length; + + /* Reserve room for all Student objects. + * + * Warning! The objects that are accessible through this + * slice are not constructed yet; they should not be + * accessed until after they are properly constructed. */ + Student[] students = + (cast(Student*)GC.calloc(totalSize))[0 .. names.length]; + + foreach (i, name; names) { + Student * candidateAddr = students.ptr + i; + Student * objectAddr = + nextAlignedAddress(candidateAddr); + writefln("address of object %s: %s", i, objectAddr); + + const id = 100 + i.to!int; + $(HILITE emplace)(objectAddr, name, id); + } + + /* All of the objects are constructed and can be used. */ + writeln(students); +} +--- + +$(P +The output of the program: +) + +$(SHELL +Student.sizeof: 0x18 (24) bytes +Student.alignof: 0x8 (8) bytes +address of object 0: 7F1532861F00 +address of object 1: 7F1532861F18 +address of object 2: 7F1532861F30 +[Amy(100), Tim(101), Joe(102)] +) + +$(H6 $(IX emplace, class) Constructing a class object at a specific location) + +$(P +Class variables need not be of the exact type of class objects. For example, a class variable of type $(C Animal) can refer to a $(C Cat) object. For that reason, $(C emplace()) does not determine the type of the object from the type of the memory pointer. Instead, the actual type of the object must be explicitly specified as a template argument of $(C emplace()). ($(I $(B Note:) Additionally, a class pointer is a pointer to a class variable, not to a class object. For that reason, specifying the actual type allows the programmer to specify whether to emplace a class object or a class variable.)) +) + +$(P +$(IX void[]) The memory location for a class object must be specified as a $(C void[]) slice with the following syntax: +) + +--- + Type variable = + emplace!$(I Type)($(I voidSlice), + /* ... constructor arguments ... */); +--- + +$(P +$(C emplace()) constructs a class $(I object) at the location specified by the slice and returns a class $(I variable) for that object. +) + +$(P +Let's use $(C emplace()) on objects of an $(C Animal) hierarchy. The objects of this hierarchy will be placed $(I side-by-side) on a piece of memory that is allocated by $(C GC.calloc). To make the example more interesting, we will ensure that the subclasses have different sizes. This will be useful to demonstrate how the address of a subsequent object can be determined depending on the size of the previous one. +) + +--- +$(CODE_NAME Animal)interface Animal { + string sing(); +} + +class Cat : Animal { + string sing() { + return "meow"; + } +} + +class Parrot : Animal { + string[] lyrics; + + this(string[] lyrics) { + this.lyrics = lyrics; + } + + string sing() { + /* std.algorithm.joiner joins elements of a range with + * the specified separator. */ + return lyrics.joiner(", ").to!string; + } +} +--- + +$(P +The buffer that holds the objects will be allocated with $(C GC.calloc): +) + +--- + const capacity = 10_000; + void * buffer = GC.calloc(capacity); +--- + +$(P +Normally, it must be ensured that there is always available capacity for objects. We will ignore that check here to keep the example simple and assume that the objects in the example will fit in ten thousand bytes. +) + +$(P +The buffer will be used for constructing a $(C Cat) and a $(C Parrot) object: +) + +--- + Cat cat = emplace!Cat(catPlace); +// ... + Parrot parrot = + emplace!Parrot(parrotPlace, [ "squawk", "arrgh" ]); +--- + +$(P +Note that the constructor argument of $(C Parrot) is specified after the address of the object. +) + +$(P +The variables that $(C emplace()) returns will be stored in an $(C Animal) slice later to be used in a $(C foreach) loop: +) + +--- + Animal[] animals; +// ... + animals ~= cat; +// ... + animals ~= parrot; + + foreach (animal; animals) { + writeln(animal.sing()); + } +--- + +$(P +More explanations are inside the code comments: +) + +--- +$(CODE_XREF Animal)$(CODE_XREF nextAlignedAddress)$(CODE_XREF nextAlignedAddress_void)import std.stdio; +import std.algorithm; +import std.conv; +import core.memory; + +// ... + +void main() { + /* A slice of Animal variables (not Animal objects). */ + Animal[] animals; + + /* Allocating a buffer with an arbitrary capacity and + * assuming that the two objects in this example will fit + * in that area. Normally, this condition must be + * validated. */ + const capacity = 10_000; + void * buffer = GC.calloc(capacity); + + /* Let's first place a Cat object. */ + void * catCandidateAddr = buffer; + void * catAddr = nextAlignedAddress!Cat(catCandidateAddr); + writeln("Cat address : ", catAddr); + + /* Since emplace() requires a void[] for a class object, + * we must first produce a slice from the pointer. */ + size_t catSize = __traits(classInstanceSize, Cat); + void[] catPlace = catAddr[0..catSize]; + + /* Construct a Cat object inside that memory slice and + * store the returned class variable for later use. */ + Cat cat = $(HILITE emplace!Cat)(catPlace); + animals ~= cat; + + /* Now construct a Parrot object at the next available + * address that satisfies the alignment requirement. */ + void * parrotCandidateAddr = catAddr + catSize; + void * parrotAddr = + nextAlignedAddress!Parrot(parrotCandidateAddr); + writeln("Parrot address: ", parrotAddr); + + size_t parrotSize = __traits(classInstanceSize, Parrot); + void[] parrotPlace = parrotAddr[0..parrotSize]; + + Parrot parrot = + $(HILITE emplace!Parrot)(parrotPlace, [ "squawk", "arrgh" ]); + animals ~= parrot; + + /* Use the objects. */ + foreach (animal; animals) { + writeln(animal.sing()); + } +} +--- + +$(P +The output: +) + +$(SHELL +Cat address : 7F0E343A2000 +Parrot address: 7F0E343A2018 +meow +squawk, arrgh +) + +$(P +Instead of repeating the steps inside $(C main()) for each object, a function template like $(C newObject(T)) would be more useful. +) + +$(H5 Destroying objects explicitly) + +$(P +The reverse operations of the $(C new) operator are destroying an object and returning the object's memory back to the GC. Normally, these operations are executed automatically at unspecified times. +) + +$(P +However, sometimes it is necessary to execute destructors at specific points in the program. For example, an object may be closing a $(C File) member in its destructor and the destructor may have to be executed immediately when the lifetime of the object ends. +) + +$(P +$(IX destroy) $(C destroy()) calls the destructor of an object: +) + +--- + destroy(variable); +--- + +$(P +$(IX .init) After executing the destructor, $(C destroy()) sets the variable to its $(C .init) state. Note that the $(C .init) state of a class variable is $(C null); so, a class variable cannot be used once destroyed. $(C destroy()) merely executes the destructor. It is still up to the GC when to reuse the piece of memory that used to be occupied by the destroyed object. +) + +$(P +$(B Warning:) When used with a $(I struct) pointer, $(C destroy()) must receive the pointee, not the pointer. Otherwise, the pointer would be set to $(C null) but the object would not be destroyed: +) + +--- +import std.stdio; + +struct S { + int i; + + this(int i) { + this.i = i; + writefln("Constructing object with value %s", i); + } + + ~this() { + writefln("Destroying object with value %s", i); + } +} + +void main() { + auto p = new S(42); + + writeln("Before destroy()"); + destroy($(HILITE p)); // ← WRONG USAGE + writeln("After destroy()"); + + writefln("p: %s", p); + + writeln("Leaving main"); +} +--- + +$(P +When $(C destroy()) receives a pointer, it is the pointer that gets destroyed (i.e. the pointer becomes $(C null)): +) + +$(SHELL +Constructing object with value 42 +Before destroy() +After destroy() $(SHELL_NOTE_WRONG The object is not destroyed before this line) +p: null $(SHELL_NOTE_WRONG Instead, the pointer becomes null) +Leaving main +Destroying object with value 42 +) + +$(P +For that reason, when used with a struct pointer, $(C destroy()) must receive the pointee: +) + +--- + destroy($(HILITE *p)); // ← Correct usage +--- + +$(P +This time the destructor is executed at the right spot and the pointer is not set to $(C null): +) + +$(SHELL +Constructing object with value 42 +Before destroy() +Destroying object with value 42 $(SHELL_NOTE Destroyed at the right spot) +After destroy() +p: 7FB64FE3F200 $(SHELL_NOTE The pointer is not null) +Leaving main +Destroying object with value 0 $(SHELL_NOTE Once more for S.init) +) + +$(P +The last line is due to executing the destructor one more time for the same object, which now has the value $(C S.init). +) + +$(H5 $(IX construction, by name) Constructing objects at run time by name) + +$(P +$(IX factory) $(IX Object) The $(C factory()) member function of $(C Object) takes the fully qualified name of a class type as parameter, constructs an object of that type, and returns a class variable for that object: +) + +--- +$(HILITE module test_module); + +import std.stdio; + +interface Animal { + string sing(); +} + +class Cat : Animal { + string sing() { + return "meow"; + } +} + +class Dog : Animal { + string sing() { + return "woof"; + } +} + +void main() { + string[] toConstruct = [ "Cat", "Dog", "Cat" ]; + + Animal[] animals; + + foreach (typeName; toConstruct) { + /* The pseudo variable __MODULE__ is always the name + * of the current module, which can be used as a + * string literal at compile time. */ + const fullName = __MODULE__ ~ '.' ~ typeName; + writefln("Constructing %s", fullName); + animals ~= cast(Animal)$(HILITE Object.factory)(fullName); + } + + foreach (animal; animals) { + writeln(animal.sing()); + } +} +--- + +$(P +Although there is no explicit $(C new) expression in that program, three class objects are created and added to the $(C animals) slice: +) + +$(SHELL +Constructing test_module.Cat +Constructing test_module.Dog +Constructing test_module.Cat +meow +woof +meow +) + +$(P +Note that $(C Object.factory()) takes the fully qualified name of the type of the object. Also, the return type of $(C factory()) is $(C Object); so, it must be cast to the actual type of the object before being used in the program. +) + +$(H5 Summary) + +$(UL +$(LI The garbage collector scans the memory at unspecified times, determines the objects that cannot possibly be reached anymore by the program, destroys them, and reclaims their memory locations.) + +$(LI The operations of the GC may be controlled by the programmer to some extent by $(C GC.collect), $(C GC.disable), $(C GC.enable), $(C GC.minimize), etc.) + +$(LI $(C GC.calloc) and other functions reserve memory, $(C GC.realloc) extends a previously allocated memory area, and $(C GC.free) returns it back to the GC.) + +$(LI It is possible to mark the allocated memory by attributes like $(C GC.BlkAttr.NO_SCAN), $(C GC.BlkAttr.NO_INTERIOR), etc.) + +$(LI The $(C .alignof) property is the default memory alignment of a type. Alignment must be obtained by $(C __traits(classInstanceAlignment)) for class $(I objects).) + +$(LI The $(C .offsetof) property is the number of bytes a member is from the beginning of the object that it is a part of.) + +$(LI The $(C align) attribute specifies the alignment of a variable, a user-defined type, or a member.) + +$(LI $(C emplace()) takes a pointer when constructing a $(C struct) object, a $(C void[]) slice when constructing a $(C class) object.) + +$(LI $(C destroy()) executes the destructor of objects. (One must destroy the struct pointee, not the struct pointer.)) + +$(LI $(C Object.factory()) constructs objects with their fully qualified type names.) + +) + +macros: + TITLE=Memory Management + + DESCRIPTION=The memory, the garbage collector, and managing memory explicitly. + + KEYWORDS=d programming language tutorial book integer gc memory diff --git a/book/d.en/mixin.d b/book/d.en/mixin.d new file mode 100644 index 0000000000..751fd2062f --- /dev/null +++ b/book/d.en/mixin.d @@ -0,0 +1,688 @@ +Ddoc + +$(DERS_BOLUMU $(IX mixin) Mixins) + +$(P +Mixins are for $(I mixing in) generated code into the source code. The mixed-in code may be generated as a template instance or a $(C string). +) + +$(P +Code can be inserted into the program as a $(I string import) as well. +) + +$(H5 $(IX template mixin) Template mixins) + +$(P +We have seen in the $(LINK2 templates.html, Templates) and $(LINK2 templates_more.html, More Templates) chapters that templates define code as a pattern, for the compiler to generate actual instances from that pattern. Templates can generate functions, structs, unions, classes, interfaces, and any other legal D code. +) + +$(P +Template mixins insert instantiations of templates into the code by the $(C mixin) keyword: +) + +--- + mixin $(I a_template)!($(I template_parameters)) +--- + +$(P +As we will see in the example below, the $(C mixin) keyword is used in the definitions of template mixins as well. +) + +$(P +The instantiation of the template for the specific set of template parameters is inserted into the source code right where the $(C mixin) keyword appears. +) + +$(P +For example, let's have a template that defines both an array of edges and a pair of functions that operate on those edges: +) + +--- +$(CODE_NAME EdgeArrayFeature)$(HILITE mixin) template EdgeArrayFeature(T, size_t count) { + T[count] edges; + + void setEdge(size_t index, T edge) { + edges[index] = edge; + } + + void printEdges() { + writeln("The edges:"); + + foreach (i, edge; edges) { + writef("%s:%s ", i, edge); + } + + writeln(); + } +} +--- + +$(P +That template leaves the type and number of array elements flexible. The instantiation of that template for $(C int) and $(C 2) would be mixed in by the following syntax: +) + +--- + $(HILITE mixin) EdgeArrayFeature!(int, 2); +--- + +$(P +For example, the $(C mixin) above can insert the two-element $(C int) array and the two functions that are generated by the template right inside a $(C struct) definition: +) + +--- +$(CODE_NAME Line)$(CODE_XREF EdgeArrayFeature)struct Line { + mixin EdgeArrayFeature!(int, 2); +} +--- + +$(P +As a result, $(C Line) ends up defining a member array and two member functions: +) + +--- +$(CODE_XREF Line)import std.stdio; + +void main() { + auto line = Line(); + line.setEdge(0, 100); + line.setEdge(1, 200); + line.printEdges(); +} +--- + +$(P +The output: +) + +$(SHELL +The edges: +0:100 1:200 +) + +$(P +Another instantiation of the same template can be used e.g. inside a function: +) + +--- +$(CODE_XREF EdgeArrayFeature)struct Point { + int x; + int y; +} + +void main() { + $(HILITE mixin) EdgeArrayFeature!($(HILITE Point), 5); + + setEdge(3, Point(3, 3)); + printEdges(); +} +--- + +$(P +That $(C mixin) inserts an array and two local functions inside $(C main()). The output: +) + +$(SHELL +The edges: +0:Point(0, 0) 1:Point(0, 0) 2:Point(0, 0) 3:Point(3, 3) 4:Point(0, 0) +) + +$(H6 $(IX local import) $(IX import, local) Template mixins must use local imports) + +$(P +Mixing in template instantiations $(I as is) can cause problems about the modules that the template itself is making use of: Those modules may not be available at the $(C mixin) site. +) + +$(P +Let's consider the following module named $(C a). Naturally, it would have to import the $(C std.string) module that it is making use of: +) + +--- +module a; + +$(HILITE import std.string;) $(CODE_NOTE wrong place) + +mixin template A(T) { + string a() { + T[] array; + // ... + return format("%(%s, %)", array); + } +} +--- + +$(P +However, if $(C std.string) is not imported at the actual $(C mixin) site, then the compiler would not be able to find the definition of $(C format()) at that point. Let's consider the following program that imports $(C a) and tries to mix in $(C A!int) from that module: +) + +--- +import a; + +void main() { + mixin A!int; $(DERLEME_HATASI) +} +--- + +$(SHELL +Error: $(HILITE undefined identifier format) +Error: mixin deneme.main.A!int error instantiating +) + +$(P +For that reason, the modules that template mixins use must be imported in local scopes: +) + +--- +module a; + +mixin template A(T) { + string a() { + $(HILITE import std.string;) $(CODE_NOTE right place) + + T[] array; + // ... + return format("%(%s, %)", array); + } +} +--- + +$(P +As long as it is inside the template definition, the $(C import) directive above can be outside of the $(C a()) function as well. +) + +$(H6 $(IX this, template parameter) Identifying the type that is mixing in) + +$(P +Sometimes a mixin may need to identify the actual type that is mixing it in. That information is available through $(I $(C this) template parameters) as we have seen in $(LINK2 templates_more.html, the More Templates chapter): +) + +--- +mixin template MyMixin(T) { + void foo$(HILITE (this MixingType))() { + import std.stdio; + writefln("The actual type that is mixing in: %s", + $(HILITE MixingType).stringof); + } +} + +struct MyStruct { + mixin MyMixin!(int); +} + +void main() { + auto a = MyStruct(); + a.foo(); +} +--- + +$(P +The output of the program shows that the actual type is available inside the template as $(C MyStruct): +) + +$(SHELL +The actual type that is mixing in: MyStruct +) + +$(H5 $(IX string mixin) String mixins) + +$(P +Another powerful feature of D is being able to insert code as $(C string) as long as that string is known at compile time. The syntax of string mixins requires the use of parentheses: +) + +--- + mixin $(HILITE $(PARANTEZ_AC))$(I compile_time_generated_string)$(HILITE $(PARANTEZ_KAPA)) +--- + +$(P +For example, the $(I hello world) program can be written with a $(C mixin) as well: +) + +--- +import std.stdio; + +void main() { + mixin (`writeln("Hello, World!");`); +} +--- + +$(P +The string gets inserted as code and the program produces the following output: +) + +$(SHELL +Hello, World! +) + +$(P +We can go further and insert all of the program as a string mixin: +) + +--- +mixin ( +`import std.stdio; void main() { writeln("Hello, World!"); }` +); +--- + +$(P +Obviously, there is no need for mixins in these examples, as the strings could have been written as code as well. +) + +$(P +The power of string mixins comes from the fact that the code can be generated at compile time. The following example takes advantage of CTFE to generate statements at compile time: +) + +--- +import std.stdio; + +string printStatement(string message) { + return `writeln("` ~ message ~ `");`; +} + +void main() { + mixin (printStatement("Hello, World!")); + mixin (printStatement("Hi, World!")); +} +--- + +$(P +The output: +) + +$(SHELL +Hello, World! +Hi, World! +) + +$(P +Note that the $(STRING "writeln") expressions are not executed inside $(C printStatement()). Rather, $(C printStatement()) generates code that includes $(C writeln()) expressions that are executed inside $(C main()). The generated code is the equivalent of the following: +) + +--- +import std.stdio; + +void main() { + writeln("Hello, World!"); + writeln("Hi, World!"); +} +--- + +$(H6 Multiple $(C mixin) arguments) + +$(P +As long as they are all known at compile time, $(C mixin) can take multiple arguments and automatically concatenates their string representations: +) + +--- + mixin ("const a = ", int.sizeof, ";"); +--- + +$(P +This can be more convenient compared to using e.g. a $(C format) expression: +) + +--- + mixin (format!"const a = %s;"(int.sizeof)); // Same as above +--- + +$(H6 Debugging string mixins) + +$(P +$(IX -mixin, compiler switch) Because generated code is not readily visible as a whole in source code, it can be difficult to identify causes of compilation errors with $(C mixin) expressions. To help with debugging string mixins, there is the $(C dmd) compiler switch $(C -mixin), which writes all mixed-in code to a specified file. +) + +$(P +Let's consider the following program that has a syntax error in code that is being mixed in. It is not obvious from the compiler error that the syntax error is the missing semicolon at the end of the definition of the $(C struct) member: +) + +--- +string makeStruct(string name, string member) { + import std.format; + return format!"struct %s {\n int %s\n}"(name, member); +} + +mixin (makeStruct("S", "m")); $(DERLEME_HATASI) + +void main() { +} +--- + +$(P +When compiled with the $(C -mixin) switch, the compilation error would point at a line inside the specified file ($(C mixed_in_code) in the example below): +) + +$(SHELL +$(SHELL_OBSERVED $) dmd $(HILITE -mixin=mixed_in_code) deneme.d +mixed_in_code($(HILITE 154)): Error: semicolon expected, not `}` +) + +$(P +Along with all other code that are mixed-in by the standard library, there would be the following code at the specified line inside file $(C mixed_in_code): +) + +$(SHELL +[...] +// expansion at deneme.d(6) +struct S { + int m +} $(SHELL_NOTE Line 154) +) + + +$(P +Another option for debugging string mixins is $(LINK2 pragma.html, $(C pragma(msg))), which would print the generated code during compilation. This option is less practical because it requires replacing the $(C mixin) keyword with $(C pragma(msg)) temporarily for debugging: +) + +--- +pragma(msg, makeStruct("S", "m")); +--- + +$(H5 $(IX name space, mixin) Mixin name spaces) + +$(P +It is possible to avoid and resolve name ambiguities in template mixins. +) + +$(P +For example, there are two $(C i) variables defined inside $(C main()) in the following program: one is defined explicitly in $(C main) and the other is mixed in. When a mixed-in name is the same as a name that is in the surrounding scope, then the name that is in the surrounding scope gets used: +) + +--- +import std.stdio; + +template Templ() { + $(HILITE int i;) + + void print() { + writeln(i); // Always the 'i' that is defined in Templ + } +} + +void main() { + $(HILITE int i;) + mixin Templ; + + i = 42; // Sets the 'i' that is defined explicitly in main + writeln(i); // Prints the 'i' that is defined explicitly in main + print(); // Prints the 'i' that is mixed in +} +--- + +$(P +As implied in the comments above, template mixins define a name space for their contents and the names that appear in the template code are first looked up in that name space. We can see this in the behavior of $(C print()): +) + +$(SHELL +42 +0 $(SHELL_NOTE printed by print()) +) + +$(P +The compiler cannot resolve name conflicts if the same name is defined by more than one template mixin. Let's see this in a short program that mixes in the same template instance twice: +) + +--- +template Templ() { + int i; +} + +void main() { + mixin Templ; + mixin Templ; + + i = 42; $(DERLEME_HATASI) +} +--- + +$(SHELL +Error: deneme.main.Templ!().i at ... $(HILITE conflicts with) +deneme.main.Templ!().i at ... +) + +$(P +To prevent this, it is possible to assign name space identifiers for template mixins and refer to contained names by those identifiers: +) + +--- + mixin Templ $(HILITE A); // Defines A.i + mixin Templ $(HILITE B); // Defines B.i + + $(HILITE A.)i = 42; // ← not ambiguous anymore +--- + +$(P +String mixins do not have these name space features. However, it is trivial to use a string as a template mixin simply by passing it through a simple wrapper template. +) + +$(P +Let's first see a similar name conflict with string mixins: +) + +--- +void main() { + mixin ("int i;"); + mixin ("int i;"); $(DERLEME_HATASI) + + i = 42; +} +--- + +$(SHELL +Error: declaration deneme.main.i is $(HILITE already defined) +) + +$(P +One way of resolving this issue is to pass the $(C string) through the following trivial template that effectively converts a string mixin to a template mixin: +) + +--- +template Templatize(string str) { + mixin (str); +} + +void main() { + mixin Templatize!("int i;") A; // Defines A.i + mixin Templatize!("int i;") B; // Defines B.i + + A.i = 42; // ← not ambiguous anymore +} +--- + +$(H5 $(IX operator overloading, mixin) String mixins in operator overloading) + +$(P +We have seen in $(LINK2 operator_overloading.html, the Operator Overloading chapter) how $(C mixin) expressions helped with the definitions of some of the operators. +) + +$(P +In fact, the reason why most operator member functions are defined as templates is to make the operators available as $(C string) values so that they can be used for code generation. We have seen examples of this both in that chapter and its exercise solutions. +) + +$(H5 $(IX destructor, mixin) Mixed in destructors) + +$(P +It is possible to mix in multiple destructors to a user defined type. Those destructors are called in the reverse order of the $(C mixin) statements that added them. This feature allows mixing in different resources to a type, each introducing its own cleanup code. +) + +--- +import std.stdio; + +mixin template Foo() { + ~this() { + writeln("Destructor mixed-in by Foo"); + } +} + +mixin template Bar() { + ~this() { + writeln("Destructor mixed-in by Bar"); + } +} + +struct S { + ~this() { + writeln("Actual destructor"); + } + mixin Foo; + mixin Bar; +} + +void main() { + auto s = S(); +} +--- + +$(SHELL +Destructor mixed-in by Bar +Destructor mixed-in by Foo +Actual destructor +) + +$(P +Due to a bug as of this writing, the same behavior does not apply to other special functions like constructors. Additionally, a destructor mixed in by a string mixin does conflict with the existing destructor of the type. +) + +$(H5 $(IX text file import) $(IX file import) $(IX import, file) $(IX string import) $(IX import, string) Importing text files) + +$(P +It is possible to insert contents of text files into code at compile time. The contents are treated as $(C string) literals and can be used anywhere strings can be used. For example, they can be mixed in as code. +) + +$(P +For example, let's assume there are two text files on the file system named $(C file_one) and $(C file_two) having the following contents. +) + +$(UL +$(LI +$(C file_one): + +$(SHELL +Hello +) +) + +$(LI +$(C file_two): + +$(SHELL +s ~= ", World!"; +import std.stdio; +writeln(s); +) +) + +) + +$(P +The two $(C import) directives in the following program would correspond to the contents of those files converted to $(C string) literals at compile time: +) + +--- +void main() { + string s = import ("file_one"); + mixin (import ("file_two")); +} +--- + +$(P +$(IX -J, compiler switch) Text file imports (a.k.a. string imports) require the $(C -J) compiler switch which tells the compiler where to find the text files. For example, if the two files are in the $(I current directory) (specified with $(C .) in Linux environments), the program can be compiled with the following command: +) + +$(SHELL +$ dmd $(HILITE -J.) deneme.d +) + +$(P +The output: +) + +$(SHELL +Hello, World! +) + +$(P +Considering the file contents as $(C string) literals, the program is the equivalent of the following one: +) + +--- +void main() { + string s = `Hello`; $(CODE_NOTE Content of file_one as string) + mixin (`s ~= ", World!"; +import std.stdio; +writeln(s);`); $(CODE_NOTE Content of file_two as string) +} +--- + +$(P +Further, considering the mixed-in string as well, the program is the equivalent of the following one: +) + +--- +void main() { + string s = `Hello`; + s ~= ", World!"; + import std.stdio; + writeln(s); +} +--- + +$(H5 Example) + +$(P +($(I $(B Note:) Specifying predicates as strings was used more commonly before the lambda syntax was added to D. Although string predicates as in this example are still used in Phobos, the $(C =>) lambda syntax may be more suitable in most cases.)) +) + +$(P +Let's consider the following function template that takes an array of numbers and returns another array that consists of the elements that satisfy a specific condition: +) + +--- +int[] filter($(HILITE string predicate))(int[] numbers) { + int[] result; + + foreach (number; numbers) { + if ($(HILITE mixin (predicate))) { + result ~= number; + } + } + + return result; +} +--- + +$(P +That function template takes the filtering condition as its template parameter and inserts that condition directly into an $(C if) statement as is. +) + +$(P +For that condition to choose numbers that are e.g. less than 7, the $(C if) condition should look like the following code: +) + +--- + if (number < 7) { +--- + +$(P +The users of $(C filter()) template can provide the condition as a $(C string): +) + +--- + int[] numbers = [ 1, 8, 6, -2, 10 ]; + int[] chosen = filter!$(HILITE "number < 7")(numbers); +--- + +$(P +Importantly, the name used in the template parameter must match the name of the variable used in the implementation of $(C filter()). So, the template must document what that name should be and the users must use that name. +) + +$(P +Phobos uses names consisting of single letters like a, b, n, etc. +) + +macros: + TITLE=Mixins + + DESCRIPTION=Template mixins and string mixins. + + KEYWORDS=d programming language tutorial book mixin + +SOZLER= +$(katma) +$(sablon) diff --git a/book/d.en/modules.d b/book/d.en/modules.d new file mode 100644 index 0000000000..90b02b1d29 --- /dev/null +++ b/book/d.en/modules.d @@ -0,0 +1,622 @@ +Ddoc + +$(DERS_BOLUMU $(IX module) Modules and Libraries) + +$(P +The building blocks of D programs (and libraries) are modules. +) + +$(P +D modules are based on a simple concept: Every source file is a module. Accordingly, the single files that we have been writing our programs in have all been individual modules. +) + +$(P +By default, the name of a module is the same as its filename without the $(C .d) extension. When explicitly specified, the name of the module is defined by the $(C module) keyword, which must appear as the first non-comment line in the source file. +) + +$(P +For example, assuming that the name of a source file is "cat.d", the name of the module would be specified by the $(C module) keyword: +) + +--- +module cat; + +class Cat { + // ... +} +--- + +$(P +The $(C module) line is optional if the module is not part of any package (see below). When not specified, it is the same as the file name without the $(C .d) extension. +) + +$(H6 $(IX static this, module) $(IX static ~this, module) $(IX this, static, module) $(IX ~this, static, module) $(IX module constructor, thread-local) $(C static this()) and $(C static ~this())) + +$(P +$(C static this()) and $(C static ~this()) at module scope are similar to their $(C struct) and $(C class) counterparts: +) + +--- +module cat; + +static this() { + // ... the initial operations of the module ... +} + +static ~this() { + // ... the final operations of the module ... +} +--- + +$(P +Code that are in these scopes are executed once for each thread. (Note that most programs consist of a single thread that starts executing the $(C main()) function.) Code that should be executed only once for the entire program (e.g. initializing $(C shared) and $(C immutable) variables) must be defined in $(C shared static this()) and $(C shared static ~this()) blocks, which will be covered in $(LINK2 concurrency_shared.html, the Data Sharing Concurrency chapter). +) + +$(H6 File and module names) + +$(P +D supports Unicode in source code and module names. However, the Unicode support of file systems vary. For example, although most Linux file systems support Unicode, the file names in Windows file systems may not distinguish between lower and upper case letters. Additionally, most file systems limit the characters that can be used in file and directory names. +) + +$(P +For portability reasons, I recommend that you use only lower case ASCII letters in file names. For example, "resume.d" would be a suitable file name for a class named $(C Résumé). +) + +$(P +Accordingly, the name of the module would consist of ASCII letters as well: +) + +--- +module resume; // Module name consisting of ASCII letters + +class Résumé { // Program code consisting of Unicode characters + // ... +} +--- + +$(H5 $(IX package, definition) Packages) + +$(P +A combination of related modules are called a $(I package). D packages are a simple concept as well: The source files that are inside the same directory are considered to belong to the same package. The name of the directory becomes the name of the package, which must also be specified as the first parts of module names. +) + +$(P +For example, if "cat.d" and "dog.d" are inside the directory "animal", then specifying the directory name along with the module name makes them be a part of the same package: +) + +--- +module $(HILITE animal.)cat; + +class Cat { + // ... +} +--- + +$(P +Similarly, for the $(C dog) module: +) + +--- +module $(HILITE animal.)dog; + +class Dog { + // ... +} +--- + +$(P +For modules that are parts of packages, the $(C module) line is not optional and the whole module name including the package name must be specified. +) + +$(P +Since package names correspond to directory names, the package names of modules that are deeper than one directory level must reflect that hierarchy. For example, if the "animal" directory included a "vertebrate" directory, the name of a module inside that directory would include $(C vertebrate) as well: +) + +--- +module animal.vertebrate.cat; +--- + +$(P +The directory hierarchies can be arbitrarily complex depending on the needs of the program. Relatively short programs usually have all of their source files in a single directory. +) + +$(H5 Importing modules) + +$(P +$(IX import) The $(C import) keyword, which we have been using in almost every program so far, is for introducing a module to the current module: +) + +--- +import std.stdio; +--- + +$(P +The module name may contain the package name as well. For example, the $(C std.) part above indicates that $(C stdio) is a module that is a part of the $(C std) package. +) + +$(P +The $(C animal.cat) and $(C animal.dog) modules would be imported similarly. Let's assume that the following code is inside a file named "deneme.d": +) + +--- +module deneme; // the name of this module + +import animal.cat; // a module that it uses +import animal.dog; // another module that it uses + +void main() { + auto cat = new Cat(); + auto dog = new Dog(); +} +--- + +$(P +$(I $(B Note:) As described below, for the program to be built correctly, those module files must also be provided to the linker.) +) + +$(P +More than one module can be imported at the same time: +) + +--- +import animal.cat, animal.dog; +--- + +$(H6 $(IX selective import) $(IX import, selective) Selective imports) + +$(P +$(IX :, import) Instead of importing a module as a whole with all of its names, it is possible to import just specific names from it. +) + +--- +import std.stdio $(HILITE : writeln;) + +// ... + + write$(HILITE f)ln("Hello %s.", name); $(DERLEME_HATASI) +--- + +$(P +The code above cannot be compiled because only $(C writeln) is imported, not $(C writefln). +) + +$(P +Selective imports are considered to be better than importing an entire module because it reduces the chance of $(I name collisions). As we will see in an example below, a name collision can occur when the same name appears in more than one imported module. +) + +$(P +Selective imports may reduce compilation times as well because the compiler needs to compile only the parts of a module that are actually imported. On the other hand, selective imports require more work as every imported name must be specified separately on the $(C import) line. +) + +$(P +This book does not take advantage of selective imports mostly for brevity. +) + +$(H6 $(IX local import) $(IX import, local) Local imports) + +$(P +So far we have always imported all of the required modules at the tops of programs: +) + +--- +import std.stdio; $(CODE_NOTE at the top) +import std.string; $(CODE_NOTE at the top) + +// ... the rest of the module ... +--- + +$(P +Instead, modules can be imported at any other line of the source code. For example, the two functions of the following program import the modules that they need in their own scopes: +) + +--- +string makeGreeting(string name) { + $(HILITE import std.string;) + + string greeting = format("Hello %s", name); + return greeting; +} + +void interactWithUser() { + $(HILITE import std.stdio;) + + write("Please enter your name: "); + string name = readln(); + writeln(makeGreeting(name)); +} + +void main() { + interactWithUser(); +} +--- + +$(P +Local imports are recommended over global imports because instead of importing every module unconditionally at the top, the compiler can import only the ones that are in the scopes that are actually used. If the compiler knows that the program never calls a function, it can ignore the import directives inside that function. +) + +$(P +Additionally, a locally imported module is accessible only inside that local scope, further reducing the risk of name collisions. +) + +$(P +We will later see in $(LINK2 mixin.html, the Mixins chapter) that local imports are in fact required for $(I template mixins.) +) + +$(P +The examples throughout this book do not take advantage of local imports mostly because local imports were added to D after the start of writing this book. +) + +$(H6 Locations of modules) + +$(P +The compiler finds the module files by converting the package and module names directly to directory and file names. +) + +$(P +For example, the previous two modules would be located as "animal/cat.d" and "animal/dog.d", respectively (or "animal\cat.d" and "animal\dog.d", depending on the file system). Considering the main source file as well, the program above consists of three files. +) + +$(H6 Long and short module names) + +$(P +The names that are used in the program may be spelled out with the module and package names: +) + +--- + auto cat0 = Cat(); + auto cat1 = animal.cat.Cat(); // same as above +--- + +$(P +The long names are normally not needed but sometimes there are name conflicts. For example, when referring to a name that appears in more than one module, the compiler cannot decide which one is meant. +) + +$(P +The following program is spelling out the long names to distinguish between two separate $(C Jaguar) structs that are defined in two separate modules: $(C animal) and $(C car): +) + +--- +import animal.jaguar; +import car.jaguar; + +// ... + + auto conflicted = Jaguar(); $(DERLEME_HATASI) + + auto myAnimal = animal.jaguar.Jaguar(); $(CODE_NOTE compiles) + auto myCar = car.jaguar.Jaguar(); $(CODE_NOTE compiles) +--- + +$(H6 Renamed imports) + +$(P +$(IX renamed import) It is possible to rename imported modules either for convenience or to resolve name conflicts: +) + +--- +import $(HILITE carnivore =) animal.jaguar; +import $(HILITE vehicle =) car.jaguar; + +// ... + + auto myAnimal = $(HILITE carnivore.)Jaguar(); $(CODE_NOTE compiles) + auto myCar = $(HILITE vehicle.)Jaguar(); $(CODE_NOTE compiles) +--- + +$(P +Instead of renaming the entire import, it is possible to rename individual imported symbols. +) + +$(P +For example, when the following code is compiled with the $(C -w) compiler switch, the compiler would warn that $(C sort()) $(I function) should be preferred instead of $(C .sort) $(I property): +) + +--- +import std.stdio; +import std.algorithm; + +// ... + + auto arr = [ 2, 10, 1, 5 ]; + arr$(HILITE .sort); $(CODE_NOTE_WRONG compilation WARNING) + writeln(arr); +--- + +$(SHELL +Warning: use std.algorithm.sort instead of .sort property +) + +$(P +$(I $(B Note:) The $(C arr.sort) expression above is the equivalent of $(C sort(arr)) but it is written in the UFCS syntax, which we will see in $(LINK2 ufcs.html, a later chapter).) +) + +$(P +One solution in this case is to import $(C std.algorithm.sort) by renaming it. The new name $(C algSort) below means the $(C sort()) $(I function) and the compiler warning is eliminated: +) + +--- +import std.stdio; +import std.algorithm : $(HILITE algSort =) sort; + +void main() { + auto arr = [ 2, 10, 1, 5 ]; + arr$(HILITE .algSort); + writeln(arr); +} +--- + +$(H6 $(IX package import) Importing a package as a module) + +$(P +Sometimes multiple modules of a package may need to be imported together. For example, whenever one module from the $(C animal) package is imported, all of the other modules may need to be imported as well: $(C animal.cat), $(C animal.dog), $(C animal.horse), etc. +) + +$(P +In such cases it is possible to import some or all of the modules of a package by importing the package as if it were a module: +) + +--- +import animal; // ← entire package imported as a module +--- + +$(P +$(IX package.d) It is achieved by a special configuration file in the package directory, which must always be named as $(C package.d). That special file includes the $(C module) directive for the package and imports the modules of the package $(I publicly): +) + +--- +// The contents of the file animal/package.d: +module animal; + +$(HILITE public) import animal.cat; +$(HILITE public) import animal.dog; +$(HILITE public) import animal.horse; +// ... same for the other modules ... +--- + +$(P +Importing a module publicly makes that module available to the users of the importing module as well. As a result, when the users import just the $(C animal) module (which actually is a package), they get access to $(C animal.cat) and all the other modules as well. +) + +$(H6 $(IX deprecated) Deprecating features) + +$(P +Modules evolve over time and get released under new version numbers. Going forward from a particular version, the authors of the module may decide to $(I deprecate) some of its features. Deprecating a feature means that newly written programs should not rely on that feature anymore; using a deprecated feature is disapproved. Deprecated features may even be removed from the module in the future. +) + +$(P +There can be many reasons why a feature is deprecated. For example, the new version of the module may include a better alternative, the feature may have been moved to another module, the name of the feature may have changed to be consistent with the rest of the module, etc. +) + +$(P +The deprecation of a feature is made official by defining it with the $(C deprecated) attribute, optionally with a custom message. For example, the following deprecation message communicates to its user that the name of the function has been changed: +) + +--- +deprecated("Please use doSomething() instead.") +void do_something() { + // ... +} +--- + +$(P +By specifying one of the following compiler switches, the user of the module can determine how the compiler should react when a deprecated feature is used: +) + +$(UL +$(LI $(IX -d, compiler switch) $(C -d): Using deprecated features should be allowed) +$(LI $(IX -dw, compiler switch) $(C -dw): Using deprecated features should produce compilation warnings) +$(LI $(IX -de, compiler switch) $(C -de): Using deprecated features should produce compilation errors) +) + +$(P +For example, calling the deprecated feature in a program and compiling it with $(C -de) would fail compilation: +) + +--- + do_something(); +--- + +$(SHELL_SMALL +$ dmd deneme.d $(HILITE -de) +$(SHELL_OBSERVED deneme.d: $(HILITE Deprecation): function deneme.do_something is +deprecated - Please use doSomething() instead.) +) + +$(P +The name of a deprecated feature is usually defined as an $(C alias) of the new name: +) + +--- +deprecated("Please use doSomething() instead.") +$(HILITE alias do_something) = doSomething; + +void doSomething() { + // ... +} +--- + +$(P +We will see the $(C alias) keyword in $(LINK2 alias.html, a later chapter). +) + +$(H6 Adding module definitions to the program) + +$(P +The $(C import) keyword is not sufficient to make modules become parts of the program. It simply makes available the features of a module inside the current module. That much is needed only to $(I compile) the code. +) + +$(P +It is not possible to build the previous program only by the main source file, "deneme.d": +) + +$(SHELL_SMALL +$ dmd deneme.d -w -de +$(SHELL_OBSERVED deneme.o: In function `_Dmain': +deneme.d: $(HILITE undefined reference) to `_D6animal3cat3Cat7__ClassZ' +deneme.d: $(HILITE undefined reference) to `_D6animal3dog3Dog7__ClassZ' +collect2: ld returned 1 exit status) +) + +$(P +Those error messages are generated by the $(I linker). Although they are not user-friendly messages, they indicate that some definitions that are needed by the program are missing. +) + +$(P +$(IX linker) $(IX building the program) The actual build of the program is the responsibility of the linker, which gets called automatically by the compiler behind the scenes. The compiler passes the modules that it has just compiled to the linker, and the linker combines those modules (and libraries) to produce the executable program. +) + +$(P +For that reason, all of the modules that make up the program must be provided to the linker. For the program above to be built, "animal/cat.d" and "animal/dog.d" must also be specified on the compilation line: +) + +$(SHELL_SMALL +$ dmd deneme.d animal/cat.d animal/dog.d -w -de +) + +$(P +Instead of having to mention the modules individually every time on the command line, they can be combined as libraries. +) + +$(H5 $(IX library) Libraries) + +$(P +A collection of compiled modules is called a library. Libraries are not programs themselves; they do not have the $(C main()) function. Libraries contain compiled definitions of functions, structs, classes, and other features of modules, which are to be linked later by the linker to produce the program. +) + +$(P +dmd's $(C -lib) command line option is for making libraries. The following command makes a library that contains the "cat.d" and the "dog.d" modules. The name of the library is specified with the $(C -of) switch: +) + +$(SHELL_SMALL +$ dmd animal/cat.d animal/dog.d -lib -ofanimal -w -de +) + +$(P +The actual name of the library file depends on the platform. For example, the extension of library files is $(C .a) under Linux systems: $(C animal.a). +) + +$(P +Once that library is built, It is not necessary to specify the "animal/cat.d" and "animal/dog.d" modules individually anymore. The library file is sufficient: +) + +$(SHELL_SMALL +$ dmd deneme.d animal.a -w -de +) + +$(P +The command above replaces the following one: +) + +$(SHELL_SMALL +$ dmd deneme.d animal/cat.d animal/dog.d -w -de +) + +$(P +$(IX Phobos, library) As an exception, the D standard library Phobos need not be specified on the command line. That library is automatically included behind the scenes. Otherwise, it could be specified similar to the following line: +) + +$(SHELL_SMALL +$ dmd deneme.d animal.a /usr/lib64/libphobos2.a -w -de +) + +$(P +$(I $(B Note:) The name and location of the Phobos library may be different on different systems.) +) + +$(H6 Using libraries of other languages) + +$(P +D can use libraries that are written in some other compiled languages like C and C++. However, because different languages use different $(I linkages), such libraries are available to D code only through their $(I D bindings). +) + +$(P +$(IX linkage) $(IX name mangling) $(IX mangling, name) $(IX symbol) Linkage is the set of rules that determines the accessibility of entities in a library as well as how the names (symbols) of those entities are represented in compiled code. The names in compiled code are different from the names that the programmer writes in source code: The compiled names are $(I name-mangled) according to the rules of a particular language or compiler. +) + +$(P +$(IX mangle, core.demangle) $(IX demangle) For example, according to C linkage, the C function name $(C foo) would be $(I mangled) with a leading underscore as $(C _foo) in compiled code. Name-mangling is more complex in languages like C++ and D because these languages allow using the same name for different entities in different modules, structs, classes, etc. as well as for overloads of functions. A D function named $(C foo) in source code has to be mangled in a way that would differentiate it from all other $(C foo) names that can exist in a program. Although the exact mangled names are usually not important to the programmer, the $(C core.demangle) module can be used to mangle and demangle symbols: +) + +--- +module deneme; + +import std.stdio; +import core.demangle; + +void foo() { +} + +void main() { + writeln($(HILITE mangle)!(typeof(foo))("deneme.foo")); +} +--- + +$(P +$(I $(B Note:) $(C mangle()) is a function template, the syntax of which is unfamiliar at this point in the book. We will see templates later in $(LINK2 templates.html, the Templates chapter).) +) + +$(P +A function that has the same type as $(C foo) above and is named as $(C deneme.foo), has the following mangled name in compiled code: +) + +$(SHELL_SMALL +_D6deneme3fooFZv +) + +$(P +Name mangling is the reason why linker error messages cannot include user-friendly names. For example, a symbol in an error message above was $(C _D6animal3cat3Cat7__ClassZ) instead of $(C animal.cat.Cat). +) + +$(P +$(IX extern()) $(IX C) $(IX C++) $(IX D) $(IX Objective-C) $(IX Pascal) $(IX System) $(IX Windows) The $(C extern()) attribute specifies the linkage of entities. The valid linkage types that can be used with $(C extern()) are $(C C), $(C C++), $(C D), $(C Objective-C), $(C Pascal), $(C System), and $(C Windows). For example, when a D code needs to make a call to a function that is defined in a C library, that function must be declared as having C linkage: +) + +--- +// Declaring that 'foo' has C linkage (e.g. it may be defined +// in a C library): +$(HILITE extern(C)) void foo(); + +void main() { + foo(); // this call would be compiled as a call to '_foo' +} +--- + +$(P +$(IX namespace, C++) In the case of C++ linkage, the namespace that a name is defined in is specified as the second argument to the $(C extern()) attribute. For example, according to the following declaration, $(C bar()) is the declaration of the function $(C a::b::c::bar()) defined in a C++ library (note that D code uses dots instead of colons): +) + +--- +// Declaring that 'bar' is defined inside namespace a::b::c +// and that it has C++ linkage: +extern(C++, $(HILITE a.b.c)) void bar(); + +void main() { + bar(); // a call to a::b::c::bar() + a.b.c.bar(); // same as above +} +--- + +$(P +$(IX binding) A file that contains such D declarations of the features of an external library is called a $(I D binding) of that library. Fortunately, in most cases programmers do not need to write them from scratch as D bindings for many popular non-D libraries are available through $(LINK2 https://github.com/D-Programming-Deimos/, the Deimos project). +) + +$(P +$(IX extern) When used without a linkage type, the $(C extern) attribute has a different meaning: It specifies that the storage for a variable is the responsibility of an external library; the D compiler should not reserve space for it in this module. Having different meanings, $(C extern) and $(C extern()) can be used together: +) + +--- +// Declaring that the storage for 'g_variable' is already +// defined in a C library: +extern(C) $(HILITE extern) int g_variable; +--- + +$(P +If the $(C extern) attribute were not specified above, while having C linkage, $(C g_variable) would be a variable of this D module. +) + +Macros: + TITLE=Modules and Libraries + + DESCRIPTION=D modules and libraries + + KEYWORDS=d programming lesson book tutorial module library diff --git a/book/d.en/name_space.d b/book/d.en/name_space.d new file mode 100644 index 0000000000..c2cbc871a2 --- /dev/null +++ b/book/d.en/name_space.d @@ -0,0 +1,143 @@ +Ddoc + +$(DERS_BOLUMU $(IX name scope) Name Scope) + +$(P +Any name is accessible from the point where it has been defined at to the point where its scope ends, as well as in all of the scopes that its scope includes. In this regard, every scope defines a $(I name scope). +) + +$(P +Names are not available beyond the end of their scope: +) + +--- +void main() { + int outer; + + if (aCondition) $(HILITE {) // ← curly bracket starts a new scope + int inner = 1; + outer = 2; // ← 'outer' is available here + + $(HILITE }) // ← 'inner' is not available beyond this point + + inner = 3; $(DERLEME_HATASI) + // 'inner' is not available in the outer scope +} +--- + +$(P +Because $(C inner) is defined within the scope of the $(C if) condition it is available only in that scope. On the other hand, $(C outer) is available in both the outer scope and the inner scope. +) + +$(P +It is not legal to define the same name in an inner scope: +) + +--- + size_t $(HILITE length) = oddNumbers.length; + + if (aCondition) { + size_t $(HILITE length) = primeNumbers.length; $(DERLEME_HATASI) + } +--- + +$(H5 Defining names closest to their first use) + +$(P +As we have been doing in all of the programs so far, variables must be defined before their first use: +) + +--- + writeln(number); $(DERLEME_HATASI) + // number is not known yet + int number = 42; +--- + +$(P +For that code to be acceptable by the compiler, $(C number) must be defined before it is used with $(C writeln). Although there is no restriction on how many lines earlier it should be defined, it is accepted as good programming practice that variables be defined closest to where they are first used. +) + +$(P +Let's see this in a program that prints the average of the numbers that it takes from the user. Programmers who are experienced in some other programming languages may be used to defining variables at tops of scopes: +) + +--- + int count; // ← HERE + int[] numbers; // ← HERE + double averageValue; // ← HERE + + write("How many numbers are there? "); + + readf(" %s", &count); + + if (count >= 1) { + numbers.length = count; + + // ... assume the calculation is here ... + + } else { + writeln("ERROR: You must enter at least one number!"); + } +--- + +$(P +Contrast the code above to the one below that defines the variables later, as each variable actually starts taking part in the program: +) + +--- + write("How many numbers are there? "); + + int count; // ← HERE + readf(" %s", &count); + + if (count >= 1) { + int[] numbers; // ← HERE + numbers.length = count; + + double averageValue; // ← HERE + + // ... assume that the calculation is here ... + + } else { + writeln("ERROR: You must enter at least one number!"); + } +--- + +$(P +Although defining all of the variables at the top may look better structurally, there are several benefits of defining them as late as possible: +) + +$(UL +$(LI $(B Speed:) Every variable definition tends to add a small speed cost to the program. As every variable is initialized in D, defining variables at the top will result in them always being initialized, even if they are only sometimes used later, wasting resources. +) + +$(LI $(B Risk of mistakes:) Every line between the definition and use of a variable carries a higher risk of programming mistakes. As an example of this, consider a variable using the common name $(C length). It is possible to confuse that variable with some other length and use it inadvertently before reaching the line of its first intended use. When that line is finally reached the variable may no longer have the desired value. +) + +$(LI $(B Readability:) As the number of lines in a scope increase, it becomes more likely that the definition of a variable is too far up in the source code, forcing the programmer to scroll back in order to look at its definition. +) + +$(LI $(B Code maintenance:) Source code is in constant modification and improvement: new features are added, old features are removed, bugs are fixed, etc. These changes sometimes make it necessary to extract a group of lines altogether into a new function. + +$(P +When that happens, having all of the variables defined close to the lines that use them makes it easier to move them as a coherent bunch. +) + +$(P +For example, in the latter code above that followed this guideline, all of the lines within the $(C if) statement can be moved to a new function in the program. +) + +$(P +On the other hand, when the variables are always defined at the top, if some lines ever need to be moved, the variables that are used in those lines must be identified one by one. +) + +) + +) + +Macros: + TITLE=Name Scope + + DESCRIPTION=The scopes in the program where names are valid and accessible, and the benefits of defining variables closest to their first use in the program. + + KEYWORDS=d programming language tutorial book name scopes diff --git a/book/d.en/nested.d b/book/d.en/nested.d new file mode 100644 index 0000000000..1ba44d153d --- /dev/null +++ b/book/d.en/nested.d @@ -0,0 +1,282 @@ +Ddoc + +$(DERS_BOLUMU $(IX function, nested) $(IX struct, nested) $(IX class, nested in function) $(IX nested definition) Nested Functions, Structs, and Classes) + +$(P +Up to this point, we have been defining functions, structs, and classes in the outermost scopes (i.e. the module scope). They can be defined in inner scopes as well. Defining them in inner scopes helps with encapsulation by narrowing the visibility of their symbols, as well as creating $(I closures) that we saw in $(LINK2 lambda.html, the Function Pointers, Delegates, and Lambdas chapter). +) + +$(P +As an example, the following $(C outerFunc()) function contains definitions of a nested function, a nested $(C struct), and a nested $(C class): +) + +--- +void outerFunc(int parameter) { + int local; + + $(HILITE void nestedFunc()) { + local = parameter * 2; + } + + $(HILITE struct NestedStruct) { + void memberFunc() { + local /= parameter; + } + } + + $(HILITE class NestedClass) { + void memberFunc() { + local += parameter; + } + } + + // Using the nested definitions inside this scope: + + nestedFunc(); + + auto s = NestedStruct(); + s.memberFunc(); + + auto c = new NestedClass(); + c.memberFunc(); +} + +void main() { + outerFunc(42); +} +--- + +$(P +Like any other variable, nested definitions can access symbols that are defined in their outer scopes. For example, all three of the nested definitions above are able to use the variables named $(C parameter) and $(C local). +) + +$(P +As usual, the names of the nested definitions are valid only in the scopes that they are defined in. For example, $(C nestedFunc()), $(C NestedStruct), and $(C NestedClass) are not accessible from $(C main()): +) + +--- +void main() { + auto a = NestedStruct(); $(DERLEME_HATASI) + auto b = outerFunc.NestedStruct(); $(DERLEME_HATASI) +} +--- + +$(P +Although their names cannot be accessed, nested definitions can still be used in other scopes. For example, many Phobos algorithms handle their tasks by nested structs that are defined inside Phobos functions. +) + +$(P +To see an example of this, let's design a function that consumes a slice from both ends in alternating order: +) + +--- +import std.stdio; +import std.array; + +auto alternatingEnds(T)(T[] slice) { + bool isFromFront = true; + + $(HILITE struct EndAlternatingRange) { + bool empty() const { + return slice.empty; + } + + T front() const { + return isFromFront ? slice.front : slice.back; + } + + void popFront() { + if (isFromFront) { + slice.popFront(); + isFromFront = false; + + } else { + slice.popBack(); + isFromFront = true; + } + } + } + + return EndAlternatingRange(); +} + +void main() { + auto a = alternatingEnds([ 1, 2, 3, 4, 5 ]); + writeln(a); +} +--- + +$(P +Even though the nested $(C struct) cannot be named inside $(C main()), it is still usable: +) + +$(SHELL +[1, 5, 2, 4, 3] +) + +$(P +$(IX Voldemort) $(I $(B Note:) Because their names cannot be mentioned outside of their scopes, such types are called $(I Voldemort types) due to analogy to a Harry Potter character.) +) + +$(P +$(IX closure) $(IX context) Note that the nested $(C struct) that $(C alternatingEnds()) returns does not have any member variables. That $(C struct) handles its task using merely the function parameter $(C slice) and the local function variable $(C isFromFront). The fact that the returned object can safely use those variables even after leaving the context that it was created in is due to a $(I closure) that has been created automatically. We have seen closures in $(LINK2 lambda.html, the Function Pointers, Delegates, and Lambdas chapter). +) + +$(H6 $(C static) when a closure is not needed) + +$(P +$(IX static, nested definition) Since they keep their contexts alive, nested definitions are more expensive than their regular counterparts. Additionally, as they must include a $(I context pointer) to determine the context that they are associated with, objects of nested definitions occupy more space as well. For example, although the following two structs have exactly the same member variables, their sizes are different: +) + +--- +import std.stdio; + +$(HILITE struct ModuleStruct) { + int i; + + void memberFunc() { + } +} + +void moduleFunc() { + $(HILITE struct NestedStruct) { + int i; + + void memberFunc() { + } + } + + writefln("OuterStruct: %s bytes, NestedStruct: %s bytes.", + ModuleStruct.sizeof, NestedStruct.sizeof); +} + +void main() { + moduleFunc(); +} +--- + +$(P +The sizes of the two structs may be different on other environments: +) + +$(SHELL +OuterStruct: $(HILITE 4) bytes, NestedStruct: $(HILITE 16) bytes. +) + +$(P +$(IX static class) $(IX static struct) However, some nested definitions are merely for keeping them as local as possible, with no need to access variables from the outer contexts. In such cases, the associated cost would be unnecessary. The $(C static) keyword removes the context pointer from nested definitions, making them equivalents of their module counterparts. As a result, $(C static) nested definitions cannot access their outer contexts: +) + +--- +void outerFunc(int parameter) { + $(HILITE static) class NestedClass { + int i; + + this() { + i = parameter; $(DERLEME_HATASI) + } + } +} +--- + +$(P +$(IX .outer, void*) The context pointer of a nested $(C class) object is available as a $(C void*) through its $(C .outer) property. For example, because they are defined in the same scope, the context pointers of the following two objects are equal: +) + +--- +void foo() { + class C { + } + + auto a = new C(); + auto b = new C(); + + assert(a$(HILITE .outer) is b$(HILITE .outer)); +} +--- + +$(P +As we will see below, for $(I classes nested inside classes), the type of the context pointer is the type of the outer class, not $(C void*). +) + +$(H6 Classes nested inside classes) + +$(P +$(IX class, nested in class) When a $(C class) is nested inside another one, the context that the nested object is associated with is the outer object itself. +) + +$(P +$(IX .new) $(IX .outer, class type) Such nested classes are constructed by the $(C this.new) syntax. When necessary, the outer object of a nested object can be accessed by $(C this.outer): +) + +--- +class OuterClass { + int outerMember; + + $(HILITE class NestedClass) { + int func() { + /* A nested class can access members of the outer + * class. */ + return outerMember * 2; + } + + OuterClass context() { + /* A nested class can access its outer object + * (i.e. its context) by '.outer'. */ + return $(HILITE this.outer); + } + } + + NestedClass algorithm() { + /* An outer class can construct a nested object by + * '.new'. */ + return $(HILITE this.new) NestedClass(); + } +} + +void main() { + auto outerObject = new OuterClass(); + + /* A member function of an outer class is returning a + * nested object: */ + auto nestedObject = outerObject.algorithm(); + + /* The nested object gets used in the program: */ + nestedObject.func(); + + /* Naturally, the context of nestedObject is the same as + * outerObject: */ + assert(nestedObject.context() is outerObject); +} +--- + +$(P +Instead of $(C this.new) and $(C this.outer), $(C .new) and $(C .outer) can be used on existing objects as well: +) + +--- + auto var = new OuterClass(); + auto nestedObject = $(HILITE var.new) OuterClass.NestedClass(); + auto var2 = $(HILITE nestedObject.outer); +--- + +$(H5 Summary) + +$(UL + +$(LI Functions, structs, and classes that are defined in inner scopes can access those scopes as their contexts.) + +$(LI Nested definitions keep their contexts alive to form closures.) + +$(LI Nested definitions are more costly than their module counterparts. When a nested definition does not need to access its context, this cost can be avoided by the $(C static) keyword.) + +$(LI Classes can be nested inside other classes. The context of such a nested object is the outer object itself. Nested class objects are constructed by $(C this.new) or $(C variable.new) and their contexts are available by $(C this.outer) or $(C variable.outer).) + +) + +Macros: + TITLE=Nested functions, structs, and classes + + DESCRIPTION=Defining functions, structs, and classes in nested scopes. + + KEYWORDS=d programming language tutorial book nested outer diff --git a/book/d.en/null_is.d b/book/d.en/null_is.d new file mode 100644 index 0000000000..be6069d622 --- /dev/null +++ b/book/d.en/null_is.d @@ -0,0 +1,285 @@ +Ddoc + +$(DERS_BOLUMU $(IX null) $(IX is, operator) $(IX !is) The $(CH4 null) Value and the $(CH4 is) Operator) + +$(P +We saw in earlier chapters that a variable of a reference type needs not reference a particular object: +) + +--- + MyClass referencesAnObject = new MyClass; + + MyClass variable; // does not reference an object +--- + +$(P +Being a reference type, $(C variable) above does have an identity but it does not reference any object yet. Such an object can be imagined to have a place in memory as in the following picture: +) + +$(MONO + variable + ───┬──────┬─── + │ null │ + ───┴──────┴─── +) + +$(P +A reference that does not reference any value is $(C null). We will expand on this below. +) + +$(P +Such a variable is in an almost useless state. Since there is no $(C MyClass) object that it references, it cannot be used in a context where an actual $(C MyClass) object is needed: +) + +--- +import std.stdio; + +class MyClass { + int member; +} + +void use(MyClass variable) { + writeln(variable.member); $(CODE_NOTE_WRONG BUG) +} + +void main() { + MyClass variable; + use(variable); +} +--- + +$(P +As there is no object that is referenced by the parameter that $(C use()) receives, attempting to access a member of a non-existing object results in a program crash: +) + +$(SHELL +$ ./deneme +$(SHELL_OBSERVED Segmentation fault) +) + +$(P +$(IX segmentation fault) "Segmentation fault" is an indication that the program has been terminated by the operating system because of attempting to access an illegal memory address. +) + +$(H5 The $(C null) value) + +$(P +The special value $(C null) can be printed just like any other value. +) + +--- + writeln(null); +--- + +$(P +The output: +) + +$(SHELL +null +) + +$(P +A $(C null) variable can be used only in two contexts: +) + +$(OL +$(LI Assigning an object to it + +--- + variable = new MyClass; // now references an object +--- + +$(P +The assignment above makes $(C variable) provide access to the newly constructed object. From that point on, $(C variable) can be used for any valid operation of the $(C MyClass) type. +) + +) + +$(LI Determining whether it is $(C null) + +$(P +However, because the $(C ==) operator needs actual objects to compare, the expression below cannot be compiled: +) + +--- + if (variable == null) $(DERLEME_HATASI) +--- + +$(P +For that reason, whether a variable is $(C null) must be determined by the $(C is) operator. +) + +) + +) + +$(H5 The $(C is) operator) + +$(P +This operator answers the question "does have the null value?": +) + +--- + if (variable $(HILITE is) null) { + // Does not reference any object + } +--- + +$(P +$(C is) can be used with other types of variables as well. In the following use, it compares the $(C values) of two integers: +) + +--- + if (speed is newSpeed) { + // Their values are equal + + } else { + // Their values are different + } +--- + +$(P +When used with slices, it determines whether the two slices reference the same set of elements: +) + +--- + if (slice is slice2) { + // They provide access to the same elements + } +--- + +$(H5 The $(C !is) operator) + +$(P +$(C !is) is the opposite of $(C is). It produces $(C true) when the values are different: +) + +--- + if (speed !is newSpeed) { + // Their values are different + } +--- + +$(H5 Assigning the $(C null) value) + +$(P +Assigning the $(C null) value to a variable of a reference type makes that variable stop referencing its current object. +) + +$(P +If that assignment happens to be terminating the very last reference to the actual object, then the actual object becomes a candidate for finalization by the garbage collector. After all, not being referenced by any variable means that the object is not being used in the program at all. +) + +$(P +Let's look at the example from $(LINK2 value_vs_reference.html, an earlier chapter) where two variables were referencing the same object: +) + +--- + auto variable = new MyClass; + auto variable2 = variable; +--- + +$(P +The following is a representation of the state of the memory after executing that code: +) + +$(MONO + (anonymous MyClass object) variable variable2 + ───┬───────────────────┬─── ───┬───┬─── ───┬───┬─── + │ ... │ │ o │ │ o │ + ───┴───────────────────┴─── ───┴─│─┴─── ───┴─│─┴─── + ▲ │ │ + │ │ │ + └────────────────────┴────────────┘ +) + +$(P +Assigning the $(C null) value to one of these variables breaks its relationship with the object: +) + +--- + variable = null; +--- + +$(P +At this point there is only $(C variable2) that references the $(C MyClass) object: +) + +$(MONO + (anonymous MyClass object) variable variable2 + ───┬───────────────────┬─── ───┬────┬─── ───┬───┬─── + │ ... │ │null│ │ o │ + ───┴───────────────────┴─── ───┴────┴─── ───┴─│─┴─── + ▲ │ + │ │ + └──────────────────────────────────┘ +) + +$(P +Assigning $(C null) to the last reference would make the $(C MyClass) object unreachable: +) + +--- + variable2 = null; +--- + +$(P +Such unreachable objects are finalized by the garbage collector at some time in the future. From the point of view of the program, the object does not exist: +) + +$(MONO + variable variable2 + ───┬───────────────────┬─── ───┬────┬─── ───┬────┬─── + │ │ │null│ │null│ + ───┴───────────────────┴─── ───┴────┴─── ───┴────┴── +) + +$(P +We had discussed ways of emptying an associative array in the exercises section of the $(LINK2 aa.html, Associative Arrays chapter). We now know a fourth method: Assigning $(C null) to an associative array variable will break the relationship of that variable with the elements: +) + +--- + string[int] names; + // ... + names = null; // Not providing access to any element +--- + +$(P +Similar to the $(C MyClass) examples, if $(C names) has been the last reference to the elements of the associative array, those elements would be finalized by the garbage collector. +) + +$(P +Slices can be assigned $(C null) as well: +) + +--- + int[] slice = otherSlice[ 10 .. 20 ]; + // ... + slice = null; // Not providing access to any element +--- + +$(H5 Summary) + +$(UL + +$(LI $(C null) is the value indicating that a variable does not provide access to any value) + +$(LI References that have the $(C null) value can only be used in two operations: assigning a value to them and determining whether they are $(C null) or not) + +$(LI Since the $(C ==) operator may have to access an actual object, determining whether a variable is $(C null) must be performed by the $(C is) operator) + +$(LI $(C !is) is the opposite of $(C is)) + +$(LI Assigning $(C null) to a variable makes that variable provide access to nothing) + +$(LI Objects that are not referenced by any variable are finalized by the garbage collector) + +) + +Macros: + TITLE=The null Value and the is Operator + + DESCRIPTION=The 'null' value of the D programming language and the operators 'is' and '!is' that determine whether variables are null or not. + + KEYWORDS=d programming language tutorial book object referencee null is !is diff --git a/book/d.en/object.cozum.d b/book/d.en/object.cozum.d new file mode 100644 index 0000000000..e81d3080d8 --- /dev/null +++ b/book/d.en/object.cozum.d @@ -0,0 +1,108 @@ +Ddoc + +$(COZUM_BOLUMU $(CH4 Object)) + +$(OL + +$(LI +For the equality comparison, $(C rhs) being non-$(C null) and the members being equal would be sufficient: + +--- +enum Color { blue, green, red } + +class Point { + int x; + int y; + Color color; + +// ... + + override bool opEquals(Object o) const { + const rhs = cast(const Point)o; + + return rhs && (x == rhs.x) && (y == rhs.y); + } +} +--- + +) + +$(LI +When the type of the right-hand side object is also $(C Point), they are compared according to the values of the $(C x) members first and then according to the values of the $(C y) members: + +--- +class Point { + int x; + int y; + Color color; + +// ... + + override int opCmp(Object o) const { + const rhs = cast(const Point)o; + enforce(rhs); + + return (x != rhs.x + ? x - rhs.x + : y - rhs.y); + } +} +--- + +) + +$(LI +Note that it is not possible to cast to type $(C const TriangularArea) inside $(C opCmp) below. When $(C rhs) is $(C const TriangularArea), then its member $(C rhs.points) would be $(C const) as well. Since the parameter of $(C opCmp) is non-$(C const), it would not be possible to pass $(C rhs.points[i]) to $(C point.opCmp). + +--- +class TriangularArea { + Point[3] points; + + this(Point one, Point two, Point three) { + points = [ one, two, three ]; + } + + override bool opEquals(Object o) const { + const rhs = cast(const TriangularArea)o; + return rhs && (points == rhs.points); + } + + override int opCmp(Object o) const { + $(HILITE auto) rhs = $(HILITE cast(TriangularArea))o; + enforce(rhs); + + foreach (i, point; points) { + immutable comparison = point.opCmp(rhs.points[i]); + + if (comparison != 0) { + /* The sort order has already been + * determined. Simply return the result. */ + return comparison; + } + } + + /* The objects are considered equal because all of + * their points have been equal. */ + return 0; + } + + override size_t toHash() const { + /* Since the 'points' member is an array, we can take + * advantage of the existing toHash algorithm for + * array types. */ + return typeid(points).getHash(&points); + } +} +--- + +) + +) + + +Macros: + TITLE=Object Solutions + + DESCRIPTION=Programming in D exercise solutions: Object + + KEYWORDS=programming in d tutorial Object diff --git a/book/d.en/object.d b/book/d.en/object.d new file mode 100644 index 0000000000..779281f5f2 --- /dev/null +++ b/book/d.en/object.d @@ -0,0 +1,866 @@ +Ddoc + +$(DERS_BOLUMU $(IX Object) $(CH4 Object)) + +$(P +Classes that do not explicitly inherit any class, automatically inherit the $(C Object) class. +) + +$(P +By that definition, the topmost class in any class hierarchy inherits $(C Object): +) + +--- +// ": Object" is not written; it is automatic +class MusicalInstrument $(DEL : Object ) { + // ... +} + +// Inherits Object indirectly +class StringInstrument : MusicalInstrument { + // ... +} +--- + +$(P +Since the topmost class inherits $(C Object), every class indirectly inherits $(C Object) as well. In that sense, every class "is an" $(C Object). +) + +$(P +Every class inherits the following member functions of $(C Object): +) + +$(UL +$(LI $(C toString): The $(C string) representation of the object.) +$(LI $(C opEquals): Equality comparison with another object.) +$(LI $(C opCmp): Sort order comparison with another object.) +$(LI $(C toHash): Associative array hash value.) +) + +$(P +The last three of these functions emphasize the values of objects. They also make a class eligible for being the key type of associative arrays. +) + +$(P +Because these functions are inherited, their redefinitions for the subclasses require the $(C override) keyword. +) + +$(P $(I $(B Note:) $(C Object) defines other members as well. This chapter will include only those four member functions of it.) +) + +$(H5 $(IX typeid) $(IX TypeInfo) $(C typeid) and $(C TypeInfo)) + +$(P +$(C Object) is defined in the $(LINK2 http://dlang.org/phobos/object.html, $(C object) module) (which is not a part of the $(C std) package). The $(C object) module defines $(C TypeInfo) as well, a class that provides information about types. Every type has a distinct $(C TypeInfo) object. The $(C typeid) $(I expression) provides access to the $(C TypeInfo) object that is associated with a particular type. As we will see later below, the $(C TypeInfo) class can be used for determining whether two types are the same, as well as for accessing special functions of a type ($(C toHash), $(C postblit), etc., most of which are not covered in this book). +) + +$(P +$(C TypeInfo) is always about the actual run-time type. For example, although both $(C Violin) and $(C Guitar) below inherit $(C StringInstrument) directly and $(C MusicalInstrument) indirectly, the $(C TypeInfo) instances of $(C Violin) and $(C Guitar) are different. They are exactly for $(C Violin) and $(C Guitar) types, respectively: +) + +--- +class MusicalInstrument { +} + +class StringInstrument : MusicalInstrument { +} + +class Violin : StringInstrument { +} + +class Guitar : StringInstrument { +} + +void main() { + TypeInfo v = $(HILITE typeid)(Violin); + TypeInfo g = $(HILITE typeid)(Guitar); + assert(v != g); $(CODE_NOTE the two types are not the same) +} +--- + +$(P +The $(C typeid) expressions above are being used with $(I types) like $(C Violin) itself. $(C typeid) can take an $(I expression) as well, in which case it returns the $(C TypeInfo) object for the run-time type of that expression. For example, the following function takes two parameters of different but related types: +) + +--- +import std.stdio; + +// ... + +void foo($(HILITE MusicalInstrument) m, $(HILITE StringInstrument) s) { + const isSame = (typeid(m) == typeid(s)); + + writefln("The types of the arguments are %s.", + isSame ? "the same" : "different"); +} + +// ... + + auto a = new $(HILITE Violin)(); + auto b = new $(HILITE Violin)(); + foo(a, b); +--- + +$(P +Since both arguments to $(C foo()) are two $(C Violin) objects for that particular call, $(C foo()) determines that their types are the same: +) + +$(SHELL +The types of the arguments are $(HILITE the same). +) + +$(P +Unlike $(C .sizeof) and $(C typeof), which never execute their expressions, $(C typeid) always executes the expression that it receives: +) + +--- +import std.stdio; + +int foo(string when) { + writefln("Called during '%s'.", when); + return 0; +} + +void main() { + const s = foo("sizeof")$(HILITE .sizeof); // foo() is not called + alias T = $(HILITE typeof)(foo("typeof")); // foo() is not called + auto ti = $(HILITE typeid)(foo("typeid")); // foo() is called +} +--- + +$(P +The output indicates that only the expression of $(C typeid) is executed: +) + +$(SHELL +Called during 'typeid'. +) + +$(P +The reason for this difference is because actual run-time types of expressions may not be known until those expressions are executed. For example, the exact return type of the following function would be either $(C Violin) or $(C Guitar) depending on the value of function argument $(C i): +) + +--- +MusicalInstrument foo(int i) { + return ($(HILITE i) % 2) ? new Violin() : new Guitar(); +} +--- + +$(P +$(IX TypeInfo_Class) $(IX .classinfo) There are various subclasses of $(C TypeInfo) for various kinds of types like arrays, structs, classes, etc. Of these, $(C TypeInfo_Class) can be particularly useful. For example, the name of the run-time type of an object can be obtained through its $(C TypeInfo_Class.name) property as a $(C string). You can access the $(C TypeInfo_Class) instance of an object by its $(C .classinfo) property: +) + +--- + TypeInfo_Class info = a$(HILITE .classinfo); + string runtimeTypeName = info$(HILITE .name); +--- + +$(H5 $(IX toString) $(C toString)) + +$(P +Same with structs, $(C toString) enables using class objects as strings: +) + +--- + auto clock = new Clock(20, 30, 0); + writeln(clock); // Calls clock.toString() +--- + +$(P +The inherited $(C toString()) is usually not useful; it produces just the name of the type: +) + +$(SHELL +deneme.Clock +) + +$(P +The part before the name of the type is the name of the module. The output above indicates that $(C Clock) has been defined in the $(C deneme) module. +) + +$(P +As we have seen in the previous chapter, this function is almost always overridden to produce a more meaningful $(C string) representation: +) + +--- +import std.string; + +class Clock { + override string toString() const { + return format("%02s:%02s:%02s", hour, minute, second); + } + + // ... +} + +class AlarmClock : Clock { + override string toString() const { + return format("%s ♫%02s:%02s", super.toString(), + alarmHour, alarmMinute); + } + + // ... +} + +// ... + + auto bedSideClock = new AlarmClock(20, 30, 0, 7, 0); + writeln(bedSideClock); +--- + +$(P +The output: +) + +$(SHELL +20:30:00 ♫07:00 +) + +$(H5 $(IX opEquals) $(C opEquals)) + +$(P +As we have seen in the $(LINK2 operator_overloading.html, Operator Overloading chapter), this member function is about the behavior of the $(C ==) operator (and the $(C !=) operator indirectly). The return value of the operator must be $(C true) if the objects are considered to be equal and $(C false) otherwise. +) + +$(P +$(B Warning:) The definition of this function must be consistent with $(C opCmp()); for two objects that $(C opEquals()) returns $(C true), $(C opCmp()) must return zero. +) + +$(P +Contrary to structs, the compiler does not call $(C a.opEquals(b)) right away when it sees the expression $(C a == b). When two class objects are compared by the $(C ==) operator, a four-step algorithm is executed: +) + +--- +bool opEquals(Object a, Object b) { + if (a is b) return true; // (1) + if (a is null || b is null) return false; // (2) + if (typeid(a) == typeid(b)) return a.opEquals(b); // (3) + return a.opEquals(b) && b.opEquals(a); // (4) +} +--- + +$(OL + +$(LI If the two variables provide access to the same object (or they are both $(C null)), then they are equal.) + +$(LI Following from the previous check, if only one is $(C null) then they are not equal.) + +$(LI If both of the objects are of the same type, then $(C a.opEquals(b)) is called to determine the equality.) + +$(LI Otherwise, for the two objects to be considered equal, $(C opEquals) must have been defined for both of their types and $(C a.opEquals(b)) and $(C b.opEquals(a)) must agree that the objects are equal.) + +) + +$(P +Accordingly, if $(C opEquals()) is not provided for a class type, then the values of the objects are not considered; rather, equality is determined by checking whether the two class variables provide access to the same object: +) + +--- + auto variable0 = new Clock(6, 7, 8); + auto variable1 = new Clock(6, 7, 8); + + assert(variable0 != variable1); // They are not equal + // because the objects are + // different +--- + +$(P +Even though the two objects are constructed by the same arguments above, the variables are not equal because they are not associated with the same object. +) + +$(P +On the other hand, because the following two variables provide access to the same object, they are $(I equal): +) + +--- + auto partner0 = new Clock(9, 10, 11); + auto partner1 = partner0; + + assert(partner0 == partner1); // They are equal because + // the object is the same +--- + +$(P +Sometimes it makes more sense to compare objects by their values instead of their identities. For example, it is conceivable that $(C variable0) and $(C variable1) above compare equal because their values are the same. +) + +$(P +Different from structs, the type of the parameter of $(C opEquals) for classes is $(C Object): +) + +--- +class Clock { + override bool opEquals($(HILITE Object o)) const { + // ... + } + + // ... +} +--- + +$(P +As you will see below, the parameter is almost never used directly. For that reason, it should be acceptable to name it simply as $(C o). Most of the time the first thing to do with that parameter is to use it in a type conversion. +) + +$(P +The parameter of $(C opEquals) is the object that appears on the right-hand side of the $(C ==) operator: +) + +--- + variable0 == variable1; // o represents variable1 +--- + +$(P +Since the purpose of $(C opEquals()) is to compare two objects of this class type, the first thing to do is to convert $(C o) to a variable of the same type of this class. Since it would not be appropriate to modify the right-hand side object in an equality comparison, it is also proper to convert the type as $(C const): +) + +--- + override bool opEquals(Object o) const { + auto rhs = cast(const Clock)o; + + // ... + } +--- + +$(P +As you would remember, $(C rhs) is a common abbreviation for $(I right-hand side). Also, $(C std.conv.to) can be used for the conversion as well: +) + +--- +import std.conv; +// ... + auto rhs = to!(const Clock)(o); +--- + +$(P +If the original object on the right-hand side can be converted to $(C Clock), then $(C rhs) becomes a non-$(C null) class variable. Otherwise, $(C rhs) is set to $(C null), indicating that the objects are not of the same type. +) + +$(P +According to the design of a program, it may make sense to compare objects of two incompatible types. I will assume here that for the comparison to be valid, $(C rhs) must not be $(C null); so, the first logical expression in the following $(C return) statement checks that it is not $(C null). Otherwise, it would be an error to try to access the members of $(C rhs): +) + +--- +class Clock { + int hour; + int minute; + int second; + + override bool opEquals(Object o) const { + auto rhs = cast(const Clock)o; + + return ($(HILITE rhs) && + (hour == rhs.hour) && + (minute == rhs.minute) && + (second == rhs.second)); + } + + // ... +} +--- + +$(P +With that definition, $(C Clock) objects can now be compared by their values: +) + +--- + auto variable0 = new Clock(6, 7, 8); + auto variable1 = new Clock(6, 7, 8); + + assert(variable0 == variable1); // Now they are equal + // because their values + // are equal +--- + +$(P +When defining $(C opEquals) it is important to remember the members of the superclass. For example, when comparing objects of $(C AlarmClock) it would make sense to also consider the inherited members: +) + +--- +class AlarmClock : Clock { + int alarmHour; + int alarmMinute; + + override bool opEquals(Object o) const { + auto rhs = cast(const AlarmClock)o; + + return (rhs && + (alarmHour == rhs.alarmHour) && + (alarmMinute == rhs.alarmMinute) && + $(HILITE super.opEquals(o))); + } + + // ... +} +--- + +$(P +That expression could be written as $(C super == o) as well. However, that would initiate the four-step algorithm again and as a result, the code might be a little slower. +) + +$(H5 $(IX opCmp) $(C opCmp)) + +$(P +This operator is used when sorting class objects. $(C opCmp) is the function that gets called behind the scenes for the $(C <), $(C <=), $(C >), and $(C >=). +) + +$(P +This operator must return a negative value when the left-hand object is before, a positive value when the left-hand object is after, and zero when both objects have the same sorting order. +) + +$(P +$(B Warning:) The definition of this function must be consistent with $(C opEquals()); for two objects that $(C opEquals()) returns $(C true), $(C opCmp()) must return zero. +) + +$(P +Unlike $(C toString) and $(C opEquals), there is no default implementation of this function in $(C Object). If the implementation is not available, comparing objects for sort order causes an exception to be thrown: +) + +--- + auto variable0 = new Clock(6, 7, 8); + auto variable1 = new Clock(6, 7, 8); + + assert(variable0 <= variable1); $(CODE_NOTE Causes exception) +--- + +$(SHELL +object.Exception: need opCmp for class deneme.Clock +) + +$(P +It is up to the design of the program what happens when the left-hand and right-hand objects are of different types. One way is to take advantage of the order of types that is maintained by the compiler automatically. This is achieved by calling the $(C opCmp) function on the $(C typeid) values of the two types: +) + +--- +class Clock { + int hour; + int minute; + int second; + + override int opCmp(Object o) const { + /* Taking advantage of the automatically-maintained + * order of the types. */ + if (typeid(this) != typeid(o)) { + return typeid(this).opCmp(typeid(o)); + } + + auto rhs = cast(const Clock)o; + /* No need to check whether rhs is null, because it is + * known at this line that it has the same type as o. */ + + if (hour != rhs.hour) { + return hour - rhs.hour; + + } else if (minute != rhs.minute) { + return minute - rhs.minute; + + } else { + return second - rhs.second; + } + } + + // ... +} +--- + +$(P +The definition above first checks whether the types of the two objects are the same. If not, it uses the ordering of the types themselves. Otherwise, it compares the objects by the values of their $(C hour), $(C minute), and $(C second) members. +) + +$(P +A chain of ternary operators may also be used: +) + +--- + override int opCmp(Object o) const { + if (typeid(this) != typeid(o)) { + return typeid(this).opCmp(typeid(o)); + } + + auto rhs = cast(const Clock)o; + + return (hour != rhs.hour + ? hour - rhs.hour + : (minute != rhs.minute + ? minute - rhs.minute + : second - rhs.second)); + } +--- + +$(P +If important, the comparison of the members of the superclass must also be considered. The following $(C AlarmClock.opCmp) is calling $(C Clock.opCmp) first: +) + +--- +class AlarmClock : Clock { + override int opCmp(Object o) const { + auto rhs = cast(const AlarmClock)o; + + const int superResult = $(HILITE super.opCmp(o)); + + if (superResult != 0) { + return superResult; + + } else if (alarmHour != rhs.alarmHour) { + return alarmHour - rhs.alarmHour; + + } else { + return alarmMinute - rhs.alarmMinute; + } + } + + // ... +} +--- + +$(P +Above, if the superclass comparison returns a nonzero value then that result is used because the sort order of the objects is already determined by that value. +) + +$(P +$(C AlarmClock) objects can now be compared for their sort orders: +) + +--- + auto ac0 = new AlarmClock(8, 0, 0, 6, 30); + auto ac1 = new AlarmClock(8, 0, 0, 6, 31); + + assert(ac0 < ac1); +--- + +$(P +$(C opCmp) is used by other language features and libraries as well. For example, the $(C sort()) function takes advantage of $(C opCmp) when sorting elements. +) + +$(H6 $(C opCmp) for string members) + +$(P +When some of the members are strings, they can be compared explicitly to return a negative, positive, or zero value: +) + +--- +import std.exception; + +class Student { + string name; + + override int opCmp(Object o) const { + auto rhs = cast(Student)o; + enforce(rhs); + + if (name < rhs.name) { + return -1; + + } else if (name > rhs.name) { + return 1; + + } else { + return 0; + } + } + + // ... +} +--- + +$(P +Instead, the existing $(C std.algorithm.cmp) function can be used, which happens to be faster as well: +) + +--- +import std.algorithm; + +class Student { + string name; + + override int opCmp(Object o) const { + auto rhs = cast(Student)o; + enforce(rhs); + + return cmp(name, rhs.name); + } + + // ... +} +--- + +$(P +Also note that $(C Student) does not support comparing incompatible types by enforcing that the conversion from $(C Object) to $(C Student) is possible. +) + +$(H5 $(IX toHash) $(C toHash)) + +$(P +This function allows objects of a class type to be used as associative array $(I keys). It does not affect the cases where the type is used as associative array $(I values). If this function is defined, $(C opEquals) must be defined as well. +) + +$(H6 $(IX hash table) Hash table indexes) + +$(P +Associative arrays are a hash table implementation. Hash table is a very fast data structure when it comes to searching elements in the table. ($(I Note: Like most other things in software, this speed comes at a cost: Hash tables must keep elements in an unordered way, and they may be taking up space that is more than exactly necessary.)) +) + +$(P +The high speed of hash tables comes from the fact that they first produce integer values for keys. These integers are called $(I hash values). The hash values are then used for indexing into an internal array that is maintained by the table. +) + +$(P +A benefit of this method is that any type that can produce unique integer values for its objects can be used as the key type of associative arrays. $(C toHash) is the function that returns the hash value for an object. +) + +$(P +Even $(C Clock) objects can be used as associative array key values: +) + +--- + string[$(HILITE Clock)] timeTags; + timeTags[new Clock(12, 0, 0)] = "Noon"; +--- + +$(P +The default definition of $(C toHash) that is inherited from $(C Clock) produces different hash values for different objects without regard to their values. This is similar to how the default behavior of $(C opEquals) considers different objects as being not equal. +) + +$(P +The code above compiles and runs even when there is no special definition of $(C toHash) for $(C Clock). However, its default behavior is almost never what is desired. To see that default behavior, let's try to access an element by an object that is different from the one that has been used when inserting the element. Although the new $(C Clock) object below has the same value as the $(C Clock) object that has been used when inserting into the associative array above, the value cannot be found: +) + +--- + if (new Clock(12, 0, 0) in timeTags) { + writeln("Exists"); + + } else { + writeln("Missing"); + } +--- + +$(P +According to the $(C in) operator, there is no element in the table that corresponds to the value $(C Clock(12, 0, 0)): +) + +$(SHELL +Missing +) + +$(P +The reason for this surprising behavior is that the key object that has been used when inserting the element is not the same as the key object that has been used when accessing the element. +) + +$(H6 Selecting members for $(C toHash)) + +$(P +Although the hash value is calculated from the members of an object, not every member is suitable for this task. +) + +$(P +The candidates are the members that distinguish objects from each other. For example, the members $(C name) and $(C lastName) of a $(C Student) class would be suitable if those members can be used for identifying objects of that type. +) + +$(P +On the other hand, a $(C grades) array of a $(C Student) class would not be suitable both because many objects may have the same array and also it is likely that the $(C grades) array may change over time. +) + +$(H6 Calculating hash values) + +$(P +The choice of hash values has a direct effect on the performance of associative arrays. Furthermore, a hash calculation that is effective on one type of data may not be as effective on another type of data. As $(I hash algorithms) are beyond the scope of this book, I will give just one guideline here: In general, it is better to produce different hash values for objects that are considered to have different values. However, it is not an error if two objects with different values produce the same index value; it is merely undesirable for performance reasons. +) + +$(P +It is conceivable that all of the members of $(C Clock) are significant to distinguish its objects from each other. For that reason, the hash values can be calculated from the values of its three members. $(I The number of seconds since midnight) would be effective hash values for objects that represent different points in time: +) + +--- +class Clock { + int hour; + int minute; + int second; + + override size_t toHash() const { + /* Because there are 3600 seconds in an hour and 60 + * seconds in a minute: */ + return (3600 * hour) + (60 * minute) + second; + } + + // ... +} +--- + +$(P +Whenever $(C Clock) is used as the key type of associative arrays, that special definition of $(C toHash) would be used. As a result, even though the two key objects of $(C Clock(12, 0, 0)) above are distinct, they would now produce the same hash value. +) + +$(P +The new output: +) + +$(SHELL +Exists +) + +$(P +Similar to the other member functions, the superclass may need to be considered as well. For example, $(C AlarmClock.toHash) can take advantage of $(C Clock.toHash) during its index calculation: +) + +--- +class AlarmClock : Clock { + int alarmHour; + int alarmMinute; + + override size_t toHash() const { + return $(HILITE super.toHash()) + alarmHour + alarmMinute; + } + + // ... +} +--- + +$(P +$(I $(B Note:) Take the calculation above just as an example. In general, adding integer values is not an effective way of generating hash values.) +) + +$(P +There are existing efficient algorithms for calculating hash values for variables of floating point, array, and struct types. These algorithms are available to the programmer as well. +) + +$(P +$(IX getHash) What needs to be done is to call $(C getHash()) on the $(C typeid) of each member. The syntax of this method is the same for floating point, array, and struct types. +) + +$(P +For example, hash values of a $(C Student) type can be calculated from its $(C name) member as in the following code: +) + +--- +class Student { + string name; + + override size_t toHash() const { + return typeid(name).getHash(&name); + } + + // ... +} +--- + +$(H6 Hash values for structs) + +$(P +Since structs are value types, hash values for their objects are calculated automatically by an efficient algorithm. That algorithm takes all of the members of the object into consideration. +) + +$(P +When there is a specific reason like needing to exclude certain members from the hash calculation, $(C toHash()) can be overridden for structs as well. +) + +$(PROBLEM_COK + +$(PROBLEM +Start with the following class, which represents colored points: + +--- +enum Color { blue, green, red } + +class Point { + int x; + int y; + Color color; + + this(int x, int y, Color color) { + this.x = x; + this.y = y; + this.color = color; + } +} +--- + +$(P +Implement $(C opEquals) for this class in a way that ignores colors. When implemented in that way, the following $(C assert) check should pass: +) + +--- + // Different colors + auto bluePoint = new Point(1, 2, Color.blue); + auto greenPoint = new Point(1, 2, Color.green); + + // They are still equal + assert(bluePoint == greenPoint); +--- + +) + +$(PROBLEM +Implement $(C opCmp) by considering first $(C x) then $(C y). The following $(C assert) checks should pass: + +--- + auto redPoint1 = new Point(-1, 10, Color.red); + auto redPoint2 = new Point(-2, 10, Color.red); + auto redPoint3 = new Point(-2, 7, Color.red); + + assert(redPoint1 < bluePoint); + assert(redPoint3 < redPoint2); + + /* Even though blue is before green in enum Color, + * because color is being ignored, bluePoint must not be + * before greenPoint. */ + assert(!(bluePoint < greenPoint)); +--- + +$(P +Like the $(C Student) class above, you can implement $(C opCmp) by excluding incompatible types by the help of $(C enforce). +) + +) + +$(PROBLEM +Consider the following class that combines three $(C Point) objects in an array: + +--- +class TriangularArea { + Point[3] points; + + this(Point one, Point two, Point three) { + points = [ one, two, three ]; + } +} +--- + +$(P +Implement $(C toHash) for that class. Again, the following $(C assert) checks should pass: +) + +--- + /* area1 and area2 are constructed by distinct points that + * happen to have the same values. (Remember that + * bluePoint and greenPoint should be considered equal.) */ + auto area1 = new TriangularArea(bluePoint, greenPoint, redPoint1); + auto area2 = new TriangularArea(greenPoint, bluePoint, redPoint1); + + // The areas should be equal + assert(area1 == area2); + + // An associative array + double[TriangularArea] areas; + + // A value is being entered by area1 + areas[area1] = 1.25; + + // The value is being accessed by area2 + assert(area2 in areas); + assert(areas[area2] == 1.25); +--- + +$(P +Remember that $(C opEquals) must also be defined when $(C toHash) is defined. +) + +) + +) + +Macros: + TITLE=Object + + DESCRIPTION=Object, the topmost class in class hierarchies in the D programming language + + KEYWORDS=d programming lesson book tutorial class Object opEquals opCmp toHash toString diff --git a/book/d.en/operator_overloading.cozum.d b/book/d.en/operator_overloading.cozum.d new file mode 100644 index 0000000000..89291c413c --- /dev/null +++ b/book/d.en/operator_overloading.cozum.d @@ -0,0 +1,297 @@ +Ddoc + +$(COZUM_BOLUMU Operator Overloading) + +$(P +The following implementation passes all of the unit tests. The design decisions have been included as code comments. +) + +$(P +Some of the functions of this struct can be implemented to run more efficiently. Additionally, it would be beneficial to also $(I normalize) the numerator and denominator. For example, instead of keeping the values 20 and 60, the values could be divided by their $(I greatest common divisor) and the numerator and the denominator can be stored as 1 and 3 instead. Otherwise, most of the operations on the object would cause the values of the numerator and the denominator to increase. +) + +--- +import std.exception; +import std.conv; + +struct Fraction { + long num; // numerator + long den; // denominator + + /* As a convenience, the constructor uses the default + * value of 1 for the denominator. */ + this(long num, long den = 1) { + enforce(den != 0, "The denominator cannot be zero"); + + this.num = num; + this.den = den; + + /* Ensuring that the denominator is always positive + * will simplify the definitions of some of the + * operator functions. */ + if (this.den < 0) { + this.num = -this.num; + this.den = -this.den; + } + } + + /* Unary -: Returns the negative of this fraction. */ + Fraction opUnary(string op)() const + if (op == "-") { + /* Simply constructs and returns an anonymous + * object. */ + return Fraction(-num, den); + } + + /* ++: Increments the value of the fraction by one. */ + ref Fraction opUnary(string op)() + if (op == "++") { + /* We could have used 'this += Fraction(1)' here. */ + num += den; + return this; + } + + /* --: Decrements the value of the fraction by one. */ + ref Fraction opUnary(string op)() + if (op == "--") { + /* We could have used 'this -= Fraction(1)' here. */ + num -= den; + return this; + } + + /* +=: Adds the right-hand fraction to this one. */ + ref Fraction opOpAssign(string op)(Fraction rhs) + if (op == "+") { + /* Addition formula: a/b + c/d = (a*d + c*b)/(b*d) */ + num = (num * rhs.den) + (rhs.num * den); + den *= rhs.den; + return this; + } + + /* -=: Subtracts the right-hand fraction from this one. */ + ref Fraction opOpAssign(string op)(Fraction rhs) + if (op == "-") { + /* We make use of the already-defined operators += and + * unary - here. Alternatively, the subtraction + * formula could explicitly be applied similar to the + * += operator above. + * + * Subtraction formula: a/b - c/d = (a*d - c*b)/(b*d) + */ + this += -rhs; + return this; + } + + /* *=: Multiplies the fraction by the right-hand side. */ + ref Fraction opOpAssign(string op)(Fraction rhs) + if (op == "*") { + /* Multiplication formula: a/b * c/d = (a*c)/(b*d) */ + num *= rhs.num; + den *= rhs.den; + return this; + } + + /* /=: Divides the fraction by the right-hand side. */ + ref Fraction opOpAssign(string op)(Fraction rhs) + if (op == "/") { + enforce(rhs.num != 0, "Cannot divide by zero"); + + /* Division formula: (a/b) / (c/d) = (a*d)/(b*c) */ + num *= rhs.den; + den *= rhs.num; + return this; + } + + /* Binary +: Produces the result of adding this and the + * right-hand side fractions. */ + Fraction opBinary(string op)(Fraction rhs) const + if (op == "+") { + /* Takes a copy of this fraction and adds the + * right-hand side fraction to that copy. */ + Fraction result = this; + result += rhs; + return result; + } + + /* Binary -: Produces the result of subtracting the + * right-hand side fraction from this one. */ + Fraction opBinary(string op)(Fraction rhs) const + if (op == "-") { + /* Uses the already-defined -= operator. */ + Fraction result = this; + result -= rhs; + return result; + } + + /* Binary *: Produces the result of multiplying this + * fraction with the right-hand side fraction. */ + Fraction opBinary(string op)(Fraction rhs) const + if (op == "*") { + /* Uses the already-defined *= operator. */ + Fraction result = this; + result *= rhs; + return result; + } + + /* Binary /: Produces the result of dividing this fraction + * by the right-hand side fraction. */ + Fraction opBinary(string op)(Fraction rhs) const + if (op == "/") { + /* Uses the already-defined /= operator. */ + Fraction result = this; + result /= rhs; + return result; + } + + /* Returns the value of the fraction as double. */ + double opCast(T : double)() const { + /* A simple division. However, as dividing values of + * type long would lose the part of the value after + * the decimal point, we could not have written + * 'num/den' here. */ + return to!double(num) / den; + } + + /* Sort order operator: Returns a negative value if this + * fraction is before, a positive value if this fraction + * is after, and zero if both fractions have the same sort + * order. */ + int opCmp(const Fraction rhs) const { + immutable result = this - rhs; + /* Being a long, num cannot be converted to int + * automatically; it must be converted explicitly by + * 'to' (or cast). */ + return to!int(result.num); + } + + /* Equality comparison: Returns true if the fractions are + * equal. + * + * The equality comparison had to be defined for this type + * because the compiler-generated one would be comparing + * the members one-by-one, without regard to the actual + * values that the objects represent. + * + * For example, although the values of both Fraction(1,2) + * and Fraction(2,4) are 0.5, the compiler-generated + * opEquals would decide that they were not equal on + * account of having members of different values. */ + bool opEquals(const Fraction rhs) const { + /* Checking whether the return value of opCmp is zero + * is sufficient here. */ + return opCmp(rhs) == 0; + } +} + +unittest { + /* Must throw when denominator is zero. */ + assertThrown(Fraction(42, 0)); + + /* Let's start with 1/3. */ + auto a = Fraction(1, 3); + + /* -1/3 */ + assert(-a == Fraction(-1, 3)); + + /* 1/3 + 1 == 4/3 */ + ++a; + assert(a == Fraction(4, 3)); + + /* 4/3 - 1 == 1/3 */ + --a; + assert(a == Fraction(1, 3)); + + /* 1/3 + 2/3 == 3/3 */ + a += Fraction(2, 3); + assert(a == Fraction(1)); + + /* 3/3 - 2/3 == 1/3 */ + a -= Fraction(2, 3); + assert(a == Fraction(1, 3)); + + /* 1/3 * 8 == 8/3 */ + a *= Fraction(8); + assert(a == Fraction(8, 3)); + + /* 8/3 / 16/9 == 3/2 */ + a /= Fraction(16, 9); + assert(a == Fraction(3, 2)); + + /* Must produce the equivalent value in type 'double'. + * + * Note that although double cannot represent every value + * precisely, 1.5 is an exception. That is why this test + * is being applied at this point. */ + assert(to!double(a) == 1.5); + + /* 1.5 + 2.5 == 4 */ + assert(a + Fraction(5, 2) == Fraction(4, 1)); + + /* 1.5 - 0.75 == 0.75 */ + assert(a - Fraction(3, 4) == Fraction(3, 4)); + + /* 1.5 * 10 == 15 */ + assert(a * Fraction(10) == Fraction(15, 1)); + + /* 1.5 / 4 == 3/8 */ + assert(a / Fraction(4) == Fraction(3, 8)); + + /* Must throw when dividing by zero. */ + assertThrown(Fraction(42, 1) / Fraction(0)); + + /* The one with lower numerator is before. */ + assert(Fraction(3, 5) < Fraction(4, 5)); + + /* The one with larger denominator is before. */ + assert(Fraction(3, 9) < Fraction(3, 8)); + assert(Fraction(1, 1_000) > Fraction(1, 10_000)); + + /* The one with lower value is before. */ + assert(Fraction(10, 100) < Fraction(1, 2)); + + /* The one with negative value is before. */ + assert(Fraction(-1, 2) < Fraction(0)); + assert(Fraction(1, -2) < Fraction(0)); + + /* The ones with equal values must be both <= and >=. */ + assert(Fraction(-1, -2) <= Fraction(1, 2)); + assert(Fraction(1, 2) <= Fraction(-1, -2)); + assert(Fraction(3, 7) <= Fraction(9, 21)); + assert(Fraction(3, 7) >= Fraction(9, 21)); + + /* The ones with equal values must be equal. */ + assert(Fraction(1, 3) == Fraction(20, 60)); + + /* The ones with equal values with sign must be equal. */ + assert(Fraction(-1, 2) == Fraction(1, -2)); + assert(Fraction(1, 2) == Fraction(-1, -2)); +} + +void main() { +} +--- + +$(P +As has been mentioned in the chapter, string mixins can be used to combine the definitions of some of the operators. For example, the following definition covers the four arithmetic operators: +) + +--- + /* Binary arithmetic operators. */ + Fraction opBinary(string op)(Fraction rhs) const + if ((op == "+") || (op == "-") || + (op == "*") || (op == "/")) { + /* Takes a copy of this fraction and applies the + * right-hand side fraction to that copy. */ + Fraction result = this; + mixin ("result " ~ op ~ "= rhs;"); + return result; + } +--- + + +Macros: + TITLE=Operator Overloading Solution + + DESCRIPTION=Programming in D exercise solutions: operators overloading + + KEYWORDS=programming in d tutorial operator overloading solution diff --git a/book/d.en/operator_overloading.d b/book/d.en/operator_overloading.d new file mode 100644 index 0000000000..699df55b8c --- /dev/null +++ b/book/d.en/operator_overloading.d @@ -0,0 +1,1902 @@ +Ddoc + +$(DERS_BOLUMU $(IX operator overloading) $(IX overloading, operator) Operator Overloading) + +$(P +The topics covered in this chapter apply mostly for classes as well. The biggest difference is that the behavior of assignment operation $(C opAssign()) cannot be overloaded for classes. +) + +$(P +Operator overloading involves many concepts, some of which will be covered later in the book (templates, $(C auto ref), etc.). For that reason, you may find this chapter to be harder to follow than the previous ones. +) + +$(P +Operator overloading enables defining how user-defined types behave when used with operators. In this context, the term $(I overload) means providing the definition of an operator for a specific type. +) + +$(P +We have seen how to define structs and their member functions in previous chapters. As an example, we have defined the $(C increment()) member function to be able to add $(C Duration) objects to $(C TimeOfDay) objects. Here are the two structs from previous chapters, with only the parts that are relevant to this chapter: +) + +--- +struct Duration { + int minute; +} + +struct TimeOfDay { + int hour; + int minute; + + void $(HILITE increment)(Duration duration) { + minute += duration.minute; + + hour += minute / 60; + minute %= 60; + hour %= 24; + } +} + +void main() { + auto lunchTime = TimeOfDay(12, 0); + lunchTime$(HILITE .increment)(Duration(10)); +} +--- + +$(P +A benefit of member functions is being able to define operations of a type alongside the member variables of that type. +) + +$(P +Despite their advantages, member functions can be seen as being limited compared to operations on fundamental types. After all, fundamental types can readily be used with operators: +) + +--- + int weight = 50; + weight $(HILITE +=) 10; // by an operator +--- + +$(P +According to what we have seen so far, similar operations can only be achieved by member functions for user-defined types: +) + +--- + auto lunchTime = TimeOfDay(12, 0); + lunchTime$(HILITE .increment)(Duration(10)); // by a member function +--- + +$(P +Operator overloading enables using structs and classes with operators as well. For example, assuming that the $(C +=) operator is defined for $(C TimeOfDay), the operation above can be written in exactly the same way as with fundamental types: +) + +--- + lunchTime $(HILITE +=) Duration(10); // by an operator + // (even for a struct) +--- + +$(P +Before getting to the details of operator overloading, let's first see how the line above would be enabled for $(C TimeOfDay). What is needed is to redefine the $(C increment()) member function under the special name $(C opOpAssign(string op)) and also to specify that this definition is for the $(C +) character. As it will be explained below, this definition actually corresponds to the $(C +=) operator. +) + +$(P +The definition of this member function does not look like the ones that we have seen so far. That is because $(C opOpAssign) is actually a $(I function template). Since we will see templates in much later chapters, I will have to ask you to accept the operator overloading syntax as is for now: +) + +--- +struct TimeOfDay { +// ... + ref TimeOfDay opOpAssign(string op)(Duration duration) // (1) + if (op == "+") { // (2) + + minute += duration.minute; + hour += minute / 60; + minute %= 60; + hour %= 24; + + return this; + } +} +--- + +$(P +The template definition consists of two parts: +) + +$(OL + +$(LI $(C opOpAssign(string op)): This part must be written as is and should be accepted as the $(I name) of the function. We will see below that there are other member functions in addition to $(C opOpAssign). +) + +$(LI $(C if (op == $(STRING "+"))): $(C opOpAssign) is used for more than one operator overload. $(C $(STRING "+")) specifies that this is the operator overload that corresponds to the $(C +) character. This syntax is a $(I template constraint), which will also be covered in later chapters. +) + +) + +$(P +Also note that this time the return type is different from the return type of the $(C increment()) member function: It is not $(C void) anymore. We will discuss the return types of operators later below. +) + +$(P +Behind the scenes, the compiler replaces the uses of the $(C +=) operator with calls to the $(C opOpAssign!$(STRING "+")) member function: +) + +--- + lunchTime += Duration(10); + + // The following line is the equivalent of the previous one + lunchTime.opOpAssign!"+"(Duration(10)); +--- + +$(P +The $(C !$(STRING "+")) part that is after $(C opOpAssign) specifies that this call is for the definition of the operator for the $(C +) character. We will cover this template syntax in later chapters as well. +) + +$(P +Note that the operator definition that corresponds to $(C +=) is defined by $(STRING "+"), not by $(STRING "+="). The $(C Assign) in the name of $(C opOpAssign()) already implies that this name is for an assignment operator. +) + +$(P +Being able to define the behaviors of operators brings a responsibility: The programmer must observe expectations. As an extreme example, the previous operator could have been defined to decrement the time value instead of incrementing it. However, people who read the code would still expect the value to be incremented by the $(C +=) operator. +) + +$(P +To some extent, the return types of operators can also be chosen freely. Still, general expectations must be observed for the return types as well. +) + +$(P +Keep in mind that operators that behave unnaturally would cause confusion and bugs. +) + +$(H5 Overloadable operators) + +$(P +There are different kinds of operators that can be overloaded. +) + +$(H6 $(IX unary operator) $(IX operator, unary) $(IX opUnary) Unary operators) + +$(P +An operator that takes a single operand is called a unary operator: +) + +--- + ++weight; +--- + +$(P +$(C ++) is a unary operator because it works on a single variable. +) + +$(P +Unary operators are defined by member functions named $(C opUnary). $(C opUnary) does not take any parameters because it uses only the object that the operator is being executed on. +) + +$(P +$(IX -, negation) +$(IX +, plus sign) +$(IX ~, bitwise complement) +$(IX *, pointee access) +$(IX ++, pre-increment) +$(IX --, pre-decrement) +The overloadable unary operators and the corresponding operator strings are the following: +) + +$(TABLE full, +$(HEAD3 Operator, Description, Operator String) +$(ROW3 -object, negative of (numeric complement of), "-") +$(ROW3 +object, the same value as (or, a copy of), "+") +$(ROW3 ~object, bitwise negation, "~") +$(ROW3 *object, access to what it points to, "*") +$(ROW3 ++object, increment, "++") +$(ROW3 --object, decrement, "--") +) + +$(P +For example, the $(C ++) operator for $(C Duration) can be defined like this: +) + +--- +struct Duration { + int minute; + + ref Duration opUnary(string op)() + if (op == "++") { + ++minute; + return this; + } +} +--- + +$(P +Note that the return type of the operator is marked as $(C ref) here as well. This will be explained later below. +) + +$(P +$(C Duration) objects can now be incremented by $(C ++): +) + +--- + auto duration = Duration(20); + ++duration; +--- + +$(P +$(IX ++, post-increment) $(IX --, post-decrement) The post-increment and post-decrement operators cannot be overloaded. The $(C object++) and $(C object--) uses are handled by the compiler automatically by saving the previous value of the object. For example, the compiler applies the equivalent of the following code for post-increment: +) + +--- + /* The previous value is copied by the compiler + * automatically: */ + Duration __previousValue__ = duration; + + /* The ++ operator is called: */ + ++duration; + + /* Then __previousValue__ is used as the value of the + * post-increment operation. */ +--- + +$(P +Unlike some other languages, the copy inside post-increment has no cost in D if the value of the post-increment expression is not actually used. This is because the compiler replaces such post-increment expressions with their pre-increment counterparts: +) + +--- + /* The value of the expression is not used below. The + * only effect of the expression is incrementing 'i'. */ + i++; +--- + +$(P +Because the $(I previous value) of $(C i) is not actually used above, the compiler replaces the expression with the following one: +) + +--- + /* The expression that is actually used by the compiler: */ + ++i; +--- + +$(P +Additionally, if an $(C opBinary) overload supports the $(C duration += 1) usage, then $(C opUnary) need not be overloaded for $(C ++duration) and $(C duration++). Instead, the compiler uses the $(C duration += 1) expression behind the scenes. Similarly, the $(C duration -= 1) overload covers the uses of $(C --duration) and $(C duration--) as well. +) + +$(H6 $(IX binary operator) $(IX operator, binary) Binary operators) + +$(P +An operator that takes two operands is called a binary operator: +) + +--- + totalWeight $(HILITE =) boxWeight $(HILITE +) chocolateWeight; +--- + +$(P +The line above has two separate binary operators: the $(C +) operator, which adds the values of the two operands that are on its two sides, and the $(C =) operator that assigns the value of its right-hand operand to its left-hand operand. +) + +$(P +$(IX +, addition) +$(IX -, subtraction) +$(IX *, multiplication) +$(IX /) +$(IX %) +$(IX ^^) +$(IX &, bitwise and) +$(IX |) +$(IX ^, bitwise exclusive or) +$(IX <<) +$(IX >>) +$(IX >>>) +$(IX ~, concatenation) +$(IX in, operator) +$(IX ==) +$(IX !=) +$(IX <, less than) +$(IX <=) +$(IX >, greater than) +$(IX >=) +$(IX =) +$(IX +=) +$(IX -=) +$(IX *=) +$(IX /=) +$(IX %=) +$(IX ^^=) +$(IX &=) +$(IX |=) +$(IX ^=) +$(IX <<=) +$(IX >>=) +$(IX >>>=) +$(IX ~=) +$(IX opBinary) +$(IX opAssign) +$(IX opOpAssign) +$(IX opBinaryRight) +The rightmost column below describes the category of each operator. The ones marked as "=" assign to the left-hand side object. +) + +$(TABLE full, +$(HEAD5 $(BR)Operator, $(BR)Description, $(BR)Function name, Function name$(BR)for right-hand side, $(BR)Category) +$(ROW5 +, add, opBinary, opBinaryRight, arithmetic) +$(ROW5 -, subtract, opBinary, opBinaryRight, arithmetic) +$(ROW5 *, multiply, opBinary, opBinaryRight, arithmetic) +$(ROW5 /, divide, opBinary, opBinaryRight, arithmetic) +$(ROW5 %, remainder of, opBinary, opBinaryRight, arithmetic) +$(ROW5 ^^, to the power of, opBinary, opBinaryRight, arithmetic) +$(ROW5 &, bitwise $(I and), opBinary, opBinaryRight, bitwise) +$(ROW5 |, bitwise $(I or), opBinary, opBinaryRight, bitwise) +$(ROW5 ^, bitwise $(I xor), opBinary, opBinaryRight, bitwise) +$(ROW5 <<, left-shift, opBinary, opBinaryRight, bitwise) +$(ROW5 >>, right-shift, opBinary, opBinaryRight, bitwise) +$(ROW5 >>>, unsigned right-shift, opBinary, opBinaryRight, bitwise) +$(ROW5 ~, concatenate, opBinary, opBinaryRight, ) +$(ROW5 in, whether contained in, opBinary, opBinaryRight, ) +$(ROW5 ==, whether equal to, opEquals, -, logical) +$(ROW5 !=, whether not equal to, opEquals, -, logical) +$(ROW5 <, whether before, opCmp, -, sorting) +$(ROW5 <=, whether not after, opCmp, -, sorting) +$(ROW5 >, whether after, opCmp, -, sorting) +$(ROW5 >=, whether not before, opCmp, -, sorting) +$(ROW5 =, assign, opAssign, -, =) +$(ROW5 +=, increment by, opOpAssign, -, =) +$(ROW5 -=, decrement by, opOpAssign, -, =) +$(ROW5 *=, multiply and assign, opOpAssign, -, =) +$(ROW5 /=, divide and assign, opOpAssign, -, =) +$(ROW5 %=, assign the remainder of, opOpAssign, -, =) +$(ROW5 ^^=, assign the power of, opOpAssign, -, =) +$(ROW5 &=, assign the result of &, opOpAssign, -, =) +$(ROW5 |=, assign the result of |, opOpAssign, -, =) +$(ROW5 ^=, assign the result of ^, opOpAssign, -, =) +$(ROW5 <<=, assign the result of <<, opOpAssign, -, =) +$(ROW5 >>=, assign the result of >>, opOpAssign, -, =) +$(ROW5 >>>=, assign the result of >>>, opOpAssign, -, =) +$(ROW5 ~=, append, opOpAssign, -, =) +) + +$(P +$(C opBinaryRight) is for when the object can appear on the right-hand side of the operator. Let's assume a binary operator that we shall call $(I op) appears in the program: +) + +--- + x $(I op) y +--- + +$(P +In order to determine what member function to call, the compiler considers the following two options: +) + +--- + // the definition for x being on the left: + x.opBinary!"op"(y); + + // the definition for y being on the right: + y.opBinaryRight!"op"(x); +--- + +$(P +The compiler picks the option that is a better match than the other. +) + +$(P +$(C opBinaryRight) is useful when defining arithmetic types that would normally work on both sides of an operator like e.g. $(C int) does: +) + +--- + auto x = MyInt(42); + x + 1; // calls opBinary!"+" + 1 + x; // calls opBinaryRight!"+" +--- + +$(P +Another common use of $(C opBinaryRight) is the $(C in) operator. It usually makes more sense to define $(C opBinaryRight) for the object that appears on the right-hand side of $(C in). We will see an example of this below. +) + +$(P +The parameter name $(C rhs) that appears in the following definitions is short for $(I right-hand side). It denotes the operand that appears on the right-hand side of the operator: +) + +--- + x $(I op) y +--- + +$(P +For the expression above, the $(C rhs) parameter would represent the variable $(C y). +) + +$(H5 Element indexing and slicing operators) + +$(P +The following operators enable using a type as a collection of elements: +) + +$(TABLE full, +$(HEAD3 Description, Function Name, Sample Usage) +$(ROW3 element access, opIndex, collection[i]) +$(ROW3 assignment to element, opIndexAssign, collection[i] = 7) +$(ROW3 unary operation on element, opIndexUnary, ++collection[i]) +$(ROW3 operation with assignment on element, opIndexOpAssign, collection[i] *= 2) +$(ROW3 number of elements, opDollar, collection[$ - 1]) +$(ROW3 slice of all elements, opSlice, collection[]) +$(ROW3 slice of some elements, opSlice(size_t, size_t), collection[i..j]) +) + +$(P +We will cover those operators later below. +) + +$(P +The following operator functions are from the earlier versions of D. They are discouraged: +) + +$(TABLE full, +$(HEAD3 Description, Function Name, Sample Usage) +$(ROW3 unary operation on all elements, opSliceUnary (discouraged), ++collection[]) +$(ROW3 unary operation on some elements, opSliceUnary (discouraged), ++collection[i..j]) +$(ROW3 assignment to all elements, opSliceAssign (discouraged), collection[] = 42) +$(ROW3 assignment to some elements, opSliceAssign (discouraged), collection[i..j] = 7) +$(ROW3 operation with assignment on all elements, opSliceOpAssign (discouraged), collection[] *= 2) +$(ROW3 operation with assignment on some elements, opSliceOpAssign (discouraged), collection[i..j] *= 2) + +) + +$(H6 Other operators) + +$(P +The following operators can be overloaded as well: +) + +$(TABLE full, +$(HEAD3 Description, Function Name, Sample Usage) +$(ROW3 function call, opCall, object(42)) +$(ROW3 type conversion, opCast, to!int(object)) +$(ROW3 dispatch for non-existent function, opDispatch, object.nonExistent()) +) + +$(P +These operators will be explained below under their own sections. +) + +$(H5 Defining more than one operator at the same time) + +$(P +To keep the code samples short, we have used only the $(C ++), $(C +), and $(C +=) operators above. It is conceivable that when one operator is overloaded for a type, many others would also need to be overloaded. For example, the $(C --) and $(C -=) operators are also defined for the following $(C Duration): +) + +--- +struct Duration { + int minute; + + ref Duration opUnary(string op)() + if (op == "++") { + $(HILITE ++)minute; + return this; + } + + ref Duration opUnary(string op)() + if (op == "--") { + $(HILITE --)minute; + return this; + } + + ref Duration opOpAssign(string op)(int amount) + if (op == "+") { + minute $(HILITE +)= amount; + return this; + } + + ref Duration opOpAssign(string op)(int amount) + if (op == "-") { + minute $(HILITE -)= amount; + return this; + } +} + +unittest { + auto duration = Duration(10); + + ++duration; + assert(duration.minute == 11); + + --duration; + assert(duration.minute == 10); + + duration += 5; + assert(duration.minute == 15); + + duration -= 3; + assert(duration.minute == 12); +} + +void main() { +} +--- + +$(P +The operator overloads above have code duplications. The only differences between the similar functions are highlighted. Such code duplications can be reduced and sometimes avoided altogether by $(I string mixins). We will see the $(C mixin) keyword in a later chapter as well. I would like to show briefly how this keyword helps with operator overloading. +) + +$(P +$(C mixin) inserts the specified string as source code right where the $(C mixin) statement appears in code. The following struct is the equivalent of the one above: +) + +--- +struct Duration { + int minute; + + ref Duration opUnary(string op)() + if ((op == "++") || (op == "--")) { + $(HILITE mixin) (op ~ "minute;"); + return this; + } + + ref Duration opOpAssign(string op)(int amount) + if ((op == "+") || (op == "-")) { + $(HILITE mixin) ("minute " ~ op ~ "= amount;"); + return this; + } +} +--- + +$(P +If the $(C Duration) objects also need to be multiplied and divided by an amount, all that is needed is to add two more conditions to the template constraint: +) + +--- +struct Duration { +// ... + + ref Duration opOpAssign(string op)(int amount) + if ((op == "+") || (op == "-") || + $(HILITE (op == "*") || (op == "/"))) { + mixin ("minute " ~ op ~ "= amount;"); + return this; + } +} + +unittest { + auto duration = Duration(12); + + duration $(HILITE *=) 4; + assert(duration.minute == 48); + + duration $(HILITE /=) 2; + assert(duration.minute == 24); +} +--- + +$(P +In fact, the template constraints are optional: +) + +--- + ref Duration opOpAssign(string op)(int amount) + /* no constraint */ { + mixin ("minute " ~ op ~ "= amount;"); + return this; + } +--- + +$(H5 $(IX return type, operator) Return types of operators) + +$(P +When overloading an operator, it is advisable to observe the return type of the same operator on fundamental types. This would help with making sense of code and reducing confusions. +) + +$(P +None of the operators on fundamental types return $(C void). This fact should be obvious for some operators. For example, the result of adding two $(C int) values as $(C a + b) is $(C int): +) + +--- + int a = 1; + int b = 2; + int c = a + b; // c gets initialized by the return value + // of the + operator +--- + +$(P +The return values of some other operators may not be so obvious. For example, even operators like $(C ++i) have values: +) + +--- + int i = 1; + writeln(++i); // prints 2 +--- + +$(P +The $(C ++) operator not only increments $(C i), it also produces the new value of $(C i). Further, the value that is produced by $(C ++) is not just the new value of $(C i), rather $(I the variable $(C i) itself). We can see this fact by printing the address of the result of that expression: +) + +--- + int i = 1; + writeln("The address of i : ", &i); + writeln("The address of the result of ++i: ", &(++i)); +--- + +$(P +The output contains identical addresses: +) + +$(SHELL +The address of i : 7FFF39BFEE78 +The address of the result of ++i: 7FFF39BFEE78 +) + +$(P +I recommend that you observe the following guidelines when overloading operators for your own types: +) + +$(UL + +$(LI $(B Operators that modify the object) + +$(P +With the exception of $(C opAssign), it is recommended that the operators that modify the object return the object itself. This guideline has been observed above with the $(C TimeOfDay.opOpAssign!$(STRING "+")) and $(C Duration.opUnary!$(STRING "++")). +) + +$(P +The following two steps achieve returning the object itself: +) + +$(OL + +$(LI The return type is the type of the struct, marked by the $(C ref) keyword to mean $(I reference). +) + +$(LI The function is exited by $$(C return this) to mean $(I return this object). +) + +) + +$(P +The operators that modify the object are $(C opUnary!$(STRING "++")), $(C opUnary!$(STRING "--")), and all of the $(C opOpAssign) overloads. +) + +) + +$(LI $(B Logical operators) + +$(P +$(C opEquals) that represents both $(C ==) and $(C !=) must return $(C bool). Although the $(C in) operator normally returns $(I the contained object), it can simply return $(C bool) as well. +) + +) + +$(LI $(B Sort operators) + +$(P +$(C opCmp) that represents $(C <), $(C <=), $(C >), and $(C >=) must return $(C int). +) + +) + +$(LI $(B Operators that make a new object) + +$(P +Some operators must make and return a new object: +) + +$(UL + +$(LI Unary operators $(C -), $(C +), and $(C ~); and the binary operator $(C ~).) + +$(LI Arithmetic operators $(C +), $(C -), $(C *), $(C /), $(C %), and $(C ^^).) + +$(LI Bitwise operators $(C &), $(C |), $(C ^), $(C <<), $(C >>), and $(C >>>).) + +$(LI As has been seen in the previous chapter, $(C opAssign) returns a copy of this object by $(C return this). + +$(P $(I $(B Note:) As an optimization, sometimes it makes more sense for $(C opAssign) to return $(C const ref) for large structs. I will not apply this optimization in this book.)) + +) + +) + +$(P +As an example of an operator that makes a new object, let's define the $(C opBinary!$(STRING "+")) overload for $(C Duration). This operator should add two $(C Duration) objects to make and return a new one: +) + +--- +struct Duration { + int minute; + + Duration opBinary(string op)(Duration rhs) const + if (op == "+") { + return Duration(minute + rhs.minute); // new object + } +} +--- + +$(P +That definition enables adding $(C Duration) objects by the $(C +) operator: +) + +--- + auto travelDuration = Duration(10); + auto returnDuration = Duration(11); + Duration totalDuration; + // ... + totalDuration = travelDuration $(HILITE +) returnDuration; +--- + +$(P +The compiler replaces that expression with the following member function call on the $(C travelDuration) object: +) + +--- + // the equivalent of the expression above: + totalDuration = + travelDuration.opBinary!"+"(returnDuration); +--- + +) + +$(LI $(C opDollar) + +$(P +Since it returns the number of elements of the container, the most suitable type for $(C opDollar) is $(C size_t). However, the return type can be other types as well (e.g. $(C int)). +) + +) + +$(LI $(B Unconstrained operators) + +$(P +The return types of some of the operators depend entirely on the design of the user-defined type: The unary $(C *), $(C opCall), $(C opCast), $(C opDispatch), $(C opSlice), and all $(C opIndex) varieties. +) + +) + +) + +$(H5 $(IX opEquals) $(C opEquals()) for equality comparisons) + +$(P +This member function defines the behaviors of the $(C ==) and the $(C !=) operators. +) + +$(P +The return type of $(C opEquals) is $(C bool). +) + +$(P +For structs, the parameter of $(C opEquals) can be defined as $(C in). However, for speed efficiency $(C opEquals) can be defined as a template that takes $(C auto ref const) (also note the empty template parentheses below): +) + +--- + bool opEquals$(HILITE ())(auto ref const TimeOfDay rhs) const { + // ... + } +--- + +$(P +As we have seen in $(LINK2 lvalue_rvalue.html, the Lvalues and Rvalues chapter), $(C auto ref) allows lvalues to be passed by reference and rvalues by copy. However, since rvalues are not copied, rather moved, the signature above is efficient for both lvalues and rvalues. +) + +$(P +To reduce confusion, $(C opEquals) and $(C opCmp) must work consistently. For two objects that $(C opEquals) returns $(C true), $(C opCmp) must return zero. +) + +$(P +Once $(C opEquals()) is defined for equality, the compiler uses its opposite for inequality: +) + +--- + x == y; + // the equivalent of the previous expression: + x.opEquals(y); + + x != y; + // the equivalent of the previous expression: + !(x.opEquals(y)); +--- + +$(P +Normally, it is not necessary to define $(C opEquals()) for structs. The compiler generates it for structs automatically. The automatically-generated $(C opEquals) compares all of the members individually. +) + +$(P +Sometimes the equality of two objects must be defined differently from this automatic behavior. For example, some of the members may not be significant in this comparison, or the equality may depend on a more complex logic. +) + +$(P +Just as an example, let's define $(C opEquals()) in a way that disregards the minute information altogether: +) + +--- +struct TimeOfDay { + int hour; + int minute; + + bool opEquals(TimeOfDay rhs) const { + return hour == rhs.hour; + } +} +// ... + assert(TimeOfDay(20, 10) $(HILITE ==) TimeOfDay(20, 59)); +--- + +$(P +Since the equality comparison considers the values of only the $(C hour) members, 20:10 and 20:59 end up being equal. (This is just an example; it should be clear that such an equality comparison would cause confusions.) +) + +$(H5 $(IX opCmp) $(C opCmp()) for sorting) + +$(P +Sort operators determine the sort orders of objects. All of the ordering operators $(C <), $(C <=), $(C >), and $(C >=) are covered by the $(C opCmp()) member function. +) + +$(P +For structs, the parameter of $(C opCmp) can be defined as $(C in). However, as with $(C opEquals), it is more efficient to define $(C opCmp) as a template that takes $(C auto ref const): +) + +--- + int opCmp$(HILITE ())(auto ref const TimeOfDay rhs) const { + // ... + } +--- + +$(P +To reduce confusion, $(C opEquals) and $(C opCmp) must work consistently. For two objects that $(C opEquals) returns $(C true), $(C opCmp) must return zero. +) + +$(P +Let's assume that one of these four operators is used as in the following code: +) + +--- + if (x $(I op) y) { $(CODE_NOTE $(I op) is one of <, <=, >, or >=) +--- + +$(P +The compiler converts that expression to the following logical expression and uses the result of the new logical expression: +) + +--- + if (x.opCmp(y) $(I op) 0) { +--- + +$(P +Let's consider the $(C <=) operator: +) + +--- + if (x $(HILITE <=) y) { +--- + +$(P +The compiler generates the following code behind the scenes: +) + +--- + if (x.opCmp(y) $(HILITE <=) 0) { +--- + +$(P +For the user-defined $(C opCmp()) to work correctly, this member function must return a result according to the following rules: +) + +$(UL +$(LI $(I A negative value) if the left-hand object is considered to be before the right-hand object) +$(LI $(I A positive value) if the left-hand object is considered to be after the right-hand object) +$(LI $(I Zero) if the objects are considered to have the same sort order) +) + +$(P +To be able to support those values, the return type of $(C opCmp()) must be $(C int), not $(C bool). +) + +$(P +The following is a way of ordering $(C TimeOfDay) objects by first comparing the values of the $(C hour) members, and then comparing the values of the $(C minute) members (only if the $(C hour) members are equal): +) + +--- + int opCmp(TimeOfDay rhs) const { + /* Note: Subtraction is a bug here if the result can + * overflow. (See the following warning in text.) */ + + return (hour == rhs.hour + ? minute - rhs.minute + : hour - rhs.hour); + } +--- + +$(P +That definition returns the difference between the $(C minute) values when the $(C hour) members are the same, and the difference between the $(C hour) members otherwise. The return value would be a $(I negative value) when the $(I left-hand) object comes before in chronological order, a $(I positive value) if the $(I right-hand) object is before, and $(I zero) when they represent exactly the same time of day. +) + +$(P +$(B Warning:) Using subtraction for the implementation of $(C opCmp) is a bug if valid values of a member can cause overflow. For example, the two objects below would be sorted incorrectly as the object with value $(C -2) is calculated to be $(I greater) than the one with value $(C int.max): +) + +--- +struct S { + int i; + + int opCmp(S rhs) const { + return i - rhs.i; $(CODE_NOTE_WRONG BUG) + } +} + +void main() { + assert(S(-2) $(HILITE >) S(int.max)); $(CODE_NOTE_WRONG wrong sort order) +} +--- + +$(P +On the other hand, subtraction is acceptable for $(C TimeOfDay) because none of the valid values of the members of that $(C struct) can cause overflow in subtraction. +) + +$(P +$(IX cmp, std.algorithm) $(IX lexicographical) You can use $(C std.algorithm.cmp) for comparing slices (including all string types and ranges). $(C cmp()) compares slices lexicographically and produces a negative value, zero, or positive value depending on their order. That result can directly be used as the return value of $(C opCmp): +) + +--- +import std.algorithm; + +struct S { + string name; + + int opCmp(S rhs) const { + return $(HILITE cmp)(name, rhs.name); + } +} +--- + +$(P +Once $(C opCmp()) is defined, this type can be used with sorting algorithms like $(C std.algorithm.sort) as well. As $(C sort()) works on the elements, it is the $(C opCmp()) operator that gets called behind the scenes to determine their order. The following program constructs 10 objects with random values and sorts them with $(C sort()): +) + +--- +import std.random; +import std.stdio; +import std.string; +import std.algorithm; + +struct TimeOfDay { + int hour; + int minute; + + int opCmp(TimeOfDay rhs) const { + return (hour == rhs.hour + ? minute - rhs.minute + : hour - rhs.hour); + } + + string toString() const { + return format("%02s:%02s", hour, minute); + } +} + +void main() { + TimeOfDay[] times; + + foreach (i; 0 .. 10) { + times ~= TimeOfDay(uniform(0, 24), uniform(0, 60)); + } + + sort(times); + + writeln(times); +} +--- + +$(P +As expected, the elements are sorted from the earliest time to the latest time: +) + +$(SHELL +[03:40, 04:10, 09:06, 10:03, 10:09, 11:04, 13:42, 16:40, 18:03, 21:08] +) + +$(H5 $(IX opCall) $(IX ()) $(C opCall()) to call objects as functions) + +$(P +The parentheses around the parameter list when calling functions are operators as well. We have already seen how $(C static opCall()) makes it possible to use the name of the $(I type) as a function. $(C static opCall()) allows creating objects with default values at run time. +) + +$(P +Non-static $(C opCall()) on the other hand allows using the $(I objects) of user-defined types as functions: +) + +--- + Foo foo; + foo$(HILITE ()); +--- + +$(P +The object $(C foo) above is being called like a function. +) + +$(P +As an example, let's consider a $(C struct) that represents a linear equation. This $(C struct) will be used for calculating the $(I y) values of the following linear equation for specific $(I x) values: +) + +$(MONO + $(I y) = $(I a)$(I x) + $(I b) +) + +$(P +The following $(C opCall()) simply calculates and returns the value of $(I y) according to that equation: +) + +--- +struct LinearEquation { + double a; + double b; + + double opCall(double x) const { + return a * x + b; + } +} +--- + +$(P +With that definition, each object of $(C LinearEquation) represents a linear equation for specific $(I a) and $(I b) values. Such an object can be used as a function that calculates the $(I y) values: +) + +--- + LinearEquation equation = { 1.2, 3.4 }; + // the object is being used like a function: + double y = equation(5.6); +--- + +$(P +$(I $(B Note:) Defining $(C opCall()) for a $(C struct) disables the compiler-generated automatic constructor. That is why the $(C { }) syntax is used above instead of the recommended $(C LinearEquation(1.2, 3.4)). When the latter syntax is desired, a $(C static opCall()) that takes two $(C double) parameters must also be defined.) +) + +$(P +$(C equation) above represents the $(I y = 1.2x + 3.4) linear equation. Using that object as a function executes the $(C opCall()) member function. +) + +$(P +This feature can be useful to define and store the $(I a) and $(I b) values in an object once and to use that object multiple times later on. The following code uses such an object in a loop: +) + +--- + LinearEquation equation = { 0.01, 0.4 }; + + for (double x = 0.0; x <= 1.0; x += 0.125) { + writefln("%f: %f", x, equation(x)); + } +--- + +$(P +That object represents the $(I y = 0.01x + 0.4) equation. It is being used for calculating the results for $(I x) values in the range from 0.0 to 1.0. +) + +$(H5 $(IX opIndex) $(IX opIndexAssign) $(IX opIndexUnary) $(IX opIndexOpAssign) $(IX opDollar) Indexing operators) + +$(P +$(C opIndex), $(C opIndexAssign), $(C opIndexUnary), $(C opIndexOpAssign), and $(C opDollar) make it possible to use indexing operators on user-defined types similar to arrays as in $(C object[index]). +) + +$(P +Unlike arrays, these operators support multi-dimensional indexing as well. Multiple index values are specified as a comma-separated list inside the square brackets (e.g. $(C object[index0, index1])). In the following examples we will use these operators only with a single dimension and cover their multi-dimensional uses in $(LINK2 templates_more.html, the More Templates chapter). +) + +$(P +The $(C deque) variable in the following examples is an object of $(C struct DoubleEndedQueue), which we will define below; and $(C e) is a variable of type $(C int). +) + +$(P +$(C opIndex) is for element access. The index that is specified inside the brackets becomes the parameter of the operator function: +) + +--- + e = deque[3]; // the element at index 3 + e = deque.opIndex(3); // the equivalent of the above +--- + +$(P +$(C opIndexAssign) is for assigning to an element. The first parameter is the value that is being assigned and the second parameter is the index of the element: +) + +--- + deque[5] = 55; // assign 55 to the element at index 5 + deque.opIndexAssign(55, 5); // the equivalent of the above +--- + +$(P +$(C opIndexUnary) is similar to $(C opUnary). The difference is that the operation is applied to the element at the specified index: +) + +--- + ++deque[4]; // increment the element at index 4 + deque.opIndexUnary!"++"(4); // the equivalent of the above +--- + +$(P +$(C opIndexOpAssign) is similar to $(C opOpAssign). The difference is that the operation is applied to an element: +) + +--- + deque[6] += 66; // add 66 to the element at index 6 + deque.opIndexOpAssign!"+"(66, 6);// the equivalent of the above +--- + +$(P +$(C opDollar) defines the $(C $) character that is used during indexing and slicing. It is for returning the number of elements in the container: +) + +--- + e = deque[$ - 1]; // the last element + e = deque[deque.opDollar() - 1]; // the equivalent of the above +--- + +$(H6 Indexing operators example) + +$(P +$(I Double-ended queue) is a data structure that is similar to arrays but it provides efficient insertion at the head of the collection as well. (In contrast, inserting at the head of an array is a relatively slow operation as it requires moving the existing elements to a newly created array.) +) + +$(P +One way of implementing a double-ended queue is to use two arrays in the background but to use the first one in reverse. The element that is conceptually inserted at the head of the queue is actually appended to the $(I head) array. As a result, this operation is as efficient as appending to the end. +) + +$(P +The following $(C struct) implements a double-ended queue that overloads the operators that we have seen in this section: +) + +--- +$(CODE_NAME DoubleEndedQueue)import std.stdio; +import std.string; +import std.conv; + +$(CODE_COMMENT_OUT)struct DoubleEndedQueue // Also known as Deque +$(CODE_COMMENT_OUT){ +private: + + /* The elements are represented as the chaining of the two + * member slices. However, 'head' is indexed in reverse so + * that the first element of the entire collection is + * head[$-1], the second one is head[$-2], etc.: + * + * head[$-1], head[$-2], ... head[0], tail[0], ... tail[$-1] + */ + int[] head; // the first group of elements + int[] tail; // the second group of elements + + /* Determines the actual slice that the specified element + * resides in and returns it as a reference. */ + ref inout(int) elementAt(size_t index) inout { + return (index < head.length + ? head[$ - 1 - index] + : tail[index - head.length]); + } + +public: + + string toString() const { + string result; + + foreach_reverse (element; head) { + result ~= format("%s ", to!string(element)); + } + + foreach (element; tail) { + result ~= format("%s ", to!string(element)); + } + + return result; + } + + /* Note: As we will see in the next chapter, the following + * is a simpler and more efficient implementation of + * toString(): */ + version (none) { + void toString(void delegate(const(char)[]) sink) const { + import std.format; + import std.range; + + formattedWrite( + sink, "%(%s %)", chain(head.retro, tail)); + } + } + + /* Adds a new element to the head of the collection. */ + void insertAtHead(int value) { + head ~= value; + } + + /* Adds a new element to the tail of the collection. + * + * Sample: deque ~= value + */ + ref DoubleEndedQueue opOpAssign(string op)(int value) + if (op == "~") { + tail ~= value; + return this; + } + + /* Returns the specified element. + * + * Sample: deque[index] + */ + inout(int) opIndex(size_t index) inout { + return elementAt(index); + } + + /* Applies a unary operation to the specified element. + * + * Sample: ++deque[index] + */ + int opIndexUnary(string op)(size_t index) { + mixin ("return " ~ op ~ "elementAt(index);"); + } + + /* Assigns a value to the specified element. + * + * Sample: deque[index] = value + */ + int opIndexAssign(int value, size_t index) { + return elementAt(index) = value; + } + + /* Uses the specified element and a value in a binary + * operation and assigns the result back to the same + * element. + * + * Sample: deque[index] += value + */ + int opIndexOpAssign(string op)(int value, size_t index) { + mixin ("return elementAt(index) " ~ op ~ "= value;"); + } + + /* Defines the $ character, which is the length of the + * collection. + * + * Sample: deque[$ - 1] + */ + size_t opDollar() const { + return head.length + tail.length; + } +$(CODE_COMMENT_OUT)} + +void $(CODE_DONT_TEST)main() { + auto deque = DoubleEndedQueue(); + + foreach (i; 0 .. 10) { + if (i % 2) { + deque.insertAtHead(i); + + } else { + deque ~= i; + } + } + + writefln("Element at index 3: %s", + deque[3]); // accessing an element + ++deque[4]; // incrementing an element + deque[5] = 55; // assigning to an element + deque[6] += 66; // adding to an element + + (deque ~= 100) ~= 200; + + writeln(deque); +} +--- + +$(P +According to the guidelines above, the return type of $(C opOpAssign) is $(C ref) so that the $(C ~=) operator can be chained on the same collection: +) + +--- + (deque ~= 100) ~= 200; +--- + +$(P +As a result, both 100 and 200 get appended to the same collection: +) + +$(SHELL +Element at index 3: 3 +9 7 5 3 2 55 68 4 6 8 100 200 +) + +$(H5 $(IX opSlice) Slicing operators) + +$(P +$(C opSlice) allows slicing the objects of user-defined types with the $(C []) operator. +) + +$(P +$(IX opSliceUnary) $(IX opSliceAssign) $(IX opSliceOpAssign) In addition to this operator, there are also $(C opSliceUnary), $(C opSliceAssign), and $(C opSliceOpAssign) but they are discouraged. +) + +$(P +D supports multi-dimensional slicing. We will see a multi-dimensional example later in $(LINK2 templates_more.html, the More Templates chapter). Although the methods described in that chapter can be used for a single dimension as well, they do not match the indexing operators that are defined above and they involve templates which we have not covered yet. For that reason, we will see the non-templated use of $(C opSlice) in this chapter, which works only with a single dimension. (This use of $(C opSlice) is discouraged as well.) +) + +$(P +$(C opSlice) has two distinct forms: +) + +$(UL + +$(LI The square brackets can be empty as in $(C deque[]) to mean $(I all elements).) + +$(LI The square brackets can contain a number range as in $(C deque[begin..end]) to mean $(I the elements in the specified range).) + +) + +$(P +The slicing operators are relatively more complex than other operators because they involve two distinct concepts: $(I container) and $(I range). We will see these concepts in more detail in later chapters. +) + +$(P +In single-dimensional slicing which does not use templates, $(C opSlice) returns an object that represents a specific range of elements of the container. The object that $(C opSlice) returns is responsible for defining the operations that are applied on that range elements. For example, behind the scenes the following expression is executed by first calling $(C opSlice) to obtain a range object and then applying $(C opOpAssign!$(STRING "*")) on that object: +) + +--- + deque[] *= 10; // multiply all elements by 10 + + // The equivalent of the above: + { + auto range = deque.opSlice(); + range.opOpAssign!"*"(10); + } +--- + +$(P +Accordingly, the $(C opSlice) operators of $(C DoubleEndedQueue) return a special $(C Range) object so that the operations are applied to it: +) + +--- +import std.exception; + +struct DoubleEndedQueue { +// ... + + /* Returns a range that represents all of the elements. + * ('Range' struct is defined below.) + * + * Sample: deque[] + */ + inout(Range) $(HILITE opSlice)() inout { + return inout(Range)(head[], tail[]); + } + + /* Returns a range that represents some of the elements. + * + * Sample: deque[begin .. end] + */ + inout(Range) $(HILITE opSlice)(size_t begin, size_t end) inout { + enforce(end <= opDollar()); + enforce(begin <= end); + + /* Determine what parts of 'head' and 'tail' + * correspond to the specified range: */ + + if (begin < head.length) { + if (end < head.length) { + /* The range is completely inside 'head'. */ + return inout(Range)( + head[$ - end .. $ - begin], + []); + + } else { + /* Some part of the range is inside 'head' and + * the rest is inside 'tail'. */ + return inout(Range)( + head[0 .. $ - begin], + tail[0 .. end - head.length]); + } + + } else { + /* The range is completely inside 'tail'. */ + return inout(Range)( + [], + tail[begin - head.length .. end - head.length]); + } + } + + /* Represents a range of elements of the collection. This + * struct is responsible for defining the opUnary, + * opAssign, and opOpAssign operators. */ + struct $(HILITE Range) { + int[] headRange; // elements that are in 'head' + int[] tailRange; // elements that are in 'tail' + + /* Applies the unary operation to the elements of the + * range. */ + Range opUnary(string op)() { + mixin (op ~ "headRange[];"); + mixin (op ~ "tailRange[];"); + return this; + } + + /* Assigns the specified value to each element of the + * range. */ + Range opAssign(int value) { + headRange[] = value; + tailRange[] = value; + return this; + } + + /* Uses each element and a value in a binary operation + * and assigns the result back to that element. */ + Range opOpAssign(string op)(int value) { + mixin ("headRange[] " ~ op ~ "= value;"); + mixin ("tailRange[] " ~ op ~ "= value;"); + return this; + } + } +$(CODE_XREF DoubleEndedQueue)} + +void $(CODE_DONT_TEST)main() { + auto deque = DoubleEndedQueue(); + + foreach (i; 0 .. 10) { + if (i % 2) { + deque.insertAtHead(i); + + } else { + deque ~= i; + } + } + + writeln(deque); + deque$(HILITE []) *= 10; + deque$(HILITE [3 .. 7]) = -1; + writeln(deque); +} +--- + +$(P +The output: +) + +$(SHELL +9 7 5 3 1 0 2 4 6 8 +90 70 50 -1 -1 -1 -1 40 60 80 +) + +$(H5 $(IX opCast) $(IX type conversion, opCast) $(C opCast) for type conversions) + +$(P +$(C opCast) defines explicit type conversions. It can be overloaded separately for each target type. As you would remember from the earlier chapters, explicit type conversions are performed by the $(C to) function and the $(C cast) operator. +) + +$(P +$(C opCast) is a template as well, but it has a different format: The target type is specified by the $(C (T : target_type)) syntax: +) + +--- + $(I target_type) opCast(T : $(I target_type))() { + // ... + } +--- + +$(P +This syntax will become clear later after the templates chapter as well. +) + +$(P +Let's change the definition of $(C Duration) so that it now has two members: hours and minutes. The operator that converts objects of this type to $(C double) can be defined as in the following code: +) + +--- +import std.stdio; +import std.conv; + +struct Duration { + int hour; + int minute; + + double opCast(T : double)() const { + return hour + (to!double(minute) / 60); + } +} + +void main() { + auto duration = Duration(2, 30); + double d = to!double(duration); + // (could be 'cast(double)duration' as well) + + writeln(d); +} +--- + +$(P +The compiler replaces the type conversion call above with the following one: +) + +--- + double d = duration.opCast!double(); +--- + +$(P +The $(C double) conversion function above produces 2.5 for two hours and thirty minutes: +) + +$(SHELL +2.5 +) + +$(P +$(IX opCast!bool) $(IX bool, opCast) Although $(C opCast) is for explicit type conversions, its $(C bool) specialization is called automatically when the variable is used in a logical expression: +) + +--- +struct Duration { +// ... + + bool opCast($(HILITE T : bool))() const { + return (hour != 0) || (minute != 0); + } +} + +// ... + + if (duration) { // compiles + // ... + } + + while (duration) { // compiles + // ... + } + + auto r = duration ? 1 : 2; // compiles +--- + +$(P +Still, the $(C bool) specialization of $(C opCast) is not for all implicit $(C bool) conversions: +) + +--- +void foo(bool b) { + // ... +} + +// ... + + foo(duration); $(DERLEME_HATASI) + bool b = duration; $(DERLEME_HATASI) +--- + +$(SHELL +Error: cannot implicitly convert expression (duration) of type Duration to +bool +Error: function deneme.foo (bool b) is not callable using argument types +(Duration) +) + +$(H5 $(IX opDispatch) Catch-all operator $(C opDispatch)) + +$(P +$(C opDispatch) gets called whenever a $(I missing) member of an object is accessed. All attempts to access non-existent members are dispatched to this function. +) + +$(P +The name of the missing member becomes the template parameter value of $(C opDispatch). +) + +$(P +The following code demonstrates a simple definition: +) + +--- +import std.stdio; + +struct Foo { + void opDispatch(string name, T)(T parameter) { + writefln("Foo.opDispatch - name: %s, value: %s", + name, parameter); + } +} + +void main() { + Foo foo; + foo.aNonExistentFunction(42); + foo.anotherNonExistentFunction(100); +} +--- + +$(P +There are no compiler errors for the calls to non-existent members. Instead, all of those calls are dispatched to $(C opDispatch). The first template parameter is the name of the member. The parameter values that are used when calling the function appear as the parameters of $(C opDispatch): +) + +$(SHELL +Foo.opDispatch - name: aNonExistentFunction, value: 42 +Foo.opDispatch - name: anotherNonExistentFunction, value: 100 +) + +$(P +The $(C name) template parameter can be used inside the function to make decisions on how the call to that specific non-existent function should be handled: +) + +--- + switch (name) { + // ... + } +--- + +$(H5 $(IX in, operator overloading) $(IX !in) Inclusion query by $(C opBinaryRight!"in")) + +$(P +This operator allows defining the behavior of the $(C in) operator for user-defined types. $(C in) is commonly used with associative arrays to determine whether a value for a specific key exists in the array. +) + +$(P +Different from other operators, this operator is normally overloaded for the case where the object appears on the right-hand side: +) + +--- + if (time in lunchBreak) { +--- + +$(P +The compiler would use $(C opBinaryRight) behind the scenes: +) + +--- + // the equivalent of the above: + if (lunchBreak.opBinaryRight!"in"(time)) { +--- + +$(P +There is also $(C !in) to determine whether a value for a specific key $(I does not) exist in the array: +) + +--- + if (a !in b) { +--- + +$(P +$(C !in) cannot be overloaded because the compiler uses the negative of the result of the $(C in) operator instead: +) + +--- + if (!(a in b)) { // the equivalent of the above +--- + +$(H6 Example of the $(C in) operator) + +$(P +The following program defines a $(C TimeSpan) type in addition to $(C Duration) and $(C TimeOfDay). The $(C in) operator that is defined for $(C TimeSpan) determines whether a moment in time is within that time span. +) + +$(P +To keep the code short, the following program defines only the necessary member functions. +) + +$(P +Note how the $(C TimeOfDay) object is used seamlessly in the $(C for) loop. That loop is a demonstration of how useful operator overloading can be. +) + +--- +import std.stdio; +import std.string; + +struct Duration { + int minute; +} + +struct TimeOfDay { + int hour; + int minute; + + ref TimeOfDay opOpAssign(string op)(Duration duration) + if (op == "+") { + minute += duration.minute; + + hour += minute / 60; + minute %= 60; + hour %= 24; + + return this; + } + + int opCmp(TimeOfDay rhs) const { + return (hour == rhs.hour + ? minute - rhs.minute + : hour - rhs.hour); + } + + string toString() const { + return format("%02s:%02s", hour, minute); + } +} + +struct TimeSpan { + TimeOfDay begin; + TimeOfDay end; // end is outside of the span + + bool opBinaryRight(string op)(TimeOfDay time) const + if (op == "in") { + return (time >= begin) && (time < end); + } +} + +void main() { + auto lunchBreak = TimeSpan(TimeOfDay(12, 00), + TimeOfDay(13, 00)); + + for (auto time = TimeOfDay(11, 30); + time < TimeOfDay(13, 30); + time += Duration(15)) { + + if (time in lunchBreak) { + writeln(time, " is during the lunch break"); + + } else { + writeln(time, " is outside of the lunch break"); + } + } +} +--- + +$(P +The output: +) + +$(SHELL +11:30 is outside of the lunch break +11:45 is outside of the lunch break +12:00 is during the lunch break +12:15 is during the lunch break +12:30 is during the lunch break +12:45 is during the lunch break +13:00 is outside of the lunch break +13:15 is outside of the lunch break +) + +$(PROBLEM_TEK + +$(P +Define a fraction type that stores its numerator and denominator as members of type $(C long). Such a type may be useful because it does not lose value like $(C float), $(C double), and $(C real) do due to their precisions. For example, although the result of multiplying a $(C double) value of 1.0/3 by 3 is $(I not) 1.0, multiplying a $(C Fraction) object that represents the fraction 1/3 by 3 would be exactly 1: +) + +--- +struct Fraction { + long num; // numerator + long den; // denominator + + /* As a convenience, the constructor uses the default + * value of 1 for the denominator. */ + this(long num, long den = 1) { + enforce(den != 0, "The denominator cannot be zero"); + + this.num = num; + this.den = den; + + /* Ensuring that the denominator is always positive + * will simplify the definitions of some of the + * operator functions. */ + if (this.den < 0) { + this.num = -this.num; + this.den = -this.den; + } + } + + /* ... you define the operator overloads ... */ +} +--- + +$(P +Define operators as needed for this type to make it a convenient type as close to fundamental types as possible. Ensure that the definition of the type passes all of the following unit tests. The unit tests ensure the following behaviors: +) + +$(UL + +$(LI An exception must be thrown when constructing an object with zero denominator. (This is already taken care of by the $(C enforce) expression above.)) + +$(LI Producing the negative of the value: For example, the negative of 1/3 should be -1/3 and negative of -2/5 should be 2/5.) + +$(LI Incrementing and decrementing the value by $(C ++) and $(C --).) + +$(LI Support for four arithmetic operations: Both modifying the value of an object by $(C +=), $(C -=), $(C *=), and $(C /=); and producing the result of using two objects with the $(C +), $(C -), $(C *), and $(C /) operators. (Similar to the constructor, dividing by zero should be prevented.) + +$(P +As a reminder, here are the formulas of arithmetic operations that involve two fractions a/b and c/d: +) + +$(UL +$(LI Addition: a/b + c/d = (a*d + c*b)/(b*d)) +$(LI Subtraction: a/b - c/d = (a*d - c*b)/(b*d)) +$(LI Multiplication: a/b * c/d = (a*c)/(b*d)) +$(LI Division: (a/b) / (c/d) = (a*d)/(b*c)) +) + +) + +$(LI The actual (and necessarily lossful) value of the object can be converted to $(C double).) + +$(LI Sort order and equality comparisons are performed by the actual values of the fractions, not by the values of the numerators and denominators. For example, the fractions 1/3 and 20/60 must be considered to be equal. +) + +) + +--- +unittest { + /* Must throw when denominator is zero. */ + assertThrown(Fraction(42, 0)); + + /* Let's start with 1/3. */ + auto a = Fraction(1, 3); + + /* -1/3 */ + assert(-a == Fraction(-1, 3)); + + /* 1/3 + 1 == 4/3 */ + ++a; + assert(a == Fraction(4, 3)); + + /* 4/3 - 1 == 1/3 */ + --a; + assert(a == Fraction(1, 3)); + + /* 1/3 + 2/3 == 3/3 */ + a += Fraction(2, 3); + assert(a == Fraction(1)); + + /* 3/3 - 2/3 == 1/3 */ + a -= Fraction(2, 3); + assert(a == Fraction(1, 3)); + + /* 1/3 * 8 == 8/3 */ + a *= Fraction(8); + assert(a == Fraction(8, 3)); + + /* 8/3 / 16/9 == 3/2 */ + a /= Fraction(16, 9); + assert(a == Fraction(3, 2)); + + /* Must produce the equivalent value in type 'double'. + * + * Note that although double cannot represent every value + * precisely, 1.5 is an exception. That is why this test + * is being applied at this point. */ + assert(to!double(a) == 1.5); + + /* 1.5 + 2.5 == 4 */ + assert(a + Fraction(5, 2) == Fraction(4, 1)); + + /* 1.5 - 0.75 == 0.75 */ + assert(a - Fraction(3, 4) == Fraction(3, 4)); + + /* 1.5 * 10 == 15 */ + assert(a * Fraction(10) == Fraction(15, 1)); + + /* 1.5 / 4 == 3/8 */ + assert(a / Fraction(4) == Fraction(3, 8)); + + /* Must throw when dividing by zero. */ + assertThrown(Fraction(42, 1) / Fraction(0)); + + /* The one with lower numerator is before. */ + assert(Fraction(3, 5) < Fraction(4, 5)); + + /* The one with larger denominator is before. */ + assert(Fraction(3, 9) < Fraction(3, 8)); + assert(Fraction(1, 1_000) > Fraction(1, 10_000)); + + /* The one with lower value is before. */ + assert(Fraction(10, 100) < Fraction(1, 2)); + + /* The one with negative value is before. */ + assert(Fraction(-1, 2) < Fraction(0)); + assert(Fraction(1, -2) < Fraction(0)); + + /* The ones with equal values must be both <= and >=. */ + assert(Fraction(-1, -2) <= Fraction(1, 2)); + assert(Fraction(1, 2) <= Fraction(-1, -2)); + assert(Fraction(3, 7) <= Fraction(9, 21)); + assert(Fraction(3, 7) >= Fraction(9, 21)); + + /* The ones with equal values must be equal. */ + assert(Fraction(1, 3) == Fraction(20, 60)); + + /* The ones with equal values with sign must be equal. */ + assert(Fraction(-1, 2) == Fraction(1, -2)); + assert(Fraction(1, 2) == Fraction(-1, -2)); +} +--- + +) + +Macros: + TITLE=Operator Overloading + + DESCRIPTION=The operator overloading feature of the D programming language that makes user-defined types as convenient as fundamental types. + + KEYWORDS=d programming lesson book tutorial operator overloading diff --git a/book/d.en/operator_precedence.d b/book/d.en/operator_precedence.d new file mode 100644 index 0000000000..f91c79b936 --- /dev/null +++ b/book/d.en/operator_precedence.d @@ -0,0 +1,323 @@ +Ddoc + +$(DERS_BOLUMU $(IX operator precedence) $(IX precedence, operator) Operator Precedence) + +$(P +As we have been using throughout the book, expressions can be $(I chained) with more than one operator. For example, the following line contains four expressions chained with three operators: +) + +--- + a = b + c * d // three operators: =, +, and * +--- + +$(P +Operator precedence rules specify the order that the chained operators are executed in and the expressions that they use. Operators are executed according to their precedences: first the higher ones, then the lower ones. +) + +$(P +The following is D's operator precedence table. Operators are listed from the highest precedence to the lowest. The ones that are in the same table row have the same precedence. (Line wrapping inside table cells is insignificant; for example, $(C ==) and $(C !is) have the same precedence.) Unless specified otherwise, operators are $(I left-associative). +) + +$(P +Some of the terms used in the table are explained later below. +) + + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OperatorsDescriptionNotes
    $(C !) Template instantiationCannot be chained +
    $(C =>) Lambda definition Not a real operator; occurs twice in the table; this row is for binding power to the $(I left) +
    $(C . ++ -- $(PARANTEZ_AC) [) Postfix operators $(C $(PARANTEZ_AC)) and $(C [) must be balanced with $(C $(PARANTEZ_KAPA)) and $(C ]), respectively +
    $(C ^^) Power operator Right-associative +
    $(C ++ -- * + - ! & ~ cast) Unary operators +
    $(C * / %) Binary operators +
    $(C + - ~) Binary operators
    $(C << >> >>>) Bit shift operators +
    $(C == != > < >= <= in !in is !is) Comparison operators Unordered with respect to bitwise operators, cannot be chained +
    $(C &) Bitwise $(I and) Unordered with respect to comparison operators +
    $(C ^) Bitwise $(I xor) Unordered with respect to comparison operators +
    $(C |) Bitwise $(I or) Unordered with respect to comparison operators +
    $(C &&) Logical $(I and)Short-circuit
    $(C ||)Logical $(I or)Short-circuit
    $(C ?:)Ternary operatorRight-associative +
    $(C = -= += = *= %= ^= ^^= ~= <<= >>= >>>=) + Assignment operators Right-associative +
    $(C =>) Lambda definition Not a real operator; occurs twice in the table; this row is for binding power to the $(I right)
    $(C ,) Comma operatorNot to be confused with using comma as a separator (e.g. in parameter lists)
    $(C ..) Number range Not a real operator; hardwired into syntax at specific points +
    + + +$(H6 $(IX operator chaining) $(IX chaining, operator) Chaining) + +$(P +Let's consider the line from the beginning of the chapter: +) + +--- + a = b + c * d +--- + +$(P +Because binary $(C *) has higher precedence than binary $(C +), and binary $(C +) has higher precedence than $(C =), that expression is executed as the following parenthesized equivalent: +) + +--- + a = (b + (c * d)) // first *, then +, then = +--- + +$(P +As another example, because postfix $(C .) has higher precedence than unary $(C *), the following expression would first access member $(C ptr) of object $(C o) and then dereference it: +) + +--- + *o.ptr $(CODE_NOTE dereferences pointer member o.ptr) + *(o.ptr) $(CODE_NOTE equivalent of the above) + (*o).ptr $(CODE_NOTE_WRONG NOT equivalent of the above) +--- + +$(P +Some operators cannot be chained: +) + +--- + if (a > b == c) { $(DERLEME_HATASI) + // ... + } +--- + +$(SHELL +Error: found '==' when expecting '$(PARANTEZ_KAPA)' +) + +$(P +The programmer must specify the desired execution order with parentheses: +) + +--- + if ((a > b) == c) { $(CODE_NOTE compiles) + // ... + } +--- + +$(H6 $(IX left-associative) $(IX right-associative) $(IX associativity, operator) $(IX operator associativity) Associativity) + +$(P +If two operators have the same precedence, then their associativity determines which operator is executed first: the one on the left or the one on the right. +) + +$(P +Most operators are $(I left-associative); the one on the left-hand side is executed first: +) + +--- + 10 - 7 - 3; + (10 - 7) - 3; $(CODE_NOTE equivalent of the above (== 0)) + 10 - (7 - 3); $(CODE_NOTE_WRONG NOT equivalent of the above (== 6)) +--- + +$(P +Some operators are right-associative; the one on the right-hand side is executed first: +) + +--- + 4 ^^ 3 ^^ 2; + 4 ^^ (3 ^^ 2); $(CODE_NOTE equivalent of the above (== 262144)) + (4 ^^ 3) ^^ 2; $(CODE_NOTE_WRONG NOT equivalent of the above (== 4096)) +--- + +$(H6 Unordered operator groups) + +$(P +Precedence between bitwise operators and logical operators are not specified by the language: +) + +--- + if (a & b == c) { $(DERLEME_HATASI) + // ... + } +--- + +$(SHELL +Error: b == c must be parenthesized when next to operator & +) + +$(P +The programmer must specify the desired execution order with parentheses: +) + +--- + if ((a & b) == c) { $(CODE_NOTE compiles) + // ... + } +--- + +$(H6 $(IX =>, operator precedence) The precedence of $(C =>)) + +$(P +Although $(C =>) is not an operator, it takes part in the table twice to specify how it interacts with operators on its left-hand side and right-hand side. +) + +--- + l = a => a = 1; +--- + +$(P +Although both sides of $(C =>) above have an $(C =) operator, $(C =>) has precedence over $(C =) on the left hand side so it $(I binds stronger) to $(C a) as if the programmer wrote the following parentheses: +) + +--- + l = (a => a = 1); +--- + +$(P +On the right-hand side, $(C =>) has lower precedence than $(C =), so the $(C a) on the right-hand side binds stronger to $(C =) as if the following extra set of parentheses are specified: +) + +--- + l = (a => $(HILITE $(PARANTEZ_AC))a = 1$(HILITE $(PARANTEZ_KAPA))); +--- + +$(P +As a result, the lambda expression does not become just $(C a => a) but includes the rest of the expression as well: $(C a => a = 1), which means $(I given a, produce a = 1). That lambda is then assigned to the variable $(C l). +) + +$(P +$(I $(B Note:) This is just an example; otherwise, $(C a = 1) is not a meaningful body for a lambda because the mutation to its parameter $(C a) is seemingly lost and the result of calling the lambda is always 1. (The reason I say "seemingly" is that the assignment operator may have been overloaded for $(C a)'s type and may have side-effects.)) +) + +$(H6 $(IX , (comma), operator) $(IX comma operator) Comma operator) + +$(P +Comma operator is a binary operator. It executes first the left-hand side expression then the right-hand side expression. The values of both expressions are ignored. +) + +--- + int a = 1; + foo()$(HILITE ,) bar()$(HILITE ,) ++a; + + assert(a == 2); +--- + +$(P +The comma operator is most commonly used with $(C for) loops when the loop iteration involves mutating more than one variable: +) + +--- + for ({ int i; int j; } i < 10; ++i$(HILITE ,) ++j) { + // ... + } +--- + +Macros: + TITLE=Operator Precedence + + DESCRIPTION=The precedences and associativity of D operators. + + KEYWORDS=d programming lesson book tutorial operator precedence associativity diff --git a/book/d.en/parallelism.d b/book/d.en/parallelism.d new file mode 100644 index 0000000000..d312e7993b --- /dev/null +++ b/book/d.en/parallelism.d @@ -0,0 +1,1217 @@ +Ddoc + +$(DERS_BOLUMU $(IX parallelism) Parallelism) + +$(P +$(IX core) Most modern microprocessors consist of more than one $(I core), each of which can operate as an individual processing unit. They can execute different parts of different programs at the same time. The features of the $(C std.parallelism) module make it possible for programs to take advantage of all of the cores in order to run faster. +) + +$(P +This chapter covers the following range algorithms. These algorithms should be used only when the operations that are to be executed $(I in parallel) are truly independent from each other. $(I In parallel) means that operations are executed on multiple cores at the same time: +) + +$(UL + +$(LI $(C parallel): Accesses the elements of a range in parallel.) + +$(LI $(C task): Creates tasks that are executed in parallel.) + +$(LI $(C asyncBuf): Iterates the elements of an $(C InputRange) semi-eagerly in parallel.) + +$(LI $(C map): Calls functions with the elements of an $(C InputRange) semi-eagerly in parallel.) + +$(LI $(C amap): Calls functions with the elements of a $(C RandomAccessRange) fully-eagerly in parallel.) + +$(LI $(C reduce): Makes calculations over the elements of a $(C RandomAccessRange) in parallel.) + +) + +$(P +In the programs that we have written so far we have been assuming that the expressions of a program are executed in a certain order, at least in general line-by-line: +) + +--- + ++i; + ++j; +--- + +$(P +In the code above, we expect that the value of $(C i) is incremented before the value of $(C j) is incremented. Although that is semantically correct, it is rarely the case in reality: microprocessors and compilers use optimization techniques to have some variables reside in microprocessor's registers that are independent from each other. When that is the case, the microprocessor would execute operations like the increments above in parallel. +) + +$(P +Although these optimizations are effective, they cannot be applied automatically to layers higher than the very low-level operations. Only the programmer can determine that certain high-level operations are independent and that they can be executed in parallel. +) + +$(P +In a loop, the elements of a range are normally processed one after the other, operations of each element following the operations of previous elements: +) + +--- + auto students = + [ Student(1), Student(2), Student(3), Student(4) ]; + + foreach (student; students) { + student.aSlowOperation(); + } +--- + +$(P +Normally, a program would be executed on one of the cores of the microprocessor, which has been assigned by the operating system to execute the program. As the $(C foreach) loop normally operates on elements one after the other, $(C aSlowOperation()) would be called for each student sequentially. However, in many cases it is not necessary for the operations of preceding students to be completed before starting the operations of successive students. If the operations on the $(C Student) objects were truly independent, it would be wasteful to ignore the other microprocessor cores, which might potentially be waiting idle on the system. +) + +$(P +$(IX Thread.sleep) To simulate long-lasting operations, the following examples call $(C Thread.sleep()) from the $(C core.thread) module. $(C Thread.sleep()) suspends the operations for the specified amount of time. $(C Thread.sleep) is admittedly an artifical method to use in the following examples because it takes time without ever busying any core. Despite being an unrealistic tool, it is still useful in this chapter to demonstrate the power of parallelism. +) + +--- +import std.stdio; +import core.thread; + +struct Student { + int number; + + void aSlowOperation() { + writefln("The work on student %s has begun", number); + + // Wait for a while to simulate a long-lasting operation + Thread.sleep(1.seconds); + + writefln("The work on student %s has ended", number); + } +} + +void main() { + auto students = + [ Student(1), Student(2), Student(3), Student(4) ]; + + foreach (student; students) { + student.aSlowOperation(); + } +} +--- + +$(P +The execution time of the program can be measured in a terminal by $(C time): +) + +$(SHELL +$ $(HILITE time) ./deneme +$(SHELL_OBSERVED +The work on student 1 has begun +The work on student 1 has ended +The work on student 2 has begun +The work on student 2 has ended +The work on student 3 has begun +The work on student 3 has ended +The work on student 4 has begun +The work on student 4 has ended + +real 0m4.005s $(SHELL_NOTE 4 seconds total) +user 0m0.004s +sys 0m0.000s +) +) + +$(P +Since the students are iterated over in sequence and since the work of each student takes 1 second, the total execution time comes out to be 4 seconds. However, if these operations were executed in an environment that had 4 cores, they could be operated on at the same time and the total time would be reduced to about 1 second. +) + +$(P +$(IX totalCPUs) Before seeing how this is done, let's first determine the number of cores that are available on the system by $(C std.parallelism.totalCPUs): +) + +--- +import std.stdio; +import std.parallelism; + +void main() { + writefln("There are %s cores on this system.", totalCPUs); +} +--- + +$(P +The output of the program in the environment that this chapter has been written is the following: +) + +$(SHELL +There are 4 cores on this system. +) + +$(H5 $(IX parallel) $(C taskPool.parallel())) + +$(P +This function can also be called simply as $(C parallel()). +) + +$(P +$(IX foreach, parallel) $(C parallel()) accesses the elements of a range in parallel. An effective usage is with $(C foreach) loops. Merely importing the $(C std.parallelism) module and replacing $(C students) with $(C parallel(students)) in the program above is sufficient to take advantage of all of the cores of the system: +) + +--- +import std.parallelism; +// ... + foreach (student; $(HILITE parallel(students))) { +--- + +$(P +We have seen earlier in the $(LINK2 foreach_opapply.html, $(C foreach) for structs and classes chapter) that the expressions that are in $(C foreach) blocks are passed to $(C opApply()) member functions as delegates. $(C parallel()) returns a range object that knows how to distribute the execution of the $(C delegate) to a separate core for each element. +) + +$(P +As a result, passing the $(C Student) range through $(C parallel()) makes the program above finish in 1 second on a system that has 4 cores: +) + +$(SHELL +$ time ./deneme +$(SHELL_OBSERVED The work on student 2 has begun +The work on student 1 has begun +The work on student 4 has begun +The work on student 3 has begun +The work on student 1 has ended +The work on student 2 has ended +The work on student 4 has ended +The work on student 3 has ended + +real 0m1.005s $(SHELL_NOTE now only 1 second) +user 0m0.004s +sys 0m0.004s) +) + +$(P +$(I $(B Note:) The execution time of the program may be different on other systems but it is expected to be roughly "4 seconds divided by the number of cores".) +) + +$(P +$(IX thread) A flow of execution through certain parts of a program is called a a $(I thread of execution) or a $(I thread). Programs can consist of multiple threads that are being actively executed at the same time. The operating system starts and executes each thread on a core and then suspends it to execute other threads. The execution of each thread may involve many cycles of starting and suspending. +) + +$(P +All of the threads of all of the programs that are active at a given time are executed on the very cores of the microprocessor. The operating system decides when and under what condition to start and suspend each thread. That is the reason why the messages that are printed by $(C aSlowOperation()) are in mixed order in the output above. This undeterministic order of thread execution may not matter if the operations of the $(C Student) objects are truly independent from each other. +) + +$(P +It is the responsibility of the programmer to call $(C parallel()) only when the operations applied to each element are independent for each iteration. For example, if it were important that the messages appear in a certain order in the output, calling $(C parallel()) should be considered an error in the program above. The programming model that supports threads that depend on other threads is called $(I concurrency). Concurrency is the topic of the next chapter. +) + +$(P +By the time parallel $(C foreach) ends, all of the operations inside the loop have been completed for all of the elements. The program can safely continue after the $(C foreach) loop. +) + +$(H6 $(IX work unit size) Work unit size) + +$(P +The second parameter of $(C parallel()) has an overloaded meaning and is ignored in some cases: +) + +--- + /* ... */ = parallel($(I range), $(I work_unit_size) = 100); +--- + +$(UL + +$(LI When iterating over $(C RandomAccessRange) ranges: + +$(P +The distribution of threads to cores has some minimal cost. This cost may sometimes be significant especially when the operations of the loop are completed in a very short time. In such cases, it may be faster to have each thread execute more than one iteration of the loop. The work unit size determines the number of elements that each thread should execute at each of its iterations: +) + +--- + foreach (student; parallel(students, $(HILITE 2))) { + // ... + } +--- + +$(P +The default value of work unit size is 100 and is suitable for most cases. +) + +) + +$(LI When iterating over non-$(C RandomAccessRange) ranges: + +$(P +$(C parallel()) does not start parallel executions until $(I work unit size) number of elements of a non-$(C RandomAccessRange) have been executed serially first. Due to the relatively high value of 100, $(C parallel()) may give the wrong impression that it is not effective when tried on short non-$(C RandomAccessRange) ranges. +) + +) + +$(LI When iterating over the result ranges of $(C asyncBuf()) or parallel $(C map()) (both are explained later in this chapter): + +$(P +When $(C parallel()) works on the results of $(C asyncBuf()) or $(C map()), it ignores the work unit size parameter. Instead, $(C parallel()) reuses the internal buffer of the result range. +) + +) + +) + +$(H5 $(IX Task) $(C Task)) + +$(P +Operations that are executed in parallel with other operations of a program are called $(I tasks). Tasks are represented by the type $(C std.parallelism.Task). +) + +$(P +In fact, $(C parallel()) constructs a new $(C Task) object for every worker thread and starts that task automatically. $(C parallel()) then waits for all of the tasks to be completed before finally exiting the loop. $(C parallel()) is very convenient as it $(I constructs), $(I starts), and $(I waits for) the tasks automatically. +) + +$(P +$(IX task) $(IX executeInNewThread) $(IX yieldForce) When tasks do not correspond to or cannot be represented by elements of a range, these three steps can be handled explicitly by the programmer. $(C task()) constructs, $(C executeInNewThread()) starts, and $(C yieldForce()) waits for a task object. These three functions are explained further in the comments of the following program. +) + +$(P +The $(C anOperation()) function is started twice in the following program. It prints the first letter of $(C id) to indicate which task it is working for. +) + +$(P +$(IX flush, std.stdio) $(I $(B Note:) Normally, the characters that are printed to output streams like $(C stdout) do not appear on the output right away. They are instead stored in an output buffer until a line of output is completed. Since $(C write) does not output a new-line character, in order to observe the parallel execution of the following program, $(C stdout.flush()) is called to send the contents of the buffer to $(C stdout) even before reaching the end of a line.) +) + +--- +import std.stdio; +import std.parallelism; +import std.array; +import core.thread; + +/* Prints the first letter of 'id' every half a second. It + * arbitrarily returns the value 1 to simulate functions that + * do calculations. This result will be used later in main. */ +int anOperation(string id, int duration) { + writefln("%s will take %s seconds", id, duration); + + foreach (i; 0 .. (duration * 2)) { + Thread.sleep(500.msecs); /* half a second */ + write(id.front); + stdout.flush(); + } + + return 1; +} + +void main() { + /* Construct a task object that will execute + * anOperation(). The function parameters that are + * specified here are passed to the task function as its + * function parameters. */ + auto theTask = $(HILITE task!anOperation)("theTask", 5); + + /* Start the task object */ + theTask.$(HILITE executeInNewThread()); + + /* As 'theTask' continues executing, 'anOperation()' is + * being called again, this time directly in main. */ + immutable result = anOperation("main's call", 3); + + /* At this point we are sure that the operation that has + * been started directly from within main has been + * completed, because it has been started by a regular + * function call, not as a task. */ + + /* On the other hand, it is not certain at this point + * whether 'theTask' has completed its operations + * yet. yieldForce() waits for the task to complete its + * operations; it returns only when the task has been + * completed. Its return value is the return value of + * the task function, i.e. anOperation(). */ + immutable taskResult = theTask.$(HILITE yieldForce()); + + writeln(); + writefln("All finished; the result is %s.", + result + taskResult); +} +--- + +$(P +The output of the program should be similar to the following. The fact that the $(C m) and $(C t) letters are printed in mixed order indicates that the operations are executed in parallel: +) + +$(SHELL +main's call will take 3 seconds +theTask will take 5 seconds +mtmttmmttmmttttt +All finished; the result is 2. +) + +$(P +The task function above has been specified as a template parameter to $(C task()) as $(C task!anOperation). Although this method works well in most cases, as we have seen in $(LINK2 templates.html, the Templates chapter), each different instantiation of a template is a different type. This distinction may be undesirable in certain situations where seemingly $(I equivalent) task objects would actually have different types. +) + +$(P +For example, although the following two functions have the same signature, the two $(C Task) instantiations that are produced through calls to the $(C task()) function template would have different types. As a result, they cannot be members of the same array: +) + +--- +import std.parallelism; + +double foo(int i) { + return i * 1.5; +} + +double bar(int i) { + return i * 2.5; +} + +void main() { + auto tasks = [ task$(HILITE !)foo(1), + task$(HILITE !)bar(2) ]; $(DERLEME_HATASI) +} +--- + +$(SHELL +Error: $(HILITE incompatible types) for ((task(1)) : (task(2))): +'Task!($(HILITE foo), int)*' and 'Task!($(HILITE bar), int)*' +) + +$(P +Another overload of $(C task()) takes the function as its first function parameter instead: +) + +--- + void someFunction(int value) { + // ... + } + + auto theTask = task($(HILITE &someFunction), 42); +--- + +$(P +As this method does not involve different instantiations of the $(C Task) template, it makes it possible to put such objects in the same array: +) + +--- +import std.parallelism; + +double foo(int i) { + return i * 1.5; +} + +double bar(int i) { + return i * 2.5; +} + +void main() { + auto tasks = [ task($(HILITE &)foo, 1), + task($(HILITE &)bar, 2) ]; $(CODE_NOTE compiles) +} +--- + +$(P +A lambda function or an object of a type that defines the $(C opCall) member can also be used as the task function. The following example starts a task that executes a lambda: +) + +--- + auto theTask = task((int value) $(HILITE {) + /* ... */ + $(HILITE }), 42); +--- + +$(H6 $(IX exception, parallelism) Exceptions) + +$(P +As tasks are executed on separate threads, the exceptions that they throw cannot be caught by the thread that started them. For that reason, the exceptions that are thrown are automatically caught by the tasks themselves, to be rethrown later when $(C Task) member functions like $(C yieldForce()) are called. This makes it possible for the main thread to catch exceptions that are thrown by a task. +) + +--- +import std.stdio; +import std.parallelism; +import core.thread; + +void mayThrow() { + writeln("mayThrow() is started"); + Thread.sleep(1.seconds); + writeln("mayThrow() is throwing an exception"); + throw new Exception("Error message"); +} + +void main() { + auto theTask = task!mayThrow(); + theTask.executeInNewThread(); + + writeln("main is continuing"); + Thread.sleep(3.seconds); + + writeln("main is waiting for the task"); + theTask.yieldForce(); +} +--- + +$(P +The output of the program shows that the uncaught exception that has been thrown by the task does not terminate the entire program right away (it terminates only the task): +) + +$(SHELL +main is continuing +mayThrow() is started +mayThrow() is throwing an exception $(SHELL_NOTE thrown) +main is waiting for the task +object.Exception@deneme.d(10): Error message $(SHELL_NOTE terminated) +) + +$(P +$(C yieldForce()) can be called in a $(C try-catch) block to catch the exceptions that are thrown by the task. Note that this is different from single threads: In single-threaded programs like the samples that we have been writing until this chapter, $(C try-catch) wraps the code that may throw. In parallelism, it wraps $(C yieldForce()): +) + +--- + try { + theTask.yieldForce(); + + } catch (Exception exc) { + writefln("Detected an error in the task: '%s'", exc.msg); + } +--- + +$(P +This time the exception is caught by the main thread instead of terminating the program: +) + +$(SHELL +main is continuing +mayThrow() is started +mayThrow() is throwing an exception $(SHELL_NOTE thrown) +main is waiting for the task +Detected an error in the task: 'Error message' $(SHELL_NOTE caught) +) + +$(H6 Member functions of $(C Task)) + +$(UL + +$(LI $(C done): Specifies whether the task has been completed; rethrows the exception if the task has been terminated with an exception. + +--- + if (theTask.done) { + writeln("Yes, the task has been completed"); + + } else { + writeln("No, the task is still going on"); + } +--- + +) + +$(LI $(C executeInNewThread()): Starts the task in a new thread.) + +$(LI $(C executeInNewThread(int priority)): Starts the task in a new thread with the specified priority. (Priority is an operating system concept that determines execution priorities of threads.)) + +) + +$(P +There are three functions to wait for the completion of a task: +) + +$(UL + +$(LI $(C yieldForce()): Starts the task if it has not been started yet; if it has already been completed, returns its return value; if it is still running, waits for its completion without making the microprocessor busy; if an exception has been thrown, rethrows that exception.) + +$(LI $(IX spinForce) $(C spinForce()): Works similarly to $(C yieldForce()), except that it makes the microprocessor busy while waiting, in order to catch the completion as early as possible.) + +$(LI $(IX workForce) $(C workForce()): Works similarly to $(C yieldForce()), except that it starts a new task in the current thread while waiting for the task to be completed.) + +) + +$(P +In most cases $(C yieldForce()) is the most suitable function to call when waiting for a task to complete; it suspends the thread that calls $(C yieldForce()) until the task is completed. Although $(C spinForce()) makes the microprocessor busy while waiting, it is suitable when the task is expected to be completed in a very short time. $(C workForce()) can be called when starting other tasks is preferred over suspending the current thread. +) + +$(P +Please see the online documentation of Phobos for the other member functions of $(C Task). +) + +$(H5 $(IX asyncBuf) $(C taskPool.asyncBuf())) + +$(P +Similarly to $(C parallel()), $(C asyncBuf()) iterates $(C InputRange) ranges in parallel. It stores the elements in a buffer as they are produced by the range, and serves the elements from that buffer to its user. +) + +$(P +In order to avoid making a potentially fully-lazy input range a fully-eager range, it iterates the elements in $(I waves). Once it prepares certain number of elements in parallel, it waits until those elements are consumed by $(C popFront()) before producing the elements of the next wave. +) + +$(P +$(C asyncBuf()) takes a range and an optional $(I buffer size) that determines how many elements to be made available during each wave: +) + +--- + auto elements = taskPool.asyncBuf($(I range), $(I buffer_size)); +--- + +$(P +To see the effects of $(C asyncBuf()), let's use a range that takes half a second to iterate and half a second to process each element. This range simply produces integers up to the specified limit: +) + +--- +import std.stdio; +import core.thread; + +struct Range { + int limit; + int i; + + bool empty() const { + return i >= limit; + } + + int front() const { + return i; + } + + void popFront() { + writefln("Producing the element after %s", i); + Thread.sleep(500.msecs); + ++i; + } +} + +void main() { + auto range = Range(10); + + foreach (element; range) { + writefln("Using element %s", element); + Thread.sleep(500.msecs); + } +} +--- + +$(P +The elements are produced and used lazily. Since it takes one second for each element, the whole range takes ten seconds to process in this program: +) + +$(SHELL +$ time ./deneme +$(SHELL_OBSERVED +Using element 0 +Producing the element after 0 +Using element 1 +Producing the element after 1 +Using element 2 +... +Producing the element after 8 +Using element 9 +Producing the element after 9 + +real 0m10.007s $(SHELL_NOTE 10 seconds total) +user 0m0.004s +sys 0m0.000s) +) + +$(P +According to that output, the elements are produced and used sequentially. +) + +$(P +On the other hand, it may not be necessary to wait for preceding elements to be processed before starting to produce the successive elements. The program would take less time if other elements could be produced while the front element is in use: +) + +--- +import std.parallelism; +//... + foreach (element; $(HILITE taskPool.asyncBuf)(range, $(HILITE 2))) { +--- + +$(P +In the call above, $(C asyncBuf()) makes two elements ready in its buffer. Elements are produced in parallel while they are being used: +) + +$(SHELL +$ time ./deneme +$(SHELL_OBSERVED +Producing the element after 0 +Producing the element after 1 +Using element 0 +Producing the element after 2 +Using element 1 +Producing the element after 3 +Using element 2 +Producing the element after 4 +Using element 3 +Producing the element after 5 +Using element 4 +Producing the element after 6 +Producing the element after 7 +Using element 5 +Using element 6 +Producing the element after 8 +Producing the element after 9 +Using element 7 +Using element 8 +Using element 9 + +real 0m6.007s $(SHELL_NOTE now 6 seconds) +user 0m0.000s +sys 0m0.004s) +) + +$(P +The default value of buffer size is 100. The buffer size that produces the best performance would be different under different situations. +) + +$(P +$(C asyncBuf()) can be used outside of $(C foreach) loops as well. For example, the following code uses the return value of $(C asyncBuf()) as an $(C InputRange) which operates semi-eagerly: +) + +--- + auto range = Range(10); + auto asyncRange = taskPool.asyncBuf(range, 2); + writeln($(HILITE asyncRange.front)); +--- + +$(H5 $(IX map, parallel) $(C taskPool.map())) + +$(P +$(IX map, std.algorithm) It helps to explain $(C map()) from the $(C std.algorithm) module before explaining $(C taskPool.map()). $(C std.algorithm.map) is an algorithm commonly found in many functional languages. It calls a function with the elements of a range one-by-one and returns a range that consists of the results of calling that function with each element. It is a lazy algorithm: It calls the function as needed. (There is also $(C std.algorithm.each), which is for generating side effects for each element, as opposed to producing a result from it.) +) + +$(P +The fact that $(C std.algorithm.map) operates lazily is very powerful in many programs. However, if the function needs to be called with every element anyway and the operations on each element are independent from each other, laziness may be unnecessarily slower than parallel execution. $(C taskPool.map()) and $(C taskPool.amap()) from the $(C std.parallelism) module take advantage of multiple cores and run faster in many cases. +) + +$(P +Let's compare these three algorithms using the $(C Student) example. Let's assume that $(C Student) has a member function that returns the average grade of the student. To demonstrate how parallel algorithms are faster, let's again slow this function down with $(C Thread.sleep()). +) + +$(P +$(C std.algorithm.map) takes the function as its template parameter, and the range as its function parameter. It returns a range that consists of the results of applying that function to the elements of the range: +) + +--- + auto $(I result_range) = map!$(I func)($(I range)); +--- + +$(P +The function may be specified by the $(C =>) syntax as a $(I lambda expression) as we have seen in earlier chapters. The following program uses $(C map()) to call the $(C averageGrade()) member function on each element: +) + +--- +import std.stdio; +import std.algorithm; +import core.thread; + +struct Student { + int number; + int[] grades; + + double averageGrade() { + writefln("Started working on student %s", + number); + Thread.sleep(1.seconds); + + const average = grades.sum / grades.length; + + writefln("Finished working on student %s", number); + return average; + } +} + +void main() { + Student[] students; + + foreach (i; 0 .. 10) { + /* Two grades for each student */ + students ~= Student(i, [80 + i, 90 + i]); + } + + auto results = $(HILITE map)!(a => a.averageGrade)(students); + + foreach (result; results) { + writeln(result); + } +} +--- + +$(P +The output of the program demonstrates that $(C map()) operates lazily; $(C averageGrade()) is called for each result as the $(C foreach) loop iterates: +) + +$(SHELL +$ time ./deneme +$(SHELL_OBSERVED +Started working on student 0 +Finished working on student 0 +85 $(SHELL_NOTE calculated as foreach iterates) +Started working on student 1 +Finished working on student 1 +86 +... +Started working on student 9 +Finished working on student 9 +94 + +real 0m10.006s $(SHELL_NOTE 10 seconds total) +user 0m0.000s +sys 0m0.004s) +) + +$(P +If $(C std.algorithm.map) were an eager algorithm, the messages about the starts and finishes of the operations would be printed altogether at the top. +) + +$(P +$(C taskPool.map()) from the $(C std.parallelism) module works essentially the same as $(C std.algorithm.map). The only difference is that it executes the function calls semi-eagerly and stores the results in a buffer to be served from as needed. The size of this buffer is determined by the second parameter. For example, the following code would make ready the results of the function calls for three elements at a time: +) + +--- +import std.parallelism; +// ... +double averageGrade(Student student) { + return student.averageGrade; +} +// ... + auto results = $(HILITE taskPool.map)!averageGrade(students, $(HILITE 3)); +--- + +$(P +$(I $(B Note:) The free-standing $(C averageGrade()) function above is needed due to a limitation that involves using local delegates with member function templates like $(C TaskPool.map). There would be a compilation error without that free-standing function: +)) + +--- +auto results = + taskPool.map!(a => a.averageGrade)(students, 3); $(DERLEME_HATASI) +--- + +$(P +This time the operations are executed in waves of three elements: +) + +$(SHELL +$ time ./deneme +$(SHELL_OBSERVED +Started working on student 1 $(SHELL_NOTE in parallel) +Started working on student 2 $(SHELL_NOTE but in unpredictable order) +Started working on student 0 +Finished working on student 1 +Finished working on student 2 +Finished working on student 0 +85 +86 +87 +Started working on student 4 +Started working on student 5 +Started working on student 3 +Finished working on student 4 +Finished working on student 3 +Finished working on student 5 +88 +89 +90 +Started working on student 7 +Started working on student 8 +Started working on student 6 +Finished working on student 7 +Finished working on student 6 +Finished working on student 8 +91 +92 +93 +Started working on student 9 +Finished working on student 9 +94 + +real 0m4.007s $(SHELL_NOTE 4 seconds total) +user 0m0.000s +sys 0m0.004s) +) + +$(P +The second parameter of $(C map()) has the same meaning as $(C asyncBuf()): It determines the size of the buffer that $(C map()) uses to store the results in. The third parameter is the work unit size as in $(C parallel()); the difference being its default value, which is $(C size_t.max): +) + +--- + /* ... */ = taskPool.map!$(I func)($(I range), + $(I buffer_size) = 100 + $(I work_unit_size) = size_t.max); +--- + +$(H5 $(IX amap) $(C taskPool.amap())) + +$(P +Parallel $(C amap()) works the same as parallel $(C map()) with two differences: +) + +$(UL + +$(LI +It is fully eager. +) + +$(LI +It works with $(C RandomAccessRange) ranges. +) + +) + +--- + auto results = $(HILITE taskPool.amap)!averageGrade(students); +--- + +$(P +Since it is eager, all of the results are ready by the time $(C amap()) returns: +) + +$(SHELL +$ time ./deneme +$(SHELL_OBSERVED +Started working on student 1 $(SHELL_NOTE all are executed up front) +Started working on student 0 +Started working on student 2 +Started working on student 3 +Finished working on student 1 +Started working on student 4 +Finished working on student 2 +Finished working on student 3 +Started working on student 6 +Finished working on student 0 +Started working on student 7 +Started working on student 5 +Finished working on student 4 +Started working on student 8 +Finished working on student 6 +Started working on student 9 +Finished working on student 7 +Finished working on student 5 +Finished working on student 8 +Finished working on student 9 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 + +real 0m3.005s $(SHELL_NOTE 3 seconds total) +user 0m0.000s +sys 0m0.004s) +) + +$(P +$(C amap()) works faster than $(C map()) at the expense of using an array that is large enough to store all of the results. It consumes more memory to gain speed. +) + +$(P +The optional second parameter of $(C amap()) is the work unit size as well: +) + +--- + auto results = taskPool.amap!averageGrade(students, $(HILITE 2)); +--- + +$(P +The results can also be stored in a $(C RandomAccessRange) that is passed to $(C amap()) as its third parameter: +) + +--- + double[] results; + results.length = students.length; + taskPool.amap!averageGrade(students, 2, $(HILITE results)); +--- + +$(H5 $(IX reduce, parallel) $(C taskPool.reduce())) + +$(P +$(IX reduce, std.algorithm) As with $(C map()), it helps to explain $(C reduce()) from the $(C std.algorithm) module first. +) + +$(P +$(IX fold, std.algorithm) $(C reduce()) is the equivalent of $(C std.algorithm.fold), which we have seen before in the $(LINK2 ranges.html, Ranges chapter). The main difference between the two is that their function parameters are reversed. (For that reason, I recommend that you prefer $(C fold()) for non-parallel code as it can take advantage of $(LINK2 ufcs.html, UFCS) in chained range expressions.) +) + +$(P +$(C reduce()) is another high-level algorithm commonly found in many functional languages. Just like $(C map()), it takes one or more functions as template parameters. As its function parameters, it takes a value to be used as the initial value of the result, and a range. $(C reduce()) calls the functions with the current value of the result and each element of the range. When no initial value is specified, the first element of the range is used instead. +) + +$(P +Assuming that it defines a variable named $(C result) in its implementation, the way that $(C reduce()) works can be described by the following steps: +) + +$(OL + +$(LI Assigns the initial value to $(C result)) + +$(LI Executes the expression $(C result = func(result, element)) for every element) + +$(LI Returns the final value of $(C result)) + +) + +$(P +For example, the sum of the squares of the elements of an array can be calculated as in the following program: +) + +--- +import std.stdio; +import std.algorithm; + +void main() { + writeln(reduce!((a, b) => a + b * b)(0, [5, 10])); +} +--- + +$(P +When the function is specified by the $(C =>) syntax as in the program above, the first parameter (here $(C a)) represents the current value of the result (initialized by the parameter $(C 0) above) and the second parameter (here $(C b)) represents the current element. +) + +$(P +The program outputs the sum of 25 and 100, the squares of 5 and 10: +) + +$(SHELL +125 +) + +$(P +As obvious from its behavior, $(C reduce()) uses a loop in its implementation. Because that loop is normally executed on a single core, it may be unnecessarily slow when the function calls for each element are independent from each other. In such cases $(C taskPool.reduce()) from the $(C std.parallelism) module can be used for taking advantage of all of the cores. +) + +$(P +To see an example of this let's use $(C reduce()) with a function that is slowed down again artificially: +) + +--- +import std.stdio; +import std.algorithm; +import core.thread; + +int aCalculation(int result, int element) { + writefln("started - element: %s, result: %s", + element, result); + + Thread.sleep(1.seconds); + result += element; + + writefln("finished - element: %s, result: %s", + element, result); + + return result; +} + +void main() { + writeln("Result: ", $(HILITE reduce)!aCalculation(0, [1, 2, 3, 4])); +} +--- + +$(P +$(C reduce()) uses the elements in sequence to reach the final value of the result: +) + +$(SHELL +$ time ./deneme +$(SHELL_OBSERVED +started - element: 1, result: 0 +finished - element: 1, result: 1 +started - element: 2, result: 1 +finished - element: 2, result: 3 +started - element: 3, result: 3 +finished - element: 3, result: 6 +started - element: 4, result: 6 +finished - element: 4, result: 10 +Result: 10 + +real 0m4.003s $(SHELL_NOTE 4 seconds total) +user 0m0.000s +sys 0m0.000s) +) + +$(P +As in the $(C parallel()) and $(C map()) examples, importing the $(C std.parallelism) module and calling $(C taskPool.reduce()) is sufficient to take advantage of all of the cores: +) + +--- +import std.parallelism; +// ... + writeln("Result: ", $(HILITE taskPool.reduce)!aCalculation(0, [1, 2, 3, 4])); +--- + +$(P +However, there are important differences in the way $(C taskPool.reduce()) works. +) + +$(P +Like the other parallel algorithms, $(C taskPool.reduce()) executes the functions in parallel by using elements in different tasks. Each task works on the elements that it is assigned to and calculates a $(C result) that corresponds to the elements of that task. Since $(C reduce()) is called with only a single initial value, every task must use that same initial value to initialize its own $(C result) (the parameter $(C 0) above). +) + +$(P +The final values of the results that each task produces are themselves used in the same $(C result) calculation one last time. These final calculations are executed sequentially, not in parallel. For that reason, $(C taskPool.reduce()) may execute slower in short examples as in this chapter as will be observed in the following output. +) + +$(P +The fact that the same initial value is used for all of the tasks, effectively being used in the calculations multiple times, $(C taskPool.reduce()) may calculate a result that is different from what $(C std.algorithm.reduce()) calculates. For that reason, the initial value must be the $(I identity value) for the calculation that is being performed, e.g. the $(C 0) in this example which does not have any effect in addition. +) + +$(P +Additionally, as the results are used by the same functions one last time in the sequential calculations, the types of the parameters that the functions take must be compatible with the types of the values that the functions return. +) + +$(P +$(C taskPool.reduce()) should be used only under these considerations. +) + +--- +import std.parallelism; +// ... + writeln("Result: ", $(HILITE taskPool.reduce)!aCalculation(0, [1, 2, 3, 4])); +--- + +$(P +The output of the program indicates that first the calculations are performed in parallel, and then their results are calculated sequentially. The calculations that are performed sequentially are highlighted: +) + +$(SHELL +$ time ./deneme +$(SHELL_OBSERVED +started - element: 3, result: 0 $(SHELL_NOTE first, the tasks in parallel) +started - element: 2, result: 0 +started - element: 1, result: 0 +started - element: 4, result: 0 +finished - element: 3, result: 3 +finished - element: 1, result: 1 +$(HILITE started - element: 1, result: 0) $(SHELL_NOTE then, their results sequentially) +finished - element: 4, result: 4 +finished - element: 2, result: 2 +$(HILITE finished - element: 1, result: 1) +$(HILITE started - element: 2, result: 1) +$(HILITE finished - element: 2, result: 3) +$(HILITE started - element: 3, result: 3) +$(HILITE finished - element: 3, result: 6) +$(HILITE started - element: 4, result: 6) +$(HILITE finished - element: 4, result: 10) +Result: 10 + +real 0m5.006s $(SHELL_NOTE parallel reduce is slower in this example) +user 0m0.004s +sys 0m0.000s) +) + +$(P +Parallel $(C reduce()) is faster in many other calculations like the calculation of the math constant $(I pi) (π) by quadrature. +) + +$(H5 Multiple functions and tuple results) + +$(P +$(C std.algorithm.map()), $(C taskPool.map()), $(C taskPool.amap()), and $(C taskPool.reduce()) can all take more than one function, in which case the results are returned as a $(C Tuple). We have seen the $(C Tuple) type in the $(LINK2 tuples.html, Tuples chapter) before. The results of individual functions correspond to the elements of the tuple in the order that the functions are specified. For example, the result of the first function is the first member of the tuple. +) + +$(P +The following program demonstrates multiple functions with $(C std.algorithm.map). Note that the return types of the functions need not be the same, as seen in the $(C quarterOf()) and $(C tenTimes()) functions below. In that case, the types of the members of the tuples would be different as well: +) + +--- +import std.stdio; +import std.algorithm; +import std.conv; + +double quarterOf(double value) { + return value / 4; +} + +string tenTimes(double value) { + return to!string(value * 10); +} + +void main() { + auto values = [10, 42, 100]; + auto results = map!($(HILITE quarterOf, tenTimes))(values); + + writefln(" Quarters Ten Times"); + + foreach (quarterResult, tenTimesResult; results) { + writefln("%8.2f%8s", quarterResult, tenTimesResult); + } +} +--- + +$(P +The output: +) + +$(SHELL + Quarters Ten Times + 2.50 100 + 10.50 420 + 25.00 1000 +) + +$(P +In the case of $(C taskPool.reduce()), the initial values of the results must be specified as a tuple: +) + +--- + taskPool.reduce!(foo, bar)($(HILITE tuple(0, 1)), [1, 2, 3, 4]); +--- + +$(H5 $(IX TaskPool) $(C TaskPool)) + +$(P +Behind the scenes, the parallel algorithms from the $(C std.parallelism) module all use task objects that are elements of a $(C TaskPool) container. Normally, all of the algorithms use the same container object named $(C taskPool). +) + +$(P +$(C taskPool) contains appropriate number of tasks depending on the environment that the program runs under. For that reason, usually there is no need to create any other $(C TaskPool) object. Even so, explicit $(C TaskPool) objects may be created and used as needed. +) + +$(P +The $(C TaskPool) constructor takes the number of threads to use during the parallel operations that are later started through it. The default value of the number of threads is one less than the number of cores on the system. All of the features that we have seen in this chapter can be applied to a separate $(C TaskPool) object. +) + +$(P +The following example calls $(C parallel()) on a local $(C TaskPool) object: +) + +--- +import std.stdio; +import std.parallelism; + +void $(CODE_DONT_TEST compiler_asm_deprecation_warning)main() { + auto workers = new $(HILITE TaskPool(2)); + + foreach (i; $(HILITE workers).parallel([1, 2, 3, 4])) { + writefln("Working on %s", i); + } + + $(HILITE workers).finish(); +} +--- + +$(P +$(C TaskPool.finish()) tells the object to stop processing when all of its current tasks are completed. +) + +$(H5 Summary) + + +$(UL + +$(LI It is an error to execute operations in parallel unless those operations are independent from each other.) + +$(LI $(C parallel()) accesses the elements of a range in parallel.) + +$(LI Tasks can explicitly be created, started, and waited for by $(C task()), $(C executeInNewThread()), and $(C yieldForce()), respectively.) + +$(LI The exceptions that are escaped from tasks can be caught later by most of the parallelism functions like $(C yieldForce()).) + +$(LI $(C asyncBuf()) iterates the elements of an $(C InputRange) semi-eagerly in parallel.) + +$(LI $(C map()) calls functions with the elements of an $(C InputRange) semi-eagerly in parallel.) + +$(LI $(C amap()) calls functions with the elements of a $(C RandomAccessRange) fully-eagerly in parallel.) + +$(LI $(C reduce()) makes calculations over the elements of a $(C RandomAccessRange) in parallel.) + +$(LI $(C map()), $(C amap()), and $(C reduce()) can take multiple functions and return the results as tuples.) + +$(LI When needed, $(C TaskPool) objects other than $(C taskPool) can be used.) + +) + +macros: + TITLE=Parallelism + + DESCRIPTION=Parallel programming that enables taking advantage of microprocessor cores + + KEYWORDS=d programming language tutorial book parallel programming + +MINI_SOZLUK= diff --git a/book/d.en/parameter_flexibility.cozum.d b/book/d.en/parameter_flexibility.cozum.d new file mode 100644 index 0000000000..e2c64af50e --- /dev/null +++ b/book/d.en/parameter_flexibility.cozum.d @@ -0,0 +1,105 @@ +Ddoc + +$(COZUM_BOLUMU Variable Number of Parameters) + +$(P +For the $(C calculate()) function to be able to take variable number of parameters, its parameter list must include a slice of $(C Calculation) followed by $(C ...): +) + +--- +double[] calculate(Calculation[] calculations...) { + double[] results; + + foreach (calculation; calculations) { + final switch (calculation.op) { + + case Operation.add: + results ~= calculation.first + calculation.second; + break; + + case Operation.subtract: + results ~= calculation.first - calculation.second; + break; + + case Operation.multiply: + results ~= calculation.first * calculation.second; + break; + + case Operation.divide: + results ~= calculation.first / calculation.second; + break; + } + } + + return results; +} +--- + +$(P +Each calculation is evaluated inside a loop and their results are appended to a slice of type $(C double[]). +) + +$(P +Here is the entire program: +) + +--- +import std.stdio; + +enum Operation { add, subtract, multiply, divide } + +struct Calculation { + Operation op; + double first; + double second; +} + +double[] calculate(Calculation[] calculations...) { + double[] results; + + foreach (calculation; calculations) { + final switch (calculation.op) { + + case Operation.add: + results ~= calculation.first + calculation.second; + break; + + case Operation.subtract: + results ~= calculation.first - calculation.second; + break; + + case Operation.multiply: + results ~= calculation.first * calculation.second; + break; + + case Operation.divide: + results ~= calculation.first / calculation.second; + break; + } + } + + return results; +} + +void main() { + writeln(calculate(Calculation(Operation.add, 1.1, 2.2), + Calculation(Operation.subtract, 3.3, 4.4), + Calculation(Operation.multiply, 5.5, 6.6), + Calculation(Operation.divide, 7.7, 8.8))); +} +--- + +$(P +The output: +) + +$(SHELL +[3.3, -1.1, 36.3, 0.875] +) + +Macros: + TITLE=Variable Number of Parameters + + DESCRIPTION=Exercise solutions of the 'Variable Number of Parameters' chapter of the tutorial book 'Programming in D'. + + KEYWORDS=d programming book tutorial variadic functions exercise solutions diff --git a/book/d.en/parameter_flexibility.d b/book/d.en/parameter_flexibility.d new file mode 100644 index 0000000000..032a143e9c --- /dev/null +++ b/book/d.en/parameter_flexibility.d @@ -0,0 +1,527 @@ +Ddoc + +$(DERS_BOLUMU $(IX parameter, variable number of) Variable Number of Parameters) + +$(P +This chapter covers two D features that bring flexibility on parameters when calling functions: +) + +$(UL +$(LI Default arguments) +$(LI Variadic functions) +) + +$(H5 $(IX default argument) $(IX argument, default) Default arguments) + +$(P +A convenience with function parameters is the ability to specify default values for them. This is similar to the default initial values of struct members. +) + +$(P +Some of the parameters of some functions are called mostly by the same values. To see an example of this, let's consider a function that prints the elements of an associative array of type $(C string[string]). Let's assume that the function takes the separator characters as parameters as well: +) + +--- +$(CODE_NAME printAA)import std.algorithm; + +// ... + +void printAA(string title, + string[string] aa, + string keySeparator, + string elementSeparator) { + writeln("-- ", title, " --"); + + auto keys = sort(aa.keys); + + // Don't print element separator before the first element + if (keys.length != 0) { + auto key = keys[0]; + write(key, keySeparator, aa[key]); + keys = keys[1..$]; // Remove the first element + } + + // Print element separator before the remaining elements + foreach (key; keys) { + write(elementSeparator); + write(key, keySeparator, aa[key]); + } + + writeln(); +} +--- + +$(P +That function is being called below with $(STRING ":") as the key separator and $(STRING ", ") as the element separator: +) + +--- +$(CODE_XREF printAA)void main() { + string[string] dictionary = [ + "blue":"mavi", "red":"kırmızı", "gray":"gri" ]; + + printAA("Color Dictionary", dictionary, ":", ", "); +} +--- + +$(P +The output: +) + +$(SHELL +-- Color Dictionary -- +blue:mavi, gray:gri, red:kırmızı +) + +$(P +If the separators are almost always going to be those two, they can be defined with default values: +) + +--- +void printAA(string title, + string[string] aa, + string keySeparator $(HILITE = ": "), + string elementSeparator $(HILITE = ", ")) { + // ... +} +--- + +$(P +Parameters with default values need not be specified when the function is called: +) + +--- + printAA("Color Dictionary", + dictionary); /* ← No separator specified. Both + * parameters will get their + * default values. */ +--- + +$(P +The parameter values can still be specified when needed, and not necessarily all of them: +) + +--- + printAA("Color Dictionary", dictionary$(HILITE , "=")); +--- + +$(P +The output: +) + +$(SHELL +-- Color Dictionary -- +blue=mavi, gray=gri, red=kırmızı +) + +$(P +The following call specifies both of the parameters: +) + +--- + printAA("Color Dictionary", dictionary$(HILITE , "=", "\n")); +--- + +$(P +The output: +) + +$(SHELL +-- Color Dictionary -- +blue=mavi +gray=gri +red=kırmızı +) + +$(P +Default values can only be defined for the parameters that are at the end of the parameter list. +) + +$(H6 Special keywords as default arguments) + +$(P +$(IX special keyword) $(IX keyword, special) The following special keywords act like compile-time literals having values corresponding to where they appear in code: +) + +$(UL + +$(LI $(IX __MODULE__) $(C __MODULE__): Name of the module as $(C string)) +$(LI $(IX __FILE__) $(C __FILE__): Name of the source file as $(C string)) +$(LI $(IX __FILE_FULL_PATH__) $(C __FILE_FULL_PATH__): Name of the source file including its full path as $(C string)) +$(LI $(IX __LINE__) $(C __LINE__): Line number as $(C int)) +$(LI $(IX __FUNCTION__) $(C __FUNCTION__): Name of the function as $(C string)) +$(LI $(IX __PRETTY_FUNCTION__) $(C __PRETTY_FUNCTION__): Full signature of the function as $(C string)) + +) + +$(P +Although they can be useful anywhere in code, they work differently when used as default arguments. When they are used in regular code, their values refer to where they appear in code: +) + +--- +import std.stdio; + +void func(int parameter) { + writefln("Inside function %s at file %s, line %s.", + __FUNCTION__, __FILE__, __LINE__); $(CODE_NOTE $(HILITE line 5)) +} + +void main() { + func(42); +} +--- + +$(P +The reported line 5 is inside the function: +) + +$(SHELL +Inside function deneme.$(HILITE func) at file deneme.d, $(HILITE line 5). +) + +$(P +However, sometimes it is more interesting to determine the line where a function is called from, not where the definition of the function is. When these special keywords are provided as default arguments, their values refer to where the function is called from: +) + +--- +import std.stdio; + +void func(int parameter, + string functionName = $(HILITE __FUNCTION__), + string file = $(HILITE __FILE__), + int line = $(HILITE __LINE__)) { + writefln("Called from function %s at file %s, line %s.", + functionName, file, line); +} + +void main() { + func(42); $(CODE_NOTE $(HILITE line 12)) +} +--- + +$(P +This time the special keywords refer to $(C main()), the caller of the function: +) + +$(SHELL +Called from function deneme.$(HILITE main) at file deneme.d, $(HILITE line 12). +) + +$(P +$(IX special token) $(IX token, special) In addition to the above, there are also the following $(I special tokens) that take values depending on the compiler and the time of day: +) + +$(UL + +$(LI $(IX __DATE__) $(C __DATE__): Date of compilation as $(C string)) + +$(LI $(IX __TIME__) $(C __TIME__): Time of compilation as $(C string)) + +$(LI $(IX __TIMESTAMP__) $(C __TIMESTAMP__): Date and time of compilation as $(C string)) + +$(LI $(IX __VENDOR__) $(C __VENDOR__): Compiler vendor as $(C string) (e.g. $(STRING "Digital Mars D"))) + +$(LI $(IX __VERSION__) $(C __VERSION__): Compiler version as $(C long) (e.g. the value $(C 2081L) for version 2.081)) + +) + +$(H5 $(IX variadic function) Variadic functions) + +$(P +Despite appearances, default parameter values do not change the number of parameters that a function receives. For example, even though some parameters may be assigned their default values, $(C printAA()) always takes four parameters and uses them according to its implementation. +) + +$(P +On the other hand, variadic functions can be called with unspecified number of arguments. We have already been taking advantage of this feature with functions like $(C writeln()). $(C writeln()) can be called with any number of arguments: +) + +--- + writeln( + "hello", 7, "world", 9.8 /*, and any number of other + * arguments as needed */); +--- + +$(P +There are four ways of defining variadic functions in D: +) + +$(UL + +$(LI $(IX _argptr) The feature that works only for functions that are marked as $(C extern(C)). This feature defines the hidden $(C _argptr) variable that is used for accessing the parameters. This book does not cover this feature partly because it is unsafe.) + +$(LI $(IX _arguments) The feature that works with regular D functions, which also uses the hidden $(C _argptr) variable, as well as the $(C _arguments) variable, the latter being of type $(C TypeInfo[]). This book does not cover this feature as well both because it relies on $(I pointers), which have not been covered yet, and because this feature can be used in unsafe ways as well.) + +$(LI A safe feature with the limitation that the unspecified number of parameters must all be of the same type. This is the feature that is covered in this section.) + +$(LI Unspecified number of template parameters. This feature will be explained later in the templates chapters.) + +) + +$(P +$(IX ..., function parameter) The parameters of variadic functions are passed to the function as a slice. Variadic functions are defined with a single parameter of a specific type of slice followed immediately by the $(C ...) characters: +) + +--- +double sum(double[] numbers$(HILITE ...)) { + double result = 0.0; + + foreach (number; numbers) { + result += number; + } + + return result; +} +--- + +$(P +That definition makes $(C sum()) a variadic function, meaning that it is able to receive any number of arguments as long as they are $(C double) or any other type that can implicitly be convertible to $(C double): +) + +--- + writeln(sum($(HILITE 1.1, 2.2, 3.3))); +--- + +$(P +The single slice parameter and the $(C ...) characters represent all of the arguments. For example, the slice would have five elements if the function were called with five $(C double) values. +) + +$(P +In fact, the variable number of parameters can also be passed as a single slice: +) + +--- + writeln(sum($(HILITE [) 1.1, 2.2, 3.3 $(HILITE ]))); // same as above +--- + +$(P +Variadic functions can also have required parameters, which must be defined first in the parameter list. For example, the following function prints an unspecified number of parameters within parentheses. Although the function leaves the number of the elements flexible, it requires that the parentheses are always specified: +) + +--- +char[] parenthesize( + string opening, // ← The first two parameters must be + string closing, // specified when the function is called + string[] words...) { // ← Need not be specified + char[] result; + + foreach (word; words) { + result ~= opening; + result ~= word; + result ~= closing; + } + + return result; +} +--- + +$(P +The first two parameters are mandatory: +) + +--- + parenthesize("{"); $(DERLEME_HATASI) +--- + +$(P +As long as the mandatory parameters are specified, the rest are optional: +) + +--- + writeln(parenthesize("{", "}", "apple", "pear", "banana")); +--- + +$(P +The output: +) + +$(SHELL +{apple}{pear}{banana} +) + +$(H6 Variadic function arguments have a short lifetime) + +$(P +The slice argument that is automatically generated for a variadic parameter points at a temporary array that has a short lifetime. This fact does not matter if the function uses the arguments only during its execution. However, it would be a bug if the function kept a slice to those elements for later use: +) + +--- +int[] numbersForLaterUse; + +void foo(int[] numbers...) { + numbersForLaterUse = numbers; $(CODE_NOTE_WRONG BUG) +} + +struct S { + string[] namesForLaterUse; + + void foo(string[] names...) { + namesForLaterUse = names; $(CODE_NOTE_WRONG BUG) + } +} + +void bar() { + foo(1, 10, 100); /* The temporary array [ 1, 10, 100 ] is + * not valid beyond this point. */ + + auto s = S(); + s.foo("hello", "world"); /* The temporary array + * [ "hello", "world" ] is not + * valid beyond this point. */ + + // ... +} + +void main() { + bar(); +} +--- + +$(P +Both the free-standing function $(C foo()) and the member function $(C S.foo()) are in error because they store slices to automatically-generated temporary arrays that live on the program stack. Those arrays are valid only during the execution of the variadic functions. +) + +$(P +For that reason, if a function needs to store a slice to the elements of a variadic parameter, it must first take a copy of those elements: +) + +--- +void foo(int[] numbers...) { + numbersForLaterUse = numbers$(HILITE .dup); $(CODE_NOTE correct) +} + +// ... + + void foo(string[] names...) { + namesForLaterUse = names$(HILITE .dup); $(CODE_NOTE correct) + } +--- + +$(P +However, since variadic functions can also be called with slices of proper arrays, copying the elements would be unnecessary in those cases. +) + +$(P +A solution that is both correct and efficient is to define two functions having the same name, one taking a variadic parameter and the other taking a proper slice. If the caller passes variable number of arguments, then the variadic version of the function is called; and if the caller passes a proper slice, then the version that takes a proper slice is called: +) + +--- +int[] numbersForLaterUse; + +void foo(int[] numbers$(HILITE ...)) { + /* Since this is the variadic version of foo(), we must + * first take a copy of the elements before storing a + * slice to them. */ + numbersForLaterUse = numbers$(HILITE .dup); +} + +void foo(int[] numbers) { + /* Since this is the non-variadic version of foo(), we can + * store the slice as is. */ + numbersForLaterUse = numbers; +} + +struct S { + string[] namesForLaterUse; + + void foo(string[] names$(HILITE ...)) { + /* Since this is the variadic version of S.foo(), we + * must first take a copy of the elements before + * storing a slice to them. */ + namesForLaterUse = names$(HILITE .dup); + } + + void foo(string[] names) { + /* Since this is the non-variadic version of S.foo(), + * we can store the slice as is. */ + namesForLaterUse = names; + } +} + +void bar() { + // This call is dispatched to the variadic function. + foo(1, 10, 100); + + // This call is dispatched to the proper slice function. + foo($(HILITE [) 2, 20, 200 $(HILITE ])); + + auto s = S(); + + // This call is dispatched to the variadic function. + s.foo("hello", "world"); + + // This call is dispatched to the proper slice function. + s.foo($(HILITE [) "hi", "moon" $(HILITE ])); + + // ... +} + +void main() { + bar(); +} +--- + +$(P +Defining multiple functions with the same name but with different parameters is called $(I function overloading), which is the subject of the next chapter. +) + +$(PROBLEM_TEK + +$(P +Assume that the following $(C enum) is already defined: +) + +--- +enum Operation { add, subtract, multiply, divide } +--- + +$(P +Also assume that there is a $(C struct) that represents the calculation of an operation and its two operands: +) + +--- +struct Calculation { + Operation op; + double first; + double second; +} +--- + +$(P +For example, the object $(C Calculation(Operation.divide, 7.7, 8.8)) would represent the division of 7.7 by 8.8. +) + +$(P +Design a function that receives an unspecified number of these $(C struct) objects, calculates the result of each $(C Calculation), and then returns all of the results as a slice of type $(C double[]). +) + +$(P +For example, it should be possible to call the function as in the following code: +) + +--- +void $(CODE_DONT_TEST)main() { + writeln( + calculate(Calculation(Operation.add, 1.1, 2.2), + Calculation(Operation.subtract, 3.3, 4.4), + Calculation(Operation.multiply, 5.5, 6.6), + Calculation(Operation.divide, 7.7, 8.8))); +} +--- + +$(P +The output of the code should be similar to the following: +) + +$(SHELL +[3.3, -1.1, 36.3, 0.875] +) + +) + + +Macros: + TITLE=Variable Number of Parameters + + DESCRIPTION=Default values for function parameters; and the 'variadic function' feature that allows passing variable number of arguments to functions. + + KEYWORDS=d programming book tutorial struct diff --git a/book/d.en/pdf.derse_ozel.css b/book/d.en/pdf.derse_ozel.css new file mode 100644 index 0000000000..fe51491309 --- /dev/null +++ b/book/d.en/pdf.derse_ozel.css @@ -0,0 +1,31 @@ +a.xref:after { + content: " (page " target-counter(attr(href, url), page) ")"; +} + +div.cozum_link_cok a.xref { + content: "The solutions are on page " target-counter(attr(href, url), page) "."; + font-style:italic; +} + +div.cozum_link_cok a.xref:after { + content: normal; +} + +div.cozum_link_tek a.xref { + content: "The solution is on page " target-counter(attr(href, url), page) "."; + font-style:italic; +} + +div.cozum_link_tek a.xref:after { + content: normal; +} + +div.cozum_link_cok, div.cozum_link_tek { + padding-top: .1em; + page-break-before: avoid; +} + +body +{ + counter-reset: h4 -2; +} diff --git a/book/d.en/pointers.cozum.d b/book/d.en/pointers.cozum.d new file mode 100644 index 0000000000..4c5e1766ab --- /dev/null +++ b/book/d.en/pointers.cozum.d @@ -0,0 +1,209 @@ +Ddoc + +$(COZUM_BOLUMU Pointers) + +$(OL + +$(LI +When parameters are value types like $(C int), the arguments are copied to functions. The preferred way of defining reference parameters is to specify them as $(C ref). + +$(P +Another way is to define the parameters as pointers that point at the actual variables. The parts of the program that have been changed are highlighted: +) + +--- +void swap(int $(HILITE *) lhs, int $(HILITE *) rhs) { + int temp = $(HILITE *)lhs; + $(HILITE *)lhs = $(HILITE *)rhs; + $(HILITE *)rhs = temp; +} + +void main() { + int i = 1; + int j = 2; + + swap($(HILITE &)i, $(HILITE &)j); + + assert(i == 2); + assert(j == 1); +} +--- + +$(P +The checks at the end of the program now pass. +) + +) + +$(LI +$(C Node) and $(C List) have been written to work only with the $(C int) type. We can convert these types to struct templates by adding $(C (T)) after their names and replacing appropriate $(C int)s in their definitions by $(C T)s: + +--- +$(CODE_NAME List)struct Node$(HILITE (T)) { + $(HILITE T) element; + Node * next; + + string toString() const { + string result = to!string(element); + + if (next) { + result ~= " -> " ~ to!string(*next); + } + + return result; + } +} + +struct List$(HILITE (T)) { + Node!$(HILITE T) * head; + + void insertAtHead($(HILITE T) element) { + head = new Node!$(HILITE T)(element, head); + } + + string toString() const { + return format("(%s)", head ? to!string(*head) : ""); + } +} +--- + +$(P +$(C List) can now be used with any type: +) + +--- +$(CODE_XREF List)import std.stdio; +import std.conv; +import std.string; + +// ... + +struct Point { + double x; + double y; + + string toString() const { + return format("(%s,%s)", x, y); + } +} + +void main() { + $(HILITE List!Point) points; + + points.insertAtHead(Point(1.1, 2.2)); + points.insertAtHead(Point(3.3, 4.4)); + points.insertAtHead(Point(5.5, 6.6)); + + writeln(points); +} +--- + +$(P +The output: +) + +$(SHELL +((5.5,6.6) -> (3.3,4.4) -> (1.1,2.2)) +) + +) + +$(LI In this case we need another pointer to point at the last node of the list. The new code is necessarily more complex in order to manage the new variable as well: + +--- +struct List(T) { + Node!T * head; + $(HILITE Node!T * tail); + + void append(T element) { + /* Since there is no node after the last one, we set + * the new node's next pointer to 'null'. */ + auto newNode = new Node!T(element, null); + + if (!head) { + /* The list has been empty. The new node becomes + * the head. */ + head = newNode; + } + + if (tail) { + /* We place this node after the current tail. */ + tail.next = newNode; + } + + /* The new node becomes the new tail. */ + tail = newNode; + } + + void insertAtHead(T element) { + auto newNode = new Node!T(element, head); + + /* The new node becomes the new head. */ + head = newNode; + + if (!tail) { + /* The list has been empty. The new node becomes + * the tail. */ + tail = newNode; + } + } + + string toString() const { + return format("(%s)", head ? to!string(*head) : ""); + } +} +--- + +$(P +The new implementation of $(C insertAtHead()) can actually be shorter: +) + +--- + void insertAtHead(T element) { + head = new Node!T(element, head); + + if (!tail) { + tail = head; + } + } +--- + +$(P +The following program uses the new $(C List) to insert $(C Point) objects with odd values at the head and $(C Point) objects with even values at the end. +) + +--- +void $(CODE_DONT_TEST)main() { + List!Point points; + + foreach (i; 1 .. 7) { + if (i % 2) { + points.insertAtHead(Point(i, i)); + + } else { + points.append(Point(i, i)); + } + } + + writeln(points); +} +--- + +$(P +The output: +) + +$(SHELL +((5,5) -> (3,3) -> (1,1) -> (2,2) -> (4,4) -> (6,6)) +) + +) + +) + +Macros: + TITLE=Pointers Solutions + + DESCRIPTION=Programming in D Solutions: Pointers + + KEYWORDS=d programming language tutorial book pointers diff --git a/book/d.en/pointers.d b/book/d.en/pointers.d new file mode 100644 index 0000000000..9cd02a7c1a --- /dev/null +++ b/book/d.en/pointers.d @@ -0,0 +1,1653 @@ +Ddoc + +$(DERS_BOLUMU $(IX pointer) Pointers) + +$(P +Pointers are variables that provide access to other variables. The value of a pointer is the address of the variable that it provides access to. +) + +$(P +Pointers can point at any type of variable, object, and even other pointers. In this chapter, I will refer to all of these simply as $(I variables). +) + +$(P +Pointers are low level features of microprocessors. They are an important part of system programming. +) + +$(P +The syntax and semantics of pointers in D are inherited directly from C. Although pointers are notoriously the most difficult feature of C to comprehend, they should not be as difficult in D. This is because other features of D that are semantically close to pointers are more useful in situations where pointers would have to be used in other languages. When the ideas behind pointers are already understood from those other features of D, pointers should be easier to grasp. +) + +$(P +The short examples throughout the most of this chapter are decidedly simple. The programs at the end of the chapter will be more realistic. +) + +$(P +The names like $(C ptr) (short for "pointer") that I have used in these examples should not be considered as useful names in general. As always, names must be chosen to be more meaningful and explanatory in actual programs. +) + +$(H5 $(IX reference, concept) The concept of a reference) + +$(P +Although we have encountered references many times in the previous chapters, let's summarize this concept one more time. +) + +$(H6 The $(C ref) variables in $(C foreach) loops) + +$(P +As we have seen in $(LINK2 foreach.html, the $(C foreach) Loop chapter), normally the loop variables are $(I copies) of elements: +) + +--- +import std.stdio; + +void main() { + int[] numbers = [ 1, 11, 111 ]; + + foreach (number; numbers) { + number = 0; // ← the copy changes, not the element + } + + writeln("After the loop: ", numbers); +} +--- + +$(P +The $(C number) that gets assigned 0 each time is a copy of one of the elements of the array. Modifying that copy does not modify the element: +) + +$(SHELL +After the loop: [1, 11, 111] +) + +$(P +When the actual elements need to be modified, the $(C foreach) variable must be defined as $(C ref): +) + +--- + foreach ($(HILITE ref) number; numbers) { + number = 0; // ← the actual element changes + } +--- + +$(P +This time $(C number) is a reference to an actual element in the array: +) + +$(SHELL_SMALL +After the loop: [0, 0, 0] +) + +$(H6 $(C ref) function parameters) + +$(P +As we have seen in $(LINK2 function_parameters.html, the Function Parameters chapter), the parameters of $(I value types) are normally copies of the arguments: +) + +--- +import std.stdio; + +void addHalf(double value) { + value += 0.5; // ← Does not affect 'value' in main +} + +void main() { + double value = 1.5; + + addHalf(value); + + writeln("The value after calling the function: ", value); +} +--- + +$(P +Because the function parameter is not defined as $(C ref), the assignment inside the function affects only the local variable there. The variable in $(C main()) is not affected: +) + +$(SHELL_SMALL +The value after calling the function: 1.5 +) + +$(P +The $(C ref) keyword would make the function parameter a reference to the argument: +) + +--- +void addHalf($(HILITE ref) double value) { + value += 0.5; +} +--- + +$(P +This time the variable in $(C main()) gets modified: +) + +$(SHELL_SMALL +The value after calling the function: 2 +) + +$(H6 Reference types) + +$(P +Some types are reference types. Variables of such types provide access to separate variables: +) + +$(UL +$(LI Class variables) +$(LI Slices) +$(LI Associative arrays) +) + +$(P +We have seen this distinction in $(LINK2 value_vs_reference.html, the Value Types and Reference Types chapter). The following example demonstrates reference types by two $(C class) variables: +) + +--- +import std.stdio; + +class Pen { + double ink; + + this() { + ink = 15; + } + + void use(double amount) { + ink -= amount; + } +} + +void main() { + auto pen = new Pen; + auto otherPen = pen; // ← Now both variables provide + // access to the same object + + writefln("Before: %s %s", pen.ink, otherPen.ink); + + pen.use(1); // ← the same object is used + otherPen.use(2); // ← the same object is used + + writefln("After : %s %s", pen.ink, otherPen.ink); +} +--- + +$(P +Because classes are reference types, the class variables $(C pen) and $(C otherPen) provide access to the same $(C Pen) object. As a result, using either of those class variables affects the same object: +) + +$(SHELL_SMALL +Before: 15 15 +After : 12 12 +) + +$(P +That single object and the two class variables would be laid out in memory similar to the following figure: +) + +$(MONO + (The Pen object) pen otherPen + ───┬───────────────────┬─── ───┬───┬─── ───┬───┬─── + │ ink │ │ o │ │ o │ + ───┴───────────────────┴─── ───┴─│─┴─── ───┴─│─┴─── + ▲ │ │ + │ │ │ + └────────────────────┴────────────┘ +) + +$(P +References $(I point at) actual variables as $(C pen) and $(C otherPen) do above. +) + +$(P +Programming languages implement the reference and pointer concepts by special registers of the microprocessor, which are specifically for $(I pointing at) memory locations. +) + +$(P +Behind the scenes, D's higher-level concepts (class variables, slices, associative arrays, etc.) are all implemented by pointers. As these higher-level features are already efficient and convenient, pointers are rarely needed in D programming. Still, it is important for D programmers to understand pointers well. +) + +$(H5 $(IX *, pointer definition) Syntax) + +$(P +The pointer syntax of D is mostly the same as in C. Although this can be seen as an advantage, the peculiarities of C's pointer syntax are necessarily inherited by D as well. For example, the different meanings of the $(C *) character may be confusing. +) + +$(P +With the exception of $(C void) pointers, every pointer is associated with a certain type and can point at only variables of that specific type. For example, an $(C int) pointer can only point at variables of type $(C int). +) + +$(P +The pointer definition syntax consists of the associated type and a $(C *) character: +) + +--- + $(I $(D_KEYWORD type_to_point_at)) * $(I name_of_the_pointer_variable); +--- + +$(P +Accordingly, a pointer variable that would be pointing at $(C int) variables would be defined like this: +) + +--- + int * myPointer; +--- + +$(P +The $(C *) character in that syntax may be pronounced as "pointer". So, the type of $(C myPointer) above is an "int pointer". The spaces before and after the $(C *) character are optional. The following syntaxes are common as well: +) + +--- + int* myPointer; + int *myPointer; +--- + +$(P +When it is specifically a pointer type that is being mentioned as in "int pointer", it is common to write the type without any spaces as in $(C int*). +) + +$(H5 $(IX &, address of) Pointer value and the address-of operator $(C &)) + +$(P +Being variables themselves pointers have values as well. The default value of a pointer is the special value $(C null), which means that the pointer is not $(I pointing at) any variable yet (i.e. does not provide access to any variable). +) + +$(P +To make a pointer provide access to a variable, the value of the pointer must be set to the address of that variable. The pointer starts pointing at the variable that is at that specific address. From now on, I will call that variable $(I the pointee). +) + +$(P +The $(C &) operator which we have used many times before with $(C readf) has also been briefly mentioned in $(LINK2 value_vs_reference.html, the Value Types and Reference Types chapter). This operator produces the address of the variable that is written after it. Its value can be used when initializing a pointer: +) + +--- + int myVariable = 180; + int * myPointer = $(HILITE &)myVariable; +--- + +$(P +Initializing $(C myPointer) by the address of $(C myVariable) makes $(C myPointer) point at $(C myVariable). +) + +$(P +The value of the pointer is the same as the address of $(C myVariable): +) + +--- + writeln("The address of myVariable: ", &myVariable); + writeln("The value of myPointer : ", myPointer); +--- + +$(SHELL_SMALL +The address of myVariable: 7FFF2CE73F10 +The value of myPointer : 7FFF2CE73F10 +) + +$(P $(I $(B Note:) The address value is likely to be different every time the program is started.) +) + +$(P +The following figure is a representation of these two variables in memory: +) + +$(MONO + myVariable at myPointer at + address 7FFF2CE73F10 some other address +───┬────────────────┬─── ───┬────────────────┬─── + │ 180 │ │ 7FFF2CE73F10 │ +───┴────────────────┴─── ───┴────────│───────┴─── + ▲ │ + │ │ + └─────────────────────────────┘ +) + +$(P +The value of $(C myPointer) is the address of $(C myVariable), conceptually $(I pointing at) the variable that is at that location. +) + +$(P +Since pointers are variables as well, the $(C &) operator can produce the address of the pointer as well: +) + +--- + writeln("The address of myPointer : ", &myPointer); +--- + +$(SHELL_SMALL +The address of myPointer : 7FFF2CE73F18 +) + +$(P +Since the difference between the two addresses above is 8, remembering that an $(C int) takes up 4 bytes, we can deduce that $(C myVariable) and $(C myPointer) are 4 bytes apart in memory. +) + +$(P +After removing the arrow that represented the concept of $(I pointing at), we can picture the contents of memory around these addresses like this: +) + +$(MONO + 7FFF2CE73F10 7FFF2CE73F14 7FFF2CE73F18 + : : : : + ───┬────────────────┬────────────────┬────────────────┬─── + │ 180 │ (unused) │ 7FFF2CE73F10 │ + ───┴────────────────┴────────────────┴────────────────┴─── +) + +$(P +The names of variables, functions, classes, etc. and keywords are not parts of programs of compiled languages like D. The variables that have been defined by the programmer in the source code are converted to bytes that occupy memory or registers of the microprocessor. +) + +$(P +$(I $(B Note:) The names (a.k.a. symbols) may actually be included in programs to help with debugging but those names do not affect the operation of the program.) +) + +$(H5 $(IX *, pointee access) The access operator $(C *)) + +$(P +We have seen above that the $(C *) character which normally represents multiplication is also used when defining pointers. A difficulty with the syntax of pointers is that the same character has a third meaning: It is also used when accessing the pointee through the pointer. +) + +$(P +When it is written before the name of a pointer, it means $(I the variable that the pointer is pointing at) (i.e. the pointee): +) + +--- + writeln("The value that it is pointing at: ", $(HILITE *)myPointer); +--- + +$(SHELL_SMALL +The value that it is pointing at: 180 +) + +$(H5 $(IX ., pointer) The $(C .) (dot) operator to access a member of the pointee) + +$(P +If you know pointers from C, this operator is the same as the $(C ->) operator in that language. +) + +$(P +We have seen above that the $(C *) operator is used for accessing the pointee. That is sufficiently useful for pointers of fundamental types like $(C int*): The value of a fundamental type is accessed simply by writing $(C *myPointer). +) + +$(P +However, when the pointee is a struct or a class object, the same syntax becomes inconvenient. To see why, let's consider the following struct: +) + +--- +struct Coordinate { + int x; + int y; + + string toString() const { + return format("(%s,%s)", x, y); + } +} +--- + +$(P +The following code defines an object and a pointer of that type: +) + +--- + auto center = Coordinate(0, 0); + Coordinate * ptr = $(HILITE &)center; // pointer definition + writeln($(HILITE *)ptr); // object access +--- + +$(P +That syntax is convenient when accessing the value of the entire $(C Coordinate) object: +) + +$(SHELL_SMALL +(0,0) +) + +$(P +However, the code becomes complicated when accessing a member of an object through a pointer and the $(C *) operator: +) + +--- + // Adjust the x coordinate + (*ptr).x += 10; +--- + +$(P +That expression modifies the value of the $(C x) member of the $(C center) object. The left-hand side of that expression can be explained by the following steps: +) + +$(UL +$(LI $(C ptr): The pointer that points at $(C center)) + +$(LI $(C $(HILITE *)ptr): Accessing the object (i.e. $(C center) itself)) + +$(LI $(C $(HILITE ()*ptr$(HILITE ))): Parentheses so that the $(C .) (dot) operator is applied to the object, not to the pointer) + +$(LI $(C (*ptr)$(HILITE .x)): The $(C x) member of the object that $(C ptr) is pointing at) + +) + +$(P +To reduce the complexity of pointer syntax in D, the $(C .) (dot) operator is transferred to the pointee and provides access to the member of the object. (The exceptions to this rule are at the end of this section.) +) + +$(P +So, the previous expression is normally written as: +) + +--- + $(HILITE ptr.x) += 10; +--- + +$(P +Since the pointer itself does not have a member named $(C x), $(C .x) is applied to the pointee and the $(C x) member of $(C center) gets modified: +) + +$(SHELL_SMALL +(10,0) +) + +$(P +Note that this is the same as the use of the $(C .) (dot) operator with classes. When the $(C .) (dot) operator is applied to a class $(I variable), it provides access to a member of the class $(I object): +) + +--- +class ClassType { + int member; +} + +// ... + + // Variable on the left, object on the right + ClassType variable = new ClassType; + + // Applied to the variable but accesses the member of + // the object + variable.member = 42; +--- + +$(P +As you remember from $(LINK2 class.html, the Classes chapter), the class object is constructed by the $(C new) keyword on the right-hand side. $(C variable) is a class variable that provides access to it. +) + +$(P +Realizing that it is the same with pointers is an indication that class variables and pointers are implemented similarly by the compiler. +) + +$(P +There is an exception to this rule both for class variables and for pointers. Type properties like $(C .sizeof) are applied to the type of the pointer, not to the type of the pointee: +) + +--- + char c; + char * p = &c; + + writeln(p.sizeof); // size of the pointer, not the pointee +--- + +$(P +$(C .sizeof) produces the size of $(C p), which is a $(C char*), not the size of $(C c), which is a $(C char). On a 64-bit system pointers are 8-byte long: +) + +$(SHELL_SMALL +8 +) + +$(H5 $(IX arithmetic, pointer) Modifying the value of a pointer) + +$(P +The values of pointers can be incremented or decremented and they can be used in addition and subtraction: +) + +--- + ++ptr; + --ptr; + ptr += 2; + ptr -= 2; + writeln(ptr + 3); + writeln(ptr - 3); +--- + +$(P +Different from their arithmetic counterparts, these operations do not modify the actual value by the specified amount. Rather, the value of the pointer gets modified so that it now points at the variable that is a certain number of variables beyond the current one. The amount of the increment or the decrement specifies $(I how many variables away) should the pointer now point at. +) + +$(P +For example, incrementing the value of a pointer makes it point at the next variable: +) + +--- + ++ptr; // Starts pointing at a variable that is next in + // memory from the old variable +--- + +$(P +For that to work correctly, the actual value of the pointer must be incremented by the size of the variable. For example, because the size of $(C int) is 4, incrementing a pointer of type $(C int*) changes its value by 4. The programmer need not pay attention to this detail; the pointer value is modified by the correct amount automatically. +) + +$(P $(B Warning): It is undefined behavior to point at a location that is not a valid byte that belongs to the program. Even if it is not actually used to access any variable there, it is invalid for a pointer to point at a nonexistent variable. (The only exception to this rule is that it is valid to point at the imaginary element one past the end of an array. This will be explained later below.) +) + +$(P +For example, it is invalid to increment a pointer that points at $(C myVariable), because $(C myVariable) is defined as a single $(C int): +) + +--- + ++myPointer; $(CODE_NOTE_WRONG undefined behavior) +--- + +$(P +Undefined behavior means that it cannot be known what the behavior of the program will be after that operation. There may be systems where the program crashes after incrementing that pointer. However, on most modern systems the pointer is likely to point at the unused memory location that has been shown as being between $(C myVariable) and $(C myPointer) in the previous figure. +) + +$(P +For that reason, the value of a pointer must be incremented or decremented only if there is a valid object at the new location. (As we will see below, pointing at the element one past the end of an array is valid as well). Arrays (and slices) have that property: The elements of an array are side by side in memory. +) + +$(P +A pointer that is pointing at an element of a slice can be incremented safely as long as it is not used to access an element beyond the end of the slice. Incrementing such a pointer by the $(C ++) operator makes it point at the next element: +) + +--- +import std.stdio; +import std.string; +import std.conv; + +enum Color { red, yellow, blue } + +struct Crayon { + Color color; + double length; + + string toString() const { + return format("%scm %s crayon", length, color); + } +} + +void main() { + writefln("Crayon objects are %s bytes each.", Crayon.sizeof); + + Crayon[] crayons = [ Crayon(Color.red, 11), + Crayon(Color.yellow, 12), + Crayon(Color.blue, 13) ]; + + $(HILITE Crayon * ptr) = $(HILITE &)crayons[0]; // (1) + + for (int i = 0; i != crayons.length; ++i) { + writeln("Pointer value: ", $(HILITE ptr)); // (2) + + writeln("Crayon: ", $(HILITE *ptr)); // (3) + $(HILITE ++ptr); // (4) + } +} +--- + +$(OL +$(LI Definition: The pointer is initialized by the address of the first element.) +$(LI Using its value: The value of the pointer is the address of the element that it is pointing at.) +$(LI Accessing the element that is being pointed at.) +$(LI Pointing at the next element.) +) + +$(P +The output: +) + +$(SHELL +Crayon objects are 16 bytes each. +Pointer value: 7F37AC9E6FC0 +Crayon: 11cm red crayon +Pointer value: 7F37AC9E6FD0 +Crayon: 12cm yellow crayon +Pointer value: 7F37AC9E6FE0 +Crayon: 13cm blue crayon +) + +$(P +Note that the loop above is iterated a total of $(C crayons.length) times so that the pointer is always used for accessing a valid element. +) + +$(H5 Pointers are risky) + +$(P +The compiler and the D runtime environment cannot guarantee that the pointers are always used correctly. It is the programmer's responsibility to ensure that a pointer is either $(C null) or points at a valid memory location (at a variable, at an element of an array, etc.). +) + +$(P +For that reason, it is always better to consider higher-level features of D before thinking about using pointers. +) + +$(H5 $(IX element one past the end) The element one past the end of an array) + +$(P +It is valid to point at the imaginary element one past the end of an array. +) + +$(P +This is a useful idiom that is similar to number ranges. When defining a slice with a number range, the second index is one past the elements of the slice: +) + +--- + int[] values = [ 0, 1, 2, 3 ]; + writeln(values[1 .. 3]); // 1 and 2 included, 3 excluded +--- + +$(P +This idiom can be used with pointers as well. It is a common function design in C and C++ where a function parameter points at the first element and another one points at the element after the last element: +) + +--- +import std.stdio; + +void tenTimes(int * begin, int * end) { + while (begin != end) { + *begin *= 10; + ++begin; + } +} + +void main() { + int[] values = [ 0, 1, 2, 3 ]; + + // The address of the second element: + int * begin = &values[1]; + + // The address of two elements beyond that one + tenTimes(begin, begin + 2); + + writeln(values); +} +--- + +$(P +The value $(C begin + 2) means two elements after the one that $(C begin) is pointing at (i.e. the element at index 3). +) + +$(P +The $(C tenTimes()) function takes two pointer parameters. It uses the element that the first one is pointing at but it never accesses the element that the second one is pointing at. As a result, only the elements at indexes 1 and 2 get modified: +) + +$(SHELL_SMALL +[0, 10, 20, 3] +) + +$(P +Such functions can be implemented by a $(C for) loop as well: +) + +--- + for ( ; begin != end; ++begin) { + *begin *= 10; + } +--- + +$(P +Two pointers that define a range can also be used with $(C foreach) loops: +) + +--- + foreach (ptr; begin .. end) { + *ptr *= 10; + } +--- + +$(P +For these methods to be applicable to $(I all of the elements) of a slice, the second pointer must necessarily point after the last element: +) + +--- + // The second pointer is pointing at the imaginary element + // past the end of the array: + tenTimes(begin, begin + values.length); +--- + +$(P +That is the reason why it is legal to point at the imaginary element one beyond the last element of an array. +) + +$(H5 $(IX []) Using pointers with the array indexing operator $(C [])) + +$(P +Although it is not absolutely necessary in D, pointers can directly be used for accessing the elements of an array by an index value: +) + +--- + double[] floats = [ 0.0, 1.1, 2.2, 3.3, 4.4 ]; + + double * ptr = &floats[2]; + + *ptr = -100; // direct access to what it points at + ptr$(HILITE [1]) = -200; // access by indexing + + writeln(floats); +--- + +$(P +The output: +) + +$(SHELL_SMALL +[0, 1.1, -100, -200, 4.4] +) + +$(P +In that syntax, the element that the pointer is pointing at is thought of being the first element of an imaginary slice. The $(C []) operator provides access to the specified element of that slice. The $(C ptr) above initially points at the element at index 2 of the original $(C floats) slice. $(C ptr[1]) is a reference to the element 1 of the imaginary slice that starts at $(C ptr) (i.e. index 3 of the original slice). +) + +$(P +Although this behavior may seem complicated, there is a very simple conversion behind that syntax. Behind the scenes, the compiler converts the $(C pointer[index]) syntax to the $(C *(pointer + index)) expression: +) + +--- + ptr[1] = -200; // slice syntax + *(ptr + 1) = -200; // the equivalent of the previous line +--- + +$(P +As I have mentioned earlier, the compiler may not guarantee that this expression refers to a valid element. D's slices provide a much safer alternative and should be considered instead: +) + +--- + double[] slice = floats[2 .. 4]; + slice[0] = -100; + slice[1] = -200; +--- + +$(P +Normally, index values are checked for slices at run time: +) + +--- + slice[2] = -300; // Runtime error: accessing outside of the slice +--- + +$(P +Because the slice above does not have an element at index 2, an exception would be thrown at run time (unless the program has been compiled with the $(C -release) compiler switch): +) + +$(SHELL_SMALL +core.exception.RangeError@deneme(8391): Range violation +) + +$(H5 $(IX slice from pointer) Producing a slice from a pointer) + +$(P +Pointers are not as safe or as useful as slices because although they can be used with the slice indexing operator, they are not aware of the valid range of elements. +) + +$(P +However, when the number of valid elements is known, a pointer can be used to construct a slice. +) + +$(P +Let's assume that the $(C makeObjects()) function below is inside a C library. Let's assume that $(C makeObjects) makes specified number of $(C Struct) objects and returns a pointer to the first one of those objects: +) + +--- + Struct * ptr = makeObjects(10); +--- + +$(P +The syntax that produces a slice from a pointer is the following: +) + +--- + /* ... */ slice = pointer[0 .. count]; +--- + +$(P +Accordingly, a slice to the 10 objects that are returned by $(C makeObjects()) can be constructed by the following code: +) + +--- + Struct[] slice = ptr[0 .. 10]; +--- + +$(P +After that definition, $(C slice) is ready to be used safely in the program just like any other slice: +) + +--- + writeln(slice[1]); // prints the second element +--- + +$(H5 $(IX void*) $(C void*) can point at any type) + +$(P +Although it is almost never needed in D, C's special pointer type $(C void*) is available in D as well. $(C void*) can point at any type: +) + +--- + int number = 42; + double otherNumber = 1.25; + void * canPointAtAnything; + + canPointAtAnything = &number; + canPointAtAnything = &otherNumber; +--- + +$(P +The $(C void*) above is able to point at variables of two different types: $(C int) and $(C double). +) + +$(P +$(C void*) pointers are limited in functionality. As a consequence of their flexibility, they cannot provide access to the pointee. When the actual type is unknown, its size is not known either: +) + +--- + *canPointAtAnything = 43; $(DERLEME_HATASI) +--- + +$(P +Instead, its value must first be converted to a pointer of the correct type: +) + +--- + int number = 42; // (1) + void * canPointAtAnything = &number; // (2) + + // ... + + int * intPointer = cast(int*)canPointAtAnything; // (3) + *intPointer = 43; // (4) +--- + +$(OL +$(LI The actual variable) +$(LI Storing the address of the variable in a $(C void*)) +$(LI Assigning that address to a pointer of the correct type) +$(LI Modifying the variable through the new pointer) +) + +$(P +It is possible to increment or decrement values of $(C void*) pointers, in which case their values are modified as if they are pointers of 1-byte types like $(C ubyte): +) + +--- + ++canPointAtAnything; // incremented by 1 +--- + +$(P +$(C void*) is sometimes needed when interacting with libraries that are written in C. Since C does not have higher level features like interfaces, classes, templates, etc. C libraries must rely on the $(C void*) type. +) + +$(H5 Using pointers in logical expressions) + +$(P +Pointers can automatically be converted to $(C bool). Pointers that have the value $(C null) produce $(C false) and the others produce $(C true). In other words, pointers that do not point at any variable are $(C false). +) + +$(P +Let's consider a function that prints objects to the standard output. Let's design this function so that it also provides the number of bytes that it has just output. However, let's have it produce this information only when specifically requested. +) + +$(P +It is possible to make this behavior optional by checking whether the value of a pointer is $(C null) or not: +) + +--- +void print(Crayon crayon, size_t * numberOfBytes) { + immutable info = format("Crayon: %s", crayon); + writeln(info); + + $(HILITE if (numberOfBytes)) { + *numberOfBytes = info.length; + } +} +--- + +$(P +When the caller does not need this special information, they can pass $(C null) as the argument: +) + +--- + print(Crayon(Color.yellow, 7), $(HILITE null)); +--- + +$(P +When the number of bytes is indeed important, then a non-$(C null) pointer value must be passed: +) + +--- + size_t numberOfBytes; + print(Crayon(Color.blue, 8), $(HILITE &numberOfBytes)); + writefln("%s bytes written to the output", numberOfBytes); +--- + +$(P +Note that this is just an example. Otherwise, it would be better for a function like $(C print()) to return the number of bytes unconditionally: +) + +--- +size_t print(Crayon crayon) { + immutable info = format("Crayon: %s", crayon); + writeln(info); + + return info.length; +} +--- + +$(H5 $(IX new) $(C new) returns a pointer for some types) + +$(P +$(C new), which we have been using only for constructing class objects can be used with other types as well: structs, arrays, and fundamental types. The variables that are constructed by $(C new) are called dynamic variables. +) + +$(P +$(C new) first allocates space from the memory for the variable and then constructs the variable in that space. The variable itself does not have a symbolic name in the compiled program; it would be accessed through the reference that is returned by $(C new). +) + +$(P +The reference that $(C new) returns is a different kind depending on the type of the variable: +) + +$(UL + +$(LI For class objects, it is a $(I class variable): + +--- + Class classVariable = new Class; +--- + +) + +$(LI For struct objects and variables of fundamental types, it is a $(I pointer): + +--- + Struct $(HILITE *) structPointer = new Struct; + int $(HILITE *) intPointer = new int; +--- + +) + +$(LI For arrays, it is a $(I slice): + +--- + int[] slice = new int[100]; +--- + +) + +) + +$(P +This distinction is usually not obvious when the type is not spelled-out on the left-hand side: +) + +--- + auto classVariable = new Class; + auto structPointer = new Struct; + auto intPointer = new int; + auto slice = new int[100]; +--- + +$(P +The following program prints the return type of $(C new) for different kinds of variables: +) + +--- +import std.stdio; + +struct Struct { +} + +class Class { +} + +void main() { + writeln(typeof(new int ).stringof); + writeln(typeof(new int[5]).stringof); + writeln(typeof(new Struct).stringof); + writeln(typeof(new Class ).stringof); +} +--- + +$(P +$(C new) returns pointers for structs and fundamental types: +) + +$(SHELL_SMALL +int* +int[] +Struct* +Class +) + +$(P +When $(C new) is used for constructing a dynamic variable of a $(LINK2 value_vs_reference.html, value type), then the lifetime of that variable is extended as long as there is still a reference (e.g. a pointer) to that object in the program. (This is the default situation for reference types.) +) + +$(H5 $(IX .ptr, array element) $(IX pointer, array element) The $(C .ptr) property of arrays) + +$(P +The $(C .ptr) property of arrays and slices is the address of the first element. The type of this value is a pointer to the type of the elements: +) + +--- + int[] numbers = [ 7, 12 ]; + + int * addressOfFirstElement = numbers$(HILITE .ptr); + writeln("First element: ", *addressOfFirstElement); +--- + +$(P +This property is useful especially when interacting with C libraries. Some C functions take the address of the first of a number of consecutive elements in memory. +) + +$(P +Remembering that strings are also arrays, the $(C .ptr) property can be used with strings as well. However, note that the first element of a string need not be the first $(I letter) of the string; rather, the first Unicode code unit of that letter. As an example, the letter é is stored as two code units in a $(C char) string. +) + +$(P +When accessed through the $(C .ptr) property, the code units of strings can be accessed individually. We will see this in the examples section below. +) + +$(H5 $(IX in, operator) The $(C in) operator of associative arrays) + +$(P +Actually, we have used pointers earlier in $(LINK2 aa.html, the Associative Arrays chapter). In that chapter, I had intentionally not mentioned the exact type of the $(C in) operator and had used it only in logical expressions: +) + +--- + if ("purple" in colorCodes) { + // there is an element for key "purple" + + } else { + // no element for key "purple" + } +--- + +$(P +In fact, the $(C in) operator returns the address of the element if there is an element for the specified key; otherwise, it returns $(C null). The $(C if) statement above actually relies on the automatic conversion of the pointer value to $(C bool). +) + +$(P +When the return value of $(C in) is stored in a pointer, the element can be accessed efficiently through that pointer: +) + +--- +import std.stdio; + +void main() { + string[int] numbers = + [ 0 : "zero", 1 : "one", 2 : "two", 3 : "three" ]; + + int number = 2; + auto $(HILITE element) = number in numbers; // (1) + + if ($(HILITE element)) { // (2) + writefln("I know: %s.", $(HILITE *element)); // (3) + + } else { + writefln("I don't know the spelling of %s.", number); + } +} +--- + +$(P +The pointer variable $(C element) is initialized by the value of the $(C in) operator (1) and its value is used in a logical expression (2). The value of the element is accessed through that pointer (3) only if the pointer is not $(C null). +) + +$(P +The actual type of $(C element) above is a pointer to the same type of the elements (i.e. values) of the associative array. Since the elements of $(C numbers) above are of type $(C string), $(C in) returns a $(C string*). Accordingly, the type could have been spelled out explicitly: +) + +--- + $(HILITE string *) element = number in numbers; +--- + +$(H5 When to use pointers) + +$(P +Pointers are rare in D. As we have seen in $(LINK2 input.html, the Reading from the Standard Input chapter), $(C readf) can in fact be used without explicit pointers. +) + +$(H6 When required by libraries) + +$(P +Pointers can appear on C and C++ library bindings. For example, the following function from the GtkD library takes a pointer: +) + +--- + GdkGeometry geometry; + // ... set the members of 'geometry' ... + + window.setGeometryHints(/* ... */, $(HILITE &)geometry, /* ... */); +--- + +$(H6 When referencing variables of value types) + +$(P +Pointers can be used for referring to local variables. The following program counts the outcomes of flipping a coin. It takes advantage of a pointer when referring to one of two local variables: +) + +--- +import std.stdio; +import std.random; + +void main() { + size_t headsCount = 0; + size_t tailsCount = 0; + + foreach (i; 0 .. 100) { + size_t * theCounter = (uniform(0, 2) == 1) + ? &headsCount + : &tailsCount; + ++(*theCounter); + } + + writefln("heads: %s tails: %s", headsCount, tailsCount); +} +--- + +$(P +Obviously, there are other ways of achieving the same goal. For example, using the ternary operator in a different way: +) + +--- + uniform(0, 2) ? ++headsCount : ++tailsCount; +--- + +$(P +By using an $(C if) statement: +) + +--- + if (uniform(0, 2)) { + ++headsCount; + + } else { + ++tailsCount; + } +--- + +$(H6 As member variables of data structures) + +$(P +Pointers are essential when implementing many data structures. +) + +$(P +Unlike the elements of an array being next to each other in memory, elements of many other data structures are apart. Such data structures are based on the concept of their elements $(I pointing at) other elements. +) + +$(P +For example, each node of a linked list $(I points at) the next node. Similarly, each node of a binary tree $(I points at) the left and right branches under that node. Pointers are encountered in most other data structures as well. +) + +$(P +Although it is possible to take advantage of D's reference types, pointers may be more natural and efficient in some cases. +) + +$(P +We will see examples of pointer members below. +) + +$(H6 When accessing memory directly) + +$(P +Being low-level microprocessor features, pointers provide byte-level access to memory locations. Note that such locations must still belong to valid variables. It is undefined behavior to attempt to access a random memory location. +) + +$(H5 Examples) + +$(H6 A simple linked list) + +$(P +The elements of linked lists are stored in $(I nodes). The concept of a linked list is based on each node pointing at the node that comes after it. The last node has no other node to point at, so it is set to $(C null): +) + +$(MONO + first node next node last node + ┌─────────┬───┐ ┌─────────┬───┐ ┌─────────┬──────┐ + │ element │ o────▶ │ element │ o────▶ ... │ element │ null │ + └─────────┴───┘ └─────────┴───┘ └─────────┴──────┘ +) + +$(P +The figure above may be misleading: In reality, the nodes are not side-by-side in memory. Each node does point to the next node but the next node may be at a completely different location. +) + +$(P +The following $(C struct) can be used for representing the nodes of such a linked list of $(C int)s: +) + +--- +struct Node { + int element; + Node * next; + + // ... +} +--- + +$(P $(I $(B Note:) Because it contains a reference to the same type as itself, $(C Node) is a $(IX recursive type) recursive type.) +) + +$(P +The entire list can be represented by a single pointer that points at the first node, which is commonly called $(I the head): +) + +--- +struct List { + Node * head; + + // ... +} +--- + +$(P +To keep the example short, let's define just one function that adds an element to the head of the list: +) + +--- +struct List { + Node * head; + + void insertAtHead(int element) { + head = new Node(element, head); + } + + // ... +} +--- + +$(P +The line inside $(C insertAtHead()) keeps the nodes $(I linked) by adding a new node to the head of the list. (A function that adds to the end of the list would be more natural and more useful. We will see that function later in one of the problems.) +) + +$(P +The right-hand side expression of that line constructs a $(C Node) object. When this new object is constructed, its $(C next) member is initialized by the current head of the list. When the $(C head) member of the list is assigned to this newly linked node, the new element ends up being the first element. +) + +$(P +The following program tests these two structs: +) + +--- +import std.stdio; +import std.conv; +import std.string; + +struct Node { + int element; + Node * next; + + string toString() const { + string result = to!string(element); + + if (next) { + result ~= " -> " ~ to!string(*next); + } + + return result; + } +} + +struct List { + Node * head; + + void insertAtHead(int element) { + head = new Node(element, head); + } + + string toString() const { + return format("(%s)", head ? to!string(*head) : ""); + } +} + +void main() { + List numbers; + + writeln("before: ", numbers); + + foreach (number; 0 .. 10) { + numbers.insertAtHead(number); + } + + writeln("after : ", numbers); +} +--- + +$(P +The output: +) + +$(SHELL_SMALL +before: () +after : (9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0) +) + +$(H6 $(IX memory access, pointer) Observing the contents of memory by $(C ubyte*)) + +$(P +The data stored at each memory address is a byte. Every variable is constructed on a piece of memory that consists of as many bytes as the size of the type of that variable. +) + +$(P +A suitable pointer type to observe the content of a memory location is $(C ubyte*). Once the address of a variable is assigned to a $(C ubyte) pointer, then all of the bytes of that variable can be observed by incrementing the pointer. +) + +$(P +Let's consider the following integer that is initialized by the hexadecimal notation so that it will be easy to understand how its bytes are placed in memory: +) + +--- + int variable = 0x01_02_03_04; +--- + +$(P +A pointer that points at that variable can be defined like this: +) + +--- + int * address = &variable; +--- + +$(P +The value of that pointer can be assigned to a $(C ubyte) pointer by the $(C cast) operator: +) + +--- + ubyte * bytePointer = cast(ubyte*)address; +--- + +$(P +Such a pointer allows accessing the four bytes of the $(C int) variable individually: +) + +--- + writeln(bytePointer[0]); + writeln(bytePointer[1]); + writeln(bytePointer[2]); + writeln(bytePointer[3]); +--- + +$(P +If your microprocessor is $(I little-endian) like mine, you should see the bytes of the value $(C 0x01_02_03_04) in reverse: +) + +$(SHELL_SMALL +4 +3 +2 +1 +) + +$(P +Let's use that idea in a function that will be useful when observing the bytes of all types of variables: +) + +--- +$(CODE_NAME printBytes)import std.stdio; + +void printBytes(T)(ref T variable) { + const ubyte * begin = cast(ubyte*)&variable; // (1) + + writefln("type : %s", T.stringof); + writefln("value : %s", variable); + writefln("address: %s", begin); // (2) + writef ("bytes : "); + + writefln("%(%02x %)", begin[0 .. T.sizeof]); // (3) + + writeln(); +} +--- + +$(OL +$(LI Assigning the address of the variable to a $(C ubyte) pointer.) +$(LI Printing the value of the pointer.) +$(LI Obtaining the size of the type by $(C .sizeof) and printing the bytes of the variable. (Note how a slice is produced from the $(C begin) pointer and then that slice is printed directly by $(C writefln()).)) +) + +$(P +Another way of printing the bytes would be to apply the $(C *) operator individually: +) + +--- + foreach (bytePointer; begin .. begin + T.sizeof) { + writef("%02x ", *bytePointer); + } +--- + +$(P +The value of $(C bytePointer) would change from $(C begin) to $(C begin + T.sizeof) to visit all of the bytes of the variable. Note that the value $(C begin + T.sizeof) is outside of the range and is never accessed. +) + +$(P +The following program calls $(C printBytes()) with various types of variables: +) + +--- +$(CODE_XREF printBytes)struct Struct { + int first; + int second; +} + +class Class { + int i; + int j; + int k; + + this(int i, int j, int k) { + this.i = i; + this.j = j; + this.k = k; + } +} + +void main() { + int integerVariable = 0x11223344; + printBytes(integerVariable); + + double doubleVariable = double.nan; + printBytes(doubleVariable); + + string slice = "a bright and charming façade"; + printBytes(slice); + + int[3] array = [ 1, 2, 3 ]; + printBytes(array); + + auto structObject = Struct(0xaa, 0xbb); + printBytes(structObject); + + auto classVariable = new Class(1, 2, 3); + printBytes(classVariable); +} +--- + +$(P +The output of the program is informative: +) + +$(SHELL_SMALL +type : int +value : 287454020 +address: 7FFF19A83FB0 +bytes : 44 33 22 11 $(SHELL_NOTE (1)) + +type : double +value : nan +address: 7FFF19A83FB8 +bytes : 00 00 00 00 00 00 f8 7f $(SHELL_NOTE (2)) + +type : string +value : a bright and charming façade +address: 7FFF19A83FC0 +bytes : 1d 00 00 00 00 00 00 00 e0 68 48 00 00 00 00 00 + $(SHELL_NOTE (3)) +type : int[3LU] +value : [1, 2, 3] +address: 7FFF19A83FD0 +bytes : 01 00 00 00 02 00 00 00 03 00 00 00 $(SHELL_NOTE (1)) + +type : Struct +value : Struct(170, 187) +address: 7FFF19A83FE8 +bytes : aa 00 00 00 bb 00 00 00 $(SHELL_NOTE (1)) + +type : Class +value : deneme.Class +address: 7FFF19A83FF0 +bytes : 80 df 79 d5 97 7f 00 00 $(SHELL_NOTE (4)) +) + +$(P $(B Observations:) +) + +$(OL + +$(LI Although in reverse order on little-endian systems, the bytes of some of the types are as one would expect: The bytes are laid out in memory side by side for $(C int)s, fixed-length arrays ($(C int[3])), and struct objects.) + +$(LI Considering that the bytes of the special value of $(C double.nan) are also in reverse order in memory, we can see that it is represented by the special bit pattern 0x7ff8000000000000.) + +$(LI $(C string) is reported to be consisting of 16 bytes but it is impossible to fit the letters $(STRING "a bright and charming façade") into so few bytes. This is due to the fact that behind the scenes $(C string) is actually implemented as a struct. Prefixing its name by $(C __) to stress the fact that it is an internal type used by the compiler, that struct is similar to the following one: + +--- +struct __string { + size_t length; + char * ptr; // the actual characters +} +--- + +$(P +The evidence of this fact is hidden in the bytes that are printed for $(C string) above. Note that because ç is made up of two UTF-8 code units, the 28 letters of the string $(STRING "a bright and charming façade") consists of a total of 29 bytes. The value 0x000000000000001d, the first 8 of the bytes of the string in the output above, is also 29. This is a strong indicator that strings are indeed laid out in memory as in the struct above. +) + +) + +$(LI Similarly, it is not possible to fit the three $(C int) members of the class object in 8 bytes. The output above hints at the possibility that behind the scenes a class variable is implemented as a single pointer that points at the actual class object: + +--- +struct __Class_VariableType { + __Class_ActualObjecType * object; +} +--- + +) + +) + +$(P +Let's now consider a more flexible function. Instead of printing the bytes of a variable, let's define a function that prints specified number of bytes at a specified location: +) + +--- +$(CODE_NAME printMemory)import std.stdio; +import std.ascii; + +void printMemory(T)(T * location, size_t length) { + const ubyte * begin = cast(ubyte*)location; + + foreach (address; begin .. begin + length) { + char c = (isPrintable(*address) ? *address : '.'); + + writefln("%s: %02x %s", address, *address, c); + } +} +--- + +$(P +Since some of the UTF-8 code units may correspond to control characters of the terminal and disrupt its output, we print only the printable characters by first checking them individually by $(C std.ascii.isPrintable()). The non-printable characters are printed as a dot. +) + +$(P +We can use that function to print the UTF-8 code units of a $(C string) through its $(C .ptr) property: +) + +--- +$(CODE_XREF printMemory)import std.stdio; + +void main() { + string s = "a bright and charming façade"; + printMemory(s.ptr, s.length); +} +--- + +$(P +As seen in the output, the letter ç consists of two bytes: +) + +$(SHELL_SMALL +47B4F0: 61 a +47B4F1: 20 +47B4F2: 62 b +47B4F3: 72 r +47B4F4: 69 i +47B4F5: 67 g +47B4F6: 68 h +47B4F7: 74 t +47B4F8: 20 +47B4F9: 61 a +47B4FA: 6e n +47B4FB: 64 d +47B4FC: 20 +47B4FD: 63 c +47B4FE: 68 h +47B4FF: 61 a +47B500: 72 r +47B501: 6d m +47B502: 69 i +47B503: 6e n +47B504: 67 g +47B505: 20 +47B506: 66 f +47B507: 61 a +47B508: c3 . +47B509: a7 . +47B50A: 61 a +47B50B: 64 d +47B50C: 65 e +) + +$(PROBLEM_COK + +$(PROBLEM +Fix the following function so that the values of the arguments that are passed to it are swapped. For this exercise, do not specify the parameters as $(C ref) but take them as pointers: + +--- +void swap(int lhs, int rhs) { + int temp = lhs; + lhs = rhs; + rhs = temp; +} + +void main() { + int i = 1; + int j = 2; + + swap(i, j); + + // Their values should be swapped + assert(i == 2); + assert(j == 1); +} +--- + +$(P +When you start the program you will notice that the $(C assert) checks currently fail. +) + +) + +$(PROBLEM +Convert the linked list that we have defined above to a template so that it can be used for storing elements of any type. +) + +$(PROBLEM +It is more natural to add elements to the end of a linked list. Modify $(C List) so that it is possible to add elements to the end as well. + +$(P +For this exercise, an additional pointer member variable that points at the last element will be useful. +) + +) + +) + +Macros: + TITLE=Pointers + + DESCRIPTION=Pointers, variables that point at other variables to provide access to them. + + KEYWORDS=d programming language tutorial book pointers diff --git a/book/d.en/pragma.d b/book/d.en/pragma.d new file mode 100644 index 0000000000..1bc8e66868 --- /dev/null +++ b/book/d.en/pragma.d @@ -0,0 +1,236 @@ +Ddoc + +$(DERS_BOLUMU $(IX pragma) Pragmas) + +$(P +Pragmas are a way of interacting with the compiler. They can be for providing special information to the compiler as well as getting information from it. Although they are useful in non-templated code as well, $(C pragma(msg)) can be helpful when debugging templates. +) + +$(P +Every compiler vendor is free to introduce their special $(C pragma) directives in addition to the following mandatory ones: +) + +$(H5 $(C pragma(msg))) + +$(P +Prints a message to $(C stderr) during compilation. No message is printed during the execution of the compiled program. +) + +$(P +For example, the following $(C pragma(msg)) is being used for exposing the types of template parameters, presumably during debugging: +) + +--- +import std.string; + +void func(A, B)(A a, B b) { + pragma($(HILITE msg), format("Called with types '%s' and '%s'", + A.stringof, B.stringof)); + // ... +} + +void main() { + func(42, 1.5); + func("hello", 'a'); +} +--- + +$(SHELL +Called with types 'int' and 'double' +Called with types 'string' and 'char' +) + +$(H5 $(C pragma(lib))) + +$(P +Instructs the compiler to link the program with a particular library. This is the easiest way of linking the program with a library that is already installed on the system. +) + +$(P +For example, the following program would be linked with the $(C curl) library without needing to mention the library on the command line: +) + +--- +import std.stdio; +import std.net.curl; + +pragma($(HILITE lib), "curl"); + +void main() { + // Get this chapter + writeln(get("ddili.org/pragma.html")); +} +--- + +$(H5 $(IX inline) $(IX function inlining) $(IX optimization, compiler) $(C pragma(inline))) + +$(P +Specifies whether a function should be $(I inlined) or not. +) + +$(P +Every function call has some performance cost. Function calls involve passing arguments to the function, returning its return value to the caller, and handling some bookkeeping information to remember where the function was called from so that the execution can continue after the function returns. +) + +$(P +This cost is usually insignificant compared to the cost of actual work that the caller and the callee perform. However, in some cases just the act of calling a certain function can have a measurable effect on the program's performance. This can happen especially when the function body is relatively fast and when it is called from a short loop that repeats many times. +) + +$(P +The following program calls a small function from a loop and increments a counter when the returned value satisfies a condition: +) + +--- +import std.stdio; +import std.datetime.stopwatch; + +// A function with a fast body: +ubyte compute(ubyte i) { + return cast(ubyte)(i * 42); +} + +void main() { + size_t counter = 0; + + StopWatch sw; + sw.start(); + + // A short loop that repeats many times: + foreach (i; 0 .. 100_000_000) { + const number = cast(ubyte)i; + + if ($(HILITE compute(number)) == number) { + ++counter; + } + } + + sw.stop(); + + writefln("%s milliseconds", sw.peek.total!"msecs"); +} +--- + +$(P +$(IX StopWatch, std.datetime.stopwatch) The code takes advantage of $(C std.datetime.stopwatch.StopWatch) to measure the time it takes executing the entire loop: +) + +$(SHELL +$(HILITE 674) milliseconds +) + +$(P +$(IX -inline, compiler switch) The $(C -inline) compiler switch instructs the compiler to perform a compiler optimization called $(I function inlining): +) + +$(SHELL +$ dmd deneme.d -w $(HILITE -inline) +) + +$(P +When a function is inlined, its body is injected into code right where it is called from; no actual function call happens. The following is the equivalent code that the compiler would compile after inlining: +) + +--- + // An equivalent of the loop when compute() is inlined: + foreach (i; 0 .. 100_000_000) { + const number = cast(ubyte)i; + + const result = $(HILITE cast(ubyte)(number * 42)); + if (result == number) { + ++counter; + } + } +--- + +$(P +On the platform that I tested that program, eliminating the function call reduced the execution time by about 40%: +) + +$(SHELL +$(HILITE 407) milliseconds +) + +$(P +Although function inlining looks like a big gain, it cannot be applied for every function call because otherwise inlined bodies of functions would make code too large to fit in the CPU's $(I instruction cache). Unfortunately, this can make the code even slower. For that reason, the decision of which function calls to inline is usually left to the compiler. +) + +$(P +However, there may be cases where it is beneficial to help the compiler with this decision. The $(C inline) pragma instructs the compiler in its inlining decisions: +) + +$(UL + +$(LI $(C pragma(inline, false)): Instructs the compiler to never inline certain functions even when the $(C -inline) compiler switch is specified.) + +$(LI $(C pragma(inline, true)): Instructs the compiler to definitely inline certain functions when the $(C -inline) compiler switch is specified. This causes a compilation error if the compiler cannot inline such a function. (The exact behavior of this pragma may be different on your compiler.)) + +$(LI $(C pragma(inline)): Sets the inlining behavior back to the setting on the compiler command line: whether $(C -inline) is specified or not.) + +) + +$(P +These pragmas can affect the function that they appear in, as well as they can be used with a scope or colon to affect more than one function: +) + +--- +pragma(inline, false) $(HILITE {) + // Functions defined in this scope should not be inlined + // ... +$(HILITE }) + +int foo() { + pragma(inline, true); // This function should be inlined + // ... +} + +pragma(inline, true)$(HILITE :) +// Functions defined in this section should be inlined +// ... + +pragma(inline)$(HILITE :) +// Functions defined in this section should be inlined or not +// depending on the -inline compiler switch +// ... +--- + +$(P +$(IX -O, compiler switch) Another compiler switch that can make programs run faster is $(C -O), which instructs the compiler to perform more optimization algorithms. However, faster program speeds come at the expense of slower compilation speeds because these algorithms take significant amounts of time. +) + +$(H5 $(IX startaddress) $(C pragma(startaddress))) + +$(P +Specifies the start address of the program. Since the start address is normally assigned by the D runtime environment, it is very unlikely that you will ever use this pragma. +) + +$(H5 $(IX mangle, pragma) $(IX name mangling) $(C pragma(mangle))) + +$(P +Specifies that a symbol should be $(I name mangled) differently from the default name mangling method. Name mangling is about how the linker identifies functions and their callers. This pragma is useful when D code needs to call a library function that happens to be a D keyword. +) + +$(P +For example, if a C library had a function named $(C override), because $(C override) happens to be a keyword in D, the only way of calling it from D would be through a different name. However, that different name must still be mangled as the actual function name in the library for the linker to be able to identify it: +) + +--- +/* If a C library had a function named 'override', it could + * only be called from D through a name like 'c_override', + * mangled as the actual function name: */ +pragma($(HILITE mangle), "override") +extern(C) string c_override(string); + +void main() { + /* D code calls the function as c_override() but the + * linker would find it by its correct C library name + * 'override': */ + auto s = $(HILITE c_override)("hello"); +} +--- + +Macros: + TITLE=Pragmas + + DESCRIPTION=Introduction of pragmas, which are a way of interacting with the compiler. + + KEYWORDS=d programming language tutorial book pragma inline diff --git a/book/d.en/preface.d b/book/d.en/preface.d new file mode 100644 index 0000000000..d88aacb321 --- /dev/null +++ b/book/d.en/preface.d @@ -0,0 +1,80 @@ +Ddoc + +$(DIV_CLASS preface, + +$(DERS_BOLUMU_CLASS preface, Preface) + +$(P +D is a multi-paradigm system programming language that combines a wide range of powerful programming concepts from the lowest to the highest levels. It emphasizes memory safety, program correctness, and pragmatism. +) + +$(P +The main aim of this book is to teach D to readers who are new to computer programming. Although having experience in other programming languages is certainly helpful, this book starts from the basics. +) + +$(P +In order for this book to be useful, you will need an environment to write, compile, and run your D programs. This $(I development environment) must include at least a D compiler and a text editor. We will learn how to install a compiler and how to compile programs in the next chapter. +) + +$(P +Each chapter is based on the contents of the previous ones, introducing as few new concepts as possible. I recommend that you read the book in linear fashion, without skipping chapters. Although this book was written with beginners in mind, it covers almost all features of D. More experienced programmers can use the book as a D language reference by starting from the index section. +) + +$(P +Some chapters include exercises and their solutions so that you can write small programs and compare your methods to mine. +) + +$(P +Computer programming is a satisfying craft that involves continuously discovering and learning new tools, techniques, and concepts. I am sure you will enjoy programming in D at least as much as I do. Learning to program is easier and more fun when shared with others. Take advantage of $(LINK2 http://forum.dlang.org/group/digitalmars.D.learn/, the D.learn newsgroup) to follow discussions and to ask and answer questions. +) + +$(P +This book is available in $(LINK2 http://ddili.org/ders/d/, Turkish) as well. +) + +$(H5_FRONTMATTER Acknowledgments) + +$(P +I am indebted to the following people who have been instrumental during the evolution of this book: +) + +$(P +Mert Ataol, Zafer Çelenk, Salih Dinçer, Can Alpay Çiftçi, Faruk Erdem Öncel, Muhammet Aydın (aka Mengü Kağan), Ergin Güney, Jordi Sayol, David Herberth, Andre Tampubolon, Gour-Gadadhara Dasa, Raphaël Jakse, Andrej Mitrović, Johannes Pfau, Jerome Sniatecki, Jason Adams, Ali H. Çalışkan, Paul Jurczak, Brian Rogoff, Михаил Страшун (Mihails Strasuns), Joseph Rushton Wakeling, Tove, Hugo Florentino, Satya Pothamsetti, Luís Marques, Christoph Wendler, Daniel Nielsen, Ketmar Dark, Pavel Lukin, Jonas Fiala, Norman Hardy, Rich Morin, Douglas Foster, Paul Robinson, Sean Garratt, Stéphane Goujet, Shammah Chancellor, Steven Schveighoffer, Robbin Carlson, Bubnenkov Dmitry Ivanovich, Bastiaan Veelo, Olivier Pisano, Dave Yost, Tomasz Miazek-Mioduszewski, Gerard Vreeswijk, Justin Whear, Gerald Jansen, Sylvain Gault, Shriramana Sharma, Jay Norwood, Henri Menke, Chen Lejia, Vladimir Panteleev, Martin Tschierschke, ag0aep6g, Andrew Edwards, Steve White, Mark Schwarzmann, Thibaut Charles, Richard Palme, Don Grant, Goksan Kadir, Aleksandr Treyger, Michael Siegel, and Quirin Schroll. +) + +$(P +Thanks especially to Luís Marques and Steven Schveighoffer who, through their hard work, improved every chapter of the book. If you find any part of this book useful, it is likely due to their diligent editing. +) + +$(P +Thanks to Luís Marques, Steven Schveighoffer, Andrej Mitrović, Robbin Carlson, Ergin Güney, and Andrew Edwards for their suggestions that elevated this book from my Inglish to English. +) + +$(P +I am grateful to the entire D community for keeping my enthusiasm and motivation high. D has an amazing community of tireless individuals like bearophile and Kenji Hara. +) + +$(P +Ebru, Damla, and Derin, thank you for being so patient and supportive while I was lost writing these chapters. +$(BR) +$(BR) +Ali Çehreli$(BR) +Mountain View, $(I May 2017) +) + +$(P +$(BR) +$(BR) +This revision of the book contains many $(LINK2 https://bitbucket.org/acehreli/ddili/commits/all, corrections, improvements), and a new chapter: $(LINK2 static_foreach.html, $(C static foreach)). +$(BR) +$(BR) +Ali Çehreli$(BR) +Mountain View, $(I February 2019) +) + +) + +Macros: + TITLE= Preface + DESCRIPTION= + KEYWORDS= diff --git a/book/d.en/property.d b/book/d.en/property.d new file mode 100644 index 0000000000..3c5cf8b3fb --- /dev/null +++ b/book/d.en/property.d @@ -0,0 +1,387 @@ +Ddoc + +$(DERS_BOLUMU $(IX property) Properties) + +$(P +Properties allow using member functions like member variables. +) + +$(P +We are familiar with this feature from slices. The $(C length) property of a slice returns the number of elements of that slice: +) + +--- + int[] slice = [ 7, 8, 9 ]; + assert(slice$(HILITE .length) == 3); +--- + +$(P +Looking merely at that usage, one might think that $(C .length) is implemented as a member variable: +) + +--- +struct SliceImplementation { + int length; + + // ... +} +--- + +$(P +However, the other functionality of this property proves that it cannot be a member variable: Assigning a new value to the $(C .length) property actually changes the length of the slice, sometimes by adding new elements to the underlying array: +) + +--- + slice$(HILITE .length = 5); // The slice now has 5 elements + assert(slice.length == 5); +--- + +$(P $(I $(B Note:) The $(C .length) property of fixed-length arrays cannot be modified.) +) + +$(P +The assignment to $(C .length) above involves more complicated operations than a simple value change: Determining whether the array has capacity for the new length, allocating more memory if not, and moving the existing elements to the new place; and finally initializing each additional element by $(C .init). +) + +$(P +Evidently, the assignment to $(C .length) operates like a function. +) + +$(P +Properties are member functions that are used like member variables. +) + +$(H5 $(IX ()) Calling functions without parentheses) + +$(P +As has been mentioned in the previous chapter, when there is no argument to pass, functions can be called without parentheses: +) + +--- + writeln(); + writeln; // Same as the previous line +--- + +$(P +This feature is closely related to properties because properties are used almost always without parentheses. +) + +$(H5 Property functions that return values) + +$(P +As a simple example, let's consider a rectangle struct that consists of two members: +) + +--- +struct Rectangle { + double width; + double height; +} +--- + +$(P +Let's assume that a third property of this type becomes a requirement, which should provide the area of the rectangle: +) + +--- + auto garden = Rectangle(10, 20); + writeln(garden$(HILITE .area)); +--- + +$(P +One way of achieving that requirement is to define a third member: +) + +--- +struct Rectangle { + double width; + double height; + double area; +} +--- + +$(P +A flaw in that design is that the object may easily become inconsistent: Although rectangles must always have the invariant of "width * height == area", this consistency may be broken if the members are allowed to be modified freely and independently. +) + +$(P +As an extreme example, objects may even begin their lives in inconsistent states: +) + +--- + // Inconsistent object: The area is not 10 * 20 == 200. + auto garden = Rectangle(10, 20, $(HILITE 1111)); +--- + +$(P +A better way would be to represent the concept of area as a property. Instead of defining an additional member, the value of that member is calculated by a function named $(C area), the same as the concept that it represents: +) + +--- +struct Rectangle { + double width; + double height; + + double area() const { + return width * height; + } +} +--- + +$(P $(I $(B Note:) As you would remember from $(LINK2 const_member_functions.html, the $(CH4 const ref) Parameters and $(CH4 const) Member Functions chapter), the $(C const) specifier on the function declaration ensures that the object is not modified by this function.) +) + +$(P +That property function enables the struct to be used as if it has a third member variable: +) + +--- + auto garden = Rectangle(10, 20); + writeln("The area of the garden: ", garden$(HILITE .area)); +--- + +$(P +As the value of the $(C area) property is calculated by multiplying the width and the height of the rectangle, this time it would always be consistent: +) + +$(SHELL +The area of the garden: 200 +) + +$(H5 Property functions that are used in assignment) + +$(P +Similar to the $(C length) property of slices, the properties of user-defined types can be used in assignment operations as well: +) + +--- + garden.area = 50; +--- + +$(P +For that assignment to actually change the area of the rectangle, the two members of the struct must be modified accordingly. To enable this functionality, we can assume that the rectangle is $(I flexible) so that to maintain the invariant of "width * height == area", the sides of the rectangle can be changed. +) + +$(P +The function that enables such an assignment syntax is also named as $(C area). The value that is used on the right-hand side of the assignment becomes the only parameter of this function. +) + +$(P +The following additional definition of $(C area()) enables using that property in assignment operations and effectively modifying the area of $(C Rectangle) objects: +) + +--- +import std.stdio; +import std.math; + +struct Rectangle { + double width; + double height; + + double area() const { + return width * height; + } + + $(HILITE void area(double newArea)) { + auto scale = sqrt(newArea / area); + + width *= scale; + height *= scale; + } +} + +void main() { + auto garden = Rectangle(10, 20); + writeln("The area of the garden: ", garden.area); + + $(HILITE garden.area = 50); + + writefln("New state: %s x %s = %s", + garden.width, garden.height, garden.area); +} +--- + +$(P +The new function takes advantage of the $(C sqrt) function from the $(C std.math) module, which returns the square root of the specified value. When both of the width and the height of the rectangle are scaled by the square root of the ratio, then the area would equal the desired value. +) + +$(P +As a result, assigning the quarter of its current value to $(C area) ends up halving both sides of the rectangle: +) + +$(SHELL +The area of the garden: 200 +New state: 5 x 10 = 50 +) + +$(H5 Properties are not absolutely necessary) + +$(P +We have seen above how $(C Rectangle) can be used as if it has a third member variable. However, regular member functions could also be used instead of properties: +) + +--- +import std.stdio; +import std.math; + +struct Rectangle { + double width; + double height; + + double $(HILITE area()) const { + return width * height; + } + + void $(HILITE setArea(double newArea)) { + auto scale = sqrt(newArea / area); + + width *= scale; + height *= scale; + } +} + +void main() { + auto garden = Rectangle(10, 20); + writeln("The area of the garden: ", garden$(HILITE .area())); + + garden$(HILITE .setArea(50)); + + writefln("New state: %s x %s = %s", + garden.width, garden.height, garden$(HILITE .area())); +} +--- + +$(P +Further, as we have seen in $(LINK2 function_overloading.html, the Function Overloading chapter), these two functions could even have the same names: +) + +--- + double area() const { + // ... + } + + void area(double newArea) { + // ... + } +--- + +$(H5 When to use) + +$(P +It may not be easy to chose between regular member functions and properties. Sometimes regular member functions feel more natural and sometimes properties. +) + +$(P +However, as we have seen in $(LINK2 encapsulation.html, the Encapsulation and Protection Attributes chapter), it is important to restrict direct access to member variables. Allowing user code to freely modify member variables always ends up causing issues with code maintenance. For that reason, member variables better be encapsulated either by regular member functions or by property functions. +) + +$(P +Leaving members like $(C width) and $(C height) open to $(C public) access is acceptable only for very simple types. Almost always a better design is to use property functions: +) + +--- +struct Rectangle { +$(HILITE private:) + + double width_; + double height_; + +public: + + double area() const { + return width * height; + } + + void area(double newArea) { + auto scale = sqrt(newArea / area); + + width_ *= scale; + height_ *= scale; + } + + double $(HILITE width()) const { + return width_; + } + + double $(HILITE height()) const { + return height_; + } +} +--- + +$(P +Note how the members are made $(C private) so that they can only be accessed by corresponding property functions. +) + +$(P +Also note that to avoid confusing their names with the member functions, the names of the member variables are appended by the $(C _) character. $(I Decorating) the names of member variables is a common practice in object oriented programming. +) + +$(P +That definition of $(C Rectangle) still presents $(C width) and $(C height) as if they are member variable: +) + +--- + auto garden = Rectangle(10, 20); + writefln("width: %s, height: %s", + garden$(HILITE .width), garden$(HILITE .height)); +--- + +$(P +When there is no property function that modifies a member variable, then that member is effectively read-only from the outside: +) + +--- + garden.width = 100; $(DERLEME_HATASI) +--- + +$(P +This is important for controlled modifications of members. The member variables can only be modified by the $(C Rectangle) type itself to ensure the consistency of its objects. +) + +$(P +When it later makes sense that a member variable should be allowed to be modified from the outside, then it is simply a matter of defining another property function for that member. +) + +$(H6 $(IX @property) $(C @property)) + +$(P +Property functions may be defined with the $(C @property) attribute as well. However, as a best practice, the use of this attribute is discouraged. +) + +--- +import std.stdio; + +struct Foo { + $(HILITE @property) int a() const { + return 42; + } + + int b() const { $(CODE_NOTE Defined without @property) + return 42; + } +} + +void main() { + auto f = Foo(); + + writeln(typeof(f.a).stringof); + writeln(typeof(f.b).stringof); +} +--- + +$(P +The only effect of the $(C @property) attribute is when determining the type of an expression that could syntactically be a property function call. As seen in the output below, the types of the expressions $(C f.a) and $(C f.b) are different: +) + +$(SHELL +int $(SHELL_NOTE The type of the expression f.a (the return type)) +const int() $(SHELL_NOTE The type of the member function Foo.b) +) + +Macros: + TITLE=Properties + + DESCRIPTION=Enabling using member functions like member variables. + + KEYWORDS=d programming lesson book tutorial property diff --git a/book/d.en/ranges.d b/book/d.en/ranges.d new file mode 100644 index 0000000000..ab3b082731 --- /dev/null +++ b/book/d.en/ranges.d @@ -0,0 +1,2044 @@ +Ddoc + +$(DERS_BOLUMU $(IX range) Ranges) + +$(P +Ranges are an abstraction of element access. This abstraction enables the use of great number of algorithms over great number of container types. Ranges emphasize how container elements are accessed, as opposed to how the containers are implemented. +) + +$(P +Ranges are a very simple concept that is based on whether a type defines certain sets of member functions. We have already seen this concept in the $(LINK2 foreach_opapply.html, $(C foreach) with Structs and Classes chapter): any type that provides the member functions $(C empty), $(C front), and $(C popFront()) can be used with the $(C foreach) loop. The set of those three member functions is the requirement of the range type $(C InputRange). +) + +$(P +I will start introducing ranges with $(C InputRange), the simplest of all the range types. The other ranges require more member functions over $(C InputRange). +) + +$(P +Before going further, I would like to provide the definitions of containers and algorithms. +) + +$(P +$(IX container) $(IX data structure) $(B Container (data structure):) Container is a very useful concept that appears in almost every program. Variables are put together for a purpose and are used together as elements of a container. D's containers are its core features arrays and associative arrays, and special container types that are defined in the $(C std.container) module. Every container is implemented as a specific data structure. For example, associative arrays are a $(I hash table) implementation. +) + +$(P +Every data structure stores its elements and provides access to them in ways that are special to that data structure. For example, in the array data structure the elements are stored side by side and accessed by an element index; in the linked list data structure the elements are stored in nodes and are accessed by going through those nodes one by one; in a sorted binary tree data structure, the nodes provide access to the preceding and successive elements through separate branches; etc. +) + +$(P +In this chapter, I will use the terms $(I container) and $(I data structure) interchangeably. +) + +$(P +$(IX algorithm) $(B Algorithm (function):) Processing of data structures for specific purposes in specific ways is called an $(I algorithm). For example, $(I linear search) is an algorithm that searches by iterating over a container from the beginning to the end; $(I binary search) is an algorithm that searches for an element by eliminating half of the candidates at every step; etc. +) + +$(P +In this chapter, I will use the terms $(I algorithm) and $(I function) interchangeably. +) + +$(P +For most of the samples below, I will use $(C int) as the element type and $(C int[]) as the container type. In reality, ranges are more powerful when used with templated containers and algorithms. In fact, most of the containers and algorithms that ranges tie together are all templates. I will leave examples of templated ranges to $(LINK2 ranges_more.html, the next chapter). +) + +$(H5 History) + +$(P +A very successful library that abstracts algorithms and data structures from each other is the Standard Template Library (STL), which also appears as a part of the C++ standard library. STL provides this abstraction with the $(I iterator) concept, which is implemented by C++'s templates. +) + +$(P +Although they are a very useful abstraction, iterators do have some weaknesses. D's ranges were designed to overcome these weaknesses. +) + +$(P +Andrei Alexandrescu introduces ranges in his paper $(LINK2 http://www.informit.com/articles/printerfriendly.aspx?p=1407357, On Iteration) and demonstrates how they can be superior to iterators. +) + +$(H5 Ranges are an integral part of D) + +$(P +D's slices happen to be implementations of the most powerful range $(C RandomAccessRange), and there are many range features in Phobos. It is essential to understand how ranges are used in Phobos. +) + +$(P +Many Phobos algorithms return temporary range objects. For example, $(C filter()), which chooses elements that are greater than 10 in the following code, actually returns a range object, not an array: +) + +--- +import std.stdio; +import std.algorithm; + +void main() { + int[] values = [ 1, 20, 7, 11 ]; + writeln(values.filter!(value => value > 10)); +} +--- + +$(P +$(C writeln) uses that range object lazily and accesses the elements as it needs them: +) + +$(SHELL +[20, 11] +) + +$(P +That output may suggest that $(C filter()) returns an $(C int[]) but this is not the case. We can see this from the fact that the following assignment produces a compilation error: +) + +--- + int[] chosen = values.filter!(value => value > 10); $(DERLEME_HATASI) +--- + +$(P +The error message contains the type of the range object: +) + +$(SHELL +Error: cannot implicitly convert expression (filter(values)) +of type $(HILITE FilterResult!(__lambda2, int[])) to int[] +) + +$(P +$(I $(B Note:) The type may be different in the version of Phobos that you are using.) +) + +$(P +It is possible to convert that temporary object to an actual array, as we will see later in the chapter. +) + +$(H5 Traditional implementations of algorithms) + +$(P +In traditional implementations of algorithms, the algorithms know how the data structures that they operate on are implemented. For example, the following function that prints the elements of a linked list must know that the nodes of the linked list have members named $(C element) and $(C next): +) + +--- +struct Node { + int element; + Node * next; +} + +void print(const(Node) * list) { + for ( ; list; list = list.$(HILITE next)) { + write(' ', list.$(HILITE element)); + } +} +--- + +$(P +Similarly, a function that prints the elements of an array must know that arrays have a $(C length) property and their elements are accessed by the $(C []) operator: +) + +--- +void print(const int[] array) { + for (int i = 0; i != array.$(HILITE length); ++i) { + write(' ', array$(HILITE [i])); + } +} +--- + +$(P +$(I $(B Note:) We know that $(C foreach) is more useful when iterating over arrays. As a demonstration of how traditional algorithms are tied to data structures, let's assume that the use of $(C for) is justified.) +) + +$(P +Having algorithms tied to data structures makes it necessary to write them specially for each type. For example, the functions find(), sort(), swap(), etc. must be written separately for array, linked list, associative array, binary tree, heap, etc. As a result, N algorithms that support M data structures must be written NxM times. (Note: In reality, the count is less than NxM because not every algorithm can be applied to every data structure; for example, associative arrays cannot be sorted.) +) + +$(P +Conversely, because ranges abstract algorithms away from data structures, implementing just N algorithms and M data structures would be sufficient. A newly implemented data structure can work with all of the existing algorithms that support the type of range that the new data structure provides, and a newly implemented algorithm can work with all of the existing data structures that support the range type that the new algorithm requires. +) + +$(H5 Phobos ranges) + +$(P +The ranges in this chapter are different from number ranges that are written in the form $(C begin..end). We have seen how number ranges are used with the $(C foreach) loop and with slices: +) + +--- + foreach (value; $(HILITE 3..7)) { // number range, + // NOT a Phobos range + + int[] slice = array[$(HILITE 5..10)]; // number range, + // NOT a Phobos range +--- + +$(P +When I write $(I range) in this chapter, I mean a Phobos range . +) + +$(P +Ranges form a $(I range hierarchy). At the bottom of this hierarchy is the simplest range $(C InputRange). The other ranges bring more requirements on top of the range on which they are based. The following are all of the ranges with their requirements, sorted from the simplest to the more capable: +) + +$(UL + +$(LI $(C InputRange): requires the $(C empty), $(C front) and $(C popFront()) member functions) + +$(LI $(C ForwardRange): additionally requires the $(C save) member function) + +$(LI $(C BidirectionalRange): additionally requires the $(C back) and $(C popBack()) member functions) + +$(LI $(C RandomAccessRange): additionally requires the $(C []) operator (and another property depending on whether the range is finite or infinite)) + +) + +$(P +This hierarchy can be shown as in the following graph. $(C RandomAccessRange) has finite and infinite versions: +) + +$(MONO + InputRange + ↑ + ForwardRange + ↗ ↖ + BidirectionalRange RandomAccessRange (infinite) + ↑ + RandomAccessRange (finite) +) + +$(P +The graph above is in the style of class hierarchies where the lowest level type is at the top. +) + +$(P +Those ranges are about providing element access. There is one more range, which is about element $(I output): +) + +$(UL +$(LI $(C OutputRange): requires support for the $(C put(range, element)) operation) +) + +$(P +These five range types are sufficient to abstract algorithms from data structures. +) + +$(H6 Iterating by shortening the range) + +$(P +Normally, iterating over the elements of a container does not change the container itself. For example, iterating over a slice with $(C foreach) or $(C for) does not affect the slice: +) + +--- + int[] slice = [ 10, 11, 12 ]; + + for (int i = 0; i != slice.length; ++i) { + write(' ', slice[i]); + } + + assert(slice.length == 3); // ← the length doesn't change +--- + +$(P +Another way of iteration requires a different way of thinking: iteration can be achieved by shortening the range from the beginning. In this method, it is always the first element that is used for element access and the first element is $(I popped) from the beginning in order to get to the next element: +) + +--- + for ( ; slice.length; slice = slice[1..$]) { + write(' ', $(HILITE slice[0])); // ← always the first element + } +--- + +$(P +$(I Iteration) is achieved by removing the first element by the $(C slice = slice[1..$]) expression. The slice above is completely consumed by going through the following stages: +) + +$(MONO +[ 10, 11, 12 ] + [ 11, 12 ] + [ 12 ] + [ ] +) + +$(P +The iteration concept of Phobos ranges is based on this new thinking of shortening the range from the beginning. ($(C BidirectionalRange) and finite $(C RandomAccessRange) types can be shortened from the end as well.) +) + +$(P +Please note that the code above is just to demonstrate this type of iteration; it should not be considered normal to iterate as in that example. +) + +$(P +Since losing elements just to iterate over a range would not be desired in most cases, a surrogate range may be consumed instead. The following code uses a separate slice to preserve the elements of the original one: +) + +--- + int[] slice = [ 10, 11, 12 ]; + int[] surrogate = slice; + + for ( ; surrogate.length; $(HILITE surrogate = surrogate[1..$])) { + write(' ', surrogate[0]); + } + + assert(surrogate.length == 0); // ← surrogate is consumed + assert(slice.length == 3); // ← slice remains the same +--- + +$(P +This is the method employed by most of the Phobos range functions: they return special range objects to be consumed in order to preserve the original containers. +) + +$(H5 $(IX InputRange) $(C InputRange)) + +$(P +This type of range models the type of iteration where elements are accessed in sequence as we have seen in the $(C print()) functions above. Most algorithms only require that elements are iterated in the forward direction without needing to look at elements that have already been iterated over. $(C InputRange) models the standard input streams of programs as well, where elements are removed from the stream as they are read. +) + +$(P +For completeness, here are the three functions that $(C InputRange) requires: +) + +$(UL + +$(LI $(IX empty) $(C empty): specifies whether the range is empty; it must return $(C true) when the range is considered to be empty, and $(C false) otherwise) + +$(LI $(IX front) $(C front): provides access to the element at the beginning of the range) + +$(LI $(IX popFront) $(C popFront()): shortens the range from the beginning by removing the first element) + +) + +$(P +$(I $(B Note:) I write $(C empty) and $(C front) without parentheses, as they can be seen as properties of the range; and $(C popFront()) with parentheses as it is a function with side effects.) +) + +$(P +Here is how $(C print()) can be implemented by using these range functions: +) + +--- +void print(T)(T range) { + for ( ; !range$(HILITE .empty); range$(HILITE .popFront())) { + write(' ', range$(HILITE .front)); + } + + writeln(); +} +--- + +$(P +Please also note that $(C print()) is now a function template to avoid limiting the range type arbitrarily. $(C print()) can now work with any type that provides the three $(C InputRange) functions. +) + +$(H6 $(C InputRange) example) + +$(P +Let's redesign the $(C School) type that we have seen before, this time as an $(C InputRange). We can imagine $(C School) as a $(C Student) container so when designed as a range, it can be seen as a range of $(C Student)s. +) + +$(P +In order to keep the example short, let's disregard some important design aspects. Let's +) + +$(UL + +$(LI implement only the members that are related to this section) + +$(LI design all types as structs) + +$(LI ignore specifiers and qualifiers like $(C private), $(C public), and $(C const)) + +$(LI not take advantage of contract programming and unit testing) + +) + +--- +import std.string; + +struct Student { + string name; + int number; + + string toString() const { + return format("%s(%s)", name, number); + } +} + +struct School { + Student[] students; +} + +void main() { + auto school = School( [ Student("Ebru", 1), + Student("Derya", 2) , + Student("Damla", 3) ] ); +} +--- + +$(P +To make $(C School) be accepted as an $(C InputRange), we must define the three $(C InputRange) member functions. +) + +$(P +For $(C empty) to return $(C true) when the range is empty, we can use the length of the $(C students) array. When the length of that array is 0, the range is considered empty: +) + +--- +struct School { + // ... + + bool empty() const { + return students.length == 0; + } +} +--- + +$(P +For $(C front) to return the first element of the range, we can return the first element of the array: +) + +--- +struct School { + // ... + + ref Student front() { + return students[0]; + } +} +--- + +$(P +$(I $(B Note:) I have used the $(C ref) keyword to be able to provide access to the actual element instead of a copy of it. Otherwise the elements would be copied because $(C Student) is a struct.) +) + +$(P +For $(C popFront()) to shorten the range from the beginning, we can shorten the $(C students) array from the beginning: +) + +--- +struct School { + // ... + + void popFront() { + students = students[1 .. $]; + } +} +--- + +$(P +$(I $(B Note:) As I have mentioned above, it is not normal to lose the original elements from the container just to iterate over them. We will address this issue below by introducing a special range type.) +) + +$(P +These three functions are sufficient to make $(C School) to be used as an $(C InputRange). As an example, let's add the following line at the end of $(C main()) above to have our new $(C print()) function template to use $(C school) as a range: +) + +--- + print(school); +--- + +$(P +$(C print()) uses that object as an $(C InputRange) and prints its elements to the output: +) + +$(SHELL + Ebru(1) Derya(2) Damla(3) +) + +$(P +We have achieved our goal of defining a user type as an $(C InputRange); we have sent it to an algorithm that operates on $(C InputRange) types. $(C School) is actually ready to be used with algorithms of Phobos or any other library that work with $(C InputRange) types. We will see examples of this below. +) + +$(H6 $(IX slice, as InputRange) The $(C std.array) module to use slices as ranges) + +$(P +Merely importing the $(C std.array) module makes the most common container type conform to the most capable range type: slices can seamlessly be used as $(C RandomAccessRange) objects. +) + +$(P +The $(C std.array) module provides the functions $(C empty), $(C front), $(C popFront()) and other range functions for slices. As a result, slices are ready to be used with any range function, for example with $(C print()): +) + +--- +import $(HILITE std.array); + +// ... + + print([ 1, 2, 3, 4 ]); +--- + +$(P +It is not necessary to import $(C std.array) if the $(C std.range) module has already been imported. +) + +$(P +Since it is not possible to remove elements from fixed-length arrays, $(C popFront()) cannot be defined for them. For that reason, fixed-length arrays cannot be used as ranges themselves: +) + +--- +void print(T)(T range) { + for ( ; !range.empty; range.popFront()) { $(DERLEME_HATASI) + write(' ', range.front); + } + + writeln(); +} + +void main() { + int[$(HILITE 4)] array = [ 1, 2, 3, 4 ]; + print(array); +} +--- + +$(P +It would be better if the compilation error appeared on the line where $(C print()) is called. This is possible by adding a template constraint to $(C print()). The following template constraint takes advantage of $(C isInputRange), which we will see in the next chapter. By the help of the template constraint, now the compilation error is for the line where $(C print()) is called, not for a line where $(C print()) is defined: +) + +--- +void print(T)(T range) + if (isInputRange!T) { // template constraint + // ... +} +// ... + print(array); $(DERLEME_HATASI) +--- + +$(P +The elements of a fixed-length array can still be accessed by range functions. What needs to be done is to use a slice of the whole array, not the array itself: +) + +--- + print(array$(HILITE [])); // now compiles +--- + +$(P +Even though slices can be used as ranges, not every range type can be used as an array. When necessary, all of the elements can be copied one by one into an array. $(C std.array.array) is a helper function to simplify this task; $(C array()) iterates over $(C InputRange) ranges, copies the elements, and returns a new array: +) + +--- +import std.array; + +// ... + + // Note: Also taking advantage of UFCS + auto copiesOfStudents = school.$(HILITE array); + writeln(copiesOfStudents); +--- + +$(P +The output: +) + +$(SHELL +[Ebru(1), Derya(2), Damla(3)] +) + +$(P +Also note the use of $(LINK2 ufcs.html, UFCS) in the code above. UFCS goes very well with range algorithms by making code naturally match the execution order of expressions. +) + +$(H6 $(IX string, as range) $(IX dchar, string range) $(IX decoding, automatic) Automatic decoding of strings as ranges of $(C dchar)) + +$(P +Being character arrays by definition, strings can also be used as ranges just by importing $(C std.array). However, $(C char) and $(C wchar) strings cannot be used as $(C RandomAccessRange). +) + +$(P +$(C std.array) provides a special functionality with all types of strings: Iterating over strings becomes iterating over Unicode code points, not over UTF code units. As a result, strings appear as ranges of Unicode characters. +) + +$(P +The following strings contain ç and é, which cannot be represented by a single $(C char), and 𝔸 (mathematical double-struck capital A), which cannot be represented by a single $(C wchar) (note that these characters may not be displayed correctly in the environment that you are reading this chapter): +) + +--- +import std.array; + +// ... + + print("abcçdeé𝔸"c); + print("abcçdeé𝔸"w); + print("abcçdeé𝔸"d); +--- + +$(P +The output of the program is what we would normally expect from a $(I range of letters): +) + +$(XXX We use MONO_NOBOLD instead of SHELL to ensure that 𝔸 is displayed correctly.) +$(MONO_NOBOLD + a b c ç d e é 𝔸 + a b c ç d e é 𝔸 + a b c ç d e é 𝔸 +) + +$(P +As you can see, that output does not match what we saw in the $(LINK2 characters.html, Characters) and $(LINK2 strings.html, Strings) chapters. We have seen in those chapters that $(C string) is an alias to an array of $(C immutable(char)) and $(C wstring) is an alias to an array of $(C immutable(wchar)). Accordingly, one might expect to see UTF code units in the previous output instead of the properly decoded Unicode characters. +) + +$(P +The reason why the characters are displayed correctly is because when used as ranges, string elements are automatically decoded. As we will see below, the decoded $(C dchar) values are not actual elements of the strings but $(LINK2 lvalue_rvalue.html, rvalues). +) + +$(P +As a reminder, let's consider the following function that treats the strings as arrays of code units: +) + +--- +void $(HILITE printElements)(T)(T str) { + for (int i = 0; i != str.length; ++i) { + write(' ', str$(HILITE [i])); + } + + writeln(); +} + +// ... + + printElements("abcçdeé𝔸"c); + printElements("abcçdeé𝔸"w); + printElements("abcçdeé𝔸"d); +--- + +$(P +When the characters are accessed directly by indexing, the elements of the arrays are not decoded: +) + +$(XXX We use MONO_NOBOLD instead of SHELL to ensure that 𝔸 is displayed correctly.) +$(MONO_NOBOLD + a b c � � d e � � � � � � + a b c ç d e é ��� ��� + a b c ç d e é 𝔸 +) + +$(P +$(IX representation, std.string) Automatic decoding is not always the desired behavior. For example, the following program that is trying to assign to the first element of a string cannot be compiled because the return value of $(C .front) is an rvalue: +) + +--- +import std.array; + +void main() { + char[] s = "hello".dup; + s.front = 'H'; $(DERLEME_HATASI) +} +--- + +$(SHELL +Error: front(s) is $(HILITE not an lvalue) +) + +$(P +When a range algorithm needs to modify the actual code units of a string (and when doing so does not invalidate the UTF encoding), then the string can be used as a range of $(C ubyte) elements by $(C std.string.represention): +) + +--- +import std.array; +import std.string; + +void main() { + char[] s = "hello".dup; + s$(HILITE .representation).front = 'H'; // compiles + assert(s == "Hello"); +} +--- + +$(P +$(C representation) presents the actual elements of $(C char), $(C wchar), and $(C dchar) strings as ranges of $(C ubyte), $(C ushort), and $(C uint), respectively. +) + +$(H6 Ranges without actual elements) + +$(P +The elements of the $(C School) objects were actually stored in the $(C students) member slices. So, $(C School.front) returned a reference to an existing $(C Student) object. +) + +$(P +One of the powers of ranges is the flexibility of not actually owning elements. $(C front) need not return an actual element of an actual container. The returned $(I element) can be calculated each time when $(C popFront()) is called, and can be used as the value that is returned by $(C front). +) + +$(P +We have already seen a range without actual elements above: Since $(C char) and $(C wchar) cannot represent all Unicode characters, the Unicode characters that appear as range elements cannot be actual elements of any $(C char) or $(C wchar) array. In the case of strings, $(C front) returns a $(C dchar) that is $(I constructed) from the corresponding UTF code units of arrays: +) + +--- +import std.array; + +void main() { + dchar letter = "é".front; // The dchar that is returned by + // front is constructed from the + // two chars that represent é +} +--- + +$(P +Although the element type of the array is $(C char), the return type of $(C front) above is $(C dchar). That $(C dchar) is not an element of the array but is an $(LINK2 lvalue_rvalue.html, rvalue) decoded as a Unicode character from the elements of the array. +) + +$(P +Similarly, some ranges do not own any elements but are used for providing access to elements of other ranges. This is a solution to the problem of losing elements while iterating over $(C School) objects above. In order to preserve the elements of the actual $(C School) objects, a special $(C InputRange) can be used. +) + +$(P +To see how this is done, let's define a new struct named $(C StudentRange) and move all of the range member functions from $(C School) to this new struct. Note that $(C School) itself is not a range anymore: +) + +--- +struct School { + Student[] students; +} + +struct StudentRange { + Student[] students; + + this(School school) { + $(HILITE this.students = school.students); + } + + bool empty() const { + return students.length == 0; + } + + ref Student front() { + return students[0]; + } + + void popFront() { + students = students[1 .. $]; + } +} +--- + +$(P +The new range starts with a member slice that provides access to the students of $(C School) and consumes that member slice in $(C popFront()). As a result, the actual slice in $(C School) is preserved: +) + +--- + auto school = School( [ Student("Ebru", 1), + Student("Derya", 2) , + Student("Damla", 3) ] ); + + print($(HILITE StudentRange)(school)); + + // The actual array is now preserved: + assert(school.students.length == 3); +--- + +$(P +$(I $(B Note:) Since all its work is dispatched to its member slice, $(C StudentRange) may not be seen as a good example of a range. In fact, assuming that $(C students) is an accessible member of $(C School), the user code could have created a slice of $(C School.students) directly and could have used that slice as a range.) +) + +$(H6 $(IX infinite range) Infinite ranges) + +$(P +Another benefit of not storing elements as actual members is the ability to create infinite ranges. +) + +$(P +Making an infinite range is as simple as having $(C empty) always return $(C false). Since it is constant, $(C empty) need not even be a function and can be defined as an $(C enum) value: +) + +--- + enum empty = false; // ← infinite range +--- + +$(P +Another option is to use an immutable $(C static) member: +) + +--- + static immutable empty = false; // same as above +--- + +$(P +As an example of this, let's design a range that represents the Fibonacci series. Despite having only two $(C int) members, the following range can be used as the infinite Fibonacci series: +) + +--- +$(CODE_NAME FibonacciSeries_InputRange)$(CODE_COMMENT_OUT)struct FibonacciSeries +$(CODE_COMMENT_OUT){ + int current = 0; + int next = 1; + + enum empty = false; // ← infinite range + + int front() const { + return current; + } + + void popFront() { + const nextNext = current + next; + current = next; + next = nextNext; + } +$(CODE_COMMENT_OUT)} +--- + +$(P +$(I $(B Note:) Although it is infinite, because the members are of type $(C int), the elements of this Fibonacci series would be wrong beyond $(C int.max).) +) + +$(P +Since $(C empty) is always $(C false) for $(C FibonacciSeries) objects, the $(C for) loop in $(C print()) never terminates for them: +) + +--- + print(FibonacciSeries()); // never terminates +--- + +$(P +An infinite range is useful when the range need not be consumed completely right away. We will see how to use only some of the elements of a $(C FibonacciSeries) below. +) + +$(H6 Functions that return ranges) + +$(P +Earlier, we have created a $(C StudentRange) object by explicitly writing $(C StudentRange(school)). +) + +$(P +$(IX convenience function) In most cases, a convenience function that returns the object of such a range is used instead. For example, a function with the whole purpose of returning a $(C StudentRange) would simplify the code: +) + +--- +StudentRange studentsOf(ref School school) { + return StudentRange(school); +} + +// ... + + // Note: Again, taking advantage of UFCS + print(school.$(HILITE studentsOf)); +--- + +$(P +This is a convenience over having to remember and spell out the names of range types explicitly, which can get quite complicated in practice. +) + +$(P +$(IX take, std.range) We can see an example of this with the simple $(C std.range.take) function. $(C take()) is a function that provides access to a specified number of elements of a range, from the beginning. In reality, this functionality is not achieved by the $(C take()) function itself, but by a special range object that it returns. This fact need not be explicit when using $(C take()): +) + +--- +import std.range; + +// ... + + auto school = School( [ Student("Ebru", 1), + Student("Derya", 2) , + Student("Damla", 3) ] ); + + print(school.studentsOf.$(HILITE take(2))); +--- + +$(P +$(C take()) returns a temporary range object above, which provides access to the first 2 elements of $(C school). In turn, $(C print()) uses that object and produces the following output: +) + +$(SHELL + Ebru(1) Derya(2) +) + +$(P +The operations above still don't make any changes to $(C school); it still has 3 elements: +) + +--- + print(school.studentsOf.take(2)); + assert(school.students.length == 3); +--- + +$(P +The specific types of the range objects that are returned by functions like $(C take()) are not important. These types may sometimes be exposed in error messages, or we can print them ourselves with the help of $(C typeof) and $(C stringof): +) + +--- + writeln(typeof(school.studentsOf.take(2)).stringof); +--- + +$(P +According to the output, $(C take()) returns an instance of a template named $(C Take): +) + +$(SHELL +Take!(StudentRange) +) + +$(H6 $(IX std.range) $(IX std.algorithm) $(C std.range) and $(C std.algorithm) modules) + +$(P +A great benefit of defining our types as ranges is being able to use them not only with our own functions, but with Phobos and other libraries as well. +) + +$(P +$(C std.range) includes a large number of range functions, structs, and classes. $(C std.algorithm) includes many algorithms that are commonly found also in the standard libraries of other languages. +) + +$(P +$(IX swapFront, std.algorithm) To see an example of how our types can be used with standard modules, let's use $(C School) with the $(C std.algorithm.swapFront) algorithm. $(C swapFront()) swaps the front elements of two $(C InputRange) ranges. (It requires that the front elements of the two ranges are swappable. Arrays satisfy that condition.) +) + +$(P + +) + +--- +import std.algorithm; + +// ... + + auto turkishSchool = School( [ Student("Ebru", 1), + Student("Derya", 2) , + Student("Damla", 3) ] ); + + auto americanSchool = School( [ Student("Mary", 10), + Student("Jane", 20) ] ); + + $(HILITE swapFront)(turkishSchool.studentsOf, + americanSchool.studentsOf); + + print(turkishSchool.studentsOf); + print(americanSchool.studentsOf); +--- + +$(P +The first elements of the two schools are swapped: +) + +$(SHELL + $(HILITE Mary(10)) Derya(2) Damla(3) + $(HILITE Ebru(1)) Jane(20) +) + +$(P +$(IX filter, std.algorithm) As another example, let's now look at the $(C std.algorithm.filter) algorithm. $(C filter()) returns a special range that filters out elements that do not satisfy a specific condition (a $(I predicate)). The operation of filtering out the elements only affects accessing the elements; the original range is preserved. +) + +$(P +$(IX predicate) Predicates are expressions that must evaluate to $(C true) for the elements that are considered to satisfy a condition, and $(C false) for the elements that do not. There are a number of ways of specifying the predicate that $(C filter()) should use. As we have seen in earlier examples, one way is to use a lambda expression. The parameter $(C a) below represents each student: +) + +--- + school.studentsOf.filter!(a => a.number % 2) +--- + +$(P +The predicate above selects the elements of the range $(C school.studentsOf) that have odd numbers. +) + +$(P +Like $(C take()), $(C filter()) returns a special range object as well. That range object in turn can be passed to other range functions. For example, it can be passed to $(C print()): +) + +--- + print(school.studentsOf.filter!(a => a.number % 2)); +--- + +$(P +That expression can be explained as $(I start with the range $(C school.studentsOf), construct a range object that will filter out the elements of that initial range, and pass the new range object to $(C print())). +) + +$(P +The output consists of students with odd numbers: +) + +$(SHELL + Ebru(1) Damla(3) +) + +$(P +As long as it returns $(C true) for the elements that satisfy the condition, the predicate can also be specified as a function: +) + +--- +import std.array; + +// ... + + bool startsWithD(Student student) { + return student.name.front == 'D'; + } + + print(school.studentsOf.filter!startsWithD); +--- + +$(P +The predicate function above returns $(C true) for students having names starting with the letter D, and $(C false) for the others. +) + +$(P +$(I $(B Note:) Using $(C student.name[0]) would have meant the first UTF-8 code unit, not the first letter. As I have mentioned above, $(C front) uses $(C name) as a range and always returns the first Unicode character.) +) + +$(P +This time the students whose names start with D are selected and printed: +) + +$(SHELL + Derya(2) Damla(3) +) + +$(P +$(IX generate, std.range) $(C generate()), a convenience function template of the $(C std.range) module, makes it easy to present values returned from a function as the elements of an $(C InputRange). It takes any callable entity (function pointer, delegate, etc.) and returns an $(C InputRange) object conceptually consisting of the values that are returned from that callable entity. +) + +$(P +The returned range object is infinite. Every time the $(C front) property of that range object is accessed, the original callable entity is called to get a new $(I element) from it. The $(C popFront()) function of the range object does not perform any work. +) + +$(P +For example, the following range object $(C diceThrower) can be used as an infinite range: +) + +--- +import std.stdio; +import std.range; +import std.random; + +void main() { + auto diceThrower = $(HILITE generate)!(() => uniform(0, 6)); + writeln(diceThrower.take(10)); +} +--- + +$(SHELL +[1, 0, 3, 5, 5, 1, 5, 1, 0, 4] +) + +$(H6 $(IX lazy range) Laziness) + +$(P +Another benefit of functions' returning range objects is that, those objects can be used lazily. Lazy ranges produce their elements one at a time and only when needed. This may be essential for execution speed and memory consumption. Indeed, the fact that infinite ranges can even exist is made possible by ranges being lazy. +) + +$(P +Lazy ranges produce their elements one at a time and only when needed. We see an example of this with the $(C FibonacciSeries) range: The elements are calculated by $(C popFront()) only as they are needed. If $(C FibonacciSeries) were an eager range and tried to produce all of the elements up front, it could never end or find room for the elements that it produced. +) + +$(P +Another problem of eager ranges is the fact that they would have to spend time and space for elements that would perhaps never going to be used. +) + +$(P +Like most of the algorithms in Phobos, $(C take()) and $(C filter()) benefit from laziness. For example, we can pass $(C FibonacciSeries) to $(C take()) and have it generate a finite number of elements: +) + +--- + print(FibonacciSeries().take(10)); +--- + +$(P +Although $(C FibonacciSeries) is infinite, the output contains only the first 10 numbers: +) + +$(SHELL + 0 1 1 2 3 5 8 13 21 34 +) + +$(H5 $(IX ForwardRange) $(C ForwardRange)) + +$(P +$(C InputRange) models a range where elements are taken out of the range as they are iterated over. +) + +$(P +Some ranges are capable of saving their states, as well as operating as an $(C InputRange). For example, $(C FibonacciSeries) objects can save their states because these objects can freely be copied and the two copies continue their lives independently from each other. +) + +$(P +$(IX save) $(C ForwardRange) provides the $(C save) member function, which is expected to return a copy of the range. The copy that $(C save) returns must operate independently from the range object that it was copied from: iterating over one copy must not affect the other copy. +) + +$(P +Importing $(C std.array) automatically makes slices become $(C ForwardRange) ranges. +) + +$(P +In order to implement $(C save) for $(C FibonacciSeries), we can simply return a copy of the object: +) + +--- +$(CODE_NAME FibonacciSeries)struct FibonacciSeries { +// ... + + FibonacciSeries save() const { + return this; + } +$(CODE_XREF FibonacciSeries_InputRange)} +--- + +$(P +The returned copy is a separate range that would continue from the point where it was copied from. +) + +$(P +$(IX popFrontN, std.range) We can demonstrate that the copied object is independent from the actual range with the following program. The algorithm $(C std.range.popFrontN()) in the following code removes a specified number of elements from the specified range: +) + +--- +$(CODE_XREF FibonacciSeries)import std.range; + +// ... + +void report(T)(const dchar[] title, const ref T range) { + writefln("%40s: %s", title, range.take(5)); +} + +void main() { + auto range = FibonacciSeries(); + report("Original range", range); + + range.popFrontN(2); + report("After removing two elements", range); + + auto theCopy = $(HILITE range.save); + report("The copy", theCopy); + + range.popFrontN(3); + report("After removing three more elements", range); + report("The copy", theCopy); +} +--- + +$(P +The output of the program shows that removing elements from the range does not affect its saved copy: +) + +$(SHELL + Original range: [0, 1, 1, 2, 3] + After removing two elements: [1, 2, 3, 5, 8] + $(HILITE The copy: [1, 2, 3, 5, 8]) + After removing three more elements: [5, 8, 13, 21, 34] + $(HILITE The copy: [1, 2, 3, 5, 8]) +) + +$(P +Also note that the range is passed directly to $(C writefln) in $(C report()). Like our $(C print()) function, the output functions of the $(C stdio) module can take $(C InputRange) objects. I will use $(C stdio)'s output functions from now on. +) + +$(P +$(IX cycle, std.range) An algorithm that works with $(C ForwardRange) is $(C std.range.cycle). $(C cycle()) iterates over the elements of a range repeatedly from the beginning to the end. In order to be able to start over from the beginning it must be able to save a copy of the initial state of the range, so it requires a $(C ForwardRange). +) + +$(P +Since $(C FibonacciSeries) is now a $(C ForwardRange), we can try $(C cycle()) with a $(C FibonacciSeries) object; but in order to avoid having $(C cycle()) iterate over an infinite range, and as a result never find the end of it, we must first make a finite range by passing $(C FibonacciSeries) through $(C take()): +) + +--- + writeln(FibonacciSeries().take(5).cycle.take(20)); +--- + +$(P +In order to make the resultant range finite as well, the range that is returned by $(C cycle) is also passed through $(C take()). The output consists of $(I the first twenty elements of cycling through the first five elements of $(C FibonacciSeries)): +) + +$(SHELL +[0, 1, 1, 2, 3, 0, 1, 1, 2, 3, 0, 1, 1, 2, 3, 0, 1, 1, 2, 3] +) + +$(P +We could have defined intermediate variables as well. The following is an equivalent of the single-line code above: +) + +--- + auto series = FibonacciSeries(); + auto firstPart = series.take(5); + auto cycledThrough = firstPart.cycle; + auto firstPartOfCycledThrough = cycledThrough.take(20); + + writeln(firstPartOfCycledThrough); +--- + +$(P +I would like to point out the importance of laziness one more time: The first four lines above merely construct range objects that will eventually produce the elements. The numbers that are part of the result are calculated by $(C FibonacciSeries.popFront()) as needed. +) + +$(P +$(I $(B Note:) Although we have started with $(C FibonacciSeries) as a $(C ForwardRange), we have actually passed the result of $(C FibonacciSeries().take(5)) to $(C cycle()). $(C take()) is adaptive: the range that it returns is a $(C ForwardRange) if its parameter is a $(C ForwardRange). We will see how this is accomplished with $(C isForwardRange) in the next chapter.) +) + +$(H5 $(IX BidirectionalRange) $(C BidirectionalRange)) + +$(P +$(IX back) $(IX popBack) $(C BidirectionalRange) provides two member functions over the member functions of $(C ForwardRange). $(C back) is similar to $(C front): it provides access to the last element of the range. $(C popBack()) is similar to $(C popFront()): it removes the last element from the range. +) + +$(P +Importing $(C std.array) automatically makes slices become $(C BidirectionalRange) ranges. +) + +$(P +$(IX retro, std.range) A good $(C BidirectionalRange) example is the $(C std.range.retro) function. $(C retro()) takes a $(C BidirectionalRange) and ties its $(C front) to $(C back), and $(C popFront()) to $(C popBack()). As a result, the original range is iterated over in reverse order: +) + +--- + writeln([ 1, 2, 3 ].retro); +--- + +$(P +The output: +) + +$(SHELL +[3, 2, 1] +) + +$(P +Let's define a range that behaves similarly to the special range that $(C retro()) returns. Although the following range has limited functionality, it shows how powerful ranges are: +) + +--- +import std.array; +import std.stdio; + +struct Reversed { + int[] range; + + this(int[] range) { + this.range = range; + } + + bool empty() const { + return range.empty; + } + + int $(HILITE front)() const { + return range.$(HILITE back); // ← reverse + } + + int back() const { + return range.front; // ← reverse + } + + void popFront() { + range.popBack(); // ← reverse + } + + void popBack() { + range.popFront(); // ← reverse + } +} + +void main() { + writeln(Reversed([ 1, 2, 3])); +} +--- + +$(P +The output is the same as $(C retro()): +) + +$(SHELL +[3, 2, 1] +) + +$(H5 $(IX RandomAccessRange) $(C RandomAccessRange)) + +$(P +$(IX opIndex) $(C RandomAccessRange) represents ranges that allow accessing elements by the $(C []) operator. As we have seen in the $(LINK2 operator_overloading.html, Operator Overloading chapter), $(C []) operator is defined by the $(C opIndex()) member function. +) + +$(P +Importing $(C std.array) module makes slices become $(C RandomAccessRange) ranges only if possible. For example, since UTF-8 and UTF-16 encodings do not allow accessing Unicode characters by an index, $(C char) and $(C wchar) arrays cannot be used as $(C RandomAccessRange) ranges of Unicode characters. On the other hand, since the codes of the UTF-32 encoding correspond one-to-one to Unicode character codes, $(C dchar) arrays can be used as $(C RandomAccessRange) ranges of Unicode characters. +) + +$(P +$(IX constant time access) It is natural that every type would define the $(C opIndex()) member function according to its functionality. However, computer science has an expectation on its algorithmic complexity: random access must take $(I constant time). Constant time access means that the time spent when accessing an element is independent of the number of elements in the container. Therefore, no matter how large the range is, element access should not depend on the length of the range. +) + +$(P +In order to be considered a $(C RandomAccessRange), $(I one) of the following conditions must also be satisfied: +) + +$(UL +$(LI to be an infinite $(C ForwardRange)) +) + +$(P +or +) + +$(UL +$(LI $(IX length, BidirectionalRange) to be a $(C BidirectionalRange) that also provides the $(C length) property) +) + +$(P +Depending on the condition that is satisfied, the range is either infinite or finite. +) + +$(H6 Infinite $(C RandomAccessRange)) + +$(P +The following are all of the requirements of a $(C RandomAccessRange) that is based on an $(I infinite $(C ForwardRange)): +) + +$(UL +$(LI $(C empty), $(C front) and $(C popFront()) that $(C InputRange) requires) +$(LI $(C save) that $(C ForwardRange) requires) +$(LI $(C opIndex()) that $(C RandomAccessRange) requires) +$(LI the value of $(C empty) to be known at compile time as $(C false)) +) + +$(P +We were able to define $(C FibonacciSeries) as a $(C ForwardRange). However, $(C opIndex()) cannot be implemented to operate at constant time for $(C FibonacciSeries) because accessing an element requires accessing all of the previous elements first. +) + +$(P +As an example where $(C opIndex()) can operate at constant time, let's define an infinite range that consists of squares of integers. Although the following range is infinite, accessing any one of its elements can happen at constant time: +) + +--- +class SquaresRange { + int first; + + this(int first = 0) { + this.first = first; + } + + enum empty = false; + + int front() const { + return opIndex(0); + } + + void popFront() { + ++first; + } + + SquaresRange save() const { + return new SquaresRange(first); + } + + int opIndex(size_t index) const { + /* This function operates at constant time */ + immutable integerValue = first + cast(int)index; + return integerValue * integerValue; + } +} +--- + +$(P +$(I $(B Note:) It would make more sense to define $(C SquaresRange) as a $(C struct).) +) + +$(P +Although no space has been allocated for the elements of this range, the elements can be accessed by the $(C []) operator: +) + +--- + auto squares = new SquaresRange(); + + writeln(squares$(HILITE [5])); + writeln(squares$(HILITE [10])); +--- + +$(P +The output contains the elements at indexes 5 and 10: +) + +$(SHELL +25 +100 +) + +$(P +The element with index 0 should always represent the first element of the range. We can take advantage of $(C popFrontN()) when testing whether this really is the case: +) + +--- + squares.popFrontN(5); + writeln(squares$(HILITE [0])); +--- + +$(P +The first 5 elements of the range are 0, 1, 4, 9 and 16; the squares of 0, 1, 2, 3 and 4. After removing those, the square of the next value becomes the first element of the range: +) + +$(SHELL +25 +) + +$(P +Being a $(C RandomAccessRange) (the most functional range), $(C SquaresRange) can also be used as other types of ranges. For example, as an $(C InputRange) when passing to $(C filter()): +) + +--- + bool are_lastTwoDigitsSame(int value) { + /* Must have at least two digits */ + if (value < 10) { + return false; + } + + /* Last two digits must be divisible by 11 */ + immutable lastTwoDigits = value % 100; + return (lastTwoDigits % 11) == 0; + } + + writeln(squares.take(50).filter!are_lastTwoDigitsSame); +--- + +$(P +The output consists of elements among the first 50, where last two digits are the same: +) + +$(SHELL +[100, 144, 400, 900, 1444, 1600] +) + +$(H6 Finite $(C RandomAccessRange)) + +$(P +The following are all of the requirements of a $(C RandomAccessRange) that is based on a $(I finite $(C BidirectionalRange)): +) + +$(UL +$(LI $(C empty), $(C front) and $(C popFront()) that $(C InputRange) requires) +$(LI $(C save) that $(C ForwardRange) requires) +$(LI $(C back) and $(C popBack()) that $(C BidirectionalRange) requires) +$(LI $(C opIndex()) that $(C RandomAccessRange) requires) +$(LI $(C length), which provides the length of the range) +) + +$(P +$(IX chain, std.range) As an example of a finite $(C RandomAccessRange), let's define a range that works similarly to $(C std.range.chain). $(C chain()) presents the elements of a number of separate ranges as if they are elements of a single larger range. Although $(C chain()) works with any type of element and any type of range, to keep the example short, let's implement a range that works only with $(C int) slices. +) + +$(P +Let's name this range $(C Together) and expect the following behavior from it: +) + +--- + auto range = Together([ 1, 2, 3 ], [ 101, 102, 103]); + writeln(range[4]); +--- + +$(P +When constructed with the two separate arrays above, $(C range) should present all of those elements as a single range. For example, although neither array has an element at index 4, the element 102 should be the element that corresponds to index 4 of the collective range: +) + +$(SHELL +102 +) + +$(P +As expected, printing the entire range should contain all of the elements: +) + +--- + writeln(range); +--- + +$(P +The output: +) + +$(SHELL +[1, 2, 3, 101, 102, 103] +) + +$(P +$(C Together) will operate lazily: the elements will not be copied to a new larger array; they will be accessed from the original slices. +) + +$(P +We can take advantage of $(I variadic functions), which were introduced in the $(LINK2 parameter_flexibility.html, Variable Number of Parameters chapter), to initialize the range by any number of original slices: +) + +--- +struct Together { + const(int)[][] slices; + + this(const(int)[][] slices$(HILITE ...)) { + this.slices = slices.dup; + + clearFront(); + clearBack(); + } + +// ... +} +--- + +$(P +Note that the element type is $(C const(int)), indicating that this $(C struct) will not modify the elements of the ranges. However, the slices will necessarily be modified by $(C popFront()) to implement iteration. +) + +$(P +The $(C clearFront()) and $(C clearBack()) calls that the constructor makes are to remove empty slices from the beginning and the end of the original slices. Such empty slices do not change the behavior of $(C Together) and removing them up front will simplify the implementation: +) + +--- +struct Together { +// ... + + private void clearFront() { + while (!slices.empty && slices.front.empty) { + slices.popFront(); + } + } + + private void clearBack() { + while (!slices.empty && slices.back.empty) { + slices.popBack(); + } + } +} +--- + +$(P +We will call those functions later from $(C popFront()) and $(C popBack()) as well. +) + +$(P +Since $(C clearFront()) and $(C clearBack()) remove all of the empty slices from the beginning and the end, still having a slice would mean that the collective range is not yet empty. In other words, the range should be considered empty only if there is no slice left: +) + +--- +struct Together { +// ... + + bool empty() const { + return slices.empty; + } +} +--- + +$(P +The first element of the first slice is the first element of this $(C Together) range: +) + +--- +struct Together { +// ... + + int front() const { + return slices.front.front; + } +} +--- + +$(P +Removing the first element of the first slice removes the first element of this range as well. Since this operation may leave the first slice empty, we must call $(C clearFront()) to remove that empty slice and the ones that are after that one: +) + +--- +struct Together { +// ... + + void popFront() { + slices.front.popFront(); + clearFront(); + } +} +--- + +$(P +A copy of this range can be constructed from a copy of the $(C slices) member: +) + +--- +struct Together { +// ... + + Together save() const { + return Together(slices.dup); + } +} +--- + +$(P +$(I Please note that $(C .dup) copies only $(C slices) in this case, not the slice elements that it contains.) +) + +$(P +The operations at the end of the range are similar to the ones at the beginning: +) + +--- +struct Together { +// ... + + int back() const { + return slices.back.back; + } + + void popBack() { + slices.back.popBack(); + clearBack(); + } +} +--- + +$(P +The length of the range can be calculated as the sum of the lengths of the slices: +) + +--- +struct Together { +// ... + + size_t length() const { + size_t totalLength = 0; + + foreach (slice; slices) { + totalLength += slice.length; + } + + return totalLength; + } +} +--- + +$(P +$(IX fold, std.algorithm) Alternatively, the length may be calculated with less code by taking advantage of $(C std.algorithm.fold). $(C fold()) takes an operation as its template parameter and applies that operation to all elements of a range: +) + +--- +import std.algorithm; + +// ... + + size_t length() const { + return slices.fold!((a, b) => a + b.length)(size_t.init); + } +--- + +$(P +The $(C a) in the template parameter represents the current result ($(I the sum) in this case) and $(C b) represents the current element. The first function parameter is the range that contains the elements and the second function parameter is the initial value of the result ($(C size_t.init) is 0). (Note how $(C slices) is written before $(C fold) by taking advantage of $(LINK2 ufcs.html, UFCS).) +) + +$(P +$(I $(B Note:) Further, instead of calculating the length every time when $(C length) is called, it may be measurably faster to maintain a member variable perhaps named $(C length_), which always equals the correct length of the collective range. That member may be calculated once in the constructor and adjusted accordingly as elements are removed by $(C popFront()) and $(C popBack()).) +) + +$(P +One way of returning the element that corresponds to a specific index is to look at every slice to determine whether the element would be among the elements of that slice: +) + +--- +struct Together { +// ... + + int opIndex(size_t index) const { + /* Save the index for the error message */ + immutable originalIndex = index; + + foreach (slice; slices) { + if (slice.length > index) { + return slice[index]; + + } else { + index -= slice.length; + } + } + + throw new Exception( + format("Invalid index: %s (length: %s)", + originalIndex, this.length)); + } +} +--- + +$(P +$(I $(B Note:) This $(C opIndex()) does not satisfy the constant time requirement that has been mentioned above. For this implementation to be acceptably fast, the $(C slices) member must not be too long.) +) + +$(P +This new range is now ready to be used with any number of $(C int) slices. With the help of $(C take()) and $(C array()), we can even include the range types that we have defined earlier in this chapter: +) + +--- + auto range = Together(FibonacciSeries().take(10).array, + [ 777, 888 ], + (new SquaresRange()).take(5).array); + + writeln(range.save); +--- + +$(P +The elements of the three slices are accessed as if they were elements of a single large array: +) + +$(SHELL +[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 777, 888, 0, 1, 4, 9, 16] +) + +$(P +We can pass this range to other range algorithms. For example, to $(C retro()), which requires a $(C BidirectionalRange): +) + +--- + writeln(range.save.retro); +--- + +$(P +The output: +) + +$(SHELL +[16, 9, 4, 1, 0, 888, 777, 34, 21, 13, 8, 5, 3, 2, 1, 1, 0] +) + +$(P +Of course you should use the more functional $(C std.range.chain) instead of $(C Together) in your programs. +) + +$(H5 $(IX OutputRange) $(C OutputRange)) + +$(P +All of the range types that we have seen so far are about element access. $(C OutputRange) represents streamed element output, similar to sending characters to $(C stdout). +) + +$(P +$(IX put) I have mentioned earlier that $(C OutputRange) requires support for the $(C put(range, element)) operation. $(C put()) is a function defined in the $(C std.range) module. It determines the capabilities of the range and the element at compile time and uses the most appropriate method to $(I output) the element. +) + +$(P +$(C put()) considers the following cases in the order that they are listed below, and applies the method for the first matching case. $(C R) represents the type of the range; $(C range), a range object; $(C E), the type of the element; and $(C e) an element of the range: +) + +$(TABLE full, +$(HEAD2 Case Considered, Method Applied) +$(ROW2 +$(C R) has a member function named $(C put)$(BR) +and $(C put) can take an $(C E) as argument, + +$(C range.put(e);) + +) +$(ROW2 +$(C R) has a member function named $(C put)$(BR) +and $(C put) can take an $(C E[]) as argument, + +$(C range.put([ e ]);) + +) +$(ROW2 +$(C R) is an $(C InputRange)$(BR) +and $(C e) can be assigned to $(C range.front), + +$(C range.front = e;) +$(BR) +$(C range.popFront();) + +) +$(ROW2 +$(C E) is an $(C InputRange)$(BR) +and can be copied to $(C R), + +$(C for (; !e.empty; e.popFront())) +$(BR) +$(C put(range, e.front);) + +) +$(ROW2 +$(C R) can take $(C E) as argument$(BR) +(e.g. $(C R) could be a delegate), + +$(C range(e);) + +) +$(ROW2 +$(C R) can take $(C E[]) as argument$(BR) +(e.g. $(C R) could be a delegate), + +$(C range([ e ]);) + +) +) + +$(P +Let's define a range that matches the first case: The range will have a member function named $(C put()), which takes a parameter that matches the type of the output range. +) + +$(P +This output range will be used for outputting elements to multiple files, including $(C stdout). When elements are outputted with $(C put()), they will all be written to all of those files. As an additional functionality, let's add the ability to specify a delimiter to be written after each element. +) + +--- +$(CODE_NAME MultiFile)struct MultiFile { + string delimiter; + File[] files; + + this(string delimiter, string[] fileNames...) { + this.delimiter = delimiter; + + /* stdout is always included */ + this.files ~= stdout; + + /* A File object for each file name */ + foreach (fileName; fileNames) { + this.files ~= File(fileName, "w"); + } + } + + // This is the version that takes arrays (but not strings) + void put(T)(T slice) + if (isArray!T && !isSomeString!T) { + foreach (element; slice) { + // Note that this is a call to the other version + // of put() below + put(element); + } + } + + // This is the version that takes non-arrays and strings + void put(T)(T value) + if (!isArray!T || isSomeString!T) { + foreach (file; files) { + file.write(value, delimiter); + } + } +} +--- + +$(P +In order to be used as an output range of any type of elements, $(C put()) is also templatized on the element type. +) + +$(P +$(IX copy, std.algorithm) An algorithm in Phobos that uses $(C OutputRange) is $(C std.algorithm.copy). $(C copy()) is a very simple algorithm, which copies the elements of an $(C InputRange) to an $(C OutputRange). +) + +--- +import std.traits; +import std.stdio; +import std.algorithm; + +$(CODE_XREF MultiFile)// ... + +void main() { + auto output = MultiFile("\n", "output_0", "output_1"); + copy([ 1, 2, 3], output); + copy([ "red", "blue", "green" ], output); +} +--- + +$(P +That code outputs the elements of the input ranges both to $(C stdout) and to files named "output_0" and "output_1": +) + +$(SHELL +1 +2 +3 +red +blue +green +) + +$(H6 $(IX slice, as OutputRange) Using slices as $(C OutputRange)) + +$(P +The $(C std.range) module makes slices $(C OutputRange) objects as well. (By contrast, $(C std.array) makes them only input ranges.) Unfortunately, using slices as $(C OutputRange) objects has a confusing effect: slices lose an element for each $(C put()) operation on them; and that element is the element that has just been outputted! +) + +$(P +The reason for this behavior is a consequence of slices' not having a $(C put()) member function. As a result, the third case of the previous table is matched for slices and the following method is applied: +) + +--- + range.front = e; + range.popFront(); +--- + +$(P +As the code above is executed for each $(C put()), the front element of the slice is assigned to the value of the $(I outputted) element, to be subsequently removed from the slice with $(C popFront()): +) + +--- +import std.stdio; +import std.range; + +void main() { + int[] slice = [ 1, 2, 3 ]; + $(HILITE put(slice, 100)); + writeln(slice); +} +--- + +$(P +As a result, although the slice is used as an $(C OutputRange), it surprisingly $(I loses) elements: +) + +$(SHELL +[2, 3] +) + +$(P +To avoid this, a separate slice must be used as an $(C OutputRange) instead: +) + +--- +import std.stdio; +import std.range; + +void main() { + int[] slice = [ 1, 2, 3 ]; + int[] slice2 = slice; + + put($(HILITE slice2), 100); + + writeln(slice2); + writeln(slice); +} +--- + +$(P +This time the second slice is consumed and the original slice has the expected elements: +) + +$(SHELL +[2, 3] +[100, 2, 3] $(SHELL_NOTE expected result) +) + +$(P +Another important fact is that the length of the slice does not grow when used as an $(C OutputRange). It is the programmer's responsibility to ensure that there is enough room in the slice: +) + +--- + int[] slice = [ 1, 2, 3 ]; + int[] slice2 = slice; + + foreach (i; 0 .. 4) { // ← no room for 4 elements + put(slice2, i * 100); + } +--- + +$(P +When the slice becomes completely empty because of the indirect $(C popFront()) calls, the program terminates with an exception: +) + +$(SHELL +core.exception.AssertError@...: Attempting to fetch the $(HILITE front +of an empty array of int) +) + +$(P +$(IX appender, std.array) $(C std.array.Appender) and its convenience function $(C appender) allows using slices as $(I an $(C OutputRange) where the elements are appended). The $(C put()) function of the special range object that $(C appender()) returns actually appends the elements to the original slice: +) + +--- +import std.array; + +// ... + + auto a = appender([ 1, 2, 3 ]); + + foreach (i; 0 .. 4) { + a.put(i * 100); + } +--- + +$(P +In the code above, $(C appender) is called with an array and returns a special range object. That range object is in turn used as an $(C OutputRange) by calling its $(C put()) member function. The resultant elements are accessed by its $(C .data) property: +) + +--- + writeln(a.data); +--- + +$(P +The output: +) + +$(SHELL +[1, 2, 3, 0, 100, 200, 300] +) + +$(P +$(C Appender) supports the $(C ~=) operator as well: +) + +--- + a $(HILITE ~=) 1000; + writeln(a.data); +--- + +$(P +The output: +) + +$(SHELL +[1, 2, 3, 0, 100, 200, 300, 1000] +) + +$(H6 $(IX toString, OutputRange) $(C toString()) with an $(C OutputRange) parameter) + +$(P +Similar to how $(C toString) member functions can be defined as $(LINK2 lambda.html, taking a $(C delegate) parameter), it is possible to define one that takes an $(C OutputRange). Functions like $(C format), $(C writefln), and $(C writeln) operate more efficiently by placing the output characters right inside the output buffer of the output range. +) + +$(P +To be able to work with any $(C OutputRange) type, such $(C toString) definitions need to be function templates, optionally with template constraints: +) + +--- +import std.stdio; +import std.range; + +struct S { + void toString(O)(ref O o) const + if (isOutputRange!(O, char)) { + $(HILITE put)(o, "hello"); + } +} + +void main() { + auto s = S(); + writeln(s); +} +--- + +$(P +Note that the code inside $(C main()) does not define an $(C OutputRange) object. That object is defined by $(C writeln) to store the characters before printing them: +) + +$(SHELL +hello +) + +$(H5 Range templates) + +$(P +Although we have used mostly $(C int) ranges in this chapter, ranges and range algorithms are much more useful when defined as templates. +) + +$(P +The $(C std.range) module includes many range templates. We will see these templates in the next chapter. +) + +$(H5 Summary) + +$(UL + +$(LI Ranges abstract data structures from algorithms and allow them to be used with algorithms seamlessly.) + +$(LI Ranges are a D concept and are the basis for many features of Phobos.) + +$(LI Many Phobos algorithms return lazy range objects to accomplish their special tasks.) + +$(LI UFCS works well with range algorithms.) + +$(LI When used as $(C InputRange) objects, the elements of strings are Unicode characters.) + +$(LI $(C InputRange) requires $(C empty), $(C front) and $(C popFront()).) + +$(LI $(C ForwardRange) additionally requires $(C save).) + +$(LI $(C BidirectionalRange) additionally requires $(C back) and $(C popBack()).) + +$(LI Infinite $(C RandomAccessRange) requires $(C opIndex()) over $(C ForwardRange).) + +$(LI Finite $(C RandomAccessRange) requires $(C opIndex()) and $(C length) over $(C BidirectionalRange).) + +$(LI $(C std.array.appender) returns an $(C OutputRange) that appends to slices.) + +$(LI Slices are ranges of finite $(C RandomAccessRange)) + +$(LI Fixed-length arrays are not ranges.) + +) + +macros: + TITLE=Ranges + + DESCRIPTION=Phobos ranges that abstract data structures from algorithms and that enables them to be used seamlessly. + + KEYWORDS=d programming language tutorial book range OutputRange InputRange ForwardRange BidirectionalRange RandomAccessRange + +MINI_SOZLUK= diff --git a/book/d.en/ranges_more.d b/book/d.en/ranges_more.d new file mode 100644 index 0000000000..487bc54746 --- /dev/null +++ b/book/d.en/ranges_more.d @@ -0,0 +1,428 @@ +Ddoc + +$(DERS_BOLUMU $(IX range) More Ranges) + +$(P +We used mostly $(C int) ranges in the previous chapter. In practice, containers, algorithms, and ranges are almost always implemented as templates. The $(C print()) example in that chapter was a template as well: +) + +--- +void print$(HILITE (T))(T range) { + // ... +} +--- + +$(P +What lacks from the implementation of $(C print()) is that even though it requires $(C T) to be a kind of $(C InputRange), it does not formalize that requirement with a template constraint. (We have seen template constraints in $(LINK2 templates_more.html, the More Templates chapter).) +) + +$(P +The $(C std.range) module contains templates that are useful both in template constraints and in $(C static if) statements. +) + +$(H5 Range kind templates) + +$(P +The group of templates with names starting with $(C is) determine whether a type satisfies the requirements of a certain kind of range. For example, $(C isInputRange!T) answers the question "is $(C T) an $(C InputRange)?" The following templates are for determining whether a type is of a specific general range kind: +) + +$(UL +$(LI $(IX isInputRange) $(C isInputRange)) +$(LI $(IX isForwardRange) $(C isForwardRange)) +$(LI $(IX isBidirectionalRange) $(C isBidirectionalRange)) +$(LI $(IX isRandomAccessRange) $(C isRandomAccessRange)) +$(LI $(IX isOutputRange) $(C isOutputRange)) +) + +$(P +Accordingly, the template constraint of $(C print()) can use $(C isInputRange): +) + +--- +void print(T)(T range) + if ($(HILITE isInputRange!T)) { + // ... +} +--- + +$(P +Unlike the others, $(C isOutputRange) takes two template parameters: The first one is a range type and the second one is an element type. It returns $(C true) if that range type allows outputting that element type. For example, the following constraint is for requiring that the range must be an $(C OutputRange) that accepts $(C double) elements: +) + +--- +void foo(T)(T range) + if (isOutputRange!($(HILITE T, double))) { + // ... +} +--- + +$(P +When used in conjunction with $(C static if), these constraints can determine the capabilities of user-defined ranges as well. For example, when a dependent range of a user-defined range is a $(C ForwardRange), the user-defined range can take advantage of that fact and can provide the $(C save()) function as well. +) + +$(P +Let's see this on a range that produces the negatives of the elements of an existing range (more accurately, the $(I numeric complements) of the elements). Let's start with just the $(C InputRange) functions: +) + +--- +struct Negative(T) + if (isInputRange!T) { + T range; + + bool empty() { + return range.empty; + } + + auto front() { + return $(HILITE -range.front); + } + + void popFront() { + range.popFront(); + } +} +--- + +$(P +$(I $(B Note:) As we will see below, the return type of $(C front) can be specified as $(C ElementType!T) as well.) +) + +$(P +The only functionality of this range is in the $(C front) function where it produces the negative of the front element of the original range. +) + +$(P +As usual, the following is the convenience function that goes with that range: +) + +--- +Negative!T negative(T)(T range) { + return Negative!T(range); +} +--- + +$(P +This range is ready to be used with e.g. $(C FibonacciSeries) that was defined in the previous chapter: +) + +--- +struct FibonacciSeries { + int current = 0; + int next = 1; + + enum empty = false; + + int front() const { + return current; + } + + void popFront() { + const nextNext = current + next; + current = next; + next = nextNext; + } + + FibonacciSeries save() const { + return this; + } +} + +// ... + + writeln(FibonacciSeries().take(5).$(HILITE negative)); +--- + +$(P +The output contains the negatives of the first five elements of the series: +) + +$(SHELL +[0, -1, -1, -2, -3] +) + +$(P +Naturally, being just an $(C InputRange), $(C Negative) cannot be used with algorithms like $(C cycle()) that require a $(C ForwardRange): +) + +--- + writeln(FibonacciSeries() + .take(5) + .negative + .cycle $(DERLEME_HATASI) + .take(10)); +--- + +$(P +However, when the original range is already a $(C ForwardRange), there is no reason for $(C Negative) not to provide the $(C save()) function as well. This condition can be determined by a $(C static if) statement and $(C save()) can be provided if the original range is a $(C ForwardRange). In this case it is as trivial as returning a new $(C Negative) object that is constructed by a copy of the original range: +) + +--- +struct Negative(T) + if (isInputRange!T) { +// ... + + $(HILITE static if) (isForwardRange!T) { + Negative save() { + return Negative(range.save); + } + } +} +--- + +$(P +The addition of the new $(C save()) function makes $(C Negative!FibonacciSeries) a $(C ForwardRange) as well and the $(C cycle()) call can now be compiled: +) + +--- + writeln(FibonacciSeries() + .take(5) + .negative + .cycle // ← now compiles + .take(10)); +--- + +$(P +The output of the entire expression can be described as $(I take the first five elements of the Fibonacci series, take their negatives, cycle those indefinitely, and take the first ten of those elements): +) + +$(SHELL +[0, -1, -1, -2, -3, 0, -1, -1, -2, -3] +) + +$(P +With the same approach, $(C Negative) can be made a $(C BidirectionalRange) and a $(C RandomAccessRange) if the original range supports those functionalities: +) + +--- +struct Negative(T) + if (isInputRange!T) { +// ... + + static if (isBidirectionalRange!T) { + auto back() { + return -range.back; + } + + void popBack() { + range.popBack(); + } + } + + static if (isRandomAccessRange!T) { + auto opIndex(size_t index) { + return -range[index]; + } + } +} +--- + +$(P +For example, when it is used with a slice, the negative elements can be accessed by the $(C []) operator: +) + +--- + auto d = [ 1.5, 2.75 ]; + auto n = d.negative; + writeln(n$(HILITE [1])); +--- + +$(P +The output: +) + +$(SHELL +-2.75 +) + +$(H5 $(IX ElementType) $(IX ElementEncodingType) $(C ElementType) and $(C ElementEncodingType)) + +$(P +$(C ElementType) provides the types of the elements of the range. +) + +$(P +For example, the following template constraint includes a requirement that is about the element type of the first range: +) + +--- +void foo(I1, I2, O)(I1 input1, I2 input2, O output) + if (isInputRange!I1 && + isForwardRange!I2 && + isOutputRange!(O, $(HILITE ElementType!I1))) { + // ... +} +--- + +$(P +The previous constraint can be described as $(I if $(C I1) is an $(C InputRange) and $(C I2) is a $(C ForwardRange) and $(C O) is an $(C OutputRange) that accepts the element type of $(C I1)). +) + +$(P +$(IX dchar, string range) Since strings are always ranges of Unicode characters, regardless of their actual character types, they are always ranges of $(C dchar), which means that even $(C ElementType!string) and $(C ElementType!wstring) are $(C dchar). For that reason, when needed in a template, the actual UTF encoding type of a string range can be obtained by $(C ElementEncodingType). +) + +$(H5 More range templates) + +$(P +The $(C std.range) module has many more range templates that can be used with D's other compile-time features. The following is a sampling: +) + +$(UL + +$(LI $(IX isInfinite) $(C isInfinite): Whether the range is infinite) + +$(LI $(IX hasLength) $(C hasLength): Whether the range has a $(C length) property) + +$(LI $(IX hasSlicing) $(C hasSlicing): Whether the range supports slicing i.e. with $(C a[x..y])) + +$(LI $(IX hasAssignableElements) $(C hasAssignableElements): Whether the return type of $(C front) is assignable) + +$(LI $(IX hasSwappableElements) $(C hasSwappableElements): Whether the elements of the range are swappable e.g. with $(C std.algorithm.swap)) + +$(LI $(IX hasMobileElements) $(IX move, std.algorithm) $(C hasMobileElements): Whether the elements of the range are movable e.g. with $(C std.algorithm.move) + +$(P +$(IX moveFront) $(IX moveBack) $(IX moveAt) This implies that the range has $(C moveFront()), $(C moveBack()), or $(C moveAt()), depending on the actual kind of the range. Since moving elements is usually faster than copying them, depending on the result of $(C hasMobileElements) a range can provide faster operations by calling $(C move()). +) + +) + +$(LI $(IX hasLvalueElements) $(IX lvalue) $(C hasLvalueElements): Whether the elements of the range are $(I lvalues) (roughly meaning that the elements are not copies of actual elements nor are temporary objects that are created on the fly) + +$(P +For example, $(C hasLvalueElements!FibonacciSeries) is $(C false) because the elements of $(C FibonacciSeries) do not exist as themselves; rather, they are copies of the member $(C current) that is returned by $(C front). Similarly, $(C hasLvalueElements!(Negative!(int[]))) is $(C false) because although the $(C int) slice does have actual elements, the range that is represented by $(C Negative) does not provide access to those elements; rather, it returns copies that have the negative signs of the elements of the actual slice. Conversely, $(C hasLvalueElements!(int[])) is $(C true) because a slice provides access to actual elements of an array. +) + +) + +) + +$(P +The following example takes advantage of $(C isInfinite) to provide $(C empty) as an $(C enum) when the original range is infinite, making it known at compile time that $(C Negative!T) is infinite as well: +) + +--- +struct Negative(T) + if (isInputRange!T) { +// ... + + static if (isInfinite!T) { + // Negative!T is infinite as well + enum empty = false; + + } else { + bool empty() { + return range.empty; + } + } + +// ... +} + +static assert( isInfinite!(Negative!FibonacciSeries)); +static assert(!isInfinite!(int[])); +--- + +$(H5 $(IX polymorphism, run-time) $(IX inputRangeObject) $(IX outputRangeObject) Run-time polymorphism with $(C inputRangeObject()) and $(C outputRangeObject())) + +$(P +Being implemented mostly as templates, ranges exhibit $(I compile-time polymorphism), which we have been taking advantage of in the examples of this chapter and previous chapters. ($(I For differences between compile-time polymorphism and run-time polymorphism, see the "Compile-time polymorphism" section in $(LINK2 templates_more.html, the More Templates chapter).)) +) + +$(P +Compile-time polymorphism has to deal with the fact that every instantiation of a template is a different type. For example, the return type of the $(C take()) template is directly related to the original range: +) + +--- + writeln(typeof([11, 22].negative.take(1)).stringof); + writeln(typeof(FibonacciSeries().take(1)).stringof); +--- + +$(P +The output: +) + +$(SHELL +Take!(Negative!(int[])) +Take!(FibonacciSeries) +) + +$(P +A natural consequence of this fact is that different range types cannot be assigned to each other. The following is an example of this incompatibility between two $(C InputRange) ranges: +) + +--- + auto range = [11, 22].negative; + // ... at a later point ... + range = FibonacciSeries(); $(DERLEME_HATASI) +--- + +$(P +As expected, the compilation error indicates that $(C FibonacciSeries) and $(C Negative!(int[])) are not compatible: +) + +$(SHELL +Error: cannot implicitly convert expression (FibonacciSeries(0, 1)) +of type $(HILITE FibonacciSeries) to $(HILITE Negative!(int[])) +) + +$(P +However, although the actual types of the ranges are different, since they both are $(I ranges of $(C int)), this incompatibility can be seen as an unnecessary limitation. From the usage point of view, since both ranges simply provide $(C int) elements, the actual mechanism that produces those elements should not be important. +) + +$(P +Phobos helps with this issue by $(C inputRangeObject()) and $(C outputRangeObject()). $(C inputRangeObject()) allows presenting ranges as $(I a specific kind of range of specific types of elements). With its help, a range can be used e.g. as $(I an $(C InputRange) of $(C int) elements), regardless of the actual type of the range. +) + +$(P +$(C inputRangeObject()) is flexible enough to support all of the non-output ranges: $(C InputRange), $(C ForwardRange), $(C BidirectionalRange), and $(C RandomAccessRange). Because of that flexibility, the object that it returns cannot be defined by $(C auto). The exact kind of range that is required must be specified explicitly: +) + +--- + // Meaning "InputRange of ints": + $(HILITE InputRange!int) range = [11, 22].negative.$(HILITE inputRangeObject); + + // ... at a later point ... + + // The following assignment now compiles + range = FibonacciSeries().$(HILITE inputRangeObject); +--- + +$(P +As another example, when the range needs to be used as $(I a $(C ForwardRange) of $(C int) elements), its type must be specified explicitly as $(C ForwardRange!int): +) + +--- + $(HILITE ForwardRange!int) range = [11, 22].negative.inputRangeObject; + + auto copy = range.$(HILITE save); + + range = FibonacciSeries().inputRangeObject; + writeln(range.$(HILITE save).take(10)); +--- + +$(P +The example calls $(C save()) just to prove that the ranges can indeed be used as $(C ForwardRange) ranges. +) + +$(P +Similarly, $(C outputRangeObject()) works with $(C OutputRange) ranges and allows their use as $(I an $(C OutputRange) that accepts specific types of elements). +) + +$(H5 Summary) + +$(UL + +$(LI The $(C std.range) module contains many useful range templates.) + +$(LI Some of those templates allow templates be more capable depending on the capabilities of original ranges.) + +$(LI $(C inputRangeObject()) and $(C outputRangeObject()) provide run-time polymorphism, allowing using different types of ranges as $(I specific kinds of ranges of specific types of elements).) +) + +macros: + TITLE=More Ranges + + DESCRIPTION=Many useful range templates of the std.range module. + + KEYWORDS=d programming language tutorial book ranges diff --git a/book/d.en/rss.xml b/book/d.en/rss.xml new file mode 100644 index 0000000000..156cb51e2d --- /dev/null +++ b/book/d.en/rss.xml @@ -0,0 +1,812 @@ + + + + + Programming in D + http://ddili.org/ + Programming with the D programming language + en + D Programming Language Book + + + 'deprecated', 'extern', and 'extern()' + http://ddili.org/modules.html + Added 'deprecated' that helps with deprecation process of library features, 'extern' that is for declaring external symbols, and 'extern()' that allows interacting with libraries of other languages (extern(C), extern(C++, std), etc.). + Chapter + 24 Oct 2015 22:00 + + + + Code Samples .zip File + http://ddili.org/index.html + You can download most of the code samples that appear in the book as a .zip file. + Code + 16 Oct 2015 20:00 + + + + Book Index + http://ddili.org/ix.html + The index section of the book. + Chapter + 21 Aug 2015 02:00 + + + + Fibers + http://ddili.org/fibers.html + Cooperative multitasking in D with fibers. + Chapter + 17 Aug 2015 15:00 + + + + Pragmas + http://ddili.org/pragma.html + Pragmas that allow interactions with the compiler, including the most recent pragma(inline). + Chapter + 17 Aug 2015 15:00 + + + + Operator Precedence + http://ddili.org/operator_precedence.html + The rules that specify the execution order of chained operators and the expressions that they use. + Chapter + 17 Aug 2015 15:00 + + + + Foreword by Andrei Alexandrescu + http://ddili.org/foreword2.html + "Instead of falling for getting things done quickly, 'Programming in D' focuses on getting things done properly, to the lasting benefit of its reader." + Chapter + 17 Aug 2015 15:00 + + + + Ebook versions + http://ddili.org/index.html + In addition to the PDF version, now there are EPUB and AZW3 versions as well. + Ebook + 15 Dec 2014 02:00 + + + + '.offsetof' property and 'align' attribute + http://ddili.org/memory.html + The .offsetof property to get the offsets of and the align attribute to specify the alignments of struct members. + Chapter + 25 Nov 2014 17:00 + + + + Contract inheritance + http://ddili.org/invariant.html + Inheriting 'in' and 'out' blocks of interface and class functions. + Chapter + 25 Nov 2014 17:00 + + + + The special keywords + http://ddili.org/templates_more.html + __MODULE__, __FILE__, __LINE__, __FUNCTION__, and __PRETTY_FUNCTION__ + Chapter + 25 Nov 2014 17:00 + + + + pragma + http://ddili.org/templates.html + The pragma directive + Chapter + 25 Nov 2014 17:00 + + + + Nested Functions, Structs, and Classes + http://ddili.org/nested.html + Defining functions, structs, and classes inside existing scopes. + Chapter + 25 Nov 2014 17:00 + + + + Lvalues and Rvalues + http://ddili.org/lvalue_rvalue.html + Lvalues, rvalues, their differences, and 'auto ref' parameter type that can accept either kind. + Chapter + 25 Nov 2014 17:00 + + + + The 'Index' section + http://ddili.org/pdf_indir.html + Automatically generated index section for the PDF version of the book. + Chapter + 25 Nov 2014 17:00 + + + + The 'Table of Contents' section + http://ddili.org/pdf_indir.html + Automatically generated TOC section for the PDF version of the book. + Chapter + 28 Sep 2014 23:00 + + + + The attributes of Throwable + http://ddili.org/exceptions.html + The attributes of the Throwable interface, collateral exceptions, and an example of accessing collateral exceptions through the .next property. + Chapter + 18 Sep 2014 16:00 + + + + Selective, local, renamed, and package imports + http://ddili.org/modules.html + Importing modules selectively, locally, under a different name, and as a package. + Chapter + 17 Sep 2014 00:30 + + + + @disable + http://ddili.org/special_functions.html + The @disable attribute to disable special functions of structs. + Chapter + 12 Sep 2014 00:15 + + + + Operator overloading for multi-dimensional indexing and slicing + http://ddili.org/templates_more.html + The templated versions of opDollar, opIndex, and opSlice, and examples of using them to support multiple indexes inside square brackets. + Chapter + 11 Sep 2014 00:15 + + + + static this, static ~this, shared static this, and shared static ~this + http://ddili.org/index.html + Specifying the initial and final operations of threads and programs. + Chapter + 26 Aug 2014 23:30 + + + + User Defined Attributes (UDA) + http://ddili.org/uda.html + Assigning user defined attributes to type and variable declarations, testing the attributes at compile time, and compiling the program according to those attributes. + Chapter + 26 Aug 2014 22:30 + + + + Memory Management + http://ddili.org/memory.html + The garbage collector, allocating memory, and placing objects at specific locations in memory. + Chapter + 24 Jul 2014 01:00 + + + + Type traits + http://ddili.org/cond_comp.html + Using type traits in conditional compilation. + Chapter + 29 May 2014 20:30 + + + + Data Sharing Concurrency + http://ddili.org/concurrency_shared.html + Multi-threaded programming in D by data sharing. + Chapter + 20 May 2014 12:00 + + + + More Ranges + http://ddili.org/ranges_more.html + Useful range templates of the std.range module. Providing range capabilities depending on the capabilities on dependent ranges. + Chapter + 01 November 2013 17:00 + + + + Mixins + http://ddili.org/mixin.html + Template and string mixins that allow inserting compile-time generated code into the source code. + Chapter + 01 November 2013 17:00 + + + + More Functions + http://ddili.org/functions_more.html + More features of D functions: auto, ref, auto ref, and inout return attributes; pure and nothrow behavioral attributes; and @safe, @trusted, and @system memory safety attributes. + Chapter + 01 November 2013 17:00 + + + + More Templates + http://ddili.org/templates_more.html + More information about templates: Templates can define any kind of code; template parameters can be of type, value, alias, this, and tuple; template constraints enable template definitions only for template arguments that satisfy that template's requirements. + Chapter + 19 September 2013 00:30 + + + + Tuples + http://ddili.org/tuples.html + Tuples, which combine values of different types and make them available similar to struct objects, and TypeTuple, which represents the concept of 'list of values' as seen in parameter lists, template argument lists, and array literal initialization lists. + Chapter + 19 September 2013 00:30 + + + + Ranges + http://ddili.org/ranges.html + The code examples in the Ranges chapter are made const-correct and they take advantage of UFCS. + Chapter + 09 July 2013 19:30 + + + + Labels and goto + http://ddili.org/goto.html + Labels that give names to code lines and the goto statement that make program execution go to a label. + Chapter + 28 June 2013 19:00 + + + + Unions + http://ddili.org/union.html + Sharing the same memory area for multiple members. + Chapter + 26 June 2013 10:00 + + + + foreach with Structs and Classes + http://ddili.org/foreach_opapply.html + Providing foreach support for structs and classes. + Chapter + 14 June 2013 18:30 + + + + Function Pointers, Delegates, and Lambdas + http://ddili.org/lambda.html + Function pointers and delegates allow storing how the program should behave at a later time. Lambdas (anonymous function or function literals) make code more readable and reduce boilerplate code. + Chapter + 9 June 2013 18:00 + + + + is Expression + http://ddili.org/is_expr.html + is expression, one of the most powerful compile-time features of the D programming language. + Chapter + 3 June 2013 22:00 + + + + Conditional Compilation + http://ddili.org/cond_comp.html + Compiling parts of programs in special ways depending on conditions that are checked at compile time. + Chapter + 3 June 2013 21:30 + + + + Bit Operations + http://ddili.org/bit_operations.html + The D features that enable manipulating data bit-by-bit. + Chapter + 21 May 2013 23:30 + + + + Pointers + http://ddili.org/pointers.html + Pointers are variables that provide access to other variables. They are low-level capabilities of the microprocessor. + Chapter + 31 Jan 2013 20:30 + + + + alias this + http://ddili.org/alias_this.html + 'alias this' enables automatic type conversions of user-defined types. + Chapter + 31 Jan 2013 20:30 + + + + alias + http://ddili.org/alias.html + 'alias' assigns aliases to existing names + Chapter + 31 Jan 2013 20:30 + + + + Contract Programming for Structs and Classes + http://ddili.org/invariant.html + The 'invariant' keyword and the use of the 'in' and 'out' blocks with structs and classes. + Chapter + 31 Jan 2013 20:30 + + + + Properties + http://ddili.org/property.html + Properties allow using member functions like member variables. + Chapter + 31 Jan 2013 20:30 + + + + Universal Function Call Syntax (UFCS) + http://ddili.org/ufcs.html + UFCS enables the member function syntax even for regular functions. + Chapter + 31 Jan 2013 20:30 + + + + Encapsulation and Protection Attributes + http://ddili.org/encapsulation.html + Preserving class invariants by limiting access to class members. + Chapter + 2 Nov 2012 21:00 + + + + Modules and Libraries + http://ddili.org/modules.html + Organizing D programs and libraries as modules and packages. + Chapter + 2 Nov 2012 21:00 + + + + destroy and scoped + http://ddili.org/destroy.html + 'destroy()' to call destructors explicitly and 'scoped()' to destroy objects automatically. + Chapter + 2 Nov 2012 21:00 + + + + Interfaces + http://ddili.org/interface.html + The 'interface' keyword to define class interfaces. + Chapter + 2 Nov 2012 21:00 + + + + Object + http://ddili.org/object.html + The Object class that is at the top of class hierarchies and its member functions toString(), opEquals(), opCmp(), and toHash(). + Chapter + 2 Nov 2012 21:00 + + + + Inheritance + http://ddili.org/inheritance.html + Inheriting the members of existing classes. + Chapter + 2 Nov 2012 21:00 + + + + Classes + http://ddili.org/class.html + The 'class' feature of the D programming language, which supports the object oriented programming (OOP) paradigm. + Chapter + 2 Nov 2012 21:00 + + + + Operator Overloading + http://ddili.org/operator_overloading.html + Defining the behaviors of operators for structs to allow their uses as convenient as the fundamental types. + Chapter + 15 Sep 2012 23:30 + + + + Constructor and Other Special Functions + http://ddili.org/special_functions.html + The four special functions of structs: constructor, destructor, postblit, and assignment. + Chapter + 15 Sep 2012 23:30 + + + + Message Passing Concurrency + http://ddili.org/concurrency.html + Receiving LinkTerminated and OwnerTerminated exceptions as messages. + Chapter + 09 Aug 2012 23:45 + + + + Parallelism + http://ddili.org/parallelism.html + Explain the parameters of the functions of the std.parallelism module: Work unit size and buffer size. + Chapter + 09 Aug 2012 23:30 + + + + Immutability + http://ddili.org/const_and_immutable.html + The consequences of marking function parameters const or immutable. + Chapter + 09 Aug 2012 22:00 + + + + const ref Parameters and const Member Functions + http://ddili.org/const_member_functions.html + Marking parameters as 'const ref' and member functions as 'const' in order to be able to use them with immutable variables as well. + Chapter + Sun, 10 Jun 2012 17:40 + + + + Member Functions + http://ddili.org/member_functions.html + Defining functions that are closely related to a struct inside the curly brackets of that struct definition. + Chapter + Sun, 10 Jun 2012 16:15 + + + + Function Overloading + http://ddili.org/function_overloading.html + The function overloading feature that enables defining multiple functions having the same name. + Chapter + Sun, 10 Jun 2012 14:50 + + + + Variable Number of Parameters + http://ddili.org/parameter_flexibility.html + Default parameter values and variadic functions. + Chapter + Sun, 10 Jun 2012 13:20 + + + + Structs + http://ddili.org/struct.html + The 'struct' feature for defining higher-level concepts as user-defined types. + Chapter + Sun, 10 Jun 2012 12:20 + + + + Type Conversions + http://ddili.org/cast.html + Automatic and explicit type conversions of D: integer promotions, arithmetic conversions, the to() and assumeUnique() functions, and the cast operator. + Chapter + Sun, 10 Jun 2012 00:05 + + + + The null Value and the is Operator + http://ddili.org/null_is.html + The null value and the is and !is operators. + Chapter + Sat, 09 Jun 2012 18:30 + + + + Value Types and Reference Types + http://ddili.org/value_vs_reference.html + Introducing value types, reference variables, and reference types; and their differences. + Chapter + Sat, 09 Jun 2012 17:45 + + + + Lifetimes and Fundamental Operations + http://ddili.org/lifetimes.html + Object lifetimes: Initialization and finalization of variables. + Chapter + Sat, 09 Jun 2012 15:15 + + + + Contract Programming + http://ddili.org/contracts.html + Contract programming in D: the 'in' and 'out' blocks of functions. + Chapter + Tue, 27 Apr 2012 23:15 + + + + Unit Testing + http://ddili.org/unit_testing.html + Unit tests for reducing the risk of bugs and test driven development (TDD). + Chapter + Tue, 24 Apr 2012 22:15 + + + + Installing dmd and compiling programs + http://ddili.org/hello_world.html + Added how to install dmd and how to compile programs on the command line. + Chapter + Sat, 21 Apr 2012 22:15 + + + + Message Passing Concurrency + http://ddili.org/concurrency.html + Multi-threaded programming in D by message passing, provided by the std.concurrency module. + Chapter + 15 Apr 2012 23:15 + + + + assert and enforce + http://ddili.org/assert.html + The assert checks and the enforce() function that help with program correctness. + Chapter + 12 April 2012 23:30 + + + + scope + http://ddili.org/scope.html + The scope(success), scope(failure), and scope(exit) statements of D, which in many cases obviate the need for try-catch-finally blocks and RAII classes. + Chapter + 28 Mar 2012 23:20 + + + + Program Environment + http://ddili.org/main.html + The environment that starts a D program and the ways the program can interact with its environment: return value, parameters, environment variables. + Chapter + 28 Mar 2012 23:10 + + + + Lazy Operators + http://ddili.org/lazy_operators.html + The shortcut evaluations of three operators: logical or, logical and, and the ternary operator. + Chapter + 28 Mar 2012 01:00 + + + + Function Parameters + http://ddili.org/function_parameters.html + Different kinds of function parameters and how they affect the functions and the arguments. + Chapter + 28 Mar 2012 01:00 + + + + Immutability + http://ddili.org/const_and_immutable.html + The concept of immutability in the D programming language, the const and immutable keywords, and recommendations on how to take advantage of immutability when defining variables and function parameters. + Chapter + 22 Mar 2012 22:50 + + + + Functions + http://ddili.org/functions.html + The functions that define the building blocks of program behavior. + Chapter + 14 Mar 2012 00:30 + + + + enum + http://ddili.org/enum.html + The enum feature that enables defining named constant values. + Chapter + 13 Mar 2012 18:30 + + + + switch and case + http://ddili.org/switch_case.html + The switch and final switch statements, their case sections, and the use of the goto statement under the case sections. + Chapter + 27 Feb 2012 18:10 + + + + The foreach Loop + http://ddili.org/foreach.html + The foreach loop, one of the most common statements of D. Its use with arrays, strings, and associative arrays. + Chapter + 27 Feb 2012 18:00 + + + + Associative Arrays + http://ddili.org/aa.html + Associative arrays, the hash table implementation of the D programming language. + Chapter + 26 Feb 2012 22:40 + + + + Parallelism + http://ddili.org/parallelism.html + The std.parallelism module to make programs run faster by taking advantage of multiple cores of the system. + Chapter + 19 Feb 2012 23:10 + + + + The do-while Loop + http://ddili.org/do_while.html + The do-while loop and its comparison to the while loop. + Chapter + 11 Feb 2012 20:10 + + + + Formatted Input + http://ddili.org/formatted_input.html + Reading data that match specific formats. + Chapter + 11 Feb 2012 20:00 + + + + Formatted Output + http://ddili.org/formatted_output.html + Determining the format of printed values. + Chapter + 31 Jan 2012 00:00 + + + + Literals + http://ddili.org/literals.html + The syntax of literals of different D types. + Chapter + 31 Jan 2012 00:00 + + + + The Ternary Operator ?: + http://ddili.org/ternary.html + The ternary operator and comparing it to the if-else statement. + Chapter + 31 Jan 2012 00:00 + + + + The for Loop + http://ddili.org/for.html + The for loop and its comparison to the while loop. + Chapter + 31 Jan 2012 00:00 + + + + PDF version of the book + http://ddili.org/index.html + The PDF version of the book is now available through a link in chapter headers + News + 21 Jan 2012 18:00 + + + + Name Space + http://ddili.org/name_space.html + The lifetime and accessibility of names of variables and other program constructs + Chapter + 21 Jan 2012 18:00 + + + + auto and typeof + http://ddili.org/auto_and_typeof.html + The 'auto' keyword and its use during type inference, and the typeof keyword to get the type of expressions + Chapter + 21 Jan 2012 18:00 + + + + Files + http://ddili.org/files.html + Reading from and writing to files using the std.stdio.File struct + Chapter + 21 Jan 2012 18:00 + + + + Redirecting Standard Input and Output Streams + http://ddili.org/stream_redirect.html + How to redirect standard input and output streams of program to files and other programs + Chapter + 21 Jan 2012 18:00 + + + + Templates + http://ddili.org/templates.html + The 'Templates' chapter + Chapter + 12 Jan 2012 00:40 + + + + Strings + http://ddili.org/strings.html + The 'Strings' chapter + Chapter + 03 Jan 2012 18:00 + + + + Slices and Other Array Features + http://ddili.org/slices.html + The 'Slices and Other Array Features' chapter + Chapter + 31 Dec 2011 19:15 + + + + Characters + http://ddili.org/characters.html + The 'Characters' chapter + Chapter + 18 Dec 2011 19:15 + + + + Arrays + http://ddili.org/arrays.html + The 'Arrays' chapter has been proofread. + Proofreading + 18 Dec 2011 19:00 + + + + Arrays + http://ddili.org/arrays.html + The 'Arrays' chapter + Chapter + 11 Dec 2011 14:00 + + + + Floating Point Types + http://ddili.org/floating_point.html + The 'Floating Point Types' chapter + Chapter + 09 Dec 2011 22:10 + + + + Index + http://ddili.org/index.html + The index of the book + Book + 13 Nov 2011 23:00 + + + + diff --git a/book/d.en/scope.d b/book/d.en/scope.d new file mode 100644 index 0000000000..245139a72b --- /dev/null +++ b/book/d.en/scope.d @@ -0,0 +1,142 @@ +Ddoc + +$(DERS_BOLUMU $(IX scope(success)) $(IX scope(exit)) $(IX scope(failure)) $(CH4 scope)) + +$(P +As we have seen in the previous chapter, expressions that must always be executed are written in the $(C finally) block, and expressions that must be executed when there are error conditions are written in $(C catch) blocks. +) + +$(P +We can make the following observations about the use of these blocks: +) + +$(UL + +$(LI $(C catch) and $(C finally) cannot be used without a $(C try) block.) + +$(LI Some of the variables that these blocks need may not be accessible within these blocks: + +--- +void foo(ref int r) { + try { + $(HILITE int addend) = 42; + + r += addend; + mayThrow(); + + } catch (Exception exc) { + r -= addend; $(DERLEME_HATASI) + } +} +--- + +$(P +That function first modifies the reference parameter and then reverts this modification when an exception is thrown. Unfortunately, $(C addend) is accessible only in the $(C try) block, where it is defined. $(I ($(B Note:) This is related to name scopes, as well as object lifetimes, which will be explained in $(LINK2 lifetimes.html, a later chapter.))) +) + +) + +$(LI Writing all of potentially unrelated expressions in the single $(C finally) block at the bottom separates those expressions from the actual code that they are related to. +) + +) + +$(P +The $(C scope) statements have similar functionality to the $(C catch) and $(C finally) scopes but they are better in many respects. Like $(C finally), the three different $(C scope) statements are about executing expressions when leaving scopes: +) + +$(UL +$(LI $(C scope(exit)): the expression is always executed when exiting the scope, regardless of whether successfully or due to an exception) + +$(LI $(C scope(success)): the expression is executed only if the scope is being exited successfully) + +$(LI $(C scope(failure)): the expression is executed only if the scope is being exited due to an exception) +) + +$(P +Although these statements are closely related to exceptions, they can be used without a $(C try-catch) block. +) + +$(P +As an example, let's write the function above with a $(C scope(failure)) statement: +) + +--- +void foo(ref int r) { + int addend = 42; + + r += addend; + $(HILITE scope(failure)) r -= addend; + + mayThrow(); +} +--- + +$(P +The $(C scope(failure)) statement above ensures that the $(C r -= addend) expression will be executed if the function's scope is exited due to an exception. A benefit of $(C scope(failure)) is the fact that the expression that reverts another expression is written close to it. +) + +$(P +$(C scope) statements can be specified as blocks as well: +) + +--- + scope(exit) { + // ... expressions ... + } +--- + +$(P +Here is another function that tests all three of these statements: +) + +--- +void test() { + scope(exit) writeln("when exiting 1"); + + scope(success) { + writeln("if successful 1"); + writeln("if successful 2"); + } + + scope(failure) writeln("if thrown 1"); + scope(exit) writeln("when exiting 2"); + scope(failure) writeln("if thrown 2"); + + throwsHalfTheTime(); +} +--- + +$(P +If no exception is thrown, the output of the function includes only the $(C scope(exit)) and $(C scope(success)) expressions: +) + +$(SHELL +when exiting 2 +if successful 1 +if successful 2 +when exiting 1 +) + +$(P +If an exception is thrown, the output includes the $(C scope(exit)) and $(C scope(failure)) expressions: +) + +$(SHELL +if thrown 2 +when exiting 2 +if thrown 1 +when exiting 1 +object.Exception@...: the error message +) + +$(P +As seen in the outputs, the blocks of the $(C scope) statements are executed in reverse order. This is because later code may depend on previous variables. Executing the $(C scope) statements in reverse order enables undoing side effects of earlier expressions in a consistent order. +) + +Macros: + TITLE=scope + + DESCRIPTION=The scope(success), scope(failure), and scope(exit) statements that are used for specifying expressions that must be executed when exiting scopes. + + KEYWORDS=d programming language tutorial book scope diff --git a/book/d.en/slices.cozum.d b/book/d.en/slices.cozum.d new file mode 100644 index 0000000000..bb64f7dcd7 --- /dev/null +++ b/book/d.en/slices.cozum.d @@ -0,0 +1,40 @@ +Ddoc + +$(COZUM_BOLUMU Slices and Other Array Features) + +$(P +Iterating over elements by consuming a slice from the beginning is an interesting concept. This method is also the basis of Phobos ranges that we will see in a later chapter. +) + +--- +import std.stdio; + +void main() { + double[] array = [ 1, 20, 2, 30, 7, 11 ]; + + double[] slice = array; // Start with a slice that + // provides access to all of + // the elements of the array + + while (slice.length) { // As long as there is at least + // one element in that slice + + if (slice[0] > 10) { // Always use the first element + slice[0] /= 2; // in the expressions + } + + slice = slice[1 .. $]; // Shorten the slice from the + // beginning + } + + writeln(array); // The actual elements are + // changed +} +--- + +Macros: + TITLE=Slices and Other Array Features Solution + + DESCRIPTION=Programming in D exercise solutions: arrays + + KEYWORDS=programming in d tutorial arrays solution diff --git a/book/d.en/slices.d b/book/d.en/slices.d new file mode 100644 index 0000000000..cd40b19a77 --- /dev/null +++ b/book/d.en/slices.d @@ -0,0 +1,834 @@ +Ddoc + +$(DERS_BOLUMU $(IX slice) $(IX array) Slices and Other Array Features) + +$(P +We have seen in the $(LINK2 arrays.html, Arrays chapter) how elements are grouped as a collection in an array. That chapter was intentionally brief, leaving most of the features of arrays to this chapter. +) + +$(P +Before going any further, here are a few brief definitions of some of the terms that happen to be close in meaning: +) + +$(UL + +$(LI $(B Array:) The general concept of a group of elements that are located side by side and are accessed by indexes. +) + +$(LI +$(B Fixed-length array (static array):) An array with a fixed number of elements. This type of array owns its elements. +) + +$(LI +$(B Dynamic array:) An array that can gain or lose elements. This type of array provides access to elements that are owned by the D runtime environment. +) + +$(LI $(B Slice:) Another name for $(I dynamic array). +) + +) + +$(P +When I write $(I slice) I will specifically mean a slice; and when I write $(I array), I will mean either a slice or a fixed-length array, with no distinction. +) + +$(H5 Slices) + +$(P +Slices are the same feature as dynamic arrays. They are called $(I dynamic arrays) for being used like arrays, and are called $(I slices) for providing access to portions of other arrays. They allow using those portions as if they are separate arrays. +) + +$(P +$(IX .., slice element range) Slices are defined by the $(I number range) syntax that correspond to the indexes that specify the beginning and the end of the range: +) + +--- + $(I beginning_index) .. $(I one_beyond_the_end_index) +--- + +$(P +In the number range syntax, the beginning index is a part of the range but the end index is outside of the range: +) + +--- +/* ... */ = monthDays[0 .. 3]; // 0, 1, and 2 are included; but not 3 +--- + +$(P +$(I $(B Note:) Number ranges are different from Phobos ranges. Phobos ranges are about struct and class interfaces. We will see these features in later chapters. +) +) + +$(P +As an example, we can $(I slice) the $(C monthDays) array to be able to use its parts as four smaller arrays: +) + +--- + int[12] monthDays = + [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; + + int[] firstQuarter = monthDays[0 .. 3]; + int[] secondQuarter = monthDays[3 .. 6]; + int[] thirdQuarter = monthDays[6 .. 9]; + int[] fourthQuarter = monthDays[9 .. 12]; +--- + +$(P +The four variables in the code above are slices; they provide access to four parts of an already existing array. An important point worth stressing here is that those slices do not have their own elements. They merely provide access to the elements of the actual array. Modifying an element of a slice modifies the element of the actual array. To see this, let's modify the first elements of each slice and then print the actual array: +) + +--- + firstQuarter[0] = 1; + secondQuarter[0] = 2; + thirdQuarter[0] = 3; + fourthQuarter[0] = 4; + + writeln(monthDays); +--- + +$(P +The output: +) + +$(SHELL +[$(HILITE 1), 28, 31, $(HILITE 2), 31, 30, $(HILITE 3), 31, 30, $(HILITE 4), 30, 31] +) + +$(P +Each slice modifies its first element, and the corresponding element of the actual array is affected. +) + +$(P +We have seen earlier that valid array indexes are from 0 to one less than the length of the array. For example, the valid indexes of a 3-element array are 0, 1, and 2. Similarly, the end index in the slice syntax specifies one beyond the last element that the slice will be providing access to. For that reason, when the last element of an array needs to be included in a slice, the length of the array must be specified as the end index. For example, a slice of all elements of a 3-element array would be $(C array[0..3]). +) + +$(P +An obvious limitation is that the beginning index cannot be greater than the end index: +) + +--- + int[3] array = [ 0, 1, 2 ]; + int[] slice = array[2 .. 1]; // ← run-time ERROR +--- + +$(P +It is legal to have the beginning and the end indexes to be equal. In that case the slice is empty. Assuming that $(C index) is valid: +) + +--- + int[] slice = anArray[index .. index]; + writeln("The length of the slice: ", slice.length); +--- + +$(P +The output: +) + +$(SHELL +The length of the slice: 0 +) + +$(H5 $(IX $, slice length) Using $(C $), instead of $(C array.length)) + +$(P +When indexing, $(C $) is a shorthand for the length of the array: +) + +--- + writeln(array[array.length - 1]); // the last element + writeln(array[$ - 1]); // the same thing +--- + +$(H5 $(IX .dup) $(IX copy, array) Using $(C .dup) to copy) + +$(P +Short for "duplicate", the $(C .dup) property makes a new array from the copies of the elements of an existing array: +) + +--- + double[] array = [ 1.25, 3.75 ]; + double[] theCopy = array.dup; +--- + +$(P +As an example, let's define an array that contains the number of days of the months of a leap year. A method is to take a copy of the non-leap-year array and then to increment the element that corresponds to February: +) + +--- +import std.stdio; + +void main() { + int[12] monthDays = + [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; + + int[] leapYear = monthDays$(HILITE .dup); + + ++leapYear[1]; // increments the days in February + + writeln("Non-leap year: ", monthDays); + writeln("Leap year : ", leapYear); +} +--- + +$(P +The output: +) + +$(SHELL_SMALL +Non-leap year: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] +Leap year : [31, $(HILITE 29), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] +) + +$(H5 $(IX assignment, array) Assignment) + +$(P +We have seen so far that the assignment operator $(I modifies) values of variables. It is the same with fixed-length arrays: +) + +--- + int[3] a = [ 1, 1, 1 ]; + int[3] b = [ 2, 2, 2 ]; + + a = b; // the elements of 'a' become 2 + writeln(a); +--- + +$(P +The output: +) + +$(SHELL +[2, 2, 2] +) + +$(P +The assignment operation has a completely different meaning for slices: It makes the slice start providing access to new elements: +) + +--- + int[] odds = [ 1, 3, 5, 7, 9, 11 ]; + int[] evens = [ 2, 4, 6, 8, 10 ]; + + int[] slice; // not providing access to any elements yet + + $(HILITE slice =) odds[2 .. $ - 2]; + writeln(slice); + + $(HILITE slice =) evens[1 .. $ - 1]; + writeln(slice); +--- + +$(P +Above, $(C slice) does not provide access to any elements when it is defined. It is then used to provide access to some of the elements of $(C odds), and later to some of the elements of $(C evens): +) + +$(SHELL +[5, 7] +[4, 6, 8] +) + +$(H5 Making a slice longer may terminate sharing) + +$(P +Since the length of a fixed-length array cannot be changed, the concept of $(I termination of sharing) is only about slices. +) + +$(P +It is possible to access the same elements by more than one slice. For example, the first two of the eight elements below are being accessed through three slices: +) + +--- +import std.stdio; + +void main() { + int[] slice = [ 1, 3, 5, 7, 9, 11, 13, 15 ]; + int[] half = slice[0 .. $ / 2]; + int[] quarter = slice[0 .. $ / 4]; + + quarter[1] = 0; // modify through one slice + + writeln(quarter); + writeln(half); + writeln(slice); +} +--- + +$(P +The effect of the modification to the second element of $(C quarter) is seen through all slices: +) + +$(SHELL +[1, $(HILITE 0)] +[1, $(HILITE 0), 5, 7] +[1, $(HILITE 0), 5, 7, 9, 11, 13, 15] +) + +$(P +$(IX stomping) When viewed this way, slices provide $(I shared) access to elements. This sharing opens the question of what happens when a new element is added to one of the slices. Since multiple slices can provide access to same elements, there may not be room to add elements to a slice without $(I stomping) on the elements of others. +) + +$(P +D disallows element stomping and answers this question by terminating the sharing relationship if there is no room for the new element: The slice that has no room to grow leaves the sharing. When this happens, all of the existing elements of that slice are copied to a new place automatically and the slice starts providing access to these new elements. +) + +$(P +To see this in action, let's add an element to $(C quarter) before modifying its second element: +) + +--- + quarter ~= 42; // this slice leaves the sharing because + // there is no room for the new element + + quarter[1] = 0; // for that reason this modification + // does not affect the other slices +--- + +$(P +The output of the program shows that the modification to the $(C quarter) slice does not affect the others: +) + +$(SHELL +[1, $(HILITE 0), 42] +[1, 3, 5, 7] +[1, 3, 5, 7, 9, 11, 13, 15] +) + +$(P +Explicitly increasing the length of a slice makes it leave the sharing as well: +) + +--- + ++quarter.length; // leaves the sharing +--- + +$(P +or +) + +--- + quarter.length += 5; // leaves the sharing +--- + +$(P +On the other hand, shortening a slice does not affect sharing. Shortening the slice merely means that the slice now provides access to fewer elements: +) + +--- + int[] a = [ 1, 11, 111 ]; + int[] d = a; + + d = d[1 .. $]; // shortening from the beginning + d[0] = 42; // modifying the element through the slice + + writeln(a); // printing the other slice +--- + +$(P +As can be seen from the output, the modification through $(C d) is seen through $(C a); the sharing is still in effect: +) + +$(SHELL +[1, $(HILITE 42), 111] +) + +$(P +Reducing the length in different ways does not terminate the sharing either: +) + +--- + d = d[0 .. $ - 1]; // shortening from the end + --d.length; // same thing + d.length = d.length - 1; // same thing +--- + +$(P +Sharing of elements is still in effect. +) + +$(H6 $(IX .capacity) Using $(C capacity) to determine whether sharing will be terminated) + +$(P +There are cases when slices continue sharing elements even after an element is added to one of them. This happens when the element is added to the longest slice and there is room at the end of it: +) + +--- +import std.stdio; + +void main() { + int[] slice = [ 1, 3, 5, 7, 9, 11, 13, 15 ]; + int[] half = slice[0 .. $ / 2]; + int[] quarter = slice[0 .. $ / 4]; + + slice ~= 42; // adding to the longest slice ... + $(HILITE slice[1] = 0); // ... and then modifying an element + + writeln(quarter); + writeln(half); + writeln(slice); +} +--- + +$(P +As seen in the output, although the added element increases the length of a slice, the sharing has not been terminated, and the modification is seen through all slices: +) + +$(SHELL +[1, $(HILITE 0)] +[1, $(HILITE 0), 5, 7] +[1, $(HILITE 0), 5, 7, 9, 11, 13, 15, 42] +) + +$(P +The $(C capacity) property of slices determines whether the sharing will be terminated if an element is added to a particular slice. ($(C capacity) is actually a function but this distinction does not have any significance in this discussion.) +) + +$(P +The value of $(C capacity) has the following meanings: +) + +$(UL + +$(LI +When its value is 0, it means that this is not the longest original slice. In this case, adding a new element would definitely relocate the elements of the slice and the sharing would terminate. +) + +$(LI +When its value is nonzero, it means that this is the longest original slice. In this case $(C capacity) denotes the total number of elements that this slice can hold without needing to be copied. The number of $(I new elements) that can be added can be calculated by subtracting the actual length of the slice from the capacity value. If the length of the slice equals its capacity, then the slice will be copied to a new location if one more element is added.) + +) + +$(P +Accordingly, a program that needs to determine whether the sharing will terminate should use a logic similar to the following: +) + +--- + if (slice.capacity == 0) { + /* Its elements would be relocated if one more element + * is added to this slice. */ + + // ... + + } else { + /* This slice may have room for new elements before + * needing to be relocated. Let's calculate how + * many: */ + auto howManyNewElements = slice.capacity - slice.length; + + // ... + } +--- + +$(P +An interesting corner case is when there are more than one slice to $(I all elements). In such a case all slices report to have capacity: +) + +--- +import std.stdio; + +void main() { + // Three slices to all elements + int[] s0 = [ 1, 2, 3, 4 ]; + int[] s1 = s0; + int[] s2 = s0; + + writeln(s0.capacity); + writeln(s1.capacity); + writeln(s2.capacity); +} +--- + +$(P +All three have capacity: +) + +$(SHELL +7 +7 +7 +) + +$(P +However, as soon as an element is added to one of the slices, the capacity of the others drop to 0: +) + +--- + $(HILITE s1 ~= 42); $(CODE_NOTE s1 becomes the longest) + + writeln(s0.capacity); + writeln(s1.capacity); + writeln(s2.capacity); +--- + +$(P +Since the slice with the added element is now the longest, it is the only one with capacity: +) + +$(SHELL +0 +7 $(SHELL_NOTE now only s1 has capacity) +0 +) + +$(H6 $(IX .reserve) Reserving room for elements) + +$(P +Both copying elements and allocating new memory to increase capacity have some cost. For that reason, appending an element can be an expensive operation. When the number of elements to append is known beforehand, it is possible to reserve capacity for the elements: +) + +--- +import std.stdio; + +void main() { + int[] slice; + + slice$(HILITE .reserve(20)); + writeln(slice.capacity); + + foreach (element; 0 .. $(HILITE 17)) { + slice ~= element; $(CODE_NOTE these elements will not be moved) + } +} +--- + +$(SHELL +31 $(SHELL_NOTE Capacity for at least 20 elements) +) + +$(P +The elements of $(C slice) would be moved only after there are more than 31 elements. +) + +$(H5 $(IX array-wise operation) $(IX elements, operation on all) Operations on all elements) + +$(P +This feature is for both fixed-length arrays and slices. +) + +$(P +The $(C []) characters written after the name of an array means $(I all elements). This feature simplifies the program when certain operations need to be applied to all of the elements of an array. +) + +--- +import std.stdio; + +void main() { + double[3] a = [ 10, 20, 30 ]; + double[3] b = [ 2, 3, 4 ]; + + double[3] result = $(HILITE a[] + b[]); + + writeln(result); +} +--- + +$(P +The output: +) + +$(SHELL +[12, 23, 34] +) + +$(P +The addition operation in that program is applied to the corresponding elements of both of the arrays in order: First the first elements are added, then the second elements are added, etc. A natural requirement is that the lengths of the two arrays must be equal. +) + +$(P +The operator can be one of the arithmetic operators $(C +), $(C -), $(C *), $(C /), $(C %), and $(C ^^); one of the binary operators $(C ^), $(C &), and $(C |); as well as the unary operators $(C -) and $(C ~) that are typed in front of an array. We will see some of these operators in later chapters. +) + +$(P +The assignment versions of these operators can also be used: $(C =), $(C +=), $(C -=), $(C *=), $(C /=), $(C %=), $(C ^^=), $(C ^=), $(C &=), and $(C |=). +) + +$(P +This feature works not only using two arrays; it can also be used with an array and a compatible expression. For example, the following operation divides all elements of an array by four: +) + +--- + double[3] a = [ 10, 20, 30 ]; + $(HILITE a[]) /= 4; + + writeln(a); +--- + +$(P +The output: +) + +$(SHELL +[2.5, 5, 7.5] +) + +$(P +To assign a specific value to all elements: +) + +--- + $(HILITE a[]) = 42; + writeln(a); +--- + +$(P +The output: +) + +$(SHELL +[42, 42, 42] +) + +$(P +This feature requires great attention when used with slices. Although there is no apparent difference in element values, the following two expressions have very different meanings: +) + +--- + slice2 = slice1; // ← slice2 starts providing access + // to the same elements that + // slice1 provides access to + + slice3[] = slice1; // ← the values of the elements of + // slice3 change +--- + +$(P +The assignment of $(C slice2) makes it share the same elements as $(C slice1). On the other hand, since $(C slice3[]) means $(I all elements of $(C slice3)), the values of its elements become the same as the values of the elements of $(C slice1). The effect of the presence or absence of the $(C []) characters cannot be ignored. +) + +$(P +We can see an example of this difference in the following program: +) + +--- +import std.stdio; + +void main() { + double[] slice1 = [ 1, 1, 1 ]; + double[] slice2 = [ 2, 2, 2 ]; + double[] slice3 = [ 3, 3, 3 ]; + + slice2 = slice1; // ← slice2 starts providing access + // to the same elements that + // slice1 provides access to + + slice3[] = slice1; // ← the values of the elements of + // slice3 change + + writeln("slice1 before: ", slice1); + writeln("slice2 before: ", slice2); + writeln("slice3 before: ", slice3); + + $(HILITE slice2[0] = 42); // ← the value of an element that + // it shares with slice1 changes + + slice3[0] = 43; // ← the value of an element that + // only it provides access to + // changes + + writeln("slice1 after : ", slice1); + writeln("slice2 after : ", slice2); + writeln("slice3 after : ", slice3); +} +--- + +$(P +The modification through $(C slice2) affects $(C slice1) too: +) + +$(SHELL +slice1 before: [1, 1, 1] +slice2 before: [1, 1, 1] +slice3 before: [1, 1, 1] +slice1 after : [$(HILITE 42), 1, 1] +slice2 after : [$(HILITE 42), 1, 1] +slice3 after : [43, 1, 1] +) + +$(P +The danger here is that the potential bug may not be noticed until after the value of a shared element is changed. +) + +$(H5 $(IX multi-dimensional array) Multi-dimensional arrays) + +$(P +So far we have used arrays with only fundamental types like $(C int) and $(C double). The element type can actually be any other type, including other arrays. This enables the programmer to define complex containers like $(I array of arrays). Arrays of arrays are called $(I multi-dimensional arrays). +) + +$(P +The elements of all of the arrays that we have defined so far have been written in the source code from left to right. To help us understand the concept of a two-dimensional array, let's define an array from top to bottom this time: +) + +--- + int[] array = [ + 10, + 20, + 30, + 40 + ]; +--- + +$(P +As you remember, most spaces in the source code are used to help with readability and do not change the meaning of the code. The array above could have been defined on a single line and would have the same meaning. +) + +$(P +Let's now replace every element of that array with another array: +) + +--- + /* ... */ array = [ + [ 10, 11, 12 ], + [ 20, 21, 22 ], + [ 30, 31, 32 ], + [ 40, 41, 42 ] + ]; +--- + +$(P +We have replaced elements of type $(C int) with elements of type $(C int[]). To make the code conform to the array definition syntax, we must now specify the type of the elements as $(C int[]) instead of $(C int): +) + +--- + $(HILITE int[])[] array = [ + [ 10, 11, 12 ], + [ 20, 21, 22 ], + [ 30, 31, 32 ], + [ 40, 41, 42 ] + ]; +--- + +$(P +Such arrays are called $(I two-dimensional arrays) because they can be seen as having rows and columns. +) + +$(P +Two-dimensional arrays are used the same way as any other array as long as we remember that each element is an array itself and is used in array operations: +) + +--- + array ~= [ 50, 51 ]; // adds a new element (i.e. a slice) + array[0] ~= 13; // adds to the first element +--- + +$(P +The new state of the array: +) + +$(SHELL_SMALL +[[10, 11, 12, $(HILITE 13)], [20, 21, 22], [30, 31, 32], [40, 41, 42], $(HILITE [50, 51])] +) + +$(P +Arrays and elements can be fixed-length as well. The following is a three-dimensional array where all dimensions are fixed-length: +) + +--- + int[2][3][4] array; // 2 columns, 3 rows, 4 pages +--- + +$(P +The definition above can be seen as $(I four pages of three rows of two columns of integers). As an example, such an array can be used to represent a 4-story building in an adventure game, each story consisting of 2x3=6 rooms. +) + +$(P +For example, the number of items in the first room of the second floor can be incremented as follows: +) + +--- + // The index of the second floor is 1, and the first room + // of that floor is accessed by [0][0] + ++itemCounts[1][0][0]; +--- + +$(P +In addition to the syntax above, the $(C new) expression can also be used to create a $(I slice of slices). The following example uses only two dimensions: +) + +--- +import std.stdio; + +void main() { + int[][] s = new int[][](2, 3); + writeln(s); +} +--- + +$(P +The $(C new) expression above creates 2 slices containing 3 elements each and returns a slice that provides access to those slices and elements. The output: +) + +$(SHELL +[[0, 0, 0], [0, 0, 0]] +) + +$(H5 Summary) + +$(UL + +$(LI +Fixed-length arrays own their elements; slices provide access to elements that don't belong exclusively to them. +) + +$(LI +Within the $(C []) operator, $(C $) is the equivalent of $(C $(I array_name).length). +) + +$(LI +$(C .dup) makes a new array that consists of the copies of the elements of an existing array. +) + +$(LI +With fixed-length arrays, the assignment operation changes the values of elements; with slices, it makes the slices start providing access to other elements. +) + +$(LI +Slices that get longer $(I may) stop sharing elements and start providing access to newly copied elements. $(C capacity) determines whether this will be the case. +) + +$(LI +The syntax $(C array[]) means $(I all elements of the array); the operation that is applied to it is applied to each element individually. +) + +$(LI +Arrays of arrays are called multi-dimensional arrays. +) + +) + +$(PROBLEM_TEK + +$(P +Iterate over the elements of an array of $(C double)s and halve the ones that are greater than 10. For example, given the following array: +) + +--- + double[] array = [ 1, 20, 2, 30, 7, 11 ]; +--- + +$(P +Modify it as the following: +) + +$(SHELL +[1, $(HILITE 10), 2, $(HILITE 15), 7, $(HILITE 5.5)] +) + +$(P +Although there are many solutions of this problem, try to use only the features of slices. You can start with a slice that provides access to all elements. Then you can shorten the slice from the beginning and always use the first element. +) + +$(P +The following expression shortens the slice from the beginning: +) + +--- + slice = slice[1 .. $]; +--- + +) + +Macros: + TITLE=Slices and Other Array Features + + DESCRIPTION=More features of D slices and arrays + + KEYWORDS=d programming language tutorial book arrays slices fixed-length dynamic diff --git a/book/d.en/special_functions.d b/book/d.en/special_functions.d new file mode 100644 index 0000000000..307191991d --- /dev/null +++ b/book/d.en/special_functions.d @@ -0,0 +1,1267 @@ +Ddoc + +$(DERS_BOLUMU Constructor and Other Special Functions) + +$(P +Although this chapter focuses only on structs, the topics that are covered here apply mostly to classes as well. The differences will be explained in later chapters. +) + +$(P +Four member functions of structs are special because they define the fundamental operations of that type: +) +$(UL +$(LI Constructor: $(C this())) +$(LI Destructor: $(C ~this())) +$(LI Postblit: $(C this(this))) +$(LI Assignment operator: $(C opAssign())) +) + +$(P +Although these fundamental operations are handled automatically for structs, hence need not be defined by the programmer, they can be overridden to make the $(C struct) behave in special ways. +) + +$(H5 $(IX constructor) $(IX this, constructor) Constructor) + +$(P +The responsibility of the constructor is to prepare an object for use by assigning appropriate values to its members. +) + +$(P +We have already used constructors in previous chapters. When the name of a type is used like a function, it is actually the constructor that gets called. We can see this on the right-hand side of the following line: +) + +--- + auto busArrival = $(HILITE TimeOfDay)(8, 30); +--- + +$(P +Similarly, a $(I class) object is being constructed on the right hand side of the following line: +) + +--- + auto variable = new $(HILITE SomeClass()); +--- + +$(P +The arguments that are specified within parentheses correspond to the constructor parameters. For example, the values 8 and 30 above are passed to the $(C TimeOfDay) constructor as its parameters. +) + +$(P +In addition to different object construction syntaxes that we have seen so far; $(C const), $(C immutable), and $(C shared) objects can be constructed with the $(I type constructor) syntax as well (e.g. as $(C immutable(S)(2))). (We will see the $(C shared) keyword in $(LINK2 concurrency_shared.html, a later chapter).) +) + +$(P +For example, although all three variables below are $(C immutable), the construction of variable $(C a) is semantically different from the constructions of variables $(C b) and $(C c): +) + +--- + /* More familiar syntax; immutable variable of a mutable + * type: */ + $(HILITE immutable) a = S(1); + + /* Type constructor syntax; a variable of an immutable + * type: */ + auto b = $(HILITE immutable(S))(2); + + /* Same meaning as 'b' */ + immutable c = $(HILITE immutable(S))(3); +--- + +$(H6 Constructor syntax) + +$(P +Different from other functions, constructors do not have return values. The name of the constructor is always $(C this): +) + +--- +struct SomeStruct { + // ... + + this(/* constructor parameters */) { + // ... operations that prepare the object for use ... + } +} +--- + +$(P +The constructor parameters include information that is needed to make a useful and consistent object. +) + +$(H6 $(IX automatic constructor) $(IX default constructor) Compiler-generated automatic constructor) + +$(P +All of the structs that we have seen so far have been taking advantage of a constructor that has been generated automatically by the compiler. The automatic constructor assigns the parameter values to the members in the order that they are specified. +) + +$(P +As you will remember from $(LINK2 struct.html, the Structs chapter), the initial values for the trailing members need not be specified. The members that are not specified get initialized by the $(C .init) value of their respective types. The $(C .init) values of a member could be provided during the definition of that member after the $(C =) operator: +) + +--- +struct Test { + int member $(HILITE = 42); +} +--- + +$(P +Also considering the $(I default parameter values) feature from $(LINK2 parameter_flexibility.html, the Variable Number of Parameters chapter), we can imagine that the automatic constructor for the following $(C struct) would be the equivalent of the following $(C this()): +) + +--- +struct Test { + char c; + int i; + double d; + + /* The equivalent of the compiler-generated automatic + * constructor (Note: This is only for demonstration; the + * following constructor would not actually be called + * when default-constructing the object as Test().) */ + this(char c_parameter = char.init, + int i_parameter = int.init, + double d_parameter = double.init) { + c = c_parameter; + i = i_parameter; + d = d_parameter; + } +} +--- + +$(P +For most structs, the compiler-generated constructor is sufficient: Usually, providing appropriate values for each member is all that is needed for objects to be constructed. +) + +$(H6 $(IX this, member access) Accessing the members by $(C this.)) + +$(P +To avoid mixing the parameters with the members, the parameter names above had $(C _parameter) appended to their names. There would be compilation errors without doing that: +) + +--- +struct Test { + char c; + int i; + double d; + + this(char c = char.init, + int i = int.init, + double d = double.init) { + // An attempt to assign an 'in' parameter to itself! + c = c; $(DERLEME_HATASI) + i = i; + d = d; + } +} +--- + +$(P +The reason is; $(C c) alone would mean the parameter, not the member, and as the parameters above are defined as $(C in), they cannot be modified: +) + +$(SHELL +Error: variable deneme.Test.this.c $(HILITE cannot modify const) +) + +$(P +A solution is to prepend the member names with $(C this.). Inside member functions, $(C this) means "this object", making $(C this.c) mean "the c member of this object": +) + +--- + this(char c = char.init, + int i = int.init, + double d = double.init) { + $(HILITE this.)c = c; + $(HILITE this.)i = i; + $(HILITE this.)d = d; + } +--- + +$(P +Now $(C c) alone means the parameter and $(C this.c) means the member, and the code compiles and works as expected: The member $(C c) gets initialized by the value of the parameter $(C c). +) + +$(H6 $(IX user defined constructor) User-defined constructors) + +$(P +I have described the behavior of the compiler-generated constructor. Since that constructor is suitable for most cases, there is no need to define a constructor by hand. +) + +$(P +Still, there are cases where constructing an object involves more complicated operations than assigning values to each member in order. As an example, let's consider $(C Duration) from the earlier chapters: +) + +--- +struct Duration { + int minute; +} +--- + +$(P +The compiler-generated constructor is sufficient for this single-member struct: +) + +--- + time.decrement(Duration(12)); +--- + +$(P +Since that constructor takes the duration in minutes, the programmers would sometimes need to make calculations: +) + +--- + // 23 hours and 18 minutes earlier + time.decrement(Duration(23 * 60 + 18)); + + // 22 hours and 20 minutes later + time.increment(Duration(22 * 60 + 20)); +--- + +$(P +To eliminate the need for these calculations, we can design a $(C Duration) constructor that takes two parameters and makes the calculation automatically: +) + +--- +struct Duration { + int minute; + + this(int hour, int minute) { + this.minute = hour * 60 + minute; + } +} +--- + +$(P +Since hour and minute are now separate parameters, the users simply provide their values without needing to make the calculation themselves: +) + +--- + // 23 hours and 18 minutes earlier + time.decrement(Duration($(HILITE 23, 18))); + + // 22 hours and 20 minutes later + time.increment(Duration($(HILITE 22, 20))); +--- + +$(H6 First assignment to a member is construction) + +$(P +When setting values of members in a constructor, the first assignment to each member is treated specially: Instead of assigning a new value over the $(C .init) value of that member, the first assignment actually constructs that member. Further assignments to that member are treated regularly as assignment operations. +) + +$(P +This special behavior is necessary so that $(C immutable) and $(C const) members can in fact be constructed with values known only at run time. Otherwise, they could never be set to desired values as assignment is disallowed for $(C immutable) and $(C const) variables. +) + +$(P +The following program demonstrates how assigment operation is allowed only once for an $(C immutable) member: +) + +--- +struct S { + int m; + immutable int i; + + this(int m, int i) { + this.m = m; $(CODE_NOTE construction) + this.m = 42; $(CODE_NOTE assignment (possible for mutable member)) + + this.i = i; $(CODE_NOTE construction) + this.i = i; $(DERLEME_HATASI) + } +} + +void main() { + auto s = S(1, 2); +} +--- + +$(H6 User-defined constructor disables compiler-generated constructor) + +$(P +A constructor that is defined by the programmer makes some uses of the compiler-generated constructor invalid: Objects cannot be constructed by $(I default parameter values) anymore. For example, trying to construct $(C Duration) by a single parameter is a compilation error: +) + +--- + time.decrement(Duration(12)); $(DERLEME_HATASI) +--- + +$(P +Calling the constructor with a single parameter does not match the programmer's constructor and the compiler-generated constructor is disabled. +) + +$(P +One solution is to $(I overload) the constructor by providing another constructor that takes just one parameter: +) + +--- +struct Duration { + int minute; + + this(int hour, int minute) { + this.minute = hour * 60 + minute; + } + + this(int minute) { + this.minute = minute; + } +} +--- + +$(P +A user-defined constructor disables constructing objects by the $(C { }) syntax as well: +) + +--- + Duration duration = { 5 }; $(DERLEME_HATASI) +--- + +$(P +Initializing without providing any parameter is still valid: +) + +--- + auto d = Duration(); // compiles +--- + +$(P +The reason is, in D, the $(C .init) value of every type must be known at compile time. The value of $(C d) above is equal to the initial value of $(C Duration): +) + +--- + assert(d == Duration.init); +--- + +$(H6 $(IX static opCall) $(IX opCall, static) $(C static opCall) instead of the default constructor) + +$(P +Because the initial value of every type must be known at compile time, it is impossible to define the default constructor explicitly. +) + +$(P +Let's consider the following constructor that tries to print some information every time an object of that type is constructed: +) + +--- +struct Test { + this() { $(DERLEME_HATASI) + writeln("A Test object is being constructed."); + } +} +--- + +$(P +The compiler output: +) + +$(SHELL +Error: constructor deneme.Deneme.this default constructor for +structs only allowed with @disable and no body +) + +$(P $(I $(B Note:) We will see in later chapters that it is possible to define the default constructor for classes. +)) + +$(P +As a workaround, a no-parameter $(C static opCall()) can be used for constructing objects without providing any parameters. Note that this has no effect on the $(C .init) value of the type. +) + +$(P +For this to work, $(C static opCall()) must construct and return an object of that struct type: +) + +--- +import std.stdio; + +struct Test { + $(HILITE static) Test $(HILITE opCall)() { + writeln("A Test object is being constructed."); + Test test; + return test; + } +} + +void main() { + auto test = $(HILITE Test()); +} +--- + +$(P +The $(C Test()) call in $(C main()) executes $(C static opCall()): +) + +$(SHELL +A Test object is being constructed. +) + +$(P +Note that it is not possible to type $(C Test()) inside $(C static opCall()). That syntax would execute $(C static opCall()) as well and cause an infinite recursion: +) + +--- + static Test opCall() { + writeln("A Test object is being constructed."); + return $(HILITE Test()); // ← Calls 'static opCall()' again + } +--- + +$(P +The output: +) + +$(SHELL +A Test object is being constructed. +A Test object is being constructed. +A Test object is being constructed. +... $(SHELL_NOTE repeats the same message) +) + +$(H6 Calling other constructors) + +$(P +Constructors can call other constructors to avoid code duplication. Although $(C Duration) is too simple to demonstrate how useful this feature is, the following single-parameter constructor takes advantage of the two-parameter constructor: +) + +--- + this(int hour, int minute) { + this.minute = hour * 60 + minute; + } + + this(int minute) { + this(0, minute); // calls the other constructor + } +--- + +$(P +The constructor that only takes the minute value calls the other constructor by passing 0 as the value of hour. +) + +$(P +$(I $(B Warning:) There is a design flaw in the $(C Duration) constructors above because the intention is not clear when the objects are constructed by a single parameter): +) + +--- + // 10 hours or 10 minutes? + auto travelDuration = Duration(10); +--- + +$(P +Although it is possible to determine by reading the documentation or the code of the struct that the parameter actually means "10 minutes," it is an inconsistency as the first parameter of the two-parameter constructor is $(I hours). +) + +$(P +Such design mistakes are causes of bugs and must be avoided. +) + +$(H6 $(IX constructor qualifier) $(IX qualifier, constructor) Constructor qualifiers) + +$(P +Normally, the same constructor is used for $(I mutable), $(C const), $(C immutable), and $(C shared) objects: +) + +--- +import std.stdio; + +struct S { + this(int i) { + writeln("Constructing an object"); + } +} + +void main() { + auto m = S(1); + const c = S(2); + immutable i = S(3); + shared s = S(4); +} +--- + +$(P +Semantically, the objects that are constructed on the right-hand sides of those expressions are all mutable but the variables have different type qualifiers. The same constructor is used for all of them: +) + +$(SHELL +Constructing an object +Constructing an object +Constructing an object +Constructing an object +) + +$(P +Depending on the qualifier of the resulting object, sometimes some members may need to be initialized differently or need not be initialized at all. For example, since no member of an $(C immutable) object can be mutated throughout the lifetime of that object, leaving its mutable members uninitialized can improve program performance. +) + +$(P +$(I Qualified constructors) can be defined differently for objects with different qualifiers: +) + +--- +import std.stdio; + +struct S { + this(int i) { + writeln("Constructing an object"); + } + + this(int i) $(HILITE const) { + writeln("Constructing a const object"); + } + + this(int i) $(HILITE immutable) { + writeln("Constructing an immutable object"); + } + + // We will see the 'shared' keyword in a later chapter. + this(int i) $(HILITE shared) { + writeln("Constructing a shared object"); + } +} + +void main() { + auto m = S(1); + const c = S(2); + immutable i = S(3); + shared s = S(4); +} +--- + +$(P +However, as indicated above, as the right-hand side expressions are all semantically mutable, those objects are still constructed with the $(I mutable) object contructor: +) + +$(SHELL +Constructing an object +Constructing an object $(SHELL_NOTE_WRONG NOT the const constructor) +Constructing an object $(SHELL_NOTE_WRONG NOT the immutable constructor) +Constructing an object $(SHELL_NOTE_WRONG NOT the shared constructor) +) + +$(P +$(IX type constructor) To take advantage of qualified constructors, one must use the $(I type constructor) syntax. (The term $(I type constructor) should not be confused with object constructors; type constructor is related to types, not objects.) This syntax $(I makes) a different type by combining a qualifier with an existing type. For example, $(C immutable(S)) is a qualified type made from $(C immutable) and $(C S): +) + +--- + auto m = S(1); + auto c = $(HILITE const(S))(2); + auto i = $(HILITE immutable(S))(3); + auto s = $(HILITE shared(S))(4); +--- + +$(P +This time, the objects that are in the right-hand expressions are different: $(I mutable), $(C const), $(C immutable), and $(C shared), respectively. As a result, each object is constructed with its matching constructor: +) + +$(SHELL +Constructing an object +Constructing a $(HILITE const) object +Constructing an $(HILITE immutable) object +Constructing a $(HILITE shared) object +) + +$(P +Note that, since all of the variables above are defined with the $(C auto) keyword, they are correctly inferred to be $(I mutable), $(C const), $(C immutable), and $(C shared), respectively. +) + +$(H6 Immutability of constructor parameters) + +$(P +In the $(LINK2 const_and_immutable.html, Immutability chapter) we have seen that it is not easy to decide whether parameters of reference types should be defined as $(C const) or $(C immutable). Although the same considerations apply for constructor parameters as well, $(C immutable) is usually a better choice for constructor parameters. +) + +$(P +The reason is, it is common to assign the parameters to members to be used at a later time. When a parameter is not $(C immutable), there is no guarantee that the original variable will not change by the time the member gets used. +) + +$(P +Let's consider a constructor that takes a file name as a parameter. The file name will be used later on when writing student grades. According to the guidelines in the $(LINK2 const_and_immutable.html, Immutability chapter), to be more useful, let's assume that the constructor parameter is defined as $(C const char[]): +) + +--- +import std.stdio; + +struct Student { + $(HILITE const char[]) fileName; + int[] grades; + + this($(HILITE const char[]) fileName) { + this.fileName = fileName; + } + + void save() { + auto file = File(fileName.idup, "w"); + file.writeln("The grades of the student:"); + file.writeln(grades); + } + + // ... +} + +void main() { + char[] fileName; + fileName ~= "student_grades"; + + auto student = Student(fileName); + + // ... + + /* Assume the fileName variable is modified later on + * perhaps unintentionally (all of its characters are + * being set to 'A' here): */ + $(HILITE fileName[] = 'A'); + + // ... + + /* The grades would be written to the wrong file: */ + student.save(); +} +--- + +$(P +The program above saves the grades of the student under a file name that consists of A characters, not to $(STRING "student_grades"). For that reason, sometimes it is more suitable to define constructor parameters and members of reference types as $(C immutable). We know that this is easy for strings by using aliases like $(C string). The following code shows the parts of the struct that would need to be modified: +) + +--- +struct Student { + $(HILITE string) fileName; + // ... + this($(HILITE string) fileName) { + // ... + } + // ... +} +--- + +$(P +Now the users of the struct must provide $(C immutable) strings and as a result the confusion about the name of the file would be prevented. +) + +$(H6 $(IX type conversion, constructor) Type conversions through single-parameter constructors) + +$(P +Single-parameter constructors can be thought of as providing a sort of type conversion: They produce an object of the particular struct type starting from a constructor parameter. For example, the following constructor produces a $(C Student) object from a $(C string): +) + +--- +struct Student { + string name; + + this(string name) { + this.name = name; + } +} +--- + +$(P +$(C to()) and $(C cast) observe this behavior as a $(I conversion) as well. To see examples of this, let's consider the following $(C salute()) function. Sending a $(C string) parameter when it expects a $(C Student) would naturally cause a compilation error: +) + +--- +void salute(Student student) { + writeln("Hello ", student.name); +} +// ... + salute("Jane"); $(DERLEME_HATASI) +--- + +$(P +On the other hand, all of the following lines ensure that a $(C Student) object is constructed before calling the function: +) + +--- +import std.conv; +// ... + salute(Student("Jane")); + salute(to!Student("Jean")); + salute(cast(Student)"Jim"); +--- + +$(P +$(C to) and $(C cast) take advantage of the single-parameter constructor by constructing a temporary $(C Student) object and calling $(C salute()) with that object. +) + +$(H6 $(IX @disable, constructor) Disabling the default constructor) + +$(P +Functions that are declared as $(C @disable) cannot be called. +) + +$(P +Sometimes there are no sensible default values for the members of a type. For example, it may be illegal for the following type to have an empty file name: +) + +--- +struct Archive { + string fileName; +} +--- + +$(P +Unfortunately, the compiler-generated default constructor would initialize $(C fileName) as empty: +) + +--- + auto archive = Archive(); // ← fileName member is empty +--- + +$(P +The default constructor can explicitly be disabled by declaring it as $(C @disable) so that objects must be constructed by one of the other constructors. There is no need to provide a body for a disabled function: +) + +--- +struct Archive { + string fileName; + + $(HILITE @disable this();) $(CODE_NOTE cannot be called) + + this(string fileName) { $(CODE_NOTE can be called) + // ... + } +} + +// ... + + auto archive = Archive(); $(DERLEME_HATASI) +--- + +$(P +This time the compiler does not allow calling $(C this()): +) + +$(SHELL +Error: constructor deneme.Archive.this is $(HILITE not callable) because +it is annotated with @disable +) + +$(P +Objects of $(C Archive) must be constructed either with one of the other constructors or explicitly with its $(C .init) value: +) + +--- + auto a = Archive("records"); $(CODE_NOTE compiles) + auto b = Archive.init; $(CODE_NOTE compiles) +--- + +$(H5 $(IX destructor) $(IX ~this) Destructor) + +$(P +The destructor includes the operations that must be executed when the lifetime of an object ends. +) + +$(P +The compiler-generated automatic destructor executes the destructors of all of the members in order. For that reason, as it is with the constructor, there is no need to define a destructor for most structs. +) + +$(P +However, sometimes some special operations may need to be executed when an object's lifetime ends. For example, an operating system resource that the object owns may need to be returned to the system; a member function of another object may need to be called; a server running somewhere on the network may need to be notified that a connection to it is about to be terminated; etc. +) + +$(P +The name of the destructor is $(C ~this) and just like constructors, it has no return type. +) + +$(H6 Destructor is executed automatically) + +$(P +The destructor is executed as soon as the lifetime of the struct object ends. (This is not the case for objects that are constructed with the $(C new) keyword.) +) + +$(P +As we have seen in the $(LINK2 lifetimes.html, Lifetimes and Fundamental Operations chapter,) the lifetime of an object ends when leaving the scope that it is defined in. The following are times when the lifetime of a struct ends: +) + +$(UL +$(LI When leaving the scope of the object either normally or due to a thrown exception: + +--- + if (aCondition) { + auto duration = Duration(7); + // ... + + } // ← The destructor is executed for 'duration' + // at this point +--- + +) + +$(LI Anonymous objects are destroyed at the end of the whole expression that they are constructed in: + +--- + time.increment(Duration(5)); // ← The Duration(5) object + // gets destroyed at the end + // of the whole expression. +--- + +) + +$(LI All of the struct members of a struct object get destroyed when the outer object is destroyed. + +) + +) + +$(H6 Destructor example) + +$(P +Let's design a type for generating simple XML documents. XML elements are defined by angle brackets. They contain data and other XML elements. XML elements can have attributes as well; we will ignore them here. +) + +$(P +Our aim will be to ensure that an element that has been $(I opened) by a $(C <name>) tag will always be $(I closed) by a matching $(C </name>) tag: +) + +$(MONO + <class1> ← opening the outer XML element + <grade> ← opening the inner XML element + 57 ← the data + </grade> ← closing the inner element + </class1> ← closing the outer element +) + +$(P +A struct that can produce the output above can be designed by two members that store the tag for the XML element and the indentation to use when printing it: +) + +--- +struct XmlElement { + string name; + string indentation; +} +--- + +$(P +If the responsibilities of opening and closing the XML element are given to the constructor and the destructor, respectively, the desired output can be produced by managing the lifetimes of XmlElement objects. For example, the constructor can print $(C <tag>) and the destructor can print $(C </tag>). +) + +$(P +The following definition of the constructor produces the opening tag: +) + +--- + this(string name, int level) { + this.name = name; + this.indentation = indentationString(level); + + writeln(indentation, '<', name, '>'); + } +--- + +$(P +$(C indentationString()) is the following function: +) + +--- +import std.array; +// ... +string indentationString(int level) { + return replicate(" ", level * 2); +} +--- + +$(P +The function calls $(C replicate()) from the $(C std.array) module, which makes and returns a new string made up of the specified value repeated the specified number of times. +) + +$(P +The destructor can be defined similar to the constructor to produce the closing tag: +) + +--- + ~this() { + writeln(indentation, "'); + } +--- + +$(P +Here is a test code to demonstrate the effects of the automatic constructor and destructor calls: +) + +--- +import std.conv; +import std.random; +import std.array; + +string indentationString(int level) { + return replicate(" ", level * 2); +} + +struct XmlElement { + string name; + string indentation; + + this(string name, int level) { + this.name = name; + this.indentation = indentationString(level); + + writeln(indentation, '<', name, '>'); + } + + ~this() { + writeln(indentation, "'); + } +} + +void main() { + immutable classes = XmlElement("classes", 0); + + foreach (classId; 0 .. 2) { + immutable classTag = "class" ~ to!string(classId); + immutable classElement = XmlElement(classTag, 1); + + foreach (i; 0 .. 3) { + immutable gradeElement = XmlElement("grade", 2); + immutable randomGrade = uniform(50, 101); + + writeln(indentationString(3), randomGrade); + } + } +} +--- + +$(P +Note that the $(C XmlElement) objects are created in three separate scopes in the program above. The opening and closing tags of the XML elements in the output are produced solely by the constructor and the destructor of $(C XmlElement). +) + +$(SHELL +<classes> + <class0> + <grade> + 72 + </grade> + <grade> + 97 + </grade> + <grade> + 90 + </grade> + </class0> + <class1> + <grade> + 77 + </grade> + <grade> + 87 + </grade> + <grade> + 56 + </grade> + </class1> +</classes> +) + +$(P +The $(C <classes>) element is produced by the $(C classesElement) variable. Because that variable is constructed first in $(C main()), the output contains the output of its construction first. Since it is also the variable that is destroyed last, upon leaving $(C main()), the output contains the output of the destructor call for its destruction last. +) + +$(H5 $(IX postblit) $(IX this(this)) Postblit) + +$(P +$(I Copying) is constructing a new object from an existing one. Copying involves two steps: +) + +$(OL + +$(LI Copying the members of the existing object to the new object bit-by-bit. This step is called $(I blit), short for $(I block transfer). +) + +$(LI Making further adjustments to the new object. This step is called $(I postblit). +) + +) + +$(P +The first step is handled automatically by the compiler: It copies the members of the existing object to the members of the new object: +) + +--- + auto returnTripDuration = tripDuration; // copying +--- + +$(P +Do not confuse copying with $(I assignment). The $(C auto) keyword above is an indication that a new object is being defined. (The actual type name could have been spelled out instead of $(C auto).) +) + +$(P +For an operation to be assignment, the object on the left-hand side must be an existing object. For example, assuming that $(C returnTripDuration) has already been defined: +) + +--- + returnTripDuration = tripDuration; // assignment (see below) +--- + +$(P +Sometimes it is necessary to make adjustments to the members of the new object after the automatic blit. These operations are defined in the postblit function of the struct. +) + +$(P +Since it is about object construction, the name of the postblit is $(C this) as well. To separate it from the other constructors, its parameter list contains the keyword $(C this): + +) + +--- + this(this) { + // ... + } +--- + +$(P +We have defined a $(C Student) type in the $(LINK2 struct.html, Structs chapter), which had a problem about copying objects of that type: +) + +--- +struct Student { + int number; + int[] grades; +} +--- + +$(P +Being a slice, the $(C grades) member of that $(C struct) is a reference type. The consequence of copying a $(C Student) object is that the $(C grades) members of both the original and the copy provide access to the same actual array elements of type $(C int). As a result, the effect of modifying a grade through one of these objects is seen through the other object as well: +) + +--- + auto student1 = Student(1, [ 70, 90, 85 ]); + + auto student2 = student1; // copying + student2.number = 2; + + student1.grades[0] += 5; // this changes the grade of the + // second student as well: + assert($(HILITE student2).grades[0] == $(HILITE 75)); +--- + +$(P +To avoid such a confusion, the elements of the $(C grades) member of the second object must be separate and belong only to that object. Such $(I adjustments) are done in the postblit: +) + +--- +struct Student { + int number; + int[] grades; + + this(this) { + grades = grades.dup; + } +} +--- + +$(P +Remember that all of the members have already been copied automatically before $(C this(this)) started executing. The single line in the postblit above makes a copy of the $(I elements) of the original array and assigns a slice of it back to $(C grades). As a result, the new object gets its own copy of the grades. +) + +$(P +Making modifications through the first object does not affect the second object anymore: +) + +--- + student1.grades[0] += 5; + assert($(HILITE student2).grades[0] == $(HILITE 70)); +--- + +$(H6 $(IX @disable, postblit) Disabling postblit) + +$(P +The postblit function can be disabled by $(C @disable) as well. Objects of such a type cannot be copied: +) + +--- +struct Archive { +// ... + + $(HILITE @disable this(this);) +} + +// ... + + auto a = Archive("records"); + auto b = a; $(DERLEME_HATASI) +--- + +$(P +The compiler does not allow calling the disabled postblit function: +) + +$(SHELL +Error: struct deneme.Archive is $(HILITE not copyable) because it is +annotated with @disable +) + +$(H5 $(IX assignment operator) $(IX =) $(IX opAssign) Assignment operator) + +$(P +Assigment is giving a new value to an existing object: +) + +--- + returnTripDuration = tripDuration; // assignment +--- + +$(P +Assignment is more complicated from the other special operations because it is actually a combination of two operations: +) + +$(UL +$(LI Destroying the left-hand side object) +$(LI Copying the right-hand side object to the left-hand side object) +) + +$(P +However, applying those two steps in that order is risky because the original object would be destroyed before knowing that copying will succeed. Otherwise, an exception that is thrown during the copy operation can leave the left-hand side object in an inconsistent state: fully destroyed but not completely copied. +) + +$(P +For that reason, the compiler-generated assignment operator acts safely by applying the following steps: +) + +$(OL + +$(LI Copy the right-hand side object to a temporary object + +$(P +This is the actual copying half of the assignment operation. Since there is no change to the left-hand side object yet, it will remain intact if an exception is thrown during this copy operation. +) + +) + +$(LI Destroy the left-hand side object + +$(P +This is the other half of the assignment operation. +) + +) + +$(LI Transfer the temporary object to the left-hand side object + +$(P +No postblit nor a destructor is executed during or after this step. As a result, the left-hand side object becomes the equivalent of the temporary object. +) + +) + +) + +$(P +After the steps above, the temporary object disappears and only the right-hand side object and its copy (i.e. the left-hand side object) remain. +) + +$(P +Although the compiler-generated assignment operator is suitable in most cases, it can be defined by the programmer. When you do that, consider potential exceptions and write the assignment operator in a way that works even at the presence of thrown exceptions. +) + +$(P +The syntax of the assignment operator is the following: +) + +$(UL +$(LI The name of the function is $(C opAssign).) +$(LI The type of the parameter is the same as the $(C struct) type. This parameter is often named as $(C rhs), short for $(I right-hand side).) +$(LI The return type is the same as the $(C struct) type.) +$(LI The function is exited by $(C return this).) +) + +$(P +As an example, let's consider a simple $(C Duration) struct where the assignment operator prints a message: +) + +--- +struct Duration { + int minute; + + $(HILITE Duration) opAssign($(HILITE Duration) rhs) { + writefln("minute is being changed from %s to %s", + this.minute, rhs.minute); + + this.minute = rhs.minute; + + $(HILITE return this;) + } +} +// ... + auto duration = Duration(100); + duration = Duration(200); // assignment +--- + +$(P +The output: +) + +$(SHELL +minute is being changed from 100 to 200 +) + +$(H6 Assigning from other types) + +$(P +Sometimes it is convenient to assign values of types that are different from the type of the $(C struct). For example, instead of requiring a $(C Duration) object on the right-hand side, it may be useful to assign from an integer: +) + +--- + duration = 300; +--- + +$(P +This is possible by defining another assignment operator that takes an $(C int) parameter: +) + +--- +struct Duration { + int minute; + + Duration opAssign(Duration rhs) { + writefln("minute is being changed from %s to %s", + this.minute, rhs.minute); + + this.minute = rhs.minute; + + return this; + } + + Duration opAssign($(HILITE int minute)) { + writefln("minute is being replaced by an int"); + + this.minute = minute; + + return this; + } +} +// ... + duration = Duration(200); + duration = $(HILITE 300); +--- + +$(P +The output: +) + +$(SHELL +minute is being changed from 100 to 200 +minute is being replaced by an int +) + +$(P +$(B Note:) Although convenient, assigning different types to each other may cause confusions and errors. +) + +$(H5 Summary) + +$(UL + +$(LI Constructor ($(C this)) is for preparing objects for use. The compiler-generated default constructor is sufficient in most cases.) + +$(LI The behavior of the default constructor may not be changed in structs; $(C static opCall) can be used instead.) + +$(LI Single-parameter constructors can be used during type conversions by $(C to) and $(C cast).) + +$(LI Destructor ($(C ~this)) is for the operations that must be executed when the lifetimes of objects end.) + +$(LI Postblit ($(C this(this))) is for adjustments to the object after the automatic member copies.) + +$(LI Assigment operator ($(C opAssign)) is for changing values of existing objects.) + +) + +Macros: + TITLE=Constructor and Other Special Functions + + DESCRIPTION=Four special functions of structs and classes: constructor, destructor, postblit, and assignment operator. + + KEYWORDS=d programming lesson book tutorial constructor destructor postblit assignment diff --git a/book/d.en/static_foreach.d b/book/d.en/static_foreach.d new file mode 100644 index 0000000000..1ef81d8ac2 --- /dev/null +++ b/book/d.en/static_foreach.d @@ -0,0 +1,220 @@ +Ddoc + +$(DERS_BOLUMU $(IX foreach, static) $(IX static foreach) $(CH4 static foreach)) + +$(P +We saw compile-time $(C foreach) earlier in the $(LINK2 tuples.html, Tuples chapter). Compile-time $(C foreach) iterates the loop at compile time and unrolls each iteration as separate pieces of code. For example, given the following $(C foreach) loop over a tuple: +) + +--- + auto t = tuple(42, "hello", 1.5); + + foreach (i, member; $(HILITE t)) { + writefln("%s: %s", i, member); + } +--- + +$(P +The compiler $(I unrolls) the loop similar to the following equivalent code: +) + +--- + { + enum size_t i = 0; + int member = t[i]; + writefln("%s: %s", i, member); + } + { + enum size_t i = 1; + string member = t[i]; + writefln("%s: %s", i, member); + } + { + enum size_t i = 2; + double member = t[i]; + writefln("%s: %s", i, member); + } +--- + +$(P +Although being very powerful, some properties of compile-time $(C foreach) may not be suitable in some cases: +) + +$(UL + +$(LI +With compile-time $(C foreach), each unrolling of the loop introduces a scope. As seen with the $(C i) and $(C member) variables above, this allows the use of a symbol in more than one scope without causing a multiple definition error. Although this can be desirable in some cases, it makes it impossible for code unrolled for one iteration to use code from other iterations. +) + +$(LI +Compile-time $(C foreach) works only with tuples (including template arguments in the form of $(C AliasSeq)). For example, despite the elements of the following array literal being known at compile time, the loop will always be executed at run time (this may very well be the desired behavior): +) + +) + +--- +void main() { + $(HILITE enum) arr = [1, 2]; + // Executed at run time, not unrolled at compile time: + foreach (i; arr) { + // ... + } +} +--- + +$(UL + +$(LI +Like regular $(C foreach), compile-time $(C foreach) can only be used inside functions. For example, it cannot be used at module scope or inside a user-defined type definition. +) + +) + +--- +import std.meta; + +// Attempting to define function overloads at module scope: +foreach (T; AliasSeq!(int, double)) { $(DERLEME_HATASI) + T twoTimes(T arg) { + return arg * 2; + } +} + +void main() { +} +--- + +$(SHELL +Error: declaration expected, not `foreach` +) + +$(UL + +$(LI +With compile-time $(C foreach), it may not be clear whether $(C break) and $(C continue) statements inside the loop body should affect the compile-time loop iteration itself or whether they should be parts of the unrolled code. +) + +) + +$(P +$(C static foreach) is a more powerful compile-time feature that provides more control: +) + +$(UL + +$(LI +$(C static foreach) can work with any range of elements that can be computed at compile time (including number ranges like $(C 1..10)). For example, given the $(C FibonacciSeries) range from $(LINK2 ranges.html, the Ranges chapter) and a function that determines whether a number is even: +) + +) + +--- + $(HILITE static foreach) (n; FibonacciSeries().take(10).filter!isEven) { + writeln(n); + } +--- + +$(P +The loop above would be unrolled as the following equivalent: +) + +--- + writeln(0); + writeln(2); + writeln(8); + writeln(34); +--- + +$(UL + +$(LI $(C static foreach) can be used at module scope.) + +$(LI +$(C static foreach) does not introduce a separate scope for each iteration. For example, the following loop defines two overloads of a function at module scope: +) + +) + +--- +import std.meta; + +static foreach (T; AliasSeq!(int, double)) { + T twoTimes(T arg) { + return arg * 2; + } +} + +void main() { +} +--- + +$(P +The loop above would be unrolled as its following equivalent: +) + +--- + int twoTimes(int arg) { + return arg * 2; + } + + double twoTimes(double arg) { + return arg * 2; + } +--- + +$(UL + +$(LI +$(C break) and $(C continue) statements inside a $(C static foreach) loop require labels for clarity. For example, the following code unrolls (generates) $(C case) clauses inside a $(C switch) statement. The $(C break) statements that are under each $(C case) clause must mention the associated $(C switch) statements by labels: +) + +) + +--- +import std.stdio; + +void main(string[] args) { + +$(HILITE theSwitchStatement:) + switch (args.length) { + static foreach (i; 1..3) { + case i: + writeln(i); + break $(HILITE theSwitchStatement); + } + + default: + writeln("default case"); + break; + } +} +--- + +$(P +After the loop above is unrolled, the $(C switch) statement would be the equivalent of the following code: +) + +--- + switch (args.length) { + case 1: + writeln(1); + break; + + case 2: + writeln(2); + break; + + default: + writeln("default case"); + break; + } +--- + +macros: + TITLE=static foreach + + DESCRIPTION=static foreach, one of D's compile-time feature that can generate code by iterating ranges. + + KEYWORDS=d programming language tutorial book static foreach + +MINI_SOZLUK= diff --git a/book/d.en/stream_redirect.cozum.d b/book/d.en/stream_redirect.cozum.d new file mode 100644 index 0000000000..e76388912c --- /dev/null +++ b/book/d.en/stream_redirect.cozum.d @@ -0,0 +1,26 @@ +Ddoc + +$(COZUM_BOLUMU Redirecting the Standard Input and Output Streams) + +$(P +Redirecting standard input and output of programs are commonly used especially on Unix-based operating system shells. (A shell is the program that interacts with the user in the terminal.) Some programs are designed to work well when piped to other programs. +) + +$(P +For example, a file named $(C deneme.d) can be searched under a directory tree by piping $(C find) and $(C grep) as in the following line: +) + +$(SHELL +find | grep deneme.d +) + +$(P +$(C find) prints the names of all of the files to its output. $(C grep) receives that output through its input and prints the lines that contain $(C deneme.d) to its own output. +) + +Macros: + TITLE=Redirecting the Standard Input and Output Streams Solutions + + DESCRIPTION=Problem solutions for the Redirecting Streams Input and Output Streams chapter. + + KEYWORDS=d programming lesson book tutorial redirect standard input output problem solution diff --git a/book/d.en/stream_redirect.d b/book/d.en/stream_redirect.d new file mode 100644 index 0000000000..7f07dc2d03 --- /dev/null +++ b/book/d.en/stream_redirect.d @@ -0,0 +1,136 @@ +Ddoc + +$(DERS_BOLUMU $(IX redirect, stream) Redirecting the Standard Input and Output Streams) + +$(P +All of the programs that we have seen so far have interacted through $(C stdin) and $(C stdout), the standard input and output streams. Input and output functions like $(C readf) and $(C writeln) operate on these streams by default. +) + +$(P +While using these streams, we assumed that the standard input comes from the keyboard and that the standard output goes to the screen. +) + +$(P +We will start writing programs that deal with files in later chapters. We will see that, just like the standard input and output streams, files are character streams as well; so they are used in almost the same way as $(C stdin) and $(C stdout). +) + +$(P +But before seeing how files are accessed from within programs, I would like to show how the standard inputs and outputs of programs can be redirected to files or piped to other programs. Existing programs can, without their source code being changed, be made to print to files instead of the screen, and read from files instead of the keyboard. Although these features are not directly related to programming languages, they are useful tools that are available in nearly all modern shells. +) + +$(H5 $(IX >, output redirect) Redirecting the standard output to a file with operator $(C >)) + +$(P +When starting the program from the terminal, typing a $(C >) character and a file name at the end of the command line redirects the standard output of that program to the specified file. Everything that the program prints to its standard output will be written to that file instead. +) + +$(P +Let's test this with a program that reads a floating point number from its input, multiplies that number by two, and prints the result to its standard output: +) + +--- +import std.stdio; + +void main() { + double number; + readf(" %s", &number); + + writeln(number * 2); +} +--- + +$(P +If the name of the program is $(C by_two), its output will be written to a file named $(C by_two_result.txt) when the program is started on the command line as in the following line: +) + +$(SHELL +./by_two > by_two_result.txt +) + +$(P +For example, if we enter $(C 1.2) at the terminal, the result $(C 2.4) will appear in $(C by_two_result.txt). ($(I $(B Note:) Although the program does not display a prompt like "Please enter a number", it still expects a number to be entered.)) +) + +$(H5 $(IX <, input redirect) Redirecting the standard input from a file with operator $(C <)) + +$(P +Similarly to redirecting the standard output by using the $(C >) operator, the standard input can be redirected from a file by using the $(C <) operator. In this case, the program reads from the specified file instead of from the keyboard. +) + +$(P +To test this, let's use a program that calculates one tenth of a number: +) + +--- +import std.stdio; + +void main() { + double number; + readf(" %s", &number); + + writeln(number / 10); +} +--- + +$(P +Assuming that the file $(C by_two_result.txt) still exists and contains $(C 2.4) from the previous output, and that the name of the new program is $(C one_tenth), we can redirect the new program's standard input from that file as in the following line: +) + +$(SHELL +./one_tenth < by_two_result.txt +) + +$(P +This time the program will read from $(C by_two_result.txt) and print the result to the terminal as $(C 0.24). +) + +$(H5 Redirecting both standard streams) + +$(P +The operators $(C >) and $(C <) can be used at the same time: +) + +$(SHELL +./one_tenth < by_two_result.txt > one_tenth_result.txt +) + +$(P +This time the standard input will be read from $(C by_two_result.txt) and the standard output will be written to $(C one_tenth_result.txt). +) + +$(H5 $(IX |, stream pipe) Piping programs with operator $(C |)) + +$(P +Note that $(C by_two_result.txt) is an intermediary between the two programs; $(C by_two) writes to it and $(C one_tenth) reads from it. +) + +$(P +The $(C |) operator pipes the standard output of the program that is on its left-hand side to the standard input of the program that is on its right-hand side without the need for an intermediary file. For example, when the two programs above are piped together as in the following line, they collectively calculate $(I one fifth) of the input: +) + +$(SHELL +./by_two | ./one_tenth +) + +$(P +First $(C by_two) reads a number from its input. (Remember that although it does not prompt for one, it still waits for a number.) Then $(C by_two) writes the result to its standard output. This result of $(C by_two) will appear on the standard input of $(C one_tenth), which in turn will calculate and print one tenth of that result. +) + +$(PROBLEM_TEK + +$(P +Pipe more than one program: +) + +$(SHELL +./one | ./two | ./three +) + +) + +Macros: + TITLE=Redirecting the Standard Input and Output Streams + + DESCRIPTION=Reading from files and other programs instead of from the keyboard, and printing to files and other programs instead of the terminal. + + KEYWORDS=d programming language tutorial book redirect standard input output diff --git a/book/d.en/strings.cozum.d b/book/d.en/strings.cozum.d new file mode 100644 index 0000000000..13869eee83 --- /dev/null +++ b/book/d.en/strings.cozum.d @@ -0,0 +1,63 @@ +Ddoc + +$(COZUM_BOLUMU Strings) + +$(OL + +$(LI +Although some of the functions in Phobos modules will be easy to use with strings, library documentations are usually terse compared to tutorials. You may find especially the Phobos ranges confusing at this point. We will see Phobos ranges in a later chapter. +) + +$(LI +Many other functions may be chained as well: + +--- +import std.stdio; +import std.string; + +void main() { + write("First name: "); + string first = capitalize(strip(readln())); + + write("Last name: "); + string last = capitalize(strip(readln())); + + string fullName = first ~ " " ~ last; + writeln(fullName); +} +--- + +) + +$(LI This program uses two indexes to make a slice: + +--- +import std.stdio; +import std.string; + +void main() { + write("Please enter a line: "); + string line = strip(readln()); + + ptrdiff_t first_e = indexOf(line, 'e'); + + if (first_e == -1) { + writeln("There is no letter e in this line."); + + } else { + ptrdiff_t last_e = lastIndexOf(line, 'e'); + writeln(line[first_e .. last_e + 1]); + } +} +--- + +) + +) + +Macros: + TITLE=Strings Solution + + DESCRIPTION=Programming in D exercise solutions: strings + + KEYWORDS=programming in d tutorial strings solution diff --git a/book/d.en/strings.d b/book/d.en/strings.d new file mode 100644 index 0000000000..cf7f6fe9dc --- /dev/null +++ b/book/d.en/strings.d @@ -0,0 +1,511 @@ +Ddoc + +$(DERS_BOLUMU Strings) + +$(P +We have used strings in many programs that we have seen so far. Strings are a combination of the two features that we have covered in the last three chapters: characters and arrays. In the simplest definition, strings are nothing but arrays of characters. For example, $(C char[]) is a type of string. +) + +$(P +This simple definition may be misleading. As we have seen in the $(LINK2 characters.html, Characters chapter), D has three separate character types. Arrays of these character types lead to three separate string types, some of which may have surprising outcomes in some string operations. +) + +$(H5 $(IX readln) $(IX strip) $(C readln) and $(C strip), instead of $(C readf)) + +$(P +There are surprises even when reading strings from the terminal. +) + +$(P +Being character arrays, strings can contain control characters like $(STRING '\n') as well. When reading strings from the input, the control character that corresponds to the Enter key that is pressed at the end of the input becomes a part of the string as well. Further, because there is no way to tell $(C readf()) how many characters to read, it continues to read until the end of the entire input. For these reasons, $(C readf()) does not work as intended when reading strings: +) + +--- +import std.stdio; + +void main() { + char[] name; + + write("What is your name? "); + readf(" %s", &name); + + writeln("Hello ", name, "!"); +} +--- + +$(P +The Enter key that the user presses after the name does not terminate the input. $(C readf()) continues to wait for more characters to add to the string: +) + +$(SHELL +What is your name? Mert + $(SHELL_NOTE The input is not terminated although Enter has been pressed) + $(SHELL_NOTE (Let's assume that Enter is pressed a second time here)) +) + +$(P +One way of terminating the standard input stream in a terminal is pressing Ctrl-D under Unix-based systems and Ctrl-Z under Windows systems. If the user eventually terminates the input that way, we see that the new-line characters have been read as parts of the string as well: +) + +$(SHELL +Hello Mert + $(SHELL_NOTE_WRONG new-line character after the name) +! $(SHELL_NOTE_WRONG (one more before the exclamation mark)) +) + +$(P +The exclamation mark appears after those characters instead of being printed right after the name. +) + +$(P +$(C readln()) is more suitable when reading strings. Short for "read line", $(C readln()) reads until the end of the line. It is used differently because the $(STRING " %s") format string and the $(C &) operator are not needed: +) + +--- +import std.stdio; + +void main() { + char[] name; + + write("What is your name? "); + $(HILITE readln(name)); + + writeln("Hello ", name, "!"); +} +--- + +$(P +$(C readln()) stores the new-line character as well. This is so that the program has a way of determining whether the input consisted of a complete line or whether the end of input has been reached: +) + +$(SHELL +What is your name? Mert +Hello Mert +! $(SHELL_NOTE_WRONG new-line character before the exclamation mark) +) + +$(P +Such control characters as well as all whitespace characters at both ends of strings can be removed by $(C std.string.strip): +) + +--- +import std.stdio; +$(HILITE import std.string;) + +void main() { + char[] name; + + write("What is your name? "); + readln(name); + $(HILITE name = strip(name);) + + writeln("Hello ", name, "!"); +} +--- + +$(P +The $(C strip()) expression above returns a new string that does not contain the trailing control characters. Assigning that return value back to $(C name) produces the intended output: +) + +$(SHELL +What is your name? Mert +Hello Mert! $(SHELL_NOTE no new-line character) +) + +$(P +$(C readln()) can be used without a parameter. In that case it $(I returns) the line that it has just read. Chaining the result of $(C readln()) to $(C strip()) enables a shorter and more readable syntax: +) + +--- + string name = strip(readln()); +--- + +$(P +I will start using that form after introducing the $(C string) type below. +) + +$(H5 $(IX formattedRead) $(C formattedRead) for parsing strings) + +$(P +Once a line is read from the input or from any other source, it is possible to parse and convert separate data that it may contain with $(C formattedRead()) from the $(C std.format) module. Its first parameter is the line that contains the data, and the rest of the parameters are used exacly like $(C readf()): +) + +--- +import std.stdio; +import std.string; +$(HILITE import std.format;) + +void main() { + write("Please enter your name and age," ~ + " separated with a space: "); + + string line = strip(readln()); + + string name; + int age; + $(HILITE formattedRead)(line, " %s %s", name, age); + + writeln("Your name is ", name, + ", and your age is ", age, '.'); +} +--- + +$(SHELL +Please enter your name and age, separated with a space: $(HILITE Mert 30) +Your name is $(HILITE Mert), and your age is $(HILITE 30). +) + +$(P +Both $(C readf()) and $(C formattedRead()) $(I return) the number of items that they could parse and convert successfully. That value can be compared against the expected number of data items so that the input can be validated. For example, as the $(C formattedRead()) call above expects to read $(I two) items (a $(C string) as name and an $(C int) as age), the following check ensures that it really is the case: +) + +--- + $(HILITE uint items) = formattedRead(line, " %s %s", name, age); + + if ($(HILITE items != 2)) { + writeln("Error: Unexpected line."); + + } else { + writeln("Your name is ", name, + ", and your age is ", age, '.'); + } +--- + +$(P +When the input cannot be converted to $(C name) and $(C age), the program prints an error: +) + +$(SHELL +Please enter your name and age, separated with a space: $(HILITE Mert) +Error: Unexpected line. +) + +$(H5 $(IX ") Double quotes, not single quotes) + +$(P +We have seen that single quotes are used to define character literals. String literals are defined with double quotes. $(STRING 'a') is a character; $(STRING "a") is a string that contains a single character. +) + +$(H5 $(IX string) $(IX wstring) $(IX dstring) $(IX char[]) $(IX wchar[]) $(IX dchar[]) $(IX immutable) $(C string), $(C wstring), and $(C dstring) are immutable) + +$(P +There are three string types that correspond to the three character types: $(C char[]), $(C wchar[]), and $(C dchar[]). +) + +$(P +There are three $(I aliases) of the $(I immutable) versions of those types: $(C string), $(C wstring), and $(C dstring). The characters of the variables that are defined by these aliases cannot be modified. For example, the characters of a $(C wchar[]) can be modified but the characters of a $(C wstring) cannot be modified. (We will see D's $(I immutability) concept in later chapters.) +) + +$(P +For example, the following code that tries to capitalize the first letter of a $(C string) would cause a compilation error: +) + +--- + string cannotBeMutated = "hello"; + cannotBeMutated[0] = 'H'; $(DERLEME_HATASI) +--- + +$(P +We may think of defining the variable as a $(C char[]) instead of the $(C string) alias but that cannot be compiled either: +) + +--- + char[] a_slice = "hello"; $(DERLEME_HATASI) +--- + +$(P +This time the compilation error is due to the combination of two factors: +) + +$(OL +$(LI The type of string literals like $(STRING "hello") is $(C string), not $(C char[]), so they are immutable. +) +$(LI The $(C char[]) on the left-hand side is a slice, which, if the code compiled, would provide access to all of the characters of the right-hand side. +) +) + +$(P +Since $(C char[]) is mutable and $(C string) is not, there is a mismatch. The compiler does not allow accessing characters of an immutable array through a mutable slice. +) + +$(P +The solution here is to take a copy of the immutable string by using the $(C .dup) property: +) + +--- +import std.stdio; + +void main() { + char[] s = "hello"$(HILITE .dup); + s[0] = 'H'; + writeln(s); +} +--- + +$(P +The program can now be compiled and will print the modified string: +) + +$(SHELL +Hello +) + +$(P +Similarly, $(C char[]) cannot be used where a $(C string) is needed. In such cases, the $(C .idup) property can be used to produce an immutable $(C string) variable from a mutable $(C char[]) variable. For example, if $(C s) is a variable of type $(C char[]), the following line will fail to compile: +) + +--- + string result = s ~ '.'; $(DERLEME_HATASI) +--- + +$(P +When the type of $(C s) is $(C char[]), the type of the expression on the right-hand side of the assignment above is $(C char[]) as well. $(C .idup) is used for producing immutable strings from existing strings: +) + +--- + string result = (s ~ '.')$(HILITE .idup); // ← now compiles +--- + +$(H5 $(IX length, string) Potentially confusing length of strings) + +$(P +We have seen that some Unicode characters are represented by more than one byte. For example, the character 'é' (the latin letter 'e' combined with an acute accent) is represented by Unicode encodings using at least two bytes. This fact is reflected in the $(C .length) property of strings: +) + +--- + writeln("résumé".length); +--- + +$(P +Although "résumé" contains six $(I letters), the length of the $(C string) is the number of UTF-8 code units that it contains: +) + +$(SHELL +8 +) + +$(P +The type of the elements of string literals like $(STRING "hello") is $(C char) and each $(C char) value represents a UTF-8 code unit. A problem that this may cause is when we try to replace a two-code-unit character with a single-code-unit character: +) + +--- + char[] s = "résumé".dup; + writeln("Before: ", s); + s[1] = 'e'; + s[5] = 'e'; + writeln("After : ", s); +--- + +$(P +The two 'e' characters do not replace the two 'é' characters; they replace single code units, resulting in an invalid UTF-8 encoding: +) + +$(SHELL +Before: résumé +After : re�sueé $(SHELL_NOTE_WRONG INCORRECT) +) + +$(P +When dealing with letters, symbols, and other Unicode characters directly, as in the code above, the correct type to use is $(C dchar): +) + +--- + dchar[] s = "résumé"d.dup; + writeln("Before: ", s); + s[1] = 'e'; + s[5] = 'e'; + writeln("After : ", s); +--- + +$(P +The output: +) + +$(SHELL +Before: résumé +After : resume +) + +$(P +Please note the two differences in the new code: +) +$(OL +$(LI The type of the string is $(C dchar[]). +$(LI There is a $(C d) at the end of the literal $(STRING "résumé"d), specifying its type as an array of $(C dchar)s.) +) +) + +$(P +In any case, keep in mind that the use of $(C dchar[]) and $(C dstring) does not solve all of the problems of manipulating Unicode characters. For instance, if the user inputs the text "résumé" you and your program cannot assume that the string length will be 6 even for $(C dchar) strings. It might be greater if e.g. at least one of the 'é' characters is not encoded as a single code point but as the combination of an 'e' and a combining accute accent. To avoid dealing with this and many other Unicode issues, consider using a Unicode-aware text manipulation library in your programs. +) + +$(H5 $(IX literal, string) String literals) + +$(P +The optional character that is specified after string literals determines the type of the elements of the string: +) + +--- +import std.stdio; + +void main() { + string s = "résumé"c; // same as "résumé" + wstring w = "résumé"w; + dstring d = "résumé"d; + + writeln(s.length); + writeln(w.length); + writeln(d.length); +} +--- + +$(P +The output: +) + +$(SHELL +8 +6 +6 +) + +$(P +Because all of the Unicode characters of "résumé" can be represented by a single $(C wchar) or $(C dchar), the last two lengths are equal to the number of characters. +) + +$(H5 $(IX concatenation, string) String concatenation) + +$(P +Since they are actually arrays, all of the array operations can be applied to strings as well. $(C ~) concatenates two strings and $(C ~=) appends to an existing string: +) + +--- +import std.stdio; +import std.string; + +void main() { + write("What is your name? "); + string name = strip(readln()); + + // Concatenate: + string greeting = "Hello " ~ name; + + // Append: + greeting ~= "! Welcome..."; + + writeln(greeting); +} +--- + +$(P +The output: +) + +$(SHELL +What is your name? Can +Hello Can! Welcome... +) + +$(H5 Comparing strings) + +$(P +$(I $(B Note:) Unicode does not define how the characters are ordered other than their Unicode codes. For that reason, you may get results that don't match your expectations below.) +) + +$(P +We have used comparison operators $(C <), $(C >=), etc. with integer and floating point values before. The same operators can be used with strings as well, but with a different meaning: strings are ordered $(I lexicographically). This ordering takes each character's Unicode code to be its place in a hypothetical grand Unicode alphabet. The concepts of $(I less) and $(I greater) are replaced with $(I before) and $(I after) in this hypothetical alphabet: +) + +--- +import std.stdio; +import std.string; + +void main() { + write(" Enter a string: "); + string s1 = strip(readln()); + + write("Enter another string: "); + string s2 = strip(readln()); + + if (s1 $(HILITE ==) s2) { + writeln("They are the same!"); + + } else { + string former; + string latter; + + if (s1 $(HILITE <) s2) { + former = s1; + latter = s2; + + } else { + former = s2; + latter = s1; + } + + writeln("'", former, "' comes before '", latter, "'."); + } +} +--- + +$(P +Because Unicode adopts the letters of the basic Latin alphabet from the ASCII table, the strings that contain only the letters of the ASCII table will always be ordered correctly. +) + +$(H5 Lowercase and uppercase are different) + +$(P +Because each character has a unique code, every letter variant is different from the others. For example, 'A' and 'a' are different letters, when directly comparing Unicode strings. +) + +$(P +Additionally, as a consequence of their ASCII code values, all of the latin uppercase letters are sorted before all of the lowercase letters. For example, 'B' comes before 'a'. The $(C icmp()) function of the $(C std.string) module can be used when strings need to be compared regardless of lowercase and uppercase. You can see the functions of this module at $(LINK2 http://dlang.org/phobos/std_string.html, its online documentation). +) + +$(P +Because strings are arrays (and as a corollary, $(I ranges)), the functions of the $(C std.array), $(C std.algorithm), and $(C std.range) modules are very useful with strings as well. +) + +$(PROBLEM_COK + +$(PROBLEM +Browse the documentations of the $(C std.string), $(C std.array), $(C std.algorithm), and $(C std.range) modules. +) + +$(PROBLEM +Write a program that makes use of the $(C ~) operator: The user enters the first name and the last name, all in lowercase letters. Produce the full name that contains the proper capitalization of the first and last names. For example, when the strings are "ebru" and "domates" the program should print "Ebru Domates". +) + +$(PROBLEM +Read a line from the input and print the part between the first and last 'e' letters of the line. For example, when the line is "this line has five words" the program should print "e has five". + +$(P +You may find the $(C indexOf()) and $(C lastIndexOf()) functions useful to get the two indexes needed to produce a slice. +) + +$(P +As it is indicated in their documentation, the return types of $(C indexOf()) and $(C lastIndexOf()) are not $(C int) nor $(C size_t), but $(C ptrdiff_t). You may have to define variables of that exact type: +) + +--- + ptrdiff_t first_e = indexOf(line, 'e'); +--- + +$(P +It is possible to define variables with the $(C auto) keyword, which we will see in a later chapter: +) + +--- + auto first_e = indexOf(line, 'e'); +--- + +) + +) + +Macros: + TITLE=Strings + + DESCRIPTION=The strings of the D programming language + + KEYWORDS=d programming language tutorial book string diff --git a/book/d.en/struct.cozum.d b/book/d.en/struct.cozum.d new file mode 100644 index 0000000000..5212f17439 --- /dev/null +++ b/book/d.en/struct.cozum.d @@ -0,0 +1,220 @@ +Ddoc + +$(COZUM_BOLUMU Structs) + +$(OL + +$(LI +One of the simplest designs is to use two $(C dchar) members: + +--- +struct Card { + dchar suit; + dchar value; +} +--- + +) + +$(LI +It would be as simple as printing the two members side by side: + +--- +void printCard(Card card) { + write(card.suit, card.value); +} +--- + +) + +$(LI +Assuming that there is already a function called $(C newSuit()), $(C newDeck()) can be implemented by calling that function for each suit: + +--- +Card[] newDeck() +out (result) { + assert(result.length == 52); + +} do { + Card[] deck; + + deck ~= newSuit('♠'); + deck ~= newSuit('♡'); + deck ~= newSuit('♢'); + deck ~= newSuit('♣'); + + return deck; +} +--- + +$(P +The rest of the work can be accomplished by the following $(C newSuit()), which constructs the suit by combining the suit character with each value of a string: +) + +--- +Card[] newSuit(dchar suit) +in { + assert((suit == '♠') || + (suit == '♡') || + (suit == '♢') || + (suit == '♣')); + +} out (result) { + assert(result.length == 13); + +} do { + Card[] suitCards; + + foreach (value; "234567890JQKA") { + suitCards ~= Card(suit, value); + } + + return suitCards; +} +--- + +$(P +Note that the functions above take advantage of contract programming to reduce risk of program errors. +) + +) + +$(LI +Swapping two elements at random would make the deck become more and more shuffled at each repetition. Although it is possible to pick the same element by chance, swapping an element with itself does not have any effect other than missing an opportunity toward a more shuffled deck. + +--- +void shuffle(Card[] deck, int repetition) { + /* Note: A better algorithm is to walk the deck from the + * beginning to the end and to swap each element + * with a random one that is picked among the + * elements from that point to the end. + * + * It would be even better to call randomShuffle() from + * the std.algorithm module, which already applies the + * same algorithm. Please read the comment in main() to + * see how randomShuffle() can be used. */ + foreach (i; 0 .. repetition) { + // Pick two elements at random + immutable first = uniform(0, deck.length); + immutable second = uniform(0, deck.length); + + swap(deck[first], deck[second]); + } +} +--- + +$(P +The function above calls $(C std.algorithm.swap), which simply swaps the values of its two $(C ref) parameters. It is effectively the equivalent of the following function: +) + +--- +void mySwap(ref Card left, + ref Card right) { + immutable temporary = left; + left = right; + right = temporary; +} +--- + +) + +) + +$(P +Here is the entire program: +) + +--- +import std.stdio; +import std.random; +import std.algorithm; + +struct Card { + dchar suit; + dchar value; +} + +void printCard(Card card) { + write(card.suit, card.value); +} + +Card[] newSuit(dchar suit) +in { + assert((suit == '♠') || + (suit == '♡') || + (suit == '♢') || + (suit == '♣')); + +} out (result) { + assert(result.length == 13); + +} do { + Card[] suitCards; + + foreach (value; "234567890JQKA") { + suitCards ~= Card(suit, value); + } + + return suitCards; +} + +Card[] newDeck() +out (result) { + assert(result.length == 52); + +} do { + Card[] deck; + + deck ~= newSuit('♠'); + deck ~= newSuit('♡'); + deck ~= newSuit('♢'); + deck ~= newSuit('♣'); + + return deck; +} + +void shuffle(Card[] deck, int repetition) { + /* Note: A better algorithm is to walk the deck from the + * beginning to the end and to swap each element + * with a random one that is picked among the + * elements from that point to the end. + * + * It would be even better to call randomShuffle() from + * the std.algorithm module, which already applies the + * same algorithm. Please read the comment in main() to + * see how randomShuffle() can be used. */ + foreach (i; 0 .. repetition) { + // Pick two elements at random + immutable first = uniform(0, deck.length); + immutable second = uniform(0, deck.length); + + swap(deck[first], deck[second]); + } +} + +void main() { + Card[] deck = newDeck(); + + shuffle(deck, 100); + /* Note: Instead of the shuffle() call above, it would be + * better to call randomShuffle() as in the + * following line: + * + * randomShuffle(deck); + */ + foreach (card; deck) { + printCard(card); + write(' '); + } + + writeln(); +} +--- + + +Macros: + TITLE=Structs Solutions + + DESCRIPTION=Programming in D exercise solutions: Structs + + KEYWORDS=d programming book tutorial struct exercise solutions diff --git a/book/d.en/struct.d b/book/d.en/struct.d new file mode 100644 index 0000000000..64dc288685 --- /dev/null +++ b/book/d.en/struct.d @@ -0,0 +1,932 @@ +Ddoc + +$(DERS_BOLUMU $(IX struct) Structs) + +$(P +As has been mentioned several times earlier in the book, fundamental types are not suitable to represent higher-level concepts. For example, although a value of type $(C int) is suitable to represent the hour of day, two $(C int) variables would be more suitable together to represent a point in time: one for the hour and the other for the minute. +) + +$(P +$(IX user defined type) Structs are the feature that allow defining new types by combining already existing other types. The new type is defined by the $(C struct) keyword. By this definition, structs are $(I user defined types). Most of the content of this chapter is directly applicable to classes as well. Especially the concept of $(I combining existing types to define a new type) is exactly the same for them. +) + +$(P +This chapter covers only the basic features of structs. We will see more of structs in the following chapters: +) + +$(UL +$(LI $(LINK2 member_functions.html, Member Functions)) +$(LI $(LINK2 const_member_functions.html, const ref Parameters and const Member Functions)) +$(LI $(LINK2 special_functions.html, Constructor and Other Special Functions)) +$(LI $(LINK2 operator_overloading.html, Operator Overloading)) +$(LI $(LINK2 encapsulation.html, Encapsulation and Protection Attributes)) +$(LI $(LINK2 property.html, Properties)) +$(LI $(LINK2 invariant.html, Contract Programming for Structs and Classes)) +$(LI $(LINK2 foreach_opapply.html, foreach with Structs and Classes)) +) + +$(P +To understand how useful structs are, let's take a look at the $(C addDuration()) function that we had defined earlier in the $(LINK2 assert.html, $(C assert) and $(C enforce) chapter). The following definition is from the exercise solution of that chapter: +) + +--- +void addDuration(int startHour, int startMinute, + int durationHour, int durationMinute, + out int resultHour, out int resultMinute) { + resultHour = startHour + durationHour; + resultMinute = startMinute + durationMinute; + resultHour += resultMinute / 60; + + resultMinute %= 60; + resultHour %= 24; +} +--- + +$(P $(I $(B Note:) I will ignore the $(C in), $(C out), and $(C unittest) blocks in this chapter to keep the code samples short.) +) + +$(P +Although the function above clearly takes six parameters, when the three pairs of parameters are considered, it is conceptually taking only three bits of information for the starting time, the duration, and the result. +) + +$(H5 Definition) + +$(P +The $(C struct) keyword defines a new type by combining variables that are related in some way: +) + +--- +$(CODE_NAME TimeOfDay)struct TimeOfDay { + int hour; + int minute; +} +--- + +$(P +The code above defines a new type named $(C TimeOfDay), which consists of two variables named $(C hour) and $(C minute). That definition allows the new $(C TimeOfDay) type to be used in the program just like any other type. The following code demonstrates how similar its use is to an $(C int)'s: +) + +--- + int number; // a variable + number = otherNumber; // taking the value of otherNumber + + TimeOfDay time; // an object + time = otherTime; // taking the value of otherTime +--- + +$(P +The syntax of $(C struct) definition is the following: +) + +--- +struct $(I TypeName) { + // ... member variables and functions ... +} +--- + +$(P +We will see member functions in later chapters. +) + +$(P +The variables that a struct combines are called its $(I members). According to this definition, $(C TimeOfDay) has two members: $(C hour) and $(C minute). +) + +$(H6 $(C struct) defines a type, not a variable) + +$(P +There is an important distinction here: Especially after the $(LINK2 name_space.html, Name Scope) and $(LINK2 lifetimes.html, Lifetimes and Fundamental Operations) chapters, the curly brackets of $(C struct) definitions may give the wrong impression that the struct members start and end their lives inside that scope. This is not true. +) + +$(P +Member definitions are not variable definitions: +) + +--- +struct TimeOfDay { + int hour; // ← Not a variable; will become a part of + // a struct variable used in the program. + + int minute; // ← Not a variable; will become a part of + // a struct variable used in the program. +} +--- + +$(P +The definition of a $(C struct) determines the types and the names of the members that the objects of that $(C struct) will have. Those member variables will be constructed as parts of $(C TimeOfDay) objects that take part in the program: +) + +--- + TimeOfDay bedTime; // This object contains its own hour + // and minute member variables. + + TimeOfDay wakeUpTime; // This object contains its own hour + // and minute member variables as + // well. The member variables of + // this object are not related to + // the member variables of the + // previous object. +--- + +$(P +$(IX object, struct) Variables of $(C struct) and $(C class) types are called $(I objects). +) + +$(H6 Coding convenience) + +$(P +Being able to combine the concepts of hour and minute together as a new type is a great convenience. For example, the function above can be rewritten in a more meaningful way by taking three $(C TimeOfDay) parameters instead of the existing six $(C int) parameters: +) + +--- +void addDuration(TimeOfDay start, + TimeOfDay duration, + out TimeOfDay result) { + // ... +} +--- + +$(P $(I $(B Note:) It is not normal to add two variables that represent two points in time. For example, it is meaningless to add the lunch time 12:00 to the breakfast time 7:30. It would make more sense to define another type, appropriately called $(C Duration), and to add objects of that type to $(C TimeOfDay) objects. Despite this design flaw, I will continue using only $(C TimeOfDay) objects in this chapter and introduce $(C Duration) in a later chapter.) +) + +$(P +As you remember, functions return up-to a single value. That has precisely been the reason why the earlier definition of $(C addDuration()) was taking two $(C out) parameters: It could not return the hour and minute information as a single value. +) + +$(P +Structs remove this limitation as well: Since multiple values can be combined as a single $(C struct) type, functions can return an object of such a $(C struct), effectively returning multiple values at once. $(C addDuration()) can now be defined as returning its result: +) + +--- +TimeOfDay addDuration(TimeOfDay start, + TimeOfDay duration) { + // ... +} +--- + +$(P +As a consequence, $(C addDuration()) now becomes a function that produces a value, as opposed to being a function that has side effects. As you would remember from the $(LINK2 functions.html, Functions chapter), producing results is preferred over having side effects. +) + +$(P +Structs can be members of other structs. For example, the following $(C struct) has two $(C TimeOfDay) members: +) + +--- +struct Meeting { + string topic; + size_t attendanceCount; + TimeOfDay start; + TimeOfDay end; +} +--- + +$(P +$(C Meeting) can in turn be a member of another $(C struct). Assuming that there is also the $(C Meal) struct: +) + +--- +struct DailyPlan { + Meeting projectMeeting; + Meal lunch; + Meeting budgetMeeting; +} +--- + +$(H5 $(IX ., member) Accessing the members) + +$(P +Struct members are used like any other variable. The only difference is that the actual struct variable and a $(I dot) must be specified before the name of the member: +) + +--- + start.hour = 10; +--- + +$(P +The line above assigns the value 10 to the $(C hour) member of the $(C start) object. +) + +$(P +Let's rewrite the $(C addDuration()) function with what we have seen so far: +) + +--- +$(CODE_NAME addDuration)TimeOfDay addDuration(TimeOfDay start, + TimeOfDay duration) { + TimeOfDay result; + + result.minute = start.minute + duration.minute; + result.hour = start.hour + duration.hour; + result.hour += result.minute / 60; + + result.minute %= 60; + result.hour %= 24; + + return result; +} +--- + +$(P +Notice that the names of the variables are now much shorter in this version of the function: $(C start), $(C duration), and $(C result). Additionally, instead of using complex names like $(C startHour), it is possible to access struct members through their respective struct variables as in $(C start.hour). +) + +$(P +Here is a code that uses the new $(C addDuration()) function. Given the start time and the duration, the following code calculates when a class period at a school would end: +) + +--- +$(CODE_XREF TimeOfDay)$(CODE_XREF addDuration)void main() { + TimeOfDay periodStart; + periodStart.hour = 8; + periodStart.minute = 30; + + TimeOfDay periodDuration; + periodDuration.hour = 1; + periodDuration.minute = 15; + + immutable periodEnd = addDuration(periodStart, + periodDuration); + + writefln("Period end: %s:%s", + periodEnd.hour, periodEnd.minute); +} +--- + +$(P +The output: +) + +$(SHELL +Period end: 9:45 +) + +$(P +The $(C main()) above has been written only by what we have seen so far. We will make this code even shorter and cleaner soon. +) + +$(H5 $(IX construction) Construction) + +$(P +The first three lines of $(C main()) are about constructing the $(C periodStart) object and the next three lines are about constructing the $(C periodDuration) object. In each three lines of code first an object is being defined and then its hour and minute values are being set. +) + +$(P +In order for a variable to be used in a safe way, that variable must first be constructed in a consistent state. Because construction is so common, there is a special construction syntax for struct objects: +) + +--- + TimeOfDay periodStart = TimeOfDay(8, 30); + TimeOfDay periodDuration = TimeOfDay(1, 15); +--- + +$(P +The values are automatically assigned to the members in the order that they are specified: Because $(C hour) is defined first in the $(C struct), the value 8 is assigned to $(C periodStart.hour) and 30 is assigned to $(C periodStart.minute). +) + +$(P +As we have seen in $(LINK2 cast.html, the Type Conversions chapter), the construction syntax can be used for other types as well: +) + +--- + auto u = ubyte(42); // u is a ubyte + auto i = int(u); // i is an int +--- + +$(H6 Constructing objects as $(C immutable)) + +$(P +Being able to construct the object by specifying the values of its members at once makes it possible to define objects as $(C immutable): +) + +--- + immutable periodStart = TimeOfDay(8, 30); + immutable periodDuration = TimeOfDay(1, 15); +--- + +$(P +Otherwise it would not be possible to mark an object first as $(C immutable) and then modify its members: +) + +--- + $(HILITE immutable) TimeOfDay periodStart; + periodStart.hour = 8; $(DERLEME_HATASI) + periodStart.minute = 30; $(DERLEME_HATASI) +--- + +$(H6 Trailing members need not be specified) + +$(P +There may be fewer values specified than the number of members. In that case, the remaining members are initialized by the $(C .init) values of their respective types. +) + +$(P +The following program constructs $(C Test) objects each time with one less constructor parameter. The $(C assert) checks indicate that the unspecified members are initialized automatically by their $(C .init) values. (The reason for needing to call $(C isNaN()) is explained after the program): +) + +--- +import std.math; + +struct Test { + char c; + int i; + double d; +} + +void main() { + // The initial values of all of the members are specified + auto t1 = Test('a', 1, 2.3); + assert(t1.c == 'a'); + assert(t1.i == 1); + assert(t1.d == 2.3); + + // Last one is missing + auto t2 = Test('a', 1); + assert(t2.c == 'a'); + assert(t2.i == 1); + assert($(HILITE isNaN(t2.d))); + + // Last two are missing + auto t3 = Test('a'); + assert(t3.c == 'a'); + assert($(HILITE t3.i == int.init)); + assert($(HILITE isNaN(t3.d))); + + // No initial value specified + auto t4 = Test(); + assert($(HILITE t4.c == char.init)); + assert($(HILITE t4.i == int.init)); + assert($(HILITE isNaN(t4.d))); + + // The same as above + Test t5; + assert(t5.c == char.init); + assert(t5.i == int.init); + assert(isNaN(t5.d)); +} +--- + +$(P +As you would remember from the $(LINK2 floating_point.html, Floating Point Types chapter), the initial value of $(C double) is $(C double.nan). Since the $(C .nan) value is $(I unordered), it is meaningless to use it in equality comparisons. That is why calling $(C std.math.isNaN) is the correct way of determining whether a value equals to $(C .nan). +) + +$(H6 $(IX default value, member) Specifying default values for members) + +$(P +It is important that member variables are automatically initialized with known initial values. This prevents the program from continuing with indeterminate values. However, the $(C .init) value of their respective types may not be suitable for every type. For example, $(C char.init) is not even a valid value. +) + +$(P +The initial values of the members of a struct can be specified when the struct is defined. This is useful for example to initialize floating point members by $(C 0.0), instead of the mostly-unusable $(C .nan). +) + +$(P +The default values are specified by the assignment syntax as the members are defined: +) + +--- +struct Test { + char c $(HILITE = 'A'); + int i $(HILITE = 11); + double d $(HILITE = 0.25); +} +--- + +$(P +Please note that the syntax above is not really assignment. The code above merely determines the default values that will be used when objects of that struct are actually constructed later in the program. +) + +$(P +For example, the following $(C Test) object is being constructed without any specific values: +) + +--- + Test t; // no value is specified for the members + writefln("%s,%s,%s", t.c, t.i, t.d); +--- + +$(P +All of the members are initialized by their default values: +) + +$(SHELL +A,11,0.25 +) + +$(H6 $(IX {}, construction) $(IX C-style struct initialization) Constructing by the $(C {}) syntax) + +$(P +Struct objects can also be constructed by the following syntax: +) + +--- + TimeOfDay periodStart = { 8, 30 }; +--- + +$(P +Similar to the earlier syntax, the specified values are assigned to the members in the order that they are specified. The trailing members get their default values. +) + +$(P +This syntax is inherited from the C programming language: +) + +--- + auto periodStart = TimeOfDay(8, 30); // ← regular + TimeOfDay periodEnd = { 9, 30 }; // ← C-style +--- + +$(P +$(IX designated initializer) This syntax allows $(I designated initializers). Designated initializers are for specifying the member that an initialization value is associated with. It is even possible to initialize members in a different order than they are defined in the $(C struct): +) + +--- + TimeOfDay t = { $(HILITE minute:) 42, $(HILITE hour:) 7 }; +--- + +$(H5 $(IX copy, struct) $(IX assignment, struct) Copying and assignment) + +$(P +Structs are value types. As has been described in the $(LINK2 value_vs_reference.html, Value Types and Reference Types chapter), this means that every $(C struct) object has its own value. Objects get their own values when constructed, and their values change when they are assigned new values. +) + +--- + auto yourLunchTime = TimeOfDay(12, 0); + auto myLunchTime = yourLunchTime; + + // Only my lunch time becomes 12:05: + myLunchTime.minute += 5; + + // ... your lunch time is still the same: + assert(yourLunchTime.minute == 0); +--- + +$(P +During a copy, all of the members of the source object are automatically copied to the corresponding members of the destination object. Similarly, assignment involves assigning each member of the source to the corresponding member of the destination. +) + +$(P +Struct members that are of reference types need extra attention. +) + +$(H6 $(IX reference type, member) Careful with members that are of reference types!) + +$(P +As you remember, copying or assigning variables of reference types does not change any value, it changes what object is being referenced. As a result, copying or assigning generates one more reference to the right-hand side object. The relevance of this for struct members is that, the members of two separate struct objects would start providing access to the same value. +) + +$(P +To see an example of this, let's have a look at a struct where one of the members is a reference type. This struct is used for keeping the student number and the grades of a student: +) + +--- +struct Student { + int number; + int[] grades; +} +--- + +$(P +The following code constructs a second $(C Student) object by copying an existing one: +) + +--- + // Constructing the first object: + auto student1 = Student(1, [ 70, 90, 85 ]); + + // Constructing the second student as a copy of the first + // one and then changing its number: + auto student2 = student1; + student2.number = 2; + + // WARNING: The grades are now being shared by the two objects! + + // Changing the grades of the first student ... + student1.grades[0] += 5; + + // ... affects the second student as well: + writeln(student2.grades[0]); +--- + +$(P +When $(C student2) is constructed, its members get the values of the members of $(C student1). Since $(C int) is a value type, the second object gets its own $(C number) value. +) + +$(P +The two $(C Student) objects also have individual $(C grades) members as well. However, since slices are reference types, the actual elements that the two slices share are the same. Consequently, a change made through one of the slices is seen through the other slice. +) + +$(P +The output of the code indicates that the grade of the second student has been increased as well: +) + +$(SHELL +75 +) + +$(P +For that reason, a better approach might be to construct the second object by the copies of the grades of the first one: +) + +--- + // The second Student is being constructed by the copies + // of the grades of the first one: + auto student2 = Student(2, student1.grades$(HILITE .dup)); + + // Changing the grades of the first student ... + student1.grades[0] += 5; + + // ... does not affect the grades of the second student: + writeln(student2.grades[0]); +--- + +$(P +Since the grades have been copied by $(C .dup), this time the grades of the second student are not affected: +) + +$(SHELL +70 +) + +$(P +$(I Note: It is possible to have even the reference members copied automatically. We will see how this is done later when covering struct member functions.) +) + +$(H5 $(IX literal, struct) Struct literals) + +$(P +Similar to being able to use integer literal values like 10 in expressions without needing to define a variable, struct objects can be used as literals as well. +) + +$(P +Struct literals are constructed by the object construction syntax. +) + +--- + TimeOfDay(8, 30) // ← struct literal value +--- + +$(P +Let's first rewrite the $(C main()) function above with what we have learned since its last version. The variables are constructed by the construction syntax and are $(C immutable) this time: +) + +--- +$(CODE_XREF TimeOfDay)$(CODE_XREF addDuration)void main() { + immutable periodStart = TimeOfDay(8, 30); + immutable periodDuration = TimeOfDay(1, 15); + + immutable periodEnd = addDuration(periodStart, + periodDuration); + + writefln("Period end: %s:%s", + periodEnd.hour, periodEnd.minute); +} +--- + +$(P +Note that $(C periodStart) and $(C periodDuration) need not be defined as named variables in the code above. Those are in fact temporary variables in this simple program, which are used only for calculating the $(C periodEnd) variable. They could be passed to $(C addDuration()) as literal values instead: +) + +--- +$(CODE_XREF TimeOfDay)$(CODE_XREF addDuration)void main() { + immutable periodEnd = addDuration(TimeOfDay(8, 30), + TimeOfDay(1, 15)); + + writefln("Period end: %s:%s", + periodEnd.hour, periodEnd.minute); +} +--- + +$(H5 $(IX static, member) $(C static) members) + +$(P +Although objects mostly need individual copies of the struct's members, sometimes it makes sense for the objects of a particular struct type to share some variables. This may be necessary to maintain e.g. a general information about that struct type. +) + +$(P +As an example, let's imagine a type that assigns a separate identifier for every object that is constructed of that type: +) + +--- +struct Point { + // The identifier of each object + size_t id; + + int line; + int column; +} +--- + +$(P +In order to be able to assign different ids to each object, a separate variable is needed to keep the next available id. It would be incremented every time a new object is created. Assume that $(C nextId) is to be defined elsewhere and to be available in the following function: +) + +--- +Point makePoint(int line, int column) { + size_t id = nextId; + ++nextId; + + return Point(id, line, column); +} +--- + +$(P +A decision must be made regarding where the common $(C nextId) variable is to be defined. $(C static) members are useful in such cases. +) + +$(P +Such common information is defined as a $(C static) member of the struct. Contrary to the regular members, there is a single variable of each $(C static) member for each thread. (Note that most programs consist of a single thread that starts executing the $(C main()) function.) That single variable is shared by all of the objects of that struct in that thread: +) + +--- +import std.stdio; + +struct Point { + // The identifier of each object + size_t id; + + int line; + int column; + + // The id of the next object to construct + $(HILITE static size_t nextId;) +} + +Point makePoint(int line, int column) { + size_t id = $(HILITE Point.)nextId; + ++$(HILITE Point.)nextId; + + return Point(id, line, column); +} + +void main() { + auto top = makePoint(7, 0); + auto middle = makePoint(8, 0); + auto bottom = makePoint(9, 0); + + writeln(top.id); + writeln(middle.id); + writeln(bottom.id); +} +--- + +$(P +As $(C nextId) is incremented at each object construction, each object gets a unique id: +) + +$(SHELL +0 +1 +2 +) + +$(P +Since $(C static) members are owned by the entire type, there need not be an object to access them. As we have seen above, such objects can be accessed by the name of the type, as well as by the name of any object of that struct: +) + +--- + ++Point.nextId; + ++$(HILITE bottom).nextId; // would be the same as above +--- + +$(P +When a variable is needed not $(I one per thread) but $(I one per program), then those variables must be defined as $(C shared static). We will see the $(C shared) keyword in a later chapter. +) + +$(H6 $(IX static this, struct) $(IX static ~this, struct) $(IX this, static, struct) $(IX ~this, static, struct) $(C static this()) for initialization and $(C static ~this()) for finalization) + +$(P +Instead of explicitly assigning an initial value to $(C nextId) above, we relied on its default initial value, zero. We could have used any other value: +) + +--- + static size_t nextId $(HILITE = 1000); +--- + +$(P +However, such initialization is possible only when the initial value is known at compile time. Further, some special code may have to be executed before a struct can be used in a thread. Such code is written in $(C static this()) scopes. +) + +$(P +For example, the following code reads the initial value from a file if that file exists: +) + +--- +import std.file; + +struct Point { +// ... + + enum nextIdFile = "Point_next_id_file"; + + $(HILITE static this()) { + if (exists(nextIdFile)) { + auto file = File(nextIdFile, "r"); + file.readf(" %s", &nextId); + } + } +} +--- + +$(P +The contents of $(C static this()) blocks are automatically executed once per thread before the $(C struct) type is ever used in that thread. Code that should be executed only once for the entire program (e.g. initializing $(C shared) and $(C immutable) variables) must be defined in $(C shared static this()) and $(C shared static ~this()) blocks, which will be covered in $(LINK2 concurrency_shared.html, the Data Sharing Concurrency chapter). +) + +$(P +Similarly, $(C static ~this()) is for the final operations of a thread and $(C shared static ~this()) is for the final operations of the entire program. +) + +$(P +The following example complements the previous $(C static this()) by writing the value of $(C nextId) to the same file, effectively persisting the object ids over consecutive executions of the program: +) + +--- +struct Point { +// ... + + $(HILITE static ~this()) { + auto file = File(nextIdFile, "w"); + file.writeln(nextId); + } +} +--- + +$(P +The program would now initialize $(C nextId) from where it was left off. For example, the following would be the output of the program's second execution: +) + +$(SHELL +3 +4 +5 +) + +$(PROBLEM_COK + +$(PROBLEM +Design a struct named $(C Card) to represent a playing card. + +$(P +This struct can have two members for the suit and the value. It may make sense to use an $(C enum) to represent the suit, or you can simply use the characters ♠, ♡, ♢, and ♣. +) + +$(P +An $(C int) or a $(C dchar) value can be used for the card value. If you decide to use an $(C int), the values 1, 11, 12, and 13 may represent the cards that do not have numbers (ace, jack, queen, and king). +) + +$(P +There are other design choices to make. For example, the card values can be represented by an $(C enum) type as well. +) + +$(P +The way objects of this struct will be constructed will depend on the choice of the types of its members. For example, if both members are $(C dchar), then $(C Card) objects can be constructed like this: +) + +--- + auto card = Card('♣', '2'); +--- + +) + +$(PROBLEM +Define a function named $(C printCard()), which takes a $(C Card) object as a parameter and simply prints it: + +--- +struct Card { + // ... please define the struct ... +} + +void printCard(Card card) { + // ... please define the function body ... +} + +void main() { + auto card = Card(/* ... */); + printCard(card); +} +--- + +$(P +For example, the function can print the 2 of clubs as: +) + +$(SHELL +♣2 +) + +$(P +The implementation of that function may depend on the choice of the types of the members. +) + +) + +$(PROBLEM +Define a function named $(C newDeck()) and have it return 52 cards of a deck as a $(C Card) slice: + +--- +Card[] newDeck() +out (result) { + assert(result.length == 52); + +} do { + // ... please define the function body ... +} +--- + +$(P +It should be possible to call $(C newDeck()) as in the following code: +) + +--- + Card[] deck = newDeck(); + + foreach (card; deck) { + printCard(card); + write(' '); + } + + writeln(); +--- + +$(P +The output should be similar to the following with 52 distinct cards: +) + +$(SHELL +♠2 ♠3 ♠4 ♠5 ♠6 ♠7 ♠8 ♠9 ♠0 ♠J ♠Q ♠K ♠A ♡2 ♡3 ♡4 +♡5 ♡6 ♡7 ♡8 ♡9 ♡0 ♡J ♡Q ♡K ♡A ♢2 ♢3 ♢4 ♢5 ♢6 ♢7 +♢8 ♢9 ♢0 ♢J ♢Q ♢K ♢A ♣2 ♣3 ♣4 ♣5 ♣6 ♣7 ♣8 ♣9 ♣0 +♣J ♣Q ♣K ♣A +) + +) + +$(PROBLEM +Write a function that shuffles the deck. One way is to pick two cards at random by $(C std.random.uniform), to swap those two cards, and to repeat this process a sufficient number of times. The function should take the number of repetition as a parameter: + +--- +void shuffle(Card[] deck, int repetition) { + // ... please define the function body ... +} +--- + +$(P +Here is how it should be used: +) + +--- + Card[] deck = newDeck(); + shuffle(deck, 1); + + foreach (card; deck) { + printCard(card); + write(' '); + } + + writeln(); +--- + +$(P +The function should swap cards $(C repetition) number of times. For example, when called by 1, the output should be similar to the following: +) + +$(SHELL +♠2 ♠3 ♠4 ♠5 ♠6 ♠7 ♠8 ♠9 ♠0 ♠J ♠Q ♠K ♠A ♡2 ♡3 ♡4 +♡5 ♡6 ♡7 ♡8 $(HILITE ♣4) ♡0 ♡J ♡Q ♡K ♡A ♢2 ♢3 ♢4 ♢5 ♢6 ♢7 +♢8 ♢9 ♢0 ♢J ♢Q ♢K ♢A ♣2 ♣3 $(HILITE ♡9) ♣5 ♣6 ♣7 ♣8 ♣9 ♣0 +♣J ♣Q ♣K ♣A +) + +$(P +A higher value for $(C repetition) should result in a more shuffled deck: +) + +--- + shuffled(deck, $(HILITE 100)); +--- + +$(P +The output: +) + +$(SHELL +♠4 ♣7 ♢9 ♢6 ♡2 ♠6 ♣6 ♢A ♣5 ♢8 ♢3 ♡Q ♢J ♣K ♣8 ♣4 +♡J ♣Q ♠Q ♠9 ♢0 ♡A ♠A ♡9 ♠7 ♡3 ♢K ♢2 ♡0 ♠J ♢7 ♡7 +♠8 ♡4 ♣J ♢4 ♣0 ♡6 ♢5 ♡5 ♡K ♠3 ♢Q ♠2 ♠5 ♣2 ♡8 ♣A +♠K ♣9 ♠0 ♣3 +) + +$(P +$(I $(B Note:) A much better way of shuffling the deck is explained in the solutions.) +) + +) + +) + +Macros: + TITLE=Structs + + DESCRIPTION=The 'struct' feature of the D programming language, which is used for defining user types. + + KEYWORDS=d programming book tutorial struct diff --git a/book/d.en/switch_case.cozum.d b/book/d.en/switch_case.cozum.d new file mode 100644 index 0000000000..2454f39c06 --- /dev/null +++ b/book/d.en/switch_case.cozum.d @@ -0,0 +1,103 @@ +Ddoc + +$(COZUM_BOLUMU $(C switch) and $(C case)) + +$(OL + +$(LI + +--- +import std.stdio; +import std.string; + +void main() { + string op; + double first; + double second; + + write("Please enter the operation: "); + op = strip(readln()); + + write("Please enter two values separated by a space: "); + readf(" %s %s", &first, &second); + + double result; + + final switch (op) { + + case "add": + result = first + second; + break; + + case "subtract": + result = first - second; + break; + + case "multiply": + result = first * second; + break; + + case "divide": + result = first / second; + break; + } + + writeln(result); +} +--- + +) + +$(LI +By taking advantage of distinct $(C case) values: + +--- + final switch (op) { + + case "add"$(HILITE , "+"): + result = first + second; + break; + + case "subtract"$(HILITE, "-"): + result = first - second; + break; + + case "multiply"$(HILITE, "*"): + result = first * second; + break; + + case "divide"$(HILITE, "/"): + result = first / second; + break; + } +--- + +) + +$(LI Since the $(C default) section is needed to throw the exception from, it cannot be a $(C final switch) statement anymore. Here are the parts of the program that are modified: + +--- +// ... + + switch (op) { + + // ... + + default: + throw new Exception("Invalid operation: " ~ op); + } + +// ... +--- + +) + +) + +Macros: + TITLE=switch and case Solutions + + DESCRIPTION=Programming in D exercise solutions: the switch statement + + KEYWORDS=programming in d tutorial switch case + diff --git a/book/d.en/switch_case.d b/book/d.en/switch_case.d new file mode 100644 index 0000000000..9f44458700 --- /dev/null +++ b/book/d.en/switch_case.d @@ -0,0 +1,361 @@ +Ddoc + +$(DERS_BOLUMU $(IX switch) $(IX case) $(CH4 switch) and $(CH4 case)) + +$(P +$(C switch) is a statement that allows comparing the value of an expression against multiple values. It is similar to but not the same as an "if, else if, else" chain. $(C case) is used for specifying the values that are to be compared with $(C switch)'s expression. $(C case) is a part of the $(C switch) statement, not a statement itself. +) + +$(P +$(C switch) takes an expression within parentheses, compares the value of that expression to the $(C case) values, and executes the operations of the $(C case) that is equal to the value of the expression. Its syntax consists of a $(C switch) block that contains one or more $(C case) sections and a $(C default) section: +) + +--- + switch ($(I expression)) { + + case $(I value_1): + // operations to execute if the expression is equal to value_1 + // ... + break; + + case $(I value_2): + // operations to execute if the expression is equal to value_2 + // ... + break; + + // ... other cases ... + + default: + // operations to execute if the expression is not equal to any case + // ... + break; + } +--- + +$(P +The expression that $(C switch) takes is not used directly as a logical expression. It is not evaluated as "if this condition is true", as it would be in an $(C if) statement. The $(I value) of the $(C switch) expression is used in equality comparisons with the $(C case) values. It is similar to an "if, else if, else" chain that has only equality comparisons: +) + +--- + auto value = $(I expression); + + if (value == $(I value_1)) { + // operations for value_1 + // ... + + } else if (value == $(I value_2)) { + // operations for value_2 + // ... + } + + // ... other 'else if's ... + + } else { + // operations for other values + // ... + } +--- + +$(P +However, the "if, else if, else" above is not an exact equivalent of the $(C switch) statement. The reasons why will be explained in the following sections. +) + +$(P +If a $(C case) value matches the value of the $(C switch) expression, then the operations that are under the $(C case) are executed. If no value matches, then the operations that are under the $(C default) are executed. +) + +$(H5 $(IX goto case) $(IX goto default) The $(C goto) statement) + +$(P +The use of $(C goto) is generally advised against in most programming languages. However, $(C goto) is useful in $(C switch) statements in some situations, without being as problematic as in other uses. The $(C goto) statement will be covered in more detail in $(LINK2 goto.html, a later chapter). +) + +$(P +$(C case) does not introduce a $(I scope) as the $(C if) statement does. Once the operations within an $(C if) or $(C else) scope are finished the evaluation of the entire $(C if) statement is also finished. That does not happen with the $(C case) sections; once a matching $(C case) is found, the execution of the program jumps to that $(C case) and executes the operations under it. When needed in rare situations, $(C goto case) makes the program execution jump to the next $(C case): +) + +--- + switch (value) { + + case 5: + writeln("five"); + $(HILITE goto case); // continues to the next case + + case 4: + writeln("four"); + break; + + default: + writeln("unknown"); + break; + } +--- + +$(P +If $(C value) is 5, the execution continues under the $(C case 5) line and the program prints "five". Then the $(C goto case) statement causes the execution to continue to the next $(C case), and as a result "four" is also printed: +) + +$(SHELL +five +four +) + +$(P +$(C goto) can appear in three ways under $(C case) sections: +) + +$(UL + +$(LI $(IX fallthrough, case) $(C goto case) causes the execution to continue (fallthrough) to the next $(C case).) + +$(LI $(C goto default) causes the execution to continue to the $(C default) section.) + +$(LI $(C goto case $(I expression)) causes the execution to continue to the $(C case) that matches that expression.) + +) + +$(P +The following program demonstrates these three uses by taking advantage of a $(C foreach) loop: +) + +--- +import std.stdio; + +void main() { + foreach (value; [ 1, 2, 3, 10, 20 ]) { + writefln("-- value: %s --", value); + + switch (value) { + + case 1: + writeln("case 1"); + $(HILITE goto case); + + case 2: + writeln("case 2"); + $(HILITE goto case 10); + + case 3: + writeln("case 3"); + $(HILITE goto default); + + case 10: + writeln("case 10"); + break; + + default: + writeln("default"); + break; + } + } +} +--- + +$(P +The output: +) + +$(SHELL +-- value: 1 -- +case 1 +case 2 +case 10 +-- value: 2 -- +case 2 +case 10 +-- value: 3 -- +case 3 +default +-- value: 10 -- +case 10 +-- value: 20 -- +default +) + +$(H5 The expression must be an integer, string, or $(C bool) type) + +$(P +Any type can be used in equality comparisons in $(C if) statements. On the other hand, the type of the $(C switch) expression is limited to all integer types, all string types, and $(C bool). +) + +--- + string op = /* ... */; + // ... + switch (op) { + + case "add": + result = first + second; + break; + + case "subtract": + result = first - second; + break; + + case "multiply": + result = first * second; + break; + + case "divide": + result = first / second; + break; + + default: + throw new Exception(format("Unknown operation: %s", op)); + } +--- + +$(P +$(I $(B Note:) The code above throws an exception when the operation is not recognized by the program. We will see exceptions in $(LINK2 exceptions.html, a later chapter).) +) + +$(P +Although it is possible to use $(C bool) expressions as well, because $(C bool) has only two values it may be more suitable to use an $(C if) statement or the ternary operator ($(C ?:)) with that type. +) + +$(H5 $(IX .., case value range) $(IX range, case) Value ranges) + +$(P +Ranges of values can be specified by $(C ..) between $(C case)s: +) + +--- + switch (dieValue) { + + case 1: + writeln("You won"); + break; + + case 2: $(HILITE ..) case 5: + writeln("It's a draw"); + break; + + case 6: + writeln("I won"); + break; + + default: + /* The program should never get here because the cases + * above cover the entire range of valid die values. + * (See 'final switch' below.) */ + break; + } +--- + +$(P +The code above determines that the game ends in a draw when the die value is 2, 3, 4, or 5. +) + +$(H5 Distinct values) + +$(P +$(IX , (comma), case value list) Let's assume that it is a draw for the values 2 and 4, rather than for the values that are in the range [2, 5]. Distinct values of a $(C case) are separated by commas: +) + +--- + case 2$(HILITE ,) 4: + writeln("It's a draw"); + break; +--- + +$(H5 $(IX final switch) The $(C final switch) statement) + +$(P +The $(C final switch) statement works similarly to the regular $(C switch) statement, with the following differences: +) + +$(UL +$(LI It cannot have a $(C default) section. Note that this section is meaningless when the $(C case) sections cover the entire range of values anyway, as has been with the six values of the die above. +) + +$(LI Value ranges cannot be used with $(C case)s (distinct values can be). +) + +$(LI If the expression is of an $(C enum) type, all of the values of the type must be covered by the $(C case)s (we will see $(C enum) types in the next chapter). +) + +) + +--- + int dieValue = 1; + + final switch (dieValue) { + + case 1: + writeln("You won"); + break; + + case 2, 3, 4, 5: + writeln("It's a draw"); + break; + + case 6: + writeln("I won"); + break; + } +--- + +$(H5 When to use) + +$(P +$(C switch) is suitable for comparing the value of an expression against a set of values that are known at compile time. +) + +$(P +When there are only two values to compare, an $(C if) statement may make more sense. For example, to check whether it is heads or tails: +) + +```d + if (headsTailsResult == heads) { + // ... + + } else { + // ... + } +``` + +$(P +As a general rule, $(C switch) is more suitable when there are three or more values to compare. +) + +$(P +When all of the values need to be handled, then prefer $(C final switch). This is especially the case for $(C enum) types. +) + +$(PROBLEM_COK + +$(PROBLEM +Write a calculator program that supports arithmetic operations. Have the program first read the operation as a $(C string), then two values of type $(C double) from the input. The calculator should print the result of the operation. For example, when the operation and values are "add" and "5 7", respectively, the program should print 12. + +$(P +The input can be read as in the following code: +) + +```d + string op; + double first; + double second; + + // ... + + op = strip(readln()); + readf(" %s %s", &first, &second); +``` + +) + +$(PROBLEM +Improve the calculator to support operators like "+" in addition to words like "add". +) + +$(PROBLEM +Have the program throw an exception for unknown operators. We will cover exceptions in $(LINK2 exceptions.html, a later chapter). For now, adapt the $(C throw) statement used above to your program. +) + +) + +Macros: + TITLE=switch and case + + DESCRIPTION=The switch-case statement that is used for comparing the value of an expression against multiple values. + + KEYWORDS=d programming language tutorial book switch case diff --git a/book/d.en/templates.d b/book/d.en/templates.d new file mode 100644 index 0000000000..dc05d14ba7 --- /dev/null +++ b/book/d.en/templates.d @@ -0,0 +1,1100 @@ +Ddoc + +$(DERS_BOLUMU $(IX template) Templates) + +$(P +Templates are the feature that allows describing the code as a pattern, for the compiler to generate program code automatically. Parts of the source code may be left to the compiler to be filled in until that part is actually used in the program. +) + +$(P +Templates are very useful especially in libraries because they enable writing generic algorithms and data structures, instead of tying them to specific types. +) + +$(P +Compared to the template supports in other languages, D's templates are very powerful and extensive. I will not get into all of the details of templates in this chapter. I will cover only function, struct, and class templates and only $(I type) template parameters. We will see more about templates in $(LINK2 templates_more.html, the More Templates chapter). For a complete reference on D templates, see $(LINK2 https://github.com/PhilippeSigaud/D-templates-tutorial, Philippe Sigaud's $(I D Templates: A Tutorial)). +) + +$(P +To see the benefits of templates let's start with a function that prints values in parentheses: +) + +--- +void printInParens(int value) { + writefln("(%s)", value); +} +--- + +$(P +Because the parameter is specified as $(C int), that function can only be used with values of type $(C int), or values that can automatically be converted to $(C int). For example, the compiler would not allow calling it with a floating point type. +) + +$(P +Let's assume that the requirements of a program changes and that other types need to be printed in parentheses as well. One of the solutions for this would be to take advantage of function overloading and provide overloads of the function for all of the types that the function is used with: +) + +--- +// The function that already exists +void printInParens(int value) { + writefln("(%s)", value); +} + +// Overloading the function for 'double' +void printInParens($(HILITE double) value) { + writefln("(%s)", value); +} +--- + +$(P +This solution does not scale well because this time the function cannot be used with e.g. $(C real) or any user-defined type. Although it is possible to overload the function for other types, the cost of doing this may be prohibitive. +) + +$(P +An important observation here is that regardless of the type of the parameter, the contents of the overloads would all be $(I generically) the same: a single $(C writefln()) expression. +) + +$(P +Such genericity is common in algorithms and data structures. For example, the binary search algorithm is independent of the type of the elements: It is about the specific steps and operations of the search. Similarly, the linked list data structure is independent of the type of the elements: Linked list is merely about $(I how) the elements are stored in the container, regardless of their type. +) + +$(P +Templates are useful in such situations: Once a piece of code is described as a template, the compiler generates overloads of the same code automatically according to the actual uses of that code in the program. +) + +$(P +As I have mentioned above, in this chapter I will cover only function, struct, and class templates, and $(I type) template parameters. +) + +$(H5 $(IX function template) Function templates) + +$(P +$(IX parameter, template) Defining a function as a template is leaving one or more of the types that it uses as unspecified, to be deduced later by the compiler. +) + +$(P +The types that are being left unspecified are defined within the template parameter list, which comes between the name of the function and the function parameter list. For that reason, function templates have two parameter lists: the template parameter list and the function parameter list: +) + +--- +void printInParens$(HILITE (T))(T value) { + writefln("(%s)", value); +} +--- + +$(P +The $(C T) within the template parameter list above means that $(C T) can be any type. Although $(C T) is an arbitrary name, it is an acronym for "type" and is very common in templates. +) + +$(P +Since $(C T) represents any type, the templated definition of $(C printInParens()) above is sufficient to use it with almost every type, including the user-defined ones: +) + +--- +import std.stdio; + +void printInParens(T)(T value) { + writefln("(%s)", value); +} + +void main() { + printInParens(42); // with int + printInParens(1.2); // with double + + auto myValue = MyStruct(); + printInParens(myValue); // with MyStruct +} + +struct MyStruct { + string toString() const { + return "hello"; + } +} +--- + +$(P +The compiler considers all of the uses of $(C printInParens()) in the program and generates code to support all those uses. The program is then compiled as if the function has been overloaded explicitly for $(C int), $(C double), and $(C MyStruct): +) + +$(MONO +/* Note: These functions are not part of the source + * code. They are the equivalents of the functions that + * the compiler would automatically generate. */ + +void printInParens($(HILITE int) value) { + writefln("(%s)", value); +} + +void printInParens($(HILITE double) value) { + writefln("(%s)", value); +} + +void printInParens($(HILITE MyStruct) value) { + writefln("(%s)", value); +} +) + +$(P +The output of the program is produced by those different $(I instantiations) of the function template: +) + +$(SHELL +(42) +(1.2) +(hello) +) + +$(P +Each template parameter can determine more than one function parameter. For example, both the two function parameters and the return type of the following function template are determined by its single template parameter: +) + +--- +/* Returns a copy of 'slice' except the elements that are + * equal to 'value'. */ +$(HILITE T)[] removed(T)(const($(HILITE T))[] slice, $(HILITE T) value) { + T[] result; + + foreach (element; slice) { + if (element != value) { + result ~= element; + } + } + + return result; +} +--- + +$(H5 More than one template parameter) + +$(P +Let's change the function template to take the parentheses characters as well: +) + +--- +void printInParens(T)(T value, char opening, char closing) { + writeln(opening, value, closing); +} +--- + +$(P +Now we can call the same function with different sets of parentheses: +) + +--- + printInParens(42, '<', '>'); +--- + +$(P +Although being able to specify the parentheses makes the function more usable, specifying the type of the parentheses as $(C char) makes it less flexible because it is not possible to call the function with characters of type $(C wchar) or $(C dchar): +) + +--- + printInParens(42, '→', '←'); $(DERLEME_HATASI) +--- + +$(SHELL_SMALL +Error: template deneme.printInParens(T) cannot deduce +template function from argument types !()(int,$(HILITE wchar),$(HILITE wchar)) +) + +$(P +One solution would be to specify the type of the parentheses as $(C dchar) but this would still be insufficient as this time the function could not be called e.g. with $(C string) or user-defined types. +) + +$(P +$(IX , (comma), template parameter list) Another solution is to leave the type of the parentheses to the compiler as well. Defining an additional template parameter instead of the specific $(C char) is sufficient: +) + +--- +void printInParens(T$(HILITE , ParensType))(T value, + $(HILITE ParensType) opening, + $(HILITE ParensType) closing) { + writeln(opening, value, closing); +} +--- + +$(P +The meaning of the new template parameter is similar to $(C T)'s: $(C ParensType) can be any type. +) + +$(P +It is now possible to use many different types of parentheses. The following are with $(C wchar) and $(C string): +) + +--- + printInParens(42, '→', '←'); + printInParens(1.2, "-=", "=-"); +--- + +$(SHELL +→42← +-=1.2=- +) + +$(P +The flexibility of $(C printInParens()) has been increased, as it now works correctly for any combination of $(C T) and $(C ParensType) as long as those types are printable with $(C writeln()). +) + +$(H5 $(IX type deduction) $(IX deduction, type) Type deduction) + +$(P +The compiler's deciding on what type to use for a template parameter is called $(I type deduction). +) + +$(P +Continuing from the last example above, the compiler decides on the following types according to the two uses of the function template: +) + +$(UL +$(LI $(C int) and $(C wchar) when 42 is printed) +$(LI $(C double) and $(C string) when 1.2 is printed) +) + +$(P +The compiler can deduce types only from the types of the parameter values that are passed to function templates. Although the compiler can usually deduce the types without any ambiguity, there are times when the types must be specified explicitly by the programmer. +) + +$(H5 Explicit type specification) + +$(P +Sometimes it is not possible for the compiler to deduce the template parameters. A situation that this can happen is when the types do not appear in the function parameter list. When template parameters are not related to function parameters, the compiler cannot deduce the template parameter types. +) + +$(P +To see an example of this, let's design a function that asks a question to the user, reads a value as a response, and returns that value. Additionally, let's make this a function template so that it can be used to read any type of response: +) + +--- +$(HILITE T) getResponse$(HILITE (T))(string question) { + writef("%s (%s): ", question, T.stringof); + + $(HILITE T) response; + readf(" %s", &response); + + return response; +} +--- + +$(P +That function template would be very useful in programs to read different types of values from the input. For example, to read some user information, we can imagine calling it as in the following line: +) + +--- + getResponse("What is your age?"); +--- + +$(P +Unfortunately, that call does not give the compiler any clue as to what the template parameter $(C T) should be. What is known is that the question is passed to the function as a $(C string), but the type of the return value cannot be deduced: +) + +$(SHELL_SMALL +Error: template deneme.getResponse(T) $(HILITE cannot deduce) template +function from argument types !()(string) +) + +$(P +$(IX !, template instance) In such cases, the template parameters must be specified explicitly by the programmer. Template parameters are specified in parentheses after an exclamation mark: +) + +--- + getResponse$(HILITE !(int))("What is your age?"); +--- + +$(P +The code above can now be accepted by the compiler and the function template is compiled as $(C T) being an alias of $(C int) within the definition of the template. +) + +$(P +When there is only one template parameter specified, the parentheses around it are optional: +) + +--- + getResponse$(HILITE !int)("What is your age?"); // same as above +--- + +$(P +You may recognize that syntax from $(C to!string), which we have been using in earlier programs. $(C to()) is a function template, which takes the target type of the conversion as a template parameter. Since it has only one template parameter that needs to be specified, it is commonly written as $(C to!string) instead of $(C to!(string)). +) + +$(H5 $(IX instantiation, template) Template instantiation) + +$(P +Automatic generation of code for a specific set of template parameter values is called an $(I instantiation) of that template for that specific set of parameter values. For example, $(C to!string) and $(C to!int) are two different instantiations of the $(C to) function template. +) + +$(P +As I will mention again in a separate section below, distinct instantiations of templates produce distinct and incompatible types. +) + +$(H5 $(IX specialization, template) Template specializations) + +$(P +Although the $(C getResponse()) function template can in theory be used for any template type, the code that the compiler generates may not be suitable for every type. Let's assume that we have the following type that represents points on a two dimensional space: +) + +--- +struct Point { + int x; + int y; +} +--- + +$(P +Although the instantiation of $(C getResponse()) for the $(C Point) type itself would be fine, the generated $(C readf()) call for $(C Point) cannot be compiled. This is because the standard library function $(C readf()) does not know how to read a $(C Point) object. The two lines that actually read the response would look like the following in the $(C Point) instantiation of the $(C getResponse()) function template: +) + +--- + Point response; + readf(" %s", &response); $(DERLEME_HATASI) +--- + +$(P +One way of reading a $(C Point) object would be to read the values of the $(C x) and $(C y) members separately and then to $(I construct) a $(C Point) object from those values. +) + +$(P +Providing a special definition of a template for a specific template parameter value is called a $(I template specialization). The specialization is defined by the type name after a $(C :) character in the template parameter list. A $(C Point) specialization of the $(C getResponse()) function template can be defined as in the following code: +) + +--- +// The general definition of the function template (same as before) +T getResponse(T)(string question) { + writef("%s (%s): ", question, T.stringof); + + T response; + readf(" %s", &response); + + return response; +} + +// The specialization of the function template for Point +T getResponse(T $(HILITE : Point))(string question) { + writefln("%s (Point)", question); + + auto x = getResponse!int(" x"); + auto y = getResponse!int(" y"); + + return Point(x, y); +} +--- + +$(P +Note that the specialization takes advantage of the general definition of $(C getResponse()) to read two $(C int) values to be used as the values of the $(C x) and $(C y) members. +) + +$(P +Instead of instantiating the template itself, now the compiler uses the specialization above whenever $(C getResponse()) is called for the $(C Point) type: +) + +--- + auto center = getResponse!Point("Where is the center?"); +--- + +$(P +Assuming that the user enters 11 and 22: +) + +$(SHELL_SMALL +Where is the center? (Point) + x (int): 11 + y (int): 22 +) + +$(P +The $(C getResponse!int()) calls are directed to the general definition of the template and the $(C getResponse!Point()) calls are directed to the $(C Point) specialization of it. +) + +$(P +As another example, let's consider using the same template with $(C string). As you would remember from the $(LINK2 strings.html, Strings chapter), $(C readf()) would read all of the characters from the input as part of a single $(C string) until the end of the input. For that reason, the default definition of $(C getResponse()) would not be useful when reading $(C string) responses: +) + +--- + // Reads the entire input, not only the name! + auto name = getResponse!string("What is your name?"); +--- + +$(P +We can provide a template specialization for $(C string) as well. The following specialization reads just the $(I line) instead: +) + +--- +T getResponse(T $(HILITE : string))(string question) { + writef("%s (string): ", question); + + // Read and ignore whitespace characters which have + // presumably been left over from the previous user input + string response; + do { + response = strip(readln()); + } while (response.length == 0); + + return response; +} +--- + +$(H5 $(IX struct template) $(IX class template) Struct and class templates) + +$(P +The $(C Point) struct may be seen as having a limitation: Because its two members are defined specifically as $(C int), it cannot represent fractional coordinate values. This limitation can be removed if the $(C Point) struct is defined as a template. +) + +$(P +Let's first add a member function that returns the distance to another $(C Point) object: +) + +--- +import std.math; + +// ... + +struct Point { + int x; + int y; + + int distanceTo(Point that) const { + immutable real xDistance = x - that.x; + immutable real yDistance = y - that.y; + + immutable distance = sqrt((xDistance * xDistance) + + (yDistance * yDistance)); + + return cast(int)distance; + } +} +--- + +$(P +That definition of $(C Point) is suitable when the required precision is relatively low: It can calculate the distance between two points at kilometer precision, e.g. between the center and branch offices of an organization: +) + +--- + auto center = getResponse!Point("Where is the center?"); + auto branch = getResponse!Point("Where is the branch?"); + + writeln("Distance: ", center.distanceTo(branch)); +--- + +$(P +Unfortunately, $(C Point) is inadequate at higher precisions than $(C int) can provide. +) + +$(P +Structs and classes can be defined as templates as well, by specifying a template parameter list after their names. For example, $(C Point) can be defined as a struct template by providing a template parameter and replacing the $(C int)s by that parameter: +) + +--- +struct Point$(HILITE (T)) { + $(HILITE T) x; + $(HILITE T) y; + + $(HILITE T) distanceTo(Point that) const { + immutable real xDistance = x - that.x; + immutable real yDistance = y - that.y; + + immutable distance = sqrt((xDistance * xDistance) + + (yDistance * yDistance)); + + return cast($(HILITE T))distance; + } +} +--- + +$(P +Since structs and classes are not functions, they cannot be called with parameters. This makes it impossible for the compiler to deduce their template parameters. The template parameter list must always be specified for struct and class templates: +) + +--- + auto center = Point$(HILITE !int)(0, 0); + auto branch = Point$(HILITE !int)(100, 100); + + writeln("Distance: ", center.distanceTo(branch)); +--- + +$(P +The definitions above make the compiler generate code for the $(C int) instantiation of the $(C Point) template, which is the equivalent of its earlier non-template definition. However, now it can be used with any type. For example, when more precision is needed, with $(C double): +) + +--- + auto point1 = Point$(HILITE !double)(1.2, 3.4); + auto point2 = Point$(HILITE !double)(5.6, 7.8); + + writeln(point1.distanceTo(point2)); +--- + +$(P +Although the template itself has been defined independently of any specific type, its single definition makes it possible to represent points of various precisions. +) + +$(P +Simply converting $(C Point) to a template would cause compilation errors in code that has already been written according to its non-template definition. For example, now the $(C Point) specialization of $(C getResponse()) cannot be compiled: +) + +--- +T getResponse(T : Point)(string question) { $(DERLEME_HATASI) + writefln("%s (Point)", question); + + auto x = getResponse!int(" x"); + auto y = getResponse!int(" y"); + + return Point(x, y); +} +--- + +$(P +The reason for the compilation error is that $(C Point) itself is not a type anymore: $(C Point) is now a $(I struct template). Only instantiations of that template would be considered as types. The following changes are required to correctly specialize $(C getResponse()) for any instantiation of $(C Point): +) + +--- +Point!T getResponse(T : Point!T)(string question) { // 2, 1 + writefln("%s (Point!%s)", question, T.stringof); // 5 + + auto x = getResponse!T(" x"); // 3a + auto y = getResponse!T(" y"); // 3b + + return Point!T(x, y); // 4 +} +--- + +$(OL + +$(LI +In order for this template specialization to support all instantiations of $(C Point), the template parameter list must mention $(C Point!T). This simply means that the $(C getResponse()) specialization is for $(C Point!T), regardless of $(C T). This specialization would match $(C Point!int), $(C Point!double), etc. +) + +$(LI +Similarly, to return the correct type as the response, the return type must be specified as $(C Point!T) as well. +) + +$(LI +Since the types of $(C x) and $(C y) members of $(C Point!T) are now $(C T), as opposed to $(C int), the members must be read by calling $(C getResponse!T()), not $(C getResponse!int()), as the latter would be correct only for $(C Point!int). +) + +$(LI +Similar to items 1 and 2, the type of the return value is $(C Point!T). +) + +$(LI +To print the name of the type accurately for every type, as in $(C Point!int), $(C Point!double), etc., $(C T.stringof) is used. +) + +) + +$(H5 $(IX default template parameter) Default template parameters) + +$(P +Sometimes it is cumbersome to provide template parameter types every time a template is used, especially when that type is almost always a particular type. For example, $(C getResponse()) may almost always be called for the $(C int) type in the program, and only in a few places for the $(C double) type. +) + +$(P +It is possible to specify default types for template parameters, which are assumed when the types are not explicitly provided. Default parameter types are specified after the $(C =) character: +) + +--- +T getResponse(T $(HILITE = int))(string question) { + // ... +} + +// ... + + auto age = getResponse("What is your age?"); +--- + +$(P +As no type has been specified when calling $(C getResponse()) above, $(C T) becomes the default type $(C int) and the call ends up being the equivalent of $(C getResponse!int()). +) + +$(P +Default template parameters can be specified for struct and class templates as well, but in their case the template parameter list must always be written even when empty: +) + +--- +struct Point(T = int) { + // ... +} + +// ... + + Point!$(HILITE ()) center; +--- + + +$(P +Similar to default function parameter values as we have seen in the $(LINK2 parameter_flexibility.html, Variable Number of Parameters chapter), default template parameters can be specified for all of the template parameters or for the $(I last) ones: +) + +--- +void myTemplate(T0, T1 $(HILITE = int), T2 $(HILITE = char))() { + // ... +} +--- + +$(P +The last two template parameters of that function may be left unspecified but the first one is required: +) + +--- + myTemplate!string(); +--- + +$(P +In that usage, the second and third parameters are $(C int) and $(C char), respectively. +) + +$(H5 Every template instantiation yields a distinct type) + +$(P +Every instantiation of a template for a given set of types is considered to be a distinct type. For example, $(C Point!int) and $(C Point!double) are separate types: +) + +--- +Point!int point3 = Point!double(0.25, 0.75); $(DERLEME_HATASI) +--- + +$(P +Those different types cannot be used in the assignment operation above: +) + +$(SHELL_SMALL +Error: cannot implicitly convert expression (Point(0.25,0.75)) +of type $(HILITE Point!(double)) to $(HILITE Point!(int)) +) + +$(H5 A compile-time feature) + +$(P +Templates are entirely a compile-time feature. The instances of templates are generated by the compiler at compile time. +) + +$(H5 Class template example: stack data structure) + +$(P +Struct and class templates are commonly used in the implementations of data structures. Let's design a stack container that will be able to contain any type. +) + +$(P +Stack is one of the simplest data structures. It represents a container where elements are placed conceptually on top of each other as would be in a stack of papers. New elements go on top, and only the topmost element is accessed. When an element is removed, it is always the topmost one. +) + +$(P +If we also define a property that returns the total number of elements in the stack, all of the operations of this data structure would be the following: +) + +$(UL +$(LI Add element ($(C push()))) +$(LI Remove element ($(C pop()))) +$(LI Access the topmost element ($(C .top))) +$(LI Report the number of elements ($(C .length))) +) + +$(P +An array can be used to store the elements such that the last element of the array would be representing the topmost element of the stack. Finally, it can be defined as a class template to be able to contain elements of any type: +) + +--- +$(CODE_NAME Stack)class Stack$(HILITE (T)) { +private: + + $(HILITE T)[] elements; + +public: + + void push($(HILITE T) element) { + elements ~= element; + } + + void pop() { + --elements.length; + } + + $(HILITE T) top() const { + return elements[$ - 1]; + } + + size_t length() const { + return elements.length; + } +} +--- + +$(P +Here is a $(C unittest) block for this class that uses its $(C int) instantiation: +) + +--- +unittest { + auto stack = new Stack$(HILITE !int); + + // The newly added element must appear on top + stack.push(42); + assert(stack.top == 42); + assert(stack.length == 1); + + // .top and .length should not affect the elements + assert(stack.top == 42); + assert(stack.length == 1); + + // The newly added element must appear on top + stack.push(100); + assert(stack.top == 100); + assert(stack.length == 2); + + // Removing the last element must expose the previous one + stack.pop(); + assert(stack.top == 42); + assert(stack.length == 1); + + // The stack must become empty when the last element is + // removed + stack.pop(); + assert(stack.length == 0); +} +--- + +$(P +To take advantage of this class template, let's try using it this time with a user-defined type. As an example, here is a modified version of $(C Point): +) + +--- +struct Point(T) { + T x; + T y; + + string toString() const { + return format("(%s,%s)", x, y); + } +} +--- + +$(P +A $(C Stack) that contains elements of type $(C Point!double) can be defined as follows: +) + +--- + auto points = new Stack!(Point!double); +--- + +$(P +Here is a test program that first adds ten elements to this stack and then removes them one by one: +) + +--- +$(CODE_XREF Stack)import std.string; +import std.stdio; +import std.random; + +struct Point(T) { + T x; + T y; + + string toString() const { + return format("(%s,%s)", x, y); + } +} + +// Returns a random value between -0.50 and 0.50. +double random_double() +out (result) { + assert((result >= -0.50) && (result < 0.50)); + +} do { + return (double(uniform(0, 100)) - 50) / 100; +} + +// Returns a Stack that contains 'count' number of random +// Point!double elements. +Stack!(Point!double) randomPoints(size_t count) +out (result) { + assert(result.length == count); + +} do { + auto points = new Stack!(Point!double); + + foreach (i; 0 .. count) { + immutable point = Point!double(random_double(), + random_double()); + writeln("adding : ", point); + points.push(point); + } + + return points; +} + +void main() { + auto stackedPoints = randomPoints(10); + + while (stackedPoints.length) { + writeln("removing: ", stackedPoints.top); + stackedPoints.pop(); + } +} +--- + +$(P +As the output of the program shows, the elements are removed in the reverse order as they have been added: +) + +$(SHELL_SMALL +adding : (-0.02,-0.01) +adding : (0.17,-0.5) +adding : (0.12,0.23) +adding : (-0.05,-0.47) +adding : (-0.19,-0.11) +adding : (0.42,-0.32) +adding : (0.48,-0.49) +adding : (0.35,0.38) +adding : (-0.2,-0.32) +adding : (0.34,0.27) +removing: (0.34,0.27) +removing: (-0.2,-0.32) +removing: (0.35,0.38) +removing: (0.48,-0.49) +removing: (0.42,-0.32) +removing: (-0.19,-0.11) +removing: (-0.05,-0.47) +removing: (0.12,0.23) +removing: (0.17,-0.5) +removing: (-0.02,-0.01) +) + +$(H5 Function template example: binary search algorithm) + +$(P +Binary search is the fastest algorithm to search for an element among the elements of an already sorted array. It is a very simple algorithm: The element in the middle is considered; if that element is the one that has been sought, then the search is over. If not, then the algorithm is repeated on the elements that are either on the left-hand side or on the right-hand side of the middle element, depending on whether the sought element is greater or less than the middle element. +) + +$(P +Algorithms that repeat themselves on a smaller range of the initial elements are recursive. Let's write the binary search algorithm recursively by calling itself. +) + +$(P +Before converting it to a template, let's first write this function to support only arrays of $(C int). We can easily convert it to a template later, by adding a template parameter list and replacing appropriate $(C int)s in its definition by $(C T)s. Here is a binary search algorithm that works on arrays of $(C int): +) + +--- +/* This function returns the index of the value if it exists + * in the array, size_t.max otherwise. */ +size_t binarySearch(const int[] values, int value) { + // The value is not in the array if the array is empty. + if (values.length == 0) { + return size_t.max; + } + + immutable midPoint = values.length / 2; + + if (value == values[midPoint]) { + // Found. + return midPoint; + + } else if (value < values[midPoint]) { + // The value can only be in the left-hand side; let's + // search in a slice that represents that half. + return binarySearch(values[0 .. midPoint], value); + + } else { + // The value can only be in the right-hand side; let's + // search in the right-hand side. + auto index = + binarySearch(values[midPoint + 1 .. $], value); + + if (index != size_t.max) { + // Adjust the index; it is 0-based in the + // right-hand side slice. + index += midPoint + 1; + } + + return index; + } + + assert(false, "We should have never gotten to this line"); +} +--- + +$(P +The function above implements this simple algorithm in four steps: +) + +$(UL +$(LI If the array is empty, return $(C size_t.max) to indicate that the value has not been found.) +$(LI If the element at the mid-point is equal to the sought value, then return the index of that element.) +$(LI If the value is less than the element at the mid-point, then repeat the same algorithm on the left-hand side.) +$(LI Else, repeat the same algorithm on the right-hand side.) +) + +$(P +Here is a unittest block that tests the function: +) + +--- +unittest { + auto array = [ 1, 2, 3, 5 ]; + assert(binarySearch(array, 0) == size_t.max); + assert(binarySearch(array, 1) == 0); + assert(binarySearch(array, 4) == size_t.max); + assert(binarySearch(array, 5) == 3); + assert(binarySearch(array, 6) == size_t.max); +} +--- + +$(P +Now that the function has been implemented and tested for $(C int), we can convert it to a template. $(C int) appears only in two places in the definition of the template: +) + +--- +size_t binarySearch(const int[] values, int value) { + // ... int does not appear here ... +} +--- + +$(P +The $(C int)s that appear in the parameter list are the types of the elements and the value. Specifying those as template parameters is sufficient to make this algorithm a template and to be usable with other types as well: +) + +--- +size_t binarySearch$(HILITE (T))(const $(HILITE T)[] values, $(HILITE T) value) { + // ... +} +--- + +$(P +That function template can be used with any type that matches the operations that are applied to that type in the template. In $(C binarySearch()), the elements are used only with comparison operators $(C ==) and $(C <): +) + +--- + if (value $(HILITE ==) values[midPoint]) { + // ... + + } else if (value $(HILITE <) values[midPoint]) { + + // ... +--- + +$(P +For that reason, $(C Point) is not ready to be used with $(C binarySearch()) yet: +) + +--- +import std.string; + +struct Point(T) { + T x; + T y; + + string toString() const { + return format("(%s,%s)", x, y); + } +} + +void $(CODE_DONT_TEST)main() { + Point!int[] points; + + foreach (i; 0 .. 15) { + points ~= Point!int(i, i); + } + + assert(binarySearch(points, Point!int(10, 10)) == 10); +} +--- + +$(P +The program above would cause a compilation error: +) + +$(SHELL_SMALL +Error: need member function $(HILITE opCmp()) for struct +const(Point!(int)) to compare +) + +$(P +According to the error message, $(C opCmp()) needs to be defined for $(C Point). $(C opCmp()) has been covered in $(LINK2 operator_overloading.html, the Operator Overloading chapter): +) + +--- +struct Point(T) { +// ... + + int opCmp(const ref Point that) const { + return (x == that.x + ? y - that.y + : x - that.x); + } +} +--- + +$(H5 Summary) + +$(P +We will see other features of templates in $(LINK2 templates_more.html, a later chapter). The following are what we have covered in this chapter: +) + +$(UL + +$(LI Templates define the code as a pattern, for the compiler to generate instances of it according to the actual uses in the program.) + +$(LI Templates are a compile-time feature.) + +$(LI Specifying template parameter lists is sufficient to make function, struct, and class definitions templates. + +--- +void functionTemplate$(HILITE (T))(T functionParameter) { + // ... +} + +class ClassTemplate$(HILITE (T)) { + // ... +} +--- + +) + +$(LI Template arguments can be specified explicitly after an exclamation mark. The parentheses are not necessary when there is only one token inside the parentheses. + +--- + auto object1 = new ClassTemplate!(double); + auto object2 = new ClassTemplate!double; // same thing +--- + +) + +$(LI Every template instantiation yields a distinct type. + +--- + assert(typeid(ClassTemplate!$(HILITE int)) != + typeid(ClassTemplate!$(HILITE uint))); +--- + +) + +$(LI Template arguments can only be deduced for function templates. + +--- + functionTemplate(42); // functionTemplate!int is deduced +--- + +) + +$(LI Templates can be specialized for the type that is after the $(C :) character. + +--- +class ClassTemplate(T $(HILITE : dchar)) { + // ... +} +--- + +) + +$(LI Default template arguments are specified after the $(C =) character. + +--- +void functionTemplate(T $(HILITE = long))(T functionParameter) { + // ... +} +--- + +) + +) + +Macros: + TITLE=Templates + + DESCRIPTION=Introduction to D's generic programming features. Templates allow defining code as a pattern and have the compiler generate actual code according to how the template is used in the program. + + KEYWORDS=d programming language tutorial book templates diff --git a/book/d.en/templates_more.d b/book/d.en/templates_more.d new file mode 100644 index 0000000000..a5a855fb26 --- /dev/null +++ b/book/d.en/templates_more.d @@ -0,0 +1,2111 @@ +Ddoc + +$(DERS_BOLUMU $(IX template) More Templates) + +$(P +We have seen the power and convenience of templates in $(LINK2 templates.html, the Templates chapter). A single templated definition of an algorithm or a data structure is sufficient to use that definition for multiple types. +) + +$(P +That chapter covered only the most common uses of templates: function, $(C struct), and $(C class) templates and their uses with $(I type) template parameters. In this chapter we will see templates in more detail. Before going further, I recommend that you review at least the summary section of that chapter. +) + +$(H5 $(IX shortcut syntax, template) The shortcut syntax) + +$(P +In addition to being powerful, D templates are easy to define and use and they are very readable. Defining a function, $(C struct), or $(C class) template is as simple as providing a template parameter list: +) + +--- +T twice$(HILITE (T))(T value) { + return 2 * value; +} + +class Fraction$(HILITE (T)) { + T numerator; + T denominator; + + // ... +} +--- + +$(P +Template definitions like the ones above are taking advantage of D's shortcut template syntax. +) + +$(P +In their full syntax, templates are defined by the $(C template) keyword. The equivalents of the two template definitions above are the following: +) + +--- +template twice$(HILITE (T)) { + T twice(T value) { + return 2 * value; + } +} + +template Fraction$(HILITE (T)) { + class Fraction { + T numerator; + T denominator; + + // ... + } +} +--- + +$(P +Although most templates are defined by the shortcut syntax, the compiler always uses the full syntax. We can imagine the compiler applying the following steps to convert a shortcut syntax to its full form behind the scenes: +) + +$(OL +$(LI Wrap the definition with a template block.) +$(LI Give the same name to that block.) +$(LI Move the template parameter list to the template block.) +) + +$(P +The full syntax that is arrived after those steps is called an $(I eponymous template), which the programmer can define explicitly as well. We will see eponymous templates later below. +) + +$(H6 $(IX name space, template) Template name space) + +$(P +It is possible to have more than one definition inside a template block. The following template contains both a function and a $(C struct) definition: +) + +--- +template MyTemplate(T) { + T foo(T value) { + return value / 3; + } + + struct S { + T member; + } +} +--- + +$(P +Instantiating the template for a specific type instantiates all of the definitions inside the block. The following code instantiates the template for $(C int) and $(C double): +) + +--- + auto result = $(HILITE MyTemplate!int).foo(42); + writeln(result); + + auto s = $(HILITE MyTemplate!double).S(5.6); + writeln(s.member); +--- + +$(P +A specific instantiation of a template introduces a $(I name space). The definitions that are inside an instantiation can be used by that name. However, if these names are too long, it is always possible to use aliases as we have seen in $(LINK2 alias.html, the $(C alias) chapter): +) + +--- + alias MyStruct = MyTemplate!dchar.S; + +// ... + + auto o = $(HILITE MyStruct)('a'); + writeln(o.member); +--- + +$(H6 $(IX eponymous template) Eponymous templates) + +$(P +Eponymous templates are $(C template) blocks that contain a definition that has the same name as that block. In fact, each shortcut template syntax is the shortcut of an eponymous template. +) + +$(P +As an example, assume that a program needs to qualify types that are larger than 20 bytes as $(I too large). Such a qualification can be achieved by a constant $(C bool) value inside a template block: +) + +--- +template isTooLarge(T) { + enum isTooLarge = T.sizeof > 20; +} +--- + +$(P +Note how the names of both the template block and its only definition are the same. This eponymous template is used by the shortcut syntax instead of the whole $(C isTooLarge!int.isTooLarge): +) + +--- + writeln($(HILITE isTooLarge!int)); +--- + +$(P +The highlighted part above is the same as the $(C bool) value inside the block. Since the size of $(C int) is less than 20, the output of the code would be $(C false). +) + +$(P +That eponymous template can be defined by the shortcut syntax as well: +) + +--- +enum isTooLarge$(HILITE (T)) = T.sizeof > 20; +--- + +$(P +A common use of eponymous templates is defining type aliases depending on certain conditions. For example, the following eponymous template picks the larger of two types by setting an alias to it: +) + +--- +$(CODE_NAME LargerOf)template LargerOf(A, B) { + static if (A.sizeof < B.sizeof) { + alias LargerOf = B; + + } else { + alias LargerOf = A; + } +} +--- + +$(P +Since $(C long) is larger than $(C int) (8 bytes versus 4 bytes), $(C LargerOf!(int, long)) would be the same as the type $(C long). Such templates are especially useful in other templates where the two types are template parameters themselves (or depend on template parameters): +) + +--- +$(CODE_XREF LargerOf)// ... + +/* The return type of this function is the larger of its two + * template parameters: Either type A or type B. */ +auto calculate(A, B)(A a, B b) { + $(HILITE LargerOf!(A, B)) result; + // ... + return result; +} + +void main() { + auto f = calculate(1, 2$(HILITE L)); + static assert(is (typeof(f) == $(HILITE long))); +} +--- + +$(H5 Kinds of templates) + +$(H6 Function, class, and struct templates) + +$(P +We have already covered function, $(C class), and $(C struct) templates in $(LINK2 templates.html, the Templates chapter) and we have seen many examples of them since then. +) + +$(H6 $(IX member function template) Member function templates) + +$(P +$(C struct) and $(C class) member functions can be templates as well. For example, the following $(C put()) member function template would work with any parameter type as long as that type is compatible with the operations inside the template (for this specific template, it should be convertible to $(C string)): +) + +--- +class Sink { + string content; + + void put$(HILITE (T))(auto ref const T value) { + import std.conv; + content ~= value.to!string; + } +} +--- + +$(P +However, as templates can have potentially infinite number of instantiations, they cannot be $(LINK2 inheritance.html, virtual functions) because the compiler cannot know which specific instantiations of a template to include in the interface. (Accordingly, the $(C abstract) keyword cannot be used either.) +) + +$(P +For example, although the presence of the $(C put()) template in the following subclass may give the impression that it is overriding a function, it actually hides the $(C put) name of the superclass (see $(I name hiding) in $(LINK2 alias.html, the alias chapter)): +) + +--- +class Sink { + string content; + + void put(T)(auto ref const T value) { + import std.conv; + content ~= value.to!string; + } +} + +class SpecialSink : Sink { + /* The following template definition does not override + * the template instances of the superclass; it hides + * those names. */ + void put(T)(auto ref const T value) { + import std.string; + super.put(format("{%s}", value)); + } +} + +void fillSink($(HILITE Sink) sink) { + /* The following function calls are not virtual. Because + * parameter 'sink' is of type 'Sink', the calls will + * always be dispatched to Sink's 'put' template + * instances. */ + + sink.put(42); + sink.put("hello"); +} + +void main() { + auto sink = new $(HILITE SpecialSink)(); + fillSink(sink); + + import std.stdio; + writeln(sink.content); +} +--- + +$(P +As a result, although the object actually is a $(C SpecialSink), both of the calls inside $(C fillSink()) are dispatched to $(C Sink) and the content does not contain the curly brackets that $(C SpecialSink.put()) inserts: +) + +$(SHELL +42hello $(SHELL_NOTE Sink's behavior, not SpecialSink's) +) + +$(H6 $(IX union template) Union templates) + +$(P +Union templates are similar to struct templates. The shortcut syntax is available for them as well. +) + +$(P +As an example, let's design a more general version of the $(C IpAdress) $(C union) that we saw in $(LINK2 union.html, the Unions chapter). There, the value of the IPv4 address was kept as a $(C uint) member in that earlier version of $(C IpAdress), and the element type of the segment array was $(C ubyte): +) + +--- +union IpAddress { + uint value; + ubyte[4] bytes; +} +--- + +$(P +The $(C bytes) array provided easy access to the four segments of the IPv4 address. +) + +$(P +The same concept can be implemented in a more general way as the following $(C union) template: +) + +--- +union SegmentedValue($(HILITE ActualT, SegmentT)) { + ActualT value; + SegmentT[/* number of segments */] segments; +} +--- + +$(P +That template would allow specifying the types of the value and its segments freely. +) + +$(P +The number of segments that are needed depends on the types of the actual value and the segments. Since an IPv4 address has four $(C ubyte) segments, that value was hard-coded as $(C 4) in the earlier definition of $(C IpAddress). For the $(C SegmentedValue) template, the number of segments must be computed at compile time when the template is instantiated for the two specific types. +) + +$(P +The following eponymous template takes advantage of the $(C .sizeof) properties of the two types to calculate the number of segments needed: +) + +--- +$(CODE_NAME segmentCount)template segmentCount(ActualT, SegmentT) { + enum segmentCount = ((ActualT.sizeof + (SegmentT.sizeof - 1)) + / SegmentT.sizeof); +} +--- + +$(P +The shortcut syntax may be more readable: +) + +--- +enum segmentCount(ActualT, SegmentT) = + ((ActualT.sizeof + (SegmentT.sizeof - 1)) + / SegmentT.sizeof); +--- + +$(P +$(I $(B Note:) The expression $(C SegmentT.sizeof - 1) is for when the sizes of the types cannot be divided evenly. For example, when the actual type is 5 bytes and the segment type is 2 bytes, even though a total of 3 segments are needed, the result of the integer division 5/2 would incorrectly be 2.) +) + +$(P +The definition of the union template is now complete: +) + +--- +$(CODE_NAME SegmentedValue)$(CODE_XREF segmentCount)union SegmentedValue(ActualT, SegmentT) { + ActualT value; + SegmentT[segmentCount!(ActualT, SegmentT)] segments; +} +--- + +$(P +Instantiation of the template for $(C uint) and $(C ubyte) would be the equivalent of the earlier definition of $(C IpAddress): +) + +--- +$(CODE_XREF SegmentedValue)import std.stdio; + +void main() { + auto address = SegmentedValue!($(HILITE uint, ubyte))(0xc0a80102); + + foreach (octet; address.segments) { + write(octet, ' '); + } +} +--- + +$(P +The output of the program is the same as the one in $(LINK2 union.html, the Unions chapter): +) + +$(SHELL_SMALL +2 1 168 192 +) + +$(P +To demonstrate the flexibility of this template, let's imagine that it is required to access the parts of the IPv4 address as two $(C ushort) values. It would be as easy as providing $(C ushort) as the segment type: +) + +--- + auto address = SegmentedValue!(uint, $(HILITE ushort))(0xc0a80102); +--- + +$(P +Although unusual for an IPv4 address, the output of the program would consist of two $(C ushort) segment values: +) + +$(SHELL_SMALL +258 49320 +) + +$(H6 $(IX interface template) Interface templates) + +$(P +Interface templates provide flexibility on the types that are used on an interface (as well as values such as sizes of fixed-length arrays and other features of an interface). +) + +$(P +Let's define an interface for colored objects where the type of the color is determined by a template parameter: +) + +--- +interface ColoredObject(ColorT) { + void paint(ColorT color); +} +--- + +$(P +That interface template requires that its subtypes must define the $(C paint()) function but it leaves the type of the color flexible. +) + +$(P +A class that represents a frame on a web page may choose to use a color type that is represented by its red, green, and blue components: +) + +--- +struct RGB { + ubyte red; + ubyte green; + ubyte blue; +} + +class PageFrame : ColoredObject$(HILITE !RGB) { + void paint(RGB color) { + // ... + } +} +--- + +$(P +On the other hand, a class that uses the frequency of light can choose a completely different type to represent color: +) + +--- +alias Frequency = double; + +class Bulb : ColoredObject$(HILITE !Frequency) { + void paint(Frequency color) { + // ... + } +} +--- + +$(P +However, as explained in $(LINK2 templates.html, the Templates chapter), "every template instantiation yields a distinct type". Accordingly, the interfaces $(C ColoredObject!RGB) and $(C ColoredObject!Frequency) are unrelated interfaces, and $(C PageFrame) and $(C Bulb) are unrelated classes. +) + +$(H5 $(IX parameter, template) Kinds of template parameters) + +$(P +The template parameters that we have seen so far have all been $(I type) parameters. So far, parameters like $(C T) and $(C ColorT) all represented types. For example, $(C T) meant $(C int), $(C double), $(C Student), etc. depending on the instantiation of the template. +) + +$(P +There are other kinds of template parameters: value, $(C this), $(C alias), and tuple. +) + +$(H6 $(IX type template parameter) Type template parameters) + +$(P +This section is only for completeness. All of the templates that we have seen so far had type parameters. +) + +$(H6 $(IX value template parameter) Value template parameters) + +$(P +Value template parameters allow flexibility on certain values used in the template implementation. +) + +$(P +Since templates are a compile-time feature, the values for the value template parameters must be known at compile time; values that must be calculated at run time cannot be used. +) + +$(P +To see the advantage of value template parameters, let's start with a set of structs representing geometric shapes: +) + +--- +struct Triangle { + Point[3] corners; +// ... +} + +struct Rectangle { + Point[4] corners; +// ... +} + +struct Pentagon { + Point[5] corners; +// ... +} +--- + +$(P +Let's assume that other member variables and member functions of those types are exactly the same and that the only difference is the $(I value) that determines the number of corners. +) + +$(P +Value template parameters help in such cases. The following struct template is sufficient to represent all of the types above and more: +) + +--- +struct Polygon$(HILITE (size_t N)) { + Point[N] corners; +// ... +} +--- + +$(P +The only template parameter of that struct template is a value named $(C N) of type $(C size_t). The value $(C N) can be used as a compile-time constant anywhere inside the template. +) + +$(P +That template is flexible enough to represent shapes of any sides: +) + +--- + auto centagon = Polygon!100(); +--- + +$(P +The following aliases correspond to the earlier struct definitions: +) + +--- +alias Triangle = Polygon!3; +alias Rectangle = Polygon!4; +alias Pentagon = Polygon!5; + +// ... + + auto triangle = Triangle(); + auto rectangle = Rectangle(); + auto pentagon = Pentagon(); +--- + +$(P +The type of the $(I value) template parameter above was $(C size_t). As long as the value can be known at compile time, a value template parameter can be of any type: a fundamental type, a $(C struct) type, an array, a string, etc. +) + +--- +struct S { + int i; +} + +// Value template parameter of struct S +void foo($(HILITE S s))() { + // ... +} + +void main() { + foo!(S(42))(); // Instantiating with literal S(42) +} +--- + +$(P +The following example uses a $(C string) template parameter to represent an XML tag to produce a simple XML output: +) + +$(UL +$(LI First the tag between the $(C <) $(C >) characters: $(C <tag>)) +$(LI Then the value) +$(LI Finally the tag between the $(C </) $(C >) characters: $(C </tag>)) +) + +$(P +For example, an XML tag representing $(I location 42) would be printed as $(C <location>42</location>). +) + +--- +$(CODE_NAME XmlElement)import std.string; + +class XmlElement$(HILITE (string tag)) { + double value; + + this(double value) { + this.value = value; + } + + override string toString() const { + return format("<%s>%s", tag, value, tag); + } +} +--- + +$(P +Note that the template parameter is not about a type that is used in the implementation of the template, rather it is about a $(C string) $(I value). That value can be used anywhere inside the template as a $(C string). +) + +$(P +The XML elements that a program needs can be defined as aliases as in the following code: +) + +--- +$(CODE_XREF XmlElement)alias Location = XmlElement!"location"; +alias Temperature = XmlElement!"temperature"; +alias Weight = XmlElement!"weight"; + +void main() { + Object[] elements; + + elements ~= new Location(1); + elements ~= new Temperature(23); + elements ~= new Weight(78); + + writeln(elements); +} +--- + +$(P +The output: +) + +$(SHELL_SMALL +[<location>1</location>, <temperature>23</temperature>, <weight>78</weight>] +) + +$(P +Value template parameters can have default values as well. For example, the following struct template represents points in a multi-dimensional space where the default number of dimensions is 3: +) + +--- +struct Point(T, size_t dimension $(HILITE = 3)) { + T[dimension] coordinates; +} +--- + +$(P +That template can be used without specifying the $(C dimension) template parameter: +) + +--- + Point!double center; // a point in 3-dimensional space +--- + +$(P +The number of dimensions can still be specified when needed: +) + +--- + Point!(int, 2) point; // a point on a surface +--- + +$(P +We have seen in $(LINK2 parameter_flexibility.html, the Variable Number of Parameters chapter) how $(I special keywords) work differently depending on whether they appear inside code or as default function arguments. +) + +$(P +Similarly, when used as default template arguments, the special keywords refer to where the template is instantiated at, not where the keywords appear: +) + +--- +import std.stdio; + +void func(T, + string functionName = $(HILITE __FUNCTION__), + string file = $(HILITE __FILE__), + size_t line = $(HILITE __LINE__))(T parameter) { + writefln("Instantiated at function %s at file %s, line %s.", + functionName, file, line); +} + +void main() { + func(42); $(CODE_NOTE $(HILITE line 12)) +} +--- + +$(P +Although the special keywords appear in the definition of the template, their values refer to $(C main()), where the template is instantiated at: +) + +$(SHELL +Instantiated at function deneme.$(HILITE main) at file deneme.d, $(HILITE line 12). +) + +$(P +We will use $(C __FUNCTION__) below in a multi-dimensional operator overloading example. +) + +$(H6 $(IX this, template parameter) $(C this) template parameters for member functions) + +$(P +Member functions can be templates as well. Their template parameters have the same meanings as other templates. +) + +$(P +However, unlike other templates, member function template parameters can also be $(I $(C this) parameters). In that case, the identifier that comes after the $(C this) keyword represents the exact type of the $(C this) reference of the object. ($(I $(C this) reference) means the object itself, as is commonly written in constructors as $(C this.member = value).) +) + +--- +struct MyStruct(T) { + void foo($(HILITE this OwnType))() const { + writeln("Type of this object: ", OwnType.stringof); + } +} +--- + +$(P +The $(C OwnType) template parameter is the actual type of the object that the member function is called on: +) + +--- + auto m = MyStruct!int(); + auto c = const(MyStruct!int)(); + auto i = immutable(MyStruct!int)(); + + m.foo(); + c.foo(); + i.foo(); +--- + +$(P +The output: +) + +$(SHELL_SMALL +Type of this object: MyStruct!int +Type of this object: const(MyStruct!int) +Type of this object: immutable(MyStruct!int) +) + +$(P +As you can see, the type includes the corresponding type of $(C T) as well as the type qualifiers like $(C const) and $(C immutable). +) + +$(P +The $(C struct) (or $(C class)) need not be a template. $(C this) template parameters can appear on member function templates of non-templated types as well. +) + +$(P +$(C this) template parameters can be useful in $(I template mixins) as well, which we will see two chapters later. +) + +$(H6 $(IX alias, template parameter) $(C alias) template parameters) + +$(P +$(C alias) template parameters can correspond to any symbol or expression that is used in the program. The only constraint on such a template argument is that the argument must be compatible with its use inside the template. +) + +$(P +$(C filter()) and $(C map()) use $(C alias) template parameters to determine the operations that they execute. +) + +$(P +Let's see a simple example on a $(C struct) template that is for modifying an existing variable. The $(C struct) template takes the variable as an $(C alias) parameter: +) + +--- +struct MyStruct(alias variable) { + void set(int value) { + variable = value; + } +} +--- + +$(P +The member function simply assigns its parameter to the variable that the $(C struct) template is instantiated with. That variable must be specified during the instantiation of the template: +) + +--- + int x = 1; + int y = 2; + + auto object = MyStruct!$(HILITE x)(); + object.set(10); + writeln("x: ", x, ", y: ", y); +--- + +$(P +In that instantiation, the $(C variable) template parameter corresponds to the variable $(C x): +) + +$(SHELL_SMALL +x: $(HILITE 10), y: 2 +) + +$(P +Conversely, $(C MyStruct!y) instantiation of the template would associate $(C variable) with $(C y). +) + +$(P +Let's now have an $(C alias) parameter that represents a callable entity, similar to $(C filter()) and $(C map()): +) + +--- +void caller(alias func)() { + write("calling: "); + $(HILITE func()); +} +--- + +$(P +As seen by the $(C ()) parentheses, $(C caller()) uses its template parameter as a function. Additionally, since the parentheses are empty, it must be legal to call the function without specifying any arguments. +) + +$(P +Let's have the following two functions that match that description. They can both represent $(C func) because they can be called as $(C func()) in the template: +) + +--- +void foo() { + writeln("foo called."); +} + +void bar() { + writeln("bar called."); +} +--- + +$(P +Those functions can be used as the $(C alias) parameter of $(C caller()): +) + +--- + caller!foo(); + caller!bar(); +--- + +$(P +The output: +) + +$(SHELL_SMALL +calling: foo called. +calling: bar called. +) + +$(P +As long as it matches the way it is used in the template, any symbol can be used as an $(C alias) parameter. As a counter example, using an $(C int) variable with $(C caller()) would cause a compilation error: +) + +--- + int variable; + caller!variable(); $(DERLEME_HATASI) +--- + +$(P +The compilation error indicates that the variable does not match its use in the template: +) + +$(SHELL_SMALL +Error: $(HILITE function expected before ()), not variable of type int +) + +$(P +Although the mistake is with the $(C caller!variable) instantiation, the compilation error necessarily points at $(C func()) inside the $(C caller()) template because from the point of view of the compiler the error is with trying to call $(C variable) as a function. One way of dealing with this issue is to use $(I template constraints), which we will see below. +) + +$(P +If the variable supports the function call syntax perhaps because it has an $(C opCall()) overload or it is a function literal, it would still work with the $(C caller()) template. The following example demonstrates both of those cases: +) + +--- +class C { + void opCall() { + writeln("C.opCall called."); + } +} + +// ... + + auto o = new C(); + caller!o(); + + caller!({ writeln("Function literal called."); })(); +--- + +$(P +The output: +) + +$(SHELL +calling: C.opCall called. +calling: Function literal called. +) + +$(P +$(C alias) parameters can be specialized as well. However, they have a different specialization syntax. The specialized type must be specified between the $(C alias) keyword and the name of the parameter: +) + +--- +import std.stdio; + +void foo(alias variable)() { + writefln("The general definition is using '%s' of type %s.", + variable.stringof, typeof(variable).stringof); +} + +void foo(alias $(HILITE int) i)() { + writefln("The int specialization is using '%s'.", + i.stringof); +} + +void foo(alias $(HILITE double) d)() { + writefln("The double specialization is using '%s'.", + d.stringof); +} + +void main() { + string name; + foo!name(); + + int count; + foo!count(); + + double length; + foo!length(); +} +--- + +$(P +Also note that $(C alias) parameters make the names of the actual variables available inside the template: +) + +$(SHELL +The general definition is using 'name' of type string. +The int specialization is using 'count'. +The double specialization is using 'length'. +) + +$(H6 $(IX tuple template parameter) Tuple template parameters) + +$(P +We have seen in $(LINK2 parameter_flexibility.html, the Variable Number of Parameters chapter) that variadic functions can take any number and any type of parameters. For example, $(C writeln()) can be called with any number of parameters of any type. +) + +$(P +$(IX ..., template parameter) $(IX variadic template) Templates can be variadic as well. A template parameter that consists of a name followed by $(C ...) allows any number and kind of parameters at that parameter's position. Such parameters appear as a tuple inside the template, which can be used like an $(C AliasSeq). +) + +$(P +Let's see an example of this with a template that simply prints information about every template argument that it is instantiated with: +) + +--- +$(CODE_NAME info)void info(T...)(T args) { + // ... +} +--- + +$(P +The template parameter $(C T...) makes $(C info) a $(I variadic template). Both $(C T) and $(C args) are tuples: +) + +$(UL +$(LI $(C T) represents the types of the arguments.) +$(LI $(C args) represents the arguments themselves.) +) + +$(P +The following example instantiates that function template with three values of three different types: +) + +--- +$(CODE_XREF info)import std.stdio; + +// ... + +void main() { + info($(HILITE 1, "abc", 2.3)); +} +--- + +$(P +The following implementation simply prints information about the arguments by iterating over them in a $(C foreach) loop: +) + +--- +void info(T...)(T args) { + // 'args' is being used like a tuple: + foreach (i, arg; $(HILITE args)) { + writefln("%s: %s argument %s", + i, typeof(arg).stringof, arg); + } +} +--- + +$(P +$(I $(B Note:) As seen in the previous chapter, since the arguments are a tuple, the $(C foreach) statement above is a) compile-time $(C foreach). +) + +$(P +The output: +) + +$(SHELL_SMALL +0: int argument 1 +1: string argument abc +2: double argument 2.3 +) + +$(P +Note that instead of obtaining the type of each argument by $(C typeof(arg)), we could have used $(C T[i]) as well. +) + +$(P +We know that template arguments can be deduced for function templates. That's why the compiler deduces the types as $(C int), $(C string), and $(C double) in the previous program. +) + +$(P +However, it is also possible to specify template parameters explicitly. For example, $(C std.conv.to) takes the destination type as an explicit template parameter: +) + +--- + to!$(HILITE string)(42); +--- + +$(P +When template parameters are explicitly specified, they can be a mixture of value, type, and other kinds. That flexibility makes it necessary to be able to determine whether each template parameter is a type or not, so that the body of the template can be coded accordingly. That is achieved by treating the arguments as an $(C AliasSeq). +) + +$(P +Let's see an example of this in a function template that produces $(C struct) definitions as source code in text form. Let's have this function return the produced source code as $(C string). This function can first take the name of the $(C struct) followed by the types and names of the members specified as pairs: +) + +--- +import std.stdio; + +void $(CODE_DONT_TEST)main() { + writeln(structDefinition!("Student", + string, "name", + int, "id", + int[], "grades")()); +} +--- + +$(P +That $(C structDefinition) instantiation is expected to produce the following $(C string): +) + +$(SHELL +struct Student { + string name; + int id; + int[] grades; +} +) + +$(P +$(I $(B Note:) Functions that produce source code are used with the $(C mixin) keyword, which we will see in $(LINK2 mixin.html, a later chapter).) +) + +$(P +The following is an implementation that produces the desired output. Note how the function template makes use of the $(C is) expression. Remember that the expression $(C is (arg)) produces $(C true) when $(C arg) is a valid type: +) + +--- +import std.string; + +string structDefinition(string name, $(HILITE Members)...)() { + /* Ensure that members are specified as pairs: first the + * type then the name. */ + static assert(($(HILITE Members).length % 2) == 0, + "Members must be specified as pairs."); + + /* The first part of the struct definition. */ + string result = "struct " ~ name ~ "\n{\n"; + + foreach (i, arg; $(HILITE Members)) { + static if (i % 2) { + /* The odd numbered arguments should be the names + * of members. Instead of dealing with the names + * here, we use them as Members[i+1] in the 'else' + * clause below. + * + * Let's at least ensure that the member name is + * specified as a string. */ + static assert(is (typeof(arg) == string), + "Member name " ~ arg.stringof ~ + " is not a string."); + + } else { + /* In this case 'arg' is the type of the + * member. Ensure that it is indeed a type. */ + static assert(is (arg), + arg.stringof ~ " is not a type."); + + /* Produce the member definition from its type and + * its name. + * + * Note: We could have written 'arg' below instead + * of Members[i]. */ + result ~= format(" %s %s;\n", + $(HILITE Members[i]).stringof, $(HILITE Members[i+1])); + } + } + + /* The closing bracket of the struct definition. */ + result ~= "}"; + + return result; +} + +import std.stdio; + +void main() { + writeln(structDefinition!("Student", + string, "name", + int, "id", + int[], "grades")()); +} +--- + +$(H5 $(IX typeof(this)) $(IX typeof(super)) $(IX typeof(return))$(C typeof(this)), $(C typeof(super)), and $(C typeof(return))) + +$(P +In some cases, the generic nature of templates makes it difficult to know or spell out certain types in the template code. The following three special $(C typeof) varieties are useful in such cases. Although they are introduced in this chapter, they work in non-templated code as well. +) + +$(UL + +$(LI $(C typeof(this)) generates the type of the $(C this) reference. It works in any $(C struct) or $(C class), even outside of member functions: + +--- +struct List(T) { + // The type of 'next' is List!int when T is int + typeof(this) *next; + // ... +} +--- + +) + +$(LI $(C typeof(super)) generates the base type of a $(C class) (i.e. the type of $(C super)). + +--- +class ListImpl(T) { + // ... +} + +class List(T) : ListImpl!T { + // The type of 'next' is ListImpl!int when T is int + typeof(super) *next; + // ... +} +--- + +) + +$(LI $(C typeof(return)) generates the return type of a function, inside that function. + +$(P +For example, instead of defining the $(C calculate()) function above as an $(C auto) function, we can be more explicit by replacing $(C auto) with $(C LargerOf!(A, B)) in its definition. (Being more explicit would have the added benefit of obviating at least some part of its function comment.) +) + +--- +$(HILITE LargerOf!(A, B)) calculate(A, B)(A a, B b) { + // ... +} +--- + +$(P +$(C typeof(return)) prevents having to repeat the return type inside the function body: +) + +--- +LargerOf!(A, B) calculate(A, B)(A a, B b) { + $(HILITE typeof(return)) result; // The type is either A or B + // ... + return result; +} +--- + +) + +) + +$(H5 Template specializations) + +$(P +We have seen template specializations in $(LINK2 templates.html, the Templates chapter). Like type parameters, other kinds of template parameters can be specialized as well. The following is the general definition of a template and its specialization for 0: +) + +--- +void foo(int value)() { + // ... general definition ... +} + +void foo(int value $(HILITE : 0))() { + // ... special definition for zero ... +} +--- + +$(P +We will take advantage of template specializations in the $(I meta programming) section below. +) + +$(H5 $(IX meta programming) Meta programming) + +$(P +As they are about code generation, templates are among the higher level features of D. A template is indeed code that generates code. Writing code that generates code is called $(I meta programming). +) + +$(P +Due to templates being compile-time features, some operations that are normally executed at runtime can be moved to compile time as template instantiations. +) + +$(P +($(I $(B Note:) Compile time function execution) (CTFE) $(I is another feature that achieves the same goal. We will see CTFE in a later chapter.)) +) + +$(P +$(I Executing) templates at compile time is commonly based on recursive template instantiations. +) + +$(P +To see an example of this, let's first consider a regular function that calculates the sum of numbers from 0 to a specific value. For example, when its argument is 4, this fuction should return the result of 0+1+2+3+4: +) + +--- +int sum(int last) { + int result = 0; + + foreach (value; 0 .. last + 1) { + result += value; + } + + return result; +} +--- + +$(P +$(IX recursion) That is an iterative implementation of the function. The same function can be implemented by recursion as well: +) + +--- +int sum(int last) { + return (last == 0 + ? last + : last + $(HILITE sum)(last - 1)); +} +--- + +$(P +The recursive function returns the sum of the last value and the previous sum. As you can see, the function terminates the recursion by treating the value 0 specially. +) + +$(P +Functions are normally run-time features. As usual, $(C sum()) can be executed at run time: +) + +--- + writeln(sum(4)); +--- + +$(P +When the result is needed at compile time, one way of achieving the same calculation is by defining a function template. In this case, the parameter must be a template parameter, not a function parameter: +) + +--- +// WARNING: This code is incorrect. +int sum($(HILITE int last))() { + return (last == 0 + ? last + : last + sum$(HILITE !(last - 1))()); +} +--- + +$(P +That function template instantiates itself by $(C last - 1) and tries to calculate the sum again by recursion. However, that code is incorrect. +) + +$(P +As the ternary operator would be compiled to be executed at run time, there is no condition check that terminates the recursion at compile time: +) + +--- + writeln(sum!4()); $(DERLEME_HATASI) +--- + +$(P +The compiler detects that the template instances would recurse infinitely and stops at an arbitrary number of recursions: +) + +$(SHELL_SMALL +Error: template instance deneme.sum!($(HILITE -296)) recursive expansion +) + +$(P +Considering the difference between the template argument 4 and -296, the compiler restricts template expansion at 300 by default. +) + +$(P +In meta programming, recursion is terminated by a template specialization. The following specialization for 0 produces the expected result: +) + +--- +$(CODE_NAME sum)// The general definition +int sum(int last)() { + return last + sum!(last - 1)(); +} + +// The special definition for zero +int sum(int last $(HILITE : 0))() { + return 0; +} +--- + +$(P +The following is a program that tests $(C sum()): +) + +--- +$(CODE_XREF sum)import std.stdio; + +void main() { + writeln(sum!4()); +} +--- + +$(P +Now the program compiles successfully and produces the result of 4+3+2+1+0: +) + +$(SHELL_SMALL +10 +) + +$(P +An important point to make here is that the function $(C sum!4()) is executed entirely at compile time. The compiled code is the equivalent of calling $(C writeln()) with literal $(C 10): +) + +--- + writeln(10); // the equivalent of writeln(sum!4()) +--- + +$(P +As a result, the compiled code is as fast and simple as can be. Although the value 10 is still calculated as the result of 4+3+2+1+0, the entire calculation happens at compile time. +) + +$(P +The previous example demonstrates one of the benefits of meta programming: moving operations from run time to compile time. CTFE obviates some of the idioms of meta programming in D. +) + +$(H5 $(IX polymorphism, compile-time) $(IX compile-time polymorphism) Compile-time polymorphism) + +$(P +In object oriented programming (OOP), polymorphism is achieved by inheritance. For example, if a function takes an interface, it accepts objects of any class that inherits that interface. +) + +$(P +Let's recall an earlier example from a previous chapter: +) + +--- +import std.stdio; + +interface SoundEmitter { + string emitSound(); +} + +class Violin : SoundEmitter { + string emitSound() { + return "♩♪♪"; + } +} + +class Bell : SoundEmitter { + string emitSound() { + return "ding"; + } +} + +void useSoundEmittingObject($(HILITE SoundEmitter object)) { + // ... some operations ... + writeln(object.emitSound()); + // ... more operations ... +} + +void main() { + useSoundEmittingObject(new Violin); + useSoundEmittingObject(new Bell); +} +--- + +$(P +$(C useSoundEmittingObject()) is benefiting from polymorphism. It takes a $(C SoundEmitter) so that it can be used with any type that is derived from that interface. +) + +$(P +Since $(I working with any type) is inherent to templates, they can be seen as providing a kind of polymorphism as well. Being a compile-time feature, the polymorphism that templates provide is called $(I compile-time polymorphism). Conversely, OOP's polymorphism is called $(I run-time polymorphism). +) + +$(P +In reality, neither kind of polymorphism allows being used with $(I any type) because the types must satisfy certain requirements. +) + +$(P +Run-time polymorphism requires that the type implements a certain interface. +) + +$(P +Compile-time polymorphism requires that the type is compatible with how it is used by the template. As long as the code compiles, the template argument can be used with that template. ($(I $(B Note:) Optionally, the argument must satisfy template constraints as well. We will see template constraints later below.)) +) + +$(P +For example, if $(C useSoundEmittingObject()) were implemented as a function template instead of a function, it could be used with any type that supported the $(C object.emitSound()) call: +) + +--- +void useSoundEmittingObject$(HILITE (T))(T object) { + // ... some operations ... + writeln(object.emitSound()); + // ... more operations ... +} + +class Car { + string emitSound() { + return "honk honk"; + } +} + +// ... + + useSoundEmittingObject(new Violin); + useSoundEmittingObject(new Bell); + useSoundEmittingObject(new Car); +--- + +$(P +Note that although $(C Car) has no inheritance relationship with any other type, the code compiles successfully, and the $(C emitSound()) member function of each type gets called. +) + +$(P +$(IX duck typing) Compile-time polymorphism is also known as $(I duck typing), a humorous term, emphasizing behavior over actual type. +) + +$(H5 $(IX code bloat) Code bloat) + +$(P +The code generated by the compiler is different for every different argument of a type parameter, of a value parameter, etc.) + +$(P +The reason for that can be seen by considering $(C int) and $(C double) as type template arguments. Each type would have to be processed by different kinds of CPU registers. For that reason, the same template needs to be compiled differently for different template arguments. In other words, the compiler needs to generate different code for each instantiation of a template. +) + +$(P +For example, if $(C useSoundEmittingObject()) were implemented as a template, it would be compiled as many times as the number of different instantiations of it. +) + +$(P +Because it results in larger program size, this effect is called $(I code bloat). Although this is not a problem in most programs, it is an effect of templates that must be known. +) + +$(P +Conversely, non-templated version of $(C useSoundEmittingObject()) would not have any code repetition. The compiler would compile that function just once and execute the same code for all types of the $(C SoundEmitter) interface. In run-time polymorphism, having the same code behave differently for different types is achieved by function pointers on the background. Although function pointers have a small cost at run time, that cost is not significant in most programs. +) + +$(P +Since both code bloat and run-time polymorphism have effects on program performance, it cannot be known beforehand whether run-time polymorphism or compile-time polymorphism would be a better approach for a specific program. +) + +$(H5 $(IX constraint, template) $(IX template constraint) Template constraints) + +$(P +The fact that templates can be instantiated with any argument yet not every argument is compatible with every template brings an inconvenience. If a template argument is not compatible with a particular template, the incompatibility is necessarily detected during the compilation of the template code for that argument. As a result, the compilation error points at a line inside the template implementation. +) + +$(P +Let's see this by using $(C useSoundEmittingObject()) with a type that does not support the $(C object.emitSound()) call: +) + +--- +class Cup { + // ... does not have emitSound() ... +} + +// ... + + useSoundEmittingObject(new Cup); // ← incompatible type +--- + +$(P +Although arguably the error is with the code that uses the template with an incompatible type, the compilation error points at a line inside the template: +) + +--- +void useSoundEmittingObject(T)(T object) { + // ... some operations ... + writeln(object.emitSound()); $(DERLEME_HATASI) + // ... more operations ... +} +--- + +$(P +An undesired consequence is that when the template is a part of a third-party library module, the compilation error would appear to be a problem with the library itself. +) + +$(P +Note that this issue does not exist for interfaces: A function that takes an interface can only be called with a type that implements that interface. Attempting to call such a function with any other type is a compilation error at the caller. +) + +$(P +$(IX if, template constraint) Template contraints are for disallowing incorrect instantiations of templates. They are defined as logical expressions of an $(C if) condition right before the template body: +) + +--- +void foo(T)() + if (/* ... constraints ... */) { + // ... +} +--- + +$(P +A template definition is considered by the compiler only if its constraints evaluate to $(C true) for a specific instantiation of the template. Otherwise, the template definition is ignored for that use. +) + +$(P +Since templates are a compile-time feature, template constraints must be evaluable at compile time. The $(C is) expression that we saw in $(LINK2 is_expr.html, the $(C is) Expression chapter) is commonly used in template constraints. We will use the $(C is) expression in the following examples as well. +) + +$(H6 $(IX single-element tuple template parameter) $(IX tuple template parameter, single-element) Tuple parameter of single element) + +$(P +Sometimes the single parameter of a template needs to be one of type, value, or $(C alias) kinds. That can be achieved by a tuple parameter of length one: +) + +--- +template myTemplate(T...) + $(HILITE if (T.length == 1)) { + static if (is ($(HILITE T[0]))) { + // The single parameter is a type + enum bool myTemplate = /* ... */; + + } else { + // The single parameter is some other kind + enum bool myTemplate = /* ... */; + } +} +--- + +$(P +Some of the templates of the $(C std.traits) module take advantage of this idiom. We will see $(C std.traits) in a later chapter. +) + +$(H6 $(IX named template constraint) Named constraints) + +$(P +Sometimes the constraints are complex, making it hard to understand the requirements of template parameters. This complexity can be handled by an idiom that effectively gives names to constraints. This idiom combines four features of D: anonymous functions, $(C typeof), the $(C is) expression, and eponymous templates. +) + +$(P +Let's see this on a function template that has a type parameter. The template uses its function parameter in specific ways: +) + +--- +void use(T)(T object) { + // ... + object.prepare(); + // ... + object.fly(42); + // ... + object.land(); + // ... +} +--- + +$(P +As is obvious from the implementation of the template, the types that this function can work with must support three specific function calls on the object: $(C prepare()), $(C fly(42)), and $(C land()). +) + +$(P +One way of specifying a template constraint for that type is by the $(C is) and $(C typeof) expressions for each function call inside the template: +) + +--- +void use(T)(T object) + if (is (typeof(object.prepare())) && + is (typeof(object.fly(1))) && + is (typeof(object.land()))) { + // ... +} +--- + +$(P +I will explain that syntax below. For now, accept the whole construct of $(C is (typeof(object.prepare()))) to mean $(I whether the type supports the $(C .prepare()) call). +) + +$(P +Although such constraints achieve the desired goal, sometimes they are too complex to be readable. Instead, it is possible to give a more descriptive name to the whole constraint: +) + +--- +void use(T)(T object) + if (canFlyAndLand!T) { + // ... +} +--- + +$(P +That constraint is more readable because it is now more clear that the template is designed to work with types that $(I can fly and land). +) + +$(P +Such constraints are achieved by an idiom that is implemented similar to the following eponymous template: +) + +--- +template canFlyAndLand(T) { + enum canFlyAndLand = is (typeof( + { + T object; + object.prepare(); // should be preparable for flight + object.fly(1); // should be flyable for a certain distance + object.land(); // should be landable + }())); +} +--- + +$(P +The D features that take part in that idiom and how they interact with each other are explained below: +) + +--- +template canFlyAndLand(T) { + // (6) (5) (4) + enum canFlyAndLand = is (typeof( + $(HILITE {) // (1) + T object; // (2) + object.prepare(); + object.fly(1); + object.land(); + // (3) + $(HILITE })())); +} +--- + +$(OL + +$(LI $(B Anonymous function:) We have seen anonymous functions in $(LINK2 lambda.html, the Function Pointers, Delegates, and Lambdas chapter). The highlighted curly brackets above define an anonymous function. +) + +$(LI $(B Function block:) The function block uses the type as it is supposed to be used in the actual template. First an object of that type is defined and then that object is used in specific ways. (This code never gets executed; see below.) +) + +$(LI $(B Evaluation of the function:) The empty parentheses at the end of an anonymous function normally execute that function. However, since that call syntax is within a $(C typeof), it is never executed. +) + +$(LI $(IX typeof) $(B The $(C typeof) expression:) $(C typeof) produces the type of an expression. + +$(P +An important fact about $(C typeof) is that it never executes the expression. Rather, it produces the type of the expression $(I if) that expression would be executed: +) + +--- + int i = 42; + typeof(++i) j; // same as 'int j;' + + assert(i == 42); // ++i has not been executed +--- + +$(P +As the previous $(C assert) proves, the expression $(C ++i) has not been executed. $(C typeof) has merely produced the type of that expression as $(C int). +) + +$(P +If the expression that $(C typeof) receives is not valid, $(C typeof) produces no type at all (not even $(C void)). So, if the anonymous function inside $(C canFlyAndLand) can be compiled successfully for $(C T), $(C typeof) produces a valid type. Otherwise, it produces no type at all. +) + +) + +$(LI $(B The $(C is) expression:) We have seen many different uses of the $(C is) expression in $(LINK2 is_expr.html, the $(C is) Expression chapter). The $(C is ($(I Type))) syntax produces $(C true) if $(C Type) is valid: + +--- + int i; + writeln(is (typeof(i))); // true + writeln(is (typeof(nonexistentSymbol))); // false +--- + +$(P +Although the second $(C typeof) above receives a nonexistent symbol, the compiler does not emit a compilation error. Rather, the effect is that the $(C typeof) expression does not produce any type, so the $(C is) expression produces $(C false): +) + +$(SHELL_SMALL +true +false +) + +) + +$(LI $(B Eponymous template:) As described above, since the $(C canFlyAndLand) template contains a definition by the same name, the template instantiation is that definition itself. +) + +) + +$(P +In the end, $(C use()) gains a more descriptive constraint: +) + +--- +void use(T)(T object) + if (canFlyAndLand!T) { + // ... +} +--- + +$(P +Let's try to use that template with two types, one that satisfies the constraint and one that does not satisfy the constraint: +) + +--- +// A type that does match the template's operations +class ModelAirplane { + void prepare() { + } + + void fly(int distance) { + } + + void land() { + } +} + +// A type that does not match the template's operations +class Pigeon { + void fly(int distance) { + } +} + +// ... + + use(new ModelAirplane); // ← compiles + use(new Pigeon); $(DERLEME_HATASI) +--- + +$(P +Named or not, since the template has a constraint, the compilation error points at the line where the template is used rather than where it is implemented. +) + +$(H5 $(IX overloading, operator) $(IX multi-dimensional operator overloading) $(IX operator overloading, multi-dimensional) Using templates in multi-dimensional operator overloading) + +$(P +We have seen in $(LINK2 operator_overloading.html, the Operator Overloading chapter) that $(C opDollar), $(C opIndex), and $(C opSlice) are for element indexing and slicing. When overloaded for single-dimensional collections, these operators have the following responsibilities: +) + +$(UL + +$(LI $(C opDollar): Returns the number of elements of the collection.) + +$(LI $(C opSlice): Returns an object that represents some or all of the elements of the collection.) + +$(LI $(C opIndex): Provides access to an element.) + +) + +$(P +Those operator functions have templated versions as well, which have different responsibilities from the non-templated ones above. Note especially that in multi-dimensional operator overloading $(C opIndex) assumes the responsibility of $(C opSlice). +) + +$(UL + +$(LI $(IX opDollar template) $(C opDollar) template: Returns the length of a specific dimension of the collection. The dimension is determined by the template parameter: + +--- + size_t opDollar$(HILITE (size_t dimension))() const { + // ... + } +--- + +) + +$(LI $(IX opSlice template) $(C opSlice) template: Returns the range information that specifies the range of elements (e.g. the $(C begin) and $(C end) values in $(C array[begin..end])). The information can be returned as $(C Tuple!(size_t, size_t)) or an equivalent type. The dimension that the range specifies is determined by the template parameter: + +--- + Tuple!(size_t, size_t) opSlice$(HILITE (size_t dimension))(size_t begin, + size_t end) { + return tuple(begin, end); + } +--- + +) + +$(LI $(IX opIndex template) $(C opIndex) template: Returns a range object that represents a part of the collection. The range of elements are determined by the template parameters: + +--- + Range opIndex$(HILITE (A...))(A arguments) { + // ... + } +--- + +) + +) + +$(P +$(IX opIndexAssign template) $(IX opIndexOpAssign template) $(C opIndexAssign) and $(C opIndexOpAssign) have templated versions as well, which operate on a range of elements of the collection. +) + +$(P +The user-defined types that define these operators can be used with the multi-dimensional indexing and slicing syntax: +) + +--- + // Assigns 42 to the elements specified by the + // indexing and slicing arguments: + m[a, b..c, $-1, d..e] = 42; +// ↑ ↑ ↑ ↑ +// dimensions: 0 1 2 3 +--- + +$(P +Such expressions are first converted to the ones that call the operator functions. The conversions are performed by replacing the $(C $) characters with calls to $(C opDollar!dimension()), and the index ranges with calls to $(C opSlice!dimension(begin, end)). The length and range information that is returned by those calls is in turn used as arguments when calling e.g. $(C opIndexAssign). Accordingly, the expression above is executed as the following equivalent (the dimension values are highlighted): +) + +--- + // The equivalent of the above: + m.opIndexAssign( + 42, // ← value to assign + a, // ← argument for dimension 0 + m.opSlice!$(HILITE 1)(b, c), // ← argument for dimension 1 + m.opDollar!$(HILITE 2)() - 1, // ← argument for dimension 2 + m.opSlice!$(HILITE 3)(d, e)); // ← argument for dimension 3 +--- + +$(P +Consequently, $(C opIndexAssign) determines the range of elements from the arguments. +) + +$(H6 Multi-dimensional operator overloading example) + +$(P +The following $(C Matrix) example demonstrates how these operators can be overloaded for a two-dimensional type. +) + +$(P +Note that this code can be implemented in more efficient ways. For example, instead of constructing a $(I single-element sub-matrix) even when operating on a single element e.g. by $(C m[i, j]), it could apply the operation directly on that element. +) + +$(P +Additionally, the $(C writeln(__FUNCTION__)) expressions inside the functions have nothing to do with the behavior of the code. They merely help expose the functions that get called behind the scenes for different operator usages. +) + +$(P +Also note that the correctness of dimension values are enforced by template constraints. +) + +--- +import std.stdio; +import std.format; +import std.string; + +/* Works as a two-dimensional int array. */ +struct Matrix { +private: + + int[][] rows; + + /* Represents a range of rows or columns. */ + struct Range { + size_t begin; + size_t end; + } + + /* Returns the sub-matrix that is specified by the row and + * column ranges. */ + Matrix subMatrix(Range rowRange, Range columnRange) { + writeln(__FUNCTION__); + + int[][] slices; + + foreach (row; rows[rowRange.begin .. rowRange.end]) { + slices ~= row[columnRange.begin .. columnRange.end]; + } + + return Matrix(slices); + } + +public: + + this(size_t height, size_t width) { + writeln(__FUNCTION__); + + rows = new int[][](height, width); + } + + this(int[][] rows) { + writeln(__FUNCTION__); + + this.rows = rows; + } + + void toString(void delegate(const(char)[]) sink) const { + sink.formattedWrite!"%(%(%5s %)\n%)"(rows); + } + + /* Assigns the specified value to each element of the + * matrix. */ + Matrix opAssign(int value) { + writeln(__FUNCTION__); + + foreach (row; rows) { + row[] = value; + } + + return this; + } + + /* Uses each element and a value in a binary operation + * and assigns the result back to that element. */ + Matrix opOpAssign(string op)(int value) { + writeln(__FUNCTION__); + + foreach (row; rows) { + mixin ("row[] " ~ op ~ "= value;"); + } + + return this; + } + + /* Returns the length of the specified dimension. */ + size_t opDollar(size_t dimension)() const + if (dimension <= 1) { + writeln(__FUNCTION__); + + static if (dimension == 0) { + /* The length of dimension 0 is the length of the + * 'rows' array. */ + return rows.length; + + } else { + /* The length of dimension 1 is the lengths of the + * elements of 'rows'. */ + return rows.length ? rows[0].length : 0; + } + } + + /* Returns an object that represents the range from + * 'begin' to 'end'. + * + * Note: Although the 'dimension' template parameter is + * not used here, that information can be useful for other + * types. */ + Range opSlice(size_t dimension)(size_t begin, size_t end) + if (dimension <= 1) { + writeln(__FUNCTION__); + + return Range(begin, end); + } + + /* Returns a sub-matrix that is defined by the + * arguments. */ + Matrix opIndex(A...)(A arguments) + if (A.length <= 2) { + writeln(__FUNCTION__); + + /* We start with ranges that represent the entire + * matrix so that the parameter-less use of opIndex + * means "all of the elements". */ + Range[2] ranges = [ Range(0, opDollar!0), + Range(0, opDollar!1) ]; + + foreach (dimension, a; arguments) { + static if (is (typeof(a) == Range)) { + /* This dimension is already specified as a + * range like 'matrix[begin..end]', which can + * be used as is. */ + ranges[dimension] = a; + + } else static if (is (typeof(a) : size_t)) { + /* This dimension is specified as a single + * index value like 'matrix[i]', which we want + * to represent as a single-element range. */ + ranges[dimension] = Range(a, a + 1); + + } else { + /* We don't expect other types. */ + static assert( + false, format("Invalid index type: %s", + typeof(a).stringof)); + } + } + + /* Return the sub-matrix that is specified by + * 'arguments'. */ + return subMatrix(ranges[0], ranges[1]); + } + + /* Assigns the specified value to each element of the + * sub-matrix. */ + Matrix opIndexAssign(A...)(int value, A arguments) + if (A.length <= 2) { + writeln(__FUNCTION__); + + Matrix subMatrix = opIndex(arguments); + return subMatrix = value; + } + + /* Uses each element of the sub-matrix and a value in a + * binary operation and assigns the result back to that + * element. */ + Matrix opIndexOpAssign(string op, A...)(int value, + A arguments) + if (A.length <= 2) { + writeln(__FUNCTION__); + + Matrix subMatrix = opIndex(arguments); + mixin ("return subMatrix " ~ op ~ "= value;"); + } +} + +/* Executes the expression that is specified as a string, and + * prints the result as well as the new state of the + * matrix. */ +void execute(string expression)(Matrix m) { + writefln("\n--- %s ---", expression); + mixin ("auto result = " ~ expression ~ ";"); + writefln("result:\n%s", result); + writefln("m:\n%s", m); +} + +void main() { + enum height = 10; + enum width = 8; + + auto m = Matrix(height, width); + + int counter = 0; + foreach (row; 0 .. height) { + foreach (column; 0 .. width) { + writefln("Initializing %s of %s", + counter + 1, height * width); + + m[row, column] = counter; + ++counter; + } + } + + writeln(m); + + execute!("m[1, 1] = 42")(m); + execute!("m[0, 1 .. $] = 43")(m); + execute!("m[0 .. $, 3] = 44")(m); + execute!("m[$-4 .. $-1, $-4 .. $-1] = 7")(m); + + execute!("m[1, 1] *= 2")(m); + execute!("m[0, 1 .. $] *= 4")(m); + execute!("m[0 .. $, 0] *= 10")(m); + execute!("m[$-4 .. $-2, $-4 .. $-2] -= 666")(m); + + execute!("m[1, 1]")(m); + execute!("m[2, 0 .. $]")(m); + execute!("m[0 .. $, 2]")(m); + execute!("m[0 .. $ / 2, 0 .. $ / 2]")(m); + + execute!("++m[1..3, 1..3]")(m); + execute!("--m[2..5, 2..5]")(m); + + execute!("m[]")(m); + execute!("m[] = 20")(m); + execute!("m[] /= 4")(m); + execute!("(m[] += 5) /= 10")(m); +} +--- + +$(H5 Summary) + +$(P +The earlier template chapter had the following reminders: +) + +$(UL + +$(LI Templates define the code as a pattern, for the compiler to generate instances of it according to the actual uses in the program.) + +$(LI Templates are a compile-time feature.) + +$(LI Specifying template parameter lists is sufficient to make function, struct, and class definitions templates.) + +$(LI Template arguments can be specified explicitly after an exclamation mark. The parentheses are not necessary when there is only one token inside the parentheses.) + +$(LI Each template instantiation yields a different type.) + +$(LI Template arguments can only be deduced for function templates.) + +$(LI Templates can be specialized for the type that is after the $(C :) character.) + +$(LI Default template arguments are specified after the $(C =) character.) + +) + +$(P +This chapter added the following concepts: +) + +$(UL + +$(LI Templates can be defined by the full syntax or the shortcut syntax.) + +$(LI The scope of the template is a name space.) + +$(LI A template that contains a definition with the same name as the template is called an eponymous template. The template represents that definition.) + +$(LI Templates can be of functions, classes, structs, unions, and interfaces, and every template body can contain any number of definitions.) + +$(LI Template parameters can be of type, value, $(C this), $(C alias), and tuple kinds.) + +$(LI $(C typeof(this)), $(C typeof(super)), and $(C typeof(return)) are useful in templates.) + +$(LI Templates can be specialized for particular arguments.) + +$(LI Meta programming is a way of executing operations at compile time.) + +$(LI Templates enable $(I compile-time polymorphism).) + +$(LI Separate code generation for different instantiations can cause $(I code bloat).) + +$(LI Template constraints limit the uses of templates for specific template arguments. They help move compilation errors from the implementations of templates to where the templates are actually used incorrectly.) + +$(LI It is more readable to give names to template constraints.) + +$(LI The templated versions of $(C opDollar), $(C opSlice), $(C opIndex), $(C opIndexAssign), and $(C opIndexOpAssign) are for multi-dimensional indexing and slicing.) + +) + +Macros: + TITLE=More Templates + + DESCRIPTION=One of generic programming features of D in more detail. + + KEYWORDS=d programming language tutorial book templates diff --git a/book/d.en/ternary.cozum.d b/book/d.en/ternary.cozum.d new file mode 100644 index 0000000000..27722ed35d --- /dev/null +++ b/book/d.en/ternary.cozum.d @@ -0,0 +1,33 @@ +Ddoc + +$(COZUM_BOLUMU The Ternary Operator $(C ?:)) + +$(P +Although it may make more sense to use an $(C if-else) statement in this exercise, the following program uses two $(C ?:) operators: +) + +--- +import std.stdio; + +void main() { + write("Please enter the net amount: "); + + int amount; + readf(" %s", &amount); + + writeln("$", + amount < 0 ? -amount : amount, + amount < 0 ? " lost" : " gained"); +} +--- + +$(P +The program prints "gained" even when the value is zero. Modify the program to print a message more appropriate for zero. +) + +Macros: + TITLE=The Ternary Operator ?: Solution + + DESCRIPTION=The exercise solution of the ?: operator of the D programming language. + + KEYWORDS=programming in d tutorial ternary solution diff --git a/book/d.en/ternary.d b/book/d.en/ternary.d new file mode 100644 index 0000000000..017fc5b820 --- /dev/null +++ b/book/d.en/ternary.d @@ -0,0 +1,251 @@ +Ddoc + +$(DERS_BOLUMU $(IX ternary operator) $(IX ?:) $(IX conditional operator) Ternary Operator $(CH4 ?:)) + +$(P +The $(C ?:) operator works very similarly to an $(C if-else) statement: +) + +--- + if (/* condition check */) { + /* ... expression(s) to execute if true */ + + } else { + /* ... expression(s) to execute if false */ + } +--- + +$(P +The $(C if) statement executes either the block for the case of $(C true) or the block for the case of $(C false). As you remember, being a statement, it does not have a value; $(C if) merely affects the execution of code blocks. +) + +$(P +On the other hand, the $(C ?:) operator is an expression. In addition to working similary to the $(C if-else) statement, it produces a value. The equivalent of the above code is the following: +) + +--- +/* condition */ ? /* truth expression */ : /* falsity expression */ +--- + +$(P +Because it uses three expressions, the $(C ?:) operator is called the ternary operator. +) + +$(P +The value that is produced by this operator is either the value of the truth expression or the value of the falsity expression. Because it is an expression, it can be used anywhere that expressions can be used. +) + +$(P +The following examples contrast the $(C ?:) operator to the $(C if-else) statement. The ternary operator is more concise for the cases that are similar to these examples. +) + +$(UL + +$(LI $(B Initialization) + +$(P +To initialize a variable with 366 if it is leap year, 365 otherwise: +) + +--- + int days = isLeapYear ? 366 : 365; +--- + +$(P +With an $(C if) statement, one way to do this is to define the variable without an explicit initial value and then assign the intended value: +) + +--- + int days; + + if (isLeapYear) { + days = 366; + + } else { + days = 365; + } +--- + +$(P +An alternative also using an $(C if) is to initialize the variable with the non-leap year value and then increment it if it is a leap year: +) + +--- + int days = 365; + + if (isLeapYear) { + ++days; + } +--- + +) + +$(LI $(B Printing) + +$(P +Printing part of a message differently depending on a condition: +) +--- + writeln("The glass is half ", + isOptimistic ? "full." : "empty."); +--- + +$(P +With an $(C if), the first and last parts of the message may be printed separately: +) + +--- + write("The glass is half "); + + if (isOptimistic) { + writeln("full."); + + } else { + writeln("empty."); + } +--- + +$(P +Alternatively, the entire message can be printed separately: +) + +--- + if (isOptimistic) { + writeln("The glass is half full."); + + } else { + writeln("The glass is half empty."); + } +--- + +) + +$(LI $(B Calculation) + +$(P +Increasing the score of the winner in a backgammon game 2 points or 1 point depending on whether the game has ended with gammon: +) + +--- + score += isGammon ? 2 : 1; +--- + +$(P +A straightforward equivalent using an $(C if): +) + +--- + if (isGammon) { + score += 2; + + } else { + score += 1; + } +--- + +$(P +An alternative also using an $(C if) is to first increment by one and then increment again if gammon: +) + +--- + ++score; + + if (isGammon) { + ++score; + } +--- + +) + +) + +$(P +As can be seen from the examples above, the code is more concise and clearer with the ternary operator in certain situations. +) + +$(H5 The type of the ternary expression) + +$(P +The value of the $(C ?:) operator is either the value of the truth expression or the value of the falsity expression. The types of these two expressions need not be the same but they must have a $(I common type). +) + +$(P +$(IX common type) The common type of two expressions is decided by a relatively complicated algorithm, involving $(LINK2 cast.html, type conversions) and $(LINK2 inheritance.html, inheritance). Additionally, depending on the expressions, the $(I kind) of the result is either $(LINK2 lvalue_rvalue.html, an lvalue or an rvalue). We will see these concepts in later chapters. +) + +$(P +For now, accept common type as a type that can represent both of the values without requiring an explicit cast. For example, the integer types $(C int) and $(C long) have a common type because they can both be represented as $(C long). On the other hand, $(C int) and $(C string) do not have a common type because neither $(C int) nor $(C string) can automatically be converted to the other type. +) + +$(P +Remember that a simple way of determining the type of an expression is using $(C typeof) and then printing its $(C .stringof) property: +) + +--- + int i; + double d; + + auto result = someCondition ? i : d; + writeln(typeof(result)$(HILITE .stringof)); +--- + +$(P +Because $(C double) can represent $(C int) but not the other way around, the common type of the ternary expression above is $(C double): +) + +$(SHELL +double +) + +$(P +To see an example of two expressions that do not have a common type, let's look at composing a message that reports the number of items to be shipped. Let's print "A dozen" when the value equals 12: "A $(B dozen) items will be shipped." Otherwise, let's have the message include the exact number: "$(B 3) items will be shipped." +) + +$(P +One might think that the varying part of the message can be selected with the $(C ?:) operator: +) + +--- + writeln( + (count == 12) ? "A dozen" : count, $(DERLEME_HATASI) + " items will be shipped."); +--- + +$(P +Unfortunately, the expressions do not have a common type because the type of $(STRING "A dozen") is $(C string) and the type of $(C count) is $(C int). +) + +$(P +A solution is to first convert $(C count) to $(C string). The function $(C to!string) from the $(C std.conv) module produces a $(C string) value from the specified parameter: +) + +--- +import std.conv; +// ... + writeln((count == 12) ? "A dozen" : to!string(count), + " items will be shipped."); +--- + +$(P +Now, as both of the selection expressions of the $(C ?:) operator are of $(C string) type, the code compiles and prints the expected message. +) + +$(PROBLEM_TEK + +$(P +Have the program read a single $(C int) value as $(I the net amount) where a positive value represents a gain and a negative value represents a loss. +) + +$(P +The program should print a message that contains "gained" or "lost" depending on whether the amount is positive or negative. For example, "$100 lost" or "$70 gained". Even though it may be more suitable, do not use the $(C if) statement in this exercise. +) + +) + + +Macros: + TITLE=Ternary Operator ?: + + DESCRIPTION=The ?: operator of the D programming language and comparing it to the if-else statement. + + KEYWORDS=d programming language tutorial book ternary operator diff --git a/book/d.en/to_be_continued.d b/book/d.en/to_be_continued.d new file mode 100644 index 0000000000..e3caf3fbfd --- /dev/null +++ b/book/d.en/to_be_continued.d @@ -0,0 +1,17 @@ +Ddoc + +$(B) +$(H4 The End) + +$(P +You can use $(LINK2 rss.xml, the RSS feed) to be notified about new chapters. +) + +Macros: + TITLE=To be continued... + + DESCRIPTION= + + KEYWORDS=d programming language tutorial book + +MINI_SOZLUK= diff --git a/book/d.en/tuples.d b/book/d.en/tuples.d new file mode 100644 index 0000000000..014044c4c8 --- /dev/null +++ b/book/d.en/tuples.d @@ -0,0 +1,575 @@ +Ddoc + +$(DERS_BOLUMU $(IX tuple) $(IX Tuple, std.typecons) Tuples) + +$(P +Tuples are for combining multiple values to be used as a single object. They are implemented as a library feature by the $(C Tuple) template from the $(C std.typecons) module. +) + +$(P +$(C Tuple) makes use of $(C AliasSeq) from the $(C std.meta) module for some of its operations. +) + +$(P +This chapter covers only the more common operations of tuples. For more information on tuples and templates see $(LINK2 https://github.com/PhilippeSigaud/D-templates-tutorial, Philippe Sigaud's $(I D Templates: A Tutorial)). +) + +$(H5 $(C Tuple) and $(C tuple())) + +$(P +Tuples are usually constructed by the convenience function $(C tuple()): +) + +--- +import std.stdio; +import std.typecons; + +void main() { + auto t = $(HILITE tuple(42, "hello")); + writeln(t); +} +--- + +$(P +The $(C tuple) call above constructs an object that consists of the $(C int) value 42 and the $(C string) value $(STRING "hello"). The output of the program includes the type of the tuple object and its members: +) + +$(SHELL +Tuple!(int, string)(42, "hello") +) + +$(P +The tuple type above is the equivalent of the following pseudo $(C struct) definition and likely have been implemented in exactly the same way: +) + +--- +// The equivalent of Tuple!(int, string) +struct __Tuple_int_string { + int __member_0; + string __member_1; +} +--- + +$(P +The members of a tuple are normally accessed by their index values. That syntax suggests that tuples can be seen as arrays consisting of different types of elements: +) + +--- + writeln(t$(HILITE [0])); + writeln(t$(HILITE [1])); +--- + +$(P +The output: +) + +$(SHELL +42 +hello +) + +$(H6 Member properties) + +$(P +It is possible to access the members by properties if the tuple is constructed directly by the $(C Tuple) template instead of the $(C tuple()) function. The type and the name of each member are specified as two consecutive template parameters: +) + +--- + auto t = Tuple!(int, "number", + string, "message")(42, "hello"); +--- + +$(P +The definition above allows accessing the members by $(C .number) and $(C .message) properties as well: +) + +--- + writeln("by index 0 : ", t[0]); + writeln("by .number : ", t$(HILITE .number)); + writeln("by index 1 : ", t[1]); + writeln("by .message: ", t$(HILITE .message)); +--- + +$(P +The output: +) + +$(SHELL +by index 0 : 42 +by .number : 42 +by index 1 : hello +by .message: hello +) + +$(H6 $(IX .expand) Expanding the members as a list of values) + +$(P +Tuple members can be expanded as a list of values that can be used e.g. as an argument list when calling a function. The members can be expanded either by the $(C .expand) property or by slicing: +) + +--- +import std.stdio; +import std.typecons; + +void foo(int i, string s, double d, char c) { + // ... +} + +void bar(int i, double d, char c) { + // ... +} + +void main() { + auto t = tuple(1, "2", 3.3, '4'); + + // Both of the following lines are equivalents of + // foo(1, "2", 3.3, '4'): + foo(t$(HILITE .expand)); + foo(t$(HILITE [])); + + // The equivalent of bar(1, 3.3, '4'): + bar(t$(HILITE [0]), t$(HILITE [$-2..$])); +} +--- + +$(P +The tuple above consists of four values of $(C int), $(C string), $(C double), and $(C char). Since those types match the parameter list of $(C foo()), an expansion of its members can be used as arguments to $(C foo()). When calling $(C bar()), a matching argument list is made up of the first member and the last two members of the tuple. +) + +$(P +As long as the members are compatible to be elements of the same array, the expansion of a tuple can be used as the element values of an array literal as well: +) + +--- +import std.stdio; +import std.typecons; + +void main() { + auto t = tuple(1, 2, 3); + auto a = [ t.expand, t[] ]; + writeln(a); +} +--- + +$(P +The array literal above is initialized by expanding the same tuple twice: +) + +$(SHELL +[1, 2, 3, 1, 2, 3] +) + +$(H6 $(IX foreach, compile-time) $(IX compile-time foreach) Compile-time $(C foreach)) + +$(P +Because their values can be expanded, tuples can be used with the $(C foreach) statement as well: +) + +--- + auto t = tuple(42, "hello", 1.5); + + foreach (i, member; $(HILITE t)) { + writefln("%s: %s", i, member); + } +--- + +$(P +The output: +) + +$(SHELL +0: 42 +1: hello +2: 1.5 +) + +$(P +$(IX unroll) +The $(C foreach) statement above may give a false impression: It may be thought of being a loop that gets executed at run time. That is not the case. Rather, a $(C foreach) statement that operates on the members of a tuple is an $(I unrolling) of the loop body for each member. The $(C foreach) statement above is the equivalent of the following code: +) + +--- + { + enum size_t i = 0; + $(HILITE int) member = t[i]; + writefln("%s: %s", i, member); + } + { + enum size_t i = 1; + $(HILITE string) member = t[i]; + writefln("%s: %s", i, member); + } + { + enum size_t i = 2; + $(HILITE double) member = t[i]; + writefln("%s: %s", i, member); + } +--- + +$(P +The reason for the unrolling is the fact that when the tuple members are of different types, the $(C foreach) body has to be compiled differently for each type. +) + +$(P +We will see $(C static foreach), a more powerful loop unrolling feature, in $(LINK2 static_foreach.html, a later chapter). +) + +$(H6 Returning multiple values from functions) + +$(P +$(IX findSplit, std.algorithm) Tuples can be a simple solution to the limitation of functions having to return a single value. An example of this is $(C std.algorithm.findSplit). $(C findSplit()) searches for a range inside another range and produces a result consisting of three pieces: the part before the found range, the found range, and the part after the found range: +) + +--- +import std.algorithm; + +// ... + + auto entireRange = "hello"; + auto searched = "ll"; + + auto result = findSplit(entireRange, searched); + + writeln("before: ", result[0]); + writeln("found : ", result[1]); + writeln("after : ", result[2]); +--- + +$(P +The output: +) + +$(SHELL +before: he +found : ll +after : o +) + +$(P +Another option for returning multiple values from a function is to return a $(C struct) object: +) + +--- +struct Result { + // ... +} + +$(HILITE Result) foo() { + // ... +} +--- + +$(H5 $(IX AliasSeq, std.meta) $(C AliasSeq)) + +$(P +$(C AliasSeq) is defined in the $(C std.meta) module. It is used for representing a concept that is normally used by the compiler but otherwise not available to the programmer as an entity: A comma-separated list of values, types, and symbols (i.e. $(C alias) template arguments). The following are three examples of such lists: +) + +$(UL +$(LI Function argument list) +$(LI Template argument list) +$(LI Array literal element list) +) + +$(P +The following three lines of code are examples of those lists in the same order: +) + +--- + foo($(HILITE 1, "hello", 2.5)); // function arguments + auto o = Bar!($(HILITE char, long))(); // template arguments + auto a = [ $(HILITE 1, 2, 3, 4) ]; // array literal elements +--- + +$(P +$(C Tuple) takes advantage of $(C AliasSeq) when expanding its members. +) + +$(P +$(IX TypeTuple, std.typetuple) The name $(C AliasSeq) comes from "alias sequence" and it can contain types, values, and symbols. ($(C AliasSeq) and $(C std.meta) used to be called $(C TypeTuple) and $(C std.typetuple), respectively.) +) + +$(P +This chapter includes $(C AliasSeq) examples that consist only of types or only of values. Examples of its use with both types and values will appear in the next chapter. $(C AliasSeq) is especially useful with variadic templates, which we will see in the next chapter as well. +) + +$(H6 $(C AliasSeq) consisting of values) + +$(P +The values that an $(C AliasSeq) represents are specified as its template arguments. +) + +$(P +Let's imagine a function that takes three parameters: +) + +--- +import std.stdio; + +void foo($(HILITE int i, string s, double d)) { + writefln("foo is called with %s, %s, and %s.", i, s, d); +} +--- + +$(P +That function would normally be called with three arguments: +) + +--- + foo(1, "hello", 2.5); +--- + +$(P +$(C AliasSeq) can combine those arguments as a single entity and can automatically be expanded when calling functions: +) + +--- +import std.meta; + +// ... + + alias arguments = AliasSeq!(1, "hello", 2.5); + foo($(HILITE arguments)); +--- + +$(P +Although it looks like the function is now being called with a single argument, the $(C foo()) call above is the equivalent of the previous one. As a result, both calls produce the same output: +) + +$(SHELL +foo is called with 1, hello, and 2.5. +) + +$(P +Also note that $(C arguments) is not defined as a variable, e.g. with $(C auto). Rather, it is an $(C alias) of a specific $(C AliasSeq) instance. Although it is possible to define variables of $(C AliasSeq)s as well, the examples in this chapter will use them only as aliases. +) + +$(P +As we have seen above with $(C Tuple), when the values are compatible to be elements of the same array, an $(C AliasSeq) can be used to initialize an array literal as well: +) + +--- + alias elements = AliasSeq!(1, 2, 3, 4); + auto arr = [ $(HILITE elements) ]; + assert(arr == [ 1, 2, 3, 4 ]); +--- + +$(H6 Indexing and slicing) + +$(P +Same with $(C Tuple), the members of an $(C AliasSeq) can be accessed by indexes and slices: +) + +--- + alias arguments = AliasSeq!(1, "hello", 2.5); + assert(arguments$(HILITE [0]) == 1); + assert(arguments$(HILITE [1]) == "hello"); + assert(arguments$(HILITE [2]) == 2.5); +--- + +$(P +Let's assume there is a function with parameters matching the last two members of the $(C AliasSeq) above. That function can be called with a slice of just the last two members of the $(C AliasSeq): +) + +--- +void bar(string s, double d) { + // ... +} + +// ... + + bar(arguments$(HILITE [$-2 .. $])); +--- + +$(H6 $(C AliasSeq) consisting of types) + +$(P +Members of an $(C AliasSeq) can consist of types. In other words, not a specific value of a specific type but a type like $(C int) itself. An $(C AliasSeq) consisting of types can represent template arguments. +) + +$(P +Let's use an $(C AliasSeq) with a $(C struct) template that has two parameters. The first parameter of this template determines the element type of a member array and the second parameter determines the return value of a member function: +) + +--- +import std.conv; + +struct S($(HILITE ElementT, ResultT)) { + ElementT[] arr; + + ResultT length() { + return to!ResultT(arr.length); + } +} + +void main() { + auto s = S!$(HILITE (double, int))([ 1, 2, 3 ]); + auto l = s.length(); +} +--- + +$(P +In the code above, we see that the template is instantiated with $(C (double, int)). An $(C AliasSeq) can represent the same argument list as well: +) + +--- +import std.meta; + +// ... + + alias Types = AliasSeq!(double, int); + auto s = S!$(HILITE Types)([ 1, 2, 3 ]); +--- + +$(P +Although it appears to be a single template argument, $(C Types) gets expanded automatically and the template instantiation becomes $(C S!(double, int)) as before. +) + +$(P +$(C AliasSeq) is especially useful in $(I variadic templates). We will see examples of this in the next chapter. +) + +$(H6 $(C foreach) with $(C AliasSeq)) + +$(P +Same with $(C Tuple), the $(C foreach) statement operating on an $(C AliasSeq) is not a run time loop. Rather, it is the unrolling of the loop body for each member. +) + +$(P +Let's see an example of this with a unit test written for the $(C S) struct that was defined above. The following code tests $(C S) for element types $(C int), $(C long), and $(C float) ($(C ResultT) is always $(C size_t) in this example): +) + +--- +unittest { + alias Types = AliasSeq!($(HILITE int, long, float)); + + foreach (Type; $(HILITE Types)) { + auto s = S!(Type, size_t)([ Type.init, Type.init ]); + assert(s.length() == 2); + } +} +--- + +$(P +The $(C foreach) variable $(C Type) corresponds to $(C int), $(C long), and $(C float), in that order. As a result, the $(C foreach) statement gets compiled as the equivalent of the code below: +) + +--- + { + auto s = S!($(HILITE int), size_t)([ $(HILITE int).init, $(HILITE int).init ]); + assert(s.length() == 2); + } + { + auto s = S!($(HILITE long), size_t)([ $(HILITE long).init, $(HILITE long).init ]); + assert(s.length() == 2); + } + { + auto s = S!($(HILITE float), size_t)([ $(HILITE float).init, $(HILITE float).init ]); + assert(s.length() == 2); + } +--- + +$(H5 $(IX .tupleof) $(C .tupleof) property) + +$(P +$(C .tupleof) represents the members of a type or an object. When applied to a user-defined type, $(C .tupleof) provides access to the definitions of the members of that type: +) + +--- +import std.stdio; + +struct S { + int number; + string message; + double value; +} + +void main() { + foreach (i, MemberType; typeof($(HILITE S.tupleof))) { + writefln("Member %s:", i); + writefln(" type: %s", MemberType.stringof); + + string name = $(HILITE S.tupleof)[i].stringof; + writefln(" name: %s", name); + } +} +--- + +$(P +$(C S.tupleof) appears in two places in the program. First, the types of the elements are obtained by applying $(C typeof) to $(C .tupleof) so that each type appears as the $(C MemberType) variable. Second, the name of the member is obtained by $(C S.tupleof[i].stringof). +) + +$(SHELL +Member 0: + type: int + name: number +Member 1: + type: string + name: message +Member 2: + type: double + name: value +) + +$(P +$(C .tupleof) can be applied to an object as well. In that case, it produces a tuple consisting of the values of the members of the object: +) + +--- + auto object = S(42, "hello", 1.5); + + foreach (i, member; $(HILITE object.tupleof)) { + writefln("Member %s:", i); + writefln(" type : %s", typeof(member).stringof); + writefln(" value: %s", member); + } +--- + +$(P +The $(C foreach) variable $(C member) represents each member of the object: +) + +$(SHELL +Member 0: + type : int + value: 42 +Member 1: + type : string + value: hello +Member 2: + type : double + value: 1.5 +) + +$(P +Here, an important point to make is that the tuple that $(C .tupleof) returns consists of the members of the object themselves, not their copies. In other words, the tuple members are references to the actual object members. +) + +$(H5 Summary) + +$(UL + +$(LI $(C tuple()) combines different types of values similar to a $(C struct) object.) + +$(LI Explicit use of $(C Tuple) allows accessing the members by properties.) + +$(LI The members can be expanded as a value list by $(C .expand) or by slicing.) + +$(LI $(C foreach) with a tuple is not a run time loop; rather, it is a loop unrolling.) + +$(LI $(C AliasSeq) represents concepts like function argument list, template argument list, array literal element list, etc.) + +$(LI $(C AliasSeq) can consist of values and types.) + +$(LI Tuples support indexing and slicing.) + +$(LI $(C .tupleof) provides information about the members of types and objects.) + +) + +macros: + TITLE=Tuples + + DESCRIPTION=Combining values and types to be able to access them as members of the same object. + + KEYWORDS=d programming language tutorial book Tuple AliasSeq tuple diff --git a/book/d.en/types.cozum.d b/book/d.en/types.cozum.d new file mode 100644 index 0000000000..862dde7a3e --- /dev/null +++ b/book/d.en/types.cozum.d @@ -0,0 +1,36 @@ +Ddoc + +$(COZUM_BOLUMU Fundamental Types) + + +$(P +We can use other types instead of $(C int): +) + +--- +import std.stdio; + +void main() { + writeln("Type : ", short.stringof); + writeln("Length in bytes: ", short.sizeof); + writeln("Minimum value : ", short.min); + writeln("Maximum value : ", short.max); + writeln("Initial value : ", short.init); + + writeln(); + + writeln("Type : ", ulong.stringof); + writeln("Length in bytes: ", ulong.sizeof); + writeln("Minimum value : ", ulong.min); + writeln("Maximum value : ", ulong.max); + writeln("Initial value : ", ulong.init); +} +--- + + +Macros: + TITLE=Fundamental Types Solutions + + DESCRIPTION=Programming in D exercise solutions: fundamental types + + KEYWORDS=programming in d tutorial solution diff --git a/book/d.en/types.d b/book/d.en/types.d new file mode 100644 index 0000000000..25e4e50d4e --- /dev/null +++ b/book/d.en/types.d @@ -0,0 +1,295 @@ +Ddoc + +$(DERS_BOLUMU $(IX type) $(IX fundamental type) Fundamental Types) + +$(P +We have seen that the brain of a computer is the CPU. Most of the tasks of a program are performed by the CPU and the rest are dispatched to other parts of the computer. +) + +$(P +The smallest unit of data in a computer is called $(I a bit). The value of a bit can be either 0 or 1. +) + +$(P +Since a type of data that can hold only the values 0 and 1 would have very limited use, the CPU supports larger data types that are combinations of more than one bit. As an example, a $(I byte) usually consists of 8 bits. If an N-bit data type is the most efficient data type supported by a CPU, we consider it to be an $(I N-bit CPU): as in 32-bit CPU, 64-bit CPU, etc. +) + +$(P +The data types that the CPU supports are still not sufficient: they can't represent higher level concepts like $(I name of a student) or $(I a playing card). Likewise, D's fundamental data types are not sufficient to represent many higher level concepts. Such concepts must be defined by the programmer as $(I structs) and $(I classes), which we will see in later chapters. +) + +$(P +$(IX bool) +$(IX byte) +$(IX ubyte) +$(IX short) +$(IX ushort) +$(IX int) +$(IX uint) +$(IX long) +$(IX ulong) +$(IX float) +$(IX double) +$(IX real) +$(IX ifloat) +$(IX idouble) +$(IX ireal) +$(IX cfloat) +$(IX cdouble) +$(IX creal) +$(IX char) +$(IX wchar) +$(IX dchar) +D's $(I fundamental types) are very similar to the fundamental types of many other languages, as seen in the following table. The terms that appear in the table are explained below: +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    D's Fundamental Data Types
    Type Definition Initial Value
    boolBoolean typefalse
    bytesigned 8 bits0
    ubyteunsigned 8 bits0
    shortsigned 16 bits0
    ushortunsigned 16 bits0
    intsigned 32 bits0
    uintunsigned 32 bits0
    longsigned 64 bits0L
    ulongunsigned 64 bits0LU
    float32-bit floating pointfloat.nan
    double64-bit floating pointdouble.nan
    realeither the largest floating point type that the hardware supports, or double; whichever is largerreal.nan
    ifloatimaginary value type of floatfloat.nan * 1.0i
    idoubleimaginary value type of doubledouble.nan * 1.0i
    irealimaginary value type of realreal.nan * 1.0i
    cfloatcomplex number type made of two floatsfloat.nan + float.nan * 1.0i
    cdoublecomplex number type made of two doublesdouble.nan + double.nan * 1.0i
    crealcomplex number type made of two realsreal.nan + real.nan * 1.0i
    charUTF-8 code unit0xFF
    wcharUTF-16 code unit0xFFFF
    dcharUTF-32 code unit and Unicode code point0x0000FFFF
    + +$(P +In addition to the above, the keyword $(C void) represents $(I having no type). The keywords $(C cent) and $(C ucent) are reserved for future use to represent signed and unsigned 128 bit values. +) + +$(P +Unless there is a specific reason not to, you can use $(C int) to represent whole values. To represent concepts that can have fractional values, consider $(C double). +) + +$(P +The following are the terms that appeared in the table: +) + +$(UL + +$(LI +$(B Boolean:) The type of logical expressions, having the value $(C true) for truth and $(C false) for falsity. +) + +$(LI +$(B Signed type:) A type that can have negative and positive values. For example, $(C byte) can have values from -128 to 127. The names of these types come from the negative $(I sign). +) + +$(LI +$(B Unsigned type:) A type that can have only positive values. For example, $(C ubyte) can have values from 0 to 255. The $(C u) at the beginning of the name of these types comes from $(I unsigned). +) + +$(LI +$(B Floating point:) The type that can represent values with fractions as in 1.25. The precision of floating point calculations are directly related to the bit count of the type: higher the bit count, more precise the results are. Only floating point types can represent fractions; integer types like $(C int) can only represent whole values like 1 and 2. +) + +$(LI +$(B Complex number type:) The type that can represent the complex numbers of mathematics. +) + +$(LI +$(B Imaginary number type:) The type that represents only the imaginary part of complex numbers. The $(C i) that appears in the Initial Value column is the square root of -1 in mathematics. +) + +$(LI +$(IX .nan) $(B nan:) Short for "not a number", representing $(I invalid floating point value). +) + +) + +$(H5 Properties of types) + +$(P +D types have $(I properties). Properties are accessed with a dot after the name of the type. For example, the $(C sizeof) property of $(C int) is accessed as $(C int.sizeof). We will see only some of type properties in this chapter: +) + +$(UL + +$(LI $(IX .stringof) $(C .stringof) is the name of the type) + +$(LI $(IX .sizeof) $(C .sizeof) is the length of the type in terms of bytes. (In order to determine the bit count, this value must be multiplied by 8, the number of bits in a $(C byte).) +) + +$(LI $(IX .min) $(C .min) is short for "minimum"; this is the smallest value that the type can have) + +$(LI $(IX .max) $(C .max) is short for "maximum"; this is the largest value that the type can have) + +$(LI $(IX .init) $(IX initial value) $(IX default value, type) $(C .init) is short for "initial value" (default value); this is the value that D assigns to a type when an initial value is not specified) + +) + +$(P +Here is a program that prints these properties for $(C int): +) + +--- +import std.stdio; + +void main() { + writeln("Type : ", int.stringof); + writeln("Length in bytes: ", int.sizeof); + writeln("Minimum value : ", int.min); + writeln("Maximum value : ", int.max); + writeln("Initial value : ", int.init); +} +--- + +$(P +The output of the program is the following: +) + +$(SHELL +Type : int +Length in bytes: 4 +Minimum value : -2147483648 +Maximum value : 2147483647 +Initial value : 0 +) + +$(H5 $(IX size_t) $(C size_t)) + +$(P +You will come across the $(C size_t) type as well. $(C size_t) is not a separate type but an alias of an existing unsigned type. Its name comes from "size type". It is the most suitable type to represent concepts like $(I size) or $(I count). +) + +$(P +$(C size_t) is large enough to represent the number of bytes of the memory that a program can potentially be using. Its actual size depends on the system: $(C uint) on a 32-bit system and $(C ulong) on a 64-bit system. For that reason, $(C ulong) is larger than $(C size_t) on a 32-bit system. +) + +$(P +You can use the $(C .stringof) property to see what $(C size_t) is an alias of on your system: +) + +--- +import std.stdio; + +void main() { + writeln(size_t.stringof); +} +--- + +$(P +The output of the program is the following on my system: +) + +$(SHELL +ulong +) + +$(PROBLEM_TEK + +$(P +Print the properties of other types. +) + +$(P +$(I $(B Note:) You can't use the reserved types $(C cent) and $(C ucent) in any program; and as an exception, $(C void) does not have the properties $(C .min), $(C .max) and $(C .init).) +) + +$(P +$(I Additionally, the $(C .min) property is deprecated for floating point types. (You can see all the various properties for the fundamental types in the $(LINK2 http://dlang.org/property.html, D property specification)). If you use a floating point type in this exercise, you would be warned by the compiler that $(C .min) is not valid for that type. Instead, as we will see later in $(LINK2 floating_point.html, the Floating Point Types chapter), you must use the negative of the $(C .max) property e.g. as $(C -double.max).) +) + +) + + +Macros: + TITLE=Fundamental Types + + DESCRIPTION=The fundamental types of the D programming language + + KEYWORDS=d programming language tutorial book fundamental types numeric limits diff --git a/book/d.en/uda.d b/book/d.en/uda.d new file mode 100644 index 0000000000..7e9742a428 --- /dev/null +++ b/book/d.en/uda.d @@ -0,0 +1,421 @@ +Ddoc + +$(DERS_BOLUMU $(IX user defined attributes) $(IX UDA) User Defined Attributes (UDA)) + +$(P +Any declaration (e.g. struct type, class type, variable, etc.) can be assigned attributes, which can then be accessed at compile time to alter the way the code is compiled. User defined attributes is purely a compile-time feature. +) + +$(P +$(IX @) The user defined attribute syntax consists of the $(C @) sign followed by the attribute and appear before the declaration that it is being assigned to. For example, the following code assigns the $(C Encrypted) attribute to the declaration of $(C name): +) + +--- + $(HILITE @Encrypted) string name; +--- + +$(P +Multiple attributes can be specified separately or as a parenthesized list of attributes. For example, both of the following variables have the same attributes: +) + +--- + @Encrypted @Colored string lastName; $(CODE_NOTE separately) + @$(HILITE $(PARANTEZ_AC))Encrypted, Colored$(HILITE $(PARANTEZ_KAPA)) string address; $(CODE_NOTE together) +--- + +$(P +An attribute can be a type name as well as a value of a user defined or a fundamental type. However, because their meanings may not be clear, attributes consisting of literal values like $(C 42) are discouraged: +) + +--- +$(CODE_NAME Encrypted)struct Encrypted { +} + +enum Color { black, blue, red } + +struct Colored { + Color color; +} + +void main() { + @Encrypted int a; $(CODE_NOTE type name) + @Encrypted() int b; $(CODE_NOTE object) + @Colored(Color.blue) int c; $(CODE_NOTE object) + @(42) int d; $(CODE_NOTE literal (discouraged)) +} +--- + +$(P +The attributes of $(C a) and $(C b) above are of different kinds: The attribute of $(C a) is the type $(C Encrypted) itself, while the attribute of $(C b) is an $(I object) of type $(C Encrypted). This is an important difference that affects the way attributes are used at compile time. We will see an example of this difference below. +) + +$(P +$(IX __traits) $(IX getAttributes) The meaning of attributes is solely determined by the programmer for the needs of the program. The attributes are determined by $(C __traits(getAttributes)) at compile time and the code is compiled according to those attributes. +) + +$(P +The following code shows how the attributes of a specific $(C struct) member (e.g. $(C Person.name)) can be accessed by $(C __traits(getAttributes)): +) + +--- +$(CODE_NAME Person)import std.stdio; + +// ... + +struct Person { + @Encrypted @Colored(Color.blue) string name; + string lastName; + @Colored(Color.red) string address; +} + +void $(CODE_DONT_TEST)main() { + foreach (attr; __traits($(HILITE getAttributes), Person.name)) { + writeln(attr.stringof); + } +} +--- + +$(P +The output of the program lists the attributes of $(C Person.name): +) + +$(SHELL +Encrypted +Colored(cast(Color)1) +) + +$(P +Two other $(C __traits) expressions are useful when dealing with user defined attributes: +) + +$(UL + +$(LI $(IX allMembers) $(C __traits(allMembers)) produces the members of a type (or a module) as strings.) + +$(LI $(IX getMember) $(C __traits(getMember)) produces a $(I symbol) useful when accessing a member. Its first argument is a symbol (e.g. a type or a variable name) and its second argument is a string. It produces a symbol by combining its first argument, a dot, and its second argument. For example, $(C __traits(getMember, Person, $(STRING "name"))) produces the symbol $(C Person.name). +) + +) + +--- +$(CODE_XREF Encrypted)$(CODE_XREF Person)import std.string; + +// ... + +void main() { + foreach (memberName; __traits($(HILITE allMembers), Person)) { + writef("The attributes of %-8s:", memberName); + + foreach (attr; __traits(getAttributes, + __traits($(HILITE getMember), + Person, memberName))) { + writef(" %s", attr.stringof); + } + + writeln(); + } +} +--- + +$(P +The output of the program lists all attributes of all members of $(C Person): +) + +$(SHELL +The attributes of name : Encrypted Colored(cast(Color)1) +The attributes of lastName: +The attributes of address : Colored(cast(Color)2) +) + +$(P +$(IX hasUDA, std.traits) Another useful tool is $(C std.traits.hasUDA), which determines whether a symbol has a specific attribute. The following $(C static assert) passes because $(C Person.name) has $(C Encrypted) attribute: +) + +--- +import std.traits; + +// ... + +static assert(hasUDA!(Person.name, Encrypted)); +--- + +$(P +$(C hasUDA) can be used with an attribute type as well as a specific value of that type. The following $(C static assert) checks both pass because $(C Person.name) has $(C Colored(Color.blue)) attribute: +) + +--- +static assert(hasUDA!(Person.name, $(HILITE Colored))); +static assert(hasUDA!(Person.name, $(HILITE Colored(Color.blue)))); +--- + +$(H5 Example) + +$(P +Let's design a function template that prints the values of all members of a $(C struct) object in XML format. The following function considers the $(C Encrypted) and $(C Colored) attributes of each member when producing the output: +) + +--- +void printAsXML(T)(T object) { +// ... + + foreach (member; __traits($(HILITE allMembers), T)) { // (1) + string value = + __traits($(HILITE getMember), object, member).to!string; // (2) + + static if ($(HILITE hasUDA)!(__traits(getMember, T, member), // (3) + Encrypted)) { + value = value.encrypted.to!string; + } + + writefln(` <%1$s color="%2$s">%3$s`, member, + $(HILITE colorAttributeOf)!(T, member), value); // (4) + } +} +--- + +$(P +The highlighted parts of the code are explained below: +) + +$(OL + +$(LI The members of the type are determined by $(C __traits(allMembers)).) + +$(LI The value of each member is converted to $(C string) to be used later when printing to the output. For example, when the member is $(STRING "name"), the right-hand side expression becomes $(C object.name.to!string).) + +$(LI Each member is tested with $(C hasUDA) to determine whether it has the $(C Encrypted) attribute. The value of the member is encrypted if it has that attribute. (Because $(C hasUDA) requires $(I symbols) to work with, note how $(C __traits(getMember)) is used to get the member as a symbol (e.g. $(C Person.name)).)) + +$(LI The color attribute of each member is determined with $(C colorAttributeOf()), which we will see below.) + +) + +$(P +The $(C colorAttributeOf()) function template can be implemented as in the following code: +) + +--- +Color colorAttributeOf(T, string memberName)() { + foreach (attr; __traits(getAttributes, + __traits(getMember, T, memberName))) { + static if (is ($(HILITE typeof(attr)) == Colored)) { + return attr.color; + } + } + + return Color.black; +} +--- + +$(P +When the compile-time evaluations are completed, the $(C printAsXML()) function template would be instantiated for the $(C Person) type as the equivalent of the following function: +) + +--- +/* The equivalent of the printAsXML!Person instance. */ +void printAsXML_Person(Person object) { +// ... + + { + string value = object.$(HILITE name).to!string; + $(HILITE value = value.encrypted.to!string;) + writefln(` <%1$s color="%2$s">%3$s`, + "name", Color.blue, value); + } + { + string value = object.$(HILITE lastName).to!string; + writefln(` <%1$s color="%2$s">%3$s`, + "lastName", Color.black, value); + } + { + string value = object.$(HILITE address).to!string; + writefln(` <%1$s color="%2$s">%3$s`, + "address", Color.red, value); + } +} +--- + +$(P +The complete program has more explanations: +) + +--- +import std.stdio; +import std.string; +import std.algorithm; +import std.conv; +import std.traits; + +/* Specifies that the symbol that it is assigned to should be + * encrypted. */ +struct Encrypted { +} + +enum Color { black, blue, red } + +/* Specifies the color of the symbol that it is assigned to. + * The default color is Color.black. */ +struct Colored { + Color color; +} + +struct Person { + /* This member is specified to be encrypted and printed in + * blue. */ + @Encrypted @Colored(Color.blue) string name; + + /* This member does not have any user defined + * attributes. */ + string lastName; + + /* This member is specified to be printed in red. */ + @Colored(Color.red) string address; +} + +/* Returns the value of the Colored attribute if the specified + * member has that attribute, Color.black otherwise. */ +Color colorAttributeOf(T, string memberName)() { + auto result = Color.black; + + foreach (attr; + __traits(getAttributes, + __traits(getMember, T, memberName))) { + static if (is (typeof(attr) == Colored)) { + result = attr.color; + } + } + + return result; +} + +/* Returns the Caesar-encrypted version of the specified + * string. (Warning: Caesar cipher is a very weak encryption + * method.) */ +auto encrypted(string value) { + return value.map!(a => dchar(a + 1)); +} + +unittest { + assert("abcdefghij".encrypted.equal("bcdefghijk")); +} + +/* Prints the specified object in XML format according to the + * attributes of its members. */ +void printAsXML(T)(T object) { + writefln("<%s>", T.stringof); + scope(exit) writefln("", T.stringof); + + foreach (member; __traits(allMembers, T)) { + string value = + __traits(getMember, object, member).to!string; + + static if (hasUDA!(__traits(getMember, T, member), + Encrypted)) { + value = value.encrypted.to!string; + } + + writefln(` <%1$s color="%2$s">%3$s`, + member, colorAttributeOf!(T, member), value); + } +} + +void main() { + auto people = [ Person("Alice", "Davignon", "Avignon"), + Person("Ben", "de Bordeaux", "Bordeaux") ]; + + foreach (person; people) { + printAsXML(person); + } +} +--- + +$(P +The output of the program shows that the members have the correct color and that the $(C name) member is encrypted: +) + +$(SHELL +<Person> + <name color="blue">Bmjdf</name> $(SHELL_NOTE blue and encrypted) + <lastName color="black">Davignon</lastName> + <address color="red">Avignon</address> $(SHELL_NOTE red) +</Person> +<Person> + <name color="blue">Cfo</name> $(SHELL_NOTE blue and encrypted) + <lastName color="black">de Bordeaux</lastName> + <address color="red">Bordeaux</address> $(SHELL_NOTE red) +</Person> +) + +$(H5 The benefit of user defined attributes) + +$(P +The benefit of user defined attributes is being able to change the attributes of declarations without needing to change any other part of the program. For example, all of the members of $(C Person) can become encrypted in the XML output by the trivial change below: +) + +--- +struct Person { + $(HILITE @Encrypted) { + string name; + string lastName; + string address; + } +} + +// ... + + printAsXML(Person("Cindy", "de Cannes", "Cannes")); +--- + +$(P +The output: +) + +$(SHELL +<Person> + <name color="black">Djoez</name> $(SHELL_NOTE encrypted) + <lastName color="black">ef!Dbooft</lastName> $(SHELL_NOTE encrypted) + <address color="black">Dbooft</address> $(SHELL_NOTE encrypted) +</Person> +) + +$(P +Further, $(C printAsXML()) and the attributes that it considers can be used with other types as well: +) + +--- +struct Data { + $(HILITE @Colored(Color.blue)) string message; +} + +// ... + + printAsXML(Data("hello world")); +--- + +$(P +The output: +) + +$(SHELL +<Data> + <message color="blue">hello world</message> $(SHELL_NOTE blue) +</Data> +) + +$(H5 Summary) + +$(UL + +$(LI User defined attributes can be assigned to any declaration.) + +$(LI User defined attributes can be type names as well as values.) + +$(LI User defined attributes can be accessed at compile time by $(C hasUDA) and $(C __traits(getAttributes)) to alter the way the program is compiled.) + +) + +macros: + TITLE=User Defined Attributes (UDA) + + DESCRIPTION=Assigning user defined attributes to declarations, determining the attributes at compile time, and compiling the code according to those attributes. + + KEYWORDS=d programming language tutorial book user defined attributes UDA diff --git a/book/d.en/ufcs.d b/book/d.en/ufcs.d new file mode 100644 index 0000000000..b205ee41f8 --- /dev/null +++ b/book/d.en/ufcs.d @@ -0,0 +1,227 @@ +Ddoc + +$(DERS_BOLUMU $(IX UFCS) $(IX universal function call syntax) Universal Function Call Syntax (UFCS)) + +$(P +UFCS is a feature that is applied by the compiler automatically. It enables the member function syntax even for regular functions. It can be explained simply by comparing two expressions: +) + +--- + variable.foo($(I arguments)) +--- + +$(P +When the compiler encounters an expression such as the one above, if there is no member function named $(C foo) that can be called on $(C variable) with the provided arguments, then the compiler also tries to compile the following expression: +) + +--- + foo(variable, $(I arguments)) +--- + +$(P +If this new expression can indeed be compiled, then the compiler simply accepts that one. As a result, although $(C foo()) evidently has been a regular function, it gets accepted to be used by the member function syntax. +) + +$(P +$(I $(B Note:) UFCS considers only functions that are defined at module scope; for example, $(LINK2 nested.html, nested functions) cannot be called with the UFCS syntax.) +) + +$(P +We know that functions that are closely related to a type are defined as member functions of that type. This is especially important for encapsulation as only the member functions of a type (and that type's module) can access its $(C private) members. +) + +$(P +Let's consider a $(C Car) class which maintains the amount of fuel: +) + +--- +$(CODE_NAME Car)class Car { + enum economy = 12.5; // kilometers per liter (average) + private double fuelAmount; // liters + + this(double fuelAmount) { + this.fuelAmount = fuelAmount; + } + + double fuel() const { + return fuelAmount; + } + + // ... +} +--- + +$(P +Although member functions are very useful and sometimes necessary, not every function that operates on a type should be a member function. Some operations on a type are too specific to a certain application to be member functions. For example, a function that determines whether a car can travel a specific distance may more appropriately be defined as a regular function: +) + +--- +$(CODE_NAME canTravel)bool canTravel(Car car, double distance) { + return (car.fuel() * car.economy) >= distance; +} +--- + +$(P +This naturally brings a discrepancy in calling functions that are related to a type: objects appear at different places in these two syntaxes: +) + +--- +$(CODE_XREF Car)$(CODE_XREF canTravel)void main() { + auto car = new Car(5); + + auto remainingFuel = $(HILITE car).fuel(); // Member function syntax + + if (canTravel($(HILITE car), 100)) { // Regular function syntax + // ... + } +} +--- + +$(P +UFCS removes this discrepancy by allowing regular functions to be called by the member function syntax: +) + +--- + if ($(HILITE car).canTravel(100)) { // Regular function, called by the + // member function syntax + // ... + } +--- + +$(P +This feature is available for fundamental types as well, including literals: +) + +--- +int half(int value) { + return value / 2; +} + +void main() { + assert(42.half() == 21); +} +--- + +$(P +As we will see in the next chapter, when there are no arguments to pass to a function, that function can be called without parentheses. When that feature is used as well, the expression above gets even shorter. All three of the following statements are equivalent: +) + +--- + result = half(value); + result = value.half(); + result = value.half; +--- + +$(P +$(IX chaining, function call) $(IX function call chaining) UFCS is especially useful when function calls are $(I chained). Let's see this on a group of functions that operate on $(C int) slices: +) + +--- +$(CODE_NAME functions)// Returns the result of dividing all of the elements by +// 'divisor' +int[] divide(int[] slice, int divisor) { + int[] result; + result.reserve(slice.length); + + foreach (value; slice) { + result ~= value / divisor; + } + + return result; +} + +// Returns the result of multiplying all of the elements by +// 'multiplier' +int[] multiply(int[] slice, int multiplier) { + int[] result; + result.reserve(slice.length); + + foreach (value; slice) { + result ~= value * multiplier; + } + + return result; +} + +// Filters out elements that have odd values +int[] evens(int[] slice) { + int[] result; + result.reserve(slice.length); + + foreach (value; slice) { + if (!(value % 2)) { + result ~= value; + } + } + + return result; +} +--- + +$(P +When written by the regular syntax, without taking advantage of UFCS, an expression that chains three calls to these functions can be written as in the following program: +) + +--- +$(CODE_XREF functions)import std.stdio; + +// ... + +void main() { + auto values = [ 1, 2, 3, 4, 5 ]; + writeln(evens(divide(multiply(values, 10), 3))); +} +--- + +$(P +The values are first multiplied by 10, then divided by 3, and finally only the even numbers are used: +) + +$(SHELL +[6, 10, 16] +) + +$(P +A problem with the expression above is that although the pair of $(C multiply) and $(C 10) are related and the pair of $(C divide) and $(C 3) are related, parts of each pair end up written away from each other. UFCS eliminates this issue and enables a more natural syntax that reflects the actual order of operations: +) + +--- + writeln(values.multiply(10).divide(3).evens); +--- + +$(P +Some programmers take advantage of UFCS even for calls like $(C writeln()): +) + +--- + values.multiply(10).divide(3).evens.writeln; +--- + +$(P +As an aside, the entire program above could have been written in a much simpler way by $(C map()) and $(C filter()): +) + +--- +import std.stdio; +import std.algorithm; + +void main() { + auto values = [ 1, 2, 3, 4, 5 ]; + + writeln(values + .map!(a => a * 10) + .map!(a => a / 3) + .filter!(a => !(a % 2))); +} +--- + +$(P +The program above takes advantage of $(LINK2 templates.html, templates), $(LINK2 ranges.html, ranges), and $(LINK2 lambda.html, lambda functions), all of which will be explained in later chapters. +) + +Macros: + TITLE=Universal Function Call Syntax (UFCS) + + DESCRIPTION=Universal function call syntax: The ability to call regular functions by the member function syntax. + + KEYWORDS=d programming lesson book tutorial encapsulation diff --git a/book/d.en/union.d b/book/d.en/union.d new file mode 100644 index 0000000000..45b661b102 --- /dev/null +++ b/book/d.en/union.d @@ -0,0 +1,412 @@ +Ddoc + +$(DERS_BOLUMU $(IX union) Unions) + +$(P +Unions, a low-level feature inherited from the C programming language, allow more than one member to share the same memory area. +) + +$(P +Unions are very similar to structs with the following main differences: +) + +$(UL + +$(LI Unions are defined by the $(C union) keyword.) + +$(LI The members of a $(C union) are not independent; they share the same memory area.) + +) + +$(P +Just like structs, unions can have member functions as well. +) + +$(P +$(IX -m32, compiler switch) The examples below will produce different results depending on whether they are compiled on a 32-bit or a 64-bit environment. To avoid getting confusing results, please use the $(C -m32) compiler switch when compiling the examples in this chapter. Otherwise, your results may be different than mine due to $(I alignment), which we will see in a later chapter. +) + +$(P +Naturally, $(C struct) objects are as large as necessary to accommodate all of their members: +) + +--- +// Note: Please compile with the -m32 compiler switch +struct S { + int i; + double d; +} + +// ... + + writeln(S.sizeof); +--- + +$(P +Since $(C int) is 4 bytes long and $(C double) is 8 bytes long, the size of that $(C struct) is the sum of their sizes: +) + +$(SHELL_SMALL +12 +) + +$(P +In contrast, the size of a $(C union) with the same members is only as large as its largest member: +) + +--- +$(HILITE union) U { + int i; + double d; +} + +// ... + + writeln(U.sizeof); +--- + +$(P +The 4-byte $(C int) and the 8-byte $(C double) share the same area. As a result, the size of the entire $(C union) is the same as its largest member: +) + +$(SHELL_SMALL +8 +) + +$(P +Unions are not a memory-saving feature. It is impossible to fit multiple data into the same memory location. The purpose of a union is to use the same area for different type of data at different times. Only one of the members can be used reliably at one time. However, although doing so may not be portable to different platforms, $(C union) members can be used for accessing fragments of other members. +) + +$(P +One of the examples below takes advantage of $(C typeid) to disallow access to members other than the one that is currently valid. +) + +$(P +The following diagram shows how the 8 bytes of the $(C union) above are shared by its members: +) + +$(MONO + 0 1 2 3 4 5 6 7 +───┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬─── + │$(HILITE <─── 4 bytes for int ───>) │ + │$(HILITE <─────────────── 8 bytes for double ────────────────>)│ +───┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴─── +) + +$(P +Either all of the 8 bytes are used for the $(C double) member, or only the first 4 bytes are used for the $(C int) member and the other 4 bytes are unused. +) + +$(P +Unions can have as many members as needed. All of the members would share the same memory location. +) + +$(P +The fact that the same memory location is used for all of the members can have surprising effects. For example, let's initialize a $(C union) object by its $(C int) member and then access its $(C double) member: +) + +--- + auto u = U(42); // initializing the int member + writeln(u.d); // accessing the double member +--- + +$(P +Initializing the $(C int) member by the value 42 sets just the first 4 bytes, and this affects the $(C double) member in an unpredictable way: +) + +$(SHELL_SMALL +2.07508e-322 +) + +$(P +Depending on the endianness of the microprocessor, the 4 bytes may be arranged in memory as 0|0|0|42, 42|0|0|0, or in some other order. For that reason, the value of the $(C double) member may appear differently on different platforms. +) + +$(H5 $(IX anonymous union) Anonymous unions) + +$(P +Anonymous unions specify what members of a user-defined type share the same area: +) + +--- +struct S { + int first; + + union { + int second; + int third; + } +} + +// ... + + writeln(S.sizeof); +--- + +$(P +The last two members of $(C S) share the same area. So, the size of the $(C struct) is a total of two $(C int)s: 4 bytes needed for $(C first) and another 4 bytes to be shared by $(C second) and $(C third): +) + +$(SHELL_SMALL +8 +) + +$(H5 Dissecting other members) + +$(P +Unions can be used for accessing individual bytes of variables of other types. For example, they make it easy to access the 4 bytes of an IPv4 address individually. +) + +$(P +The 32-bit value of the IPv4 address and a fixed-length array can be defined as the two members of a $(C union): +) + +--- +$(CODE_NAME IpAddress)union IpAddress { + uint value; + ubyte[4] bytes; +} +--- + +$(P +The members of that $(C union) would share the same memory area as in the following figure: +) + +$(MONO + 0 1 2 3 +───┬──────────┬──────────┬──────────┬──────────┬─── + │$(HILITE <──── 32 bits of the IPv4 address ────> )│ + │ bytes[0] │ bytes[1] │ bytes[2] │ bytes[3] │ +───┴──────────┴──────────┴──────────┴──────────┴─── +) + +$(P +For example, when an object of this $(C union) is initialized by 0xc0a80102 (the value that corresponds to the dotted form 192.168.1.2), the elements of the $(C bytes) array would automatically have the values of the four octets: +) + +--- +$(CODE_XREF IpAddress)import std.stdio; + +void main() { + auto address = IpAddress(0xc0a80102); + writeln(address$(HILITE .bytes)); +} +--- + +$(P +When run on a little-endian system, the octets would appear in reverse of their dotted form: +) + +$(SHELL_SMALL +[2, 1, 168, 192] +) + +$(P +The reverse order of the octets is another example of how accessing different members of a $(C union) may produce unpredictable results. This is because the behavior of a $(C union) is guaranteed only if that $(C union) is used through just one of its members. There are no guarantees on the values of the members other than the one that the $(C union) has been initialized with. +) + +$(P +$(IX bswap, std.bitop) $(IX endian, std.system) Although it is not directly related to this chapter, $(C bswap) from the $(C core.bitop) module is useful in dealing with endianness issues. $(C bswap) returns its parameter after swapping its bytes. Also taking advantage of the $(C endian) value from the $(C std.system) module, the octets of the previous IPv4 address can be printed in the expected order after swapping its bytes: +) + +--- +import std.system; +import core.bitop; + +// ... + + if (endian == Endian.littleEndian) { + address.value = bswap(address.value); + } +--- + +$(P +The output: +) + +$(SHELL_SMALL +[192, 168, 1, 2] +) + +$(P +Please take the $(C IpAddress) type as a simple example; in general, it would be better to consider a dedicated networking module for non-trivial programs. +) + +$(H5 Examples) + +$(H6 Communication protocol) + +$(P +In some protocols like TCP/IP, the meanings of certain parts of a protocol packet depend on a specific value inside the same packet. Usually, it is a field in the header of the packet that determines the meanings of successive bytes. Unions can be used for representing such protocol packets. +) + +$(P +The following design represents a protocol packet that has two kinds: +) + +--- +struct Host { + // ... +} + +struct ProtocolA { + // ... +} + +struct ProtocolB { + // ... +} + +enum ProtocolType { A, B } + +struct NetworkPacket { + Host source; + Host destination; + ProtocolType $(HILITE type); + + $(HILITE union) { + ProtocolA aParts; + ProtocolB bParts; + } + + ubyte[] payload; +} +--- + +$(P +The $(C struct) above can make use of the $(C type) member to determine whether $(C aParts) or $(C bParts) of the $(C union) to be used. +) + +$(H6 $(IX discriminated union) Discriminated union) + +$(P +Discriminated union is a data structure that brings type safety over a regular $(C union). Unlike a $(C union), it does not allow accessing the members other than the one that is currently valid. +) + +$(P +The following is a simple discriminated union type that supports only two types: $(C int) and $(C double). In addition to a $(C union) to store the data, it maintains a $(LINK2 object.html, $(C TypeInfo)) member to know which one of the two $(C union) members is valid. +) + +--- +$(CODE_NAME Discriminated)import std.stdio; +import std.exception; + +struct Discriminated { +private: + + TypeInfo validType_; + + union { + int i_; + double d_; + } + +public: + + this(int value) { + // This is a call to the property function below: + i = value; + } + + // Setter for 'int' data + void i(int value) { + i_ = value; + validType_ $(HILITE = typeid(int)); + } + + // Getter for 'int' data + int i() const { + enforce(validType_ $(HILITE == typeid(int)), + "The data is not an 'int'."); + return i_; + } + + this(double value) { + // This is a call to the property function below: + d = value; + } + + // Setter for 'double' data + void d(double value) { + d_ = value; + validType_ $(HILITE = typeid(double)); + } + + // Getter for 'double' data + double d() const { + enforce(validType_ $(HILITE == typeid(double)), + "The data is not a 'double'." ); + return d_; + } + + // Identifies the type of the valid data + const(TypeInfo) type() const { + return validType_; + } +} + +unittest { + // Let's start with 'int' data + auto var = Discriminated(42); + + // The type should be reported as 'int' + assert(var.type == typeid(int)); + + // 'int' getter should work + assert(var.i == 42); + + // 'double' getter should fail + assertThrown(var.d); + + // Let's replace 'int' with 'double' data + var.d = 1.5; + + // The type should be reported as 'double' + assert(var.type == typeid(double)); + + // Now 'double' getter should work ... + assert(var.d == 1.5); + + // ... and 'int' getter should fail + assertThrown(var.i); +} +--- + +$(P +$(IX Variant, std.variant) $(IX Algebraic, std.variant) This is just an example. You should consider using $(C Algebraic) and $(C Variant) from the $(C std.variant) module in your programs. Additionally, this code could take advantage of other features of D like $(LINK2 templates.html, templates) and $(LINK2 mixin.html, mixins) to reduce code duplication. +) + +$(P +Regardless of the data that is being stored, there is only one $(C Discriminated) type. (An alternative template solution could take the data type as a template parameter, in which case each instantiation of the template would be a distinct type.) For that reason, it is possible to have an array of $(C Discriminated) objects, effectively enabling a collection where elements can be of different types. However, the user must still know the valid member before accessing it. For example, the following function determines the actual type of the valid data with the $(C type) property of $(C Discriminated): +) + +--- +$(CODE_XREF Discriminated)void main() { + Discriminated[] arr = [ Discriminated(1), + Discriminated(2.5) ]; + + foreach (value; arr) { + if (value.type $(HILITE == typeid(int))) { + writeln("Working with an 'int' : ", value$(HILITE .i)); + + } else if (value.type $(HILITE == typeid(double))) { + writeln("Working with a 'double': ", value$(HILITE .d)); + + } else { + assert(0); + } + } +} +--- + +$(SHELL +Working with an 'int' : 1 +Working with a 'double': 2.5 +) + +Macros: + TITLE=Unions + + DESCRIPTION=Unions, the feature that allows sharing the same memory area for more than one member. + + KEYWORDS=d programming language tutorial book union diff --git a/book/d.en/unit_testing.cozum.d b/book/d.en/unit_testing.cozum.d new file mode 100644 index 0000000000..714efcf030 --- /dev/null +++ b/book/d.en/unit_testing.cozum.d @@ -0,0 +1,190 @@ +Ddoc + +$(COZUM_BOLUMU Unit Testing) + +$(P +The first thing to do is to compile and run the program to ensure that the tests actually work and indeed fail: +) + +$(SHELL +$ dmd deneme.d -w -unittest +$ ./deneme +$(SHELL_OBSERVED core.exception.AssertError@deneme(11): unittest failure) +) + +$(P +The line number 11 indicates that the first one of the tests has failed. +) + +$(P +For demonstration purposes let's write an obviously incorrect implementation that passes the first test by accident. The following function simply returns a copy of the input: +) + +--- +dstring toFront(dstring str, dchar letter) { + dstring result; + + foreach (c; str) { + result ~= c; + } + + return result; +} + +unittest { + immutable str = "hello"d; + + assert(toFront(str, 'h') == "hello"); + assert(toFront(str, 'o') == "ohell"); + assert(toFront(str, 'l') == "llheo"); +} + +void main() { +} +--- + +$(P +The first test passes but the second one fails: +) + +$(SHELL +$ ./deneme +$(SHELL_OBSERVED core.exception.AssertError@deneme.d($(HILITE 17)): unittest failure) +) + +$(P +Here is a correct implementation that passes all of the tests: +) + +--- +dstring toFront(dstring str, dchar letter) { + dchar[] firstPart; + dchar[] lastPart; + + foreach (c; str) { + if (c == letter) { + firstPart ~= c; + + } else { + lastPart ~= c; + } + } + + return (firstPart ~ lastPart).idup; +} + +unittest { + immutable str = "hello"d; + + assert(toFront(str, 'h') == "hello"); + assert(toFront(str, 'o') == "ohell"); + assert(toFront(str, 'l') == "llheo"); +} + +void main() { +} +--- + +$(P +The tests finally pass: +) + +$(SHELL +$ ./deneme +$ +) + +$(P +This function can now be modified in different ways under the confidence that its tests will have to pass. The following two implementations are very different from the first one but they too are correct according to the tests. +) + +$(UL + +$(LI +An implementation that takes advantage of $(C std.algorithm.partition): + +--- +import std.algorithm; + +dstring toFront(dstring str, dchar letter) { + dchar[] result = str.dup; + partition!(c => c == letter, SwapStrategy.stable)(result); + + return result.idup; +} + +unittest { + immutable str = "hello"d; + + assert(toFront(str, 'h') == "hello"); + assert(toFront(str, 'o') == "ohell"); + assert(toFront(str, 'l') == "llheo"); +} + +void main() { +} +--- + +$(P +$(I $(B Note:) The $(C =>) syntax that appears in the program above creates a $(I lambda function). We will see lambda functions in later chapters.) +) + +) + +$(LI +The following implementation first counts how many times the special letter appears in the string. That information is then sent to a separate function named $(C repeated()) to produce the first part of the result. Note that $(C repeated()) has a set of unit tests of its own: + +--- +dstring repeated(size_t count, dchar letter) { + dstring result; + + foreach (i; 0..count) { + result ~= letter; + } + + return result; +} + +unittest { + assert(repeated(3, 'z') == "zzz"); + assert(repeated(10, 'é') == "éééééééééé"); +} + +dstring toFront(dstring str, dchar letter) { + size_t specialLetterCount; + dstring lastPart; + + foreach (c; str) { + if (c == letter) { + ++specialLetterCount; + + } else { + lastPart ~= c; + } + } + + return repeated(specialLetterCount, letter) ~ lastPart; +} + +unittest { + immutable str = "hello"d; + + assert(toFront(str, 'h') == "hello"); + assert(toFront(str, 'o') == "ohell"); + assert(toFront(str, 'l') == "llheo"); +} + +void main() { +} +--- + +) + +) + +Macros: + TITLE=Unit Testing + + DESCRIPTION=The exercise solutions for the Unit Testing chapter. + + KEYWORDS=programming in d tutorial unit testing diff --git a/book/d.en/unit_testing.d b/book/d.en/unit_testing.d new file mode 100644 index 0000000000..60092403cf --- /dev/null +++ b/book/d.en/unit_testing.d @@ -0,0 +1,530 @@ +Ddoc + +$(DERS_BOLUMU $(IX unit testing) $(IX test) Unit Testing) + +$(P +As it should be known by most people, any device that runs some piece of computer program contains software bugs. Software bugs plague computer devices from the simplest to the most complex. Debugging and fixing software bugs is among the less favorable daily activities of a programmer. +) + +$(H5 $(IX bug, causes of) Causes of bugs) + +$(P +There are many reasons why software bugs occur. The following is an incomplete list roughly from the design stage of a program through the actual coding of it: +) + +$(UL + +$(LI +The requirements and the specifications of the program may not be clear. What the program should actually do may not be known at the design stage. +) + +$(LI +The programmer may misunderstand some of the requirements of the program. +) + +$(LI +The programming language may not be expressive enough. Considering that there are confusions even between native speakers of human languages, the unnatural syntax and rules of a programming language may be cause of mistakes. +) + +$(LI +Certain assumptions of the programmer may be incorrect. For example, the programmer may be assuming that 3.14 would be precise enough to represent π. +) + +$(LI +The programmer may have incorrect information on a topic or none at all. For example, the programmer may not know that using a floating point variable in a particular logical expression would not be reliable. +) + +$(LI +The program may encounter an unforeseen situation. For example, one of the files of a directory may be deleted or renamed while the program is using the files of that directory in a $(C foreach) loop. +) + +$(LI +The programmer may make silly mistakes. For example, the name of a variable may be mistyped and accidentally matched the name of another variable. +) + +$(LI etc.) + +) + +$(P +Unfortunately, there is still no software development methodology that ensures that a program will always work correctly. This is still a hot software engineering topic where promising solutions emerge every decade or so. +) + +$(H5 Discovering the bugs) + +$(P +Software bugs are discovered at various stages of the lifetime of the program by various types of tools and people. The following is a partial list of when a bug may be discovered, from the earliest to the latest: +) + +$(UL +$(LI When writing the program + +$(UL +$(LI By the programmer +) + +$(LI By another programmer during $(I pair programming) +) + +$(LI By the compiler through compiler messages +) + +$(LI By $(HILITE unit tests) as a part of building the program +) + +) + +) + +$(LI When reviewing the code + +$(UL +$(LI By tools that analyze the code at compile time +) + +$(LI By other programmers during $(I code reviews) +) +) + +) + +$(LI When running the program + +$(UL +$(LI By tools that analyze the execution of the program at run time (e.g. by valgrind) +) + +$(LI During QA testing, either by the failure of $(C assert) checks or by the observed behavior of the program +) + +$(LI By the $(I beta) users before the release of the program +) + +$(LI By the end users after the release of the program) + +) + +) + +) + +$(P +Detecting bugs as early as possible reduces loss of money, time, and in some cases human lives. Additionally, identifying the causes of bugs that have been discovered by the end users are harder than identifying the causes of bugs that are discovered early, during development. +) + +$(H5 Unit testing for catching bugs) + +$(P +Since programs are written by programmers and D is a compiled language, the programmers and the compiler will always be there to discover bugs. Those two aside, the earliest and partly for that reason the most effective way of catching bugs is unit testing. +) + +$(P +Unit testing is an indispensable part of modern programming. It is the most effective method of reducing coding errors. According to some development methodologies, code that is not guarded by unit tests is buggy code. +) + +$(P +Unfortunately, the opposite is not true: Unit tests do not guarantee that the code is free of bugs. Although they are very effective, they can only reduce the risk of bugs. +) + +$(P +Unit testing also enables refactoring the code (i.e. making improvements to it) with ease and confidence. Otherwise, it is common to accidentally break some of the existing functionality of a program when adding new features to it. Bugs of this type are called $(I regressions). Without unit testing, regressions are sometimes discovered as late as during the QA testing of future releases, or worse, by the end users. +) + +$(P +Risk of regressions discourage programmers from refactoring the code, sometimes preventing them from performing the simplest of improvements like correcting the name of a variable. This in turn causes $(I code rot), a condition where the code becomes more and more unmaintainable. For example, although some lines of code would better be moved to a newly defined function in order to be called from more than one place, fear of regressions make programmers copy and paste the existing lines to other places instead, leading to the problem of $(I code duplication). +) + +$(P +Phrases like "if it isn't broken, don't fix it" are related to fear of regressions. Although they seem to be conveying wisdom, such guidelines cause the code to rot slowly and become an untouchable mess. +) + +$(P +Modern programming rejects such "wisdom". To the contrary, to prevent it from becoming a source of bugs, the code is supposed to be "refactored mercilessly". The most powerful tool of this modern approach is unit testing. +) + +$(P +Unit testing involves testing the smallest units of code independently. When units of code are tested independently, it is less likely that there are bugs in higher-level code that use those units. When the parts work correctly, it is more likely that the whole will work correctly as well. +) + +$(P +Unit tests are provided as library solutions in other languages (e.g. JUnit, CppUnit, Unittest++, etc.) In D, unit testing is a core feature of the language. It is debatable whether a library solution or a language feature is better for unit testing. Because D does not provide some of the features that are commonly found in unit testing libraries, it may be worthwhile to consider library solutions as well. +) + +$(P +The unit testing features of D are as simple as inserting $(C assert) checks into $(C unittest) blocks. +) + +$(H5 $(IX -unittest, compiler switch) Activating the unit tests) + +$(P +Unit tests are not a part of the actual execution of the program. They should be activated only during program development when explicitly requested. +) + +$(P +The $(C dmd) compiler switch that activates unit tests is $(C ‑unittest). +) + +$(P +Assuming that the program is written in a single source file named $(C deneme.d), its unit tests can be activated by the following command: +) + +$(SHELL +$ dmd deneme.d -w $(HILITE -unittest) +) + +$(P +When a program that is built by the $(C ‑unittest) switch is started, its unit test blocks are executed first. Only if all of the unit tests pass then the program execution continues with $(C main()). +) + +$(H5 $(IX unittest) $(C unittest) blocks) + +$(P +The lines of code that involve unit tests are written inside $(C unittest) blocks. These blocks do not have any significance for the program other than containing the unit tests: +) + +--- +unittest { + /* ... the tests and the code that support them ... */ +} +--- + +$(P +Although $(C unittest) blocks can appear anywhere, it is convenient to define them right after the code that they test. +) + +$(P +As an example, let's test a function that returns the ordinal form of the specified number as in "1st", "2nd", etc. A $(C unittest) block of this function can simply contain $(C assert) statements that compare the return values of the function to the expected values. The following function is being tested with the four distinct expected outcomes of the function: +) + +--- +string ordinal(size_t number) { + // ... +} + +$(HILITE unittest) { + assert(ordinal(1) == "1st"); + assert(ordinal(2) == "2nd"); + assert(ordinal(3) == "3rd"); + assert(ordinal(10) == "10th"); +} +--- + +$(P +The four tests above test that the function works correctly at least for the values of 1, 2, 3, and 10 by making four separate calls to the function and comparing the returned values to the expected ones. +) + +$(P +Although unit tests are based on $(C assert) checks, $(C unittest) blocks can contain any D code. This allows for preparations before actually starting the tests or any other supporting code that the tests may need. For example, the following block first defines a variable to reduce code duplication: +) + +--- +dstring toFront(dstring str, dchar letter) { + // ... +} + +unittest { + immutable str = "hello"d; + + assert(toFront(str, 'h') == "hello"); + assert(toFront(str, 'o') == "ohell"); + assert(toFront(str, 'l') == "llheo"); +} +--- + +$(P +The three $(C assert) checks above test that $(C toFront()) works according to its specification. +) + +$(P +As these examples show, unit tests are also useful as examples of how particular functions should be called. Usually it is easy to get an idea on what a function does just by reading its unit tests. +) + +$(H5 $(IX assertThrown, std.exception) $(IX assertNotThrown, std.exception) Testing for exceptions) + +$(P +It is common to test some code for exception types that it should or should not throw under certain conditions. The $(C std.exception) module contains two functions that help with testing for exceptions: +) + +$(UL + +$(LI $(C assertThrown): Ensures that a specific exception type is thrown from an expression) + +$(LI $(C assertNotThrown): Ensures that a specific exception type is $(I not) thrown from an expression) + +) + +$(P +For example, a function that requires that both of its slice parameters have equal lengths and that it works with empty slices can be tested as in the following tests: +) + +--- +import std.exception; + +int[] average(int[] a, int[] b) { + // ... +} + +unittest { + /* Must throw for uneven slices */ + assertThrown(average([1], [1, 2])); + + /* Must not throw for empty slices */ + assertNotThrown(average([], [])); +} +--- + +$(P +Normally, $(C assertThrown) ensures that some type of exception is thrown without regard to the actual type of that exception. When needed, it can test against a specific exception type as well. Likewise, $(C assertNotThrown) ensures that no exception is thrown whatsoever but it can be instructed to test that a specific exception type is not thrown. The specific exception types are specified as template parameters to these functions: +) + +--- + /* Must throw UnequalLengths for uneven slices */ + assertThrown$(HILITE !UnequalLengths)(average([1], [1, 2])); + + /* Must not throw RangeError for empty slices (it may + * throw other types of exceptions) */ + assertNotThrown$(HILITE !RangeError)(average([], [])); +--- + +$(P +We will see templates in a $(LINK2 templates.html, later chapter). +) + +$(P +The main purpose of these functions is to make code more succinct and more readable. For example, the following $(C assertThrown) line is the equivalent of the lengthy code below it: +) + +--- + assertThrown(average([1], [1, 2])); + +// ... + + /* The equivalent of the line above */ + { + auto isThrown = false; + + try { + average([1], [1, 2]); + + } catch (Exception exc) { + isThrown = true; + } + + assert(isThrown); + } +--- + +$(H5 $(IX TDD) $(IX test driven development) Test driven development) + +$(P +Test driven development (TDD) is a software development methodology that prescribes writing unit tests before implementing functionality. In TDD, the focus is on unit testing. Coding is a secondary activity that makes the tests pass. +) + +$(P +In accordance to TDD, the $(C ordinal()) function above can first be implemented intentionally incorrectly: +) + +--- +import std.string; + +string ordinal(size_t number) { + return ""; // ← intentionally wrong +} + +unittest { + assert(ordinal(1) == "1st"); + assert(ordinal(2) == "2nd"); + assert(ordinal(3) == "3rd"); + assert(ordinal(10) == "10th"); +} + +void main() { +} +--- + +$(P +Although the function is obviously wrong, the next step would be to run the unit tests to see that the tests do indeed catch problems with the function: +) + +$(SHELL +$ dmd deneme.d -w -unittest +$ ./deneme +$(SHELL_OBSERVED core.exception.AssertError@deneme(10): $(HILITE unittest failure)) +) + +$(P +The function should be implemented only $(I after) seeing the failure, and only to make the tests pass. Here is just one implementation that passes the tests: +) + +--- +import std.string; + +string ordinal(size_t number) { + string suffix; + + switch (number) { + case 1: suffix = "st"; break; + case 2: suffix = "nd"; break; + case 3: suffix = "rd"; break; + default: suffix = "th"; break; + } + + return format("%s%s", number, suffix); +} + +unittest { + assert(ordinal(1) == "1st"); + assert(ordinal(2) == "2nd"); + assert(ordinal(3) == "3rd"); + assert(ordinal(10) == "10th"); +} + +void main() { +} +--- + +$(P +Since the implementation above does pass the unit tests, there is reason to trust that the $(C ordinal()) function is correct. Under the assurance that the tests bring, the implementation of the function can be changed in many ways with confidence. +) + +$(H6 Unit tests before bug fixes) + +$(P +Unit tests are not a panacea; there will always be bugs. If a bug is discovered when actually running the program, it can be seen as an indication that the unit tests have been incomplete. For that reason, it is better to $(I first) write a unit test that reproduces the bug and only $(I then) to fix the bug to pass the new test. +) + +$(P +Let's have a look at the following function that returns the spelling of the ordinal form of a number specified as a $(C dstring): +) + +--- +$(CODE_NAME ordinalSpelled)import std.exception; +import std.string; + +dstring ordinalSpelled(dstring number) { + enforce(number.length, "number cannot be empty"); + + dstring[dstring] exceptions = [ + "one": "first", "two" : "second", "three" : "third", + "five" : "fifth", "eight": "eighth", "nine" : "ninth", + "twelve" : "twelfth" + ]; + + dstring result; + + if (number in exceptions) { + result = exceptions[number]; + + } else { + result = number ~ "th"; + } + + return result; +} + +unittest { + assert(ordinalSpelled("one") == "first"); + assert(ordinalSpelled("two") == "second"); + assert(ordinalSpelled("three") == "third"); + assert(ordinalSpelled("ten") == "tenth"); +} + +void main() { +} +--- + +$(P +The function takes care of exceptional spellings and even includes a unit test for that. Still, the function has a bug yet to be discovered: +) + +--- +$(CODE_XREF ordinalSpelled)import std.stdio; + +void main() { + writefln("He came the %s in the race.", + ordinalSpelled("twenty")); +} +--- + +$(P +The spelling error in the output of the program is due to a bug in $(C ordinalSpelled()), which its unit tests fail to catch: +) + +$(SHELL +He came the $(HILITE twentyth) in the race. +) + +$(P +Although it is easy to see that the function does not produce the correct spelling for numbers that end with the letter y, TDD prescribes that first a unit test must be written to reproduce the bug before actually fixing it: +) + +--- +unittest { +// ... + assert(ordinalSpelled("twenty") == "twentieth"); +} +--- + +$(P +With that improvement to the tests, now the bug in the function is being caught during development: +) + +$(SHELL +core.exception.AssertError@deneme(3274338): unittest failure +) + +$(P +The function should be fixed only then: +) + +--- +dstring ordinalSpelled(dstring number) { +// ... + if (number in exceptions) { + result = exceptions[number]; + + } else { + if ($(HILITE number[$-1] == 'y')) { + result = number[0..$-1] ~ "ieth"; + + } else { + result = number ~ "th"; + } + } + + return result; +} +--- + +$(PROBLEM_TEK + +$(P +Implement $(C toFront()) according to TDD. Start with the intentionally incomplete implementation below. Observe that the unit tests fail and provide an implementation that passes the tests. +) + +--- +dstring toFront(dstring str, dchar letter) { + dstring result; + return result; +} + +unittest { + immutable str = "hello"d; + + assert(toFront(str, 'h') == "hello"); + assert(toFront(str, 'o') == "ohell"); + assert(toFront(str, 'l') == "llheo"); +} + +void main() { +} +--- + +) + +Macros: + TITLE=Unit Testing + + DESCRIPTION=The unittest feature of the D programming language, which is one of the most effective tools for program correctness. + + KEYWORDS=d programming language tutorial book unittest diff --git a/book/d.en/value_vs_reference.d b/book/d.en/value_vs_reference.d new file mode 100644 index 0000000000..ce6cb5964e --- /dev/null +++ b/book/d.en/value_vs_reference.d @@ -0,0 +1,701 @@ +Ddoc + +$(DERS_BOLUMU $(IX value type) $(IX reference type) Value Types and Reference Types) + +$(P +This chapter introduces the concepts of value types and reference types. These concepts are particularly important to understand the differences between structs and classes. +) + +$(P +This chapter also gets into more detail with the $(C &) operator. +) + +$(P +The chapter ends with a table that contains the outcomes of the following two concepts for different types of variables: +) + +$(UL +$(LI Value comparison) +$(LI Address comparison) +) + +$(H5 Value types) + +$(P +Value types are easy to describe: Variables of value types carry values. For example, all of the integer and floating point types are values types. Although not immediately obvious, fixed-length arrays are value types as well. +) + +$(P +For example, a variable of type $(C int) has an integer value: +) + +--- + int speed = 123; +--- + +$(P +The number of bytes that the variable $(C speed) occupies is the size of an $(C int). If we visualize the memory as a ribbon going from left to right, we can imagine the variable living on some part of it: +) + +$(MONO + speed + ───┬─────┬─── + │ 123 │ + ───┴─────┴─── +) + +$(P +When variables of value types are copied, they get their own values: +) + +--- + int newSpeed = speed; +--- + +$(P +The new variable would have a place and a value of its own: +) + +$(MONO + speed newSpeed + ───┬─────┬─── ───┬─────┬─── + │ 123 │ │ 123 │ + ───┴─────┴─── ───┴─────┴─── +) + +$(P +Naturally, modifications that are made to these variables are independent: +) + +--- + speed = 200; +--- + +$(P +The value of the other variable does not change: +) + +$(MONO + speed newSpeed + ───┬─────┬─── ───┬─────┬─── + │ 200 │ │ 123 │ + ───┴─────┴─── ───┴─────┴─── +) + +$(H6 The use of $(C assert) checks below) + +$(P +The following examples contain $(C assert) checks to indicate that their conditions are true. In other words, they are not checks in the normal sense, rather my way of telling to the reader that "this is true". +) + +$(P +For example, the check $(C assert(speed == newSpeed)) below means "speed is equal to newSpeed". +) + +$(H6 Value identity) + +$(P +As the memory representations above indicate, there are two types of equality that concern variables: +) + +$(UL + +$(LI $(B Value equality): The $(C ==) operator that appears in many examples throughout the book compares variables by their values. When two variables are said to be $(I equal) in that sense, their values are equal. +) +$(LI $(B Value identity): In the sense of owning separate values, $(C speed) and $(C newSpeed) have separate identities. Even when their values are equal, they are different variables. +) + +) + +--- + int speed = 123; + int newSpeed = speed; + assert(speed == newSpeed); + speed = 200; + assert(speed != newSpeed); +--- + +$(H6 Address-of operator, $(C &)) + +$(P +We have been using the $(C &) operator so far with $(C readf()). The $(C &) operator tells $(C readf()) where to put the input data. +) + +$(P $(I $(B Note:) As we have seen in $(LINK2 input.html, the Reading from the Standard Input chapter), $(C readf()) can be used without explicit pointers as well. +)) + +$(P +The addresses of variables can be used for other purposes as well. The following code simply prints the addresses of two variables: +) + +--- + int speed = 123; + int newSpeed = speed; + + writeln("speed : ", speed, " address: ", $(HILITE &)speed); + writeln("newSpeed: ", newSpeed, " address: ", $(HILITE &)newSpeed); +--- + +$(P +$(C speed) and $(C newSpeed) have the same value but their addresses are different: +) + +$(SHELL +speed : 123 address: 7FFF4B39C738 +newSpeed: 123 address: 7FFF4B39C73C +) + +$(P $(I $(B Note:) It is normal for the addresses to have different values every time the program is run. Variables live at parts of memory that happen to be available during that particular execution of the program.) +) + +$(P +Addresses are normally printed in hexadecimal format. +) + +$(P +Additionally, the fact that the two addresses are 4 apart indicates that those two integers are placed next to each other in memory. (Note that the value of hexadecimal C is 12, so the difference between 8 and 12 is 4.) +) + +$(H5 $(IX variable, reference) Reference variables) + +$(P +Before getting to reference types let's first define reference variables. +) + +$(P +$(B Terminology:) We have been using the phrase $(I to provide access to) so far in several contexts throughout the book. For example, slices and associative arrays do not own any elements but provide access to elements that are owned by the D runtime. Another phrase that is identical in meaning is $(I being a reference of) as in "slices are references of zero or more elements", which is sometimes used even shorter as $(I to reference) as in "this slice references two elements". Finally, the act of accessing a value through a reference is called $(I dereferencing). +) + +$(P +Reference variables are variables that act like aliases of other variables. Although they look and are used like variables, they do not have values themselves. Modifications made on a reference variable change the value of the actual variable. +) + +$(P +We have already used reference variables so far in two contexts: +) + +$(UL + +$(LI $(B $(C ref) in $(C foreach) loops): The $(C ref) keyword makes the loop variable the $(I actual) element that corresponds to that iteration. When the $(C ref) keyword is not used, the loop variable is a $(I copy) of the actual element. + +$(P +This can be demonstrated by the $(C &) operator as well. If their addresses are the same, two variables would be referencing the same value (or the $(I same element) in this case): +) + +--- + int[] slice = [ 0, 1, 2, 3, 4 ]; + + foreach (i, $(HILITE ref) element; slice) { + assert(&element == &slice[i]); + } +--- + +$(P +Although they are separate variables, the fact that the addresses of $(C element) and $(C slice[i]) are the same proves that they have the same value identity. +) + +$(P +In other words, $(C element) and $(C slice[i]) are references of the same value. Modifying either of those affects the actual value. The following memory layout indicates a snapshot of the iteration when $(C i) is 3: +) + +$(MONO + slice[0] slice[1] slice[2] slice[3] slice[4] + ⇢ ⇢ ⇢ (element) +──┬────────┬────────┬────────┬────────┬─────────┬── + │ 0 │ 1 │ 2 │ 3 │ 4 │ +──┴────────┴────────┴────────┴────────┴─────────┴── +) + +) + +$(LI $(B $(C ref) and $(C out) function parameters): Function parameters that are specified as $(C ref) or $(C out) are aliases of the actual variable the function is called with. + +$(P +The following example demonstrates this case by passing the same variable to separate $(C ref) and $(C out) parameters of a function. Again, the $(C &) operator indicates that both parameters have the same value identity: +) + +--- +import std.stdio; + +void main() { + int originalVariable; + writeln("address of originalVariable: ", &originalVariable); + foo(originalVariable, originalVariable); +} + +void foo($(HILITE ref) int refParameter, $(HILITE out) int outParameter) { + writeln("address of refParameter : ", &refParameter); + writeln("address of outParameter : ", &outParameter); + assert($(HILITE &)refParameter == $(HILITE &)outParameter); +} +--- + +$(P +Although they are defined as separate parameters, $(C refParameter) and $(C outParameter) are aliases of $(C originalVariable): +) + +$(SHELL +address of originalVariable: 7FFF24172958 +address of refParameter : 7FFF24172958 +address of outParameter : 7FFF24172958 +) + +) + +) + +$(H5 $(IX type, reference) Reference types) + +$(P +Variables of reference types have individual identities but they do not have individual values. They $(I provide access to) existing variables. +) + +$(P +We have already seen this concept with slices. Slices do not own elements, they provide access to existing elements: +) + +--- +void main() { + // Although it is named as 'array' here, this variable is + // a slice as well. It provides access to all of the + // initial elements: + int[] array = [ 0, 1, 2, 3, 4 ]; + + // A slice that provides access to elements other than the + // first and the last: + int[] slice = array[1 .. $ - 1]; + + // At this point slice[0] and array[1] provide access to + // the same value: + assert($(HILITE &)slice[0] == $(HILITE &)array[1]); + + // Changing slice[0] changes array[1]: + slice[0] = 42; + assert(array[1] == 42); +} +--- + +$(P +Contrary to reference variables, reference types are not simply aliases. To see this distinction, let's define another slice as a copy of one of the existing slices: +) + +--- + int[] slice2 = slice; +--- + +$(P +The two slices have their own adresses. In other words, they have separate identities: +) + +--- + assert(&slice != &slice2); +--- + +$(P +The following list is a summary of the differences between reference variables and reference types: +) + +$(UL + +$(LI Reference variables do not have identities, they are aliases of existing variables.) + +$(LI Variables of reference types have identities but they do not own values; rather, they provide access to existing values.) + +) + +$(P +The way $(C slice) and $(C slice2) live in memory can be illustrated as in the following figure: +) + +$(MONO + slice slice2 + ───┬───┬───┬───┬───┬───┬─── ───┬───┬─── ───┬───┬─── + │ 0 │$(HILITE  1 )│$(HILITE  2 )│$(HILITE  3 )│ 4 │ │ o │ │ o │ + ───┴───┴───┴───┴───┴───┴─── ───┴─│─┴─── ───┴─│─┴─── + ▲ │ │ + │ │ │ + └────────────────────┴────────────┘ +) + +$(P +The three elements that the two slices both reference are highlighted. +) + +$(P +One of the differences between C++ and D is that classes are reference types in D. Although we will cover classes in later chapters in detail, the following is a short example to demonstrate this fact: +) + +--- +class MyClass { + int member; +} +--- + +$(P +Class objects are constructed by the $(C new) keyword: +) + +--- + auto variable = new MyClass; +--- + +$(P +$(C variable) is a reference to an anonymous $(C MyClass) object that has been constructed by $(C new): +) + +$(MONO + (anonymous MyClass object) variable + ───┬───────────────────┬─── ───┬───┬─── + │ ... │ │ o │ + ───┴───────────────────┴─── ───┴─│─┴─── + ▲ │ + │ │ + └────────────────────┘ +) + +$(P +Just like with slices, when $(C variable) is copied, the copy becomes another reference to the same object. The copy has its own address: +) + +--- + auto variable = new MyClass; + auto variable2 = variable; + assert(variable == variable2); + assert(&variable != &variable2); +--- + +$(P +They are equal from the point of view of referencing the same object, but they are separate variables: +) + +$(MONO + (anonymous MyClass object) variable variable2 + ───┬───────────────────┬─── ───┬───┬─── ───┬───┬─── + │ ... │ │ o │ │ o │ + ───┴───────────────────┴─── ───┴─│─┴─── ───┴─│─┴─── + ▲ │ │ + │ │ │ + └────────────────────┴────────────┘ +) + +$(P +This can also be shown by modifying the member of the object: +) + +--- + auto variable = new MyClass; + variable.member = 1; + + auto variable2 = variable; // They share the same object + variable2.member = 2; + + assert(variable.member == 2); // The object that variable + // provides access to has + // changed. +--- + +$(P +Another reference type is associative arrays. Like slices and classes, when an associative array is copied or assigned to another variable, both give access to the same set of elements: +) + +--- + string[int] byName = + [ + 1 : "one", + 10 : "ten", + 100 : "hundred", + ]; + + // The two associative arrays will be sharing the same + // set of elements + string[int] byName2 = byName; + + // The mapping added through the second ... + byName2[4] = "four"; + + // ... is visible through the first. + assert(byName[4] == "four"); +--- + +$(P +As it will be explained in the next chapter, there is no element sharing if the original associative array were $(C null) to begin with. +) + +$(H6 The difference in the assignment operation) + +$(P +With value types and reference variables, the assignment operation changes $(I the actual value): +) + +--- +void main() { + int number = 8; + + halve(number); // The actual value changes + assert(number == 4); +} + +void halve($(HILITE ref) int dividend) { + dividend /= 2; +} +--- + +$(P +On the other hand, with reference types, the assignment operation changes $(I which value is being accessed). For example, the assignment of the $(C slice3) variable below does not change the value of any element; rather, it changes what elements $(C slice3) is now a reference of: +) + +--- + int[] slice1 = [ 10, 11, 12, 13, 14 ]; + int[] slice2 = [ 20, 21, 22 ]; + + int[] slice3 = slice1[1 .. 3]; // Access to element 1 and + // element 2 of slice1 + + slice3[0] = 777; + assert(slice1 == [ 10, 777, 12, 13, 14 ]); + + // This assignment does not modify the elements that + // slice3 is providing access to. It makes slice3 provide + // access to other elements. + $(HILITE slice3 =) slice2[$ - 1 .. $]; // Access to the last element + + slice3[0] = 888; + assert(slice2 == [ 20, 21, 888 ]); +--- + +$(P +Let's demonstrate the same effect this time with two objects of the $(C MyClass) type: +) + +--- + auto variable1 = new MyClass; + variable1.member = 1; + + auto variable2 = new MyClass; + variable2.member = 2; + + auto $(HILITE aCopy = variable1); + aCopy.member = 3; + + $(HILITE aCopy = variable2); + aCopy.member = 4; + + assert(variable1.member == 3); + assert(variable2.member == 4); +--- + +$(P +The $(C aCopy) variable above first references the same object as $(C variable1), and then the same object as $(C variable2). As a consequence, the $(C .member) that is modified through $(C aCopy) is first $(C variable1)'s and then $(C variable2)'s. +) + +$(H6 Variables of reference types may not be referencing any object) + +$(P +With a reference variable, there is always an actual variable that it is an alias of; it can not start its life without a variable. On the other hand, variables of reference types can start their lives without referencing any object. +) + +$(P +For example, a $(C MyClass) variable can be defined without an actual object having been created by $(C new): +) + +--- + MyClass variable; +--- + +$(P +Such variables have the special value of $(C null). We will cover $(C null) and the $(C is) keyword in $(LINK2 null_is.html, a later chapter). +) + +$(H5 Fixed-length arrays are value types, slices are reference types) + +$(P +D's arrays and slices diverge when it comes to value type versus reference type. +) + +$(P +As we have already seen above, slices are reference types. On the other hand, fixed-length arrays are value types. They own their elements and behave as individual values: +) + +--- + int[3] array1 = [ 10, 20, 30 ]; + + auto array2 = array1; // array2's elements are different + // from array1's + array2[0] = 11; + + // First array is not affected: + assert(array1[0] == 10); +--- + +$(P +$(C array1) is a fixed-length array because its length is specified when it has been defined. Since $(C auto) makes the compiler infer the type of $(C array2), it is a fixed-length array as well. The values of $(C array2)'s elements are copied from the values of the elements of $(C array1). Each array has its own elements. Modifying an element through one does not affect the other. +) + + +$(H5 Experiment) + +$(P +The following program is an experiment of applying the $(C ==) operator to different types. It applies the operator to both variables of a certain type and to the addresses of those variables. The program produces the following output: +) + +$(MONO + Type of variable a == b &a == &b +=========================================================================== + variables with equal values (value type) true false + variables with different values (value type) false false + foreach with 'ref' variable true true + foreach without 'ref' variable true false + function with 'out' parameter true true + function with 'ref' parameter true true + function with 'in' parameter true false + slices providing access to same elements true false + slices providing access to different elements false false + MyClass variables to same object (reference type) true false +MyClass variables to different objects (reference type) false false +) + +$(P +The table above has been generated by the following program: +) + +--- +import std.stdio; +import std.array; + +int moduleVariable = 9; + +class MyClass { + int member; +} + +void printHeader() { + immutable dchar[] header = + " Type of variable" ~ + " a == b &a == &b"; + + writeln(); + writeln(header); + writeln(replicate("=", header.length)); +} + +void printInfo(const dchar[] label, + bool valueEquality, + bool addressEquality) { + writefln("%55s%9s%9s", + label, valueEquality, addressEquality); +} + +void main() { + printHeader(); + + int number1 = 12; + int number2 = 12; + printInfo("variables with equal values (value type)", + number1 == number2, + &number1 == &number2); + + int number3 = 3; + printInfo("variables with different values (value type)", + number1 == number3, + &number1 == &number3); + + int[] slice = [ 4 ]; + foreach (i, ref element; slice) { + printInfo("foreach with 'ref' variable", + element == slice[i], + &element == &slice[i]); + } + + foreach (i, element; slice) { + printInfo("foreach without 'ref' variable", + element == slice[i], + &element == &slice[i]); + } + + outParameter(moduleVariable); + refParameter(moduleVariable); + inParameter(moduleVariable); + + int[] longSlice = [ 5, 6, 7 ]; + int[] slice1 = longSlice; + int[] slice2 = slice1; + printInfo("slices providing access to same elements", + slice1 == slice2, + &slice1 == &slice2); + + int[] slice3 = slice1[0 .. $ - 1]; + printInfo("slices providing access to different elements", + slice1 == slice3, + &slice1 == &slice3); + + auto variable1 = new MyClass; + auto variable2 = variable1; + printInfo( + "MyClass variables to same object (reference type)", + variable1 == variable2, + &variable1 == &variable2); + + auto variable3 = new MyClass; + printInfo( + "MyClass variables to different objects (reference type)", + variable1 == variable3, + &variable1 == &variable3); +} + +void outParameter(out int parameter) { + printInfo("function with 'out' parameter", + parameter == moduleVariable, + ¶meter == &moduleVariable); +} + +void refParameter(ref int parameter) { + printInfo("function with 'ref' parameter", + parameter == moduleVariable, + ¶meter == &moduleVariable); +} + +void inParameter(in int parameter) { + printInfo("function with 'in' parameter", + parameter == moduleVariable, + ¶meter == &moduleVariable); +} +--- + +$(P +Notes: +) + +$(UL + +$(LI +$(IX module variable) $(IX variable, module) The program makes use of a module variable when comparing different types of function parameters. Module variables are defined at module level, outside of all of the functions. They are globally accessible to all of the code in the module. +) + +$(LI +$(IX replicate, std.array) The $(C replicate()) function of the $(C std.array) module takes an array (the $(STRING "=") string above) and repeats it the specified number of times. +) + +) + +$(H5 Summary) + +$(UL + +$(LI Variables of value types have their own values and adresses.) + +$(LI Reference variables do not have their own values nor addresses. They are aliases of existing variables.) + +$(LI Variables of reference types have their own addresses but the values that they reference do not belong to them.) + +$(LI With reference types, assignment does not change value, it changes which value is being accessed.) + +$(LI Variables of reference types may be $(C null).) + +) + +Macros: + TITLE=Value Types and Reference Types + + DESCRIPTION=A comparison of value types and reference types in the D programming language, and the 'address of' operator. + + KEYWORDS=d programming book tutorial value reference diff --git a/book/d.en/variables.cozum.d b/book/d.en/variables.cozum.d new file mode 100644 index 0000000000..e472ee1ccc --- /dev/null +++ b/book/d.en/variables.cozum.d @@ -0,0 +1,22 @@ +Ddoc + +$(COZUM_BOLUMU Variables) + +--- +import std.stdio; + +void main() { + int amount = 20; + double rate = 2.11; + + writeln("I have exchanged ", amount, + " Euros at the rate of ", rate); +} +--- + +Macros: + TITLE=Variables Solutions + + DESCRIPTION=Programming in D exercise solutions: variables + + KEYWORDS=programming in d tutorial variables solution diff --git a/book/d.en/variables.d b/book/d.en/variables.d new file mode 100644 index 0000000000..b61f9bc4ca --- /dev/null +++ b/book/d.en/variables.d @@ -0,0 +1,107 @@ +Ddoc + +$(DERS_BOLUMU $(IX variable) Variables) + +$(P +Concrete concepts that are represented in a program are called $(I variables). A value like $(I air temperature) and a more complicated object like $(I a car engine) can be variables of a program. +) + +$(P +The main purpose of a variable is to represent a value in the program. The value of a variable is the last value that has been assigned to that variable. Since every value is of a certain type, every variable is of a certain type as well. Most variables have names as well, but some variables are anonymous. +) + +$(P +As an example of a variable, we can think of the concept of $(I the number of students) at a school. Since the number of students is a whole number, $(C int) is a suitable type, and $(C studentCount) would be a sufficiently descriptive name. +) + +$(P +According to D's syntax rules, a variable is introduced by its type followed by its name. The introduction of a variable to the program is called its $(I definition). Once a variable is defined, its name represents its value. +) + +--- +import std.stdio; + +void main() { + // The definition of the variable; this definition + // specifies that the type of studentCount is int: + int studentCount; + + // The name of the variable becomes its value: + writeln("There are ", studentCount, " students."); +} +--- + +$(P +The output of this program is the following: +) + +$(SHELL +There are 0 students. +) + +$(P +As seen from that output, the value of $(C studentCount) is 0. This is according to the fundamental types table from the previous chapter: the initial value of $(C int) is 0. +) + +$(P +Note that $(C studentCount) does not appear in the output as its name. In other words, the output of the program is not "There are studentCount students". +) + +$(P +The values of variables are changed by the $(C =) operator. The $(C =) operator assigns new values to variables, and for that reason is called the $(I assignment operator): +) + +--- +import std.stdio; + +void main() { + int studentCount; + writeln("There are ", studentCount, " students."); + + // Assigning the value 200 to the studentCount variable: + studentCount $(HILITE =) 200; + writeln("There are now ", studentCount, " students."); +} +--- + +$(SHELL +There are 0 students. +There are now 200 students. +) + +$(P +When the value of a variable is known at the time of the variable's definition, the variable can be defined and assigned at the same time. This is an important guideline; it makes it impossible to use a variable before assigning its intended value: +) + +--- +import std.stdio; + +void main() { + // Definition and assignment at the same time: + int studentCount = 100; + + writeln("There are ", studentCount, " students."); +} +--- + +$(SHELL +There are 100 students. +) + +$(PROBLEM_TEK + +$(P +Define two variables to print "I have exchanged 20 Euros at the rate of 2.11". You can use the floating point type $(C double) for the decimal value. +) + +) + + +Macros: + TITLE=Variables + + DESCRIPTION=The variables in the D programming language + + KEYWORDS=d programming language tutorial book variables + +MINI_SOZLUK= diff --git a/book/d.en/while.cozum.d b/book/d.en/while.cozum.d new file mode 100644 index 0000000000..61f3b3bf33 --- /dev/null +++ b/book/d.en/while.cozum.d @@ -0,0 +1,50 @@ +Ddoc + +$(COZUM_BOLUMU The $(CH4 while) Loop) + +$(OL + +$(LI +Because the initial value of $(C number) is 0, the logical expression of the $(C while) loop is $(C false) since the very beginning, and this is preventing from entering the loop body. A solution is to use an initial value that will allow the $(C while) condition to be $(C true) at the beginning: + +--- + int number = 3; +--- + +) + +$(LI +All of the variables in the following program are default initialized to 0. This allows entering both of the loops at least once: + +--- +import std.stdio; + +void main() { + int secretNumber; + + while ((secretNumber < 1) || (secretNumber > 10)) { + write("Please enter a number between 1 and 10: "); + readf(" %s", &secretNumber); + } + + int guess; + + while (guess != secretNumber) { + write("Guess the secret number: "); + readf(" %s", &guess); + } + + writeln("That is correct!"); +} +--- + +) + +) + +Macros: + TITLE=The while Loop Solutions + + DESCRIPTION=Programming in D exercise solutions: the 'while' loop + + KEYWORDS=programming in d tutorial while solution diff --git a/book/d.en/while.d b/book/d.en/while.d new file mode 100644 index 0000000000..5e65d16d9b --- /dev/null +++ b/book/d.en/while.d @@ -0,0 +1,230 @@ +Ddoc + +$(DERS_BOLUMU $(IX while) $(IX loop, while) $(CH4 while) Loop) + +$(P +The $(C while) loop is similar to the $(C if) statement and essentially works as a repeated $(C if) statement. Just like $(C if), $(C while) also takes a logical expression and evaluates the block when the logical expression is $(C true). The difference is that the $(C while) statement evaluates the logical expression and executes the expressions in the block repeatedly, as long as the logical expression is $(C true), not just once. Repeating a block of code this way is called $(I looping). +) + +$(P +Here is the syntax of the $(C while) statement: +) + +--- + while (a_logical_expression) { + // ... expression(s) to execute while true + } +--- + +$(P +For example, the code that represents $(I eat cookies as long as there is cookie) can be coded like this: +) + +--- +import std.stdio; + +void main() { + bool existsCookie = true; + + while (existsCookie) { + writeln("Take cookie"); + writeln("Eat cookie"); + } +} +--- + +$(P +That program would continue repeating the loop because the value of $(C existsCookie) never changes from $(C true). +) + +$(P +$(C while) is useful when the value of the logical expression changes during the execution of the program. To see this, let's write a program that takes a number from the user as long as that number is zero or greater. Remember that the initial value of $(C int) variables is 0: +) + +--- +import std.stdio; + +void main() { + int number; + + while (number >= 0) { + write("Please enter a number: "); + readf(" %s", &number); + + writeln("Thank you for ", number); + } + + writeln("Exited the loop"); +} +--- + +$(P +The program thanks for the provided number and exits the loop only when the number is less than zero. +) + +$(H5 $(IX continue) The $(C continue) statement) + +$(P +The continue statement starts the next iteration of the loop right away, instead of executing the rest of the expressions of the block. +) + +$(P +Let's modify the program above to be a little picky: instead of thanking for any number, let's not accept 13. The following program does not thank for 13 because in that case the $(C continue) statement makes the program go to the beginning of the loop to evaluate the logical expression again: +) + +--- +import std.stdio; + +void main() { + int number; + + while (number >= 0) { + write("Please enter a number: "); + readf(" %s", &number); + + if (number == 13) { + writeln("Sorry, not accepting that one..."); + $(HILITE continue); + } + + writeln("Thank you for ", number); + } + + writeln("Exited the loop"); +} +--- + +$(P +We can define the behavior of that program as $(I take numbers as long as they are greater than or equal to 0 but skip 13). +) + +$(P +$(C continue) works with $(C do-while), $(C for), and $(C foreach) statements as well. We will see these features in later chapters. +) + +$(H5 $(IX break) The $(C break) statement) + +$(P +Sometimes it becomes obvious that there is no need to stay in the $(C while) loop any longer. $(C break) allows the program to exit the loop right away. The following program exits the loop as soon as it finds a special number: +) + +--- +import std.stdio; + +void main() { + int number; + + while (number >= 0) { + write("Please enter a number: "); + readf(" %s", &number); + + if (number == 42) { + writeln("FOUND IT!"); + $(HILITE break); + } + + writeln("Thank you for ", number); + } + + writeln("Exited the loop"); +} +--- + +$(P +We can summarize this behavior as $(I take numbers as long as they are greater than or equal to 0 or until a number is 42). +) + +$(P +$(C break) works with $(C do-while), $(C for), $(C foreach), and $(C switch) statements as well. We will see these features in later chapters. +) + +$(H5 $(IX loop, infinite) $(IX loop, unconditional) $(IX infinite loop) $(IX unconditional loop) Unconditional loop) + +$(P +Sometimes the logical expression is intentionally made a constant $(C true). The $(C break) statement is a common way of exiting such $(I unconditional loops). ($(I Infinite loop) is an alternative but not completely accurate term that means unconditional loop.) +) + +$(P +The following program prints a menu in an unconditional loop; the only way of exiting the loop is a $(C break) statement: +) + +--- +import std.stdio; + +void main() { + /* Unconditional loop, because the logical expression is always + * true */ + while ($(HILITE true)) { + write("0:Exit, 1:Turkish, 2:English - Your choice? "); + + int choice; + readf(" %s", &choice); + + if (choice == 0) { + writeln("See you later..."); + $(HILITE break); // The only exit of this loop + + } else if (choice == 1) { + writeln("Merhaba!"); + + } else if (choice == 2) { + writeln("Hello!"); + + } else { + writeln("Sorry, I don't know that language. :/"); + } + } +} +--- + +$(P +$(I $(B Note:)) Exceptions $(I can terminate an unconditional loop as well. We will see exceptions in a later chapter.) +) + +$(PROBLEM_COK + +$(PROBLEM +The following program is designed to stay in the loop as long as the input is 3, but there is a bug: it doesn't ask for any input: + +--- +import std.stdio; + +void main() { + int number; + + while (number == 3) { + write("Number? "); + readf(" %s", &number); + } +} +--- + +$(P +Fix the bug. The program should stay in the loop as long as the input is 3. +) + +) + +$(PROBLEM +Make the computer help Anna and Bill play a game. First, the computer should take a number from Anna in the range from 1 to 10. The program should not accept any other number; it should ask again. + +$(P +Once the program takes a valid number from Anna, it should start taking numbers from Bill until he guesses Anna's number correctly. +) + +$(P +$(I $(B Note:) The numbers that Anna enters obviously stay on the terminal and can be seen by Bill. Let's ignore this fact and write the program as an exercise of the $(C while) statement.) +) + +) + +) + +Macros: + TITLE=while Loop + + DESCRIPTION=The while loop and the related statements break and continue + + KEYWORDS=d programming language tutorial book while loop statement break continue + +MINI_SOZLUK= diff --git a/book/d.en/writeln.cozum.d b/book/d.en/writeln.cozum.d new file mode 100644 index 0000000000..1ce1f15b22 --- /dev/null +++ b/book/d.en/writeln.cozum.d @@ -0,0 +1,32 @@ +Ddoc + +$(COZUM_BOLUMU writeln and write) + +$(OL + +$(LI +One method is to use another parameter in between: + +--- + writeln("Hello, World!", " ", "Hello, fish!"); +--- + +) + +$(LI +$(C write) can take multiple parameters as well: + +--- + write("one", " two", " three"); +--- + +) + +) + +Macros: + TITLE=writeln and write Solutions + + DESCRIPTION=Programming in D exercise solutions: writeln and write + + KEYWORDS=programming in d tutorial writeln and write exercise solution diff --git a/book/d.en/writeln.d b/book/d.en/writeln.d new file mode 100644 index 0000000000..4fe7e336a0 --- /dev/null +++ b/book/d.en/writeln.d @@ -0,0 +1,83 @@ +Ddoc + +$(DERS_BOLUMU $(IX writeln) $(IX write) $(CH4 writeln) and $(CH4 write)) + +$(P +In the previous chapter we have seen that $(C writeln) takes a string within parentheses and prints the string. +) + +$(P +The parts of programs that actually do work are called $(I functions) and the information that they need to complete their work are called $(I parameters). The act of giving such information to functions is called $(I passing parameter values) to them. Parameters are passed to functions within parentheses, separated by commas. +) + +$(P +$(I $(B Note:) The word ) parameter $(I describes the information that is passed to a function at the conceptual level. The concrete information that is actually passed during the execution of the program is called an) argument. $(I Although not technically the same, these terms are sometimes used interchangably in the software industry.) +) + +$(P +$(C writeln) can take more than one argument. It prints them one after the other on the same line: +) + +--- +import std.stdio; + +void main() { + writeln("Hello, World!", "Hello, fish!"); +} +--- + +$(P +Sometimes, not all of the information that is to be printed on the same line may be readily available to be passed to $(C writeln). In such cases, the first parts of the line may be printed by $(C write) and the last part of the line may be printed by $(C writeln). +) + +$(P +$(C writeln) advances to the next line, $(C write) stays on the same line: +) + +--- +import std.stdio; + +void main() { + // Let's first print what we have available: + write("Hello,"); + + // ... let's assume more operations at this point ... + + write("World!"); + + // ... and finally: + writeln(); +} +--- + +$(P +Calling $(C writeln) without any parameter merely completes the current line, or if nothing has been written, outputs a blank line. +) + +$(P +$(IX //) $(IX comment) Lines that start with $(COMMENT //) are called $(I comment lines) or briefly $(I comments). A comment is not a part of the program code in the sense that it doesn't affect the behavior of the program. Its only purpose is to explain what the code does in that particular section of the program. The audience of a comment is anybody who may be reading the program code later, including the programmer who wrote the comment in the first place. +) + +$(PROBLEM_COK + +$(PROBLEM + +Both of the programs in this chapter print the strings without any spaces between them. Change the programs so that there is space between the arguments as in "Hello, World!". + +) + +$(PROBLEM +Try calling $(C write) with more than one parameter as well. +) + +) + + +Macros: + TITLE=writeln and write + + DESCRIPTION=Two functions of the D standard library: writeln and write. + + KEYWORDS=d programming language tutorial book if conditional statement + +MINI_SOZLUK= diff --git a/book/dlang.org.ddoc b/book/dlang.org.ddoc new file mode 100644 index 0000000000..9fb9cf513a --- /dev/null +++ b/book/dlang.org.ddoc @@ -0,0 +1,577 @@ +_=Macros for the dlang.org site look and feel. Please keep sorted by name. Multiline macros should keep one _= line before and after for clarity. Also, one _= line should be present when the first letter changes. (The "_="" is needed so there's no extra newline after the last macro defined in a group.) + +ACRONYM = $1 ($+) +ASSIGNEXPRESSION = $(GLINK2 expression, AssignExpression) +_= + +BIGOH = $(SPANC bigoh, Ο($(D $0))) +BLOCKQUOTE = $(T blockquote, $(P $0)) +BLOCKQUOTE_BY = $(BLOCKQUOTE $+ $(T cite, $1)) +BLACK=$(SPANC black, $0) +BLUE=$(SPANC blue, $0) +BODY_PREFIX= +BOOKTABLE = $(TC table, book, $(T caption, $1)$+) +BUGZILLA = $(SPANC bugzilla, $(AHTTPS issues.dlang.org/show_bug.cgi?id=$0, Bugzilla $0)) +BUGZILLA_NEW_BUG_URL=https://github.com/dlang/$(PROJECT)/issues/new?title=%5B$(TITLE)%5D%20 +_= + +CCODE=$(TC pre, ccode notranslate, $0) +CODE=$(D $0) +CODE_AMP=$(D &) +CODE_DOLLAR=$(D $) +CODE_HIGHLIGHT=$(B $(I $0)) +CODE_LCURL=$(D {) +CODE_PERCENT=$(D %) +CODE_PIPE=$(D |) +CODE_RCURL=$(D }) +_= + +COMMON_HEADERS_DLANG= + +_= +COMMON_SCRIPTS = + $(SCRIPTLOAD https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js) + $(SCRIPT window.jQuery || document.write('\x3Cscript src="https://github.com/$(STATIC%20js/jquery-1.7.2.min.js)">\x3C/script>');$(EXTRA_JS)) + $(SCRIPTLOAD $(STATIC js/dlang.js)) + $(COMMON_SCRIPTS_DLANG) +_= +COMMON_SCRIPTS_DLANG = + $(SCRIPTLOAD $(STATIC js/codemirror-compressed.js)) + $(SCRIPTLOAD $(STATIC js/run.js)) +_= + +COMPATIBILITY_BOX_DEPRECATED = $(MESSAGE_BOX red, $(B Deprecated) - $0) +COMPATIBILITY_BOX_SUPERSEDED = $(MESSAGE_BOX gray, $(B Obsolete) - $0) +COMPATIBILITY_BOX_OBSOLETE = $(MESSAGE_BOX gray, $(B Obsolete) - $0) +COMPATIBILITY_BOX_OUTDATED = $(MESSAGE_BOX gray, $(B Obsolete) - $0) +COMPATIBILITY_BOX_EXPERIMENTAL = $(MESSAGE_BOX orange, $(B Experimental) - $0) +_= + +CONSOLE=$(TC pre, console notranslate, $0) +COPYRIGHT_FOUNDATION=Copyright © 1999-$(YEAR) by the $(LINK2 $(ROOT_DIR)foundation_overview.html, D Language Foundation) +CPPCODE=$(TC pre, cppcode notranslate, $0) +CPPLISTING=$(CPPCODE $0) +CROSS=✘ +_= + +D=$(SPANC d_inlinecode donthyphenate notranslate, $0) +D_CODE=$(TC pre, d_code notranslate, $0) +OTHER_CODE=$(TC pre, $1code notranslate, $+) +_= + +DDOC= + + + + + + + +$(T title, $(FULL_TITLE)) +$(COMMON_HEADERS_DLANG) + + + + +$(EXTRA_HEADERS) + + +$(SCRIPT document.body.className += ' have-javascript') +$(DIVID top, $(DIVC helper, $(DIVC helper expand-container, + $(DIVC logo, ) + Menu + $(NAVIGATION) + $(DIVC search-container expand-container, + Search + $(SEARCH_BOX) + ) +))) +$(LAYOUT_PREFIX) +$(DIVC container, + $(SUBNAV) + $(DIVCID $(HYPHENATE), content, + $(PAGE_TOOLS) + $(LAYOUT_TITLE) + $(BODY_PREFIX) + $(BODY) + $(FOOTER) + ) +) +$(COMMON_SCRIPTS) +$(EXTRA_FOOTERS) +$(LAYOUT_SUFFIX) + + +$(LF) +_= + +DDLINK=$(LINK2 $(ROOT_DIR)$1.html, $3) +DDOC_BACKQUOTED = $(D $0) +DDOC_SUMMARY = $(DIVC summary, $0) +DDOC_DESCRIPTION = $(DIVC description, $0)$(LF) +DDOC_AUTHORS = $(DDOCKEYVAL Authors, $0)$(LF) +DDOC_BUGS = $(DDOCKEYVAL Bugs, $0)$(LF) +DDOC_COPYRIGHT = $(DDOCKEYVAL Copyright, $0)$(LF) +DDOC_DATE = $(DDOCKEYVAL Date, $0)$(LF) +DDOC_DEPRECATED = $(DDOCKEYVAL Deprecated, $0)$(LF) +DDOC_EXAMPLES = $(DDOCKEYVAL Examples, $0)$(LF) +DDOC_HISTORY = $(DDOCKEYVAL History, $0)$(LF) +DDOC_LICENSE = $(DDOCKEYVAL License, $0)$(LF) +DDOC_RETURNS = $(DDOCKEYVAL Returns, $0)$(LF) +DDOC_SEE_ALSO = $(DDOCKEYVAL2 SeeAlso, See Also, $0)$(LF) +DDOC_STANDARDS = $(DDOCKEYVAL Standards, $0)$(LF) +DDOC_THROWS = $(DDOCKEYVAL Throws, $0)$(LF) +DDOC_VERSION = $(DDOCKEYVAL Version, $0)$(LF) +DDOC_SECTION_H =

    $(SPANC key keySection, $0)$(LF) +DDOC_SECTION = $(DIVC val, $0

    )$(LF) +DDOC_PARAM_ROW = $0$(LF) +DDOC_PARAM_ID = $0$(LF) +DDOC_PARAM_DESC = $0 +DDOC_PARAMS = $(DDOCKEYVAL Parameters, $0
    )$(LF) +DDOC_BLANKLINE = +DDOC_KEYWORD = $(TC code, ddoc_keyword, $0) +DDOC_PARAM = $(TC code, ddoc_param, $0) +DDOC_PSYMBOL = $(ADEF $0)$(TC code, ddoc_psymbol, $0) +DDOC_ANCHOR = $(ADEF .$1)$(DIVCID quickindex, quickindex.$1, ) +DDOC_DECL = $(TC dt, d_decl, $(DIV, $0)) +DDOC_UNDEFINED_MACRO = $(DDOC_COMMENT UNDEFINED MACRO: "$1") +DDOCCODE=$(TC pre, ddoccode notranslate, $0) +DDOCKEYVAL=$(DIVC keyval $1, $(SPANC key key$1, $1:) $(DIVC val val$1, $+)) +DDOCKEYVAL2=$(DIVC keyval $1, $(SPANC key key$1, $2:) $(DIVC val val$1, $(TAIL $+))) +DDSUBLINK=$(LINK2 $(ROOT_DIR)$1.html#$2, $3) +_= + + +DMDSRC=$(HTTPS github.com/dlang/dmd/blob/master/src/dmd/$0, $0) +DOT_PREFIXED=.$1$(DOT_PREFIXED $+) +DOT_PREFIXED_SKIP=$(DOT_PREFIXED $+) +DRUNTIMESRC=$(HTTPS github.com/dlang/druntime/blob/master/src/$0, $0) +_= + +$(COMMENT URL prefix for the site root. + Relative (e.g. "../") for dlang.org pages; + absolute ("https://dlang.org/") for the ebook.) +DPLLINK=$(LINK2 $(ROOT_DIR)$1,$+) +_= + +ELABORATE_HEADER=$(TR DC) +$(TR 32 bit64 bit) +_= +EXTRA_HEADERS= +EXTRA_JS= +EXTRA_FOOTERS= +_= + +FAVICON=$(STATIC favicon.ico) +FOOTER = $(DIVCID smallprint, copyright, $(COPYRIGHT_FOUNDATION) | Page generated by +$(LINK2 $(ROOT_DIR)spec/ddoc.html, Ddoc) on $(GEN_DATETIME)) +FOOTNOTE=$(SPANC footnote, $0) +FULL_TITLE=$(TITLE) - D Programming Language +_= + +GDEPRECATED=$0 +GRESERVED=$0 +GEN_DATETIME=$(DATETIME) +GLINK=$(RELATIVE_LINK2 $0, $(I $0)) +GLINK2=$(DDSUBLINK spec/$1,$2,$(I $2)) +GLINK2_ALTTEXT=$(DDSUBLINK spec/$1,$2,$(I $3)) +GLINK_LEX=$(DDSUBLINK spec/lex,$1,$(I $1)) +GLOSSARY = $(HTTP dlang.org/spec/glossary.html#$0, $0) +GLOSSARY2 = $(HTTP dlang.org/spec/glossary.html#$1, $2) +GNAME=$(SPANC gname, $0) +GRAMMAR=$(TC pre, bnf notranslate, $0) +GRAMMAR_INFORMATIVE=$(GRAMMAR $0) +GRAMMAR_LEX=$(GRAMMAR $0) +GRAMMAR_INLINE=$(TC tt, bnf notranslate, $0) +GREEN=$(SPANC green, $0) +GSELF=$(I $0) +GT=> +_= + +HASH=# +HEADERNAV_TOC=$(DIVC page-contents quickindex, + $(DIVC page-contents-header, + $(B Contents) + ) + $(OL $0) +) +HEADERNAV_ITEM=$(LI $(RELATIVE_LINK2 $1, $+)) +HEADERNAV_SUBITEMS=$(LI $(RELATIVE_LINK2 $1, $2)$(OL $(MULTICOLS $+))) +HTMLTAG3=<$1 $2>$(TAIL $+) +HTMLTAG3V=<$1 $2>$(TAIL $+) +HYPHENATE=hyphenate +_= + + +ISEXPRESSION=$(GLINK2 expression, IsExpression) +_= + +LATEX= +LAYOUT_PREFIX= +LAYOUT_SUFFIX= +LAYOUT_TITLE=$(H1 $(TITLE)) +LEGACY_LNAME2=$(LNAME2 $+) +PHOBOS_PATH=$(ROOT_DIR)phobos/ +LIST=$(UL $(LIX $1, $+)) +LIX=$(LI $1)$(LIX $+) +LNAME2=$+ +LONGTABLE_2COLS=$(TABLE2 $2,$3 $4) +LONGTABLE_3COLS=$(TABLE2 $2,$3 $4) +LONGTABLE_5COLS=$(TABLE2 $1,$2 $3) +LT=< +LUCKY = $(HTTPS google.com/search?btnI=I%27m+Feeling+Lucky&ie=UTF-8&oe=UTF-8&q=$0,$0) +LUCKY2 = $(HTTPS google.com/search?btnI=I%27m+Feeling+Lucky&q=$+,$1) +_= + +MDASH=$(T nobr,  — ) +METACODE=$(SPANC metacode, $0) +MENU =
  • $+
  • +MENU_W_SUBMENU =
  • $(TT $1) +MENU_W_SUBMENU_LINK =
  • $+ +MENU_W_SUBMENU_END =
  • +MENU_INTERNAL_SEPARATOR = $(DIVC modlist-internal-separator, Internal API) +MESSAGE_BOX = $(DIVC message-box message-box-$1, $+) +META_KEYWORDS=D programming language +META_DESCRIPTION=D Programming Language +MODDEFFILE=$(TC pre, moddeffile notranslate, $0) +MULTICOL_CELL=$+ +MULTICOL_HEADER=$+ +MULTICOLS=$+ +MULTIROW_HEADER=$+ +MREF=$(LINK2 $(PHOBOS_PATH)$1$(UNDERSCORE_PREFIXED $+).html, $(D $1$(DOT_PREFIXED $+))) +MREF_ALTTEXT=$(LINK2 $(PHOBOS_PATH)$2$(UNDERSCORE_PREFIXED_SKIP $+).html, $1) +MREF1=$(LINK2 $(PHOBOS_PATH)$1.html, $(D $1)) +_= + + +NAVIGATION= +$(DIVID cssmenu, $(UL + $(MENU https://tour.dlang.org, Learn) + $(MENU_W_SUBMENU_LINK $(ROOT_DIR)documentation.html, Documentation) + $(NAVIGATION_DOCUMENTATION) + $(MENU $(ROOT_DIR)download.html, Downloads) + $(MENU https://code.dlang.org, Packages) + $(MENU_W_SUBMENU_LINK $(ROOT_DIR)community.html, Community) + $(NAVIGATION_COMMUNITY) + $(MENU_W_SUBMENU_LINK $(ROOT_DIR)resources.html, Resources) + $(NAVIGATION_RESOURCES) +)) +NAVIGATION_COMMUNITY= +$(SUBMENU_MANUAL + $(SUBMENU_LINK https://dlang.org/blog, Blog) + $(SUBMENU_LINK $(ROOT_DIR)orgs-using-d.html, Orgs using D) + $(SUBMENU_LINK https://twitter.com/search?q=%23dlang, Twitter) + $(SUBMENU_LINK $(ROOT_DIR)calendar.html, Calendar) + $(SUBMENU_LINK_DIVIDER https://discord.gg/bMZk9Q4, Discord (community-run)) + $(SUBMENU_LINK https://forum.dlang.org, Forums) + $(SUBMENU_LINK irc://irc.libera.chat/d, IRC) + $(SUBMENU_LINK https://wiki.dlang.org, Wiki) + $(SUBMENU_LINK_DIVIDER $(ROOT_DIR)bugstats.html, Issues) + $(SUBMENU_LINK $(ROOT_DIR)contributing.html, Contributing) + $(SUBMENU_LINK_DIVIDER $(ROOT_DIR)foundation/contributors.html, Contributors) + $(SUBMENU_LINK $(ROOT_DIR)foundation/index.html, Foundation) + $(SUBMENU_LINK $(ROOT_DIR)/security.html, Security Team) + $(SUBMENU_LINK $(ROOT_DIR)foundation/donate.html, Donate) + $(SUBMENU_LINK $(ROOT_DIR)foundation/sponsors.html, Sponsors) +) +NAVIGATION_DOCUMENTATION= +$(SUBMENU_MANUAL + $(SUBMENU_LINK $(ROOT_DIR)spec/spec.html, Language Reference) + $(SUBMENU_LINK $(ROOT_DIR)phobos/index.html, Library Reference) + $(SUBMENU_LINK $(ROOT_DIR)dmd.html, Command-line Reference) + $(SUBMENU_LINK_DIVIDER $(ROOT_DIR)comparison.html, Feature Overview) + $(SUBMENU_LINK $(ROOT_DIR)articles.html, Articles) +) +NAVIGATION_RESOURCES= +$(SUBMENU_MANUAL + $(SUBMENU_LINK https://tour.dlang.org, Tour) + $(SUBMENU_LINK https://wiki.dlang.org/Books, Books) + $(SUBMENU_LINK https://wiki.dlang.org/Tutorials, Tutorials) + $(SUBMENU_LINK_DIVIDER https://wiki.dlang.org/Development_tools, Tools) + $(SUBMENU_LINK https://wiki.dlang.org/Editors, Editors) + $(SUBMENU_LINK https://wiki.dlang.org/IDEs, IDEs) + $(SUBMENU_LINK https://run.dlang.io, run.dlang.io) + $(SUBMENU_LINK $(VISUALD), Visual D) + $(SUBMENU_LINK_DIVIDER $(ROOT_DIR)acknowledgements.html, Acknowledgments) + $(SUBMENU_LINK $(ROOT_DIR)dstyle.html, D Style) + $(SUBMENU_LINK $(ROOT_DIR)glossary.html, Glossary) + $(SUBMENU_LINK $(ROOT_DIR)sitemap.html, Sitemap) +) +_= + +NEWS=http://digitalmars.com/webnews/newsgroups.php?search_txt=$(AMP)group=$1$(AMP)article_id=$+ +NG_digitalmars_D = D/$0 +NG_digitalmars_D_announce = D.announce/$0 +NOTRANSLATE=$(SPANC notranslate, $0) +NO= +NOT_EBOOK=$0 +NOTICE_L=$2 +NOTICE=$1 +_= + +OPT=$(SUBSCRIPT opt) +_= + +PAGE_TOOLS= +$(DIVID tools, $(DIV, + $(DIVC tip smallprint, + $(HTMLTAG3 a, href="https://github.com/$(BUGZILLA_NEW_BUG_URL)$(AMP)label=Severity:Enhancement", Report a bug) + $(DIV, + If you spot a problem with this page, click here to create a Bugzilla issue. + ) + ) + $(DIVC tip smallprint, + Improve this page + $(DIV, + Quickly fork, edit online, and submit a pull request for this page. + Requires a signed-in GitHub account. This works well for small changes. + If you'd like to make larger changes you may want to consider using + a local clone. + ) + ) +)) +_= + +PC=$(TC p, $1, $+) +_= + +PHOBOSSRC=$(SPANC phobos_src, $(AHTTPS github.com/dlang/phobos/blob/master/$0, $0)) +_= + +RED=$(SPANC red, $0) +_= + +$(COMMENT + The REF macro generates a link to a phobos symbol. + + The first argument is the symbol name inside its module, without any + module/package parts, in usual dotted format. + + Arguments 2 and higher form the module name. The segments are passed + as individual arguments. + + The weird order is due to the format of the generated link, and Ddoc being + simplistic. + + The REF1 variants work around DDoc limitations and allow linking to + modules not inside packages (i.e. object.) + + Example: + + $(REF Array.back, std,container,array) generates a link to + std.container.array.Array.back + + To clarify, std.container.array is a module, Array is a struct in that + module, and back is a method of that struct. + + The generated href will be "phobos/std_container_array.html#.Array.back" + (the phobos path can be different, of course). +) +REF=$(LINK2 $(PHOBOS_PATH)$2$(UNDERSCORE_PREFIXED_SKIP $+).html#.$1, $(D $2$(DOT_PREFIXED_SKIP $+, $1))) +REF1=$(LINK2 $(PHOBOS_PATH)$2.html#.$1", $(D $1)) +_= + +$(COMMENT + The REF_ALTTEXT macro works the same as the REF macro, but it has another + parameter in front of the others that specifies the link text. + + Example: + $(REF_ALTTEXT the 'back' method, Array.back, std,container,array) + generates a link like this: + the 'back' method +) +REF_ALTTEXT=$(LINK2 $(PHOBOS_PATH)$3$(UNDERSCORE_PREFIXED_SKIP2 $+).html#.$2, $1) +REF1_ALTTEXT=$(LINK2 $(PHOBOS_PATH)$3.html#.$2", $1) +_= + +$(COMMENT + REF_SHORT takes the same arguments as REF. It displays only the + unqualified symbol name, without module or packages. +) +REF_SHORT=$(REF_ALTTEXT $(D $1), $1, $+) +_= + +RELATIVE_LINK2=$(ALOCAL $1, $+) +_= + +RUNNABLE_EXAMPLE=
    +$1 +
    +RUNNABLE_EXAMPLE_STDIN=$0 +RUNNABLE_EXAMPLE_ARGS=$0 + +SCINI=$(TC pre, scini notranslate, $0) +SCRIPTLOAD= +SEARCHDEFAULT_PHOBOS= +SEARCHDEFAULT_FORUM= +SEARCHDEFAULT_SPEC= +SEARCH_BOX= + $(DIVID search-box, +
    + + + $(SPANID search-query, )$(SPANID search-dropdown, $(SPANC helper, + + ))$(SPANID search-submit, ) +
    + ) +SEARCH_OPTIONS_EXTRA= +_= + +SECTION1=$(H1 $1)$+ +SECTION2=$(H2 $1)$+ +SECTION3=$(H3 $1)$+ +SECTION4=$(H4 $1)$+ +SECTION5=$(H5 $1)$+ +_= + +$(COMMENT + SIMPLE_CHEATSHEET is used for cheat sheets that play the same role + as the listings generated by DDOX. Consequently, DDOX hides these cheat + sheets. +) +SIMPLE_CHEATSHEET=$(TC table, simple-cheatsheet, $(T caption, Cheat Sheet) $0) +_= + +SLASH_PREFIXED=/$1$(SLASH_PREFIXED $+) + + +SRC_FILENAME=$(SRCFILENAME) +STATIC=$(ROOT_DIR)$1 +SUBMENU=
      $(SUBMENU2 $1,$+)
    +SUBMENU2=
  • $2
  • $(SUBMENU3 $+) +SUBMENU3=$(SUBMENU2 $+) +SUBMENU_MANUAL=
      $1 $+
    +SUBMENU_LINK=
  • $2
  • +SUBMENU_LINK_DIVIDER= +_= + +SUBNAV= +SUBNAV_ARTICLES= +$(SUBNAV_TEMPLATE + $(SUBNAV_HEAD Articles, $(ROOT_DIR)articles/index.html, overview) + $(UL $(SUBMENU2 + $(ROOT_DIR)articles/faq.html, FAQ, + $(ROOT_DIR)articles/const-faq.html, const(FAQ), + $(ROOT_DIR)articles/d-floating-point.html, Floating Point, + $(ROOT_DIR)articles/warnings.html, Warnings, + $(ROOT_DIR)articles/rationale.html, Rationale, + $(ROOT_DIR)articles/builtin.html, Builtin Rationale, + $(ROOT_DIR)articles/ctod.html, C to D, + $(ROOT_DIR)articles/cpptod.html, C++ to D, + $(ROOT_DIR)articles/pretod.html, C Preprocessor vs D, + $(ROOT_DIR)articles/code_coverage.html, Code coverage analysis, + $(ROOT_DIR)articles/exception-safe.html, Exception Safety, + $(ROOT_DIR)articles/hijack.html, Hijacking, + $(ROOT_DIR)articles/intro-to-datetime.html, Introduction to std.datetime, + $(ROOT_DIR)articles/lazy-evaluation.html, Lazy Evaluation, + $(ROOT_DIR)articles/migrate-to-shared.html, Migrating to Shared, + $(ROOT_DIR)articles/mixin.html, Mixins, + $(ROOT_DIR)articles/regular-expression.html, Regular Expressions, + $(ROOT_DIR)articles/safed.html, SafeD, + $(ROOT_DIR)articles/templates-revisited.html, Templates Revisited, + $(ROOT_DIR)articles/ctarguments.html, Compile-time Sequences, + $(ROOT_DIR)articles/variadic-function-templates.html, Variadic Templates, + $(ROOT_DIR)articles/d-array-article.html, D Slices, + $(ROOT_DIR)articles/cppcontracts.html, D's Contract Programming, + $(ROOT_DIR)articles/template-comparison.html, Template Comparison, + $(ROOT_DIR)articles/dll-linux.html, Writing Shared Libraries, + $(ROOT_DIR)articles/RefReturnScope.html, Coralling Wild Pointers With ref return scope, + $(ROOT_DIR)articles/dll-windows.html, Creating Windows DLLs + )) +) +SUBNAV_FOUNDATION= +$(SUBNAV_TEMPLATE + $(SUBNAV_HEAD Foundation, $(ROOT_DIR)foundation/index.html, overview) + $(UL $(SUBMENU2 + $(ROOT_DIR)foundation/about.html, About the Foundation, + $(ROOT_DIR)foundation/donate.html, Donate, + $(ROOT_DIR)foundation/upb-scholarship.html, Scholarships, + https://dconf.org, DConf, + $(ROOT_DIR)foundation/sponsors.html, Sponsors, + $(ROOT_DIR)foundation/contributors.html, Contributors, + $(ROOT_DIR)foundation/prman.html, Pull-Request/Issue Managers, + )) +) + +SUBNAV_HEAD= + $(DIVC head, + $(H2 $1) + $(TC p, $4, + $(LINK2 $2, $3)) + ) +SUBNAV_TEMPLATE=$(DIVC subnav-helper) $(DIVC subnav, $0) +_= + +SUBNAV_CLI_REFERENCE= +$(SUBNAV_TEMPLATE + $(SUBNAV_HEAD Command-line Reference, http://wiki.dlang.org/Development_tools, overview) + $(UL $(SUBMENU2 + $(ROOT_DIR)dmd-windows.html, dmd (Windows), + $(ROOT_DIR)dmd-linux.html, dmd (Linux), + $(ROOT_DIR)dmd-osx.html, dmd (OSX), + $(ROOT_DIR)dmd-freebsd.html, dmd (FreeBSD), + $(ROOT_DIR)rdmd.html, rdmd, + $(ROOT_DIR)install.html, install.sh, + $(ROOT_DIR)htod.html, htod + )) +) +SWNAME=$(LNAME2 switch$1, $(B $1)) +SWLINK=$(LINK2 #switch$1, $(B $1)) +SWITCH=$(DT $1)$(DD $+) +_= + +TABLE_10=$(TABLE2 $1, $+) +TABLE_2COLS=$(TABLE2 $1, $+) +TABLE_3COLS=$(TABLE2 $1, $+) +TABLE_SPECIAL=$(TABLE2 $1,$+) +TABLE2=$(T center, $(T table, $(T caption, $1)$(CONCAT $+))) +TDX=$(TD $1)$(TDX $+) +TH=$0 +THEAD=$(TR $(THX $1, $+)) +THX=$(TC th, donthyphenate, $(B $1))$(THX $+) +TOC=$(SPEC_S $1,$+) +TOC_LISTING=$0 +TR2=$(TR $1 $2) +TR3=$(TR $1 $2 $3) +TROW=$(TR $(TDX $1, $+)) +TROW_EXPLANATORY=$0 +_= + +UNDERSCORE=_ +UNDERSCORE_PREFIXED=_$1$(UNDERSCORE_PREFIXED $+) +UNDERSCORE_PREFIXED_SKIP=$(UNDERSCORE_PREFIXED $+) +UNDERSCORE_PREFIXED_SKIP2=$(UNDERSCORE_PREFIXED_SKIP $+) +_= + +VERTROW=$(TR $(TDX $1, $+)) +VISUALD = http://rainers.github.io/visuald/visuald/StartPage.html +_= + +WHITE=$(SPANC white, $0) +_= + +YELLOW=$(SPANC yellow, $0) +YES=$(CHECKMARK) + +PROJECT_SOURCE_DIR= + +FA_ICON= +_= + +_ = Opt-out of automatic keyword highlighting - see https://dlang.org/changelog/2.079.0.html#fix18361 +DDOC_AUTO_PSYMBOL = $0 +DDOC_AUTO_KEYWORD = $0 +DDOC_AUTO_PARAM = $0 +_ = DDOC_AUTO_PSYMBOL_SUPPRESS = FIXME_UNDERSCORE_PREFIX +DDOC_AUTO_PSYMBOL_SUPPRESS = $1 diff --git a/book/doc.ddoc b/book/doc.ddoc new file mode 100644 index 0000000000..2f2d9ff9fa --- /dev/null +++ b/book/doc.ddoc @@ -0,0 +1,23 @@ +ROOT_DIR = +ROOT = . +SELF_PATH = +BODYCLASS = doc +PROJECT = dlang.org +_= + +D_S = $(LAYOUT ,$1,$(ARGS $+)) +SPEC_S = $(LAYOUT ,$1,$(ARGS $+)) +COMMUNITY= $(LAYOUT ,$1,$(ARGS $+)) +_= + +LAYOUT=$3 +_= + +SFINAE=$(GLOSSARY2 sfinae, $(ACRONYM SFINAE, Substitution Failure Is Not An Error)) +_= + +AMAZONLINK= $(HTTP amazon.com/exec/obidos/ASIN/$1/classicempire, $+) +_= + +MIDRULE= +_= diff --git a/book/html.ddoc b/book/html.ddoc new file mode 100644 index 0000000000..2fd73d19ae --- /dev/null +++ b/book/html.ddoc @@ -0,0 +1,440 @@ +_=General macros for HTML generation. Even predefined macros are present +here for completeness. Macros defer wherever possible to style classes. + +_=Simple tags, ordered alphabetically + +A = $+ +ADEF = +AHTTP = $+ +AHTTPS = $+ +ALOCAL = $+ +BIG = $(EMC big, $0) +BR =
    +CAPTION = $(T caption, $0) +CHECKMARK = ✔ +DD = $(T dd, $0) +DIV =
    $+
    +DIVC = $(TC div, $1, $+) +DIVCID = $(DIV class="$1" id="$2", $3) +DIVID = $(DIV id="$1", $+) +DL = $(T dl, $0) +DOLLAR=$ +DOUBLEQUOTE = $(LDQUO)$0$(RDQUO) +DT = $(T dt, $0) +EMC = $(TC em, $1, $+) +ENUMERATE = $(OL $(ITEMS_HELPER $1, $+)) +GREATER = > +ITEMIZE = $(UL $(ITEMS_HELPER $1, $+)) +ITEMS_HELPER = $(LI $1)$(ITEMS_HELPER $+) +H1 = $(T h1, $0) +H2 = $(T h2, $0) +H3 = $(T h3, $0) +H4 = $(T h4, $0) +H5 = $(T h5, $0) +HR =
    +I = $(T i, $0) +LI = $(T li, $0) +LESS = < +OL = $(T ol, $0) +P = $(T p, $0) +PRE = $(T pre, $0) +SCRIPT = +SINGLEQUOTE = $(LSQUO)$0$(RSQUO) +SMALL = $(T small, $0) +SPAN = $+ +SPANC = $(TC span, $1, $+) +SPANID = $(SPAN id="$1", $+) +SUBSCRIPT = $(T sub, $0) +SUPERSCRIPT = $(T sup, $0) +TABLE = $(T table, $0) +TABLEC = $(TC table, $1, $+) +T=<$1>$+ +TC=<$1 class="$2">$(TAIL $+) +TD = $(T td, $0) +TD_HELPER = $(TD $1)$(TD_HELPER $+) +TH_HELPER = $(TH $1)$(TH_HELPER $+) +THEAD = $(TR $(TH_HELPER $1, $+)) +TR = $(T tr, $0) +TT = $(EMC tt, $0) +U = $(EMC u, $0) +UL = $(T ul, $0) +_= + +_=Defining anchors and linking + +LINK = $(A $0, $0) +LINK2 = $(A $1, $+) +HTTP = $(LINK2 http://$1,$2) +HTTPS = $(LINK2 https://$1,$2) +WEB = $(HTTP $1,$2) +_= + +_=Colors + +RED = $(SPAN style="color:red", $0) +GREEN = $(SPAN style="color:green", $0) +BLUE = $(SPAN style="color:blue", $0) +YELLOW = $(SPAN style="color:yellow", $0) +BLACK = $(SPAN style="color:black", $0) +WHITE = $(SPAN style="color:white", $0) +_= + +_=Explanatory stuff of the kind "Throws: blah" or "Returns: +blah". Note that if you want to make a SPAN-like (brief) explanation, +you can do it with the DIV block using "display: inline-block;", see +e.g. https://stackoverflow.com/questions/1611065/span-vs-div-inline-block + +DDOC_EXPLANATORY=$(DIVC explanatory, $(SPANC explanation_item, $1:) $(DIVC $1, $+)) +_= + +_=Predefined D-related stuff + +D_CODE = $(TC pre, d_code, $0) +OTHER_CODE = $(TC pre, code $1, $+) +D_COMMENT = $(SPANC d_comment, $0) +D_STRING = $(SPANC d_string, $0) +D_KEYWORD = $(SPANC d_keyword, $0) +D_PSYMBOL = $(SPANC d_psymbol, $0) +D_PARAM = $(SPANC d_param, $0) +D_TITLE = $(SPANC d_title, $0) +_= + +_=Main entry point + +DDOC = $(T html, +$(T head, + + + $(T title, $(TITLE)) +) +$(T body, $(H1 $(TITLE))$(BODY)))$(LF) +_= + +_=DDoc-related stuff + +DDOC_COMMENT = +DDOC_MEMBER = $0 +DDOC_MEMBER_HEADER = +DDOC_HEADER_ANCHOR = +DDOC_DECL = $(DT $(BIG $0)) +DDOC_DECL_DD = $(DD $0) +DDOC_DITTO = $(BR)$0 +DDOC_SECTIONS = $0$(LF) +DDOC_SUMMARY = $0$(BR)$(BR)$(LF) +DDOC_DESCRIPTION = $0$(BR)$(BR)$(LF) +DDOC_AUTHORS = $(B Authors:)$(BR) + $0$(BR)$(BR) +DDOC_BUGS = $(RED BUGS:)$(BR) + $0$(BR)$(BR)$(LF) +DDOC_COPYRIGHT = $(B Copyright:)$(BR) + $0$(BR)$(BR)$(LF) +DDOC_DATE = $(B Date:)$(BR) + $0$(BR)$(BR) +DDOC_DEPRECATED = $(RED Deprecated:)$(BR) + $0$(BR)$(BR) +DDOC_EXAMPLES = $(B Examples:)$(BR) + $0$(BR)$(BR) +DDOC_HISTORY = $(B History:)$(BR) + $0$(BR)$(BR) +DDOC_LICENSE = $(B License:)$(BR) + $0$(BR)$(BR) +DDOC_RETURNS = $(B Returns:)$(BR) + $0$(BR)$(BR) +DDOC_SEE_ALSO = $(B See Also:)$(BR) + $0$(BR)$(BR) +DDOC_STANDARDS = $(B Standards:)$(BR) + $0$(BR)$(BR) +DDOC_THROWS = $(B Throws:)$(BR) + $0$(BR)$(BR) +DDOC_VERSION = $(B Version:)$(BR) + $0$(BR)$(BR)$(LF) +DDOC_SECTION_H = $(B $0)$(BR)$(BR)$(LF) +DDOC_SECTION = $0$(BR)$(BR)$(LF) +DDOC_MEMBERS = $(DL $0) +DDOC_MODULE_MEMBERS = $(DDOC_MEMBERS $0)$(LF) +DDOC_CLASS_MEMBERS = $(DDOC_MEMBERS $0)$(LF) +DDOC_STRUCT_MEMBERS = $(DDOC_MEMBERS $0)$(LF) +DDOC_ENUM_MEMBERS = $(DDOC_MEMBERS $0)$(LF) +DDOC_TEMPLATE_MEMBERS = $(DDOC_MEMBERS $0)$(LF) +DDOC_PARAMS = $(B Params:)$(BR)$(LF) +$(TABLE $0)$(BR) +DDOC_PARAM_ROW = $(TR $0)$(LF) +DDOC_PARAM_ID = $(TD $0)$(LF) +DDOC_PARAM_DESC = $(TD $0) +_= + +DDOC_ANCHOR = $(ADEF $1) +DDOC_PSYMBOL = $(U $0) +DDOC_KEYWORD = $(B $0) +DDOC_PARAM = $(I $0) +DDOC_OVERLOAD_SEPARATOR = $(BR) +DDOC_CONSTRAINT=$(BR)$(SPAN class="constraint", if ($0)) +DDOC_TEMPLATE_PARAM_LIST=$(SPAN class="template_param_list" title="Template parameter list", $0) +_= + +_=Generic blurb to describe C header bindings + +C_HEADER_DESCRIPTION = This module contains bindings to selected types and +functions from the standard C header $(HTTP $1, $(D $(LESS)$2$(GREATER))). Note that this +is not automatically generated, and may omit some types/functions from the +original C header. +_= + +_=HTML named entities, ordered approximately as in https://dlang.org/entity.html + +QUOT = " +AMP = & +PERCENT = % +TAB = +_= + +OELIG_CAP = Œ +OELIG = œ +SCARON_CAP = Š +SCARON = š +YUML = Ÿ +CIRC = ˆ +TILDE = ˜ +ENSP =   +EMSP =   +THINSP =   +ZWNJ = ‌ +ZWJ = ‍ +LRM = ‎ +RLM = ‏ +NDASH = – +MDASH = — +LSQUO = ‘ +RSQUO = ’ +SBQUO = ‚ +LDQUO = “ +RDQUO = ” +BDQUO = „ +DAGGER = † +DAGGER_CAP = ‡ +PERMIL = ‰ +LSAQUO = ‹ +RSAQUO = › +EURO = € +NBSP =   +IEXCL = ¡ +CENT = ¢ +POUND = £ +CURREN = ¤ +YEN = ¥ +BRVBAR = ¦ +SECT = § +UML = ¨ +COPY = © +REG = ® +ORDF = ª +LAQUO = « +NOT = ¬ +SHY = ­ +REG = ® +MACR = ¯ +DEG = ° +PLUSMN = ± +SUP2 = ² +SUP3 = ³ +ACUTE = ´ +MICRO = µ +PARA = ¶ +MIDDOT = · +CEDIL = ¸ +SUP1 = ¹ +ORDM = º +RAQUO = » +FRAC14 = ¼ +FRAC12 = ½ +FRAC34 = ¾ +IQUEST = ¿ +AGRAVE_CAP = À +AACUTE_CAP = Á +ACIRC_CAP =  +ATILDE_CAP = à +AUML_CAP = Ä +ARING_CAP = Å +AELIG_CAP = Æ +CCEDIL_CAP = Ç +EGRAVE_CAP = È +EACUTE_CAP = É +ECIRC_CAP = Ê +EUML_CAP = Ë +IGRAVE_CAP = Ì +IACUTE_CAP = Í +ICIRC_CAP = Î +IUML_CAP = Ï +ETH_CAP = Ð +NTILDE_CAP = Ñ +OGRAVE_CAP = Ò +OACUTE_CAP = Ó +OCIRC_CAP = Ô +OTILDE_CAP = Õ +OUML_CAP = Ö +TIMES = × +OSLASH_CAP = Ø +UGRAVE_CAP = Ù +UACUTE_CAP = Ú +UCIRC_CAP = Û +UUML_CAP = Ü +YACUTE_CAP = Ý +THORN_CAP = Þ +SZLIG = ß +AGRAVE = à +AACUTE = á +ACIRC = â +ATILDE = ã +AUML = ä +ARING = å +AELIG = æ +CCEDIL = ç +EGRAVE = è +EACUTE = é +ECIRC = ê +EUML = ë +IGRAVE = ì +IACUTE = í +ICIRC = î +IUML = ï +ETH = ð +NTILDE = ñ +OGRAVE = ò +OACUTE = ó +OCIRC = ô +OTILDE = õ +OUML = ö +DIVIDE = ÷ +OSLASH = ø +UGRAVE = ù +UACUTE = ú +UCIRC = û +UUML = ü +YACUTE = ý +THORN = þ +YUML = ÿ +FNOF = ƒ +ALPHA_CAP = Α +BETA_CAP = Β +GAMMA_CAP = Γ +DELTA_CAP = Δ +EPSILON_CAP = Ε +ZETA_CAP = Ζ +ETA_CAP = Η +THETA_CAP = Θ +IOTA_CAP = Ι +KAPPA_CAP = Κ +LAMBDA_CAP = Λ +MU_CAP = Μ +NU_CAP = Ν +XI_CAP = Ξ +OMICRON_CAP = Ο +PI_CAP = Π +RHO_CAP = Ρ +SIGMA_CAP = Σ +TAU_CAP = Τ +UPSILON_CAP = Υ +PHI_CAP = Φ +CHI_CAP = Χ +PSI_CAP = Ψ +OMEGA_CAP = Ω +ALPHA = α +BETA = β +GAMMA = γ +DELTA = δ +EPSILON = ε +ZETA = ζ +ETA = η +THETA = θ +IOTA = ι +KAPPA = κ +LAMBDA = λ +MU = μ +NU = ν +XI = ξ +OMICRON = ο +PI = π +RHO = ρ +SIGMAF = ς +SIGMA = σ +TAU = τ +UPSILON = υ +PHI = φ +CHI = χ +PSI = ψ +OMEGA = ω +THETASYM = ϑ +UPSIH = ϒ +PIV = ϖ +BULL = • +HELLIP = … +PRIME = ′ +PRIME_CAP = ″ +OLINE = ‾ +FRASL = ⁄ +WEIERP = ℘ +IMAGE = ℑ +REAL = ℜ +TRADE = ™ +ALEFSYM = ℵ +LARR = ← +UARR = ↑ +RARR = → +DARR = ↓ +HARR = ↔ +CRARR = ↵ +LARR_CAP = ⇐ +UARR_CAP = ⇑ +RARR_CAP = ⇒ +DARR_CAP = ⇓ +HARR_CAP = ⇔ +FORALL = ∀ +PART = ∂ +EXIST = ∃ +EMPTY = ∅ +NABLA = ∇ +ISIN = ∈ +NOTIN = ∉ +NI = ∋ +PROD = ∏ +SUM = ∑ +MINUS = − +LOWAST = ∗ +RADIC = √ +PROP = ∝ +INFIN = ∞ +ANG = ∠ +AND = ∧ +OR = ∨ +CAP = ∩ +CUP = ∪ +INT = ∫ +THERE4 = ∴ +SIM = ∼ +CONG = ≅ +ASYMP = ≈ +NE = ≠ +EQUIV = ≡ +LE = ≤ +GE = ≥ +SUB = ⊂ +SUP = ⊃ +NSUB = ⊄ +SUBE = ⊆ +SUPE = ⊇ +OPLUS = ⊕ +OTIMES = ⊗ +PERP = ⊥ +SDOT = ⋅ +LCEIL = ⌈ +RCEIL = ⌉ +LFLOOR = ⌊ +RFLOOR = ⌋ +LOZ = ◊ +SPADES = ♠ +CLUBS = ♣ +HEARTS = ♥ +DIAMS = ♦ +LANG = ⟨ +RANG = ⟩ +_= diff --git a/book/macros.ddoc b/book/macros.ddoc new file mode 100644 index 0000000000..236e41693e --- /dev/null +++ b/book/macros.ddoc @@ -0,0 +1,14 @@ +_=Fundamental macros that apply to all generated formats + +ARGS = $0 +CONCAT = $1$(CONCAT $+) +COMMA = , +COMMENT = +DOLLAR = $ +LPAREN = ( +RPAREN = ) +TAIL = $+ +COLON = : +LF = $(LF) +$(LF) +_= diff --git a/book/test.d b/book/test.d new file mode 100644 index 0000000000..c30e42b191 --- /dev/null +++ b/book/test.d @@ -0,0 +1,13 @@ +Ddoc + +# Hello +Some text here + +```d +import std; +void main() => writeln("Hello World") +``` + +*Some more information here* + +### Karl \ No newline at end of file diff --git a/bugstats.dd b/bugstats.dd new file mode 100644 index 0000000000..c0ae6e591b --- /dev/null +++ b/bugstats.dd @@ -0,0 +1,35 @@ +Ddoc + +$(D_S Issue tracker, + +$(P + We use $(B Github) to track the issues for the D programming language. + $(BR) + The home of the D issue tracker is: $(B $(LINK https://github.com/dlang/dmd/issues)) +) + +$(P + You can browse through the existing projects $(LINK2 https://github.com/dlang, $(B here)). +) + +$(P + And if you want to file a new issue, you can use $(LINK2 https://github.com/dlang/dmd/issues/new, $(B this page)), + but please $(HTTPS github.com/dlang/dmd/blob/master/CONTRIBUTING.md#reporting-bugs, check the guidelines) first. +) + +$(H3 GitHub Labels) +$(P + Issues & PRs are categorized using $(LINK2 https://github.com/dlang/dmd/labels, labels). Common labels include: + $(UL + $(LI $(B $(LINK2 https://github.com/dlang/dmd/labels/Severity%3AICE, Severity:ICE )) - Internal Compilation Error) + $(LI $(B $(LINK2 https://github.com/dlang/dmd/labels/Severity%3AEnhancement, Severity:Enhancement)) - Enhancement requests) + $(LI $(B $(LINK2 https://github.com/dlang/dmd/labels/Severity%3ABug%20Fix, Severity:Bug Fix)) - Bug related issues) + $(LI $(B $(LINK2 https://github.com/dlang/dmd/labels/Druntime, Druntime)) - Specific to Druntime) + $(LI $(B $(LINK2 https://github.com/dlang/dmd/labels/P1, P1)) - High Priority) + $(LI $(B $(LINK2 https://github.com/dlang/dmd/labels/Review%3AWIP, Review:WIP)) - Work in Progress) + ) +) +) + +Macros: + TITLE=The D Issue Tracker diff --git a/bugstats.php.dd b/bugstats.php.dd deleted file mode 100644 index 517e51bd08..0000000000 --- a/bugstats.php.dd +++ /dev/null @@ -1,24 +0,0 @@ -Ddoc - -$(D_S Bug tracker, - -$(BOOKTABLE $(SECTION3 Current bugs $(LINK2 http://d.puremagic.com/issues/enter_bug.cgi?product=D,[report new bug])), -$(DISPLAY Regression, y_axis_field=bug_severity&query_format=report-table&product=D&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_severity=regression) -$(DISPLAY Blocker, y_axis_field=bug_severity&query_format=report-table&product=D&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_severity=blocker) -$(DISPLAY Critical, y_axis_field=bug_severity&query_format=report-table&product=D&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_severity=critical) -$(DISPLAY Major, y_axis_field=bug_severity&query_format=report-table&product=D&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_severity=major) -$(DISPLAY Normal$(COMMA) minor$(COMMA) or trivial, y_axis_field=bug_severity&query_format=report-table&product=D&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_severity=normal&bug_severity=minor&bug_severity=trivial) -$(DISPLAY Enhancement, y_axis_field=bug_severity&query_format=report-table&product=D&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_severity=enhancement) -$(DISPLAY All open, y_axis_field=bug_severity&query_format=report-table&product=D&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_severity=normal&bug_severity=minor&bug_severity=trivial&bug_severity=regression&bug_severity=blocker&bug_severity=critical&bug_severity=major&bug_severity=enhancement) -$(DISPLAY All closed, y_axis_field=bug_severity&query_format=report-table&product=D&bug_severity=normal&bug_severity=minor&bug_severity=trivial&bug_severity=regression&bug_severity=blocker&bug_severity=critical&bug_severity=major&bug_severity=enhancement&bug_status=RESOLVED&bug_status=VERIFIED&bug_status=CLOSED) -) - -$(P
    $(LINK2 http://d.puremagic.com/issues/reports.cgi?product=D&datasets=NEW%3A&datasets=ASSIGNED%3A&datasets=REOPENED%3A&datasets=RESOLVED%3A, )
    ) - -) - -Macros: - TITLE=Bug tracker for dmd - PHP= - BOOKTABLE =
    $2
    $1
    - DISPLAY=$(TR $(TD $(LINK2 http://d.puremagic.com/issues/buglist.cgi?$2, $1)) $(TD )) diff --git a/builtin.dd b/builtin.dd deleted file mode 100644 index 5143896f7d..0000000000 --- a/builtin.dd +++ /dev/null @@ -1,181 +0,0 @@ -Ddoc - -$(COMMUNITY Core Language Features vs Library Implementation, - - - $(P D offers several capabilities built in to the core language - that are implemented as libraries in other languages such - as C++: - ) - - $(OL - $(LI Dynamic Arrays) - $(LI Strings) - $(LI Associative Arrays) - ) - - $(P Some consider this as evidence of language bloat, rather than - a useful feature. - So why not implement each of these as standardized library types? - ) - - $(P Some general initial observations: - ) - - $(OL - - $(LI Each of them is heavily used. This means that even small - improvements in usability are worth reaching for. - ) - - $(LI Being a core language feature means that the compiler can - issue better and more to the point error messages when a type - is used incorrectly. - Library implementations tend to give notoriously obtuse messages - based on the internal details of those implementations. - ) - - $(LI Library features cannot invent new syntax, new operators, - or new tokens. - ) - - $(LI Library implementations tend to require a lot of compile - time processing of the implementation, over and over for each compile, - that slows down compilation. - ) - - $(LI Library implementations are supposed to provide flexibility - to the end user. But if they are standardized, standardized to the - point of the compiler being allowed to recognized them as special - (the C++ Standard allows this), then they become just as inflexible - as builtin core features. - ) - - $(LI The ability to define new library types, while having greatly - advanced in the last few years, still leaves a lot to be desired - in smoothly integrating it into the existing language. - Rough edges, clumsy syntax, and odd corner cases abound. - ) - - ) - - $(P More specific comments: - ) - -$(SECTION2 Dynamic Arrays, - - $(P C++ has builtin core arrays. It's just that they don't work very - well. Rather than fix them, several different array types were - created as part of the C++ Standard Template Library, each covering - a different deficiency in the builtin arrays. These - include: - ) - - $(UL - $(LI $(D basic_string)) - $(LI $(D vector)) - $(LI $(D valarray)) - $(LI $(D deque)) - $(LI $(D slice_array)) - $(LI $(D gslice_array)) - $(LI $(D mask_array)) - $(LI $(D indirect_array)) - ) - - $(P Fixing the builtin array support means the need for each of these - variations just evaporates. There's one array type that covers - it all, only one thing to learn, and no problems getting one array - type to work with another array type. - ) - - $(P As usual, a builtin type lets us create syntactic sugar for it. - This starts with having an array literal, and follows with some - new operators specific to arrays. A library array implementation - has to make due with overloading existing operators. - The indexing operator, $(D a[i]), it shares with C++. - Added are the array concatenation operator $(D ~), array append operator - $(D ~=), array slice operator $(D a[i..j]), - and the array vector operator - $(D a[]). - ) - - $(P The ~ and ~= concatenation operators resolve a problem that comes - up when only existing operators can be overloaded. Usually, + is - pressed into service as concatenation for library array - implementations. But that winds up precluding having + mean - array vector addition. Furthermore, concatenation has nothing in - common with addition, and using the same operator for both is - confusing. - ) -) - - -$(SECTION2 Strings, - - $(REDO $(P A detailed comparison with C++'s std::string. - )) - - $(P C++ has, of course, builtin string support in the form of string - literals and char arrays. It's just that they suffer from all - the weaknesses of C++ builtin arrays. - ) - - $(P But after all, what is a string if not an array of characters? - If the builtin array problems are fixed, doesn't that resolve - the string problems as well? It does. It seems odd at first that - D doesn't have a string class, but since manipulating strings - is nothing more than manipulating arrays of characters, if arrays - work, there's nothing a class adds to it. - ) - - $(P Furthermore, the oddities resulting from builtin string literals - not being of the same type as the library string class type go - away. - ) -) - - -$(SECTION2 Associative Arrays, - - $(P The main benefit for this is, once again, syntactic sugar. - An associative array keying off of a type $(D T) and storing an - $(D int) value is naturally written - as: - ) - ---------------- -int[T] foo; ---------------- - - $(P rather than: - ) - ---------------- -import std.associativeArray; -... -std.associativeArray.AA!(T, int) foo; ---------------- - - $(P Builtin associative arrays also offer the possibility of having - associative array literals, which are an often requested additional - feature. - ) -) - - -$(SECTION2 Please Note, - - $(P D currently has a built-in complex type that is being phased - out in favor of a library implementation. Advances in D language - semantics and compiler implementation have obviated the need for a - built-in complex type.) - -) - -) - -Macros: - TITLE=D Builtin Rationale - WIKI=builtins - CATEGORY_OVERVIEW=$0 - diff --git a/changelog.d b/changelog.d deleted file mode 100644 index 7e2330f7b5..0000000000 --- a/changelog.d +++ /dev/null @@ -1,2123 +0,0 @@ -Ddoc - -$(D_S D Change Log, - -$(UPCOMING - $(LI Shared libraries for Linux) -) - -$(VERSION 073, Jan 18, 2012, =================================================, - - $(WHATSNEW - $(LI Convert to -shared dmd switch instead of -dylib) - $(LI Better use of XMM registers in OS X 32 bit target.) - ) - $(BUGSFIXED -314 - [module] Static, renamed, and selective imports are always public -796 - Asserting a null object reference throws AssertError Failure internal\invariant.d(14) or Access Violation -1313 - out/body disables escape analysis -3092 - Indexing a tuple produces a tuple containing the indexed element -3187 - Nested foreach over opApply doesn't work -4135 - Regression(1.034): ICE(statement.c): mixin in bad foreach, D1 only -4413 - typeof(this) doesn't work in method template signature -4523 - [tdpl] .remove method for Associative Arrays returns void in all cases -4647 - [tdpl] Cannot explicitly call final interface method, ambiguous calls allowed -4711 - Incorrect handling of && operator with void operand -6037 - [CTFE] recursive ref parameters evaluated incorrectly -6701 - template specialization resolution failure -6933 - Segfault(declaration.c) using struct with destructor in CTFE -6934 - [CTFE] can't use $ in a slice of an array passed by ref -6964 - Error message with __error: static assert(undefined+1) -6984 - CTFE generates a torrent of spurious errors, if there was a previous error -6985 - [CTFE] Non-constant case expressions can't be interpreted -6995 - [CTFE] can't interpret static template method -7011 - No line number error for vector power -7043 - CTFE: ICE illegal reference value 0LU, only with -inline -7073 - Parsing of class-returning varargs function inside module ctor fails -7108 - ICE: TraitsExp::semantic(Scope*) 2.056 -> 2.057 regression - segfault -7120 - Scope Delegates + Delegate Literals -7123 - static assert(is(typeof(toDelegate(&main)))) is false -7127 - Const-related infinite recursion in DWARF generation -7143 - [CTFE] cannot compare class references with "is" -7144 - [CTFE] base class does not call overridden members -7154 - [CTFE] failing downcast causes error -7158 - [CTFE] ICE(interpret.c) calling a class member using a dotvar expression -7162 - [CTFE] "bool || void" expression crashes dmd -7165 - [CTFE] ice converting null pointer to bool with constant member function -7173 - dmd: glue.c:1065: virtual unsigned int Type::totym(): Assertion `0' failed. -7185 - [CTFE] ICE on changing char array length -7187 - Regression(head 12d62ca5): [CTFE] ICE on slicing -7189 - inline failed -7190 - Tuple length incorrect -7194 - [CTFE] Incorrect behaviour with pointers as local struct variable -7217 - [CTFE] ICE on accessing struct array field -7218 - Nested function with contract is rejected -7232 - Warning: statement is not reachable has no line number -7239 - C style struct initialization doesn't work with aliases -7245 - [CTFE] Address of ref foreach parameter changes to point after array -7248 - [CTFE] Stack overflow on using struct filed pointer with address of array element -7266 - [CTFE] Assign to ref param (that's taken from struct member) is noop -7285 - Implicit fixed-size array cast -7309 - [2.058] Regression caused by new inlining code - ) -) - -
    -$(UL - $(NEW1 073) - $(NEW1 072) - $(NEW1 071) - $(NEW1 070) - $(NEW1 069) - $(NEW1 068) - $(NEW1 067) - $(NEW1 066) - $(NEW1 065) - $(NEW1 064) - $(NEW1 063) - $(NEW1 062) - $(NEW1 061) - $(NEW1 060) - $(NEW1 059) - $(NEW1 058) - $(NEW1 057) - $(NEW1 056) - $(NEW1 055) - $(NEW1 054) - $(NEW1 053) - $(NEW1 052) - $(NEW1 051) - $(NEW1 050) - $(NEW1 049) - $(NEW1 048) - $(NEW1 047) - $(NEW1 046) - $(NEW1 045) - $(NEW1 044) - $(NEW1 043) - $(NEW1 042) - $(NEW1 041) - $(NEW1 040) - $(NEW1 039) - $(NEW1 038) - $(NEW1 037) - $(NEW1 036) - $(NEW1 035) - $(NEW1 034) - $(NEW1 033) - $(NEW1 032) - $(NEW1 031) - $(NEW1 030) - $(NEW1 029) - $(NEW1 028) - $(NEW1 027) - $(NEW1 026) - $(NEW1 025) - $(NEW1 024) - $(NEW1 023) - $(NEW1 022) - $(NEW1 021) - $(NEW1 020) - $(NEW1 019) - $(NEW1 018) - $(NEW1 017) - $(NEW1 016) - $(NEW1 015) - $(NEW1 014) - $(NEW1 013) - $(NEW1 012) - $(NEW1 011) - $(NEW1 010) - $(NEW1 009) - $(NEW1 007) - $(NEW1 006) - $(NEW1 005) - $(NEW1 004) - $(NEW1 003) - $(NEW1 002) - $(NEW1 001) - - $(LI $(LINK2 http://www.digitalmars.com/d/changelog.html, change log for D 2.0)) - $(LI $(LINK2 changelog2.html, older versions)) - $(LI $(LINK2 changelog1.html, even older versions)) - - $(LI Download latest stable (1.030) - - D compiler for Win32 and x86 linux) - - $(LI $(LINK2 http://www.digitalmars.com/pnews/index.php?category=2, tech support)) -$(COMMENT - $(LI $(LINK2 http://www.digitalmars.com/drn-bin/wwwnews?newsgroups=*, tech support)) -) -) -
    - -$(VERSION 072, Dec 10, 2011, =================================================, - - $(WHATSNEW - $(LI Better use of XMM registers in 64 bit targets.) - $(LI Add Mach-O 64 bit support for obj2asm and dumpobj) - $(LI Add OSX 64 bit target) - $(LI classes, interfaces, and exceptions are supported in CTFE) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 2532): '=' does not give a boolean result) - $(LI $(BUGZILLA 2856): static opIndex does not compile for a templated struct/class) - $(LI $(BUGZILLA 3990): Deferencing a dynamic array as pointer) - $(LI $(BUGZILLA 4047): [CTFE] class/struct heap allocation) - $(LI $(BUGZILLA 4511): Contravariance problem) - $(LI $(BUGZILLA 4583): PIC code not working: EBX register set incorrectly) - $(LI $(BUGZILLA 5311): Pure is broken when accessing globals / static data through instance reference) - $(LI $(BUGZILLA 5364): optimizer kills high dword of -1) - $(LI $(BUGZILLA 6077): CTFE: Cannot append null array to null array.) - $(LI $(BUGZILLA 6354): Optimizer bug on x86_64: Bitshift optimized out when foreach and scope(failure) are used) - $(LI $(BUGZILLA 6416): [CTFE] Declaration static struct is not yet implemented in CTFE) - $(LI $(BUGZILLA 6522): [CTFE] Problem with opAssign call in foreach(ref)) - $(LI $(BUGZILLA 6603): [CTFE] Can't call through a manifest constant function pointer) - $(LI $(BUGZILLA 6792): [CTFE] ICE with pointer cast of indexed array) - $(LI $(BUGZILLA 6800): [CTFE] dangerous pointer casts should be rejected) - $(LI $(BUGZILLA 6816): [CTFE] nested function can't access this) - $(LI $(BUGZILLA 6817): [CTFE] Error on interpreting inlined IfStatement) - $(LI $(BUGZILLA 6851): [CTFE] Cannot deref pointer passed by argument) - $(LI $(BUGZILLA 6859): Segfault when abstract method uses with contract.) - $(LI $(BUGZILLA 6868): IsExp + incorrect static array type = error) - $(LI $(BUGZILLA 6877): [XMM] regression, clobbered float value) - $(LI $(BUGZILLA 6879): The difference of between template matching and IsExp) - $(LI $(BUGZILLA 6881): [XMM] ICE with painted float) - $(LI $(BUGZILLA 6885): [CTFE] wrong code with dynamically allocated 2D array) - $(LI $(BUGZILLA 6886): [CTFE] ICE(interpret.c) new array with initializer) - $(LI $(BUGZILLA 6901): wrong error "override cannot be applied to variable" in CTFE forward reference) - $(LI $(BUGZILLA 6910): __traits(hasMember, "") does not work, if template has alias param) - $(LI $(BUGZILLA 6919): [CTFE] Cannot get effect to local variable through its pointer) - $(LI $(BUGZILLA 6972): [CTFE] ICE with ubyte/=uint) - $(LI $(BUGZILLA 6997): 64bit optimizer bug) - $(LI $(BUGZILLA 7004): Iterating tuple with index which explicitly typed as size_t causes an error) - $(LI $(BUGZILLA 7026): 64 bit optimizer bug) - $(LI $(BUGZILLA 7028): Fails to save FPU regs when executing finally block) - ) -) - -$(VERSION 071, Oct 26, 2011, =================================================, - - $(WHATSNEW - $(LI add -gs compiler switch) - $(LI $(BUGZILLA 6752): Add separate option to control stack frame generation) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 546): Error message for accessing a deprecated variable is doubled) - $(LI $(BUGZILLA 1891): Array-concatenation of T* and T*[] produces corrupted result) - $(LI $(BUGZILLA 1993): Error calling vararg delegate with null) - $(LI $(BUGZILLA 2315): DMD Stack Overflow on unwanted ctfe recursion) - $(LI $(BUGZILLA 2553): Excess attribute propagation for interfaces) - $(LI $(BUGZILLA 2740): Template Mixins do not work as advertised) - $(LI $(BUGZILLA 2953): tuple.length rejected as a tuple parameter in a static foreach) - $(LI $(BUGZILLA 3069): Array literals do not implicitly cast to void[]) - $(LI $(BUGZILLA 3133): Compiler does not check that static array casts are legal) - $(LI $(BUGZILLA 4022): [CTFE] AA get) - $(LI $(BUGZILLA 4197): ICE(glue.c): error in forward-referenced in/out contract) - $(LI $(BUGZILLA 4206): type accepted as enum initializer) - $(LI $(BUGZILLA 4237): Typedefs of the same name cause initializer conflict) - $(LI $(BUGZILLA 4269): Regression(2.031): invalid type accepted if evaluated while errors are gagged) - $(LI $(BUGZILLA 4284): empty string[] alias lacks .length in a template) - $(LI $(BUGZILLA 5453): ICE(statement.c): invalid switch statement forward referenced by CTFE) - $(LI $(BUGZILLA 5696): Templates typetuple iteration) - $(LI $(BUGZILLA 5932): Internal error: s2ir.c 339) - $(LI $(BUGZILLA 6073): Cannot pass __traits(parent, ...) as a template parameter if it is a module) - $(LI $(BUGZILLA 6084): Impossible to instantiate local template with TypeTuple-foreach iterator variable.) - $(LI $(BUGZILLA 6087): typeof(this) doesn't work outside member function) - $(LI $(BUGZILLA 6139): Duplicate error message on compile-time out of bounds array index) - $(LI $(BUGZILLA 6296): ICE(glue.c): invalid template instantiated in is(typeof()).) - $(LI $(BUGZILLA 6584): ICE on large version number/debug level) - $(LI $(BUGZILLA 6599): Segfault: invalid expression in initializer) - $(LI $(BUGZILLA 6661): Templates instantiated only through is(typeof()) shouldn't cause errors) - $(LI $(BUGZILLA 6665): Regression(2.055) ICE(cg87.c): static double inside closure) - $(LI $(BUGZILLA 6672): [CTFE] ICE on compile time std.algorithm.sort) - $(LI $(BUGZILLA 6693): [CTFE] Cannot set value to nested AA) - $(LI $(BUGZILLA 6695): typeof(this) does not take into account const/immutable attributes inside member functions) - $(LI $(BUGZILLA 6721): [CTFE] Cannot get pointer to start of char[]) - $(LI $(BUGZILLA 6727): [CTFE] ICE(interpret.c): assignment from string literal.dup.ptr) - $(LI $(BUGZILLA 6733): Regression(2.054) ICE(cod2.c) pure nothrow func with side-effect parameters) - $(LI $(BUGZILLA 6739): [CTFE] Cannot set a value to an outer AA of a nested AA) - $(LI $(BUGZILLA 6749): [CTFE] problem with array of structs) - $(LI $(BUGZILLA 6751): [CTFE] ref argument of AA doesn't work) - $(LI $(BUGZILLA 6765): [CTFE]: AA.length doesn't compile when AA is null) - $(LI $(BUGZILLA 6769): [CTFE] AA.keys doesn't compile when -inline is used) - $(LI $(BUGZILLA 6775): Regression(2.054) ICE(glue.c) template parameter deduction with errors gagged) - $(LI $(BUGZILLA 6813): Yet another "cannot get frame pointer" error) - $(LI $(BUGZILLA 6825): Regression(2.055+): Address of templated method incorrectly taken) - ) -) - -$(VERSION 070, Sep 4, 2011, =================================================, - - $(WHATSNEW - $(LI Add support for Mac OS X 10.7 Lion) - $(LI Add protection to json output) - $(LI Add SSE4.1 and SSE4.2 assembly instructions) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1471): Linker error on template function. Error 42: Symbol Undefined ...) - $(LI $(BUGZILLA 1567): call to private super-constructor should not be allowed) - $(LI $(BUGZILLA 1684): offsetof does not work, adding cast is workaround) - $(LI $(BUGZILLA 1904): wrong protection lookup for private template functions) - $(LI $(BUGZILLA 2156): [] and null should be accepted where a compile-time string is required) - $(LI $(BUGZILLA 2246): Regression(2.046, 1.061): Specialization of template to template containing int arguments fails) - $(LI $(BUGZILLA 2355): is() doesn't resolve aliases before template matching) - $(LI $(BUGZILLA 2634): Function literals are non-constant.) - $(LI $(BUGZILLA 2774): Functions-as-properties makes it impossible to get the .mangleof a function) - $(LI $(BUGZILLA 2941): Wrong code for inline asm because CPU type is set too late) - $(LI $(BUGZILLA 3512): dchar iteration over string in CTFE fails) - $(LI $(BUGZILLA 4021): [CTFE] AA rehash) - $(LI $(BUGZILLA 4444): Cannot index built-in array with expression tuple) - $(LI $(BUGZILLA 4460): Regression(2.036) ICE(e2ir.c) when compiling foreach over associative array literal) - $(LI $(BUGZILLA 4682): [CTFE] Run-time Vs Compile-time of int.min % -1) - $(LI $(BUGZILLA 4837): ICE(constfold.c) CTFE with >>>=) - $(LI $(BUGZILLA 5046): Wrong type of implicit 'this' in struct/class templates) - $(LI $(BUGZILLA 5239): optimizer misreports an used before set error) - $(LI $(BUGZILLA 5585): bad debug line number info for return statements with enumerator expressions) - $(LI $(BUGZILLA 5790): 'Error: variable result used before set' when -release -inline -O) - $(LI $(BUGZILLA 5799): Address-of operator fails on nested conditional operator expression) - $(LI $(BUGZILLA 5953): Too many trailing commas are accepted) - $(LI $(BUGZILLA 6097): SSSE3 not working with MMX instructions) - $(LI $(BUGZILLA 6215): LLVM-compiled DMD segfaults due to mem.c alignment issues) - $(LI $(BUGZILLA 6250): [CTFE] Crash when swapping two pointers to arrays.) - $(LI $(BUGZILLA 6270): XMMREGS not preserved on indirect function call) - $(LI $(BUGZILLA 6276): [CTFE] Strange behavior of using ~= operator twice) - $(LI $(BUGZILLA 6280): [CTFE] Cannot put 'in' expression of AA in an 'if' condition) - $(LI $(BUGZILLA 6281): [CTFE] A null pointer '!is null' returns 'true'.) - $(LI $(BUGZILLA 6282): [CTFE] ICE when dereferencing a pointer to reference type from 'in' of an AA) - $(LI $(BUGZILLA 6283): [CTFE][Regression 2.054] Failed to assign to AA using a constness-changed array as key) - $(LI $(BUGZILLA 6306): Regression(2.054): [CTFE] Strange behavior of indirect recursive call in CTFE) - $(LI $(BUGZILLA 6331): [CTFE] Cannot evaluate SliceExp on if condition) - $(LI $(BUGZILLA 6337): [CTFE] ICE when touching member variable of struct during CTFE) - $(LI $(BUGZILLA 6344): [CTFE] Assertion Failure in interpret.c when create an empty slice from null pointer) - $(LI $(BUGZILLA 6355): Template constructor cannot initialize non-mutable field) - $(LI $(BUGZILLA 6374): [CTFE] Cannot subscript using pointer to array) - $(LI $(BUGZILLA 6375): [CTFE] Segfault when using std.array.appender with an initial array) - $(LI $(BUGZILLA 6386): [CTFE] ICE on pointer casting) - $(LI $(BUGZILLA 6399): [CTFE] struct member array.length -= x doesn't work, while array[0..$-x] works) - $(LI $(BUGZILLA 6418): [CTFE] Cannot call a struct member function with name 'length'.) - $(LI $(BUGZILLA 6429): Nested function error in reduce) - $(LI $(BUGZILLA 6491): Fully qualified values in default arguments of non-template functions are generated with an extra 'module' keyword) - $(LI $(BUGZILLA 6505): Wrong code for expression involving 8 floats, only with -O) - $(LI $(BUGZILLA 6512): [CTFE] new T[][] doesn't work) - $(LI $(BUGZILLA 6516): Regression(2.055 beta) [CTFE] ICE(constfold.c) involving new dchar[]) - $(LI $(BUGZILLA 6558): [CTFE] UTF-decoding foreach gives wrong index (1-indexed)) - $(LI $(BUGZILLA 6563): wrong code when using at least 8 XMM regs) - $(LI $(BUGZILLA 6601): Regression(2.053): CTFE segfault taking address of function template) - $(LI $(BUGZILLA 6602): Invalid template instantiations leaked by is(typeof())/__traits(compiles, )/Type::trySemantic) - ) -) - -$(VERSION 069, Jul 10, 2011, =================================================, - - $(WHATSNEW - $(LI Allow labelled break and continue in CTFE) - $(LI Pointers are now supported in CTFE) - $(LI Heap-allocated structs are now supported in CTFE) - $(LI Added SSSE3 instructions to inline assembler) - $(LI Change win32 dmd to not emit a map file unless asked for with -map) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 693): 'this' can't be used as an alias parameter for a mixin) - $(LI $(BUGZILLA 1373): typeof(func).stringof fails when func has parameters.) - $(LI $(BUGZILLA 1570): Wrong return for address operator) - $(LI $(BUGZILLA 2180): filename error with #line) - $(LI $(BUGZILLA 2842): std.file.listdir on OSX produces invalid UTF-8 sequence) - $(LI $(BUGZILLA 3445): partial fix) - $(LI $(BUGZILLA 3722): A method without an in contract should always succeed, even if overridden) - $(LI $(BUGZILLA 4063): [CTFE] key not found in AA gives bad error message) - $(LI $(BUGZILLA 4065): [CTFE] AA "in" operator doesn't work) - $(LI $(BUGZILLA 4107): Duplicate documentation for member function templates) - $(LI $(BUGZILLA 4448): [CTFE] labeled break doesn't work in CTFE) - $(LI $(BUGZILLA 4494): ICE(cod1.c) Array literal filled with results of void function) - $(LI $(BUGZILLA 4633): typeof({return 1;}()) declaration fails if inside main) - $(LI $(BUGZILLA 4745): Non-uniform handling of commas in static initialization of structs) - $(LI $(BUGZILLA 4910): [CTFE] Cannot evaluate a function that has failed at once) - $(LI $(BUGZILLA 4963): ICE(type.c:320) for struct append where T.sizeof < 3) - $(LI $(BUGZILLA 4969): nothrow check can't handle multiple catches) - $(LI $(BUGZILLA 5086): Regression(1.061): Stack overflow with recursive alias declaration) - $(LI $(BUGZILLA 5258): [CTFE] Stack overflow with struct by ref) - $(LI $(BUGZILLA 5396): [CTFE] Invalid code with nested functions in CTFE) - $(LI $(BUGZILLA 5615): [CTFE] std.string.indexOf broken at compile time) - $(LI $(BUGZILLA 5633): [CTFE] ICE(constfold.c): is expression with struct, struct pointer, array literal...) - $(LI $(BUGZILLA 5676): [CTFE] segfault using tuple containing struct that has opAssign) - $(LI $(BUGZILLA 5682): [CTFE] Silently wrong result possibly related to operator overloading and expression order) - $(LI $(BUGZILLA 5682): Wrong CTFE with operator overloading) - $(LI $(BUGZILLA 5708): [CTFE] Incorrect string constant folding with -inline) - $(LI $(BUGZILLA 5845): Regression(2.041) [CTFE] "stack overflow" with recursive ref argument) - $(LI $(BUGZILLA 5936): Invalid code with nested functions in CTFE) - $(LI $(BUGZILLA 5946): failing lookup 'this' from function in template) - $(LI $(BUGZILLA 5963): iasm does not accept 64bit integer literal) - $(LI $(BUGZILLA 5885): wrong codegen for OPu32_d) - $(LI $(BUGZILLA 6001): [CTFE] ICE(interpret.c) mutating ref array) - $(LI $(BUGZILLA 6015): [CTFE] Strange behavior of assignment appears in a situation) - $(LI $(BUGZILLA 6049): [CTFE] Array literals of structs with invariant() are wrong) - $(LI $(BUGZILLA 6052): [CTFE] Struct elements in an array are treated like reference type) - $(LI $(BUGZILLA 6053): [CTFE] Two ICEs involving pointers (dereference and assign; pointer variable on stack)) - $(LI $(BUGZILLA 6054): [CTFE] ICE when returning a returned compile-time associative array containing a key of an idup-ed array literal) - $(LI $(BUGZILLA 6072): [CTFE] Regression(git master): Cannot declare variable inside an 'if' condition) - $(LI $(BUGZILLA 6077): [CTFE] Cannot append null array to null array.) - $(LI $(BUGZILLA 6078): [CTFE] ICE on foreach over array struct member which is null) - $(LI $(BUGZILLA 6079): [CTFE] Array index out of bound detection is off-by-one) - $(LI $(BUGZILLA 6090): DDoc parenthesis escape issues.) - $(LI $(BUGZILLA 6100): [CTFE] Regression: struct return values wrong if used in array initializer) - $(LI $(BUGZILLA 6120): [CTFE] ICE on calling constructor of template struct with -inline in function/delegate literal.) - $(LI $(BUGZILLA 6123): [CTFE] Cannot call a template member method inside delegate/function literal with -inline.) - $(LI $(BUGZILLA 6137): [CTFE] Foreach on semantically wrong initialized array crashes the compiler) - $(LI $(BUGZILLA 6164): [CTFE] Local arrays in a recursive local function behave funny) - $(LI $(BUGZILLA 6242): Disallow inoperant "in" contracts) - ) -) - -$(VERSION 068, May 12, 2011, =================================================, - - $(WHATSNEW - $(LI Added 64 bit tools to Linux) - $(LI Renamed linux/bin to linux/bin32, added linux/bin64) - $(LI $(BUGZILLA 4833): dmd -od doesn't make it to optlink's command line for map files) - $(LI Added cmpxchg16b, 64 bit bswap and movq instructions to IASM) - - ) - $(BUGSFIXED - $(LI $(BUGZILLA 937): C-style variadic functions broken) - $(LI $(BUGZILLA 1330): Array slicing does not work the same way in CTFE as at runtime) - $(LI $(BUGZILLA 1389): Can't use mixin expressions when start of a statement.) - $(LI $(BUGZILLA 2436): Unexpected OPTLINK termination EIP = 00425303 with /co) - $(LI $(BUGZILLA 2990): TypeInfo.init() returns invalid array) - $(LI $(BUGZILLA 3214): Incorrect DWARF line number debugging information on Linux) - $(LI $(BUGZILLA 3372): optlink silently mistreats object files with more than 16384 symbols) - $(LI $(BUGZILLA 3779): ["123"][0][$-1] causes __dollar unresolved in compile-time.) - $(LI $(BUGZILLA 3792): Regression(1.053) "non-constant expression" for a template inside) - $(LI $(BUGZILLA 3801): CTFE: this.arr[i] cannot be evaluated at compile time for structs) - $(LI $(BUGZILLA 3809): Struct initializers apparently always CTFE'd) - $(LI $(BUGZILLA 3835): ref foreach does not work in CTFE) - $(LI $(BUGZILLA 4001): const variables should be readable inside CTFE) - $(LI $(BUGZILLA 4048): [CTFE] struct initializer: missing line number in error message) - $(LI $(BUGZILLA 4050): [CTFE] array struct member slice update) - $(LI $(BUGZILLA 4051): [CTFE] array struct member item update) - $(LI $(BUGZILLA 4140): Error: non-constant expression "hello"[1u..__dollar]) - $(LI $(BUGZILLA 4275): Unexpected optlink termination when 'export' attribute is missing) - $(LI $(BUGZILLA 4543): Regression(1.054, 2.038) typedef circular definition and segfault) - $(LI $(BUGZILLA 4815): CodeView: Global and Static symbols should have unmangled names) - $(LI $(BUGZILLA 4817): CodeView: Enum members should have simple names) - $(LI $(BUGZILLA 4917): Symbol conflict error message refers to aliased symbol instead of the alias) - $(LI $(BUGZILLA 5147): [CTFE] Return fixed-sized matrix) - $(LI $(BUGZILLA 5362): checking $ in bracket is broken.) - $(LI $(BUGZILLA 5647): [64-bit] Valgrind complains about illegal instruction) - $(LI $(BUGZILLA 5664): Cannot compile static synchronized member function.) - $(LI $(BUGZILLA 5670): Optlink 8.00.11 crash) - $(LI $(BUGZILLA 5671): Issue 5671 - CTFE string concat problem) - $(LI $(BUGZILLA 5672): ICE(cod2.c): incorrect optimization of (long &1) == 1) - $(LI $(BUGZILLA 5680): wrong calling convention on wsprintfA/W) - $(LI $(BUGZILLA 5694): va_arg doesn't work with idouble and ifloat) - $(LI $(BUGZILLA 5706): Incorrect opcode prefix generated for x86_64 inline assembly) - $(LI $(BUGZILLA 5708): Incorrect string constant folding with -inline) - $(LI $(BUGZILLA 5717): 1.067 regression: appending Unicode char to string broken) - $(LI $(BUGZILLA 5722): Regression(2.052): Appending code-unit from multi-unit code-point at compile-time gives wrong result.) - $(LI $(BUGZILLA 5735): non-scalar types implicitly converted to boolean.) - $(LI $(BUGZILLA 5740): Unable to use "this" pointer in inline assembly) - $(LI $(BUGZILLA 5741): Add the SYSCALL and SYSRET opcodes to the inline assembler) - $(LI $(BUGZILLA 5840): Cannot assign to an array member of struct in CTFE) - $(LI $(BUGZILLA 5852): CTFE: wrong code for string[] ~= const(string)) - $(LI $(BUGZILLA 5858): Import not acctept const string as arguments) - $(LI $(BUGZILLA 5865): __dollar cannot be read at compile time) - $(LI $(BUGZILLA 5916): DMD: bad message for incorrect operands error) - $(LI $(BUGZILLA 5966): [2.053 beta][CTFE] Stack overflow on trivial func) - $(LI $(BUGZILLA 5972): CTFE: Can't assign to elements of arrays of slices) - $(LI $(BUGZILLA 5975): [2.053 beta][CTFE] ICE: 'global.errors' on line 1416 in file 'constfold.c') - $(LI $(BUGZILLA 5976): "variable used before set" with foreach with ref + scope(failure) + structure method + -O -inline) - $(LI Fix spelling of $(CODE cmpxchgb8)) - ) -) - -$(VERSION 067, Feb 17, 2011, =================================================, - - $(WHATSNEW - $(LI 64 bit support for Linux) - $(LI Support HTML5 entities) - $(LI FreeBSD version upgraded to FreeBSD 8.1) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 190): Cannot forward reference typedef/alias in default value for function parameter) - $(LI $(BUGZILLA 1914): Array initialisation from const array yields memory trample) - $(LI $(BUGZILLA 3198): wrong initializer for structs arrays) - $(LI $(BUGZILLA 3681): ICE(go.c): when function takes too long to optimize, only with -O.) - $(LI $(BUGZILLA 4245): Declaring conflicting symbols in single function scope allowed) - $(LI $(BUGZILLA 4379): ICE(blockopt.c): foreach over huge tuple, only with -O) - $(LI $(BUGZILLA 4389): ICE(constfold.c, expression.c), or wrong code: string~=dchar in CTFE) - $(LI $(BUGZILLA 4486): CodeView debug info should contain absolute path names) - $(LI $(BUGZILLA 4753): fail_compilation/fail116.d sends dmd into a loop, exhausting memory) - $(LI $(BUGZILLA 4878): Ddoc: Default arguments can break Ddoc output) - $(LI $(BUGZILLA 4973): map file with spaces in file name passed without quotes to linker) - $(LI $(BUGZILLA 5015): Regression(1.061): Cyclic import breaks is() in a static if) - $(LI $(BUGZILLA 5090): ICE(todt.c) struct literal initializing zero length array) - $(LI $(BUGZILLA 5105): Member function template cannot be synchronized) - $(LI $(BUGZILLA 5221): entity.c: Merge Walter's list with Thomas') - $(LI $(BUGZILLA 5241): dmd: ABI breakage/regression (TypeInfo.toString() returns partially corrupted string)) - $(LI $(BUGZILLA 5242): self referencing template constraint crashes compiler) - $(LI $(BUGZILLA 5244): PATCH: fix use of uninitialised variable in toObj.c) - $(LI $(BUGZILLA 5246): PATCH(s): fix a couple more uninitialised variables) - $(LI $(BUGZILLA 5349): ICE(toir.c): nested class in static member function) - $(LI $(BUGZILLA 5391): Crash with recursive alias declaration) - $(LI $(BUGZILLA 5439): 64bit struct alignment inconsistent with C ABI) - $(LI $(BUGZILLA 5455): ICE(cgcod.c): Optimization (register allocation?) regression in DMD 1.065) - $(LI $(BUGZILLA 5486): Missing define for running dmd as 64 bit) - $(LI $(BUGZILLA 5534): [64-bit] Inexplicable segfault in small code snippet, -O -release -m64 only) - $(LI $(BUGZILLA 5536): Array append with dollar op on 64-bit) - $(LI $(BUGZILLA 5545): [64-bit] DMD fails to postincrement ubytes.) - $(LI $(BUGZILLA 5549): [64-bit] Internal error: backend/cgcod.c 1845) - $(LI $(BUGZILLA 5556): [64-bit] Wrong Implicit Conversion to Double) - $(LI $(BUGZILLA 5557): [64-Bit] FP (alignment?) issues with Rvalues) - $(LI $(BUGZILLA 5564): [64-bit] loading of wrong constant byte value) - $(LI $(BUGZILLA 5565): [64-bit] Wrong Floating Point Results, Related to Mixing With size_t) - $(LI $(BUGZILLA 5566): [64-bit] More erratic FP results with size_t) - $(LI $(BUGZILLA 5571): [64-bit] new bool returns bogus address) - $(LI $(BUGZILLA 5572): [64-bit] Global Hidden Mutexes Seem to share Addresses W/ Global Variables) - $(LI $(BUGZILLA 5580): [64-bit] String switch statements broken in 64-bit mode) - $(LI $(BUGZILLA 5581): [64-bit] Wrong code with bitwise operations on bools) - $(LI $(BUGZILLA 5592): Previous definition different: __arrayExpSliceMulSliceAddass_d) - ) -) - -$(VERSION 066, Dec 21, 2010, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI $(BUGZILLA 603): Undocumented behaviour: case and default create a scope) - $(LI $(BUGZILLA 632): Typedef/enum promotions spec ambiguous - ultimate base type or lowest common denominator?) - $(LI $(BUGZILLA 679): Spec needs allowances for copying garbage collection) - $(LI $(BUGZILLA 690): ABI not fully documented) - $(LI $(BUGZILLA 1351): Discrepancies in the language specification) - $(LI $(BUGZILLA 1466): Spec claims maximal munch technique always works: not for "1..3") - $(LI $(BUGZILLA 2206): unnamed template mixin of class inside function or class has incorrect classinfo and mangleof) - $(LI $(BUGZILLA 2385): spec says all structs are returned via hidden pointer on linux, but it uses registers) - $(LI $(BUGZILLA 2392): Parsing ambiguity between function pointer declaration and function call) - $(LI $(BUGZILLA 2406): Declarator2 definition error) - $(LI $(BUGZILLA 2556): Property classinfo needs better documentation (RTTI, typeof, typeid, runtime type information)) - $(LI $(BUGZILLA 2616): Undocumented behaviour: part-explicit, part-implicit instantiations of function templates are accepted) - $(LI $(BUGZILLA 2651): class body declaration grammar incorrect) - $(LI $(BUGZILLA 2652): DeclDef grammar is wrong) - $(LI $(BUGZILLA 2734): Ambiguity in tokenizing: _._ as a float literal) - $(LI $(BUGZILLA 2994): Incomplete "Predefined Versions" documentation) - $(LI $(BUGZILLA 3112): Specification on what operations call the GC is missing) - $(LI $(BUGZILLA 3276): Recursion broken by alias template parameter) - $(LI $(BUGZILLA 3554): Ddoc generates invalid output for documentation comments with non paired parantheses) - $(LI $(BUGZILLA 4529): Segfault(typinf.c) involving typeid(typeof(functionName))) - $(LI $(BUGZILLA 4728): Segfault(toctype.c) by protected/private constructor in an other module) - $(LI $(BUGZILLA 4864): ICE(statement.c) Crash on invalid 'if statement' body inside mixin) - $(LI $(BUGZILLA 5110): Excess attribute propagation of structs and classes) - $(LI $(BUGZILLA 5117): [CTFE] Member function call with rather complex this: side effects ignored) - $(LI $(BUGZILLA 5120): ICE(mtype.c) void associative arrays) - $(LI $(BUGZILLA 5145): Regression(2.050, 1.065) override error with forward ref of superclass) - $(LI $(BUGZILLA 5159): Segfault(interpret.c): calling a static function pointer variable in CTFE) - $(LI $(BUGZILLA 5164): Error without line number using "is (T...)") - $(LI $(BUGZILLA 5180): ICE(arrayop.c) in-place array operation on incompatible types) - $(LI $(BUGZILLA 5182): ICE(expression.c): calling unittest from a function) - $(LI $(BUGZILLA 5195): Forward references ignore const) - $(LI $(BUGZILLA 5230): Regression(2.041, 1.057) ICE(tocsym.c) overriding a method that has an out contract) - $(LI $(BUGZILLA 5238): PATCH: fix return of uninitialised var in interpret.c) - $(LI $(BUGZILLA 5275): x86_64 related hidden function parameter mishandled) - $(LI $(BUGZILLA 5294): -O optimization breaks for loop) - $(LI $(BUGZILLA 5331): mach format problem) - ) -) - -$(VERSION 065, Oct 29, 2010, =================================================, - - $(WHATSNEW - $(LI added talign() and argTypes() to TypeInfo) - $(LI Upgrade zlib support to zlib 1.2.5) - ) - $(BUGSFIXED - $(LI Unlisted bug: signed long comparisons under OS X) - $(LI $(BUGZILLA 3602): ICE(tocsym.c) compiling a class, if its super class has preconditions) - $(LI $(BUGZILLA 3665): Regression(1.051, 2.036) Assignment with array slicing does not work) - $(LI $(BUGZILLA 4398): dmd always uses Windows name mangling for _d_throw - $(RED may require update to Tango)) - $(LI $(BUGZILLA 4623): Non-integer type allowed as static array size) - $(LI $(BUGZILLA 4768): Regression(1.056): wrong code with forward declaration of enum) - $(LI $(BUGZILLA 4825): Regression(1.057, 2.040) "Error: non-constant expression" with -inline) - $(LI $(BUGZILLA 4873): Assertion failure: '0' on line 1483 in file 'expression.c') - $(LI $(BUGZILLA 4897): CodeView: No locals or parameters are shown when debugging, because of missing function info) - $(LI $(BUGZILLA 4925): [ICE] segfault with module-scope assert(0)) - $(LI $(BUGZILLA 4926): ICE: PREC_zero assertion failure due to unset precedence) - $(LI $(BUGZILLA 4941): Built-in tuple slice boundaries are not CTFE'd) - $(LI $(BUGZILLA 4949): ICE on invalid static if using value of 'this') - $(LI $(BUGZILLA 5026): ICE(expression.c) Incomplete mixin expression + char[] to char assignment) - ) -) - -$(VERSION 064, Sep 13, 2010, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(xxLI $(BUGZILLA 190): Cannot forward reference typedef/alias in default value for function parameter) - $(LI $(BUGZILLA 1715): Template specialization checks for equality rather than convertibility) - $(LI $(BUGZILLA 1970): Templated interfaces not matched) - $(LI $(BUGZILLA 2511): Covariant return type doesn't work with circular import) - $(LI $(BUGZILLA 2716): Confusion of auto and scope as the class attribute) - $(LI $(BUGZILLA 3046): Segfault with C++ static variable (Linux only)) - $(LI $(BUGZILLA 3418): link error with cast(ulong)(ulong*real)) - $(xxLI $(BUGZILLA 3493): Segfault(cast.c) Forward reference with type inference, D1 only.) - $(LI $(BUGZILLA 3544): optlink termination 0041338f with recursive nested functions) - $(LI $(BUGZILLA 3554): Ddoc generats invalid output for documentation comments with non paired paranthasis) - $(LI $(BUGZILLA 3627): -of with a filename with a double extension confuses linker) - $(LI $(BUGZILLA 4009): OPTLINK ruins the day yet again) - $(LI $(BUGZILLA 4173): Regression(2.037) Explicitly instantiated templates still try to do IFTI in some cases) - $(LI $(BUGZILLA 4278): allow inlining of super calls (undo limitations of bug3500's fix)) - $(LI $(BUGZILLA 4302): Regression(2.046, 1.061): compiler errors using startsWith in CTFE) - $(LI $(BUGZILLA 4645): to!string(const char*) in library causes Optlink to issue warning) - $(LI $(BUGZILLA 4652): Compiler hangs on template with zero-length tuple and another argument) - $(LI $(BUGZILLA 4655): Regression(1.063, 2.048) goto to a try block ICEs) - $(LI $(BUGZILLA 4676): Overload resolution rejects valid code when mixing variadics, non-variadics) - $(LI $(BUGZILLA 4691): Incorrect comparison of double and long) - $(LI $(BUGZILLA 4721): compilation slow when compiling unittests on dcollections) - $(LI $(BUGZILLA 4751): Regression(1.062, 2.047) ICE(constfold.c) >> after error) - $(LI $(BUGZILLA 4752): fail_compilation/fail345.d asserts in expression.c) - $(LI $(BUGZILLA 4771): fail_compilation/fail274.d hits a halt in iasm.c) - $(LI $(BUGZILLA 4828): ICE w/ non-boolean dot expression sth.template_instance in static if) - ) -) - -$(VERSION 063, Aug 8, 2010, =================================================, - - $(WHATSNEW - $(LI $(BUGZILLA 4080): Patch for building dynamic libraries on Mac OS X) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1418): tupleof bug on nested classes) - $(LI $(BUGZILLA 1678): ref with varargs generates invalid code) - $(LI $(BUGZILLA 2931): Initialization struct with array from another struct) - $(LI $(BUGZILLA 3326): $ in delegate literal causes Access Violation) - $(LI $(BUGZILLA 3560): foreach over nested function generates wrong code) - $(LI $(BUGZILLA 3569): DMD Stack Overflow with a struct member function inside a C-style struct initializer) - $(LI $(BUGZILLA 3679): Regression(2.031) template forward reference regression) - $(LI $(BUGZILLA 3706): delegates of interfaces with multiple inheritance fail) - $(LI $(BUGZILLA 4191): [FreeBSD] real constants are rounded to double precision) - $(LI $(BUGZILLA 4198): [FreeBSD] imprecision in decimal floating-point literals) - $(LI $(BUGZILLA 4238): Segfault(statement.c): with(typeof(int))) - $(LI $(BUGZILLA 4303): __traits(compiles) returns wrong result when used recursively) - $(LI $(BUGZILLA 4314): Regression(1.062): Expression array1 && array2 doesn't compile) - $(LI $(BUGZILLA 4339): Struct destructor + invariant + struct parameter = horrific error message) - $(LI $(BUGZILLA 4396): mkdir race prevents concurrent compiling with DMD using make -j) - $(LI $(BUGZILLA 4443): Optimizer produces wrong code for || or && with struct arrays) - $(LI $(BUGZILLA 4503): forward reference to aliased template instance) - $(LI $(BUGZILLA 4506): Regression(2.034): -O flag breaks some recursive functions) - $(LI $(BUGZILLA 4514): Regression: Cannot cast from X* to X) - $(LI $(BUGZILLA 4569): extern(c++) doesn't understand const types, produces bad mangled symbol) - $(LI $(BUGZILLA 4578): Regression(2.047,1.062): ICE(cgcod.c): var+arr[]) - ) -) - - -$(VERSION 062, Jun 9, 2010, =================================================, - - $(WHATSNEW - $(LI $(BUGZILLA 2008): Poor optimization of functions with ref parameters) - $(LI $(BUGZILLA 4296): Reduce parasitic error messages) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1193): regression: "matches more than one template declaration" doesn't list the location of the conflicting templates) - $(LI $(BUGZILLA 1894): scope(exit) is ignored except in compound statements) - $(LI $(BUGZILLA 1941): missing line on inaccesable external private module member) - $(LI $(BUGZILLA 2127): inliner turns struct "return *this" from by-value into by-ref) - $(LI $(BUGZILLA 2276): Error message missing line number on array operation) - $(LI $(BUGZILLA 2546): Array Ops silently fail when no slice symbol is used.) - $(LI $(BUGZILLA 2881): x.stringof returns typeof(x).stringof when x is an enum) - $(LI $(BUGZILLA 3064): Invalid array operation accepted, generates bad code) - $(LI $(BUGZILLA 3323): Segfault or ICE(e2ir.c) using struct with destructor almost anywhere) - $(LI $(BUGZILLA 3398): Attributes inside a union screws data alignment) - $(LI $(BUGZILLA 3547): for option -od for relative path the path is added twice) - $(LI $(BUGZILLA 3548): ICE occurs when an array is returned from a function is incorrectly used in an array op expression.) - $(LI $(BUGZILLA 3651): mangleof broken for enums) - $(LI $(BUGZILLA 3854): Error on static initialization of arrays with trailing comma.) - $(LI $(BUGZILLA 4003): The result changes only with the order of source files.) - $(LI $(BUGZILLA 4045): [CTFE] increasing array length) - $(LI $(BUGZILLA 4052): [CTFE] increment from array item) - $(LI $(BUGZILLA 4078): [CTFE] Failed return of dynamic array item) - $(LI $(BUGZILLA 4084): Ignored missing main() closing bracket) - $(LI $(BUGZILLA 4143): fix warnings in dmd build) - $(LI $(BUGZILLA 4156): Segfault with array+=array) - $(LI $(BUGZILLA 4169): building dmd with a modern gcc produces a buggy compiler) - $(LI $(BUGZILLA 4175): linux.mak doesn't declare sufficient dependencies to support parallel builds) - $(LI $(BUGZILLA 4210): Random crashes / heisenbugs caused by dmd commit 478: compiler messes up vtables) - $(LI $(BUGZILLA 4212): DWARF: void arrays cause gdb errors) - $(LI $(BUGZILLA 4213): Strange behaviour with static void[] arrays) - $(LI $(BUGZILLA 4242): ICE(module.c): importing a module with same name as package) - $(LI $(BUGZILLA 4252): [CTFE] No array bounds checking in assignment to char[] array) - $(LI $(BUGZILLA 4257): ICE(interpret.c): passing parameter into CTFE as ref parameter) - $(LI $(BUGZILLA 4259): Header generation omits leading '@' for properties) - $(LI $(BUGZILLA 4270): Missing line number in 'can only catch class objects' error message) - ) -) - -$(VERSION 061, May 10, 2010, =================================================, - - $(WHATSNEW - $(LI Add hints for missing import declarations.) - $(LI Speed up compilation.) - ) - $(BUGSFIXED - $(LI Fix hanging problem on undefined identifiers.) - $(LI $(BUGZILLA 461): Constant not understood to be constant when circular module dependency exists.) - $(LI $(BUGZILLA 945): template forward reference with named nested struct only) - $(LI $(BUGZILLA 1055): union forward reference "overlapping initialization" error) - $(LI $(BUGZILLA 2085): CTFE fails if the function is forward referenced) - $(LI $(BUGZILLA 2386): Array of forward referenced struct doesn't compile) - $(LI $(BUGZILLA 4015): forward reference in alias causes error) - $(LI $(BUGZILLA 4016): const initializer cannot forward reference other const initializer) - $(LI $(BUGZILLA 4042): Unable to instantiate a struct template.) - $(LI $(BUGZILLA 4100): Break and continue to label should mention foreach) - ) -) - - -$(VERSION 060, May 4, 2010, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI Another try at fixing the Dwarf issues.) - ) -) - -$(VERSION 059, Apr 30, 2010, =================================================, - - $(WHATSNEW - $(LI Improve spelling checking distance to 2.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1079): gdb: Dwarf Error: Cannot find DIE at 0xb705 referenced from DIE at 0x250) - $(LI $(BUGZILLA 2549): Segfault on array multiplication.) - $(LI $(BUGZILLA 3066): Array operation without a slice as the lvalue accepted, bad codegen) - $(LI $(BUGZILLA 3207): gdb: Push D patches upstream) - $(LI $(BUGZILLA 3415): broken JSON output) - $(LI $(BUGZILLA 3522): ICE(cg87.c): variable*array[].) - $(LI $(BUGZILLA 3974): ICE(init.c): Static array initializer with more elements than destination array) - $(LI $(BUGZILLA 3987): [gdb] Invalid DWARF output for function pointers) - $(LI $(BUGZILLA 4036): Segfault with -inline and literal of struct containing union) - $(LI $(BUGZILLA 4037): [gdb] Invalid DWARF output for wchar) - $(LI $(BUGZILLA 4038): [gdb] Invalid DWARF output for function pointers with ref args) - $(LI $(BUGZILLA 4067): [CTFE] Code inside try-catch blocks is silently ignored) - $(LI $(BUGZILLA 4089): crash when creating JSON output for incomplete struct) - $(LI $(BUGZILLA 4093): Segfault(interpret.c): with recursive struct templates) - $(LI $(BUGZILLA 4105): Stack overflow involving alias template parameters and undefined identifier) - ) -) - -$(VERSION 058, Apr 6, 2010, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI $(BUGZILLA 122): DDoc newline behaviour produces suboptimal results) - $(LI $(BUGZILLA 1628): Ddoc produces invalid documentation for --- blocks) - $(LI $(BUGZILLA 2609): No documentation generated for destructor) - $(LI $(BUGZILLA 3808): Assertion Failure : Assertion failure: 'classinfo->structsize == CLASSINFO_SIZE' on line 870 in file 'toobj.c') - $(LI $(BUGZILLA 3842): ICE(expression.c) using pointer in CTFE) - $(LI $(BUGZILLA 3884): Segfault: defining a typedef with an invalid object.d) - $(LI $(BUGZILLA 3885): No multithread support for Windows DLL) - $(LI $(BUGZILLA 3899): CTFE: poor error message for use of uninitialized variable) - $(LI $(BUGZILLA 3900): CTFE: Wrong return value for array.var assignment) - $(LI $(BUGZILLA 3901): PATCH: Nested struct assignment for CTFE) - $(LI $(BUGZILLA 3914): Struct as argument that fits in register has member accessed wrong) - $(LI $(BUGZILLA 3919): ICE(expression.c, 9944): * or / with typedef ireal) - $(LI $(BUGZILLA 3920): Assertion failure: '0' on line 10018 in file 'expression.c') - $(LI $(BUGZILLA 3958): mixin(non-static method) crashes compiler) - $(LI $(BUGZILLA 3972): Regarding module with name different from its file name) - $(LI $(BUGZILLA 4002): dmd.conf and binary path in dmd -v output) - $(LI $(BUGZILLA 4004): DMD 2.042 CTFE regression with functions taking ref parameters) - $(LI $(BUGZILLA 4005): std.c.stdlib.exit in CTFE and more) - $(LI $(BUGZILLA 4011): Incorrect function overloading using mixins) - $(LI $(BUGZILLA 4019): [CTFE] Adding an item to an empty AA) - $(LI $(BUGZILLA 4020): [ICE][CTFE] struct postblit in CTFE) - $(LI $(BUGZILLA 4027): Closures in CTFE generate wrong code) - $(LI $(BUGZILLA 4029): CTFE: cannot invoke delegate returned from function) - ) -) - - -$(VERSION 057, Mar 7, 2010, =================================================, - - $(WHATSNEW - $(LI Warnings no longer halt the parsing/semantic passes, though they still return - an error status and still do not generate output files. They also no longer count - as errors when testing with "compiles" traits.) - $(LI Added $(B -wi) switch for $(BUGZILLA 2567)) - $(LI Associative array contents can now be compared for equality) - $(LI Add simple spell checking.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 2321): spec on inline asm can be misunderstood) - $(LI $(BUGZILLA 2463): No line number in "statement is not reachable" warning) - $(LI $(BUGZILLA 3029): Bug in array value mangling rule) - $(LI $(BUGZILLA 3306): bad function/delegate literal generated into header files) - $(LI $(BUGZILLA 3373): bad codeview debug info for long and ulong) - $(LI Posix only, $(BUGZILLA 3420): [PATCH] Allow string import of files using subdirectories) - $(LI $(BUGZILLA 3450): incorrect result for is (typeof({ ... }())) inside a struct) - $(LI $(BUGZILLA 3500): super behaves differently with -inline) - $(LI $(BUGZILLA 3558): Optimizer bug results in false if condition being taken) - $(LI $(BUGZILLA 3670): Declarator grammar rule is broken) - $(LI $(BUGZILLA 3710): Typo in allMembers description?) - $(LI $(BUGZILLA 3736): corrupted struct returned by function with optimizations (-O)) - $(LI $(BUGZILLA 3737): SEG-V at expression.c:6255 from bad opDispatch) - $(LI $(BUGZILLA 3768): reapeted quotes in ddoc.html) - $(LI $(BUGZILLA 3769): Regression: Segfault(constfold.c) array literals and case statements) - $(LI $(BUGZILLA 3775): Segfault(cast.c): casting no-parameter template function using property syntax) - $(LI $(BUGZILLA 3781): ICE(interpret.c): using no-argument C-style variadic function in CTFE) - $(LI $(BUGZILLA 3792): Regression: "non-constant expression" for a template inside a struct using a struct initializer) - $(LI $(BUGZILLA 3803): compiler segfaults) - $(LI $(BUGZILLA 3840): Jump to: section in the docs should be sorted) - ) -) - -$(VERSION 056, Jan 29, 2010, =================================================, - - $(WHATSNEW - $(LI Clarification: function returns are not lvalues) - $(LI Add $(B -map) command line switch) - $(LI Delegates and function pointers may be used in CTFE) - $(LI Delegate literals and function literals may be used in CTFE) - $(LI Lazy function parameters may now be used in CTFE) - $(LI Slicing of char[] arrays may now be used in CTFE) - ) - $(BUGSFIXED - $(LI $(CPPBUGZILLA 48): Internal error: cgreg 784) - $(LI $(BUGZILLA 1298): CTFE: tuple foreach bugs) - $(LI $(BUGZILLA 1790): CTFE: foreach(Tuple) won't compile if Tuple contains string) - $(LI $(BUGZILLA 2101): CTFE: Please may I use mutable arrays at compile time?) - $(LI Partial fix for $(BUGZILLA 3569), stops the stack overflow) - $(LI $(BUGZILLA 3668): foreach over typedef'd array crashes dmd) - $(LI $(BUGZILLA 3674): forward reference error with multiple overloads with same name) - $(LI $(BUGZILLA 3685): Regression(D1 only): DMD silently exits on valid code) - $(LI $(BUGZILLA 3687): Array operation "slice times scalar" tramples over memory) - $(LI $(BUGZILLA 3719): forward references can cause out-of-memory error) - $(LI $(BUGZILLA 3723): Regression: forward referenced enum) - $(LI $(BUGZILLA 3724): bug in Expression::arraySyntaxCopy (null pointer dereference on struct->union->struct)) - $(LI $(BUGZILLA 3726): Regression: ICE(mangle.c 81): struct forward reference with static this) - $(LI $(BUGZILLA 3740): Regression: class with fwd reference of a nested struct breaks abstract) - ) -) - -$(VERSION 055, Jan 1, 2010, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI $(BUGZILLA 3663): struct forward reference regresssion) - $(LI $(BUGZILLA 3664): struct forward declaration causes enum to conflict with itself) - ) -) - -$(VERSION 054, Dec 30, 2009, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI $(CPPBUGZILLA 45): Internal error: cgcod 1594) - $(LI $(CPPBUGZILLA 46): Constant folding with long doubles) - $(LI $(NG_digitalmars_D 103391): D1 garbage collector + threads + malloc = garbage?) - $(LI $(BUGZILLA 282): Bizarre circular import nested name invisibility issue) - $(LI $(BUGZILLA 390): Cannot forward reference enum nested in struct) - $(LI $(BUGZILLA 400): forward reference error; no propety X for type Y (struct within struct)) - $(LI $(BUGZILLA 1160): enums can not be forward referenced) - $(LI $(BUGZILLA 1564): Forward reference error for enum in circular import) - $(LI $(BUGZILLA 2029): Typesafe variadic functions don't work in CTFE) - $(LI $(BUGZILLA 2816): Sudden-death static assert is not very useful) - $(LI $(BUGZILLA 3455): Some Unicode characters not allowed in identifiers) - $(LI $(BUGZILLA 3575): CTFE: member structs not initialized correctly) - $(LI $(BUGZILLA 3584): DeclDef rule is missing entries) - $(LI $(BUGZILLA 3585): Duplicate clauses in EqualExpression and RelExpression rules) - $(LI $(BUGZILLA 3587): Aggregate rule references undefined Tuple) - $(LI $(BUGZILLA 3588): WithStatement rule references unspecified Symbol) - $(LI $(BUGZILLA 3589): BaseClassList and InterfaceClasses rules are incorrect, missing ',') - $(LI $(BUGZILLA 3590): FunctionParameterList rule is missing) - $(LI $(BUGZILLA 3591): TemplateIdentifier rule is misspelled) - $(LI $(BUGZILLA 3592): ClassTemplateDeclaration and FunctionTemplateDeclaration rules are unreferenced) - $(LI $(BUGZILLA 3593): IntegerExpression rule unspecified) - $(LI $(BUGZILLA 3594): AsmPrimaryExp rule references unspecified rules) - $(LI $(BUGZILLA 3595): Several rules are missing ':' after rule name) - $(LI $(BUGZILLA 3601): Debug and Release builds of DMD produce different object files) - $(LI $(BUGZILLA 3611): Enum forward referencing regression) - $(LI $(BUGZILLA 3612): ExpressionList is undefined) - $(LI $(BUGZILLA 3617): CTFE: wrong code for if(x) where x is int or smaller) - $(LI $(BUGZILLA 3628): can't cast null to int) - $(LI $(BUGZILLA 3633): Optimizer causes access violation) - $(LI $(BUGZILLA 3645): manifest constant (enum) crashes dmd) - ) -) - -$(VERSION 053, Dec 3, 2009, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI $(BUGZILLA 111): appending a dchar to a char[]) - $(LI $(BUGZILLA 370): Compiler stack overflow on recursive typeof in function declaration.) - $(LI $(BUGZILLA 2229): ICE(template.c) instantiating an invalid variadic template with more than one argument) - $(LI $(BUGZILLA 2967): spec does not mention that inline asm is a valid "return" statement) - $(LI $(BUGZILLA 3115): >>> and >>>= generate wrong code) - $(LI $(BUGZILLA 3171): % not implemented correctly for floats) - $(LI $(BUGZILLA 3381): [tdpl] Incorrect assessment of overriding in triangular-shaped hierarchy) - $(LI $(BUGZILLA 3469): ICE(func.c): Regression. Calling non-template function as a template, from another module) - $(LI $(BUGZILLA 3495): Segfault(typinf.c) instantiating D variadic function with too few arguments) - $(LI $(BUGZILLA 3496): ICE(cgelem.c, optimizer bug) cast(void *)(x&1)== null.) - $(LI $(BUGZILLA 3502): Fix for dropped Mac OS X 10.5) - $(LI $(BUGZILLA 3521): Optimized code access popped register) - $(LI $(BUGZILLA 3540): Another DWARF line number fix) - ) -) - -$(VERSION 052, Nov 12, 2009, =================================================, - - $(WHATSNEW - $(LI OSX versions 10.5 and older are no longer supported.) - ) - $(BUGSFIXED - $(LI Works on OSX 10.6 now.) - ) -) - -$(VERSION 051, Nov 5, 2009, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI Problem with complicated array op expressions) - $(LI $(BUGZILLA 195): DDoc generates bad output when example contains "protected" attribute) - $(LI $(BUGZILLA 424): Unexpected OPTLINK Termination at EIP=0044C37B (too many fixups)) - $(LI $(BUGZILLA 874): Bad codegen: wrong value variable in tuple foreach, D1 only) - $(LI $(BUGZILLA 1117): ddoc generates corrupted docs if code examples contain attributes with colons) - $(LI $(BUGZILLA 1812): DDOC - Unicode identifiers are not correctly marked.) - $(LI $(BUGZILLA 2862): ICE(template.c) using type tuple as function argument) - $(LI $(BUGZILLA 3292): ICE(todt.c) when using a named mixin with an initializer as template alias parameter) - $(LI $(BUGZILLA 3397): Unintended function call to static opCall) - $(LI $(BUGZILLA 3401): Compiler crash on invariant + method overload) - $(LI $(BUGZILLA 3422): ICE(cgcod.c) Structs with default initializers bigger than register size cannot be default parameters) - $(LI $(BUGZILLA 3426): ICE(optimize.c): struct literal with cast, as function default parameter.) - $(LI $(BUGZILLA 3432): ICE(e2ir.c): casting template expression) - ) -) - -$(VERSION 050, Oct 14, 2009, =================================================, - - $(WHATSNEW - $(LI Use $(B -X) to generate JSON files.) - ) - $(BUGSFIXED - $(LI Fold in patch from $(BUGZILLA 1170)) - $(LI $(BUGZILLA 923): No constant folding for template value default arguments, D1 only) - $(LI $(BUGZILLA 1534): Can't mix in a case statement.) - $(LI $(BUGZILLA 2423): Erroneous unreachable statement warning) - $(LI $(BUGZILLA 3392): a cast of this to void in tango.core.Thread is not allowed) - ) -) - -$(VERSION 049, Oct 11, 2009, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI $(BUGZILLA 258): Undefined identifier error for circular import) - $(LI $(BUGZILLA 928): nested struct definition in unittest section of a templated class, hangs DMD) - $(LI $(BUGZILLA 1140): ICE(cod1.c) casting last function parameter to 8 byte value) - $(LI $(BUGZILLA 1592): dmd fail to resolve class symbol when i put files in a package) - $(LI $(BUGZILLA 1787): Compiler segfaults on circular references.) - $(LI $(BUGZILLA 1897): ICE(template.c) with tuple delegate) - $(LI $(BUGZILLA 1934): ICE(e2ir.c) using static array as AA key) - $(LI $(BUGZILLA 2229): ICE(template.c) instantiating an invalid variadic template with more than one argument) - $(LI $(BUGZILLA 2687): ICE(statement.c): tuple foreach in an erroneous template.) - $(LI $(BUGZILLA 2773): ICE(go.c) array assignment through a pointer, only with -O.) - $(LI $(BUGZILLA 2829): ICE(expression.c) static array block-initialized in struct literal) - $(LI $(BUGZILLA 2851): Segfault(expression.c) using C-style struct initializer with too few arguments) - $(LI $(BUGZILLA 3006): ICE(e2ir.c, tocsym.c) template module using array operation) - $(LI $(BUGZILLA 3041): Array slices can be compared to their element type: bad codegen or ICE) - $(LI $(BUGZILLA 3101): Stack overflow: declaring aggregate member twice with static if) - $(LI $(BUGZILLA 3174): ICE(mtype.c): Compiler crash or compiler error with auto returns and const / immutable / invarient / pure) - $(LI $(BUGZILLA 3176): Compiler hangs on poorly formed mixin in variadic template) - $(LI $(BUGZILLA 3261): compiler crash with mixin and forward reference) - $(LI $(BUGZILLA 3286): Default parameter prevents to resolve inter-module circular dependency) - $(LI $(BUGZILLA 3301): Undefined identifier error dependent on order of imports when a circular import is involved) - $(LI $(BUGZILLA 3325): ICE(func.c) function literal with post-contract) - $(LI $(BUGZILLA 3343): Crash by "auto main(){}") - $(LI $(BUGZILLA 3344): ICE(e2ir.c) returning an invalid function from main()) - $(LI $(BUGZILLA 3357): ICE(cod1.c) using 'in' with a static char array as AA key) - $(LI $(BUGZILLA 3366): Segfault(declaration.c) variadic template with unmatched constraint) - $(LI $(BUGZILLA 3374): [tdpl] ICE(init.c): Associative array type not inferred) - ) -) - -$(VERSION 048, Oct 5, 2009, =================================================, - - $(WHATSNEW - $(LI Compiler now detects some cases of illegal null dereferencing when compiled with -O) - $(LI $(BUGZILLA 2905): Faster +-*/ involving a floating-pointing literal) - ) - $(BUGSFIXED - $(LI gdb stack trace should work now) - $(LI $(BUGZILLA 302): in/out contract inheritance yet to be implemented) - $(LI $(BUGZILLA 718): ICE(cgcod.c) with int /= cast(creal)) - $(LI $(BUGZILLA 814): lazy argument + variadic arguments = segfault) - $(LI $(BUGZILLA 1168): Passing a .stringof of an expression as a template value parameter results in the string of the type) - $(LI $(BUGZILLA 1571): Segfault(class.c) const on function parameters not carried through to .di file) - $(LI $(BUGZILLA 1731): forward reference of function type alias resets calling convention) - $(LI $(BUGZILLA 2202): Error getting type of non-static member of a class) - $(LI $(BUGZILLA 2469): ICE(cod1.c) arbitrary struct accepted as struct initializer) - $(LI $(BUGZILLA 2697): Cast of float function return to ulong or uint gives bogus value) - $(LI $(BUGZILLA 2702): Struct initialisation silently inserts deadly casts) - $(LI $(BUGZILLA 2839): ICE(cgcs.c) with int /= imaginary) - $(LI $(BUGZILLA 3049): ICE(cod4.c) or segfault: Array operation on void[] array) - $(LI $(BUGZILLA 3059): Nonsensical complex op= should be illegal) - $(LI $(BUGZILLA 3160): ICE(cgcod.c 1511-D1) or bad code-D2 returning string from void main) - $(LI $(BUGZILLA 3304): Segfault using 'is' with a pointer enum.) - $(LI $(BUGZILLA 3305): Segfault(expression.c) with recursive struct template alias expressions) - $(LI $(BUGZILLA 3335): minor warning cleanups) - $(LI $(BUGZILLA 3336): ICE(glue.c) declaring AA with tuple key, only with -g) - $(LI $(BUGZILLA 3353): storage class of a member function is propagated to default arguments) - ) -) - -$(VERSION 047, Sep 2, 2009, =================================================, - - $(WHATSNEW - $(LI $(BUGZILLA 3122): [patch] Adding support for fast and reliable build tools to the frontend) - $(LI Added support for: ---- -a[i].var = e2 ---- - and: ---- -a[] = e ---- - in CTFE. $(I (thanks, Don!))) - $(LI Member functions can now be used in CTFE) - $(LI Operator overloading can now be used in CTFE) - $(LI Nested functions can now be used in CTFE) - $(LI CTFE error messages now explain why the function could not be - interpreted at compile time) - ) - $(BUGSFIXED - $(LI Fixed bug processing spaces in dmd's directory) - $(LI $(BUGZILLA 601): statement.html - Formatting/markup errors in BNF) - $(LI $(BUGZILLA 1461): Local variable as template alias parameter breaks CTFE) - $(LI $(BUGZILLA 1605): break in switch with goto breaks in ctfe) - $(LI $(BUGZILLA 1948): CTFE fails when mutating a struct in an array) - $(LI $(BUGZILLA 1950): CTFE doesn't work correctly for structs passed by ref) - $(LI $(BUGZILLA 2569): static arrays in CTFE functions don't compile) - $(LI $(BUGZILLA 2575): gdb can not show code) - $(LI $(BUGZILLA 2604): DW_TAG_module and GDB) - $(LI $(BUGZILLA 2940): null is null cannot be evaluated at compile time) - $(LI $(BUGZILLA 2960): CTFE rejects static array to dynamic array casts) - $(LI $(BUGZILLA 3039): -vtls compiler flag not listed in man file) - $(LI $(BUGZILLA 3165): What kind of integer division does D use?) - $(LI $(BUGZILLA 3166): "positive" -> "non-negative" in modulo operator description) - $(LI $(BUGZILLA 3168): Declaring structs as incomplete types no longer works) - $(LI $(BUGZILLA 3170): Forward reference of nested class fails if outer class is not plain) - $(LI $(BUGZILLA 3183): Spec of align attribute needs work) - $(LI $(BUGZILLA 3186): corrections for http://www.digitalmars.com/d/2.0/dmd-osx.html) - $(LI $(BUGZILLA 3192): asm in a anonymous delegate crash the compiler) - $(LI $(BUGZILLA 3196): Segfault(mtype.c) after almost any error involving a delegate literal) - $(LI $(BUGZILLA 3205): CTFE: $ cannot be used in lvalues) - $(LI $(BUGZILLA 3246): ICE(init.c) using indexed array initializer on local array) - $(LI $(BUGZILLA 3264): -O causes wrong "used before set" error when using enum.) - ) -) - -$(VERSION 046, Jul 6, 2009, =================================================, - - $(WHATSNEW - $(LI $(BUGZILLA 3080): dmd should output compilation errors to stderr, not stdout) - ) - $(BUGSFIXED - $(LI Fix dmd crash on multicore Windows.) - $(LI $(BUGZILLA 106): template - mixin sequence) - $(LI $(BUGZILLA 810): Cannot forward reference template) - $(LI $(BUGZILLA 852): ICE(toir.c) using local class in non-static nested function in nested static function) - $(LI $(BUGZILLA 854): TypeTuple in anonymous delegate causes ice in glue.c) - $(LI $(BUGZILLA 1054): regression: circular aliases cause compiler stack overflow) - $(LI $(BUGZILLA 1343): Various errors with static initialization of structs and arrays) - $(LI $(BUGZILLA 1358): ICE(root.c) on Unicode codepoints greater than 0x7FFFFFFF) - $(LI $(BUGZILLA 1459): ICE(cgcs.c) on attempt to set value of non-lvalue return struct) - $(LI $(BUGZILLA 1524): ICE(constfold.c) on using "is" with strings in CTFE) - $(LI $(BUGZILLA 1984): Assertion failure: 'e1->type' on line 1198 in file 'constfold.c') - $(LI $(BUGZILLA 2323): ICE(cgcs.c): taking address of a method of a temporary struct) - $(LI $(BUGZILLA 2429): std.stream.File incorrect flag parsing and sharing mode) - $(LI $(BUGZILLA 2432): complex alias -> mtype.c:125: virtual Type* Type::syntaxCopy(): Assertion `0' failed.) - $(LI $(BUGZILLA 2603): ICE(cgcs.c) on subtracting string literals) - $(LI $(BUGZILLA 2843): ICE(constfold.c) with is-expression with invalid dot-expression in is-expression involving typeid) - $(LI $(BUGZILLA 2884): ICE: Assert: 'template.c', line 3773, 'global.errors') - $(LI $(BUGZILLA 2888): [PATCH] speedup for float * 2.0) - $(LI $(BUGZILLA 2915): [Patch]: Optimize -a*-b into a*b) - $(LI $(BUGZILLA 2923): -O generates bad code for ?:) - $(LI $(BUGZILLA 2932): bad e_ehsize (36 != 52)) - $(LI $(BUGZILLA 2952): Segfault on exit when using array ops with arrays of doubles larger than 8 elements) - $(LI $(BUGZILLA 3003): Need to implicitly add () on member template function calls) - $(LI $(BUGZILLA 3014): ICE(template.c) instantiating template with tuple) - $(LI $(BUGZILLA 3016): Errors in the documentation of std.math.acos) - $(LI $(BUGZILLA 3026): Segfault with incomplete static array initializer) - $(LI $(BUGZILLA 3044): Segfault(template.c) instantiating struct tuple constructor with zero arguments.) - $(LI $(BUGZILLA 3078): NaN reported as equal to zero) - $(LI $(BUGZILLA 3114): optlink failing on multicore machines) - $(LI $(BUGZILLA 3117): dmd crash by *1) - $(LI $(BUGZILLA 3128): Internal error: ..\ztc\cod4.c 2737) - $(LI $(BUGZILLA 3130): Crashed with triple stars) - ) -) - -$(VERSION 045, May 11, 2009, =================================================, - - $(WHATSNEW - $(LI Folded in compiler/library changes by Unknown W. Brackets - to support Solaris.) - $(LI Migrate Posix uses of std.c.linux.linux to std.c.posix.posix) - $(LI added .typeinfo to ClassInfo $(BUGZILLA 2836): Navigate from ClassInfo to TypeInfo) - ) - $(BUGSFIXED - $(LI Fix instruction scheduler bug on Linux) - $(LI $(BUGZILLA 642): error: mixin "static this" into where it cannot be) - $(LI $(BUGZILLA 713): circular const definitions with module operator "." cause the compiler to segfault) - $(LI $(BUGZILLA 752): Assertion failure: 'e->type->ty != Ttuple' on line 4518 in file 'mtype.c') - $(LI $(BUGZILLA 858): Forward reference to struct inside class crashes the compiler) - $(LI $(BUGZILLA 884): Segfault in recursive template) - $(LI $(BUGZILLA 934): Segfault taking mangleof a forward reference in a template.) - $(LI $(BUGZILLA 1011): illegal import declaration causes compile time segfault) - $(LI $(BUGZILLA 1054): regression: circular aliases cause segfaults) - $(LI $(BUGZILLA 1061): "asm inc [;" segfaults compiler.) - $(LI $(BUGZILLA 1195): regression: aliasing an enum member causes compile time segfaults) - $(LI $(BUGZILLA 1305): Compiler hangs with templated opCmp returning templated class) - $(LI $(BUGZILLA 1385): Stack Overflow with huge array literal.) - $(LI $(BUGZILLA 1428): Segfault on template specialization with delegates and tuples) - $(LI $(BUGZILLA 1586): DMD and GDC segfaults on incomplete code segment.) - $(LI $(BUGZILLA 1791): Segmentation fault with anon class in anon class and non-constant variable init) - $(LI $(BUGZILLA 1916): segfault on invalid string concat) - $(LI $(BUGZILLA 1946): Compiler crashes on attempt to implicit cast const typedef to non-const.) - $(LI $(BUGZILLA 2048): DMD crash on CTFE that involves assigning to member variables of void-initialized struct) - $(LI $(BUGZILLA 2061): wrong vtable call with multiple interface inheritance) - $(LI $(BUGZILLA 2215): Forward reference enum with base type within a struct causes Segmentation Fault in the compiler) - $(LI $(BUGZILLA 2309): Crash on a template mixing in a variadic template with an undefined template identifier) - $(LI $(BUGZILLA 2346): ICE when comparing typedef'd class) - $(LI $(BUGZILLA 2821): struct alignment inconsistent with C for { int, long }) - $(LI $(BUGZILLA 2920): recursive templates blow compiler stack) - ) -) - -$(VERSION 044, Apr 9, 2009, =================================================, - - $(WHATSNEW - $(LI Added std.c.posix.* to Phobos.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 675): %a format has an out-by-1 bug for denormals.) - $(LI $(BUGZILLA 2064): Segfault with mixin(for/foreach) with empty loop body) - $(LI $(BUGZILLA 2199): Segfault using array operation in function call) - $(LI $(BUGZILLA 2203): typeof(class.template.foo) crashes compiler) - ) -) - -$(VERSION 043, Apr 6, 2009, =================================================, - - $(WHATSNEW - $(LI Added FreeBSD 7.1 support.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 2796): Dependency on libstdc++-v3) - ) -) - -$(VERSION 042, Mar 31, 2009, =================================================, - - $(WHATSNEW - $(LI Added response files for Linux and OSX) - $(LI On Windows, if there are multiple source files on the command - line they are now read with a background thread. This may speed up - compilation.) - $(LI Folded in patches for LDC compatibility from Tomas Lindquist Olsen) - $(LI The $(B Posix) version identifier can now be set even though - it is reserved and predefined, because many build systems and makefiles - try to set it.) - ) - $(BUGSFIXED - $(LI std.math.hypot is wrong for subnormal arguments) - $(LI Fix bug where / wasn't recognized as a path separator on Windows.) - $(LI $(BUGZILLA 920): Fix one more out of date reference to 'auto' rather than 'scope') - $(LI $(BUGZILLA 1923): GC optimization for contiguous pointers to the same page) - $(LI $(BUGZILLA 2319): "Win32 Exception" not very useful) - $(LI $(BUGZILLA 2570): Patch for some mistakes in Ddoc comments) - $(LI $(BUGZILLA 2591): custom allocator new argument should be size_t instead of uint) - $(LI $(BUGZILLA 2689): seek behaves incorrectly on MAC OSX) - $(LI $(BUGZILLA 2692): alignment of double on x86 linux is incorrect) - $(LI $(BUGZILLA 2705): Response file size cannot exceed 64kb) - $(LI $(BUGZILLA 2711): -H produces bad headers files if function defintion is templated and have auto return value) - $(LI $(BUGZILLA 2731): Errors in associative array example) - $(LI $(BUGZILLA 2743): dumpobj gives "buss error" on Tiger) - $(LI $(BUGZILLA 2744): wrong init tocbuffer of forstatement) - $(LI $(BUGZILLA 2745): missing token tochars in lexer.c) - $(LI $(BUGZILLA 2747): improper toCBuffer of funcexp) - $(LI $(BUGZILLA 2750): Optimize slice copy with size known at compile time) - $(LI $(BUGZILLA 2751): incorrect scope storage class vardeclaration tocbuffer) - $(LI $(BUGZILLA 2767): DMD incorrectly mangles NTFS stream names) - $(LI $(BUGZILLA 2772): lib can't open response file) - ) -) - -$(VERSION 041, Mar 3, 2009, =================================================, - - $(WHATSNEW - $(LI Added buildable dmd source.) - $(LI Improved accuracy of exp, expm1, exp2, sinh, cosh, tanh on Mac OSX, - and tripled speed on all platforms.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1629): Link error: Previous Definition Different: blablah__initZ) - $(LI $(BUGZILLA 1662): Falls back to libphobos if -debuglib isn't used when -g is) - $(LI $(BUGZILLA 1681): cast(real) ulong.max == 0) - $(LI $(BUGZILLA 2416): Slice of typedef'ed array should preserve the typedef'ed type) - $(LI $(BUGZILLA 2582): Significantly Increased Compile Times For DWT) - $(LI $(BUGZILLA 2670): std.file.read() should read files of 0 length) - $(LI $(BUGZILLA 2673): Static constructors sometimes do not run when compiling with -lib) - $(LI $(BUGZILLA 2678): for loops are already assumed to terminate) - $(LI $(BUGZILLA 2679): Spurious "warning - " messages and erratic behaviour with is(typeof({void function}()))) - $(LI $(BUGZILLA 2690): DMD aborts with MALLOC_CHECK_ set) - ) -) - -$(VERSION 040, Feb 11, 2009, =================================================, - - $(WHATSNEW - $(LI Added Mac OSX support.) - $(LI Separated bin and lib directories into windows, linux, - and osx.) - $(LI No longer need to download dmc to use the windows version.) - $(LI Use version(OSX) for Mac OSX. Although version(darwin) is - also supported for the time being, it is deprecated.) - ) - $(BUGSFIXED - ) -) - -$(VERSION 039, Jan 14, 2009, =================================================, - - $(WHATSNEW - $(LI Improved speed of long division.) - $(LI Added predefined $(LINK2 version.html#PredefinedVersions, version) - $(B D_Ddoc) which is predefined when $(B -D) switch is thrown.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 2517): DDoc omits abstract on classes) - $(LI $(BUGZILLA 2518): scope(success) not execuate and RAII variable destructor is not called) - $(LI $(BUGZILLA 2519): Segfault when >> used in an invalid slice) - $(LI $(BUGZILLA 2527): Alias Template Params Are Always Same Type As First Instantiation (according to typeof(x).stringof)) - $(LI $(BUGZILLA 2531): DDoc not generated correctly for struct methods inside static if) - $(LI $(BUGZILLA 2537): compiler crashes on this code:) - $(LI $(BUGZILLA 2542): array casts behave differently at compile and runtime) - ) -) - -$(VERSION 038, Dec 11, 2008, =================================================, - - $(WHATSNEW - $(LI Changed IUnknown to use the extern(System) interface rather - that extern(Windows).) - $(LI Added Partial IFTI $(BUGZILLA 493)) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1518): Crash using 'scope', 'with' and undefined 'RegExp') - $(LI $(BUGZILLA 1685): Array index is evaluated twice) - $(LI $(BUGZILLA 1963): -H creates broken headers) - $(LI $(BUGZILLA 2041): Spec implies relationship between interfaces and COM objects) - $(LI $(BUGZILLA 2105): added patch) - $(LI $(BUGZILLA 2468): result type of AndAndExp and OrOrExp deduced incorrectly) - $(LI $(BUGZILLA 2489): import in struct causes assertion failure) - $(LI $(BUGZILLA 2490): extern(C++) can not handle structs as return types) - $(LI $(BUGZILLA 2492): ICE building on Linux with -lib option) - $(LI $(BUGZILLA 2499): Template alias default value cannot be template instantiation) - $(LI $(BUGZILLA 2500): template struct methods are left unresolved if imported from multiple modules) - $(LI $(BUGZILLA 2501): member function marked as final override ignores override requirements) - $(LI Incorporated some of the patches from $(BUGZILLA 1752)) - ) -) - -$(VERSION 037, Nov 25, 2008, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI $(BUGZILLA 313): Fully qualified names bypass private imports) - $(LI $(BUGZILLA 341): Undocumented function void print() in object.d) - $(LI $(BUGZILLA 929): Resizing array of associative arrays (uint[char[]][]) causes infinite loop / hang) - $(LI $(BUGZILLA 1372): Compiler accepts pragma(msg,)) - $(LI $(BUGZILLA 1610): Enum.stringof is int, not the name of the enum) - $(LI $(BUGZILLA 1663): pragma(lib, "") don't work on linux) - $(LI $(BUGZILLA 1797): Documentation comments - ///) - $(LI $(BUGZILLA 2326): Methods within final class are not considered final when optimizing) - $(LI $(BUGZILLA 2429): std.stream.File incorrect flag parsing and sharing mode) - $(LI $(BUGZILLA 2431): Internal error: ../ztc/cgcod.c 1031 when using -O) - $(LI $(BUGZILLA 2470): Cannot build libraries from other libraries) - $(LI unittest functions now always use D linkage) - ) -) - -$(VERSION 036, Oct 20, 2008, =================================================, - - $(WHATSNEW - $(LI Improved performance of AAs by rebalancing trees when rehashing.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1229): Linker fills disk) - $(LI $(BUGZILLA 2340): Template properties don't work) - $(LI $(BUGZILLA 2365): compilation error: static const array in struct) - $(LI $(BUGZILLA 2368): Calling a function with an address of another function, then calling a returned object is rejected) - $(LI $(BUGZILLA 2373): freebsd select does not accept values > 999,999) - $(LI $(BUGZILLA 2376): CTFE fails on array literal of array literals of chars) - $(LI $(BUGZILLA 2380): static struct initializer accepted as non static initializer is not documented) - $(LI $(BUGZILLA 2383): default arguments can implicitly access private global variables that are not visible at call site) - $(LI $(BUGZILLA 2385): spec says all structs are returned via hidden pointer on linux, but it uses registers) - $(LI $(BUGZILLA 2390): Missing warning on conversion from int to char) - ) -) - -$(VERSION 035, Sep 2, 2008, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1627): ICE with a method called _ctor) - $(LI $(BUGZILLA 1633): Nonsensical "C style cast illegal" message with !is) - $(LI $(BUGZILLA 1637): regression: new unittest failure in std/math2.d, odd cosh() behavior) - $(LI $(BUGZILLA 1763): EndianStream doesn't handle ubyte/byte read/writes. Simple fix.) - $(LI $(BUGZILLA 1771): dmd fails to execute on linux) - $(LI $(BUGZILLA 1773): excessively long integer literal) - $(LI $(BUGZILLA 1785): Mixing in an incorrect array literal causes infinite loop.) - $(LI $(BUGZILLA 2176): Assertion failure: 'sz == es2->sz' on line 1339 in file 'constfold.c' (concatenating strings of different types)) - $(LI $(BUGZILLA 2183): Bad formatting in std.c.stdlib) - $(LI $(BUGZILLA 2232): DMD generates invalid code when an object file is compiled -inline) - $(LI $(BUGZILLA 2241): DMD abort) - $(LI $(BUGZILLA 2243): const bool = is(function literal), badly miscast) - $(LI $(BUGZILLA 2262): -inline breaks -lib library) - $(LI $(BUGZILLA 2286): movmskpd compiled incorrectly) - $(LI $(BUGZILLA 2308): CTFE crash on foreach over nonexistent variable) - $(LI $(BUGZILLA 2311): Static destructors in templates are never run) - $(LI $(BUGZILLA 2314): Crash on anonymous class variable instantiation) - $(LI $(BUGZILLA 2317): asm offsetof generates: Internal error: ../ztc/cod3.c 2651) - ) -) - -$(VERSION 034, Aug 7, 2008, =================================================, - - $(WHATSNEW - $(LI Now supports $(LINK2 arrays.html#array-operations, array operations).) - ) - $(BUGSFIXED - $(LI Added hash to generated module names when building libs to reduce collisions) - $(LI $(BUGZILLA 1622): parameters to TypeInfo_Struct.compare seem to be switched around.) - $(LI $(BUGZILLA 2216): bad code generation for static arrays of zero length static arrays) - $(LI $(BUGZILLA 2223): Typo in error message) - $(LI $(BUGZILLA 2242): linux system calls are canceled by GC) - $(LI $(BUGZILLA 2247): bad header file generated for if (auto o = ...) {}) - $(LI $(BUGZILLA 2248): .di should be a supported file extension) - $(LI $(BUGZILLA 2250): Update of user32.lib and kernel32.lib) - $(LI $(BUGZILLA 2254): Size of executable almost triples) - $(LI $(BUGZILLA 2258): Docs -> Inline Assembler -> Operand Types -> qword missing) - $(LI $(BUGZILLA 2259): Assertion failure: '0' on line 122 in file 'statement.c') - $(LI $(BUGZILLA 2269): D BUG: cosine of complex) - $(LI $(BUGZILLA 2272): synchronized attribute documentation) - $(LI $(BUGZILLA 2273): Whitespace is not inserted after commas) - ) -) - -$(VERSION 033, Jul 11, 2008, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI $(BUGZILLA 870): contradictory error messages for templates) - $(LI $(BUGZILLA 2207): overload resolution fails with deprecation) - $(LI $(BUGZILLA 2208): Deprecated function declarations cannot use deprecated types) - $(LI $(BUGZILLA 2209): Typo in doc for offsetof) - ) -) - -$(VERSION 032, Jul 9, 2008, =================================================, - - $(WHATSNEW - $(LI Added $(B .__vptr) and $(B .__monitor) properties for class objects - for use in the internal runtime library. - ) - ) - $(BUGSFIXED - $(LI $(NG_digitalmars_D_announce 12322): mixin regression) - $(LI $(BUGZILLA 203): std.format.doFormat() pads width incorrectly on Unicode strings) - $(LI $(BUGZILLA 211): Linking error with alias mixin params and anonymous methods) - $(LI $(BUGZILLA 224): Incorrect warning "no return at end of function") - $(LI $(BUGZILLA 252): -w and switch returns = bogus "no return at end of function" warning) - $(LI $(BUGZILLA 253): Invalid <dl> tag generated by Ddoc) - $(LI $(BUGZILLA 294): DDoc: Function templates get double and incomplete documentation) - $(LI $(BUGZILLA 398): No way to abort compilation in a doubly recursive mixin) - $(LI $(BUGZILLA 423): dmd ignores empty commandline arguments) - $(LI $(BUGZILLA 515): Spec incorrect in where .offsetof can be applied) - $(LI $(BUGZILLA 520): Invariants allowed to call public functions) - $(LI $(BUGZILLA 542): Function parameter of a deprecated type (other than a class) is not caught) - $(LI $(BUGZILLA 543): Function return of a deprecated type is not caught) - $(LI $(BUGZILLA 544): Variable declared of a deprecated type (other than a class) is not caught) - $(LI $(BUGZILLA 545): Attempt to access a static built-in property of a deprecated struct, union, enum or typedef is not caught) - $(LI $(BUGZILLA 547): Accessing a deprecated member variable through an explicit object reference is not caught) - $(LI $(BUGZILLA 548): Accessing a value of a deprecated enum is not caught) - $(LI $(BUGZILLA 566): Adding non-static members and functions to classes using a template doesn't error) - $(LI $(BUGZILLA 570): Bogus recursive mixin error) - $(LI $(BUGZILLA 571): class instance member template returns strange value) - $(LI $(BUGZILLA 572): parse error when using template instantiation with typeof) - $(LI $(BUGZILLA 581): Error message w/o line number in dot-instantiated template) - $(LI $(BUGZILLA 617): IFTI doesn't use normal promotion rules for non-template parameters) - $(LI $(BUGZILLA 951): Missing line number: no constructor provided for a class derived from a class with no default constructor) - $(LI $(BUGZILLA 1097): Missing line number: casting array to array of different element size) - $(LI $(BUGZILLA 1158): Missing line number: invalid mixin outside function scope) - $(LI $(BUGZILLA 1176): Error missing file and line number) - $(LI $(BUGZILLA 1187): Segfault with syntax error in two-level mixin.) - $(LI $(BUGZILLA 1194): fcmov* emmits incorrect code) - $(LI $(BUGZILLA 1207): Documentation on destructors is confusing) - $(LI $(BUGZILLA 1341): typeof(int) should probably be legal) - $(LI $(BUGZILLA 1601): shr and shl error message is missing line numbers) - $(LI $(BUGZILLA 1612): No file/line number for using an undefined label in inline assembly) - $(LI $(BUGZILLA 1907): Error message without a line number) - $(LI $(BUGZILLA 1912): Error without line number (Tuple, invalid value argument)) - $(LI $(BUGZILLA 1936): Error with no line number (array dimension overflow)) - $(LI $(BUGZILLA 2161): Modify compiler to pass array TypeInfo to _adEq and _adCmp instead of element TypeInfo) - $(LI $(BUGZILLA 2166): More stuff that doesn't compile in Phobos) - $(LI $(BUGZILLA 2178): 3 errors without line number: typeof) - ) -) - -$(VERSION 031, June 18, 2008, =================================================, - - $(WHATSNEW - $(LI Added $(LINK2 version.html#PredefinedVersions, version identifier - $(B D_PIC)) when $(B -fPIC) switch is used.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1383): Implicit Function Instantiation with typesafe-variadic of delegates doesn't work) - $(LI $(BUGZILLA 1559): version statement makes code outside of it disappear) - $(LI $(BUGZILLA 1675): "Identifier too long" error with OMF object files) - $(LI $(BUGZILLA 1963): -H creates broken headers) - $(LI $(BUGZILLA 2111): Protection incorrectly resolved when accessing super class' tupleof) - $(LI $(BUGZILLA 2118): Inconsistent use of string vs invariant(char[]) in doc) - $(LI $(BUGZILLA 2123): Anonymous class crashes) - $(LI $(BUGZILLA 2132): CTFE: can't evaluate ~= at compile time, D2 only.) - $(LI $(BUGZILLA 2136): typeof(super(...)) counted as a constructor call) - $(LI $(BUGZILLA 2140): static if as final statement with no code causes containing code to be skipped) - $(LI $(BUGZILLA 2143): Mixed-in identifier is not recognized by static if) - $(LI $(BUGZILLA 2144): 'is' is defined to be the same as '==' for non-class and non-array types, but does not call opEquals) - $(LI $(BUGZILLA 2146): Multiple execution of 'static this' defined in template) - $(LI $(BUGZILLA 2149): Auto variables loose the keyword "auto" in di files generated with -H option.) - ) -) - -$(VERSION 030, May 16, 2008, =================================================, - - $(WHATSNEW - $(LI Added $(B -lib) switch to generate library files.) - $(LI Added $(B -man) switch to browse manual.) - $(LI When generating an executable file, only one object file - is now generated containing all the modules that were compiled, rather - than one object file per module.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 2031): Documentation: template value parameters) - $(LI $(BUGZILLA 2032): Documentation for creating a class on the stack is unintuitive) - $(LI $(BUGZILLA 2033): -g + circular refs => dmd hangs) - $(LI $(BUGZILLA 2039): -ignore switch is missing from compiler docs) - $(LI $(BUGZILLA 2044): -g hangs DMD) - $(LI $(BUGZILLA 2055): (ICE) Compiler crash on struct initializer with too many elements) - $(LI $(BUGZILLA 2058): Describe hidden value passed to class member functions) - $(LI $(BUGZILLA 2067): call from anonymous class makes access violation.) - $(LI $(BUGZILLA 2071): spec doesn't mention pointer arithmetic with two pointer operands) - $(LI $(BUGZILLA 2075): Spec does not specify how array literals are stored.) - $(LI $(BUGZILLA 2084): operator ?: does not compute the tightest type) - $(LI $(BUGZILLA 2086): Describe relationship between string and char[] more explicitly) - $(LI $(BUGZILLA 2089): Issues with CTFE and tuple indexes) - $(LI $(BUGZILLA 2090): Cannot alias a tuple member which is a template instance) - ) -) - -$(VERSION 029, Apr 23, 2008, =================================================, - - $(WHATSNEW - $(LI Added $(B -ignore) switch to ignore unsupported pragmas.) - $(LI Unsupported pragmas now printed out with $(B -v) switch.) - $(LI Incorporated Benjamin Shropshire's doc changes) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1712): vtbl[0] for interface not set to corresponding Interface*) - $(LI $(BUGZILLA 1741): crash on associative array with static array as index type) - $(LI $(BUGZILLA 1905): foreach docs inconsistency) - $(LI $(BUGZILLA 1906): foreach cannot use index with large arrays) - $(LI $(BUGZILLA 1908): fix closure14.d) - $(LI $(BUGZILLA 1935): The std.recls samples in the DMD .zip are obsolete.) - $(LI $(BUGZILLA 1967): getDirName does not seem to use altsep on windows) - $(LI $(BUGZILLA 1978): Wrong vtable call) - $(LI $(BUGZILLA 1991): Dmd hangs) - $(LI $(BUGZILLA 2019): Appending a one-element array literal doesn't work) - ) -) - -$(VERSION 028, Mar 6, 2008, =================================================, - -$(WHATSNEW - $(LI Added compile time error for comparing class types against $(CODE null).) -) - -$(BUGSFIXED - $(LI Fixed dwarf bug with DT_AT_upper_bound) - $(LI $(BUGZILLA 756): IFTI for tuples only works if tuple parameter is last) - $(LI $(BUGZILLA 1454): IFTI cant deduce parameter if alias argument used) - $(LI $(BUGZILLA 1661): Not possible to specialize on template with integer parameter) - $(LI $(BUGZILLA 1809): template.c:2600) - $(LI $(BUGZILLA 1810): MmFile anonymous mapping does not work under win32) - $(LI $(BUGZILLA 1819): spurious warning about missing return statement after synchronized) - $(LI $(BUGZILLA 1828): Several Thread Issues) - $(LI $(BUGZILLA 1833): std.c.windows.windows should use enums for constants, or be more selective about use of extern(Windows)) - $(LI $(BUGZILLA 1836): Inline assembler can't use enum values as parameters.) - $(LI $(BUGZILLA 1837): Make dmd stop flooding the console: prints content of passed parameter file) - $(LI $(BUGZILLA 1843): Bogus unreachable statement on forward referenced struct, lacks line number) - $(LI $(BUGZILLA 1850): The compiler accepts lower case asm registers.) - $(LI $(BUGZILLA 1852): you get opCall missing when cast to a struct(diagnostic)) - $(LI $(BUGZILLA 1853): opCmp documentation really needs some examples) - $(LI $(BUGZILLA 1857): Runtime segfault while profileing - jump to invalid code address) - $(LI $(BUGZILLA 1862): asm: [ESI+1*EAX] should be a legal addr mode) - $(LI $(BUGZILLA 1864): Variable incorrectly declared final in final class template) - $(LI $(BUGZILLA 1865): Escape sequences are flawed.) - $(LI $(BUGZILLA 1877): Errors in the documentation of std.math.atan2) - $(LI $(BUGZILLA 1879): Compiler segfaults on 'scope' and 'static if') - $(LI $(BUGZILLA 1882): Internal error: ..\ztc\cod1.c 2529) -) -) - - -$(VERSION 027, Feb 18, 2008, =================================================, - -$(WHATSNEW - $(LI Re-enabled auto interfaces.) -) - -$(BUGSFIXED - $(LI Fixed display of ddoc template parameters that were aliased) - $(LI $(BUGZILLA 1072): CTFE: crash on for loop with blank increment) - $(LI $(BUGZILLA 1435): DDoc: Don't apply DDOC_PSYMBOL everywhere) - $(LI $(BUGZILLA 1825): local instantiation and function nesting) - $(LI $(BUGZILLA 1837): Make dmd stop flooding the console: prints content of passed parameter file) - $(LI $(BUGZILLA 1842): Useless linker command line output during compilation on Linux) -) -) - -$(VERSION 026, Jan 20, 2008, =================================================, - -$(WHATSNEW - $(LI $(CODE WinMain) and $(CODE DllMain) can now be in template mixins.) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 1697): Internal error: ..\ztc\cgcod.c 2322 with -O) - $(LI $(BUGZILLA 1707): '==' in TemplateParameterList in IsExpression causes segfault) - $(LI $(BUGZILLA 1711): typeof with delegate literal not allowed as template parameter) - $(LI $(BUGZILLA 1718): obscure exit with error code 5) - $(LI $(BUGZILLA 1719): Compiler crash or unstable code generation with scoped interface instances) - $(LI $(BUGZILLA 1724): Internal error: toir.c 177) - $(LI $(BUGZILLA 1725): std.stream.BufferedFile.create should use FileMode.OutNew) - $(LI $(BUGZILLA 1767): rejects-valid, diagnostic) - $(LI $(BUGZILLA 1769): Typo on the page about exceptions) - $(LI $(BUGZILLA 1773): excessively long integer literal) - $(LI $(BUGZILLA 1779): Compiler crash when deducing more than 2 type args) - $(LI $(BUGZILLA 1783): DMD 1.025 asserts on code with struct, template, and alias) - $(LI $(BUGZILLA 1788): dmd segfaults without info) -) -) - - -$(VERSION 025, Jan 1, 2008, =================================================, - -$(BUGSFIXED - $(LI $(BUGZILLA 1111): enum value referred to by another value of same enum is considered as enum's base type, not enum type) - $(LI $(BUGZILLA 1720): std.math.NotImplemented missing a space in message) - $(LI $(BUGZILLA 1738): Error on struct without line number) - $(LI $(BUGZILLA 1742): CTFE fails on some template functions) - $(LI $(BUGZILLA 1743): interpret.c:1421 assertion failure on CTFE code) - $(LI $(BUGZILLA 1744): CTFE: crash on assigning void-returning function to variable) - $(LI $(BUGZILLA 1749): std.socket not thread-safe due to strerror) - $(LI $(BUGZILLA 1753): String corruption in recursive CTFE functions) -) -) - - -$(VERSION 024, Nov 27, 2007, =================================================, - -$(WHATSNEW - $(LI Changed the way coverage analysis is done so it is independent - of order dependencies among modules.) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 70): valgrind: Conditional jump or move depends on uninitialised value(s) in elf_findstr) - $(LI $(BUGZILLA 71): valgrind: Invalid read of size 4 in elf_renumbersyms) - $(LI $(BUGZILLA 204): Error message on attempting to instantiate an abstract class needs to be improved) - $(LI $(BUGZILLA 1508): dmd/linux template symbol issues) - $(LI $(BUGZILLA 1656): illegal declaration accepted) - $(LI $(BUGZILLA 1664): (1.23).stringof generates bad code) - $(LI $(BUGZILLA 1665): Internal error: ..\ztc\cod2.c 411) -) -) - - -$(VERSION 023, Oct 31, 2007, =================================================, - -$(WHATSNEW - $(LI Data items in static data segment >= 16 bytes in size - are now paragraph aligned.) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 318): wait does not release thread resources on Linux) - $(LI $(BUGZILLA 322): Spawning threads which allocate and free memory leads to pause error on collect) - $(LI $(BUGZILLA 645): Race condition in std.thread.Thread.pauseAll) - $(LI $(BUGZILLA 689): Clean up the spec printfs!) - $(LI $(BUGZILLA 697): No const folding on asm db,dw, etc) - $(LI $(BUGZILLA 706): incorrect type deduction for array literals in functions) - $(LI $(BUGZILLA 708): inline assembler: "CVTPS2PI mm, xmm/m128" fails to compile) - $(LI $(BUGZILLA 709): inline assembler: "CVTPD2PI mm, xmm/m128" fails to compile) - $(LI $(BUGZILLA 718): Internal error: ../ztc/cgcod.c 562) - $(LI $(BUGZILLA 723): bad mixin of class definitions at function level: func.c:535: virtual void FuncDeclaration::semantic3(Scope*): Assertion `0' failed) - $(LI $(BUGZILLA 725): expression.c:6516: virtual Expression* MinAssignExp::semantic(Scope*): Assertion `e2->type->isfloating()' failed.) - $(LI $(BUGZILLA 726): incorrect error line for "override" mixin) - $(LI $(BUGZILLA 729): scope(...) statement in SwitchBody causes compiler to segfault) - $(LI $(BUGZILLA 733): std.conv.toFloat does not catch errors) - $(LI $(BUGZILLA 1258): Garbage collector loses memory upon array concatenation) - $(LI $(BUGZILLA 1478): Avoid libc network api threadsafety issues) - $(LI $(BUGZILLA 1480): std.stream throws the new override warning all over the place) - $(LI $(BUGZILLA 1483): Errors in threads not directed to stderr) - $(LI $(BUGZILLA 1491): Suppress SIGPIPE when sending to a dead socket) - $(LI $(BUGZILLA 1557): std.zlib allocates void[]s instead of ubyte[]s, causing leaks.) - $(LI $(BUGZILLA 1562): Deduction of template alias parameter fails) - $(LI $(BUGZILLA 1575): Cannot do assignment of tuples) - $(LI $(BUGZILLA 1593): ICE compiler crash empty return statement in function) - $(LI $(BUGZILLA 1613): DMD hangs on syntax error) - $(LI $(BUGZILLA 1618): Typo in std\system.d) -) -) - -$(VERSION 022, Oct 1, 2007, =================================================, - -$(BUGSFIXED - $(LI Fix std.boxer boxing of Object's (unit test failure)) - $(LI Fix std.demangle to not show hidden parameters (this and delegate context pointers)) - $(LI $(BUGZILLA 217): typeof not working properly in internal/object.d) - $(LI $(BUGZILLA 218): Clean up old code for packed bit array support) - $(LI $(BUGZILLA 223): Error message for unset constants doesn't specify error location) - $(LI $(BUGZILLA 278): dmd.conf search path doesn't work) - $(LI $(BUGZILLA 479): can't compare arrayliteral statically with string) - $(LI $(BUGZILLA 549): A class derived from a deprecated class is not caught) - $(LI $(BUGZILLA 550): Shifting by more bits than size of quantity is allowed) - $(LI $(BUGZILLA 551): Modulo operator works with imaginary and complex operands) - $(LI $(BUGZILLA 556): is (Type Identifier : TypeSpecialization) doesn't work as it should) - $(LI $(BUGZILLA 668): Use of *.di files breaks the order of static module construction) - $(LI $(BUGZILLA 1125): Segfault using tuple in asm code, when size not specified) - $(LI $(BUGZILLA 1437): dmd crash: "Internal error: ..\ztc\cod4.c 357") - $(LI $(BUGZILLA 1474): regression: const struct with an initializer not recognized as a valid alias template param) - $(LI $(BUGZILLA 1484): Forward reference of enum member crashes DMD) - $(LI $(BUGZILLA 1488): Bad code generation when using tuple from asm) - $(LI $(BUGZILLA 1510): ICE: Assertion failure: 'ad' on line 925 in file 'func.c') - $(LI $(BUGZILLA 1523): struct literals not work with typedef) - $(LI $(BUGZILLA 1531): cannot access typedef'd class field) - $(LI $(BUGZILLA 1537): Internal error: ..\ztc\cgcod.c 1521) - $(LI $(BUGZILLA 1609): TypeInfo_Typedef has incorrect implementation of next()) -) -) - -$(VERSION 021, Sep 5, 2007, =================================================, - -$(WHATSNEW - $(LI Added command line switches $(B -defaultlib) and $(B -debuglib)) - $(LI $(BUGZILLA 1445): Add default library options to sc.ini / dmd.conf) - $(LI Added trace_term() to object.d to fix $(BUGZILLA 971): No profiling output is generated if the application terminates with exit) - $(LI Multiple module static constructors/destructors allowed.) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 961): std.windows.registry stack corruption) - $(LI $(BUGZILLA 1315): CTFE doesn't default initialise arrays of structs) - $(LI $(BUGZILLA 1363): Compile-time issue with structs in 'for') - $(LI $(BUGZILLA 1375): CTFE fails for null arrays) - $(LI $(BUGZILLA 1378): A function call in an array literal causes compiler to crash) - $(LI $(BUGZILLA 1384): Compiler segfaults when using struct variable like a function with no opCall member.) - $(LI $(BUGZILLA 1388): multiple static constructors allowed in module) - $(LI $(BUGZILLA 1414): compiler crashes with CTFE and structs) - $(LI $(BUGZILLA 1423): Registry: corrupted value) - $(LI $(BUGZILLA 1436): std.date.getLocalTZA() returns wrong values when in DST under Windows) - $(LI $(BUGZILLA 1447): CTFE does not work for static member functions of a class) - $(LI $(BUGZILLA 1448): UTF-8 output to console is seriously broken) - $(LI $(BUGZILLA 1450): Registry: invalid UTF-8 sequence) - $(LI $(BUGZILLA 1460): Compiler crash on valid code) - $(LI $(BUGZILLA 1464): "static" foreach breaks CTFE) -) -) - -$(VERSION 020, Jul 23, 2007, =================================================, - -$(BUGSFIXED - $(LI Fixed $(B extern (System))) -) -) - -$(VERSION 019, Jul 21, 2007, =================================================, - -$(WHATSNEW - $(LI Added 0x78 Codeview extension for type $(B dchar).) - $(LI Added $(B extern (System))) - $(LI $(BUGZILLA 345): updated std.uni.isUniAlpha to Unicode 5.0.0) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 46): Included man files should be updated) - $(LI $(BUGZILLA 268): Bug with SocketSet and classes) - $(LI $(BUGZILLA 406): std.loader is broken on linux) - $(LI $(BUGZILLA 561): Incorrect duplicate error message when trying to create instance of interface) - $(LI $(BUGZILLA 588): lazy argument and nested symbol support to std.demangle) - $(LI $(BUGZILLA 668): Use of *.di files breaks the order of static module construction) - $(LI $(BUGZILLA 1110): std.format.doFormat + struct without toString() == crash) - $(LI $(BUGZILLA 1199): Strange error messages when indexing empty arrays or strings at compile time) - $(LI $(BUGZILLA 1300): Issues with struct in compile-time function) - $(LI $(BUGZILLA 1306): extern (Windows) should work like extern (C) for variables) - $(LI $(BUGZILLA 1331): header file genaration generates a ":" instead of ";" at pragma) - $(LI $(BUGZILLA 1332): Internal error: ../ztc/cod4.c 357) - $(LI $(BUGZILLA 1333): -inline ICE: passing an array element to an inner class's constructor in a nested function, all in a class or struct) - $(LI $(BUGZILLA 1336): Internal error when trying to construct a class declared within a unittest from a templated class.) -) -) - -$(VERSION 018, Jul 1, 2007, =================================================, - -$(BUGSFIXED - $(LI $(BUGZILLA 540): Nested template member function error - "function expected before ()") - $(LI $(BUGZILLA 559): Final has no effect on methods) - $(LI $(BUGZILLA 627): Concatenation of strings to string arrays with ~ corrupts data) - $(LI $(BUGZILLA 629): Misleading error message "Can only append to dynamic arrays") - $(LI $(BUGZILLA 639): Escaped tuple parameter ICEs dmd) - $(LI $(BUGZILLA 641): Complex string operations in template argument ICEs dmd) - $(LI $(BUGZILLA 657): version(): ignored) - $(LI $(BUGZILLA 689): Clean up the spec printfs!) - $(LI $(BUGZILLA 1103): metastrings.ToString fails for long > 0xFFFF_FFFF) - $(LI $(BUGZILLA 1107): CodeView: wrong CV type for bool) - $(LI $(BUGZILLA 1118): weird switch statement behaviour) - $(LI $(BUGZILLA 1186): Bind needs a small fix) - $(LI $(BUGZILLA 1199): Strange error messages when indexing empty arrays or strings at compile time) - $(LI $(BUGZILLA 1200): DMD crash: some statements containing only a ConditionalStatement with a false condition) - $(LI $(BUGZILLA 1203): Cannot create Anonclass in loop) - $(LI $(BUGZILLA 1204): segfault using struct in CTFE) - $(LI $(BUGZILLA 1206): Compiler hangs on this() after method in class that forward references struct) - $(LI $(BUGZILLA 1207): Documentation on destructors is confusing) - $(LI $(BUGZILLA 1211): mixin("__LINE__") gives incorrect value) - $(LI $(BUGZILLA 1212): dmd generates bad line info) - $(LI $(BUGZILLA 1216): Concatenation gives 'non-constant expression' outside CTFE) - $(LI $(BUGZILLA 1217): Dollar ($) seen as non-constant expression in non-char[] array) - $(LI $(BUGZILLA 1219): long.max.stringof gets corrupted) - $(LI $(BUGZILLA 1224): Compilation does not stop on asserts during CTFE) - $(LI $(BUGZILLA 1228): Class invariants should not be called before the object is fully constructed) - $(LI $(BUGZILLA 1233): std.string.ifind(char[] s, char[] sub) fails on certain non ascii strings) - $(LI $(BUGZILLA 1234): Occurrence is misspelled almost everywhere) - $(LI $(BUGZILLA 1235): std.string.tolower() fails on certain utf8 characters) - $(LI $(BUGZILLA 1236): Grammar for Floating Literals is incomplete) - $(LI $(BUGZILLA 1239): ICE when empty tuple is passed to variadic template function) - $(LI $(BUGZILLA 1242): DMD AV) - $(LI $(BUGZILLA 1244): Type of array length is unspecified) - $(LI $(BUGZILLA 1247): No time zone info for India) - $(LI $(BUGZILLA 1285): Exception typedefs not distinguished by catch) - $(LI $(BUGZILLA 1287): Iterating over an array of tuples causes "glue.c:710: virtual unsigned int Type::totym(): Assertion `0' failed.") - $(LI $(BUGZILLA 1290): Two ICEs, both involving real, imaginary, ? : and +=.) - $(LI $(BUGZILLA 1291): .stringof for a class type returned from a template doesn't work) - $(LI $(BUGZILLA 1292): Template argument deduction doesn't work) - $(LI $(BUGZILLA 1294): referencing fields in static arrays of structs passed as arguments generates invalid code) - $(LI $(BUGZILLA 1295): Some minor errors in the lexer grammar) -) -) - -$(VERSION 017, Jun 25, 2007, =================================================, - -$(WHATSNEW - $(LI Added $(B __VENDOR__) and $(B __VERSION__).) - $(LI The $(B .init) property for a variable is now based on its - type, not its initializer.) -) - -$(BUGSFIXED - $(LI $(B std.compiler) now is automatically updated.) - $(LI Fixed CFTE bug with e++ and e--.) - $(LI $(BUGZILLA 1254): Using a parameter initialized to void in a compile-time evaluated function doesn't work) - $(LI $(BUGZILLA 1256): "with" statement with symbol) - $(LI $(BUGZILLA 1259): Inline build triggers an illegal error msg "Error: S() is not an lvalue") - $(LI $(BUGZILLA 1260): Another tuple bug) - $(LI $(BUGZILLA 1261): Regression from overzealous error message) - $(LI $(BUGZILLA 1262): Local variable of struct type initialized by literal resets when compared to .init) - $(LI $(BUGZILLA 1263): Template function overload fails when overloading on both template and non-template class) - $(LI $(BUGZILLA 1268): Struct literals try to initialize static arrays of non-static structs incorrectly) - $(LI $(BUGZILLA 1269): Compiler crash on assigning to an element of a void-initialized array in CTFE) - $(LI $(BUGZILLA 1270): -inline produces an ICE) - $(LI $(BUGZILLA 1272): problems with the new 1.0 section) - $(LI $(BUGZILLA 1276): static assert message displayed with escaped characters) - $(LI $(BUGZILLA 1283): writefln: formatter applies to following variable) -) -) - -$(VERSION 016, Jun 14, 2007, =================================================, - -$(WHATSNEW - $(LI The compiler was not changed.) - $(LI Added aliases $(B string), $(B wstring), and $(B dstring) to ease - compatiblity with 2.0.) -) - -$(BUGSFIXED -) -) - -$(VERSION 015, Jun 5, 2007, =================================================, - -$(BUGSFIXED - $(LI Added missing \n to exception message going to stderr.) - $(LI Fixed default struct initialization for CTFE.) - $(LI $(BUGZILLA 1226): ICE on a struct literal) - $(LI Fixed gc memory corrupting problem.) -) -) - -$(VERSION 014, Apr 26, 2007, =================================================, - -$(WHATSNEW - $(LI Added $(LINK2 expression.html#AssocArrayLiteral, associative array literals)) - $(LI Added struct literals) - $(LI Array element assignments can now be done in CTFE) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 1000): writefln fails on nested arrays) - $(LI $(BUGZILLA 1143): Assertion failure: '0' on line 850 in 'template.c' - On specialization of IFTI template parameters.) - $(LI $(BUGZILLA 1144): template mixin causes DMD crash) - $(LI $(BUGZILLA 1146): mixin + assert() crashes compiler) - $(LI $(BUGZILLA 1153): dmd assertion failure) - $(LI $(BUGZILLA 1159): Various mixins cause "CompileExp::semantic" message, some crash DMD) - $(LI $(BUGZILLA 1174): Program hangs creating an array of enums with nonzero initializer) - $(LI $(BUGZILLA 1177): $(DOLLAR) no longer works inside CTFE functions.) - $(LI $(BUGZILLA 1180): the GC failes to handle large allocation requests propperly) - $(LI $(BUGZILLA 1189): Reverse the titles on web pages) -) -) - -$(VERSION 013, Apr 19, 2007, =================================================, - -$(BUGSFIXED - $(LI Fixed crash with std.format and static arrrays) - $(LI $(BUGZILLA 582): Cannot slice mixed tuples) - $(LI $(BUGZILLA 594): can't cast arrayliteral statically) - $(LI $(BUGZILLA 595): can't append to array/arrayliteral statically) - $(LI $(BUGZILLA 997): [Regression] Struct-returning function that conditionally passes the result of another function straight through doesn't work (NRVO bug?)) - $(LI $(BUGZILLA 1090): Attribute specification: "}" vs "end of scope") - $(LI $(BUGZILLA 1091): Wrong size reserved for critical sections) - $(LI $(BUGZILLA 1094): switch bug) - $(LI $(BUGZILLA 1096): Mysterious hang with toUTCString + UTCtoLocalTime + d_time_nan) - $(LI $(BUGZILLA 1098): symbol collision in d/dmd/expression.c between math.h and port.h) - $(LI $(BUGZILLA 1119): Internal error: ../ztc/cgcod.c 2190 (template instantiation)) - $(LI $(BUGZILLA 1121): Assertion codegen issue with templated function) - $(LI $(BUGZILLA 1132): DMD calling linker over commandline) - $(LI $(BUGZILLA 1134): incorrect calling convention used) - $(LI $(BUGZILLA 1135): invariant keyword parsing is messed up) - $(LI $(BUGZILLA 1147): Typo in phobos/std/file.d: 4069 should be 4096) - $(LI $(BUGZILLA 1148): Problems returning structs from functions) - $(LI $(BUGZILLA 1150): Compiler creates wrong code) - $(LI $(BUGZILLA 1156): Installed libraries need to be passed in different order) - $(LI $(BUGZILLA 1163): Can't initialize multiple variables with void.) -) -) - -$(VERSION 012, Apr 12, 2007, =================================================, - -$(BUGSFIXED - $(LI $(NG_digitalmars_D_announce 8190) now works with $(B -v1)) - $(LI $(NG_digitalmars_D_announce 8193)) - $(LI $(BUGZILLA 532): Wrong name mangling for template alias params of local vars) - $(LI $(BUGZILLA 1068): stack corruption with mixins and function templates) - $(LI $(BUGZILLA 1089): Unsafe pointer comparison in TypeInfo_Pointer.compare) - $(LI $(BUGZILLA 1127): -v1 doesn't disable the ref and macro keywords) -) -) - -$(VERSION 011, Apr 11, 2007, =================================================, - -$(WHATSNEW - $(LI Extended $(LINK2 abi.html#codeview, Codeview) - symbolic debug output with LF_OEM types.) - $(LI Extended $(LINK2 abi.html#dwarf, Dwarf) - symbolic debug output with DW_TAG_darray_type, - DW_TAG_aarray_type, and DW_TAG_delegate types.) - $(LI Added keywords $(B ref) and $(B macro).) - $(LI $(B final) classes cannot be subclassed.) - $(LI $(B final) for variables now works.) - $(LI $(B ref) now works as a replacement for $(B inout).) - $(LI Fixed so multiple type inferring declarations like - $(CODE auto a=1,c=2;) works.) -) - -$(BUGSFIXED - $(LI Fixed problem with overloading of function templates that - have the same template parameter list, but different function - parameters.) - $(LI Fixed problems with type deduction from specializations that - are template instances.) - $(LI Fixed assert template.c(2956) s->parent) - $(LI Got .$(I property) to work for typeof.) - $(LI Fixed bug in DW_AT_comp_dir output for some linux versions.) - $(LI $(NG_digitalmars_D_announce 8027)) - $(LI $(NG_digitalmars_D_announce 8047)) - $(LI $(NG_digitalmars_D 51800)) - $(LI $(BUGZILLA 1028): Segfault using tuple inside asm code.) - $(LI $(BUGZILLA 1052): DMD 1.009 - aliasing functions from superclasses may result in incorrect conflicts) - $(LI $(BUGZILLA 1080): Failed to link to std.windows.registry) - $(LI $(BUGZILLA 1081): with using real and -O option, dmd generate bug code) - $(LI $(BUGZILLA 1082): The .offsetof property yields a signed int, a size_t would be more appropriate) - $(LI $(BUGZILLA 1086): CodeView: missing line information for string switch) - $(LI $(BUGZILLA 1092): compiler crash in ..\ztc\cod1.c 2528) - $(LI $(BUGZILLA 1102): switch case couldn't contain template member) - $(LI $(BUGZILLA 1108): Indexing an int[] not evaluatable at compile time) - $(LI $(BUGZILLA 1122): dmd generate bad line number while reporting error message) -) -) - -$(VERSION 010, Mar 24, 2007, =================================================, - -$(WHATSNEW - $(LI Added template partial specialization derived from multiple - parameters.) - $(LI Added Object.factory(char[] classname) method to create - class objects based on a string.) - $(LI Added std.gc.malloc(), std.gc.extend() and std.gc.capacity().) - $(LI Added std.string.isEmail() and std.string.isURL().) - $(LI Added std.stdio.readln().) - $(LI Improved gc performance for array resize and append.) - $(LI $(BUGZILLA 64): Unhandled errors should go to stderr) - $(LI Added predefined Ddoc macro DOCFILENAME) -) - -$(BUGSFIXED - $(LI Fixed $(LINK2 http://www.digitalmars.com/d/archives/digitalmars/D/bugs/Broken_link_in_http_digitalmars.com_d_comparison.html_10906.html, Broken link in http://digitalmars.com/d/comparison.html)) - $(LI Fixed problem with CTFE and array literals) - $(LI $(BUGZILLA 931): D Strings vs C++ Strings Page Incorrect) - $(LI $(BUGZILLA 935): Extern Global C Variables) - $(LI $(BUGZILLA 948): operatoroverloading.html - Rationale section is both out of date and incomplete) - $(LI $(BUGZILLA 950): Missing filename and line number: conflict between implicit length in [...] and explicit length declared in the scope) - $(LI $(BUGZILLA 959): smaller ddoc documentation issue) - $(LI $(BUGZILLA 1056): segfault with pragma(msg) inside CTFE) - $(LI $(BUGZILLA 1062): Cannot catch typedef'd class) - $(LI $(BUGZILLA 1074): Dead link to std.c.locale webpage) -) -) - -$(VERSION 009, Mar 10, 2007, =================================================, - -$(BUGSFIXED - $(LI $(NG_digitalmars_D 49928) 1) - $(COMMENT $(NG_digitalmars_D_announce 7563)) - $(LI $(LINK2 http://www.digitalmars.com/d/archives/digitalmars/D/announce/DMD_1.007_release_7507.html#N7563, D.announce 7563)) - $(LI $(BUGZILLA 146): Wrong filename in DWARF debugging information for templates) - $(LI $(BUGZILLA 992): CTFE Failure with static if) - $(LI $(BUGZILLA 993): incorrect ABI documentation for float parameters) - $(LI $(BUGZILLA 995): compile-time function return element of Tuple / const array) - $(LI $(BUGZILLA 1005): dmd: tocsym.c:343: virtual Symbol* FuncDeclaration::toSymbol(): Assertion `0' failed.) - $(LI $(BUGZILLA 1009): CodeView: out and inout parameters are declared void*) - $(LI $(BUGZILLA 1014): Error with character literal escaping when generating header with -H) - $(LI $(BUGZILLA 1016): CTFE fails with recursive functions) - $(LI $(BUGZILLA 1017): CTFE doesn't support (string == string)) - $(LI $(BUGZILLA 1018): regression: Error: divide by 0) - $(LI $(BUGZILLA 1019): regression: missing filename and line number: Error: array index X is out of bounds [0 .. Y]) - $(LI $(BUGZILLA 1020): regression: mov EAX, func) - $(LI $(BUGZILLA 1021): CTFE and functions returning void) - $(LI $(BUGZILLA 1022): CodeView: unions have zero length in typeleafs and datasymbols) - $(LI $(BUGZILLA 1026): dmd SEGV when checking length of Tuple elements when length == 0) - $(LI $(BUGZILLA 1030): ICE one-liner; struct in delegate) - $(LI $(BUGZILLA 1038): explicit class cast breakage in 1.007) -) -) - -$(VERSION 007, Feb 20, 2007, =================================================, - -$(WHATSNEW - $(LI Comparison operators are no longer associative; comparison, - equality, identity and in operators all have the same precedence.) - $(LI $(CODE out) and $(CODE inout) parameters are now allowed - for compile time function execution.) - $(LI The $(CODE .dup) property is now allowed - for compile time function execution.) - $(LI Updated $(LINK2 http://www.digitalmars.com/ctg/lib.html, lib) - to insert COMDATs into symbol table.) - $(LI Class references can no longer be implicitly converted to - $(CODE void*).) -) - -$(BUGSFIXED - $(LI $(NG_digitalmars_D 48806) crash) - $(LI $(NG_digitalmars_D 48811)) - $(LI $(NG_digitalmars_D 48845)) - $(LI $(NG_digitalmars_D 48869)) - $(LI $(NG_digitalmars_D 48917)) - $(LI $(NG_digitalmars_D 48953)) - $(LI $(NG_digitalmars_D 48990)) - $(LI $(NG_digitalmars_D 49033)) - $(LI $(NG_digitalmars_D_announce 7496)) - $(LI $(BUGZILLA 968): ICE on compile-time execution) - $(LI $(BUGZILLA 974): compile-time parenthesis bug) - $(LI $(BUGZILLA 975): compile-time const array makes dmd crash) - $(LI $(BUGZILLA 980): If a function tries to concatenate a char to a empty array, dmd complains that the function can't be evaluated at compile time) - $(LI $(BUGZILLA 981): CFTE fails in non-template and functions that takes no args.) - $(LI $(BUGZILLA 986): Internal error: e2ir.c 1098) -) -) - -$(VERSION 006, Feb 15, 2007, =================================================, - -$(WHATSNEW - $(LI Added $(B -J)$(I path) switch, which is now required in - order to import text files.) - $(LI Enhanced $(B -v) output to include actual filename.) - $(LI name string for TypeInfo_Struct now part of the - TypeInfo_Struct comdat.) - $(LI $(LINK2 function.html#interpretation, Compile time execution) - of functions) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 960): New: DMD 1.0 is in the past -- not the future) - $(LI Codeview for classes now gives correct LF_CLASS) -) -) - -$(VERSION 005, Feb 5, 2007, =================================================, - -$(WHATSNEW - $(LI $(B -v) now emits pragma library statements and - imported file names) - $(LI deprecated $(B ===), and $(B !==), tokens no longer recognized) - $(LI $(CODE length) can no longer shadow other $(CODE length) declarations) - $(LI Added $(LINK2 statement.html#MixinStatement, MixinStatement)s, - $(LINK2 expression.html#MixinExpression, MixinExpression)s, - and $(LINK2 module.html#MixinDeclaration, MixinDeclaration)s.) - $(LI Added $(LINK2 expression.html#ImportExpression, ImportExpression)s.) - $(LI Added $(LINK2 phobos/std_metastrings.html, std.metastrings)) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 761): std.format.doFormat fails for items of a char[][] containing %s) - $(LI $(BUGZILLA 784): regression: [Issue 402] compiler crash with mixin and forward reference) - $(LI $(BUGZILLA 787): incorrect documentation of std.ctype.isprint) - $(LI $(BUGZILLA 788): Compiler rejects hex floats in the format: HexPrefix HexDigits . HexDigits(opt) with binary-exponent-part required) - $(LI $(BUGZILLA 789): const initialization in forwarding constructors doesn't work) - $(LI $(BUGZILLA 791): dhry.d example doesn't compile in 1.0 without trivial change) - $(LI $(BUGZILLA 794): std.math.exp2(0) equals 0 instead of 1) - $(LI $(BUGZILLA 800): writefln() on an associative array fails hard) - $(LI $(BUGZILLA 821): segfault with char array copy; mistaken samples in doc) - $(LI $(BUGZILLA 831): Warning!! String literals are read-only one some platforms.) - $(LI $(BUGZILLA 832): NRVO: return inside foreach results in junk) - $(LI $(BUGZILLA 835): RegExp.test wrongly matches strings on case insensitive attribute) - $(LI $(BUGZILLA 846): Error 42: Symbol Undefined _D1a7__arrayZ) - $(LI $(BUGZILLA 848): typo in C sorting example) - $(LI $(BUGZILLA 862): Selectively importing a nonexistent identifier results in spurious and incorrect error message) - $(LI $(BUGZILLA 872): Assertion in expression.c caused by taking typeof of "this.outer" in nested classes.) - $(LI $(BUGZILLA 875): crash in glue.c line 700) - $(LI $(BUGZILLA 886): std.zlib uncompression routines do not mark result as containing no pointers) - $(LI $(BUGZILLA 887): TypeInfo does not correctly override opCmp, toHash) - $(LI $(BUGZILLA 888): -cov and _ModuleInfo linking bugs) - $(LI $(BUGZILLA 890): Returning char[4] and assigning to char[] produces unexpected results.) - $(LI $(BUGZILLA 891): Crash when compiling the following code (tested with 1.0, 1.001 and 1.002)) - $(LI $(BUGZILLA 893): The profile flag no longer seems to work on Linux x86 64) - $(LI $(BUGZILLA 894): base class with implemented abstract method problem) - $(LI $(BUGZILLA 897): fix default dmd.conf file) - $(LI $(BUGZILLA 898): std.conv.toInt doesn't raise ConvOverflowError) - $(LI $(BUGZILLA 901): Comparison of array literals fails) - $(LI $(BUGZILLA 903): Example with printf and string literals crashes) - $(LI $(BUGZILLA 908): compiler dies trying to inline static method call to nonstatic method in template code.) - $(LI $(BUGZILLA 910): Error in description of "this" and "super" keywords) - $(LI $(BUGZILLA 913): deprecated tokens still listed) - $(LI $(BUGZILLA 915): dmd generate bad form return(retn 4) for invariant func) - $(LI $(BUGZILLA 916): regression: Internal error: ../ztc/gloop.c 1305) - $(LI $(BUGZILLA 917): regression: circular typedefs cause segfaults) - $(LI $(BUGZILLA 924): GC collects valid objects) - $(LI $(NG_digitalmars_D_announce 6983)) -) -) - -$(VERSION 004, Jan 26, 2007, =================================================, - -$(BUGSFIXED - $(LI $(BUGZILLA 892): Another bug in the new GC - pointers in mixins) -) -) - -$(VERSION 003, Jan 26, 2007, =================================================, - -$(BUGSFIXED - $(LI $(NG_digitalmars_D_announce 6929)) - $(LI $(NG_digitalmars_D_announce 6953)) -) -) - -$(VERSION 002, Jan 24, 2007, =================================================, - -$(BUGSFIXED - $(LI $(NG_digitalmars_D_announce 6893): ClassInfo.flags incorrectly set) - $(LI $(NG_digitalmars_D_announce 6906): Three subtle cases of tail recursion item 1 and 2) -) -) - -$(VERSION 001, Jan 23, 2007, =================================================, - -$(WHATSNEW - $(LI tail recursion works again) - $(LI New type aware GC) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 621): When inside a loop, if you call break inside a try block the finally block is never executed) - $(LI $(BUGZILLA 804): missing linux functions) - $(LI $(BUGZILLA 815): scope(exit) isn't executed when "continue" is used to continue a while-loop) - $(LI $(BUGZILLA 817): const char[] = string_literal - string_literal gets included for every reference) - $(LI $(BUGZILLA 819): mention response files in cmd line usage) - $(LI $(BUGZILLA 820): gc should scan only pointer types for pointers) - $(LI $(BUGZILLA 823): frontend: incorrect verror declaration in mars.h) - $(LI $(BUGZILLA 824): "mov EAX, func;" and "lea EAX, func;" generate incorrect code) - $(LI $(BUGZILLA 825): dmd segmentation fault with large char[] template value parameter) - $(LI $(BUGZILLA 826): ICE: is-expression with invalid template instantiation) -) -) - -) - -Macros: - TITLE=Change Log - WIKI=ChangeLog - - NEW1 = $(LI What's new for D 1.$0) - - VERSION= -
    - $(B $(LARGE - Version - D 1.$1 - )) - $(SMALL $(I $2, $3)) - $5 -
    - - BUGZILLA = Bugzilla $0 - CPPBUGZILLA = Bugzilla $0 - DSTRESS = dstress $0 - BUGSFIXED =

    Bugs Fixed

    $(UL $0 ) - UPCOMING =

    Under Construction

    $(OL $0 ) - WHATSNEW =

    New/Changed Features

    $(UL $0 ) - LARGE=$0 - diff --git a/changelog.dd b/changelog.dd deleted file mode 100644 index cc821cf9c5..0000000000 --- a/changelog.dd +++ /dev/null @@ -1,3622 +0,0 @@ -Ddoc - -$(D_S D Change Log, - -$(COMMENT $(UPCOMING - $(LI Shared libraries for Linux) -)) - -$(VERSION 058, $(B upcoming) Feb 13, 2012, =================================================, - - $(WHATSNEW - $(LI Add new => lambda syntax.) - $(LI Allow 1.userproperty syntax) - $(LI Convert to -shared dmd switch instead of -dylib) - $(LI Better use of XMM registers in OS X 32 bit target.) - $(LI Add inline assembler support for AVX instructions (64 bit targets only).) - $(LI Use of base class protection is now deprecated.) - $(LI Added traits isVirtualMethod and getVirtualMethods.) - $(LI Struct/class invariants are now implicitly const.) - ) - $(RUNTIMEBUGSFIXED - ) - $(LIBBUGSFIXED - $(LI $(BUGZILLA 4295): IID_IUnknown symbol undefined in phobos.lib) - $(LI $(BUGZILLA 7241): std.format can't read into array of dchar ) - ) - $(DMDBUGSFIXED - $(LI $(BUGZILLA 314): [module] Static, renamed, and selective imports are always public) - $(LI $(BUGZILLA 516): Mutually calling constructors allowed) - $(LI $(BUGZILLA 620): Can't use property syntax with a template function) - $(LI $(BUGZILLA 664): is(func T == function) ignores variadic arguments) - $(LI $(BUGZILLA 678): Compiler accepts, for a function T[] t(), t().ptr but not t.ptr) - $(LI $(BUGZILLA 796): Asserting a null object reference throws AssertError Failure internal\invariant.d(14) or Access Violation) - $(LI $(BUGZILLA 949): Wrong spec/compiler behaviour for Strings, Integers and Floats) - $(LI $(BUGZILLA 955): Passing arguments into functions - in, out, inout, const, and contracts) - $(LI $(BUGZILLA 1313): out/body disables escape analysis) - $(LI $(BUGZILLA 1521): Ambiguous documentation) - $(LI $(BUGZILLA 1563): dynamic cast is not always performed) - $(LI $(BUGZILLA 1570): Wrong return for address operator) - $(LI $(BUGZILLA 1918): __traits(getVirtualFunctions) returns final functions) - $(LI $(BUGZILLA 1920): Class documentation incomplete) - $(LI $(BUGZILLA 1943): Templates can't take function pointer parameters) - $(LI $(BUGZILLA 2106): export class doesn't affect, what is exported) - $(LI $(BUGZILLA 2351): enum with no members allowed) - $(LI $(BUGZILLA 2382): spec is not clear on what is allowed as global/static initializers) - $(LI $(BUGZILLA 2387): Static array terminology) - $(LI $(BUGZILLA 2411): Reference Tuple Foreach) - $(LI $(BUGZILLA 2417): [module] protected base member is not available via base handle in a derived class if it is defined in a separate module) - $(LI $(BUGZILLA 2442): opApply does not allow inferring parameter types when overloaded on const) - $(LI $(BUGZILLA 2443): opApply should allow delegates that are not ref if it makes no sense) - $(LI $(BUGZILLA 2483): DMD allows assignment to a scope variable) - $(LI $(BUGZILLA 2494): describe explicit casting of arrays) - $(LI $(BUGZILLA 2495): const syntax for member functions needs better description) - $(LI $(BUGZILLA 2497): delete and null relationship needs more details) - $(LI $(BUGZILLA 2524): final override inconsistent when implementing interfaces) - $(LI $(BUGZILLA 2639): Hex and octal string values not completely specified) - $(LI $(BUGZILLA 2819): array.sort segfaults if array length >=0x8F_FFFF) - $(LI $(BUGZILLA 2894): abstract classes sometimes allow non-abstract bodyless functions) - $(LI $(BUGZILLA 2997): allMembers does not return interface members) - $(LI $(BUGZILLA 3084): Formatting of lazy in parameters section) - $(LI $(BUGZILLA 3092): Indexing a tuple produces a tuple containing the indexed element) - $(LI $(BUGZILLA 3111): 'mangleof' can't be member of a struct not documented) - $(LI $(BUGZILLA 3187): Nested foreach over opApply doesn't work) - $(LI $(BUGZILLA 3204): Document global properties) - $(LI $(BUGZILLA 3235): [tdpl] Function literals must be deduced as "function" or "delegate") - $(LI $(BUGZILLA 3265): .classinfo for Interface-typed reference does not return instance's ClassInfo) - $(LI $(BUGZILLA 3492): Can't overload nested functions) - $(LI $(BUGZILLA 3578): Impossible to run a struct invariant using assert(s)) - $(LI $(BUGZILLA 3735): op=) - $(LI $(BUGZILLA 3757): Overloading const function with overridden non-const function results in seg fault.) - $(LI $(BUGZILLA 3777): size_t is undefined) - $(LI $(BUGZILLA 3783): Text inconsistent with EscapeSequence rules) - $(LI $(BUGZILLA 3787): clarification: assigment to 'this') - $(LI $(BUGZILLA 3791): Reference anonymous nested classes when describing new expressions) - $(LI $(BUGZILLA 3800): "Foreach over Structs and Classes with Ranges" and "Invariant Struct" in D2 Spec) - $(LI $(BUGZILLA 3838): PrimaryExpression rule doesn't permit module scope template instances) - $(LI $(BUGZILLA 3886): Bad example of definition file for DLLs) - $(LI $(BUGZILLA 3906): Undefined struct and union declarations are not documented) - $(LI $(BUGZILLA 3908): @ attributes not part of function grammar) - $(LI $(BUGZILLA 3954): DeclDef rule is missing TemplateMixinDeclaration) - $(LI $(BUGZILLA 3988): Provide canonical example for operator overloading) - $(LI $(BUGZILLA 4180): D DWARF extensions conflict with DWARF-4) - $(LI $(BUGZILLA 4251): Hole in the const system: immutable(T)[] implicitly casts to ref const(T)[]) - $(LI $(BUGZILLA 4371): segfault(template.c) template tuple in is() expression) - $(LI $(BUGZILLA 4413): typeof(this) doesn't work in method template signature) - $(LI $(BUGZILLA 4421): Union propagates copy constructors and destructors over all members) - $(LI $(BUGZILLA 4523): [tdpl] .remove method for Associative Arrays returns void in all cases) - $(LI $(BUGZILLA 4539): Refuse assignment to string literal) - $(LI $(BUGZILLA 4545): Alias to members possible without "this" instance) - $(LI $(BUGZILLA 4550): D2 Language Docs: http://www.digitalmars.com/d/2.0/statement.html) - $(LI $(BUGZILLA 4553): D2 Language Docs: http://www.digitalmars.com/d/2.0/struct.html) - $(LI $(BUGZILLA 4647): [tdpl] Cannot explicitly call final interface method, ambiguous calls allowed) - $(LI $(BUGZILLA 4651): Docs: Returned classes that have access to stack variables of its enclosing function) - $(LI $(BUGZILLA 4675): [tdpl] Eponymous Template should hide internal names) - $(LI $(BUGZILLA 4711): Incorrect handling of && operator with void operand) - $(LI $(BUGZILLA 4887): Right-shifting by 32 is allowed and broken) - $(LI $(BUGZILLA 4940): ICE(symbol.c): Accessing tuple-typed field of struct literal with user-defined constructor) - $(LI $(BUGZILLA 4956): remove direct references to gcc from linux.mak) - $(LI $(BUGZILLA 5023): Docs about order of execution of invariant and pre/post conditions) - $(LI $(BUGZILLA 5111): Static function-level variables are not in the language spec.) - $(LI $(BUGZILLA 5114): Too many error messages) - $(LI $(BUGZILLA 5132): ~ unary operator silently different from C) - $(LI $(BUGZILLA 5138): Special token sequence) - $(LI $(BUGZILLA 5261): Uncompilable example for Windows) - $(LI $(BUGZILLA 5299): Protected inheritance is semantically undefined.) - $(LI $(BUGZILLA 5337): Documentation regarding interfacing with C does not account for TLS differences) - $(LI $(BUGZILLA 5476): spec: attributes have an optional else clause) - $(LI $(BUGZILLA 5493): Able to overwrite immutable data by passing through ref function parameter) - $(LI $(BUGZILLA 5527): Bug in http://www.digitalmars.com/d/2.0/ctod.html#closures) - $(LI $(BUGZILLA 5605): [tdpl] foreach with ranges doesn't support opSlice()) - $(LI $(BUGZILLA 5648): dmd command line option list inconsistencies) - $(LI $(BUGZILLA 5713): Broken final switch on ints) - $(LI $(BUGZILLA 5715): Contradiction in spec: meaning of variable.init) - $(LI $(BUGZILLA 5796): ICE with pragma(msg, ...) after missing ';' in a template) - $(LI $(BUGZILLA 5820): Documentation states string literals can implicitly convert to char*) - $(LI $(BUGZILLA 5841): alias grammar is incorrect) - $(LI $(BUGZILLA 6013): private ignored for aliases) - $(LI $(BUGZILLA 6037): [CTFE] recursive ref parameters evaluated incorrectly) - $(LI $(BUGZILLA 6091): [d-p-l.org] Description for "Modifier casting" is misleading) - $(LI $(BUGZILLA 6165): Anonymous enums specification) - $(LI $(BUGZILLA 6177): Regression(2.053): ICE backend/cgcs.c: struct with destructor in assoc. array or typesafe variadic functions) - $(LI $(BUGZILLA 6205): Strongly-pure nothrow functions with ignored return value are entirely stripped even if it contains a failing 'assert'.) - $(LI $(BUGZILLA 6208): Parameter storage classes are ignored in template function deducing.) - $(LI $(BUGZILLA 6364): Static struct's destructor called on exit of function) - $(LI $(BUGZILLA 6402): Note on @property in spec needs updating) - $(LI $(BUGZILLA 6451): [64bit] ICE(expression.c:4434): SymbolExp::SymbolExp(Loc, TOK, int, Declaration*, int): Assertion 'var' failed) - $(LI $(BUGZILLA 6473): Stack overflow with struct destructor as default parameter) - $(LI $(BUGZILLA 6701): template specialization resolution failure) - $(LI $(BUGZILLA 6704): CommaExpression as an IfCondition) - $(LI $(BUGZILLA 6714): [tdpl] Type inference for parameters of function and delegate literals) - $(LI $(BUGZILLA 6738): Can't call templatized property function from within a struct/class method) - $(LI $(BUGZILLA 6780): Templated global property functions do not work) - $(LI $(BUGZILLA 6839): documentation for opAssign incorrect) - $(LI $(BUGZILLA 6933): Segfault(declaration.c) using struct with destructor in CTFE) - $(LI $(BUGZILLA 6934): [CTFE] can't use $ in a slice of an array passed by ref) - $(LI $(BUGZILLA 6939): wrong type qualifier combination) - $(LI $(BUGZILLA 6940): immutable(int*)*/immutable(int)** and int** do not combine) - $(LI $(BUGZILLA 6948): Possible bug in compiler or documentation regarding signature of opCmp()) - $(LI $(BUGZILLA 6964): Error message with __error: static assert(undefined+1)) - $(LI $(BUGZILLA 6968): Segmantation fault, if exclamation mark absent) - $(LI $(BUGZILLA 6971): [lex.dd] Type of string literals are outdated) - $(LI $(BUGZILLA 6984): CTFE generates a torrent of spurious errors, if there was a previous error) - $(LI $(BUGZILLA 6985): [CTFE] Non-constant case expressions can't be interpreted) - $(LI $(BUGZILLA 6987): The "Memory Management" documentation incorrectly claims arrays are passed by reference) - $(LI $(BUGZILLA 6995): [CTFE] can't interpret static template method) - $(LI $(BUGZILLA 7011): No line number error for vector power) - $(LI $(BUGZILLA 7037): TemplateTypeParameterSpecialization works differently from IsExpression regarding alias this) - $(LI $(BUGZILLA 7043): CTFE: ICE illegal reference value 0LU, only with -inline) - $(LI $(BUGZILLA 7073): Parsing of class-returning varargs function inside module ctor fails) - $(LI $(BUGZILLA 7108): ICE: TraitsExp::semantic(Scope*) 2.056 -> 2.057 regression - segfault) - $(LI $(BUGZILLA 7120): Scope Delegates + Delegate Literals) - $(LI $(BUGZILLA 7123): static assert(is(typeof(toDelegate(&main)))) is false) - $(LI $(BUGZILLA 7124): Alias this type is not considered in template type deduction) - $(LI $(BUGZILLA 7127): Const-related infinite recursion in DWARF generation) - $(LI $(BUGZILLA 7133): [tdpl] There should be no empty statement) - $(LI $(BUGZILLA 7136): alias this lookup should run before merging modifiers of both sides.) - $(LI $(BUGZILLA 7143): [CTFE] cannot compare class references with "is") - $(LI $(BUGZILLA 7144): [CTFE] base class does not call overridden members) - $(LI $(BUGZILLA 7154): [CTFE] failing downcast causes error) - $(LI $(BUGZILLA 7158): [CTFE] ICE(interpret.c) calling a class member using a dotvar expression) - $(LI $(BUGZILLA 7160): Regression(2.057): ICE(dsymbol.c:1052) ICE using __traits(derivedMembers)) - $(LI $(BUGZILLA 7162): [CTFE] "bool || void" expression crashes dmd) - $(LI $(BUGZILLA 7165): [CTFE] ice converting null pointer to bool with constant member function) - $(LI $(BUGZILLA 7166): Internal error: ../ztc/cgxmm.c 60) - $(LI $(BUGZILLA 7168): Regression(2.057) __traits(allMembers) returns wrong tuple) - $(LI $(BUGZILLA 7170): [UFCS] array + specialized template member syntax causes ICE) - $(LI $(BUGZILLA 7173): dmd: glue.c:1065: virtual unsigned int Type::totym(): Assertion `0' failed.) - $(LI $(BUGZILLA 7178): Segfault with import of invalid template) - $(LI $(BUGZILLA 7185): [CTFE] ICE on changing char array length) - $(LI $(BUGZILLA 7187): Regression(head 12d62ca5): [CTFE] ICE on slicing) - $(LI $(BUGZILLA 7188): "import phobos;" crashes DMD) - $(LI $(BUGZILLA 7189): inline failed) - $(LI $(BUGZILLA 7190): Tuple length incorrect) - $(LI $(BUGZILLA 7193): Regression(2.058head): ICE: delete lambda expression crashes dmd) - $(LI $(BUGZILLA 7194): [CTFE] Incorrect behaviour with pointers as local struct variable) - $(LI $(BUGZILLA 7196): Unfair function address overload resolution) - $(LI $(BUGZILLA 7197): enum string doesn't work with CTFE) - $(LI $(BUGZILLA 7201): Lambda template assignment to variable) - $(LI $(BUGZILLA 7207): Explicit cast should resolve lambda type) - $(LI $(BUGZILLA 7212): Regression(Head): ICE with overload resolution and delegate/function inference) - $(LI $(BUGZILLA 7216): [CTFE] Can't call struct member function using pointer field) - $(LI $(BUGZILLA 7217): [CTFE] ICE on accessing struct array field) - $(LI $(BUGZILLA 7218): Nested function with contract is rejected) - $(LI $(BUGZILLA 7228): MOVDQ2Q instruction is emitted with swapped register indices) - $(LI $(BUGZILLA 7231): Segfault using opDispatch with property notation) - $(LI $(BUGZILLA 7232): Warning: statement is not reachable has no line number) - $(LI $(BUGZILLA 7234): Segmentation fault when using stdio) - $(LI $(BUGZILLA 7239): C style struct initialization doesn't work with aliases) - $(LI $(BUGZILLA 7245): [CTFE] Address of ref foreach parameter changes to point after array) - $(LI $(BUGZILLA 7248): [CTFE] Stack overflow on using struct filed pointer with address of array element) - $(LI $(BUGZILLA 7266): [CTFE] Assign to ref param (that's taken from struct member) is noop) - $(LI $(BUGZILLA 7277): [CTFE ICE] Assertion failure: 'thisval' on line 1690 in file 'interpret.c') - $(LI $(BUGZILLA 7278): Templated struct (instantiated with null) can't access its own members) - $(LI $(BUGZILLA 7285): Implicit fixed-size array cast) - $(LI $(BUGZILLA 7290): Heap allocation with scoped delegate literal) - $(LI $(BUGZILLA 7295): Alias This + Pure + pointsTo = rejects-valid) - $(LI $(BUGZILLA 7296): [2.058] Regression: Cannot swap RefCounted) - $(LI $(BUGZILLA 7309): [2.058] Regression caused by new inlining code) - $(LI $(BUGZILLA 7321): returning void considered unsafe by safety inference) - $(LI $(BUGZILLA 7335): sometimes the OUT - block have undefined class members-acces) - $(LI $(BUGZILLA 7351): Possible asm bug: bad type/size of operands 'xadd') - $(LI $(BUGZILLA 7359): Template function with typesafe variadic rejects more than one string arguments) - $(LI $(BUGZILLA 7365): [Regression after 2.057] AAs broken for Object keys and values with opEquals) - $(LI $(BUGZILLA 7367): wrong char comparison result) - $(LI $(BUGZILLA 7369): Inout constructor causes compiler to reject invariant) - $(LI $(BUGZILLA 7373): (Regression git) Renamed imports conflict with other implicitly imported symbols) - $(LI $(BUGZILLA 7375): Regression(2.057): Invalid downcast permitted with derived/aliased template classes) - $(LI $(BUGZILLA 7377): Compiler segfault in: TemplateMixin::hasPointers()) - $(LI $(BUGZILLA 7379): DMD segfaults on semantic3 phase when alias enum this) - $(LI $(BUGZILLA 7383): Blank lines in code sections cause premature section termination) - $(LI $(BUGZILLA 7384): Typo in volatile deprecation message) - ) -) - -
    -$(UL - $(NEW 058) - $(NEW 057) - $(NEW 056) - $(NEW 055) - $(NEW 054) - $(NEW 053) - $(NEW 052) - $(NEW 051) - $(NEW 050) - $(NEW 049) - $(NEW 048) - $(NEW 047) - $(NEW 046) - $(NEW 045) - $(NEW 044) - $(NEW 043) - $(NEW 042) - $(NEW 041) - $(NEW 040) - $(NEW 039) - $(NEW 038) - $(NEW 037) - $(NEW 036) - $(NEW 035) - $(NEW 034) - $(NEW 033) - $(NEW 032) - $(NEW 031) - $(NEW 030) - $(NEW 029) - $(NEW 028) - $(NEW 027) - $(NEW 026) - $(NEW 025) - $(NEW 023) - $(NEW 022) - $(NEW 021) - $(NEW 020) - $(NEW 019) - $(NEW 018) - $(NEW 017) - $(NEW 016) - $(NEW 015) - $(NEW 014) - $(NEW 013) - $(NEW 012) - $(NEW 011) - $(NEW 010) - $(NEW 009) - $(NEW 008) - $(NEW 007) - $(NEW 006) - $(NEW 005) - $(NEW 004) - $(NEW 003) - $(NEW 002) - $(NEW 001) - $(NEW 000) - - $(LI $(LINK2 http://www.digitalmars.com/d/1.0/changelog.html, changelog for 1.0)) - - $(COMMENT $(LI Download latest D 2.0 alpha - - D compiler for Win32 and x86 linux)) - - $(LI $(LINK2 http://www.digitalmars.com/pnews/index.php?category=2, tech support)) -) -
    - -$(VERSION 057, Dec 13, 2011, =================================================, - - $(WHATSNEW - $(LI Better use of XMM registers in 64 bit targets.) - $(LI The $(D_KEYWORD invariant) keyword as a synonym for $(D_KEYWORD immutable) is now deprecated - use $(D_KEYWORD immutable) instead) - $(LI Add Mach-O 64 bit support for obj2asm and dumpobj) - $(LI classes, interfaces, and exceptions are supported in CTFE) - $(LI $(BUGZILLA 3474): PATCH: Implement opDollar for struct and class indexing operations) - $(LI $(BUGZILLA 6572): Deprecate typedef) - - $(LI Major overhaul of std.regex module's implementation. - $(RED Breaking change) in std.regex.replace with delegate, - use Captures!string instead of RegexMatch!string as delegate parameter.) - $(LI As typedef has been deprecated, overloads of std.conv.to which use - typedef have now been deprecated.) - $(LI std.array.insert has been deprecated. Please use std.array.insertInPlace instead.) - $(LI The overload of std.array.replace which replaces in place has been deprecated. - Please use std.array.replaceInPlace instead.) - $(LI The toISOExtendedString and fromISOExtendedString functions on SysTime, Date, - TimeOfDay, and DateTime in std.datetime have been deprecated. Please use - toISOExtString and fromISOExtString instead.) - $(LI std.file.getTimesPosix has been deprecated. Please use std.file.getTimes instead.) - $(LI The overloads for isDir, isFile, and isSymlink in std.file which take a uint - have been deprecated. Please use attrIsDir, attrIsFile, and attrIsSymlink instead.) - $(LI $(BUGZILLA 2550): implicit conversions don't apply to template value parameter specialization) - $(LI $(BUGZILLA 3467): Non-int integral template parameters not correctly propagated) - $(LI Removed top const from dynamic array types and pointer types in IFTI.) - ) - $(RUNTIMEBUGSFIXED - $(LI $(BUGZILLA 6909): incorrect definition of the OVERLAPPED struct in core.sys.windows.windows ?) - ) - $(LIBBUGSFIXED - $(LI Unlisted bug: std.conv: Fix to!float("-0")) - $(LI Unlisted bug: std.file broken on OS X x86_64 due to wrong stat64 declaration.) - $(LI $(BUGZILLA 2936): std.regex.match() short string optimization) - $(LI $(BUGZILLA 4765): std.math.modf always returns 0) - $(LI $(BUGZILLA 5193): SList cannot have struct elements that have immutable members.) - $(LI $(BUGZILLA 5620): Implicit conversion of RegexMatch to bool.) - $(LI $(BUGZILLA 5712): [patch] std.regex.replace disallows w/dstring) - $(LI $(BUGZILLA 6204): emplace() for classes accepts larger chunk but fails in array assignment) - $(LI $(BUGZILLA 6887): Regression of getopt) - $(LI $(BUGZILLA 6888): std.getopt.getopt: one-letter hash option causes range violation) - $(LI $(BUGZILLA 6935): struct with @disable this cannot make range) - $(LI $(BUGZILLA 6953): std.concurrency needs more documentation) - $(LI $(BUGZILLA 6973): static assert(isOutputRange!(OutputRange!int, int)) is false) - $(LI $(BUGZILLA 6976): GetLastError called as property) - $(LI $(BUGZILLA 6977): getErrno called as property in std.stdio) - $(LI $(BUGZILLA 6979): hasUnsharedAliasing cannot accept plural parameters) - $(LI $(BUGZILLA 6990): std.string.splitlines deprecation doc missing a word) - $(LI $(BUGZILLA 7000): missing import of std.stdio in std.regex?) - $(LI $(BUGZILLA 7039): Posix 2.057 Makefile error breaking 64bit build) - $(LI $(BUGZILLA 7040): Phobos must use "version/else version" blocks for proper - documentation generation.) - $(LI $(BUGZILLA 7045): AssertError in std.regex on line 1573) - $(LI $(BUGZILLA 7055): to!float("INF2") == 2) - ) - $(DMDBUGSFIXED - $(LI $(BUGZILLA 2095): covariance w/o typechecks = bugs) - $(LI $(BUGZILLA 2532): '=' does not give a boolean result) - $(LI $(BUGZILLA 2778): alias this + IFTI doesn't work.) - $(LI $(BUGZILLA 2856): static opIndex does not compile for a templated struct/class) - $(LI $(BUGZILLA 3990): Deferencing a dynamic array as pointer) - $(LI $(BUGZILLA 4047): [CTFE] class/struct heap allocation) - $(LI $(BUGZILLA 4401): auto functions cannot be inner functions) - $(LI $(BUGZILLA 4511): Contravariance problem) - $(LI $(BUGZILLA 4583): PIC code not working: EBX register set incorrectly) - $(LI $(BUGZILLA 5311): Pure is broken when accessing globals / static data through instance reference) - $(LI $(BUGZILLA 5364): optimizer kills high dword of -1) - $(LI $(BUGZILLA 5416): null should have a type of its own) - $(LI $(BUGZILLA 5899): auto-return function cannot match 'null' with reference type.) - $(LI $(BUGZILLA 6056): Type lookup problem in string mixins) - $(LI $(BUGZILLA 6077): CTFE: Cannot append null array to null array.) - $(LI $(BUGZILLA 6330): Cannot disable assignment to a struct.) - $(LI $(BUGZILLA 6354): Optimizer bug on x86_64: Bitshift optimized out when foreach and scope(failure) are used) - $(LI $(BUGZILLA 6416): [CTFE] Declaration static struct is not yet implemented in CTFE) - $(LI $(BUGZILLA 6479): spurious alias this with struct and mixin template) - $(LI $(BUGZILLA 6522): [CTFE] Problem with opAssign call in foreach(ref)) - $(LI $(BUGZILLA 6603): [CTFE] Can't call through a manifest constant function pointer) - $(LI $(BUGZILLA 6736): Regression(2.054): ICE (cgcod.c 1672) with alias this and certain structs) - $(LI $(BUGZILLA 6763): Using TypeTuple with (const/in/ref etc.) changes it forever) - $(LI $(BUGZILLA 6792): [CTFE] ICE with pointer cast of indexed array) - $(LI $(BUGZILLA 6800): [CTFE] dangerous pointer casts should be rejected) - $(LI $(BUGZILLA 6805): Can't use a type from opDispatch template) - $(LI $(BUGZILLA 6816): [CTFE] nested function can't access this) - $(LI $(BUGZILLA 6817): [CTFE] Error on interpreting inlined IfStatement) - $(LI $(BUGZILLA 6832): Can't test objects wrapped with alias this) - $(LI $(BUGZILLA 6836): map + UFCS = fail) - $(LI $(BUGZILLA 6837): alias this + UFCS = fail) - $(LI $(BUGZILLA 6851): [CTFE] Cannot deref pointer passed by argument) - $(LI $(BUGZILLA 6859): Segfault when abstract method uses with contract.) - $(LI $(BUGZILLA 6864): Const conversion should precedence over the shared one) - $(LI $(BUGZILLA 6865): inout matching removes shared qualifier) - $(LI $(BUGZILLA 6866): ICE(mtype.c): alias this and inout matching) - $(LI $(BUGZILLA 6867): inout and nested foreach loops) - $(LI $(BUGZILLA 6868): IsExp + incorrect static array type = error) - $(LI $(BUGZILLA 6870): type qualifiers behave inconsistently in combination with typeof) - $(LI $(BUGZILLA 6872): Breaking type parsing of shared(inout(int)[])) - $(LI $(BUGZILLA 6877): [XMM] regression, clobbered float value) - $(LI $(BUGZILLA 6879): The difference of between template matching and IsExp) - $(LI $(BUGZILLA 6881): [XMM] ICE with painted float) - $(LI $(BUGZILLA 6885): [CTFE] wrong code with dynamically allocated 2D array) - $(LI $(BUGZILLA 6886): [CTFE] ICE(interpret.c) new array with initializer) - $(LI $(BUGZILLA 6901): wrong error "override cannot be applied to variable" in CTFE forward reference) - $(LI $(BUGZILLA 6902): Different "pure nothrow int()" types) - $(LI $(BUGZILLA 6910): __traits(hasMember, "") does not work, if template has alias param) - $(LI $(BUGZILLA 6912): const(T)[] can be implicitly cast to inout(const(T)[])) - $(LI $(BUGZILLA 6919): [CTFE] Cannot get effect to local variable through its pointer) - $(LI $(BUGZILLA 6922): [TDPL] superimposing of const and immutable does not work correctly) - $(LI $(BUGZILLA 6927): Better @property management by chained functions) - $(LI $(BUGZILLA 6928): alias this, immutable and common type fail in presence of fields with indirections) - $(LI $(BUGZILLA 6929): [ICE] typeMerge crashes in presence of ambiguous alias this conversions) - $(LI $(BUGZILLA 6941): .stringof displays redundant storage classes) - $(LI $(BUGZILLA 6972): [CTFE] ICE with ubyte/=uint) - $(LI $(BUGZILLA 6994): Using explicit 'this' in template constraint causes an error) - $(LI $(BUGZILLA 6997): 64bit optimizer bug) - $(LI $(BUGZILLA 7004): Iterating tuple with index which explicitly typed as size_t causes an error) - $(LI $(BUGZILLA 7026): 64 bit optimizer bug) - $(LI $(BUGZILLA 7027): Struct member trySemantic() regression in DMD Git master) - $(LI $(BUGZILLA 7028): Fails to save FPU regs when executing finally block) - $(LI $(BUGZILLA 7072): [2.057 Beta] Assertion failure: '0' on line 145 in file 'mtype.c') - $(LI $(BUGZILLA 7093): aliased type sometimes isn't resolved) - ) -) - -$(VERSION 056, Oct 26, 2011, =================================================, - - $(WHATSNEW - $(LI add -gs compiler switch) - $(LI $(BUGZILLA 3194): invariant should be checked at the beginning and end of protected functions) - $(LI $(BUGZILLA 5399): Return the result of a nonvoid function in a void function) - $(LI $(BUGZILLA 6752): Add separate option to control stack frame generation) - $(LI std.exception: enforce/enforceEx now can use in @safe pure function.) - $(LI Added optional KeepTerminator param to std.string.splitLines.) - $(LI Added std.string.outdent.) - $(LI std.utf: More @safe and pure.) - $(LI std.windows.registry now use *W functions in order to deal properly with Unicode.) - ) - $(RUNTIMEBUGSFIXED - $(LI $(BUGZILLA 5967): Mangling of ArgClose for variadic function is swapped) - $(LI $(BUGZILLA 6493): Source code for the doc of core.time points to std.datetime.) - $(LI $(BUGZILLA 6466): core.demangle incorrect demangling of variables) - ) - $(LIBBUGSFIXED - $(LI $(BUGZILLA 5522): std.range.zip fails on arrays of Object.) - $(LI $(BUGZILLA 6009): std/container disabled on freebsd/64) - $(LI $(BUGZILLA 6160): std.conv.to: Ignore _ to match the rest of D) - $(LI $(BUGZILLA 6181): assert fails in datetime.d while runining Phobos unittest) - $(LI $(BUGZILLA 6258): std.conv.to!real("-") fetches the front of an empty array.) - $(LI $(BUGZILLA 6275): Const values in tuples) - $(LI $(BUGZILLA 6288): std.conv.to removes const/immutable when converting a class) - $(LI $(BUGZILLA 6609): std.conv.parse!Integer should consider sign when radix == 10) - $(LI $(BUGZILLA 6634): std.path.globMatch throws wrong assertion) - $(LI $(BUGZILLA 6640): More formatting consistency between string and range of char) - $(LI $(BUGZILLA 6761): Strange behavior of RedBlackTree causing a dangling pointer) - $(LI $(BUGZILLA 6819): BigInt ^^ fails for some big numbers (powers)) - ) - $(DMDBUGSFIXED - $(LI $(BUGZILLA 546): Error message for accessing a deprecated variable is doubled) - $(LI $(BUGZILLA 1339): Invariant/const-ness is broken by built-in array properties sort and reverse) - $(LI $(BUGZILLA 1891): Array-concatenation of T* and T*[] produces corrupted result) - $(LI $(BUGZILLA 1993): Error calling vararg delegate with null) - $(LI $(BUGZILLA 2315): DMD Stack Overflow on unwanted ctfe recursion) - $(LI $(BUGZILLA 2553): Excess attribute propagation for interfaces) - $(LI $(BUGZILLA 2361): delete is allowed on invariant references.) - $(LI $(BUGZILLA 2737): Nonsensical Error Message on Unsafe .idup) - $(LI $(BUGZILLA 2740): Template Mixins do not work as advertised) - $(LI $(BUGZILLA 2953): tuple.length rejected as a tuple parameter in a static foreach) - $(LI $(BUGZILLA 3069): Array literals do not implicitly cast to void[]) - $(LI $(BUGZILLA 3133): Compiler does not check that static array casts are legal) - $(LI $(BUGZILLA 3180): Covariance of delegates/function pointers) - $(LI $(BUGZILLA 3550): array.dup violates const/invariant without a cast.) - $(LI $(BUGZILLA 3659): Too much exegesis on opEquals) - $(LI $(BUGZILLA 3748): inout does not work properly) - $(LI $(BUGZILLA 4022): [CTFE] AA get) - $(LI $(BUGZILLA 4197): ICE(glue.c): error in forward-referenced in/out contract) - $(LI $(BUGZILLA 4206): type accepted as enum initializer) - $(LI $(BUGZILLA 4237): Typedefs of the same name cause initializer conflict) - $(LI $(BUGZILLA 4269): Regression(2.031): invalid type accepted if evaluated while errors are gagged) - $(LI $(BUGZILLA 4284): empty string[] alias lacks .length in a template) - $(LI $(BUGZILLA 5453): ICE(statement.c): invalid switch statement forward referenced by CTFE) - $(LI $(BUGZILLA 5696): Templates typetuple iteration) - $(LI $(BUGZILLA 5703): std.intrinsic. and core.bitop.bsf, bsr and bswap should be CTFE-able) - $(LI $(BUGZILLA 5886): Template this parameter cannot be made implicit, when other parameters are explicitly given) - $(LI $(BUGZILLA 5932): Internal error: s2ir.c 339) - $(LI $(BUGZILLA 6062): segv in dmd/64 with assoc array literals) - $(LI $(BUGZILLA 6073): Cannot pass __traits(parent, ...) as a template parameter if it is a module) - $(LI $(BUGZILLA 6084): Impossible to instantiate local template with TypeTuple-foreach iterator variable.) - $(LI $(BUGZILLA 6087): typeof(this) doesn't work outside member function) - $(LI $(BUGZILLA 6139): Duplicate error message on compile-time out of bounds array index) - $(LI $(BUGZILLA 6289): Make slices of const/immutable arrays mutable (but keep the elements const/immutable)) - $(LI $(BUGZILLA 6296): ICE(glue.c): invalid template instantiated in is(typeof()).) - $(LI $(BUGZILLA 6352): Regression(2.054) Implicit pure/nothrow/@safe messes up delegate arrays) - $(LI $(BUGZILLA 6360): @property is doubled in di files when used with auto) - $(LI $(BUGZILLA 6404): Cannot check ref-ness of auto ref parameter in template constraint) - $(LI $(BUGZILLA 6488): DMD compiler bug) - $(LI $(BUGZILLA 6518): break inside a static foreach inside a switch) - $(LI $(BUGZILLA 6529): writeln(const array of enums) too) - $(LI $(BUGZILLA 6584): ICE on large version number/debug level) - $(LI $(BUGZILLA 6596): Error message with not extern(C) function) - $(LI $(BUGZILLA 6599): Segfault: invalid expression in initializer) - $(LI $(BUGZILLA 6630): Assigning null to class with nested alias this class is misinterpreted) - $(LI $(BUGZILLA 6656): static alias this broken in 2.055) - $(LI $(BUGZILLA 6661): Templates instantiated only through is(typeof()) shouldn't cause errors) - $(LI $(BUGZILLA 6665): Regression(2.055) ICE(cg87.c): static double inside closure) - $(LI $(BUGZILLA 6672): [CTFE] ICE on compile time std.algorithm.sort) - $(LI $(BUGZILLA 6674): Regression(2.055) mixin and __traits(allMembers) generates incorrect result) - $(LI $(BUGZILLA 6675): Regression(2.054) ICE(glue.c) template parameter deduction with errors gagged) - $(LI $(BUGZILLA 6682): Template function that has lazy parameter is not inferred as pure) - $(LI $(BUGZILLA 6690): Using lazy parameter should be inferred as @safe) - $(LI $(BUGZILLA 6691): static constructor inside template cannot initialize immutable template members) - $(LI $(BUGZILLA 6693): [CTFE] Cannot set value to nested AA) - $(LI $(BUGZILLA 6695): typeof(this) does not take into account const/immutable attributes inside member functions) - $(LI $(BUGZILLA 6698): Regression(2.053): segfault with naked asm in inner function) - $(LI $(BUGZILLA 6700): Regression(2.053) using $ inside a slice of a tuple) - $(LI $(BUGZILLA 6719): "Error: out of memory" in parsing) - $(LI $(BUGZILLA 6721): [CTFE] Cannot get pointer to start of char[]) - $(LI $(BUGZILLA 6727): [CTFE] ICE(interpret.c): assignment from string literal.dup.ptr) - $(LI $(BUGZILLA 6733): Regression(2.054) ICE(cod2.c) pure nothrow func with side-effect parameters) - $(LI $(BUGZILLA 6739): [CTFE] Cannot set a value to an outer AA of a nested AA) - $(LI $(BUGZILLA 6746): static this() inside struct skipped upon static method call) - $(LI $(BUGZILLA 6749): [CTFE] problem with array of structs) - $(LI $(BUGZILLA 6751): [CTFE] ref argument of AA doesn't work) - $(LI $(BUGZILLA 6753): Regression(2.055beta) "Reinterpret" cast of array to a tail const one doesn't work inside @trusted) - $(LI $(BUGZILLA 6759): missing initialization in foreach with alias this) - $(LI $(BUGZILLA 6765): [CTFE]: AA.length doesn't compile when AA is null) - $(LI $(BUGZILLA 6769): [CTFE] AA.keys doesn't compile when -inline is used) - $(LI $(BUGZILLA 6770): inout is allowed on fields) - $(LI $(BUGZILLA 6773): inout variable should not be modifiable) - $(LI $(BUGZILLA 6775): [CTFE] foreach over an AA fails to compile) - $(LI $(BUGZILLA 6782): inout-correct range is not iterable using foreach with type deduction inside non-inout function) - $(LI $(BUGZILLA 6813): Yet another "cannot get frame pointer" error) - $(LI $(BUGZILLA 6822): New ubuntu linking rules prevent dmd from linking programs on Ubuntu 11.10) - $(LI $(BUGZILLA 6825): Regression(2.055+): Address of templated method incorrectly taken) - ) -) - -$(VERSION 055, Sep 4, 2011, =================================================, - - $(WHATSNEW - $(LI Added $(LINK2 http://www.digitalmars.com/ctg/dman.html, dman)) - $(LI Add support for Mac OS X 10.7 Lion) - $(LI Add protection to json output) - $(LI Add SSE4.1 and SSE4.2 assembly instructions) - $(LI $(BUGZILLA 4375): Require explicit braces when 'else' is ambiguous) - - $(LI std.algorithm.copy now specializes on arrays for 10-80x improved - performance.) - $(LI std.path has been rewritten from scratch and has a completely new API.) - $(LI std.utf.toUTFz allows you to get a zero-terminated string of any - character type and of any type of mutability.) - $(LI Added symlink and readLink to std.file for Posix systems.) - $(LI Values for GDC and LDC were added to std.compiler.Vendor.) - $(LI Added functions to std.bitswap for generically handling swapping - endianness.) - $(LI Added std.parallelism.TaskPool.workerIndex.) - $(LI Added buffer recycling overload of std.parallelism.asyncBuf) - $(LI std.math.tgamma, lgamma, erf, and erfc are now deprecated. The - equivalent functions in std.mathspecial should be used instead.) - $(LI The names of the values of std.mmfile.Mode, std.system.Endian, - std.traits.FunctionAttributes, std.traits.ParameterStorageClass, - and std.traits.Variadic were changed to match Phobos' naming conventions.) - $(LI std.range: Added indexed and chunks) - $(LI std.string.translate has been updated to work with unicode. As a - result, its signature has been changed. The old version and - std.string.maketrans have been scheduled for deprecation.) - $(LI std.string.tr has been updated so that it works with any string type.) - $(LI std.conv.parse works for associative array and static array) - $(LI std.format: Improvement of formatValue and unformatValue. - They now works for associative array, consider element escaping, - and treat range format spec more properly.) - $(LI std.complex: added sin(), cos(), sqrt()) - $(LI md5: 1.4X speedup) - ) - $(RUNTIMEBUGSFIXED - $(LI $(BUGZILLA 5967): Mangling of ArgClose for variadic function is swapped) - $(LI $(BUGZILLA 6493): Source code for the doc of core.time points to std.datetime.) - $(LI $(BUGZILLA 6466): core.demangle incorrect demangling of variables) - ) - $(LIBBUGSFIXED - $(LI Unlisted bug: std.range.transversal should have length) - $(LI $(BUGZILLA 3890): Bad writeln of a nested struct) - $(LI $(BUGZILLA 4500): scoped moves class after calling the constructor) - $(LI $(BUGZILLA 4977): cannot use nothrow or pure with Rebindable) - $(LI $(BUGZILLA 5237): writefln doesn't respect Complex.toString) - $(LI $(BUGZILLA 5645): std.range.drop()) - $(LI $(BUGZILLA 5825): write is calling a deprecated function) - $(LI $(BUGZILLA 6040): std.cpuid and core.cpuid return different values for some methods) - $(LI $(BUGZILLA 6064): std.array.join is unnecssarily slow for strings) - $(LI $(BUGZILLA 6194): [GSoC] Destructor gets called on object before it is copied when calling writeln()) - $(LI $(BUGZILLA 6261): [2.054 beta regression] Regex cannot take a char[]) - $(LI $(BUGZILLA 6301): Cannot 'zip'/'retro'/'stride' etc. a range having 'ulong' length.) - $(LI $(BUGZILLA 6377): std.conv.to should check range when changing signedness) - $(LI $(BUGZILLA 6424): std.traits.hasElaborateAssign is limited) - $(LI $(BUGZILLA 6448): writef("%05d", BigInt) problem) - $(LI $(BUGZILLA 6514): CTFE dot product) - $(LI $(BUGZILLA 6587): std.parallelism's Task cannot handle immutable values) - $(LI $(BUGZILLA 6606): RefCounted doesn't work with unions due to use of format) - $(LI $(BUGZILLA 6608): Tuple field is not escaped) - ) - $(DMDBUGSFIXED - $(LI $(BUGZILLA 1471): Linker error on template function. Error 42: Symbol Undefined ...) - $(LI $(BUGZILLA 1567): call to private super-constructor should not be allowed) - $(LI $(BUGZILLA 1684): offsetof does not work, adding cast is workaround) - $(LI $(BUGZILLA 1904): wrong protection lookup for private template functions) - $(LI $(BUGZILLA 2156): [] and null should be accepted where a compile-time string is required) - $(LI $(BUGZILLA 2234): __traits(allMembers) returns incorrect results for mixin and template alias members of an aggregate) - $(LI $(BUGZILLA 2245): Bug with overloaded, mixin template functions in classes) - $(LI $(BUGZILLA 2246): Regression(2.046, 1.061): Specialization of template to template containing int arguments fails) - $(LI $(BUGZILLA 2540): super can not be using in alias statement) - $(LI $(BUGZILLA 2634): Function literals are non-constant.) - $(LI $(BUGZILLA 2355): is() doesn't resolve aliases before template matching) - $(LI $(BUGZILLA 2579): Template function accepting a delegate with in argument doesn't compile) - $(LI $(BUGZILLA 2774): Functions-as-properties makes it impossible to get the .mangleof a function) - $(LI $(BUGZILLA 2777): alias this doesn't forward __dollar and slice op.) - $(LI $(BUGZILLA 2781): alias this doesn't work with foreach) - $(LI $(BUGZILLA 2787): Members found in an 'alias this' are not implicitly accessible in methods) - $(LI $(BUGZILLA 2941): Wrong code for inline asm because CPU type is set too late) - $(LI $(BUGZILLA 3268): can't compare pointer to functions when one is const) - $(LI $(BUGZILLA 3273): Regression(2.031): struct invariant + dtor fails to compile (no line number)) - $(LI $(BUGZILLA 3512): dchar iteration over string in CTFE fails) - $(LI $(BUGZILLA 3661): ^^ not supported in array operations.) - $(LI $(BUGZILLA 3797): Regression(2.038): Implicit conversion between incompatible function pointers) - $(LI $(BUGZILLA 4021): [CTFE] AA rehash) - $(LI $(BUGZILLA 4099): Inconsistent behaviour of ++/-- when mixing opUnary and 'alias this'.) - $(LI $(BUGZILLA 4444): Cannot index built-in array with expression tuple) - $(LI $(BUGZILLA 4460): Regression(2.036) ICE(e2ir.c) when compiling foreach over associative array literal) - $(LI $(BUGZILLA 4682): [CTFE] Run-time Vs Compile-time of int.min % -1) - $(LI $(BUGZILLA 4773): Rebindable should be castable to bool) - $(LI $(BUGZILLA 4837): ICE(constfold.c) CTFE with >>>=) - $(LI $(BUGZILLA 4984): Recursive template constraint results in dmd running out of memory) - $(LI $(BUGZILLA 5046): Wrong type of implicit 'this' in struct/class templates) - $(LI $(BUGZILLA 5081): Pure functions as initializers for immutable structures) - $(LI $(BUGZILLA 5188): alias this and compare expression generates wrong code) - $(LI $(BUGZILLA 5239): optimizer misreports an used before set error) - $(LI $(BUGZILLA 5373): Regression (2.051) CTFE and std.string.replace() causes "Bad binary function q{a == b}..) - $(LI $(BUGZILLA 5440): ICE(template.c): when struct AssociativeArray is missing from object.d) - $(LI $(BUGZILLA 5585): bad debug line number info for return statements with enumerator expressions) - $(LI $(BUGZILLA 5745): Missing error line number with lazy argument) - $(LI $(BUGZILLA 5750): Allow pure functions to have lazy arguments) - $(LI $(BUGZILLA 5777): Move semantics require full spec NRVO) - $(LI $(BUGZILLA 5785): Lexing or Parsing issue with UFCS) - $(LI $(BUGZILLA 5790): 'Error: variable result used before set' when -release -inline -O) - $(LI $(BUGZILLA 5799): Address-of operator fails on nested conditional operator expression) - $(LI $(BUGZILLA 5936): Regression(2.050): Segfault when forward-referencing pure auto-return member function with parameter.) - $(LI $(BUGZILLA 5953): Too many trailing commas are accepted) - $(LI $(BUGZILLA 6097): SSSE3 not working with MMX instructions) - $(LI $(BUGZILLA 6215): LLVM-compiled DMD segfaults due to mem.c alignment issues) - $(LI $(BUGZILLA 6220): Regression(2.053) static foreach over a string[] no longer produces directly usable strings) - $(LI $(BUGZILLA 6228): Regression(2.053) ICE(e2ir.c) on {auto x = (*ptr) ^^ y} with const integer types) - $(LI $(BUGZILLA 6230): Member functions can no longer be weakly pure) - $(LI $(BUGZILLA 6250): [CTFE] Crash when swapping two pointers to arrays.) - $(LI $(BUGZILLA 6265): Pure-inference failed when calling other pure functions) - $(LI $(BUGZILLA 6270): XMMREGS not preserved on indirect function call) - $(LI $(BUGZILLA 6276): [CTFE] Strange behavior of using ~= operator twice) - $(LI $(BUGZILLA 6280): [CTFE] Cannot put 'in' expression of AA in an 'if' condition) - $(LI $(BUGZILLA 6281): [CTFE] A null pointer '!is null' returns 'true'.) - $(LI $(BUGZILLA 6282): [CTFE] ICE when dereferencing a pointer to reference type from 'in' of an AA) - $(LI $(BUGZILLA 6283): [CTFE][Regression 2.054] Failed to assign to AA using a constness-changed array as key) - $(LI $(BUGZILLA 6284): [Regression 2.054] 'pure' does not work with 'with' statement) - $(LI $(BUGZILLA 6286): Regression(2.054): Static arrays can not be assigned from const(T)[N] to T[N]) - $(LI $(BUGZILLA 6293): [Regression 2.054] The expression x.y makes the function impure when the 'x' part is not just a variable) - $(LI $(BUGZILLA 6295): [Regression 2.054] Segfault in checkPurity() of template value parameter) - $(LI $(BUGZILLA 6306): Regression(2.054): [CTFE] Strange behavior of indirect recursive call in CTFE) - $(LI $(BUGZILLA 6308): Destruction of temporaries on exception causes unhandled access violation) - $(LI $(BUGZILLA 6316): Regression(2.054): Class downcast is rejected in @safe code) - $(LI $(BUGZILLA 6317): ICE on struct literal of nested struct) - $(LI $(BUGZILLA 6331): [CTFE] Cannot evaluate SliceExp on if condition) - $(LI $(BUGZILLA 6337): [CTFE] ICE when touching member variable of struct during CTFE) - $(LI $(BUGZILLA 6344): [CTFE] Assertion Failure in interpret.c when create an empty slice from null pointer) - $(LI $(BUGZILLA 6351): Regression(2.054) Segfault: Vararg delegate as template param) - $(LI $(BUGZILLA 6355): Template constructor cannot initialize non-mutable field) - $(LI $(BUGZILLA 6366): alias this doesn't work with foreach range.front) - $(LI $(BUGZILLA 6369): alias this doesn't work with initializer) - $(LI $(BUGZILLA 6374): [CTFE] Cannot subscript using pointer to array) - $(LI $(BUGZILLA 6375): [CTFE] Segfault when using std.array.appender with an initial array) - $(LI $(BUGZILLA 6386): [CTFE] ICE on pointer casting) - $(LI $(BUGZILLA 6389): Segfault(dsymbol.c): deprecated @disable) - $(LI $(BUGZILLA 6399): [CTFE] struct member array.length -= x doesn't work, while array[0..$-x] works) - $(LI $(BUGZILLA 6404): Cannot check ref-ness of auto ref parameter in template constraint) - $(LI $(BUGZILLA 6418): [CTFE] Cannot call a struct member function with name 'length'.) - $(LI $(BUGZILLA 6420): [CTFE] ICE on dereference-assigning to a pointer casted from a literal ) - $(LI $(BUGZILLA 6429): Nested function error in reduce) - $(LI $(BUGZILLA 6433): Meta-Bug AA type propagation) - $(LI $(BUGZILLA 6434): opDispatch must be considered before alias this.) - $(LI $(BUGZILLA 6491): Fully qualified values in default arguments of non-template functions are generated with an extra 'module' keyword) - $(LI $(BUGZILLA 6499): [GSoC] Destructor not called on object returned by method.) - $(LI $(BUGZILLA 6505): Wrong code for expression involving 8 floats, only with -O) - $(LI $(BUGZILLA 6508): alias this doesn't work with AssignExp rhs) - $(LI $(BUGZILLA 6510): [CTFE] "internal error: illegal stack value" when compiled with -inline) - $(LI $(BUGZILLA 6511): [CTFE] Array op gives wrong result) - $(LI $(BUGZILLA 6512): [CTFE] new T[][] doesn't work) - $(LI $(BUGZILLA 6516): Regression(2.055 beta) [CTFE] ICE(constfold.c) involving new dchar[]) - $(LI $(BUGZILLA 6517): [CTFE] ptr++ doesn't work but ++ptr does) - $(LI $(BUGZILLA 6546): alias this + IdentityExpression doesn't work) - $(LI $(BUGZILLA 6556): ICE for ImportStatement in DebugStatement) - $(LI $(BUGZILLA 6558): [CTFE] UTF-decoding foreach gives wrong index (1-indexed)) - $(LI $(BUGZILLA 6561): alias this + undefined symbol should cause error) - $(LI $(BUGZILLA 6563): wrong code when using at least 8 XMM regs) - $(LI $(BUGZILLA 6577): 'Cannot initialize member' error line number) - $(LI $(BUGZILLA 6601): Regression(2.053): CTFE segfault taking address of function template) - $(LI $(BUGZILLA 6602): Invalid template instantiations leaked by is(typeof())/__traits(compiles, )/Type::trySemantic) - ) -) - -$(VERSION 054, Jul 10, 2011, =================================================, - - $(WHATSNEW - $(LI Implement @safe) - $(LI Implement @property) - $(LI Automatic inference for @safe, pure, nothrow) - $(LI Allow labelled break and continue in CTFE) - $(LI Warn about switch case fallthrough) - $(LI Pointers are now supported in CTFE) - $(LI Heap-allocated structs are now supported in CTFE) - $(LI Added SSSE3 instructions to inline assembler) - $(LI Change from warning to deprecated: non-final switch statements must have a default statement) - $(LI Change from warning to deprecated: function is hidden by function) - $(LI Add warning about switch case fallthrough) - $(LI Add warning about calling pure nothrow functions and ignoring the result) - $(LI Allow associative arrays with key of type bool) - $(LI Added inference for purity and safety) - $(LI Change win32 dmd to not emit a map file unless asked for with -map) - $(LI Added $(B -property) switch) - $(LI $(BUGZILLA 5823): @property call syntax restriction not implemented) - - $(LI Added core.sys.posix.netdb) - $(LI For functions which have a version which takes a core.time.Duration - and another version which takes an integral value, the version which - takes an integral value is now scheduled for deprecation.) - - $(LI std.array.insertInPlace supports inserting of multiple ranges/elements in one go) - $(LI Added std.array.uninitializedArray and std.array.minimallyInitializedArray) - $(LI Various functions in std.string were renamed to match Phobos' - naming conventions and be properly camelcased. The old names - are still there but have been scheduled for deprecation.) - $(LI Various functions in std.uni were renamed so that they don't have - "Uni" in their name, since it was decided that it was not desirable to - repeat a module's name in its functions' names. The old names - are still there but have been scheduled for deprecation.) - $(LI std.ctype has been scheduled for deprecation. std.ascii has been - added to replace it.) - $(LI Major performance improvements for std.algorithm.sort) - $(LI std.string.atoi has been removed; replace it with std.conv.to!int) - $(LI Switched to using posix.mak instead of various .mak files) - ) - $(RUNTIMEBUGSFIXED - $(LI $(BUGZILLA 4323): std.demangle incorrectly handles template floating point numbers) - $(LI $(BUGZILLA 5272): Postblit not called on copying due to array append) - $(LI $(BUGZILLA 5956): Undocumented mangling of struct value) - $(LI $(BUGZILLA 6135): Thread/GC interaction bug on OS X) - ) - $(LIBBUGSFIXED - $(LI $(BUGZILLA 2108): regexp.d: The greedy dotstar isn't so greedy) - $(LI $(BUGZILLA 3136): Incorrect and strange behavior of std.regexp.RegExp if using a pattern with optional prefix and suffix longer than 1 char) - $(LI $(BUGZILLA 3457): rdmd fails silently in a particular setup where the compiler is not the expected) - $(LI $(BUGZILLA 3479): writef/writefln: positional precision not working) - $(LI $(BUGZILLA 3564): Rdmd failing to link external C libraries) - $(LI $(BUGZILLA 3752): File.byLine fetches lines in a confusing manner) - $(LI $(BUGZILLA 4367): std.regex: Captures is not a random access range) - $(LI $(BUGZILLA 4574): std.regex: breaks with empy string regex) - $(LI $(BUGZILLA 4608): std.string.chomp documentation mismatch implementation) - $(LI $(BUGZILLA 5019): In std.regex, empty capture at end of string causes error) - $(LI $(BUGZILLA 5059): String assignment in foreach loop breaks immutability) - $(LI $(BUGZILLA 5458): scope for function parameters is not documented) - $(LI $(BUGZILLA 5511): std.regex optional capture with no-match cause error) - $(LI $(BUGZILLA 5598): rdmd does not fail on invalid filename) - $(LI $(BUGZILLA 5673): Add lookahead and forgetful matching support std.regex) - $(LI $(BUGZILLA 5705): Swapping identical struct with hasElaborateAssign causes "overlapping array copy" exception) - $(LI $(BUGZILLA 5836): std.typetuple.staticIndexOf's example code missing %s in call to writefln) - $(LI $(BUGZILLA 5857): std.regex (...){n,m} is bogus when (...) contains repetitions) - $(LI $(BUGZILLA 5869): std.thread needs to be removed) - $(LI $(BUGZILLA 6026): DLL example needs update due to missing core.dll_helper) - $(LI $(BUGZILLA 6076): regression, std.regex: "c.*|d" matches "mm") - $(LI $(BUGZILLA 6101): Documentation for dead modules still distributed with DMD) - $(LI $(BUGZILLA 6113): singletons in std.datetime are not created early enough) - $(LI $(BUGZILLA 6193): Appender.clear() functionality or documentation) - ) - $(DMDBUGSFIXED - $(LI $(BUGZILLA 693): 'this' can't be used as an alias parameter for a mixin) - $(LI $(BUGZILLA 1373): typeof(func).stringof fails when func has parameters.) - $(LI $(BUGZILLA 1411): ref Tuple should transform to Tuple of ref's) - $(LI $(BUGZILLA 1570): Wrong return for address operator) - $(LI $(BUGZILLA 2180): filename error with #line) - $(LI $(BUGZILLA 2521): Not possible to return immutable value by ref) - $(LI Temp destructors now called if exception is thrown) - $(LI $(BUGZILLA 2625): Creating new struct with literal bypasses immutability of members if struct is in array) - $(LI $(BUGZILLA 3147): Incorrect value range propagation for addition) - $(LI $(BUGZILLA 3359): Cannot parse pure/const/immutable functions with inferred return type) - $(LI $(BUGZILLA 3445): partial fix) - $(LI $(BUGZILLA 3511): ref return property confused with property setter) - $(LI $(BUGZILLA 3632): modify float is float to do a bitwise compare) - $(LI $(BUGZILLA 3688): Can't have declaration with assignment to const/immutable inside if condition) - $(LI $(BUGZILLA 3722): A method without an in contract should always succeed, even if overridden) - $(LI $(BUGZILLA 3799): isStaticFunction trait evaluates to true for non-static nested functions) - $(LI $(BUGZILLA 4031): Should be able to access const value-type globals from pure functions) - $(LI $(BUGZILLA 4040): const/immutable on the right in auto return class methods) - $(LI $(BUGZILLA 4063): [CTFE] key not found in AA gives bad error message) - $(LI $(BUGZILLA 4065): [CTFE] AA "in" operator doesn't work) - $(LI $(BUGZILLA 4107): Duplicate documentation for member function templates) - $(LI $(BUGZILLA 4132): pointer arithmetic accepted in @safe functions) - $(LI $(BUGZILLA 4170): Missing line number on compile-time array index) - $(LI $(BUGZILLA 4258): "auto ref" doesn't work in one or more cases) - $(LI $(BUGZILLA 4448): [CTFE] labeled break doesn't work in CTFE) - $(LI $(BUGZILLA 4494): ICE(cod1.c) Array literal filled with results of void function) - $(LI $(BUGZILLA 4633): typeof({return 1;}()) declaration fails if inside main) - $(LI $(BUGZILLA 4661): Array Literal Incompatible Type Error Msg Should Include Line Number) - $(LI $(BUGZILLA 4706): Overloading auto return w/ non-auto return = strange error msg) - $(LI $(BUGZILLA 4745): Non-uniform handling of commas in static initialization of structs) - $(LI $(BUGZILLA 4885): Uninitialize Pointers Allowed in @safe code) - $(LI $(BUGZILLA 4910): [CTFE] Cannot evaluate a function that has failed at once) - $(LI $(BUGZILLA 4963): ICE(type.c:320) for struct append where T.sizeof < 3) - $(LI $(BUGZILLA 4969): nothrow check can't handle multiple catches) - $(LI $(BUGZILLA 5088): Cannot cast const(int) to long in @safe function) - $(LI $(BUGZILLA 5258): [CTFE] Stack overflow with struct by ref) - $(LI $(BUGZILLA 5284): Array ops punch through const system) - $(LI $(BUGZILLA 5327): Creating new struct with literal bypasses immutability of members of members of the struct) - $(LI $(BUGZILLA 5396): [CTFE] Invalid code with nested functions in CTFE) - $(LI $(BUGZILLA 5415): @Safe functions not working) - $(LI $(BUGZILLA 5497): -- now produces error message instead of wrong code) - $(LI $(BUGZILLA 5551): opUnary-opBinary conflict) - $(LI $(BUGZILLA 5574): Struct destructor freaks out when an array of struct with single element is instantiated inside a class) - $(LI $(BUGZILLA 5615): [CTFE] std.string.indexOf broken at compile time) - $(LI $(BUGZILLA 5633): [CTFE] ICE(constfold.c): is expression with struct, struct pointer, array literal...) - $(LI $(BUGZILLA 5657): Temporary object destruction) - $(LI $(BUGZILLA 5659): Conditional operator, array literal, and std.traits.CommonType return a wrong common type) - $(LI $(BUGZILLA 5676): [CTFE] segfault using tuple containing struct that has opAssign) - $(LI $(BUGZILLA 5682): [CTFE] Silently wrong result possibly related to operator overloading and expression order) - $(LI $(BUGZILLA 5693): Segfault with address of template struct opCall) - $(LI $(BUGZILLA 5708): [CTFE] Incorrect string constant folding with -inline) - $(LI $(BUGZILLA 5771): Template constructor and auto ref do not work) - $(LI $(BUGZILLA 5819): DMD doesn't error/warn about illegal asm for 64bit mode) - $(LI $(BUGZILLA 5845): Regression(2.041) [CTFE] "stack overflow" with recursive ref argument) - $(LI $(BUGZILLA 5856): overloading on const doesn't work for operator overload) - $(LI $(BUGZILLA 5859): Declaration inside if condition doesn't call destructor) - $(LI $(BUGZILLA 5861): Wrong filename in error message when an invalid delegate in a template parameter is typeof()-ed) - $(LI $(BUGZILLA 5885): wrong codegen for OPu32_d) - $(LI $(BUGZILLA 5897): unrelated struct type casting should ignite construction) - $(LI $(BUGZILLA 5936): Invalid code with nested functions in CTFE) - $(LI $(BUGZILLA 5946): failing lookup 'this' from function in template) - $(LI $(BUGZILLA 5954): [CTFE] enum structs with ctor) - $(LI $(BUGZILLA 5959): Return by reference with nested function should be allowed) - $(LI $(BUGZILLA 5962): Template function declaration with prefixed storage class and auto occurs conflict) - $(LI $(BUGZILLA 5963): iasm does not accept 64bit integer literal) - $(LI $(BUGZILLA 6001): [CTFE] ICE(interpret.c) mutating ref array) - $(LI $(BUGZILLA 6015): [CTFE] Strange behavior of assignment appears in a situation) - $(LI $(BUGZILLA 6049): [CTFE] Array literals of structs with invariant() are wrong) - $(LI $(BUGZILLA 6052): [CTFE] Struct elements in an array are treated like reference type) - $(LI $(BUGZILLA 6053): [CTFE] Two ICEs involving pointers (dereference and assign; pointer variable on stack)) - $(LI $(BUGZILLA 6054): [CTFE] ICE when returning a returned compile-time associative array containing a key of an idup-ed array literal) - $(LI $(BUGZILLA 6059): Incompatible types in array literal shows __error and error) - $(LI $(BUGZILLA 6072): [CTFE] Regression(git master): Cannot declare variable inside an 'if' condition) - $(LI $(BUGZILLA 6075): Cannot set value to associative array from a weakly-pure function when the value type has a (pure) opAssign) - $(LI $(BUGZILLA 6077): [CTFE] Cannot append null array to null array.) - $(LI $(BUGZILLA 6078): [CTFE] ICE on foreach over array struct member which is null) - $(LI $(BUGZILLA 6079): [CTFE] Array index out of bound detection is off-by-one) - $(LI $(BUGZILLA 6090): DDoc parenthesis escape issues.) - $(LI $(BUGZILLA 6100): [CTFE] Regression: struct return values wrong if used in array initializer) - $(LI $(BUGZILLA 6109): 'nothrow' does not check slice indices) - $(LI $(BUGZILLA 6111): Escaping reference to local variable not detected) - $(LI $(BUGZILLA 6119): Assertion failure: '0' on line 1118 in file 'glue.c') - $(LI $(BUGZILLA 6120): [CTFE] ICE on calling constructor of template struct with -inline in function/delegate literal.) - $(LI $(BUGZILLA 6123): [CTFE] Cannot call a template member method inside delegate/function literal with -inline.) - $(LI $(BUGZILLA 6137): [CTFE] Foreach on semantically wrong initialized array crashes the compiler) - $(LI $(BUGZILLA 6145): Meaningless second error message for complex size of static array) - $(LI $(BUGZILLA 6150): runnable/testsocket.d) - $(LI $(BUGZILLA 6158): winsamp and dhry samples need an update) - $(LI $(BUGZILLA 6161): iasm opcode family Jcc use absolute address instead of relative for functions) - $(LI $(BUGZILLA 6164): [CTFE] Local arrays in a recursive local function behave funny) - $(LI $(BUGZILLA 6198): [GSoC] ICE(e2ir.c) With circular import) - $(LI $(BUGZILLA 6229): %= and /= no longer work on char type) - $(LI $(BUGZILLA 6230): Member functions can no longer be weakly pure) - $(LI $(BUGZILLA 6234): 64-bit array append generates inline code to copy new data, but does not call postblit) - $(LI $(BUGZILLA 6241): test sdtor.d on osx not catching) - $(LI $(BUGZILLA 6242): Disallow inoperant "in" contracts) - $(LI $(BUGZILLA 6264): ICE on testing opSlice in static if) - $(LI $(BUGZILLA 6267): Can't increment alias this'd struct from ref return) - $(LI $(BUGZILLA 6279): Regression(2.054 beta): array-vararg with pointer type not working in safe code) - ) -) - -$(VERSION 053, May 12, 2011, =================================================, - - $(WHATSNEW - $(LI Added 64 bit tools to Linux) - $(LI Added FreeBSD support) - $(LI Renamed linux/bin to linux/bin32, added linux/bin64) - $(LI osx/lib32 renamed back to osx/lib) - $(LI Added some gc benchmark apps) - $(LI Move std.intrinsic to core.intrinsic) - $(LI Implemented $(I exception chaining), as described in TDPL for Posix.) - $(LI Added $(CODE parent) to $(CODE __traits) for QtD support) - $(LI Allow impure code inside debug conditionals) - $(LI Added cmpxchg16b, 64 bit bswap and movq instructions to internal assembler) - $(LI Added bindings for libcurl: etc.c.curl) - $(LI Added std.net.isemail) - $(LI Added std.parallelism) - $(LI Added support for positional parameter intervals, e.g. %1:3$s - prints the first three parameters using the 's' format specifier) - $(LI Added findSplit, findSplitBefore, findSplitAfter to std.algorithm; - improved walkLength) - $(LI Improved online documentation for std.algorithm) - $(LI Added roundRobin, takeOne, and takeNone to std.range; improved - stride) - $(LI Added unsigned to std.traits) - $(LI Removed std.iterator. Use either std.range.ElementType or std.range.ElementEncodingType - depending on what you're trying to do.) - $(LI $(BUGZILLA 2656): Remove octal literals) - $(LI $(BUGZILLA 4097): Error: can only declare type aliases within static if conditionals) - $(LI $(BUGZILLA 4360): Allow intrinsics in core.bitop to operate as intrinsics) - $(LI $(BUGZILLA 4833): dmd -od doesn't make it to optlink's command line for map files) - ) - $(RUNTIMEBUGSFIXED - $(LI $(BUGZILLA 5612): core.cpuid not implemented on 64) - $(LI $(BUGZILLA 1001): print stack trace (in debug mode) when program die) - $(LI $(BUGZILLA 5847): Threads started by core.thread should have same floating point state as main thread) - ) - $(LIBBUGSFIXED - $(LI $(BUGZILLA 4644): assertExceptionThrown to assert that a particular exception was thrown) - $(LI $(BUGZILLA 4944): Missing tzname even though we have tzset) - $(LI $(BUGZILLA 5451): Three ideas for RedBlackTree) - $(LI $(BUGZILLA 5474): unaryFun byRef is borked for custom parameter name) - $(LI $(BUGZILLA 5485): TLS sections handled incorrectly in FreeBSD) - $(LI $(BUGZILLA 5616): std.datetime: not cross-platform) - $(LI $(BUGZILLA 5654): BigInt returns ZERO with strings of single digit number with leading zeros) - $(LI $(BUGZILLA 5661): std.algorithm.move does not work on elaborate struct) - $(LI $(BUGZILLA 5731): std.datetime.SysTime prints UTC offsets backwards) - $(LI $(BUGZILLA 5761): std.datetime: Date.this(int day) conversion fails for Dec 30 of leap years) - $(LI $(BUGZILLA 5780): [patch] std.traits.hasIndirections incorrectly handles static arrays) - $(LI $(BUGZILLA 5781): std.datetime: On Windows, times off by one hour in some years due to DST rule changes) - $(LI $(BUGZILLA 5794): std.datetime StopWatch (and perhaps benchmark) examples need a small fix) - $(LI $(BUGZILLA 5928): Bigint modulo problem -- critical wrong-code bug) - ) - $(DMDBUGSFIXED - $(LI $(RED Note:) Although temporaries are destroyed now, they are not destroyed when - exceptions are thrown. This is scheduled to be fixed.) - $(LI $(BUGZILLA 2436): Unexpected OPTLINK termination EIP = 00425303 with /co) - $(LI $(BUGZILLA 3372): optlink silently mistreats object files with more than 16384 symbols) - $(LI $(BUGZILLA 4275): Unexpected optlink termination when 'export' attribute is missing) - $(LI $(BUGZILLA 4808): UNEXPECTED OPTLINK TERMINATION AT EIP=0042787B) - $(LI $(BUGZILLA 5670): Optlink 8.00.11 crash) - - $(LI $(BUGZILLA 937): C-style variadic functions broken) - $(LI $(BUGZILLA 1330): Array slicing does not work the same way in CTFE as at runtime) - $(LI $(BUGZILLA 1336): Inconsistent __traits usage) - $(LI $(BUGZILLA 1389): Can't use mixin expressions when start of a statement.) - $(LI $(BUGZILLA 1880): templates instantiated with non-constants should fail sooner) - $(LI $(BUGZILLA 2257): Template value parameters behave like alias parameters) - $(LI $(BUGZILLA 2414): enum is dynamically evaluated, yum) - $(LI $(BUGZILLA 2526): non-const initializer to constant accepted inside template) - $(LI $(BUGZILLA 2706): invalid template instantiation (and declaration?) is not rejected) - $(LI $(BUGZILLA 2733): Unclear semantics of template value parameters) - $(LI $(BUGZILLA 2841): char[] incorrectly accepted as a template value argument in D2) - $(LI $(BUGZILLA 2850): bad codegen for struct static initializers) - $(LI $(BUGZILLA 2990): TypeInfo.init() returns invalid array) - $(LI $(BUGZILLA 3086): TypeInfo opEquals returns incorrect results) - $(LI $(BUGZILLA 3214): Incorrect DWARF line number debugging information on Linux) - $(LI $(BUGZILLA 3271): Struct initializers silently fail) - $(LI $(BUGZILLA 3516): Destructor not called on temporaries) - $(LI $(BUGZILLA 3792): Regression(1.053) "non-constant expression" for a template inside a struct using a struct initializer) - $(LI $(BUGZILLA 3779): ["123"][0][$-1] causes __dollar unresolved in compile-time) - $(LI $(BUGZILLA 3801): CTFE: this.arr[i] cannot be evaluated at compile time for structs) - $(LI $(BUGZILLA 3835): ref foreach does not work in CTFE) - $(LI $(BUGZILLA 4033): Error: base class is forward referenced) - $(LI $(BUGZILLA 4050): [CTFE] array struct member slice update) - $(LI $(BUGZILLA 4051): [CTFE] array struct member item update) - $(LI $(BUGZILLA 4097): Error: can only declare type aliases within static if conditionals) - $(LI $(BUGZILLA 4140): Error: non-constant expression "hello"[1u..__dollar]) - $(LI $(BUGZILLA 4298): Constant array translated to unnecessary array literal creation) - $(LI $(BUGZILLA 4322): "void initializer has no value" on struct/union members initialized to "void") - $(LI $(BUGZILLA 4329): Do not show error messages that refer to __error) - $(LI $(BUGZILLA 4360): Allow intrinsics in core.bitop to operate as intrinsics) - $(LI $(BUGZILLA 4437): copy construction bug with "return this;") - $(LI $(BUGZILLA 4499): calls to @disabled postblit are emitted) - $(LI $(BUGZILLA 4543): Regression(1.054, 2.038) typedef causes circular definition and segfault) - $(LI $(BUGZILLA 4750): fail_compilation/fail225.d causes dmd to segv) - $(LI $(BUGZILLA 4815): CodeView: Global and Static symbols should have unmangled names) - $(LI $(BUGZILLA 4817): CodeView: Enum members should have simple names) - $(LI $(BUGZILLA 4833): dmd -od doesn't make it to optlink's command line for map files) - $(LI $(BUGZILLA 4917): Symbol conflict error message refers to aliased symbol instead of the alias) - $(LI $(BUGZILLA 5147): [CTFE] Return fixed-size matrix) - $(LI $(BUGZILLA 5268): Outdated windows GUI sample in Samples folder) - $(LI $(BUGZILLA 5362): checking $ in bracket is broken) - $(LI $(BUGZILLA 5482): Crash with align(0)) - $(LI $(BUGZILLA 5485): TLS sections handled incorrectly) - $(LI $(BUGZILLA 5524): [CTFE] Trouble with typesafe variadic function) - $(LI $(BUGZILLA 5647): [64-bit] Valgrind complains about illegal instruction) - $(LI $(BUGZILLA 5649): std.conv.parse faulty for floating point with -O -m32) - $(LI $(BUGZILLA 5657): Temporary object destruction) - $(LI $(BUGZILLA 5664): Cannot compile static synchronized member function.) - $(LI $(BUGZILLA 5694): va_arg doesn't work with idouble and ifloat) - $(LI $(BUGZILLA 5671): CTFE string concat problem) - $(LI $(BUGZILLA 5672): ICE(cod2.c): incorrect optimization of (long &1) == 1) - $(LI $(BUGZILLA 5678): new enum struct re-allocated at compile time) - $(LI $(BUGZILLA 5694): va_arg doesn't work with idouble and ifloat) - $(LI $(BUGZILLA 5706): Incorrect opcode prefix generated for x86_64 inline assembly) - $(LI $(BUGZILLA 5708): Incorrect string constant folding with -inline) - $(LI $(BUGZILLA 5717): 1.067 regression: appending Unicode char to string broken) - $(LI $(BUGZILLA 5722): Regression(2.052): Appending code-unit from multi-unit code-point at compile-time gives wrong result) - $(LI $(BUGZILLA 5735): non-scalar types implicitly converted to boolean) - $(LI $(BUGZILLA 5740): Unable to use this pointer in inline assembly) - $(LI $(BUGZILLA 5741): Add the SYSCALL and SYSRET opcodes to the inline assembler) - $(LI $(BUGZILLA 5798): Weakly pure function calls skipped inside a comma expression) - $(LI $(BUGZILLA 5812): Added constant fold optimisations for ^^ expressions) - $(LI $(BUGZILLA 5840): Cannot assign to an array member of struct in CTFE) - $(LI $(BUGZILLA 5852): CTFE: wrong code for string[] ~= const(string)) - $(LI $(BUGZILLA 5858): Import doesn't accept const string as argument) - $(LI $(BUGZILLA 5865): __dollar cannot be read at compile time) - $(LI $(BUGZILLA 5890): ICE and wrong scope problem for 2nd argument in static assert with DMD on git master) - $(LI $(BUGZILLA 5916): DMD: bad message for incorrect operands error) - $(LI $(BUGZILLA 5938): ICE ztc\symbol.c 1043) - $(LI $(BUGZILLA 5940): Cannot create arrays of std.algorithm.map) - $(LI $(BUGZILLA 5965): [2.053 beta] map rejects a predicate with anon-func and nested func) - $(LI $(BUGZILLA 5966): [2.053 beta][CTFE] Stack overflow on trivial func) - $(LI $(BUGZILLA 5972): CTFE: Can't assign to elements of arrays of slices) - $(LI $(BUGZILLA 5975): [2.053 beta][CTFE] ICE: 'global.errors' on line 1416 in file 'constfold.c') - $(LI $(BUGZILLA 5976): "variable used before set" with foreach with ref + scope(failure) + structure method + -O -inline) - $(LI $(BUGZILLA 5982): [2.053 beta] std.iterator gone, but no mention of the change) - $(LI $(BUGZILLA 5987): mydll sample doesn't compile) - $(LI Clarify tuple index out of bounds error message) - $(LI Add 64 version of xchg and jmp to inline assembler. Fixed 64 bit LEA) - $(LI CTFE: Generate error messages for accessing null arrays) - $(LI Fix optimizer bug with to!float("123e2")) - $(LI Fix spelling of $(CODE cmpxchgb8)) - ) -) - -$(VERSION 052, Feb 17, 2011, =================================================, - - $(WHATSNEW - $(LI 64 bit support for Linux) - $(LI Implemented $(I exception chaining), as described in TDPL. Currently Windows-only.) - $(LI std.random: Added Xorshift random generator) - $(LI Support HTML5 entities) - $(LI Added std.datetime for handling dates and times. std.date and std.gregorian - are now scheduled for deprecation. Any functions in other modules of Phobos - which used std.date.d_time have been changed to use std.datetime.SysTime or - are scheduled for deprecation with new functions with the same functionality - added which use SysTime (done in cases where switching existing functions to - use SysTime would have broken code). New code should use std.datetime instead - of std.date.) - $(LI Various functions in std.file were renamed to match Phobos' naming - conventions (e.g. isFile instead of isfile). The old names are aliased - and scheduled for deprecation.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 190): Cannot forward reference typedef/alias in default value for function parameter) - $(LI $(BUGZILLA 1513): try/catch/finally misbehavior on windows) - $(LI $(BUGZILLA 1899): AA of fixed-length arrays fails to initialize) - $(LI $(BUGZILLA 1914): Array initialisation from const array yields memory trample) - $(LI $(BUGZILLA 2581): DDoc doesn't work for functions with auto return type.) - $(LI $(BUGZILLA 2810): Bogus forward reference error with auto function) - $(LI $(BUGZILLA 2874): phobos docs issues) - $(LI $(BUGZILLA 3198): wrong initializer for structs arrays) - $(LI $(BUGZILLA 3334): std.demangle doesn't parse ref, pure, nothrow) - $(LI $(BUGZILLA 3681): ICE(go.c): when function takes too long to optimize, only with -O.) - $(LI $(BUGZILLA 3848): functions in std.file don't take symbolic links into account) - $(LI $(BUGZILLA 4013): Inconsistent codeview debug info for classes derived from IUnknown) - $(LI $(BUGZILLA 4069): Issue 4069 - std.xml.Document.pretty saves empty elements with spaces and line breaks) - $(LI $(BUGZILLA 4245): Declaring conflicting symbols in single function scope allowed) - $(LI $(BUGZILLA 4307): spawn()'ed thread doesn't terminate) - $(LI $(BUGZILLA 4328): templated unittests fail to link when instantiated from other file if compiler order isn't correct) - $(LI $(BUGZILLA 4379): ICE(blockopt.c): foreach over huge tuple, only with -O) - $(LI $(BUGZILLA 4389): ICE(constfold.c, expression.c), or wrong code: string~=dchar in CTFE) - $(LI $(BUGZILLA 4486): CodeView debug info should contain absolute path names) - $(LI $(BUGZILLA 4598): std.xml check is too restrictive) - $(LI $(BUGZILLA 4601): Spawned threads frequently don't terminate or let other threads ever run if you spawn more than one thread) - $(LI $(BUGZILLA 4732): __traits(identifier) performs constant folding on symbols) - $(LI $(BUGZILLA 4753): fail_compilation/fail116.d sends dmd into a loop, exhausting memory) - $(LI $(BUGZILLA 4807): Examples for std.array insert and replace) - $(LI $(BUGZILLA 4852): core.demangle cannot demangle functions with class/struct return types) - $(LI $(BUGZILLA 4878): Ddoc: Default arguments can break Ddoc output) - $(LI $(BUGZILLA 4913): Implicit opCast!bool in if statement doesn't work with declarator) - $(LI $(BUGZILLA 4973): map file with spaces in file name passed without quotes to linker) - $(LI $(BUGZILLA 5025): ICE(cast.c) shared struct literal) - $(LI $(BUGZILLA 5090): ICE(todt.c) struct literal initializing zero length array) - $(LI $(BUGZILLA 5105): Member function template cannot be synchronized) - $(LI $(BUGZILLA 5197): Ddoc: access-attributed auto template function crashes dmd) - $(LI $(BUGZILLA 5198): Appender much slower when appending ranges of elements than individual elements) - $(LI $(BUGZILLA 5209): posix/sys/select.d: FD_ISSET function should return bool) - $(LI $(BUGZILLA 5221): entity.c: Merge Walter's list with Thomas') - $(LI $(BUGZILLA 5242): self referencing template constraint crashes compiler) - $(LI $(BUGZILLA 5244): PATCH: fix use of uninitialised variable in toObj.c) - $(LI $(BUGZILLA 5246): PATCH(s): fix a couple more uninitialised variables) - $(LI $(BUGZILLA 5248): CTFE Segfault when calling a function on an enum struct) - $(LI $(BUGZILLA 5271): Not constant RAND_MAX) - $(LI $(BUGZILLA 5320): gcstub/gc.d: SEGV because of missing returns) - $(LI $(BUGZILLA 5349): ICE(toir.c): nested class in static member function) - $(LI $(BUGZILLA 5365): Regression (2.051) implicit conversions via alias this are broken) - $(LI $(BUGZILLA 5381): Regression (2.051) switch fails for wstring and dstring) - $(LI $(BUGZILLA 5382): [regression 2.051] DLL multi-threading broken) - $(LI $(BUGZILLA 5391): Crash with recursive alias declaration) - $(LI $(BUGZILLA 5400): Add const to FD_ISSET) - $(LI $(BUGZILLA 5439): 64bit struct alignment inconsistent with C ABI) - $(LI $(BUGZILLA 5447): Should be illegal to throw a non-Throwable) - $(LI $(BUGZILLA 5455): ICE(cgcod.c): Optimization (register allocation?) regression in DMD 1.065) - $(LI $(BUGZILLA 5486): Missing define for running dmd as 64 bit) - $(LI $(BUGZILLA 5488): Spawned threads hang in a way that suggests allocation or gc issue) - $(LI $(BUGZILLA 5504): Regression(2.051): Template member functions of a shared class don't compile) - $(LI $(BUGZILLA 5534): [64-bit] Inexplicable segfault in small code snippet, -O -release -m64 only) - $(LI $(BUGZILLA 5536): Array append with dollar op on 64-bit) - $(LI $(BUGZILLA 5545): [64-bit] DMD fails to postincrement ubytes.) - $(LI $(BUGZILLA 5549): [64-bit] Internal error: backend/cgcod.c 1845) - $(LI $(BUGZILLA 5552): std.datetime.d DosFileTimeToSysTime has a bug) - $(LI $(BUGZILLA 5556): [64-bit] Wrong Implicit Conversion to Double) - $(LI $(BUGZILLA 5557): [64-Bit] FP (alignment?) issues with Rvalues) - $(LI $(BUGZILLA 5564): [64-bit] loading of wrong constant byte value) - $(LI $(BUGZILLA 5565): [64-bit] Wrong Floating Point Results, Related to Mixing With size_t) - $(LI $(BUGZILLA 5566): [64-bit] More erratic FP results with size_t) - $(LI $(BUGZILLA 5579): Segfault on first call to GC after starting new thread) - $(LI $(BUGZILLA 5580): [64-bit] String switch statements broken in 64-bit mode) - $(LI $(BUGZILLA 5581): [64-bit] Wrong code with bitwise operations on bools) - $(LI $(BUGZILLA 5592): Previous definition different: __arrayExpSliceMulSliceAddass_d) - $(LI $(BUGZILLA 5595): Compiler crash on heavy std.algorithm use) - ) -) - -$(VERSION 051, Dec 21, 2010, =================================================, - - $(WHATSNEW - $(LI Added std.mathspecial, containing mathematical Special Functions) - $(LI std.base64: Replaced. Boost License, Performance improvement, Range support. Function signature changed from 'encode' to 'Base64.encode') - $(LI std.math: D implementation of pow. Almost all std.math functions are now @safe pure nothrow. - tgamma, lgamma, erf, erfc have been moved to std.mathspecial) - $(LI std.exception: Added pure and nothrow to assumeUnique) - $(LI std.utf: Removed UtfError class and toUTF* shortcut functions for validation. Added pure, nothrow, @safe and @trusted attributes. count function supports dchar) - $(LI Both druntime and phobos now build successfully with dmd -m64. Still somewhat behind dmd1, very little executes correctly still.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 603): Undocumented behaviour: case and default create a scope) - $(LI $(BUGZILLA 632): Typedef/enum promotions spec ambiguous - ultimate base type or lowest common denominator?) - $(LI $(BUGZILLA 679): Spec needs allowances for copying garbage collection) - $(LI $(BUGZILLA 690): ABI not fully documented) - $(LI $(BUGZILLA 1351): Discrepancies in the language specification) - $(LI $(BUGZILLA 1466): Spec claims maximal munch technique always works: not for "1..3") - $(LI $(BUGZILLA 2080): ICE(mangle.c) alias corrupts type inference of static variables) - $(LI $(BUGZILLA 2206): unnamed template mixin of class inside function or class has incorrect classinfo and mangleof) - $(LI $(BUGZILLA 2385): spec says all structs are returned via hidden pointer on linux, but it uses registers) - $(LI $(BUGZILLA 2392): Parsing ambiguity between function pointer declaration and function call) - $(LI $(BUGZILLA 2406): Declarator2 definition error) - $(LI $(BUGZILLA 2556): Property classinfo needs better documentation (RTTI, typeof, typeid, runtime type information)) - $(LI $(BUGZILLA 2616): Undocumented behaviour: part-explicit, part-implicit instantiations of function templates are accepted) - $(LI $(BUGZILLA 2651): class body declaration grammar incorrect) - $(LI $(BUGZILLA 2652): DeclDef grammar is wrong) - $(LI $(BUGZILLA 2734): Ambiguity in tokenizing: _._ as a float literal) - $(LI $(BUGZILLA 2751): const/invariant/immutable static arrays: const(T)[N] and const(T[N]) are the same, but DMD treats them as different) - $(LI $(BUGZILLA 2954): [tdpl] Appalling bug in associative arrays (D2 only)) - $(LI $(BUGZILLA 2994): Incomplete "Predefined Versions" documentation) - $(LI $(BUGZILLA 3020): No description is given why function may not be nothrow) - $(LI $(BUGZILLA 3112): Specification on what operations call the GC is missing) - $(LI $(BUGZILLA 3276): Recursion broken by alias template parameter) - $(LI $(BUGZILLA 3554): Ddoc generates invalid output for documentation comments with non paired parantheses) - $(LI $(BUGZILLA 3864): Dyn array allocations can be allowed in nothrow functions) - $(LI $(BUGZILLA 4059): Incorrect C++ name mangling) - $(LI $(BUGZILLA 4217): Function overloads are not distinguished when instantiating templates) - $(LI $(BUGZILLA 4254): ICE(mtype.c): function with const inout parameter) - $(LI $(BUGZILLA 4297): Nothrow functions cannot use constant dynamic array) - $(LI $(BUGZILLA 4384): Cyclic dependency check for modules is broken) - $(LI $(BUGZILLA 4434): ICE(mtype.c, 887) alias with const, shared, or immutable) - $(LI $(BUGZILLA 4445): roundTo!ubyte(255.0) throws) - $(LI $(BUGZILLA 4529): Segfault(typinf.c) involving typeid(typeof(functionName))) - $(LI $(BUGZILLA 4638): Regression: new writeln does not recognize "wstring toString") - $(LI $(BUGZILLA 4728): Segfault(toctype.c) by protected/private constructor in an other module) - $(LI $(BUGZILLA 4781): Segfault(mtype.c) with forward referenced typeof and .init) - $(LI $(BUGZILLA 4864): ICE(statement.c) Crash on invalid 'if statement' body inside mixin) - $(LI $(BUGZILLA 4901): std.algorithm.sort does not compile for interfaces.) - $(LI $(BUGZILLA 4915): auto return type escapes function purity) - $(LI $(BUGZILLA 5020): Forward implicit bool conversions to alias this) - $(LI $(BUGZILLA 5053): Better error message for cyclic dependencies.) - $(LI $(BUGZILLA 5054): Splitter example doesn't work) - $(LI $(BUGZILLA 5094): No implicit conversion with "alias property this") - $(LI $(BUGZILLA 5107): Const-shared classes/structs not typed as shared) - $(LI $(BUGZILLA 5110): Excess attribute propagation of structs and classes) - $(LI $(BUGZILLA 5117): [CTFE] Member function call with rather complex this: side effects ignored) - $(LI $(BUGZILLA 5120): ICE(mtype.c) void associative arrays) - $(LI $(BUGZILLA 5131): Segfault(expression.c) opAssign and associative arrays (AA) are broken for types != this) - $(LI $(BUGZILLA 5133): dmd fails to build rdmd (problem with startsWith)) - $(LI $(BUGZILLA 5145): Regression(2.050, 1.065) override error with forward ref of superclass) - $(LI $(BUGZILLA 5148): Incorrect C++ mangling of multiple const char* parameters) - $(LI $(BUGZILLA 5154): Class Range does not work in writeln) - $(LI $(BUGZILLA 5159): Segfault(interpret.c): calling a static function pointer variable in CTFE) - $(LI $(BUGZILLA 5163): meaningless error message with front() applied to void[].) - $(LI $(BUGZILLA 5164): Error without line number using "is (T...)") - $(LI $(BUGZILLA 5180): ICE(arrayop.c) in-place array operation on incompatible types) - $(LI $(BUGZILLA 5182): ICE(expression.c): calling unittest from a function) - $(LI $(BUGZILLA 5191): Combination of pure and nothrow result in a function that does nothing) - $(LI $(BUGZILLA 5194): ddoc does not show modifiers on constructors such as pure or nothrow) - $(LI $(BUGZILLA 5195): Forward references ignore const) - $(LI $(BUGZILLA 5214): Compiler crash with array of empty {}) - $(LI $(BUGZILLA 5218): Can't implicitly convert from "abc"w to wchar[3]) - $(LI $(BUGZILLA 5220): Make std.conv.ConvError an Exception instead of an Error; $(RED deprecated ConvError and ConvOverflowError) with ConvException and ConvOverflowException. Note that any code depending on the fact that these exceptions were Error gets broken.) - $(LI $(BUGZILLA 5230): Regression(2.041, 1.057) ICE(tocsym.c) overriding a method that has an out contract) - $(LI $(BUGZILLA 5238): PATCH: fix return of uninitialised var in interpret.c) - $(LI $(BUGZILLA 5247): std.utf.stride() should not return 0xFF) - $(LI $(BUGZILLA 5275): x86_64 related hidden function parameter mishandled) - $(LI $(BUGZILLA 5293): std.math: Error: shift by -48 is outside the range 0..32) - $(LI $(BUGZILLA 5294): -O optimization breaks for loop) - $(LI $(BUGZILLA 5321): std.math: assumes X86 or X86_64 on FPU control word code) - $(LI $(BUGZILLA 5322): std.math: version(Sparc) should be SPARC) - $(LI $(BUGZILLA 5330): Druntime/Phobos: remove special treatment for GDC) - $(LI $(BUGZILLA 5331): mach format problem) - $(LI $(BUGZILLA 5340): isOutputRange!(Appender!string, int) must be false) - $(LI $(BUGZILLA 5353): clear function is calling the destructor twice) - ) -) - -$(VERSION 050, Oct 29, 2010, =================================================, - - $(WHATSNEW - $(LI added talign() and argTypes() to TypeInfo) - $(LI Upgrade zlib support to zlib 1.2.5) - $(LI std.stdio: Added ByChunk. This struct is a InputRange like ByLine. File.byChunk returns ByChunk) - $(LI std.traits: Most higher-order ranges now work with const/immutable arrays and other ranges - with a natural tail const, and ranges w/ const/immutable elements.) - $(LI $(BUGZILLA 4888): Heavy reliance on Bug 3534 in Phobos range usage) - $(LI $(BUGZILLA 4987): C function pointer syntax needs to be deprecated) - $(LI std.typecons: Several improvements to the Tuple struct template: - $(UL $(LI Tuple members are now accessible with the syntax a[0], a[1] etc.) - $(LI Eliminated an internal union. See $(BUGZILLA 4421) and $(BUGZILLA 4846).) - $(LI Worked around $(BUGZILLA 4424). Got opAssign back.) - $(LI Made Tuple.slice!(from, to) to preserve field names if any.) - $(LI Added isTuple!(T) template.) - )) - $(LI std.algorithm: changed filter() such that filter is curryable) - $(LI std.algorithm: Added function balancedParens) - $(LI std.typecons: Deprecated defineEnum) - $(LI Added relaxed purity checking rules.) - ) - $(BUGSFIXED - $(LI Unlisted bug: std.exception.pointsTo() calls postblit on subobjects.) - $(LI Unlisted bug: std.typetuple.staticMap!() doesn't work with empty/single tuples.) - $(LI Unlisted bug: std.traits: Interfaces should have indirections, aliasing, etc.) - $(LI Unlisted bug: std.socket: Race condition - gethostbyname and gethostbyaddr on Linux return static data. The call was synchronized, but using the data wasn't) - $(LI Unlisted bug: signed long comparisons under OS X) - $(LI $(BUGZILLA 941): std.regexp fails to match when grouping certain sub-expressions) - $(LI $(BUGZILLA 1482): std.file docs are insufficient) - $(LI $(BUGZILLA 1635): DirEntry.isfile() and DirEntry.isdir() broken) - $(LI $(BUGZILLA 1733): parse() function does not handle all build-in types) - $(LI $(BUGZILLA 2073): Variant.coerce!() fails) - $(LI $(BUGZILLA 2142): getopt() incorrectly processes bundled command-line options) - $(LI $(BUGZILLA 2310): Inconsistent formatting of arrays in std.stdio.write() and std.conv.to!(string)()) - $(LI $(BUGZILLA 2424): std.functional binaryRevertArgs : "revert" should be "reverse") - $(LI $(BUGZILLA 2451): Adding structs that use opAssign or postblit to an AA is broken) - $(LI $(BUGZILLA 2655): Allow alternation patterns in std.path.fnmatch) - $(LI $(BUGZILLA 2669): Variant does not have opApply or another iteration mechanism) - $(LI $(BUGZILLA 2718): Inconsistent string parameters in Phobos functions) - $(LI $(BUGZILLA 2838): std.file.rmdirRecurse fails) - $(LI $(BUGZILLA 2930): Problems in std.range documentation) - $(LI $(BUGZILLA 2943): Struct copying in presence of alias member this only copies alias this member) - $(LI $(BUGZILLA 2965): std.date: timezone not initialized) - $(LI $(BUGZILLA 3157): [patch] Pipes should be closed with pclose) - $(LI $(BUGZILLA 3318): [PATCH]Rebindable.get is not accessible) - $(LI $(BUGZILLA 3570): mkdirRecurse throws exception on trailing empty directory.) - $(LI $(BUGZILLA 3602): ICE(tocsym.c) compiling a class, if its super class has preconditions) - $(LI $(BUGZILLA 3665): Regression(1.051, 2.036) Assignment with array slicing does not work) - $(LI $(BUGZILLA 4344): Sockets with multiple threads report missing/failed WSAStartup) - $(LI $(BUGZILLA 4398): dmd always uses Windows name mangling for _d_throw) - $(LI $(BUGZILLA 4439): The declaration of the in6addr_* in druntime is wrong.) - $(LI $(BUGZILLA 4465): ICE(symbol.c): immutable type inference with ^^2) - $(LI $(BUGZILLA 4524): Regression(2.026) Bus error with nested struct) - $(LI $(BUGZILLA 4623): Non-integer type allowed as static array size) - $(LI $(BUGZILLA 4634): typo in levenshteinDistanceAndPath documentation) - $(LI $(BUGZILLA 4641): Associative arrays of structs with alias this broken.) - $(LI $(BUGZILLA 4742): int % BigInt should work.) - $(LI $(BUGZILLA 4775): No substitution on writef("%%%s", "hi").) - $(LI $(BUGZILLA 4825): Regression(1.057, 2.040) "Error: non-constant expression" with -inline) - $(LI $(BUGZILLA 4866): Static-to-dynamic converted manifest constant array gets non-converted type in static/constraint if) - $(LI $(BUGZILLA 4869): auto return + inheritance + modules = compiler crashes(toctype.c)) - $(LI $(BUGZILLA 4873): Assertion failure: '0' on line 1483 in file 'expression.c') - $(LI $(BUGZILLA 4882): std.traits hasUnsharedAliasing does not work for function type.) - $(LI $(BUGZILLA 4897): CodeView: No locals or parameters are shown when debugging, because of missing function info) - $(LI $(BUGZILLA 4890): GC.collect() deadlocks multithreaded program.) - $(LI $(BUGZILLA 4925): [ICE] segfault with module-scope assert(0)) - $(LI $(BUGZILLA 4926): ICE: PREC_zero assertion failure due to unset precedence) - $(LI $(BUGZILLA 4938): Regression(2.047) dmd segfault when compiling) - $(LI $(BUGZILLA 4941): Built-in tuple slice boundaries are not CTFE'd) - $(LI $(BUGZILLA 4949): ICE on invalid static if using value of 'this') - $(LI $(BUGZILLA 4951): InternetAddress fails to resolve host when multithreading.) - $(LI $(BUGZILLA 4959): std.conv.parse error "no digits seen" on string starting with zero.) - $(LI $(BUGZILLA 4992): ICE(glue.c) or segfault: using int[new]) - $(LI $(BUGZILLA 5003): regex(replace with delegate) sample doesn't work.) - $(LI $(BUGZILLA 5026): ICE(expression.c) Incomplete mixin expression + char[] to char assignment) - $(LI $(BUGZILLA 5049): std.algortihm.bringToFront() returns wrong value.) - $(LI $(BUGZILLA 5052): take!(Take!R) should return Take!R, not Take!(Take!R).) - $(LI $(BUGZILLA 5071): passing value by ref to a function with an inner dynamic closure results in a wrong code) - ) -) - -$(VERSION 049, Sep 13, 2010, =================================================, - - - $(WHATSNEW - $(LI std.algorithm: reduce now works with non-range-based iteration, such as opApply.) - $(LI std.numeric: Added FFT.) - $(LI std.path: Changed sep, altsep etc. to manifest constants (enum).) - $(LI std.process: Added environment, an AA-like interface for environment variables.) - $(LI std.range: Iota, Stride, Transversal, FrontTransveral now support slicing where possible.) - $(LI std.range: Added support for moveFront() and assignable elements in several higher-order ranges.) - $(LI std.range: Added Lockstep, hasLvalueElements.) - $(LI std.range: Added virtual function-based wrappers (InputRangeObject, OutputRangeObject) for when a binary interface to a range is required.) - $(LI std.typecons: Added convenience functions for Rebindable.) - $(LI std.traits: Added isAssignable, isIterable, ForeachType, isSafe, isUnsafe, EnumMembers.) - $(LI std.traits: hasLocalAliasing, hasLocalObjects and hasLocalRawAliasing are now hasUnsharedAliasing, hasUnsharedObjects and hasUnsharedRawAliasing. Aliases to the old names are included for now for backwards compatibility.) - $(LI std.typetuple: Added anySatisfy.) - $(LI std.array: Modified Appender's interface to fix memory issues. - Note that appending via $(D ~=) and using appender on the same array - will not interleave anymore.) - $(LI $(BUGZILLA 2477): Trailing comma in array literal sometimes accepted, sometimes not) - ) - $(BUGSFIXED - $(LI Andrej Mitrovic updated the samples/d code) - $(LI Unlisted Bug: std.math.pow doesn't work on immutable numbers.) - $(LI Unlisted Bug: std.math.pow floating point overload expects both arguments to be exact same type.) - $(LI Unlisted Bug: std.path.join("", "foo") returns "/foo" instead of "foo" on Posix.) - $(LI Unlisted Bug: std.range.iota() random access primitives inconsistent after popFront on floating point version) - $(LI Unlisted Bug: std.algorithm.findAdjacent() [...]) - $(LIX $(BUGZILLA 190): Cannot forward reference typedef/alias in default value for function parameter) - $(LI $(BUGZILLA 1715): Template specialization checks for equality rather than convertibility) - $(LI $(BUGZILLA 1970): Templated interfaces not matched) - $(LI $(BUGZILLA 2511): Covariant return type doesn't work with circular import) - $(LI $(BUGZILLA 2716): Confusion of auto and scope as the class attribute) - $(LI $(BUGZILLA 2903): Splitter should be bi-dir if the input range is bi-dir.) - $(LI $(BUGZILLA 2951): std.random.dice() should be templated on proportions.) - $(LI $(BUGZILLA 2958): std.getopt RangeError on missing arg) - $(LI $(BUGZILLA 3046): Segfault with C++ static variable (Linux only)) - $(LI $(BUGZILLA 3123): std.algorithm.zip fails on 'lazy' ranges) - $(LI $(BUGZILLA 3294): forward reference to inferred return type of function call) - $(LI $(BUGZILLA 3312): std.string.count should use const(char)[], not immutable.) - $(LI $(BUGZILLA 3348): Documentation for many std.process functions has disappeared) - $(LI $(BUGZILLA 3361): code in std.zlib concatenates void[] arrays ) - $(LI $(BUGZILLA 3418): link error with cast(ulong)(ulong*real)) - $(LI $(BUGZILLA 3544): optlink termination 0041338f with recursive nested functions) - $(LI $(BUGZILLA 3554): Ddoc generats invalid output for documentation comments with non paired paranthasis) - $(LI $(BUGZILLA 3627): -of with a filename with a double extension confuses linker) - $(LI $(BUGZILLA 3877): std.range.chain do not manage infinite ranges correctly) - $(LI $(BUGZILLA 3894): std.range.Stride!R requires R.front() and R.back() to return by reference) - $(LI $(BUGZILLA 3935): opBinary is instantiated with "=") - $(LI $(BUGZILLA 3946): schwartzSort - SwapStrategy always unstable) - $(LIX $(BUGZILLA 3979): Order-of-compilation and forward reference errors) - $(LI $(BUGZILLA 3996): Regression(2.041) ICE(glue.c) Passing struct as AA template parameter (Algebraic with struct)) - $(LI $(BUGZILLA 4009): OPTLINK ruins the day yet again) - $(LI $(BUGZILLA 4173): Regression(2.037) Explicitly instantiated templates still try to do IFTI in some cases) - $(LI $(BUGZILLA 4177): __ctfe can't be used in pure functions) - $(LI $(BUGZILLA 4278): allow inlining of super calls (undo limitations of bug3500's fix)) - $(LI $(BUGZILLA 4291): Pure functions cannot access mixed in variables) - $(LI $(BUGZILLA 4292): CommonType fails for singular alias value.) - $(LI $(BUGZILLA 4302): Regression(2.046, 1.061): compiler errors using startsWith in CTFE) - $(LI $(BUGZILLA 4345): std.range.take!string: "Nonsensical finite range with slicing but no length".) - $(LI $(BUGZILLA 4346): More flexible std.array.array.) - $(LI $(BUGZILLA 4363): Some phobos ranges are not forward ranges (but should be).) - $(LI $(BUGZILLA 4381): Length attribute for std.typecons.Tuple.) - $(LI $(BUGZILLA 4387): std.range.Cycle assumes lvalue elements.) - $(LI $(BUGZILLA 4388): std.range.Radial assumes lvalue elements.) - $(LI $(BUGZILLA 4402): std.range.Zip doesn't work w/ non-lvalue ranges.) - $(LI $(BUGZILLA 4403): std.range.FrontTransversal assumes lvalue elements.) - $(LI $(BUGZILLA 4404): std.range.Transversal assumes lvalue elements.) - $(LI $(BUGZILLA 4408): Ambiguity when using std.algorithm.splitter with generic ranges.) - $(LI $(BUGZILLA 4430): Regression(2.037) erroneous matching on specialized template function) - $(LI $(BUGZILLA 4455): Taking the sqrt of an integer shouldn't require an explicit cast.) - $(LI $(BUGZILLA 4464): std.range.take does not always return Take!R.) - $(LI $(BUGZILLA 4518): to!string(enum w/invalid value) produces a somewhat unhelpful error) - $(LI $(BUGZILLA 4564): ICE on undefined variable in foreach over 0 .. undef) - $(LI $(BUGZILLA 4603): array(iota(1, 0)) error.) - $(LI $(BUGZILLA 4643): Shared values are unwritable.) - $(LI $(BUGZILLA 4645): to!string(const char*) in library causes Optlink to issue warning) - $(LI $(BUGZILLA 4652): Compiler hangs on template with zero-length tuple and another argument) - $(LI $(BUGZILLA 4655): Regression(1.063, 2.048) goto to a try block ICEs) - $(LI $(BUGZILLA 4676): Overload resolution rejects valid code when mixing variadics, non-variadics) - $(LI $(BUGZILLA 4681): Appender access violation) - $(LI $(BUGZILLA 4691): Incorrect comparison of double and long) - $(LI $(BUGZILLA 4700): to!float("0") fails) - $(LI $(BUGZILLA 4721): compilation slow when compiling unittests on dcollections) - $(LI $(BUGZILLA 4748): Shadowing declaration error in std.string.tolower) - $(LI $(BUGZILLA 4751): Regression(1.062, 2.047) ICE(constfold.c) >> after error) - $(LI $(BUGZILLA 4752): fail_compilation/fail345.d asserts in expression.c) - $(LI $(BUGZILLA 4771): fail_compilation/fail274.d hits a halt in iasm.c) - $(LI $(BUGZILLA 4789): std.algorithm.sort bug) - $(LI $(BUGZILLA 4810): dotProduct problem with ints) - $(LI $(BUGZILLA 4826): Regression(2.041) "cannot create associative array" and compiler crash) - $(LI $(BUGZILLA 4828): ICE w/ non-boolean dot expression sth.template_instance in static if) - $(LI $(BUGZILLA 4834): Implicit sharing via delegates in std.concurrency) - ) -) - - -$(VERSION 048, Aug 8, 2010, =================================================, - - - $(WHATSNEW - $(LI std.complex: New Complex.toString() syntax.) - $(LI std.string: icmp() now works with all built-in string types.) - $(LI $(BUGZILLA 4077): Bugs caused by bitwise operator precedence) - $(LI $(BUGZILLA 4080): Patch for building dynamic libraries on Mac OS X) - ) - $(BUGSFIXED - $(LI Unlisted Bug: std.algorithm.filter not a forward range) - $(LI Unlisted Bug: std.algorithm.Uniq requires a bidirectional range) - $(LI Unlisted Bug: std.algorithm.Uniq missing a save() function) - $(LI Unlisted Bug: std.algorithm.Group missing a save() function) - $(LI Unlisted Bug: std.traits.isAssociativeArray reports true for structs w/ keys, values properties) - $(LI Unlisted Bug: gc_query returns 0 for attr when called on interior pointers) - $(LI $(NG_digitalmars_D 112964): capacity can return a value < length) - $(LI $(BUGZILLA 978): std.utf's toUTF* functions accept some invalid and reject some valid UTF) - $(LI $(BUGZILLA 996): Error in doc on implicit conversion between pointer and array) - $(LI $(BUGZILLA 1418): tupleof bug on nested classes) - $(LI $(BUGZILLA 1678): ref with varargs generates invalid code) - $(LI $(BUGZILLA 2275): std.utf.toUTF16z() should return const(wchar)*) - $(LI $(BUGZILLA 2627): std.traits.hasAliasing reports true for static arrays) - $(LI $(BUGZILLA 2872): Length, opIndex for Map) - $(LI $(BUGZILLA 2931): Initialization struct with array from another struct) - $(LI $(BUGZILLA 3202): std.math.pow cause dead loop) - $(LI $(BUGZILLA 3326): $ in delegate literal causes Access Violation) - $(LI $(BUGZILLA 3355): std.string.cmp works incorrectly for mixed-type and different-length strings) - $(LI $(BUGZILLA 3386): to!bool(string) is not implemented) - $(LI $(BUGZILLA 3436): std.functional.compose with only one function) - $(LI $(BUGZILLA 3439): std.range.Sequence.opIndex not consistent after calling popFront().) - $(LI $(BUGZILLA 3447): std.file uses unconventional file permissions) - $(LI $(BUGZILLA 3528): FreeBSD patches for druntime.) - $(LI $(BUGZILLA 3560): foreach over nested function generates wrong code) - $(LI $(BUGZILLA 3569): DMD Stack Overflow with a struct member function inside a C-style struct initializer) - $(LI $(BUGZILLA 3604): extern(C) callable function with array parameters broken) - $(LI $(BUGZILLA 3679): Regression(2.031) template forward reference regression) - $(LI $(BUGZILLA 3706): delegates of interfaces with multiple inheritance fail) - $(LI $(BUGZILLA 3716): Regression (2.037) with multi dimensional array literals) - $(LI $(BUGZILLA 3782): The POSIX sys/un.h header) - $(LI $(BUGZILLA 3853): core.sys.posix.stdio.pclose is missing) - $(LI $(BUGZILLA 3872): std.algorithm.filter could become bidirectional if its input range is bidir) - $(LI $(BUGZILLA 3874): std.range.stride assumes a bidirectional input range) - $(LI $(BUGZILLA 3917): opEquals for Ojbect could be more efficient) - $(LI $(BUGZILLA 3937): os.path.dirname fails on absolute path) - $(LI $(BUGZILLA 3961): Error with to!(somestruct)) - $(LI $(BUGZILLA 3983): Regression(2.037): struct with == can't be member of struct with template opEquals) - $(LI $(BUGZILLA 4109): (reopened) writeln doesn't work with empty static array) - $(LI $(BUGZILLA 4171): std.random.uniform does not work for a range of characters) - $(LI $(BUGZILLA 4191): [FreeBSD] real constants are rounded to double precision) - $(LI $(BUGZILLA 4198): [FreeBSD] imprecision in decimal floating-point literals) - $(LI $(BUGZILLA 4238): Segfault(statement.c): with(typeof(int))) - $(LI $(BUGZILLA 4260): windows & basename) - $(LI $(BUGZILLA 4267): forward reference error when 2-fold aliasing a template instance) - $(LI $(BUGZILLA 4303): __traits(compiles) returns wrong result when used recursively) - $(LI $(BUGZILLA 4305): Take, Chain on top of ranges w/o moveFront() ) - $(LI $(BUGZILLA 4307): spawn()'ed thread doesn't terminate) - $(LI $(BUGZILLA 4314): Regression(1.062): Expression array1 && array2 doesn't compile) - $(LI $(BUGZILLA 4327): std.container.Array.Range.~this() tries to call free(T[])) - $(LI $(BUGZILLA 4339): Struct destructor + invariant + struct parameter = horrific error message) - $(LI $(BUGZILLA 4356): Copy constructor not called under extremely mysterious circumstances) - $(LI $(BUGZILLA 4362): std.range.repeat and cycle do not have a .save() method) - $(LI $(BUGZILLA 4363): std.algorithm.Until is not a forward range) - $(LI $(BUGZILLA 4369): Multiple bugs in GC minimize()) - $(LI $(BUGZILLA 4370): POSIX monitor attribute not being used) - $(LI $(BUGZILLA 4396): mkdir race prevents concurrent compiling with DMD using make -j) - $(LI $(BUGZILLA 4400): D2 GC doesn't allocate with 16 bytes alignment) - $(LI $(BUGZILLA 4406): Typo (bug) in std.concurrency) - $(LI $(BUGZILLA 4412): Array capacity growth spikey and the ratio approaches 1.0) - $(LI $(BUGZILLA 4443): Optimizer produces wrong code for || or && with struct arrays) - $(LI $(BUGZILLA 4452): Incorrect result of BigInt ^^ long) - $(LI $(BUGZILLA 4470): Problems with std.bigint mod and divide) - $(LI $(BUGZILLA 4503): forward reference to aliased template instance) - $(LI $(BUGZILLA 4506): Regression(2.034): -O flag breaks some recursive functions) - $(LI $(BUGZILLA 4514): Regression: Cannot cast from X* to X) - $(LI $(BUGZILLA 4516): Regression(2.040): forward declaration of enum not supported) - $(LI $(BUGZILLA 4551): D2 Language Docs: http://www.digitalmars.com/d/2.0/arrays.html) - $(LI $(BUGZILLA 4569): extern(c++) doesn't understand const types, produces bad mangled symbol) - $(LI $(BUGZILLA 4570): ElementType!(void[]) shows error message) - $(LI $(BUGZILLA 4578): Regression(2.047,1.062): ICE(cgcod.c): var+arr[]) - $(LI $(BUGZILLA 4590): Spec incorrectly describes array appending and memory stomping) - ) -) - -$(VERSION 047, Jun 11, 2010, =================================================, - - $(WHATSNEW - $(LI Changed "op=" to just "op" for template argument to opOpAssign) - $(LI std.algorithm: Added save() to forward ranges; added split() using only one element as separator; added indexOf; fixed unlisted bug in startsWith and endsWith; added skipOver(); added canFind().) - $(LI std.array: Added implementation of save() for T[]s.) - $(LI std.concurrency: Eliminated spurious unittest stdout messages.) - $(LI std.container: Added.) - $(LI std.conv: Added file and line information to conversion errors; added brackets '[' and ']' around arrays and associative arrays as defaults; added emplace() for non-class types.) - $(LI std.file: Replaced exception upon out-of-memory error with assert(0).) - $(LI std.functional: toDelegate now accepts callable(function pointers, delegates and objects implement opCall) ) - $(LI std.path: Made basename() generic in string type.) - $(LI std.range: Added the existence of the property save as a condition for isForwardRange; added save to the range defined within; replaced a couple of awkward front() implementations; defined module-level moveFront() and range member moveFront() where appropriate; added @property maxLength to Take; arranged things such that take() for slice-able ranges returns the same type as the slice; eliminated SListRange; defined iota() with one argument; moved BinaryHeap within.) - $(LI std.regex: Qualified indexOf with std.algorithm.) - $(LI std.regexp: Qualified indexOf with std.algorithm.) - $(LI std.stdio: Added an error message to enforce() in rawRead().) - $(LI std.string: Improved indexOf(), tolower(), splitter(), chomp().) - $(LI std.traits: Added templates to get compile-time information about functions.) - $(LI std.typecons: Added AutoImplement.) - $(LI std.utf: Eliminated decodeFront() and decodeBack() - they aren't needed since strings are bidirectional ranges.) - $(LI $(BUGZILLA 2008): Poor optimization of functions with ref parameters) - $(LI $(BUGZILLA 3793): Functions with static arrays as arguments are not inlined) - $(LI $(BUGZILLA 4296): Reduce parasitic error messages) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1193): regression: "matches more than one template declaration" doesn't list the location of the conflicting templates) - $(LI $(BUGZILLA 1894): scope(exit) is ignored except in compound statements) - $(LI $(BUGZILLA 1941): missing line on inaccesable external private module member) - $(LI $(BUGZILLA 2127): inliner turns struct "return *this" from by-value into by-ref) - $(LI $(BUGZILLA 2276): Error message missing line number on array operation) - $(LI $(BUGZILLA 2546): Array Ops silently fail when no slice symbol is used.) - $(LI $(BUGZILLA 2738): Rebindable should work for interfaces.) - $(LI $(BUGZILLA 2835): std.socket.TcpSocket doesn't actually connect) - $(LI $(BUGZILLA 2881): x.stringof returns typeof(x).stringof when x is an enum) - $(LI $(BUGZILLA 3064): Invalid array operation accepted, generates bad code) - $(LI $(BUGZILLA 3088): std.xml.check() fails on xml comments) - $(LI $(BUGZILLA 3139): compiler dies "Error: out of memory" with case range) - $(LI $(BUGZILLA 3200): std.xml doesn't follow spec for Tag.text) - $(LI $(BUGZILLA 3323): Segfault or ICE(e2ir.c) using struct with destructor almost anywhere) - $(LI $(BUGZILLA 3398): Attributes inside a union screws data alignment) - $(LI $(BUGZILLA 3465): isIdeographic can be wrong in std.xml) - $(LI Major improvements to CustomFloat, fixing $(BUGZILLA 3520): std.numeric.CustomFloat horribly broken) - $(LI $(BUGZILLA 3538): Default value of alias template parameter is instantiated only once.) - $(LI $(BUGZILLA 3547): for option -od for relative path the path is added twice) - $(LI $(BUGZILLA 3548): ICE occurs when an array is returned from a function is incorrectly used in an array op expression.) - $(LI $(BUGZILLA 3604): extern(C) callable function with array parameters broken) - $(LI $(BUGZILLA 3651): mangleof broken for enums) - $(LI $(BUGZILLA 3653): Problem sorting array of Rebindable) - $(LI $(BUGZILLA 3658): Crashing on vector operations (Mac only)) - $(LI $(BUGZILLA 3662): Wrong compile error within struct constructor and C-style initializer) - $(LI $(BUGZILLA 3667): Regression(D2 only): broken out(result) in contracts) - $(LI $(BUGZILLA 3786): bug in std.string.removechars) - $(LI $(BUGZILLA 3854): Error on static initialization of arrays with trailing comma.) - $(LI $(BUGZILLA 3873): std.range.repeat should have popBack defined) - $(LI $(BUGZILLA 3876): std.range.Take back/popBack methods don't work correctly) - $(LI $(BUGZILLA 3880): std.regex functions with const/immutable Regex object) - $(LI $(BUGZILLA 4003): The result changes only with the order of source files.) - $(LI $(BUGZILLA 4045): [CTFE] increasing array length) - $(LI $(BUGZILLA 4052): [CTFE] increment from array item) - $(LI $(BUGZILLA 4056): Template instantiation with bare parameter not documented) - $(LI $(BUGZILLA 4073): core.cpuid crashes) - $(LI $(BUGZILLA 4078): [CTFE] Failed return of dynamic array item) - $(LI $(BUGZILLA 4084): Ignored missing main() closing bracket) - $(LI $(BUGZILLA 4109): writeln doesn't work with empty static array) - $(LI $(BUGZILLA 4143): fix warnings in dmd build) - $(LI $(BUGZILLA 4156): Segfault with array+=array) - $(LI $(BUGZILLA 4169): building dmd with a modern gcc produces a buggy compiler) - $(LI $(BUGZILLA 4175): linux.mak doesn't declare sufficient dependencies to support parallel builds) - $(LI $(BUGZILLA 4188): std.file.remove throws Exception on success) - $(LI $(BUGZILLA 4193): Regression 2.046, ICE(expression.c): initialising class member with const forward reference) - $(LI $(BUGZILLA 4202): Changset 1517 doesn't compile) - $(LI $(BUGZILLA 4207): std.cover.setDestDir does not work.) - $(LI $(BUGZILLA 4208): druntime should not depend on Phobos) - $(LI $(BUGZILLA 4212): DWARF: void arrays cause gdb errors) - $(LI $(BUGZILLA 4213): Strange behaviour with static void[] arrays) - $(LI $(BUGZILLA 4219): hasAliasing does not care about immutable) - $(LI $(BUGZILLA 4220): I cannot apply @safe to intrinsic operation(eg: std.math.sqrt)) - $(LI $(BUGZILLA 4228): std.array.replace contains 2 bugs) - $(LI $(BUGZILLA 4230): version(unittest)) - $(LI $(BUGZILLA 4231): Solitary opUnary Postincrement and Postdecrement user defined operators are broken.) - $(LI $(BUGZILLA 4242): ICE(module.c): importing a module with same name as package) - $(LI $(BUGZILLA 4249): std.regex fails to compile with debug=regex) - $(LI $(BUGZILLA 4252): [CTFE] No array bounds checking in assignment to char[] array) - $(LI $(BUGZILLA 4257): ICE(interpret.c): passing parameter into CTFE as ref parameter) - $(LI $(BUGZILLA 4259): Header generation omits leading '@' for properties) - $(LI $(BUGZILLA 4262): Header generation omits 'enum' for enum declarations) - $(LI $(BUGZILLA 4263): Header generation omits '@system' attribute) - $(LI $(BUGZILLA 4270): Missing line number in 'can only catch class objects' error message) - $(LI $(BUGZILLA 4300): BigInt * int doesn't work well) - ) -) - -$(VERSION 046, May 10, 2010, =================================================, - - $(WHATSNEW - $(LI Add hints for missing import declarations.) - $(LI Speed up compilation.) - $(LI All length methods in Phobos are now a @property.) - $(LI $(BUGZILLA 1001): print stack trace (in debug mode) when program die) - ) - $(BUGSFIXED - $(LI Fix hanging problem on undefined identifiers.) - $(LI $(BUGZILLA 461): Constant not understood to be constant when circular module dependency exists.) - $(LI $(BUGZILLA 945): template forward reference with named nested struct only) - $(LI $(BUGZILLA 1055): union forward reference "overlapping initialization" error) - $(LI $(BUGZILLA 2085): CTFE fails if the function is forward referenced) - $(LI $(BUGZILLA 2386): Array of forward referenced struct doesn't compile) - $(LI $(BUGZILLA 3945): AssertExpression message should implicitly convert to const char[]) - $(LI $(BUGZILLA 4015): forward reference in alias causes error) - $(LI $(BUGZILLA 4016): const initializer cannot forward reference other const initializer) - $(LI $(BUGZILLA 4042): Unable to instantiate a struct template.) - $(LI $(BUGZILLA 4100): Break and continue to label should mention foreach) - $(LI $(BUGZILLA 4116): object.di does not match object_.d) - $(LI $(BUGZILLA 4146): Unavailable: core.sys.posix.sys.wait.waitid()) - $(LI $(BUGZILLA 4184): associative array with certain key types results in corrupt values during iteration) - ) -) - -$(VERSION 045, May 4, 2010, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI Another try at fixing the Dwarf issues.) - ) -) - -$(VERSION 044, Apr 30, 2010, =================================================, - - $(WHATSNEW - $(LI Improve spelling checking distance to 2.) - $(LI Now all unittests are run, even if some fail) - $(LI Many small improvements to error diagnostics and recovery) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1079): gdb: Dwarf Error: Cannot find DIE at 0xb705 referenced from DIE at 0x250) - $(LI $(BUGZILLA 2437): ICE(tocsym.c, !needThis()) - default struct argument) - $(LI $(BUGZILLA 2935): ICE(out.c) using struct with constructor as function default argument) - $(LI $(BUGZILLA 2549): Segfault on array multiplication.) - $(LI $(BUGZILLA 3066): Array operation without a slice as the lvalue accepted, bad codegen) - $(LI $(BUGZILLA 3207): gdb: Push D patches upstream) - $(LI $(BUGZILLA 3415): broken JSON output) - $(LI $(BUGZILLA 3522): ICE(cg87.c): variable*array[].) - $(LI $(BUGZILLA 3987): [gdb] Invalid DWARF output for function pointers) - $(LI $(BUGZILLA 3974): ICE(init.c): Static array initializer with more elements than destination array) - $(LI $(BUGZILLA 4036): Segfault with -inline and literal of struct containing union) - $(LI $(BUGZILLA 4037): [gdb] Invalid DWARF output for wchar) - $(LI $(BUGZILLA 4038): [gdb] Invalid DWARF output for function pointers with ref args) - $(LI $(BUGZILLA 4067): [CTFE] Code inside try-catch blocks is silently ignored) - $(LI $(BUGZILLA 4072): Stack overflow on recursive template expansion inside contract) - $(LI $(BUGZILLA 4081): cannot compile the dmd on FreeBSD 8) - $(LI $(BUGZILLA 4089): crash when creating JSON output for incomplete struct) - $(LI $(BUGZILLA 4093): Segfault(interpret.c): with recursive struct templates) - $(LI $(BUGZILLA 4105): Stack overflow involving alias template parameters and undefined identifier) - $(LI $(BUGZILLA 4108): ICE(cod2.c): zero-length static array in function call) - $(LI $(BUGZILLA 4118): std.conv.to!SomeStruct("hello") crashes compiler) - $(LI $(BUGZILLA 4131): break does not work correctly with foreach and associative arrays) - ) -) - -$(VERSION 043, Apr 6, 2010, =================================================, - - $(WHATSNEW - $(LI $(B .init) property for static arrays is now an array literal) - $(LI Improved speed of associative arrays) - $(LI std.bigint has been completely replaced with a faster implementation. - Multiplication is now 5 times faster, division is - 300 times faster, and squaring is 10 times faster. For large numbers - (~5000 words), the speedup is 5 times larger than this.) - ) - $(BUGSFIXED - $(LI Fixed memory corruption problem with array appends) - $(LI $(BUGZILLA 122): DDoc newline behaviour produces suboptimal results) - $(LI $(BUGZILLA 1628): Ddoc produces invalid documentation for --- blocks) - $(LI $(BUGZILLA 2609): No documentation generated for destructor) - $(LI $(BUGZILLA 3808): Assertion Failure : Assertion failure: 'classinfo->structsize == CLASSINFO_SIZE' on line 870 in file 'toobj.c') - $(LI $(BUGZILLA 3884): Segfault: defining a typedef with an invalid object.d) - $(LI $(BUGZILLA 3911): Associative array in CTFE crashes compiler) - $(LI $(BUGZILLA 3958): mixin(non-static method) crashes compiler) - $(LI $(BUGZILLA 3972): Regarding module with name different from its file name) - $(LI $(BUGZILLA 3984): Segfault(interpret.c): CTFE using struct constructor on a local static variable) - $(LI $(BUGZILLA 3986): Struct constructors bypass default initialization of member variables) - $(LI $(BUGZILLA 4002): dmd.conf and binary path in dmd -v output) - $(LI $(BUGZILLA 4004): DMD 2.042 CTFE regression with functions taking ref parameters) - $(LI $(BUGZILLA 4005): std.c.stdlib.exit in CTFE and more) - $(LI $(BUGZILLA 4011): Incorrect function overloading using mixins) - $(LI $(BUGZILLA 4019): [CTFE] Adding an item to an empty AA) - $(LI $(BUGZILLA 4020): [ICE][CTFE] struct postblit in CTFE) - $(LI $(BUGZILLA 4023): std.math.hypot() returns infinity when either argument is zero) - $(LI $(BUGZILLA 4027): Closures in CTFE generate wrong code) - $(LI $(BUGZILLA 4029): CTFE: cannot invoke delegate returned from function) - ) -) - -$(VERSION 042, Mar 19, 2010, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI Add base class destruction to clear() in object.d) - $(LI $(BUGZILLA 3842): ICE(expression.c) using pointer in CTFE) - $(LI $(BUGZILLA 3885): No multithread support for Windows DLL) - $(LI $(BUGZILLA 3899): CTFE: poor error message for use of uninitialized variable) - $(LI $(BUGZILLA 3900): CTFE: Wrong return value for array.var assignment) - $(LI $(BUGZILLA 3901): PATCH: Nested struct assignment for CTFE) - $(LI $(BUGZILLA 3902): Definition of opCmp) - $(LI $(BUGZILLA 3912): pure static nested functions are not recognized as pure) - $(LI $(BUGZILLA 3914): Struct as argument that fits in register has member accessed wrong) - $(LI $(BUGZILLA 3919): ICE(expression.c, 9944): * or / with typedef ireal) - $(LI $(BUGZILLA 3920): Assertion failure: '0' on line 10018 in file 'expression.c') - $(LI $(BUGZILLA 3930): AAs horribly broken) - ) -) - -$(VERSION 041, Mar 7, 2010, =================================================, - - $(WHATSNEW - $(LI __traits allMembers and and derivedMembers now return a tuple of strings - rather than an array of strings. Enclose __traits in [ ] to make array literal. - This makes it possible for foreach statements to iterate at compile time over it. - ) - $(LI Interface member functions can now have $(LINK2 interface.html#InterfaceContracts, contracts).) - $(LI Added new $(LINK2 operatoroverloading.html, operator overloading) regime.) - $(LI Warnings no longer halt the parsing/semantic passes, though they still return - an error status and still do not generate output files. They also no longer count - as errors when testing with "compiles" traits.) - $(LI Added $(B -wi) switch for $(BUGZILLA 2567)) - $(LI Mixin template definitions should be preceded with $(CODE mixin)) - $(LI Add $(LINK2 expression.html#InExpression, $(B !in)) operator.) - $(LI Associative array contents can now be compared for equality) - $(LI Use of $(B length) inside of [ ] is now deprecated, use $(DOLLAR) instead) - $(LI Added $(B toDelegate()) to std.functional to convert function pointers to delegates.) - $(LI Implemented attributes for constructors.) - $(LI Implemented qualifiers for struct literals, like $(CODE immutable(S)(1,2,3))) - $(LI Array equality can now be done with differing array element types.) - $(LI Add simple spell checking.) - $(LI $(BUGZILLA 3378): [tdpl] ++x should be an lvalue) - $(LI string, wstring are now bidirectional (not random) ranges) - $(LI std.algorithm: defined move with one argument; levenshtein distance generalized to with all forward ranges; take now has swapped arguments) - $(LI std.array: empty for arrays is now a @property; front and back for a string and wstring automatically decodes the first/last character; popFront, popBack for string and wstring obey the UTF stride) - $(LI std.conv: changed the default array formatting from "[a, b, c]" to "a b c") - $(LI std.range: swapped order of arguments in take) - $(LI std.stdio: added readln template) - $(LI std.variant: now works with statically-sized arrays and const data) - $(LI std.traits: added isNarrowString) - $(LI The default type for [1,2,3] is now int[] rather than int[3].) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 2321): spec on inline asm can be misunderstood) - $(LI $(BUGZILLA 2463): No line number in "statement is not reachable" warning) - $(LI $(BUGZILLA 3029): Bug in array value mangling rule) - $(LI $(BUGZILLA 3306): bad function/delegate literal generated into header files) - $(LI $(BUGZILLA 3373): bad codeview debug info for long and ulong) - $(LI Posix only, $(BUGZILLA 3420): [PATCH] Allow string import of files using subdirectories) - $(LI $(BUGZILLA 3450): incorrect result for is (typeof({ ... }())) inside a struct) - $(LI $(BUGZILLA 3453): Linking order affects proper execution (Mac OSX only)) - $(LI $(BUGZILLA 3491): typeof((string[string]).init) == AssociativeArray!(string, string), doesn't implicitly convert to string[string].) - $(LI $(BUGZILLA 3500): super behaves differently with -inline) - $(LI $(BUGZILLA 3558): Optimizer bug results in false if condition being taken) - $(LI $(BUGZILLA 3582): core.stdc.ctype functions are not pure) - $(LI $(BUGZILLA 3619): Thread crash on exit) - $(LI $(BUGZILLA 3637): Array append patch to prevent stomping and to enhance thread-local append performance) - $(LI $(BUGZILLA 3644): Wrong UCHAR_MAX value in module core.stdc.limits) - $(LI $(BUGZILLA 3670): Declarator grammar rule is broken) - $(LI $(BUGZILLA 3689): Grammar does not allow const(int)) - $(LI $(BUGZILLA 3692): ICE(mtype.c) with associative arrays when std.variant is imported) - $(LI $(BUGZILLA 3695): __EOF__ token not documented) - $(LI $(BUGZILLA 3697): StructTemplateDeclaration and others missing constraint in rule) - $(LI $(BUGZILLA 3710): Typo in allMembers description?) - $(LI $(BUGZILLA 3736): corrupted struct returned by function with optimizations (-O)) - $(LI $(BUGZILLA 3737): SEG-V at expression.c:6255 from bad opDispatch) - $(LI $(BUGZILLA 3763): std.stdio.readlnImpl absurdly inefficient and overflows stack) - $(LI $(BUGZILLA 3768): reapeted quotes in ddoc.html) - $(LI $(BUGZILLA 3769): Regression: Segfault(constfold.c) array literals and case statements) - $(LI $(BUGZILLA 3775): Segfault(cast.c): casting no-parameter template function using property syntax) - $(LI $(BUGZILLA 3776): Wrong CHAR_MIN value in module core.stdc.limits) - $(LI $(BUGZILLA 3781): ICE(interpret.c): using no-argument C-style variadic function in CTFE) - $(LI $(BUGZILLA 3803): compiler segfaults) - $(LI $(BUGZILLA 3840): Jump to: section in the docs should be sorted) - ) -) - -$(VERSION 040, Jan 29, 2010, =================================================, - - $(WHATSNEW - $(LI Clarification: function returns are not lvalues) - $(LI Added shared static constructors/destructors, regular static - constructors/destructors now deal with TLS) - $(LI Add $(B -map) command line switch) - $(LI Add $(LINK2 attribute.html#disable, $(B @disable)) attribute) - $(LI Delegates and function pointers may be used in CTFE) - $(LI Delegate literals and function literals may be used in CTFE) - $(LI Lazy function parameters may now be used in CTFE) - $(LI Slicing of char[] arrays may now be used in CTFE) - $(LI added static/final function implementations to interfaces) - $(LI added $(B getOverloads), $(B identifier), and $(B isStaticFunction) traits.) - $(LI ModuleInfo changed from class to struct) - $(LI $(BUGZILLA 3556): version(CTFE)) - $(LI $(BUGZILLA 3728): getOverloads and identifier traits) - ) - $(BUGSFIXED - $(LI Added TLS support for OSX) - $(LI $(CPPBUGZILLA 47): Internal error: cg87 3316) - $(LI $(BUGZILLA 1298): CTFE: tuple foreach bugs) - $(LI $(BUGZILLA 1790): CTFE: foreach(Tuple) won't compile if Tuple contains string) - $(LI $(BUGZILLA 2101): CTFE: Please may I use mutable arrays at compile time?) - $(LI $(BUGZILLA 2066): to!(string)(int) into CTFE-compatible) - $(LI $(BUGZILLA 3488): Segfault(expression.c): enum declared with struct static initializer) - $(LI $(BUGZILLA 3535): struct constructors don't work in CTFE) - $(LI $(BUGZILLA 3552): ICE(mtype.c): declaring a variable called 'AssociativeArray' then using an AA.) - $(LI Partial fix for $(BUGZILLA 3569), stops the stack overflow) - $(LI $(BUGZILLA 3600): template instantiation with empty tuple) - $(LI $(BUGZILLA 3660): Templates and shared functions don't mix) - $(LI $(BUGZILLA 3668): foreach over typedef'd array crashes dmd) - $(LI $(BUGZILLA 3671): x^^3 gives wrong result when x is a floating-point literal) - $(LI $(BUGZILLA 3674): forward reference error with multiple overloads with same name) - $(LI $(BUGZILLA 3675): Regression: Struct literals cannot be initialized with another struct literal) - $(LI $(BUGZILLA 3687): Array operation "slice times scalar" tramples over memory) - $(LI $(BUGZILLA 3719): forward references can cause out-of-memory error) - $(LI $(BUGZILLA 3723): Regression: forward referenced enum) - $(LI $(BUGZILLA 3724): bug in Expression::arraySyntaxCopy (null pointer dereference on struct->union->struct)) - $(LI $(BUGZILLA 3726): Regression: ICE(mangle.c 81): struct forward reference with static this) - $(LI $(BUGZILLA 3727): lots of "deffering SomeStructName" messages when compiling) - $(LI $(BUGZILLA 3734): [patch] src/traits.c does not compile with gcc (Ubuntu 4.4.1-4ubuntu8) 4.4.1) - $(LI $(BUGZILLA 3740): Regression: class with fwd reference of a nested struct breaks abstract) - ) -) - -$(VERSION 039, Jan 1, 2010, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI $(BUGZILLA 3663): struct forward reference regresssion) - $(LI $(BUGZILLA 3664): struct forward declaration causes enum to conflict with itself) - ) -) - -$(VERSION 038, Dec 30, 2009, =================================================, - - $(WHATSNEW - $(LI Added core.cpuid in Druntime) - $(LI $(BUGZILLA 3514): opApply should be the first-choice foreach iteration method.) - $(LI $(BUGZILLA 3577): Wrong precedence for opPow) - $(LI Added $(LINK2 function.html#auto-ref-functions, auto ref functions)) - $(LI Added $(LINK2 template.html#auto-ref-parameters, function template auto ref parameters)) - $(LI Added $(B isRef), $(B isOut) and $(B isLazy) to $(LINK2 traits.html, $(D_KEYWORD __traits))) - $(LI Transporting return type from args to return type, see $(LINK2 http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP2, DIP2)) - ) - $(BUGSFIXED - $(LI $(CPPBUGZILLA 45): Internal error: cgcod 1594) - $(LI $(CPPBUGZILLA 46): Constant folding with long doubles) - $(LI $(BUGZILLA 282): Bizarre circular import nested name invisibility issue) - $(LI $(BUGZILLA 390): Cannot forward reference enum nested in struct) - $(LI $(BUGZILLA 400): forward reference error; no propety X for type Y (struct within struct)) - $(LI $(BUGZILLA 1160): enums can not be forward referenced) - $(LI $(BUGZILLA 1564): Forward reference error for enum in circular import) - $(LI $(BUGZILLA 2029): Typesafe variadic functions don't work in CTFE) - $(LI $(BUGZILLA 2816): Sudden-death static assert is not very useful) - $(LI $(BUGZILLA 3270): pure functions returning struct) - $(LI $(BUGZILLA 3443): Thread.thread_needLock() should be nothrow) - $(LI $(BUGZILLA 3455): Some Unicode characters not allowed in identifiers) - $(LI $(BUGZILLA 3458): int fsync(int) commented out in core.sys.posix.unistd) - $(LI $(BUGZILLA 3476): C-style initializer for structs must be disallowed for structs with a constructor) - $(LI $(BUGZILLA 3575): CTFE: member structs not initialized correctly) - $(LI $(BUGZILLA 3583): Unsigned right shift works the same as signed right shift.) - $(LI $(BUGZILLA 3584): DeclDef rule is missing entries) - $(LI $(BUGZILLA 3585): Duplicate clauses in EqualExpression and RelExpression rules) - $(LI $(BUGZILLA 3587): Aggregate rule references undefined Tuple) - $(LI $(BUGZILLA 3588): WithStatement rule references unspecified Symbol) - $(LI $(BUGZILLA 3589): BaseClassList and InterfaceClasses rules are incorrect, missing ',') - $(LI $(BUGZILLA 3590): FunctionParameterList rule is missing) - $(LI $(BUGZILLA 3591): TemplateIdentifier rule is misspelled) - $(LI $(BUGZILLA 3592): ClassTemplateDeclaration and FunctionTemplateDeclaration rules are unreferenced) - $(LI $(BUGZILLA 3593): IntegerExpression rule unspecified) - $(LI $(BUGZILLA 3594): AsmPrimaryExp rule references unspecified rules) - $(LI $(BUGZILLA 3595): Several rules are missing ':' after rule name) - $(LI $(BUGZILLA 3596): Need alias for using std.algorithm.remove) - $(LI $(BUGZILLA 3601): Debug and Release builds of DMD produce different object files) - $(LI $(BUGZILLA 3611): Enum forward referencing regression) - $(LI $(BUGZILLA 3612): ExpressionList is undefined) - $(LI $(BUGZILLA 3617): CTFE: wrong code for if(x) where x is int or smaller) - $(LI $(BUGZILLA 3621): implicit conversion to const rules need tightening) - $(LI $(BUGZILLA 3633): Optimizer causes access violation) - $(LI $(BUGZILLA 3641): alias shared T U does not work) - $(LI $(BUGZILLA 3645): manifest constant (enum) crashes dmd) - $(LI $(BUGZILLA 3647): non-function opDispatch crashes dmd) - ) -) - -$(VERSION 037, Dec 3, 2009, =================================================, - - $(WHATSNEW - $(LI Conditional expressions ?: can now be modifiable lvalues.) - $(LI The type inferred from an - $(LINK2 expression.html#ArrayLiteral, $(I ArrayLiteral)) - is now a dynamic array, not a static one.) - $(LI Added support for $(I op)= for array.length) - $(LI Array and associative array types are now determined by using ?: across - all the elements, not just using the first one.) - $(LI Array concatenation with elements now allows implicit conversion of - the elements to the array element type.) - $(LI No more comma operators allowed between [ ].) - $(LI ClassInfo now merged into TypeInfo_Class.) - $(LI $(BUGZILLA 3379): [tdpl] Parameter names not visible in the if clause of a template) - $(LI $(BUGZILLA 3380): [tdpl] typeid(obj) should return the dynamic type of the object) - $(LI Removed $(B -safe) command line switch, added $(B -noboundscheck) command - line switch.) - $(LI $(BUGZILLA 3481): PATCH: opPow(), x ^^ y as a power operator) - $(LI Added opDispatch) - $(LI properties can only have 0 or 1 arguments) - $(LI properties cannot be overloaded with non-properties) - $(LI std.math: Added FloatControl, IeeeFlags for enabling floating-point exceptions.) - $(LI std.math: Inverse trig functions are now pure nothrow.) - ) - $(BUGSFIXED - $(LI std.array: Fixed unlisted bug in array().) - $(LI $(BUGZILLA 111): appending a dchar to a char[]) - $(LI $(BUGZILLA 2664): OSX standard math functions are less accurate) - $(LI $(BUGZILLA 2802): VariantN.opCmp!(T) fails when T != VariantN) - $(LI $(BUGZILLA 2967): spec does not mention that inline asm is a valid "return" statement) - $(LI $(BUGZILLA 2977): std.random.unpredictableSeed() should use thread ID somewhere) - $(LI $(BUGZILLA 3115): >>> and >>>= generate wrong code) - $(LI $(BUGZILLA 3171): % not implemented correctly for floats) - $(LI $(BUGZILLA 3311): std.range.chain shouldn't have opIndexAssign if arguments aren't mutable) - $(LI $(BUGZILLA 3375): [tdpl] Ternary operator doesn't yield an lvalue) - $(LI $(BUGZILLA 3381): [tdpl] Incorrect assessment of overriding in triangular-shaped hierarchy) - $(LI $(BUGZILLA 3388): [tdpl] contracts should allow throw expressions) - $(LI $(BUGZILLA 3390): [tdpl] out(result) contract should not be able to rebind result) - $(LI $(BUGZILLA 3407): [tdpl] Compiling with -safe -release must keep all bound checks) - $(LI $(BUGZILLA 3433): [tdpl] Comparing structs for equality is not member-by-member) - $(LI $(BUGZILLA 3469): ICE(func.c): Regression. Calling non-template function as a template, from another module) - $(LI $(BUGZILLA 3478): "no effect in expression" error on return to void) - $(LI $(BUGZILLA 3494): Segfault(mtype.c) using typeof(return) inside an auto function) - $(LI $(BUGZILLA 3495): Segfault(typinf.c) instantiating D variadic function with too few arguments) - $(LI $(BUGZILLA 3496): ICE(cgelem.c, optimizer bug) cast(void *)(x&1)== null.) - $(LI $(BUGZILLA 3502): Fix for dropped Mac OS X 10.5) - $(LI $(BUGZILLA 3521): Optimized code access popped register) - $(LI $(BUGZILLA 3540): Another DWARF line number fix) - $(LI $(BUGZILLA 3551): nested struct => dmd adds a hidden pointer) - $(LI $(BUGZILLA 3553): ICE when a function argument defaults to __LINE__) - ) -) - -$(VERSION 036, Nov 5, 2009, =================================================, - - $(WHATSNEW - $(LI Static arrays are now passed by value to functions rather than by reference) - $(LI std.algorithm: Add hasLength requirement to topN; - implemented topN for two non-adjacent ranges; added replaceTop - function to BinaryHeap; changed BinaryHeap.top to return ref.) - $(LI std.ctype: Add pure to isalnum, isalpha, iscntrl, isdigit, - islower, ispunct, isspace, isxdigit, isgraph, isprint, isascii, - toupper.) - $(LI std.date: Implementation change and unittest for isLeapYear and - daysInYear. Made both pure as well.) - $(LI std.encoding: Added function count().) - $(LI std.md5: Added explicit pass-by-ref for fixed-size buffers.) - $(LI std.numeric: Added gcd.) - $(LI std.random: Added static checks for the parameters of the linear - congruential generator.) - $(LI std.range: Reinstated some unittests; fixed Cycle to work with - the new fixed-size arrays.) - $(LI std.typecons: Added alias 'expand' for Tuple.field.) - $(LI std:utf: Added count function and changed the encode function - to take fixed-size array by reference.) - $(LI $(BUGZILLA 3446): Rename float.min to float.min_normal) - ) - $(BUGSFIXED - $(LI std.range: Fixed unlisted bug in Transposed.) - $(LI Problem with complicated array op expressions) - $(LI $(BUGZILLA 195): DDoc generates bad output when example contains "protected" attribute) - $(LI $(BUGZILLA 424): Unexpected OPTLINK Termination at EIP=0044C37B (too many fixups)) - $(LI $(BUGZILLA 1117): ddoc generates corrupted docs if code examples contain attributes with colons) - $(LI $(BUGZILLA 1812): DDOC - Unicode identifiers are not correctly marked.) - $(LI $(BUGZILLA 2694): alias pure nothrow XXX; is not pure nothrow!) - $(LI $(BUGZILLA 2862): ICE(template.c) using type tuple as function argument) - $(LI $(BUGZILLA 3035): cannot have const/invariant out parameter of type shared) - $(LI $(BUGZILLA 3102): Incorrectly matching type as shared (two cases with is expressions)) - $(LI $(BUGZILLA 3269): pure functions silently become nothrow) - $(LI $(BUGZILLA 3292): ICE(todt.c) when using a named mixin with an initializer as template alias parameter) - $(LI $(BUGZILLA 3349): typeid(shared(T)) generates wrong value) - $(LI $(BUGZILLA 3367): Regression: struct initialization no longer supports ctor overloads) - $(LI $(BUGZILLA 3397): Unintended function call to static opCall) - $(LI $(BUGZILLA 3401): Compiler crash on invariant + method overload) - $(LI $(BUGZILLA 3422): ICE(cgcod.c) Structs with default initializers bigger than register size cannot be default parameters) - $(LI $(BUGZILLA 3423): Destructor and postblit don't get copied to the header file when using -H) - $(LI $(BUGZILLA 3426): ICE(optimize.c): struct literal with cast, as function default parameter.) - $(LI $(BUGZILLA 3429): Core dump on passing template literal to member function.) - $(LI $(BUGZILLA 3432): ICE(e2ir.c): casting template expression) - ) -) - -$(VERSION 035, Oct 14, 2009, =================================================, - - $(WHATSNEW - $(LI Use $(B -X) to generate JSON files.) - ) - $(BUGSFIXED - $(LI Fold in patch from $(BUGZILLA 1170)) - $(LI $(BUGZILLA 1534): Can't mix in a case statement.) - $(LI $(BUGZILLA 2423): Erroneous unreachable statement warning) - $(LI $(BUGZILLA 2826): failed assignment gives wrong line number) - $(LI $(BUGZILLA 3190): enum doesn't work as the increment in a for loop) - $(LI $(BUGZILLA 3316): Functions nested in a pure templated function cannot reference its local variables) - $(LI $(BUGZILLA 3352): RangeError in std.conv) - $(LI $(BUGZILLA 3385): `std.string.split` requires a mutable array) - $(LI $(BUGZILLA 3392): a cast of this to void in tango.core.Thread is not allowed) - ) -) - -$(VERSION 034, Oct 11, 2009, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI $(BUGZILLA 258): Undefined identifier error for circular import) - $(LI $(BUGZILLA 1140): ICE(cod1.c) casting last function parameter to 8 byte value) - $(LI $(BUGZILLA 1592): dmd fail to resolve class symbol when i put files in a package) - $(LI $(BUGZILLA 2687): ICE(statement.c): tuple foreach in an erroneous template.) - $(LI $(BUGZILLA 2773): ICE(go.c) array assignment through a pointer, only with -O.) - $(LI $(BUGZILLA 2829): ICE(expression.c) static array block-initialized in struct literal) - $(LI $(BUGZILLA 3006): ICE(e2ir.c, tocsym.c) template module using array operation) - $(LI $(BUGZILLA 3041): Array slices can be compared to their element type: bad codegen or ICE) - $(LI $(BUGZILLA 3042): Segfault on incorrect override) - $(LI $(BUGZILLA 3101): Stack overflow: declaring aggregate member twice with static if) - $(LI $(BUGZILLA 3119): Segfault(expression.c) template function overloads with function with same name in other module) - $(LI $(BUGZILLA 3174): ICE(mtype.c): Compiler crash or compiler error with auto returns and const / immutable / invarient / pure) - $(LI $(BUGZILLA 3176): Compiler hangs on poorly formed mixin in variadic template) - $(LI $(BUGZILLA 3261): compiler crash with mixin and forward reference) - $(LI $(BUGZILLA 3286): Default parameter prevents to resolve inter-module circular dependency) - $(LI $(BUGZILLA 3301): Undefined identifier error dependent on order of imports when a circular import is involved) - $(LI $(BUGZILLA 3325): ICE(func.c) function literal with post-contract) - $(LI $(BUGZILLA 3343): Crash by "auto main(){}") - $(LI $(BUGZILLA 3344): ICE(e2ir.c) returning an invalid function from main()) - $(LI $(BUGZILLA 3357): ICE(cod1.c) using 'in' with a static char array as AA key) - $(LI $(BUGZILLA 3366): Segfault(declaration.c) variadic template with unmatched constraint) - $(LI $(BUGZILLA 3374): [tdpl] ICE(init.c): Associative array type not inferred) - ) -) - -$(VERSION 033, Oct 5, 2009, =================================================, - - $(WHATSNEW - $(LI Phobos is now using the Boost 1.0 license) - $(LI Compiler now detects some cases of illegal null dereferencing when compiled with -O) - $(LI The result type of the $(CODE typeid($(I type))) is now the most derived TypeInfo class, rather than the TypeInfo base class) - $(LI $(BUGZILLA 2905): Faster +-*/ involving a floating-pointing literal) - $(LI Improved performance of int-to-string conversion) - ) - $(BUGSFIXED - $(LI gdb stack trace should work now) - $(LI $(BUGZILLA 302): in/out contract inheritance yet to be implemented) - $(LI $(BUGZILLA 718): ICE(cgcod.c) with int /= cast(creal)) - $(LI $(BUGZILLA 814): lazy argument + variadic arguments = segfault) - $(LI $(BUGZILLA 1168): Passing a .stringof of an expression as a template value parameter results in the string of the type) - $(LI $(BUGZILLA 1253): array initializers as expressions are not allowed in const arrays) - $(LI $(BUGZILLA 1571): Segfault(class.c) const on function parameters not carried through to .di file) - $(LI $(BUGZILLA 1731): forward reference of function type alias resets calling convention) - $(LI $(BUGZILLA 2202): Error getting type of non-static member of a class) - $(LI $(BUGZILLA 2469): ICE(cod1.c) arbitrary struct accepted as struct initializer) - $(LI $(BUGZILLA 2697): Cast of float function return to ulong or uint gives bogus value) - $(LI $(BUGZILLA 2702): Struct initialisation silently inserts deadly casts) - $(LI $(BUGZILLA 2839): ICE(cgcs.c) with int /= imaginary) - $(LI $(BUGZILLA 2970): std.path.join with version(Windows)) - $(LI $(BUGZILLA 2998): ICE(expression.c) with floating point enum) - $(LI $(BUGZILLA 3049): ICE(cod4.c) or segfault: Array operation on void[] array) - $(LI $(BUGZILLA 3059): Nonsensical complex op= should be illegal) - $(LI $(BUGZILLA 3132): std.string.split should be templated on mutable/const/immutable - closing again after the reopening on 2009-09-03 07:56:25 PDT) - $(LI $(BUGZILLA 3160): ICE(cgcod.c 1511-D1) or bad code-D2 returning string from void main) - $(LI $(BUGZILLA 3173): ICE(mtype.c) on wrong code (double to long to int conversion)) - $(LI $(BUGZILLA 3288): conv.d: using to with const int or long fails to compile.) - $(LI $(BUGZILLA 3300): std.string.toupper and tolower should be (const(char)[]), not string) - $(LI $(BUGZILLA 3304): Segfault using 'is' with a pointer enum.) - $(LI $(BUGZILLA 3305): Segfault(expression.c) with recursive struct template alias expressions) - $(LI $(BUGZILLA 3333): std.conv.to!(string, const int) error: cannot modify const) - $(LI $(BUGZILLA 3335): minor warning cleanups) - $(LI $(BUGZILLA 3336): ICE(glue.c) declaring AA with tuple key, only with -g) - $(LI $(BUGZILLA 3340): std.string.split(S1 s, S2 delim) still doesn't work for char[]) - $(LI $(BUGZILLA 3353): storage class of a member function is propagated to default arguments) - $(LI (unlisted): std.algorithm: bug in reduce when passed const arguments) - $(LI (unlisted): std.stdio: fixed documentation example) - $(LI (unlisted): std.utf: fixed decodeFront and decodeBack) - ) -) - -$(VERSION 032, Sep 2, 2009, =================================================, - - $(WHATSNEW - $(LI Improved exception message for assert(0) in Windows -release builds) - $(LI Added support for: ---- -a[i].var = e2 ---- - and: ---- -a[] = e ---- - in CTFE. $(I (thanks, Don!))) - $(LI Member functions can now be used in CTFE) - $(LI Operator overloading can now be used in CTFE) - $(LI Nested functions can now be used in CTFE) - $(LI CTFE error messages now explain why the function could not be - interpreted at compile time) - $(LI synchronized member functions now implicitly typed as shared.) - $(LI std.algorithm: added minPos) - $(LI std.format: added raw specifier for reading) - $(LI added File.byChunk) - $(LI std.algorithm: added more unittests and checks for user-based comparison passed to topN) - $(LI std.math: replaced std.c with core.stdc; improved approxEqual to work with ranges, not only numbers or arrays) - $(LI std.range: defined Take.popBack whenever sensible; improved iota to accept negative ranges and steps) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 601): statement.html - Formatting/markup errors in BNF) - $(LI $(BUGZILLA 1461): Local variable as template alias parameter breaks CTFE) - $(LI $(BUGZILLA 1600): Functions taking only one array cannot be called with property syntax) - $(LI $(BUGZILLA 1604): Non-final method on final struct is too restrictive (closed with "invalid" advise)) - $(LI $(BUGZILLA 1605): break in switch with goto breaks in ctfe) - $(LI $(BUGZILLA 1616): std/metastrings.d) - $(LI $(BUGZILLA 1940): Phobos buildscripts do not work on x86_64) - $(LI $(BUGZILLA 1948): CTFE fails when mutating a struct in an array) - $(LI $(BUGZILLA 1950): CTFE doesn't work correctly for structs passed by ref) - $(LI $(BUGZILLA 1969): ICE(cod1.c) using undefined operator with one const operand) - $(LI $(BUGZILLA 1972): Foreach range statement breaks CTFE) - $(LI $(BUGZILLA 2150): cannot get values from const variant) - $(LI $(BUGZILLA 2277): array ops and const arrays incompatible) - $(LI $(BUGZILLA 2398): writef("%x") for a pointer is always uppercase) - $(LI $(BUGZILLA 2560): ICE(cod4.c) on invoking method that takes ref const struct parameter) - $(LI $(BUGZILLA 2564): CTFE: the index in a tuple foreach is uninitialized (bogus error)) - $(LI $(BUGZILLA 2569): static arrays in CTFE functions don't compile) - $(LI $(BUGZILLA 2575): gdb can not show code) - $(LI $(BUGZILLA 2587): std.process.shell doesn't work for win32) - $(LI $(BUGZILLA 2604): DW_TAG_module and GDB) - $(LI $(BUGZILLA 2665): ICE(cod4.c) on certain const struct function return types) - $(LI $(BUGZILLA 2784): Interfaces should be able to require type definitions (closed with "invalid" advise)) - $(LI $(BUGZILLA 2785): Interfaces should be able to require non-member functions (closed with "invalid" advise)) - $(LI $(BUGZILLA 2786): Interfaces should be able to require constructors (closed with "invalid" advise)) - $(LI $(BUGZILLA 2882): std.random.MersenneTwisterEngine without no seed) - $(LI $(BUGZILLA 2925): Destructor not called) - $(LI $(BUGZILLA 2937): postblit not called for foreach arg over array of structs) - $(LI $(BUGZILLA 2940): null is null cannot be evaluated at compile time) - $(LI $(BUGZILLA 2976): rename retreatN to retreat) - $(LI $(BUGZILLA 2979): Xml tags with only attributes return as without attributes ElementParser.parse) - $(LI $(BUGZILLA 2980): compiler error when writefln( uint )) - $(LI $(BUGZILLA 2987): D2 phobos BigInt opMul doesn't work correctly) - $(LI $(BUGZILLA 2988): Chain needs opIndexAssign.) - $(LI $(BUGZILLA 2989): std.typetuple: add support for any static tuples) - $(LI $(BUGZILLA 2992): (closed with "later" advise)) - $(LI $(BUGZILLA 2996): std.typetuple: add support for any static tuples) - $(LI $(BUGZILLA 3000): iota should work with floats) - $(LI $(BUGZILLA 3017): doc errors in std.range (on behalf of Steven Schveighoffer)) - $(LI $(BUGZILLA 3025): uniform(float,float) pops first, uniform(int,int) pops last) - $(LI $(BUGZILLA 3037): Off-by-one error in Stride.length) - $(LI $(BUGZILLA 3039): -vtls compiler flag not listed in man file) - $(LI $(BUGZILLA 3058): [CTFE] Cannot return out of foreach range statement) - $(LI $(BUGZILLA 3074): std.conv.to!(string)(int.min)) - $(LI $(BUGZILLA 3077): 3077 crash exiting main() without result code) - $(LI $(BUGZILLA 3087): std.range.retro.opIndex out of range) - $(LI $(BUGZILLA 3098): std.algorithm.reduce example can not compile) - $(LI $(BUGZILLA 3100): ICE(cast.c) struct with members is shared) - $(LI $(BUGZILLA 3132): std.string.split should be templated on mutable/const/immutable) - $(LI $(BUGZILLA 3148): syntax error using invariant) - $(LI $(BUGZILLA 3153): win32.mak tries to copy phobos.lib, gcstub.obj to nonexistent folder lib) - $(LI $(BUGZILLA 3162): can't fully use compile-time floats as template parameters) - $(LI $(BUGZILLA 3165): What kind of integer division does D use?) - $(LI $(BUGZILLA 3166): "positive" -> "non-negative" in modulo operator description) - $(LI $(BUGZILLA 3169): Segfault(cast.c) dividing ulong by int) - $(LI $(BUGZILLA 3170): Forward reference of nested class fails if outer class is not plain) - $(LI $(BUGZILLA 3183): Spec of align attribute needs work) - $(LI $(BUGZILLA 3184): std.algorithm.until should work like "find") - $(LI $(BUGZILLA 3185): osx is not a directory (complains cannot read std/c/osx/socket.d)) - $(LI $(BUGZILLA 3186): corrections for http://www.digitalmars.com/d/2.0/dmd-osx.html) - $(LI $(BUGZILLA 3189): `std.conv.to` : check for a custom `to` method in classes/structs) - $(LI $(BUGZILLA 3192): asm in a anonymous delegate crash the compiler) - $(LI $(BUGZILLA 3195): `std.conv` pureness (closed with "later" advise)) - $(LI $(BUGZILLA 3196): Segfault(mtype.c) after almost any error involving a delegate literal) - $(LI $(BUGZILLA 3197): Minor fixes and additions to std.traits) - $(LI $(BUGZILLA 3199): sort(chain(...)) doesn't work in some cases) - $(LI $(BUGZILLA 3205): CTFE: $ cannot be used in lvalues) - $(LI $(BUGZILLA 3212): Error message says "mutable"; should say "immutable") - $(LI $(BUGZILLA 3217): std.functional.binaryFunImpl doesn't support UDT with string functions , therefore neither does many std.algorithm functions) - $(LI $(BUGZILLA 3218): Performance of std.xml.encode must be improved) - $(LI $(BUGZILLA 3219): Inaccurate std.conv.to!(numeric)(numeric) error messages) - $(LI $(BUGZILLA 3224): std.random documentation bugs) - $(LI $(BUGZILLA 3229): No return or assert(0) at end of function) - $(LI $(BUGZILLA 3236): Postblit called but no matching destructor) - $(LI $(BUGZILLA 3239): std.conv.roundTo does not accept const/immutable/shared) - $(LI $(BUGZILLA 3240): std.numeric.findRoot only works with real) - $(LI $(BUGZILLA 3242): splitter does not handle input range made of a unique separator correctly) - $(LI $(BUGZILLA 3245): Easy bug fix available for disabled unit test code in std.encoding) - $(LI $(BUGZILLA 3246): ICE(init.c) using indexed array initializer on local array) - $(LI $(BUGZILLA 3249): sort and setIntersection on array of struct or class) - $(LI $(BUGZILLA 3253): DMD crashes on function pointer struct member initialization with function literal) - $(LI $(BUGZILLA 3255): final switch broken with -w switch) - $(LI $(BUGZILLA 3257): Spec is unclear describing string switch case labels) - $(LI $(BUGZILLA 3260): "Error: undefined identifier backend" when compiling 'write' with 'wchar') - $(LI $(BUGZILLA 3264): -O causes wrong "used before set" error when using enum.) - $(LI $(BUGZILLA 3281): ICE(cod1.c) append returned struct to array) - $(LI Fixed bug processing spaces in dmd's directory) - $(LI Fixed assert failure on line 4823 in expression.c) - $(LI Fixed OSX compile error on samples/d/dhry.d) - $(LI std.format: fixed unlisted bug in documentation) - $(LI std.random: uniform does not work when passed immutable data) - $(LI std.range: fixed unlisted bug in Take.back) - $(LI unlisted: made entropy work on const/immutable arrays) - ) -) - -$(VERSION 031, July 6, 2009, =================================================, - - $(WHATSNEW - $(LI Renamed root directory \dmd to \dmd2) - $(LI Use of with symbols that shadow local symbols is no longer allowed) - $(LI Added $(LINK2 statement.html#FinalSwitchStatement, final switch statements)) - $(LI Added $(LINK2 statement.html#CaseRangeStatement, case range statements)) - $(LI Implicit integral conversions that could result in loss of significant - bits are no longer allowed.) - $(LI Warning on no return expr; is now an error.) - $(LI $(BUGZILLA 3080): dmd should output compilation errors to stderr, not stdout) - $(LI $(BUGZILLA 3122): [patch] Adding support for fast and reliable build tools to the frontend) - $(LI std.algorithm: Made std.algorithm.swap faster by having it use memcpy; added std.algorithm.group, std.algorithm.until, std.algorithm.nWayUnion, std.algorithm.largestPartialIntersectionWeighted; added additional constraints to std.algorithm.equal; changed signature of std.algorithm.topNIndex and std.algorithm.topNCopy to use an enum parameter instead of a confusing bool.) - $(LI std.array: added array function.) - $(LI std.conv: added Shin Fujishiro's code for printing and parsing enumerated values.) - $(LI std.ctype: made isupper and tolower pure.) - $(LI std.date: changed signature of benchmark to return ulong[] instead of uint[].) - $(LI std.demangle: changed it to use the snazzy switch statement with ranged labels.) - $(LI std.random: added randomSample) - $(LI std.string: deprecated std.string.find and std.string.find, replaced with std.string.indexOf; deprecated std.string.rfind and std.string.irfind, replaced with std.string.lastIndexOf; added flag CaseSensitive for indexOf and lastIndexOf; removed startsWith and endsWith because std.algorithm defines them; defined std.string.byDchar.) - $(LI std.traits: added isSomeChar, isPointer.) - $(LI std.typetuple: replaced indexOf with indexOfType, kept the old name as an alias that will be deprecated.) - $(LI std.utf: improved error messages.) - ) - $(BUGSFIXED - $(LI Fix dmd crash on multicore Windows.) - $(LI Fixed unlisted bug in std.algorithm.startsWith) - $(LI Fixed unlisted bug in std.algorithm.topN) - $(LI Fixed unlisted bug in std.algorithm.topNIndex (empty index made it crash)) - $(LI Fixed unlisted bug in std.algorithm.setIntersection) - $(LI Fixed unlisted bug in std.range.retro: retro'izing a range twice must return the original range) - $(LI $(BUGZILLA 106): template - mixin sequence) - $(LI $(BUGZILLA 810): Cannot forward reference template) - $(LI $(BUGZILLA 852): ICE(toir.c) using local class in non-static nested function in nested static function) - $(LI $(BUGZILLA 1343): Various errors with static initialization of structs and arrays) - $(LI $(BUGZILLA 1358): ICE(root.c) on Unicode codepoints greater than 0x7FFFFFFF) - $(LI $(BUGZILLA 1524): ICE(constfold.c) on using "is" with strings in CTFE) - $(LI $(BUGZILLA 1984): Assertion failure: 'e1->type' on line 1198 in file 'constfold.c') - $(LI $(BUGZILLA 2323): ICE(cgcs.c): taking address of a method of a temporary struct) - $(LI $(BUGZILLA 2399): ICE(cgcod.c) on casting function to delegate) - $(LI $(BUGZILLA 2429): std.stream.File incorrect flag parsing and sharing mode) - $(LI $(BUGZILLA 2432): complex alias -> mtype.c:125: virtual Type* Type::syntaxCopy(): Assertion `0' failed.) - $(LI $(BUGZILLA 2603): ICE(cgcs.c) on subtracting string literals) - $(LI $(BUGZILLA 2843): ICE(constfold.c) with is-expression with invalid dot-expression in is-expression involving typeid) - $(LI $(BUGZILLA 2865): RandomCover not random) - $(LI $(BUGZILLA 2875): ICE(cgcod.c) setting delegate = &Struct.func) - $(LI $(BUGZILLA 2884): ICE: Assert: 'template.c', line 3773, 'global.errors') - $(LI $(BUGZILLA 2888): [PATCH] speedup for float * 2.0) - $(LI $(BUGZILLA 2900): Array appending slowed drastically since integration of druntime) - $(LI $(BUGZILLA 2915): [Patch]: Optimize -a*-b into a*b) - $(LI $(BUGZILLA 2923): -O generates bad code for ?:) - $(LI $(BUGZILLA 2932): bad e_ehsize (36 != 52)) - $(LI $(BUGZILLA 2952): Segfault on exit when using array ops with arrays of doubles larger than 8 elements) - $(LI $(BUGZILLA 2974): Segfault(mtype.c) on auto function) - $(LI $(BUGZILLA 2981): Bad code generation for structs containing invariants) - $(LI $(BUGZILLA 2982): Assertion failure in function if() clause) - $(LI $(BUGZILLA 3003): Need to implicitly add () on member template function calls) - $(LI $(BUGZILLA 3014): ICE(template.c) instantiating template with tuple) - $(LI $(BUGZILLA 3016): Errors in the documentation of std.math.acos) - $(LI $(BUGZILLA 3026): Segfault with incomplete static array initializer) - $(LI $(BUGZILLA 3044): Segfault(template.c) instantiating struct tuple constructor with zero arguments.) - $(LI $(BUGZILLA 3071): nested func declaration parse problem) - $(LI $(BUGZILLA 3078): NaN reported as equal to zero) - $(LI $(BUGZILLA 3081): unaryFun can't be used to get element out of struct.) - $(LI $(BUGZILLA 3095): wc example for D2 doesn't compile) - $(LI $(BUGZILLA 3114): optlink failing on multicore machines) - $(LI $(BUGZILLA 3117): dmd crash by *1) - $(LI $(BUGZILLA 3121): recurrence does not generate the correct numbers) - $(LI $(BUGZILLA 3128): Internal error: ..\ztc\cod4.c 2737) - $(LI $(BUGZILLA 3130): Crashed with triple stars) - ) -) - -$(VERSION 030, May 11, 2009, =================================================, - - $(WHATSNEW - $(LI added $(B -vtls) compiler switch) - $(LI $(RED classic global storage now defaults to TLS (Thread Local Storage)). - This is a big change, see $(LINK2 migrate-to-shared.html, Migrating To Shared).) - $(LI std.algorithm: added minPos. Improvements to Splitter suggested by Brad Roberts. Splitter now is bidirectional. Also Splitter has one extra trailing element if it ends with a separator. Added variadic arguments for setUnion and setIntersection. Added functions setSymmetricDifference and largestPartialIntersection. Improved BinaryHeap's interface and implementation.) - $(LI std.array: Improvements to Appender. Now it works with string and other immutable-element arrays, and accepts ranges in put().) - $(LI std.format: added raw specifier for reading) - $(LI std.range: Added iota with two arguments. Added FrontTransversal and Transversal.) - $(LI std.stdio: added File.byChunk) - $(LI std.traits: Added isImplicitlyConvertible.) - $(LI std.tuple: Added Tuple.opComp.) - $(LI Folded in compiler changes by Unknown W. Brackets - to support Solaris.) - $(LI added .typeinfo to ClassInfo $(BUGZILLA 2836): Navigate from ClassInfo to TypeInfo) - ) - $(BUGSFIXED - $(LI Fix instruction scheduler bug on Linux) - $(LI unlisted: made std.numeric.entropy work on const/immutable arrays) - $(LI Fixed several problems associated with thread local storage) - $(LI $(BUGZILLA 642): error: mixin "static this" into where it cannot be) - $(LI $(BUGZILLA 713): circular const definitions with module operator "." cause the compiler to segfault) - $(LI $(BUGZILLA 752): Assertion failure: 'e->type->ty != Ttuple' on line 4518 in file 'mtype.c') - $(LI $(BUGZILLA 858): Forward reference to struct inside class crashes the compiler) - $(LI $(BUGZILLA 884): Segfault in recursive template) - $(LI $(BUGZILLA 934): Segfault taking mangleof a forward reference in a template.) - $(LI $(BUGZILLA 1011): illegal import declaration causes compile time segfault) - $(LI $(BUGZILLA 1054): regression: circular aliases cause segfaults) - $(LI $(BUGZILLA 1061): "asm inc [;" segfaults compiler.) - $(LI $(BUGZILLA 1305): Compiler hangs with templated opCmp returning templated class) - $(LI $(BUGZILLA 1385): Stack Overflow with huge array literal.) - $(LI $(BUGZILLA 1428): Segfault on template specialization with delegates and tuples) - $(LI $(BUGZILLA 1791): Segmentation fault with anon class in anon class and non-constant variable init) - $(LI $(BUGZILLA 1916): segfault on invalid string concat) - $(LI $(BUGZILLA 1946): Compiler crashes on attempt to implicit cast const typedef to non-const.) - $(LI $(BUGZILLA 2048): DMD crash on CTFE that involves assigning to member variables of void-initialized struct) - $(LI $(BUGZILLA 2061): wrong vtable call with multiple interface inheritance) - $(LI $(BUGZILLA 2215): Forward reference enum with base type within a struct causes Segmentation Fault in the compiler) - $(LI $(BUGZILLA 2309): Crash on a template mixing in a variadic template with an undefined template identifier) - $(LI $(BUGZILLA 2346): ICE when comparing typedef'd class) - $(LI $(BUGZILLA 2580): Documented WinMain for D2 is wrong) - $(LI $(BUGZILLA 2633): incorrect ModuleInfo declaration in object.di) - $(LI $(BUGZILLA 2695): pure functions can invoke impure function pointers) - $(LI $(BUGZILLA 2807): Marking a nested function as 'pure' may cause bad code generations silently accepted) - $(LI $(BUGZILLA 2821): struct alignment inconsistent with C for { int, long }) - $(LI $(BUGZILLA 2851): Segfault using C-style struct initializer with too few arguments) - $(LI $(BUGZILLA 2865): RandomCover not random) - $(LI $(BUGZILLA 2882): std.random.MersenneTwisterEngine without seed) - $(LI $(BUGZILLA 2890): deadlock in std.stdio) - $(LI $(BUGZILLA 2893): qualified types don't have an Unsigned counterpart) - $(LI $(BUGZILLA 2906): writef problem with formatting floating point) - $(LI $(BUGZILLA 2914): to!string(struct) is broken) - $(LI $(BUGZILLA 2920): recursive templates blow compiler stack) - $(LI $(BUGZILLA 2922): Egregiously bad hashing performance with strings) - ) -) - -$(VERSION 029, Apr 19, 2009, =================================================, - - $(NEWPHOBOS - $(LII std.algorithm, - $(LI Everything converted to ranges. Big disruption. Algorithms added.) - ) - $(LII std.array, - $(LI Range primitives for arrays) - $(LI Appender template) - $(LI insert, replace functions) - ) - $(LII std.bitmanip, - $(LI Bitfields of length 0 are defined to be always 0.) - $(LI The read functions for bitfields are const.) - ) - $(LII std.contracts, - $(LI enforce accepts const(char)[] instead of string) - $(LI Added enforce overload that invokes a delegate on failure) - $(LI Added assumeSorted template) - $(LI Added structuralCast that implements, well, structural casting - (incomplete).) - ) - $(LII std.conv, - $(LI Rewrote conversions with constrained templates.) - $(LI Added text() function that transforms everything into text.) - ) - $(LII std.date, - $(LI Added a benchmark function that allows for simple timing measurements.) - ) - $(LII std.file, - - $(LI read, write, append, rename, remove, getSize, getTimes, - getAttributes, isfile, isdir, chdir, mkdir, mkdirRecurse, rmdir, - listdir, copy, take filename(s) by "in char[]") - $(LI Added function readText that reads and validates a text file) - $(LI Added function slurp that reads a file into an array of tuples. - Example: ---- -auto a = slurp!(int, double)("filename", "%s, %s"); ---- - Each line in the file looks like e.g. "1, 2.3". slurp returns an array - of Tuple!(int, double) with the parsed content. - ) - ) - $(LII std.format, - - $(LI Added vector parsing and printing with the specifier "%()". For - example, writefln("[%(s; )]", [1, 2, 3][]) writes "[1; 2; 3]". This - support is experimental and may be changed in the future.) - $(LI Added a formattedRead function (i.e., scanf that doesn't suck). The - implementation is incomplete but common cases are supported.) - ) - $(LII std.functional, - $(LI Improved error messages) - $(LI Added configurable parameter names for functions as strings) - $(LI Added Adjoin template) - ) - $(LII std.getopt, - $(LI Added support for parameterless delegates) - ) - $(LII std.math, - $(LI Intrinsics std.math.yl2x and yl2xp1 added. Improves performance of - std.math.log() and similar functions (and they are now pure nothrow). ) - ) - $(LII std.mmfile, - $(LI Minor cosmetic changes) - ) - $(LII std.numeric, - - $(LI Added type CustomFloat that allows defining specialized floating-point - numbers (e.g. 16-bit floats, positive floats etc.)) - $(LI Added FPTemporary as the best type to store temporary values.) - $(LI Templatized oppositeSigns) - $(LI Added Euclidean distance) - $(LI Added dotProduct) - $(LI Added cosineSimilarity) - $(LI Added normalize) - $(LI Added string kernel functions gapWeightedSimilarity, - gapWeightedSimilarityNormalized, gapWeightedSimilarityIncremental.) - ) - $(LII std.outbuffer, - $(LI Added a few missing overloads of write()) - ) - $(LII std.path, - $(LI getDrive now works with all string types) - $(LI isabs accepts in char[]) - $(LI join accepts variadic in char[]) - $(LI fnmatch works with in char[]) - ) - $(LII std.random, - - $(LI Added RandomCover that covers a given range in a random manner) - $(LI Eliminated the old-fashioned random functions) - $(LI Defined a default random object that simplifies calls to the random - functions) - $(LI Changed generators to obey the range interface. So now you can write: ---- -Random r; -foreach (n; take(100, uniform(0, 100))) { ... } ---- - ) - ) - $(LII std.range (new file), - $(LI Range manipulation stuff.) - ) - $(LII std.regex (new file), - $(LI Regular expression library with wide char support, simplified - interface, better speed etc.) - ) - $(LII std.regexp, - $(LI Scheduled for deprecation. Use std.regex instead.) - ) - $(LII std.stdio, - $(LI Major breaking changes: introduced the File struct. Now stdin, - stdout, stderr are instances of the File struct.) - $(LI Due to bugs in the compiler, the copy constructor and destructor of - File are commented out. Walter will look into fixing the issues soon. - File should work fine, but you need to close it manually.) - $(LI A byRecord iteration mode makes it pretty easy to iterate structured - text files.) - $(LI writef and writefln now require a string as their first argument.) - ) - $(LII std.string, - $(LI strip, stripl, stripr, startsWith, endsWith now work with any string type) - ) - $(LII std.typecons, - $(LI Added constructors, assignment operator, length, toString, and slice - to Tuple.) - ) - $(LII std.utf, - $(LI toUTF16z accepts in char[]) - ) - $(LII std.variant, - $(LI Added support for Variants that contain vectors and hashes of themselves) - ) - $(LII std.c.stdio, - $(LI Added fopen64 and friends) - ) - ) - $(WHATSNEW - $(LI Added template function literals) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 675): %a format has an out-by-1 bug for denormals) - $(LI $(BUGZILLA 2199): Segfault using array operation in function call) - $(LI $(BUGZILLA 2203): typeof(class.template.foo) crashes compiler) - $(LI $(BUGZILLA 2577): DMD crashes on foreach of undefined identifier) - $(LI $(BUGZILLA 2808): 'nothrow' nested functions cannot be parsed) - $(LI $(BUGZILLA 2812): sqrt(2.0) is about -2.7341e-53) - ) -) - -$(VERSION 028, Apr 7, 2009, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1586): DMD and GDC segfaults on incomplete code segment) - $(LI $(BUGZILLA 2064): Segfault with mixin(for/foreach) with empty loop body) - $(LI $(BUGZILLA 2812): sqrt(2.0) is about -2.7341e-53) - $(LI $(BUGZILLA 2804): Impure nested functions should be legal inside pure functions) - ) -) - -$(VERSION 027, Mar 31, 2009, =================================================, - - $(WHATSNEW - $(LI Most functions in std.math are now pure nothrow. Improved speed of std.math.hypot.) - $(LI Added response files for Linux and OSX) - $(LI Added $(LINK2 class.html#AliasThis, $(B alias this))) - $(LI $(BUGZILLA 2746): Make float.init signalling NaN by default) - $(LI On Windows, if there are multiple source files on the command - line they are now read with a background thread. This may speed up - compilation.) - $(LI Folded in patches for LDC compatibility from Tomas Lindquist Olsen) - $(LI Removed $(B etc.gamma) from the library.) - ) - $(BUGSFIXED - $(LI std.math.hypot is wrong for subnormal arguments) - $(LI Fix bug where / wasn't recognized as a path separator on Windows.) - $(LI $(BUGZILLA 920): Fix one more out of date reference to 'auto' rather than 'scope') - $(LI $(BUGZILLA 1645): can override base class' const method with non-const method) - $(LI $(BUGZILLA 2319): "Win32 Exception" not very useful) - $(LI $(BUGZILLA 2336): link to nonexistent std_array.html) - $(LI $(BUGZILLA 2570): Patch for some mistakes in Ddoc comments) - $(LI $(BUGZILLA 2574): std.c.stdio doesn't compile: va_list not defined!) - $(LI $(BUGZILLA 2591): custom allocator new argument should be size_t instead of uint) - $(LI $(BUGZILLA 2595): template ctors crash compiler) - $(LI $(BUGZILLA 2596): Variadic constructors don't compile) - $(LI $(BUGZILLA 2626): template function not working against template struct instantiated with default arguments) - $(LI $(BUGZILLA 2674): Copy postblit constructor this(this) not called for members) - $(LI $(BUGZILLA 2689): seek behaves incorrectly on MAC OSX) - $(LI $(BUGZILLA 2692): alignment of double on x86 linux is incorrect) - $(LI $(BUGZILLA 2700): typeof tests stops compilation abruptly) - $(LI $(BUGZILLA 2705): Response file size cannot exceed 64kb) - $(LI $(BUGZILLA 2711): -H produces bad headers files if function defintion is templated and have auto return value) - $(LI $(BUGZILLA 2722): ICE with variadic template parameters) - $(LI $(BUGZILLA 2723): ICE with variadic template parameters, different case) - $(LI $(BUGZILLA 2724): Persistent segfaults in templated code) - $(LI $(BUGZILLA 2725): Pattern matching in static if not working with variadic arguments) - $(LI $(BUGZILLA 2727): std.date Cyclic dependency) - $(LI $(BUGZILLA 2728): Bogus Error message on const ref return) - $(LI $(BUGZILLA 2729): hash_t undocumented and unnecessary) - $(LI $(BUGZILLA 2730): Restriction on op= can be lifted) - $(LI $(BUGZILLA 2731): Errors in associative array example) - $(LI $(BUGZILLA 2739): _argptr is invalid for functions nested in class methods) - $(LI $(BUGZILLA 2743): dumpobj gives "buss error" on Tiger) - $(LI $(BUGZILLA 2744): wrong init tocbuffer of forstatement) - $(LI $(BUGZILLA 2745): missing token tochars in lexer.c) - $(LI $(BUGZILLA 2747): improper toCBuffer of funcexp) - $(LI $(BUGZILLA 2750): Optimize slice copy with size known at compile time) - $(LI $(BUGZILLA 2751): incorrect scope storage class vardeclaration tocbuffer) - $(LI $(BUGZILLA 2752): std.xml does not encode CData correctly) - $(LI $(BUGZILLA 2754): The error message regarding implicit conversion to shared doesn't mention shared in the message.) - $(LI $(BUGZILLA 2755): ICE on invalid ref returns in linked objects: Assertion failure: 'type' on line 6566 in file 'expression.c'. No ICE or error if invalid code is local to the file.) - $(LI $(BUGZILLA 2756): Bad code generation for pure nothrow math functions) - $(LI $(BUGZILLA 2761): Unreachable statement warning in std.string) - $(LI $(BUGZILLA 2763): std.mangle.demangle not translating 'ya') - $(LI $(BUGZILLA 2766): DMD hangs with 0%cpu) - $(LI $(BUGZILLA 2767): DMD incorrectly mangles NTFS stream names) - $(LI $(BUGZILLA 2772): lib can't open response file) - ) -) - -$(VERSION 026, Mar 3, 2009, =================================================, - - $(WHATSNEW - $(LI Escape string literals deprecated, see $(BUGZILLA 2658)) - $(LI Tripled speed of exp, expm1, and exp2. std.math is now less dependent on the C standard library.) - $(LI Added $(LINK2 struct.html#nested, nested structs).) - $(LI Added buildable dmd source.) - $(LI Many changes to std.math for speed, accuracy, and Tango compatibility: - $(UL - $(LI Improved accuracy of exp, expm1, exp2, sinh, cosh, tanh on Mac OSX, - and tripled speed on all platforms.) - $(LI Now using IEEE754-2008 camelCase names for isNaN, isFinite, - isNormal, isSubnormal, isInfinity. Aliases for the old names have been retained.) - $(LI The non-functional nan(char[]) is replaced with NaN, getNaNpayload.) - ) - ) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1603): String literals bind to pointer types) - $(LI $(BUGZILLA 1629): Link error: Previous Definition Different: blablah__initZ) - $(LI $(BUGZILLA 1662): Falls back to libphobos if -debuglib isn't used when -g is) - $(LI $(BUGZILLA 1681): cast(real) ulong.max == 0) - $(LI $(BUGZILLA 2416): Slice of typedef'ed array should preserve the typedef'ed type) - $(LI $(BUGZILLA 2597): auto return doesn't work for a variety of cases) - $(LI $(BUGZILLA 2612): immutable not accepted wherever invariant is) - $(LI $(BUGZILLA 2619): Locally-instantiated structs are not instantiated locally) - $(LI $(BUGZILLA 2621): ref binds to rvalues of user-defined types) - $(LI $(BUGZILLA 2622): ref returns not allowed in complex template) - $(LI $(BUGZILLA 2623): Function type drops ref spec) - $(LI $(BUGZILLA 2670): std.file.read() should read files of 0 length) - $(LI $(BUGZILLA 2673): Static constructors sometimes do not run when compiling with -lib) - $(LI $(BUGZILLA 2675): cannot foreach structs with copy constructor) - $(LI $(BUGZILLA 2676): alias parameters not matched in concept if clause) - $(LI $(BUGZILLA 2677): Alias type parameters not visible in concept-if clauses) - $(LI $(BUGZILLA 2678): for loops are already assumed to terminate) - $(LI $(BUGZILLA 2679): Spurious "warning - " messages and erratic behaviour with is(typeof({void function}()))) - $(LI $(BUGZILLA 2684): Associative arrays have wrong opIndex signatures) - $(LI $(BUGZILLA 2690): DMD aborts with MALLOC_CHECK_ set) - ) -) - -$(VERSION 025, Feb 14, 2009, =================================================, - - $(WHATSNEW - $(LI Added Mac OSX support.) - $(LI Separated bin and lib directories into windows, linux, - and osx.) - $(LI No longer need to download dmc to use the windows version.) - $(LI Use version(OSX) for Mac OSX. Although version(darwin) is - also supported for the time being, it is deprecated.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 2448): template return by reference causes seg fault) - ) -) - -$(VERSION 023, Jan 2, 2009, =================================================, - - $(WHATSNEW - $(LI Improved speed of long division.) - $(LI Optimizer now takes advantage of immutable and pure.) - $(LI Added predefined $(LINK2 version.html#PredefinedVersions, version) - $(B D_Ddoc) which is predefined when $(B -D) switch is thrown.) - $(LI the type of a string literal is now $(CODE invariant(char)[]) - rather than $(CODE invariant(char)[length_of_string]). It is still - implicitly convertible to the latter. This is intended to reduce - template instantiation bloat.) - $(LI Undid fix for $(BUGZILLA 2500), as the fix was arguably worse - than the bug.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1078): Frontend uses of 'auto' where 'scope' should be used) - $(LI $(BUGZILLA 2517): DDoc omits abstract on classes) - $(LI $(BUGZILLA 2518): scope(success) not execuate and RAII variable destructor is not called) - $(LI $(BUGZILLA 2519): Segfault when >> used in an invalid slice) - $(LI $(BUGZILLA 2527): Alias Template Params Are Always Same Type As First Instantiation (according to typeof(x).stringof)) - $(LI $(BUGZILLA 2531): DDoc not generated correctly for struct methods inside static if) - $(LI $(BUGZILLA 2533): compiler falls with "assertion failed" message on wrong code) - $(LI $(BUGZILLA 2534): dmd.conf is wrong) - $(LI $(BUGZILLA 2537): compiler crashes on this code:) - $(LI $(BUGZILLA 2541): cannot use aliased type for decl of foreach variable) - $(LI $(BUGZILLA 2542): array casts behave differently at compile and runtime) - ) -) - -$(VERSION 022, Dec 11, 2008, =================================================, - - $(WHATSNEW - $(LI Changed IUnknown to use the extern(System) interface rather - that extern(Windows).) - $(LI Pure functions now get semantically checked.) - $(LI Nothrow functions now get semantically checked.) - $(LI $(D shared) is now a type constructor.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1518): Crash using 'scope', 'with' and undefined 'RegExp') - $(LI $(BUGZILLA 1649): Variant coercion fails with delegates) - $(LI $(BUGZILLA 1685): Array index is evaluated twice) - $(LI $(BUGZILLA 1933): Delimited string constants can cause segfault) - $(LI $(BUGZILLA 1963): -H creates broken headers) - $(LI $(BUGZILLA 2041): Spec implies relationship between interfaces and COM objects) - $(LI $(BUGZILLA 2105): added patch) - $(LI $(BUGZILLA 2441): header file generation translates enum to manifest) - $(LI $(BUGZILLA 2468): result type of AndAndExp and OrOrExp deduced incorrectly) - $(LI $(BUGZILLA 2489): import in struct causes assertion failure) - $(LI $(BUGZILLA 2490): extern(C++) can not handle structs as return types) - $(LI $(BUGZILLA 2491): druntime GC wrongly frees data pointed to by TLS.) - $(LI $(BUGZILLA 2492): ICE building on Linux with -lib option) - $(LI $(BUGZILLA 2499): Template alias default value cannot be template instantiation) - $(LI $(BUGZILLA 2500): template struct methods are left unresolved if imported from multiple modules) - $(LI $(BUGZILLA 2501): member function marked as final override ignores override requirements) - $(LI $(BUGZILLA 2503): Error 42: Symbol Undefined _D3std7process6systemFAyaZi) - $(LI $(BUGZILLA 2506): Can't initialize const member in ctor if it is accessed via this.member syntax) - $(LI Incorporated some of the patches from $(BUGZILLA 1752)) - $(LI $(D extern __thread) now works on Linux.) - ) -) - -$(VERSION 021, Nov 25, 2008, =================================================, - - $(WHATSNEW - $(LI Added $(B -safe) switch and $(CODE module(system) Identifier;) syntax.) - $(LI Added range support to foreach statement.) - $(LI $(B scope) parameter storage class means the parameter will - not 'escape' the scope of the function invocation. - Using this for delegate parameters will prevent some closure allocations - by the calling function.) - $(LI The $(B lazy) storage class now implies $(B scope) so that lazy - arguments won't trigger a heap allocated closure.) - $(LI The 'this' parameter to struct member functions is now a - reference type, rather than a pointer. - $(RED This breaks existing code.) - ) - - $(LI More changes to druntime: - $(TABLE1 - $(TR $(TH from) $(TH to)) - $(TRENAME OutOfMemoryException, OutOfMemoryError) - $(TRENAME SwitchException, SwitchError) - $(TRENAME HiddenFuncException, HiddenFuncError) - $(TRENAME ArrayBoundsException, RangeError) - $(TRENAME AssertException, AssertError) - $(TRENAME FinalizeException, FinalizeError) - $(TRENAME onArrayBoundsError, onRangeError) - $(TRENAME stdc.*, core.stdc.*) - $(TRENAME sys.*, core.sys.*) - - - ) - ) - - $(LI Added core.runtime.loadLibrary() as an experimental feature for - loading dynamic libraries (Win32 only at the moment).) - $(LI Added core.runtime.unloadLibrary() as an experimental feature for - unloading dynamic libraries previously loaded by loadLibrary().) - $(LI core.thread.sleep() accepts a long integer specifying the sleep interval - in 100 nanosecond intervals (the previous release notes said this was a - float, IIRC).) - $(LI It is no longer necessary to link in druntime separately, it is - inserted into libphobos2.a.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 313): Fully qualified names bypass private imports) - $(LI $(BUGZILLA 920): SPEC: Auto classes referenced where scope should be used) - $(LI $(BUGZILLA 929): Resizing array of associative arrays (uint[char[]][]) causes infinite loop / hang) - $(LI $(BUGZILLA 1372): Compiler accepts pragma(msg,)) - $(LI $(BUGZILLA 1610): Enum.stringof is int, not the name of the enum) - $(LI $(BUGZILLA 1663): pragma(lib, "") don't work on linux) - $(LI $(BUGZILLA 1797): Documentation comments - ///) - $(LI $(BUGZILLA 2428): Accessing item in enum'd array produced compiler error) - $(LI $(BUGZILLA 2429): std.stream.File incorrect flag parsing and sharing mode) - $(LI $(BUGZILLA 2431): Internal error: ../ztc/cgcod.c 1031 when using -O) - $(LI $(BUGZILLA 2470): Cannot build libraries from other libraries) - $(LI unittest functions now always use D linkage) - ) -) - -$(VERSION 020, Oct 20, 2008, =================================================, - - $(WHATSNEW - $(LI Improved performance of AAs by rebalancing trees when rehashing.) - $(LI $(D_KEYWORD immutable) now is implemented.) - $(LI $(BUGZILLA 2344): Two wrong lookups for array functions) - $(LI $(BUGZILLA 2345): Return by $(LINK2 function.html#ref-functions, reference) should be allowed) - $(LI $(CODE Posix) is now a predefined identifier when compiling under Linux) - $(LI Based on Sean Kelly's hard work, Phobos has been split into - two libraries, druntime.lib and phobos.lib. This will enable - better integration with Tango. - The user source code changes are: - $(TABLE1 - $(TR $(TH from) $(TH to)) - $(TRENAME bit, bool) - $(TRENAME _d_OutOfMemory(), onOutOfMemoryError()) - $(TRENAME import std.asserterror;, import core.exception;) - $(TRENAME import std.hiddenfunc;, import core.exception;) - $(TRENAME import std.switcherr;, import core.exception;) - $(TRENAME import std.array;, import core.exception;) - $(TRENAME import std.outofmemory;, import core.exception;) - $(TRENAME import std.gc;, import core.memory;) - $(TRENAME import std.thread;, import core.thread;) - $(TRENAME SwitchError, SwitchException) - $(TRENAME AssertError, AssertException) - $(TRENAME HiddenFuncError, HiddenFuncException) - $(TRENAME ArrayBoundsError, ArrayBoundsException) - $(TRENAME std.gc.fullCollect(), GC.collect()) - $(TRENAME std.gc.*(), memory.gc_*()) - $(TRENAME _moduleUnitTests(), import runtime; runModuleUnitTests()) - $(TR $(TD $(CODE printf)) $(TD add $(CODE import std.c.stdio;))) - ) - Changes to thread: - $(UL - $(LI The thread handle isn't exposed to the user. This can always be obtained using the appropriate OS calls from within the thread.) - $(LI There is no druntime equivalent for Thread.pause() and Thread.resume(). The closest is thread_suspendAll() and thread_resumeAll()--extern (C) calls meant for use by the GC.) - $(LI Thread.wait() is renamed to Thread.join().) - $(LI Sleep functionality is available as Thread.sleep(double), where the parameter represents the number of seconds to sleep (fractional values accepted, obviously).) - ) - This is a big change, and expect some problems for a release or two - with this. - ) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1229): Linker fills disk) - $(LI $(BUGZILLA 2332): Initializing const or invariant hashes croaks) - $(LI $(BUGZILLA 2333): Hash initializer does not work) - $(LI $(BUGZILLA 2336): link to nonexistent std_array.html) - $(LI $(BUGZILLA 2340): Template properties don't work) - $(LI $(BUGZILLA 2341): Double destruction without intervening copy) - $(LI $(BUGZILLA 2362): Confusing description of 'aliasing of invariant with mutable'?) - $(LI $(BUGZILLA 2363): Spurious () required after function name when used with array in prefix form) - $(LI $(BUGZILLA 2366): Const member function syntax is missing) - $(LI $(BUGZILLA 2368): Calling a function with an address of another function, then calling a returned object is rejected) - $(LI $(BUGZILLA 2373): freebsd select does not accept values > 999,999) - $(LI $(BUGZILLA 2376): CTFE fails on array literal of array literals of chars) - $(LI $(BUGZILLA 2380): static struct initializer accepted as non static initializer is not documented) - $(LI $(BUGZILLA 2383): default arguments can implicitly access private global variables that are not visible at call site) - $(LI $(BUGZILLA 2385): spec says all structs are returned via hidden pointer on linux, but it uses registers) - $(LI $(BUGZILLA 2390): Missing warning on conversion from int to char) - ) -) - -$(VERSION 019, Sep 2, 2008, =================================================, - - $(WHATSNEW - $(LI Added $(LINK2 struct.html#Struct-Constructor, struct constructors).) - $(LI Special member functions _ctor, _dtor, etc., now have two - leading _ in order to not conflict with the user identifier space.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1322): foreach bypasses invariant) - $(LI $(BUGZILLA 1615): inout is allowed in foreach of string literal) - $(LI $(BUGZILLA 1627): ICE with a method called _ctor) - $(LI $(BUGZILLA 1633): Nonsensical "C style cast illegal" message with !is) - $(LI $(BUGZILLA 1771): dmd fails to execute on linux) - $(LI $(BUGZILLA 1773): excessively long integer literal) - $(LI $(BUGZILLA 1785): Mixing in an incorrect array literal causes infinite loop.) - $(LI $(BUGZILLA 2176): Assertion failure: 'sz == es2->sz' on line 1339 in file 'constfold.c' (concatenating strings of different types)) - $(LI $(BUGZILLA 2183): Bad formatting in std.c.stdlib) - $(LI $(BUGZILLA 2190): toHash documentation is deprecated [D2.0]) - $(LI $(BUGZILLA 2232): DMD generates invalid code when an object file is compiled -inline) - $(LI $(BUGZILLA 2241): DMD abort) - $(LI $(BUGZILLA 2243): const bool = is(function literal), badly miscast) - $(LI $(BUGZILLA 2262): -inline breaks -lib library) - $(LI $(BUGZILLA 2286): movmskpd compiled incorrectly) - $(LI $(BUGZILLA 2287): std.conv should accept structs defining toString) - $(LI $(BUGZILLA 2289): Stack overflow on very large BigInt to string.) - $(LI $(BUGZILLA 2308): CTFE crash on foreach over nonexistent variable) - $(LI $(BUGZILLA 2311): Static destructors in templates are never run) - $(LI $(BUGZILLA 2314): Crash on anonymous class variable instantiation) - $(LI $(BUGZILLA 2316): std.file docs are out of date) - $(LI $(BUGZILLA 2317): asm offsetof generates: Internal error: ../ztc/cod3.c 2651) - ) -) - -$(VERSION 018, Aug 7, 2008, =================================================, - - $(WHATSNEW - $(LI Now supports $(LINK2 arrays.html#array-operations, array operations).) - ) - $(BUGSFIXED - $(LI Added hash to generated module names when building libs to reduce collisions) - $(LI $(BUGZILLA 1622): parameters to TypeInfo_Struct.compare seem to be switched around.) - $(LI $(BUGZILLA 1644): Template instantiation should automatically cast to const to make const-ness irrelevant when argument is const anyways) - $(LI $(BUGZILLA 2216): bad code generation for static arrays of zero length static arrays) - $(LI $(BUGZILLA 2223): Typo in error message) - $(LI $(BUGZILLA 2231): missing bigint document) - $(LI $(BUGZILLA 2242): linux system calls are canceled by GC) - $(LI $(BUGZILLA 2247): bad header file generated for if (auto o = ...) {}) - $(LI $(BUGZILLA 2248): .di should be a supported file extension) - $(LI $(BUGZILLA 2250): Update of user32.lib and kernel32.lib) - $(LI $(BUGZILLA 2254): Size of executable almost triples) - $(LI $(BUGZILLA 2258): Docs -> Inline Assembler -> Operand Types -> qword missing) - $(LI $(BUGZILLA 2259): Assertion failure: '0' on line 122 in file 'statement.c') - $(LI $(BUGZILLA 2266): opEquals documentation still says it returns int) - $(LI $(BUGZILLA 2269): D BUG: cosine of complex) - $(LI $(BUGZILLA 2272): synchronized attribute documentation) - $(LI $(BUGZILLA 2273): Whitespace is not inserted after commas) - ) -) - -$(VERSION 017, Jul 11, 2008, =================================================, - - $(WHATSNEW - ) - $(BUGSFIXED - $(LI $(BUGZILLA 2207): overload resolution fails with deprecation) - $(LI $(BUGZILLA 2208): Deprecated function declarations cannot use deprecated types) - $(LI $(BUGZILLA 2209): Typo in doc for offsetof) - $(LI $(BUGZILLA 2212): phobos itself should be able to be compiled with '-w' switch) - $(LI $(BUGZILLA 2264): typo in documentation regarding atof.) - ) -) - -$(VERSION 016, Jul 8, 2008, =================================================, - - $(WHATSNEW - $(LI re-implemented $(B internal.monitor) in D. Rationalized $(B internal.object)) - $(LI $(BUGZILLA 288): changed return type of $(B opEquals) from int - to bool. This necessitates doing a grep for opEquals and - $(RED changing all the return values). - ) - $(LI Added $(B .__vptr) and $(B .__monitor) properties for class objects - for use in the internal runtime library. - ) - $(LI Made $(LINK2 rdmd.html, rdmd)'s source available through svn, see $(LINK http://dsource.org/projects/phobos/browser/trunk/tools/rdmd.d)) - $(LI Simplified $(B std.algorithm) by fusing together higher-order functions taking an alias and their counterparts taking a string) - $(LI Added module $(B std.array) containing array operations: $(B insert), $(B erase), and $(B replace)) - $(LI Changed the $(B enforce)'s implementation to generate smaller code per call) - $(LI Changed $(B std.functional.binaryFun) to work with strings and function aliases alike) - $(LI In $(B std.getopt), added $(B optChar), $(B assignChar), and $(B endOfOptions), per popular demand :o|) - $(LI In $(B std.math), replaced a bunch of $(B const)s with $(B enum)s) - $(LI In $(B std.numeric), added Don Clugston as author and operated minor documentation fixes) - $(LI Improved $(B std.stdio.chunks) to take an iteration tally in addition to the chunk) - ) - $(BUGSFIXED - $(LI $(NG_digitalmars_D_announce 12322): mixin regression) - $(LI $(BUGZILLA 203): std.format.doFormat() pads width incorrectly on Unicode strings) - $(LI $(BUGZILLA 211): Linking error with alias mixin params and anonymous methods) - $(LI $(BUGZILLA 224): Incorrect warning "no return at end of function") - $(LI $(BUGZILLA 252): -w and switch returns = bogus "no return at end of function" warning) - $(LI $(BUGZILLA 253): Invalid <dl> tag generated by Ddoc) - $(LI $(BUGZILLA 294): DDoc: Function templates get double and incomplete documentation) - $(LI $(BUGZILLA 398): No way to abort compilation in a doubly recursive mixin) - $(LI $(BUGZILLA 423): dmd ignores empty commandline arguments) - $(LI $(BUGZILLA 515): Spec incorrect in where .offsetof can be applied) - $(LI $(BUGZILLA 520): Invariants allowed to call public functions) - $(LI $(BUGZILLA 542): Function parameter of a deprecated type (other than a class) is not caught) - $(LI $(BUGZILLA 543): Function return of a deprecated type is not caught) - $(LI $(BUGZILLA 544): Variable declared of a deprecated type (other than a class) is not caught) - $(LI $(BUGZILLA 545): Attempt to access a static built-in property of a deprecated struct, union, enum or typedef is not caught) - $(LI $(BUGZILLA 547): Accessing a deprecated member variable through an explicit object reference is not caught) - $(LI $(BUGZILLA 548): Accessing a value of a deprecated enum is not caught) - $(LI $(BUGZILLA 566): Adding non-static members and functions to classes using a template doesn't error) - $(LI $(BUGZILLA 570): Bogus recursive mixin error) - $(LI $(BUGZILLA 571): class instance member template returns strange value) - $(LI $(BUGZILLA 572): parse error when using template instantiation with typeof) - $(LI $(BUGZILLA 581): Error message w/o line number in dot-instantiated template) - $(LI $(BUGZILLA 617): IFTI doesn't use normal promotion rules for non-template parameters) - $(LI $(BUGZILLA 870): contradictory error messages for templates) - $(LI $(BUGZILLA 951): Missing line number: no constructor provided for a class derived from a class with no default constructor) - $(LI $(BUGZILLA 1097): Missing line number: casting array to array of different element size) - $(LI $(BUGZILLA 1158): Missing line number: invalid mixin outside function scope) - $(LI $(BUGZILLA 1176): Error missing file and line number) - $(LI $(BUGZILLA 1187): Segfault with syntax error in two-level mixin.) - $(LI $(BUGZILLA 1194): fcmov* emmits incorrect code) - $(LI $(BUGZILLA 1207): Documentation on destructors is confusing) - $(LI $(BUGZILLA 1341): typeof(int) should probably be legal) - $(LI $(BUGZILLA 1601): shr and shl error message is missing line numbers) - $(LI $(BUGZILLA 1612): No file/line number for using an undefined label in inline assembly) - $(LI $(BUGZILLA 1912): Error without line number (Tuple, invalid value argument)) - $(LI $(BUGZILLA 1936): Error with no line number (array dimension overflow)) - $(LI $(BUGZILLA 2076): asm: offset has wrong docs and error without line number) - $(LI $(BUGZILLA 2161): Modify compiler to pass array TypeInfo to _adEq and _adCmp instead of element TypeInfo) - $(LI $(BUGZILLA 2178): 3 errors without line number: typeof) - $(LI $(BUGZILLA 2188): man-or-boy test fails with access violation) - $(LI Fixed bugs in $(B std.file.rename) and $(B std.file.remove) on Linux) - $(LI Fixed documentation in $(B std.typecons)) - ) -) - -$(VERSION 015, Jun 17, 2008, =================================================, - - $(WHATSNEW - $(LI $(LINK2 template.html#aliasparameters, Template alias arguments) - can now be literals.) - $(LI $(LINK2 template.html#function-templates, Function templates) - can now deduce the return type if they - are declared with $(CODE auto).) - $(LI Non-lvalues are no longer matched to $(CODE ref) and $(CODE out) - parameters when - $(LINK2 function.html#function-overloading, overloading).) - $(LI Relaxed hidden hijacking detection when hidden function is disjoint - from overloading with any other virtual function in the - $(LINK2 function.html#function-inheritance, hierarchy).) - $(LI Added $(LINK2 version.html#PredefinedVersions, version identifier - $(B D_PIC)) when $(B -fPIC) switch is used.) - $(LI Added $(LINK2 template.html#Constraint, $(I Constraint)s) to - templates.) - ) - $(BUGSFIXED - $(LI $(BUGZILLA 1383): Implicit Function Instantiation with typesafe-variadic of delegates doesn't work) - $(LI $(BUGZILLA 1559): version statement makes code outside of it disappear) - $(LI $(BUGZILLA 1675): "Identifier too long" error with OMF object files) - $(LI $(BUGZILLA 1947): ICE (Assertion failure: '0' on statement.c:123) with null mixin) - $(LI $(BUGZILLA 1963): -H creates broken headers) - $(LI $(BUGZILLA 2098): Outdated docs) - $(LI $(BUGZILLA 2099): Text and Sample Code Disagree (non-static local invariant declaration)) - $(LI $(BUGZILLA 2112): the type of undefined variable incorrectly assumed to be int) - $(LI $(BUGZILLA 2118): Inconsistent use of string vs invariant(char[]) in doc) - $(LI $(BUGZILLA 2123): Anonymous class crashes) - $(LI $(BUGZILLA 2129): foreach won't work with invariant limits) - $(LI $(BUGZILLA 2132): CTFE: can't evaluate ~= at compile time, D2 only.) - $(LI $(BUGZILLA 2133): anonymous enum without {} doesn't work as asm value) - $(LI $(BUGZILLA 2136): typeof(super(...)) counted as a constructor call) - $(LI $(BUGZILLA 2140): static if as final statement with no code causes containing code to be skipped) - $(LI $(BUGZILLA 2143): Mixed-in identifier is not recognized by static if) - $(LI $(BUGZILLA 2144): 'is' is defined to be the same as '==' for non-class and non-array types, but does not call opEquals) - $(LI $(BUGZILLA 2145): Phobos buildsystem unable to build html) - $(LI $(BUGZILLA 2146): Multiple execution of 'static this' defined in template) - $(LI $(BUGZILLA 2149): Auto variables loose the keyword "auto" in di files generated with -H option.) - ) -) - -$(VERSION 014, May 16, 2008, =================================================, - - $(WHATSNEW - $(LI Added $(B -man) switch to browse manual.) - $(LI Added $(B -lib) switch to generate library files. - Also causes multiple object files to be generated from one - source module.) - $(LI When generating an executable file, only one object file - is now generated containing all the modules that were compiled, rather - than one object file per module.) - $(LI Rewrote the $(LINK2 rdmd.html,$(B rdmd)) utility to properly track - dependencies and command-line compiler options (currently only working - under Linux).) - $(LI Changed the Phobos makefile $(D linux.mak) to take advantage of - the new $(B -lib) feature. Improved full build speed by 3x.) - $(LI std.algorithm: Changed the map() function so that it deduces the return type. Also map can be now curried.) - $(LI std.contracts: Added file and line information to enforce. Added errnoEnforce that formats the error message according to errno. Added corresponding ErrnoException class.) - $(LI std.conv: Made std.to curryable. Changed std.to to throw exception when object-to-object cast fails. Eliminated some superfluous printfs.) - $(LI std.encoding: Added new functions encodedLength(dchar) and encode(dchar, ref E[])) - $(LI std.encoding: Got rid of types Utf8, Utf16, Utf32, Ascii, Latin1, Windows1252. Introduced types AsciiChar, AsciiString, Latin1Char, Latin1String, Windows1252Char, Windows1252String.) - $(LI std.encoding: For now commented out std.encoding.to.) - $(LI std.file: Changed Boolean function signatures (e.g. exists) to return bool instead of int. Got rid of some gotos. Added the readText, lastModified, mkdirRecurse, and rmdirRecurse functions.) - $(LI std.functional: Improved compose so it accepts an unbounded number of functions. Added the pipe function.) - $(LI std.getopt: Added new option stopOnFirstNonOption. Also automatically expand dubious option groups with embedded spaces in them (useful for shebang scripts)) - $(LI std.math: improved integral powers) - $(LI std.md5: Improved signature of sum so it takes multiple arrays. Added getDigestString.) - $(LI std.path: changed signatures of test functions from bool to int. Implemented rel2abs for Windows. Improved join so that it accepts multiple paths. Got rid of some gotos with the help of scope statements.) - $(LI std.process: added getenv and setenv. Improved system() so it returns the exit code correctly on Linux.) - $(LI std.random: added the dice function - a handy (possibly biased) dice.) - $(LI std.typecons: Finalized and documented the stupendous Rebindable template.) - $(LI std.utf: added the codeLength function. Got rid of some gotos.) - ) - $(BUGSFIXED - $(LI std.format: Fixed unlisted bug in raw write for arrays) - $(LI std.getopt: Fixed unlisted bug in dealing with one-letter options with bundling disabled) - $(LI $(BUGZILLA 2014): fopen fails on large files.) - $(LI $(BUGZILLA 2031): Documentation: template value parameters) - $(LI $(BUGZILLA 2032): Documentation for creating a class on the stack is unintuitive) - $(LI $(BUGZILLA 2037): Article on hijacking is outdated) - $(LI $(BUGZILLA 2038): Remove hello2.html from samples directory) - $(LI $(BUGZILLA 2039): -ignore switch is missing from compiler docs) - $(LI $(BUGZILLA 2054): Const system broken on struct assignment.) - $(LI $(BUGZILLA 2055): (ICE) Compiler crash on struct initializer with too many elements) - $(LI $(BUGZILLA 2056): Const system does not allow certain safe casts/conversions involving deep composite types) - $(LI $(BUGZILLA 2058): Describe hidden value passed to class member functions) - $(LI $(BUGZILLA 2063): std.xml access violation for nested, closed tags) - $(LI $(BUGZILLA 2065): Return value of std.file.exists() is inverted.) - $(LI $(BUGZILLA 2067): call from anonymous class makes access violation.) - $(LI $(BUGZILLA 2071): spec doesn't mention pointer arithmetic with two pointer operands) - $(LI $(BUGZILLA 2072): std.typecons documentation anomaly.) - $(LI $(BUGZILLA 2074): Variant arithmetic operations fail. For now the fix is to comment out all right-hand side operators. Suggestions for a better fix are welcome.) - $(LI $(BUGZILLA 2075): Spec does not specify how array literals are stored.) - $(LI $(BUGZILLA 2084): operator ?: does not compute the tightest type) - $(LI $(BUGZILLA 2086): Describe relationship between string and char[] more explicitly) - $(LI $(BUGZILLA 2089): Issues with CTFE and tuple indexes) - $(LI $(BUGZILLA 2090): Cannot alias a tuple member which is a template instance) - $(LI $(BUGZILLA 2100): Assertion failure: '0' on line 4842 in file 'expression.c') - $(LI $(BUGZILLA 2109): asm {lea EAX, [0*0+EAX]; } rejected.) - ) -) - -$(VERSION 013, Apr 22, 2008, =================================================, - - $(WHATSNEW - $(LI Added $(B -ignore) switch to ignore unsupported pragmas.) - $(LI Unsupported pragmas now printed out with $(B -v) switch.) - $(LI Added $(LINK2 operatoroverloading.html#Dot, opDot), which is - $(RED experimental only).) - $(LI $(LINK2 statement.html#SwitchStatement, $(I SwitchStatement))s - can now accept - runtime initialized const and invariant case statements.) - $(LI Changed $(CODE __FILE__) and $(CODE __LINE__) so they work as - parameter default initializers.) - $(LI Incorporated Benjamin Shropshire's doc changes) - $(LI Hidden methods now get a compile time warning rather than a runtime - one.) - $(LI $(LINK2 html.html, Html source files) are now deprecated.) - $(LI Added $(LINK2 function.html#pure-functions, pure) and - $(LINK2 function.html#nothrow-functions, nothrow) function attributes, - although their semantics are not implemented.) - $(LI Deprecated $(I VolatileStatement); use - $(LINK2 statement.html#SynchronizedStatement, $(I SynchronizedStatement)) instead.) - $(LI Added $(B __thread) storage class for thread local storage. - This is $(RED for testing purposes only) to check out the machinery - in the back end. The front end design of this will change.) - $(LI $(LINK2 http://www.digitalmars.com/ctg/obj2asm.html, $(B obj2asm)) - and $(LINK2 http://www.digitalmars.com/ctg/dumpobj.html, $(B dumpobj)) - now better handle special ELF fixup records.) - $(LI Added $(LINK2 function.html#partial-ordering, partial ordering) - rules to disambiguate function overloading.) - $(LI std.perf: Bill Baxter cleaned it up.) - $(LI std.xml.Document constructor now creates whole DOM tree.) - $(LI Added std.encoding.) - ) - $(BUGSFIXED - $(LI $(NG_digitalmars_D 69085): const/invariant bug?) - $(LI $(BUGZILLA 1712): vtbl[0] for interface not set to corresponding Interface*) - $(LI $(BUGZILLA 1723): __traits(getVirtualFunctions) on a non-function fails badly) - $(LI $(BUGZILLA 1741): crash on associative array with static array as index type) - $(LI $(BUGZILLA 1905): foreach docs inconsistency) - $(LI $(BUGZILLA 1906): foreach cannot use index with large arrays) - $(LI $(BUGZILLA 1925)) - $(LI $(BUGZILLA 1935): The std.recls samples in the DMD .zip are obsolete.) - $(LI $(BUGZILLA 1967): getDirName does not seem to use altsep on windows) - $(LI $(BUGZILLA 1978): Wrong vtable call) - $(LI $(BUGZILLA 1991): Dmd hangs) - $(LI $(BUGZILLA 2016): 'invariant' TypeSpecialization is missing) - $(LI $(BUGZILLA 2019): Appending a one-element array literal doesn't work) - ) -) - -$(VERSION 012, Mar 6, 2008, =================================================, - - $(WHATSNEW - $(LI Added predefined version($(LINK2 version.html#PredefinedVersions, unittest)). See $(BUGZILLA 458)) - $(LI Removed $(B std.math2)) - $(LI Added compile time error for comparing class types against $(CODE null).) - $(LI Added struct destructors and postblits.) - - $(LI std.algorithm: Made some imports conditional for the Unittest - version; fixed doc typo; made min and max always return the tightest - type and work with mixes of signed and unsigned; changed enum value - names to obey lowercase convention; changed OrderStrategy to - SwapStrategy as it's not just for ordering (e.g. see eliminate).) - - $(LI std.bitmanip: simplified code generated for bitfields and improved - error message.) - - $(LI std.format: ate dogfood: used bitfields internally.) - - $(LI std.functional: fixed binaryfun to work with constant-size arrays; - added compose.) - - $(LI std.random: made unpredictableSeed return different numbers every - call (except for rarely-encountered MT scenarios); added private - variable name that will take experts millenia to figure out; changed the - boundaries syntax from two separate characters '[', '$(LPAREN)' to one - string "[$(LPAREN)" throughout.) - - $(LI std.traits: added mostNegative, mostly to assuage for the - unpardonable mistake of inheriting C++'s unpardonable mistake of - defining "min" to mean very different things for floating-point types - and integral types.) - - $(LI std.typecons: added undocumented Rebindable in preparation for - opImplicitCast.) - - $(LI std.math: - $(UL - $(LI Support for different CPU IEEE 'real' formats: 64-bit, 80-bit and - 128-bit (quadruple) reals, both BigEndian and LittleEndian; partial - support for non-IEEE 'doubledouble' reals.) - $(LI Added implementation of nextafter $(BUGZILLA 1722) and scalb for - DMD-Windows.) - $(LI Added nextUp(), nextDown()) - $(LI $(BUGZILLA 1881): feqrel nonsensical for non-real arguments.) - $(LI internal functions isPosZero(), isNegZero() removed in favour of - the more generally useful isIdentical().) - $(LI asm versions of functions which were not implemented by DMD - Windows: scalb, lrint.) - $(LI added creal expi(real y) which is useful for simultaneous - calculation of sin + cos.) - ) - ) - ) - $(BUGSFIXED - $(LI std.contracts: fixed unlisted bug in pointsTo.) - $(LI std.conv: fixed bug related to number-to-number conversion (T.min - hits again).) - $(LI Fixed dwarf bug with DT_AT_upper_bound) - $(LI $(BUGZILLA 756): IFTI for tuples only works if tuple parameter is last) - $(LI $(BUGZILLA 1454): IFTI cant deduce parameter if alias argument used) - $(LI $(BUGZILLA 1661): Not possible to specialize on template with integer parameter) - $(LI $(BUGZILLA 1800): Compiler crash on enums nested in structs) - $(LI $(BUGZILLA 1801): Const structs should be assignable to non-const variables unless they contain references) - $(LI $(BUGZILLA 1806): "const" makes typesafe variadic arguments not work properly.) - $(LI $(BUGZILLA 1809): template.c:2600) - $(LI $(BUGZILLA 1810): MmFile anonymous mapping does not work under win32) - $(LI $(BUGZILLA 1819): spurious warning about missing return statement after synchronized) - $(LI $(BUGZILLA 1821): ICE when using __traits isSame on const/invariant variables) - $(LI $(BUGZILLA 1823): Implicit conversion to const on associative array) - $(LI $(BUGZILLA 1828): Several Thread Issues) - $(LI $(BUGZILLA 1833): std.c.windows.windows should use enums for constants, or be more selective about use of extern(Windows)) - $(LI $(BUGZILLA 1836): Inline assembler can't use enum values as parameters.) - $(LI $(BUGZILLA 1837): Make dmd stop flooding the console: prints content of passed parameter file) - $(LI $(BUGZILLA 1843): Bogus unreachable statement on forward referenced struct, lacks line number) - $(LI $(BUGZILLA 1850): The compiler accepts lower case asm registers.) - $(LI $(BUGZILLA 1851): missing opCall? when cast away const struct) - $(LI $(BUGZILLA 1852): you get opCall missing when cast to a struct(diagnostic)) - $(LI $(BUGZILLA 1853): opCmp documentation really needs some examples) - $(LI $(BUGZILLA 1854): bug in new flow analysis (warnings on valid code)) - $(LI $(BUGZILLA 1857): Runtime segfault while profileing - jump to invalid code address) - $(LI $(BUGZILLA 1862): asm: [ESI+1*EAX] should be a legal addr mode) - $(LI $(BUGZILLA 1865): Escape sequences are flawed.) - $(LI $(BUGZILLA 1867): lazy adds spurious const qualifier) - $(LI $(BUGZILLA 1871): DMD debug messages printed) - $(LI $(BUGZILLA 1873): structs with at least one immutable member are completely immutable) - $(LI $(BUGZILLA 1874): __traits(allMembers, T) fails to list methods which only have non-mutating overloads) - $(LI $(BUGZILLA 1876): inside a non-static class method, should "&( f)" be same as "&(this.f)" ?) - $(LI $(BUGZILLA 1877): Errors in the documentation of std.math.atan2) - $(LI $(BUGZILLA 1882): Internal error: ..\ztc\cod1.c 2529) - $(LI $(BUGZILLA 1883): templates instantiated as real gives incorrect values) - $(LI $(BUGZILLA 1884): manifest constants for strings) - $(LI $(BUGZILLA 1885): Syntax error for object identity test between invariant/mutable references) - $(LI $(BUGZILLA 1887): compiler freeze on array of dyn. arrays with empty first initializer) - ) -) - -$(VERSION 011, Feb 18, 2008, =================================================, - - $(WHATSNEW - $(LI std.typecons: fixed code bloat issue; added Tuple.toString; added function tuple(); fixed unlisted bug in enumValuesImpl.) - $(LI std.process: added function shell().) - $(LI std.math: minor change in approxEqual.) - $(LI std.contracts: added functions pointsTo()) - $(LI std.numeric: minor unittest fixes.) - $(LI std.bitmanip: fixed code bloat issue, reintroduced FloatRep and DoubleRep.) - $(LI std.conv: minor simplification of implementation.) - $(LI std.regexp: added reference to ECMA standard in the documentation.) - $(LI std.getopt: changed return type from bool to void, error is signaled by use of exceptions.) - $(LI std.functional: added unaryFun, binaryFun, adjoin.) - $(LI std.string: updated documentation, changed code to compile with warnings enabled.) - $(LI std.traits: changed FieldTypeTuple; added RepresentationTypeTuple, hasAliasing; fixed bug 1826; added call to flush() from within write; fixed unlisted bug in lines().) - $(LI std.algorithm: added map, reduce, filter, inPlace, move, swap, overwriteAdjacent, find, findRange, findBoyerMoore, findAdjacent, findAmong, findAmongSorted, canFind, canFindAmong, canFindAmongSorted, count, equal, overlap, min, max, mismatch, EditOp, none, substitute, insert, remove, levenshteinDistance, levenshteinDistanceAndPath, copy, copyIf, iterSwap, swapRanges, reverse, rotate, SwapStrategy, Unstable, Semistable, Stable, eliminate, partition, nthElement, sort, schwartzSort, partialSort, isSorted, makeIndex, schwartzMakeIndex, lowerBound, upperBound, equalRange, canFindSorted.) - $(LI std.thread: fixed so it compiles with warnings enabled.) - $(LI std.file: made getSize() faster under Linux.) - $(LI std.random: fixed so it compiles with warnings enabled; improved function uniform so it deduces type generated from its arguments.) - $(LI std.format: added fixes to make formatting work with const data.) - $(LI std.path: minor documentation changes. ) - $(LI Added $(CODE std.xml)) - $(LI Added $(CODE std.complex)) - $(LI Added $(CODE std.iterator)) - $(LI Added $(CODE std.c.linux.tipc)) - $(LI Added $(CODE std.c.linux.termios)) - $(LI Added $(CODE nothrow) keyword) - $(LI Re-enabled auto interfaces.) - $(LI Now allow static arrays to be lvalues.) - $(LI Now allows implicit casting of $(CODE null) to/from const/invariant.) - $(LI Now allows implicit casting of $(I StructLiteral)s if each of - its arguments can be implicitly cast.) - $(LI Now allows implicit casting of structs to/from const/invariant if - each of its fields can be.) - $(LI Added $(LINK2 pragma.html#Predefined-Pragmas, pragma startaddress).) - $(LI $(CODE .tupleof) can now access private fields of a struct/class) - $(LI Enhancement $(BUGZILLA 493): Partial IFTI does not work) - ) - - $(BUGSFIXED - $(LI Fixed $(NG_digitalmars_D 66406) Remaining const niggles #1 - Custom POD types) - $(LI Fixed display of ddoc template parameters that were aliased) - $(LI Fixed bug in std.file.readln() for Windows in translated mode) - $(LI $(BUGZILLA 1072): CTFE: crash on for loop with blank increment) - $(LI $(BUGZILLA 1435): DDoc: Don't apply DDOC_PSYMBOL everywhere) - $(LI $(BUGZILLA 1815): foreach with interval does not increment pointers correctly) - $(LI $(BUGZILLA 1825): local instantiation and function nesting) - $(LI $(BUGZILLA 1837): Make dmd stop flooding the console: prints content of passed parameter file) - $(LI $(BUGZILLA 1842): Useless linker command line output during compilation on Linux) - ) -) - -$(VERSION 010, Jan 20, 2008, =================================================, - - $(WHATSNEW - $(LI $(CODE opAssign) can no longer be overloaded for class objects.) - $(LI $(CODE WinMain) and $(CODE DllMain) can now be in template mixins.) - $(LI Added $(CODE pure) keyword.) - ) - - $(BUGSFIXED - $(LI $(BUGZILLA 1319): compiler crashes with functions that take const ref arguments) - $(LI $(BUGZILLA 1697): Internal error: ..\ztc\cgcod.c 2322 with -O) - $(LI $(BUGZILLA 1700): ICE attempting to modify member of const return struct) - $(LI $(BUGZILLA 1707): '==' in TemplateParameterList in IsExpression causes segfault) - $(LI $(BUGZILLA 1711): typeof with delegate literal not allowed as template parameter) - $(LI $(BUGZILLA 1713): foreach index with tuples and templates fails) - $(LI $(BUGZILLA 1718): obscure exit with error code 5) - $(LI $(BUGZILLA 1719): Compiler crash or unstable code generation with scoped interface instances) - $(LI $(BUGZILLA 1720): std.math.NotImplemented missing a space in message) - $(LI $(BUGZILLA 1724): Internal error: toir.c 177) - $(LI $(BUGZILLA 1725): std.stream.BufferedFile.create should use FileMode.OutNew) - $(LI $(BUGZILLA 1757): there is an fault in phobos windows api interface) - $(LI $(BUGZILLA 1762): Wrong name mangling for pointer args of free extern (C++) functions) - $(LI $(BUGZILLA 1767): rejects-valid, diagnostic) - $(LI $(BUGZILLA 1769): Typo on the page about exceptions) - $(LI $(BUGZILLA 1773): excessively long integer literal) - $(LI $(BUGZILLA 1779): Compiler crash when deducing more than 2 type args) - $(LI $(BUGZILLA 1783): DMD 1.025 asserts on code with struct, template, and alias) - $(LI $(BUGZILLA 1788): dmd segfaults without info) - $(LI $(NG_digitalmars_D_announce 11066): Re: DMD 1.025 and 2.009 releases) - ) -) - -$(VERSION 009, Jan 1, 2008, =================================================, - -$(WHATSNEW - $(LI Redid const/invariant semantics again.) - $(LI Extended enums to allow declaration of manifest constants.) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 1111): enum value referred to by another value of same enum is considered as enum's base type, not enum type) - $(LI $(BUGZILLA 1694): Zip::ArchiveMember::name format bug) - $(LI $(BUGZILLA 1702): ICE when identifier is undefined) - $(LI $(BUGZILLA 1738): Error on struct without line number) - $(LI $(BUGZILLA 1742): CTFE fails on some template functions) - $(LI $(BUGZILLA 1743): interpret.c:1421 assertion failure on CTFE code) - $(LI $(BUGZILLA 1744): CTFE: crash on assigning void-returning function to variable) - $(LI $(BUGZILLA 1745): Internal error: ..\ztc\out.c 115) - $(LI $(BUGZILLA 1749): std.socket not thread-safe due to strerror) - $(LI $(BUGZILLA 1753): String corruption in recursive CTFE functions) - $(LI $(NG_digitalmars_D 63456): Cannot overload on constancy of this) -) -) - -$(VERSION 008, Nov 27, 2007, =================================================, - -$(WHATSNEW - $(LI std.string: Made munch more general and added function chompPrefix.) - $(LI std.variant: Added documentation for variantArray) - $(LI std.traits: Added CommonType template, fixed isStaticArray.) - $(LI std.bitarray: scheduled for deprecation) - $(LI std.bitmanip: new module with the content of std.bitarray plus the bitfields, FloatRep, and DoubleRep templates) - $(LI std.process: Made getpid visible in Linux builds) - $(LI std.math: Made nextafter visible for all floating types. Added approxEqual template.) - $(LI std.contracts: Added enforce signature taking an exception) - $(LI std.conv: Made conv_error a template parameterized on the types being converted.) - $(LI std.stdio: Cosmetic changes.) - $(LI std.system: Cosmetic changes.) - $(LI std.file: Fixed bug in function dirEntries.) - $(LI std.random: Major addition of engines and distributions.) - $(LI std.format: Added raw ('r') format specifier for writef*.) - $(LI std.path: Added rel2abs (Linux version only).) - $(LI std.algorithm: new module) - $(LI std.typecons: new module) - $(LI std.functional: new module) - $(LI std.numeric: new module) - $(LI Added $(LINK2 struct.html#ConstStruct, const/invariant structs), - $(LINK2 class.html#ConstClass, classes) and - $(LINK2 interface.html#ConstInterface, interfaces).) - $(LI Added $(CODE const) and $(CODE invariant) to $(LINK2 expression.html#IsExpression, IsExpression)s.) - $(LI Added $(CODE typeof(return)) type specifier.) - $(LI Changed the way coverage analysis is done so it is independent - of order dependencies among modules.) - $(LI Revamped const/invariant.) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 70): valgrind: Conditional jump or move depends on uninitialised value(s) in elf_findstr) - $(LI $(BUGZILLA 71): valgrind: Invalid read of size 4 in elf_renumbersyms) - $(LI $(BUGZILLA 204): Error message on attempting to instantiate an abstract class needs to be improved) - $(LI $(BUGZILLA 1508): dmd/linux template symbol issues) - $(LI $(BUGZILLA 1651): .di file generated with -H switch does not translate function() arguments correctly) - $(LI $(BUGZILLA 1655): Internal error: ..\ztc\cgcod.c 1817) - $(LI $(BUGZILLA 1656): illegal declaration accepted) - $(LI $(BUGZILLA 1664): (1.23).stringof generates bad code) - $(LI $(BUGZILLA 1665): Internal error: ..\ztc\cod2.c 411) -) -) - -$(VERSION 007, Oct 31, 2007, =================================================, - -$(WHATSNEW - $(LI Functors now supported by std.traits.ReturnType().) - $(LI Transitive const now leaves invariants intact in the tail.) - $(LI Added overloadable unary * operation as opStar().) - $(LI Full closure support added.) - $(LI Data items in static data segment >= 16 bytes in size - are now paragraph aligned.) -) - -$(BUGSFIXED - $(LI Variables of type void[0] can now be declared.) - $(LI Static multidimensional arrays can now be initialized with - other matching static multidimensional arrays.) - $(LI $(BUGZILLA 318): wait does not release thread resources on Linux) - $(LI $(BUGZILLA 322): Spawning threads which allocate and free memory leads to pause error on collect) - $(LI $(BUGZILLA 645): Race condition in std.thread.Thread.pauseAll) - $(LI $(BUGZILLA 689): Clean up the spec printfs!) - $(LI $(BUGZILLA 697): No const folding on asm db,dw, etc) - $(LI $(BUGZILLA 706): incorrect type deduction for array literals in functions) - $(LI $(BUGZILLA 708): inline assembler: "CVTPS2PI mm, xmm/m128" fails to compile) - $(LI $(BUGZILLA 709): inline assembler: "CVTPD2PI mm, xmm/m128" fails to compile) - $(LI $(BUGZILLA 718): Internal error: ../ztc/cgcod.c 562) - $(LI $(BUGZILLA 723): bad mixin of class definitions at function level: func.c:535: virtual void FuncDeclaration::semantic3(Scope*): Assertion `0' failed) - $(LI $(BUGZILLA 725): expression.c:6516: virtual Expression* MinAssignExp::semantic(Scope*): Assertion `e2->type->isfloating()' failed.) - $(LI $(BUGZILLA 726): incorrect error line for "override" mixin) - $(LI $(BUGZILLA 729): scope(...) statement in SwitchBody causes compiler to segfault) - $(LI $(BUGZILLA 1258): Garbage collector loses memory upon array concatenation) - $(LI $(BUGZILLA 1480): std.stream throws the new override warning all over the place) - $(LI $(BUGZILLA 1483): Errors in threads not directed to stderr) - $(LI $(BUGZILLA 1557): std.zlib allocates void[]s instead of ubyte[]s, causing leaks.) - $(LI $(BUGZILLA 1580): concatenating invariant based strings should work) - $(LI $(BUGZILLA 1593): ICE compiler crash empty return statement in function) - $(LI $(BUGZILLA 1613): DMD hangs on syntax error) - $(LI $(BUGZILLA 1618): Typo in std\system.d) -) -) - -$(VERSION 006, Oct 16, 2007, =================================================, - -$(WHATSNEW - $(LI $(RED Transformed all of $(CODE string), $(CODE wstring), - and $(CODE dstring) into invariant definitions). - Tons of changes in function signatures and - implementations rippled through the standard library. - Initial experience - with invariant strings seems to be highly encouraging.) - $(LI Implemented $(LINK2 function.html#overload-sets, Overload Sets) for functions and templates.) - $(LI Added the $(LINK2 phobos/std_getopt.html,std.getopt) module that makes standards-conforming command-line processing easy.) - $(LI Added the parse and assumeUnique to the $(LINK2 phobos/std_conv.html, std.conv) module.) - $(LI Added the dirEntries function to the $(LINK2 phobos/std_file.html, std.file) module.) - $(LI Added the basename and dirname functions (which alias the less gainful names getBaseName and getDirectoryName to the $(LINK2 phobos/std_path.html,std.path) module.)) - $(LI Added optional terminator to readln; added the convenience functions fopen and popen; added functions lines and chunks; all to the $(LINK2 phobos/std_stdio.html, std.stdio) module.) - $(LI Added the munch function to the $(LINK2 phobos/std_string.html, std.string) module.) - $(LI Fixed isStaticArray; added BaseClassesTuple, TransitiveBaseTypeTuple, ImplicitConversionTargets, isIntegral, isFloatingPoint, isNumeric, isSomeString, isAssociativeArray, isDynamicArray, isArray; all to the $(LINK2 phobos/std_traits.html, std.traits) module.) - $(LI Added the $(LINK2 phobos/std_variant.html, std.variant) module.) - $(LI Incorporated many of the Tango GC structural differences (much more to go still).) - $(LI Added the $(LINK2 phobos/std_contracts.html, std.contracts) module.) - $(LI Breaking change: $(CODE std.stdio.writef) can now only accept a format as - its first argument.) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 1478): Avoid libc network api threadsafety issues) - $(LI $(BUGZILLA 1491): Suppress SIGPIPE when sending to a dead socket) - $(LI $(BUGZILLA 1562): Deduction of template alias parameter fails) - $(LI $(BUGZILLA 1571): Const on function parameters not carried through to .di file) - $(LI $(BUGZILLA 1575): Cannot do assignment of tuples) - $(LI $(BUGZILLA 1579): write[ln] fails for obj.toString()) - $(LI $(BUGZILLA 1580): Concatenating invariant based strings should work) -) -) - -$(VERSION 005, Oct 1, 2007, =================================================, - -$(WHATSNEW - $(LI $(D std.math.sin), $(D cos), $(D tan) are now evaluated at - compile time if the argument is a constant.) - $(LI Added Cristian Vlasceanu's idea for - $(LINK2 cpp_interface.html, C++ interface) for 'plugins') - $(LI Overhaul phobos $(D linux.mak) and add documentation build logic) - $(LI Massive additions to $(LINK2 phobos/std_conv.html, std.conv)) - $(LI Add $(CODE writeln()) and $(CODE write()) to $(LINK2 phobos/std_stdio.html, std.stdio)) -) - -$(BUGSFIXED - $(LI Fix std.boxer boxing of Object's (unit test failure)) - $(LI Fix std.demangle to not show hidden parameters (this and delegate context pointers)) - $(LI $(BUGZILLA 217): typeof not working properly in internal/object.d) - $(LI $(BUGZILLA 218): Clean up old code for packed bit array support) - $(LI $(BUGZILLA 223): Error message for unset constants doesn't specify error location) - $(LI $(BUGZILLA 278): dmd.conf search path doesn't work) - $(LI $(BUGZILLA 479): can't compare arrayliteral statically with string) - $(LI $(BUGZILLA 549): A class derived from a deprecated class is not caught) - $(LI $(BUGZILLA 550): Shifting by more bits than size of quantity is allowed) - $(LI $(BUGZILLA 551): Modulo operator works with imaginary and complex operands) - $(LI $(BUGZILLA 556): is (Type Identifier : TypeSpecialization) doesn't work as it should) - $(LI $(BUGZILLA 668): Use of *.di files breaks the order of static module construction) - $(LI $(BUGZILLA 1125): Segfault using tuple in asm code, when size not specified) - $(LI $(BUGZILLA 1437): dmd crash: "Internal error: ..\ztc\cod4.c 357") - $(LI $(BUGZILLA 1456): Cannot use a constant with alias template parameters) - $(LI $(BUGZILLA 1474): regression: const struct with an initializer not recognized as a valid alias template param) - $(LI $(BUGZILLA 1488): Bad code generation when using tuple from asm) - $(LI $(BUGZILLA 1510): ICE: Assertion failure: 'ad' on line 925 in file 'func.c') - $(LI $(BUGZILLA 1523): struct literals not work with typedef) - $(LI $(BUGZILLA 1530): Aliasing problem in DMD front end code) - $(LI $(BUGZILLA 1531): cannot access typedef'd class field) - $(LI $(BUGZILLA 1537): Internal error: ..\ztc\cgcod.c 1521) -) -) - -$(VERSION 004, Sep 5, 2007, =================================================, - -$(WHATSNEW - $(LI Added command line switches $(B -defaultlib) and $(B -debuglib)) - $(LI $(BUGZILLA 1445): Add default library options to sc.ini / dmd.conf) - $(LI Changed result type of IsExpression from int to bool.) - $(LI Added $(B isSame) and $(B compiles) to $(B __traits).) - $(LI Added optional $(I TemplateParameterList) to $(I IsExpression).) - $(LI Added warning when $(B override) is omitted.) - $(LI Added $(B std.hiddenfunc).) - $(LI Added trace_term() to object.d to fix $(BUGZILLA 971): No profiling output is generated if the application terminates with exit) - $(LI Multiple module static constructors/destructors allowed.) - $(LI Added new syntax for string literals (delimited, heredoc, D tokens)) - $(LI Added __EOF__ token) -) - -$(BUGSFIXED - $(LI Fixed $(NG_digitalmars_D 56414)) - $(LI $(BUGZILLA 961): std.windows.registry stack corruption) - $(LI $(BUGZILLA 1315): CTFE doesn't default initialise arrays of structs) - $(LI $(BUGZILLA 1342): struct const not accepted as initializer for another struct) - $(LI $(BUGZILLA 1363): Compile-time issue with structs in 'for') - $(LI $(BUGZILLA 1375): CTFE fails for null arrays) - $(LI $(BUGZILLA 1378): A function call in an array literal causes compiler to crash) - $(LI $(BUGZILLA 1384): Compiler segfaults when using struct variable like a function with no opCall member.) - $(LI $(BUGZILLA 1388): multiple static constructors allowed in module) - $(LI $(BUGZILLA 1414): compiler crashes with CTFE and structs) - $(LI $(BUGZILLA 1421): Stack Overflow when using __traits(allMembers...)) - $(LI $(BUGZILLA 1423): Registry: corrupted value) - $(LI $(BUGZILLA 1436): std.date.getLocalTZA() returns wrong values when in DST under Windows) - $(LI $(BUGZILLA 1446): Missing comma in Final Const and Invariant page title) - $(LI $(BUGZILLA 1447): CTFE does not work for static member functions of a class) - $(LI $(BUGZILLA 1448): UTF-8 output to console is seriously broken) - $(LI $(BUGZILLA 1450): Registry: invalid UTF-8 sequence) - $(LI $(BUGZILLA 1460): Compiler crash on valid code) - $(LI $(BUGZILLA 1464): "static" foreach breaks CTFE) - $(LI $(BUGZILLA 1468): A bug about stack overflow.) -) -) - -$(VERSION 003, Jul 21, 2007, =================================================, - -$(WHATSNEW - $(LI Added 0x78 Codeview extension for type $(B dchar).) - $(LI Moved $(B next) member from $(B Object.Error) to $(B Object.Exception)) - $(LI Added $(LINK2 statement.html#ForeachRangeStatement, ForeachRangeStatement)). - $(LI Added $(B extern (System))) - $(LI Added $(LINK2 traits.html, std.traits)) - $(LI $(BUGZILLA 345): updated std.uni.isUniAlpha to Unicode 5.0.0) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 46): Included man files should be updated) - $(LI $(BUGZILLA 268): Bug with SocketSet and classes) - $(LI $(BUGZILLA 406): std.loader is broken on linux) - $(LI $(BUGZILLA 561): Incorrect duplicate error message when trying to create instance of interface) - $(LI $(BUGZILLA 588): lazy argument and nested symbol support to std.demangle) - $(LI $(BUGZILLA 668): Use of *.di files breaks the order of static module construction) - $(LI $(BUGZILLA 1110): std.format.doFormat + struct without toString() == crash) - $(LI $(BUGZILLA 1300): Issues with struct in compile-time function) - $(LI $(BUGZILLA 1306): extern (Windows) should work like extern (C) for variables) - $(LI $(BUGZILLA 1318): scope + ref/out parameters are allowed, contrary to spec) - $(LI $(BUGZILLA 1320): Attributes spec uses 1.0 const semantics in 2.0 section) - $(LI $(BUGZILLA 1331): header file genaration generates a ":" instead of ";" at pragma) - $(LI $(BUGZILLA 1332): Internal error: ../ztc/cod4.c 357) - $(LI $(BUGZILLA 1333): -inline ICE: passing an array element to an inner class's constructor in a nested function, all in a class or struct) - $(LI $(BUGZILLA 1336): Internal error when trying to construct a class declared within a unittest from a templated class.) -) -) - -$(VERSION 002, Jul 1, 2007, =================================================, - -$(WHATSNEW - $(LI Renamed linux library from $(B libphobos.a) to $(B libphobos2.a)) -) - -$(BUGSFIXED - $(LI $(BUGZILLA 540): Nested template member function error - "function expected before ()") - $(LI $(BUGZILLA 559): Final has no effect on methods) - $(LI $(BUGZILLA 627): Concatenation of strings to string arrays with ~ corrupts data) - $(LI $(BUGZILLA 629): Misleading error message "Can only append to dynamic arrays") - $(LI $(BUGZILLA 639): Escaped tuple parameter ICEs dmd) - $(LI $(BUGZILLA 641): Complex string operations in template argument ICEs dmd) - $(LI $(BUGZILLA 657): version(): ignored) - $(LI $(BUGZILLA 689): Clean up the spec printfs!) - $(LI $(BUGZILLA 1103): metastrings.ToString fails for long > 0xFFFF_FFFF) - $(LI $(BUGZILLA 1107): CodeView: wrong CV type for bool) - - $(LI $(BUGZILLA 1118): weird switch statement behaviour) - $(LI $(BUGZILLA 1186): Bind needs a small fix) - $(LI $(BUGZILLA 1199): Strange error messages when indexing empty arrays or strings at compile time) - $(LI $(BUGZILLA 1200): DMD crash: some statements containing only a ConditionalStatement with a false condition) - $(LI $(BUGZILLA 1203): Cannot create Anonclass in loop) - $(LI $(BUGZILLA 1204): segfault using struct in CTFE) - $(LI $(BUGZILLA 1206): Compiler hangs on this() after method in class that forward references struct) - $(LI $(BUGZILLA 1207): Documentation on destructors is confusing) - $(LI $(BUGZILLA 1211): mixin("__LINE__") gives incorrect value) - $(LI $(BUGZILLA 1212): dmd generates bad line info) - - $(LI $(BUGZILLA 1216): Concatenation gives 'non-constant expression' outside CTFE) - $(LI $(BUGZILLA 1217): Dollar ($) seen as non-constant expression in non-char[] array) - $(LI $(BUGZILLA 1219): long.max.stringof gets corrupted) - $(LI $(BUGZILLA 1224): Compilation does not stop on asserts during CTFE) - $(LI $(BUGZILLA 1228): Class invariants should not be called before the object is fully constructed) - $(LI $(BUGZILLA 1233): std.string.ifind(char[] s, char[] sub) fails on certain non ascii strings) - $(LI $(BUGZILLA 1234): Occurrence is misspelled almost everywhere) - $(LI $(BUGZILLA 1235): std.string.tolower() fails on certain utf8 characters) - $(LI $(BUGZILLA 1236): Grammar for Floating Literals is incomplete) - $(LI $(BUGZILLA 1239): ICE when empty tuple is passed to variadic template function) - - $(LI $(BUGZILLA 1242): DMD AV) - $(LI $(BUGZILLA 1244): Type of array length is unspecified) - $(LI $(BUGZILLA 1247): No time zone info for India) - $(LI $(BUGZILLA 1285): Exception typedefs not distinguished by catch) - $(LI $(BUGZILLA 1287): Iterating over an array of tuples causes "glue.c:710: virtual unsigned int Type::totym(): Assertion `0' failed.") - $(LI $(BUGZILLA 1290): Two ICEs, both involving real, imaginary, ? : and +=.) - $(LI $(BUGZILLA 1291): .stringof for a class type returned from a template doesn't work) - $(LI $(BUGZILLA 1292): Template argument deduction doesn't work) - $(LI $(BUGZILLA 1294): referencing fields in static arrays of structs passed as arguments generates invalid code) - $(LI $(BUGZILLA 1295): Some minor errors in the lexer grammar) -) -) - -$(VERSION 001, Jun 27, 2007, =================================================, - -$(WHATSNEW - $(LI Added $(B D_Version2) predefined identifier to indicate - this is a D version 2.0 compiler) - $(LI Added $(B __VENDOR__) and $(B __VERSION__).) - $(LI Now an error to use both $(B const) and $(B invariant) as storage - classes for the same declaration) - $(LI The $(B .init) property for a variable is now based on its - type, not its initializer.) -) - -$(BUGSFIXED - $(LI $(B std.compiler) now is automatically updated.) - $(LI Fixed problem catting mutable to invariant arrays.) - $(LI Fixed CFTE bug with e++ and e--.) - $(LI $(BUGZILLA 1254): Using a parameter initialized to void in a compile-time evaluated function doesn't work) - $(LI $(BUGZILLA 1256): "with" statement with symbol) - $(LI $(BUGZILLA 1259): Inline build triggers an illegal error msg "Error: S() is not an lvalue") - $(LI $(BUGZILLA 1260): Another tuple bug) - $(LI $(BUGZILLA 1261): Regression from overzealous error message) - $(LI $(BUGZILLA 1262): Local variable of struct type initialized by literal resets when compared to .init) - $(LI $(BUGZILLA 1263): Template function overload fails when overloading on both template and non-template class) - $(LI $(BUGZILLA 1268): Struct literals try to initialize static arrays of non-static structs incorrectly) - $(LI $(BUGZILLA 1269): Compiler crash on assigning to an element of a void-initialized array in CTFE) - $(LI $(BUGZILLA 1270): -inline produces an ICE) - $(LI $(BUGZILLA 1272): problems with the new 1.0 section) - $(LI $(BUGZILLA 1274): 2.0 beta link points to dmd.zip which is the 1.x chain) - $(LI $(BUGZILLA 1275): ambiguity with 'in' meaning) - $(LI $(BUGZILLA 1276): static assert message displayed with escaped characters) - $(LI $(BUGZILLA 1277): "in final const scope" not considered redundant storage classes) - $(LI $(BUGZILLA 1279): const/invariant functions don't accept const/invariant return types) - $(LI $(BUGZILLA 1280): std.socket.Socket.send (void[],SocketFlags) should take a const(void)[] instead) - $(LI $(BUGZILLA 1283): writefln: formatter applies to following variable) - $(LI $(BUGZILLA 1286): crash on invariant struct member function referencing globals) -) -) - -$(VERSION 000, Jun 17, 2007, =================================================, - -$(WHATSNEW - $(LI Added aliases $(B string), $(B wstring), and $(B dstring) - for strings.) - $(LI Added $(B .idup) property for arrays to create invariant - copies.) - $(LI Added const, invariant, and final.) - $(LI $(B in) parameter storage class now means final scope const.) - $(LI foreach value variables now default to final if not declared - as inout.) - $(LI class and struct invariant declarations now must have a ().) -) - -$(BUGSFIXED - $(LI Added missing \n to exception message going to stderr.) - $(LI Fixed default struct initialization for CTFE.) - $(LI $(BUGZILLA 1226): ICE on a struct literal) -) -) - -) - -Macros: - TITLE=Change Log - WIKI=ChangeLog - - NEW = $(LI Version D 2.$0) - - VERSION= -
    - $(B $(LARGE - Version - D 2.$1 - )) - $(SMALL $(I $2, $3)) - $5 -
    - - BUGZILLA = Bugzilla $0 - CPPBUGZILLA = Bugzilla $0 - DSTRESS = dstress $0 - BUGSFIXED =

    Bugs Fixed

    $(UL $0 )
    - DMDBUGSFIXED =

    DMD Bugs Fixed

    $(UL $0 )
    - LIBBUGSFIXED =

    Library Bugs Fixed

    $(UL $0 )
    - RUNTIMEBUGSFIXED =

    Druntime Bugs Fixed

    $(UL $0 )
    - UPCOMING =

    Under Construction

    $(OL $0 )
    - WHATSNEW =

    New/Changed Features

    $(UL $0 )
    - NEWPHOBOS =

    New/Changed Phobos

    $(UL $0 )
    - LARGE=$0 - TRENAME=$(TR $(TD $(CODE $1)) $(TD $(CODE $2))) - LII= $(LI $(D $1) $(UL $+ )) diff --git a/changelog/2.000.dd b/changelog/2.000.dd new file mode 100644 index 0000000000..773f073502 --- /dev/null +++ b/changelog/2.000.dd @@ -0,0 +1,29 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jun 17, 2007, =================================================, + +$(WHATSNEW + $(LI Added aliases $(B string), $(B wstring), and $(B dstring) + for strings.) + $(LI Added $(B .idup) property for arrays to create invariant + copies.) + $(LI Added const, invariant, and final.) + $(LI $(B in) parameter storage class now means final scope const.) + $(LI foreach value variables now default to final if not declared + as inout.) + $(LI class and struct invariant declarations now must have a ().) +) + +$(BUGSFIXED + $(LI Added missing \n to exception message going to stderr.) + $(LI Fixed default struct initialization for CTFE.) + $(LI $(BUGZILLA 1226): ICE on a struct literal) +) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.000 + TITLE=Change Log: $(VER) diff --git a/changelog/2.001.dd b/changelog/2.001.dd new file mode 100644 index 0000000000..b668b64c1f --- /dev/null +++ b/changelog/2.001.dd @@ -0,0 +1,46 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jun 27, 2007, =================================================, + +$(WHATSNEW + $(LI Added $(B D_Version2) predefined identifier to indicate + this is a D version 2.0 compiler) + $(LI Added $(B __VENDOR__) and $(B __VERSION__).) + $(LI Now an error to use both $(B const) and $(B invariant) as storage + classes for the same declaration) + $(LI The $(B .init) property for a variable is now based on its + type, not its initializer.) +) + +$(BUGSFIXED + $(LI $(B std.compiler) now is automatically updated.) + $(LI Fixed problem catting mutable to invariant arrays.) + $(LI Fixed CFTE bug with e++ and e--.) + $(LI $(BUGZILLA 1254): Using a parameter initialized to void in a compile-time evaluated function doesn't work) + $(LI $(BUGZILLA 1256): "with" statement with symbol) + $(LI $(BUGZILLA 1259): Inline build triggers an illegal error msg "Error: S() is not an lvalue") + $(LI $(BUGZILLA 1260): Another tuple bug) + $(LI $(BUGZILLA 1261): Regression from overzealous error message) + $(LI $(BUGZILLA 1262): Local variable of struct type initialized by literal resets when compared to .init) + $(LI $(BUGZILLA 1263): Template function overload fails when overloading on both template and non-template class) + $(LI $(BUGZILLA 1268): Struct literals try to initialize static arrays of non-static structs incorrectly) + $(LI $(BUGZILLA 1269): Compiler crash on assigning to an element of a void-initialized array in CTFE) + $(LI $(BUGZILLA 1270): -inline produces an ICE) + $(LI $(BUGZILLA 1272): problems with the new 1.0 section) + $(LI $(BUGZILLA 1274): 2.0 beta link points to dmd.zip which is the 1.x chain) + $(LI $(BUGZILLA 1275): ambiguity with 'in' meaning) + $(LI $(BUGZILLA 1276): static assert message displayed with escaped characters) + $(LI $(BUGZILLA 1277): "in final const scope" not considered redundant storage classes) + $(LI $(BUGZILLA 1279): const/invariant functions don't accept const/invariant return types) + $(LI $(BUGZILLA 1280): std.socket.Socket.send (void[],SocketFlags) should take a const(void)[] instead) + $(LI $(BUGZILLA 1283): writefln: formatter applies to following variable) + $(LI $(BUGZILLA 1286): crash on invariant struct member function referencing globals) +) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.001 + TITLE=Change Log: $(VER) diff --git a/changelog/2.002.dd b/changelog/2.002.dd new file mode 100644 index 0000000000..f5c3ae7488 --- /dev/null +++ b/changelog/2.002.dd @@ -0,0 +1,61 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 1, 2007, =================================================, + +$(WHATSNEW + $(LI Renamed linux library from $(B libphobos.a) to $(B libphobos2.a)) +) + +$(BUGSFIXED + $(LI $(BUGZILLA 540): Nested template member function error - "function expected before ()") + $(LI $(BUGZILLA 559): Final has no effect on methods) + $(LI $(BUGZILLA 627): Concatenation of strings to string arrays with ~ corrupts data) + $(LI $(BUGZILLA 629): Misleading error message "Can only append to dynamic arrays") + $(LI $(BUGZILLA 639): Escaped tuple parameter ICEs dmd) + $(LI $(BUGZILLA 641): Complex string operations in template argument ICEs dmd) + $(LI $(BUGZILLA 657): version(): ignored) + $(LI $(BUGZILLA 689): Clean up the spec printfs!) + $(LI $(BUGZILLA 1103): metastrings.ToString fails for long > 0xFFFF_FFFF) + $(LI $(BUGZILLA 1107): CodeView: wrong CV type for bool) + + $(LI $(BUGZILLA 1118): weird switch statement behaviour) + $(LI $(BUGZILLA 1186): Bind needs a small fix) + $(LI $(BUGZILLA 1199): Strange error messages when indexing empty arrays or strings at compile time) + $(LI $(BUGZILLA 1200): DMD crash: some statements containing only a ConditionalStatement with a false condition) + $(LI $(BUGZILLA 1203): Cannot create Anonclass in loop) + $(LI $(BUGZILLA 1204): segfault using struct in CTFE) + $(LI $(BUGZILLA 1206): Compiler hangs on this() after method in class that forward references struct) + $(LI $(BUGZILLA 1207): Documentation on destructors is confusing) + $(LI $(BUGZILLA 1211): mixin("__LINE__") gives incorrect value) + $(LI $(BUGZILLA 1212): dmd generates bad line info) + + $(LI $(BUGZILLA 1216): Concatenation gives 'non-constant expression' outside CTFE) + $(LI $(BUGZILLA 1217): Dollar ($) seen as non-constant expression in non-char[] array) + $(LI $(BUGZILLA 1219): long.max.stringof gets corrupted) + $(LI $(BUGZILLA 1224): Compilation does not stop on asserts during CTFE) + $(LI $(BUGZILLA 1228): Class invariants should not be called before the object is fully constructed) + $(LI $(BUGZILLA 1233): std.string.ifind(char[] s, char[] sub) fails on certain non ascii strings) + $(LI $(BUGZILLA 1234): Occurrence is misspelled almost everywhere) + $(LI $(BUGZILLA 1235): std.string.tolower() fails on certain utf8 characters) + $(LI $(BUGZILLA 1236): Grammar for Floating Literals is incomplete) + $(LI $(BUGZILLA 1239): ICE when empty tuple is passed to variadic template function) + + $(LI $(BUGZILLA 1242): DMD AV) + $(LI $(BUGZILLA 1244): Type of array length is unspecified) + $(LI $(BUGZILLA 1247): No time zone info for India) + $(LI $(BUGZILLA 1285): Exception typedefs not distinguished by catch) + $(LI $(BUGZILLA 1287): Iterating over an array of tuples causes "glue.c:710: virtual unsigned int Type::totym(): Assertion `0` failed.") + $(LI $(BUGZILLA 1290): Two ICEs, both involving real, imaginary, ? : and +=.) + $(LI $(BUGZILLA 1291): .stringof for a class type returned from a template doesn't work) + $(LI $(BUGZILLA 1292): Template argument deduction doesn't work) + $(LI $(BUGZILLA 1294): referencing fields in static arrays of structs passed as arguments generates invalid code) + $(LI $(BUGZILLA 1295): Some minor errors in the lexer grammar) +) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.002 + TITLE=Change Log: $(VER) diff --git a/changelog/2.003.dd b/changelog/2.003.dd new file mode 100644 index 0000000000..b38ead539b --- /dev/null +++ b/changelog/2.003.dd @@ -0,0 +1,38 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 21, 2007, =================================================, + +$(WHATSNEW + $(LI Added 0x78 Codeview extension for type $(B dchar).) + $(LI Moved $(B next) member from $(B Object.Error) to $(B Object.Exception)) + $(LI Added $(LINK2 $(ROOT_DIR)spec/statement.html#ForeachRangeStatement, ForeachRangeStatement)). + $(LI Added $(B extern (System))) + $(LI Added $(LINK2 $(ROOT_DIR)spec/traits.html, std.traits)) + $(LI $(BUGZILLA 345): updated std.uni.isUniAlpha to Unicode 5.0.0) +) + +$(BUGSFIXED + $(LI $(BUGZILLA 46): Included man files should be updated) + $(LI $(BUGZILLA 268): Bug with SocketSet and classes) + $(LI $(BUGZILLA 406): std.loader is broken on linux) + $(LI $(BUGZILLA 561): Incorrect duplicate error message when trying to create instance of interface) + $(LI $(BUGZILLA 588): lazy argument and nested symbol support to std.demangle) + $(LI $(BUGZILLA 668): Use of *.di files breaks the order of static module construction) + $(LI $(BUGZILLA 1110): std.format.doFormat + struct without toString() == crash) + $(LI $(BUGZILLA 1300): Issues with struct in compile-time function) + $(LI $(BUGZILLA 1306): extern (Windows) should work like extern (C) for variables) + $(LI $(BUGZILLA 1318): scope + ref/out parameters are allowed, contrary to spec) + $(LI $(BUGZILLA 1320): Attributes spec uses 1.0 const semantics in 2.0 section) + $(LI $(BUGZILLA 1331): header file genaration generates a ":" instead of ";" at pragma) + $(LI $(BUGZILLA 1332): Internal error: ../ztc/cod4.c 357) + $(LI $(BUGZILLA 1333): -inline ICE: passing an array element to an inner class's constructor in a nested function, all in a class or struct) + $(LI $(BUGZILLA 1336): Internal error when trying to construct a class declared within a unittest from a templated class.) +) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.003 + TITLE=Change Log: $(VER) diff --git a/changelog/2.004.dd b/changelog/2.004.dd new file mode 100644 index 0000000000..0fd3f2b1fb --- /dev/null +++ b/changelog/2.004.dd @@ -0,0 +1,48 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 5, 2007, =================================================, + +$(WHATSNEW + $(LI Added command line switches $(B -defaultlib) and $(B -debuglib)) + $(LI $(BUGZILLA 1445): Add default library options to sc.ini / dmd.conf) + $(LI Changed result type of IsExpression from int to bool.) + $(LI Added $(B isSame) and $(B compiles) to $(B __traits).) + $(LI Added optional $(I TemplateParameterList) to $(I IsExpression).) + $(LI Added warning when $(B override) is omitted.) + $(LI Added $(B std.hiddenfunc).) + $(LI Added trace_term() to object.d to fix $(BUGZILLA 971): No profiling output is generated if the application terminates with exit) + $(LI Multiple module static constructors/destructors allowed.) + $(LI Added new syntax for string literals (delimited, heredoc, D tokens)) + $(LI Added __EOF__ token) +) + +$(BUGSFIXED + $(LI Fixed $(NG_digitalmars_D 56414)) + $(LI $(BUGZILLA 961): std.windows.registry stack corruption) + $(LI $(BUGZILLA 1315): CTFE doesn't default initialise arrays of structs) + $(LI $(BUGZILLA 1342): struct const not accepted as initializer for another struct) + $(LI $(BUGZILLA 1363): Compile-time issue with structs in 'for') + $(LI $(BUGZILLA 1375): CTFE fails for null arrays) + $(LI $(BUGZILLA 1378): A function call in an array literal causes compiler to crash) + $(LI $(BUGZILLA 1384): Compiler segfaults when using struct variable like a function with no opCall member.) + $(LI $(BUGZILLA 1388): multiple static constructors allowed in module) + $(LI $(BUGZILLA 1414): compiler crashes with CTFE and structs) + $(LI $(BUGZILLA 1421): Stack Overflow when using __traits(allMembers...)) + $(LI $(BUGZILLA 1423): Registry: corrupted value) + $(LI $(BUGZILLA 1436): std.date.getLocalTZA() returns wrong values when in DST under Windows) + $(LI $(BUGZILLA 1446): Missing comma in Final Const and Invariant page title) + $(LI $(BUGZILLA 1447): CTFE does not work for static member functions of a class) + $(LI $(BUGZILLA 1448): UTF-8 output to console is seriously broken) + $(LI $(BUGZILLA 1450): Registry: invalid UTF-8 sequence) + $(LI $(BUGZILLA 1460): Compiler crash on valid code) + $(LI $(BUGZILLA 1464): "static" foreach breaks CTFE) + $(LI $(BUGZILLA 1468): A bug about stack overflow.) +) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.004 + TITLE=Change Log: $(VER) diff --git a/changelog/2.005.dd b/changelog/2.005.dd new file mode 100644 index 0000000000..181b7effc3 --- /dev/null +++ b/changelog/2.005.dd @@ -0,0 +1,48 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 1, 2007, =================================================, + +$(WHATSNEW + $(LI $(D std.math.sin), $(D cos), $(D tan) are now evaluated at + compile time if the argument is a constant.) + $(LI Added Cristian Vlasceanu's idea for + $(LINK2 $(ROOT_DIR)spec/cpp_interface.html, C++ interface) for 'plugins') + $(LI Overhaul phobos $(D linux.mak) and add documentation build logic) + $(LI Massive additions to + $(LINK2 $(ROOT_DIR)phobos/std_conv.html, std.conv)) + $(LI Add $(CODE writeln()) and $(CODE write()) to + $(LINK2 $(ROOT_DIR)phobos/std_stdio.html, std.stdio)) +) + +$(BUGSFIXED + $(LI Fix std.boxer boxing of Object's (unit test failure)) + $(LI Fix std.demangle to not show hidden parameters (this and delegate context pointers)) + $(LI $(BUGZILLA 217): typeof not working properly in internal/object.d) + $(LI $(BUGZILLA 218): Clean up old code for packed bit array support) + $(LI $(BUGZILLA 223): Error message for unset constants doesn't specify error location) + $(LI $(BUGZILLA 278): dmd.conf search path doesn't work) + $(LI $(BUGZILLA 479): can't compare arrayliteral statically with string) + $(LI $(BUGZILLA 549): A class derived from a deprecated class is not caught) + $(LI $(BUGZILLA 550): Shifting by more bits than size of quantity is allowed) + $(LI $(BUGZILLA 551): Modulo operator works with imaginary and complex operands) + $(LI $(BUGZILLA 556): is (Type Identifier : TypeSpecialization) doesn't work as it should) + $(LI $(BUGZILLA 668): Use of *.di files breaks the order of static module construction) + $(LI $(BUGZILLA 1125): Segfault using tuple in asm code, when size not specified) + $(LI $(BUGZILLA 1437): dmd crash: "Internal error: ..\ztc\cod4.c 357") + $(LI $(BUGZILLA 1456): Cannot use a constant with alias template parameters) + $(LI $(BUGZILLA 1474): regression: const struct with an initializer not recognized as a valid alias template param) + $(LI $(BUGZILLA 1488): Bad code generation when using tuple from asm) + $(LI $(BUGZILLA 1510): ICE: Assertion failure: 'ad' on line 925 in file 'func.c') + $(LI $(BUGZILLA 1523): struct literals not work with typedef) + $(LI $(BUGZILLA 1530): Aliasing problem in DMD front end code) + $(LI $(BUGZILLA 1531): cannot access typedef'd class field) + $(LI $(BUGZILLA 1537): Internal error: ..\ztc\cgcod.c 1521) +) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.005 + TITLE=Change Log: $(VER) diff --git a/changelog/2.006.dd b/changelog/2.006.dd new file mode 100644 index 0000000000..3af25eadb7 --- /dev/null +++ b/changelog/2.006.dd @@ -0,0 +1,53 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 16, 2007, =================================================, + +$(WHATSNEW + $(LI $(RED Transformed all of $(CODE string), $(CODE wstring), + and $(CODE dstring) into invariant definitions). + Tons of changes in function signatures and + implementations rippled through the standard library. + Initial experience + with invariant strings seems to be highly encouraging.) + $(LI Implemented $(LINK2 $(ROOT_DIR)spec/function.html#overload-sets, Overload Sets) + for functions and templates.) + $(LI Added the + $(LINK2 $(ROOT_DIR)phobos/std_getopt.html,std.getopt) module that makes + standards-conforming command-line processing easy.) + $(LI Added the parse and assumeUnique to the + $(LINK2 $(ROOT_DIR)phobos/std_conv.html, std.conv) module.) + $(LI Added the dirEntries function to the + $(LINK2 $(ROOT_DIR)phobos/std_file.html, std.file) module.) + $(LI Added the basename and dirname functions (which alias the less gainful names getBaseName and getDirectoryName to the + $(LINK2 $(ROOT_DIR)phobos/std_path.html,std.path) module.)) + $(LI Added optional terminator to readln; added the convenience functions fopen and popen; added functions lines and chunks; all to the + $(LINK2 $(ROOT_DIR)phobos/std_stdio.html, std.stdio) module.) + $(LI Added the munch function to the + $(LINK2 $(ROOT_DIR)phobos/std_string.html, std.string) module.) + $(LI Fixed isStaticArray; added BaseClassesTuple, TransitiveBaseTypeTuple, ImplicitConversionTargets, isIntegral, isFloatingPoint, isNumeric, isSomeString, isAssociativeArray, isDynamicArray, isArray; all to the + $(LINK2 $(ROOT_DIR)phobos/std_traits.html, std.traits) module.) + $(LI Added the + $(LINK2 $(ROOT_DIR)phobos/std_variant.html, std.variant) module.) + $(LI Incorporated many of the Tango GC structural differences (much more to go still).) + $(LI Added the $(D std.contracts) module.) + $(LI Breaking change: $(CODE std.stdio.writef) can now only accept a format as + its first argument.) +) + +$(BUGSFIXED + $(LI $(BUGZILLA 1478): Avoid libc network api threadsafety issues) + $(LI $(BUGZILLA 1491): Suppress SIGPIPE when sending to a dead socket) + $(LI $(BUGZILLA 1562): Deduction of template alias parameter fails) + $(LI $(BUGZILLA 1571): Const on function parameters not carried through to .di file) + $(LI $(BUGZILLA 1575): Cannot do assignment of tuples) + $(LI $(BUGZILLA 1579): write[ln] fails for obj.toString()) + $(LI $(BUGZILLA 1580): Concatenating invariant based strings should work) +) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.006 + TITLE=Change Log: $(VER) diff --git a/changelog/2.007.dd b/changelog/2.007.dd new file mode 100644 index 0000000000..5787095265 --- /dev/null +++ b/changelog/2.007.dd @@ -0,0 +1,47 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 31, 2007, =================================================, + +$(WHATSNEW + $(LI Functors now supported by std.traits.ReturnType().) + $(LI Transitive const now leaves invariants intact in the tail.) + $(LI Added overloadable unary * operation as opStar().) + $(LI Full closure support added.) + $(LI Data items in static data segment >= 16 bytes in size + are now paragraph aligned.) +) + +$(BUGSFIXED + $(LI Variables of type void[0] can now be declared.) + $(LI Static multidimensional arrays can now be initialized with + other matching static multidimensional arrays.) + $(LI $(BUGZILLA 318): wait does not release thread resources on Linux) + $(LI $(BUGZILLA 322): Spawning threads which allocate and free memory leads to pause error on collect) + $(LI $(BUGZILLA 645): Race condition in std.thread.Thread.pauseAll) + $(LI $(BUGZILLA 689): Clean up the spec printfs!) + $(LI $(BUGZILLA 697): No const folding on asm db,dw, etc) + $(LI $(BUGZILLA 706): incorrect type deduction for array literals in functions) + $(LI $(BUGZILLA 708): inline assembler: "CVTPS2PI mm, xmm/m128" fails to compile) + $(LI $(BUGZILLA 709): inline assembler: "CVTPD2PI mm, xmm/m128" fails to compile) + $(LI $(BUGZILLA 718): Internal error: ../ztc/cgcod.c 562) + $(LI $(BUGZILLA 723): bad mixin of class definitions at function level: func.c:535: virtual void FuncDeclaration::semantic3(Scope*): Assertion `0` failed) + $(LI $(BUGZILLA 725): expression.c:6516: virtual Expression* MinAssignExp::semantic(Scope*): Assertion `e2->type->isfloating()` failed.) + $(LI $(BUGZILLA 726): incorrect error line for "override" mixin) + $(LI $(BUGZILLA 729): scope(...) statement in SwitchBody causes compiler to segfault) + $(LI $(BUGZILLA 1258): Garbage collector loses memory upon array concatenation) + $(LI $(BUGZILLA 1480): std.stream throws the new override warning all over the place) + $(LI $(BUGZILLA 1483): Errors in threads not directed to stderr) + $(LI $(BUGZILLA 1557): std.zlib allocates void[]s instead of ubyte[]s, causing leaks.) + $(LI $(BUGZILLA 1580): concatenating invariant based strings should work) + $(LI $(BUGZILLA 1593): ICE compiler crash empty return statement in function) + $(LI $(BUGZILLA 1613): DMD hangs on syntax error) + $(LI $(BUGZILLA 1618): Typo in std\system.d) +) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.007 + TITLE=Change Log: $(VER) diff --git a/changelog/2.008.dd b/changelog/2.008.dd new file mode 100644 index 0000000000..e781881877 --- /dev/null +++ b/changelog/2.008.dd @@ -0,0 +1,55 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Nov 27, 2007, =================================================, + +$(WHATSNEW + $(LI std.string: Made munch more general and added function chompPrefix.) + $(LI std.variant: Added documentation for variantArray) + $(LI std.traits: Added CommonType template, fixed isStaticArray.) + $(LI std.bitarray: scheduled for deprecation) + $(LI std.bitmanip: new module with the content of std.bitarray plus the bitfields, FloatRep, and DoubleRep templates) + $(LI std.process: Made getpid visible in Linux builds) + $(LI std.math: Made nextafter visible for all floating types. Added approxEqual template.) + $(LI std.contracts: Added enforce signature taking an exception) + $(LI std.conv: Made conv_error a template parameterized on the types being converted.) + $(LI std.stdio: Cosmetic changes.) + $(LI std.system: Cosmetic changes.) + $(LI std.file: Fixed bug in function dirEntries.) + $(LI std.random: Major addition of engines and distributions.) + $(LI std.format: Added raw ('r') format specifier for writef*.) + $(LI std.path: Added rel2abs (Linux version only).) + $(LI std.algorithm: new module) + $(LI std.typecons: new module) + $(LI std.functional: new module) + $(LI std.numeric: new module) + $(LI Added + $(LINK2 $(ROOT_DIR)spec/struct.html#ConstStruct, const/invariant structs), + $(LINK2 $(ROOT_DIR)spec/class.html#ConstClass, classes) and + $(LINK2 $(ROOT_DIR)spec/interface.html#ConstInterface, interfaces).) + $(LI Added $(CODE const) and $(CODE invariant) to + $(LINK2 $(ROOT_DIR)spec/expression.html#IsExpression, IsExpression)s.) + $(LI Added $(CODE typeof(return)) type specifier.) + $(LI Changed the way coverage analysis is done so it is independent + of order dependencies among modules.) + $(LI Revamped const/invariant.) +) + +$(BUGSFIXED + $(LI $(BUGZILLA 70): valgrind: Conditional jump or move depends on uninitialised value(s) in elf_findstr) + $(LI $(BUGZILLA 71): valgrind: Invalid read of size 4 in elf_renumbersyms) + $(LI $(BUGZILLA 204): Error message on attempting to instantiate an abstract class needs to be improved) + $(LI $(BUGZILLA 1508): dmd/linux template symbol issues) + $(LI $(BUGZILLA 1651): .di file generated with -H switch does not translate function() arguments correctly) + $(LI $(BUGZILLA 1655): Internal error: ..\ztc\cgcod.c 1817) + $(LI $(BUGZILLA 1656): illegal declaration accepted) + $(LI $(BUGZILLA 1664): (1.23).stringof generates bad code) + $(LI $(BUGZILLA 1665): Internal error: ..\ztc\cod2.c 411) +) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.008 + TITLE=Change Log: $(VER) diff --git a/changelog/2.009.dd b/changelog/2.009.dd new file mode 100644 index 0000000000..70b4bbdf18 --- /dev/null +++ b/changelog/2.009.dd @@ -0,0 +1,30 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 1, 2008, =================================================, + +$(WHATSNEW + $(LI Redid const/invariant semantics again.) + $(LI Extended enums to allow declaration of manifest constants.) +) + +$(BUGSFIXED + $(LI $(BUGZILLA 1111): enum value referred to by another value of same enum is considered as enum's base type, not enum type) + $(LI $(BUGZILLA 1694): Zip::ArchiveMember::name format bug) + $(LI $(BUGZILLA 1702): ICE when identifier is undefined) + $(LI $(BUGZILLA 1738): Error on struct without line number) + $(LI $(BUGZILLA 1742): CTFE fails on some template functions) + $(LI $(BUGZILLA 1743): interpret.c:1421 assertion failure on CTFE code) + $(LI $(BUGZILLA 1744): CTFE: crash on assigning void-returning function to variable) + $(LI $(BUGZILLA 1745): Internal error: ..\ztc\out.c 115) + $(LI $(BUGZILLA 1749): std.socket not thread-safe due to strerror) + $(LI $(BUGZILLA 1753): String corruption in recursive CTFE functions) + $(LI $(NG_digitalmars_D 63456): Cannot overload on constancy of this) +) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.009 + TITLE=Change Log: $(VER) diff --git a/changelog/2.010.dd b/changelog/2.010.dd new file mode 100644 index 0000000000..63c78f97c6 --- /dev/null +++ b/changelog/2.010.dd @@ -0,0 +1,40 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 20, 2008, =================================================, + + $(WHATSNEW + $(LI $(CODE opAssign) can no longer be overloaded for class objects.) + $(LI $(CODE WinMain) and $(CODE DllMain) can now be in template mixins.) + $(LI Added $(CODE pure) keyword.) + ) + + $(BUGSFIXED + $(LI $(BUGZILLA 1319): compiler crashes with functions that take const ref arguments) + $(LI $(BUGZILLA 1697): Internal error: ..\ztc\cgcod.c 2322 with -O) + $(LI $(BUGZILLA 1700): ICE attempting to modify member of const return struct) + $(LI $(BUGZILLA 1707): '==' in TemplateParameterList in IsExpression causes segfault) + $(LI $(BUGZILLA 1711): typeof with delegate literal not allowed as template parameter) + $(LI $(BUGZILLA 1713): foreach index with tuples and templates fails) + $(LI $(BUGZILLA 1718): obscure exit with error code 5) + $(LI $(BUGZILLA 1719): Compiler crash or unstable code generation with scoped interface instances) + $(LI $(BUGZILLA 1720): std.math.NotImplemented missing a space in message) + $(LI $(BUGZILLA 1724): Internal error: toir.c 177) + $(LI $(BUGZILLA 1725): std.stream.BufferedFile.create should use FileMode.OutNew) + $(LI $(BUGZILLA 1757): there is an fault in phobos windows api interface) + $(LI $(BUGZILLA 1762): Wrong name mangling for pointer args of free extern (C++) functions) + $(LI $(BUGZILLA 1767): rejects-valid, diagnostic) + $(LI $(BUGZILLA 1769): Typo on the page about exceptions) + $(LI $(BUGZILLA 1773): excessively long integer literal) + $(LI $(BUGZILLA 1779): Compiler crash when deducing more than 2 type args) + $(LI $(BUGZILLA 1783): DMD 1.025 asserts on code with struct, template, and alias) + $(LI $(BUGZILLA 1788): dmd segfaults without info) + $(LI $(NG_digitalmars_D_announce 11066): Re: DMD 1.025 and 2.009 releases) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.010 + TITLE=Change Log: $(VER) diff --git a/changelog/2.011.dd b/changelog/2.011.dd new file mode 100644 index 0000000000..7a1e3cc74f --- /dev/null +++ b/changelog/2.011.dd @@ -0,0 +1,61 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 18, 2008, =================================================, + + $(WHATSNEW + $(LI std.typecons: fixed code bloat issue; added Tuple.toString; added function tuple(); fixed unlisted bug in enumValuesImpl.) + $(LI std.process: added function shell().) + $(LI std.math: minor change in approxEqual.) + $(LI std.contracts: added functions pointsTo()) + $(LI std.numeric: minor unittest fixes.) + $(LI std.bitmanip: fixed code bloat issue, reintroduced FloatRep and DoubleRep.) + $(LI std.conv: minor simplification of implementation.) + $(LI std.regexp: added reference to ECMA standard in the documentation.) + $(LI std.getopt: changed return type from bool to void, error is signaled by use of exceptions.) + $(LI std.functional: added unaryFun, binaryFun, adjoin.) + $(LI std.string: updated documentation, changed code to compile with warnings enabled.) + $(LI std.traits: changed FieldTypeTuple; added RepresentationTypeTuple, hasAliasing; fixed bug 1826; added call to flush() from within write; fixed unlisted bug in lines().) + $(LI std.algorithm: added map, reduce, filter, inPlace, move, swap, overwriteAdjacent, find, findRange, findBoyerMoore, findAdjacent, findAmong, findAmongSorted, canFind, canFindAmong, canFindAmongSorted, count, equal, overlap, min, max, mismatch, EditOp, none, substitute, insert, remove, levenshteinDistance, levenshteinDistanceAndPath, copy, copyIf, iterSwap, swapRanges, reverse, rotate, SwapStrategy, Unstable, Semistable, Stable, eliminate, partition, nthElement, sort, schwartzSort, partialSort, isSorted, makeIndex, schwartzMakeIndex, lowerBound, upperBound, equalRange, canFindSorted.) + $(LI std.thread: fixed so it compiles with warnings enabled.) + $(LI std.file: made getSize() faster under Linux.) + $(LI std.random: fixed so it compiles with warnings enabled; improved function uniform so it deduces type generated from its arguments.) + $(LI std.format: added fixes to make formatting work with const data.) + $(LI std.path: minor documentation changes. ) + $(LI Added $(CODE std.xml)) + $(LI Added $(CODE std.complex)) + $(LI Added $(CODE std.iterator)) + $(LI Added $(CODE std.c.linux.tipc)) + $(LI Added $(CODE std.c.linux.termios)) + $(LI Added $(CODE nothrow) keyword) + $(LI Re-enabled auto interfaces.) + $(LI Now allow static arrays to be lvalues.) + $(LI Now allows implicit casting of $(CODE null) to/from const/invariant.) + $(LI Now allows implicit casting of $(I StructLiteral)s if each of + its arguments can be implicitly cast.) + $(LI Now allows implicit casting of structs to/from const/invariant if + each of its fields can be.) + $(LI Added $(LINK2 + $(ROOT_DIR)spec/pragma.html#Predefined-Pragmas, pragma startaddress).) + $(LI $(CODE .tupleof) can now access private fields of a struct/class) + $(LI Enhancement $(BUGZILLA 493): Partial IFTI does not work) + ) + + $(BUGSFIXED + $(LI Fixed $(NG_digitalmars_D 66406) Remaining const niggles #1 - Custom POD types) + $(LI Fixed display of ddoc template parameters that were aliased) + $(LI Fixed bug in std.file.readln() for Windows in translated mode) + $(LI $(BUGZILLA 1072): CTFE: crash on for loop with blank increment) + $(LI $(BUGZILLA 1435): DDoc: Don't apply DDOC_PSYMBOL everywhere) + $(LI $(BUGZILLA 1815): foreach with interval does not increment pointers correctly) + $(LI $(BUGZILLA 1825): local instantiation and function nesting) + $(LI $(BUGZILLA 1837): Make dmd stop flooding the console: prints content of passed parameter file) + $(LI $(BUGZILLA 1842): Useless linker command line output during compilation on Linux) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.011 + TITLE=Change Log: $(VER) diff --git a/changelog/2.012.dd b/changelog/2.012.dd new file mode 100644 index 0000000000..e8c7238a25 --- /dev/null +++ b/changelog/2.012.dd @@ -0,0 +1,106 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 6, 2008, =================================================, + + $(WHATSNEW + $(LI Added predefined version($(LINK2 + $(ROOT_DIR)spec/version.html#PredefinedVersions, unittest)). See $(BUGZILLA 458)) + $(LI Removed $(B std.math2)) + $(LI Added compile time error for comparing class types against $(CODE null).) + $(LI Added struct destructors and postblits.) + + $(LI std.algorithm: Made some imports conditional for the Unittest + version; fixed doc typo; made min and max always return the tightest + type and work with mixes of signed and unsigned; changed enum value + names to obey lowercase convention; changed OrderStrategy to + SwapStrategy as it's not just for ordering (e.g. see eliminate).) + + $(LI std.bitmanip: simplified code generated for bitfields and improved + error message.) + + $(LI std.format: ate dogfood: used bitfields internally.) + + $(LI std.functional: fixed binaryfun to work with constant-size arrays; + added compose.) + + $(LI std.random: made unpredictableSeed return different numbers every + call (except for rarely-encountered MT scenarios); added private + variable name that will take experts millenia to figure out; changed the + boundaries syntax from two separate characters '[', '$(LPAREN)' to one + string "[$(LPAREN)" throughout.) + + $(LI std.traits: added mostNegative, mostly to assuage for the + unpardonable mistake of inheriting C++'s unpardonable mistake of + defining "min" to mean very different things for floating-point types + and integral types.) + + $(LI std.typecons: added undocumented Rebindable in preparation for + opImplicitCast.) + + $(LI std.math: + $(UL + $(LI Support for different CPU IEEE 'real' formats: 64-bit, 80-bit and + 128-bit (quadruple) reals, both BigEndian and LittleEndian; partial + support for non-IEEE 'doubledouble' reals.) + $(LI Added implementation of nextafter $(BUGZILLA 1722) and scalb for + DMD-Windows.) + $(LI Added nextUp(), nextDown()) + $(LI $(BUGZILLA 1881): feqrel nonsensical for non-real arguments.) + $(LI internal functions isPosZero(), isNegZero() removed in favour of + the more generally useful isIdentical().) + $(LI asm versions of functions which were not implemented by DMD + Windows: scalb, lrint.) + $(LI added creal expi(real y) which is useful for simultaneous + calculation of sin + cos.) + ) + ) + ) + $(BUGSFIXED + $(LI std.contracts: fixed unlisted bug in pointsTo.) + $(LI std.conv: fixed bug related to number-to-number conversion (T.min + hits again).) + $(LI Fixed dwarf bug with DT_AT_upper_bound) + $(LI $(BUGZILLA 756): IFTI for tuples only works if tuple parameter is last) + $(LI $(BUGZILLA 1454): IFTI cant deduce parameter if alias argument used) + $(LI $(BUGZILLA 1661): Not possible to specialize on template with integer parameter) + $(LI $(BUGZILLA 1800): Compiler crash on enums nested in structs) + $(LI $(BUGZILLA 1801): Const structs should be assignable to non-const variables unless they contain references) + $(LI $(BUGZILLA 1806): "const" makes typesafe variadic arguments not work properly.) + $(LI $(BUGZILLA 1809): template.c:2600) + $(LI $(BUGZILLA 1810): MmFile anonymous mapping does not work under win32) + $(LI $(BUGZILLA 1819): spurious warning about missing return statement after synchronized) + $(LI $(BUGZILLA 1821): ICE when using __traits isSame on const/invariant variables) + $(LI $(BUGZILLA 1823): Implicit conversion to const on associative array) + $(LI $(BUGZILLA 1828): Several Thread Issues) + $(LI $(BUGZILLA 1833): std.c.windows.windows should use enums for constants, or be more selective about use of extern(Windows)) + $(LI $(BUGZILLA 1836): Inline assembler can't use enum values as parameters.) + $(LI $(BUGZILLA 1837): Make dmd stop flooding the console: prints content of passed parameter file) + $(LI $(BUGZILLA 1843): Bogus unreachable statement on forward referenced struct, lacks line number) + $(LI $(BUGZILLA 1850): The compiler accepts lower case asm registers.) + $(LI $(BUGZILLA 1851): missing opCall? when cast away const struct) + $(LI $(BUGZILLA 1852): you get opCall missing when cast to a struct(diagnostic)) + $(LI $(BUGZILLA 1853): opCmp documentation really needs some examples) + $(LI $(BUGZILLA 1854): bug in new flow analysis (warnings on valid code)) + $(LI $(BUGZILLA 1857): Runtime segfault while profileing - jump to invalid code address) + $(LI $(BUGZILLA 1862): asm: [ESI+1*EAX] should be a legal addr mode) + $(LI $(BUGZILLA 1865): Escape sequences are flawed.) + $(LI $(BUGZILLA 1867): lazy adds spurious const qualifier) + $(LI $(BUGZILLA 1871): DMD debug messages printed) + $(LI $(BUGZILLA 1873): structs with at least one immutable member are completely immutable) + $(LI $(BUGZILLA 1874): __traits(allMembers, T) fails to list methods which only have non-mutating overloads) + $(LI $(BUGZILLA 1876): inside a non-static class method, should "&( f)" be same as "&(this.f)" ?) + $(LI $(BUGZILLA 1877): Errors in the documentation of std.math.atan2) + $(LI $(BUGZILLA 1882): Internal error: ..\ztc\cod1.c 2529) + $(LI $(BUGZILLA 1883): templates instantiated as real gives incorrect values) + $(LI $(BUGZILLA 1884): manifest constants for strings) + $(LI $(BUGZILLA 1885): Syntax error for object identity test between invariant/mutable references) + $(LI $(BUGZILLA 1887): compiler freeze on array of dyn. arrays with empty first initializer) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.012 + TITLE=Change Log: $(VER) diff --git a/changelog/2.013.dd b/changelog/2.013.dd new file mode 100644 index 0000000000..1329295ef6 --- /dev/null +++ b/changelog/2.013.dd @@ -0,0 +1,59 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 22, 2008, =================================================, + + $(WHATSNEW + $(LI Added $(B -ignore) switch to ignore unsupported pragmas.) + $(LI Unsupported pragmas now printed out with $(B -v) switch.) + $(LI Added $(LINK2 $(ROOT_DIR)spec/operatoroverloading.html#Dot, opDot), which is + $(RED experimental only).) + $(LI + $(LINK2 $(ROOT_DIR)spec/statement.html#SwitchStatement, $(I SwitchStatement))s + can now accept runtime initialized const and invariant case statements.) + $(LI Changed $(CODE __FILE__) and $(CODE __LINE__) so they work as + parameter default initializers.) + $(LI Incorporated Benjamin Shropshire's doc changes) + $(LI Hidden methods now get a compile time warning rather than a runtime + one.) + $(LI Html source files are now deprecated.) + $(LI Added $(LINK2 $(ROOT_DIR)spec/function.html#pure-functions, pure) and + $(LINK2 $(ROOT_DIR)spec/function.html#nothrow-functions, nothrow) + function attributes, although their semantics are not implemented.) + $(LI Deprecated $(I VolatileStatement); use + $(LINK2 $(ROOT_DIR)spec/statement.html#SynchronizedStatement, $(I SynchronizedStatement)) + instead.) + $(LI Added $(B __thread) storage class for thread local storage. + This is $(RED for testing purposes only) to check out the machinery + in the back end. The front end design of this will change.) + $(LI $(LINK2 http://www.digitalmars.com/ctg/obj2asm.html, $(B obj2asm)) + and $(LINK2 http://www.digitalmars.com/ctg/dumpobj.html, $(B dumpobj)) + now better handle special ELF fixup records.) + $(LI Added $(LINK2 $(ROOT_DIR)spec/function.html#partial-ordering, partial ordering) + rules to disambiguate function overloading.) + $(LI std.perf: Bill Baxter cleaned it up.) + $(LI std.xml.Document constructor now creates whole DOM tree.) + $(LI Added std.encoding.) + ) + $(BUGSFIXED + $(LI $(NG_digitalmars_D 69085): const/invariant bug?) + $(LI $(BUGZILLA 1712): vtbl[0] for interface not set to corresponding Interface*) + $(LI $(BUGZILLA 1723): __traits(getVirtualFunctions) on a non-function fails badly) + $(LI $(BUGZILLA 1741): crash on associative array with static array as index type) + $(LI $(BUGZILLA 1905): foreach docs inconsistency) + $(LI $(BUGZILLA 1906): foreach cannot use index with large arrays) + $(LI $(BUGZILLA 1925)) + $(LI $(BUGZILLA 1935): The std.recls samples in the DMD .zip are obsolete.) + $(LI $(BUGZILLA 1967): getDirName does not seem to use altsep on windows) + $(LI $(BUGZILLA 1978): Wrong vtable call) + $(LI $(BUGZILLA 1991): Dmd hangs) + $(LI $(BUGZILLA 2016): 'invariant' TypeSpecialization is missing) + $(LI $(BUGZILLA 2019): Appending a one-element array literal doesn't work) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.013 + TITLE=Change Log: $(VER) diff --git a/changelog/2.014.dd b/changelog/2.014.dd new file mode 100644 index 0000000000..9e51b35756 --- /dev/null +++ b/changelog/2.014.dd @@ -0,0 +1,69 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION May 16, 2008, =================================================, + + $(WHATSNEW + $(LI Added $(B -man) switch to browse manual.) + $(LI Added $(B -lib) switch to generate library files. + Also causes multiple object files to be generated from one + source module.) + $(LI When generating an executable file, only one object file + is now generated containing all the modules that were compiled, rather + than one object file per module.) + $(LI Rewrote the $(LINK2 $(ROOT_DIR)rdmd.html,$(B rdmd)) utility to properly + track dependencies and command-line compiler options (currently only + working under Linux).) + $(LI Changed the Phobos makefile $(D linux.mak) to take advantage of + the new $(B -lib) feature. Improved full build speed by 3x.) + $(LI std.algorithm: Changed the map() function so that it deduces the return type. Also map can be now curried.) + $(LI std.contracts: Added file and line information to enforce. Added errnoEnforce that formats the error message according to errno. Added corresponding ErrnoException class.) + $(LI std.conv: Made std.to curryable. Changed std.to to throw exception when object-to-object cast fails. Eliminated some superfluous printfs.) + $(LI std.encoding: Added new functions encodedLength(dchar) and encode(dchar, ref E[])) + $(LI std.encoding: Got rid of types Utf8, Utf16, Utf32, Ascii, Latin1, Windows1252. Introduced types AsciiChar, AsciiString, Latin1Char, Latin1String, Windows1252Char, Windows1252String.) + $(LI std.encoding: For now commented out std.encoding.to.) + $(LI std.file: Changed Boolean function signatures (e.g. exists) to return bool instead of int. Got rid of some gotos. Added the readText, lastModified, mkdirRecurse, and rmdirRecurse functions.) + $(LI std.functional: Improved compose so it accepts an unbounded number of functions. Added the pipe function.) + $(LI std.getopt: Added new option stopOnFirstNonOption. Also automatically expand dubious option groups with embedded spaces in them (useful for shebang scripts)) + $(LI std.math: improved integral powers) + $(LI std.md5: Improved signature of sum so it takes multiple arrays. Added getDigestString.) + $(LI std.path: changed signatures of test functions from bool to int. Implemented rel2abs for Windows. Improved join so that it accepts multiple paths. Got rid of some gotos with the help of scope statements.) + $(LI std.process: added getenv and setenv. Improved system() so it returns the exit code correctly on Linux.) + $(LI std.random: added the dice function - a handy (possibly biased) dice.) + $(LI std.typecons: Finalized and documented the stupendous Rebindable template.) + $(LI std.utf: added the codeLength function. Got rid of some gotos.) + ) + $(BUGSFIXED + $(LI std.format: Fixed unlisted bug in raw write for arrays) + $(LI std.getopt: Fixed unlisted bug in dealing with one-letter options with bundling disabled) + $(LI $(BUGZILLA 2014): fopen fails on large files.) + $(LI $(BUGZILLA 2031): Documentation: template value parameters) + $(LI $(BUGZILLA 2032): Documentation for creating a class on the stack is unintuitive) + $(LI $(BUGZILLA 2037): Article on hijacking is outdated) + $(LI $(BUGZILLA 2038): Remove hello2.html from samples directory) + $(LI $(BUGZILLA 2039): -ignore switch is missing from compiler docs) + $(LI $(BUGZILLA 2054): Const system broken on struct assignment.) + $(LI $(BUGZILLA 2055): (ICE) Compiler crash on struct initializer with too many elements) + $(LI $(BUGZILLA 2056): Const system does not allow certain safe casts/conversions involving deep composite types) + $(LI $(BUGZILLA 2058): Describe hidden value passed to class member functions) + $(LI $(BUGZILLA 2063): std.xml access violation for nested, closed tags) + $(LI $(BUGZILLA 2065): Return value of std.file.exists() is inverted.) + $(LI $(BUGZILLA 2067): call from anonymous class makes access violation.) + $(LI $(BUGZILLA 2071): spec doesn't mention pointer arithmetic with two pointer operands) + $(LI $(BUGZILLA 2072): std.typecons documentation anomaly.) + $(LI $(BUGZILLA 2074): Variant arithmetic operations fail. For now the fix is to comment out all right-hand side operators. Suggestions for a better fix are welcome.) + $(LI $(BUGZILLA 2075): Spec does not specify how array literals are stored.) + $(LI $(BUGZILLA 2084): operator ?: does not compute the tightest type) + $(LI $(BUGZILLA 2086): Describe relationship between string and char[] more explicitly) + $(LI $(BUGZILLA 2089): Issues with CTFE and tuple indexes) + $(LI $(BUGZILLA 2090): Cannot alias a tuple member which is a template instance) + $(LI $(BUGZILLA 2100): Assertion failure: '0' on line 4842 in file 'expression.c') + $(LI $(BUGZILLA 2109): asm {lea EAX, [0*0+EAX]; } rejected.) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.014 + TITLE=Change Log: $(VER) diff --git a/changelog/2.015.dd b/changelog/2.015.dd new file mode 100644 index 0000000000..293b50c953 --- /dev/null +++ b/changelog/2.015.dd @@ -0,0 +1,52 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jun 17, 2008, =================================================, + + $(WHATSNEW + $(LI + $(LINK2 $(ROOT_DIR)spec/template.html#aliasparameters, Template alias arguments) + can now be literals.) + $(LI + $(LINK2 $(ROOT_DIR)spec/template.html#function-templates, Function templates) + can now deduce the return type if they are declared with $(CODE auto).) + $(LI Non-lvalues are no longer matched to $(CODE ref) and $(CODE out) + parameters when + $(LINK2 $(ROOT_DIR)spec/function.html#function-overloading, overloading).) + $(LI Relaxed hidden hijacking detection when hidden function is disjoint + from overloading with any other virtual function in the + $(LINK2 $(ROOT_DIR)spec/function.html#function-inheritance, hierarchy).) + $(LI Added $(LINK2 $(ROOT_DIR)spec/version.html#PredefinedVersions, version + identifier $(B D_PIC)) when $(B -fPIC) switch is used.) + $(LI Added $(LINK2 $(ROOT_DIR)spec/template.html#Constraint, $(I Constraint)s) to + templates.) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 1383): Implicit Function Instantiation with typesafe-variadic of delegates doesn't work) + $(LI $(BUGZILLA 1559): version statement makes code outside of it disappear) + $(LI $(BUGZILLA 1675): "Identifier too long" error with OMF object files) + $(LI $(BUGZILLA 1947): ICE (Assertion failure: '0' on statement.c:123) with null mixin) + $(LI $(BUGZILLA 1963): -H creates broken headers) + $(LI $(BUGZILLA 2098): Outdated docs) + $(LI $(BUGZILLA 2099): Text and Sample Code Disagree (non-static local invariant declaration)) + $(LI $(BUGZILLA 2112): the type of undefined variable incorrectly assumed to be int) + $(LI $(BUGZILLA 2118): Inconsistent use of string vs invariant(char[]) in doc) + $(LI $(BUGZILLA 2123): Anonymous class crashes) + $(LI $(BUGZILLA 2129): foreach won't work with invariant limits) + $(LI $(BUGZILLA 2132): CTFE: can't evaluate ~= at compile time, D2 only.) + $(LI $(BUGZILLA 2133): anonymous enum without {} doesn't work as asm value) + $(LI $(BUGZILLA 2136): typeof(super(...)) counted as a constructor call) + $(LI $(BUGZILLA 2140): static if as final statement with no code causes containing code to be skipped) + $(LI $(BUGZILLA 2143): Mixed-in identifier is not recognized by static if) + $(LI $(BUGZILLA 2144): 'is' is defined to be the same as '==' for non-class and non-array types, but does not call opEquals) + $(LI $(BUGZILLA 2145): Phobos buildsystem unable to build html) + $(LI $(BUGZILLA 2146): Multiple execution of 'static this' defined in template) + $(LI $(BUGZILLA 2149): Auto variables loose the keyword "auto" in di files generated with -H option.) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.015 + TITLE=Change Log: $(VER) diff --git a/changelog/2.016.dd b/changelog/2.016.dd new file mode 100644 index 0000000000..3dfe42b8e7 --- /dev/null +++ b/changelog/2.016.dd @@ -0,0 +1,78 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 8, 2008, =================================================, + + $(WHATSNEW + $(LI re-implemented $(B internal.monitor) in D. Rationalized $(B internal.object)) + $(LI $(BUGZILLA 288): changed return type of $(B opEquals) from int + to bool. This necessitates doing a grep for opEquals and + $(RED changing all the return values). + ) + $(LI Added $(B .__vptr) and $(B .__monitor) properties for class objects + for use in the internal runtime library. + ) + $(LI Made $(LINK2 $(ROOT_DIR)rdmd.html, rdmd)'s source available through + svn, see + $(LINK http://dsource.org/projects/phobos/browser/trunk/tools/rdmd.d) + ) + $(LI Simplified $(B std.algorithm) by fusing together higher-order functions taking an alias and their counterparts taking a string) + $(LI Added module $(B std.array) containing array operations: $(B insert), $(B erase), and $(B replace)) + $(LI Changed the $(B enforce)'s implementation to generate smaller code per call) + $(LI Changed $(B std.functional.binaryFun) to work with strings and function aliases alike) + $(LI In $(B std.getopt), added $(B optChar), $(B assignChar), and $(B endOfOptions), per popular demand :o|) + $(LI In $(B std.math), replaced a bunch of $(B const)s with $(B enum)s) + $(LI In $(B std.numeric), added Don Clugston as author and operated minor documentation fixes) + $(LI Improved $(B std.stdio.chunks) to take an iteration tally in addition to the chunk) + ) + $(BUGSFIXED + $(LI $(NG_digitalmars_D_announce 12322): mixin regression) + $(LI $(BUGZILLA 203): std.format.doFormat() pads width incorrectly on Unicode strings) + $(LI $(BUGZILLA 211): Linking error with alias mixin params and anonymous methods) + $(LI $(BUGZILLA 224): Incorrect warning "no return at end of function") + $(LI $(BUGZILLA 252): -w and switch returns = bogus "no return at end of function" warning) + $(LI $(BUGZILLA 253): Invalid <dl> tag generated by Ddoc) + $(LI $(BUGZILLA 294): DDoc: Function templates get double and incomplete documentation) + $(LI $(BUGZILLA 398): No way to abort compilation in a doubly recursive mixin) + $(LI $(BUGZILLA 423): dmd ignores empty commandline arguments) + $(LI $(BUGZILLA 515): Spec incorrect in where .offsetof can be applied) + $(LI $(BUGZILLA 520): Invariants allowed to call public functions) + $(LI $(BUGZILLA 542): Function parameter of a deprecated type (other than a class) is not caught) + $(LI $(BUGZILLA 543): Function return of a deprecated type is not caught) + $(LI $(BUGZILLA 544): Variable declared of a deprecated type (other than a class) is not caught) + $(LI $(BUGZILLA 545): Attempt to access a static built-in property of a deprecated struct, union, enum or typedef is not caught) + $(LI $(BUGZILLA 547): Accessing a deprecated member variable through an explicit object reference is not caught) + $(LI $(BUGZILLA 548): Accessing a value of a deprecated enum is not caught) + $(LI $(BUGZILLA 566): Adding non-static members and functions to classes using a template doesn't error) + $(LI $(BUGZILLA 570): Bogus recursive mixin error) + $(LI $(BUGZILLA 571): class instance member template returns strange value) + $(LI $(BUGZILLA 572): parse error when using template instantiation with typeof) + $(LI $(BUGZILLA 581): Error message w/o line number in dot-instantiated template) + $(LI $(BUGZILLA 617): IFTI doesn't use normal promotion rules for non-template parameters) + $(LI $(BUGZILLA 870): contradictory error messages for templates) + $(LI $(BUGZILLA 951): Missing line number: no constructor provided for a class derived from a class with no default constructor) + $(LI $(BUGZILLA 1097): Missing line number: casting array to array of different element size) + $(LI $(BUGZILLA 1158): Missing line number: invalid mixin outside function scope) + $(LI $(BUGZILLA 1176): Error missing file and line number) + $(LI $(BUGZILLA 1187): Segfault with syntax error in two-level mixin.) + $(LI $(BUGZILLA 1194): fcmov* emmits incorrect code) + $(LI $(BUGZILLA 1207): Documentation on destructors is confusing) + $(LI $(BUGZILLA 1341): typeof(int) should probably be legal) + $(LI $(BUGZILLA 1601): shr and shl error message is missing line numbers) + $(LI $(BUGZILLA 1612): No file/line number for using an undefined label in inline assembly) + $(LI $(BUGZILLA 1912): Error without line number (Tuple, invalid value argument)) + $(LI $(BUGZILLA 1936): Error with no line number (array dimension overflow)) + $(LI $(BUGZILLA 2076): asm: offset has wrong docs and error without line number) + $(LI $(BUGZILLA 2161): Modify compiler to pass array TypeInfo to _adEq and _adCmp instead of element TypeInfo) + $(LI $(BUGZILLA 2178): 3 errors without line number: typeof) + $(LI $(BUGZILLA 2188): man-or-boy test fails with access violation) + $(LI Fixed bugs in $(B std.file.rename) and $(B std.file.remove) on Linux) + $(LI Fixed documentation in $(B std.typecons)) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.016 + TITLE=Change Log: $(VER) diff --git a/changelog/2.017.dd b/changelog/2.017.dd new file mode 100644 index 0000000000..cc0c120a99 --- /dev/null +++ b/changelog/2.017.dd @@ -0,0 +1,21 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 11, 2008, =================================================, + + $(WHATSNEW + ) + $(BUGSFIXED + $(LI $(BUGZILLA 2207): overload resolution fails with deprecation) + $(LI $(BUGZILLA 2208): Deprecated function declarations cannot use deprecated types) + $(LI $(BUGZILLA 2209): Typo in doc for offsetof) + $(LI $(BUGZILLA 2212): phobos itself should be able to be compiled with '-w' switch) + $(LI $(BUGZILLA 2264): typo in documentation regarding atof.) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.017 + TITLE=Change Log: $(VER) diff --git a/changelog/2.018.dd b/changelog/2.018.dd new file mode 100644 index 0000000000..e536c86122 --- /dev/null +++ b/changelog/2.018.dd @@ -0,0 +1,35 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Aug 7, 2008, =================================================, + + $(WHATSNEW + $(LI Now supports $(LINK2 $(ROOT_DIR)spec/arrays.html#array-operations, array + operations).) + ) + $(BUGSFIXED + $(LI Added hash to generated module names when building libs to reduce collisions) + $(LI $(BUGZILLA 1622): parameters to TypeInfo_Struct.compare seem to be switched around.) + $(LI $(BUGZILLA 1644): Template instantiation should automatically cast to const to make const-ness irrelevant when argument is const anyways) + $(LI $(BUGZILLA 2216): bad code generation for static arrays of zero length static arrays) + $(LI $(BUGZILLA 2223): Typo in error message) + $(LI $(BUGZILLA 2231): missing bigint document) + $(LI $(BUGZILLA 2242): linux system calls are canceled by GC) + $(LI $(BUGZILLA 2247): bad header file generated for if (auto o = ...) {}) + $(LI $(BUGZILLA 2248): .di should be a supported file extension) + $(LI $(BUGZILLA 2250): Update of user32.lib and kernel32.lib) + $(LI $(BUGZILLA 2254): Size of executable almost triples) + $(LI $(BUGZILLA 2258): Docs -> Inline Assembler -> Operand Types -> qword missing) + $(LI $(BUGZILLA 2259): Assertion failure: '0' on line 122 in file 'statement.c') + $(LI $(BUGZILLA 2266): opEquals documentation still says it returns int) + $(LI $(BUGZILLA 2269): D BUG: cosine of complex) + $(LI $(BUGZILLA 2272): synchronized attribute documentation) + $(LI $(BUGZILLA 2273): Whitespace is not inserted after commas) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.018 + TITLE=Change Log: $(VER) diff --git a/changelog/2.019.dd b/changelog/2.019.dd new file mode 100644 index 0000000000..78b1a10003 --- /dev/null +++ b/changelog/2.019.dd @@ -0,0 +1,42 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 2, 2008, =================================================, + + $(WHATSNEW + $(LI Added $(LINK2 $(ROOT_DIR)spec/struct.html#Struct-Constructor, struct + constructors).) + $(LI Special member functions _ctor, _dtor, etc., now have two + leading _ in order to not conflict with the user identifier space.) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 1322): foreach bypasses invariant) + $(LI $(BUGZILLA 1615): inout is allowed in foreach of string literal) + $(LI $(BUGZILLA 1627): ICE with a method called _ctor) + $(LI $(BUGZILLA 1633): Nonsensical "C style cast illegal" message with !is) + $(LI $(BUGZILLA 1771): dmd fails to execute on linux) + $(LI $(BUGZILLA 1773): excessively long integer literal) + $(LI $(BUGZILLA 1785): Mixing in an incorrect array literal causes infinite loop.) + $(LI $(BUGZILLA 2176): Assertion failure: 'sz == es2->sz' on line 1339 in file 'constfold.c' (concatenating strings of different types)) + $(LI $(BUGZILLA 2183): Bad formatting in std.c.stdlib) + $(LI $(BUGZILLA 2190): toHash documentation is deprecated [D2.0]) + $(LI $(BUGZILLA 2232): DMD generates invalid code when an object file is compiled -inline) + $(LI $(BUGZILLA 2241): DMD abort) + $(LI $(BUGZILLA 2243): const bool = is(function literal), badly miscast) + $(LI $(BUGZILLA 2262): -inline breaks -lib library) + $(LI $(BUGZILLA 2286): movmskpd compiled incorrectly) + $(LI $(BUGZILLA 2287): std.conv should accept structs defining toString) + $(LI $(BUGZILLA 2289): Stack overflow on very large BigInt to string.) + $(LI $(BUGZILLA 2308): CTFE crash on foreach over nonexistent variable) + $(LI $(BUGZILLA 2311): Static destructors in templates are never run) + $(LI $(BUGZILLA 2314): Crash on anonymous class variable instantiation) + $(LI $(BUGZILLA 2316): std.file docs are out of date) + $(LI $(BUGZILLA 2317): asm offsetof generates: Internal error: ../ztc/cod3.c 2651) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.019 + TITLE=Change Log: $(VER) diff --git a/changelog/2.020.dd b/changelog/2.020.dd new file mode 100644 index 0000000000..795fd4f663 --- /dev/null +++ b/changelog/2.020.dd @@ -0,0 +1,73 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 20, 2008, =================================================, + + $(WHATSNEW + $(LI Improved performance of AAs by rebalancing trees when rehashing.) + $(LI $(D_KEYWORD immutable) now is implemented.) + $(LI $(BUGZILLA 2344): Two wrong lookups for array functions) + $(LI $(BUGZILLA 2345): Return by + $(LINK2 $(ROOT_DIR)spec/function.html#ref-functions, reference) should be + allowed) + $(LI $(CODE Posix) is now a predefined identifier when compiling under Linux) + $(LI Based on Sean Kelly's hard work, Phobos has been split into + two libraries, druntime.lib and phobos.lib. This will enable + better integration with Tango. + The user source code changes are: + $(TABLE + $(TR $(TH from) $(TH to)) + $(TRENAME bit, bool) + $(TRENAME _d_OutOfMemory(), onOutOfMemoryError()) + $(TRENAME import std.asserterror;, import core.exception;) + $(TRENAME import std.hiddenfunc;, import core.exception;) + $(TRENAME import std.switcherr;, import core.exception;) + $(TRENAME import std.array;, import core.exception;) + $(TRENAME import std.outofmemory;, import core.exception;) + $(TRENAME import std.gc;, import core.memory;) + $(TRENAME import std.thread;, import core.thread;) + $(TRENAME SwitchError, SwitchException) + $(TRENAME AssertError, AssertException) + $(TRENAME HiddenFuncError, HiddenFuncException) + $(TRENAME ArrayBoundsError, ArrayBoundsException) + $(TRENAME std.gc.fullCollect(), GC.collect()) + $(TRENAME std.gc.\*(), memory.gc_\*()) + $(TRENAME _moduleUnitTests(), import runtime; runModuleUnitTests()) + $(TR $(TD $(CODE printf)) $(TD add $(CODE import std.c.stdio;))) + ) + Changes to thread: + $(UL + $(LI The thread handle isn't exposed to the user. This can always be obtained using the appropriate OS calls from within the thread.) + $(LI There is no druntime equivalent for Thread.pause() and Thread.resume(). The closest is thread_suspendAll() and thread_resumeAll()--extern (C) calls meant for use by the GC.) + $(LI Thread.wait() is renamed to Thread.join().) + $(LI Sleep functionality is available as Thread.sleep(double), where the parameter represents the number of seconds to sleep (fractional values accepted, obviously).) + ) + This is a big change, and expect some problems for a release or two + with this. + ) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 1229): Linker fills disk) + $(LI $(BUGZILLA 2332): Initializing const or invariant hashes croaks) + $(LI $(BUGZILLA 2333): Hash initializer does not work) + $(LI $(BUGZILLA 2336): link to nonexistent std_array.html) + $(LI $(BUGZILLA 2340): Template properties don't work) + $(LI $(BUGZILLA 2341): Double destruction without intervening copy) + $(LI $(BUGZILLA 2362): Confusing description of 'aliasing of invariant with mutable'?) + $(LI $(BUGZILLA 2363): Spurious () required after function name when used with array in prefix form) + $(LI $(BUGZILLA 2366): Const member function syntax is missing) + $(LI $(BUGZILLA 2368): Calling a function with an address of another function, then calling a returned object is rejected) + $(LI $(BUGZILLA 2373): freebsd select does not accept values > 999,999) + $(LI $(BUGZILLA 2376): CTFE fails on array literal of array literals of chars) + $(LI $(BUGZILLA 2380): static struct initializer accepted as non static initializer is not documented) + $(LI $(BUGZILLA 2383): default arguments can implicitly access private global variables that are not visible at call site) + $(LI $(BUGZILLA 2385): spec says all structs are returned via hidden pointer on linux, but it uses registers) + $(LI $(BUGZILLA 2390): Missing warning on conversion from int to char) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.020 + TITLE=Change Log: $(VER) diff --git a/changelog/2.021.dd b/changelog/2.021.dd new file mode 100644 index 0000000000..7427cbec96 --- /dev/null +++ b/changelog/2.021.dd @@ -0,0 +1,67 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Nov 25, 2008, =================================================, + + $(WHATSNEW + $(LI Added $(B -safe) switch and $(CODE module(system) Identifier;) syntax.) + $(LI Added range support to foreach statement.) + $(LI $(B scope) parameter storage class means the parameter will + not 'escape' the scope of the function invocation. + Using this for delegate parameters will prevent some closure allocations + by the calling function.) + $(LI The $(B lazy) storage class now implies $(B scope) so that lazy + arguments won't trigger a heap allocated closure.) + $(LI The 'this' parameter to struct member functions is now a + reference type, rather than a pointer. + $(RED This breaks existing code.) + ) + + $(LI More changes to druntime: + $(TABLE + $(TR $(TH from) $(TH to)) + $(TRENAME OutOfMemoryException, OutOfMemoryError) + $(TRENAME SwitchException, SwitchError) + $(TRENAME HiddenFuncException, HiddenFuncError) + $(TRENAME ArrayBoundsException, RangeError) + $(TRENAME AssertException, AssertError) + $(TRENAME FinalizeException, FinalizeError) + $(TRENAME onArrayBoundsError, onRangeError) + $(TRENAME stdc.\*, core.stdc.\*) + $(TRENAME sys.\*, core.sys.\*) + + + ) + ) + + $(LI Added core.runtime.loadLibrary() as an experimental feature for + loading dynamic libraries (Win32 only at the moment).) + $(LI Added core.runtime.unloadLibrary() as an experimental feature for + unloading dynamic libraries previously loaded by loadLibrary().) + $(LI core.thread.sleep() accepts a long integer specifying the sleep interval + in 100 nanosecond intervals (the previous release notes said this was a + float, IIRC).) + $(LI It is no longer necessary to link in druntime separately, it is + inserted into libphobos2.a.) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 313): Fully qualified names bypass private imports) + $(LI $(BUGZILLA 920): SPEC: Auto classes referenced where scope should be used) + $(LI $(BUGZILLA 929): Resizing array of associative arrays (uint[char[]][]) causes infinite loop / hang) + $(LI $(BUGZILLA 1372): Compiler accepts pragma(msg,)) + $(LI $(BUGZILLA 1610): Enum.stringof is int, not the name of the enum) + $(LI $(BUGZILLA 1663): pragma(lib, "") don't work on linux) + $(LI $(BUGZILLA 1797): Documentation comments - ///) + $(LI $(BUGZILLA 2428): Accessing item in enum'd array produced compiler error) + $(LI $(BUGZILLA 2429): std.stream.File incorrect flag parsing and sharing mode) + $(LI $(BUGZILLA 2431): Internal error: ../ztc/cgcod.c 1031 when using -O) + $(LI $(BUGZILLA 2470): Cannot build libraries from other libraries) + $(LI unittest functions now always use D linkage) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.021 + TITLE=Change Log: $(VER) diff --git a/changelog/2.022.dd b/changelog/2.022.dd new file mode 100644 index 0000000000..f3d39c60e2 --- /dev/null +++ b/changelog/2.022.dd @@ -0,0 +1,41 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Dec 11, 2008, =================================================, + + $(WHATSNEW + $(LI Changed IUnknown to use the extern(System) interface rather + that extern(Windows).) + $(LI Pure functions now get semantically checked.) + $(LI Nothrow functions now get semantically checked.) + $(LI $(D shared) is now a type constructor.) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 1518): Crash using 'scope', 'with' and undefined 'RegExp') + $(LI $(BUGZILLA 1649): Variant coercion fails with delegates) + $(LI $(BUGZILLA 1685): Array index is evaluated twice) + $(LI $(BUGZILLA 1933): Delimited string constants can cause segfault) + $(LI $(BUGZILLA 1963): -H creates broken headers) + $(LI $(BUGZILLA 2041): Spec implies relationship between interfaces and COM objects) + $(LI $(BUGZILLA 2105): added patch) + $(LI $(BUGZILLA 2441): header file generation translates enum to manifest) + $(LI $(BUGZILLA 2468): result type of AndAndExp and OrOrExp deduced incorrectly) + $(LI $(BUGZILLA 2489): import in struct causes assertion failure) + $(LI $(BUGZILLA 2490): extern(C++) can not handle structs as return types) + $(LI $(BUGZILLA 2491): druntime GC wrongly frees data pointed to by TLS.) + $(LI $(BUGZILLA 2492): ICE building on Linux with -lib option) + $(LI $(BUGZILLA 2499): Template alias default value cannot be template instantiation) + $(LI $(BUGZILLA 2500): template struct methods are left unresolved if imported from multiple modules) + $(LI $(BUGZILLA 2501): member function marked as final override ignores override requirements) + $(LI $(BUGZILLA 2503): Error 42: Symbol Undefined _D3std7process6systemFAyaZi) + $(LI $(BUGZILLA 2506): Can't initialize const member in ctor if it is accessed via this.member syntax) + $(LI Incorporated some of the patches from $(BUGZILLA 1752)) + $(LI $(D extern __thread) now works on Linux.) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.022 + TITLE=Change Log: $(VER) diff --git a/changelog/2.023.dd b/changelog/2.023.dd new file mode 100644 index 0000000000..57f7754f45 --- /dev/null +++ b/changelog/2.023.dd @@ -0,0 +1,38 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 2, 2009, =================================================, + + $(WHATSNEW + $(LI Improved speed of long division.) + $(LI Optimizer now takes advantage of immutable and pure.) + $(LI Added predefined + $(LINK2 $(ROOT_DIR)spec/version.html#PredefinedVersions, version) + $(B D_Ddoc) which is predefined when $(B -D) switch is thrown.) + $(LI the type of a string literal is now $(CODE invariant(char)[]) + rather than $(CODE invariant(char)[length_of_string]). It is still + implicitly convertible to the latter. This is intended to reduce + template instantiation bloat.) + $(LI Undid fix for $(BUGZILLA 2500), as the fix was arguably worse + than the bug.) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 1078): Frontend uses of 'auto' where 'scope' should be used) + $(LI $(BUGZILLA 2517): DDoc omits abstract on classes) + $(LI $(BUGZILLA 2518): scope(success) not execuate and RAII variable destructor is not called) + $(LI $(BUGZILLA 2519): Segfault when >> used in an invalid slice) + $(LI $(BUGZILLA 2527): Alias Template Params Are Always Same Type As First Instantiation (according to typeof(x).stringof)) + $(LI $(BUGZILLA 2531): DDoc not generated correctly for struct methods inside static if) + $(LI $(BUGZILLA 2533): compiler falls with "assertion failed" message on wrong code) + $(LI $(BUGZILLA 2534): dmd.conf is wrong) + $(LI $(BUGZILLA 2537): compiler crashes on this code:) + $(LI $(BUGZILLA 2541): cannot use aliased type for decl of foreach variable) + $(LI $(BUGZILLA 2542): array casts behave differently at compile and runtime) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.023 + TITLE=Change Log: $(VER) diff --git a/changelog/2.025.dd b/changelog/2.025.dd new file mode 100644 index 0000000000..9353af0730 --- /dev/null +++ b/changelog/2.025.dd @@ -0,0 +1,23 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 14, 2009, =================================================, + + $(WHATSNEW + $(LI Added Mac OSX support.) + $(LI Separated bin and lib directories into windows, linux, + and osx.) + $(LI No longer need to download dmc to use the windows version.) + $(LI Use version(OSX) for Mac OSX. Although version(darwin) is + also supported for the time being, it is deprecated.) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 2448): template return by reference causes seg fault) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.025 + TITLE=Change Log: $(VER) diff --git a/changelog/2.026.dd b/changelog/2.026.dd new file mode 100644 index 0000000000..b121f76ccb --- /dev/null +++ b/changelog/2.026.dd @@ -0,0 +1,49 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 3, 2009, =================================================, + + $(WHATSNEW + $(LI Escape string literals deprecated, see $(BUGZILLA 2658)) + $(LI Tripled speed of exp, expm1, and exp2. std.math is now less dependent on the C standard library.) + $(LI Added $(LINK2 $(ROOT_DIR)spec/struct.html#nested, nested structs).) + $(LI Added buildable dmd source.) + $(LI Many changes to std.math for speed, accuracy, and Tango compatibility: + $(UL + $(LI Improved accuracy of exp, expm1, exp2, sinh, cosh, tanh on Mac OSX, + and tripled speed on all platforms.) + $(LI Now using IEEE754-2008 camelCase names for isNaN, isFinite, + isNormal, isSubnormal, isInfinity. Aliases for the old names have been retained.) + $(LI The non-functional nan(char[]) is replaced with NaN, getNaNpayload.) + ) + ) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 1603): String literals bind to pointer types) + $(LI $(BUGZILLA 1629): Link error: Previous Definition Different: blablah__initZ) + $(LI $(BUGZILLA 1662): Falls back to libphobos if -debuglib isn't used when -g is) + $(LI $(BUGZILLA 1681): cast(real) ulong.max == 0) + $(LI $(BUGZILLA 2416): Slice of typedef'ed array should preserve the typedef'ed type) + $(LI $(BUGZILLA 2597): auto return doesn't work for a variety of cases) + $(LI $(BUGZILLA 2612): immutable not accepted wherever invariant is) + $(LI $(BUGZILLA 2619): Locally-instantiated structs are not instantiated locally) + $(LI $(BUGZILLA 2621): ref binds to rvalues of user-defined types) + $(LI $(BUGZILLA 2622): ref returns not allowed in complex template) + $(LI $(BUGZILLA 2623): Function type drops ref spec) + $(LI $(BUGZILLA 2670): std.file.read() should read files of 0 length) + $(LI $(BUGZILLA 2673): Static constructors sometimes do not run when compiling with -lib) + $(LI $(BUGZILLA 2675): cannot foreach structs with copy constructor) + $(LI $(BUGZILLA 2676): alias parameters not matched in concept if clause) + $(LI $(BUGZILLA 2677): Alias type parameters not visible in concept-if clauses) + $(LI $(BUGZILLA 2678): for loops are already assumed to terminate) + $(LI $(BUGZILLA 2679): Spurious "warning - " messages and erratic behaviour with is(typeof({void function}()))) + $(LI $(BUGZILLA 2684): Associative arrays have wrong opIndex signatures) + $(LI $(BUGZILLA 2690): DMD aborts with MALLOC_CHECK_ set) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.026 + TITLE=Change Log: $(VER) diff --git a/changelog/2.027.dd b/changelog/2.027.dd new file mode 100644 index 0000000000..3b397581d4 --- /dev/null +++ b/changelog/2.027.dd @@ -0,0 +1,68 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 31, 2009, =================================================, + + $(WHATSNEW + $(LI Most functions in std.math are now pure nothrow. Improved speed of std.math.hypot.) + $(LI Added response files for Linux and OSX) + $(LI Added $(LINK2 $(ROOT_DIR)spec/class.html#AliasThis, $(B alias this))) + $(LI $(BUGZILLA 2746): Make float.init signalling NaN by default) + $(LI On Windows, if there are multiple source files on the command + line they are now read with a background thread. This may speed up + compilation.) + $(LI Folded in patches for LDC compatibility from Tomas Lindquist Olsen) + $(LI Removed $(B etc.gamma) from the library.) + ) + $(BUGSFIXED + $(LI std.math.hypot is wrong for subnormal arguments) + $(LI Fix bug where / wasn't recognized as a path separator on Windows.) + $(LI $(BUGZILLA 920): Fix one more out of date reference to 'auto' rather than 'scope') + $(LI $(BUGZILLA 1645): can override base class' const method with non-const method) + $(LI $(BUGZILLA 2319): "Win32 Exception" not very useful) + $(LI $(BUGZILLA 2336): link to nonexistent std_array.html) + $(LI $(BUGZILLA 2570): Patch for some mistakes in Ddoc comments) + $(LI $(BUGZILLA 2574): std.c.stdio doesn't compile: va_list not defined!) + $(LI $(BUGZILLA 2591): custom allocator new argument should be size_t instead of uint) + $(LI $(BUGZILLA 2595): template ctors crash compiler) + $(LI $(BUGZILLA 2596): Variadic constructors don't compile) + $(LI $(BUGZILLA 2626): template function not working against template struct instantiated with default arguments) + $(LI $(BUGZILLA 2674): Copy postblit constructor this(this) not called for members) + $(LI $(BUGZILLA 2689): seek behaves incorrectly on MAC OSX) + $(LI $(BUGZILLA 2692): alignment of double on x86 linux is incorrect) + $(LI $(BUGZILLA 2700): typeof tests stops compilation abruptly) + $(LI $(BUGZILLA 2705): Response file size cannot exceed 64kb) + $(LI $(BUGZILLA 2711): -H produces bad headers files if function defintion is templated and have auto return value) + $(LI $(BUGZILLA 2722): ICE with variadic template parameters) + $(LI $(BUGZILLA 2723): ICE with variadic template parameters, different case) + $(LI $(BUGZILLA 2724): Persistent segfaults in templated code) + $(LI $(BUGZILLA 2725): Pattern matching in static if not working with variadic arguments) + $(LI $(BUGZILLA 2727): std.date Cyclic dependency) + $(LI $(BUGZILLA 2728): Bogus Error message on const ref return) + $(LI $(BUGZILLA 2729): hash_t undocumented and unnecessary) + $(LI $(BUGZILLA 2730): Restriction on op= can be lifted) + $(LI $(BUGZILLA 2731): Errors in associative array example) + $(LI $(BUGZILLA 2739): _argptr is invalid for functions nested in class methods) + $(LI $(BUGZILLA 2743): dumpobj gives "buss error" on Tiger) + $(LI $(BUGZILLA 2744): wrong init tocbuffer of forstatement) + $(LI $(BUGZILLA 2745): missing token tochars in lexer.c) + $(LI $(BUGZILLA 2747): improper toCBuffer of funcexp) + $(LI $(BUGZILLA 2750): Optimize slice copy with size known at compile time) + $(LI $(BUGZILLA 2751): incorrect scope storage class vardeclaration tocbuffer) + $(LI $(BUGZILLA 2752): std.xml does not encode CData correctly) + $(LI $(BUGZILLA 2754): The error message regarding implicit conversion to shared doesn't mention shared in the message.) + $(LI $(BUGZILLA 2755): ICE on invalid ref returns in linked objects: Assertion failure: 'type' on line 6566 in file 'expression.c'. No ICE or error if invalid code is local to the file.) + $(LI $(BUGZILLA 2756): Bad code generation for pure nothrow math functions) + $(LI $(BUGZILLA 2761): Unreachable statement warning in std.string) + $(LI $(BUGZILLA 2763): std.mangle.demangle not translating 'ya') + $(LI $(BUGZILLA 2766): DMD hangs with 0%cpu) + $(LI $(BUGZILLA 2767): DMD incorrectly mangles NTFS stream names) + $(LI $(BUGZILLA 2772): lib can't open response file) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.027 + TITLE=Change Log: $(VER) diff --git a/changelog/2.028.dd b/changelog/2.028.dd new file mode 100644 index 0000000000..62b4d783cb --- /dev/null +++ b/changelog/2.028.dd @@ -0,0 +1,20 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 7, 2009, =================================================, + + $(WHATSNEW + ) + $(BUGSFIXED + $(LI $(BUGZILLA 1586): DMD and GDC segfaults on incomplete code segment) + $(LI $(BUGZILLA 2064): Segfault with mixin(for/foreach) with empty loop body) + $(LI $(BUGZILLA 2812): sqrt(2.0) is about -2.7341e-53) + $(LI $(BUGZILLA 2804): Impure nested functions should be legal inside pure functions) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.028 + TITLE=Change Log: $(VER) diff --git a/changelog/2.029.dd b/changelog/2.029.dd new file mode 100644 index 0000000000..0ce916a1c4 --- /dev/null +++ b/changelog/2.029.dd @@ -0,0 +1,160 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 19, 2009, =================================================, + + $(NEWPHOBOS + $(LII std.algorithm, + $(LI Everything converted to ranges. Big disruption. Algorithms added.) + ) + $(LII std.array, + $(LI Range primitives for arrays) + $(LI Appender template) + $(LI insert, replace functions) + ) + $(LII std.bitmanip, + $(LI Bitfields of length 0 are defined to be always 0.) + $(LI The read functions for bitfields are const.) + ) + $(LII std.contracts, + $(LI enforce accepts const(char)[] instead of string) + $(LI Added enforce overload that invokes a delegate on failure) + $(LI Added assumeSorted template) + $(LI Added structuralCast that implements, well, structural casting + (incomplete).) + ) + $(LII std.conv, + $(LI Rewrote conversions with constrained templates.) + $(LI Added text() function that transforms everything into text.) + ) + $(LII std.date, + $(LI Added a benchmark function that allows for simple timing measurements.) + ) + $(LII std.file, + + $(LI read, write, append, rename, remove, getSize, getTimes, + getAttributes, isfile, isdir, chdir, mkdir, mkdirRecurse, rmdir, + listdir, copy, take filename(s) by "in char[]") + $(LI Added function readText that reads and validates a text file) + $(LI Added function slurp that reads a file into an array of tuples. + Example: +--- +auto a = slurp!(int, double)("filename", "%s, %s"); +--- + Each line in the file looks like e.g. "1, 2.3". slurp returns an array + of Tuple!(int, double) with the parsed content. + ) + ) + $(LII std.format, + + $(LI Added vector parsing and printing with the specifier "%()". For + example, writefln("[%(s; )]", [1, 2, 3][]) writes "[1; 2; 3]". This + support is experimental and may be changed in the future.) + $(LI Added a formattedRead function (i.e., scanf that doesn't suck). The + implementation is incomplete but common cases are supported.) + ) + $(LII std.functional, + $(LI Improved error messages) + $(LI Added configurable parameter names for functions as strings) + $(LI Added Adjoin template) + ) + $(LII std.getopt, + $(LI Added support for parameterless delegates) + ) + $(LII std.math, + $(LI Intrinsics std.math.yl2x and yl2xp1 added. Improves performance of + std.math.log() and similar functions (and they are now pure nothrow). ) + ) + $(LII std.mmfile, + $(LI Minor cosmetic changes) + ) + $(LII std.numeric, + + $(LI Added type CustomFloat that allows defining specialized floating-point + numbers (e.g. 16-bit floats, positive floats etc.)) + $(LI Added FPTemporary as the best type to store temporary values.) + $(LI Templatized oppositeSigns) + $(LI Added Euclidean distance) + $(LI Added dotProduct) + $(LI Added cosineSimilarity) + $(LI Added normalize) + $(LI Added string kernel functions gapWeightedSimilarity, + gapWeightedSimilarityNormalized, gapWeightedSimilarityIncremental.) + ) + $(LII std.outbuffer, + $(LI Added a few missing overloads of write()) + ) + $(LII std.path, + $(LI getDrive now works with all string types) + $(LI isabs accepts in char[]) + $(LI join accepts variadic in char[]) + $(LI fnmatch works with in char[]) + ) + $(LII std.random, + + $(LI Added RandomCover that covers a given range in a random manner) + $(LI Eliminated the old-fashioned random functions) + $(LI Defined a default random object that simplifies calls to the random + functions) + $(LI Changed generators to obey the range interface. So now you can write: +--- +Random r; +foreach (n; take(100, uniform(0, 100))) { ... } +--- + ) + ) + $(LII std.range (new file), + $(LI Range manipulation stuff.) + ) + $(LII std.regex (new file), + $(LI Regular expression library with wide char support, simplified + interface, better speed etc.) + ) + $(LII std.regexp, + $(LI Scheduled for deprecation. Use std.regex instead.) + ) + $(LII std.stdio, + $(LI Major breaking changes: introduced the File struct. Now stdin, + stdout, stderr are instances of the File struct.) + $(LI Due to bugs in the compiler, the copy constructor and destructor of + File are commented out. Walter will look into fixing the issues soon. + File should work fine, but you need to close it manually.) + $(LI A byRecord iteration mode makes it pretty easy to iterate structured + text files.) + $(LI writef and writefln now require a string as their first argument.) + ) + $(LII std.string, + $(LI strip, stripl, stripr, startsWith, endsWith now work with any string type) + ) + $(LII std.typecons, + $(LI Added constructors, assignment operator, length, toString, and slice + to Tuple.) + ) + $(LII std.utf, + $(LI toUTF16z accepts in char[]) + ) + $(LII std.variant, + $(LI Added support for Variants that contain vectors and hashes of themselves) + ) + $(LII std.c.stdio, + $(LI Added fopen64 and friends) + ) + ) + $(WHATSNEW + $(LI Added template function literals) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 675): %a format has an out-by-1 bug for denormals) + $(LI $(BUGZILLA 2199): Segfault using array operation in function call) + $(LI $(BUGZILLA 2203): typeof(class.template.foo) crashes compiler) + $(LI $(BUGZILLA 2577): DMD crashes on foreach of undefined identifier) + $(LI $(BUGZILLA 2808): 'nothrow' nested functions cannot be parsed) + $(LI $(BUGZILLA 2812): sqrt(2.0) is about -2.7341e-53) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.029 + TITLE=Change Log: $(VER) diff --git a/changelog/2.030.dd b/changelog/2.030.dd new file mode 100644 index 0000000000..7f3308e77f --- /dev/null +++ b/changelog/2.030.dd @@ -0,0 +1,67 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION May 11, 2009, =================================================, + + $(WHATSNEW + $(LI added $(B -vtls) compiler switch) + $(LI $(RED classic global storage now defaults to TLS (Thread Local Storage)). + This is a big change, see + $(LINK2 $(ROOT_DIR)migrate-to-shared.html, Migrating To Shared).) + $(LI std.algorithm: added minPos. Improvements to Splitter suggested by Brad Roberts. Splitter now is bidirectional. Also Splitter has one extra trailing element if it ends with a separator. Added variadic arguments for setUnion and setIntersection. Added functions setSymmetricDifference and largestPartialIntersection. Improved BinaryHeap's interface and implementation.) + $(LI std.array: Improvements to Appender. Now it works with string and other immutable-element arrays, and accepts ranges in put().) + $(LI std.format: added raw specifier for reading) + $(LI std.range: Added iota with two arguments. Added FrontTransversal and Transversal.) + $(LI std.stdio: added File.byChunk) + $(LI std.traits: Added isImplicitlyConvertible.) + $(LI std.tuple: Added Tuple.opComp.) + $(LI Folded in compiler changes by Unknown W. Brackets + to support Solaris.) + $(LI added .typeinfo to ClassInfo $(BUGZILLA 2836): Navigate from ClassInfo to TypeInfo) + ) + $(BUGSFIXED + $(LI Fix instruction scheduler bug on Linux) + $(LI unlisted: made std.numeric.entropy work on const/immutable arrays) + $(LI Fixed several problems associated with thread local storage) + $(LI $(BUGZILLA 642): error: mixin "static this" into where it cannot be) + $(LI $(BUGZILLA 713): circular const definitions with module operator "." cause the compiler to segfault) + $(LI $(BUGZILLA 752): Assertion failure: 'e->type->ty != Ttuple' on line 4518 in file 'mtype.c') + $(LI $(BUGZILLA 858): Forward reference to struct inside class crashes the compiler) + $(LI $(BUGZILLA 884): Segfault in recursive template) + $(LI $(BUGZILLA 934): Segfault taking mangleof a forward reference in a template.) + $(LI $(BUGZILLA 1011): illegal import declaration causes compile time segfault) + $(LI $(BUGZILLA 1054): regression: circular aliases cause segfaults) + $(LI $(BUGZILLA 1061): "asm inc [;" segfaults compiler.) + $(LI $(BUGZILLA 1305): Compiler hangs with templated opCmp returning templated class) + $(LI $(BUGZILLA 1385): Stack Overflow with huge array literal.) + $(LI $(BUGZILLA 1428): Segfault on template specialization with delegates and tuples) + $(LI $(BUGZILLA 1791): Segmentation fault with anon class in anon class and non-constant variable init) + $(LI $(BUGZILLA 1916): segfault on invalid string concat) + $(LI $(BUGZILLA 1946): Compiler crashes on attempt to implicit cast const typedef to non-const.) + $(LI $(BUGZILLA 2048): DMD crash on CTFE that involves assigning to member variables of void-initialized struct) + $(LI $(BUGZILLA 2061): wrong vtable call with multiple interface inheritance) + $(LI $(BUGZILLA 2215): Forward reference enum with base type within a struct causes Segmentation Fault in the compiler) + $(LI $(BUGZILLA 2309): Crash on a template mixing in a variadic template with an undefined template identifier) + $(LI $(BUGZILLA 2346): ICE when comparing typedef'd class) + $(LI $(BUGZILLA 2580): Documented WinMain for D2 is wrong) + $(LI $(BUGZILLA 2633): incorrect ModuleInfo declaration in object.di) + $(LI $(BUGZILLA 2695): pure functions can invoke impure function pointers) + $(LI $(BUGZILLA 2807): Marking a nested function as 'pure' may cause bad code generations silently accepted) + $(LI $(BUGZILLA 2821): struct alignment inconsistent with C for { int, long }) + $(LI $(BUGZILLA 2851): Segfault using C-style struct initializer with too few arguments) + $(LI $(BUGZILLA 2865): RandomCover not random) + $(LI $(BUGZILLA 2882): std.random.MersenneTwisterEngine without seed) + $(LI $(BUGZILLA 2890): deadlock in std.stdio) + $(LI $(BUGZILLA 2893): qualified types don't have an Unsigned counterpart) + $(LI $(BUGZILLA 2906): writef problem with formatting floating point) + $(LI $(BUGZILLA 2914): to!string(struct) is broken) + $(LI $(BUGZILLA 2920): recursive templates blow compiler stack) + $(LI $(BUGZILLA 2922): Egregiously bad hashing performance with strings) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.030 + TITLE=Change Log: $(VER) diff --git a/changelog/2.031.dd b/changelog/2.031.dd new file mode 100644 index 0000000000..5ddf8dffdb --- /dev/null +++ b/changelog/2.031.dd @@ -0,0 +1,83 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION July 6, 2009, =================================================, + + $(WHATSNEW + $(LI Renamed root directory \dmd to \dmd2) + $(LI Use of with symbols that shadow local symbols is no longer allowed) + $(LI Added $(LINK2 $(ROOT_DIR)spec/statement.html#FinalSwitchStatement, final + switch statements)) + $(LI Added $(LINK2 $(ROOT_DIR)spec/statement.html#CaseRangeStatement, case range + statements)) + $(LI Implicit integral conversions that could result in loss of significant + bits are no longer allowed.) + $(LI Warning on no return expr; is now an error.) + $(LI $(BUGZILLA 3080): dmd should output compilation errors to stderr, not stdout) + $(LI $(BUGZILLA 3122): [patch] Adding support for fast and reliable build tools to the frontend) + $(LI std.algorithm: Made std.algorithm.swap faster by having it use memcpy; added std.algorithm.group, std.algorithm.until, std.algorithm.nWayUnion, std.algorithm.largestPartialIntersectionWeighted; added additional constraints to std.algorithm.equal; changed signature of std.algorithm.topNIndex and std.algorithm.topNCopy to use an enum parameter instead of a confusing bool.) + $(LI std.array: added array function.) + $(LI std.conv: added Shin Fujishiro's code for printing and parsing enumerated values.) + $(LI std.ctype: made isupper and tolower pure.) + $(LI std.date: changed signature of benchmark to return ulong[] instead of uint[].) + $(LI std.demangle: changed it to use the snazzy switch statement with ranged labels.) + $(LI std.random: added randomSample) + $(LI std.string: deprecated std.string.find and std.string.find, replaced with std.string.indexOf; deprecated std.string.rfind and std.string.irfind, replaced with std.string.lastIndexOf; added flag CaseSensitive for indexOf and lastIndexOf; removed startsWith and endsWith because std.algorithm defines them; defined std.string.byDchar.) + $(LI std.traits: added isSomeChar, isPointer.) + $(LI std.typetuple: replaced indexOf with indexOfType, kept the old name as an alias that will be deprecated.) + $(LI std.utf: improved error messages.) + ) + $(BUGSFIXED + $(LI Fix dmd crash on multicore Windows.) + $(LI Fixed unlisted bug in std.algorithm.startsWith) + $(LI Fixed unlisted bug in std.algorithm.topN) + $(LI Fixed unlisted bug in std.algorithm.topNIndex (empty index made it crash)) + $(LI Fixed unlisted bug in std.algorithm.setIntersection) + $(LI Fixed unlisted bug in std.range.retro: retro'izing a range twice must return the original range) + $(LI $(BUGZILLA 106): template - mixin sequence) + $(LI $(BUGZILLA 810): Cannot forward reference template) + $(LI $(BUGZILLA 852): ICE(toir.c) using local class in non-static nested function in nested static function) + $(LI $(BUGZILLA 1343): Various errors with static initialization of structs and arrays) + $(LI $(BUGZILLA 1358): ICE(root.c) on Unicode codepoints greater than 0x7FFFFFFF) + $(LI $(BUGZILLA 1524): ICE(constfold.c) on using "is" with strings in CTFE) + $(LI $(BUGZILLA 1984): Assertion failure: 'e1->type' on line 1198 in file 'constfold.c') + $(LI $(BUGZILLA 2323): ICE(cgcs.c): taking address of a method of a temporary struct) + $(LI $(BUGZILLA 2399): ICE(cgcod.c) on casting function to delegate) + $(LI $(BUGZILLA 2429): std.stream.File incorrect flag parsing and sharing mode) + $(LI $(BUGZILLA 2432): complex alias -> mtype.c:125: virtual Type* Type::syntaxCopy(): Assertion `0` failed.) + $(LI $(BUGZILLA 2603): ICE(cgcs.c) on subtracting string literals) + $(LI $(BUGZILLA 2843): ICE(constfold.c) with is-expression with invalid dot-expression in is-expression involving typeid) + $(LI $(BUGZILLA 2865): RandomCover not random) + $(LI $(BUGZILLA 2875): ICE(cgcod.c) setting delegate = $(AMP)Struct.func) + $(LI $(BUGZILLA 2884): ICE: Assert: 'template.c', line 3773, 'global.errors') + $(LI $(BUGZILLA 2888): [PATCH] speedup for float * 2.0) + $(LI $(BUGZILLA 2900): Array appending slowed drastically since integration of druntime) + $(LI $(BUGZILLA 2915): [Patch]: Optimize -a*-b into a*b) + $(LI $(BUGZILLA 2923): -O generates bad code for ?:) + $(LI $(BUGZILLA 2932): bad e_ehsize (36 != 52)) + $(LI $(BUGZILLA 2952): Segfault on exit when using array ops with arrays of doubles larger than 8 elements) + $(LI $(BUGZILLA 2974): Segfault(mtype.c) on auto function) + $(LI $(BUGZILLA 2981): Bad code generation for structs containing invariants) + $(LI $(BUGZILLA 2982): Assertion failure in function if() clause) + $(LI $(BUGZILLA 3003): Need to implicitly add () on member template function calls) + $(LI $(BUGZILLA 3014): ICE(template.c) instantiating template with tuple) + $(LI $(BUGZILLA 3016): Errors in the documentation of std.math.acos) + $(LI $(BUGZILLA 3026): Segfault with incomplete static array initializer) + $(LI $(BUGZILLA 3044): Segfault(template.c) instantiating struct tuple constructor with zero arguments.) + $(LI $(BUGZILLA 3071): nested func declaration parse problem) + $(LI $(BUGZILLA 3078): NaN reported as equal to zero) + $(LI $(BUGZILLA 3081): unaryFun can't be used to get element out of struct.) + $(LI $(BUGZILLA 3095): wc example for D2 doesn't compile) + $(LI $(BUGZILLA 3114): optlink failing on multicore machines) + $(LI $(BUGZILLA 3117): dmd crash by *1) + $(LI $(BUGZILLA 3121): recurrence does not generate the correct numbers) + $(LI $(BUGZILLA 3128): Internal error: ..\ztc\cod4.c 2737) + $(LI $(BUGZILLA 3130): Crashed with triple stars) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.031 + TITLE=Change Log: $(VER) diff --git a/changelog/2.032.dd b/changelog/2.032.dd new file mode 100644 index 0000000000..290e083eed --- /dev/null +++ b/changelog/2.032.dd @@ -0,0 +1,130 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 2, 2009, =================================================, + + $(WHATSNEW + $(LI Improved exception message for assert(0) in Windows -release builds) + $(LI Added support for: +--- +a[i].var = e2 +--- + and: +--- +a[] = e +--- + in CTFE. $(I (thanks, Don!))) + $(LI Member functions can now be used in CTFE) + $(LI Operator overloading can now be used in CTFE) + $(LI Nested functions can now be used in CTFE) + $(LI CTFE error messages now explain why the function could not be + interpreted at compile time) + $(LI synchronized member functions now implicitly typed as shared.) + $(LI std.algorithm: added minPos) + $(LI std.format: added raw specifier for reading) + $(LI added File.byChunk) + $(LI std.algorithm: added more unittests and checks for user-based comparison passed to topN) + $(LI std.math: replaced std.c with core.stdc; improved approxEqual to work with ranges, not only numbers or arrays) + $(LI std.range: defined Take.popBack whenever sensible; improved iota to accept negative ranges and steps) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 601): statement.html - Formatting/markup errors in BNF) + $(LI $(BUGZILLA 1461): Local variable as template alias parameter breaks CTFE) + $(LI $(BUGZILLA 1600): Functions taking only one array cannot be called with property syntax) + $(LI $(BUGZILLA 1604): Non-final method on final struct is too restrictive (closed with "invalid" advise)) + $(LI $(BUGZILLA 1605): break in switch with goto breaks in ctfe) + $(LI $(BUGZILLA 1616): std/metastrings.d) + $(LI $(BUGZILLA 1940): Phobos buildscripts do not work on x86_64) + $(LI $(BUGZILLA 1948): CTFE fails when mutating a struct in an array) + $(LI $(BUGZILLA 1950): CTFE doesn't work correctly for structs passed by ref) + $(LI $(BUGZILLA 1969): ICE(cod1.c) using undefined operator with one const operand) + $(LI $(BUGZILLA 1972): Foreach range statement breaks CTFE) + $(LI $(BUGZILLA 2150): cannot get values from const variant) + $(LI $(BUGZILLA 2277): array ops and const arrays incompatible) + $(LI $(BUGZILLA 2398): writef("%x") for a pointer is always uppercase) + $(LI $(BUGZILLA 2560): ICE(cod4.c) on invoking method that takes ref const struct parameter) + $(LI $(BUGZILLA 2564): CTFE: the index in a tuple foreach is uninitialized (bogus error)) + $(LI $(BUGZILLA 2569): static arrays in CTFE functions don't compile) + $(LI $(BUGZILLA 2575): gdb can not show code) + $(LI $(BUGZILLA 2587): std.process.shell doesn't work for win32) + $(LI $(BUGZILLA 2604): DW_TAG_module and GDB) + $(LI $(BUGZILLA 2665): ICE(cod4.c) on certain const struct function return types) + $(LI $(BUGZILLA 2784): Interfaces should be able to require type definitions (closed with "invalid" advise)) + $(LI $(BUGZILLA 2785): Interfaces should be able to require non-member functions (closed with "invalid" advise)) + $(LI $(BUGZILLA 2786): Interfaces should be able to require constructors (closed with "invalid" advise)) + $(LI $(BUGZILLA 2882): std.random.MersenneTwisterEngine without no seed) + $(LI $(BUGZILLA 2925): Destructor not called) + $(LI $(BUGZILLA 2937): postblit not called for foreach arg over array of structs) + $(LI $(BUGZILLA 2940): null is null cannot be evaluated at compile time) + $(LI $(BUGZILLA 2976): rename retreatN to retreat) + $(LI $(BUGZILLA 2979): Xml tags with only attributes return as without attributes ElementParser.parse) + $(LI $(BUGZILLA 2980): compiler error when writefln( uint )) + $(LI $(BUGZILLA 2987): D2 phobos BigInt opMul doesn't work correctly) + $(LI $(BUGZILLA 2988): Chain needs opIndexAssign.) + $(LI $(BUGZILLA 2989): std.typetuple: add support for any static tuples) + $(LI $(BUGZILLA 2992): (closed with "later" advise)) + $(LI $(BUGZILLA 2996): std.typetuple: add support for any static tuples) + $(LI $(BUGZILLA 3000): iota should work with floats) + $(LI $(BUGZILLA 3017): doc errors in std.range (on behalf of Steven Schveighoffer)) + $(LI $(BUGZILLA 3025): uniform(float,float) pops first, uniform(int,int) pops last) + $(LI $(BUGZILLA 3037): Off-by-one error in Stride.length) + $(LI $(BUGZILLA 3039): -vtls compiler flag not listed in man file) + $(LI $(BUGZILLA 3058): [CTFE] Cannot return out of foreach range statement) + $(LI $(BUGZILLA 3074): std.conv.to!(string)(int.min)) + $(LI $(BUGZILLA 3077): 3077 crash exiting main() without result code) + $(LI $(BUGZILLA 3087): std.range.retro.opIndex out of range) + $(LI $(BUGZILLA 3098): std.algorithm.reduce example can not compile) + $(LI $(BUGZILLA 3100): ICE(cast.c) struct with members is shared) + $(LI $(BUGZILLA 3132): std.string.split should be templated on mutable/const/immutable) + $(LI $(BUGZILLA 3148): syntax error using invariant) + $(LI $(BUGZILLA 3153): win32.mak tries to copy phobos.lib, gcstub.obj to nonexistent folder lib) + $(LI $(BUGZILLA 3162): can't fully use compile-time floats as template parameters) + $(LI $(BUGZILLA 3165): What kind of integer division does D use?) + $(LI $(BUGZILLA 3166): "positive" -> "non-negative" in modulo operator description) + $(LI $(BUGZILLA 3169): Segfault(cast.c) dividing ulong by int) + $(LI $(BUGZILLA 3170): Forward reference of nested class fails if outer class is not plain) + $(LI $(BUGZILLA 3183): Spec of align attribute needs work) + $(LI $(BUGZILLA 3184): std.algorithm.until should work like "find") + $(LI $(BUGZILLA 3185): osx is not a directory (complains cannot read std/c/osx/socket.d)) + $(LI $(BUGZILLA 3186): corrections for http://www.digitalmars.com/d/2.0/dmd-osx.html) + $(LI $(BUGZILLA 3189): `std.conv.to` : check for a custom `to` method in classes/structs) + $(LI $(BUGZILLA 3192): asm in a anonymous delegate crash the compiler) + $(LI $(BUGZILLA 3195): `std.conv` pureness (closed with "later" advise)) + $(LI $(BUGZILLA 3196): Segfault(mtype.c) after almost any error involving a delegate literal) + $(LI $(BUGZILLA 3197): Minor fixes and additions to std.traits) + $(LI $(BUGZILLA 3199): sort(chain(...)) doesn't work in some cases) + $(LI $(BUGZILLA 3205): CTFE: $ cannot be used in lvalues) + $(LI $(BUGZILLA 3212): Error message says "mutable"; should say "immutable") + $(LI $(BUGZILLA 3217): std.functional.binaryFunImpl doesn't support UDT with string functions , therefore neither does many std.algorithm functions) + $(LI $(BUGZILLA 3218): Performance of std.xml.encode must be improved) + $(LI $(BUGZILLA 3219): Inaccurate std.conv.to!(numeric)(numeric) error messages) + $(LI $(BUGZILLA 3224): std.random documentation bugs) + $(LI $(BUGZILLA 3229): No return or assert(0) at end of function) + $(LI $(BUGZILLA 3236): Postblit called but no matching destructor) + $(LI $(BUGZILLA 3239): std.conv.roundTo does not accept const/immutable/shared) + $(LI $(BUGZILLA 3240): std.numeric.findRoot only works with real) + $(LI $(BUGZILLA 3242): splitter does not handle input range made of a unique separator correctly) + $(LI $(BUGZILLA 3245): Easy bug fix available for disabled unit test code in std.encoding) + $(LI $(BUGZILLA 3246): ICE(init.c) using indexed array initializer on local array) + $(LI $(BUGZILLA 3249): sort and setIntersection on array of struct or class) + $(LI $(BUGZILLA 3253): DMD crashes on function pointer struct member initialization with function literal) + $(LI $(BUGZILLA 3255): final switch broken with -w switch) + $(LI $(BUGZILLA 3257): Spec is unclear describing string switch case labels) + $(LI $(BUGZILLA 3260): "Error: undefined identifier backend" when compiling 'write' with 'wchar') + $(LI $(BUGZILLA 3264): -O causes wrong "used before set" error when using enum.) + $(LI $(BUGZILLA 3281): ICE(cod1.c) append returned struct to array) + $(LI Fixed bug processing spaces in dmd's directory) + $(LI Fixed assert failure on line 4823 in expression.c) + $(LI Fixed OSX compile error on samples/d/dhry.d) + $(LI std.format: fixed unlisted bug in documentation) + $(LI std.random: uniform does not work when passed immutable data) + $(LI std.range: fixed unlisted bug in Take.back) + $(LI unlisted: made entropy work on const/immutable arrays) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.032 + TITLE=Change Log: $(VER) diff --git a/changelog/2.033.dd b/changelog/2.033.dd new file mode 100644 index 0000000000..5b30a9d3fb --- /dev/null +++ b/changelog/2.033.dd @@ -0,0 +1,53 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 5, 2009, =================================================, + + $(WHATSNEW + $(LI Phobos is now using the Boost 1.0 license) + $(LI Compiler now detects some cases of illegal null dereferencing when compiled with -O) + $(LI The result type of the $(CODE typeid($(I type))) is now the most derived TypeInfo class, rather than the TypeInfo base class) + $(LI $(BUGZILLA 2905): Faster +-*/ involving a floating-pointing literal) + $(LI Improved performance of int-to-string conversion) + ) + $(BUGSFIXED + $(LI gdb stack trace should work now) + $(LI $(BUGZILLA 302): in/out contract inheritance yet to be implemented) + $(LI $(BUGZILLA 718): ICE(cgcod.c) with int /= cast(creal)) + $(LI $(BUGZILLA 814): lazy argument + variadic arguments = segfault) + $(LI $(BUGZILLA 1168): Passing a .stringof of an expression as a template value parameter results in the string of the type) + $(LI $(BUGZILLA 1253): array initializers as expressions are not allowed in const arrays) + $(LI $(BUGZILLA 1571): Segfault(class.c) const on function parameters not carried through to .di file) + $(LI $(BUGZILLA 1731): forward reference of function type alias resets calling convention) + $(LI $(BUGZILLA 2202): Error getting type of non-static member of a class) + $(LI $(BUGZILLA 2469): ICE(cod1.c) arbitrary struct accepted as struct initializer) + $(LI $(BUGZILLA 2697): Cast of float function return to ulong or uint gives bogus value) + $(LI $(BUGZILLA 2702): Struct initialisation silently inserts deadly casts) + $(LI $(BUGZILLA 2839): ICE(cgcs.c) with int /= imaginary) + $(LI $(BUGZILLA 2970): std.path.join with version(Windows)) + $(LI $(BUGZILLA 2998): ICE(expression.c) with floating point enum) + $(LI $(BUGZILLA 3049): ICE(cod4.c) or segfault: Array operation on void[] array) + $(LI $(BUGZILLA 3059): Nonsensical complex op= should be illegal) + $(LI $(BUGZILLA 3132): std.string.split should be templated on mutable/const/immutable - closing again after the reopening on 2009-09-03 07:56:25 PDT) + $(LI $(BUGZILLA 3160): ICE(cgcod.c 1511-D1) or bad code-D2 returning string from void main) + $(LI $(BUGZILLA 3173): ICE(mtype.c) on wrong code (double to long to int conversion)) + $(LI $(BUGZILLA 3288): conv.d: using to with const int or long fails to compile.) + $(LI $(BUGZILLA 3300): std.string.toupper and tolower should be (const(char)[]), not string) + $(LI $(BUGZILLA 3304): Segfault using 'is' with a pointer enum.) + $(LI $(BUGZILLA 3305): Segfault(expression.c) with recursive struct template alias expressions) + $(LI $(BUGZILLA 3333): std.conv.to!(string, const int) error: cannot modify const) + $(LI $(BUGZILLA 3335): minor warning cleanups) + $(LI $(BUGZILLA 3336): ICE(glue.c) declaring AA with tuple key, only with -g) + $(LI $(BUGZILLA 3340): std.string.split(S1 s, S2 delim) still doesn't work for char[]) + $(LI $(BUGZILLA 3353): storage class of a member function is propagated to default arguments) + $(LI (unlisted): std.algorithm: bug in reduce when passed const arguments) + $(LI (unlisted): std.stdio: fixed documentation example) + $(LI (unlisted): std.utf: fixed decodeFront and decodeBack) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.033 + TITLE=Change Log: $(VER) diff --git a/changelog/2.034.dd b/changelog/2.034.dd new file mode 100644 index 0000000000..bb68c0147b --- /dev/null +++ b/changelog/2.034.dd @@ -0,0 +1,38 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 11, 2009, =================================================, + + $(WHATSNEW + ) + $(BUGSFIXED + $(LI $(BUGZILLA 258): Undefined identifier error for circular import) + $(LI $(BUGZILLA 1140): ICE(cod1.c) casting last function parameter to 8 byte value) + $(LI $(BUGZILLA 1592): dmd fail to resolve class symbol when i put files in a package) + $(LI $(BUGZILLA 2687): ICE(statement.c): tuple foreach in an erroneous template.) + $(LI $(BUGZILLA 2773): ICE(go.c) array assignment through a pointer, only with -O.) + $(LI $(BUGZILLA 2829): ICE(expression.c) static array block-initialized in struct literal) + $(LI $(BUGZILLA 3006): ICE(e2ir.c, tocsym.c) template module using array operation) + $(LI $(BUGZILLA 3041): Array slices can be compared to their element type: bad codegen or ICE) + $(LI $(BUGZILLA 3042): Segfault on incorrect override) + $(LI $(BUGZILLA 3101): Stack overflow: declaring aggregate member twice with static if) + $(LI $(BUGZILLA 3119): Segfault(expression.c) template function overloads with function with same name in other module) + $(LI $(BUGZILLA 3174): ICE(mtype.c): Compiler crash or compiler error with auto returns and const / immutable / invarient / pure) + $(LI $(BUGZILLA 3176): Compiler hangs on poorly formed mixin in variadic template) + $(LI $(BUGZILLA 3261): compiler crash with mixin and forward reference) + $(LI $(BUGZILLA 3286): Default parameter prevents to resolve inter-module circular dependency) + $(LI $(BUGZILLA 3301): Undefined identifier error dependent on order of imports when a circular import is involved) + $(LI $(BUGZILLA 3325): ICE(func.c) function literal with post-contract) + $(LI $(BUGZILLA 3343): Crash by "auto main(){}") + $(LI $(BUGZILLA 3344): ICE(e2ir.c) returning an invalid function from main()) + $(LI $(BUGZILLA 3357): ICE(cod1.c) using 'in' with a static char array as AA key) + $(LI $(BUGZILLA 3366): Segfault(declaration.c) variadic template with unmatched constraint) + $(LI $(BUGZILLA 3374): [tdpl] ICE(init.c): Associative array type not inferred) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.034 + TITLE=Change Log: $(VER) diff --git a/changelog/2.035.dd b/changelog/2.035.dd new file mode 100644 index 0000000000..6a3b952d17 --- /dev/null +++ b/changelog/2.035.dd @@ -0,0 +1,26 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 14, 2009, =================================================, + + $(WHATSNEW + $(LI Use $(B -X) to generate JSON files.) + ) + $(BUGSFIXED + $(LI Fold in patch from $(BUGZILLA 1170)) + $(LI $(BUGZILLA 1534): Can't mix in a case statement.) + $(LI $(BUGZILLA 2423): Erroneous unreachable statement warning) + $(LI $(BUGZILLA 2826): failed assignment gives wrong line number) + $(LI $(BUGZILLA 3190): enum doesn't work as the increment in a for loop) + $(LI $(BUGZILLA 3316): Functions nested in a pure templated function cannot reference its local variables) + $(LI $(BUGZILLA 3352): RangeError in std.conv) + $(LI $(BUGZILLA 3385): `std.string.split` requires a mutable array) + $(LI $(BUGZILLA 3392): a cast of this to void in tango.core.Thread is not allowed) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.035 + TITLE=Change Log: $(VER) diff --git a/changelog/2.036.dd b/changelog/2.036.dd new file mode 100644 index 0000000000..772746342a --- /dev/null +++ b/changelog/2.036.dd @@ -0,0 +1,57 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Nov 5, 2009, =================================================, + + $(WHATSNEW + $(LI Static arrays are now passed by value to functions rather than by reference) + $(LI std.algorithm: Add hasLength requirement to topN; + implemented topN for two non-adjacent ranges; added replaceTop + function to BinaryHeap; changed BinaryHeap.top to return ref.) + $(LI std.ctype: Add pure to isalnum, isalpha, iscntrl, isdigit, + islower, ispunct, isspace, isxdigit, isgraph, isprint, isascii, + toupper.) + $(LI std.date: Implementation change and unittest for isLeapYear and + daysInYear. Made both pure as well.) + $(LI std.encoding: Added function count().) + $(LI std.md5: Added explicit pass-by-ref for fixed-size buffers.) + $(LI std.numeric: Added gcd.) + $(LI std.random: Added static checks for the parameters of the linear + congruential generator.) + $(LI std.range: Reinstated some unittests; fixed Cycle to work with + the new fixed-size arrays.) + $(LI std.typecons: Added alias 'expand' for Tuple.field.) + $(LI std:utf: Added count function and changed the encode function + to take fixed-size array by reference.) + $(LI $(BUGZILLA 3446): Rename float.min to float.min_normal) + ) + $(BUGSFIXED + $(LI std.range: Fixed unlisted bug in Transposed.) + $(LI Problem with complicated array op expressions) + $(LI $(BUGZILLA 195): DDoc generates bad output when example contains "protected" attribute) + $(LI $(BUGZILLA 424): Unexpected OPTLINK Termination at EIP=0044C37B (too many fixups)) + $(LI $(BUGZILLA 1117): ddoc generates corrupted docs if code examples contain attributes with colons) + $(LI $(BUGZILLA 1812): DDOC - Unicode identifiers are not correctly marked.) + $(LI $(BUGZILLA 2694): alias pure nothrow XXX; is not pure nothrow!) + $(LI $(BUGZILLA 2862): ICE(template.c) using type tuple as function argument) + $(LI $(BUGZILLA 3035): cannot have const/invariant out parameter of type shared) + $(LI $(BUGZILLA 3102): Incorrectly matching type as shared (two cases with is expressions)) + $(LI $(BUGZILLA 3269): pure functions silently become nothrow) + $(LI $(BUGZILLA 3292): ICE(todt.c) when using a named mixin with an initializer as template alias parameter) + $(LI $(BUGZILLA 3349): typeid(shared(T)) generates wrong value) + $(LI $(BUGZILLA 3367): Regression: struct initialization no longer supports ctor overloads) + $(LI $(BUGZILLA 3397): Unintended function call to static opCall) + $(LI $(BUGZILLA 3401): Compiler crash on invariant + method overload) + $(LI $(BUGZILLA 3422): ICE(cgcod.c) Structs with default initializers bigger than register size cannot be default parameters) + $(LI $(BUGZILLA 3423): Destructor and postblit don't get copied to the header file when using -H) + $(LI $(BUGZILLA 3426): ICE(optimize.c): struct literal with cast, as function default parameter.) + $(LI $(BUGZILLA 3429): Core dump on passing template literal to member function.) + $(LI $(BUGZILLA 3432): ICE(e2ir.c): casting template expression) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.036 + TITLE=Change Log: $(VER) diff --git a/changelog/2.037.dd b/changelog/2.037.dd new file mode 100644 index 0000000000..af5006884c --- /dev/null +++ b/changelog/2.037.dd @@ -0,0 +1,62 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Dec 3, 2009, =================================================, + + $(WHATSNEW + $(LI Conditional expressions ?: can now be modifiable lvalues.) + $(LI The type inferred from an + $(LINK2 $(ROOT_DIR)spec/expression.html#ArrayLiteral, $(I ArrayLiteral)) + is now a dynamic array, not a static one.) + $(LI Added support for $(I op)= for array.length) + $(LI Array and associative array types are now determined by using ?: across + all the elements, not just using the first one.) + $(LI Array concatenation with elements now allows implicit conversion of + the elements to the array element type.) + $(LI No more comma operators allowed between [ ].) + $(LI ClassInfo now merged into TypeInfo_Class.) + $(LI $(BUGZILLA 3379): [tdpl] Parameter names not visible in the if clause of a template) + $(LI $(BUGZILLA 3380): [tdpl] typeid(obj) should return the dynamic type of the object) + $(LI Removed $(B -safe) command line switch, added $(B -noboundscheck) command + line switch.) + $(LI $(BUGZILLA 3481): PATCH: opPow(), x ^^ y as a power operator) + $(LI Added opDispatch) + $(LI properties can only have 0 or 1 arguments) + $(LI properties cannot be overloaded with non-properties) + $(LI std.math: Added FloatControl, IeeeFlags for enabling floating-point exceptions.) + $(LI std.math: Inverse trig functions are now pure nothrow.) + ) + $(BUGSFIXED + $(LI std.array: Fixed unlisted bug in array().) + $(LI $(BUGZILLA 111): appending a dchar to a char[]) + $(LI $(BUGZILLA 2664): OSX standard math functions are less accurate) + $(LI $(BUGZILLA 2802): VariantN.opCmp!(T) fails when T != VariantN) + $(LI $(BUGZILLA 2967): spec does not mention that inline asm is a valid "return" statement) + $(LI $(BUGZILLA 2977): std.random.unpredictableSeed() should use thread ID somewhere) + $(LI $(BUGZILLA 3115): >>> and >>>= generate wrong code) + $(LI $(BUGZILLA 3171): % not implemented correctly for floats) + $(LI $(BUGZILLA 3311): std.range.chain shouldn't have opIndexAssign if arguments aren't mutable) + $(LI $(BUGZILLA 3375): [tdpl] Ternary operator doesn't yield an lvalue) + $(LI $(BUGZILLA 3381): [tdpl] Incorrect assessment of overriding in triangular-shaped hierarchy) + $(LI $(BUGZILLA 3388): [tdpl] contracts should allow throw expressions) + $(LI $(BUGZILLA 3390): [tdpl] out(result) contract should not be able to rebind result) + $(LI $(BUGZILLA 3407): [tdpl] Compiling with -safe -release must keep all bound checks) + $(LI $(BUGZILLA 3433): [tdpl] Comparing structs for equality is not member-by-member) + $(LI $(BUGZILLA 3469): ICE(func.c): Regression. Calling non-template function as a template, from another module) + $(LI $(BUGZILLA 3478): "no effect in expression" error on return to void) + $(LI $(BUGZILLA 3494): Segfault(mtype.c) using typeof(return) inside an auto function) + $(LI $(BUGZILLA 3495): Segfault(typinf.c) instantiating D variadic function with too few arguments) + $(LI $(BUGZILLA 3496): ICE(cgelem.c, optimizer bug) cast(void *)(x&1)== null.) + $(LI $(BUGZILLA 3502): Fix for dropped Mac OS X 10.5) + $(LI $(BUGZILLA 3521): Optimized code access popped register) + $(LI $(BUGZILLA 3540): Another DWARF line number fix) + $(LI $(BUGZILLA 3551): nested struct => dmd adds a hidden pointer) + $(LI $(BUGZILLA 3553): ICE when a function argument defaults to __LINE__) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.037 + TITLE=Change Log: $(VER) diff --git a/changelog/2.038.dd b/changelog/2.038.dd new file mode 100644 index 0000000000..212378164c --- /dev/null +++ b/changelog/2.038.dd @@ -0,0 +1,63 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Dec 30, 2009, =================================================, + + $(WHATSNEW + $(LI Added core.cpuid in Druntime) + $(LI $(BUGZILLA 3514): opApply should be the first-choice foreach iteration method.) + $(LI $(BUGZILLA 3577): Wrong precedence for opPow) + $(LI Added $(LINK2 $(ROOT_DIR)spec/function.html#auto-ref-functions, auto ref + functions)) + $(LI Added $(LINK2 $(ROOT_DIR)spec/template.html#auto-ref-parameters, function + template auto ref parameters)) + $(LI Added $(B isRef), $(B isOut) and $(B isLazy) to + $(LINK2 $(ROOT_DIR)spec/traits.html, $(D_KEYWORD __traits))) + $(LI Transporting return type from args to return type, see $(LINK2 http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP2, DIP2)) + ) + $(BUGSFIXED + $(LI $(CPPBUGZILLA 45): Internal error: cgcod 1594) + $(LI $(CPPBUGZILLA 46): Constant folding with long doubles) + $(LI $(BUGZILLA 282): Bizarre circular import nested name invisibility issue) + $(LI $(BUGZILLA 390): Cannot forward reference enum nested in struct) + $(LI $(BUGZILLA 400): forward reference error; no propety X for type Y (struct within struct)) + $(LI $(BUGZILLA 1160): enums can not be forward referenced) + $(LI $(BUGZILLA 1564): Forward reference error for enum in circular import) + $(LI $(BUGZILLA 2029): Typesafe variadic functions don't work in CTFE) + $(LI $(BUGZILLA 2816): Sudden-death static assert is not very useful) + $(LI $(BUGZILLA 3270): pure functions returning struct) + $(LI $(BUGZILLA 3443): Thread.thread_needLock() should be nothrow) + $(LI $(BUGZILLA 3455): Some Unicode characters not allowed in identifiers) + $(LI $(BUGZILLA 3458): int fsync(int) commented out in core.sys.posix.unistd) + $(LI $(BUGZILLA 3476): C-style initializer for structs must be disallowed for structs with a constructor) + $(LI $(BUGZILLA 3575): CTFE: member structs not initialized correctly) + $(LI $(BUGZILLA 3583): Unsigned right shift works the same as signed right shift.) + $(LI $(BUGZILLA 3584): DeclDef rule is missing entries) + $(LI $(BUGZILLA 3585): Duplicate clauses in EqualExpression and RelExpression rules) + $(LI $(BUGZILLA 3587): Aggregate rule references undefined Tuple) + $(LI $(BUGZILLA 3588): WithStatement rule references unspecified Symbol) + $(LI $(BUGZILLA 3589): BaseClassList and InterfaceClasses rules are incorrect, missing ',') + $(LI $(BUGZILLA 3590): FunctionParameterList rule is missing) + $(LI $(BUGZILLA 3591): TemplateIdentifier rule is misspelled) + $(LI $(BUGZILLA 3592): ClassTemplateDeclaration and FunctionTemplateDeclaration rules are unreferenced) + $(LI $(BUGZILLA 3593): IntegerExpression rule unspecified) + $(LI $(BUGZILLA 3594): AsmPrimaryExp rule references unspecified rules) + $(LI $(BUGZILLA 3595): Several rules are missing ':' after rule name) + $(LI $(BUGZILLA 3596): Need alias for using std.algorithm.remove) + $(LI $(BUGZILLA 3601): Debug and Release builds of DMD produce different object files) + $(LI $(BUGZILLA 3611): Enum forward referencing regression) + $(LI $(BUGZILLA 3612): ExpressionList is undefined) + $(LI $(BUGZILLA 3617): CTFE: wrong code for if(x) where x is int or smaller) + $(LI $(BUGZILLA 3621): implicit conversion to const rules need tightening) + $(LI $(BUGZILLA 3633): Optimizer causes access violation) + $(LI $(BUGZILLA 3641): alias shared T U does not work) + $(LI $(BUGZILLA 3645): manifest constant (enum) crashes dmd) + $(LI $(BUGZILLA 3647): non-function opDispatch crashes dmd) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.038 + TITLE=Change Log: $(VER) diff --git a/changelog/2.039.dd b/changelog/2.039.dd new file mode 100644 index 0000000000..5e3739686e --- /dev/null +++ b/changelog/2.039.dd @@ -0,0 +1,18 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 1, 2010, =================================================, + + $(WHATSNEW + ) + $(BUGSFIXED + $(LI $(BUGZILLA 3663): struct forward reference regresssion) + $(LI $(BUGZILLA 3664): struct forward declaration causes enum to conflict with itself) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.039 + TITLE=Change Log: $(VER) diff --git a/changelog/2.040.dd b/changelog/2.040.dd new file mode 100644 index 0000000000..08cd8fa7e5 --- /dev/null +++ b/changelog/2.040.dd @@ -0,0 +1,55 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 29, 2010, =================================================, + + $(WHATSNEW + $(LI Clarification: function returns are not lvalues) + $(LI Added shared static constructors/destructors, regular static + constructors/destructors now deal with TLS) + $(LI Add $(B -map) command line switch) + $(LI Add $(LINK2 $(ROOT_DIR)spec/attribute.html#disable, $(B @disable)) + attribute) + $(LI Delegates and function pointers may be used in CTFE) + $(LI Delegate literals and function literals may be used in CTFE) + $(LI Lazy function parameters may now be used in CTFE) + $(LI Slicing of char[] arrays may now be used in CTFE) + $(LI added static/final function implementations to interfaces) + $(LI added $(B getOverloads), $(B identifier), and $(B isStaticFunction) traits.) + $(LI ModuleInfo changed from class to struct) + $(LI $(BUGZILLA 3556): version(CTFE)) + $(LI $(BUGZILLA 3728): getOverloads and identifier traits) + ) + $(BUGSFIXED + $(LI Added TLS support for OSX) + $(LI $(CPPBUGZILLA 47): Internal error: cg87 3316) + $(LI $(BUGZILLA 1298): CTFE: tuple foreach bugs) + $(LI $(BUGZILLA 1790): CTFE: foreach(Tuple) won't compile if Tuple contains string) + $(LI $(BUGZILLA 2101): CTFE: Please may I use mutable arrays at compile time?) + $(LI $(BUGZILLA 2066): to!(string)(int) into CTFE-compatible) + $(LI $(BUGZILLA 3488): Segfault(expression.c): enum declared with struct static initializer) + $(LI $(BUGZILLA 3535): struct constructors don't work in CTFE) + $(LI $(BUGZILLA 3552): ICE(mtype.c): declaring a variable called 'AssociativeArray' then using an AA.) + $(LI Partial fix for $(BUGZILLA 3569), stops the stack overflow) + $(LI $(BUGZILLA 3600): template instantiation with empty tuple) + $(LI $(BUGZILLA 3660): Templates and shared functions don't mix) + $(LI $(BUGZILLA 3668): foreach over typedef'd array crashes dmd) + $(LI $(BUGZILLA 3671): x^^3 gives wrong result when x is a floating-point literal) + $(LI $(BUGZILLA 3674): forward reference error with multiple overloads with same name) + $(LI $(BUGZILLA 3675): Regression: Struct literals cannot be initialized with another struct literal) + $(LI $(BUGZILLA 3687): Array operation "slice times scalar" tramples over memory) + $(LI $(BUGZILLA 3719): forward references can cause out-of-memory error) + $(LI $(BUGZILLA 3723): Regression: forward referenced enum) + $(LI $(BUGZILLA 3724): bug in Expression::arraySyntaxCopy (null pointer dereference on struct->union->struct)) + $(LI $(BUGZILLA 3726): Regression: ICE(mangle.c 81): struct forward reference with static this) + $(LI $(BUGZILLA 3727): lots of "deffering SomeStructName" messages when compiling) + $(LI $(BUGZILLA 3734): [patch] src/traits.c does not compile with gcc (Ubuntu 4.4.1-4ubuntu8) 4.4.1) + $(LI $(BUGZILLA 3740): Regression: class with fwd reference of a nested struct breaks abstract) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.040 + TITLE=Change Log: $(VER) diff --git a/changelog/2.041.dd b/changelog/2.041.dd new file mode 100644 index 0000000000..aabd57c71b --- /dev/null +++ b/changelog/2.041.dd @@ -0,0 +1,79 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 7, 2010, =================================================, + + $(WHATSNEW + $(LI __traits allMembers and and derivedMembers now return a tuple of strings + rather than an array of strings. Enclose __traits in [ ] to make array literal. + This makes it possible for foreach statements to iterate at compile time over it. + ) + $(LI Interface member functions can now have + $(LINK2 $(ROOT_DIR)spec/interface.html#InterfaceContracts, contracts).) + $(LI Added new + $(LINK2 $(ROOT_DIR)spec/operatoroverloading.html, operator overloading) regime.) + $(LI Warnings no longer halt the parsing/semantic passes, though they still return + an error status and still do not generate output files. They also no longer count + as errors when testing with "compiles" traits.) + $(LI Added $(B -wi) switch for $(BUGZILLA 2567)) + $(LI Mixin template definitions should be preceded with $(CODE mixin)) + $(LI Add + $(LINK2 $(ROOT_DIR)spec/expression.html#InExpression, $(B !in)) operator.) + $(LI Associative array contents can now be compared for equality) + $(LI Use of $(B length) inside of [ ] is now deprecated, use $(DOLLAR) instead) + $(LI Added $(B toDelegate()) to std.functional to convert function pointers to delegates.) + $(LI Implemented attributes for constructors.) + $(LI Implemented qualifiers for struct literals, like $(CODE immutable(S)(1,2,3))) + $(LI Array equality can now be done with differing array element types.) + $(LI Add simple spell checking.) + $(LI $(BUGZILLA 3378): [tdpl] ++x should be an lvalue) + $(LI string, wstring are now bidirectional (not random) ranges) + $(LI std.algorithm: defined move with one argument; levenshtein distance generalized to with all forward ranges; take now has swapped arguments) + $(LI std.array: empty for arrays is now a @property; front and back for a string and wstring automatically decodes the first/last character; popFront, popBack for string and wstring obey the UTF stride) + $(LI std.conv: changed the default array formatting from "[a, b, c]" to "a b c") + $(LI std.range: swapped order of arguments in take) + $(LI std.stdio: added readln template) + $(LI std.variant: now works with statically-sized arrays and const data) + $(LI std.traits: added isNarrowString) + $(LI The default type for [1,2,3] is now int[] rather than int[3].) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 2321): spec on inline asm can be misunderstood) + $(LI $(BUGZILLA 2463): No line number in "statement is not reachable" warning) + $(LI $(BUGZILLA 3029): Bug in array value mangling rule) + $(LI $(BUGZILLA 3306): bad function/delegate literal generated into header files) + $(LI $(BUGZILLA 3373): bad codeview debug info for long and ulong) + $(LI Posix only, $(BUGZILLA 3420): [PATCH] Allow string import of files using subdirectories) + $(LI $(BUGZILLA 3450): incorrect result for is (typeof({ ... }())) inside a struct) + $(LI $(BUGZILLA 3453): Linking order affects proper execution (Mac OSX only)) + $(LI $(BUGZILLA 3491): typeof((string[string]).init) == AssociativeArray!(string, string), doesn't implicitly convert to string[string].) + $(LI $(BUGZILLA 3500): super behaves differently with -inline) + $(LI $(BUGZILLA 3558): Optimizer bug results in false if condition being taken) + $(LI $(BUGZILLA 3582): core.stdc.ctype functions are not pure) + $(LI $(BUGZILLA 3619): Thread crash on exit) + $(LI $(BUGZILLA 3637): Array append patch to prevent stomping and to enhance thread-local append performance) + $(LI $(BUGZILLA 3644): Wrong UCHAR_MAX value in module core.stdc.limits) + $(LI $(BUGZILLA 3670): Declarator grammar rule is broken) + $(LI $(BUGZILLA 3689): Grammar does not allow const(int)) + $(LI $(BUGZILLA 3692): ICE(mtype.c) with associative arrays when std.variant is imported) + $(LI $(BUGZILLA 3695): __EOF__ token not documented) + $(LI $(BUGZILLA 3697): StructTemplateDeclaration and others missing constraint in rule) + $(LI $(BUGZILLA 3710): Typo in allMembers description?) + $(LI $(BUGZILLA 3736): corrupted struct returned by function with optimizations (-O)) + $(LI $(BUGZILLA 3737): SEG-V at expression.c:6255 from bad opDispatch) + $(LI $(BUGZILLA 3763): std.stdio.readlnImpl absurdly inefficient and overflows stack) + $(LI $(BUGZILLA 3768): reapeted quotes in ddoc.html) + $(LI $(BUGZILLA 3769): Regression: Segfault(constfold.c) array literals and case statements) + $(LI $(BUGZILLA 3775): Segfault(cast.c): casting no-parameter template function using property syntax) + $(LI $(BUGZILLA 3776): Wrong CHAR_MIN value in module core.stdc.limits) + $(LI $(BUGZILLA 3781): ICE(interpret.c): using no-argument C-style variadic function in CTFE) + $(LI $(BUGZILLA 3803): compiler segfaults) + $(LI $(BUGZILLA 3840): Jump to: section in the docs should be sorted) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.041 + TITLE=Change Log: $(VER) diff --git a/changelog/2.042.dd b/changelog/2.042.dd new file mode 100644 index 0000000000..4df4b9059b --- /dev/null +++ b/changelog/2.042.dd @@ -0,0 +1,28 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 19, 2010, =================================================, + + $(WHATSNEW + ) + $(BUGSFIXED + $(LI Add base class destruction to clear() in object.d) + $(LI $(BUGZILLA 3842): ICE(expression.c) using pointer in CTFE) + $(LI $(BUGZILLA 3885): No multithread support for Windows DLL) + $(LI $(BUGZILLA 3899): CTFE: poor error message for use of uninitialized variable) + $(LI $(BUGZILLA 3900): CTFE: Wrong return value for array.var assignment) + $(LI $(BUGZILLA 3901): PATCH: Nested struct assignment for CTFE) + $(LI $(BUGZILLA 3902): Definition of opCmp) + $(LI $(BUGZILLA 3912): pure static nested functions are not recognized as pure) + $(LI $(BUGZILLA 3914): Struct as argument that fits in register has member accessed wrong) + $(LI $(BUGZILLA 3919): ICE(expression.c, 9944): * or / with typedef ireal) + $(LI $(BUGZILLA 3920): Assertion failure: '0' on line 10018 in file 'expression.c') + $(LI $(BUGZILLA 3930): AAs horribly broken) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.042 + TITLE=Change Log: $(VER) diff --git a/changelog/2.043.dd b/changelog/2.043.dd new file mode 100644 index 0000000000..a217d2461b --- /dev/null +++ b/changelog/2.043.dd @@ -0,0 +1,42 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 6, 2010, =================================================, + + $(WHATSNEW + $(LI $(B .init) property for static arrays is now an array literal) + $(LI Improved speed of associative arrays) + $(LI std.bigint has been completely replaced with a faster implementation. + Multiplication is now 5 times faster, division is + 300 times faster, and squaring is 10 times faster. For large numbers + (~5000 words), the speedup is 5 times larger than this.) + ) + $(BUGSFIXED + $(LI Fixed memory corruption problem with array appends) + $(LI $(BUGZILLA 122): DDoc newline behaviour produces suboptimal results) + $(LI $(BUGZILLA 1628): Ddoc produces invalid documentation for --- blocks) + $(LI $(BUGZILLA 2609): No documentation generated for destructor) + $(LI $(BUGZILLA 3808): Assertion Failure : Assertion failure: 'classinfo->structsize == CLASSINFO_SIZE' on line 870 in file 'toobj.c') + $(LI $(BUGZILLA 3884): Segfault: defining a typedef with an invalid object.d) + $(LI $(BUGZILLA 3911): Associative array in CTFE crashes compiler) + $(LI $(BUGZILLA 3958): mixin(non-static method) crashes compiler) + $(LI $(BUGZILLA 3972): Regarding module with name different from its file name) + $(LI $(BUGZILLA 3984): Segfault(interpret.c): CTFE using struct constructor on a local static variable) + $(LI $(BUGZILLA 3986): Struct constructors bypass default initialization of member variables) + $(LI $(BUGZILLA 4002): dmd.conf and binary path in dmd -v output) + $(LI $(BUGZILLA 4004): DMD 2.042 CTFE regression with functions taking ref parameters) + $(LI $(BUGZILLA 4005): std.c.stdlib.exit in CTFE and more) + $(LI $(BUGZILLA 4011): Incorrect function overloading using mixins) + $(LI $(BUGZILLA 4019): [CTFE] Adding an item to an empty AA) + $(LI $(BUGZILLA 4020): [ICE][CTFE] struct postblit in CTFE) + $(LI $(BUGZILLA 4023): std.math.hypot() returns infinity when either argument is zero) + $(LI $(BUGZILLA 4027): Closures in CTFE generate wrong code) + $(LI $(BUGZILLA 4029): CTFE: cannot invoke delegate returned from function) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.043 + TITLE=Change Log: $(VER) diff --git a/changelog/2.044.dd b/changelog/2.044.dd new file mode 100644 index 0000000000..03b5aa73b4 --- /dev/null +++ b/changelog/2.044.dd @@ -0,0 +1,41 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 30, 2010, =================================================, + + $(WHATSNEW + $(LI Improve spelling checking distance to 2.) + $(LI Now all unittests are run, even if some fail) + $(LI Many small improvements to error diagnostics and recovery) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 1079): gdb: Dwarf Error: Cannot find DIE at 0xb705 referenced from DIE at 0x250) + $(LI $(BUGZILLA 2437): ICE(tocsym.c, !needThis()) - default struct argument) + $(LI $(BUGZILLA 2935): ICE(out.c) using struct with constructor as function default argument) + $(LI $(BUGZILLA 2549): Segfault on array multiplication.) + $(LI $(BUGZILLA 3066): Array operation without a slice as the lvalue accepted, bad codegen) + $(LI $(BUGZILLA 3207): gdb: Push D patches upstream) + $(LI $(BUGZILLA 3415): broken JSON output) + $(LI $(BUGZILLA 3522): ICE(cg87.c): variable*array[].) + $(LI $(BUGZILLA 3987): [gdb] Invalid DWARF output for function pointers) + $(LI $(BUGZILLA 3974): ICE(init.c): Static array initializer with more elements than destination array) + $(LI $(BUGZILLA 4036): Segfault with -inline and literal of struct containing union) + $(LI $(BUGZILLA 4037): [gdb] Invalid DWARF output for wchar) + $(LI $(BUGZILLA 4038): [gdb] Invalid DWARF output for function pointers with ref args) + $(LI $(BUGZILLA 4067): [CTFE] Code inside try-catch blocks is silently ignored) + $(LI $(BUGZILLA 4072): Stack overflow on recursive template expansion inside contract) + $(LI $(BUGZILLA 4081): cannot compile the dmd on FreeBSD 8) + $(LI $(BUGZILLA 4089): crash when creating JSON output for incomplete struct) + $(LI $(BUGZILLA 4093): Segfault(interpret.c): with recursive struct templates) + $(LI $(BUGZILLA 4105): Stack overflow involving alias template parameters and undefined identifier) + $(LI $(BUGZILLA 4108): ICE(cod2.c): zero-length static array in function call) + $(LI $(BUGZILLA 4118): std.conv.to!SomeStruct("hello") crashes compiler) + $(LI $(BUGZILLA 4131): break does not work correctly with foreach and associative arrays) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.044 + TITLE=Change Log: $(VER) diff --git a/changelog/2.045.dd b/changelog/2.045.dd new file mode 100644 index 0000000000..9abd4a19ba --- /dev/null +++ b/changelog/2.045.dd @@ -0,0 +1,17 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION May 4, 2010, =================================================, + + $(WHATSNEW + ) + $(BUGSFIXED + $(LI Another try at fixing the Dwarf issues.) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.045 + TITLE=Change Log: $(VER) diff --git a/changelog/2.046.dd b/changelog/2.046.dd new file mode 100644 index 0000000000..ad934039fe --- /dev/null +++ b/changelog/2.046.dd @@ -0,0 +1,34 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION May 10, 2010, =================================================, + + $(WHATSNEW + $(LI Add hints for missing import declarations.) + $(LI Speed up compilation.) + $(LI All length methods in Phobos are now a @property.) + $(LI $(BUGZILLA 1001): print stack trace (in debug mode) when program die) + ) + $(BUGSFIXED + $(LI Fix hanging problem on undefined identifiers.) + $(LI $(BUGZILLA 461): Constant not understood to be constant when circular module dependency exists.) + $(LI $(BUGZILLA 945): template forward reference with named nested struct only) + $(LI $(BUGZILLA 1055): union forward reference "overlapping initialization" error) + $(LI $(BUGZILLA 2085): CTFE fails if the function is forward referenced) + $(LI $(BUGZILLA 2386): Array of forward referenced struct doesn't compile) + $(LI $(BUGZILLA 3945): AssertExpression message should implicitly convert to const char[]) + $(LI $(BUGZILLA 4015): forward reference in alias causes error) + $(LI $(BUGZILLA 4016): const initializer cannot forward reference other const initializer) + $(LI $(BUGZILLA 4042): Unable to instantiate a struct template.) + $(LI $(BUGZILLA 4100): Break and continue to label should mention foreach) + $(LI $(BUGZILLA 4116): object.di does not match object_.d) + $(LI $(BUGZILLA 4146): Unavailable: core.sys.posix.sys.wait.waitid()) + $(LI $(BUGZILLA 4184): associative array with certain key types results in corrupt values during iteration) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.046 + TITLE=Change Log: $(VER) diff --git a/changelog/2.047.dd b/changelog/2.047.dd new file mode 100644 index 0000000000..03f5767ffd --- /dev/null +++ b/changelog/2.047.dd @@ -0,0 +1,100 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jun 11, 2010, =================================================, + + $(WHATSNEW + $(LI Changed "op=" to just "op" for template argument to opOpAssign) + $(LI std.algorithm: Added save() to forward ranges; added split() using only one element as separator; added indexOf; fixed unlisted bug in startsWith and endsWith; added skipOver(); added canFind().) + $(LI std.array: Added implementation of save() for T[]s.) + $(LI std.concurrency: Eliminated spurious unittest stdout messages.) + $(LI std.container: Added.) + $(LI std.conv: Added file and line information to conversion errors; added brackets '[' and ']' around arrays and associative arrays as defaults; added emplace() for non-class types.) + $(LI std.file: Replaced exception upon out-of-memory error with assert(0).) + $(LI std.functional: toDelegate now accepts callable(function pointers, delegates and objects implement opCall) ) + $(LI std.path: Made basename() generic in string type.) + $(LI std.range: Added the existence of the property save as a condition for isForwardRange; added save to the range defined within; replaced a couple of awkward front() implementations; defined module-level moveFront() and range member moveFront() where appropriate; added @property maxLength to Take; arranged things such that take() for slice-able ranges returns the same type as the slice; eliminated SListRange; defined iota() with one argument; moved BinaryHeap within.) + $(LI std.regex: Qualified indexOf with std.algorithm.) + $(LI std.regexp: Qualified indexOf with std.algorithm.) + $(LI std.stdio: Added an error message to enforce() in rawRead().) + $(LI std.string: Improved indexOf(), tolower(), splitter(), chomp().) + $(LI std.traits: Added templates to get compile-time information about functions.) + $(LI std.typecons: Added AutoImplement.) + $(LI std.utf: Eliminated decodeFront() and decodeBack() - they aren't needed since strings are bidirectional ranges.) + $(LI $(BUGZILLA 2008): Poor optimization of functions with ref parameters) + $(LI $(BUGZILLA 3793): Functions with static arrays as arguments are not inlined) + $(LI $(BUGZILLA 4296): Reduce parasitic error messages) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 1193): regression: "matches more than one template declaration" doesn't list the location of the conflicting templates) + $(LI $(BUGZILLA 1894): scope(exit) is ignored except in compound statements) + $(LI $(BUGZILLA 1941): missing line on inaccesable external private module member) + $(LI $(BUGZILLA 2127): inliner turns struct "return *this" from by-value into by-ref) + $(LI $(BUGZILLA 2276): Error message missing line number on array operation) + $(LI $(BUGZILLA 2546): Array Ops silently fail when no slice symbol is used.) + $(LI $(BUGZILLA 2738): Rebindable should work for interfaces.) + $(LI $(BUGZILLA 2835): std.socket.TcpSocket doesn't actually connect) + $(LI $(BUGZILLA 2881): x.stringof returns typeof(x).stringof when x is an enum) + $(LI $(BUGZILLA 3064): Invalid array operation accepted, generates bad code) + $(LI $(BUGZILLA 3088): std.xml.check() fails on xml comments) + $(LI $(BUGZILLA 3139): compiler dies "Error: out of memory" with case range) + $(LI $(BUGZILLA 3200): std.xml doesn't follow spec for Tag.text) + $(LI $(BUGZILLA 3323): Segfault or ICE(e2ir.c) using struct with destructor almost anywhere) + $(LI $(BUGZILLA 3398): Attributes inside a union screws data alignment) + $(LI $(BUGZILLA 3465): isIdeographic can be wrong in std.xml) + $(LI Major improvements to CustomFloat, fixing $(BUGZILLA 3520): std.numeric.CustomFloat horribly broken) + $(LI $(BUGZILLA 3538): Default value of alias template parameter is instantiated only once.) + $(LI $(BUGZILLA 3547): for option -od for relative path the path is added twice) + $(LI $(BUGZILLA 3548): ICE occurs when an array is returned from a function is incorrectly used in an array op expression.) + $(LI $(BUGZILLA 3604): extern(C) callable function with array parameters broken) + $(LI $(BUGZILLA 3651): mangleof broken for enums) + $(LI $(BUGZILLA 3653): Problem sorting array of Rebindable) + $(LI $(BUGZILLA 3658): Crashing on vector operations (Mac only)) + $(LI $(BUGZILLA 3662): Wrong compile error within struct constructor and C-style initializer) + $(LI $(BUGZILLA 3667): Regression(D2 only): broken out(result) in contracts) + $(LI $(BUGZILLA 3786): bug in std.string.removechars) + $(LI $(BUGZILLA 3854): Error on static initialization of arrays with trailing comma.) + $(LI $(BUGZILLA 3873): std.range.repeat should have popBack defined) + $(LI $(BUGZILLA 3876): std.range.Take back/popBack methods don't work correctly) + $(LI $(BUGZILLA 3880): std.regex functions with const/immutable Regex object) + $(LI $(BUGZILLA 4003): The result changes only with the order of source files.) + $(LI $(BUGZILLA 4045): [CTFE] increasing array length) + $(LI $(BUGZILLA 4052): [CTFE] increment from array item) + $(LI $(BUGZILLA 4056): Template instantiation with bare parameter not documented) + $(LI $(BUGZILLA 4073): core.cpuid crashes) + $(LI $(BUGZILLA 4078): [CTFE] Failed return of dynamic array item) + $(LI $(BUGZILLA 4084): Ignored missing main() closing bracket) + $(LI $(BUGZILLA 4109): writeln doesn't work with empty static array) + $(LI $(BUGZILLA 4143): fix warnings in dmd build) + $(LI $(BUGZILLA 4156): Segfault with array+=array) + $(LI $(BUGZILLA 4169): building dmd with a modern gcc produces a buggy compiler) + $(LI $(BUGZILLA 4175): linux.mak doesn't declare sufficient dependencies to support parallel builds) + $(LI $(BUGZILLA 4188): std.file.remove throws Exception on success) + $(LI $(BUGZILLA 4193): Regression 2.046, ICE(expression.c): initialising class member with const forward reference) + $(LI $(BUGZILLA 4202): Changset 1517 doesn't compile) + $(LI $(BUGZILLA 4207): std.cover.setDestDir does not work.) + $(LI $(BUGZILLA 4208): druntime should not depend on Phobos) + $(LI $(BUGZILLA 4212): DWARF: void arrays cause gdb errors) + $(LI $(BUGZILLA 4213): Strange behaviour with static void[] arrays) + $(LI $(BUGZILLA 4219): hasAliasing does not care about immutable) + $(LI $(BUGZILLA 4220): I cannot apply @safe to intrinsic operation(eg: std.math.sqrt)) + $(LI $(BUGZILLA 4228): std.array.replace contains 2 bugs) + $(LI $(BUGZILLA 4230): version(unittest)) + $(LI $(BUGZILLA 4231): Solitary opUnary Postincrement and Postdecrement user defined operators are broken.) + $(LI $(BUGZILLA 4242): ICE(module.c): importing a module with same name as package) + $(LI $(BUGZILLA 4249): std.regex fails to compile with debug=regex) + $(LI $(BUGZILLA 4252): [CTFE] No array bounds checking in assignment to char[] array) + $(LI $(BUGZILLA 4257): ICE(interpret.c): passing parameter into CTFE as ref parameter) + $(LI $(BUGZILLA 4259): Header generation omits leading '@' for properties) + $(LI $(BUGZILLA 4262): Header generation omits 'enum' for enum declarations) + $(LI $(BUGZILLA 4263): Header generation omits '@system' attribute) + $(LI $(BUGZILLA 4270): Missing line number in 'can only catch class objects' error message) + $(LI $(BUGZILLA 4300): BigInt * int doesn't work well) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.047 + TITLE=Change Log: $(VER) diff --git a/changelog/2.048.dd b/changelog/2.048.dd new file mode 100644 index 0000000000..bdb05741b3 --- /dev/null +++ b/changelog/2.048.dd @@ -0,0 +1,92 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Aug 8, 2010, =================================================, + + + $(WHATSNEW + $(LI std.complex: New Complex.toString() syntax.) + $(LI std.string: icmp() now works with all built-in string types.) + $(LI $(BUGZILLA 4077): Bugs caused by bitwise operator precedence) + $(LI $(BUGZILLA 4080): Patch for building dynamic libraries on Mac OS X) + ) + $(BUGSFIXED + $(LI Unlisted Bug: std.algorithm.filter not a forward range) + $(LI Unlisted Bug: std.algorithm.Uniq requires a bidirectional range) + $(LI Unlisted Bug: std.algorithm.Uniq missing a save() function) + $(LI Unlisted Bug: std.algorithm.Group missing a save() function) + $(LI Unlisted Bug: std.traits.isAssociativeArray reports true for structs w/ keys, values properties) + $(LI Unlisted Bug: gc_query returns 0 for attr when called on interior pointers) + $(LI $(NG_digitalmars_D 112964): capacity can return a value $(LESS) length) + $(LI $(BUGZILLA 978): std.utf's toUTF* functions accept some invalid and reject some valid UTF) + $(LI $(BUGZILLA 996): Error in doc on implicit conversion between pointer and array) + $(LI $(BUGZILLA 1418): tupleof bug on nested classes) + $(LI $(BUGZILLA 1678): ref with varargs generates invalid code) + $(LI $(BUGZILLA 2275): std.utf.toUTF16z() should return const(wchar)*) + $(LI $(BUGZILLA 2627): std.traits.hasAliasing reports true for static arrays) + $(LI $(BUGZILLA 2872): Length, opIndex for Map) + $(LI $(BUGZILLA 2931): Initialization struct with array from another struct) + $(LI $(BUGZILLA 3202): std.math.pow cause dead loop) + $(LI $(BUGZILLA 3326): $ in delegate literal causes Access Violation) + $(LI $(BUGZILLA 3355): std.string.cmp works incorrectly for mixed-type and different-length strings) + $(LI $(BUGZILLA 3386): to!bool(string) is not implemented) + $(LI $(BUGZILLA 3436): std.functional.compose with only one function) + $(LI $(BUGZILLA 3439): std.range.Sequence.opIndex not consistent after calling popFront().) + $(LI $(BUGZILLA 3447): std.file uses unconventional file permissions) + $(LI $(BUGZILLA 3528): FreeBSD patches for druntime.) + $(LI $(BUGZILLA 3560): foreach over nested function generates wrong code) + $(LI $(BUGZILLA 3569): DMD Stack Overflow with a struct member function inside a C-style struct initializer) + $(LI $(BUGZILLA 3604): extern(C) callable function with array parameters broken) + $(LI $(BUGZILLA 3679): Regression(2.031) template forward reference regression) + $(LI $(BUGZILLA 3706): delegates of interfaces with multiple inheritance fail) + $(LI $(BUGZILLA 3716): Regression (2.037) with multi dimensional array literals) + $(LI $(BUGZILLA 3782): The POSIX sys/un.h header) + $(LI $(BUGZILLA 3853): core.sys.posix.stdio.pclose is missing) + $(LI $(BUGZILLA 3872): std.algorithm.filter could become bidirectional if its input range is bidir) + $(LI $(BUGZILLA 3874): std.range.stride assumes a bidirectional input range) + $(LI $(BUGZILLA 3917): opEquals for Ojbect could be more efficient) + $(LI $(BUGZILLA 3937): os.path.dirname fails on absolute path) + $(LI $(BUGZILLA 3961): Error with to!(somestruct)) + $(LI $(BUGZILLA 3983): Regression(2.037): struct with == can't be member of struct with template opEquals) + $(LI $(BUGZILLA 4109): (reopened) writeln doesn't work with empty static array) + $(LI $(BUGZILLA 4171): std.random.uniform does not work for a range of characters) + $(LI $(BUGZILLA 4191): [FreeBSD] real constants are rounded to double precision) + $(LI $(BUGZILLA 4198): [FreeBSD] imprecision in decimal floating-point literals) + $(LI $(BUGZILLA 4238): Segfault(statement.c): with(typeof(int))) + $(LI $(BUGZILLA 4260): windows & basename) + $(LI $(BUGZILLA 4267): forward reference error when 2-fold aliasing a template instance) + $(LI $(BUGZILLA 4303): __traits(compiles) returns wrong result when used recursively) + $(LI $(BUGZILLA 4305): Take, Chain on top of ranges w/o moveFront() ) + $(LI $(BUGZILLA 4307): spawn()'ed thread doesn't terminate) + $(LI $(BUGZILLA 4314): Regression(1.062): Expression array1 && array2 doesn't compile) + $(LI $(BUGZILLA 4327): std.container.Array.Range.~this() tries to call free(T[])) + $(LI $(BUGZILLA 4339): Struct destructor + invariant + struct parameter = horrific error message) + $(LI $(BUGZILLA 4356): Copy constructor not called under extremely mysterious circumstances) + $(LI $(BUGZILLA 4362): std.range.repeat and cycle do not have a .save() method) + $(LI $(BUGZILLA 4363): std.algorithm.Until is not a forward range) + $(LI $(BUGZILLA 4369): Multiple bugs in GC minimize()) + $(LI $(BUGZILLA 4370): POSIX monitor attribute not being used) + $(LI $(BUGZILLA 4396): mkdir race prevents concurrent compiling with DMD using make -j) + $(LI $(BUGZILLA 4400): D2 GC doesn't allocate with 16 bytes alignment) + $(LI $(BUGZILLA 4406): Typo (bug) in std.concurrency) + $(LI $(BUGZILLA 4412): Array capacity growth spikey and the ratio approaches 1.0) + $(LI $(BUGZILLA 4443): Optimizer produces wrong code for || or && with struct arrays) + $(LI $(BUGZILLA 4452): Incorrect result of BigInt ^^ long) + $(LI $(BUGZILLA 4470): Problems with std.bigint mod and divide) + $(LI $(BUGZILLA 4503): forward reference to aliased template instance) + $(LI $(BUGZILLA 4506): Regression(2.034): -O flag breaks some recursive functions) + $(LI $(BUGZILLA 4514): Regression: Cannot cast from X* to X) + $(LI $(BUGZILLA 4516): Regression(2.040): forward declaration of enum not supported) + $(LI $(BUGZILLA 4551): D2 Language Docs: http://www.digitalmars.com/d/2.0/arrays.html) + $(LI $(BUGZILLA 4569): extern(c++) doesn't understand const types, produces bad mangled symbol) + $(LI $(BUGZILLA 4570): ElementType!(void[]) shows error message) + $(LI $(BUGZILLA 4578): Regression(2.047,1.062): ICE(cgcod.c): var+arr[]) + $(LI $(BUGZILLA 4590): Spec incorrectly describes array appending and memory stomping) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.048 + TITLE=Change Log: $(VER) diff --git a/changelog/2.049.dd b/changelog/2.049.dd new file mode 100644 index 0000000000..71596e6557 --- /dev/null +++ b/changelog/2.049.dd @@ -0,0 +1,104 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 13, 2010, =================================================, + + + $(WHATSNEW + $(LI std.algorithm: reduce now works with non-range-based iteration, such as opApply.) + $(LI std.numeric: Added FFT.) + $(LI std.path: Changed sep, altsep etc. to manifest constants (enum).) + $(LI std.process: Added environment, an AA-like interface for environment variables.) + $(LI std.range: Iota, Stride, Transversal, FrontTransveral now support slicing where possible.) + $(LI std.range: Added support for moveFront() and assignable elements in several higher-order ranges.) + $(LI std.range: Added Lockstep, hasLvalueElements.) + $(LI std.range: Added virtual function-based wrappers (InputRangeObject, OutputRangeObject) for when a binary interface to a range is required.) + $(LI std.typecons: Added convenience functions for Rebindable.) + $(LI std.traits: Added isAssignable, isIterable, ForeachType, isSafe, isUnsafe, EnumMembers.) + $(LI std.traits: hasLocalAliasing, hasLocalObjects and hasLocalRawAliasing are now hasUnsharedAliasing, hasUnsharedObjects and hasUnsharedRawAliasing. Aliases to the old names are included for now for backwards compatibility.) + $(LI std.typetuple: Added anySatisfy.) + $(LI std.array: Modified Appender's interface to fix memory issues. + Note that appending via $(D ~=) and using appender on the same array + will not interleave anymore.) + $(LI $(BUGZILLA 2477): Trailing comma in array literal sometimes accepted, sometimes not) + ) + $(BUGSFIXED + $(LI Andrej Mitrovic updated the samples/d code) + $(LI Unlisted Bug: std.math.pow doesn't work on immutable numbers.) + $(LI Unlisted Bug: std.math.pow floating point overload expects both arguments to be exact same type.) + $(LI Unlisted Bug: std.path.join("", "foo") returns "/foo" instead of "foo" on Posix.) + $(LI Unlisted Bug: std.range.iota() random access primitives inconsistent after popFront on floating point version) + $(LI Unlisted Bug: std.algorithm.findAdjacent() [...]) + $(LIX $(BUGZILLA 190): Cannot forward reference typedef/alias in default value for function parameter) + $(LI $(BUGZILLA 1715): Template specialization checks for equality rather than convertibility) + $(LI $(BUGZILLA 1970): Templated interfaces not matched) + $(LI $(BUGZILLA 2511): Covariant return type doesn't work with circular import) + $(LI $(BUGZILLA 2716): Confusion of auto and scope as the class attribute) + $(LI $(BUGZILLA 2903): Splitter should be bi-dir if the input range is bi-dir.) + $(LI $(BUGZILLA 2951): std.random.dice() should be templated on proportions.) + $(LI $(BUGZILLA 2958): std.getopt RangeError on missing arg) + $(LI $(BUGZILLA 3046): Segfault with C++ static variable (Linux only)) + $(LI $(BUGZILLA 3123): std.algorithm.zip fails on 'lazy' ranges) + $(LI $(BUGZILLA 3294): forward reference to inferred return type of function call) + $(LI $(BUGZILLA 3312): std.string.count should use const(char)[], not immutable.) + $(LI $(BUGZILLA 3348): Documentation for many std.process functions has disappeared) + $(LI $(BUGZILLA 3361): code in std.zlib concatenates void[] arrays ) + $(LI $(BUGZILLA 3418): link error with cast(ulong)(ulong*real)) + $(LI $(BUGZILLA 3544): optlink termination 0041338f with recursive nested functions) + $(LI $(BUGZILLA 3554): Ddoc generats invalid output for documentation comments with non paired paranthasis) + $(LI $(BUGZILLA 3627): -of with a filename with a double extension confuses linker) + $(LI $(BUGZILLA 3877): std.range.chain do not manage infinite ranges correctly) + $(LI $(BUGZILLA 3894): std.range.Stride!R requires R.front() and R.back() to return by reference) + $(LI $(BUGZILLA 3935): opBinary is instantiated with "=") + $(LI $(BUGZILLA 3946): schwartzSort - SwapStrategy always unstable) + $(LIX $(BUGZILLA 3979): Order-of-compilation and forward reference errors) + $(LI $(BUGZILLA 3996): Regression(2.041) ICE(glue.c) Passing struct as AA template parameter (Algebraic with struct)) + $(LI $(BUGZILLA 4009): OPTLINK ruins the day yet again) + $(LI $(BUGZILLA 4173): Regression(2.037) Explicitly instantiated templates still try to do IFTI in some cases) + $(LI $(BUGZILLA 4177): __ctfe can't be used in pure functions) + $(LI $(BUGZILLA 4278): allow inlining of super calls (undo limitations of bug3500's fix)) + $(LI $(BUGZILLA 4291): Pure functions cannot access mixed in variables) + $(LI $(BUGZILLA 4292): CommonType fails for singular alias value.) + $(LI $(BUGZILLA 4302): Regression(2.046, 1.061): compiler errors using startsWith in CTFE) + $(LI $(BUGZILLA 4345): std.range.take!string: "Nonsensical finite range with slicing but no length".) + $(LI $(BUGZILLA 4346): More flexible std.array.array.) + $(LI $(BUGZILLA 4363): Some phobos ranges are not forward ranges (but should be).) + $(LI $(BUGZILLA 4381): Length attribute for std.typecons.Tuple.) + $(LI $(BUGZILLA 4387): std.range.Cycle assumes lvalue elements.) + $(LI $(BUGZILLA 4388): std.range.Radial assumes lvalue elements.) + $(LI $(BUGZILLA 4402): std.range.Zip doesn't work w/ non-lvalue ranges.) + $(LI $(BUGZILLA 4403): std.range.FrontTransversal assumes lvalue elements.) + $(LI $(BUGZILLA 4404): std.range.Transversal assumes lvalue elements.) + $(LI $(BUGZILLA 4408): Ambiguity when using std.algorithm.splitter with generic ranges.) + $(LI $(BUGZILLA 4430): Regression(2.037) erroneous matching on specialized template function) + $(LI $(BUGZILLA 4455): Taking the sqrt of an integer shouldn't require an explicit cast.) + $(LI $(BUGZILLA 4464): std.range.take does not always return Take!R.) + $(LI $(BUGZILLA 4518): to!string(enum w/invalid value) produces a somewhat unhelpful error) + $(LI $(BUGZILLA 4564): ICE on undefined variable in foreach over 0 .. undef) + $(LI $(BUGZILLA 4603): array(iota(1, 0)) error.) + $(LI $(BUGZILLA 4643): Shared values are unwritable.) + $(LI $(BUGZILLA 4645): to!string(const char*) in library causes Optlink to issue warning) + $(LI $(BUGZILLA 4652): Compiler hangs on template with zero-length tuple and another argument) + $(LI $(BUGZILLA 4655): Regression(1.063, 2.048) goto to a try block ICEs) + $(LI $(BUGZILLA 4676): Overload resolution rejects valid code when mixing variadics, non-variadics) + $(LI $(BUGZILLA 4681): Appender access violation) + $(LI $(BUGZILLA 4691): Incorrect comparison of double and long) + $(LI $(BUGZILLA 4700): to!float("0") fails) + $(LI $(BUGZILLA 4721): compilation slow when compiling unittests on dcollections) + $(LI $(BUGZILLA 4748): Shadowing declaration error in std.string.tolower) + $(LI $(BUGZILLA 4751): Regression(1.062, 2.047) ICE(constfold.c) >> after error) + $(LI $(BUGZILLA 4752): fail_compilation/fail345.d asserts in expression.c) + $(LI $(BUGZILLA 4771): fail_compilation/fail274.d hits a halt in iasm.c) + $(LI $(BUGZILLA 4789): std.algorithm.sort bug) + $(LI $(BUGZILLA 4810): dotProduct problem with ints) + $(LI $(BUGZILLA 4826): Regression(2.041) "cannot create associative array" and compiler crash) + $(LI $(BUGZILLA 4828): ICE w/ non-boolean dot expression sth.template_instance in static if) + $(LI $(BUGZILLA 4834): Implicit sharing via delegates in std.concurrency) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.049 + TITLE=Change Log: $(VER) diff --git a/changelog/2.050.dd b/changelog/2.050.dd new file mode 100644 index 0000000000..33d7c69f8a --- /dev/null +++ b/changelog/2.050.dd @@ -0,0 +1,90 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 29, 2010, =================================================, + + $(WHATSNEW + $(LI added talign() and argTypes() to TypeInfo) + $(LI Upgrade zlib support to zlib 1.2.5) + $(LI std.stdio: Added ByChunk. This struct is a InputRange like ByLine. File.byChunk returns ByChunk) + $(LI std.traits: Most higher-order ranges now work with const/immutable arrays and other ranges + with a natural tail const, and ranges w/ const/immutable elements.) + $(LI $(BUGZILLA 4888): Heavy reliance on Bug 3534 in Phobos range usage) + $(LI $(BUGZILLA 4987): C function pointer syntax needs to be deprecated) + $(LI std.typecons: Several improvements to the Tuple struct template: + $(UL $(LI Tuple members are now accessible with the syntax a[0], a[1] etc.) + $(LI Eliminated an internal union. See $(BUGZILLA 4421) and $(BUGZILLA 4846).) + $(LI Worked around $(BUGZILLA 4424). Got opAssign back.) + $(LI Made Tuple.slice!(from, to) to preserve field names if any.) + $(LI Added isTuple!(T) template.) + )) + $(LI std.algorithm: changed filter() such that filter is curryable) + $(LI std.algorithm: Added function balancedParens) + $(LI std.typecons: Deprecated defineEnum) + $(LI Added relaxed purity checking rules.) + ) + $(BUGSFIXED + $(LI Unlisted bug: std.exception.pointsTo() calls postblit on subobjects.) + $(LI Unlisted bug: std.typetuple.staticMap!() doesn't work with empty/single tuples.) + $(LI Unlisted bug: std.traits: Interfaces should have indirections, aliasing, etc.) + $(LI Unlisted bug: std.socket: Race condition - gethostbyname and gethostbyaddr on Linux return static data. The call was synchronized, but using the data wasn't) + $(LI Unlisted bug: signed long comparisons under OS X) + $(LI $(BUGZILLA 941): std.regexp fails to match when grouping certain sub-expressions) + $(LI $(BUGZILLA 1482): std.file docs are insufficient) + $(LI $(BUGZILLA 1635): DirEntry.isfile() and DirEntry.isdir() broken) + $(LI $(BUGZILLA 1733): parse() function does not handle all build-in types) + $(LI $(BUGZILLA 2073): Variant.coerce!() fails) + $(LI $(BUGZILLA 2142): getopt() incorrectly processes bundled command-line options) + $(LI $(BUGZILLA 2310): Inconsistent formatting of arrays in std.stdio.write() and std.conv.to!(string)()) + $(LI $(BUGZILLA 2424): std.functional binaryRevertArgs : "revert" should be "reverse") + $(LI $(BUGZILLA 2451): Adding structs that use opAssign or postblit to an AA is broken) + $(LI $(BUGZILLA 2655): Allow alternation patterns in std.path.fnmatch) + $(LI $(BUGZILLA 2669): Variant does not have opApply or another iteration mechanism) + $(LI $(BUGZILLA 2718): Inconsistent string parameters in Phobos functions) + $(LI $(BUGZILLA 2838): std.file.rmdirRecurse fails) + $(LI $(BUGZILLA 2930): Problems in std.range documentation) + $(LI $(BUGZILLA 2943): Struct copying in presence of alias member this only copies alias this member) + $(LI $(BUGZILLA 2965): std.date: timezone not initialized) + $(LI $(BUGZILLA 3157): [patch] Pipes should be closed with pclose) + $(LI $(BUGZILLA 3318): [PATCH]Rebindable.get is not accessible) + $(LI $(BUGZILLA 3570): mkdirRecurse throws exception on trailing empty directory.) + $(LI $(BUGZILLA 3602): ICE(tocsym.c) compiling a class, if its super class has preconditions) + $(LI $(BUGZILLA 3665): Regression(1.051, 2.036) Assignment with array slicing does not work) + $(LI $(BUGZILLA 4344): Sockets with multiple threads report missing/failed WSAStartup) + $(LI $(BUGZILLA 4398): dmd always uses Windows name mangling for _d_throw) + $(LI $(BUGZILLA 4439): The declaration of the in6addr_* in druntime is wrong.) + $(LI $(BUGZILLA 4465): ICE(symbol.c): immutable type inference with ^^2) + $(LI $(BUGZILLA 4524): Regression(2.026) Bus error with nested struct) + $(LI $(BUGZILLA 4623): Non-integer type allowed as static array size) + $(LI $(BUGZILLA 4634): typo in levenshteinDistanceAndPath documentation) + $(LI $(BUGZILLA 4641): Associative arrays of structs with alias this broken.) + $(LI $(BUGZILLA 4742): int % BigInt should work.) + $(LI $(BUGZILLA 4775): No substitution on writef("%%%s", "hi").) + $(LI $(BUGZILLA 4825): Regression(1.057, 2.040) "Error: non-constant expression" with -inline) + $(LI $(BUGZILLA 4866): Static-to-dynamic converted manifest constant array gets non-converted type in static/constraint if) + $(LI $(BUGZILLA 4869): auto return + inheritance + modules = compiler crashes(toctype.c)) + $(LI $(BUGZILLA 4873): Assertion failure: '0' on line 1483 in file 'expression.c') + $(LI $(BUGZILLA 4882): std.traits hasUnsharedAliasing does not work for function type.) + $(LI $(BUGZILLA 4897): CodeView: No locals or parameters are shown when debugging, because of missing function info) + $(LI $(BUGZILLA 4890): GC.collect() deadlocks multithreaded program.) + $(LI $(BUGZILLA 4925): [ICE] segfault with module-scope assert(0)) + $(LI $(BUGZILLA 4926): ICE: PREC_zero assertion failure due to unset precedence) + $(LI $(BUGZILLA 4938): Regression(2.047) dmd segfault when compiling) + $(LI $(BUGZILLA 4941): Built-in tuple slice boundaries are not CTFE'd) + $(LI $(BUGZILLA 4949): ICE on invalid static if using value of 'this') + $(LI $(BUGZILLA 4951): InternetAddress fails to resolve host when multithreading.) + $(LI $(BUGZILLA 4959): std.conv.parse error "no digits seen" on string starting with zero.) + $(LI $(BUGZILLA 4992): ICE(glue.c) or segfault: using int[new]) + $(LI $(BUGZILLA 5003): regex(replace with delegate) sample doesn't work.) + $(LI $(BUGZILLA 5026): ICE(expression.c) Incomplete mixin expression + char[] to char assignment) + $(LI $(BUGZILLA 5049): std.algortihm.bringToFront() returns wrong value.) + $(LI $(BUGZILLA 5052): take!(Take!R) should return Take!R, not Take!(Take!R).) + $(LI $(BUGZILLA 5071): passing value by ref to a function with an inner dynamic closure results in a wrong code) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.050 + TITLE=Change Log: $(VER) diff --git a/changelog/2.051.dd b/changelog/2.051.dd new file mode 100644 index 0000000000..97330b3d40 --- /dev/null +++ b/changelog/2.051.dd @@ -0,0 +1,97 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Dec 21, 2010, =================================================, + + $(WHATSNEW + $(LI Added std.mathspecial, containing mathematical Special Functions) + $(LI std.base64: Replaced. Boost License, Performance improvement, Range support. Function signature changed from 'encode' to 'Base64.encode') + $(LI std.math: D implementation of pow. Almost all std.math functions are now @safe pure nothrow. + tgamma, lgamma, erf, erfc have been moved to std.mathspecial) + $(LI std.exception: Added pure and nothrow to assumeUnique) + $(LI std.utf: Removed UtfError class and toUTF* shortcut functions for validation. Added pure, nothrow, @safe and @trusted attributes. count function supports dchar) + $(LI Both druntime and phobos now build successfully with dmd -m64. Still somewhat behind dmd1, very little executes correctly still.) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 603): Undocumented behaviour: case and default create a scope) + $(LI $(BUGZILLA 632): Typedef/enum promotions spec ambiguous - ultimate base type or lowest common denominator?) + $(LI $(BUGZILLA 679): Spec needs allowances for copying garbage collection) + $(LI $(BUGZILLA 690): ABI not fully documented) + $(LI $(BUGZILLA 1351): Discrepancies in the language specification) + $(LI $(BUGZILLA 1466): Spec claims maximal munch technique always works: not for "1..3") + $(LI $(BUGZILLA 2080): ICE(mangle.c) alias corrupts type inference of static variables) + $(LI $(BUGZILLA 2206): unnamed template mixin of class inside function or class has incorrect classinfo and mangleof) + $(LI $(BUGZILLA 2385): spec says all structs are returned via hidden pointer on linux, but it uses registers) + $(LI $(BUGZILLA 2392): Parsing ambiguity between function pointer declaration and function call) + $(LI $(BUGZILLA 2406): Declarator2 definition error) + $(LI $(BUGZILLA 2556): Property classinfo needs better documentation (RTTI, typeof, typeid, runtime type information)) + $(LI $(BUGZILLA 2616): Undocumented behaviour: part-explicit, part-implicit instantiations of function templates are accepted) + $(LI $(BUGZILLA 2651): class body declaration grammar incorrect) + $(LI $(BUGZILLA 2652): DeclDef grammar is wrong) + $(LI $(BUGZILLA 2734): Ambiguity in tokenizing: _._ as a float literal) + $(LI $(BUGZILLA 2751): const/invariant/immutable static arrays: const(T)[N] and const(T[N]) are the same, but DMD treats them as different) + $(LI $(BUGZILLA 2954): [tdpl] Appalling bug in associative arrays (D2 only)) + $(LI $(BUGZILLA 2994): Incomplete "Predefined Versions" documentation) + $(LI $(BUGZILLA 3020): No description is given why function may not be nothrow) + $(LI $(BUGZILLA 3112): Specification on what operations call the GC is missing) + $(LI $(BUGZILLA 3276): Recursion broken by alias template parameter) + $(LI $(BUGZILLA 3554): Ddoc generates invalid output for documentation comments with non paired parentheses) + $(LI $(BUGZILLA 3864): Dyn array allocations can be allowed in nothrow functions) + $(LI $(BUGZILLA 4059): Incorrect C++ name mangling) + $(LI $(BUGZILLA 4217): Function overloads are not distinguished when instantiating templates) + $(LI $(BUGZILLA 4254): ICE(mtype.c): function with const inout parameter) + $(LI $(BUGZILLA 4297): Nothrow functions cannot use constant dynamic array) + $(LI $(BUGZILLA 4384): Cyclic dependency check for modules is broken) + $(LI $(BUGZILLA 4434): ICE(mtype.c, 887) alias with const, shared, or immutable) + $(LI $(BUGZILLA 4445): roundTo!ubyte(255.0) throws) + $(LI $(BUGZILLA 4529): Segfault(typinf.c) involving typeid(typeof(functionName))) + $(LI $(BUGZILLA 4638): Regression: new writeln does not recognize "wstring toString") + $(LI $(BUGZILLA 4728): Segfault(toctype.c) by protected/private constructor in an other module) + $(LI $(BUGZILLA 4781): Segfault(mtype.c) with forward referenced typeof and .init) + $(LI $(BUGZILLA 4864): ICE(statement.c) Crash on invalid 'if statement' body inside mixin) + $(LI $(BUGZILLA 4901): std.algorithm.sort does not compile for interfaces.) + $(LI $(BUGZILLA 4915): auto return type escapes function purity) + $(LI $(BUGZILLA 5020): Forward implicit bool conversions to alias this) + $(LI $(BUGZILLA 5053): Better error message for cyclic dependencies.) + $(LI $(BUGZILLA 5054): Splitter example doesn't work) + $(LI $(BUGZILLA 5094): No implicit conversion with "alias property this") + $(LI $(BUGZILLA 5107): Const-shared classes/structs not typed as shared) + $(LI $(BUGZILLA 5110): Excess attribute propagation of structs and classes) + $(LI $(BUGZILLA 5117): [CTFE] Member function call with rather complex this: side effects ignored) + $(LI $(BUGZILLA 5120): ICE(mtype.c) void associative arrays) + $(LI $(BUGZILLA 5131): Segfault(expression.c) opAssign and associative arrays (AA) are broken for types != this) + $(LI $(BUGZILLA 5133): dmd fails to build rdmd (problem with startsWith)) + $(LI $(BUGZILLA 5145): Regression(2.050, 1.065) override error with forward ref of superclass) + $(LI $(BUGZILLA 5148): Incorrect C++ mangling of multiple const char* parameters) + $(LI $(BUGZILLA 5154): Class Range does not work in writeln) + $(LI $(BUGZILLA 5159): Segfault(interpret.c): calling a static function pointer variable in CTFE) + $(LI $(BUGZILLA 5163): meaningless error message with front() applied to void[].) + $(LI $(BUGZILLA 5164): Error without line number using "is (T...)") + $(LI $(BUGZILLA 5180): ICE(arrayop.c) in-place array operation on incompatible types) + $(LI $(BUGZILLA 5182): ICE(expression.c): calling unittest from a function) + $(LI $(BUGZILLA 5191): Combination of pure and nothrow result in a function that does nothing) + $(LI $(BUGZILLA 5194): ddoc does not show modifiers on constructors such as pure or nothrow) + $(LI $(BUGZILLA 5195): Forward references ignore const) + $(LI $(BUGZILLA 5214): Compiler crash with array of empty {}) + $(LI $(BUGZILLA 5218): Can't implicitly convert from "abc"w to wchar[3]) + $(LI $(BUGZILLA 5220): Make std.conv.ConvError an Exception instead of an Error; $(RED deprecated ConvError and ConvOverflowError) with ConvException and ConvOverflowException. Note that any code depending on the fact that these exceptions were Error gets broken.) + $(LI $(BUGZILLA 5230): Regression(2.041, 1.057) ICE(tocsym.c) overriding a method that has an out contract) + $(LI $(BUGZILLA 5238): PATCH: fix return of uninitialised var in interpret.c) + $(LI $(BUGZILLA 5247): std.utf.stride() should not return 0xFF) + $(LI $(BUGZILLA 5275): x86_64 related hidden function parameter mishandled) + $(LI $(BUGZILLA 5293): std.math: Error: shift by -48 is outside the range 0..32) + $(LI $(BUGZILLA 5294): -O optimization breaks for loop) + $(LI $(BUGZILLA 5321): std.math: assumes X86 or X86_64 on FPU control word code) + $(LI $(BUGZILLA 5322): std.math: version(Sparc) should be SPARC) + $(LI $(BUGZILLA 5330): Druntime/Phobos: remove special treatment for GDC) + $(LI $(BUGZILLA 5331): mach format problem) + $(LI $(BUGZILLA 5340): isOutputRange!(Appender!string, int) must be false) + $(LI $(BUGZILLA 5353): clear function is calling the destructor twice) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.051 + TITLE=Change Log: $(VER) diff --git a/changelog/2.052.dd b/changelog/2.052.dd new file mode 100644 index 0000000000..1e7e9bea28 --- /dev/null +++ b/changelog/2.052.dd @@ -0,0 +1,98 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 17, 2011, =================================================, + + $(WHATSNEW + $(LI 64 bit support for Linux) + $(LI Implemented $(I exception chaining), as described in TDPL. Currently Windows-only.) + $(LI std.random: Added Xorshift random generator) + $(LI Support HTML5 entities) + $(LI Added std.datetime for handling dates and times. std.date and std.gregorian + are now scheduled for deprecation. Any functions in other modules of Phobos + which used std.date.d_time have been changed to use std.datetime.SysTime or + are scheduled for deprecation with new functions with the same functionality + added which use SysTime (done in cases where switching existing functions to + use SysTime would have broken code). New code should use std.datetime instead + of std.date.) + $(LI Various functions in std.file were renamed to match Phobos' naming + conventions (e.g. isFile instead of isfile). The old names are aliased + and scheduled for deprecation.) + ) + $(BUGSFIXED + $(LI $(BUGZILLA 190): Cannot forward reference typedef/alias in default value for function parameter) + $(LI $(BUGZILLA 1513): try/catch/finally misbehavior on windows) + $(LI $(BUGZILLA 1899): AA of fixed-length arrays fails to initialize) + $(LI $(BUGZILLA 1914): Array initialisation from const array yields memory trample) + $(LI $(BUGZILLA 2581): DDoc doesn't work for functions with auto return type.) + $(LI $(BUGZILLA 2810): Bogus forward reference error with auto function) + $(LI $(BUGZILLA 2874): phobos docs issues) + $(LI $(BUGZILLA 3198): wrong initializer for structs arrays) + $(LI $(BUGZILLA 3334): std.demangle doesn't parse ref, pure, nothrow) + $(LI $(BUGZILLA 3681): ICE(go.c): when function takes too long to optimize, only with -O.) + $(LI $(BUGZILLA 3848): functions in std.file don't take symbolic links into account) + $(LI $(BUGZILLA 4013): Inconsistent codeview debug info for classes derived from IUnknown) + $(LI $(BUGZILLA 4069): Issue 4069 - std.xml.Document.pretty saves empty elements with spaces and line breaks) + $(LI $(BUGZILLA 4245): Declaring conflicting symbols in single function scope allowed) + $(LI $(BUGZILLA 4307): spawn()'ed thread doesn't terminate) + $(LI $(BUGZILLA 4328): templated unittests fail to link when instantiated from other file if compiler order isn't correct) + $(LI $(BUGZILLA 4379): ICE(blockopt.c): foreach over huge tuple, only with -O) + $(LI $(BUGZILLA 4389): ICE(constfold.c, expression.c), or wrong code: string~=dchar in CTFE) + $(LI $(BUGZILLA 4486): CodeView debug info should contain absolute path names) + $(LI $(BUGZILLA 4598): std.xml check is too restrictive) + $(LI $(BUGZILLA 4601): Spawned threads frequently don't terminate or let other threads ever run if you spawn more than one thread) + $(LI $(BUGZILLA 4732): __traits(identifier) performs constant folding on symbols) + $(LI $(BUGZILLA 4753): fail_compilation/fail116.d sends dmd into a loop, exhausting memory) + $(LI $(BUGZILLA 4807): Examples for std.array insert and replace) + $(LI $(BUGZILLA 4852): core.demangle cannot demangle functions with class/struct return types) + $(LI $(BUGZILLA 4878): Ddoc: Default arguments can break Ddoc output) + $(LI $(BUGZILLA 4913): Implicit opCast!bool in if statement doesn't work with declarator) + $(LI $(BUGZILLA 4973): map file with spaces in file name passed without quotes to linker) + $(LI $(BUGZILLA 5025): ICE(cast.c) shared struct literal) + $(LI $(BUGZILLA 5090): ICE(todt.c) struct literal initializing zero length array) + $(LI $(BUGZILLA 5105): Member function template cannot be synchronized) + $(LI $(BUGZILLA 5197): Ddoc: access-attributed auto template function crashes dmd) + $(LI $(BUGZILLA 5198): Appender much slower when appending ranges of elements than individual elements) + $(LI $(BUGZILLA 5209): posix/sys/select.d: FD_ISSET function should return bool) + $(LI $(BUGZILLA 5221): entity.c: Merge Walter's list with Thomas') + $(LI $(BUGZILLA 5242): self referencing template constraint crashes compiler) + $(LI $(BUGZILLA 5244): PATCH: fix use of uninitialised variable in toObj.c) + $(LI $(BUGZILLA 5246): PATCH(s): fix a couple more uninitialised variables) + $(LI $(BUGZILLA 5248): CTFE Segfault when calling a function on an enum struct) + $(LI $(BUGZILLA 5271): Not constant RAND_MAX) + $(LI $(BUGZILLA 5320): gcstub/gc.d: SEGV because of missing returns) + $(LI $(BUGZILLA 5349): ICE(toir.c): nested class in static member function) + $(LI $(BUGZILLA 5365): Regression (2.051) implicit conversions via alias this are broken) + $(LI $(BUGZILLA 5381): Regression (2.051) switch fails for wstring and dstring) + $(LI $(BUGZILLA 5382): [regression 2.051] DLL multi-threading broken) + $(LI $(BUGZILLA 5391): Crash with recursive alias declaration) + $(LI $(BUGZILLA 5400): Add const to FD_ISSET) + $(LI $(BUGZILLA 5439): 64bit struct alignment inconsistent with C ABI) + $(LI $(BUGZILLA 5447): Should be illegal to throw a non-Throwable) + $(LI $(BUGZILLA 5455): ICE(cgcod.c): Optimization (register allocation?) regression in DMD 1.065) + $(LI $(BUGZILLA 5486): Missing define for running dmd as 64 bit) + $(LI $(BUGZILLA 5488): Spawned threads hang in a way that suggests allocation or gc issue) + $(LI $(BUGZILLA 5504): Regression(2.051): Template member functions of a shared class don't compile) + $(LI $(BUGZILLA 5534): [64-bit] Inexplicable segfault in small code snippet, -O -release -m64 only) + $(LI $(BUGZILLA 5536): Array append with dollar op on 64-bit) + $(LI $(BUGZILLA 5545): [64-bit] DMD fails to postincrement ubytes.) + $(LI $(BUGZILLA 5549): [64-bit] Internal error: backend/cgcod.c 1845) + $(LI $(BUGZILLA 5552): std.datetime.d DosFileTimeToSysTime has a bug) + $(LI $(BUGZILLA 5556): [64-bit] Wrong Implicit Conversion to Double) + $(LI $(BUGZILLA 5557): [64-Bit] FP (alignment?) issues with Rvalues) + $(LI $(BUGZILLA 5564): [64-bit] loading of wrong constant byte value) + $(LI $(BUGZILLA 5565): [64-bit] Wrong Floating Point Results, Related to Mixing With size_t) + $(LI $(BUGZILLA 5566): [64-bit] More erratic FP results with size_t) + $(LI $(BUGZILLA 5579): Segfault on first call to GC after starting new thread) + $(LI $(BUGZILLA 5580): [64-bit] String switch statements broken in 64-bit mode) + $(LI $(BUGZILLA 5581): [64-bit] Wrong code with bitwise operations on bools) + $(LI $(BUGZILLA 5592): Previous definition different: __arrayExpSliceMulSliceAddass_d) + $(LI $(BUGZILLA 5595): Compiler crash on heavy std.algorithm use) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.052 + TITLE=Change Log: $(VER) diff --git a/changelog/2.053.dd b/changelog/2.053.dd new file mode 100644 index 0000000000..d5cf126b89 --- /dev/null +++ b/changelog/2.053.dd @@ -0,0 +1,154 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION May 12, 2011, =================================================, + + $(WHATSNEW + $(LI Added 64 bit tools to Linux) + $(LI Added FreeBSD support) + $(LI Renamed linux/bin to linux/bin32, added linux/bin64) + $(LI osx/lib32 renamed back to osx/lib) + $(LI Added some gc benchmark apps) + $(LI Move std.intrinsic to core.intrinsic) + $(LI Implemented $(I exception chaining), as described in TDPL for Posix.) + $(LI Added $(CODE parent) to $(CODE __traits) for QtD support) + $(LI Allow impure code inside debug conditionals) + $(LI Added cmpxchg16b, 64 bit bswap and movq instructions to internal assembler) + $(LI Added bindings for libcurl: etc.c.curl) + $(LI Added std.net.isemail) + $(LI Added std.parallelism) + $(LI Added support for positional parameter intervals, e.g. %1:3$s + prints the first three parameters using the 's' format specifier) + $(LI Added findSplit, findSplitBefore, findSplitAfter to std.algorithm; + improved walkLength) + $(LI Improved online documentation for std.algorithm) + $(LI Added roundRobin, takeOne, and takeNone to std.range; improved + stride) + $(LI Added unsigned to std.traits) + $(LI Removed std.iterator. Use either std.range.ElementType or std.range.ElementEncodingType + depending on what you're trying to do.) + $(LI $(BUGZILLA 2656): Remove octal literals) + $(LI $(BUGZILLA 4097): Error: can only declare type aliases within static if conditionals) + $(LI $(BUGZILLA 4360): Allow intrinsics in core.bitop to operate as intrinsics) + $(LI $(BUGZILLA 4833): dmd -od doesn't make it to optlink's command line for map files) + ) + $(RUNTIMEBUGSFIXED + $(LI $(BUGZILLA 5612): core.cpuid not implemented on 64) + $(LI $(BUGZILLA 1001): print stack trace (in debug mode) when program die) + $(LI $(BUGZILLA 5847): Threads started by core.thread should have same floating point state as main thread) + ) + $(LIBBUGSFIXED + $(LI $(BUGZILLA 4644): assertExceptionThrown to assert that a particular exception was thrown) + $(LI $(BUGZILLA 4944): Missing tzname even though we have tzset) + $(LI $(BUGZILLA 5451): Three ideas for RedBlackTree) + $(LI $(BUGZILLA 5474): unaryFun byRef is borked for custom parameter name) + $(LI $(BUGZILLA 5485): TLS sections handled incorrectly in FreeBSD) + $(LI $(BUGZILLA 5616): std.datetime: not cross-platform) + $(LI $(BUGZILLA 5654): BigInt returns ZERO with strings of single digit number with leading zeros) + $(LI $(BUGZILLA 5661): std.algorithm.move does not work on elaborate struct) + $(LI $(BUGZILLA 5731): std.datetime.SysTime prints UTC offsets backwards) + $(LI $(BUGZILLA 5761): std.datetime: Date.this(int day) conversion fails for Dec 30 of leap years) + $(LI $(BUGZILLA 5780): [patch] std.traits.hasIndirections incorrectly handles static arrays) + $(LI $(BUGZILLA 5781): std.datetime: On Windows, times off by one hour in some years due to DST rule changes) + $(LI $(BUGZILLA 5794): std.datetime StopWatch (and perhaps benchmark) examples need a small fix) + $(LI $(BUGZILLA 5928): Bigint modulo problem -- critical wrong-code bug) + ) + $(DMDBUGSFIXED + $(LI $(RED Note:) Although temporaries are destroyed now, they are not destroyed when + exceptions are thrown. This is scheduled to be fixed.) + $(LI $(BUGZILLA 2436): Unexpected OPTLINK termination EIP = 00425303 with /co) + $(LI $(BUGZILLA 3372): optlink silently mistreats object files with more than 16384 symbols) + $(LI $(BUGZILLA 4275): Unexpected optlink termination when 'export' attribute is missing) + $(LI $(BUGZILLA 4808): UNEXPECTED OPTLINK TERMINATION AT EIP=0042787B) + $(LI $(BUGZILLA 5670): Optlink 8.00.11 crash) + + $(LI $(BUGZILLA 937): C-style variadic functions broken) + $(LI $(BUGZILLA 1330): Array slicing does not work the same way in CTFE as at runtime) + $(LI $(BUGZILLA 1336): Inconsistent __traits usage) + $(LI $(BUGZILLA 1389): Can't use mixin expressions when start of a statement.) + $(LI $(BUGZILLA 1880): templates instantiated with non-constants should fail sooner) + $(LI $(BUGZILLA 2257): Template value parameters behave like alias parameters) + $(LI $(BUGZILLA 2414): enum is dynamically evaluated, yum) + $(LI $(BUGZILLA 2526): non-const initializer to constant accepted inside template) + $(LI $(BUGZILLA 2706): invalid template instantiation (and declaration?) is not rejected) + $(LI $(BUGZILLA 2733): Unclear semantics of template value parameters) + $(LI $(BUGZILLA 2841): char[] incorrectly accepted as a template value argument in D2) + $(LI $(BUGZILLA 2850): bad codegen for struct static initializers) + $(LI $(BUGZILLA 2990): TypeInfo.init() returns invalid array) + $(LI $(BUGZILLA 3086): TypeInfo opEquals returns incorrect results) + $(LI $(BUGZILLA 3214): Incorrect DWARF line number debugging information on Linux) + $(LI $(BUGZILLA 3271): Struct initializers silently fail) + $(LI $(BUGZILLA 3516): Destructor not called on temporaries) + $(LI $(BUGZILLA 3792): Regression(1.053) "non-constant expression" for a template inside a struct using a struct initializer) + $(LI $(BUGZILLA 3779): ["123"][0][$-1] causes __dollar unresolved in compile-time) + $(LI $(BUGZILLA 3801): CTFE: this.arr[i] cannot be evaluated at compile time for structs) + $(LI $(BUGZILLA 3835): ref foreach does not work in CTFE) + $(LI $(BUGZILLA 4033): Error: base class is forward referenced) + $(LI $(BUGZILLA 4050): [CTFE] array struct member slice update) + $(LI $(BUGZILLA 4051): [CTFE] array struct member item update) + $(LI $(BUGZILLA 4097): Error: can only declare type aliases within static if conditionals) + $(LI $(BUGZILLA 4140): Error: non-constant expression "hello"[1u..__dollar]) + $(LI $(BUGZILLA 4298): Constant array translated to unnecessary array literal creation) + $(LI $(BUGZILLA 4322): "void initializer has no value" on struct/union members initialized to "void") + $(LI $(BUGZILLA 4329): Do not show error messages that refer to __error) + $(LI $(BUGZILLA 4360): Allow intrinsics in core.bitop to operate as intrinsics) + $(LI $(BUGZILLA 4437): copy construction bug with "return this;") + $(LI $(BUGZILLA 4499): calls to @disabled postblit are emitted) + $(LI $(BUGZILLA 4543): Regression(1.054, 2.038) typedef causes circular definition and segfault) + $(LI $(BUGZILLA 4750): fail_compilation/fail225.d causes dmd to segv) + $(LI $(BUGZILLA 4815): CodeView: Global and Static symbols should have unmangled names) + $(LI $(BUGZILLA 4817): CodeView: Enum members should have simple names) + $(LI $(BUGZILLA 4833): dmd -od doesn't make it to optlink's command line for map files) + $(LI $(BUGZILLA 4917): Symbol conflict error message refers to aliased symbol instead of the alias) + $(LI $(BUGZILLA 5147): [CTFE] Return fixed-size matrix) + $(LI $(BUGZILLA 5268): Outdated windows GUI sample in Samples folder) + $(LI $(BUGZILLA 5362): checking $ in bracket is broken) + $(LI $(BUGZILLA 5482): Crash with align(0)) + $(LI $(BUGZILLA 5485): TLS sections handled incorrectly) + $(LI $(BUGZILLA 5524): [CTFE] Trouble with typesafe variadic function) + $(LI $(BUGZILLA 5647): [64-bit] Valgrind complains about illegal instruction) + $(LI $(BUGZILLA 5649): std.conv.parse faulty for floating point with -O -m32) + $(LI $(BUGZILLA 5657): Temporary object destruction) + $(LI $(BUGZILLA 5664): Cannot compile static synchronized member function.) + $(LI $(BUGZILLA 5694): va_arg doesn't work with idouble and ifloat) + $(LI $(BUGZILLA 5671): CTFE string concat problem) + $(LI $(BUGZILLA 5672): ICE(cod2.c): incorrect optimization of (long &1) == 1) + $(LI $(BUGZILLA 5678): new enum struct re-allocated at compile time) + $(LI $(BUGZILLA 5694): va_arg doesn't work with idouble and ifloat) + $(LI $(BUGZILLA 5706): Incorrect opcode prefix generated for x86_64 inline assembly) + $(LI $(BUGZILLA 5708): Incorrect string constant folding with -inline) + $(LI $(BUGZILLA 5717): 1.067 regression: appending Unicode char to string broken) + $(LI $(BUGZILLA 5722): Regression(2.052): Appending code-unit from multi-unit code-point at compile-time gives wrong result) + $(LI $(BUGZILLA 5735): non-scalar types implicitly converted to boolean) + $(LI $(BUGZILLA 5740): Unable to use this pointer in inline assembly) + $(LI $(BUGZILLA 5741): Add the SYSCALL and SYSRET opcodes to the inline assembler) + $(LI $(BUGZILLA 5798): Weakly pure function calls skipped inside a comma expression) + $(LI $(BUGZILLA 5812): Added constant fold optimisations for ^^ expressions) + $(LI $(BUGZILLA 5840): Cannot assign to an array member of struct in CTFE) + $(LI $(BUGZILLA 5852): CTFE: wrong code for string[] ~= const(string)) + $(LI $(BUGZILLA 5858): Import doesn't accept const string as argument) + $(LI $(BUGZILLA 5865): __dollar cannot be read at compile time) + $(LI $(BUGZILLA 5890): ICE and wrong scope problem for 2nd argument in static assert with DMD on git master) + $(LI $(BUGZILLA 5916): DMD: bad message for incorrect operands error) + $(LI $(BUGZILLA 5938): ICE ztc\symbol.c 1043) + $(LI $(BUGZILLA 5940): Cannot create arrays of std.algorithm.map) + $(LI $(BUGZILLA 5965): [2.053 beta] map rejects a predicate with anon-func and nested func) + $(LI $(BUGZILLA 5966): [2.053 beta][CTFE] Stack overflow on trivial func) + $(LI $(BUGZILLA 5972): CTFE: Can't assign to elements of arrays of slices) + $(LI $(BUGZILLA 5975): [2.053 beta][CTFE] ICE: 'global.errors' on line 1416 in file 'constfold.c') + $(LI $(BUGZILLA 5976): "variable used before set" with foreach with ref + scope(failure) + structure method + -O -inline) + $(LI $(BUGZILLA 5982): [2.053 beta] std.iterator gone, but no mention of the change) + $(LI $(BUGZILLA 5987): mydll sample doesn't compile) + $(LI Clarify tuple index out of bounds error message) + $(LI Add 64 version of xchg and jmp to inline assembler. Fixed 64 bit LEA) + $(LI CTFE: Generate error messages for accessing null arrays) + $(LI Fix optimizer bug with to!float("123e2")) + $(LI Fix spelling of $(CODE cmpxchgb8)) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.053 + TITLE=Change Log: $(VER) diff --git a/changelog/2.054.dd b/changelog/2.054.dd new file mode 100644 index 0000000000..d9379c2d6e --- /dev/null +++ b/changelog/2.054.dd @@ -0,0 +1,184 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 10, 2011, =================================================, + + $(WHATSNEW + $(LI Implement @safe) + $(LI Implement @property) + $(LI Automatic inference for @safe, pure, nothrow) + $(LI Allow labelled break and continue in CTFE) + $(LI Warn about switch case fallthrough) + $(LI Pointers are now supported in CTFE) + $(LI Heap-allocated structs are now supported in CTFE) + $(LI Added SSSE3 instructions to inline assembler) + $(LI Change from warning to deprecated: non-final switch statements must have a default statement) + $(LI Change from warning to deprecated: function is hidden by function) + $(LI Add warning about switch case fallthrough) + $(LI Add warning about calling pure nothrow functions and ignoring the result) + $(LI Allow associative arrays with key of type bool) + $(LI Added inference for purity and safety) + $(LI Change win32 dmd to not emit a map file unless asked for with -map) + $(LI Added $(B -property) switch) + $(LI $(BUGZILLA 5823): @property call syntax restriction not implemented) + + $(LI Added core.sys.posix.netdb) + $(LI For functions which have a version which takes a core.time.Duration + and another version which takes an integral value, the version which + takes an integral value is now scheduled for deprecation.) + + $(LI std.array.insertInPlace supports inserting of multiple ranges/elements in one go) + $(LI Added std.array.uninitializedArray and std.array.minimallyInitializedArray) + $(LI Various functions in std.string were renamed to match Phobos' + naming conventions and be properly camelcased. The old names + are still there but have been scheduled for deprecation.) + $(LI Various functions in std.uni were renamed so that they don't have + "Uni" in their name, since it was decided that it was not desirable to + repeat a module's name in its functions' names. The old names + are still there but have been scheduled for deprecation.) + $(LI std.ctype has been scheduled for deprecation. std.ascii has been + added to replace it.) + $(LI Major performance improvements for std.algorithm.sort) + $(LI std.string.atoi has been removed; replace it with std.conv.to!int) + $(LI Switched to using posix.mak instead of various .mak files) + ) + $(RUNTIMEBUGSFIXED + $(LI $(BUGZILLA 4323): std.demangle incorrectly handles template floating point numbers) + $(LI $(BUGZILLA 5272): Postblit not called on copying due to array append) + $(LI $(BUGZILLA 5956): Undocumented mangling of struct value) + $(LI $(BUGZILLA 6135): Thread/GC interaction bug on OS X) + ) + $(LIBBUGSFIXED + $(LI $(BUGZILLA 2108): regexp.d: The greedy dotstar isn't so greedy) + $(LI $(BUGZILLA 3136): Incorrect and strange behavior of std.regexp.RegExp if using a pattern with optional prefix and suffix longer than 1 char) + $(LI $(BUGZILLA 3457): rdmd fails silently in a particular setup where the compiler is not the expected) + $(LI $(BUGZILLA 3479): writef/writefln: positional precision not working) + $(LI $(BUGZILLA 3564): Rdmd failing to link external C libraries) + $(LI $(BUGZILLA 3752): File.byLine fetches lines in a confusing manner) + $(LI $(BUGZILLA 4367): std.regex: Captures is not a random access range) + $(LI $(BUGZILLA 4574): std.regex: breaks with empy string regex) + $(LI $(BUGZILLA 4608): std.string.chomp documentation mismatch implementation) + $(LI $(BUGZILLA 5019): In std.regex, empty capture at end of string causes error) + $(LI $(BUGZILLA 5059): String assignment in foreach loop breaks immutability) + $(LI $(BUGZILLA 5458): scope for function parameters is not documented) + $(LI $(BUGZILLA 5511): std.regex optional capture with no-match cause error) + $(LI $(BUGZILLA 5598): rdmd does not fail on invalid filename) + $(LI $(BUGZILLA 5673): Add lookahead and forgetful matching support std.regex) + $(LI $(BUGZILLA 5705): Swapping identical struct with hasElaborateAssign causes "overlapping array copy" exception) + $(LI $(BUGZILLA 5836): std.typetuple.staticIndexOf's example code missing %s in call to writefln) + $(LI $(BUGZILLA 5857): std.regex (...){n,m} is bogus when (...) contains repetitions) + $(LI $(BUGZILLA 5869): std.thread needs to be removed) + $(LI $(BUGZILLA 6026): DLL example needs update due to missing core.dll_helper) + $(LI $(BUGZILLA 6076): regression, std.regex: "c.*|d" matches "mm") + $(LI $(BUGZILLA 6101): Documentation for dead modules still distributed with DMD) + $(LI $(BUGZILLA 6113): singletons in std.datetime are not created early enough) + $(LI $(BUGZILLA 6193): Appender.clear() functionality or documentation) + ) + $(DMDBUGSFIXED + $(LI $(BUGZILLA 693): 'this' can't be used as an alias parameter for a mixin) + $(LI $(BUGZILLA 1373): typeof(func).stringof fails when func has parameters.) + $(LI $(BUGZILLA 1411): ref Tuple should transform to Tuple of refs) + $(LI $(BUGZILLA 1570): Wrong return for address operator) + $(LI $(BUGZILLA 2180): filename error with #line) + $(LI $(BUGZILLA 2521): Not possible to return immutable value by ref) + $(LI Temp destructors now called if exception is thrown) + $(LI $(BUGZILLA 2625): Creating new struct with literal bypasses immutability of members if struct is in array) + $(LI $(BUGZILLA 3147): Incorrect value range propagation for addition) + $(LI $(BUGZILLA 3359): Cannot parse pure/const/immutable functions with inferred return type) + $(LI $(BUGZILLA 3445): partial fix) + $(LI $(BUGZILLA 3511): ref return property confused with property setter) + $(LI $(BUGZILLA 3632): modify float is float to do a bitwise compare) + $(LI $(BUGZILLA 3688): Can't have declaration with assignment to const/immutable inside if condition) + $(LI $(BUGZILLA 3722): A method without an in contract should always succeed, even if overridden) + $(LI $(BUGZILLA 3799): isStaticFunction trait evaluates to true for non-static nested functions) + $(LI $(BUGZILLA 4031): Should be able to access const value-type globals from pure functions) + $(LI $(BUGZILLA 4040): const/immutable on the right in auto return class methods) + $(LI $(BUGZILLA 4063): [CTFE] key not found in AA gives bad error message) + $(LI $(BUGZILLA 4065): [CTFE] AA "in" operator doesn't work) + $(LI $(BUGZILLA 4107): Duplicate documentation for member function templates) + $(LI $(BUGZILLA 4132): pointer arithmetic accepted in @safe functions) + $(LI $(BUGZILLA 4170): Missing line number on compile-time array index) + $(LI $(BUGZILLA 4258): "auto ref" doesn't work in one or more cases) + $(LI $(BUGZILLA 4448): [CTFE] labeled break doesn't work in CTFE) + $(LI $(BUGZILLA 4494): ICE(cod1.c) Array literal filled with results of void function) + $(LI $(BUGZILLA 4633): typeof({return 1;}()) declaration fails if inside main) + $(LI $(BUGZILLA 4661): Array Literal Incompatible Type Error Msg Should Include Line Number) + $(LI $(BUGZILLA 4706): Overloading auto return w/ non-auto return = strange error msg) + $(LI $(BUGZILLA 4745): Non-uniform handling of commas in static initialization of structs) + $(LI $(BUGZILLA 4885): Uninitialize Pointers Allowed in @safe code) + $(LI $(BUGZILLA 4910): [CTFE] Cannot evaluate a function that has failed at once) + $(LI $(BUGZILLA 4963): ICE(type.c:320) for struct append where T.sizeof $(LESS) 3) + $(LI $(BUGZILLA 4969): nothrow check can't handle multiple catches) + $(LI $(BUGZILLA 5088): Cannot cast const(int) to long in @safe function) + $(LI $(BUGZILLA 5258): [CTFE] Stack overflow with struct by ref) + $(LI $(BUGZILLA 5284): Array ops punch through const system) + $(LI $(BUGZILLA 5327): Creating new struct with literal bypasses immutability of members of members of the struct) + $(LI $(BUGZILLA 5396): [CTFE] Invalid code with nested functions in CTFE) + $(LI $(BUGZILLA 5415): @Safe functions not working) + $(LI $(BUGZILLA 5497): -- now produces error message instead of wrong code) + $(LI $(BUGZILLA 5551): opUnary-opBinary conflict) + $(LI $(BUGZILLA 5574): Struct destructor freaks out when an array of struct with single element is instantiated inside a class) + $(LI $(BUGZILLA 5615): [CTFE] std.string.indexOf broken at compile time) + $(LI $(BUGZILLA 5633): [CTFE] ICE(constfold.c): is expression with struct, struct pointer, array literal...) + $(LI $(BUGZILLA 5657): Temporary object destruction) + $(LI $(BUGZILLA 5659): Conditional operator, array literal, and std.traits.CommonType return a wrong common type) + $(LI $(BUGZILLA 5676): [CTFE] segfault using tuple containing struct that has opAssign) + $(LI $(BUGZILLA 5682): [CTFE] Silently wrong result possibly related to operator overloading and expression order) + $(LI $(BUGZILLA 5693): Segfault with address of template struct opCall) + $(LI $(BUGZILLA 5708): [CTFE] Incorrect string constant folding with -inline) + $(LI $(BUGZILLA 5771): Template constructor and auto ref do not work) + $(LI $(BUGZILLA 5819): DMD doesn't error/warn about illegal asm for 64bit mode) + $(LI $(BUGZILLA 5845): Regression(2.041) [CTFE] "stack overflow" with recursive ref argument) + $(LI $(BUGZILLA 5856): overloading on const doesn't work for operator overload) + $(LI $(BUGZILLA 5859): Declaration inside if condition doesn't call destructor) + $(LI $(BUGZILLA 5861): Wrong filename in error message when an invalid delegate in a template parameter is typeof()-ed) + $(LI $(BUGZILLA 5885): wrong codegen for OPu32_d) + $(LI $(BUGZILLA 5897): unrelated struct type casting should ignite construction) + $(LI $(BUGZILLA 5936): Invalid code with nested functions in CTFE) + $(LI $(BUGZILLA 5946): failing lookup 'this' from function in template) + $(LI $(BUGZILLA 5954): [CTFE] enum structs with ctor) + $(LI $(BUGZILLA 5959): Return by reference with nested function should be allowed) + $(LI $(BUGZILLA 5962): Template function declaration with prefixed storage class and auto occurs conflict) + $(LI $(BUGZILLA 5963): iasm does not accept 64bit integer literal) + $(LI $(BUGZILLA 6001): [CTFE] ICE(interpret.c) mutating ref array) + $(LI $(BUGZILLA 6015): [CTFE] Strange behavior of assignment appears in a situation) + $(LI $(BUGZILLA 6049): [CTFE] Array literals of structs with invariant() are wrong) + $(LI $(BUGZILLA 6052): [CTFE] Struct elements in an array are treated like reference type) + $(LI $(BUGZILLA 6053): [CTFE] Two ICEs involving pointers (dereference and assign; pointer variable on stack)) + $(LI $(BUGZILLA 6054): [CTFE] ICE when returning a returned compile-time associative array containing a key of an idup-ed array literal) + $(LI $(BUGZILLA 6059): Incompatible types in array literal shows __error and error) + $(LI $(BUGZILLA 6072): [CTFE] Regression(git master): Cannot declare variable inside an 'if' condition) + $(LI $(BUGZILLA 6075): Cannot set value to associative array from a weakly-pure function when the value type has a (pure) opAssign) + $(LI $(BUGZILLA 6077): [CTFE] Cannot append null array to null array.) + $(LI $(BUGZILLA 6078): [CTFE] ICE on foreach over array struct member which is null) + $(LI $(BUGZILLA 6079): [CTFE] Array index out of bound detection is off-by-one) + $(LI $(BUGZILLA 6090): DDoc parenthesis escape issues.) + $(LI $(BUGZILLA 6100): [CTFE] Regression: struct return values wrong if used in array initializer) + $(LI $(BUGZILLA 6109): 'nothrow' does not check slice indices) + $(LI $(BUGZILLA 6111): Escaping reference to local variable not detected) + $(LI $(BUGZILLA 6119): Assertion failure: '0' on line 1118 in file 'glue.c') + $(LI $(BUGZILLA 6120): [CTFE] ICE on calling constructor of template struct with -inline in function/delegate literal.) + $(LI $(BUGZILLA 6123): [CTFE] Cannot call a template member method inside delegate/function literal with -inline.) + $(LI $(BUGZILLA 6137): [CTFE] Foreach on semantically wrong initialized array crashes the compiler) + $(LI $(BUGZILLA 6145): Meaningless second error message for complex size of static array) + $(LI $(BUGZILLA 6150): runnable/testsocket.d) + $(LI $(BUGZILLA 6158): winsamp and dhry samples need an update) + $(LI $(BUGZILLA 6161): iasm opcode family Jcc use absolute address instead of relative for functions) + $(LI $(BUGZILLA 6164): [CTFE] Local arrays in a recursive local function behave funny) + $(LI $(BUGZILLA 6198): [GSoC] ICE(e2ir.c) With circular import) + $(LI $(BUGZILLA 6229): %= and /= no longer work on char type) + $(LI $(BUGZILLA 6230): Member functions can no longer be weakly pure) + $(LI $(BUGZILLA 6234): 64-bit array append generates inline code to copy new data, but does not call postblit) + $(LI $(BUGZILLA 6241): test sdtor.d on osx not catching) + $(LI $(BUGZILLA 6242): Disallow inoperant "in" contracts) + $(LI $(BUGZILLA 6264): ICE on testing opSlice in static if) + $(LI $(BUGZILLA 6267): Can't increment alias this'd struct from ref return) + $(LI $(BUGZILLA 6279): Regression(2.054 beta): array-vararg with pointer type not working in safe code) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.054 + TITLE=Change Log: $(VER) diff --git a/changelog/2.055.dd b/changelog/2.055.dd new file mode 100644 index 0000000000..428e69064a --- /dev/null +++ b/changelog/2.055.dd @@ -0,0 +1,176 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 4, 2011, =================================================, + + $(WHATSNEW + $(LI Added $(LINK2 http://www.digitalmars.com/ctg/dman.html, dman)) + $(LI Add support for Mac OS X 10.7 Lion) + $(LI Add protection to json output) + $(LI Add SSE4.1 and SSE4.2 assembly instructions) + $(LI $(BUGZILLA 4375): Require explicit braces when 'else' is ambiguous) + + $(LI std.algorithm.copy now specializes on arrays for 10-80x improved + performance.) + $(LI std.path has been rewritten from scratch and has a completely new API.) + $(LI std.utf.toUTFz allows you to get a zero-terminated string of any + character type and of any type of mutability.) + $(LI Added symlink and readLink to std.file for Posix systems.) + $(LI Values for GDC and LDC were added to std.compiler.Vendor.) + $(LI Added functions to std.bitswap for generically handling swapping + endianness.) + $(LI Added std.parallelism.TaskPool.workerIndex.) + $(LI Added buffer recycling overload of std.parallelism.asyncBuf) + $(LI std.math.tgamma, lgamma, erf, and erfc are now deprecated. The + equivalent functions in std.mathspecial should be used instead.) + $(LI The names of the values of std.mmfile.Mode, std.system.Endian, + std.traits.FunctionAttributes, std.traits.ParameterStorageClass, + and std.traits.Variadic were changed to match Phobos' naming conventions.) + $(LI std.range: Added indexed and chunks) + $(LI std.string.translate has been updated to work with unicode. As a + result, its signature has been changed. The old version and + std.string.maketrans have been scheduled for deprecation.) + $(LI std.string.tr has been updated so that it works with any string type.) + $(LI std.conv.parse works for associative array and static array) + $(LI std.format: Improvement of formatValue and unformatValue. + They now works for associative array, consider element escaping, + and treat range format spec more properly.) + $(LI std.complex: added sin(), cos(), sqrt()) + $(LI md5: 1.4X speedup) + ) + $(RUNTIMEBUGSFIXED + $(LI $(BUGZILLA 5967): Mangling of ArgClose for variadic function is swapped) + $(LI $(BUGZILLA 6493): Source code for the doc of core.time points to std.datetime.) + $(LI $(BUGZILLA 6466): core.demangle incorrect demangling of variables) + ) + $(LIBBUGSFIXED + $(LI Unlisted bug: std.range.transversal should have length) + $(LI $(BUGZILLA 3890): Bad writeln of a nested struct) + $(LI $(BUGZILLA 4500): scoped moves class after calling the constructor) + $(LI $(BUGZILLA 4977): cannot use nothrow or pure with Rebindable) + $(LI $(BUGZILLA 5237): writefln doesn't respect Complex.toString) + $(LI $(BUGZILLA 5645): std.range.drop()) + $(LI $(BUGZILLA 5825): write is calling a deprecated function) + $(LI $(BUGZILLA 6040): std.cpuid and core.cpuid return different values for some methods) + $(LI $(BUGZILLA 6064): std.array.join is unnecssarily slow for strings) + $(LI $(BUGZILLA 6194): [GSoC] Destructor gets called on object before it is copied when calling writeln()) + $(LI $(BUGZILLA 6261): [2.054 beta regression] Regex cannot take a char[]) + $(LI $(BUGZILLA 6301): Cannot 'zip'/'retro'/'stride' etc. a range having 'ulong' length.) + $(LI $(BUGZILLA 6377): std.conv.to should check range when changing signedness) + $(LI $(BUGZILLA 6424): std.traits.hasElaborateAssign is limited) + $(LI $(BUGZILLA 6448): writef("%05d", BigInt) problem) + $(LI $(BUGZILLA 6514): CTFE dot product) + $(LI $(BUGZILLA 6587): std.parallelism's Task cannot handle immutable values) + $(LI $(BUGZILLA 6606): RefCounted doesn't work with unions due to use of format) + $(LI $(BUGZILLA 6608): Tuple field is not escaped) + ) + $(DMDBUGSFIXED + $(LI $(BUGZILLA 1471): Linker error on template function. Error 42: Symbol Undefined ...) + $(LI $(BUGZILLA 1567): call to private super-constructor should not be allowed) + $(LI $(BUGZILLA 1684): offsetof does not work, adding cast is workaround) + $(LI $(BUGZILLA 1904): wrong protection lookup for private template functions) + $(LI $(BUGZILLA 2156): [] and null should be accepted where a compile-time string is required) + $(LI $(BUGZILLA 2234): __traits(allMembers) returns incorrect results for mixin and template alias members of an aggregate) + $(LI $(BUGZILLA 2245): Bug with overloaded, mixin template functions in classes) + $(LI $(BUGZILLA 2246): Regression(2.046, 1.061): Specialization of template to template containing int arguments fails) + $(LI $(BUGZILLA 2540): super can not be using in alias statement) + $(LI $(BUGZILLA 2634): Function literals are non-constant.) + $(LI $(BUGZILLA 2355): is() doesn't resolve aliases before template matching) + $(LI $(BUGZILLA 2579): Template function accepting a delegate with in argument doesn't compile) + $(LI $(BUGZILLA 2774): Functions-as-properties makes it impossible to get the .mangleof a function) + $(LI $(BUGZILLA 2777): alias this doesn't forward __dollar and slice op.) + $(LI $(BUGZILLA 2781): alias this doesn't work with foreach) + $(LI $(BUGZILLA 2787): Members found in an 'alias this' are not implicitly accessible in methods) + $(LI $(BUGZILLA 2941): Wrong code for inline asm because CPU type is set too late) + $(LI $(BUGZILLA 3268): can't compare pointer to functions when one is const) + $(LI $(BUGZILLA 3273): Regression(2.031): struct invariant + dtor fails to compile (no line number)) + $(LI $(BUGZILLA 3512): dchar iteration over string in CTFE fails) + $(LI $(BUGZILLA 3661): ^^ not supported in array operations.) + $(LI $(BUGZILLA 3797): Regression(2.038): Implicit conversion between incompatible function pointers) + $(LI $(BUGZILLA 4021): [CTFE] AA rehash) + $(LI $(BUGZILLA 4099): Inconsistent behaviour of ++/-- when mixing opUnary and 'alias this'.) + $(LI $(BUGZILLA 4444): Cannot index built-in array with expression tuple) + $(LI $(BUGZILLA 4460): Regression(2.036) ICE(e2ir.c) when compiling foreach over associative array literal) + $(LI $(BUGZILLA 4682): [CTFE] Run-time Vs Compile-time of int.min % -1) + $(LI $(BUGZILLA 4773): Rebindable should be castable to bool) + $(LI $(BUGZILLA 4837): ICE(constfold.c) CTFE with >>>=) + $(LI $(BUGZILLA 4984): Recursive template constraint results in dmd running out of memory) + $(LI $(BUGZILLA 5046): Wrong type of implicit 'this' in struct/class templates) + $(LI $(BUGZILLA 5081): Pure functions as initializers for immutable structures) + $(LI $(BUGZILLA 5188): alias this and compare expression generates wrong code) + $(LI $(BUGZILLA 5239): optimizer misreports an used before set error) + $(LI $(BUGZILLA 5373): Regression (2.051) CTFE and std.string.replace() causes "Bad binary function q{a == b}..) + $(LI $(BUGZILLA 5440): ICE(template.c): when struct AssociativeArray is missing from object.d) + $(LI $(BUGZILLA 5585): bad debug line number info for return statements with enumerator expressions) + $(LI $(BUGZILLA 5745): Missing error line number with lazy argument) + $(LI $(BUGZILLA 5750): Allow pure functions to have lazy arguments) + $(LI $(BUGZILLA 5777): Move semantics require full spec NRVO) + $(LI $(BUGZILLA 5785): Lexing or Parsing issue with UFCS) + $(LI $(BUGZILLA 5790): 'Error: variable result used before set' when -release -inline -O) + $(LI $(BUGZILLA 5799): Address-of operator fails on nested conditional operator expression) + $(LI $(BUGZILLA 5936): Regression(2.050): Segfault when forward-referencing pure auto-return member function with parameter.) + $(LI $(BUGZILLA 5953): Too many trailing commas are accepted) + $(LI $(BUGZILLA 6097): SSSE3 not working with MMX instructions) + $(LI $(BUGZILLA 6215): LLVM-compiled DMD segfaults due to mem.c alignment issues) + $(LI $(BUGZILLA 6220): Regression(2.053) static foreach over a string[] no longer produces directly usable strings) + $(LI $(BUGZILLA 6228): Regression(2.053) ICE(e2ir.c) on {auto x = (*ptr) ^^ y} with const integer types) + $(LI $(BUGZILLA 6230): Member functions can no longer be weakly pure) + $(LI $(BUGZILLA 6250): [CTFE] Crash when swapping two pointers to arrays.) + $(LI $(BUGZILLA 6265): Pure-inference failed when calling other pure functions) + $(LI $(BUGZILLA 6270): XMMREGS not preserved on indirect function call) + $(LI $(BUGZILLA 6276): [CTFE] Strange behavior of using ~= operator twice) + $(LI $(BUGZILLA 6280): [CTFE] Cannot put 'in' expression of AA in an 'if' condition) + $(LI $(BUGZILLA 6281): [CTFE] A null pointer '!is null' returns 'true'.) + $(LI $(BUGZILLA 6282): [CTFE] ICE when dereferencing a pointer to reference type from 'in' of an AA) + $(LI $(BUGZILLA 6283): [CTFE][Regression 2.054] Failed to assign to AA using a constness-changed array as key) + $(LI $(BUGZILLA 6284): [Regression 2.054] 'pure' does not work with 'with' statement) + $(LI $(BUGZILLA 6286): Regression(2.054): Static arrays can not be assigned from const(T)[N] to T[N]) + $(LI $(BUGZILLA 6293): [Regression 2.054] The expression x.y makes the function impure when the 'x' part is not just a variable) + $(LI $(BUGZILLA 6295): [Regression 2.054] Segfault in checkPurity() of template value parameter) + $(LI $(BUGZILLA 6306): Regression(2.054): [CTFE] Strange behavior of indirect recursive call in CTFE) + $(LI $(BUGZILLA 6308): Destruction of temporaries on exception causes unhandled access violation) + $(LI $(BUGZILLA 6316): Regression(2.054): Class downcast is rejected in @safe code) + $(LI $(BUGZILLA 6317): ICE on struct literal of nested struct) + $(LI $(BUGZILLA 6331): [CTFE] Cannot evaluate SliceExp on if condition) + $(LI $(BUGZILLA 6337): [CTFE] ICE when touching member variable of struct during CTFE) + $(LI $(BUGZILLA 6344): [CTFE] Assertion Failure in interpret.c when create an empty slice from null pointer) + $(LI $(BUGZILLA 6351): Regression(2.054) Segfault: Vararg delegate as template param) + $(LI $(BUGZILLA 6355): Template constructor cannot initialize non-mutable field) + $(LI $(BUGZILLA 6366): alias this doesn't work with foreach range.front) + $(LI $(BUGZILLA 6369): alias this doesn't work with initializer) + $(LI $(BUGZILLA 6374): [CTFE] Cannot subscript using pointer to array) + $(LI $(BUGZILLA 6375): [CTFE] Segfault when using std.array.appender with an initial array) + $(LI $(BUGZILLA 6386): [CTFE] ICE on pointer casting) + $(LI $(BUGZILLA 6389): Segfault(dsymbol.c): deprecated @disable) + $(LI $(BUGZILLA 6399): [CTFE] struct member array.length -= x doesn't work, while array[0..$-x] works) + $(LI $(BUGZILLA 6404): Cannot check ref-ness of auto ref parameter in template constraint) + $(LI $(BUGZILLA 6418): [CTFE] Cannot call a struct member function with name 'length'.) + $(LI $(BUGZILLA 6420): [CTFE] ICE on dereference-assigning to a pointer casted from a literal ) + $(LI $(BUGZILLA 6429): Nested function error in reduce) + $(LI $(BUGZILLA 6433): Meta-Bug AA type propagation) + $(LI $(BUGZILLA 6434): opDispatch must be considered before alias this.) + $(LI $(BUGZILLA 6491): Fully qualified values in default arguments of non-template functions are generated with an extra 'module' keyword) + $(LI $(BUGZILLA 6499): [GSoC] Destructor not called on object returned by method.) + $(LI $(BUGZILLA 6505): Wrong code for expression involving 8 floats, only with -O) + $(LI $(BUGZILLA 6508): alias this doesn't work with AssignExp rhs) + $(LI $(BUGZILLA 6510): [CTFE] "internal error: illegal stack value" when compiled with -inline) + $(LI $(BUGZILLA 6511): [CTFE] Array op gives wrong result) + $(LI $(BUGZILLA 6512): [CTFE] new T[][] doesn't work) + $(LI $(BUGZILLA 6516): Regression(2.055 beta) [CTFE] ICE(constfold.c) involving new dchar[]) + $(LI $(BUGZILLA 6517): [CTFE] ptr++ doesn't work but ++ptr does) + $(LI $(BUGZILLA 6546): alias this + IdentityExpression doesn't work) + $(LI $(BUGZILLA 6556): ICE for ImportStatement in DebugStatement) + $(LI $(BUGZILLA 6558): [CTFE] UTF-decoding foreach gives wrong index (1-indexed)) + $(LI $(BUGZILLA 6561): alias this + undefined symbol should cause error) + $(LI $(BUGZILLA 6563): wrong code when using at least 8 XMM regs) + $(LI $(BUGZILLA 6577): 'Cannot initialize member' error line number) + $(LI $(BUGZILLA 6601): Regression(2.053): CTFE segfault taking address of function template) + $(LI $(BUGZILLA 6602): Invalid template instantiations leaked by is(typeof())/__traits(compiles, )/Type::trySemantic) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.055 + TITLE=Change Log: $(VER) diff --git a/changelog/2.056.dd b/changelog/2.056.dd new file mode 100644 index 0000000000..fba2665ebb --- /dev/null +++ b/changelog/2.056.dd @@ -0,0 +1,120 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 26, 2011, =================================================, + + $(WHATSNEW + $(LI add -gs compiler switch) + $(LI $(BUGZILLA 3194): invariant should be checked at the beginning and end of protected functions) + $(LI $(BUGZILLA 5399): Return the result of a nonvoid function in a void function) + $(LI $(BUGZILLA 6752): Add separate option to control stack frame generation) + $(LI std.exception: enforce/enforceEx now can use in @safe pure function.) + $(LI Added optional KeepTerminator param to std.string.splitLines.) + $(LI Added std.string.outdent.) + $(LI std.utf: More @safe and pure.) + $(LI std.windows.registry now use *W functions in order to deal properly with Unicode.) + ) + $(RUNTIMEBUGSFIXED + $(LI $(BUGZILLA 5967): Mangling of ArgClose for variadic function is swapped) + $(LI $(BUGZILLA 6493): Source code for the doc of core.time points to std.datetime.) + $(LI $(BUGZILLA 6466): core.demangle incorrect demangling of variables) + ) + $(LIBBUGSFIXED + $(LI $(BUGZILLA 5522): std.range.zip fails on arrays of Object.) + $(LI $(BUGZILLA 6009): std/container disabled on freebsd/64) + $(LI $(BUGZILLA 6160): std.conv.to: Ignore _ to match the rest of D) + $(LI $(BUGZILLA 6181): assert fails in datetime.d while runining Phobos unittest) + $(LI $(BUGZILLA 6258): std.conv.to!real("-") fetches the front of an empty array.) + $(LI $(BUGZILLA 6275): Const values in tuples) + $(LI $(BUGZILLA 6288): std.conv.to removes const/immutable when converting a class) + $(LI $(BUGZILLA 6609): std.conv.parse!Integer should consider sign when radix == 10) + $(LI $(BUGZILLA 6634): std.path.globMatch throws wrong assertion) + $(LI $(BUGZILLA 6640): More formatting consistency between string and range of char) + $(LI $(BUGZILLA 6761): Strange behavior of RedBlackTree causing a dangling pointer) + $(LI $(BUGZILLA 6819): BigInt ^^ fails for some big numbers (powers)) + ) + $(DMDBUGSFIXED + $(LI $(BUGZILLA 546): Error message for accessing a deprecated variable is doubled) + $(LI $(BUGZILLA 1339): Invariant/const-ness is broken by built-in array properties sort and reverse) + $(LI $(BUGZILLA 1891): Array-concatenation of T* and T*[] produces corrupted result) + $(LI $(BUGZILLA 1993): Error calling vararg delegate with null) + $(LI $(BUGZILLA 2315): DMD Stack Overflow on unwanted ctfe recursion) + $(LI $(BUGZILLA 2553): Excess attribute propagation for interfaces) + $(LI $(BUGZILLA 2361): delete is allowed on invariant references.) + $(LI $(BUGZILLA 2737): Nonsensical Error Message on Unsafe .idup) + $(LI $(BUGZILLA 2740): Template Mixins do not work as advertised) + $(LI $(BUGZILLA 2953): tuple.length rejected as a tuple parameter in a static foreach) + $(LI $(BUGZILLA 3069): Array literals do not implicitly cast to void[]) + $(LI $(BUGZILLA 3133): Compiler does not check that static array casts are legal) + $(LI $(BUGZILLA 3180): Covariance of delegates/function pointers) + $(LI $(BUGZILLA 3550): array.dup violates const/invariant without a cast.) + $(LI $(BUGZILLA 3659): Too much exegesis on opEquals) + $(LI $(BUGZILLA 3748): inout does not work properly) + $(LI $(BUGZILLA 4022): [CTFE] AA get) + $(LI $(BUGZILLA 4197): ICE(glue.c): error in forward-referenced in/out contract) + $(LI $(BUGZILLA 4206): type accepted as enum initializer) + $(LI $(BUGZILLA 4237): Typedefs of the same name cause initializer conflict) + $(LI $(BUGZILLA 4269): Regression(2.031): invalid type accepted if evaluated while errors are gagged) + $(LI $(BUGZILLA 4284): empty string[] alias lacks .length in a template) + $(LI $(BUGZILLA 5453): ICE(statement.c): invalid switch statement forward referenced by CTFE) + $(LI $(BUGZILLA 5696): Templates typetuple iteration) + $(LI $(BUGZILLA 5703): std.intrinsic. and core.bitop.bsf, bsr and bswap should be CTFE-able) + $(LI $(BUGZILLA 5886): Template this parameter cannot be made implicit, when other parameters are explicitly given) + $(LI $(BUGZILLA 5932): Internal error: s2ir.c 339) + $(LI $(BUGZILLA 6062): segv in dmd/64 with assoc array literals) + $(LI $(BUGZILLA 6073): Cannot pass __traits(parent, ...) as a template parameter if it is a module) + $(LI $(BUGZILLA 6084): Impossible to instantiate local template with TypeTuple-foreach iterator variable.) + $(LI $(BUGZILLA 6087): typeof(this) doesn't work outside member function) + $(LI $(BUGZILLA 6139): Duplicate error message on compile-time out of bounds array index) + $(LI $(BUGZILLA 6289): Make slices of const/immutable arrays mutable (but keep the elements const/immutable)) + $(LI $(BUGZILLA 6296): ICE(glue.c): invalid template instantiated in is(typeof()).) + $(LI $(BUGZILLA 6352): Regression(2.054) Implicit pure/nothrow/@safe messes up delegate arrays) + $(LI $(BUGZILLA 6360): @property is doubled in di files when used with auto) + $(LI $(BUGZILLA 6404): Cannot check ref-ness of auto ref parameter in template constraint) + $(LI $(BUGZILLA 6488): DMD compiler bug) + $(LI $(BUGZILLA 6518): break inside a static foreach inside a switch) + $(LI $(BUGZILLA 6529): writeln(const array of enums) too) + $(LI $(BUGZILLA 6584): ICE on large version number/debug level) + $(LI $(BUGZILLA 6596): Error message with not extern(C) function) + $(LI $(BUGZILLA 6599): Segfault: invalid expression in initializer) + $(LI $(BUGZILLA 6630): Assigning null to class with nested alias this class is misinterpreted) + $(LI $(BUGZILLA 6656): static alias this broken in 2.055) + $(LI $(BUGZILLA 6661): Templates instantiated only through is(typeof()) shouldn't cause errors) + $(LI $(BUGZILLA 6665): Regression(2.055) ICE(cg87.c): static double inside closure) + $(LI $(BUGZILLA 6672): [CTFE] ICE on compile time std.algorithm.sort) + $(LI $(BUGZILLA 6674): Regression(2.055) mixin and __traits(allMembers) generates incorrect result) + $(LI $(BUGZILLA 6675): Regression(2.054) ICE(glue.c) template parameter deduction with errors gagged) + $(LI $(BUGZILLA 6682): Template function that has lazy parameter is not inferred as pure) + $(LI $(BUGZILLA 6690): Using lazy parameter should be inferred as @safe) + $(LI $(BUGZILLA 6691): static constructor inside template cannot initialize immutable template members) + $(LI $(BUGZILLA 6693): [CTFE] Cannot set value to nested AA) + $(LI $(BUGZILLA 6695): typeof(this) does not take into account const/immutable attributes inside member functions) + $(LI $(BUGZILLA 6698): Regression(2.053): segfault with naked asm in inner function) + $(LI $(BUGZILLA 6700): Regression(2.053) using $ inside a slice of a tuple) + $(LI $(BUGZILLA 6719): "Error: out of memory" in parsing) + $(LI $(BUGZILLA 6721): [CTFE] Cannot get pointer to start of char[]) + $(LI $(BUGZILLA 6727): [CTFE] ICE(interpret.c): assignment from string literal.dup.ptr) + $(LI $(BUGZILLA 6733): Regression(2.054) ICE(cod2.c) pure nothrow func with side-effect parameters) + $(LI $(BUGZILLA 6739): [CTFE] Cannot set a value to an outer AA of a nested AA) + $(LI $(BUGZILLA 6746): static this() inside struct skipped upon static method call) + $(LI $(BUGZILLA 6749): [CTFE] problem with array of structs) + $(LI $(BUGZILLA 6751): [CTFE] ref argument of AA doesn't work) + $(LI $(BUGZILLA 6753): Regression(2.055beta) "Reinterpret" cast of array to a tail const one doesn't work inside @trusted) + $(LI $(BUGZILLA 6759): missing initialization in foreach with alias this) + $(LI $(BUGZILLA 6765): [CTFE]: AA.length doesn't compile when AA is null) + $(LI $(BUGZILLA 6769): [CTFE] AA.keys doesn't compile when -inline is used) + $(LI $(BUGZILLA 6770): inout is allowed on fields) + $(LI $(BUGZILLA 6773): inout variable should not be modifiable) + $(LI $(BUGZILLA 6775): [CTFE] foreach over an AA fails to compile) + $(LI $(BUGZILLA 6782): inout-correct range is not iterable using foreach with type deduction inside non-inout function) + $(LI $(BUGZILLA 6813): Yet another "cannot get frame pointer" error) + $(LI $(BUGZILLA 6822): New ubuntu linking rules prevent dmd from linking programs on Ubuntu 11.10) + $(LI $(BUGZILLA 6825): Regression(2.055+): Address of templated method incorrectly taken) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.056 + TITLE=Change Log: $(VER) diff --git a/changelog/2.057.dd b/changelog/2.057.dd new file mode 100644 index 0000000000..d8640bb05b --- /dev/null +++ b/changelog/2.057.dd @@ -0,0 +1,132 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Dec 13, 2011, =================================================, + + $(WHATSNEW + $(LI Better use of XMM registers in 64 bit targets.) + $(LI The $(D_KEYWORD invariant) keyword as a synonym for $(D_KEYWORD immutable) is now deprecated - use $(D_KEYWORD immutable) instead) + $(LI Add Mach-O 64 bit support for obj2asm and dumpobj) + $(LI classes, interfaces, and exceptions are supported in CTFE) + $(LI $(BUGZILLA 3474): PATCH: Implement opDollar for struct and class indexing operations) + $(LI $(BUGZILLA 6572): Deprecate typedef) + + $(LI Major overhaul of std.regex module's implementation. + $(RED Breaking change) in std.regex.replace with delegate, + use Captures!string instead of RegexMatch!string as delegate parameter.) + $(LI As typedef has been deprecated, overloads of std.conv.to which use + typedef have now been deprecated.) + $(LI std.array.insert has been deprecated. Please use std.array.insertInPlace instead.) + $(LI The overload of std.array.replace which replaces in place has been deprecated. + Please use std.array.replaceInPlace instead.) + $(LI The toISOExtendedString and fromISOExtendedString functions on SysTime, Date, + TimeOfDay, and DateTime in std.datetime have been deprecated. Please use + toISOExtString and fromISOExtString instead.) + $(LI std.file.getTimesPosix has been deprecated. Please use std.file.getTimes instead.) + $(LI The overloads for isDir, isFile, and isSymlink in std.file which take a uint + have been deprecated. Please use attrIsDir, attrIsFile, and attrIsSymlink instead.) + $(LI $(BUGZILLA 2550): implicit conversions don't apply to template value parameter specialization) + $(LI $(BUGZILLA 3467): Non-int integral template parameters not correctly propagated) + $(LI Removed top const from dynamic array types and pointer types in IFTI.) + ) + $(RUNTIMEBUGSFIXED + $(LI $(BUGZILLA 6909): incorrect definition of the OVERLAPPED struct in core.sys.windows.windows ?) + ) + $(LIBBUGSFIXED + $(LI Unlisted bug: std.conv: Fix to!float("-0")) + $(LI Unlisted bug: std.file broken on OS X x86_64 due to wrong stat64 declaration.) + $(LI $(BUGZILLA 2936): std.regex.match() short string optimization) + $(LI $(BUGZILLA 4765): std.math.modf always returns 0) + $(LI $(BUGZILLA 5193): SList cannot have struct elements that have immutable members.) + $(LI $(BUGZILLA 5620): Implicit conversion of RegexMatch to bool.) + $(LI $(BUGZILLA 5712): [patch] std.regex.replace disallows w/dstring) + $(LI $(BUGZILLA 6204): emplace() for classes accepts larger chunk but fails in array assignment) + $(LI $(BUGZILLA 6887): Regression of getopt) + $(LI $(BUGZILLA 6888): std.getopt.getopt: one-letter hash option causes range violation) + $(LI $(BUGZILLA 6935): struct with @disable this cannot make range) + $(LI $(BUGZILLA 6953): std.concurrency needs more documentation) + $(LI $(BUGZILLA 6973): static assert(isOutputRange!(OutputRange!int, int)) is false) + $(LI $(BUGZILLA 6976): GetLastError called as property) + $(LI $(BUGZILLA 6977): getErrno called as property in std.stdio) + $(LI $(BUGZILLA 6979): hasUnsharedAliasing cannot accept plural parameters) + $(LI $(BUGZILLA 6990): std.string.splitlines deprecation doc missing a word) + $(LI $(BUGZILLA 7000): missing import of std.stdio in std.regex?) + $(LI $(BUGZILLA 7039): Posix 2.057 Makefile error breaking 64bit build) + $(LI $(BUGZILLA 7040): Phobos must use "version/else version" blocks for proper + documentation generation.) + $(LI $(BUGZILLA 7045): AssertError in std.regex on line 1573) + $(LI $(BUGZILLA 7055): to!float("INF2") == 2) + ) + $(DMDBUGSFIXED + $(LI $(BUGZILLA 2095): covariance w/o typechecks = bugs) + $(LI $(BUGZILLA 2532): '=' does not give a boolean result) + $(LI $(BUGZILLA 2778): alias this + IFTI doesn't work.) + $(LI $(BUGZILLA 2856): static opIndex does not compile for a templated struct/class) + $(LI $(BUGZILLA 3990): Deferencing a dynamic array as pointer) + $(LI $(BUGZILLA 4047): [CTFE] class/struct heap allocation) + $(LI $(BUGZILLA 4401): auto functions cannot be inner functions) + $(LI $(BUGZILLA 4511): Contravariance problem) + $(LI $(BUGZILLA 4583): PIC code not working: EBX register set incorrectly) + $(LI $(BUGZILLA 5311): Pure is broken when accessing globals / static data through instance reference) + $(LI $(BUGZILLA 5364): optimizer kills high dword of -1) + $(LI $(BUGZILLA 5416): null should have a type of its own) + $(LI $(BUGZILLA 5899): auto-return function cannot match 'null' with reference type.) + $(LI $(BUGZILLA 6056): Type lookup problem in string mixins) + $(LI $(BUGZILLA 6077): CTFE: Cannot append null array to null array.) + $(LI $(BUGZILLA 6330): Cannot disable assignment to a struct.) + $(LI $(BUGZILLA 6354): Optimizer bug on x86_64: Bitshift optimized out when foreach and scope(failure) are used) + $(LI $(BUGZILLA 6416): [CTFE] Declaration static struct is not yet implemented in CTFE) + $(LI $(BUGZILLA 6479): spurious alias this with struct and mixin template) + $(LI $(BUGZILLA 6522): [CTFE] Problem with opAssign call in foreach(ref)) + $(LI $(BUGZILLA 6603): [CTFE] Can't call through a manifest constant function pointer) + $(LI $(BUGZILLA 6736): Regression(2.054): ICE (cgcod.c 1672) with alias this and certain structs) + $(LI $(BUGZILLA 6763): Using TypeTuple with (const/in/ref etc.) changes it forever) + $(LI $(BUGZILLA 6792): [CTFE] ICE with pointer cast of indexed array) + $(LI $(BUGZILLA 6800): [CTFE] dangerous pointer casts should be rejected) + $(LI $(BUGZILLA 6805): Can't use a type from opDispatch template) + $(LI $(BUGZILLA 6816): [CTFE] nested function can't access this) + $(LI $(BUGZILLA 6817): [CTFE] Error on interpreting inlined IfStatement) + $(LI $(BUGZILLA 6832): Can't test objects wrapped with alias this) + $(LI $(BUGZILLA 6836): map + UFCS = fail) + $(LI $(BUGZILLA 6837): alias this + UFCS = fail) + $(LI $(BUGZILLA 6851): [CTFE] Cannot deref pointer passed by argument) + $(LI $(BUGZILLA 6859): Segfault when abstract method uses with contract.) + $(LI $(BUGZILLA 6864): Const conversion should precedence over the shared one) + $(LI $(BUGZILLA 6865): inout matching removes shared qualifier) + $(LI $(BUGZILLA 6866): ICE(mtype.c): alias this and inout matching) + $(LI $(BUGZILLA 6867): inout and nested foreach loops) + $(LI $(BUGZILLA 6868): IsExp + incorrect static array type = error) + $(LI $(BUGZILLA 6870): type qualifiers behave inconsistently in combination with typeof) + $(LI $(BUGZILLA 6872): Breaking type parsing of shared(inout(int)[])) + $(LI $(BUGZILLA 6877): [XMM] regression, clobbered float value) + $(LI $(BUGZILLA 6879): The difference of between template matching and IsExp) + $(LI $(BUGZILLA 6881): [XMM] ICE with painted float) + $(LI $(BUGZILLA 6885): [CTFE] wrong code with dynamically allocated 2D array) + $(LI $(BUGZILLA 6886): [CTFE] ICE(interpret.c) new array with initializer) + $(LI $(BUGZILLA 6901): wrong error "override cannot be applied to variable" in CTFE forward reference) + $(LI $(BUGZILLA 6902): Different "pure nothrow int()" types) + $(LI $(BUGZILLA 6910): __traits(hasMember, "$(LESS)name$(GREATER)") does not work, if template has alias param) + $(LI $(BUGZILLA 6912): const(T)[] can be implicitly cast to inout(const(T)[])) + $(LI $(BUGZILLA 6919): [CTFE] Cannot get effect to local variable through its pointer) + $(LI $(BUGZILLA 6922): [TDPL] superimposing of const and immutable does not work correctly) + $(LI $(BUGZILLA 6927): Better @property management by chained functions) + $(LI $(BUGZILLA 6928): alias this, immutable and common type fail in presence of fields with indirections) + $(LI $(BUGZILLA 6929): [ICE] typeMerge crashes in presence of ambiguous alias this conversions) + $(LI $(BUGZILLA 6941): .stringof displays redundant storage classes) + $(LI $(BUGZILLA 6972): [CTFE] ICE with ubyte/=uint) + $(LI $(BUGZILLA 6994): Using explicit 'this' in template constraint causes an error) + $(LI $(BUGZILLA 6997): 64bit optimizer bug) + $(LI $(BUGZILLA 7004): Iterating tuple with index which explicitly typed as size_t causes an error) + $(LI $(BUGZILLA 7026): 64 bit optimizer bug) + $(LI $(BUGZILLA 7027): Struct member trySemantic() regression in DMD Git master) + $(LI $(BUGZILLA 7028): Fails to save FPU regs when executing finally block) + $(LI $(BUGZILLA 7072): [2.057 Beta] Assertion failure: '0' on line 145 in file 'mtype.c') + $(LI $(BUGZILLA 7093): aliased type sometimes isn't resolved) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.057 + TITLE=Change Log: $(VER) diff --git a/changelog/2.058.dd b/changelog/2.058.dd new file mode 100644 index 0000000000..b050e12bae --- /dev/null +++ b/changelog/2.058.dd @@ -0,0 +1,245 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 14, 2012, =================================================, + + $(WHATSNEW + $(LI Add new => lambda syntax.) + $(LI Allow 1.userproperty syntax. NOTE: 1.f is no longer a float literal, add a 0.) + $(LI Convert to -shared dmd switch instead of -dylib) + $(LI Better use of XMM registers in OS X 32 bit target.) + $(LI Add inline assembler support for AVX instructions (64 bit targets only).) + $(LI Use of base class protection is now deprecated.) + $(LI Added traits isVirtualMethod and getVirtualMethods.) + $(LI Struct/class invariants are now implicitly const.) + + $(LI Major overhaul of std.regex module's implementation. + $(RED Breaking change) in std.regex.replace with delegate, + use Captures!string instead of RegexMatch!string as delegate parameter.) + $(LI As typedef has been deprecated, overloads of std.conv.to which use + typedef have now been deprecated.) + $(LI std.array.insert has been deprecated. Please use std.array.insertInPlace instead.) + $(LI The overload of std.array.replace which replaces in place has been deprecated. + Please use std.array.replaceInPlace instead.) + $(LI The toISOExtendedString and fromISOExtendedString functions on SysTime, Date, + TimeOfDay, and DateTime in std.datetime have been deprecated. Please use + toISOExtString and fromISOExtString instead.) + $(LI std.file.getTimesPosix has been deprecated. Please use std.file.getTimes instead.) + $(LI The overloads for isDir, isFile, and isSymlink in std.file which take a uint + have been deprecated. Please use attrIsDir, attrIsFile, and attrIsSymlink instead.) + ) + $(RUNTIMEBUGSFIXED + ) + $(LIBBUGSFIXED + $(LI $(BUGZILLA 4295): IID_IUnknown symbol undefined in phobos.lib) + $(LI $(BUGZILLA 7241): std.format can't read into array of dchar ) + ) + $(DMDBUGSFIXED + $(LI $(BUGZILLA 516): Mutually calling constructors allowed) + $(LI $(BUGZILLA 620): Can't use property syntax with a template function) + $(LI $(BUGZILLA 664): is(func T == function) ignores variadic arguments) + $(LI $(BUGZILLA 678): Compiler accepts, for a function T[] t(), t().ptr but not t.ptr) + $(LI $(BUGZILLA 796): Asserting a null object reference throws AssertError Failure internal\invariant.d(14) or Access Violation) + $(LI $(BUGZILLA 949): Wrong spec/compiler behaviour for Strings, Integers and Floats) + $(LI $(BUGZILLA 955): Passing arguments into functions - in, out, inout, const, and contracts) + $(LI $(BUGZILLA 1313): out/body disables escape analysis) + $(LI $(BUGZILLA 1521): Ambiguous documentation) + $(LI $(BUGZILLA 1563): dynamic cast is not always performed) + $(LI $(BUGZILLA 1570): Wrong return for address operator) + $(LI $(BUGZILLA 1918): __traits(getVirtualFunctions) returns final functions) + $(LI $(BUGZILLA 1920): Class documentation incomplete) + $(LI $(BUGZILLA 1943): Templates can't take function pointer parameters) + $(LI $(BUGZILLA 2106): export class doesn't affect, what is exported) + $(LI $(BUGZILLA 2351): enum with no members allowed) + $(LI $(BUGZILLA 2382): spec is not clear on what is allowed as global/static initializers) + $(LI $(BUGZILLA 2387): Static array terminology) + $(LI $(BUGZILLA 2411): Reference Tuple Foreach) + $(LI $(BUGZILLA 2417): [module] protected base member is not available via base handle in a derived class if it is defined in a separate module) + $(LI $(BUGZILLA 2442): opApply does not allow inferring parameter types when overloaded on const) + $(LI $(BUGZILLA 2443): opApply should allow delegates that are not ref if it makes no sense) + $(LI $(BUGZILLA 2483): DMD allows assignment to a scope variable) + $(LI $(BUGZILLA 2494): describe explicit casting of arrays) + $(LI $(BUGZILLA 2495): const syntax for member functions needs better description) + $(LI $(BUGZILLA 2497): delete and null relationship needs more details) + $(LI $(BUGZILLA 2524): final override inconsistent when implementing interfaces) + $(LI $(BUGZILLA 2639): Hex and octal string values not completely specified) + $(LI $(BUGZILLA 2819): array.sort segfaults if array length >=0x8F_FFFF) + $(LI $(BUGZILLA 2894): abstract classes sometimes allow non-abstract bodyless functions) + $(LI $(BUGZILLA 2997): allMembers does not return interface members) + $(LI $(BUGZILLA 3084): Formatting of lazy in parameters section) + $(LI $(BUGZILLA 3092): Indexing a tuple produces a tuple containing the indexed element) + $(LI $(BUGZILLA 3111): 'mangleof' can't be member of a struct not documented) + $(LI $(BUGZILLA 3187): Nested foreach over opApply doesn't work) + $(LI $(BUGZILLA 3204): Document global properties) + $(LI $(BUGZILLA 3235): [tdpl] Function literals must be deduced as "function" or "delegate") + $(LI $(BUGZILLA 3265): .classinfo for Interface-typed reference does not return instance's ClassInfo) + $(LI $(BUGZILLA 3492): Can't overload nested functions) + $(LI $(BUGZILLA 3578): Impossible to run a struct invariant using assert(s)) + $(LI $(BUGZILLA 3735): op=) + $(LI $(BUGZILLA 3757): Overloading const function with overridden non-const function results in seg fault.) + $(LI $(BUGZILLA 3777): size_t is undefined) + $(LI $(BUGZILLA 3783): Text inconsistent with EscapeSequence rules) + $(LI $(BUGZILLA 3787): clarification: assigment to 'this') + $(LI $(BUGZILLA 3791): Reference anonymous nested classes when describing new expressions) + $(LI $(BUGZILLA 3800): "Foreach over Structs and Classes with Ranges" and "Invariant Struct" in D2 Spec) + $(LI $(BUGZILLA 3838): PrimaryExpression rule doesn't permit module scope template instances) + $(LI $(BUGZILLA 3886): Bad example of definition file for DLLs) + $(LI $(BUGZILLA 3906): Undefined struct and union declarations are not documented) + $(LI $(BUGZILLA 3908): @ attributes not part of function grammar) + $(LI $(BUGZILLA 3954): DeclDef rule is missing TemplateMixinDeclaration) + $(LI $(BUGZILLA 3988): Provide canonical example for operator overloading) + $(LI $(BUGZILLA 4088): opEquals not called on interfaces) + $(LI $(BUGZILLA 4180): D DWARF extensions conflict with DWARF-4) + $(LI $(BUGZILLA 4251): Hole in the const system: immutable(T)[] implicitly casts to ref const(T)[]) + $(LI $(BUGZILLA 4371): segfault(template.c) template tuple in is() expression) + $(LI $(BUGZILLA 4413): typeof(this) doesn't work in method template signature) + $(LI $(BUGZILLA 4421): Union propagates copy constructors and destructors over all members) + $(LI $(BUGZILLA 4523): [tdpl] .remove method for Associative Arrays returns void in all cases) + $(LI $(BUGZILLA 4539): Refuse assignment to string literal) + $(LI $(BUGZILLA 4545): Alias to members possible without "this" instance) + $(LI $(BUGZILLA 4550): D2 Language Docs: http://www.digitalmars.com/d/2.0/statement.html) + $(LI $(BUGZILLA 4553): D2 Language Docs: http://www.digitalmars.com/d/2.0/struct.html) + $(LI $(BUGZILLA 4647): [tdpl] Cannot explicitly call final interface method, ambiguous calls allowed) + $(LI $(BUGZILLA 4651): Docs: Returned classes that have access to stack variables of its enclosing function) + $(LI $(BUGZILLA 4675): [tdpl] Eponymous Template should hide internal names) + $(LI $(BUGZILLA 4711): Incorrect handling of && operator with void operand) + $(LI $(BUGZILLA 4841): -inline wrecks nested struct with alias template parameter (An array()/map inlining problem)) + $(LI $(BUGZILLA 4887): Right-shifting by 32 is allowed and broken) + $(LI $(BUGZILLA 4940): ICE(symbol.c): Accessing tuple-typed field of struct literal with user-defined constructor) + $(LI $(BUGZILLA 4956): remove direct references to gcc from linux.mak) + $(LI $(BUGZILLA 5023): Docs about order of execution of invariant and pre/post conditions) + $(LI $(BUGZILLA 5111): Static function-level variables are not in the language spec.) + $(LI $(BUGZILLA 5114): Too many error messages) + $(LI $(BUGZILLA 5132): ~ unary operator silently different from C) + $(LI $(BUGZILLA 5138): Special token sequence) + $(LI $(BUGZILLA 5261): Uncompilable example for Windows) + $(LI $(BUGZILLA 5299): Protected inheritance is semantically undefined.) + $(LI $(BUGZILLA 5337): Documentation regarding interfacing with C does not account for TLS differences) + $(LI $(BUGZILLA 5476): spec: attributes have an optional else clause) + $(LI $(BUGZILLA 5493): Able to overwrite immutable data by passing through ref function parameter) + $(LI $(BUGZILLA 5527): Bug in http://www.digitalmars.com/d/2.0/ctod.html#closures) + $(LI $(BUGZILLA 5605): [tdpl] foreach with ranges doesn't support opSlice()) + $(LI $(BUGZILLA 5648): dmd command line option list inconsistencies) + $(LI $(BUGZILLA 5713): Broken final switch on ints) + $(LI $(BUGZILLA 5715): Contradiction in spec: meaning of variable.init) + $(LI $(BUGZILLA 5718): Can't demangle symbol defined inside unittest block) + $(LI $(BUGZILLA 5796): ICE with pragma(msg, ...) after missing ';' in a template) + $(LI $(BUGZILLA 5820): Documentation states string literals can implicitly convert to char*) + $(LI $(BUGZILLA 5841): alias grammar is incorrect) + $(LI $(BUGZILLA 6013): private ignored for aliases) + $(LI $(BUGZILLA 6037): [CTFE] recursive ref parameters evaluated incorrectly) + $(LI $(BUGZILLA 6091): [d-p-l.org] Description for "Modifier casting" is misleading) + $(LI $(BUGZILLA 6165): Anonymous enums specification) + $(LI $(BUGZILLA 6177): Regression(2.053): ICE backend/cgcs.c: struct with destructor in assoc. array or typesafe variadic functions) + $(LI $(BUGZILLA 6205): Strongly-pure nothrow functions with ignored return value are entirely stripped even if it contains a failing 'assert'.) + $(LI $(BUGZILLA 6208): Parameter storage classes are ignored in template function deducing.) + $(LI $(BUGZILLA 6364): Static struct's destructor called on exit of function) + $(LI $(BUGZILLA 6402): Note on @property in spec needs updating) + $(LI $(BUGZILLA 6451): [64bit] ICE(expression.c:4434): SymbolExp::SymbolExp(Loc, TOK, int, Declaration*, int): Assertion 'var' failed) + $(LI $(BUGZILLA 6473): Stack overflow with struct destructor as default parameter) + $(LI $(BUGZILLA 6504): Regression(2.041): "str" ~ [arr] allows string literal to be modified) + $(LI $(BUGZILLA 6701): template specialization resolution failure) + $(LI $(BUGZILLA 6704): CommaExpression as an IfCondition) + $(LI $(BUGZILLA 6714): [tdpl] Type inference for parameters of function and delegate literals) + $(LI $(BUGZILLA 6780): Templated global property functions do not work) + $(LI $(BUGZILLA 6839): documentation for opAssign incorrect) + $(LI $(BUGZILLA 6933): Segfault(declaration.c) using struct with destructor in CTFE) + $(LI $(BUGZILLA 6934): [CTFE] can't use $ in a slice of an array passed by ref) + $(LI $(BUGZILLA 6939): wrong type qualifier combination) + $(LI $(BUGZILLA 6940): immutable(int*)*/immutable(int)** and int** do not combine) + $(LI $(BUGZILLA 6948): Possible bug in compiler or documentation regarding signature of opCmp()) + $(LI $(BUGZILLA 6964): Error message with __error: static assert(undefined+1)) + $(LI $(BUGZILLA 6968): Segmantation fault, if exclamation mark absent) + $(LI $(BUGZILLA 6971): [lex.dd] Type of string literals are outdated) + $(LI $(BUGZILLA 6984): CTFE generates a torrent of spurious errors, if there was a previous error) + $(LI $(BUGZILLA 6985): [CTFE] Non-constant case expressions can't be interpreted) + $(LI $(BUGZILLA 6987): The "Memory Management" documentation incorrectly claims arrays are passed by reference) + $(LI $(BUGZILLA 6995): [CTFE] can't interpret static template method) + $(LI $(BUGZILLA 7011): No line number error for vector power) + $(LI $(BUGZILLA 7037): TemplateTypeParameterSpecialization works differently from IsExpression regarding alias this) + $(LI $(BUGZILLA 7043): CTFE: ICE illegal reference value 0LU, only with -inline) + $(LI $(BUGZILLA 7073): Parsing of class-returning varargs function inside module ctor fails) + $(LI $(BUGZILLA 7108): ICE: TraitsExp::semantic(Scope*) 2.056 -> 2.057 regression - segfault) + $(LI $(BUGZILLA 7120): Scope Delegates + Delegate Literals) + $(LI $(BUGZILLA 7123): static assert(is(typeof(toDelegate($(AMP)main)))) is false) + $(LI $(BUGZILLA 7124): Alias this type is not considered in template type deduction) + $(LI $(BUGZILLA 7127): Const-related infinite recursion in DWARF generation) + $(LI $(BUGZILLA 7133): [tdpl] There should be no empty statement) + $(LI $(BUGZILLA 7136): alias this lookup should run before merging modifiers of both sides.) + $(LI $(BUGZILLA 7143): [CTFE] cannot compare class references with "is") + $(LI $(BUGZILLA 7144): [CTFE] base class does not call overridden members) + $(LI $(BUGZILLA 7154): [CTFE] failing downcast causes error) + $(LI $(BUGZILLA 7158): [CTFE] ICE(interpret.c) calling a class member using a dotvar expression) + $(LI $(BUGZILLA 7160): Regression(2.057): ICE(dsymbol.c:1052) ICE using __traits(derivedMembers)) + $(LI $(BUGZILLA 7162): [CTFE] "bool || void" expression crashes dmd) + $(LI $(BUGZILLA 7165): [CTFE] ice converting null pointer to bool with constant member function) + $(LI $(BUGZILLA 7166): Internal error: ../ztc/cgxmm.c 60) + $(LI $(BUGZILLA 7168): Regression(2.057) __traits(allMembers) returns wrong tuple) + $(LI $(BUGZILLA 7170): [UFCS] array + specialized template member syntax causes ICE) + $(LI $(BUGZILLA 7173): dmd: glue.c:1065: virtual unsigned int Type::totym(): Assertion `0` failed.) + $(LI $(BUGZILLA 7178): Segfault with import of invalid template) + $(LI $(BUGZILLA 7185): [CTFE] ICE on changing char array length) + $(LI $(BUGZILLA 7187): Regression(head 12d62ca5): [CTFE] ICE on slicing) + $(LI $(BUGZILLA 7188): "import phobos;" crashes DMD) + $(LI $(BUGZILLA 7189): inline failed) + $(LI $(BUGZILLA 7190): Tuple length incorrect) + $(LI $(BUGZILLA 7193): Regression(2.058head): ICE: delete lambda expression crashes dmd) + $(LI $(BUGZILLA 7194): [CTFE] Incorrect behaviour with pointers as local struct variable) + $(LI $(BUGZILLA 7196): Unfair function address overload resolution) + $(LI $(BUGZILLA 7197): enum string doesn't work with CTFE) + $(LI $(BUGZILLA 7199): std.string.indexof cannot be compiled with -inline) + $(LI $(BUGZILLA 7201): Lambda template assignment to variable) + $(LI $(BUGZILLA 7207): Explicit cast should resolve lambda type) + $(LI $(BUGZILLA 7212): Regression(Head): ICE with overload resolution and delegate/function inference) + $(LI $(BUGZILLA 7216): [CTFE] Can't call struct member function using pointer field) + $(LI $(BUGZILLA 7217): [CTFE] ICE on accessing struct array field) + $(LI $(BUGZILLA 7218): Nested function with contract is rejected) + $(LI $(BUGZILLA 7228): MOVDQ2Q instruction is emitted with swapped register indices) + $(LI $(BUGZILLA 7231): Segfault using opDispatch with property notation) + $(LI $(BUGZILLA 7232): Warning: statement is not reachable has no line number) + $(LI $(BUGZILLA 7234): Segmentation fault when using stdio) + $(LI $(BUGZILLA 7239): C style struct initialization doesn't work with aliases) + $(LI $(BUGZILLA 7245): [CTFE] Address of ref foreach parameter changes to point after array) + $(LI $(BUGZILLA 7248): [CTFE] Stack overflow on using struct filed pointer with address of array element) + $(LI $(BUGZILLA 7261): ICE(glue.c): With taskPool.reduce) + $(LI $(BUGZILLA 7266): [CTFE] Assign to ref param (that's taken from struct member) is noop) + $(LI $(BUGZILLA 7277): [CTFE ICE] Assertion failure: 'thisval' on line 1690 in file 'interpret.c') + $(LI $(BUGZILLA 7278): Templated struct (instantiated with null) can't access its own members) + $(LI $(BUGZILLA 7285): Implicit fixed-size array cast) + $(LI $(BUGZILLA 7290): Heap allocation with scoped delegate literal) + $(LI $(BUGZILLA 7294): [Regression] No warning when escaping local reference type variables) + $(LI $(BUGZILLA 7295): Alias This + Pure + pointsTo = rejects-valid) + $(LI $(BUGZILLA 7296): [2.058] Regression: Cannot swap RefCounted) + $(LI $(BUGZILLA 7309): [2.058] Regression caused by new inlining code) + $(LI $(BUGZILLA 7321): returning void considered unsafe by safety inference) + $(LI $(BUGZILLA 7335): sometimes the OUT - block have undefined class members-acces) + $(LI $(BUGZILLA 7351): Possible asm bug: bad type/size of operands 'xadd') + $(LI $(BUGZILLA 7359): Template function with typesafe variadic rejects more than one string arguments) + $(LI $(BUGZILLA 7363): Eponymous Template doesn't hide internal names in some cases with `static if`) + $(LI $(BUGZILLA 7365): [Regression after 2.057] AAs broken for Object keys and values with opEquals) + $(LI $(BUGZILLA 7367): wrong char comparison result) + $(LI $(BUGZILLA 7369): Inout constructor causes compiler to reject invariant) + $(LI $(BUGZILLA 7373): (Regression git) Renamed imports conflict with other implicitly imported symbols) + $(LI $(BUGZILLA 7375): Regression(2.057): Invalid downcast permitted with derived/aliased template classes) + $(LI $(BUGZILLA 7377): Compiler segfault in: TemplateMixin::hasPointers()) + $(LI $(BUGZILLA 7379): DMD segfaults on semantic3 phase when alias enum this) + $(LI $(BUGZILLA 7383): Blank lines in code sections cause premature section termination) + $(LI $(BUGZILLA 7384): Typo in volatile deprecation message) + $(LI $(BUGZILLA 7394): ddmangle tool needs rebuilding) + $(LI $(BUGZILLA 7416): 2.058 regression: fails to instantiate a constrained function template with a nested function) + $(LI $(BUGZILLA 7419): [2.058/CTFE] Constructor of struct is overwritten inside a unittest with -inline) + $(LI $(BUGZILLA 7422): Regression(master): ICE with template function and if statement) + $(LI $(BUGZILLA 7424): Segfault when trying to call a templated property with different const-ancy.) + $(LI $(BUGZILLA 7425): IFTI does not work with inout methods) + $(LI $(BUGZILLA 7428): regression (DMD 2.058head) ICE on slightly convoluted setup including closures) + $(LI $(BUGZILLA 7435): Regression(master):dmd crashes when 'scope(failure) debug ...' without -debug option.) + $(LI $(BUGZILLA 7475): Regression(2.058 beta): Template member erroneously inaccessible) + $(LI $(BUGZILLA 7498): function expected before (), not function) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.058 + TITLE=Change Log: $(VER) diff --git a/changelog/2.059.dd b/changelog/2.059.dd new file mode 100644 index 0000000000..f327450598 --- /dev/null +++ b/changelog/2.059.dd @@ -0,0 +1,218 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 12, 2012, =================================================, + + $(WHATSNEW + $(LI Add predefined Ddoc macro SRCFILENAME) + $(LI Changed lexer to support # as a token, preserving #line's original behavior) + $(LI added AES, PCLMULQDQ, RDRAND, AVX, VAES, VPCLMULQDQ, FMA, FP16C to core.cpuid) + $(LI $(BUGZILLA 435): Constructors should be templatized) + $(LI $(BUGZILLA 2367): Overloading error with string literals) + $(LI $(BUGZILLA 3382): [tdpl] Implement uniform function call syntax) + $(LI $(BUGZILLA 4536): Typetuples (T...) should have an .init member) + $(LI $(BUGZILLA 5525): Eponymous templates should allow for overloaded eponymous members) + $(LI $(BUGZILLA 7105): relax inout rules) + $(LI $(BUGZILLA 7833): Changelog should clearly mention struct literal/opCmp/opEquals/toHash changes) + + $(LI Strive to make toHash, toString, opEquals and opCmp functions pure, nothrow, + const and @safe. Soon, this will become a requirement.) + + $(LI The deprecated std.date, std.dateparse, and std.gregorian modules + have been removed. Please use std.datetime instead.) + $(LI Several deprecated functions in std.file have been removed.) + $(LI The old functions in std.path which were scheduled for deprecation + have now been deprecated. Please use the new ones which were + introduced in 2.055. However, note that curdir and pardir do not + have replacements, because they're "." and ".." respectively on all + OSes so variables for them were seen as unnecessary. Also, one major + change to note about the new std.path functions is that when operating + on extensions, they expect "." to be part of the extension whereas the + old ones did not (e.g. "file.txt".extension == ".txt" whereas + "file.txt".getExt() == "txt").) + $(LI The version of std.exception.enforceEx which was scheduled for + deprecation has been deprecated. Please use the version which + takes exceptions which can be constructed with new E(msg, file, line) + (rather than just new E(msg) as the old version did). That way, + exceptions constructed with enforceEx will give the file and line + number where enforceEx was called.) + $(LI Get rid of Win9x support.) + $(LI std.typecons: Added Proxy mixin template.) + $(LI std.format: Added documentation about compound format specifier.) + ) + $(RUNTIMEBUGSFIXED + ) + $(LIBBUGSFIXED + $(LI $(BUGZILLA 4604): A stack overflow with writeln) + $(LI $(BUGZILLA 5523): std.regex handles "\s" and "\W" (etc.) inside square brackets improperly) + $(LI $(BUGZILLA 5652): Add \p and \P unicode properties to std.regex) + $(LI $(BUGZILLA 5674): AssertError in std.regex) + $(LI $(BUGZILLA 5964): std.stdio.readln can throw a UnicodeException) + $(LI $(BUGZILLA 6217): [GSOC] result of std.algorithm.map is not movable) + $(LI $(BUGZILLA 6403): Upgrade std.regex to Unicode UTS #18 Level 1 support) + $(LI $(BUGZILLA 6892): Formatted write with specified length of enum member) + $(LI $(BUGZILLA 7111): New regex engine cannot match beginning of empty string) + $(LI $(BUGZILLA 7138): Can't call array() on dirEntries) + $(LI $(BUGZILLA 7264): Can't iterate result from 4-arg dirEntries as string) + $(LI $(BUGZILLA 7299): std.uni missing doc comments) + $(LI $(BUGZILLA 7300): std.regex.ShiftOr!dchar.search is broken) + $(LI $(BUGZILLA 7374): stdin.byLine() throws AssertError on empty input) + $(LI $(BUGZILLA 7460): std.windows.registry reports a false exception message) + $(LI $(BUGZILLA 7476): Write(ln) functions no longer accept retro range) + $(LI $(BUGZILLA 7628): std.format formatValue incorrect overload) + $(LI $(BUGZILLA 7674): regex replace requires escaped format) + $(LI $(BUGZILLA 7679): std.regex.split and splitter don't work w/ ctRegex) + $(LI $(BUGZILLA 7718): regex and ctRegex produce different results) + ) + $(DMDBUGSFIXED + $(LI rdmd: --force now works with --eval) + $(LI rdmd: update --eval's import list) + $(LI $(BUGZILLA 176): [module] message "module and package have the same name") + $(LI $(BUGZILLA 783): Cannot use an array w/ const or variable index as new[] size argument.) + $(LI $(BUGZILLA 977): Expressions inside a struct or array initializer get wrong line number) + $(LI $(BUGZILLA 3279): Confusing error message when comparing types) + $(LI $(BUGZILLA 3354): invalid number of args accepted for 1/2 arg floating point instructions) + $(LI $(BUGZILLA 3509): Cannot forward reference a template mixin's members in a compile-time context) + $(LI $(BUGZILLA 3510): Cannot forward reference a templated type from within a template mixin) + $(LI $(BUGZILLA 3559): DMD 1.048+ fails to take function pointer from overloaded member functions) + $(LI $(BUGZILLA 3630): bad error location in "has no effect in expression" error) + $(LI $(BUGZILLA 3682): Regression(2.038) is expression fails to match types) + $(LI $(BUGZILLA 3812): Missing line number for implicit cast of variadic function to array) + $(LI $(BUGZILLA 3822): Invalid optimization of alloca called with constant size) + $(LI $(BUGZILLA 3927): array.length++; is an error, but ++array.length compiles) + $(LI $(BUGZILLA 4241): duplicate union initialization error doesn't give a file location) + $(LI $(BUGZILLA 4269): Regression(2.031): invalid type accepted if evaluated while errors are gagged) + $(LI $(BUGZILLA 4507): use spellchecker when override function doesn't override anything) + $(LI $(BUGZILLA 4820): Regression(1.058, 2.044) in DStress caused by changeset 452) + $(LI $(BUGZILLA 4854): Regression(2.047, Mac 10.5 only) writefln Segmentation fault if no globals) + $(LI $(BUGZILLA 4993): Temporary values and opIndexAssign) + $(LI $(BUGZILLA 5181): Excess cast on in-place operation op= involving conversion) + $(LI $(BUGZILLA 5412): import wtf2) + $(LI $(BUGZILLA 5554): [qtd] Covariance detection failure) + $(LI $(BUGZILLA 5590): Regression(2.036) ICE(e2ir.c): when using .values on enum which is associative array) + $(LI $(BUGZILLA 5733): Calling opDispatch As Template Results in Compiler Infinite Loop) + $(LI $(BUGZILLA 5879): Not all frontend errors use stderr) + $(LI $(BUGZILLA 5889): Struct literal/construction should be rvalue (it binds to ref parameters)) + $(LI $(BUGZILLA 6391): Line-less error when passing the '.im' of floating pointer value by reference) + $(LI $(BUGZILLA 6438): [CTFE] wrong error "value used before set" when slicing =void array) + $(LI $(BUGZILLA 6611): better error message for array post increment/decrement) + $(LI $(BUGZILLA 6681): struct constructor call is converted to struct literal that breaks union initialization) + $(LI $(BUGZILLA 6685): Allow using "with" with rvalues) + $(LI $(BUGZILLA 6699): More cases of __error in error messages) + $(LI $(BUGZILLA 6738): Can't call templatized property function from within a struct/class method) + $(LI $(BUGZILLA 6785): Wrong error message from pragma(msg) of failed instantiation) + $(LI $(BUGZILLA 6982): immutability isn't respected on associative array assignment) + $(LI $(BUGZILLA 7038): Type mismatch with const struct) + $(LI $(BUGZILLA 7110): opSlice() & opIndex functions works unstable as template arguments) + $(LI $(BUGZILLA 7288): ICE(toir.c): with lambda return + auto) + $(LI $(BUGZILLA 7353): NRVO not properly working with inferred return type) + $(LI $(BUGZILLA 7380): Crash trying to use address of variable in struct constructor at module level) + $(LI $(BUGZILLA 7399): Broken import statement in trySemantic() causes silent compiler error) + $(LI $(BUGZILLA 7406): tuple foreach doesn't work with mixed tuples) + $(LI $(BUGZILLA 7411): Deduce base type from vector types in templates) + $(LI $(BUGZILLA 7439): Compound assignment causes segmentation fault) + $(LI $(BUGZILLA 7452): Function using enforce() cannot be inferred as @safe because of anonymous function due to lazy argument) + $(LI $(BUGZILLA 7462): Error message with _error_ in overridden function) + $(LI $(BUGZILLA 7463): Duplicated error message with bad template value parameter) + $(LI $(BUGZILLA 7473): [CTFE] Non-ref argument behaves as if it's a ref argument) + $(LI $(BUGZILLA 7481): Compiler should 'soldier on' after template errors) + $(LI $(BUGZILLA 7493): Initialization of void[][N]) + $(LI $(BUGZILLA 7499): ICE(cast.c line 1495) with lambda array) + $(LI $(BUGZILLA 7500): [ICE] (template.c line 5287) with immutable lambda function) + $(LI $(BUGZILLA 7502): 2.056 regression: Assigning .init takes forever to compile for large structs) + $(LI $(BUGZILLA 7504): Cannot assign an object of type 'typeof(null)' to an array) + $(LI $(BUGZILLA 7518): std.array.empty doesn't work for shared arrays) + $(LI $(BUGZILLA 7525): [2.058 regression] Broken return type inference for delegate returns) + $(LI $(BUGZILLA 7527): [CTFE] Segfault when slicing a pointer at compile time) + $(LI $(BUGZILLA 7536): ctfeAdrOnStack triggered) + $(LI $(BUGZILLA 7544): ICE(interpret.c) Catching an exception with a null catch block) + $(LI $(BUGZILLA 7545): ICE(cast.c) Merge integral types through alias this) + $(LI $(BUGZILLA 7547): -deps output lists object as a top level module) + $(LI $(BUGZILLA 7550): Missing AVX instruction VPMULDQ) + $(LI $(BUGZILLA 7552): Cannot get and combine a part of overloaded functions) + $(LI $(BUGZILLA 7554): Immutable function pointer arguments too) + $(LI $(BUGZILLA 7557): Sea of errors after template failure) + $(LI $(BUGZILLA 7562): DMD crashes by using TemplateThisParameter) + $(LI $(BUGZILLA 7563): Class members with default template arguments have no type) + $(LI $(BUGZILLA 7568): pragma(msg) segfaults with an aggregate including a class.) + $(LI $(BUGZILLA 7578): ICE on indexing result of vararg opDispatch) + $(LI $(BUGZILLA 7580): Identity assignment of Nullable crashes dmd) + $(LI $(BUGZILLA 7582): Untyped nested delegate literals don't compile) + $(LI $(BUGZILLA 7583): [CTFE] ICE with tuple and alias this) + $(LI $(BUGZILLA 7589): __traits(compiles) does not work with a template that fails to compile) + $(LI $(BUGZILLA 7592): Conversion from ireal to ifloat broken when using xmm) + $(LI $(BUGZILLA 7595): Data being overwritten.) + $(LI $(BUGZILLA 7608): __traits(allMembers) is broken) + $(LI $(BUGZILLA 7618): delegate/function pointer call bypass parameter storage class) + $(LI $(BUGZILLA 7621): Immutable type equivalence problem) + $(LI $(BUGZILLA 7633): Missing CTFE error message) + $(LI $(BUGZILLA 7639): Undefined enum AA key crashes compiler) + $(LI $(BUGZILLA 7641): std.typecons.Proxy incorrectly allows implicit conversion to class) + $(LI $(BUGZILLA 7643): Whole tuple slice isn't resolved as expected) + $(LI $(BUGZILLA 7649): Bad lambda inference in default function argument) + $(LI $(BUGZILLA 7650): Bad lambda inference in associative array literal) + $(LI $(BUGZILLA 7667): ICE(interpret.c): 'ctfeStack.stackPointer() == 0') + $(LI $(BUGZILLA 7669): Broken inout deduction with static array type) + $(LI $(BUGZILLA 7670): UFCS problem with @property and structs) + $(LI $(BUGZILLA 7671): Broken inout deduction of shared(inout(T[n])) from immutable(int[3])) + $(LI $(BUGZILLA 7672): Remove top const doesn't work for inout array type.) + $(LI $(BUGZILLA 7681): Regression(2.059head):ICE:opCatAssign(delegate) to undefined identifier) + $(LI $(BUGZILLA 7682): shared array type and "cast() is not an lvalue" error) + $(LI $(BUGZILLA 7684): IFTI and shared overload doesn't work) + $(LI $(BUGZILLA 7694): Internal error: e2ir.c 1251 when calling member function inside struct via alias param) + $(LI $(BUGZILLA 7695): Regression(2.058): ICE(mtype.c) on associative array with keys of struct type with const members) + $(LI $(BUGZILLA 7698): can't specialize parameterized template value) + $(LI $(BUGZILLA 7699): Cannot get frame pointer to in contract when compiling with -inline) + $(LI $(BUGZILLA 7702): opDispatch goes into infinite loop) + $(LI $(BUGZILLA 7703): [UFCS] explicit template function instantiation as property) + $(LI $(BUGZILLA 7705): lambda syntax doesn't allow some valid signatures) + $(LI $(BUGZILLA 7713): lambda inference doesn't work on template function argument) + $(LI $(BUGZILLA 7722): Refuse normal functions to be used as properties) + $(LI $(BUGZILLA 7731): Assertion failure: 't' on line 7911 in file 'mtype.c') + $(LI $(BUGZILLA 7732): [CTFE] wrong code for a struct called AssociativeArray) + $(LI $(BUGZILLA 7735): Functions with variadic void[][]... arguments corrupt passed data) + $(LI $(BUGZILLA 7742): 'More initializers than fields' error with correct number of fields) + $(LI $(BUGZILLA 7743): Parsing problem with nothrow delegate) + $(LI $(BUGZILLA 7745): Regression (1.x git-415e48a) Methods defined in external object files when a pointer to it is taken) + $(LI $(BUGZILLA 7751): [ICE] (Regression 2.059head) From auto and forward reference) + $(LI $(BUGZILLA 7754): static this() in template is stripped during header gen) + $(LI $(BUGZILLA 7755): regression(2.059head): ICE in glue.c) + $(LI $(BUGZILLA 7757): Inout function with lazy inout parameter doesn't compile) + $(LI $(BUGZILLA 7761): lambda expression doesn't parse attributes) + $(LI $(BUGZILLA 7768): More readable template error messages) + $(LI $(BUGZILLA 7769): relax inout rule doesn't work for template function) + $(LI $(BUGZILLA 7722): Refuse normal functions to be used as properties) + $(LI $(BUGZILLA 7773): UCFS syntax on built-in attributes too?) + $(LI $(BUGZILLA 7781): [CTFE] Segmentation fault on 'mixin({return;}());) + $(LI $(BUGZILLA 7782): [ICE] With wrong import syntax) + $(LI $(BUGZILLA 7785): [CTFE] ICE when slicing pointer to variable) + $(LI $(BUGZILLA 7786): dmd crashes with invalid module name) + $(LI $(BUGZILLA 7789): [CTFE] null pointer exception on setting array length) + $(LI $(BUGZILLA 7794): Sea of errors when calling regex() after compile error) + $(LI $(BUGZILLA 7808): Nullable's alias this does not work with structs containing classes) + $(LI $(BUGZILLA 7812): Segfault on invalid code during template match deduction with errors gagged) + $(LI $(BUGZILLA 7814): Regression(2.059head) ICE(tocsym.c) using scope(failure) within foreach-range) + $(LI $(BUGZILLA 7815): Mixin template forward reference (?) regression) + $(LI $(BUGZILLA 7820): regression(DMD 2.059head) Wrong error on forward reference to 'front' with -property switch) + $(LI $(BUGZILLA 7823): Can't use a struct initializer to initialize a nested enum used as a default function argument initializer) + $(LI $(BUGZILLA 7826): [D2 Beta] Cannot use getHash in toHash without a warning) + $(LI $(BUGZILLA 7843): Regression(2.059 beta): Informational warning fails to produce executable) + $(LI $(BUGZILLA 7857): File#write formats enum as a boolean.) + $(LI $(BUGZILLA 7858): __traits(getOverloads) returns incorrect symbol) + $(LI $(BUGZILLA 7859): Crash on invalid alias template parameter type) + $(LI $(BUGZILLA 7861): Segfault during __error propagation with self-referencing module) + $(LI $(BUGZILLA 7862): Accepts-invalid template forward reference bug related to derivedMembers) + $(LI $(BUGZILLA 7868): derivedMembers/static if regression) + $(LI $(BUGZILLA 7869): Cannot format pointer of struct has toString member function) + $(LI $(BUGZILLA 7871): RangeViolation with findSplitBefore) + $(LI $(BUGZILLA 7873): [2.059 beta] IFTI with inout does not properly match template parameter if called from inout function for pointers) + $(LI $(BUGZILLA 7886): derivedMembers infinite recursion) + $(LI $(BUGZILLA 7888): derivedMembers forward reference error with nested imports) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.059 + TITLE=Change Log: $(VER) diff --git a/changelog/2.060.dd b/changelog/2.060.dd new file mode 100644 index 0000000000..4477c41ffb --- /dev/null +++ b/changelog/2.060.dd @@ -0,0 +1,329 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Aug 2, 2012, =================================================, + + $(WHATSNEW + $(LI std.string: $(RED The current implementations of std.string.format and string.sformat are + scheduled to be replaced in November 2012 with improved implementations + which conform to writef. In some, rare cases, this will break code. + Please see the documentation for std.string.format and std.string.sformat for details.)) + $(LI std.bitmanip: Added peek, read, write, and append for converting + ranges of bytes to and from integral types.) + $(LI std.container: Added DList, which is an implementation of a doubly-linked list.) + $(LI Added std.file.tempDir which returns the path to a directory + where a program can put temporary files.) + $(LI std.process: Added escapeShellCommand, escapeShellFileName, and + escapeWindowsArgument. Documented browse function.) + $(LI std.range: Added RefRange, which effectively makes it possible to + pass a range by reference.) + $(LI std.traits: Added KeyType, ValueType, isScalarType, isBasicType, and + SetFunctionAttributes templates.) + $(LI std.utf: Added overload of codeLength which operates on a string.) + $(LI std.traits: areAllSafe has been scheduled for deprecation. Please use + allSatisfy(isSafe, ...) instead.) + $(LI clear has been renamed to destroy, and clear (as an alias to destroy) has + been scheduled for deprpecation.) + $(LI Capitalized std.traits.pointerTarget to PointerTarget. Old one is + scheduled for deprecation.) + $(LI std.algorithm.indexOf - which was scheduled for deprecation - has been deprecated (it was + easily confused with std.string.indexOf). Please use countUntil instead.) + $(LI std.cpuid - which was scheduled for deprecation - has been deprecated. + Please use core.cpuid instead.) + $(LI std.conv.ConvError and ConvOverflowException - which were scheduled for deprecation - have + been deprecated. Please catch ConvException and ConvOverflowException instead.) + $(LI The overloads of std.conv.to which were scheduled for deprecation + because formattedWrite replaced them have now been deprecated. + Please use std.format.formattedWrite instead.) + $(LI The overload of std.exception.enforce which takes the file and line number as template + arguments has been scheduled for deprecation (as it causes unnecessary template bloat). + Please use the overload which takes them as function arguments instead. This will have no + effect on any calls to enforce which do not explicitly pass the file or line number.) + $(LI std.format.FormatError - which was scheduled for deprecation - has been deprecated. + Please catch FormatException instead.) + $(LI std.file.listDir has been deprecated. Please use std.file.dirEntries instead.) + $(LI std.range.replicate - which was scheduled for deprecation - has been deprecated. + Please use repeat instead.) + $(LI std.range.SortedRange.canFind - which was scheduled for deprecation - has been deprecated. + Please use SortedRange.contains instead.) + $(LI std.socket: timeval and linger - which were scheduled for deprecation - have been deprecated. + Please use TimeVal and Linger.) + $(LI std.stdio.isStreamingDevice has been scheduled for deprecation. Please use + isFileHandle instead.) + $(LI The deprecated std.typecons.defineEnum has been removed.) + $(LI UtfException - which was scheduled for deprecation - has been deprecated. + Please use UTFException instead.) + $(LI The deprecated overloads of std.array.insert and std.array.replace + have been removed. Please use insertInPlace and replaceInPlace instead.) + $(LI The deprecated toISOExtendedString and fromISOExtendedString + functions in std.datetime have been removed. Please use + toISOExtString and fromISOExtString instead.) + $(LI The deprecated std.file.getTimesPosix has been removed. + Please use std.file.getTimes instead.) + $(LI The deprecated overloads of isFile, isDir, and isSymLink in + std.file which took uint have been removed. Please use + attrIsFile, attrIsDir, and attrIsSymlink instead.) + $(LI The deprecated std.file.DirEntry.timeStatusChanged has been removed. + Please use std.file.DirEntry.attributes to get at that information + if you need it.) + $(LI The deprecated std.contracts module has been removed. Please use + std.exception instead.) + $(LI The deprecated std.arg, std.bind, and std.loader modules have been + removed.) + + $(LI Added TypeInfo.rtInfo property to get library defined runtime info.) + $(LI Added front end support for AVX 256 bit SIMD instructions.) + $(LI Default arguments and parameter identifiers (if any) are added to the tuple generated from + IsExpression's __parameters case.) + $(LI Changed the way the align attribute works, to make it more usable and comprehensible. + Default alignment has not changed.) + $(LI The align attribute now accepts arbitrary powers of two. This affects layout + of static data, too. Such effects are dependent on limitations of the object file format - + currently Win32 programs cannot align on larger than 16 byte boundaries.) + $(LI HTML input file support completely removed.) + $(LI $(BUGZILLA 3150): cast from dynamic array to ulong is allowed) + $(LI $(BUGZILLA 3866): anonymous delegate with default parameters cross-talks to another anonymous delegate) + $(LI $(BUGZILLA 4174): Template interface functions not allowed, making operator overloads difficult) + $(LI $(BUGZILLA 6652): 1. Warn modifying non ref variable if -w is specified.) + $(LI $(BUGZILLA 7243): Compiler should call separate function when allocating a struct on the heap) + $(LI $(BUGZILLA 7923): Please remove 'deprecated' from setAssertHandler()) + $(LI $(BUGZILLA 8105): in ref) + $(LI $(BUGZILLA 8127): dmd link library paths not given precedence over gcc defaults) + $(LI $(BUGZILLA 8221): typeof(null) rejected as return type for covariant overrides) + ) + $(RUNTIMEBUGSFIXED + $(LI $(BUGZILLA 6909): incorrect definition of the OVERLAPPED struct in core.sys.windows.windows ?) + ) + $(LIBBUGSFIXED + $(LI $(BUGZILLA 2328): setTypeInfo in gc.d backwards.) + $(LI $(BUGZILLA 2588): std.signals should not use 'length' stealth keyword in indexing) + $(LI $(BUGZILLA 4405): all function - returns whether predicate is true for all elements in a range) + $(LI $(BUGZILLA 4603): array(iota(1, 0)) error) + $(LI $(BUGZILLA 4605): Wrong print of an int[string] aa) + $(LI $(BUGZILLA 4629): BufferedFile.printf() wants char[] as first argument) + $(LI $(BUGZILLA 4695): std.range.zip is broken) + $(LI $(BUGZILLA 4744): std.conv: string->enum doesn't look for longer match) + $(LI $(BUGZILLA 4822): Problem with std.stdio.File.writef("%c") + $(LI $(BUGZILLA 5011): std.container: SList linearRemove produces wrong results) + $(LI $(BUGZILLA 5089): feqrel does not compile for floats) + $(LI $(BUGZILLA 5260): std.math.feqrel() returns negative number) + $(LI $(BUGZILLA 5346): instantiation of std.conv.toImpl and std.format.formatValue fails for unions) + $(LI $(BUGZILLA 5354): formatValue: range templates introduce 3 bugs related to class & struct cases) + $(LI $(BUGZILLA 5786): std.algorithm.sort does not work with std.container.Array: Range violation) + $(LI $(BUGZILLA 5843): Unable to convert a struct with an alias-this to long/ulong to int, using std.conv.to!int.) + $(LI $(BUGZILLA 5970): fix BigInt.toString) + $(LI $(BUGZILLA 6027): bigint to!string conversion and its implications) + $(LI $(BUGZILLA 6175): String corruption when passing static char arrays to std.conv) + $(LI $(BUGZILLA 6191): removechars doesn't accept a const string) + $(LI $(BUGZILLA 6197): std.traits.isImplicitlyConvertible returns some wrong results.) + $(LI $(BUGZILLA 6222): A problem with iota() using size_t) + $(LI $(BUGZILLA 6231): [patch] std.conv.to/std.format.: Structs with toString and isInputRange match multiple templates.) + $(LI $(BUGZILLA 6273): Tuple [] operator in pure function) + $(LI $(BUGZILLA 6379): std.container.SList fails to compile) + $(LI $(BUGZILLA 6437): Refcounted calls dtor before ctor, never calls dtor for globals) + $(LI $(BUGZILLA 6547): Call to std.algorithm.remove causes compile error) + $(LI $(BUGZILLA 6580): scoped classes are aligned incorrectly) + $(LI $(BUGZILLA 6597): to!SomeString should use std.format.formatValue) + $(LI $(BUGZILLA 6642): SysTime should not be hasUnsharedAliasing) + $(LI $(BUGZILLA 6892): Formatted write with specified length of enum member) + $(LI $(BUGZILLA 6926): std.process.system return wrong exit code) + $(LI $(BUGZILLA 7022): File.byLine doesn't release file handle) + $(LI $(BUGZILLA 7138): Can't call array() on dirEntries) + $(LI $(BUGZILLA 7317): writeln cannot handle alias this of array type) + $(LI $(BUGZILLA 7326): write interprets enum with byte backing type as a character) + $(LI $(BUGZILLA 7348): to!string(null) matches more than one template declaration) + $(LI $(BUGZILLA 7356): Implement KeyType, ValueType for hashes in std.traits) + $(LI $(BUGZILLA 7360): Predicate templates in std.traits should consider alias this) + $(LI $(BUGZILLA 7515): The new std.string.translate is slow for ASCII text) + $(LI $(BUGZILLA 7537): `File.tmpfile` requires administrator rights on Windows) + $(LI $(BUGZILLA 7561): std.net.curl broken) + $(LI $(BUGZILLA 7660): toImpl conflict in std.conv) + $(LI $(BUGZILLA 7796): std.typecons.Unique is using writeln without importing std.stdio) + $(LI $(BUGZILLA 7824): isInputRange fails to recognize inout(T)[]) + $(LI $(BUGZILLA 7831): Unlisted @@@BUG in File.detach causes FILE* leaks when reopening) + $(LI $(BUGZILLA 7878): A problem with purity and general templated algorithms) + $(LI $(BUGZILLA 7898): [CTFE] std.algorithm:copy fails when used with two arrays) + $(LI $(BUGZILLA 7909): to!(enum)(string) and to!(string)(enum) break when enum is integral) + $(LI $(BUGZILLA 7919): Sample code works on GDC but fails with DMD) + $(LI $(BUGZILLA 7936): std.random.randomSample always returns the same first value when passed a random number generator) + $(LI $(BUGZILLA 7937): Range iota.Result should be const where possible) + $(LI $(BUGZILLA 7944): std.range.iota.popFront() cycles when the range is empty) + $(LI $(BUGZILLA 7948): std.range.zip broken with requireSameLength) + $(LI $(BUGZILLA 7962): std.regex: Captures.length() returns incorrect value) + $(LI $(BUGZILLA 7973): BigInt %= long/ulong gives wrong value) + $(LI $(BUGZILLA 7975): Incorrect quotes escaping in std.format) + $(LI $(BUGZILLA 7982): iota broken when start and end are unsigned and step is negative.) + $(LI $(BUGZILLA 7993): BigInt divide-by-1 error) + $(LI $(BUGZILLA 8003): Phobos uses deprecated std.path sep symbol) + $(LI $(BUGZILLA 8011): BigInt ++ and -- do wrong thing on negative numbers) + $(LI $(BUGZILLA 8015): std.typecons.Tuple does not support struct with alias method this) + $(LI $(BUGZILLA 8022): BigInt division bug (2)) + $(LI $(BUGZILLA 8026): Fix or disallow randomShuffle() on fixed-sized arrays) + $(LI $(BUGZILLA 8031): If a class have some signals it's impossible for a derived class to have any signals) + $(LI $(BUGZILLA 8037): hasElaborateDestructor is false for non-zero-length static array of structs with elaborate destructor) + $(LI $(BUGZILLA 8039): `scoped` doesn't call any elaborate destructors for struct fields) + $(LI $(BUGZILLA 8040): writeln(null) too) + $(LI $(BUGZILLA 8055): [Regression 2.059] std.algorithm.move corrupts moved object field) + $(LI $(BUGZILLA 8057): std.algorithm.move cannot use for nested struct) + $(LI $(BUGZILLA 8080): 'alias this' causes toString to be shadowed by aliased object) + $(LI $(BUGZILLA 8112): std.algorithm.fill must accept InputRange) + $(LI $(BUGZILLA 8158): std.algorithm.min fails to compile with user-defined types) + $(LI $(BUGZILLA 8164): BigInt from char[] too) + $(LI $(BUGZILLA 8165): BigInt opAssign return value) + $(LI $(BUGZILLA 8171): [Regression 2.060head] Broken std.algorithm.move for nested struct has no member) + $(LI $(BUGZILLA 8186): Formatting class object has an alias this to int* field is broken.) + $(LI $(BUGZILLA 8187): replaceFirst doesn't work for string[] haystack) + $(LI $(BUGZILLA 8191): cstream.printf is completely unusable on x86_64) + $(LI $(BUGZILLA 8195): Segfault when comparing a VariantN to a non-variant type which it holds) + $(LI $(BUGZILLA 8203): Use of std.regex.match() generates "not enough preallocated memory" error) + $(LI $(BUGZILLA 8214): blocking option for TaskPool.finish()) + $(LI $(BUGZILLA 8233): std.array.array fails to compile with ranges of immutable elements which have a length property) + $(LI $(BUGZILLA 8240): std.algorithm.joiner and empty inputRangeObject) + $(LI $(BUGZILLA 8264): [std.conv.to] constructing conversion doesn't work with alias this) + $(LI $(BUGZILLA 8310): writeln of Range of fixed size array) + $(LI $(BUGZILLA 8323): std.string.chompPrefix does not handle differing string types properly) + $(LI $(BUGZILLA 8362): std.traits.isSafe doesn't work with unsafe lamdba functions) + $(LI $(BUGZILLA 8386): writeln stopped working with wstring) + $(LI $(BUGZILLA 8398): enforceEx cannot be used with OutOfMemoryError) + $(LI $(BUGZILLA 8450): std.traits.isSafe doesn't work with unsafe lamdba functions) + )) + $(DMDBUGSFIXED + $(LI $(BUGZILLA 1175): nested class inheritance) + $(LI $(BUGZILLA 1780): Type tuple deduction failure for class templates) + $(LI $(BUGZILLA 2472): Delegates are not lvalue.) + $(LI $(BUGZILLA 2962): ICE(glue.c) or bad codegen passing variable as template value parameter) + $(LI $(BUGZILLA 3290): accepts-invalid: non-const by-ref foreach over a const array is accepted) + $(LI $(BUGZILLA 3574): post-condition in void main() is not evaluated if there is no return statement) + $(LI $(BUGZILLA 3608): Allow isExpression and templates to capture template parameters and FQN of template) + $(LI $(BUGZILLA 3703): static array assignment) + $(LI $(BUGZILLA 3895): Appending a double[] to a float[] generates wrong code) + $(LI $(BUGZILLA 4024): Last catch only accepts block statement) + $(LI $(BUGZILLA 4155): return of NaN to temporary fails equality test) + $(LI $(BUGZILLA 4288): Error on passing delegate to C linkage function) + $(LI $(BUGZILLA 4364): ICE(class.c) compiling a struct def named 'Object' followed by a class definition) + $(LI $(BUGZILLA 4510): [tdpl] ref with a wrong type specifier is accepted) + $(LI $(BUGZILLA 4583): PIC code not working: EBX register set incorrectly) + $(LI $(BUGZILLA 4785): auto return of a function with in contract) + $(LI $(BUGZILLA 4884): Using template struct parameters in method definition fails with "parameter _param_0 is already defined") + $(LI $(BUGZILLA 4953): Regression(2.031): templates don't do implicit conversion properly) + $(LI $(BUGZILLA 4967): member default initializers not working in static struct initializers) + $(LI $(BUGZILLA 5039): Cannot use invariant() with auto methods) + $(LI $(BUGZILLA 5082): delegate alias parameters are silently accepted inside structs. limits most of std.algorithm, etc.) + $(LI $(BUGZILLA 5435): Static foreach over tuple ignores type annotation) + $(LI $(BUGZILLA 5437): Problems with length of std.traits.EnumMembers) + $(LI $(BUGZILLA 5473): Members of const-qualified classes are not const themselves.) + $(LI $(BUGZILLA 5737): postblit not called for locals initialized from ref functions) + $(LI $(BUGZILLA 5809): [64 bit] wrong code for *p==0, when widening conversion occurs) + $(LI $(BUGZILLA 5896): const overload matching is succumb to template parameter one) + $(LI $(BUGZILLA 6189): [64bit] optimizer: register content destroyed in function prolog) + $(LI $(BUGZILLA 6199): [GSoC] Postblit not called when returning a reference to a by-value function) + $(LI $(BUGZILLA 6470): postblits not called on arrays of structs) + $(LI $(BUGZILLA 6475): template identifier is not a member of alias) + $(LI $(BUGZILLA 6591): di header generation loses selective import symbols) + $(LI $(BUGZILLA 6612): Associative arrays with associative array keys literals) + $(LI $(BUGZILLA 6636): Destructors of static array elements are not called on function parameter) + $(LI $(BUGZILLA 6637): Postblits of static array elements are not called on function argument) + $(LI $(BUGZILLA 6758): std.c.stdarg problems with 8 or more integer arguments on x86_64) + $(LI $(BUGZILLA 6891): template with uint value parameter causes several issues) + $(LI $(BUGZILLA 7396): Indicate default alignment with 0.) + $(LI $(BUGZILLA 7385): Bad error message missing line number on invalid array op that isn't special cased) + $(LI $(BUGZILLA 7413): Vector literals don't work) + $(LI $(BUGZILLA 7414): Vector literal assignment doesn't work in global scope) + $(LI $(BUGZILLA 7418): Overloading doesn't work with aliases declared inside templates) + $(LI $(BUGZILLA 7453): Can't return value from within opApply) + $(LI $(BUGZILLA 7478): stack overflow compiling with -deps -release -inline -noboundscheck) + $(LI $(BUGZILLA 7494): Selective import does not work inside a function) + $(LI $(BUGZILLA 7506): Postblit does not called properly with inlining) + $(LI $(BUGZILLA 7530): Postblit not called structs returned from an array index expr.) + $(LI $(BUGZILLA 7560): Base class overloaded methods created by mixins can't be overriden) + $(LI $(BUGZILLA 7581): Compiler uses wrong instructions to move complex value from ST to xmm registers) + $(LI $(BUGZILLA 7585): functions in templates inferred as delegate) + $(LI $(BUGZILLA 7750): while(true) loop with try/catch block causes segfault) + $(LI $(BUGZILLA 7770): __dollar cannot be read at compile time) + $(LI $(BUGZILLA 7784): ICE with self-referencing literals) + $(LI $(BUGZILLA 7793): static assert( void_function() ) gives misleading error message) + $(LI $(BUGZILLA 7807): Ambiguous virtual function error on const overloading with covariant return types) + $(LI $(BUGZILLA 7851): Internal error: e2ir.c 688) + $(LI $(BUGZILLA 7880): [CTFE] cast from void array allowed with different results than at runtime) + $(LI $(BUGZILLA 7893): Spec completely wrong for D variadic arguments on 64 bits) + $(LI $(BUGZILLA 7894): [CTFE] - goto within ForStatement restarts loop) + $(LI $(BUGZILLA 7906): [ICE] enum declaration with invalid array literal crashes dmd) + $(LI $(BUGZILLA 7907): [ICE] invalid expression on template argument crashes dmd) + $(LI $(BUGZILLA 7911): Nested static if failing to execute) + $(LI $(BUGZILLA 7922): alias this causes weird formatting issues for strings) + $(LI $(BUGZILLA 7929): Broken semantic of StructInitializer with const) + $(LI $(BUGZILLA 7931): Error message with _error_ with var[1,2]) + $(LI $(BUGZILLA 7932): Corrupted argument inside out contract in x86_64) + $(LI $(BUGZILLA 7933): Illegal interaction of templates) + $(LI $(BUGZILLA 7941): Regression(2.059): Type check is ignored when manifest constant initializer is function literal) + $(LI $(BUGZILLA 7943): UFCS does not work with alias this) + $(LI $(BUGZILLA 7945): alias this doesn't work on function ref parameter) + $(LI $(BUGZILLA 7949): [ICE] (cgcod.c) with SIMD array) + $(LI $(BUGZILLA 7950): Type tuples are incorrectly flattened in base type list of interface) + $(LI $(BUGZILLA 7951): DMD: Internal error: backend/cgxmm.c 567) + $(LI $(BUGZILLA 7965): Invalid outer function scope pointer in some cases) + $(LI $(BUGZILLA 7974): forward reference of mixin declaration) + $(LI $(BUGZILLA 7983): ICE with getMember on a unittest member) + $(LI $(BUGZILLA 7987): [CTFE] cannot compare arrays of slices) + $(LI $(BUGZILLA 8002): Excess initial errors when passing template args to non-templated struct) + $(LI $(BUGZILLA 8004): Direct call of function literal should consider default arguments) + $(LI $(BUGZILLA 8005): Lambda with parameter type inference should consider default args) + $(LI $(BUGZILLA 8016): Methods defined in external object files when template alias parameter is involved) + $(LI $(BUGZILLA 8032): `mixin template` before virtual method with same method causes an error) + $(LI $(BUGZILLA 8036): Zero-length static array of structs with elaborate destructor as struct or class field is rejected) + $(LI $(BUGZILLA 8038): #line which is in a double template instantiation doesn't work) + $(LI $(BUGZILLA 8060): xmmstore cannot allocate store for optimized operation that uses int and floats) + $(LI $(BUGZILLA 8064): return reference semantics not obeyed on delegates?) + $(LI $(BUGZILLA 8066): ICE on missing return statement if invariant is present) + $(LI $(BUGZILLA 8069): incorrect ambiguous virtual function error) + $(LI $(BUGZILLA 8073): Regression (git) Error: undefined identifier __result) + $(LI $(BUGZILLA 8089): Importing package as module causes segfault) + $(LI $(BUGZILLA 8091): Optimizer generates wrong code when reducing comparisons) + $(LI $(BUGZILLA 8094): Static if matching using alias parameter in template fails) + $(LI $(BUGZILLA 8095): [64 bit] Wrong code generation with spilled register, -m64 -O) + $(LI $(BUGZILLA 8098): Inner class method can modify outer's members regardless of constancy) + $(LI $(BUGZILLA 8099): Inner class's outer pointer matches constancy of inner, but can be set to object of arbitrary constancy) + $(LI $(BUGZILLA 8182): with a lazy struct parameter, the struct's destructor is called on the generated delegate) + $(LI $(BUGZILLA 8180): UFCS writeln doesn't work with Tuples) + $(LI $(BUGZILLA 8113): alias this doesn't forward opCall) + $(LI $(BUGZILLA 8123): alias declaration lookup is broken) + $(LI $(BUGZILLA 8125): TypeInstance dedunction problem) + $(LI $(BUGZILLA 8129): Cannot deduce template function when using partially specified type in function parameter) + $(LI $(BUGZILLA 8147): Blah!R.init now requires parens - (Blah!R).init) + $(LI $(BUGZILLA 8168): dmd crashes when asm statement with wrong opcode) + $(LI $(BUGZILLA 8169): Method loses its compile-time evaluability when used through alias this) + $(LI $(BUGZILLA 8185): Pure functions and pointers) + $(LI $(BUGZILLA 8188): need this to access member when mixining in a function) + $(LI $(BUGZILLA 8190): Externally defined struct error message) + $(LI $(BUGZILLA 8194): "Function cannot access frame" even though all I requested was the type) + $(LI $(BUGZILLA 8198): Nested lambda inference doesn't work) + $(LI $(BUGZILLA 8199): stack is not aligned in finally block) + $(LI $(BUGZILLA 8212): shared value data structures should implicitly cast to mutable) + $(LI $(BUGZILLA 8216): CTFE should allow 'pointer is inside range' comparisons) + $(LI $(BUGZILLA 8226): Global lambda assign to const/immutable) + $(LI $(BUGZILLA 8237): Error message with _error_ when using failed type inference in template parameter) + $(LI $(BUGZILLA 8241): cannot use template function literal as default alias argument) + $(LI $(BUGZILLA 8242): cannot use template function literals at module scope) + $(LI $(BUGZILLA 8249): Spurious error message with templates and alias this) + $(LI $(BUGZILLA 8252): no UFCS for 0 literal) + $(LI $(BUGZILLA 8276): [CTFE] ICE when reading variable from nested function) + $(LI $(BUGZILLA 8283): ICE(cod1.c): returning struct with constructor as member of another struct) + $(LI $(BUGZILLA 8315): Invalid nested-ref check in template constraint) + $(LI $(BUGZILLA 8335): `ref` is ignored for static array of stucts with postblit argument) + $(LI $(BUGZILLA 8390): Refused array operation mutable[] += const[]) + $(LI $(BUGZILLA 8397): parameter types are not checked when assigning a function literal) + $(LI $(BUGZILLA 8423): Wrong code for bool parameter in 5th integer register.) + $(LI $(BUGZILLA 8429): [2.060 beta] 'version' rejected inside 'static if's) + $(LI $(BUGZILLA 8434): [Regression 2.058] cannot implicitly convert expression (vs1.opCast()) of type const(Vector2D) to object.Object) + $(LI $(BUGZILLA 8437): [2.060 beta] static struct no size yet for forward reference) + $(LI $(BUGZILLA 8442): [2.060 beta] Empty array enum not treated as immutable) + $(LI $(BUGZILLA 8453): Associative array keys refused as property by sort) + $(LI $(BUGZILLA 8454): [ICE] (backend\cg87.c 3497) with cdouble and sqrt) + ) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.060 + TITLE=Change Log: $(VER) diff --git a/changelog/2.061.dd b/changelog/2.061.dd new file mode 100644 index 0000000000..68326215ab --- /dev/null +++ b/changelog/2.061.dd @@ -0,0 +1,159 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 1, 2013, =================================================, + + $(WHATSNEW + $(LI DMD now shows deprecated features as warnings by default (a + message is displayed but compilation is not halted anymore). + There are also 2 new compiler flags: -de, to get the old default + behaviour (using deprecated features is an error) and -dw, to + explicitly enable the new default behaviour (just warn). + This makes it possible to add -de in the configuration file to + get the old default and still be able to override that default + by using -dw when compiling. + The -d flag stays the same (silently ignore deprecated features). + ) + $(LI Complete list of $(WHATSNEW2 2012-08-02, 2012-12-31)) + ) + $(BUGSFIXED + $(LI $(DMDBUGSFIXED2 2012-08-02, 2013-01-01)) + $(LI $(DRUNTIMEBUGSFIXED2 2012-08-02, 2012-12-31)) + $(LI $(PHOBOSBUGSFIXED2 2012-08-02, 2012-12-31)) + ) +$(COMMENT + $(WHATSNEW + $(LI $(BUGZILLA 1353): Can't use typeof() in base class list.) + $(LI $(BUGZILLA 1427): Generated .di files look ugly and are hard to read) + $(LI $(BUGZILLA 8108): Forward declaration and implementation allowed in same file) + $(LI $(BUGZILLA 8794): DDoc should provide qualified symbol names suitable for anchors) + $(LI $(BUGZILLA 9219): Allow matching { } in asm statements.) + $(LI $(BUGZILLA 9221): Added -di flag to make use of deprecated symbols a warning) + $(LI $(BUGZILLA 9222): Add User Defined Attributes) + $(LI $(BUGZILLA 9223): Add -de and -dw switches) + $(LI $(BUGZILLA 9224): Add Win64 code generation support for use with Visual C) + $(LI $(BUGZILLA 9225): Add sections [Environment32] and [Environment64] to sc.ini/dmd.conf) + $(LI $(BUGZILLA 9226): More simd instructions allowed as intrinsics.) + $(LI $(BUGZILLA 9227): __traits(identifier,...) to pick out identifier from parameter list tuple) + $(LI $(BUGZILLA 9228): Add getProtection to __traits()) + ) + $(RUNTIMEBUGSFIXED + $(LI $(BUGZILLA 391): .sort and .reverse break utf8 encoding) + $(LI $(BUGZILLA 8936): Throwing results in searching the whole directory tree rooted in current directory) + ) + $(LIBBUGSFIXED + $(LI $(BUGZILLA 9060): std.range.chain and std.range.zip cannot get frame pointer) + ) + $(DMDBUGSFIXED + $(LI $(BUGZILLA 2273): Whitespace is not inserted after commas) + $(LI $(BUGZILLA 2775): "private" ignored for templates) + $(LI $(BUGZILLA 2830): private attribute doesn't work for structs/unions/classes) + $(LI $(BUGZILLA 4082): nothrow main() can throw) + $(LI $(BUGZILLA 5448): Array of AAs literal doesn't work) + $(LI $(BUGZILLA 5587): Use __LINE__ to pick number in unittest block names) + $(LI $(BUGZILLA 5679): Type aliasing "this" from an access function defined in base class confuses the compiler about the type of objects) + $(LI $(BUGZILLA 5832): Template alias parameters are never successfully pattern matched) + $(LI $(BUGZILLA 5996): ICE(expression.c) CTFE of erroneous auto return function) + $(LI $(BUGZILLA 6373): More descriptive 'hidden by X is deprecated' error) + $(LI $(BUGZILLA 6395): ICE(glue.c) Multiple-at-a-time bug breaking e.g. DustMite) + $(LI $(BUGZILLA 6937): new with struct doesn't allow field assignment) + $(LI $(BUGZILLA 6969): Forward reference on template class triangle) + $(LI $(BUGZILLA 7003): no tuple expansion for c++ mangling) + $(LI $(BUGZILLA 7017): Pure inference makes inconsistent result) + $(LI $(BUGZILLA 7192): improve error message for "object.d cannot be read") + $(LI $(BUGZILLA 7220): Bad initialization when using mixin to generate a static field in a -lib'rary) + $(LI $(BUGZILLA 7810): [CTFE] Typesafe variadic function with array of structs) + $(LI $(BUGZILLA 7876): [CTFE] assertion failure on invalid stack reference) + $(LI $(BUGZILLA 7940): CTFE wrong-code for opAssign and std.array.Appender) + $(LI $(BUGZILLA 7998): static assert message string printing problem) + $(LI $(BUGZILLA 8178): Wrong line number in trying to modify enum string) + $(LI $(BUGZILLA 8257): __traits(compiles) gives compile error) + $(LI $(BUGZILLA 8271): [Ddoc] non-ascii character string macro names cannot be replaced) + $(LI $(BUGZILLA 8339): is(typeof(...)) is reporting true when it's false due to nested function error) + $(LI $(BUGZILLA 8376): 64 bit codegen bug involving dynamically indexed static array and continue statement) + $(LI $(BUGZILLA 8377): Unexpected OPTLINK Termination at EIP=004106BE) + $(LI $(BUGZILLA 8340): *= operator breaks long array in x64) + $(LI $(BUGZILLA 8348): ICE(glue.c): 'semanticRun == PASSsemantic3done' on line 547 in file 'glue.c') + $(LI $(BUGZILLA 8422): [CTFE] TypeTuple of tuples can't be read at compile time) + $(LI $(BUGZILLA 8408): Purity calculation should be improved) + $(LI $(BUGZILLA 8484): [CTFE] Assertion failure: 'thisval $(AMP)$(AMP) thisval->op == TOKclassreference' on line 4896 in file 'interpret.c'.) + $(LI $(BUGZILLA 8497): Regression 2.060: Bad code gen involving ubyte, ternary operators, and shifts) + $(LI $(BUGZILLA 8519): winsamp.d doesn't compile with 2.060) + $(LI $(BUGZILLA 8556): Using take results in a corrupted call to opSlice) + $(LI $(BUGZILLA 8601): CTFE Assertion failure (interpret.c) on dstring[].toUpper) + $(LI $(BUGZILLA 8623): Multiple function match needs to print file+line numbers) + $(LI $(BUGZILLA 8624): Regression: CTFE: long comparisons completely broken) + $(LI $(BUGZILLA 8630): Assertion failure: 'fd $(AMP)$(AMP) fd->inferRetType' on line 81 in file 'mangle.c') + $(LI $(BUGZILLA 8644): CTFE doesn't support string $(LESS),$(GREATER) on array literals) + $(LI $(BUGZILLA 8673): enum z = [0][(()=>$-1)()]; crashes the compiler) + $(LI $(BUGZILLA 8675): Nothrow can't throw Errors) + $(LI $(BUGZILLA 8714): Missing error message with circular use of CTFE) + $(LI $(BUGZILLA 8770): Wrong error line number with immutable field) + $(LI $(BUGZILLA 8774): 2.059 worked 2.060 does not: nested delegate memory corruption) + $(LI $(BUGZILLA 8788): The super constructor call can be prevented by mentioning "return".) + $(LI $(BUGZILLA 8796): Optimizer bug on 64bit: *p++=1 where p is a parameter) + $(LI $(BUGZILLA 8801): assigning to __ctfe crashes the compiler) + $(LI $(BUGZILLA 8818): CTFE fails to compare strings correctly) + $(LI $(BUGZILLA 8830): [CTFE] Incorrect slicing with pointer from sliced array) + $(LI $(BUGZILLA 8836): function called with argument types ((void function())) matches both f(void function() fn) and f(void delegate() dg)) + $(LI $(BUGZILLA 8840): calculating minimum of longs with following comparison compiles to wrong code when enabling the optimizer) + $(LI $(BUGZILLA 8857): [CTFE] does not evaluate to a boolean, only with -inline) + $(LI $(BUGZILLA 8870): Incorrect values passing struct by value) + $(LI $(BUGZILLA 8889): [2.061 beta][64-bit] Assertion Failure argtypes.c) + $(LI $(BUGZILLA 8894): 2.059: Lookup error message has become uninformative) + $(LI $(BUGZILLA 8923): Destructors of struct members get called at the wrong point) + $(LI $(BUGZILLA 8928): Poor error message for derived class without constructor) + $(LI $(BUGZILLA 8939): ICE(glue.c) on passing by ref statically initialized const/immutable variable) + $(LI $(BUGZILLA 8940): Able to modify const/immutable with passing to a templated function by `ref`) + $(LI $(BUGZILLA 8942): `alias ` ignores in foreach over tuple) + $(LI $(BUGZILLA 8943): Cannot get parent of an overload) + $(LI $(BUGZILLA 8966): ICE(cgcod.c) when passing cfloat argument with indirection) + $(LI $(BUGZILLA 8971): __traits(getOverloads) fails in a member function) + $(LI $(BUGZILLA 8986): The PVS-Studio analyzer has something for you) + $(LI $(BUGZILLA 8990): Forward reference error on three structs) + $(LI $(BUGZILLA 8937): import declaration statement without scope after `if` imports to a parent scope) + $(LI $(BUGZILLA 8987): Compiling using -O -release options yield Internal error: backend\cgcod.c 1663) + $(LI $(BUGZILLA 9000): ICE on assigning struct's `init` to enum) + $(LI $(BUGZILLA 9003): Nested structs smetimes have null context pointers in static struct) + $(LI $(BUGZILLA 9004): Wrong line number for undefined identifier error) + $(LI $(BUGZILLA 9006): Static struct with nested struct fields sometimes has current context pointers in `init`) + $(LI $(BUGZILLA 9008): Another forward referencing bug) + $(LI $(BUGZILLA 9010): opEquals() const results in not-covered code) + $(LI $(BUGZILLA 9013): Compiler crash with foreach on wrongly defined interval) + $(LI $(BUGZILLA 9025): core.thread.Fiber seems to crash on Win64) + $(LI $(BUGZILLA 9026): Template mixin identifier as template alias parameter doesn't work) + $(LI $(BUGZILLA 9035): Nested struct `init` is lvalue and can be modified) + $(LI $(BUGZILLA 9036): postblit is called for nested structs when assigning `init`) + $(LI $(BUGZILLA 9046): typeof(T.init) should have the type T) + $(LI $(BUGZILLA 9057): Regression(Beta): Segfault or 'Non-constant expression' error with local import) + $(LI $(BUGZILLA 9058): Problem with std.traits.EnumMembers conversion to array) + $(LI $(BUGZILLA 9069): struct literals are treated as lvalues) + $(LI $(BUGZILLA 9070): nothrow of constructer/destructor isn't correct) + $(LI $(BUGZILLA 9076): Aliased template function and property resolution doesn't work) + $(LI $(BUGZILLA 9077): Struct copy constructor ignored when opAssign with a different type is present) + $(LI $(BUGZILLA 9090): auto ref doesn't work with arrays) + $(LI $(BUGZILLA 9093): Overloads in extern(C++) interfaces throw up COMDAT errors) + $(LI $(BUGZILLA 9100): Weird behavior on template instance argument) + $(LI $(BUGZILLA 9124): Object variable of variadic template struct needs explicit "this" in certain situations) + $(LI $(BUGZILLA 9140): ref foreach of immutables in postcondition) + $(LI $(BUGZILLA 9143): template structs with two parameters confuse DMD on multiple instantiations) + $(LI $(BUGZILLA 9153): Type inference for array of delegates should not break based on order) + $(LI $(BUGZILLA 9154): Incorrectly generated assignment operator) + $(LI $(BUGZILLA 9162): [tdpl] Non-static structs should have access to outer lexical scope) + $(LI $(BUGZILLA 9170): CTFE: Allow reinterpret casts float $(LESS)-$(GREATER) int) + $(LI $(BUGZILLA 9171): error optimization of expression) + $(LI $(BUGZILLA 9210): [2.061 beta] Import cycle causes unpredictable compile errors) + $(LI $(BUGZILLA 9213): [2.061 beta] Member access without this and __traits(compiles, ...)) + ) +) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.061 + TITLE=Change Log: $(VER) + WHATSNEW2=$(LINK2 https://issues.dlang.org/buglist.cgi?chfieldto=$2$(AMP)query_format=advanced$(AMP)chfield=resolution$(AMP)chfieldfrom=$1$(AMP)chfieldvalue=FIXED$(AMP)bug_severity=enhancement$(AMP)bug_status=RESOLVED$(AMP)version=D2$(AMP)version=D1%20%26%20D2$(AMP)resolution=FIXED$(AMP)product=D, New/Changed Features) + DMDBUGSFIXED2=$(LINK2 https://issues.dlang.org/buglist.cgi?chfieldto=$2$(AMP)query_format=advanced$(AMP)chfield=resolution$(AMP)chfieldfrom=$1$(AMP)chfieldvalue=FIXED$(AMP)bug_severity=regression$(AMP)bug_severity=blocker$(AMP)bug_severity=critical$(AMP)bug_severity=major$(AMP)bug_severity=normal$(AMP)bug_severity=minor$(AMP)bug_severity=trivial$(AMP)bug_status=RESOLVED$(AMP)version=D2$(AMP)version=D1%20%26%20D2$(AMP)component=DMD$(AMP)resolution=FIXED$(AMP)product=D, DMD Bugs Fixed) + DRUNTIMEBUGSFIXED2=$(LINK2 https://issues.dlang.org/buglist.cgi?chfieldto=$2$(AMP)query_format=advanced$(AMP)chfield=resolution$(AMP)chfieldfrom=$1$(AMP)chfieldvalue=FIXED$(AMP)bug_severity=regression$(AMP)bug_severity=blocker$(AMP)bug_severity=critical$(AMP)bug_severity=major$(AMP)bug_severity=normal$(AMP)bug_severity=minor$(AMP)bug_severity=trivial$(AMP)bug_status=RESOLVED$(AMP)version=D2$(AMP)version=D1%20%26%20D2$(AMP)component=druntime$(AMP)resolution=FIXED$(AMP)product=D, Druntime Bugs Fixed) + PHOBOSBUGSFIXED2=$(LINK2 https://issues.dlang.org/buglist.cgi?chfieldto=$2$(AMP)query_format=advanced$(AMP)chfield=resolution$(AMP)chfieldfrom=$1$(AMP)chfieldvalue=FIXED$(AMP)bug_severity=regression$(AMP)bug_severity=blocker$(AMP)bug_severity=critical$(AMP)bug_severity=major$(AMP)bug_severity=normal$(AMP)bug_severity=minor$(AMP)bug_severity=trivial$(AMP)bug_status=RESOLVED$(AMP)version=D2$(AMP)version=D1%20%26%20D2$(AMP)component=Phobos$(AMP)resolution=FIXED$(AMP)product=D, Phobos Bugs Fixed) diff --git a/changelog/2.062.dd b/changelog/2.062.dd new file mode 100644 index 0000000000..f4806f47f1 --- /dev/null +++ b/changelog/2.062.dd @@ -0,0 +1,323 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 18, 2013, =================================================, +$(BUGSTITLE Language Changes, + +$(LI $(D typeof()) change:) + +$(P As a result of fixing $(BUGZILLA 6408), the usage of $(D typeof()) and indexing may require changes to user code:) + +--------- +template ElementTypeOf(T) +{ + alias typeof(T[0]) ElementTypeOf; +} + +void main() +{ + // worked in 2.061 due to a bug + static assert(is(ElementTypeOf!(int[]) == int)); +} +--------- + +$(P The expression in $(D typeof(T[0])) used to be wrongly interpreted as the element type of $(B T), however in v2.062 it is interpreted as a static array of element $(B T) with length 0. To work around this the user can either use a trait from the standard library, or use the $(D .init) property of a type for arbitrary expressions:) + +--------- +import std.range; + +template ElementTypeOf(T) +{ + // use T.init + alias typeof(T.init[0]) ElementTypeOf; +} + +void main() +{ + // use std.range.ElementType + static assert(is(ElementType!(int[]) == int)); + + // use custom template after fixing its code + static assert(is(ElementTypeOf!(int[]) == int)); +} +--------- + +$(LI $(D alias) syntax change:) + +$(P The newly introduced "$(D alias foo = int)" syntax is not usable with +$(DDSUBLINK spec/class, AliasThis, subtyping). This is to prevent confusion from a possible future syntax which would enable aliasing of super constructors. For now, the existing $(D alias) syntax can be used:) + +--------- +struct S +{ + int x; + // alias this = x; // error + alias x this; +} +--------- + +$(P In the upcoming release (v2.063) a new syntax will be introduced:) + +--------- +struct S +{ + int x; + alias this : x; // new feature in upcoming 2.063 +} +--------- + +) + +$(BR)$(BIG List of all bug fixes and enhancements:) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 9174): regression$(LPAREN)2.057$(RPAREN) ice$(LPAREN)cast.c$(RPAREN) with ternary operator and alias this) +$(LI $(BUGZILLA 9244): union containing pointers not allowed) +$(LI $(BUGZILLA 9258): opAssign with base class triggers "identity assignment operator overload" error) +$(LI $(BUGZILLA 9259): Passing an array of pointers to a typesafe vararg is broken) +$(LI $(BUGZILLA 9263): statement is not reachable when statement is reachable) +$(LI $(BUGZILLA 9266): Cannot define two Tuple objects.) +$(LI $(BUGZILLA 9268): [ice-on-invalid] void assignment in fail44.d no longer caught in frontend) +$(LI $(BUGZILLA 9273): DMD segfaults with templated ctors in implicit super call) +$(LI $(BUGZILLA 9276): regression$(LPAREN)2.061$(RPAREN): Forward reference error) +$(LI $(BUGZILLA 9278): ICE todt.c:692 when float containing struct is defined after use) +$(LI $(BUGZILLA 9309): Regression $(LPAREN)2.061$(RPAREN): -O -release generates wrong code) +$(LI $(BUGZILLA 9332): [REG][2.060 -> 02.061] struct constructor taking itself creates 'Warning: statement is not reachable') +$(LI $(BUGZILLA 9377): Link-failure regression cause by fixing issue 8504) +$(LI $(BUGZILLA 9385): [Regression 2.057] null literal should be implicitly convertible to bool) +$(LI $(BUGZILLA 9387): Compiler switch -O changes behavior of correct code) +$(LI $(BUGZILLA 9399): ICE with nested function, template alias parameter, -inline, depending on order of source files) +$(LI $(BUGZILLA 9404): Nullable is unusable with 2.061) +$(LI $(BUGZILLA 9406): $(LPAREN)Regression: 2.061$(RPAREN) Stack overflow from a forward reference error) +$(LI $(BUGZILLA 9409): [2.062-alpha] Regression with $ inside of expression tuples) +$(LI $(BUGZILLA 9410): [Regression 2.061] Wrong selection for function overload) +$(LI $(BUGZILLA 9416): [REG][2.060 -> 02.061] DMD eagerly instantiates template parameter-less opAssign) +$(LI $(BUGZILLA 9420): [2.062alpha] Weird "$(LPAREN)null$(RPAREN)" output in error message) +$(LI $(BUGZILLA 9435): regression$(LPAREN)head$(RPAREN): forward reference error) +$(LI $(BUGZILLA 9436): enum cannot be forward referenced with cyclic imports and mixin) +$(LI $(BUGZILLA 9496): [REG 2.061 -> 2.062 alpha] "this[1 .. $]" passes wrong "this" to "opDollar") +$(LI $(BUGZILLA 9514): "template instance … is not an alias") +$(LI $(BUGZILLA 9525): [CTFE] Cannot convert $(AMP)S to const$(LPAREN)S*$(RPAREN) at compile time) + +) + +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 1369): Unable to find 'this' in __traits$(LPAREN)getMember$(RPAREN)) +$(LI $(BUGZILLA 1730): Bogus error message calling a non-const struct method on a const struct reference) +$(LI $(BUGZILLA 1841): Closure detection doesn't work when variable is used in a nested function) +$(LI $(BUGZILLA 2452): Unimplemented method errors should show function overload) +$(LI $(BUGZILLA 3321): debug flags) +$(LI $(BUGZILLA 3466): Wrong JSON output for templated classes, structs, and interfaces) +$(LI $(BUGZILLA 4178): destructor missing in JSON output) +$(LI $(BUGZILLA 4269): Regression$(LPAREN)2.031$(RPAREN): invalid type accepted if evaluated while errors are gagged) +$(LI $(BUGZILLA 4477): JSON output for function definitions includes insufficient type information) +$(LI $(BUGZILLA 4478): JSON output omits import statements) +$(LI $(BUGZILLA 4540): Better error message for wrong switch type) +$(LI $(BUGZILLA 5168): String enums don't work with -g compiler switch) +$(LI $(BUGZILLA 5461): Invalid declaration for auto functions in .di files generated by DMD -H) +$(LI $(BUGZILLA 5933): Cannot retrieve the return type of an auto-return member function) +$(LI $(BUGZILLA 5978): ICE$(LPAREN)mtype.c$(RPAREN) when calling __traits$(LPAREN)parent$(RPAREN) on the child of an anonymous function.) +$(LI $(BUGZILLA 6057): Problem with defining enum in function) +$(LI $(BUGZILLA 6319): debug's relaxed purity does not apply to nested scopes) +$(LI $(BUGZILLA 6332): Auto-return function cannot be inferred as @safe) +$(LI $(BUGZILLA 6408): string[].init gives a wrong type) +$(LI $(BUGZILLA 6538): ICE$(LPAREN)mangle.c$(RPAREN) Invalid template constraints) +$(LI $(BUGZILLA 6552): Wrong fallthrough warning for CaseRange) +$(LI $(BUGZILLA 6652): foreach parameter with number range is always ref) +$(LI $(BUGZILLA 6708): immutable ref implicit cast to const ref) +$(LI $(BUGZILLA 6743): ICE$(LPAREN)mars.c$(RPAREN) attempting to compile an exe file) +$(LI $(BUGZILLA 6833): Floating point literals lose fractional part in headers) +$(LI $(BUGZILLA 6873): Multiple storage class is not allowed on template argument) +$(LI $(BUGZILLA 6902): Different "pure nothrow int$(LPAREN)$(RPAREN)" types) +$(LI $(BUGZILLA 6905): ref acts as auto ref when return type is missing) +$(LI $(BUGZILLA 6962): Wrong Code With Scope Exit and Array Parameter, only with -O) +$(LI $(BUGZILLA 6963): pure/nothrow inference doesn't work for function pointers) +$(LI $(BUGZILLA 7152): Can't assign null to default argument) +$(LI $(BUGZILLA 7159): Forward reference when casting auto return method) +$(LI $(BUGZILLA 7252): ICE$(LPAREN)template.c$(RPAREN): 'global.errors' on line 4893 in file 'template.c') +$(LI $(BUGZILLA 7408): traits compiles fails for built-in properties of template instances) +$(LI $(BUGZILLA 7420): Duplicate "cannot be read at compile time" error messages) +$(LI $(BUGZILLA 7585): functions in templates inferred as delegate) +$(LI $(BUGZILLA 7740): unicodeProperties cannot be read at compile time for ctRegex) +$(LI $(BUGZILLA 7950): Type tuples are incorrectly flattened in base type list of interface) +$(LI $(BUGZILLA 8053): Recursive alias this causes infinite loop) +$(LI $(BUGZILLA 8152): Linking C library causes Seg-fault) +$(LI $(BUGZILLA 8153): Warning about toHash signature is incorrect on x86_64) +$(LI $(BUGZILLA 8504): Template attribute inferrence doesn't work) +$(LI $(BUGZILLA 8583): [64 bit] AA ushort[dchar] byValue range is corrupted on x86_64) +$(LI $(BUGZILLA 8631): illegal overrides accepted) +$(LI $(BUGZILLA 8717): `private` and `protected` restrict member usage in same module) +$(LI $(BUGZILLA 8741): wrong code for struct member initialized using struct constructor) +$(LI $(BUGZILLA 8742): Anonymous nested class derived from another nested class makes DMD crash) +$(LI $(BUGZILLA 8763): struct initialization with empty variadic arguments tries to call constructor) +$(LI $(BUGZILLA 8783): ref foreach update of const fixed size arrays in constructor) +$(LI $(BUGZILLA 8787): Virtual not abstract methods in interfaces error message) +$(LI $(BUGZILLA 8832): Segfault when accessing range returned by function that has delegate referencing local variables) +$(LI $(BUGZILLA 8847): voldemort + inout confuses "is") +$(LI $(BUGZILLA 8892): Wrong diagnostic for static array assignment) +$(LI $(BUGZILLA 8898): false positive dangling else warning) +$(LI $(BUGZILLA 8913): Wrong code in IfStatement condition Expression) +$(LI $(BUGZILLA 8922): __traits$(LPAREN)parent, $(LESS)imported package$(GREATER)$(RPAREN) shows current module as a parent) +$(LI $(BUGZILLA 8969): is$(LPAREN)T == __parameters$(RPAREN) is undocumented) +$(LI $(BUGZILLA 8982): ICE$(LPAREN)ctfeexpr.c$(RPAREN) __parameters of an erroneous default parameter) +$(LI $(BUGZILLA 9018): __traits$(LPAREN)compiles, ...$(RPAREN) is true on second check for same incompilable code) +$(LI $(BUGZILLA 9083): mixin expression on template argument doesn't work) +$(LI $(BUGZILLA 9113): ICE$(LPAREN)interpret.c$(RPAREN): CTFE assignment to member of struct in union) +$(LI $(BUGZILLA 9178): UDA: getAttributes does not play well with tupleof) +$(LI $(BUGZILLA 9191): Unhelpful error message on failing override) +$(LI $(BUGZILLA 9195): Should not be able to index a pointer in safed) +$(LI $(BUGZILLA 9198): Vararg functions don't respect IFTI rules) +$(LI $(BUGZILLA 9200): Wrong SIMD code generated) +$(LI $(BUGZILLA 9208): [ICE]$(LPAREN)func.c line 1205$(RPAREN) with auto return in recursive function) +$(LI $(BUGZILLA 9236): CTFE ice on switch + with$(LPAREN)EnumType$(RPAREN)) +$(LI $(BUGZILLA 9250): Wrong line number for error involving length of a static array) +$(LI $(BUGZILLA 9254): ICE on invalid foreach aggregate) +$(LI $(BUGZILLA 9264): [64bit] Wrong code with conversion from int parameter to float) +$(LI $(BUGZILLA 9284): DMD segfaults with templated ctors in constructor delegation) +$(LI $(BUGZILLA 9291): [ICE][REG] throwing undefined identifier with nothrow crashes dmd) +$(LI $(BUGZILLA 9293): enum struct with StructInitializer reports weird error) +$(LI $(BUGZILLA 9304): Unary minus operator doesn't work correctly with SIMD types.) +$(LI $(BUGZILLA 9305): Ugly Ddoc for default template lambda expressions) +$(LI $(BUGZILLA 9312): with statement error message is wrong) +$(LI $(BUGZILLA 9315): ICE $(LPAREN)expression.c:4249, StructLiteralExp::getField$(RPAREN) Tupleof of nested struct literal) +$(LI $(BUGZILLA 9320): optimizer should do copy propagation on structs, too) +$(LI $(BUGZILLA 9322): Internal error: ../ztc/cod1.c 3510 with SIMD on OSX 32) +$(LI $(BUGZILLA 9330): Cannot run dmd test suite with MSYS) +$(LI $(BUGZILLA 9338): Compiler segfaults if try to CTFE member function without valid 'this') +$(LI $(BUGZILLA 9348): "tmpl!arg" syntax followed by "!is" or "!in") +$(LI $(BUGZILLA 9350): std.algorithm.findAdjacent unreachable code warning with infinite ranges) +$(LI $(BUGZILLA 9357): Floating-point literal should always be printed with a period in diagnostic errors) +$(LI $(BUGZILLA 9358): Compiler creates duplicate switch cases after an error) +$(LI $(BUGZILLA 9368): Final switch on typedef'ed enum is not properly checked) +$(LI $(BUGZILLA 9369): DDoc hardcodes '$(AMP)' -> '$(AMP)amp;' in code) +$(LI $(BUGZILLA 9374): 'super' should be accessible inside template constraint) +$(LI $(BUGZILLA 9398): Wrong diagnostic for ternary operator type mismatch) +$(LI $(BUGZILLA 9418): Segmentation fault using only datetime and stdio.) +$(LI $(BUGZILLA 9438): Strange RefCounted stack overflow) +$(LI $(BUGZILLA 9442): typeid$(LPAREN)$(RPAREN) doesn't work without `this.` for class fields) +$(LI $(BUGZILLA 9453): ice$(LPAREN)symbol.c$(RPAREN) with slice on temporary) +$(LI $(BUGZILLA 9458): ModExp generates invalid code against array operands) +$(LI $(BUGZILLA 9461): Ability to break typesystem with `inout`) +$(LI $(BUGZILLA 9479): _error_ in error message of type inference of a delegate literal) +$(LI $(BUGZILLA 9484): Syntax error in JSON output) +$(LI $(BUGZILLA 9510): core.bitop.bsr undefined) + +) + +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 2630): ddoc should be able to document unittests) +$(LI $(BUGZILLA 3404): JSON output should retain original alias names) +$(LI $(BUGZILLA 4194): Attributes included in JSON output) +$(LI $(BUGZILLA 5529): std.system.endian for pure functions?) +$(LI $(BUGZILLA 5893): Allow simple aliases for operator overloading) +$(LI $(BUGZILLA 6171): rdmd: cache dependency file to improve startup time [patch]) +$(LI $(BUGZILLA 8105): Implement "in ref") +$(LI $(BUGZILLA 8128): unittest blocks should be allowed in interfaces) +$(LI $(BUGZILLA 9389): ignore -Hd if -Hf is present) +$(LI $(BUGZILLA 9463): make @safe "non-escapable") + +) + +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 9355): [security] SSL certificate signature verification disabled in std.net.curl) +$(LI $(BUGZILLA 9444): Regression $(LPAREN)2.059$(RPAREN): shell doesn't throw on error.) +$(LI $(BUGZILLA 9457): isSorted$(LPAREN)string$(RPAREN) doesn't work) +$(LI $(BUGZILLA 9523): std.conv.to will no longer convert enums to themselves) + +) + +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 5065): writefln$(LPAREN)"%f" of a Tuple prints a result) +$(LI $(BUGZILLA 5265): std.array.back does not work correctly for wchar-based arrays) +$(LI $(BUGZILLA 5726): boyerMooreFinder hangs when finding) +$(LI $(BUGZILLA 5763): traits.d BaseClassesTuple function incorrectly handles Object class argument) +$(LI $(BUGZILLA 5773): sort$(LPAREN)$(RPAREN) and topN$(LPAREN)$(RPAREN) fail on sliced/resized array of tuples) +$(LI $(BUGZILLA 6066): std.container: BinaryHeap interface is broken.) +$(LI $(BUGZILLA 6436): Refcounted initialization bug) +$(LI $(BUGZILLA 6635): std.conv.emplace: enforcement is too weak) +$(LI $(BUGZILLA 6668): Wrong "to" conversion stack trace) +$(LI $(BUGZILLA 7142): Wrong formatted write of boolean values) +$(LI $(BUGZILLA 7659): std.stdio.File.close$(LPAREN)$(RPAREN) erases file.name) +$(LI $(BUGZILLA 7819): std.file.setTimes throws error on folders) +$(LI $(BUGZILLA 8078): receiveOnly should tell which type it expected and got on mismatch) +$(LI $(BUGZILLA 8314): randomSample primes with constant) +$(LI $(BUGZILLA 8326): std.string.format results in run-time exception) +$(LI $(BUGZILLA 8367): std.range.chain's template constraint is inadequate) +$(LI $(BUGZILLA 8368): std.algorithm.sort's template constraint is inadequate) +$(LI $(BUGZILLA 8567): isDynamicArrray!S == true for S with alias this to array) +$(LI $(BUGZILLA 8689): Variant opArithmetic does not attempt float conversion) +$(LI $(BUGZILLA 8694): std.zlib.$(LPAREN)Un$(RPAREN)Compress can cause an _onInvalidMemoryOperationError) +$(LI $(BUGZILLA 8837): BigInt needs better operator template constraints) +$(LI $(BUGZILLA 8890): std.algorithm.commonPrefix does not handle unicode correctly) +$(LI $(BUGZILLA 8920): iota should work with all integral types) +$(LI $(BUGZILLA 9005): std.concurrency.spawn should allow `void delegate$(LPAREN)Args$(RPAREN) shared` for new Tid) +$(LI $(BUGZILLA 9163): std.parallelism broken with extensive optimizations $(LPAREN)gdc$(RPAREN)) +$(LI $(BUGZILLA 9211): regex lookahead, $(LPAREN)?=$(LPAREN)\d\d\d$(RPAREN)+\b$(RPAREN) failed) +$(LI $(BUGZILLA 9288): Parameter$(LPAREN)Identifier|DefaultValue$(RPAREN)Tuple report pointless errors) +$(LI $(BUGZILLA 9299): std.algorithm.minPos of const$(LPAREN)int$(RPAREN)[]) +$(LI $(BUGZILLA 9317): ParameterStorageClassTuple reports errors for inout function) +$(LI $(BUGZILLA 9336): Writeln is unable to print address of shared variable) + +) + +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 4287): opOpAssign!$(LPAREN)"~="$(RPAREN) for std.array.Appender) +$(LI $(BUGZILLA 4813): trait for getting at access modifiers) +$(LI $(BUGZILLA 5666): std.array.replace compile error $(LPAREN)string and immutable string$(RPAREN)) +$(LI $(BUGZILLA 6614): std.traits should have an isFinal template) +$(LI $(BUGZILLA 7896): Sequence slicing) +$(LI $(BUGZILLA 8143): Safe std.conv.to enum conversion) +$(LI $(BUGZILLA 9337): There's no Duration.max) +$(LI $(BUGZILLA 9339): std.random.uniform!Enum should return random enum member) + +) + +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 4793): Runtime.loadLibrary cannot load dll using MBS paths.) +$(LI $(BUGZILLA 5375): Detection of cyclic module imports provides error findings on console, instead of exception msg) +$(LI $(BUGZILLA 8132): LPTSTR always aliases to LPSTR) +$(LI $(BUGZILLA 9373): Add deprecation message to all empty deprecation statements) + +) + +$(BUGSTITLE Website regressions, + +$(LI $(BUGZILLA 9467): Operator Overloading anchors are broken) +$(LI $(BUGZILLA 9492): [2.052 beta] Stylesheet not found for off-line HTML docs) + +) + +$(BUGSTITLE Website bugs, + +$(LI $(BUGZILLA 5513): Erroneous example in std.algorithm) +$(LI $(BUGZILLA 7304): Online docs incorrect with regards to covariant arrays) +$(LI $(BUGZILLA 7345): interfaceToC.html missing on left-hand side) +$(LI $(BUGZILLA 8302): Documentation of dirEntries in std.file is incomplete) +$(LI $(BUGZILLA 8574): [std.format] The flag ' ' works for floating numbers, not only for integers) +$(LI $(BUGZILLA 8619): Tuples article uses writefln instead of writeln) +$(LI $(BUGZILLA 9321): Dead link to HTML5 standard in language specification) +$(LI $(BUGZILLA 9394): ABI for static arrays is outdated) +$(LI $(BUGZILLA 9446): ".keys" missing from properties table at https://dlang.org/hash-map.html) +$(LI $(BUGZILLA 9503): [grammar] template declaration/instance must take one or more arguments?) + +) + +$(BUGSTITLE Website enhancements, + +$(LI $(BUGZILLA 9302): Document extern properly) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.062 + TITLE=Change Log: $(VER) diff --git a/changelog/2.063.dd b/changelog/2.063.dd new file mode 100644 index 0000000000..228a473871 --- /dev/null +++ b/changelog/2.063.dd @@ -0,0 +1,1639 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION May 28, 2013, =================================================, + +$(BUGSTITLE Language Changes, +$(LI $(RELATIVE_LINK2 staticfields, Const and immutable fields with initializers are now warned about.)) +$(LI $(RELATIVE_LINK2 ctorqualifier, Constructor qualifiers are taken into account when constructing objects.)) +$(LI $(RELATIVE_LINK2 structuralcompare, Struct members which require non-bitwise comparison are now properly compared.)) +$(LI $(RELATIVE_LINK2 slicecopy, Array copy operations now always require using the slice syntax.)) +$(LI $(RELATIVE_LINK2 passtype, Types no longer act as arguments in typeof expressions.)) +$(LI $(RELATIVE_LINK2 foreachref, The index variable in a foreach range is no longer implicitly a reference.)) +$(LI $(RELATIVE_LINK2 hashentry, Associative array entries are no longer default-initialized before assignment.)) +$(LI $(RELATIVE_LINK2 constinherit, The const attribute is no longer inherited in overriden methods.)) +$(LI $(RELATIVE_LINK2 typeofnullconv, typeof(null) no longer implicitly converts to T[].)) +$(LI $(RELATIVE_LINK2 templatethisattrib, The Template This Parameter now changes the member function qualifier.)) +$(LI $(RELATIVE_LINK2 sliceref, Array slices are now r-values.)) +$(LI $(RELATIVE_LINK2 thisrefaccess, Accessing a non-static field without a $(D this) reference is only allowed in certain contexts.)) +$(LI $(RELATIVE_LINK2 implicitarrayptr, Arrays no longer implicitly convert to a pointer.)) +) + +$(BUGSTITLE Language Enhancements, +$(LI $(RELATIVE_LINK2 uniqueinference, Expressions which return unique objects can be implicitly casted to immutable.)) +$(LI $(RELATIVE_LINK2 staticarrayvoid, Static array of void can now be user-initialized.)) +$(LI $(RELATIVE_LINK2 multiinvariant, Aggregates can now contain multiple invariants.)) +$(LI $(RELATIVE_LINK2 attribinference, Methods of templated aggregates can now infer attributes.)) +$(LI $(RELATIVE_LINK2 isexpident, $(B is expression) no longer requires an identifier.)) +$(LI $(RELATIVE_LINK2 implicitarraycast, Dynamic arrays of known size can be implicitly cast to static arrays in some contexts.)) +$(LI $(RELATIVE_LINK2 tupleinitvoid, Tuples can now be void-initialized.)) +$(LI $(RELATIVE_LINK2 tupleequality, Tuples can now be compared for equality.)) +$(LI $(RELATIVE_LINK2 templconstraint, Template constraints can now be put after the inheritance list.)) +$(LI $(RELATIVE_LINK2 initfield, Fields with initializers can now be re-initialized in a const constructor.)) +$(LI $(RELATIVE_LINK2 isnestedtrait, Added the $(B isNested) trait for discovery of aggregates and functions with context pointers.)) +$(LI $(RELATIVE_LINK2 nestedtemplate, Templates can now be nested inside of functions.)) +$(LI $(RELATIVE_LINK2 ufcslocalimport, UFCS now works with scoped local imports.)) +$(LI $(RELATIVE_LINK2 prettyfunc, Added $(D __FUNCTION__), $(D __PRETTY_FUNCTION__) and $(D __MODULE__).)) +$(LI $(RELATIVE_LINK2 deprecatedmacro, DDoc: Deprecated declarations are now wrapped in a $(B DEPRECATED) macro.)) +$(LI $(RELATIVE_LINK2 documentedunittest, Added documented unittest feature for verifiable code example generation.)) +) + +$(BUGSTITLE Compiler Enhancements, +$(LI $(RELATIVE_LINK2 mainswitch, Added -main switch which adds an empty main function.)) +$(LI $(RELATIVE_LINK2 minimalcov, Added -cov=percentage switch for minimal coverage tests.)) +$(LI $(RELATIVE_LINK2 symbolmangle, Added ability to override the mangling of a symbol with a compiler pragma.)) +) + +$(BUGSTITLE Phobos Changes, +$(LI $(RELATIVE_LINK2 scopedtypeof, std.typecons.scoped implementation changed, potentially breaking some user-code.)) +) + +$(BUGSTITLE Phobos Enhancements, +$(LI $(RELATIVE_LINK2 newstdprocess, std.process has been redesigned from the ground up and introduces a new API and functionality.)) +$(LI $(RELATIVE_LINK2 getoptbool, std.getopt can now set booleans to false.)) +$(LI $(RELATIVE_LINK2 ownertid, Added ownerTid property in std.concurrency.)) +) + +$(BR)$(BIG $(RELATIVE_LINK2 list2063, List of all bug fixes and enhancements in D 2.063.)) + +$(HR) + +$(BUGSTITLE Language Changes, + +$(LI $(LNAME2 staticfields, Const and immutable fields with initializers are now warned about:) + +$(P Eventually, they will be deprecated, and then will trigger an error. Such fields should now +be changed to enum or static.) + +$(P In a future release, a new behavior for them will be enabled:) + +$(P Fields in an aggregate which are not static will always be addressable. +This means they will occupy space in the object:) + +--------- +struct S +{ + // used to be implicitly static in 2.062, now warns. In a future release it will become non-static. + immutable int[] arr = [1, 2]; + + // ditto + const int[] arr2 = [1, 2]; +} +--------- + +$(P This means that code which accessed such declarations without the $(D this) +reference will no longer compile. Additionally code which depended on the size +of a structure with such fields will have to be fixed:) + +--------- +struct S +{ + immutable int[] arr = [1, 2]; +} + +void main() +{ + auto x = S.arr; // becomes an error in a future release, 'arr' will require the 'this' reference. + + // S is size 1 in 2.062 and 2.063. In a future release this will change and the following static assert will pass. + static assert(S.sizeof == size_t.sizeof + size_t.sizeof); // ptr + length for the array +} +--------- + +$(P To make the field static again, simply use the static keyword. Alternatively +make the field an $(D enum) to turn it into a manifest constant:) + +--------- +struct S +{ + static immutable int[] arr = [1, 2]; + enum arr2 = [1, 2]; +} +--------- + +$(P Note however that manifest constants which are arrays are allocated on each usage, +so you may prefer using $(D static) instead.) + +$(H3 Rationale:) + +$(P Making a field implicitly static based on whether it is const/immutable and has an initializer leads to confusion. The $(D static) keyword can be used to explicitly make any field static.)) + +$(LI $(LNAME2 ctorqualifier, Constructor qualifiers are taken into account when constructing objects:) + +$(P A qualified constructor is now invoked when a $(D const)/$(D immutable)/$(D shared) aggregate object is + instantiated, respectively:) + +--------- +import std.stdio; + +class C +{ + this() { writeln("1"); } + this() const { writeln("2"); } + this() immutable { writeln("3"); } + this() shared { writeln("4"); } +} + +void main() +{ + auto a = new C; // writes "1" + auto b = new const C; // writes "2" + auto c = new immutable C; // writes "3" + auto d = new shared C; // writes "4" +} +--------- + + +$(P This has the consequence that aggregates which have only $(D immutable) or $(D shared) + constructors can no longer be used to instantiate mutable objects:) + +--------- +class C +{ + this() immutable { } + this() shared { } +} + +void main() +{ + auto c1 = new C; // disallowed + auto c2 = new immutable C; // ok + auto c3 = new shared C; // ok +} +--------- + +$(P On the other hand, aggregates which do not have $(D shared) or $(D immutable) constructors can + no longer be used to construct $(D shared) or $(D immutable) objects, respectively:) + +--------- +class C +{ + this() { } +} + +void main() +{ + auto c1 = new C; // ok + auto c2 = new immutable C; // disallowed + auto c3 = new shared C; // disallowed +} +--------- + +$(P However, if an aggregate has a $(D pure) constructor it can be used to construct an object with any type constructor:) + +--------- +class C +{ + this() pure { } +} + +void main() +{ + auto c1 = new C; // ok + auto c2 = new immutable C; // ok + auto c3 = new shared C; // ok +} +--------- +) +$(LI $(LNAME2 structuralcompare, Struct members which require non-bitwise comparison are now properly compared.) + +$(P In earlier releases some struct members such as arrays would be bitwise-compared in a comparison operation. + This has now been changed to be a structural comparison instead:) + +--------- +struct S +{ + char[] data; +} + +void main () +{ + auto s1 = S("foo".dup); + auto s2 = S("foo".dup); + + assert(s1.data !is s2.data); // both are unique data + + assert(s1 == s2); // passes in 2.063 + assert(s1.data == s2.data); // equivalent of above +} +--------- + +$(P If an $(D opEquals) function is not present the compiler rewrites the expression + $(CODE s1 == s2) to $(CODE s1.tupleof == s2.tupleof). Comparing $(D .tupleof) expressions is + also a feature new to D in the 2.063 release.)) + +$(LI $(LNAME2 slicecopy, Array copy operations now always require using the slice syntax:) + +$(P The right-hand-side of an array copy operation now requires using the slice syntax:) + +--------- +void main() +{ + int[][2] x; + int[] y; + int[] z; + + x[] = z; // copies z (pointer + length) 2 times to x + y[] = z; // copies each element of z into y (compiler emits warning) +} +--------- + +$(P If the user intended to write such code they must use the slice syntax for both the source and target arrays:) + +--------- +void main() +{ + int[][2] x; + int[] y; + int[] z; + + y[] = z[]; // copies each element of z into y (no warnings) +} +--------- + +$(H3 Rationale:) + +$(P The compiler will emit a warning to make the user aware that the copy operation is arbitrarily expensive.)) + +$(LI $(LNAME2 passtype, Types no longer act as arguments in $(D typeof) expressions:) + +$(P A type can no longer be passed to a function as a value of that type:) + +--------- +T[] foo(T)(T t) +{ + return null; +} + +void main() +{ + alias int Int; + + // used to work (only with an alias), now a compiler error + alias typeof(foo(Int)) IntArray; +} +--------- + +$(P If the user wants to pass an argument of a certain type, they can use the $(D .init) property:) + +--------- +T[] foo(T)(T t) +{ + return null; +} + +void main() +{ + alias typeof(foo(int.init)) IntArray; // ok +} +--------- + +$(H3 Rationale:) + +$(P Treating types as expressions in special contexts only leads to confusion. +Instead, the $(D .init) property can be used for such purposes.)) + +$(LI $(LNAME2 foreachref, The index variable in a foreach range is no longer implicitly a reference:) + +$(P The index variable in a foreach range is now by default a value type:) + +--------- +void main() +{ + size_t count; + foreach (n; 0 .. 10) + { + ++n; + ++count; + } + assert(count == 10); // passes +} +--------- + +$(P If the user wants to modify the index variable he must use the $(D ref) keyword:) + +--------- +void main() +{ + size_t count; + foreach (ref n; 0 .. 10) + { + ++n; + ++count; + } + assert(count == 5); +} +--------- + + +$(H3 Rationale:) + +$(P Making the index variable implicitly $(D ref) can introduce bugs that are hard to track down.)) + +$(LI $(LNAME2 hashentry, Associative array entries are no longer default-initialized before assignment:) + +$(P An associative array entry used to be default-initialized before assignment took place:) + +--------- +void main() +{ + int[int] aa; + aa[1] = aa[1] + 1; // no Error thrown in 2.062 + assert(aa[1] == 1); // worked in 2.062 +} +--------- + +$(P In 2.063, accessing an entry which does not exist will now throw a RangeError:) + +--------- +void main() +{ + int[int] aa; + aa[1] = aa[1] + 1; // RangeError thrown in 2.063 +} +--------- + +$(H3 Rationale:) + +$(P Default-initialization during assignment can be a source of bugs.)) + +$(LI $(LNAME2 constinherit, The const attribute is no longer inherited in overriden methods.) + +$(P Method overrides no longer inherit constness of the base method:) + +--------- +class A +{ + void foo() const { } +} + +class B : A +{ + // used to work in 2.062, now an error + override void foo() { } // note missing 'const' +} +--------- + +$(P If the user wants to override a const method he has to mark the overriden + method as const:) + +--------- +class A +{ + void foo() const { } +} + +class B : A +{ + override void foo() const { } // ok +} +--------- + +$(P The feature allows introducing new overloads based on the constness of the method:) + +--------- +class A +{ + void foo() const { } +} + +class B : A +{ + // introduces new overload (not override!) + void foo() { } + + // if the above overload is introduced the user must either: + // a: re-introduce the const overload to prevent function hijacking + alias super.foo foo; // without this you will get a compiler error + + // or b: provide a properly typed override: + override void foo() const { } +} +--------- +) + +$(LI $(LNAME2 typeofnullconv, $(D typeof(null)) no longer implicitly converts to T[]:) + +$(P The following code used to be allowed:) + +--------- +void f(int[] function() del) +{ + assert(!del()); // fails +} + +typeof(null) g() { return null; } + +void main() +{ + f(&g); + f(() => null); +} +--------- + +$(P However the implicit conversion would end up generating wrong code. + To work around this, make sure the return type is typed properly, + or use $(CODE (T[]).init) in the return expression of a lambda expression:) + +--------- +void f(int[] function() del) +{ + assert(!del()); // passes +} + +int[] g() { return null; } // fixed return type + +void main() +{ + f(&g); // ok + f(() => (int[]).init); // ok +} +--------- +) +$(LI $(LNAME2 templatethisattrib, The Template This Parameter now changes the member function qualifier:) + +$(P The $(LINK2 $(ROOT_DIR)spec/template.html#TemplateThisParameter, Template This +Parameter) can now be used to infer the qualifier of $(D this) to member +functions:) + +--------- +struct S +{ + void foo(this T)() + { + } +} + +void main() +{ + immutable S s; + s.foo(); // makes S.foo immutable +} +--------- +) +$(LI $(LNAME2 sliceref, Array slices are now r-values:) + +$(P Array slices are no longer l-values. This means an address can no longer be +taken of a slice, and slices cannot be passed by ref to functions:) + +--------- +void foo(ref int[] arr) { arr = new int[10]; } + +void main() +{ + int[] arr; + foo(arr); // ok + assert(arr.length == 10); + + foo(arr[]); // disallowed in 2.063, the slice is an r-value + auto ptr = &arr[1..2]; // disallowed in 2.063, cannot take address of r-value +} +--------- + +$(P To work around this you can make your function take an r-value if it doesn't + need to reassign and resize the slice, but only needs to read or modify its contents. + Otherwise, to accept both l-values and r-values you can make your function take + its argument by $(D auto ref):) + +--------- +void take(int[] arr) { } +void takeRef(ref int[] arr) { } +void takeAutoRef(T)(auto ref T[] arr) { } + +void main() +{ + int[] arr = [1, 2, 3, 4]; + take(arr); // ok + takeRef(arr); // ok + takeAutoRef(arr); // ok + + int[] arr2 = arr[1 .. 2]; + take(arr2); // ok, arr2 is a variable + takeRef(arr2); // ditto + takeAutoRef(arr2); // ditto + + take(arr[1 .. 2]); // ok + takeRef(arr[1 .. 2]); // error, cannot pass r-value by reference + takeAutoRef(arr[1 .. 2]); // ok +} +--------- + +$(H3 Rationale:) + +$(P Passing slices by reference had no observable effect when reassigning or +resizing such a slice at the call site, therefore such slices should by default be r-values. +For example, the following code used to be allowed but is now a compile-time error:) + +--------- +void reAssign(ref int[] arr) { arr = new int[2]; } +void reSize(ref int[] arr) { arr.length = 10; } + +void main() +{ + int[] arr = [1, 2, 3, 4]; + + reAssign(arr[0 .. 4]); // reassigning has no observable effect at the call site + assert(arr == [1, 2, 3, 4]); + + reSize(arr[0 .. 4]); // resizing has no observable effect at the call site + assert(arr.length == 4); +} +--------- +) +$(LI $(LNAME2 thisrefaccess, Accessing a non-static field without a $(D this) reference is only allowed in certain contexts:) + +$(P Accessing non-static fields used to be allowed in many contexts, but is now limited to only a few:) + +$(P - $(D offsetof), $(D init), and other built-in properties are allowed:) + +--------- +struct S { int field; } + +void main() +{ + auto a = S.field.offsetof; // ok, statically known + auto c = S.field.max; // ditto + auto d = S.field; // disallowed, no `this` reference +} +--------- + +$(P - When invoking static methods of a non-static field:) + +--------- +struct Foo +{ + static struct Bar + { + static int get() { return 0; } + } + + Bar bar; +} + +void main() +{ + static assert(Foo.bar.get() == 0); // ok, equivalent to `typeof(Foo.bar).get()` +} +--------- + +$(P - When accessing static fields implicitly using an +$(LINK2 $(ROOT_DIR)spec/class.html#AliasThis, $(D alias this)) expression:) + +--------- +struct Foo +{ + static struct Bar + { + static int get() { return 0; } + } + + Bar bar; + alias bar this; +} + +void main() +{ + static assert(Foo.get() == 0); // ok, equivalent to 'typeof(Foo.bar).get()' +} +--------- +) +$(LI $(LNAME2 implicitarrayptr, Arrays no longer implicitly convert to a pointer:) + +$(P The implicit conversion of an array to a pointer was a deprecated feature:) + +--------- +void foo(int* p) { } + +void main() +{ + int[] arr = [1, 2]; + foo(arr); // ok if -d switch is used during compilation +} +--------- + +$(P This feature has now been completely removed. The workaround is to either + use the $(D .ptr) property, or explicitly pass the pointer to the first element:) + +--------- +void foo(int* p) { } + +void main() +{ + int[] arr = [1, 2]; + foo(arr); // compile error + foo(arr.ptr); // ok + foo(&arr[0]); // ok +} +--------- +)) +$(BUGSTITLE Language Enhancements, + +$(LI $(LNAME2 uniqueinference, Expressions which return unique objects can be implicitly casted to immutable:) + +$(P Expressions such as $(D new) for objects and arrays, and $(D dup) for arrays, can now be inferred to be unique. + This allows the compiler to implicitly convert such an expression to immutable:) + +--------- +class C { } + +void main() +{ + immutable int[] arr1 = new int[](3); // ok + immutable int[] arr2 = [1, 2, 3].dup; // ok in 2.063 + immutable C[] arr3 = [new C, new C].dup; // ok in 2.063 +} +--------- +) +$(LI $(LNAME2 staticarrayvoid, Static array of void can now be user-initialized.) + +$(P A static array of void could not be initialized in user-code:) + +--------- +void main() +{ + void[2] varr1; // error in 2.062 + void[2] varr2 = (void[2]).init; // error in 2.062 + void[2] varr3 = void; // ok in 2.062 +} +--------- + +$(P In 2.063, an explicit initializer can be used:) + +--------- +void main() +{ + void[2] varr1; // still an error in 2.063 + void[2] varr2 = (void[2]).init; // ok in 2.063 + void[2] varr3 = void; // ok in 2.063 +} +--------- + +$(P The $(D .init) property effectively zero-initializes the array.) + +$(H3 Rationale:) + +$(P The restriction has been lifted to allow generic code to use $(D .init) without +having to specialize for static void arrays.)) + +$(LI $(LNAME2 multiinvariant, Aggregates can now contain multiple invariants:) + +$(P If an aggregate type has multiple invariants, the invariants' bodies will be merged + into a single invariant function and will be run in sequence. Note that the code in + one invariant cannot reference code or data in another invariant:) + +--------- +struct S +{ + int x; + + void foo() { } + + invariant() + { + int local; + assert(x != 0); + } + + invariant() + { + // local = 1; // invariant does not have access to the other invariant's body + assert(x % 2 == 0); + } +} + +void main() +{ + S s = S(2); + s.foo(); // invoking public function triggers both invariants in sequence +} +--------- +) +$(LI $(LNAME2 attribinference, Methods of templated aggregates can now infer attributes:) + +$(P If a function with some attributes instantiates a templated aggregate, + its member functions will infer those attributes:) + +--------- +struct S(T) +{ + T square(T x) + { + return x * x; + } +} + +void main() pure +{ + S!int s; // S!int.square becomes pure and callable from main() + assert(s.square(2) == 4); // ok +} +--------- +) +$(LI $(LNAME2 isexpident, $(B is expression) no longer requires an identifier:) + +$(P In some cases the + $(LINK2 $(ROOT_DIR)spec/expression.html#IsExpression, is expression) + required an identifier even when you didn't have a use for it:) + +--------- +void main() +{ + alias AA = string[int]; + + static if (is(AA _ == V[K], V, K)) + { + pragma(msg, _); // prints string[int] + pragma(msg, K); // prints int + pragma(msg, V); // prints string + } +} +--------- + +$(P The identifier is no longer required, so the above can be rewritten to:) + +--------- +void main() +{ + alias AA = string[int]; + + static if (is(AA == V[K], V, K)) + { + pragma(msg, AA); // prints string[int] + pragma(msg, K); // prints int + pragma(msg, V); // prints string + } +} +--------- +) +$(LI $(LNAME2 implicitarraycast, Dynamic arrays of known size can be implicitly cast to static arrays in some contexts:) + +$(P In some contexts the compiler knows the size of a dynamic array or of a slice of an array. + In such a case the compiler will allow an implicit conversion to a static array of the same size:) + +--------- +void foo(int[4] x) { } + +void main() +{ + int[] arr = [1, 2, 3, 4, 5, 6, 7, 8]; + foo(arr[0 .. 4]); // ok +} +--------- + +$(P Another example, where a string is converted to a reference to a static array:) + +--------- +string str = "aaaabbbbccccdddd"; + +void foo(ref const(char)[16] buf) +{ + assert(buf.ptr is str.ptr); +} + +void main() +{ + foo(str[0..16]); // ok +} +--------- + +$(H3 Limitations:) + +$(P - This feature does not yet work with complex expressions where it might be + reasonable to assume the size of a slice:) + +--------- +void foo(int[4] x) { } + +void main() +{ + int[] arr = [1, 2, 3, 4, 5, 6, 7, 8]; + foreach (i; 0 .. 4) + { + foo(arr[i .. i + 4]); // not yet supported + } +} +--------- +) +$(LI $(LNAME2 tupleinitvoid, Tuples can now be void-initialized:) + +$(P You can now void-initialize a tuple variable:) + +--------- +template Tuple(T...) +{ + alias T Tuple; +} + +void main() +{ + Tuple!(int, int) tup1 = void; // ok +} +--------- + +$(P Upon such initialization the values in the tuple are undetermined.)) + +$(LI $(LNAME2 templconstraint, Template constraints can now be put after the inheritance list:) + +$(P Template constraints used to be allowed only before the inheritance list, leading to + code where the inheritance list could be hard to spot:) + +--------- +class Foo(T1, T2) + if (is(T1 == int) && is(T2 == string)) : Base +{ +} +--------- + +$(P This restriction has been lifted, so you can now write:) + +--------- +class Foo(T1, T2) : Base + if (is(T1 == int) && is(T2 == string)) +{ +} +--------- +) +$(LI $(LNAME2 tupleequality, Tuples can now be compared for equality:) + +$(P Example:) + +--------- +struct Tuple(T...) { T field; alias field this; } + +void main() +{ + auto tup1 = Tuple!(int, int)(1, 2); + auto tup2 = Tuple!(int, int)(1, 2); + auto tup3 = Tuple!(int, int)(1, 3); + + assert(tup1 == tup2); // works since 2.063 + assert(tup1 != tup3); // works since 2.063 +} +--------- + +$(P This also means you can now compare $(B ParameterStorageClassTuple) instances from std.traits:) + +--------- +import std.traits; + +void func1(ref int x, ref int y) { } +void func2(ref float x, ref float y) { } + +void main() +{ + alias Storages = ParameterStorageClassTuple; + assert(Storages!func1 == Storages!func2); +} +--------- + +$(P In addition to that, builtin $(D .tupleof) expressions can be used to easily compare fields of an aggregate:) + +--------- +struct S +{ + char[] a, b; + + // Implements equality test against another instance of this type. + bool opEquals(S rhs) { return this.tupleof == rhs.tupleof; } +} + +void main() +{ + S s1 = S("a".dup, "b".dup); + S s2 = S("a".dup, "b".dup); + assert(s1 == s2); +} +--------- + +$(P This also allows you to implement a structural equality test against an instance of a different + type:) + +--------- +struct S1 +{ + char[] a, b; + + // Implements a structural equality test against any other type T + bool opEquals(T)(T rhs) { return this.tupleof == rhs.tupleof; } +} + +struct S2 +{ + string x, y; +} + +void main() +{ + auto s1 = S1("123".dup, "456".dup); + auto s2 = S2("123", "456"); + assert(s1 == s2); +} +--------- + + +$(P Since tuples can be sliced you can use this feature to compare a subset of tuples:) + +--------- +struct S +{ + int a, b, c, d, e; + + bool opEquals(S rhs) + { + // compares a, b, d, and e + return this.tupleof[0..2] == rhs.tupleof[0..2] && + this.tupleof[3..5] == rhs.tupleof[3..5]; + } +} + +void main() +{ + S s1 = S(1, 2, 0, 3, 4); + S s2 = S(1, 2, 1, 3, 4); + assert(s1 == s2); +} +--------- +) +$(LI $(LNAME2 initfield, Fields with initializers can now be re-initialized in a const constructor:) + +$(P You can now initialize a field in a const constructor even if + such a field already has an initializer:) + +--------- +struct S +{ + bool field = true; + + this(int v) const + { + field = false; // ok + } +} +--------- +) +$(LI $(LNAME2 isnestedtrait, Added the $(B isNested) trait for discovery of aggregates and functions with context pointers:) + +$(P The new $(LINK2 $(ROOT_DIR)spec/traits.html#isNested, isNested) trait allows you + to discover whether an aggregate or function contains a context pointer:) + +--------- +void main() +{ + int x; + + struct S1 { void f() { x++; } } + static struct S2 { } + + void f1() { x++; } + static void f2() { } + + static assert(__traits(isNested, S1)); + static assert(__traits(isNested, f1)); + static assert(!__traits(isNested, S2)); + static assert(!__traits(isNested, f2)); +} +--------- +) +$(LI $(LNAME2 nestedtemplate, Templates can now be nested inside of functions:)) + +--------- +void test() +{ + template ArrayOf(T) { alias ArrayOf = T[]; } + static assert(is(ArrayOf!int == int[])); +} +--------- + +$(P Allowing $(D template)s inside of functions will enable better encapsulation and avoid the + pollution of module-scoped symbol names.) + +$(LI $(LNAME2 ufcslocalimport, UFCS now works with scoped local imports:) + +$(P Functions that are made available through a local import are now picked up when using Uniform Function Call Syntax:) + +--------- +module foo; +string concat(string arg1, string arg2) { return arg1 ~ arg2; } +--------- + +--------- +module test; +void main() +{ + import foo; + assert("foo".concat("bar") == "foobar"); // UFCS now works +} +--------- + +$(P This feature also works for imports within aggregates. Note that local imports have a higher precedence than + module-scoped imports.)) + +$(LI $(LNAME2 prettyfunc, Added $(D __FUNCTION__), $(D __PRETTY_FUNCTION__) and $(D __MODULE__):) + +$(P A new set of + $(LINK2 $(ROOT_DIR)spec/traits.html#specialkeywords, special keywords) were + added. Together with $(D __FILE__) and $(D __LINE__) they form a complete + feature set that is useful in debugging code:) + +--------- +module test; +import std.stdio; + +void test(string file = __FILE__, size_t line = __LINE__, string mod = __MODULE__, + string func = __FUNCTION__, string pretty = __PRETTY_FUNCTION__) +{ + writefln("file: '%s', line: '%s', module: '%s',\nfunction: '%s', pretty function: '%s'", + file, line, mod, func, pretty); +} + +int main(string[] args) +{ + test(); + return 0; +} +--------- + +$(P The above will output:) + +$(CONSOLE +file: 'test.d', line: '13', module: 'test', +function: 'test.main', pretty function: 'int test.main(string[] args)' +)) + +$(LI $(LNAME2 deprecatedmacro, DDoc: Deprecated declarations are now wrapped in a $(B DEPRECATED) macro:) + +--------- +module test; + +/// sum function +deprecated int sum(int x, int y) { return x + y; } +--------- + +$(P By default the macro expands to its argument. It can be overriden by the user, for example:) + +$(P $(B macros.ddoc:)) + +--------- +DEPRECATED=$(DOLLAR)0 +--------- + +$(P The above ddoc file can then be used when the documentation is being generated:) + +$(CONSOLE +$ dmd -D -o- test.d macros.ddoc +)) + +$(LI $(LNAME2 documentedunittest, Added documented unittest feature for verifiable code example generation:) + +$(P Documented unittests which follow any symbol declarations are now used to generate example sections for the symbol + when generating DDOC documentation. Example:) + +--------- +/// sum function +int sum(int x, int y) { return x + y; } + +/// +unittest +{ + assert(sum(2, 2) == 4); +} +--------- + +$(P The body of the unittest will be part of the documentation of the sum function. This allows the + implementor of the function to keep their examples always up-to-date.) + +$(P For more information, see the + $(LINK2 $(ROOT_DIR)spec/unittest.html#documented-unittests, documentation page) + of documented unittests.) + +)) + + +$(BUGSTITLE Compiler Enhancements, +$(LI $(LNAME2 mainswitch, Added -main switch which adds an empty main function:) + +$(P The $(B -main) switch is primarily useful when unittesting libraries:) + +--------- +module test; + +int sum(int a, int b) { return a + b; } +unittest +{ + assert(sum(2, 2) == 4); +} +--------- + +$(P The above library would need a $(B main()) function for the unittests to run, + and $(B -main) can be used for this purpose:) + +$(CONSOLE +$ dmd -unittest -main -run test.d +)) + +$(LI $(LNAME2 minimalcov, Added -cov=percentage switch for minimal coverage tests.) + +$(P The $(B -cov) switch now has an optional percentage setting which makes the + executable emit an error when the coverage doesn't meet the specified requirement:) + +--------- +module test; + +void test1() { int x = 5; } +void test2() { int x = 5; } +void test3() { int x = 5; } + +void main() +{ + test1(); + test2(); +} +--------- + +$(P Example of coverage testing:) + +$(CONSOLE +$ dmd -cov=90 test.d +$ test +Error: test.d is 80% covered, less than required 90% +)) + +$(LI $(LNAME2 symbolmangle, Added ability to override the mangling of a symbol with a compiler pragma:) + +$(P The new $(CODE pragma(mangle, ...)) directive allows you to set a custom mangling for any symbol:) + +--------- +pragma(mangle, "module") extern(C) void module_(); +--------- + +$(P The above allows linking to a C function named "module", which ordinarily we wouldn't be + able to link to directly since "module" is a reserved D keyword.) + +)) + +$(BUGSTITLE Phobos Changes, + +$(LI $(LNAME2 scopedtypeof, std.typecons.scoped implementation changed, potentially breaking some user-code:) + +$(P User-code which used the $(D std.traits.ReturnType) trait to retrieve the type of a $(D scoped) call will have to be + changed to use the $(D typeof) operator instead:) + +--------- +class A +{ + this() {} + this(int) {} +} + +class B +{ + // ReturnType!(scoped!A) a; // disallowed in 2.063 + typeof(scoped!A()) a; // rewritten, compiles in 2.063 + + this() + { + a = scoped!A(1); // would not compile in 2.062, but works with syntax used for 2.063 + } +} +--------- + +$(P The reason for this change is that the $(D ReturnType) trait would retrieve the wrong type when a class + had multiple constructors, and this would cause initializing the field to fail.) + +$(P Another benefit of the new implementation is that $(D scoped) can now be aliased for usability purposes:) + +--------- +class A +{ + this(int) { } +} + +void main() +{ + alias scoped!A scopeA; + auto a = scopeA(1); +} +--------- + +)) + +$(BUGSTITLE Phobos Enhancements, + +$(LI $(LNAME2 newstdprocess, $(MREF std,process) has been redesigned from the ground up and introduces a new API and functionality:) + +$(P The new $(MREF std,process) module introduces functionality for invoking processes with custom pipe redirection, +the ability to wait for processes to finish, and the ability to kill processes. The full list of features +can be found in the $(MREF std,process) documentation.)) + +$(LI $(LNAME2 getoptbool, $(MREF std,getopt) can now set booleans to false:) + +$(P Example code:) + +--------- +void main(string[] args) +{ + bool flag = true; + getopt(args, &flag); +} +--------- + +$(P When invoked via $(CODE --flag=false), it will set $(B flag) to $(D false).)) + +$(LI $(LNAME2 ownertid, Added ownerTid property in $(MREF std,concurrency):) + +$(P It is now easier to send a message from a child thread to its +owner thread. Simply use the $(B ownerTid) property to get the owner +thread's Tid identifier:) + +--------- +void fun() +{ + string res = receiveOnly!string(); + assert(res == "Main calling"); + + ownerTid.send("Child responding"); // new +} + +void main() +{ + auto child = spawn(&fun); + child.send("Main calling"); + + string res = receiveOnly!string(); + assert(res == "Child responding"); +} +--------- + +$(P If the owner thread has exited, accessing ownerTid from any + of its child threads will throw a $(B TidMissingException).) + +)) + +$(BR)$(BIG $(LNAME2 list2063, List of all bug fixes and enhancements in D 2.063:)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 9130): Wrong codegen for compile time constructed struct) +$(LI $(BUGZILLA 9258): opAssign with base class triggers "identity assignment operator overload" error) +$(LI $(BUGZILLA 9526): ICE when compiling project with unittests) +$(LI $(BUGZILLA 9536): IFTI fails when calling a static member from const member) +$(LI $(BUGZILLA 9538): Regression $(LPAREN)2.062$(RPAREN): Can't use typeid on .ptr of static array) +$(LI $(BUGZILLA 9539): Wrong implicit conversion of array to pointer) +$(LI $(BUGZILLA 9545): [REG 2.063a] ICE with member template instantiation) +$(LI $(BUGZILLA 9552): DMD crashed when taking member delegate from __traits$(LPAREN)getOverloads$(RPAREN)) +$(LI $(BUGZILLA 9566): Regression $(LPAREN)2.062$(RPAREN): Cannot use struct .init when it contains a static array initialized from a single element.) +$(LI $(BUGZILLA 9568): [64bit] wrong code for scope$(LPAREN)exit$(RPAREN)) +$(LI $(BUGZILLA 9633): compiles trait wrongly returns true even when object method call actually does not compile) +$(LI $(BUGZILLA 9650): __traits$(LPAREN)compiles$(RPAREN) + mixin) +$(LI $(BUGZILLA 9663): [REG2.063a] ICE caused by issue 7444 change.) +$(LI $(BUGZILLA 9672): mixin within cyclic import causes undefined properties) +$(LI $(BUGZILLA 9689): std.typecons.Proxy breaks with @disable this$(LPAREN)this$(RPAREN)) +$(LI $(BUGZILLA 9694): A member struct that has mutable opEquals reports weird error message) +$(LI $(BUGZILLA 9739): Regression $(LPAREN)1.077 git-head$(RPAREN): DMD not considering ctor with default args as default ctor) +$(LI $(BUGZILLA 9759): compiler segfault in StructLiteral::implicitConvTo$(LPAREN)Type*$(RPAREN) on invalid code) +$(LI $(BUGZILLA 9764): Ddoc: Ddoc file name is incorrectly emphasized) +$(LI $(BUGZILLA 9775): Can no longer create a const Date in CTFE if the variable is explicitly typed) +$(LI $(BUGZILLA 9806): assertion failure in struct.c:668) +$(LI $(BUGZILLA 9834): incorrect detection of lambda locality.) +$(LI $(BUGZILLA 9846): regression of forward references) +$(LI $(BUGZILLA 9858): const alias this fails when opAssign is present) +$(LI $(BUGZILLA 9865): Crash on bogus import / circular reference) +$(LI $(BUGZILLA 9890): Alias This + Alias Fields) +$(LI $(BUGZILLA 9903): Broken ddoc in std.typecons and etc.c.sqlite3) +$(LI $(BUGZILLA 9919): Regression $(LPAREN)2.062$(RPAREN): Symbol lookup fails with public import and mixin) +$(LI $(BUGZILLA 9952): regression$(LPAREN)HEAD$(RPAREN): Attribute inference for virtual functions breaks subclasses) +$(LI $(BUGZILLA 9957): [2.061 -> 2.062] Taking pointer of enum float array gives some garbage) +$(LI $(BUGZILLA 9974): immutable class constructor is broken) +$(LI $(BUGZILLA 9984): inout qualifier is skipped for constructor arguments $(LPAREN)template constructor only$(RPAREN)) +$(LI $(BUGZILLA 9987): Declaring struct ModuleInfo should be allowed) +$(LI $(BUGZILLA 10002): 2.062 -> 2.063 calling "remove" is impure) +$(LI $(BUGZILLA 10003): void* UFCS regression) +$(LI $(BUGZILLA 10016): Incorrect error gagging using RefCounted) +$(LI $(BUGZILLA 10040): struct-related ICE) +$(LI $(BUGZILLA 10041): ufcs writeln of associative array) +$(LI $(BUGZILLA 10043): ICE with __traits$(LPAREN)compiles$(RPAREN)) +$(LI $(BUGZILLA 10044): Wrong di generation for IsExp with TemplateParameterList) +$(LI $(BUGZILLA 10047): opDispatch instantiation failure should be gagged for UFCS) +$(LI $(BUGZILLA 10049): Spurious "Label already defined" error inside a foreach over a range aggregate) +$(LI $(BUGZILLA 10050): Regression $(LPAREN)git-head$(RPAREN): RDMD no longer emits error messages from DMD) +$(LI $(BUGZILLA 10053): struct member with pure dtor forces declared dtor to be pure, too) +$(LI $(BUGZILLA 10055): Incorrect attribute merging in dtor/postblit building) +$(LI $(BUGZILLA 10056): Strange Error with templates and string.format) +$(LI $(BUGZILLA 10067): [REG] Recursive template instantiation) +$(LI $(BUGZILLA 10073): Default opEquals depends on class declaration order with DMD HEAD) +$(LI $(BUGZILLA 10076): expression.c:4310: virtual Expression* TypeExp::semantic$(LPAREN)Scope*$(RPAREN): Assertion `0` failed.) +$(LI $(BUGZILLA 10089): Strange function call error message with specified module) +$(LI $(BUGZILLA 10091): [HEAD] Cannot cast struct member string enum to static ubyte array of same size) +$(LI $(BUGZILLA 10096): Regression $(LPAREN)git-head$(RPAREN): __traits$(LPAREN)allMembers$(RPAREN) triggers out of bounds error) +$(LI $(BUGZILLA 10101): static if conditional cannot be at global scope using mixin template) +$(LI $(BUGZILLA 10106): [ICE] Ice in glue.c:1215 + 2 error messages without lines) +$(LI $(BUGZILLA 10134): Mutual referencing templates error) +$(LI $(BUGZILLA 10142): [REG2.063a] enum value semantic problem that declared in class member) +$(LI $(BUGZILLA 10144): Using enum inside final class occurs weird errors) +$(LI $(BUGZILLA 10148): regression 062=>063: unjustified 'safe function cannot call system function') +$(LI $(BUGZILLA 10151): final: before enum is now an error.) +$(LI $(BUGZILLA 10160): No line number "cannot modify struct ... with immutable members") +$(LI $(BUGZILLA 10166): XXX is not a template) +$(LI $(BUGZILLA 10178): Compiler segfault with zero-length tuple comparison) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 1520): TypeInfo_Const.opEquals is incorrect) +$(LI $(BUGZILLA 1804): Severe GC leaks with repetitive array allocations) +$(LI $(BUGZILLA 2356): array literal as non static initializer generates horribly inefficient code.) +$(LI $(BUGZILLA 3789): [TDPL] Structs members that require non-bitwise comparison not correctly compared) +$(LI $(BUGZILLA 4094): ICE$(LPAREN)expression.c$(RPAREN): recursive struct templates with type inference) +$(LI $(BUGZILLA 4247): Cannot create default-constructed struct on heap when constructor is defined) +$(LI $(BUGZILLA 4414): ICE$(LPAREN)cgcs.c$(RPAREN) Taking item of static array returned by function) +$(LI $(BUGZILLA 4436): Double bug regarding Tuple.init) +$(LI $(BUGZILLA 4479): Module Foo is in multiple files Foo) +$(LI $(BUGZILLA 4617): Alias this'ed symbols cannot be passed to templates) +$(LI $(BUGZILLA 4814): rdmd: Doesn't rebuild when using -of and turning an -L linker option on or off) +$(LI $(BUGZILLA 5450): no match for implicit super$(LPAREN)$(RPAREN) call in constructor) +$(LI $(BUGZILLA 5625): std.format unittest disabled) +$(LI $(BUGZILLA 6070): CTFE UFCS forward reference error) +$(LI $(BUGZILLA 6089): __gshared with not static 2D array) +$(LI $(BUGZILLA 6153): Inserting to An Array!T inside an Array!$(LPAREN)Array!T$(RPAREN) causes a segfault.) +$(LI $(BUGZILLA 6312): template instance cannot use argument from enclosing template) +$(LI $(BUGZILLA 6431): [RDMD] Modifying a library doesn't trigger a rebuild) +$(LI $(BUGZILLA 6535): RDMD outputs broken library files) +$(LI $(BUGZILLA 6539): Incomprehensible error message with failed template instantiation) +$(LI $(BUGZILLA 6545): [CTFE] Hard-coded array operations not yet supported) +$(LI $(BUGZILLA 6578): Ignored const with struct with constructor) +$(LI $(BUGZILLA 6795): ICE$(LPAREN)cgcs.c$(RPAREN): Incrementing an enum array item) +$(LI $(BUGZILLA 6852): Cannot compare instances of ParameterStorageClassTuple) +$(LI $(BUGZILLA 7068): copying array of pointers calls memset instead of memcpy with -d) +$(LI $(BUGZILLA 7437): DMD enters infinite loop during overload resolution) +$(LI $(BUGZILLA 7569): cannot void initialize tuple declarations) +$(LI $(BUGZILLA 7572): f.fn!$(LPAREN)void$(RPAREN) is not an lvalue) +$(LI $(BUGZILLA 7719): enum forward reference error when enum is in braces) +$(LI $(BUGZILLA 7980): Stack overflow / recursive expansion with alias this) +$(LI $(BUGZILLA 8041): __gshared/static problem) +$(LI $(BUGZILLA 8081): pure nothrow unittest problem in generated 'header' file) +$(LI $(BUGZILLA 8130): Memory corruption because without *.def file DMD compiles DLL with assumption `_tls_index = 0`) +$(LI $(BUGZILLA 8213): Incorrect error message with pointer to ubyte[] and front) +$(LI $(BUGZILLA 8238): templates can create ghost fields) +$(LI $(BUGZILLA 8245): UFCS doesn't work for pointers) +$(LI $(BUGZILLA 8294): complex breaks calling in 64 bit DMD) +$(LI $(BUGZILLA 8347): Parser bug with const placed after ~this$(LPAREN)$(RPAREN) in decl) +$(LI $(BUGZILLA 8366): Overriding const member function in conjunction with mutable overload causes a strange error) +$(LI $(BUGZILLA 8589): Incorrect conversion of function returning `typeof$(LPAREN)null$(RPAREN)` to function returning an array) +$(LI $(BUGZILLA 8609): A forward reference error with static arrays) +$(LI $(BUGZILLA 8668): public selective import makes functions conflict when otherwise they don't) +$(LI $(BUGZILLA 8670): IFTI fails from aliases) +$(LI $(BUGZILLA 8697): Invalid error message: Forward reference of interface) +$(LI $(BUGZILLA 8698): Forward reference error with interfaces) +$(LI $(BUGZILLA 8827): Cannot move contents of R12) +$(LI $(BUGZILLA 8828): Long compilation time of a destroy$(LPAREN)$(RPAREN) on a large fixed-sized matrix) +$(LI $(BUGZILLA 8833): Odd error with expression tuples) +$(LI $(BUGZILLA 8902): Unexpected "duplicate union initialization for X" error) +$(LI $(BUGZILLA 8945): Can't call static struct initializer or constructor without qualifier for templated inner struct) +$(LI $(BUGZILLA 8953): Parser rejects qualifier after destructor i.e. `~this$(LPAREN)$(RPAREN) $(LESS)qualifier$(GREATER) { }`) +$(LI $(BUGZILLA 8989): cfloat argument passing broken) +$(LI $(BUGZILLA 8998): 'inout pure' returns immutable, which in reality is mutable) +$(LI $(BUGZILLA 9091): Using __traits$(LPAREN)getMember$(RPAREN) on template argument fails inside member function) +$(LI $(BUGZILLA 9144): synchronized CRITSECSIZE should be a target constant) +$(LI $(BUGZILLA 9199): Module level qualified functions should be rejected) +$(LI $(BUGZILLA 9209): ice$(LPAREN)symbol.c$(RPAREN) with const struct heap allocation) +$(LI $(BUGZILLA 9231): overriding inout funcion with attribute inference reports weird error) +$(LI $(BUGZILLA 9232): Parsing error on some templated methods calls) +$(LI $(BUGZILLA 9241): 2.061: Property call error message disappeared) +$(LI $(BUGZILLA 9280): Runtime range violation with named capture groups in regex) +$(LI $(BUGZILLA 9311): shared library file extension incorrectly modified) +$(LI $(BUGZILLA 9345): CTFE fails when using std.string.format with imported string enum) +$(LI $(BUGZILLA 9346): nested struct calls disabled postblit) +$(LI $(BUGZILLA 9386): struct destructor called erroneously) +$(LI $(BUGZILLA 9393): Partial template specialization and template lambda does not work) +$(LI $(BUGZILLA 9401): destructor and nothrow syntax) +$(LI $(BUGZILLA 9413): Incorrect modification inside contracts is not detected correctly) +$(LI $(BUGZILLA 9414): Incorrect modification inside contracts is not detected on virtual function) +$(LI $(BUGZILLA 9415): delegate inference should make function literal impure) +$(LI $(BUGZILLA 9417): "no size yet for forward reference" error with nested structure) +$(LI $(BUGZILLA 9428): Wrong array concatenation) +$(LI $(BUGZILLA 9441): struct constructor missed on auto/type-inferred variable definition) +$(LI $(BUGZILLA 9445): interpret.c:151: Assertion `v->ctfeAdrOnStack >= 0 $(AMP)$(AMP) v->ctfeAdrOnStack < stackPointer$(LPAREN)$(RPAREN)` failed.) +$(LI $(BUGZILLA 9451): Listing abstract functions in diagnostic should show full signature) +$(LI $(BUGZILLA 9473): Unittest docs should each be in their own section) +$(LI $(BUGZILLA 9474): Ddoc'd unittests should work correctly with interspersed version$(LPAREN)none$(RPAREN)) +$(LI $(BUGZILLA 9475): Should retain source formatting in ddoc's unittests) +$(LI $(BUGZILLA 9480): The template name in the JSON output contains template and function arguments) +$(LI $(BUGZILLA 9494): compiler stack overflow on invalid associative array) +$(LI $(BUGZILLA 9495): Win64 vararg issue when first argument is > 8 byte) +$(LI $(BUGZILLA 9508): RDMD doesn't generate new dependency list when a file is changed.) +$(LI $(BUGZILLA 9540): Compiler crash on delegate context frame assignment) +$(LI $(BUGZILLA 9561): Many error messages from std.format) +$(LI $(BUGZILLA 9590): UFCS does not work with void lazy expressions) +$(LI $(BUGZILLA 9613): Parser bug when using .init with type constructor) +$(LI $(BUGZILLA 9617): ulong.max is wrongly accepted by smaller signed parameter) +$(LI $(BUGZILLA 9619): Failed struct field typeof in inner function) +$(LI $(BUGZILLA 9622): Range violation in rdmd) +$(LI $(BUGZILLA 9649): DMD doesn't parse valid PostfixExpression . NewExpression syntax.) +$(LI $(BUGZILLA 9652): __traits$(LPAREN)getAttributes$(RPAREN) doesn't work with manifest constants) +$(LI $(BUGZILLA 9654): Template function cannot take string by ref T[len]) +$(LI $(BUGZILLA 9656): Built-in dup result should behave as like unique array, if it is possible.) +$(LI $(BUGZILLA 9658): Setting pre-initialized field should be allowed in qualified constructor.) +$(LI $(BUGZILLA 9677): Crash on setting length property of array VC 2012 64 bit) +$(LI $(BUGZILLA 9679): Refused const/immutable assignment in conditional) +$(LI $(BUGZILLA 9692): __traits$(LPAREN)allMembers$(RPAREN) fails on module without a package) +$(LI $(BUGZILLA 9700): std.typecons.Proxy with invaliant and in-place operation causes Access Violation) +$(LI $(BUGZILLA 9712): IFTI does not support deducing static array types from array literal arguments) +$(LI $(BUGZILLA 9713): Ddoc: Empty description suppress automatic example generation) +$(LI $(BUGZILLA 9714): Ddoc: Combination of -D and -unittest reveals hidden unittest function) +$(LI $(BUGZILLA 9720): OSX wrong code with -O Illegal instruction) +$(LI $(BUGZILLA 9722): optimizer kills GOT to EBX load) +$(LI $(BUGZILLA 9729): interface thunk doesn't set EBX to GOT) +$(LI $(BUGZILLA 9735): Casting delegates to void* should be illegal) +$(LI $(BUGZILLA 9736): VS2010 project file does full rebuild every time) +$(LI $(BUGZILLA 9743): IFTI and polymorphic string literal should support implicit conversion to static array type) +$(LI $(BUGZILLA 9744): Poor error message taking address of thread-local variable at compile time) +$(LI $(BUGZILLA 9747): IFTI argument deduction fails for committed string literals which are implicitly converted to a static array) +$(LI $(BUGZILLA 9755): JSON output is missing the protection attribute for templates) +$(LI $(BUGZILLA 9757): Ddoc: documented unittest after ditto should work) +$(LI $(BUGZILLA 9758): Ddoc: empty ddoc comment and unittest block generates no Examples section) +$(LI $(BUGZILLA 9768): No line number for wrong foreach type) +$(LI $(BUGZILLA 9773): ref parameter with default value should not compile) +$(LI $(BUGZILLA 9774): Error message with __error using == on tuple members) +$(LI $(BUGZILLA 9777): Calling final interface method leads to wrong code) +$(LI $(BUGZILLA 9781): -inline will cause backend ICE) +$(LI $(BUGZILLA 9788): -profile doesn't work if exceptions are thrown in the running program) +$(LI $(BUGZILLA 9790): Internal error when compiling a invalid variable in template $(LPAREN)in expression.c and backend\evalu8.c$(RPAREN)) +$(LI $(BUGZILLA 9791): [ICE] $(LPAREN)struct.c line 668$(RPAREN) map with a missing tuple import) +$(LI $(BUGZILLA 9818): Constant folding for static array does not work with initializing by element) +$(LI $(BUGZILLA 9829): rdmd passes '--' to dmd) +$(LI $(BUGZILLA 9837): IFTI should consider enum base type) +$(LI $(BUGZILLA 9844): DMD $(LPAREN)-m64$(RPAREN) int long initialisation bug) +$(LI $(BUGZILLA 9845): enum value should be able to contain forward references in global scope) +$(LI $(BUGZILLA 9863): Incorrect generation of SAHF instruction on 64 bits) +$(LI $(BUGZILLA 9873): Built-in tuple should support equality comparison) +$(LI $(BUGZILLA 9874): Function call syntax disuniformity in template constraints) +$(LI $(BUGZILLA 9880): Redundant template instance displaying in error message) +$(LI $(BUGZILLA 9883): Error on using property as new dynamic array size) +$(LI $(BUGZILLA 9885): IFTI should consider known tuple types.) +$(LI $(BUGZILLA 9892): [ICE] forward reference in enum declaration members causes compiler segfault) +$(LI $(BUGZILLA 9899): struct with pure/nothrow destructor cannot be used as a struct member in pure/nothrow functions) +$(LI $(BUGZILLA 9901): string return from inner template function error) +$(LI $(BUGZILLA 9907): Struct literal with destructor should match to non-ref overload) +$(LI $(BUGZILLA 9910): Scalar op vector is broken.) +$(LI $(BUGZILLA 9928): ice with void* and function literal) +$(LI $(BUGZILLA 9936): Wrong opBinary/opBinaryRight rewrite.) +$(LI $(BUGZILLA 9939): allMembers trait doesn't returns members of nested anonymous enum) +$(LI $(BUGZILLA 9940): ICE applying getProtection to a functions obtained using getOverloads.) +$(LI $(BUGZILLA 9946): A UFCS disallowed in dynamic array allocation) +$(LI $(BUGZILLA 9961): Using UFCS properties suppress actual errors) +$(LI $(BUGZILLA 9965): Wrong Assembly For DIL, SIL Registers) +$(LI $(BUGZILLA 9971): eponymous function is not an lvalue) +$(LI $(BUGZILLA 9985): Postblit isn't called on local struct return) +$(LI $(BUGZILLA 9990): templates with function alias cause forward reference error) +$(LI $(BUGZILLA 9993): const ctor should be preferred than mutable for const obj creation) +$(LI $(BUGZILLA 9994): Built-in generated opAssign should call dtor on assignment) +$(LI $(BUGZILLA 10004): tuple comparison with side-effect should work) +$(LI $(BUGZILLA 10005): struct variable declaration and const-correctness) +$(LI $(BUGZILLA 10011): Wrong JSON "init" property output for class reference initializers) +$(LI $(BUGZILLA 10029): Update list of reserved version identifiers.) +$(LI $(BUGZILLA 10058): Inconsistent mangling between C++ and extern$(LPAREN)C++$(RPAREN).) +$(LI $(BUGZILLA 10059): export doesn't work for variable declarations) +$(LI $(BUGZILLA 10063): inout+pure results in ability to produce immutable reference to mutable data) +$(LI $(BUGZILLA 10066): Template opEquals sometimes obstructs struct compilation) +$(LI $(BUGZILLA 10102): @disable incompletely implemented) +$(LI $(BUGZILLA 10103): template mixin with property overloads) +$(LI $(BUGZILLA 10105): ICE when converting string literal to static char array in enum initializer) +$(LI $(BUGZILLA 10115): More @disabled holes) +$(LI $(BUGZILLA 10171): Unexpected error "cannot infer type from overloaded function symbol") +$(LI $(BUGZILLA 10180): offsetof doesn't work through function call alias this) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 3449): const and invariant struct members do not behave according to spec) +$(LI $(BUGZILLA 3502): Fix for dropped Mac OS X 10.5) +$(LI $(BUGZILLA 3673): inheritance + if clause = no go) +$(LI $(BUGZILLA 4528): Better error message for private abstract method) +$(LI $(BUGZILLA 5140): Add __FUNCTION__, __PRETTY_FUNCTION__, and __MODULE__) +$(LI $(BUGZILLA 6185): Include non-global functions when resolving UFCS) +$(LI $(BUGZILLA 6453): Allow multiple invariant per struct/class) +$(LI $(BUGZILLA 6809): IFTI should imply const where inout is present on args, but not on return type) +$(LI $(BUGZILLA 7444): Require [] for array copies too) +$(LI $(BUGZILLA 7511): attribute inference should work for template functions) +$(LI $(BUGZILLA 8220): invalid function call not detected during semantic analysis) +$(LI $(BUGZILLA 8669): TemplateThisParameter should change member function's qualifier) +$(LI $(BUGZILLA 8819): void static array should have init built-in propert) +$(LI $(BUGZILLA 8959): IsExpression should support syntax which has no Identifier in all cases) +$(LI $(BUGZILLA 9033): Remove __thread from the language) +$(LI $(BUGZILLA 9136): Add isNested trait) +$(LI $(BUGZILLA 9155): Ddoc: code section should strip leading spaces) +$(LI $(BUGZILLA 9170): CTFE: Allow reinterpret casts float $(LESS)-$(GREATER) int) +$(LI $(BUGZILLA 9185): Add note about where -op is useful) +$(LI $(BUGZILLA 9574): Diagnostic for old use of 'alias this = that' should be informative) +$(LI $(BUGZILLA 9627): Not good enough error messages in some cases when using UFCS) +$(LI $(BUGZILLA 9635): Improved error message for failed access of array field properties from static method) +$(LI $(BUGZILLA 9676): Ddoc: Wrap deprecated declarations in a $$(LPAREN)DEPRECATED$(RPAREN) macro) +$(LI $(BUGZILLA 9680): Include entry point location in "dmd -v -o-" output) +$(LI $(BUGZILLA 9723): Implement -main switch to inject a default main$(LPAREN)$(RPAREN) function) +$(LI $(BUGZILLA 9726): Add minimum % coverage required for -cov testing) +$(LI $(BUGZILLA 9727): Documented unittest comment should appear before Example section) +$(LI $(BUGZILLA 9745): Allow non-thread local static variables to have their address taken in CTFE) +$(LI $(BUGZILLA 9778): RDMD: Support passing resource files to DMD) +$(LI $(BUGZILLA 9789): Ddoc for aliases should use new "alias x=y" syntax) +$(LI $(BUGZILLA 9866): movsxd not supported) +$(LI $(BUGZILLA 9920): [Optimizer] Use mul/imul for integer division by constant) +$(LI $(BUGZILLA 9941): [CTFE] Allow to store "newed" classes and structs in the data segment) +$(LI $(BUGZILLA 9943): Allow to return typeid from CTFE) +$(LI $(BUGZILLA 9963): Absurdly Inefficient Codegen For Adding Boolean Predicates) +$(LI $(BUGZILLA 9977): Function local templates should be allowed) +$(LI $(BUGZILLA 10030): Support '-l:' switch when passing default library to ld) +$(LI $(BUGZILLA 10077): add pragma$(LPAREN)mangle, "..."$(RPAREN) to override symbol mangle.) +$(LI $(BUGZILLA 10109): add -transition compiler switch to aid in dealing with breaking changes) +$(LI $(BUGZILLA 10150): Prefix method 'this' qualifiers should be just ignored anytime) +$(LI $(BUGZILLA 10179): Tuple assignment should not cause "has no effect" error even if the length is zero) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 9122): std.concurrency send$(LPAREN)$(RPAREN) fails with multiple arrays) +$(LI $(BUGZILLA 9742): std.math.floor returns 0 for any value x > -1 and x $(LESS) 0) +$(LI $(BUGZILLA 10122): `Appender` doesn't work with disabled default construction) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 3795): Problem with phobos std.variant) +$(LI $(BUGZILLA 4729): std.algorithm: strange iota behaviour) +$(LI $(BUGZILLA 4798): std.algorithm.map unusable for ranges with const elements) +$(LI $(BUGZILLA 4955): struct dirent.d_type is not a mask) +$(LI $(BUGZILLA 5032): std.file.rename acts differently on Windows and Linux when the target file already exists.) +$(LI $(BUGZILLA 5201): std.string.indexOf and std.algorithm.indexOf return different things for narrow strings) +$(LI $(BUGZILLA 5310): Variant == const$(LPAREN)Variant$(RPAREN) doesn't compile) +$(LI $(BUGZILLA 5359): std.traits.isDelegate should work for types and expressions) +$(LI $(BUGZILLA 5360): calling rdmd from different folder) +$(LI $(BUGZILLA 5514): Erroneous documentation and lacking randomization for topN) +$(LI $(BUGZILLA 5658): Undocumented fields in std.typecons.Tuple) +$(LI $(BUGZILLA 5924): schwartzSort of Tuple!$(LPAREN)char$(RPAREN)[]) +$(LI $(BUGZILLA 8321): std.range.put doesn't work with RefCounted output range) +$(LI $(BUGZILLA 8613): std.typecons.Proxy cannot work with operator 'in') +$(LI $(BUGZILLA 8655): bitfields and Typedef don't mix) +$(LI $(BUGZILLA 9164): Can't easily assign one Nullable to another) +$(LI $(BUGZILLA 9431): Tuple creation problem with array of array) +$(LI $(BUGZILLA 9456): decodeFront is inconsistent in whether it pops elements off of the range or not) +$(LI $(BUGZILLA 9512): std.regex: Incorrect parsing of hex sequences composed from capital letters.) +$(LI $(BUGZILLA 9553): SOCKET should be 64 bit wide on Win64) +$(LI $(BUGZILLA 9583): std.getopt.getopt does not consume options terminator "--" from args list, as docs claim) +$(LI $(BUGZILLA 9612): std.range.Cycle.opSlice tests on the bounds are missing) +$(LI $(BUGZILLA 9624): fullyQualifiedName fails for functions) +$(LI $(BUGZILLA 9648): Missing std.random import for std.algorithm.topN) +$(LI $(BUGZILLA 9753): std.string.translate precondition asserts) +$(LI $(BUGZILLA 9794): std.json cannot handle delete character) +$(LI $(BUGZILLA 9804): `std.math.FloatingPointControl` corrupts floating point state) +$(LI $(BUGZILLA 9812): std.conv.parse string fails on certain escape characters.) +$(LI $(BUGZILLA 9836): std.array.popFront does not work with alias this.) +$(LI $(BUGZILLA 9950): std.json should return empty string/array instead of null on empty input) +$(LI $(BUGZILLA 9956): hasElaborateAssign trait does not work with static arrays) +$(LI $(BUGZILLA 9979): Regex bug with \b and look-behind) +$(LI $(BUGZILLA 10116): stdio.File.byLine repeats last line forever, readln$(LPAREN)ref C[],R$(RPAREN) returns bad data) +$(LI $(BUGZILLA 10167): Wrong Document Comment on std.format.d$(LPAREN)181$(RPAREN)) +$(LI $(BUGZILLA 10182): std.bitmanip unit test has pointless/unused foreach loop) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 4787): std.algorithm.bisectRight$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 4921): Synopsis code in std.variant documentation throws an assertion error) +$(LI $(BUGZILLA 5013): std.typecons.Tuple should have constructor for static arrays) +$(LI $(BUGZILLA 5106): makeIndex should return SortedRange) +$(LI $(BUGZILLA 5226): indexOf$(LPAREN)$(RPAREN) which takes a pred but no needle) +$(LI $(BUGZILLA 5401): std.socket updates and boost license) +$(LI $(BUGZILLA 5507): countUntil should take Ranges... instead of R2) +$(LI $(BUGZILLA 6224): Add an ownerTid property in std.concurrency) +$(LI $(BUGZILLA 6486): std.math.abs$(LPAREN)BigInt$(RPAREN)) +$(LI $(BUGZILLA 7405): std.algorithm.schwartzSort.release) +$(LI $(BUGZILLA 9260): getopt should allow setting booleans to false) +$(LI $(BUGZILLA 9265): Nullable fixed-sized array wrapper) +$(LI $(BUGZILLA 9625): assertNotThrown should print exception msg if no msg is provided) +$(LI $(BUGZILLA 9802): Add `std.traits.{isNested,hasNested}`.) +$(LI $(BUGZILLA 9814): Add std.traits.isNestedFunction) +$(LI $(BUGZILLA 9839): std.traits.Select should be able to select symbols) +$(LI $(BUGZILLA 9888): Allow passing a generator to std.random.uniform for enums) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 4307): spawn$(LPAREN)$(RPAREN)'ed thread doesn't terminate) +$(LI $(BUGZILLA 6024): Document that Windows 2000 SP4 is no longer supported) +$(LI $(BUGZILLA 10057): [2.063 beta] Module info overwritten in shared phobos.) +$(LI $(BUGZILLA 10081): Incorrect char array comparison) +) +$(BUGSTITLE Optlink bugs, + +$(LI $(BUGZILLA 6144): Unexpected OPTLINK Termination at EIP=00428DA3) +) +$(BUGSTITLE Installer bugs, + +$(LI $(BUGZILLA 9343): Problem installing dmd-2.061-0.fedora.x86_64.rpm on Fedora 18) +) +$(BUGSTITLE Website bugs, + +$(LI $(BUGZILLA 4847): std.algorithm.topN documentation) +$(LI $(BUGZILLA 9544): D logo image is broken on non-root-level pages) +$(LI $(BUGZILLA 9609): Ddoc tags for std.string.icmp seem wrong) +$(LI $(BUGZILLA 10036): missing core.atomic docs on dlang.org) +)) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.063 + TITLE=Change Log: $(VER) diff --git a/changelog/2.064.dd b/changelog/2.064.dd new file mode 100644 index 0000000000..f0b73e85de --- /dev/null +++ b/changelog/2.064.dd @@ -0,0 +1,1427 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION November 5, 2013, =================================================, + +$(BUGSTITLE Language Enhancements, +$(LI $(RELATIVE_LINK2 import-package, Introduced the ability to define and import package modules.)) +$(LI $(RELATIVE_LINK2 eponymous-template, Introduced a new eponymous template syntax.)) +$(LI $(RELATIVE_LINK2 postfix-new, Postfix expressions are now allowed after a $(D new) expression.)) +$(LI $(RELATIVE_LINK2 ifti-deduction, Implicit Function Template Instantiation now supports enclosing type/scope deduction.)) +$(LI $(RELATIVE_LINK2 ddoc-warning, DDoc can now warn the user when the symbol names in a ddoc comment do not match the actual code.)) +$(LI $(RELATIVE_LINK2 slice-pointer, Strings literals which are sliced are now implicitly convertible to a char pointer.)) +$(LI $(RELATIVE_LINK2 function-template-overload, Templated and non-template functions can now be overloaded against each other.)) +$(LI $(RELATIVE_LINK2 template-overload-set, Cross-module template declarations can now make an overload set.)) +) + +$(BUGSTITLE Compiler Changes, +$(LI $(RELATIVE_LINK2 deps-printing, Allow printing dependencies to stdout for tooling support.)) +) + +$(BUGSTITLE Compiler Enhancements, +$(LI $(RELATIVE_LINK2 getunittest-trait, Introduced the $(D getUnitTests) trait for retrieval and custom execution of unittests.)) +$(LI $(RELATIVE_LINK2 getvirtualindex-trait, Introduced the $(D getVirtualIndex) trait to get the index of a virtual function.)) +$(LI $(RELATIVE_LINK2 isoverridefunction-trait, Introduced the $(D isOverrideFunction) trait which indicates if a function is overridden or not.)) +) + +$(BUGSTITLE Phobos enhancements, +$(LI $(RELATIVE_LINK2 wrap-unwrap, Introduced the structural typesafe conversion functions $(D wrap) and $(D unwrap).)) +$(LI $(RELATIVE_LINK2 pure-conv-format, $(D std.conv.to) and $(D std.string.format) are now pure functions.)) +$(LI $(RELATIVE_LINK2 generic-strip, Introduced generic $(D strip)/$(D stripLeft)/$(D stripRight) functions.)) +$(LI $(RELATIVE_LINK2 translate-buffer, Introduced an overload of $(D std.string.translate) which can take a buffer, avoiding the need for implicit memory allocations.)) +$(LI $(RELATIVE_LINK2 current-path, Introduced the $(D thisExePath) function to retrieve the executable path of the currently running process.)) +$(LI $(RELATIVE_LINK2 regex-api, New API for std.regex $(D match)/$(D replace) functions. )) +$(LI $(RELATIVE_LINK2 ct-regex, Compile-time $(D std.regex.ctRegex) now supports lookaround just like run-time one.)) +) + +$(BR)$(BIG $(RELATIVE_LINK2 list2064, List of all bug fixes and enhancements in D 2.064.)) + +$(HR) + +$(BUGSTITLE Language Enhancements, + +$(LI $(LEGACY_LNAME2 import_package, import-package, Introduced the ability to define and import package modules.) + +$(P The new package import feature allows you to define a library module which has the purpose of publicly importing +any other modules in that library. The user can then simply import this one module and use the library as +if the user import all the modules at once. For example:) + +$(P $(B libweb/client.d:)) + +--------- +module libweb.client; + +void runClient() { } +--------- + +$(P $(B libweb/server.d:)) + +--------- +module libweb.server; + +void runServer() { } +--------- + +$(P $(B libweb/package.d:)) + +--------- +module libweb; + +public import libweb.client; +public import libweb.server; +--------- + +$(P Notice that the package module must always have the file name $(D package.d). The module name +is the qualified name of the package. The user then uses the standard import syntax to import a +package module, simply using the module declaration name to import the package:) + +$(P $(B test.d:)) + +--------- +module test; + +import libweb; + +void main() +{ + startServer(); + startClient(); +} +--------- + +$(P The following is an example of a package module of a sub-package:) + +$(P $(B libweb/utils/package.d:)) + +--------- +module libweb.utils; // fully qualified name of the package, not just "utils"! + +// publicly import modules from within the 'libweb.utils' package. +public import libweb.utils.conv; +public import libweb.utils.text; +--------- + +$(P To import this subpackage, use the standard module import declaration:) + +$(P $(B test.d:)) + +--------- +module test; + +import libweb.utils; + +void main() +{ +} +--------- + +$(H3 Rationale:) + +$(P Until now $(I public import) modules were implementable, but only by convention. The user would typically +have to import a specific module specified by the library author, e.g. $(D libweb.all) or $(D libweb._). +Introducing the package import feature standardizes this common convention of library authors) +) + +$(LI $(LEGACY_LNAME2 eponymous_template, eponymous-template, Introduced a new eponymous template syntax.) + +$(P The new eponymous template syntax allows you to write shorter templates without having to +explicitly define and repeat the template name when using traditional eponymous templates. +For example, before 2.064 eponymous templates were written and used like the following:) + +--------- +template Tuple(T...) { alias Tuple = T; } + +template isIntOrFloat(T) +{ + static if (is(T == int) || is(T == float)) + enum isIntOrFloat = true; + else + enum isIntOrFloat = false; +} + +void main() +{ + alias Tup = Tuple!(int, float, string); + static assert(isIntOrFloat!(Tup[0])); // int is an int or a float + static assert(isIntOrFloat!(Tup[1])); // float is an int or a float + static assert(!isIntOrFloat!(Tup[2])); // string is neither an int nor a float +} +--------- + +$(P With the new eponymous syntax, the implementation code becomes much simpler:) + +--------- +alias Tuple(T...) = T; + +enum isIntOrFloat(T) = is(T == int) || is(T == float); + +void main() +{ + alias Tup = Tuple!(int, float, string); + static assert(isIntOrFloat!(Tup[0])); // int is an int or a float + static assert(isIntOrFloat!(Tup[1])); // float is an int or a float + static assert(!isIntOrFloat!(Tup[2])); // string is neither an int nor a float +} +--------- + +$(P Notice how you need to start the declaration of such a template with an $(D alias) or $(D enum), +rather than starting it with the keyword $(D template).) + +$(H3 Limitations:) + +$(P Currently you cannot define template constraints for these types of templates. +This limitation may be lifted in a future release.) +) + +$(LI $(LEGACY_LNAME2 postfix_new, postfix-new, Postfix expressions are now allowed after a $(D new) expression.) + +$(P Before 2.064, you could not both instantiate a new class and call a method or access a property +of the object without having to wrap the $(D new) expression in parentheses:) + +--------- +class Server +{ + this(string[] args) { } + void run() { } +} + +void main(string[] args) +{ + (new Server(args)).run(); +} +--------- + +$(P In 2.064 this limitation has been lifted, allowing you to write the code as follows:) + +--------- +class Server +{ + this(string[] args) { } + void run() { } +} + +void main(string[] args) +{ + new Server(args).run(); +} +--------- + +$(P $(B Note:) When instantiating a class with the default constructor, you must insert +an empty set of parentheses before accessing a field or calling a method on the object:) + +--------- +class Server +{ + this() { } + void run() { } +} + +void main() +{ + new Server.run(); // error + new Server().run(); // ok +} +--------- +) + +$(LI $(LEGACY_LNAME2 ifti_deduction, ifti-deduction, Implicit Function Template Instantiation now supports enclosing type/scope deduction:)) + +$(P IFTI has been improved, allowing you to write code such as the following:) + +--------- +struct A +{ + struct Foo { } +} + +struct B +{ + struct Foo { } +} + +/** +Templated function which expects the second argument to be of type 'Foo, +which is a nested in the type 'T'. +*/ +void call(T)(T t, T.Foo foo) { } + +void main() +{ + auto a = A(); + auto a_f = A.Foo(); + call(a, a_f); // ok + + auto b = B(); + auto b_f = B.Foo(); + call(b, b_f); // ok + + call(a, b_f); // fails: b_f is typed as B.Foo, not A.Foo +} +--------- + +$(P This IFTI feature also allows you to retrieve the module of a symbol, by using an $(D alias) +template parameter, rather than a type one:) + +--------- +module my_module; + +struct A +{ + struct B { } +} + +void foo(alias Mod)(Mod.A, Mod.A.B) +{ + // 'Mod' is deduced to be the module 'my_module' which encloses the struct 'A' + static assert(__traits(isSame, Mod, my_module)); +} + +void main() +{ + A a; + A.B b; + foo(a, b); // ok +} +--------- + + +$(LI $(LEGACY_LNAME2 ddoc_warning, ddoc-warning, DDoc can now warn the user when the symbol names in a ddoc comment do not match the actual code:)) + +$(P Here is an example documented function, where the parameter names are wrongly documented:) + +--------- +/** + This is the sum function. + + params: + x = The first parameter + y = The second parameter +*/ +int sum(int a, int b) +{ + return a + b; +} +--------- + +$(P Generating the documentation with warnings enabled will emit the following:) + +$(CONSOLE +dmd -D -c -w test.d +) + +$(CONSOLE +test.d(8): Warning: Ddoc: function declaration has no parameter 'x' +test.d(8): Warning: Ddoc: function declaration has no parameter 'y' +) + +$(P This feature can help ensure that the documentation for library code is always kept up-to-date.) + +$(P $(B Note:) Remember to use the $(B -w) switch when building the documentation with the $(B -D) switch +in order to enable these warnings.) + +$(LI $(LEGACY_LNAME2 slice_pointer, slice-pointer, Strings literals which are sliced are now implicitly convertible to a char pointer:)) + +$(P To help ease interacting with C libraries which expect strings as null-terminated pointers, +slicing string $(B literals) (not variables!) will now allow the implicit conversion to such a pointer:) + +--------- +extern(C) void call(const(char)* str) { } + +void main() +{ + const(char)* abc = "abc"; + call(abc); // already previously allowed + + const(char)* ab = "abc"[0 .. 2]; + call(ab); // allowed in 2.064 +} +--------- + + +$(LI $(LEGACY_LNAME2 function_template_overload, function-template-overload, Templated and non-template functions can now be overloaded against each other:)) + +--------- +auto foo(int n) { return 1; } +auto foo(T)(T t) { return 2; } + +void main() +{ + assert(foo(100) == 1); + assert(foo("a") == 2); + + // Integer literal 10L can be converted to int without loss of precisions. + // Then the call matches to foo(int n). + assert(foo(10L) == 1); + + // A runtime variable 'num' typed long is not implicitly convertible to int. + // Then the call matches to foo(T)(T t). + long num = 10L; + assert(foo(num) == 2); +} +--------- + + +$(LI $(LEGACY_LNAME2 template_overload_set, template-overload-set, Cross-module template declarations can now make an overload set:)) + +$(P Template declarations are now overloadable just like regular function declarations. Templates with matching names from multiple modules will introduce an overload set:) + +--------- +module a; + +template Traits(T) if (is(T == double)) +{ + enum Traits = "abc"; +} + +auto func(T, A...)(A args) if (is(T == double)) +{ + return 1; +} +--------- +--------- +module b; + +template Traits(T) if (is(T == string)) +{ + enum Traits = "def"; +} + +auto func(T, A...)(A args) if (is(T == string)) +{ + return 2; +} +--------- +--------- +module c; +import a, b; +static assert(Traits!double == "abc"); // matches to a.Traits +static assert(Traits!string == "def"); // matches to b.Traits +void main() +{ + assert(func!double(1, "msg") == 1); // matches to a.func(T, A...) + assert(func!string(1, "msg") == 2); // matches to b.func(T, A...) +} +--------- + +$(H3 Limitations:) + +$(P Merging template overload sets by using an alias declaration is currently not supported. +The limitation will be lifted in a future release.) +) + +$(BUGSTITLE Compiler Changes, + +$(LI $(LEGACY_LNAME2 deps_printing, deps-printing, Allow printing dependencies to stdout for tooling support:)) + +$(P You can now use the $(B -deps) switch without having to specify a filename. +The dependencies will then be printed to standard output, allowing both users and tools +to introspect the dependencies in the output.) + +$(P The types of dependencies which are printed out are as follows:) + +$(P $(B depsImport): Module imports found (same as -deps=file output, except prefixed with depsImport)) +$(P $(B depsVersion): Versions (except standard ones and ones set in the module itself)) +$(P $(B depsFile): String imports found, e.g. $(D string x = import("foo.txt");)) +$(P $(B depsLib): Libraries specified with a $(D pragma(lib) statement)) +$(P $(B depsDebug): Any $(D debug()) statements found (except the ones set in the module itself)) +) + +$(BUGSTITLE Compiler Enhancements, +$(LI $(LEGACY_LNAME2 getunittest_trait, getunittest-trait, Introduced the $(D getUnitTests) trait for retrieval and custom execution of unittests:)) + +$(P With the new $(D getUnitTests) trait you can retrieve all unittest in a module or an +aggregate, and then run the tests manually. Here's an example of implementing a custom +unittest running routine which prints out some additional statistics:) + +--------- +import core.runtime; +import core.exception; +import std.stdio; + +shared static this() +{ + // this overrides the default D runtime unittest runner function, + // since we're providing a __traits-based one in our main function. + Runtime.moduleUnitTester = { return true; }; +} + +unittest +{ + assert(1); // passes. +} + +unittest +{ + assert(0); // fails. +} + +unittest +{ + assert(1); // passes. +} + +void main() +{ + Throwable[] errors; // collect all thrown exceptions. + size_t passCount; // count the number of unittests which pass. + + // iterate over each unittest (this is a tuple). + foreach (test; __traits(getUnitTests, my_module)) + { + try + { + test(); + passCount++; + } + catch (Throwable error) + { + errors ~= error; + } + } + + // print out the errors or the statistics. + if (errors.length) + { + writeln("Some unittests failed:\n"); + foreach (error; errors) + writeln(error); + } + else + { + writefln("All unittests passed. Passed unittest count: %s", passCount); + } +} +--------- + +$(P $(B Note:) You must compile with the $(D -unittest) flag to be able to retrieve the unittests.) + +$(P $(B Note:) By default the D runtime provides its own unittest execution function. +If you want to avoid it from being invoked at runtime (before the main function is called) you +need to set a custom one by assigning to $(D Runtime.moduleUnitTester) in the module constructor. +The one used in the above test-case simply returns $(D true), which allows the $(D main) function +to be called.) + +$(P $(B Note:) The $(D getUnitTests) trait is not recursive. This means that calling it on a module +will not retrieve unittests which are nested in aggregates in that module.) + +$(LI $(LEGACY_LNAME2 getvirtualindex_trait, getvirtualindex-trait, Introduced the $(D getVirtualIndex) trait to get the index of a virtual function:)) + +$(P You can use this trait to get the index of a virtual method in the virtual method table:) + +--------- +class C +{ + void foo() { } + void bar() { } +} + +class D : C +{ + void doo() { } + void doo(int) { } + void doo(double) { } +} + +void main() +{ + /** + Note that each class implicitly inherits from the Object class, + so the following will most likely not begin with index 0. + */ + pragma(msg, __traits(getVirtualIndex, D.foo)); + pragma(msg, __traits(getVirtualIndex, D.bar)); + + /** + When dealing with overloads you can use the getOverloads trait to index + into a specific method + */ + pragma(msg, __traits(getVirtualIndex, __traits(getOverloads, D, "doo")[0])); + pragma(msg, __traits(getVirtualIndex, __traits(getOverloads, D, "doo")[1])); + pragma(msg, __traits(getVirtualIndex, __traits(getOverloads, D, "doo")[2])); +} +--------- + +$(LI $(LEGACY_LNAME2 isoverridefunction_trait, isoverridefunction-trait, Introduced the $(D isOverrideFunction) trait which indicates whether or not a function is overriding:)) + +--- +class Base +{ + void foo() { } +} + +class Foo : Base +{ + override void foo() { } + void bar() { } +} + +static assert (__traits(isOverrideFunction, Base.foo) == false); +static assert (__traits(isOverrideFunction, Foo.foo) == true); +static assert (__traits(isOverrideFunction, Foo.bar) == false); +--- +) + +$(BUGSTITLE Phobos enhancements, + +$(LI $(LEGACY_LNAME2 wrap_unwrap, wrap-unwrap, Introduced the structural typesafe conversion functions $(D wrap) and $(D unwrap):)) + +$(P Sometimes you may want your class to be usable with a function which expects a specific interface +argument type, but you do not necessarily want to edit the class to inherit that interface. +The class could also be implemented in another library for which you do not have the source code, +which means you wouldn't be able to edit the inheritance list of that class.) + +$(P The new $(D wrap) function allows you to perform a $(I structural cast), allowing a class object to +act as if it were an object of another type. For example (note: for now please pass the -allinst flag to dmd when compiling):) + +--------- +import std.typecons; + +interface IDrawable +{ + void drawLine(int x1, int y1, int x2, int y2); +} + +class ImageDraw // note: it does not inherit IDrawable. +{ + void drawLine(int x1, int y1, int x2, int y2) { } +} + +/** Draw a rectangle outline. */ +void drawRect(IDrawable draw) +{ + draw.drawLine( 0, 0, 100, 0); + draw.drawLine(100, 0, 100, 100); + draw.drawLine( 0, 100, 100, 100); + draw.drawLine( 0, 0, 0, 100); +} + +void main() +{ + auto imageDraw = new ImageDraw(); + drawRect(imageDraw); // error: can't call this, ImageDraw is not an IDrawable. + + // perform a structural cast. + IDrawable i = wrap!IDrawable(imageDraw); + drawRect(i); // and now imageDraw can act as an IDrawable. +} +--------- + +$(P The $(D wrap) function can also be used with classes which define an $(D opDispatch) function, for example:) + +--------- +import std.typecons; + +interface IDrawable +{ + void drawLine(int x1, int y1, int x2, int y2); + void drawRect(int x, int y, int width, int height); +} + +class ImageDraw +{ + void opDispatch(string name, Args...)(Args args) + if (name == "drawLine") + { + // ... + } + + void opDispatch(string name, Args...)(Args args) + if (name == "drawRect") + { + // ... + } +} + +/** Draw some shapes. */ +void drawShapes(IDrawable draw) +{ + draw.drawLine(0, 100, 100, 0); + draw.drawRect(0, 0, 100, 100); +} + +void main() +{ + auto imageDraw = new ImageDraw(); + IDrawable i = wrap!IDrawable(imageDraw); + drawShapes(i); +} +--------- + +$(P You can unwrap a structurally cast object back to its original type:) + +--------- +interface IDrawable +{ + void drawLine(int x1, int y1, int x2, int y2); +} + +class ImageDraw +{ + void drawLine(int x1, int y1, int x2, int y2) { } +} + +void main() +{ + auto imageDraw = new ImageDraw(); + + // perform a structural cast (note the simple UFCS syntax). + IDrawable i = imageDraw.wrap!IDrawable; + + // get back the original type (ditto, using UFCS syntax). + ImageDraw draw = i.unwrap!ImageDraw; +} +--------- + +$(P And you can structurally cast to multiple interface types:) + +--------- +import std.typecons; + +unittest +{ + interface IStoppable { void stop(); } + interface IRunnable { void run(); } + + class Timer + { + void run() { } + void stop() { } + } + + auto timer = new Timer(); + auto obj = timer.wrap!(IStoppable, IRunnable); + + // extract the individual structurally casted types + // from the wrapped type + IStoppable iStop = obj; + IRunnable iRun = obj; + + iRun.run(); + iStop.stop(); +} +--------- + +$(LI $(LEGACY_LNAME2 pure_conv_format, pure-conv-format, $(D std.conv.to) and $(D std.string.format) are now pure functions:)) + +$(P Since 2.064, pure functions can take advantage of $(D to) and $(D format). For example:) + +--------- +import std.conv; +import std.string; + +void main() pure // this main is a pure function. +{ + string date = format("%s.%s.%s", 2013, 12, 10); + int one = to!int(1.0); +} +--------- + +$(LI $(LEGACY_LNAME2 generic_strip, generic-strip, Introduced generic $(D strip)/$(D stripLeft)/$(D stripRight) functions:)) + +$(P The new generic strip functions allow you to not only strip strings but also any other Input range +($(D stripLeft)) or Bidirectional range ($(D strip)/$(D stripRight)), for example:) + +--------- +import std.algorithm; + +void main() +{ + // strip whitespace. + assert(" foobar ".strip!(a => a == ' ')() == "foobar"); + + // an audio waveform. + float[] data = [0.0, 0.0, 0.1, 0.5, 0.2]; + + // strip leading silence in the waveform. + assert(data.strip!(a => a < 0.1)().length == 3); +} +--------- + +$(LI $(LEGACY_LNAME2 translate_buffer, translate-buffer, Introduced an overload of $(D std.string.translate) which can take a buffer, avoiding the need for implicit memory allocations:)) + +$(P To avoid implicit memory allocations $(D translate) now features overloads which can take an output range +to write the contents to. For example:) + +--------- +import std.array; +import std.string; + +void main() +{ + dchar[dchar] transTable = ['a' : '1', 'b' : '2', 'c': '3']; + + // create our output range by using the Phobos Appender. + auto buffer = appender!(dchar[])(); + + auto toRemove = null; // don't remove any characters. + + translate("abcdef", transTable, toRemove, buffer); + assert(buffer.data == "123def"); + + // or use a static array to avoid heap allocations. + // note: if the buffer is too small an exception will be thrown. + dchar[6] dbuffer; + translate("abcdef", transTable, toRemove, dbuffer[]); + assert(dbuffer == "123def"); +} +--------- + +$(LI $(LEGACY_LNAME2 current_path, current-path, Introduced the $(D thisExePath) function to retrieve the executable path of the currently running process:)) + +$(P With the $(D thisExePath) function you can retrieve the current executable path:) + +--------- +import std.file; +import std.stdio; + +void main(string[] args) +{ + // Prints the full path of the current running executable. + // Note: this may, or may not be the same as args[0]. The content + // of args[0] is dependent of how the application was invoked, thisExePath() + // is not. It's also possible to access thisExePath() from other parts of the + // code than main. + writeln(thisExePath()); +} +--------- +$(LI $(LEGACY_LNAME2 regex_api, regex-api, New API for std.regex $(D match)/$(D replace) functions:)) + +$(P The old API based around "g"(=global) flag was confusing and error prone. +Moreover in some cases it was already being overriden by a function as is the case +with $(D std.regex.splitter).) + +$(P New version ties the operation to the function in question, thus being simpler to +understand without extra context. For the moment the "g" flag is kept working as +is but the new API always overrides it where applicable. Another addition in the new +API is an overload for the $(D replace) family of functions to work directly with +output ranges.) + +$(P To understand the difference in the API compare 2 samples below.) + +$(P Before 2.064:) +--- +void main() +{ + import std.regex, std.algorithm, std.range, std.stdio, std.string; + auto m = "3.141592".match(`(\d+)\.(\d+)`); + // m is a range of ranges + assert(m.front.equal(["3.141592", "3", "141592"])); + + // global vs non-global + auto word = regex(`(\w)\w*`); + auto gword = regex(`(\w)\w*`, "g"); + auto list = "tomatoes, potatoes, pineapple"; + // this will print only 'tomatoes', which raised many questions + foreach(item; list.match(word)) + writeln(item.hit); + + // while this will print each of them + foreach(item; list.match(gword)) + writeln(item.hit); + + auto justFirst = replace!(m => toUpper(m[1]) ~ m[0].drop(1))(list, word); + assert(justFirst == "Tomatoes, potatoes, pineapple"); + auto allOfThem = replace!(m => toUpper(m[1]) ~ m[0].drop(1))(list, gword); + assert(allOfThem == "Tomatoes, Potatoes, Pineapple"); +} +--- +$(P After 2.064:) +--- +void main() +{ + import std.regex, std.algorithm, std.range, std.stdio, std.string; + auto m = "3.141592".matchFirst(`(\d+)\.(\d+)`); + // m is simply a range of submatches + assert(m.equal(["3.141592", "3", "141592"])); + + auto word = regex(`(\w)\w*`); + auto list = "tomatoes, potatoes, pineapple"; + // iterates over submatches so it will print 2 lines: + // tomatoes + // t + foreach(item; list.matchFirst(word)) + writeln(item); + // so just to get the whole match: + assert(list.matchFirst(word).hit == "tomatoes"); + + // now there is no need to check if it has "g" option + // it's crystal clear in the function name + foreach(item; list.matchAll(word)) + writeln(item.hit); + + auto justFirst = replaceFirst!(m => toUpper(m[1]) ~ m[0].drop(1))(list, word); + assert(justFirst == "Tomatoes, potatoes, pineapple"); + auto allOfThem = replaceAll!(m => toUpper(m[1]) ~ m[0].drop(1))(list, word); + assert(allOfThem == "Tomatoes, Potatoes, Pineapple"); + + // NEW feature - if there is no need to allocate, the resulting string + // replacement may be just sent directly to the wire (an OutputRange) + auto sink = stdout.lockingTextWriter(); + replaceAllInto!(m => toUpper(m[1]) ~ m[0].drop(1))(sink, list, word); +} +--- + +$(P The old API still works, even though eventual deprecation is planned. +Also note the new functionality in form of *Into functions that forward the +replacement directly to an output range avoiding extra pressure on the heap.) + +$(LI $(LEGACY_LNAME2 ct_regex, ct-regex, Compile-time $(D std.regex.ctRegex) now supports lookaround just like run-time one:)) + +$(P Now $(D ctRegex) supports full syntax spectrum of run-time one except for set +algebra inside of a character class. For instance, the following now compiles and +passes:) +--- +void main() +{ + import std.regex; + // a word, but not a title-cased ASCII + // ?063: Cannot interpret TypeInfo at compile time) +$(LI $(BUGZILLA 10592): Regression of overloaded template function) +$(LI $(BUGZILLA 10600): regression$(LPAREN)2.063.2$(RPAREN) ICE: Assertion failed: $(LPAREN)type->ty != Tstruct || $(LPAREN)$(LPAREN)TypeStruct *$(RPAREN)type$(RPAREN)->sym == this$(RPAREN), function semantic, file struct.c, line 741.) +$(LI $(BUGZILLA 10612): Regression $(LPAREN)2.064 HEAD$(RPAREN): ICE on using enum as hash key with mutual module imports) +$(LI $(BUGZILLA 10617): contract with -profile -debug is not nothrow) +$(LI $(BUGZILLA 10624): [REG2.064a] ICE with tuple comparison) +$(LI $(BUGZILLA 10626): ICE with vector operation) +$(LI $(BUGZILLA 10628): [REG2.063] spurious "hidden by" deprecation warning) +$(LI $(BUGZILLA 10669): CTFE: using initialized static const class member no longer works) +$(LI $(BUGZILLA 10673): memory corruption in interpret.c) +$(LI $(BUGZILLA 10682): [ICE]$(LPAREN)cgcod.c line 1561$(RPAREN) with ^^ operator and ulong) +$(LI $(BUGZILLA 10684): Refused array op with array literal) +$(LI $(BUGZILLA 10687): Refused cast from uint[] to array of uint-based enums at compile-time) +$(LI $(BUGZILLA 10713): [REG2.063] ICE with typeof$(LPAREN)this.nonExistingField$(RPAREN) in method signature) +$(LI $(BUGZILLA 10721): ICE with constructor with postcondition) +$(LI $(BUGZILLA 10722): Regression $(LPAREN)2.064 git-head$(RPAREN): Cannot interpret struct at compile-time) +$(LI $(BUGZILLA 10726): Bogus Circular Reference error if opEquals defined and has a loop) +$(LI $(BUGZILLA 10727): Regression $(LPAREN)dmd-2.061$(RPAREN) -- DMD dumps core) +$(LI $(BUGZILLA 10734): Assertion failure: '0' on line 1546 in file 'cast.c') +$(LI $(BUGZILLA 10736): Regression $(LPAREN)2.064 git-head$(RPAREN): Instantiation failure triggered by module import and module order) +$(LI $(BUGZILLA 10744): [regression git-head v2.064] Rejects valid interface inheritance + wrong error message) +$(LI $(BUGZILLA 10782): dmd segfault with string mixin, CTFE, class, non-literal initializer) +$(LI $(BUGZILLA 10788): Regression: forward reference of enum member E from another module.) +$(LI $(BUGZILLA 10789): Struct destructor erroneously called) +$(LI $(BUGZILLA 10804): regression$(LPAREN)2.063=>2.064$(RPAREN) problem with Appender or dmd?) +$(LI $(BUGZILLA 10808): [REG2.064a] Incorrect typeid template argument should report error) +$(LI $(BUGZILLA 10836): 'errors compiling the function' for optimized builds) +$(LI $(BUGZILLA 10946): Integer constant expression expected instead of...) +$(LI $(BUGZILLA 10949): CTFE ICE after indexing error) +$(LI $(BUGZILLA 10964): [REG][2.063] Static array assign/blit exception slips through catch block.) +$(LI $(BUGZILLA 10981): Contracts in pure class methods are useless) +$(LI $(BUGZILLA 10994): [REG] cannot declare statics struct with void-initialized static arrays) +$(LI $(BUGZILLA 10998): [REG 2.063] compile-time postblit call check is incorrectly suppressed.) +$(LI $(BUGZILLA 11010): Regression $(LPAREN)2.063.2$(RPAREN) typeid doesn't work on a member of an instance.) +$(LI $(BUGZILLA 11039): Undefined instantiation from circular imports) +$(LI $(BUGZILLA 11054): ICE: interpret.c:357: virtual void Statement::ctfeCompile$(LPAREN)CompiledCtfeFunction*$(RPAREN): Assertion `0` failed.) +$(LI $(BUGZILLA 11062): inline ice with alias this and opIndexAssign) +$(LI $(BUGZILLA 11069): DMD $(LPAREN)github HEAD$(RPAREN) Linker Regression) +$(LI $(BUGZILLA 11081): Win64: duplicate COMDAT with failed compilation with lambdas) +$(LI $(BUGZILLA 11086): dmd segfault) +$(LI $(BUGZILLA 11105): Error on struct with multidimentional static array initialization from its element) +$(LI $(BUGZILLA 11117): Pseudo module __entrypoint.d listed as dependency with -deps) +$(LI $(BUGZILLA 11121): Wrong parenthesis omission in ddoc output) +$(LI $(BUGZILLA 11127): std.range.cycle linker errors) +$(LI $(BUGZILLA 11153): Regression $(LPAREN)2.064 git-head$(RPAREN): ICE during a diagnostic for missing return type) +$(LI $(BUGZILLA 11163): [ICE]$(LPAREN)ctfeexpr.c line 355$(RPAREN) with pragma$(LPAREN)msg$(RPAREN) of a wrong expression) +$(LI $(BUGZILLA 11186): Regression $(LPAREN)2.061$(RPAREN): Presence of Variant and const field invokes opAssign) +$(LI $(BUGZILLA 11197): [DMD 2.064a] Struct with postblit cannot be appended to an AA of arrays) +$(LI $(BUGZILLA 11203): extern $(LPAREN)C++$(RPAREN) classes broken) +$(LI $(BUGZILLA 11220): Regression in master: XXX__lambda2 cannot access frame of function XXX) +$(LI $(BUGZILLA 11223): inline ice with tuple assignment and if/else) +$(LI $(BUGZILLA 11225): Module dependency cycle causes import statements inside typeof$(LPAREN)$(RPAREN) expressions inside templates to fail) +$(LI $(BUGZILLA 11228): alias this confuses static array copy) +$(LI $(BUGZILLA 11230): [REG2.064a] Inexact mangling for template function literal.) +$(LI $(BUGZILLA 11233): DMD HEAD very slow with large static array struct field) +$(LI $(BUGZILLA 11237): zero initializer emitted to read-only data segment, slow compilation) +$(LI $(BUGZILLA 11242): [REG2.064beta] Fails to infer template argument with inout) +$(LI $(BUGZILLA 11245): [REG 2.063] Can't access length of static arrays from within classes) +$(LI $(BUGZILLA 11246): [REG 2.063] Struct initialized in constructor is destroyed first) +$(LI $(BUGZILLA 11256): Error mixing struct with disabled default construction and templated with lambda struct) +$(LI $(BUGZILLA 11261): Can't infer types without explicit slice in foreach) +$(LI $(BUGZILLA 11262): std.regex.replace does not accept StaticRegex) +$(LI $(BUGZILLA 11265): Segfault while calling instance method of class defined inside struct) +$(LI $(BUGZILLA 11267): Resulting executable sizes varies a lot) +$(LI $(BUGZILLA 11271): [REG 2.063] auto ref opAssign + destructor + struct literal fails) +) + +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 952): Strange "Error:" prefix on some warning messages) +$(LI $(BUGZILLA 1982): [CTFE] Problems with compile-time null) +$(LI $(BUGZILLA 2407): function pointer as an enum's base type doesn't work) +$(LI $(BUGZILLA 2486): taking address of slice rvalue should not be allowed) +$(LI $(BUGZILLA 3096): EnumBaseType) +$(LI $(BUGZILLA 3646): Default values of function arguments are ignored when instantiating a template.) +$(LI $(BUGZILLA 3866): anonymous delegate with default parameters cross-talks to another anonymous delegate) +$(LI $(BUGZILLA 4018): __FILE__ and __LINE__ as default template parameters not set to instantiation point per spec) +$(LI $(BUGZILLA 4481): ICE$(LPAREN)glue.c,!vthis->csym$(RPAREN) or compiles, depending on the import statements order) +$(LI $(BUGZILLA 4611): stack overflow or ICE$(LPAREN)cgcod.c$(RPAREN) when static array of structs exceeds 16MB limit) +$(LI $(BUGZILLA 4841): -inline wrecks certain nested structs causing error "*** is a nested function and cannot be accessed from ***") +$(LI $(BUGZILLA 4899): Ddoc: Warnings about stray parens do not include file and line numbers for module comments) +$(LI $(BUGZILLA 5012): ICE$(LPAREN)cod3.c$(RPAREN): handling a nested function in inline asm.) +$(LI $(BUGZILLA 5655): Lambda inside static foreach saves wrong value of counter) +$(LI $(BUGZILLA 5842): hash table corruption) +$(LI $(BUGZILLA 5911): Closure destroys the thrown Exception .) +$(LI $(BUGZILLA 5988): Template accepts instantiating an already-instantiated template type) +$(LI $(BUGZILLA 6107): ICE$(LPAREN)expression.c$(RPAREN) when a non-template member named '__ctor' exists in a struct, and the constructor is attempted to be invoked.) +$(LI $(BUGZILLA 6169): [CTFE] pure functions cannot compute constants using functions not marked as pure) +$(LI $(BUGZILLA 6178): Struct inside the AA are not init correctly) +$(LI $(BUGZILLA 6310): Missing "template instantiation" traceback when an error happens in the template parameter of an alias.) +$(LI $(BUGZILLA 6461): multiple definitions with typeid and multiobj) +$(LI $(BUGZILLA 6711): "with" doesn't work with "alias this") +$(LI $(BUGZILLA 6720): ICE$(LPAREN)cod1.c$(RPAREN) casting return of void function to bool) +$(LI $(BUGZILLA 6799): ICE$(LPAREN)type.c$(RPAREN) involving AAs and pointers to structs) +$(LI $(BUGZILLA 6906): Cannot assign value into associative array if contains opAssign) +$(LI $(BUGZILLA 7051): Class member with un-@safe destructor gives confusing error) +$(LI $(BUGZILLA 7156): ICE$(LPAREN)go.c$(RPAREN): with 199 or 200 repeated integer increments, only with -O) +$(LI $(BUGZILLA 7202): Hole in type system still present for delegates) +$(LI $(BUGZILLA 7254): ICE$(LPAREN)cod3.c$(RPAREN) returning strings as static arrays) +$(LI $(BUGZILLA 7436): ICE$(LPAREN)cg87.c$(RPAREN) ubyte = ubyte op= float) +$(LI $(BUGZILLA 7474): ICE$(LPAREN)cgcs.c$(RPAREN) on instantiating a struct with field and destructor as tuple) +$(LI $(BUGZILLA 7522): ICE$(LPAREN)interpret.c$(RPAREN) Accessing a non-static member without this) +$(LI $(BUGZILLA 7524): D1: #line __LINE__ doesn't parse) +$(LI $(BUGZILLA 7533): Error with no line number with pure static ctor) +$(LI $(BUGZILLA 7538): All kinds of property functions should be called before getting their types inside typeof) +$(LI $(BUGZILLA 7565): ICE$(LPAREN)cg87$(RPAREN):202, postincrement of a double parameter, 64-bit only) +$(LI $(BUGZILLA 7656): ddoc misinterprets commented parentheses in an example) +$(LI $(BUGZILLA 7715): DDoc eats $1, $2, $3 etc. inside d_code section) +$(LI $(BUGZILLA 7727): "static initializer" for non-static unions too) +$(LI $(BUGZILLA 7746): Error with 'TOK232' declaring enum of anonymous nested class type) +$(LI $(BUGZILLA 7780): Template mixin'd members do not properly overload) +$(LI $(BUGZILLA 7806): ICE$(LPAREN)gloop.c$(RPAREN) iterating with idouble, when compiling with -O) +$(LI $(BUGZILLA 7848): pure and nothrow ignored on unittest blocks) +$(LI $(BUGZILLA 7892): Compiler-generated struct copies can result in errors when ctor is @disable'd) +$(LI $(BUGZILLA 7976): ICE$(LPAREN)backend/cg87.c$(RPAREN)assignment btw two elements of dynamic array of complex number types) +$(LI $(BUGZILLA 7988): [CTFE] CTFE return values should be allowed in compile-time expressions) +$(LI $(BUGZILLA 8119): Cannot cast from void* to forwarded struct pointer) +$(LI $(BUGZILLA 8179): ICE$(LPAREN)e2ir.c$(RPAREN) with failed fixed size array cast) +$(LI $(BUGZILLA 8253): CTFE ICE: calling of member function of non-CTFE class variable) +$(LI $(BUGZILLA 8285): Issue with slice returned from CTFE function) +$(LI $(BUGZILLA 8352): Wrong "__overloadset isn't a template" error) +$(LI $(BUGZILLA 8360): Destruction of uninitialized temporary struct with assert) +$(LI $(BUGZILLA 8361): [ICE] $(LPAREN)eh.c line 316$(RPAREN) with struct with dtor in assert) +$(LI $(BUGZILLA 8441): mixin containing template functions causes compiler errors) +$(LI $(BUGZILLA 8563): Exception segfault) +$(LI $(BUGZILLA 8579): Default parameter appears a part of typeof$(LPAREN)$(RPAREN).stringof of a function variable) +$(LI $(BUGZILLA 8651): Slice op Slice throws exceptions $(LPAREN)not errors$(RPAREN), and nothrow) +$(LI $(BUGZILLA 8733): Normalize -of path on Windows) +$(LI $(BUGZILLA 8795): mixing in "switch" or "interface;" makes dmd segfault) +$(LI $(BUGZILLA 8911): -property makes fullyQualifiedName fail for functions) +$(LI $(BUGZILLA 8956): Ability to break typesystem with constructor/postblit/destructor $(LPAREN)e.g. modify immutable$(RPAREN)) +$(LI $(BUGZILLA 8977): Ability to break typesystem with static struct initializer $(LPAREN)e.g. modify immutable$(RPAREN)) +$(LI $(BUGZILLA 9017): __traits$(LPAREN)compiles, { enum e = $(LESS)expression tuple$(GREATER); }$(RPAREN) is true but code doesn't compile) +$(LI $(BUGZILLA 9235): Template mixin doesn't allow to mixin non-conflicting overloads) +$(LI $(BUGZILLA 9247): Compiler accepts opaque struct returned by value from function pointer declaration.) +$(LI $(BUGZILLA 9319): Unexpected compiles __traits behaviour in a certain situation) +$(LI $(BUGZILLA 9364): [ICE] Error: CTFE internal error painting S*) +$(LI $(BUGZILLA 9396): Wrong line number when assigning nested enum to struct) +$(LI $(BUGZILLA 9524): Unittest ddocs fail to appear following ditto) +$(LI $(BUGZILLA 9531): __traits$(LPAREN)parent, ...$(RPAREN) does not work for types defined within a unittest block) +$(LI $(BUGZILLA 9534): Distributed CHM file lacks styling) +$(LI $(BUGZILLA 9546): getProtection trait does not work with mixin or getMember) +$(LI $(BUGZILLA 9571): link error due to using unique ids in anonymous funcliteral) +$(LI $(BUGZILLA 9578): "is a nested function and cannot be accessed from" problem) +$(LI $(BUGZILLA 9586): Win64 5/6/7 struct returns) +$(LI $(BUGZILLA 9628): Lambda in foreach loop Vs. lambda in static foreach loop) +$(LI $(BUGZILLA 9634): [CTFE] wrong code concatenating arrays of structs) +$(LI $(BUGZILLA 9665): Structure constant members can not be initialized if have opAssign) +$(LI $(BUGZILLA 9710): Pointer enums crash dmd) +$(LI $(BUGZILLA 9733): Hello world segfaults on Debian x86_64 with -m64) +$(LI $(BUGZILLA 9782): implementing RTInfo!T causes errors for deprecated types) +$(LI $(BUGZILLA 9859): Cannot use inout in delegate) +$(LI $(BUGZILLA 9904): typeof$(LPAREN)null$(RPAREN) can be casted to aggregate type if .sizeof equals size of pointer) +$(LI $(BUGZILLA 9921): Enum variables of type void should be illegal) +$(LI $(BUGZILLA 9923): [ICE] $(LPAREN)interpret.c line 167$(RPAREN) with countUntil on Typedef[]) +$(LI $(BUGZILLA 9938): ICE using global interface variable in CTFE) +$(LI $(BUGZILLA 9954): Runtime wrong code with global interface var created in CTFE) +$(LI $(BUGZILLA 9982): ICE on CTFE for pointer dereference) +$(LI $(BUGZILLA 10007): function overrides but is not covariant) +$(LI $(BUGZILLA 10037): Compiler should not generate opEquals method implicitly) +$(LI $(BUGZILLA 10064): opDollar called on garbage) +$(LI $(BUGZILLA 10065): Compiler fails without error message for tuple map) +$(LI $(BUGZILLA 10079): Built-in generated opAssign should be pure nothrow @safe by default) +$(LI $(BUGZILLA 10082): ICE$(LPAREN)e2ir.c$(RPAREN) Multiple mixin template instantiations are not checked) +$(LI $(BUGZILLA 10083): Insufficient IFTI/eponymous template specification) +$(LI $(BUGZILLA 10086): ICE$(LPAREN)glue.c$(RPAREN) or wrong code on passing variable as template value parameter) +$(LI $(BUGZILLA 10094): NRVO with static array return should work) +$(LI $(BUGZILLA 10099): Diagnostic for disabled default construction should improve) +$(LI $(BUGZILLA 10113): Can't use an enum : string in a switch statement) +$(LI $(BUGZILLA 10141): wrong error message with Tuple!$(LPAREN)int$(RPAREN) : Error: static assert "Cannot put a char[] into a Appender!$(LPAREN)string$(RPAREN)") +$(LI $(BUGZILLA 10156): Can't handle usage of TypeTuple argument in templated function) +$(LI $(BUGZILLA 10196): RDMD: RDMD can't be used from MSys) +$(LI $(BUGZILLA 10198): CTFE: Wrong code for multi-dimensional block assignment) +$(LI $(BUGZILLA 10208): Module-level const/immutable variables with initialization value don't support UDAs) +$(LI $(BUGZILLA 10211): CTFE: Support casts from S** to D**, if S* -> D* is supported.) +$(LI $(BUGZILLA 10214): Incorrect "element-wise assignment is better" warning) +$(LI $(BUGZILLA 10243): [CTFE] Wrong-code on passing dereferenced array pointer by ref) +$(LI $(BUGZILLA 10244): ICE: expression.c:8364: virtual Expression* CallExp::semantic$(LPAREN)Scope*$(RPAREN): Assertion `td` failed) +$(LI $(BUGZILLA 10249): incorrect mangling for overloaded symbol) +$(LI $(BUGZILLA 10252): CTFE: Should generate error for shifts outside valid range) +$(LI $(BUGZILLA 10254): Purity correctness is broken with constructor) +$(LI $(BUGZILLA 10273): ICE$(LPAREN)ctfeexpr.c$(RPAREN): using CTFE after error in struct default values) +$(LI $(BUGZILLA 10274): DMD 2.063 produces broken binaries) +$(LI $(BUGZILLA 10275): CTFE: Allow const casts of struct literals) +$(LI $(BUGZILLA 10277): Incorrect error file and line on redeclaration of TypeInfo) +$(LI $(BUGZILLA 10279): Calling a typesafe variadic @trusted function from an @safe function results in an error.) +$(LI $(BUGZILLA 10280): CTFE: Circular variable initializers should be detected properly) +$(LI $(BUGZILLA 10283): ICE$(LPAREN)interpret.c$(RPAREN): passing struct with failed initalizer to CTFE) +$(LI $(BUGZILLA 10288): Direct lambda call and purity inference bug) +$(LI $(BUGZILLA 10289): compiler should infer nothrow even if Error is thrown) +$(LI $(BUGZILLA 10296): Nested template function call and purity inference bug) +$(LI $(BUGZILLA 10298): CTFE fails with array literal initialization) +$(LI $(BUGZILLA 10302): Package module conflicts with package name) +$(LI $(BUGZILLA 10319): @safe/pure/nothrow error should print fully qualified name) +$(LI $(BUGZILLA 10325): ddoc: template constraints inconsistently shown in generated html) +$(LI $(BUGZILLA 10327): Missing 'package.d' for DIP37 needs a better error message) +$(LI $(BUGZILLA 10341): Range case without an associated switch statement crashes DMD) +$(LI $(BUGZILLA 10343): Cannot resolve a forward reference to a template inside global typeof) +$(LI $(BUGZILLA 10344): Exiting _Dmain should flush all FILE*s and return nonzero on failure) +$(LI $(BUGZILLA 10346): No line number error with undefined template identifier) +$(LI $(BUGZILLA 10354): DIP37: ICE with using indirectly imported template through package.d) +$(LI $(BUGZILLA 10359): Pointer slicing allowed in @safe mode) +$(LI $(BUGZILLA 10381): Nonsense associative array comparison) +$(LI $(BUGZILLA 10386): Package import feature breaks with static libraries) +$(LI $(BUGZILLA 10389): Infinite recursion on printing self-referential StructLiteralExp) +$(LI $(BUGZILLA 10390): ICE on printing ClassReferenceExp) +$(LI $(BUGZILLA 10405): redundant "expression has no effect" error when returning non-void in void function) +$(LI $(BUGZILLA 10414): Delegate arguments for lazy variadic functions are only inferred in first argument) +$(LI $(BUGZILLA 10415): Bad error message with const property of const class instance) +$(LI $(BUGZILLA 10418): bad error message: "not a property") +$(LI $(BUGZILLA 10419): Unhandled exception in dmd after correct error message) +$(LI $(BUGZILLA 10421): 'package' access should work with package module) +$(LI $(BUGZILLA 10429): RDMD: --loop option doesn't work due to symbol conflict) +$(LI $(BUGZILLA 10431): ICE$(LPAREN)DMD 2.063$(RPAREN) in struct.c:741) +$(LI $(BUGZILLA 10432): RDMD: --dry-run option tries to read non-existent file) +$(LI $(BUGZILLA 10433): Array sum operation in function template) +$(LI $(BUGZILLA 10435): rdmd doesn't support the -op argument.) +$(LI $(BUGZILLA 10451): Array of pointers to opaque struct gives forward reference errors.) +$(LI $(BUGZILLA 10452): CTFE: Cannot compare delegates with == or 'is') +$(LI $(BUGZILLA 10462): interface thunk doesn't preserve EBX) +$(LI $(BUGZILLA 10479): cannot pass implicitly to base class casted result to out contract by ref) +$(LI $(BUGZILLA 10495): Incorrect "initializer required" error using lambdas in class with fields with disabled default construction) +$(LI $(BUGZILLA 10497): Opaque structs cannot be dereferenced in pointer to pointer types) +$(LI $(BUGZILLA 10504): Tuple error: no property 'offsetof' for type 'int') +$(LI $(BUGZILLA 10506): Purity should not be checked in a mixin statement) +$(LI $(BUGZILLA 10519): Stray-paren in doc-unittest code generates wrong document) +$(LI $(BUGZILLA 10526): opDispatch with IFTI should not disable UFCS) +$(LI $(BUGZILLA 10534): Addition and subtraction of delegates allowed) +$(LI $(BUGZILLA 10539): [REG][2.063] Implicit pointer to array dereference for .ptr property fails) +$(LI $(BUGZILLA 10542): implicitly generated class ctor doesnt inherit base class ctor attributes) +$(LI $(BUGZILLA 10551): [CTFE] Wrong-code on passing dereferenced array pointer by ref 2) +$(LI $(BUGZILLA 10568): CTFE rejects function pointer safety casts) +$(LI $(BUGZILLA 10583): DMD 2.063 dumps core with mixins involving __traits$(LPAREN)getProtection, ..) +$(LI $(BUGZILLA 10595): Using alias this and a hash generates wrong code) +$(LI $(BUGZILLA 10596): A method with out contract and auto return type causes segfault) +$(LI $(BUGZILLA 10597): opDollar not callable in static constext) +$(LI $(BUGZILLA 10599): CTFE: assert failure interpret.c 310) +$(LI $(BUGZILLA 10609): Refused UFCS in __traits$(LPAREN)compile$(RPAREN)) +$(LI $(BUGZILLA 10610): interpret.c:4067 Assertion Failure) +$(LI $(BUGZILLA 10618): Template instance member access disallowed in dynamic array allocation) +$(LI $(BUGZILLA 10630): Structs with disabled default construction can't be used as `out` parameters) +$(LI $(BUGZILLA 10633): Win64: wrong codegen with %=) +$(LI $(BUGZILLA 10634): Win64: wrong codegen with .init of small structs) +$(LI $(BUGZILLA 10639): Win64: wrong optimizer codegen with struct literal with complex fields) +$(LI $(BUGZILLA 10642): Win64: wrong codegen comparing different sized integer arguments) +$(LI $(BUGZILLA 10646): No front-end error for invalid casting dynamic array/static array to class reference) +$(LI $(BUGZILLA 10651): Throwing non-Throwable object causes ICE) +$(LI $(BUGZILLA 10676): excessive compilation times with optimized PIC build) +$(LI $(BUGZILLA 10677): Win64: cfloat return value not forwarded correctly as function argument) +$(LI $(BUGZILLA 10678): Win64: wrong code passing small fixed sized array as function argument) +$(LI $(BUGZILLA 10694): wrong purity check for static variables with impure destructor) +$(LI $(BUGZILLA 10695): __MODULE__ in string mixin crashes compiler) +$(LI $(BUGZILLA 10715): negated bit test $(LPAREN)bt$(RPAREN) not recognized by optimizer) +$(LI $(BUGZILLA 10735): Buffer overflow bug in symbol_generate$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 10746): Win64: corrupt debug info with very long symbols) +$(LI $(BUGZILLA 10752): accessing a private cached symbol a second time doesn't cause an error in __traits$(LPAREN)compiles, ...$(RPAREN)) +$(LI $(BUGZILLA 10758): Unsound type checking for inout.) +$(LI $(BUGZILLA 10761): DMD crashes on unspecified inout matching.) +$(LI $(BUGZILLA 10768): DMD does not show deprecation message for missing 'override' keyword) +$(LI $(BUGZILLA 10781): ctRegex! throws a huge error) +$(LI $(BUGZILLA 10783): ICE and bad diagnostics when using non-existent symbols in switch and with statements) +$(LI $(BUGZILLA 10792): Bad diagnostic on new eponymous enum template syntax) +$(LI $(BUGZILLA 10793): Forward reference errors casting from void* to opaque struct pointer) +$(LI $(BUGZILLA 10809): [REG] darwin 32 dmd release broken) +$(LI $(BUGZILLA 10811): Order dependent IFTI failure) +$(LI $(BUGZILLA 10813): ICE$(LPAREN)DMD2.063$(RPAREN) template.c:6040: Identifier* TemplateInstance::genIdent$(LPAREN)Objects*$(RPAREN): Assertion `global.errors` failed) +$(LI $(BUGZILLA 10834): cannot use cast$(LPAREN)void$(RPAREN)expr if the type of expr is a struct) +$(LI $(BUGZILLA 10840): [CTFE] *this._data.arr is not yet implemented at compile time) +$(LI $(BUGZILLA 10842): Some integer casts wrongly remove side-effect of the operand.) +$(LI $(BUGZILLA 10857): ICE$(LPAREN)glue.c, bugzilla 2962?$(RPAREN) or compiles, depending on the files order) +$(LI $(BUGZILLA 10858): CTFE wrong code for comparison of array of pointers) +$(LI $(BUGZILLA 10862): Assignment inside if condition still sometimes accepted) +$(LI $(BUGZILLA 10869): Ddoc mark methods with "const" twice) +$(LI $(BUGZILLA 10870): Ddoc adds "abstract" to interfaces) +$(LI $(BUGZILLA 10937): struct inside union gives uninitialized error in CTFE) +$(LI $(BUGZILLA 10942): ICE on 1087+ initializers $(LPAREN)Internal error: backend\cgcv.c 203$(RPAREN)) +$(LI $(BUGZILLA 10944): [ICE]$(LPAREN)interpret.c line 310$(RPAREN) with arith operation on missing variable) +$(LI $(BUGZILLA 10947): const out parameter is not properly rejected) +$(LI $(BUGZILLA 10953): Attribute inheritance needs to apply to contracts, too) +$(LI $(BUGZILLA 10968): array element copy $(LPAREN)1-N and N-N$(RPAREN) ignores postblit attributes) +$(LI $(BUGZILLA 10969): Variadic template parameter re-use in function signature) +$(LI $(BUGZILLA 10970): Segfault in a simple test compiled without -g.) +$(LI $(BUGZILLA 10980): static initialization of immutable structs with disabled postblit fails) +$(LI $(BUGZILLA 10984): Frame access diagnostic should improve) +$(LI $(BUGZILLA 10989): [CTFE] Uncaught exception messages are not pretty printed if message wasn't literal) +$(LI $(BUGZILLA 10990): Passing in a module as a mixin to __traits$(LPAREN)getUnitTests$(RPAREN) behaves differently than passing in the module directly.) +$(LI $(BUGZILLA 10992): Trait getUnitTests skips first test if aggregate contains multiple tests.) +$(LI $(BUGZILLA 10993): mangling of voldemort types with lambdas changes during return type inference) +$(LI $(BUGZILLA 10995): CTFE failures for structs with void initialized members) +$(LI $(BUGZILLA 11002): Compiler doesn't see std.sys.linux.epoll.) +$(LI $(BUGZILLA 11075): ICE$(LPAREN)struct.c$(RPAREN) after gagged error in struct field initializer) +$(LI $(BUGZILLA 11125): UFCS instantiation of template causes template constraint to be skipped) +$(LI $(BUGZILLA 11132): Odd diagnostic with C-style struct initializer when union field is present) +$(LI $(BUGZILLA 11134): Inconsistent postblit call count depends on the pointer size) +$(LI $(BUGZILLA 11136): ICE on incorrect module declaration) +$(LI $(BUGZILLA 11137): Stack overflow on invalid output path) +$(LI $(BUGZILLA 11141): Missing .pdb file with phobos64) +$(LI $(BUGZILLA 11142): Wrong error message "no size yet for forward reference" for opaque struct) +$(LI $(BUGZILLA 11144): Better diagnostic for typeid symbol) +$(LI $(BUGZILLA 11145): Duplicated deprecation message "use of typedef is deprecated;") +$(LI $(BUGZILLA 11146): Wrong line number of "identity assignment operator overload is illegal") +$(LI $(BUGZILLA 11147): Nested structs in a union are not correctly initialized) +$(LI $(BUGZILLA 11151): Undetected overlapping initialization) +$(LI $(BUGZILLA 11159): [CTFE] Integer exponentiation give incorrect values) +$(LI $(BUGZILLA 11164): wrong dependencies generated when compiling with -main) +$(LI $(BUGZILLA 11182): dmd crashes on compiling regex) +$(LI $(BUGZILLA 11187): A small transitive const bug on struct copying) +) + +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 658): struct pointers in with$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 767): compiler shall print dependencies and pragma$(LPAREN)lib$(RPAREN)) +$(LI $(BUGZILLA 5943): Power expression optimisation for 2^^unsigned) +$(LI $(BUGZILLA 8635): Allow postfix expressions for new) +$(LI $(BUGZILLA 9022): IFTI should support enclosing type/scope deduction) +$(LI $(BUGZILLA 9097): Value range propagation to disable some array bound tests) +$(LI $(BUGZILLA 9565): Index of static array should not print literal suffix) +$(LI $(BUGZILLA 10022): Importing packages) +$(LI $(BUGZILLA 10117): Support C++ class-scope static variables) +$(LI $(BUGZILLA 10236): Ddoc: Warning on wrong parameter names) +$(LI $(BUGZILLA 10334): ddoc should prefer simple syntax for template instantiations with one parameter) +$(LI $(BUGZILLA 10367): DDoc should output enum base type) +$(LI $(BUGZILLA 10688): Misleading error message when attempting a "private override") +$(LI $(BUGZILLA 10724): Allow slice of string literal to convert to const$(LPAREN)char$(RPAREN)*) +$(LI $(BUGZILLA 10991): Implement trait to get vptr index of a method.) +$(LI $(BUGZILLA 11088): Diagnostics for enum member overflows should improve) +$(LI $(BUGZILLA 11257): Allow whole implicit conversion if one or more overlapped field could.) +) + +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 10218): std.typecons.opAssign is not CTFEable) +$(LI $(BUGZILLA 10268): [REG2.063] std.typecons.Nullable!JSONValue - error instantiating) +$(LI $(BUGZILLA 10355): fullyQualifiedName doesn't work with enums) +$(LI $(BUGZILLA 10468): Regression $(LPAREN)2.063$(RPAREN): Lockstep no longer works with iota) +$(LI $(BUGZILLA 10499): [REG 2.064] retro is no longer CTFE-able) +$(LI $(BUGZILLA 10686): No [] operator overload for immutable Tuple) +$(LI $(BUGZILLA 10866): Regression $(LPAREN)2.064 git-head$(RPAREN) Massive compiler slowdown) +$(LI $(BUGZILLA 10896): currently tools/ddemangle doesn't compile on git master) +$(LI $(BUGZILLA 10906): [2.064 git-head] Out of memory compiling Phobos on Windows) +$(LI $(BUGZILLA 10913): [2.064 git-head] regex/demange compilation failure) +$(LI $(BUGZILLA 11009): Regression $(LPAREN)2.064 git-head$(RPAREN): DMD consumes huge memory when it compiles enum containing many items) +$(LI $(BUGZILLA 11057): [REG2.064dev] New std.uni has icmp$(LPAREN)$(RPAREN) partly broken) +$(LI $(BUGZILLA 11165): std.typecons._d_toObject conflicts with std.signals._d_toObject) +$(LI $(BUGZILLA 11283): [REG 2.064] assert in std/windows/syserror.d) +) + +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 2717): alloca$(LPAREN)0$(RPAREN) leaves stack unaligned on OSX) +$(LI $(BUGZILLA 4575): Uses of deprecated delete statement in D2 Phobos) +$(LI $(BUGZILLA 5224): std.algorithm.remove!$(LPAREN)SwapStrategy.unstable$(RPAREN) doesn't work) +$(LI $(BUGZILLA 5378): File.byLine terminator string) +$(LI $(BUGZILLA 5630): array$(LPAREN)$(RPAREN) of iterable of immutable items) +$(LI $(BUGZILLA 5692): Printing complex numbers with negative imaginary part) +$(LI $(BUGZILLA 5942): Bitfields are overwritten erroneously) +$(LI $(BUGZILLA 6342): Tuple field access problem in pure function) +$(LI $(BUGZILLA 6407): take$(LPAREN)map$(RPAREN) problem) +$(LI $(BUGZILLA 6686): bitmanip bitfields are broken at 64 bits) +$(LI $(BUGZILLA 6893): Write of enum member represented with ubyte or ulong) +$(LI $(BUGZILLA 7756): iota$(LPAREN)const doubles$(RPAREN) problem) +$(LI $(BUGZILLA 8124): std.net.isemail not included in phobos.lib) +$(LI $(BUGZILLA 8330): std.algorithm.find doesn't handle reference type ranges correctly) +$(LI $(BUGZILLA 8474): bitfields doesn't work with 32 bit fields) +$(LI $(BUGZILLA 8806): fullyQualifiedName!T does not work for inner types) +$(LI $(BUGZILLA 9310): escapeShellCommand unittests are never run) +$(LI $(BUGZILLA 9384): std.socket: UnixAddress broken on Linux and others) +$(LI $(BUGZILLA 9548): BigInt: Wrong comparison result: BigInt$(LPAREN)"-1"$(RPAREN) > long.min) +$(LI $(BUGZILLA 9557): std.array.array of array of immutable structs) +$(LI $(BUGZILLA 9559): Range of Nullable doesn't work with std.array.array) +$(LI $(BUGZILLA 9579): std.regex.replace format argument should not require same constness as target string) +$(LI $(BUGZILLA 9599): File.byLine doesn't function properly with take) +$(LI $(BUGZILLA 9607): std.random.randomShuffle and partialShuffle don't work with Xorshift) +$(LI $(BUGZILLA 9629): toUpperInPlace doesn't work properly with unicode characters) +$(LI $(BUGZILLA 9725): std.string.format does wasteful UTF decoding) +$(LI $(BUGZILLA 9824): Emplace is broken) +$(LI $(BUGZILLA 9967): ParameterIdentifierTuple broken for setters) +$(LI $(BUGZILLA 10017): Can not assign to a Variant another Variant holding a bigger structure) +$(LI $(BUGZILLA 10078): std.string.indexOf$(LPAREN)Char[], dchar, CaseSensitive$(RPAREN) fails at compile time) +$(LI $(BUGZILLA 10130): map of iota with const step) +$(LI $(BUGZILLA 10161): std.datetime unittest failure "Libya Standard Time") +$(LI $(BUGZILLA 10188): Wrong Document Comment on std.format.d$(LPAREN)176$(RPAREN)) +$(LI $(BUGZILLA 10216): Bad warning in std.process.kill) +$(LI $(BUGZILLA 10265): RandomSample fails when passed an InputRange as input) +$(LI $(BUGZILLA 10269): RandomSample should use popFrontExactly, not popFrontN, when skipping across input range) +$(LI $(BUGZILLA 10322): std.random.RandomSample.index$(LPAREN)$(RPAREN) returns wrong value if called before front$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 10347): buildPath returns relative path when joining absolute with relative path) +$(LI $(BUGZILLA 10348): isRooted is either wrong or poorly specified) +$(LI $(BUGZILLA 10377): std.typecons.wrap doesn't consider private members) +$(LI $(BUGZILLA 10408): Two-function std.algorithm.reduce of a const array) +$(LI $(BUGZILLA 10426): Improve code coverage of std.random unittests) +$(LI $(BUGZILLA 10463): dirEntries$(LPAREN)$(RPAREN) segfaults on paths the user does not have access to) +$(LI $(BUGZILLA 10469): WinAPI declarations in std.process should be moved to core.sys.windows.windows) +$(LI $(BUGZILLA 10474): When takeExactly returns a new range type, it fails to propagate all relevant attributes) +$(LI $(BUGZILLA 10510): enforce can't take an extern$(LPAREN)C$(RPAREN) function to call) +$(LI $(BUGZILLA 10517): readln$(LPAREN)Char$(RPAREN)$(LPAREN)Char[] buf$(RPAREN) accepts non-mutable buffers) +$(LI $(BUGZILLA 10536): std.typecons.wrap doesn't work with a class that defines opCast) +$(LI $(BUGZILLA 10543): std.algorithm.map incorrectly uses source range length for narrow strings) +$(LI $(BUGZILLA 10550): Xorshift32 and Xorshift160 do not generate uniformly-distributed random numbers) +$(LI $(BUGZILLA 10570): Example of `how` function for AutoImplement should work for non-abstract class) +$(LI $(BUGZILLA 10601): std.path.setExtension leaves trailing dot if extension is empty) +$(LI $(BUGZILLA 10607): DirEntry has no constructor) +$(LI $(BUGZILLA 10608): std.typecons.RefCounted has very poor diagnostics) +$(LI $(BUGZILLA 10644): Win64: wrong code when passing arguments through ...) +$(LI $(BUGZILLA 10647): AutoImplement should implement overridden member functions with 'override' attributes) +$(LI $(BUGZILLA 10660): ddoc on std.algorithm: Cheat sheet description for 'filter' is wrong) +$(LI $(BUGZILLA 10680): BigInt uses deprecated std.traits.unsigned) +$(LI $(BUGZILLA 10732): Example code for std.utf.toUTFindex does not work) +$(LI $(BUGZILLA 10773): std.algorithm.splitter produces infinite range with empty delimiter) +$(LI $(BUGZILLA 10796): std.regex: ctRegex bug with '.' and $ in multi-line mode) +$(LI $(BUGZILLA 10797): std.regex: ctRegex "codegen" bug with certain nested infinite loops) +$(LI $(BUGZILLA 10799): std.regex: ctRegex lookahead support) +$(LI $(BUGZILLA 10800): ParameterDefaultValueTuple returns an empty string for default values in property functions.) +$(LI $(BUGZILLA 10801): std.regex: support for lookbehind in ctRegex) +$(LI $(BUGZILLA 10802): std.regex: ctRegex fails to compile with backreference) +$(LI $(BUGZILLA 10874): std.conv.to should support conversion from ulong to int-based enum) +$(LI $(BUGZILLA 10893): Numerous DDoc parameter warnings in Phobos $(LPAREN)as found by 10236$(RPAREN)) +$(LI $(BUGZILLA 10898): LockingTextWriter segfaults in .init state) +$(LI $(BUGZILLA 10951): EnumMembers should document about returning duplicate members) +$(LI $(BUGZILLA 11068): raw formatting of chars and strings is wrong) +$(LI $(BUGZILLA 11089): std.string.toUpper doesn't work with 1:m mappings) +$(LI $(BUGZILLA 11152): formatChar doesn't handle `\0`) +$(LI $(BUGZILLA 11160): Bitfield compilation error with degenerate bitfields of length 32 $(AMP) 64) +$(LI $(BUGZILLA 11194): std.container.Array.reserve calls opAssign on uninitialized data) +$(LI $(BUGZILLA 11222): std.string.isNumeric accepts a "+") +$(LI $(BUGZILLA 11232): Windows sysErrorString only supports ASCII) +) + +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 4120): bigint implicit cast too bool) +$(LI $(BUGZILLA 4124): toString$(LPAREN)$(RPAREN) for BitArray) +$(LI $(BUGZILLA 4850): std.conv.to isn't pure) +$(LI $(BUGZILLA 6154): std.math.abs on std.complex numbers too) +$(LI $(BUGZILLA 6381): math.floor, math.ceil are not pure functions.) +$(LI $(BUGZILLA 6626): std.complex.expi$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 9699): strip functions should have stripLeft/stripRight counterparts and be generic) +$(LI $(BUGZILLA 10092): Renaming std.range.chunks as std.range.chunked) +$(LI $(BUGZILLA 10314): Add std.traits.signed) +$(LI $(BUGZILLA 10538): std.typecons.wrap should consider opDispatch) +$(LI $(BUGZILLA 10621): dirEntry is $(LPAREN)now$(RPAREN) useless) +$(LI $(BUGZILLA 10717): std.ascii.toLower and toUpper should return char instead of dchar and avoid me to use a bad cast$(LPAREN)char$(RPAREN)) +$(LI $(BUGZILLA 10868): std.string.translate should take an optional buffer) +$(LI $(BUGZILLA 10881): Support %f formatting for a std.complex.complex) +$(LI $(BUGZILLA 10909): std.conv.to!$(LPAREN)bool$(RPAREN)$(LPAREN)int$(RPAREN): conversion from integer to bool) +$(LI $(BUGZILLA 11020): Add function for getting the current executable path) +$(LI $(BUGZILLA 11123): std.getopt should support functions) +) + +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 10976): thread_joinAll after main exit performed too late) +) + +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 6210): Associative array with array key often cannot be equated.) +$(LI $(BUGZILLA 6372): data loss due to possible bug in garbage collector) +$(LI $(BUGZILLA 7741): getHash inconsistent for const$(LPAREN)char$(RPAREN)[] vs. char[] and string) +$(LI $(BUGZILLA 8435): BigInts don't work well in associative arrays) +$(LI $(BUGZILLA 9783): profiling recursive function calls yields bad tree timing) +$(LI $(BUGZILLA 9852): Empty associative array crashes program) +$(LI $(BUGZILLA 10027): demangled name format of local function is wrong) +$(LI $(BUGZILLA 10118): BigInt as associative array key wrong behavior) +$(LI $(BUGZILLA 10323): getAMDcacheinfo needlessly allocates) +$(LI $(BUGZILLA 10420): Incorrect function attributes in `core.exception`) +$(LI $(BUGZILLA 10436): The runtime should print stack traces to stderr $(LPAREN)like on *nix$(RPAREN), not stdout) +$(LI $(BUGZILLA 10457): _d_toObject might fail with shared libraries) +$(LI $(BUGZILLA 10593): array's reserve/capacity go haywire if length has been changed prior) +$(LI $(BUGZILLA 10711): shared phobos library should not depend on _Dmain) +$(LI $(BUGZILLA 10720): ICE with is$(LPAREN)aaOfNonCopyableStruct.nonExistingField$(RPAREN)) +$(LI $(BUGZILLA 10894): Numerous DDoc parameter warnings in druntime $(LPAREN)as found by 10236$(RPAREN)) +) + +$(BUGSTITLE Druntime enhancements, + +$(LI $(BUGZILLA 9190): Vector operations are not optimized for x86_64 architecture) +) + +$(BUGSTITLE Installer bugs, + +$(LI $(BUGZILLA 10062): installers should use CDN) +) + +$(BUGSTITLE Website bugs, + +$(LI $(BUGZILLA 9533): CHM generation crashes) +$(LI $(BUGZILLA 10031): Link to old wiki on dlang.org) +$(LI $(BUGZILLA 10230): Duplicated buttons for runnable examples) +$(LI $(BUGZILLA 10410): Improve cast$(LPAREN)void$(RPAREN) documentation) +$(LI $(BUGZILLA 10461): Incorrect example of "depend on order of evaluation" expression) +$(LI $(BUGZILLA 10565): Level-5 titles are missing in Language reference) +$(LI $(BUGZILLA 10605): Lambda grammar is not sufficient) +$(LI $(BUGZILLA 10885): [std.range] refRange is missing from module description tables) +$(LI $(BUGZILLA 11001): Need documentation for __traits$(LPAREN)getVirtualIndex$(RPAREN)) +$(LI $(BUGZILLA 11036): Document that .stringof should not be used for code generation) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.064 + TITLE=Change Log: $(VER) diff --git a/changelog/2.065.0.dd b/changelog/2.065.0.dd new file mode 100644 index 0000000000..c5a3327a42 --- /dev/null +++ b/changelog/2.065.0.dd @@ -0,0 +1,951 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION February 24, 2014, =================================================, + +$(BUGSTITLE Compiler Changes, +$(LI $(RELATIVE_LINK2 d-scripts, Extensionless D source file names can now be run when using the -run switch.)) +) + +$(BUGSTITLE Language Changes, +$(LI $(RELATIVE_LINK2 disable-goto-skips-init, Goto jumps now cannot skip variable declarations.)) +$(LI $(RELATIVE_LINK2 attribinference2, All instantiated functions now infer their attributes.)) +$(LI $(RELATIVE_LINK2 inout-const, Add a new type qualifier $(D inout const).)) +$(LI $(RELATIVE_LINK2 slicing-tuple, Entire slicing operation of built-in tuple is now accepted.)) +$(LI $(RELATIVE_LINK2 untyped-packages, Packages and module names now have no type.)) +$(LI $(RELATIVE_LINK2 staticfields2, Const and immutable fields with initializers are now deprecated.)) +$(LI $(RELATIVE_LINK2 deprecate-unorderd-compares, Deprecate unordered floating point comparisons.)) +$(LI $(RELATIVE_LINK2 deprecate-floating-properties, Deprecate $(D .min) property for floating-point types.)) +$(LI $(RELATIVE_LINK2 ctfe-overlapped-field, CTFE can handle overlapped union fields.)) +$(LI $(RELATIVE_LINK2 get-alias-this, Add a new trait getAliasThis.)) +$(LI $(RELATIVE_LINK2 mixing-struct-opcall, Mixing struct constructors and static opCall is no longer allowed.)) +) + +$(BUGSTITLE Library Changes, +$(LI $(RELATIVE_LINK2 algorithm-pred, Many functions in std.algorithm can now be used as predicates to other functions.)) +$(LI $(RELATIVE_LINK2 algorithm-all, Allow std.algorithm.all to be used without a predicate.)) +$(LI $(RELATIVE_LINK2 uni-bygrapheme, Add std.uni.byGrapheme and std.uni.byCodePoint.)) +$(LI $(RELATIVE_LINK2 range-only, Add support for any number of arguments to std.range.only.)) +) + +$(BUGSTITLE Linker Changes, +$(LI $(RELATIVE_LINK2 large-address-aware, Added /LARGEADDRESSAWARE to the Win32 Optlink linker.)) +) + +$(BR)$(BIG $(RELATIVE_LINK2 list2065, List of all bug fixes and enhancements in D 2.065.)) + +$(HR) + +$(BUGSTITLE Compiler Changes, + +$(LI $(LEGACY_LNAME2 d_scripts, d-scripts, Extensionless D source file names can now be run when using the -run switch:) + + $(P On Posix systems it is frequently useful to have a shebang line at the start of an extensionless file, + which marks the tool used to compile the script. It's now possible to use this technique with D, e.g. + the following is a D source file with the file name $(B "my-script"): + + --------- + #!rdmd + + void main() + { + } + --------- + ) + + $(P $(B Note:) This does not allow an arbitrary extension, as D source files need to be proper D identifiers.) + $(P $(B Note:) This feature is not available on Windows, as Windows does not have extensionless executable files.) + $(P $(B Note:) When compiling, and in order to avoid the default behavior of generating + an extensionless executable + which would overwrite the source file, the compiler will generate $(I "a.out") instead. + ) +) + +) + +$(BUGSTITLE Language Changes, + +$(LI $(LEGACY_LNAME2 disable_goto_skips_init, disable-goto-skips-init, Goto jumps now cannot skip variable declarations:) + + $(P For a very long period, the following code had been allowed by mistake, but it is prohibited now: + + --------- + import std.stdio; + + void main() + { + goto Label; // Error: goto skips declaration of variable v + + int v = 42; + + Label: + writeln(v); + } + --------- + ) +) + +$(LI $(LNAME2 attribinference2, All instantiated functions now infer their attributes:) + + $(P Regardless of how directly or indirectly a function is instantiated, its attributes will still be inferred: + + --------- + struct S(T) + { + T square(T x) + { + T calc() + { + return x * x; + } + return calc(); + } + + static double pi() { return 3.141592; } + } + + void main() pure @safe nothrow + { + S!int s; + + // S!int.square and its nested function calc are instantiated functions, so + // their attributes are inferred as pure and callable from main() + assert(s.square(2) == 4); // ok + + // static member function attributes are also inferred now + auto pi = typeof(s).pi(); + } + --------- + ) +) + +$(LI $(LEGACY_LNAME2 inout_const, inout-const, Add a new type qualifier $(D inout const):) + + $(P Until now, the common type of $(D immutable$(LPAREN)T$(RPAREN)) and $(D inout$(LPAREN)T$(RPAREN)) had been + $(D const$(LPAREN)T$(RPAREN)). But that loses the $(D inout) information, which might then refuse some valid code. + Now the type becomes $(D inout$(LPAREN)const$(LPAREN)T$(RPAREN)$(RPAREN)), which meaningfully propagates the appropriate type qualifier. + + --------- + inout(const(int))[] foo(bool condition, inout(int)[] x, immutable(int)[] y) + { + static assert(is(typeof(condition ? x : y) == inout(const(int))[])); + return condition ? x : y; + } + + void main() + { + int[] marr = [1,2,3]; + const(int)[] carr = [4,5,6]; + immutable(int)[] iarr = [7,8,9]; + + // inout(const(int))[] can go back to const(int)[] or immutable(int)[]. + static assert(is(typeof(foo(true, marr, iarr)) == const(int)[])); + static assert(is(typeof(foo(true, carr, iarr)) == const(int)[])); + static assert(is(typeof(foo(true, iarr, iarr)) == immutable(int)[])); + } + --------- + ) +) + +$(LI $(LEGACY_LNAME2 slicing_tuple, slicing-tuple, Entire slicing operation of built-in tuple is now accepted:) + + $(P $(BUGZILLA 8244): cannot slice a type tuple with '[]' in locations where a type is valid: + + --------- + import std.typetuple; + alias Types = TypeTuple!(int, double, string); + + // Was error in 2.064, but allowed from 2.065. + alias Types2 = Types[]; + static assert(is(Types == Types2)); + --------- + ) +) + +$(LI $(LEGACY_LNAME2 untyped_packages, untyped-packages, Packages and module names now have no type:) + + $(P $(BUGZILLA 9081): Modules shouldn't have a type + + --------- + import std.stdio; + + // Both had printed 'void' in 2.064. + // From 2.065, both will cause "has no type" error. + pragma(msg, typeof(std)); + pragma(msg, typeof(std.stdio)); + --------- + ) + + $(P By the change, an idiom that used to work + $(D is$(LPAREN)typeof$(LPAREN)package_or_module_name$(RPAREN)$(RPAREN)) + is changed to not work. Instead use: $(D __traits$(LPAREN)compiles, package_or_module_name$(RPAREN)). + ) +) + +$(LI $(LNAME2 staticfields2, Const and immutable fields with initializers are now deprecated:) + + $(P Eventually, they will be changed to occupy space in the object. Such fields should now be changed to enum or static. + See also $(RELATIVE_LINK2 staticfields, the release note in 2.063). + ) + + $(P Related to that, void-initialized const or immutable fields will now + occupy space in the object instance ahead of schedule: + + --------- + struct S + { + const int[1000] x = void; + + this(int n) + { + // Was disallowed in 2.064. + // From 2.065 x is a field of runtime object. + x[] = n; + } + } + + // S.sizeof had been 1 in 2.064. + // From 2.065, field s.x occupies space in the object. + static assert(S.sizeof == int.sizeof * 1000); + + void main() + { + S s = S(3); + + foreach (e; s.x) + { + assert(e == 3); // OK + } + } + --------- + ) +) + +$(LI $(LEGACY_LNAME2 deprecate_unorderd_compares, deprecate-unorderd-compares, Deprecate unordered floating point comparisons:) + + $(P $(BUGZILLA 10369): Deprecate unordered floating point comparisons + ) +) + +$(LI $(LEGACY_LNAME2 deprecate_floating_properties, deprecate-floating-properties, Deprecate $(D .min) property for floating-point types:) + + $(P $(BUGZILLA 10439): Deprecate float.min, double.min, real.min + ) +) + +$(LI $(LEGACY_LNAME2 ctfe_overlapped_field, ctfe-overlapped-field, CTFE can handle overlapped union fields:) + + $(P Example code: + + --------- + union U + { + size_t x; + int* y; + } + + bool test() + { + U u; + assert(u.x == 0); + // In here, reading u.y will cause CTFE error. + + u.y = [1,2,3].ptr; + // Writing value to overlapped field u.y will make corresponding field u.x invalid. + + assert(u.y[0..3] == [1,2,3]); + // u.y holds valid field and reading it is allowed + // In here, reading u.x will cause CTFE error. + + u.x = 10; + // Set value to u.x again. + assert(u.x == 10); // OK + // In here, reading u.y will cause CTFE error. + + return true; + } + static assert(test()); // run CTFE + --------- + ) + + $(P Bit image reinterpretation by using two overlapped union fields is not allowed during CTFE. + ) +) + +$(LI $(LEGACY_LNAME2 get_alias_this, get-alias-this, Add a new trait getAliasThis:) + + $(P The new $(B getAliasThis) trait will return a tuple of field names which are marked as the + $(LINK2 $(ROOT_DIR)spec/class.html#AliasThis, subtypes) of an aggregate type. + For example: + + --------- + struct S + { + string var; + alias var this; + } + + static assert(__traits(getAliasThis, S)[0] == "var"); + --------- + ) + + $(P $(B Note:) Multiple subtyping is not yet implemented in D, therefore this trait will always + return a tuple of length 1. + ) +) + +$(LI $(LNAME2 mixing-struct-opcall, Mixing struct constructors and static opCall is no longer allowed): + $(P This was not implemented correctly and caused ambiguities.) + $(P + Example: + --- + struct S + { + this(int i) {} + + static S opCall() // disallowed due to constructor + { + return S.init; + } + } + --- + ) + $(P Note: $(D static opCall) can be used to simulate struct + constructors with no arguments, but this is not recommended + practice. Instead, the preferred solution is to use a factory + function to create struct instances. + ) +) + +) + +$(BUGSTITLE Library Changes, + +$(LI $(LEGACY_LNAME2 algorithm_pred, algorithm-pred, Many functions in std.algorithm can now be used as predicates to other functions:) + + $(P Functions such as $(REF_SHORT any, std,algorithm), $(REF_SHORT all, std,algorithm), $(REF_SHORT canFind, std,algorithm) + and $(REF_SHORT equal, std,algorithm) are now templates, which allows them to be used as predicates to + other templates, as well as allowing the user to alias an instantiation of any such templates. + For an example of how this allows terser syntax in user-code, in the following example the + programmer wants to check whether all the strings in a string array have at least one ASCII digit: + + --------- + import std.algorithm : all; + import std.ascii : isDigit; + + void main() + { + string[] inputs = ["foo1", "bar2"]; + + bool allContainDigit; + foreach (input; inputs) + { + if (!any!isDigit(input)) // none of the characters are ASCII digits + { + allContainDigit = false; + break; + } + } + } + --------- + ) + + $(P But it is now simpler to use the $(D any) template itself as a predicate. + We can make it a predicate to another useful template, the $(D all) template: + + --------- + import std.algorithm : any, all; + import std.ascii : isDigit; + + void main() + { + string[] inputs = ["foo1", "bar2"]; + bool allContainDigit = all!(any!isDigit)(inputs); + } + --------- + ) + + $(P In addition to allowing these functions to become predicates they can now also be aliased, + which allow you to make your functions simpler to understand: + + --------- + import std.algorithm : any, all; + import std.ascii : isDigit; + + void main() + { + alias isAnyDigit = any!isDigit; // less visual noise and a self-describing function + + string[] inputs = ["foo1", "bar2"]; + bool allContainDigit = all!isAnyDigit(inputs); // easier to understand + + alias doAllContainDigits = all!isAnyDigit; // or wrap the entire algorithm into one symbol! + + assert( doAllContainDigits(["1", "a 1", "b 2"])); // self-describing code + assert(!doAllContainDigits(["c", "a 1", "b 2"])); + } + --------- + ) + + $(P You can of course combine $(D all) and $(D any) in a number of combinations. For example, + if you want to reverse the test and instead check whether $(B any) of the strings in the + string array contain $(B all) digits, the code might look like the following: + + --------- + import std.algorithm : any, all; + import std.ascii : isDigit; + + void main() + { + alias areAllDigits = all!isDigit; + + alias areAnyIntegrals = any!areAllDigits; + + assert( areAnyIntegrals(["123", "456"])); + assert( areAnyIntegrals(["abc", "123"])); // "123" is a number + assert(!areAnyIntegrals(["abc", "def123"])); // "def123" is not really a number + } + --------- + ) + + $(P If on the other hand you want to ensure that $(B all) strings in the string array contain + $(B all) digits, the could might look like the following: + + --------- + import std.algorithm : any, all; + import std.ascii : isDigit; + + void main() + { + alias areAllDigits = all!isDigit; + + alias allStringsDigits = all!areAllDigits; + + assert( allStringsDigits(["123", "456"])); + assert(!allStringsDigits(["abc", "123"])); // "123" is a number, but "abc" is not + } + --------- + ) +) + +$(LI $(LEGACY_LNAME2 algorithm_all, algorithm-all, Allow std.algorithm.all to be used without a predicate.) + + $(P You no longer need to pass a predicate if you want to match all items in a range which + implicitly convert to $(D true): + + --------- + import std.algorithm; + + void main() + { + auto arr1 = [true, true, true]; + assert( all(arr1)); // all values are true + + auto arr2 = [false, true, true]; + assert(!all(arr2)); // all values are not true + + auto arr3 = [1, 2, 3]; + assert( all(arr3)); // all values convert to true + + auto arr4 = [0, 2, 3]; + assert(!all(arr4)); // all values do not convert to true + } + --------- + ) +) + +$(LI $(LEGACY_LNAME2 uni_bygrapheme, uni-bygrapheme, Add std.uni.byGrapheme and std.uni.byCodePoint.) + + $(P Complementary higher-order ranges which enable range operations on graphemes: + --------- + import std.array : array; + import std.range : retro; + import std.string : text; + import std.uni : byCodePoint, byGrapheme; + + void main() + { + string s = "noe\u0308l"; // noël + // reverse it and convert the result back to UTF-8 + string reverse = s.byGrapheme() + .array() // Note: byGrapheme will support bidirectionality in the future + .retro() + .byCodePoint() + .text(); + + assert(reverse == "le\u0308on"); // lëon + } + --------- + Note that $(D byGrapheme) will support bidirectionality in the future, + obviating the need for $(D array) in the above example. + ) +) + +$(LI $(LEGACY_LNAME2 range_only, range-only, Add support for any number of arguments to std.range.only.) + + $(P $(REF_SHORT only, std,range) can now be used with more than one argument: + --------- + import std.algorithm : joiner; + import std.range : equal, only; + + void main() + { + assert(only("one", "two", "three").joiner(" ").equal("one two three")); + } + --------- + ) + + $(P Additionally, $(D only()) is now a way to get an empty range.) +) + +) + +$(BUGSTITLE Linker Changes, + +$(LI $(LEGACY_LNAME2 large_address_aware, large-address-aware, Added /LARGEADDRESSAWARE to the Win32 Optlink linker.) + + $(P When using the default Optlink linker on win32 (for linking 32-bit object files and executables), + the $(B /LARGEADDRESSAWARE) option tells the linker that the application can handle addresses + larger than 2 gigabytes. This is equivalent to Visual C's + $(LINK2 https://msdn.microsoft.com/en-us/library/wz223b1z.aspx, linker option) of the same name since + this is an operating-system feature that is enabled by setting a specific flag in the executable. + ) +) + +) + +$(BR)$(BIG $(LNAME2 list2065, List of all bug fixes and enhancements in D 2.065:)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 7782): [ICE] With wrong import syntax) +$(LI $(BUGZILLA 9107): Value Range Analysis with uint and byte) +$(LI $(BUGZILLA 9639): Recursive template instanciation segfault dmd) +$(LI $(BUGZILLA 11078): Diagnostic for wrong RHS in property assign of a property group should improve) +$(LI $(BUGZILLA 11321): Can't link _D6object15__T7reserveTyaZ7reserveFNaNbNeKAyamZm) +$(LI $(BUGZILLA 11441): DMD halts compilation at semantic3) +$(LI $(BUGZILLA 11447): Closure provide bogus values) +$(LI $(BUGZILLA 11472): REGRESSION$(LPAREN)2.064$(RPAREN): dmd segfaults on wrong code instead of giving error) +$(LI $(BUGZILLA 11487): dmd segfaults on writefln in nested template) +$(LI $(BUGZILLA 11504): [CTFE] JSONValue cannot make in CTFE) +$(LI $(BUGZILLA 11505): Bad error message: "opAssign [...] is annotated with @disable") +$(LI $(BUGZILLA 11508): [REG 2.064] Wrong code with -O on x86_64 for char comparisons) +$(LI $(BUGZILLA 11513): [REG 2.064] Assertion in module.c) +$(LI $(BUGZILLA 11525): REG$(LPAREN)2.065$(RPAREN): Error: 'a[] *= a[]' each element is not a scalar, it is a Complex!double) +$(LI $(BUGZILLA 11553): dmd segfault with recursive template) +$(LI $(BUGZILLA 11554): `is$(LPAREN)T == enum$(RPAREN);` produces an error if T is an enum defined with no members) +$(LI $(BUGZILLA 11563): Module dependency cycle causes unrelated template instantiations to fail) +$(LI $(BUGZILLA 11566): ICE with invalid array op) +$(LI $(BUGZILLA 11596): Internal error: backend/cgcs.c 351) +$(LI $(BUGZILLA 11610): Compiler core dumps on FreeBSD, compiles forever on Linux) +$(LI $(BUGZILLA 11614): Error: this for _expand_field_0 needs to be type Tuple not type Foo) +$(LI $(BUGZILLA 11626): [ICE] $(LPAREN)mtype.c line 9718$(RPAREN) With missing in ref type) +$(LI $(BUGZILLA 11659): false positive goto skips initialization of variable error $(LPAREN)skipping enum initialization$(RPAREN)) +$(LI $(BUGZILLA 11718): [REG2.065a] Unintended mangled names conflict of nested template structs) +$(LI $(BUGZILLA 11723): Too many "integer overflow" errors) +$(LI $(BUGZILLA 11730): associative array with Nullable!SysTime values: Called `get` on null Nullable!SysTime.) +$(LI $(BUGZILLA 11751): [REG2.065a] Hex float exponents should be decimal) +$(LI $(BUGZILLA 11755): Operator $(LESS)$(GREATER)= and !$(LESS)$(GREATER)= with arrays make internal error in e2ir) +$(LI $(BUGZILLA 11767): doubly mixed-in struct "failed semantic analysis") +$(LI $(BUGZILLA 11776): [ICE] Assertion failure: 'tf->next == NULL' on line 119 in file 'mangle.c') +$(LI $(BUGZILLA 11777): [ICE] dmd memory corruption as `Scope::pop` `free`s `fieldinit` used also in `enclosing`) +$(LI $(BUGZILLA 11805): Removal of Bool has critically broken expression evaluation) +$(LI $(BUGZILLA 11818): Ternary operator not allowed in a value parameter anymore) +$(LI $(BUGZILLA 11822): `-de` switch causees ICE with `auto` return and other stuff) +$(LI $(BUGZILLA 11824): A stack variable escaping problem in CTFE Phobos code) +$(LI $(BUGZILLA 11844): ICE$(LPAREN)template.c:6643$(RPAREN) Assertion failed: $(LPAREN)td->semanticRun != PASSinit$(RPAREN)) +$(LI $(BUGZILLA 11849): Recursive enum causes segfault) +$(LI $(BUGZILLA 11850): [ICE] Problem with filter with signed-unsigned array comparison) +$(LI $(BUGZILLA 11852): RDMD broken on the Github HEAD) +$(LI $(BUGZILLA 11854): Git-head does not build with Visual Studio) +$(LI $(BUGZILLA 11863): std.conv.to!string$(LPAREN)int/uint, radix$(RPAREN) returns incorrect string) +$(LI $(BUGZILLA 11868): ICE$(LPAREN)template.c$(RPAREN) on passing `inout const` argument as TemplateTupleParameter) +$(LI $(BUGZILLA 11896): [REG2.066a] isVirtualMethod related GitHub HEAD regression $(LPAREN)works with 2.064$(RPAREN)) +$(LI $(BUGZILLA 11914): Missed tuple unpacking in foreach for cartesianProduct) +$(LI $(BUGZILLA 11919): GitHub HEAD regression for getAttributes trait $(LPAREN)DMD CORE DUMP$(RPAREN)) +$(LI $(BUGZILLA 11922): [REG2.065a] ICE on nonexistent identifier in templated auto method) +$(LI $(BUGZILLA 11924): inout Variadic Template Parameters) +$(LI $(BUGZILLA 11925): [2.065] [REGRESSION] ICE in CompoundStatement::semantic) +$(LI $(BUGZILLA 11930): Github regression -- Alias this not considered in is$(LPAREN)T unused: U$(RPAREN) matching) +$(LI $(BUGZILLA 11931): Linkers "Symbol Undefined" again with dmd HEAD when -g specified) +$(LI $(BUGZILLA 11941): Errors when appending to aggregate member array in CTFE) +$(LI $(BUGZILLA 11956): dmd doesn't lookup /etc/dmd.conf) +$(LI $(BUGZILLA 11963): Regression$(LPAREN)2.065$(RPAREN) ICE$(LPAREN)parse.c$(RPAREN) Parser crash) +$(LI $(BUGZILLA 11965): Regression$(LPAREN)2.064$(RPAREN) Segfault on garbage) +$(LI $(BUGZILLA 11966): Regression 2.065.b1: inout$(LPAREN)const$(LPAREN)char$(RPAREN)$(RPAREN)[] doesn't convert to inout$(LPAREN)char$(RPAREN)[]) +$(LI $(BUGZILLA 11967): Regression$(LPAREN)2.065$(RPAREN) ICE$(LPAREN)parse.c$(RPAREN) Parser crash) +$(LI $(BUGZILLA 11980): startaddress pragma broken $(LPAREN)DMD 2.061 regression$(RPAREN)) +$(LI $(BUGZILLA 11993): [REG] typeof$(LPAREN)this$(RPAREN) in constraint of member function template should reflect method qualifier) +$(LI $(BUGZILLA 12002): Internal error: toir.c 181) +$(LI $(BUGZILLA 12008): alias this and "unable to resolve forward reference" error) +$(LI $(BUGZILLA 12010): [REG DMD2.065-b1] Undefined template symbols for static library linked with debug symbols) +$(LI $(BUGZILLA 12016): implicit immutable upcast becomes null in CTFE) +$(LI $(BUGZILLA 12017): DDoc leaves out the majority of documentation) +$(LI $(BUGZILLA 12023): Regression 2.065-b2: template mixin fails within template class) +$(LI $(BUGZILLA 12037): Link-failure with std.numeric.CustomFloat) +$(LI $(BUGZILLA 12044): Invalid code gen causes segfault) +$(LI $(BUGZILLA 12047): Regression $(LPAREN)2.065 git-head$(RPAREN): UDAs are not checked) +$(LI $(BUGZILLA 12070): Variant opCall not static) +$(LI $(BUGZILLA 12079): Internal error: backend/cod4.c 358 for associative array access) +$(LI $(BUGZILLA 12080): Internal error: backend/symbol.c 1035 for invariant) +$(LI $(BUGZILLA 12089): std.utf.validate and inout$(LPAREN)char[]$(RPAREN) failts to compile) +$(LI $(BUGZILLA 12144): [REG DMD2.064] Unresolved xopEquals when referenced by dynamic array constructor) +$(LI $(BUGZILLA 12158): ICE with .init of nonexisting selective import) +$(LI $(BUGZILLA 12160): UDA related regressions) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 235): goto $(AMP) scope: cannot goto forward into different try block level) +$(LI $(BUGZILLA 275): Undefined identifier in instances of templates with forward mixins) +$(LI $(BUGZILLA 602): Compiler allows a goto statement to skip an initalization) +$(LI $(BUGZILLA 899): structure field .offsetof property inaccessible in the scope) +$(LI $(BUGZILLA 900): changing import order causes type mismatch) +$(LI $(BUGZILLA 918): $(LPAREN)D1 only$(RPAREN): Template order matter, version block change something with typedef, and another template bug.) +$(LI $(BUGZILLA 1687): "extern $(LPAREN)C++$(RPAREN) interface" and vtbl) +$(LI $(BUGZILLA 1748): Wrong stringof for templated classes) +$(LI $(BUGZILLA 2481): mixing field into anonymous struct inside class generates field overlapping vtable) +$(LI $(BUGZILLA 2806): enum member cannot be forward referenced) +$(LI $(BUGZILLA 2885): Silent forward reference bug using ReturnType) +$(LI $(BUGZILLA 3013): Duplicate error message on calling a function with a type) +$(LI $(BUGZILLA 3107): [meta] Property syntax) +$(LI $(BUGZILLA 3226): -fPIC flag doesn't seem to work) +$(LI $(BUGZILLA 3279): $(LPAREN)D1 only$(RPAREN) Confusing error message when comparing types) +$(LI $(BUGZILLA 3307): Template alias default parameters aren't resolved properly) +$(LI $(BUGZILLA 3753): ICE$(LPAREN)eh.c$(RPAREN): Related to exception handling and alloca.) +$(LI $(BUGZILLA 3817): Array op: wrong error message) +$(LI $(BUGZILLA 3834): forward reference in templated class) +$(LI $(BUGZILLA 3903): Traits compiles as true for an array sum with wrong syntax) +$(LI $(BUGZILLA 3970): Problem with cast -1.0L ==> uint/ulong) +$(LI $(BUGZILLA 3991): Void initializers in unions considered overlapping) +$(LI $(BUGZILLA 4145): cross alias namespace can't be resolve) +$(LI $(BUGZILLA 4162): pass by alias offset problems) +$(LI $(BUGZILLA 4983): [ICE] Stack overflow while initializing struct member with address of one of its methods) +$(LI $(BUGZILLA 5569): 64 bit Dwarf symbolic debug info not recognized by gdb) +$(LI $(BUGZILLA 5878): Forward reference in returning superclass from template using is$(LPAREN)$(RPAREN) expression $(LPAREN)Breaks std.traits.BaseTypeTuple$(RPAREN)) +$(LI $(BUGZILLA 6010): -fPIC is broken on freebsd/64) +$(LI $(BUGZILLA 6382): edge case with static foreach) +$(LI $(BUGZILLA 6439): [CTFE] union fields are initialized independently) +$(LI $(BUGZILLA 6764): IFTI fails on typesafe variadic function over static array with non IntegerLiteral length) +$(LI $(BUGZILLA 6796): Several __error with wrong enum definition) +$(LI $(BUGZILLA 7077): $(LPAREN)D1 only$(RPAREN) mixin statements can invade the enclosing scope) +$(LI $(BUGZILLA 7175): Zero-length static array .ptr is always null) +$(LI $(BUGZILLA 7472): Cast from class to basic type not rejected during semantic) +$(LI $(BUGZILLA 7645): ICE$(LPAREN)e2ir.c$(RPAREN) nested classes) +$(LI $(BUGZILLA 7744): Forward reference in string mixin) +$(LI $(BUGZILLA 7966): First template instantiation inside `with` results in `Error 42: Symbol Undefined`) +$(LI $(BUGZILLA 8019): $(LPAREN)D1 only$(RPAREN) can't convert [] to int[]) +$(LI $(BUGZILLA 8117): Cannot initialize struct member without default constructor) +$(LI $(BUGZILLA 8179): ICE$(LPAREN)e2ir.c$(RPAREN) with failed fixed size array cast) +$(LI $(BUGZILLA 8200): DMD segfault: template aliasing result of map) +$(LI $(BUGZILLA 8244): cannot slice a type tuple with '[]' in locations where a type is valid) +$(LI $(BUGZILLA 8255): [CTFE] ICE when passing 'ref' literal) +$(LI $(BUGZILLA 8313): stack overflow on recursive ifti evaluation) +$(LI $(BUGZILLA 8365): Static fixed size array of enums initialization fails) +$(LI $(BUGZILLA 8396): wrong order of evaluation for tuple expansion in function arguments) +$(LI $(BUGZILLA 8492): can't infer type in static assert) +$(LI $(BUGZILLA 8511): Segfault with forward-referenced enum) +$(LI $(BUGZILLA 8525): optimizer loops infinitely) +$(LI $(BUGZILLA 8543): simd literals need better CTFE support) +$(LI $(BUGZILLA 8581): Internal error: backend/cod1.c 1677 on structs with bitfields $(LPAREN)when compile with release or optimize parameter$(RPAREN)) +$(LI $(BUGZILLA 8648): No error line number with incomplete template) +$(LI $(BUGZILLA 8658): Passing large structs to function b value causes stack corruption) +$(LI $(BUGZILLA 8664): Compiler causes stack overflow with recursive typedef and option -g) +$(LI $(BUGZILLA 8711): ICE with initializing function pointer with array) +$(LI $(BUGZILLA 8722): foreach triggers a floating point exception with multidimensional array of a dimension equal to 0) +$(LI $(BUGZILLA 8735): ICE: Assertion failure: 't' on line 100 in file 'aliasthis.c') +$(LI $(BUGZILLA 8739): DDoc outputs wrong parameter name in delegate parameter list) +$(LI $(BUGZILLA 8825): Wrong line number of error message) +$(LI $(BUGZILLA 8903): Bad code for enum array members) +$(LI $(BUGZILLA 8997): template instances omit symbol that may be used in other modules) +$(LI $(BUGZILLA 9008): Another forward referencing bug) +$(LI $(BUGZILLA 9050): Too early instantiation of template structs) +$(LI $(BUGZILLA 9081): Modules shouldn't have a type) +$(LI $(BUGZILLA 9212): Associative array foreach iteration with immutable key) +$(LI $(BUGZILLA 9256): A purity-related error message in case of member access) +$(LI $(BUGZILLA 9271): Forwarding lambda predicate with type inference causes segfault) +$(LI $(BUGZILLA 9296): LITTLE_ENDIAN and BIG_ENDIAN are always defined on Linux) +$(LI $(BUGZILLA 9301): using XMM.PSHUFD results in an internal compiler error) +$(LI $(BUGZILLA 9356): -inline with inout and append generates wrong code) +$(LI $(BUGZILLA 9459): Front-end does not detect invalid array operations) +$(LI $(BUGZILLA 9466): Compiler crash with code-coverage generation with large files) +$(LI $(BUGZILLA 9504): typeof does not look up properties correctly on template argument) +$(LI $(BUGZILLA 9562): Built-in runtime properties should become error with `Type.prop`) +$(LI $(BUGZILLA 9572): Missed wrong implicit integral conversion) +$(LI $(BUGZILLA 9577): Crash on static array of function literals) +$(LI $(BUGZILLA 9644): Spell checker gives silly suggestions for 1-2 character symbols) +$(LI $(BUGZILLA 9662): Implement RDMD test suite) +$(LI $(BUGZILLA 9690): cannot access to @disable'd symbol from inner function of another @disable'd) +$(LI $(BUGZILLA 9741): undefined identifier with User Defined Attribute) +$(LI $(BUGZILLA 9765): Error message with __error with struct literal dotvar expression) +$(LI $(BUGZILLA 9807): with statement does not work with alias this) +$(LI $(BUGZILLA 9831): Error message with failed lambda inference) +$(LI $(BUGZILLA 9861): Spurious 'is used as type' error with failed template instantiation) +$(LI $(BUGZILLA 9912): Wrong codegen when using tuple over member variable in more than one method) +$(LI $(BUGZILLA 10207): Alias and @attributes: Assertion failure: '!udas' on line 3132 in file 'parse.c') +$(LI $(BUGZILLA 10224): core.simd ICE cgcv.c line 2162 when compiling with -g) +$(LI $(BUGZILLA 10251): CTFE: Allow returning pointers to global static variables of known value) +$(LI $(BUGZILLA 10259): ICE on invalid compile-time class instantiation) +$(LI $(BUGZILLA 10312): compiler assert failure with ctfe on simd vector type) +$(LI $(BUGZILLA 10313): inout constructor + IFTI + has indirections arg doesn't work) +$(LI $(BUGZILLA 10329): Attributes not inferred for indirectly templated methods) +$(LI $(BUGZILLA 10391): Segfault compiling on Mac OS 10.8) +$(LI $(BUGZILLA 10459): align$(LPAREN)16$(RPAREN) does not work on Win64 with seperate compilation) +$(LI $(BUGZILLA 10483): ICE$(LPAREN)expression.c$(RPAREN) .init of struct with block initialized 2D static array) +$(LI $(BUGZILLA 10598): Using not-imported type - AssertFail: 'global.errors' line 6040 'template.c') +$(LI $(BUGZILLA 10632): [ICE]$(LPAREN)glue.c line 1227$(RPAREN) With inlining and tuples) +$(LI $(BUGZILLA 10635): Error: cannot use array to initialize S) +$(LI $(BUGZILLA 10643): Refused const array struct field initialized with void) +$(LI $(BUGZILLA 10747): Win64: warning about non-existing vc100.pdb) +$(LI $(BUGZILLA 10770): is$(LPAREN)T BASE==enum$(RPAREN) with tag enum T - AssertFail:'type' line 428 declaration.c) +$(LI $(BUGZILLA 10805): wrong error message for wrong delimited string) +$(LI $(BUGZILLA 10883): [ICE] Internal error: ../ztc/cod4.c 358 when compiling with -inline) +$(LI $(BUGZILLA 10905): [ICE]$(LPAREN)ctfeexpr.c line 355$(RPAREN) with ulong2 in structs) +$(LI $(BUGZILLA 10922): Compiler segfaults when using __traits$(LPAREN)parent, {}$(RPAREN)) +$(LI $(BUGZILLA 10926): Wrong expression printed when ternary operator used as lvalue) +$(LI $(BUGZILLA 10927): Power of complex number causes an internal error) +$(LI $(BUGZILLA 10938): ICE on recursive instantiation in opDispatch) +$(LI $(BUGZILLA 11019): fwd reference : legal in C++, CT error in D $(LPAREN)unable to resolve forward reference in definition$(RPAREN)) +$(LI $(BUGZILLA 11034): ICE: Assertion failed: $(LPAREN)!scope$(RPAREN), function toObjFile, file toobj.c, line 366.) +$(LI $(BUGZILLA 11155): Wrong SIMD code generated $(LPAREN)unaligned movaps$(RPAREN)) +$(LI $(BUGZILLA 11193): [ICE] String template argument mixed with variadic template arguments causes ICE) +$(LI $(BUGZILLA 11198): Error messages for declaring a 'version' inside main$(LPAREN)$(RPAREN) and other functions are unclear) +$(LI $(BUGZILLA 11215): `inout` lose enclosing `shared` on resolution) +$(LI $(BUGZILLA 11224): Inlining stops NRVO) +$(LI $(BUGZILLA 11247): Error: typeof$(LPAREN)i$(RPAREN).sizeof is used as a type) +$(LI $(BUGZILLA 11286): Impure dtor makes "cannot call impure function" error, although it won't actually be called.) +$(LI $(BUGZILLA 11288): dmd assertion when assigning to $(LPAREN)static$(RPAREN) opDispatch) +$(LI $(BUGZILLA 11297): [ICE]$(LPAREN)glue.c line 868$(RPAREN) with a string concat in global enum lambda) +$(LI $(BUGZILLA 11314): inline ice with tuple assignment and if/else again) +$(LI $(BUGZILLA 11317): glue.c:1218: virtual unsigned int Type::totym$(LPAREN)$(RPAREN): Assertion `0` failed.) +$(LI $(BUGZILLA 11322): ICE with -inline cgcs.c 221) +$(LI $(BUGZILLA 11332): ICE$(LPAREN)dt.c$(RPAREN) and missing error when interpreting an unimplemented builtin) +$(LI $(BUGZILLA 11371): core.simd and ctfe) +$(LI $(BUGZILLA 11375): [profile+nothrow] Semantic 'no throw' error with -profile switch) +$(LI $(BUGZILLA 11376): ICE on __traits$(LPAREN)compiles, ...$(RPAREN) with invalid array-op) +$(LI $(BUGZILLA 11383): Some array casts incorrectly rejected in safe code) +$(LI $(BUGZILLA 11385): XXX is a nested function and cannot be accessed from XXX) +$(LI $(BUGZILLA 11394): NRVO should work for object field initialization in constructor) +$(LI $(BUGZILLA 11406): ld.gold breaks switch table jumps) +$(LI $(BUGZILLA 11425): Broken shadowing variable diagnostic) +$(LI $(BUGZILLA 11427): anonymous unions break structs in @safe code) +$(LI $(BUGZILLA 11445): adding double[string] causes crash) +$(LI $(BUGZILLA 11479): template members ignore private attribute in ddoc) +$(LI $(BUGZILLA 11484): [e2ir] Error in e2ir at cast to/from static array) +$(LI $(BUGZILLA 11485): [e2ir] Error in e2ir at numeric/bool to class/interface cast) +$(LI $(BUGZILLA 11489): Improper implicit cast to immutable.) +$(LI $(BUGZILLA 11497): lambda in "static if"/"assert" prevent inlining of function) +$(LI $(BUGZILLA 11518): DMD segfault on multiple template match) +$(LI $(BUGZILLA 11534): [CTFE] inout + returning a pointer into a member array) +$(LI $(BUGZILLA 11540): [ICE] CTFE segfault with try-catch-finally and goto) +$(LI $(BUGZILLA 11552): Missing label is not caught during semantic) +$(LI $(BUGZILLA 11562): Goto into or out of finally block is not caught during semantic) +$(LI $(BUGZILLA 11565): [Optimizer] Zeroes out the higher 32bits of register in ?: expression) +$(LI $(BUGZILLA 11587): Cannot compare AAs at compile time) +$(LI $(BUGZILLA 11618): Internal Compiler Error) +$(LI $(BUGZILLA 11627): [CTFE] cannot cast dchar to char at compile time on AA assignment) +$(LI $(BUGZILLA 11629): [CTFE] crash on AA.rehash) +$(LI $(BUGZILLA 11635): RDMD eats the -op flag when it should just pass through) +$(LI $(BUGZILLA 11653): No error when forgetting break with range cases.) +$(LI $(BUGZILLA 11656): property offsetof does not work with __vector fields) +$(LI $(BUGZILLA 11661): Meaningless error: "a struct is not a valid initializer for a void function$(LPAREN)$(RPAREN)") +$(LI $(BUGZILLA 11664): A function with a local static variable is unusable in CTFE) +$(LI $(BUGZILLA 11689): deprecated local function does not work) +$(LI $(BUGZILLA 11696): C++ incorrect static member mangling) +$(LI $(BUGZILLA 11722): Qualifier-only casts should not invoke opCast) +$(LI $(BUGZILLA 11726): ICE with ufcs on undefined identifier and opDispatch) +$(LI $(BUGZILLA 11727): Repeated error message with using forward referenced enum as variable) +$(LI $(BUGZILLA 11735): pragma$(LPAREN)msg, ...$(RPAREN) fails to print wstring, dstring) +$(LI $(BUGZILLA 11745): Unittests retrieved by __traits$(LPAREN)getUnitTests$(RPAREN) can not be invoked if private.) +$(LI $(BUGZILLA 11748): [ICE] function call as alias parameter of template gives ICE) +$(LI $(BUGZILLA 11749): switch case fallthrough error is enabled with -w, but cannot be made informational warning) +$(LI $(BUGZILLA 11750): ICE with debug info and empty #line Filespec) +$(LI $(BUGZILLA 11756): Irrelevant variable name printing in CTFE error message) +$(LI $(BUGZILLA 11769): Wrong line number in "matches both" error message) +$(LI $(BUGZILLA 11785): Order of method/function declarations has an effect on compilation result.) +$(LI $(BUGZILLA 11790): ICE$(LPAREN)interpret.c$(RPAREN): passing creation of array with type string as size to CTFE) +$(LI $(BUGZILLA 11793): [ICE] Compiler runs out of memory with trivial program: class with own class member instance) +$(LI $(BUGZILLA 11800): alias this matching incorrectly changes lvalue-ness) +$(LI $(BUGZILLA 11802): Wrong vtbl order for extern$(LPAREN)C++$(RPAREN) classes with overloaded functions on win32) +$(LI $(BUGZILLA 11813): Improve IFTI error diagnostic) +$(LI $(BUGZILLA 11814): Unnecessary error messages "does not match ..." on IFTI failure) +$(LI $(BUGZILLA 11843): Template instantiated twice: failed semantic analysis) +$(LI $(BUGZILLA 11875): static if template type deduction causes infinite recursion with recursive alias this) +$(LI $(BUGZILLA 11926): Segmentation fault when using const in an enum) +$(LI $(BUGZILLA 11944): ICE$(LPAREN)expression.c$(RPAREN) Assertion `f` failed.) +$(LI $(BUGZILLA 11968): ICE$(LPAREN)expression.c$(RPAREN) Crash when deleting __FILE__) +$(LI $(BUGZILLA 11969): ICE$(LPAREN)statement.c$(RPAREN) When mixing in a array literal containing errors) +$(LI $(BUGZILLA 11974): ICE$(LPAREN)cast.c$(RPAREN) Segfault with invalid assignment) +$(LI $(BUGZILLA 11982): ICE$(LPAREN)func.c$(RPAREN) With function literal with no body) +$(LI $(BUGZILLA 12038): alias this and $(AMP)this cause ICE) +$(LI $(BUGZILLA 12040): Compiler segfault with circular reference in variable type) +$(LI $(BUGZILLA 12051): Wrong code with ?: resulting in char on x86-64) +$(LI $(BUGZILLA 12095): Wrong code with -O -inline) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 3597): Need single source for parser and documentation grammar.) +$(LI $(BUGZILLA 5109): some advise) +$(LI $(BUGZILLA 5746): Make std.range.iota strongly pure) +$(LI $(BUGZILLA 6930): combined type of immutable$(LPAREN)T$(RPAREN) and inout$(LPAREN)T$(RPAREN) should be inout$(LPAREN)const$(LPAREN)T$(RPAREN)$(RPAREN)) +$(LI $(BUGZILLA 9477): String $(LPAREN)and array$(RPAREN) comparisons are needlessly very slow) +$(LI $(BUGZILLA 10199): labels cannot be used without a statement) +$(LI $(BUGZILLA 11284): add -allinst compiler switch) +$(LI $(BUGZILLA 11365): Allow D source file names to have no extension $(LPAREN)or an arbitrary extension$(RPAREN) when -run is used) +$(LI $(BUGZILLA 11417): rotate with immediate not recognized by optimizer) +$(LI $(BUGZILLA 11510): Relax restriction for overlapped pointer field access in safe code/during CTFE) +$(LI $(BUGZILLA 11533): Compiler should allow to being nested for static local template functions) +$(LI $(BUGZILLA 11546): string import dependency failure) +$(LI $(BUGZILLA 11711): Add __traits$(LPAREN)getAliasThis$(RPAREN)) +$(LI $(BUGZILLA 11759): Poor error message trying to use lowercase L in literal suffix.) +$(LI $(BUGZILLA 11840): Show all errors of undefined identifier used in a line) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 1832): reading/writing an archive causes data loss; std.zip horribly broken) +$(LI $(BUGZILLA 11309): std.concurrency: OwnerTerminated message doesn't work) +$(LI $(BUGZILLA 11512): Can't build Phobos docs with win32 makefile) +$(LI $(BUGZILLA 11527): JSONValue cannot set values through named fields) +$(LI $(BUGZILLA 11528): appender: crash with -inline -O) +$(LI $(BUGZILLA 11576): std.algorithm.remove!$(LPAREN)SwapStrategy.unstable$(RPAREN) overruns array bounds) +$(LI $(BUGZILLA 11583): bigint bug) +$(LI $(BUGZILLA 11591): std.typecons.Tuple -s with classes fails at runtime as associative array keys) +$(LI $(BUGZILLA 11603): std.algorithm.canFind does not work when needle is 1-byte zero) +$(LI $(BUGZILLA 11671): ctRegex broken) +$(LI $(BUGZILLA 11684): SIGSEGV with ld.bfd version 2.22) +$(LI $(BUGZILLA 11692): can't set file attributes for std.zip.ArchiveMember) +$(LI $(BUGZILLA 11764): [REG2.065a]std.getopt broken) +$(LI $(BUGZILLA 11831): std.zip no longer allows setting madeVersion field in zip file) +$(LI $(BUGZILLA 11838): Missing emplace import for std.range.zip?) +$(LI $(BUGZILLA 11853): Tuples fail "isAssignable") +$(LI $(BUGZILLA 11973): std/datetime.d$(LPAREN)14647$(RPAREN): Deprecation: function std.algorithm.canFind!$(LPAREN)not$(RPAREN).canFind!$(LPAREN)immutable$(LPAREN)dchar$(RPAREN)[]$(RPAREN).canFind is deprecated - Please use any instead) +$(LI $(BUGZILLA 12024): [REG DMD2.065-b2] template instantiation for swap$(LPAREN)SysTime, SysTime$(RPAREN) fails) +$(LI $(BUGZILLA 12071): Algebraic won't take delegate returning structure) +$(LI $(BUGZILLA 12098): libcurl bad argument on handle null) +$(LI $(BUGZILLA 12135): [AA] Format tail after associative array value is treated as separator if explicit separator is empty) +$(LI $(BUGZILLA 12168): [REG2.065a] Add ref to array$(LPAREN)$(RPAREN) and object$(LPAREN)$(RPAREN) of JSONValue getters to add new element) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 1804): Severe GC leaks with repetitive array allocations) +$(LI $(BUGZILLA 2162): Access violation when threads run closures) +$(LI $(BUGZILLA 4301): BigInt * const$(LPAREN)BigInt$(RPAREN) doesn't work well) +$(LI $(BUGZILLA 4673): Bug in std.string $(LPAREN)isNumeric$(RPAREN)) +$(LI $(BUGZILLA 4874): std.numeric.dotProduct doesn't work with bigints) +$(LI $(BUGZILLA 5280): to!FP$(LPAREN)Hex float string$(RPAREN) doesn't work well) +$(LI $(BUGZILLA 5762): getopt: short option parameter read incorrectly when bundling enabled) +$(LI $(BUGZILLA 5977): String splitting with empty separator) +$(LI $(BUGZILLA 6730): std.algorithm.splitter conflicts with std.array.splitter) +$(LI $(BUGZILLA 7069): Variant Doesn't Handle Const or Immutable Contents) +$(LI $(BUGZILLA 7689): splitter$(LPAREN)$(RPAREN) on ivalid UTF-8 sequences) +$(LI $(BUGZILLA 8013): splitter$(LPAREN)$(RPAREN) and split$(LPAREN)$(RPAREN) give different results) +$(LI $(BUGZILLA 8203): Use of std.regex.match$(LPAREN)$(RPAREN) generates "not enough preallocated memory" error) +$(LI $(BUGZILLA 8291): dirEntry cannot handle root directories + unhandled exception causes crash) +$(LI $(BUGZILLA 8298): dirEntries special linux file in Home dir) +$(LI $(BUGZILLA 8877): std.encoding.transcode is extremely slow) +$(LI $(BUGZILLA 9528): std.array.appender can't append elements with const members) +$(LI $(BUGZILLA 9645): std.algorithm.splitter on string with char as separator performs badly in certain situations) +$(LI $(BUGZILLA 9823): Delegate accepting element not accepted in std.range.put) +$(LI $(BUGZILLA 10569): std.traits: EnumMembers, isExpressionTuple, isTypeTuple $(AMP) Largest balks at large input) +$(LI $(BUGZILLA 10571): formattedWrite error with delegate and string) +$(LI $(BUGZILLA 10710): shared phobos library doesn't work on all linux distributions) +$(LI $(BUGZILLA 10864): [REG 2.064][PERFORMANCE] new Safe appender is slower than "~=") +$(LI $(BUGZILLA 11005): std.xml does not encode attributes) +$(LI $(BUGZILLA 11110): Variant.convertsTo doesn't work like isImplicitlyConvertible) +$(LI $(BUGZILLA 11112): Unable to execute shell commands in different threads) +$(LI $(BUGZILLA 11148): Can't implicitly convert const$(LPAREN)BigInt$(RPAREN) or immutable$(LPAREN)BigInt$(RPAREN) to BigInt) +$(LI $(BUGZILLA 11180): Launching a process from a Windows GUI process using std.process.spawnProcess always fails) +$(LI $(BUGZILLA 11403): functions in std.algo can't be used as pred) +$(LI $(BUGZILLA 11459): std.container.Array bool constraint ambiguity) +$(LI $(BUGZILLA 11568): can't compile std.stdio.rawWrite with -m64 in Windows) +$(LI $(BUGZILLA 11600): to!BigInt$(LPAREN)string$(RPAREN) accepts non-numeric input) +$(LI $(BUGZILLA 11606): Cannot instantiate Tuple of non printable) +$(LI $(BUGZILLA 11617): std.uni.normalize doesn't compile) +$(LI $(BUGZILLA 11652): Support numerical ^^ complex operations in std.complex) +$(LI $(BUGZILLA 11681): std.datetime.IntervalRange.opAssign with non-ref parameter is required) +$(LI $(BUGZILLA 11691): can't join pathSplitter with dirSeparator) +$(LI $(BUGZILLA 11713): std.string munch$(LPAREN)$(RPAREN) does not properly handle UTF strings.) +$(LI $(BUGZILLA 11738): partialShuffle actually shuffles the entire input) +$(LI $(BUGZILLA 11771): Unicode set intersection with char is broken) +$(LI $(BUGZILLA 11775): std.regex should check for valid repetition range in assert mode) +$(LI $(BUGZILLA 11780): RangeError in format for incomplete format specifier) +$(LI $(BUGZILLA 11808): std.uni.CodepointSet$(LPAREN)'А', 'Я'+1, 'а', 'я'+1$(RPAREN) asserts) +$(LI $(BUGZILLA 11839): std.regex capture group names should allow numbers to be in them) +$(LI $(BUGZILLA 11879): missing default User-Agent in std.net.curl) +$(LI $(BUGZILLA 11884): std.container.Array lacks a constructor from an input range) +$(LI $(BUGZILLA 12069): ctRegex is 3x slower then R-T ?) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 3868): It would be nice to have a function which read a file lazily using a range) +$(LI $(BUGZILLA 4859): Another File.byChunk$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 4909): Two suggestions for std.algorithm.schwartzSort$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 5611): back$(LPAREN)$(RPAREN) and front$(LPAREN)$(RPAREN) with ref return + opSlice$(LPAREN)$(RPAREN) in sort$(LPAREN)$(RPAREN) constraint) +$(LI $(BUGZILLA 6986): SortedRange[x..$] fails with unidentified __dollar) +$(LI $(BUGZILLA 8167): BigInt$(LPAREN)BigInt$(LPAREN)1$(RPAREN)$(RPAREN) too) +$(LI $(BUGZILLA 9061): BigInt | BigInt, BigInt $(AMP) int) +$(LI $(BUGZILLA 11770): std.regex.Captures should be convertible to bool) +$(LI $(BUGZILLA 11789): No setAttributes to complement getAttributes) +$(LI $(BUGZILLA 11798): std.algorithm.all with no predicate too) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 11478): shared library on osx: worked in 2.062, fails in 2.063.2, still fails in 2.064) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 3454): Inconsistent flag setting in GC.realloc$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 4809): Stack trace when throwing exception misses location of the throw statement) +$(LI $(BUGZILLA 7508): float4 values aren't stored on initialisation) +$(LI $(BUGZILLA 8301): Access violation when a big array is allocated) +$(LI $(BUGZILLA 10701): [GC] segfault in GC) +$(LI $(BUGZILLA 11806): Freeze in GC.collect$(LPAREN)$(RPAREN) in in-contracts when multithreading is used) +) +$(BUGSTITLE Optlink regressions, + +$(LI $(BUGZILLA 11559): Optlink crash with more than 2048 modules generated and debug info) +) +$(BUGSTITLE Optlink bugs, + +$(LI $(BUGZILLA 2837): OPTLINK and LARGEADDRESSAWARE) +$(LI $(BUGZILLA 3956): linker removes underscore from all exported symbols of a module but the first) +$(LI $(BUGZILLA 6673): Map file contains broken lines on every 16,384 bytes) +$(LI $(BUGZILLA 7634): optlink creates bad debug info for a large number of modules) +) +$(BUGSTITLE Installer bugs, + +$(LI $(BUGZILLA 10246): Windows installer still downloads from ftp.digitalmars.com) +$(LI $(BUGZILLA 11799): Incompatible argument types in create_dmd_release) +) +$(BUGSTITLE Installer enhancements, + +$(LI $(BUGZILLA 10153): Beta releases should all have unique names) +) +$(BUGSTITLE Website regressions, + +$(LI $(BUGZILLA 11449): Jump lists of phobos are in wrong order) +) +$(BUGSTITLE Website bugs, + +$(LI $(BUGZILLA 5388): SList.insertFront has complexity O$(LPAREN)log$(LPAREN)n$(RPAREN)$(RPAREN)) +$(LI $(BUGZILLA 9734): setIntersection accepts only 2 ranges, but documentation says otherwise) +$(LI $(BUGZILLA 10205): 'deprecated' '$(LPAREN)' assignExpression '$(RPAREN)' grammar is not documented) +$(LI $(BUGZILLA 10206): User-defined attributes not documented well in language specification) +$(LI $(BUGZILLA 10250): Grammar does not allow invariants in struct declarations) +$(LI $(BUGZILLA 10514): Constructor declaration grammar is incorrect) +$(LI $(BUGZILLA 11398): Language spec does not allow new eponymous template syntax) +$(LI $(BUGZILLA 11579): dlang.org repo can't be built without git) +$(LI $(BUGZILLA 11762): std.regex macro is not displayed/expanded properly) +) +$(BUGSTITLE Website enhancements, + +$(LI $(BUGZILLA 11676): Add a link to D Wiki Sidebar to take users back to DLang.org) +$(LI $(BUGZILLA 12087): Add Readme to dlang.org repository that explains how to contribute) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.065.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.066.0.dd b/changelog/2.066.0.dd new file mode 100644 index 0000000000..18b7ca00de --- /dev/null +++ b/changelog/2.066.0.dd @@ -0,0 +1,1153 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION August 18, 2014, =================================================, + +$(BUGSTITLE Compiler Changes, +$(LI $(RELATIVE_LINK2 warn-unused-retval, $(D -w) now warns about an unused return value of a strongly pure nothrow function call.)) +$(LI $(RELATIVE_LINK2 boundscheck, $(D -noboundscheck) has been deprecated in favor of $(D boundscheck=[on|safeonly|off]).)) +$(LI $(RELATIVE_LINK2 vgc-switch, $(D -vgc) was added to list GC allocation code positions in the code.)) +$(LI $(RELATIVE_LINK2 vcolumns-switch, $(D -vcolumns) was added to display column numbers in error messages.)) +$(LI $(RELATIVE_LINK2 color-switch, $(D -color) was added to make console output colored.)) +) + +$(BUGSTITLE Language Changes, +$(LI $(RELATIVE_LINK2 nogc-attribute, $(D @nogc) attribute was added.)) +$(LI $(RELATIVE_LINK2 extern-cpp-nspace, $(D extern $(LPAREN)C++,) $(I namespace)$(D $(RPAREN)) was added.)) +$(LI $(RELATIVE_LINK2 opover-multidim-slicing, Operator overloading for multi-dimensional slicing was added.)) +$(LI $(RELATIVE_LINK2 traits-getfunctionattributes, $(D __traits$(LPAREN)getFunctionAttributes$(RPAREN)) was added.)) +$(LI $(RELATIVE_LINK2 narrowing-conversion-in-ifti, Support template parameter deduction for arguments with a narrowing conversion.)) +$(LI $(RELATIVE_LINK2 deprecate-rmw, Read-Modify-Write operations on shared variables are now deprecated.)) +$(LI $(RELATIVE_LINK2 uniform-scalar-construction, Support uniform construction syntax for built-in scalar types.)) +) + +$(BUGSTITLE Library Changes, +$(LI $(RELATIVE_LINK2 duration-split, Duration.get and its wrappers have been deprecated in favor of the new Duration.split.)) +$(LI $(RELATIVE_LINK2 array-and-aa-changes, Some built-in type properties have been replaced with library functions.)) +$(LI $(RELATIVE_LINK2 aa-key-requirement, Associative array keys now require equality instead of order comparison.)) +) + +$(BUGSTITLE Linker Changes, +) + +$(BR)$(BIG $(RELATIVE_LINK2 list2066, List of all bug fixes and enhancements in D 2.066.)) + +$(HR) + +$(BUGSTITLE Compiler Changes, + +$(LI $(LEGACY_LNAME2 warn_unused_retval, warn-unused-retval, $(D -w) now warns about an unused return value of a strongly pure nothrow function call:) + + $(P A discarded return value from a strongly pure nothrow function call now generates a warning. + + --------- + int foo() pure nothrow { return 1; } + void main() + { + foo(); // the result of foo() is unused + } + --------- + + With the $(D -w) switch, the compiler will complain: + + $(CONSOLE Warning: calling foo without side effects discards return value of type int, prepend a cast(void) if intentional) + ) +) + +$(LI $(LNAME2 boundscheck, $(D -noboundscheck) has been deprecated in favor of $(D boundscheck=[on|safeonly|off]):) + + $(P Confusion over what the $(D -noboundscheck) command line option did led to the creation of + the new option $(D -boundscheck=[on|safeonly|off]) which aims to be more clear while enabling + more flexibility than was present before. + ) + + $(P $(D -boundscheck=) + $(UL + $(LI $(B on): Bounds checks are enabled for all code. This is the default.) + $(LI $(B safeonly): Bounds checks are enabled only in $(D @safe) code. + This is the default for $(B -release) builds.) + $(LI $(B off): Bounds checks are disabled completely (even in $(D @safe) + code). This option should be used with caution and as a + last resort to improve performance. Confirm turning off + $(D @safe) bounds checks is worthwhile by benchmarking.) + ) + ) + + $(P $(B Use $(D -boundscheck=off) to replace instances of $(D -noboundscheck).)) + + $(P Prior to this there was no way to enable bounds checking for $(D -release) builds nor any + way of turning off non-$(D @safe) bounds checking without pulling in everything else $(D + -release) does.) +) + +$(LI $(LEGACY_LNAME2 vgc_switch, vgc-switch, $(D -vgc) was added to list GC allocation code positions in the code): + + $(P Prints all GC-allocation points. Analysis will follow the semantics of + the new $(D @nogc) attribute. + ) +) + +$(LI $(LEGACY_LNAME2 vcolumns_switch, vcolumns-switch, $(D -vcolumns) was added to display column numbers in error messages): + + $(P Diagnostic messages will print the character number from each line head. + + --------- + int x = missing_name; + --------- + + Without $(D -vcolumns): + + --------- + test.d(1): Error: undefined identifier missing_name + --------- + + With $(D -vcolumns): + + --------- + test.d(1,9): Error: undefined identifier missing_name + --------- + ) +) + +$(LI $(LEGACY_LNAME2 color_switch, color-switch, $(D -color) was added to make console output colored:) + + $(P Errors, deprecation, and warning messages will be colored. + ) +) + +) + +$(BUGSTITLE Language Changes, + +$(LI $(LEGACY_LNAME2 nogc_attribute, nogc-attribute, $(D @nogc) attribute was added:) + + $(P @nogc attribute disallows GC-heap allocation. + + --------- + class C {} + void foo() @nogc + { + auto c = new C(); // GC-allocation is disallowed + } + --------- + ) +) + +$(LI $(LEGACY_LNAME2 extern_cpp_nspace, extern-cpp-nspace, $(D extern $(LPAREN)C++,) $(I namespace)$(D $(RPAREN)) was added): + + $(P To represent a C++ namespace, $(D extern $(LPAREN)C++$(RPAREN)) now takes optional dot-chained identifiers. + + --------- + extern (C++, a.b.c) int foo(); + --------- + + is equivalent with: + +$(CPPCODE +namespace a { + namespace b { + namespace c { + int foo(); + } + } +} +) + ) +) + +$(LI $(LEGACY_LNAME2 opover_multidim_slicing, opover-multidim-slicing, Operator overloading for multi-dimensional slicing was added:) + + $(P Documentation is + $(LINK2 $(ROOT_DIR)spec/operatoroverloading.html#ArrayOps, here).) + + $(P Example code: + + --------- + struct MyContainer(E) + { + E[][] payload; + + this(size_t w, size_t h) + { + payload = new E[][](h, w); + } + + size_t opDollar(size_t dim)() + { + return payload[dim].length; + } + + auto opSlice(size_t dim)(size_t lwr, size_t upr) + { + import std.typecons; + return tuple(lwr, upr); + } + + void opIndexAssign(A...)(E val, A indices) + { + assert(A.length == payload.length); + + foreach (dim, x; indices) + { + static if (is(typeof(x) : size_t)) + { + // this[..., x, ...] + payload[dim][x] = val; + } + else + { + // this[..., x[0] .. x[1], ...] + payload[dim][x[0] .. x[1]] = val; + } + } + } + } + void main() + { + import std.stdio; + + auto c = MyContainer!int(4, 3); + writefln("[%([%(%d%| %)]%|\n %)]", c.payload); + // [[0 0 0 0] + // [0 0 0 0] + // [0 0 0 0]] + + c[1 .. 3, + 2, + 0 .. $] = 1; + /* + Rewritten as: + c.opIndexAssign(c.opSlice!0(1, 3), + 2, + c.opSlice!2(0, c.opDollar!2())); + */ + + writefln("[%([%(%d%| %)]%|\n %)]", c.payload); + // [[0 1 1 0] + // [0 0 1 0] + // [1 1 1 1]] + } + --------- + ) +) + +$(LI $(LEGACY_LNAME2 traits_getfunctionattributes, traits-getfunctionattributes, $(D __traits$(LPAREN)getFunctionAttributes$(RPAREN)) was added): + + $(P This can take one argument, either a function symbol, function type, function + pointer type, or delegate type. + + Examples: + + --------- + void foo() pure nothrow @safe; + static assert([__traits(getFunctionAttributes, foo)] == ["pure", "nothrow", "@safe"]); + + ref int bar(int) @property @trusted; + static assert([__traits(getFunctionAttributes, typeof(&bar))] == ["@property", "ref", "@trusted"]); + --------- + ) +) + +$(LI $(LEGACY_LNAME2 narrowing_conversion_in_ifti, narrowing-conversion-in-ifti, Support template parameter deduction for arguments with a narrowing conversion): + + $(P Implicit Function Template Instantiation will now consider a narrowing conversion + of function arguments when deducing the template instance parameter types. + + --------- + void foo(T)(T[] arr, T elem) { ... } + void main() + { + short[] a; + foo(a, 1); + } + --------- + + In 2.065 and earlier, calling $(D foo(a, 1)) was not allowed. From 2.066, + $(D T) is deduced as $(D short) by considering a narrowing conversion + of the second function argument `1` from $(D int) to $(D short). + ) +) + +$(LI $(LEGACY_LNAME2 deprecate_rmw, deprecate-rmw, Read-Modify-Write operations on shared variables are now deprecated): + + $(P Examples: + + --------- + shared int global; + void main() + { + global++; // deprecated + global *= 2; // deprecated + } + --------- + + Instead you should use $(D atomicOp) from $(D core.atomic): + + --------- + shared int global; + void main() + { + import core.atomic; + atomicOp!"+="(global, 1); + atomicOp!"*="(global, 2); + } + --------- + ) +) + +$(LI $(LEGACY_LNAME2 uniform_scalar_construction, uniform-scalar-construction, Support uniform construction syntax for built-in scalar types): + + $(P Examples: + + --------- + short n1 = 1; + auto n2 = short(1); // equivalent with n1, typeof(n2) is short + + auto p1 = new long(1); // typeof(p1) is long* + auto p2 = new immutable double(3.14); // typeof(p2) is immutable(double)* + --------- + ) + + $(P The constructor argument should be implicitly convertible to the constructed type. + + --------- + auto n1 = short(32767); // OK + auto n2 = short(32768); // Not allowed, out of bounds of signed short -32768 to 32767 + --------- + ) +) + +) + +$(BUGSTITLE Library Changes, + +$(LI $(LEGACY_LNAME2 duration_split, duration-split, Duration.get and its wrappers have been deprecated in favor of the new Duration.split:) + + $(P $(REF_SHORT Duration.get, core,time) and its wrappers, $(REF_SHORT Duration.weeks, core,time), + $(REF_SHORT Duration.days, core,time), $(REF_SHORT Duration.hours, core,time), and + $(REF_SHORT Duration.seconds, core,time), as well as $(REF_SHORT Duration.fracSec, core,time) (which + served a similar purpose as $(REF_SHORT Duration.get, core,time) for the fractional second units) + have proven to be too easily confused with $(REF_SHORT Duration.total, core,time), causing + subtle bugs. So, they have been deprecated. In their place, $(REF_SHORT Duration.split, core,time) + has been added - and it's not only very useful, but it does a great job of showing off + what D can do. + + Whereas $(REF_SHORT Duration.get, core,time) split out all of the units of a + $(REF_SHORT Duration, core,time) and then returned only one of them, + $(REF_SHORT Duration.split, core,time) splits out a $(REF_SHORT Duration, core,time) into the units + that it's told to (which could be one unit or all of them) and returns all of + them. It has two overloads, both which take template arguments that indicate which + of the units are to be split out. The difference is in how the result is returned. + + As with most of the templates in core.time and std.datetime which take strings + to represent units, $(REF_SHORT Duration.split, core,time) accepts $(D "weeks"), $(D "days"), + $(D "hours"), $(D "minutes"), $(D "seconds"), $(D "msecs"), $(D "usecs"), + $(D "hnsecs"), and $(D "nsecs"). + + The first overload returns the split out units as $(D out) parameters. + + --------- + auto d = weeks(5) + days(4) + hours(17) + seconds(2) + hnsecs(12_007); + short days; + long seconds; + int msecs; + d.split!("days", "seconds", "msecs")(days, seconds, msecs); + assert(days == 39); + assert(seconds == 61_202); + assert(msecs == 1); + --------- + + The arguments can be any integral type (though no protection is given against integer + overflow, so unless it's known that the values are going to be small, it's unwise to + use a small integral type for any of the arguments). + + The second overload returns a struct with the unit names as its fields. Only the + requested units are present as fields. All of the struct's fields are $(D long)s. + + --------- + auto d = weeks(5) + days(4) + hours(17) + seconds(2) + hnsecs(12_007); + auto result = d.split!("days", "seconds", "msecs")(); + assert(result.days == 39); + assert(result.seconds == 61_202); + assert(result.msecs == 1); + --------- + + Or if no units are given to the second overload, then it will return a struct with + all of the units save for $(D nsecs) (since $(D nsecs) would always be $(D 0) when + $(D hnsecs) is one of the units as $(REF_SHORT Duration, core,time) has hnsec precision). + + --------- + auto d = weeks(5) + days(4) + hours(17) + seconds(2) + hnsecs(12_007); + auto result = d.split(); + assert(result.weeks == 5); + assert(result.days == 4); + assert(result.hours == 17); + assert(result.minutes == 0); + assert(result.seconds == 2); + assert(result.msecs == 1); + assert(result.usecs == 200); + assert(result.hnsecs == 7); + --------- + + Calling $(REF_SHORT Duration.get, core,time) or its wrappers for each of the units would be + equivalent to that example, only less efficient when more than one unit is + requested, as the calculations would have to be done more than once. The exception + is $(REF_SHORT Duration.fracSec, core,time) which would have given the total of the + fractional seconds as the requested units rather than splitting them out. + + --------- + // Equivalent to previous example + auto d = weeks(5) + days(4) + hours(17) + seconds(2) + hnsecs(12_007); + assert(d.weeks == 5); + assert(d.days == 4); + assert(d.hours == 17); + assert(d.minutes == 0); + assert(d.seconds == 2); + assert(d.fracSec.msecs == 1); + assert(d.fracSec.usecs == 1200); + assert(d.fracSec.hnsecs == 12_007); + --------- + + It is hoped that $(REF_SHORT Duration.split, core,time) will be less confusing and thus + result in fewer bugs, but it's definitely the case that it's more powerful. It's + also a great example of D's metaprogramming capabilities given how it splits out + only the requested units and even is able to return a struct with fields with the + same names as the requested units. This on top of being able to handle a variety + of integral types as arguments. And its implemenation isn't even very complicated. + ) + +) + +$(LI $(LEGACY_LNAME2 array_and_aa_changes, array-and-aa-changes, Some built-in type properties have been replaced with library functions:) + + $(P Built-in array properties $(D dup) and $(D idup) were replaced with + (module-scoped) free functions in the $(D object) module, thanks to D's support of + $(LINK2 $(ROOT_DIR)spec/function.html#pseudo-member, Uniform Function Call + Syntax). + ) + + $(P Built-in associative array properties $(D rehash), $(D dup), $(D byKey), + $(D byValue), $(D keys), $(D values), and $(D get) were also replaced with free + functions in the $(D object) module. + ) +) + +$(LI $(LEGACY_LNAME2 aa_key_requirement, aa-key-requirement, Associative array keys now require equality rather than ordering:) + + $(P Until 2.065, opCmp was used to customize the comparison of AA struct keys. + + --------- + void main() + { + int[MyKey] aa; + } + + struct MyKey + { + int x; + int y; // want to be ignored for AA key comparison + + int opCmp(ref const MyKey rhs) const + { + if (this.x == rhs.x) + return 0; + + // defined order was merely unused for AA keys. + return this.x > rhs.x ? 1 : -1; + } + } + --------- + + From 2.066, the AA implementation has been changed to use the equality operator ($(D ==)) + for the key comparison. So the $(D MyKey) struct should be modified to: + + --------- + struct MyKey + { + int x; + int y; // want to be ignored for AA key comparison + + int opEquals(ref const MyKey rhs) const + { + return this.x == rhs.x; + } + } + --------- + ) +) + +) + +$(BR)$(BIG $(LNAME2 list2066, List of all bug fixes and enhancements in D 2.066:)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 5105): Member function template cannot be synchronized) +$(LI $(BUGZILLA 9449): Static arrays of 128bit types segfault on initialization. Incorrect calling of memset128ii.) +$(LI $(BUGZILLA 11777): [ICE] dmd memory corruption as `Scope::pop` `free`s `fieldinit` used also in `enclosing`) +$(LI $(BUGZILLA 12174): Problems caused by enum predicate with std.algorithm.sum) +$(LI $(BUGZILLA 12179): [ICE]$(LPAREN)e2ir.c 1861$(RPAREN) with array operation) +$(LI $(BUGZILLA 12242): conflict error with public imports) +$(LI $(BUGZILLA 12243): [REG 2.065.0] "ICE: cannot append 'char' to 'string'" with -inline) +$(LI $(BUGZILLA 12250): [REG 2.065.0][ICE]$(LPAREN)e2ir.c 2077$(RPAREN) with inout T[] and array operation) +$(LI $(BUGZILLA 12255): Regression: opCmp requirement for AAs breaks code) +$(LI $(BUGZILLA 12262): [REG2.065] A specialized parameter `alias a : B!A` should not match to the non-eponymous instantiated variable) +$(LI $(BUGZILLA 12264): [REG2.066a] A specialized alias parameter conflicts with the unspecialized one.) +$(LI $(BUGZILLA 12266): Regression $(LPAREN)2.065$(RPAREN): Header generation produces uncompilable header) +$(LI $(BUGZILLA 12296): [REG2.066a] const compatible AA pointer conversion is wrongly rejected in CTFE) +$(LI $(BUGZILLA 12312): Regression $(LPAREN)2.064$(RPAREN): Diagnostic for void static arrays has gone bad) +$(LI $(BUGZILLA 12316): GIT HEAD: AA.get broken for Object VAL types) +$(LI $(BUGZILLA 12376): ICE with constarainted template instantiation with error gagging) +$(LI $(BUGZILLA 12382): `opDollar` can't be used at CT) +$(LI $(BUGZILLA 12390): [REG2.066a] "has no effect in expression" diagnostic regression) +$(LI $(BUGZILLA 12396): Regression: major breakage from new import rules) +$(LI $(BUGZILLA 12399): Static and selective import acts like a normal import) +$(LI $(BUGZILLA 12400): Misleading/useless diagnostic on bad fully-qualified symbol name) +$(LI $(BUGZILLA 12403): [AA] Associative array `get` function rejects some cases) +$(LI $(BUGZILLA 12405): Named imports act like regular imports) +$(LI $(BUGZILLA 12413): Infinite recursion of `Package::search`) +$(LI $(BUGZILLA 12467): Regression $(LPAREN)2.066 git-head$(RPAREN): char[] is implicitly convertible to string) +$(LI $(BUGZILLA 12485): [REG2.065] DMD crashes when recursive template expansion) +$(LI $(BUGZILLA 12497): [REG2.064] ICE on string mixin with non-string operand) +$(LI $(BUGZILLA 12501): Assertion `global.gaggedErrors || global.errors` failed.) +$(LI $(BUGZILLA 12509): Compiler performance highly depends on declared array size - for struct with long static array of structs) +$(LI $(BUGZILLA 12554): [ICE]$(LPAREN)struct.c line 898$(RPAREN) with failed delegate purity) +$(LI $(BUGZILLA 12574): [ICE]$(LPAREN)statement.c, line 713$(RPAREN) with reduce with wrong tuple arity) +$(LI $(BUGZILLA 12580): [REG2.066a] dup$(LPAREN)$(RPAREN) won't accept void[]) +$(LI $(BUGZILLA 12581): [ICE]$(LPAREN)statement.c, line 713$(RPAREN) with invalid assignment + alias this) +$(LI $(BUGZILLA 12585): Regression$(LPAREN)2.064$(RPAREN): Segfault on lazy/catch/opIndex) +$(LI $(BUGZILLA 12591): [DMD|REG] std/typecons.d$(LPAREN)440$(RPAREN): Error: tuple has no effect in expression) +$(LI $(BUGZILLA 12593): [REG2.065] AA cannot have struct as key) +$(LI $(BUGZILLA 12619): Invalid warning for unused return value of debug memcpy) +$(LI $(BUGZILLA 12649): "discards return value" warning will cause ICE on function pointer call) +$(LI $(BUGZILLA 12650): Invalid codegen on taking lvalue of instance field initializ) +$(LI $(BUGZILLA 12689): [CTFE] assigning via pointer from 'in' expression doesn't work) +$(LI $(BUGZILLA 12703): GIT HEAD : final class rejects members initialization) +$(LI $(BUGZILLA 12719): struct.c:705: virtual void StructDeclaration::semantic$(LPAREN)Scope*$(RPAREN): Assertion `parent $(AMP)$(AMP) parent == sc->parent` failed.) +$(LI $(BUGZILLA 12727): [REG2.066a] DMD hangs up on recursive alias declaration) +$(LI $(BUGZILLA 12728): [REG2.066a] IFTI should consider instantiated types that has template parameters with default args) +$(LI $(BUGZILLA 12760): Initializing an object that has "this$(LPAREN)Args$(RPAREN) inout" causes "discards return value" warning) +$(LI $(BUGZILLA 12769): ICE returning array) +$(LI $(BUGZILLA 12774): REG$(LPAREN)2.066$(RPAREN) ICE$(LPAREN)optimize.c$(RPAREN) Newing struct containing union causes segfault) +$(LI $(BUGZILLA 12824): REG$(LPAREN)2.066$(RPAREN) ICE$(LPAREN)statement.c$(RPAREN) Segfault with label and static if) +$(LI $(BUGZILLA 12860): REG 2.065: typeid$(LPAREN)_error_$(RPAREN) symbols leaked to backend) +$(LI $(BUGZILLA 12864): can no longer use toLower in string switch case) +$(LI $(BUGZILLA 12880): [REG2.066a] Wrong IFTI for string.init argument) +$(LI $(BUGZILLA 12896): ld.gold complains about bad relocations when building libphobos2.so) +$(LI $(BUGZILLA 12900): REG 2.065: Wrong code in IfStatement condition Expression) +$(LI $(BUGZILLA 12904): Wrong-code for some slice to slice assignments when using `opDollar`) +$(LI $(BUGZILLA 12906): [CTFE] Static array of structs causes postblit call) +$(LI $(BUGZILLA 12910): [AA] `rehash` is incorrectly inferred as strongly pure for some associative arrays) +$(LI $(BUGZILLA 12924): deprecated$(LPAREN)"foo"$(RPAREN); and deprecated; should not compile) +$(LI $(BUGZILLA 12956): [ICE] Assertion in expression.c:432) +$(LI $(BUGZILLA 12981): Can't refer to 'outer' from mixin template) +$(LI $(BUGZILLA 12989): Wrong x86_64 code for delegate return when compiled as lib $(LPAREN)-lib$(RPAREN)) +$(LI $(BUGZILLA 13002): DMD 2.066 prep: 32-bit build fails on Ubuntu via create_dmd_release) +$(LI $(BUGZILLA 13008): [REG2.066a] 'deprecated' is not allowed to refer another deprecated when it is a function declaration) +$(LI $(BUGZILLA 13021): Constructing union with floating type and then accessing its field in one expression causes ICE) +$(LI $(BUGZILLA 13024): [ICE]$(LPAREN)expression.c line 1172$(RPAREN) with implicit supertype conversion of different enums in array literal) +$(LI $(BUGZILLA 13025): Tools repository does not build on Ubuntu) +$(LI $(BUGZILLA 13026): object.get cannot be called with [] as "defaultValue" argument) +$(LI $(BUGZILLA 13027): Assertion `ex->op == TOKblit || ex->op == TOKconstruct` failed.) +$(LI $(BUGZILLA 13030): DMD assertion fails at mtype.c:697 if delegate has an argument name) +$(LI $(BUGZILLA 13034): [Reg] core.stdc.stdio - deprecation warning with dmd -inline) +$(LI $(BUGZILLA 13053): Wrong warning on implicitly generated __xtoHash) +$(LI $(BUGZILLA 13056): [2.066.0-b1] Regression: Error: template std.path.baseName cannot deduce function from argument types !$(LPAREN)$(RPAREN)$(LPAREN)DirEntry$(RPAREN)) +$(LI $(BUGZILLA 13071): [ICE] dmd 2.066.0-b1 assertion in nogc.c:73) +$(LI $(BUGZILLA 13077): [dmd 2.066-b2] std.range.array with shared InputRangeObject) +$(LI $(BUGZILLA 13081): ICE with alias this and opSlice) +$(LI $(BUGZILLA 13087): Error: no property 'xyz' for type 'Vec!4') +$(LI $(BUGZILLA 13102): Cannot parse 184467440737095516153.6L) +$(LI $(BUGZILLA 13113): cannot build druntime's gc.d with -debug=INVARIANT, bad @nogc inference?) +$(LI $(BUGZILLA 13114): old opCmp requirement for AA keys should be detected for classes) +$(LI $(BUGZILLA 13117): Executable size of hello world explodes from 472K to 2.7M) +$(LI $(BUGZILLA 13127): Cannot deduce function with int[][] argument and "in" parameter) +$(LI $(BUGZILLA 13132): ICE on interface AA key) +$(LI $(BUGZILLA 13141): array cast from string[] to immutable$(LPAREN)char[][]$(RPAREN) is not supported at compile time) +$(LI $(BUGZILLA 13152): [REG2.064.2] Compiler high cpu usage and never ends) +$(LI $(BUGZILLA 13154): Incorrect init of static float array when sliced) +$(LI $(BUGZILLA 13158): "void has no value" in std.variant.Algebraic $(LPAREN)affects D:YAML$(RPAREN)) +$(LI $(BUGZILLA 13178): Duplicate symbol of compiler generated symbols) +$(LI $(BUGZILLA 13179): AA key type TagIndex now requires equality rather than comparison) +$(LI $(BUGZILLA 13180): [REG2.066a] AA get returns const$(LPAREN)char[]$(RPAREN) instead of string) +$(LI $(BUGZILLA 13187): Function wrongly deduced as pure) +$(LI $(BUGZILLA 13193): Extreme slowdown in compilation time of OpenSSL in Tango for optimized build) +$(LI $(BUGZILLA 13201): Wrong "Warning: statement is not reachable" error with -w) +$(LI $(BUGZILLA 13208): [ICE]$(LPAREN)e2ir.c 2077$(RPAREN) with array operation) +$(LI $(BUGZILLA 13218): [ICE] s2ir.c 142: Must fully qualify call to ParameterTypeTuple) +$(LI $(BUGZILLA 13219): segmentation fault in FuncDeclaration::getLevel) +$(LI $(BUGZILLA 13220): [ICE] 'global.gaggedErrors || global.errors' on line 750 in file 'statement.c') +$(LI $(BUGZILLA 13221): [ICE] '0' on line 318 in file 'interpret.c') +$(LI $(BUGZILLA 13223): Cannot deduce argument for array template parameters) +$(LI $(BUGZILLA 13232): dmd compile times increased by 10-20%) +$(LI $(BUGZILLA 13237): Wrong code with "-inline -O") +$(LI $(BUGZILLA 13245): segfault when instantiating template with non-compiling function literal) +$(LI $(BUGZILLA 13252): ParameterDefaultValueTuple affects other instantiations) +$(LI $(BUGZILLA 13259): [ICE] 'v.result' on line 191 in file 'todt.c') +$(LI $(BUGZILLA 13284): [dmd 2.066-rc2] Cannot match shared classes at receive) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 648): DDoc: unable to document mixin statement) +$(LI $(BUGZILLA 846): Error 42: Symbol Undefined "$(LESS)mangle_of_class_template$(GREATER)__arrayZ") +$(LI $(BUGZILLA 1659): template alias parameters are chosen over all but exact matches.) +$(LI $(BUGZILLA 2427): Function call in struct initializer fails to compile) +$(LI $(BUGZILLA 2438): Cannot get types of delegate properties) +$(LI $(BUGZILLA 2456): "cannot put catch statement inside finally block", missing line number) +$(LI $(BUGZILLA 2711): -H produces bad headers files if function defintion is templated and have auto return value) +$(LI $(BUGZILLA 2791): port.h and port.c are missing licenses) +$(LI $(BUGZILLA 3032): No stack allocation for "scope c = new class Object {};") +$(LI $(BUGZILLA 3109): [meta] Template ordering) +$(LI $(BUGZILLA 3490): DMD Never Inlines Functions that Could Throw) +$(LI $(BUGZILLA 3672): [tdpl] read-modify-write $(LPAREN)rmw$(RPAREN) operators must be disabled for shared) +$(LI $(BUGZILLA 4225): mangle.c:81: char* mangle$(LPAREN)Declaration*$(RPAREN): Assertion `fd $(AMP)$(AMP) fd->inferRetType` failed.) +$(LI $(BUGZILLA 4423): [tdpl] enums of struct types) +$(LI $(BUGZILLA 4757): A forward reference error with return of inner defined struct) +$(LI $(BUGZILLA 4791): Assigning a static array to itself should be allowed) +$(LI $(BUGZILLA 5030): Operators don't work with AssociativeArray!$(LPAREN)T1,T2$(RPAREN)) +$(LI $(BUGZILLA 5095): Error for typesafe variadic functions for structs) +$(LI $(BUGZILLA 5498): wrong common type deduction for array of classes) +$(LI $(BUGZILLA 5635): Code inside 'foreach' using opApply cannot modify variable out of its scope in a template function.) +$(LI $(BUGZILLA 5810): Struct postincrement generates 'no effect' error if used on struct member) +$(LI $(BUGZILLA 5835): `TypeInfo_Array.getHash` creates raw data hash instead using array element hash function) +$(LI $(BUGZILLA 5854): Built-in array sort doesn't sort SysTime correctly) +$(LI $(BUGZILLA 6140): Wrong ambiguity error with overloading) +$(LI $(BUGZILLA 6359): Pure/@safe-inference should not be affected by __traits$(LPAREN)compiles$(RPAREN)) +$(LI $(BUGZILLA 6430): Overloaded auto-return functions each with a nested aggregate of the same name are conflated) +$(LI $(BUGZILLA 6677): static this attributes position) +$(LI $(BUGZILLA 6889): "finally" mentioned in a compilation error, instead of "scope$(LPAREN)exit$(RPAREN)" or "scope$(LPAREN)success$(RPAREN)") +$(LI $(BUGZILLA 7019): implicit constructors are inconsistently allowed) +$(LI $(BUGZILLA 7209): Stack overflow on explicitly typed enum circular dependency) +$(LI $(BUGZILLA 7469): template mangling depends on instantiation order) +$(LI $(BUGZILLA 7477): Enum structs without specified values) +$(LI $(BUGZILLA 7870): Shared library support for Linux is missing) +$(LI $(BUGZILLA 7887): [CTFE] can't assign to returned reference) +$(LI $(BUGZILLA 8100): [ICE] with templated subclassing) +$(LI $(BUGZILLA 8236): Wrong error message in creating struct from vector operation) +$(LI $(BUGZILLA 8254): nested struct cannot access the types of the parent's fields) +$(LI $(BUGZILLA 8269): The 'with statement' does not observe temporary object lifetime) +$(LI $(BUGZILLA 8296): @disable this propagates through reference) +$(LI $(BUGZILLA 8309): ICE in typeMerge on 'void main$(LPAREN)$(RPAREN){auto x = [$(LPAREN)$(RPAREN)=>1.0, $(LPAREN)$(RPAREN)=>1];}') +$(LI $(BUGZILLA 8370): invalid deprecation error with -release -inline -noboundscheck) +$(LI $(BUGZILLA 8373): IFTI fails on overloading of function vs non function template) +$(LI $(BUGZILLA 8392): DMD sometime fail when using a non static function template within a function template) +$(LI $(BUGZILLA 8499): ICE on undefined identifier) +$(LI $(BUGZILLA 8596): Indeterministic assertion failure in rehash) +$(LI $(BUGZILLA 8704): Invalid nested struct constructions should be detected) +$(LI $(BUGZILLA 8738): Struct literal breaks assigment ordering) +$(LI $(BUGZILLA 9245): [CTFE] postblit not called on static array initialization) +$(LI $(BUGZILLA 9596): Ambiguous match is incorrectly hidden by additional lesser match) +$(LI $(BUGZILLA 9708): inout breaks zero parameter IFTI) +$(LI $(BUGZILLA 9931): Mac OS X ABI not followed when returning structs for extern $(LPAREN)C$(RPAREN)) +$(LI $(BUGZILLA 10054): x86_64 valgrind reports unrecognised instruction $(LPAREN)DMD 2.062$(RPAREN)) +$(LI $(BUGZILLA 10071): 'real' alignment wrong on several platforms) +$(LI $(BUGZILLA 10112): Mangle, which defined by pragma$(LPAREN)mangle$(RPAREN) should not be mangled by backend.) +$(LI $(BUGZILLA 10133): ICE for templated static conditional lambda) +$(LI $(BUGZILLA 10169): duplicate error message: member is not accessible) +$(LI $(BUGZILLA 10219): Implicit conversion between delegates returning a class and an interface) +$(LI $(BUGZILLA 10366): Ddoc: Symbols in template classes don't get fully qualified anchors) +$(LI $(BUGZILLA 10629): [ICE]$(LPAREN)dt.c 106$(RPAREN) with void array) +$(LI $(BUGZILLA 10658): Cannot merge template overload set by using alias declaration) +$(LI $(BUGZILLA 10703): Front-end code removal "optimisation" with try/catch blocks produces wrong codegen) +$(LI $(BUGZILLA 10908): Links in d.chm file are broken) +$(LI $(BUGZILLA 10928): Fails to create closures that reference structs with dtor) +$(LI $(BUGZILLA 10985): Compiler doesn't attempt to inline non-templated functions from libraries $(LPAREN)even having the full source$(RPAREN)) +$(LI $(BUGZILLA 11066): Spurious warning 'statement is not reachable' with -profile) +$(LI $(BUGZILLA 11177): parameterized enum can't be typed) +$(LI $(BUGZILLA 11181): Missing compile-time error for wrong array literal) +$(LI $(BUGZILLA 11201): ICE: $(LPAREN)symbol.c$(RPAREN) -inline stops compilation) +$(LI $(BUGZILLA 11333): ICE: Cannot subtype 0-tuple with "alias this") +$(LI $(BUGZILLA 11421): Dynamic array of associative array literal type inference) +$(LI $(BUGZILLA 11448): `dup` calls @system impure code from @safe pure function) +$(LI $(BUGZILLA 11453): Compiling packages has a dependency on order of modules passed to the compiler.) +$(LI $(BUGZILLA 11511): DDoc - C variadic parameters cannot be properly documented) +$(LI $(BUGZILLA 11535): CTFE ICE on reassigning a static array initialized with block assignment) +$(LI $(BUGZILLA 11542): scope$(LPAREN)failure$(RPAREN) messes up nothrow checking) +$(LI $(BUGZILLA 11543): multiple definition of std.regex with shared library) +$(LI $(BUGZILLA 11545): Aggregate function literal member should not have access to enclosing scope) +$(LI $(BUGZILLA 11550): [ICE] Checking if std.conv.to compiles with an array of non-builtins results in an ICE in s2ir.c.) +$(LI $(BUGZILLA 11622): Assertion failure in totym$(LPAREN)$(RPAREN), glue.c, line 1288) +$(LI $(BUGZILLA 11672): default initialization of static array of structs with a single value fails) +$(LI $(BUGZILLA 11677): user defined attributes must be first) +$(LI $(BUGZILLA 11678): user defined attributes cannot appear as postfixes) +$(LI $(BUGZILLA 11679): user defined attributes not allowed for local auto declarations) +$(LI $(BUGZILLA 11680): user defined attributes for type inference) +$(LI $(BUGZILLA 11735): pragma$(LPAREN)msg, ...$(RPAREN) fails to print wstring, dstring) +$(LI $(BUGZILLA 11740): [64-bit] Struct with constructor incorrectly passed on stack to extern$(LPAREN)C++$(RPAREN) function) +$(LI $(BUGZILLA 11752): Make issues.dlang.org work) +$(LI $(BUGZILLA 11774): Lambda argument to templated function changes its signature forever) +$(LI $(BUGZILLA 11783): Make std.datetime unittesting faster) +$(LI $(BUGZILLA 11788): [x86] Valgrind unhandled instruction bytes: 0xC8 0x8 0x0 0x0) +$(LI $(BUGZILLA 11832): std.datetime: ddoc warnings) +$(LI $(BUGZILLA 11872): Support for overloaded template functions in with block) +$(LI $(BUGZILLA 11885): ICE$(LPAREN)s2ir.c 359$(RPAREN) with continuing a labeled ByLine $(LPAREN)range struct w/ dtor$(RPAREN) loop) +$(LI $(BUGZILLA 11889): std.container.Array.opIndex returns by value, resulting in perfect storm) +$(LI $(BUGZILLA 11901): real win64) +$(LI $(BUGZILLA 11906): Compiler assertion when comparing function pointers) +$(LI $(BUGZILLA 12009): local import and "unable to resolve forward reference" error) +$(LI $(BUGZILLA 12011): "Internal Compiler Error: Null field" on CTFE method call on .init) +$(LI $(BUGZILLA 12042): "CTFE internal error: Dotvar assignment" with template method and "with") +$(LI $(BUGZILLA 12057): [ICE], backend/cg87.c 925) +$(LI $(BUGZILLA 12063): No line number error on uninitialized enum member if base type is not incrementable) +$(LI $(BUGZILLA 12077): Instantiated type does not match to the specialized alias parameter) +$(LI $(BUGZILLA 12078): forward reference issue with is$(LPAREN)$(RPAREN) and curiously recurring template pattern) +$(LI $(BUGZILLA 12110): [CTFE] Error: CTFE internal error: Dotvar assignment) +$(LI $(BUGZILLA 12138): Label statement creates an unexpected scope block) +$(LI $(BUGZILLA 12143): Base class is forward referenced) +$(LI $(BUGZILLA 12164): Function returning ptrdiff_t.min in 64-bit returning 0 when -O is set.) +$(LI $(BUGZILLA 12212): Static array assignment makes slice implicitly) +$(LI $(BUGZILLA 12231): ICE on the class declaration within lambda inside template constraint) +$(LI $(BUGZILLA 12235): ICE on printing mangled name of forward reference lambda by pragma$(LPAREN)msg$(RPAREN)) +$(LI $(BUGZILLA 12236): Inconsistent mangleof result) +$(LI $(BUGZILLA 12237): Inconsistent behavior of the instantiating enclosing template function) +$(LI $(BUGZILLA 12263): Specialized template parameter incorrectly fail to match to the same name template.) +$(LI $(BUGZILLA 12278): __traits$(LPAREN)classInstanceSize$(RPAREN) returns wrong value if used before class is declared) +$(LI $(BUGZILLA 12287): infinite loop on std.traits.moduleName on templated struct member) +$(LI $(BUGZILLA 12292): Template specialization ": string" passes for static arrays of other types) +$(LI $(BUGZILLA 12302): Assertion failure in expression.c $(LPAREN)line 432$(RPAREN) when using template isCallable) +$(LI $(BUGZILLA 12306): Struct Enums cannot be read at compile time) +$(LI $(BUGZILLA 12307): Contextfull error diagnostic about AA key type) +$(LI $(BUGZILLA 12313): Unneeded stack temporaries created by tuple foreach) +$(LI $(BUGZILLA 12334): Cannot access frame pointer of nested class from inside lambda) +$(LI $(BUGZILLA 12350): Assigning __traits$(LPAREN)getAttributes$(RPAREN) to variable crashes DMD) +$(LI $(BUGZILLA 12362): dmd hangs when attempting to use undefined enum) +$(LI $(BUGZILLA 12378): Compiler accepts any syntactically-valid code inside double-nested map predicate) +$(LI $(BUGZILLA 12392): No attribute inference if first template instantiation uses `alias`) +$(LI $(BUGZILLA 12397): CTFE ICE CompiledCtfeFunction::walkAllVars with 2.065) +$(LI $(BUGZILLA 12432): Diagnostic on argument count mismatch for ranges and opApply should improve) +$(LI $(BUGZILLA 12436): Opaque struct parameter type should not be allowed) +$(LI $(BUGZILLA 12460): Crash with goto and static if) +$(LI $(BUGZILLA 12476): Assert error in interpret.c:3204) +$(LI $(BUGZILLA 12480): static assert should print out the string representation of a value it can interpret) +$(LI $(BUGZILLA 12498): ICE: while$(LPAREN)string$(RPAREN) causes compiler to crash during CTFE) +$(LI $(BUGZILLA 12499): tuple/TypeTuple 1-Arg initialization fails during CTFE.) +$(LI $(BUGZILLA 12503): Bad optimization with scope$(LPAREN)success$(RPAREN) and return statement) +$(LI $(BUGZILLA 12506): Wrongly private lambda to define global immutable array) +$(LI $(BUGZILLA 12508): Codegen bug for interface type covariant return with lambda type inference) +$(LI $(BUGZILLA 12523): wrong foreach argument type with ref and inout) +$(LI $(BUGZILLA 12524): wrong type with inout const arg and inout return) +$(LI $(BUGZILLA 12528): [CTFE] cannot append elements from one inout array to another inout array) +$(LI $(BUGZILLA 12534): ICE on using expression tuple as type tuple) +$(LI $(BUGZILLA 12539): Compiler crash when looking up a nonexistent tuple element in an associative array) +$(LI $(BUGZILLA 12542): No function attribute inference for recursive functions) +$(LI $(BUGZILLA 12543): Class.sizeof requires the Class' definition) +$(LI $(BUGZILLA 12555): Incorrect error ungagging for speculatively instantiated class) +$(LI $(BUGZILLA 12571): __traits$(LPAREN)parent$(RPAREN) should work for typed manifest constant in initializer) +$(LI $(BUGZILLA 12577): ice on compile time struct field access) +$(LI $(BUGZILLA 12586): redundant error messages for tuple index exceeding) +$(LI $(BUGZILLA 12602): [CTFE] Changes to an array slice wrapped in a struct do not propogate to the original) +$(LI $(BUGZILLA 12604): No "mismatched array lengths" error with narrowing conversions) +$(LI $(BUGZILLA 12622): Purity, @safe not checked for pointers to functions) +$(LI $(BUGZILLA 12630): @nogc should recognize compile-time evaluation context) +$(LI $(BUGZILLA 12640): Error inside a switch statement causes a spurious switch case fallthrough warning) +$(LI $(BUGZILLA 12642): Avoid some heap allocation cases for fixed-size arrays) +$(LI $(BUGZILLA 12651): TemplateArgsOf accepts nonsensical arguments) +$(LI $(BUGZILLA 12660): Wrong non-@nogc function invariant error) +$(LI $(BUGZILLA 12673): ICE with static assert and __traits$(LPAREN)compiles$(RPAREN) with non-existent symbol) +$(LI $(BUGZILLA 12677): Assertion failure: 'isCtfeValueValid$(LPAREN)newval$(RPAREN)' on line 6579 in file 'interpret.c') +$(LI $(BUGZILLA 12678): Field constness missing in diagnostics for multiple field initialization error) +$(LI $(BUGZILLA 12686): Struct invariant prevents NRVO) +$(LI $(BUGZILLA 12688): Strange error if function call is in parentheses) +$(LI $(BUGZILLA 12704): typeof function literal incorrectly infers attributes) +$(LI $(BUGZILLA 12705): @system is missing when using getFunctionAttributes on a typeof$(LPAREN)function$(RPAREN)) +$(LI $(BUGZILLA 12706): ddoc: __dollar should not appear in the documentation) +$(LI $(BUGZILLA 12725): IFTI should consider instantiated types with dependent template parameters) +$(LI $(BUGZILLA 12737): static constructor requires call of super constructor) +$(LI $(BUGZILLA 12739): Foreach delegate to opApply does not have infered nothrow) +$(LI $(BUGZILLA 12745): [Ddoc] Underscore is removed from numbers in document comments) +$(LI $(BUGZILLA 12746): Wrong overload access within manually aliased eponymous function template) +$(LI $(BUGZILLA 12749): Constructor-local function allows multiple mutation of immutable member) +$(LI $(BUGZILLA 12756): Cannot build dmd on windows because of longdouble) +$(LI $(BUGZILLA 12777): const/immutable member function violating its const-ness - confusing error message) +$(LI $(BUGZILLA 12778): Aliasing opBinaryRight to opBinary works only in certain cases) +$(LI $(BUGZILLA 12788): -di doesn't warn about implicit conversion from char[] to char*) +$(LI $(BUGZILLA 12809): More strict nothrow check for try-finally statement) +$(LI $(BUGZILLA 12820): DMD can inline calls to functions that use alloca, allocating the memory in the caller function instead.) +$(LI $(BUGZILLA 12825): Invalid "duplicated union initialization" error with initialized field in extern$(LPAREN)C++$(RPAREN) class) +$(LI $(BUGZILLA 12826): Win64: bad code for x ~= x;) +$(LI $(BUGZILLA 12833): switch statement does not work properly when -inline used) +$(LI $(BUGZILLA 12836): CTFE ICE CompiledCtfeFunction::walkAllVars) +$(LI $(BUGZILLA 12838): Dmd show ICEs when using Tuple and wrong type) +$(LI $(BUGZILLA 12841): ICE on taking function address) +$(LI $(BUGZILLA 12849): pmovmskb instruction cannot store to 64-bit registers) +$(LI $(BUGZILLA 12850): ICE when passing associative array to template) +$(LI $(BUGZILLA 12851): ICE when passing const static array to template) +$(LI $(BUGZILLA 12852): 64 bit wrong code generated) +$(LI $(BUGZILLA 12855): Shadow register assignments for spilling can conflict) +$(LI $(BUGZILLA 12873): Valgrind unhandled instruction bytes 0x48 0xDB $(LPAREN)redundant REX_W prefix on x87 load$(RPAREN)) +$(LI $(BUGZILLA 12874): Wrong file name in range violation error) +$(LI $(BUGZILLA 12876): Implicit cast of array slice to fixed-size array for templates too) +$(LI $(BUGZILLA 12901): `in`/`out` contracts on struct constructor must require function body) +$(LI $(BUGZILLA 12902): [ICE] Assertion failure '!ae->lengthVar' in 'expression.c' when using `opDollar`) +$(LI $(BUGZILLA 12907): [ICE] Assertion failure '0' in 'mangle.c' when using `auto` return type with lambda with dereferanced `function` call) +$(LI $(BUGZILLA 12909): [AA] Function is incorrectly inferred as strongly pure for associative array with key of non-mutable array or pointer as argument) +$(LI $(BUGZILLA 12928): Bounds check dropped for array[length]) +$(LI $(BUGZILLA 12933): [D1] ICE with default __FILE__ and __LINE__) +$(LI $(BUGZILLA 12934): Strange newly implemented VRP behavior on foreach) +$(LI $(BUGZILLA 12937): ICE with void static array initializing) +$(LI $(BUGZILLA 12938): Error message mistake in out parameter with @disable this) +$(LI $(BUGZILLA 12953): Wrong alignment number in error messages) +$(LI $(BUGZILLA 12962): osver.mak should use isainfo on Solaris to determine model) +$(LI $(BUGZILLA 12965): DMD sets ELFOSABI to ELFOSABI_LINUX on all systems) +$(LI $(BUGZILLA 12968): DMD inline asm outputs wrong XCHG instruction) +$(LI $(BUGZILLA 12970): Enclosing @system attribute is precedence than postfix @safe) +$(LI $(BUGZILLA 13003): Lack of read-modify-write operation check on shared object field) +$(LI $(BUGZILLA 13011): inout delegate parameter cannot receive exactly same type argument) +$(LI $(BUGZILLA 13023): optimizer produces wrong code for comparision and division of ulong) +$(LI $(BUGZILLA 13043): Redundant linking to TypeInfo in non-root module) +$(LI $(BUGZILLA 13044): Assignment of structs with const members) +$(LI $(BUGZILLA 13045): TypeInfo.getHash should return consistent result with object equality by default) +$(LI $(BUGZILLA 13049): in template arguments the compiler fails to parse scope for function pointers arguments) +$(LI $(BUGZILLA 13050): pragma mangle breaks homonym template aliasing) +$(LI $(BUGZILLA 13082): Spurious error message with failed call to class ctor) +$(LI $(BUGZILLA 13088): Compiler segfaults with trivial case code.) +$(LI $(BUGZILLA 13089): Spurious 'is not nothrow' error on static array initialization) +$(LI $(BUGZILLA 13109): -run and -lib dmd flags conflict) +$(LI $(BUGZILLA 13116): Should not be able to return ref to 'this') +$(LI $(BUGZILLA 13131): [2.066-b3] dmd: glue.c:1492: unsigned int totym$(LPAREN)Type*$(RPAREN): Assertion `0` failed.) +$(LI $(BUGZILLA 13135): IFTI fails on partially qualified argument in some cases) +$(LI $(BUGZILLA 13142): Enums on different classes confuse the compiler) +$(LI $(BUGZILLA 13161): Wrong offset of extern$(LPAREN)C++$(RPAREN) class member) +$(LI $(BUGZILLA 13175): [D1] ICE on conflicting overloads in presense of default __FILE__/__LINE__) +$(LI $(BUGZILLA 13182): extern$(LPAREN)C++$(RPAREN) classes cause crash when allocated on the stack with scope) +$(LI $(BUGZILLA 13190): Optimizer breaks comparison with zero) +$(LI $(BUGZILLA 13194): ICE when static class members initialized to void) +$(LI $(BUGZILLA 13195): Delete calls destructor but doesn't free) +$(LI $(BUGZILLA 13204): recursive alias declaration) +$(LI $(BUGZILLA 13212): Trailing Windows line endings not stripped from .ddoc macros) +$(LI $(BUGZILLA 13217): nothrow, template function and delegate: compilation error) +$(LI $(BUGZILLA 13225): [ICE] Access violation on invalid mixin template instantiation) +$(LI $(BUGZILLA 13226): Symbol is not accessible when using traits or mixin) +$(LI $(BUGZILLA 13230): std.variant.Variant Uses Deprecated .min Property in opArithmetic When T is a Floating Point Type) +$(LI $(BUGZILLA 13235): Wrong code on mutually recursive tuple type) +$(LI $(BUGZILLA 13260): [D1] ICE accessing non-existent aggregate member) +$(LI $(BUGZILLA 13273): ddoc can't handle \r in unittests and ESCAPES properly) +$(LI $(BUGZILLA 13275): Wrong di header generation on if and foreach statements) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 1553): foreach_reverse is allowed for delegates) +$(LI $(BUGZILLA 1673): Implement the isTemplate trait) +$(LI $(BUGZILLA 1952): Support a unit test handler) +$(LI $(BUGZILLA 2025): Inconsistent rules for instantiating templates with a tuple parameter) +$(LI $(BUGZILLA 2548): Array ops that return value to a new array should work.) +$(LI $(BUGZILLA 3882): Unused result of pure functions) +$(LI $(BUGZILLA 5070): Heap-allocated closures listing) +$(LI $(BUGZILLA 6798): Integrate overloadings for multidimentional indexing and slicing) +$(LI $(BUGZILLA 7747): Diagnostic should be informative for an inferred return type in a recursive call) +$(LI $(BUGZILLA 7961): Add support for C++ namespaces) +$(LI $(BUGZILLA 8101): Display candidate function overloads when function call fails) +$(LI $(BUGZILLA 9112): Uniform construction for built-in types) +$(LI $(BUGZILLA 9570): Wrong foreach index implicit conversion error) +$(LI $(BUGZILLA 9616): SortedRange should support all range kinds) +$(LI $(BUGZILLA 10018): Value range propagation for immutable variables) +$(LI $(BUGZILLA 11345): Optimize array literal to static array assignment to not allocate on GC heap) +$(LI $(BUGZILLA 11620): dmd json output should output enum values) +$(LI $(BUGZILLA 11819): Implement better diagnostics for unrecognized traits) +$(LI $(BUGZILLA 12232): The result of pointer arithmetic on unique pointers should be a unique pointer) +$(LI $(BUGZILLA 12273): 'dmd -color' flag to colorize error/warning messages) +$(LI $(BUGZILLA 12280): Redundant "template instance ... error instantiating" messages) +$(LI $(BUGZILLA 12290): IFTI should consider implicit conversions of the literal arguments) +$(LI $(BUGZILLA 12310): [CTFE] Support heap allocation for built-in scalar types) +$(LI $(BUGZILLA 12352): Consistently stop encoding return type of parent functions) +$(LI $(BUGZILLA 12550): Deprecate -noboundscheck and replace with more useful -boundscheck= option) +$(LI $(BUGZILLA 12598): Poor diagnostic with local import hijacking) +$(LI $(BUGZILLA 12606): Mismatch of known array length during dynamic => static array assignment should emit better diagnostics) +$(LI $(BUGZILLA 12641): D1: __FILE__ and __LINE__ default argument behaviour) +$(LI $(BUGZILLA 12653): Add the getFunctionAttributes trait) +$(LI $(BUGZILLA 12681): Rewrite rule prevents unique detection) +$(LI $(BUGZILLA 12798): constant folding should optimize subsequent concatenations) +$(LI $(BUGZILLA 12802): Allow optional 'StorageClasses' for new alias syntax) +$(LI $(BUGZILLA 12821): Missed redundant storage class / protection errors.) +$(LI $(BUGZILLA 12932): Support @nogc for immediately iterated array literal) +$(LI $(BUGZILLA 12967): Prefix method 'this' qualifiers should be disallowed in DeclDefs scope) +$(LI $(BUGZILLA 13001): Support VRP for ternary operator $(LPAREN)CondExp$(RPAREN)) +$(LI $(BUGZILLA 13138): add peek/poke as compiler intrinsics) +$(LI $(BUGZILLA 13277): The base class in the JSON output is always unqualified) +$(LI $(BUGZILLA 13281): Print type suffix of real/complex literals in pragma$(LPAREN)msg$(RPAREN) and error diagnostic) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 12332): std.json API broken without notice) +$(LI $(BUGZILLA 12375): Writeln of a char plus a fixed size array of chars) +$(LI $(BUGZILLA 12394): Regression: std.regex unittests take agonizingly long to run - like hours on OSX) +$(LI $(BUGZILLA 12428): Regression $(LPAREN)2.066 git-head$(RPAREN): toUpper is corrupting input data $(LPAREN)modifying immutable strings$(RPAREN)) +$(LI $(BUGZILLA 12455): [uni][reg] Bad lowercase mapping for 'LATIN CAPITAL LETTER I WITH DOT ABOVE') +$(LI $(BUGZILLA 12494): Regression $(LPAREN)2.064$(RPAREN): to!string$(LPAREN)enum$(RPAREN) returns incorrect value) +$(LI $(BUGZILLA 12505): Null pointers are pretty-printed even when hex output is requested) +$(LI $(BUGZILLA 12713): [REG 2.066A] std.regex.regex crashes with SEGV, illegal instruction resp. assertion failure with certain bad input) +$(LI $(BUGZILLA 12859): Read-modify-write operation for shared variable in Phobos) +$(LI $(BUGZILLA 13076): [dmd 2.066-b2] DList clearing of empty list) +$(LI $(BUGZILLA 13098): std.path functions no longer works with DirEntry) +$(LI $(BUGZILLA 13181): install target broken) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 1452): std.cstream doc incorrect - imports of stream and stdio are not public) +$(LI $(BUGZILLA 1726): std.stream FileMode documentation problems) +$(LI $(BUGZILLA 3054): multithreading GC problem. And Stdio not multithreading safe) +$(LI $(BUGZILLA 3363): std.stream.readf segfaults with immutable format strings) +$(LI $(BUGZILLA 3484): std.socket.Address hierarchy not const-safe) +$(LI $(BUGZILLA 4330): std.range.transposed$(LPAREN)$(RPAREN) should be documented) +$(LI $(BUGZILLA 4600): writeln$(LPAREN)$(RPAREN) is not thread-safe) +$(LI $(BUGZILLA 5177): std.socketstream's close$(LPAREN)$(RPAREN) should call super.close$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 5538): Immutable classes can't be passed as messages in std.concurrency) +$(LI $(BUGZILLA 5870): Debug code in SortedRange assumes it can always print the range) +$(LI $(BUGZILLA 6644): std.stdio write/writef$(LPAREN)ln$(RPAREN) are not @trusted) +$(LI $(BUGZILLA 6791): std.algorithm.splitter random indexes utf strings) +$(LI $(BUGZILLA 6998): std.container.Array destroys class instances) +$(LI $(BUGZILLA 7246): Provide a simpler example for std.algorithm.remove) +$(LI $(BUGZILLA 7289): Document how std.format handles structs, unions, and hashes.) +$(LI $(BUGZILLA 7693): Getopt Ignores Trailing Characters on Enums) +$(LI $(BUGZILLA 7767): Unstable sort - slow performance cases) +$(LI $(BUGZILLA 7822): lseek cast$(LPAREN)int$(RPAREN)offset should be lseek cast$(LPAREN)off_t$(RPAREN)offset) +$(LI $(BUGZILLA 7924): reduce does not work with immutable/const as map and filter do) +$(LI $(BUGZILLA 8086): std.stdio is underdocumented) +$(LI $(BUGZILLA 8590): Documentation for "any" and "all" in std.algorithm is incorrect) +$(LI $(BUGZILLA 8721): std.algorithm.remove problem) +$(LI $(BUGZILLA 8730): writeln stops on a nul character, even if passed a D string) +$(LI $(BUGZILLA 8756): Add link to location of curl static library) +$(LI $(BUGZILLA 8764): chunks.transposed causes infinite ranges.) +$(LI $(BUGZILLA 8866): Splitter$(LPAREN)R1, R2$(RPAREN) CANNOT be bidirectional.) +$(LI $(BUGZILLA 8905): DList.Range: Internal error, inconsistent state) +$(LI $(BUGZILLA 8921): Enum arrays should be formatted properly) +$(LI $(BUGZILLA 9015): std.container.DList.opOpAssign missing return) +$(LI $(BUGZILLA 9016): swap$(LPAREN)$(RPAREN) doesn't work with std.container.DList.front and back) +$(LI $(BUGZILLA 9054): std.net.curl byLineAsync and byChunkAsync broken.) +$(LI $(BUGZILLA 9556): Missing underscore in docs for std.string.isNumeric) +$(LI $(BUGZILLA 9878): std.algorithm.cartesianProduct results order) +$(LI $(BUGZILLA 9975): pointsTo asserts because of false pointer in union) +$(LI $(BUGZILLA 10500): Problem with length property when using variant) +$(LI $(BUGZILLA 10502): Can't get fullyQualifiedName of a templated struct) +$(LI $(BUGZILLA 10693): cartesianProduct with over 7 ranges causes segfault at compile time) +$(LI $(BUGZILLA 10779): cartesianProduct leads to heavy code bloat) +$(LI $(BUGZILLA 10798): std.regex: ctRegex unicode set ops unimplemented) +$(LI $(BUGZILLA 10911): std.net.curl.HTTP: should allow user code to indicate content type of POST data) +$(LI $(BUGZILLA 10916): toHash on VariantN not being recognised) +$(LI $(BUGZILLA 10931): etc.c.zlib should properly annotate const parameters) +$(LI $(BUGZILLA 10948): BitArray.opEquals is invalid) +$(LI $(BUGZILLA 11017): std.string/uni.toLower is very slow) +$(LI $(BUGZILLA 11072): BitArray.opCmp is invalid on 64x) +$(LI $(BUGZILLA 11175): Format should support IUnknown classes) +$(LI $(BUGZILLA 11183): Win64: lrint yields bad results) +$(LI $(BUGZILLA 11184): Win64: killing process with invalid handle terimates current process) +$(LI $(BUGZILLA 11192): std.demangle doesn't demangle alias template arguments) +$(LI $(BUGZILLA 11253): std.algorithm.count is not nothrow) +$(LI $(BUGZILLA 11308): Don't use Voldemort types for std.process output) +$(LI $(BUGZILLA 11364): Variant fails to compile with const$(LPAREN)TypeInfo$(RPAREN).) +$(LI $(BUGZILLA 11608): Inadequate documentation for std.getopt.config.passThrough) +$(LI $(BUGZILLA 11698): readf doesn't compile with bool) +$(LI $(BUGZILLA 11705): std.typecons.Typedef is missing proper documentation) +$(LI $(BUGZILLA 11778): format for null does not verify fmt flags.) +$(LI $(BUGZILLA 11784): std.regex: bug in set intersection) +$(LI $(BUGZILLA 11825): An impossible memcpy at CTFE with cartesianProduct.array) +$(LI $(BUGZILLA 11834): std.net.curl: ddoc warnings) +$(LI $(BUGZILLA 11978): std.algorithm canFind uses "value" where it means "needle") +$(LI $(BUGZILLA 12007): cartesianProduct doesn't work with ranges of immutables) +$(LI $(BUGZILLA 12076): ctRegex range violation) +$(LI $(BUGZILLA 12148): std.uuid.parseUUID should document that it changes lvalue input data) +$(LI $(BUGZILLA 12157): Variant opEquals always returns false for classes.) +$(LI $(BUGZILLA 12169): sum$(LPAREN)int[]$(RPAREN) should return a int) +$(LI $(BUGZILLA 12183): using std.algorithm.sort makes valgrind abort) +$(LI $(BUGZILLA 12245): BinaryHeap exhibits quadratic performance in debug mode) +$(LI $(BUGZILLA 12297): std.typecons.Proxy does not properly forward IFTI calls) +$(LI $(BUGZILLA 12309): The template fullyQualifiedName returns wrong result) +$(LI $(BUGZILLA 12349): std.File.flush and error causes segfault after calling close) +$(LI $(BUGZILLA 12356): std.traits.isTypeTuple and isExpressionTuple are poorly documented) +$(LI $(BUGZILLA 12366): Range violation in compile-time regex) +$(LI $(BUGZILLA 12419): assertion failure in std.utf) +$(LI $(BUGZILLA 12434): std.algorithm.sum of immutable array too) +$(LI $(BUGZILLA 12449): Undefined format in std.algorithm.max) +$(LI $(BUGZILLA 12464): DMD/Phobos cannot auto-implement D variadic methods) +$(LI $(BUGZILLA 12477): std.bitmanip should emit informative diagnostics) +$(LI $(BUGZILLA 12557): std.numeric.gcd documentation reports Euler's algorithm, but it uses Euclid's algorithm) +$(LI $(BUGZILLA 12568): std.functional.memoize with constant array argument too) +$(LI $(BUGZILLA 12569): Better error message for std.algorithm.reduce used with two functions and a scalar seed) +$(LI $(BUGZILLA 12582): Non-existant named capture groups cause runtime range violation or segmentation fault in regex) +$(LI $(BUGZILLA 12600): Variant should support coercion to bool) +$(LI $(BUGZILLA 12608): Dead assignment in UUIDParsingException) +$(LI $(BUGZILLA 12609): Useless variable assignment in std.regex) +$(LI $(BUGZILLA 12643): @nogc std.range.dropOne) +$(LI $(BUGZILLA 12668): std.traits.functionAttributes should use the new getFunctionAttributes trait) +$(LI $(BUGZILLA 12691): std.regex.bmatch bug in empty OR operator inside of $(LPAREN)$(RPAREN)*) +$(LI $(BUGZILLA 12731): Infinite range slices are not themselves sliceable) +$(LI $(BUGZILLA 12747): std.regex bug in the parser allows reference to open groups.) +$(LI $(BUGZILLA 12771): opIndex on static arrays in a Variant is not implemented.) +$(LI $(BUGZILLA 12781): process.d: "Executable file not found" is supposed to show executable name but fails) +$(LI $(BUGZILLA 12796): std.string toLower/toUpper array conversion.) +$(LI $(BUGZILLA 12806): Does std.traits.isArray include associative arrays?) +$(LI $(BUGZILLA 12828): Fix SimpleTimeZone.utcOffset so that it has the correct return type) +$(LI $(BUGZILLA 12846): Phobos git HEAD: std.datetime spewing out tons of deprecation messages) +$(LI $(BUGZILLA 12853): std.encoding EncodingSchemeUtf16Native and EncodingSchemeUtf32Native decode$(LPAREN)$(RPAREN) and SafeDecode$(LPAREN)$(RPAREN) wrong stripping length) +$(LI $(BUGZILLA 12875): [unittest] std.datetime fails: Not a valid tzdata file.) +$(LI $(BUGZILLA 12898): `std.process.browse` expects URL to be encoded in CP_ACP on Windows instead of UTF-8) +$(LI $(BUGZILLA 12921): Module std.getopt does not respect property syntax) +$(LI $(BUGZILLA 12923): UTF exception in stride even though passes validate.) +$(LI $(BUGZILLA 12996): SList: linearRemove cannot remove root node) +$(LI $(BUGZILLA 13000): Casts should be removed to utilize features of inout) +$(LI $(BUGZILLA 13068): std.typecons.Unique should disable postblit) +$(LI $(BUGZILLA 13100): std.process.setCLOEXEC$(LPAREN)$(RPAREN) throws on invalid file descriptor) +$(LI $(BUGZILLA 13151): std.range.take template constraint ambiguity) +$(LI $(BUGZILLA 13163): std.conv.parse misses overflow when it doesn't result in a smaller value) +$(LI $(BUGZILLA 13171): std.algorithm.until$(LPAREN)range, sentinel, OpenRight.no$(RPAREN) doesn't propagate popping of sentinel to range) +$(LI $(BUGZILLA 13214): array.opSlice one element falsy empty) +$(LI $(BUGZILLA 13258): std.process file closing logic is incorrect) +$(LI $(BUGZILLA 13263): phobos/posix.mak has incorrect dependencies) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 3780): getopt improvements by Igor Lesik) +$(LI $(BUGZILLA 4725): std.algorithm.sum$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 4999): Add Kenji Hara's adaptTo$(LPAREN)$(RPAREN) to Phobos) +$(LI $(BUGZILLA 5175): Add a way to get parameter names to std.traits) +$(LI $(BUGZILLA 5228): Add GetOptException $(LPAREN)or similar$(RPAREN) to std.getopt) +$(LI $(BUGZILLA 5240): Faster std.random.uniform$(LPAREN)$(RPAREN) for [0.0, 1.0$(RPAREN) range) +$(LI $(BUGZILLA 5316): std.getopt: Add character-separated elements support for arrays and associative arrays) +$(LI $(BUGZILLA 5808): std.string.indexOf enhancement with start-at parameter) +$(LI $(BUGZILLA 6793): Document that assumeUnique may not be necessary in some contexts) +$(LI $(BUGZILLA 7146): enhance strip* $(LPAREN)implementation provided$(RPAREN)) +$(LI $(BUGZILLA 8278): std.range.chunks for generic Forward Ranges?) +$(LI $(BUGZILLA 8762): instanceOf trait for static conditionals) +$(LI $(BUGZILLA 9819): Allow access to named tuple's names.) +$(LI $(BUGZILLA 9942): Add a functional switch function) +$(LI $(BUGZILLA 10162): Opposite of std.string.representation) +$(LI $(BUGZILLA 11598): std.random.uniform could be faster for integrals) +$(LI $(BUGZILLA 11876): std.getopt: Implement --help and --help=option automatic printout) +$(LI $(BUGZILLA 12015): std.digest.sha256 too) +$(LI $(BUGZILLA 12027): Range of true bits for std.bitmanip.BitArray) +$(LI $(BUGZILLA 12173): Optional start value for std.algorithm.sum) +$(LI $(BUGZILLA 12184): Provide formating options for std.uni.InversionList) +$(LI $(BUGZILLA 12446): std.parallelism.amap prefer iteration to indexing) +$(LI $(BUGZILLA 12448): "in" argument for std.string.toStringz) +$(LI $(BUGZILLA 12479): replace "pointsTo" with "maybePointsTo" and "definitlyPointsTo") +$(LI $(BUGZILLA 12556): Add persistent byLine) +$(LI $(BUGZILLA 12566): Give DList true reference semantics) +$(LI $(BUGZILLA 12596): Implement Typedef ctor that can take itself as a parameter) +$(LI $(BUGZILLA 12633): std.conv.to should support target fixed-sized arrays) +$(LI $(BUGZILLA 12644): Some std.math functions are not yet @nogc) +$(LI $(BUGZILLA 12656): Some functions in std.ascii can be @nogc) +$(LI $(BUGZILLA 12671): std.complex abs and ^^ @nogc) +$(LI $(BUGZILLA 12784): Add an "in" operator for std.json.JSONValue) +$(LI $(BUGZILLA 12835): std.random.uniform with open lower bound cannot support smaller integral types or character types) +$(LI $(BUGZILLA 12877): std.random.uniform cannot handle dchar variates) +$(LI $(BUGZILLA 12886): std.datetime cannot parse HTTP date) +$(LI $(BUGZILLA 12890): std.array index based replace) +$(LI $(BUGZILLA 12957): std.algorithm.cartesianProduct is sometimes very slow to compile) +$(LI $(BUGZILLA 13013): Failed unittests in std.json - does not parse doubles correctly) +$(LI $(BUGZILLA 13022): std.complex lacks a function returning the squared modulus of a Complex) +$(LI $(BUGZILLA 13042): std.net.curl.SMTP doesn't send emails with libcurl-7.34.0 or newer) +$(LI $(BUGZILLA 13159): std.socket.getAddress allocates once per DNS lookup hit) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 12220): [REG2.066a] hash.get$(LPAREN)$(RPAREN) does not accept proper parameters) +$(LI $(BUGZILLA 12427): Regression $(LPAREN)2.066 git-head$(RPAREN): Building druntime fails with -debug=PRINTF) +$(LI $(BUGZILLA 12710): Bad @nogc requirement for Windows callbacks) +$(LI $(BUGZILLA 12738): core.sys.posix.signal sigaction_t handler type mismatch) +$(LI $(BUGZILLA 12848): [REG2.061] crash in _d_run_main$(LPAREN)$(RPAREN) on some unicode command line argument $(LPAREN)Win32$(RPAREN)) +$(LI $(BUGZILLA 13078): [dmd 2.066-b2] AA rehash failed with shared) +$(LI $(BUGZILLA 13084): ModuleInfo.opApply delegate expects immutable parameter) +$(LI $(BUGZILLA 13111): GC.realloc returns invalid memory for large reallocation) +$(LI $(BUGZILLA 13148): ModuleInfo fields are unnecessary changed to const) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 4323): std.demangle incorrectly handles template floating point numbers) +$(LI $(BUGZILLA 5892): Lazy evaluation of stack trace when exception is thrown) +$(LI $(BUGZILLA 7954): x86_64 Windows fibers do not save nonvolatile XMM registers) +$(LI $(BUGZILLA 8607): __simd and pcmpeq should be @safe pure nothrow) +$(LI $(BUGZILLA 9584): Exceptions in D are ludicrously slow $(LPAREN)far worse than Java$(RPAREN)) +$(LI $(BUGZILLA 10380): [AA] Wrong code using associative array as key type in associative array) +$(LI $(BUGZILLA 10897): btc, btr and bts shouldn't be safe) +$(LI $(BUGZILLA 11011): core.time.Duration has example code which cannot compile) +$(LI $(BUGZILLA 11037): [AA] AA's totally broken for struct keys with indirection) +$(LI $(BUGZILLA 11519): fix timing issue in core.thread unittest) +$(LI $(BUGZILLA 11761): aa.byKey and aa.byValue are not forward ranges) +$(LI $(BUGZILLA 12800): Fibers are broken on Win64) +$(LI $(BUGZILLA 12870): No x86_64 optimized implementation for float array ops) +$(LI $(BUGZILLA 12958): core.checkedint.mulu is broken) +$(LI $(BUGZILLA 12975): posix.mak should use isainfo on Solaris systems to determine model) +$(LI $(BUGZILLA 13057): posix getopt variables in core/sys/posix/unistd.d should be marked __gshared) +$(LI $(BUGZILLA 13073): Wrong uint/int array comparison) +) +$(BUGSTITLE Druntime enhancements, + +$(LI $(BUGZILLA 8409): Proposal: implement arr.dup in library) +$(LI $(BUGZILLA 12964): dev_t is incorrectly defined in runtime for Solaris systems) +$(LI $(BUGZILLA 12976): ModuleInfo should be immutable on Solaris) +$(LI $(BUGZILLA 12977): lf64 definitions aren't correct on Solaris) +$(LI $(BUGZILLA 12978): struct sigaction is too small on 32-bit solaris) +$(LI $(BUGZILLA 13037): SIGRTMIN and SIGRTMAX aren't correctly defined on Solaris) +$(LI $(BUGZILLA 13144): Add fenv support for Solaris) +$(LI $(BUGZILLA 13145): Need LC_ locale values for Solaris) +$(LI $(BUGZILLA 13146): Add missing function definitions from stdlib.h on Solaris) +) +$(BUGSTITLE Installer regressions, + +$(LI $(BUGZILLA 13004): /? option to cl.exe results in ICE) +$(LI $(BUGZILLA 13047): cannot stat `./icons/16/dmd-source.png`: No such file or directory) +$(LI $(BUGZILLA 13210): libphobos2.so not being built) +$(LI $(BUGZILLA 13233): Windows installer: downloading external installers $(LPAREN)Visual D/dmc$(RPAREN) does not work) +) +$(BUGSTITLE Installer bugs, + +$(LI $(BUGZILLA 3319): DInstaller overwrites the %PATH% variable) +$(LI $(BUGZILLA 5732): Windows installer creates incorrect target for Start menu link) +$(LI $(BUGZILLA 13149): released libphobos2.a is build with PIC code) +) +$(BUGSTITLE Website regressions, + +$(LI $(BUGZILLA 12813): Parser is confused between float and UFC syntax) +) +$(BUGSTITLE Website bugs, + +$(LI $(BUGZILLA 1497): Add a link to the DWiki debuggers page) +$(LI $(BUGZILLA 1574): DDoc documentation lacks macro examples) +$(LI $(BUGZILLA 3093): Object.factory has incomplete documentation) +$(LI $(BUGZILLA 4164): sieve Sample D Program -- need documentation for array representation) +$(LI $(BUGZILLA 6017): std.algorithm.remove has a wrong link) +$(LI $(BUGZILLA 7075): overloading opAssign for classes is poorly specified) +$(LI $(BUGZILLA 7459): Document the workarounds for mutually-called nested functions.) +$(LI $(BUGZILLA 8074): template-mixin example contradicts text) +$(LI $(BUGZILLA 8798): Tuple curry example not really curry) +$(LI $(BUGZILLA 9542): Broken link on std.range doc page) +$(LI $(BUGZILLA 10033): Wrong example in chapter Vector Extensions) +$(LI $(BUGZILLA 10231): Spec: Document typed alias parameter feature) +$(LI $(BUGZILLA 10297): Memory safe D spec is out of date) +$(LI $(BUGZILLA 10564): Errors on the Template page of the language specification) +$(LI $(BUGZILLA 10764): bug reporting / better linking to issue tracker / include resolved in default search) +$(LI $(BUGZILLA 10901): Win_64 Autotester KO'd) +$(LI $(BUGZILLA 11104): Document exact behavior of structsasd initialization inside AA) +$(LI $(BUGZILLA 11396): Function alias declaration not valid according to spec) +$(LI $(BUGZILLA 11462): std.algorithm.multiSort is missing from the index) +$(LI $(BUGZILLA 11638): Variadic function documentation, out-of-date example) +$(LI $(BUGZILLA 11846): Missing pragma/$(LPAREN)mangle$(RPAREN) documentation) +$(LI $(BUGZILLA 11867): Documentation for new package.d feature) +$(LI $(BUGZILLA 11917): Stale Phobos documentation pages found on site root) +$(LI $(BUGZILLA 11979): inout const is not documented) +$(LI $(BUGZILLA 12005): DDoc example refers to a dead project, yet a more recent one exists that is not mentioned.) +$(LI $(BUGZILLA 12241): Document change to static opCall in changelog) +$(LI $(BUGZILLA 12293): forward is missing from std.algorithm's cheat-sheet) +$(LI $(BUGZILLA 12459): Bugzilla logs users in only on https site, and does not redirect from http to https) +$(LI $(BUGZILLA 12526): DDox possible issue with case sensitive file names) +$(LI $(BUGZILLA 12535): The language introduction page is not linked from index) +$(LI $(BUGZILLA 12538): ZeroBUGS links are broken) +$(LI $(BUGZILLA 12607): Document that IUnknown classes must mark toString with extern$(LPAREN)D$(RPAREN) when overriding it) +$(LI $(BUGZILLA 12623): Special lexing case not mentioned in language spec) +$(LI $(BUGZILLA 12740): DMD accepts invalid version syntax) +$(LI $(BUGZILLA 13012): Open bugs chart is missing from https://dlang.org/bugstats.php) +) +$(BUGSTITLE Website enhancements, + +$(LI $(BUGZILLA 8103): Use case-insensitive sorting for Jump-to lists in the documentation) +$(LI $(BUGZILLA 12783): Adding 'Third Party Libraries' link to the navigation sidebar) +$(LI $(BUGZILLA 12858): Document opEquals usage in AAs) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.066.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.066.1.dd b/changelog/2.066.1.dd new file mode 100644 index 0000000000..6987d8ccfc --- /dev/null +++ b/changelog/2.066.1.dd @@ -0,0 +1,73 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION October 15, 2014, =================================================, + +$(BR)$(BIG List of all bug fixes in D 2.066.1.) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 11312): [REG2.063] Avoid auto-dereference for UFCS functions) +$(LI $(BUGZILLA 11946): need 'this' to access member when passing field to template parameter) +$(LI $(BUGZILLA 13294): [IFTI] IFTI fails or works incorrectly for function with const and mutable `ref` parameters of most types) +$(LI $(BUGZILLA 13299): [dmd-2.066-rc2] - Property not found with typesafe variadic opDispatch) +$(LI $(BUGZILLA 13303): Internal error: ..\ztc\cgcs.c 351 with rvalue Variant.get call) +$(LI $(BUGZILLA 13311): [REG2.065] ICE, CtorDeclaration::semantic$(LPAREN)Scope*$(RPAREN): Assertion `tf $(AMP)$(AMP) tf->ty == Tfunction` failed) +$(LI $(BUGZILLA 13321): Wrong goto skips declaration error) +$(LI $(BUGZILLA 13353): [REG2.066] [ICE] assertion with is$(LPAREN)$(RPAREN) and templated interface) +$(LI $(BUGZILLA 13374): Wrong template overload resolution when passing function to alias/string parameter) +$(LI $(BUGZILLA 13378): Wrong failure of template value parameter deduction in IFTI) +$(LI $(BUGZILLA 13379): Latest dmd fails with recursive template expansion in std.regex) +$(LI $(BUGZILLA 13394): invariant fail to link since 2.066 when using separate compilation) +$(LI $(BUGZILLA 13400): Linking problems with bigints and std.functional.memoize) +$(LI $(BUGZILLA 13415): [REG2.066] '-inline' causes wrong enclosing scope pointer for nested function called from templated struct) +$(LI $(BUGZILLA 13417): [REG2.066] segmentation fault when deduce template type) +$(LI $(BUGZILLA 13424): [REG2.066] Initialization of delegate to do-nothing default causes segfault at runtime) +$(LI $(BUGZILLA 13427): [REG2.066] cannot inline default argument alloca$(LPAREN)...$(RPAREN)) +$(LI $(BUGZILLA 13472): [REG2.066] trying to insert a null into an array of object segfaults the compiler) +$(LI $(BUGZILLA 13476): [REG2.065] Writing stubs for dynamically loaded functions no longer works. $(LPAREN)circular reference$(RPAREN)) +$(LI $(BUGZILLA 13478): [REG2.066] Templates not emitted when also referenced in speculative contexts) +$(LI $(BUGZILLA 13504): ICE$(LPAREN)backend/cgelem.c 2418$(RPAREN) with "-O -cov") +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 13235): Wrong code on mutually recursive tuple type) +$(LI $(BUGZILLA 13204): recursive alias declaration) +$(LI $(BUGZILLA 13333): Incorrect error ungagging during the resolution of forward references) +$(LI $(BUGZILLA 12503): Bad optimization with scope$(LPAREN)success$(RPAREN) and return statement) +$(LI $(BUGZILLA 13383): wrong code with -O with ints, longs and bitwise operations) +$(LI $(BUGZILLA 13413): dmd does not follow symlink when searching for dmd.conf) +$(LI $(BUGZILLA 13323): UDA applied to import statement causes compilation to fail without error) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 12567): Modules can't be marked as deprecated) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 13618): removing deprecated std.metastrings module breaks code) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 13313): std.datetime fails unittests on Windows) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 13399): va_arg is nothrow yet may throw) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 13377): core/sys/posix/syslog.d is in druntime/src but not in druntime/src/import) +$(LI $(BUGZILLA 13414): Static destructors not called correctly with dynamic loading) +) +$(BUGSTITLE Installer regressions, + +$(LI $(BUGZILLA 13233): Windows installer: downloading external installers $(LPAREN)Visual D/dmc$(RPAREN) does not work) +) +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.066.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.067.0.dd b/changelog/2.067.0.dd new file mode 100644 index 0000000000..ae29e815e1 --- /dev/null +++ b/changelog/2.067.0.dd @@ -0,0 +1,818 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 24, 2015, =================================================, + +$(BUGSTITLE Language Changes, +$(LI $(RELATIVE_LINK2 heap-struct-destructors, Destructors for structs allocated on the heap are now invoked.)) +$(LI $(RELATIVE_LINK2 asm-attributes, $(D asm) statements can now be used in $(D pure), $(D nothrow), $(D @nogc), or $(D @trusted) code.)) +$(LI $(RELATIVE_LINK2 package-protection, $(D package) protection attribute can be optionally bound to specified package)) +$(LI $(RELATIVE_LINK2 sealed-references, Sealed references were added $(LPAREN)DIP25$(RPAREN))) +$(LI $(RELATIVE_LINK2 with-statement-8269, The with statement now observes temporary object lifetime)) +) + +$(BUGSTITLE Library Changes, +$(LI $(RELATIVE_LINK2 faster-gc-1, The garbage collector got faster.)) +$(LI $(RELATIVE_LINK2 volatile-load-store, $(D volatileLoad) and $(D volatileStore) intrinsics were added.)) +$(LI $(RELATIVE_LINK2 gc-options, $(B Experimental:) The garbage collector can now be configured.)) +$(LI $(RELATIVE_LINK2 aa-keyvalue, $(D byKeyValue) was added.)) +$(LI $(REF_SHORT initOnce, std,concurrency) was added to perform thread-safe lazy initialization.) +$(LI $(RELATIVE_LINK2 std-range-enumerate, A new range algorithm $(D enumerate) was added to +attach indexes to range elements.)) +$(LI $(RELATIVE_LINK2 std-exception-handle, A new range algorithm $(D handle) was added to +enable exception handling in range compositions.)) +$(LI $(RELATIVE_LINK2 logger, An experimental logging system was added.)) +) + +$(BR)$(BIG $(RELATIVE_LINK2 list2067, List of all bug fixes and enhancements in D 2.067.)) + +$(HR) + +$(BUGSTITLE Language Changes, + +$(LI $(LNAME2 heap-struct-destructors, Destructors for structs allocated on the heap are now invoked.) + + $(P Previously, when a struct allocated on the heap was freed, the destructor was not + invoked. This is no longer the case, and these destructors will now be invoked + before the memory is freed by the GC. + ) +) + +$(LI $(LNAME2 asm-attributes, $(D asm) statements can now be used in $(D pure), $(D nothrow), $(D @nogc), or $(D @trusted) code.) + + $(P By adding the appropriate attributes to an asm statement you + can tell the compiler how that asm code behaves, thus allowing asm + statements to be used in pure, nothrow, @nogc, or @safe functions. + + --------- + asm pure nothrow @nogc @trusted + { + // the compiler does not check the attributes + ret; + } + --------- + ) +) + +$(LI $(LNAME2 package-protection, $(D package) protection attribute can be optionally bound to specified package) + + $(P New optional syntax was added for package protection attribute: + + -------- + module aaa.bbb.ccc.ddd; + + // accessible from any module with aaa.bbb in qualified path + package(aaa.bbb) void foo() {} + + // old style, means same as package(aaa.bbb.ccc) + package void bar() {} + --------- + ) +) + +$(LI $(LNAME2 sealed-references, Sealed references were added $(LPAREN)DIP25$(RPAREN)) + + $(P In $(D @safe) functions it is now required to use $(D return ref) to return a reference to a parameter or a field of it.) + + -------- + @safe: + ref int fun(ref int a) { return a; } // ERROR + ref int gun(return ref int a) { return a; } // FINE + ref T hun(T)(ref T a) { return a; } // FINE, templates use deduction + -------- + + $(P See $(LINK2 https://wiki.dlang.org/DIP25, DIP25) for more details.) +) + +$(LI $(LNAME2 with-statement-8269, The with statement now observes temporary object lifetime) + + $(P A longstanding $(LINK2 https://issues.dlang.org/show_bug.cgi?id=8269, bug) of the with statement was fixed which prevented the idiomatic use of $(LINK2 https://wiki.dlang.org/Commonly-Used_Acronyms,RAII) values.) + + -------- + with (File("output.log", "w")) + { + writeln("Content"); + } + // File is automatically closed + -------- +) + +) + +$(BUGSTITLE Library Changes, + +$(LI $(LNAME2 faster-gc-1, This release comes with various GC optimizations that make many applications faster.) + + $(P A new GC growth policy was implemented that helps to reduce the + number of collections by keeping a collection threshold at 2x the size + of the used memory. After each collection the used memory and the + threshold are recomputed. This allows for an exponential growth of the + GC heap, e.g. during program startup, but limits the heap size relative + to the actual used memory. + The factor 2x is configurable by setting $(RELATIVE_LINK2 gc-options, heapSizeFactor). + ) + + $(P The heap traversal during the marking phase is now done using tail + recursion with a separate compact state stack. This allows to mark very + deep heaps (lists) much faster because the previous recursion limit of + 50 is eliminated. + ) + + $(P You can see a list of all improvements $(LINK2 + https://github.com/dlang/druntime/pulls?q=is:merged+is:pr+label:GC+merged:2014-08-18..2015-03-01, + here).) + + GC benchmarks +) + +$(LI $(LNAME2 volatile-load-store, $(D volatileLoad) and $(D volatileStore) intrinsics were added.) + + $(P Calls to $(D volatileLoad) and $(D volatileStore) are recognized by + the compiler and guaranteed to not be removed or reordered in the same + thread. + + --------- + void example(uint* address, uint value) + { + import core.bitop; + + // store value + volatileStore(address, value); + + // wait until value takes affect + while (volatileLoad(address) != value) + { } + } + --------- + ) + + $(P $(B Note:) These intrinsics are currently in core.bitop$(COMMA) but will + be moved to core.volatile when $(D volatile) is no longer a keyword. + ) +) + +$(LI $(LNAME2 gc-options, $(B Experimental:) The garbage collector can now be configured through the command line, + the environment or by options embedded into the executable.) + + $(P By default, GC options can only be passed on the command line of the program + to run, e.g. + + --------- + app "--DRT-gcopt=profile:1 minPoolSize:16" arguments to app + --------- + ) + $(P Available GC options are: + $(UL + $(LI disable:0|1 - start disabled) + $(LI profile:0|1 - enable profiling with summary when terminating program) + $(LI initReserve:N - initial memory to reserve in MB) + $(LI minPoolSize:N - initial and minimum pool size in MB) + $(LI maxPoolSize:N - maximum pool size in MB) + $(LI incPoolSize:N - pool size increment MB) + $(LI heapSizeFactor:N - targeted heap size to used memory ratio) + ) + ) + $(P In addition, --DRT-gcopt=help will show the list of options and their current settings. + ) + $(P Command line options starting with "--DRT-" are filtered out before calling main, + so the program will not see them. They are still available via rt_args(). + ) + $(P Configuration via the command line can be disabled by declaring a variable for the + linker to pick up before using its default from the runtime: + --------- + extern(C) __gshared bool rt_cmdline_enabled = false; + --------- + ) + $(P Likewise, declare a boolean rt_envvars_enabled to enable configuration via the + environment variable "DRT_GCOPT: + --------- + extern(C) __gshared bool rt_envvars_enabled = true; + --------- + ) + $(P Setting default configuration properties in the executable can be done by specifying an + array of options named rt_options: + --------- + extern(C) __gshared string[] rt_options = [ "gcopt=initReserve:100 profile:1" ]; + --------- + ) + $(P Evaluation order of options is rt_options, then environment variables, then command + line arguments, i.e. if command line arguments are not disabled, they can override + options specified through the environment or embedded in the executable. + ) +) + +$(LI $(LNAME2 aa-keyvalue, $(D byKeyValue) was added.) + + $(P Built-in associative arrays now have a $(D .byKeyValue) method that + returns a forward range iterating over key/value pairs.) + + ------ + void main() + { + auto aa = ["a": 1]; + foreach (pair; aa.byKeyValue) + { + assert(pair.key == "a"); + assert(pair.value == 1); + } + } + ------ +) + +$(LI $(LNAME2 std-range-enumerate, $(D enumerate) was added.) + $(P $(REF_SHORT enumerate, std,range) enables iteration of ranges with an index variable:) + ------ + void main() + { + import std.stdio : stdin, stdout; + import std.range : enumerate; + + foreach (lineNum, line; stdin.byLine().enumerate(1)) + stdout.writefln("line #%s: %s", lineNum, line); + } + ------ +) + +$(LI $(LNAME2 std-exception-handle, $(D handle) was added.) + $(P $(REF_SHORT handle, std,exception) enables exception handling in range compositions:) + ------ + import std.algorithm : equal; + import std.range : retro; + import std.utf : UTFException; + + auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit + + auto handled = str.handle!(UTFException, RangePrimitive.access, + (e, r) => ' '); // Replace invalid code points with spaces + + assert(handled.equal("hello world")); // `front` is handled, + assert(handled.retro.equal("dlrow olleh")); // as well as `back` + ------ +) + +$(LI $(LNAME2 logger, An experimental logging system was added.) + +------ +import std.experimental.logger; + +void main() +{ + log("message logging in D"); +} +------ +) + +) + +$(BR)$(BIG $(LNAME2 list2067, List of all bug fixes and enhancements in D 2.067:)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 4890): GC.collect$(LPAREN)$(RPAREN) deadlocks multithreaded program.) +$(LI $(BUGZILLA 12381): [REG2.065] [ICE] An internal error in e2ir.c while casting array ops) +$(LI $(BUGZILLA 12422): [REG2.055] Templated nested function is inferred as `pure` even if it calls impure functions) +$(LI $(BUGZILLA 12912): Lambda function is incorrectly inferred as impure if it uses member field or function) +$(LI $(BUGZILLA 13009): [REG2.064] inout overload conflicts with non-inout when used via alias this) +$(LI $(BUGZILLA 13311): [REG2.065] ICE, CtorDeclaration::semantic$(LPAREN)Scope*$(RPAREN): Assertion `tf $(AMP)$(AMP) tf->ty == Tfunction' failed) +$(LI $(BUGZILLA 13479): [REG2.067a] Templates not emitted when instantiated in mixins mixed in functions) +$(LI $(BUGZILLA 13497): [REG2.065] [ICE e2ir 1911] Array op compiler error) +$(LI $(BUGZILLA 13498): Return type is not checked in function template) +$(LI $(BUGZILLA 13502): [REG2.065] Stray '$(LPAREN)' warning not emitted for documentation of enum templates) +$(LI $(BUGZILLA 13503): [REG2.065] Bad code with -inline, varargs and auto return) +$(LI $(BUGZILLA 13514): Druntime no longer builds with -g) +$(LI $(BUGZILLA 13515): [REG2.064] "Range violation" when writing to array of AAs from static this) +$(LI $(BUGZILLA 13550): [REG2.067a] Inner functions take outer function attributes erroneously) +$(LI $(BUGZILLA 13564): [REG2.065] nested struct destructor trying to access members of a global class fail to compile) +$(LI $(BUGZILLA 13601): [REG2.064] static if $(LPAREN)__ctfe$(RPAREN) should emit error) +$(LI $(BUGZILLA 13640): [REG2.066] can break immutability with inout) +$(LI $(BUGZILLA 13644): [REG2.066] ICE with foreach over array of Tuples) +$(LI $(BUGZILLA 13673): ICE$(LPAREN)backend/cod2.d 5114$(RPAREN)) +$(LI $(BUGZILLA 13675): enum type used with template causes compiler to segfault) +$(LI $(BUGZILLA 13694): Typesafe variadic function template overload fails to match to any template) +$(LI $(BUGZILLA 13714): [REG2.066.1] Assertion failure: '0' on line 2022 in file 'mtype.c') +$(LI $(BUGZILLA 13729): [REG2.067a] One not detected case of not purity) +$(LI $(BUGZILLA 13760): [REG2.067a] Cannot deduce function for object.get) +$(LI $(BUGZILLA 13775): [REG2.067a] Broken explicit casting of dynamic array slices of known size to static array of different type) +$(LI $(BUGZILLA 13776): [REG2.067a] Incorrect "recursive alias declaration" error with `__traits$(LPAREN)compiles, ...$(RPAREN)`) +$(LI $(BUGZILLA 13807): [REG2.067a] inout$(LPAREN)T$(RPAREN)[] no longer matches string[]) +$(LI $(BUGZILLA 13827): [REG2.067a] Internal Compiler Error: null field) +$(LI $(BUGZILLA 13840): [REG2.067a] nothrow attribute affects inside of try-catch block when using foreach with opApply) +$(LI $(BUGZILLA 13864): [REG2.066] tuple expand causes range violation) +$(LI $(BUGZILLA 13873): 2.066.1 Compiling with -debug -inline generates huge files) +$(LI $(BUGZILLA 13886): [REG2.066] global.gaggedErrors ICE) +$(LI $(BUGZILLA 13921): ICE with template instantiation error) +$(LI $(BUGZILLA 13934): Cannot pass 'this' to function by reference) +$(LI $(BUGZILLA 13937): C++ mangling for template negative parameter not correct for dmc) +$(LI $(BUGZILLA 13942): [REG2.066] Bad template error message) +$(LI $(BUGZILLA 13950): [REG2.062] zero-length tuple does not work on function default argument) +$(LI $(BUGZILLA 13952): [REG2.067a] change in struct ctor lowering triggers codegen bug) +$(LI $(BUGZILLA 13966): [REG2.067a] dmd: expression.c:3761: size_t StringExp::length$(LPAREN)int$(RPAREN): Assertion `encSize == 1 || encSize == 2 || encSize == 4' failed.) +$(LI $(BUGZILLA 13968): [REG2.067a] constructing and returing union causes segfault) +$(LI $(BUGZILLA 13969): [REG2.063] [ICE] $(LPAREN)backend\cgcod.c 2309$(RPAREN) with cycle$(LPAREN)iota$(LPAREN)a,b,s$(RPAREN)$(RPAREN)) +$(LI $(BUGZILLA 13992): [REG2.067a] CTFE produces strange error with += operator on integer type) +$(LI $(BUGZILLA 13998): Wrong code with -O -inline, loops, and taking address of double) +$(LI $(BUGZILLA 13999): [REG2.067a] Associative array literal with static array keys must now have matching key lengths) +$(LI $(BUGZILLA 14038): [REG2.067a] Non-mutable AA initialization segfaults in runtime) +$(LI $(BUGZILLA 14039): [REG2.067a] function is incorrectly inferred as 'pure') +$(LI $(BUGZILLA 14044): dmd generates spurious functions in object file created from empty module) +$(LI $(BUGZILLA 14049): [REG2.064] Wrong purity inference for nested lambda) +$(LI $(BUGZILLA 14057): [REG2.066] opSlice not working correctly with AliasThis) +$(LI $(BUGZILLA 14061): Refused array concat at compile-time) +$(LI $(BUGZILLA 14074): [REG2.067a] non-separate compilation fails, but separate compilation works) +$(LI $(BUGZILLA 14075): [REG2.067a] Segfault with ambiguous overloading functions without body) +$(LI $(BUGZILLA 14089): [REG2.064] Assigning to AA has no value when overriding opAssign) +$(LI $(BUGZILLA 14090): [REG2.067a] Incorrect "recursive alias declaration") +$(LI $(BUGZILLA 14093): [REG2.065] __traits$(LPAREN)compiles, cast$(LPAREN)Object$(RPAREN)$(LPAREN)tuple$(RPAREN)$(RPAREN) is true even if it doesn't compile.) +$(LI $(BUGZILLA 14104): aa with pointer key type doesn't find existing value) +$(LI $(BUGZILLA 14106): sort is @safe in release mode, @system in debug mode) +$(LI $(BUGZILLA 14109): [REG2.066.1] Property-like function call does not work on template value parameter) +$(LI $(BUGZILLA 14126): GITHEAD - GC seemingly corrupting memory) +$(LI $(BUGZILLA 14130): [REG2.067a] ICE following error in template parameter default value) +$(LI $(BUGZILLA 14144): [REG2.067a] opAssign seems broken) +$(LI $(BUGZILLA 14146): [REG2.067a] ICE with non-empty default constructor in struct) +$(LI $(BUGZILLA 14155): [REG2.066] A defect in DIP29: the return value of some pure functions cannot be unique pointer) +$(LI $(BUGZILLA 14160): [REG2.066] mutable global data access is wrongly accepted in pure function) +$(LI $(BUGZILLA 14166): [REG2.066] Excess CTFE running for the temporary variable in module level expression) +$(LI $(BUGZILLA 14169): Template symbol visibility regression) +$(LI $(BUGZILLA 14173): [REG2.064] Omitting return type with override hides an error) +$(LI $(BUGZILLA 14177): [REG2.066.1] ICE$(LPAREN)statement.c$(RPAREN) recursive aliases) +$(LI $(BUGZILLA 14198): [REG2.067a] Link failure with Variant) +$(LI $(BUGZILLA 14199): [REG2.067a] Dwarf Error: mangled line number section) +$(LI $(BUGZILLA 14218): [REG2.067a] casting null to integer type causes error message) +$(LI $(BUGZILLA 14220): Bad codegen for optimized std.conv.text in combination with concatenation) +$(LI $(BUGZILLA 14232): redundant attribute 'const') +$(LI $(BUGZILLA 14235): [REG2.066] full-qualified template instantiation misses its error location) +$(LI $(BUGZILLA 14262): [REG] [2.067-b3] Can't use class `this` as ref argument) +$(LI $(BUGZILLA 14267): [REG2.067beta2] ICE when determining if a function can be inlined) +$(LI $(BUGZILLA 14283): [2.067-b4]: Spurious "this is not an lvalue" deprecation message for "auto ref" arguments) +$(LI $(BUGZILLA 14285): [REG2.063] alias this to nothing is accepted) +$(LI $(BUGZILLA 14299): [REG2.067.0-rc1] "ref" parameter in CTFE handled incorrectly for recursive calls) +$(LI $(BUGZILLA 14301): [2.067-rc1] Private symbols of module conflicts with public from another) +$(LI $(BUGZILLA 14304): [REG2.067a] ICE with static immutable variable CTFE) +$(LI $(BUGZILLA 14317): [REG2.066] ICE $(LPAREN)cgcod.c 1767$(RPAREN) when compiing with -profile -O -inline) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 1625): CTFE: cannot evaluate function when return type includes a union) +$(LI $(BUGZILLA 1829): Inline assembler cannot get label addresses) +$(LI $(BUGZILLA 2644): Unresolved template reference) +$(LI $(BUGZILLA 2834): Struct Destructors are not called by the GC, but called on explicit delete.) +$(LI $(BUGZILLA 3022): scope x = new Foo; does not allocate on stack if Foo has allocator) +$(LI $(BUGZILLA 3918): Parameter use before its use in an AndAnd expression with reals treats NaN as false) +$(LI $(BUGZILLA 4062): can call method without this pointer inside is$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 4103): opAssign signature rules not enforced on templated opAssign) +$(LI $(BUGZILLA 4149): refs displayed as pointers in gdb) +$(LI $(BUGZILLA 4181): GDB prints wrong value of TLS variables) +$(LI $(BUGZILLA 5314): Wrong error message: struct within immutable member and postblit function) +$(LI $(BUGZILLA 5908): Optimizer generates wrong value with divide-by-zero.) +$(LI $(BUGZILLA 6423): Garbage is returned from `void main$(LPAREN)$(RPAREN)`) +$(LI $(BUGZILLA 6565): out 2D fixed-sized array) +$(LI $(BUGZILLA 6574): Erroneous recursive call in template instantiation) +$(LI $(BUGZILLA 6810): Strange `tuple used as a type` error) +$(LI $(BUGZILLA 7104): linker error on void main$(LPAREN)$(RPAREN){ typeof$(LPAREN)new class{}$(RPAREN) c; c = new typeof$(LPAREN)c$(RPAREN); }) +$(LI $(BUGZILLA 7151): [CTFE] cannot compare classes with ==) +$(LI $(BUGZILLA 7465): Duplicate error message for bad template mixin) +$(LI $(BUGZILLA 7874): [CTFE] internal error: unsupported assignment $(LPAREN)x OP= y$(RPAREN) = z) +$(LI $(BUGZILLA 7942): Appending different string types corrupts memory) +$(LI $(BUGZILLA 8246): tuple fields pollute the linker namespace) +$(LI $(BUGZILLA 8425): Missing line number and module name that can't use core.simd) +$(LI $(BUGZILLA 9047): Expression requiring std.math fails with function-local import) +$(LI $(BUGZILLA 9148): 'pure' is broken) +$(LI $(BUGZILLA 9537): auto ref returns a reference its own stack) +$(LI $(BUGZILLA 9554): Inconsistent stringof and mangleof result for module/package identifier) +$(LI $(BUGZILLA 9581): Exceptions are too slow) +$(LI $(BUGZILLA 9620): Error messages of failed pure enforcement) +$(LI $(BUGZILLA 9685): Context pointer of struct isn't copied when a closure is passed by alias) +$(LI $(BUGZILLA 9728): Ddoc anchors non-unique across overloads) +$(LI $(BUGZILLA 9906): filter of static opCall) +$(LI $(BUGZILLA 10307): Bad error message for not supported array operation) +$(LI $(BUGZILLA 10311): gdb prints wrong value for variable updated from closure) +$(LI $(BUGZILLA 10528): Private constant $(LPAREN)enum$(RPAREN) properties not private) +$(LI $(BUGZILLA 10855): Missing dmd.conf for FreeBSD in DMD 2.063.2 release) +$(LI $(BUGZILLA 10915): std.typecons.Nullable throws in writeln$(LPAREN)$(RPAREN) if it's null) +$(LI $(BUGZILLA 10920): template instantiation order dependent link failure problem) +$(LI $(BUGZILLA 11042): Inconsistent "static condition" behaviors) +$(LI $(BUGZILLA 11260): Assertion `type->ty != Tstruct || $(LPAREN)$(LPAREN)TypeStruct *$(RPAREN)type$(RPAREN)->sym == this' failed) +$(LI $(BUGZILLA 11355): Copy through alias this with @disabled this$(LPAREN)this$(RPAREN)) +$(LI $(BUGZILLA 11467): [CTFE] Overlapping array copy is allowed in CT) +$(LI $(BUGZILLA 11746): invalid enum forward reference pattern not detected) +$(LI $(BUGZILLA 11888): Incorrect behaviour taking slice from return value) +$(LI $(BUGZILLA 11902): DMD debuginfo doesn't seem to write classes correctly) +$(LI $(BUGZILLA 11915): Inconsistent overload resolution behaviour between `ref` and `out`) +$(LI $(BUGZILLA 11916): [IFTI] Disabled by constraint overload with `out` with IFTI breaks overload resolution) +$(LI $(BUGZILLA 12092): Wrong TLS access in PIC code $(LPAREN)X86_32$(RPAREN)) +$(LI $(BUGZILLA 12130): Segmentation fault if HOME environment variable does not exist) +$(LI $(BUGZILLA 12163): pdb debugging $(LPAREN)win64$(RPAREN): stepping loops points to incorrect lines) +$(LI $(BUGZILLA 12447): variadic template functions hijack all eponymous enum and alias template overloads) +$(LI $(BUGZILLA 12495): CTFE slice cast can cause allocation) +$(LI $(BUGZILLA 12500): ICE in codegen when multiplying an incremented size_t by a double) +$(LI $(BUGZILLA 12502): Some static array casts incorrectly rejected in safe code) +$(LI $(BUGZILLA 12531): forward reference with nested struct) +$(LI $(BUGZILLA 12579): DMD rejects valid function literal) +$(LI $(BUGZILLA 12636): extern$(LPAREN)C++$(RPAREN) class that implements D interface segfaults) +$(LI $(BUGZILLA 12741): DMD accepts functions with contracts and no body) +$(LI $(BUGZILLA 12776): Wrong type for __vector$(LPAREN)int[4]$(RPAREN).init) +$(LI $(BUGZILLA 12780): Multiplying integer array by scalar double fails) +$(LI $(BUGZILLA 12827): [ICE] Segfault on immutable field self-initialization) +$(LI $(BUGZILLA 12871): inner function returning pointer to outer context local rejected) +$(LI $(BUGZILLA 12908): [AA] `foreach` by keys and values over associative array in pure function allow impure function calls) +$(LI $(BUGZILLA 12979): Nothrow violation error is hidden by inline assembler) +$(LI $(BUGZILLA 12983): overload not recognized depending on order of declaration) +$(LI $(BUGZILLA 13028): [ICE] CTFE internal error: cannot evaluate at compile time) +$(LI $(BUGZILLA 13064): Redundant `auto` storage class is allowed for functions) +$(LI $(BUGZILLA 13095): Sometimes struct destructor is called if constructor throws) +$(LI $(BUGZILLA 13120): Body of `foreach` over string with transcoding ignores function attributes) +$(LI $(BUGZILLA 13200): Assertion `protName' failed) +$(LI $(BUGZILLA 13236): Invalid recursive struct field error not gagged in 'is'-expression) +$(LI $(BUGZILLA 13280): `this.sizeof` rejected as static array length in some cases) +$(LI $(BUGZILLA 13289): wchar and dchar C++ mangling is incorrect) +$(LI $(BUGZILLA 13295): [CTFE] Modifications of const user type disappear) +$(LI $(BUGZILLA 13297): [CTFE] Modifications of user type pointer member passed by ref in function disappear) +$(LI $(BUGZILLA 13320): Redundant error messages for missing operation on struct instance) +$(LI $(BUGZILLA 13336): auto ref return deduced to be ref despite return value coercion) +$(LI $(BUGZILLA 13337): Invalid extern C++ namespace resolution) +$(LI $(BUGZILLA 13356): [ICE] $(LPAREN)dmd 2.066: statement.c:754$(RPAREN) with recursive Algebraic) +$(LI $(BUGZILLA 13361): Empty UDA accepted) +$(LI $(BUGZILLA 13382): [e2ir] compare string to int - leads to ICE in e2ir.c 1902) +$(LI $(BUGZILLA 13385): ICE with new package$(LPAREN)names$(RPAREN) protection) +$(LI $(BUGZILLA 13403): [ICE][2.067Alpha] Internal error: backend\type.c 332 with new package protection extension.) +$(LI $(BUGZILLA 13434): [ICE] indexing array with empty tuple causes dmd segfault) +$(LI $(BUGZILLA 13437): [e2ir] ICE in e2ir.c 4616) +$(LI $(BUGZILLA 13459): segfault in two auto opSlices$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 13465): Segfault by eager semantic2 running in template instantiation) +$(LI $(BUGZILLA 13468): Wrong code when comparing class reference with typeof$(LPAREN)null$(RPAREN)) +$(LI $(BUGZILLA 13481): bug with inferring attributes from built-in properties) +$(LI $(BUGZILLA 13484): Template type deduction from delegate parameter fails) +$(LI $(BUGZILLA 13485): FP wrong-code with -O) +$(LI $(BUGZILLA 13490): Can't append to array of structs with alias this as lvalue ternary opoerator result) +$(LI $(BUGZILLA 13505): No line number with void array in class) +$(LI $(BUGZILLA 13508): array vararg function safety not inferred) +$(LI $(BUGZILLA 13521): [D1] -di disables declaration shadowing message) +$(LI $(BUGZILLA 13528): Internal Compiler Error: CTFE DotType:) +$(LI $(BUGZILLA 13530): [REG 2.066] D Inline Assembler in nothrow function hides errors) +$(LI $(BUGZILLA 13539): Disallow optional template parameters with C-style syntax) +$(LI $(BUGZILLA 13563): ICE with opIndexAssign op-overloading and ModuleScopeOperator) +$(LI $(BUGZILLA 13574): incorrect code for assignment to dollar in slice expression) +$(LI $(BUGZILLA 13583): Inconsistent naming of template arguments in debug symbols) +$(LI $(BUGZILLA 13586): Destructors not run when argument list evaluation throws) +$(LI $(BUGZILLA 13599): [D1] backend/cod1.c ICE with -inline) +$(LI $(BUGZILLA 13600): ICE in dwarf.c line 1949 with -g enabled and lazy void parameter) +$(LI $(BUGZILLA 13612): Wrong 'this' variable accessed in recursive ctfe member function) +$(LI $(BUGZILLA 13613): Pragma msg affects data structure layout) +$(LI $(BUGZILLA 13630): Senseless error with foreach over variadic list) +$(LI $(BUGZILLA 13645): Incorrect ddoc generation for deprecated module) +$(LI $(BUGZILLA 13661): static array init does not call destructors) +$(LI $(BUGZILLA 13666): Undefined Symbols for __gshared data symbols in templates) +$(LI $(BUGZILLA 13668): [ICE] unable to compile __traits$(LPAREN)allMembers...$(RPAREN)) +$(LI $(BUGZILLA 13669): [CTFE] Destructor call on static array variable is not yet supported in CTFE) +$(LI $(BUGZILLA 13679): foreach_reverse is allowed for AAs) +$(LI $(BUGZILLA 13701): [REG2.061] Associative array values ignore immutability) +$(LI $(BUGZILLA 13707): msvc32 C++ struct return ABI not followed for structs with constructors) +$(LI $(BUGZILLA 13739): in CTFE making an array over an array copies the data) +$(LI $(BUGZILLA 13740): CTFE fails ref foreach over range) +$(LI $(BUGZILLA 13747): Linux CMSG_NXTHDR is private, since alias doesn't change protection level) +$(LI $(BUGZILLA 13757): [CTFE] extern$(LPAREN)C$(RPAREN) alias declaration does not work in CTFE) +$(LI $(BUGZILLA 13779): gdb can't find frame base when using ld.gold) +$(LI $(BUGZILLA 13783): Function overload with rvalue `inout` parameter not selected when `enum` parameter implicitly converted to its base type) +$(LI $(BUGZILLA 13784): Wrong code with modulo operation and optimisations enabled) +$(LI $(BUGZILLA 13787): Error without line number when slicing function pointer) +$(LI $(BUGZILLA 13788): dmd segfault, pragma$(LPAREN)mangle$(RPAREN) and a mixin) +$(LI $(BUGZILLA 13795): DMD ICE segfault compiling druntime) +$(LI $(BUGZILLA 13831): DMD crash on newing struct with overlapped fields in CTFE) +$(LI $(BUGZILLA 13832): delegates that return ref do not output correctly to .di file) +$(LI $(BUGZILLA 13835): ICE in interpret.c:736 - Issue with static variables.) +$(LI $(BUGZILLA 13841): infinite loop in compiler on simd arithmetic) +$(LI $(BUGZILLA 13843): Issue when passing a delegate as an class alias template parameter) +$(LI $(BUGZILLA 13847): CTFE internal error: dottype) +$(LI $(BUGZILLA 13858): Wrong warning about unreachable code with break/goto case) +$(LI $(BUGZILLA 13860): template required forward reference for typeof$(LPAREN)member$(RPAREN)) +$(LI $(BUGZILLA 13861): compiler segfault with nested struct, cannot access frame) +$(LI $(BUGZILLA 13874): Invalid FunctionTypeOf segfault the compiler) +$(LI $(BUGZILLA 13879): Default inizialization of function pointers array) +$(LI $(BUGZILLA 13884): No error line number with std.array.array of range of type tuples) +$(LI $(BUGZILLA 13899): Unwanted warning for pure opApply) +$(LI $(BUGZILLA 13902): Compiler allows escaping the address of part of a local) +$(LI $(BUGZILLA 13907): Surrogate pairs in wchar string literal will cause incorrect length match) +$(LI $(BUGZILLA 13910): Internal error: e2ir.c 1926) +$(LI $(BUGZILLA 13932): c++ mangling for template negative int parameter) +$(LI $(BUGZILLA 13938): IASM shouldn't be able to access TLS variables) +$(LI $(BUGZILLA 13939): IASM shouldn't access global symbol with PIC code) +$(LI $(BUGZILLA 13947): Padding in empty structs is compared) +$(LI $(BUGZILLA 13955): 64 bit C ABI not followed for passing structs with mixed floating types) +$(LI $(BUGZILLA 13956): 64 bit C ABI not followed for passing empty structs) +$(LI $(BUGZILLA 13959): ICE in e2ir when casting struct to pointer) +$(LI $(BUGZILLA 13977): Front-end optimizer bug in AndAndExp) +$(LI $(BUGZILLA 13978): Front-end optimizer bug in OrOrExp) +$(LI $(BUGZILLA 13982): D1: wrong template instantiation is not rejected) +$(LI $(BUGZILLA 13987): Invalid struct segfaults) +$(LI $(BUGZILLA 14009): iasm parser accepts incorrect AsmExp) +$(LI $(BUGZILLA 14010): Support mangleof property for opaque enum and struct type) +$(LI $(BUGZILLA 14016): Nested inherited class doesn't know the type of its outer object) +$(LI $(BUGZILLA 14022): [CTFE] postblits/destructors not called on static array field assignment) +$(LI $(BUGZILLA 14023): [CTFE] postblits/destructors not called on static array index assignment) +$(LI $(BUGZILLA 14024): [CTFE] unstable postblit/destructor call order on static array assignment) +$(LI $(BUGZILLA 14028): [CTFE] Possible reinterpret cast to a pointer to static array) +$(LI $(BUGZILLA 14050): `dmd -v` lists imports from failed __traits$(LPAREN)compiles$(RPAREN) blocks) +$(LI $(BUGZILLA 14055): CTFE internal error with uninitialized array: Assertion failure: '0' on line 318 in file 'interpret.c') +$(LI $(BUGZILLA 14083): Remained unresolved forward reference issue with template classes) +$(LI $(BUGZILLA 14096): ICE in toir.c: 187) +$(LI $(BUGZILLA 14116): Assertion failure: 'p->isPkgMod == PKGmodule' on line 143 in file 'import.c') +$(LI $(BUGZILLA 14132): [ICE] error on arrays) +$(LI $(BUGZILLA 14141): `pure` member function returning qualified member result is implicitly convertible to unqualified) +$(LI $(BUGZILLA 14154): [e2ir] Error in e2ir at casting to struct) +$(LI $(BUGZILLA 14163): No line number for error with disabled class constructor) +$(LI $(BUGZILLA 14165): Link failure on class declaration with @disable this$(LPAREN)$(RPAREN);) +$(LI $(BUGZILLA 14174): Weird IFTI deduction failure) +$(LI $(BUGZILLA 14179): Posix x86_64 varargs prolog clobbers RDX) +$(LI $(BUGZILLA 14195): Ice when mangling templated function parameter extern$(LPAREN)C++$(RPAREN) function) +$(LI $(BUGZILLA 14200): C++ mangling issue with expanded tuples) +$(LI $(BUGZILLA 14201): fatal error LNK1235: corrupt or invalid COFF symbol table) +$(LI $(BUGZILLA 14210): invalid merging of template instances) +$(LI $(BUGZILLA 14229): RAII ordering is wrong) +$(LI $(BUGZILLA 14272): DMD segfault on invalid circular enum initialization) +$(LI $(BUGZILLA 14275): Qualified package protection for aggregate member doesn't work) +$(LI $(BUGZILLA 14276): DWARF debug info for SIMD broken) +$(LI $(BUGZILLA 14306): Wrong codegen with -inline for generic lambdas) +$(LI $(BUGZILLA 14311): Win32 COFF: bad symbols/relocation entries for global data accesses) +$(LI $(BUGZILLA 14313): [ld.gold] gdb: wrong value of shared variables) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 1317): Document suggested means of overlapping array copy) +$(LI $(BUGZILLA 2498): make foreach work for any callable symbol) +$(LI $(BUGZILLA 2529): 'package' access qualifier should allow access to sub-packages) +$(LI $(BUGZILLA 3449): const and immutable struct members do not behave according to spec) +$(LI $(BUGZILLA 4567): dmd should print the dmd.conf location with usage statement) +$(LI $(BUGZILLA 9089): Very restrictive Tuple constructor) +$(LI $(BUGZILLA 9915): Typeid .name inconsistent between templated classes and structs) +$(LI $(BUGZILLA 10165): No syntax to create thread-local shared variables) +$(LI $(BUGZILLA 11530): need gdb test suite) +$(LI $(BUGZILLA 12888): Include template constraints in JSON output) +$(LI $(BUGZILLA 12985): Better error message for not supported array operation) +$(LI $(BUGZILLA 13019): Different color for "Warning:") +$(LI $(BUGZILLA 13350): is$(LPAREN)typeof$(LPAREN)fun$(RPAREN)$(RPAREN) causes link error when template fun calls undefined reference) +$(LI $(BUGZILLA 13388): accept '@' before 'nothrow' and 'pure') +$(LI $(BUGZILLA 13510): When adding "New issue" there should be no choice among DStress, puremagic, and D. Just leave D.) +$(LI $(BUGZILLA 13609): better error message for missing '}') +$(LI $(BUGZILLA 13704): Confusing error message when passing the same file on the command line twice) +$(LI $(BUGZILLA 13756): [AA] Allow ref const index on foreach AA iteration) +$(LI $(BUGZILLA 13802): Improve pretty-print result for the const$(LPAREN)string$(RPAREN) type) +$(LI $(BUGZILLA 13803): Improve pretty-print result for the wstring an dstring types) +$(LI $(BUGZILLA 13839): Use new style for alias declarations in di files) +$(LI $(BUGZILLA 13944): Built-in stringof and mangleof properties are unnecessarily fixed to the type 'string') +$(LI $(BUGZILLA 13976): Value range propagation to disable some slice bound tests) +$(LI $(BUGZILLA 14105): strideImpl fails for 0xFF) +$(LI $(BUGZILLA 14123): cannot compare typeid$(LPAREN)object.Object$(RPAREN) at compile time) +$(LI $(BUGZILLA 14156): buffer overflow in LibELF) +$(LI $(BUGZILLA 14211): Compiler should devirtualize calls to members of final class) +$(LI $(BUGZILLA 14338): Implement DIP25 Sealed References) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 13241): [REG2.067a] writeln no longer flushes stdout) +$(LI $(BUGZILLA 13257): [REG2.067a] Deprecation message when using std.getopt with string[] parameter) +$(LI $(BUGZILLA 13300): pure function 'std.array.Appender!$(LPAREN)T[]$(RPAREN).Appender.ensureAddable' cannot call impure function 'test.T.__fieldPostBlit') +$(LI $(BUGZILLA 13304): std.algorithm.reduce: "Unable to deduce an acceptable seed type" with float[]) +$(LI $(BUGZILLA 13367): Buffer overflow when setting PATH) +$(LI $(BUGZILLA 13375): Linking failure when importing both std.regex and std.algorithm) +$(LI $(BUGZILLA 13390): [REG2.066] std.range.cycle ctor fails when empty input passed) +$(LI $(BUGZILLA 13393): [REG2.067a] std.algorithm.joiner Assertion failure in popFront$(LPAREN)$(RPAREN) when using with cartesianProduct) +$(LI $(BUGZILLA 13621): inout issue with std.container.Array opSlice) +$(LI $(BUGZILLA 13716): Phobos std.file fails to build) +$(LI $(BUGZILLA 13717): `split` no longer defined by std.string) +$(LI $(BUGZILLA 13766): std.container, std.range, std.regex documentation is now broken) +$(LI $(BUGZILLA 13774): Multiple definition of `conv_50c_dc8` with three libraries and `std.file` import) +$(LI $(BUGZILLA 13871): [REG2.067a] Segmentation fault from std/variant.d:609) +$(LI $(BUGZILLA 14037): Problem with BigInt and std.functional.memoize) +$(LI $(BUGZILLA 14041): Refused writeln of a fixed size array of chars) +$(LI $(BUGZILLA 14042): std.conv.to of a immutable char pointer) +$(LI $(BUGZILLA 14197): "replace" was moved from std.string without alias added) +$(LI $(BUGZILLA 14212): frexp for const and immutable fails to compile) +$(LI $(BUGZILLA 14213): Strange deprecated message in std.typecons.Proxy with using method) +$(LI $(BUGZILLA 14230): [REG2.067b2] std.array.join misses the first element which is empty string) +$(LI $(BUGZILLA 14233): [REG2.067b2] Can't build Algebraic!$(LPAREN)This[]$(RPAREN) anymore) +$(LI $(BUGZILLA 14253): [REG2.067b3] std.traits.ParameterStorageClassTuple gives compiler errors when encountering 'return' functions) +$(LI $(BUGZILLA 14300): [2.067-rc1] DList casting to base type is broken) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 649): concatenation hangs in threaded program) +$(LI $(BUGZILLA 3141): osx syntax problem with touch) +$(LI $(BUGZILLA 5036): Remove caching from ranges) +$(LI $(BUGZILLA 5233): [patch] std.range.put accepts *any* element type when putting to an array.) +$(LI $(BUGZILLA 5698): va_arg sets wrong length for $(LPAREN)u$(RPAREN)short[]) +$(LI $(BUGZILLA 6256): [patch] std.algorithm.map does not support static arrays and has 'length' for narrow strings.) +$(LI $(BUGZILLA 6339): stdin.byChunk throws with Windows pipes on command line) +$(LI $(BUGZILLA 7223): Access violation when using rmdirRecurse on folder without modify permissions) +$(LI $(BUGZILLA 7797): std.typelist should be deprecated) +$(LI $(BUGZILLA 8578): std.demangle.demangle does not parse symbols that are type names) +$(LI $(BUGZILLA 8708): Documentation for std.process.exec family is inaccurate) +$(LI $(BUGZILLA 9507): std.range.transposed behaves poorly with jagged ranges of ranges) +$(LI $(BUGZILLA 10104): std.algorithm.group of a const/immutable array) +$(LI $(BUGZILLA 10125): readln!dchar misdecodes Unicode non-BMP) +$(LI $(BUGZILLA 10139): std.stdio.writef and friends documentation is severely out of date) +$(LI $(BUGZILLA 10460): std.algorithm: some of algorithms don't use 'auto ref' for front) +$(LI $(BUGZILLA 11434): std.file.copy doesn't preserve file attributes $(LPAREN)eg: executable mode etc$(RPAREN)) +$(LI $(BUGZILLA 11539): wrong "Orphan format specifier:" error message) +$(LI $(BUGZILLA 11895): Add Strings Overview page to Phobos documentation) +$(LI $(BUGZILLA 12114): buildNormalizedPath shouldn't normalize current path to empty string) +$(LI $(BUGZILLA 12320): std.stdio.LockingTextReader populates .front in .empty) +$(LI $(BUGZILLA 12589): std.random.randomCover fails for empty ranges) +$(LI $(BUGZILLA 12631): std.string.isNumeric uses among without explicit braces when calling 'std.algorithm.among' when compiling with dmd -property flag) +$(LI $(BUGZILLA 12733): parallelism.amap incorrect assignment without initialization) +$(LI $(BUGZILLA 12913): Mistake concerning DLists) +$(LI $(BUGZILLA 12915): RedBlackTree leaks memory) +$(LI $(BUGZILLA 12969): std.json: Lack of opIndexAssign operator for JSONValue may become a source of runtime errors) +$(LI $(BUGZILLA 13018): std.string.translate needs mutable translation table) +$(LI $(BUGZILLA 13124): std.algorithm.until with not-boolean predicates too) +$(LI $(BUGZILLA 13248): std.range.tee unit test prints to stdout) +$(LI $(BUGZILLA 13315): std.getopt: implicit help option doesn't work without config.passThrough) +$(LI $(BUGZILLA 13316): std.getopt: implicit help option breaks the next argument) +$(LI $(BUGZILLA 13317): std.getopt: endOfOptions broken when it doesn't look like an option) +$(LI $(BUGZILLA 13352): Algebraic does not support binary arithmetic when omitting small number types) +$(LI $(BUGZILLA 13354): Algebraic.opIndex/opIndexAssign makes wrong assumptions on the index/value type) +$(LI $(BUGZILLA 13391): BigInt division by ulong rejected) +$(LI $(BUGZILLA 13418): uninitializedArray $(AMP) core.simd.Vector return incorrect type) +$(LI $(BUGZILLA 13425): DList.linearRemove on last element returns non-empty range) +$(LI $(BUGZILLA 13441): joiner asserts with only$(LPAREN)x$(RPAREN) separator) +$(LI $(BUGZILLA 13446): Can't use executeShell/escapeShellFileName to redirect to file whose name starts with $(AMP)) +$(LI $(BUGZILLA 13447): Do not escape process parameters unless necessary) +$(LI $(BUGZILLA 13477): std.process should ignore unnamed service variables on Windows) +$(LI $(BUGZILLA 13529): std.string.lastIndexOf matches wrong element) +$(LI $(BUGZILLA 13535): byCodeUnit doesn't satisfy hasSlicing) +$(LI $(BUGZILLA 13592): std.datetime fails its unittests on Windows 7 - no Belarus Standard Time?) +$(LI $(BUGZILLA 13594): std.algorithm.nextPermutation should accept ranges of lvalues) +$(LI $(BUGZILLA 13647): std.traits documentation needs linking correctly and has spurious category value) +$(LI $(BUGZILLA 13649): uniform01 Assertion failure) +$(LI $(BUGZILLA 13686): Reading unicode string with readf $(LPAREN)"%s"$(RPAREN) produces a wrong string) +$(LI $(BUGZILLA 13689): byCodeUnit fails to be a random access range) +$(LI $(BUGZILLA 13746): formatValue of delegates with @nogc) +$(LI $(BUGZILLA 13781): Tuple assign should be @nogc) +$(LI $(BUGZILLA 13805): Nested struct initialization error) +$(LI $(BUGZILLA 13877): Problem with map+join) +$(LI $(BUGZILLA 13922): std.range.package.takeOne doesn't accept non-forward ranges) +$(LI $(BUGZILLA 13931): Missing overflow checks in `std.conv` for negative numbers which start from the most negative number digits) +$(LI $(BUGZILLA 13935): Problem with std.algorithm.cartesianProduct$(LPAREN)map, map$(RPAREN)) +$(LI $(BUGZILLA 13963): BigInt modulo ulong is rejected) +$(LI $(BUGZILLA 13990): std.algorithm.move incorrectly uses hasAliasing for class references) +$(LI $(BUGZILLA 14012): std.socket: wrong SocketSet.max on Posix) +$(LI $(BUGZILLA 14013): std.socket: off-by-one error when automatically resizing on POSIX) +$(LI $(BUGZILLA 14025): unittests for memoize fail intermittently) +$(LI $(BUGZILLA 14059): Formatted write with wrong formatting string) +$(LI $(BUGZILLA 14065): std.json not tracking line:column properly) +$(LI $(BUGZILLA 14082): RedBlackTree unittest fails with custom predicate less) +$(LI $(BUGZILLA 14111): Broken DDOC for std.format) +$(LI $(BUGZILLA 14124): BigInt %= int can return "-0") +$(LI $(BUGZILLA 14181): Wrong document for std.mathspecial.normalDistribution) +$(LI $(BUGZILLA 14223): TimSort algorithm is incorrect) +$(LI $(BUGZILLA 14231): findRoot fails with trivial bounds) +$(LI $(BUGZILLA 14297): [2.067-rc1] Broken links in phobos/index.html) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 2138): Allow more than 65535 files in Zip archives) +$(LI $(BUGZILLA 2181): Constant-time std.gc.removeRange) +$(LI $(BUGZILLA 4493): Add sorting capability to toJSON) +$(LI $(BUGZILLA 4764): Lazy versions of std.string.split and std.string.splitlines) +$(LI $(BUGZILLA 5190): std.stdio should have File.fdopen) +$(LI $(BUGZILLA 5494): [patch,enh] Issues with std.stdarg) +$(LI $(BUGZILLA 5550): std.range.enumerate$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 6147): file scheme uri from file path and vice versa) +$(LI $(BUGZILLA 6586): feqrel for const values too) +$(LI $(BUGZILLA 6756): Idea about std.stdio.chunks and std.range.chunks) +$(LI $(BUGZILLA 6989): Implement toString for std.concurrency.Tid) +$(LI $(BUGZILLA 7775): std.range.chunks on const array of strings too) +$(LI $(BUGZILLA 8371): Add a function to make a range from a sequence of elements) +$(LI $(BUGZILLA 8851): std.string.join should allow 'char' as joiner) +$(LI $(BUGZILLA 9959): Add functional pattern matching for object references) +$(LI $(BUGZILLA 11363): std.process should offer a way to run a executable with a given working directory) +$(LI $(BUGZILLA 11706): Add a TypedefType trait to extract the underlying type of a std.typecons.Typedef) +$(LI $(BUGZILLA 12409): Add "each" function as found in Ruby and jQuery) +$(LI $(BUGZILLA 13091): nothrow std.algorithm.cartesianProduct) +$(LI $(BUGZILLA 13157): std.typecons.Unique: Support construction and conversion from compatible types) +$(LI $(BUGZILLA 13319): tzDatabaseNameToWindowsTZName should return null on failure rather than throw) +$(LI $(BUGZILLA 13380): Conflict with std.typecons.Identity and std.traits.Identity) +$(LI $(BUGZILLA 13402): code cleanup: removing c-style array declarations in phobos) +$(LI $(BUGZILLA 13419): code cleanup in std.uni: removing "comma expressions") +$(LI $(BUGZILLA 13445): std.process fails to create process with empty $(LPAREN)non-null$(RPAREN) working directory) +$(LI $(BUGZILLA 13450): Add WindowsException and wenforce to std.exception) +$(LI $(BUGZILLA 13483): std.range.tee should also accept a function name) +$(LI $(BUGZILLA 13555): Categorize functions in std.math) +$(LI $(BUGZILLA 13595): Extend std.algorithm.groupBy to support non-equivalence relations) +$(LI $(BUGZILLA 13623): std.typecons.Proxy doesn't work inside classes) +$(LI $(BUGZILLA 13662): @safe pure @nogc nothrow findRoot) +$(LI $(BUGZILLA 13681): @safe empty writeln) +$(LI $(BUGZILLA 13837): Named tuples with type inference) +$(LI $(BUGZILLA 13908): @safe write of a $(LPAREN)uint, uint$(RPAREN) tuple) +$(LI $(BUGZILLA 13909): A problem with immutable zip + assocArray) +$(LI $(BUGZILLA 14110): std.file.read cannot read files open for writing) +$(LI $(BUGZILLA 14183): Updates to groupBy) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 13748): benchmark druntime/benchmark/aabench/string.d fails) +$(LI $(BUGZILLA 13809): dup no longer works with types with postblit and destructors) +$(LI $(BUGZILLA 14134): Free of large array does not work) +$(LI $(BUGZILLA 14192): Access Violation when assigning to shared AA) +$(LI $(BUGZILLA 14225): [REG2.067a] GDB: error reading variable $(LPAREN)string + dup$(RPAREN)) +$(LI $(BUGZILLA 14291): Druntime master no longer builds) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 5629): core.time unittest disabled) +$(LI $(BUGZILLA 8960): DMD tester: Unable to set thread priority) +$(LI $(BUGZILLA 13052): TypeInfo.getHash should return same hash for different floating point zeros.) +$(LI $(BUGZILLA 13410): Performance problem with associative array byKey/byValue) +$(LI $(BUGZILLA 13416): dead-lock in FreeBSD suspend handler) +$(LI $(BUGZILLA 13722): onFinalizeError should not allocate) +$(LI $(BUGZILLA 13723): onFinalizeError should not be called for Errors) +$(LI $(BUGZILLA 13854): Appending to an interior slice of a large array results in unnecessary 16-byte offset) +$(LI $(BUGZILLA 13878): Appending to an array block with modified flags loses flag info) +$(LI $(BUGZILLA 14036): Do not throw FinalizeError on OutOfMemoryError or InvalidMemoryOperationError) +$(LI $(BUGZILLA 14157): fabsf fabsl for CRuntime_Microsoft) +$(LI $(BUGZILLA 14247): string within demangled symbol name should be made escape) +$(LI $(BUGZILLA 14303): rt.util.container.array.Array unittest contains invalid code) +) +$(BUGSTITLE Druntime enhancements, + +$(LI $(BUGZILLA 9119): [AA] Forward range addition to associative arrays.) +$(LI $(BUGZILLA 11216): Make synchronized statement `nothrow`) +$(LI $(BUGZILLA 13401): code cleanup: removing c-style array declarations in druntime) +$(LI $(BUGZILLA 13559): missing 64-bit version of array short operations) +$(LI $(BUGZILLA 13725): onInvalidMemoryOperationError et al should not be inlined) +$(LI $(BUGZILLA 13755): core.sys.linux.stdio, std.stdio.File: fopencookie, fmemopen missing) +$(LI $(BUGZILLA 14007): shmctl with IPC_STAT returns wrong number of attachments. shmid_ds is defined wrong.) +) +$(BUGSTITLE Optlink bugs, + +$(LI $(BUGZILLA 4831): Optlink rejects paths with invalid characters based on HPFS filesystem instead of NTFS) +) +$(BUGSTITLE Installer bugs, + +$(LI $(BUGZILLA 9392): Misleading text about required OS version) +) +$(BUGSTITLE Website regressions, + +$(LI $(BUGZILLA 14258): SIGSEGV in dpldocs) +$(LI $(BUGZILLA 14280): Links to command line tools have disappeared from navigation) +) +$(BUGSTITLE Website bugs, + +$(LI $(BUGZILLA 8307): inconsistent treatment of auto functions) +$(LI $(BUGZILLA 9118): typo in github tools repo) +$(LI $(BUGZILLA 9535): incomplete documentation for std.range.recurrence and std.range.sequence) +$(LI $(BUGZILLA 9691): Static void arrays are not documented) +$(LI $(BUGZILLA 9970): Document the definition and difference between storage class and type constructor) +$(LI $(BUGZILLA 10232): AndExpression grammar is not correct) +$(LI $(BUGZILLA 10235): Grammar does not contain a rule for function declarations) +$(LI $(BUGZILLA 10284): dlang.org/phobos/index.html needs redesign) +$(LI $(BUGZILLA 10285): Enum grammar documentation is incorrect) +$(LI $(BUGZILLA 12810): PrimaryExpression grammar does not allow type constructors) +$(LI $(BUGZILLA 13093): D ABI change for guaranteed efficient return of fixed size array) +$(LI $(BUGZILLA 13308): AsmPrimaryExp documentation is incorrect) +$(LI $(BUGZILLA 13310): Old style multiple alias declaration not documented) +$(LI $(BUGZILLA 13328): Missing link to contracts description from function specification page) +$(LI $(BUGZILLA 13329): AutoDeclarationX grammar lists '=' token and template parameters in the wrong order) +$(LI $(BUGZILLA 13436): posix.mak is broken for dlang.org repo) +$(LI $(BUGZILLA 13448): Class specification misses template classes in base classes list) +$(LI $(BUGZILLA 13451): Lambda syntax with explicit return type not documented) +$(LI $(BUGZILLA 13467): A little better std.algorithm.canFind documentation) +$(LI $(BUGZILLA 13523): Auto function declaration does not match any grammar rule) +$(LI $(BUGZILLA 13525): Redundant SpecialKeyword grammar listd in DefaultInitializerExpression) +$(LI $(BUGZILLA 13538): Divide old C style syntax from D style grammar rule) +$(LI $(BUGZILLA 13547): "D is a fully garbage collected language") +$(LI $(BUGZILLA 13648): ddoc problem with std.random.uniform01) +$(LI $(BUGZILLA 13664): Grammar does not allow @<template_instance> UDAs) +$(LI $(BUGZILLA 13671): https://dlang.org/const3.html incorrectly calls type qualifiers "type constructors") +$(LI $(BUGZILLA 13696): Missing entry for unicode code point literals on the lexer page) +$(LI $(BUGZILLA 13895): Declaration grammar is insufficient) +$(LI $(BUGZILLA 13941): NewExpression grammar is insufficient) +$(LI $(BUGZILLA 13979): ForeachType grammar does not allow 'ref' to appear after type constructors) +$(LI $(BUGZILLA 13991): Invariant grammar does not document that parenthesis are optional) +$(LI $(BUGZILLA 14002): Book link is broken) +$(LI $(BUGZILLA 14031): Frame content going outside frame) +$(LI $(BUGZILLA 14047): "this" missing from AsmPrimaryExp grammar) +$(LI $(BUGZILLA 14081): Table in the document of std.bigint.BigInt.toString$(LPAREN)$(RPAREN) duplicates.) +$(LI $(BUGZILLA 14121): Wiki: "Create account" page completely broken!) +$(LI $(BUGZILLA 14135): std.uuid.randomUUID breaks @safety) +$(LI $(BUGZILLA 14153): std.format page displaying incorrectly) +) +$(BUGSTITLE Website enhancements, + +$(LI $(BUGZILLA 4954): Clarify documentation of foreach with delegates.) +$(LI $(BUGZILLA 6251): D spec should warn about using foreach_reverse on a delegate) +$(LI $(BUGZILLA 9469): Keywords list could use linkage; more-humane documentation) +$(LI $(BUGZILLA 10154): Betas should be posted on dlang.org) +$(LI $(BUGZILLA 10164): std.string.column examples and documentation) +$(LI $(BUGZILLA 13325): __vector not documented in language specification) +$(LI $(BUGZILLA 14011): Canonical links help message should clarify that 'thread' is invalid) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.067.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.067.1.dd b/changelog/2.067.1.dd new file mode 100644 index 0000000000..8fc29cff03 --- /dev/null +++ b/changelog/2.067.1.dd @@ -0,0 +1,41 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 25, 2015, =================================================, + +$(BR)$(BIG List of all bug fixes and enhancements in D 2.067.1:) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 14344): [REG2.067] Wrong opBinary call in construction) +$(LI $(BUGZILLA 14376): [REG2.064] false positive "Error: one path skips field") +$(LI $(BUGZILLA 14395): [REG2.067] Typesafe variadic function call collapsed if being used for default value) +$(LI $(BUGZILLA 14424): [REG2.066] dmd crashes with __traits$(LPAREN)getUnitTests$(RPAREN)) +$(LI $(BUGZILLA 14440): [REG2.067] [CTFE] Wrong values set in a matrix constructor) +$(LI $(BUGZILLA 14443): [REG2.067.0] Incorrect double freeing of reference counted struct) +$(LI $(BUGZILLA 14463): [REG2.067] DMD crashes compiling module level immutable struct that takes an array in ctor) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 14375): static assert leads to __traits$(LPAREN)allMembers$(RPAREN) retuning an extra empty entry) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 14396): [REG2.066] compile error std.conv.parse!int with input range) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 14467): arr.capacity sometimes erroneously returns 0) +) +$(BUGSTITLE Website bugs, + +$(LI $(BUGZILLA 14329): [2.067] offline doc - menu broken due to missing jquery-1.7.2.min.js) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.067.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.068.0.dd b/changelog/2.068.0.dd new file mode 100644 index 0000000000..160596991d --- /dev/null +++ b/changelog/2.068.0.dd @@ -0,0 +1,522 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Aug 09, 2015, =================================================, + +$(BUGSTITLE Compiler Changes, +$(LI $(RELATIVE_LINK2 fix14828-warning, $(RED Warning:) Change in helper function generation might cause link error.)) +$(LI $(RELATIVE_LINK2 profile-gc, The new `-profile=gc` switch enables profiling memory allocation.)) +$(LI $(RELATIVE_LINK2 lex-only-unittest, `unittest` blocks no longer parsed unless `-unittest` is specified.)) +$(LI Compiler generated inclusive destructor and postblit functions for + $(LINK2 https://wiki.dlang.org/Commonly-Used_Acronyms, UDTs) are now + accessible as `.__xdtor` and `.__xpostblit`, see $(DMDPR 4650).) +) + +$(BUGSTITLE Language Changes, +$(LI $(RELATIVE_LINK2 pragma-inline, `pragma(inline)` was added.)) +$(LI $(RELATIVE_LINK2 attribinference3, attribute inference for auto functions)) +$(LI $(RELATIVE_LINK2 index-type-followed-ident, Indexed type tuples can now be followed by dot identifiers.)) +$(LI $(RELATIVE_LINK2 ifti-from-default-arg, Support template parameter deduction from function default arguments.)) +$(LI $(RELATIVE_LINK2 invalid-cast-check, Invalid reinterpret casts can be detected in the frontend.)) +) + +$(BUGSTITLE Library Changes, +$(LI $(RELATIVE_LINK2 rangified-functions, Many phobos functions were rangified.)) +$(LI $(MREF std,typetuple) was renamed to $(MREF std,meta) + but a backwards compatible forwarding module will remain.) +$(LI $(REF_SHORT TypeTuple, std,typetuple) was renamed to $(REF_SHORT AliasSeq, std,meta) + but a backwards compatible alias will remain.) +$(LI $(REF_SHORT hexString, std,conv) was added to replace core language hex strings.) +$(LI $(REF_SHORT hasUDA, std,traits) was added to help check + for the existence of user-defined attributes on symbols.) +$(LI $(RELATIVE_LINK2 gc-api-profile, GC API calls can now be profiled separately.)) +$(LI The runtime implementations of `synchronized` and `synchronized (obj)` were + rewritten to fix a race condition during mutex initialization, see $(DRUNTIMEPR 1274).) +$(LI The handwritten object.di header was replaced by directly using the object.d source file, + see $(DRUNTIMEPR 1222) for more details.) +$(LI $(RELATIVE_LINK2 aa-open-addressing, The AA implementation now uses open addressing.)) +$(LI Merging code coverage reports was fixed, see $(BUGZILLA 14464) and $(REF_SHORT dmd_coverSetMerge, core,runtime).) +$(LI $(REF_SHORT executeShell, std,process) now ignores the `SHELL` environment variable and always uses `sh`, see $(BUGZILLA 14282).) +$(LI $(REF_SHORT byLine, std,stdio) was improved to use `getdelim` where available and is now up to 3x faster, see $(BUGZILLA 11810).) +$(LI The newly added $(REF_SHORT ordered, std,algorithm_sorting) and $(REF_SHORT strictlyOrdered, std,algorithm_sorting) can be used to test whether a few given values are ordered.) +$(LI $(REF_SHORT RefCounted, std,typecons) uses the new `return` attribute to enable escape checking for its payload.) +) + +$(BR)$(BIG $(RELATIVE_LINK2 list2068, List of all bug fixes and enhancements in D 2.068.)) + +$(HR) + +$(BUGSTITLE Compiler Changes, + +$(LI $(LNAME2 fix14828-warning, $(RED Warning:) Change in helper function generation might cause link error.) + + $(P In order to fix $(LINK2 https://issues.dlang.org/show_bug.cgi?id=14828, + Issue 14828) compiler helper functions for array bounds checking and + assert are now generated only once when a module is compiled, not + everytime they are used. This may lead to link errors when using a + module without compiling and linking against it. + ) + + $(P If you encounter link errors like + $(PRE undefined reference to '_D5mylib5mymod7__arrayZ') + $(PRE undefined reference to '_D5mylib5mymod8__assertFiZv') + $(PRE undefined reference to '_D5mylib5mymod15__unittest_failFiZv') then you're + not compiling and/or not linking the module mylib.mymod. + ) +) + +$(LI $(LNAME2 profile-gc, The new `-profile=gc` switch enables profiling memory allocation.) + + + $(P When compiling with `-profile=gc` dmd will instrument GC allocations to + be traced by the runtime. The runtime accumulates the traces and + writes a report to the file $(TT profilegc.log) upon program termination. + ) + + $(P + Example: + $(PRE +bytes allocated, type, function, file:line + 171 immutable(char)[] example.concat example.d:4 + 24 closure D main example.d:18 + 16 example.Klass D main example.d:20 + ) + ) + + $(P $(RED Note:) GC allocations using the core.memory interface are not profiled. + ) +) + +$(LI $(LNAME2 lex-only-unittest, `unittest` blocks no longer parsed unless `-unittest` is specified:) + + $(P When the unittest code is not necessary, it will be merely analyzed + as the tokens enclosed with paired braces, to speed up compilation. + ) + + --- + unittest { auto r = test(); assert(r); } + // If you don't specify -unittest, no AST generated for the unittest block. + + unittest { the contents is just ignored. } + // Since 2.067: this had caused parsing error. + // From 2.068: no error happens, because it's equivalent with: + enum unittest_code = q{ the contents is just ignored. }; + --- +) + +) + +$(BUGSTITLE Language Changes, + +$(LI $(LNAME2 pragma-inline, `pragma(inline)` was added:) + + $(P A new pragma was added for more fine-grained control of inlining. + It must be used together with the `-inline` switch. + ) + --- + pragma(inline, true) // errors if function isn't inlined + int double(int val) { return 2 * val; } + --- + --- + pragma(inline, false) // never inline + int double(int val) { return 2 * val; } + --- + + $(P Read the $(DDSUBLINK spec/pragma, inline, documentation) for more details. + ) +) + +$(LI $(LNAME2 attribinference3, Attributes for auto return function are now inferred.) + + $(P Just like templated functions, functions with an auto return type must + always have a function body. The compiler was changed to take advantage + of this fact and now also infers attributes for them. + ) + + --- + auto foo()() {} // template function + auto bar() {} // non-template function without return type + void baz() {} // non-template function with return type + + static assert(is(typeof(&foo!()) == void function() pure nothrow @nogc @safe)); + static assert(is(typeof(&bar) == void function() pure nothrow @nogc @safe)); + static assert(is(typeof(&baz) == void function())); + --- +) + +$(LI $(LNAME2 index-type-followed-ident, Indexed type tuples can now be followed by dot identifiers.) + + $(P A parsing limitation was lifted and it's now possible to use an indexed + type tuple followed by dot identifiers as typename. + ) + + --- + alias TypeTuple(T...) = T; + + struct S + { + alias T = int; + alias U = TypeTuple!(long, string); + } + + alias Pair = TypeTuple!(S, S); + + struct X(Types...) // used tuple parameter + { + + Types[0].T a; // Types[0] == S, then typeof(a) == S.T == int + Types[0].U[1] b; // Types[0].U == S.U, then typeof(b) == S.U[1] == string + } + alias x = X!Pair; + --- +) + +$(LI $(LNAME2 ifti-from-default-arg, Support template parameter deduction from function default arguments:) + + $(P When performing $(LINK2 https://wiki.dlang.org/Commonly-Used_Acronyms, + IFTI) templated types can now be deduced from a parameter's default argument. + This avoids a redundant and error prone declaration of the default type. + ) + + --- + void previously(T=int)(T t = 0) { } // it was necessary to also specify a default type + void now(T)(T t = 0) { } // the default type can be deduced from the default argument as int + void main() { previously(); now(); } + --- +) + +$(LI $(LNAME2 invalid-cast-check, Invalid reinterpret casts can be detected in the frontend.) + + $(P Invalid reinterpret casts are now detected in the compiler frontend + instead of the backend. This allows to check for possible reinterpret + casts during compile time and improves the error messages for invalid + casts. + ) + + --- + pragma(msg, is(typeof({ void* x; auto y = cast(void delegate())x; }))); + // Since 2.067: it prints 'true' + // From 2.068: it prints 'false' + + void test() { void* x; auto y = cast(void delegate())x; } + // Since 2.067: it had reported internal compiler error "Error: e2ir: cannot cast ..." + // From 2.068: it reports proper frontend error. + --- +) + +) + +$(BUGSTITLE Library Changes, + +$(LI $(LNAME2 rangified-functions, Many phobos functions were rangified.) + + $(P Many phobos functions that allocated GC memory were changed to support + ranges or were complemented by an alternative supporting ranges. + Using ranges often eliminates GC allocations. + ) + + --- + setExtension("foo.jpg", ".png"); // allocates a new string + withExtension("foo.jpg", ".png"); // returns a range without allocating + --- + + $(BOOKTABLE Rangified Functions:, + $(TR $(TH Module) $(TH Functions) + ) + $(TR $(TD $(MREF std,algorithm,comparison)) + $(TD + $(REF_SHORT levenshteinDistance, std,algorithm_comparison) + ) + ) + $(TR $(TD $(MREF std,path)) + $(TD + $(REF_SHORT asAbsolutePath, std,path) + $(REF_SHORT asNormalizedPath, std,path) + $(REF_SHORT asRelativePath, std,path) + $(REF_SHORT chainPath, std,path) + $(REF_SHORT dirName, std,path) + $(REF_SHORT driveName, std,path) + $(REF_SHORT filenameCmp, std,path) + $(REF_SHORT globMatch, std,path) + $(REF_SHORT isValidFilename, std,path) + $(REF_SHORT isValidPath, std,path) + $(REF_SHORT pathSplitter, std,path) + $(REF_SHORT rootName, std,path) + $(REF_SHORT stripExtension, std,path) + $(REF_SHORT withDefaultExtension, std,path) + $(REF_SHORT withExtension, std,path) + ) + ) + $(TR $(TD $(MREF std,string)) + $(TD + $(REF_SHORT centerJustifier, std,string) + $(REF_SHORT chomp, std,string) + $(REF_SHORT chompPrefix, std,string) + $(REF_SHORT chop, std,string) + $(REF_SHORT column, std,string) + $(REF_SHORT detabber, std,string) + $(REF_SHORT entabber, std,string) + $(REF_SHORT indexOf, std,string) + $(REF_SHORT leftJustifier, std,string) + $(REF_SHORT makeTransTable, std,string) + $(REF_SHORT rightJustifier, std,string) + $(REF_SHORT soundexer, std,string) + $(REF_SHORT strip, std,string) + $(REF_SHORT stripLeft, std,string) + $(REF_SHORT stripRight, std,string) + ) + ) + $(TR $(TD $(MREF std,uni)) + $(TD + $(REF_SHORT asCapitalized, std,uni) + $(REF_SHORT asLowerCase, std,uni) + $(REF_SHORT asUpperCase, std,uni) + ) + ) + ) +) + +$(LI $(LNAME2 gc-api-profile, GC API calls can now be profiled separately.) + + $(P The $(RELATIVE_LINK2 gc-options, GC option) `--DRT-gcopt=profile` has been + enhanced to accept an additional level 2 that allows profiling API calls grouped + by most common operations. + ) + $(P As this instrumentation has an impact on the GC performance even if unused, you have + to recompile the GC module with -debug=PROFILE_API, e.g. + ) + --- + dmd test.d -O -inline -debug=PROFILE_API -Ipath-to-druntime/src path-to-druntime/src/gc/gc.d + ./test --DRT-gcopt=profile:2 + --- + + The profiling summary will then look like this: + --- + malloc: 9768628 calls, 531 ms + realloc: 0 calls, 0 ms + free: 0 calls, 0 ms + extend: 1100 calls, 0 ms + other: 826 calls, 0 ms + lock time: 160 ms + GC API: 692 ms + GC summary: 12 MB, 52 GC 331 ms, Pauses 227 ms < 4 ms API 692 ms + --- + $(P The malloc function includes time for GC collections. Lock time (GC + synchronization) is measured separately and not included in the other + times. + ) +) + +$(LI $(LNAME2 aa-open-addressing, The AA implementation now uses open addressing.) + + $(P The runtime implementation for associative arrays was rewritten and now + uses open addressing with $(LINK2 https://en.wikipedia.org/wiki/Quadratic_probing, quadratic probing) + and triangular numbers. This is much more cache friendly than the old + $(LINK2 https://en.wikipedia.org/wiki/Hash_table#Separate_chaining, separate chaining) + implementation and can result in ~25% faster lookups for big AAs. Also see $(DRUNTIMEPR 1229). + ) + + AA benchmarks + + $(P $(RED Note:) As the allocation pattern changed (the table is bigger, nodes + are smaller) you might see a small drop in performance because the GC manages + big allocations less efficiently. + ) +) + +) + +$(BR)$(BIG $(LNAME2 list2068, List of all bug fixes and enhancements in D 2.068:)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 9279): [REG2.055/2.063] Static array return value implicitly converted to immutable dynamic array) +$(LI $(BUGZILLA 12984): [REG2.068a] ICE on forward reference of derived class from other instantiated class) +$(LI $(BUGZILLA 13816): [REG2.066.0] The compiler crashes with recursive tuple expansion) +$(LI $(BUGZILLA 14207): [REG2.065] [CTFE] ICE on unsupported reinterpret cast in compile time) +$(LI $(BUGZILLA 14351): [REG2.063] `inout` base class constructor can't be called) +$(LI $(BUGZILLA 14390): [REG2.068a] ICE or bad "has forward references" error with circular class structure) +$(LI $(BUGZILLA 14406): [REG2.068a] GIT HEAD ignores forward reference and generates wrong code) +$(LI $(BUGZILLA 14430): [REG2.060] Null parameter is detected as non-null.) +$(LI $(BUGZILLA 14468): [Reg 2.068.0-devel] overload mismatch for template instance with typesafe variadic parameter) +$(LI $(BUGZILLA 14481): [REG2.066] ICE with forward reference of manifest constant on template arguments) +$(LI $(BUGZILLA 14520): [REG2.067.0] string/alias template overload) +$(LI $(BUGZILLA 14528): [REG2.058a] can't pass protected member to template by alias) +$(LI $(BUGZILLA 14546): "ClockType.uptime is not supported by MonoTimeImpl on this system") +$(LI $(BUGZILLA 14549): isVirtualMethod does not work well with Github DMD) +$(LI $(BUGZILLA 14552): [REG2.066] SIGSEGV with compile construction nested class in predicate) +$(LI $(BUGZILLA 14556): [REG2.067] can't instantiate struct that has constructor and static array of enum) +$(LI $(BUGZILLA 14560): [REG2.058] Strange -inline behavior) +$(LI $(BUGZILLA 14568): [REG2.067] gaggederrors ICE) +$(LI $(BUGZILLA 14571): [REG2.064] Large static arrays seem to lock up DMD) +$(LI $(BUGZILLA 14572): cannot build dmd from source anymore: 'g++ -m64: No such file or directory') +$(LI $(BUGZILLA 14573): [REG2.067] Extreme memory usage when `synchronized$(LPAREN) object $(RPAREN)` is used) +$(LI $(BUGZILLA 14587): [REG2.064] generated 64 bit code for switch jump tables is wrong) +$(LI $(BUGZILLA 14594): [REG2.068a] DDoc for template functions and structs has disappeared) +$(LI $(BUGZILLA 14606): [REG2.067.0] Bad code with -inline and structs) +$(LI $(BUGZILLA 14609): [REG2.068a] Github HEAD: DMD assertion failure for valid code) +$(LI $(BUGZILLA 14610): [REG2.067] 'null this' assertion missing in 2.067) +$(LI $(BUGZILLA 14634): dmd crashes without any input) +$(LI $(BUGZILLA 14642): [REG2.066] ICE in ctfeInterpret) +$(LI $(BUGZILLA 14666): [REG2.061] Bogus forward reference error) +$(LI $(BUGZILLA 14672): [REG2.067.0] Internal error: e2ir.c 4620 when copying array of derived class to an array of base class) +$(LI $(BUGZILLA 14805): [REG2.064] Unreasonably slow "new Struct[large]") +$(LI $(BUGZILLA 14806): [REG2.063] alias this doesn't force elaborate equality, but is followed during it) +$(LI $(BUGZILLA 14814): ld: GOT load reloc does not point to a movq instruction) +$(LI $(BUGZILLA 14828): [REG2.067] duplicate symbol __ModuleInfoZ depending on ordering of files passed to dmd) +$(LI $(BUGZILLA 14829): [REG2.066.0] wrong code with -O -inline) +$(LI $(BUGZILLA 14834): [REG 2.068-b2] dirEntries with mask stopped working with "-inline -debug") +$(LI $(BUGZILLA 14836): [REG2.068a] Multiple variadic template argument trick broken) +$(LI $(BUGZILLA 14838): [REG 2.066] Wrong attribute inference for auto-generated class destructor with static array of non-POD type) +$(LI $(BUGZILLA 14844): [REG2.068a] __traits$(LPAREN)allMembers$(RPAREN) must not visit yet not instantiated template members) +$(LI $(BUGZILLA 14851): [REG2.068.0-b2] Cannot assign array operation result to static array variable) +$(LI $(BUGZILLA 14853): [REG2.066] DMD segfaults with the cast from mutable struct new to shared) +$(LI $(BUGZILLA 14890): [REG 2.068.0-rc1] Can not construct a RedBlackTree of Tuples) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 1759): Closures and With Statements) +$(LI $(BUGZILLA 2803): template + default argument = doesn't work) +$(LI $(BUGZILLA 3869): Unreasonable error without line number: "recursive template expansion") +$(LI $(BUGZILLA 5770): Template constructor bypass access check) +$(LI $(BUGZILLA 6613): Can't use empty tuple as default value for variadic template function parameter) +$(LI $(BUGZILLA 6766): Forward reference error for default struct/class arguments) +$(LI $(BUGZILLA 8217): static nested class can reference outer scope by template instantiation) +$(LI $(BUGZILLA 8234): symbols used in CTFE affect the function literal type) +$(LI $(BUGZILLA 9023): CTFE: cannot use ~= on an empty AA.) +$(LI $(BUGZILLA 10158): 'offsetof' property of nested struct does not work properly) +$(LI $(BUGZILLA 10282): Refused assignment of vector op result to const array) +$(LI $(BUGZILLA 10492): Illegal Instruction for mixin template with scope declarations) +$(LI $(BUGZILLA 10972): aggregate postblit doesn't clean up in case of failure) +$(LI $(BUGZILLA 11166): Forward reference error when alias of template instance is private) +$(LI $(BUGZILLA 12036): Wrong code with auto-returning function as mixin alias param) +$(LI $(BUGZILLA 12152): Cannot forward reference subclass member in superclass) +$(LI $(BUGZILLA 12406): Broken delegate closure) +$(LI $(BUGZILLA 12603): [CTFE] goto does not correctly call dtors) +$(LI $(BUGZILLA 12799): Forward reference to nested enum with struct.sizeof) +$(LI $(BUGZILLA 12971): Missing REX prefix for 8 bit register access) +$(LI $(BUGZILLA 13270): ddoc can't find parameters of ditto'd function overloads) +$(LI $(BUGZILLA 13920): DMD crash when trying to set a delegate from __traits$(LPAREN)getOverloads$(RPAREN)) +$(LI $(BUGZILLA 13985): Wrong code when using "super" to call final interface method) +$(LI $(BUGZILLA 14097): root/async.c: use after free) +$(LI $(BUGZILLA 14185): [ICE] [mtype.c] compiler segfault in in Type::aliasthisOf) +$(LI $(BUGZILLA 14243): mixin template scope inconsistency?) +$(LI $(BUGZILLA 14249): Loose error check for incorrect template mixin) +$(LI $(BUGZILLA 14264): Destructor not called when struct is returned from a parenthesis-less function call) +$(LI $(BUGZILLA 14268): Win64: debug info for associative arrays have no type information) +$(LI $(BUGZILLA 14281): duplicate .debug_info entries for arrays, delegates and AAs) +$(LI $(BUGZILLA 14290): is-expression accepts instantiation of already instantiated template) +$(LI $(BUGZILLA 14320): Improve diagnostic message for "undefined identifier" error) +$(LI $(BUGZILLA 14321): Unnecessary destructor call with and AAs) +$(LI $(BUGZILLA 14325): [CTFE] Comparison of AAs makes wrong result) +$(LI $(BUGZILLA 14330): Wrong DWARF type of dynamic array variable) +$(LI $(BUGZILLA 14343): Postfix increment doesn't work on structs with immutable member) +$(LI $(BUGZILLA 14348): typeof$(LPAREN)x$(RPAREN).ident is not accepted as a symbol) +$(LI $(BUGZILLA 14352): Two goto cases in one case branch does not work correctly) +$(LI $(BUGZILLA 14357): Match on specType does not check the conflict with already deduced template arguments) +$(LI $(BUGZILLA 14371): [CTFE] Binary assignment expression makes wrong result in compile-time) +$(LI $(BUGZILLA 14388): ICE with idup-ed struct literal in template argument) +$(LI $(BUGZILLA 14398): Segfault when nested struct in static array accesses context) +$(LI $(BUGZILLA 14407): No protection and attributes check for class/struct allocator in NewExp) +$(LI $(BUGZILLA 14409): false positive "Error: one path skips constructor") +$(LI $(BUGZILLA 14416): .sizeof yields 1 for uninstantiated struct templates) +$(LI $(BUGZILLA 14425): Indirect template instantiation within is expression causes missing linker symbols) +$(LI $(BUGZILLA 14446): ICE on invalid import) +$(LI $(BUGZILLA 14510): Bad tail call optimization with static arrays) +$(LI $(BUGZILLA 14596): Error: e2ir: cannot cast malloc$(LPAREN)42u$(RPAREN) of type void* to type char[]) +$(LI $(BUGZILLA 14617): PTHREAD_MUTEX_INITIALIZER does not work on OSX) +$(LI $(BUGZILLA 14629): Type system breaking and wrong code bugs in casting reference types to typeof$(LPAREN)null$(RPAREN)) +$(LI $(BUGZILLA 14649): ICE on invalid array operation with string literals) +$(LI $(BUGZILLA 14656): "auto" of "auto ref" spills over to other function) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 9914): Do attribute inference for auto functions) +$(LI $(BUGZILLA 11003): Improve .di generation) +$(LI $(BUGZILLA 14465): CTFE exception stacktrace shows location of Exception constructor) +$(LI $(BUGZILLA 14547): Ddoc should prefer new Variable Template syntax) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 14712): GIT HEAD : std.net.curl regressions) +$(LI $(BUGZILLA 14748): Removing std.stdio import causes 2x increase in "Hello, world" program binary filesize) +$(LI $(BUGZILLA 14765): [Reg2.068.0] Rangified functions no longer accept types that implicitly cast to string) +$(LI $(BUGZILLA 14842): [REG 2.068-b2] approxEqual does not work with integers) +$(LI $(BUGZILLA 14881): [REG] posix.mak omits package.d files when building zip file) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 12702): [FixIncluded] std.container.RedBlackTree's in operator is not const) +$(LI $(BUGZILLA 13534): std.variant can violate memory safety) +$(LI $(BUGZILLA 14282): executeShell should use sh and ignore the SHELL env variable) +$(LI $(BUGZILLA 14373): std.range.refRange doesn't work on mere input ranges) +$(LI $(BUGZILLA 14408): std.process: Can't start interactive process from Windows GUI application) +$(LI $(BUGZILLA 14422): std.process: Pipes do not append to files on Win64) +$(LI $(BUGZILLA 14469): file.readText on Win64 doesn't work for files > 4GB.) +$(LI $(BUGZILLA 14526): GetOptException DDOC needs cleanup) +$(LI $(BUGZILLA 14544): isForwardRange failed to recognise valid forward range) +$(LI $(BUGZILLA 14575): compile error with std.range.refRange when front/back isn't implicitly convertible from const to mutable) +$(LI $(BUGZILLA 14585): destructor called on garbage in std.variant) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 14194): nothrow emplace for classes needed) +$(LI $(BUGZILLA 14288): std.windows.registry should use std.windows.syserror) +$(LI $(BUGZILLA 14289): WindowsException should not attempt to parse code 0) +$(LI $(BUGZILLA 14368): stdio.rawRead underperforms stdio) +$(LI $(BUGZILLA 14432): move construction for RefCounted) +$(LI $(BUGZILLA 14457): Algebraic does not allow assignment from subset type) +$(LI $(BUGZILLA 14535): std.net.curl.CurlException should include status line) +$(LI $(BUGZILLA 14548): std.stdio.File should have sync$(LPAREN)$(RPAREN) method $(LPAREN)fsync/FlushFileBuffers wrapper$(RPAREN)) +$(LI $(BUGZILLA 14586): can't get an immutable value from a const std.variant.Variant) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 14626): [REG2.066] byValue doesn't work with inout AA) +$(LI $(BUGZILLA 14746): [REG2.068a] Behavior change with struct destructor and alias this) +$(LI $(BUGZILLA 14863): CLOCK_BOOTTIME should be optional to support <2.6.39 kernels) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 6607): critical_.d and critical.c use double check locking the wrong way) +$(LI $(BUGZILLA 12289): incorrect core.stdc.stdio.fpos_t alias) +$(LI $(BUGZILLA 14350): Unit test failures are not displayed in Windows GUI programs) +$(LI $(BUGZILLA 14401): typeid$(LPAREN)shared X$(RPAREN).init is empty for class types) +$(LI $(BUGZILLA 14423): struct destructors not finalized for AA values) +$(LI $(BUGZILLA 14464): coverage merge doesn't work) +$(LI $(BUGZILLA 14476): core.thread unit tests failing on FreeBSD 9+) +$(LI $(BUGZILLA 14511): Profiler does not work with multithreaded programs) +$(LI $(BUGZILLA 14565): dmd -profile produces garbled output for long-running CPU-intensive processes) +) +$(BUGSTITLE Druntime enhancements, + +$(LI $(BUGZILLA 12891): add atomicFetchAdd and atomicFetchSub to core.atomic) +$(LI $(BUGZILLA 14385): AA should use open addressing hash) +) +$(BUGSTITLE dlang.org bugs, + +$(LI $(BUGZILLA 12803): __traits$(LPAREN)getFunctionAttributes$(RPAREN) is not documented) +$(LI $(BUGZILLA 13527): ddoc website documentation does not match the current built-in symbols) +$(LI $(BUGZILLA 14079): Variable templates' documentation not generated.) +$(LI $(BUGZILLA 14080): No mention of documented unittests on ddoc's page) +$(LI $(BUGZILLA 14326): syntax highlighting of dpl-docs no longer works) +$(LI $(BUGZILLA 14418): D-style Variadic Function example does not compile) +) +$(BUGSTITLE Tools bugs, + +$(LI $(BUGZILLA 13758): RDMD renames directory if -ofNAME is the name of a directory) +$(LI $(BUGZILLA 14259): rdmd: --build-only / -of / -od incompatible with --dry-run) +) +$(BUGSTITLE Installer bugs, + +$(LI $(BUGZILLA 14801): OS X installer not compatible with OS X 10.11) +$(LI $(BUGZILLA 14864): windows uninstall during installation pops up spurious warning) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.068.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.068.1.dd b/changelog/2.068.1.dd new file mode 100644 index 0000000000..e42f60df45 --- /dev/null +++ b/changelog/2.068.1.dd @@ -0,0 +1,92 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 06, 2015, =================================================, + +$(BUGSTITLE Library Changes, +$(LI $(RELATIVE_LINK2 coverage-profile-config, Functions to configure coverage, profile, and profile=gc reports were added.)) +) + +$(BR)$(BIG $(RELATIVE_LINK2 list2068_1, List of all bug fixes and enhancements in D 2.068.1.)) + +$(HR) + +$(BUGSTITLE Library Changes, + +$(LI $(LNAME2 coverage-profile-config, Functions to configure coverage, profile, and profile=gc reports were added.) + + $(P While they have been accessible through `extern(C)` linkage + for a while, the functions to configure coverage, profile, and + profile=gc reports where added to $(MREF core,runtime). + ) + + $(BOOKTABLE, + $(TR $(TH Functions) $(TH Decscription)) + $(TR $(TD $(REF_SHORT dmd_coverSourcePath, core,runtime)) $(TD Set the directory which contains the source files.)) + $(TR $(TD $(REF_SHORT dmd_coverDestPath, core,runtime)) $(TD Set the directory where to write the -cov reports.)) + $(TR $(TD $(REF_SHORT dmd_coverSetMerge, core,runtime)) $(TD Set whether or not to merge results with existing -cov reports.)) + $(TR $(TD $(REF_SHORT trace_setlogfilename, core,runtime)) $(TD Set the output file for the -profile report.)) + $(TR $(TD $(REF_SHORT trace_setdeffilename, core,runtime)) $(TD Set the output file for the optimized -profile linker script.)) + $(TR $(TD $(REF_SHORT profilegc_setlogfilename, core,runtime)) $(TD Set the output file for the -profile=gc report.)) + ) + + $(P Note that these functions are specific to dmd, and might not + be available on other compilers. + ) +) + +) + +$(BR)$(BIG $(LNAME2 list2068_1, List of all bug fixes and enhancements in D 2.068.1:)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 14431): [REG 2.067.0] huge slowdown of compilation speed) +$(LI $(BUGZILLA 14621): [REG2.066] ICE: Assertion failure: 'global.gaggedErrors || global.errors' on line 752 in file 'statement.c') +$(LI $(BUGZILLA 14781): [REG2.067] impure delegate to pure function context should be able to modify context) +$(LI $(BUGZILLA 14901): [reg 2.067/2.068] template static shared this$(LPAREN)$(RPAREN) run multiple times with separate compilation) +$(LI $(BUGZILLA 14911): Compiler found indexing in code "new MyStruct[2].ptr") +$(LI $(BUGZILLA 14923): [REG2.067] ICE: Assertion failed: $(LPAREN)tret->ty != Tvoid$(RPAREN), function semantic3, file func.c, line 1736.) +$(LI $(BUGZILLA 14926): Programs compiled using dmd 2.068 are generating dummy profilegc.log files) +$(LI $(BUGZILLA 14929): [REG2.067] ICE: Assertion failure: 'ez->exp $(AMP)$(AMP) ez->exp->op == TOKconstruct' on line 302 in file 'escape.c') +$(LI $(BUGZILLA 14944): [REG2.064] cannot initialize static array by static this$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 14948): [Reg 2.068.0] AA key requirement was broken w/o notice and w/ horrible error message) +$(LI $(BUGZILLA 14962): [REG2.068] compiler inference of attributes for nested map seems broken) +$(LI $(BUGZILLA 14973): [REG2.068] compiler inference of contexts for nested map seems broken) +$(LI $(BUGZILLA 14985): [REG2.068.1-b1] Link failure for const TypeInfo of speculative instantiated struct) +$(LI $(BUGZILLA 14986): [REG2.068.1-b2] Assertion failed: $(LPAREN)id->dyncast$(LPAREN)$(RPAREN) == DYNCAST_DSYMBOL$(RPAREN)) +$(LI $(BUGZILLA 15002): [REG2.064] ICE with invalid static variable initializer while CTFE) +$(LI $(BUGZILLA 15017): [REG2.068.1-b2] assigning a Variant to be value in a hashmap) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 14624): The array operator overloading fallback is not correct) +$(LI $(BUGZILLA 14625): opIndex$(LPAREN)$(RPAREN) doesn't work on foreach container iteration) +$(LI $(BUGZILLA 14696): destructor for temporary called before statement is complete with conditional operator) +$(LI $(BUGZILLA 14708): destructor for temporary not called during stack unwinding) +$(LI $(BUGZILLA 14889): ICE: Assertion `o->dyncast$(LPAREN)$(RPAREN) == DYNCAST_DSYMBOL' failed.) +$(LI $(BUGZILLA 14900): 2.068.0 change log example does not compile) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 13889): mscoff32 libs not available) +$(LI $(BUGZILLA 14951): Win64: Invalid C++ mangling for __gshared pointer variables) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 14904): [REG2.067.0] bad error message in reduce: 'Incompatible function/seed/element') +$(LI $(BUGZILLA 14920): [REG2.067.0] SList.insertAfter on uninitialized list triggers assertion in _first) +$(LI $(BUGZILLA 14980): [REG2.068] getAddressInfo$(LPAREN)null$(RPAREN) broken) +) +$(BUGSTITLE Installer bugs, + +$(LI $(BUGZILLA 14897): shared linux libraries from zip package don't work) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.068.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.068.2.dd b/changelog/2.068.2.dd new file mode 100644 index 0000000000..64f78db4f7 --- /dev/null +++ b/changelog/2.068.2.dd @@ -0,0 +1,27 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 23, 2015, =================================================, + +$(BUGSTITLE Compiler Changes, + +$(LI The fix for $(BUGZILLA 14708) was reverted: destructor for temporary not called during stack unwinding, see $(DMDPR 5110).) + +) + +$(BR)$(BIG List of all bug fixes and enhancements in D 2.068.2:) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 15021): [REG2.068.1] linker error with speculative instantiation and -inline) +$(LI $(BUGZILLA 15030): [REG2.068.1] ICE with recursive delegate, -unittest, and std.range) +$(LI $(BUGZILLA 15044): [REG2.068.0] destroy might leak memory) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.068.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.069.0.dd b/changelog/2.069.0.dd new file mode 100644 index 0000000000..b5c3049e7e --- /dev/null +++ b/changelog/2.069.0.dd @@ -0,0 +1,449 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Nov 3, 2015, =================================================, + +$(BUGSTITLE Compiler Changes, +$(LI $(RELATIVE_LINK2 self-hosted-dmd, DMD has been ported to D.)) +$(LI $(RELATIVE_LINK2 objective-c-support, Basic support for Objective-C.)) +$(LI $(RELATIVE_LINK2 property-switch-deprecated, The $(TT -property) switch has + been deprecated.)) +$(LI $(RELATIVE_LINK2 backend-improvements, DMD's codegen has improved.)) +) + +$(BUGSTITLE Library Changes, +$(LI The package $(MREF std,experimental,allocator) was added.) +$(LI $(RELATIVE_LINK2 more-rangified-functions, More phobos functions were rangified.)) +$(LI $(RELATIVE_LINK2 curl-dynamic-loading, libcurl is now loaded dynamically)) +$(LI $(RELATIVE_LINK2 backtraces-with-line-numbers, Backtraces now include file name and line number.)) +$(LI $(RELATIVE_LINK2 link-against-vs2015, Support to link against VS2015 libraries.)) +$(LI $(RELATIVE_LINK2 documentation-improvements, The documentation for Phobos has been improved.)) +$(LI $(RELATIVE_LINK2 std-algorithm-moveEmplace, `moveEmplace` was added)) +$(LI Use $(REF_SHORT isPermutation, std,algorithm_comparison) to test + whether two ranges are permutations of each other.) +$(LI The new $(REF_SHORT isSameLength, std,algorithm_comparison) can be more + efficient than comparing the $(REF_SHORT walkLength, std,range_primitives) of two + ranges.) +$(LI $(REF_SHORT getUDAs, std,traits) was added to help get + user-defined attributes of specific types from symbols.) +$(LI $(REF_SHORT getSymbolsByUDA, std,traits) was + added to find symbols with specific user-defined attributes.) +$(LI $(REF_SHORT cmp, std,math) was added, defining total ordering on + floating-point numbers, including NaN.) +$(LI FreeBSD now also ships with a shared libphobos2.so library ($(LINK2 https://dlang.org/dll-linux.html, usage info)).) +) + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D 2.069.0.)) + +$(HR) + +$(BUGSTITLE Compiler Changes, + +$(LI $(LNAME2 self-hosted-dmd, DMD has been ported to D.) + + $(P The DMD frontend code has been ported to D. Self-hosting the + compiler allows us to benefit from D's improved productivity + and modelling power. + ) +) + +$(LI $(LNAME2 objective-c-support, Basic support for Objective-C.) + + $(P Basic support for Objective-C classes, interfaces and instance methods. + This is implemented by adding a new linkage attribute, `Objective-C`, + and a compiler recognized UDA, `@selector`. The linkage attribute is to + be used on a class or interface. The UDA is attached to a method. + See $(LINK2 $(ROOT_DIR)spec/objc_interface.html, Interfacing to Objective-C) + for more information. + ) +) + +$(LI $(LNAME2 property-switch-deprecated, The $(TT -property) switch has + been deprecated.) + + $(P The $(TT -property) switch used to disallow calling non-properties + without parentheses. The switch has not been used to build Phobos for + some time now. So naturally, code that's incompatible with + $(TT -property) has found its way in. This means, the switch has + effectively not been supported by D at large. + ) + + $(P Since the behaviour of the $(TT -property) switch was not well-liked, + it's been deprecated and made to have no effect when used. + ) + + $(P The $(A $(ROOT_DIR)spec/function.html#property-functions,$(D @property) + attribute) is not affected, and remains as a mostly cosmetic keyword. + Its semantics are going to be revisited in the future. + ) +) + +$(LI $(LNAME2 backend-improvements, DMD's codegen has improved.) + + $(P Several improvements have been made to the backend's codegen. Parameters + and stack frame set up are optimized to use `SUB`/`MOV` instead of `PUSH`, + resulting in 30% faster code in some cases. Also, functions marked as + `nothrow` no longer generate a BP stack frame on Windows and Linux. + ) +) + +) + +$(BUGSTITLE Library Changes, + +$(LI $(LNAME2 more-rangified-functions, More phobos functions were rangified.) + + $(P Following the work released with $(LINK2 2.068.0.html#rangified-functions, + 2.068.0) more phobos functions were rangified. + ) + + $(BOOKTABLE Rangified Functions:, + $(TR $(TH Module) $(TH Functions) + ) + $(TR $(TD $(MREF std,stdio)) + $(TD + $(REF_SHORT File.this, std,stdio) + ) + ) + $(TR $(TD $(MREF std,file)) + $(TD + $(REF_SHORT append, std,file) + $(REF_SHORT chdir, std,file) + $(REF_SHORT copy, std,file) + $(REF_SHORT exists, std,file) + $(REF_SHORT getAttributes, std,file) + $(REF_SHORT getLinkAttributes, std,file) + $(REF_SHORT getSize, std,file) + $(REF_SHORT getTimes, std,file) + $(REF_SHORT getTimesWin, std,file) + $(REF_SHORT isDir, std,file) + $(REF_SHORT isFile, std,file) + $(REF_SHORT isSymlink, std,file) + $(REF_SHORT mkdir, std,file) + $(REF_SHORT read, std,file) + $(REF_SHORT readText, std,file) + $(REF_SHORT remove, std,file) + $(REF_SHORT rename, std,file) + $(REF_SHORT rmdir, std,file) + $(REF_SHORT setAttributes, std,file) + $(REF_SHORT setTimes, std,file) + $(REF_SHORT timeLastModified, std,file) + $(REF_SHORT write, std,file) + ) + ) + ) +) + +$(LI $(LNAME2 curl-dynamic-loading, libcurl is now loaded dynamically) + + $(P $(MREF std,net,curl) was changed to load curl as shared + library at runtime. This simplifies the usage as it's no longer + necessary to link against libcurl or to install any development + libraries. + ) + + $(P The implementation will also try to get the needed curl symbols from the + executable itself. So it remains possible to link with a specific + version of libcurl or with a static libcurl library. + ) + + $(P To make this work you have to link with $(I --export-dynamic) respectively + use a $(I .DEF) file on Windows (see $(LINK2 + https://wiki.dlang.org/Curl_on_Windows#Using_the_static_lib, wiki) for + more info on the latter). + ) +) + +$(LI $(LNAME2 backtraces-with-line-numbers, Backtraces now include file name and line number.) + + $(P The default tracehandler on linux and FreeBSD now parses DWARF + debug info to add file names and line numbers to backtraces. + ) + + $(PRE +std.conv.ConvException@DPL/dmd/src/../../phobos/std/conv.d(1720): Unexpected 'a' when converting from type string to type ulong + +DPL/dmd/src/../../phobos/std/conv.d:1720 pure @safe ulong std.conv.toImpl!(ulong, immutable(char)[]).toImpl(immutable(char)[]) [0x43b339] +DPL/dmd/src/../../phobos/std/conv.d:298 pure @safe ulong std.conv.to!(ulong).to!(immutable(char)[]).to(immutable(char)[]) [0x437717] +example.d:5 ulong example.foo(immutable(char)[]) [0x4376c7] +example.d:10 _Dmain [0x4376e5] +??:? _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv [0x444576] +??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x4444cc] +??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() [0x444532] +??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x4444cc] +??:? _d_run_main [0x444429] +??:? main [0x44039f] +??:? __libc_start_main [0xc3ae96ff] + ) +) + +$(LI $(LNAME2 link-against-vs2015, Support to link against VS2015 libraries.) + + $(P Support for linking against the Microsoft runtime library distributed with VS 2015 + has been added. This affects both the 64-bit build for Win64 and the 32-bit build + targeting the MS runtime (-m32mscoff). + ) + + $(P The compiler detects the library version to adjust the link command line automatically. + If you don't use dmd for linking, make sure to add legacy_stdio_definitions.lib to your + command line when linking against the VS2015 runtime. + ) +) + +$(LI $(LNAME2 documentation-improvements, The documentation for Phobos has been improved) + + $(P A large portion of the functions in Phobos have improved documentation, including but + not limited to spelling fixes, clarifications, better explanations of function and template + parameters, and better explanations of return values. + ) +) + +$(LI $(LNAME2 std-algorithm-moveEmplace, A combined `moveEmplace` was added.) + + $(P $(REF_SHORT moveEmplace, std,algorithm_mutation) efficiently combines + $(REF_SHORT move, std,algorithm_mutation) with $(REF_SHORT emplace, std,conv) thus avoids + having to initialize and destroy a value before moving into uninitialized data. + ) + + ------ + T* moveToHeap(T)(ref T value) + { + import core.memory : GC; + + auto ptr = cast(T*)GC.malloc(T.sizeof); + // move value and emplace it into ptr + moveEmplace(value, *ptr); + return ptr; + } + ------ + $(P There are also $(REF_SHORT moveEmplaceAll, std,algorithm_mutation) + and $(REF_SHORT moveEmplaceSome, std,algorithm_mutation) as counterparts of + $(REF_SHORT moveAll, std,algorithm_mutation) and $(REF_SHORT moveSome, std,algorithm_mutation). + ) +) + +) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D 2.069.0:)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 13720): [REG2.067] Adding trivial destructor to std.datetime causes Internal error: ..\ztc\cgelem.c 2418) +$(LI $(BUGZILLA 14430): [REG2.060] Null parameter is detected as non-null.) +$(LI $(BUGZILLA 14572): cannot build dmd from source anymore: 'g++ -m64: No such file or directory') +$(LI $(BUGZILLA 14588): [REG2.067] undefined reference error while linking with -debug option to a static library.) +$(LI $(BUGZILLA 14682): [REG2.037] Incorrect interpretation of ~ []) +$(LI $(BUGZILLA 14699): [REG2.062] ICE: segfaults on array with zero size) +$(LI $(BUGZILLA 14710): VC-built DMD crashes on templated variadic function IFTI) +$(LI $(BUGZILLA 14731): [REG2.068a] Error location insufficient when CTFE) +$(LI $(BUGZILLA 14735): [REG2.068-b1] std.string.indexOf cannot deduce function for char argument) +$(LI $(BUGZILLA 14737): [REG2.058] A concatenation of array literal and static array should make dynamic array) +$(LI $(BUGZILLA 14754): [REG2.068b1] 64bit wrong code with -inline) +$(LI $(BUGZILLA 14779): incorrect addressing of arguments in require/in-contract) +$(LI $(BUGZILLA 14829): [REG2.066.0] wrong code with -O -inline) +$(LI $(BUGZILLA 14886): [REG2.066] std.parallelism.parallel with large static array seems to hang compile) +$(LI $(BUGZILLA 14926): Programs compiled using dmd 2.068 are generating dummy profilegc.log files) +$(LI $(BUGZILLA 14952): Redundant REX.W before FSTP confuses Valgrind) +$(LI $(BUGZILLA 14991): dmd doesn't build under OSX 32 bit) +$(LI $(BUGZILLA 15045): [Reg 2.069-devel] hasElaborateCopyConstructor is true for struct with opDispatch) +$(LI $(BUGZILLA 15072): [REG2.069-devel] Re-introducing codegen performance regression 14805) +$(LI $(BUGZILLA 15079): [REG2.068.1] Assertion `fd->semanticRun == PASSsemantic3done' failed.) +$(LI $(BUGZILLA 15092): [REG2.066.0] ICE on duplicated struct declarations in class members) +$(LI $(BUGZILLA 15123): [REG2.069.0-devel] segfault when compiling simple SIMD code) +$(LI $(BUGZILLA 15126): [REG2.069-devel] dmd crashes when analyzing array literal) +$(LI $(BUGZILLA 15138): [REG2.068.2] ICE with basic use of stdx.data.json) +$(LI $(BUGZILLA 15149): [REG2.068.1] Linker error with separate compilation) +$(LI $(BUGZILLA 15150): [REG2.068.1] Public selective import causes conflict) +$(LI $(BUGZILLA 15152): [REG2.069.0-devel] template fails to instantiate if argument is itself a template) +$(LI $(BUGZILLA 15168): [REG2.068.0] std.variant.Algebraic interacts badly with string alias this sub-types) +$(LI $(BUGZILLA 15176): [REG2.069.0-b1] ICE$(LPAREN)glue.c$(RPAREN):separate compilation with -inline crash in glue.c) +$(LI $(BUGZILLA 15177): [REG2.069.0-b1] mixin + traits issue with 2.069 beta 1) +$(LI $(BUGZILLA 15181): SYSCONFDIR is broken) +$(LI $(BUGZILLA 15200): [REG2.068.2] ICE$(LPAREN)glue.c$(RPAREN) when compiling with -inline) +$(LI $(BUGZILLA 15207): [REG2.069.0-b1] Wrong codegen with -inline) +$(LI $(BUGZILLA 15210): [REG2.064][ICE] $(LPAREN)glue.c at 1489$(RPAREN) with tuples and AAs) +$(LI $(BUGZILLA 15214): [REG2.065.0] ICE in Mangler::mangleFunc) +$(LI $(BUGZILLA 15251): [REG2.069.0-rc1] std.datetime bug with -inline) +$(LI $(BUGZILLA 15253): [REG2.069.0-rc1] inliner prevent compilation) +$(LI $(BUGZILLA 15272): [2.069-rc2,inline] nothing written to output when -inline is set) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 1747): class to base interface static cast is incorrect in some cases) +$(LI $(BUGZILLA 2013): interface to interface dynamic cast is incorrect in some cases) +$(LI $(BUGZILLA 2091): D2 final cannot be applied to variable) +$(LI $(BUGZILLA 2354): conditional compilation rejects else if the declaration is a single pragma) +$(LI $(BUGZILLA 3243): instantiated 'static this$(LPAREN)$(RPAREN)' bring on a compiler message ': __gate is thread local') +$(LI $(BUGZILLA 6417): Wrong context for nested functions in virtual class member function contracts) +$(LI $(BUGZILLA 7625): inlining only works with explicit else branch) +$(LI $(BUGZILLA 7979): Alias this does not work with switch) +$(LI $(BUGZILLA 9383): Wrong context for contracts if closure [dis]appears in override function) +$(LI $(BUGZILLA 9891): Ability to modify immutable using default value of ref/out parameter) +$(LI $(BUGZILLA 12487): DMD correctly reports excessive CTFE recursion, but not template recursion) +$(LI $(BUGZILLA 12744): auto ref crashes DMD on ASSERT) +$(LI $(BUGZILLA 13007): Wrong x86 code: long negate) +$(LI $(BUGZILLA 13203): conflicting aliases allowed with static if) +$(LI $(BUGZILLA 13244): Wrong code with -inline and foreach/map/all) +$(LI $(BUGZILLA 13652): 2D Static Array Init produces wrong result $(LPAREN)-m64/-m32$(RPAREN)) +$(LI $(BUGZILLA 13792): Segfault with a pointer of opaque enum type) +$(LI $(BUGZILLA 14140): Bad codegen for CTFE union initialisers for immutable structs) +$(LI $(BUGZILLA 14459): String literal merge bug causes incorrect runtime program behavior) +$(LI $(BUGZILLA 14510): Bad tail call optimization with static arrays) +$(LI $(BUGZILLA 14541): "duplicate COMDAT" linker error with the template forward reference in Tuple.opAssign) +$(LI $(BUGZILLA 14653): scoped!range in foreach crashes) +$(LI $(BUGZILLA 14669): auto attribute on function parameter should be error always) +$(LI $(BUGZILLA 14709): dmd/samples/listener.d socket.accept exception handling is incorrect) +$(LI $(BUGZILLA 14743): ICE in TemplateInstance::needsTypeInference$(LPAREN)$(RPAREN) with template forward reference) +$(LI $(BUGZILLA 14745): Qualifiers rejected for delegate literals) +$(LI $(BUGZILLA 14747): compiler insists on unnecessary return statement) +$(LI $(BUGZILLA 14753): pragma$(LPAREN)inline$(RPAREN) hides the alias "string") +$(LI $(BUGZILLA 14768): Error: index 174762 overflow for static array) +$(LI $(BUGZILLA 14802): Template argument deduction depends on order of arguments) +$(LI $(BUGZILLA 14815): Destructor is not called for static array assignment) +$(LI $(BUGZILLA 14818): Unhelpful "does not match template overload set" error) +$(LI $(BUGZILLA 14846): Insufficient context deduction with implicit nested lambda) +$(LI $(BUGZILLA 14858): spurious "Error: overload alias 'foo' is not a variable" when overloading template and non-template via aliases) +$(LI $(BUGZILLA 14860): Destructor is not called for block assignment) +$(LI $(BUGZILLA 14862): Constructor of overlapped struct does not initialize correctly global variables) +$(LI $(BUGZILLA 14874): __traits$(LPAREN)getFunctionAttributes$(RPAREN) does not support the new `return` attribute) +$(LI $(BUGZILLA 14875): A template instance with deprecated symbol/type needlessly repeats "Deprecation:" messages) +$(LI $(BUGZILLA 14876): Deprecation message is sometimes duplicated) +$(LI $(BUGZILLA 14906): dmd dumps core at incorrect enum declaration) +$(LI $(BUGZILLA 14928): Switches -betterC and -m32mscoff do not appear in DMD's help text) +$(LI $(BUGZILLA 14950): Setting enum value to the last member of another enum causes int overflow error) +$(LI $(BUGZILLA 14996): only$(LPAREN)EnumMembers!T$(RPAREN) eats all my memory when T : string) +$(LI $(BUGZILLA 15001): Duplicate error message without line number on if statement) +$(LI $(BUGZILLA 15014): Win64: Invalid C++ mangling for multiple long arguments) +$(LI $(BUGZILLA 15018): Win64: ICE when assigning struct of size 4 to slice) +$(LI $(BUGZILLA 15019): [ICE] Heisencrash on OS X 32-bit with non-trivial projects) +$(LI $(BUGZILLA 15065): associative array has no keys property) +$(LI $(BUGZILLA 15080): extern$(LPAREN)C++$(RPAREN) classes have wrong static data layout) +$(LI $(BUGZILLA 15089): Marks wrong line as where error occurs.) +$(LI $(BUGZILLA 15127): Parser assertion on wrong code) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 12421): Allow simpler syntax for lambda template declarations) +$(LI $(BUGZILLA 14717): Ddoc macro recursion limit too low) +$(LI $(BUGZILLA 14755): Could -profile=gc also give the number of allocations that led to X bytes being allocated?) +$(LI $(BUGZILLA 14975): DMD refuses to inline even trivial struct constructors) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 14564): [REG2.067] dmd -property -unittest combination causes compiler error) +$(LI $(BUGZILLA 14685): [REG2.067] Silent incorrect behavior with enforce and custom exception) +$(LI $(BUGZILLA 14712): GIT HEAD : std.net.curl regressions) +$(LI $(BUGZILLA 14817): [REG-master] copy$(LPAREN)"foo", "bar"$(RPAREN) std.algorithm/std.file conflict) +$(LI $(BUGZILLA 14881): [REG] posix.mak omits package.d files when building zip file) +$(LI $(BUGZILLA 15027): rangified functions no longer work with alias this'ed strings $(LPAREN)e.g. DirEntry$(RPAREN)) +$(LI $(BUGZILLA 15039): Algebraic cannot store a Typedef along with Typedef'ed type) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 10895): incorrect std.array.join behavior with array of string-like class using alias this) +$(LI $(BUGZILLA 13650): std.algorithm.copy doesn't work with char/wchar) +$(LI $(BUGZILLA 13856): std.stdio.readln stomps arrays) +$(LI $(BUGZILLA 14282): executeShell should use sh and ignore the SHELL env variable) +$(LI $(BUGZILLA 14605): RefAppender fails isOutputRange) +$(LI $(BUGZILLA 14724): std.getopt: config.required breaks --help) +$(LI $(BUGZILLA 14760): Clear content-length for libcurl option to eliminate segmentation fault.) +$(LI $(BUGZILLA 14762): Do not use other method options on persistent connection.) +$(LI $(BUGZILLA 14799): Documentation for std.zlib.compress is incorrect) +$(LI $(BUGZILLA 14868): MmFile destructor seems to corrupt memory) +$(LI $(BUGZILLA 14880): findSkip summary is wrong) +$(LI $(BUGZILLA 14884): `among` docs broken link to `find` and `canFind`) +$(LI $(BUGZILLA 14924): Error in std.uri definition/description) +$(LI $(BUGZILLA 14925): replaceInPlace fail compilation) +$(LI $(BUGZILLA 14949): Non-descriptive "Enforcement failed" when attempting to write to closed file) +$(LI $(BUGZILLA 14994): std.mmfile incorrectly handles map failure) +$(LI $(BUGZILLA 14995): std.mmfile incorrectly handles errors in ctor) +$(LI $(BUGZILLA 15000): Changes to userShell either need to be reverted or the std.process documentation needs to be updated) +$(LI $(BUGZILLA 15003): assumeSorted Allocates GC Memory in Debug Mode) +$(LI $(BUGZILLA 15033): Element type of float iota is double) +$(LI $(BUGZILLA 15115): std.typetuple link to std.meta is 404) +$(LI $(BUGZILLA 15187): dispose for allocators is broken) +$(LI $(BUGZILLA 15188): `deallocate` cause memory leaks) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 5945): redBlackTree printing) +$(LI $(BUGZILLA 12752): std.algorithm.isPermutation) +$(LI $(BUGZILLA 12966): Merge the heapsort code in std with the binary heap in std.range) +$(LI $(BUGZILLA 13596): permutations range) +$(LI $(BUGZILLA 14433): std.encoding does not support Central European ISO-8859-2 and CP1250 encodings) +$(LI $(BUGZILLA 14763): Use optionsData argument for curl options function.) +$(LI $(BUGZILLA 14777): 0 is not the initial value for std.zlib.adler32) +$(LI $(BUGZILLA 14798): [etc.c.sqlite3] sqlite3_errstr definition missing) +$(LI $(BUGZILLA 14877): std.net.curl needs PATCH http method) +$(LI $(BUGZILLA 14938): std.net.curl tests should use localhost or stub any networking) +$(LI $(BUGZILLA 14940): Can't call logger with more complex objects) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 14750): druntime/test/coverage was added to druntime, but not to the MANIFEST - zip file broken again) +$(LI $(BUGZILLA 14882): [REG] MANIFEST is missing test/common.mak) +$(LI $(BUGZILLA 14990): No rule to make target `src/core/sys/windows/stdio_msvc12.d', needed by 'druntime.zip'.) +$(LI $(BUGZILLA 14993): Allocating in a destructor segfaults instead of throwing InvalidMemoryOperationError) +$(LI $(BUGZILLA 15012): Druntime Makefile whitelists compilers) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 11414): druntime should run debug unittest) +$(LI $(BUGZILLA 14327): Unhandled exception from writeln$(LPAREN)$(RPAREN) in C++/D application) +$(LI $(BUGZILLA 14663): shared library test - link_linkdep - segfaults on FreeBSD 10) +$(LI $(BUGZILLA 14776): shared library test - loadDR - segfaults on FreeBSD 10 when not building with -release) +$(LI $(BUGZILLA 14785): Some corner cases are not handled properly by core.checkedint.) +$(LI $(BUGZILLA 14870): incorrect use of assert to detect environmental errors in core.time) +$(LI $(BUGZILLA 15009): Object.destroy calls unnecessary postblits for destruction of static arrays object) +$(LI $(BUGZILLA 15036): SimpleDllMain assumes various symbols are available unqualified) +$(LI $(BUGZILLA 15104): Switching fibers in finally blocks breaks EH) +) +$(BUGSTITLE Druntime enhancements, + +$(LI $(BUGZILLA 15076): Get ID of current thread) +$(LI $(BUGZILLA 15137): core.time: Support Duration/Duration and Duration%Duration) +) +$(BUGSTITLE dlang.org regressions, + +$(LI $(BUGZILLA 15046): [REG2.068] isForwardRange documentation is documenting issue 14544) +) +$(BUGSTITLE dlang.org bugs, + +$(LI $(BUGZILLA 12072): Regex article needs update) +$(LI $(BUGZILLA 14579): [SPEC] No specification on modifiers in TypeDelegate symbols) +$(LI $(BUGZILLA 14695): [dlang.org] std.uuid Is Not Listed On The Index Page) +$(LI $(BUGZILLA 14879): tuple documentation broken link) +$(LI $(BUGZILLA 15095): Malformed URL in documentation link) +) +$(BUGSTITLE dlang.org enhancements, + +$(LI $(BUGZILLA 14328): The terms "lvalue" and "rvalue" should be added to the glossary) +$(LI $(BUGZILLA 14522): Postfix array declaration examples should be removed from arrays.html) +$(LI $(BUGZILLA 14808): phobos sidebar "D Lib" link is back to homepage) +$(LI $(BUGZILLA 14933): specifications for the pragma$(LPAREN)mangle$(RPAREN) are vague) +) +$(BUGSTITLE Tools bugs, + +$(LI $(BUGZILLA 15031): rdmd should force rebuild when --compiler changes) +) +$(BUGSTITLE Tools enhancements, + +$(LI $(BUGZILLA 14715): Add README.md to the tools Repository) +) +$(BUGSTITLE Installer bugs, + +$(LI $(BUGZILLA 13234): Windows installer: when updating, uninstaller reports wrong installation directory) +$(LI $(BUGZILLA 14801): OS X installer not compatible with OS X 10.11) +) +$(BUGSTITLE Installer enhancements, + +$(LI $(BUGZILLA 14714): Add README.md to the Installer Repository) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.069.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.069.1.dd b/changelog/2.069.1.dd new file mode 100644 index 0000000000..f239ca2e3c --- /dev/null +++ b/changelog/2.069.1.dd @@ -0,0 +1,19 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Nov 11, 2015, =================================================, + +$(BR)$(BIG List of all bug fixes and enhancements in D $(VER):) + +$(BUGSTITLE Installer regressions, + +$(LI $(BUGZILLA 15284): dmd installer hangs when updating installed windows version) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.069.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.069.2.dd b/changelog/2.069.2.dd new file mode 100644 index 0000000000..dee8aeaf7d --- /dev/null +++ b/changelog/2.069.2.dd @@ -0,0 +1,32 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Dec 3, 2015, =================================================, + +$(BR)$(BIG List of all bug fixes and enhancements in D $(VER):) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 15292): [REG2.068.0] Segmentation fault with self-referencing struct / inout / alias this) +$(LI $(BUGZILLA 15296): [REG2.069] cannot inline simple function that calls use non-inlinable statements) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 15293): [REG2.069.0] std.stdio.readln$(LPAREN)buffer$(RPAREN) messes up buffer's capacity) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 15281): std\experimental\allocator\package.d not included in build script) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 15334): [REG 2.069] OS X core.time ticksPerSecond calculation is incorrect) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.069.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.070.0.dd b/changelog/2.070.0.dd new file mode 100644 index 0000000000..432a74ddca --- /dev/null +++ b/changelog/2.070.0.dd @@ -0,0 +1,199 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 27, 2016, =================================================, + +$(BUGSTITLE Language Changes, +$(LI $(RELATIVE_LINK2 alias-funclit, Add syntactic support to make an alias to a function literal.)) +) + +$(BUGSTITLE Library Changes, +$(LI The package $(D std.experimental.ndslice) was added. + It is also available as part of the $(LINK2 https://github.com/DlangScience/mir, Mir library).) +$(LI $(RELATIVE_LINK2 core-sys-windows, The `core.sys.windows` package has been + greatly expanded.) +) +$(LI $(RELATIVE_LINK2 typeinfo-initializer, `TypeInfo.init` has been renamed to `TypeInfo.initializer`.)) +$(LI $(RELATIVE_LINK2 json-encode-control-characters, `std.json` encodes string control characters.)) +$(LI Default LogLevel of FileLogger was changed to LogLevel.all.) +$(LI Access to the internal `ptr` and `len` fields of $(REF_SHORT BitArray, std,bitmanip) was deprecated.) +) + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BUGSTITLE Language Changes, + +$(LI $(LNAME2 alias-funclit, Add syntactic support to make an alias to a function literal.) + + $(P Example:) + + --- + alias less1 = (a, b) => a < b; + alias less2 = (a, b) => a > b; + + import std.algorithm : sort, equal; + + int[] arr = [4, 1, 3, 2]; + assert(equal(sort!less1(arr), [1, 2, 3, 4])); + assert(equal(sort!less2(arr), [4, 3, 2, 1])); + --- +) +) + +$(BUGSTITLE Library Changes, + +$(LI $(LNAME2 core-sys-windows, The `core.sys.windows` package has been + greatly expanded.) + + $(P The `core.sys.windows` package now contains a considerably more + comprehensive set of Windows API bindings. The package has been + adapted from $(HTTP github.com/smjgordon/bindings, Stewart Gordon's + bindings), which were originally adapted from the MinGW project. + ) +) + +$(LI $(LNAME2 typeinfo-initializer, `TypeInfo.init` has been renamed to + `TypeInfo.initializer`.) + + $(P The method `TypeInfo.init` has been renamed to + $(REF1 TypeInfo.initializer, object) to resolve + a name clash with the type property $(GLINK2 property, init). + ) + + $(P An alias with the old name was added and will be deprecated + over the next releases. + ) +) + +$(LI $(LNAME2 json-encode-control-characters, `std.json` encodes string control characters.) + + $(P Instead of throwing a $(REF_SHORT JSONException, std,json), $(REF_SHORT toJSON, std,json) + encodes now the control characters of a string. + ) + + ------ + assert(toJSON(JSONValue("foo\u007fbar")) == `"foo\u007Fbar"`); + ------ +) +) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 13009): [REG2.064] inout overload conflicts with non-inout when used via alias this) +$(LI $(BUGZILLA 14782): Internal error: backend/cod1.c) +$(LI $(BUGZILLA 15369): [REG master] id.d$(LPAREN)369$(RPAREN): Error: Outside Unicode code space) +$(LI $(BUGZILLA 15430): amdMmx hangs up) +$(LI $(BUGZILLA 15500): default construction disabled for struct constructor with default arguments) +$(LI $(BUGZILLA 15550): [Reg 2.070.0-b1] compile error while testing template constraint) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 3438): struct ctor with defaulted parameters should be rejected) +$(LI $(BUGZILLA 3913): Bad error message with wrong enum) +$(LI $(BUGZILLA 4350): $(LPAREN)mixin$(RPAREN) mixed in template identifier is not accessible by "with" statement) +$(LI $(BUGZILLA 7903): [TDPL] public member variables are supposed to be illegal in synchronized classes) +$(LI $(BUGZILLA 14040): Doesn't use assignment in slice) +$(LI $(BUGZILLA 14778): ddoc doesnt generate code for enum in template struct) +$(LI $(BUGZILLA 15133): Error message is incomprehensible) +$(LI $(BUGZILLA 15141): Object.factory allows the creation of derived abstract classes) +$(LI $(BUGZILLA 15156): overload set in eponymous template) +$(LI $(BUGZILLA 15163): Parser bug on double function call) +$(LI $(BUGZILLA 15172): ICE$(LPAREN)interpret.c ctfeCompile$(RPAREN) Assertion `!fd->semantic3Errors' failed.) +$(LI $(BUGZILLA 15209): redundant error message on invalid field access) +$(LI $(BUGZILLA 15233): TypeTuple causes segfault in dmd 2.68.2) +$(LI $(BUGZILLA 15239): ICE $(LPAREN)assertion failure$(RPAREN) in ctfeInterpret$(LPAREN)$(RPAREN) — opDispatch & inline asm) +$(LI $(BUGZILLA 15260): [dmd-internal] StringExp.compare may cause invalid memory access) +$(LI $(BUGZILLA 15261): [dmd-internal] Trivial problem in BinExp.checkOpAssignTypes) +$(LI $(BUGZILLA 15262): [dmd-internal] Duplicated initialization in Token struct static constructor) +$(LI $(BUGZILLA 15309): [dmd-internal] ScopeExp.semantic$(LPAREN)$(RPAREN) should set its type always) +$(LI $(BUGZILLA 15317): Segfault in Type::kind$(LPAREN)$(RPAREN) with DMD v2.069.0) +$(LI $(BUGZILLA 15340): Spurious "overlapped default initialization" errors with auto fields) +$(LI $(BUGZILLA 15352): template arguments matching error with delegates) +$(LI $(BUGZILLA 15366): Enum typed as bool behaves as bool even when cast) +$(LI $(BUGZILLA 15389): extern$(LPAREN)C++$(RPAREN) forward referencing problem) +$(LI $(BUGZILLA 15394): [internal] CompileExp and FileExp has same op TOKmixin) +$(LI $(BUGZILLA 15396): static immutable not recognized as constant within switch statement) +$(LI $(BUGZILLA 15403): [internal] FileExp represents ImportExpression, the AST class naming is not intuitive) +$(LI $(BUGZILLA 15404): [internal] DotIdExp$(LPAREN)TOKdot$(RPAREN) and DotExp$(LPAREN)TOKdotexp$(RPAREN)) +$(LI $(BUGZILLA 15417): Wrong parameter passing for variadic nested functions within aggregate) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 12421): Allow simpler syntax for lambda template declarations) +$(LI $(BUGZILLA 15015): Win64: interop with C/C++ fails if function return value is a struct of size 8) +$(LI $(BUGZILLA 15186): Emit better diagnostic for C++ member lookup operators) +$(LI $(BUGZILLA 15464): Template parameter-dependent attributes) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 14861): Error in stdio.d in LockingTextReader.readFront$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 15319): [REG2.069] module map is in file std/map.d which cannot be read) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 3764): Remove Phobos workarounds for fixed bugs) +$(LI $(BUGZILLA 14786): The built-in exponentiation operator ^^ sometimes returns a value with the wrong sign.) +$(LI $(BUGZILLA 15187): dispose for allocators is broken) +$(LI $(BUGZILLA 15188): `deallocate` cause memory leaks) +$(LI $(BUGZILLA 15220): [REG2.065] std.getopt parses -o=value as "=value") +$(LI $(BUGZILLA 15238): Heisenbug running std.random unittests) +$(LI $(BUGZILLA 15313): std.conv.emplace cannot initialize const objects) +$(LI $(BUGZILLA 15336): std.json: opIn undocumented for JSONValue) +$(LI $(BUGZILLA 15409): Mallocator cant be used in @nogc code) +$(LI $(BUGZILLA 15420): topN$(LPAREN)Range, Range$(RPAREN) does not respect its less predicate) +$(LI $(BUGZILLA 15429): [std.stdio] Broken link in documentation) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 12987): topN should return the top portion of the range) +$(LI $(BUGZILLA 15128): "IP_ADD_MEMBERSHIP" error in winsock2.d) +$(LI $(BUGZILLA 15146): std.file.dirEntries$(LPAREN)""$(RPAREN) only works on Windows) +$(LI $(BUGZILLA 15198): evenChunks - std.range.chunks variant which slices range into N evenly-sized chunks) +$(LI $(BUGZILLA 15208): Eradicate all uses of "Enforcement failed" in Phobos) +$(LI $(BUGZILLA 15212): BigInt should implement opCast!long and opCast!int) +$(LI $(BUGZILLA 15320): static assert$(LPAREN)__traits$(LPAREN)compiles, xyz$(RPAREN)$(RPAREN) considered harmful in unittests) +$(LI $(BUGZILLA 15385): Apply Andersson91 idea to SortedRange.contains) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 15270): use TLS to store Thread.getThis $(LPAREN)pthread_getspecific causes heavy lock contention$(RPAREN)) +$(LI $(BUGZILLA 15367): array of delegates comparison fails) +) +$(BUGSTITLE Druntime enhancements, + +$(LI $(BUGZILLA 15053): Runtime.cArgs not @nogc) +$(LI $(BUGZILLA 15268): possible deadlock for Thread.getAll/Thread.opApply w/ GC.collect) +) +$(BUGSTITLE dlang.org bugs, + +$(LI $(BUGZILLA 8846): Specs for Inline Assembler don't include cmpxchg16b) +$(LI $(BUGZILLA 15250): Grammar does not contain rules for multiple slices in an index expression) +) +$(BUGSTITLE dlang.org enhancements, + +$(LI $(BUGZILLA 13624): Parts of the Overview page is very out of date) +$(LI $(BUGZILLA 15078): GC documentation should reflect 2.067 changes) +) +$(BUGSTITLE Tools bugs, + +$(LI $(BUGZILLA 15173): rdmd man page incorrect/outdated) +$(LI $(BUGZILLA 15174): Add or undocument --tmpdir switch) +$(LI $(BUGZILLA 15175): rdmd --loop and --eval now complain about std.stream deprecation warnings) +) +$(BUGSTITLE Installer bugs, + +$(LI $(BUGZILLA 15456): sc.ini: Access denied for non-superusers on Windows 10) +$(LI $(BUGZILLA 15572): Windows installer leaves "sc.ini" inaccessible) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.070.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.070.1.dd b/changelog/2.070.1.dd new file mode 100644 index 0000000000..bd6c73e6ae --- /dev/null +++ b/changelog/2.070.1.dd @@ -0,0 +1,27 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 27, 2016, =================================================, + +$(BR)$(BIG List of all bug fixes and enhancements in D $(VER):) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 15490): [REG 2.067] Error variable __nrvoretval cannot be modified at compile time when using -inline) +$(LI $(BUGZILLA 15524): [REG2.069] 64bit app with anon-class crashes in contract) +$(LI $(BUGZILLA 15661): [REG2.067.0] Destructor called while object still alive) +$(LI $(BUGZILLA 15674): [REG 2.066] alias this rejected for 'out' parameter) +$(LI $(BUGZILLA 15681): [REG2.067] Nested user type enum not retaining value properly.) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 15664): [REG2.064] incorrect initialisation of member of an immutable struct) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.070.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.070.2.dd b/changelog/2.070.2.dd new file mode 100644 index 0000000000..17811c0d0c --- /dev/null +++ b/changelog/2.070.2.dd @@ -0,0 +1,19 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 3, 2016, =================================================, + +$(BR)$(BIG List of all bug fixes and enhancements in D $(VER):) + +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 15665): Templated scope class with constructor don't compile) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.070.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.071.0.dd b/changelog/2.071.0.dd new file mode 100644 index 0000000000..cccce09b4a --- /dev/null +++ b/changelog/2.071.0.dd @@ -0,0 +1,366 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 5, 2016, =================================================, + +$(BUGSTITLE Compiler Changes, + $(LI $(RELATIVE_LINK2 imports-313, Import access checks for fully qualified names were fixed.)) + $(LI $(RELATIVE_LINK2 imports-314, Protection for selective and renamed imports were fixed.)) +) + +$(BUGSTITLE Language Changes, + $(LI $(RELATIVE_LINK2 import-lookup, Imports no longer hide locals declared in outer scopes.)) + $(LI $(RELATIVE_LINK2 dip22, Private symbols are no longer visible in other modules.)) + $(LI $(RELATIVE_LINK2 extended-deprecated, Manifest constant can now be used for deprecation message.)) +) + +$(BUGSTITLE Library Changes, + $(LI $(RELATIVE_LINK2 aa-clear, A `clear` method has been added to associative + arrays to remove all elements.)) + $(LI $(RELATIVE_LINK2 spinlock, The GC now uses a spinlock instead of a recursive mutex.)) + $(LI Calls to $(REF_SHORT GC.free, core,memory) are now ignored during finalization instead of throwing an InvalidMemoryOperationError, see $(BUGZILLA 15353).) + $(LI $(REF_SHORT GC.addRoot, core,memory) and $(REF_SHORT GC.addRange, core,memory) now use a separate lock.) + $(LI $(REF_SHORT GCAllocator.goodAllocSize, std,experimental_allocator_gc_allocator) + was added.) + $(LI High-level API of $(MREF std,net,curl) now uses $(REF_SHORT Appender, std,array) + for received content. Which generally makes all calls slightly faster. Up to 200ms for large + amounts of data.) + $(LI $(REF_SHORT Repeat, std,meta) was added to obtain a repeating + $(REF_SHORT AliasSeq, std,meta) consisting of template arguments.) + $(LI $(REF_SHORT fold, std,algorithm_iteration) was added as an alternative to $(REF_SHORT reduce, std,algorithm_iteration) + with argument order swapped.) + $(LI $(RELATIVE_LINK2 nextPow2, Added nextPow2 and truncPow2 to std.math.)) + $(LI $(REF_SHORT bsf, core,bitop), $(REF_SHORT bsr, core,bitop), and $(REF_SHORT popcnt, core,bitop) now + work with ulongs on 32 bit systems.) + $(LI $(REF_SHORT topN, std,algorithm_sorting) is now 5% - 7% faster.) + $(LI $(RELATIVE_LINK2 unary, Unary overloads of `startsWith` and `endsWith` were added.)) + $(LI $(RELATIVE_LINK2 maxCount, $(REF_SHORT maxCount, std,algorithm_searching) and + $(REF_SHORT maxPos, std,algorithm_searching) were added.)) + $(LI Range support for the convenience wrapper $(REF_SHORT redBlackTree, std,container_rbtree) + was added.) +) + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BUGSTITLE Compiler Changes, + $(LI $(LNAME2 imports-313, Import access checks for fully qualified names were fixed.) + + $(P It is no longer possible to bypass private imports by using fully qualified names, e.g. + the following example will fail with `package std.range is not accessible here`. + ) + + --- + import std.algorithm; + + static assert(std.range.isForwardRange!string); + --- + + $(P To ease updating existing code, the old behavior was retained but deprecated. + ) + ) + + $(LI $(LNAME2 imports-314, Protection for selective and renamed imports were fixed.) + + $(P It is no longer possible to use private selective or renamed imports in another module, e.g. + the following example will fail with `a.File is not visible from module b`. + ) + + --- + module a; + import std.stdio : File; // imports are private by default + --- + --- + module b; + import a; + + File f; // File is private + --- + + $(P To ease updating existing code, the old behavior was retained but deprecated. + This fix relies on the visibility changes introduced with $(RELATIVE_LINK2 dip22, DIP22). + ) + ) +) + +$(BUGSTITLE Language Changes, + $(LI $(LNAME2 import-lookup, Imports no longer hide locals declared in outer scopes.) + + $(P These changes were made to the name lookup algorithm: + + $(OL + $(LI Lookup for unqualified names is change from one pass to two pass. The first + pass goes through the scopes but does not check import declarations. If not found, + the second pass goes through the scopes and only looks at import declarations. + ) + $(LI Qualified name lookups, base class lookups, and WithStatement lookups no longer + search import declarations, unless a module is the subject of the lookup, where the + behavior remains as before. + ) + ) + ) + + $(P This can break existing code, although reliance on the previous behavior tends to be + unintended, and fixing it improves the comprehensibility of the code. Breakage tends + to take the form of a symbol now being flagged as undefined. Fixing the breakage can + be done by fully qualifying the name, or adding an alias to the import declaration. + ) + + $(P The old lookup behavior can be restored using the -transition=import + compiler switch. With -transition=checkimports the compiler will issue + deprecation warnings when the old and new lookup find different + symbols. + You can combine both switches to use the old lookup and still get + deprecation warnings. + ) + + $(P See also $(BUGZILLA 10378)) + ) + + $(LI $(LNAME2 dip22, Private symbols are no longer visible in other modules.) + + $(P Protection (private, package, protected) is now already enforced during + symbol lookup in order to resolve any conflicts between private and + public symbols that could occur with the old access check scheme. + ) + + $(P The visibility of overloaded symbols with mixed protection is determined + by the most visibile member, but additional access check against the exact + symbol is performed after overload resolution. + ) + + $(P To ease updating existing code, a deprecated search for invisible symbols will be performed. + For the the old lookup behavior (using the -transition=import or -transition=checkimports compiler switch) + symbol visibility is ignored. + All existing access checks remain active during the deprecation phase. + ) + + $(P See also $(LINK2 http://wiki.dlang.org/DIP22, DIP22)) + ) + + $(LI $(LNAME2 extended-deprecated, Manifest constant can now be used for deprecation message.) + + $(P Manifest constants (enum, static immutable) can now be used for deprecation message, as well as concatenated strings.) + $(P Example:) + --- + string generateMessage() { return "Some deprecation message"; } + enum DepMsg = generateMessage(); + + deprecated(DepMsg) class Foo {} + deprecated("Some long deprecation " ~ "message") class Bar {} + --- + ) +) + +$(BUGSTITLE Library Changes, + +$(LI $(LNAME2 aa-clear, A `clear` method has been added to associative + arrays to remove all elements.) + + $(P One can now use `aa.clear()` to remove all elements from an + associative array. This allows removing all elements from all + references to the same array (setting to `null` just reset the + reference, but did not removed the elements from other references). + ) + +------- +auto aa = ["first" : "entry", "second": "entry"]; +auto aa2 = aa1; // reference to the same AA +aa.clear(); // still retains its current capacity for faster imports +assert(aa2.length == 0); // other references affected +------- +) + +$(LI $(LNAME2 spinlock, The GC is no longer wrapped in a pthread_mutex, it + now uses a spinlock.) + + $(P This results in a 5% faster GC on average, with the most benefits going + to multi-threaded programs that use the GC. See $(DRUNTIMEPR 1447) for + more details. + ) +) + +$(LI $(LNAME2 nextPow2, Added nextPow2 and truncPow2 to std.math.) + $(P $(REF_SHORT nextPow2, std,math) and $(REF_SHORT truncPow2, std,math) are functions for + rounding numbers to powers of two. + ) +------ +import std.math; + +assert(nextPow2(10) == 16); +assert(nextPow2(4000) == 4096); + +assert(truncPow2(10) == 8); +assert(truncPow2(4000) == 2048); +------ +) + +$(LI $(LNAME2 unary, Unary overloads of `startsWith` and `endsWith` were added.) + $(P $(REF_SHORT startsWith, std,algorithm_searching) and $(REF_SHORT endsWith, std,algorithm_searching) + can now be used just with a predicate. + ) +------ +import std.algorithm.searching; +import std.ascii : isAlpha; + +assert("abc".endsWith!isAlpha); +assert(!"ab1".endsWith!(a => a.isAlpha)); + +assert("abc".startsWith!isAlpha); +assert(!"1ab".startsWith!isAlpha); +------ +) + +$(LI $(LNAME2 maxPos, $(REF_SHORT maxCount, std,algorithm_searching) and + $(REF_SHORT maxPos, std,algorithm_searching) were added.) +$(P Previous to this addition, in order to get the number of the greatest + elements, you had to use `minCount!"a > b"`, which was very confusing. + This change adds convenience functions to fix this issue.) +) +) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 14965): [REG2.031] Forward reference to inferred return type of function call when using auto return type) +$(LI $(BUGZILLA 14973): [REG2.068] compiler inference of contexts for nested map seems broken) +$(LI $(BUGZILLA 15296): [REG2.069] cannot inline simple function that calls use non-inlinable statements) +$(LI $(BUGZILLA 15422): [REG2.066] associative array of nested struct - crash on usage) +$(LI $(BUGZILLA 15455): [REG v2.065] Compiler segfault for simple nested structure) +$(LI $(BUGZILLA 15618): [REG-master] Class member layout has been changed, ABI needs to be updated?) +$(LI $(BUGZILLA 15713): [REG-master] ctfe string concatenation is templates is broken) +$(LI $(BUGZILLA 15729): [REG$(LPAREN)master$(RPAREN)] broken debug info for libraries) +$(LI $(BUGZILLA 15733): [REG2.066] Forward reference issue involving inheritance) +$(LI $(BUGZILLA 15744): [REG2.067] $(LPAREN)SIGABRT$(RPAREN) Error: overloadset t.Bar.__ctor is aliased to a function) +$(LI $(BUGZILLA 15778): [REG2.064] polysemous string type doesn't work in array operation) +$(LI $(BUGZILLA 15781): [REG2.069] Template type deduction failure with same-type variables with different constness) +$(LI $(BUGZILLA 15785): [DMD HEAD] Spurious warning when calling protected super) +$(LI $(BUGZILLA 15788): [REG2.069] ICE assert triggered on overloaded function) +$(LI $(BUGZILLA 15814): [REG-master] Custom deprecation message is not shown) +$(LI $(BUGZILLA 15815): [REG2.071-devel] deprecation for aliased template instance not shown) +$(LI $(BUGZILLA 15817): [REG2.068] ICE $(LPAREN)with no stacktrace$(RPAREN) instead of 'cannot index null array counts' with CTFE AA) +$(LI $(BUGZILLA 15839): [REG2.071-b1] this.outer is of wrong type) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 143): 'package' does not work at all) +$(LI $(BUGZILLA 313): [module] Fully qualified names bypass private imports) +$(LI $(BUGZILLA 314): [module] Static, renamed, and selective imports are always public) +$(LI $(BUGZILLA 1754): module member visibility does not affect conflicts) +$(LI $(BUGZILLA 2991): [module] Import within aggregate causes conflicts with private identifiers) +$(LI $(BUGZILLA 3254): [module] Module member visibility depends on declaration order) +$(LI $(BUGZILLA 6907): ice$(LPAREN)interpret.d$(RPAREN) delete expressions crash interpreter) +$(LI $(BUGZILLA 7516): Postblit not called for structs returned from a ternary operator) +$(LI $(BUGZILLA 7517): Interface contracts broken) +$(LI $(BUGZILLA 11581): Given T..., new T[0] does not work) +$(LI $(BUGZILLA 12748): ICE: Using typeof$(LPAREN)S.init[0]$(RPAREN) in type name specialization.) +$(LI $(BUGZILLA 12829): Wrong error line number for closure allocation in @nogc function) +$(LI $(BUGZILLA 13702): One missed 'may cause GC allocation' error message) +$(LI $(BUGZILLA 14442): Wrong this.outer reference in nested classes) +$(LI $(BUGZILLA 14486): delete on classes ignores @nogc) +$(LI $(BUGZILLA 14603): "cannot alias an expression" when opDispatch results in a template) +$(LI $(BUGZILLA 14604): "cannot resolve forward reference" when opDispatch results in a template) +$(LI $(BUGZILLA 14686): Postblit isn't sometimes called on concatenation) +$(LI $(BUGZILLA 14730): Wrong closure var access with -inline) +$(LI $(BUGZILLA 14788): Incorrect rejection of inout function call) +$(LI $(BUGZILLA 14895): ICE on array operation when its result is concatenated) +$(LI $(BUGZILLA 14989): Overload merge sometimes doesn't work) +$(LI $(BUGZILLA 14992): static array local variables always require .init) +$(LI $(BUGZILLA 15309): [dmd-internal] ScopeExp.semantic$(LPAREN)$(RPAREN) should set its type always) +$(LI $(BUGZILLA 15310): [dmd-internal] TemplateDeclaration should be converted to TemplateExp always) +$(LI $(BUGZILLA 15332): ICE in e2ir.c: assert$(LPAREN)irs->sthis$(RPAREN) in visit$(LPAREN)ThisExp$(RPAREN), function literal with keyword 'function' calls method) +$(LI $(BUGZILLA 15353): std.experimental.allocator cannot free memory in its destructor if the GC is an ancestor) +$(LI $(BUGZILLA 15384): assignment is sometimes still accepted as a condition) +$(LI $(BUGZILLA 15389): extern$(LPAREN)C++$(RPAREN) forward referencing problem) +$(LI $(BUGZILLA 15407): Assert hit in toElem e2ir.c:1962) +$(LI $(BUGZILLA 15411): Function literal accessing variable in declaration scope produces bad error message with inline call) +$(LI $(BUGZILLA 15441): dmd segfaults using std.experimental.ndslice) +$(LI $(BUGZILLA 15450): ICE during CTFE of legit function) +$(LI $(BUGZILLA 15519): Circular imports leads to fwd ref error with aliased imports) +$(LI $(BUGZILLA 15535): Emit error on "goto default" in final switch) +$(LI $(BUGZILLA 15565): Forward reference error with namespaces) +$(LI $(BUGZILLA 15578): Should have access to namespace private symbols from same module) +$(LI $(BUGZILLA 15579): extern$(LPAREN)C++$(RPAREN) interfaces/multiple-inheritance) +$(LI $(BUGZILLA 15610): extern$(LPAREN)C++$(RPAREN) multiple inheritance - calling with wrong 'this' ptr) +$(LI $(BUGZILLA 15623): is$(LPAREN)M!N$(RPAREN) evaluates to true for M!N that fails to instantiate.) +$(LI $(BUGZILLA 15626): extern$(LPAREN)C++$(RPAREN) calling crash) +$(LI $(BUGZILLA 15638): no common type for const classes) +$(LI $(BUGZILLA 15647): Casting from one C++ interface in a hierarchy to another is a noop) +$(LI $(BUGZILLA 15665): Templated scope class with constructor don't compile) +$(LI $(BUGZILLA 15667): dmd infinite loop on invalid syntax.) +$(LI $(BUGZILLA 15669): Wrong line number in error message) +$(LI $(BUGZILLA 15688): dmd segfault with an integer call through comma expression) +$(LI $(BUGZILLA 15784): Overload set constructor call should be supported from inside a constructor) +$(LI $(BUGZILLA 15789): ICE Assert in TemplateInstance semanticTiargs) +$(LI $(BUGZILLA 15794): Lambda cannot get a chance to run its codegen) +$(LI $(BUGZILLA 15811): -transition=import and -transition=checkimport have oddly behaviors) +$(LI $(BUGZILLA 15825): dmd's -transition=checkimports reports a false positive for tuple __dollar) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 10378): Prevent local imports from hiding local symbols) +$(LI $(BUGZILLA 12954): deprecated doesn't work with concatenated strings or anything else but a string literal) +$(LI $(BUGZILLA 14383): [ddoc] documented unittests don't work for module declaration) +$(LI $(BUGZILLA 15644): Change object layout ABI to MI style) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 15222): std.experimental omitted from phobos zip file) +$(LI $(BUGZILLA 15782): [Reg 2.071-devel] Alias no longer strips qualifiers from user defined types) +$(LI $(BUGZILLA 15807): Array!bool insertBack is broken) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 1238): Private identifiers in imported modules create conflicts with public ones) +$(LI $(BUGZILLA 15543): [ndslice] assumeSameStructure has useless flag) +$(LI $(BUGZILLA 15545): csv Reader line feed '\r' failure) +$(LI $(BUGZILLA 15549): [ndslice] byElement is broken for packed slices) +$(LI $(BUGZILLA 15553): topN very inefficient [slower than sort, even for topN$(LPAREN)0$(RPAREN)] but should be O$(LPAREN)n$(RPAREN)) +$(LI $(BUGZILLA 15561): std.typecons.Proxy gets NaN comparisons wrong) +$(LI $(BUGZILLA 15639): std.experimental.allocator enables abstract class instantiation) +$(LI $(BUGZILLA 15654): SysTime.toISOString formats the time zones incorrectly) +$(LI $(BUGZILLA 15655): SysTime.from*String incorrectly accept single digit time zones and minutes > 59) +$(LI $(BUGZILLA 15659): SList: clear$(LPAREN)$(RPAREN) can cause crash) +$(LI $(BUGZILLA 15663): writefln$(LPAREN)"%#o", 0$(RPAREN) should yield "0" instead of "00") +$(LI $(BUGZILLA 15677): std.experimental.allocators.expandArray overload with init should take the array by ref.) +$(LI $(BUGZILLA 15683): broken link in DDoc) +$(LI $(BUGZILLA 15686): std.uni overloads documentation) +$(LI $(BUGZILLA 15715): [ndslice] rangeHasMutableElements is not defined) +$(LI $(BUGZILLA 15721): free error when calling Mallocator.dispose on interfaces) +$(LI $(BUGZILLA 15772): emplace works with abstract classes but it shouldn't) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 15377): std.stdio: Use MSVCRT's _fseeki64 / _ftelli64 on Windows COFF) +$(LI $(BUGZILLA 15532): [ndslice] iota$(LPAREN)5$(RPAREN).sliced$(LPAREN)2,2$(RPAREN) should throw error) +$(LI $(BUGZILLA 15596): strip with delimiter?) +$(LI $(BUGZILLA 15714): [ndslice] byElement seems to be missing some slicing primitives) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 15224): making 'clean' results in garbage commands) +$(LI $(BUGZILLA 15779): DWARF EH fails when using stack stomping $(LPAREN)-gx$(RPAREN)) +$(LI $(BUGZILLA 15822): InvalidMemoryOperationError when calling GC.removeRange/Root from a finalizer) +) +$(BUGSTITLE Druntime enhancements, + +$(LI $(BUGZILLA 15628): Exceptions in fibers never caught with /SAFESEH) +) +$(BUGSTITLE dlang.org bugs, + +$(LI $(BUGZILLA 10987): Add documentation for 'extern $(LPAREN)C++$(RPAREN)' classes) +$(LI $(BUGZILLA 15344): m32mscoff switch missing from documentation.) +$(LI $(BUGZILLA 15666): Grammar does not allow member function attributes on static constructors) +$(LI $(BUGZILLA 15696): The website logo overlaps the Learn tab when using Microsoft Edge) +$(LI $(BUGZILLA 15697): The script for This Week in D is served over HTTP even when accessing the website over HTTPs.) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.071.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.071.1.dd b/changelog/2.071.1.dd new file mode 100644 index 0000000000..b3b2ecffbf --- /dev/null +++ b/changelog/2.071.1.dd @@ -0,0 +1,45 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION June 27, 2016, =================================================, + +$(BR)$(BIG List of all bug fixes and enhancements in D $(VER):) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 15629): [REG2.066.0] wrong code with '-O -inline' but correct with '-O') +$(LI $(BUGZILLA 15861): [REG 2.069] Wrong double-to-string conversion with -O) +$(LI $(BUGZILLA 15897): private base class method not seen through derived class) +$(LI $(BUGZILLA 15898): [REG2.069] Internal error: backend\cgcod.c 1651) +$(LI $(BUGZILLA 15925): -transition=[check]imports ignores import declaration from mixin templates) +$(LI $(BUGZILLA 15961): [REG2.066] ICE with instance field introduced by anonymous struct) +$(LI $(BUGZILLA 15998): [REG2.067] Segmentation fault on const folding of arrays of static arrays) +$(LI $(BUGZILLA 16022): [REG2.069] dmd assertion failure due to misplaced comma operator) +$(LI $(BUGZILLA 16027): Wrong result of double multiplication) +$(LI $(BUGZILLA 16080): [REG2.071.0] Internal error: backend\cgobj.c 3406 when building static library) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 15856): Confusing error message with -transition=checkimports) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 15402): allow private access to package symbols) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 15914): [REG 2.071] getopt doesn't accept anymore a character for a bool option) +$(LI $(BUGZILLA 15941): [REG v2.069] rbtree no longer supports classes) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 15911): undefined __Unwind_GetIPInfo for x86_64) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.071.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.071.2.dd b/changelog/2.071.2.dd new file mode 100644 index 0000000000..145b5f7417 --- /dev/null +++ b/changelog/2.071.2.dd @@ -0,0 +1,32 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION September 19, 2016, =================================================, + +$(BR)$(BIG List of all bug fixes and enhancements in D $(VER):) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 15780): [REG2.069] CTFE foreach fails with tuple) +$(LI $(BUGZILLA 15900): [REG 2.071] $(LPAREN)Import deprecation$(RPAREN) Public import ignored when using fully qualified name) +$(LI $(BUGZILLA 15907): Unjustified "is not visible from module" deprecation warning when using getMember trait) +$(LI $(BUGZILLA 16031): [REG2.071] stale DW.ref.name EH symbol used with -lib and -fPIC) +$(LI $(BUGZILLA 16085): wrong visibility warning for overloaded alias symbol) +$(LI $(BUGZILLA 16188): [REG2.069] ICE on invalid code) +$(LI $(BUGZILLA 16225): [REG 2.068] Internal error cod1.c 1338 with -O) +$(LI $(BUGZILLA 16316): [REG 2.071] $(LPAREN)Import deprecation$(RPAREN) fully qualified name of imports in mixin template not accessible) +$(LI $(BUGZILLA 16348): [REG 2.070.2] ICE with package visibility) +$(LI $(BUGZILLA 16460): [REG2.071] ICE for package visibility check in function literal) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 15857): incorrect checkimports mismatch for overload sets) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.071.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.072.0.dd b/changelog/2.072.0.dd new file mode 100644 index 0000000000..e014b32ec7 --- /dev/null +++ b/changelog/2.072.0.dd @@ -0,0 +1,1110 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 30, 2016, =================================================, + +$(BUGSTITLE Language Changes, + $(LI $(RELATIVE_LINK2 deprecated_commaexp, Using the result of a comma expression is deprecated.)) + + $(LI $(RELATIVE_LINK2 deprecated_implicit_catch, Implicit catch statement are deprecated.)) + + $(LI $(RELATIVE_LINK2 deprecated_implicit_cat, Implicit string concatenation is deprecated.)) + + $(LI $(RELATIVE_LINK2 unrestricted_unions, Restrictions of postblits and destructors in union fields have been lifted.)) + + $(LI $(RELATIVE_LINK2 align_by_ctfe, Align attribute can be used with CTFEable expression.)) + + $(LI $(RELATIVE_LINK2 scope_value_parameters, `scope` is ignored for value parameters without indirections.)) +) + +$(BUGSTITLE Compiler Changes, + $(LI $(RELATIVE_LINK2 iteration_closure, `opApply` now conservatively allocates a closure unless marked `scope`)) + $(LI $(RELATIVE_LINK2 native_tls_osx, Native TLS on OS X 64 bit.)) + $(LI $(RELATIVE_LINK2 deferred_alias, Analysis for aliases in imported modules is deferred.)) + $(LI $(RELATIVE_LINK2 __FILE_FULL_PATH__, Special keyword replaced by the source file's absolute file name.)) + $(LI $(RELATIVE_LINK2 dash_verrors_spec, Add `-verrors=spec` switch.)) +) + +$(BUGSTITLE Library Changes, + $(LI $(RELATIVE_LINK2 TypeInfo.init-deprecated, `TypeInfo.init` has been deprecated.)) + $(LI $(RELATIVE_LINK2 drt-oncycle, New druntime switch `--DRT-oncycle` + allows specifying what to do on cycle detection in modules.)) + $(LI Wrong + $(LINK2 $(ROOT_DIR)spec/function.html#trusted-functions, `@trusted`) + attributes have been + removed from $(MREF etc,c,curl) functions + $(REF_ALTTEXT `curl_easy_escape`, curl_easy_escape, etc,c,curl), + $(REF_ALTTEXT `curl_escape`, curl_escape, etc,c,curl), + $(REF_ALTTEXT `curl_easy_unescape`, curl_easy_unescape, etc,c,curl), and + $(REF_ALTTEXT `curl_unescape`, curl_unescape, etc,c,curl).) + $(LI $(RELATIVE_LINK2 std-digest-murmurhash, Implementation of MurmurHash + digest.)) + $(LI $(RELATIVE_LINK2 process, Process creation in `std.process` was sped up + on Posix.)) + $(LI $(RELATIVE_LINK2 std-algorithm-iteration-cumulativeFold, + `algorithm.iteration.cumulativeFold` was added.)) + $(LI $(RELATIVE_LINK2 padLeft-padRight, `std.range.padLeft` and + `std.range.padRight` were added.)) + $(LI $(RELATIVE_LINK2 regex-multiple-patterns, `std.regex.regex` now + supports matching multiple patterns in one go.)) + $(LI $(RELATIVE_LINK2 regex-with-matches, `std.regex.splitter` now + supports keeping the pattern matches in the resulting range.)) + $(LI $(RELATIVE_LINK2 optimization, `findLocalMin` was added to `std.numeric`.)) + $(LI $(RELATIVE_LINK2 slice_ptr, `ptr` property and public constructor were + added to `std.experimental.ndslice.slice.Slice`.)) + $(LI $(RELATIVE_LINK2 slice_toHash, `toHash` method was + added to `std.experimental.ndslice.slice.Slice`.)) + $(LI $(RELATIVE_LINK2 slice_alloc, `slice`, `shape`, `ndarray`, and other + utilities were added to `std.experimental.ndslice.slice`.)) + $(LI $(RELATIVE_LINK2 slice_as, `as` lazy tensor was added to + `std.experimental.ndslice.slice`.)) + $(LI $(RELATIVE_LINK2 slice_iota, `iotaSlice` lazy tensor was added to + `std.experimental.ndslice.selection`.)) + $(LI $(RELATIVE_LINK2 slice_index, `indexSlice` lazy tensor was added to + `std.experimental.ndslice.selection`.)) + $(LI $(RELATIVE_LINK2 slice_repeat, `repeatSlice` lazy tensor was added to + `std.experimental.ndslice.selection`.)) + $(LI $(RELATIVE_LINK2 slice_map, `mapSlice` lazy tensor was added to + `std.experimental.ndslice.selection`.)) + $(LI $(RELATIVE_LINK2 slice_mio, partial support for Math Index Order + was added to `std.experimental.ndslice.slice.Slice`.)) + $(LI $(RELATIVE_LINK2 mutation, `std.algorithm.mutation.swapAt` was + exposed)) + $(LI $(RELATIVE_LINK2 iota-length-size_t, `std.range.iota's `.length` + property is fixed to `size_t` instead of the type being iterated)) + $(LI $(REF isNumber, std,uni) and $(REF isPunctuation, std,uni) now use a separate, + optimized path for ASCII inputs.) + $(LI $(REF isAlphaNum, std,uni), which is analogous to $(REF isAlphaNum, std,ascii) + was added.) + $(LI $(REF regex, std,regex) now supports inline comments with (?#...) syntax.) + $(LI std.regex had numerous optimization applied, compile-time $(REF ctRegex, std,regex) + should now be generally faster then the run-time version.) + $(LI $(REF moveAt, std,range,primitives) accepts only `size_t` for its index + arguments.) + $(LI $(REF isStrictlyMonotonic, std,algorithm,sorting) which doesn't allow + equal values was added.) + $(LI $(REF readLink, std,file) and $(REF symlink, std,file) have been + rangified.) + $(LI All overloads of `std.conv.toImpl` has been made private. Please use + $(REF to, std,conv) instead.) + $(LI $(RELATIVE_LINK2 min-max-element, + `std.algorithm.searching.{min,max}Element` for ranges have been added.)) + $(LI $(REF Ternary, std,typecons) was added to represent three valued + logic.) + $(LI $(RELATIVE_LINK2 quantize, Added `std.math.quantize`, for rounding to + the nearest multiple of some number.)) + $(LI $(RELATIVE_LINK2 traits, Three new traits were added to `std.traits`.)) + $(LI $(RELATIVE_LINK2 generate, `std.range.generate` fixed to be a proper + range.)) + $(LI $(MREF std,numeric) no longer uses `enforce` for verifying + contract preconditions.) + $(LI $(RELATIVE_LINK2 headconst, `Final` was added to + `std.experimental.typecons`)) + $(LI $(RELATIVE_LINK2 inner-class, `std.traits.isInnerClass` was added to + identify nested classes with an accessible `outer` pointer)) + $(LI $(RELATIVE_LINK2 emplace-inner-class, `std.conv.emplace` no longer allows + to emplace classes directly nested inside other classes without specifying a + suitable `outer` pointer)) + $(LI $(RELATIVE_LINK2 gc-runtimeswitch-added, A switch for selecting + the GC implementation at runtime was added.)) + $(LI $(RELATIVE_LINK2 manualgc-added, A GC implementation allowing manual + memory management was added.)) +) + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BUGSTITLE Language Changes, + $(LI $(LNAME2 deprecated_commaexp, Using the result of a comma expression is deprecated.) + + $(P Comma expressions have proven to be a frequent source of confusion, and bugs - + see $(HTTPS issues.dlang.org/show_bug.cgi?id=2659#c2, here) for examples.) + + $(P Using the result of a comma expression will now trigger a deprecation message.) + + $(P Example:) + + --- + void main () { + // OK, result of increment not directly used + for (int i, j; i != 3; i++, j++) {...} + + auto r1 = getRange!int, r2 = getRange!int; + // OK + for (; !r1.empty && !r2.empty; r1.popFront, r2.popFront) {...} + // Deprecated - the loop condition is always used + for (; !r1.empty, !r2.empty; r1.popFront, r2.popFront) {...} + + MyContainerClass mc; + // OK - expression statement, result not used + if (!mc) + (mc = new MyContainerClass), mc.append(new Entry); + + int i; + // Deprecated + mc = (i++, new MyContainerClass); + } + --- + ) + + $(LI $(LNAME2 deprecated_implicit_catch, Implicit catch statement are deprecated.) + + $(P Implicit catch statement are catch statement without type specified. + They default to catching `Throwable`, which is something that should always be explicit.) + + $(P Example:) + + --- + int[] arr = new int[](10); + // This will throw a RangeError + try { arr[42]++; } + catch { writeln("An error was caught and ignored"); } + // The previous line is equivalent to: + // catch (Throwable) { writeln("An error was caught and ignored"); } + --- + ) + + $(LI $(LNAME2 deprecated_implicit_cat, Implicit string concatenation is deprecated.) + + $(P Implicit concatenation of string literal is a very early feature that is now supplanted + by the concatenation operator ('~'), the later being more explicit.) + + $(P It could result in hard to spot bug, where one missed a comma in an array expression:) + + --- + void foo () + { + string[] arr = [ "Hello", "buggy" "World" ]; + assert(arr.length == 3); // Fail, the length of the array is 2 and the content is [ "Hello", "buggyWorld" ] + } + --- + ) + + $(LI $(LNAME2 unrestricted_unions, Restrictions of postblits and destructors in union fields have been lifted.) + + $(P It is now allowed to have fields with postblits (`this(this)`), + destructors (`~this()`), or invariants (`invariant()`) in unions. + Actually destructing or blitting the correct field is the duty of the + programmer.) + + $(P Example:) + + --- + struct S { this(this) {} ~this() {} } + union U + { + int var; + S s; + } + + unittest + { + U u; // won't call s.~this when u goes out of scope + u = U(); // only copies the memory, use fieldwise assignment instead + u.s = S(); // works like normal struct assignment + destroy(u.s); // destroy currently used field + } + --- + ) + + $(LI $(LNAME2 align_by_ctfe, Align attribute can be used with CTFEable expression.) + + $(P Example:) + + --- + version (D_LP64) + enum n = 8; + else + enum n = 4; + align (n) struct Data + { + align (n == 8 ? 2 : 1): + ubyte[3] buffer; + int flags; + } + + version (D_LP64) + static assert(Data.flags.offsetof == 4); + else + static assert(Data.flags.offsetof == 3); + --- + ) + + $(LI $(LNAME2 scope_value_parameters, `scope` is now ignored for value parameters without indirections.) + + $(P The `scope` storage class is now ignored for copied value parameters that don't have any indirections.) + + $(P Example:) + + --- + import std.traits; + void valueParam(scope int param); + static assert(ParameterStorageClassTuple!valueParam[0] == ParameterStorageClass.none); + void scopeParam(scope int* param); + static assert(ParameterStorageClassTuple!scopeParam[0] == ParameterStorageClass.scope_); + --- + ) +) + +$(BUGSTITLE Compiler Changes, + $(LI $(LNAME2 native_tls_osx, Native TLS on OS X 64 bit.) + + $(P + The compiler has been updated to use native thread local storage + (TLS) on OS X when compiling for 64 bit. This means that it's + possible to to link with C/C++ TLS variables. This change is an ABI + breaking change and requires recompiling libraries. + ) + + $(P + The minimum required version of running the compiler and any + produced binary is now Mac OS X Lion (10.7). + ) + + $(P + Xcode 7.3 has a bug causing linker errors for some TLS variables. + Xcode 7.3.1 fixes this bug. Any version older than 7.3 works as well. + ) + ) + + $(LI $(LNAME2 deferred_alias, Analysis for aliases in imported modules is deferred.) + + $(P Example:) + + --- + module lib; + template ExpensiveApiImpl(int ver) + { + ... + void func() {} + pragma(msg, "instantiated ExpensiveApiImpl ", ver); + } + alias api1 = ExpensiveApiImpl!(1); + alias api2 = ExpensiveApiImpl!(2); + --- + + --- + import lib; + void main() + { + // OK, prints "instantiated ExpensiveApiImpl 1" + api1.func(); + + // Don't print "instantiated ExpensiveApiImpl 2", because + // the alias name 'api2' is not used. + } + --- + ) + + $(LI $(LNAME2 __FILE_FULL_PATH__, Special keyword replaced by the source file's absolute file name.) + $(P + The __FILE_FULL_PATH__ special keyword is replaced by the absolute path + of the current source file by the compiler. + ) + $(P Example:) + --- + import std.stdio; + import std.path; + import std.file; + void main() + { + writeln("The main source file lives here: ", __FILE_FULL_PATH__); + writeln("The contents are:"); + foreach(line; File(__FILE_FULL_PATH__, "r").byLine) { + writeln(line); + } + writeln(); + writeln("Other files in the same directory are:"); + foreach(entry; dirEntries(__FILE_FULL_PATH__.dirName, SpanMode.shallow)) { + writefln(" - %s", entry.name); + } + } + --- + ) + + $(LI $(LNAME2 dash_verrors_spec, Add `-verrors=spec` switch.) + $(P Shows errors from speculative compiles such as:) + --- + void foo(int i) + { + int p; + bool b = __traits(compiles, { p = &i; }); + } + --- + $(P that are normally not shown:) + --- + (spec:1) test.d(13): Error: cannot implicitly convert expression (& i) of type int* to int + --- + $(P The number after `spec:` is the nesting of the speculative compiles.) + ) +) + +$(BUGSTITLE Library Changes, + + $(LI $(LNAME2 TypeInfo.init-deprecated, `TypeInfo.init` has been + deprecated.) + + $(P This is a step towards removal of `TypeInfo.init`, which is necessary + to resolve a name clash with the type property $(GLINK2 property, init). + ) + + $(P Use $(REF1 TypeInfo.initializer, object) instead.) + ) + + $(LI $(LNAME2 drt-oncycle, New druntime switch `--DRT-oncycle` allows + specifying what to do on cycle detection in modules.) + $(P When module cycles are detected, the default behavior is to print + the cycle, and abort execution. However, in many cases, the cycles + are not harmful. With the new `--DRT-oncycle` switch, you can effect + a different behavior when cycles are detected:) + $(DL + $(DT `--DRT-oncycle=abort`) + $(DD This is the default behavior, and will abort, printing the cycle to `stderr` when the first cycle is detected) + $(DT `--DRT-oncycle=print`) + $(DD Print all cycles that are detected to `stderr`, but do not halt execution. Order of initialization is arbitrarily chosen based on the order the modules are in the binary) + $(DT `--DRT-oncycle=ignore`) + $(DD Do not print anything, and do not halt execution. Order of initialization is arbitrarily chosen based on the order the modules are in the binary) + ) + ($P As there were improvements of the cycle detection algorithm implemented within the scope of this release, + previously undetected (even harmless) module dependency cycles may start to abort program execution + or program may malfunction due to changed call order of module static construction/destruction. + In order to preserve the program behaviour without the need to specify `--DRT-oncycle` command line argument, + it is possible to instruct the linker by declaring the following array in the source code:) + + --- + extern(C) __gshared string[] rt_options = [ "oncycle=ignore" ]; + --- + + ($P For more information, please consult the D language specification, section Overriding Cycle Detection Abort in chapter 4 + and chapter 28.7 Configuring the Garbage Collector.) + ) + + $(LI $(LNAME2 std-digest-murmurhash, Implementation of `std.digest.murmurhash`). + $(P $(MREF std,digest,murmurhash) has been added. MurmurHash is a + non-cryptographic hash function suitable for general hash-based lookup. It + is optimized for x86 architectures. + ) + ------ + // Computing the 32-bits hash value of an int array using the convenient digest template. + import std.digest.murmurhash; + + ubyte[4] hashed = digest!MurmurHash3_32_opt32([1, 2, 3, 4]); + ------ + ) + + $(LI $(LNAME2 process, Process creation in `std.process` was sped up on Posix.) + $(P Previously, Posix systems would attempt to close every file descriptor + from 3 to the maximum file descriptor number if `inheritFDs` was not + specified with `spawnProcess`, `pipeProcess`, etc. + $(MREF std,process) now uses `poll()` to determine which + descriptors need closing. + ) + ) + + $(LI $(LNAME2 std-algorithm-iteration-cumulativeFold, + `algorithm.iteration.cumulativeFold` was added.) + + $(P $(REF cumulativeFold, std,algorithm,iteration) returns the successive + reduced values of an input range.) + ------ + assert([1, 2, 3, 4, 5].cumulativeFold!((a, b) => a + b).array == [1, 3, 6, 10, 15]); + assert([1, 2, 3].cumulativeFold!((a, b) => a + b)(100).array == [101, 103, 106]); + ------ + ) + + $(LI $(LNAME2 padLeft-padRight, `std.range.padLeft` and `std.range.padRight` + were added.) + $(P $(REF padLeft, std,range) and $(REF padRight, std,range) are functions for + padding ranges to a specified length using the given element. + ) + + ------- + import std.range; + import std.algorithm.comparison; + + assert([1, 2, 3, 4, 5].padLeft(0, 7).equal([0, 0, 1, 2, 3, 4, 5])); + + assert("Hello World!".padRight('!', 15).equal("Hello World!!!!")); + ------- + ) + + $(LI $(LNAME2 regex-multiple-patterns, `std.regex.regex` now supports matching multiple patterns in one go.) + ------- + import std.regex; + // multi-pattern regex + auto multi = regex([`\d+,\d+`,`(a-z]+):(\d+)`]); + auto m = "abc:43 12,34".matchAll(multi); + assert(m.front.whichPattern == 2); + assert(m.front[1] == "abc"); + assert(m.front[2] == "43"); + m.popFront(); + assert(m.front.whichPattern == 1); + assert(m.front[1] == "12"); + ------- + ) + + $(LI $(LNAME2 regex-with-matches, `std.regex.splitter` now supports keeping the + pattern matches in the resulting range.) + ------- + import std.regex; + import std.algorithm.comparison : equal; + + auto pattern = regex(`([\.,])`); + assert("2003.04.05" + .splitter!(No.keepSeparators)(pattern) + .equal(["2003", "04", "05"])); + assert("2003.04.05" + .splitter!(Yes.keepSeparators)(pattern) + .equal(["2003", ".", "04", ".", "05"])); + ------- + ) + + $(LI $(LNAME2 optimization, `findLocalMin` was added to `std.numeric`.) + $(P $(REF findLocalMin, std,numeric) finds a real minimum of a real function `f(x)` via bracketing.) + ------- + import std.numeric, std.math; + + auto ret = findLocalMin((double x) => (x-4)^^2, -1e7, 1e7); + + assert(ret.x.approxEqual(4.0)); + assert(ret.y.approxEqual(0.0)); + ------- + ) + + $(LI $(LNAME2 slice_ptr, `ptr` property and public constructor were added to + `std.experimental.ndslice.slice.Slice`.) + $(P `ptr` property allows to access `Slice`'s underlaying pointer or range. + Please refer to $(D std.experimental.ndslice.slice.Slice)'s + internal binary epresentation before using the property. + `ptr` property is used in $(LINK2 https://github.com/libmir/mir, Mir) + for $(LINK2 http://docs.mir.dlang.io/latest/mir_sparse.html, sparse tensors). + `ndslice` developer mirror in Mir will be removed as + soon as LDC (LLVM D compiler) supports D version 2.072. + ) + $(P Public constructor for `Slice` was added to support + $(D std.experimental.ndslice) integration + with other languages and libraries such as Julia language and NumPy library. + ) + ) + + $(LI $(LNAME2 slice_toHash, $(P $(D std.experimental.ndslice.slice.Slice.toHash) method was added.)) + --- + import std.experimental.ndslice; + + // hash is the same for allocated data and generated data + auto a = iotaSlice(3, 7); + auto b = iotaSlice(3, 7).slice; + + assert(a.toHash == b.toHash); + --- + ) + + $(LI $(LNAME2 slice_alloc, `slice`, `shape`, `ndarray`, and other utilities + were added to `std.experimental.ndslice.slice`.) + $(P These utility functions have been added to + $(D std.experimental.ndslice):) + $(UL + $(LI $(D std.experimental.ndslice.slice.makeNdarray),) + $(LI $(D std.experimental.ndslice.slice.makeSlice),) + $(LI $(D std.experimental.ndslice.slice.makeUninitializedSlice),) + $(LI $(D std.experimental.ndslice.slice.ndarray),) + $(LI $(D std.experimental.ndslice.slice.shape),) + $(LI $(D std.experimental.ndslice.slice.slice),) + $(LI $(D std.experimental.ndslice.slice.uninitializedSlice).) + ) + $(P Example: Transposing common 2D array using `ndslice`) + ----- + import std.experimental.ndslice; + + auto ar = [[0, 1, 2], [3, 4, 5]]; + + auto sh = ar.shape; // [2, 3] type of size_t[2] + auto sl = slice!int(sh); // allocates slice with corresponding shape + sl[] = ar; // fills sl with values from ar + ar = sl.transposed.ndarray; // allocates common 2D array + + assert(ar == [[0, 3], [1, 4], [2, 5]]); + ----- + ) + + $(LI $(LNAME2 slice_as, $(P $(D std.experimental.ndslice.slice.as) + lazy tensor was added.)) + --- + import std.experimental.ndslice; + + auto matrix = slice!double([2, 2], 0); + auto stringMatrixView = matrix.as!string; + assert(stringMatrixView == + [["0", "0"], + ["0", "0"]]); + + matrix.diagonal[] = 1; + assert(stringMatrixView == + [["1", "0"], + ["0", "1"]]); + --- + ) + + $(LI $(LNAME2 slice_iota, `iotaSlice` lazy tensor was added to `std.experimental.ndslice.selection`.) + $(P $(D std.experimental.ndslice.selection.iotaSlice) is the fastest possible `Slice`.) + --- + import std.experimental.ndslice; + + auto sl = iotaSlice([2, 3], 10); + + assert(sl.transposed == [[10, 13], + [11, 14], + [12, 15]]); + --- + ) + + $(LI $(LNAME2 slice_index, $(P $(D std.experimental.ndslice.selection.indexSlice) + lazy tensor was added.)) + --- + import std.experimental.ndslice; + + auto slice = indexSlice(2, 3); + + assert(slice == [[[0, 0], [0, 1], [0, 2]], + [[1, 0], [1, 1], [1, 2]]]); + --- + ) + + $(LI $(LNAME2 slice_repeat, $(P $(D std.experimental.ndslice.selection.repeatSlice) + lazy tensor was added.)) + --- + import std.experimental.ndslice; + + auto sl = iotaSlice(3).repeatSlice(4); + assert(sl == [[0, 1, 2], + [0, 1, 2], + [0, 1, 2], + [0, 1, 2]]); + + auto m = 4.repeatSlice(2, 3); + assert(m == [[4, 4, 4], + [4, 4, 4]]); + --- + ) + + $(LI $(LNAME2 slice_map, $(P $(D std.experimental.ndslice.selection.mapSlice) + lazy tensor was added.)) + --- + import std.experimental.ndslice; + + auto s = iotaSlice(2, 3).mapSlice!(a => a * a); + assert(s == [[ 0, 1, 4], + [ 9, 16, 25]]); + --- + ) + + $(LI $(LNAME2 slice_mio, partial support for Math Index Order was added to `std.experimental.ndslice.slice.Slice`.) + --- + import std.experimental.ndslice; + + auto sl = iotaSlice(3, 4); + + assert(sl[2, 3] == 11); // D & C index order + assert(sl(3, 2) == 11); // Math & Fortran index order + --- + ) + + $(LI $(LNAME2 mutation, `std.algorithm.mutation.swapAt` was exposed) + $(P $(REF swapAt, std,algorithm,mutation) allows to swap elements + of a RandomAccessRange by their indices. + ) + ) + + $(LI $(LNAME2 iota-length-size_t, `std.range.iota`'s `.length` property is fixed + to `size_t` instead of the type being iterated) + $(P $(REF iota, std,range)'s `.length` property is now always returned as + `size_t`. This means if you are on a 32-bit CPU and you are using + iota to iterate 64-bit types, the length will be truncated to `size_t`. + In non-release mode, you will get an exception if the length exceeds + `size_t.max` in your call to `iota`. + ) + ) + + $(LI $(LNAME2 min-max-element, `std.algorithm.searching.{min,max}Element` + have been added.) + $(P $(REF minElement, std,algorithm,searching) and $(REF maxElement, std,algorithm,searching) + are functions to search for the minimum and maximum + element in a range. They support a custom `map` accessor. + ) + + ------- + import std.algorithm.searching; + import std.range; + import std.typecons; + assert([3, 1, 4].minElement == 1); + assert([4, 7, 5].enumerate.maxElement!`a.value` == tuple(1, 7)); + ------- + ) + + $(LI $(LNAME2 quantize, Added `std.math.quantize`.) + $(P $(REF quantize, std,math) rounds to the nearest multiple of some number. + Features:) + $(UL + $(LI The rounding method can be specified using the `rfunc` parameter. By + default, the current rounding mode will be used, which is typically + "banker's rounding".) + $(LI Overloads are included for the common case of rounding to the $(I Nth) + digit place in some base.) + $(LI If known at compile time, the base and exponent (digit place) can be + supplied as template parameters for better performance.) + ) + --- + import std.math; + + assert(12345.6789L.quantize(20.0L) == 12340.0L); + assert(12345.6789L.quantize!(10, -2) == 12345.68L); + assert(12345.6789L.quantize!(10, floor)(-2) == 12345.67L); + --- + ) + + $(LI $(LNAME2 traits, Three new traits were added to `std.traits`.) + $(P $(REF isType, std,traits), $(REF isFunction, std,traits), and + $(REF isFinal, std,traits) were added to `std.traits`. + ) + + ------- + import std.traits; + + static assert(isType!int); + + struct S {} + class C {} + interface I {} + + static assert(isType!S); + static assert(isType!C); + static assert(isType!I); + ------- + + ------- + import std.traits; + + void func(){} + struct S + { + @property int prop(){ return 0; } + } + + static assert(isFunction!func); + static assert(isFunction!(S.prop)); + + // is a delegate type, not function type + static assert(!isFunction!(typeof(&S.prop))); + ------- + + ------- + import std.traits; + + class C + { + void nf() {} + final void ff() {} + } + final class FC {} + + static assert(!isFinal!(C)); + static assert( isFinal!(FC)); + static assert(!isFinal!(C.nf)); + static assert( isFinal!(C.ff)); + ------- + ) + + $(LI $(LNAME2 generate, `std.range.generate` fixed to be a proper range.) + $(P $(REF generate, std, range) was set up to return a different value on each + call to `front`. In addition, `popFront` did nothing. This means that + manipulation functions like $(REF drop, std, range) did nothing. The new + version uses a one-element cache to meet the expectations of the range + definition. It preserves the ref-ness of the generator as well. + ) + ) + + $(LI $(LNAME2 headconst, `Final` was added to `std.experimental.typecons`.) + $(P $(REF Final, std, experimental, typecons) can't be mutated directly. + However references are typed with their original mutability. This is + equivalent to `final` in Java or `readonly` in C#. + ) + ------- + auto a = makeFinal([1, 2, 3]); + assert(a[0] == 1); + + // a = [2, 3]; // Reassignment is illegal, + a[0] = 42; // Elements or fields are still mutable. + + assert(a[0] == 42); + ------- + ) + + $(LI $(LNAME2 inner-class, `std.traits.isInnerClass` was added to identify + nested classes with an accessible `outer` pointer) + $(P Classes, that are nested inside other classes (and not inside functions) + and that don't define any `outer` symbol, have an `outer` field which allows + to get and even set the instance of the outer class they are nested in. + $(REF isInnerClass, std, traits) allows to identify them. The types satisfying + `isInnerClass` are a subset of the ones satisfying `isNested`, as the latter + includes classes and structures nested inside functions or that redefine `outer`. + ) + ------- + class Outer + { + class Inner1 { } + class Inner2 + { + int outer; // redefines outer, so the Outer instance is not accessible + } + static class Inner3 {} // static, thus not nested + } + static assert(isInnerClass!(Outer.Inner1)); + static assert(!isInnerClass!(Outer.Inner2)); + static assert(!isInnerClass!(Outer.Inner3)); + ------- + ) + + $(LI $(LNAME2 emplace-inner-class, `std.conv.emplace` no longer allows to emplace + classes nested directly inside other classes without specifying a suitable `outer` + pointer) + $(P If a class is nested within another class (there's a new trait + $(REF isInnerClass, std, traits) to check for this condition), `emplace` requires + now the outer class instance as additional mandatory parameter. Before this + change, emplacing did not require this parameter and access to variables of the + outer class resulted in segmentation faults. + ) + ------- + class Outer + { + int x; + class Inner + { + auto getX() { return x; } + } + } + Outer outer = new Outer(); + + // auto inner = buf.emplace!(Outer.Inner)(); // this is no longer allowed + auto inner = buf.emplace!(Outer.Inner)(outer); // use this instead + + auto x = inner.getX(); // this used to cause a segmentation fault; + // now it works as expected + ------- + ) + + $(LI $(LNAME2 gc-runtimeswitch-added, A runtime switch for selecting + the GC implementation was added.) + + $(P This allows to select a GC at program startup.) + ------- + ./my_d_exe --DRT-gcopt=gc:conservative # use conservative GC (default) + ./my_d_exe --DRT-gcopt=help # list available GC options + ------- + $(P See $(LINK2 $(ROOT_DIR)spec/garbage.html#gc_config, gc_config) for more information about gcopt.) + $(P In a future release it should be possible to extend the list + of GCs by linking with an alternative one. + ) + ) + + $(LI $(LNAME2 manualgc-added, A manual GC was added.) + + $(P Use the `--DRT-gc=gc:manual` option to select the manual GC.) + + $(P This GC is a thin wrapper around malloc and free and does not collect + any garbage. It only releases memory explicity freed using $(REF_SHORT GC.free, core,memory). + Builtin language constructs such as arrays or delegates that might + allocate GC memory can leak. It supersedes the gcstub implementation. + ) + + $(P The manual GC is useful for applications that deterministically control memory. + Use dmd's `-vgc` switch to keep track of hidden allocations that might leak. + ) + $(P It can also be helpful to find memory corruptions with tools like valgrind.) + ) +) +) + + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(P +$(LI $(BUGZILLA 15726): [REG2.068.0] forward reference error for circular classes, RefCounted) +$(LI $(BUGZILLA 15861): [REG 2.069] Wrong double-to-string conversion with -O) +$(LI $(BUGZILLA 15925): -transition=[check]imports ignores import declaration from mixin templates) +$(LI $(BUGZILLA 15992): [REG2.072a] ICE with field variable of instantiated struct) +$(LI $(BUGZILLA 16080): [REG2.071.0] Internal error: backend\cgobj.c 3406 when building static library) +$(LI $(BUGZILLA 16115): [REG2.067] Wrong code with comma operator) +$(LI $(BUGZILLA 16233): [REG2.069] ICE on wrong code) +$(LI $(BUGZILLA 16254): [REG 2.072-devel] wrong switch skips initialization error with mixed in case labels) +$(LI $(BUGZILLA 16292): [REG2.069] bogus Error: goto skips declaration of variable) +$(LI $(BUGZILLA 16536): DMD master does not build on OS X 10.11.6/Xcode 7.3.1) +$(LI $(BUGZILLA 16570): [REG 2.072.0-b1] Enum member with interpreted initializer has type of initializer not enum) +) +) +$(BUGSTITLE DMD Compiler bugs, + +$(P +$(LI $(BUGZILLA 1357): Cannot use FFFF and FFFE in Unicode escape sequences.) +$(LI $(BUGZILLA 5305): Cannot take pointer to intrinsic function) +$(LI $(BUGZILLA 10225): core.simd wrong codegen for XMM.STOUPS with __simd_sto) +$(LI $(BUGZILLA 10591): Error: only one main allowed doesn't show location of conflicting main symbols) +$(LI $(BUGZILLA 11047): UDA + getAttributes bypass purity/safety check) +$(LI $(BUGZILLA 11169): __traits$(LPAREN)isAbstractClass$(RPAREN) prematurely sets a class to be abstract) +$(LI $(BUGZILLA 11585): ICE$(LPAREN)cgcod.c$(RPAREN) with SIMD and -O) +$(LI $(BUGZILLA 12357): Untyped string variable fails silently. No compiler warning given.) +$(LI $(BUGZILLA 12527): Cannot make @system function/delegate alias in a @safe section) +$(LI $(BUGZILLA 12537): Templatizing opEquals results in infinite recursion in the compiler) +$(LI $(BUGZILLA 12558): try/catch allows implicit catching of Errors without specifying any Exception type) +$(LI $(BUGZILLA 12822): Delegate .ptr assignment considered @safe) +$(LI $(BUGZILLA 12939): More uniform error messages for not nothrow and not @safe functions) +$(LI $(BUGZILLA 13116): Should not be able to return ref to 'this') +$(LI $(BUGZILLA 13147): Wrong codegen for thisptr in naked extern $(LPAREN)C++$(RPAREN) methods) +$(LI $(BUGZILLA 13536): Union of delegates breaks @safety) +$(LI $(BUGZILLA 13537): Unions may break immutability) +$(LI $(BUGZILLA 13674): ICE$(LPAREN)el.c$(RPAREN) with simd multiplication of short8) +$(LI $(BUGZILLA 13698): ICE$(LPAREN)e2ir.c$(RPAREN) on on simd call) +$(LI $(BUGZILLA 13867): Overriding a method from an extern$(LPAREN)C++$(RPAREN) interface requires extern$(LPAREN)C++$(RPAREN) on the method definition) +$(LI $(BUGZILLA 13975): ICE: dmd crash if -gc and enum member is immutable int) +$(LI $(BUGZILLA 14162): Erratic inference of @safe for lambdas) +$(LI $(BUGZILLA 14450): Incorrect overloading of immutable constructor for template struct) +$(LI $(BUGZILLA 14496): void initialization of member with indirections must not be @safe) +$(LI $(BUGZILLA 14504): Regex Optimizer doesn't merge equivalent threads.) +$(LI $(BUGZILLA 14532): switch block allows creating uninitialized variables) +$(LI $(BUGZILLA 15116): Unreasonable rejection of tuple field access via named mixin) +$(LI $(BUGZILLA 15117): Unreasonable circular reference error via named mixin) +$(LI $(BUGZILLA 15144): Bad operand size in asm { movdqa ... } produces bogus ubyte16 initializer error elsewhere.) +$(LI $(BUGZILLA 15191): DIP25: Taking address of ref return is not type checked soundly) +$(LI $(BUGZILLA 15192): DIP25: Nested ref returns are type checked unsoundly) +$(LI $(BUGZILLA 15193): DIP25 $(LPAREN)implementation$(RPAREN): Lifetimes of temporaries tracked incorrectly) +$(LI $(BUGZILLA 15258): Anonymous const union members don't allow for initialization) +$(LI $(BUGZILLA 15306): Delegates with shared context can have unshared aliasing) +$(LI $(BUGZILLA 15326): False positive for dangling else warning) +$(LI $(BUGZILLA 15333): Assertion failed: $(LPAREN)!fd->vthis->csym$(RPAREN), function FuncDeclaration_toObjFile, file glue.c, line 1034.) +$(LI $(BUGZILLA 15372): DMD emits wrong mangling for extern$(LPAREN)C++$(RPAREN) free function templates) +$(LI $(BUGZILLA 15399): unaligned pointers are not @safe) +$(LI $(BUGZILLA 15513): Memory Corruption with thread local objects) +$(LI $(BUGZILLA 15573): -O -inline causes wrong code with idiv instruction) +$(LI $(BUGZILLA 15607): [ICE] CTFE internal error: bad compare on accessing default-initialized static immutable array of array) +$(LI $(BUGZILLA 15672): Casting from void[] to T[] is erroneously considered @safe) +$(LI $(BUGZILLA 15680): TypeInfo broken for typeof$(LPAREN)null$(RPAREN)) +$(LI $(BUGZILLA 15703): @safe code should not allow certain types of array casts) +$(LI $(BUGZILLA 15704): @safe code should not allow copying to/from void[]) +$(LI $(BUGZILLA 15757): D main is a nested function and cannot be accessed) +$(LI $(BUGZILLA 15760): Segfault when compiling when using __gshared and selective import.) +$(LI $(BUGZILLA 15762): Array casts involving const enums can be made @safe) +$(LI $(BUGZILLA 15799): Misleading error message against the contract followed by semicolon in interface) +$(LI $(BUGZILLA 15802): $(LPAREN)SIGSEGV$(RPAREN) CppMangleVisitor::source_name) +$(LI $(BUGZILLA 15816): ICE void ddmd.dclass.__assert$(LPAREN)int$(RPAREN) with error: anonymous classes not allowed) +$(LI $(BUGZILLA 15835): Segfault with typeid call from lazy argument) +$(LI $(BUGZILLA 15855): "a[{for" causes dmd to segfault) +$(LI $(BUGZILLA 15913): cannot initialize immutable fixed size array without similar const-code) +$(LI $(BUGZILLA 15922): DMD segfault in functionParameters$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 15934): Non-virtual super class member function call ignores 'this' type qualifier) +$(LI $(BUGZILLA 15957): Disabled postblit + template mixin break opAssign with confusing error message) +$(LI $(BUGZILLA 15974): Spurious error: argument to mixin must be a string, not $(LPAREN)expression$(LPAREN)$(RPAREN)$(RPAREN) of type string) +$(LI $(BUGZILLA 15999): Inline assembly incorrect sign extension instead of error) +$(LI $(BUGZILLA 16035): Compiler crashes with inout, templates, and recursion) +$(LI $(BUGZILLA 16094): error: overlapping slice assignment $(LPAREN)CTFE$(RPAREN)) +$(LI $(BUGZILLA 16095): a delegate can mutate immutable data and break shared / non-shared enforcements) +$(LI $(BUGZILLA 16096): Linking to static library: can't parse __DATA/__objc_imageinfo) +$(LI $(BUGZILLA 16142): Adding a dtor / postblit $(LPAREN)even disabled$(RPAREN) forces opAssign) +$(LI $(BUGZILLA 16193): opApply$(LPAREN)$(RPAREN) doesn't heap allocate closure) +$(LI $(BUGZILLA 16195): delete should be @system) +$(LI $(BUGZILLA 16226): -dip25 doesn't work if the return type is not explicit) +$(LI $(BUGZILLA 16228): Insufficient diagnostics for wrong application of DIP25) +$(LI $(BUGZILLA 16229): [Win64] Crash when generating huge symbols) +$(LI $(BUGZILLA 16340): case where version$(LPAREN)unittest$(RPAREN) results in an invalid warning about a dangling else) +$(LI $(BUGZILLA 16365): cannot allow calling function pointer from delegate in @safe code) +$(LI $(BUGZILLA 16439): Non-typesafe variadic functions can never be @safe) +$(LI $(BUGZILLA 16466): Alignment of reals inside structs on 32 bit OSX should be 16, not 8) +$(LI $(BUGZILLA 16525): C++ member variables have no mangling) +$(LI $(BUGZILLA 16530): -O -cov interaction leads to wrong codegen) +$(LI $(BUGZILLA 16534): RefRange should define opDollar if it defines length) +) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(P +$(LI $(BUGZILLA 2659): Remove the comma operator) +$(LI $(BUGZILLA 3657): No lexical scope for local variables in debug info) +$(LI $(BUGZILLA 3827): Warn against and then deprecate implicit concatenation of adjacent string literals) +$(LI $(BUGZILLA 9766): align$(LPAREN)n$(RPAREN) with n compile-time constant) +$(LI $(BUGZILLA 11886): "cannot access frame" error on lambda in lambda) +$(LI $(BUGZILLA 13242): imported aliases should be analyzed lazily) +$(LI $(BUGZILLA 14411): switch statement: docs/behavior differ) +$(LI $(BUGZILLA 15323): Module.members and .deferred3 should use data structure with fast lookup) +$(LI $(BUGZILLA 16077): [CodeView] no language information in MS-COFF debug information) +$(LI $(BUGZILLA 16394): TypeInfo.init$(LPAREN)$(RPAREN) for static arrays returns single element instead of whole array) +$(LI $(BUGZILLA 16409): Add support for assign-style switches) +) +) +$(BUGSTITLE Phobos regressions, + +$(P +$(LI $(BUGZILLA 15457): Symbol Undefined __lseeki64) +$(LI $(BUGZILLA 15918): [2.070] Results from findSplit can no longer be assigned to each other) +$(LI $(BUGZILLA 16179): [REG2.072] git HEAD: multiSort no longer callable with delegate with context) +$(LI $(BUGZILLA 16291): phobosinit never gets called $(LPAREN)EncodingScheme.create fails$(RPAREN)) +$(LI $(BUGZILLA 16544): Add File.reopen) +$(LI $(BUGZILLA 16580): [REG 2.072.0-b1] spawnShell segfaults on macOS) +$(LI $(BUGZILLA 16587): split$(LPAREN)"", "x"$(RPAREN) should be []) +) +) +$(BUGSTITLE Phobos bugs, + +$(P +$(LI $(BUGZILLA 4509): XML parser in std.xml throws TagException if the attr value is put in apostrophes.) +$(LI $(BUGZILLA 7972): std.file.read allocate a buffer the size of the file even when given a upper limit) +$(LI $(BUGZILLA 7989): isInputRange and isForwardRange declare unused variables) +$(LI $(BUGZILLA 11791): std.file.write failed to write huge files) +$(LI $(BUGZILLA 12368): std.file.write conflicts with std.stdio.write) +$(LI $(BUGZILLA 12897): std.json.toJSON doesn't translate unicode chars$(LPAREN)>=0x80$(RPAREN) to "\uXXXX") +$(LI $(BUGZILLA 13572): etc.c.zlib must be nothrow) +$(LI $(BUGZILLA 14136): std.uni.utfMatcher breaks @safety) +$(LI $(BUGZILLA 14137): std.socket.getAddressInfo breaks @safety) +$(LI $(BUGZILLA 14485): .front of empty filtered zip range is accessible) +$(LI $(BUGZILLA 14615): std.regex.replaceFirstInto throws exception when no match is found) +$(LI $(BUGZILLA 14966): Comparing two std.xml.Document result in infinite recursion) +$(LI $(BUGZILLA 15341): segfault with std.signals slots) +$(LI $(BUGZILLA 15658): isFile isn't a template) +$(LI $(BUGZILLA 15773): D's treatment of whitespace in character classes in free-form regexes is not the same as Perl's) +$(LI $(BUGZILLA 15791): Cannot get a stored nested struct object from Variant) +$(LI $(BUGZILLA 15823): opIndex doesn't work for const std.variant.Variant) +$(LI $(BUGZILLA 15827): std.variant.Variant can not be initialized with some struct) +$(LI $(BUGZILLA 15864): chmgen triggers exception in std.regex) +$(LI $(BUGZILLA 15865): std.file.copy$(LPAREN)from,to$(RPAREN) deletes the file if from and to specify the same file) +$(LI $(BUGZILLA 15872): [ndslice] indexing a slice with an array causes an error inside ndslice) +$(LI $(BUGZILLA 15874): getSymbolsByUDA fails if struct has no UDAs) +$(LI $(BUGZILLA 15884): Assigning char[] to std.json.JSONValue creates array, not string) +$(LI $(BUGZILLA 15885): float serialized to JSON loses precision) +$(LI $(BUGZILLA 15917): std.concurrency module destructor causes useless creation of new MessageBox) +$(LI $(BUGZILLA 15919): [ndslice] Undetected spell miss in selection.reshape$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 15920): std.traits.MemberFunctionsTuple gives a wrong result) +$(LI $(BUGZILLA 15960): SetUnion should filter duplicates) +$(LI $(BUGZILLA 15963): Hidden unresolved forward reference issue in std.uni) +$(LI $(BUGZILLA 15964): The template constraints for std.uni.sicmp are too permissive) +$(LI $(BUGZILLA 15973): nextPow2 and truncPow2 rely on processor specific behavior) +$(LI $(BUGZILLA 15980): std.traits.Identity is undocumented but public) +$(LI $(BUGZILLA 16010): [ndslice] byElement throw assert error) +$(LI $(BUGZILLA 16026): std.math.frexp!float$(LPAREN)$(RPAREN) wrong for very small subnormal values) +$(LI $(BUGZILLA 16036): std.net.isemail - isEmail reurns "valid: false" for any email with EmailStatusCode.none $(LPAREN)default$(RPAREN)) +$(LI $(BUGZILLA 16046): ScopedAllocator does not set prev, causing segfaults) +$(LI $(BUGZILLA 16054): can break immutable with std.typecons.Rebindable) +$(LI $(BUGZILLA 16070): std.meta.{ApplyLeft,ApplyRight} fail with mixed type/value arguments) +$(LI $(BUGZILLA 16072): std.container.binaryheap should be extendable for arrays) +$(LI $(BUGZILLA 16090): popFront generates out-of-bounds array index on corrupted utf-8 strings) +$(LI $(BUGZILLA 16192): std.conv.toChars$(LPAREN)$(RPAREN) opSlice wrong for radix other than 10) +$(LI $(BUGZILLA 16219): std.experimental.allocator.makeArray does unnecessary allocations for ranges with length) +$(LI $(BUGZILLA 16238): std.string.lastIndexOf fails compilation with -de) +$(LI $(BUGZILLA 16241): std.xml mistakenly disallows "==" in comments but allows "--") +$(LI $(BUGZILLA 16331): std.container.array constructor shouldn't check result of emplacement) +$(LI $(BUGZILLA 16351): Nonstandard output library causes no-argument writeln$(LPAREN)$(RPAREN) to fail.) +$(LI $(BUGZILLA 16372): Broken links in documentation) +$(LI $(BUGZILLA 16383): Algebraic visit does not match handlers to const classes) +$(LI $(BUGZILLA 16385): std.range: undefined behaviour when skipping over 0xff in string.popFront) +$(LI $(BUGZILLA 16386): std.concurrency: destructors called twice on objects passed as Message) +$(LI $(BUGZILLA 16387): getSymbolsByUDA works with structs but fails with classes) +$(LI $(BUGZILLA 16413): multiSort doesn't work with @system comparison function) +$(LI $(BUGZILLA 16420): Incorrect example in std.getopt docs) +$(LI $(BUGZILLA 16501): packed ndslices does not compile) +$(LI $(BUGZILLA 16503): [ndslice] prevents fastmath LDC attribute) +$(LI $(BUGZILLA 16506): segfaults in std.experimental.allocator: FreeTree with GCAllocator or Mallocator) +$(LI $(BUGZILLA 16507): std.experimental.allocator: FreeTree clears too eagerly) +) +) +$(BUGSTITLE Phobos enhancements, + +$(P +$(LI $(BUGZILLA 2104): std.regex: escape function for regular expressions) +$(LI $(BUGZILLA 7551): Regex parsing bug for right bracket in character class) +$(LI $(BUGZILLA 10777): std.algorithm.multiSort to return a std.range.SortedRange) +$(LI $(BUGZILLA 11229): std.string.toLower is slow) +$(LI $(BUGZILLA 12227): Allow matching multiple patterns in one go with std.regex) +$(LI $(BUGZILLA 12367): std.regex: Recognize $(LPAREN)?# ... $(RPAREN) comment syntax) +$(LI $(BUGZILLA 12379): Add toFile function which writes its first argument to a file) +$(LI $(BUGZILLA 13409): std.range.padLeft/Right) +$(LI $(BUGZILLA 13422): std.ascii has isAlphaNum but std.uni doesn't) +$(LI $(BUGZILLA 13796): A simple "array head const" struct for Phobos) +$(LI $(BUGZILLA 15229): BigInt$(LPAREN)Range of chars$(RPAREN) too) +$(LI $(BUGZILLA 15797): Add Option to Not Drop Matches in std.regex.splitter) +$(LI $(BUGZILLA 15800): std.conv.to!int does not work with ranges of any char type) +$(LI $(BUGZILLA 15803): std.file should support sub-second file time precision on POSIX) +$(LI $(BUGZILLA 15860): lockstep should support foreach_reverse) +$(LI $(BUGZILLA 15991): std.datetime.StopWatch is not @nogc) +$(LI $(BUGZILLA 15995): std.conv.text and friends can be made faster with std.array.appender) +$(LI $(BUGZILLA 16308): [ndslice] should always has save primitive) +$(LI $(BUGZILLA 16311): toHash for Slice is not defined) +$(LI $(BUGZILLA 16315): [] ?= operations does not work with packed slices [ndslice]) +$(LI $(BUGZILLA 16319): std.experimental.allocator.make subtly wrong with nested classes) +$(LI $(BUGZILLA 16363): Cannot construct a random access range using frontTransversal) +$(LI $(BUGZILLA 16364): getUDAs and hasUDA do not give consistent results) +$(LI $(BUGZILLA 16443): std.getopt: segmentation fault with empty string option) +) +) +$(BUGSTITLE Druntime regressions, + +$(P +$(LI $(BUGZILLA 1180): the GC failes to handle large allocation requests propperly) +$(LI $(BUGZILLA 16211): [REG 2.058] Cyclic dependencies broken again) +) +) +$(BUGSTITLE Druntime bugs, + +$(P +$(LI $(BUGZILLA 6333): The 'capacity' function is not pure/nothrow/@safe.) +$(LI $(BUGZILLA 14601): pthread functions aren't marked @nogc) +$(LI $(BUGZILLA 15111): hashOf fails for structs that have an alias this to a dynamic array) +$(LI $(BUGZILLA 15838): Many Win32 API callback functions miss extern$(LPAREN)Windows$(RPAREN)) +$(LI $(BUGZILLA 15958): Missing extern$(LPAREN)Windows$(RPAREN) of core.sys.windows functions) +$(LI $(BUGZILLA 15959): core.sys.windows modules should be modified for x64) +$(LI $(BUGZILLA 15976): explicite TLS initializes badly in DLLs if other threads exist) +$(LI $(BUGZILLA 15987): core.sys.windows.msacm remains pseudo definitions) +$(LI $(BUGZILLA 15997): Wrong constant value for ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED in winhttp) +$(LI $(BUGZILLA 16007): Some Win32 API structs has wrong definitions) +$(LI $(BUGZILLA 16049): core.sys.windows structs have wrong sizes and aligns) +$(LI $(BUGZILLA 16594): module destructors called again if an exception got thrown earlier) +) +) +$(BUGSTITLE Druntime enhancements, + +$(P +$(LI $(BUGZILLA 14117): core.atomic should be @safe) +) +) +$(BUGSTITLE dlang.org bugs, + +$(P +$(LI $(BUGZILLA 15442): Eponymous template restrictions should be documented) +$(LI $(BUGZILLA 16004): Document changes to protection attributes) +$(LI $(BUGZILLA 16016): Remove std.concurrencybase from the docs) +$(LI $(BUGZILLA 16040): Remove Dconf announcement) +$(LI $(BUGZILLA 16114): [ddox] "Improve this page" links broken for package.d modules) +$(LI $(BUGZILLA 16167): chm-nav.json generation is broken) +$(LI $(BUGZILLA 16186): [Programming in D for C Programmers] Backticks should be escaped in explanation of raw string syntax) +$(LI $(BUGZILLA 16231): Language specification: rename std.regexp -> std.regex) +) +) +$(BUGSTITLE dlang.org enhancements, + +$(P +$(LI $(BUGZILLA 16141): Organizations page unreachable) +$(LI $(BUGZILLA 16152): dpl-docs/ddox doesn't show documentation for eponymous template member) +$(LI $(BUGZILLA 16464): opCast doco is insufficient) +) +) +$(BUGSTITLE Installer bugs, + +$(P +$(LI $(BUGZILLA 16349): better curl retry for install.sh script) +) +) + +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.072.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.072.1.dd b/changelog/2.072.1.dd new file mode 100644 index 0000000000..6a3c50deeb --- /dev/null +++ b/changelog/2.072.1.dd @@ -0,0 +1,38 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Nov 30, 2016, =================================================, + +$(BR)$(BIG List of all bug fixes and enhancements in D $(VER):) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 16102): [REG2.070] struct dtor replace value on stack) +$(LI $(BUGZILLA 16574): [REG 2.072.0-b1] Unexplained errors about functions that overridde anything) +$(LI $(BUGZILLA 16678): [REG] Fix for issue 16193 creates major breakage) +$(LI $(BUGZILLA 16699): [REG 2.070] stack corruption with scope$(LPAREN)exit$(RPAREN)) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 13927): optimizer hangs in optelem with SIMD initialization) +$(LI $(BUGZILLA 16193): opApply$(LPAREN)$(RPAREN) doesn't heap allocate closure) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 16661): [REG2.072] std/format.d$(LPAREN)1070$(RPAREN): Incorrect format specifier: .2f for wstring and dstring) +$(LI $(BUGZILLA 16663): [REG 2.072] std.unit.toUpper rejects an alias this to a string) +$(LI $(BUGZILLA 16667): [REG] dub test fails on std.conv after upgrade to dmd 2.072.0) +$(LI $(BUGZILLA 16682): [REG 2.072] "privatization" of symbols in std.stdio breaks DFMT) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 16651): atomicOp!"-="$(LPAREN)ulong, uint$(RPAREN) = wrong result/codegen) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.072.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.072.2.dd b/changelog/2.072.2.dd new file mode 100644 index 0000000000..847ccda9da --- /dev/null +++ b/changelog/2.072.2.dd @@ -0,0 +1,66 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Dec 31, 2016, =================================================, + +$(BUGSTITLE Library Changes, + $(LI $(RELATIVE_LINK2 drt-cycle-deprecated, The --DRT-cycle=deprecate runtime switch was added.)) +) + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BUGSTITLE Library Changes, + + $(LI $(LNAME2 drt-cycle-deprecated, The --DRT-cycle=deprecate runtime switch was added.) + + $(P As a follow-up to the fixed module cycle detection in + 2.072.0, the $(LINK2 $(ROOT_DIR)spec/module.html#override_cycle_abort,--DRT-oncycle) + runtime switch got a deprecate option. + It was made default, instead of --DRT-oncycle=abort, in + order to deprecate code that was relying on previously + undected module constructor cycles. + ) + ) +) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 16747): [Reg 2.072] Cannot have stack allocated classes in @safe code) +$(LI $(BUGZILLA 16980): [REG2.072.0] wrong interface called) +$(LI $(BUGZILLA 17029): [Reg 2.072] scope variable may not be returned) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 16667): [REG] dub test fails on std.conv after upgrade to dmd 2.072.0) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 9378): std.internal.digest.sha_SSE3 breaks if compiled with PIC) +$(LI $(BUGZILLA 16794): dmd not working on Ubuntu 16.10 because of default PIE linking) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 16974): [REG2.068] Equal associative arrays with associative array keys are considered unequal) +) +$(BUGSTITLE dlang.org bugs, + +$(LI $(BUGZILLA 16948): broken links in std.stdio due to inccorrect use of WEB macro) +) +$(BUGSTITLE Tools regressions, + +$(LI $(BUGZILLA 14296): RDMD fails at building a lib when the source is in a subdir) +$(LI $(BUGZILLA 16962): rdmd --build-only --force -c main.d fails: ./main: No such file or directory) +$(LI $(BUGZILLA 16978): [REG2.072.0] pragma$(LPAREN)lib$(RPAREN) is broken with rdmd) +) + +) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.072.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.073.0.dd b/changelog/2.073.0.dd new file mode 100644 index 0000000000..c70048746e --- /dev/null +++ b/changelog/2.073.0.dd @@ -0,0 +1,320 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 22, 2017, =================================================, + +$(BUGSTITLE Compiler changes, + +$(LI $(RELATIVE_LINK2 mscrtlib-option,New command line option $(B -mscrtlib=$(I libname)) for Windows MS-COFF object files.)) +$(LI $(RELATIVE_LINK2 overhauled_ddoc_theme,The builtin Ddoc theme has been overhauled.)) + +) + +$(BUGSTITLE Library changes, + +$(LI $(RELATIVE_LINK2 std-traits-promoted,Added `std.traits.Promoted` to get the result of scalar type promotion in multi-term arithmetic expressions)) +$(LI $(RELATIVE_LINK2 std-algorithm-searching-maxindex,Added `std.algorithm.searching.maxIndex` to get the index of the maximum element of a range.)) +$(LI $(RELATIVE_LINK2 std-meta-staticissorted,Added `std.meta.staticIsSorted` to check if an `AliasSeq` is sorted according to some template predicate.)) +$(LI $(RELATIVE_LINK2 std-algorithm-searching-minindex,Added `std.algorithm.searching.minIndex` to get the index of the minimum element of a range.)) +$(LI $(RELATIVE_LINK2 std-traits-hasFunctionAttributes,`std.traits.hasFunctionAttributes` has been added)) +$(LI $(RELATIVE_LINK2 ndslice-removal,`std.experimental.ndslice` has been deprecated.)) + +) + +$(BUGSTITLE Language changes, + +$(LI $(RELATIVE_LINK2 mcpu_avx,Add `D_AVX` predefined version when $(TT -mcpu=avx) is used.)) + +) + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BUGSTITLE Compiler changes, + +$(LI $(LNAME2 mscrtlib-option,New command line option $(B -mscrtlib=$(I libname)) for Windows MS-COFF object files.) + $(P + If building MS-COFF object files with -m64 or -m32mscoff, this option + specifies the reference to the C runtime library $(I libname) that is + embedded into the object file containing `main`, + `DllMain` or `WinMain` for automatic linking. The default is $(TT libcmt) + (release version with static linkage), the other usual alternatives are + $(TT libcmtd), $(TT msvcrt) and $(TT msvcrtd). + If $(I libname) is empty, no C runtime library is automatically linked in. + ) +) + +$(LI $(LNAME2 overhauled_ddoc_theme,The builtin Ddoc theme has been overhauled.) + $(P + Dmd will now use more modern looking theme for generated documentation, + also see $(LINK2 https://github.com/dlang/dmd/pull/6173, dmd#6173). + ) +) + + +) + +$(BUGSTITLE Library changes, + +$(LI $(LNAME2 std-traits-promoted,Added `std.traits.Promoted` to get the result of scalar type promotion in multi-term arithmetic expressions) + $(P + `std.traits.Promoted` gets the type to which a scalar type will be promoted + in multi-term arithmetic expressions + ) + ------- + import std.traits : Promoted; + static assert(is(typeof(ubyte(3) * ubyte(5)) == Promoted!ubyte)); + static assert(is(Promoted!ubyte == int)); + ------- + + $(P + See the D specification on $(LINK2 $(ROOT_DIR)spec/type.html#integer-promotions, + scalar type promotions) for more information. + ) +) + +$(LI $(LNAME2 std-algorithm-searching-maxindex,Added `std.algorithm.searching.maxIndex` to get the index of the maximum element of a range.) + $(P + `std.algorithm.searching.maxIndex` gets the index of the maximum element of a range, + according to a specified predicate. The default predicate is "a > b". + ) + + ------- + import std.algorithm.searching : maxIndex; + int[] a = [5, 4, 2, 1, 9, 10]; + assert(a.maxIndex == 5); + + int[] a; + assert(a.maxIndex == -1); + ------- +) + +$(LI $(LNAME2 std-meta-staticissorted,Added `std.meta.staticIsSorted` to check if an `AliasSeq` is sorted according to some template predicate.) + $(P + `std.meta.staticIsSorted` checks whether an `AliasSeq` is + sorted according to some template predicate. + ) + ------ + enum Comp(T1, T2) = T1.sizeof < T2.sizeof; + + import std.meta : staticIsSorted; + static assert( staticIsSorted!(Comp, byte, uint, double)); + static assert(!staticIsSorted!(Comp, bool, long, dchar)); + ------ + + $(P + Additionally, the compile-time performance of `std.meta.staticSort` has been + greatly improved. Nevertheless, due to compiler limitations it is still an + extraordinarily expensive operation to perform on longer sequences; strive to + minimize such use. + ) +) + +$(LI $(LNAME2 std-algorithm-searching-minindex,Added `std.algorithm.searching.minIndex` to get the index of the minimum element of a range.) + $(P + `std.algorithm.searching.minIndex` gets the index of the minimum element of a range, + according to a specified predicate. The default predicate is "a < b". + ) + + ------- + import std.algorithm.searching : minIndex; + int[] a = [5, 4, 2, 1, 9, 10]; + assert(a.minIndex == 3); + + int[] a; + assert(a.minIndex == -1); + ------- +) + +$(LI $(LNAME2 std-traits-hasFunctionAttributes,`std.traits.hasFunctionAttributes` has been added) + $(P + It exposes a user-friendly way to query for function attributes: + ) + ------- + import std.traits : hasFunctionAttributes; + + // manually annotated function + real func(real x) pure nothrow @safe + { + return x; + } + static assert(hasFunctionAttributes!(func, "@safe", "pure")); + static assert(!hasFunctionAttributes!(func, "@trusted")); + + // for templated function types are automatically inferred + bool myFunc(T)(T b) + { + return !b; + } + static assert(hasFunctionAttributes!(myFunc!bool, "@safe", "pure", "@nogc", "nothrow")); + static assert(!hasFunctionAttributes!(myFunc!bool, "shared")); + ------- +) + +$(LI $(LNAME2 ndslice-removal,`std.experimental.ndslice` has been deprecated.) + $(P + The synchronization between Phobos and Mir turned out to be a lot of work + with litte gain. Users of `std.experimental.ndslice` are advised to + switch to the upstream $(LINK2 https://github.com/libmir/mir-algorithm, mir package). + ) +) + + +) + +$(BUGSTITLE Language changes, + +$(LI $(LNAME2 mcpu_avx,Add `D_AVX` predefined version when $(TT -mcpu=avx) is used.) +) + + +) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 16102): [REG2.070] struct dtor replace value on stack) +$(LI $(BUGZILLA 16278): [REG2.067] undefined reference when class template is instantiated only in 'is' expression) +$(LI $(BUGZILLA 16574): [REG 2.072.0-b1] Unexplained errors about functions that overridde anything) +$(LI $(BUGZILLA 16598): [REG2.069] ICE with void ternary + finalizers) +$(LI $(BUGZILLA 16678): [REG] Fix for issue 16193 creates major breakage) +$(LI $(BUGZILLA 16699): [REG 2.070] stack corruption with scope$(LPAREN)exit$(RPAREN)) +$(LI $(BUGZILLA 16747): [Reg 2.072] Cannot have stack allocated classes in @safe code) +$(LI $(BUGZILLA 16980): [REG2.072.0] wrong interface called) +$(LI $(BUGZILLA 17029): [Reg 2.072] scope variable may not be returned) +$(LI $(BUGZILLA 17059): [REG 2.072.2] incorrect circular reference with `is$(LPAREN)Klass : Interface$(RPAREN)`) +$(LI $(BUGZILLA 17072): [REG 2.073.0-b1] missing symbols with -inline) +$(LI $(BUGZILLA 17073): [Reg 2.071.0] Priority clash with `void` default initialization of struct fields) +$(LI $(BUGZILLA 17074): extern$(LPAREN)C++, keyword$(RPAREN) crashes compiler) +$(LI $(BUGZILLA 17087): [REG2.072] Wrong generated with cfloat and creal when casting from int) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 922): export keyword causes undefined references on linux) +$(LI $(BUGZILLA 1761): TypeInfo.toString for function types always indicates no-parameter function) +$(LI $(BUGZILLA 5995): string append negative integer causes segfault) +$(LI $(BUGZILLA 8838): Slicing static arrays should be considered unsafe $(LPAREN)@system$(RPAREN)) +$(LI $(BUGZILLA 10447): Refused increment of double2 with a immutable$(LPAREN)double2$(RPAREN)) +$(LI $(BUGZILLA 11118): undefined identifier in template structs functions) +$(LI $(BUGZILLA 11961): Can't select CRT to link against) +$(LI $(BUGZILLA 12430): non compile-time __simd opcode causes ICE) +$(LI $(BUGZILLA 13927): optimizer hangs in optelem with SIMD initialization) +$(LI $(BUGZILLA 14238): DIP25: escape checks can be circumvented with delegate) +$(LI $(BUGZILLA 14613): DMD: Internal error: backend/cod1.c 1567 on '-O' switch) +$(LI $(BUGZILLA 15544): Escaping fields to a heap delegate must be disallowed in @safe code) +$(LI $(BUGZILLA 15576): extern$(LPAREN)C++, namespace$(RPAREN) wrong mangling of variables $(LPAREN)Windows$(RPAREN)) +$(LI $(BUGZILLA 15862): Functions that return types with mutable indirections should be weakly pure, not strongly pure) +$(LI $(BUGZILLA 15989): Initializing manifest constants with CTFE allocated data) +$(LI $(BUGZILLA 16116): Infinite loop on $(LPAREN)somewhat complex$(RPAREN) simd math) +$(LI $(BUGZILLA 16146): postblit is not called on struct creation with "{field:value}" syntax) +$(LI $(BUGZILLA 16381): Wrapping a float4 array leads to segfault.) +$(LI $(BUGZILLA 16488): [spec][optimization] broadcast scalar to simd vector) +$(LI $(BUGZILLA 16499): Misleading error message for 'in' operator with wrong argument) +$(LI $(BUGZILLA 16523): [ICE] Internal error: backend/symbol.c 1031) +$(LI $(BUGZILLA 16589): Taking address of stack variables in @safe code is allowed in some cases) +$(LI $(BUGZILLA 16679): prefetch on old pentium d results in an illegal instruction) +$(LI $(BUGZILLA 16743): Intrinsic recognition sometimes fails if a software implementation is available) +$(LI $(BUGZILLA 16854): Inline assembler has VMOVLHPS and VMOVHLPS swapped) +$(LI $(BUGZILLA 16967): No switch case fallthrough warnings in in/out contracts) +$(LI $(BUGZILLA 16977): bad debug info for function default arguments) +$(LI $(BUGZILLA 17034): DMD 32 bit PIC wrong code) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 768): A switch to print predefined version identifiers) +$(LI $(BUGZILLA 13474): Discard excess precision for float and double $(LPAREN)x87$(RPAREN)) +$(LI $(BUGZILLA 16449): add support for RDTSCP in iasm) +$(LI $(BUGZILLA 16558): [Mir] Generic unaligned load/store like $(LPAREN)like LDC loadUnaligned and storeUnaligned$(RPAREN)) +$(LI $(BUGZILLA 16560): [Mir] Prefetch intrinsics like in LDC) +$(LI $(BUGZILLA 16703): Support indexing of SIMD vector types) +$(LI $(BUGZILLA 16798): Extend -Ipath switch to -Imodule=path so path heirarchy doesn't have to match package heirarchy) +$(LI $(BUGZILLA 16958): replace -mavx switch with -mcpu=id) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 16609): std.experimental.ndslice.slice issues warnings when building Phobos) +$(LI $(BUGZILLA 16661): [REG2.072] std/format.d$(LPAREN)1070$(RPAREN): Incorrect format specifier: .2f for wstring and dstring) +$(LI $(BUGZILLA 16663): [REG 2.072] std.unit.toUpper rejects an alias this to a string) +$(LI $(BUGZILLA 16667): [REG] dub test fails on std.conv after upgrade to dmd 2.072.0) +$(LI $(BUGZILLA 16682): [REG 2.072] "privatization" of symbols in std.stdio breaks DFMT) +$(LI $(BUGZILLA 17066): [REG2.073a] std.regex captures got immutable) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 6716): Linking a C program with D library causes DEH errors) +$(LI $(BUGZILLA 8087): Improve clarity of std.algorithm documentation) +$(LI $(BUGZILLA 9378): std.internal.digest.sha_SSE3 breaks if compiled with PIC) +$(LI $(BUGZILLA 9391): Constant std.regex.regex) +$(LI $(BUGZILLA 13314): BinaryHeap assumes Store has dup property) +$(LI $(BUGZILLA 16048): std.getopt: duplicated options are not detected) +$(LI $(BUGZILLA 16135): missing std.format import in std.algorithm.comparison) +$(LI $(BUGZILLA 16255): std.algorithm.iteration.each on opApply doesn't support ref) +$(LI $(BUGZILLA 16352): dead-lock in std.allocator.free_list unittest) +$(LI $(BUGZILLA 16419): issue with ndslice.slice toHash) +$(LI $(BUGZILLA 16478): Don't allow to!T$(LPAREN)$(RPAREN) in constraint) +$(LI $(BUGZILLA 16588): uniq's BidirectionalRange behavior is inconsistent with its InputRange behavior) +$(LI $(BUGZILLA 16611): std.traits.fullyQualifiedName fails with error 'Unrecognized type const$(LPAREN)void$(RPAREN)') +$(LI $(BUGZILLA 16624): std.path.setExtension ddoc comment is strangely formated) +$(LI $(BUGZILLA 16634): std.math exposes yl2x and yl2xp1 publicly) +$(LI $(BUGZILLA 16653): ParameterDefaultValueTuple fails to compile when function has lazy param) +$(LI $(BUGZILLA 16724): RandomCover.popFront is a no-op for the first call) +$(LI $(BUGZILLA 16758): Variant.opIndex result not modified after opAssign) +$(LI $(BUGZILLA 16794): dmd not working on Ubuntu 16.10 because of default PIE linking) +$(LI $(BUGZILLA 16955): std.process.spawnProcessImpl can crash due to alloca) +$(LI $(BUGZILLA 16959): bringToFront fails on char arrays) +$(LI $(BUGZILLA 16970): Fix deprecations and warnings when compiling Phobos) +$(LI $(BUGZILLA 16996): std.algorithm.remove with SwapStrategy.unstable removes more entries) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 4125): std.numeric.gcd can use a binary GCD) +$(LI $(BUGZILLA 16249): std.signals: disconnect$(LPAREN)$(RPAREN) is unsafe during emit$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 16571): Unittests should not list /tmp/ recursively) +$(LI $(BUGZILLA 16628): Special case std.algorithm.equal for known empty or infinite ranges) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 16974): [REG2.068] Equal associative arrays with associative array keys are considered unequal) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 16651): atomicOp!"-="$(LPAREN)ulong, uint$(RPAREN) = wrong result/codegen) +$(LI $(BUGZILLA 16654): hashOf returns different hashes for the same string value) +$(LI $(BUGZILLA 16764): `hashOf` is misleading, error-prone, and useless) +) +$(BUGSTITLE Druntime enhancements, + +$(LI $(BUGZILLA 16797): Zero clock resolution lead to division by zero) +) +$(BUGSTITLE dlang.org bugs, + +$(LI $(BUGZILLA 16592): Building dlang.org does not work without a preexisting dmd installation) +$(LI $(BUGZILLA 16948): broken links in std.stdio due to inccorrect use of WEB macro) +) +$(BUGSTITLE dlang.org enhancements, + +$(LI $(BUGZILLA 8799): Give example of Tuple mapped to a function) +$(LI $(BUGZILLA 16147): Provide shiny 404 error pages) +) +$(BUGSTITLE Tools regressions, + +$(LI $(BUGZILLA 14296): RDMD fails at building a lib when the source is in a subdir) +$(LI $(BUGZILLA 16962): rdmd --build-only --force -c main.d fails: ./main: No such file or directory) +$(LI $(BUGZILLA 16978): [REG2.072.0] pragma$(LPAREN)lib$(RPAREN) is broken with rdmd) +) +$(BUGSTITLE Tools bugs, + +$(LI $(BUGZILLA 16966): rdmd: AssertError@rdmd.d$(LPAREN)489$(RPAREN): should have been created by compileRootAndGetDeps) +) +$(BUGSTITLE Tools enhancements, + +$(LI $(BUGZILLA 16593): Building "tools" produces deprecation warnings) +) +) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.073.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.073.1.dd b/changelog/2.073.1.dd new file mode 100644 index 0000000000..1bdaf31923 --- /dev/null +++ b/changelog/2.073.1.dd @@ -0,0 +1,35 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 16, 2017, =================================================, + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 17123): [REG 2.073] Issues with return @safe inference) +$(LI $(BUGZILLA 17143): [REG2.072.0] Declaration is already defined on global enum = tuple$(LPAREN)...$(RPAREN).expand declaration) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 17168): Shift left operator causes segfault when compiling with -O flag) +$(LI $(BUGZILLA 17169): New default ddoc theme merges all paragraphs except the first) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 17161): [REG 2.072.2] Massive Regex Slowdown) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 17176): https://dlang.org/phobos/std_stdio.html#.File.tmpfile broken link) +) +) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.073.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.073.2.dd b/changelog/2.073.2.dd new file mode 100644 index 0000000000..56f3a19a31 --- /dev/null +++ b/changelog/2.073.2.dd @@ -0,0 +1,33 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 09, 2017, =================================================, + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 17215): [Reg 2.073] ICE$(LPAREN)cgcod.c:findreg$(RPAREN) with SIMD and -O -inline) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 17237): Wrong alignment of 256-bit and 512-bit vectors) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 17212): std.regex doesn't ignore whitespace after character classes, even when compiling with "x") +) +$(BUGSTITLE Tools bugs, + +$(LI $(BUGZILLA 17198): rdmd does not recompile when --extra-file is added) +) +) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.073.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.074.0.dd b/changelog/2.074.0.dd new file mode 100644 index 0000000000..dd5124d90e --- /dev/null +++ b/changelog/2.074.0.dd @@ -0,0 +1,420 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 10, 2017, =================================================, + +$(BUGSTITLE Runtime changes, + +$(LI $(RELATIVE_LINK2 disable-TypeInfo.init,`TypeInfo.init` has been `@disable`d.)) + +) + +$(BUGSTITLE Library changes, + +$(LI $(RELATIVE_LINK2 std-range-bitwise,Added `std.range.bitwise` to create a bitwise adapter over an integral type range, consuming the range elements bit by bit.)) +$(LI $(RELATIVE_LINK2 std-variant-genericfunc,Allow a generic function for std.variant.visit.)) +$(LI $(RELATIVE_LINK2 std-utf-decodeBack,Added `std.utf.decodeBack` which decodes the last UTF code point of given character range.)) +$(LI $(RELATIVE_LINK2 std-algorithm-searching-extremum,Performance improvements for `std.algorithm.searching.{min,max}Element`)) +$(LI $(RELATIVE_LINK2 std-format-formattedWrite,`std.format.formattedWrite` now accepts a compile-time checked format string)) +$(LI $(RELATIVE_LINK2 std-experimental-checkedint,New: Checked, a lightweight and highly configurable checked integral)) +$(LI $(RELATIVE_LINK2 std-traits-hasStaticMember,Added `std.traits.hasStaticMember` to check whether a symbol is a static member of a type.)) +$(LI $(RELATIVE_LINK2 std-expertimental-ndslice-removed,`std.experimental.ndslice` has been removed)) +$(LI $(RELATIVE_LINK2 std-format-formattedRead,`std.format.formattedRead` now accepts `ref` parameters as input arguments.)) +$(LI $(RELATIVE_LINK2 std-stdio-readf-only-pointers,`std.stdio.readf` now accepts `ref` parameters as input arguments.)) +$(LI $(RELATIVE_LINK2 std-random-MersenneTwisterEngine,`MersenneTwisterEngine` has been updated so that its template signature matches the C++11 standard.)) + +) + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BUGSTITLE Runtime changes, + +$(LI $(LNAME2 disable-TypeInfo.init,`TypeInfo.init` has been `@disable`d.) +$(P +$(REF1 TypeInfo.init, object) has been `@disable`d. Use +$(REF1 TypeInfo.initializer, object) instead. +) + +$(P +`TypeInfo.init` is a legacy alias of the method that is now called +$(REF1 TypeInfo.initializer, object). The name change is necessary because +the name "init" clashes with the type property of the same name +($(GLINK2 property, init)). +) + +$(P +The legacy alias has been deprecated since 2.072.0. It's going to be removed in +2.075.0. +) +) + + +) + +$(BUGSTITLE Library changes, + +$(LI $(LNAME2 std-range-bitwise,Added `std.range.bitwise` to create a bitwise adapter over an integral type range, consuming the range elements bit by bit.) +$(P +`std.range.bitwise` creates a bit by bit adapter over an integral type range: +) +------- +import std.range : bitwise; +ubyte[] arr = [3, 9]; +auto r = arr.bitwise; + +r[2] = 1; +assert(arr[0] == 7); +------- +) + +$(LI $(LNAME2 std-variant-genericfunc,Allow a generic function for std.variant.visit.) +$(P +If a lambda with a single generic parameter is provided as a handler +to std.variant.visit, it is invoked for any type contained in the +Algebraic which does not have a handler for that type. +) + +$(P +This allows something like: +) + +------- +// Assume Circle, Square, and Triangle all define center() +Algebraic!(Circle, Square, Triangle) someShape; +auto center = someShape.visit!(x => x.center); +------- + +$(P +This may be combined with explicitly typed handlers and a single +fallback handler for an empty variant: +) + +------- +Algebraic!(int, float, string) something; +something.visit!((string s) => s.length, // called for string + x => x, // called for int/float + () => 0); // called if empty +------- +) + +$(LI $(LNAME2 std-utf-decodeBack,Added `std.utf.decodeBack` which decodes the last UTF code point of given character range.) +------- + import std.utf : decodeBack; + + string text = "サイト"; + + assert(decodeBack(text) == 'ト'); + assert(decodeBack(text) == 'イ'); + assert(decodeBack(text) == 'サ'); + assert(text.empty); +------- +) + +$(LI $(LNAME2 std-algorithm-searching-extremum,Performance improvements for `std.algorithm.searching.{min,max}Element`) +$(P +$(REF minElement, std, algorithm, searching) and $(REF maxElement, std, algorithm, searching) +are now considerably faster (almost 2x in microbenchmarks) +as a special path for the identity case is provided. This allows the compiler +to make use of SSE instructions. +) + +$(P +The exact improvements are: +) + +$(P +$(CONSOLE +% dmd -release -O test.d && ./test +extremum.before = 54 secs, 12 ms, 347 μs, and 9 hnsecs +extremum.after = 29 secs, 521 ms, 896 μs, and 5 hnsecs +) +) + +$(P +$(CONSOLE +% ldc -release -O3 test.d && ./test +extremum.before = 13 secs, 186 ms, 176 μs, and 4 hnsecs +extremum.after = 2 secs, 241 ms, 454 μs, and 9 hnsecs +) +) + +$(P +$(LINK2 https://gist.github.com/wilzbach/9f757fa76200956aadb97059d614df34, See the benchmark code). +) +) + +$(LI $(LNAME2 std-format-formattedWrite,`std.format.formattedWrite` now accepts a compile-time checked format string) +$(P +$(REF formattedWrite, std, format) and related functions now have overloads to +take the format string as a compile-time argument. This allows the format +specifiers to be matched against the argument types passed. Any mismatch or +orphaned specifiers/arguments will cause a compile-time error: +) + +------- +import std.format, std.stdio; + +auto s = format!"%s is %s"("Pi", 3.14); +assert(s == "Pi is 3.14"); +writefln!"%c is %s"('e', 1.61); + +static assert(!__traits(compiles, {s = format!"%l"();})); // missing arg +static assert(!__traits(compiles, {s = format!""(404);})); // surplus arg +static assert(!__traits(compiles, {s = format!"%d"(4.03);})); // incompatible arg +------- +) + +$(LI $(LNAME2 std-experimental-checkedint,New: Checked, a lightweight and highly configurable checked integral) +$(P +$(REF Checked, std, experimental, checkedint) is a wrapper around any integral +type that inserts checks against common sources of bugs: overflow in operators, +mixed-sign comparisons, and casts that lose information. +) + +$(P +The example below illustrates the basic use of the facility: +) + +------- +void main() +{ + import std.experimental.checkedint, std.stdio; + writeln((checked(5) + 7).get); // 12 + writeln((checked(10) * 1000 * 1000 * 1000).get); // Overflow +} +------- + +$(P +By default, all checks are enabled and the program is aborted if any check +fails. An implementation based on hooks discoverable by using Design by +Introspection allows unbounded customizations of both the checks to do, and the +enforcement policy. +) +) + +$(LI $(LNAME2 std-traits-hasStaticMember,Added `std.traits.hasStaticMember` to check whether a symbol is a static member of a type.) +------- +import std.traits : hasStaticMember; + +struct S +{ + static int staticVar; + int nonstaticVar; +} + +assert( hasStaticMember!(S, "staticVar")); +assert(!hasStaticMember!(S, "nonstaticVar")); +------- +) + +$(LI $(LNAME2 std-expertimental-ndslice-removed,`std.experimental.ndslice` has been removed) +$(P +The synchronization between Phobos and Mir turned out to be a high amount of work with little gain. +Users of `std.experimental.ndslice` are advised to switch to the upstream +$(LINK2 https://github.com/libmir/mir-algorithm, mir-algorithm package). +) + +$(P +It comes with a lot of new features +$(UL + $(LI $(LINK2 http://docs.algorithm.dlang.io/latest/mir_ndslice_topology.html, `mir.ndslice.topology`) - + Multidimensional `std.range` analog. Includes `bitwise`, `bitpack`, `zip`, `unzip`, `map`, `indexed` and many other features.) + $(LI $(LINK2 http://docs.algorithm.dlang.io/latest/mir_ndslice_concatenation.html, `mir.ndslice.concatenation`) - + Concatenation and padding) + $(LI $(LINK2 http://docs.algorithm.dlang.io/latest/mir_ndslice_algorithm.html, `mir.ndslice.algorithm`) - + Slim multidimensional `std.algorithm` analog) + $(LI $(LINK2 http://docs.algorithm.dlang.io/latest/mir_ndslice_sorting.html, `mir.ndslice.sorting`) - + Multidimensional sorting utilities) +) +) + +$(P +`ndslice` design was changed. New ndslices can be created on top of random access iterators including pointers. There are three kinds of ndslice: +) + +$(P +$(UL + $(LI `Contiguous` - Contiguous in memory representation. It does not store strides and can be always flattened to 1 dimensional ndslice on top of the same iterator type. ) + $(LI `Canonical` - BLAS like. Stride for row dimension assumed to be equal to 1.) + $(LI `Universal` - Numpy like. Each dimension has strides. All dimensions can be exchanged without reallocation. The old ndslice ABI corresponds to to the `Universal` ndslice.) +) +) +) + +$(LI $(LNAME2 std-format-formattedRead,`std.format.formattedRead` now accepts `ref` parameters as input arguments.) +$(P +When $(REF formattedRead, std, format) is used with `ref` parameters it is `@safe`. +For compatibility it's still possible to use $(REF formattedRead, std, format) +with pointers: +) + +------- +import std.format; +void main() { + string text = "1 2 3"; + int a, b, c; + formattedRead(text, "%d %d %d", a, b, c); + // pointers can still be used + formattedRead(text, "%d %d %d", &a, &b, &c); + // and even combined: + formattedRead(text, "%d %d %d", a, &b, c); +} +------- +) + +$(LI $(LNAME2 std-stdio-readf-only-pointers,`std.stdio.readf` now accepts `ref` parameters as input arguments.) +------- +import std.stdio : readf; +void main() { + // assume every line from stdin is similar to "1 2 3"; + int a, b, c; + readf(" %d %d %d", a, b, c); + // pointers can still be used + readf(" %d %d %d, &a, &b, &c); + // and even combined: + readf(" %d %d %d, a, &b, c); +} +------- +) + +$(LI $(LNAME2 std-random-MersenneTwisterEngine,`MersenneTwisterEngine` has been updated so that its template signature matches the C++11 standard.) +$(P +`MersenneTwisterEngine` has been updated so that its template signature +matches the C++11 standard (adding two new template parameters, an extra +tempering parameter `d` and the initialization multiplier `f`). +) + +$(P +Handling of the word size `w` has been fixed so that the generator will +now properly handle cases where it is less than the number of bits in +the chosen `UIntType`. This has been validated against the behaviour +of a widely-used implementation of the C++11 standard. +) + +$(P +For anyone using the standard template instantiation `Mt19937` this will +have no noticeable effect. However, these will be breaking changes for +anyone using the `MersenneTwisterEngine` template directly. +) + +$(P +The internal implementation has been reworked to use Ilya Yaroshenko's +highly optimized algorithm from $(LINK2 https://github.com/libmir/mir-random, mir-random). This should have a very +noticeable positive effect for anyone who cares about generating a lot +of random numbers quickly. +) + +$(P +A new `Mt19937_64` template instantiation has been added, corresponding +to the standard 64-bit implementation of the algorithm (MT19937-64). +This fixes $(LINK https://issues.dlang.org/show_bug.cgi?id=10900). +) +) + + +) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 15947): [REG 2.069.0?] simple multithreaded program + "-profile=gc" = crash) +$(LI $(BUGZILLA 16680): dmd doesn't use druntime optimized versions of subtraction array operations) +$(LI $(BUGZILLA 17117): [REG2.073] erroneous "escaping reference to local variable") +$(LI $(BUGZILLA 17123): [REG 2.073] Issues with return @safe inference) +$(LI $(BUGZILLA 17291): [REG 2.074-b1] windows: invalid relocation entries) +$(LI $(BUGZILLA 17292): [REG 2.069] Windows: dmd causes "out of memory" when using less than 2GB of memory) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 6400): opDispatch with WithStatement) +$(LI $(BUGZILLA 15428): __traits$(LPAREN)compiles, super$(LPAREN)$(RPAREN)$(RPAREN) cause error "multiple constructor calls" later) +$(LI $(BUGZILLA 15616): missing candidate in error message) +$(LI $(BUGZILLA 15676): The compiler does not preserve @disable while generating .di files) +$(LI $(BUGZILLA 16083): AliasSeq loses type of enums that have the same value) +$(LI $(BUGZILLA 16245): the message emitted when a const function mutates members is misleading) +$(LI $(BUGZILLA 16346): Enum used as a constructor evaluates to the underlying type, not to the enum type.) +$(LI $(BUGZILLA 16355): __xpostblit incorrectly generated for a struct with a zero-length static array) +$(LI $(BUGZILLA 16382): Passing &this as a CT parameter seg faults dmd) +$(LI $(BUGZILLA 16483): ICE in expression.d from typeof) +$(LI $(BUGZILLA 17049): [scope] member methods not escape checked like free functions) +$(LI $(BUGZILLA 17057): trait "allMembers" incorrectly includes imports) +$(LI $(BUGZILLA 17076): [scope] compiling identity function template with -dip1000 causes error) +$(LI $(BUGZILLA 17086): DMD segfault with multiple template matches and invalid code) +$(LI $(BUGZILLA 17255): Warning when compiling ddmd.backend/ptrntab.c about type-punning) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 14859): static declared array with more than 16MB size should be allowed in struct and class declaration) +$(LI $(BUGZILLA 16513): Speed up TemplateInstance.findExistingInstance hash) +$(LI $(BUGZILLA 16697): Extend IsExpression to accept __vector as a TypeSpecialization) +$(LI $(BUGZILLA 17111): DMD accepts switch statement with non-const case variables) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 17282): [REG 2.074.0-b1] std.conv.parse throws with -debug) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 8260): * used three or more times on an array inside std.format.formattedRead and not guarded by template constraint) +$(LI $(BUGZILLA 8471): std.stdio.readf should be @trusted) +$(LI $(BUGZILLA 9615): std.conv.parse!$(LPAREN)T[]$(RPAREN) fails on trailing comma) +$(LI $(BUGZILLA 11703): Typedef properties should not be of the original type) +$(LI $(BUGZILLA 13619): std.container.array capacity not updated when length increases) +$(LI $(BUGZILLA 16342): std.algorithm.fill can't fill a char[]?) +$(LI $(BUGZILLA 16442): FrontTransversal fails with empty ranges) +$(LI $(BUGZILLA 16564): KRRegion.empty sometimes returns Ternary.no) +$(LI $(BUGZILLA 16642): byCodeUnit doesn't work AutodecodableStrings unless they're actually strings or alias a variable that's a string) +$(LI $(BUGZILLA 16824): std.experimental.allocator.dispose leaks memory for arrays of more than 1 dimension) +$(LI $(BUGZILLA 17075): ctRegex BacktrackingMatcher.prevStack: free$(LPAREN)$(RPAREN): invalid pointer) +$(LI $(BUGZILLA 17102): std.write.file generates a segmentation fault when the file name is a string with a default value) +$(LI $(BUGZILLA 17116): std.typecons.ReplaceType is not able to process const delegate) +$(LI $(BUGZILLA 17153): std.container.array.Array cannot be used in @nogc code) +$(LI $(BUGZILLA 17154): std.conv.toChars doesn't support $ in slicing) +$(LI $(BUGZILLA 17157): ctRegex.matchAll doesn't set last item in Captures) +$(LI $(BUGZILLA 17177): AutoImplement fails on function overload sets with "cannot infer type from overloaded function symbol") +$(LI $(BUGZILLA 17217): std.net.isemail.isEmail doesn't work with non char arrays) +$(LI $(BUGZILLA 17229): File.byChunk $(LPAREN)ubyte$(RPAREN) w/ stdout.lockingTextWriter corrupts utf-8 data $(LPAREN)and is very slow$(RPAREN)) +$(LI $(BUGZILLA 17243): std.math.{FloatingPointControl,ieeeFlags} don't work on x86_64) +$(LI $(BUGZILLA 17247): std.bitmanip.read should not assume sliceable range is assign-copyable to ubyte[].) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 10900): Mersenne Twister should have a 64-bit $(LPAREN)ulong$(RPAREN) version) +$(LI $(BUGZILLA 13017): opEquals for null std.typecons.Nullable) +$(LI $(BUGZILLA 16281): std.format.formattedRead should use ref instead of requiring pointers) +$(LI $(BUGZILLA 16323): std.utf.decodeBack) +$(LI $(BUGZILLA 16736): Retrieving cUrl time values is quite cumbersome) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 17130): [Reg 2.074] ambiguous implicit super call when inheriting core.sync.mutex.Mutex) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 16470): Segfault with negative array length) +) +$(BUGSTITLE Druntime enhancements, + +$(LI $(BUGZILLA 8411): core.time: No easy way to check if Duration is empty) +) +$(BUGSTITLE dlang.org bugs, + +$(LI $(BUGZILLA 17115): [404 Not Found] std.concurrencybase) +) +$(BUGSTITLE dlang.org enhancements, + +$(LI $(BUGZILLA 16991): Make writeln documentation palatable) +) +$(BUGSTITLE Tools bugs, + +$(LI $(BUGZILLA 17139): [BLOCKING] dscanner needs to handle 'scope' function attributes) +) +) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.074.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.074.1.dd b/changelog/2.074.1.dd new file mode 100644 index 0000000000..71878d3da7 --- /dev/null +++ b/changelog/2.074.1.dd @@ -0,0 +1,30 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION May 30, 2017, =================================================, + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 17407): [REG] __traits$(LPAREN)compiles$(RPAREN) triggers assertion failure) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 17289): With Xcode 8.3 linker, warnings of "pointer not aligned") +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 17330): [REG 2.072] BigInt's constructor used to be pure) +$(LI $(BUGZILLA 17340): [REG 2.074.0] isNumeric!bool should not be true) +) +) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.074.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.075.0.dd b/changelog/2.075.0.dd new file mode 100644 index 0000000000..8578859eec --- /dev/null +++ b/changelog/2.075.0.dd @@ -0,0 +1,522 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 19, 2017, =================================================, + +$(BUGSTITLE Compiler changes, + +$(LI $(RELATIVE_LINK2 changelog17425,add __traits(getParameterStorageClasses, f, i))) +$(LI $(RELATIVE_LINK2 b6227,Comparison of values belonging to different enums is deprecated.)) +$(LI $(RELATIVE_LINK2 removeArrayProps,The deprecated built-in array properties `.sort` and `.reverse` were removed.)) +$(LI $(RELATIVE_LINK2 disallowSemiEmpty,Deprecate empty statements made by semicolon)) +$(LI $(RELATIVE_LINK2 changelog17421,add __traits(getFunctionVariadicStyle, f))) + +) + +$(BUGSTITLE Runtime changes, + +$(LI $(RELATIVE_LINK2 scandataseg-precise,Windows: the DATA and TLS segment can now be configured to be scanned precisely.)) +$(LI $(RELATIVE_LINK2 fiber-configure,Make fiber stack protection-page size configurable)) +$(LI $(RELATIVE_LINK2 fiber,Add Fiber's stack-protection page for Posix.)) +$(LI $(RELATIVE_LINK2 remove-TypeInfo.init,`TypeInfo.init` now refers to type property.)) + +) + +$(BUGSTITLE Library changes, + +$(LI $(RELATIVE_LINK2 std-range-has-length,`hasLength` now enforces that `length` has type `size_t`)) +$(LI $(RELATIVE_LINK2 split-std-datetime,std.datetime has been split into a package.)) +$(LI $(RELATIVE_LINK2 pattern-deprecate,Several functions in `std.string` have been deprecated)) +$(LI $(RELATIVE_LINK2 std-digest-digest-secureCompare,Added a constant time comparison function for cryptographic hashes)) +$(LI $(RELATIVE_LINK2 std-digest-crc64,Added support for 64 bit CRC)) + +) + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BUGSTITLE Compiler changes, + +$(LI $(LNAME2 changelog17425,add __traits(getParameterStorageClasses, f, i)) +$(P +$(LINK2 https://issues.dlang.org/show_bug.cgi?id=17425, Bugzilla 17425) +) + +--- +ref int foo(return ref const int* p, scope int* a, out int b, lazy int c); + +pragma(msg, __traits(getParameterStorageClasses, foo, 0)); + +static assert(__traits(getParameterStorageClasses, foo, 0)[0] == "return"); +static assert(__traits(getParameterStorageClasses, foo, 0)[1] == "ref"); + +pragma(msg, __traits(getParameterStorageClasses, foo, 1)); +static assert(__traits(getParameterStorageClasses, foo, 1)[0] == "scope"); +static assert(__traits(getParameterStorageClasses, foo, 2)[0] == "out"); +static assert(__traits(getParameterStorageClasses, typeof(&foo), 3)[0] == "lazy"); +--- +) + +$(LI $(LNAME2 b6227,Comparison of values belonging to different enums is deprecated.) +$(P +This change does not affect anonymous enumerations. +) + +--- +enum Status +{ + good, + bad +} +enum OtherStatus +{ + ok + no, +} + +// Deprecated - Even though both good and ok evaluate to 0 they belong to +// different enumeration types +static assert(Status.good == OtherStatus.ok); +--- +) + +$(LI $(LNAME2 removeArrayProps,The deprecated built-in array properties `.sort` and `.reverse` were removed.) +$(P +Usage of those built-in array properties was deprecated since 2.072.0 and they have now been removed. +Use $(REF sort, std, algorithm, sorting) and $(REF reverse, std, algorithm, mutation) instead. +) +) + +$(LI $(LNAME2 disallowSemiEmpty,Deprecate empty statements made by semicolon) +$(P +Creating empty statements using semicolons, for which +was previously issued a warning is now causing a deprecation +hint. +) +) + +$(LI $(LNAME2 changelog17421,add __traits(getFunctionVariadicStyle, f)) +$(P +$(LINK2 https://issues.dlang.org/show_bug.cgi?id=17421, Bugzilla 17421) +) + +--- +import core.stdc.stdarg; + +void novar() {} +extern(C) void cstyle(int, ...) {} +extern(C++) void cppstyle(int, ...) {} +void dstyle(...) {} +void typesafe(int[]...) {} + +static assert(__traits(getFunctionVariadicStyle, novar) == "none"); +static assert(__traits(getFunctionVariadicStyle, cstyle) == "stdarg"); +static assert(__traits(getFunctionVariadicStyle, cppstyle) == "stdarg"); +static assert(__traits(getFunctionVariadicStyle, dstyle) == "argptr"); +static assert(__traits(getFunctionVariadicStyle, typesafe) == "typesafe"); + +static assert(__traits(getFunctionVariadicStyle, (int[] a...) {}) == "typesafe"); +static assert(__traits(getFunctionVariadicStyle, typeof(cstyle)) == "stdarg"); +--- +) + + +) + +$(BUGSTITLE Runtime changes, + +$(LI $(LNAME2 scandataseg-precise,Windows: the DATA and TLS segment can now be configured to be scanned precisely.) +$(P +A new runtime option "scanDataSeg" has been added to enable precise scanning of the +DATA and the TLS segments. This uses information generated by the compiler to +identify possible pointers inside these segments. Possible option values are +"conservative" (default) and "precise". +) + +$(P +As usual, this option can be set by the environment, the command line or by +embedding the option into the executable similar to the +$(LINK2 $(ROOT_DIR)spec/garbage.html#gc_config, GC options). +) + +$(P +For example add this code to your main module to enable precise scanning: +) +--------- +extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise" ]; +--------- +) + +$(LI $(LNAME2 fiber-configure,Make fiber stack protection-page size configurable) +$(P +It is now possible to change the guard page size by using +the new Fiber's constructor argument - guard_page_size. It defaults to +`PAGE_SIZE` (the same it used to be on Windows), and specifying 0 will +turn this feature off. +) +) + +$(LI $(LNAME2 fiber,Add Fiber's stack-protection page for Posix.) +$(P +The feature already existing for Windows' fiber implementation is now added to +the systems using mmap to allocate fibers' stacks: After (or before) the last +page used for the Fiber's stack, the page is allocate which is protected for +any kind of access. This will cause system to trap immediately on the fiber's +stack overflow. +) +) + +$(LI $(LNAME2 remove-TypeInfo.init,`TypeInfo.init` now refers to type property.) +$(P +`TypeInfo.init` used to refer to the method that is now called +$(REF1 TypeInfo.initializer, object). The name change was necessary because +the name "init" would clash with the type property of the same name +($(GLINK2 property, init)). `TypeInfo.init` now refers to the type property. +) +) + + +) + +$(BUGSTITLE Library changes, + +$(LI $(LNAME2 std-range-has-length,`hasLength` now enforces that `length` has type `size_t`) +$(P +Historically `hasLength!R` yielded `true` for types whereby +`R.length` returns other types convertible to `ulong`, such as `int`, `ushort`, +`const(size_t)`, user-defined types using `alias this`, or notably `ulong` on +32-bit systems. This behavior has been deprecated. After December 2017, +$(REF hasLength, std, range, primitives) will yield `true` only if `R.length` +yields the exact type `size_t`. +) +) + +$(LI $(LNAME2 split-std-datetime,std.datetime has been split into a package.) +$(P +std.datetime is now a package containing the following modules: +) + +$(P +$(UL + $(LI $(MREF std,datetime,date)) + $(LI $(MREF std,datetime,interval)) + $(LI $(MREF std,datetime,stopwatch)) + $(LI $(MREF std,datetime,systime)) + $(LI $(MREF std,datetime,timezone)) +) +) + +$(P +The $(MREF std,datetime) package publicly imports all of those modules. So, it +should be the case that no existing code will break, as everything in +std.datetime will still be imported by importing std.datetime. New code can +choose to import the modules individually or to import the entire package. +) + +$(P +$(MREF std,datetime,date) contains Date, TimeOfDay, DateTime, and the related +free functions. It also contains DateTimeException. +) + +$(P +$(MREF std,datetime,interval) contains the *Interval and *IntervalRange types +as well as the related free functions. +) + +$(P +$(MREF std,datetime,systime) contains SysTime and the related free functions. +) + +$(P +$(MREF std,datetime,timezone) contains the time zone types. +) + +$(P +The $(MREF std,datetime) package contains StopWatch and the benchmarking functions +(so, they can only be imported via $(D std.datetime) and not via a submodule). As +those functions use $(REF TickDuration,core,time) (which is being replaced by +$(REF MonoTime,core,time), they are slated for deprecation). +) + +$(P +$(MREF std,datetime,stopwatch) has been added. It contains versions of +StopWatch and benchmark which have almost the same API as the existing symbols, +but they use $(REF MonoTime,core,time) and $(REF Duration,core,time) instead of +$(REF TickDuration,core,time). In the next major release, the old functions in +std.datetime.package will be deprecated, so code which uses the old +benchmarking functions should be updated to use std.datetime.stopwatch. +) + +$(P +However, note that in order to avoid irreconcilable symbol conflicts between +the new and old versions, std.datetime.stopwatch will not be publicly imported +by std.datetime.package until the old symbols have been removed. So, for the +time being, code using $(REF StopWatch,std,datetime,stopwatch) or +$(REF benchmark,std,datetime,stopwatch) will need to import +std.datetime.stopwatch directly. Code which imports both std.datetime and +std.datetime.stopwatch will need to either use selective imports or fully +qualified symbols to reconcile the symbol conflicts, but no code will be +affected by the changes until it's updated to import std.datetime.stopwatch, +and when the old symbols are finally removed, the selective imports and fully +qualified paths to the new symbols will continue to work and won't break +(though at that point, simply importing std.datetime will work, since +std.datetime.package will have been updated to publicly import +std.datetime.stopwatch). Code that simply imporst std.datetime.stopwatch without +importing std.datetime will not have to worry about symbol conflicts. +) +) + +$(LI $(LNAME2 pattern-deprecate,Several functions in `std.string` have been deprecated) +$(P +The functions $(REF inPattern, std, string), $(REF countchars, std, string), +$(REF removechars, std, string), $(REF squeeze, std, string), and +$(REF munch, std, string), have all been deprecated. These functions are +obsolete, as their functionality is better covered by the functions in +$(MREF std, regex) and $(MREF std, algorithm). They will be removed from +$(MREF std, string) on May 2018. +) + +$(P +If you still need to use these, please see $(LINK2 https://github.com/dlang/undeaD, undeaD). +) + +$(P +The following are examples of the deprecated functions, and their modern replacements. +) + +$(P +Use $(REF find, std, algorithm, searching) to replace $(REF munch, std, string): +) +------- +import std.algorithm; +import std.ascii; +import std.string; +import std.utf; + +string s = "\tabc"; + +// old +s.munch(whitespace); + +// new +s = s.find!(a => !isWhite(a)); +------- + +$(P +Use $(REF matchFirst, std, regex) to replace $(REF inPattern, std, string): +) +------- +import std.string; +import std.regex; + +// old +if (inPattern('x', "a-z")) { ... } + +// new +if ("x".matchFirst(regex("[a-z]"))) { ... } +------- + +$(P +Use $(REF replaceAll, std, regex) to replace $(REF removechars, std, string): +) +------- +import std.string; +import std.regex; + +// old +"abc".removechars("a-z"); + +// new +"abc".replaceAll(regex("[a-z]"), ""); +------- + +$(P +Use $(REF uniq, std, algorithm, iteration) to replace $(REF squeeze, std, string): +) +------- +import std.algorithm; +import std.string; + +// old +"hello".squeeze; + +// new +"hello".uniq; +------- +) + +$(LI $(LNAME2 std-digest-digest-secureCompare,Added a constant time comparison function for cryptographic hashes) +$(P +Added a new function to $(REF secureEqual, std, digest, digest) that compares +two ranges that represent hashes in a secure manner. The comparison is done in +constant time regardless of the equality of the two ranges in order to protect +against timing attacks. For more information on the attack, please refer to +the docs on $(REF secureEqual, std, digest, digest). +) + +----- +import std.digest.digest : secureEqual, toHexString; +import std.digest.hmac : hmac; +import std.digest.sha : SHA1; +import std.string : representation; + +void main() +{ + // a typical HMAC data integrity verification + auto secret = "A7GZIP6TAQA6OHM7KZ42KB9303CEY0MOV5DD6NTV".representation; + auto data = "data".representation; + + string hex1 = data.hmac!SHA1(secret).toHexString; + string hex2 = data.hmac!SHA1(secret).toHexString; + + string hex3 = "data1".representation.hmac!SHA1(secret).toHexString; + + assert( secureEqual(hex1, hex2)); + assert(!secureEqual(hex1, hex3)); +} +----- +) + +$(LI $(LNAME2 std-digest-crc64,Added support for 64 bit CRC) +$(P +Support for both ISO and ECMA 64 bit CRC was added to $(MREF std, digest, crc). +) + +------- +import std.digest.crc; + +void main() +{ + ubyte[8] hash64ecma = crc64ECMAOf("abc"); + assert(crcHexString(hash64ecma) == "2CD8094A1A277627"); + + ubyte[8] hash64iso = crc64ISOOf("abc"); + assert(crcHexString(hash64iso) == "3776C42000000000"); +} +------- +) + + +) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 16408): [REG2.065] left-to-right order of evaluation of function arguments not consistently followed) +$(LI $(BUGZILLA 17275): [REG 2.072.0] AssertError@declaration.d$(LPAREN)2121$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 17293): "Using C++ Classes From D" example no longer works) +$(LI $(BUGZILLA 17338): [Reg 2.075] link failure unsupported symbol section 0xff01) +$(LI $(BUGZILLA 17352): [REG 2.075a] Internal error: ddmd/backend/elfobj.c 1739 on duplicate definition) +$(LI $(BUGZILLA 17356): [Reg 2.075] __simd_sto no longer executed) +$(LI $(BUGZILLA 17399): [REG2.071] core.checkedint.addu cannot inline function) +$(LI $(BUGZILLA 17451): ICE in ddmd/declaration.d$(LPAREN)2179$(RPAREN)) +$(LI $(BUGZILLA 17481): [REG 2.069.0] synchronized: Access Violation with dmd -O on win32) +$(LI $(BUGZILLA 17492): [REG 2.066] [ICE] AssertError@ddmd/dclass.d$(LPAREN)1007$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 17502): [REG2.064] Out contract in class method causes dmd segfault.) +$(LI $(BUGZILLA 17505): [REG2.075] @safe constructor requires the deconstructor to be safe as well) +$(LI $(BUGZILLA 17506): [REG2.075] @disable constructor requires members to be initialized) +$(LI $(BUGZILLA 17545): [REG2.072] __traits$(LPAREN)getAttributes, name$(RPAREN) evaluates name to value prematurely) +$(LI $(BUGZILLA 17548): [REG2.072.0] Forward reference error with scope function parameters) +$(LI $(BUGZILLA 17614): [REG2.075.0-b2] __VERSION__ has the wrong value) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 7016): local import does not create -deps dependency) +$(LI $(BUGZILLA 13331): naked asm functions are broken when compiling with -profile) +$(LI $(BUGZILLA 15896): private ignored when import bindings are used) +$(LI $(BUGZILLA 15945): sizeof on an invalid type seems to compile.) +$(LI $(BUGZILLA 16244): compiler ICE on complex `typeof$(LPAREN)$(RPAREN)` for method arg type) +$(LI $(BUGZILLA 16566): hasLength should enforce that length has type size_t) +$(LI $(BUGZILLA 17289): With Xcode 8.3 linker, warnings of "pointer not aligned") +$(LI $(BUGZILLA 17317): 2.074.0 release candidate does not have updated backend license) +$(LI $(BUGZILLA 17335): Function calls in conjunctions do not short circuit when evaluated during compilation) +$(LI $(BUGZILLA 17337): SIGILL for AVX vector initialization) +$(LI $(BUGZILLA 17339): ambiguous mangling with const alias argument) +$(LI $(BUGZILLA 17344): ICE with assignment of post inc-/decremented integral vector) +$(LI $(BUGZILLA 17349): Covariant overrides should be allowed) +$(LI $(BUGZILLA 17367): CodeView/MSCOFF: bad debug information for enumerators) +$(LI $(BUGZILLA 17391): SECURITY: XSS through DDOC comments) +$(LI $(BUGZILLA 17422): [scope] class reference not initialized as scope variable) +$(LI $(BUGZILLA 17432): [DIP1000] scope delegates change type, but not mangling) +$(LI $(BUGZILLA 17450): escaping delegate context pointer not detected for member functions) +$(LI $(BUGZILLA 17468): Internal assertion fails during CTFE) +$(LI $(BUGZILLA 17491): Compiles on invalid: *&s.init.var is not an lvalue) +$(LI $(BUGZILLA 17495): __traits$(LPAREN)getParameterStorageClasses$(RPAREN) doesn't work with tuples as parameters) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 6227): Comparison of different enums) +$(LI $(BUGZILLA 16197): Constructors/postblits and destructors don't match up for array initialisation) +$(LI $(BUGZILLA 16540): Attributes do not propagate correctly in lazy params) +$(LI $(BUGZILLA 16600): Wrong error message for ambiguous mutable/immutable constructor) +$(LI $(BUGZILLA 17396): Add colorized syntax highlighting to error messages emitted by dmd) +$(LI $(BUGZILLA 17419): add __traits$(LPAREN)getLinkage, s$(RPAREN) to the the linkage of symbol s) +$(LI $(BUGZILLA 17425): add __traits$(LPAREN)getParameterStorageClasses, f, i$(RPAREN)) +$(LI $(BUGZILLA 17429): [scope] each scope class references adds another delete call) +$(LI $(BUGZILLA 17457): Named Return Value Optimization $(LPAREN)NRVO$(RPAREN) not done with return of constructor call) +$(LI $(BUGZILLA 17494): Do not execute scope$(LPAREN)...$(RPAREN) if an Error exception has been thrown) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 17452): Undefined references in std.container.array) +$(LI $(BUGZILLA 17472): [Reg 2.075] typeof$(LPAREN)stdin$(RPAREN) is no longer a File) +$(LI $(BUGZILLA 17482): [REG 2.074] comile error: Comparing Nullable!Variant with basic type) +$(LI $(BUGZILLA 17511): [REG 2.075a] std.xml puts grand-children into items) +$(LI $(BUGZILLA 17555): [REG2.070.0] Control characters in JSON data are invalid and should cause an exception) +$(LI $(BUGZILLA 17650): [REG v2.075.0 b1-b4] std.getopt range violation) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 5904): std.json parseString doesn't handle chars outside the BMP) +$(LI $(BUGZILLA 15517): std.experimental.logger: using 'sharedLog' to change to file logging for default logger does not work) +$(LI $(BUGZILLA 15534): [std.experimental.logger.core] Documentation mismatch) +$(LI $(BUGZILLA 15720): iota$(LPAREN)long.max, long.min, step$(RPAREN) does not work properly) +$(LI $(BUGZILLA 15763): std.math.approxEqual is not symmetric) +$(LI $(BUGZILLA 16246): cannot call iota with 3 [u]bytes or 3 [u]shorts) +$(LI $(BUGZILLA 16256): std.experimental.logger cant log a dstring properly) +$(LI $(BUGZILLA 16326): filter is not lazy enough & has weird save behavior) +$(LI $(BUGZILLA 17251): Appender.put errors out with const input range elements) +$(LI $(BUGZILLA 17270): std.experimental.Final fails on pointers) +$(LI $(BUGZILLA 17283): std.experimental.typecons uses private module members) +$(LI $(BUGZILLA 17288): formattedWrite error when width/precision provided and no value to format) +$(LI $(BUGZILLA 17314): BinaryHeap crashes upon insertion if heapified with an array of length 1) +$(LI $(BUGZILLA 17328): std.experimental.logger: wrong hex formatting for zeros) +$(LI $(BUGZILLA 17519): RedBlackTree doesn't like const/immutable elements) +$(LI $(BUGZILLA 17553): std.json should not do UTF decoding when encoding JSON) +$(LI $(BUGZILLA 17556): std.json encodes non-BMP characters incorrectly with JSONOptions.escapeNonAsciiChars) +$(LI $(BUGZILLA 17564): std.experimental.allocator.theAllocator is null within shared static this) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 6621): Superimposition amount for std.range.chunks) +$(LI $(BUGZILLA 7102): std.numeric.gcd with BigInts too) +$(LI $(BUGZILLA 10001): string formatting with underscores) +$(LI $(BUGZILLA 16108): `to!string` fails on struct with disabled postblit) +$(LI $(BUGZILLA 16615): std.process is missing functionality for child processes) +$(LI $(BUGZILLA 17286): A function for comparing two digests securely) +$(LI $(BUGZILLA 17327): std.getopt: repeated options unrecognised) +$(LI $(BUGZILLA 17394): std.file.mkdirRecurse isn't @safe) +$(LI $(BUGZILLA 17557): std.json should not do UTF decoding when parsing) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 9275): [GC] removeRoot hits assert$(LPAREN)0$(RPAREN) instead of being a no-op $(LPAREN)as documented$(RPAREN)) +$(LI $(BUGZILLA 12233): Attempting to use TypeInfo.init results in a compiler error due to lack of 'this'.) +$(LI $(BUGZILLA 13186): core/sys/posix/sys/uio.d is not linked into the standard lib) +$(LI $(BUGZILLA 16856): D does not work on FreeBSD current $(LPAREN)what will eventually be 12$(RPAREN) due to libunwind) +) +$(BUGSTITLE dlang.org bugs, + +$(LI $(BUGZILLA 8107): Float literals are not specified as they are implemented) +$(LI $(BUGZILLA 17303): type error in the href url under the link Systems Programming) +$(LI $(BUGZILLA 17469): View source code) +$(LI $(BUGZILLA 17501): Runnable unittest problem with AST rewrite) +) +) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.075.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.075.1.dd b/changelog/2.075.1.dd new file mode 100644 index 0000000000..82cc3a6e93 --- /dev/null +++ b/changelog/2.075.1.dd @@ -0,0 +1,38 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Aug 11, 2017, =================================================, + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 17622): [REG2.075.0-b1] Wrong code with appender and -inline) +$(LI $(BUGZILLA 17676): [REG 2.075] bad inlining of functions with multiple return statements) +$(LI $(BUGZILLA 17677): [REG 2.073.0] ICE when adding ulong to cfloat) +$(LI $(BUGZILLA 17684): [REG 2.062] `static alias this` bug or incomplete implementation?) +$(LI $(BUGZILLA 17686): [REG2.075.0] Covariant return types doesn't work with override in some cases) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 17646): dmd segfaults on missing foreach body in import) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 17192): ParameterDefaults fails when parameter is called "i") +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 17667): `regex([r".", r"[\(\{[\]\}\)]"]);`) +$(LI $(BUGZILLA 17668): `regex(q"<[^]>")`) +) +) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.075.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.076.0.dd b/changelog/2.076.0.dd new file mode 100644 index 0000000000..53360883ce --- /dev/null +++ b/changelog/2.076.0.dd @@ -0,0 +1,451 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 1, 2017, =================================================, + +$(BUGSTITLE Compiler changes, + +$(LI $(RELATIVE_LINK2 staticforeach,Implement DIP 1010 - $(LINK2 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1010.md, Static foreach))) +$(LI $(RELATIVE_LINK2 betterc,$(TT -betterC) enhancements)) +$(LI $(RELATIVE_LINK2 avx2,AVX2 was added as $(TT -mcpu=avx2) architecture.)) +$(LI $(RELATIVE_LINK2 fix17697,Fix Issue 17697 - Ddoc: automatically highlight URLs outside of macro arguments)) + +) + +$(BUGSTITLE Runtime changes, + +$(LI $(RELATIVE_LINK2 unhandled,Print unhandled exception's trace and abort if rt_trapExceptions is false)) + +) + +$(BUGSTITLE Library changes, + +$(LI $(RELATIVE_LINK2 std-base64-base64urlnopadding,`Base64URLNoPadding` (URL-safe Base64 without padding) was added)) +$(LI $(RELATIVE_LINK2 std-digest-package,`std.digest.digest` was renamed to `std.digest`.)) +$(LI $(RELATIVE_LINK2 std-meta-stride,`std.meta.Stride` was added)) +$(LI $(RELATIVE_LINK2 std-process-config-detached,`Config.detached` flag for `spawnProcess` has been added)) +$(LI $(RELATIVE_LINK2 std-range-input-chunks,`std.range.chunks` was extended to support non-forward input ranges.)) +$(LI $(RELATIVE_LINK2 std-socket-abstract,`std.socket.UnixAddress` now supports abstract addresses.)) +$(LI $(RELATIVE_LINK2 std-typecons-AutoImplement,Added possibility to use a baseclass when auto-implementing an interface)) + +) + +$(BUGSTITLE Tools changes, + +$(LI $(RELATIVE_LINK2 b11997,rdmd now checks for a D compiler binary in the directory it's in first)) + +) + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BUGSTITLE Compiler changes, + +$(LI $(LNAME2 staticforeach,Implement DIP 1010 - $(LINK2 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1010.md, Static foreach)) +$(P +Support for `static foreach` has been added. +) + +$(P +`static foreach` is a conditional compilation construct that is to `foreach` what `static if` is to `if`. +It is a convenient way to generate declarations and statements by iteration. +) + +--- +import std.conv: to; + +static foreach(i; 0 .. 10) +{ + + // a `static foreach` body does not introduce a nested scope + // (similar to `static if`). + + // The following mixin declaration is at module scope: + mixin(`enum x` ~ to!string(i) ~ ` = i;`); // declares 10 variables x0, x1, ..., x9 +} + +import std.range: iota; +// all aggregate types that can be iterated with a standard `foreach` +// loop are also supported by static foreach: +static foreach(i; iota(10)) +{ + // we access the declarations generated in the first `static foreach` + pragma(msg, "x", i, ": ", mixin(`x` ~ to!string(i))); + static assert(mixin(`x` ~ to!string(i)) == i); +} + +void main() +{ + import std.conv: text; + import std.typecons: tuple; + import std.algorithm: map; + import std.stdio: writeln; + + // `static foreach` has both declaration and statement forms + // (similar to `static if`). + + static foreach(x; iota(3).map!(i => tuple(text("x", i), i))) + { + // generates three local variables x0, x1 and x2. + mixin(text(`int `,x[0],` = x[1];`)); + + scope(exit) // this is within the scope of `main` + { + writeln(mixin(x[0])); + } + } + + writeln(x0," ",x1," ",x2); // first runtime output +} +--- +) + +$(LI $(LNAME2 betterc,$(TT -betterC) enhancements) +$(P +Many improvements were added to the dmd's $(TT -betterC) implementation, most +notably programs compiled with $(TT -betterC) will no longer reference unused +druntime symbols, asserts are implemented as C `` calls, and phobos is +not linked by default. +) + +$(P +See the $(LINK2 $(ROOT_DIR)spec/betterc.html, Better C) specs for more details. +) +) + +$(LI $(LNAME2 avx2,AVX2 was added as $(TT -mcpu=avx2) architecture.) +$(P +This allows the backend to emit AVX2 instructions. The compiler will +add the predefined version $(LINK2 $(ROOT_DIR)spec/version.html#predefined-versions, `D_AVX2`). +AVX2 support is automatically detected with -mcpu=native. +) +) + +$(LI $(LNAME2 fix17697,Fix Issue 17697 - Ddoc: automatically highlight URLs outside of macro arguments) +$(P +URLs which appear in Ddoc text: +) + +--- +/**** + * http://www.fooa.com/test1 + */ +--- + +$(P +will be treated as if they were written: +) + +--- +/**** + * $(LINK http://www.fooa.com/test1) + */ +--- + +$(P +and a clickable hyperlink will be emitted to the resulting .html file. +) + +$(P +This detection does not happen if the URL is part of a macro argument: +) + +--- +/**** + * $(DOLLAR)$(LPAREN)ABC http://www.fooa.com/test1$(RPAREN) + */ +--- + +$(P +The behavior of that is unchanged. URLs can start with `http://` or `https://` +) + +$(P +`http:` and `https:` at the beginning of the line are no longer treated +as section headings. +) +) + +) + +$(BUGSTITLE Runtime changes, + +$(LI $(LNAME2 unhandled,Print unhandled exception's trace and abort if rt_trapExceptions is false) +$(P +D exception handling was assuming the top level exception handler, +so all exceptions would be handled somewhere. In case rt_trapExceptions +is cleared, this handler would not be enabled, and this assertion +would fail, aborting the program, but without any information +about the exception. This is now changed, so the exception information +will be printed to the stderr, followed by abort. +) +) + + +) + +$(BUGSTITLE Library changes, + +$(LI $(LNAME2 std-base64-base64urlnopadding,`Base64URLNoPadding` (URL-safe Base64 without padding) was added) +$(P +$(REF Base64URLNoPadding, std, base64) allows encoding/decoding without padding: +) + +--- +import std.base64 : Base64URLNoPadding; + +ubyte[] data = [0x83, 0xd7, 0x30, 0x7b, 0xef]; +assert(Base64URLNoPadding.encode(data) == "g9cwe-8"); +assert(Base64URLNoPadding.decode("g9cwe-8") == data); +--- +) + +$(LI $(LNAME2 std-digest-package,`std.digest.digest` was renamed to `std.digest`.) +$(P +$(B Motivation): +) + +$(P +The fully qualified name of the digest function template was `std.digest.digest.digest`. +This is because `std.digest` is a package, with a module named `digest` in it, and the function `digest` inside that. +) + +$(P +$(MREF std, digest) contains the former `std.digest.digest` package. +) +) + +$(LI $(LNAME2 std-meta-stride,`std.meta.Stride` was added) +$(P +$(REF Stride, std,meta) allows selecting a subset of template by a step size and offset: +) + +--- +alias attribs = AliasSeq!(short, int, long, ushort, uint, ulong); +static assert(is(Stride!(3, attribs) == AliasSeq!(short, ushort))); +static assert(is(Stride!(3, attribs[1 .. $]) == AliasSeq!(int, uint))); +--- +) + +$(LI $(LNAME2 std-process-config-detached,`Config.detached` flag for `spawnProcess` has been added) +$(P +`Config.detached` allows $(REF_ALTTEXT spawning processes, spawnProcess, std, process) which run independently from the current process. There is no need to wait on the processes created with this flag, and no $(HTTPS en.wikipedia.org/wiki/Zombie_process, zombie process) will be left after they exit. +Attempts to call $(REF wait, std, process) or $(REF kill, std, process) on detached processes will throw. +) +) + +$(LI $(LNAME2 std-range-input-chunks,`std.range.chunks` was extended to support non-forward input ranges.) +$(P +Now `std.range.chunks` can be used with input ranges that are not forward +ranges, albeit with limited semantics as imposed by the underlying range. +) + +--- +import std.algorithm.comparison : equal; + +int i; + +// The generator doesn't save state, so it cannot be a forward range. +auto inputRange = generate!(() => ++i).take(10); + +// We can still process it in chunks, but it will be single-pass only. +auto chunked = inputRange.chunks(2); + +assert(chunked.front.equal([1, 2])); +assert(chunked.front.empty); // Iterating the chunk has consumed it +chunked.popFront; +assert(chunked.front.equal([3, 4])); +--- +) + +$(LI $(LNAME2 std-socket-abstract,`std.socket.UnixAddress` now supports abstract addresses.) +$(P +UNIX domain sockets are usually identified by pathnames. Linux offers a +non-portable extension to this scheme, known as abstract socket addresses, +which are independent of the filesystem. An abstract socket address starts with +a null byte (`'\0'`), e.g.: +) + +--- +auto addr = new UnixAddress("\0/tmp/dbus-OtHLWmCLPR"); +--- +) + +$(LI $(LNAME2 std-typecons-AutoImplement,Added possibility to use a baseclass when auto-implementing an interface) +$(P +A second $(REF AutoImplement, std, typecons) template has been added, which +differs from the existing one in accepting an extra type parameter. The extra +parameter specifies a class to derive from while auto-implementing an interface. +) + +$(P +The base class used may contain non-default constructors. Matching constructors +will be created in the auto-implemented class and be implemented as just a call +to super with all arguments. +) +) + + +) + +$(BUGSTITLE Tools changes, + +$(LI $(LNAME2 b11997,rdmd now checks for a D compiler binary in the directory it's in first) +$(P +If you downloaded a zip/tar file with the compiler before +and ran `rdmd`, it would invoke the D compiler from the system +`PATH` rather than the compiler right next to it, failing if +there wasn't one in the `PATH`. `rdmd` will now try to use +the D compiler next to it first, and only fall back to the +`PATH` if there isn't one adjacent. If you want rdmd to run a +specific compiler, add the `--compiler` flag to force it, as +always. +) + +$(P +To restore the old behaviour of only using the compiler from +your `PATH`, add `--compiler=dmd` (or `ldmd2` or `gdmd`). +) +) + + +) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 16680): dmd doesn't use druntime optimized versions of subtraction array operations) +$(LI $(BUGZILLA 17522): win64.mak broken) +$(LI $(BUGZILLA 17582): [REG2.059] Applying const to struct declaration should make the struct type const) +$(LI $(BUGZILLA 17612): [REG2.063] Segmentation fault with bad object.d) +$(LI $(BUGZILLA 17684): [REG 2.062] `static alias this` bug or incomplete implementation?) +$(LI $(BUGZILLA 17690): [REG2.066.0] scope guards leak declarations) +$(LI $(BUGZILLA 17695): [Reg 2.076] ICE with vector negation) +$(LI $(BUGZILLA 17761): [REG2.075] dmd 2.075.1 creates object files that can't be linked by ld.bfd) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 4014): CodeView debug type info not linked in from library) +$(LI $(BUGZILLA 11881): -betterC switch suffers from bit rot) +$(LI $(BUGZILLA 11997): rdmd should search its binary path for the compiler) +$(LI $(BUGZILLA 13512): Allow non-UTF-8 encoding in shebang line) +$(LI $(BUGZILLA 15432): Win64: bad code offset in debug line number info) +$(LI $(BUGZILLA 16640): void fun$(LPAREN)string file=__FILE_FULL_PATH__$(RPAREN) returns relative path) +$(LI $(BUGZILLA 17380): Compiler segfaults on undefined symbol) +$(LI $(BUGZILLA 17388): [scope] e[] should be treated like &e as far as scope goes) +$(LI $(BUGZILLA 17430): [scope] delegate can escape context ptr) +$(LI $(BUGZILLA 17484): high penalty for vbroadcastsd with -mcpu=avx) +$(LI $(BUGZILLA 17489): ICE in ddmd/argtypes.d) +$(LI $(BUGZILLA 17551): VC build: bad mangling of real template argument) +$(LI $(BUGZILLA 17629): package.di files cannot be used) +$(LI $(BUGZILLA 17660): ICE with `static foreach`: AssertError@ddmd/visitor.d$(LPAREN)39$(RPAREN)) +$(LI $(BUGZILLA 17688): ICE with static foreach directly inside switch) +$(LI $(BUGZILLA 17689): finally clause leaks declarations) +$(LI $(BUGZILLA 17721): Wrong expression type using vector extensions with shift operands) +$(LI $(BUGZILLA 17722): Wrong diagnostic using __traits$(LPAREN)compiles, e1 && e2$(RPAREN) expressions.) +$(LI $(BUGZILLA 17735): AssertError@ddmd/target.d$(LPAREN)357$(RPAREN): unhandled op using fish operators) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 9287): DMD should read from stdin when an input file is "-") +$(LI $(BUGZILLA 9731): Ddoc should output per-paragraph macro instead of $$(LPAREN)DDOC_BLANKLINE$(RPAREN)) +$(LI $(BUGZILLA 17392): Add Dub file for the lexer and parser) +$(LI $(BUGZILLA 17428): [scope] class field assignment allows to escape scope parameters) +$(LI $(BUGZILLA 17499): with -betterC switch, call C's assert failure function rather than druntime's) +$(LI $(BUGZILLA 17521): -betterC programs should not link in Phobos runtime library by default) +$(LI $(BUGZILLA 17590): Unnecessary GC alloc on returning static local struct) +$(LI $(BUGZILLA 17697): Ddoc: automatically highlight URLs outside of macro arguments) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 17650): [REG v2.075.0 b1-b4] std.getopt range violation) +$(LI $(BUGZILLA 17661): New isInputRange rejects valid input range) +$(LI $(BUGZILLA 17724): digest is not a template declaration, it is a module) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 6718): "nWayUnion" => "nWayMerge", plus true nWayUnion) +$(LI $(BUGZILLA 12260): Improve error of std.stdio.readf when involving whitespace) +$(LI $(BUGZILLA 12866): Append to std.container.Array of fixed size arrays) +$(LI $(BUGZILLA 16079): memoize should cache objects too) +$(LI $(BUGZILLA 16191): std/digest/digest.d should be renamed to package.d) +$(LI $(BUGZILLA 17389): std.traits.hasNested fails for class with member of same type) +$(LI $(BUGZILLA 17458): [std.regex] Assertion failure in package.d) +$(LI $(BUGZILLA 17539): std.parallellism.parallel triggers 'statement not reachable' warnings in the rdmd_test suite) +$(LI $(BUGZILLA 17562): Tangent function returns NaN for abs$(LPAREN)input$(RPAREN) >= 2^63) +$(LI $(BUGZILLA 17574): Range violation in std.getopt:getopt AA parsing) +$(LI $(BUGZILLA 17616): makeIndex cannot fully use range of index type) +$(LI $(BUGZILLA 17640): std.concurrenct writeln conflicts with std.stdio writeln in unittests) +$(LI $(BUGZILLA 17673): wrong whichPattern in multi-regex with alteration) +$(LI $(BUGZILLA 17711): std.array.byPair should be usable with const AA) +$(LI $(BUGZILLA 17780): Malformed DDOC links in std.range) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 2137): Data not compressed on fly when adding to zip archive) +$(LI $(BUGZILLA 6384): std.traits.isComparable) +$(LI $(BUGZILLA 15759): chunks should work with only an input range) +$(LI $(BUGZILLA 15771): FileLogger should create the output directory if it does not exist) +$(LI $(BUGZILLA 16062): Add 'clear' method to OutBuffer $(LPAREN)std.outbuffer$(RPAREN)) +$(LI $(BUGZILLA 16993): Documentation for toSimpleString and toString does not explain how they differ) +$(LI $(BUGZILLA 17250): ProcessPipes $(LPAREN)std.process$(RPAREN) should provide a test for a null pid) +$(LI $(BUGZILLA 17365): https://dlang.org/phobos/std_experimental_checkedint.html is missing the Throw hook description) +$(LI $(BUGZILLA 17369): [Module std.traits] Documentation lists ditto in table) +$(LI $(BUGZILLA 17525): std.algorithm.searching.skipOver should have a single argument with pred version) +$(LI $(BUGZILLA 17540): std.net.curl: HTTP no possibillity to set CURLOPT_NOPROXY) +$(LI $(BUGZILLA 17587): JSONOptions: No forward slash encoding) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 15619): [REG 2.066] Floating-point x86_64 codegen regression, when involving array ops) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 11594): synchronized causing segfault instead of Error.) +$(LI $(BUGZILLA 14319): core.demangle does not support member function attributes) +$(LI $(BUGZILLA 14563): core.demangle: Does not demangle type modifers) +$(LI $(BUGZILLA 14576): [ddemangle] core.demangle unable to handle ambiguity in symbols) +$(LI $(BUGZILLA 16856): D does not work on FreeBSD current $(LPAREN)what will eventually be 12$(RPAREN) due to libunwind) +$(LI $(BUGZILLA 17609): core.demangle demangles delegate variables as functions) +$(LI $(BUGZILLA 17610): core.demangle shows return type of template alias parameter) +$(LI $(BUGZILLA 17611): core.demangle cannot demangle delegates with function attributes) +$(LI $(BUGZILLA 17624): typo in Fields documentation section of https://dlang.org/library/object/exception.html) +$(LI $(BUGZILLA 17665): Win64 atomicLoad for T[] cannot be cast from size_t[2]) +) +$(BUGSTITLE Druntime enhancements, + +$(LI $(BUGZILLA 16664): core.demangle functions are not callable from @safe or pure code) +) +$(BUGSTITLE dlang.org bugs, + +$(LI $(BUGZILLA 17159): Behavior of unions at compile time is not documented) +$(LI $(BUGZILLA 17224): Foreach documentation still refers to TypeTuples, rather than AliasSequences) +$(LI $(BUGZILLA 17305): [SPEC] ABI page still has references to D1 Phobos) +$(LI $(BUGZILLA 17509): [typo] "refered to" $(LPAREN)"referred to"$(RPAREN)) +$(LI $(BUGZILLA 17510): How could 509 be a byte value?) +$(LI $(BUGZILLA 17513): [english] "a enum" -> "an enum") +$(LI $(BUGZILLA 17702): codemirror hangs firefox for several seconds) +) +$(BUGSTITLE dlang.org enhancements, + +$(LI $(BUGZILLA 13153): dlang.org: provide version-specific documentation of the language and stdlib) +$(LI $(BUGZILLA 17262): Better docs for rdmd) +$(LI $(BUGZILLA 17322): Add Magikcraft to organizations using D) +$(LI $(BUGZILLA 17480): [Downloads]) +$(LI $(BUGZILLA 17524): [The C Preprocessor vs D] "need to worry about"?) +$(LI $(BUGZILLA 17560): Enhancement: view and copy full code example for offline compile/play) +$(LI $(BUGZILLA 17581): Document behavior of -betterC) +$(LI $(BUGZILLA 17594): Define DDOC_BLANKLINE as an empty HTML paragraph, thus obviating the need to wrap text in $$(LPAREN)P ...$(RPAREN)) +) +$(BUGSTITLE Tools bugs, + +$(LI $(BUGZILLA 17731): dman fails to build due to more than 32767 symbols) +) +) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.076.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.076.1.dd b/changelog/2.076.1.dd new file mode 100644 index 0000000000..87917ec0ad --- /dev/null +++ b/changelog/2.076.1.dd @@ -0,0 +1,44 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 09, 2017, =================================================, + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 17502): [REG2.064] Out contract in class method causes dmd segfault.) +$(LI $(BUGZILLA 17619): [REG2.072] Wrong debug line information with single line loops) +$(LI $(BUGZILLA 17876): [REG 2.074] Internal error when comparing inout$(LPAREN)Foo[][]$(RPAREN) with Foo[][]) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 17800): [2.076] "static foreach" allocates closures in GC without reason) +$(LI $(BUGZILLA 17805): -dirty flag on dmd's version) +$(LI $(BUGZILLA 17807): Spurious dead code warnings on enum and static variables.) +$(LI $(BUGZILLA 17812): crash when building JSON info with static foreach) +$(LI $(BUGZILLA 17814): bad output of "static foreach" with -vcg-ast) +$(LI $(BUGZILLA 17831): [ICE] Internal error: backend/symbol.c 1039: foreach inside a switch statement) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 17801): Date.fromISOExtString broken in 2.076 because of changed type specifier) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 13348): std.uni.Grapheme is impure due to using C malloc and friends) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 17788): MSCOFF: TLS broken when linking with linker from VS2017 15.3.1) +) +) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.076.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.077.0.dd b/changelog/2.077.0.dd new file mode 100644 index 0000000000..608260feec --- /dev/null +++ b/changelog/2.077.0.dd @@ -0,0 +1,231 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Nov 1, 2017, =================================================, + +$(BUGSTITLE Compiler changes, + +$(LI $(RELATIVE_LINK2 mangleBackref,Mangled Symbols now back reference types and identifiers.)) +$(LI $(RELATIVE_LINK2 removePreludeAssert,Removed prelude assert for constructors & destructors)) +$(LI $(RELATIVE_LINK2 reproducible_builds,DMD builds are now reproducible)) + +) + +$(BUGSTITLE Runtime changes, + +$(LI $(RELATIVE_LINK2 atomicLoad-return-types,`core.atomic.atomicLoad`'s returns types have changed for aggregate types that have indirections.)) +$(LI $(RELATIVE_LINK2 vectorized_array_ops,Vectorized array operations are now templated)) + +) + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BUGSTITLE Compiler changes, + +$(LI $(LNAME2 mangleBackref,Mangled Symbols now back reference types and identifiers.) +$(P +Symbols with extern(D) linkage are now mangled using back references +to types and identifiers if these occur more than once in the mangled name +as emitted before. This reduces symbol length, especially with chained expressions +of templated functions with Voldemort return types. For example, the average +symbol length of the 127000+ symbols created by a phobos unittest build +is reduced by a factor of about 3, while the longest symbol +shrinks from 416133 to 1142 characters. +) + +$(P +See details in the $(LINK2 $(ROOT_DIR)spec/abi.html#name_mangling, ABI) +specification. +) +) + +$(LI $(LNAME2 removePreludeAssert,Removed prelude assert for constructors & destructors) +$(P +The compiler used to insert an `assert(this, "null this");` at the start of constructors & destructors. +To trigger these asserts one needed to construct or destruct an aggregate at the null memory location. +This would crash upon any data member access, which is required for a constructor or destructor to do anything useful. +) +) + +$(LI $(LNAME2 reproducible_builds,DMD builds are now reproducible) +$(P +The dmd reference compiler now deterministically produces identical binaries for +a given source code and configuration, thus allowing third parties to verify +that distributed binaries indeed originate from specified source code. +) + +$(P +This guarantee only applies when the same compiler version and configuration is +used. Also values of the non-deterministic lexer tokens `__DATE__`, `__TIME__`, +and `__TIMESTAMP__` must not end up in the binary. +) + +$(P +See $(LINK2 https://reproducible-builds.org/, reproducible-builds.org) for further information. +) +) + + +) + +$(BUGSTITLE Runtime changes, + +$(LI $(LNAME2 atomicLoad-return-types,`core.atomic.atomicLoad`'s returns types have changed for aggregate types that have indirections.) +$(P +$(REF atomicLoad, core,atomic) used to strip the `shared` qualifier off too +eagerly. When an aggregate type has a "head" and a "tail", connected by an +indirection, then `atomicLoad` used to strip `shared` off the tail. That was a +bug ($(BUGZILLA 16230)). `atomicLoad` only loads the head. The tail remains in +shared memory, and must keep the `shared` qualifier. +) + +$(P +When loading a struct that contains indirections, `atomicLoad` now returns a +wrapper that provides getters which return properly typed values. +) + +$(P +When loading a class reference, `atomicLoad` now leaves the `shared` qualifier +on. +) + +$(P +Example: +) +---- +class C { int value; } +shared C shc = new C; + +struct S { int head; int* tailPointer; } +shared int tail = 1; +auto shs = shared S(2, &tail); + +void main() +{ + import core.atomic : atomicLoad, atomicOp; + + // Loading a class reference: + shared C c = atomicLoad(shc); + // c itself is not actually shared. It's safe to copy it non-atomically: + shared C c2 = c; // ok + // c's fields are still shared and need to be loaded atomically: + int v = atomicLoad(c.value); + + // Loading a struct that has an indirection: + auto s = atomicLoad(shs); + // The struct's head has been copied and can be modified non-atomically: + ++s.head; + // The tail is still shared and needs to be handled atomically: + shared(int)* t = s.tailPointer; + atomicOp!"+="(*t, 1); +} +---- +) + +$(LI $(LNAME2 vectorized_array_ops,Vectorized array operations are now templated) +$(P +Array operations have been converted from dedicated assembly routines for $(B some) array operations to a generic template implementation for $(B all) array operations. This provides huge performance increases (2-4x higher throughput) for array operations that were not previously vectorized. +Furthermore the implementation makes better use of vectorization even for short arrays to heavily reduce latency for some operations (up to 4x). +) + +$(P +For GDC/LDC the implementation relies on auto-vectorization, for DMD the implementation performs the vectorization itself. Support for vector operations with DMD is determined statically (`-march=native`, `-march=avx2`) to avoid binary bloat and the small test overhead. DMD enables SSE2 for 64-bit targets by default. +) + +$(P +Also see $(DRUNTIMEPR 1891) +) + +$(P +$(RED Note:) The implementation no longer weakens floating point divisions (e.g. `ary[] / scalar`) to multiplication (`ary[] * (1.0 / scalar)`) as that may reduce precision. To preserve the higher performance of float multiplication when loss of precision is acceptable, use either `-ffast-math` with GDC/LDC or manually rewrite your code to multiply by `(1.0 / scalar)` for DMD. +) +) + + +) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 15538): [REG 2.064] wrong code with switch) +$(LI $(BUGZILLA 16013): [REG2.072a] ICE with mutually dependent structs and alias this) +$(LI $(BUGZILLA 16273): [REG 2.072a] dmd segfault with inheritance, templates, override) +$(LI $(BUGZILLA 17307): [REG2.072.0][ICE] TypeBasic::implicitConvTo: After error "anonymous struct can only be a part of an aggregate") +$(LI $(BUGZILLA 17684): [REG 2.062] `static alias this` bug or incomplete implementation?) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 6625): Distribute newer Windows API import libraries) +$(LI $(BUGZILLA 11259): __traits$(LPAREN)isSame$(RPAREN) fails on the result of __traits$(LPAREN)parent$(RPAREN) if parent is a package) +$(LI $(BUGZILLA 17370): [scope] Escaping scope pointers possible via struct GC allocation) +$(LI $(BUGZILLA 17568): [scope] addresses to fields can be escaped from scope method) +$(LI $(BUGZILLA 17725): [scope] escape from nested function to enclosing local) +$(LI $(BUGZILLA 17751): Internal error: ddmd/backend/el.c 2927) +$(LI $(BUGZILLA 17782): The identifier delimiter of a delimited string can not begin with '_') +$(LI $(BUGZILLA 17790): [scope] Escaping pointer possible through array of aggregates) +$(LI $(BUGZILLA 17795): [scope] Scope errors not detected in ~= operation) +$(LI $(BUGZILLA 17857): T.alignof ignores explicit align$(LPAREN)N$(RPAREN) type alignment) +$(LI $(BUGZILLA 17943): Wrong pointer arithmetic optimization) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 10523): Don't call array op functions for short vector ops) +$(LI $(BUGZILLA 13262): Cannot send certain shared data to another thread) +$(LI $(BUGZILLA 15831): IFTI voldemort type exploding bloat) +$(LI $(BUGZILLA 16995): __traits$(LPAREN)getUnittests$(RPAREN) doesn't work with separate compilation) +$(LI $(BUGZILLA 17787): Add a BetterC predefined version so libraries can adapt) +$(LI $(BUGZILLA 17791): Add __traits$(LPAREN)isDeprecated, ...$(RPAREN)) +$(LI $(BUGZILLA 17887): Add WebAssembly reserved version identifier) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 3191): std.zlib.UnCompress errors if buffer is reused) +$(LI $(BUGZILLA 8779): std.zlib.UnCompress needs a way to detect end-of-stream) +$(LI $(BUGZILLA 9505): std.zlib seem to be bugged) +$(LI $(BUGZILLA 10444): writeln of a SIMD register) +$(LI $(BUGZILLA 11389): template arity does not work with function type) +$(LI $(BUGZILLA 12470): std.array.replace does not work with inout$(LPAREN)char$(RPAREN)[]) +$(LI $(BUGZILLA 13829): std.uni.byCodePoint for strings has length) +$(LI $(BUGZILLA 15096): std.array.array cannot be instantiated for pointers to ranges) +$(LI $(BUGZILLA 15735): std.algorithm.iteration.splitter returns empty range) +$(LI $(BUGZILLA 16264): BigInt multiplication crashes on 64-bit $(LPAREN)biguintnoasm.d$(LPAREN)276$(RPAREN): Range violation$(RPAREN)) +$(LI $(BUGZILLA 17847): Properly sanitize seeds for Park–Miller engines) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 4582): distinct field names constraint for std.typecons.Tuple) +$(LI $(BUGZILLA 6004): std.range.unzip$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 6409): std.array.empty for associative arrays too) +$(LI $(BUGZILLA 9183): Add a Nullable.get$(LPAREN)x$(RPAREN) overload) +$(LI $(BUGZILLA 9591): std.typetuple.staticApplyMap) +$(LI $(BUGZILLA 16512): std.allocator: Nullify the argument passed to allocator.dispose) +$(LI $(BUGZILLA 16984): Make more modules runnable on dlang.org) +$(LI $(BUGZILLA 17803): std.typecons.Tuple: opAssign should return ref Tuple) +$(LI $(BUGZILLA 17844): std.process.execute should allow not capturing stderr) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 16230): core.atomic.atomicLoad removes shared from aggregate types too eagerly) +$(LI $(BUGZILLA 17829): core.stdc.errno does not work with -betterC) +) +$(BUGSTITLE dlang.org bugs, + +$(LI $(BUGZILLA 9958): "Integer FloatSuffix" is not a valid FloatLiteral) +$(LI $(BUGZILLA 17649): CONTRIBUTING.md instructions failed $(LPAREN)no ../druntime dir$(RPAREN)) +$(LI $(BUGZILLA 17798): [2.076] "static foreach" not documented) +$(LI $(BUGZILLA 17848): Example of floating point literals in the documentation is invalid) +$(LI $(BUGZILLA 17856): __traits$(LPAREN) identifier $(RPAREN) could use examples in on line documentation.) +) +$(BUGSTITLE dlang.org enhancements, + +$(LI $(BUGZILLA 17581): Document behavior of -betterC) +) +) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.077.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.077.1.dd b/changelog/2.077.1.dd new file mode 100644 index 0000000000..855a90bee0 --- /dev/null +++ b/changelog/2.077.1.dd @@ -0,0 +1,31 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Nov 29, 2017, =================================================, + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 16183): [REG2.068] compile-time string concatenation fails with CTFE and char[] literal involved) +$(LI $(BUGZILLA 17955): compiler segfault in DsymbolSemanticVisitor::visit$(LPAREN)UnittestDeclaration*$(RPAREN)) +$(LI $(BUGZILLA 17969): [REG 2.077.0] dmd 2.077.0 crashes when computing mangling symbol for simple program) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 17996): [Reg 2.077] don't build libphobos2.a with PIC for i386) +) +$(BUGSTITLE Druntime regressions, + +$(LI $(BUGZILLA 17914): [Reg 2.075] Fibers guard page uses a lot more memory mappings) +) +) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.077.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.078.0.dd b/changelog/2.078.0.dd new file mode 100644 index 0000000000..3657798402 --- /dev/null +++ b/changelog/2.078.0.dd @@ -0,0 +1,754 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 01, 2018, =================================================, + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 PR7356,`opDispatch` resolution in `with` statements)) +$(LI $(RELATIVE_LINK2 body,Generate header files using `do` instead of `body` as per DIP1003)) +$(LI $(RELATIVE_LINK2 crt-constructor,pragma(crt_constructor) and pragma(crt_destructor) were added)) +$(LI $(RELATIVE_LINK2 fix11006,Subtraction of pointers that point to different types has been deprecated.)) +$(LI $(RELATIVE_LINK2 fix15243_PR7403,Variadic template arguments no longer require `alias` workaround)) +$(LI $(RELATIVE_LINK2 fix16997,fix Issue 16997 - Integral promotion rules not being followed for unary + - ~ operators)) +$(LI $(RELATIVE_LINK2 optional_ModuleInfo,Optional `ModuleInfo`)) +$(LI $(RELATIVE_LINK2 raii,Added RAII and try-finally support for -betterC mode.)) +$(LI $(RELATIVE_LINK2 vs-auto-detection,Windows: dmd can now detect Visual Studio installation paths)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 core-runtime-unittestEnhancement,`core.runtime` now allows more fine-grained control over unittests.)) +$(LI $(RELATIVE_LINK2 covopts,The runtime learned a few new options to customize how coverage reports are created.)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 std-algorithm-iteration-mean,`mean` Was Added To `std.algorithm`)) +$(LI $(RELATIVE_LINK2 std-algorithm-searching-findSkip,`findSkip` can now skip elements using just a predicate function)) +$(LI $(RELATIVE_LINK2 std-array-bypair,`std.array.byPair` now returns a `NamedTuple`)) +$(LI $(RELATIVE_LINK2 std-container-dlist-linearRemoveElement,`std.container.dlist` supports `linearRemoveElement`)) +$(LI $(RELATIVE_LINK2 std-container-slist-linearRemoveElement,`std.container.slist` supports `linearRemoveElement`)) +$(LI $(RELATIVE_LINK2 std-range-package-Transposed-deprecate-save,Deprecate `save` for `std.range.package.Transposed`)) +$(LI $(RELATIVE_LINK2 std-typecons-ternary-opBinary,`std.typecons.Ternary.opBinary` supports `bool` bitwise operands)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 PR7356,`opDispatch` resolution in `with` statements) +$(P +`opDispatch` resolution in `with` statements has been modified to bring it into compliance with the existing scope resolution rules in the language specification. See $(LINK2 $(ROOT_DIR)spec/statement.html#with-statement, WithStatement) in the language specification. +) + +$(P +Prior to this release, the following code would not compile because the compiler would not be able to resolve the second call to `f()`, as `Bar` does not implement `f()` or `opDispatch`. +) +------- +import std.stdio; + +struct Foo +{ + void opDispatch(string name)() + { + mixin("writeln(\"Foo.opDispatch!" ~ name ~ "\");"); + } +} + +struct Bar +{ + // `Bar` does not implement `f()` or `opDispatch` +} + +void main() +{ + Foo foo; + Bar bar; + + with(foo) + { + f(); // prints "Foo.opDispatch!f" + with(bar) + { + f(); // Prior to this Release: Error: undefined identifer `f` + // Starting with this release: Prints "Foo.opDispatch!f". + // `f`'s resolution is forwarded up the scope hierarchy. + } + } +} +------- + +$(P +Starting with this release, the second call to `f()` will be forwarded up the scope hierarchy, matching the implementation of `Foo.opDispatch`. +) +) + +$(LI $(LNAME2 body,Generate header files using `do` instead of `body` as per DIP1003) +$(P +Support for +$(LINK2 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1003.md, DIP1003) +was added in release 2.075.0. Use of `body` in an error message and +header file generation has been fixed in this release. +) +) + +$(LI $(LNAME2 crt-constructor,pragma(crt_constructor) and pragma(crt_destructor) were added) +$(P +This allows programs to run initialization code before or cleanup code after C +main. +) + +$(P +In particular those pragmas can be used in $(TT -betterC) code as substitutes +for $(LINK2 $(ROOT_DIR)spec/class.html#shared_static_constructors, `shared static this()`) and +$(LINK2 $(ROOT_DIR)spec/class.html#shared_static_destructors, `shared static ~this()`). +) + +$(P +$(RED Note:) At the time of execution druntime is not initialized. +) + +$(P +$(RED Note:) The order in which constructors are executed is unspecified. +) + +--- +import core.stdc.stdio; + +pragma(crt_constructor) +void init() +{ + puts("init"); +} + +pragma(crt_destructor) +void fini() +{ + puts("fini"); +} + +extern(C) int main() +{ + puts("main"); +} +--- +) + +$(LI $(LNAME2 fix11006,Subtraction of pointers that point to different types has been deprecated.) +$(P +$(LINK2 $(ROOT_DIR)spec/expression.html#add_expressions, The language specification) reads: +"If both operands are pointers, and the operator is -, the pointers are subtracted and the result is divided by the size of the type pointed to by the operands. It is an error if the pointers point to different types." +) + +$(P +Prior to this release, the compiler allowed the following pointer arithmetic: +) +------- +void* p1; +int* p2; +auto p3 = p2 - p1; +------- +$(P +Starting with this release, the subtraction of pointers that point to different types will emit a deprecation warning. The warning will remain in place for at least a year, after which it will be changed to an error. +) +) + +$(LI $(LNAME2 fix15243_PR7403,Variadic template arguments no longer require `alias` workaround) +$(P +Prior to this release, the following code would not compile. +) + +---- +class C(Types...) +{ + void apply(U)(U delegate(Types[0]) f0) { } // Error: cannot deduce function from argument types +} + +void test() +{ + C!int c; + + int f(int) { return 0; } + + c.apply(&f); +} +---- + +$(P +It could be worked around by `alias`ing the individual template arguments. +) + +---- +class C(Types...) +{ + alias Types[0] T0; + void apply(U)(U delegate(T0) f0) { } // OK +} +---- + +$(P +Starting with this release, the workaround is no longer required. +) +) + +$(LI $(LNAME2 fix16997,fix Issue 16997 - Integral promotion rules not being followed for unary + - ~ operators) +$(P +To follow the C integral promotion rules, types are promoted to `int` before the +unary + - or ~ operators are applied. Existing D does not do this. +) + +$(P +This is corrected when one of the following command line switches are used: +) + +$(P + -transition=intpromote + -transition=16997 +) + +$(P +It affects operands of type `byte`, `ubyte`, `short`, `ushort`, `char`, and `wchar`. +The operands are promoted to `int` before the operator is applied. The result +type will now be `int`. +) + +$(P +The values computed will be different for some values of the operands: +) + +$(P +* All values of - and ~ applied to ubyte, ushort, char, and dchar operands will change. +) + +$(P +* The values of `-byte(-128)` and `-short(-32768)` will change. +) + +$(P +If one of the '-transition=' switches is not specified, a deprecation will be emitted for these operations. +To fix the deprecation and work as desired with or without the '-transition=' switch: +) + +$(P +Option 1: +) + +$(P +Rewrite `op b` as `op int(b)` to use correct, i.e. C-like, behavior. +) + +$(P +Option 2: +) + +$(P +Rewrite `op b` as `typeof(b)(op int(b))` to preserve the old behavior. +) + +$(P +Once deprecated this will become an error, and then the C-like behavior will become the default. +) +) + +$(LI $(LNAME2 optional_ModuleInfo,Optional `ModuleInfo`) +$(P +$(LINK2 $(ROOT_DIR)phobos/object.html#.ModuleInfo, `ModuleInfo`) is not a necessary feature of D. There are use cases where the program author may choose to provide an alternate implementation of the D runtime that does not include `ModuleInfo`. This could be for interoperability with other software or to reduce the footprint of D programs in resource constrained platforms. +) + +$(P +Prior to this release, the compiler would emit an error if `ModuleInfo` was not declared in the D runtime. +) + +$(P +Platform support is provided by the D runtime. `ModuleInfo` is declared in object.d. Therefore, the compiler can see, at compile-time, whether or not the platform has provided support for `ModuleInfo` and generate object code accordingly. +) + +$(P +Starting with this release, if `ModuleInfo` is not deсlared in the D runtime, the compiler will simply not generate `ModuleInfo` instances. +) + +$(P +This should reduce friction for those wishing to incrementally port D to new platforms and use D in a more pay-as-you-go fashion. +) +) + +$(LI $(LNAME2 raii,Added RAII and try-finally support for -betterC mode.) +$(P +This also means that scope(exit) statements will also work, because +they are internally lowered to try-finally statements. +) + +$(P +This does not mean that exceptions are supported. Throwing, +catching, and stack frame unwinding is not supported, as that +requires support from Phobos. +) + +$(P +It means that, for RAII, when variables go out of lexical scope +their destructors get run. When try blocks from try-finally statements +exit, the code in the finally block is run. +) +) + +$(LI $(LNAME2 vs-auto-detection,Windows: dmd can now detect Visual Studio installation paths) +$(P +dmd now determines the environment variables that are usually set if the "Command Line prompt for Visual Studio" link is used to open a console window (or vcvarsall.bat is executed). This includes Windows SDK directories and Visual C library directories. When compiling with -m64 or -m32mscoff this allows dmd to invoke the linker without having a Visual Studio version preselected by the installer. +) + +$(P +In particular, the variables WindowsSdkDir, WindowsSdkVersion, UniversalCRTSdkDir, +UCRTVersion, VSINSTALLDIR, VisualStudioVersion, VCINSTALLDIR and VCTOOLSINSTALLDIR are +determined from the registry if they are not set in the environment or sc.ini. +) + +$(P +Supported Windows SDK range from 7.0A to 10.x, supported Visual Studio Versions are +VS 2008 to VS 2017. If multiple versions are installed, highest versions are preferred. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 core-runtime-unittestEnhancement,`core.runtime` now allows more fine-grained control over unittests.) +$(P +`core.runtime.extendedModuleUnitTester` property allows specifying information +about the tests run, and how to handle the result. See documentation for +`core.runtime.UnitTestResult` for details. +) + +$(P +`core.runtime.moduleUnitTester` (setting a unittest handler that returns bool) +will continue to be supported for legacy projects. +) + +----------------- +import core.runtime; +import core.stdc.stdio: printf; + +UnitTestResult customTester() +{ + UnitTestResult ret; + + // run only the tests in my package + immutable prefix = "myPackage."; + foreach (m; ModuleInfo) + { + if (m.unitTest !is null && m.name.length >= prefix.length && + m.name[0 .. prefix.length] == prefix) + { + ++ret.executed; // count unit tests run + try + { + m.unitTest(); + ++ret.passed; // count unit tests passed + } + catch(Throwable t) + { + auto msg = t.toString(); + printf("%.*s\n", cast(uint)msg.length, msg.ptr); + } + } + } + // always summarize + ret.summarize = true; + // only unit testing, don't ever run main + ret.runMain = false; +} + +version(unittest) static shared this() +{ + Runtime.extendedModuleUnitTester = &customTester; +} +----------------- +) + +$(LI $(LNAME2 covopts,The runtime learned a few new options to customize how coverage reports are created.) +$(P +The format is the same as with the GC but using `covopt` as suffix, for example +you can pass options separating them with spaces like `--DRT-covopt "merge:1 +dstpath:/tmp"`. +) + +$(P +These are the currently accepted options: +) + +$(P +$(DL + $(DT merge) $(DD Merge the current run with existing reports if 1, or overwrite the existing reports if 0.) + $(DT srcpath) $(DD Set path to where source files are located.) + $(DT dstpath) $(DD Set path to where listing files are to be written.) +) +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 std-algorithm-iteration-mean,`mean` Was Added To `std.algorithm`) +$(P +$(REF mean, std, algorithm, iteration) accurately finds the +mean (a.k.a the average) of any range of number-like elements. +) + +----- +import std.algorithm.iteration : mean; +import std.math : approxEqual; + +int[] arr1 = [1, 2, 3]; +real[] arr2 = [1.5, 2.5, 12.5]; + +assert(arr1.mean.approxEqual(2)); +assert(arr2.mean.approxEqual(5.5)); + +// user defined number types also work +import std.bigint : BigInt; + +auto bigint_arr = [ + BigInt("1_000_000_000_000_000_000"), + BigInt("2_000_000_000_000_000_000"), + BigInt("3_000_000_000_000_000_000"), + BigInt("6_000_000_000_000_000_000") +]; +auto seed = BigInt(0); +assert(bigint_arr.mean(seed) == BigInt("3_000_000_000_000_000_000")); +----- +) + +$(LI $(LNAME2 std-algorithm-searching-findSkip,`findSkip` can now skip elements using just a predicate function) +$(P +Previously, $(REF findSkip, std, algorithm, searching) could only +be used to find a specific string. Now, a new overload allows elements +in a range to be skipped over if the passed function returns `true`: +) + +------- +import std.ascii : isWhite; +string s = " abc"; +assert(findSkip!isWhite(s) == 3 && s == "abc"); +assert(!findSkip!isWhite(s) && s == "abc"); +------- +) + +$(LI $(LNAME2 std-array-bypair,`std.array.byPair` now returns a `NamedTuple`) +$(P +$(REF byPair, std, array) now returns a named tuple. +) + +--- +import std.array : byPair; +import std.typecons : Tuple; + +int[string] dict = ["b": 2, "c": 3]; +auto pairs = dict.byPair; +static assert(is(typeof(pairs.front) : Tuple!(string,int))); + +// access by index (existing way) +assert(pairs.front[0] == "b"); +assert(pairs.front[1] == 2); + +// access by name (enabled with this release) +assert(pairs.front.key == "b"); +assert(pairs.front.value == 2); +--- +) + +$(LI $(LNAME2 std-container-dlist-linearRemoveElement,`std.container.dlist` supports `linearRemoveElement`) +$(P +`linearRemoveElement` removes the first occurence of an element from the dlist +) + +----- +import std.container : Dlist; +import std.algorithm.comparison : equal; + +auto a = DList!int(-1, 1, 2, 1, 3, 4); +a.linearRemoveElement(1); +assert(equal(a[], [-1, 2, 1, 3, 4])); +----- +) + +$(LI $(LNAME2 std-container-slist-linearRemoveElement,`std.container.slist` supports `linearRemoveElement`) +$(P +`linearRemoveElement` removes the first occurence of an element from the slist +) + +----- +import std.container : Slist; +import std.algorithm.comparison : equal; + +auto a = SList!int(-1, 1, 2, 1, 3, 4); +a.linearRemoveElement(1); +assert(equal(a[], [-1, 2, 1, 3, 4])); +----- +) + +$(LI $(LNAME2 std-range-package-Transposed-deprecate-save,Deprecate `save` for `std.range.package.Transposed`) +$(P +Transposed is incorrectly marked as a forward range. Its `popFront` primitive +cannot be used without affecting any other copies made with `save`. `save` will be +removed from Transposed in November 2018. +) + +----- +auto x = [[1,2,3],[4,5,6]].transposed; +auto y = x.save; +y.popFront; +assert(x.equal([[1,4],[2,5],[3,6]])); // FAILS, x is really [[2,5],[3,6]] +----- + +$(P +For more details, please see the respective $(LINK2 https://issues.dlang.org/show_bug.cgi?id=17952, +Bugzilla issue). +) +) + +$(LI $(LNAME2 std-typecons-ternary-opBinary,`std.typecons.Ternary.opBinary` supports `bool` bitwise operands) +$(P +Now $(REF Ternary, std, typecons) can be used in bitwise operations with `bool`s: +) + +----- +import std.typecons : Ternary; + +Ternary a = Ternary(true); +assert(a == Ternary.yes); +assert((a & false) == Ternary.no); +assert((a | false) == Ternary.yes); +assert((a ^ true) == Ternary.no); +assert((a ^ false) == Ternary.yes); +----- +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 17246): [REG2.053] Extra destructor call.) +$(LI $(BUGZILLA 17371): [REG 2.074.0] di generation broken for anonymous classes) +$(LI $(BUGZILLA 17559): [REG2.073.0] Wrong line number in stack trace) +$(LI $(BUGZILLA 17915): [REG 2.073] core.exception.AssertError@ddmd/optimize.d$(LPAREN)614$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 17955): compiler segfault in DsymbolSemanticVisitor::visit$(LPAREN)UnittestDeclaration*$(RPAREN)) +$(LI $(BUGZILLA 18020): [Reg 2.078] no property opCmp for anon class) +$(LI $(BUGZILLA 18093): [Reg 2.071] MSCOFF: dmd crashes when overriding a C++ method in a mixin template) +$(LI $(BUGZILLA 18141): [REG2.078a] dmd -v no longer prints predefs) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 5332): Undefined reference to zero length array) +$(LI $(BUGZILLA 6400): opDispatch with WithStatement) +$(LI $(BUGZILLA 8262): ICE$(LPAREN)mtype.c$(RPAREN) alias this to alias of an expression tuple) +$(LI $(BUGZILLA 9290): Ability to modify immutable struct members in static array assignment) +$(LI $(BUGZILLA 10310): VRP for bitwise &|^ does not always produce the tightest bounds.) +$(LI $(BUGZILLA 11006): Subtraction of pointers for `void` and non-void types compiles) +$(LI $(BUGZILLA 12385): Enum member should not be modifiable when the member is immutable) +$(LI $(BUGZILLA 12496): __traits$(LPAREN)parent, x$(RPAREN) returns incorrect type) +$(LI $(BUGZILLA 12625): [scope] [DIP1000] implicit slicing of RValue static array should be illegal) +$(LI $(BUGZILLA 15094): __traits$(LPAREN)getMember$(RPAREN) fails when the source is a struct/class field) +$(LI $(BUGZILLA 15243): rejects-valid on variadic) +$(LI $(BUGZILLA 15289): VRP not working as expected on division) +$(LI $(BUGZILLA 15290): length of associative array literal with duplicate keys is wrong) +$(LI $(BUGZILLA 16649): Header gen skips parens) +$(LI $(BUGZILLA 16694): ICE on taking address of `export` function $(LPAREN)declaration-only$(RPAREN)) +$(LI $(BUGZILLA 16997): Integral promotion rules not being followed for unary + - ~ expressions) +$(LI $(BUGZILLA 17096): many traits accept an invalid parameter count without error) +$(LI $(BUGZILLA 17167): dmd fails to write to file or create directory with more than 248 characters in the path) +$(LI $(BUGZILLA 17382): void main$(LPAREN)$(RPAREN){}pragma$(LPAREN)msg,main$(LPAREN)$(RPAREN)$(RPAREN); crashes DMD) +$(LI $(BUGZILLA 17585): Wrong error message for deprecated overrides) +$(LI $(BUGZILLA 17586): Overriding a deprecated base class function gives no warning) +$(LI $(BUGZILLA 17842): [scope] array append allows for escaping references) +$(LI $(BUGZILLA 17843): -betterC struct with `double` field generates references to TypeInfo) +$(LI $(BUGZILLA 17853): Switch statement without braces only works with one case) +$(LI $(BUGZILLA 17900): FreeBSD 10.3 runnable/cpp_abi_tests.d$(LPAREN)94$(RPAREN): Assertion failure $(LPAREN)test suite$(RPAREN)) +$(LI $(BUGZILLA 17908): Can't alias an overload set with disabled function) +$(LI $(BUGZILLA 17927): [scope] `scope inout` parameter value can be escaped via return) +$(LI $(BUGZILLA 17934): [scope] scopeness entrypoint for unique/ref-counted missing) +$(LI $(BUGZILLA 17935): [scope] auto-generated destructor not scope aware) +$(LI $(BUGZILLA 17940): bool function parameters loaded from struct sometimes miscompiled with -O) +$(LI $(BUGZILLA 17944): MSCOFF: debug info not compatible with LLVMs LLD) +$(LI $(BUGZILLA 17947): C++ std::pair::swap mangled incorrectly) +$(LI $(BUGZILLA 17976): core.exception.AssertError@ddmd/dsymbolsem.d$(LPAREN)1624$(RPAREN)) +$(LI $(BUGZILLA 17997): autotester's d_do_test has strange failures with Win32) +$(LI $(BUGZILLA 18013): DMD test suite assertion failure in test_cdvecfill.d) +$(LI $(BUGZILLA 18014): DMD test suite fails to link on Linux distros where PIC/PIE is enforced) +$(LI $(BUGZILLA 18045): Temporary created during comparison not destroyed) +$(LI $(BUGZILLA 18099): betterC check throw statements error!) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 4946): Not good error message with wrongly positioned 'const') +$(LI $(BUGZILLA 17256): Inconsistent output between json and ddoc) +$(LI $(BUGZILLA 17868): add pragma$(LPAREN)crt_con/destructor$(RPAREN)) +$(LI $(BUGZILLA 17878): Add __traits$(LPAREN)isFuture, ...$(RPAREN)) +$(LI $(BUGZILLA 18076): dmd -run should work with `-` $(LPAREN)stdin$(RPAREN) too) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 17962): dirEntries now truncates Unicode file names) +$(LI $(BUGZILLA 17986): Erratic failure with std/experimental/allocator/common.d$(LPAREN)445$(RPAREN): unittest failure) +$(LI $(BUGZILLA 18084): [REG2.072] tempCString buffer size is unittest-versioned) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 2447): There's no disconnectall for std.signals) +$(LI $(BUGZILLA 6820): etc.c.curl missing const) +$(LI $(BUGZILLA 6895): std.traits.isCovariantWith doesn't work for function, function pointer and delegate) +$(LI $(BUGZILLA 9661): LockingTextWriter should increment file handle reference count) +$(LI $(BUGZILLA 10395): [std.stdio] Closing a popened File with unread output throws an exception) +$(LI $(BUGZILLA 12064): std.typecons.wrap doesn't handle NVI) +$(LI $(BUGZILLA 14477): Nullable does not work with structs with default constructor disabled) +$(LI $(BUGZILLA 15140): std.experimental.allocator.building_blocks.free_list.FreeList leaks memory) +$(LI $(BUGZILLA 15637): Region allocator assert failure when expanding the last allocation) +$(LI $(BUGZILLA 16253): BitmappedBlock allocator not working with chooseAtRuntime) +$(LI $(BUGZILLA 16542): makeArray not usable with const initializer) +$(LI $(BUGZILLA 16564): KRRegion.empty sometimes returns Ternary.no) +$(LI $(BUGZILLA 17459): format$(LPAREN)"%012,3d", ...$(RPAREN) doesn't handle field width and zero-padding correctly) +$(LI $(BUGZILLA 17467): BitArray are broken with <<= 64) +$(LI $(BUGZILLA 17730): [scope][dip1000] std.algorithm.move escapes scope variable in @safe code) +$(LI $(BUGZILLA 17901): FreeBSD 10.3: AssertError@std/experimental/allocator/building_blocks/region.d$(LPAREN)652$(RPAREN)) +$(LI $(BUGZILLA 17995): template NoDuplicates$(LPAREN)TList...$(RPAREN) bug.) +$(LI $(BUGZILLA 18044): std.conv.to for implicitly convertible associative arrays) +$(LI $(BUGZILLA 18047): std.format value.length modulo seperator step width leads to wrong length) +$(LI $(BUGZILLA 18092): Can't combine take and takeExactly) +$(LI $(BUGZILLA 18135): [REG2.078] can't join RegexMatch anymore) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 1998): std.bitarray should have setAll / opSliceAssign$(LPAREN)bool$(RPAREN) etc) +$(LI $(BUGZILLA 4717): std.bitmanip.BitArray changes) +$(LI $(BUGZILLA 4763): std.stdio.File.open$(LPAREN)$(RPAREN) : more efficient implementation) +$(LI $(BUGZILLA 6244): Add powmod / modpow function to std.math) +$(LI $(BUGZILLA 9362): Add a method to remove one item to std.container.SList) +$(LI $(BUGZILLA 13532): std.regex performance $(LPAREN)enums; regex vs ctRegex$(RPAREN)) +$(LI $(BUGZILLA 14034): std.algorithm.mean) +$(LI $(BUGZILLA 16398): experimental allocators, add aligned reallocation for Posix) +$(LI $(BUGZILLA 17742): std.range.transposed does not have opIndex) +$(LI $(BUGZILLA 17905): byCodeUnit should allow access to underlying range) +$(LI $(BUGZILLA 17919): std.container.Array could use pureMalloc) +$(LI $(BUGZILLA 17952): std.range.transposed save is invalid) +$(LI $(BUGZILLA 18021): FileLogger Member not accessible to subclasses) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 17914): [Reg 2.075] Fibers guard page uses a lot more memory mappings) +$(LI $(BUGZILLA 18071): [REG2.078] byKey, byValue and byKeyValue are now a hole for unsafe code) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 17108): Associative array byKeyValue is unsafe) +$(LI $(BUGZILLA 17851): htonl already defined in phobos64.lib) +$(LI $(BUGZILLA 17956): core.memory unittest failure $(LPAREN)possibly glibc 2.26 specific$(RPAREN)) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 17300): Enable setting code coverage options on the command line) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 18033): Open in Editor button doesn't work) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 16392): drop win32.mak) +$(LI $(BUGZILLA 17265): WithStatement: Find better Example for what "with" really does) +$(LI $(BUGZILLA 17527): dlangspec.pdf: escape sequences table goes over the page boundaries) +$(LI $(BUGZILLA 17529): dlangspec.pdf: grammar definitions go over the right margin) +$(LI $(BUGZILLA 17531): dlangspec.pdf: overloading unary operators exposes LaTeX) +$(LI $(BUGZILLA 17534): dlangspec.pdf: 25.24: getFunctionVariadicStyle's tables goes over the page margin and uses HTML) +$(LI $(BUGZILLA 17535): dlangspec.pdf: enforce a maximal width for all code examples) +$(LI $(BUGZILLA 17536): dlangspec.pdf: Unittests documentation uses HTML) +$(LI $(BUGZILLA 17538): dlangspec.pdf: 33.14 Comparing D Immutable and Const with C++ Const goes over the page margin) +$(LI $(BUGZILLA 17723): Replace Facebook on the front page with Weka.io) +$(LI $(BUGZILLA 17925): [Contract Programming]) +$(LI $(BUGZILLA 17993): 404 Not Found: phobos/ddmd_utf.html) +$(LI $(BUGZILLA 18032): [Home] Print hex dump example doesn't run) +$(LI $(BUGZILLA 18067): Benchmark example is broken on the frontpage) +$(LI $(BUGZILLA 18081): dlangspec.pdf: don't escape dollars in code examples) +$(LI $(BUGZILLA 18082): Ubuntu/Debian repository installation should mention dub) +) +$(BUGSTITLE_BUGZILLA Tools bugs, + +$(LI $(BUGZILLA 7997): Optlink issues 'Index Range' error with static zero length array) +) +) +$(D_CONTRIBUTORS_HEADER 57) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR abaga129) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR aldacron) + $(D_CONTRIBUTOR Alexandru Caciulescu) + $(D_CONTRIBUTOR Alexandru Jercaianu) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Benoit Rostykus) + $(D_CONTRIBUTOR Brad Roberts) + $(D_CONTRIBUTOR Chris Coutinho) + $(D_CONTRIBUTOR Dashster) + $(D_CONTRIBUTOR Dmitry Olshansky) + $(D_CONTRIBUTOR Dragos Carp) + $(D_CONTRIBUTOR dukc) + $(D_CONTRIBUTOR Eduard Staniloiu) + $(D_CONTRIBUTOR H. S. Teoh) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Ilya Yaroshenko) + $(D_CONTRIBUTOR Jack Stouffer) + $(D_CONTRIBUTOR Jean-Louis Leroy) + $(D_CONTRIBUTOR JinShil) + $(D_CONTRIBUTOR Joakim Noah) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR Jon Degenhardt) + $(D_CONTRIBUTOR Jonathan M Davis) + $(D_CONTRIBUTOR Jonathan Marler) + $(D_CONTRIBUTOR Jordi Sayol) + $(D_CONTRIBUTOR Kevin De Keyser) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR Kotet) + $(D_CONTRIBUTOR Laeeth Isharc) + $(D_CONTRIBUTOR Leandro Lucarella) + $(D_CONTRIBUTOR Lucia Mcojocaru) + $(D_CONTRIBUTOR Martin Krejcirik) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR MetaLang) + $(D_CONTRIBUTOR n8sh) + $(D_CONTRIBUTOR Nemanja Boric) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Oleg Nykytenko) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Robert burner Schadek) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR skl131313) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Temtaime) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR yashikno) + $(D_CONTRIBUTOR Yuxuan Shui) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.078.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.078.1.dd b/changelog/2.078.1.dd new file mode 100644 index 0000000000..f22774405a --- /dev/null +++ b/changelog/2.078.1.dd @@ -0,0 +1,52 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 21, 2018, =================================================, + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 16621): [REG2.060] DMD hang in semantic3 on alias this) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 13742): undefined reference to __coverage) +$(LI $(BUGZILLA 18111): unittests get different names depending on how the files are passed to dmd) +$(LI $(BUGZILLA 18233): building with -m64 doesn't work with sc.ini from the zip distribution and VS2017) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 18215): std.array.replace throws a range violation if the from range is longer than the array) +$(LI $(BUGZILLA 18244): Generic functions in std.math cannot be overloaded) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 18193): module config is in file 'rt/config.d' which cannot be read) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 16017): package functions show up in std.experimental.allocator.common docs) +) +) +$(D_CONTRIBUTORS_HEADER 8) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Eugen Wissner) + $(D_CONTRIBUTOR growlercab) + $(D_CONTRIBUTOR H. S. Teoh) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.078.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.078.2.dd b/changelog/2.078.2.dd new file mode 100644 index 0000000000..a9a2479d4e --- /dev/null +++ b/changelog/2.078.2.dd @@ -0,0 +1,38 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 07, 2018, =================================================, + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 18352): [REG 2.078] dmd can't generate 64-bit binaries on Windows 10 with VS 2015) +$(LI $(BUGZILLA 18354): [Reg 2.078] Building fails with VC 2015 Build Tools) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 18315): wrong code for `int.min > 0`) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 18252): [Reg 2.078] comparison of arrays of associative arrays no longer compiles) +) +) +$(D_CONTRIBUTORS_HEADER 4) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Sebastian Wilzbach) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.078.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.078.3.dd b/changelog/2.078.3.dd new file mode 100644 index 0000000000..dceca3450e --- /dev/null +++ b/changelog/2.078.3.dd @@ -0,0 +1,32 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 15, 2018, =================================================, + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 18403): [REG2.078.2] Access violation when dmd tries to print highlighted code) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 17752): Switch skips over declaration issued for explicitly uninitialized variables) +) +) +$(D_CONTRIBUTORS_HEADER 3) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Sebastian Wilzbach) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.078.3 + TITLE=Change Log: $(VER) diff --git a/changelog/2.079.0.dd b/changelog/2.079.0.dd new file mode 100644 index 0000000000..39fb326f85 --- /dev/null +++ b/changelog/2.079.0.dd @@ -0,0 +1,1664 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 01, 2018, =================================================, + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 argument-mismatch,Argument mismatch errors have been improved)) +$(LI $(RELATIVE_LINK2 comma-deprecation-error,The deprecation period of using the result of comma expression has ended)) +$(LI $(RELATIVE_LINK2 default_after_variadic,Function parameters with default values are now allowed after variadic template parameters)) +$(LI $(RELATIVE_LINK2 deprecate_delete,The `delete` keyword has been deprecated.)) +$(LI $(RELATIVE_LINK2 deprecation-dylib,The deprecation period of the `-dylib` flag on OSX has ended. Use `-shared`)) +$(LI $(RELATIVE_LINK2 dip1008,Experimental `@nogc` Exception throwing with `-dip1008`)) +$(LI $(RELATIVE_LINK2 disabled-trait,A compiler trait used to detect if a function is marked with `@disable` has been added.)) +$(LI $(RELATIVE_LINK2 fix17630,Fix Issue 17630 - selective imports find symbols in private imports of other modules)) +$(LI $(RELATIVE_LINK2 fix17899,Fix issue 17899 - Allow delegates to be initialised at compile time)) +$(LI $(RELATIVE_LINK2 fix18053,Fix Issue 18053 - mangle long/ulong as int64_t/uint64_t)) +$(LI $(RELATIVE_LINK2 fix18219,Fix Issue 18219 - Private import inside struct leaks symbols when used as VarDeclaration types)) +$(LI $(RELATIVE_LINK2 fix18361,Fix issue 18361 - Ddoc ability to opt-out of automatic keyword highlighting in running text)) +$(LI $(RELATIVE_LINK2 fix8207,D ABI change on Win32 and OSX targets)) +$(LI $(RELATIVE_LINK2 hexstrings,HexString literals are deprecated.)) +$(LI $(RELATIVE_LINK2 includeimports,Added the `-i` command line option to automatically include imports)) +$(LI $(RELATIVE_LINK2 json_includes,Added `-Xi=` to include more fields in the JSON output)) +$(LI $(RELATIVE_LINK2 lambdacomp,Lambda comparison using `__traits(isSame, ...)`)) +$(LI $(RELATIVE_LINK2 lld_mingw,Windows: Visual C++ and the Windows SDK are no longer required to build 64-bit executables)) +$(LI $(RELATIVE_LINK2 minimal_runtime,Using D with no/minimal/custom runtime implementation in a pay-as-you-go fashion)) +$(LI $(RELATIVE_LINK2 osx-10_9,macOS deployment target was increased to 10.9)) +$(LI $(RELATIVE_LINK2 private,Deprecate the use of selectively imported private members)) +$(LI $(RELATIVE_LINK2 ptr-safe-end-of-deprecation,`.ptr` on arrays can no longer be used in `@safe` code)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 core-memory-__delete,`core.memory.__delete` has been added)) +$(LI $(RELATIVE_LINK2 lazy-gc-init,The garbage collector is now lazily initialized on first use)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 compile-time-format-optimized,`std.format` with strings passed during compile-time has been optimized)) +$(LI $(RELATIVE_LINK2 fix18397,Changed `std.conv.hexString` to return an immutable string literal)) +$(LI $(RELATIVE_LINK2 nullable-class,`Nullable!C.nullify` no longer calls .destroy when `C` is a class or interface)) +$(LI $(RELATIVE_LINK2 std-algorithm-iteration-substitute,`std.algorithm.iteration.substitute` was added)) +$(LI $(RELATIVE_LINK2 std-bigint-divmod,`divMod` was added to std.bigint.)) +$(LI $(RELATIVE_LINK2 std-bigint-getDigit,`getDigit` Was Added To `std.bigint`)) +$(LI $(RELATIVE_LINK2 std-exception-enforce,std.exception.enforce can now be used as an eponymous template to create your own enforce function)) +$(LI $(RELATIVE_LINK2 std-experimental-all,`import std.experimental.all` as a global convenience import)) +$(LI $(RELATIVE_LINK2 std-experimental-allocator-rciallocator,Replace `std.experimental.allocator.IAllocator` with `std.experimental.allocator.RCIAllocator`)) +$(LI $(RELATIVE_LINK2 std-experimental-allocator-rcisharedallocator,Replace `std.experimental.allocator.ISharedAllocator` with `std.experimental.allocator.RCISharedAllocator`)) +$(LI $(RELATIVE_LINK2 std-file-readText,readText now checks BOMs)) +$(LI $(RELATIVE_LINK2 std-parallelism-fold,`fold` is added to `std.parallelism.TaskPool`)) +$(LI $(RELATIVE_LINK2 std-range-nullsink,`nullSink` was added to `std.range`)) +$(LI $(RELATIVE_LINK2 std-range-slide,`std.range.slide` (a fixed-size sliding window range) was added)) +$(LI $(RELATIVE_LINK2 std-string-strip,`std.string.strip` now accepts a string of characters to be stripped)) +$(LI $(RELATIVE_LINK2 std-traits-issomestring,isSomeString and isNarrowString are now `false` for enums)) +$(LI $(RELATIVE_LINK2 toString,`toString` Can Now Use Output Ranges)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 argument-mismatch,Argument mismatch errors have been improved) +$(P +$(P `dmd` now shows which argument failed to match a parameter with an explanatory error message.) +) +--- +void fill(ref char[16] buf, char c); + +void main() +{ + fill("1234567890123456", '*'); + + const char[16] s; + fill(s, '*'); +} +--- +$(P +$(P Output:) +$(CONSOLE +fillchar.d(5): Error: function `fillchar.fill(ref char[16] buf, char c)` is not callable using argument types `(string, char)` +fillchar.d(5): cannot pass rvalue argument `"1234567890123456"` of type `string` to parameter `ref char[16] buf` +fillchar.d(8): Error: function `fillchar.fill(ref char[16] buf, char c)` is not callable using argument types `(const(char[16]), char)` +fillchar.d(8): cannot pass argument `s` of type `const(char[16])` to parameter `ref char[16] buf` +) +$(P Note: Currently this change doesn't apply when the function has overloads.) +) +) + +$(LI $(LNAME2 comma-deprecation-error,The deprecation period of using the result of comma expression has ended) +$(P +Comma expressions have proven to be a frequent source of confusion, and bugs. +Using their result will now trigger an error message. +) + +$(P +$(P The comma operator (`,`) allows executing multiple expressions and + discards the result of them except for the last which is returned. +) + + --- + int a = 1; + int b = 2; + bool ret = a == 2, b == 2; // true + --- + +$(P + It's also common to use the comma operator in for-loop increment + statements to allow multiple expressions. +) + + --- + for (; !a.empty && !b.empty; a.popFront, b.popFront) + --- + +$(P + Hence, using the comma operator in for-loop increment statements is still allowed. +) +$(H4 Corrective Action) +$(P If possible, split the comma operator in two statements. Otherwise use + lambdas. +) + + --- + auto result = foo(), bar(); + + // split off in two statements + foo(); + auto result = bar(); + + // or use lambdas + auto result = {foo(); return bar();}(); + --- +$(P +) +$(H4 Rationale) +$(P The comma operator leads to unintended behavior (see below for a selection) + Moreover it is not commonly used and it blocks the ability to implement tuples + as a language feature using commas. +) + +$(P + A selection of problems through the accidental use of the comma operator: +) + --- + writeln( 6, mixin("7,8"), 9 ); // 6, 8, 9 + + struct Vec + { + this(T...)(T args) { ... } + } + // missing type name + Vec v = (0, 0, 3); // Vec(3) + + int a = 0; + int b = 2; + if (a == 1, b == 2) { + // will always be reached + } + + void foo(int x, int y=0) {} + foo((a, b)); // Oops, foo(b) is called + + synchronized (lockA, lockB) {} + // multiple expressions aren't currently implemented, but it compiles due to the comma operator + --- +$(P +) +) +) + +$(LI $(LNAME2 default_after_variadic,Function parameters with default values are now allowed after variadic template parameters) +$(P +Function parameters with default values are now allowed after variadic template parameters +and when IFTI is used, always take their default values. +This allows using special tokens (eg `__FILE__`) after variadic parameters, which was previously impossible. +) + +$(P +For example: +) + +--- +string log(T...)(T a, string file = __FILE__, int line = __LINE__) +{ + return text(file, ":", line, " ", a); +} + +assert(log(10, "abc") == text(__FILE__, ":", __LINE__, " 10abc")); +--- + +$(P +This should be preferred to the previous workaround, which causes a new template instantiation +for every invocation: +) +--- +string log(string file = __FILE__, int line = __LINE__, T...)(T a); +--- +) + +$(LI $(LNAME2 deprecate_delete,The `delete` keyword has been deprecated.) +$(P +See the $(LINK2 $(ROOT_DIR)deprecate.html#delete, Deprecated Features) for more information. +) + +$(P +Starting with this release, using the `delete` keyword will result in a deprecation warning. +) + +$(P +As a replacement, users are encouraged to use $(REF1 destroy, object) +if feasible, or $(REF __delete, core,memory) as a last resort. +) +) + +$(LI $(LNAME2 deprecation-dylib,The deprecation period of the `-dylib` flag on OSX has ended. Use `-shared`) +$(P +The deprecation period of the `-dylib` flag on OSX has ended. +) + +$(P +$(CONSOLE dmd -dylib awesome_d_library.d) +) + +$(P +Use the `-shared` flag to generate a shared library: +) + +$(P +$(CONSOLE dmd -shared awesome_d_library.d) +) +) + +$(LI $(LNAME2 dip1008,Experimental `@nogc` Exception throwing with `-dip1008`) +$(P +$(HTTPS github.com/dlang/DIPs/blob/master/DIPs/DIP1008.md, DIP 1008) has been merged and it can be previewed under the experimental `-dip1008` flag: +) + +--- +void main() @nogc +{ + throw new Exception("I'm @nogc now"); +} +--- + +$(P +$(CONSOLE rdmd -dip1008 app.d) +) +) + +$(LI $(LNAME2 disabled-trait,A compiler trait used to detect if a function is marked with `@disable` has been added.) +$(P +Prior to this release is was impossible to filter out `@disable` functions without +using `__trait(compiles)`, which was less than ideal since `false` could be +returned for other reasons. +) + +$(P +Now, in metaprogramming code, `@disable` functions can be detected accurately, +using `__traits(isDisabled)` and even in overload sets: +) + +--- +module runnable; + +struct Foo +{ + import std.stdio; + @disable static void foo() {__PRETTY_FUNCTION__.writeln;} + static void foo(int v) {__PRETTY_FUNCTION__.writeln;} + static void bar() {__PRETTY_FUNCTION__.writeln;} + @disable static void bar(int v) {__PRETTY_FUNCTION__.writeln;} +} + +void test(T)() +{ + foreach (member; __traits(allMembers, T)) + foreach (overload; __traits(getOverloads, T, member)) + static if (!__traits(isDisabled, overload)) + { + static if (is(typeof(&overload) == void function())) + overload(); + else static if (is(typeof(&overload) == void function(int))) + overload(42); + } +} + +void main(){test!Foo;} +--- + +$(P +prints: +) + +$(P +$(CONSOLE +void runnable.Foo.foo(int v) +void runnable.Foo.bar() +) +) +) + +$(LI $(LNAME2 fix17630,Fix Issue 17630 - selective imports find symbols in private imports of other modules) +$(P +Selectively importing a symbol should work only if the symbol +imported is defined or publicly imported in the imported module. +Due to a compiler bug, selectively importing a symbol works even +if the symbol is defined in a privately imported module in the +imported module. +) +----------------------------------------------------------- +//a.d +int bar; + +//b.d +import a; + +//c.d +import b : bar; +------------------------------------------------------------ +$(P +The above code will now result in a deprecation message +which states that `bar` cannot be accessed since it is +privately imported in `b`. +) +) + +$(LI $(LNAME2 fix17899,Fix issue 17899 - Allow delegates to be initialised at compile time) +$(P +delegates may now be initialised at module scope. This changes the effect of the fix for 13259 (turning the ICE that resulted into an error) making the follow legal: +) +--- +void delegate() bar = (){}; +--- + +$(P +The function pointer is set to the function of the delegate, the context pointer is set to null. +) +) + +$(LI $(LNAME2 fix18053,Fix Issue 18053 - mangle long/ulong as int64_t/uint64_t) +$(P +This is a breaking change (on OSX 64). +) + +$(P +Due to the erratic implementation defined behavior of C++ name mangling, it was +difficult to get D's long/ulong to portably match up with the corresponding +C++ compiler. +) + +$(P +By instead relying on how the corresponding C++ compiler mangled int64_t/uint64_t +it makes the C++ side of the D<=>C++ interface much simpler. +) + +$(P +For the current platforms dmd supports, only the OSX 64 bit mangling changes. In +this case from 'm' to 'y'. +) + +$(P +Note: + int64_t and uint64_t are defined in stdint.h +) +) + +$(LI $(LNAME2 fix18219,Fix Issue 18219 - Private import inside struct leaks symbols when used as VarDeclaration types) +$(P +When implementing a struct which has a local private import +the imported symbols are leaked if present in a VarDeclaration statement. For more information and examples see : https://issues.dlang.org/show_bug.cgi?id=18219 +) + +$(P +Symbols from the private import should not visible outside the +struct scope. A deprecation is now issued when such cases are +encountered +) +) + +$(LI $(LNAME2 fix18361,Fix issue 18361 - Ddoc ability to opt-out of automatic keyword highlighting in running text) +$(P +Currently, ddoc automatically highlights all occurrences of words in running +text that coincide with the symbol or module being documented, or a parameter +name of a function being documented. While convenient, it often caused +unintended highlighting of normal words in text when module, function, or +parameter identifiers coincide with normal words. This led to a proliferation +of prefixing words with `_` in order to suppress this behaviour. +) + +$(P +Now a better solution has been implemented to completely opt-out of this +feature via the `DDOC_AUTO_PSYMBOL`, `DDOC_AUTO_KEYWORD`, and `DDOC_AUTO_PARAM` +macros, which are used for all such automatically-highlighted words in running +text. Occurrences of module, function, or parameter names inside code blocks +are not included. By default, these macros simply redirect to `DDOC_PSYMBOL`, +`DDOC_KEYWORD`, and `DDOC_PARAM`, but the user can now redefine these macros so +that they simply expand to the word itself without any highlighting: +) + +---- +DDOC_AUTO_PSYMBOL = $(DOLLAR)0 +DDOC_AUTO_KEYWORD = $(DOLLAR)0 +DDOC_AUTO_PARAM = $(DOLLAR)0 +---- + +$(P +Furthermore, whenever a word is prefixed with `_` to suppress automatic +highlighting, it is now wrapped in the `DDOC_AUTO_PSYMBOL_SUPPRESS` macro. This +is to provide users who wish to opt out of automatic highlighting an easy way +to find all occurrences of these underscore prefixes so that they can be +removed from the text. For example, they can redefine this macro to something +highly-visible and easily searched for, such as: +) + +---- +DDOC_AUTO_PSYMBOL_SUPPRESS = FIXME_UNDERSCORE_PREFIX $0 +---- + +$(P +and then search the generated documentation for the string +`FIXME_UNDERSCORE_PREFIX` and delete the `_` prefix from all corresponding +parts of the documentation comment text. +) +) + +$(LI $(LNAME2 fix8207,D ABI change on Win32 and OSX targets) +$(P +The compiler has been updated to prefix all `extern(D)` symbols with an extra +underscore where the platform expects one on all external symbols. This allows +compiled code to work better with binutil programs, such as the ability to list +symbols demangled inside a debugger. +) + +$(P +This is an ABI breaking change and requires recompiling libraries. +) +) + +$(LI $(LNAME2 hexstrings,HexString literals are deprecated.) +$(P +$(LINK2 http://dlang.org/spec/lex.html#HexString, HexString literals) are deprecated. +Use $(LINK2 https://dlang.org/phobos/std_conv.html#hexString, `std.conv.hexString`) instead. +) +) + +$(LI $(LNAME2 includeimports,Added the `-i` command line option to automatically include imports) +$(P +Added the command line option `-i` which causes the compiler to treat imported modules as if they were given on the command line. The option also accepts "module patterns" that include/exclude modules based on their name. For example, the following will include all modules whose names start with `foo`, except for those that start with `foo.bar`: +) + +$(P +$(CONSOLE dmd -i=foo -i=-foo.bar) +) + +$(P +The option `-i` by itself is equivalent to: +) + +$(P +$(CONSOLE dmd -i=-std -i=-core -i=-etc -i=-object) +) +) + +$(LI $(LNAME2 json_includes,Added `-Xi=` to include more fields in the JSON output) +$(P +Added `-Xi=` to include more fields in the JSON output. Currently there are 4 fields that can be included: "compilerInfo", "buildInfo", "modules" and "semantics", i.e. +) + +$(P +$(CONSOLE dmd -Xi=compilerInfo -Xi=buildInfo -Xi=semantics -Xi=modules) +) + +$(P +will generate a JSON file with the following: +) +--- +{ + "compilerInfo" : { + "binary" : "", + "version" : "", + "supportsIncludeImports" : true, + }, + "buildInfo" : { + "config" : "", + "cwd" : "", + "importParths" : [ + "", + "", + // ... + ] + }, + "semantics" : { + "modules" : [ + { + "name" : "", + "file" : "", + "isRoot" : true|false + }, + // more module objects... + ] + }, + "modules" : [ + // an array of the syntax data for all the modules, + // this is the same array that would be generated + // for a JSON file with no -Xi= options + ] +} +--- +$(P +If JSON is generated without any `-Xi=` options then the old format is used. The old format is the same data that would appear in the new "modules" field. +) + +$(P +Also note that the compiler can now be invoked with no source files as long as at least one JSON field is provided, i.e. +) + +$(P +$(CONSOLE dmd -Xi=compilerInfo) +) + +$(P +$(RED This is an experimental command-line flag and will be stabilized in the next release.) +) +) + +$(LI $(LNAME2 lambdacomp,Lambda comparison using `__traits(isSame, ...)`) +$(P +It is now possible to compare two lambda functions, under certain +constraints, using `__traits(isSame, lamda1, lambda2)`. In order to +correctly compare two lambdas, the following conditions must be +satisfied: +) + +$(P +$(UL + $(LI the lambda function arguments must not have a template instantiation + as an explicit argument type. Any other argument types (basic, + user-defined, template) are supported.) + $(LI the lambda function body must contain a single expression (no return statement) + which contains only numeric values, manifest constants, enum values and arguments. + If the expression contains local variables, function calls or return statements, + the function is considered uncomparable.) +) +) + +$(P +These limitations might be lifted in the next release version. +) + +$(P +Whenever a lambda is considered uncomparable, the `__traits(isSame, ...)` expression +in which it's used will return false, no matter what other lambda is used in +the comparison. +) +) + +$(LI $(LNAME2 lld_mingw,Windows: Visual C++ and the Windows SDK are no longer required to build 64-bit executables) +$(P +The Windows installer now adds platform libraries built from the MinGW definitions and +a wrapper library for the VC2010 shared C runtime. When building COFF object files with +`-m64` or `-m32mscoff` and no Visual Studio installation is detected or +no platform libraries are found these will be used as replacements. If the Microsoft linker +is not found, the LLVM linker LLD will be used. +) +) + +$(LI $(LNAME2 minimal_runtime,Using D with no/minimal/custom runtime implementation in a pay-as-you-go fashion) +$(P +$(P DMD has been further decoupled from the runtime so it is now easier and more +convenient to use D without the runtime in a pay-as-you-go fashion. This will +be of interest to users wishing to incrementally or partially port D to new +platforms, users targeting bare-metal or resource constrained platforms, and +users wishing to use D as a library from other languages without the runtime.) +) + +$(P +$(P Prior to this release, if one attempted to compile a simple D application that +made no use of any runtime features, the compiler would have emitted a number +of errors about a missing object.d, a missing `Error` class, missing `TypeInfo`, +and missing `ModuleInfo`, among others.) +) + +$(P +$(P Starting with this release, one can now create a library for use from another +language, requiring only the `.d` source file that implements that library, and +an empty `object.d` file) +) + +$(P +$(B Example 1) +) +--- +module object +--- + +--- +module math; + +extern(C) int add(int a, int b) +{ + return a + b; +} +--- + +$(P +$(CONSOLE +dmd -conf= -lib math.d +size math.a + text data bss dec hex filename + 0 0 0 0 0 math.o (ex math.a) + 20 0 0 20 14 math_1_129.o (ex math.a) +) +) + +$(P +$(P Also, starting with this release, one can now create very small executables +with a minimal runtime implementation.) +) + +$(P +$(B Example 2) +$(P DMD auto-generates a call to `_d_run_main` which, in turn, calls the user-defined +`main` function. DMD automatically generates a call to `g++` which links in the C runtime.) +) +--- +module object; + +private alias extern(C) int function(char[][] args) MainFunc; +private extern (C) int _d_run_main(int argc, char** argv, MainFunc mainFunc) +{ + return mainFunc(null); // assumes `void main()` for simplicity +} +--- + +--- +module main; + +void main() { } +--- + +$(P +$(CONSOLE +dmd -conf= -defaultlib= -fPIC main.d object.d -of=main +size main + text data bss dec hex filename + 1403 584 16 2003 7d3 main +) +) + +$(P +$(B Example 3) +$(P Manually generated call to `main`. No C runtime.) +) +--- +module object; + +extern(C) void __d_sys_exit(long arg1) +{ + asm + { + mov RAX, 60; + mov RDI, arg1; + syscall; + } +} + +extern void main(); +private extern(C) void _start() +{ + main(); + __d_sys_exit(0); +} +--- + +--- +module main; + +void main() { } +--- + +$(P +$(CONSOLE +dmd -c -lib main.d object.d -of=main.o +ld main.o -o main +size main + text data bss dec hex filename + 56 0 0 56 38 main +) +) + +$(P +$(P Usage of more advanced D features (e.g. classes, exceptions, etc...) will require +runtime implementation code, but they can be implemented in a pay-as-you-go fashion.) +) +) + +$(LI $(LNAME2 osx-10_9,macOS deployment target was increased to 10.9) +$(P +The compiler has been updated to use 10.9 and link with `libc++` on OSX. +This is due the shared `libstdc++` library from older versions of macOS +having compatibility issues with the headers included in a modern XCode. +) + +$(P +The minimum required version of running the compiler is now Mac OS X Mavericks (10.9). +) +) + +$(LI $(LNAME2 private,Deprecate the use of selectively imported private members) +$(P +$(LINK2 $(ROOT_DIR)spec/attribute.html#visibility_attributes, The specification states) that a private member +is visible only from within the same module. +Prior to this release, due to a bug, private members +were visible through selective imports from other modules, violating the specification. +Beginning with this release, accessing private members from outside the module +in which they are declared will result in a deprecation message. +) +) + +$(LI $(LNAME2 ptr-safe-end-of-deprecation,`.ptr` on arrays can no longer be used in `@safe` code) +$(P +The deprecation period for using `.ptr` on arrays in `@safe` ended. +The following now triggers an error instead of a deprecation: +) + +--- +@safe ubyte* oops(ubyte[] arr) { + return arr.ptr; +} +--- + +$(P +Use `&arr[0]` instead: +) + +--- +@safe ubyte* oops(ubyte[] arr) { + return &arr[0]; +} +--- + +$(P +Note that this only applies to SafeD - in `@system` code `.ptr` may still be used: +) + +--- +@system ubyte* oops(ubyte[] arr) { + return arr.ptr; +} +--- +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 core-memory-__delete,`core.memory.__delete` has been added) +$(P +$(REF __delete, core, memory) allows easy migration from the deprecated `delete`. +`__delete` behaves exactly like `delete`: +) + +--- +bool dtorCalled; +class B +{ + int test; + ~this() + { + dtorCalled = true; + } +} +B b = new B(); +B a = b; +b.test = 10; + +__delete(b); +assert(b is null); +assert(dtorCalled); +// but be careful, a still points to it +assert(a !is null); +--- + +$(P +For example, on a Posix platform you can simply run: +) + +$(P +$(CONSOLE +`sed "s/delete \(.*\);/__delete(\1);/" -i **/*.d` +) +) + +$(P +Users should prefer $(REF destroy, object)` to explicitly finalize objects, +and only resort to $(REF __delete, core,memory) when $(REF destroy, object) +would not be a feasible option. +) +) + +$(LI $(LNAME2 lazy-gc-init,The garbage collector is now lazily initialized on first use) +$(P +The runtime now lazily initializes the GC on first use, thus allowing applications that do not use the GC to skip its initialization. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 compile-time-format-optimized,`std.format` with strings passed during compile-time has been optimized) +$(P +Giving $(REF format, std, format) a string as a template parameter allows +the type correctness of the parameters to be checked at compile time: +) + +------- +import std.format : format; + +auto s1 = format!"%d"(4); // works fine +auto s2 = format("%d"); // runtime exception +auto s3 = format!"%d"(); // compile time error +------- + +$(P +Now, using this overload also allows std.format to make an educated guess at +the length of the resulting string, reducing the total number of reallocations +made to the output buffer. +) + +------- +import std.format : format; + +auto s1 = format!"%02d:%02d:%02d"(10, 30, 50); // known for certain to be 8 chars long +auto s2 = format!"%s %d"("Error Code: ", 42); // Makes an educated guess +------- + +$(P +Longer format strings benefit the most from this change. +) +) + +$(LI $(LNAME2 fix18397,Changed `std.conv.hexString` to return an immutable string literal) +$(P +$(REF hexString, std,conv) now returns an immutable string literal rather than an array of ubytes. +This is more in keeping with +the documentation that says it is a replacement for the deprecated +`x"deadbeef"` string literal syntax. +) + +$(P +The benefits of this change are: +) + +$(P +$(UL + $(LI behavior consistency with the documentation) + $(LI the `hexString` template instantiations no longer appear in the generated object file) + $(LI the generated object file no longer contains references to `TypeInfo` and various druntime functions) + $(LI it is now compatible with `-betterC` mode) +) +) + +$(P +In some cases, code did rely on it being an array, and a cast will +fix the issue: +) + +--- +// now an error: +enum ubyte[8] input = hexString!"c3 fc 3d 7e fb ea dd aa"; +--- + +--- +// add cast to fix: +enum ubyte[8] input = cast(ubyte[8]) hexString!"c3 fc 3d 7e fb ea dd aa"; +--- +) + +$(LI $(LNAME2 nullable-class,`Nullable!C.nullify` no longer calls .destroy when `C` is a class or interface) +$(P +Previously, when `.nullify` is called on a `Nullable!C` where `C` is a class or +interface, the underlying object is destructed immediately via the `.destroy` +function. This led to bugs when there are still references to the object +outside of the `Nullable` instance: +) + +------ +class C +{ + int canary = 0xA71FE; + ~this() + { + canary = 0x5050DEAD; + } +} + +auto c = new C; +assert(c.canary == 0xA71FE); + +Nullable!C nc = nullable(c); +nc.nullify; +assert(c.canary == 0xA71FE); // This would fail +------ + +$(P +The `.nullify` method has been fixed so that it no longer calls `.destroy` on +class or interface instances, and the above code will now work correctly. +) +) + +$(LI $(LNAME2 std-algorithm-iteration-substitute,`std.algorithm.iteration.substitute` was added) +$(P +$(REF substitute, std,algorithm,iteration) yields a lazy range with +all occurrences of the substitution patterns in `r` replaced with their substitution: +) + +--- +import std.algorithm.comparison : equal; +import std.algorithm.iteration : substitute; + +// substitute single elements +assert("do_it".substitute('_', ' ').equal("do it")); + +// substitute multiple, single elements +assert("do_it".substitute('_', ' ', + 'd', 'g', + 'i', 't', + 't', 'o') + .equal("go to")); + +// substitute subranges +assert("do_it".substitute("_", " ", + "do", "done") + .equal("done it")); + +// substitution works for any ElementType +int[] x = [1, 2, 3]; +auto y = x.substitute(1, 0.1); +assert(y.equal([0.1, 2, 3])); +static assert(is(typeof(y.front) == double)); +--- + +$(P +If the substitution parameters are known at compile-time, the faster +template overload can be used: +) + +--- +import std.algorithm.comparison : equal; +import std.algorithm.iteration : substitute; + +// substitute subranges of a range +assert("apple_tree".substitute!("apple", "banana", + "tree", "shrub").equal("banana_shrub")); + +// substitute elements in a range +assert("apple_tree".substitute!('a', 'b', + 't', 'f').equal("bpple_free")); + +// substitute values +assert('a'.substitute!('a', 'b', 't', 'f') == 'b'); +--- +) + +$(LI $(LNAME2 std-bigint-divmod,`divMod` was added to std.bigint.) +$(P +$(REF divMod, std, bigint) calculates both the quotient and the remainder in one go: +) + +----- +void divMod(const BigInt dividend, const BigInt divisor, out BigInt quotient, out BigInt remainder) pure nothrow +{ +auto a = BigInt(123); +auto b = BigInt(25); +BigInt q, r; + +divMod(a, b, q, r); + +assert(q == 4); +assert(r == 23); +assert(q * b + r == a); +} +----- +) + +$(LI $(LNAME2 std-bigint-getDigit,`getDigit` Was Added To `std.bigint`) +$(P +$(REF getDigit, std, bigint) gives the `ulongs` or `uints` +that make up the underlying representation of the `BigInt`. +) + +----- +import std.bigint; + +auto a = BigInt("1000"); +assert(a.getDigit(0) == 1000); + +auto b = BigInt("2_000_000_000_000_000_000_000_000_000"); +assert(b.getDigit(0) == 4584946418820579328); +assert(b.getDigit(1) == 108420217); +----- +) + +$(LI $(LNAME2 std-exception-enforce,std.exception.enforce can now be used as an eponymous template to create your own enforce function) +$(P +$(REF enforce, std,exception) now mirrors the behavior of $(REF enforceEx, std,exception) +and can be used as an eponymous template: +) + +--- +import std.conv : ConvException; +alias convEnforce = enforce!ConvException; +assertNotThrown(convEnforce(true)); +assertThrown!ConvException(convEnforce(false, "blah")); +--- + +$(P +With this change, $(REF enforce, std,exception) is a strict superset of $(REF enforceEx, std,exception), which will be deprecated in 2.079. +) +) + +$(LI $(LNAME2 std-experimental-all,`import std.experimental.all` as a global convenience import) +$(P +$(MREF std,experimental,all) allows convenient use of all Phobos modules +with one import: +) + +--- +import std.experimental.all; +void main() +{ + 10.iota.map!log.sum.writeln; +} +--- + +$(P +For short scripts a lot of imports are often needed to get all the +modules from the standard library. +With this release it's possible to use `import std.experimental.all` for importing the entire +standard library at once. This can be used for fast prototyping or REPLs: +) + +--- +import std.experimental.all; +void main() +{ + 6.iota + .filter!(a => a % 2) // 0 2 4 + .map!(a => a * 2) // 0 4 8 + .tee!writeln + .sum + .writefln!"Sum: %d"; // 18 +} +--- + +$(P +As before, symbol conflicts will only arise if a symbol with collisions is used. +In this case, $(LINK2 $(ROOT)spec/module.html#static_imports, static imports) or +$(LINK2 $(ROOT)spec/module.html#renamed_imports, renamed imports) can be used +to uniquely select a specific symbol. +) + +$(P +The baseline cost for `import std.experimental.all` +is less than half a second (varying from system to system) and +work is in progress to reduce this overhead even further. +) +) + +$(LI $(LNAME2 std-experimental-allocator-rciallocator,Replace `std.experimental.allocator.IAllocator` with `std.experimental.allocator.RCIAllocator`) +$(P +$(B Motivation): +) + +$(P +Keep track of references to allocators so they don't escape, dangle, +and cause undefined behavior. +) + +$(P +From now on, `RCIAllocator` will be used instead of the old `IAllocator` +interface. $(REF allocatorObject, std, experimental, allocator) can be used to build +a `RCIAllocator` out of a custom allocator. +) + +------ +import std.experimental.allocator.mallocator : Mallocator; + +RCIAllocator a = allocatorObject(Mallocator.instance); +auto b = a.allocate(100); +assert(b.length == 100); +assert(a.deallocate(b)); +------ +) + +$(LI $(LNAME2 std-experimental-allocator-rcisharedallocator,Replace `std.experimental.allocator.ISharedAllocator` with `std.experimental.allocator.RCISharedAllocator`) +$(P +$(B Motivation): +) + +$(P +Keep track of references to allocators so they don't escape, dangle, +and cause undefined behavior. +) + +$(P +From now on, `RCISharedAllocator` will be used instead of the old +`ISharedAllocator` interface. +$(REF sharedAllocatorObject, std, experimental, allocator)` can be used to build +a `RCISharedAllocator` out of a custom allocator. +) + +------ +import std.experimental.allocator.building_blocks.free_list : SharedFreeList; +import std.experimental.allocator.mallocator : Mallocator; + +shared SharedFreeList!(Mallocator, chooseAtRuntime, chooseAtRuntime) sharedFL; +shared RCISharedAllocator sharedFLObj = sharedAllocatorObject(sharedFL); + +auto b = sharedFLObj.allocate(100); +assert(b.length == 100); +assert(sharedFLObj.deallocate(b)); +------ +) + +$(LI $(LNAME2 std-file-readText,readText now checks BOMs) +$(P +$(REF readText, std, file) now checks for a +$(HTTPS en.wikipedia.org/wiki/Byte_order_mark, BOM). If a BOM is present +and it is for UTF-8, UTF-16, or UTF-32, $(REF readText, std, file) verifies +that it matches the requested string type and the endianness of the machine, +and if there is a mismatch, a $(REF UTFException, std, utf) is thrown without +bothering to validate the string. +) + +$(P +If there is no BOM, or if the BOM is not for UTF-8, UTF-16, or UTF-32, then the +behavior is what it's always been, and UTF validation continues as per normal, +so if the text isn't valid for the requested string type, a +$(REF UTFException, std, utf) will be thrown. +) + +$(P +In addition, before the buffer is cast to the requested string type, the +alignment is checked (e.g. 5 bytes don't fit cleanly in an array of $(D wchar) +or $(D dchar)), and a $(REF UTFException, std, utf) is now throw if the +number of bytes does not align with the requested string type. Previously, the +alignment was not checked before casting, so if there was an alignment mismatch, +the cast would throw an Error, killing the program. +) +) + +$(LI $(LNAME2 std-parallelism-fold,`fold` is added to `std.parallelism.TaskPool`) +$(P +$(REF TaskPool.fold, std, parallelism) is functionally equivalent to +$(REF_ALTTEXT TaskPool.reduce, reduce, std, parallelism) except the range +parameter comes first and there is no need to use $(REF_ALTTEXT +`tuple`,tuple,std,typecons) for multiple seeds. +) + +--- +static int adder(int a, int b) +{ + return a + b; +} +static int multiplier(int a, int b) +{ + return a * b; +} + +// Just the range +auto x = taskPool.fold!adder([1, 2, 3, 4]); +assert(x == 10); + +// The range and the seeds (0 and 1 below; also note multiple +// functions in this example) +auto y = taskPool.fold!(adder, multiplier)([1, 2, 3, 4], 0, 1); +assert(y[0] == 10); +assert(y[1] == 24); + +// The range, the seed (0), and the work unit size (20) +auto z = taskPool.fold!adder([1, 2, 3, 4], 0, 20); +assert(z == 10); +--- +) + +$(LI $(LNAME2 std-range-nullsink,`nullSink` was added to `std.range`) +$(P +$(REF nullSink, std, range) is a convenience wrapper for $(REF NullSink, std,range) +and creates an output range that discards the data it receives. It's the range analog +of `/dev/null`. +) + +--- +import std.csv : csvNextToken; + +string line = "a,b,c"; + +// ignore the first column +line.csvNextToken(nullSink, ',', '"'); +line.popFront; + +// look at the second column +Appender!string app; +line.csvNextToken(app, ',', '"'); +assert(app.data == "b"); +--- +) + +$(LI $(LNAME2 std-range-slide,`std.range.slide` (a fixed-size sliding window range) was added) +$(P +$(REF slide, std, range) allows to iterate a range in sliding windows: +) + +--- +import std.array : array; +import std.algorithm.comparison : equal; + +assert([0, 1, 2, 3].slide(2).equal!equal( + [[0, 1], [1, 2], [2, 3]] +)); +assert(5.iota.slide(3).equal!equal( + [[0, 1, 2], [1, 2, 3], [2, 3, 4]] +)); + +assert(iota(7).slide(2, 2).equal!equal([[0, 1], [2, 3], [4, 5]])); +assert(iota(12).slide(2, 4).equal!equal([[0, 1], [4, 5], [8, 9]])); + +// set a custom stepsize (default 1) +assert(6.iota.slide(1, 2).equal!equal( + [[0], [2], [4]] +)); + +assert(6.iota.slide(2, 4).equal!equal( + [[0, 1], [4, 5]] +)); + +// allow slide with less elements than the window size +assert(3.iota.slide!(No.withPartial)(4).empty); +assert(3.iota.slide!(Yes.withPartial)(4).equal!equal( + [[0, 1, 2]] +)); +--- +) + +$(LI $(LNAME2 std-string-strip,`std.string.strip` now accepts a string of characters to be stripped) +$(P +New overload functions of $(REF strip, std, string), +$(REF stripLeft, std, string) and +$(REF stripRight, std, string) accepts a string of characters to be +stripped instead of stripping only whitespace. +) + +--- +import std.string: stripLeft, stripRight, strip; + +assert(stripLeft("www.dlang.org", "w.") == "dlang.org"); +assert(stripRight("dlang.org/", "/") == "dlang.org"); +assert(strip("www.dlang.org/", "w./") == "dlang.org"); +--- +) + +$(LI $(LNAME2 std-traits-issomestring,isSomeString and isNarrowString are now `false` for enums) +$(P +Previously, enums whose base type was a string type were `true` for +$(REF isSomeString, std, traits) and $(REF isNarrowString, std, traits). +Occasionally, this was useful, but in general, it was a source of bugs, because +code that works with strings does not necessarily work with enums whose base +type is a string, making it easy to write code where an enum would pass the +template constraint and then the template would fail to compile. For instance, +enums of base type string are `false` for +$(REF isInputRange, std, range, primitives). As such, it really doesn't make +sense for $(REF isSomeString, std, traits) and +$(REF isNarrowString, std, traits) to be `true` for enums. +) + +$(P +For some code, this will be a breaking change, but most code will either be +unaffected, or it will then fail with enums at the template constraint instead +of inside the function. So, the risk of code breakage is minimal but does exist. +Other code will now be able to remove stuff like `!is(T == enum)` from its +template constraints, since that is now part of +$(REF isSomeString, std, traits) and $(REF isNarrowString, std, traits), but +it will continue to compile with the now unnecessary check for enums. +) + +$(P +Code that uses $(REF isSomeString, std, traits) or +$(REF isNarrowString, std, traits) in a template constraint and has no other +conditions which would prevent enums from passing the constraint but then would +fail to compile inside the template if an enum were passed to it will now fail +to compile at the template constraint instead of inside the template. So, such +code is fixed rather than broken. +) + +$(P +The rare code that does break because of these changes is code that uses +$(REF isSomeString, std, traits) or $(REF isNarrowString, std, traits) in a +template constraint or static if and does not use other conditions to prevent enums +from passing and actually has code in the template which compiles with both strings +and enums with a base type of string. Such code will need to be changed to use +$(REF OriginalType, std, traits), $(REF asOriginalType, std, conv), or +$(REF StringTypeOf, std, traits) instead. e.g. for enums to pass the constraint, +instead of +) + +--- +auto foo(S)(S str) +if (isSomeString!S) +{ + ... +} +--- + +$(P +the code would be +) + +--- +auto foo(S)(S str) +if (isSomeString!(OriginalType!S)) +{ + ... +} +--- + +$(P +As a rule of thumb, generic code should either disallow implicit conversions +and force the caller to do the conversion explicitly (which generally is the +least error-prone approach), or it should force the conversion to the desired +type before the parameter is used in the function so that the function is +definitely operating on the desired type and not just on one that implicitly +converts to it and thus will work regardless of whether the argument was the +exact type or implicitly converted to it. +) + +$(P +However, great care should be taken if the implicit conversion will result in +slicing the parameter or otherwise referring to its address, since that makes +it very easy for a reference to local memory to escape the function, whereas if +the conversion is done at the call site, then the slicing is done at the call +site, so the dynamic array is still valid when the function returns. +Fortunately, enums with a base type of string do not have that problem, but +other types which implicitly convert to dynamic arrays (such as static arrays) +do have that problem, which is a big reason why it's generally recommended to +not have generic functions accept types based on implicit conversions. +) + +$(P +It is recommended that if a function is supposed to accept both strings and +types which implicitly convert to a string type, then it should explicitly +accept dynamic arrays but be templated on the element type. e.g. +) + +--- +auto foo(C)(C[] str) +if (isSomeChar!C) +{ + ... +} +--- + +$(P +That way, any implicit conversions are done at the call site and do not +introduce @safety problems inside the function. It also tends to result in +template constraints which are shorter and more easily understood. +) +) + +$(LI $(LNAME2 toString,`toString` Can Now Use Output Ranges) +$(P +The standard library has been modified to recognize and use `toString` overloads +that accept $(REF_ALTTEXT output ranges, isOutputRange, std, range, primitives) +when such overloads exist. +) + +------- +import std.range.primitives; +import std.stdio; + +struct MyType +{ + void toString(W)(ref W writer) if (isOutputRange!(W, char)) + { + put(writer, "Custom toString"); + } +} + +auto t = MyType(); +writeln(t); // writes "Custom toString" +------- + +$(P +This has several benefits for the user. First, this design is much friendlier +to inlining than the `toString(scope void delegate(const(char)[]) sink)` method of +`toString`. Second, this cuts down on memory usage, as characters are placed right +into the output buffers of functions like $(REF format, std, format). Third, +because `toString` is now a template, can be marked `@safe` via inference much more +often. +) + +$(P +All previous forms of `toString` will continue to work. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 17605): [REG2.066.0] __traits$(LPAREN)compiles, closure$(RPAREN) adds link-time reference to _d_allocmemory) +$(LI $(BUGZILLA 17970): shared struct destructor doesn't compile anymore) +$(LI $(BUGZILLA 18030): Segmentation fault with __traits$(LPAREN)getProtection$(RPAREN) on template function.) +$(LI $(BUGZILLA 18093): [Reg 2.071] MSCOFF: dmd crashes when overriding a C++ method in a mixin template) +$(LI $(BUGZILLA 18097): [REG2.077] Unittest function is undefined identifier) +$(LI $(BUGZILLA 18296): [Reg2.078.1] invalid code with coverage and copy construction) +$(LI $(BUGZILLA 18322): void fun$(LPAREN)string file=__FILE_FULL_PATH__$(RPAREN)$(LPAREN)$(RPAREN) returns relative path $(LPAREN)pointing to nowhere$(RPAREN)) +$(LI $(BUGZILLA 18430): isSame is wrong for non global lambdas) +$(LI $(BUGZILLA 18469): [REG 2.079-b1] Segfault when trying to get type of __dtor.opCall) +$(LI $(BUGZILLA 18480): [Reg 2.079] dmd hangs with self-alias declaration) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 8207): OS X: Should extern$(LPAREN)D$(RPAREN) symbols include another underscore?) +$(LI $(BUGZILLA 8687): Variadic templates do not work properly with default arguments) +$(LI $(BUGZILLA 9433): Deprecate delete) +$(LI $(BUGZILLA 12511): static overloaded function is not accessible) +$(LI $(BUGZILLA 12901): Assignments to outside members in `in`/`out` contracts shouldn't be allowed) +$(LI $(BUGZILLA 14147): Compiler crash on identical functions in a single module) +$(LI $(BUGZILLA 14907): DMD crash when using template name as a default value of template's typed argument) +$(LI $(BUGZILLA 15777): Premature expansion of overload set in tuples) +$(LI $(BUGZILLA 16042): Identifier on template arguments should consider eponymous member lookup) +$(LI $(BUGZILLA 17437): Incorrect range check when implicitly converting integer literals to float/double) +$(LI $(BUGZILLA 17570): Misleading error message illegal conditional function definition) +$(LI $(BUGZILLA 17625): Confusing error message for private functions in different modules) +$(LI $(BUGZILLA 17630): selective imports find symbols in private imports of other modules) +$(LI $(BUGZILLA 17663): header generation $(LPAREN)-H$(RPAREN) is broken with public override of private default) +$(LI $(BUGZILLA 18014): DMD test suite fails to link on Linux distros where PIC/PIE is enforced) +$(LI $(BUGZILLA 18057): [ICE] Segmentation fault $(LPAREN)stack overflow$(RPAREN) in Expression::ctfeInterpret$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 18083): -w doesn't work for the ddoc build) +$(LI $(BUGZILLA 18143): in/out contracts should be implicitly 'this' const) +$(LI $(BUGZILLA 18190): [asan] heap-buffer-overflow in Module.load.checkModFileAlias) +$(LI $(BUGZILLA 18212): Usage of cfloat,cdouble,cfloat,ifloat,idouble,ireal shouldn't trigger an error in deprecated code) +$(LI $(BUGZILLA 18218): __traits$(LPAREN)isDeprecated, creal$(RPAREN) should return true) +$(LI $(BUGZILLA 18219): Private import inside struct leaks symbols when used as VarDeclaration types) +$(LI $(BUGZILLA 18225): Wrong condition in VRP) +$(LI $(BUGZILLA 18232): Union methods fail to initialize local variables to .init) +$(LI $(BUGZILLA 18243): selective import + overload = private visibility) +$(LI $(BUGZILLA 18261): Linkage information isn't part of the json output) +$(LI $(BUGZILLA 18312): string concatenation with -betterC fails with linker errors) +$(LI $(BUGZILLA 18335): The D_ObjectiveC version identifier is not printed in verbose mode) +$(LI $(BUGZILLA 18364): header file generation doesn't print the package name in package$(LPAREN)XXX$(RPAREN)) +$(LI $(BUGZILLA 18367): dmd should not segfault on -X with libraries, but no source files) +$(LI $(BUGZILLA 18429): alias this enum causes segmentation fault) +$(LI $(BUGZILLA 18468): cannot use `synchronized {}` in @safe code) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 6549): Implement contracts without implementation.) +$(LI $(BUGZILLA 11529): Unclear error message when rvalue is passed as `ref') +$(LI $(BUGZILLA 11714): Improve error message for wrongly initialized thread-local class instances) +$(LI $(BUGZILLA 13855): Allow multiple selective imports from different modules in a single import statement) +$(LI $(BUGZILLA 16492): support @nogc in debug{} blocks) +$(LI $(BUGZILLA 17899): Cannot initialise contextless delegate at compile time) +$(LI $(BUGZILLA 18053): Use stdint.h mangling for int64_t/uint64_t when mangling D long/ulong) +$(LI $(BUGZILLA 18149): Add a compiler trait to detect if a function is @disable) +$(LI $(BUGZILLA 18273): Better C: wrong exit code from main$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 18361): Ddoc: support ability to opt out of automatic keyword highlighting in text) +$(LI $(BUGZILLA 18427): `Symbol FOO is not visible because it is privately imported` => compiler should show how to import it) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 18114): [Reg 2.078] regex performance regression) +$(LI $(BUGZILLA 18316): std.net.curl.SMTP.mailTo fails to compile) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 7054): format$(LPAREN)$(RPAREN) aligns using code units instead of graphemes) +$(LI $(BUGZILLA 10879): std.variant Variant/Algebraic: Can't store static arrays > 32$(LPAREN)/16$(RPAREN) bytes) +$(LI $(BUGZILLA 15157): std.experimental.allocator.building_blocks docs) +$(LI $(BUGZILLA 15391): Problems loading libcurl.so and running datetime unittest on NixOS package build) +$(LI $(BUGZILLA 17832): std.random.choice cannot be used with other random generators) +$(LI $(BUGZILLA 18092): Can't combine take and takeExactly) +$(LI $(BUGZILLA 18124): std.regex.RegexMatch's front property is under-documented) +$(LI $(BUGZILLA 18153): deprecate public symbols ByLine, ByRecord, ByChunk) +$(LI $(BUGZILLA 18224): BigInt modulo uint must return long.) +$(LI $(BUGZILLA 18229): Misleading documentation of std.process.environment.get) +$(LI $(BUGZILLA 18259): allocatorObject's CAllocatorImpl should store the passed allocator within) +$(LI $(BUGZILLA 18278): writef documentation 404 error) +$(LI $(BUGZILLA 18285): std.algorithm.comparison.cmp for strings with custom predicate compares lengths wrong) +$(LI $(BUGZILLA 18286): std.algorithm.comparison.cmp for string with custom predicate fails if distinct chars can compare equal) +$(LI $(BUGZILLA 18288): std.algorithm.comparison.cmp for wide strings should be @safe) +$(LI $(BUGZILLA 18299): std.datetime.date.cmpTimeUnits does not throw a DateTimeException) +$(LI $(BUGZILLA 18328): algorithm.startsWith can compare narrow string lengths in more circumstances) +$(LI $(BUGZILLA 18349): std/math.d$(LPAREN)543,33$(RPAREN): Deprecation: integral promotion not done for -x) +$(LI $(BUGZILLA 18384): std.net.isemail is slow to import due to regex) +$(LI $(BUGZILLA 18397): Poor implementation of std.conv.hexString results in unintended bloat) +$(LI $(BUGZILLA 18434): BigInt gcd asserts when one argument is zero.) +$(LI $(BUGZILLA 18492): DLang STL links are broken) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 5489): std.typecons tuples dynamically iterable) +$(LI $(BUGZILLA 10828): datetime toString functions should accept sink) +$(LI $(BUGZILLA 11084): std.algorithm.scan) +$(LI $(BUGZILLA 11555): std.algorithm.reverse should return the just-reversed range) +$(LI $(BUGZILLA 11747): Better error message with @disabled toString) +$(LI $(BUGZILLA 13632): Second argument for std.string.strip) +$(LI $(BUGZILLA 14767): Support CTFE of BigInt under x86) +$(LI $(BUGZILLA 15949): Improve readtext handling of byte order mark $(LPAREN)BOM$(RPAREN)) +$(LI $(BUGZILLA 17249): Make BigInt data visible $(LPAREN)not modifiable!$(RPAREN)) +$(LI $(BUGZILLA 17440): Nullable.nullify$(LPAREN)$(RPAREN) resets referenced object) +$(LI $(BUGZILLA 18086): BigInt DivMod) +$(LI $(BUGZILLA 18096): Add fold$(LPAREN)$(RPAREN) to std.parallelism) +$(LI $(BUGZILLA 18116): to!wchar$(LPAREN)[string, dstring]$(RPAREN), and to!char$(LPAREN)[wstring, dstring]$(RPAREN) don't compile) +$(LI $(BUGZILLA 18152): std.format.formattedRead should work with rvalues.) +$(LI $(BUGZILLA 18186): std.array.replaceSlice should be usable in @safe) +$(LI $(BUGZILLA 18214): TemplateOf should return void for non-templated symbols) +$(LI $(BUGZILLA 18217): Don't repeatedly call unpredictableSeed to initialize rndGen) +$(LI $(BUGZILLA 18230): multiwayUnion sets wrong pred lambdas) +$(LI $(BUGZILLA 18239): std.experimental.allocator fillWithMemcpy could use memset when T.sizeof==1) +$(LI $(BUGZILLA 18280): std.algorithm.comparison.cmp for non-strings should call opCmp only once per item pair) +$(LI $(BUGZILLA 18329): std.algorithm.startsWith & endsWith can sometimes statically determine decoding unnecessary) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 15482): new uuid.d forbids to link statically with other libraries) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 18240): core.stdc.wchar_ wmemset, etc. should be pure) +$(LI $(BUGZILLA 18247): core.stdc.math functions that never set errno should be pure) +$(LI $(BUGZILLA 18279): rt.util.utf does not properly reserve buffer in toUTF16/toUTF16z) +$(LI $(BUGZILLA 18300): core.demangle demangling of really long symbol fails) +$(LI $(BUGZILLA 18409): DScanner SEGFAULTS on CircleCI) +$(LI $(BUGZILLA 18531): core.exception.RangeError@src/core/demangle.d$(LPAREN)216$(RPAREN): Range violation) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 13844): core.stdc.config isn't listed in the docs) +$(LI $(BUGZILLA 14475): man page is outdated) +$(LI $(BUGZILLA 16490): Usage of attributes in inline asm blocks is not documented) +$(LI $(BUGZILLA 18306): No compliation errors shown when running modified examples) +$(LI $(BUGZILLA 18319): std.exception: enforce example does not compile) +$(LI $(BUGZILLA 18341): Documentation for std.array.split is confusing/incorrect) +$(LI $(BUGZILLA 18355): [Areas of D usage]) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 17998): Document Options for install.sh) +$(LI $(BUGZILLA 18202): Show TOC overview in the dlang specification pages) +$(LI $(BUGZILLA 18337): https://dlang.org/spec/operatoroverloading.html missing opIn/opIn_r) +$(LI $(BUGZILLA 18379): [404 Not Found] Foundation Donate page not found) +$(LI $(BUGZILLA 18383): Front page blog section is only partially filled.) +) +$(BUGSTITLE_BUGZILLA Tools bugs, + +$(LI $(BUGZILLA 18208): demangle RangeError@src/core/demangle.d$(LPAREN)230$(RPAREN)) +) +$(BUGSTITLE_BUGZILLA Installer bugs, + +$(LI $(BUGZILLA 15131): curl.lib is not available in 32 bit mscoff format) +$(LI $(BUGZILLA 18510): [Beta 2.079] lld-link.exe fails to open obj file in subpath) +) +) +$(D_CONTRIBUTORS_HEADER 78) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR acehreli) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR aldacron) + $(D_CONTRIBUTOR Alexandru Jercaianu) + $(D_CONTRIBUTOR Ali Akhtarzada) + $(D_CONTRIBUTOR Ali Çehreli) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Andrey Penechko) + $(D_CONTRIBUTOR Andy Smith) + $(D_CONTRIBUTOR Aravinda VK) + $(D_CONTRIBUTOR Arun Chandrasekaran) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR BBasile) + $(D_CONTRIBUTOR Brad Roberts) + $(D_CONTRIBUTOR carblue) + $(D_CONTRIBUTOR Daniel Kozak) + $(D_CONTRIBUTOR Diederik de Groot) + $(D_CONTRIBUTOR dmdw64) + $(D_CONTRIBUTOR Dragos Carp) + $(D_CONTRIBUTOR Duncan Paterson) + $(D_CONTRIBUTOR Eduard Staniloiu) + $(D_CONTRIBUTOR Elias Batek) + $(D_CONTRIBUTOR H. S. Teoh) + $(D_CONTRIBUTOR Héctor Barreras Almarcha [Dechcaudron]) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jack Stouffer) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR jacob-carlborg) + $(D_CONTRIBUTOR jercaianu) + $(D_CONTRIBUTOR jmh530) + $(D_CONTRIBUTOR Joakim Noah) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR Johannes Pfau) + $(D_CONTRIBUTOR Jonathan M Davis) + $(D_CONTRIBUTOR Jonathan Marler) + $(D_CONTRIBUTOR Joseph Rushton Wakeling) + $(D_CONTRIBUTOR Kai Nacke) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR Lance Bachmeier) + $(D_CONTRIBUTOR Lucia Mcojocaru) + $(D_CONTRIBUTOR Luís Marques) + $(D_CONTRIBUTOR Manuel Maier) + $(D_CONTRIBUTOR Markus F.X.J. Oberhumer) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Baumann) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR MetaLang) + $(D_CONTRIBUTOR Michael Parker) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Lindsay Wilson) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Oleg Nykytenko) + $(D_CONTRIBUTOR Patrick Schlüter) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Pradeep Gowda) + $(D_CONTRIBUTOR Radu Racariu) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR shoo) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR skl131313) + $(D_CONTRIBUTOR Stanislav Blinov) + $(D_CONTRIBUTOR Stefan Koch) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Thomas Mader) + $(D_CONTRIBUTOR Timothee Cour) + $(D_CONTRIBUTOR Tomáš Chaloupka) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR Yannick Koechlin) + $(D_CONTRIBUTOR Yuxuan Shui) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.079.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.079.1.dd b/changelog/2.079.1.dd new file mode 100644 index 0000000000..2e182d1493 --- /dev/null +++ b/changelog/2.079.1.dd @@ -0,0 +1,68 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 14, 2018, =================================================, + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 17512): [REG 2.073] [DIP1000] Error on bad interplay of 'auto ref' and 'return' attribute deduction.) +$(LI $(BUGZILLA 18645): DMD segmentation fault) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 17942): Enums are evaluated differently in global scope) +$(LI $(BUGZILLA 18670): compiler segfault if `new` on a union type with dip1000) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 18647): Use of delete should be allowed without a deprecation in a deprecated scope) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 18565): std.regex Captures opAssign returns void since v2.079.0) +$(LI $(BUGZILLA 18624): getSymbolsByUDA produces wrong result if one of the symbols having the UDA is a function) +$(LI $(BUGZILLA 18691): assigning a std.regex.Captures with 3 or more groups causes double free) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 18548): [2.079] std.format ignores templated toString if another toString is not a template) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 18648): Document the type of std.stdio.stdin and friends) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 18530): [Reg 2.079] src/rt/tracegc.d$(LPAREN)43$(RPAREN): Deprecation: The delete keyword has been deprecated) +) +) +$(D_CONTRIBUTORS_HEADER 15) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Brad Roberts) + $(D_CONTRIBUTOR Brian Schott) + $(D_CONTRIBUTOR Dmitry Olshansky) + $(D_CONTRIBUTOR Jack Stouffer) + $(D_CONTRIBUTOR Jan Jurzitza) + $(D_CONTRIBUTOR Jonathan M Davis) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR MetaLang) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Spoov) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) +Macros: + VER=2.079.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.080.0.dd b/changelog/2.080.0.dd new file mode 100644 index 0000000000..86fb4fdafe --- /dev/null +++ b/changelog/2.080.0.dd @@ -0,0 +1,839 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION May 01, 2018, =================================================, + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 deprecate_class_allocators,Class allocators and deallocators have been deprecated)) +$(LI $(RELATIVE_LINK2 deprecate_double_initialization,Deprecate double initialization of immutable fields inside constructor)) +$(LI $(RELATIVE_LINK2 fix18736,Issue 18736 - constructor calls allowed after case labels)) +$(LI $(RELATIVE_LINK2 fix5227,fix Issue 5227 - X ^^ FP at compile-time)) +$(LI $(RELATIVE_LINK2 isReturnOnStack,add __traits(isReturnOnStack, func))) +$(LI $(RELATIVE_LINK2 objc_class_methods,Support for calling Objective-C class (static) methods has been added.)) +$(LI $(RELATIVE_LINK2 postblitQualifiers,Deprecate the use of a `const`/`immutable`/`shared` postblit)) +$(LI $(RELATIVE_LINK2 rwm-shared-error,The deprecation for read-modify-write operations on `shared` variables has ended)) +$(LI $(RELATIVE_LINK2 switch-skip-declaration,The deprecation for `switch` cases which skip the declaration of a variable has ended)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 bitflags-property-opdispatch,`std.typecons.BitFlags` now supports opDispatch-based property access)) +$(LI $(RELATIVE_LINK2 rndtonl-deprecated,std.math.rndtonl has been deprecated)) +$(LI $(RELATIVE_LINK2 shared-bitmapped-block,Added the SharedBitmappedBlock, as the thread-safe version of the regular BitmappedBlock.)) +$(LI $(RELATIVE_LINK2 std-aligned-block-list,Implemented a new allocator, `AlignedBlockList` and its thread-safe version `SharedAlignedBlockList`)) +$(LI $(RELATIVE_LINK2 std-exception-enforceEx,`std.exception.enforceEx` was deprecated in favor of `std.exception.enforce`)) +$(LI $(RELATIVE_LINK2 std-format-fixDigitGrouping,Fixed digits grouping for floating point number without decimal part)) +$(LI $(RELATIVE_LINK2 std-functional-binaryReverseArgs,`std.functional.binaryReverseArgs` was deprecated in favor of `std.functional.reverseArgs`)) +$(LI $(RELATIVE_LINK2 std-typecons-nullable-apply,`apply` was added to `std.typecons`.)) + +) + +$(BUGSTITLE_TEXT_HEADER Tools changes, + +$(LI $(RELATIVE_LINK2 rdmdMakefiles,rdmd can now be used as a shell in makefiles)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 deprecate_class_allocators,Class allocators and deallocators have been deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecate_class_allocators.dd) +$(P +Class allocators and deallocators have been planned for deprecation for years. Starting with this release the following code will emit deprecation messages. +) + +--- +class C +{ + new(size_t size) // deprecation message + { + return malloc(size); + } + + delete(void* obj) // deprecation message + { + free(obj); + } +} +--- + +$(P +See the $(LINK2 $(ROOT_DIR)deprecate.html#Class%20allocators%20and%20deallocators, Deprecated Features) for more information. +) + +$(P +Many alternatives for class allocators/deallcators exist. Among them is the generic $(REF make, std,experimental,allocator) and $(REF dispose, std,experimental,allocator) from the allocator package. For other alternatives, see $(LINK2 https://dlang.org/blog/the-gc-series, the recent article about memory allocation on the DBlog) and $(LINK2 https://wiki.dlang.org/Memory_Management, the D Wiki memory management article). +) + +$(P +Users have leveraged allocators in order to disable GC allocation, as illustrated in the following example: +) + +--- +class C +{ + @disable new(size_t size); +} + +void main() +{ + auto c = new C(); // Error: allocator `new` is not callable because it is annotated with `@disable` +} +--- + +$(P +That idiom will remain, but has been enhanced with this release to no longer require the `size_t` argument. That is, starting with this release, the following syntax is also permitted: +) + +--- +class C +{ + @disable new(); +} + +void main() +{ + auto c = new C(); // Error: allocator `new` is not callable because it is annotated with `@disable` +} +--- +) + +$(LI $(LNAME2 deprecate_double_initialization,Deprecate double initialization of immutable fields inside constructor) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecate_double_initialization.dd) +$(P +Inside a constructor scope, assigning to aggregate declaration (class/struct) +members is done by considering the first assignment as initialization and +subsequent assignments as modifications of the initially constructed object. +For `const`/`immutable` fields the initialization is accepted in the constructor, +but subsequent modifications are not. Example: +) + +--- +struct A +{ + int a; + immutable int b; + this(int a, int b) + { + this.a = a; + this.b = b; + + this.a = 7; // OK, a is mutable + this.b = 9; // Error: immutable field b initialized multiple times + } +} +--- + +$(P +However, $(BUGZILLA 18719) shows that this rule does not apply when inside +a constructor scope there is a call to a different constructor: +) + +--- +struct A +{ + immmutable int a; + this() + { + this(42); + this.a = 5; // second initialization of immutable field + } + + this(int a) + { + this.a = a; + } +} +--- + +$(P +The above code wrongfully compiled succesfully before this patch, accepting the double +initialization of the `immutable` field `a`. After this patch, `this.a = 5` will issue +a deprecation warning stating that `a` is initialized multiple times. +) +) + +$(LI $(LNAME2 fix18736,Issue 18736 - constructor calls allowed after case labels) +$(CHANGELOG_SOURCE_FILE dmd, changelog/fix18736.dd) +$(P +Delegating constructor calls are not allowed after labels, +but case labels and default labels should also count as labels. +) + +--- +class A +{ + this(char c) { } + + this(int i) + { + switch (i) + { + case 1: break; + default: break; + } + this('c'); // now gives an error + } +} +--- + +$(P +This is necessary so the compiler can guarantee that each +field is initialized exactly once. To get code like the above +to pass the compiler, replace it with an if-then sequence. +) +) + +$(LI $(LNAME2 fix5227,fix Issue 5227 - X ^^ FP at compile-time) +$(CHANGELOG_SOURCE_FILE dmd, changelog/fix5227.dd) +$(P +The pow operator `^^` can now be used by CTFE. +) + +$(P +Adds these std.math functions to those that can be used by CTFE: +) + +$(P +round +floor +ceil +trunc +log +log2 +log10 +pow +expm1 +exp2 +fmin +fmax +copysign +fma +) +) + +$(LI $(LNAME2 isReturnOnStack,add __traits(isReturnOnStack, func)) +$(CHANGELOG_SOURCE_FILE dmd, changelog/isReturnOnStack.dd) +$(P +Determines if a function's return value is placed on the stack, +or is returned via registers. +For more details, see $(LINK2 $(ROOT_DIR)spec/traits.html#isReturnOnStack, isReturnOnStack). +) +) + +$(LI $(LNAME2 objc_class_methods,Support for calling Objective-C class (static) methods has been added.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/objc_class_methods.dd) +$(P +Previously to call an Objective-C class method it was necessary to make explicit +calls to the Objective-C runtime. The following code is an example of the old +way to call a class method: +) + +--- +extern (C) Class objc_lookUpClass(in char* name); + +extern (Objective-C) +interface Class +{ + NSObject alloc() @selector("alloc"); +} + +extern (Objective-C) +interface NSObject +{ + NSObject init() @selector("init"); +} + +void main() +{ + auto cls = objc_lookUpClass("NSObject"); + auto o = cls.alloc().init(); +} +--- + +$(P +The above code can now be replaced with the following: +) + +--- +extern (Objective-C) +interface NSObject +{ + static NSObject alloc() @selector("alloc"); + NSObject init() @selector("init"); +} + +void main() +{ + auto o = NSObject.alloc().init(); +} +--- + +$(P +Note the use of the `static` attribute in the method declaration. +) +) + +$(LI $(LNAME2 postblitQualifiers,Deprecate the use of a `const`/`immutable`/`shared` postblit) +$(CHANGELOG_SOURCE_FILE dmd, changelog/postblitQualifiers.dd) +$(P +Before this patch, if a postblit was declared `const`/`immutable`/`shared` +the compiler would have accepted the declaration but there would have +been no way of calling the postblit succesfully, except for const due +to the implicit conversion mutable -> const. Even though calling a +const posblit is possible, there is no way to modify the fields of the +newly copied struct: +) + +--- +struct S +{ + int n + this(this) const + { + ++n; // Error: cannot modify this.n in const method + } +} + +void main() +{ + S a; + auto a2 = a; +} +--- + +$(P +With this release, if a postblit contains `const`/`immutable`/`shared` in +its signature, a deprecation message will be emitted. +) +) + +$(LI $(LNAME2 rwm-shared-error,The deprecation for read-modify-write operations on `shared` variables has ended) +$(CHANGELOG_SOURCE_FILE dmd, changelog/rwm-shared-error.dd) +$(P +Read-modify-write operations are not allowed for `shared` variables: +) + +--- +shared int i; +i++; // Error: read-modify-write operations are not allowed for shared variables +--- + +$(P +Use $(REF atomicOp, core, atomic) instead: +) + +--- +import core.atomic : atomicOp; +shared int i; +atomicOp!"+="(i, 1); +--- +) + +$(LI $(LNAME2 switch-skip-declaration,The deprecation for `switch` cases which skip the declaration of a variable has ended) +$(CHANGELOG_SOURCE_FILE dmd, changelog/switch-skip-declaration.dd) +$(P +Usage of a variable which is declared in another `switch` case now results in an error. +) + +--- +int i = 2; +switch (i) +{ + case 1: + { + int j; + case 2: + j++; + j.writeln; // BUG: j is not initialized and e.g. prints -321532879 + break; + } + default: + break; +} +--- + +$(P +If this behavior is wanted, it can explicitly requested by using `void` initialization: +) + +--- +int i = 2; +switch (i) +{ + case 1: + { + int j = void; + case 2: + j = 2; + j.writeln; + break; + } + default: + break; +} +--- +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 bitflags-property-opdispatch,`std.typecons.BitFlags` now supports opDispatch-based property access) +$(CHANGELOG_SOURCE_FILE phobos, changelog/bitflags-property-opdispatch.dd) +$(P +$(REF BitFlags, std, typecons) was extended so that enum members can be set and tested directly on the +`BitFlags` instead of having to `&` with the underlying enum. +) + +------- +enum Features +{ + fast = 1 << 0, + size = 1 << 1, +} + +void run(BitFlags!Features features) +{ + // get + if (features.fast && !features.size) {} // new new new + if ((features & Features.fast) && !(features & Features.size)) {} // old old old + // set + features.fast = true; // new new new + features.fast = false; // new new new + features.fast |= Features.fast; // old old old + features.fast &= ~Features.fast; // old old old +} +------- + +$(P +This also works for unsafe `BitFlags` where the property get access tests for an exact +match of all bits of the unsafe `BitFlags` combination. +Analogously, the property set access clears or sets all bits of the unsafe `BitFlags` combination. +) + +------- +enum Features +{ + fast = 1 << 0, + size = 1 << 1, + combined = fast | size, +} + +void run(BitFlags!(Features, Yes.unsafe) features) +{ + // get + if (features.combined) {} // new new new + if ((features & Features.combined) == BitFlags!(Features, Yes.unsafe)(Features.combined)) {} // old old old + // set + features.combined = true; // new new new + features.combined = false; // new new new + features.combined |= Features.combined; // old old old + features.combined &= ~Features.combined; // old old old +} +------- +) + +$(LI $(LNAME2 rndtonl-deprecated,std.math.rndtonl has been deprecated) +$(CHANGELOG_SOURCE_FILE phobos, changelog/rndtonl-deprecated.dd) +$(P +$(REF rndtonl, std, math) is a rounding function only available when using the +Digital Mars C Runtime on Windows. As this function is not cross-platform, it +has been deprecated, and will be removed on version 2.089. Please use +$(REF round, std, math) instead. +) +) + +$(LI $(LNAME2 shared-bitmapped-block,Added the SharedBitmappedBlock, as the thread-safe version of the regular BitmappedBlock.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/shared-bitmapped-block.dd) +$(P +The new $(REF SharedBitmappedBlock, std,experimental,allocator,building_blocks,bitmapped_block) and its single-threaded version can now be instantiated with `Yes.multiblock` or `No.multiblock`. +If instantiated with `Yes.multiblock` (the default behavior), each allocation can return an arbitrary number of blocks. +With `No.multiblock` however, any allocation request can't exceed the block size. This allows for greater performance on both single and multithreaded environments. +) + +--- +// The 'BitmappedBlock' is implicitly instantiated with Yes.multiblock +auto a = BitmappedBlock!(blockSize, 8, Mallocator, Yes.multiblock)(numBlocks * blockSize); + +// Instantiated with Yes.multiblock, can allocate more than one block at a time +void[] buf = a.allocate(2 * blockSize); +assert(buf.length == 2 * blockSize); +assert(a.deallocate(buf)); +--- + +--- +// Instantate the 'BitmappedBlock' with No.multiblock +auto a = BitmappedBlock!(blockSize, 8, Mallocator, No.multiblock)(1024 * blockSize); + +// Since instantiated with No.multiblock, can only allocate at most the block size +void[] buf = a.allocate(blockSize + 1); +assert(buf is null); +--- + +$(P +For shared the same rules apply, we only need to replace `BitmappedBlock` with `SharedBitmappedBlock`. +) +) + +$(LI $(LNAME2 std-aligned-block-list,Implemented a new allocator, `AlignedBlockList` and its thread-safe version `SharedAlignedBlockList`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-aligned-block-list.dd) +$(P +$(REF AlignedBlockList, std,experimental,allocator,building_blocks, aligned_block_list) represents +a list of allocators which allows for deallocations in constant time. +Although allocations are in theory served in linear searching time, `deallocate` calls take +$(BIGOH 1) time, by using aligned allocations. The `ParentAllocator` must implement `alignedAllocate`. +) + +$(P +$(REF SharedAlignedBlockList, std,experimental,allocator,building_blocks, aligned_block_list) has the +same semantics as its single threaded version, however the internal allocators must be in addition marked +as shared. +) +) + +$(LI $(LNAME2 std-exception-enforceEx,`std.exception.enforceEx` was deprecated in favor of `std.exception.enforce`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-exception-enforceEx.dd) +$(P +With 2.079 $(REF enforce, std,exception) became a complete super set of +$(REF enforceEx, std,exception) +) + +$(P +$(H3 Corrective action) +) + +$(P +Replace: +) + +--- +import std.exception; +alias enf = enforceEx!Exception; +assertNotThrown(enf(true)); +assertThrown(enf(false, "blah")); +--- + +$(P +with: +) + +--- +import std.exception; +alias enf = enforce!Exception; +assertNotThrown(enf(true)); +assertThrown(enf(false, "blah")); +--- +) + +$(LI $(LNAME2 std-format-fixDigitGrouping,Fixed digits grouping for floating point number without decimal part) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-format-fixDigitGrouping.dd) +$(P +$(REF formatValue, std, format) now correctly groups digits in the output string +by inserting a group separator character (,) every n characters specified +by the $(LINK2 https://dlang.org/library/std/format/formatted_write.html#format-string, Separator) +grammar rule in cases with zero decimal precision specified in the format string +for floating point numbers. +) + +$(P +No group separators at all are inserted for floating point numbers when formatted +with zero precision (i.e. no decimal digits) in Phobos before this fix, +regardless of the respective decimal part of the formatted number. +) + +------- +import std.format; + +assert(format("%,3.2f", 1172.009) == "1,172.01"); +assert(format("%,3.0f", 1172.009) == "1,172"); +assert(format("%#,3.4f", 1303.2508) == "1,303.250,8"); +assert(format("%#,3.0f", 1303.2508) == "1,303."); + +// original (buggy) behaviour before this fix +//assert(format("%,3.0f", 1303.2508) == "1303"); +//assert(format("%,3.0f", 1303.) == "1303"); + +// original (correct) behaviour before this fix +//assert(format("%,3.1f", 1303.2508) == "1,303.3"); +//assert(format("%,3.2f", 1303.) == "1,303.00"); +//assert(format("%,3f", 1303.) == "1,303.000,000"); +------- +) + +$(LI $(LNAME2 std-functional-binaryReverseArgs,`std.functional.binaryReverseArgs` was deprecated in favor of `std.functional.reverseArgs`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-functional-binaryReverseArgs.dd) +$(P +$(REF reverseArgs, std,functional) is a full super set of $(REF binaryReverseArgs, std,functional). +) + +$(P +Correct action: replace `binaryReverseArgs` with `reverseArgs`. +) +) + +$(LI $(LNAME2 std-typecons-nullable-apply,`apply` was added to `std.typecons`.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-typecons-nullable-apply.dd) +$(P +`apply` is an operation for $(REF Nullable, std, typecons) values that "unpacks" the `Nullable`, performs some +operation (that is passed as a template parameter), then packs the result into another `Nullable` if necessary. +When the initial `Nullable` is `null`, the resulting `Nullable` is also `null` and the function is not +called. +) + +----- +Nullable!int n; +alias square = i => i * i; +n = n.apply!square; // does nothing if isNull +assert(n.isNull); +n = 2; +assert(n.apply!square.get == 4); +----- +) + + +) + +$(BUGSTITLE_TEXT_BODY Tools changes, + +$(LI $(LNAME2 rdmdMakefiles,rdmd can now be used as a shell in makefiles) +$(CHANGELOG_SOURCE_FILE tools, ../tools/changelog/rdmdMakefiles.dd) +$(P +With gnu make(3.82 or higher), rdmd can now be used in makefiles. +This is accomplished by setting the SHELL and .SHELLFLAGS to /usr/bin/rdmd and --eval respectively. +) +--- +.ONESHELL: +SHELL = /usr/bin/rdmd +.SHELLFLAGS = --eval +hello.txt: +$(TAB)import std.file; +$(TAB)write("$@","hello world\n"); +--- +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 16243): wrong C++ argument passing with empty struct when interfacing with Clang) +$(LI $(BUGZILLA 18197): [REG2.073] Internal error: backend\cgcod.c 1659) +$(LI $(BUGZILLA 18489): [REG 2.073]Internal error: dmd/backend/cgcod.c 1688) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 5212): no escape analysis for typesafe variadic function arguments) +$(LI $(BUGZILLA 5227): X ^^ FP at compile-time) +$(LI $(BUGZILLA 9433): Deprecate delete) +$(LI $(BUGZILLA 12486): Function returning struct isn't called if `enum` of its result is accessed) +$(LI $(BUGZILLA 14997): __ctor present in error message) +$(LI $(BUGZILLA 15653): IFTI fails for immutable parameter) +$(LI $(BUGZILLA 15660): break immutable with pure function and mutable reference params) +$(LI $(BUGZILLA 16107): [ICE] - Internal error: backend/cgcod.c 2297) +$(LI $(BUGZILLA 16189): Optimizer bug, with simple test case) +$(LI $(BUGZILLA 16555): Stack corruption when calling multi-parameter outer function from nested function) +$(LI $(BUGZILLA 16578): bogus deprecation - switch skips declaration of variable) +$(LI $(BUGZILLA 17284): Template function attribute inference wrongly infers @safe for accessing overlapping pointer fields in unions) +$(LI $(BUGZILLA 17423): pointer assignment to `this` in member function is not accounted for) +$(LI $(BUGZILLA 17874): Segmentation fault when constructing a struct with a static array of structs containing floats) +$(LI $(BUGZILLA 17892): Scope analysis with -dip1000 fails for templated structs) +$(LI $(BUGZILLA 17918): [Reg 2.072] ICE with unknown symbol in base class) +$(LI $(BUGZILLA 17959): [DIP1000] Can store scope delegate in non-scope member) +$(LI $(BUGZILLA 17991): ICE with imports without module) +$(LI $(BUGZILLA 18000): [scope] auto-generated opAssign not scope aware) +$(LI $(BUGZILLA 18034): SIMD optimization issues) +$(LI $(BUGZILLA 18130): ICE on zero-length `out` array parameter) +$(LI $(BUGZILLA 18199): Error with lambda in struct initializer) +$(LI $(BUGZILLA 18242): DMD Segmentation fault.) +$(LI $(BUGZILLA 18282): [Scope][DIP1000]Assignment of local variable to `scope` variable not recognized by compiler) +$(LI $(BUGZILLA 18459): The static array ABI doesn't match the struct ABI) +$(LI $(BUGZILLA 18461): codegen bug - OPbt expressions and assignments to ambiguous symbols) +$(LI $(BUGZILLA 18474): Postblit not working in shared structs) +$(LI $(BUGZILLA 18484): [dip1000] Subtype allows reference to escape with implicit casting) +$(LI $(BUGZILLA 18504): Assert in synchronized crashes with SIGILL on exit) +$(LI $(BUGZILLA 18505): delete deprecation message is misleading) +$(LI $(BUGZILLA 18534): Wrong code for ?: operator when compiling with -O) +$(LI $(BUGZILLA 18553): Inline assembler: CR2, CR3 control registers not available in 64-bit code) +$(LI $(BUGZILLA 18554): `tupleof` ignoring `private` shouldn't be accepted in @safe code) +$(LI $(BUGZILLA 18568): partially overlapping assignments have undefined behavior but are accepted in @safe code) +$(LI $(BUGZILLA 18575): making delegate from member function can lead to unsafe code) +$(LI $(BUGZILLA 18576): Compiler not doing RVO with auto returns) +$(LI $(BUGZILLA 18597): more unsafe unaligned pointer errors) +$(LI $(BUGZILLA 18607): using labelled continue in tuple foreach can break pure and @safe) +$(LI $(BUGZILLA 18644): [dip1000] escape of outer local not detected) +$(LI $(BUGZILLA 18661): auto ref and return attribute inference) +$(LI $(BUGZILLA 18708): Flow analysis in constructors not done correctly for if, ||, &&) +$(LI $(BUGZILLA 18719): Doubly-called constructor against member when using forwarding constructors) +$(LI $(BUGZILLA 18736): constructor calls allowed after case labels) +$(LI $(BUGZILLA 18737): An assert$(LPAREN)0$(RPAREN) should be a leaf in constructor flow analysis) +$(LI $(BUGZILLA 18753): chunkBy compile error causes ICE) +$(LI $(BUGZILLA 18762): DMD should use a unique path/filename for __stdin.o) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 15624): opApply with @safe and @system variants can't be used with foreach syntax) +$(LI $(BUGZILLA 16037): assigning delegate to a scope variable shouldn't allocate closure) +$(LI $(BUGZILLA 17784): [scope][DIP1000] Confusing error message for escaping local via new-expression) +$(LI $(BUGZILLA 18417): Make const and immutable postblit constructors illegal) +$(LI $(BUGZILLA 18460): Improve error message for missing 'new' for class instantiation) +$(LI $(BUGZILLA 18503): Confusing error message for erroneous postblit) +$(LI $(BUGZILLA 18551): Improve hint for "does not override any function) +$(LI $(BUGZILLA 18574): Unclear error message when trying to inherit from multiple classes) +$(LI $(BUGZILLA 18578): First enum value assigned 0 instead of EnumBaseType.init) +$(LI $(BUGZILLA 18591): DMD should allow access to mixin template declarations) +$(LI $(BUGZILLA 18694): pure functions using static/global structs with no fields should pass compilation) +$(LI $(BUGZILLA 18767): __xtoHash memberwise hashing shouldn't just sum the member hashes) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 17961): std.uni does not compile with -unittest -dip1000) +$(LI $(BUGZILLA 18800): [REG2.080.0-beta.1] Array.length setter segfaults for payloads with indirections) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 7879): format of class with not const toString$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 13642): std.container.Array: change of length reallocates without notifying GC) +$(LI $(BUGZILLA 15768): std.stdio.File does not support __gshared semantics of stdout/err/in) +$(LI $(BUGZILLA 17862): std.random.XorshiftEngine.min is wrong when bits == 32) +$(LI $(BUGZILLA 17982): Support for const$(LPAREN)Class$(RPAREN) in algorithm.searching.extremum) +$(LI $(BUGZILLA 18133): BitArray constructors are poorly documented.) +$(LI $(BUGZILLA 18134): BitArray >>= broken when length % $(LPAREN)8 * size_t.sizeof$(RPAREN) == 0) +$(LI $(BUGZILLA 18452): std.zip has size limit of 2 GB) +$(LI $(BUGZILLA 18524): std.range.Zip.moveBack instead performs moveFront) +$(LI $(BUGZILLA 18579): No group separators for floating point number formatted with zero decimal digits) +$(LI $(BUGZILLA 18615): Rebindable!A doesn't use class A's opEquals $(LPAREN)returns a is b instead$(RPAREN)) +$(LI $(BUGZILLA 18634): std.container.rbtree does not work with delegate comparators) +$(LI $(BUGZILLA 18663): std.random.isSeedable has false positives) +$(LI $(BUGZILLA 18669): isNestedFunction does not check if parameter is a function) +$(LI $(BUGZILLA 18689): std.format should always throw FormatException on bad specs/arguments) +$(LI $(BUGZILLA 18704): std/datetime/stopwatch.d$(LPAREN)452$(RPAREN) assertion failure on auto-tester) +$(LI $(BUGZILLA 18714): Phobos calls localtime, which is not threadsafe) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 4591): Concat of std.typecons.Tuples) +$(LI $(BUGZILLA 8341): topN$(LPAREN)zip$(LPAREN)$(RPAREN)$(RPAREN) too?) +$(LI $(BUGZILLA 10828): datetime toString functions should accept sink) +$(LI $(BUGZILLA 13880): nothrow @nogc std.algorithm.reduce on fixed-size arrays) +$(LI $(BUGZILLA 14637): Array operations should work on tuples) +$(LI $(BUGZILLA 18158): std.file.getcwd should be usable in @safe) +$(LI $(BUGZILLA 18166): std.array.replace should be usable in @safe for dstrings) +$(LI $(BUGZILLA 18168): std.base64.encode for output ranges should be usable in @safe) +$(LI $(BUGZILLA 18174): std.math.equalsDigit should be usable in @safe) +$(LI $(BUGZILLA 18182): std.uri should be usable in @safe) +$(LI $(BUGZILLA 18223): std.experimental.allocator uninitializedFillDefault could use memset) +$(LI $(BUGZILLA 18438): hasStaticMember fails with a T* while hasMember passes) +$(LI $(BUGZILLA 18501): randomShuffle and partialShuffle should return their input argument) +$(LI $(BUGZILLA 18596): std.random.unpredictableSeed could use something better than MinstdRand0) +$(LI $(BUGZILLA 18600): Regex performance enhancement for repeated matchFirst calls) +$(LI $(BUGZILLA 18638): The main override of std.range.zip could infer @nogc and nothrow) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 18652): hashOf example doesn't compile) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 18482): wincrypt functions should be `@nogc` `nothrow`) +$(LI $(BUGZILLA 18536): Bad stack traces when building with -m32mscoff) +$(LI $(BUGZILLA 18537): Cannot pass absolute path to coverage options) +$(LI $(BUGZILLA 18547): Win32: throwing exception in fiber crashes application) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 18602): [Better C] docs) +$(LI $(BUGZILLA 18603): Illegal instruction: 4 on Mac OS 10.7.5 Leopard) +$(LI $(BUGZILLA 18702): FAQ item "What does D have that C++ doesn't?" comparison link $(LPAREN)https://dlang.org/articles/comparison.html$(RPAREN) returns 404) +$(LI $(BUGZILLA 18709): DDOC_AUTO_PSYMBOL and friends are wrong) +$(LI $(BUGZILLA 18747): [Structs, Unions]) +) +$(BUGSTITLE_BUGZILLA Installer bugs, + +$(LI $(BUGZILLA 18649): curl on Ubuntu 18.04 depends on libcurl4, .deb installer depends on libcurl3) +) +) +$(D_CONTRIBUTORS_HEADER 65) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Alexandru Caciulescu) + $(D_CONTRIBUTOR Alexandru Jercaianu) + $(D_CONTRIBUTOR Ali Akhtarzada) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Andrei-Cristian VASILE (87585)) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Brad Roberts) + $(D_CONTRIBUTOR byebye) + $(D_CONTRIBUTOR carblue) + $(D_CONTRIBUTOR cedretaber) + $(D_CONTRIBUTOR crimaniak) + $(D_CONTRIBUTOR David Nadlinger) + $(D_CONTRIBUTOR Denis Feklushkin) + $(D_CONTRIBUTOR Diederik de Groot) + $(D_CONTRIBUTOR Dmitry Olshansky) + $(D_CONTRIBUTOR drug007) + $(D_CONTRIBUTOR Eduard Staniloiu) + $(D_CONTRIBUTOR FeepingCreature) + $(D_CONTRIBUTOR Giles Bathgate) + $(D_CONTRIBUTOR Harry T. Vennik) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jack Stouffer) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR Joakim Noah) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR John Belmonte) + $(D_CONTRIBUTOR Jonathan M Davis) + $(D_CONTRIBUTOR Jonathan Marler) + $(D_CONTRIBUTOR Joseph Rushton Wakeling) + $(D_CONTRIBUTOR Kai Nacke) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR LemonBoy) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR MetaLang) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR n8sh) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Lindsay Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Oleg Nykytenko) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Radu Racariu) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Roman Chistokhodov) + $(D_CONTRIBUTOR rracariu) + $(D_CONTRIBUTOR Ryan Frame) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Simon Naarmann) + $(D_CONTRIBUTOR skl131313) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Superstar64) + $(D_CONTRIBUTOR Thomas Mader) + $(D_CONTRIBUTOR Timothee Cour) + $(D_CONTRIBUTOR Unknown) + $(D_CONTRIBUTOR viktor) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR Ľudovít Lučenič) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.080.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.080.1.dd b/changelog/2.080.1.dd new file mode 100644 index 0000000000..fa0f11048b --- /dev/null +++ b/changelog/2.080.1.dd @@ -0,0 +1,58 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jun 07, 2018, =================================================, + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 17968): [REG 2.073] object initializer omitted when it should be included.) +$(LI $(BUGZILLA 18115): [REG2.078-b1] case where && is not shortcut anymore in CTFE) +$(LI $(BUGZILLA 18821): DMD segfault when doing unsafe operation outside of any function) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 17819): static foreach segfaults on __traits$(LPAREN)allMembers$(RPAREN)) +$(LI $(BUGZILLA 18211): Access violation when generating JSON on static foreach) +$(LI $(BUGZILLA 18819): DMD compilation crash) +$(LI $(BUGZILLA 18902): -lib crashes on static libraries in the command line) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 18822): [REG 2.080.0] Compiling byGrapheme Fails) +$(LI $(BUGZILLA 18871): DMD "illegal hardware instruction" crash) +$(LI $(BUGZILLA 18884): getSymbolsByUDA fails on AliasSeq members) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 18904): core.internal.string has issues with radix) +) +) +$(D_CONTRIBUTORS_HEADER 13) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Eugen Wissner) + $(D_CONTRIBUTOR Jack Stouffer) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Timon Gehr) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.080.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.081.0.dd b/changelog/2.081.0.dd new file mode 100644 index 0000000000..d2698d9f00 --- /dev/null +++ b/changelog/2.081.0.dd @@ -0,0 +1,878 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 01, 2018, =================================================, + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 deprecate_ctor_in_static_block,Deprecate allowing a constructor declaration in a static block)) +$(LI $(RELATIVE_LINK2 deprecate_this_super_as_types,Deprecate usage of `this` and `super` as types)) +$(LI $(RELATIVE_LINK2 expression-based_contract_syntax,Implement DIP 1009 - Add Expression-Based Contract Syntax)) +$(LI $(RELATIVE_LINK2 extern_cpp_overhaul,`extern (C++)` construction, destruction, operators and other mangling improvements)) +$(LI $(RELATIVE_LINK2 fix16206,Support for iterating template overloads)) +$(LI $(RELATIVE_LINK2 getlinkage_for_classes,__traits(getLinkage, ...) now works on structs, classes, and interfaces.)) +$(LI $(RELATIVE_LINK2 implicit_catch_error,Implicit `catch` statements will now result in an error)) +$(LI $(RELATIVE_LINK2 implicit_enum_comparison_error,Implicit comparison of different enums will now result in an error)) +$(LI $(RELATIVE_LINK2 implicit_string_concatenation_error,Implicit string concatenation will now result in an error)) +$(LI $(RELATIVE_LINK2 iretq,`IRETQ` is now supported in inline assembler.)) +$(LI $(RELATIVE_LINK2 min_runtime_classes,Interfaces and classes can be used without the runtime if only static fields are utilized)) +$(LI $(RELATIVE_LINK2 redundant_stc_error,Specifying redundant storage classes will now result in a compiler error)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 backtrace_debug_info_macos,Filenames and line numbers have been added to stacktraces on macOS)) +$(LI $(RELATIVE_LINK2 cpp_destroy,`object.destroy()` supports `extern(C++)` classes.)) +$(LI $(RELATIVE_LINK2 getsect,Add missing declarations to `core.sys.darwin.mach.getsect`)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 remove_std_c,The deprecated `std.c` package has been removed.)) +$(LI $(RELATIVE_LINK2 std-algorithm-iteration-joiner,The performance of `std.algorithm.iteration.joiner` has been improved)) +$(LI $(RELATIVE_LINK2 std-algorithm-mutation-remove,`std.algorithm.mutation.remove` now only accepts integral values or pair of integral values as offset)) +$(LI $(RELATIVE_LINK2 std-math-fminmax,Changed semantics of std.math.{fmin,fmax} wrt. NaNs.)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 customCachePaths,DUB supports "customCachePaths" for providing read-only package paths)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 deprecate_ctor_in_static_block,Deprecate allowing a constructor declaration in a static block) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecate_ctor_in_static_block.dd) +$(P +Before patch: +The language specification states that a static constructor is +defined using the construction "static this()". Defining a +constructor inside a static block does not have any effect +on the constructor. The following code samples do not affect +the constructor in any way: +) + +--- +static: + this() {} +--- + +--- +static +{ + this() {} +} +--- + +$(P +The compiler does not issue any warning/error on the above code +samples and generates a normal constructor which is not ran before +the main() function. This leads to situations in which the +compiler is not able to correctly indicate the problem: +) + +--- +class A +{ + static + { + this() {} + } + + this() {} +} + +void main() +{ + new A(); +} +--- + +$(P +This code will result in an error message indicating that +there is a multiple definition of the constructor this() +which is a misleading message. +) + +$(P +After patch: +Whenever a constructor is encountered in a static context a +deprecation message is issued stating that the `static` +keyword does not have any effect on the constructor. +The solution is to declare the constructor outside the +static block either as a normal constructor or a static +one (`static this()`). +) +) + +$(LI $(LNAME2 deprecate_this_super_as_types,Deprecate usage of `this` and `super` as types) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecate_this_super_as_types.dd) +$(P +Prior to this release, `this` and `super` could be used as both data or types +depending on the context. Starting with this release using `this` or `super` +as a type will result in a compiler error. +) + +--- +class C +{ + shared(this) x; // Deprecation: Using `this` as a type is deprecated. Use `typeof(this)` instead +} + +class D : C +{ + shared(super) a; // Deprecation: Using `super` as a type is deprecated. Use `typeof(super)` instead + super b; // Deprecation: Using `super` as a type is deprecated. Use `typeof(super)` instead +} +--- + +$(P +Use `typeof(super)` or `typeof(this)` instead. +) + +--- +class C +{ + shared(typeof(this)) x; +} + +class D : C +{ + shared(typeof(super)) a; + typeof(super) b; +} +--- +) + +$(LI $(LNAME2 expression-based_contract_syntax,Implement DIP 1009 - Add Expression-Based Contract Syntax) +$(CHANGELOG_SOURCE_FILE dmd, changelog/expression-based_contract_syntax.dd) +$(P +Expression-based contract syntax has been added: Contracts that consist of a single assertion can now be written more succinctly and multiple `in` or `out` contracts can be specified for the same function. +) + +$(P +Example: +) + +--- +class C { + private int x; + invariant(x >= 0); + // ... +} + +int fun(ref int a, int b) + in(a > 0) + in(b >= 0, "b cannot be negative") + out(r; r > 0, "return must be positive") + out(; a != 0) +{ + // ... +} +--- +) + +$(LI $(LNAME2 extern_cpp_overhaul,`extern (C++)` construction, destruction, operators and other mangling improvements) +$(CHANGELOG_SOURCE_FILE dmd, changelog/extern_cpp_overhaul.dd) +$(P +Many improvements have been made to the `extern(C++)` experience in this release cycle. +) + +$(P +Mangling improvements include: +) + +$(P +$(UL + $(LI Constructor/destructor mangling matches C++) + $(LI Compatible D style operators now mangle as C++ operators) + $(LI `nullptr_t` mangles correctly) + $(LI Various mangling bugs have been fixed) +) +) + +$(P +`extern(C++)` APIs that use `nullptr_t` can use `typeof(null)` on the D side: +) +--- +alias nullptr_t = typeof(null); +extern (C++) void fun(nullptr_t); +--- + +$(P +`extern (C++)` mangling of operators is working for all operators that are semantically equivalent. +This list includes all instantiations of `opUnary`, `opBinary`, `opAssign`, `opOpAssign`, `opCast`, `opEquals`, `opIndex`, `opCall`. +Two notable exceptions are `opCmp`, and C++ `operator !`, which don't have compatible implementations. +) + +$(P +Mangling of `extern (C++) class` constructors and destructor are working. +) + +$(P +This release also includes ABI fixes where destructors are now correctly added to the virtual table, and constructor/destructor calling semantics now match C++. +With this, mixed-language class hierarchies are working, with construction/destruction being supported in either language. +) +) + +$(LI $(LNAME2 fix16206,Support for iterating template overloads) +$(CHANGELOG_SOURCE_FILE dmd, changelog/fix16206.dd) +$(P +`__traits(getOverloads)` has been extended to return template overloads when passed an optional parameter with a true value. +) + +--- +struct S +{ + static int foo()() { return 0; } + static int foo()(int n) { return 1; } + static int foo(string s) { return 2; } + enum foo(int[] arr) = arr.length; +} + +alias AliasSeq(T...) = T; + +alias allFoos = AliasSeq!(__traits(getOverloads, S, "foo", true)); + +static assert(allFoos.length == 4); + +static assert(allFoos[0]("") == 2); +static assert(allFoos[1]() == 0); +static assert(allFoos[2](1) == 1); +alias foo3 = allFoos[3]; +static assert(foo3!([]) == 0); +--- +) + +$(LI $(LNAME2 getlinkage_for_classes,__traits(getLinkage, ...) now works on structs, classes, and interfaces.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/getlinkage_for_classes.dd) +$(P +It is now possible to detect the language ABI specified for a struct, class, or interface. +) + +--- +class MyClass {} +extern (C++) struct MyCPPStruct {} +extern (C++) interface MyCPPInterface {} +extern (Objective-C) interface MyObjcInterface {} +static assert(__traits(getLinkage, MyClass) == "D"); +static assert(__traits(getLinkage, MyCPPStruct) == "C++"); +static assert(__traits(getLinkage, MyCPPInterface) == "C++"); +static assert(__traits(getLinkage, MyObjcInterface) == "Objective-C"); +--- +) + +$(LI $(LNAME2 implicit_catch_error,Implicit `catch` statements will now result in an error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/implicit_catch_error.dd) +$(P +See the $(LINK2 $(ROOT_DIR)deprecate.html#Implicit catch statement, Deprecated Features) +for more information. +) + +$(P +Implicit `catch` statements were deprecated in 2.072. Starting with this release, implicit +`catch` statements will cause the compiler to emit an error. +) + +--- +import std.stdio; + +void main() +{ + int[] arr = new int[](10); + // This will throw a RangeError + try { arr[42]++; } + catch // Error: `catch` statement without an exception specification is deprecated; + // use `catch(Throwable)` for old behavior + { + writeln("An error was caught and ignored"); + } +} +--- +) + +$(LI $(LNAME2 implicit_enum_comparison_error,Implicit comparison of different enums will now result in an error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/implicit_enum_comparison_error.dd) +$(P +See the $(LINK2 $(ROOT_DIR)deprecate.html#Implicit comparison of different enums, Deprecated Features) for more information. +) + +$(P +Implicit comparison of different enums was deprecated in 2.075. Starting with this release, implicit comparison of different +enums will cause the compiler to emit an error. +) + +--- +enum Status +{ + good, + bad +} +enum OtherStatus +{ + ok, + no +} +static assert(Status.good == OtherStatus.ok); // Error: Comparison between different enumeration types `Status` and `OtherStatus`; + // If this behavior is intended consider using `std.conv.asOriginalType` +--- +) + +$(LI $(LNAME2 implicit_string_concatenation_error,Implicit string concatenation will now result in an error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/implicit_string_concatenation_error.dd) +$(P +See the $(LINK2 $(ROOT_DIR)deprecate.html#Implicit%20string%20concatenation, Deprecated Features) for more information. +) + +$(P +Implicit string concatenation was deprecated in 2.072. Starting with this release, implicit string concatenation will cause the compiler +to emit an error. +) + +--- +void main() +{ + string s = "Hello" ", World!"; // Error: Implicit string concatenation is deprecated, use "" ~ "" instead +} +--- +) + +$(LI $(LNAME2 iretq,`IRETQ` is now supported in inline assembler.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/iretq.dd) +$(P +`IRETQ` is the 64-bit version of the already supported `IRET` instruction. With +its inclusion, it is now possible to write 64-bit interrupt service routines +in pure D. +) + +--- +void isr() +{ + asm + { + naked; + // ... + iretq; + } +} +--- +) + +$(LI $(LNAME2 min_runtime_classes,Interfaces and classes can be used without the runtime if only static fields are utilized) +$(CHANGELOG_SOURCE_FILE dmd, changelog/min_runtime_classes.dd) +$(P +Prior to this release any attempt to use interfaces and/or classes without the runtime would result +in compile-time errors due to the lack of `TypeInfo`. However, as long as classes are not instantiated +there is no need for `TypeInfo`. +) + +$(P +Beginning with this release the compiler will no longer emit errors about missing `TypeInfo` when +using interfaces and/or classes as long as they are not instantiated and only `shared static` members are +utilized. +) + +$(P +$(B Example 1) +) +--- +module object + +private alias extern(C) int function(char[][] args) MainFunc; +private extern (C) int _d_run_main(int argc, char** argv, MainFunc mainFunc) +{ + return mainFunc(null); // assumes `void main()` for simplicity +} +--- + +--- +interface I +{ + shared static int i; +} + +class A : I +{ + shared static int a; +} + +class B : A +{ + shared static int b; +} + +void main() +{ + B.b = B.a + B.i; +} +--- + +$(P +$(CONSOLE +dmd -conf= -defaultlib= main.d object.d -of=main +size main + text data bss dec hex filename + 1867 1208 32 3107 c23 main +) +) + +$(P +Non-shared static members can also be used, but will require a thread-local storage (TLS) implementation. +For example, on Linux the TLS implementation is already supplied by the C runtime and C +standard library, so, since dmd automatically calls gcc to link the final executable, it will automatically +bring in the TLS implementation. +) + +$(P +$(B Example 2) +) +--- +module object + +private alias extern(C) int function(char[][] args) MainFunc; +private extern (C) int _d_run_main(int argc, char** argv, MainFunc mainFunc) +{ + return mainFunc(null); // assumes `void main()` for simplicity +} +--- + +--- +interface I +{ + static int i; +} + +class A : I +{ + static int a; +} + +class B : A +{ + static int b; +} + +void main() +{ + B.b = B.a + B.i; +} +--- + +$(P +$(CONSOLE +dmd -conf= -defaultlib= main.d object.d -of=main +size main + text data bss dec hex filename + 2123 1296 28 3447 d77 main +) +) + +$(P +Some platforms may require some TLS implementation code or some specialized build procedures to link +in a TLS implementation. +) + +$(P +This will hopefully reduce friction for those using D without the runtime, porting D to new platforms, +or using D from other langauges, while enabling more features and idioms of D to be used in those use cases. +) +) + +$(LI $(LNAME2 redundant_stc_error,Specifying redundant storage classes will now result in a compiler error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/redundant_stc_error.dd) +$(P +Specifying redundant storage classes was deprecated long ago and was originally scheduled to emit a compiler error beginning with the 2.068 release. +That promise has been fulfilled with this release. +) + +--- +@safe void f() @safe {} // Error: redundant attribute `@safe` +--- +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 backtrace_debug_info_macos,Filenames and line numbers have been added to stacktraces on macOS) +$(CHANGELOG_SOURCE_FILE druntime, changelog/backtrace_debug_info_macos.dd) +$(P +When an exception is throw and not caught, a stacktrace is printed. On Linux, +FreeBSD and DragonFlyBSD this stacktrace includes the filenames and line numbers, +if the application was built with debug info enabled. This feature has now been +added to macOS. +) + +$(P +This requires support from the compiler since debug info is stripped by the +linker on macOS. +) + +$(P +Example: +) + +--- +void bar() +{ + throw new Exception("bar"); +} + +void foo() +{ + bar(); +} + +void main() +{ + foo(); +} +--- + +$(P +Compiling the above code, with debug info enabled, by running: `dmd -g main.d`. +When running the application it will produce an output similar to: +) + +$(P +$(CONSOLE +object.Exception@main.d(3): bar +main.d:3 void main.bar() [0x71afdfb] +main.d:8 void main.foo() [0x71afe0c] +main.d:13 _Dmain [0x71afd78] +) +) +) + +$(LI $(LNAME2 cpp_destroy,`object.destroy()` supports `extern(C++)` classes.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/cpp_destroy.dd) +$(P +`object.destroy()` was crashing when called with an `extern(C++)` class. It now correctly destructs and resets the object to `init`. +) +) + +$(LI $(LNAME2 getsect,Add missing declarations to `core.sys.darwin.mach.getsect`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/getsect.dd) +$(P +Declarations that were missing from $(LINK2 https://opensource.apple.com/source/cctools/cctools-895/include/mach-o/getsect.h.auto.html, mach-o/getsect.h) has been added to `core.sys.darwin.mach.getsect`. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 remove_std_c,The deprecated `std.c` package has been removed.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/remove_std_c.dd) +$(P +Use the `core.stdc` package instead. +) +) + +$(LI $(LNAME2 std-algorithm-iteration-joiner,The performance of `std.algorithm.iteration.joiner` has been improved) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-algorithm-iteration-joiner.dd) +$(P +$(H4 DMD) +) + +$(P +$(CONSOLE +\> dmd -O -inline -release ./joiner.d && ./joiner +before.joiner = 57 secs, 834 ms, 289 μs, and 3 hnsecs +new.joiner = 44 secs, 936 ms, 706 μs, and 5 hnsecs +) +) + +$(P +$(H4 LDC) +) + +$(P +$(CONSOLE +\> ldmd -O3 -release -inline joiner.d && ./joiner +before.joiner = 5 secs, 180 ms, 193 μs, and 7 hnsecs +new.joiner = 3 secs, 168 ms, 560 μs, and 6 hnsecs +) +) + +$(P +The benchmark code can be found $(LINK2 https://gist.github.com/wilzbach/ffd5d20639766a831fd4b1962572897a, here). +) +) + +$(LI $(LNAME2 std-algorithm-mutation-remove,`std.algorithm.mutation.remove` now only accepts integral values or pair of integral values as offset) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-algorithm-mutation-remove.dd) +$(P +Previously, without being stated in the documentation, +$(REF remove, std,algorithm) used to accept any values as `offset`. +This behavior was very error-prone: +) + +--- +import std.algorithm, std.stdio; +[0, 1, 2, 3, 4].remove(1, 3).writeln; // 0, 2, 4 -- correct +[0, 1, 2, 3, 4].remove([1, 3]).writeln; // 0, 3, 4 -- incorrect +--- + +$(P +With this release, using arrays as individual elements is no longer valid. +$(REF tuple, std,typecons) can be used to explicitly indicate that a range +from `start` to `stop` (non-enclosing) should be removed: +) + +--- +import std.algorithm, std.stdio, std.typecons; +[0, 1, 2, 3, 4].remove(tuple(1, 3)).writeln; // 0, 3, 4 +--- + +$(P +However, only 2-tuples are allowed to avoid this un-intuitive scenario: +) + +--- +import std.algorithm, std.stdio, std.typecons; +[0, 1, 2, 3, 4].remove(tuple(1, 3, 4)).writeln; // 0, 4? +--- +) + +$(LI $(LNAME2 std-math-fminmax,Changed semantics of std.math.{fmin,fmax} wrt. NaNs.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-math-fminmax.dd) +$(P +The semantics of $(REF fmin, std, math) and $(REF fmax, std, math) have been +streamlined with the C functions: if one of the arguments is a NaN, return the +other. This involves an additional $(REF isNaN, std, math) check. Use +$(REF min, std, algorithm, comparison) and $(REF max, std, algorithm, comparison) +for the previous semantics performing a single comparison. +) + +--- +import std.math; +assert(fmin(real.nan, 2.0L) == 2.0L); +assert(fmin(2.0L, real.nan) == 2.0L); // previously: NaN +assert(isNaN(fmin(real.nan, real.nan))); + +import std.algorithm.comparison; +assert(min(real.nan, 2.0L) == 2.0L); +assert(isNaN(min(2.0L, real.nan))); +assert(isNaN(min(real.nan, real.nan))); +--- +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 customCachePaths,DUB supports "customCachePaths" for providing read-only package paths) +$(CHANGELOG_SOURCE_FILE dub, changelog/customCachePaths.dd) +$(P +With this release DUB allows defining additional paths that contain packages in subfolders with the pattern "(name)-(version)/(name)/" by defining a "customCachePaths" field in `/etc/dub/settings.json` or `~/.dub/settings.json.` +) + +$(P +"customCachePaths" can be used to provide prebuilt DUB libraries (e.g. for distribution package maintainers). +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 18068): No file names and line numbers in stack trace) +$(LI $(BUGZILLA 18821): DMD segfault when doing unsafe operation outside of any function) +$(LI $(BUGZILLA 18905): [Reg 2.079] C++ classes can no longer be used with -betterC) +$(LI $(BUGZILLA 18936): Internal error: dmd/backend/cgxmm.c 684) +$(LI $(BUGZILLA 19024): [REG 2.081-beta] AssertError@dmd/dsymbolsem.d$(LPAREN)4317$(RPAREN): Assertion failure) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 5153): Struct pointer to struct variable assign error message) +$(LI $(BUGZILLA 7443): Better diagnostic on wrongly written static constructor) +$(LI $(BUGZILLA 11742): cannot inizialize void initialized static variable in static constructor.) +$(LI $(BUGZILLA 12764): Disabled struct default construction circumvented when field is written to) +$(LI $(BUGZILLA 12807): UFCS checks "alias this" attributes even when not called) +$(LI $(BUGZILLA 13435): Strange error if struct is a class member and opAssign applied) +$(LI $(BUGZILLA 13741): std.traits.moduleName & packageName do not work with functions that have parameters) +$(LI $(BUGZILLA 14178): C++ linux name mangling does not handle standard abbreviations for const types) +$(LI $(BUGZILLA 14739): Immutable alias to template triggers dmd assert) +$(LI $(BUGZILLA 15068): wrong error message on attempting to use type as template) +$(LI $(BUGZILLA 15388): extern$(LPAREN)C++$(RPAREN) - typeof$(LPAREN)null$(RPAREN) should mangle as nullptr_t) +$(LI $(BUGZILLA 15475): Ddoc code sample with unbalanced paren comes out as macro) +$(LI $(BUGZILLA 15574): wrong order of linker arguments) +$(LI $(BUGZILLA 15755): DMD segfault upon alias on alias on __trait$(LPAREN)getAttributes, ...$(RPAREN)) +$(LI $(BUGZILLA 15869): RVO can overwrite argument) +$(LI $(BUGZILLA 16088): Parse error for import expression in statement) +$(LI $(BUGZILLA 16206): traits getOverloads fails when one of the overload is a templatized function) +$(LI $(BUGZILLA 17373): traits getOverloads + multiple interface inheritance only see one of the interfaces' overloads) +$(LI $(BUGZILLA 18228): this$(LPAREN)this a$(RPAREN){} doesn't generate postblit ctor; this$(LPAREN)this$(RPAREN){} does) +$(LI $(BUGZILLA 18236): Invalid line reported on error casting enum) +$(LI $(BUGZILLA 18266): ICE: should allow reusing identifier in declarations in disjoint scopes in a function) +$(LI $(BUGZILLA 18365): header file generation doesn't include the return attribute) +$(LI $(BUGZILLA 18584): Undefined identifier when not specifying 'this') +$(LI $(BUGZILLA 18730): dmd miscompiles core.bitop.bt with -O) +$(LI $(BUGZILLA 18746): function returning empty struct isn't called if used in equality expression) +$(LI $(BUGZILLA 18775): DMD falsely reports deprecation for deprecated implicit casts that were not used in UFCS) +$(LI $(BUGZILLA 18803): just "static if" in nested import crashes dmd) +$(LI $(BUGZILLA 18828): [-betterC] helpless error in object.d) +$(LI $(BUGZILLA 18858): switch 'skips declaration' test only checks last declaration) +$(LI $(BUGZILLA 18868): Separate compilation generates two static this functions, runs it twice) +$(LI $(BUGZILLA 18888): extern$(LPAREN)C++$(RPAREN) template arg/alias arg mangling issue) +$(LI $(BUGZILLA 18890): extern$(LPAREN)C++$(RPAREN) mangles all destructors the same) +$(LI $(BUGZILLA 18891): extern$(LPAREN)C++$(RPAREN) destructor prototype should just link; not generate field/aggregate dtor) +$(LI $(BUGZILLA 18892): Wrong type in error message for static members and alias this) +$(LI $(BUGZILLA 18916): ICE using Typedef and __LINE__) +$(LI $(BUGZILLA 18922): dmd doesn't do substitutions for C++ namespaces in different module/file) +$(LI $(BUGZILLA 18928): extern$(LPAREN)C++$(RPAREN) bad codegen, wrong calling convention) +$(LI $(BUGZILLA 18951): package static method masked by public static method in class) +$(LI $(BUGZILLA 18953): Win32: extern$(LPAREN)C++$(RPAREN) struct destructor not called correctly through runtime) +$(LI $(BUGZILLA 18957): extern$(LPAREN)C++$(RPAREN) doesn't mangle 'std' correctly on posix systems) +$(LI $(BUGZILLA 18966): extern$(LPAREN)C++$(RPAREN) constructor should match C++ semantics assigning vtable) +$(LI $(BUGZILLA 18970): DMD segfault due to opDispatch) +$(LI $(BUGZILLA 18976): Inconsistency in overload merging with aliases) +$(LI $(BUGZILLA 18984): Debugging stack structs which are returned causes incorrect debuginfo.) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 14086): Invalid extern C++ name for constructor / destructor) +$(LI $(BUGZILLA 15589): extern$(LPAREN)C++$(RPAREN) virtual destructors are not put in vtbl[]) +$(LI $(BUGZILLA 15691): Improve error message for struct member initializer) +$(LI $(BUGZILLA 18859): Silence class allocator/deallocator deprecation warning if they are marked "deprecated") +$(LI $(BUGZILLA 18963): Relax restrictions on 'return' parameters when parameter is not a pointer) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 18937): [REG 2.080.0] std.experimental.allocator: compiling `make` needs an unreasonable amount of memory for structs that contain static arrays) +$(LI $(BUGZILLA 18993): toLower is broken for UTF chars) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 12086): std.algorithm.remove + range of indices produces wrong results) +$(LI $(BUGZILLA 17084): Can't sort array of structs with alias this: swap can't call non-@nogc function doesPointTo) +$(LI $(BUGZILLA 17806): processAllocator getter will override set value if it was set before getter was called at least once) +$(LI $(BUGZILLA 18415): Typedef ignores @disabled default constructor) +$(LI $(BUGZILLA 18470): std.algorithm.splitter has frame access problems for custom preds) +$(LI $(BUGZILLA 18525): Constraint on std.algorithm.mutation.remove fails with char[]) +$(LI $(BUGZILLA 18760): theAllocator should hold a reference to the allocator that it uses) +$(LI $(BUGZILLA 18847): std.allocator: Region uses .parent before it can be set) +$(LI $(BUGZILLA 18934): std.concurrency receive throws assertion failure if message is a struct containing const data) +$(LI $(BUGZILLA 18940): [std.net.curl]Can't run examples on page. cannot implicitly convert expression ... `char[]` to `string`) +$(LI $(BUGZILLA 18952): std.experimental.checkedint.Saturate prints integral promotion deprecation message) +$(LI $(BUGZILLA 19020): findSkip, findSplit and findSplitBefore return wrong results) +$(LI $(BUGZILLA 19023): findSplitBefore and findSplitAfter give wrong bool result) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 18178): std.path should be usable in @safe) +$(LI $(BUGZILLA 18593): std.datetime.stopwatch.benchmark shouldn't optimize away its functions) +$(LI $(BUGZILLA 18766): std.typecons.Tuple.toHash could be improved) +$(LI $(BUGZILLA 18813): fromStringz should work with char, wchar and dchar) +$(LI $(BUGZILLA 18837): MMFile should have opDollar) +$(LI $(BUGZILLA 18948): std.uni.toLower and std.uni.toUpper should work with random access ranges) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 18996): Inserting a type containing indirections into an std.container Array causes SIGILL$(LPAREN)4$(RPAREN). Illegal Instruction.) +$(LI $(BUGZILLA 19005): [REG2.081-b1] object.hashOf no longer works for std.datetime.date.Date) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 14536): Calling destroy$(LPAREN)$(RPAREN) on a on an extern$(LPAREN)C++$(RPAREN) class causes a segfault) +$(LI $(BUGZILLA 18932): core.internal.hash.hashOf$(LPAREN)val, seed$(RPAREN) ignores `seed` when val is a raw pointer) +$(LI $(BUGZILLA 18989): On OSX32, core.stdc.time.clock$(LPAREN)$(RPAREN) should resolve to clock$UNIX2003$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 19008): core.internal.convert.toUbyte doesn't work on enums) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 18768): object.getArrayHash with custom toHash shouldn't just sum hashes of array elements) +$(LI $(BUGZILLA 18920): core.internal.hash of array of scalars should be `@safe`) +$(LI $(BUGZILLA 18924): Use addition rather than XOR for order-independent hash combination) +$(LI $(BUGZILLA 18925): core.internal.hash auto-hash for structs of scalar fields should be `@safe`) +$(LI $(BUGZILLA 18943): core.internal.hash remove outdated special case for DMD unaligned reads) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 18752): std.file.read runnable example fails) +$(LI $(BUGZILLA 18761): Page for assumeUnique documentation displays incorrectly) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 14099): Promote DPaste $(LPAREN)dpaste.dzfl.pl$(RPAREN) to run.dlang.org) +$(LI $(BUGZILLA 18869): Add Jumia Food to organizations using D) +$(LI $(BUGZILLA 18874): Add thatneedle.com to organizations using D) +$(LI $(BUGZILLA 18959): [Change Log: 2.079.0] substitute was added in std.algorithm.iteration but the changelog points to std.algorithm.searching) +) +) +$(D_CONTRIBUTORS_HEADER 51) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Alexandru Jercaianu) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR BBasile) + $(D_CONTRIBUTOR carblue) + $(D_CONTRIBUTOR David Bennett) + $(D_CONTRIBUTOR David Gileadi) + $(D_CONTRIBUTOR Diederik de Groot) + $(D_CONTRIBUTOR Dmitry Olshansky) + $(D_CONTRIBUTOR Eduard Staniloiu) + $(D_CONTRIBUTOR Giles Bathgate) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jack Stouffer) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR jercaianu) + $(D_CONTRIBUTOR Joakim Noah) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR Jonathan Marler) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR Leandro Lucarella) + $(D_CONTRIBUTOR leitimmel) + $(D_CONTRIBUTOR Manu Evans) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Lindsay Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Quirin F. Schroll) + $(D_CONTRIBUTOR Radosław Rusiniak) + $(D_CONTRIBUTOR Radu Racariu) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Remi Thebault) + $(D_CONTRIBUTOR Roman Chistokhodov) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Tero Hänninen) + $(D_CONTRIBUTOR thaven) + $(D_CONTRIBUTOR Thibaut CHARLES) + $(D_CONTRIBUTOR Timon Gehr) + $(D_CONTRIBUTOR Timoses) + $(D_CONTRIBUTOR Tomáš Chaloupka) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.081.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.081.1.dd b/changelog/2.081.1.dd new file mode 100644 index 0000000000..ac89bdea8a --- /dev/null +++ b/changelog/2.081.1.dd @@ -0,0 +1,33 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 10, 2018, =================================================, + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 19064): [REG2.081] getOverloads traits returns empty tuples for void functions) +$(LI $(BUGZILLA 19066): [REG 2.080.1] Error: `const$(LPAREN)Object$(RPAREN)` is used as a type with structs that have symbol named Object) +) +) +$(D_CONTRIBUTORS_HEADER 6) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Steven Schveighoffer) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.081.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.081.2.dd b/changelog/2.081.2.dd new file mode 100644 index 0000000000..10582e175f --- /dev/null +++ b/changelog/2.081.2.dd @@ -0,0 +1,45 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Aug 12, 2018, =================================================, + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 19074): [REG 2.080] SIGSEGV in el_ptr $(LPAREN)s=0x15$(RPAREN) at dmd/backend/el.c:1760) +$(LI $(BUGZILLA 19076): dmd 2.081 crashed by getVirtualFunctions for a interface extended interface) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 19112): Associative array opIn with static array key fails with dynamic array) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 19082): Cannot inline "...Slides.numberOfFullFrames", "...Slides.gap") +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 19092): __delete doesn't work with immutable) +) +) +$(D_CONTRIBUTORS_HEADER 6) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Sebastian Wilzbach) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.081.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.082.0.dd b/changelog/2.082.0.dd new file mode 100644 index 0000000000..25d3f9db7f --- /dev/null +++ b/changelog/2.082.0.dd @@ -0,0 +1,911 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 01, 2018, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 28 major changes and 76 fixed Bugzilla issues. + A huge thanks goes to the 50 contributors who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 betterc_cmp_types,Support for comparing arrays of unsigned byte-sized types and structs has been added to -betterC)) +$(LI $(RELATIVE_LINK2 betterc_versions,Added `D_ModuleInfo`, `D_Exceptions`, and `D_TypeInfo` version identifiers)) +$(LI $(RELATIVE_LINK2 cond_assign,Deprecate conditional expression followed by an assign expression)) +$(LI $(RELATIVE_LINK2 debug-unsafe,Unsafe code can now be used in debug blocks)) +$(LI $(RELATIVE_LINK2 deprecate-opDot,Deprecate usage of `opDot`)) +$(LI $(RELATIVE_LINK2 enum_attributes,D now supports deprecated, @disable and user-defined attributes on enum members)) +$(LI $(RELATIVE_LINK2 error_for_c-style_arrays,Deprecated C-style array declarations will now result in a compilation error)) +$(LI $(RELATIVE_LINK2 fix19043,Mangling of extern(C++) template on Windows now correctly mangles const non-pointer template parameters.)) +$(LI $(RELATIVE_LINK2 objc_offsetof_tupleof,`.offsetof` and `.tupleof` for fields of Objective-C classes have now been disabled)) +$(LI $(RELATIVE_LINK2 osx64_long_cppmangling,64-bit OS X: Revert C++ mangling of `long` to pre-2.079 to restore `size_t` interop)) +$(LI $(RELATIVE_LINK2 uda-function-parameters,UDAs on function parameters are now supported)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 exceptions-opt,Exception trapping can now be disabled via `--DRT-trapExceptions=0`)) +$(LI $(RELATIVE_LINK2 require_update,Additional functions for associative arrays)) +$(LI $(RELATIVE_LINK2 typeinfo-gethash,`TypeInfo.getHash` now uses `core.internal.hash.hashOf` functions for hash computing)) +$(LI $(RELATIVE_LINK2 utsname_version,core.sys.posix.utsname.update renamed to version_)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 math_float_double_implementations,Single- and double-precision implementations for (a)tan and exp function families)) +$(LI $(RELATIVE_LINK2 std-algorithm-iteration-each-early-stopping,`std.algorithm.iteration.each` is now capable of early-stopping)) +$(LI $(RELATIVE_LINK2 std-algorithm-iteration-joiner,`std.algorithm.iteration.joiner` can now be used for bidirectional ranges)) +$(LI $(RELATIVE_LINK2 std-algorithm-searching-skipOver,`std.algorithm.searching.skipOver` can now handle variadic arguments)) +$(LI $(RELATIVE_LINK2 std-array-asStatic,Added `staticArray` to construct a static array from array / input range. Includes a length-inferring compile-time variant.)) +$(LI $(RELATIVE_LINK2 std-datetime-timezone-remove,Deprecated functions for getting the timezone have been removed.)) + +) + +$(BUGSTITLE_TEXT_HEADER Installer changes, + +$(LI $(RELATIVE_LINK2 signed_windows_binaries,Windows installer and binaries are now code-signed)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 buildSettingsVars,Variables such as `$ARCH` or `$PLATFORM` are now supported in the build settings.)) +$(LI $(RELATIVE_LINK2 buildTypeSyntax,DUB supports build type "syntax")) +$(LI $(RELATIVE_LINK2 env-var-replacement,Enviroment variable expansion was improved)) +$(LI $(RELATIVE_LINK2 recursive_dependecy_resolution,Dependency resolution has been reimplemented using a recursive algorithm)) +$(LI $(RELATIVE_LINK2 stdinForSingleFilePackages,DUB accepts single file packages on STDIN)) +$(LI $(RELATIVE_LINK2 upgrade_check,The regular upgrade check has been removed)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 betterc_cmp_types,Support for comparing arrays of unsigned byte-sized types and structs has been added to -betterC) +$(CHANGELOG_SOURCE_FILE dmd, changelog/betterc_cmp_types.dd) +$(P +Prior to this release, the following code did not build in -betterC, but will with this release. +) + +--- +// (Prior to this release) Error: TypeInfo cannot be used with -betterC +struct Sint +{ + int x; + this(int v) { x = v;} +} + +extern(C) void main() +{ + Sint[6] a1 = [Sint(1), Sint(2), Sint(3), Sint(1), Sint(2), Sint(3)]; + assert(a1[0..3] == a1[3..$]); +} +--- + +--- +// (Prior to this release) Linker Error: undefined reference to `core.internal.string.dstrcmp` +extern(C) void main() +{ + auto s = "abc"; + switch(s) + { + case "abc": + break; + default: + break; + } +} +--- + +--- +// (Prior to this release) Linker Error: undefined reference to `core.internal.string.dstrcmp` +extern(C) void main() +{ + char[6] a = [1,2,3,1,2,3]; + assert(a[0..3] >= a[3..$]); // failed for any byte-sized type (e.g. `char`, `ubyte`, etc...) +} +--- +) + +$(LI $(LNAME2 betterc_versions,Added `D_ModuleInfo`, `D_Exceptions`, and `D_TypeInfo` version identifiers) +$(CHANGELOG_SOURCE_FILE dmd, changelog/betterc_versions.dd) +$(P +`D_ModuleInfo`, `D_Exceptions`, and `D_TypeInfo` version identifiers were added to allow +better precision in druntime and other library implementations. +) + +$(P +See $(LINK2 https://dlang.org/spec/version.html#predefined-versions, Predefined Versions) +) +) + +$(LI $(LNAME2 cond_assign,Deprecate conditional expression followed by an assign expression) +$(CHANGELOG_SOURCE_FILE dmd, changelog/cond_assign.dd) +$(P +When a conditional expression is the left operand of an assign +expression, they would be parsed as an assignment to $(I the result) of +the conditional. This has now been deprecated. To preserve the existing +behaviour, add parentheses for the conditional without including the +assignment: +) + +--- +bool test; +int a, b, c; +... +test ? a = b : c = 2; // Deprecated +(test ? a = b : c) = 2; // Equivalent +--- + +$(P +This makes the intent clearer, because the first statement can easily +be misread as the following code: +) + +--- +test ? a = b : (c = 2); +--- +) + +$(LI $(LNAME2 debug-unsafe,Unsafe code can now be used in debug blocks) +$(CHANGELOG_SOURCE_FILE dmd, changelog/debug-unsafe.dd) +$(P +When writing debug code, one isn't interested in the type safety, but a pleasant +debugging experience. +The type checker already allowed to escape `pure` and `@nogc` within `debug` +statement. +With this release, `@system` code can be called from `debug` statements too: +) + +--- +void main() +{ + int[] arr = [1, 2]; + debug unsafeCode(arr); +} + +@system void unsafeCode(T)(T[] arr) +{ + import core.stdc.stdio; + printf("arr.ptr: %p", arr.ptr); +} +--- +) + +$(LI $(LNAME2 deprecate-opDot,Deprecate usage of `opDot`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecate-opDot.dd) +$(P +`opDot` was the D1 analog to `alias this`. +However, `alias this` covers all use cases of `opDot`, but ensures safety. +) + +--- +struct S +{ + int a, b; +} +struct T +{ + S s; + + S* opDot() + { + return &s; + } +} + +void main() +{ + T t; + t.a = 4; + assert(t.a == 4); + t.b = 5; +} +--- + +$(P +With `alias this`: +) + +--- +struct S +{ + int a, b; +} +struct T +{ + S s; + + alias s this; +} + +void main() @safe +{ + T t; + t.a = 4; + assert(t.a == 4); + t.b = 5; +} +--- +) + +$(LI $(LNAME2 enum_attributes,D now supports deprecated, @disable and user-defined attributes on enum members) +$(CHANGELOG_SOURCE_FILE dmd, changelog/enum_attributes.dd) +$(P +Example +) +--- +template AliasSeq(TList...) +{ + alias AliasSeq = TList; +} + +enum MyEnum +{ + @("uda0") value0, + @disable value1, + deprecated value2 // Deprecation: enum member `main.MyEnum.value2` is deprecated +} + +static assert(__traits(getAttributes, MyEnum.value0) == AliasSeq!("uda0")); + +void main() +{ + auto v1 = MyEnum.value1; // Error: enum member `main.MyEnum.value1` cannot be used because it is annotated with `@disable` +} +--- +) + +$(LI $(LNAME2 error_for_c-style_arrays,Deprecated C-style array declarations will now result in a compilation error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/error_for_c-style_arrays.dd) +$(P +The deprecation period for C-style array declarations has expired. Beginning with this +release, declaring arrays with C-style syntax will result in an error. +) + +--- +int a[2]; // Error: instead of C-style syntax, use D-style `int a[2]` +int[2] b; // OK +--- +) + +$(LI $(LNAME2 fix19043,Mangling of extern(C++) template on Windows now correctly mangles const non-pointer template parameters.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/fix19043.dd) +$(P +It used to ignore the const and was missing the $$C escape prefix. +) + +----- +extern(C++) struct foo(T) {} + +extern(C++) void test(foo!(const(char)) a) {} +// New +static assert(test.mangleof == "?test@@YAXU?$foo@$$CBD@@@Z"); +// Old +//static assert(test.mangleof == "?test@@YAXU?$foo@D@@@Z"); +----- +) + +$(LI $(LNAME2 objc_offsetof_tupleof,`.offsetof` and `.tupleof` for fields of Objective-C classes have now been disabled) +$(CHANGELOG_SOURCE_FILE dmd, changelog/objc_offsetof_tupleof.dd) +$(P +To solve the fragile base class problem [1] in Objective-C, fields have a +dynamic offset instead of a static offset. The compiler outputs a statically +known offset which later the dynamic loader can update, if necessary, when the +application is loaded. Due to this behavior it doesn't make sense to be able to +get the offset of a field at compile time, because this offset might not +actually be the same at runtime. +) + +$(P +To get the offset or value of a field, that is correct at runtime, functionality +from the Objective-C runtime can be used instead [2]. +) + +$(P +[1] $(LINK2 https://en.wikipedia.org/wiki/Fragile_binary_interface_problem, Fragile Binary Interface Problem) +[2] $(LINK2 https://developer.apple.com/documentation/objectivec/objective_c_runtime, Objective-C Runtime) +) +) + +$(LI $(LNAME2 osx64_long_cppmangling,64-bit OS X: Revert C++ mangling of `long` to pre-2.079 to restore `size_t` interop) +$(CHANGELOG_SOURCE_FILE dmd, changelog/osx64_long_cppmangling.dd) +$(P +Direct interop of D `size_t` and C++ `size_t` was working before 2.079, on all platforms +except for 32-bit OS X. By mangling D `long` as C++ `long long` on 64-bit OS X starting +with 2.079, `size_t` interop broke on a more relevant platform. +With new/fixed aliases, e.g., $(REF int64_t, core, stdc, stdint), +$(REF uint64_t, core, stdc, stdint) and $(REF cpp_size_t, core, stdc, config), there are +now proper tools for portable C++ interop wrt. integers. +Reverting to the previous C++ mangling on 64-bit OS X (C++ `long`) may save mixed D/C++ +code bases from the need of manual adaptations by skipping the 2.079-2.081 DMD versions. +) +) + +$(LI $(LNAME2 uda-function-parameters,UDAs on function parameters are now supported) +$(CHANGELOG_SOURCE_FILE dmd, changelog/uda-function-parameters.dd) +$(P +User-defined attributes on function parameters behave analogous to existing UDAs: +) + +--- +void example(@(22) string param) +{ + @(11) string var; + static assert([__traits(getAttributes, var)] == [11]); + static assert([__traits(getAttributes, param)] == [22]); +} +--- +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 exceptions-opt,Exception trapping can now be disabled via `--DRT-trapExceptions=0`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/exceptions-opt.dd) +$(P +Previously it was only possible to disable the trapping of exception by setting +the global variable `rt_trapExceptions` to `false`. +Now you can, for example, immediately open `gdb` at the uncaught exception: +) + +$(P +$(CONSOLE +\> gdb -ex run --args --DRT-trapExceptions=0 +[Thread debugging using libthread_db enabled] +Using host libthread_db library "/usr/lib/libthread_db.so.1". +uncaught exception +object.Exception@src/rt_trap_exceptions_drt.d(4): foo +$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH) +src/rt_trap_exceptions_drt.d:4 void rt_trap_exceptions_drt.test() [0x55591026] +src/rt_trap_exceptions_drt.d:9 _Dmain [0x55591058] +$(P) +Program received signal SIGABRT, Aborted. +0x00007ffff6e7b86b in raise () from /usr/lib/libc.so.6 +(gdb) bt full +#0 0x00007ffff6e7b86b in raise () from /usr/lib/libc.so.6 +No symbol table info available. +#1 0x00007ffff6e6640e in abort () from /usr/lib/libc.so.6 +No symbol table info available. +#2 0x00005555555918cc in _d_throwdwarf (o=0x7ffff7ea4000) at src/rt/dwarfeh.d:233 + eh = 0x7ffff7fa4740 + refcount = 0 + r = 5 +#3 0x0000555555591027 in rt_trap_exceptions_drt.test() () at ../../src/object.d:2695 + innerLocal = 20 +#4 0x0000555555591059 in D main (args=...) at src/rt_trap_exceptions_drt.d:9 + myLocal = "bar" +) +) + +$(P +$(LINK2 http://arsdnet.net/this-week-in-d/2016-aug-07.html, This Week in D) for +an in-depth explanation of `rt_trapExceptions` +) +) + +$(LI $(LNAME2 require_update,Additional functions for associative arrays) +$(CHANGELOG_SOURCE_FILE druntime, changelog/require_update.dd) +$(P +The $(D require) function provides a means to construct a new value when the key +is not present. +) + +--------- +class C{} +C[string] aa; + +auto a = aa.require("a", new C); // lookup "a", construct if not present +--------- + +$(P +The $(D update) function allows different operations to be performed depending +on whether a value already exists or needs to be constructed. +) + +--------- +class C{} +C[string] aa; + +C older; +C newer; +aa.update("a", +{ + newer = new C; + return newer; +}, +(ref C c) +{ + older = c; + newer = new C; + return newer; +}); +--------- + +$(P +The functions avoid the need to perform multiple key lookups. Further details +are available in the $(LINK2 $(ROOT_DIR)spec/hash-map.html, spec.) +) +) + +$(LI $(LNAME2 typeinfo-gethash,`TypeInfo.getHash` now uses `core.internal.hash.hashOf` functions for hash computing) +$(CHANGELOG_SOURCE_FILE druntime, changelog/typeinfo-gethash.dd) +$(P +Now `typeid(typeof(var)).getHash(&var)` should be always equal `hashOf(val)`. +hashOf uses MurmurHash3 algorithm for bitwise hashing, including string hashing. +Old implementation used polynomial hash for string hashing, which often provided +lexicographical order of strings in associative array. However AA doesn't guarantee +some specific order of elements, thus tests which rely on it should be changed. +) +) + +$(LI $(LNAME2 utsname_version,core.sys.posix.utsname.update renamed to version_) +$(CHANGELOG_SOURCE_FILE druntime, changelog/utsname_version.dd) +$(P +The struct that $(D uname) returns - $(D utsname) - has the field $(D version) +in C. The D definition of the struct cannot match that, because $(D version) is +a keyword in D. So, it's been called $(D update), which is not an obvious +choice. It is more in line with current naming policies (and more in line with +the name in C) for it to be called $(D version_), since that's the closest that +we can get to $(D version) in D. So, $(D update) has now been renamed to +$(D version_), and $(D update) is an alias of $(D version_) which will be +deprecated in a future release. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 math_float_double_implementations,Single- and double-precision implementations for (a)tan and exp function families) +$(CHANGELOG_SOURCE_FILE phobos, changelog/math_float_double_implementations.dd) +$(P +The `float` and `double` overloads of +$(REF atan, std, math), $(REF atan2, std, math), $(REF tan, std, math), +$(REF exp, std, math), $(REF expm1, std, math) and $(REF exp2, std, math) +previously forwarded to the `real` implementation (inline assembly) and +now got proper 'software' implementations in the corresponding precision. +) + +$(P +While this may result in a slowdown in some cases for DMD (especially for +`exp()` and `exp2()`), the overall speed-up factor for LDC is > 3, for +both `double` and `float`. +) + +$(P +This also implies less precise results, especially in single-precision, +so if your code depended on more accurate results via 80-bit intermediate +precision, you'll have to cast the argument(s) explicitly now. +) +) + +$(LI $(LNAME2 std-algorithm-iteration-each-early-stopping,`std.algorithm.iteration.each` is now capable of early-stopping) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-algorithm-iteration-each-early-stopping.dd) +$(P +$(REF each, std,algorithm,iteration) is now capable of exiting early. +When a `No.each` $(REF Flag, std,typecons) is returned from the function that +is called by `each`, the iteration will be aborted early. +Analogously, returning `Yes.each` will continue the iteration. +For example: +) + +--- +auto arr = [10, 20, 30]; +arr.each!((n) { arr ~= n; return (n == 20) ? No.each : Yes.each; }); // aborts after the second iteration +assert(arr == [10, 20, 30, 10, 20]); +--- +) + +$(LI $(LNAME2 std-algorithm-iteration-joiner,`std.algorithm.iteration.joiner` can now be used for bidirectional ranges) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-algorithm-iteration-joiner.dd) +$(P +$(REF joiner, std,algorithm,iteration) can now be requested to be a bidirectional range. +) + +--- +import std.algorithm.iteration : joiner; +import std.range : retro; +[[1, 2], [3, 4]].joiner.retro; // [4, 3, 2, 1] +--- + +$(P +A more complex example of inserting a format delimiter fully lazily: +) + +--- +import std.algorithm.comparison : equal; +import std.range : chain, cycle, iota, only, retro, take, zip; +import std.format : format; + +static immutable number = "12345678"; +static immutable delimiter = ","; +auto formatted = number.retro + .zip(3.iota.cycle.take(number.length)) + .map!(z => chain(z[0].only, z[1] == 2 ? delimiter : null)) + .joiner + .retro; // "12,345,678" +--- +) + +$(LI $(LNAME2 std-algorithm-searching-skipOver,`std.algorithm.searching.skipOver` can now handle variadic arguments) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-algorithm-searching-skipOver.dd) +$(P +$(REF skipOver, std,algorithm) which allows to move over a needle if it matches +now accepts variadic arguments for needles to skip over: +) + +--- +auto s = "DLang.rocks"; +assert(!s.skipOver("dlang", "DLF", "DLang ")); +assert(s == "DLang.rocks"); + +assert(s.skipOver("dlang", "DLANG", "DLF", "D", "DL", "DLanp")); +assert(s == "ang.rocks"); +--- +) + +$(LI $(LNAME2 std-array-asStatic,Added `staticArray` to construct a static array from array / input range. Includes a length-inferring compile-time variant.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-array-asStatic.dd) +$(P +The type of elements can be specified implicitly so that $(D [1, 2].staticArray) results in `int[2]`, +or explicitly, e.g. $(D [1, 2].staticArray!float) returns `float[2]`. +When `a` is a range whose length is not known at compile time, the number of elements must be given as template argument +(e.g. `myrange.staticArray!2`). +Size and type can be combined, if the source range elements are implicitly +convertible to the requested element type (eg: `2.iota.staticArray!(long[2])`). +When the range `a` is known at compile time, it can also be specified as a +template argument to avoid having to specify the number of elements +(e.g.: `staticArray!(2.iota)` or `staticArray!(double, 2.iota)`). +) + +--- +import std.range : iota; + +auto input = 3.iota; +auto a = input.staticArray!2; +static assert(is(typeof(a) == int[2])); +assert(a == [0, 1]); +auto b = input.staticArray!(long[4]); +static assert(is(typeof(b) == long[4])); +assert(b == [0, 1, 2, 0]); +--- +) + +$(LI $(LNAME2 std-datetime-timezone-remove,Deprecated functions for getting the timezone have been removed.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-datetime-timezone-remove.dd) +$(P +Due to the fact that Microsoft changes its timezone definitions too frequently +to maintain the conversion between the IANA TZ Database names and the names that +Microsoft uses in the standard library, several functions in +std.datetime.timezone related to getting the time zone independently of the +host OS were previously deprecated: $(D TimeZone.getTimeZone), +$(D TimeZone.getInstalledTZNames), $(D tzDatabaseNameToWindowsTZName), and +$(D windowsTZNameToTZDatabaseName). These functions have now been fully removed. +) + +$(P +Instead of $(D TimeZone.getTimeZone), +$(REF PosixTimeZone.getTimeZone, std, datetime, timezone) and +$(REF WindowsTimeZone.getTimeZone, std, datetime, timezone) should be used +directly. Instead of $(D Timezone.getInstalledTimeZones), +$(REF PosixTimeZone.getInstalledTZNames, std, datetime, timezone) and +$(REF WindowsTimeZone.getInstalledTZNames, std, datetime, timezone) should be +used directly. And any programs looking to convert between the TZ Database +names and the Windows names can use +$(REF parseTZConversions, std, datetime, timezone) with the current +windowsZones.xml file to get the current conversions (see the documenation for +$(REF parseTZConversions, std, datetime, timezone) for details). +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Installer changes, + +$(LI $(LNAME2 signed_windows_binaries,Windows installer and binaries are now code-signed) +$(CHANGELOG_SOURCE_FILE installer, changelog/signed_windows_binaries.dd) +$(P +All released executables on Windows will now be code-signed by the following certificate. +) + +$(P +$(PRE + Issuer: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 Assured ID Code Signing CA + Serial Number: 04:e7:49:06:78:3a:e6:5f:54:37:fd:55:45:66:5f:e5 + Validity + Not Before: Aug 7 00:00:00 2018 GMT + Not After : Aug 11 12:00:00 2021 GMT + Subject: C = US, ST = Washington, L = Kirkland, O = D Language Foundation, CN = D Language Foundation + SHA1 Fingerprint: BD:E0:0F:CA:EF:6A:FA:37:15:DB:D4:AA:1A:43:2E:78:27:54:E6:60 + SHA256 Fingerprint: AA:B0:6F:7B:A8:26:52:51:C4:24:44:1B:34:8E:30:68:F4:34:DB:35:38:6A:17:A7:45:C3:27:77:11:24:C4:E5 +) +) + +$(P +Nightly builds and branch/feature previews will not be code-signed for now. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 buildSettingsVars,Variables such as `$ARCH` or `$PLATFORM` are now supported in the build settings.) +$(CHANGELOG_SOURCE_FILE dub, changelog/buildSettingsVars.dd) +$(P +JSON lines such as +) +------- + "lflags-posix-x86": [ "-L$PACKAGE_DIR/lib/posix-x86" ], + "lflags-posix-x86_64": [ "-L$PACKAGE_DIR/lib/posix-x86_64" ], +------- +$(P +can be turned into +) +------- + "lflags-posix": [ "-L$PACKAGE_DIR/lib/posix-$ARCH" ], +------- + +$(P +Both `$VAR` and `${VAR}` syntaxes are supported. +The supported variables are as follow: +$(TABLE + $(TR $(TH name) $(TH values)) + $(TR $(TD `$ARCH`) $(TD $(D_INLINECODE "x86", "x86_64"))) + $(TR $(TD `$PLATFORM`) $(TD $(D_INLINECODE "linux", "windows", ...))) + $(TR $(TD `$PLATFORM_POSIX`) $(TD $(D_INLINECODE "posix", "windows", ...))) + $(TR $(TD `$BUILD_TYPE`) $(TD $(D_INLINECODE "debug", "release", ...))) +) +) +) + +$(LI $(LNAME2 buildTypeSyntax,DUB supports build type "syntax") +$(CHANGELOG_SOURCE_FILE dub, changelog/buildTypeSyntax.dd) +$(P +With this release new build type "syntax" is added. This build type is useful for IDEs to check the syntax of D coding without generating binaries. +) +) + +$(LI $(LNAME2 env-var-replacement,Enviroment variable expansion was improved) +$(CHANGELOG_SOURCE_FILE dub, changelog/env-var-replacement.dd) +$(P +Environment variable expansion now supports the braced `${MY_VAR}` expansion syntax: e.g. for `${PACKAGE_PATH}_suffix`. +) + +$(P +Moreover, `$PACKAGE_PATH`, `$ROOT_PACKAGE_PATH`, and `$DEP_PACKAGE_PATH` no longer end + with a `/` or `\` to support clean concatenation, e.g. `${PACKAGE_PATH}/subpath`. +) + +$(P +Learn more about the details at $(LINK2 https://github.com/dlang/dub/pull/1392, #1392). +) +) + +$(LI $(LNAME2 recursive_dependecy_resolution,Dependency resolution has been reimplemented using a recursive algorithm) +$(CHANGELOG_SOURCE_FILE dub, changelog/recursive_dependecy_resolution.dd) +$(P +The new algorithm minimizes the search space while descending the dependency +graph. Compared to the old approach, it is now much less likely to run into +pathological cases that result in exponential run time ("The dependency +resolution algorithm is taking too long"). +) + +$(P +Furthermore, the error message in case of unsatisfiable dependencies is more +precise, usually making it straight forward to debug issues in the dependency +graph of a failing package. +) +) + +$(LI $(LNAME2 stdinForSingleFilePackages,DUB accepts single file packages on STDIN) +$(CHANGELOG_SOURCE_FILE dub, changelog/stdinForSingleFilePackages.dd) +$(P +You can pass single file packages to dub on STDIN using dash as first argument to DUB. +All arguments after dash will be passed as runtime arguments to the application. +) + +$(P +Example `cat app.d | dub - --foo=bar` +) +) + +$(LI $(LNAME2 upgrade_check,The regular upgrade check has been removed) +$(CHANGELOG_SOURCE_FILE dub, changelog/upgrade_check.dd) +$(P +Previously dub would regularly (once a day) check for possible package upgrades before building a packages. +This lead to unexpected build failures, e.g. when internet connectivity was down or dependency resolution failed, and caused unnecessary delays. +) + +$(P +The build flag `--nodeps` now only suppresses resolution of missing dependencies. +) + +$(P +The new upgrade flag `--dry-run` was added to explicitly check for upgradable packages without actually upgrading anything. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 18068): No file names and line numbers in stack trace) +$(LI $(BUGZILLA 19050): Running the DMD test suite with a compiler compiled in debug mode fails due to invalid characters, -) +$(LI $(BUGZILLA 19058): __traits$(LPAREN)getUnitTests$(RPAREN) stops working with separate compilation in dmd 2.081.0) +$(LI $(BUGZILLA 19074): [REG 2.080] SIGSEGV in el_ptr $(LPAREN)s=0x15$(RPAREN) at dmd/backend/el.c:1760) +$(LI $(BUGZILLA 19076): dmd 2.081 crashed by getVirtualFunctions for a interface extended interface) +$(LI $(BUGZILLA 19134): [C++] static const y = new Derived$(LPAREN)$(RPAREN); ->pointer cast from const$(LPAREN)Derived$(RPAREN) to immutable$(LPAREN)void*$(RPAREN)** is not supported at compile time) +$(LI $(BUGZILLA 19140): [REG master] AssertError@dmd/ctfeexpr.d$(LPAREN)229$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 19152): 2.081.1 getOverloads regression compiler bug) +$(LI $(BUGZILLA 19162): [REG: 2.079.0] Public Import Overlapping Names Conflict Resolution) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 9701): UDAs cannot be attached to enum values.) +$(LI $(BUGZILLA 15373): Segfault when using typeid on extern$(LPAREN)C++$(RPAREN) class with virtual functions) +$(LI $(BUGZILLA 17580): Marking methods as synchronized is allowed despite spec) +$(LI $(BUGZILLA 18620): `error cannot be interpreted at compile time` is missing context where error occurs) +$(LI $(BUGZILLA 18985): bad error message for += operation on shared Object) +$(LI $(BUGZILLA 19018): Lexer allows invalid integer literals, like `0x`) +$(LI $(BUGZILLA 19035): Escape in scope inference, improve scope inference) +$(LI $(BUGZILLA 19043): Incorrect mangling for extern$(LPAREN)C++$(RPAREN) const template parameter on windows) +$(LI $(BUGZILLA 19051): Undefined functions Set/GetWindowLongPtr in mingw libs) +$(LI $(BUGZILLA 19053): debug should escape @safe) +$(LI $(BUGZILLA 19059): Invalid integer literal 08 and 09 allowed) +$(LI $(BUGZILLA 19107): -de produces compilation error, -dw does not) +$(LI $(BUGZILLA 19112): Associative array opIn with static array key fails with dynamic array) +$(LI $(BUGZILLA 19176): Dmd crashes because of __traits$(LPAREN)getUnitTests$(RPAREN)) +$(LI $(BUGZILLA 19181): Semantic errors in opDispatch argument lead to "no property X") +$(LI $(BUGZILLA 19187): __traits$(LPAREN)compiles$(RPAREN) segfaults on access to partially undefined overload set from import) +$(LI $(BUGZILLA 19193): deprecated attribute on enum members in templates is ignored) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 17602): improve message for deprecated enum comparison) +$(LI $(BUGZILLA 18743): ConditionalExpression and AssignExpression should require parentheses) +$(LI $(BUGZILLA 18994): Use noncopyable variable in foreach loop without ref results in error message without line number) +$(LI $(BUGZILLA 19022): CTorFlow: Show the line of the duplicated initialization for const/immutable fields) +$(LI $(BUGZILLA 19081): Can't declare enum with UDA at statement level) +$(LI $(BUGZILLA 19108): Unknown pragmas not ignored inside body) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 12507): SysTime.init.toString should not segfault) +$(LI $(BUGZILLA 15732): std.function partial does not work with function / delegate references) +$(LI $(BUGZILLA 18682): std.typecons.Nullable has opEquals but no toHash) +$(LI $(BUGZILLA 18804): std.algorithm.mutation.copy puts whole source range into target range when it should put elements) +$(LI $(BUGZILLA 18933): std.range.assumeSorted should not nest SortedRange!$(LPAREN)SortedRange!$(LPAREN)...$(RPAREN), pred$(RPAREN)) +$(LI $(BUGZILLA 18995): std.array.array doesn't free elements) +$(LI $(BUGZILLA 19003): format!"" breaks with structs containing invariants violated in .init) +$(LI $(BUGZILLA 19094): Anchored section does not exist in std.uni.normalize phobos documentation) +$(LI $(BUGZILLA 19138): std.uuid.randomUUID should not depend on std.random.Random being Mt19937) +$(LI $(BUGZILLA 19147): Reduce template bloat in std.complex by using const arguments) +$(LI $(BUGZILLA 19171): Array!bool range slicing has invalid assert) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 12335): std.algorithm.skipOver should support multiple args like startsWith) +$(LI $(BUGZILLA 13121): std.algorithm.joiner should return a bidirectional range if possible) +$(LI $(BUGZILLA 14001): Optionally @nogc std.random.randomCover) +$(LI $(BUGZILLA 16639): Review std.json wrt this article on JSON edge cases and ambiguities) +$(LI $(BUGZILLA 16745): Add template helper for creating static arrays with the size inferred) +$(LI $(BUGZILLA 17019): std.algorithm.iteration.each should be usable with parallel) +$(LI $(BUGZILLA 18790): can't put a const$(LPAREN)char$(RPAREN)[] into a char[]) +$(LI $(BUGZILLA 19037): Nullable should use moveEmplace to support any type.) +$(LI $(BUGZILLA 19135): std.json : JSON_TYPE does not match D Style.) +$(LI $(BUGZILLA 19156): @nogc std.random.randomShuffle) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 19046): OSX: bad value for core.stdc.time.CLOCKS_PER_SEC) +$(LI $(BUGZILLA 19073): core.internal.hash should not bitwise hash representations of floating point numbers) +$(LI $(BUGZILLA 19177): No version $(LPAREN)Solaris$(RPAREN) in druntime/src/core/stdc/time.d) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 18220): Allow rt_trapexceptions to be set from the CLI) +$(LI $(BUGZILLA 18918): core.internal.hash should perform memberwise hashing of structs with references) +$(LI $(BUGZILLA 18921): make core.internal.hash cater to memberwise hash chaining) +$(LI $(BUGZILLA 18923): Semaphore internal handle should be `protected` instead of `private`) +$(LI $(BUGZILLA 18942): core.internal.hash can take advantage of alignment info on non-x86) +$(LI $(BUGZILLA 18981): SIGSEGV during backtrace when debug info is compressed) +$(LI $(BUGZILLA 19009): core.internal.hash.hashOf default hash $(LPAREN)absent `toHash`$(RPAREN) should be `@nogc`) +$(LI $(BUGZILLA 19048): In core.internal.hash.hashOf reduce template bloat: remove `auto ref` where unneeded and add `const` where possible) +$(LI $(BUGZILLA 19049): object.hashOf - don't wrap a public function with an identical public function) +$(LI $(BUGZILLA 19071): core.internal.hash should have non-chained toHash overloads) +$(LI $(BUGZILLA 19072): Object.toHash and typeid$(LPAREN)void*$(RPAREN).getHash$(LPAREN)&ptr$(RPAREN) should be more varied in their low bits) +$(LI $(BUGZILLA 19075): rt.util.random.Rand48.defaultSeed should prefer RDTSC or mach_absolute_time or QueryPerformanceCounter to ctime.time) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 18558): Template alias spec incomplete) +$(LI $(BUGZILLA 18782): Documentation error: ProtectionAttributes should say Visibility Attributes) +$(LI $(BUGZILLA 19055): [404 Not Found] std.digest.digest) +$(LI $(BUGZILLA 19067): [Mixins] Dead Link to template-mixin) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 19041): errnoEnforce: example does not compile) +) +$(BUGSTITLE_BUGZILLA Installer bugs, + +$(LI $(BUGZILLA 2473): Linux system install instructions incorrect) +$(LI $(BUGZILLA 10941): object.d not found when following Mac installation instructions) +$(LI $(BUGZILLA 19100): install.sh signature verification fails, no public key) +) +) +$(D_CONTRIBUTORS_HEADER 50) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Alexibu) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR BBasile) + $(D_CONTRIBUTOR Brian Schott) + $(D_CONTRIBUTOR David Bennett) + $(D_CONTRIBUTOR Denis Feklushkin) + $(D_CONTRIBUTOR Diederik de Groot) + $(D_CONTRIBUTOR dukc) + $(D_CONTRIBUTOR GabyForceQ) + $(D_CONTRIBUTOR gapdan) + $(D_CONTRIBUTOR Giles Bathgate) + $(D_CONTRIBUTOR glitchbunny) + $(D_CONTRIBUTOR Greg V) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR Joakim Noah) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR Jonathan M Davis) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR look-at-me) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Lindsay Wilson) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Roman Chistokhodov) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Timothee Cour) + $(D_CONTRIBUTOR Tyler Knott) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR wazar) + $(D_CONTRIBUTOR Yuxuan Shui) + $(D_CONTRIBUTOR Zach Tollen) + $(D_CONTRIBUTOR Zevenberge) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.082.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.082.1.dd b/changelog/2.082.1.dd new file mode 100644 index 0000000000..4d9a473f2a --- /dev/null +++ b/changelog/2.082.1.dd @@ -0,0 +1,51 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 10, 2018, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 6 fixed Bugzilla issues. + A huge thanks goes to the 10 contributors who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 19219): Could not CTFE with std.math.exp from 2.082.0) +$(LI $(BUGZILLA 19243): [REG 2.081] Can no longer override pragma$(LPAREN)lib$(RPAREN) with -L switch) +$(LI $(BUGZILLA 19266): Some source files names are no longer accepted) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 19252): Templated format with variable width allocates 2GB of RAM per call.) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 18851): std.net.curl.post cannot be used with !ubyte) +$(LI $(BUGZILLA 19207): std.algorithm.subsitute wrong results for single subrange substitution) +) +) +$(D_CONTRIBUTORS_HEADER 10) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Remi Thebault) + $(D_CONTRIBUTOR wolframw) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.082.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.083.0.dd b/changelog/2.083.0.dd new file mode 100644 index 0000000000..8fb4d74362 --- /dev/null +++ b/changelog/2.083.0.dd @@ -0,0 +1,406 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Nov 01, 2018, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 11 major changes and 47 fixed Bugzilla issues. + A huge thanks goes to the 51 contributors who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 cppVersions,Add `CppRuntime_*` version identifiers.)) +$(LI $(RELATIVE_LINK2 deprecated_switch_gc,Deprecated CLI switch `-gc` have been removed)) +$(LI $(RELATIVE_LINK2 isZeroInit,Expose `__traits(isZeroInit, T)`)) +$(LI $(RELATIVE_LINK2 mangle_cpp,Implement new C++ mangling syntax)) +$(LI $(RELATIVE_LINK2 pragmaLinkerDirective,Add `pragma(linkerDirective)`, to emit linker directives into object files.)) +$(LI $(RELATIVE_LINK2 reboot14246,fix Issue 14246 - RAII - proper destruction of partially constructed objects)) +$(LI $(RELATIVE_LINK2 targetinfo,Add `__traits(getTargetInfo, "key")` to query details about the compilation target.)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 std-algorithm-iteration-each-early-stopping,`std.algorithm.iteration.each` is now capable of early-stopping)) +$(LI $(RELATIVE_LINK2 std-experimental-checkedint-toHash,`toHash` function has been added to `std.experimental.checkedint.Checked`)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 betterC_build_option,betterC build option has been added)) +$(LI $(RELATIVE_LINK2 env_var_package_version,Environment variable DUB_PACKAGE_VERSION added)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 cppVersions,Add `CppRuntime_*` version identifiers.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/cppVersions.dd) +$(P +In order to link against C++ code, it is important to know what C++ runtime the ABI targets. +) + +$(P +Supported version identifiers include: +$(UL + $(LI `CppRuntime_Clang`) + $(LI `CppRuntime_DigitalMars`) + $(LI `CppRuntime_Gcc`) + $(LI `CppRuntime_Microsoft`) + $(LI `CppRuntime_Sun`) +) +) + +$(P +The C++ runtime in use generally depends on the C++ compiler used to build the C++ code that will be linked against. +This is contrast to the C runtime, which generally depends on the target system. +) +) + +$(LI $(LNAME2 deprecated_switch_gc,Deprecated CLI switch `-gc` have been removed) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecated_switch_gc.dd) +$(P +This switch was deprecated in v2.075.0 and is now removed, +meaning DMD will complain about an unrecognized switch. +`-gc` used to pretend to be C, but debuggers have been +D-aware for around a decade. +) +) + +$(LI $(LNAME2 isZeroInit,Expose `__traits(isZeroInit, T)`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/isZeroInit.dd) +$(P +Takes one argument which must be a type. If the type's +$(DDSUBLINK spec/property, init, default initializer) has no non-zero +bits then `true` is returned, otherwise `false`. `isZeroInit` will +always return `true` for a class `C` because `C.init` is a null +reference. +) + +$(P +This property was already being computed internally by the compiler +so exposing it via `__traits` is more efficient than re-implementing +it in library code. +) + +--- +struct S1 +{ + int x; +} + +struct S2 +{ + int x = -1; +} + +static assert(__traits(isZeroInit, S1)); +static assert(!__traits(isZeroInit, S2)); + +void test() +{ + int x = 3; + static assert(__traits(isZeroInit, typeof(x))); +} +--- +) + +$(LI $(LNAME2 mangle_cpp,Implement new C++ mangling syntax) +$(CHANGELOG_SOURCE_FILE dmd, changelog/mangle_cpp.dd) +$(P +The new syntax allows for keywords to be used for mangling +and only changes the mangle of a symbol. It does not provide any +feature resembling C++ namespaces. This allows users to structure +their C++ in traditional D fashion, utilizing modules. The old syntax +`extern(C++, foo)` would occupy the symbol `foo`. This meant modules +couldn't use this name and match the C++ namespace. +) + +--- +extern(C++, "__traits") void foo(); + +extern(C++, "std", "chrono") void bar(); // multiple namespace syntax + +int std; // no symbol clashing with above extern(C++, "std", ...) +--- +) + +$(LI $(LNAME2 pragmaLinkerDirective,Add `pragma(linkerDirective)`, to emit linker directives into object files.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/pragmaLinkerDirective.dd) +$(P +Emits a custom linker directive to the object file, eg: +) +--- +pragma(linkerDirective, "/alternatename:_pWeakValue=_pDefaultWeakValue"); +--- + +$(P +This is only supported for MS-COFF output. +) +) + +$(LI $(LNAME2 reboot14246,fix Issue 14246 - RAII - proper destruction of partially constructed objects) +$(CHANGELOG_SOURCE_FILE dmd, changelog/reboot14246.dd) +$(P +Since destructors for object fields can now get called by the constructor for that +object if the constructor fails, the attributes of the destructors must be covariant +with the attributes for the constructor. +) + +$(P +I.e. if the constructor is marked @safe, the fields' destructors must also be @safe +or @trusted. +) + +$(P +Since this behavior was never checked before, this fix causes breakage of existing +code. Hence, enabling this behavior is behind the new `transition=dtorfields` compiler +switch. It will eventually become the default behavior, so it is recommended to +fix any of these destructor attribute issues. +) +) + +$(LI $(LNAME2 targetinfo,Add `__traits(getTargetInfo, "key")` to query details about the compilation target.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/targetinfo.dd) +$(P +`getTargetInfo` accepts a string key as argument to select the target detail of interest. +) + +--- +static if (__traits(getTargetInfo, "cppRuntimeLibrary") == "msvcrtd") { ... } + +static assert (__traits(getTargetInfo, "not_a_target_info") == "??"); // <- error: no such targetInfo "not_a_target_info"! +--- + +$(P +`getTargetInfo` keys are implementation defined, allowing relevant data for exotic targets. A reliable subset which are always available shall be mentioned in the spec. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 std-algorithm-iteration-each-early-stopping,`std.algorithm.iteration.each` is now capable of early-stopping) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-algorithm-iteration-each-early-stopping.dd) +$(P +$(REF each, std,algorithm,iteration) is now capable of exiting early. +When a `No.each` $(REF Flag, std,typecons) is returned from the function that +is called by `each`, the iteration will be aborted early. +Analogously, returning `Yes.each` will continue the iteration. +For example: +) + +--- +auto arr = [10, 20, 30]; +arr.each!((n) { arr ~= n; return (n == 20) ? No.each : Yes.each; }); // aborts after the second iteration +assert(arr == [10, 20, 30, 10, 20]); +--- +) + +$(LI $(LNAME2 std-experimental-checkedint-toHash,`toHash` function has been added to `std.experimental.checkedint.Checked`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-experimental-checkedint-toHash.dd) +$(P +Custom hashing can be implemented in a `Hook`. If no hashing is specified, then +the built-in function will be used. Checked can now be used with associative +arrays. +) + +------- +import std.experimental.checkedint; + +static struct MyHook +{ + static size_t hookToHash(T)(T payload) + { + auto h = typeid(payload).getHash(&payload); + return h + 0x9e3779b9 + (h << 6) + (h >> 2); + } +} + +auto h = checked!MyHook(142).toHash(); +------- +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 betterC_build_option,betterC build option has been added) +$(CHANGELOG_SOURCE_FILE dub, changelog/betterC_build_option.dd) +$(P +This build option can be used to pass `-betterC` argument to DMD or LDC: +) + +$(P +dub.json: +) +--- +"buildOptions": ["betterC"] +--- + +$(P +dub.sdl: +) +--- +buildOptions "betterC" +--- +) + +$(LI $(LNAME2 env_var_package_version,Environment variable DUB_PACKAGE_VERSION added) +$(CHANGELOG_SOURCE_FILE dub, changelog/env_var_package_version.dd) +$(P +When executing external commands, DUB will now set the environment variable `DUB_PACKAGE_VERSION`. +The variable will contain the version of the package being built, as it appears in the output of `dub describe`. +) +$(P +One application of this addition is to use a pre-build command to save the package version to a source file, +in order to compile the version string into the application being built. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 19248): Wrong mangle for C++ const STL classes/structs) +$(LI $(BUGZILLA 19304): [Reg 2.081.0] Linker arguments order changed in issue 15574 hinders using --whole-archive linker directive) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 11538): [ICE] stack overflow with recursive NullableRef fails) +$(LI $(BUGZILLA 14246): RAII - proper destruction of partially constructed objects/structs) +$(LI $(BUGZILLA 15374): [internal] Nothing should import ddmd.mars) +$(LI $(BUGZILLA 18457): betterC - struct destructor is always called at function return) +$(LI $(BUGZILLA 18771): Identical overload sets in different modules have different identities) +$(LI $(BUGZILLA 18955): extern$(LPAREN)C++$(RPAREN) default struct mangling is overridden when interacting with a `cppmangle = class` template) +$(LI $(BUGZILLA 19098): Improve error for non-assignable struct) +$(LI $(BUGZILLA 19181): Semantic errors in opDispatch argument lead to "no property X") +$(LI $(BUGZILLA 19182): missing semicolon crashes compiler) +$(LI $(BUGZILLA 19185): [ICE] Nested struct segfaults when using variable from outer scope) +$(LI $(BUGZILLA 19201): Error: func called with argument types $(LPAREN)ulong$(RPAREN) matches both: __c_long and __c_ulong) +$(LI $(BUGZILLA 19209): [ICE] Overriding a field in a baseclass issues an ICE) +$(LI $(BUGZILLA 19225): Confusing error message on `static else`) +$(LI $(BUGZILLA 19251): Alias this does not get called on struct qualified type) +$(LI $(BUGZILLA 19284): alias this not used in nested functions of a method) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 15512): extern$(LPAREN)C++, ns$(RPAREN) should consider taking a string) +$(LI $(BUGZILLA 19180): Expose dmd.mtype.Type.isZeroInit as __traits$(LPAREN)isZeroInit, T$(RPAREN)) +$(LI $(BUGZILLA 19194): version for `-mscrtlib` specification) +$(LI $(BUGZILLA 19195): Support pragma to specify linker directives) +$(LI $(BUGZILLA 19199): Use core.bitops intrinsics during CTFE) +$(LI $(BUGZILLA 19203): alias this to a bool behaves both inconsistently and incorrectly with static assert) +$(LI $(BUGZILLA 19212): Add versions for C++ runtimes.) +$(LI $(BUGZILLA 19292): Mixin expressions should take an argument list the same as pragma$(LPAREN)msg$(RPAREN) does) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 11431): std.file.slurp fails with Windows newlines) +$(LI $(BUGZILLA 11959): Phobos should not declare public symbols in version$(LPAREN)unittest$(RPAREN) blocks) +$(LI $(BUGZILLA 17276): BaseClassesTuple fails on extern C++ classes that implement an interface without a base class) +$(LI $(BUGZILLA 18675): std.experimental.checkedint.Checked has opEquals but no toHash) +$(LI $(BUGZILLA 18683): std.containers.rbtree.RedBlackTree has opEquals but no toHash) +$(LI $(BUGZILLA 18838): Formatting the number zero with separator doesn't obey width specifier) +$(LI $(BUGZILLA 19085): std.experimental.allocator.makeArray should work with void) +$(LI $(BUGZILLA 19200): Variant operators don't overload correctly) +$(LI $(BUGZILLA 19228): hasAliasing fails on static arrays) +$(LI $(BUGZILLA 19240): std.typecons.Tuple should check for reserved identifiers) +$(LI $(BUGZILLA 19275): std.process: redirecting output in a non-console application fails) +$(LI $(BUGZILLA 19289): std.range.transposed with enforceNotJagged not throwing) +$(LI $(BUGZILLA 19297): JSONValue of signed and unsigned equal values is not equal) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 18142): checkedint opOpAssign doesn't accept a checkedint) +$(LI $(BUGZILLA 19236): Replace runtime `typeid$(LPAREN)T$(RPAREN).initializer$(LPAREN)$(RPAREN).ptr is null` checks with compile-time `__traits$(LPAREN)isZeroInit, T$(RPAREN)`) +$(LI $(BUGZILLA 19257): std.array.join does not handle const fields that cannot be converted to mutable) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 19250): DWARF Backtraces with very long symbol names read out of bounds when printing) +$(LI $(BUGZILLA 19262): hashOf associative array should infer nothrow) +$(LI $(BUGZILLA 19282): hashOf segfaults for non-null C++ objects) +$(LI $(BUGZILLA 19314): Thread object destruction may result in UB) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 19280): Remove unnecessary error checks in core.time.currSystemTick and currTime) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 18104): Alias example compiles where it states that it should be illegal) +) +) +$(D_CONTRIBUTORS_HEADER 51) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR 0xEAB) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Alexandru ermicioi) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Arun Chandrasekaran) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR BBasile) + $(D_CONTRIBUTOR Carsten Schlote) + $(D_CONTRIBUTOR devel) + $(D_CONTRIBUTOR deviator) + $(D_CONTRIBUTOR dhasenan) + $(D_CONTRIBUTOR Diederik de Groot) + $(D_CONTRIBUTOR Dragos Carp) + $(D_CONTRIBUTOR Erik van Velzen) + $(D_CONTRIBUTOR Eugen Wissner) + $(D_CONTRIBUTOR GoaLitiuM) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Ilya Yaroshenko) + $(D_CONTRIBUTOR Ionut) + $(D_CONTRIBUTOR Joakim Noah) + $(D_CONTRIBUTOR Johannes Loher) + $(D_CONTRIBUTOR Johannes Pfau) + $(D_CONTRIBUTOR Jonathan M Davis) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR look-at-me) + $(D_CONTRIBUTOR Manu Evans) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Mihails Strasuns) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR Márcio Martins) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Lindsay Wilson) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Pjotr Prins) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Ryan David Sheasby) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR shove70) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Thomas Mader) + $(D_CONTRIBUTOR Vlad Vitan) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR wolframw) + $(D_CONTRIBUTOR Ľudovít Lučenič) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.083.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.083.1.dd b/changelog/2.083.1.dd new file mode 100644 index 0000000000..de2815e85c --- /dev/null +++ b/changelog/2.083.1.dd @@ -0,0 +1,49 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Dec 08, 2018, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 5 fixed Bugzilla issues. + A huge thanks goes to the 9 contributors who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 19337): [Reg 2.082.0] Cannot call std.algorithm.sort twice) +$(LI $(BUGZILLA 19419): [REG2.080.1] @disabled this$(LPAREN)$(RPAREN) will print wrong error if calling non-default constructor with wrong parameters) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 19163): static/tuple foreach counted incorrectly in coverage analysis) +$(LI $(BUGZILLA 19393): Structure dtor isn't called after passed to T[]... argument. Memory leaks issue) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 19444): hasRawAliasing loops on class with static array, cannot swap class refs) +) +) +$(D_CONTRIBUTORS_HEADER 9) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR FeepingCreature) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Stanislav Blinov) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.083.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.084.0.dd b/changelog/2.084.0.dd new file mode 100644 index 0000000000..571ac19b4d --- /dev/null +++ b/changelog/2.084.0.dd @@ -0,0 +1,679 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 01, 2019, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 21 major changes and 100 fixed Bugzilla issues. + A huge thanks goes to the 53 contributors who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 alias_from_trait,Aliases can be created directly from a `__trait`.)) +$(LI $(RELATIVE_LINK2 check-switch,Added -check switch to turn on and off each category of runtime checks.)) +$(LI $(RELATIVE_LINK2 checkaction,Add `-checkaction=D|C|halt` compiler switch.)) +$(LI $(RELATIVE_LINK2 color,`-color` and `-color=on` will now always output colorized console output)) +$(LI $(RELATIVE_LINK2 debugmixins,The code generated by `mixin` statements can now be saved with -mixin)) +$(LI $(RELATIVE_LINK2 deprecated_binary_literals,Deprecate invalid binary literals)) +$(LI $(RELATIVE_LINK2 deprecated_extern_pascal,Deprecated `extern(Pascal)` linkage)) +$(LI $(RELATIVE_LINK2 fqn_imports_bypass_private_imports_error,The deprecation phase for fully qualified names that bypassed private imports is finished)) +$(LI $(RELATIVE_LINK2 posix_cpp_template_mangling,Templates are now mangled correctly on POSIX)) +$(LI $(RELATIVE_LINK2 wchar_t,Added `__c_wchar_t` as a correct mangling type for C's `wchar_t`)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 array,Added `core.stdcpp.array`.)) +$(LI $(RELATIVE_LINK2 crt_externs,Add D header file $(REF_ALTTEXT `core.sys.darwin.crt_externs`, crt_externs, core, sys, darwin) for $(LINK2 https://opensource.apple.com/source/Libc/Libc-1244.30.3/include/crt_externs.h.auto.html, libc/crt_externs.h) on Darwin.)) +$(LI $(RELATIVE_LINK2 destroy_noinit,Added `initialize` template argument to `object.destroy()`.)) +$(LI $(RELATIVE_LINK2 string_view,Added `core.stdcpp.string_view`.)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 pr6580,Add overload `std.random.unpredictableSeed!UIntType`)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 addcommand,Add Command)) +$(LI $(RELATIVE_LINK2 dubEnvVar,dub now supports `$DUB` variable)) +$(LI $(RELATIVE_LINK2 pre-post-run-commands,Pre/Post run commands added)) +$(LI $(RELATIVE_LINK2 shebang-without-d-extension,Shebang without .d extension)) +$(LI $(RELATIVE_LINK2 sortJson,Sort JSON)) +$(LI $(RELATIVE_LINK2 version-identifier-filter,Added experimental feature to improve build cache efficiency)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 alias_from_trait,Aliases can be created directly from a `__trait`.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/alias_from_trait.dd) +$(P +Aliases can be created directly from the traits that return symbol(s) or tuples. +This includes `getMember`, `allMembers`, `derivedMembers`, `parent`, `getOverloads`, +`getVirtualFunctions`, `getVirtualMethods`, `getUnitTests`, `getAttributes` and finally `getAliasThis`. +Previously an `AliasSeq` was necessary in order to alias their return. +Now the grammar allows to write shorter declarations: +) + +--- +struct Foo +{ + static int a; +} + +alias oldWay = AliasSeq!(__traits(getMember, Foo, "a"))[0]; +alias newWay = __traits(getMember, Foo, "a"); +--- + +$(P +To permit this it was more interesting to include `__trait` in the basic types +rather than just changing the alias syntax. So additionally, wherever a type appears +a `__trait` can be used, for example in a variable declaration: +) + +--- +struct Foo { static struct Bar {} } +const(__traits(getMember, Foo, "Bar")) fooBar; +static assert(is(typeof(fooBar) == const(Foo.Bar))); +--- +) + +$(LI $(LNAME2 check-switch,Added -check switch to turn on and off each category of runtime checks.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/check-switch.dd) +$(P +Option("check=[assert|bounds|in|invariant|out|switch][=[on|off]]", + `Overrides default, -boundscheck, -release and -unittest options to enable or disable specific checks. + $(UL + $(LI $(B assert): assertion checking) + $(LI $(B bounds): array bounds) + $(LI $(B in): in contracts) + $(LI $(B invariant): class/struct invariants) + $(LI $(B out): out contracts) + $(LI $(B switch): switch default) + ) + $(UL + $(LI $(B on) or not specified: specified check is enabled.) + $(LI $(B off): specified check is disabled.) + )` + ) +) +) + +$(LI $(LNAME2 checkaction,Add `-checkaction=D|C|halt` compiler switch.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/checkaction.dd) +$(P +It covers action taken when an assert fails, a bounds check fails, +or a final switch error happens. D means the usual D behavior of +throwing an `Error`, C means call the C runtime library assert failure +function, and halt means halt the program execution. +) + +$(P +The halt is the main addition here, it enables very lightweight assert's. +) +) + +$(LI $(LNAME2 color,`-color` and `-color=on` will now always output colorized console output) +$(CHANGELOG_SOURCE_FILE dmd, changelog/color.dd) +$(P +Before this release `-color` wouldn't output colorized console output if +the terminal detection failed. +With this release, a new option `auto` is introduced for `-color=` +which will continue to be the default: +) + +$(P +$(UL + $(LI `auto`: enable colorized output if a tty is detected (default)) + $(LI `on`: always use colored output.) + $(LI `off`: never use colored output.) +) +) + +$(P +Hence, it is now possible to use `-color` (a shortcut for `-color=on`) to +force DMD to emit colorized console output. +For example, this will now use colorized console output: +) + +$(P +$(CONSOLE +\> echo $(DOLLAR)(echo "test" | dmd -color - 2>&1) +__stdin.d(2): $(RED Error): no identifier for declarator $(B test) +) +) +) + +$(LI $(LNAME2 debugmixins,The code generated by `mixin` statements can now be saved with -mixin) +$(CHANGELOG_SOURCE_FILE dmd, changelog/debugmixins.dd) +$(P +This is useful to debug errors in compilation and provides source for debuggers to show when requested. +) +) + +$(LI $(LNAME2 deprecated_binary_literals,Deprecate invalid binary literals) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecated_binary_literals.dd) +$(P +Prior to this release, binary literals without any digits after the prefix `0b` +were considered valid. This has now been deprecated. +) +--- +auto foo = 0b; // deprecated +auto bar = 0b_; // deprecated +auto baz = 0b0; // conforming equivalent +--- +) + +$(LI $(LNAME2 deprecated_extern_pascal,Deprecated `extern(Pascal)` linkage) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecated_extern_pascal.dd) +$(P +This linkage is completely unused, being an heritage from a few decades ago. +Additionally, it's only supported by DMD and cause mangling ambiguity. +) +) + +$(LI $(LNAME2 fqn_imports_bypass_private_imports_error,The deprecation phase for fully qualified names that bypassed private imports is finished) +$(CHANGELOG_SOURCE_FILE dmd, changelog/fqn_imports_bypass_private_imports_error.dd) +--- +// a.d +import std.stdio; +--- + +--- +// b.d +import a; + +void main() +{ + std.stdio.writefln("foo"); // deprecation before patch, now errors +} +--- + +$(P +In order to compile the example successfully, `public` needs to be added +to the import located in `a.d` : `public import std.stdio;` or `import std.stdio;` +needs to be added to `b.d`. +) +) + +$(LI $(LNAME2 posix_cpp_template_mangling,Templates are now mangled correctly on POSIX) +$(CHANGELOG_SOURCE_FILE dmd, changelog/posix_cpp_template_mangling.dd) +$(P +Before this version, anything including `extern(C++)` templates +was not correctly mangled on OSX, Linux, and FreeBSD, leading to linker errors. +) +) + +$(LI $(LNAME2 wchar_t,Added `__c_wchar_t` as a correct mangling type for C's `wchar_t`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/wchar_t.dd) +$(P +This allows code interfacing with C++ that uses `wchar_t` to link correctly. +It replaces `wchar` (Windows) and `dchar` (Posix) as the memory type for the +DRuntime alias `wchar_t`. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 array,Added `core.stdcpp.array`.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/array.dd) +$(P +Added `core.stdcpp.array`, which links against C++ `std::array` +) +) + +$(LI $(LNAME2 crt_externs,Add D header file $(REF_ALTTEXT `core.sys.darwin.crt_externs`, crt_externs, core, sys, darwin) for $(LINK2 https://opensource.apple.com/source/Libc/Libc-1244.30.3/include/crt_externs.h.auto.html, libc/crt_externs.h) on Darwin.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/crt_externs.dd) +$(P +Add D header file $(REF_ALTTEXT `core.sys.darwin.crt_externs`, crt_externs, core, sys, darwin) for $(LINK2 https://opensource.apple.com/source/Libc/Libc-1244.30.3/include/crt_externs.h.auto.html, libc/crt_externs.h) on Darwin. +) +) + +$(LI $(LNAME2 destroy_noinit,Added `initialize` template argument to `object.destroy()`.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/destroy_noinit.dd) +$(P +`object.destroy()` now receives an `initialize` argument to specify whether to re-initialize the object after destruction. +) +) + +$(LI $(LNAME2 string_view,Added `core.stdcpp.string_view`.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/string_view.dd) +$(P +Added `core.stdcpp.string_view`, which links against C++ `std::string_view` +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 pr6580,Add overload `std.random.unpredictableSeed!UIntType`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/pr6580.dd) +$(P +$(REF unpredictableSeed, std,random) now has an overloaded version +`std.random.unpredictableSeed!UIntType` that can be used to produce +seeds of any unsigned type `UIntType`. +) + +------- +import std.random : unpredictableSeed; + +auto a = unpredictableSeed!uint; +static assert(is(typeof(a) == uint)); + +auto b = unpredictableSeed!ulong; +static assert(is(typeof(b) == ulong)); + +// The old syntax still works. +uint c = unpredictableSeed; +------- + +$(P +Additionally the implementation quality of `unpredictableSeed` has been +improved, speeding it up and eliminating an obvious pattern in the high +bit. (Bear in mind that `unpredictableSeed` is still not +cryptographically secure.) +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 addcommand,Add Command) +$(CHANGELOG_SOURCE_FILE dub, changelog/addcommand.dd) +$(P +The `add` command adds a dependency to the dub.json/dub.sdl recipe file. +) + +$(P +Running `dub add vibe-d` queries the latest version for vibe-d from the +registry, then rewrites your recipe file with the new dependency added. +) + +$(P +dub.json: +) +------ + "dependencies": { + "vibe-d": "~>X.Y.Z" + } +------ + +$(P +dub.sdl: +) +------ +dependency "vibe-d" version="~>X.Y.Z" +------ + +$(P +It is also possible to add multiple packages at once and explicitly add a +simple $(LINK2 https://code.dlang.org/package-format?lang=json#version-specs,version specification) +for some of them. +) + +$(P +For example the command `dub add vibe-d='~>0.8.2' mir-algorithm=3.1.21` would +add the given 2 dependencies to the recipe file without querying the registry. +) + +$(P +Packages with and without version-specifier can be mixed in a single invocation. +) + +$(P +The can also be used to overwrite existing dependencies of the same name with +different version specifications. +) +) + +$(LI $(LNAME2 dubEnvVar,dub now supports `$DUB` variable) +$(CHANGELOG_SOURCE_FILE dub, changelog/dubEnvVar.dd) +$(P +With this release, one can call dub from build commands in the following way: +) +------ + // dub.sdl: + preBuildCommands "$DUB run --single somebuildscript.d" +----- +$(P +This is useful if dub is not in the `$PATH`, or if several versions of dub are installed. +) + +$(P +`$DUB` is also accessible as environment variable in the build commands processes. +) + +$(P +`$DUB` points to the running executable, unless it is used as a library. +In such case, `$DUB` will resolve to the first dub executable found in `$PATH`. +) +) + +$(LI $(LNAME2 pre-post-run-commands,Pre/Post run commands added) +$(CHANGELOG_SOURCE_FILE dub, changelog/pre-post-run-commands.dd) +$(P +DUB now supports commands preRunCommands which are executed before the target run +and postRunCommands which are executed after the target run. +Environment variable DUB_TARGET_EXIT_STATUS contains the target executable call status +and is available in postRunCommands. +) +) + +$(LI $(LNAME2 shebang-without-d-extension,Shebang without .d extension) +$(CHANGELOG_SOURCE_FILE dub, changelog/shebang-without-d-extension.dd) +$(P +Dub single-file packages e.g. `app.d` can now be called without .d extension. +In addition to `dub app.d --param` you can call `dub app --param`. +) + +$(P +Also files without .d extension are supported now as single-file packages. +) +) + +$(LI $(LNAME2 sortJson,Sort JSON) +$(CHANGELOG_SOURCE_FILE dub, changelog/sortJson.dd) +$(P +JSON files are now sorted before being written to dub.json. This is to prevent the order of the JSON properties from changing when dub.json is updated. +) +) + +$(LI $(LNAME2 version-identifier-filter,Added experimental feature to improve build cache efficiency) +$(CHANGELOG_SOURCE_FILE dub, changelog/version-identifier-filter.dd) +$(P +Using version identifiers to configure certain features can often lead to +unnecessary rebuilds of dependencies that don't use those version +identifiers. In order to improve the build cache efficiency, dub gained a new +experimental `--filter-versions` switch. +) + +$(P +When `--filter-versions` is passed to any build, test, or generate command, dub +will grep for all the version identifiers packages actually use and only apply +those during building. This allows for example to reuse a cached build for a +library between two applications using different version identifiers when the +library isn't using any of those itself. +) + +$(P +The following regular expressions used to grep for version identifiers. +) +--- +enum verRE = ctRegex!`(?:^|\s)version\s*\(\s*([^\s]*?)\s*\)`; +enum debVerRE = ctRegex!`(?:^|\s)debug\s*\(\s*([^\s]*?)\s*\)`; +--- + +$(P +For packages that use version identifiers in mixins or auto-generated sources, +the list of applicable version identifiers can be specified explicitly in the +package file. +) + +$(P +dub.json: +) +--- +"-versionFilters": ["Have_vibe_d"] +"-versionFilters-posix": ["UseUnixSockets", "UseMMap"] +"-debugVersionFilters": ["ValidateRequests"] +--- +$(P +dub.sdl: +) +--- +x:versionFilters "Have_vibe_d" +x:versionFilters "UseUnixSockets" "UseMMap" platform="posix" +x:debugVersionFilters "ValidateRequests" +--- + +$(P +Note that the inferred version identifiers are cached and grepping is generally +very fast, so explicitly specifying version identifiers should only be used if +necessary. +) + +$(P +Also note that specifying either of versionFilters or debugVersionFilters will +disable inference for both of them. +) + +$(P +The reservered version identifier none can be used for packages that don't use +any version identifiers or debug version identifiers at all. +) + +$(P +dub.json: +) +---- +"-versionFilters": ["none"] +---- +$(P +dub.sdl: +) +---- +x:debugVersionFilters "none" +---- +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 15206): [REG2.077] ICE on optimized build, tym = x1d Internal error: backend\cgxmm.c 547) +$(LI $(BUGZILLA 16284): [REG2.067] CTFE internal error: bad compare) +$(LI $(BUGZILLA 18938): Dmd segfault when compiling this dub package in test release) +$(LI $(BUGZILLA 19103): Can imports symbols in module to a struct with mixin.) +$(LI $(BUGZILLA 19202): deprecated eponymous template prints no warning) +$(LI $(BUGZILLA 19227): S.init is S.init failing for struct with float member) +$(LI $(BUGZILLA 19389): Multiple assignment does not work for struct members) +$(LI $(BUGZILLA 19409): static if $(LPAREN)__traits$(LPAREN)compiles, __traits$(LPAREN)identifier, ...$(RPAREN)$(RPAREN)$(RPAREN) evaluates to false even though the expression alone evaluates to true) +$(LI $(BUGZILLA 19447): [REG2.066] fixed size slice assignment in ctfe loses connection with array) +$(LI $(BUGZILLA 19473): DMD Segfault on circular struct reference) +$(LI $(BUGZILLA 19491): ICE $(LPAREN)segfault$(RPAREN) when initializing scope variable with shared type) +$(LI $(BUGZILLA 19510): [2.084 REG] random and spurious error about a missing NOLOGO.d file) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 5973): alias this is not considered with superclass lookup) +$(LI $(BUGZILLA 6777): alias this disables casting for classes) +$(LI $(BUGZILLA 9274): is + alias this = wrong code) +$(LI $(BUGZILLA 10692): Deprecation isn't checked using alias this) +$(LI $(BUGZILLA 11499): is-expression misbehaving with 'alias this') +$(LI $(BUGZILLA 13392): class + alias this + cast$(LPAREN)void*$(RPAREN) == overzealous cast) +$(LI $(BUGZILLA 13953): AA .remove pseudo-method doesn't work via alias this) +$(LI $(BUGZILLA 14632): Diagnostic improvement for invalid cast with alias this) +$(LI $(BUGZILLA 15876): various cases of SEGFAULT when formatting parser errors) +$(LI $(BUGZILLA 16082): Can't access alias this member with same name as module) +$(LI $(BUGZILLA 16086): Imported function name shadows alias this member) +$(LI $(BUGZILLA 16479): Missing substitution while mangling C++ template parameter for functions) +$(LI $(BUGZILLA 16633): Case where an alias this is tried before the object itself) +$(LI $(BUGZILLA 16976): Implicit conversion from ulong to int in foreach_reverse) +$(LI $(BUGZILLA 18010): Undefined reference to _d_arraycopy when copying arrays in -betterC) +$(LI $(BUGZILLA 18456): crt_constructor/crt_destructor segfaults if -lib) +$(LI $(BUGZILLA 18572): AliasSeq default arguments are broken) +$(LI $(BUGZILLA 18979): Template constructor bypasses private) +$(LI $(BUGZILLA 19014): Compiler imports symbols that aren't actually imported.) +$(LI $(BUGZILLA 19086): Bad stack trace for exceptions) +$(LI $(BUGZILLA 19307): Variables moved to a closure show nonsense in debugger) +$(LI $(BUGZILLA 19318): Variables captured from outer functions not visible in debugger) +$(LI $(BUGZILLA 19319): No line number when std.math is missing for x ^^ y) +$(LI $(BUGZILLA 19336): [ICE] segfault on invalid code) +$(LI $(BUGZILLA 19376): Do not generate object file from .di file passed on command line) +$(LI $(BUGZILLA 19381): capture pointer in nested function should not be called "this") +$(LI $(BUGZILLA 19415): return non-copyable struct fails if member function has return attribute) +$(LI $(BUGZILLA 19464): typeof immutable fields order dependent) +$(LI $(BUGZILLA 19497): the program crash using dmd with -O, it works fine without optimizations.) +$(LI $(BUGZILLA 19520): assert$(LPAREN)TypeExp is TypeExp$(RPAREN): compiles with empty structs) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 1870): Reproduce offending lines in error messages for string mixins) +$(LI $(BUGZILLA 7804): Cannot alias __traits directly) +$(LI $(BUGZILLA 12790): Compiler should keep mixin file around for debugging purposes) +$(LI $(BUGZILLA 16165): Show expected number of function arguments on mismatch) +$(LI $(BUGZILLA 19246): Binary literal `0b_` allowed) +$(LI $(BUGZILLA 19278): extern$(LPAREN)C++, "name"$(RPAREN) doesn't accept expressions) +$(LI $(BUGZILLA 19439): Make __traits$(LPAREN)getAliasThis$(RPAREN) return empty tuple for non-aggregate types) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 13300): pure function 'std.array.Appender!$(LPAREN)T[]$(RPAREN).Appender.ensureAddable' cannot call impure function 'test.T.__fieldPostBlit') +$(LI $(BUGZILLA 18824): [REG 2.080] Tuple's opBinaryRight takes precedence over appending a tuple to an array of tuples) +$(LI $(BUGZILLA 19133): core.exception.rangeerror@std/file.d$(LPAREN)3812$(RPAREN):) +$(LI $(BUGZILLA 19213): goto skips declaration of variable in std.algorithm.iteration.joiner) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 4957): std.concurrency does not allow to pass Tid in struct fields) +$(LI $(BUGZILLA 18327): std.random.XorshiftEngine is parameterized by UIntType but only works with uint) +$(LI $(BUGZILLA 18680): std.random.LinearCongruentialEngine has opEquals but no toHash) +$(LI $(BUGZILLA 18755): std.typecons.Rebindable breaks @safe-ty) +$(LI $(BUGZILLA 18778): std.format: Positional arguments do not work as expected with nesting) +$(LI $(BUGZILLA 18796): std.algorithm.substitute asserts on empty range) +$(LI $(BUGZILLA 19331): std.regex.internal.ir.SmallFixedArray.toHash is ignored because it's non-const) +$(LI $(BUGZILLA 19338): std.bitmanip.BitArray.count gives segfault for empy BitArray) +$(LI $(BUGZILLA 19366): Qualify opCast$(LPAREN)bool$(RPAREN) as const for findSplit, findSplitBefore and findSplitAfter) +$(LI $(BUGZILLA 19367): std.net.curl does not understand HTTP/2 status lines) +$(LI $(BUGZILLA 19456): ParameterIdentifierTuple incorrect for abstract methods with unnamed parameters) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 5502): More handy ways to create associative arrays) +$(LI $(BUGZILLA 9702): std.string.replace for single chars too?) +$(LI $(BUGZILLA 10930): std.array.replace cannot simple replace an element in array) +$(LI $(BUGZILLA 18595): std.random: add unpredictableSeedOf!UIntType for non-uint unpredictableSeed) +$(LI $(BUGZILLA 19197): Replace instances of typeid$(LPAREN)T$(RPAREN).getHash$(LPAREN)..$(RPAREN) with hashOf) +$(LI $(BUGZILLA 19238): no-arg splitter should work on ranges of characters) +$(LI $(BUGZILLA 19308): Optimize std.string.stripLeft) +$(LI $(BUGZILLA 19364): Decrease template bloat for string functions) +$(LI $(BUGZILLA 19396): [betterC] ScopeBuffer can't be used in betterC with inline) +$(LI $(BUGZILLA 19403): Make std.string.stripLeft on char array @nogc nothrow) +$(LI $(BUGZILLA 19404): Optimize std.string.stripRight) +$(LI $(BUGZILLA 19405): Speed up backwards UTF-8 decoding in stripRight & make nogc nothrow for strings) +$(LI $(BUGZILLA 19429): indexOf$(LPAREN)"a", "b"$(RPAREN) should be nothrow/@nogc) +$(LI $(BUGZILLA 19466): functionLinkage documentation omits some values) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 19498): undefined identifier rt_loadLibraryW) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 8872): Missing extended window styles $(LPAREN)WS_EX_... enumeration$(RPAREN) in windows header) +$(LI $(BUGZILLA 11168): core.stdc.time.asctime$(LPAREN)$(RPAREN) is incorrectly marked as @trusted) +$(LI $(BUGZILLA 11174): Both AF_PACKET and SO_BINDTODEVICE undefined) +$(LI $(BUGZILLA 11294): Object destruction with alias this) +$(LI $(BUGZILLA 19087): `final switch` cannot be used in -betterC) +$(LI $(BUGZILLA 19090): core.internal.hash.bytesHash unit test uses incorrect test vector on BigEndian machines) +$(LI $(BUGZILLA 19204): hashOf doesn't accept SIMD vectors) +$(LI $(BUGZILLA 19332): hashOf fails to compile for const struct that has non-const toHash & has all fields bitwise-hashable) +$(LI $(BUGZILLA 19401): Fix bug in core.internal.traits.hasElaborateDestructor & hasElaborateCopyConstructor for struct with static array alias & for nested structs/unions) +$(LI $(BUGZILLA 19433): Don't consume --DRT-* options if rt_cmdline_enabled is false) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 19214): Support object.destruct$(LPAREN)$(RPAREN) for efficient $(LPAREN)and correct!$(RPAREN) destruction) +$(LI $(BUGZILLA 19398): Document meaning of core.atomic.MemoryOrder) +$(LI $(BUGZILLA 19414): object.__cmp$(LPAREN)T[]$(RPAREN) on big-endian architectures can use memcmp for unsigned integers of any size) +$(LI $(BUGZILLA 19416): Make core.exception.onOutOfMemoryError work in betterC) +$(LI $(BUGZILLA 19421): Make pureMalloc, etc. usable in BetterC) +$(LI $(BUGZILLA 19423): In core.stdc.errno directly link __errno on OpenBSD & NetBSD) +$(LI $(BUGZILLA 19424): Add Haiku support to core.stdc.errno) +$(LI $(BUGZILLA 19468): Improve cyclic dependency error message) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 19374): TypeVector undefined in grammar) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 19321): Unions "may not" have fields with destructors) +) +$(BUGSTITLE_BUGZILLA Installer bugs, + +$(LI $(BUGZILLA 19434): "Invalid signature" when using install.sh with no ~/.gnupg) +) +) +$(D_CONTRIBUTORS_HEADER 53) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Andu033) + $(D_CONTRIBUTOR ARaspiK) + $(D_CONTRIBUTOR Arun Chandrasekaran) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR BBasile) + $(D_CONTRIBUTOR Chris) + $(D_CONTRIBUTOR David Gileadi) + $(D_CONTRIBUTOR Diederik de Groot) + $(D_CONTRIBUTOR dukc) + $(D_CONTRIBUTOR Eduard Staniloiu) + $(D_CONTRIBUTOR H. S. Teoh) + $(D_CONTRIBUTOR HANATANI Takuma) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR jmh530) + $(D_CONTRIBUTOR Joakim Noah) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR Johannes Pfau) + $(D_CONTRIBUTOR jsatellite) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR Laurent Tréguier) + $(D_CONTRIBUTOR look-at-me) + $(D_CONTRIBUTOR Manu Evans) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Lindsay Wilson) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Oleksandr Palamar) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Pharap) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Richard Palme) + $(D_CONTRIBUTOR Robert burner Schadek) + $(D_CONTRIBUTOR Roman Chistokhodov) + $(D_CONTRIBUTOR rracariu) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR Stanislav Blinov) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Thomas Mader) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR wolframw) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.084.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.084.1.dd b/changelog/2.084.1.dd new file mode 100644 index 0000000000..c7488a7fce --- /dev/null +++ b/changelog/2.084.1.dd @@ -0,0 +1,41 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 09, 2019, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 3 fixed Bugzilla issues. + A huge thanks goes to the 6 contributors who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 19549): -check=in=off doesn't work) +$(LI $(BUGZILLA 19551): corrupt ELF library when using pragma$(LPAREN)crt_constructor$(RPAREN)) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 19543): Shared object "libstdc++.so.6" not found, required by "dmd") +) +) +$(D_CONTRIBUTORS_HEADER 6) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Thomas Mader) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.084.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.085.0.dd b/changelog/2.085.0.dd new file mode 100644 index 0000000000..4cdc89bb8e --- /dev/null +++ b/changelog/2.085.0.dd @@ -0,0 +1,1054 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 01, 2019, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 26 major changes and 58 fixed Bugzilla issues. + A huge thanks goes to the 49 contributors who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 1_objc_class,Add support for Objective-C classes)) +$(LI $(RELATIVE_LINK2 2_objc_instance_variable,Add support for Objective-C instance variable)) +$(LI $(RELATIVE_LINK2 3_objc_super_call,Add support for Objective-C super calls)) +$(LI $(RELATIVE_LINK2 4_deprecated_objc_interfaces,Deprecate Objective-C interfaces)) +$(LI $(RELATIVE_LINK2 assert,Context-aware assertion error messages)) +$(LI $(RELATIVE_LINK2 const_cast_dont_construct_structs,Avoid calling the struct constructor from const-casts)) +$(LI $(RELATIVE_LINK2 error-context,dmd now supports expressive diagnostic error messages with `-verrors=context`)) +$(LI $(RELATIVE_LINK2 no-cmpsb,`memcmp()` compares are no longer performed for struct equality tests, memberwise comparisons are done instead, per the spec)) +$(LI $(RELATIVE_LINK2 osx-32bit,OSX 32-bit is no longer supported)) +$(LI $(RELATIVE_LINK2 preview-flags,`-preview` and `-revert` command line switches have been introduced)) +$(LI $(RELATIVE_LINK2 stdcpp,Transition to C++11 character types)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 core-memory-gc-profile-stats,Added `GC.profileStats()` to `core.memory`)) +$(LI $(RELATIVE_LINK2 cpp_new,Added `core.stdcpp.new_`)) +$(LI $(RELATIVE_LINK2 cpu_count,Added `core.sys.linux.sched.CPU_COUNT`.)) +$(LI $(RELATIVE_LINK2 cpu_isset,Added `core.sys.linux.sched.CPU_ISSET`.)) +$(LI $(RELATIVE_LINK2 emplace,Moved `std.conv.emplace`, `std.algorithm.mutation.move`, `std.algorithm.mutation.moveEmplace`, and `std.functional.forward` to core/lifetime.d)) +$(LI $(RELATIVE_LINK2 gc_cleanup,GC cleanup can now be configured as a DRT GC option)) +$(LI $(RELATIVE_LINK2 gc_precise,A garbage collector with precise heap scanning can now be selected)) +$(LI $(RELATIVE_LINK2 gc_realloc,GC.realloc is now more consistent and robust)) +$(LI $(RELATIVE_LINK2 gc_registry,User supplied garbage collectors can now be linked with the runtime)) +$(LI $(RELATIVE_LINK2 std_allocator,Added `core.stdcpp.allocator`)) +$(LI $(RELATIVE_LINK2 zero_init,`char`/`wchar` fields in most D runtime (`core.*` and `rt.*`) structs are now zero-initialized)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 dub-fetch-shortcut,`dub fetch` now supports `@` as a shortcut)) +$(LI $(RELATIVE_LINK2 extraDependencyFiles-attribute-added,extraDependencyFiles attribute added)) +$(LI $(RELATIVE_LINK2 file-system-supplier,File system supplier enabled)) +$(LI $(RELATIVE_LINK2 toolchain_requirements,`toolchainRequirements` recipe entry)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 1_objc_class,Add support for Objective-C classes) +$(CHANGELOG_SOURCE_FILE dmd, changelog/1_objc_class.dd) +$(P +Prior to this release D interfaces were used to represent Objective-C classes. +Now proper support for Objective-C classes has been added and D classes can +be used instead to represent Objective-C classes. It's preferred to use D +classes to represent Objective-C classes. +) + +$(P +This release also adds support for implementing Objective-C subclasses and +methods in D. +) + +$(P +To match the behavior in Objective-C some additional changes have been made: +) + +$(P +$(UL + $(LI `static` and `final` methods are virtual. Although `final` methods are + virtual it's not possible to override a `final` method in a subclass) + $(LI `static` methods are overridable in subclasses) +) +) + +$(P +Example: +) + +--- +extern (Objective-C) +class NSObject +{ + static NSObject alloc() @selector("alloc"); + NSObject init() @selector("init"); + void release() @selector("release"); +} + +extern (Objective-C) +class Foo : NSObject +{ + override static Foo alloc() @selector("alloc"); + override Foo init() @selector("init"); + + int bar(int a) @selector("bar:") + { + return a; + } +} + +void main() +{ + auto foo = Foo.alloc.init; + scope (exit) foo.release(); + + assert(foo.bar(3) == 3); +} +--- +) + +$(LI $(LNAME2 2_objc_instance_variable,Add support for Objective-C instance variable) +$(CHANGELOG_SOURCE_FILE dmd, changelog/2_objc_instance_variable.dd) +$(P +It's now possible to declare instance variables in Objective-C classes. +) + +$(P +Instance variables in Objective-C are non-fragile. That means that the base +class can change (add or remove instance variables) without the subclasses +needing to recompile or relink. Thanks to this feature it's not necessary to +declare instance variables when creating bindings to Objective-C classes. +) + +$(P +Example: +) + +--- +extern (Objective-C) +class NSObject {} + +extern (Objective-C) +class Foo : NSObject +{ + int bar; + + static Foo alloc() @selector("alloc"); + Foo init() @selector("init"); + void release() @selector("release"); + + void getBar() @selector("getBar") + { + return bar; + } +} + +void main() +{ + auto foo = Foo.alloc.init; + scope (exit) foo.release(); + foo.bar = 3; + + assert(foo.getBar() == 3); +} +--- +) + +$(LI $(LNAME2 3_objc_super_call,Add support for Objective-C super calls) +$(CHANGELOG_SOURCE_FILE dmd, changelog/3_objc_super_call.dd) +$(P +It's now possible to implement an Objective-C method and make a super call to +a method in the base class. +) + +$(P +Example: +) + +--- +extern (Objective-C) +class NSObject +{ + void release() @selector("release"); +} + +extern (Objective-C) +class Foo : NSObject +{ + int foo() @selector("foo") + { + return 3; + } +} + +extern (Objective-C) +class Bar : Foo +{ + static Bar alloc() @selector("alloc"); + Bar init() @selector("init"); + + override int foo() @selector("foo") + { + return super.foo() + 1; + } +} + +void main() +{ + auto bar = Bar.alloc.init; + scope (exit) bar.release(); + + assert(bar.foo() == 4); +} +--- +) + +$(LI $(LNAME2 4_deprecated_objc_interfaces,Deprecate Objective-C interfaces) +$(CHANGELOG_SOURCE_FILE dmd, changelog/4_deprecated_objc_interfaces.dd) +$(P +Prior to this release, it was necessary to represent an Objective-C class +as a D interface. Now support for Objective-C classes has been implemented and +the `class` keyword should be used instead. +) + +$(P +The reason for this deprecation is to allow `extern (Objective-C)` interfaces +to be repurposed for representing Objective-C protocols in the future. +) + +$(P +Deprecated: +) +--- +extern (Objective-C) interface NSObject {} // deprecated +--- + +$(P +Replace with: +) +--- +extern (Objective-C) class NSObject {} +--- +) + +$(LI $(LNAME2 assert,Context-aware assertion error messages) +$(CHANGELOG_SOURCE_FILE dmd, changelog/assert.dd) +$(P +With this release DMD supports generating context-aware assertion error messages +when no error message has been provided by the user. +For example, currently the following file: +) + +--- +void main() +{ + int a, b = 2; + assert(a == b); +} +--- + +$(P +would yield this error when compiled and run: +) + +$(P +$(CONSOLE +\> dmd -run main.d +core.exception.AssertError@main.d(4): Assertion failure +$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH) +??:? _d_assertp [0x1c4eae48] +onlineapp.d:4 _Dmain [0x1c4ead85] +) +) + +$(P +However, with the new experimental compiler switch `-checkaction=context` it yields: +) + +$(P +$(CONSOLE +\> dmd -checkaction=context -run main.d +core.exception.AssertError@main.d(4): 0 != 2 +$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH) +??:? _d_assert_msg [0x4a3f9cf0] +??:? _Dmain [0x4a3f8fc4] +) +) + +$(P +The new switch already supports a variety of assertion messages: +) + +--- +string dlang = "d2"; +assert(dlang != dlang); // ERROR: "d2" == "d2" + +struct S { int s; } +assert(S(0) == S(1)); // ERROR: "S(0) !is S(1)" + +int a = 1, b = 2; +assert(a > b); // ERROR: 1 <= 2 +--- + +$(P +Also if no error message can be generated, it will now fallback to displaying +the text of the `assert` expression. For example, for this more complicated +assert expression: +) + +--- +void main() +{ + int a, b = 2; + assert(a && (a == b)); +} +--- + +$(P +Compiling and running with `-checkaction=context` will now result in: +) + +$(P +$(CONSOLE +\> dmd -checkaction=context -run main.d +core.exception.AssertError@main.d(4): assert(a && (a == b)) failed +$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH) +??:? _d_assert_msg [0xb7e5fdfc] +??:? _Dmain [0xb7e5fd40] +) +) + +$(P +This switch for context-aware assertion error messages is still experimental +and feedback is welcome. +) +) + +$(LI $(LNAME2 const_cast_dont_construct_structs,Avoid calling the struct constructor from const-casts) +$(CHANGELOG_SOURCE_FILE dmd, changelog/const_cast_dont_construct_structs.dd) +$(P +In previous versions of DMD, there was an undocumented interaction of const-cast with +regular cast, ie. `cast()`, `cast(const)` and `cast(immutable)`, where these casts would +be expressed as `cast(const(typeof(expr))) expr`; hence if `expr` was of type `Struct`, +these casts could potentially call its constructor `Struct(expr)`, as per spec. +) + +$(P +The dangerous part however, was if this occurred with structs that used their first field +as `alias this`, the implicit conversion via `alias this` would potentially satisfy an +implicit struct constructor, leaving the other fields set to `init` and leading to apparent +data corruption from a mere `cast()`. +) + +$(P +In other words, `cast() s` to `S(s)` to `S(s.implicitCast)`. +) + +$(P +This can no longer occur, since $(B `cast()`, `cast(const)` and `cast(immutable)` will +no longer generate an implicit constructor call.) +Implicit constructor calls to `S()` will only occur when one explicitly uses `cast(S)`. +) +) + +$(LI $(LNAME2 error-context,dmd now supports expressive diagnostic error messages with `-verrors=context`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/error-context.dd) +$(P +With the new CLI option `-verrors=context` dmd will now show the offending line directly in its error messages. +Consider this faulty program `test.d`: +) + +--- +void foo() +{ + a = 1; +} +--- + +$(P +Now run it with `-verrors=context`: +) + +$(P +$(CONSOLE +\> dmd -verrors=context test.d +test.d(4): $(RED Error): undefined identifier a + a = 1; + ^ +) +) +) + +$(LI $(LNAME2 no-cmpsb,`memcmp()` compares are no longer performed for struct equality tests, memberwise comparisons are done instead, per the spec) +$(CHANGELOG_SOURCE_FILE dmd, changelog/no-cmpsb.dd) +$(P +The compiler would sometimes generate code for struct equality tests using +`memcmp()` across the whole struct object. This assumed that: +) + +$(P +$(OL +$(LI alignment holes were filled with 0, which is not always the case) +$(LI there were no floating point NaN values, which should compare as not equal +even if the bit patterns match) +) +) + +$(P +The spec requires that the comparison be done in a memberwise manner. +This brings the implementation in line with this. +) + +$(P +$(LINK2 https://dlang.org/spec/expression.html#equality_expressions, Equality Expressions) +) + +$(P +This can break existing code that relied on the former erroneous behavior. +To correct such code, use one of the following: +) + +$(P +$(OL +$(LI define an `opEquals()` operator overload to achieve the desired behavior) +$(LI use `is` instead of `==`, as `is` will do a bit compare of the struct object.) +) +) + +$(P +This new behavior is enabled with the `-preview=fieldwise` compiler switch. It +will eventually become the default behavior. +) +) + +$(LI $(LNAME2 osx-32bit,OSX 32-bit is no longer supported) +$(CHANGELOG_SOURCE_FILE dmd, changelog/osx-32bit.dd) +$(P +With this release, the DMD compiler will no longer officially support +building 32-bit applications for OSX. For legacy purposes, older releases +can be used. +) + +$(P +$(B Motivation:) The latest macOS release $(I Mojave) is the last version of OSX +with support for running 32-bit applications. The D development team wants to +focus its efforts and build/test infrastructure on active and important platforms. +) +) + +$(LI $(LNAME2 preview-flags,`-preview` and `-revert` command line switches have been introduced) +$(CHANGELOG_SOURCE_FILE dmd, changelog/preview-flags.dd) +$(P +Command line switches adding or subtracting features of the D language have been normally added on an ad-hoc basis. +Over time this has grown to: +) + +$(P +$(UL + $(LI `-dip25`) + $(LI `-dip1000`) + $(LI `-dip1000`) + $(LI `-dip1008`) +) +) + +$(P +Moreover, in parallel `-transition` has been introduced and the following DMD +example is only a subset of the transitional features that DMD supports at the moment: +) + +$(P +$(CONSOLE +dmd -transition=3449 -transition=10378 -transition=14246 -transition=14888 -transition=16997 +) +) + +$(P +While these transitions also have a name alias, it's still not clear for the user +whether the transition is (a) an experimental feature or an upcoming breaking change, +(b) a warning or help on an upcoming change, or (c) revert of a change for users +who don't want to deal with the breaking change for now. +) + +$(P +With this release, DMD gained a `-preview` command line switch which can be used to test upcoming features or potentially breaking changes. +For example, with this release the list of upcoming features is: +) + +$(P +$(UL + $(LI `-preview=dip25`: Implements $(LINK2 https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md, DIP25) (Sealed references)) + $(LI `-preview=dip1000`: Implements $(LINK2 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md, DIP1000) (Scoped Pointers)) + $(LI `-preview=dip1008`: Implements $(LINK2 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1008.md, DIP1008) (`@nogc` Throwables)) + $(LI `-preview=markdown`: Enables Markdown replacements in Ddoc) + $(LI `-preview=fixAliasThis`: Enables a potentially breaking fix for `alias this` with which DMD will first check the this scope before searching in upper scopes) + $(LI `-preview=intpromote`: Enables integral promotion for the unary `+`, `-` and `~` operators) + $(LI `-preview=dtorfields`: Enables a potentially breaking fix which enables to destruct fields of partially constructed objects) +) +) + +$(P +Adding new features can be disruptive to existing code bases. By initially putting them behind +a `-preview` switch users will have ample opportunity to adapt to them at their own pace. +) + +$(P +Therefore, for end users the new `-preview` interface allows a glimpse into the future. +As always, feedback and bug reports for all `-preview` features is $(I very welcome) and encouraged, +so that potential problems or breakages can be caught early. +) + +$(P +Whenever a `-preview` feature gets enabled by default, +it $(I must) pass on all Continuous Integrations, pass the $(LINK2 https://buildkite.com/dlang, test suite of about 50 of the most popular D packages) +and be without any other known major real-world issues on Bugzilla. +) + +$(P +However, as the behavior of DMD could still deviate slightly from previous versions, sometimes a `-revert` switch might be introduced by the D development team which allows an easy opt-out of a new feature for users in case they run into issues. +As of now, DMD offers these reverts: +) + +$(P +$(UL + $(LI `-revert=dip25`: Reverts $(LINK2 https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md, DIP25) changes) + $(LI `-revert=import`: Revert to single phase name lookup) +) +) + +$(P +Transitioning to new features (or fixing an important bug) is very often not trivial which is why an additional `-transition` exists. +The `-transition` options are $(I informational only) and intended to help gauge the problems of an upcoming change or assist debugging these changes. +For example, DMD currently supports these transitions: +) + +$(P +$(UL + $(LI `-transition=field`: List all non-mutable fields which occupy an object instance) + $(LI `-transition=checkimports`: Emit deprecation messages about 10378 anomalies) + $(LI `-transition=complex`: Emit deprecation messages for all usages of complex or imaginary types) + $(LI `-transition=tls`: List all variables going into the thread local storage) + $(LI `-transition=vmarkdown`: List instances of Markdown replacements in Ddoc) +) +) + +$(P +`-transition` command line switches might be turned into actual deprecations if the importance of a change is considered high enough (compared to the impact on real-world code), +but they are only intended as information for developers on where they would be affected by a certain transition. +) + +$(P +As all of this information will be updated continuously with each release, all three command line switches support a help page with either `h`, `help` or `?` option listing all currently available options: +) + +$(P +$(CONSOLE +\> dmd -preview=help +... +\> dmd -revert=help +... +\> dmd -transition=help +... +) +) + +$(P +$(B IMPORTANT): All old command line switches will continue to work and won't be deprecated. +However, they were removed from the documentation and new code is encouraged +to use `-preview` or `-revert` where applicable. +) +) + +$(LI $(LNAME2 stdcpp,Transition to C++11 character types) +$(CHANGELOG_SOURCE_FILE dmd, changelog/stdcpp.dd) +$(P +With C++11 comes the advent of changed character type mangling. +D's default behavior will be to conform to this after a one +release transition period. A new switch -extern-std={c++98,c++11} is +added to control the version that compatibility is set to. +This switch sets `__traits(getTargetInfo, "cppStd")` to the value of +`__cplusplus` that the corresponding version of the C++ standard defines. +) + +$(P +Of particular note is the new difference between wchar and wchar_t on +Windows. This will manifest itself as compile errors when +interfacing wchar* with wchar_t* code when calling the Windows API. +A cast will resolve the issue. +) + +$(P +Going forward we recommend using WCHAR instead of wchar or wchar_t +when interfacing to Windows API functions. (WCHAR is Microsoft +Windows' 16 bit character type.) +) + +$(P +$(H3 C++ Type Equivalence) +) + +$(P +$(H4 c++98 behavior:) +) + +$(P + $(TABLE + $(THEAD D , Posix , DMC++ Windows , VC++ Windows) + $(TROW wchar , unsigned short , wchar_t , wchar_t) + $(TROW dchar , wchar_t , unsigned , unsigned) + $(TROW wchar_t , wchar_t , wchar_t , wchar_t) + $(TROW WCHAR , -- , wchar_t , wchar_t)) +) + +$(P +$(H4 c++11:) +) + +$(P + $(TABLE + $(THEAD D , Posix , DMC++ Windows , VC++ Windows) + $(TROW wchar , char16_t , wchar_t , char16_t) + $(TROW dchar , char32_t , unsigned , char32_t) + $(TROW wchar_t , wchar_t , wchar , wchar_t) + $(TROW WCHAR , -- , wchar , wchar_t)) +) + +$(P +$(H3 Name Mangling:) +) + +$(P +$(H4 c++98 behavior:) +) + +$(P + $(TABLE + $(THEAD D , Posix , DMC++ Windows , VC++ Windows) + $(TROW wchar , t , _Y , _W) + $(TROW dchar , w , I , I) + $(TROW wchar_t , w , _Y , _W)) +) + +$(P +$(H4 c++11:) +) + +$(P + $(TABLE + $(THEAD D , Posix , DMC++ Windows , VC++ Windows) + $(TROW wchar , Ds , _Y , _S) + $(TROW dchar , Di , I , _U) + $(TROW wchar_t , w , _Y , _W)) +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 core-memory-gc-profile-stats,Added `GC.profileStats()` to `core.memory`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/core-memory-gc-profile-stats.dd) +$(P +Allows access to current GC profiling information. +See $(REF GC.ProfileStats, core,memory) for a list of profile stats. +) +) + +$(LI $(LNAME2 cpp_new,Added `core.stdcpp.new_`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/cpp_new.dd) +$(P +Added `core.stdcpp.new_`, which exposes interfaces for C++ global new/delete operators. +This allows D programs to conveniently allocate from the C++ heap, which is useful when sharing memory between languages. +) +) + +$(LI $(LNAME2 cpu_count,Added `core.sys.linux.sched.CPU_COUNT`.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/cpu_count.dd) +$(P +Added `core.sys.linux.sched.CPU_COUNT`, which returns the number of CPUs in set. +) +) + +$(LI $(LNAME2 cpu_isset,Added `core.sys.linux.sched.CPU_ISSET`.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/cpu_isset.dd) +$(P +Added `core.sys.linux.sched.CPU_ISSET`, which tests to see if cpu is a member of set. +) +) + +$(LI $(LNAME2 emplace,Moved `std.conv.emplace`, `std.algorithm.mutation.move`, `std.algorithm.mutation.moveEmplace`, and `std.functional.forward` to core/lifetime.d) +$(CHANGELOG_SOURCE_FILE druntime, changelog/emplace.dd) +$(P +`emplace` is the counterpart to `destroy`, so it has been moved to also live in druntime (core/lifetime.d) where it is accessible by projects that use a shallow runtime library stack. +`move`, `moveEmplace`, and `forward` are related low-level construction machinery which also belong in `core.lifetime`. +) +) + +$(LI $(LNAME2 gc_cleanup,GC cleanup can now be configured as a DRT GC option) +$(CHANGELOG_SOURCE_FILE druntime, changelog/gc_cleanup.dd) +$(P +The default cleanup method for the GC is to unconditionally run a +collection before runtime termination to finalize objects +that are still alive and hold resources that affect system state outside +the current process. This combines the worst of possible alternatives: +it can cause a considerable delay and does not guarantee finalization +of all objects as roots might still exist. +) + +$(P +The cleanup behaviour can now be configured by a DRT option to the +$(LINK2 $(ROOT_DIR)spec/garbage.html, GC configuration), +e.g. by passing `--DRT-gcopt=cleanup:none` on the command +line. Three options are provided: +) + +$(P +$(UL + $(LI collect: run a collection (the default for backward compatibility)) + $(LI none: do nothing) + $(LI finalize: all live objects are finalized unconditionally) +) +) + +$(P +As usual, you can also embed the configuration into the application by +redefining `rt_options`, e.g. +) + +------- +extern(C) __gshared string[] rt_options = [ "gcopt=cleanup:none" ]; +------- +) + +$(LI $(LNAME2 gc_precise,A garbage collector with precise heap scanning can now be selected) +$(CHANGELOG_SOURCE_FILE druntime, changelog/gc_precise.dd) +$(P +Precise heap scanning can now be enabled by a DRT option to the +$(LINK2 $(ROOT_DIR)spec/garbage.html, GC configuration), +e.g. by passing `--DRT-gcopt=gc:precise` on the command +line or by redefining `rt_options`. See the +$(LINK2 $(ROOT_DIR)spec/garbage.html#precise_gc, documentation) +for details. +) +) + +$(LI $(LNAME2 gc_realloc,GC.realloc is now more consistent and robust) +$(CHANGELOG_SOURCE_FILE druntime, changelog/gc_realloc.dd) +$(P +The specification of $(REF GC.realloc, core, memory) has changed slightly: +) + +$(P +$(UL + $(LI `GC.realloc` now returns `null` for failure. (It used to return the original pointer but + that is is not a good indication of failure as it might also be returned on success. It can + lead to overwriting memory if an enlargement was requested.)) + $(LI as with `GC.free`, the caller has to ensure that there are no other live pointers to the + memory passed to `GC.realloc` (This used to be required only when passing a new size `0`).) + $(LI as a consequence the GC is allowed to free the memory immediately (the previous + implementation did this for objects larger than 4kB when shrinking).) + $(LI block attribute bits on the existing block are only set if it is reused (the previous + implementation didn't set bits if it reused a small block).) +) +) + +$(P +The implementation now properly verifies that pointers are actually base pointers to allocated +GC memory (passing other pointers could have crashed immediately or corrupt the GC). +) +) + +$(LI $(LNAME2 gc_registry,User supplied garbage collectors can now be linked with the runtime) +$(CHANGELOG_SOURCE_FILE druntime, changelog/gc_registry.dd) +$(P +A GC registry has been implemented that allows to add +garbage collector implementations by just linking them into +the binary. See the +$(LINK2 $(ROOT_DIR)spec/garbage.html#gc_registry, documentation) +for details. +) +) + +$(LI $(LNAME2 std_allocator,Added `core.stdcpp.allocator`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/std_allocator.dd) +$(P +Added `core.stdcpp.allocator`, which exposes the C++ `std::allocator` class. +This is a required foundation for any of the allocating STL container types. +) +) + +$(LI $(LNAME2 zero_init,`char`/`wchar` fields in most D runtime (`core.*` and `rt.*`) structs are now zero-initialized) +$(CHANGELOG_SOURCE_FILE druntime, changelog/zero_init.dd) +$(P +Fields that are single `char`/`wchar` or fixed-length arrays of such are now initialized to all zero bits instead of all one bits for most structs in the D runtime (`core.*` and `rt.*` modules). This simplifies initialization and removes the need to store init data when it makes the entire struct zero-initialized. Most affected structs are used for interoperability with C APIs. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 dub-fetch-shortcut,`dub fetch` now supports `@` as a shortcut) +$(CHANGELOG_SOURCE_FILE dub, changelog/dub-fetch-shortcut.dd) +$(P +`dub fetch @` is a shortcut for +`dub fetch --version=`: +) + +$(P +$(CONSOLE +\> dub fetch gitcompatibledubpackage@1.0.4 +Fetching gitcompatibledubpackage 1.0.4... +) +) +) + +$(LI $(LNAME2 extraDependencyFiles-attribute-added,extraDependencyFiles attribute added) +$(CHANGELOG_SOURCE_FILE dub, changelog/extraDependencyFiles-attribute-added.dd) +$(P +Using attribute `extraDependencyFiles` a list of files can be specified +causing rebuild on change. +) +) + +$(LI $(LNAME2 file-system-supplier,File system supplier enabled) +$(CHANGELOG_SOURCE_FILE dub, changelog/file-system-supplier.dd) +$(P +Existing file system supplier is enabled for usage. +It searches a certain directory for files with names of +the form "[package name]-[version].zip". +) + +$(P +Example `dub fetch mypackage --registry=file:///etc/dub/packages/` +) +) + +$(LI $(LNAME2 toolchain_requirements,`toolchainRequirements` recipe entry) +$(CHANGELOG_SOURCE_FILE dub, changelog/toolchain_requirements.dd) +$(P +DUB now supports a new entry in `dub.json` or `dub.sdl` to restrict the versions of +DUB and of compilers supported by a package. +) + +$(P +dub.json: +) +--- +{ + "toolchainRequirements": { + "dub": "~>1.10", + "frontend": ">=2.068 <2.083" + } +} +--- + +$(P +dub.sdl: +) +--- +toolchainRequirements dub="~>1.10" frontend=">=2.068|<2.083" +--- + +$(P +Supported entries in `toolchainRequirements` are: +$(UL + $(LI dub) + $(LI frontend) + $(LI dmd) + $(LI ldc) + $(LI gdc) +) +) + +$(P +Each can contain a +$(LINK2 https://dub.pm/package-format-sdl.html#version-specs, version specification), +where DMD-like versions are supported in addition to SemVer versions. For +compilers, instead of a version specification, the keyword `no` can also be used +to indicate that the compiler should not be used for this package. +) + +$(P +Example scenario:$(BR) +Package that needs DUB>=1.12, and that will only build with LDC>=1.10: +) + +$(P +dub.json: +) +--- +{ + "toolchainRequirements": { + "dub": ">=1.12", + "dmd": "no", + "gdc": "no", + "ldc": ">=1.10" + } +} +--- + +$(P +dub.sdl: +) +--- +toolchainRequirements dub=">=1.12" dmd="no" gdc="no" ldc=">=1.10" +--- +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 16214): [REG2.069] ICE: Assertion `fd->semanticRun == PASSsemantic3done' failed.) +$(LI $(BUGZILLA 16652): [Reg 2.071] returned rvalue destroyed too early) +$(LI $(BUGZILLA 17518): [Reg 2.063] confusing error message with inout constructor/ctor) +$(LI $(BUGZILLA 18372): REG$(LPAREN)2.072$(RPAREN): error missing line number: Error: undefined identifier __va_list_tag) +$(LI $(BUGZILLA 19494): [REG 2.080.0][objc] interface `main.NSObject.Class` conflicts with interface `main.NSObject.Class`) +$(LI $(BUGZILLA 19499): __c_long_double has exact match with double) +$(LI $(BUGZILLA 19523): "undefined identifier" causes DMD crash) +$(LI $(BUGZILLA 19618): Incorrect conversion of function returning `typeof$(LPAREN)null$(RPAREN)` to function returning an associative array) +$(LI $(BUGZILLA 19639): Initializing static array with slice enum of different length crashes the compiler) +$(LI $(BUGZILLA 19652): [REG2.084] alias this chain no longer works) +$(LI $(BUGZILLA 19654): [REG master] cannot have final methods in objc interfaces) +$(LI $(BUGZILLA 19672): Function uses the stack to read a static array parameter but it is passed in the registers) +$(LI $(BUGZILLA 19685): Nested aggregate overlaps not detected) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 12001): __traits$(LPAREN)isSame$(RPAREN) does not work with the basic types) +$(LI $(BUGZILLA 16098): align$(LPAREN)32$(RPAREN) not respected for stack variables) +$(LI $(BUGZILLA 17090): `dmd -transition=?` needs quoting => make it `-transition=help`) +$(LI $(BUGZILLA 17181): Local imports in templates should be added to imported modules list of module that instantiated it) +$(LI $(BUGZILLA 18545): Casting away const with cast$(LPAREN)$(RPAREN) triggers alias this, but returns the supertype anyway) +$(LI $(BUGZILLA 19223): core.simd __vector.array compiler crash) +$(LI $(BUGZILLA 19224): core.simd __vector.array "__r2.length cannot be evaluated at compile time") +$(LI $(BUGZILLA 19574): DMD crashes with templated structs in two identical extern$(LPAREN)C++, ""$(RPAREN) blocks) +$(LI $(BUGZILLA 19608): [ICE] dmd/backend/cod1.d$(LPAREN)3826$(RPAREN): Assertion `0' failed.) +$(LI $(BUGZILLA 19609): [ICE] dmd/expression.d$(LPAREN)2790$(RPAREN): Segmentation fault) +$(LI $(BUGZILLA 19627): [CTFE][SIMD] Error: cannot cast `int` to `int[4]`) +$(LI $(BUGZILLA 19628): [CTFE][SIMD] ICE indexing vector array) +$(LI $(BUGZILLA 19630): [CTFE][SIMD] Error: cannot determine length of vector slice at compile time) +$(LI $(BUGZILLA 19676): Destructor not called for returned temporary that was cast to void) +$(LI $(BUGZILLA 19687): Wrong error for overloaded opDispatch + UFCS with non-existing function) +$(LI $(BUGZILLA 19699): [2.085.0-beta.2] Obj-C segfault - in objc_glue.getClassName) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 16360): DMD fails to inline functions that contain a type) +$(LI $(BUGZILLA 19097): Extend Return Scope Semantics) +$(LI $(BUGZILLA 19552): -transition is non-intuitive to use - the flag should list options by default) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 18519): freebsd 11 + phobos + curl, timing out) +$(LI $(BUGZILLA 18913): Cannot move static array of non-copyable type) +$(LI $(BUGZILLA 19532): chunkBy assert error involving non-forward input ranges.) +$(LI $(BUGZILLA 19572): std.array.Appender.put invokes struct constructor via cast) +$(LI $(BUGZILLA 19580): [non-DMD] std.random seed bootstrap: don't count on reading an uninitialized variable being treated as an ordinary read) +$(LI $(BUGZILLA 19644): std.range.takeOne opSlice asserts incorrectly when operating on non-forward input range) +$(LI $(BUGZILLA 19647): std.range.takeOne opSlice incorrect for empty slice of non-forward input range) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 19453): Remove unnecessary error checks in std.datetime.systime.currStdTime$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 19526): make std.typecons.RefCounted work in betterC) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 11393): [GC] GC realloc and free don't ignore interior pointers) +$(LI $(BUGZILLA 11446): [GC] GC realloc doesn't ignore non-GC owned pointers) +$(LI $(BUGZILLA 12843): Unit tests fail when GC is compiled with SENTINEL) +$(LI $(BUGZILLA 15393): Debug versions in GC code doesn't compile.) +$(LI $(BUGZILLA 17431): GCBits should be @nogc to prevent deadlocks) +$(LI $(BUGZILLA 19281): GC mishandles allocations >= 4GB) +$(LI $(BUGZILLA 19522): [GC] GC.query/addrOf/sizeOf fail for freed memory) +$(LI $(BUGZILLA 19562): core.internal.hash.hashOf array of pointers or delegates should be `@safe`) +$(LI $(BUGZILLA 19568): hashOf should not unnecessarily call a struct's fields' postblits & dtors in CTFE) +$(LI $(BUGZILLA 19571): Incorrect definition of DTM_FIRST in core.sys.windows.commctrl) +$(LI $(BUGZILLA 19582): Make core.internal.convert.toUbyte in CTFE for arrays work with reference type elements and not call postblits/dtors) +$(LI $(BUGZILLA 19593): dstrcmp with -profile causes stack overflow) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 16377): Make --DRT GC profile information available outside of GC destruction) +$(LI $(BUGZILLA 19128): argument to alloca may be too large) +$(LI $(BUGZILLA 19455): GC wastes too much memory) +$(LI $(BUGZILLA 19524): Make core.checkedint work in betterC) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 19592): Rule for IdentifierList is wrong) +) +) +$(D_CONTRIBUTORS_HEADER 48) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR 0xEAB) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Andrej Mitrovic) + $(D_CONTRIBUTOR Arun Chandrasekaran) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR BBasile) + $(D_CONTRIBUTOR Cameron Ross) + $(D_CONTRIBUTOR David Gileadi) + $(D_CONTRIBUTOR Eduard Staniloiu) + $(D_CONTRIBUTOR FeepingCreature) + $(D_CONTRIBUTOR Flying-Toast) + $(D_CONTRIBUTOR H. S. Teoh) + $(D_CONTRIBUTOR hatf0) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR Jacob Jensen) + $(D_CONTRIBUTOR Joakim Noah) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR Johannes Pfau) + $(D_CONTRIBUTOR John) + $(D_CONTRIBUTOR Jon Degenhardt) + $(D_CONTRIBUTOR Jonathan Marler) + $(D_CONTRIBUTOR jsatellite) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR look-at-me) + $(D_CONTRIBUTOR Manu Evans) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Maya Rashish) + $(D_CONTRIBUTOR MetaLang) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR Márcio Martins) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Radu Racariu) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Ryan Boggs) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Stefan Koch) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR سليمان السهمي (Soolaïman Sahmi)) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.085.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.085.1.dd b/changelog/2.085.1.dd new file mode 100644 index 0000000000..848954035e --- /dev/null +++ b/changelog/2.085.1.dd @@ -0,0 +1,78 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 05, 2019, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 23 fixed Bugzilla issues. + A huge thanks goes to the 14 contributors who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 19655): DMD generates wrong code for some circular dependencies) +$(LI $(BUGZILLA 19656): D compiler fails to resolve circular module dependency when modules are compiled separately) +$(LI $(BUGZILLA 19657): D compiler fails to resolve circular module dependency when modules are compiled together) +$(LI $(BUGZILLA 19691): ICE on null default value for struct parameter in constructor) +$(LI $(BUGZILLA 19718): DMD 2.085 changes to gsroa make DCD crashing) +$(LI $(BUGZILLA 19724): Regression: wrong order of linker arguments, again: -L-l before -L--start-group) +$(LI $(BUGZILLA 19730): if $(LPAREN)auto x$(RPAREN) {} isn't properly rejected) +$(LI $(BUGZILLA 19746): DMD fails to compile some circular dependencies spiced with is $(LPAREN)T == super$(RPAREN) condition) +$(LI $(BUGZILLA 19750): [Reg v2.070.2] DMD fails with some circular module refs with Template/Mixin instances) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 13285): wrong codegen for destructor call of unnamed struct instance on 64 bit environments) +$(LI $(BUGZILLA 15875): case of undetected circular reference in function parameter) +$(LI $(BUGZILLA 17259): ICE with multiple mixin templates containing conflicting ctor declarations) +$(LI $(BUGZILLA 17285): Segfault when types are used in array literals) +$(LI $(BUGZILLA 17290): DMD crash due to circular reference in function return type) +$(LI $(BUGZILLA 19635): -checkaction=context not working with attributes) +$(LI $(BUGZILLA 19700): [2.085.0-beta.2] Obj-C wrong code overloading selectors and extern$(LPAREN)D$(RPAREN)) +$(LI $(BUGZILLA 19717): case of segfault due to undetected forward reference) +$(LI $(BUGZILLA 19755): Compiler crash) +$(LI $(BUGZILLA 19757): crash on invalid initializer at CTFE) +$(LI $(BUGZILLA 19762): ICE on invalid code) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 18818): VariantN has unittests that are compiled into user modules) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 19765): std.algorithm.searching.findAmong doesn't `save` like it should) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 19723): wrong time values in GC.profileStats) +) +) +$(D_CONTRIBUTORS_HEADER 14) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR Kriyszig) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Puneet Goel) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Sebastian Wilzbach) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.085.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.086.0.dd b/changelog/2.086.0.dd new file mode 100644 index 0000000000..267b06b345 --- /dev/null +++ b/changelog/2.086.0.dd @@ -0,0 +1,862 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION May 04, 2019, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 17 major changes and 69 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 51 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 1_deprecation_to_error_visibility,Turn deprecation into error for privately imported symbols inside aggregate declarations)) +$(LI $(RELATIVE_LINK2 alias_this_opEquals,Generated `opEquals` takes precedence over aliased this member `opEquals`)) +$(LI $(RELATIVE_LINK2 copy_constructor,Copy Constructor)) +$(LI $(RELATIVE_LINK2 dephexstrings,HexString literals are now obsolete)) +$(LI $(RELATIVE_LINK2 error_visibility,Turn deprecation into error for selectively imported symbols in imported modules.)) +$(LI $(RELATIVE_LINK2 funcliteralsbyref,Function literals can now return by reference)) +$(LI $(RELATIVE_LINK2 lowmem,New command-line option `-lowmem` to reduce compiler memory requirements)) +$(LI $(RELATIVE_LINK2 traits,Enable private member access for traits)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 core_sync_event,New module core.sync.event)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 comparison_bug,Fixed comparison bug in `std.algorithm.comparison.levenshteinDistance`)) +$(LI $(RELATIVE_LINK2 std-all,`std.experimental.all` has been moved to `std`)) + +) + +$(BUGSTITLE_TEXT_HEADER Installer changes, + +$(LI $(RELATIVE_LINK2 lld-8,The bundled LLD Linker has been upgraded to 8.0.0)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 custom-dub-init-type,Support of custom dub init type)) +$(LI $(RELATIVE_LINK2 dmd-mscoff-default,DUB will no longer use OPTLINK as default on Windows)) +$(LI $(RELATIVE_LINK2 dub-run,`dub run` will now automatically fetch a package if it's not found locally)) +$(LI $(RELATIVE_LINK2 remove-dub-list-installed,Remove `dub list-installed` command)) +$(LI $(RELATIVE_LINK2 single-api-requests,DUB uses single API requests to upgrade/resolve dependencies.)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 1_deprecation_to_error_visibility,Turn deprecation into error for privately imported symbols inside aggregate declarations) +$(CHANGELOG_SOURCE_FILE dmd, changelog/1_deprecation_to_error_visibility.dd) +$(P +With this release DMD will issue an error when a symbol that is privately imported in the scope of an aggregate declaration is used as a member of the aggregate outside of the module where the aggregate is defined. Example: +) + +--- +// a.d +class Foobar +{ + int a; + this(int a) + { + this.a = a; + } + static int smeth() + { + return 1; + } +} +void fun() {} + +// b.d +struct AST +{ + import a; +} + +// c.d +void main() +{ + import b; + AST.Foobar t; // triggered a deprecation, but will now trigger an error + AST.Foobar.smeth(); // error + AST.fun(); // error +} +--- +) + +$(LI $(LNAME2 alias_this_opEquals,Generated `opEquals` takes precedence over aliased this member `opEquals`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/alias_this_opEquals.dd) +$(P +Before this patch, if a `struct` had an aliased this member that defined an +`opEquals` method, the aliased this `opEquals` would have been preferred +instead of the `struct` one: +) + +--- +struct A +{ + int a, b; + bool opEquals(ref A rhs) const + { + return a == rhs.a && b == rhs.b; + } +} + +struct B +{ + int n; + A a; + alias a this; +} + +void main() +{ + B a, b; + assert(a == b); // rewritten to a.a.opEquals(b.a) +} +--- + +$(P +Although the compiler generates an `opEquals` for `struct B` that does member-wise +equality comparison (`==`), the aliased this one is wrongfully preferred. +) + +$(P +This patch corrects this issue by always choosing the defined `opEquals` (even if it is +generated by the compiler) instead of the alias this one. If the behavior prior to this +patch is desired, an explicit `opEquals` needs to be provided. +) + +$(P +References: +[1] https://issues.dlang.org/show_bug.cgi?id=16657 +[2] https://github.com/dlang/dmd/pull/9289 +[3] https://github.com/dlang/dlang.org/pull/2593 +) +) + +$(LI $(LNAME2 copy_constructor,Copy Constructor) +$(CHANGELOG_SOURCE_FILE dmd, changelog/copy_constructor.dd) +$(P +With this release, the D language compiler implements the full functionality of the +copy constructor described extensively in this DIP [1]. +) + +$(P +$(P Copy constructors are used to initialize a `struct` instance from +another `struct` of the same type.) +) + +$(P +$(P A constructor declaration is a copy constructor declaration if and only if it is a constructor +declaration that takes only one non-default parameter by reference that is +of the same type as `typeof(this)`, followed by any number of default parameters:) +) + +--- +struct A +{ + this(ref return scope A rhs) {} // copy constructor + this(ref return scope const A rhs, int b = 7) {} // copy constructor with default parameter +} +--- + +$(P +$(P The copy constructor is type checked as a normal constructor.) +) + +$(P +$(P If a copy constructor is defined, implicit calls to it will be inserted +in the following situations:) +) + +$(OL +$(LI When a variable is explicitly initialized:) +--- +struct A +{ + this(ref return scope A rhs) {} +} + +void main() +{ + A a; + A b = a; // copy constructor gets called +} +--- + +$(LI When a parameter is passed by value to a function:) +--- +struct A +{ + this(ref return scope A another) {} +} + +void fun(A a) {} + +void main() +{ + A a; + fun(a); // copy constructor gets called +} +--- + +$(LI When a parameter is returned by value from a function and Named Returned Value Optiomization (NRVO) +cannot be performed:) +--- +struct A +{ + this(ref return scope A another) {} +} + +A fun() +{ + A a; + return a; // NRVO, no copy constructor call +} + +A a; +A gun() +{ + return a; // cannot perform NRVO, rewrite to: return (A __tmp; __tmp.copyCtor(a)); +} + +void main() +{ + A a = fun(); + A b = gun(); +} +--- +) + +$(P +$(P When a copy constructor is defined for a `struct`, all +implicit blitting is disabled for that `struct`: +) +) +--- +struct A +{ + int[] a; + this(ref return scope A rhs) {} +} + +void fun(immutable A) {} + +void main() +{ + immutable A a; + fun(a); // error: copy constructor cannot be called with types (immutable) immutable +} +--- + +$(P +$(P The copy constructor can be overloaded with different qualifiers applied +to the parameter (copying from a qualified source) or to the copy constructor +itself (copying to a qualified destination): +) +) +--- +struct A +{ + this(ref return scope A another) {} // 1 - mutable source, mutable destination + this(ref return scope immutable A another) {} // 2 - immutable source, mutable destination + this(ref return scope A another) immutable {} // 3 - mutable source, immutable destination + this(ref return scope immutable A another) immutable {} // 4 - immutable source, immutable destination +} + +void main() +{ + A a; + immutable A ia; + + A a2 = a; // calls 1 + A a3 = ia; // calls 2 + immutable A a4 = a; // calls 3 + immutable A a5 = ia; // calls 4 +} +--- + +$(P +$(P The `inout` qualifier may be applied to the copy constructor parameter in +order to specify that mutable, `const`, or `immutable` types are treated the same: +) +) +--- +struct A +{ + this(ref return scope inout A rhs) immutable {} +} + +void main() +{ + A r1; + const(A) r2; + immutable(A) r3; + + // All call the same copy constructor because `inout` acts like a wildcard + immutable(A) a = r1; + immutable(A) b = r2; + immutable(A) c = r3; +} +--- + +$(P +$(P A copy constructor is generated implicitly by the compiler for a `struct S` +if all of the following conditions are met:) +) + +$(P +$(OL +$(LI `S` does not explicitly declare any copy constructors;) +$(LI `S` defines at least one direct member that has a copy constructor, and that +member is not overlapped (by means of `union`) with any other member.) +) +) + +$(P +$(P If the restrictions above are met, the following copy constructor is generated:) +) +--- +this(ref return scope inout(S) src) inout +{ + foreach (i, ref inout field; src.tupleof) + this.tupleof[i] = field; +} +--- + +$(P +$(P If the generated copy constructor fails to type check, it will receive the `@disable` attribute.) +) + +$(P +$(P f an `union S` has fields that define a copy constructor, whenever an object of type `S` +is initialized by copy, an error will be issued. The same rule applies to overlapped fields +(anonymous unions).) +) + +$(P +$(P A `struct` that defines a copy constructor is not a POD.) +) + +$(P +[1] https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1018.md +) +) + +$(LI $(LNAME2 dephexstrings,HexString literals are now obsolete) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dephexstrings.dd) +$(P +$(LINK2 http://dlang.org/spec/lex.html#HexString, HexString literals) are obsolete. +) + +$(P +Prior to this release, usage of hex string literals would emit a deprecation warning. Starting with this release they will emit an error. +) + +$(P +Use $(LINK2 https://dlang.org/phobos/std_conv.html#hexString, `std.conv.hexString`) instead. +) +) + +$(LI $(LNAME2 error_visibility,Turn deprecation into error for selectively imported symbols in imported modules.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/error_visibility.dd) +$(P +With this release DMD will issue an error when a symbol that is privately and selectively imported in `module A` is accessed in `module B` that imports `module A` non-selectively. Example: +) + +--- +// a.d +import fun : foo; + +// b.d +import a; + +void main() +{ + foo(); // deprecation up until now; error from now on +} +--- + +$(P +To make the above code compile, the import in `a.d` needs to be made `public`. +) +) + +$(LI $(LNAME2 funcliteralsbyref,Function literals can now return by reference) +$(CHANGELOG_SOURCE_FILE dmd, changelog/funcliteralsbyref.dd) +$(P +Prior to this release, there was no way to declare a function that would return a reference by using an anonymous function. +$(BR)(It was possible to return a pointer but it's not worth mentioning.) +) + +$(P +Here this function returns by value: +) +--- +alias fn = () => a += 2; +--- +$(P +In order to return by reference, we needed to define a named function to assign from: +) +--- +ref int func() // a static or non-nested function to mimic a `function` literal +{ // or a non-static nested function to mimic a `delegate` literal + return a += 2; +} +alias fn = func; +--- +$(P +Now it's possible to use the `ref` keyword to indicate a return by reference: +) +--- +function ref () { return x; } // `=>` shorthand is there too +delegate ref () { return x; } +ref () { return x; } +--- +$(P +For example: +) +--- +int x = 1; +alias add2 = ref () => x += 2; +add2() += 7; // add2 as a lvalue +assert(x == 10); +--- +) + +$(LI $(LNAME2 lowmem,New command-line option `-lowmem` to reduce compiler memory requirements) +$(CHANGELOG_SOURCE_FILE dmd, changelog/lowmem.dd) +$(P +It enables the garbage collector for the compiler, trading compile times for (in some cases, significantly) less memory requirements. +) + +$(P +E.g., compiling DMD's test tool d_do_test (`dmd -c [-lowmem] test/tools/d_do_test.d`) requires about 75% less memory (~1,630 MB -> 410) at the cost of a runtime increase by ~30% (~4.8 secs -> 6.3). +) +) + +$(LI $(LNAME2 traits,Enable private member access for traits) +$(CHANGELOG_SOURCE_FILE dmd, changelog/traits.dd) +$(P +The following traits can now access non-public members: +$(UL + $(LI getMember) + $(LI getOverloads) +) +) + +$(P +This fixes a long-standing issue in D where the allMembers trait would correctly return non-public members but those non-public members would be inaccessible to other traits. +) + +$(P +See BugZilla issue $(LINK2 https://issues.dlang.org/show_bug.cgi?id=15371, 15371) +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 core_sync_event,New module core.sync.event) +$(CHANGELOG_SOURCE_FILE druntime, changelog/core_sync_event.dd) +$(P +This module provides a cross-platform interface for lightweight signaling of other threads. +It can be used to start execution of multiple waiting threads simultaneously. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 comparison_bug,Fixed comparison bug in `std.algorithm.comparison.levenshteinDistance`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/comparison_bug.dd) +$(P +Previously the algorithm was allocating the amount of memory which was equal to +the size of the biggest range, that is $(BIGOH max(s.length, t.length)). +This is now fixed to be $(BIGOH min(s.length, t.length)). +For more details see $(REF levenshteinDistance, std, algorithm, comparison). +) +) + +$(LI $(LNAME2 std-all,`std.experimental.all` has been moved to `std`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-all.dd) +$(P +`std.experimental.all` allowed the convenient use of all Phobos modules +with one import (`import std.experimental.all;`). With this release, this +convenience module has been stabilized and moved to `std`. From now on, the +convenience module can be accessed with `import std;`: +) + +--- +import std; +void main() +{ + 5f.iota.map!exp2.sum; // 31 +} +--- + +$(P +Scripts and experimental code often use long and frequently changing +lists of imports from the standard library. +) + +$(P +With this release it is possible to use `import std;` for importing the entire +standard library at once. This can be used for fast prototyping or REPLs: +) + +--- +import std; +void main() +{ + 6.iota + .filter!(a => a % 2) // 1 3 5 + .map!(a => a * 2) // 2 6 10 + .tee!writeln // peek into the processed stream + .substitute(6, -6) // 2 -6 10 + .mean // (2 - 6 + 10) / 3 + .reverseArgs!writefln("Sum: %.2f"); // 2 +} +--- + +$(P +As before, symbol conflicts will only arise if a symbol with collisions is used. +In this case, $(LINK2 $(ROOT)spec/module.html#static_imports, static imports) or +$(LINK2 $(ROOT)spec/module.html#renamed_imports, renamed imports) can be used +to uniquely select a specific symbol. +) + +$(P +The baseline cost for `import std;` +is less than half a second (varying from system to system) and +work is in progress to reduce this overhead even further. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Installer changes, + +$(LI $(LNAME2 lld-8,The bundled LLD Linker has been upgraded to 8.0.0) +$(CHANGELOG_SOURCE_FILE installer, changelog/lld-8.dd) +$(P +The bundled LLD Linker on Windows binaries has been upgraded to 8.0.0. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 custom-dub-init-type,Support of custom dub init type) +$(CHANGELOG_SOURCE_FILE dub, changelog/custom-dub-init-type.dd) +$(P +Command dub init now supports custom dub packages for argument `-t`. +$(CONSOLE +\> dub init -n myPackage --format sdl -t custom-dub-init-dubpackage -- --foo=bar +) +) + +$(P +Dub init will be invoked like before. The package `custom-dub-init-dubpackage` +contains a sub package `init-exec` which will be invoked afterwards to create a custom +package skeleton. Additional arguments could be passed e.g. `-- --foo=bar`. +) +) + +$(LI $(LNAME2 dmd-mscoff-default,DUB will no longer use OPTLINK as default on Windows) +$(CHANGELOG_SOURCE_FILE dub, changelog/dmd-mscoff-default.dd) +$(P +DMD's $(LINK2 https://digitalmars.com/ctg/optlink.html, OPTLINK) has many limitations. Apart from long-standing issues in the underlying DigitalMars runtime, +the maximum number of symbols is limited as well, which is why most big DUB +libraries can't be compiled with OPTLINK for years. This has been a cause of +grief and pain for many users and impacted the newcomer experience severly. +) + +$(P +With this release, `dub` will no longer use `OPTLINK` as default on Windows, but +use `-m32mscoff` (MSCOFF) on 32-bit Windows systems and `-m64` (MSCOFF) on 64-bit +Windows. +) + +$(P +Users can still manually instruct `dub` to use OPTLINK with the `--arch=x86` switch of `dub`: +) + +$(P +$(CONSOLE +\> dub --arch=x86 +) +) +) + +$(LI $(LNAME2 dub-run,`dub run` will now automatically fetch a package if it's not found locally) +$(CHANGELOG_SOURCE_FILE dub, changelog/dub-run.dd) +$(P +Starting with this release, `dub run ` makes sure that the package is available locally. +This means that now a `dub fetch ` is no longer required and all a user of a library needs to run your dub package is `dub run`: +) + +$(P +$(CONSOLE +\> dub run gitcompatibledubpackage +gitcompatibledubpackage wasn't found locally, but it's available online: +‐-- +Description: Example of a DUB package also usable as git submodule. For DUB test suite. +Version: 1.0.4 +‐-- +Do you want to fetch gitcompatibledubpackage? [Y/n]: +) +) + +$(P +An optional `--yes` (`-y`) flag is provided to confirm fetching non-interactively: +) + +$(P +$(CONSOLE +\> dub run --yes gitcompatibledubpackage +gitcompatibledubpackage wasn't found locally, but it's available online: +‐-- +Description: Example of a DUB package also usable as git submodule. For DUB test suite. +Version: 1.0.4 +‐-- +Fetching gitcompatibledubpackage 1.0.4... +Building package gitcompatibledubpackage in /home/seb/.dub/packages/gitcompatibledubpackage-1.0.4/gitcompatibledubpackage/ +Performing "debug" build using dmd for x86_64. +gitcompatibledubpackage 1.0.4: building configuration "exe"... +Linking... +Running ../../.dub/packages/gitcompatibledubpackage-1.0.4/gitcompatibledubpackage/gitcompatibledubpackage +Hello DUB +) +) + +$(P +An optional `--non-interactive` (`-n`) flag is provided to skip searching online packages: +) + +$(P +$(CONSOLE +\> dub run --non-interactive gitcompatibledubpackage +Failed to find a package named 'gitcompatibledubpackage'. +) +) + +$(P +If one wants to run a specific version of a package, it can be passed to `dub run` too: +) + +$(P +$(CONSOLE +\> dub run gitcompatibledubpackage@1.0.3 +Fetching gitcompatibledubpackage 1.0.3... +Building package gitcompatibledubpackage in /home/seb/.dub/packages/gitcompatibledubpackage-1.0.3/gitcompatibledubpackage/ +Performing "debug" build using dmd for x86_64. +gitcompatibledubpackage 1.0.3: building configuration "exe"... +Linking... +Running ../../.dub/packages/gitcompatibledubpackage-1.0.3/gitcompatibledubpackage/gitcompatibledubpackage +Hello DUB +) +) +) + +$(LI $(LNAME2 remove-dub-list-installed,Remove `dub list-installed` command) +$(CHANGELOG_SOURCE_FILE dub, changelog/remove-dub-list-installed.dd) +$(P +`dub list-installed` command was deprecated and renamed to `list` at $(LINK2 https://github.com/dlang/dub/pull/150, in 2013). +) +) + +$(LI $(LNAME2 single-api-requests,DUB uses single API requests to upgrade/resolve dependencies.) +$(CHANGELOG_SOURCE_FILE dub, changelog/single-api-requests.dd) +$(P +`dub` now uses single API request to upgrade/resolve dependencies. +For more details, see $(LINK2 https://github.com/dlang/dub/pull/1366, pull #1366). +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 17684): [REG 2.062] `static alias this` bug or incomplete implementation?) +$(LI $(BUGZILLA 18810): root/ctfloat depends upon backend) +$(LI $(BUGZILLA 19519): cannot determine length of static array at compile time) +$(LI $(BUGZILLA 19691): ICE on null default value for struct parameter in constructor) +$(LI $(BUGZILLA 19722): botched implementation of semantic3Errors causes compiler assert fail) +$(LI $(BUGZILLA 19774): wrong code caused by opIndex) +$(LI $(BUGZILLA 19778): ICE when accessing empty array at compile time) +$(LI $(BUGZILLA 19782): `alias this` appends `null` instead of inner/aliased element to array) +$(LI $(BUGZILLA 19804): fails to compile with fixes size array T[1]... argument) +$(LI $(BUGZILLA 19822): 2.086 regression wrt. union initializers) +$(LI $(BUGZILLA 19833): The member as template cannot be acquired by getMember) +$(LI $(BUGZILLA 19840): Ice in e2ir.d visit$(LPAREN)CastExp$(RPAREN) assert$(LPAREN)false, "This case should have been rewritten to `__ArrayCast` in the semantic phase"$(RPAREN);) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 5050): No way to declare delegates with ref return) +$(LI $(BUGZILLA 10806): Interface covariance for more than one interface at once also broken) +$(LI $(BUGZILLA 11934): Allow `ref` in `foreach` over range iff `front` returns by `ref`) +$(LI $(BUGZILLA 15875): case of undetected circular reference in function parameter) +$(LI $(BUGZILLA 17285): Segfault when types are used in array literals) +$(LI $(BUGZILLA 17289): With Xcode 8.3 linker, warnings of "pointer not aligned") +$(LI $(BUGZILLA 17290): DMD crash due to circular reference in function return type) +$(LI $(BUGZILLA 17651): Segfault when parsing Ddoc ESCAPES macro) +$(LI $(BUGZILLA 18573): cast$(LPAREN)void$(RPAREN) leads to floating point return value not being popped from FPU stack) +$(LI $(BUGZILLA 19051): Undefined functions Set/GetWindowLongPtr in mingw libs) +$(LI $(BUGZILLA 19099): Struct with field that has postblit or destructor makes struct assignable) +$(LI $(BUGZILLA 19442): multiple argument string mixin dont support char literals) +$(LI $(BUGZILLA 19463): DIP1008 - _d_newclass is called instead of _d_newThrowable) +$(LI $(BUGZILLA 19540): ICE when using `typeof$(LPAREN)new class {}$(RPAREN)` as default value for template parameter) +$(LI $(BUGZILLA 19563): extern$(LPAREN)C++$(RPAREN) Incorrect ABI passing small struct) +$(LI $(BUGZILLA 19569): overload resolution not right?) +$(LI $(BUGZILLA 19658): C++ enum mangling is wrong on Windows for other integer types) +$(LI $(BUGZILLA 19679): variable escapes unnoticed when referenced in function called from function whose address is taken) +$(LI $(BUGZILLA 19688): [ICE] Default function argument concatenation crashes DMD) +$(LI $(BUGZILLA 19717): case of segfault due to undetected forward reference) +$(LI $(BUGZILLA 19719): Debugging string mixins using -mixin doesn't work) +$(LI $(BUGZILLA 19731): auto struct methods whose address is taken don't test invariants) +$(LI $(BUGZILLA 19734): isDataseg returns true for non-static declarations) +$(LI $(BUGZILLA 19735): Error: variable extern symbols cannot have initializers) +$(LI $(BUGZILLA 19744): Confusing error message when annotating a non-member function with `return`) +$(LI $(BUGZILLA 19747): No debug line info for code in scope$(LPAREN)exit$(RPAREN)) +$(LI $(BUGZILLA 19775): multiple argument string mixin doesn't expand tuples) +$(LI $(BUGZILLA 19797): File.seek$(LPAREN)$(RPAREN) terminates ungracefully on incorrect origin for -m32mscoff and -m64) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 8065): No way to write function/delegate literals returning ref T) +$(LI $(BUGZILLA 12330): array.reserve at compile time too) +$(LI $(BUGZILLA 15361): Incomprehensible error message: function declaration without return type.) +$(LI $(BUGZILLA 15371): __traits$(LPAREN)getMember$(RPAREN) should bypass the protection) +$(LI $(BUGZILLA 16271): Should be able to express that a lambda returns by reference) +$(LI $(BUGZILLA 16657): alias this interacts with generated opCmp and opEquals) +$(LI $(BUGZILLA 18825): No syntax for function literal returning a reference) +$(LI $(BUGZILLA 19441): alias this causes partial assignment) +$(LI $(BUGZILLA 19809): `override` block affects passing lambda as argument) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 19777): [REG2.086a] SortedRange.opSlice is wrongly `@trusted`) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 18728): std.math.fdim does not handle nan correctly) +$(LI $(BUGZILLA 19042): Chunking a padRight'ed range leads to range violations) +$(LI $(BUGZILLA 19151): std.utf.toUTF16z$(LPAREN)$(RPAREN) can not be used for LPWSTR) +$(LI $(BUGZILLA 19681): std.range.padRight.popFront does not correctly adjust length) +$(LI $(BUGZILLA 19689): large types cannot be moved) +$(LI $(BUGZILLA 19751): std.stdio.File should not retry fclose after error) +$(LI $(BUGZILLA 19799): templated string formatting fails with const Nullable!string) +$(LI $(BUGZILLA 19806): phobos/std/uri.d: ietf link outdated) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 15853): std.random save methods must be const) +$(LI $(BUGZILLA 18806): minIndex should be able to take an input range but does not) +$(LI $(BUGZILLA 19412): std.algorithm.cmp with default ordering can use memcmp for all size 1 unsigned types $(LPAREN)instead of just char$(RPAREN)) +$(LI $(BUGZILLA 19686): sgn is too greedy) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 18530): [Reg 2.079] src/rt/tracegc.d$(LPAREN)43$(RPAREN): Deprecation: The delete keyword has been deprecated) +$(LI $(BUGZILLA 19796): druntime PR#1982 broke array ops on double[] due to wrong assumption of integral element type) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 19810): destroy does not work for C++ classes without destructor) +$(LI $(BUGZILLA 19830): core.memory.__delete destructs arrays of structs in the wrong order) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 11161): Document the default struct equality comparison and operator overloading) +$(LI $(BUGZILLA 19621): The specification is self-contradictory on immutability) +) +$(BUGSTITLE_BUGZILLA Installer regressions, + +$(LI $(BUGZILLA 18522): [REG 2.079-b2] MinGW import libraries interfere with platform SDK) +) +) +$(D_CONTRIBUTORS_HEADER 51) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Ali Çehreli) + $(D_CONTRIBUTOR Andrea Fontana) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Andy Kurnia) + $(D_CONTRIBUTOR Arun Chandrasekaran) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Basile-z) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Cameron Ross) + $(D_CONTRIBUTOR David Gileadi) + $(D_CONTRIBUTOR David Nadlinger) + $(D_CONTRIBUTOR Dejan Lekic) + $(D_CONTRIBUTOR Eduard Staniloiu) + $(D_CONTRIBUTOR Flying-Toast) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Ilya Yaroshenko) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR Jon Degenhardt) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR lempiji) + $(D_CONTRIBUTOR look-at-me) + $(D_CONTRIBUTOR majiang) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Radu Racariu) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR Sönke Ludwig) + $(D_CONTRIBUTOR tibi77) + $(D_CONTRIBUTOR TJesionowski) + $(D_CONTRIBUTOR Vasniktel) + $(D_CONTRIBUTOR Vasyl Teliman) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR XyjVam) + $(D_CONTRIBUTOR سليمان السهمي (Suleyman Sahmi)) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.086.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.086.1.dd b/changelog/2.086.1.dd new file mode 100644 index 0000000000..412765acc1 --- /dev/null +++ b/changelog/2.086.1.dd @@ -0,0 +1,145 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jun 15, 2019, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 1 major change and 41 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 19 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 interface_contracts,Interface contracts retrieve arguments correctly)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 interface_contracts,Interface contracts retrieve arguments correctly) +$(CHANGELOG_SOURCE_FILE dmd, changelog/interface_contracts.dd) +$(P +Fixed regression $(LINK2 https://issues.dlang.org/show_bug.cgi?id=15984, 15984). +) + +$(P +As a side effect, contracts are not ABI compatible with previous releases. +) + +--- +interface I +{ + void fun(int i) + out { assert(i == 5); } // succeeds +} + +class C : I +{ + void fun(int i) + do { } +} + +unittest +{ + auto c = new C; + c.fun(5); +} +--- +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 19584): Illegal optimization: Shift-or -> imul) +$(LI $(BUGZILLA 19631): Segfault on simple nested templated struct) +$(LI $(BUGZILLA 19871): Copy constructor rejects valid code if default construction is disabled) +$(LI $(BUGZILLA 19887): Segfault with void tuple default parameter) +$(LI $(BUGZILLA 19901): importing export symbols causes link errors) +$(LI $(BUGZILLA 19936): Deprecated alias get this falsely triggers on appending to array) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 12950): Lexer interprets UFCS on hex integer as hex float literal) +$(LI $(BUGZILLA 13819): ICE: backend\cg87.c with -O: "a % 2 != 0" for a double) +$(LI $(BUGZILLA 17258): Pass by name doesn't work reliably and can sometimes lead to memory corruption) +$(LI $(BUGZILLA 17793): [ICE] Internal error: ddmd/backend/cod1.c 3976 using simd.double4) +$(LI $(BUGZILLA 18439): Error: cannot use operator ~= in @nogc delegate 'main.test.__lambda1') +$(LI $(BUGZILLA 18772): [ICE] Internal error: dmd\backend\cgcod.c 607 no optimizations) +$(LI $(BUGZILLA 18784): Segfault due to dmd codegen interfacing with C++) +$(LI $(BUGZILLA 19002): __FUNCTION__ and __PRETTY_FUNCTION__ cannot be used as C string literals) +$(LI $(BUGZILLA 19386): Destructor not called when constructed inside if condition, leading to memory leak) +$(LI $(BUGZILLA 19557): extern$(LPAREN)C++, ns$(RPAREN) and extern$(LPAREN)C++, class$(RPAREN) interact weird) +$(LI $(BUGZILLA 19713): dmd crashes generating code for C++ template function) +$(LI $(BUGZILLA 19825): Memory corruption involving lazy variadic, stdio and json) +$(LI $(BUGZILLA 19831): throw/catch in scope$(LPAREN)exit$(RPAREN) crashes with illegal instruction) +$(LI $(BUGZILLA 19857): Name mangling mismatch when compiling with -dip1000) +$(LI $(BUGZILLA 19881): Escaping reference to local through return scope with -dip1000 and @safe) +$(LI $(BUGZILLA 19888): default parameters in templates with tuple parameters+defaults are thrown away) +$(LI $(BUGZILLA 19895): Floating point exception casting zero length array) +$(LI $(BUGZILLA 19897): dinterpret.d:6439: Internal Compiler Error: null field) +$(LI $(BUGZILLA 19898): ICE: in sizemask at dmd/mtype.d$(LPAREN)2563$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 19911): ICE: Segmentation fault with struct object and variadic function) +$(LI $(BUGZILLA 19912): [module] No implicit import of object module when an object declaration exists.) +$(LI $(BUGZILLA 19913): ICE: Segmentation fault with mixin and enum) +$(LI $(BUGZILLA 19914): ICE: Segmentation fault with mixin and templated class) +$(LI $(BUGZILLA 19915): ICE: Segmentation fault with alias and templated class) +$(LI $(BUGZILLA 19922): ICE: Segmentation fault with typeid$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 19923): ICE: typesem.d$(LPAREN)3809$(RPAREN): Assertion failure with .classinfo) +$(LI $(BUGZILLA 19941): [ICE] Segmentation fault in ImplicitConvTo::visit$(LPAREN)AddrExp*$(RPAREN) at dmd/dcast.d$(LPAREN)980$(RPAREN)) +$(LI $(BUGZILLA 19942): [ICE] Segmentation fault in resolvePropertiesX at dmd/expressionsem.d:1112) +$(LI $(BUGZILLA 19954): ICE: Casting AliasSeq to array and passing to a function) +$(LI $(BUGZILLA 19955): [ICE] Segmentation fault in StatementSemanticVisitor::visit$(LPAREN)SwitchStatement*$(RPAREN) at dmd/statementsem.d:2558) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 19837): std.random.isUniformRNG$(LPAREN)Rng, ElementType$(RPAREN) should not require Rng.front to be annotated `@property`) +$(LI $(BUGZILLA 19850): double nested joiner .back falsely thinks the range is empty) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 19701): undefined reference to `_D6object__T6hashOf) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 17248): Multiple wrong function definitions in core.sys.windows.winldap $(LPAREN)causing runtime issues$(RPAREN)) +$(LI $(BUGZILLA 19847): no GC memory above 4GB reported with --DRT-gcopt=profile:1) +) +) +$(D_CONTRIBUTORS_HEADER 19) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Eugen Wissner) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jan Jurzitza) + $(D_CONTRIBUTOR kinke) + $(D_CONTRIBUTOR Les De Ridder) + $(D_CONTRIBUTOR look-at-me) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Spoov) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR سليمان السهمي (Suleyman Sahmi)) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.086.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.087.0.dd b/changelog/2.087.0.dd new file mode 100644 index 0000000000..bd6af94c8a --- /dev/null +++ b/changelog/2.087.0.dd @@ -0,0 +1,643 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 01, 2019, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 22 major changes and 44 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 63 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 aliasdecly_func,A new syntax is available to declare an alias to a function type)) +$(LI $(RELATIVE_LINK2 ddoc_markdown,Add Markdown-inspired features to Ddoc)) +$(LI $(RELATIVE_LINK2 dep_scope_class,`scope` as a type constraint on class declarations is deprecated.)) +$(LI $(RELATIVE_LINK2 dep_type_error,Usage of `this` and `super` as types is obsolete)) +$(LI $(RELATIVE_LINK2 error_invalid_integer_literal,Turn deprecation into error for some invalid integer literals.)) +$(LI $(RELATIVE_LINK2 fix16002,fix Issue 16002 - Add `is(sym == module)` and `is(sym == package)`)) +$(LI $(RELATIVE_LINK2 local_templates,Local templates can now receive local symbols.)) +$(LI $(RELATIVE_LINK2 msvcrt,Windows: The mingw based runtime and platform import libraries can now be selected explicitly)) +$(LI $(RELATIVE_LINK2 nan,Floating point types now use a quiet nan as the .init value)) +$(LI $(RELATIVE_LINK2 remove_alloc_dealloc,Class allocators and deallocators are now obsolete)) +$(LI $(RELATIVE_LINK2 remove_visibility,The deprecation phase for access checks is finished)) +$(LI $(RELATIVE_LINK2 static_this_immutable_initialization,Initialization of `immutable` global data from `static this` is deprecated)) +$(LI $(RELATIVE_LINK2 struct_ctor_default_params,Struct constructors with all-default parameter will now error)) +$(LI $(RELATIVE_LINK2 template_alias_matches_basic_types,Template alias parameters now match basic types as a conversion.)) +$(LI $(RELATIVE_LINK2 xmm-linux-changelog,32 Bit Linux now uses XMM registers for float and double rather than the x87.)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 freebsd-ttycom,Convert FreeBSD's sys/ttycom.h into core.sys.posix.sys.ttycom)) +$(LI $(RELATIVE_LINK2 gc_parallel,GC now marks the heap with multiple threads)) +$(LI $(RELATIVE_LINK2 linux-clone-unshare,Add the clone and unshare functions to core.sys.linux.sched)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 asciicontroltable,Added a table of control characters in ASCII table)) +$(LI $(RELATIVE_LINK2 count_processors_via_sched_affinity_on_linux,Count processors via sched_getaffinity on Linux)) +$(LI $(RELATIVE_LINK2 new_schwartzSort_overload,Add overload `std.algorithm.sorting.schwartzSort!(alias transform, SwapStrategy ss, R)`)) +$(LI $(RELATIVE_LINK2 phobos-dip1000,Phobos is now compiled with -preview=dip1000)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 aliasdecly_func,A new syntax is available to declare an alias to a function type) +$(CHANGELOG_SOURCE_FILE dmd, changelog/aliasdecly_func.dd) +$(P +It's now possible to declare an alias to a function type using the `alias` syntax based on the assignment operator. +The declaration consists of the return type, followed by parameters and ends with optional (member) function attributes. See the +$(GLINK2 https://dlang.org/spec/grammar.html, AliasDeclarationY) rule for more details. +) + +$(P +Example: +) + +--- +alias int OldStyleFunAlias(string); +alias NewStyleFunAlias = int(string); + +int fun(string p){return 0;} +static assert(is(typeof(fun) == NewStyleFunAlias)); +--- + +$(P +Note that an advantage compared to the old syntax is that the new allows a shortcut to function template types: +) + +--- +alias SetterProto(T) = void(T t); +alias GetterProto(T) = T() const; +--- +) + +$(LI $(LNAME2 ddoc_markdown,Add Markdown-inspired features to Ddoc) +$(CHANGELOG_SOURCE_FILE dmd, changelog/ddoc_markdown.dd) +$(P +With the `-preview=markdown` flag to dmd, Ddoc now supports $(LINK2 https://daringfireball.net/projects/markdown/syntax, Markdown) features like headings, emphasized text, links and more. The full list of features is described in $(LINK2 https://dlang.org/spec/ddoc.html#highlighting, the Ddoc documentation page). +) + +$(P +Use the `-transition=vmarkdown` flag together with the `-preview=markdown` flag to log all instances of Markdown features as they're processed in your documentation. +) +) + +$(LI $(LNAME2 dep_scope_class,`scope` as a type constraint on class declarations is deprecated.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dep_scope_class.dd) +$(P +`scope` as a type constraint on class declarations has been deprecated for quite some time. However, +starting with this release, the compiler will emit a deprecation warning if used. +) + +--- +scope class C { } // Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site. +--- + +$(P +Note that this does not apply to structs. Deprecation of `scope` as a type constraint on structs is still awaiting a decision. +) +) + +$(LI $(LNAME2 dep_type_error,Usage of `this` and `super` as types is obsolete) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dep_type_error.dd) +$(P +Prior to this release, `this` and `super` could be used as both data or types depending on the context, but +was deprecated about a year ago. Starting with this release using `this` or `super` as a type will result in a compiler error. +) + +--- +class C +{ + shared(this) x; // Error: Using `this` as a type is obsolete. Use `typeof(this)` instead +} + +class D : C +{ + shared(super) a; // Error: Using `super` as a type is obsolete. Use `typeof(super)` instead + super b; // Error: Using `super` as a type is obsolete. Use `typeof(super)` instead +} +--- + +$(P +Use `typeof(super)` or `typeof(this)` instead. +) + +--- +class C +{ + shared(typeof(this)) x; +} + +class D : C +{ + shared(typeof(super)) a; + typeof(super) b; +} +--- +) + +$(LI $(LNAME2 error_invalid_integer_literal,Turn deprecation into error for some invalid integer literals.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/error_invalid_integer_literal.dd) +$(P +With this release DMD will issue an error when some invalid integer literals like `0b` or `0x` are used. Example: +) + +--- +auto a = 0b; // Error: `0b` isn't a valid integer literal, use `0b0` instead +auto a = 0x; // Error: `0x` isn't a valid integer literal, use `0x0` instead +--- +) + +$(LI $(LNAME2 fix16002,fix Issue 16002 - Add `is(sym == module)` and `is(sym == package)`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/fix16002.dd) +$(P +This enhancement adds two new forms of the `is()`, expression, which +determine whether a given symbol represents a module or package. +) + +$(P +It also adds `__traits(isModule, sym)` and `__traits(isPackage, sym)`, which +do the same thing. +) +) + +$(LI $(LNAME2 local_templates,Local templates can now receive local symbols.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/local_templates.dd) +$(P +With this release local and member templates can be instantiated with local symbols. +) + +--- +struct S +{ + private int _m; + void exec(alias fun)() + { + fun(_m); + } +} + +unittest +{ + int localVar; + + void set(int i) + { + localVar = i; + } + + auto obj = S(10); + obj.exec!set(); + + assert(localVar == 10); +} +--- + +$(P +This was a long-standing limitation that disturbed the metaprograming experience. +) + +$(P +See issue $(LINK2 https://issues.dlang.org/show_bug.cgi?id=5710, 5710). +) +) + +$(LI $(LNAME2 msvcrt,Windows: The mingw based runtime and platform import libraries can now be selected explicitly) +$(CHANGELOG_SOURCE_FILE dmd, changelog/msvcrt.dd) +$(P +When specifying `-mscrtlib=msvcrt100` explicitly on the command line to dmd, detection +of a Visual Studio installation is skipped and the redistributable +VC2010 dynamic runtime library and mingw based platform import libraries will be used +unconditionally. The LLD linker (provided by the LLVM project) will be invoked +instead of the Microsoft linker. +) +) + +$(LI $(LNAME2 nan,Floating point types now use a quiet nan as the .init value) +$(CHANGELOG_SOURCE_FILE dmd, changelog/nan.dd) +$(P +Prior to this release, `float.init`, `double.init` and `real.init` used a +signalling nan. They now use a quiet nan, which is the same as the corresponding +`.nan` value. +) + +$(P +Old behaviour: +) +--- +double a = double.init, b = double.nan; +writefln("%x",*cast(ulong*)&a); // 7ff4000000000000 +writefln("%x",*cast(ulong*)&b); // 7ff8000000000000 +--- + +$(P +New behaviour: +) +--- +double a = double.init, b = double.nan; +writefln("%x",*cast(ulong*)&a); // 7ff8000000000000 +writefln("%x",*cast(ulong*)&b); // 7ff8000000000000 +--- +) + +$(LI $(LNAME2 remove_alloc_dealloc,Class allocators and deallocators are now obsolete) +$(CHANGELOG_SOURCE_FILE dmd, changelog/remove_alloc_dealloc.dd) +$(P +Starting with this release any use of $(LINK2 https://dlang.org/spec/class.html#allocators, class allocators) +or $(LINK2 https://dlang.org/spec/class.html#deallocators, deallocators) will result in a compilation error. +) + +$(P +See the $(LINK2 https://dlang.org/deprecate.html#Class%20allocators%20and%20deallocators, deprecated features page) +for more information. +) +) + +$(LI $(LNAME2 remove_visibility,The deprecation phase for access checks is finished) +$(CHANGELOG_SOURCE_FILE dmd, changelog/remove_visibility.dd) +$(P +The `-transition=import` and `-transition=checkimports` switches no longer have an +effect and are now deprecated. Symbols that are not visible in a particular +scope will no longer be found by the compiler. +) +) + +$(LI $(LNAME2 static_this_immutable_initialization,Initialization of `immutable` global data from `static this` is deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/static_this_immutable_initialization.dd) +$(P +Prior to this release, the following code was possible: +) + +--- +module foo; +immutable int bar; +static this() +{ + bar = 42; +} +--- + +$(P +However, module constructors (`static this`) run each time a thread is +spawned, and `immutable` data is implicitly `shared`, which led to +`immutable` value being overriden every time a new thread was spawned. +The simple fix for this is to use `shared static this` over `static this`, +as the former is only run once per process. +) +) + +$(LI $(LNAME2 struct_ctor_default_params,Struct constructors with all-default parameter will now error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/struct_ctor_default_params.dd) +$(P +Since 2.070.0, the following code has been giving deprecations: +) +--- +struct Oops +{ + this (int universe = 42) {} +} +--- +$(P +It will now error out. +) +) + +$(LI $(LNAME2 template_alias_matches_basic_types,Template alias parameters now match basic types as a conversion.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/template_alias_matches_basic_types.dd) +$(P +With this release, templates with alias parameters can be instantiated with basic types, +such as `int` or `void function()`. +) + +--- +template Example(alias A) { alias Example = A[]; } +alias IntArray = Example!int; + +template MatchType(T) { enum MatchType = "type"; } +template MatchType(alias A) { enum MatchType = "alias"; } + +// alias matches, but type matches take priority. +static assert (MatchType!int == "type"); +--- + +$(P +Templates with alias parameters already matched named types, lambdas, and even value literals. Templates with +variadic parameters already matched basic types. This led to strange replacements for `alias` such as +`template Template(T...) if (T.length == 1)`. Those replacements are no longer necessary. +) + +$(P +As a consequence, in some cases templates will match that did not used to. For instance, a template +may have falsely relied on `alias` parameters being "something callable" vs. type parameters being +"the type of something callable", such as +) + +--- +void fun(T...)(T callable) { ... } +void fun(alias A)() { ... } +--- + +$(P +Such overloads may now need to explicitly check whether A is callable in the second case: +) + +--- +void fun(alias A)() if (__traits(compiles, A())) { ... } +// shorter, but may miss cases like structs with a static opCall +void fun(alias A)() if (!isType!A) { ... } +--- +) + +$(LI $(LNAME2 xmm-linux-changelog,32 Bit Linux now uses XMM registers for float and double rather than the x87.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/xmm-linux-changelog.dd) +$(P +This should substantially speed up routine float and double processing. +SIMD vector operations, however, are still not support on 32 bit Linux code +because of issues with 16 byte stack alignment. +) + +$(P +This means that generated code will no longer work on older x86 processors that +do not have XMM registers. If this is an issue, please file a bug report. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 freebsd-ttycom,Convert FreeBSD's sys/ttycom.h into core.sys.posix.sys.ttycom) +$(CHANGELOG_SOURCE_FILE druntime, changelog/freebsd-ttycom.dd) +$(P +In FreeBSD, as in OSX, the tty part of ioctl is defined in +sys/ttycom.h which is included by sys/ioctl.h. +In druntime, there were OSX part of definitions in ttycom.d, +but there were no FreeBSD equivalent. +This change implements FreeBSD part of ttycom.d and ioccom.d, +and public import core.sys.posix.sys.ttycom in ioctl.d. +The OSX users and FreeBSD users can now use full ioctls related +to tty by importing core.sys.posix.sys.ioctl, like including +sys/ioctl.h in C language. (For example, TIOCGWINSZ ioctl was +not provided in FreeBSD.) +Since there are only version(OSX) and version(FreeBSD) part +in ttycom.d, public import'ing core.sys.posix.sys.ttycom from +ioctl.d will make no harm to other platforms. +) +) + +$(LI $(LNAME2 gc_parallel,GC now marks the heap with multiple threads) +$(CHANGELOG_SOURCE_FILE druntime, changelog/gc_parallel.dd) +$(P +The garbage collector now uses available CPU cores to mark the heap +faster. This reduces pause times for a collection considerably. +) + +$(P +By default, the GC uses all available logical cores of your CPU. This +might affect your application if it has threads that are not suspended +during the mark phase of the collection. You can configure the number of +additional threads used for marking by DRT option `parallel` to the +$(LINK2 $(ROOT_DIR)spec/garbage.html, GC configuration), +e.g. by passing `--DRT-gcopt=parallel:2` on the command +line. A value of `0` disables parallel marking completely. +) + +$(P +As usual, you can also embed the configuration into the application by +redefining `rt_options`, e.g. +) + +------- +extern(C) __gshared string[] rt_options = [ "gcopt=parallel:0" ]; +------- +) + +$(LI $(LNAME2 linux-clone-unshare,Add the clone and unshare functions to core.sys.linux.sched) +$(CHANGELOG_SOURCE_FILE druntime, changelog/linux-clone-unshare.dd) +$(P +clone(2) and unshare(2) are Linux-specific system calls. Bindings have been +added to the corresponding D module, as well as the CLONE_* constants that +are used as flags to these functions. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 asciicontroltable,Added a table of control characters in ASCII table) +$(CHANGELOG_SOURCE_FILE phobos, changelog/asciicontroltable.dd) +$(P +There is a new enumerated type $(REF ControlChar, std, ascii). It has +values for every control character in ASCII table and has a base type +of `char`, allowing for alternative markup of strings with control +characters: +) +------- +import std.ascii, std.conv; +with (ControlChar) assert(text("Phobos", us, "Deimos", us, "Tango", rs) == "Phobos\x1FDeimos\x1FTango\x1E"); +------- +) + +$(LI $(LNAME2 count_processors_via_sched_affinity_on_linux,Count processors via sched_getaffinity on Linux) +$(CHANGELOG_SOURCE_FILE phobos, changelog/count_processors_via_sched_affinity_on_linux.dd) +$(P +On GNU/Linux usable number of processors may be restricted if a process runs in containers. +In case it's better to use sched_getaffinity(2). +) +------- +import std.parallelism; + +writeln(totalCPUs); // 4 +writeln(totalCPUs); // 1: runs on `taskset -c 0` +------- +) + +$(LI $(LNAME2 new_schwartzSort_overload,Add overload `std.algorithm.sorting.schwartzSort!(alias transform, SwapStrategy ss, R)`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/new_schwartzSort_overload.dd) +$(P +$(REF schwartzSort, std,algorithm,sorting) now has an overloaded version that can be +used to provide a `SwapStrategy` without also explicitly specifying the predicate to +sort by. +) + +------- +auto s1 = a.schwartzSort!(abs, SwapStrategy.stable); + +// The old syntax still works. +auto s2 = a.schwartzSort!(abs, "a < b", SwapStrategy.stable); +------- +) + +$(LI $(LNAME2 phobos-dip1000,Phobos is now compiled with -preview=dip1000) +$(CHANGELOG_SOURCE_FILE phobos, changelog/phobos-dip1000.dd) +$(P +Phobos and Druntime are now compiled with -preview=dip1000. +) + +$(P +This is a major milestone in the transition to $(LINK2 https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md, DIP1000). Hence, end users can now start using `-preview=dip1000` in their own code bases. +) + +$(P +As always, any encountered issue should be reported to the $(LINK2 https://issues.dlang.org, issue tracker). +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 19661): DMD 2.084.0 SIGSEGV in std.traits.isFunction) +$(LI $(BUGZILLA 19758): $(LPAREN)0x01 & 0xFF$(RPAREN) == 0 by dmd 2.085.0$(LPAREN)-m64$(RPAREN) on Windows) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 711): combining mixins and overriding causes inifite loops) +$(LI $(BUGZILLA 1170): Cannot forward reference a type defined in a MixinStatement) +$(LI $(BUGZILLA 4923): immutable module variables are modifiable in non-shared module constructors) +$(LI $(BUGZILLA 5710): cannot use delegates as parameters to non-global template) +$(LI $(BUGZILLA 6541): using synchronized on a templated method crashes the compiler) +$(LI $(BUGZILLA 9029): Built-in types treated specially for alias parameters) +$(LI $(BUGZILLA 10739): Struct defined by template mixin leads to order-sensitivity of declarations) +$(LI $(BUGZILLA 13471): CTFE glitch when executing std.digest.crc.crc32Of$(LPAREN)$(RPAREN) and checking the result with enforce$(LPAREN)$(RPAREN). $(LPAREN)keyword: uninitialized variable$(RPAREN)) +$(LI $(BUGZILLA 13848): overlapping initialization for r) +$(LI $(BUGZILLA 17141): Type Inference Incorrectly Converts Characters to Integers) +$(LI $(BUGZILLA 18794): Compiling with -O causes runtime segfault) +$(LI $(BUGZILLA 18958): extern$(LPAREN)C++$(RPAREN) wchar, dchar mangling not correct) +$(LI $(BUGZILLA 19234): betterC TypeInfo error when using slice copy on Structs) +$(LI $(BUGZILLA 19813): Generated bt instruction seg faults, high 32 bits of register is garbage) +$(LI $(BUGZILLA 19814): Nested code blocks in Ddoc break formatting) +$(LI $(BUGZILLA 19829): __traits$(LPAREN)isSame$(RPAREN) returns true for some non-local delegate lambdas even when they are different) +$(LI $(BUGZILLA 19870): Generated Copy Constructor disables default construction) +$(LI $(BUGZILLA 19890): ICE: Segmentation fault with negative array size) +$(LI $(BUGZILLA 19891): Confusing error message for auto ref parameters with default values) +$(LI $(BUGZILLA 19893): extern$(LPAREN)C++, "ns"$(RPAREN) should count as module scope for version declarations) +$(LI $(BUGZILLA 19905): Floating point .init should be bitwise identical to .nan) +$(LI $(BUGZILLA 19920): __trait$(LPAREN)parent, ...$(RPAREN) broken with extern$(LPAREN)C++,"ns"$(RPAREN) nested in scopes) +$(LI $(BUGZILLA 19971): wrong string literals in "cannot pass argument" errors) +$(LI $(BUGZILLA 19995): parameter attributes are accepted in parameter-less functions) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 10665): The documentation produced by ddoc should clearly list all public imports of a module) +$(LI $(BUGZILLA 16002): Add __traits$(LPAREN)isModule$(RPAREN) and __traits$(LPAREN)isPackage$(RPAREN)) +$(LI $(BUGZILLA 16020): Allow AliasDeclarationY to express function types) +$(LI $(BUGZILLA 19856): [aApplycd2]: foreach $(LPAREN)int$(RPAREN) doesn't work on BigEndian targets) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 17358): [REG 2.074.0] std.stdio.File.lockingTextWriter.put no longer accepts chains of characters) +$(LI $(BUGZILLA 19740): Incorrect result of BigInt * BigInt) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 11061): std.variant.Variant equality comparison always returns false for static array literals.) +$(LI $(BUGZILLA 19226): std.typecons.Nullable$(LPAREN)T, T nullValue$(RPAREN) doesn't fully handle non-self-equal nullValue) +$(LI $(BUGZILLA 19781): etc.c.zlib should be @nogc) +$(LI $(BUGZILLA 19836): Excessive probability of UUID collisions in std.uuid.randomUUID) +$(LI $(BUGZILLA 19883): Cyclic constructor call for BigInt$(LPAREN)dstring$(RPAREN)) +$(LI $(BUGZILLA 19899): std.bitmanip.bitsSet should accept const arguments) +$(LI $(BUGZILLA 19939): std.format %13,3.2f does not count width correctly) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 6657): dotProduct overload for small fixed size arrays) +$(LI $(BUGZILLA 13965): More handy schwartzSort) +$(LI $(BUGZILLA 19513): Use sched_getaffinity$(LPAREN)2$(RPAREN) to get the number of CPU cores if available) +$(LI $(BUGZILLA 19892): Add CTFE support for std.bitmanip: nativeToBigEndian, bigEndianToNative, littleEndianToNative, nativeToLittleEndian) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 19861): core.cpuid reports the wrong number of threads) +) +) +$(D_CONTRIBUTORS_HEADER 63) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Aurélien Fredouelle) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Basile-z) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR Benjamin L. Merritt) + $(D_CONTRIBUTOR Cameron Ross) + $(D_CONTRIBUTOR Chloé) + $(D_CONTRIBUTOR dan) + $(D_CONTRIBUTOR Dan Printzell) + $(D_CONTRIBUTOR David Gileadi) + $(D_CONTRIBUTOR Dibyendu Majumdar) + $(D_CONTRIBUTOR Diederik de Groot) + $(D_CONTRIBUTOR dukc) + $(D_CONTRIBUTOR Ernesto Castellotti) + $(D_CONTRIBUTOR Eugen Wissner) + $(D_CONTRIBUTOR Flying-Toast) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Hiroo Ono) + $(D_CONTRIBUTOR hygonsoc) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Igor Stojković) + $(D_CONTRIBUTOR Ilya Yaroshenko) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR Johannes Pfau) + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR Jonathan M Davis) + $(D_CONTRIBUTOR Jonathan Marler) + $(D_CONTRIBUTOR Joseph Rushton Wakeling) + $(D_CONTRIBUTOR Leandro Lucarella) + $(D_CONTRIBUTOR look-at-me) + $(D_CONTRIBUTOR Manu Evans) + $(D_CONTRIBUTOR Marco de Wild) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR MetaLang) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Quirin F. Schroll) + $(D_CONTRIBUTOR Radu Racariu) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Robert Schadek) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR shove) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR stefanos-baziotis) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Tomáš Chaloupka) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR Zevenberge) + $(D_CONTRIBUTOR سليمان السهمي (Suleyman Sahmi)) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.087.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.087.1.dd b/changelog/2.087.1.dd new file mode 100644 index 0000000000..081b0262ea --- /dev/null +++ b/changelog/2.087.1.dd @@ -0,0 +1,121 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Aug 04, 2019, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 1 major change and 33 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 24 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 darwin-loader,Add all missing symbols to `core.sys.darwin.mach.loader`)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 darwin-loader,Add all missing symbols to `core.sys.darwin.mach.loader`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/darwin-loader.dd) +$(P +This also updates the module to match header in the macOS 10.15 SDK. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 19295): ICE when taking address of member function passed as template parameter) +$(LI $(BUGZILLA 20011): [REG] modification of member of a manifest constant that's also a struct is allowed) +$(LI $(BUGZILLA 20022): POSIX: extern$(LPAREN)C++, `namespace`$(RPAREN) does not apply namespace to enum) +$(LI $(BUGZILLA 20056): DMD Segfault in 2.087) +$(LI $(BUGZILLA 20063): compiler segfaults on passing templates expression to lazy val) +$(LI $(BUGZILLA 20067): [REG2.086] foreach no longer works on range with alias front) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 930): Templates inside templates used as mixins) +$(LI $(BUGZILLA 11856): DMD segfault with circular template constraints) +$(LI $(BUGZILLA 17828): [ICE] Internal error: ddmd/backend/cgcs.c 352 - CTFE appending to an array on a struct from a template) +$(LI $(BUGZILLA 17885): Unable to remove a tuple from associative array.) +$(LI $(BUGZILLA 19708): Can't use __traits$(LPAREN)getAttributes, ...$(RPAREN)[...] as a type) +$(LI $(BUGZILLA 19950): access violation at compile time, possibly via template constraint and alias interaction) +$(LI $(BUGZILLA 20019): Symbol not found: _dyld_enumerate_tlv_storage on macOS 10.15) +$(LI $(BUGZILLA 20025): alias this combined with a copy constructor seems to lead to undefined behaviour.) +$(LI $(BUGZILLA 20035): [ICE] Segmentation fault in ExpressionPrettyPrintVisitor::visit$(LPAREN)IntegerExp*$(RPAREN) at dmd/hdrgen.d:1775) +$(LI $(BUGZILLA 20039): ICE from double template instantiation with getMember of overload of class and template function) +$(LI $(BUGZILLA 20042): __vector CTFE crashes the compiler) +$(LI $(BUGZILLA 20044): Compiler crash when using an opaque struct as template parameter) +$(LI $(BUGZILLA 20045): bogus error: "integer constant expression expected instead of $(LPAREN)uint$(RPAREN).sizeof") +$(LI $(BUGZILLA 20048): [Windows] Program segfaults when running tests) +$(LI $(BUGZILLA 20051): ICE in func literal used in __traits$(LPAREN)compiles$(RPAREN)) +$(LI $(BUGZILLA 20052): SIMD 32 bytes causes obscure segfault) +$(LI $(BUGZILLA 20072): [2.087.0] Mixin templates: no property `somevar` for type `some.Type`, did you mean `some.Type.__anonymous.somevar`?) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 20065): Empty AliasSeq can't be used to form compiletime array literal) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 16132): std.variant.VariantN does not work with a class that inherits from a template instantiation) +$(LI $(BUGZILLA 19696): ReplaceType replaces type with the type forwarding using alias this) +$(LI $(BUGZILLA 19697): ReplaceType fails to compile for self-referential inheritance chains) +$(LI $(BUGZILLA 20046): someAllocator.make!T doesn't compile if T is a shared value type) +$(LI $(BUGZILLA 20070): [2.087.0] std.conv.toImpl matches two functions when using static arrays as inout$(LPAREN) T $(RPAREN)) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 19838): RefCounted fails to instantiate due to pureness of moveEmplace) +$(LI $(BUGZILLA 20043): Tuple.rename doesn't work with const) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 20026): retrying while pthread_cond_signal/pthread_cond_broadcast return EAGAIN) +$(LI $(BUGZILLA 20049): object.destroy doesn't propagate attributes) +) +) +$(D_CONTRIBUTORS_HEADER 24) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Basile-z) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Harry T. Vennik) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR karita) + $(D_CONTRIBUTOR Les De Ridder) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Márcio Martins) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Radu Racariu) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Shigeki Karita) + $(D_CONTRIBUTOR shove) + $(D_CONTRIBUTOR Stefan Koch) + $(D_CONTRIBUTOR Timon Gehr) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR سليمان السهمي (Suleyman Sahmi)) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.087.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.088.0.dd b/changelog/2.088.0.dd new file mode 100644 index 0000000000..1179965682 --- /dev/null +++ b/changelog/2.088.0.dd @@ -0,0 +1,747 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 01, 2019, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 27 major changes and 58 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 58 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dep_d1_ops,D1 operator overloads have been deprecated.)) +$(LI $(RELATIVE_LINK2 deprecate_ctor_in_static_block,Deprecate allowing a constructor declaration in a static block)) +$(LI $(RELATIVE_LINK2 deprecated_alias_this,`deprecated` now applies to `alias this` as well)) +$(LI $(RELATIVE_LINK2 error_18719,Double initialization of immutable fields inside constructor is now obsolete)) +$(LI $(RELATIVE_LINK2 getloc,add `__traits(getLocation, symbol)`)) +$(LI $(RELATIVE_LINK2 no-readmodify-error-if-struct-class,Suppress the "read-modify-write" error if type is a struct or a class)) +$(LI $(RELATIVE_LINK2 union_members,Postblit and destructors are no longer called on members of anonymous unions.)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 atomic-msync,`core.atomic : msync` has been removed)) +$(LI $(RELATIVE_LINK2 atomic_cas,Added overloads for `core.atomic.cas` which don't discard their result.)) +$(LI $(RELATIVE_LINK2 atomic_exchange,Added `core.atomic.atomicExchange`.)) +$(LI $(RELATIVE_LINK2 clock-monotonic,Non-POSIX `CLOCK` enum members have been removed from `core.sys.posix.time`)) +$(LI $(RELATIVE_LINK2 deprecate-callStructDtorsDuringGC,The druntime option `callStructDtorsDuringGC` has been deprecated.)) +$(LI $(RELATIVE_LINK2 dlfcn-posix,`core.sys.posix.dlfcn : dladdr, dlvsym, Dl_info` have been removed)) +$(LI $(RELATIVE_LINK2 exception-hiddenfunc,core.exception: Remove `onHiddenFuncError` / `HiddenFuncError`)) +$(LI $(RELATIVE_LINK2 exception-setasserthandler,`core.exception : setAssertHandler` has been removed)) +$(LI $(RELATIVE_LINK2 fiber-call,`core.thread : Fiber.call(bool)` has been removed)) +$(LI $(RELATIVE_LINK2 netinet-tcp,Module `core.sys.linux.sys.netinet.tcp` has been removed)) +$(LI $(RELATIVE_LINK2 runtime-initerm,`core.runtime : Runtime.initialize, Runtime.terminate` functions taking `ExceptionHandler` have been removed)) +$(LI $(RELATIVE_LINK2 std_string,Added `core.stdcpp.string`.)) +$(LI $(RELATIVE_LINK2 std_vector,Added `core.stdcpp.vector`.)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 array-opslice,std.array.Appender and RefAppender: use .opSlice() instead of data())) +$(LI $(RELATIVE_LINK2 errnoexception-errno-attributes,ErrnoException.errno is now nothrow pure @nogc @safe)) +$(LI $(RELATIVE_LINK2 remove-nullable-alias-get-this,`Nullable` `alias get this` has been deprecated)) +$(LI $(RELATIVE_LINK2 std-file-getAvailableDiskSpace,Added the `std.file.getAvailableDiskSpace` functionality.)) +$(LI $(RELATIVE_LINK2 std_json_trailing_comma,Allow std.json to overlook trailing comma)) + +) + +$(BUGSTITLE_TEXT_HEADER Installer changes, + +$(LI $(RELATIVE_LINK2 update-curl,Bundled libcurl is now built with `DONT_USE_RECV_BEFORE_SEND_WORKAROUND`)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 project-settings.file,Support for dub global settings file at the root package level)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dep_d1_ops,D1 operator overloads have been deprecated.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dep_d1_ops.dd) +$(P +The following D1 operator overloads have been deprecated in favor of `opUnary`: + * `opNeg` Replace with `opUnary(string op)() if (op == "-")` + * `opCom` Replace with `opUnary(string op)() if (op == "~")` + * `opPostInc` Replace with `opUnary(string op)() if (op == "++")` + * `opPostDec` Replace with `opUnary(string op)() if (op == "--")` + * `opStar` Replace with `opUnary(string op)() if (op == "*")` +) + +$(P +The following D1 operator overloads have been deprecated in favor of `opBinary`: + * `opAdd` Replace with `opBinary(string op)(...) if (op == "+")` + * `opSub` Replace with `opBinary(string op)(...) if (op == "-")` + * `opMul` Replace with `opBinary(string op)(...) if (op == "*")` + * `opDiv` Replace with `opBinary(string op)(...) if (op == "/")` + * `opMod` Replace with `opBinary(string op)(...) if (op == "%")` + * `opAnd` Replace with `opBinary(string op)(...) if (op == "&")` + * `opXor` Replace with `opBinary(string op)(...) if (op == "^")` + * `opOr` Replace with `opBinary(string op)(...) if (op == "|")` + * `opShl` Replace with `opBinary(string op)(...) if (op == "<<")` + * `opShr` Replace with `opBinary(string op)(...) if (op == ">>")` + * `opUShr` Replace with `opBinary(string op)(...) if (op == ">>>")` + * `opCat` Replace with `opBinary(string op)(...) if (op == "~")` + * `opIn` Replace with `opBinary(string op)(...) if (op == "in")` +) + +$(P +The following D1 operator overloads have been deprecated in favor of `opBinaryRight`: + * `opAdd_r` Replace with `opBinaryRight(string op)(...) if (op == "+")` + * `opSub_r` Replace with `opBinaryRight(string op)(...) if (op == "-")` + * `opMul_r` Replace with `opBinaryRight(string op)(...) if (op == "*")` + * `opDiv_r` Replace with `opBinaryRight(string op)(...) if (op == "/")` + * `opMod_r` Replace with `opBinaryRight(string op)(...) if (op == "%")` + * `opAnd_r` Replace with `opBinaryRight(string op)(...) if (op == "&")` + * `opXor_r` Replace with `opBinaryRight(string op)(...) if (op == "^")` + * `opOr_r` Replace with `opBinaryRight(string op)(...) if (op == "|")` + * `opShl_r` Replace with `opBinaryRight(string op)(...) if (op == "<<")` + * `opShr_r` Replace with `opBinaryRight(string op)(...) if (op == ">>")` + * `opUShr_r` Replace with `opBinaryRight(string op)(...) if (op == ">>>")` + * `opCat_r` Replace with `opBinaryRight(string op)(...) if (op == "~")` + * `opIn_r` Replace with `opBinaryRight(string op)(...) if (op == "in")` +) + +$(P +The following D1 operator overloads have been deprecated in favor of `opOpAssign`: + * `opAddAssign` Replace with `opOpAssign(string op)(...) if (op == "+")` + * `opSubAssign` Replace with `opOpAssign(string op)(...) if (op == "-")` + * `opMulAssign` Replace with `opOpAssign(string op)(...) if (op == "*")` + * `opDivAssign` Replace with `opOpAssign(string op)(...) if (op == "/")` + * `opModAssign` Replace with `opOpAssign(string op)(...) if (op == "%")` + * `opAndAssign` Replace with `opOpAssign(string op)(...) if (op == "&")` + * `opOrAssign` Replace with `opOpAssign(string op)(...) if (op == "|")` + * `opXorAssign` Replace with `opOpAssign(string op)(...) if (op == "^")` + * `opShlAssign` Replace with `opOpAssign(string op)(...) if (op == "<<")` + * `opShrAssign` Replace with `opOpAssign(string op)(...) if (op == ">>")` + * `opUShrAssign` Replace with `opOpAssign(string op)(...) if (op == ">>>")` + * `opCatAssign` Replace with `opOpAssign(string op)(...) if (op == "~")` +) + +$(P +Starting with this release, any D code that triggers a lowering to the D1 operator overloads will emit a deprecation warning. +) + +$(P +Example of deprecation warning: +) +--- +struct S +{ + int opAdd(int i) { ... } +} + +void main() +{ + S s; + int i; + i = s + 1; // Deprecation: `opAdd` is deprecated. Use `opBinary` instead. +} +--- + +$(P +Example of corrective action: +) +--- +struct S +{ + int opBinary(string op)(int i) if (op == "+") { ... } +} + +void main() +{ + S s; + int i; + i = s + 1; // OK +} +--- +) + +$(LI $(LNAME2 deprecate_ctor_in_static_block,Deprecate allowing a constructor declaration in a static block) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecate_ctor_in_static_block.dd) +$(P +The language specification states that a static constructor is +defined using the construction `static this()`. Defining a +constructor inside a static block does not have any effect +on the constructor. The following code does not affect +the constructor in any way: +) + +--- +static: + this() {} +--- + +--- +static +{ + this() {} +} +--- + +$(P +The compiler does not issue any warning/error on the above code +samples and generates a normal constructor which is not ran before +the `main` function. This leads to situations in which the +compiler is not able to correctly indicate the problem: +) + +--- +class A +{ + static + { + this() {} + } + + this() {} +} + +void main() +{ + new A(); +} +--- + +$(P +This code will result in an error message indicating that +there is a multiple definition of the constructor `this()` +which is a misleading message. +) + +$(P +Beginning with this release, whenever a constructor +is encountered in a static context an +error message is emitted stating that the `static` +keyword does not have any effect on the constructor. +The solution is to declare the constructor outside the +static block either as a normal constructor or a static +one (`static this()`). +) +) + +$(LI $(LNAME2 deprecated_alias_this,`deprecated` now applies to `alias this` as well) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecated_alias_this.dd) +$(P +Before this release, `deprecated` on `alias this` was accepted by the parser +but did not trigger a deprecation mesage on usage. +) +) + +$(LI $(LNAME2 error_18719,Double initialization of immutable fields inside constructor is now obsolete) +$(CHANGELOG_SOURCE_FILE dmd, changelog/error_18719.dd) +$(P +Inside a constructor scope, assigning to aggregate declaration (class/struct) +members is done by considering the first assignment as initialization and +subsequent assignments as modifications of the initially constructed object. +For `const`/`immutable` fields the initialization is accepted in the constructor, +but subsequent modifications are not. Example: +) + +--- +class A +{ + int a; + immutable int b; + this(int a, int b) + { + this.a = a; + this.b = b; + + this.a = 7; // OK, a is mutable + this.b = 9; // Error: immutable field b initialized multiple times + } +} +--- + +$(P +However, $(BUGZILLA 18719) shows that this rule does not apply when inside +a constructor scope there is a call to a different constructor: +) + +--- +class A +{ + immutable int a; + this() + { + this(42); + this.a = 5; // second initialization of immutable field + } + + this(int a) + { + this.a = a; + } +} +--- + +$(P +The above code wrongfully compiled succesfully before this patch, accepting the double +initialization of the `immutable` field `a`. Starting with this release, `this.a = 5` will emit +an error stating that `a` is initialized multiple times. +) +) + +$(LI $(LNAME2 getloc,add `__traits(getLocation, symbol)`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/getloc.dd) +$(P +Takes one argument which is a symbol. Returns a `tuple(string, int, int)` whose entries correspond to the filename, line number and column number where the argument +was declared. +) + +$(P +To disambiguate between overloads, pass the result of getOverloads with the desired index, to getLocation: +) +--- +module m; +int foo(); +int foo(int); +enum loc = __traits(getLocation, __traits(getOverloads, m, "foo")[0]); +--- +) + +$(LI $(LNAME2 no-readmodify-error-if-struct-class,Suppress the "read-modify-write" error if type is a struct or a class) +$(CHANGELOG_SOURCE_FILE dmd, changelog/no-readmodify-error-if-struct-class.dd) +$(P +If a struct or class with shared type implements the opUnary or opOpAssign +operator then it is possible to perform "read-modify-write" operations +because the operator's implementation is supposed to perform atomic operations. +) + +$(P +The purpose of this modification is to allow the creation of wrappers +(with structs or classes) to run atomic operations silently, for example: +) + +--- +shared struct Atomic { + int a; + + int opUnary(string s)() if (s == "++") + { + import core.atomic : atomicOp; + return atomicOp!"+="(a, 1); + } +} + +Atomic atomicvar; +atomicvar++; // Safe! Atomic struct implements opUnary +--- +) + +$(LI $(LNAME2 union_members,Postblit and destructors are no longer called on members of anonymous unions.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/union_members.dd) +$(P +Due to a bug in dmd, members of anonymous `unions` inside `struct` declarations +had their postblits/destructors called when an object of the containing +`struct` type was copied/destroyed. With this release, the postblit/destructor +is no longer called in such situations. +) + +$(P +Fixes: https://issues.dlang.org/show_bug.cgi?id=19122 +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 atomic-msync,`core.atomic : msync` has been removed) +$(CHANGELOG_SOURCE_FILE druntime, changelog/atomic-msync.dd) +$(P +It had been deprecated in 2.061 in favor of MemoryOrder. +) +) + +$(LI $(LNAME2 atomic_cas,Added overloads for `core.atomic.cas` which don't discard their result.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/atomic_cas.dd) +$(P +Existing `core.atomic.cas` functions discard the result, which make it impossible to implement certain operations. +A new set of overloads was added which take `ifThis` by pointer and write the result back to the argument. +) +) + +$(LI $(LNAME2 atomic_exchange,Added `core.atomic.atomicExchange`.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/atomic_exchange.dd) +$(P +Added missing `core.atomic.atomicExchange` function to the atomic suite. +) +) + +$(LI $(LNAME2 clock-monotonic,Non-POSIX `CLOCK` enum members have been removed from `core.sys.posix.time`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/clock-monotonic.dd) +$(P +Namely `CLOCK_MONOTONIC_RAW`, `CLOCK_MONOTONIC_COARSE` (linux), +`CLOCK_MONOTONIC_PRECISE`, `CLOCK_MONOTONIC_FAST` (FreeBSD, DragonflyBSD), +and `CLOCK_MONOTONIC_COARSE` (CRuntime_Glibc). +Those were deprecated in 2.067. +They are available on their respective platform modules. +) +) + +$(LI $(LNAME2 deprecate-callStructDtorsDuringGC,The druntime option `callStructDtorsDuringGC` has been deprecated.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/deprecate-callStructDtorsDuringGC.dd) +$(P +Starting with this release utilizing the `callStructDtorsDuringGC` runtime option will result in a +deprecation message printed to `stderr`. The option will be removed in a future release. +) +) + +$(LI $(LNAME2 dlfcn-posix,`core.sys.posix.dlfcn : dladdr, dlvsym, Dl_info` have been removed) +$(CHANGELOG_SOURCE_FILE druntime, changelog/dlfcn-posix.dd) +$(P +They are linux extensions, not POSIX, and thus can be found in `core.sys.linux.dlfcn`. +They had been deprecated since 2.063. +) +) + +$(LI $(LNAME2 exception-hiddenfunc,core.exception: Remove `onHiddenFuncError` / `HiddenFuncError`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/exception-hiddenfunc.dd) +$(P +Those have been deprecated since 2.068, +and are related to a language feature that is long gone. +) +) + +$(LI $(LNAME2 exception-setasserthandler,`core.exception : setAssertHandler` has been removed) +$(CHANGELOG_SOURCE_FILE druntime, changelog/exception-setasserthandler.dd) +$(P +It had been deprecated in 2.064 in favor of `assertHandler`. +) +) + +$(LI $(LNAME2 fiber-call,`core.thread : Fiber.call(bool)` has been removed) +$(CHANGELOG_SOURCE_FILE druntime, changelog/fiber-call.dd) +$(P +This had been deprecated since 2.068 in favor of `Fiber.call(Rethrow.[Yes|No])`. +) +) + +$(LI $(LNAME2 netinet-tcp,Module `core.sys.linux.sys.netinet.tcp` has been removed) +$(CHANGELOG_SOURCE_FILE druntime, changelog/netinet-tcp.dd) +$(P +This module had been deprecated since 2.077.0. +`core.sys.linux.netinet.tcp` should be imported instead. +) +) + +$(LI $(LNAME2 runtime-initerm,`core.runtime : Runtime.initialize, Runtime.terminate` functions taking `ExceptionHandler` have been removed) +$(CHANGELOG_SOURCE_FILE druntime, changelog/runtime-initerm.dd) +$(P +They were deprecated since 2.065 in favor of `rt_init` C functions, +which allow to initialize the runtime from C code. +) +) + +$(LI $(LNAME2 std_string,Added `core.stdcpp.string`.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/std_string.dd) +$(P +Added `core.stdcpp.string`, which links against C++ `std::basic_string` +) + +$(P +Known issues: +) + +$(P +Currently, the GCC (`libstdc++`) implementation has a known issue with the modern `__cxx11` ABI, because the C++ struct contains an interior pointer which is illegal in D, and incompatible with D move semantics. +To use `core.stdcpp.string` on linux/GCC, you must use the old string ABI by supplying `-D_GLIBCXX_USE_CXX11_ABI=0` to `g++`, and also `-version=_GLIBCXX_USE_CXX98_ABI` to your D compiler. +Work to define D move constructors is ongoing and expected to resolve this issue when it arrives. +) +) + +$(LI $(LNAME2 std_vector,Added `core.stdcpp.vector`.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/std_vector.dd) +$(P +Added `core.stdcpp.vector`, which links against C++ `std::vector` +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 array-opslice,std.array.Appender and RefAppender: use .opSlice() instead of data()) +$(CHANGELOG_SOURCE_FILE phobos, changelog/array-opslice.dd) +$(P +Previonsly, Appender.data() was used to extract a slice of the Appender's array. +Now use the [] slice operator instead. +The same goes for RefAppender. +) + +$(P +$(REF Appender, std, array) +$(REF RefAppender, std, array) +) +) + +$(LI $(LNAME2 errnoexception-errno-attributes,ErrnoException.errno is now nothrow pure @nogc @safe) +$(CHANGELOG_SOURCE_FILE phobos, changelog/errnoexception-errno-attributes.dd) +$(P +Before, it was just @system. As it turns out, all it does is return the value +of an integer field, so it can have all these attributes. +) +) + +$(LI $(LNAME2 remove-nullable-alias-get-this,`Nullable` `alias get this` has been deprecated) +$(CHANGELOG_SOURCE_FILE phobos, changelog/remove-nullable-alias-get-this.dd) +$(P +`Nullable`'s feature of implicitly converting to its contained value has been marked deprecated. +) + +$(P +All sites where a `Nullable!T` is implicitly converted to `T`, potentially throwing an error at runtime, +will now produce a deprecation warning or error with `-de`. +) + +$(P +To fix this, explicitly use `.get` to access the contained value of the `Nullable`. +) + +$(P +`alias get this` is the only implicit conversion in D that may throw an error. Since it is an implicit conversion, +it can easily be used accidentally and lead to unexpected runtime errors. By explicitly invoking `get`, +the developer acknowledges that the operation has a chance of error. Conversely, by not implicitly converting +`Nullable!T` to `T`, the compiler gives the developer a chance to spot forgotten `isNull` checks. +) + +$(P +This feature will be removed after release 2.096. +) +) + +$(LI $(LNAME2 std-file-getAvailableDiskSpace,Added the `std.file.getAvailableDiskSpace` functionality.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-file-getAvailableDiskSpace.dd) +$(P +$(REF getAvailableDiskSpace, std,file) receives as a parameter the path of a file or +directory in the file system, and returns the available disk space on the mounted filesystem. +If the given path is nonexistent, an exception is thrown. +) + +--- +import std.file; +ulong size = getAvailableDiskSpace("."); +assert(size > 0); +--- + +--- +import std.file; +assertThrown(getAvailableDiskSpace("NonExistentFile")); +--- +) + +$(LI $(LNAME2 std_json_trailing_comma,Allow std.json to overlook trailing comma) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std_json_trailing_comma.dd) +$(P +The JSON grammar does not allow trailing commas, however they are accepted by many JSON parsers. +$(MREF std,json) now ignores trailing commas as well. Use $(REF_SHORT JSONOptions.strictParsing, std,json) to disable this behavior. +) + +------- +import std.json; +import std.exception : assertThrown, assertNotThrown; + +// before +assertThrown(parseJSON(`{ "a" : { } , }`)); + +// after +assertNotThrown(parseJSON(`{ "a" : { } , }`)); +------- +) + + +) + +$(BUGSTITLE_TEXT_BODY Installer changes, + +$(LI $(LNAME2 update-curl,Bundled libcurl is now built with `DONT_USE_RECV_BEFORE_SEND_WORKAROUND`) +$(CHANGELOG_SOURCE_FILE installer, changelog/update-curl.dd) +$(P +The bundled libcurl is now build with +`DONT_USE_RECV_BEFORE_SEND_WORKAROUND`. See [#399](https://github.com/dlang/installer/pull/399) for details. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 project-settings.file,Support for dub global settings file at the root package level) +$(CHANGELOG_SOURCE_FILE dub, changelog/project-settings.file.dd) +$(P +Dub settings file can now also be added to project root folder +and has the highest priority. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 20021): `static if` doesn't evaluate `opCast$(LPAREN)T : bool$(RPAREN)`) +$(LI $(BUGZILLA 20057): compiler hang on conflicting local and imported template) +$(LI $(BUGZILLA 20136): opEquals not recognized for AA key) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 1142): .stringof performs semantic analysis) +$(LI $(BUGZILLA 7443): Better diagnostic on wrongly written static constructor) +$(LI $(BUGZILLA 9884): Refused initialization of const array in the module static this$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 15795): bogus "conflicts with" error depending on order of declaration) +$(LI $(BUGZILLA 15818): Multiple function declarations without definition cause ambiguity overloading error) +$(LI $(BUGZILLA 18719): Doubly-called constructor against member when using forwarding constructors) +$(LI $(BUGZILLA 18729): dmd -run executes in different environment) +$(LI $(BUGZILLA 19122): Postblits and destructors called on members of anonymous unions) +$(LI $(BUGZILLA 19315): #line inside token string affect outside code) +$(LI $(BUGZILLA 19534): Wrong error message "only one index allowed to index int") +$(LI $(BUGZILLA 19646): Initialization of globals not checked for @safe) +$(LI $(BUGZILLA 19919): Incorrect initialization of union when first member isn't marked = void) +$(LI $(BUGZILLA 19925): static opDispatch not considered in WithStatement) +$(LI $(BUGZILLA 19931): Missing error message when defining postblit, rvalue constructor and copy constructor) +$(LI $(BUGZILLA 19968): @safe code can create invalid bools resulting in memory corruption) +$(LI $(BUGZILLA 20001): Error: a struct is not a valid initializer for a _error_) +$(LI $(BUGZILLA 20033): alias this does not support `deprecated` attribute) +$(LI $(BUGZILLA 20047): call of static nested function ignores purity) +$(LI $(BUGZILLA 20050): pure function should be able to return function pointer to impure static nested function) +$(LI $(BUGZILLA 20073): Wrong implicit conversion for return type) +$(LI $(BUGZILLA 20074): header file generation doesn't include attributes with CallExp) +$(LI $(BUGZILLA 20096): error message 'cannot goto into try block' is followed by seg fault) +$(LI $(BUGZILLA 20100): Segfault with checkaction=context on struct comparison) +$(LI $(BUGZILLA 20108): -dip1000 defeated by auto) +$(LI $(BUGZILLA 20113): Cannot find source code for runtime library file 'object.d' when the path contains '~') +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 1252): Inline assembler could support BasicType properties) +$(LI $(BUGZILLA 18665): Deprecate Undocumented Operator Overloads) +$(LI $(BUGZILLA 19917): unions should require that all members are `= void` initialised) +$(LI $(BUGZILLA 19969): Unhelpful error when attempting $(LPAREN)incorrectly$(RPAREN) to append to a string) +$(LI $(BUGZILLA 20000): Casting to interfaces disallowed in @safe code) +$(LI $(BUGZILLA 20024): "No property x for type Y" error not as helpful as it should be) +$(LI $(BUGZILLA 20037): Imports in module info should be deduplicated) +$(LI $(BUGZILLA 20053): add mixin types) +$(LI $(BUGZILLA 20059): mismatched function return type inference should give location of inferred type) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 19823): std.algorithm.iteration.filter's popFront doesn't always pop the first element like it's supposed to) +$(LI $(BUGZILLA 19980): File.byLine skips first line in some cases when used inside map!$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 19986): Can't assign large const T to std.Variant.VariantN) +$(LI $(BUGZILLA 19987): std.variantN wastes space) +$(LI $(BUGZILLA 20064): format separator fails with leading zeros) +$(LI $(BUGZILLA 20097): SysTime cannot be used with std.concurrency.send) +$(LI $(BUGZILLA 20129): AA require with File values gives "Error: `return` expression expected" in object.d) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 16487): Add function to obtain the available disk space) +$(LI $(BUGZILLA 19834): File exception for [std.file.copy] on windows shows the target file rather than the source file) +$(LI $(BUGZILLA 19979): std.regex should return null instead of zero-length slice for non-matched captures) +$(LI $(BUGZILLA 19983): Add fast path using slice assignment to std.internal.cstring.tempCString) +$(LI $(BUGZILLA 19994): Can't nest self-referential Algebraic types) +$(LI $(BUGZILLA 20069): std.format digit grouping separator $(LPAREN)aka thousands separator$(RPAREN) needs to be revisited) +$(LI $(BUGZILLA 20098): Improve result of printing std.regex compiled pattern) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 20066): Assertion on void[] does not compile with -checkaction=context) +$(LI $(BUGZILLA 20088): void[] cast unusable in betterC due to new __ArrayCast template) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 19976): Simplify std.internal.convert.toUbyte CTFE path for float and double) +$(LI $(BUGZILLA 20104): core.atomic has no exchange function) +$(LI $(BUGZILLA 20122): core.atomic.cas discards result on failure) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 19402): specs for promotion rule of shift exp is wrong) +$(LI $(BUGZILLA 19944): Some examples on std.file docs page raise FileException) +) +) +$(D_CONTRIBUTORS_HEADER 58) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Alexibu) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Basile-z) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Brian Kessler) + $(D_CONTRIBUTOR Cameron Ross) + $(D_CONTRIBUTOR Charles McAnany) + $(D_CONTRIBUTOR Chloé Kekoa) + $(D_CONTRIBUTOR Dan Printzell) + $(D_CONTRIBUTOR David Gileadi) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR Dmitry Olshansky) + $(D_CONTRIBUTOR Dragos Carp) + $(D_CONTRIBUTOR Eduard Staniloiu) + $(D_CONTRIBUTOR Elias Batek) + $(D_CONTRIBUTOR Ernesto Castellotti) + $(D_CONTRIBUTOR Francesco Mecca) + $(D_CONTRIBUTOR godmyoh) + $(D_CONTRIBUTOR Greg V) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jason Schroeder) + $(D_CONTRIBUTOR jercaianu) + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR Jonathan Marler) + $(D_CONTRIBUTOR Kriyszig) + $(D_CONTRIBUTOR lenoil98) + $(D_CONTRIBUTOR Les De Ridder) + $(D_CONTRIBUTOR Manu Evans) + $(D_CONTRIBUTOR Marco de Wild) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Quirin F. Schroll) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Robert burner Schadek) + $(D_CONTRIBUTOR Robert Schadek) + $(D_CONTRIBUTOR Sebastiaan Koppe) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR shove) + $(D_CONTRIBUTOR Stanislav Blinov) + $(D_CONTRIBUTOR TJesionowski) + $(D_CONTRIBUTOR Tomáš Chaloupka) + $(D_CONTRIBUTOR Viktor) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR سليمان السهمي (Suleyman Sahmi)) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.088.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.088.1.dd b/changelog/2.088.1.dd new file mode 100644 index 0000000000..df8bedee89 --- /dev/null +++ b/changelog/2.088.1.dd @@ -0,0 +1,52 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 11, 2019, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 6 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 9 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 20223): C++, POSIX: Wrong mangling for const reference of callback) +$(LI $(BUGZILLA 20224): Segfault when using ref parameter on a templated struct $(LPAREN)C++ mangling$(RPAREN)) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 20219): Idle D programs keep consuming CPU in Gcx.scanBackground) +$(LI $(BUGZILLA 20227): "Aborting from src/core/sync/event.d$(LPAREN)141$(RPAREN) Error: pthread_mutex_destroy failed." after fork$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 20256): problem with signal handling and parallel GC on linux) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 20271): Handle forking in the GC) +) +) +$(D_CONTRIBUTORS_HEADER 9) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Igor Khasilev) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Vladimir Panteleev) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.088.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.089.0.dd b/changelog/2.089.0.dd new file mode 100644 index 0000000000..d174aab317 --- /dev/null +++ b/changelog/2.089.0.dd @@ -0,0 +1,442 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Nov 02, 2019, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 11 major changes and 66 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 44 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 deprecate_foreach_shadowing,Deprecate allowing shadowing in foreach loops)) +$(LI $(RELATIVE_LINK2 isexpression-const-inout-shared,$(I IsExpression)s now correctly match combinations of `const`, `inout`, and `shared`.)) +$(LI $(RELATIVE_LINK2 mixin_template_mangling,`extern(C)` declarations in template mixins now mangle as C symbols when mixed in at global scope)) +$(LI $(RELATIVE_LINK2 optlink,The default linker for the Digital Mars tool chain is now optlink.exe)) +$(LI $(RELATIVE_LINK2 xcc,New `-Xcc` compiler flag to address issue 6952)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 atomic_fetch_add,Added `core.atomic.atomicFetchAdd` and `core.atomic.atomicFetchSub`.)) +$(LI $(RELATIVE_LINK2 wait_attributes,Make wstatus predicates pure and @safe)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 unconst,Added std.traits.Unconst)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 ldc2,Improved support for LDC, incl. cross-compilation)) +$(LI $(RELATIVE_LINK2 lint,Lint command added)) +$(LI $(RELATIVE_LINK2 semver-compatibility-operator,Added SemVer compatibility operator "^")) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 deprecate_foreach_shadowing,Deprecate allowing shadowing in foreach loops) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecate_foreach_shadowing.dd) +$(P +Up until this version it was allowed to shadow a variable in a `foreach` loop, although +it is dissallowed in a normal `for` loop. This patch makes the behavior of the `foreach` +loop consistent with the `for` loop one. To fix any issues encountered, rename the variable +inside the `foreach` body that shadows the one from the upper scope. +) +) + +$(LI $(LNAME2 isexpression-const-inout-shared,$(I IsExpression)s now correctly match combinations of `const`, `inout`, and `shared`.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/isexpression-const-inout-shared.dd) +$(P +With $(BUGZILLA 20138) fixed, +$(LINK2 $(ROOT_DIR)spec/expression.html#is_expression, $(I IsExpression)s) now +correctly match combinations of the qualifiers `const`, `inout`, and `shared`. +) + +$(P +Examples that failed previously but pass now: +) + +---- +static assert(is(shared(const int) U == shared U) && is(U == const int)); +static assert(is(shared(inout int) U == inout U) && is(U == shared int)); +---- + +$(P +Note that the behavior of code like the following changes: +) + +---- +static if (is(T U == const U) { ...} +else static if (is(T U == shared const U)) { ... } +---- + +$(P +The second case will never be reached, because the first one now matches when +`T` is `shared const`. To get the old behavior, switch the order. +) +) + +$(LI $(LNAME2 mixin_template_mangling,`extern(C)` declarations in template mixins now mangle as C symbols when mixed in at global scope) +$(CHANGELOG_SOURCE_FILE dmd, changelog/mixin_template_mangling.dd) +$(P +This was already true for string mixins, but since template mixins introduce a new scope, symbols inside them got mangled as D symbols. +However, users often use `extern(C)` inside a mixin template to automatically generate boilerplate code that should be accessible from C. +) + +------- +// library code +mixin template WasmEntryPoint() { + extern(C) export void _start() { + // boilerplate code + } +} + +mixin template UseGpuInsteadOfIntegratedGraphics() { + extern(C) export uint NvOptimusEnablement = 0x00000001; + extern(C) export int AmdPowerXpressRequestHighPerformance = 1; +} + +// application code +mixin WasmEntryPoint; +mixin UseGpuInsteadOfIntegratedGraphics; + +static assert(_start.mangleof == "_start"); +static assert(NvOptimusEnablement.mangleof == "NvOptimusEnablement"); +------- + +$(P +Previously, _start would be mangled like `_D9onlineapp8__mixin46_startUkZv` and users had to manually add `pragma(mangle, "_start")` or use a string mixin instead. +With the new behavior this is not necessary anymore for `extern(C)`, as well as `extern(Windows)` and `extern(Objective-C)`. +`extern(C++)` remains unchanged since it already always mangles to C++, even in nested scopes. +) + +$(P +There is a possibility this breaks code if you mix in different `extern(C)` declarations with the same name in the global scope of multiple modules. +) + +------- +import core.stdc.stdio; + +mixin template GenPrintCallback(string text) { + extern(C): + + auto textLength = text.length; + auto textPointer = text.ptr; + + void callBackOnly() { + printf("%.*s\n", textLength, textPointer); + } + + mixin(`auto `, text, ` = &callBackOnly;`); +} + +mixin GenPrintCallback!"foo"; + +// in a different module: +mixin GenPrintCallback!"bar"; +------- + +$(P +In this case textLength, textPointer and callBackOnly will be defined multiple times, so the linker either picks one or raises and error. +The solution is to not make variables `extern(C)` and make C callback functions anonymous: +) + +------- +import core.stdc.stdio; + +mixin template GenPrintCallback(string text) { + + auto textLength = text.length; // not below an extern(C): anymore + auto textPointer = text.ptr; + + alias FunT = extern(C) void function(); + enum FunT callBackOnly = () { + printf("%.*s\n", textLength, textPointer); + }; + + mixin(`auto `, text, ` = callBackOnly;`); +} +------- +) + +$(LI $(LNAME2 optlink,The default linker for the Digital Mars tool chain is now optlink.exe) +$(CHANGELOG_SOURCE_FILE dmd, changelog/optlink.dd) +$(P +The default linker when building with -m32 under Windows has been changed +from link.exe to optlink.exe to avoid calling the wrong linker when both +the Digital Mars tool chain and the Microsoft compiler tools are found in +the PATH environment variable. +) +) + +$(LI $(LNAME2 xcc,New `-Xcc` compiler flag to address issue 6952) +$(CHANGELOG_SOURCE_FILE dmd, changelog/xcc.dd) +$(P +On POSIX, `dmd` passes `-L`-prefixed compiler flags through the linker driver (`cc` by default) to +the linker (e.g. `ld`) by prepending them with `-Xlinker`. Therefore, it was not possible to pass +flags directly to the linker driver. +) + +$(P +This release adds a new compiler flag, `-Xcc`, which specifies a flag to pass to the linker driver. +This switch has already existed in the LDC compiler for several releases. Some use cases for it +would be `-nostartfiles`, `-pthread`, and `-static`, which can now be specified as +`-Xcc=-nostartfiles`, `-Xcc=-pthread`, and `-Xcc=-static` respectively. +) + +$(P +Note that it was previously also possible to specify linker driver options by setting the `CC` +environment variable, e.g. `CC='cc -pthread' dmd ...`, or by setting the `CC` variable to point to a +custom linker driver wrapper script. `-Xcc` improves on this through composability and better +opportunities for integration into build systems. +) + +$(P +See also: +- $(LINK2 https://issues.dlang.org/show_bug.cgi?id=6952, Issue 6952) +- $(LINK2 https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html, GCC Link Options) +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 atomic_fetch_add,Added `core.atomic.atomicFetchAdd` and `core.atomic.atomicFetchSub`.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/atomic_fetch_add.dd) +$(P +Added `core.atomic.atomicFetchAdd` and `core.atomic.atomicFetchSub` to the atomic suite. +) +) + +$(LI $(LNAME2 wait_attributes,Make wstatus predicates pure and @safe) +$(CHANGELOG_SOURCE_FILE druntime, changelog/wait_attributes.dd) +$(P +The predicates that operate on the wstatus value reported by wait(2) are now +marked pure and @safe, allowing them to be used in functions with those +attributes. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 unconst,Added std.traits.Unconst) +$(CHANGELOG_SOURCE_FILE phobos, changelog/unconst.dd) +$(P +$(REF Unconst, std, traits) works like $(REF Unqual, std, traits), but removes +only `const`, `inout` and `immutable` qualifiers from a type. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 ldc2,Improved support for LDC, incl. cross-compilation) +$(CHANGELOG_SOURCE_FILE dub, changelog/ldc2.dd) +$(P +The ldc2 driver now supports +* some more command-line options (coverage, profiling, keeping stack frame), +* separate linking, +* cross-compilation by specifying the target triple (LDC `-mtriple`) as `--arch`, e.g., `--arch=x86_64-pc-windows-msvc`. + Check out https://wiki.dlang.org/Cross-compiling_with_LDC for how to setup LDC. +) +) + +$(LI $(LNAME2 lint,Lint command added) +$(CHANGELOG_SOURCE_FILE dub, changelog/lint.dd) +$(P +Dub supports now command `lint`, which will execute D-Scanner on the dub package. +By default `dub lint` will execute style check. Import paths to dependent dub +packages will be passed to D-Scanner. +) + +$(P +$(CONSOLE +> dub lint +) +) +) + +$(LI $(LNAME2 semver-compatibility-operator,Added SemVer compatibility operator "^") +$(CHANGELOG_SOURCE_FILE dub, changelog/semver-compatibility-operator.dd) +$(P +Dub now supports version specifications of the form `^x.y.z`. +This corresponds to a "semver compatible version", ie. any version up from +`x.y.z` with the same major number. If the major number is 0, only the same +version matches. This corresponds to the versions listed on https://semver.org/ as +compatible with the public API of the version given. +`^x.y` is equivalent to `^x.y.0`. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 20126): codegen reloads parameter from register when iasm changed the backing memory) +$(LI $(BUGZILLA 20212): invalid debug info with enum type in library) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 982): Codeview: symbols of enum type are declared integer) +$(LI $(BUGZILLA 1104): CodeView: char is marked 0x20 $(LPAREN)T_UCHAR$(RPAREN) instead of 0x10 $(LPAREN)T_CHAR$(RPAREN)) +$(LI $(BUGZILLA 2195): Variable shadowing in foreach is not detected and reported) +$(LI $(BUGZILLA 2450): Error using operators from named template mixin) +$(LI $(BUGZILLA 3831): writeln of a delegate typeid) +$(LI $(BUGZILLA 4372): type of enumerator values reduced to base type in debug info) +$(LI $(BUGZILLA 6952): Static Linking on Linux) +$(LI $(BUGZILLA 13582): Deprecated modules imported from other deprecated modules shouldn't be warned about) +$(LI $(BUGZILLA 16047): Range violation in setting multi-dimensional AA entries) +$(LI $(BUGZILLA 19965): [DIP1000] Template allows to escape internal pointer) +$(LI $(BUGZILLA 20012): extern$(LPAREN)C$(RPAREN) functions inside template mixins are not mangled as C functions) +$(LI $(BUGZILLA 20089): FPU stack not cleaned up properly) +$(LI $(BUGZILLA 20131): Bad codegen from inline asm LOCK CMPXCHG; possible REX prefix missing) +$(LI $(BUGZILLA 20138): is expression not evaluating correctly?) +$(LI $(BUGZILLA 20163): Deprecated import in string mixin does not output diagnostic message) +$(LI $(BUGZILLA 20164): Importing deprecated module at function-local scope does not output diagnostic message) +$(LI $(BUGZILLA 20181): [nightly 2019-08-29] internal compiler error when static foreach iterating property method of struct) +$(LI $(BUGZILLA 20244): New dmd option -preview=noXlinker does not work on Linux to build a simple D application) +$(LI $(BUGZILLA 20267): Error: `string` is used as a type - and similar “smart” error messages) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 809): Should be possible to convert lazy argument to delegate) +$(LI $(BUGZILLA 1547): Default parameter values should use implicit static opCall) +$(LI $(BUGZILLA 3004): [patch] Better handling of ignored pragmas) +$(LI $(BUGZILLA 15118): Have dmd on Win32 look for optlink.exe instead of link.exe) +$(LI $(BUGZILLA 18272): missing changelog entry and no doc for -gf $(LPAREN)besides cryptic emit debug info for all referenced types$(RPAREN)) +$(LI $(BUGZILLA 18617): need __traits$(LPAREN)deprecated, expr$(RPAREN) to check whether an expression would trigger deprecation) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 20186): File size of "Hello, world" executable increased by 185KB) +$(LI $(BUGZILLA 20295): std.zip: zip64 with 0xff bytes in end of central dir record do not work) +$(LI $(BUGZILLA 20328): [REG 2.089 beta] deprecation message about Nullable.get in isInputRange) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 15230): Inconsistent std.range.SortedRange predicate checks) +$(LI $(BUGZILLA 17705): std.math.isFinite cannot run at compile-time) +$(LI $(BUGZILLA 19514): gcd$(LPAREN)BigInt$(LPAREN)2$(RPAREN), BigInt$(LPAREN)1$(RPAREN)$(RPAREN) fails) +$(LI $(BUGZILLA 20027): std.zip susceptible to zip malware attacks) +$(LI $(BUGZILLA 20145): Random unittest failures inf std.datetime.stopwatch) +$(LI $(BUGZILLA 20205): std.math: Wrong result for abs$(LPAREN)int.min$(RPAREN)) +$(LI $(BUGZILLA 20218): Checked format string takes infinite time for infinite ranges) +$(LI $(BUGZILLA 20239): chameleon zip-file should be rejected by std.zip) +$(LI $(BUGZILLA 20240): BitArray inconsistently preserves bits past length) +$(LI $(BUGZILLA 20241): BitArray.bitsSet ignores length) +$(LI $(BUGZILLA 20287): std.zip: Wrong compressed data) +$(LI $(BUGZILLA 20301): std.regex.regex doesn't accept a const/immutable array of patterns) +$(LI $(BUGZILLA 20302): std.functional.memoize doesn't accept a functions with const/immutable parameters) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 20147): Enable comparison $(LPAREN)==, >, >=, <=, <$(RPAREN) between std.bigint.BigInt and floating point numbers) +$(LI $(BUGZILLA 20159): Make std.math.scalbn work in CTFE) +$(LI $(BUGZILLA 20192): Make std.math.isSubnormal work in CTFE) +$(LI $(BUGZILLA 20196): Make std.math.isNormal work in CTFE) +$(LI $(BUGZILLA 20199): Make std.math.frexp work in CTFE) +$(LI $(BUGZILLA 20200): Make std.math.isPowerOf2 work for floating point numbers in CTFE) +$(LI $(BUGZILLA 20201): Make std.math.scalbn pure) +$(LI $(BUGZILLA 20202): Make std.math.signbit work in CTFE) +$(LI $(BUGZILLA 20203): Make std.math.copysign work in CTFE) +$(LI $(BUGZILLA 20242): BitArray constructor should not modify input data) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 20270): [REG2.087] Deadlock in garbage collection when running processes in parallel) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 13821): fiber + exception + win server 2012 failures) +$(LI $(BUGZILLA 16380): no bindings for err.h) +$(LI $(BUGZILLA 18643): Compiling error when combining CAS and numeric literal.) +$(LI $(BUGZILLA 19481): Aborting from local/libphobos/libdruntime/core/sync/mutex.d$(LPAREN)95$(RPAREN) Error: pthread_mutex_init failed.) +$(LI $(BUGZILLA 20155): Allocating a struct with dtor on the GC heap can produce false pointers) +$(LI $(BUGZILLA 20214): GC: realloc can result in false pointers if address doesn't change) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 8831): core.atomic: add compare-and-swap function with other result type) +$(LI $(BUGZILLA 13826): Move volatileLoad/Store to core.volatile when the volatile keyword is removed) +$(LI $(BUGZILLA 15007): core.atomic match C++11) +$(LI $(BUGZILLA 20105): core.atomic 'cas' function is incomplete) +$(LI $(BUGZILLA 20106): core.atomic : atomicFence doesn't accept MemoryOrder) +$(LI $(BUGZILLA 20107): core.atomic : Memory order is missing keys) +) +) +$(D_CONTRIBUTORS_HEADER 44) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR 0xEAB) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Andrej Mitrovic) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Bernhard Seckinger) + $(D_CONTRIBUTOR Berni) + $(D_CONTRIBUTOR Cameron Ross) + $(D_CONTRIBUTOR Chloé) + $(D_CONTRIBUTOR Dan Printzell) + $(D_CONTRIBUTOR devel) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR drug007) + $(D_CONTRIBUTOR Eduard Staniloiu) + $(D_CONTRIBUTOR Ernesto Castellotti) + $(D_CONTRIBUTOR Feldwor) + $(D_CONTRIBUTOR Harry T. Vennik) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jon Degenhardt) + $(D_CONTRIBUTOR Jonathan Marler) + $(D_CONTRIBUTOR Les De Ridder) + $(D_CONTRIBUTOR look-at-me) + $(D_CONTRIBUTOR Manu Evans) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Mike Franklin) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Robert burner Schadek) + $(D_CONTRIBUTOR Robert Schadek) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Stefanos Baziotis) + $(D_CONTRIBUTOR stefanos-baziotis) + $(D_CONTRIBUTOR Tobias Pankrath) + $(D_CONTRIBUTOR Tomoya Tanjo) + $(D_CONTRIBUTOR Viktor) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.089.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.089.1.dd b/changelog/2.089.1.dd new file mode 100644 index 0000000000..4b1d1ce03c --- /dev/null +++ b/changelog/2.089.1.dd @@ -0,0 +1,90 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Dec 14, 2019, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 22 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 19 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 15069): [REG2.064] nonsense struct template instantiations still compile) +$(LI $(BUGZILLA 19884): [regression] Error: alias op = op; cannot alias itself, use a qualified name to create an overload set) +$(LI $(BUGZILLA 20348): [Reg 2.089.0-rc.1] Bad debug info for enum forward references) +$(LI $(BUGZILLA 20349): [REG2.087] ICE with sqrt) +$(LI $(BUGZILLA 20376): @disable this$(LPAREN)ref return scope Foo rhs$(RPAREN) enables broken binaries $(LPAREN)out-of-bounds access$(RPAREN)) +$(LI $(BUGZILLA 20388): Parse error when compiling lambdas in mixins as template parameters) +$(LI $(BUGZILLA 20416): [Regression 2.073.2] compiler complains about escaping reference in certain cases) +$(LI $(BUGZILLA 20420): [REG2.067] inlining error with a valid function) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 20092): void[1] auto slicing makes the compiler hang) +$(LI $(BUGZILLA 20253): bad debug line info for function without epilog) +$(LI $(BUGZILLA 20264): ICE on illegal cast to vector.) +$(LI $(BUGZILLA 20280): Compiler segfault when building two small files) +$(LI $(BUGZILLA 20366): CTFE foreach_reverse on array with utf characters crashes compiler) +$(LI $(BUGZILLA 20431): Allow a Mixin Type to resolve to an expression where it makes sense) +$(LI $(BUGZILLA 20441): Wrong code with -O -fPIC and pointer subtraction) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 20356): exceeding template expansion limits) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 20054): getSymbolsByUDA no longer works on modules) +$(LI $(BUGZILLA 20350): JSONType deprecations should be undeprecated) +$(LI $(BUGZILLA 20354): interface is not supported by CanCAS in core.internal.atomic) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 20438): [Reg 2.086] GC: memory not reusable when calling GC.collect after GC.free) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 20355): undefined identifier U in core.atomic) +) +$(BUGSTITLE_BUGZILLA Tools bugs, + +$(LI $(BUGZILLA 20386): Test extractor shouldn't emit unit tests, but regular functions for @betterC tests) +) +) +$(D_CONTRIBUTORS_HEADER 19) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Carsten Schlote) + $(D_CONTRIBUTOR dukc) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR lempiji) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Robert Schadek) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR Stian Gulpen) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR سليمان السهمي (Suleyman Sahmi)) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.089.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.090.0.dd b/changelog/2.090.0.dd new file mode 100644 index 0000000000..3d20ce775a --- /dev/null +++ b/changelog/2.090.0.dd @@ -0,0 +1,397 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 05, 2020, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 10 major changes and 71 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 48 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 lazy-delegate,Can now extract delegate from `lazy` parameter)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 gc_in_finalizer,$(REF GC.inFinalizer, core, memory) was added)) +$(LI $(RELATIVE_LINK2 platform_dependent_execinfo,Platform dependent execinfo introspection added)) +$(LI $(RELATIVE_LINK2 to-prec,Added intrinsic `toPrec` to round to a specific float precision)) +$(LI $(RELATIVE_LINK2 unittest-default,Unittest default mode)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 appender-toString,Deprecated `std.array.Appender.toString` was removed)) +$(LI $(RELATIVE_LINK2 binaryReverseArgs,Deprecated `std.functional.binaryReverseArgs` was removed)) +$(LI $(RELATIVE_LINK2 bitmanip-toString,Deprecated `std.bitmanip.BitArray.toString` was removed)) +$(LI $(RELATIVE_LINK2 experimental-all,Deprecated module `std.experimental.all` was removed)) +$(LI $(RELATIVE_LINK2 json_number_conversion,Added get!(T) getter to std.json)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 lazy-delegate,Can now extract delegate from `lazy` parameter) +$(CHANGELOG_SOURCE_FILE dmd, changelog/lazy-delegate.dd) +$(P +The underlying delegate of the `lazy` parameter may be extracted +using the `&` operator: +) + +--- +void test(lazy int dg) +{ + int delegate() dg_ = &dg; + assert(dg_() == 7); + assert(dg == dg_()); +} + +void main() +{ + int a = 7; + test(a); +} +--- + +$(P +Previously this caused a compile error. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 gc_in_finalizer,$(REF GC.inFinalizer, core, memory) was added) +$(CHANGELOG_SOURCE_FILE druntime, changelog/gc_in_finalizer.dd) +$(P +A new function exposing information about the state of the GC was added. +It returns `true` if the current thread is executing destructors (finalizers) +of objects allocated on the GC heap that are either: +* no longer being referenced +* to whose finalizers an explicit call to `GC.runFinalizers` + was made (usually as part of shared library unloading). +) + +$(P +Destructors of objects allocated on the GC heap presently have several +limitations or oddities: +* As destructors of all unreachable objects are ran in indeterministic order, + there's no guarantee that object members are alive during the object's + finalization +* Allocation during finalization is disallowed +* In contrast to stack allocated objects, partially constructed objects (object + whose constructor threw an exception) may be finalized +) + +$(P +$(REF GC.inFinalizer, core, memory) can be used to efficiently guard against +programming errors such as the above, or to detect whether certain +objects were left to be destroyed by the GC. +) +) + +$(LI $(LNAME2 platform_dependent_execinfo,Platform dependent execinfo introspection added) +$(CHANGELOG_SOURCE_FILE druntime, changelog/platform_dependent_execinfo.dd) +$(P +A new module (core.internal.execinfo) has been added for platform dependent +execinfo detection. On every POSIX system which provides an execinfo +implementation as part of its C runtime the appropriate implementation- +dependent execinfo module will be imported automatically. +) + +$(P +Besides that, there is an opportunity for using external execinfo +implementations built as separated libraries and linking DRuntime with them. +) + +$(P +$(B IMPORTANT:) On platforms with C runtime not providing execinfo +functionality one should decide whether an external lib (e.g. libexecinfo) +will be used, or not. If not, DRuntime should be built normally without any +additional version ID, but with external lib exactly one of the following +version IDs should be chosen at compile time. That means, the selected +external format cannot be changed later without rebuilding DRuntime. +) + +$(P +It could be really important to keep this in mind when someone is packaging +DRuntime for such OSs (e.g. ones using musl libc) and provide packages with +and without execinfo support (with the specific external library as +dependency) or in the case of source based packages, make this build option +selectable (e.g. portage). +) + +$(P +$(TABLE +$(THEAD Version ID, Backtrace format) +$(TROW $(B ExtExecinfo_BSDFmt), 0x00000000 <_D6module4funcAFZv+0x78> at module) +$(TROW $(B ExtExecinfo_DarwinFmt), +1 module 0x00000000 D6module4funcAFZv + 0) +$(TROW $(B ExtExecinfo_GNUFmt), module(_D6module4funcAFZv) [0x00000000] $(B or) +module(_D6module4funcAFZv+0x78) [0x00000000] +$(B or) module(_D6module4funcAFZv-0x78) [0x00000000]) +$(TROW $(B ExtExecinfo_SolarisFmt), object'symbol+offset [pc]) +) +) + +$(P +These formats above cover most of the "classic" backtrace outputs but as a new +important format emerges, it can be easily added. +) +) + +$(LI $(LNAME2 to-prec,Added intrinsic `toPrec` to round to a specific float precision) +$(CHANGELOG_SOURCE_FILE druntime, changelog/to-prec.dd) +$(P +The intrinsic $(REF toPrec, core,math) forces rounding of it +floating point argument to the precision of `float`, +`double`, or `real`. +) + +$(P +Some floating point algorithms, such as +Kahan-Babuska-Neumaier Summation, require rounding +to specific precisions. Rounding to precision after +every operation, however, loses overall precision in +the general case and is a runtime performance problem. +) + +$(P +Adding these functions guarantee the rounding at required +points in the code, and document where in the algorithm +the requirement exists. +) +) + +$(LI $(LNAME2 unittest-default,Unittest default mode) +$(CHANGELOG_SOURCE_FILE druntime, changelog/unittest-default.dd) +$(P +Switched the default for unittests to only run the tests by default. Use `--DRT-testmode=run-main` for the original behavior (run unittests then main). +) + +$(P +The feature to control unit testing was added in $(LINK2 $(ROOT_DIR)/changelog/2.078.0.html#core-runtime-unittestEnhancement, 2.078.0), and the switch above will work for all versions since then. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 appender-toString,Deprecated `std.array.Appender.toString` was removed) +$(CHANGELOG_SOURCE_FILE phobos, changelog/appender-toString.dd) +$(P +The overload accepting a callable was deprecated since 2.079 +and has now been removed. Use the overload accepting an output +range instead. +) +) + +$(LI $(LNAME2 binaryReverseArgs,Deprecated `std.functional.binaryReverseArgs` was removed) +$(CHANGELOG_SOURCE_FILE phobos, changelog/binaryReverseArgs.dd) +$(P +This specialisation of `reverseArgs` accepting exactly two arguments was +deprecated since 2.079 and has now been removed. Use `reverseArgs` instead. +) +) + +$(LI $(LNAME2 bitmanip-toString,Deprecated `std.bitmanip.BitArray.toString` was removed) +$(CHANGELOG_SOURCE_FILE phobos, changelog/bitmanip-toString.dd) +$(P +The overload accepting a callable was deprecated since 2.079 +and has now been removed. Use the overload accepting an output +range instead. +) +) + +$(LI $(LNAME2 experimental-all,Deprecated module `std.experimental.all` was removed) +$(CHANGELOG_SOURCE_FILE phobos, changelog/experimental-all.dd) +$(P +All symbols contained in Phobos can now be used with `import std` +) +) + +$(LI $(LNAME2 json_number_conversion,Added get!(T) getter to std.json) +$(CHANGELOG_SOURCE_FILE phobos, changelog/json_number_conversion.dd) +$(P +This getter will try to return underlying json type as T if possible. +It is convenient for automatic integer conversion like this: +) +------- +import std.json; +string s = `{ "a": 123 }`; +auto json = parseJSON(s); + +// This will throw with json["a"].floating +assert(json["a"].get!double == 123.0); +------- +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 20383): [REG 2.084.z] illegal conversion from int[] to ubyte[] is accepted) +$(LI $(BUGZILLA 20418): Unittest failure in bitarray.d on Win32) +$(LI $(BUGZILLA 20465): Dynamic + static array declaration fail) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 6592): di header file created even if errors occur) +$(LI $(BUGZILLA 8684): Missing '$(RPAREN)' in argument list creates a sea of error messages) +$(LI $(BUGZILLA 9490): 'this' is not found when expression is in parentheses) +$(LI $(BUGZILLA 10562): Cannot initialize arrays by an element value when the elements are fixed-length arrays) +$(LI $(BUGZILLA 14696): destructor for temporary called before statement is complete with conditional operator) +$(LI $(BUGZILLA 17125): Header Generation Incorrectly Formats Floating Point Number) +$(LI $(BUGZILLA 19432): Cannot initialize ulong with decimal value above signed long range) +$(LI $(BUGZILLA 20151): particular directory layout causes DMD to crash with an access violation) +$(LI $(BUGZILLA 20220): pragma$(LPAREN)crt_constructor$(RPAREN) does not work with clang 9) +$(LI $(BUGZILLA 20318): Illegal instruction $(LPAREN)core dumped$(RPAREN)) +$(LI $(BUGZILLA 20326): stringof on opaque type results in forward reference error) +$(LI $(BUGZILLA 20367): Postblit cannot be disabled when copy ctor is defined) +$(LI $(BUGZILLA 20400): CTFE increasing length of array of characters changes its value) +$(LI $(BUGZILLA 20401): ref variable copied before return) +$(LI $(BUGZILLA 20406): Copy constructor requires default constructor) +$(LI $(BUGZILLA 20413): C++ mangling bug with templates & the std namespace) +$(LI $(BUGZILLA 20417): __traits$(LPAREN)compiles$(RPAREN) returns false result if expression is not wrapped inside a lambda while typeof works correctly) +$(LI $(BUGZILLA 20419): is$(LPAREN)missing == module/package$(RPAREN) results in unknown identifier) +$(LI $(BUGZILLA 20466): Optimizer clobbering msw register when testing it for 0) +$(LI $(BUGZILLA 20475): Struct of static array of strings is bitwise-compared instead of member-wise) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 4544): Better error-message when expecting string but got a character constant) +$(LI $(BUGZILLA 11038): static has no effect as a block attribute for imports) +$(LI $(BUGZILLA 18809): Improve error message on nonexistent property) +$(LI $(BUGZILLA 20334): posix.mak clean target does not remove all generated files) +$(LI $(BUGZILLA 20448): Error: unknown when mutating an escaped member reference from a template function) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 9588): format prints context pointer for struct) +$(LI $(BUGZILLA 9592): Justified Tuple printing) +$(LI $(BUGZILLA 10126): Make TaskPool terminate on its own or improve docs to make it clear that it won't) +$(LI $(BUGZILLA 10448): min and max are not NaN aware) +$(LI $(BUGZILLA 10902): some phobos unittests take an excessive amount of time) +$(LI $(BUGZILLA 11013): ignoring variable inside the predicate of findSplitBefore) +$(LI $(BUGZILLA 11782): format pointer to range prints range) +$(LI $(BUGZILLA 15405): FormatSpec.writeUpToNextSpec$(LPAREN)$(RPAREN) not documented) +$(LI $(BUGZILLA 15940): ImplicitConversionTargets and class alias in struct) +$(LI $(BUGZILLA 16223): BigUint: undefined shift for small instantiation type) +$(LI $(BUGZILLA 18248): radix overload of std.conv.parse fails to throw on non-empty range without number) +$(LI $(BUGZILLA 18446): Wrong curl onProgress examples) +$(LI $(BUGZILLA 19283): [std.mathspecial] documentation for normal distribution doesn't list parameters) +$(LI $(BUGZILLA 19626): RedBlackTree of an enum fails in unittest mode) +$(LI $(BUGZILLA 19733): expi documentation links broken) +$(LI $(BUGZILLA 20160): ThreadInfo.cleanup$(LPAREN)$(RPAREN) clears local thread's registered names instead of "this"'s) +$(LI $(BUGZILLA 20260): CustomFloat with 0 precision/exponentWidth) +$(LI $(BUGZILLA 20261): CustomFloat.epsilon yields infinity) +$(LI $(BUGZILLA 20263): Wrong value for CustomFloat.min_exp) +$(LI $(BUGZILLA 20281): CustomFloat is limited to 64 bit) +$(LI $(BUGZILLA 20282): CustomFloat.dig fails at some values.) +$(LI $(BUGZILLA 20283): CustomFloat.max_exp not working in some cases) +$(LI $(BUGZILLA 20284): CustomFloat.max_10_exp does not work for types with too many digits in exponent) +$(LI $(BUGZILLA 20286): CustomFloat.min_normal fails, when not allowDenorm) +$(LI $(BUGZILLA 20313): Inconsistent behavior of wouldHaveBlocked on Windows) +$(LI $(BUGZILLA 20314): passing const variables to `only` forces const range element type) +$(LI $(BUGZILLA 20357): format should obey space flag when printing nan or inf) +$(LI $(BUGZILLA 20396): format!"%a" leeds to wrong result for denormalized float) +$(LI $(BUGZILLA 20398): Wrong number of totalEntries in std.zip) +$(LI $(BUGZILLA 20408): style checker should not check backup files) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 20198): Make std.math.nextUp and nextDown and nextafter work in CTFE for float and double) +$(LI $(BUGZILLA 20288): std.format double with NaN fails with range violation on comma) +$(LI $(BUGZILLA 20425): Proxy opCmp fails to compile with types that overloaded opCmp) +$(LI $(BUGZILLA 20439): memoize fails with types that have a void opAssign) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 20299): checkaction=context not working with temporary destructors) +$(LI $(BUGZILLA 20303): Memory leak in core.thread) +$(LI $(BUGZILLA 20315): checkaction=context fails for const$(LPAREN)void[]$(RPAREN) argument) +$(LI $(BUGZILLA 20322): checkaction=context fails for wstring/dstring arguments) +$(LI $(BUGZILLA 20323): checkaction=context fails for non-copyable arguments) +$(LI $(BUGZILLA 20346): std.uuid does not compile with checkaction=context) +$(LI $(BUGZILLA 20364): [REG2.069] changing length for typeof$(LPAREN)null$(RPAREN)[] array seg faults in _d_arraysetlengthiT$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 20440): Associative arrays with values whose opAssign doesn't return a ref don't support require function) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 17563): gc_inFinalizer should be public) +) +) +$(D_CONTRIBUTORS_HEADER 48) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR 0l-l0) + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR Alexandru Militaru) + $(D_CONTRIBUTOR Ali Akhtarzada) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR Bernhard Seckinger) + $(D_CONTRIBUTOR berni44) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Cristian Creteanu) + $(D_CONTRIBUTOR Damian Ziemba) + $(D_CONTRIBUTOR Diederik de Groot) + $(D_CONTRIBUTOR drug007) + $(D_CONTRIBUTOR Eduard Staniloiu) + $(D_CONTRIBUTOR Ernesto Castellotti) + $(D_CONTRIBUTOR Fangrui Song) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR Florian Brandt) + $(D_CONTRIBUTOR GoaLitiuM) + $(D_CONTRIBUTOR GrimMaple) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Joan Piles) + $(D_CONTRIBUTOR Jonathan Marler) + $(D_CONTRIBUTOR Jonathan Samson) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Rasmus Thomsen) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Robert burner Schadek) + $(D_CONTRIBUTOR Robert Schadek) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Stian Gulpen) + $(D_CONTRIBUTOR StianGulpen) + $(D_CONTRIBUTOR tastyminerals) + $(D_CONTRIBUTOR Victor Porton) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR سليمان السهمي (Suleyman Sahmi)) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.090.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.090.1.dd b/changelog/2.090.1.dd new file mode 100644 index 0000000000..6f9fc99864 --- /dev/null +++ b/changelog/2.090.1.dd @@ -0,0 +1,117 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 06, 2020, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 1 major change and 16 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 13 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 d1-operator-deprecation,D1-style operator now have a lower priority than D2-style)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 d1-operator-deprecation,D1-style operator now have a lower priority than D2-style) +$(CHANGELOG_SOURCE_FILE dmd, changelog/d1-operator-deprecation.dd) +$(P +D1 operator overloads have been deprecated in $(LINK2 https://dlang.org/changelog/2.088.0.html, v2.088.0). +They historically had priority over D2 operator overload, and that priority was kept as is even after deprecating them. +) + +$(P +One main difference between D1 and D2 operator overload is that D1's are `virtual` by default, +while the D2 operator overloading scheme relies on template, and so cannot be virtual. +Code relying on virtuality of operator can be trivially adapted by providing a D2-style operator +overload that forwards to a virtual method. +) + +$(P +However, as D1 operator overloads take priority, the deprecation message will be issued even if a D2 +operator overload is present. +This means that code relying on virtual operators would need not only to introduce the aforementioned +D2-style overload, but also to rename their method not to match the reserved D1 names. +This in turns forces libraries to introduce a breaking change in order to silence the deprecation. +) + +$(P +Starting from this release, D2-style operator overloads take priority over D1-style, +making it trivial to forward the former to the later. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 20391): [REG 2.089] DMD compile times increased by 40% because ENABLE_RELEASE=0 in build) +$(LI $(BUGZILLA 20488): AA.length in multiple modules causes opDispatch failure) +$(LI $(BUGZILLA 20518): simple import ICE regression) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 19542): Forward reference segfault with string namespace C++ syntax) +$(LI $(BUGZILLA 20530): is$(LPAREN)<...> == module/package$(RPAREN) does not work with string mixins) +$(LI $(BUGZILLA 20549): Initialization with a tuple of a module symbol referencing itself could crash dmd) +$(LI $(BUGZILLA 20559): Reference type + alias this + AA + AA.clear causes SEGV) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 19738): std.range.choose assignment breaks @safe-ty) +$(LI $(BUGZILLA 20511): Can't format JSONValue to OutputRange due to @safe) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 17441): std.traits.moduleName gives wrong answer for modules imported under a different name in a mixin) +$(LI $(BUGZILLA 20495): std.range.choose range is not safe when calling save) +$(LI $(BUGZILLA 20527): std.json CTFE cannot read integer) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 19902): hasElaborateCopyConstructor doesn't know about copy constructors) +$(LI $(BUGZILLA 20447): [REG 2.089] importing core.thread exposes unistd, hiding object.dup) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 20497): thread with limited stackspace crashes depending on size of TLS) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 20500): running examples on the home page only displays '1 unittests passed') +) +) +$(D_CONTRIBUTORS_HEADER 13) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Bernhard Seckinger) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Don Clugston) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.090.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.091.0.dd b/changelog/2.091.0.dd new file mode 100644 index 0000000000..075a9553a0 --- /dev/null +++ b/changelog/2.091.0.dd @@ -0,0 +1,546 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 08, 2020, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 18 major changes and 66 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 55 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 deallocator,Class deallocator have been removed from the language)) +$(LI $(RELATIVE_LINK2 gnu-error-style,Can now report line numbers in GNU error style)) +$(LI $(RELATIVE_LINK2 headers,Added experimental `C++` header generation from `extern(C|C++)` declarations)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 add_missing_pthread_attr_destroy,Added missing `pthread_attr_destroy` in some place.)) +$(LI $(RELATIVE_LINK2 expanded_windows_security_bindings,Expanded bindings in core.sys.windows.security)) +$(LI $(RELATIVE_LINK2 std_unique_ptr,Added `core.stdcpp.memory.unique_ptr`)) +$(LI $(RELATIVE_LINK2 tfd_timer_cancel_on_set,Added `TFD_TIMER_CANCEL_ON_SET`.)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 bigint-safe,`std.bigint` is now `@safe`)) +$(LI $(RELATIVE_LINK2 isClose,Replaced `approxEqual` by `isClose` in std.math.)) +$(LI $(RELATIVE_LINK2 mangle_removed,Removed deprecated `std.format.Mangle`.)) +$(LI $(RELATIVE_LINK2 remove-stdio-structs,Removed deprecated structs `ByLine`, `ByChunk`, `ByRecord` from `std.stdio`.)) +$(LI $(RELATIVE_LINK2 remove-string-functions,Removed deprecated functions from `std.string`)) +$(LI $(RELATIVE_LINK2 schwartzSort,`std.algorithm.sorting.schwartzSort` supports binary transform functions too)) +$(LI $(RELATIVE_LINK2 std-functional-curry,Added curry to std.functional)) + +) + +$(BUGSTITLE_TEXT_HEADER Installer changes, + +$(LI $(RELATIVE_LINK2 install-sh-windows,The install script now runs on Windows)) +$(LI $(RELATIVE_LINK2 windows,The Windows installation has received a couple of updates)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 env_variable_source_files_added,Environment variable SOURCE_FILES added)) +$(LI $(RELATIVE_LINK2 zsh-completion,DUB now has zsh completion)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 deallocator,Class deallocator have been removed from the language) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deallocator.dd) +$(P +Class deallocator have been deprecated in v2.080.0 +(see $(LINK2 https://dlang.org/changelog/2.080.0.html#deprecate_class_allocators, the changelog entry)), +and turned into an error in v2.087.0. +They have now been completely removed from the language, and the parser won't recognize them anymore. +) +) + +$(LI $(LNAME2 gnu-error-style,Can now report line numbers in GNU error style) +$(CHANGELOG_SOURCE_FILE dmd, changelog/gnu-error-style.dd) +$(P +DMD now supports reporting errors and warnings in GNU error style, that is, `filename:line[:column]: message`. +This may ease compatibility with existing IDEs. +) + +$(P +Enable this style by calling DMD with `-verror-style=gnu`. +) +) + +$(LI $(LNAME2 headers,Added experimental `C++` header generation from `extern(C|C++)` declarations) +$(CHANGELOG_SOURCE_FILE dmd, changelog/headers.dd) +$(P +DMD can now write C++ header files which contain bindings for declarations +in existing D files that were marked as `extern(C)` or `extern(C++)`. +) + +$(P +This feature is available via the following command line switches: +- `-HC`: Write the generated headers to standard output +- `-HCf=`: Write the generated headers to file +- `-HCd=`: Write the generated headers to file (not implemented yet) +) + +$(P +Consider the following example: +) + +``` +module a; + +extern(C) int foo(int a) { ... } +extern(C++) void bar() { ... } +void ignored() { ... } +``` +``` +module b; + +extern (C++) struct S +{ + string name; + this (string name) { ... } + bool bar() { ... } +} +``` +``` +module c; + +import a, b; + +extern (C++) class C +{ + S[] s; + this () {} + bool bar() { ...} +} + +``` + +$(P +Compiling these modules with `dmd -c -o- -HC a.d b.d c.d` will generate the following header: +) + +``` +#pragma once + +// Automatically generated by dmd -HC + +#include +#include +#include +#include + +#define _d_void void +#define _d_bool bool +#define _d_byte signed char +#define _d_ubyte unsigned char +#define _d_short short +#define _d_ushort unsigned short +#define _d_int int +#define _d_uint unsigned +#define _d_long long long +#define _d_ulong unsigned long long +#define _d_float float +#define _d_double double +#define _d_real long double +#define _d_char char +#define _d_wchar wchar_t +#define _d_dchar unsigned +typedef _d_long d_int64; +#define _d_null NULL + +// Parsing module a +// Parsing module b +// Parsing module c +struct S; +extern "C" _d_int foo(_d_int a); + +extern _d_void bar(); + +// ignoring function a.ignored because of linkage +struct S +{ + DArray< _d_char > name; + S(DArray< _d_char > name); + _d_bool bar(); + S() : name() {} +}; + +class C +{ +public: + DArray< S > s; + C(); + virtual _d_bool bar(); +}; +``` + +$(P +Refer to the $(LINK2 $(ROOT_DIR)/spec/cpp_interface.html, documentation) for further information regarding C++ interoperation. +) + +$(P +Note that this feature is considered experimental and might not work correctly sometimes. +Please open an issue in the $(LINK2 https://issues.dlang.org, bug tracker) if you encounter a bug while using this feature. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 add_missing_pthread_attr_destroy,Added missing `pthread_attr_destroy` in some place.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/add_missing_pthread_attr_destroy.dd) +$(P +Added missing `pthread_attr_destroy`, this prevents memory leak in some OSes such as freebsd or solaris. +) +) + +$(LI $(LNAME2 expanded_windows_security_bindings,Expanded bindings in core.sys.windows.security) +$(CHANGELOG_SOURCE_FILE druntime, changelog/expanded_windows_security_bindings.dd) +$(P +Many enum members were missing, the list is now reasonably up-to-date. +) +) + +$(LI $(LNAME2 std_unique_ptr,Added `core.stdcpp.memory.unique_ptr`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/std_unique_ptr.dd) +$(P +Added `core.stdcpp.memory.unique_ptr`, which corresponds to C++ `std::unique_ptr`. +) +) + +$(LI $(LNAME2 tfd_timer_cancel_on_set,Added `TFD_TIMER_CANCEL_ON_SET`.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/tfd_timer_cancel_on_set.dd) +$(P +Added `TFD_TIMER_CANCEL_ON_SET` option, which marks a timer as cancelable if the realtime clock is used. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 bigint-safe,`std.bigint` is now `@safe`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/bigint-safe.dd) +$(P +Many `BigInt` operations used to be `@system` because of assembly routines and casts from mutable to immutable data. +These parts are now marked `@trusted`, so that `BigInt` can now be used in `@safe` code. +) +) + +$(LI $(LNAME2 isClose,Replaced `approxEqual` by `isClose` in std.math.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/isClose.dd) +$(P +The template `approxEqual` for comparing floating point numbers has +been replaced by the template `isClose`, which has better default +values and is symmetric in its arguments. +) + +$(P +To (almost) keep the current behaviour of `approxEqual(a, b)` use +`isClose(a, b, 1e-2, 1e-2)`, but we recommend to adjust the code to +make it work with `isClose(a, b)`. +) + +$(P +In one of the next releases `approxEqual` will be deprecated and +eventually removed. +) +) + +$(LI $(LNAME2 mangle_removed,Removed deprecated `std.format.Mangle`.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/mangle_removed.dd) +$(P +The deprecated enum `Mangle` containing mangled names of basic types has been +removed. Use `std.demangle.demangle` instead to parse mangled names. +) +) + +$(LI $(LNAME2 remove-stdio-structs,Removed deprecated structs `ByLine`, `ByChunk`, `ByRecord` from `std.stdio`.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/remove-stdio-structs.dd) +$(P +The deprecated structs `ByLine`, `ByChunk`, `ByRecord` have been removed from +`std.stdio`. Use the functions `byLine`, `byChunk`, `byRecord` instead. +) +) + +$(LI $(LNAME2 remove-string-functions,Removed deprecated functions from `std.string`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/remove-string-functions.dd) +$(P +The deprecated functions `inPattern`, `countchars`, `removechars`, `squeeze` +and `munch` in `std.string` have been removed. Any code that still needs +them can use [UndeaD](https://github.com/dlang/undeaD) instead. +) +) + +$(LI $(LNAME2 schwartzSort,`std.algorithm.sorting.schwartzSort` supports binary transform functions too) +$(CHANGELOG_SOURCE_FILE phobos, changelog/schwartzSort.dd) +$(P +The `transform` template parameter of $(REF schwartzSort, std, algorithm, sorting) +isn't restricted to unary functions taking an element anymore, but can +also be a binary function taking an element and its index in the +original range. +) + +$(P +The original index can therefore be used when computing the transformed +value to sort by. +) +) + +$(LI $(LNAME2 std-functional-curry,Added curry to std.functional) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-functional-curry.dd) +$(P +Converts a function of multiple parameters to a function of 1 parameter that +returns a function of 1 parameter... until it runs out of parameters and +evaluates the function. Essentially: f(x, y, z) == curry(f)(x)(y)(z) +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Installer changes, + +$(LI $(LNAME2 install-sh-windows,The install script now runs on Windows) +$(CHANGELOG_SOURCE_FILE installer, changelog/install-sh-windows.dd) +$(P +The D installation script (install.sh, available at +$(LINK2 https://dlang.org/install.sh, dlang.org/install.sh)) +now supports POSIX-like environments on Windows. +This allows installing and using Windows versions of DMD, LDC, and Dub +from e.g. CygWin or MSys2, thus providing a unified way of installing +D compilers across supported platforms. +) +) + +$(LI $(LNAME2 windows,The Windows installation has received a couple of updates) +$(CHANGELOG_SOURCE_FILE installer, changelog/windows.dd) +$(P +- the released dmd.exe is now built with LDC for a reduction of compilation + times of 30-40%. +- 64-bit builds of dmd.exe, dub.exe and lld-link.exe have been added to the bin64 folder +- The bundled Windows libraries and definitions have been changed from MinGW 5.0.2 + to MinGW 7.0.0 (with additional wide string `main` entrypoints). +- The bundled LLD linker on Windows has been upgraded to 9.0.0 (including a + patch that allows exceptions to work on Win32). +- The VC runtime linked with the MinGW import libraries has been upgraded to + msvcr120.dll (the last version that allows simple copying and no dependency + on the universal C runtime). The redistributable DLLs have been added to the + respective bin folder for immediate use without running additional installers. +- The curl libraries/DLLs have been updated to 7.68. +- ancient windbg.exe has been removed from the installation. +- The installer now detects an installation of VS 2019. If no VC installation is + found the proposed download is not VS 2017 anymore, but VS 2019. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 env_variable_source_files_added,Environment variable SOURCE_FILES added) +$(CHANGELOG_SOURCE_FILE dub, changelog/env_variable_source_files_added.dd) +$(P +New environment variable `$SOURCE_FILES` added containing +source files from build settings. +) +) + +$(LI $(LNAME2 zsh-completion,DUB now has zsh completion) +$(CHANGELOG_SOURCE_FILE dub, changelog/zsh-completion.dd) +$(P +A zsh completion script is now present in `scripts/zsh-completion/_zsh`. +It can be installed under the user's prefered `fpath` and provides completion +for options for the most common `dub` commands, as well as list of packages +(based on local packages), e.g. for `dub add`. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 10100): Identifiers with double underscores and allMembers) +$(LI $(BUGZILLA 15812): static struct inside extern$(LPAREN)C++$(RPAREN) class cannot be used as key to associative array) +$(LI $(BUGZILLA 16709): [Reg 2.068] Error: common.to at common.d conflicts with common.to at common.d) +$(LI $(BUGZILLA 17098): Takes hours to -O compile then fails with Internal error: backend/cgreg.c 405) +$(LI $(BUGZILLA 17145): [REG2.066.0] Tuple expansion error in local enum declaration) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 9937): CTFE floats don't overflow correctly) +$(LI $(BUGZILLA 11847): sub-pkg not available as qualified name) +$(LI $(BUGZILLA 17257): Wrong recursive template destructor reflection) +$(LI $(BUGZILLA 18147): Debug information limited in size) +$(LI $(BUGZILLA 19479): Garbage .init in string mixins in static foreach in mixin templates) +$(LI $(BUGZILLA 19504): pragma$(LPAREN)mangle$(RPAREN) ignored for C++ destructors) +$(LI $(BUGZILLA 19515): POSIX,C++: Template argument pack wrongly mangled) +$(LI $(BUGZILLA 20362): dmd fails to infer scope parameter for delegate) +$(LI $(BUGZILLA 20375): std.typecons.RefCounted does not work with checkaction-context) +$(LI $(BUGZILLA 20421): Exceptions don't work when linking through lld-link) +$(LI $(BUGZILLA 20474): Deprecation warnings inside deprecated function template) +$(LI $(BUGZILLA 20507): Debug statements affect inference of templated functions attributes) +$(LI $(BUGZILLA 20514): obj-c info incorrectly placed in __objc_const section) +$(LI $(BUGZILLA 20530): is$(LPAREN)<...> == module/package$(RPAREN) does not work with string mixins) +$(LI $(BUGZILLA 20537): traits isPackage/isModule and is$(LPAREN)package/module$(RPAREN) fail on single level package.d import) +$(LI $(BUGZILLA 20538): malformed enum definition compiles) +$(LI $(BUGZILLA 20545): Segfault/Assertion failure when parsing invalid AA literal) +$(LI $(BUGZILLA 20547): Wrong error message when trying to "new" an associative array) +$(LI $(BUGZILLA 20551): In @safe code and using delegates, it's possible to escape references to function frame) +$(LI $(BUGZILLA 20592): [GCC ASM] [ICE] dmd/iasmgcc.d$(LPAREN)332$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 20613): String switch in -betterC fails for 7+ labels) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 20569): [DIP1000] allow taking the address of a `scope` struct field if it has no indirections) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 7006): std.math.pow $(LPAREN)integral, integral$(RPAREN) crashes on negative exponents) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 5232): [patch] std.conv.to & std.conv.roundTo report invalid overflows for very large numbers) +$(LI $(BUGZILLA 5628): std.math unittest disabled - roundoff error in pow$(LPAREN)$(RPAREN) on SSE2) +$(LI $(BUGZILLA 7446): [TDPL] Trivial asynchronous file copy example crashes with OwnerTerminated) +$(LI $(BUGZILLA 8388): std.traits.MemberFunctionsTuple doesn't work with constructors or destructors) +$(LI $(BUGZILLA 12461): Typedef and opOpAssign) +$(LI $(BUGZILLA 15891): Compiler error when std.algorithm.cache after 2 layers of std.algorithm.map) +$(LI $(BUGZILLA 17427): std.concurrency internal errors on uninitialised mailbox) +$(LI $(BUGZILLA 20232): WhiteHole is unusable with @safe interface functions) +$(LI $(BUGZILLA 20259): [Function Socket.bind] Doesn't inform what Exception it throws) +$(LI $(BUGZILLA 20493): Incorrect result of BigInt * BigInt) +$(LI $(BUGZILLA 20521): Checking for and getting empty variables on Wine / XP fails) +$(LI $(BUGZILLA 20540): $(LPAREN)White|Black$(RPAREN)Hole does not work with return|scope functions) +$(LI $(BUGZILLA 20542): std.math.nextafter$(LPAREN)NaN, y$(RPAREN) and nextafter$(LPAREN)x, NaN$(RPAREN) should return NaN) +$(LI $(BUGZILLA 20544): socket.remoteAddress throws out of memory error with unix domain socket peer) +$(LI $(BUGZILLA 20585): std.stdio.File open$(LPAREN)$(RPAREN) failure leaves File in invalid state) +$(LI $(BUGZILLA 20639): Some BitArray methods should be const/pure/nothrow/...) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 20146): Allow casting from std.bigint.BigInt to built-in floating point types) +$(LI $(BUGZILLA 20480): make std.getopt ready for DIP 1000) +$(LI $(BUGZILLA 20548): Use bit vector instead of bool[] in RandomCover when choices cannot be packed in a single word) +$(LI $(BUGZILLA 20566): std.sformat should avoid allocating memory when printing floating point values) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 19322): A lot of memory is consumed and not freed to the system when Exception is formatted with stacktrace in debug) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 15322): version$(LPAREN)Unicode$(RPAREN) should affect only default aliases) +$(LI $(BUGZILLA 16658): Win32API: default IE ver. set to 4.0 is too old) +$(LI $(BUGZILLA 19489): Null function call results in no stack trace) +$(LI $(BUGZILLA 19909): core.stdc.errno missing POSIX error code on Windows) +$(LI $(BUGZILLA 20459): Runtime arg parsing should stop at '--') +$(LI $(BUGZILLA 20468): emplace doesn't forward constructor arguments' $(LPAREN)l/r$(RPAREN)valueness) +$(LI $(BUGZILLA 20476): chainTogether leaks exception with -dip1008) +$(LI $(BUGZILLA 20512): Return type of memchr should be inout$(LPAREN)void$(RPAREN)* rather than void*) +$(LI $(BUGZILLA 20513): Return type of wmemchr should be inout$(LPAREN)wchar_t$(RPAREN)* rather than wchar_t*) +$(LI $(BUGZILLA 20591): ldc doesn't print files' directories when printing stack trace) +$(LI $(BUGZILLA 20629): atomicStore does not compile for struct using -m64) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 19218): object.destroy should check for classes for static arrays) +$(LI $(BUGZILLA 20550): Use fixed seeds for treaps in GC) +$(LI $(BUGZILLA 20567): GC should not start threads for parallel marking in simple programs) +$(LI $(BUGZILLA 20577): Add missing symbols related to Windows UAC) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 20500): running examples on the home page only displays '1 unittests passed') +) +$(BUGSTITLE_BUGZILLA Installer enhancements, + +$(LI $(BUGZILLA 20489): Installer deleting files after install) +) +) +$(D_CONTRIBUTORS_HEADER 55) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Ahmet Sait) + $(D_CONTRIBUTOR Alexandru Militaru) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Asakusa Yakumo) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR Bernhard Seckinger) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Daniel Kozák) + $(D_CONTRIBUTOR Dennis Katsonis) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR Dragos Carp) + $(D_CONTRIBUTOR drug007) + $(D_CONTRIBUTOR dukc) + $(D_CONTRIBUTOR Etienne Cimon) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR Jiyuan Zhang) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR Jonathan Marler) + $(D_CONTRIBUTOR Julian Fondren) + $(D_CONTRIBUTOR Kazuya Takahashi) + $(D_CONTRIBUTOR Lance Bachmeier) + $(D_CONTRIBUTOR Manish Khurana) + $(D_CONTRIBUTOR Manu Evans) + $(D_CONTRIBUTOR Marco de Wild) + $(D_CONTRIBUTOR Mark) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Moonchild) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Rasmus Thomsen) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Robert Schadek) + $(D_CONTRIBUTOR Sebastiaan Koppe) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR skoppe) + $(D_CONTRIBUTOR Stefan Koch) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR Yazan Dabain) + $(D_CONTRIBUTOR سليمان السهمي (Suleyman Sahmi)) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.091.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.091.1.dd b/changelog/2.091.1.dd new file mode 100644 index 0000000000..bcec5d7255 --- /dev/null +++ b/changelog/2.091.1.dd @@ -0,0 +1,59 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 17, 2020, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 9 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 10 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 20130): ICE when casting from string to other array type due to __ArrayCast not being written) +$(LI $(BUGZILLA 20730): [REG 2.091] __traits$(LPAREN)compiles$(RPAREN) fails if any ungagged errors occurred in compilation) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 18651): ice: assert in glue.d:777 when building these three trivial files) +$(LI $(BUGZILLA 20610): const in a .tupleof loop is ignored) +$(LI $(BUGZILLA 20656): cannot compile live function without -preview=dip1021) +$(LI $(BUGZILLA 20692): Nested alias declarations and getMember trait can crash dmd) +$(LI $(BUGZILLA 20700): Forward references leads to `extern$(LPAREN)C++, class|struct$(RPAREN)` being ignored) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 20649): Trait isZeroInit gives false in certain scenarios) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 20731): checkaction=context fails for structs with 'alias this') +) +) +$(D_CONTRIBUTORS_HEADER 10) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Ernesto Castellotti) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Razvan Nitu) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.091.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.092.0.dd b/changelog/2.092.0.dd new file mode 100644 index 0000000000..bded1c961e --- /dev/null +++ b/changelog/2.092.0.dd @@ -0,0 +1,986 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION May 10, 2020, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 15 major changes and 44 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 47 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 bug10478-cli-switches,CLI switches `-revert=import` and `-transition=checkimports` have been removed)) +$(LI $(RELATIVE_LINK2 cpp_abi_tags,Added support for mangling C++'s GNU ABI tags)) +$(LI $(RELATIVE_LINK2 dep-non-externd-modulectordtors,Module constructors and destructors which are not extern(D) are deprecated)) +$(LI $(RELATIVE_LINK2 dip25,DIP25 violations will now issue deprecations by default)) +$(LI $(RELATIVE_LINK2 ob,Prototype Ownership/Borrowing System for Pointers)) +$(LI $(RELATIVE_LINK2 preview-in,Added `-preview=in` to make the `in` storage class mean `scope const`.)) +$(LI $(RELATIVE_LINK2 printfParams2,Validate printf and scanf (variants too) arguments against format specifiers)) +$(LI $(RELATIVE_LINK2 reproducible-builds,Environment variable `SOURCE_DATE_EPOCH` is now supported)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 isbaseof,Added TypeInfo_Class/TypeInfo_Interface.isBaseOf that works like C#/Java isAssignableFrom.)) +$(LI $(RELATIVE_LINK2 page_size,Add `core.memory.pageSize` and `minimumPageSize`.)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 date-isoweek,Add `Date.isoWeekYear` and `Date.fromISOWeek` in `std.datetime.date`)) +$(LI $(RELATIVE_LINK2 deprecate-xml,Deprecated module `std.xml`)) +$(LI $(RELATIVE_LINK2 digest,The deprecated aliases in std.digest.digest were removed)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 ignoreHiddenDirectories,Hidden directories are now ignored.)) +$(LI $(RELATIVE_LINK2 lintReportFile,Dub lint now supports --report-file argument.)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 bug10478-cli-switches,CLI switches `-revert=import` and `-transition=checkimports` have been removed) +$(CHANGELOG_SOURCE_FILE dmd, changelog/bug10478-cli-switches.dd) +$(P +Those switched were already not doing anything and had been deprecated for a while. +The compiler will no longer recognized them. +) +) + +$(LI $(LNAME2 cpp_abi_tags,Added support for mangling C++'s GNU ABI tags) +$(CHANGELOG_SOURCE_FILE dmd, changelog/cpp_abi_tags.dd) +$(P +GNU ABI tags are a feature that was added with C++11 in $(LINK2 https://gcc.gnu.org/gcc-5/changes.html#libstdcxx, GCC 5.1). +In order for D to fully support the $(LINK2 http://www.cplusplus.com/reference/, standard C++ library), +DMD now recognize the special UDA `gnuAbiTag`, declared in `core.attribute` and publicly aliased in `object` +(so one need not import anything to use it). +The ABI tags are a low level feature that most user will not need to interact with, +but can be used to bind to C++ libraries that need it. +In particular, it is required to bind $(LINK2 http://www.cplusplus.com/reference/string/, `std::string`) +when targeting C++11 and higher (DMD switch `-extern-std={c++11,c++14,c++17}`). +) + +$(P +It can be used in the following way: +) +--- +extern(C++): +@gnuAbiTag("tagOnStruct") +struct MyStruct {} +@gnuAbiTag("Multiple", "Tags", "On", "Function") +MyStruct func(); +--- + +$(P +Only one `gnuAbiTag` can be present on a symbol at a time. +The order of the array entries does not matter (they are sorted on output). +The UDA will only have an effect if `-extern-std=c++11` or higher is passed +to the compiler. The default (`-extern-std=c++98`) will ignore the UDA. +This UDA can only be applied to `extern(C++)` symbols and cannot be applied to namespaces. +) +) + +$(LI $(LNAME2 dep-non-externd-modulectordtors,Module constructors and destructors which are not extern(D) are deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dep-non-externd-modulectordtors.dd) +$(P +Module constructors and destructors (shared or not) could be marked with +a different linkage than `extern(D)`, which would affect their mangling. +Since such a mangling is simple and predictable, there was a very small +chance of conflict if two same kind of constructor/destructors +were declared in similar condition, for example if the third +module constructor in module `a` was on line 479 and the third +module constructor in module `b` was also on line 479, +they would have the same mangling. +) + +$(P +While it's unlikely that such a bug is triggered in practice, +affected symbols will now trigger a deprecation message. +) +) + +$(LI $(LNAME2 dip25,DIP25 violations will now issue deprecations by default) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dip25.dd) +$(P +DIP25 has been available since $(LINK2 https://dlang.org/changelog/2.067.0.html#sealed-references, v2.067.0), +first as its own switch, and more recently under the `-preview=dip25` switch. +The feature is now fully functional and has been built on, for example by DIP1000. +) + +$(P +Starting from this release, code that would trigger errors when `-preview=dip25` is passed to the compiler +will also trigger a deprecation message without `-preview=dip25`. +The behavior of the switch is unchanged (errors will still be issued). +) + +$(P +DIP25 aims to make it impossible for `@safe` code to refer to destructed object. +In practice, functions and methods returning a `ref` to their parameter might +be required to qualify the method or the parameter as `return`, as hinted by the compiler. +) +--- +struct Foo +{ + int x; + // returning `this.x` escapes a reference to parameter `this`, perhaps annotate with `return` + ref int method() /* return */ { return this.x; } +} +// returning `v` escapes a reference to parameter `v`, perhaps annotate with `return` +ref int identity(/* return */ ref int v) { return v; } +--- +$(P +In both cases, uncommenting the `return` annotation will appease the compiler. +The complete description of DIP25 can be found $(LINK2 https://wiki.dlang.org/DIP25, here). +) +) + +$(LI $(LNAME2 ob,Prototype Ownership/Borrowing System for Pointers) +$(CHANGELOG_SOURCE_FILE dmd, changelog/ob.dd) +$(P +An Ownership/Borrowing (aka OB) system for pointers can guarantee that +dereferenced pointers are pointing to a valid memory object. +) + + +$(P +$(H3 Scope of Prototype OB System) +) + +$(P +This is a prototype OB system adapted to D. It is initially for pointers +only, not dynamic arrays, class references, refs, or pointer fields +of aggregates. Adding support for such adds complexity, +but does not change the nature of it, hence it is deferred to later. +RAII objects can safely manage their own memory, so are not covered +by OB. Whether a pointer is allocates memory using the GC or some other +storage allocator is immaterial to OB, they are not distinguished and are +handled identically. +) + +$(P +The system is only active in functions annotated with the `@live` attribute. +It is applied after semantic processing is done as purely a check +for violations of the OB rules. No new syntax is added. No change is made +to the code generated. +If `@live` functions +call non-`@live` functions, those called functions are expected to present +an `@live` compatible interface, although it is not checked. +if non-`@live` functions call `@live` functions, arguments passed are +expected to follow `@live` conventions. +) + +$(P +The OB system will detect as errors: +) + +$(P +$(UL +$(LI dereferencing pointers that are in an invalid state) +$(LI more than one active pointer to a mutable memory object) +) +) + +$(P +It will not detect attempts to dereference `null` pointers or possibly +`null` pointers. This is unworkable because there is no current method +of annotating a type as a non-`null` pointer. +) + + +$(P +$(H3 Core OB Principle) +) + +$(P +The OB design follows from the following principle: +) + +$(P +For each memory object, there can exist either exactly one mutating pointer +to it, or multiple non-mutating (read-only) pointers. +) + + +$(P +$(H3 Design) +) + +$(P +The single mutating pointer is called the "owner" of the memory object. +It transitively owns the memory object and all memory objects accessible +from it (i.e. the memory object graph). Since it is the sole pointer to +that memory object, it can safely +manage the memory (change its shape, allocate, free and resize) without +pulling the rug out from under any other pointers (mutating or not) +that may point to it. +) + +$(P +If there are multiple read-only pointers to the memory object graph, +they can safely read from it without being concerned about the memory +object graph being changed underfoot. +) + +$(P +The rest of the design is concerned with how pointers become owners, +read only pointers, and invalid pointers, and how the Core OB Principle +is maintained at all times. +) + + +$(P +$(H4 Tracked Pointers) +) + +$(P +The only pointers that are tracked are those declared in the `@live` function +as `this`, function parameters or local variables. Variables from other +functions are not tracked, even `@live` ones, as the analysis of interactions +with other functions depends +entirely on that function signature, not its internals. +Parameters that are `const` are not tracked. +) + + +$(P +$(H4 Pointer States) +) + +$(P +Each pointer is in one of the following states: +) + +$(P +$(DL +$(DT Undefined) +) + +$(P +$(DD The pointer is in an invalid state. Dereferencing such a pointer is +an error.) +) + +$(P +$(DT Owner) +) + +$(P +$(DD The owner is the sole pointer to a memory object graph. +An Owner pointer normally does not have a `scope` attribute. +If a pointer with the `scope` attribute is initialized +with an expression not derived from a tracked pointer, it is an Owner. +) + +$(P +If an Owner pointer is assigned to another Owner pointer, the +former enters the Undefined state. +) +) + +$(P +$(DT Borrowed) +) + +$(P +$(DD A Borrowed pointer is one that temporarily becomes the sole pointer +to a memory object graph. It enters that state via assignment +from an owner pointer, and the owner then enters the Lent state +until after the last use of the borrowed pointer. +) + +$(P +A Borrowed pointer must have the `scope` attribute and must +be a pointer to mutable. +) +) + +$(P +$(DT Readonly) +) + +$(P +$(DD A Readonly pointer acquires its value from an Owner. +While the Readonly pointer is live, only Readonly pointers can +be acquired from that Owner. +A Readonly pointer must have the `scope` attribute and also +must not be a pointer to mutable. +) +) +) + +$(P +$(H4 Lifetimes) +) + +$(P +The lifetime of a Borrowed or Readonly pointer value starts when it is +first read (not when it is initialized or assigned a value), and ends at +the last read of that value. +) + +$(P +This is also known as *Non-Lexical Lifetimes*. +) + + +$(P +$(H4 Pointer State Transitions) +) + +$(P +A pointer changes its state when one of these operations is done to it: +) + +$(P +$(UL +$(LI storage is allocated for it (such as a local variable on the stack), +which places the pointer in the Undefined state) +) + +$(P +$(LI initialization (treated as assignment)) +) + +$(P +$(LI assignment - the source and target pointers change state based on what +states they are in and their types and storage classes) +) + +$(P +$(LI passed to an `out` function parameter (changes state after the function returns), +treated the same as initialization) +) + +$(P +$(LI passed by `ref` to a function parameter, treated as an assignment to a Borrow or a Readonly +depending on the storage class and type of the parameter) +) + +$(P +$(LI returned from a function) +) + +$(P +$(LI it is passed by value to a function parameter, which is +treated as an assignment to that parameter.) +) + +$(P +$(LI it is implicitly passed by ref as a closure variable to a nested function) +) + +$(P +$(LI the address of the pointer is taken, which is treated as assignment to whoever +receives the address) +) + +$(P +$(LI the address of any part of the memory object graph is taken, which is +treated as assignment to whoever receives that address) +) + +$(P +$(LI a pointer value is read from any part of the memory object graph, +which is treated as assignment to whoever receives that pointer) +) + +$(P +$(LI merging of control flow reconciles the state of each variable based on the +states they have from each edge) +) +) + +$(P +$(H3 Limitations) +) + +$(P +Being a prototype, there are a lot of aspects not dealt with yet, and +won't be until the prototype shows that it is a good design. +) + +$(P +$(H4 Bugs) +) + +$(P +Expect lots of bugs. Please report them to bugzilla and tag with the "ob" +keyword. It's not necessary to report the other limitations that are enumerated here. +) + +$(P +$(H4 Class References and Associative Array References are not Tracked) +) + +$(P +They are presumed to be managed by the garbage collector. +) + +$(P +$(H4 Borrowing and Reading from Non-Owner Pointers) +) + +$(P +Owners are tracked for leaks, not other pointers. +Borrowers are considered Owners if they are initialized from other than +a pointer. +) + +--- +@live void uhoh() +{ + scope p = malloc(); // p is considered an Owner + scope const pc = malloc(); // pc is not considered an Owner +} // dangling pointer pc is not detected on exit + +--- +$(P +It doesn't seem to make much sense to have such pointers as +`scope`, perhaps this can be resolved by making such an error. +) + +$(P +$(H4 Pointers Read/Written by Nested Functions) +) + +$(P +They're not tracked. +) + +--- +@live void ohno() +{ + auto p = malloc(); + + void sneaky() { free(p); } + + sneaky(); + free(p); // double free not detected +} +--- + +$(P +$(H4 Exceptions) +) + +$(P +The analysis assumes no exceptions are thrown. +) + +--- +@live void leaky() +{ + auto p = malloc(); + pitcher(); // throws exception, p leaks + free(p); +} +--- + +$(P +One solution is to use `scope(exit)`: +) + +--- +@live void waterTight() +{ + auto p = malloc(); + scope(exit) free(p); + pitcher(); +} +--- + +$(P +or use RAII objects or call only `nothrow` functions. +) + +$(P +$(H4 Lazy Parameters) +) + +$(P +These are not considered. +) + +$(P +$(H4 Quadratic Behavior) +) + +$(P +The analysis exhibits quadratic behavior, so keeping the `@live` functions +smallish will help. +) + +$(P +$(H4 Mixing Memory Pools) +) + +$(P +Conflation of different memory pools: +) + +--- +void* xmalloc(size_t); +void xfree(void*); + +void* ymalloc(size_t); +void yfree(void*); + +auto p = xmalloc(20); +yfree(p); // should call xfree() instead +--- +$(P +is not detected. +) + +$(P +This can be mitigated by using type-specific pools: +) + +--- +U* umalloc(); +void ufree(U*); + +V* vmalloc(); +void vfree(V*); + +auto p = umalloc(); +vfree(p); // type mismatch +--- + +$(P +and perhaps disabling implicit conversions to `void*` in `@live` functions. +) + +$(P +$(H4 Variadic Function Arguments) +) + +$(P +Arguments to variadict functions (like `printf`) are considered to be consumed. +While safe, this doesn't seem to be very practical, and will likely need revisiting. +) +) + +$(LI $(LNAME2 preview-in,Added `-preview=in` to make the `in` storage class mean `scope const`.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/preview-in.dd) +$(P +Although technically defined to be `const scope`, the `in` storage +class has never been implemented as such until this preview switch. +With the implementation now done, `in` should be the storage class +of choice for purely input function parameters. +) + +$(P +Without `-preview=in`, these two declarations are equivalent: +) +------------- +void fun(in int x); +void fun(const int x); +------------- + +$(P +With `-preview=in`, these two declarations are equivalent: +) +------------------ +void fun(in int x); +void fun(scope const int x); +------------------ +) + +$(LI $(LNAME2 printfParams2,Validate printf and scanf (variants too) arguments against format specifiers) +$(CHANGELOG_SOURCE_FILE dmd, changelog/printfParams2.dd) +$(P +Follows the C99 specification 7.19.6.1 for printf and 7.19.6.2 for scanf. +) + +$(P +For printf, it takes a generous, rather than strict, view of compatiblity. +For example, an unsigned value can be formatted with a signed specifier. +) + +$(P +For scanf, it takes a strict view of compatiblity. +) + +$(P +Diagnosed incompatibilities are: +) + +$(P +1. incompatible sizes which will cause argument misalignment +2. deferencing arguments that are not pointers +3. insufficient number of arguments +4. struct arguments +5. array and slice arguments +6. non-pointer arguments to `s` specifier +7. non-standard formats +8. undefined behavior per C99 +) + +$(P +Per the C Standard, extra arguments are ignored. +) + +$(P +No attempt is made to fix the arguments or the format string. +) + +$(P +In order to use non-Standard printf/scanf formats, an easy workaround is: +) + +--- +printf("%k\n", value); // error: non-Standard format k +--- +--- +const format = "%k\n"; +printf(format.ptr, value); // no error +--- + +$(P +Most of the errors detected are portability issues. For instance, +) + +--- +string s; +printf("%.*s\n", s.length, s.ptr); +printf("%d\n", s.sizeof); +ulong u; +scanf("%lld%*c\n", &u); +--- +$(P +should be replaced with: +) +--- +string s; +printf("%.*s\n", cast(int) s.length, s.ptr); +printf("%zd\n", s.sizeof); +ulong u; +scanf("%llu%*c\n", &u); +--- + +$(P +Printf-like and scanf-like functions are detected by prefixing them +with `pragma(printf)` for printf-like functions or `pragma(scanf)` for scanf-like functions. +) + +$(P +In addition to +the pragma, the functions must conform to the following characteristics: +) + +$(P +$(OL +$(LI be `extern (C)` or `extern (C++)`) +$(LI have the format parameter declared as `const(char)*`) +$(LI have the format parameter immediately precede the `...` for non-v functions, +or immediately precede the `va_list` parameter (which is the last parameter for "v" +variants of `printf` and `scanf`)) +) +) + +$(P +which enables automatic detection of the format string argument and the argument list. +) + +$(P +Checking of "v" format strings is not implemented yet. +) +) + +$(LI $(LNAME2 reproducible-builds,Environment variable `SOURCE_DATE_EPOCH` is now supported) +$(CHANGELOG_SOURCE_FILE dmd, changelog/reproducible-builds.dd) +$(P +The environment variable `SOURCE_DATE_EPOCH` is used for +$(LINK2 https://reproducible-builds.org/, reproducible builds). +It is an UNIX timestamp (seconds since 1970-01-01 00:00:00), +as described $(LINK2 https://reproducible-builds.org/docs/source-date-epoch/, here). +DMD now correctly recognize it and will set the `__DATE__`, +`__TIME__`, and `__TIMESTAMP__` tokens accordingly. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 isbaseof,Added TypeInfo_Class/TypeInfo_Interface.isBaseOf that works like C#/Java isAssignableFrom.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/isbaseof.dd) +$(P +`TypeInfo_Class.isBaseOf` returns true if the argument and the receiver +are equal or if the class represented by the argument inherits from the +class represented by the receiver. This is called `isBaseOf` instead of +`isAssignableFrom` to avoid confusion for classes that overload +`opAssign` and so may allow assignment from classes outside their +inheritance hierarchy and to match existing terminology in the D +runtime. `TypeInfo_Interface.isBaseOf` is similar with the addition +that the argument may be either `TypeInfo_Class` or +`TypeInfo_Interface`. +) +------- +class ClassA {} +class ClassB : ClassA {} + +auto a = new ClassA(), b = new ClassB(); + +assert(typeid(a).isBaseOf(typeid(a))); +assert(typeid(a).isBaseOf(typeid(b))); +assert(!typeid(b).isBaseOf(typeid(a))); +------- +) + +$(LI $(LNAME2 page_size,Add `core.memory.pageSize` and `minimumPageSize`.) +$(CHANGELOG_SOURCE_FILE druntime, changelog/page_size.dd) +$(P +`pageSize` contains the size of a system page in bytes. +) + +--- +import core.memory : pageSize; +ubyte[] buffer = new ubyte[pageSize]; +--- + +$(P +`minimumPageSize` contains the minimum size of a system page in bytes. +) + +$(P +This is a compile time, platform specific value. This value might not +be accurate, since it might be possible to change this value. Whenever possible, +please use `pageSize` instead, which is initialized during runtime. +) + +$(P +The minimum size is useful when the context requires a compile time known value, +like the size of a static array: `ubyte[minimumPageSize] buffer`. +) + +--- +import core.memory : minimumPageSize; +ubyte[minimumPageSize] buffer; +--- +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 date-isoweek,Add `Date.isoWeekYear` and `Date.fromISOWeek` in `std.datetime.date`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/date-isoweek.dd) +$(P +It is now possible to convert from the ISO 8601 week calendar into the +Gregorian calendar which is used by Date and DateTime. +) + +$(P +Dates are constructed from the year in the ISO week calendar, the week number +and a day of week. `Date.fromISOWeek(2020, 11, DayOfWeek.mon)` will result in +`Date(2020, 3, 9)`. +) + +$(P +As the year in the Gregorian calendar and the year in the ISO week calendar are +not always the same there is a new `.isoWeekYear` property to get the year of +the `Date` object in the ISO week calendar. If you convert between them often, +consider using `.isoWeekAndYear` to compute both week number and year in one +step. +) +) + +$(LI $(LNAME2 deprecate-xml,Deprecated module `std.xml`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/deprecate-xml.dd) +$(P +The module `std.xml` has been deprecated. Any code that still needs +it can use [UndeaD](https://github.com/dlang/undeaD) instead. +For parsing xml files, we recommend to use the dub package +[dxml](https://code.dlang.org/packages/dxml). +) +) + +$(LI $(LNAME2 digest,The deprecated aliases in std.digest.digest were removed) +$(CHANGELOG_SOURCE_FILE phobos, changelog/digest.dd) +$(P +They were deprecated since 2.076.1 and have now been removed. +Import `std.digest` or its submodules instead. +) + +$(P +Additionally the deprecation cycle for `std.digest.digest` was started +and the module will be removed in 2.101. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 ignoreHiddenDirectories,Hidden directories are now ignored.) +$(CHANGELOG_SOURCE_FILE dub, changelog/ignoreHiddenDirectories.dd) +$(P +A hidden directory on most Posix file systems starts with a period. e.g. +`.dub`. By default, dub ignored hidden files (e.g. `.swap.file.d`), but not +hidden directories. Some operating systems create hidden directories that dub +would try to include for compilation. This release now will properly ignore +hidden directories, unless those directories are specifically named in the dub +recipe file. +) + +$(P +Note that this uses the directory name exclusively and does not check file +attributes. +) +) + +$(LI $(LNAME2 lintReportFile,Dub lint now supports --report-file argument.) +$(CHANGELOG_SOURCE_FILE dub, changelog/lintReportFile.dd) +$(P +Dub lint can now be called with --report-file argument: +dub lint --report-file report.json +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 20596): [REG2.086] Error on missed stack allocation for closure for template) +$(LI $(BUGZILLA 20597): [REG2.080] Wrong closure GC allocation with dip1000) +$(LI $(BUGZILLA 20718): enum type mismatch causes wrong location on error) +$(LI $(BUGZILLA 20742): dmd -X $(LPAREN)JSON output$(RPAREN) includes uncompiled symbols) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 14639): Assigning init value to struct uses stack, causing segfault) +$(LI $(BUGZILLA 15867): Compiler reports wrong error location for immutability error) +$(LI $(BUGZILLA 19949): C++ Mangling: no support for abi-tags from the Itanium ABI) +$(LI $(BUGZILLA 20084): return by auto ref unsafe - and different code for inout ref and ref.) +$(LI $(BUGZILLA 20461): [dip1000] Passing stack allocated string to assert compiles) +$(LI $(BUGZILLA 20593): [GCC ASM] Parser syntax for asm operands differs from GCC) +$(LI $(BUGZILLA 20637): spelling correction offers private members) +$(LI $(BUGZILLA 20638): spelling correction offers private member of package on named package access) +$(LI $(BUGZILLA 20643): printf without arguments aborts compilation) +$(LI $(BUGZILLA 20644): Invalid printf deprecation for ubyte passed to "%hhu") +$(LI $(BUGZILLA 20645): printf deprecation for width + precision) +$(LI $(BUGZILLA 20653): Short-circuiting boolean logic not working) +$(LI $(BUGZILLA 20658): can modify overlapped storage classes in @safe enum function) +$(LI $(BUGZILLA 20675): dip1000 improper error about copying scope parameter into allocated memory) +$(LI $(BUGZILLA 20682): [DIP1000] wrong error: scope variable may not be copied into allocated memory) +$(LI $(BUGZILLA 20696): Should error when retrieving mangling while the type is not yet final) +$(LI $(BUGZILLA 20779): Segfault when self-containing struct is accessed from inside in a __traits$(LPAREN)compiles$(RPAREN) context) +$(LI $(BUGZILLA 20795): [dip1000] segfault on templated opEquals) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 20444): Make __DATE__ in dlang reproducible using SOURCE_DATE_EPOCH) +$(LI $(BUGZILLA 20470): accessing an AliasSeq tuple loses `this`) +$(LI $(BUGZILLA 20609): Disabled and deprecated functions show up as candidate) +$(LI $(BUGZILLA 20625): Function literal diagnostic is not on par with other messages) +$(LI $(BUGZILLA 20627): Module ctors / dtors should always have D linkage) +$(LI $(BUGZILLA 20636): Support the RDSEED instruction in asm blocks) +$(LI $(BUGZILLA 20734): Array literals as arguments to scope slice parameters should be stack-allocated) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 20589): typeof may give wrong result in case of classes defining `opCall` operator) +$(LI $(BUGZILLA 20606): Cannot cast non-mutable BitArray to void[], size_t[]) +$(LI $(BUGZILLA 20733): Documentation for hasElaborateAssign says copy construction creates an opAssign) +$(LI $(BUGZILLA 20743): Checked!$(LPAREN)int, Abort$(RPAREN) does not abort but raise SIGFPE) +$(LI $(BUGZILLA 20755): ImplicitConversionTargets of const class are nonconst) +$(LI $(BUGZILLA 20799): schwartzSort does not pin transformation results with indirections, leading to memory corruption) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 20723): std.random.unpredictableSeed: on x86/x86-64 try using RDRAND when there is no arc4random) +$(LI $(BUGZILLA 20732): swap doesn't support types with impure gc or throwing copy constructors) +) +$(BUGSTITLE_BUGZILLA Druntime regressions, + +$(LI $(BUGZILLA 20748): Deprecation for assert using shared type and checkaction=context) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 20750): checkaction=context segfaults for null references) +$(LI $(BUGZILLA 20757): checkaction=context prints characters as integers) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 19924): Make core.bitop.bswap$(LPAREN)ulong$(RPAREN) work in betterC) +$(LI $(BUGZILLA 20178): Add TypeInfo_Class/TypeInfo_Interface.isBaseOf $(LPAREN)equivalent to C#/Java isAssignableFrom$(RPAREN)) +$(LI $(BUGZILLA 20711): object.update requires the "update" callback to wastefully return a copy of the updated value) +$(LI $(BUGZILLA 20741): `dup`, `idup` for arrays plus `keys`, `values` for built-in associative arrays: if a type is known to have a postblit do not emit code for the non-postblit path and vice versa) +) +) +$(D_CONTRIBUTORS_HEADER 47) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR Bernhard Seckinger) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Brian Schott) + $(D_CONTRIBUTOR David Abdurachmanov) + $(D_CONTRIBUTOR Denis Feklushkin) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR Don.Clugston) + $(D_CONTRIBUTOR drug007) + $(D_CONTRIBUTOR Ernesto Castellotti) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR H Paterson) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR ivan.roubicek) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR Jan Jurzitza) + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR Lucien Perregaux) + $(D_CONTRIBUTOR Luhrel) + $(D_CONTRIBUTOR Manu Evans) + $(D_CONTRIBUTOR Mark) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias L. Baumann) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Rasmus Thomsen) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Robert burner Schadek) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Stefan Koch) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR wolframw) + $(D_CONTRIBUTOR سليمان السهمي (Suleyman Sahmi)) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.092.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.092.1.dd b/changelog/2.092.1.dd new file mode 100644 index 0000000000..83b8ca5a64 --- /dev/null +++ b/changelog/2.092.1.dd @@ -0,0 +1,71 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jun 10, 2020, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 19 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 9 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 20626): ICE when using typeof of unittest symbol without -unittest flag) +$(LI $(BUGZILLA 20830): Segfault for multiple duplicate interfaces) +$(LI $(BUGZILLA 20885): pointer rejected for the variable declared in a `if` condition) +$(LI $(BUGZILLA 20890): parameter corruption when other parameter is a static array of length 1) +$(LI $(BUGZILLA 20893): [REG 2.087] 32-bit arithmetic goes wrong) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 12520): Comparing two TypeTuples with == does not compile for no arguments) +$(LI $(BUGZILLA 19344): Enum member UDAs & getUDAs throwing an error) +$(LI $(BUGZILLA 19728): AliasSeq in UDA errors) +$(LI $(BUGZILLA 20093): __traits$(LPAREN)getAttributes$(RPAREN) Error: cannot form tuple of tuples) +$(LI $(BUGZILLA 20710): ICE when statically accessing struct member containing empty array) +$(LI $(BUGZILLA 20758): __traits$(LPAREN)getAttributes$(RPAREN) as template argument results in broken template instances) +$(LI $(BUGZILLA 20835): Enum member attributes being evaluated in wrong scope.) +$(LI $(BUGZILLA 20875): [REG2.087.1] Enum template specialization ignored) +$(LI $(BUGZILLA 20884): Using getMember with a type as first argument can lose type qualifiers.) +$(LI $(BUGZILLA 20894): ICE: passing a member template mixin identifier as alias argument) +$(LI $(BUGZILLA 20919): DMD crash when '__traits' prints error involving a Parameter) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 20744): Using __parameters result in function definition causes wrong lookup) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 20785): std.file.setTimes: on macOS use setattrlist to avoid truncating timestamp precision to microseconds) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 20832): Fix ioctl request for TCSETS2) +) +) +$(D_CONTRIBUTORS_HEADER 9) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Christian Koestlin) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nils Lankila) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.092.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.093.0.dd b/changelog/2.093.0.dd new file mode 100644 index 0000000000..d0661d740a --- /dev/null +++ b/changelog/2.093.0.dd @@ -0,0 +1,432 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 07, 2020, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 11 major changes and 58 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 54 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 add_traits_isCopyable,Add new builtin `__traits(isCopyable, T)` for some type `T`)) +$(LI $(RELATIVE_LINK2 check_interface_implementations,Properly check interface implementations)) +$(LI $(RELATIVE_LINK2 shared-init,Allow initialization of shared variables.)) +$(LI $(RELATIVE_LINK2 vtemplates,Add -vtemplates switch to collect and list template statistics)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 add_exit_group,add `exit_group` to `core.sys.linux.unistd`)) +$(LI $(RELATIVE_LINK2 darwin_bindings,Added module `core.sys.darwin.mach.nlist` and `core.sys.darwin.mach.stab`)) +$(LI $(RELATIVE_LINK2 depercate_object_selector,Deprecated `object.selector`)) +$(LI $(RELATIVE_LINK2 gc_suffixes,Memory releated GC options can now be specified with higher accuracy)) + +) + +$(BUGSTITLE_TEXT_HEADER Installer changes, + +$(LI $(RELATIVE_LINK2 install_sh_windows,The install script now also works on the Windows command prompt.)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 dub_root_package_target_env_vars_added,Dub root package target environment variables added)) +$(LI $(RELATIVE_LINK2 improved_cli_extensibility,Improved CLI extensibility)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 add_traits_isCopyable,Add new builtin `__traits(isCopyable, T)` for some type `T`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/add_traits_isCopyable.dd) +$(P +Changing Phobos' `std.traits.isCopyable` to make use of this new builtin trait +will reduce memory usage and, in turn, improve the performance of the compiler +checking whether a type is copyable or not. +) +) + +$(LI $(LNAME2 check_interface_implementations,Properly check interface implementations) +$(CHANGELOG_SOURCE_FILE dmd, changelog/check_interface_implementations.dd) +$(P +In previous releases the check to verify that a class implements all methods of +the interfaces it implements was performed late in the compilation phase. This +caused the check to not be performed when code generation was skipped +(compiling with the `-o-` flag). +) + +$(P +In this release the check has been moved to an earlier phase of the compilation, +causing errors to be reported even when the `-o-` flag is used. This can cause +some breakage if a piece of code has only been compiled with the `-o-` flag. +) + +$(P +The compiler will now properly report an error for the following code when the +`-o-` flag is used: +) + +``` +interface Foo +{ + void foo(); +} + +class Bar : Foo +{ + +} +``` +) + +$(LI $(LNAME2 shared-init,Allow initialization of shared variables.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/shared-init.dd) +$(P +Shared variables can now be initialized when the `-preview=nosharedaccess` +switch is used. +) + +--- +void test() +{ + shared int x; + shared int y = 3; +} +--- +) + +$(LI $(LNAME2 vtemplates,Add -vtemplates switch to collect and list template statistics) +$(CHANGELOG_SOURCE_FILE dmd, changelog/vtemplates.dd) +$(P +Template instantiations can consume lots of time and memory. +By passing the -vtemplates switch to the compiler, +the compiler will collect and print statistics about template usage +in the code being compiled. +) + +$(P +For each template that was instantiated, a list of how many +times it is instantiated, and how many of those instantiations +are unique, is printed. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 add_exit_group,add `exit_group` to `core.sys.linux.unistd`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/add_exit_group.dd) +$(P +add `exit_group` to `core.sys.linux.unistd`, exits all threads in a process, present since linux 2.5.35 +) +) + +$(LI $(LNAME2 darwin_bindings,Added module `core.sys.darwin.mach.nlist` and `core.sys.darwin.mach.stab`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/darwin_bindings.dd) +$(P +Those modules contains bindings for the 64 bits part of Mac OSX's +`` and ``, respectively, +and can be used by users wishing to inspect binary data of Mach-O object files. +) +) + +$(LI $(LNAME2 depercate_object_selector,Deprecated `object.selector`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/depercate_object_selector.dd) +$(P +The public import of `selector` in the module `object` has been deprecated. +Please explicitly import `selector` instead using: `import core.attribute : selector;` +) + +$(P +The following code has been deprecated: +) + +``` +extern (Objective-C) +extern class NSObject +{ + static NSObject alloc() @selector("alloc"); +} +``` + +$(P +Replace with: +) + +``` +import core.attribute : selector; + +extern (Objective-C) +extern class NSObject +{ + static NSObject alloc() @selector("alloc"); +} +``` +) + +$(LI $(LNAME2 gc_suffixes,Memory releated GC options can now be specified with higher accuracy) +$(CHANGELOG_SOURCE_FILE druntime, changelog/gc_suffixes.dd) +$(P +Memory-related GC options stored in bytes instead of megabytes to +provide fine-tune GC on low memory devices. +) + +$(P +Added ability to use suffixes B, K, M or G: +) +--- +extern(C) __gshared string[] rt_options = + [ "gcopt=minPoolSize:4K maxPoolSize:2M incPoolSize:8K" ]; +--- + +$(P +Values without suffix treated as megabytes. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Installer changes, + +$(LI $(LNAME2 install_sh_windows,The install script now also works on the Windows command prompt.) +$(CHANGELOG_SOURCE_FILE installer, changelog/install_sh_windows.dd) +$(P +The official D version manager ($(LINK2 https://dlang.org/install.sh, install.sh), +documented at $(LINK2 https://dlang.org/install.html, dlang.org/install.html)) +used to require a POSIX environment. On Windows, prior to this release, this +meant running the script and the compilers that it installed from within a +POSIX terminal emulator as provided by MSYS2 or Cygwin. With this release it is +now possible to install and activate compilers from the Windows command prompt +directly. +) + +$(P +Assuming an MSYS2 installation is present in `C:\msys64`, necessary decompression +tools can be installed from the Windows command prompt: +) +------- +C:\msys64\usr\bin\pacman.exe --sync unzip p7zip +------- + +$(P +The following will invoke the script directly from dlang.org and install the +latest dmd compiler in the `%USERPROFILE%\dlang` folder: +) +------- +C:\msys64\usr\bin\curl.exe https://dlang.org/install.sh | \msys64\usr\bin\bash.exe -s +------- +$(P +This process will end with a message showing the location of `activate.bat`, +which can be used to add the installed compiler to your `PATH`. +) + +$(P +The script itself will also be installed locally. This will show you its other +uses: +) +------- +C:\msys64\usr\bin\bash.exe %USERPROFILE%\dlang\install.sh --help +------- +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 dub_root_package_target_env_vars_added,Dub root package target environment variables added) +$(CHANGELOG_SOURCE_FILE dub, changelog/dub_root_package_target_env_vars_added.dd) +$(P +Environment variables `DUB_ROOT_PACKAGE_TARGET_TYPE`, `DUB_ROOT_PACKAGE_TARGET_PATH` +and `DUB_ROOT_PACKAGE_TARGET_NAME` have been added and exposed. +) +) + +$(LI $(LNAME2 improved_cli_extensibility,Improved CLI extensibility) +$(CHANGELOG_SOURCE_FILE dub, changelog/improved_cli_extensibility.dd) +$(P +The code from the runDubCommandLine was moved to some other structs. The new +CommandLineHandler structure takes care of the CLI state and commands, which +allows DUB commands to be extended in other projects. +) + +$(P +The CommandArgs class now has new `hasAppArgs` and `appArgs` methods which +allows you to get the app arguments. In addition, the `extractAllRemainingArgs` +method will return all unused arguments and the app arguments. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 19550): [REG 2.078] Massive compiler backend slowdown) +$(LI $(BUGZILLA 20014): [REG 2.084] -transition=all, -preview=all, -revert=all is invalid) +$(LI $(BUGZILLA 20833): Template members prevent __traits$(LPAREN)getOverloads$(RPAREN) from working properly) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 11292): Cannot re-initialize a const field in postblit) +$(LI $(BUGZILLA 12504): Wrong 'cannot cover index range' error message) +$(LI $(BUGZILLA 15235): inline asm: silent ICE $(LPAREN)segfault$(RPAREN) in asm_add_exp$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 16971): Misleading error messages "break is not inside scope$(LPAREN)exit$(RPAREN) bodies" "continue is not inside scope$(LPAREN)exit$(RPAREN) bodies") +$(LI $(BUGZILLA 20183): Assigning statement scope of struct literal or temporary to variable with longer lifetime) +$(LI $(BUGZILLA 20410): ReplaceTypeUnless replaces enums with their basetype) +$(LI $(BUGZILLA 20709): Segmentation fault when importing nonexistent type) +$(LI $(BUGZILLA 20719): Self referential struct definition causes stack overflow) +$(LI $(BUGZILLA 20747): @live tracking of non-pointer owners not done) +$(LI $(BUGZILLA 20771): va_arg doesn't work for structs with postblits) +$(LI $(BUGZILLA 20772): va_arg doesn't work for structs with copy constructors) +$(LI $(BUGZILLA 20775): Missing fail compilation test for passing types that need destruction) +$(LI $(BUGZILLA 20780): Function parameter UDA not accepted in nested function declarations) +$(LI $(BUGZILLA 20789): is$(LPAREN)T: U$(RPAREN) doesn't exclude deprecated alias calls with -de) +$(LI $(BUGZILLA 20800): Error: cannot implicitly convert expression with bad diagnostic.) +$(LI $(BUGZILLA 20824): error messages generated by dmd build script can be prefixed with a non-standard "ERROR:") +$(LI $(BUGZILLA 20825): the filename of the error messages generated by dmd build.d script miss the "src/" part of the path) +$(LI $(BUGZILLA 20840): No deprecation when using template from deprecated selective import) +$(LI $(BUGZILLA 20842): Structs with disabled default/copy ctors can't be initialized) +$(LI $(BUGZILLA 20861): Interface implementations are not checked when code gen is skipped) +$(LI $(BUGZILLA 20903): seg fault on long signed divide overflow) +$(LI $(BUGZILLA 20906): unnecessary divide-by-zero errors when constant folding short circuits) +$(LI $(BUGZILLA 20909): .offsetof fails on forward reference of field) +$(LI $(BUGZILLA 20915): __traits$(LPAREN)allMembers$(RPAREN) results include custom version identifiers, which is unusable) +$(LI $(BUGZILLA 20923): Redefinition of 'size_t' is affecting TypeStruct functions) +$(LI $(BUGZILLA 20989): Checking array.ptr causes safety error with -checkaction=context) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 20791): extern$(LPAREN)C++ $(RPAREN) should allow a trailing comma) +$(LI $(BUGZILLA 20796): protection attribute package$(LPAREN)x.y$(RPAREN) does not bind to one of ancestor packages of module x.y when declared in x/y/package.d) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 20943): std.algorithm.setops.cartesianProduct fails for ranges with @system popFront) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 9298): some std.math functions not implemented for Win64) +$(LI $(BUGZILLA 20426): doesPointTo with void[N] fails) +$(LI $(BUGZILLA 20751): SortedRange with ref predicate parameters fails) +$(LI $(BUGZILLA 20782): std.conv.to can't convert string to const enum) +$(LI $(BUGZILLA 20783): std.string.lastIndexOf doesn't work correctly in CTFE) +$(LI $(BUGZILLA 20836): std.math: reorder declarations from most visible to least) +$(LI $(BUGZILLA 20850): Can't assign enum of Tuple) +$(LI $(BUGZILLA 20874): std.json.assign requires '@safe' and 'pure') +$(LI $(BUGZILLA 20928): Overloaded opIndex confuses MapResult) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 19525): Duration is not usable with zero-arg std.algorithm.sum) +$(LI $(BUGZILLA 20496): chunkby should support ref predicates) +$(LI $(BUGZILLA 20869): `std.algorithm.mutation : move` is overly trusting of `opPostMove`) +$(LI $(BUGZILLA 20887): Improve speed of std.digest.digest!$(LPAREN)Hash, Range$(RPAREN) on non-array ranges) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 18011): core.sys.condition cannot be used as shared) +$(LI $(BUGZILLA 20760): checkaction=context doesnt print floating point numbers correctly) +$(LI $(BUGZILLA 20763): checkaction=context does not format pointers) +$(LI $(BUGZILLA 20767): [DIP1014] __move_post_blt must only recursively call itself on a struct's fields not all members) +$(LI $(BUGZILLA 20768): [DIP1014] __move_post_blt must recursively call itself on static arrays whose elements are structs or static arrays that recursively contain structs) +$(LI $(BUGZILLA 20852): core.sys.posix.sys.wait missing definitions on FreeBSD) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 20746): Change LCG in garbage collector treap to use full 64 bits of state instead of 48) +$(LI $(BUGZILLA 20787): Add module core.sys.darwin.sys.attr with getattrlist, setattrlist, searchfs, and related definitions) +$(LI $(BUGZILLA 20844): DMD compiler should take care of data alignment, after seeing the 'cas' call) +$(LI $(BUGZILLA 20859): Add overloads of core.sync.rwmutex.ReadWriteMutex.Reader/Writer.tryLock that take a timeout duration) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 20882): Outdated examples in the documentation $(LPAREN)std.stdio$(RPAREN)) +) +$(BUGSTITLE_BUGZILLA Tools enhancements, + +$(LI $(BUGZILLA 13345): rdmd --eval doesn't support args) +) +$(BUGSTITLE_BUGZILLA Installer bugs, + +$(LI $(BUGZILLA 20826): CI breakage: create_dmd_release attempts to copy the complete dmd repo.) +) +) +$(D_CONTRIBUTORS_HEADER 54) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Alexandru Militaru) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Anton Oks) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR blackbird) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR BthereDthat) + $(D_CONTRIBUTOR Cristian Creteanu) + $(D_CONTRIBUTOR Denis Feklushkin) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR drug007) + $(D_CONTRIBUTOR Ernesto Castellotti) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR guai) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR Kazuya Takahashi) + $(D_CONTRIBUTOR Luhrel) + $(D_CONTRIBUTOR Manu Evans) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Nils Lankila) + $(D_CONTRIBUTOR Patrick Schlüter) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Pierre Grimaud) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Richard Manthorpe) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Sergei Akhmatdinov) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Tomoya Tanjo) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR Walter Waldron) + $(D_CONTRIBUTOR welkam) + $(D_CONTRIBUTOR Witold Baryluk) + $(D_CONTRIBUTOR wolframw) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.093.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.093.1.dd b/changelog/2.093.1.dd new file mode 100644 index 0000000000..8544cb9e36 --- /dev/null +++ b/changelog/2.093.1.dd @@ -0,0 +1,60 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Aug 15, 2020, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 10 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 13 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 21063): getLinkage is wrong for forward reference extern$(LPAREN)C++$(RPAREN) class) +$(LI $(BUGZILLA 21074): const lost in mixin) +$(LI $(BUGZILLA 21095): [ICE] AssertError@dmd/expressionsem.d$(LPAREN)5015$(RPAREN): Assertion failure) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 16400): naked variadic C function emits broken prologue) +$(LI $(BUGZILLA 17351): Static const array can't be evaluated at compile time when passed as ref argument) +$(LI $(BUGZILLA 21085): [glue] Only 9999 "hidden identifiers" can be generated) +$(LI $(BUGZILLA 21092): [ICE] Segmentation fault in ExpressionPrettyPrintVisitor::visit$(LPAREN)CommaExp*$(RPAREN) at dmd/hdrgen.d:2293) +$(LI $(BUGZILLA 21096): [ICE] Segmentation fault in dmd.hdrgen.sizeToBuffer at dmd/hdrgen.d:3153) +$(LI $(BUGZILLA 21122): __traits$(LPAREN)getAttributes$(RPAREN) wrong scope on enums) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 21059): install.sh: posix_terminal returns false on Linux Mint 20) +) +) +$(D_CONTRIBUTORS_HEADER 13) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Andrej Mitrovic) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Stefan Koch) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.093.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.094.0.dd b/changelog/2.094.0.dd new file mode 100644 index 0000000000..29e91ea178 --- /dev/null +++ b/changelog/2.094.0.dd @@ -0,0 +1,910 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 22, 2020, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 21 major changes and 119 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 49 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 add_traits_child,Add `__traits(child, parent, member)`)) +$(LI $(RELATIVE_LINK2 array-literal-inference,Improve type determination for array literals)) +$(LI $(RELATIVE_LINK2 better-vtemplates,Template usage diagnostics via `-vtemplates` has been improved.)) +$(LI $(RELATIVE_LINK2 cxx-header-modes,C++ header generation omits `Ignored ...` comments by default)) +$(LI $(RELATIVE_LINK2 debug-nothrow,Exception-throwing code can now be used in debug blocks)) +$(LI $(RELATIVE_LINK2 hasAlwaysInlines,Always inline `pragma(inline, true)` functions regardless of -inline compiler switch.)) +$(LI $(RELATIVE_LINK2 implicit-override-deprecation-end-17349,The deprecation period for implicit override has ended)) +$(LI $(RELATIVE_LINK2 implicit-vector-conversions,Strict implicit conversion rules for Vector types)) +$(LI $(RELATIVE_LINK2 in-identity,Parameters marked as `in` will now be properly displayed)) +$(LI $(RELATIVE_LINK2 markdown-default,DDoc Markdown support has been enabled by default)) +$(LI $(RELATIVE_LINK2 preview-in,Added support for input parameters (`in` parameter, `-preview=in`))) +$(LI $(RELATIVE_LINK2 vector-operation-support,Usage of vector types and operations on an unsupported `-mcpu=` will now error)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 array_equality,Equality of arrays of structs is consistent again, as before v2.078)) +$(LI $(RELATIVE_LINK2 faster_profilegc,`core.memory.GC.allocatedInCurrentThread()` was added, which makes `-profile=gc` faster)) + +) + +$(BUGSTITLE_TEXT_HEADER Installer changes, + +$(LI $(RELATIVE_LINK2 install-dmd-dc,Installation script now supports `get-path `)) +$(LI $(RELATIVE_LINK2 ldc-built-releases,DMD binary releases are now built with LDC)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 add_x86_omf,Added architecture x86_omf for windows-dmd)) +$(LI $(RELATIVE_LINK2 dub-remove,`dub remove --non-interactive` will now remove all packages by default)) +$(LI $(RELATIVE_LINK2 enforce_proper_package_loading,Running `dub upgrade` on a package-less folder is now a no-op)) +$(LI $(RELATIVE_LINK2 git-paths,Support dependencies as git url with exact commit)) +$(LI $(RELATIVE_LINK2 version,All commands now support `package[@]`, `--version` is deprecated)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 add_traits_child,Add `__traits(child, parent, member)`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/add_traits_child.dd) +$(P +Takes two arguments. The first must be a symbol or expression and the second +must be a symbol, such as an alias to a member of `parent`. The result is +`member` interpreted with its `this` context set to `parent`. This is the +inverse of `__traits(parent, member)`. +) + +--- +struct A +{ + int i; + int foo(int j) { + return i * j; + } +} + +alias Ai = A.i; + +void main() +{ + A a; + + __traits(child, a, Ai) = 3; + assert(a.i == 3); + assert(__traits(child, a, A.foo)(2) == 6); +} +--- +) + +$(LI $(LNAME2 array-literal-inference,Improve type determination for array literals) +$(CHANGELOG_SOURCE_FILE dmd, changelog/array-literal-inference.dd) +$(P +There were some cases where DMD wasn't able to determine the common type for +array literal elements. Mismatched enums and literals containing only mutable +and immutable elements should now be correctly inferred. +) +) + +$(LI $(LNAME2 better-vtemplates,Template usage diagnostics via `-vtemplates` has been improved.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/better-vtemplates.dd) +$(P +Every template having at least one instantiation is now printed using standard +compiler diagnostics formatting for easy navigation to the point of its +declaration. +) + +$(P +All messages of this kind are sorted by descending unique instantiation count. +) + +$(P +If the flag argument `list-instances` is passed (such as `-vtemplates=list-instances`), +each location where a template was instantiated is printed along with the reason for +the instantiation (implicit or explicit). +) + +$(P +For instance, a D source file named `main.d` containing +) + +--- +void foo(int I)() { } +void goo1(int I)() { } +void goo2(int I)() { goo1!(I); } + +void test() +{ + foo!(1)(); + foo!(1)(); + foo!(2)(); + + goo1!(1)(); + + goo2!(1)(); +} +--- + +$(P +compiled with `-vtemplates=list-instances` will output +) + +--- +main.d(1): vtemplate: 3 (2 unique) instantiation(s) of template `foo(int I)()` found, they are: +main.d(7): vtemplate: explicit instance `foo!1` +main.d(8): vtemplate: explicit instance `foo!1` +main.d(9): vtemplate: explicit instance `foo!2` +main.d(2): vtemplate: 2 (1 unique) instantiation(s) of template `goo1(int I)()` found, they are: +main.d(11): vtemplate: explicit instance `goo1!1` +main.d(3): vtemplate: implicit instance `goo1!1` +main.d(3): vtemplate: 1 (1 unique) instantiation(s) of template `goo2(int I)()` found, they are: +main.d(13): vtemplate: explicit instance `goo2!1` +--- +) + +$(LI $(LNAME2 cxx-header-modes,C++ header generation omits `Ignored ...` comments by default) +$(CHANGELOG_SOURCE_FILE dmd, changelog/cxx-header-modes.dd) +$(P +The C++ header generated used to write comments when it encountered +non-`extern(C++)` declarations, e.g. +) + +--- +// test.d +void foo() {} +--- +--- +// test.h +[...] +// ignoring function test.foo because of linkage +--- + +$(P +This caused a lot of bloat in the generated header file and is now +customizable via the `-HC= switch which accepts either +`verbose` (write comments) and `silent` (omit comments). The default +was changed to `silent`. +) + +$(P +Note: The header generator is still considerer experimental, so please + submit any bugs encountered to [the bug tracker](https://issues.dlang.org). +) +) + +$(LI $(LNAME2 debug-nothrow,Exception-throwing code can now be used in debug blocks) +$(CHANGELOG_SOURCE_FILE dmd, changelog/debug-nothrow.dd) +$(P +When writing debug code, one isn't interested statically ensuring that a function block doesn't `throw`, +but a pleasant debugging experience as e.g. writing to the console or logfiles typically can't be `nothrow`. +DMD already allowed to escape `pure` and `@nogc` within `debug` statement. +With this release, exception-throwing code can be called from `debug` statements too: +) + +--- +import std.stdio; +void main() nothrow +{ + debug writeln("Your throwing log statement."); +} +--- +) + +$(LI $(LNAME2 hasAlwaysInlines,Always inline `pragma(inline, true)` functions regardless of -inline compiler switch.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/hasAlwaysInlines.dd) +$(P +Marking a function with `pragma(inline, true)` will now cause it to be always inlined +when called, and a compile error will result if it cannot be inlined. +) + +$(P +If the `pragma(inline, true)` is embedded in the function body rather than +outside it, it may not always take effect. (It depends on whether the function +body is analyzed before it is called or not.) +) + +$(P +If a function marked with `pragma(inline, true)` cannot be inlined it will now +issue a warning if and only if the -wi command line switch is given. Previously, +it would issue an error. +) +) + +$(LI $(LNAME2 implicit-override-deprecation-end-17349,The deprecation period for implicit override has ended) +$(CHANGELOG_SOURCE_FILE dmd, changelog/implicit-override-deprecation-end-17349.dd) +$(P +Implicit overrides of base classes methods were deprecated in 2.075.0 +(released 2017-07-19) when [issue 17349](https://issues.dlang.org/show_bug.cgi?id=17349) +was fixed by [PR 6731](https://github.com/dlang/dmd/pull/6731). +) + +$(P +The deprecation period has now ended and the following code will always error from now: +) +--- +class Base +{ + void myFunction(); + void myOtherFunction(void* ptr); +} + +class Child : Base +{ + // Error: Implicitly overriding `Base.myFunction` + void myFunction() const; + // Error: Implicitly overriding `Base.myOtherFunction(void*)` + void myOtherFunction(const void* ptr); +} +--- +) + +$(LI $(LNAME2 implicit-vector-conversions,Strict implicit conversion rules for Vector types) +$(CHANGELOG_SOURCE_FILE dmd, changelog/implicit-vector-conversions.dd) +$(P +Previously, the compiler allowed any `__vector` type to be implicitly +convertible with any other `__vector` type. +) + +--- +int4 x = 2; +float8 y = x; +short8 z = y / 3; +--- + +$(P +In this release, `__vector` types now, like static arrays, can only be +implicitly converted to either qualified types of itself, or void. +) + +--- +const int4 a = 5; +int4 b = a; // OK, both are int4 +void16 c = a; // OK, cast to void of same size. +float4 d = b; // Error, cannot implicitly convert int4 to float4. +--- + +$(P +Explicit conversions between `__vector` types can be done, but only between +vectors of the same size. +) + +--- +long2 a = 8; +short8 b = cast(short8)a; // OK +short16 c = cast(short16)b; // Error, cannot cast because of different sizes. +--- + +$(P +Users of the `__simd` and `__simd_sto` intrinsics will have to either add +explicit casts from void16 to the appropriate type at each use, or operate +strictly with void16 vectors until a value is required to be peeked. +) + +--- +float4 fun1(float4 a, float4 b) +{ + a = cast(float4)__simd(XMM.ADDPD, a, b); + a = cast(float4)__simd(XMM.ADDSS, a, b); + return a; +} + +float4 fun2(void16 a, void16 b) +{ + a = __simd(XMM.ADDPD, a, b); + a = __simd(XMM.ADDSS, a, b); + return cast(float4)a; +} +--- +) + +$(LI $(LNAME2 in-identity,Parameters marked as `in` will now be properly displayed) +$(CHANGELOG_SOURCE_FILE dmd, changelog/in-identity.dd) +$(P +In earlier releases, using `in` on parameters would be lowered too early, +leading to confusing display: error messages would show the parameter +as `const` (or `scope const` if `-preview=in` was used), +and so would header generations or stack traces. +The header generation was problematic, as a header generated with `-preview=in` +would be different from one generated without. +From this release, `in` will now display correctly in every message. +As this requires an update to the mangling, some older debuggers or tools +might not be able to properly demangle functions that uses `in` parameters. +) +) + +$(LI $(LNAME2 markdown-default,DDoc Markdown support has been enabled by default) +$(CHANGELOG_SOURCE_FILE dmd, changelog/markdown-default.dd) +$(P +Ddoc's [Markdown](https://daringfireball.net/projects/markdown/syntax) has now been enabled by default. +The full list of supported Markdown features (headings, emphasized text, links, and more) is described in [the Ddoc documentation page](https://dlang.org/spec/ddoc.html#highlighting). +) + +$(P +For the more cautious, a list of all instances of Markdown features can be logged with `-transition=vmarkdown`. +If you encounter issues with this transition, you can temporarily disable the processing of the Markdown features with `-revert=markdown` and report an issue. +) + +$(P +A huge thanks goes to David Gileadi for championing this issue! +) +) + +$(LI $(LNAME2 preview-in,Added support for input parameters (`in` parameter, `-preview=in`)) +$(CHANGELOG_SOURCE_FILE dmd, changelog/preview-in.dd) +$(P +D has supported the `in`, `ref`, and `out` storage classes on parameters +since its inception. `out` and `ref` are commonly used, +however `in` was usually left behind, as, while it was originally intended +as an alias to `const scope`, it was made an alias to `const` when +support for `scope` was introduced (DIP1000). +) + +$(P +DMD v2.092.0 rectified this by adding `-preview=in` to mean `const scope`, +as it was originally intended, instead of `const` without the switch. +) + +$(P +However, this didn't really capture the intended meaning of `in`: +the be applied on input parameters. +Input parameters are parameters that a function intend to only examine, +without modifying it, nor keeping a reference to them around. +This is covered by `const scope`. However, some input parameters can +be pretty large, or copying them can have side effects (postblit, copy constructor), +hence those should be passed by reference to avoid runtime overhead. +Which prompts a new issue: D doesn't support passing rvalues by references. +Hence, when designing an API accepting an input parameter, a common +practice was to have both an `in`-accepting overload, and an `in ref`-accepting one. +While this works well for a single parameter, it also suffers from combinatorial explosion. +) + +$(P +This release reworks the meaning of `in` to properly support all those use cases. +`in` parameters will now be passed by reference when optimal, and will accept rvalue. +When using the switch, `in ref` parameters will also trigger an error. +) + +$(P +Note that the rules for passing by reference are as follow: +- If the type has an elaborate copy or destruction (postblit, copy constructor, destructor), +the type is always passed by reference. +- If the type is not copy-able, it will always be passed by reference. +- Reference types (dynamic arrays, function pointers, delegates, associative arrays, classes) + do not get passed by `ref`. This allows for covariance on delegates. +- Otherwise, if the type's size requires it, it will be passed by reference. + Currently, types which are over twice the machine word size will be passed by reference, + however this is controlled by the backend and can be changed based on the platform's ABI. +) +) + +$(LI $(LNAME2 vector-operation-support,Usage of vector types and operations on an unsupported `-mcpu=` will now error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/vector-operation-support.dd) +$(P +Previously, the compiler accepted the following code as being supported by all +`-mcpu=` types on both OSX 32-bit and all 64-bit targets. +) + +--- +__vector(long[4]) x; // AVX type +x += 1; // AVX2 operation +--- + +$(P +In this release, all `__vector` types and operations now check the current CPU +being targeted for, and will issue an error if there is insufficient support. +) + +$(P +This also allows for conditional compilation using `__traits(compiles)` to +probe which operations are supported at compile-time. +) + +--- +static if (__traits(compiles, long4)) +{ + // Compiled in if `-mcpu=avx` or higher +} + +static if (__traits(compiles, { int4 x; x += 1; })) +{ + // Compiled in if `-mcpu=baseline` or higher +} + +static if (__traits(compiles, { int4 x; x *= 1; })) +{ + // Compiled in if `-mcpu=avx` or higher +} + +static if (__traits(compiles, { int8 x; x += 1; })) +{ + // Compiled in if `-mcpu=avx2` or higher +} +--- + +$(P +The following tables describe what minimum `-mcpu=` level is required. +) + +$(P +$(TABLE2 Minimum Required `-mcpu=` for 128-bit Vector Types +$(THEAD void16,byte16,ubyte16,short8,ushort8,int4,uint4,long2,ulong2,float4,double2) +$(TROW baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline) +) +) + +$(P +$(TABLE2 Minimum Required `-mcpu=` for 128-bit Vector Operators, +$(THEAD Operator,byte16,ubyte16,short8,ushort8,int4,uint4,long2,ulong2,float4,double2) +$(TROW +,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline) +$(TROW -,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline) +$(TROW *,$(NDASH),$(NDASH),baseline,baseline,avx,avx,$(NDASH),$(NDASH),baseline,baseline) +$(TROW /,$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),baseline,baseline) +$(TROW $(CODE_AMP),baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,$(NDASH),$(NDASH)) +$(TROW |,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,$(NDASH),$(NDASH)) +$(TROW $(D ^),baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,$(NDASH),$(NDASH)) +$(TROW +=,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline) +$(TROW -=,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline) +$(TROW *=,$(NDASH),$(NDASH),baseline,baseline,avx,avx,$(NDASH),$(NDASH),baseline,baseline) +$(TROW /=,$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),baseline,baseline) +$(TROW $(CODE_AMP)=,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,$(NDASH),$(NDASH)) +$(TROW |=,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,$(NDASH),$(NDASH)) +$(TROW $(D ^=),baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,$(NDASH),$(NDASH)) +$(TROW $(I unary)$(D ~),baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,$(NDASH),$(NDASH)) +$(TROW $(I unary)+,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline) +$(TROW $(I unary)-,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline) +) +) + +$(P +$(TABLE2 Minimum Required `-mcpu=` for 256-bit Vector Types +$(THEAD void32,byte32,ubyte32,short16,ushort16,int8,uint8,long4,ulong4,float8,double4) +$(TROW avx,avx,avx,avx,avx,avx,avx,avx,avx,avx,avx) +) +) + +$(P +$(TABLE2 Minimum Required `-mcpu=` for 256-bit Vector Operators, +$(THEAD Operator,byte32,ubyte32,short16,ushort16,int8,uint8,long4,ulong4,float8,double4) +$(TROW +,avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx,avx) +$(TROW -,avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx,avx) +$(TROW *,$(NDASH),$(NDASH),avx2,avx2,avx2,avx2,$(NDASH),$(NDASH),avx,avx) +$(TROW /,$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),avx,avx) +$(TROW $(CODE_AMP),avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx2,$(NDASH),$(NDASH)) +$(TROW |,avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx2,$(NDASH),$(NDASH)) +$(TROW $(D ^),avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx2,$(NDASH),$(NDASH)) +$(TROW +=,avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx,avx) +$(TROW -=,avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx,avx) +$(TROW *=,$(NDASH),$(NDASH),avx2,avx2,avx2,avx2,$(NDASH),$(NDASH),avx,avx) +$(TROW /=,$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),$(NDASH),avx,avx) +$(TROW $(CODE_AMP)=,avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx2,$(NDASH),$(NDASH)) +$(TROW |=,avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx2,$(NDASH),$(NDASH)) +$(TROW $(D ^=),avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx2,$(NDASH),$(NDASH)) +$(TROW $(I unary)$(D ~),avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx2,$(NDASH),$(NDASH)) +$(TROW $(I unary)+,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline,baseline) +$(TROW $(I unary)-,avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx2,avx,avx) +) +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 array_equality,Equality of arrays of structs is consistent again, as before v2.078) +$(CHANGELOG_SOURCE_FILE druntime, changelog/array_equality.dd) +$(P +Since v2.078, some array equality comparisons (e.g., if both arrays are +dynamic arrays) have been wrongly using a `.tupleof` comparison for +structs without custom `opEquals`, basically enforcing +`-preview=fieldwise` for these array comparisons. +) + +--- +union U +{ + string s; +} + +void main() +{ + static immutable from = "from", from2 = "from2"; + U[] a = [{ s : from }]; + U[1] b = [{ s : from2[0..4] }]; + assert(a[0] != b[0]); + assert(a != b); + assert(a != b[]); // worked before v2.078, been failing since, now working again +} +--- +) + +$(LI $(LNAME2 faster_profilegc,`core.memory.GC.allocatedInCurrentThread()` was added, which makes `-profile=gc` faster) +$(CHANGELOG_SOURCE_FILE druntime, changelog/faster_profilegc.dd) +$(P +The new function `core.memory.GC.allocatedInCurrentThread()` returns +the same as `core.memory.GC.stats().allocatedInCurrentThread`, but +is faster, because it avoids calculating other statistics. +It is used for `-profile=gc` and makes it faster, too. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Installer changes, + +$(LI $(LNAME2 install-dmd-dc,Installation script now supports `get-path `) +$(CHANGELOG_SOURCE_FILE installer, changelog/install-dmd-dc.dd) +$(P +`get-path ` has been added as a new action to the install script. +This action allows printing information about a compiler binary. +The behavior of `get-path` can be changed with the following additional options: +) + +$(P +$(UL + $(LI `--install` install compiler if not found locally) + $(LI `--dmd` returns the path of a specific compiler executable (DMD-alike interface)) + $(LI `--dub` returns the path of the DUB executable) +) +) + +$(P +$(H4 Examples) +) + +$(P +$(CONSOLE curl https://dlang.org/install.sh | bash -s get-path --install +/home/user/dlang/dmd-2.093.0/linux/bin64/dmd +) +) + +$(P +$(CONSOLE ~/dlang/install.sh get-path ldc-1.23.0 --install +/home/user/dlang/ldc-1.23.0/bin/ldc2 +) +) + +$(P +$(CONSOLE ~/dlang/install.sh get-path --dmd ldc --install +/home/user/dlang/ldc-1.23.0/bin/ldmd2 +) +) + +$(P +$(CONSOLE ~/dlang/install.sh get-path --dub ldc --install +/home/user/dlang/ldc-1.23.0/bin/dub +) +) + +$(P +$(CONSOLE ~/dlang/install.sh get-path --dub dub-1.22.0 --install +/home/user/dlang/dub-1.22.0/dub +) +) + +$(P +$(CONSOLE ~/dlang/install.sh get-path --dub ldc,dub-1.22.0 --install +/home/user/dlang/dub-1.22.0/dub +) +) + +$(P +If a compiler installation isn't found and `--install` has not been passed, an error will be issued. +) +) + +$(LI $(LNAME2 ldc-built-releases,DMD binary releases are now built with LDC) +$(CHANGELOG_SOURCE_FILE installer, changelog/ldc-built-releases.dd) +$(P +Binary releases for Linux, OSX, and FreeBSD are now built with +LDC. This follows the switch to LDC as host compiler for Windows +releases with 2.091.0. +) + +$(P +Building DMD with LDC should provide a significant speedup of the compiler (20-30%). +) + +$(P +This change comes with the following limitations: +- no more FreeBSD 32-bit binary releases (no 32-bit LDC host compiler) +- additional binary tools copied over from previous dmd releases are no longer included + (see [c0de0295e6b1f9a802bb04a97cca9f06c5b0dccd](https://github.com/dlang/installer/commit/c0de0295e6b1f9a802bb04a97cca9f06c5b0dccd) (optlink still included)) + They are still available via https://digitalmars.com/ or from older dmd releases. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 add_x86_omf,Added architecture x86_omf for windows-dmd) +$(CHANGELOG_SOURCE_FILE dub, changelog/add_x86_omf.dd) +$(P +On windows dmd the x86_omf architecture can now be used as platform +specification using `--arch=x86_omf`. This is currently equivalent to +the previously existing `--arch=x86` argument. +) +) + +$(LI $(LNAME2 dub-remove,`dub remove --non-interactive` will now remove all packages by default) +$(CHANGELOG_SOURCE_FILE dub, changelog/dub-remove.dd) +$(P +When calling a command with a package name and no version specification, +the latest version is usually assumed. +While this behavior makes sense for `dub fetch` or `dub run`, +it can come as a surprise when cleaning up local packages through `dub remove`, +and so previous version would simply error out when more than one version was available. +From this version, `dub remove -n $PKGNAME` will just remove all cached versions +of the package named `$PKGNAME`, without asking you to use `$PKGNAME@*`. +) +) + +$(LI $(LNAME2 enforce_proper_package_loading,Running `dub upgrade` on a package-less folder is now a no-op) +$(CHANGELOG_SOURCE_FILE dub, changelog/enforce_proper_package_loading.dd) +$(P +Prior to this change, accidentally running `dub upgrade` in a folder +where no `dub.json` / `dub.sdl` was present would leave you with a +`dub.selections.json` and, in some instances, an empty `.dub` folder. +This has been fixed and running `dub upgrade` where one shouldn't +will now only generate a friendly error message. +) +) + +$(LI $(LNAME2 git-paths,Support dependencies as git url with exact commit) +$(CHANGELOG_SOURCE_FILE dub, changelog/git-paths.dd) +$(P +Git repositories can be directly used by dub as dependencies. +) + +$(P +dub.json: +) +------- +{ + "name": "git-dependency", + "dependencies": { + "gitcompatibledubpackage": { + "repository": "git+https://github.com/dlang-community/gitcompatibledubpackage.git", + "version": "ccb31bf6a655437176ec02e04c2305a8c7c90d67" + } + } +} +------- +) + +$(LI $(LNAME2 version,All commands now support `package[@]`, `--version` is deprecated) +$(CHANGELOG_SOURCE_FILE dub, changelog/version.dd) +$(P +`dub` commands had some disparity in their version handling. +Most commands accepting a package name (e.g. `dub fetch` or `dub run`) supported +either `package[@version-spec]`, or supported only `package` and accepted an +option `--version=`. +The latter form has now been deprecated and all commands now accept `package[@]`. +Note that the absence of `@` still means "latest version" (except for `remove`). +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 18412): [REG2.077.0] immutable array in library becomes null when referenced in static constructor) +$(LI $(BUGZILLA 19476): explicit mixin template function call results in recursive call instead) +$(LI $(BUGZILLA 20296): Segfault when using variadic D functions with extern$(LPAREN)C++$(RPAREN) linkage) +$(LI $(BUGZILLA 20620): dmd version has -dirty suffix) +$(LI $(BUGZILLA 20958): incomplete semantic analysis when generating code for function) +$(LI $(BUGZILLA 20981): Runtime segfault for inlined __simd_sto) +$(LI $(BUGZILLA 21088): std.meta.staticMap no longer works for typeid) +$(LI $(BUGZILLA 21091): [ICE] Segmentation fault: Module::importAll$(LPAREN)Scope*$(RPAREN) $(LPAREN)this=0x0, prevsc=0x0$(RPAREN) at dmd/dmodule.d:1124) +$(LI $(BUGZILLA 21163): Scope lambda argument in struct initializer causes parsing error) +$(LI $(BUGZILLA 21196): [REG 2.092] Deprecation for language feature triggered inside of deprecated block) +$(LI $(BUGZILLA 21258): Tuple parameters with defaults use the first tuple element for all defaults since 2.094.0-beta.1) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 2617): asm silently accepts ambiguous-sized operations) +$(LI $(BUGZILLA 5570): 64 bit C ABI not followed for passing structs and complex numbers as function parameters) +$(LI $(BUGZILLA 5922): inline assembler - referencing immutable variable values fails) +$(LI $(BUGZILLA 6166): Named return value optimization not dealt with in inline assembler) +$(LI $(BUGZILLA 6459): Inline assembler does not work well for 64 bit registers R8..R15) +$(LI $(BUGZILLA 7387): call instruction does not understand $) +$(LI $(BUGZILLA 10966): Optimizer generates wrong code with try-catch) +$(LI $(BUGZILLA 12490): No "Error: , has no effect" Error for comma expression LHS) +$(LI $(BUGZILLA 12730): lea instruction accepts subtraction of scaling register but actually adds) +$(LI $(BUGZILLA 12832): asm movdqu accepts wrong operand size) +$(LI $(BUGZILLA 13215): Error message with static this array assignment) +$(LI $(BUGZILLA 13957): 64 bit C ABI not followed for passing structs with floating+integer types) +$(LI $(BUGZILLA 14203): Return of floating point values from extern$(LPAREN)C++$(RPAREN) member functions does not match dmc) +$(LI $(BUGZILLA 14458): very slow ubyte[] assignment $(LPAREN)dmd doesn't use memset$(RPAREN)) +$(LI $(BUGZILLA 14872): [2.068.2] Label address in asm [x86-64]) +$(LI $(BUGZILLA 15103): Improve declaration / initialization syntax error message) +$(LI $(BUGZILLA 15257): __traits$(LPAREN)compiles, …$(RPAREN) with malformed inline asm silently ends compilation) +$(LI $(BUGZILLA 15745): Inline Assembly stomped on by Profiling) +$(LI $(BUGZILLA 16044): __traits$(LPAREN)allMembers$(RPAREN) returns empty tuple for subpackages) +$(LI $(BUGZILLA 16092): AVX registers YMM0-YMM7 are inaccessible to 32-bit asm) +$(LI $(BUGZILLA 16268): Wrong loop optimization in code with integer overflow) +$(LI $(BUGZILLA 16317): Wrong binop evaluation/load order when optimizing) +$(LI $(BUGZILLA 16857): inline assembler reverses operands of VPEXTRW instruction) +$(LI $(BUGZILLA 16963): Forward reference label name resolution in asm statement) +$(LI $(BUGZILLA 17617): No RIP relative addressing available in x64 inline assembly $(LPAREN)iasm$(RPAREN)) +$(LI $(BUGZILLA 17720): Wrong code using vector extensions with different types) +$(LI $(BUGZILLA 17965): Usage of the FPU while function result already in right XMM registers) +$(LI $(BUGZILLA 18373): The inline assembler parser allows strange constructs) +$(LI $(BUGZILLA 18748): bt instruction with immediate offset uses 64-bit variant for 32-bit data) +$(LI $(BUGZILLA 18749): bt instruction using 64-bit register for 32-bit offset) +$(LI $(BUGZILLA 19210): Poor error message for `return` function parameter that is not `ref`) +$(LI $(BUGZILLA 19384): [Codegen] Address of stack temporary is returned) +$(LI $(BUGZILLA 19590): __traits allMembers should put fully qualified names for imports) +$(LI $(BUGZILLA 19729): Constructor overloads coming from mixin are not resolved) +$(LI $(BUGZILLA 19846): zero size function parameter such as byte[0] causes code to not be executed) +$(LI $(BUGZILLA 20017): JSON $(LPAREN)-X$(RPAREN) compilerInfo.architectures generation depends on params.isXXX for CPU detection) +$(LI $(BUGZILLA 20162): Sign Extension for ?: optimization done wrong) +$(LI $(BUGZILLA 20363): painting XMM registers as integers leads to codegen bugs) +$(LI $(BUGZILLA 20422): confusing error "new can only create structs, dynamic arrays or class objects, not int[]'s") +$(LI $(BUGZILLA 20761): __traits$(LPAREN)isSame$(RPAREN) for alias tuples is broken and underspecified) +$(LI $(BUGZILLA 20831): __traits$(LPAREN)getAttributes$(RPAREN) failes to compile when used on a parameter with no name) +$(LI $(BUGZILLA 20911): Documentation for test/unit is non-existant) +$(LI $(BUGZILLA 20934): preview=dtorfields segfaults for disabled/extern constructors) +$(LI $(BUGZILLA 20938): Cannot create const arrays mixing immutable and mutable structs with indirections) +$(LI $(BUGZILLA 20963): wrong code for cast$(LPAREN)double$(RPAREN)anUlong) +$(LI $(BUGZILLA 20995): Range violation with -preview=dip1021) +$(LI $(BUGZILLA 21001): Private alias becomes public if used before declaration) +$(LI $(BUGZILLA 21019): Azure pipelines Windows_VisualD win32-ldc fails with Heisenbug) +$(LI $(BUGZILLA 21037): AVX code sometimes fails to set VEX prefix) +$(LI $(BUGZILLA 21038): wchar and dchar string alignment should be 2 and 4, respectively) +$(LI $(BUGZILLA 21040): SIMD: illegal instruction using 32-byte operations on AVX) +$(LI $(BUGZILLA 21050): __traits$(LPAREN)getOverloads$(RPAREN) for templates returns incorrect symbol for the first overload) +$(LI $(BUGZILLA 21053): Test Suite run.d is built with compiler under test, must be build with bootstrap dmd) +$(LI $(BUGZILLA 21058): __traits$(LPAREN)getOverloads$(RPAREN) forgets "this" with third argument or if first overload is a template) +$(LI $(BUGZILLA 21082): Testsuite fails on OSX $(LPAREN)runnable/test16096.sh with asserts on$(RPAREN)) +$(LI $(BUGZILLA 21089): With vm.overcommit_memory=0, DMD can't link if it uses more than half the total $(LPAREN)ram+swap$(RPAREN) memory in the system.) +$(LI $(BUGZILLA 21092): [ICE] Segmentation fault in ExpressionPrettyPrintVisitor::visit$(LPAREN)CommaExp*$(RPAREN) at dmd/hdrgen.d:2293) +$(LI $(BUGZILLA 21117): When compiler segfaults running autotester, cannot tell which file it was testing) +$(LI $(BUGZILLA 21120): Inconsistent mangling of __init symbol) +$(LI $(BUGZILLA 21153): DWARF: DMD emits the mangled name for DW_AT_name) +$(LI $(BUGZILLA 21154): DWARF: shared types are not represented) +$(LI $(BUGZILLA 21164): segfault on incomplete static if) +$(LI $(BUGZILLA 21181): Inline Assmbler compiles long ptr as a byte operation for 32 bit compiles) +$(LI $(BUGZILLA 21198): Inout copy constructor on union field does not prevent copy-initialization of union) +$(LI $(BUGZILLA 21208): [ICE] dtoh with enums) +$(LI $(BUGZILLA 21213): preview=dtorfields with strict attributes in base class constructor) +$(LI $(BUGZILLA 21217): C++ header generator shouldn't emit private enums) +$(LI $(BUGZILLA 21219): Invalid C++ header generated for extern$(LPAREN)C++, [class|struct]$(RPAREN)) +$(LI $(BUGZILLA 21225): preview=dtorfields inserts unnecessary dtor call in nothrow ctors) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 1995): invalid paths feed to -J option should be warned) +$(LI $(BUGZILLA 12223): __traits$(LPAREN)getMember,...$(RPAREN) needed for aliases) +$(LI $(BUGZILLA 14120): iasm is missing pause instruction) +$(LI $(BUGZILLA 14697): Add support for pclmulqdq instruction to dmd's inline assembler) +$(LI $(BUGZILLA 14936): Dividing by a power of 2 slow on 32bit) +$(LI $(BUGZILLA 19277): storage class used in alias statement has no effect) +$(LI $(BUGZILLA 19663): On x86_64 the fabs intrinsic should use SSE) +$(LI $(BUGZILLA 19705): Static foreach slow for numeric ranges) +$(LI $(BUGZILLA 20931): code which was executed at ctfe should be accounted for in coverage) +$(LI $(BUGZILLA 20990): Optimizer should move cold branches to the end of the function) +$(LI $(BUGZILLA 21060): ICE in semantic, at d/dmd/dstruct.c:1224) +$(LI $(BUGZILLA 21159): DWARF: DW_AT_pure should be emitted for pure functions) +) +$(BUGSTITLE_BUGZILLA Phobos regressions, + +$(LI $(BUGZILLA 21129): [REG2.090] std.range.only broken for reference conversions of local copies of parameters) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 7033): File.rawWrite is slow on Windows) +$(LI $(BUGZILLA 12521): std.getopt does not conform to documentation) +$(LI $(BUGZILLA 20370): On POSIX, std.file.copy only copies the file times at second precision) +$(LI $(BUGZILLA 20765): Can't run processes with relative paths when specifying a working directory) +$(LI $(BUGZILLA 20929): std.experimental.allocator.expandArray's range-based overload fails to instantiate for char and wchar arrays.) +$(LI $(BUGZILLA 20949): std.range.popFront is unsafe in release mode) +$(LI $(BUGZILLA 20984): Heisenbug: FreeBSD64 Phobos random test suite failure in std/process) +$(LI $(BUGZILLA 21021): std.variant confused by alias this when struct larger than maxDataSize) +$(LI $(BUGZILLA 21148): Semaphoreci: core.exception.AssertError@std/file.d$(LPAREN)1929$(RPAREN): unittest failure) +$(LI $(BUGZILLA 21182): asm code is missing `int ptr` and so defaults to byte op) +$(LI $(BUGZILLA 21183): schwartzSort does not strip const) +$(LI $(BUGZILLA 21191): min should be stable: when in doubt, return the first argument) +$(LI $(BUGZILLA 21199): Nullable.apply should take string expression like rest of Phobos) +$(LI $(BUGZILLA 21210): std.traits : isAssignable false positive on disabled copy struct) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 20889): Support construction of std.bigint.BigInt from a sign and a byte-array magnitude) +$(LI $(BUGZILLA 21113): std.file.thisExePath on NetBSD depends upon the /proc filesystem) +$(LI $(BUGZILLA 21131): Appender with string does not process UTF input ranges properly) +$(LI $(BUGZILLA 21201): let std.uuid.parseUUID accept input ranges whose elements are char or wchar, not just dchar) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 19554): [2.084.0] Confusing message - Warning: struct Foo has method toHash) +$(LI $(BUGZILLA 20910): Default unittest runner reports wrong unittest count) +$(LI $(BUGZILLA 21029): Remove __ArrayEq which the compiler no longer uses as of DMD PR #11212) +$(LI $(BUGZILLA 21055): core.stdc.stdarg is not @nogc) +$(LI $(BUGZILLA 21116): onArrayCastError is horribly unsafe) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 21026): add core.bitop.byteswap$(LPAREN)ushort$(RPAREN)) +$(LI $(BUGZILLA 21070): -profile=gc makes the program much slower) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 13569): Inconsistent integer divide by zero behavior and spec) +) +) +$(D_CONTRIBUTORS_HEADER 49) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR Adela Vais) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Andrej Mitrovic) + $(D_CONTRIBUTOR Andrey Zherikov) + $(D_CONTRIBUTOR Anton Oks) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR canopyofstars) + $(D_CONTRIBUTOR Denis Feklushkin) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR Euan Torano) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR H. S. Teoh) + $(D_CONTRIBUTOR Harry Gillanders) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR Lance Bachmeier) + $(D_CONTRIBUTOR Lucien Perregaux) + $(D_CONTRIBUTOR Luhrel) + $(D_CONTRIBUTOR Mark) + $(D_CONTRIBUTOR Markus Laker) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Nils Lankila) + $(D_CONTRIBUTOR nordlow) + $(D_CONTRIBUTOR Olivier Léobal) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Richard Manthorpe) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR Stefan Koch) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Tim Schendekehl) + $(D_CONTRIBUTOR Vlad Nastase) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR سليمان السهمي (Suleyman Sahmi)) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.094.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.094.1.dd b/changelog/2.094.1.dd new file mode 100644 index 0000000000..08acd2414b --- /dev/null +++ b/changelog/2.094.1.dd @@ -0,0 +1,54 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 18, 2020, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 6 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 11 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 21272): Overzealous and inconsistent foreach shadowing deprecations for nested functions) +$(LI $(BUGZILLA 21282): mixin of AliasSeq "cannot alias an expression") +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 15909): Duplicate case error reports characters as numbers) +$(LI $(BUGZILLA 21283): [C++] Wrong mangling for ref of parameter pack) +$(LI $(BUGZILLA 21299): [LINK] undefined reference to dmd.root.stringtable.StringValue!$(LPAREN)Type$(RPAREN).StringValue.lstring$(LPAREN)$(RPAREN)) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 21315): TypeInfo_StaticArray.swap is broken) +) +) +$(D_CONTRIBUTORS_HEADER 11) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Luhrel) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Sebastian Wilzbach) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.094.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.094.2.dd b/changelog/2.094.2.dd new file mode 100644 index 0000000000..d209e69889 --- /dev/null +++ b/changelog/2.094.2.dd @@ -0,0 +1,92 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Nov 20, 2020, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 1 major change and 14 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 10 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 musl-32bits,Support time64 changes for `CRuntime_Musl`)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 musl-32bits,Support time64 changes for `CRuntime_Musl`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/musl-32bits.dd) +$(P +Up to v1.1.24, Musl used a 32 bits `time_t` on 32 bits architectures. +Since v1.2.0, `time_t` is now always 64 bits. +From this release, druntime will also default to a 64 bits `time_t` +on 32 bits architecture, unless the `CRuntime_Musl_Pre_Time64w` is provided. +) + +$(P +This change should only affect packagers for Musl-based systems who support +32 bits architectures (64 bits architectures already use 64 bits `time_t`), +who now need to define `CRuntime_Musl_Pre_Time64` both when building +druntime / Phobos and in the default configuration, if the linked Musl is < 1.2.0. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 21285): Delegate covariance broken between 2.092 and 2.094 $(LPAREN)git master$(RPAREN).) +$(LI $(BUGZILLA 21372): False deprecation raised for templated overloaded struct method) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 20324): Calling __traits$(LPAREN)getUnitTests$(RPAREN) on a template causes compiler segfault) +$(LI $(BUGZILLA 21330): __traits$(LPAREN)getUnitTests$(RPAREN) should include unittests from anonymous mixins) +$(LI $(BUGZILLA 21353): 'With$(LPAREN)$(RPAREN)' statement ignores symbol visibility in some cases.) +$(LI $(BUGZILLA 21398): Name clash between import and method triggers a segfault) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 21256): Segfault with Appender!string.init.toString$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 21337): join can iterates ranges multiple times) +$(LI $(BUGZILLA 21383): std.random.uniform!T$(LPAREN)urng$(RPAREN) when T is dchar disregards urng and always uses a thread-local random) +$(LI $(BUGZILLA 21384): std.random.uniform!T$(LPAREN)$(RPAREN) and std.random.uniform!T$(LPAREN)urng$(RPAREN) when T is dchar with any qualifiers can exceed dchar.max) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 21323): $(LPAREN)64-bit Windows only$(RPAREN) core.stdcpp.vector could not have core.stdcpp.vector as element) +$(LI $(BUGZILLA 21344): core.stdcpp.string.basic_string does not implement opEquals) +$(LI $(BUGZILLA 21346): core.stdcpp.vector.vector does not implement opEquals) +$(LI $(BUGZILLA 21365): TypeInfo.swap must not allow reachable memory to be freed if interrupted by a garbage collection pass) +) +) +$(D_CONTRIBUTORS_HEADER 10) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Kazuya Takahashi) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Richard Manthorpe) + $(D_CONTRIBUTOR Simen Kjærås) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.094.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.095.0.dd b/changelog/2.095.0.dd new file mode 100644 index 0000000000..ac8a9c9269 --- /dev/null +++ b/changelog/2.095.0.dd @@ -0,0 +1,833 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 01, 2021, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 27 major changes and 78 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 61 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 deprecate_visibility,Deprecate bypassing of symbol visibility when doing overload resolution)) +$(LI $(RELATIVE_LINK2 deprecation-context,Deprecation triggered inside of templates now show instantiation trace)) +$(LI $(RELATIVE_LINK2 dtoh-improvements,Improvements for the C++ header generation)) +$(LI $(RELATIVE_LINK2 duplicate-implementations-deprecation,Diagnostics for conflicting function definitions within a module)) +$(LI $(RELATIVE_LINK2 extern-pascal,`extern(Pascal)` has been removed)) +$(LI $(RELATIVE_LINK2 extern-std-cpp20,The compiler now accepts `-extern-std=c++20`)) +$(LI $(RELATIVE_LINK2 extern-std-standard,C++ compability standard now c++11 by default)) +$(LI $(RELATIVE_LINK2 inclusive-incontracts,Add `-preview=inclusiveincontracts`: `in` contracts must be an explicit superset of the parent `in` contracts.)) +$(LI $(RELATIVE_LINK2 objc_protocols,Add support for Objective-C protocols)) +$(LI $(RELATIVE_LINK2 pragma_inline_ctfe,Allow any compile-time argument in pragma(inline))) +$(LI $(RELATIVE_LINK2 traits-getcppnamespaces,Add `__traits(getCppNamespaces, symbol)` to retrieve the C++ namespaces a symbol resides in.)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 accidentally-exposed-sigs,Variables `suspendSignalNumber` and `resumeSignalNumber` are now private)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 conv_parse_count,Return the number of characters consumed by `std.conv.parse`)) +$(LI $(RELATIVE_LINK2 deprecate-stdio-bindings,Deprecate `std.stdio.getdelim` and `std.stdio.getline`)) +$(LI $(RELATIVE_LINK2 jsonvalue-get-integer-conv,Add integer conversions in `JSONValue.get`)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 add-ability-for-specify-version-range-for-commandline-commands,All commands now accept a version specification)) +$(LI $(RELATIVE_LINK2 auto-exclude-main-from-other-configs,Dub will now automatically exclude `mainSourceFile` from other configurations)) +$(LI $(RELATIVE_LINK2 betterc-generated-in-visuald,Add support for -betterC compiler flag to the visuald project generator)) +$(LI $(RELATIVE_LINK2 cache-generated-test-config,Caching of generated unittest runner (dub test))) +$(LI $(RELATIVE_LINK2 dependency-build-settings,Allow custom build settings to be defined for dependencies)) +$(LI $(RELATIVE_LINK2 dont-propagate-flags,`DFLAGS` and `LFLAGS` no longer propagate to nested `dub` invocations)) +$(LI $(RELATIVE_LINK2 env-d-compiler,Use DC environment variable as default D compiler)) +$(LI $(RELATIVE_LINK2 fix-2051,Fix #2051 "Running unit tests from DUB single file packages fails")) +$(LI $(RELATIVE_LINK2 improved-ldc-cross-compile,Improve ldc cross compilation)) +$(LI $(RELATIVE_LINK2 improved-list-command,Filter ability for list command)) +$(LI $(RELATIVE_LINK2 support-for-.netrc-file-added,Support for .netrc file added)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 deprecate_visibility,Deprecate bypassing of symbol visibility when doing overload resolution) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecate_visibility.dd) +$(P +If an aggregate declaration contains a private method and a public method in the +same overload set it is possible to call the private method from a different module. +) + +$(P +Example: +) +``` +============================== +module foo; + +struct Foo +{ + import std : writeln; + + private int _x; + + private ref int x() return + { + writeln("ref int"); + return _x; + } + + int x() const + { + writeln("int"); + return _x; + } +} +============================ + +--- +$(P +module main; +) + +$(P +void main() +{ + import std : writeln; + import foo : Foo; +) + +$(P + auto f = Foo(); + f.x = 3; // ok to call private method + writeln(f); +} +=========================== +) +``` + +Starting from this version a deprecation message will be issued +in such situations. +) + +$(LI $(LNAME2 deprecation-context,Deprecation triggered inside of templates now show instantiation trace) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecation-context.dd) +$(P +A common issue when dealing with deprecations is to have it trigger in library code, +for example having a `deprecated` `alias this`, or a hook (`opApply`, range primitives...) +being called by a function deeply nested inside Phobos. +) + +$(P +In such cases, finding out where the instantiation comes from can be quite tedious. +From this release, if a deprecation is triggered inside a template, the compiler +will show the template instantiation trace, just like it already does on error. +The same limit apply (6 frames, recursive templates are compressed), and `-v` +can be used to lift it. +) +) + +$(LI $(LNAME2 dtoh-improvements,Improvements for the C++ header generation) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dtoh-improvements.dd) +$(P +The following features/bugfixes/improvements were implemented for the +experimental C++ header generator: +) + +$(P +- Enums are no longer emitted in macros and `enum class` is used when the + C++ standard set from `-extern-std=` is c++11 or later. +- Forward referenced declarations are now properly indented. +- Default functions parameters are properly emitted +- Tuple members/parameters/variables are emitted as individual variables + using the compiler internal names instead of causing an assertion failure. +- Interfaces are now emitted as base classes. +- Aggregate members will be emitted with proper protection levels +- Protected enums in aggregates are emitted again +- Private member methods are no longer emitted +- No auto-generated default constructor for unions +- No longer ignores declarations nested inside an extern block, + e.g. `extern(D) extern(C++) void foo() {} ` +- Opaque enums no longer cause segfaults & are properly exported for C++ 11 +- C++11 constructs are avoided when compiling with `-extern-std=c++98`. +- Using `typeof(null)` type no longer causes an assertion failure. +- The base type of floating point literals is propagated into the header +- `NaN`, `Infinity` are emitted using `NAN`/`INFINITY` from `math.h`. +- Final classes are marked as `final` +- `immutable` is emitted as `const` instead of mutable +- Identifier chains in templates are printed completely +- Proper vtable layout is ensured by emitting hidden placeholders for + virtual functions that are not `extern(C|C++)`. +- Fixed missing `const` for class members/methods +- Templated class declarations are now emitted +- Manifest constants that are not `extern(C|C++)` are no longer emitted. +) + +$(P +Note: The header generator is still considerer experimental, so please submit + any bugs encountered to [the bug tracker](https://issues.dlang.org). +) +) + +$(LI $(LNAME2 duplicate-implementations-deprecation,Diagnostics for conflicting function definitions within a module) +$(CHANGELOG_SOURCE_FILE dmd, changelog/duplicate-implementations-deprecation.dd) +$(P +Previously, multiple definitions of identical functions within a module were not +recognized, although they have the same mangling. This was problematic because a +binary cannot contain multiple definitions of a symbol, which caused undefined +behavior depending on the compiler backend. +) + +$(P +DMD will now raise an error message if there are conflicting implementations +within a single module: +) + +--- +void foo() {} +void foo() {} // error +--- + +$(P +Multiple declarations are still allowed as long as there is at most one definition: +) + +--- +void bar(int); +void bar(int) { } +void bar(int); +--- + +$(P +DMD will issue a deprecation for mangling schemes that don't support overloading +(`extern(C|Windows|System)`): +) + +--- +extern(C): +void foo(int) { } +void foo(double) { } // deprecation +--- + +$(P +This deprecation will become an error in 2.105. +) +) + +$(LI $(LNAME2 extern-pascal,`extern(Pascal)` has been removed) +$(CHANGELOG_SOURCE_FILE dmd, changelog/extern-pascal.dd) +$(P +This unused linkage was deprecated in $(LINK2 https://dlang.org/changelog/2.084.0.html#deprecated_extern_pascal, v2.084.0) and has now been removed. +) +) + +$(LI $(LNAME2 extern-std-cpp20,The compiler now accepts `-extern-std=c++20`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/extern-std-cpp20.dd) +$(P +The compiler now accepts c++20 as a supported standard for `-extern-std=`. +Currently this only changes the value of `__traits(getTargetInfo, "cppStd")`, +though new types may be added in the future. +) +) + +$(LI $(LNAME2 extern-std-standard,C++ compability standard now c++11 by default) +$(CHANGELOG_SOURCE_FILE dmd, changelog/extern-std-standard.dd) +$(P +The default setting for `-extern-std=` has been updated to c++11. +) + +$(P +Declarations with `extern(C++)` linkage are no longer guaranteed to link with +code compiled by a C++98 compiler. Additionally, C++ headers generated by `-HC` +will use constructs only available from C++11 onwards. +) + +$(P +If compatibility with older C++ compilers is required, you must now pass +`-extern-std=c++98` on the command-line. +) +) + +$(LI $(LNAME2 inclusive-incontracts,Add `-preview=inclusiveincontracts`: `in` contracts must be an explicit superset of the parent `in` contracts.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/inclusive-incontracts.dd) +$(P +As per Liskov, `in` contracts can only loosen the conditions placed on the method they appear on. +Currently this is enforced by automatically "oring" together the `in` contract with the `in` contract +on the parent method, creating a combined contract that is necessarily looser than the parent. +) + +$(P +However, this leads to odd behavior like this code passing: +) + +``` +class A +{ + void foo(int i) in (i > 0) { } +} +class B : A +{ + void foo(int i) in (i < 0) { } +} +unittest { (new B).foo(5); } +``` + +$(P +That is because the `in` contract of `B.foo` is $(I implicitly) `super.in() || i < 0`, ie. `i > 0 || i < 0` +) + +$(P +With `-preview=inclusiveincontracts`, this code will now fail with an `AssertError`. +To reach the previous behavior, you would have to write out `in (i > 0 || i < 0)`; +that is, you explicitly include the parent's `in` contract in the child's. +) +) + +$(LI $(LNAME2 objc_protocols,Add support for Objective-C protocols) +$(CHANGELOG_SOURCE_FILE dmd, changelog/objc_protocols.dd) +$(P +It's now possible to declare [Objective-C protocols][objc_protocol]. In D, this +is declared using the `interface` keyword. +) + +$(P +To match the behavior of protocols in Objective-C, some additional changes have +been made: +) + +$(P +* It's possible to declare optional methods in an interface. This is done +with the `@optional` User Defined Attribute, available in the `core.attributes` +module. An optional method is a method that does **not** have to be implemented +in the class that implements the interface. To safely call an optional method, +a runtime check should be performed to make sure the receiver implements the +method. +) + +$(P +* It's possible to have `static` methods in an interface. This method is +required to be implemented in the class that implements the interface (unless +it's declared optional). Unlike in `extern (D)` interfaces, `static` methods in +`extern (Objective-C)` cannot have a body. +) + +$(P +Example: +) + +--- +import core.attribute : optional, selector; +import std.stdio : writeln; + +struct objc_selector; +alias SEL = objc_selector*; + +extern (C) SEL sel_registerName(in char* str); + +extern (Objective-C) +extern class NSObject +{ + static NSObject alloc() @selector("alloc"); + NSObject init() @selector("init"); +} + +extern (Objective-C) +interface Foo +{ + bool respondsToSelector(SEL sel) @selector("respondsToSelector:"); + void foo() @selector("foo"); + + // this is an optional method + @optional void bar() @selector("bar"); +} + +extern (Objective-C) +class Bar : NSObject, Foo +{ + override static Bar alloc() @selector("alloc"); + override Bar init() @selector("init"); + + bool respondsToSelector(SEL sel) @selector("respondsToSelector:"); + + void foo() @selector("foo") + { + writeln("foo"); + } +} + +void main() +{ + Foo f = Bar.alloc.init; + + // check, at runtime, if the instance `f` implements the method `bar` + if (f.respondsToSelector(sel_registerName("bar"))) + f.bar(); + else + f.foo(); +} +--- + +$(P +[objc_protocol][https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithProtocols/WorkingwithProtocols.html] +) +) + +$(LI $(LNAME2 pragma_inline_ctfe,Allow any compile-time argument in pragma(inline)) +$(CHANGELOG_SOURCE_FILE dmd, changelog/pragma_inline_ctfe.dd) +$(P +Previously only `true` or `false` literals were allowed (the spec stated that integers worked, but they did not). +) + +$(P +Now the `pragma` can receive any compile-time expression convertible to `bool`, this expression will be evaluated only when the target function is actually used. +) + +$(P +For example, in the following code all three functions should be inlined: +) + +--- +pragma(inline, canInline("func1")) +void func1() {} + +void func2() +{ + pragma(inline, canInline(__traits(identifier, __traits(parent, {})))); +} + +pragma(inline, canInline("func3") || true) +void func3() {} + +int canInline(string fname) +{ + switch (fname) + { + case "func1": + case "func2": + return 1; + default: + return 0; + } +} + +void main() +{ + func1(); + func2(); + func3(); +} +--- +) + +$(LI $(LNAME2 traits-getcppnamespaces,Add `__traits(getCppNamespaces, symbol)` to retrieve the C++ namespaces a symbol resides in.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/traits-getcppnamespaces.dd) +$(P +This new trait returns a tuple of strings representing the namespace(s) the symbol resides in. +This enables determining what namespaces a given symbol resides in for use in reflection, and can be used directly with an `extern(C++)` declaration as demonstrated below. +) + +``` +extern(C++, "ns") +struct Foo {} +static assert(__traits(getCppNamespaces, Foo)[0] == "ns"); +struct Bar {} +static assert(!__traits(getCppNamespaces, Foo).length); +extern(C++, __traits(getCppNamespaces, Foo)) struct Baz {} +static assert(__traits(getCppNamespaces, Foo) == __traits(getCppNamespaces, Baz)); +``` +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 accidentally-exposed-sigs,Variables `suspendSignalNumber` and `resumeSignalNumber` are now private) +$(CHANGELOG_SOURCE_FILE druntime, changelog/accidentally-exposed-sigs.dd) +$(P +These variables, which are in `core.thread.osthread`, were accidentally exposed. +They shouldn't be accessed directly and have been made private. +In order to set GC signals, one should call `thread_setGCSignals` instead. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 conv_parse_count,Return the number of characters consumed by `std.conv.parse`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/conv_parse_count.dd) +$(P +By setting the flag `doCount` to `Yes.doCount`, the function returns a named tuple. +The tuple contains the fields `data` and `count`. +The field `data` is of type `Target` and it contains the result of the original function. +The field `count` is of type `size_t` and it contains the number of characters consumed. +The function is keeping its original behaviour otherwise. +Example: +) +------- +import std.typecons : Flag, Yes, No; + +string s1 = "123"; +auto a1 = parse!(int, string, Yes.doCount)(s1); +assert(a1.data == 123 && a1.count == 3); +------- +) + +$(LI $(LNAME2 deprecate-stdio-bindings,Deprecate `std.stdio.getdelim` and `std.stdio.getline`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/deprecate-stdio-bindings.dd) +$(P +The publicly available `extern(C)` bindings for `getdelim` and `getline` in +`std.stdio` have been deprecated. Any code that still needs it can import the +symbol from `core.sys.posix.stdio` in druntime instead. +) +) + +$(LI $(LNAME2 jsonvalue-get-integer-conv,Add integer conversions in `JSONValue.get`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/jsonvalue-get-integer-conv.dd) +$(P +`JSONValue.get` now allows to convert a stored `uinteger` or `integer` into any +signed or unsigned integer. The conversion is performed with `std.conv.to`, and +throws a `ConvException` in case of an integer overflow; +) + +------- +auto json = parseJSON(`{"a": 123}`); +writeln(json["a"].get!ubyte); +------- +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 add-ability-for-specify-version-range-for-commandline-commands,All commands now accept a version specification) +$(CHANGELOG_SOURCE_FILE dub, changelog/add-ability-for-specify-version-range-for-commandline-commands.dd) +$(P +Before this release dub could only get an exact version for some commands +(`describe`, `generate`, `fetch`, etc...). All commands now accept a version specification, +such as can be found in `dub.json` / `dub.sdl`: +) + +$(P + dub fetch 'foo@>0.2.0' + dub describe foo@'>=0.3.0 <1.0.0' +) + +$(P +Note that commands such as `describe` will still not fetch from the network. +) +) + +$(LI $(LNAME2 auto-exclude-main-from-other-configs,Dub will now automatically exclude `mainSourceFile` from other configurations) +$(CHANGELOG_SOURCE_FILE dub, changelog/auto-exclude-main-from-other-configs.dd) +$(P +By default, Dub uses all files it can find under its `sourcePaths`. +However, a common pattern when dealing with multiple targets is to use +configurations to represent said targets. In the case those targets are executables, +users would be forced to add main files from other configurations to the +`excludedSourceFiles` list, or store the main in a different directory outside of +the sourcePaths. +) + +$(P +To simplify this workflow, Dub will now exclude files listed in mainSourceFile +for other configuration. In case this is not desirable, the files need to be manually +added to the `sourceFiles` list. +) +) + +$(LI $(LNAME2 betterc-generated-in-visuald,Add support for -betterC compiler flag to the visuald project generator) +$(CHANGELOG_SOURCE_FILE dub, changelog/betterc-generated-in-visuald.dd) +$(P +If betterC is specified in the buildOptions, visuald project files will also be +configured to use betterC. +) +) + +$(LI $(LNAME2 cache-generated-test-config,Caching of generated unittest runner (dub test)) +$(CHANGELOG_SOURCE_FILE dub, changelog/cache-generated-test-config.dd) +$(P +For projects without a user-defined unittest configuration `dub test` generates a main file automatically. +This main file is now being cached and won't be regenerated won subsequent runs without file changes. +) +) + +$(LI $(LNAME2 dependency-build-settings,Allow custom build settings to be defined for dependencies) +$(CHANGELOG_SOURCE_FILE dub, changelog/dependency-build-settings.dd) +$(P +For example: +) +--- +{ + "name": "example", + "dependencies": { + "vibe-d": { "version" : "~>0.9.2", "dflags" : ["-preview=in"] } + } +} +--- + +$(P +In this example, `-preview=in` will be applied to `vibe-d` and all of its dependencies. +Any $(LINK2 build settings, https://dub.pm/package-format-json.html#build-settings) field will be parsed, +however only `dflags` is taken into account when compiling for now. +) +) + +$(LI $(LNAME2 dont-propagate-flags,`DFLAGS` and `LFLAGS` no longer propagate to nested `dub` invocations) +$(CHANGELOG_SOURCE_FILE dub, changelog/dont-propagate-flags.dd) +$(P +`DFLAGS` and `LFLAGS` will no longer be exported as environment variables by default +when invoking pre-generate, pre-build, pre-run, post-generate, post-build, or post-run commands. +) + +$(P +If the previous behavior is still desired, they can be accessed using `$DFLAGS` and `$LFLAGS` in dub.json +E.g.: +`preGenerateCommands : ["DFLAGS=$DFLAGS env | grep DFLAGS"]` +) + +$(P +will output DFLAGS environment variable with all the dflags used. +) +) + +$(LI $(LNAME2 env-d-compiler,Use DC environment variable as default D compiler) +$(CHANGELOG_SOURCE_FILE dub, changelog/env-d-compiler.dd) +$(P +dub now respects the `DC` environment variable, meaning that `DC=ldc2 dub build` will behave as `dub build --compiler=ldc2`. +In case both are supplied, the `--compiler` switch still has priority. +Note that when DUB recursively invokes itself, for example in `preGenerateCommands`, +it sets the `DC` variable to the compiler it is using, meaning that nested dub invocation will now use the same compiler. +) +) + +$(LI $(LNAME2 fix-2051,Fix #2051 "Running unit tests from DUB single file packages fails") +$(CHANGELOG_SOURCE_FILE dub, changelog/fix-2051.dd) +$(P +Now dub is capable run test command in single mode like: `dub test --single yoursinglefile.d` +) +) + +$(LI $(LNAME2 improved-ldc-cross-compile,Improve ldc cross compilation) +$(CHANGELOG_SOURCE_FILE dub, changelog/improved-ldc-cross-compile.dd) +$(P +Enables co-existence and parallel compilation of the same project with different settings (e.g. cross compilation) by moving `.dub/obj` to `$DUB_TARGET_PATH/obj`. +) +) + +$(LI $(LNAME2 improved-list-command,Filter ability for list command) +$(CHANGELOG_SOURCE_FILE dub, changelog/improved-list-command.dd) +$(P +For list command added optional filtration by name and version specification: +) + +$(P + dub list foo + dub list foo@'>=0.1.0 <1.0.0' +) +) + +$(LI $(LNAME2 support-for-.netrc-file-added,Support for .netrc file added) +$(CHANGELOG_SOURCE_FILE dub, changelog/support-for-.netrc-file-added.dd) +$(P +Basic authentication credentials defined in .netrc file +will now be taken into account while connecting to secured +repositories. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 20608): [REG2.087] Cannot pass tuple.expand to auto ref T... template argument pack) +$(LI $(BUGZILLA 21282): mixin of AliasSeq "cannot alias an expression") +$(LI $(BUGZILLA 21294): [REG 2.095]: DMD fails to link since PR11743) +$(LI $(BUGZILLA 21312): [REG 2.095] Newly triggered is not an lvalue and cannot be modified) +$(LI $(BUGZILLA 21325): Flags not set for ?: evaluation with floating point operands) +$(LI $(BUGZILLA 21328): Forwarding static float array element inside a lambda crashes dmd backend) +$(LI $(BUGZILLA 21357): [REG2.093] postblit aliases old and new struct pointers) +$(LI $(BUGZILLA 21364): Improperly aligned struct when one member is a GPR and the other is an XMM) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 3713): Tail call optimization not enabled with the ?: operator) +$(LI $(BUGZILLA 8156): Very slow compilation with string-imported file ~100 MiB) +$(LI $(BUGZILLA 10664): Win64: exception handling does not work with COMDAT folding) +$(LI $(BUGZILLA 11049): array bounds error uses module file name rather than file name modified by #line directive) +$(LI $(BUGZILLA 11435): Pushing indirect ref to byte or short can read beyond edge of valid memory) +$(LI $(BUGZILLA 14708): destructor for temporary not called during stack unwinding) +$(LI $(BUGZILLA 15909): Duplicate case error reports characters as numbers) +$(LI $(BUGZILLA 19754): cast$(LPAREN)$(RPAREN) sometimes yields lvalue, sometimes yields rvalue) +$(LI $(BUGZILLA 19970): [CTFE] 0 ptr is not null) +$(LI $(BUGZILLA 20195): -preview=nosharedaccess has some access problems) +$(LI $(BUGZILLA 20604): [ICE] dtoh ICE with nested template structs $(LPAREN)and probably most templates) +$(LI $(BUGZILLA 20652): extern$(LPAREN)C++$(RPAREN) doesn't seem to mangle the types in core.simd right) +$(LI $(BUGZILLA 20714): Struct with postblitting member does not call it's copy constructor) +$(LI $(BUGZILLA 20716): Wrong code/ABI for extern$(LPAREN)C++$(RPAREN) interface method that returns non-POD) +$(LI $(BUGZILLA 20916): hard to find where a deprecation comes from) +$(LI $(BUGZILLA 20965): Implicitly generated postblit overrides disabled copy ctor) +$(LI $(BUGZILLA 20970): Test Suite Azure Pipelines Windows_LDC_Debug x64-debug-ldc failed due to heisenbug) +$(LI $(BUGZILLA 21218): dtoh: protection attributes should be emitted to headers) +$(LI $(BUGZILLA 21227): import$(LPAREN)".\\file"$(RPAREN) doesn't work on Windows) +$(LI $(BUGZILLA 21234): Import expression can read files outside of -J path in case of symlink/hardlink) +$(LI $(BUGZILLA 21246): Compiler must show mismatching types when functions do not properly override) +$(LI $(BUGZILLA 21255): "overload alias ... forward declaration" when overload set of imported template functions is passed to alias template parameter) +$(LI $(BUGZILLA 21271): C++ header generation ignores extern$(LPAREN)D$(RPAREN) class methods affecting vtable layout) +$(LI $(BUGZILLA 21283): [C++] Wrong mangling for ref of parameter pack) +$(LI $(BUGZILLA 21293): dtoh: segfault when encountering opaque enum) +$(LI $(BUGZILLA 21299): [LINK] undefined reference to dmd.root.stringtable.StringValue!$(LPAREN)Type$(RPAREN).StringValue.lstring$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 21300): C++ header generation produce nonsense code on enum with enum as parent) +$(LI $(BUGZILLA 21320): @live mistakes borrowed pointer for owner in parameter) +$(LI $(BUGZILLA 21424): Variable is incremented twice) +$(LI $(BUGZILLA 21464): Superfluous module-level import affects attribute inference) +$(LI $(BUGZILLA 21479): ternary operator returns wrong val with ref return) +$(LI $(BUGZILLA 21514): [ICE] cod1.d:4015: Assertion `retregs || !*pretregs' failed with -m32) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 8044): Print names, not casted values when using enum template parameter) +$(LI $(BUGZILLA 21204): Error in generated copy constructor gives confusing message) +$(LI $(BUGZILLA 21259): struct initialization with deprecated fields should issue deprecation warnings) +$(LI $(BUGZILLA 21275): Overload resolution bypasses private access) +$(LI $(BUGZILLA 21340): extern$(LPAREN)C++,$(LPAREN)emptyTuple$(RPAREN)$(RPAREN) should result in no namespace not an error) +) +$(BUGSTITLE_BUGZILLA Phobos bugs, + +$(LI $(BUGZILLA 13930): std.concurrency can't send immutable AA to another thread) +$(LI $(BUGZILLA 15425): std.traits.hasIndirections fails to recognize nested structs) +$(LI $(BUGZILLA 18789): std.stdio messes up UTF conversions on output) +$(LI $(BUGZILLA 18801): std.stdio.File doesn't work with MSVCRT's UTF-8 mode) +$(LI $(BUGZILLA 20924): std.numeric.gcd cannot be used with const BigInt) +$(LI $(BUGZILLA 21231): Unreachable warning for empty struct in VariantN with preview=fieldwise) +$(LI $(BUGZILLA 21249): clamp$(LPAREN)$(RPAREN) is not stable and is not constrained) +$(LI $(BUGZILLA 21253): Can't compile Variant.visit!$(LPAREN)...$(RPAREN) with generic function) +$(LI $(BUGZILLA 21296): std.variant.Variant cannot be initialized with immutable AA) +$(LI $(BUGZILLA 21302): std.uni's documentation contains a dead link to its source file) +$(LI $(BUGZILLA 21452): isCallable erroneously returns false on function templates) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 6484): compose can't take multi arg functions) +$(LI $(BUGZILLA 20869): `std.algorithm.mutation : move` is overly trusting of `opPostMove`) +$(LI $(BUGZILLA 20980): std.bigint.BigInt: special case x & non-negative int to avoid unnecessary allocation) +$(LI $(BUGZILLA 21233): std.conv.parse doesn't report the number of characters consumed) +$(LI $(BUGZILLA 21237): isLvalueAssignable and isRvalueAssignable should be public) +$(LI $(BUGZILLA 21347): std.functional.adjoin should work in BetterC) +$(LI $(BUGZILLA 21407): Make std.math.NaN and std.math.getNaNPayload work in CTFE) +$(LI $(BUGZILLA 21408): Make std.math.nextUp and nextDown and nextafter work in CTFE for extended-precision real) +$(LI $(BUGZILLA 21430): Add `const` to front, save, & length properties of range returned by std.bitmanip.bitsSet) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 14226): invalid Runtime.traceHandler setup) +$(LI $(BUGZILLA 21421): core.stdcpp.new_.cpp_delete does not work with classes) +$(LI $(BUGZILLA 21441): TypeInfo_Enum.destroy and TypeInfo_Enum.postblit not calling destroy and postblit of base type) +$(LI $(BUGZILLA 21442): Calling AA.remove from a destructor might lead to InvalidMemoryOperationError) +$(LI $(BUGZILLA 21468): Inscrutable template error when core.stdcpp.vector of a struct with a core.stdcpp.vector field is referenced before the struct's definition) +$(LI $(BUGZILLA 21484): Infinite recursion in core.memory : GC.{get,set,clr}Attr$(LPAREN)const scope void*...$(RPAREN)) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 21030): Reduce template function instantiations related to array equality) +$(LI $(BUGZILLA 21417): core.stdcpp.new_.cpp_delete unnecessarily requires destruction to be @nogc) +$(LI $(BUGZILLA 21426): `dup`, `idup` for arrays plus `keys`, `values` for associative arrays: call postblits directly instead of via TypeInfo function pointer) +) +$(BUGSTITLE_BUGZILLA dlang.org bugs, + +$(LI $(BUGZILLA 21189): Plain Old Data and copy constructors) +$(LI $(BUGZILLA 21273): [spec] Inexistent contrast for shell snippets make them unreadable $(LPAREN)CSS$(RPAREN)) +) +$(BUGSTITLE_BUGZILLA Installer bugs, + +$(LI $(BUGZILLA 21433): "bash: line 952: --list-keys: command not found" when running install.sh on Catalina) +$(LI $(BUGZILLA 21439): install.sh is disabled for LDC on FreeBSD) +) +) +$(D_CONTRIBUTORS_HEADER 61) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adela Vais) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Andrey Zherikov) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Brian Schott) + $(D_CONTRIBUTOR Crom (Thibaut CHARLES)) + $(D_CONTRIBUTOR Daniel Graczer) + $(D_CONTRIBUTOR Denis Feklushkin) + $(D_CONTRIBUTOR Dimitar Nestorov) + $(D_CONTRIBUTOR Ernesto Castellotti) + $(D_CONTRIBUTOR Ezneh) + $(D_CONTRIBUTOR godmyoh) + $(D_CONTRIBUTOR Guillaume Piolat) + $(D_CONTRIBUTOR H. S. Teoh) + $(D_CONTRIBUTOR Harry T. Vennik) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Imperatorn) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR James Gray) + $(D_CONTRIBUTOR James Thompson) + $(D_CONTRIBUTOR jmh530) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR K) + $(D_CONTRIBUTOR Lio李歐) + $(D_CONTRIBUTOR Lorenzo Gabriele) + $(D_CONTRIBUTOR Luhrel) + $(D_CONTRIBUTOR Luís Ferreira) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Mihaela Chirea) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR nordlow) + $(D_CONTRIBUTOR Panke) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR phebert5009) + $(D_CONTRIBUTOR Quirin F. Schroll) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Remi Thebault) + $(D_CONTRIBUTOR Roman Chistokhodov) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR Simon Naarmann) + $(D_CONTRIBUTOR starcanopy) + $(D_CONTRIBUTOR Tobias Pankrath) + $(D_CONTRIBUTOR Tomoya Tanjo) + $(D_CONTRIBUTOR Tomáš Chaloupka) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR Yanis Zafirópulos) + $(D_CONTRIBUTOR Ömer Faruk IRMAK) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.095.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.095.1.dd b/changelog/2.095.1.dd new file mode 100644 index 0000000000..649ea154c9 --- /dev/null +++ b/changelog/2.095.1.dd @@ -0,0 +1,66 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 17, 2021, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 11 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 12 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regressions, + +$(LI $(BUGZILLA 21177): printf check does not recognize GNU extensions) +$(LI $(BUGZILLA 21505): Function alias reported as conflicting function) +$(LI $(BUGZILLA 21513): [Reg 2.094.1] Slice assignment segmentation fault) +$(LI $(BUGZILLA 21590): assignment inside assert accepted if -checkaction=context is given) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bugs, + +$(LI $(BUGZILLA 21569): Unable to rebuild DMD build using win32.mak - v2.095.0) +$(LI $(BUGZILLA 21586): Struct dtor is called twice if struct is created inside ternary operator) +$(LI $(BUGZILLA 21591): Mangling problem wrt. backrefs and function types) +$(LI $(BUGZILLA 21614): compiled imports: core.exception.AssertError@src/dmd/semantic3.d$(LPAREN)812$(RPAREN): Assertion failure) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 21567): build.d install fails, can't find dmd.conf) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 20552): Deprecated Nullable.get warning with Appenders) +) +$(BUGSTITLE_BUGZILLA Druntime bugs, + +$(LI $(BUGZILLA 21578): core.atomic.atomicFetchSub for pointers incorrectly calls wrong function from core.internal.atomic) +) +) +$(D_CONTRIBUTORS_HEADER 12) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Lucien Perregaux) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Remi Thebault) + $(D_CONTRIBUTOR Roy Margalit) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.095.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.096.0.dd b/changelog/2.096.0.dd new file mode 100644 index 0000000000..9285dcd1be --- /dev/null +++ b/changelog/2.096.0.dd @@ -0,0 +1,548 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 11, 2021, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 17 major changes and 81 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 54 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 abi-fix-creal,D ABI change on x86_64 Posix targets)) +$(LI $(RELATIVE_LINK2 complex_types,Added `__c_complex_float`, `__c_complex_double`, and `__c_complex_real` types)) +$(LI $(RELATIVE_LINK2 copy-constructor-priority,Having both a copy constructor and a generated postblit is now deprecated)) +$(LI $(RELATIVE_LINK2 ddoc-always-visibility,DMD's JSON output will now always include the protection level)) +$(LI $(RELATIVE_LINK2 ddoc-shared-static-ctor,DMD's JSON output now have distinct types for [shared] module constructor/destructor)) +$(LI $(RELATIVE_LINK2 deprecate_dualcontext,Deprecate local templates that receive local symbols by alias)) +$(LI $(RELATIVE_LINK2 dtoh-improvements,Improvements for the C++ header generation)) +$(LI $(RELATIVE_LINK2 dwarf-switch,Add `-gdwarf=` switch for the DMD compiler.)) +$(LI $(RELATIVE_LINK2 getVisibility,Introduced `__traits(getVisibility, Sym)` as an alias to `getProtection`)) +$(LI $(RELATIVE_LINK2 runtime-synchronized,Plain `synchronized` statements now use run-time allocated mutexes.)) +$(LI $(RELATIVE_LINK2 shortfunctions,Allow shortened function implementations for single-expression functions.)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 callStructDtorsDuringGC,The druntime option `callStructDtorsDuringGC` has been removed)) +$(LI $(RELATIVE_LINK2 freebsd-statvfs,FreeBSD declarations from statvfs that belong in mount have been removed)) +$(LI $(RELATIVE_LINK2 libunwind,Experimental llvm-libunwind based backtrace printing was added)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 deprecate-approxEqual,Deprecate `std.math : approxEqual`)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 dmd-linker-dflags,More 'linker dflags' with DMD)) +$(LI $(RELATIVE_LINK2 visuald-copyfiles,copyFiles can now be used in VisualD projects.)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 abi-fix-creal,D ABI change on x86_64 Posix targets) +$(CHANGELOG_SOURCE_FILE dmd, changelog/abi-fix-creal.dd) +$(P +The compiler has been updated to return the real part of `creal` numbers in +ST0, and the imaginary part in ST1, to match the x86_64 System V ABI. +) + +$(P +This is an ABI breaking change and requires recompiling libraries that make use +of the `creal` type. +) +) + +$(LI $(LNAME2 complex_types,Added `__c_complex_float`, `__c_complex_double`, and `__c_complex_real` types) +$(CHANGELOG_SOURCE_FILE dmd, changelog/complex_types.dd) +$(P +This allows code interfacing with C and C++ to maintain ABI compatibility with +`_Complex` types. It replaces the built-in types `cfloat`, `cdouble`, and +`creal` which are due to be deprecated. +) +) + +$(LI $(LNAME2 copy-constructor-priority,Having both a copy constructor and a generated postblit is now deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/copy-constructor-priority.dd) +$(P +Up until this release, the postblit had priority over the copy constructor, +no matter if the former was user-defined or generated. This prevented new +code that uses the copy constructor to interact with library code that uses +the postblit. To enable this interaction, having a generated postblit +and a copy constructor (user-defined or generated) is now deprecated. +For example: +) + +--- +// library code using postblit +struct A +{ + this(this) {} +} + +// new code using copy constructor +struct B +{ + A a; + this(const scope ref B) {} +} +--- + +$(P +Up until this release, in the above code, `struct B` had a generated postblit +that had priority over the user defined copy constructor. With this release, +a deprecation will be issued at the definition of ` structB`, stating that the +postblit is going to be preferred to the copy constructor. If `B` has both a +user-defined postblit and a copy constructor (generated or user-defined), +the postblit will continue to have priority. +) + +$(P +To get rid of the deprecation, the user can either: +) + +$(P +1. Explicitly `@disable this(this)` in `struct B`. That will instruct +the compiler that the copy constructor is preferred over the postblit. +) + +$(P +2. Define a postblit for `struct B`. That will instruct the compiler +that the postblit is preferred over the postblit. +) + +$(P +3. Remove all copy constructors from `struct B`. In this case the postblit +will be used for copy constructing instances of `struct B`. +) +) + +$(LI $(LNAME2 ddoc-always-visibility,DMD's JSON output will now always include the protection level) +$(CHANGELOG_SOURCE_FILE dmd, changelog/ddoc-always-visibility.dd) +$(P +In previous release, the JSON output the compiler generates did not include +the protection level if it was `public`. It is now always included. +) +) + +$(LI $(LNAME2 ddoc-shared-static-ctor,DMD's JSON output now have distinct types for [shared] module constructor/destructor) +$(CHANGELOG_SOURCE_FILE dmd, changelog/ddoc-shared-static-ctor.dd) +$(P +Previously, module constructors and destructors (shared or not) would be output as +functions, and the only way for documentation generators to recognize them was +to search for the pattern that was used for their naming. +This means that external tools would need to depend on internal compiler details +for generating documentation. +From this release, 4 new values have been introduced for `kind`: +`shared static constructor`, `shared static destructor`, `static constructor`, `static destructor`. +) +) + +$(LI $(LNAME2 deprecate_dualcontext,Deprecate local templates that receive local symbols by alias) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecate_dualcontext.dd) +$(P +Support for instantiating local and member templates with local +symbols was implemented in DMD 2.087.0. However, the implementation +was incompatible with GDC and LDC backends. +) + +$(P +In order to maintain feature parity among D implementations, this +improvement has been deprecated, and may be removed from a future DMD +release. +) +) + +$(LI $(LNAME2 dtoh-improvements,Improvements for the C++ header generation) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dtoh-improvements.dd) +$(P +The following features/bugfixes/improvements were implemented for the +experimental C++ header generator: +) + +$(P +- Generate fieldwise constructors for aggregates +- Don't emit instantiated classes as unique class declarations +- Emit template arguments for instantiated base classes +- Don't emit enums for opaque types specially handled by the compiler +) + +$(P +Note: The header generator is still considerer experimental, so please submit + any bugs encountered to [the bug tracker](https://issues.dlang.org). +) +) + +$(LI $(LNAME2 dwarf-switch,Add `-gdwarf=` switch for the DMD compiler.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dwarf-switch.dd) +$(P +Emit DWARF symbolic debug info (non-Windows machines only). +Supported versions are 3, 4, and 5. +) + +$(P +Once added, the `-g` switch is implicitly activated. +) + +$(P +Note: DWARF Version 5 is experimental. +) +) + +$(LI $(LNAME2 getVisibility,Introduced `__traits(getVisibility, Sym)` as an alias to `getProtection`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/getVisibility.dd) +$(P +Since the changes in v2.071.0, attributes such as `private`, `protected`, `public`, +etc... are visibility attributes, and not protection attributes. +However, the name of this trait predates such change and was thus inconsistent with +all the other documentation. +This change only introduce the new name, and `getProtection` has been left un-deprecated, +and while using the new name is reccommended for users that only supports the latest +version of the language, there is no plan to deprecate it. +) +) + +$(LI $(LNAME2 runtime-synchronized,Plain `synchronized` statements now use run-time allocated mutexes.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/runtime-synchronized.dd) +$(P +Synchronized statements have two forms, `synchronized` and `synchronized(exp)`. +When there is no expression argument, a global mutex is created using a static +buffer big enough to store the platform dependant critical section type and a +pointer field. +) + +$(P +Example: +) +``` +void main() +{ + synchronized { + // __gshared byte[40 + 8] __critsec; + // _d_criticalenter(&__critsec[0]); + // scope(exit) _d_criticalexit(&__critsec[0]); + (cast() counter) += 1; + } +} +``` + +$(P +This implementation suffers from a couple deficiencies. Neither the size nor +alignment of the `critsec` buffer are obtained from the OS critical section +type defined in druntime. As a result, if the size allocated by the compiler is +too small, or the platform has strict alignment requirements, then the program +run-time will crash on entering the synchronized statement. +) + +$(P +This code will now call a new implementation that allocates the critical +section lazily at run-time, moving all logic out of the compiler to druntime. +) +) + +$(LI $(LNAME2 shortfunctions,Allow shortened function implementations for single-expresssion functions.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/shortfunctions.dd) +$(P +`-preview=shortenedMethods` is added. This allows functions to be written in a similar form to lambda functions: +) + +--- +// these 2 are equivalent +int foo() { return 1; } +int foo() => 1; +--- + +$(P +The syntax allows the form `=> expr` to replace the function body `{ return expr; }` +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 callStructDtorsDuringGC,The druntime option `callStructDtorsDuringGC` has been removed) +$(CHANGELOG_SOURCE_FILE druntime, changelog/callStructDtorsDuringGC.dd) +$(P +It had been deprecated in 2.088. +) +) + +$(LI $(LNAME2 freebsd-statvfs,FreeBSD declarations from statvfs that belong in mount have been removed) +$(CHANGELOG_SOURCE_FILE druntime, changelog/freebsd-statvfs.dd) +$(P +It had been deprecated in 2.082 in favor of `core.sys.freebsd.sys.mount`. +) +) + +$(LI $(LNAME2 libunwind,Experimental llvm-libunwind based backtrace printing was added) +$(CHANGELOG_SOURCE_FILE druntime, changelog/libunwind.dd) +$(P +Currently, druntime uses the `backtrace` and `backtrace_symbols` functions +to provide debug informations (addresses and function names, respectively). +) + +$(P +This can create issues for target that do not provide `backtrace`, such as Musl libc. +Additionally, the `backtrace` interface is inherently limited, as it only allow +to get up to `X` frames (where `X` is the size of the buffer), and forces them +to be stored continuously in memory. The same apply to `backtrace_symbols`. +) + +$(P +On the other hand, libunwind is an industry standard for unwinding and stack trace inspection. +It has been ported to a variety of platform, has a simple yet flexible API, +and is part of GCC, and a similar library is part of LLVM. +) + +$(P +Starting from this release, druntime includes a way to use LLVM's libunwind as a backtrace provider. +The support is limited to LLVM's version of libunwind, as it is available on Alpine Linux, +and easier to interface with. +) + +$(P +For packagers, one can define `DRuntime_Use_Libunwind` when building druntime, +enabling the support by default. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 deprecate-approxEqual,Deprecate `std.math : approxEqual`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/deprecate-approxEqual.dd) +$(P +The template `approxEqual` for comparing floating point numbers has +been deprecated. +) + +$(P +Please use the template `isClose` instead, which has better default +values and is symmetric in its arguments. +) + +$(P +To (almost) keep the current behaviour of `approxEqual(a, b)` use +`isClose(a, b, 1e-2, 1e-2)`, but we recommend to adjust the code to +make it work with `isClose(a, b)`. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 dmd-linker-dflags,More 'linker dflags' with DMD) +$(CHANGELOG_SOURCE_FILE dub, changelog/dmd-linker-dflags.dd) +$(P +`-betterC`, `-L…` and `-Xcc=…` `dflags` are now used for linking too. +) +) + +$(LI $(LNAME2 visuald-copyfiles,copyFiles can now be used in VisualD projects.) +$(CHANGELOG_SOURCE_FILE dub, changelog/visuald-copyfiles.dd) +$(P +Files that are needed for the application to run can be specified in the `copyFiles` build option, +which causes these files to be copied to the target path. The dub generator for VisualD now replicates +this behaviour, so that this kind of applications can be successfully debugged in Visual Studio. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 20661): opEquals not recognized for AA key $(LPAREN)take two$(RPAREN)) +$(LI $(BUGZILLA 21319): DMD crashes on immutable circular reference) +$(LI $(BUGZILLA 21547): Order of constructor declaration affects struct initializer) +$(LI $(BUGZILLA 21678): "_d_arraysetlengthT is not callable using argument types" on chained array length assignment) +$(LI $(BUGZILLA 21696): DMD 2.095.1 Compilation Crash) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 5713): Broken final switch on ints) +$(LI $(BUGZILLA 10619): Wrong local variable passed as alias arguments to templates) +$(LI $(BUGZILLA 11717): CTFE: non-constant value with array and vector ops.) +$(LI $(BUGZILLA 13667): ICE: stack overflow using self-referencing cast inside recursive alias this method) +$(LI $(BUGZILLA 14831): Each function local symbols should have unique mangled name) +$(LI $(BUGZILLA 15225): cannot overload directly aliased function literals) +$(LI $(BUGZILLA 16635): Alias this for implicit conversion to "ref const$(LPAREN)typeof$(LPAREN)this$(RPAREN)$(RPAREN)" causes dmd to segfault) +$(LI $(BUGZILLA 17105): [ICE] SIMD Internal error with optimizations: backend\cod3.c 6807) +$(LI $(BUGZILLA 18867): backend/cgcod.c crash on assignment to vector element) +$(LI $(BUGZILLA 19788): compiler crash on slicing a enum typed as vector) +$(LI $(BUGZILLA 20041): CTFE incorrect result with __vector) +$(LI $(BUGZILLA 20111): asm VCVTPS2PH is not encoded correctly) +$(LI $(BUGZILLA 20235): C++ ABI doesn't destruct struct arguments in the callee) +$(LI $(BUGZILLA 20565): Local template declarations in different scopes produce uncaught name collisions) +$(LI $(BUGZILLA 20695): Copy constructor disable default struct constructor) +$(LI $(BUGZILLA 20821): Aliased template method confuses overload resolution) +$(LI $(BUGZILLA 20868): DIP1000: scope delegate triggers error in unsafe code and it shouldn't) +$(LI $(BUGZILLA 21214): simd: wrong diagnostic with unsupported vectors) +$(LI $(BUGZILLA 21352): enum members should not be given UDAs of its parent enum declaration) +$(LI $(BUGZILLA 21469): ICE core.simd when implementing _mm_set1_epi16) +$(LI $(BUGZILLA 21471): Backend assertion triggered with `-checkation=context` and `-inline`) +$(LI $(BUGZILLA 21472): `-checkaction=context` doesn't work with `tupleof`) +$(LI $(BUGZILLA 21474): ICE with core.simd and -O $(LPAREN)Illegal Instruction$(RPAREN)) +$(LI $(BUGZILLA 21481): functions in overloaded template are lost when the template overloads an alias) +$(LI $(BUGZILLA 21489): Duplicated template instantiation using mixin inside alias declaration) +$(LI $(BUGZILLA 21490): Optimizer can add SSE integer multiply for machines less than SSE4.1 which do not have it) +$(LI $(BUGZILLA 21501): [REG 2.089.1] undefined identifier in package when using mixin and cyclic imports) +$(LI $(BUGZILLA 21508): private class p in file p.d visible outside the file $(LPAREN)module$(RPAREN)) +$(LI $(BUGZILLA 21515): extern$(LPAREN)C$(RPAREN) and extern$(LPAREN)C++$(RPAREN) returns creal in wrong order) +$(LI $(BUGZILLA 21518): delegates not checked for attribute match in const arrays) +$(LI $(BUGZILLA 21522): function gets lost when aliasing an overloaded function template) +$(LI $(BUGZILLA 21526): x87 not rounding to precision on assignment on some platforms) +$(LI $(BUGZILLA 21530): dtoh: Identifiers need to be sanitized wrt. reserved C++ keywords) +$(LI $(BUGZILLA 21534): dtoh: Default params for default ctor missing template args) +$(LI $(BUGZILLA 21543): dmd infinite loop on alias this and std.typecons.Nullable) +$(LI $(BUGZILLA 21553): incorrect call to expressionSemantic$(LPAREN)$(RPAREN) in statementsem.d) +$(LI $(BUGZILLA 21598): checkaction=context reruns pure functions with debug blocks on failure) +$(LI $(BUGZILLA 21640): @live not working with templates) +$(LI $(BUGZILLA 21647): pragma$(LPAREN)msg$(RPAREN) should be able to print a void type) +$(LI $(BUGZILLA 21659): [OSX] core.stdc.config.__c_ulonglong is forward referenced while looking for sizeof) +$(LI $(BUGZILLA 21662): Extern linkage variables cannot be of types with disabled default construction) +$(LI $(BUGZILLA 21668): Cannot declare ref parameter of opaque type) +$(LI $(BUGZILLA 21682): checkaction=context fails for expressions using static operator overloads) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 7176): Lambda => syntax for function and methods too) +$(LI $(BUGZILLA 10445): add .min, .max, etc. properties for vector types) +$(LI $(BUGZILLA 19632): [SIMD] Error: invalid foreach aggregate) +$(LI $(BUGZILLA 20788): Difference between colored and non colored output) +$(LI $(BUGZILLA 21527): Unnecessary store to memory in SIMD code) +$(LI $(BUGZILLA 21593): Only update file time if file to be written already exists) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 21663): std.concurrency.receiveOnly doesn't work with tuples) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 13663): Comparison of Tuples with floating point fields) +$(LI $(BUGZILLA 15136): If we want toStringz to be fully correct, it needs to stop checking for '\0') +$(LI $(BUGZILLA 17269): formattedWrite of struct with Nullable string fails) +$(LI $(BUGZILLA 20508): std.math.pow$(LPAREN)-infinity, y$(RPAREN) does not return NaN for imaginary or complex results) +$(LI $(BUGZILLA 20539): std.conv.to: internal overload conflict for enums with base types that have a catch-all opEquals overload $(LPAREN)?$(RPAREN)) +$(LI $(BUGZILLA 20848): Bug in formatValueImpl) +$(LI $(BUGZILLA 21103): isDynamicArray instantiates unecessary templates) +$(LI $(BUGZILLA 21444): bad string concat in static assert message) +$(LI $(BUGZILLA 21555): std.container.array: insertBack is wrong and should be tested for Array!bool) +$(LI $(BUGZILLA 21556): std.container.array: insertAfter is wrong and should be tested) +$(LI $(BUGZILLA 21609): LinearCongruentialEngine fails for m = 0) +$(LI $(BUGZILLA 21634): std.bitmanip: bitfields may generate invalid variable) +$(LI $(BUGZILLA 21635): std.bitmanip: bitfields should produce better error messages with wrong parameters) +$(LI $(BUGZILLA 21636): std.bitmanip: bitfields size of bitfield should be checked against size of used type) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 21523): Microsoft Windows std.stdio.File.lock$(LPAREN)$(RPAREN), tryLock$(LPAREN)$(RPAREN), unlock$(LPAREN)$(RPAREN): do not allocate memory for error messages when they are not needed) +$(LI $(BUGZILLA 21559): Speed up walkLength for narrow strings) +$(LI $(BUGZILLA 21629): std.csv report one record on empty input) +$(LI $(BUGZILLA 21638): std.typecons.RefCounted!$(LPAREN)T, RefCountedAutoInitialize.no$(RPAREN) should still work when T.this$(LPAREN)$(RPAREN) is annotated with `@disable`) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 21309): Missing core.thread.threadbase documentation) +$(LI $(BUGZILLA 21642): [REG 2.084] hashOf will fail to compile for some structs/unions that recursively contain shared enums) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 8046): simd.d needs some documentation) +$(LI $(BUGZILLA 21544): -checkaction=context formats enum members as their base type) +$(LI $(BUGZILLA 21666): wrong printf format specifier for `real` with -checkaction=context on Win64) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 14790): coverage merge should detect changed source code) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 21292): Chrome by default now blocks downloading .dmg or .exe files via HTTP) +$(LI $(BUGZILLA 21493): Documentation broken hyperlink std.stdio) +) +) +$(D_CONTRIBUTORS_HEADER 54) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Bartosz Wójcik) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR Bernhard Seckinger) + $(D_CONTRIBUTOR berni42) + $(D_CONTRIBUTOR berni44) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR brianush1) + $(D_CONTRIBUTOR Cameron Ross) + $(D_CONTRIBUTOR Crom (Thibaut CHARLES)) + $(D_CONTRIBUTOR Denis Feklushkin) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR Eugen Wissner) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR H. S. Teoh) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR Lucien Perregaux) + $(D_CONTRIBUTOR Luhrel) + $(D_CONTRIBUTOR Luís Ferreira) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR mhh) + $(D_CONTRIBUTOR Mihaela Chirea) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR nordlow) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Quirin F. Schroll) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR rkulhanek) + $(D_CONTRIBUTOR Robert burner Schadek) + $(D_CONTRIBUTOR Roman Kashitsyn) + $(D_CONTRIBUTOR Roy Margalit) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Stefan Koch) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Tim Schendekehl) + $(D_CONTRIBUTOR Tomáš Chaloupka) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR Witold Baryluk) + $(D_CONTRIBUTOR سليمان السهمي (Suleyman Sahmi)) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.096.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.096.1.dd b/changelog/2.096.1.dd new file mode 100644 index 0000000000..058a7ea8f0 --- /dev/null +++ b/changelog/2.096.1.dd @@ -0,0 +1,91 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 23, 2021, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 21 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 18 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 21229): [REG 2.080.2] Constructor flow analysis doesn't understand unions) +$(LI $(BUGZILLA 21687): Confusing error message for CTFE pointer in static initializer) +$(LI $(BUGZILLA 21798): checkaction=context creates temporary of type void) +$(LI $(BUGZILLA 21806): Overload selection ignores slice) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 19192): [wrong-code] [crashes] Covariant method interface <- abstract class <- class hierarchies) +$(LI $(BUGZILLA 20705): `-preview=rvaluerefparam` does not work with template deduction) +$(LI $(BUGZILLA 21799): CTFE doesn't call base class destructor for extern$(LPAREN)D$(RPAREN) classes) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 21845): Wrong ParameterStorageClass when -preview=in is used) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 20886): std.process.browse does not work with URLs 256 characters or longer) +$(LI $(BUGZILLA 21716): std.regex performance regression $(LPAREN)additional GC allocation$(RPAREN)) +$(LI $(BUGZILLA 21725): Specifying null as bitfields variable name now fails) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 21702): avoid quadratic template expansion in constraints of multiple search term versions of std.algorithm.searching.startsWith & endsWith) +$(LI $(BUGZILLA 21721): casting std.BigInts to built-in floating point types doesn't work without -preview=dip1000) +$(LI $(BUGZILLA 21724): std.algorithm.mutation.copy fails on overlapping arrays if the source array's pointer is less than the destination array's pointer) +$(LI $(BUGZILLA 21758): std.experimental.checkedint opBinaryRight with integer left-hand side does not compile for any operators except + and -) +$(LI $(BUGZILLA 21801): std.typecons.ReplaceType does not work for `in` parameters) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 21709): std.conv.emplace not usable in betterC - 2.096) +$(LI $(BUGZILLA 21712): [REG 2.096.0] sometimes coverage *.lst files are corrupted) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 21371): core.stdcpp.allocator: _Adjust_manually_vector_aligned checks for sentinel unconditionally $(LPAREN)Windows only$(RPAREN)) +$(LI $(BUGZILLA 21701): casWeak is not implemented) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 21784): joining a detached thread results in segfault.) +) +) +$(D_CONTRIBUTORS_HEADER 18) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Imperatorn) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR Jon Degenhardt) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Puneet Goel) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Roy Margalit) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Ömer Faruk Irmak) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.096.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.097.0.dd b/changelog/2.097.0.dd new file mode 100644 index 0000000000..4c1069536c --- /dev/null +++ b/changelog/2.097.0.dd @@ -0,0 +1,944 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jun 03, 2021, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 29 major changes and 144 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 54 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 ambiguous-ternary,Deprecation period for ambiguous ternary expressions has ended)) +$(LI $(RELATIVE_LINK2 body-deprecation,Usage of the `body` keyword has been deprecated)) +$(LI $(RELATIVE_LINK2 fqn-bypass-deprecation,Deprecate a case of using fully-qualified names to bypass imports)) +$(LI $(RELATIVE_LINK2 package-visibility,Explicit package visibility attribute is now always applied to new scopes)) +$(LI $(RELATIVE_LINK2 pragma-mangle-aggregate,`pragma(mangle)` can now be applied to aggregates)) +$(LI $(RELATIVE_LINK2 transition-complex,Complex and imaginary types are now deprecated)) +$(LI $(RELATIVE_LINK2 while-condition-assignment,`while (auto n = expression)` is now supported)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 add_centering_flag,Centering formatted output.)) +$(LI $(RELATIVE_LINK2 add_conversion_target,`AllImplicitConversionTargets` replaces `ImplicitConversionTargets`)) +$(LI $(RELATIVE_LINK2 add_format_integers_as_floats,Formatting integers with `%e`, `%f`, `%g` and `%a` is now possible.)) +$(LI $(RELATIVE_LINK2 bugfix_for_pow,Implementation of `pow(f, -2)` and `f ^^ -2` changed)) +$(LI $(RELATIVE_LINK2 deprecate_enforceValidFormatSpec,Deprecate std.format : enforceValidFormatSpec)) +$(LI $(RELATIVE_LINK2 deprecate_formatElement,Deprecate std.format : formatElement)) +$(LI $(RELATIVE_LINK2 deprecate_unformatElement,Deprecate std.format : unformatElement)) +$(LI $(RELATIVE_LINK2 fieldnametuple_interface,`FieldnameTuple` now returns an empty tuple for interfaces)) +$(LI $(RELATIVE_LINK2 fields_interface,`Fields` (formerly `FieldTypeTuple`) now returns an empty tuple for interfaces)) +$(LI $(RELATIVE_LINK2 formatting_floats_in_CTFE,Floating point numbers can be formatted at compile time)) +$(LI $(RELATIVE_LINK2 formatting_floats_nogc,Formatting floating point numbers don't allocate with the GC anymore.)) +$(LI $(RELATIVE_LINK2 formatting_some_reals_as_doubles,Some reals will be downcast to double when used with `std.format`.)) +$(LI $(RELATIVE_LINK2 nullable-remove-alias-get-this,`std.typecons.Nullable`: Remove deprecated `alias get this`.)) +$(LI $(RELATIVE_LINK2 rework_format_docs,Documentation of `std.format` has been completely reworked.)) +$(LI $(RELATIVE_LINK2 splitting_format,Module `std.format` has been split into smaller modules)) +$(LI $(RELATIVE_LINK2 splitting_math,Module `std.math` has been split into smaller modules)) +$(LI $(RELATIVE_LINK2 splitwhen,splitWhen added to std.algorithm.iteration)) +$(LI $(RELATIVE_LINK2 std-datetime,The old benchmarking functionality in `std.datetime` has been removed.)) +$(LI $(RELATIVE_LINK2 std-exception,`std.exception.enforceEx` has been removed.)) +$(LI $(RELATIVE_LINK2 std-sumtype,New module: `std.sumtype`)) +$(LI $(RELATIVE_LINK2 transposed-remove-save,`std.range.Transposed`: Remove deprecated member `save`)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 add_lowmem,Added support for low memory compilation option to the $(LINK2 https://dub.pm/settings, dub settings file).)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 ambiguous-ternary,Deprecation period for ambiguous ternary expressions has ended) +$(CHANGELOG_SOURCE_FILE dmd, changelog/ambiguous-ternary.dd) +$(P +In D, the ternary operator (`?:`) has a higher precedence than +the assignment operator (`=`), hence: +) +--- +true ? stt = "AA" : stt = "BB" +--- + +$(P +actually means: +) +--- +(true ? (stt = "AA") : stt) = "BB", +--- + +$(P +This is in line with C, and many other languages (except C++), +but comes at a surprise to many, which is why this specific combination +of ternary and assignment was deprecated in v2.082.0 (2018-09-01). +) + +$(P +The deprecation instructs the user to use parenthesis to make the +intent explicit, so the above snippet should read as: +) +--- +true ? (stt = "AA") : (stt = "BB") +--- + +$(P +This deprecation period has now ended and the compiler will now issue +an error for ambiguous code. +) +) + +$(LI $(LNAME2 body-deprecation,Usage of the `body` keyword has been deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/body-deprecation.dd) +$(P +Using `body` to indicate the body of a function or method +in the presence of contracts is now deprecated. +Any leftover usage of `body` can be replaced with `do`. +This replacement, introduced by $(LINK2 https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1003.md, DIP1003), +has been available since $(LINK2 https://github.com/dlang/dmd/pull/6855, DMD v2.075.0 (July 2017)). +) +) + +$(LI $(LNAME2 fqn-bypass-deprecation,Deprecate a case of using fully-qualified names to bypass imports) +$(CHANGELOG_SOURCE_FILE dmd, changelog/fqn-bypass-deprecation.dd) +$(P +Since v2.084 it is no longer possible to bypass private imports by using fully-qualified names, +this was deprecated in v2.071 but when fully-qualified names are used as a type +(vs an expression) the code is accepted without any warning. +) + +$(P +Starting with this release the compiler will now properly deprecate the previous omitted case. +) + +$(P +The issue is best described in the following example: +) + +```d +import std.algorithm; + +// deprecated in v2.071, error since v2.084 +auto a = std.range.Take!(int[]); // Error: undefined identifier `range` in package `std`... + +// now it's deprecated, will be error from v2.106 +std.range.Take!(int[]) s; + +```` +) + +$(LI $(LNAME2 package-visibility,Explicit package visibility attribute is now always applied to new scopes) +$(CHANGELOG_SOURCE_FILE dmd, changelog/package-visibility.dd) +$(P +If a less restrictive package attribute appeared within the scope of another +package attribute, the more restrictive parent would override any explicit +child visibility. +) + +$(P +Example: +) +--- +module pkg.foo; + +package(pkg.foo): // analogous to "private" or plain "package" + +package(pkg) int bar(); // package(pkg) was being ignored +--- + +$(P +Starting from this version, the package visibility attribute is now always +applied as long as it is valid. In the given example, this allows any module +in the package `pkg` to import and use the symbol `bar`. +) +) + +$(LI $(LNAME2 pragma-mangle-aggregate,`pragma(mangle)` can now be applied to aggregates) +$(CHANGELOG_SOURCE_FILE dmd, changelog/pragma-mangle-aggregate.dd) +$(P +The syntax is `pragma(mangle, str_or_decl [, str] ) declaration;` where `str_or_decl` is either: +a string expression to substitute the name of `declaration`; +or a `class`, `struct`, or `union` declaration or template instance to use instead of `declaration`s for mangling. +If the optional second argument is present, use that as a name instead but keep the namespaces and template parameters of +`str_or_decl` (if any). +) + +$(P +This enables binding with functions that take classes by value or reference and to classes that are D keywords. +) + +$(P +To bind C++'s `std::function` by value: +) +--- +extern(C++, "std") +{ + template std_function(F) + { + pragma(mangle, "function") + class std_function + { + // member variables and functions + } + } +} + +template ScopeClass(C , string name) +{ + enum ns = __traits(getCppNamespaces,C); + extern(C++, class) extern(C++,(ns)) + { + pragma(mangle, C, name) + struct ScopeClass + { + char[__traits(classInstanceSize, C)] buffer; + // member variables and functions + } + } +} + +alias FuncType = void function(int); +alias RawFuncType = typeof(*FuncType.init); +// Mangles as `void funk(std::function a)` +extern(C++) void funk( ScopeClass!(std_function!(RawFuncType)),"function") a ); +--- +) + +$(LI $(LNAME2 transition-complex,Complex and imaginary types are now deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/transition-complex.dd) +$(P +D previously supported complex and imaginary versions of all floating point +types as part of the language. +) +--- +float a = 2; +ifloat b = 4i; +cfloat c = a + b; +assert(c == 2 + 4i); +--- + +$(P +However these types are too specialized to be a part of the core language, and +the same functionalities can be implemented as part of a library type. As +such, older versions of DMD provided the `-transition=complex` switch to warn +when those builtin types were used. This transition phase has finished, and +those deprecations are now turned on by default. +) + +$(P +Users should use $(LINK2 https://dlang.org/phobos/std_complex.html#Complex, `std.complex.Complex`) instead. +) +--- +import std.complex; +float a = 2; +float b = 4; +auto c = complex(a, b); +assert(c == complex(2, 4)); +--- + +$(P +The `-transition=complex` switch that previously turn on deprecation warnings +no longer has an effect and has also been deprecated. +) +) + +$(LI $(LNAME2 while-condition-assignment,`while (auto n = expression)` is now supported) +$(CHANGELOG_SOURCE_FILE dmd, changelog/while-condition-assignment.dd) +$(P +Up until this release, `while (auto n = expression)` was not +supported, although the `if` counterpart: `if (auto n = expression)` +compiled succesfully. Starting with the current compiler version, +`while (auto n = expression)` is accepted, having the exact +same semantics as: +) + +--- +while (true) +{ + if (auto n = expression) + { /* loop body */ } + else + { break; } +} +--- +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 add_centering_flag,Centering formatted output.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/add_centering_flag.dd) +$(P +A new flag $(B '=') has been added to the format specifier, which +allows to center the output: +) + +``` +assert(format!"|%=8d|"(1234) == "| 1234 |"); +``` + +$(P +In case the output cannot be centered exactly it is moved slightly to +the left if $(B '-') flag is present too and to the right else: +) + +``` +assert(format!"|%=-8d|"(123) == "| 123 |"); +assert(format!"|%=8d|"(123) == "| 123 |"); +``` +) + +$(LI $(LNAME2 add_conversion_target,`AllImplicitConversionTargets` replaces `ImplicitConversionTargets`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/add_conversion_target.dd) +$(P +The function `ImplicitConversionTargets` in module `std.traits` has a +design flaw: The list of conversion targets contains some, but not all +unsafe conversion targets. To overcome this, a new function +`AllImplicitConversionTargets` has been added and +`ImplicitConversionTargets` has been deprecated. +) +) + +$(LI $(LNAME2 add_format_integers_as_floats,Formatting integers with `%e`, `%f`, `%g` and `%a` is now possible.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/add_format_integers_as_floats.dd) +$(P +The formatting posibilities of integers have been expanded to the +specifiers that are typical for floating point numbers: Integers can +now be formatted using `%e`, `%f`, `%g` and `%a`. The result is +similar to the result expected for the corresponding floating point +value. +) + +``` +assert(format!"%.3e"(ulong.max) == "1.845e+19"); +assert(format!"%.3,3f"(ulong.max) == "18,446,744,073,709,551,615.000"); +assert(format!"%.3g"(ulong.max) == "1.84e+19"); +assert(format!"%.3a"(ulong.max) == "0x1.000p+64"); +``` +) + +$(LI $(LNAME2 bugfix_for_pow,Implementation of `pow(f, -2)` and `f ^^ -2` changed) +$(CHANGELOG_SOURCE_FILE phobos, changelog/bugfix_for_pow.dd) +$(P +We noticed that the implementation of `pow(f, -2)` and `f ^^ -2` with +`f` being a floating point value, was buggy for some values of `f`. +Unfortunately the fix implies small changes for other values for `f` +(with exponent `-2`) too: The least significant bits of the result might +differ from the current implementation. (This is due to the +peculiarities of floating point numbers and cannot be avoided with +reasonable means.) +) + +$(P +To avoid problems, make sure, that your algorithms do not rely on the +least significant bits of floating point calculations, for example by +using `isClose` instead of `==`. +) +) + +$(LI $(LNAME2 deprecate_enforceValidFormatSpec,Deprecate std.format : enforceValidFormatSpec) +$(CHANGELOG_SOURCE_FILE phobos, changelog/deprecate_enforceValidFormatSpec.dd) +$(P +`enforceValidFormatSpec` from `std.format` has been accidentally made +public and will be removed from public view in 2.107.0. +) +) + +$(LI $(LNAME2 deprecate_formatElement,Deprecate std.format : formatElement) +$(CHANGELOG_SOURCE_FILE phobos, changelog/deprecate_formatElement.dd) +$(P +`formatElement` from `std.format` has been accidentally made public and +will be removed from public view in 2.107.0. +) + +$(P +Please use instead of `formatElement(sink, value, fmt)`: +) + +``` +import std.range : only; + +sink.put(format!("%("~fmt~"%)")(only(value))); +``` +) + +$(LI $(LNAME2 deprecate_unformatElement,Deprecate std.format : unformatElement) +$(CHANGELOG_SOURCE_FILE phobos, changelog/deprecate_unformatElement.dd) +$(P +`unformatElement` from `std.format` has been accidentally made public and +will be removed from public view in 2.107.0. +) + +$(P +Please use instead for strings and characters `parseElement` from +`std.conv` and for all else `unformatValue` from `std.format.read`. +) +) + +$(LI $(LNAME2 fieldnametuple_interface,`FieldnameTuple` now returns an empty tuple for interfaces) +$(CHANGELOG_SOURCE_FILE phobos, changelog/fieldnametuple_interface.dd) +$(P +Previously `FieldNameTuple` returned `AliasSeq!""` for interfaces as done for +non-aggregate types like `int`, `char*`, ... . This behaviour was surprising +because an instance of that interface *may* have members that just are not +known at compile time. +) + +$(P +`FieldNameTuple` will now return an empty `AliasSeq!()` for interfaces. +) +) + +$(LI $(LNAME2 fields_interface,`Fields` (formerly `FieldTypeTuple`) now returns an empty tuple for interfaces) +$(CHANGELOG_SOURCE_FILE phobos, changelog/fields_interface.dd) +$(P +Previously `Fields` returned `AliasSeq!(Interface)` for interfaces as done for +non-aggregate types like `int`, `char*`, ... . This behaviour was surprising +because an instance of an interface *may* have members that just are not +known at compile time. +) + +$(P +`Fields` will now return an empty `AliasSeq!()` for interfaces. +) +) + +$(LI $(LNAME2 formatting_floats_in_CTFE,Floating point numbers can be formatted at compile time) +$(CHANGELOG_SOURCE_FILE phobos, changelog/formatting_floats_in_CTFE.dd) +$(P +Example: +) +------ +import std.format : format; +import std.math : sqrt; + +enum pi = format!"%s"(3.1415926f); +static assert(pi == "3.14159"); + +enum golden_ratio = format!"|%+-20.10E|"((1 + sqrt(5.0)) / 2); +static assert(golden_ratio == "|+1.6180339887E+00 |"); +------ +) + +$(LI $(LNAME2 formatting_floats_nogc,Formatting floating point numbers don't allocate with the GC anymore.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/formatting_floats_nogc.dd) +$(P +The implementation of formatting floating point numbers has been +reworked. We made sure that working examples never allocate with the +GC, however, we are still using exceptions which are GC managed. +Therefore, code that uses formatting correctly will never allocate, +but in the case of exceptions, the GC will be used to allocate the +exception. We are working on DIP 1008 to solve this issue. +) +) + +$(LI $(LNAME2 formatting_some_reals_as_doubles,Some reals will be downcast to double when used with `std.format`.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/formatting_some_reals_as_doubles.dd) +$(P +In the internals of `std.format` we replaced a call to `snprintf` of +`libc` with routines written in D for formatting floating point +values. These functions only work for floats, doubles, 64-bit-reals +and 80-bit-reals (x87-reals) yet. +) + +$(P +All other reals are handled by downcasting them to doubles before +being formatted. This might result in a loss of precision in the +output. Further, numbers larger than `double.max` will be formatted like +`double.max` and numbers large than zero but smaller than the smallest +positive double will be formatted like the smallest positive double. +Likewise for negative values. +) +) + +$(LI $(LNAME2 nullable-remove-alias-get-this,`std.typecons.Nullable`: Remove deprecated `alias get this`.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/nullable-remove-alias-get-this.dd) +$(P +`Nullable` no longer implicitly converts to its member. +This feature was problematic because a simple use of a value could +invisibly cause an assertion due to type conversion. +To restore the previous behavior, replace uses of a `Nullable` value +`n` with `n.get`. +) +) + +$(LI $(LNAME2 rework_format_docs,Documentation of `std.format` has been completely reworked.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/rework_format_docs.dd) +$(P +In the last years, the documentation of `std.format` was outdated +little by little and therefore needed a complete rework. The whole +package was reviewed and all documentations, including examples, +improved and extended. +) + +$(P +Some highlights: +) + +$(P +$(UL +$(LI The grammar of the format string was updated.) +$(LI A detailed description of format specifiers was provided.) +$(LI Several examples on how to use the functions and the format + strings were added.) +) +) +) + +$(LI $(LNAME2 splitting_format,Module `std.format` has been split into smaller modules) +$(CHANGELOG_SOURCE_FILE phobos, changelog/splitting_format.dd) +$(P +The module `std.format` has been split into submodules: +) + +$(P +$(UL + $(LI `std.format.spec`: Symbols concerning the format string, mainly + the `struct FormatSpec` and the `template singleSpec`) + $(LI `std.format.read`: Symbols concerning reading input, mainly + the `template formattedRead` and the `template unformatValue`) + $(LI `std.format.write`: Symbols concerning writing output, mainly + the `template formattedWrite` and the `template formatValue`) +) +) + +$(P +All public symbols are still accessible using std.format as usual. +) +) + +$(LI $(LNAME2 splitting_math,Module `std.math` has been split into smaller modules) +$(CHANGELOG_SOURCE_FILE phobos, changelog/splitting_math.dd) +$(P +The module `std.math` has been split into submodules: +) + +$(P +$(UL + $(LI `std.math.constants`: Mathematical constants, like `PI`.) + $(LI `std.math.algebraic`: Basic algebraic functions, like `abs` and `sqrt`.) + $(LI `std.math.trigonometry`: Trigonometric functions, like `sin` and `cos`.) + $(LI `std.math.rounding`: Functions concerned about rounding, like `ceil` and `floor`.) + $(LI `std.math.exponential`: Exponential and logarithmic functions, like `pow`, `exp` and `log`.) + $(LI `std.math.remainder`: Function calculating the remainder, like `fmod`.) + $(LI `std.math.operations`: Floating-point operations, like `isClose`, `nextUp` and `fmin`.) + $(LI `std.math.traits`: Floating-point introspection, like `isNaN` and `isSubnormal`.) + $(LI `std.math.hardware`: Hardware control: `IeeeFlags` and `FloatingPointControl`.) +) +) + +$(P +All public symbols are still accessible using `std.math` as usual. +) +) + +$(LI $(LNAME2 splitwhen,splitWhen added to std.algorithm.iteration) +$(CHANGELOG_SOURCE_FILE phobos, changelog/splitwhen.dd) +$(P +$(REF splitWhen, std, algorithm, iteration) is a variant of the existing $(REF +chunkBy, std, algorithm, iteration) function that does not require its predicate +to be an equivalence relation, allowing it to be used in ways that chunkBy +cannot. For example: +) +------- +// Grouping by maximum adjacent difference: +import std.math : abs; +import std.algorithm; +auto r3 = [1, 3, 2, 5, 4, 9, 10].splitWhen!((a, b) => abs(a-b) >= 3); +assert(r3.equal!equal([ + [1, 3, 2], + [5, 4], + [9, 10] +])); +------- + +$(P +This would have an undefined result with chunkBy, because it requires that if +pred(a,b) and pred(b,c) return true, pred(a,c) must also return true. +) +) + +$(LI $(LNAME2 std-datetime,The old benchmarking functionality in `std.datetime` has been removed.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-datetime.dd) +$(P +It had been deprecated in 2.077.0 in favor of +`std.datetime.stopwatch`, which uses `core.time.MonoTime` and +`core.time.Duration`. +) +) + +$(LI $(LNAME2 std-exception,`std.exception.enforceEx` has been removed.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-exception.dd) +$(P +It had been deprecated in 2.079 in favor of `std.exception.enforce`. +) +) + +$(LI $(LNAME2 std-sumtype,New module: `std.sumtype`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std-sumtype.dd) +$(P +The [`sumtype` package](https://code.dlang.org/packages/sumtype) from +code.dlang.org has been added to the standard library as `std.sumtype`. +) + +$(P +It provides `SumType`, a generic discriminated union implementation that uses +[design-by-introspection](https://www.youtube.com/watch?v=HdzwvY8Mo-w) to +generate safe and efficient code, and is intended to serve as a replacement for +the legacy `std.variant.Algebraic`. +) + +$(P +Features of `SumType` include: +) + +$(P +* Pattern matching. +* Support for self-referential types. +* Full compatibility with `pure`, `@safe`, `@nogc`, `nothrow`, and `scope`. +* No dependency on runtime type information (`TypeInfo`). +* Compatibility with BetterC. +) + +$(P +Example usage: +) + +--- +import std.sumtype; +import std.math : isClose; + +struct Fahrenheit { double degrees; } +struct Celsius { double degrees; } +struct Kelvin { double degrees; } + +alias Temperature = SumType!(Fahrenheit, Celsius, Kelvin); + +// Construct from any of the member types. +Temperature t1 = Fahrenheit(98.6); +Temperature t2 = Celsius(100); +Temperature t3 = Kelvin(273); + +// Use pattern matching to access the value. +Fahrenheit toFahrenheit(Temperature t) +{ + return Fahrenheit( + t.match!( + (Fahrenheit f) => f.degrees, + (Celsius c) => c.degrees * 9.0/5 + 32, + (Kelvin k) => k.degrees * 9.0/5 - 459.4 + ) + ); +} + +assert(toFahrenheit(t1).degrees.isClose(98.6)); +assert(toFahrenheit(t2).degrees.isClose(212)); +assert(toFahrenheit(t3).degrees.isClose(32)); + +// Use ref to modify the value in place. +void freeze(ref Temperature t) +{ + t.match!( + (ref Fahrenheit f) => f.degrees = 32, + (ref Celsius c) => c.degrees = 0, + (ref Kelvin k) => k.degrees = 273 + ); +} + +freeze(t1); +assert(toFahrenheit(t1).degrees.isClose(32)); + +// Use a catch-all handler to give a default result. +bool isFahrenheit(Temperature t) +{ + return t.match!( + (Fahrenheit f) => true, + _ => false + ); +} + +assert(isFahrenheit(t1)); +assert(!isFahrenheit(t2)); +assert(!isFahrenheit(t3)); +--- +) + +$(LI $(LNAME2 transposed-remove-save,`std.range.Transposed`: Remove deprecated member `save`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/transposed-remove-save.dd) +$(P +`Transposed` never worked as forward range. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 add_lowmem,Added support for low memory compilation option to the $(LINK2 https://dub.pm/settings, dub settings file).) +$(CHANGELOG_SOURCE_FILE dub, changelog/add_lowmem.dd) +$(P +To enable, set `defaultLowMemory` to `true`. For dmd and ldc, the `-lowmem` command-line option is added when compiling. +) + +``` +{ + "defaultLowMemory": true +} +``` +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 21752): Template constraint breaks nested eponymeous template) +$(LI $(BUGZILLA 21802): opAssign and opOpAssign treat lazy void parameters inconsistently) +$(LI $(BUGZILLA 21880): [REG 2.095] scope variable assigned to non-scope parameter calling function) +$(LI $(BUGZILLA 21898): Qualifier ignored in alias definition if parentheses are not present) +$(LI $(BUGZILLA 21914): naked assembler functions get wrong offset to parameters) +$(LI $(BUGZILLA 21936): [REG 2.080.1] Segfault when compiled with -dip1000) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 2450): Error using operators from named template mixin) +$(LI $(BUGZILLA 13815): Inconsistent goto jump behavior between compile-time and runtime) +$(LI $(BUGZILLA 14114): Allow volatileLoad/Store to access null location) +$(LI $(BUGZILLA 14145): opDispatch not considered when function body doesn't compile) +$(LI $(BUGZILLA 14740): __traits$(LPAREN)allMembers$(RPAREN) returns erroneous 'this' member for types declared in functions.) +$(LI $(BUGZILLA 14954): extern opaque struct instance doesn't compile) +$(LI $(BUGZILLA 15478): cases of missed CTFE evaluation when defining arrays dimensions) +$(LI $(BUGZILLA 16472): Spurious "is used as a type" when aliasing enum template as default parameter) +$(LI $(BUGZILLA 17146): Internal error: tk.c 266 with -O -inline) +$(LI $(BUGZILLA 18251): deprecate + transition=complex shouldn't look at functions with non-matching if constraints) +$(LI $(BUGZILLA 19387): [dip1000] __fieldPostblit should be scope or deduce scope qualifier) +$(LI $(BUGZILLA 19443): core.simd generates MOVLPS instead of MOVHLPS) +$(LI $(BUGZILLA 19783): Fail to emplace struct with betterC) +$(LI $(BUGZILLA 20460): [OSX] DMD writes the same address everywhere in DWARF debug infos) +$(LI $(BUGZILLA 20581): DIP1000 wrongly flags hidden ref temporary) +$(LI $(BUGZILLA 20599): cpp_long as enum type doesn't work) +$(LI $(BUGZILLA 20704): `-preview=rvaluerefparam` does not work with `init` as default parameter) +$(LI $(BUGZILLA 20855): stack overflow when compiling large file) +$(LI $(BUGZILLA 21403): dmd/backend/cgcs.d:375 assert failed) +$(LI $(BUGZILLA 21651): Unimported package doesn't error out when used as part of fully qualified type) +$(LI $(BUGZILLA 21661): Can't use fully-qualified name of the current module inside an expression) +$(LI $(BUGZILLA 21665): Void initialization should not be allowed for instances of struct with invariant) +$(LI $(BUGZILLA 21668): Cannot declare ref parameter of opaque type) +$(LI $(BUGZILLA 21672): [REG][ICE][SIMD] accessing SIMD type as a short causes compiler ice) +$(LI $(BUGZILLA 21680): inconsistent error on `typeof$(LPAREN){ return field; }$(LPAREN)$(RPAREN)$(RPAREN)`) +$(LI $(BUGZILLA 21684): Assert fail for Win32 with a struct larger than 64k in size) +$(LI $(BUGZILLA 21699): Duplicate error for index out of bounds at compile time) +$(LI $(BUGZILLA 21726): Wrong comparison in package$(LPAREN)...$(RPAREN) visibilities) +$(LI $(BUGZILLA 21739): debug case can access variable from other case) +$(LI $(BUGZILLA 21742): dot template expressions don't have the void type like any template) +$(LI $(BUGZILLA 21743): getOverloads fails to propagate 'this' expression for template member) +$(LI $(BUGZILLA 21753): Struct literal with function literal member not allowed as template value argument) +$(LI $(BUGZILLA 21765): Assignment-as-condition error with checkaction=context) +$(LI $(BUGZILLA 21779): assert not omitted for -release -checkaction=context) +$(LI $(BUGZILLA 21785): Cannot declare variable of opaque enum with base type) +$(LI $(BUGZILLA 21791): Stack overflow for forward-referenced enum initializer) +$(LI $(BUGZILLA 21792): Enum using itself as base type crashes dmd) +$(LI $(BUGZILLA 21793): Cannot initialize shared member with -preview=nosharedaccess) +$(LI $(BUGZILLA 21797): Stack overflow for forward-referenced enum min / max) +$(LI $(BUGZILLA 21812): __traits$(LPAREN)allMembers$(RPAREN) on types with value tuples return ghost members) +$(LI $(BUGZILLA 21816): testing XMM for nan does not work) +$(LI $(BUGZILLA 21822): Optimizer flowlv$(LPAREN)$(RPAREN) does not account for OPmemcmp and OPstrcmp) +$(LI $(BUGZILLA 21825): DIP1034: Do not spuriously warn "calling XXX without side effects discards return value of type 'noreturn'") +$(LI $(BUGZILLA 21826): MSCOFF output for Win32 should not use EBP for anything other than the frame pointer) +$(LI $(BUGZILLA 21827): Null pointer exception in elToPair$(LPAREN)$(RPAREN) in backend/cgelem.d) +$(LI $(BUGZILLA 21828): Enum forward-references just assume int base type) +$(LI $(BUGZILLA 21830): Wrong deprecation message when non-deprecated template in static condition) +$(LI $(BUGZILLA 21831): Wrong deprecation message in template parameters before evaluating constraints) +$(LI $(BUGZILLA 21832): Wrong deprecation message when importing non-deprecated template in static condition) +$(LI $(BUGZILLA 21833): Optimizer incorrectly rewrites integer comparison to unsigned short comparison) +$(LI $(BUGZILLA 21849): UTF8: -verrors=context doesn't respect multibyte characters) +$(LI $(BUGZILLA 21861): ctfe fails when a nested enum or function has a UDA) +$(LI $(BUGZILLA 21870): Property/method not invoked and requires $(LPAREN)$(RPAREN) when used in static array length) +$(LI $(BUGZILLA 21874): The test suite fails with most recent GDB versions) +$(LI $(BUGZILLA 21876): Zero-length static arrays "cannot be read at compile time") +$(LI $(BUGZILLA 21878): "ref" lost when indexing array in CTFE) +$(LI $(BUGZILLA 21882): [ICE][dip1021] src/dmd/escape.d$(LPAREN)1850$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 21883): poor error message when swapping order of base class and interface) +$(LI $(BUGZILLA 21918): segfault in getParameterStorageClasses on auto function with error) +$(LI $(BUGZILLA 21927): ICE $(LPAREN)illegal instruction$(RPAREN) with static foreach over empty member template) +$(LI $(BUGZILLA 21940): Compiler flags -check=on/off not recognized) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 16140): while$(LPAREN)auto x = y$(RPAREN) does not behave like if$(LPAREN)auto x = y$(RPAREN)) +$(LI $(BUGZILLA 20068): Union initialization in constructors should be @safe) +$(LI $(BUGZILLA 21203): Accept pragma$(LPAREN)mangle$(RPAREN) on aggregate types) +$(LI $(BUGZILLA 21585): add __traits$(LPAREN)totype, string$(RPAREN) to convert mangled type string to an existing type) +$(LI $(BUGZILLA 21630): assert$(LPAREN)0$(RPAREN) and assert$(LPAREN)false$(RPAREN) should not be marked for coverage) +$(LI $(BUGZILLA 21835): Operation on float should use XMM register, not x87) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 21716): std.regex performance regression $(LPAREN)additional GC allocation$(RPAREN)) +$(LI $(BUGZILLA 21725): Specifying null as bitfields variable name now fails) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 8424): Compile time conversions of double/floats to strings) +$(LI $(BUGZILLA 9297): Formatting of floating point values in std.format truncates reals to double) +$(LI $(BUGZILLA 15227): std.format undocumented grammar) +$(LI $(BUGZILLA 15348): std.stdio.writef format specifier error message) +$(LI $(BUGZILLA 15386): std.format.formatValue usage hangs) +$(LI $(BUGZILLA 15888): std.format should not produce deprecated hexstrings) +$(LI $(BUGZILLA 16432): JSON incorrectly parses to string) +$(LI $(BUGZILLA 17381): Checked format string is permissive after floating point argument) +$(LI $(BUGZILLA 18780): Inconsistent behavior with Variant holding int converting to unsigned types) +$(LI $(BUGZILLA 20320): format$(LPAREN)"%f"$(RPAREN) leeds to wrong output) +$(LI $(BUGZILLA 20371): std.format limited to 500 characters for floats) +$(LI $(BUGZILLA 20502): Converting std.typecons.RefCounted!T to a string gives T's storage location instead of T's fields when T is a struct without an explicit toString) +$(LI $(BUGZILLA 20534): std.format: %r on boolean gives wrong result) +$(LI $(BUGZILLA 20536): std.format: %a on reals is inconsistent with %a on float/double) +$(LI $(BUGZILLA 21456): std.format does not accept enum member with string base type as template parameter) +$(LI $(BUGZILLA 21512): RedBlackTree!Tid treats any values as duplicated except for Tid.init) +$(LI $(BUGZILLA 21575): Child processes spawned by std.process.spawnProcess accidentally inherit signal masks in parent process) +$(LI $(BUGZILLA 21592): two stack traces if high surrogate is printed) +$(LI $(BUGZILLA 21601): std.math : pow$(LPAREN)float/double, -2$(RPAREN) produces sometimes wrong result) +$(LI $(BUGZILLA 21627): macOS: std.stdio.File.sync does not guarantee to be written to disk) +$(LI $(BUGZILLA 21641): std.format: %g produces in rare circumstances inconsistent result) +$(LI $(BUGZILLA 21679): Assertion failure in Base64.encoder for empty input range of ranges) +$(LI $(BUGZILLA 21700): Long deprecated Stopwatch std.datetime is still not removed) +$(LI $(BUGZILLA 21702): avoid quadratic template expansion in constraints of multiple search term versions of std.algorithm.searching.startsWith & endsWith) +$(LI $(BUGZILLA 21704): Nullable fails to destroy static array elements) +$(LI $(BUGZILLA 21705): Nullable!T.opEquals fails for T with non-const opEquals overload) +$(LI $(BUGZILLA 21707): std.base64: Faulty input creates range error instead of Base64Exception) +$(LI $(BUGZILLA 21708): SumType.opEquals gives confusing error message) +$(LI $(BUGZILLA 21721): casting std.BigInts to built-in floating point types doesn't work without -preview=dip1000) +$(LI $(BUGZILLA 21722): toString$(LPAREN)sink, string format$(RPAREN) does not work with non-"%s" strings) +$(LI $(BUGZILLA 21724): std.algorithm.mutation.copy fails on overlapping arrays if the source array's pointer is less than the destination array's pointer) +$(LI $(BUGZILLA 21728): rawRead calls fread with NULL if invoked on closed readEnd of Pipe $(LPAREN)segfault$(RPAREN)) +$(LI $(BUGZILLA 21729): rawRead derefences null pointer if invoked on closed File $(LPAREN)segfault$(RPAREN)) +$(LI $(BUGZILLA 21730): null ptr dereferenced in ChunksImpl.opApply $(LPAREN)SIGSEGV$(RPAREN)) +$(LI $(BUGZILLA 21738): std.format.spec: singleSpec should throw on "%%") +$(LI $(BUGZILLA 21758): std.experimental.checkedint opBinaryRight with integer left-hand side does not compile for any operators except + and -) +$(LI $(BUGZILLA 21777): std.format: several issues when formatting integers with precision) +$(LI $(BUGZILLA 21814): std.format: grouping with width 0 causes floating point exception) +$(LI $(BUGZILLA 21817): std.format: %u on integer does not print unsigned value) +$(LI $(BUGZILLA 21820): std.format: formatting zero should never lead to empty string) +$(LI $(BUGZILLA 21834): std.numeric.gcd can't handle negative values) +$(LI $(BUGZILLA 21836): std.format: grouping may cause RangeError) +$(LI $(BUGZILLA 21838): std.format: Grouping garbles up %a output) +$(LI $(BUGZILLA 21840): std.format: grouping ignores space flag with %e) +$(LI $(BUGZILLA 21841): std.format: grouping produces strange result with zero precision and %e) +$(LI $(BUGZILLA 21842): std.format: "%-+05,g" adds extra comma) +$(LI $(BUGZILLA 21846): std.format: provided format string for toString does not work with grouping) +$(LI $(BUGZILLA 21853): std.format: formatting real.max in CTFE fails) +$(LI $(BUGZILLA 21863): FieldNameTuple returns emptry string for interfaces) +$(LI $(BUGZILLA 21875): std.format: wrong number of format specifiers in nested format string of associative arrays should be detected) +$(LI $(BUGZILLA 21900): std.format: round to even does not work for hex integers with letters) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 13595): Extend std.algorithm.groupBy to support non-equivalence relations) +$(LI $(BUGZILLA 16200): Faster pow implementation for integral exponents) +$(LI $(BUGZILLA 18024): checkedint.Abort and checkedint.Warn should be @safe) +$(LI $(BUGZILLA 18627): std.complex is a lot slower than builtin complex types at number crunching) +$(LI $(BUGZILLA 20756): ImplicitConversionTargets ignores interface inheritance) +$(LI $(BUGZILLA 21759): std.experimental.checkedint.Checked is not compatible with "%d" and "%x" integer format specifiers) +$(LI $(BUGZILLA 21760): std.conv.to does not know how to convert a string to a std.experimental.checkedint.Checked!T) +$(LI $(BUGZILLA 21761): make std.experimental.checkedint.Checked!T.toHash callable when Checked!T is shared) +$(LI $(BUGZILLA 21808): std.format: It should be possible to change the order of key and value of AAs.) +$(LI $(BUGZILLA 21847): std.format: %e, %g and %a should be supported for integers too) +$(LI $(BUGZILLA 21858): std.format: centering output) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 21097): [REG2.083] Stack exhaustion upon large struct .destroy) +$(LI $(BUGZILLA 21363): [REG2.094] Implementation of core.bitop.ror$(LPAREN)x,0$(RPAREN) is using UB) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 21764): checkaction=context doesn't work for empty tuples) +$(LI $(BUGZILLA 21857): TypeInfo_Array.compare can give wrong result when either array exceeds 2GB) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 21789): Codecov should use default umask for file permissions) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 21161): [Variadic Templates] uses outdated example from D1 / Tango) +$(LI $(BUGZILLA 21869): Invalid hyperlink to doxygen) +) +) +$(D_CONTRIBUTORS_HEADER 54) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Airbus5717) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Andrej Petrović) + $(D_CONTRIBUTOR Arne) + $(D_CONTRIBUTOR Ate Eskola) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR berni44) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Brian Callahan) + $(D_CONTRIBUTOR Chigusa0w0) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR DoctorNoobingstoneIPresume) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Imperatorn) + $(D_CONTRIBUTOR Jason B. Cox) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR Jon Degenhardt) + $(D_CONTRIBUTOR linkrope) + $(D_CONTRIBUTOR Lucien Perregaux) + $(D_CONTRIBUTOR Luhrel) + $(D_CONTRIBUTOR Luís Ferreira) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Max Haughton) + $(D_CONTRIBUTOR MetaLang) + $(D_CONTRIBUTOR mhh) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR nordlow) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Robert Aron) + $(D_CONTRIBUTOR Robert Schadek) + $(D_CONTRIBUTOR Roy Margalit) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Stefan Koch) + $(D_CONTRIBUTOR Tobias Pankrath) + $(D_CONTRIBUTOR Tomoya Tanjo) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR Witold Baryluk) + $(D_CONTRIBUTOR wolframw) + $(D_CONTRIBUTOR Ömer Faruk IRMAK) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.097.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.097.1.dd b/changelog/2.097.1.dd new file mode 100644 index 0000000000..dfef93a191 --- /dev/null +++ b/changelog/2.097.1.dd @@ -0,0 +1,65 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 20, 2021, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 16 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 9 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 22035): [REG 2.097][ICE] Segmentation fault parsing invalid case statement) +$(LI $(BUGZILLA 22048): [REG2.095] `alias a = int p;` compiles) +$(LI $(BUGZILLA 22084): [REG 2.097] Segmentation fault passing non-pod struct as variadic argument) +$(LI $(BUGZILLA 22121): [REG 2.097][ICE] Segmentation fault in in dmd.dsymbol.ScopeDsymbol.addAccessiblePackage) +$(LI $(BUGZILLA 22122): [REG 2.097][ICE] Segmentation fault in in dmd.access.hasPackageAccess) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 21951): Segfault on `noreturn.init`) +$(LI $(BUGZILLA 21993): Cannot cast to noreturn) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 22056): [Reg 2.074] std.traits.isFloatingPoint, isNumeric, isUnsigned, & isSigned should never be true for SIMD vectors) +$(LI $(BUGZILLA 22057): [Reg 2.074] std.traits.isNumeric & isUnsigned should not be true for enum types with character base types) +$(LI $(BUGZILLA 22058): [Reg 2.074] std.traits.isNumeric & isSigned should not be true for complex or imaginary types) +$(LI $(BUGZILLA 22093): [Reg 2.097] std.typecons.RefCounted!T for struct T without an explicit toString or alias this previously could be converted to string even when uninitialized but now cannot be) +$(LI $(BUGZILLA 22125): std.process.Config was changed to a struct but miss operator overloads, leading to user code breakage.) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 21996): -checkaction=context triggers InvalidMemoryOperationError in finalizer) +$(LI $(BUGZILLA 22024): hashOf does not work on enum types whose base type is a SIMD vector) +$(LI $(BUGZILLA 22076): hashOf$(LPAREN)S$(RPAREN) can segfault if S.toHash is forwarded via 'alias this' to a receiver which may be null) +$(LI $(BUGZILLA 22081): DWARF v5 support is utterly broken - 'illegal instruction' when throwing exceptions) +) +) +$(D_CONTRIBUTORS_HEADER 9) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Ate Eskola) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Vladimir Panteleev) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.097.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.097.2.dd b/changelog/2.097.2.dd new file mode 100644 index 0000000000..230caeb48a --- /dev/null +++ b/changelog/2.097.2.dd @@ -0,0 +1,62 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Aug 09, 2021, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 12 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 7 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 22133): [REG2.097] Breaking change in DotTemplateExp type semantics leading to e.g. isInputRange regression) +$(LI $(BUGZILLA 22157): Bad diagnostic for static/non-static overload resolution conflict) +$(LI $(BUGZILLA 22170): interface thunk doesn't set EBX to GOT) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 21912): delegate assigned to return scope variable needs closure) +$(LI $(BUGZILLA 22144): ICE$(LPAREN)dcast.d$(RPAREN): Floating point exception in castTo::CastTo::visit$(LPAREN)Expression*$(RPAREN) at dmd/dcast.d:1702) +$(LI $(BUGZILLA 22179): core.stdcpp.utility is missing in dmd binary dist) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 22176): Nullable creates autogenerated opAssign, triggering invariants) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 21110): OOB memory access, safety violation) +$(LI $(BUGZILLA 22178): [REG 2.097] Compilers do not compile on Musl Libc) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 22166): On OpenBSD and Android make core.sys.posix.arpa.inet: htonl, htons, ntohl, & ntohs work correctly on big endian architectures) +$(LI $(BUGZILLA 22167): OpenBSD core.sys.posix.semaphore: sem_t should be a pointer to an opaque struct) +$(LI $(BUGZILLA 22168): Fix non-compiling ELF32_M_INFO & ELF64_M_INFO in core.sys.*.sys.elf32 & core.sys.*.sys.elf64 for DragonFlyBSD, FreeBSD, NetBSD, & OpenBSD) +) +) +$(D_CONTRIBUTORS_HEADER 7) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Razvan Nitu) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.097.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.098.0.dd b/changelog/2.098.0.dd new file mode 100644 index 0000000000..878b335f96 --- /dev/null +++ b/changelog/2.098.0.dd @@ -0,0 +1,1398 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Oct 10, 2021, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 17 major changes and 160 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 62 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 AliasAssign,Add Alias Assignment)) +$(LI $(RELATIVE_LINK2 ImportC,Accessing C Declarations From D Via ImportC Compiler)) +$(LI $(RELATIVE_LINK2 ambiguous-lambda,Using the syntax `(args) => {}` now triggers a deprecation message)) +$(LI $(RELATIVE_LINK2 dtoh-improvements,Improvements for the C++ header generation)) +$(LI $(RELATIVE_LINK2 dtorfileds,-preview=dtorfields is now enabled by default)) +$(LI $(RELATIVE_LINK2 fix10445,Add .min, .max, etc. properties for vector types.)) +$(LI $(RELATIVE_LINK2 mutable-cases,Using a mutable variable as a switch case now triggers an error)) +$(LI $(RELATIVE_LINK2 range-error,Out of bounds array access now gives a better error message)) +$(LI $(RELATIVE_LINK2 remove_alloc,Class allocators have been removed from the language)) +$(LI $(RELATIVE_LINK2 static_this_immutable_initialization,Initialization of `immutable` global data from `static this` now triggers an error)) +$(LI $(RELATIVE_LINK2 target,Add `-target=` for operating system, c, and c++ runtime cross compilation)) +$(LI $(RELATIVE_LINK2 union_initialization,Default initialization of `union` field that isn't the first member now triggers an error)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 UniqueTypeInfoNames,TypeInfo names for aggregates are fully qualified and hence unique now)) +$(LI $(RELATIVE_LINK2 forkgc,A concurrent GC for Posix systems)) +$(LI $(RELATIVE_LINK2 improve_posix_imports,Improve POSIX imports)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 add_isValidCharacter,New function `isValidCodepoint` in `std.utf`)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 add_env,Added support for environment variables to use compilation and run(or test) option to the $(LINK2 https://dub.pm/settings, dub settings file) and dub.json/dub.sdl.)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 AliasAssign,Add Alias Assignment) +$(CHANGELOG_SOURCE_FILE dmd, changelog/AliasAssign.dd) +$(P +This adds the ability for an alias declaration inside a template to be +assigned a new value. For example, the recursive template: +) + +--- +template staticMap(alias F, T...) +{ + static if (T.length == 0) + alias staticMap = AliasSym!(); + else + alias staticMap = AliasSym!(F!(T[0]), staticMap!(T[0 .. T.length])); +} +--- + +$(P +can now be reworked into an iterative template: +) + +--- +template staticMap(alias F, T...) +{ + alias A = AliasSeq!(); + static foreach (t; T) + A = AliasSeq!(A, F!t); // alias assignment here + alias staticMap = A; +} +--- + +$(P +Using the iterative approach will eliminate the combinatorial explosion of recursive +template instantiations, eliminating the associated high memory and runtime costs, +as well as eliminating the issues with limits on the nesting depth of templates. +It will eliminate the obtuse error messages generated when deep in recursion. +) + +$(P +The grammar: +) + +--- +AliasAssign: + Identifier = Type; +--- + +$(P +is added to the expansion of DeclDef. The Identifier must resolve to a lexically +preceding AliasDeclaration: +) + +--- +alias Identifier = Type; +--- + +$(P +where the Identifier's match, and both are members of the same TemplateDeclaration. +Upon semantic processing, when the AliasAssign is encountered the Type in the +AliasAssign replaces the Type from the corresponding AliasDeclaration or any previous matching +AliasAssign. +) + +$(P +The AliasAssign grammar was previously rejected by the parser, so adding it +should not break existing code. +) +) + +$(LI $(LNAME2 ImportC,Accessing C Declarations From D Via ImportC Compiler) +$(CHANGELOG_SOURCE_FILE dmd, changelog/ImportC.dd) +$(P +One of D's best features is easy integration with C code. +There's almost a one-to-one mapping between C and a subset +of D code (known as DasBetterC). D and C code can call each +other directly. +) + +$(P +But D cannot read C code directly. In particular, the interface +to most C code comes in the form of a .h (or "header") file. +To access the declarations in the .h file and make them +available to D code, the C declarations in the .h file must somehow +be translated into D. +Although hand translating the .h files to D is not difficult, +it is tedious, annoying, and definitely a barrier to using D +with existing C code. +) + +$(P +Why can't the +D compiler simply read the .h file and extract its declarations? +Why doesn't it "just work"? +D has had great success with integrating documentation +generation into the language, as well as unit testing. Despite the +existence of many documentation generators and testing frameworks, +the simplicity of it being built in and "just working" is transformative. +) + +$(P +## The C Preprocessor +) + +$(P +Is its own language that is completely distinct from the C language +itself. It has its own grammar, its own tokens, and its own rules. +The C compiler is not even aware of the existence of the preprocessor. +(The two can be integrated, but that doesn't change the fact +that the two semantically know nothing about each other.) +The preprocessor is different enough from D that there's no hope +of translating preprocessor directives to D in anything but the most +superficial manner, any more than the preprocessor directives can +be replaced with C. +) + +$(P +## Previous Solutions +) + +$(P +### htod by Walter Bright +) + +$(P +[htod](https://dlang.org/htod.html) converts a C .h file +to a D source file, suitable for importing into D code. +htod is built from the front end of the Digital Mars C and C++ compiler. +It works just like a C or C++ compiler except that its output is source +code for a D module rather than object code. +) + +$(P +### DStep by Jacob Carlborg +) + +$(P +[DStep code](https://code.dlang.org/packages/dstep) +) + +$(P +[DStep Article](https://dlang.org/blog/2019/04/22/dstep-1-0-0/) +) + +$(P +From the Article: "DStep is a tool for automatically generating D +bindings for C and Objective-C libraries. This is implemented by +processing C or Objective-C header files and outputting D modules. +DStep uses the Clang compiler as a library (libclang) to process the header files." +) + +$(P +### dpp by Átila Neves +) + +$(P +[dpp code](https://code.dlang.org/packages/dpp/0.2.1) +) + +$(P +[dpp Article](https://dlang.org/blog/2019/04/08/project-highlight-dpp/) +) + +$(P +From the Article: "dpp is a compiler wrapper that will parse a D source +file with the .dpp extension and expand in place any #include directives +it encounters, translating all of the C or C++ symbols to D, and then +pass the result to a D compiler (DMD by default)." +) + +$(P +Like DStep, dpp relies on libclang. +) + +$(P +## Introducing ImportC, an ISO C11 Compiler +) + +$(P +Here is the next step: +) + +$(P +* Forget about the C preprocessor. +* Overlook C++. +* Put a real ISO C11 compiler in the D front end. +* Call it ImportC to distinguish this unique capability. +) + +$(P +In detail: +) + +$(P +1. Compile C code directly, but *only* C code that has already been run through +the C preprocessor. To import stdio.h into a D program, +the build script would be: +) + +$(P + gcc -E -P stdio.h >stdio.c +) + +$(P +and in the D source file: +) + +$(P + import stdio; // reads stdio.c and compiles it +) + +$(P +With gcc doing all the preprocessor work, it becomes 100% behavior compatible. +) + +$(P +2. A C compiler front end, stripped of its integrated preprocessor, is a simple +beast. It could be compiled directly into dmd's internal data structure types. +) + +$(P +3. The D part of dmd will have no idea it originated as C code. It would be +just another import. There is no change whatsoever to D. +) + +$(P +### Using ImportC As A C Compiler +) + +$(P +Instead of importing C code, dmd can be used to compile C code like a +standalone C compiler. +) + +$(P +Create the file hello.c: +) + +``` +int printf(const char*, ...); + +int main() +{ + printf("hello world\n"); +} +``` + +$(P +Compile and run it: +) + +``` +dmd hello.c +./hello +hello world! +``` + +$(P +For C code using C includes you can preprocess the C source with a C +preprocessor. Create the file testcode.c: +) + +``` +#include + +uint32_t someCodeInC(uint32_t a, uint32_t b) +{ + return a + b; +} +``` + +$(P +Preprocess the C code with the C preprocessor: +) +``` +gcc -E -P testcode.c >testcode.i +``` + +$(P +Create D file d_main.d: +) +``` +import std.stdio; +import testcode; + +void main() +{ + writeln("Result of someCodeInC(3,4) = ", someCodeInC(3, 4) ); +} +``` + +$(P +Compile and run it: +) +``` +dmd d_main.d testcode.i +./d_main +Result of someCodeInC(3,4) = 7 +``` + +$(P +The '.i' file extension can be used instead of '.c'. This makes it clear, that +preprocessed imtermediate C code is in use. The '.i' files can be created by +some generator script or a Makefile. +) + +$(P +## Implementation Details +) + +$(P +### User Experience +) + +$(P +* Error messages are spare and utilitarian. +) + +$(P +* Recovering after encountering an error is not well developed. +Only the first error message is likely to be on point. +) + +$(P +* Pretty-printing code is done in D syntax, not C. Also, +differing precedence for Relational/Equality expressions. +) + +$(P +* No warnings are emitted. ImportC doesn't care about coding style, +best practices or suspicious constructs. If ISO C says it's good, it passes. +) + +$(P +* If the ImportC code corrupts memory, overflows buffers, etc., +it will still compile. Use DasBetterC for a better way. +) + +$(P +* Symbolic debugging support is there. +) + + +$(P +### Variance From ISO C11 +) + +$(P +* Doesn't have a C Preprocessor. +The C code must be run through a preprocessor before +it can be processed by ImportC. Incorporating this into your build system +is advisable. +) + +$(P +* Tag symbols are part of the global symbol table, not the special tag +symbol table like they are supposed to reside in. +) + +$(P +* Multiple chars in char literal are not supported. +) + +$(P +* `_Atomic` as type qualifier is ignored. +) + +$(P +* `_Atomic` as type specifier is ignored. +) + +$(P +* `_Alignof` is ignored. +) + +$(P +* `_Generic` is not implemented. +) + +$(P +* `const` is transitive, as in D. A pointer to a const pointer to a mutable +value can be declared, but it'll be treated as a pointer to a const pointer +to a const value. +) + +$(P +* { initializer-list } is not implemented. +) + +$(P +* ( type-name ) { initializer-list } is not implemented. +) + +$(P +* Complex numbers are not implemented. +) + +$(P +* Forward referencing works in ImportC. All global symbols are visible +during semantic processing, +not just the ones lexically prior to the piece of code it is working on. +) + +$(P +* Semantics applied after C parsing are D semantics, not C semantics, +although they are very close. For example, implicitly converting an +`int` to a `char` will pass C without complaint, but the D semantic +pass will issue an error. +) + +$(P +### Implementation Defined Behavior +) + +$(P +The C11 Standard allows for many instances of +implementation defined behavior. +) + +$(P +* `volatile`, `restrict`, `register`, `_Noreturn` are accepted and ignored +) + +$(P +* `char` is unsigned +) + +$(P +* `inline` is ignored, as the D compiler inlines what it feels like inlining. +) + +$(P +* `long double` matches what the host C compiler does, which is not necessarily +the same as D's `real` type. +) + + +$(P +### Extensions +) + +$(P +Using a D compiler for semantic processing offers many temptations to add in +better D semantics. Inventing yet another new dialect of C is not the point +of ImportC. However, some things are useful: +) + +$(P +* Compile Time Function Execution +) + +$(P +This works. It comes in handy for writing test cases for ImportC using +`_Static_assert`. It also means that the D compiler can execute the ImportC +functions in imports just like it can for D. +) + +$(P +### Unimplemented Extensions +) + +$(P +* Much of C code makes use of extensions provided by the host C compiler. +None of these are implemented. +) + +$(P +* Alternative keywords are not implemented. You can define the alternate + keywords as macros to remove or replace them with standard keywords. +) + +``` +#define __attribute __attribute__ +#define __asm asm +#define __asm__ asm +#define __const const +#define __const__ const +#define __inline inline +#define __inline__ inline +#define __extension__ + +#include +``` + +$(P +## Future Directions +) + +$(P +### C Preprocessor +) + +$(P +Some means of incorporating this may be practical. For now, use cpp, +warp or spp. +) + +$(P +Translation of C macros to D needs to be done, as htod, DStep and dpp all +do this. +) + +$(P +### ImportC++ ? +) + +$(P +No. Use dpp. +) + +$(P +### ImportObjective-C ? +) + +$(P +No. Use DStep. +) + +$(P +### Documentation +) + +$(P +More info on ImportC will be written on [its page in the specification](https://dlang.org/spec/importc.html). +) +) + +$(LI $(LNAME2 ambiguous-lambda,Using the syntax `(args) => {}` now triggers a deprecation message) +$(CHANGELOG_SOURCE_FILE dmd, changelog/ambiguous-lambda.dd) +$(P +Newcomers from languages with built-in delegates (such as JavaScript and C#) +would often use `(args) => { /* body */ }` for delegate/function literals. +) + +$(P +However, in D, this syntax results in a `delegate` that returns a `delegate`, +without any other side effects. This may trigger hard-to-debug bugs, +therefore it is now deprecated. +) + +$(P +If a delegate returning a delegate is indeed the intended usage, +use either `(args) { return () => /* body */; }` or `(args) => () { /* body */ }`. +) +) + +$(LI $(LNAME2 dtoh-improvements,Improvements for the C++ header generation) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dtoh-improvements.dd) +$(P +The following features/bugfixes/improvements were implemented for the +experimental C++ header generator: +) + +$(P +- Declarations from template mixins are emitted into the instantation context +- (Superclass) methods aliases are emitted as `using ...` instead of `typedef ...` +- `extern(D)` symbols are no longer emitted by accident in certain situations +- `extern(D)` structs and classes are emitted if referenced by an exported symbol +- Symbols referenced from template declarations are emitted before their first use +- Forward declarations consistently include `template<...>` +- `extern(C++, class)`, `extern(C++, struct)` affects forward declarations +- Types used in reference parameters are forward declared if possible +- Renamed or local imports are emitted as `using ...` when possible +- Complex types are emitted as `_Complex`. +- Declarations are emitted before the first member access +- Global variables with invalid names in C++ are omitted +- Initializers of `union` variables/parameters omit non-active members +- Typecasts are emitted as C style, not D's `cast(...) ...` +- Structs are always tagged as `final` because D disallows `struct` inheritance +- No longer asserts for declarations using `noreturn` +- Symbol names always include template parameters and enclosing declarations + when required +- Properly emits (static / enum) members of templated aggregates +- Properly emits static arrays in template declarations +- No longer omits the parent aggregate when referencing `__gshared` variables +- No longer uses D syntax for expressions nested in unary / binary expressions +- Does not emit `public:`, ... inside of anonymous structs/unions +- Does not emit `typedef` for aliases to declaration symbols +) + +$(P +Note: The header generator is still considerer experimental, so please submit + any bugs encountered to [the bug tracker](https://issues.dlang.org). +) +) + +$(LI $(LNAME2 dtorfileds,-preview=dtorfields is now enabled by default) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dtorfileds.dd) +$(P +This preview ensures that partially constructed objects are properly destroyed +when an exception is thrown inside of an constructor. It was introduced in +2.075 and is now enabled by default. +) + +$(P +Note that code may fail to compile if a constructor with strict attributes +may call a less qualified destructor: +) + +```d +struct Array +{ + int[] _payload; + ~this() + { + import core.stdc.stdlib : free; + free(_payload.ptr); + } +} + +class Scanner +{ + Array arr; + this() @safe {} // Might call arr.~this() +} +``` + +$(P +Such code should either make the constructor `nothrow` s.t. the destructor +will never be called, or adjust the field destructors. +) + +$(P +The compiler will only issue a deprectation for attribute violations caused +by the inserted destructor call unless the `-preview=dtorfields` flag is +explicitly specified. +) +) + +$(LI $(LNAME2 fix10445,Add .min, .max, etc. properties for vector types.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/fix10445.dd) +$(P +For integral vector types, add the `.min` and `.max` properties. +) + +$(P +For floating point vector types, add the `.min`, `.max`, `.min_normal`, +`.nan`, `.infinity`, and `.epsilon` properties. +) + +$(P +The value of those properties is the value corresponsing to the vector +element type broadcast to the vector type. I.e.: +) + +--- +import core.simd; + +static assert(float4.max == cast(float4)float.max); +--- +) + +$(LI $(LNAME2 mutable-cases,Using a mutable variable as a switch case now triggers an error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/mutable-cases.dd) +$(P +Variables that are `const` or `immutable` can be used as switch cases even if they are initialized at run-time, but using variables that are mutable has been deprecated since dmd 2.073.2. +This deprecation has now been turned into an error: +) +------- +void foo(int s, int x, const int y, immutable int z) { + switch (s) { + case x: // error + case y: // allowed + case z: // allowed + default: + } +} +------- +$(P +It is advised to only use compile-time known values in `case` statements, because the presence of any run-time variable (even a `const` or `immutable` one) results in the entire switch being lowered to a series of if-else statements before code generation, instead of an efficient jump table. +Prefer regular if-statements for comparing pairs of run-time known variables. +) +) + +$(LI $(LNAME2 range-error,Out of bounds array access now gives a better error message) +$(CHANGELOG_SOURCE_FILE dmd, changelog/range-error.dd) +$(P +Errors resulting from bad indexing will now contain the length of +the array, as well as the offending index for `arr[bad]`, +or offending indices `arr[bad1 .. bad2]` for bad slices. +) + +$(P +For example: +) + +--- +void main() +{ + int[] a = [1, 2, 3]; + int b = a[7]; +} +--- + +$(P +Previously this would yield the following error when compiled and run: +) + +$(P +$(CONSOLE +dmd -run main.d +core.exception.RangeError@main.d(4): Range violation +$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH) +??:? _d_arrayboundsp [0x555765c167f9] +??:? _Dmain [0x555765c16752] +) +) + +$(P +It now yields: +) + +$(P +$(CONSOLE +dmd -run main.d +core.exception.ArrayIndexError@main.d(4): index [7] exceeds array of length 3 +$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH) +??:? _d_arraybounds_indexp [0x5647250b980d] +??:? _Dmain [0x5647250b9751] +) +) + +$(P +Similarly, in case of out of bounds slice operations: +) +--- +void main() +{ + int[] a = [1, 2, 3]; + int[] b = a[2 .. 4]; +} +--- + +$(P +$(CONSOLE +dmd -run main.d +core.exception.ArraySliceError@main.d(4): slice [2 .. 4] extends past array of length 3 +$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH) +??:? _d_arraybounds_slicep [0x5647250b980d] +??:? _Dmain [0x5647250b9751] +) +) + +$(P +The error messages for an out of bounds slice copy (`arr[a..b] = arr[c..d]`) or indexing a non-existent key in an Associative Array (`table["bad"]`) have not been updated. +) +) + +$(LI $(LNAME2 remove_alloc,Class allocators have been removed from the language) +$(CHANGELOG_SOURCE_FILE dmd, changelog/remove_alloc.dd) +$(P +Class allocators have been deprecated since v2.080.0. +) + +``` +class C +{ + new(size_t size) + { + return malloc(size); + } +} +``` + +$(P +Starting with this release all class allocators not annotated with `@disable` +will result in a compilation error. As the grammar will also be changing, there +are new deprecation messages for the old-style allocator syntax, which accepted +a non-empty parameter list and function body. +) + +``` +class C +{ + @disable new(size_t size) // Deprecation: non-empty parameter list + { + return malloc(size); // Deprecation: function definition + } +} +``` + +$(P +Example of corrective action: +) +``` +class C +{ + @disable new(); +} +``` + +$(P +See the $(LINK2 https://dlang.org/deprecate.html#Class%20allocators%20and%20deallocators, deprecated features page) +for more information. +) +) + +$(LI $(LNAME2 static_this_immutable_initialization,Initialization of `immutable` global data from `static this` now triggers an error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/static_this_immutable_initialization.dd) +$(P +The following code has been deprecated since 2.087.0. +) + +``` +module foo; +immutable int bar; +static this() +{ + bar = 42; +} +``` + +$(P +This is problematic because module constructors (`static this`) run each time a +thread is spawned, and `immutable` data is implicitly `shared`, which led to +`immutable` value being overriden every time a new thread was spawned. +) + +$(P +The corrective action for any code that still does this is to use `shared +static this` over `static this`, as the former is only run once per process. +) +) + +$(LI $(LNAME2 target,Add `-target=` for operating system, c, and c++ runtime cross compilation) +$(CHANGELOG_SOURCE_FILE dmd, changelog/target.dd) +$(P +The command line switch `-target=` can be used to specify the target the +compiler should produce code for. The format for `` is `-[-][-[-` +___ +`` is an Architecture bitness, optionally followed by instruction set (which duplicates the functionality of the `-mcpu` flag) +| `` | Architecture bitness | +|----------|----------------------------| +| `x86_64` | 64 bit | +| `x64` | 64 bit | +| `x86` | 32 bit | +| `x32` | 64bit with 32 bit pointers | +) + +$(P +| subarch features | equivalent `-mcpu` flag | +|------------------|-------------------------| +| `+sse2` | `baseline` | +| `+avx` | `avx` | +| `+avx2` | `avx2` | +) + +$(P +The architecture and subarch features are concatenated, so `x86_64+avx2` is 64bit with `avx2` instructions. +) + + +$(P +`` +___ +`` is always ignored, but supported for easier interoperability with other compilers that report and consume target triples. +) + +$(P +`` +___ +) + +$(P +`` is the operating system specifier. It may be optionally followed by a version number as in `darwin20.3.0` or `freebsd12`. For Freebsd, this sets the corresponding predefined `version` identifier, e.g. `freebsd12` sets `version(FreeBSD12)`. For other operating systems this is for easier interoperability with other compilers. +) + +$(P +| `` | Operating system | +|----------------|---------------------| +| `freestanding` | No operating system | +| `darwin` | MacOS | +| `dragonfly` | DragonflyBSD | +| `freebsd` | FreeBSD | +| `openbsd` | OpenBSD | +| `linux` | Linux | +| `solaris` | Solaris | +| `windows` | Windows | +) + +$(P +`` +___ +`` is the C runtime environment. This specifier is optional. For MacOS the C runtime environment is always assumed to be the system default. +) + +$(P +| `` | C runtime environment | Default for OS | +|----------------|------------------------------------|----------------| +| `musl` | musl-libc | | +| `msvc` | MSVC runtime | Windows | +| `bionic` | Andriod libc | | +| `digital_mars` | Digital Mars C runtime for Windows | | +| `glibc` | GCC C runtime | linux | +| `newlib` | Newlib Libc | | +| `uclibc` | uclibc | | +) + + +$(P +`` +___ +) + +$(P +`` is the C++ runtime environment. This specifier is optional. If this specifier is present the `` specifier must also be present. +) + +$(P +| `` | C++ runtime environment | Default for OS | +|----------------|--------------------------------------|---------------------------------------| +| `clang` | LLVM C++ runtime | MacOS, FreeBSD, OpenBSD, DragonflyBSD | +| `gcc` | GCC C++ runtime | linux | +| `msvc` | MSVC runtime | Windows | +| `digital_mars` | Digital Mars C++ runtime for Windows | | +| `sun` | Sun C++ runtime | Solaris | +) +) + +$(LI $(LNAME2 union_initialization,Default initialization of `union` field that isn't the first member now triggers an error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/union_initialization.dd) +$(P +The following code has been deprecated since 2.088.0 +) + +``` +union U +{ + int a; + long b = 4; +} +``` + +$(P +This is problematic because unions are default initialized to whatever the +initializer for the first field is, any other initializers present are ignored. +) + +$(P +The corrective action is to declare the `union` field with the default +initialization as the first field. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 UniqueTypeInfoNames,TypeInfo names for aggregates are fully qualified and hence unique now) +$(CHANGELOG_SOURCE_FILE druntime, changelog/UniqueTypeInfoNames.dd) +$(P +Previously, template arguments weren't fully qualified; they now are, +implying longer names in that case. +) + +$(P +`TypeInfo_Struct` instances now store the (potentially significantly shorter) +mangled name only and demangle it lazily on the first `name` or `toString()` +call (with a per-thread cache). So if you only need a unique string per +struct TypeInfo, prefer `mangledName` over computed `name` (non-`@nogc` and +non-`pure`). +) + +$(P +**Related breaking change**: `TypeInfo.toString()` isn't `pure` anymore to +account for the `TypeInfo_Struct` demangled name cache. +`TypeInfo_Class.toString()` and others are still `pure`. +) +) + +$(LI $(LNAME2 forkgc,A concurrent GC for Posix systems) +$(CHANGELOG_SOURCE_FILE druntime, changelog/forkgc.dd) +$(P +For Posix systems that support the fork() function (or the clone() on linux systems), +the conservative/precise GC can be made concurrent by enabling the 'fork' GC options in the usual ways, e.g. +by adding `--DRT-gcopt=fork:1` to the command line or by embedding +) +---- +extern(C) __gshared string[] rt_options = [ "gcopt=fork:1" ]; +---- +$(P +into your linked binary (see $(LINK $(ROOT_DIR)spec/garbage.html#gc_config)). +) + +$(P +The application continues execution and new memory is allocated from the system while the forked +process is marking heap objects. Parallel marking is disabled for the forked process so it only +uses a single thread for minimal impact on the concurrent execution of the application. +) + +$(P +This reduces "stop the world" time at the cost of needing more memory and page-protection overhead when +writing to memory currently being scanned. +) +) + +$(LI $(LNAME2 improve_posix_imports,Improve POSIX imports) +$(CHANGELOG_SOURCE_FILE druntime, changelog/improve_posix_imports.dd) +$(P +The `lwpid_t` symbol was added to `core/sys/linux/sys/procfs.d`. +The `O_CLOEXEC` symbol was added to `core/sys/posix/fcntl.d`. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 add_isValidCharacter,New function `isValidCodepoint` in `std.utf`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/add_isValidCharacter.dd) +$(P +A new function `isValidCodepoint` has been added to `std.utf`. It can +be used to check if a single character forms a valid code point. For +example the `char` `0x80` is not a valid code point, because it can +only be used in trailing characters of UTF8 sequences, whereas the +wchar `ä` is a valid character: +) + +``` +assert(!isValidCodepoint(cast(char) 0x80)); +assert(isValidCodepoint('ä')); +``` +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 add_env,Added support for environment variables to use compilation and run(or test) option to the $(LINK2 https://dub.pm/settings, dub settings file) and dub.json/dub.sdl.) +$(CHANGELOG_SOURCE_FILE dub, changelog/add_env.dd) +$(P +The following items have been added to the dub setting file: `defaultEnvironments`, `defaultBuildEnvironments`, `defaultRunEnvironments`, `defaultPreGenerateEnvironments`, `defaultPostGenerateEnvironments`, `defaultPreBuildEnvironments`, `defaultPostBuildEnvironments`, `defaultPreRunEnvironments`, `defaultPostRunEnvironments`. +They are used when there are no project-specific settings. +) + +``` +{ + "defaultEnvironments": { + "VAR": "Foo" + } +} +``` + +$(P +The following items are available in each project-specific setting: `environments`, `buildEnvironments`, `runEnvironments`, `preGenerateEnvironments`, `postGenerateEnvironments`, `preBuildEnvironments`, `postBuildEnvironments`, `preRunEnvironments`, `postRunEnvironments`. +) + +$(P +In JSON +) +``` +{ + "environments": { + "VAR": "Foo" + } +} +``` + +$(P +In SDL +) +``` +environments "VAR" "Foo" +``` +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 13009): [REG2.064] inout overload conflicts with non-inout when used via alias this) +$(LI $(BUGZILLA 21238): -deps considers only the first instantiation site of a template for dependencies) +$(LI $(BUGZILLA 21850): [REG2.093] Template inference of pure not working) +$(LI $(BUGZILLA 22035): [REG 2.097][ICE] Segmentation fault parsing invalid case statement) +$(LI $(BUGZILLA 22054): Referencing a fwd-declared field results in many error messages) +$(LI $(BUGZILLA 22075): [Reg 2.068] "AA key type S should have 'size_t toHash$(LPAREN)$(RPAREN) const nothrow @safe' if opEquals defined" is not triggered if any field of S has its own 'alias this') +$(LI $(BUGZILLA 22086): importC: RangeError@src/dmd/dscope.d$(LPAREN)469$(RPAREN): Range violation) +$(LI $(BUGZILLA 22118): Const union causes false multiple-initialization error in constructor) +$(LI $(BUGZILLA 22121): [REG 2.097][ICE] Segmentation fault in in dmd.dsymbol.ScopeDsymbol.addAccessiblePackage) +$(LI $(BUGZILLA 22122): [REG 2.097][ICE] Segmentation fault in in dmd.access.hasPackageAccess) +$(LI $(BUGZILLA 22196): importC: Error: found `const` when expecting `$(RPAREN)`in __attribute__) +$(LI $(BUGZILLA 22205): catch$(LPAREN)Exception$(RPAREN) not longer working in debug blocks) +$(LI $(BUGZILLA 22214): Regression 2.097.0: __traits$(LPAREN)compiles$(RPAREN) doesn't notice invalid getMember that yields type) +$(LI $(BUGZILLA 22224): [REG 2.097.0] compiler segfaults with -profile) +$(LI $(BUGZILLA 22226): [REG 2.095.1] __ctfe + function call in conditional expression used to initialize struct member in constructor causes ICE) +$(LI $(BUGZILLA 22228): [CTFE] taking address of immutable in frame function causes ICE on Unix platforms) +$(LI $(BUGZILLA 22292): REG[2.084.1] Recursive class literal segfaults compiler) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 13165): Using -profile does extra control flow analysis, leading to spurious statement is not reachable warning) +$(LI $(BUGZILLA 14064): Error message about @ attributes incomplete.) +$(LI $(BUGZILLA 15631): gdb: Parent's scope not considered for symbol lookup) +$(LI $(BUGZILLA 16274): The curses of debugging: short argument passed in 16-bit register, against ABI) +$(LI $(BUGZILLA 17041): foreach-ref can't use to static array's AliasSeq) +$(LI $(BUGZILLA 20150): -dip1000 defeated by pure) +$(LI $(BUGZILLA 20245): DIP1000: Should infer scope when taking address of ref) +$(LI $(BUGZILLA 21209): scope attribute inference with does not work well with foreach) +$(LI $(BUGZILLA 21868): DIP1000 doesn't catch pointer to struct temporary) +$(LI $(BUGZILLA 21905): case of IFTI failure when combining `ref`, and `alias this` on a static instance) +$(LI $(BUGZILLA 21928): Wrong location for "array literal in @nogc function main may cause GC allocation" error) +$(LI $(BUGZILLA 21931): importC: 'alias time_t = time_t;' cannot alias itself, use a qualified name to create an overload set) +$(LI $(BUGZILLA 21932): importC: enum 'ENUM' conflicts with enum 'ENUM') +$(LI $(BUGZILLA 21933): importC: struct parameters: AssertError@src/dmd/typesem.d$(LPAREN)1890$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 21934): importC: Support asm labels to specify the assembler name to use for a C symbol) +$(LI $(BUGZILLA 21937): importC: Support parsing __attribute specifiers) +$(LI $(BUGZILLA 21939): Duplicate error messages for wrong aggregate in 'static foreach') +$(LI $(BUGZILLA 21942): importC: Support parsing __inline__ keyword) +$(LI $(BUGZILLA 21944): importC: Support parsing # line marker directive extensions) +$(LI $(BUGZILLA 21945): importC AssertError@src/dmd/dsymbolsem.d$(LPAREN)4787$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 21946): importC: Support parsing __extension__ keyword) +$(LI $(BUGZILLA 21948): importC: Support declaring local variables of typedef types) +$(LI $(BUGZILLA 21949): noreturn doesn't follow covariance rules) +$(LI $(BUGZILLA 21962): importC: Empty enums are accepted as valid code) +$(LI $(BUGZILLA 21963): importC: Support declaring union types) +$(LI $(BUGZILLA 21965): importC: Anonymous top-level struct or union triggers AssertError@dsymbolsem.d$(LPAREN)4787$(RPAREN)) +$(LI $(BUGZILLA 21967): importC: Error function without 'this' cannot be 'const') +$(LI $(BUGZILLA 21968): importC: struct fields: AssertError@src/dmd/typesem.d$(LPAREN)1890$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 21970): importC: Error: variable extern symbols cannot have initializers) +$(LI $(BUGZILLA 21973): importC: AssertError@src/dmd/dsymbolsem.d$(LPAREN)4307$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 21976): importC: does not distinguish between cast-expression and unary-expression correctly) +$(LI $(BUGZILLA 21977): importC: Global declarations are thread-local by default) +$(LI $(BUGZILLA 21982): importC: Error: variable no definition of struct) +$(LI $(BUGZILLA 21985): "goto" errors with unexistent label report wrong/misleading line) +$(LI $(BUGZILLA 21992): importC: Error: variable is used as a type) +$(LI $(BUGZILLA 21994): $(LPAREN)char*$(RPAREN)"string" fails to compile) +$(LI $(BUGZILLA 22005): ICE: Segmentation fault with static foreach and -betterC) +$(LI $(BUGZILLA 22006): static foreach and foreach over tuple doesn't work on 16-bit) +$(LI $(BUGZILLA 22007): static foreach: cannot implicitly convert expression Tuple4$(LPAREN)0LU, 1$(RPAREN) of type Tuple4 to int) +$(LI $(BUGZILLA 22019): `case 1,:` allowed by grammar but not DMD) +$(LI $(BUGZILLA 22028): importC: Parser accepts initializers for struct members) +$(LI $(BUGZILLA 22029): importC: Parser accepts storage-class specifiers for fields) +$(LI $(BUGZILLA 22030): importC: Wrong error with bad declarator) +$(LI $(BUGZILLA 22032): importC: infinite loop: illegal combination of type specifiers) +$(LI $(BUGZILLA 22053): `catch {` not rejected while in a template) +$(LI $(BUGZILLA 22060): importC: Multiple forward declarations result in error struct conflicts with struct) +$(LI $(BUGZILLA 22063): importC: Error: undefined identifier 'var' with pointer-to-typedef type) +$(LI $(BUGZILLA 22066): importC: Error: expression expected, not ';' using $(LPAREN)postfix-expression$(RPAREN)++) +$(LI $(BUGZILLA 22067): importC: cast-expression accepted as lvalue in assignment-expression) +$(LI $(BUGZILLA 22068): importC: cast-expression accepted as lvalue in unary-expression) +$(LI $(BUGZILLA 22069): importC: Error: found '&' instead of statement) +$(LI $(BUGZILLA 22070): importC: Error: string literal is not an lvalue) +$(LI $(BUGZILLA 22071): importC: Error: struct literal is not an lvalue) +$(LI $(BUGZILLA 22073): importC: Error: found '.' when expecting ';' following compound literal) +$(LI $(BUGZILLA 22079): importC: Error: '=', ';' or ',' expected taking sizeof compound literal) +$(LI $(BUGZILLA 22080): ImportC: Error: cannot implicitly convert expression of type 'extern$(LPAREN)C$(RPAREN) function' to 'function') +$(LI $(BUGZILLA 22088): ImportC: C11 6.3 semantics on implicit conversions is not implemented) +$(LI $(BUGZILLA 22102): importC: Error: function is used as a type) +$(LI $(BUGZILLA 22103): importC: Parser accepts wrong syntax for array declarators) +$(LI $(BUGZILLA 22106): importC: Error: variable 'var' no definition of struct 'type') +$(LI $(BUGZILLA 22126): -checkaction=context should not print overlapped struct members) +$(LI $(BUGZILLA 22149): TypeInfo_Struct names aren't unique, leading to botched equality semantics) +$(LI $(BUGZILLA 22150): TypeInfo_Class names aren't unique, leading to botched equality semantics) +$(LI $(BUGZILLA 22160): importC: Error: redeclaring `module test` as `struct test`) +$(LI $(BUGZILLA 22180): .alignof not working for globals) +$(LI $(BUGZILLA 22182): importC: Error: expression expected, not `$(RPAREN)` when casting pointer with redundant parens.) +$(LI $(BUGZILLA 22209): NRVO variable detection ignoring `alias this` conversion => segfaults) +$(LI $(BUGZILLA 22246): importC: C11 does not allow _Alignof $(LPAREN)expression$(RPAREN)) +$(LI $(BUGZILLA 22250): ImportC: Array subscripts do not comply with C standard.) +$(LI $(BUGZILLA 22252): ImportC: Array, Function parameter types should be converted to pointers) +$(LI $(BUGZILLA 22253): ImportC expressions inadvertently supporting D properties) +$(LI $(BUGZILLA 22262): importC: Error: incompatible types for '$(LPAREN)buf$(RPAREN) is $(LPAREN)0$(RPAREN)': 'ubyte*' and 'int') +$(LI $(BUGZILLA 22263): ImportC: function and variable re-declarations should be allowed) +$(LI $(BUGZILLA 22264): importC: Error: '=', ';' or ',' expected using K&R function syntax) +$(LI $(BUGZILLA 22265): importC: Error: cannot modify 'const' expression) +$(LI $(BUGZILLA 22274): importC: [ICE]: 4 identifiers does not match 3 declarations using K&R syntax) +$(LI $(BUGZILLA 22275): importC: Error: incompatible types for $(LPAREN)dest$(RPAREN) !is $(LPAREN)buf$(RPAREN): char* and char[1]) +$(LI $(BUGZILLA 22286): importC: $(LPAREN)identifier$(RPAREN)$(LPAREN)other_identifier$(RPAREN) incorrectly parsed as a cast-expression) +$(LI $(BUGZILLA 22294): importC: enums aren’t placed in surrounding namespace.) +$(LI $(BUGZILLA 22303): ImportC: pragma directives should be ignored) +$(LI $(BUGZILLA 22304): importC: parsing gnu-style attributes fails if return type is pointer) +$(LI $(BUGZILLA 22312): importC: redundant typedefs are rejected) +$(LI $(BUGZILLA 22313): ImportC: account for $(LPAREN) $(RPAREN) when doing lookahead on assignment-expressions) +$(LI $(BUGZILLA 22314): ImportC: fails to parse gnu attributes on enum members) +$(LI $(BUGZILLA 22321): ImportC: non-static arrays can’t be initialized by an initializer list.) +$(LI $(BUGZILLA 22322): ImportC: struct with floating point members causes problems with generated toHash$(LPAREN)$(RPAREN) function) +$(LI $(BUGZILLA 22326): ImportC: struct with flexible array member is incorrectly handled) +$(LI $(BUGZILLA 22329): DMD and LDC2 Segumentation Faults due to alias this on private field + special names) +$(LI $(BUGZILLA 22333): ImportC: fails to parse enumerators with = and gnu attributes) +$(LI $(BUGZILLA 22373): Glue layer rejects cast from noreturn to other type) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 15889): Array bounds check should report index and length) +$(LI $(BUGZILLA 16001): Lambda syntax: forbid use with FunctionLiteralBody: $(LPAREN)x$(RPAREN) => {assert$(LPAREN)x$(RPAREN);}) +$(LI $(BUGZILLA 16689): Errors in instantiated mixin templates should show instantiation point) +$(LI $(BUGZILLA 17400): put a new line before "candidates are:" in error messages) +$(LI $(BUGZILLA 18907): Support cross-compiling) +$(LI $(BUGZILLA 21885): Bad diagnostic: struct is not copyable because it is annotated @disable) +$(LI $(BUGZILLA 21997): CTFE should allow function pointer casts with different attributes) +$(LI $(BUGZILLA 22038): final switch error message should report all missing enum members) +$(LI $(BUGZILLA 22115): Optimize if $(LPAREN)s.a == 3 ? s : null$(RPAREN) to if $(LPAREN)s.a == 3$(RPAREN)) +$(LI $(BUGZILLA 22138): foreach cannot declare the loop variables as scope) +$(LI $(BUGZILLA 22227): `if $(LPAREN)scope f = x$(LPAREN)$(RPAREN)$(RPAREN)` and `while $(LPAREN)scope f = x$(LPAREN)$(RPAREN)$(RPAREN)` do not parse) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 21920): [REG master] Error: `auto` can only be used as part of `auto ref` for template function parameters) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 19727): std.algorithm.endsWith fails to compile while startsWith succeeds) +$(LI $(BUGZILLA 20393): formattedRead accepts input, that should be rejected) +$(LI $(BUGZILLA 20937): std.range.array of a lengthless range with indirection is not @safe) +$(LI $(BUGZILLA 21916): Error message is obfuscated when using wrong format specifier at compile-time) +$(LI $(BUGZILLA 22001): Equality of std.conv.toChars$(LPAREN)$(RPAREN) results for radix 10 depends on uninitialized bytes) +$(LI $(BUGZILLA 22077): `std.sumtype` support for copy constructors is incomplete) +$(LI $(BUGZILLA 22101): Nullable.get$(LPAREN)fallback$(RPAREN) cannot be used with non-@safe/pure/nothrow types) +$(LI $(BUGZILLA 22110): isCallable fails for template opCall without any templated argument) +$(LI $(BUGZILLA 22140): FunctionTypeOf fails for template opCall without any templated argument) +$(LI $(BUGZILLA 22146): std.algorithm.searching.findAdjacent$(LPAREN)$(RPAREN) can fall off end of function) +$(LI $(BUGZILLA 22222): Custom unittest runner on phobos fails due to segfault on fork$(LPAREN)$(RPAREN) exiting) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 16210): std.utf.byUTF can be made into a bidirectional range) +$(LI $(BUGZILLA 16218): Windows std.file.readImpl should be marked @system) +$(LI $(BUGZILLA 18632): enable use of fromStringz with char[n]) +$(LI $(BUGZILLA 20665): std.concurrency.spawn should document not working with delegates) +$(LI $(BUGZILLA 21926): Allow leading zeros in std.conv.octal) +$(LI $(BUGZILLA 22100): Support chained assignment of Nullable) +$(LI $(BUGZILLA 22225): SumType: Some assignments should be able to execute in safe code) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 9799): Missing aliases and enums in druntime imports) +$(LI $(BUGZILLA 14439): aa's keys, values not usable in @safe context) +$(LI $(BUGZILLA 21550): core.memory.__delete does not actually work) +$(LI $(BUGZILLA 21983): dup leaves a partially constructed array if postblit/copy ctor throws) +$(LI $(BUGZILLA 21996): -checkaction=context triggers InvalidMemoryOperationError in finalizer) +$(LI $(BUGZILLA 22024): hashOf does not work on enum types whose base type is a SIMD vector) +$(LI $(BUGZILLA 22026): checkaction=context: Exception thrown by toString hides assertion failures) +$(LI $(BUGZILLA 22076): hashOf$(LPAREN)S$(RPAREN) can segfault if S.toHash is forwarded via 'alias this' to a receiver which may be null) +$(LI $(BUGZILLA 22081): DWARF v5 support is utterly broken - 'illegal instruction' when throwing exceptions) +$(LI $(BUGZILLA 22085): checkaction=context doesn't support extern$(LPAREN)C++$(RPAREN) classes) +$(LI $(BUGZILLA 22107): [scope][dip1000] Can't .dup an array of structs with impure copy constructor) +$(LI $(BUGZILLA 22143): Throwable ctor doesn't increment chained exception's ref count) +$(LI $(BUGZILLA 22218): Dynamic casts across binary boundaries can easily fail) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 22169): Mark as pure core.sys.posix.string: memccpy, stpcpy, stpncpy, strnlen) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 3345): Static and nonstatic methods with the same name should be allowed) +$(LI $(BUGZILLA 20557): Spec does not allow StringPostfix after DelimitedString or TokenString while implementation does) +$(LI $(BUGZILLA 21125): Typo in std.range.refRange documentation for opIndex) +$(LI $(BUGZILLA 21906): obscure sentence in the introduction to phases of compilation) +$(LI $(BUGZILLA 21935): Broken Link in Lazy Evaluation Article) +$(LI $(BUGZILLA 22229): Struct initialization via constructor missing from language spec) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 21495): File.readf documentation does not state what what is returned.) +$(LI $(BUGZILLA 21600): Regex.namedCaptures is undocumented) +) +$(BUGSTITLE_BUGZILLA Installer bug fixes, + +$(LI $(BUGZILLA 21488): Bundled 32-bit dlang tools $(LPAREN)ddemangle, dustmite, rdmd$(RPAREN) segfault on startup) +) +) +$(D_CONTRIBUTORS_HEADER 62) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Airbus5717) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Andrei David) + $(D_CONTRIBUTOR Andrej Petrović) + $(D_CONTRIBUTOR Ate Eskola) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR avaj) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR berni44) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Brandon Mitchell) + $(D_CONTRIBUTOR Brian Callahan) + $(D_CONTRIBUTOR Cameron Ross) + $(D_CONTRIBUTOR Carsten Schlote) + $(D_CONTRIBUTOR Craig Barnes) + $(D_CONTRIBUTOR dandrei279) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR DoctorNoobingstoneIPresume) + $(D_CONTRIBUTOR drug007) + $(D_CONTRIBUTOR Etienne Brateau) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR João Lourenço) + $(D_CONTRIBUTOR linkrope) + $(D_CONTRIBUTOR lucica28) + $(D_CONTRIBUTOR Luís Ferreira) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Max Haughton) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR nordlow) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Ramanuj) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Richard Manthorpe) + $(D_CONTRIBUTOR RUSshy) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR Sinisa Susnjar) + $(D_CONTRIBUTOR Stefan Koch) + $(D_CONTRIBUTOR Teodor Dutu) + $(D_CONTRIBUTOR Tomoya Tanjo) + $(D_CONTRIBUTOR TungstenHeart) + $(D_CONTRIBUTOR vladchicos) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR Walter Waldron) + $(D_CONTRIBUTOR Witold Baryluk) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.098.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.098.1.dd b/changelog/2.098.1.dd new file mode 100644 index 0000000000..d137bd31f7 --- /dev/null +++ b/changelog/2.098.1.dd @@ -0,0 +1,179 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Dec 19, 2021, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 106 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 18 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 20133): [REG2.084.0] Bogus slice assignment in recursive CTFE call) +$(LI $(BUGZILLA 20236): spurious deprecation warnings on function calls within with$(LPAREN)X$(RPAREN) blocks while X has a deprecated alias this target) +$(LI $(BUGZILLA 20860): OpDispatch does not work for structs with constructor and destructor) +$(LI $(BUGZILLA 20998): error in static struct initialization causes wrong position for subsequent members, producing extra errors) +$(LI $(BUGZILLA 21039): `alias this` returns 'null' for ref types when put into array initializer) +$(LI $(BUGZILLA 21073): Rebindable does not work when class has alias this to inout property) +$(LI $(BUGZILLA 21380): A case of compiler crash when using auto ref) +$(LI $(BUGZILLA 21414): Spurious "non-constant expression" error with immutable constructors) +$(LI $(BUGZILLA 21438): Compiler segfault on static array in a struct at CTFE) +$(LI $(BUGZILLA 22004): [REG2.097] Error: mismatched function return type inference of `void` and `noreturn`) +$(LI $(BUGZILLA 22151): Compiler crash when attempting to assign to function) +$(LI $(BUGZILLA 22300): [REG 2.098-rc.2] `-checkaction=context` of a `shared` type with an `opCast` fails to compile) +$(LI $(BUGZILLA 22385): CTFE fails to iterate over associative array previously indexed with implicit conversion to enum base type) +$(LI $(BUGZILLA 22410): [REG2.094] function with tuple parameter with default argument fails if there's a qualifier) +$(LI $(BUGZILLA 22420): [REG2.098] Apparent CTFE regression wrt. alias this) +$(LI $(BUGZILLA 22472): Invalid error message for `void` return from non-`void` functions) +$(LI $(BUGZILLA 22512): importC: incomplete array type must have initializer) +$(LI $(BUGZILLA 22514): Invalid duplicate case error when the switched value has errors) +$(LI $(BUGZILLA 22516): Segfault for function literal in struct initializer with previous errors) +$(LI $(BUGZILLA 22529): wrong deprecation about empty statement) +$(LI $(BUGZILLA 22558): [REG 2.098] Error: function 'core.stdc.stdio.vfprintf' 'pragma$(LPAREN)printf$(RPAREN)' functions must be 'extern$(LPAREN)C$(RPAREN) int vfprintf$(LPAREN)[parameters...], const$(LPAREN)char$(RPAREN)*, va_list$(RPAREN)') +$(LI $(BUGZILLA 22570): more arguments than fields allowed in struct constructor) +$(LI $(BUGZILLA 22584): importC: Error: undefined reference to 'parameter' when no parameter names in forward declaration) +$(LI $(BUGZILLA 22585): importC: Error: variable 'var' extern symbols cannot have initializers) +$(LI $(BUGZILLA 22592): importC: Segmentation fault indexing global array at run-time) +$(LI $(BUGZILLA 22593): ICE on overloaded constructors) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 16579): ReturnStatement[CallExp$(LPAREN)DotVarExp$(RPAREN)]: Corrupted runtime on missed manifest constant propagation) +$(LI $(BUGZILLA 18054): Wrong cast of float constant to bool) +$(LI $(BUGZILLA 19660): 'export' keyword on OSX/Linux globals causing segfaults) +$(LI $(BUGZILLA 21093): [ICE] AssertError@dmd/optimize.d$(LPAREN)691$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 21794): Internal compiler assertion) +$(LI $(BUGZILLA 21930): ICE $(LPAREN)illegal instruction$(RPAREN) with bad code) +$(LI $(BUGZILLA 21950): cod1: Assertion failure for noreturn parameter) +$(LI $(BUGZILLA 21952): ice for global / tls variable of type noreturn) +$(LI $(BUGZILLA 21957): ice when dmd computes the alignment of an union containing a noreturn) +$(LI $(BUGZILLA 22104): importC: Parser accepts arrays with incomplete element types) +$(LI $(BUGZILLA 22315): ImportC: #pragma pack is not implemented) +$(LI $(BUGZILLA 22323): Link error for virtual destructor of C++ class in DLL) +$(LI $(BUGZILLA 22362): ImportC: error parsing compound literal with more than one value at function scope.) +$(LI $(BUGZILLA 22375): importC: Error: C non-array initializer not supported yet) +$(LI $(BUGZILLA 22376): importC: Error: cannot use non-constant CTFE pointer in an initializer) +$(LI $(BUGZILLA 22388): Wrong overload selected for @safe delegate) +$(LI $(BUGZILLA 22389): noreturn functions are allowed to return normally) +$(LI $(BUGZILLA 22398): importC: Error: unknown, when compiling source with non-constant initializer.) +$(LI $(BUGZILLA 22399): importC: Error: static variable cannot be read at compile time) +$(LI $(BUGZILLA 22400): importC: Error: unknown, when compiling source with typedef'd initializer) +$(LI $(BUGZILLA 22402): importC: Error: can't subtract '__tag2[1]' from pointer) +$(LI $(BUGZILLA 22403): importC: Error: cannot pass argument '0' of type 'int' to parameter 'const$(LPAREN)char$(RPAREN)*') +$(LI $(BUGZILLA 22405): importC: Error: cannot modify 'const' expression '$(LPAREN)*s$(RPAREN).field') +$(LI $(BUGZILLA 22406): importC: Error: 'switch' statement without a 'default'; use 'final switch' or add 'default: assert$(LPAREN)0$(RPAREN);' or add 'default: break;') +$(LI $(BUGZILLA 22407): importC: Error: cannot implicitly convert expression of type 'extern $(LPAREN)C$(RPAREN) int$(LPAREN)int a$(RPAREN)' to 'const$(LPAREN)extern $(LPAREN)C$(RPAREN) int function$(LPAREN)int$(RPAREN)$(RPAREN)') +$(LI $(BUGZILLA 22409): importC: [ICE] Error: struct no size because of forward reference) +$(LI $(BUGZILLA 22411): importC: Error: cannot implicitly convert expression of type 'const$(LPAREN)char*$(RPAREN)' to 'char*') +$(LI $(BUGZILLA 22413): importC: Error: array index 0 is out of bounds) +$(LI $(BUGZILLA 22422): ImportC: parse gnu attributes after a function parameter) +$(LI $(BUGZILLA 22428): importC: static variables/functions emit global symbols) +$(LI $(BUGZILLA 22432): ImportC: casting result of postfix operator on a parenthesized expression to a typedef’d type is parsed incorrectly) +$(LI $(BUGZILLA 22461): OpenBSD: Use fmodl) +$(LI $(BUGZILLA 22462): OpenBSD: bash lives in /usr/local) +$(LI $(BUGZILLA 22463): OpenBSD: Allow DMD to work on 32-bit OpenBSD) +$(LI $(BUGZILLA 22500): ImportC: Lots of errors when compiling tomlc99) +$(LI $(BUGZILLA 22513): ImportC: address of member of struct can’t be taken at compile time.) +$(LI $(BUGZILLA 22517): [REG 2.093][ICE] Bus error at dmd/lexer.d:398) +$(LI $(BUGZILLA 22530): Explicit cast between classes incorrectly goes through 'alias this' inside CTFE) +$(LI $(BUGZILLA 22531): importC: D name mangling applied to forward declaration of function inside function) +$(LI $(BUGZILLA 22534): ImportC: const pointer $(LPAREN)not pointer to const$(RPAREN) is treated as transitive const) +$(LI $(BUGZILLA 22538): importC: function 'func' conflicts with function 'func' when using static in forward declaration) +$(LI $(BUGZILLA 22549): importC: float literal should support leading zero) +$(LI $(BUGZILLA 22560): ImportC: extra semicolon not allowed outside of functions) +$(LI $(BUGZILLA 22573): DMD compiler errors on Illumos/Solaris) +$(LI $(BUGZILLA 22576): ImportC: cannot implicitly convert expression S$(LPAREN)0$(RPAREN) of type S to int in an S array) +$(LI $(BUGZILLA 22577): ImportC: decay of function to typedef'd const function pointer causes ICE.) +$(LI $(BUGZILLA 22589): importC: Error: undefined reference to '__builtin_va_start' and '__builtin_va_end') +$(LI $(BUGZILLA 22591): importC: Debug information for C sources have DW_AT_language set to D.) +$(LI $(BUGZILLA 22597): importC: Segmentation fault initializing va_list with __builtin_va_start) +$(LI $(BUGZILLA 22602): importC: Error: cannot convert string literal to 'void*') +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 22474): OpenBSD: Add support to test/runnable/dhry.d) +$(LI $(BUGZILLA 22475): OpenBSD: Disable test/compilable/cdcmp.d on OpenBSD) +$(LI $(BUGZILLA 22476): OpenBSD: Add OpenBSD to the fail_compilation/fail21227_win.d ignore list) +$(LI $(BUGZILLA 22477): OpenBSD: Add to fail_compilation/fail3753.d ignore list) +$(LI $(BUGZILLA 22478): OpenBSD: Add to fail_compilation/invalid_lib.d) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 16705): [REG2.069] TaskPool.reduce fails to compile "cannot get frame pointer to D main") +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 22458): OpenBSD: Add OpenBSD to std/system.d OS list) +$(LI $(BUGZILLA 22487): Array!T.init.data crashes) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 22393): OpenBSD: Add polyImpl implementation for x86) +$(LI $(BUGZILLA 22488): data should work with const/immutable Array's) +$(LI $(BUGZILLA 22511): Nullable is not copyable when templated type has elaborate copy ctor) +$(LI $(BUGZILLA 22557): std.traits.fqnType is missing support for typeof$(LPAREN)null$(RPAREN)) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 21656): [REG2.091] Wrong file read during exception stringification leads to SIGBUS) +$(LI $(BUGZILLA 22210): std.meta.allSatisfy in mutual recursion classes cannot be compiled) +$(LI $(BUGZILLA 22235): `core.demangle` does not support `noreturn`) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 21919): darwin: SEGV in core.thread tests on OSX 11) +$(LI $(BUGZILLA 22416): Unify polyImpl implementations) +$(LI $(BUGZILLA 22440): OpenBSD: Sync sysctl.d) +$(LI $(BUGZILLA 22443): OpenBSD: Fix Fiber support by adding MAP_STACK) +$(LI $(BUGZILLA 22453): OpenBSD: Add a dummy value for AI_V4MAPPED) +$(LI $(BUGZILLA 22455): Remove useless conditional assignment of DISABLED_TESTS in posix.mak) +$(LI $(BUGZILLA 22456): OpenBSD: timer_* functions don't exist on OpenBSD) +$(LI $(BUGZILLA 22485): OpenBSD: Fix core.sys.openbsd.unistd imports) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 22395): OpenBSD: Add more OpenBSD-specific function prototypes in string.d and unistd.d) +$(LI $(BUGZILLA 22439): OpenBSD: Sync mman.d) +$(LI $(BUGZILLA 22448): OpenBSD: Add OpenBSD-specific alloc and free function prototypes from stdlib.h) +$(LI $(BUGZILLA 22454): OpenBSD: Add prototypes for pthread_np.h) +$(LI $(BUGZILLA 22457): OpenBSD: enableDwarf in opApply in runtime.d) +$(LI $(BUGZILLA 22542): Explicitly cast backtrace results to int) +$(LI $(BUGZILLA 22545): OpenBSD: Always use system backtrace) +) +) +$(D_CONTRIBUTORS_HEADER 18) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Ate Eskola) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Brian Callahan) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR lucica28) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Max Haughton) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Tim Schendekehl) + $(D_CONTRIBUTOR Tomoya Tanjo) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR Ömer Faruk IRMAK) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.098.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.099.0.dd b/changelog/2.099.0.dd new file mode 100644 index 0000000000..063479d2a9 --- /dev/null +++ b/changelog/2.099.0.dd @@ -0,0 +1,947 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 06, 2022, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 20 major changes and 221 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 100 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 22541,When `ref scope return` attributes are used on a parameter, and `return scope` appears, the `return` applies to the `scope`, not the `ref`.)) +$(LI $(RELATIVE_LINK2 TraitsParameters,`__traits(parameters)` has been added to the compiler.)) +$(LI $(RELATIVE_LINK2 __import,Add ability to import modules to ImportC)) +$(LI $(RELATIVE_LINK2 allow_casting_from_typetuple_to_typetuple,Casting between compatible sequences)) +$(LI $(RELATIVE_LINK2 disasm,New command line switch -vasm which outputs assembler code per function)) +$(LI $(RELATIVE_LINK2 fix16997,The '-preview=intpromote' switch is now set by default.)) +$(LI $(RELATIVE_LINK2 fix18964,`-m32` now produces MS Coff objects when targeting windows)) +$(LI $(RELATIVE_LINK2 ignore_nonroot_ut,Ignore unittests in non-root modules)) +$(LI $(RELATIVE_LINK2 main_return_type,`main` can now return type `noreturn` and supports return inference)) +$(LI $(RELATIVE_LINK2 switch_fallthrough_error,Falling through switch cases is now an error)) +$(LI $(RELATIVE_LINK2 throw_expression,Throw expression as proposed by DIP 1034 have been implemented)) +$(LI $(RELATIVE_LINK2 traits_initSymbol,Added __traits(initSymbol) to obtain aggregate initializers)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 openbsd_ioctls,Add support for OpenBSD ioctls)) +$(LI $(RELATIVE_LINK2 safe_opequals,Add support for `@safe` class `opEquals`)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 checkedint,Move checkedint out of experimental.)) +$(LI $(RELATIVE_LINK2 chunkBy_mostly_safe,`chunkBy` `@safe` with forward ranges and `splitWhen` fully `@safe`)) +$(LI $(RELATIVE_LINK2 csv_un_equal_separator_count,`std.csv` can now optionally handle csv files with variable number of columns.)) +$(LI $(RELATIVE_LINK2 logger_default_warning,Change default log level for std.experimental.logger to LogLevel.warning)) +$(LI $(RELATIVE_LINK2 support_for_tuples,`std.conv.to` accepts `std.typecons` tuples)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 pdb,Windows: Copy PDB files to `targetPath`, alongside executable/DLL)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 22541,When `ref scope return` attributes are used on a parameter, and `return scope` appears, the `return` applies to the `scope`, not the `ref`.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/22541.dd) +$(P +Formerly, the `return` sometimes applied to the `ref` instead, which can be +confusing. If `return scope` does not appear adjacent and in that order, the `return` +will apply to the `ref`. +) +) + +$(LI $(LNAME2 TraitsParameters,`__traits(parameters)` has been added to the compiler.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/TraitsParameters.dd) +$(P +If used inside a function, this trait yields a +tuple of the parameters to that function for example: +) + +--- +int echoPlusOne(int x) +{ + __traits(parameters)[0] += 1; + return x; +} +--- + +$(P +This can be used to simply forward a functions parameters (becoming arguments of another), +in effect unifying functions with variadic parameters and normal functions +i.e. the following pattern is now possible without use of variadics: +) + +--- +int add(int x, int y) +{ + return x + y; +} + +auto forwardToAdd(Pack...)(Pack xy) +{ + return add(xy); +} +--- +$(P +would become +) +--- +int add(int x, int y) +{ + return x + y; +} + +auto forwardToAdd(int x, int y) +{ + return add(__traits(parameters)); +} +--- + +$(P +When used inside a nested function or lambda, the trait gets the arguments +of that and only that nested function or lambda, not what they are contained in. +) + +$(P +For example, these assertions hold: +) +--- +int testNested(int x) +{ + static assert(typeof(__traits(parameters)).length == 1); + int add(int x, int y) + { + static assert(typeof(__traits(parameters)).length == 2); + return x + y; + } + return add(x + 2, x + 3); +} +--- + +$(P +When used inside a `foreach` using an overloaded `opApply`, the trait yields +the parameters to the delegate and not the function the foreach appears within. +) + +--- +class Tree { + int opApply(int delegate(size_t, Tree) dg) { + if (dg(0, this)) return 1; + return 0; + } +} +void useOpApply(Tree top, int x) +{ + foreach(idx; 0..5) + { + static assert(is(typeof(__traits(parameters)) == AliasSeq!(Tree, int))); + } + foreach(idx, elem; top) + { + static assert(is(typeof(__traits(parameters)) == AliasSeq!(size_t, Tree))); + } +} +--- +) + +$(LI $(LNAME2 __import,Add ability to import modules to ImportC) +$(CHANGELOG_SOURCE_FILE dmd, changelog/__import.dd) +$(P +ImportC can now import modules with the __import keyword, with the C code: +) + +$(P +$(CCODE +__import core.stdc.stdarg; // import a D source file +__import test2; // import an ImportC file +) + +$(P +int foo() +{ + va_list x; + return 1 + A; +} +) +) + +$(P +test2.c is: +) + +$(P +$(CCODE +enum E { A = 3 }; +) +) + +$(P +The syntax for `__import` after the keyword is the same as for D's `import` declaration. +) +) + +$(LI $(LNAME2 allow_casting_from_typetuple_to_typetuple,Casting between compatible sequences) +$(CHANGELOG_SOURCE_FILE dmd, changelog/allow_casting_from_typetuple_to_typetuple.dd) +$(P +Prior to this release, casting between built-in sequences of the same type was not allowed. +) + +$(P +Starting with this release, casting between sequences of the same length is accepted provided that the underlying types of the casted sequence are implicitly convertible to the target sequence types. +) + +--- +alias Seq(T...) = T; + +void foo() +{ + Seq!(int, int) seq; + + auto foo = cast(long) seq; + pragma(msg, typeof(foo)); // (int, int) + + auto bar = cast(Seq!(long, int)) seq; // allowed + pragma(msg, typeof(bar)); // (long, int) +} +--- +) + +$(LI $(LNAME2 disasm,New command line switch -vasm which outputs assembler code per function) +$(CHANGELOG_SOURCE_FILE dmd, changelog/disasm.dd) +$(P +The new -vasm compiler switch will print to the console the generated assembler +code for each function. As opossed to a typical dissasembler, it will omit all +the boilerplate and output just the assembly code for each function. For example, +compiling the following code: +) + +--- +// test.d +int demo(int x) +{ + return x * x; +} +--- + +$(P +by using the command `dmd test.d -c -vasm` will yield: +) + +--- +_D4test4demoFiZi: +0000: 89 F8 mov EAX,EDI +0002: 0F AF C0 imul EAX,EAX +0005: C3 ret +--- +) + +$(LI $(LNAME2 fix16997,The '-preview=intpromote' switch is now set by default.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/fix16997.dd) +$(P +Integer promotions now follow C integral promotions rules consistently +It affects the unary `-` and `~` operators with operands of type `byte`, `ubyte`, `short`, `ushort`, `char`, or `wchar`. +The operands are promoted to `int` before the operator is applied, and the resulting type will now be `int`. +) + +$(P +To revert to the old behavor, either use the '-revert=intpromote' switch, or explicitly cast the result of the unary operator back to the smaller integral type: +) + +--- +void main() +{ + // Note: byte.max = 127, byte.min = -128 + byte b = -128; + int x = -b; // new behavior: x = 128 + int y = cast(byte)(-b); // old behavior: y = -128 + byte b2 = cast(byte) -b; // cast now required +} +--- +) + +$(LI $(LNAME2 fix18964,`-m32` now produces MS Coff objects when targeting windows) +$(CHANGELOG_SOURCE_FILE dmd, changelog/fix18964.dd) +$(P +The `-m32mscoff` switch is deprecated and `-m32` should be used in its place. +A new switch `-m32omf` has been added to produce code for OMF. Use of this switch +is discouraged because OMF will soon be unsupported. +) +) + +$(LI $(LNAME2 ignore_nonroot_ut,Ignore unittests in non-root modules) +$(CHANGELOG_SOURCE_FILE dmd, changelog/ignore_nonroot_ut.dd) +$(P +This mainly means that unittests *inside templates* are now only instantiated if +the module lexically declaring the template is one of the root modules. +) + +$(P +E.g., compiling some project with `-unittest` does NOT compile and later run any +unittests in instantiations of templates declared in other libraries anymore. +) + +$(P +Declaring unittests *inside* templates is considered an anti-pattern. In almost +all cases, the unittests don't depend on the template parameters, but +instantiate the template with fixed arguments (e.g., `Nullable!T` unittests +instantiating `Nullable!int`), so compiling and running identical tests for each +template instantiation is hardly desirable. +But adding a unittest right below some function being tested is arguably good +for locality, so unittests end up inside templates. +) + +$(P +To make sure a template's unittests are run, it should be instantiated in the +same module, e.g., some module-level unittest. +) + +$(P +This change paved the way for a more straight-forward template emission +algorithm without `-unittest` special cases, showing significant compile-time +improvements for some projects. `-allinst` now emits all templates instantiated +in root modules. +) +) + +$(LI $(LNAME2 main_return_type,`main` can now return type `noreturn` and supports return inference) +$(CHANGELOG_SOURCE_FILE dmd, changelog/main_return_type.dd) +$(P +If `main` never returns (due to an infinite loop or always throwing an +exception), it can now be declared as returning `noreturn`. +See https://dlang.org/spec/type.html#noreturn. +) + +$(P +If `main` is declared with `auto`, the inferred return type must be +one of `void`, `int` and `noreturn`. +) +) + +$(LI $(LNAME2 switch_fallthrough_error,Falling through switch cases is now an error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/switch_fallthrough_error.dd) +$(P +This was deprectated in 2.072.2 because it is a common mistake to forget a `break` statement at the end of a switch case. +The deprecation warning has now been turned into an error. +) + +$(P +If you intend to let control flow continue from one case to the next, use the `goto case;` statement. +) + +--- +void parseNumFmt(char c, out int base, out bool uppercase) +{ + switch (c) + { + case 'B': // fallthrough allowed, case has no code + case 'b': + base = 2; + // error, accidental fallthrough to case 'X' + case 'X': + uppercase = true; + goto case; // allowed, explicit fallthrough + case 'x': + base = 16; + break; + default: + break; + } +} +--- +) + +$(LI $(LNAME2 throw_expression,Throw expression as proposed by DIP 1034 have been implemented) +$(CHANGELOG_SOURCE_FILE dmd, changelog/throw_expression.dd) +$(P +Prior to this release, `throw` was considered as a statement and hence was not +allowed to appear inside of other expressions. This was cumbersome e.g. when +wanting to throw an expression from a lambda: +) + +--- +SumType!(int, string) result; + +result.match!( + (int num) => writeln("Found ", num), + // (string err) => throw new Exception(err) // expression expected + (string err) { throw new Exception(err); } // ok, introduces an explicit body + +); +--- + +$(P +`throw` is now treated as an expression as specified by DIP 1034 [1], causing +it to become more flexible and easier to use. +) + + +--- +SumType!(int, string) result; + +result.match!( + (int num) => writeln("Found ", num), + (string err) => throw new Exception(err) // works + +); +--- + +$(P +[1] https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1034.md +) +) + +$(LI $(LNAME2 traits_initSymbol,Added __traits(initSymbol) to obtain aggregate initializers) +$(CHANGELOG_SOURCE_FILE dmd, changelog/traits_initSymbol.dd) +$(P +Using `__traits(initSymbol, A)` where `A` is either a `class` or a `struct` +will yield a `const(void)[]` that holds the initial state of an instance +of `A`. The slice either points to the initializer symbol of `A` or `null` +if `A` is zero-initialised - matching the behaviour of `TypeInfo.initializer()`. +) + +$(P +This traits can e.g. be used to initialize `malloc`'ed class instances without +relying on `TypeInfo`: +) + +--- +class C +{ + int i = 4; +} + +void main() +{ + const void[] initSym = __traits(initSymbol, C); + + void* ptr = malloc(initSym.length); + scope (exit) free(ptr); + + ptr[0..initSym.length] = initSym[]; + + C c = cast(C) ptr; + assert(c.i == 4); +} +--- +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 openbsd_ioctls,Add support for OpenBSD ioctls) +$(CHANGELOG_SOURCE_FILE druntime, changelog/openbsd_ioctls.dd) +$(P +Support OpenBSD ioctls as found in OpenBSD's $(LINK2 https://github.com/openbsd/src/blob/master/sys/sys/filio.h, /usr/include/sys/filio.h), $(LINK2 https://github.com/openbsd/src/blob/master/sys/sys/ioccom.h, /usr/include/sys/ioccom.h), $(LINK2 https://github.com/openbsd/src/blob/master/sys/sys/ioctl.h, /usr/include/sys/ioctl.h), and $(LINK2 https://github.com/openbsd/src/blob/master/sys/sys/ttycom.h, /usr/include/sys/ttycom.h). +) +) + +$(LI $(LNAME2 safe_opequals,Add support for `@safe` class `opEquals`) +$(CHANGELOG_SOURCE_FILE druntime, changelog/safe_opequals.dd) +$(P +`object.opEquals` is now `@safe` if the static types being compared provide an `opEquals` method that is also `@safe`. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 checkedint,Move checkedint out of experimental.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/checkedint.dd) +$(P +std.experimental.checkedint is now std.checkedint. The old name +is still available and publicly imports the new one, and is also +deprecated. +) +) + +$(LI $(LNAME2 chunkBy_mostly_safe,`chunkBy` `@safe` with forward ranges and `splitWhen` fully `@safe`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/chunkBy_mostly_safe.dd) +$(P +`std.algorithm.iteration.splitWhen` now infers safety from the underlying range, +as most Phobos ranges do. `std.algorithm.iteration.chunkBy` also does that when +instantiated with a forward range. Inference for `chunkBy` with a non-forward +input range is not yet implemented, though. +) + +------- +@safe void fun() +{ + import std.algorithm; + + // Grouping by particular attribute of each element: + auto data = [ + [1, 1], + [1, 2], + [2, 2], + [2, 3] + ]; + + auto r1 = data.chunkBy!((a,b) => a[0] == b[0]); + assert(r1.equal!equal([ + [[1, 1], [1, 2]], + [[2, 2], [2, 3]] + ])); + + auto r2 = [1, 2, 3, 4, 5, 6, 7, 8, 9].splitWhen!((x, y) => ((x*y) % 3) > 0); + assert(r2.equal!equal([ + [1], + [2, 3, 4], + [5, 6, 7], + [8, 9] + ])); +} +------- +) + +$(LI $(LNAME2 csv_un_equal_separator_count,`std.csv` can now optionally handle csv files with variable number of columns.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/csv_un_equal_separator_count.dd) +$(P +By default `std.csv` will throw if the number of columns on a line +is not equal to the number of columns of the first line. +To allow, or disallow, a variable amount of columns a `bool` can be passed to +all overloads of the `csvReader` function as shown below. +) + +``` +string text = "76,26,22\n1,2\n3,4,5,6"; +auto records = text.csvReader!int(',', '"', true); + +assert(records.equal!equal([ + [76, 26, 22], + [1, 2], + [3, 4, 5, 6] +])); +``` +) + +$(LI $(LNAME2 logger_default_warning,Change default log level for std.experimental.logger to LogLevel.warning) +$(CHANGELOG_SOURCE_FILE phobos, changelog/logger_default_warning.dd) +$(P +`std.experimental.logger.core.sharedLog` now returns by default a +logger with its log level set to LogLevel.warning. +) +) + +$(LI $(LNAME2 support_for_tuples,`std.conv.to` accepts `std.typecons` tuples) +$(CHANGELOG_SOURCE_FILE phobos, changelog/support_for_tuples.dd) +$(P +The previous version of `to` did not support +conversions to `std.typecons` tuples. Starting +with this release, tuples are now supported as +highlighted in the following example: +) + +------- +void main() +{ + import std.conv : to; + import std.typecons : Tuple; + auto data = ["10", "20", "30"]; + auto a3 = data.to!(int[3]); // accepted in previous and current versions + auto t3 = data.to!(Tuple!(int, int, int)); // rejected in past versions, accepted now +} +------- +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 pdb,Windows: Copy PDB files to `targetPath`, alongside executable/DLL) +$(CHANGELOG_SOURCE_FILE dub, changelog/pdb.dd) +$(P +If the default PDB file is generated when linking an executable or DLL +(e.g., no `/PDB:my\path.pdb` lflag), it is now copied to the target +directory too. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 17635): [REG 2.066.0] cannot convert unique immutable$(LPAREN)int$(RPAREN)** to immutable) +$(LI $(BUGZILLA 21367): Nameless union propagates copy constructors and destructors over all members) +$(LI $(BUGZILLA 21538): Overriding with more attributes on delegate parameter is allowed) +$(LI $(BUGZILLA 21674): [REG v2.086] `alias this` triggers wrong deprecation message on function call) +$(LI $(BUGZILLA 21719): [REG 2.072] "auto" methods of classes do not infer attributes correctly.) +$(LI $(BUGZILLA 22130): [REG2.080.1][DIP1000] pure factory functions stopped working) +$(LI $(BUGZILLA 22163): [REG 2.094.0] wrong code with static float array and delegate accessing it) +$(LI $(BUGZILLA 22226): [REG 2.095.1] __ctfe + function call in conditional expression used to initialize struct member in constructor causes ICE) +$(LI $(BUGZILLA 22254): Template instantiated twice results in different immutable qualifier) +$(LI $(BUGZILLA 22512): importC: incomplete array type must have initializer) +$(LI $(BUGZILLA 22659): [REG master] Error: declaration '$(LPAREN)S[2] arr = __error__;$(RPAREN)' is not yet implemented in CTFE) +$(LI $(BUGZILLA 22676): fullyQualifiedName fails to compile with 2.098.1 relese -- there is some issue with call to __traits$(LPAREN)isScalar ..) +$(LI $(BUGZILLA 22705): importC: forward reference to struct typedef gives struct already exists) +$(LI $(BUGZILLA 22714): ICE: Assertion failure in ClassDeclaration::isBaseOf) +$(LI $(BUGZILLA 22730): master: "dmd -i" doesn't include unit tests from imported modules) +$(LI $(BUGZILLA 22738): std.file.tempDir adds an addition / even when it already has one) +$(LI $(BUGZILLA 22761): [REG 2.099] importC: Error: redeclaration with different type) +$(LI $(BUGZILLA 22780): [REG 2.090] variable reference to scope class must be scope) +$(LI $(BUGZILLA 22804): [REG 2.099] compiling multiple files without linking produces broken object files) +$(LI $(BUGZILLA 22816): [REG 2.099] Parser reads files with other extensions) +$(LI $(BUGZILLA 22817): [REG 2.099] Missing file gives misleading error message) +$(LI $(BUGZILLA 22826): [REG 2.098] #line accepts importC linemarker flags) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 2): Hook up new dmd command line arguments) +$(LI $(BUGZILLA 3): Finish or remove MatchExp::toElem) +$(LI $(BUGZILLA 3818): Generic error message for wrong foreach) +$(LI $(BUGZILLA 8346): Literals 00 - 07 results in odd errors when used with UFCS) +$(LI $(BUGZILLA 10584): Unhelpful error default constructing nested class) +$(LI $(BUGZILLA 15711): Incorrect type inferring of [char]/string when passed via recursive template, extracting it from a structure field) +$(LI $(BUGZILLA 15804): missing UDAs on nested struct template) +$(LI $(BUGZILLA 17870): Can't alias a mix of parent and child class members) +$(LI $(BUGZILLA 17977): [DIP1000] destructor allows escaping reference to a temporary struct instance) +$(LI $(BUGZILLA 18960): Function parameter requires name with default value) +$(LI $(BUGZILLA 19320): -cov and -O yield variable used before set) +$(LI $(BUGZILLA 19482): attributes incorrectly applied to static foreach local variables) +$(LI $(BUGZILLA 19873): function should be by default @system even with -preview=dip1000) +$(LI $(BUGZILLA 20023): Separate compilation breaks dip1000 / dip1008 @safety) +$(LI $(BUGZILLA 20691): Converting scope static array to scope dynamic array should be error) +$(LI $(BUGZILLA 20777): User defined type as enum base type fails to compile.) +$(LI $(BUGZILLA 20904): dip1000 implicit conversion delegates error) +$(LI $(BUGZILLA 21431): Incorrect maximum and actual number of cases in a switch case range is reported) +$(LI $(BUGZILLA 21844): makedeps option adds spurious/incorrect dependency) +$(LI $(BUGZILLA 21969): importC: Error: bit fields are not supported) +$(LI $(BUGZILLA 22124): Corrupted closure when compiling with -preview=dip1000) +$(LI $(BUGZILLA 22127): compiler assertion failure parser on UDA and function literal) +$(LI $(BUGZILLA 22137): -preview=dip1000 enables visibility checks for tupleof) +$(LI $(BUGZILLA 22139): Compiler special cases object.dup when compiling with -preview=dip1000) +$(LI $(BUGZILLA 22233): importC: $(LPAREN)identifier$(RPAREN)$(LPAREN)$(RPAREN) incorrectly parsed as a cast-expression) +$(LI $(BUGZILLA 22236): sizeof an empty C struct should be 0, not 1) +$(LI $(BUGZILLA 22245): importC: Error: found `.` when expecting `$(RPAREN)`) +$(LI $(BUGZILLA 22267): ImportC: typedef-ed variable initialization with RHS in parenthesis doesn't parse) +$(LI $(BUGZILLA 22277): removing strongly pure function calls is an incorrect optimization) +$(LI $(BUGZILLA 22283): -preview=in -inline leads to strange error inside object.d) +$(LI $(BUGZILLA 22285): markdown tables are not parsed correctly) +$(LI $(BUGZILLA 22287): ambiguous virtual function for extern$(LPAREN)C++$(RPAREN) under Windows) +$(LI $(BUGZILLA 22298): [DIP1000] Nested function's scope parameters can be assigned to variables in enclosing function) +$(LI $(BUGZILLA 22305): ImportC: #pragma STDC FENV_ACCESS is not supported) +$(LI $(BUGZILLA 22311): dmd slice length is wrong on DWARF) +$(LI $(BUGZILLA 22323): Link error for virtual destructor of C++ class in DLL) +$(LI $(BUGZILLA 22339): importC: error message with character literal reports as integer instead of character literal.) +$(LI $(BUGZILLA 22342): importC: Error: function 'func$(LPAREN)$(RPAREN)' is not callable using argument types '$(LPAREN)int$(RPAREN)') +$(LI $(BUGZILLA 22344): ImportC: overloading of functions is not allowed) +$(LI $(BUGZILLA 22356): Can't mixin the return type of a function) +$(LI $(BUGZILLA 22361): Failed import gives misleading error message) +$(LI $(BUGZILLA 22365): Compiler crash: tcs.body_ null in StatementSemanticVisitor.visit$(LPAREN)TryCatchStatement$(RPAREN) in semantic3 pass $(LPAREN)dmd/statementsem.d:3956$(RPAREN)) +$(LI $(BUGZILLA 22366): [dip1000] scope variable can be assigned to associative array) +$(LI $(BUGZILLA 22372): Loop index incorrectly optimised out for -release -O) +$(LI $(BUGZILLA 22387): Noreturn init loses type qualifiers) +$(LI $(BUGZILLA 22401): importC: Error: cannot implicitly convert expression of type 'const$(LPAREN)int[1]$(RPAREN)' to 'const$(LPAREN)int*$(RPAREN)') +$(LI $(BUGZILLA 22415): importC: Deprecation: switch case fallthrough - use 'goto case;' if intended) +$(LI $(BUGZILLA 22421): static foreach introduces semantic difference between indexing and iteration variable) +$(LI $(BUGZILLA 22467): DWARF: wchar_t reports wrong DECL attributes) +$(LI $(BUGZILLA 22510): Structs with copy constructor can not be heap allocated with default constructor) +$(LI $(BUGZILLA 22515): Aggregate definition with qualifiers has inconsistencies between structs and classes) +$(LI $(BUGZILLA 22517): [REG 2.093][ICE] Bus error at dmd/lexer.d:398) +$(LI $(BUGZILLA 22527): Casting out-of-range floating point value to signed integer overflows) +$(LI $(BUGZILLA 22533): OpenBSD: Use correct size_t compat for 32-bit) +$(LI $(BUGZILLA 22535): ImportC: gcc/clang math intrinsics are rejected.) +$(LI $(BUGZILLA 22553): ImportC: undefined identifier `__uint128_t`) +$(LI $(BUGZILLA 22566): Error: unknown architecture feature `4+avx` for `-target`) +$(LI $(BUGZILLA 22573): DMD compiler errors on Illumos/Solaris) +$(LI $(BUGZILLA 22590): importC: static functions have no debug information generated for them) +$(LI $(BUGZILLA 22598): importC: Add support for __extension__ keyword) +$(LI $(BUGZILLA 22607): ImportC misses some float values ending with f) +$(LI $(BUGZILLA 22619): Missing inout substitution for __copytmp temporaries caused by copy ctors) +$(LI $(BUGZILLA 22623): ImportC: typedef'd struct definition tag not put in symbol table) +$(LI $(BUGZILLA 22624): ImportC: struct members in static initializer misaligned following bit field) +$(LI $(BUGZILLA 22625): ImportC: original name of typedefed struct not visible in D when compiling separately) +$(LI $(BUGZILLA 22632): Crash happens when CTFE compares an associative array to null using ==) +$(LI $(BUGZILLA 22634): assert for too many symbols should be error) +$(LI $(BUGZILLA 22655): Disassembler assertion on rdtsc) +$(LI $(BUGZILLA 22656): SSE2 instructions have inconsistent layouts in the disassembler output) +$(LI $(BUGZILLA 22665): ImportC: qualified enum values should be of enum type on the D side, not int) +$(LI $(BUGZILLA 22666): ImportC: Error: attributes should be specified before the function definition) +$(LI $(BUGZILLA 22668): Deprecation when a deprecated method overrides another deprecated method) +$(LI $(BUGZILLA 22685): Template function instantiated with lambda and overload is nested incorrectly) +$(LI $(BUGZILLA 22686): ICE: dmd segfaults on invalid member reference in static function) +$(LI $(BUGZILLA 22698): ImportC: nested struct tag stored in wrong scope) +$(LI $(BUGZILLA 22699): importC: assignment cannot be used as a condition) +$(LI $(BUGZILLA 22703): importC: C++11 unscoped enums with underlying type rejects some C types.) +$(LI $(BUGZILLA 22708): switch statement with an undefined symbol results in many errors) +$(LI $(BUGZILLA 22709): [dip1000] slice of static array can be escaped in @safe using ref arguments) +$(LI $(BUGZILLA 22710): CTFE on bitfields does not account for field width) +$(LI $(BUGZILLA 22713): ImportC: op= not correctly implemented for bit fields) +$(LI $(BUGZILLA 22717): object.TypeInfo_Struct.equals swaps lhs and rhs parameters) +$(LI $(BUGZILLA 22725): ImportC: segfault when compiling with -H) +$(LI $(BUGZILLA 22726): ImportC: typedefs of tagged enums fail to compile) +$(LI $(BUGZILLA 22727): ImportC: support for __stdcall and __fastcall is necessary for 32-bit Windows builds) +$(LI $(BUGZILLA 22734): importC: typedef anonymous enum members not available when used from D) +$(LI $(BUGZILLA 22749): importC: C11 does not allow taking the address of a bit-field) +$(LI $(BUGZILLA 22756): ImportC: no __builtin_offsetof) +$(LI $(BUGZILLA 22757): importC: typedef causes forward reference error) +$(LI $(BUGZILLA 22758): ImportC: parenthesized expression confused with cast-expression) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 5096): More readable unpaired brace error) +$(LI $(BUGZILLA 7925): extern$(LPAREN)C++$(RPAREN) delegates?) +$(LI $(BUGZILLA 11008): Allow -main switch even if user-defined main function exists) +$(LI $(BUGZILLA 20340): [betterC] -main inserts D main function even with betterC) +$(LI $(BUGZILLA 20616): Error: undefined identifier __dollar) +$(LI $(BUGZILLA 21160): DWARF: DW_AT_main_subprogram should be emitted for _Dmain) +$(LI $(BUGZILLA 22113): Allow `noreturn` as a type for main function) +$(LI $(BUGZILLA 22198): Compile time bounds checking for static arrays) +$(LI $(BUGZILLA 22278): [Conditional Compilation] there should be in and out flags) +$(LI $(BUGZILLA 22291): __traits$(LPAREN)arguments$(RPAREN) to return a tuple of the function arguments) +$(LI $(BUGZILLA 22353): Header generation is producing trailing whitespace on attribute declarations) +$(LI $(BUGZILLA 22354): Header generation is producing trailing whitespace on enum declarations) +$(LI $(BUGZILLA 22355): LLD fallback for mscoff is broken in the presence of some old VS versions) +$(LI $(BUGZILLA 22377): Show location for Windows extern$(LPAREN)C++$(RPAREN) mangling ICE) +$(LI $(BUGZILLA 22379): OpenBSD: link -lexecinfo to get backtrace symbols) +$(LI $(BUGZILLA 22419): Allow return type inference for main) +$(LI $(BUGZILLA 22423): DWARF DW_TAG_subprogram should generate DW_AT_decl_column) +$(LI $(BUGZILLA 22426): DWARF DW_AT_noreturn should be present when function is noreturn) +$(LI $(BUGZILLA 22459): DWARF: delegate type names should be distinguishable) +$(LI $(BUGZILLA 22468): DWARF: dchar type is missing encoding) +$(LI $(BUGZILLA 22469): DWARF: some debug info types are named wrongly) +$(LI $(BUGZILLA 22471): DWARF: generated main is not marked as DW_AT_artificial) +$(LI $(BUGZILLA 22494): Search paths for dmd.conf missing from dmd man page) +$(LI $(BUGZILLA 22508): DWARF: associative arrays should report qualified name instead of _AArray__) +$(LI $(BUGZILLA 22519): [dip1000] cannot take address of `ref return`) +$(LI $(BUGZILLA 22541): DIP1000: Resolve ambiguity of ref-return-scope parameters) +$(LI $(BUGZILLA 22631): ImportC: support C++11 unscoped enums with underlying type) +$(LI $(BUGZILLA 22672): Allow casting a ValueSeq to a compatible TypeTuple) +$(LI $(BUGZILLA 22733): hdrgen generates inconsistent order of STC attributes for ~this$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 22746): Functions that throws marked as nothrow produces bad error) +$(LI $(BUGZILLA 22753): Deprecation message for import module shouldn't produce hifen when no message) +$(LI $(BUGZILLA 22754): Header generator shouldn't generate trailing whitespace on visibility declaration) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 17037): std.concurrency has random segfaults) +$(LI $(BUGZILLA 19544): Can't call inputRangeObject on ranges not supported by moveFront) +$(LI $(BUGZILLA 20554): std.algorithm.searching.all 's static assert produces a garbled error message) +$(LI $(BUGZILLA 21022): std.range.only does not work with const) +$(LI $(BUGZILLA 21457): std.functional.partial ignores function overloads) +$(LI $(BUGZILLA 22105): std.container.array.Array.length setter creates values of init-less types) +$(LI $(BUGZILLA 22185): std.array.array$(LPAREN)$(RPAREN) doesn't handle throwing element copying) +$(LI $(BUGZILLA 22249): std.experimental.checkedint: Warn.onLowerBound does not compile) +$(LI $(BUGZILLA 22255): JSONValue.opBinaryRight!"in" is const) +$(LI $(BUGZILLA 22297): Behavior of minElement and maxElement with empty range is undocumented) +$(LI $(BUGZILLA 22301): Only use 'from' if a packet was actually received) +$(LI $(BUGZILLA 22325): ReplaceType fails on templated type instantiated with void-returning function) +$(LI $(BUGZILLA 22359): joiner over an empty forward range object liable to segfault) +$(LI $(BUGZILLA 22364): Unreachable warning for collectException[Msg] with noreturn value) +$(LI $(BUGZILLA 22368): has[Unshared]Aliasing fails to instantiate for noreturn) +$(LI $(BUGZILLA 22369): Unreachable statements in std.concurrency with noreturn values / callbacks) +$(LI $(BUGZILLA 22383): Array of bottom types not recognized as a range) +$(LI $(BUGZILLA 22384): castSwitch confused by noreturn handlers) +$(LI $(BUGZILLA 22386): Unreachable warning for assertThrown with noreturn value) +$(LI $(BUGZILLA 22394): std.getopt cannot handle "-") +$(LI $(BUGZILLA 22408): Multiple issues in AllImplicitConversionTargets) +$(LI $(BUGZILLA 22414): clamp$(LPAREN)a, b, c$(RPAREN) should always return typeof$(LPAREN)a$(RPAREN)) +$(LI $(BUGZILLA 22561): only$(LPAREN)$(RPAREN).joiner fails with immutable element type) +$(LI $(BUGZILLA 22572): Cannot define SumType over immutable struct with Nullable) +$(LI $(BUGZILLA 22608): RandomAccessInfinite is not a valid random-access range) +$(LI $(BUGZILLA 22647): [std.variant.Variant] Cannot compare types compliant with null comparison with 'null') +$(LI $(BUGZILLA 22648): [std.variant.Variant] Incorrectly written unittests) +$(LI $(BUGZILLA 22673): .array of a range with length preallocates without checking if the length was lying or not.) +$(LI $(BUGZILLA 22683): core.math.rndtonl can't be linked) +$(LI $(BUGZILLA 22695): std.traits.isBuiltinType is false for typeof$(LPAREN)null$(RPAREN)) +$(LI $(BUGZILLA 22704): Linker error when running the public unittests) +$(LI $(BUGZILLA 22838): std.bitmanip.BitArray.count$(LPAREN)$(RPAREN) reads beyond data when data size is integer size_t multiple) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 13551): std.conv.to for std.typecons tuples too) +$(LI $(BUGZILLA 17488): Platform-inconsistent behavior from getTempDir$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 18051): missing enum support in formattedRead/unformatValue) +$(LI $(BUGZILLA 21507): SysTime.toISOExtString is unusable for logging or consistent filename creation) +$(LI $(BUGZILLA 22117): Can't store scope pointer in a SumType) +$(LI $(BUGZILLA 22340): totalCPUs may not return accurate number of CPUs) +$(LI $(BUGZILLA 22370): std.concurrency.spawn* should accept noreturn callables) +$(LI $(BUGZILLA 22511): Nullable is not copyable when templated type has elaborate copy ctor) +$(LI $(BUGZILLA 22532): std.experimental.logger Change default log level to LogLevel.warning, or LogLevel.off) +$(LI $(BUGZILLA 22701): std.typecons.apply needlessly checks if the predicate is callable) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 22136): [REG 2.097.1] hashOf failed to compile because of different inheritance order) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 22328): Specific D types are used instead of Windows type aliases) +$(LI $(BUGZILLA 22336): core.lifetime.move doesn't work with betterC on elaborate non zero structs) +$(LI $(BUGZILLA 22523): DRuntime options passed after -- affect current process) +$(LI $(BUGZILLA 22552): moveEmplace wipes context pointer of nested struct contained in non-nested struct) +$(LI $(BUGZILLA 22630): It is possible for VS to be installed and providing VC directory without VC libraries being installed) +$(LI $(BUGZILLA 22702): druntime not compliant with D spec re getLinkage) +$(LI $(BUGZILLA 22721): importC: some gnu builtins are rejected) +$(LI $(BUGZILLA 22735): __builtins.di does not implement __builtin_bswap64 correctly) +$(LI $(BUGZILLA 22741): importC: Error: bswap isn’t a template) +$(LI $(BUGZILLA 22744): ImportC: builtins defined in __builtins.di cause undefined symbol linker errors.) +$(LI $(BUGZILLA 22777): stat struct in core.sys.windows.stat assumes CRuntime_DigitalMars) +$(LI $(BUGZILLA 22779): druntime: Calling __delete with null pointer-to-struct segfaults) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 14892): -profile=gc doesn't account for GC API allocations) +$(LI $(BUGZILLA 20936): core.sync.rwmutex should have shared overloads $(LPAREN)and make it usable in @safe code$(RPAREN)) +$(LI $(BUGZILLA 21005): Speed up hashOf for associative arrays) +$(LI $(BUGZILLA 21014): aa.byKeyValue, byKey, byValue very under-documented) +$(LI $(BUGZILLA 22378): OpenBSD: execinfo.d and unistd.d aren't being installed) +$(LI $(BUGZILLA 22669): OpenBSD: Sync socket.d) +$(LI $(BUGZILLA 22670): Support *BSD kqueue-backed API-compatible inotify shim library) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 19136): is expressions don't work as documented) +$(LI $(BUGZILLA 21717): [Oh No! Page Not Found]) +$(LI $(BUGZILLA 22064): Missing documentation page for phobos core.builtins) +$(LI $(BUGZILLA 22281): unreadable quotes in the upcoming 2.099 changelog) +$(LI $(BUGZILLA 22363): Wrong link in https://dlang.org/spec/abi.html for "Garbage Collection") +$(LI $(BUGZILLA 22417): Slice assignment operator overloading example is incorrect) +$(LI $(BUGZILLA 22504): spec/type.html: 6.1 Basic Data Types: Backslash missing in default value for {,d,w}char) +$(LI $(BUGZILLA 22518): [dip1000] return without scope/ref not specified) +$(LI $(BUGZILLA 22544): [spec] C++ and Objective-C are not single tokens) +$(LI $(BUGZILLA 22692): Underground Rekordz link is dead) +$(LI $(BUGZILLA 22711): Effect of template UDAs on instance members is undocumented) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 22425): Documentation on implicit conversion of arrays is incomplete) +$(LI $(BUGZILLA 22431): Add OpenBSD to Third-party downloads list) +) +$(BUGSTITLE_BUGZILLA Installer enhancements, + +$(LI $(BUGZILLA 18362): Build dmd with LTO and PGO) +$(LI $(BUGZILLA 22078): install.sh: Recognize ARM64 as architecture) +) +) +$(D_CONTRIBUTORS_HEADER 100) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR 12345swordy) + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Andrej Petrović) + $(D_CONTRIBUTOR Anton Curmanschii) + $(D_CONTRIBUTOR Antonio Cabrera) + $(D_CONTRIBUTOR Arun Chandrasekaran) + $(D_CONTRIBUTOR Ate Eskola) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR BarrOff) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR Bianca Fodor) + $(D_CONTRIBUTOR bistcuite) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Brian Callahan) + $(D_CONTRIBUTOR David Gileadi) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR DoctorNoobingstoneIPresume) + $(D_CONTRIBUTOR Domenico Teodonio) + $(D_CONTRIBUTOR Dorian Verna) + $(D_CONTRIBUTOR dorianverna17) + $(D_CONTRIBUTOR dteod) + $(D_CONTRIBUTOR Eddy Schauman-Haigh) + $(D_CONTRIBUTOR Eduard Staniloiu) + $(D_CONTRIBUTOR etienne02) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR fourst4r) + $(D_CONTRIBUTOR Gabriel) + $(D_CONTRIBUTOR Gabriel Dolberg) + $(D_CONTRIBUTOR giacomo.ratto00) + $(D_CONTRIBUTOR H. S. Teoh) + $(D_CONTRIBUTOR Harrison) + $(D_CONTRIBUTOR Harry T. Vennik) + $(D_CONTRIBUTOR Hasan Kashi) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR human) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Ilya Yaroshenko) + $(D_CONTRIBUTOR Imperatorn) + $(D_CONTRIBUTOR James S Blachly, MD) + $(D_CONTRIBUTOR Jan Jurzitza) + $(D_CONTRIBUTOR Jeremy DeHaan) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR John Kilpatrick) + $(D_CONTRIBUTOR João Lourenço) + $(D_CONTRIBUTOR jpiles) + $(D_CONTRIBUTOR jrfondren) + $(D_CONTRIBUTOR Julian Fondren) + $(D_CONTRIBUTOR Laeeth Isharc) + $(D_CONTRIBUTOR Lionello Lunesu) + $(D_CONTRIBUTOR Lio李歐) + $(D_CONTRIBUTOR lucica28) + $(D_CONTRIBUTOR Lucien Perregaux) + $(D_CONTRIBUTOR Luís Ferreira) + $(D_CONTRIBUTOR Manu Evans) + $(D_CONTRIBUTOR Marcelo Silva Nascimento Mancini) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Max H Haughton) + $(D_CONTRIBUTOR Max Haughton) + $(D_CONTRIBUTOR Max Samukha) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR quassy) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Richard Andrew Cattermole) + $(D_CONTRIBUTOR rikki cattermole) + $(D_CONTRIBUTOR Robert burner Schadek) + $(D_CONTRIBUTOR Ryan Frame) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Sebastien Alaiwan) + $(D_CONTRIBUTOR sorin-gabriel) + $(D_CONTRIBUTOR Stanislav Blinov) + $(D_CONTRIBUTOR Stefan Koch) + $(D_CONTRIBUTOR Sönke Ludwig) + $(D_CONTRIBUTOR teo) + $(D_CONTRIBUTOR Teodor Dutu) + $(D_CONTRIBUTOR thaven) + $(D_CONTRIBUTOR Tim Schendekehl) + $(D_CONTRIBUTOR tim-dlang) + $(D_CONTRIBUTOR Tobias Pankrath) + $(D_CONTRIBUTOR Tomáš Chaloupka) + $(D_CONTRIBUTOR Victarus) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR Walter Waldron) + $(D_CONTRIBUTOR wolframw) + $(D_CONTRIBUTOR Ömer Faruk IRMAK) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.099.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.099.1.dd b/changelog/2.099.1.dd new file mode 100644 index 0000000000..e9344a9ac7 --- /dev/null +++ b/changelog/2.099.1.dd @@ -0,0 +1,148 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 07, 2022, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 2 major changes and 21 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 12 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 TraitsParametersRevised,Special case for `__traits(parameters)` in foreach loops was removed)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 log_default_info,std.experimental.logger default level changed to `info` instead of `warning`)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 TraitsParametersRevised,Special case for `__traits(parameters)` in foreach loops was removed) +$(CHANGELOG_SOURCE_FILE dmd, changelog/TraitsParametersRevised.dd) +$(P +Previously, when used inside a `foreach` using an overloaded `opApply`, the trait +would yield the parameters to the delegate and not the function the foreach appears within. +) + +$(P +This behaviour is unintuitive, especially when the type of the `foreach` aggregate +depends on a template parameter. Hence `__traits(parameters)` was changed to consistently +return the parameters of the lexically enclosing function. +) + +--- +class Tree { + int opApply(int delegate(size_t, Tree) dg) { + if (dg(0, this)) return 1; + return 0; + } +} +void useOpApply(Tree top, int x) +{ + foreach(idx; 0..5) + { + static assert(is(typeof(__traits(parameters)) == AliasSeq!(Tree, int))); + } + + foreach(idx, elem; top) + { + // Previously: + // static assert(is(typeof(__traits(parameters)) == AliasSeq!(size_t, Tree))); + + // Now: + static assert(is(typeof(__traits(parameters)) == AliasSeq!(Tree, int))); + } +} +--- +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 log_default_info,std.experimental.logger default level changed to `info` instead of `warning`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/log_default_info.dd) +$(P +In the 2.099.0 release, the default log level $(LINK2 https://dlang.org/changelog/2.099.0.html#logger_default_warning, was changed to warning). +) + +$(P +However, this was erroneously assumed to include `info` (informational) logs as well. Now it does include `info` log messages. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 17434): [REG: 2.073] import lookup ignores public import.) +$(LI $(BUGZILLA 20015): [REG 2.086] Deprecated -preview, -revert, and -transition options not documented) +$(LI $(BUGZILLA 20717): Unsilenced bogus "undefined identifier" error from speculative collision) +$(LI $(BUGZILLA 21285): Delegate covariance broken between 2.092 and 2.094 $(LPAREN)git master$(RPAREN).) +$(LI $(BUGZILLA 22175): assert fail when struct assignment value is desired and struct size is odd) +$(LI $(BUGZILLA 22639): Copy constructors with default arguments not getting called) +$(LI $(BUGZILLA 22858): [REG2.099] Incorrect alignment of void*[0]) +$(LI $(BUGZILLA 22859): Error: forward reference of variable `isAssignable` for mutually recursed `allSatisfy`) +$(LI $(BUGZILLA 22860): `Error: unknown` with mutually recursive and nested SumType) +$(LI $(BUGZILLA 22863): [REG2.099] -main doesn't work anymore when used for linking only $(LPAREN)without source modules$(RPAREN)) +$(LI $(BUGZILLA 22969): Can't mixin name of manifest constant on right-hand side of alias declaration) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 22852): importC: Lexer allows invalid wysiwyg and hex strings) +$(LI $(BUGZILLA 22853): importC: Lexer allows nesting block comments) +$(LI $(BUGZILLA 22868): __traits$(LPAREN)parameters$(RPAREN) returns parameters of delegate instead of function) +$(LI $(BUGZILLA 22871): Using an alias to `__traits$(LPAREN)parameters$(RPAREN)` causes unknown error) +$(LI $(BUGZILLA 22939): bad error message: Error: no property `msg` for type `string`) +$(LI $(BUGZILLA 22942): Invalid section type / offset for newer XCode versions) +$(LI $(BUGZILLA 22993): Missing quotes in octal literal hint) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 20778): exception messages with nulls within are treated inconsistently) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 22908): OpenBSD: Add getpwnam_shadow and getpwuid_shadow function prototypes) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 21086): Wrong source link for core.thread.context) +) +) +$(D_CONTRIBUTORS_HEADER 12) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Brian Callahan) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.099.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.100.0.dd b/changelog/2.100.0.dd new file mode 100644 index 0000000000..c2d8f942bf --- /dev/null +++ b/changelog/2.100.0.dd @@ -0,0 +1,869 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION May 10, 2022, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 22 major changes and 179 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 41 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 alias_this_assignment,End deprecation period for using `alias this` for partial assignment.)) +$(LI $(RELATIVE_LINK2 d1_style_operators,The deprecation period for D1-style operators has ended.)) +$(LI $(RELATIVE_LINK2 dep_scope_type,`scope` as a type constraint on class, struct, and enum declarations is deprecated.)) +$(LI $(RELATIVE_LINK2 deprecation_asm_stc,The deprecation period of unannotated `asm` blocks has been ended.)) +$(LI $(RELATIVE_LINK2 deprecation_delete,The deprecation period of the `delete` keyword has been ended.)) +$(LI $(RELATIVE_LINK2 dtoh-improvements,Improvements for the C++ header generation)) +$(LI $(RELATIVE_LINK2 error_scope_interface,The deprecation period for `scope` as a type constraint on interface declarations has ended.)) +$(LI $(RELATIVE_LINK2 inout-return,The `inout` attribute no longer implies the `return` attribute)) +$(LI $(RELATIVE_LINK2 invariant_contract_version_identifier,Support contract invariant version identifier.)) +$(LI $(RELATIVE_LINK2 mustUse,Implement DIP 1038: @mustuse)) +$(LI $(RELATIVE_LINK2 static_array_tupleof,Added `.tupleof` property for static arrays)) +$(LI $(RELATIVE_LINK2 super_type_gone,Usage of `this` and `super` as types has been removed)) +$(LI $(RELATIVE_LINK2 switch-fallthrough,A missed case of switch case fallthrough has been deprecated)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 std_functional_bind,New function `bind` in `std.functional`)) +$(LI $(RELATIVE_LINK2 std_typecons_nullable_range,`Nullable` in `std.typecons` can now act as a range)) +$(LI $(RELATIVE_LINK2 zlib,Zlib updated to 1.2.12)) + +) + +$(BUGSTITLE_TEXT_HEADER Tools changes, + +$(LI $(RELATIVE_LINK2 rdmd-environment-args,rdmd now supports specifying the D compiler using the `RDMD_DMD` environment variable)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 actual-dynamiclibrary,Builds dynamicLibrary targets as dynamic libraries instead of static libraries.)) +$(LI $(RELATIVE_LINK2 build-path-variable,The `$DUB_BUILD_PATH` variable was added)) +$(LI $(RELATIVE_LINK2 command-variables,Command environment variable substitution changed)) +$(LI $(RELATIVE_LINK2 etc-dub-settings-json,Posix: use /etc/dub/settings.json if DUB is installed in /usr)) +$(LI $(RELATIVE_LINK2 injectsourcefile,Adds injection of source files from dependencies via injectSourceFiles command)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 alias_this_assignment,End deprecation period for using `alias this` for partial assignment.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/alias_this_assignment.dd) +$(P +Starting with this release, `alias this` may not be used for the partial +assignment of a left-hand side operand. Any such assignment will result in a +compiler error. +) + +$(P +If a struct has a single member which is aliased this directly or aliased to a +ref getter function that returns the mentioned member, then alias this may be +used since the object will be fully initialised. +) + +--- +struct Allowed +{ + int onemember; + alias onemember this; +} + +struct Rejected +{ + int aliased; + long other; + alias aliased this; +} + +void fun(Allowed a, Rejected r) +{ + a = 0; // OK, struct has only one member. + r = 0; // Error, cannot use `alias this` to partially initialize variable `r` of type `Rejected`. Use `r.aliased` +} +--- +) + +$(LI $(LNAME2 d1_style_operators,The deprecation period for D1-style operators has ended.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/d1_style_operators.dd) +$(P +Starting with this release, any use of the deprecated D1 overload operators +will result in a compiler error. +) + +$(P +The corrective action is to replace all operators with their D2 equivalent. +) + +$(P +The following D1 operator overloads have been removed in favor of `opUnary`: + * `opNeg` must be replaced with `opUnary(string op)() if (op == "-")` + * `opCom` must be replaced with `opUnary(string op)() if (op == "~")` + * `opPostInc`must be replaced with `opUnary(string op)() if (op == "++")` + * `opPostDec`must be replaced with `opUnary(string op)() if (op == "--")` + * `opStar`must be replaced with `opUnary(string op)() if (op == "*")` +) + +$(P +The following D1 operator overloads have been removed in favor of `opBinary`: + * `opAdd` must be replaced with `opBinary(string op)(...) if (op == "+")` + * `opSub` must be replaced with `opBinary(string op)(...) if (op == "-")` + * `opMul` must be replaced with `opBinary(string op)(...) if (op == "*")` + * `opDiv` must be replaced with `opBinary(string op)(...) if (op == "/")` + * `opMod` must be replaced with `opBinary(string op)(...) if (op == "%")` + * `opAnd` must be replaced with `opBinary(string op)(...) if (op == "&")` + * `opXor` must be replaced with `opBinary(string op)(...) if (op == "^")` + * `opOr` must be replaced with `opBinary(string op)(...) if (op == "|")` + * `opShl` must be replaced with `opBinary(string op)(...) if (op == "<<")` + * `opShr` must be replaced with `opBinary(string op)(...) if (op == ">>")` + * `opUShr` must be replaced with `opBinary(string op)(...) if (op == ">>>")` + * `opCat` must be replaced with `opBinary(string op)(...) if (op == "~")` + * `opIn` must be replaced with `opBinary(string op)(...) if (op == "in")` +) + +$(P +The following D1 operator overloads have been removed in favor of `opBinaryRight`: + * `opAdd_r` must be replaced with `opBinaryRight(string op)(...) if (op == "+")` + * `opSub_r` must be replaced with `opBinaryRight(string op)(...) if (op == "-")` + * `opMul_r` must be replaced with `opBinaryRight(string op)(...) if (op == "*")` + * `opDiv_r` must be replaced with `opBinaryRight(string op)(...) if (op == "/")` + * `opMod_r` must be replaced with `opBinaryRight(string op)(...) if (op == "%")` + * `opAnd_r` must be replaced with `opBinaryRight(string op)(...) if (op == "&")` + * `opXor_r` must be replaced with `opBinaryRight(string op)(...) if (op == "^")` + * `opOr_r` must be replaced with `opBinaryRight(string op)(...) if (op == "|")` + * `opShl_r` must be replaced with `opBinaryRight(string op)(...) if (op == "<<")` + * `opShr_r` must be replaced with `opBinaryRight(string op)(...) if (op == ">>")` + * `opUShr_r` must be replaced with `opBinaryRight(string op)(...) if (op == ">>>")` + * `opCat_r` must be replaced with `opBinaryRight(string op)(...) if (op == "~")` + * `opIn_r` must be replaced with `opBinaryRight(string op)(...) if (op == "in")` +) + +$(P +Note: The `opBinaryRight` overload operator takes precedence over any `opBinary` operators. +) + +$(P +The following D1 operator overloads have been removed in favor of `opOpAssign`: + * `opAddAssign` must be replaced with `opOpAssign(string op)(...) if (op == "+")` + * `opSubAssign` must be replaced with `opOpAssign(string op)(...) if (op == "-")` + * `opMulAssign` must be replaced with `opOpAssign(string op)(...) if (op == "*")` + * `opDivAssign` must be replaced with `opOpAssign(string op)(...) if (op == "/")` + * `opModAssign` must be replaced with `opOpAssign(string op)(...) if (op == "%")` + * `opAndAssign` must be replaced with `opOpAssign(string op)(...) if (op == "&")` + * `opOrAssign` must be replaced with `opOpAssign(string op)(...) if (op == "|")` + * `opXorAssign` must be replaced with `opOpAssign(string op)(...) if (op == "^")` + * `opShlAssign` must be replaced with `opOpAssign(string op)(...) if (op == "<<")` + * `opShrAssign` must be replaced with `opOpAssign(string op)(...) if (op == ">>")` + * `opUShrAssign` must be replaced with `opOpAssign(string op)(...) if (op == ">>>")` + * `opCatAssign` must be replaced with `opOpAssign(string op)(...) if (op == "~")` +) + +$(P +The following D1 operator overloads have been removed in favor of `alias this`: + * `opDot` must be replaced with `alias this` +) +) + +$(LI $(LNAME2 dep_scope_type,`scope` as a type constraint on class, struct, and enum declarations is deprecated.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dep_scope_type.dd) +$(P +`scope` as a type constraint on class declarations was meant to force users +of a class to `scope` allocate it, which resulted in the class being placed +on the stack rather than GC-allocated. While it has been scheduled for +deprecation for quite some time, the compiler will emit a deprecation warning +on usage starting from this release. +) + +$(P +`scope` as a type constraint on struct or enum declarations has never had any +effect, and has been deprecated as well. +) + +--- +scope class C { } // Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site. +scope struct S { } // Ditto +scope enum E { } // Ditto +--- + +$(P +Using `scope` to stack-allocate `class` is still suported, +only the type constraint is deprecated. +) + +--- +class C { } + +void main () @nogc +{ + scope c = new C; +} +--- +) + +$(LI $(LNAME2 deprecation_asm_stc,The deprecation period of unannotated `asm` blocks has been ended.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecation_asm_stc.dd) +$(P +See the $(LINK2 $(ROOT_DIR)deprecate.html#asm, Deprecated Features) for more +information. +) + +$(P +Starting with this release, using `asm` blocks will assume to be `@system`, +`@nogc`, impure and might throw, unless explicitly annotated. +) +) + +$(LI $(LNAME2 deprecation_delete,The deprecation period of the `delete` keyword has been ended.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecation_delete.dd) +$(P +See the $(LINK2 $(ROOT_DIR)deprecate.html#delete, Deprecated Features) for more information. +) + +$(P +Starting with this release, using the `delete` keyword will result in a compiler error. +) + +$(P +As a replacement, users are encouraged to use $(REF1 destroy, object) +if feasible, or $(REF __delete, core,memory) as a last resort. +) +) + +$(LI $(LNAME2 dtoh-improvements,Improvements for the C++ header generation) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dtoh-improvements.dd) +$(P +The following features/bugfixes/improvements were implemented for the +experimental C++ header generator: +) + +$(P +- The implicitly generated context pointer for nested aggregates is now + emitted as `outer` instead of `this` +- Explicit mangling via `pragma(mangle, "...")` is partially supported for + functions / variables. The mangling is used as the identifier of `extern(C)` + declarations because C doesn't mangle declaration names. `extern(C++)` + declarations are ignored because there's no portable alternative for C++. +- Emits destructors not easily accessible from C++ (e.g. `extern(D)`) as private + members, preventing the creation of instances that would not be destroyed + on the C++ side. +- No longer generates `extern(C)` functions in aggregates that are emitted + with D mangling. +) + +$(P +Note: The header generator is still considered experimental, so please submit + any bugs encountered to [the bug tracker](https://issues.dlang.org). +) +) + +$(LI $(LNAME2 error_scope_interface,The deprecation period for `scope` as a type constraint on interface declarations has ended.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/error_scope_interface.dd) +$(P +Starting with this release, using `scope` as a type constraint on `interface` +declarations will result in a compiler error. +) + +--- +scope interface I { } // Error: `scope` as a type constraint is obsolete. Use `scope` at the usage site. +--- +) + +$(LI $(LNAME2 inout-return,The `inout` attribute no longer implies the `return` attribute) +$(CHANGELOG_SOURCE_FILE dmd, changelog/inout-return.dd) +$(P +The compiler would formerly add the `return` attribute to `inout` functions, under the assumption that every `inout` function would return its argument. +However, it could also return a member of the `inout` argument, which would still be `inout` because `const` and `immutable` are transitive, while `return` semantics are not transitive. +) + +--- +@safe: + +struct Node +{ + Node* next; + int x; + + // This escapes a pointer to this struct + // This used to be allowed because of `inout` + @safe inout(int)* getScopePointer() inout + { + return &this.x; + } + + // But what if you do not return a pointer to this struct? + // `inout` applies because it's transitive, but `return ref` does not + // The compiler could needlessly treat the returned pointer as a scope pointer + @safe inout(int)* getNonScopePointer() inout + { + return &this.next.x; + } + + // Corrective action for the first case: + // if you want `inout` + `return ref`, annotate it with both + @safe inout(int)* getScopePointer() inout return + { + return &this.x; + } +} +--- +) + +$(LI $(LNAME2 invariant_contract_version_identifier,Support contract invariant version identifier.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/invariant_contract_version_identifier.dd) +$(P +Sometimes it is useful to compile code only when invariants are enabled. This +feature provides the reserved version identifier D_Invariants which evaluates to +true or false when invariants are compiled in or not respectively. +) + +--- +bool hit; + +class Foo +{ + this() {} + invariant { hit = true; } +} + +void main() +{ + cast(void) new Foo(); + + version(D_Invariants) assert(hit); // runs if invariants are compiled in +} +--- +) + +$(LI $(LNAME2 mustUse,Implement DIP 1038: @mustuse) +$(CHANGELOG_SOURCE_FILE dmd, changelog/mustUse.dd) +$(P +`@mustuse` is a new attribute that can be applied to a `struct` or `union` type +to make ignoring an expression of that type into a compile-time error. It can +be used to implement alternative error-handling mechanisms for code that cannot +use exceptions, including `@nogc` and BetterC code. +) + +$(P +For more information, see +$(LINK2 https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1038.md, DIP 1038). +) +) + +$(LI $(LNAME2 static_array_tupleof,Added `.tupleof` property for static arrays) +$(CHANGELOG_SOURCE_FILE dmd, changelog/static_array_tupleof.dd) +$(P +The `.tupleof` property may now be used with instances of static arrays, yielding an $(DDSUBLINK spec/template, homogeneous_sequences, lvalue sequence) of each element in the array. +) + +$(P +Note that this is only for static array *instances*. It remains an error when used on a type, to avoid breaking older code lacking suitable checks. As a workaround, use `typeof((T[N]).init.tupleof)`. +) + +--- +void foo(int, int, int) { /* ... */ } + +int[3] ia = [1, 2, 3]; +foo(ia.tupleof); // same as `foo(1, 2, 3);` + +float[3] fa; +//fa = ia; // error +fa.tupleof = ia.tupleof; +assert(fa == [1F, 2F, 3F]); +--- +) + +$(LI $(LNAME2 super_type_gone,Usage of `this` and `super` as types has been removed) +$(CHANGELOG_SOURCE_FILE dmd, changelog/super_type_gone.dd) +$(P +Prior to this release, using `this` or `super` as a type resulted in a compiler +error suggesting to use `typeof(this)` or `typeof(super)` instead. This has now +been completely removed from the language, and the parser won't recognize this +wrong code anymore. +) +) + +$(LI $(LNAME2 switch-fallthrough,A missed case of switch case fallthrough has been deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/switch-fallthrough.dd) +$(P +Forgetting a `break;` statement in a switch case has been turned from a deprecation +$(LINK2 $(ROOT_DIR)/changelog/2.099.0.html#switch_fallthrough_error, into an error in DMD 2.099.0). +However, the compiler would not issue an error when using multiple values in a single case statement: +) + +--- +void main() +{ + int i = 0; + switch (10) + { + case 10, 11: + i = 4; + // accidental falltrough allowed + default: + i = 8; + } + assert(i == 4); // fails +} +--- + +$(P +This bug has been fixed, but to avoid breaking code, this specific case now issues a deprecation warning. +Starting from DMD 2.110, it will produce an error just like other cases of switch case fallthrough. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 std_functional_bind,New function `bind` in `std.functional`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std_functional_bind.dd) +$(P +It is used to pass the fields of a struct as arguments to a function. For +example, it can be used in a range pipeline to give names to the elements of a +$(REF Tuple, std, typecons): +) + +--- +import std.stdio; +import std.range; +import std.algorithm; +import std.functional; + +void printWithLineNumbers(File f) +{ + f.byLine + .enumerate + .each!(bind!((num, line) { + writefln("%8d %s", num, line); + })); +} +--- + +$(P +See $(REF_ALTTEXT the standard library documentation, bind, std, functional) +for more information. +) +) + +$(LI $(LNAME2 std_typecons_nullable_range,`Nullable` in `std.typecons` can now act as a range) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std_typecons_nullable_range.dd) +$(P +`Nullable` now offers an alternative 0 or 1 element range interface. +) + +--- +import std.stdio; +import std.algorithm; +import std.typecons; + +void printValues(Nullable!int[] values) +{ + values.joiner.each!writeln(); +} +--- +) + +$(LI $(LNAME2 zlib,Zlib updated to 1.2.12) +$(CHANGELOG_SOURCE_FILE phobos, changelog/zlib.dd) +$(P +The bundled zlib has been updated to version 1.2.12. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Tools changes, + +$(LI $(LNAME2 rdmd-environment-args,rdmd now supports specifying the D compiler using the `RDMD_DMD` environment variable) +$(CHANGELOG_SOURCE_FILE tools, ../tools/changelog/rdmd-environment-args.dd) +$(P +rdmd now uses the `RDMD_DMD` environment variable, if it is present in the environment, to choose the D compiler to use. As with the `--compiler` option, the variable's value must specify the name or path of a compiler with a DMD-like command line syntax, such as `gdmd` or `ldmd2`. The variable overrides the default (which is decided at the time `rdmd` was built), but can still be overridden by the `--compiler` option. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 actual-dynamiclibrary,Builds dynamicLibrary targets as dynamic libraries instead of static libraries.) +$(CHANGELOG_SOURCE_FILE dub, changelog/actual-dynamiclibrary.dd) +$(P +Dub will no longer build dynamicLibrary targetType's as staticLibrary. +) + +$(P +Except for x86_omf. This has been disabled due to numerous issues that will lead this to not doing what is expected of it. +) + +$(P +No compiler or linker flags have been added at this time, you will need to specify the relevant flag to get the compiler to link dynamically against Phobos. +) +) + +$(LI $(LNAME2 build-path-variable,The `$DUB_BUILD_PATH` variable was added) +$(CHANGELOG_SOURCE_FILE dub, changelog/build-path-variable.dd) +$(P +The `$DUB_BUILD_PATH` variable is now defined inside the `postBuildCommands` +section. It contains the absolute path in which the package was built, and can +be used to copy by-products of the build process to their intended locations. +) + +$(P +For example, if an executable exports symbols, you will want to make the +resulting import library and symbols export file available somewhere. That can +be done with a `dub.json` section like this: +) +------- + "postBuildCommands-windows": [ + "copy /y $DUB_BUILD_PATH\\$DUB_TARGET_NAME.lib $PACKAGE_DIR\\lib" + "copy /y $DUB_BUILD_PATH\\$DUB_TARGET_NAME.exp $PACKAGE_DIR\\lib" + ], +------- +) + +$(LI $(LNAME2 command-variables,Command environment variable substitution changed) +$(CHANGELOG_SOURCE_FILE dub, changelog/command-variables.dd) +$(P +Now users can use the documented predefined variables inside custom command +directives without the need for a wrapper shell script. +) + +$(P +Before this would have failed: +) +```json +"preBuildCommands": ["$DC -run foo.d"] +``` +$(P +unless DC was defined as environment variable outside DUB. +) + +$(P +It was before possible to run a script that used the $DC environment variable or +on POSIX escape the `$` with `$$DC` to make the shell substitute the variable. +These workarounds are no longer needed now. +) + +$(P +API change: none of the different command directives are no longer substituted +with the process environment variables. You now access the raw commands as +provided by the user in the recipe. `dub describe` has been adjusted and now +also processes the predefined environment variables as well as the process +environment variables. +) +) + +$(LI $(LNAME2 etc-dub-settings-json,Posix: use /etc/dub/settings.json if DUB is installed in /usr) +$(CHANGELOG_SOURCE_FILE dub, changelog/etc-dub-settings-json.dd) +$(P +For Linux distributions that put the dub installation in /usr, there is now a +special case that DUB will load from /etc/dub/settings.json (absolute path) if +the installation is inside /usr. +) + +$(P +Previously settings would have attempted to be loaded from +`/usr/etc/dub/settings.json` if installed in `/usr/bin/dub`. This is still +loaded if it exists, but if not `/etc/dub/settings.json` will be loaded. +) +) + +$(LI $(LNAME2 injectsourcefile,Adds injection of source files from dependencies via injectSourceFiles command) +$(CHANGELOG_SOURCE_FILE dub, changelog/injectsourcefile.dd) +$(P +Each (sub)package now supports a source file that will be included in any executable or dynamic library that depends either directly or indirectly on it. +) + +$(P +This can be used to register and unregister elements of a package within the dependant package without requiring the dependant to acknowledge that the registration mechanism needs to take place. +) + +$(P +A comparable existing feature to this is the usage of sourceLibrary target type. +A sourceLibrary targetType defers compilation of source code until it is dependent upon by a static library, dynamic library or executable (sub)package. +Unlike sourceLibrary the injection of source code using this feature will inject it into every dynamic library and executable that depends on it, regardless of how deep it is in the dependency graph. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 22788): [REG master] Expression header out of sync) +$(LI $(BUGZILLA 22797): [REG master] Internal Compiler Error: cannot mixin static assert '') +$(LI $(BUGZILLA 22801): [REG 2.099.0-beta.1] Can't return address of return ref parameter from constructor) +$(LI $(BUGZILLA 22810): [REG 2.088] FAIL: runnable/test15.d on BigEndian targets) +$(LI $(BUGZILLA 22833): [REG 2.083] error: 'string' is not a member of 'std') +$(LI $(BUGZILLA 22844): [REG 2.089] SIGBUS, Bus error in _d_newitemU) +$(LI $(BUGZILLA 22881): ICE Index of array outside of bounds at CTFE) +$(LI $(BUGZILLA 22913): importC: array index expression parsed as cast) +$(LI $(BUGZILLA 22961): importC: K&R-style main function rejected) +$(LI $(BUGZILLA 22997): DMD crash: copy ctor can't call other ctor) +$(LI $(BUGZILLA 22999): no switch fallthrough error with multi-valued case) +$(LI $(BUGZILLA 23019): Missing filename when -of points to an existing directory) +$(LI $(BUGZILLA 23036): Rvalue constructor with default parameter crashes compiler in the presence of a copy constructor) +$(LI $(BUGZILLA 23046): [REG][CODEGEN] __simd$(LPAREN)XMM.LODLPS$(RPAREN) bad codegen) +$(LI $(BUGZILLA 23087): getLinkage trait regression for overloads with v2.100.0-rc.1) +$(LI $(BUGZILLA 23089): Linkage-related ICE regression in v2.100.0-rc.1) +$(LI $(BUGZILLA 23097): [REG 2.100] ArrayIndexError@src/dmd/mtype.d$(LPAREN)4767$(RPAREN): index [18446744073709551615] is out of bounds for array of length 0) +$(LI $(BUGZILLA 23098): array literal to scope inout parameter not allowed in safe code) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 7625): inlining only works with explicit else branch) +$(LI $(BUGZILLA 12344): .di generation doesn't include contracts in interfaces) +$(LI $(BUGZILLA 19948): Fully qualified name not used in errors when implicit const conversion is involved) +$(LI $(BUGZILLA 20149): [DIP1000] Local data escapes inout method if not decorated with return) +$(LI $(BUGZILLA 20603): 'cannot use non-constant CTFE pointer in an initializer' in recursive structure with overlap) +$(LI $(BUGZILLA 20881): [DIP1000] scope inference turns return-ref into return-scope) +$(LI $(BUGZILLA 21008): dmd segfaults because of __traits$(LPAREN)getMember, ...$(RPAREN) and virtual function overriding) +$(LI $(BUGZILLA 21324): @live not detecting overwrite of Owner without disposing of previous owned value) +$(LI $(BUGZILLA 21546): covariant return checks for functions wrong if returning by ref) +$(LI $(BUGZILLA 21676): [ICE][SIMD] DMD crashing with SIMD + optimizations + inlining) +$(LI $(BUGZILLA 21975): is expression ignores implicit conversion of struct via alias this when pattern matching) +$(LI $(BUGZILLA 22023): adding `return` to escaped argument of a variadic defeats @safe) +$(LI $(BUGZILLA 22145): scope for foreach parameters is ignored) +$(LI $(BUGZILLA 22202): Wrong error message for implicit call to @system copy constructor in @safe code) +$(LI $(BUGZILLA 22221): [dip1000] pure function can escape parameters through Exception) +$(LI $(BUGZILLA 22234): __traits$(LPAREN)getLinkage$(RPAREN) returns wrong value for extern$(LPAREN)System$(RPAREN) functions) +$(LI $(BUGZILLA 22489): C header generation ignores custom mangling) +$(LI $(BUGZILLA 22539): [dip1000] slicing of returned ref scope static array should not be allowed) +$(LI $(BUGZILLA 22635): opCast prevent calling destructor for const this.) +$(LI $(BUGZILLA 22751): DMD as a library crashes with fatal$(LPAREN)$(RPAREN) on parseModule) +$(LI $(BUGZILLA 22755): ImportC: declared symbol must be available in initializer) +$(LI $(BUGZILLA 22756): ImportC: no __builtin_offsetof) +$(LI $(BUGZILLA 22776): string literal printing fails on non-ASCII/non-printable chars) +$(LI $(BUGZILLA 22782): [dip1000] address of ref can be assigned to non-scope parameter) +$(LI $(BUGZILLA 22793): importC: __import conflicts when importing multiple modules with same package) +$(LI $(BUGZILLA 22802): [dip1000] First ref parameter seen as `return` destination even with `this`) +$(LI $(BUGZILLA 22806): cppmangle: Complex real mangled incorrectly) +$(LI $(BUGZILLA 22807): ImportC: Array index is out of bounds for old-style flexible arrays.) +$(LI $(BUGZILLA 22808): ImportC: function not decaying to pointer to function in return statement.) +$(LI $(BUGZILLA 22809): ImportC: druntime’s definition of __builtin_offsetof leads to dereference of invalid pointer.) +$(LI $(BUGZILLA 22812): ImportC: C11 does not allow newlines between the start and end of a directive) +$(LI $(BUGZILLA 22818): typesafe variadic function parameter of type class should be scope) +$(LI $(BUGZILLA 22823): dmd.root.file: File.read fails to read any file on PPC) +$(LI $(BUGZILLA 22830): Solaris: error: module 'core.stdc.math' import 'signbit' not found) +$(LI $(BUGZILLA 22831): No error for malformed extern$(LPAREN)C$(RPAREN) main function) +$(LI $(BUGZILLA 22837): [dip1000] checkConstructorEscape quits after first non-pointer) +$(LI $(BUGZILLA 22840): [dip1000] inout method with inferred @safe escapes local data) +$(LI $(BUGZILLA 22841): importC: Error: variable 'var' is shadowing variable 'var') +$(LI $(BUGZILLA 22842): importC: cannot declare function with a typedef) +$(LI $(BUGZILLA 22845): DWARF .debug_line section is not standard compliant) +$(LI $(BUGZILLA 22846): [REG 2.066] SIGBUS, Bus error in _d_newarrayiT) +$(LI $(BUGZILLA 22848): DWARF .debug_line section should be generated to conform with DW_AT_stmt_list bounds) +$(LI $(BUGZILLA 22874): ICE: Segmentation fault building druntime on mips64el-linux) +$(LI $(BUGZILLA 22876): importC: expression parsing affected by parentheses that should do nothing) +$(LI $(BUGZILLA 22878): importC: glibc fallback for HUGE_VAL gives 'not representable') +$(LI $(BUGZILLA 22884): ImportC: function does not decay to pointer when being cast) +$(LI $(BUGZILLA 22885): ImportC: typedef declared with itself should work) +$(LI $(BUGZILLA 22886): ImportC: forward declaration of struct in a function prototype leads to redeclaration with different type error) +$(LI $(BUGZILLA 22887): ImportC: typedef enum fails) +$(LI $(BUGZILLA 22892): importC: dereferencing array as pointer is not supported) +$(LI $(BUGZILLA 22894): importC: static struct initializer can't take address of own field) +$(LI $(BUGZILLA 22895): importC: exponent parsed as member access) +$(LI $(BUGZILLA 22896): importC: 'function redeclaration with different type' should ignore const) +$(LI $(BUGZILLA 22897): importC: segfault calling forward-declared static function through pointer) +$(LI $(BUGZILLA 22899): importC: extra parentheses in sizeof should give error with typedef types) +$(LI $(BUGZILLA 22904): importC: syntax error for function call with casted result and parentheses around name) +$(LI $(BUGZILLA 22906): DMD as a library hangs on semantic analysis of non regular D files) +$(LI $(BUGZILLA 22909): importC: u8 strings rejected by parser) +$(LI $(BUGZILLA 22910): [dip1000] return scope struct member functions allow returning `this` by ref) +$(LI $(BUGZILLA 22912): importC: syntax error for function call with cast and typedef and parentheses around name) +$(LI $(BUGZILLA 22914): outdated supplemental error "perhaps remove scope") +$(LI $(BUGZILLA 22915): Errors for invalid foreach aggregates should print the type) +$(LI $(BUGZILLA 22918): importC: some types not zero-initialized in static variables) +$(LI $(BUGZILLA 22919): [dip1000] -checkaction=context gives "assigned to `__assertOp2` with longer lifetime") +$(LI $(BUGZILLA 22923): importC: forward-declared static variable has invalid address) +$(LI $(BUGZILLA 22924): importC: boolean expression result should be int) +$(LI $(BUGZILLA 22927): importC: 'struct already exists' with forward reference and function with same name) +$(LI $(BUGZILLA 22928): importC: array does not have a boolean value) +$(LI $(BUGZILLA 22929): importC: extern array with unknown length gives bounds errors) +$(LI $(BUGZILLA 22930): importC: switch statement should use default:break; if no default specified) +$(LI $(BUGZILLA 22931): importC: Error: `0` has no effect) +$(LI $(BUGZILLA 22933): importC: goto skips declaration of variable) +$(LI $(BUGZILLA 22934): Header generator emits context pointer as `this`) +$(LI $(BUGZILLA 22935): importC: offsetof with array element gives 'dereference of invalid pointer') +$(LI $(BUGZILLA 22951): Dtor missing from generated C++ header) +$(LI $(BUGZILLA 22954): Header generator emits extern$(LPAREN)C$(RPAREN) member functions) +$(LI $(BUGZILLA 22955): importC: wrong alignof for D struct with specified alignment) +$(LI $(BUGZILLA 22970): importC: taking address one past array end gives bounds error) +$(LI $(BUGZILLA 22971): importC: can't initialize unsigned char array with string literal) +$(LI $(BUGZILLA 22972): importC: static variable cannot be read at compile time) +$(LI $(BUGZILLA 22974): importC: D name mangling applied to extern variable inside function) +$(LI $(BUGZILLA 22976): importC: fails to multiply by element size when doing address-of) +$(LI $(BUGZILLA 22988): no short-circuiting when constant folding ternary operator) +$(LI $(BUGZILLA 22994): importC: some types not zero-initialized in static array) +$(LI $(BUGZILLA 23000): final switch error has no line number with -checkaction=C) +$(LI $(BUGZILLA 23002): importC: struct or union field with same name as type gives circular reference error) +$(LI $(BUGZILLA 23003): ImportC should not import object.d) +$(LI $(BUGZILLA 23004): importC: calling function pointer named 'init' or 'stringof' from struct or union pointer gives error) +$(LI $(BUGZILLA 23008): importC: dmd asserts on empty struct or union as global) +$(LI $(BUGZILLA 23009): [CODEGEN][SIMD] SIMD + optimizations + inlining + double) +$(LI $(BUGZILLA 23011): importC: asm label to set symbol name doesn't work with externs) +$(LI $(BUGZILLA 23017): C++ class may not derive from D class) +$(LI $(BUGZILLA 23025): ImportC: duplicate symbol for tentative definition and definition of variable) +$(LI $(BUGZILLA 23028): ImportC: found _Generic instead of statement) +$(LI $(BUGZILLA 23029): ImportC: _Generic treats pointer to const and regular pointers as the same type) +$(LI $(BUGZILLA 23031): importC: hex character escapes should be variable length) +$(LI $(BUGZILLA 23034): importC: head-const struct confused with multiple files on command line) +$(LI $(BUGZILLA 23037): importC: type with only type-qualifier doesn't work) +$(LI $(BUGZILLA 23038): importC: sizeof inside struct has struct members in scope) +$(LI $(BUGZILLA 23039): importC: declaration with array length has itself in scope) +$(LI $(BUGZILLA 23044): importC: comma expression with function call parsed as declaration) +$(LI $(BUGZILLA 23045): importC: casted function type is missing extern$(LPAREN)C$(RPAREN)) +$(LI $(BUGZILLA 23047): [ICE][SIMD] Do not SROA vector types) +$(LI $(BUGZILLA 23056): importC: dmd asserts for missing return statement in CTFE function) +$(LI $(BUGZILLA 23057): importC: dmd segfault on invalid syntax) +$(LI $(BUGZILLA 23066): importC: cannot initialize char array with string literal of different length) +$(LI $(BUGZILLA 23075): global const string definitions should go in readonly segment) +$(LI $(BUGZILLA 23077): codegen cannot generage XMM load/store for optimized operation that uses byte/short/...) +$(LI $(BUGZILLA 23083): .tupleof on static array rvalue evaluates expression multiple times) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 3632): modify float is float to do a bitwise compare) +$(LI $(BUGZILLA 11463): DDoc html to show the normal escaped ASCII chars) +$(LI $(BUGZILLA 14277): Compile-time array casting error - ugly error report) +$(LI $(BUGZILLA 20853): static array ptr cannot be used in safe code but it should be allowed) +$(LI $(BUGZILLA 21673): [SIMD][Win64] Wrong codegen for _mm_move_ss) +$(LI $(BUGZILLA 22027): inout shouldn't imply return) +$(LI $(BUGZILLA 22541): DIP1000: Resolve ambiguity of ref-return-scope parameters) +$(LI $(BUGZILLA 22770): C++ header generator generates trailing newlines) +$(LI $(BUGZILLA 22790): ref-return-scope is always ref-return, scope, unless return-scope appear in that order) +$(LI $(BUGZILLA 22820): Error messages for slice pointers of structs with opIndex can be improved) +$(LI $(BUGZILLA 22821): Dub package does not use incremental compilation) +$(LI $(BUGZILLA 22861): Build the compiler with PGO) +$(LI $(BUGZILLA 22880): importC: support __restrict__ __signed__ __asm__) +$(LI $(BUGZILLA 22922): Support empty array literal in -betterC) +$(LI $(BUGZILLA 22945): [Conditional Compilation] support invariant version flag) +$(LI $(BUGZILLA 22967): [dip1000] no return ref inference for extended return semantics) +$(LI $(BUGZILLA 23021): [dip1000] infer return scope from pure nothrow) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 20182): [REG 2.086.0] std.traits.ParameterDefaults fails for copy constructor of nested struct) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 13541): std.windows.syserror.sysErrorString$(LPAREN)$(RPAREN) should be nothrow) +$(LI $(BUGZILLA 18036): Documentation of moveFront$(LPAREN)$(RPAREN) fails to mention different behavior depending on hasElaborateCopyConstructor) +$(LI $(BUGZILLA 22213): Base64: Missing `@nogc` attribute on encodeLength) +$(LI $(BUGZILLA 22503): Invalid changelog entry for isValidCodePoint) +$(LI $(BUGZILLA 22771): BigInt divMod can return "-0" $(LPAREN)negative zero$(RPAREN)) +$(LI $(BUGZILLA 22791): std\socket.d$(LPAREN)790$(RPAREN) Heisenbug random failure) +$(LI $(BUGZILLA 22851): Missing reference to std.sumtype's source in the latter's documentation) +$(LI $(BUGZILLA 22867): std.utf.decode changes offset despite error.) +$(LI $(BUGZILLA 22873): Wrong std.format output for `inout`) +$(LI $(BUGZILLA 22901): Can't construct inout SumType) +$(LI $(BUGZILLA 22946): WindowsException ctor is not nothrow) +$(LI $(BUGZILLA 22947): sysErrorString throws Exception instead of WindowsException) +$(LI $(BUGZILLA 22998): Update to zlib 1.2.12) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 22736): Add destructuring bind for std.typecons.Tuple tuples) +$(LI $(BUGZILLA 22798): defaultGetoptPrinter should be @safe) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 22829): [REG master] Undefined symbol stderr first referenced in file test19933.o) +$(LI $(BUGZILLA 22834): runnable_cxx/stdint.d: Undefined reference to _Z15testCppI8Mangleahahah) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 18117): ldiv_t struct in core.stdc.stdlib -- int vs c_long expectations) +$(LI $(BUGZILLA 21631): core.atomic.cas fails to compile with const ifThis $(LPAREN)if target is a pointer$(RPAREN)) +$(LI $(BUGZILLA 22763): importing std.utf fails in BetterC) +$(LI $(BUGZILLA 22822): core.sys.posix.sys.stat: PPC stat_t bindings corrupt) +$(LI $(BUGZILLA 22832): Can't destroy class with overloaded opCast) +$(LI $(BUGZILLA 22843): Program hangs on full gc collect with --DRT-gcopt=fork:1 if run under valgrind/callgrind) +$(LI $(BUGZILLA 23051): OpenBSD: Build broken on 2.100.0-beta.1 due to the inout attribute no longer implying the return attribute) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 18816): [betterC] Standard Streams Unlinkable) +$(LI $(BUGZILLA 19933): MSVC: Undefined std{in,out,err} with -betterC) +$(LI $(BUGZILLA 22766): copyEmplace does not work with copy constructor and @disable this$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 22964): array cast message is awkwardly worded) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 15437): documentation for typeof$(LPAREN)someTemplate$(RPAREN) == void) +$(LI $(BUGZILLA 22215): returning expired stack pointers in @system code allowed by spec, not by implementation) +$(LI $(BUGZILLA 22795): Access denied when trying to download DMD 2.099.0-beta.1) +$(LI $(BUGZILLA 22850): [Oh No! Page Not Found] Contract Programming) +$(LI $(BUGZILLA 22959): Documentation for C/D main is incomplete) +) +$(BUGSTITLE_BUGZILLA Installer bug fixes, + +$(LI $(BUGZILLA 22958): [Internal] Installer uses outdated image on Azure) +) +) +$(D_CONTRIBUTORS_HEADER 41) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Andrei Alexandrescu) + $(D_CONTRIBUTOR Arne Ludwig) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Brian Callahan) + $(D_CONTRIBUTOR Cameron Ross) + $(D_CONTRIBUTOR canopyofstars) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR devmynote) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR Etienne Brateau) + $(D_CONTRIBUTOR Florian) + $(D_CONTRIBUTOR Gabriel) + $(D_CONTRIBUTOR Harry T. Vennik) + $(D_CONTRIBUTOR human) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Ilya Yaroshenko) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR João Lourenço) + $(D_CONTRIBUTOR Luís Ferreira) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Max Haughton) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR rikki cattermole) + $(D_CONTRIBUTOR sorin-gabriel) + $(D_CONTRIBUTOR Steven Dwy) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Teodor Dutu) + $(D_CONTRIBUTOR Tim Schendekehl) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.100.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.100.1.dd b/changelog/2.100.1.dd new file mode 100644 index 0000000000..4fb3477494 --- /dev/null +++ b/changelog/2.100.1.dd @@ -0,0 +1,109 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 15, 2022, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 1 major change and 16 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 14 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 deprecate_scope_failure_return,`scope(failure)` blocks that contain `return` statements are now deprecated)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 deprecate_scope_failure_return,`scope(failure)` blocks that contain `return` statements are now deprecated) +$(CHANGELOG_SOURCE_FILE dmd, release/script/tools/../dmd/changelog/deprecate_scope_failure_return.dd) +$(P +Starting with this release, having a `return` statement in the body of a `scope(failure)` +statement is deprecated. Having the ability to `return` from such blocks is error prone since currently, Errors are also handled by `scope(failure)`. This leads to the following situation: +) + +--- +ulong get () @safe nothrow +{ + scope (failure) return 10; + throw new Error(""); +} + +void main () @safe +{ + assert(get() == 10); // passes +} +--- + +$(P +where an error is circumvented by a return. If a return is indeed desired +in such situations, then the solution is to simply use a try-catch block +for the function body. +) + +$(P +Note: `scope(exit)` and `scope(success)` already present this restriction. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 23100): empty array literal passed to scope param not 'falsey' anymore) +$(LI $(BUGZILLA 23148): Missing invariant symbol with static library when template function declares struct with destructor and invariant that instantiates template with lambda, also main has a lambda) +$(LI $(BUGZILLA 23170): Array literal passed to map in lambda, then returned from nested function, is memory corrupted) +$(LI $(BUGZILLA 23172): [REG2.100] Wrong cast inserted for ternary operator and non-int enums) +$(LI $(BUGZILLA 23181): [REG 2.099] AssertError@src/dmd/e2ir.d$(LPAREN)6094$(RPAREN): Trying reference _d_arraysetctor) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 20143): ICE in optimizer on real 0/0 returned as double) +$(LI $(BUGZILLA 21443): scope $(LPAREN)failure$(RPAREN) with a return breaks safety) +$(LI $(BUGZILLA 21723): Linker error: two module static library, main compiled inline, invariant that defines a function, type alias, and an alias lambda) +$(LI $(BUGZILLA 23082): stringof of template alias overloaded with function accessed by trait: segfault.) +$(LI $(BUGZILLA 23102): pinholeopt, "Conditional jump or move depends on uninitialised value$(LPAREN)s$(RPAREN)") +$(LI $(BUGZILLA 23108): ICE: AssertError@src/dmd/clone.d$(LPAREN)567$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 23109): ICE: AssertError@src/dmd/dclass.d$(LPAREN)449$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 23114): Can't use noreturn operand in arithmetic expression) +$(LI $(BUGZILLA 23120): dmd illegal instruction throw expression) +$(LI $(BUGZILLA 23166): seg fault when compiling with -inline) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 23132): "cannot access frame pointer" comparing two ranges for equality from v2.099.0) +) +) +$(D_CONTRIBUTORS_HEADER 14) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR FeepingCreature) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR mhh) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR richard andrew cattermole) + $(D_CONTRIBUTOR Tomáš Chaloupka) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.100.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.100.2.dd b/changelog/2.100.2.dd new file mode 100644 index 0000000000..8916b79cda --- /dev/null +++ b/changelog/2.100.2.dd @@ -0,0 +1,118 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 10, 2022, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 1 major change and 21 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 18 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 deprecate_scope_failure_return,`scope(failure)` blocks that contain `return` statements are now deprecated)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 deprecate_scope_failure_return,`scope(failure)` blocks that contain `return` statements are now deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/deprecate_scope_failure_return.dd) +$(P +Starting with this release, having a `return` statement in the body of a `scope(failure)` +statement is deprecated. Having the ability to `return` from such blocks is error prone since currently, Errors are also handled by `scope(failure)`. This leads to the following situation: +) + +--- +ulong get () @safe nothrow +{ + scope (failure) return 10; + throw new Error(""); +} + +void main () @safe +{ + assert(get() == 10); // passes +} +--- + +$(P +where an error is circumvented by a return. If a return is indeed desired +in such situations, then the solution is to simply use a try-catch block +for the function body. +) + +$(P +Note: `scope(exit)` and `scope(success)` already present this restriction. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 23100): empty array literal passed to scope param not 'falsey' anymore) +$(LI $(BUGZILLA 23148): Missing invariant symbol with static library when template function declares struct with destructor and invariant that instantiates template with lambda, also main has a lambda) +$(LI $(BUGZILLA 23170): Array literal passed to map in lambda, then returned from nested function, is memory corrupted) +$(LI $(BUGZILLA 23172): [REG2.100] Wrong cast inserted for ternary operator and non-int enums) +$(LI $(BUGZILLA 23181): [REG 2.099] AssertError@src/dmd/e2ir.d$(LPAREN)6094$(RPAREN): Trying reference _d_arraysetctor) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 20143): ICE in optimizer on real 0/0 returned as double) +$(LI $(BUGZILLA 21443): scope $(LPAREN)failure$(RPAREN) with a return breaks safety) +$(LI $(BUGZILLA 21723): Linker error: two module static library, main compiled inline, invariant that defines a function, type alias, and an alias lambda) +$(LI $(BUGZILLA 23082): stringof of template alias overloaded with function accessed by trait: segfault.) +$(LI $(BUGZILLA 23102): pinholeopt, "Conditional jump or move depends on uninitialised value$(LPAREN)s$(RPAREN)") +$(LI $(BUGZILLA 23108): ICE: AssertError@src/dmd/clone.d$(LPAREN)567$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 23109): ICE: AssertError@src/dmd/dclass.d$(LPAREN)449$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 23114): Can't use noreturn operand in arithmetic expression) +$(LI $(BUGZILLA 23120): dmd illegal instruction throw expression) +$(LI $(BUGZILLA 23166): seg fault when compiling with -inline) +$(LI $(BUGZILLA 23177): ModuleInfo is not exported on Windows) +$(LI $(BUGZILLA 23234): Delegate literal with inferred return value that requires following alias-this uses class cast instead.) +$(LI $(BUGZILLA 23258): ICE on SumType of two arrays of classes) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 23132): "cannot access frame pointer" comparing two ranges for equality from v2.099.0) +$(LI $(BUGZILLA 23140): Array!T where T is a shared class no longer works) +$(LI $(BUGZILLA 23238): Cannot write a const Nullable$(LPAREN)T, T nullValue$(RPAREN)) +) +) +$(D_CONTRIBUTORS_HEADER 18) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR dawg) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR FeepingCreature) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Max Haughton) + $(D_CONTRIBUTOR mhh) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR richard andrew cattermole) + $(D_CONTRIBUTOR RubyTheRoobster) + $(D_CONTRIBUTOR Tomáš Chaloupka) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR wolframw) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.100.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.101.0.dd b/changelog/2.101.0.dd new file mode 100644 index 0000000000..160ea2f5b3 --- /dev/null +++ b/changelog/2.101.0.dd @@ -0,0 +1,1191 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Nov 14, 2022, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 40 major changes and 209 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 72 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.bitfields,Add bit fields to D)) +$(LI $(RELATIVE_LINK2 dmd.class_instance_alignment,Added `__traits(classInstanceAlignment)`)) +$(LI $(RELATIVE_LINK2 dmd.crt_constructor_signature,Relaxed `pragma(crt_constructor)` / `pragma(crt_destructor)` linkage check)) +$(LI $(RELATIVE_LINK2 dmd.d_optimized,Add predefined version `D_Optimized` when compiling with `-O`)) +$(LI $(RELATIVE_LINK2 dmd.deprecate_throwing_nothrow_contracts,Throwing from contracts of `nothrow` functions has been deprecated)) +$(LI $(RELATIVE_LINK2 dmd.deprecate_version_int,Using integers for `version` or `debug` conditions has been deprecated)) +$(LI $(RELATIVE_LINK2 dmd.dip1000_deprecation_warnings,Print deprecations for `scope` pointer errors)) +$(LI $(RELATIVE_LINK2 dmd.dtoh-improvements,Improvements for the C++ header generation)) +$(LI $(RELATIVE_LINK2 dmd.fix-immutable-conv,`-preview=fixImmutableConv` has been added)) +$(LI $(RELATIVE_LINK2 dmd.fix22134,Returning a discarded void value from a function is now deprecated)) +$(LI $(RELATIVE_LINK2 dmd.importc_typeof,ImportC now recognizes the `typeof(...)` operator)) +$(LI $(RELATIVE_LINK2 dmd.markdown,Removed the `-transition=markdown` and `-revert=markdown` switches)) +$(LI $(RELATIVE_LINK2 dmd.new-aa,`new` can now allocate an associative array)) +$(LI $(RELATIVE_LINK2 dmd.previewInLink,`-preview=in` can now be used with `extern(C++)`, disabled for other non-D linkage)) +$(LI $(RELATIVE_LINK2 dmd.shortenedMethodsEnabled,The shortened method syntax is now available by default.)) +$(LI $(RELATIVE_LINK2 dmd.unicode-directionality,Source files may no longer contain Unicode directionality overrides)) +$(LI $(RELATIVE_LINK2 dmd.windows_stack_limit,Windows: Double DMD stack limit to 16 MB)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 druntime.cpuid-add-avx512f,Added avx512f detection to `core.cpuid`)) +$(LI $(RELATIVE_LINK2 druntime.drt-oncycle-deprecate,`--DRT-oncycle=deprecate` is removed)) +$(LI $(RELATIVE_LINK2 druntime.posix_gc_signals,Posix (excl. Darwin): Switch default GC signals from SIGUSR1/2 to SIGRTMIN/SIGRTMIN+1)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 borrow_for_refcounted,Added `SafeRefCounted`, that can be used in `@safe` with `-preview=dip1000`.)) +$(LI $(RELATIVE_LINK2 logger,Move logger out of experimental.)) +$(LI $(RELATIVE_LINK2 logger_remove_compile_time_loglevel,remove std.experimental.logger's capability to set the minimal LogLevel at compile time)) +$(LI $(RELATIVE_LINK2 logger_sharedLog_returning_shared_logger,Change std.experimental.logger.core.sharedLog to return shared(Logger))) +$(LI $(RELATIVE_LINK2 remove-experimental-typecons,std.experimental.typecons has been removed)) +$(LI $(RELATIVE_LINK2 remove-std-digest-digest,std.digest.digest has been removed)) +$(LI $(RELATIVE_LINK2 remove-std-xml,std.xml has been removed)) +$(LI $(RELATIVE_LINK2 scopesocket,`std.socket.Socket` methods now accept only `scope` arrays.)) +$(LI $(RELATIVE_LINK2 std_outbuffer_align,Add custom fill value to std.outbuffer.OutBuffer class)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 build_unittest,Building the special test runner configuration)) +$(LI $(RELATIVE_LINK2 colored_output,Output will now be colorized)) +$(LI $(RELATIVE_LINK2 configy_stricter_parsing,dub will now warn on unrecognized fields in `dub.json`, settings, or selections file)) +$(LI $(RELATIVE_LINK2 cov_ctfe,The two new build types `cov-ctfe` and `unittest-cov-ctfe` have been added.)) +$(LI $(RELATIVE_LINK2 dpath,DUB settings & packages directory placement overhauled)) +$(LI $(RELATIVE_LINK2 exitcodes,DUB command exit codes have been made more consistent)) +$(LI $(RELATIVE_LINK2 install_uninstall,'install' and 'uninstall' commands have been removed)) +$(LI $(RELATIVE_LINK2 make-copies-writable,When `copyFiles` is used to copy read-only files, it now makes the copy writable.)) +$(LI $(RELATIVE_LINK2 overrides_deprecated,The override system is deprecated)) +$(LI $(RELATIVE_LINK2 subpackage_short_syntax,The shortcut syntax for "dub run" is now also available for sub packages.)) +$(LI $(RELATIVE_LINK2 subpackage_upgrade,Upgrading all sub packages at once)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.bitfields,Add bit fields to D) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.bitfields.dd) +$(P +They work just like the bit fields in ImportC do. +) + +$(P +https://github.com/dlang/dlang.org/pull/3190 +) + +--- +struct B +{ + int x:3, y:2; +} + +static assert(B.sizeof == 4); + +int vaporator(B b) +{ + b.x = 4; + b.y = 2; + return b.x + b.y; // returns 6 +} +--- +) + +$(LI $(LNAME2 dmd.class_instance_alignment,Added `__traits(classInstanceAlignment)`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.class_instance_alignment.dd) +$(P +To complement `__traits(classInstanceSize)`, providing the required +alignment for manual buffers etc.: +) + +--- +align(__traits(classInstanceAlignment, C)) +void[__traits(classInstanceSize, C)] buffer; +--- +) + +$(LI $(LNAME2 dmd.crt_constructor_signature,Relaxed `pragma(crt_constructor)` / `pragma(crt_destructor)` linkage check) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.crt_constructor_signature.dd) +$(P +`extern(C)` isn't a requirement for CRT con/destructors anymore when +using the default `void ()` signature. +) +) + +$(LI $(LNAME2 dmd.d_optimized,Add predefined version `D_Optimized` when compiling with `-O`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.d_optimized.dd) +$(P +It allows code to distinguish whether it's being compiled with optimizations enabled (the `-O` flag was provided). +This is orthogonal to whether `-release` mode is active - for that see the +predefined versions `assert`, `D_NoBoundsChecks`, `D_Invariants`, etc. +) +) + +$(LI $(LNAME2 dmd.deprecate_throwing_nothrow_contracts,Throwing from contracts of `nothrow` functions has been deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecate_throwing_nothrow_contracts.dd) +$(P +Up until now, the compiler accepted `in` and `out` contracts of `nothrow` +functions to throw exceptions and call throwing functions. As this breaks +`nothrow` guarantees, a deprecation notice is now triggered. +) + +--- +// deprecated: +float sqrt(float n) nothrow +in +{ + if (n < 0) + throw new Exception("n must be positive"); +} +do +{ + // ... +} + +// fix: remove nothrow attribute or use assertions +float sqrt(float n) nothrow +in +{ + assert(n >= 0); +} +do +{ + // ... +} +--- +) + +$(LI $(LNAME2 dmd.deprecate_version_int,Using integers for `version` or `debug` conditions has been deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecate_version_int.dd) +$(P +The problem is that it only provides a single number namespace without any meaning. +It's better to use version identifiers describing the feature they enable. +See also [this thread on the forum](https://forum.dlang.org/post/chtcuqdjzddlesdhablo@forum.dlang.org). +) + +--- +// now deprecated: +version = 3; +version (2) { } + +debug = 4; +debug (5) { } + +// use identifiers instead: +version = HasX; + +version (HasX) + void x() { /* ... */ } +else + void x() {} +--- +) + +$(LI $(LNAME2 dmd.dip1000_deprecation_warnings,Print deprecations for `scope` pointer errors) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.dip1000_deprecation_warnings.dd) +$(P +The `scope` attribute has existed for a long time, but the compiler would only verify its semantics when the `-preview=dip1000` switch was passed, to avoid breaking code. +Pointers or references stored in a scope variable are not allowed to escape the scope in which the variable is defined. +) + +$(P +Usually, it is not necessary to mark variables `scope`, since the [Garbage Collector](https://dlang.org/spec/garbage.html) (GC) takes care of freeing memory. +However, D allows creating pointers / slices that point to local variables, which use [Stack-based memory allocation](https://en.wikipedia.org/wiki/Stack-based_memory_allocation) and are destructed at the end of their scope. +It is important that in `@safe` code, creating such pointers is either disallowed, or has `scope` semantics enforced, but the compiler would formerly fail to do that: +) + +--- +@safe: +int[] getSlice() +{ + int[4] stackBuffer; + int[] slice = stackBuffer[]; // slice points to local variable allocated on stack + return slice; // dangling pointer! +} + +struct S +{ + int x; + + int* get() + { + int* y = &this.x; // this struct instance could be a local variable + return y; // dangerous! + } +} +--- + +$(P +Starting with this release, `scope` semantics are enforced in `@safe` code on pointers to stack memory, but only as deprecation warnings. +Eventually, they will be turned into errors. +To turn them into errors immediately, use `-preview=dip1000`. +To disable the deprecations, use `-revert=dip1000`. +) + +$(P +Note that [the original DIP1000 text](https://dlang.org/dips/1000) is outdated, so please refer to the specification pages for documentation: +) + +$(P +$(UL + $(LI $(DDSUBLINK spec/memory-safe-d, scope-return-params, Scope and Return Parameters) ) + $(LI $(DDSUBLINK spec/attribute, scope, scope Attribute) ) + $(LI $(DDSUBLINK spec/function, scope-parameters, Scope Parameters) ) + $(LI $(DDSUBLINK spec/function, return-scope-parameters, Return Scope Parameters) ) + $(LI $(DDSUBLINK spec/function, return-ref-scope-parameters, Ref Return Scope Parameters) ) + $(LI $(DDSUBLINK spec/function, pure-scope-inference, Inferred scope parameters in pure functions) ) +) +) +) + +$(LI $(LNAME2 dmd.dtoh-improvements,Improvements for the C++ header generation) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.dtoh-improvements.dd) +$(P +The following features/bugfixes/improvements were implemented for the +experimental C++ header generator: +) + +$(P +- Overriding virtual functions are now marked with the `override` keyword when + generating C++11 compatible headers. +- Final virtual functions are now marked with the `final` keyword when + generating C++11 compatible headers. +) + +$(P +Note: The header generator is still considered experimental, so please submit + any bugs encountered to [the bug tracker](https://issues.dlang.org). +) +) + +$(LI $(LNAME2 dmd.fix-immutable-conv,`-preview=fixImmutableConv` has been added) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.fix-immutable-conv.dd) +$(P +The compiler allows implicitly converting a return value with indirections to immutable if it determines the result is unique. +Formerly, this check would inspect the types of the indirections, and forget to take into account conversions, such as `int[]` to `void[]`: +) + +--- +int[] f(ref void[] m) pure +{ + auto result = new int[5]; + m = result; + return result; +} + +void main() +{ + void[] v; + immutable x = f(v); + // `v` is now a mutable alias to immutable variable `x` +} +--- + +$(P +This was filed as [issue 15660](https://issues.dlang.org/show_bug.cgi?id=15660), which has been fixed some time ago by making the check more strict: the called function must be strongly pure. +However, to avoid breaking code, the fix was only active with the `-preview=dip1000` switch. +Since it is unrelated to dip1000 (which is about `scope` pointers), the fix has been moved to a new `-preview=fixImmutableConv` switch. +) +) + +$(LI $(LNAME2 dmd.fix22134,Returning a discarded void value from a function is now deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.fix22134.dd) +$(P +An expression statement of type void that has no side effects should +be discarded since it has no effect. The compiler, generally, does not +allow such statements, however, in the case of return statements this +error is circumvented. For example: +) + +--- +struct StackBuffer +{ + auto opIndex(size_t i) + { + return arr[i]; + } + +private: + void[] arr; +} +--- + +$(P +Although this code compiles, any call to `opIndex` is going to result in an +error because the return type must either be stored somewhere (and variables +cannot be of type void) or the call will have no effect. +) + +$(P +Starting with this release, returning a discarded void value from a function +is deprecated. Such code can be deleted as it most certainly is dead code. +) +) + +$(LI $(LNAME2 dmd.importc_typeof,ImportC now recognizes the `typeof(...)` operator) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.importc_typeof.dd) +$(P +ISO C does not specify a `typeof` operator, but it is a widely-implemented vendor extension. +ImportC now implements this extension as well. +) + +$(P +Only the form `typeof(...)` is recognized, other compilers also support (or only support one of) +`__typeof__(...)` and `__typeof(...)`. Imported C using these forms will need to be normalized with `#define`s. +) +) + +$(LI $(LNAME2 dmd.markdown,Removed the `-transition=markdown` and `-revert=markdown` switches) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.markdown.dd) +$(P +This release removes the `-transition=markdown`, which prints markdown substitutions +made when processing markdown in ddoc documentation blocks, and `-revert=markdown` +switches which disables markdown substitutions in ddoc documentation blocks. +) + +$(P +Markdown substitutions have been the default for some time now, and as of this release +is always performed. +) +) + +$(LI $(LNAME2 dmd.new-aa,`new` can now allocate an associative array) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.new-aa.dd) +$(P +This allows two associative array references to point to the same +associative array instance before any keys have been inserted. +) + +--- +int[string] a = new int[string]; +auto b = a; +... +a["seven"] = 7; +assert(b["seven"] == 7); +--- + +$(P +Note: Calling `new` is not needed before inserting keys on a null +associative array reference - the instance will be allocated if it +doesn't exist. +) +) + +$(LI $(LNAME2 dmd.previewInLink,`-preview=in` can now be used with `extern(C++)`, disabled for other non-D linkage) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.previewInLink.dd) +$(P +The intent of `-preview=in` is to make `in` the go-to storage class for input parameters in D. +However, it is D centric, as it is an enhanced version of `scope const ref`. +As non-`extern(D)` functions usually are expected to match a specific ABI, +using `in` is hardly a good idea. +) + +$(P +As C++ also has a "go to" storage class for input parameters (`const T&`), +`in` can also be applied on `extern(C++)` function in order to bind to `const T&` parameters. +This also allows to expose a closer API for a function than via `const ref`, +as `in` will allow to bind rvalues to `const T&`, as in C++. +) +) + +$(LI $(LNAME2 dmd.shortenedMethodsEnabled,The shortened method syntax is now available by default.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.shortenedMethodsEnabled.dd) +$(P +[DIP 1043---Shortened Method Syntax](https://forum.dlang.org/thread/ahswpyijfidyorixgaqm@forum.dlang.org) has been accepted, the flag `-preview=shortenedMethods` +is no longer required to write shortened function bodies: +) + +--- +int add(int x, int y) pure => x + y; + +// equivalent full function body: +int add(int x, int y) pure +{ + return x + y; +} +--- + +$(P +The preview flag will still work until it is deprecated in a future release. +) +) + +$(LI $(LNAME2 dmd.unicode-directionality,Source files may no longer contain Unicode directionality overrides) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.unicode-directionality.dd) +$(P +[Trojan Source: Invisible Vulnerabilities](https://github.com/nickboucher/trojan-source) shows how they can be used to maliciously hide code in various programming languages. +[D is also affected](https://github.com/nickboucher/trojan-source/pull/16). +) + +$(P +To prevent this, the compiler now raises an error when they appear in source files. +If you need a string literal containing directionality overrides, use escape sequences instead: +) +--- +string s = "\u202E\u2066"; +--- +) + +$(LI $(LNAME2 dmd.windows_stack_limit,Windows: Double DMD stack limit to 16 MB) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.windows_stack_limit.dd) +$(P +The compilation of some projects require more stack space than previously available. +Now DMD has the same limit as LDC, which +$(LINK2 https://github.com/ldc-developers/ldc/pull/3921, increased its stack limit) +in its 1.29.0 release. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 druntime.cpuid-add-avx512f,Added avx512f detection to `core.cpuid`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.cpuid-add-avx512f.dd) +$(P +The feature flag `core.cpuid.avx512f` has been added to allow detection at +run-time CPUs with 512-bit vector support. +) +) + +$(LI $(LNAME2 druntime.drt-oncycle-deprecate,`--DRT-oncycle=deprecate` is removed) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.drt-oncycle-deprecate.dd) +$(P +The option was [introduced in 2.072.2](https://dlang.org/changelog/2.072.2.html#drt-cycle-deprecated) to help transition code that relied on the old faulty cycle checker for module constructors. +It now prints a warning and does the same as the default, `--DRT-oncycle=abort`. +See also: $(DDSUBLINK spec/module, order_of_static_ctor, Order of Static Construction) in the specification. +) +) + +$(LI $(LNAME2 druntime.posix_gc_signals,Posix (excl. Darwin): Switch default GC signals from SIGUSR1/2 to SIGRTMIN/SIGRTMIN+1) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.posix_gc_signals.dd) +$(P +As the SIGUSR ones might be used by 'system' libraries (e.g., Android +Dalvik VM or LLVM libFuzzer), while the SIGRT ones are reserved for +user-defined purposes and less likely to collide. +) + +$(P +The used signals can still be customized with an early call to +`core.thread.osthread.thread_setGCSignals()`. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 borrow_for_refcounted,Added `SafeRefCounted`, that can be used in `@safe` with `-preview=dip1000`.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/borrow_for_refcounted.dd) +$(P +`RefCounted` is only available for `@system` code, because of the possibility of +escaping a reference to its payload past the end of its lifetime. a modified +copy of it, `std.typecons.SafeRefCounted` has been added. Also added is a +`borrow` function, that lets one safely access and modify the payload. +`-preview=dip1000` prevents escaping a reference to it in `@safe` code. +) + +------- +@safe pure nothrow void fun() +{ + import std.typecons; + + auto rcInt = safeRefCounted(5); + assert(rcInt.borrow!(theInt => theInt) == 5); + auto sameInt = rcInt; + assert(sameInt.borrow!"a" == 5); + + // using `ref` in the function + auto arr = [0, 1, 2, 3, 4, 5, 6]; + sameInt.borrow!(ref (x) => arr[x]) = 10; + assert(arr == [0, 1, 2, 3, 4, 10, 6]); + + // modifying the payload via an alias + sameInt.borrow!"a*=2"; + assert(rcInt.borrow!"a" == 10); +} +------- + +$(P +Direct access to the payload unfortunately has to be `@system`, though. While +`-dip1000` could prevent escaping the reference, it is possible to destroy the +last reference before the end of it's scope: +) + +------- +int destroyFirstAndUseLater() +{ + import std.typecons; + + auto rc = SafeRefCounted!int(123); + int* ptr = &rc.refCountedPayload(); + destroy(rc); + return *ptr; // Reads from freed memory. Don't do this. +} +------- + +$(P +As a side effect, this enabled us to make $(REF dirEntries, std, file) `@safe` +with `-preview=dip1000`. +) + +$(P +Some member functions of `RefCounted` that are `@safe` are not so in +`SafeRefCounted`. The `RefCounted` type and `refCounted` function are still +available for the old behaviour. However, their main purpose is backwards +compatibility. They are not recommended for new code. +) +) + +$(LI $(LNAME2 logger,Move logger out of experimental.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/logger.dd) +$(P +The std.experimental.logger package is now std.logger. The old package and modules are +still available and publicly import the new ones. To avoid breakage in modules that compile +with deprecations as errors, for now the old modules aren't deprecated, but they will be. +) +) + +$(LI $(LNAME2 logger_remove_compile_time_loglevel,remove std.experimental.logger's capability to set the minimal LogLevel at compile time) +$(CHANGELOG_SOURCE_FILE phobos, changelog/logger_remove_compile_time_loglevel.dd) +$(P +Before this change std.experimental.logger had the capability to disable +logging at compile time. +It was also possible to set the minimal LogLevel at compile time. +The trade-off between gained capability, added complexity, and error-proneness +was too heavily tilted towards the second two items. +This change removes these compile time features. +) +) + +$(LI $(LNAME2 logger_sharedLog_returning_shared_logger,Change std.experimental.logger.core.sharedLog to return shared(Logger)) +$(CHANGELOG_SOURCE_FILE phobos, changelog/logger_sharedLog_returning_shared_logger.dd) +$(P +To make unsafe code more explicit std.experimental.logger.sharedLog +now returns a shared(Logger) instead of a Logger. +) +) + +$(LI $(LNAME2 remove-experimental-typecons,std.experimental.typecons has been removed) +$(CHANGELOG_SOURCE_FILE phobos, changelog/remove-experimental-typecons.dd) +$(P +This was an attempt to update `std.typecons.wrap` with an implementation that could work with struct, but it did not go anywhere. +See [this post on the forum](https://forum.dlang.org/post/ialskabybaxtqamgtwge@forum.dlang.org). +) +) + +$(LI $(LNAME2 remove-std-digest-digest,std.digest.digest has been removed) +$(CHANGELOG_SOURCE_FILE phobos, changelog/remove-std-digest-digest.dd) +$(P +This module was initially deprecated in 2.076.1, and has been empty since +2.092.0 when all deprecated symbols were removed in favour of importing +`std.digest` or its submodules instead. +) +) + +$(LI $(LNAME2 remove-std-xml,std.xml has been removed) +$(CHANGELOG_SOURCE_FILE phobos, changelog/remove-std-xml.dd) +$(P +This module is considered out-dated and not up to Phobos' current standards. +If you still need it, go to $(LINK https://github.com/DigitalMars/undeaD) +) +) + +$(LI $(LNAME2 scopesocket,`std.socket.Socket` methods now accept only `scope` arrays.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/scopesocket.dd) +$(P +To comply with dip1000, `std.socket.Socket` methods now all have `scope` +attributes applied to any slice parameters. This includes `receive` and `send` +flavors, and also `setOption`. While not technically a breaking change for +users of `Socket`, if you derive from it, you must apply those attributes to your +derivatives or it will fail to compile. However, applying the attributes is +backwards compatible with previous versions of Phobos, so there is no need for +a migration path. +) +) + +$(LI $(LNAME2 std_outbuffer_align,Add custom fill value to std.outbuffer.OutBuffer class) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std_outbuffer_align.dd) +$(P +Extend the fill, alignSize, align{2,4} methods of `std.outbuffer.OutBuffer` to specify value to write +when filling (up to an alignment). +) + +$(P +For flash device images it is desirable to use 0xff as the fill value, +because 0xff is the value of the unprogrammed flash memory cell. Padding +with 0 requires to programm the flash cell from 0xff to 0x00, which +increases wear and tear on the flash memory device. Usually there is some +larger block at the end if the flash memory image, which must be padded +up to the size of the flash device (usually a power of two). Instead +of padding with 0x00 the PR allows to fill with 0xff instead. +) + +$(P +There might be also some other use-cases, where it might be reasonable to fill +the alignment gaps with some other value than 0x00, e.g. when debugging +and viewing output data in a hex editor. It is easier to spot gaps, when +the padded spaces contain a custom value like 0x55 or 0xaa. +) + +$(P +A new fill method was added, which allows filling with a user-defined value +instead of the 0 as in the previous implementation. +) + +------- +OutBuffer buf = new OutBuffer(); +buff.fill( 1234, 42 ); // Fills 1234 bytes with 42 starting at buf.offset +buff.fill( 10 ); // Same as fill0( 10 ); +------- + +$(P +The alignSize, align{2,4} methods were modified to use some user-defined +value for padding to the requested alignment boundary. +) + +------- +OutBuffer buf = new OutBuffer(); +buf.write(cast(ubyte) 1); +buf.align2(0x55); +assert(buf.toBytes() == "\x01\x55"); +buf.write(cast(ubyte) 2); +buf.align4(0x55); +assert(buf.toBytes() == "\x01\x55\x02\x55"); +buf.write(cast(ubyte) 3); +buf.alignSize(8, 0x55); +assert(buf.toBytes() == "\x01\x55\x02\x55\x03\x55\x55\x55"); +------- +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 build_unittest,Building the special test runner configuration) +$(CHANGELOG_SOURCE_FILE dub, changelog/build_unittest.dd) +$(P +`dub build --config=unittest --build=unittest[-cov]` can now be used to +mimic building the test runner executable of `dub test [--coverage]`. +Note that this doesn't require an existing `unittest` configuration. +) + +$(P +`dub describe --config=unittest` allows to derive the path to the +executable. +) +) + +$(LI $(LNAME2 colored_output,Output will now be colorized) +$(CHANGELOG_SOURCE_FILE dub, changelog/colored_output.dd) +$(P +Dub output has been improved to be more human readable, +which means the most important informations in the output +will now be colorized / bold. +) + +$(P +As is usual with CLI tools, this behavior is automatically +turned on whether the output is a TTY. To force the old output +in the presence of a TTY, use `--color=off`. To force colored +output in the absence of a TTY, use `--color=on`. +) + +$(P +The `--color` flag, if set to `on` or `off`, is automatically +forwarded to the compiler. This is especially useful for CI +pipelines to ensure human-readable output. +) +) + +$(LI $(LNAME2 configy_stricter_parsing,dub will now warn on unrecognized fields in `dub.json`, settings, or selections file) +$(CHANGELOG_SOURCE_FILE dub, changelog/configy_stricter_parsing.dd) +$(P +Previously, dub was silently accepting anything it didn't recognize +in `dub.json`, `[dub.]settings.json` and `dub.selections.json`. While the original +intent was to make forward-compatibility easy, it proved detrimental +as typos would just mean the user setting was ignored. +) + +$(P +From this release, dub will now warn about any entry in its configuration files +or in `dub.selections.json`. After 10 releases, those warnings will turn into errors. +) +) + +$(LI $(LNAME2 cov_ctfe,The two new build types `cov-ctfe` and `unittest-cov-ctfe` have been added.) +$(CHANGELOG_SOURCE_FILE dub, changelog/cov_ctfe.dd) +$(P +These extend the existing build types `cov` and `unittest-cov` respectively by +appending `-cov=ctfe` to the set of flags passed to the compiler. +) +) + +$(LI $(LNAME2 dpath,DUB settings & packages directory placement overhauled) +$(CHANGELOG_SOURCE_FILE dub, changelog/dpath.dd) +$(P +You can now configure where DUB places its downloaded packages and where the user configuration is stored through environment variables or through the dub configuration. You need to use an environment variable or the system-wide dub configuration to specify where the user configuration is stored. +) + +$(P +By default DUB stores the packages on +- Windows: `%APPDATA%/dub/settings.json` + `%LOCALAPPDATA%/dub/packages/` +- Posix: `$HOME/.dub/{packages/,settings.json}` +) + +$(P +now if the `DUB_HOME` environment variable is set it instead stores the packages (and other config) in +- `$DUB_HOME/{packages/,settings.json}` +) + +$(P +alternatively if `DUB_HOME` isn't set, but `DPATH` is set, the following path is used: +- `$DPATH/dub/{packages/,settings.json}` +) + +$(P +The `DPATH` environment variable is intended to be used by all D tooling related things doing user-space installation of things. It can be used to avoid cluttering the home folder. +) + +$(P +Additionally to environment variables it is possible to configure the package placement path + settings.json path through DUB's settings.json file. To configure where the user-editable settings.json is placed you need to adjust the system-wide dub configuration. +) + +$(P +In the settings.json you can set the following fields: +) + +```json +{ + "dubHome": "/path/to/dub", // sets both package store and config location +} +``` + +$(P +Additionally, these config paths will have environment variables using the `$VARIABLE` syntax resolved. +) + +$(P +The following list describes which path is going to be picked, from top to bottom, stopping whenever one is found: +) + +$(P +- `$DUB_HOME` environment variable +- `$DPATH` environment variable +- system-wide settings.json: `"dubHome"` property (only for userSettings) +- most specific settings.json: `"dubHome"` property (only for localRepository) +) +) + +$(LI $(LNAME2 exitcodes,DUB command exit codes have been made more consistent) +$(CHANGELOG_SOURCE_FILE dub, changelog/exitcodes.dd) +$(P +Some dub commands have been adjusted to return exit code 2 instead of exit code 1. Exit code 1 is now always used for usage errors, while exit code 2 is the more generic any error occurred or package failed to load. +) + +$(P +The following commands are affected: +) + +$(P +- dub clean +- dub add +- dub search +- dub convert +) +) + +$(LI $(LNAME2 install_uninstall,'install' and 'uninstall' commands have been removed) +$(CHANGELOG_SOURCE_FILE dub, changelog/install_uninstall.dd) +$(P +Those commands were long-deprecated aliases to `fetch` and `remove`, +respectively, and usage of them triggered a warning. +They are no longer listed as command in help and dub will no longer recognize them. +) +) + +$(LI $(LNAME2 make-copies-writable,When `copyFiles` is used to copy read-only files, it now makes the copy writable.) +$(CHANGELOG_SOURCE_FILE dub, changelog/make-copies-writable.dd) +$(P +Previously, if the target file would already exist due to a prior run of Dub, `copyFiles` would produce an access +denied error because the read-only target could not be overwritten. Note that if you were affected by this behaviour, +you will need to remove those files by hand once to eliminate these errors. +) + +$(P +It is common for version control systems to mark binary files read-only in the working copy, to prevent concurrent +edits of files in unmergeable formats. +) +) + +$(LI $(LNAME2 overrides_deprecated,The override system is deprecated) +$(CHANGELOG_SOURCE_FILE dub, changelog/overrides_deprecated.dd) +$(P +Dub had an "override" system, allowing a specific version or version range +to be overriden by a specific package. +This override system was developed with a purely version-based approach in mind, +however since its inception, more ways to specify dependencies have been added, +making the override approach redundant and less flexible than other approaches. +From this release, dub will warn you if it finds an override file, +or when using the `dub add-override` / `dub remove-override` commands. +) +) + +$(LI $(LNAME2 subpackage_short_syntax,The shortcut syntax for "dub run" is now also available for sub packages.) +$(CHANGELOG_SOURCE_FILE dub, changelog/subpackage_short_syntax.dd) +$(P +Invoking dub as "dub :subpackage" is now equivalent to "dub run :subpackage", +analogous to just "dub" being equivalent to "dub run". +) +) + +$(LI $(LNAME2 subpackage_upgrade,Upgrading all sub packages at once) +$(CHANGELOG_SOURCE_FILE dub, changelog/subpackage_upgrade.dd) +$(P +A new "-s" switch allows to "dub upgrade" all sub packages together with the +base package. This aims to provide a better workflow for fully reproducible +builds and tests. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 20809): return statement might access memory from destructed temporary) +$(LI $(BUGZILLA 21197): Wrong lifetime inference with DIP1000 in dmd 2.093.0) +$(LI $(BUGZILLA 23019): Missing filename when -of points to an existing directory) +$(LI $(BUGZILLA 23076): SIMD assert fail with -inline -O converting float to short) +$(LI $(BUGZILLA 23247): Deprecation: argument 0.0L for format specification "%La" must be double, not real) +$(LI $(BUGZILLA 23271): `goto` skips declaration of variable `bugred.A.test.__appendtmp4`) +$(LI $(BUGZILLA 23291): Members of arrays of shared classes cannot be compared) +$(LI $(BUGZILLA 23337): Wrongly elided postblit/copy ctor for array construction $(LPAREN)_d_arrayctor lowering$(RPAREN)) +$(LI $(BUGZILLA 23386): Segfault on enum member UDA inside template) +$(LI $(BUGZILLA 23431): [REG 2.101.0][ICE] Segmentation fault in Dsymbol::toParent$(LPAREN)$(RPAREN) $(LPAREN)this=0x0$(RPAREN) at dmd/dsymbol.d:561) +$(LI $(BUGZILLA 23433): [REG 2.081][ICE] Segmentation fault in dmd.blockexit.checkThrow at at src/dmd/blockexit.d:557) +$(LI $(BUGZILLA 23439): [REG 2.098] Error: CTFE internal error: literal 'assert$(LPAREN)false, "Accessed expression of type noreturn"$(RPAREN)') +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 2): Hook up new dmd command line arguments) +$(LI $(BUGZILLA 9161): Linker error on linux if struct has @disabled ~this$(LPAREN)$(RPAREN);) +$(LI $(BUGZILLA 13123): Disallow throwing contracts for nothrow functions) +$(LI $(BUGZILLA 13732): Regular templates can use "template this", and they allow any type to be passed) +$(LI $(BUGZILLA 14694): Functions nested within functions need their body in the generated .di file) +$(LI $(BUGZILLA 15525): SEGV running semantic analysis on non-root decl that has errors.) +$(LI $(BUGZILLA 16575): [ICE] extern$(LPAREN)C++$(RPAREN) function with D specific types) +$(LI $(BUGZILLA 17764): [scope][DIP1000] Escape checker defeated by composition transformations) +$(LI $(BUGZILLA 18973): @disable on const toHash causes unresolved symbol error) +$(LI $(BUGZILLA 19178): Static initialization of 2d static arrays in structs produces garbage or doesn't compile sometimes) +$(LI $(BUGZILLA 19285): false positive GC inferred) +$(LI $(BUGZILLA 20365): Copy constructor not invoked on static arrays of structs but the postblit works) +$(LI $(BUGZILLA 20823): [DIP 1000] un-@safe code fails with dip1000) +$(LI $(BUGZILLA 21314): ICE on extern$(LPAREN)c++$(RPAREN) static class variables) +$(LI $(BUGZILLA 21416): betterC mode program with C++ interface fails to link) +$(LI $(BUGZILLA 21432): [CTFE] Cannot declare enum array in function scope) +$(LI $(BUGZILLA 21477): TypeInfo errors in betterC are cryptic) +$(LI $(BUGZILLA 21676): [ICE][SIMD] DMD crashing with SIMD + optimizations + inlining) +$(LI $(BUGZILLA 21956): ice on foreach over an AA of noreturn) +$(LI $(BUGZILLA 22108): DIP1000 parameter mistakenly interpreted as return scope instead of scope) +$(LI $(BUGZILLA 22134): Deprecate returning a discarded void value from a function) +$(LI $(BUGZILLA 22351): extern$(LPAREN)C++$(RPAREN) function contravariant in D, but not C++) +$(LI $(BUGZILLA 22390): Compiler crash when iterating empty array of bottom types) +$(LI $(BUGZILLA 22429): importC: designator-list not supported yet) +$(LI $(BUGZILLA 22610): ImportC: 3 extra initializer$(LPAREN)s$(RPAREN) for struct __tag21) +$(LI $(BUGZILLA 22626): Can't use synchronized member functions with -nosharedaccess) +$(LI $(BUGZILLA 22652): importC: Braceless initializer of nested struct is rejected.) +$(LI $(BUGZILLA 22664): Disassembler mistakes rdtscp for invlpg ECX) +$(LI $(BUGZILLA 22674): ImportC: compatible types declared in different translation units are not treated equivalent in D.) +$(LI $(BUGZILLA 22680): @safe hole with destructors) +$(LI $(BUGZILLA 22706): Bad error on explicit instantiation of function template with auto ref parameter) +$(LI $(BUGZILLA 22724): ImportC: VC extension __pragma$(LPAREN)pack$(RPAREN) is not implemented) +$(LI $(BUGZILLA 22784): pragma$(LPAREN)printf$(RPAREN) applies to nested functions) +$(LI $(BUGZILLA 22865): __traits$(LPAREN)compiles$(RPAREN) affects inferrence of attributes) +$(LI $(BUGZILLA 22875): importC: cannot assign const typedef with pointers to non-const one) +$(LI $(BUGZILLA 22925): importC: multi-dimensional array is not a static and cannot have static initializer) +$(LI $(BUGZILLA 22952): Compiler fails to find package.d modules via -mv map) +$(LI $(BUGZILLA 22973): importC: sizeof with array and pointer access gives array type has incomplete element type) +$(LI $(BUGZILLA 23006): importC: dmd segfaults on static initializer for multi-dimensional array inside struct) +$(LI $(BUGZILLA 23007): importC: dmd segfaults for extra braces in array initializer) +$(LI $(BUGZILLA 23009): [CODEGEN][SIMD] SIMD + optimizations + inlining + double) +$(LI $(BUGZILLA 23010): mixed in aliaseqs used as type dont initualize) +$(LI $(BUGZILLA 23012): importC: asm label to set symbol name not applied from forward declaration) +$(LI $(BUGZILLA 23018): importC: syntax error for sizeof with postfix operator on parenthesized expression) +$(LI $(BUGZILLA 23022): [dip1000] typesafe variadic parameter should not infer return) +$(LI $(BUGZILLA 23027): ImportC: Array of struct is not a static and cannot have static initializer) +$(LI $(BUGZILLA 23030): importC: errors using typedef struct after first use as const) +$(LI $(BUGZILLA 23037): importC: type with only type-qualifier doesn't work) +$(LI $(BUGZILLA 23038): importC: sizeof inside struct has struct members in scope) +$(LI $(BUGZILLA 23039): importC: declaration with array length has itself in scope) +$(LI $(BUGZILLA 23042): -betterC still includes RTInfo) +$(LI $(BUGZILLA 23044): importC: comma expression with function call parsed as declaration) +$(LI $(BUGZILLA 23045): importC: casted function type is missing extern$(LPAREN)C$(RPAREN)) +$(LI $(BUGZILLA 23047): [ICE][SIMD] Do not SROA vector types) +$(LI $(BUGZILLA 23050): Incorrect disassembly of code with -vasm and 0xBE and 0xBF opcodes) +$(LI $(BUGZILLA 23054): importC: struct compound-literal assigned by pointer has wrong storage duration) +$(LI $(BUGZILLA 23056): importC: dmd asserts for missing return statement in CTFE function) +$(LI $(BUGZILLA 23057): importC: dmd segfault on invalid syntax) +$(LI $(BUGZILLA 23063): It is possible to return a noreturn value) +$(LI $(BUGZILLA 23068): [betterC] BetterC does not respect -checkaction=halt) +$(LI $(BUGZILLA 23073): [dip1000] scope inference from pure doesn't consider self-assignment) +$(LI $(BUGZILLA 23088): spurious case of "`expression` has no effect") +$(LI $(BUGZILLA 23105): `__trait$(LPAREN)getMember$(RPAREN)` and `mixin$(LPAREN)$(RPAREN)` of the same code as a string behave differently) +$(LI $(BUGZILLA 23112): code passes @nogc, allocates anyway) +$(LI $(BUGZILLA 23123): -vasm wrong result for cmpxchg16b) +$(LI $(BUGZILLA 23135): Covariance rules for C++ member functions mismatch D) +$(LI $(BUGZILLA 23138): Overrides of member functions of an inherited class ignores attribute "downcast") +$(LI $(BUGZILLA 23159): [betterC] scope$(LPAREN)failure$(RPAREN) use in betterC gives confusing error) +$(LI $(BUGZILLA 23167): inaccurate diagnostic for internal tuple bound violation) +$(LI $(BUGZILLA 23168): [DIP1000] return scope wrongly rewritten for structs with no indirections) +$(LI $(BUGZILLA 23169): [DIP1000] Mangling does not distinguish return and return scope) +$(LI $(BUGZILLA 23173): "Error: signed integer overflow" for compiler generated string of `long.min`) +$(LI $(BUGZILLA 23174): Can't alias tuple when it's part of dot expression following a struct literal) +$(LI $(BUGZILLA 23176): -vasm misses immediates for some SSE2 instructions) +$(LI $(BUGZILLA 23178): Unknown error using alias to `__traits` evaluated as expression) +$(LI $(BUGZILLA 23192): Can't iterate aggregate fields with static foreach inside a member function) +$(LI $(BUGZILLA 23205): Can't declare mixin template inside a function) +$(LI $(BUGZILLA 23206): ImportC: __declspec$(LPAREN)noreturn$(RPAREN) does not compile) +$(LI $(BUGZILLA 23207): dmd hangs compiling druntime/src/core/stdc/errno.c) +$(LI $(BUGZILLA 23213): ImportC - variable length array does not compile) +$(LI $(BUGZILLA 23214): ImportC: typedef with unsigned types does not compile) +$(LI $(BUGZILLA 23217): ImportC: extra initializer$(LPAREN)s$(RPAREN) error for array of structs) +$(LI $(BUGZILLA 23222): vcg-ast segfaults on aliases to parent module) +$(LI $(BUGZILLA 23223): Aliases to modules print the modules contents into ast dump) +$(LI $(BUGZILLA 23224): ImportC: memory model switch is not passed to C preprocessor) +$(LI $(BUGZILLA 23225): OpenBSD: cpp invocation cannot find files) +$(LI $(BUGZILLA 23230): cannot implicitly convert expression define of type char[7] to char) +$(LI $(BUGZILLA 23235): [DIP1000] typesafe variadic parameters should automatically be scope) +$(LI $(BUGZILLA 23236): can't initialize a @mustuse member in constructor) +$(LI $(BUGZILLA 23241): __traits getMember breaks compilation when hit an alias) +$(LI $(BUGZILLA 23249): Deprecation: argument &p for format specification "%m" must be char*, not char**) +$(LI $(BUGZILLA 23251): Deprecation: format specifier "%[a-z]" is invalid) +$(LI $(BUGZILLA 23252): Deprecation: format specifier "%[]]" is invalid) +$(LI $(BUGZILLA 23254): Deprecation: format specifier "%S" and "%C" are invalid) +$(LI $(BUGZILLA 23256): must supply -mscrtlib manually when compiling for Windows) +$(LI $(BUGZILLA 23262): typesafe variadic function parameter cannot infer return) +$(LI $(BUGZILLA 23293): ImportC: _Bool bit fields layout does not match gcc) +$(LI $(BUGZILLA 23308): Can't resolve overload of varargs function if one parameter is the result of a ternary expression) +$(LI $(BUGZILLA 23327): [ICE] SEGV in AssocArray!$(LPAREN)Identifier, Dsymbol$(RPAREN).AssocArray.opIndex$(LPAREN)const$(LPAREN)Identifier$(RPAREN)$(RPAREN) at src/dmd/root/aav.d:313) +$(LI $(BUGZILLA 23331): implicit cast from noreturn crashes compiler in various ways) +$(LI $(BUGZILLA 23338): braceless subarray initalizers for struct fields fails) +$(LI $(BUGZILLA 23340): std.path: expandTilde erroneously raises onOutOfMemory on failed getpwam_r$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 23342): ImportC: Array compound literals use the GC) +$(LI $(BUGZILLA 23343): ImportC: functions declared with asm label to set symbol name gets extra underscore prepended) +$(LI $(BUGZILLA 23345): ImportC: out of order designated initializers initialize to wrong value) +$(LI $(BUGZILLA 23346): ImportC: pragma pack is not popped) +$(LI $(BUGZILLA 23347): ImportC: pragma pack causes asm label to set symbol name to be ignored) +$(LI $(BUGZILLA 23348): not handling braceless sub structs in initializers) +$(LI $(BUGZILLA 23351): A bunch of Mayonix's dmd-segfaulting programs) +$(LI $(BUGZILLA 23355): invalid template parameter loses error location in some cases) +$(LI $(BUGZILLA 23357): ImportC: compatible types with definitions leads to redeclaration error when used from D.) +$(LI $(BUGZILLA 23368): Throwing a null exception at compile time crashes the compiler) +$(LI $(BUGZILLA 23379): Cast of expressions with type noreturn result in ice) +$(LI $(BUGZILLA 23380): [dip1000] class parameter should not be treated as ref qua lifetime) +$(LI $(BUGZILLA 23406): [seg fault] enums can cause compile time seg faults with assignments using alias this) +$(LI $(BUGZILLA 23461): dmd: src/dmd/backend/cod1.d:2037: Assertion false failed) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 7372): Error provides too little information to diagnose the problem $(LPAREN)error: undefined identifier$(RPAREN)) +$(LI $(BUGZILLA 14690): pragma$(LPAREN)inline, true$(RPAREN) functions must have their bodies emitted in the .di file) +$(LI $(BUGZILLA 16701): Remove Restriction of "package.d" Source File Module Forced to All Lowercase) +$(LI $(BUGZILLA 17575): named mixin template error message) +$(LI $(BUGZILLA 21243): Allow lambdas to return auto ref) +$(LI $(BUGZILLA 21673): [SIMD][Win64] Wrong codegen for _mm_move_ss) +$(LI $(BUGZILLA 22911): dtoh: make include directives sorted for generated headers) +$(LI $(BUGZILLA 23079): [dip1000] be more lenient when taking address of `ref` return) +$(LI $(BUGZILLA 23141): Improve -release switch description) +$(LI $(BUGZILLA 23142): Scope should not apply to unittests) +$(LI $(BUGZILLA 23143): ImportC: forward enum declarations need to be supported) +$(LI $(BUGZILLA 23165): lambda functions are not inlined) +$(LI $(BUGZILLA 23191): [dip1000] scope parameter can be returned in @system code) +$(LI $(BUGZILLA 23216): Better Error Message For foreach_reverse Without Bidirectional Range) +$(LI $(BUGZILLA 23284): Enhance floating point not representable error message) +$(LI $(BUGZILLA 23295): [dip1000] explain why scope inference failed) +$(LI $(BUGZILLA 23306): @disable new$(LPAREN)$(RPAREN) ought not disable `scope A = new A`) +$(LI $(BUGZILLA 23369): Confusing error message for duplicate import) +$(LI $(BUGZILLA 23376): Allow multi-code-point HTML entities) +$(LI $(BUGZILLA 23384): Suggest calling matching base class method when hidden) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 23245): [REG 2.099] std.format ignores non-const toString method of static array element) +$(LI $(BUGZILLA 23246): [REG 2.099] std.format ignores non-const toString method of associative array value) +$(LI $(BUGZILLA 23268): clamp no longer accepts shorts) +$(LI $(BUGZILLA 23400): [REG 2.099] Can't format enum value whose base type has non-const opEquals) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 14543): std.algorithm.searching.until does not handle range sentinels nicely) +$(LI $(BUGZILLA 16034): map should be possible with a reference only) +$(LI $(BUGZILLA 16232): std.experimental.logger.core.sharedLog isn't thread-safe) +$(LI $(BUGZILLA 18631): std.random.choice does not work with const arrays) +$(LI $(BUGZILLA 22637): std.conv `to!double` and `parse!double` dont throw on under/overflow) +$(LI $(BUGZILLA 23182): Can't assign struct with opAssign to SumType in CTFE) +$(LI $(BUGZILLA 23196): File constructor fails to preallocate oom error, uses exception instead) +$(LI $(BUGZILLA 23215): calling std.file.remove with null string segfaults in strlen) +$(LI $(BUGZILLA 23250): Unicode regional indicators are not paired correctly) +$(LI $(BUGZILLA 23270): std.random.dice is poorly documented) +$(LI $(BUGZILLA 23288): zlib: Fix potential buffer overflow) +$(LI $(BUGZILLA 23324): Incorrect source link in std.format docs) +$(LI $(BUGZILLA 23350): Nondeterministic test failure in std.concurrency) +$(LI $(BUGZILLA 23362): Permutations should be a forward range) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 13893): "rawRead must take a non-empty buffer") +$(LI $(BUGZILLA 18735): all versions of find and canfind should identify usage of predicate) +$(LI $(BUGZILLA 21000): -preview=nosharedaccess precludes use of stdin,stdout,stderr) +$(LI $(BUGZILLA 23101): [std.sumtype] canMatch does not account ref) +$(LI $(BUGZILLA 23298): std.string wrap wraps early) +$(LI $(BUGZILLA 23333): DList range can be @nogc) +$(LI $(BUGZILLA 23370): std.base64 can have more @nogc functions) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 15939): GC.collect causes deadlock in multi-threaded environment) +$(LI $(BUGZILLA 23060): MacOS: core.sys.posix.sys.socket missing some definitions) +$(LI $(BUGZILLA 23065): importC: __builtin_expect should use c_long) +$(LI $(BUGZILLA 23067): importC: offsetof macro assumes size_t is defined) +$(LI $(BUGZILLA 23129): object.destroy doesn't consider initialize=false on D classes) +$(LI $(BUGZILLA 23228): OpenBSD: No SIGRTMIN or SIGRTMAX) +$(LI $(BUGZILLA 23302): std.algorithm.comparison.predSwitch producing SwitchError with error message as the filename) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 23456): OpenBSD: Add waitid support) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 14542): Table of contents in specification PDF is broken) +$(LI $(BUGZILLA 15379): "final" attribute on function parameter) +$(LI $(BUGZILLA 15476): DDOC_UNDEFINED_MACRO is undocumented) +$(LI $(BUGZILLA 17324): Floating point 1/$(LPAREN)1/x$(RPAREN) > 0 if x > 0 not generally true) +$(LI $(BUGZILLA 17514): "positive" -> "nonnegative") +$(LI $(BUGZILLA 17623): Unexpected failure of an assertion on empty strings) +$(LI $(BUGZILLA 18496): Complement expressions now actually int promote) +$(LI $(BUGZILLA 18855): Behavior of Anonymous Union is Undocumented) +$(LI $(BUGZILLA 18887): inout badly described) +$(LI $(BUGZILLA 19869): `FunctionLiteral` allows incorrect forms) +$(LI $(BUGZILLA 21188): Anonymous structs - not described) +$(LI $(BUGZILLA 21279): cast expression between integer types is not defined) +$(LI $(BUGZILLA 21781): [Oh No! Page Not Found] Links to core libs from Better C) +$(LI $(BUGZILLA 22237): AA.update is underspecified) +$(LI $(BUGZILLA 22835): Undocumented type specializations of is-expression) +$(LI $(BUGZILLA 23062): Function/delegate inference example does not compile) +$(LI $(BUGZILLA 23194): Add our company to the list of D firms) +$(LI $(BUGZILLA 23237): dmd 2.100.1 download link error.) +$(LI $(BUGZILLA 23276): DOC: ">" instead of ">" in dmd-windows.html) +$(LI $(BUGZILLA 23296): Value Range Propagation not documented) +$(LI $(BUGZILLA 23314): Language spec falsely states that struct field invariants are checked) +$(LI $(BUGZILLA 23325): Assigning dynamic array to static array not documented) +$(LI $(BUGZILLA 23358): Link unusable due to space insertion) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 15286): is$(LPAREN)typeof$(LPAREN)symbol$(RPAREN)$(RPAREN)) +$(LI $(BUGZILLA 19036): .tupleof order guarantee) +$(LI $(BUGZILLA 22141): Property .capacity is not listed in the array properties section) +$(LI $(BUGZILLA 23186): wchar/dchar do not have their endianess defined) +$(LI $(BUGZILLA 23359): Rename InOut to ParameterStorageClass) +) +) +$(D_CONTRIBUTORS_HEADER 72) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR Adela Vais) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Andrea Fontana) + $(D_CONTRIBUTOR Andrej Mitrovic) + $(D_CONTRIBUTOR Ast-x64) + $(D_CONTRIBUTOR Ate Eskola) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR bistcuite) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Brian Callahan) + $(D_CONTRIBUTOR Carsten Schlote) + $(D_CONTRIBUTOR chloekek) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR drpriver) + $(D_CONTRIBUTOR Elias Batek) + $(D_CONTRIBUTOR Emanuele Torre) + $(D_CONTRIBUTOR Etienne Brateau) + $(D_CONTRIBUTOR etienne02) + $(D_CONTRIBUTOR Grim Maple) + $(D_CONTRIBUTOR hatf0) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR human) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR ichordev) + $(D_CONTRIBUTOR Ilya Yaroshenko) + $(D_CONTRIBUTOR Iulia Dumitru) + $(D_CONTRIBUTOR james) + $(D_CONTRIBUTOR Jan Jurzitza) + $(D_CONTRIBUTOR Jasmine Hegman) + $(D_CONTRIBUTOR Joe) + $(D_CONTRIBUTOR João Lourenço) + $(D_CONTRIBUTOR Lucian Danescu) + $(D_CONTRIBUTOR lucica28) + $(D_CONTRIBUTOR Luís Ferreira) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Martin Nowak) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Max Haughton) + $(D_CONTRIBUTOR mhh) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR MoonlightSentinel) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Quirin F. Schroll) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Robert burner Schadek) + $(D_CONTRIBUTOR Roy Margalit) + $(D_CONTRIBUTOR ryuukk) + $(D_CONTRIBUTOR Sebastiaan Koppe) + $(D_CONTRIBUTOR Stefan Rohe) + $(D_CONTRIBUTOR Steven Dwy) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Su) + $(D_CONTRIBUTOR Teodor Dutu) + $(D_CONTRIBUTOR the-horo) + $(D_CONTRIBUTOR TheGag96) + $(D_CONTRIBUTOR Tim Schendekehl) + $(D_CONTRIBUTOR tynuk) + $(D_CONTRIBUTOR vali0901) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR wolframw) + $(D_CONTRIBUTOR yori) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.101.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.101.1.dd b/changelog/2.101.1.dd new file mode 100644 index 0000000000..9aa84db767 --- /dev/null +++ b/changelog/2.101.1.dd @@ -0,0 +1,62 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Dec 15, 2022, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 11 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 11 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 23490): DMD creating corrupted vtable) +$(LI $(BUGZILLA 23497): Erroneous escape reference to parameter error.) +$(LI $(BUGZILLA 23532): Missing type properties for complex special enum types) +$(LI $(BUGZILLA 23549): assert$(LPAREN)0$(RPAREN) as default parameter causes segfault) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 22587): ternary with function call and assert$(LPAREN)0$(RPAREN) leads to cod1 assertion) +$(LI $(BUGZILLA 23481): [inf loop] usertype enums opOpAssign cause an compile time infinite loop) +$(LI $(BUGZILLA 23516): Anonymous enum without base type causes segfault inferring member value) +$(LI $(BUGZILLA 23529): [ICE] Compiler segfaults on static array cast) +$(LI $(BUGZILLA 23533): Segmentation fault accessing enum.max with -preview=nosharedaccess) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 22745): std.parallelism.parallel fails to process empty range on a single CPU) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 23498): OpenBSD: Fix core.sys.posix.sys.wait) +) +) +$(D_CONTRIBUTORS_HEADER 11) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Brian Callahan) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR mhh) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Stefan Koch) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.101.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.101.2.dd b/changelog/2.101.2.dd new file mode 100644 index 0000000000..a57fdbd1e2 --- /dev/null +++ b/changelog/2.101.2.dd @@ -0,0 +1,53 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 01, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 16 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 3 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 18646): [REG 2.079.0] Recursive template expansion incorrectly reported) +$(LI $(BUGZILLA 20811): Regression as of 2.066.0 - CTFE static variable retained across calls) +$(LI $(BUGZILLA 22638): [REG 2.096][ICE] cod4.d: Assertion cast$(LPAREN)int$(RPAREN)sz > 0 failed) +$(LI $(BUGZILLA 22646): [REG2.099] CT bounds checking ignores short circuit evaluation) +$(LI $(BUGZILLA 22813): [REG 2.079.1] recursive template expansion) +$(LI $(BUGZILLA 22854): static foreach byCodepoint segfault $(LPAREN)2.099-rc.1$(RPAREN)) +$(LI $(BUGZILLA 22975): 3 cyclic aliases with meaningful overloads not caught [ice]) +$(LI $(BUGZILLA 23391): [Reg 2.098.1] Segmentation fault with static foreach + range + inout) +$(LI $(BUGZILLA 23499): inliner crashes/asserts when building for 32-bit) +$(LI $(BUGZILLA 23564): [REG 2.099.0] SIGSEGV during compilation) +$(LI $(BUGZILLA 23567): pragma$(LPAREN)printf$(RPAREN) messes up with the vtable of extern$(LPAREN)C++$(RPAREN) classes) +$(LI $(BUGZILLA 23589): [REG2.095] Purity check special case gives circular reference error.) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 14907): DMD crash when using template name as a default value of template's typed argument) +$(LI $(BUGZILLA 19585): Invalid recursive template expansion error) +$(LI $(BUGZILLA 23151): ICE: core.exception.AssertError@src/dmd/aggregate.d$(LPAREN)678$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 23574): ICE: AssertError@src/dmd/optimize.d$(LPAREN)866$(RPAREN): Assertion failure) +) +) +$(D_CONTRIBUTORS_HEADER 3) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.101.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.102.0.dd b/changelog/2.102.0.dd new file mode 100644 index 0000000000..32583796e9 --- /dev/null +++ b/changelog/2.102.0.dd @@ -0,0 +1,630 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 01, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 15 major changes and 75 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 40 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.deprecate-duplicate-system-implementations,A missed case of conflicting `extern (D) @system` function definitions has been deprecated)) +$(LI $(RELATIVE_LINK2 dmd.deprecate-getAttributes-overloadSet,Deprecate the ability to call `__traits(getAttributes)` on overload sets)) +$(LI $(RELATIVE_LINK2 dmd.for-increment,Deprecate non-empty `for` statement *Increment* clause with no effect)) +$(LI $(RELATIVE_LINK2 dmd.scope-array-on-stack,Array literals assigned to `scope` array variables can now be allocated on the stack)) +$(LI $(RELATIVE_LINK2 dmd.static-assert,`static assert` now supports multiple message arguments)) +$(LI $(RELATIVE_LINK2 dmd.system-variables,`-preview=systemVariables` has been added)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 druntime.nogc-traceinfo,The default `Throwable.TraceInfo` generation now is `@nogc`.)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 log_float_double_implementations,Single- and double-precision implementations for log function families)) +$(LI $(RELATIVE_LINK2 unicode_properties_c,The Unicode property "C" aka "Other" has had the wrong properties associated with it.)) +$(LI $(RELATIVE_LINK2 unicode_table_generator,Unicode table generator is now in Phobos, tables are updated to version 15.)) +$(LI $(RELATIVE_LINK2 unique-struct-dtor,`std.typecons.Unique` now calls `destroy` on struct types)) + +) + +$(BUGSTITLE_TEXT_HEADER Installer changes, + +$(LI $(RELATIVE_LINK2 VisualDUpdate,Update the bundled VisualD package)) +$(LI $(RELATIVE_LINK2 issue_23623,Prefer 64 bit over 32 bit DMD on Windows 64 bit.)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 build-cache,Binary output will now be in a central cache)) +$(LI $(RELATIVE_LINK2 metadata-cache,DUB API breaking change: `Package.metadataCache` setter and getter have been removed)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.deprecate-duplicate-system-implementations,A missed case of conflicting `extern (D) @system` function definitions has been deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecate-duplicate-system-implementations.dd) +$(P +Having multiple definitions of functions within a module had been turned +$(LINK2 $(ROOT_DIR)/changelog/2.095.0.html#duplicate-implementations-deprecation, +into an error in DMD 2.095.0). +) + +$(P +However, the compiler would not issue an error when two implementations +differed by an explicit and inferred `@system` attribute, although they have +the same mangling. +) + +--- +void foo() {} +void foo() @system {} // no error +--- + +$(P +This bug has been fixed, and DMD will now issue a deprecation if there are such +conflicting `@system` function implementations. Starting from DMD 2.112, it +will produce a multiple definition error just like other kinds of conflicting +functions within a module. +) +) + +$(LI $(LNAME2 dmd.deprecate-getAttributes-overloadSet,Deprecate the ability to call `__traits(getAttributes)` on overload sets) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecate-getAttributes-overloadSet.dd) +$(P +Up until this release, `__traits(getAttributes)` could be called both on +individual functions and on overload sets. However, in the latter case, +the compiler simply collected the user defined attributes for the first +lexically defined function. This behavior is error prone. Consider: +) + +```d +module test; + +@("gigi") +void fun() {} +@("mimi") +void fun(int) {} + +void main() +{ + static foreach(attr; __traits(getAttributes, fun)) + pragma(msg, attr); +``` + +$(P +The above code will print "gigi" although there is no indication on +what overload is actually queried. The first one is always picked. +) + +$(P +Starting with this release, this sort of usage of `__traits(getAttributes)` +is deprecated. If a specific overload needs to be handled, `__traits(getOverloads)` +may be used in conjunction with `__traits(getAttributes)` for proper behavior: +) + +```d +module test; + +@("gigi") +void fun() {} +@("mimi") +void fun(int) {} + +void main() +{ + static foreach (t; __traits(getOverloads, test, "fun")) + static foreach(attr; __traits(getAttributes, t)) + pragma(msg, attr); +``` + +$(P +The above code prints: +) + +``` +gigi +mimi +``` +) + +$(LI $(LNAME2 dmd.for-increment,Deprecate non-empty `for` statement *Increment* clause with no effect) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.for-increment.dd) +$(P +The $(DDSUBLINK spec/statement, for-statement, last clause of a `for` statement) +should not produce a value without also having some meaningful +side-effect. This is now detected with a deprecation message. The +following `for` statements each trigger the deprecation: +) + +--- +// evaluating `j` has no side-effects +int j; +for (;; j) {...} + +// unnecessary dereference +for (ubyte* sp;; *sp++) {...} + +// first clause is a block statement +// last clause is a function literal, not a block statement +for({j = 2; int d = 3;} j + d < 7; {j++; d++;}) {...} +--- + +$(P +Note: Calling a function returning `void` is *not* deprecated even if the +function does nothing. This is for generic code. +) +) + +$(LI $(LNAME2 dmd.scope-array-on-stack,Array literals assigned to `scope` array variables can now be allocated on the stack) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.scope-array-on-stack.dd) +$(P +Formerly, they were always allocated with the Garbage Collector, making it unavailable in `@nogc` or `-betterC` code. +This led to frequent use of the following workaround: +) + +--- +void main() @nogc +{ + int[3] buffer = [10, 20, 30]; + int[] arr = buffer[]; +} +--- + +$(P +This can now be written in a single line: +) + +--- +void main() @nogc +{ + scope int[] arr = [10, 20, 30]; +} +--- + +$(P +With the following limitations: +- The variable must be explicitly annotated `scope`, not just inferred `scope` +- The `-preview=dip1000` must be passed, to prevent introducing memory corruption in legacy code. +Note that in `@system` and `@trusted` code, the compiler doesn't verify that your `scope` variable doesn't escape. +- The array literal must be initializing the variable. Subsequent array literals assignments still use the GC. +- The array elements may not have a destructor +) + +$(P +Some of these limitations might get lifted in the future. +) +) + +$(LI $(LNAME2 dmd.static-assert,`static assert` now supports multiple message arguments) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.static-assert.dd) +$(P +When the condition evaluates to false, any subsequent expressions will +each be converted to string and then concatenated. The resulting string +will be printed out along with the error diagnostic. +) +--- +enum e = 3; +static assert(false, "a = ", e); +--- +$(P +Will print: +$(CONSOLE +file.d(2): Error: static assert: a = 3 +) +) +) + +$(LI $(LNAME2 dmd.system-variables,`-preview=systemVariables` has been added) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.system-variables.dd) +$(P +Since [DIP 1035 - System Variables](http://dlang.org/dips/1035) has been accepted, variables marked `@system` may no longer be accessed from `@safe` code. +To avoid code breakage, the compiler will start with emitting deprecation warnings. +The preview switch will turn these into errors, and it will be enabled by default in a future release. +) + +--- +@system int* p; + +struct S +{ + @system int i; +} + +void main() @safe +{ + int x = *p; // error with `-preview=systemVariables`, deprecation otherwise + + S s; + s.i = 0; // ditto +} +--- + +$(P +Note that currently this is limited to variables explicitly marked `@system`, inference of `@system` based on a variable's initializer is yet to be implemented. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 druntime.nogc-traceinfo,The default `Throwable.TraceInfo` generation now is `@nogc`.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.nogc-traceinfo.dd) +$(P +The way this works: +) + +$(P +1. The runtime now has 2 trace-related functions, one for allocating a traceinfo, and one for deallocating the traceinfo. Both are set via the same `Runtime.traceHandler` function. The second parameter that sets the deallocation function is optional (so existing code will not be affected). +2. When a `Throwable` is thrown, if the trace info is not yet set, the runtime uses the designated function to allocate a trace info. If the deallocation function is non-null, the function pointer is copied into the `Throwable`, into the new member `infoDeallocator`. +3. When the `Throwable` is destroyed, if the `infoDeallocator` member is set, it is called on the `info` member. +) + +$(P +The default allocator and deallocator now uses C malloc and free to allocate and deallocate the `TraceInfo`. Almost everything was already nogc, *except* for the allocation of the `TraceInfo` object itself. +) + +$(P +The benefits: +) + +$(P +1. Stack traces can now be generated when run inside the GC collection routine. +2. InvalidMemoryOperationError now has a stack trace. +3. Little known is that even inside `@nogc` functions, throwing a `Throwable` actually was using the GC, that is no longer the case (by default). +4. Certain GC hangs have been fixed (see bug fixes listed below). +) + +$(P +One possible drawback is that the `TraceInfo` is deallocated upon `Throwable` being finalized, leading to a potential dangling pointer situation. If you do copy the `info` out of the `Throwable`, makes sure to not keep it beyond the lifetime of the `Throwable`, or make sure to set the `infoDeallocator` member to null. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 log_float_double_implementations,Single- and double-precision implementations for log function families) +$(CHANGELOG_SOURCE_FILE phobos, changelog/log_float_double_implementations.dd) +$(P +New `float` and `double` overloads of $(REF log, std, math, exponential), +$(REF log10, std, math, exponential), $(REF log1p, std, math, exponential), + $(REF log2, std, math, exponential), and $(REF logb, std, math, exponential) +have been added to Phobos with proper 'software' implementations in the +corresponding precision. Furthermore, $(REF logb, std, math, exponential) is +now `pure`. +) + +$(P +While this may result in a slowdown in some cases for DMD, the overall speed-up +factor for GDC and LDC is over 3x, for both `double` and `float`. +) + +$(P +This also implies less precise results, especially in single-precision, +so if your code depended on more accurate results via 80-bit intermediate +precision, you'll have to cast the argument(s) explicitly now. +) +) + +$(LI $(LNAME2 unicode_properties_c,The Unicode property "C" aka "Other" has had the wrong properties associated with it.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/unicode_properties_c.dd) +$(P +If you use `unicode.c` or `unicode.Other` (case insensitive) from `std.uni`, you should mitigate or fix your codebase. +) + +$(P +This change makes it match the [Unicode Techical Report #44](https://www.unicode.org/reports/tr44/). Unfortunately if you are already using it with its previous wrong values, this will break your code, below is a function which reflects the original values that you can use to mitigate against any breakage. +) + +--- +@property auto loadPropertyOriginal(string name)() pure +{ + import std.uni : unicode; + + static if (name == "C" || name == "c" || name == "other" || name == "Other") + { + auto target = unicode.Co; + target |= unicode.Lo; + target |= unicode.No; + target |= unicode.So; + target |= unicode.Po; + return target; + } + else + return unicode.opDispatch!name; +} +--- +) + +$(LI $(LNAME2 unicode_table_generator,Unicode table generator is now in Phobos, tables are updated to version 15.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/unicode_table_generator.dd) +$(P +It is likely that this change will result in breakage in code and program usage. +This is due to a number of factors, the tables being updated so significantly and the table generator not having all its changes commited throughout the years. +) +) + +$(LI $(LNAME2 unique-struct-dtor,`std.typecons.Unique` now calls `destroy` on struct types) +$(CHANGELOG_SOURCE_FILE phobos, changelog/unique-struct-dtor.dd) +$(P +When Unique goes out of scope, any destructor will now be called. +Previously the destructor was not called then. +) + +$(P +$(RUNNABLE_EXAMPLE +) +--- +static int i; + +struct S +{ + ~this() + { + i++; + } +} +{ + Unique!S u = new S; + // S.~this now called here +} +assert(i == 1); +--- +$(P +) +) + +$(P +$(B Note:) Above, the struct destructor will also be called by the GC just +before the memory for `new S` is reclaimed. Take care that any struct +destructor used will handle being called again on the struct `.init` +value. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Installer changes, + +$(LI $(LNAME2 VisualDUpdate,Update the bundled VisualD package) +$(CHANGELOG_SOURCE_FILE installer, changelog/VisualDUpdate.dd) +$(P +The $(LINK2 https://rainers.github.io/visuald/visuald/StartPage.html, VisualD) package version +that the installer downloads hasn't been updated in years. This has been remedied by a version +bump to 1.3.1, the latest release of VisualD. +) +) + +$(LI $(LNAME2 issue_23623,Prefer 64 bit over 32 bit DMD on Windows 64 bit.) +$(CHANGELOG_SOURCE_FILE installer, changelog/issue_23623.dd) +$(P +The NSIS installer for Windows has the option "Add to PATH". Previously, only +the 32 bit version of DMD was added to the PATH environment variable. Now, on +Windows 64 bit, the 64 bit version of DMD will be selected from PATH. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 build-cache,Binary output will now be in a central cache) +$(CHANGELOG_SOURCE_FILE dub, changelog/build-cache.dd) +$(P +Up until now, dub would output build artifact in the package directory. +) + +$(P +This allowed reuse of build artifact for dependencies, but also created +issues with large amount of build artifacts in the packages folder, +preventing the use of read-only location to store packages, +and making garbage collection of build artifacts unreliable. +) + +$(P +Starting from this version, build artifacts will be output by default to +`$HOME/.dub/cache/build/$BASE_PACKAGE_NAME/$PACKAGE_VERSION/[+$SUB_PACKAGE_NAME]` +on Linux, and +`%APPDATA%/cache/build/$BASE_PACKAGE_NAME/$PACKAGE_VERSION/[+$SUB_PACKAGE_NAME]` +on Windows. +) +) + +$(LI $(LNAME2 metadata-cache,DUB API breaking change: `Package.metadataCache` setter and getter have been removed) +$(CHANGELOG_SOURCE_FILE dub, changelog/metadata-cache.dd) +$(P +Those two functions were used to provide access to the metadata cache file +to the generator. They were never intended for public consumption, +and the JSON file format was not stable. +) + +$(P +Due to the introduction of the build cache, they needed to be removed, +as there was no way to provide a sensible transition path, and they should be unused. +If you have a use case for it, please open an issue in dub repository. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 19268): BetterC turns off .dup for CTFE) +$(LI $(BUGZILLA 20520): Runtime segfault when taking typeid of a class instanciated within an enum) +$(LI $(BUGZILLA 21301): Wrong values being passed in long parameter list) +$(LI $(BUGZILLA 23307): [REG][CODEGEN][SIMD] wrong codegen with inlined local functions + SIMD) +$(LI $(BUGZILLA 23539): [REG master] Scope C++ definition out of sync with D) +$(LI $(BUGZILLA 23548): [REG 2.098] C sources files have precedent over D modules in imports) +$(LI $(BUGZILLA 23569): [REG 2.081][ICE] Segmentation fault in in AggregateDeclaration::getType$(LPAREN)$(RPAREN) $(LPAREN)this=0x0$(RPAREN) at src/dmd/aggregate.d:594) +$(LI $(BUGZILLA 23587): cast$(LPAREN)void$(RPAREN) doesn't work for noreturn) +$(LI $(BUGZILLA 23591): [REG 2.101] Invalid casts accepted by the compiler if from type is noreturn) +$(LI $(BUGZILLA 23607): invalid code leading to an ICE due to an error message that's not emitted anymore) +$(LI $(BUGZILLA 23626): [REG2.096] Template deduction with auto const ref Args... and delegate) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 13060): @nogc reading an associative array) +$(LI $(BUGZILLA 15414): __traits$(LPAREN)getAttributes$(RPAREN) should error if the function has multiple overloads) +$(LI $(BUGZILLA 15712): extern$(LPAREN)C$(RPAREN) attribute inside extern$(LPAREN)C$(RPAREN) unittest is incorrectly ignored) +$(LI $(BUGZILLA 18026): Stack overflow in ddmd/dtemplate.d:6241, TemplateInstance::needsCodegen$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 19623): HERE string identifier cannot start with Unicode letter) +$(LI $(BUGZILLA 19649): Misleading error message for duplicate constraints) +$(LI $(BUGZILLA 21062): Confusing error when using a keyword as an identifier for a declaration) +$(LI $(BUGZILLA 21506): misalignment of _argptr for variadic functions) +$(LI $(BUGZILLA 21613): DMD crash: copy ctor + templated rvalue ctor) +$(LI $(BUGZILLA 22759): ImportC: cannot modify const expression from dereferencing const pointer declared within function.) +$(LI $(BUGZILLA 23122): enum member UDAs semantics are not checked properly) +$(LI $(BUGZILLA 23218): ICE: src/dmd/backend/cgxmm.d:1373: Assertion `0' failed.) +$(LI $(BUGZILLA 23412): void init member detection does not account for static arrays) +$(LI $(BUGZILLA 23418): double argument is passed on stack, but assumed to be in XMM0 register) +$(LI $(BUGZILLA 23447): wrong expression in error message when template instance doesn't match any overload) +$(LI $(BUGZILLA 23462): dmd: src/dmd/backend/cod2.d:2158: Assertion cast$(LPAREN)int$(RPAREN)tysize$(LPAREN)$(LPAREN)*e$(RPAREN).Ety$(RPAREN) <= REGSIZE$(LPAREN)$(RPAREN) failed) +$(LI $(BUGZILLA 23463): Don't count skipped function overloads when limiting overloads shown) +$(LI $(BUGZILLA 23465): Invalid token error points to wrong line) +$(LI $(BUGZILLA 23470): Backticks in diagnostic are confusing with wrong number of arguments passed) +$(LI $(BUGZILLA 23491): Nonsensical deprecation message when using delegate) +$(LI $(BUGZILLA 23531): [DIP1000] scope variable can be assigned as AA key) +$(LI $(BUGZILLA 23534): __traits$(LPAREN)isZeroInit$(RPAREN) is true for enums with explicit values) +$(LI $(BUGZILLA 23536): crt_constructors and crt_destructors should not be non-static member functions) +$(LI $(BUGZILLA 23568): Error: cannot implicitly convert expression 'a < b' of type 'float4' to 'int4') +$(LI $(BUGZILLA 23578): Types are not matched to alias parameters in "is" expression) +$(LI $(BUGZILLA 23586): DMD forgets a variable was just declared.) +$(LI $(BUGZILLA 23593): core.thread: suspendAll doesn't wait for all if current thread has detached itself) +$(LI $(BUGZILLA 23614): ImportC: __int128 not supported) +$(LI $(BUGZILLA 23618): Right Shift equals expressions on unsigned shorts should be unsigned right shift) +$(LI $(BUGZILLA 23620): 'alias this' is not respected in static array length position) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 9848): Better diagnostic when type declaration was not expected) +$(LI $(BUGZILLA 15368): Improve error message for "auto" keyword inside "foreach") +$(LI $(BUGZILLA 21338): Confusing error message for template overload resolution failure) +$(LI $(BUGZILLA 22306): scope array variable should be stack allocated) +$(LI $(BUGZILLA 23410): ImportC: binary constants not allowed) +$(LI $(BUGZILLA 23424): improve error when template instantiation doesn't match any overload) +$(LI $(BUGZILLA 23458): No template candidates listed when OverDeclaration or OverloadSet don't match) +$(LI $(BUGZILLA 23466): -verrors=context should not repeat same context for supplemental messages) +$(LI $(BUGZILLA 23480): non-empty ForStatement Increment clause should require a side effect) +$(LI $(BUGZILLA 23552): Function `x` does not override any function, but it actually does) +$(LI $(BUGZILLA 23566): ImportC: __PRETTY_FUNCTION__ is not defined) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 23319): std.range.Generator does not work with non-mutable elements) +$(LI $(BUGZILLA 23488): std.format.sformat mishandles char ranges) +$(LI $(BUGZILLA 23507): Socket.blocking property incorrect on new Socket on Windows) +$(LI $(BUGZILLA 23540): std.uni loadProperty aliases for C are incorrect) +$(LI $(BUGZILLA 23561): std.typecons.Unique!struct does not destroy struct instance) +$(LI $(BUGZILLA 23640): Nullable range iteration doesn't work with immutable values) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 19737): [std.experimental.allocator] link table in docs has missing symbols) +$(LI $(BUGZILLA 23453): Generic iota should be a forward range) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 22616): Infinity loop instead of InvalidMemoryOperationError during GC routine) +$(LI $(BUGZILLA 23562): [REG master] Segmentation fault in core.demangle) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 16641): Infinite loop on InvalidMemoryOperationError in __dmd_personality_v0) +$(LI $(BUGZILLA 19467): Support EV_SET on OSX) +$(LI $(BUGZILLA 23572): OpenBSD: Add OpenBSD to the RTLD_DEFAULT list) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 20650): Cryptic error message when GC called in finalizer) +$(LI $(BUGZILLA 23332): core.sync.condition notify methods should be @nogc) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 23382): Non-template requirement for copy constructors is undocumented) +$(LI $(BUGZILLA 23436): Spec falsely states mutable references in struct .init are forbidden) +$(LI $(BUGZILLA 23541): [ImportC] dlang.org contains incorrect links) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 23426): Example Run button shows wrong line numbers for errors) +$(LI $(BUGZILLA 23432): document when array capacity is zero and capacity performance) +$(LI $(BUGZILLA 23511): Incrementing a not supported type in enum) +$(LI $(BUGZILLA 23553): opCmp spec is incomplete) +) +$(BUGSTITLE_BUGZILLA Installer bug fixes, + +$(LI $(BUGZILLA 23623): On 64 bit Windows the path should point to 64 bit dmd.) +) +) +$(D_CONTRIBUTORS_HEADER 40) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR aG0aep6G) + $(D_CONTRIBUTOR Amaury) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Brian Callahan) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR fn ⌃ ⌥) + $(D_CONTRIBUTOR Gabriel Dolberg) + $(D_CONTRIBUTOR Garrett D'Amore) + $(D_CONTRIBUTOR H. S. Teoh) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jan Jurzitza) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR Jordi Sayol) + $(D_CONTRIBUTOR Loren Burkholder) + $(D_CONTRIBUTOR Lucian Danescu) + $(D_CONTRIBUTOR lucica28) + $(D_CONTRIBUTOR Luís Ferreira) + $(D_CONTRIBUTOR Marcelo Silva Nascimento Mancini) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Max Haughton) + $(D_CONTRIBUTOR mhh) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Quirin F. Schroll) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR richard (rikki) andrew cattermole) + $(D_CONTRIBUTOR RJ Nowling) + $(D_CONTRIBUTOR Stefan Koch) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR Ömer Faruk IRMAK) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.102.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.102.1.dd b/changelog/2.102.1.dd new file mode 100644 index 0000000000..015a5d4949 --- /dev/null +++ b/changelog/2.102.1.dd @@ -0,0 +1,94 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 15, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 2 major changes and 6 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 6 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 cwd-fix,Reverted v1.31.0 working directory change when using `dub run --root=`)) +$(LI $(RELATIVE_LINK2 path-dep-fix,Path dependencies of path-based sub-packages have been fixed)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 cwd-fix,Reverted v1.31.0 working directory change when using `dub run --root=`) +$(CHANGELOG_SOURCE_FILE dub, changelog/cwd-fix.dd) +$(P +DUB < v1.31.0 would run applications in the working directory it was invoked in, +ignoring the `--root` argument. +) + +$(P +In v1.31.0, `dub` started to respect the `--root` argument and run programs in +the requested directory. +) + +$(P +While sometimes desirable, this change was not intended, and has now been +reverted. To restore the 1.31.0 behaivor, set `"workingDirectory"` to `"."` in +the dub.json/dub.sdl file. This works both with older DUB versions and with +future DUB versions. +) +) + +$(LI $(LNAME2 path-dep-fix,Path dependencies of path-based sub-packages have been fixed) +$(CHANGELOG_SOURCE_FILE dub, changelog/path-dep-fix.dd) +$(P +Path-based dependencies in path-based sub-packages in DUB v1.30.0 and 1.31.0 +have had regressed and didn't resolve properly. (dub.selections.json could be +used to workaround this issue before) +) + +$(P +From this release, these resolve properly again. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 23674): incompatible types for array comparison: string and string) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 23662): ImportC bad handling of enum arguments for a function) +$(LI $(BUGZILLA 23672): importC: Infinite recursion: Error: found 'End of File' when expecting ',') +$(LI $(BUGZILLA 23679): off-by-one error for static array size limit) +$(LI $(BUGZILLA 23705): dmd: src/dmd/backend/cgcod.d:734: Assertion `sz >= 0' failed.) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 23668): Can't stable sort structs with disabled default constructor.) +) +) +$(D_CONTRIBUTORS_HEADER 6) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dmytro Katyukha) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Razvan Nitu) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.102.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.102.2.dd b/changelog/2.102.2.dd new file mode 100644 index 0000000000..7ee6ce420d --- /dev/null +++ b/changelog/2.102.2.dd @@ -0,0 +1,54 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 01, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 6 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 8 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 23732): Cannot create shared instance of class with -preview=nosharedaccess) +$(LI $(BUGZILLA 23745): Segfault with forward reference mismatched override with undeclared type) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 23514): Incorrect compilation when adding a 64-bit constant to a link-time address) +$(LI $(BUGZILLA 23743): wrong code with `foreach`, `ubyte`, `>=`, ternary operator) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 23750): log1p for floats/doubles not actually providing extra accuracy) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 23608): [musl 32-bit] Time functions linked incorrectly on musl >=1.2.0 / 32-bit) +) +) +$(D_CONTRIBUTORS_HEADER 8) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR richard (rikki) andrew cattermole) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Zachary Yedidia) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.102.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.103.0.dd b/changelog/2.103.0.dd new file mode 100644 index 0000000000..691e7061b9 --- /dev/null +++ b/changelog/2.103.0.dd @@ -0,0 +1,356 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 01, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 9 major changes and 83 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 43 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.check,Add __check(assign-expression) to ImportC)) +$(LI $(RELATIVE_LINK2 dmd.deprecate-alias-this-for-classes,Alias this for classes is deprecated)) +$(LI $(RELATIVE_LINK2 dmd.dip25-default,`-preview=dip25` has been enabled by default)) +$(LI $(RELATIVE_LINK2 dmd.extern-dllimport,export int a; now generates dllexport instead of dllimport)) +$(LI $(RELATIVE_LINK2 dmd.get-is-virtual-function,Deprecate `traits(isVirtualFunction)` and `traits(getVirtualFunctions)`)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 grapheme_walker_update,Unicode grapheme walking updated to conform to Unicode version 15)) +$(LI $(RELATIVE_LINK2 joiner_assert_message,Better static assert messages for `std.algorithm.iteration.joiner`)) +$(LI $(RELATIVE_LINK2 sort_assert_messaged,Better static assert messages for `std.algorithm.sorting.sort`)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 colors,The `--color` argument now accepts values `auto`, `never`, `always`)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.check,Add __check(assign-expression) to ImportC) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.check.dd) +$(P +C code normally relies on `#include ` to add support for assert's. D has them builtin to the +language, which is much more convenient and does not rely on a preprocessor. This extension adds +) + +--- +__check(assign-expression) +--- + +$(P +as an expression to ImportC. The compiler switch -checkaction=C gives it the same behavior +as C's assert macro. If the compiler switch -release is thrown, the `__check`'s are ignored. +The `__check` expressions are handy for writing C programs that are free of reliance on `#include`. +) + +$(P +`__assert` is not used due to conflicts with some C .h files. +) +) + +$(LI $(LNAME2 dmd.deprecate-alias-this-for-classes,Alias this for classes is deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecate-alias-this-for-classes.dd) +$(P +Using `alias this` for classes has not been clearly specified and the lookup rules in such circumstances are not defined. As a consequence, various failures or crashes may appear when `alias this` is used in conjunction with classes. Starting with this release, `alias this` for classes is being deprecated. As an alternative, getter/setter methods may be used to replace the `alias this`. This can be generically handled by: +) + +```d +static foreach(member, __traits(allMembers, LeClass)) + mixin("ref auto " ~ member() { return $field_name." ~ member ~ "; }"); +``` +) + +$(LI $(LNAME2 dmd.dip25-default,`-preview=dip25` has been enabled by default) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.dip25-default.dd) +$(P +Deprecation warnings for [DIP25](http://dlang.org/dips/25) violations have been enabled since 2.092. +Starting with this release, it will report errors, unless the `-revert=dip25` switch is used. +Using the switch (or its short version `-dip25`) is now deprecated. +) + +--- +ref int escapeRef(ref int x) {return x;} + +// Formerly: +// Deprecation: returning `x` escapes a reference to parameter `x` +// perhaps annotate the parameter with `return` +// +// Now it is an error, unless `-revert=dip25` is used +--- +) + +$(LI $(LNAME2 dmd.extern-dllimport,export int a; now generates dllexport instead of dllimport) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.extern-dllimport.dd) +$(P +In order to make it dllimport, use: +) + +--- +export extern int a; +--- +) + +$(LI $(LNAME2 dmd.get-is-virtual-function,Deprecate `traits(isVirtualFunction)` and `traits(getVirtualFunctions)`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.get-is-virtual-function.dd) +$(P +Up until this release, D had both `traits(isVirtualFunction)` and `traits(isVirtualMethod)` +(and their coressponding `traits(get...)` counterpart). The differenrcte between the two is +that `isVirtualFunction` returns true for `final` methods that do not override anything. This +is in contradiction with the D spec which states that `final` functions that do not override +other functions cannot be virtual. `isVirtualMethod` correctly returns `false` in that case. +) + +$(P +Starting with this release, both `traits(isVirtualFunction)` and `traits(getVirtualFunctions)` +are deprecated. If the behavior of `traits(isVirtualFunction)` is desired, it can be achieved by +`traits(isVirtualMethod, f) || (traits(isFinalFunction, f) && !traits(isOverrideFunction, f))`. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 grapheme_walker_update,Unicode grapheme walking updated to conform to Unicode version 15) +$(CHANGELOG_SOURCE_FILE phobos, changelog/grapheme_walker_update.dd) +$(P +Up until now `graphemeStride`, `byGrapheme` and `decodeGrapheme` functions in +`std.uni` have used obsolete rules from earlier Unicode standards. +) + +$(P +This release brings grapheme breaking rules up to date with Unicode version 15. +This means Phobos functions now recognise extended pictogram sequences and +prepend characters. +) +) + +$(LI $(LNAME2 joiner_assert_message,Better static assert messages for `std.algorithm.iteration.joiner`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/joiner_assert_message.dd) +$(P +Up until now `filter` used a template constraint to check if the passed Data +could be used. If it were not, it was very tedious to figure out why. +) + +$(P +As the template constraint is not used to overload the symbol template +function, the constrains are move into static asserts with expressive error +messages. +) +) + +$(LI $(LNAME2 sort_assert_messaged,Better static assert messages for `std.algorithm.sorting.sort`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/sort_assert_messaged.dd) +$(P +Up until now `sort` used a template constraint to check if the passed Range +could be used. If it were not, it was very tedious to figure out why. +) + +$(P +As the template constraint is not used to overload the symbol template +function, the constrains are move into static asserts with expressive error +messages. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 colors,The `--color` argument now accepts values `auto`, `never`, `always`) +$(CHANGELOG_SOURCE_FILE dub, changelog/colors.dd) +$(P +The previous `automatic`, `on`, `off` values are still supported, but +undocumented, because they are used in almost no other program like this. For +consistency, with other Linux tools especially, we have implemented and switched +the defaults to the widely-used `auto`, `never`, `always` values. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 15985): [REG2.068/2.069] Code doesn't link unless compiled with -debug) +$(LI $(BUGZILLA 18472): [Reg 2.078] betterC: cannot use format at compile time.) +$(LI $(BUGZILLA 21772): [REG2.069] Consecutive different-signed double.nans in an array literal take the sign of the previous nan $(LPAREN)same for float and real$(RPAREN)) +$(LI $(BUGZILLA 22039): ICE on infinite recursion in default parameter) +$(LI $(BUGZILLA 23688): FTBFS: error: cannot convert 'Expression' to 'Expression*') +$(LI $(BUGZILLA 23710): [REG master] Reachable code inside an 'if $(LPAREN)false$(RPAREN)' block no longer gets codegen) +$(LI $(BUGZILLA 23758): [REG 2.103] Segfault accessing NewExp::argprefix from C++) +$(LI $(BUGZILLA 23799): Link error with -betterC) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 10886): Typeof on @property function triggers 'wrong this' type error) +$(LI $(BUGZILLA 11051): Unmatched case in a final switch should throw in both release and non-release mode) +$(LI $(BUGZILLA 16098): align$(LPAREN)N$(RPAREN) not respected for stack variables if N > platform stack alignment) +$(LI $(BUGZILLA 16213): CTFE internal error with static array $ as template argument) +$(LI $(BUGZILLA 20781): Can call @live function without checking dip1021 rules) +$(LI $(BUGZILLA 20908): -preview=nosharedaccess requires zero-initializion for aggregates) +$(LI $(BUGZILLA 21288): Wrong context pointer for alias this function) +$(LI $(BUGZILLA 21492): betterC: TypeInfo is generated for code guarded by if$(LPAREN)__ctfe$(RPAREN)) +$(LI $(BUGZILLA 21821): Optimizer assumes immutables do not change, but they can in @system code) +$(LI $(BUGZILLA 22916): [dip1000] copy of ref return still treated as scope variable) +$(LI $(BUGZILLA 23145): Stack allocation of scope new variables defeats @safe) +$(LI $(BUGZILLA 23195): Win64 function ABI bug for small non-POD arguments) +$(LI $(BUGZILLA 23261): druntime core.std.attribute.Tagged1_2 constructor is unsafe) +$(LI $(BUGZILLA 23387): ImportC: identical structs defined in two C files lead to duplicate .init symbol on macOS) +$(LI $(BUGZILLA 23407): ImportC: function-local struct definition as part of variable declaration doesn’t shadow global definition) +$(LI $(BUGZILLA 23545): export int a; should generate dllexport, not dllimport) +$(LI $(BUGZILLA 23583): ImportC: undefined identifier __builtin___memmove_chk) +$(LI $(BUGZILLA 23584): ImportC: __builtin_bit_cast not supported) +$(LI $(BUGZILLA 23598): Circular reference bug with static if and eponymous templates) +$(LI $(BUGZILLA 23606): betterC with CTFE and gc) +$(LI $(BUGZILLA 23616): ImportC: clang __has_feature and __has_extension not recognized) +$(LI $(BUGZILLA 23617): traits$(LPAREN)child$(RPAREN) compile error need this for something that doesn't need this) +$(LI $(BUGZILLA 23622): ImportC #defines conflict with declarations) +$(LI $(BUGZILLA 23635): Nonsensical "`case` must be a `string` or an integral constant, not `x`") +$(LI $(BUGZILLA 23639): Casting to shared not allowed with -preview=nosharedaccess) +$(LI $(BUGZILLA 23650): Using typeid with struct defined in in __traits$(LPAREN)compiles, ...$(RPAREN) causes linker error) +$(LI $(BUGZILLA 23651): Order dependency in semantic analysis of template members) +$(LI $(BUGZILLA 23658): .di generation of variables should turn them into declarations) +$(LI $(BUGZILLA 23669): [DIP1000] Compound assignment to length of slice member variable in scope method fails) +$(LI $(BUGZILLA 23676): Static foreach hangs compilation for some time) +$(LI $(BUGZILLA 23682): dip1000 problem with return by ref) +$(LI $(BUGZILLA 23694): compilable/ctests2.c:51:9: error: initializer element is not constant) +$(LI $(BUGZILLA 23711): compilable/testcstuff1.c:63:1: error: invalid use of restrict) +$(LI $(BUGZILLA 23717): runnable/bitfields.c:192:5: error: unknown type name S; use struct keyword to refer to the type) +$(LI $(BUGZILLA 23752): ImportC: can't take address of dereferenced void pointer) +$(LI $(BUGZILLA 23760): Error: unknown) +$(LI $(BUGZILLA 23763): ICE on operations involving zero-initialized structs) +$(LI $(BUGZILLA 23767): ImportC: ternary with null constant has wrong pointer type) +$(LI $(BUGZILLA 23778): Code generator fails to handle __c_complex_real properly for Windows) +$(LI $(BUGZILLA 23781): [ICE] Segmentation Fault when taking the address of a ref return at CTFE) +$(LI $(BUGZILLA 23783): -preview=nosharedaccess does not detect comparison of shared data) +$(LI $(BUGZILLA 23790): Cannot use cas on member variable with -preview=nosharedaccess) +$(LI $(BUGZILLA 23792): lexer warns about preprocessor inside token strings) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 11316): Some cases of missing delegate argument type inference) +$(LI $(BUGZILLA 13656): clarify error message upon trying to declare a variable of type ref) +$(LI $(BUGZILLA 16495): __traits$(LPAREN)fullyQualifedName$(RPAREN) instead of std.traits.fullyQualifiedName) +$(LI $(BUGZILLA 20101): BetterC: Template instantiation in CTFE only context should skip codegen / nogc / ... Phases) +$(LI $(BUGZILLA 23558): add __traits$(LPAREN)getModuleClasses [, module name]$(RPAREN)) +$(LI $(BUGZILLA 23597): .di files not compatible with -i) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 23776): getSymbolsByUDA fails to fetch symbols from module) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 23474): Grapheme should end after carriage return if not followed by line feed.) +$(LI $(BUGZILLA 23600): [std.format.read] formattedRead static asserts with Tuple and compile time format string) +$(LI $(BUGZILLA 23668): Can't stable sort structs with disabled default constructor.) +$(LI $(BUGZILLA 23724): HTTP.onReceive example does not compile) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 19567): [std.stdio] Not really helpful documentation of `tell`) +$(LI $(BUGZILLA 20397): [std.algorithm] documentation nthPermutation) +$(LI $(BUGZILLA 23683): std.file.setTimes requests more permissions than needed) +$(LI $(BUGZILLA 23706): Do not escape POSIX shell parameters unless necessary) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 19575): core.cpuid not usable without a runtime) +$(LI $(BUGZILLA 23625): Function ZeroMemory missing in windows headers) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 6583): cast$(LPAREN)$(RPAREN) operation not fully specified) +$(LI $(BUGZILLA 11493): dlang.org/type.html incorrectly says that you can't cast from -1 to unsigned types) +$(LI $(BUGZILLA 16707): [Templates] run variadic templates example failed) +$(LI $(BUGZILLA 21132): Ff two keys in an associative array literal are equal) +$(LI $(BUGZILLA 21178): It is not explained what is "unknown") +$(LI $(BUGZILLA 23716): ImportC: Missing documentation on the asm keyword accepted as an extension) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 18765): [Arrays] Docs need info on initialization of static array with element literal) +$(LI $(BUGZILLA 20997): Missing example of scope guard executing after return statement) +$(LI $(BUGZILLA 22418): Error in documentation on strings) +$(LI $(BUGZILLA 22594): Update "Interfacing to C" to include intptr_t and uintptr_t) +$(LI $(BUGZILLA 23612): Template constraints article not listed in article index) +$(LI $(BUGZILLA 23636): No spec docs for shared qualifer) +$(LI $(BUGZILLA 23730): Clarify IsExpression `Identifier :` and `== TypeCtor` spec) +) +$(BUGSTITLE_BUGZILLA Tools bug fixes, + +$(LI $(BUGZILLA 23624): Race condition in test runner for DMD) +$(LI $(BUGZILLA 23634): Possible data race with runnable example tester) +) +) +$(D_CONTRIBUTORS_HEADER 43) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Amaury) + $(D_CONTRIBUTOR Andra Maslaev) + $(D_CONTRIBUTOR Andrea Fontana) + $(D_CONTRIBUTOR Ate Eskola) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR BVRazvan) + $(D_CONTRIBUTOR Daniel Zuncke) + $(D_CONTRIBUTOR DanutAldea) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR Drehuta Andreea) + $(D_CONTRIBUTOR Dumitrache Adrian-George) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Ikey Doherty) + $(D_CONTRIBUTOR ioanavivi12) + $(D_CONTRIBUTOR Jan Jurzitza) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR João Lourenço) + $(D_CONTRIBUTOR KytoDragon) + $(D_CONTRIBUTOR Luís Ferreira) + $(D_CONTRIBUTOR Mateiuss) + $(D_CONTRIBUTOR MathewColin) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR matthriscu) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Quirin F. Schroll) + $(D_CONTRIBUTOR Rareș Constantin) + $(D_CONTRIBUTOR Razvan Mihai Popa) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR richard (rikki) andrew cattermole) + $(D_CONTRIBUTOR Robert burner Schadek) + $(D_CONTRIBUTOR Robert Grancsa) + $(D_CONTRIBUTOR Robert Stoica) + $(D_CONTRIBUTOR Rosca Rares) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Teodor Dutu) + $(D_CONTRIBUTOR Tudor Brindus) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.103.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.103.1.dd b/changelog/2.103.1.dd new file mode 100644 index 0000000000..bbc113b6a4 --- /dev/null +++ b/changelog/2.103.1.dd @@ -0,0 +1,77 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION May 01, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 1 major change and 6 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 5 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.deprecate-pound-in-token-string,Deprecate invalid special token sequences inside token strings)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.deprecate-pound-in-token-string,Deprecate invalid special token sequences inside token strings) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecate-pound-in-token-string.dd) +$(P +A token string is specified to contain valid D tokens, but the compiler formerly allowed `#identifier` tokens in them. +) + +--- +enum s = q{ +#endif x +} + +--- + +$(P +This will now issue a deprecation warning. It will become an error in dmd 2.113. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 20090): Header generation wrongfully outputs constructor bodies) +$(LI $(BUGZILLA 23816): Typing invalid mnemonic in asm{} block segfaults) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 22739): Segmentation fault in CppMangleVisitor.headOfType) +$(LI $(BUGZILLA 22765): Assertion failure in CppMangleVisitor.template_args) +$(LI $(BUGZILLA 22857): Segfault for malformed static if in imported template) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 23859): [REG 2.103] Throwing while in a deep callstack causes memory corruption) +) +) +$(D_CONTRIBUTORS_HEADER 5) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Steven Schveighoffer) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.103.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.104.0.dd b/changelog/2.104.0.dd new file mode 100644 index 0000000000..c91259e200 --- /dev/null +++ b/changelog/2.104.0.dd @@ -0,0 +1,435 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jun 01, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 11 major changes and 63 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 38 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.attr-inference-diag,Better error message when attribute inference fails down the call stack)) +$(LI $(RELATIVE_LINK2 dmd.empty-statement-error,Using `;` as an empty statement has been turned into an error)) +$(LI $(RELATIVE_LINK2 dmd.in-externd,Using `in` parameters with non `extern(D)`/`extern(C++)` functions is deprecated)) +$(LI $(RELATIVE_LINK2 dmd.in-ref,`in ref` on parameters has been deprecated in favor of `-preview=in`)) +$(LI $(RELATIVE_LINK2 dmd.throw-qualifier,Throwing qualified objects is now deprecated)) +$(LI $(RELATIVE_LINK2 dmd.uda-template-args,User Defined Attributes now parse Template Arguments)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 clamp_assert_message,Better static assert messages for `std.algorithm.comparison.clamp`)) +$(LI $(RELATIVE_LINK2 rebindable_all_types,`std.typecons.Rebindable` now supports all types)) + +) + +$(BUGSTITLE_TEXT_HEADER Tools changes, + +$(LI $(RELATIVE_LINK2 rdmd_shared,rdmd supports `-shared`)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 collect_c_source_and_headers_for_ImportC,Add new properties 'cSourcePaths' and 'cImportPaths' to SDL/JSON)) +$(LI $(RELATIVE_LINK2 hierarchy,The way packages are stored internally has changed)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.attr-inference-diag,Better error message when attribute inference fails down the call stack) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.attr-inference-diag.dd) +$(P +When a function fails to infer a function attribute, all callers of that function also fail to infer the attribute. +The resulting error message only points to the top most function with the explicit attribute: +) + +--- +void main() @nogc +{ + fun(); +} + +auto fun() +{ + funImpl(); +} + +auto funImpl() +{ + int[] a = [1, 2, 3]; +} +--- + +$(P +$(CONSOLE +app.d(4): Error: `@nogc` function `D main` cannot call non-@nogc function `app.fun` +) +) + +$(P +This doesn't tell the underlying reason why `fun` wasn't inferred `@nogc`, and led to use of [workarounds to get better information](https://www.schveiguy.com/blog/2023/02/spelunking-attribute-inference-in-d/). +The new error message will point to the function which failed to infer the attribute: +) + +$(P +$(CONSOLE +app.d(4): Error: `@nogc` function `D main` cannot call non-@nogc function `app.fun` +app.d(7): which calls `app.funImpl` +app.d(14): which wasn't inferred `@nogc` because of: +app.d(14): array literal in `@nogc` function `app.funImpl` may cause a GC allocation +) +) + +$(P +Note: this was already implemented for `@safe` since 2.101, but it has now been extended to `@nogc`, `nothrow`, and `pure`. +) +) + +$(LI $(LNAME2 dmd.empty-statement-error,Using `;` as an empty statement has been turned into an error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.empty-statement-error.dd) +$(P +This has been deprecated since 2.075.0 because it's error prone: +) + +--- +void main() +{ + foreach (i; 0 .. 8); + { + // Because of the accidental semicolon above, + // this block statement is executed once. + // It's not the loop body + } +} +--- + +$(P +It will now result in an error. +) + +$(P +$(CONSOLE +app.d(3): Error: use `{ }` for an empty statement, not `;` +) +) +) + +$(LI $(LNAME2 dmd.in-externd,Using `in` parameters with non `extern(D)`/`extern(C++)` functions is deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.in-externd.dd) +$(P +In preparation for enabling `-preview=in` by default, +using `in` parameters on function that have neither D nor C++ linkage is deprecated. +Users can replace instances of `in` with either `const` or `scope const`. +Refer to [v2.101.0 changelog's](https://dlang.org/changelog/2.101.0.html#dmd.previewInLink) +for a full rationale. +) +) + +$(LI $(LNAME2 dmd.in-ref,`in ref` on parameters has been deprecated in favor of `-preview=in`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.in-ref.dd) +$(P +Using `in ref` (or `ref in`) on function parameters will now yield a deprecation. +Users are encouraged to remove the `ref` and compile with `-preview=in`, +which will infer whether the parameter should be passed by reference or value. +Users wanting a specific ABI are encouraged to use `scope const ref` instead. +Note that this also applies to `auto ref in`, which is equivalent to `in` with `-preview=in`, +but the latter doesn't require the function to be templated. +) +) + +$(LI $(LNAME2 dmd.throw-qualifier,Throwing qualified objects is now deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.throw-qualifier.dd) +$(P +Previously, an `immutable`, `const`, `inout` or `shared` exception could be +thrown and then caught in an unqualified `catch (Exception e)` clause. +That breaks type safety. +Throwing a qualified object is now deprecated. This helps to prevent +possible mutation of an immutable object in a `catch` clause. +) + +$(P +The runtime also modifies a thrown object (e.g. to contain a stack +trace) which can violate `const` or `immutable` objects. Throwing +qualified objects has been deprecated for this reason also. +) +) + +$(LI $(LNAME2 dmd.uda-template-args,User Defined Attributes now parse Template Arguments) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.uda-template-args.dd) +$(P +It was already allowed to put types in UDAs, but the parser would reject basic types written directly, requiring the use of an alias. +) + +--- +alias Tint = int; + +@Tint void f(); +--- + +$(P +Also, simple literals that can appear in template instantiations without brackets (example: `foo!"arg"`) require parentheses when used as an attribute: +) +--- +@("my test") unittest +{ + +} +--- + +$(P +Now, arguments that can appear after a template instantiation `foo!` can also appear after an `@` attribute. +) +--- +@int void f(); + +@"my test" unittest +{ + +} +--- +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 clamp_assert_message,Better static assert messages for `std.algorithm.comparison.clamp`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/clamp_assert_message.dd) +$(P +Until now, `clamp` used a template constraint to check if the passed types +could be used. If they were not, it was very tedious to figure out why. +) + +$(P +As the template constraint is not used for overload resolution +the constrains are moved into static asserts with expressive error +messages. +) +) + +$(LI $(LNAME2 rebindable_all_types,`std.typecons.Rebindable` now supports all types) +$(CHANGELOG_SOURCE_FILE phobos, changelog/rebindable_all_types.dd) +$(P +`Rebindable` can now be used to store and rebind values of any type, including +`immutable struct` values. +) + +$(P +To ensure const safety is preserved, the stored values cannot be accessed +by reference. +) + +$(P +The implementation used for all previously supported types (classes, interfaces +and arrays) is unchanged. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Tools changes, + +$(LI $(LNAME2 rdmd_shared,rdmd supports `-shared`) +$(CHANGELOG_SOURCE_FILE tools, ../tools/changelog/rdmd_shared.dd) +$(P +rdmd now understands DMD's `-shared` switch, and sets the default output file name appropriately (`.dll`, `.so`, or `.dylib` depending on the platform), in the same way as `-lib`. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 collect_c_source_and_headers_for_ImportC,Add new properties 'cSourcePaths' and 'cImportPaths' to SDL/JSON) +$(CHANGELOG_SOURCE_FILE dub, changelog/collect_c_source_and_headers_for_ImportC.dd) +$(P +`cSourcePaths` passes the C source files in all specified directories to the compiler. +All C sources found in the given directories for 'cImportPaths' are passed to the D compiler. +This ensures backward compatible behaviour for projects that stored C sources aside of D source file, while porting them to D. +) + +$(P +The second keyword 'cImportPaths' will add additional search paths for C headers. These directories are passed to the D compilers +as addition include paths. The feature might need additional tweaking, because the include paths are currently joint with the +D import paths. This might change in future to support independant search paths for C to be passed to the D compilers. +) +) + +$(LI $(LNAME2 hierarchy,The way packages are stored internally has changed) +$(CHANGELOG_SOURCE_FILE dub, changelog/hierarchy.dd) +$(P +Previous versions of dub stored packages in the following format: +`$CACHE_PATH/$PACKAGE_NAME-$PACKAGE_VERSION/$PACKAGE_NAME/` +Starting from this version, the format will be: +`$CACHE_PATH/$PACKAGE_NAME/$PACKAGE_VERSION/$PACKAGE_NAME`. +) + +$(P +Introducing a new level will help users quickly list what packages +they actually have installed, and reduce visibility of packages that +might update frequently. It will render various commands (e.g. `du`) +more useful, pave the way for a package GC function, and make manual +browsing easier. +) + +$(P +More importantly, it will allow future version of dub to infer the +version from the path to the package, removing the need to read (or edit) +the recipe file on every dub invocation. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 23764): Message printed twice: Usage of in on parameter) +$(LI $(BUGZILLA 23832): dmd regression 2.103.0 silent error cannot call decode at runtime) +$(LI $(BUGZILLA 23874): -profile=gc segfaults / ICE regression) +$(LI $(BUGZILLA 23882): ICE $(LPAREN)segfault$(RPAREN) on nasty alias this code) +$(LI $(BUGZILLA 23905): Initialization of SumType with opaque enum causes ICE) +$(LI $(BUGZILLA 23913): __traits$(LPAREN)getMember$(RPAREN) fails for some C symbols) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 12118): Modify immutable data using throw) +$(LI $(BUGZILLA 18493): [betterC] Can't use aggregated type with postblit) +$(LI $(BUGZILLA 19454): Name collisions with unnamed function parameters) +$(LI $(BUGZILLA 19706): Attribute inference in struct fails) +$(LI $(BUGZILLA 20737): TLS variables unusable with -betterC for Windows MSVC targets) +$(LI $(BUGZILLA 21667): scope parameter causes 'no size because of forward references') +$(LI $(BUGZILLA 22760): Segmentation fault in CppMangleVisitor.template_arg) +$(LI $(BUGZILLA 22785): joiner does not support range over immutable) +$(LI $(BUGZILLA 22960): importC: K&R-style functions assume variadic calling convention) +$(LI $(BUGZILLA 23014): importC: static thread-locals do not work) +$(LI $(BUGZILLA 23055): importC: using compound-literal array as pointer in CTFE gives 'dereference of invalid pointer') +$(LI $(BUGZILLA 23402): importc function definitions from includes can cause D name conflicts) +$(LI $(BUGZILLA 23427): ImportC: some bitfield combinations lead to wrong size struct) +$(LI $(BUGZILLA 23509): ImportC: need statement expressions extension for GLibC's assert$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 23691): compilable/test22294.i:16:1: control Z interpreted as end of file) +$(LI $(BUGZILLA 23715): ImportC: No rejection of _Thread_local variables declared at function scope without 'static' as per C11 6.2.4-5) +$(LI $(BUGZILLA 23727): ImportC support imaginary real numbers) +$(LI $(BUGZILLA 23784): ImportC: __ptr32, __ptr64) +$(LI $(BUGZILLA 23787): ImportC: __unaligned) +$(LI $(BUGZILLA 23789): ImportC: __declspec$(LPAREN)align$(LPAREN)n$(RPAREN)$(RPAREN)) +$(LI $(BUGZILLA 23795): Cannot cast _Complex!double to _Complex!float) +$(LI $(BUGZILLA 23801): ImportC: enumeration constant does not fit in an int) +$(LI $(BUGZILLA 23802): ImportC: __volatile__ is yet another alias for volatile) +$(LI $(BUGZILLA 23808): #include is not working with importc) +$(LI $(BUGZILLA 23822): Deprecated struct alias ignored completely) +$(LI $(BUGZILLA 23826): Deprecated type member passed to template doesn't warn) +$(LI $(BUGZILLA 23836): Two errors printed for typeof$(LPAREN)super$(RPAREN) in non-static member context) +$(LI $(BUGZILLA 23837): importc fails to link on windows x86 but successes on x64) +$(LI $(BUGZILLA 23838): DMD lexer / parser examples might not compile) +$(LI $(BUGZILLA 23861): Compiler segmentation fault with ref and alias this) +$(LI $(BUGZILLA 23863): `typeof` rejects `AliasSeq!$(LPAREN)$(RPAREN)` as argument) +$(LI $(BUGZILLA 23866): ImportC: Multiple __declspecs rejected) +$(LI $(BUGZILLA 23867): ImportC: undefined identifier `__builtin_isnan`) +$(LI $(BUGZILLA 23869): ImportC: undefined identifier `isfinite`) +$(LI $(BUGZILLA 23873): [ICE] segfault on imported `static if ; else auto x`) +$(LI $(BUGZILLA 23885): [CI] C++ interop tests with g++ fail) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 13577): More informative error message for refused immutable foreach loop) +$(LI $(BUGZILLA 17374): Improve inferred attribute error message) +$(LI $(BUGZILLA 20268): anonymous function parameter mismatch errors don't include parameters) +$(LI $(BUGZILLA 22559): ImportC: support gnu case ranges) +$(LI $(BUGZILLA 23401): ImportC: add -cpp=filename switch to select C preprocessor) +$(LI $(BUGZILLA 23862): with statement should accept an expression with enum type) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 19642): std.range.slide!$(LPAREN)No.withPartial$(RPAREN) on lengthless forward range: get empty when expecting one window) +$(LI $(BUGZILLA 22147): DList can't accept a struct with postblit disabled) +$(LI $(BUGZILLA 22786): maxElement et al does not support range over immutable) +$(LI $(BUGZILLA 23834): std.file : File links to c functions are invalid and need updating) +$(LI $(BUGZILLA 23846): std.math can't compile under macos rosetta) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 6106): Keep track of changes during replace function) +$(LI $(BUGZILLA 14478): isInputRange should allow ranges of non-copyable elements) +$(LI $(BUGZILLA 23769): Lambda isn't a unary predicate for lambda that doesn't compile) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 14891): profilegc_setlogfilename w/o null-terminated string might fail during fopen) +$(LI $(BUGZILLA 23949): core.stdc.assert_ for FreeBSD and DragonFlyBSD is incorrect) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 11989): Phase out TickDuration) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 14932): The language specification does not define what the shared attribute does) +$(LI $(BUGZILLA 23698): ImportC: __stdcall is not documented as supported MSVC/DMC extensions) +$(LI $(BUGZILLA 23699): ImportC: Unclear documentation that struct/union/enum introduce implicit typedefs) +$(LI $(BUGZILLA 23872): Wrong example in Interfacing to C: Calling printf section) +) +) +$(D_CONTRIBUTORS_HEADER 38) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR Andrew Lalis) + $(D_CONTRIBUTOR Ate Eskola) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Caleb Xu) + $(D_CONTRIBUTOR Christian Koestlin) + $(D_CONTRIBUTOR Denis Feklushkin) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR Dmytro Katyukha) + $(D_CONTRIBUTOR drpriver) + $(D_CONTRIBUTOR Ernesto Castellotti) + $(D_CONTRIBUTOR Grim Maple) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR jamesragray) + $(D_CONTRIBUTOR Jan Jurzitza) + $(D_CONTRIBUTOR Jeremy) + $(D_CONTRIBUTOR Jordi Sayol) + $(D_CONTRIBUTOR Lance Bachmeier) + $(D_CONTRIBUTOR Lucian Danescu) + $(D_CONTRIBUTOR lucica28) + $(D_CONTRIBUTOR Marcelo Silva Nascimento Mancini) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Max Haughton) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Robert burner Schadek) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Temtaime) + $(D_CONTRIBUTOR Teodor Dutu) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.104.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.104.1.dd b/changelog/2.104.1.dd new file mode 100644 index 0000000000..986827c74c --- /dev/null +++ b/changelog/2.104.1.dd @@ -0,0 +1,58 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 01, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 11 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 10 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 23965): [REG2.101.0] Appending deprecated structs in deprecated function causes deprecation message) +$(LI $(BUGZILLA 23978): [REG 2.103.0] ICE: dip1021 memory corruption) +$(LI $(BUGZILLA 23979): ICE on failed alias this attempt on pointer expression) +$(LI $(BUGZILLA 24013): [REG 2.103.0] address of a __traits$(LPAREN)getOverloads$(RPAREN) item is not converted to a delegate anymore) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 21025): Segfault for function contract -preview=dip1021) +$(LI $(BUGZILLA 22729): ICE: Invalid array access for invalid interface definition) +$(LI $(BUGZILLA 23768): ImportC: ICE on nested C initializer) +$(LI $(BUGZILLA 23982): segfault when printing scope inference failure) +$(LI $(BUGZILLA 23986): ICE: dip1021 asserts on `typeof$(LPAREN)null$(RPAREN)` parameter) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 23976): std.range.slide fails in dmd-2.104.0) +$(LI $(BUGZILLA 23993): std.algorithm.maxElement no longer works with array of BigInt) +) +) +$(D_CONTRIBUTORS_HEADER 10) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR FeepingCreature) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Richard (Rikki) Andrew Cattermole) + $(D_CONTRIBUTOR Teodor Dutu) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.104.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.104.2.dd b/changelog/2.104.2.dd new file mode 100644 index 0000000000..71a12d839a --- /dev/null +++ b/changelog/2.104.2.dd @@ -0,0 +1,50 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 15, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 6 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 7 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 23966): [REG2.102] Cannot use traits$(LPAREN)getAttributes$(RPAREN) with overloaded template) +$(LI $(BUGZILLA 24026): ImportC: ICE on nested C initializer 2) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 23279): Segmentation fault on mixin template + using unknown type) +$(LI $(BUGZILLA 23951): "alias this" not properly dereferenced when the object being looked up is a field of a type) +$(LI $(BUGZILLA 24027): error: instantiated from here: `maxElement!$(LPAREN)"a.a", A[]$(RPAREN)`) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 23890): "Warning: cannot inline function" in core.lifetime) +) +) +$(D_CONTRIBUTORS_HEADER 7) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dmytro Katyukha) + $(D_CONTRIBUTOR FeepingCreature) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.104.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.105.0.dd b/changelog/2.105.0.dd new file mode 100644 index 0000000000..d295a0e85c --- /dev/null +++ b/changelog/2.105.0.dd @@ -0,0 +1,463 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Aug 01, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 12 major changes and 59 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 34 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.alias-this-syntax,Assignment-style syntax is now allowed for `alias this`)) +$(LI $(RELATIVE_LINK2 dmd.catch-immutable,Catch clause must take only `const` or mutable exceptions)) +$(LI $(RELATIVE_LINK2 dmd.enum-function,Functions can no longer have `enum` storage class)) +$(LI $(RELATIVE_LINK2 dmd.extern-c-overload,Overloading `extern(C)` functions is now an error)) +$(LI $(RELATIVE_LINK2 dmd.private-deprecation-error,Deprecation phase ended for access to private method when overloaded with public method.)) +$(LI $(RELATIVE_LINK2 dmd.visionos-version-identifier,Added predefined version identifier `VisionOS`)) +$(LI $(RELATIVE_LINK2 dmd.allow-parentheses-for-call,Do not error with a C cast when surrounding a type or expression in parentheses when calling or constructing.)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 druntime.input-headers,Linux input header translations were added to druntime)) +$(LI $(RELATIVE_LINK2 druntime.valgrind,Integration with the Valgrind `memcheck` tool has been added to the garbage collector)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 permutation_assert_message,Better static assert messages for `std.algorithm.iteration.permutations`)) +$(LI $(RELATIVE_LINK2 std_system_instruction_set_architecture,Added `std.system.instructionSetArchitecture` and `std.system.ISA`)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 d_versions_flag,Exposed `--d-versions` CLI flag)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.alias-this-syntax,Assignment-style syntax is now allowed for `alias this`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.alias-this-syntax.dd) +$(P +`alias this` declarations can now be written using the same `alias new = old;` +syntax as other `alias` declarations. +) + +--- +struct S +{ + int n; + alias this = n; + // Equivalent to: + //alias n this; +} +--- +) + +$(LI $(LNAME2 dmd.catch-immutable,Catch clause must take only `const` or mutable exceptions) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.catch-immutable.dd) +$(P +In 2.104, throwing qualified types was +[deprecated](https://dlang.org/changelog/2.104.0.html#dmd.throw-qualifier). +) + +$(P +It is also unsafe to catch an exception as `immutable`, `inout` or `shared`. +This is because the exception may still be accessible through another +mutable or non-shared reference. Catching an exception with those qualifiers +is now deprecated. +) + +--- +auto e = new Exception("first"); +try { + throw e; +} catch(immutable Exception ie) { // now an error + e.msg = "second"; + assert(ie.msg == "first"); // would fail +} +--- +) + +$(LI $(LNAME2 dmd.enum-function,Functions can no longer have `enum` storage class) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.enum-function.dd) +$(P +`enum` on a function declaration had no effect other than being +equivalent to the `auto` storage class when no return type was present. +That syntax could be confused with `enum` manifest constants and is +now an error: +) +--- +enum void f1() { } // error +enum f2() { } // error +--- + +$(P +Instead, remove `enum` and use `auto` where necessary: +) +--- +void f1() { } +auto f2() { } +--- +) + +$(LI $(LNAME2 dmd.extern-c-overload,Overloading `extern(C)` functions is now an error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.extern-c-overload.dd) +$(P +Since 2.095.0, defining the same function multiple times in a module is not allowed, since it would result in symbol clashes at link time. +Overloading a function with different parameter types is still allowed of course, and works because D mangles symbol names including parameter types. +However, some external linkages (such as `extern(C)`, `extern(Windows)`) don't do this, so overloading them can also result in symbol clashes at link time. +Therefore, doing this was deprecated in that release as well. +) + +$(P +This deprecation now turned into an error. +As a corrective action, give the function D or C++ linkage, or use a unique function name. +) + +--- +// Error: +extern(C) float square(float x) { return x * x; } +extern(C) double square(double x) { return x * x; } + +// Corrective action: +extern(C) float squaref(float x) { return x * x; } +extern(C) double squared(double x) { return x * x; } + +// Or: +float square(float x) { return x * x; } +double square(double x) { return x * x; } +--- +) + +$(LI $(LNAME2 dmd.private-deprecation-error,Deprecation phase ended for access to private method when overloaded with public method.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.private-deprecation-error.dd) +$(P +When a private method was overloaded with a public method that came after it, +you could access the private overload as if it was public. +) + +$(P +After a deprecation period starting with 2.094, this code is now an error. +) + +$(P +Example: +) + +``` +struct Foo +{ + private void test(int) { } + public void test(string) { } +} +... +Foo().test(3); +``` +) + +$(LI $(LNAME2 dmd.visionos-version-identifier,Added predefined version identifier `VisionOS`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.visionos-version-identifier.dd) +$(P +This is Apple's new operating system for their VR/AR device Vision Pro. +) +) + +$(LI $(LNAME2 dmd.allow-parentheses-for-call,Do not error with a C cast when surrounding a type or expression in parentheses when calling or constructing.) +$(P +Previous to this version, an expression like `(IdentifierOrBasicType)(Expression)` would be considered a c-style cast, +and disallowed, even if the `IdentifierOrBasicType` could be used as a callable. This is now allowed, as long as the expression is a call, or a construction. + +``` +struct S { int x; } +int foo(int x) { return x; } +auto bar = &foo; + +// these were previously disallowed +auto s = (S)(5); // equivalent to S(5) +auto f = (foo)(5); // equivalent to foo(5) +auto b = (bar)(5); // equivalent to bar(5) +auto i = (int)(5); // equivalent to int(5), not a cast. + +// these are not allowed +auto bad = (int)5; // Error: C style cast illegal, use `cast(int)5` +auto bad2 = (ubyte)(12345); // Error: cannot implicitly convert expression `12345` of type `int` to `ubyte` +``` +) + +$(P See $(BUGZILLA 24025): Expressions contained in parentheses should not be assumed to be C casts) +) + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 druntime.input-headers,Linux input header translations were added to druntime) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.input-headers.dd) +$(P +These headers give access to the [Linux Input Subsystem userspace API](https://docs.kernel.org/input/input_uapi.html), +which is used to read input from e.g. keyboards, touch screens, and game controllers, or to emulate input devices. +You can now import them through `core.sys.linux`: +) + +--- +import core.sys.linux.input; // linux/input.h +import core.sys.linux.input_event_codes; // linux/input-event-codes.h +import core.sys.linux.uinput; // linux/uinput.h +--- +) + +$(LI $(LNAME2 druntime.valgrind,Integration with the Valgrind `memcheck` tool has been added to the garbage collector) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.valgrind.dd) +$(P +The garbage collector gained a compile-time option to enable integration with Valgrind's `memcheck` tool. +When it is enabled, the GC will communicate with Valgrind and inform it which memory access operations are valid and which are not. +) + +$(P +The integration allows catching memory errors in D programs which mix safe (GC) and unsafe (manual) memory management, for example: +) + +--- +import core.memory; + +void main() +{ + auto arr = new int[3]; + GC.free(arr.ptr); + arr[1] = 42; // use after free +} +--- + +$(P +To use it, obtain the DMD source code, then include the garbage collector and lifetime implementation into your program's compilation and compile with the `-debug=VALGRIND` option: +) + +``` +git clone -b v2.105.0 --depth=1 https://github.com/dlang/dmd +dmd -g -debug=VALGRIND program.d -Idmd/druntime/src dmd/druntime/src/{core/internal/gc/impl/conservative/gc,rt/lifetime,etc/valgrind/valgrind}.d +valgrind --tool=memcheck ./program +``` + +$(P +The option is compatible with other GC debugging build options, such as `MEMSTOMP` and `SENTINEL`. +) + +$(P +Dub users can try the following equivalent recipe: +) + +``` +git clone -b v2.105.0 --depth=1 https://github.com/dlang/dmd +cat >> dub.sdl <’?) +$(LI $(BUGZILLA 23857): backend inliner takes too long on recursive function call) +$(LI $(BUGZILLA 23870): ImportC doesn't accept '\' followed by newline, whereas VC does) +$(LI $(BUGZILLA 23875): ImportC: __attribute__ in a cast doesn't work) +$(LI $(BUGZILLA 23879): ImportC: Windows system headers use __alignof) +$(LI $(BUGZILLA 23880): ImportC: __attribute__$(LPAREN)$(LPAREN)vector_size$(LPAREN)N$(RPAREN)$(RPAREN)$(RPAREN) is not implemented) +$(LI $(BUGZILLA 23885): [CI] C++ interop tests with g++ fail) +$(LI $(BUGZILLA 23900): @safe is allowed in inline asm) +$(LI $(BUGZILLA 23908): confusing nonexistent import hint on cyclic import) +$(LI $(BUGZILLA 23912): Destructor disables scope inference) +$(LI $(BUGZILLA 23914): "auto ref" resolution on return value prevented by noreturn $(LPAREN)bottom type$(RPAREN)) +$(LI $(BUGZILLA 23935): ImportC: __pragma not allowed between struct and tag name) +$(LI $(BUGZILLA 23936): ImportC: pragma pack is not working for structs) +$(LI $(BUGZILLA 23947): If a class overloads a method mixing private and public and the last overload is public, the method is always public.) +$(LI $(BUGZILLA 23968): Deprecation not emitted with alias to template function in UFCS) +$(LI $(BUGZILLA 23988): Conditional Exp does not bring enums to correct common type if one leg is const) +$(LI $(BUGZILLA 24010): Destructor called before end of scope for tuples) +$(LI $(BUGZILLA 24017): [UFCS] Bypassing `nothrow` with `debug` doesn’t work) +$(LI $(BUGZILLA 24024): cannot pass class this to ref class) +$(LI $(BUGZILLA 24025): Expressions contained in parentheses should not be assumed to be C casts) +$(LI $(BUGZILLA 24029): ImportC: symbol name clash on statement expressions) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 4663): Wrong 'static' position error message) +$(LI $(BUGZILLA 15436): Compiler still refers to AliasSeq-s as "tuple"-s $(LPAREN)and TypeTuple?$(RPAREN)) +$(LI $(BUGZILLA 23475): confusing printf deprecation message with ulong/long on Windows) +$(LI $(BUGZILLA 23871): ImportC: __attribute not recognized) +$(LI $(BUGZILLA 23877): ImportC: Importing byteswap.h results in undefined reference to core.bitop.byteswap) +$(LI $(BUGZILLA 23886): ImportC preprocessor directive #ident not supported) +$(LI $(BUGZILLA 23928): improve error msg: scope variable s assigned to non-scope parameter this calling abc) +$(LI $(BUGZILLA 23931): Error: reference to local variable `this` calling non-scope member function `this.this$(LPAREN)$(RPAREN)`) +$(LI $(BUGZILLA 23948): __FILE__ and __MODULE__ cannot be implicitly converted to const$(LPAREN)char$(RPAREN)* as default paramenter) +$(LI $(BUGZILLA 23971): Provide clearer error message when trying to return a slice with C++ linkage) +$(LI $(BUGZILLA 24000): show the open bracket "{" location for Error: matching `}` expected, not `End of File`) +$(LI $(BUGZILLA 24023): Unnecessary module prefix in error message types) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 23361): std.uni.normalize should be pure) +$(LI $(BUGZILLA 23844): chain$(LPAREN)only$(RPAREN) doesn't support immutable structs) +$(LI $(BUGZILLA 23940): std.getopt does not assert with options that only differ in case with config.caseInsensitive) +$(LI $(BUGZILLA 23997): isClose$(LPAREN)1, -double.infinity$(RPAREN) returns true) +$(LI $(BUGZILLA 24028): BigInt power operator ignores sign of exponent) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 23881): std.system has no function for system architecture) +$(LI $(BUGZILLA 23922): [std.socket]) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 23312): Crash when calling writeln in WinMain) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 23980): OpenBSD: Add getthrname$(LPAREN)2$(RPAREN) and setthrname$(LPAREN)2$(RPAREN) to unistd.d) +$(LI $(BUGZILLA 24044): Support float opCmp$(LPAREN)...$(RPAREN) with array) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 23692): ImportC: __pragma and __declspec are not documented as supported Visual C extensions) +$(LI $(BUGZILLA 23697): No examples of invalid forward references in C code accepted by ImportC) +$(LI $(BUGZILLA 23946): specifications state that "there can only be one destructor" which can be confusing because of mixin templates) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 5636): Array ops use lexicographic comparison instead of vector-style element-wise) +$(LI $(BUGZILLA 23571): Discussion of manifest constants in enum documentation is confusing at best) +) +) +$(D_CONTRIBUTORS_HEADER 34) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Amaury) + $(D_CONTRIBUTOR Ate Eskola) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Boris Carvajal) + $(D_CONTRIBUTOR Brian Callahan) + $(D_CONTRIBUTOR Cameron Ross) + $(D_CONTRIBUTOR Dante Broggi) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR Dmytro Katyukha) + $(D_CONTRIBUTOR Ernesto Castellotti) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jacob Carlborg) + $(D_CONTRIBUTOR Jan Jurzitza) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR Lucian Danescu) + $(D_CONTRIBUTOR Lucipetus) + $(D_CONTRIBUTOR Luís Ferreira) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR mhh) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Quirin F. Schroll) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Robert burner Schadek) + $(D_CONTRIBUTOR Teodor Dutu) + $(D_CONTRIBUTOR Tim Schendekehl) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.105.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.105.1.dd b/changelog/2.105.1.dd new file mode 100644 index 0000000000..85fbca47ad --- /dev/null +++ b/changelog/2.105.1.dd @@ -0,0 +1,80 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 01, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 1 major change and 9 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 10 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.enum-function,A function with enum storage class is now deprecated, not an error)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.enum-function,A function with enum storage class is now deprecated, not an error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.enum-function.dd) +$(P +The error was introduced in 2.105.0. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 24066): __traits$(LPAREN)isAbstractClass$(RPAREN) causes a segfault when passed an opaque class) +$(LI $(BUGZILLA 24078): [REG] crash related to concatenation) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 24065): __traits$(LPAREN)getTargetInfo$(RPAREN) causes a segfault when passed a non value) +$(LI $(BUGZILLA 24070): Opaque struct with nested definition when taking pointer segfaults) +$(LI $(BUGZILLA 24088): A nested function that returns a tuple that is written with short syntax function does not want to compile.) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 24064): Cannot chain$(LPAREN)$(RPAREN) array and immutable Nullable) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 24083): Int128.opCmp's behavior with negative numbers is inconsistent with Int128.opEquals) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 24079): core.sys.windows.winnt.IMAGE_FIRST_SECTION returns bad pointer) +$(LI $(BUGZILLA 24106): core.stdc.math provides an implementation of modfl for uClibc that only works when real and double are the same size) +) +) +$(D_CONTRIBUTORS_HEADER 10) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR mhh) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Teodor Dutu) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.105.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.105.2.dd b/changelog/2.105.2.dd new file mode 100644 index 0000000000..6c82a3d303 --- /dev/null +++ b/changelog/2.105.2.dd @@ -0,0 +1,47 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Sep 15, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 6 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 4 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 24109): [REG2.103] 'need this' when invoking outer method from inner method) +$(LI $(BUGZILLA 24110): [REG2.104] Array comparison lowering apparently not handled properly in __traits$(LPAREN)compiles$(RPAREN)) +$(LI $(BUGZILLA 24118): ICE / regression from 2.103.1 - segfault on CTFE only code in 2.104.2 and 2.105.0) +$(LI $(BUGZILLA 24144): [REG2.105] Silent file name index overflow) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 24139): 'this' corruption in extern$(LPAREN)C++$(RPAREN) dtor when destructing via TypeInfo_Struct) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 24140): Int128.opBinary [+-*/%&|^] with negative long arguments gives wrong answers) +) +) +$(D_CONTRIBUTORS_HEADER 4) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Razvan Nitu) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.105.2 + TITLE=Change Log: $(VER) diff --git a/changelog/2.105.3.dd b/changelog/2.105.3.dd new file mode 100644 index 0000000000..1351081bc9 --- /dev/null +++ b/changelog/2.105.3.dd @@ -0,0 +1,42 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Nov 01, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 4 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 4 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 24171): [REG 2.100] Segfault compiling an empty ddoc file) +$(LI $(BUGZILLA 24188): ICE $(LPAREN)Illegal instruction$(RPAREN) with missing imported symbol) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 23686): template instance reused with default alias arg) +$(LI $(BUGZILLA 23865): duplicate alias not detected) +) +) +$(D_CONTRIBUTORS_HEADER 4) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Kinkelin) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.105.3 + TITLE=Change Log: $(VER) diff --git a/changelog/2.106.0.dd b/changelog/2.106.0.dd new file mode 100644 index 0000000000..5d60709e77 --- /dev/null +++ b/changelog/2.106.0.dd @@ -0,0 +1,528 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Dec 01, 2023, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 17 major changes and 65 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 33 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.catch-immutable,Catch clause must take only `const` or mutable exceptions)) +$(LI $(RELATIVE_LINK2 dmd.dtoh-improvements,Improvements for the C++ header generation)) +$(LI $(RELATIVE_LINK2 dmd.enum-function,A function with enum storage class is now deprecated, not an error)) +$(LI $(RELATIVE_LINK2 dmd.fix24084,Add -nothrow Switch to Compiler)) +$(LI $(RELATIVE_LINK2 dmd.intel-cet-ibt-protection,Added support for Intel CET (Control-flow Enforcement Technology) IBT (Indirect Branch Tracking) protection)) +$(LI $(RELATIVE_LINK2 dmd.scope-ctor-error,Creating a `scope` class instance with a non-scope constructor is `@system` only with DIP1000)) +$(LI $(RELATIVE_LINK2 dmd.shared-static-ctor-const,Global `const` variables can no longer be initialized from a non-shared static constructor)) +$(LI $(RELATIVE_LINK2 dmd.static-assoc-array,Global variables can now be initialized with Associative Arrays)) +$(LI $(RELATIVE_LINK2 dmd.template-_d_newarrayT,`_d_newarray{U,T,iT}` are converted to templates)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 druntime.gc-collect-safe,4 `core.memory.GC` functions have been marked `@safe`)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 PR8804,Undo etc.c.odbc deprecation and enable usage on non-Windows systems)) +$(LI $(RELATIVE_LINK2 is_input_range_element,isInputRange now takes an optional element type.)) +$(LI $(RELATIVE_LINK2 unshared,Add Unshared to std.traits.)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 deep,Added `--deep=` switch to dub build)) +$(LI $(RELATIVE_LINK2 describe-configs,Added `default-config`, `configs`, `default-build`, `builds` data to dub describe)) +$(LI $(RELATIVE_LINK2 init_license,Dub init now has a select menu for package format and license)) +$(LI $(RELATIVE_LINK2 recipefile,Added `--recipe=` switch to DUB)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.catch-immutable,Catch clause must take only `const` or mutable exceptions) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.catch-immutable.dd) +$(P +In 2.104, throwing qualified types was +[deprecated](https://dlang.org/changelog/2.104.0.html#dmd.throw-qualifier). +) + +$(P +It is also unsafe to catch an exception as `immutable`, `inout` or `shared`. +This is because the exception may still be accessible through another +mutable or non-shared reference. Catching an exception with those qualifiers +is now deprecated. +) + +--- +auto e = new Exception("first"); +try { + throw e; +} catch(immutable Exception ie) { // now an error + e.msg = "second"; + assert(ie.msg == "first"); // would fail +} +--- +) + +$(LI $(LNAME2 dmd.dtoh-improvements,Improvements for the C++ header generation) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.dtoh-improvements.dd) +$(P +The following features/bugfixes/improvements were implemented for the +experimental C++ header generator: +) + +$(P +- Static variables used in a default argument context are now emitted using + their fully qualified name. +) + +$(P +Note: The header generator is still considered experimental, so please submit + any bugs encountered to [the bug tracker](https://issues.dlang.org). +) +) + +$(LI $(LNAME2 dmd.enum-function,A function with enum storage class is now deprecated, not an error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.enum-function.dd) +$(P +The error was introduced in 2.105.0. +) +) + +$(LI $(LNAME2 dmd.fix24084,Add -nothrow Switch to Compiler) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.fix24084.dd) +$(P +dmd itself (and presumably others) do not throw Exceptions, preferring other methods +for dealing with errors. There is a cost, however, in supporting Exceptions even when +they are never thrown. The cost is in adding stack unwinders for things like RAII +objects, and preventing numerous optimizations across try-catch boundaries. +) + +$(P +Adding `nothrow` to all the code in a project turns out to be an inordinate amount of +work if the program is large. Putting `nothrow:` at the top of the module doesn't +influence the status for member functions in a class or struct, the `nothrow:` +will have to be repeated for each class/struct. +) + +$(P +Adding the -nothrow switch to the compiler causes the stack unwinders to not be added +and enables the optimizations. This capability is already there for -betterC code, +this would just enable it for regular D code. +) + +$(P +The switch does not affect semantic analysis, just the code generation. Name mangling +is not affected. +) + +$(P +The switch is useful for determining what effect exception handling has on an executable's +size and performance in non-throwing code. +) +) + +$(LI $(LNAME2 dmd.intel-cet-ibt-protection,Added support for Intel CET (Control-flow Enforcement Technology) IBT (Indirect Branch Tracking) protection) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.intel-cet-ibt-protection.dd) +$(P +CET is a technology that is useful for preventing an attacker from redirecting a program's control flow, +specifically IBT prevents an attacker from causing an indirect branch to go to an unintended place. +) + +$(P +Intel IBT expects the compiler to emit special instructions (`endbr32` and `endbr64`) which in older processors +that do not support IBT are equivalent to `nop` instructions, consequently a program compiled with active IBT +will be compatible on any x86 processor and the protection will be opportunistically active on supported processors. +) + +$(P +To enable Intel IBT protection in DMD you need to pass the `-fIBT` flag to the compiler, consequently the compiler +will manage the emission of instructions for IBT by itself. +Be careful when using inline assembly, the compiler will not automatically handle IBT inside an inline assembly. +) + +$(P +To find out within a D program whether IBT has been activated or not use the traits getTargetInfo as follows: +) + +--- +// IBT active +static assert(__traits(getTargetInfo, "CET") == 1); // CET == 1 if IBT is active + +// IBT not active +static assert(__traits(getTargetInfo, "CET") == 0); // CET == 0 if IBT is not active +--- +) + +$(LI $(LNAME2 dmd.scope-ctor-error,Creating a `scope` class instance with a non-scope constructor is `@system` only with DIP1000) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.scope-ctor-error.dd) +$(P +The fix for [issue 23145](https://issues.dlang.org/show_bug.cgi?id=23145) broke existing code, so it's put behind `-preview=DIP1000` now, just like other `scope` related errors. +) +) + +$(LI $(LNAME2 dmd.shared-static-ctor-const,Global `const` variables can no longer be initialized from a non-shared static constructor) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.shared-static-ctor-const.dd) +$(P +Just like `immutable` data, global `const` data is not placed in Thread Local Storage (TLS), so initializing it in a thread-local static constructor allows you to violate `const`: +see [issue 24056](https://issues.dlang.org/show_bug.cgi?id=24056) for details. +Doing this will now result in a deprecation: +) + +--- +int x; +const int y; +immutable int z; + +static this() +{ + x = 1; + y = 2; // Deprecation: cannot modify const variable + z = 3; // Error: cannot modify immutable variable (same as before) +} +--- + +$(P +As a corrective action, move the initialization to a shared static constructor: +) + +--- +const int y; + +shared static this() +{ + y = 4; // OK +} +--- +) + +$(LI $(LNAME2 dmd.static-assoc-array,Global variables can now be initialized with Associative Arrays) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.static-assoc-array.dd) +$(P +Formerly, module constructors or `enum` had to be used to initialize global variables with Associtive Arrays. +By internally lowering to Steven Schveighoffer's [newaa](https://github.com/schveiguy/newaa/blob/master/source/schlib/newaa.d) struct implementation, Associative Arrays can now be used directly. +) + +--- +immutable string[string] table = ["key": "value"]; + +void main() +{ + assert(table["key"] == "value"); +} +--- + +$(P +When the key/value types have `toHash`, `opEquals` or `~this` defined, they must be callable at compile time. +An `if (!__ctfe)` branch can be used to make a destructor only run at run time. +Future enhancements may obviate the need for this workaround. +) +) + +$(LI $(LNAME2 dmd.template-_d_newarrayT,`_d_newarray{U,T,iT}` are converted to templates) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.template-_d_newarrayT.dd) +$(P +The template `_d_newarrayT` now uses DBI to check what type of initialiser is required by the type of the elements in the array. +Thus it replaces both `_d_newarrayT` and `_d_newarrayiT`. +) + +$(P +`_d_newarrayU` is the generic implementation of both of the above hooks and just allocates the array. +It hasn't been incorporated into `_d_newarrayT` because it is used by `dup`. +Currently `dup` is still using the non-template `_d_newarrayU`. +A future PR will update `dup` to use the new template. +) + +$(P +Now the compiler performs the following lowering: +) + +--- +S[] s = new S[10] + +// is now lowered to: +S[] s = _d_newarrayT!S(10); +--- + +$(P +This change adds the new templates to `core.internal.array.construction`. +In addition, it implements template `__arrayClearPad`, `__arrayAlloc`, `__arrayStart` and `__setArrayAllocLength` in `core.internal.array.utils`. +`__arrayClearPad` and `__arrayStart` were also removed from `rt.lifetime`. +The others can't be removed yet because they receive a `TypeInfo` argument and are called by other hooks in `rt.lifetime`. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 druntime.gc-collect-safe,4 `core.memory.GC` functions have been marked `@safe`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.gc-collect-safe.dd) +$(P +* `GC.enable` +* `GC.disable` +* `GC.collect` +* `GC.minimize` +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 PR8804,Undo etc.c.odbc deprecation and enable usage on non-Windows systems) +$(CHANGELOG_SOURCE_FILE phobos, changelog/PR8804.dd) +$(P +Previously, the etc.c.odbc bindings were deprecated and forwarded the core.sys.windows versions of the bindings via public import. However, ODBC is supported on all major platforms and the machine translated MinGW bindings in core.sys.windows have version(Windows) specified which results in being unable to use those bindings on non-Windows platforms. The bindings have been returned to etc.c.odbc, undeprecated, and support for non-Windows platforms enabled. +) +) + +$(LI $(LNAME2 is_input_range_element,isInputRange now takes an optional element type.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/is_input_range_element.dd) +$(P +isInputRange now has an optional 2nd template parameter that defaults +to void. If not void, it only evaluates to true if the range's element +type is the same type as this extra argument, modulo const. For +instance, `isInputRange!(int[], const(int))` is true, but +`isInputRange!(int[], string)` is false. +) +) + +$(LI $(LNAME2 unshared,Add Unshared to std.traits.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/unshared.dd) +$(P +`Unshared` is the `shared` equivalent of `Unconst`. It strips off the outer +layer of `shared` from a type. e.g. +) + +``` + static assert(Unshared!(shared int) == int); + static assert(Unshared!(shared(int[])) == shared(int)[]); +``` + +$(P +So, `Unconst` strips off the outer layer of `const`, `immutable`, and `inout`; +`Unshared` strips off the outer layer of `shared`; and `Unqual` strips off all +qualifiers from the outer layer of a type. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 deep,Added `--deep=` switch to dub build) +$(CHANGELOG_SOURCE_FILE dub, changelog/deep.dd) +$(P +By specifying this flag, you can now build all the dependencies +of a staticLibrary. The default behavior is to only build the +library located in the root directory of the dub configuration +file. This allows better integration with other build systems +which require the libraries to be built upfront. +) + +``` +dub build --deep +``` + +$(P +If a staticLibrary A depends on staticLibrary B, and the --deep +flag is specified, dub will output both the A and B libraries. +) +) + +$(LI $(LNAME2 describe-configs,Added `default-config`, `configs`, `default-build`, `builds` data to dub describe) +$(CHANGELOG_SOURCE_FILE dub, changelog/describe-configs.dd) +$(P +- `default-config` will be a single string that is the `--config` configuration that DUB would pick when not provided any configuration such as in a simple `dub build` call +- `configs` is a list of all available configurations (default generated application and/or library, or the manually specified ones in the recipe) +- `default-build` will be a single string that is the `--build` build type that DUB would pick when not provided any (currently always "debug") +- `builds` is a list of all available build types (built-in + custom defined) +) +) + +$(LI $(LNAME2 init_license,Dub init now has a select menu for package format and license) +$(CHANGELOG_SOURCE_FILE dub, changelog/init_license.dd) +$(P +When creating a package using `dub init` you are now prompted to select a license for the package. +) +) + +$(LI $(LNAME2 recipefile,Added `--recipe=` switch to DUB) +$(CHANGELOG_SOURCE_FILE dub, changelog/recipefile.dd) +$(P +You can now override which file is used as recipe, instead of the default +`dub.sdl` and `dub.json`. This means you can define multiple dub.json files for +local development, for example for special local-machine-only operations, and +select which one to use over the CLI. +) + +``` +dub build --recipe=custom-dub.json +``` + +$(P +This can also be used to pick dub.sdl over dub.json, if both of them exist in +the same directory. Although this is discouraged for interoperability with other +DUB-supporting tools and general confusion for users. Both existing at the same +time may also become an error when this switch is not specified in the future. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 20655): [REG: 2.072] attribute inference accepts unsafe union access as @safe) +$(LI $(BUGZILLA 24066): __traits$(LPAREN)isAbstractClass$(RPAREN) causes a segfault when passed an opaque class) +$(LI $(BUGZILLA 24159): BetterC: appending to dynamic arrays no longer errors at compile time) +$(LI $(BUGZILLA 24184): [REG 2.103] Segmentation fault accessing variable with align$(LPAREN)N$(RPAREN) > platform stack alignment) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 8662): Better error for duplicate labels inside static foreach body) +$(LI $(BUGZILLA 11455): Overriding template methods should raise a compile error) +$(LI $(BUGZILLA 14835): Constant folding should not affect front end flow analysis) +$(LI $(BUGZILLA 18578): First enum value assigned 0 instead of EnumBaseType.init) +$(LI $(BUGZILLA 19460): C style cast error has wrong line number for functions) +$(LI $(BUGZILLA 22682): `pragma$(LPAREN)mangle$(RPAREN)` does not work for nested functions) +$(LI $(BUGZILLA 23103): static initialization of associative arrays is not implemented) +$(LI $(BUGZILLA 23522): Error message when enum type is not integral and a value lacks an initializer) +$(LI $(BUGZILLA 23733): Can't use template type parameter as type of alias parameter) +$(LI $(BUGZILLA 24036): assert message in CTFE becomes `['m', 'e', 's', 's', 'a', 'g', 'e'][0..7]` if produced using std.format.format) +$(LI $(BUGZILLA 24051): Safety attrib inference of enum/immut/const decls inconsistent with mutable static variable decls) +$(LI $(BUGZILLA 24054): return expression expected on noreturn function) +$(LI $(BUGZILLA 24055): is$(LPAREN)x == __parameters$(RPAREN) does not work on function pointer/delegate types) +$(LI $(BUGZILLA 24056): const uninitialized data at module scope is not in TLS) +$(LI $(BUGZILLA 24065): __traits$(LPAREN)getTargetInfo$(RPAREN) causes a segfault when passed a non value) +$(LI $(BUGZILLA 24070): Opaque struct with nested definition when taking pointer segfaults) +$(LI $(BUGZILLA 24071): When enum has typedef integer constants do not have types determined correctly) +$(LI $(BUGZILLA 24072): cast$(LPAREN)__vector$(RPAREN) array literal incorrectly triggers GC error) +$(LI $(BUGZILLA 24105): Dip1000 C variadics not marked as scope should not accept scope arguments) +$(LI $(BUGZILLA 24107): The error for exceeding the CTFE recursion limit bypasses speculative compilation.) +$(LI $(BUGZILLA 24108): dmd -H and -X fail when given an importC module) +$(LI $(BUGZILLA 24117): noreturn can be used as expression) +$(LI $(BUGZILLA 24121): ImportC: typedef enum fails to compile when generating .di file) +$(LI $(BUGZILLA 24129): ImportC: MS-Link cannot handle multiple COMDATs with the same name) +$(LI $(BUGZILLA 24130): ImportC: Windows headers use inline asm with different syntax) +$(LI $(BUGZILLA 24133): printf format checking of %n allows writing to const pointers) +$(LI $(BUGZILLA 24154): ImportC: useless expression parsed as invalid variable declaration) +$(LI $(BUGZILLA 24156): ImportC: Apple uses __signed as a keyword) +$(LI $(BUGZILLA 24168): Corrupted if TLS values are passed in ref parameters when compiling with -fPIE) +$(LI $(BUGZILLA 24174): [CTFE] goto within with statements & catch blocks cause a infinite loop) +$(LI $(BUGZILLA 24181): reading double parameter from RCX rather than XMM1) +$(LI $(BUGZILLA 24187): ImportC: _Float32 not defined) +$(LI $(BUGZILLA 24193): Incorrect size of unions with bit fields) +$(LI $(BUGZILLA 24199): ImportC: generated .di file uses struct keyword when referring to a type) +$(LI $(BUGZILLA 24208): [DIP1000] Scope pointer can escape via non-scope parameter of pure nested function) +$(LI $(BUGZILLA 24209): static aa initialization of static function variable ICE) +$(LI $(BUGZILLA 24212): [DIP1000] Scope pointer can escape via non-scope parameter of pure virtual function) +$(LI $(BUGZILLA 24213): [DIP1000] Scope pointer can escape via non-scope parameter of pure delegate) +$(LI $(BUGZILLA 24257): ImportC: ICE on accessing last _Bool bitfield) +$(LI $(BUGZILLA 24262): Assert error with bit fields) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 5445): DMD does not look for ".dmd.conf" in HOME dir) +$(LI $(BUGZILLA 10532): Silence some unreachable statement warnings when in a static foreach) +$(LI $(BUGZILLA 11070): Allow declaration statement in a switch expression) +$(LI $(BUGZILLA 15752): Diagnostic: Better Error Message for Assigning Incorrect AA Empty Value) +$(LI $(BUGZILLA 20522): Spurious statement unreachable warning caused by undefined variable) +$(LI $(BUGZILLA 21520): dmd does not honor the NO_COLOR environment variable) +$(LI $(BUGZILLA 21852): diagnostic: One-liner errors with formatted Loc should print context when -verrors=context) +$(LI $(BUGZILLA 23958): ImportC: undefined identifier `__builtin__sprintf_chk`) +$(LI $(BUGZILLA 24060): Improve "Cannot create instance of abstract class" error) +$(LI $(BUGZILLA 24084): Add -nothrow Switch to Compiler) +$(LI $(BUGZILLA 24173): ImportC: add Microsoft iNN integer literal suffixes) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 24267): [REG 2.106 beta] Grapheme cannot be used as an AA key) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 24049): std.conv.to: string to enum conversion is not documented) +$(LI $(BUGZILLA 24207): std.parallelism: AbstractTask private data is inadvertently available) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 24082): add Int128.toString that supports std.format) +$(LI $(BUGZILLA 24142): Allow casting Int128 to integral and floating types) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 24079): core.sys.windows.winnt.IMAGE_FIRST_SECTION returns bad pointer) +$(LI $(BUGZILLA 24123): More importc definitions are needed for macOS) +$(LI $(BUGZILLA 24230): Infinite loop in core.cpuid.getCpuInfo0B in Solaris/x86 kernel zone) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 3396): Compiler accepts call of superclass abstract method with no implementation) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 24012): [spec/cpp_interface] _d_dynamicArray generated by -HC not documented) +) +) +$(D_CONTRIBUTORS_HEADER 33) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR Adam Wilson) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Dante Broggi) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR Ernesto Castellotti) + $(D_CONTRIBUTOR H. S. Teoh) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Imperatorn) + $(D_CONTRIBUTOR Jan Jurzitza) + $(D_CONTRIBUTOR Jeremy) + $(D_CONTRIBUTOR Jonathan M Davis) + $(D_CONTRIBUTOR liushuyu) + $(D_CONTRIBUTOR Mai-Lapyst) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Nathan Sashihara) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Piotr Fusik) + $(D_CONTRIBUTOR Prajwal S N) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Temtaime) + $(D_CONTRIBUTOR Teodor Dutu) + $(D_CONTRIBUTOR Tim Schendekehl) + $(D_CONTRIBUTOR tjs137) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.106.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.106.1.dd b/changelog/2.106.1.dd new file mode 100644 index 0000000000..5f5393eba5 --- /dev/null +++ b/changelog/2.106.1.dd @@ -0,0 +1,42 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jan 01, 2024, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 4 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 4 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 22212): dmd version has -dirty suffix on windows) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 22483): DMD generates invalid string sections that work by coincidence) +$(LI $(BUGZILLA 24281): Segfault with missing field after named argument) +$(LI $(BUGZILLA 24283): [SIMD][CODEGEN] Bad codegen with and not + AVX2 registers) +) +) +$(D_CONTRIBUTORS_HEADER 4) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Siarhei Siamashka) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.106.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.107.0.dd b/changelog/2.107.0.dd new file mode 100644 index 0000000000..99282bc1d6 --- /dev/null +++ b/changelog/2.107.0.dd @@ -0,0 +1,470 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Feb 01, 2024, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 10 major changes and 61 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 37 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.assert-string,A string literal as an assert condition is deprecated)) +$(LI $(RELATIVE_LINK2 dmd.makefiles,Makefiles cleanup for the compiler)) +$(LI $(RELATIVE_LINK2 dmd.pragma,Unrecognized pragmas are no longer an error, but instead simply ignored)) +$(LI $(RELATIVE_LINK2 dmd.standalone-attribute,Added `@standalone` for module constructors)) +$(LI $(RELATIVE_LINK2 dmd.template-_d_newarratmT,`_d_newarray{mTX,miTX,OpT}` are converted to a single template: `_d_newarraymTX`)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 druntime.coreatomic,Using an invalid MemoryOrder for `core.atomic` operations are now rejected at compile time)) +$(LI $(RELATIVE_LINK2 druntime.makefiles,Makefiles cleanup for druntime)) +$(LI $(RELATIVE_LINK2 druntime.stdatomic,New addition of the C stdatomic header implemented in D)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 is_forward_range_element,isForwardRange now takes an optional element type.)) +$(LI $(RELATIVE_LINK2 makefiles,Makefiles cleanup)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.assert-string,A string literal as an assert condition is deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.assert-string.dd) +$(P +Boolean evaluation of a string literal could happen unintentionally +e.g. when an `assert(0, "message")` was meant and the `0` was missing. +) + +```d +assert("unexpected runtime condition"); +static assert("unhandled case for `", T, "`"); +``` + +$(P +The 2 asserts would silently always have no effect. +Now these cases will be detected with deprecation messages. +If the original behaviour was actually intended, use `expr !is null` instead: +) + +```d +assert("" !is null); +static assert("" !is null); +``` +) + +$(LI $(LNAME2 dmd.makefiles,Makefiles cleanup for the compiler) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.makefiles.dd) +$(P +The Makefiles for building the compiler (`compiler/src/{posix,win32,win64}.mak`) have been deprecated for a while, and finally removed. Please use the `compiler/src/build.d` tool directly now (see [docs](https://github.com/dlang/dmd/tree/master/compiler/src#building-the-compiler)), or build compiler and druntime in one step via the top-level Makefile in the repo root, e.g., for an optimized build using an LDC host compiler: `make -jN HOST_DMD=ldmd2 ENABLE_RELEASE=1 ENABLE_LTO=1` +) + +$(P +The top-level Makefile has been renamed from `posix.mak` to `Makefile` (with a deprecated `posix.mak` forwarder). The semantics of some targets have slightly changed, e.g., druntime is included in the `test`, `install` and `clean` targets now. +) + +$(P +The legacy `src/posix.mak` file still exists, but forwards to the top-level Makefile. So e.g. the default `all` target now includes druntime too, not just the compiler. +) + +$(P +Top-level `win{32,64}.mak` and legacy `src/win{32,64}.mak` files (for DigitalMars make) have been removed altogether. The generic top-level `Makefile` works on Windows too - with a GNU make (and a git installation providing bash and GNU tools). +) + +$(P +Long-deprecated `compiler/test/Makefile` has also been removed; use `compiler/test/run.d` directly instead (see [docs](https://github.com/dlang/dmd/tree/master/compiler/test#quick-guide)). +) +) + +$(LI $(LNAME2 dmd.pragma,Unrecognized pragmas are no longer an error, but instead simply ignored) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.pragma.dd) +$(P +Previously, unrecognized pragmas would issue a hard error unless you used the `-ignore` dmd switch. Now, they are always ignored and the `-ignore` dmd switch is ignored. +) +) + +$(LI $(LNAME2 dmd.standalone-attribute,Added `@standalone` for module constructors) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.standalone-attribute.dd) +$(P +When two modules import each other and both have module constructors, +druntime would throw an error because it can't determine which to run first. +) + +$(P +This could be circumvented by using `pragma(crt_constructor)` instead, but in C runtime constructors, druntime isn't initialized. +Therefore the Garbage Collector can't be used in such constructors. +) + +$(P +`@standalone` is a new attribute that can be used to mark module constructors that run after druntime has been initialized, +but do not depend on any other module constructors being run before it, so it will not cause a cyclic dependency error. +It must be imported from `core.attribute`. +) + +$(P +The compiler doesn't verify that the module constructor truly doesn't depend on other variables being initialized, so it must be enforced manually. +Because of this, they must be marked `@system` or `@trusted`. +) + +--- +import core.attribute : standalone; + +immutable int* x; + +@standalone @system shared static this() +{ + x = new int(10); +} + +void main() +{ + assert(*x == 10); +} +--- + +$(P +If possible, prefer to solve cyclic dependency errors by putting the offending module constructors into their own smaller modules instead of using `@standalone`. +) +) + +$(LI $(LNAME2 dmd.template-_d_newarratmT,`_d_newarray{mTX,miTX,OpT}` are converted to a single template: `_d_newarraymTX`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.template-_d_newarratmT.dd) +$(P +The template `_d_newarraymTX` now uses DBI to check what type of initialiser is required by the type of the elements in the array. +Thus it replaces both `_d_newarraymTX` and `_d_newarraymiTX`. +) + +$(P +`_d_newarrayOpT` was the generic implementation of both of the above hooks. +It first allocated the "outer" arrays as pointer arrays and then it called either `_d_newarrayT` or `_d_newarrayiT`, to allocate initialise the "inner" 1-dimensional arrays accordingly. +Now this is no longer needed due to the merge between `_d_newarraymTX` and `_d_newarraymiTX`. +) + +$(P +Now the compiler performs the following lowering: +) + +--- +S[][] s = new S[][](2, 3) + +// is now lowered to: +S[] s = _d_newarraymTX!(S[][], S)([2, 3]); +--- + +$(P +This change adds the new template to `core.internal.array.construction`. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 druntime.coreatomic,Using an invalid MemoryOrder for `core.atomic` operations are now rejected at compile time) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.coreatomic.dd) +$(P +The following `core.atomic` functions have become more restrictive: +) + +$(P +1. `atomicLoad` and `atomicStore` now reject being instantiated with the +argument `MemoryOrder.acq_rel`. Previously `atomicLoad` and `atomicStore` only +rejected `MemoryOrder.rel` and `MemoryOrder.acq` respectively. +) + +$(P +In most cases, code that previously used `MemoryOrder.acq_rel` should switch to +use `MemoryOrder.seq` instead. +) + +--- +// Error: +atomicLoad!(MemoryOrder.acq_rel)(src); +atomicStore!(MemoryOrder.acq_rel)(dest, value); + +// Corrective action: +atomicLoad!(MemoryOrder.seq)(src); +atomicStore!(MemoryOrder.seq)(dest, value); + +// Or: +atomicLoad(src); +atomicStore(dest, value); +--- + +$(P +2. `atomicExchange` now rejects being instantiated with the argument +`MemoryOrder.acq`. +) + +$(P +In most cases, code that previously used `MemoryOrder.acq` should switch to use +`MemoryOrder.seq` instead. +) + +--- +// Error: +atomicExchange!(MemoryOrder.acq)(dest, value); + +// Corrective action: +atomicExchange!(MemoryOrder.seq)(dest, value); + +// Or: +atomicExchange(dest, value); +--- + +$(P +3. `atomicCompareExchangeWeak` and `atomicCompareExchangeStrong` now reject +being instantiated when the second `fail` argument is `MemoryOrder.rel` or +`MemoryOrder.acq_rel`. +) + +$(P +In most cases, code that previously used either of these should switch to use +`MemoryOrder.raw` instead. +) + +--- +// Error: +atomicExchangeWeak!(MemoryOrder.rel, MemoryOrder.rel)(dest, compare, value); +atomicExchangeWeakNoResult!(MemoryOrder.acq_rel, MemoryOrder.acq_rel)(dest, compare, value); +atomicExchangeStrong!(MemoryOrder.acq, MemoryOrder.rel)(dest, compare, value); +atomicExchangeStrongNoResult!(MemoryOrder.seq, MemoryOrder.acq_rel)(dest, compare, value); + +// Corrective action: +atomicExchangeWeak!(MemoryOrder.rel, MemoryOrder.raw)(dest, compare, value); +atomicExchangeWeakNoResult!(MemoryOrder.acq_rel, MemoryOrder.raw)(dest, compare, value); +atomicExchangeStrong!(MemoryOrder.acq, MemoryOrder.raw)(dest, compare, value); +atomicExchangeStrongNoResult!(MemoryOrder.seq, MemoryOrder.raw)(dest, compare, value); +--- + +$(P +4. `atomicCompareExchangeWeak` and `atomicCompareExchangeStrong` additionally +now reject being instantiated when the second `fail` argument has a greater +value than its first `succ` argument. +) + +$(P +In most cases, code that violates this contract should use the same MemoryOrder +for both `succ` and `fail` arguments. +) + +--- +// Error: +atomicExchangeWeak!(MemoryOrder.raw)(dest, compare, value); +atomicExchangeStrong!(MemoryOrder.acq, MemoryOrder.seq)(dest, compare, value); + +// Corrective action: +atomicExchangeWeak!(MemoryOrder.raw, MemoryOrder.raw)(dest, compare, value); +atomicExchangeStrong!(MemoryOrder.acq, MemoryOrder.acq)(dest, compare, value); +--- +) + +$(LI $(LNAME2 druntime.makefiles,Makefiles cleanup for druntime) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.makefiles.dd) +$(P +The `{posix,win32,win64}.mak` Makefiles have been merged to a generic `Makefile` (including the ones in `druntime/test/`). `posix.mak` is kept as a deprecated forwarder for now. +) + +$(P +On Windows, you can/need to use the generic Makefile too - with a GNU make (and a git installation providing bash and GNU tools). Windows devs can finally exploit parallelism via `-j`! You may download a prebuilt zipped .exe from https://github.com/dlang/dmd/releases/download/nightly/gnumake-4.4-win64.zip. +) +) + +$(LI $(LNAME2 druntime.stdatomic,New addition of the C stdatomic header implemented in D) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.stdatomic.dd) +$(P +The goal of this module is to assist in porting efforts for code from C to D and to give as close as possible same code generation as the system C compiler counterpart. +) + +$(P +If you do not care about code generation quality should the aliases to the function names not exist, you may append ``_impl`` to get at the implementation. +) + +$(P +If the code generation provided by a given function is not on-par to the system C compiler and it matters to your use case, please report it as a bug. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 is_forward_range_element,isForwardRange now takes an optional element type.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/is_forward_range_element.dd) +$(P +isForwardRange now has an optional 2nd template parameter that defaults +to void. If not void, it only evaluates to true if the range's element +type is the same type as this extra argument, modulo const. For +instance, `isForwardRange!(int[], const(int))` is true, but +`isForwardRange!(int[], string)` is false. +) +) + +$(LI $(LNAME2 makefiles,Makefiles cleanup) +$(CHANGELOG_SOURCE_FILE phobos, changelog/makefiles.dd) +$(P +The `{posix,win32,win64}.mak` Makefiles have been merged to a generic `Makefile`. `posix.mak` is kept as a deprecated forwarder for now. +) + +$(P +On Windows, you can/need to use the generic Makefile too - with a GNU make (and a git installation providing bash and GNU tools). Windows devs can finally exploit parallelism via `-j`! You may download a prebuilt zipped .exe from https://github.com/dlang/dmd/releases/download/nightly/gnumake-4.4-win64.zip. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 24266): ImportC: struct initializer entry gets ignored) +$(LI $(BUGZILLA 24274): [REG master] ImportC: unrecognized C initializer with array in struct) +$(LI $(BUGZILLA 24295): [betterC] ICE with new int[]) +$(LI $(BUGZILLA 24301): [REG 2.100] Misleading error message when passing non-copyable struct by value in @safe code) +$(LI $(BUGZILLA 24338): Cannot concatenate dynamic arrays of enum type with static array base type) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 16357): cast$(LPAREN)T[]$(RPAREN)[x] casts x to T instead of [x] to T[]) +$(LI $(BUGZILLA 20339): isPOD returns true if sizeof is accessed inside struct declaration) +$(LI $(BUGZILLA 20369): shadowed variable in foreach loop always considered "foreach variable") +$(LI $(BUGZILLA 22216): Incomplete/incorrect error message for mutability overloads) +$(LI $(BUGZILLA 22905): gdb backtrace contains wrong location) +$(LI $(BUGZILLA 23411): ImportC: undefined identifier __builtin_nanf) +$(LI $(BUGZILLA 23713): compilable/testcstuff1.c:206:1: error: static assertion failed: sizeof$(LPAREN)u'a'$(RPAREN) == 4) +$(LI $(BUGZILLA 23714): compilable/testcstuff1.c:213:1: error: static assertion failed: u'ab' == 0x610062) +$(LI $(BUGZILLA 23972): class identity check is broken) +$(LI $(BUGZILLA 24031): ImportC: rejects nested C initializers) +$(LI $(BUGZILLA 24094): importC __declspec not working in front of declaration statement) +$(LI $(BUGZILLA 24200): ImportC: .di file collected macro conflicts with Special Token) +$(LI $(BUGZILLA 24224): __traits$(LPAREN)initSymbol$(RPAREN) treats aggregate-derived enum as base type) +$(LI $(BUGZILLA 24248): const constructor call with mutable target gives wrong error message) +$(LI $(BUGZILLA 24252): ci: Error: error writing file 'compilable\testcstuff3_0.obj') +$(LI $(BUGZILLA 24264): ImportC: inliner trips on _Bool return) +$(LI $(BUGZILLA 24276): ImportC: typedef aliases not emitted correctly in .di files) +$(LI $(BUGZILLA 24280): ImportC: forward reference error when compiling multiple files) +$(LI $(BUGZILLA 24281): Segfault with missing field after named argument) +$(LI $(BUGZILLA 24283): [SIMD][CODEGEN] Bad codegen with and not + AVX2 registers) +$(LI $(BUGZILLA 24292): Struct with destructor wrongly returned in register) +$(LI $(BUGZILLA 24303): anonymous struct problems when typedef'd in separate C files) +$(LI $(BUGZILLA 24304): __uint16_t, __uint32_t, __uint64_t are not recognized) +$(LI $(BUGZILLA 24306): ImportC: same name structs in separate C files interfere when compiled together) +$(LI $(BUGZILLA 24309): Memory allocation failed on Azure pipeline) +$(LI $(BUGZILLA 24311): Named enum with AA base type causes ICE) +$(LI $(BUGZILLA 24319): OpenBSD: Use correct type for file_time) +$(LI $(BUGZILLA 24326): ImportC: segfault on nameless enum translation with -H) +$(LI $(BUGZILLA 24340): Invalid export directives generated) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 14387): Disallow string literals as assert conditions) +$(LI $(BUGZILLA 23629): importC: Need to support code coverage analysis) +$(LI $(BUGZILLA 24069): ImportC does not parse function pointer as parameter without name) +$(LI $(BUGZILLA 24125): ImportC: vector type initializer not understood) +$(LI $(BUGZILLA 24155): ImportC: accept C23 default initializers) +$(LI $(BUGZILLA 24206): Can't alias a function type that returns a type with a TypeSuffix) +$(LI $(BUGZILLA 24238): Confusing "not an lvalue"error messages) +$(LI $(BUGZILLA 24247): Improve constructor not callable using $modifier object error) +$(LI $(BUGZILLA 24294): ImportC: unrecognized command line option -Wno-builtin-macro-redefined with gcc) +$(LI $(BUGZILLA 24297): ImportC incompatible with glibc _FORTIFY_SOURCE) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 24243): Can't format chain$(LPAREN)filter, filter$(RPAREN)) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 24151): std.container.array: Array!string$(LPAREN)""$(RPAREN) does not compile) +$(LI $(BUGZILLA 24215): std.traits.isBasicType!Enum should be false) +$(LI $(BUGZILLA 24278): std.math.abs promotes unsigned argument to 32 bits) +$(LI $(BUGZILLA 24342): T[][].until$(LPAREN)T[]$(RPAREN) breaks if sentinel is longer than 1.) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 11111): std.algorithm.canFind should support Needles...) +$(LI $(BUGZILLA 24075): Can't use toChars with `ushort` or `ubyte`) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 4071): Missing support to share memory and objects between DLLs and executable) +$(LI $(BUGZILLA 24272): operations.arrayOp is forced @nogc nothrow pure) +$(LI $(BUGZILLA 24298): cpp_delete should check for null) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 20332): associative array clear function should be @safe) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 23712): ImportC: Unclear documentation of what type is inferred from integer literals $(LPAREN)type of 9223372036854775808 is undefined$(RPAREN)) +$(LI $(BUGZILLA 24239): dlang.org tests on CircleCI run out of memory) +$(LI $(BUGZILLA 24241): Spec disallows missing default arguments) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 24176): Parameters of opApply delegate don't have to be `ref`) +$(LI $(BUGZILLA 24177): Array literal can implicitly convert to an expected type) +$(LI $(BUGZILLA 24210): Function types are not documented) +) +) +$(D_CONTRIBUTORS_HEADER 37) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Basile Burg) + $(D_CONTRIBUTOR Brian Callahan) + $(D_CONTRIBUTOR Daniel Pflager) + $(D_CONTRIBUTOR Danil Sidoruk) + $(D_CONTRIBUTOR Denis Feklushkin) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR Feldwor) + $(D_CONTRIBUTOR HuskyNator) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR IchorDev) + $(D_CONTRIBUTOR Imperatorn) + $(D_CONTRIBUTOR imrying) + $(D_CONTRIBUTOR Jeremy) + $(D_CONTRIBUTOR jibal) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR mhh) + $(D_CONTRIBUTOR Mike Parker) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR richard (rikki) andrew cattermole) + $(D_CONTRIBUTOR ryuukk) + $(D_CONTRIBUTOR Sönke Ludwig) + $(D_CONTRIBUTOR Teodor Dutu) + $(D_CONTRIBUTOR Tim Schendekehl) + $(D_CONTRIBUTOR Timon Gehr) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR Yang Yujie) + $(D_CONTRIBUTOR Семён Марьясин) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.107.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.107.1.dd b/changelog/2.107.1.dd new file mode 100644 index 0000000000..ba338b9981 --- /dev/null +++ b/changelog/2.107.1.dd @@ -0,0 +1,55 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 01, 2024, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 15 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 6 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 20802): [REG2.088.0] Link failure with writefln) +$(LI $(BUGZILLA 24371): [REG 2.104] String array concatenation does not respect operator precedence) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 20297): ld: warning: no platform load command found for macOS) +$(LI $(BUGZILLA 21047): Linker error: GOT load reloc does not point to a movq instruction) +$(LI $(BUGZILLA 22556): Invalid GOT load reloc with -O on MacOS) +$(LI $(BUGZILLA 23517): dmd with -g flag fails to link on macOS with unaligned pointer) +$(LI $(BUGZILLA 24137): Link failure on macOS with symbol count from symbol table and dynamic symbol table differ) +$(LI $(BUGZILLA 24365): ICE when printing 'showCtfeContext' error) +$(LI $(BUGZILLA 24370): static array values in static AA initialise to dynamic arrays) +$(LI $(BUGZILLA 24399): Link failure on MacOS with address=0x0 points to section$(LPAREN)2$(RPAREN) with no content in config_a68_4c3.o) +$(LI $(BUGZILLA 24401): OSX: Linker error: GOT load reloc does not point to a movq instruction) +$(LI $(BUGZILLA 24402): OSX: Linker warning: pointer not aligned at __OBJC_PROTOCOL_$_Foo) +$(LI $(BUGZILLA 24407): OSX: ld: Assertion failed: $(LPAREN)slot < _sideTableBuffer.size$(LPAREN)$(RPAREN)$(RPAREN), function addAtom) +$(LI $(BUGZILLA 24409): DMD crash for CTFE in stompOverlappedFields) +$(LI $(BUGZILLA 24422): ImportC: ICE: Segfault in cparseFunctionDefinition) +) +) +$(D_CONTRIBUTORS_HEADER 6) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Teodor Dutu) + $(D_CONTRIBUTOR Tim Schendekehl) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.107.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.108.0.dd b/changelog/2.108.0.dd new file mode 100644 index 0000000000..d31fe0e72c --- /dev/null +++ b/changelog/2.108.0.dd @@ -0,0 +1,436 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 01, 2024, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 8 major changes and 36 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 36 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.classinfo,Added .nameSig field to TypeInfo_Class in object.d)) +$(LI $(RELATIVE_LINK2 dmd.default-init,Keywords like `__FILE__` are always evaluated at the call site)) +$(LI $(RELATIVE_LINK2 dmd.hexstring-cast,Hex strings now convert to integer arrays)) +$(LI $(RELATIVE_LINK2 dmd.ies,Add support for Interpolated Expression Sequences)) +$(LI $(RELATIVE_LINK2 dmd.named-arguments,Named arguments for functions have been implemented and documented)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 range_predicate_element,`isForwardRange`, `isBidirectionalRange`, and `isRandomAccessRange` now take an optional element type)) +$(LI $(RELATIVE_LINK2 upgrade-unicode,std.uni has been upgraded from Unicode 15.0.0 to 15.1.0)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 dub-fetch,The fetch command now supports multiple arguments, recursive fetch, and is project-aware)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.classinfo,Added .nameSig field to TypeInfo_Class in object.d) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.classinfo.dd) +$(P +This is a 16 byte md5 signature of the fully qualified name of the class. +It is used to compare two classes for equality, rather than comparing the +pointers with a fallback to doing a string compare on the name, which can +be rather slow. +) + +$(P +The result is both druntime and phobos will need to be recompiled to be +compatible with this change. Any libraries will need to be recompiled +as well. +) +) + +$(LI $(LNAME2 dmd.default-init,Keywords like `__FILE__` are always evaluated at the call site) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.default-init.dd) +$(P +Default arguments for functions can contain the keywords `__FILE__`, +`__FILE_FULL_PATH__`, `__MODULE__`, `__LINE__`, `__FUNCTION__` +and `__PRETTY_FUNCTION__`. They are now evaluated at the source location +of the calling function in more complex expressions as long as used in +an initializer, directly or not. Previously they had to be used directly +in the initializer to be evaluated at the call site. Here are some +examples, where more complex initializers are now evaluated at the +call site: +) + +--- +void func1(const(char)* file = __FILE__.ptr, size_t line = __LINE__) +{ + // This now prints the filename of the calling function. + // Previously it was the filename of func1 itself. + printf("%s:%zd\n", file, line); +} + +struct Loc +{ + string file; + size_t line; +} + +void func2(Loc loc = Loc(__FILE__, __LINE__)) +{ + // Variable loc now contains file and line of the calling function. + // Previously it was the location of func2. + writeln(loc.file, ":", loc.line); +} + +Loc defaultLoc(string file = __FILE__, size_t line = __LINE__) +{ + return Loc(file, line); +} + +void func3(Loc loc = defaultLoc) +{ + // Variable loc contains file and line of the calling function of + // func3 and not the location of func3 or defaultLoc. + writeln(loc.file, ":", loc.line); +} +--- +) + +$(LI $(LNAME2 dmd.hexstring-cast,Hex strings now convert to integer arrays) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.hexstring-cast.dd) +$(P +Hex strings are the most efficient way to embed binary data into source files. +However, they couldn't easily be used to initialize a `short[]`, `int[]` or `long[]` because re-interpret casting arrays is not allowed during CTFE. +Now, hex strings implicitly convert to all integer arrays. +A big endian byte order is assumed, consistent with how integer literals are written. +) + +--- +immutable uint[] data = x"AABBCCDD"; + +static assert(data[0] == 0xAABBCCDD); +--- + +$(P +Character postfixes can now also be used to explicitly set an element size of 2 or 4. +) + +--- +immutable ushort[] f = x"80 3F"w; +static assert(f[0] == 0x803F); + +immutable ubyte[] g = x"80 35"w; // error: size mismatch +--- + +$(P +Formerly, they would pad each byte with 1 or 3 zeros, which did not serve a purpose (See [Issue 24363](https://issues.dlang.org/show_bug.cgi?id=24363)). +) + +$(P +If the string's byte length is not a multiple of the target element size, it is an error: +) + +--- +immutable ushort[] e = x"AABBCC"w; // Error, 3 bytes is not a multiple of `ushort.sizeof` +--- +) + +$(LI $(LNAME2 dmd.ies,Add support for Interpolated Expression Sequences) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.ies.dd) +$(P +Interpolated Expression Sequences are a way to implement things like string interpolation in library code. Three forms of literals are added: +) + +``` +i"Content $(a + 4)" +i`Content $(a + 4)` +iq{Content $(a + 4)} +``` + +$(P +all provide the same thing: a tuple that can be passed to other functions, like `writeln` from `std.stdio` and `text` from `std.conv`: +) + +``` +int a = 6; +writeln(i"Content $(a + 4)"); // prints "Content 10" +``` + +$(P +You can also pass them to other functions which understand the types in the new `core.interpolation` module. Numerous examples can be found documentation of that module or in this repository: https://github.com/adamdruppe/interpolation-examples/ +) +) + +$(LI $(LNAME2 dmd.named-arguments,Named arguments for functions have been implemented and documented) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.named-arguments.dd) +$(P +When calling a function, arguments may be preceded with a parameter name for purposes of clarity and flexible ordering. +Consequently, default arguments need not be at the end of the parameter list anymore. +) + +--- +void createWindow(bool fullScreen = false, int width, int height, string title); + +void main() +{ + createWindow(title: "Skynet", width: 1280, height: 720); +} +--- + +$(P +Named arguments can also be used in struct/union literals. +A union can now be initialized by setting a field different than the first one. +) + +--- +union U +{ + float asFloat; + uint asInt; +} + +auto u0 = U(1.0); // this sets the `asFloat` field +auto u1 = U(asInt: 0x3F800000); // formerly not possible +--- + +$(P +Relevant specification pages are: +$(UL + $(LI $(DDSUBLINK spec/struct, struct-literal, Struct Literals)) + $(LI $(DDSUBLINK spec/struct, anonymous, Anonymous Structs and Unions)) + $(LI $(DDSUBLINK spec/expression, argument-parameter-matching, Matching Arguments to Parameters)) + $(LI $(DDSUBLINK spec/function, function-overloading, Function Overloading)) +) +) + +$(P +Note that the implementation for regular functions and struct literals has been around since dmd 2.103, but it was undocumented and wouldn't work with template functions. +) + +$(P +This implements [DIP1030](https://www.dlang.org/dips/1030) for *function arguments*, but named *template arguments* are not implemented yet. +Also, there are still implementation details to be ironed out which the DIP doesn't specify, such as how named arguments interact with tuples. +For more information, see: [Named Arguments Status Update](https://forum.dlang.org/post/bynneksajyfyadwndsbm@forum.dlang.org) +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 range_predicate_element,`isForwardRange`, `isBidirectionalRange`, and `isRandomAccessRange` now take an optional element type) +$(CHANGELOG_SOURCE_FILE phobos, changelog/range_predicate_element.dd) +$(P +In Phobos 2.106, an optional second template parameter was added to +`isInputRange` to enable conveniently checking a range's element type. Now, the +same parameter has been added to `isForwardRange`, `isBidirectionalRange`, and +`isRandomAccessRange`. +) + +$(P +As before, if a second type argument is passed to one of these templates, the +range's element type is checked to see if it is +$(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible) +to the given type, and this additional check must pass in order for the +template to evaluate to `true`. +) + +$(P +Examples: +) +--- +// exact match +static assert( isForwardRange!(int[], int)); + +// match with qualifier conversion +static assert( isBidirectionalRange!(int[], const(int)); + +// not a match +static assert(!isRandomAccessRange!(int[], string)); +--- +) + +$(LI $(LNAME2 upgrade-unicode,std.uni has been upgraded from Unicode 15.0.0 to 15.1.0) +$(CHANGELOG_SOURCE_FILE phobos, changelog/upgrade-unicode.dd) +$(P +This Unicode update was released September 12, 2023. +See: https://www.unicode.org/versions/Unicode15.1.0/ +) + +``` +import std; + +void main() +{ + const alphaCount = iota(0, dchar.max).filter!(std.uni.isAlpha).walkLength; + writeln(alphaCount); + // formerly: 137765 + // now: 138387 + // 622 new dchars return true for `isAlpha` +} +``` + +$(P +The internal unicode tables (std/internal/unicode_tables.d) have also been changed to use hex strings instead of array literals, which makes them faster to import. +The exact speed up depends on your computer and D compiler, but it likely cuts between 30 and 100 milliseconds if you compile something which imports `std.string` or `std.uni`. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 dub-fetch,The fetch command now supports multiple arguments, recursive fetch, and is project-aware) +$(CHANGELOG_SOURCE_FILE dub, changelog/dub-fetch.dd) +$(P +Previously, `dub fetch` could only fetch a single package, +and was working independently of the working directory. +) + +$(P +With this release, support for multiple packages have +been added, such that the following is now possible: +) +--- +$ dub fetch vibe-d@0.9.0 vibe-d@0.9.1 vibe-d@0.9.2 +--- + +$(P +When called with no argument, `dub fetch` used to error out. +However, it will now attempt to fetch dependencies for the +current project, if any exists. +) + +$(P +Finally, when fetching a package, it might be useful to fetch +all its dependencies. This is done automatically for projects, +and can now be done for direct fetch as well: +) +--- +$ dub fetch --recursive vibe-d@0.9.0 vibe-d@0.9.1 +--- +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 24179): Ddoc broke D code sections) +$(LI $(BUGZILLA 24315): dmd/cpreprocess.d:87: warning: use of tmpnam is dangerous use mkstemp) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 23515): Named Enum of function SIGSEGFAULT) +$(LI $(BUGZILLA 23786): __traits$(LPAREN)parent, {}$(RPAREN) in overloaded function produces wierd results dependent on declaration order) +$(LI $(BUGZILLA 23818): Error HMODULE not defined, please use HMODULE) +$(LI $(BUGZILLA 24293): ImportC: C preprocessor output should use temporary files) +$(LI $(BUGZILLA 24309): Memory allocation failed on Azure pipeline) +$(LI $(BUGZILLA 24359): slice equality expression can be discarded) +$(LI $(BUGZILLA 24363): hex string postfixes are useless) +$(LI $(BUGZILLA 24383): Index assignment expression in __traits$(LPAREN)compiles$(RPAREN) fails to parse) +$(LI $(BUGZILLA 24387): Base class construction ignores private) +$(LI $(BUGZILLA 24389): importC: Building zlib in Phobos with importC fails on FreeBSD 14) +$(LI $(BUGZILLA 24390): AssertError@src/dmd/backend/cgxmm.d$(LPAREN)1476$(RPAREN): Assertion failure) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 3543): [tdpl] ternary operator can't find common type for classes/interfaces) +$(LI $(BUGZILLA 18919): __FILE__ and __LINE__ should work when used in default argument expressions) +$(LI $(BUGZILLA 24316): Allow CTFE access to immutable variable through pointer) +$(LI $(BUGZILLA 24397): Support C preprocessor function-like macros) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 24339): std.mmfile has poor documentation) +$(LI $(BUGZILLA 24348): Inaccurate documentation for hasSlicing with infinite range) +$(LI $(BUGZILLA 24384): roundRobin crashes with empty first argument) +$(LI $(BUGZILLA 24403): Nullable doesn't work with non-mutable types with a destructor) +$(LI $(BUGZILLA 24458): Mac M3 associative array keys on std.net.curl gets overwritten) +$(LI $(BUGZILLA 24465): Tuple does not get a copy constructor when its members need it) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 24318): Nullable should support non-copyable objects) +$(LI $(BUGZILLA 24382): std.range.only should have assignable elements) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 24453): [REG2.108] idup fails for inout$(LPAREN)T$(RPAREN)[] slices) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 4071): Missing support to share memory and objects between DLLs and executable) +$(LI $(BUGZILLA 24349): object noreturn link is missing) +$(LI $(BUGZILLA 24404): The names of the union fields in Linux's ifaddrs are named incorrectly.) +$(LI $(BUGZILLA 24405): FreeBSD's ifaddrs missing the ifa_broadaddr field) +$(LI $(BUGZILLA 24408): AF_INET6 duplicated in core.sys.linux.sys.socket) +$(LI $(BUGZILLA 24417): core.sys.posix.sys.select: fds_bits named __fds_bits on FreeBSD) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 15504): core.demangle uses exception handling for normal control flow) +$(LI $(BUGZILLA 19702): Remove usage of DECLARE_HANDLE) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 24313): Download page should reference Github nightlies) +$(LI $(BUGZILLA 24331): @nogc and GC.disable$(LPAREN)$(RPAREN) are often confused) +) +) +$(D_CONTRIBUTORS_HEADER 36) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Adam D. Ruppe) + $(D_CONTRIBUTOR Adam Wilson) + $(D_CONTRIBUTOR Atila Neves) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Denis Feklushkin) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR dkorpel) + $(D_CONTRIBUTOR Hiroki Noda) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jeremy) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR Johannes) + $(D_CONTRIBUTOR Jonathan M Davis) + $(D_CONTRIBUTOR kt) + $(D_CONTRIBUTOR Mai-Lapyst) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Max Haughton) + $(D_CONTRIBUTOR MrcSnm) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Ogi-kun) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Puneet Goel) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Richard (Rikki) Andrew Cattermole) + $(D_CONTRIBUTOR ryuukk) + $(D_CONTRIBUTOR Spoov) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Teodor Dutu) + $(D_CONTRIBUTOR Tim Schendekehl) + $(D_CONTRIBUTOR vabenil) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.108.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.108.1.dd b/changelog/2.108.1.dd new file mode 100644 index 0000000000..82620ac987 --- /dev/null +++ b/changelog/2.108.1.dd @@ -0,0 +1,62 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION May 01, 2024, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 10 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 12 contributors) + who made $(VER) possible.) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 23657): [REG2.101] Incorrect error escape reference to stack allocated value) +$(LI $(BUGZILLA 24436): a array be overwritten when other array be written) +$(LI $(BUGZILLA 24479): [REG2.104] Error on getAttributes on getOverloads of templates) +$(LI $(BUGZILLA 24505): [REG2.108] ImportC: Function-like macros $(LPAREN)newly translated to templates$(RPAREN) may collide with regular symbols) +$(LI $(BUGZILLA 24519): compiler segfault on default argument with slice operator []) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 24495): ImportC: Struct initialization expression fails to initialize field) +$(LI $(BUGZILLA 24509): importC cannot handle _stdcall Function Calling Convention with single heading underscore) +$(LI $(BUGZILLA 24511): __stdcall functions from C are extern$(LPAREN)C$(RPAREN) in D.) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 24481): retro no longer works with types that support assignment but not moving) +) +$(BUGSTITLE_BUGZILLA Druntime regression fixes, + +$(LI $(BUGZILLA 24498): Multidimensional array not scanned by GC) +) +) +$(D_CONTRIBUTORS_HEADER 12) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Artha) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR FeepingCreature) + $(D_CONTRIBUTOR Ferhat Kurtulmuş) + $(D_CONTRIBUTOR Harry Gillanders) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Jonathan M Davis) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Tim Schendekehl) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.108.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.109.0.dd b/changelog/2.109.0.dd new file mode 100644 index 0000000000..cd182c6a3e --- /dev/null +++ b/changelog/2.109.0.dd @@ -0,0 +1,582 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jun 01, 2024, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 15 major changes and 26 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 39 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.alias-instance-member,[next edition] Aliasing a member of a type *instance* is now an error)) +$(LI $(RELATIVE_LINK2 dmd.bitfield-introspection,Add Bitfield Introspection Capability)) +$(LI $(RELATIVE_LINK2 dmd.ctfeWrite,Added `__ctfeWrite` to write messages from CTFE)) +$(LI $(RELATIVE_LINK2 dmd.deprecation-limit,Deprecation warnings are now also limited by `-verrors`)) +$(LI $(RELATIVE_LINK2 dmd.dtoh-windows,dtoh generates signatures for `extern(Windows)` and `extern(System)` functions.)) +$(LI $(RELATIVE_LINK2 dmd.foreach-array-index-type,`foreach` on a dynamic array can have an index type smaller than `size_t`)) +$(LI $(RELATIVE_LINK2 dmd.foreach-reverse-delegate-error,`foreach_reverse` on a delegate is now an error)) +$(LI $(RELATIVE_LINK2 dmd.identifier-tables,Expansion of identifier tables to allow new characters to match C23 have been added along with CLI configurability)) +$(LI $(RELATIVE_LINK2 dmd.importc-unicode,ImportC has improved Unicode support)) +$(LI $(RELATIVE_LINK2 dmd.linker-error,Missing symbol errors are made less cryptic)) +$(LI $(RELATIVE_LINK2 dmd.omf-removed,Windows OMF support has been removed)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 druntime.core.sys.linux.sys.mount,Add module `core.sys.linux.sys.mount`.)) +$(LI $(RELATIVE_LINK2 druntime.removenostackcollect,Remove all `collectNoStack` functions and API from druntime.)) +$(LI $(RELATIVE_LINK2 druntime.thread-sleep-trusted,Mark `Thread.sleep` as `@trusted`)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 std.process.Config.preExecDelegate,Add `std.process.Config.preExecDelegate`)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.alias-instance-member,[next edition] Aliasing a member of a type *instance* is now an error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.alias-instance-member.dd) +$(P +Such an alias actually aliases a member of the instance's *type*, not +the instance member itself. That could be confusing, and is now an error. +Instead, alias a member of the type: +) + +--- +struct Foo +{ + int v; + void test(Foo that) const + { + alias a = this.v; // OK + alias b = that.v; // Error, use `typeof(that).v` instead + assert(&a is &b); // passes + assert(&b !is &that.v); + } +} + +struct Bar +{ + Foo f; + alias v = f.v; // Error, use `typeof(f).v` +} +--- +) + +$(LI $(LNAME2 dmd.bitfield-introspection,Add Bitfield Introspection Capability) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.bitfield-introspection.dd) +$(P +Adds: +) + +$(P +* property `.bitoffsetof` to get the starting bit number of a bitfield +) + +$(P +* property `.bitwidth` to get the number of bits in a bitfield +) + +$(P +* `__traits(isBitfield, symbol)` returns true if a field symbol is a bitfield +) +) + +$(LI $(LNAME2 dmd.ctfeWrite,Added `__ctfeWrite` to write messages from CTFE) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.ctfeWrite.dd) +$(P +The special function `__ctfeWrite` can now be used to write messages +during CTFE, similar to `pragma(msg, ...)`. It is Implementation Defined +how the message is presented to the user; the recommended way is by +printing the message to `stderr`, standard error stream. +The function is available in `object.d` and accepts any value implicitly +convertible to `const(char)[]`. +) + +$(P +For example: +) + +```d +int greeting() +{ + __ctfeWrite("Hello from CTFE. Today is "); + __ctfeWrite(__DATE__); + __ctfeWrite("\n"); + return 0; +} + +enum forceCTFE = greeting(); +``` + +$(P +Compiling this program will generate the following output: +) + +``` +Hello from CTFE. Today is +``` +) + +$(LI $(LNAME2 dmd.deprecation-limit,Deprecation warnings are now also limited by `-verrors`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecation-limit.dd) +$(P +By default, the compiler stops after 20 error messages, unless a different amount is specified by passing e.g. `-verrors=50` or `-verrors=0` for no limit. +This error limit now also applies to deprecation messages, so the command line isn't flooded with hundreds of them when compiling a big project that hasn't fixed all deprecations yet. +) + +--- +deprecated void f() +{ +} + +void main() +{ + f(); + f(); + f(); + f(); +} +--- + +$(P +$(CONSOLE +> dmd -verrors=3 app.d +app.d(7): Deprecation: function `app.f` is deprecated +app.d(8): Deprecation: function `app.f` is deprecated +app.d(9): Deprecation: function `app.f` is deprecated +1 deprecation warning omitted, use `-verrors=0` to show all +) +) +) + +$(LI $(LNAME2 dmd.dtoh-windows,dtoh generates signatures for `extern(Windows)` and `extern(System)` functions.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.dtoh-windows.dd) +$(P +When using the -HC switch, in addition to `extern(C)` and `extern(C++)` functions, `extern(Windows)` and `extern(System)` functions are output in the .h file as well. +) + +$(P +Example D module: +) +--- +extern(Windows) int hello() +{ + return 0; +} + +extern(System) int myFriend() +{ + return 0; +} +--- + +$(P +Output with `-HC` switch: +) +--- +// (full header omitted) + +#ifndef _WIN32 +#define EXTERN_SYSTEM_AFTER __stdcall +#define EXTERN_SYSTEM_BEFORE +#else +#define EXTERN_SYSTEM_AFTER +#define EXTERN_SYSTEM_BEFORE extern "C" +#endif + +int32_t __stdcall hello(); + +EXTERN_SYSTEM_BEFORE int32_t EXTERN_SYSTEM_AFTER myFriend(x); +--- +) + +$(LI $(LNAME2 dmd.foreach-array-index-type,`foreach` on a dynamic array can have an index type smaller than `size_t`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.foreach-array-index-type.dd) +$(P +The array length is known at compile-time for the following cases: +) + +$(P +* The array is a literal +* The array is a slice expression whose upper bound is known at + compile-time +) + +$(P +For an array `a`, the index type can be any integer type `I` where +`a.length <= I.max`. +) + +$(P +Other cases [are not implemented](https://issues.dlang.org/show_bug.cgi?id=24542) yet. +) +) + +$(LI $(LNAME2 dmd.foreach-reverse-delegate-error,`foreach_reverse` on a delegate is now an error) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.foreach-reverse-delegate-error.dd) +$(P +The compiler did not try to implement reverse traversal of the results returned by +the delegate when $(D foreach_reverse) was used. That could result in code +that was confusing to read, so it was deprecated (for many years). Using +$(D foreach_reverse) with a delegate is now an error. +) +) + +$(LI $(LNAME2 dmd.identifier-tables,Expansion of identifier tables to allow new characters to match C23 have been added along with CLI configurability) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.identifier-tables.dd) +$(P +You can currently choose between ``c99``, ``c11``, ``UAX31`` (C23's) and ``all`` (the least restrictive set) for both D and ImportC. +) + +$(P +This can be done with ``-identifiers=`` and for ImportC ``-identifiers-importc=
    ``. +) + +$(P +The default table for D is currently set to ``all``, while ImportC is set to ``c11``. +Previously both D and ImportC used the ``c99`` tables. +) + +$(P +D's table will be swapped over at a later date to [UAX31](https://unicode.org/reports/tr31/), this should be done in 2.117. +If you find yourself at this time using ``c99`` specific characters and not willing to change them, you may switch back to ``all``. +Although it should be unlikely that you will need to. +) +) + +$(LI $(LNAME2 dmd.importc-unicode,ImportC has improved Unicode support) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.importc-unicode.dd) +$(P +Universal Character Names are now supported, allowing you to use the ``\uXXXX`` and ``\UXXXXXXXX`` syntax where ``X`` is a hex digit as part of an identifier. +) + +$(P +DigitalMars sppn does not support anything newer than C99. +It is known to be limited and using any Unicode character not in those ranges will result in an error. +) +) + +$(LI $(LNAME2 dmd.linker-error,Missing symbol errors are made less cryptic) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.linker-error.dd) +$(P +It is not uncommon to forget to link a library, list a .d file on the command line, or include a `main` function. +Example: +) +--- +module app; + +unittest +{ + import assertions; + assertEquals('D', 'D'); +} +--- + +--- +module assertions; + +void assertEquals(char a, char b) +{ + assert(a == b); +} +--- + +$(P +When compiling this as follows: +) + +$(P +$(CONSOLE +\> dmd -unittest app.d +) +) + +$(P +The compiler would not see any error, but at link time there are missing symbols. +Formerly, this would result in a cryptic linker error with mangled symbol names: +) + +$(P +$(CONSOLE +/usr/bin/ld: /usr/lib/gcc/x86_64-pc-linux-gnu/13.2.1/../../../../lib/Scrt1.o: in function `_start': +(.text+0x1b): undefined reference to `main' +/usr/bin/ld: app.o: in function `_D3app16__unittest_L5_C1FZv': +app.d:(.text._D3app16__unittest_L5_C1FZv[_D3app16__unittest_L5_C1FZv]+0xc): undefined reference to `_D10assertions12assertEqualsFaaZv' +collect2: error: ld returned 1 exit status +) +) + +$(P +Experienced users might know how to demangle the symbol to make it more readable: +) + +$(P +$(CONSOLE +\> echo _D10assertions12assertEqualsFaaZv | ddemangle +void assertions.assertEquals(char, char) +) +) + +$(P +But this is inconvenient to do manually every time. +Now, when the compiler invokes the linker program, it will read its output, scan for undefined symbol errors, and demangle the names: +) + +$(P +$(CONSOLE +Error: undefined reference to `main` +Error: undefined reference to `void assertions.assertEquals(char, char)` + referenced from `void app.__unittest_L5_C1()` + perhaps define a `void main() {}` function or use the `-main` switch + perhaps `.d` files need to be added on the command line, or use `-i` to compile imports +Error: linker exited with status 1 +) +) + +$(P +Which makes it easier to fix the command: +$(CONSOLE +\> dmd -unittest -main -i app.d +) +) + +$(P +Currently supported linkers are ld, bfd, gold, mold, and Microsoft LINK. +Please file an issue if your linker's errors aren't detected. +) +) + +$(LI $(LNAME2 dmd.omf-removed,Windows OMF support has been removed) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.omf-removed.dd) +$(P +After two years of making PE-COFF support the default on Windows, OMF support has now been removed. +) + +$(P +This includes the switch (``-m32omf``). +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 druntime.core.sys.linux.sys.mount,Add module `core.sys.linux.sys.mount`.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.core.sys.linux.sys.mount.dd) +$(P +The new module `core.sys.linux.sys.mount` provides definitions corresponding to +those in the header `` on Linux. +) +) + +$(LI $(LNAME2 druntime.removenostackcollect,Remove all `collectNoStack` functions and API from druntime.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.removenostackcollect.dd) +$(P +The function `collectNoStack` in the D garbage collector performed a +collection, without using any roots from thread stacks or thread-local-storage. +The danger of running this mechanism is that any blocks of memory which only +have a reference from a thread might be collected, while the thread is still +running and possibly using the memory. +) + +$(P +The only time this function was called was at GC termination. At GC +termination, the GC is about to be destroyed, and so we want to run as many +destructors as possible. However, if some thread is using GC-allocated memory, +cleaning up that memory isn't going to help matters. Either it will crash after +the GC cleans the memory, or it will crash after the GC is destroyed. +) + +$(P +The original purpose of this function (from D1) was to ensure simple uses of +the GC were cleaned up in small test programs, as this mechanism was only used +on single-threaded programs (and of course, at program exit). Also note at the +time, D1 was 32-bit, and false pointers where much more common. Avoiding +scanning stacks would aid in avoiding seemingly random behavior in cleanup. +However, as shown below, there are more deterministic ways to ensure data is +always cleaned up. +) + +$(P +Today, the dangers are much greater that such a function is even callable -- +any call to such a function would immediately start use-after-free memory +corruption in any thread that is still running. Therefore, we are removing the +functionality entirely, and simply doing a standard GC cleanup (scanning stacks +and all). One less footgun is the benefit for having less guaranteed GC clean +up at program exit. +) + +$(P +In addition, the GC today is a bit smarter about where the valid stack is, so +there is even less of a chance of leaving blocks unfinalized. +) + +$(P +As always, the GC is *not* guaranteed to clean up any block at the end of +runtime. Any change in behavior with code that had blocks clean up before, but +no longer are cleaned up is still within specification. And if you want the +behavior that absolutely cleans all blocks, you can use the +`--DRT-gcopt=cleanup:finalize` druntime configuration option, which will clean +up all blocks without even scanning. +) +) + +$(LI $(LNAME2 druntime.thread-sleep-trusted,Mark `Thread.sleep` as `@trusted`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.thread-sleep-trusted.dd) +$(P +The static method `core.thread.Thread.sleep` is now marked as `@trusted` and +can be called directly from `@safe` code. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 std.process.Config.preExecDelegate,Add `std.process.Config.preExecDelegate`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/std.process.Config.preExecDelegate.dd) +$(P +$(LINK2 $(ROOT_DIR)phobos/std_process.html#.Config.preExecDelegate, `std.process.Config.preExecDelegate`) +is just like +$(LINK2 $(ROOT_DIR)phobos/std_process.html#.Config.preExecFunction, `std.process.Config.preExecFunction`), +but can capture an environment, for example: +) + +------- +import core.sys.linux.sys.prctl : PR_SET_PDEATHSIG, prctl; +import std.process : Config, execute; + +void runProgram(int pdeathsig) +{ + execute( + ["program"], + config: Config( + preExecDelegate: () @trusted => + prctl(PR_SET_PDEATHSIG, pdeathsig, 0, 0, 0) != -1, + ), + ); +} +------- + +$(P +`preExecFunction` is retained for backwards compatibility. If both +`preExecFunction` and `preExecDelegate` are given, both are called. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 24560): dmd crash on imported function with default parameter containing `new`) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 14128): AliasDeclaration allows expressions, causing false code for ThisExp) +$(LI $(BUGZILLA 20148): void initializated bool can be both true and false) +$(LI $(BUGZILLA 21854): @live breaks foreach over integers) +$(LI $(BUGZILLA 21923): @live does not take destructor code into account.) +$(LI $(BUGZILLA 22977): [dip1000] can escape scope pointer returned by nested function) +$(LI $(BUGZILLA 23530): casting immutable away allowed in safe) +$(LI $(BUGZILLA 24434): Casting away const with cast$(LPAREN)$(RPAREN) should not produce an lvalue) +$(LI $(BUGZILLA 24477): Union access of bool shouldn't be allowed in @safe) +$(LI $(BUGZILLA 24485): Invalid implicit ref return reinterpret cast for structs with copy constructor) +$(LI $(BUGZILLA 24493): FreeBSD_14 version identifier missing) +$(LI $(BUGZILLA 24504): ImportC: Enum declarations with a mixture of `int` and `uint` literal values cause errors, when targeting Windows, when debug info generation is enabled.) +$(LI $(BUGZILLA 24520): [REG] type$(LPAREN)value$(RPAREN) got a synonym $(LPAREN)type$(RPAREN)$(LPAREN)value$(RPAREN)) +$(LI $(BUGZILLA 24525): auto ref lambda exp not parsed if used as left-most expression in an expression statement) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 5573): Compiler $(LPAREN)not linker$(RPAREN) should generate an error for missing main$(LPAREN)$(RPAREN)) +$(LI $(BUGZILLA 21718): Preview switches have insufficient descriptions) +$(LI $(BUGZILLA 24111): [ImportC] fatal error C1034: stdio.h: no include path set) +$(LI $(BUGZILLA 24450): apply VRP to foreach indices when array is of known length) +$(LI $(BUGZILLA 24452): Can't disable coverage at runtime) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 15708): std.range.choose assumes hasElaborateCopyConstructor means "has __postblit") +$(LI $(BUGZILLA 24478): std.csv array out of bounds when row size exceeds header) +$(LI $(BUGZILLA 24549): std.process.environment.get$(LPAREN)null$(RPAREN) segfaults) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 24517): druntime tests fail on FreeBSD 14) +$(LI $(BUGZILLA 24546): importC musl setjmp.h failure) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 24472): __traits$(LPAREN)fullyQualifedName$(RPAREN) is undocumented in spec) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 24488): contributor guide hard to find from home page) +) +) +$(D_CONTRIBUTORS_HEADER 39) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR 0-v-0) + $(D_CONTRIBUTOR Adam Wilson) + $(D_CONTRIBUTOR Andrei Horodniceanu) + $(D_CONTRIBUTOR Ate Eskola) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR chloekek) + $(D_CONTRIBUTOR Denis Feklushkin) + $(D_CONTRIBUTOR Dennis) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR dokutoku) + $(D_CONTRIBUTOR Don Allen) + $(D_CONTRIBUTOR drug007) + $(D_CONTRIBUTOR Emmanuel Nyarko) + $(D_CONTRIBUTOR Harry Gillanders) + $(D_CONTRIBUTOR Horodniceanu Andrei) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR IchorDev) + $(D_CONTRIBUTOR Inkrementator) + $(D_CONTRIBUTOR Jeremy Baxter) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR John Dougan) + $(D_CONTRIBUTOR Jonathan M Davis) + $(D_CONTRIBUTOR liushuyu) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Matheus C. França) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Petar Kirov) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Richard (Rikki) Andrew Cattermole) + $(D_CONTRIBUTOR shoo) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Sönke Ludwig) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR WANG Rui) + $(D_CONTRIBUTOR zopsicle) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.109.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.109.1.dd b/changelog/2.109.1.dd new file mode 100644 index 0000000000..b278b26227 --- /dev/null +++ b/changelog/2.109.1.dd @@ -0,0 +1,80 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Jul 01, 2024, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 1 major change and 5 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 7 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.unsafe-boolean-values,`bool` values other than 0 or 1 are not `@safe`)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.unsafe-boolean-values,`bool` values other than 0 or 1 are not `@safe`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.unsafe-boolean-values.dd) +$(P +The spec has been updated so that only 0 and 1 are +[safe values](https://dlang.org/spec/function.html#safe-values) +for `bool`. This means that reading a `bool` value whose underlying byte representation +has other bits set is implementation-defined and should be avoided. Consequently: +) + +$(P +* `void` initialization of booleans is now deprecated in `@safe` code. +* Reading a `bool` field from a union is now deprecated in `@safe` code. +) + +$(P +Runtime array casting to `bool[]` is +[yet to be deprecated](https://issues.dlang.org/show_bug.cgi?id=24582). +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 24602): Internal compiler error: failed to detect static initialization of associative array) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 24566): condition that starts with runtime value and uses compile time array does not short circuit) +$(LI $(BUGZILLA 24596): Rebindable2 corrupts objects) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 24595): OpenBSD: Use .init_array/.fini_array) +$(LI $(BUGZILLA 24597): FreeBSD/OpenBSD: Enable ELF_COMDAT) +) +) +$(D_CONTRIBUTORS_HEADER 7) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR Brian Callahan) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR Mathis Beer) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Timon Gehr) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.109.1 + TITLE=Change Log: $(VER) diff --git a/changelog/2.110.0.dd b/changelog/2.110.0.dd new file mode 100644 index 0000000000..22814fb069 --- /dev/null +++ b/changelog/2.110.0.dd @@ -0,0 +1,265 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Mar 07, 2025, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 5 major changes and 58 fixed Bugzilla issues. + A huge thanks goes to the + $(LINK2 #contributors, 34 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.copying-to-void-arrays,Copying from `const(void)[]` to `void[]` is disallowed with `-preview=fixImmutableConv`)) +$(LI $(RELATIVE_LINK2 dmd.import-exp-hexstring,Import expressions are now treated as hex strings)) +$(LI $(RELATIVE_LINK2 dmd.isCOMClass,New trait isCOMClass to detect if a type is a COM class)) +$(LI $(RELATIVE_LINK2 dmd.unsafe-boolean-values,`bool` values other than 0 or 1 are not `@safe`)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 selections_from_parent_dir,`dub.selections.json` files are now looked up in parent directories too)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.copying-to-void-arrays,Copying from `const(void)[]` to `void[]` is disallowed with `-preview=fixImmutableConv`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.copying-to-void-arrays.dd) +$(P +If `const(void)[]` data contains tail `const` pointers, copying to `void[]` +can subsequently violate `const` data: +) +--- +void f(int*[] a, const int*[] b) +{ + void[] va = a; + const void[] vb = b; + va[] = vb[]; // fills `a` with pointers to const + *a[0] = 0; // const data mutated +} +--- +$(P +Copying `vb` data to `va` is no longer allowed with the +`-preview=fixImmutableConv` switch. +) +) + +$(LI $(LNAME2 dmd.import-exp-hexstring,Import expressions are now treated as hex strings) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.import-exp-hexstring.dd) +$(P +While [Import expressions](https://dlang.org/spec/expression.html#import_expressions) are typed as `string`, they are also used to embed binary files. +By treating them the same as hex strings, they will implicitly convert to arrays of integral types other than `char`. +) + +--- +// Formerly, a cast was required: +immutable ubyte[] iconImg = cast(immutable ubyte[]) import("icon.png"); + +// Now, it implicitly converts to integral arrays: +immutable ubyte[] iconImg = import("icon.png"); +--- +) + +$(LI $(LNAME2 dmd.isCOMClass,New trait isCOMClass to detect if a type is a COM class) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.isCOMClass.dd) +$(P +A COM class inherits from a possibly user defined interface called ``IUnknown``. +To detect this during compilation use the trait ``__traits(isCOMClass, Type)``. +Or for during runtime use the ``TypeInfo_Class`` flag. +) +) + +$(LI $(LNAME2 dmd.unsafe-boolean-values,`bool` values other than 0 or 1 are not `@safe`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.unsafe-boolean-values.dd) +$(P +The spec [was updated](https://dlang.org/spec/type.html#bool) +(for 2.109) so that only 0 and 1 are +[safe values](https://dlang.org/spec/function.html#safe-values) +for `bool`. This means that reading a `bool` value whose underlying byte representation +has other bits set is implementation-defined and should be avoided. +Consequently the following are deprecated in `@safe` code: +) + +$(P +* `void` initialization of booleans (since 2.109) +* Reading a `bool` field from a union (since 2.109) +* Runtime casting a dynamic array to a `bool` dynamic array type +* Runtime casting a `bool` dynamic array to a tail mutable dynamic array type +* Casting a pointer to a `bool` pointer type +* Casting a `bool` pointer to a tail mutable pointer type +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 selections_from_parent_dir,`dub.selections.json` files are now looked up in parent directories too) +$(CHANGELOG_SOURCE_FILE dub, changelog/selections_from_parent_dir.dd) +$(P +In case the root package directory doesn't contain a `dub.selections.json` +file, dub now looks in parent directories too and potentially uses the +first (deepest) one it finds - if and only if that JSON file contains an +optional new `"inheritable": true` flag. +) + +$(P +This allows using a 'central' `dub.selections.json` file for a repository +containing multiple dub projects, making it automatically apply to all +builds in that source tree if located in the repository root directory +(unless a local `dub.selections.json` overrides it). +) + +$(P +Such an inherited selections file is never mutated when running dub for a +nested project, i.e., changes are always saved to a *local* +`dub.selections.json` file. E.g., when running `dub upgrade` for a nested +project. +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(P +Note: Because some bugs from this release were fixed after the migration from Bugzilla to GitHub issues, this list does not include all fixed bugs yet. +We are working to update the changelog to include closed GitHub issues as well. +) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 24431): dmd -vcg-ast crashes printing failed template instantiation) +$(LI $(BUGZILLA 24599): [REG2.103] Wrongly elided TypeInfo emission leading to undefined symbols at link-time) +$(LI $(BUGZILLA 24687): [REG2.110] Cannot cast string-imports to select overload anymore) +$(LI $(BUGZILLA 24699): [REG2.108] No short-circuit evaluation of mixing template bool argument) +$(LI $(BUGZILLA 24812): [REG 2.106] Incorrect highlighting when diagnosing an empty enum declaration since #15664) +$(LI $(BUGZILLA 24882): COM class is allocated using GC not malloc) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 10574): "auto ref" fails to match when IFTI succeeds $(LPAREN)strip to level const$(RPAREN)) +$(LI $(BUGZILLA 12885): const union wrongly converts implicitly to mutable) +$(LI $(BUGZILLA 17148): Copying from const$(LPAREN)void$(RPAREN)[] to void[] breaks immutable) +$(LI $(BUGZILLA 18281): Compiler rejects safe code in @safe) +$(LI $(BUGZILLA 20894): ICE: passing a member template mixin identifier as alias argument) +$(LI $(BUGZILLA 20907): [DIP1000] Unittest fails when duplicated) +$(LI $(BUGZILLA 23722): Lambdas are mangled incorrectly when using multiple compilation units, resulting in incorrect code) +$(LI $(BUGZILLA 23957): Casting to derived extern$(LPAREN)C++$(RPAREN) class is unsafe) +$(LI $(BUGZILLA 24337): Segfault when printing an int[] cast from a string literal) +$(LI $(BUGZILLA 24534): Having a label on a declaration makes it possible to skip it with goto) +$(LI $(BUGZILLA 24558): C asserts segfault on Glibc) +$(LI $(BUGZILLA 24577): Struct with constructor returned from C++ wrong) +$(LI $(BUGZILLA 24582): Detect unsafe `cast$(LPAREN)bool[]$(RPAREN)`) +$(LI $(BUGZILLA 24583): di generator emits return scope and scope return in wrong order) +$(LI $(BUGZILLA 24592): ImportC: Bitfield layout wrong for int64 on 32-bit Linux) +$(LI $(BUGZILLA 24594): ImportC: Packed struct has wrong layout) +$(LI $(BUGZILLA 24603): Can copy from non-void array into void[] in safe code) +$(LI $(BUGZILLA 24622): Modify const data with void[] concatenation/append) +$(LI $(BUGZILLA 24630): Casting a bool pointer to a mutable pointer type is unsafe) +$(LI $(BUGZILLA 24631): Pointer cast allows changing @system field in @safe code) +$(LI $(BUGZILLA 24634): Parse error initializing array from expression with StructInitializer) +$(LI $(BUGZILLA 24731): IFTI cannot handle integer expressions) +$(LI $(BUGZILLA 24760): ICE on variadic after default argument) +$(LI $(BUGZILLA 24764): ICE when -vcg-ast prints imported invariant) +$(LI $(BUGZILLA 24790): -vcg-ast ICE on lowered assign exp) +$(LI $(BUGZILLA 24819): Optimizer changes result of float calculations on 32-bit) +$(LI $(BUGZILLA 24832): Segfault in hex string) +$(LI $(BUGZILLA 24884): backend generates wrong 32-bit code after inlining math with double[4]) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 20243): inout not substituted for in associative array key type) +$(LI $(BUGZILLA 24135): Eponymous template member overloads not shown as call candidates) +$(LI $(BUGZILLA 24580): ImportC: Asm label after attributes results in syntax error) +$(LI $(BUGZILLA 24598): OpenBSD: adapt compiler tests) +$(LI $(BUGZILLA 24623): Rename version CppRuntime_Clang/Gcc to CppRuntime_libcxx/libstdcxx.) +$(LI $(BUGZILLA 24841): UTF-16 surrogates when used as an escape of a string should hint on error) +) +$(BUGSTITLE_BUGZILLA Phobos regression fixes, + +$(LI $(BUGZILLA 23487): std.experimental.logger assigning FileLogger to sharedLog no longer works) +$(LI $(BUGZILLA 24637): [REG 2.104] Cannot insert const/immutable elements into DList) +$(LI $(BUGZILLA 24686): SumType stopped working on LDC 1.37 with unmatched DeducedParameterType template) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 24564): std.file.DirEntry throws Exception instead of FileException) +$(LI $(BUGZILLA 24773): Stable sort$(LPAREN)$(RPAREN) invokes the destructor on uninitialized elements) +$(LI $(BUGZILLA 24809): In some cases, stable sort assigns to unininitialized elements) +$(LI $(BUGZILLA 24824): std.process.browse returns on failure in forked child) +$(LI $(BUGZILLA 24827): maxElement does not correctly handle types with opAssign) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 24579): stat_t has wrong size for Android armv7a) +$(LI $(BUGZILLA 24626): hasUDA does not handle multiple UDAs of the same symbol) +$(LI $(BUGZILLA 24846): atomicLoad does not work for class arguments with -preview=nosharedaccess) +$(LI $(BUGZILLA 24872): Assigning non-copyable value to array has no effect) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 20859): Add overloads of core.sync.rwmutex.ReadWriteMutex.Reader/Writer.tryLock that take a timeout duration) +$(LI $(BUGZILLA 24590): Illegal instruction with module constructors cycle and shared libphobos2 in _d_criticalenter2) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 24543): The `@__future` attribute is $(LPAREN)almost$(RPAREN) undocumented) +$(LI $(BUGZILLA 24548): [spec] Boolean condition conversion is not documented) +$(LI $(BUGZILLA 24565): out contract variable is implicitly const) +) +$(BUGSTITLE_BUGZILLA Installer bug fixes, + +$(LI $(BUGZILLA 24600): DMD nightly builds are outdated) +) +) +$(D_CONTRIBUTORS_HEADER 31) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR 0-v-0) + $(D_CONTRIBUTOR Alex Muscar) + $(D_CONTRIBUTOR Andrei Horodniceanu) + $(D_CONTRIBUTOR Bastiaan Veelo) + $(D_CONTRIBUTOR Ben Jones) + $(D_CONTRIBUTOR Brad Roberts) + $(D_CONTRIBUTOR Brian Callahan) + $(D_CONTRIBUTOR Connor) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR Emmanuel Nyarko) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Ilya Yanok) + $(D_CONTRIBUTOR Jeremy Baxter) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR Jonathan M Davis) + $(D_CONTRIBUTOR Luis Ferreira) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Quirin F. Schroll) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Richard (Rikki) Andrew Cattermole) + $(D_CONTRIBUTOR RubyTheRoobster) + $(D_CONTRIBUTOR ryuukk) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Sönke Ludwig) + $(D_CONTRIBUTOR Tim Schendekehl) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR zopsicle) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.110.0 + TITLE=Change Log: $(VER) diff --git a/changelog/2.111.0.dd b/changelog/2.111.0.dd new file mode 100644 index 0000000000..eef0f15f38 --- /dev/null +++ b/changelog/2.111.0.dd @@ -0,0 +1,1551 @@ +Ddoc + +$(CHANGELOG_NAV_INJECT) + +$(VERSION Apr 01, 2025, =================================================, + +$(CHANGELOG_HEADER_STATISTICS +$(VER) comes with 41 major changes and 129 fixed Bugzilla issues, and 56 fixed GitHub issues. + A huge thanks goes to the + $(LINK2 #contributors, 78 contributors) + who made $(VER) possible.) + +$(BUGSTITLE_TEXT_HEADER Compiler changes, + +$(LI $(RELATIVE_LINK2 dmd.auto-ref-local,Storage classes `ref` and `auto ref` can now be applied to local, static, extern, and global variables)) +$(LI $(RELATIVE_LINK2 dmd.auto-ref-put-adjacent,Keywords `auto` and `ref` must be adjacent)) +$(LI $(RELATIVE_LINK2 dmd.default-align,The `align` attribute now allows specifying `default` explicitly)) +$(LI $(RELATIVE_LINK2 dmd.delete-keyword,Remove `delete` as a keyword)) +$(LI $(RELATIVE_LINK2 dmd.deprecation-case,Case fallthough for multivalued cases is an error now)) +$(LI $(RELATIVE_LINK2 dmd.deprecation-dtor-fields,An error is now given for constructors when a field's destructor has stricter attributes)) +$(LI $(RELATIVE_LINK2 dmd.deprecation-noop-assignment,Initializing a field with itself has been deprecated)) +$(LI $(RELATIVE_LINK2 dmd.deprecation-pointer-subtract,An error is now given for subtracting pointers of different types)) +$(LI $(RELATIVE_LINK2 dmd.deprecation-throwing-contracts,An error is now issued for `in`/`out` contracts of `nothrow` functions that may throw)) +$(LI $(RELATIVE_LINK2 dmd.deprecation-typesafe-variadic-class,Typesafe variadic class parameters have been deprecated)) +$(LI $(RELATIVE_LINK2 dmd.deprecation-version-debug-number,Integers in `debug` or `version` statements have been removed from the language)) +$(LI $(RELATIVE_LINK2 dmd.error-messages,Many error messages have changed)) +$(LI $(RELATIVE_LINK2 dmd.extern-std-cpp23,The compiler now accepts `-extern-std=c++23`)) +$(LI $(RELATIVE_LINK2 dmd.ftime-trace,Build time profiling has been added to DMD)) +$(LI $(RELATIVE_LINK2 dmd.getBitfieldInfo,New traits `getBitfieldOffset` and `getBitfieldWidth` for built-in bitfields)) +$(LI $(RELATIVE_LINK2 dmd.import-c-i,Using the compiler flag `-i` will now properly pick up C source files)) +$(LI $(RELATIVE_LINK2 dmd.importc-pragma-stc,A pragma for ImportC allows to set `nothrow`, `@nogc` or `pure`)) +$(LI $(RELATIVE_LINK2 dmd.mixin-assign,Mixin templates can now use assignment syntax)) +$(LI $(RELATIVE_LINK2 dmd.obj_extensions,Object file extensions `.o` and `.obj` are now accepted on all platforms)) +$(LI $(RELATIVE_LINK2 dmd.objc-improvements,Objective-C selectors are now automatically generated when not specified with `@selector`.)) +$(LI $(RELATIVE_LINK2 dmd.oq-compiler-switch,New compiler switch `-oq` for DMD)) +$(LI $(RELATIVE_LINK2 dmd.placementNew,Added Placement New Expression)) +$(LI $(RELATIVE_LINK2 dmd.postfix-this-attributes,Postfix type qualifier method attributes for `-H` and `-D`)) +$(LI $(RELATIVE_LINK2 dmd.remove-samples,The folder *samples* has been removed from DMD installations)) +$(LI $(RELATIVE_LINK2 dmd.rvalue,New keyword `__rvalue`)) +$(LI $(RELATIVE_LINK2 dmd.safer,Add `-preview=safer` switch for safety checking on unattributed functions)) +$(LI $(RELATIVE_LINK2 dmd.shortened-method-constructor,Shortened method syntax can now be used in constructors)) + +) + +$(BUGSTITLE_TEXT_HEADER Runtime changes, + +$(LI $(RELATIVE_LINK2 druntime.bcrypt,Add Windows BCrypt bindings under `core.sys.windows.bcrypt`)) +$(LI $(RELATIVE_LINK2 druntime.criticalRegionLock,Remove `criticalRegionLock`)) +$(LI $(RELATIVE_LINK2 druntime.expect-trap,Adds `expect`, `likely`, `unlikely`, and `trap` to `core.builtins`)) +$(LI $(RELATIVE_LINK2 druntime.segfault-message,New segfault handler showing backtraces for null access / call stack overflow on linux)) + +) + +$(BUGSTITLE_TEXT_HEADER Library changes, + +$(LI $(RELATIVE_LINK2 bit-cast,Added `std.conv.bitCast`)) +$(LI $(RELATIVE_LINK2 formatted_read_tuple_return,Extend the functionality of formattedRead to permit a std.file.slurp like execution.)) +$(LI $(RELATIVE_LINK2 fromhexstring,Added fromHexString and fromHexStringAsRange functions to std.digest.)) +$(LI $(RELATIVE_LINK2 odbc-4,ODBC Bindings in `etc.c.odbc` have been updated to ODBC 4.0.)) +$(LI $(RELATIVE_LINK2 pop-grapheme,Added popGrapheme function to std.uni.)) +$(LI $(RELATIVE_LINK2 readfln,Added `readfln` and `File.readfln` to `std.stdio`)) +$(LI $(RELATIVE_LINK2 shared-allocator-list,Added the `SharedAllocatorList`, as the thread-safe version of the regular `AllocatorList`.)) +$(LI $(RELATIVE_LINK2 sumtype_procedural_api,New procedural API for `std.sumtype`)) +$(LI $(RELATIVE_LINK2 unicode-16,std.uni has been upgraded from Unicode 15.1.0 to 16.0.0)) + +) + +$(BUGSTITLE_TEXT_HEADER Dub changes, + +$(LI $(RELATIVE_LINK2 fix-cimport-paths,Fix issue where cImportPaths wasn't working with dmd and ldc)) + +) + +$(CHANGELOG_SEP_HEADER_TEXT_NONEMPTY) + +$(CHANGELOG_SEP_HEADER_TEXT) + +$(BUGSTITLE_TEXT_BODY Compiler changes, + +$(LI $(LNAME2 dmd.auto-ref-local,Storage classes `ref` and `auto ref` can now be applied to local, static, extern, and global variables) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.auto-ref-local.dd) +$(P +For example, one can now write: +) +``` +struct S { int a; } + +void main() +{ + S s; + ref int r = s.a; + r = 3; + assert(s.a == 3); + + auto ref x = 0; + auto ref y = x; + static assert(!__traits(isRef, x)); + static assert( __traits(isRef, y)); +} +``` +) + +$(LI $(LNAME2 dmd.auto-ref-put-adjacent,Keywords `auto` and `ref` must be adjacent) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.auto-ref-put-adjacent.dd) +$(P +It's now deprecated to declare `auto ref` parameters without putting those two keywords next to each other. +This way it's clear that `auto ref` semantics are intended, rather than `ref` and `auto` semantics separately. +For the newly introduced $(RELATIVE_LINK2 dmd.reflocal, `ref` local / global variables), it's an error immediately. +) + +--- +void t()(ref const auto int x) // Deprecation +{ + ref auto y = x; // Error +} + +// Correction: +void t()(auto ref const int x) +{ + auto ref y = x; +} +--- +) + +$(LI $(LNAME2 dmd.default-align,The `align` attribute now allows specifying `default` explicitly) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.default-align.dd) +$(P +A lone `align` sets the alignment to the type’s default. +To be more explicit, `align(default)` does the same. +) + +``` +struct S +{ + align(4) + { + byte x; + align(default) long y; + long z; + } +} + +void main() +{ + pragma(msg, S.x.alignof); // 4 + pragma(msg, S.y.alignof); // 8 + pragma(msg, S.z.alignof); // 4 +} +``` +) + +$(LI $(LNAME2 dmd.delete-keyword,Remove `delete` as a keyword) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.delete-keyword.dd) +$(P +After being superseded by `destroy()`, deprecated, and turned into an error, `delete` can now be used as an identifier: +) + +--- +enum Action +{ + add, delete +} + +void delete(T)(T obj) +{ + +} +--- +) + +$(LI $(LNAME2 dmd.deprecation-case,Case fallthough for multivalued cases is an error now) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecation-case.dd) +$(P +This used to give a deprecation and now gives an error: +) +``` +int i; +switch (0) +{ + case 0, 1: i = 20; + default: assert(0); // Error: switch case fallthrough - use 'goto default;' if intended +} + +switch (0) +{ + default: + case 0, 1: i = 20; + case 2, 3: i = 30; // Error: switch case fallthrough - use 'goto case;' if intended +} +``` +) + +$(LI $(LNAME2 dmd.deprecation-dtor-fields,An error is now given for constructors when a field's destructor has stricter attributes) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecation-dtor-fields.dd) +``` +struct HasDtor +{ + ~this() {} +} + +struct Pure +{ + HasDtor member; + this(int) pure {} // Error: `this` has stricter attributes than its destructor (`pure`) +} + +struct Nothrow +{ + HasDtor member; + this(int) nothrow {} // Error: `this` has stricter attributes than its destructor (`nothrow`) +} + +struct NoGC +{ + HasDtor member; + this(int) @nogc {} // Error: `this` has stricter attributes than its destructor (`@nogc`) +} + +struct Safe +{ + HasDtor member; + this(int) @safe {} // Error: `this` has stricter attributes than its destructor (`@safe`) +} +``` +) + +$(LI $(LNAME2 dmd.deprecation-noop-assignment,Initializing a field with itself has been deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecation-noop-assignment.dd) +$(P +This is to prevent a common mistake when a field and a parameter ought to have the same name, +but one is misspelled where it's declared: +) + +--- +struct S +{ + int field; + + this(int feild) // supposed to be: this(int field) + { + this.field = field; // equal to this.field = this.field + } +} +--- +) + +$(LI $(LNAME2 dmd.deprecation-pointer-subtract,An error is now given for subtracting pointers of different types) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecation-pointer-subtract.dd) +$(P +The following code now gives errors: +) +``` +static assert(cast(void*)8 - cast(int*) 0 == 2L); +static assert(cast(int*) 8 - cast(void*)0 == 8L); +void test() +{ + auto foo = (ushort*).init - (ubyte*).init; +} +``` +) + +$(LI $(LNAME2 dmd.deprecation-throwing-contracts,An error is now issued for `in`/`out` contracts of `nothrow` functions that may throw) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecation-throwing-contracts.dd) +$(P +This used to issue a deprecation, it is now an error: +) +``` +void test() nothrow +in +{ + throw new Exception(null); // Error: `in` contract may throw but function is marked as `nothrow` +} +out +{ + throw new Exception(null); // Error: `out` contract may throw but function is marked as `nothrow` +} +do +{ +} +``` +) + +$(LI $(LNAME2 dmd.deprecation-typesafe-variadic-class,Typesafe variadic class parameters have been deprecated) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecation-typesafe-variadic-class.dd) +$(P +This obscure feature allowed a limited form of implicit construction: +) + +--- +void check(bool x, Exception e...) +{ + if (!x) + throw e; +} + +void main(string[] args) +{ + check(args.length > 1, "missing argument"); +} +--- + +$(P +However, few uses of this feature have been found, and one project was actually mistakenly using it instead of the more common Typesafe variadic array parameter. +Considering D doesn't support implicit construction and already has a confusing amount of different variadic parameter forms, it was decided to remove this feature. +) + +$(P +As a corrective action, either call the constructor in the callee: +) + +--- +void check(string msg) +{ + if (!x) + throw new Exception(msg); +} +--- + +$(P +Or let the caller construct the class instance: +) + +--- +void check(bool x, Exception e); + +void main(string[] args) +{ + check(args.length > 1, new Exception("missing argument")); +} +--- +) + +$(LI $(LNAME2 dmd.deprecation-version-debug-number,Integers in `debug` or `version` statements have been removed from the language) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.deprecation-version-debug-number.dd) +$(P +These were deprecated in 2.101. +Use `-debug=identifier` and `-version=identifier` instead for versions set on the command line, +and likewise `version = identifier;` and `debug = identifier;` for versions set in code at global scope. +) +) + +$(LI $(LNAME2 dmd.error-messages,Many error messages have changed) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.error-messages.dd) +$(P +Some changes have been made without being associated to a reported issue: +) + +$(P +Error messages for `@safe` violations now consistently mention they are related to `@safe` functions (or default functions with `-preview=safer`). +In general, function attributes that failed to infer have a more compact error message: +) + +$(P +Before: +$(CONSOLE +app.d(8): Error: function `attributediagnostic_nothrow.gc1` is not `nothrow` +app.d(2): which wasn't inferred `nothrow` because of: +app.d(2): `object.Exception` is thrown but not caught +) +) + +$(P +After: +$(CONSOLE +app.d(8): Error: function `attributediagnostic_nothrow.gc1` is not `nothrow` +app.d(2): and `object.Exception` being thrown but not caught makes it fail to infer `nothrow` +) +) + +$(P +Function literals are now referred to by their (truncated) function body, instead of the internal `__lambda` name. +) + +--- +/* +BEFORE: + +../test/test_.d(3): Error: function literal `__lambda1()` is not callable using argument types `(int)` + (() => 42)(1); + ^ +AFTER: + +../test/test_.d(3): Error: function literal `() => 42` is not callable using argument types `(int)` + (() => 42)(1); + ^ +*/ +--- + +$(P +Match levels are now mentioned on ambiguous overloads: [#20637](https://github.com/dlang/dmd/pull/20637) +) + +$(P +Before: +$(CONSOLE +Error: `app.bar` called with argument types `(string)` matches both: +) +) + +$(P +After: +$(CONSOLE +Error: `app.bar` called with argument types `(string)` matches multiple overloads after implicit conversions: +) +) + +$(P +Error messages related to operator overloading have been improved. +When the related template functions (`opUnary`, `opBinary`, `opBinaryRight`, `opOpAssign`, `opIndex`, `opSlice`) +are missing, a suggestion to implement them is given. +) + +$(P +When they do exist but fail to instantiate, the error from instantiation is shown. +There's no longer a need to manually e.g. rewrite `s + 1` to `s.opBinary!"+"(1)` to diagnose the error. +) + +--- +struct S {} + +void main() +{ + S s; + const x = s[3 .. "4"]; +} +--- + +$(P +Before: +$(CONSOLE +app.d(6): Error: no `[]` operator overload for type `S` +) +) + +$(P +After: +$(CONSOLE +app.d(6): Error: no `[3.."4"]` operator overload for type `S` +app.d(1): perhaps define `auto opSlice(int lower, string upper) {}` for `app.S` +) +) + +--- +struct Str {} + +struct Number +{ + int x; + int opBinary(string op : "+")(int rhs) => this.x + x; +} + +void f(Str str, Number number) +{ + const s = str ~ "hey"; + const n = number + "oops"; +} +--- + +$(P +Before: +$(CONSOLE +app.d(12): Error: incompatible types for `(str) ~ ("hey")`: `Str` and `string` + const s = str ~ "hey"; + ^ +app.d(13): Error: incompatible types for `(number) + ("oops")`: `Number` and `string` + const n = number + "oops"; +) +) + +$(P +After: +$(CONSOLE +app.d(12): Error: operator `~` is not defined for type `Str` + const s = str ~ "hey"; + ^ +app.d(2): perhaps overload the operator with `auto opBinary(string op : "~")(string rhs) {}` +struct Str {} +^ +app.d(13): Error: function `test_.Number.opBinary!"+".opBinary(int rhs)` is not callable using argument types `(string)` + const n = number + "oops"; + ^ +app.d(13): cannot pass argument `"oops"` of type `string` to parameter `int rhs` +app.d(7): `opBinary` defined here + int opBinary(string op : "+")(int rhs) => this.x + x; + ^ +) +) + +$(P +Furthermore: +) + +$(P +- D1 operator overloading functions (`opAdd`, `opDot`) are completely removed and no longer mentioned in error messages specifically. +- Class allocators (`auto new() {}`) are not only a semantic error, but no longer parse. +) +) + +$(LI $(LNAME2 dmd.extern-std-cpp23,The compiler now accepts `-extern-std=c++23`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.extern-std-cpp23.dd) +$(P +The compiler now accepts c++23 as a supported standard for `-extern-std=`. +Currently this only changes the value of `__traits(getTargetInfo, "cppStd")`. +) +) + +$(LI $(LNAME2 dmd.ftime-trace,Build time profiling has been added to DMD) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.ftime-trace.dd) +$(P +The `-ftime-trace` switch that the LDC compiler already has, is now also available in dmd. +It can be used to figure out which parts of your code take the longest to compile, so you can optimize your build times. +) + +$(P +$(CONSOLE +dmd -ftime-trace app.d +) +) + +$(P +This will output `app.o.time-trace`. +) + +$(P +A different output file can be selected with `-ftime-trace-file=trace.json`. +) + +$(P +The output is in Google Chrome's profiler format, which can be viewed in an interactive viewer like [ui.perfetto.dev](https://ui.perfetto.dev). +) + +$(P +See also the YouTube tutorial [*Easily Reduce Build Times by Profiling the D Compiler*](https://www.youtube.com/watch?v=b8wZqU5t9vs). +) +) + +$(LI $(LNAME2 dmd.getBitfieldInfo,New traits `getBitfieldOffset` and `getBitfieldWidth` for built-in bitfields) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.getBitfieldInfo.dd) +$(P +This completes the introspection capabilities of built-in bitfields. For example: +) + +--- +struct S +{ + int a,b; + int :2, c:3; +} + +static assert(__traits(getBitfieldOffset, S.b) == 0); +static assert(__traits(getBitfieldOffset, S.c) == 2); +static assert(__traits(getBitfieldWidth, S.b) == 32); +static assert(__traits(getBitfieldWidth, S.c) == 3); +--- +) + +$(LI $(LNAME2 dmd.import-c-i,Using the compiler flag `-i` will now properly pick up C source files) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.import-c-i.dd) +$(P +Previously, you needed to manually include `*.c` source files, it now works just like with D files. +) +) + +$(LI $(LNAME2 dmd.importc-pragma-stc,A pragma for ImportC allows to set `nothrow`, `@nogc` or `pure`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.importc-pragma-stc.dd) +$(P +The following new pragma for ImportC allows to set default storage +classes for function declarations: +) +```c +#pragma attribute(push, [storage classes...]) +``` +$(P +The storage classes `nothrow`, `nogc` and `pure` are supported. +Unrecognized attributes are ignored. +Enabling a default storage class affects all function declarations +after the pragma until it is disabled with another pragma. +Declarations in includes are also affected. +The changed storage classes are pushed on a stack. The last change can +be undone with the following pragma. +The following example +enables `@nogc` and `nothrow` for a library: +) + +```c +#pragma attribute(push, nogc, nothrow) +#include +#pragma attribute(pop) +``` + +$(P +This can also disable multiple default storage classes at the same time, +if they were enabled with a single `#pragma attribute(push, ...)` directive. +) +) + +$(LI $(LNAME2 dmd.mixin-assign,Mixin templates can now use assignment syntax) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.mixin-assign.dd) +$(P +Previously, giving a name to a mixed-in mixin template instance required putting the name at the end. +Now, it can also go in front of the instantiation using assignment syntax. +) +--- +mixin MyMixinTemplate!(Args) myName; // old style +mixin myName = MyMixinTemplate!(Args); // new style +--- +) + +$(LI $(LNAME2 dmd.obj_extensions,Object file extensions `.o` and `.obj` are now accepted on all platforms) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.obj_extensions.dd) +$(P +Accepting `.o` and `.obj` file extensions on all platforms makes DMD behave +like Clang and other modern compilers. There is no point in +discarding `*.o` or `*.obj` depending on the current operating system, as both extensions +unambiguously denote object file. +) +) + +$(LI $(LNAME2 dmd.objc-improvements,Objective-C selectors are now automatically generated when not specified with `@selector`.) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.objc-improvements.dd) +$(P +Additionally, the Objective-C selector generation rules have changed, following these steps: +1. Functions marked with `@property` will generate `setXYZ:` for the setters. +2. For property functions with names starting with `is`, that prefix will be stripped off in the setter. +3. Selector generation now uses the names of the function parameters instead of their D-mangled types. +) + +$(P +Selectors may still be specified with the `@selector` UDA, in which case it takes precedence over the +automatically generated selectors. +) + +$(P +These new rules apply both for `extern` and non-`extern` Objective-C classes and protocols. +) + +--- +extern(Objective-C) +extern class NSObject { + static NSObject alloc(); // Generates as `alloc` + NSObject init(); // Generates as `init` +} + +extern(Objective-C) +class Fox : NSObject { + bool fluffy; + + @property bool isFluffy() => fluffy; // `isFluffy` + @property void isFluffy(bool value) { fluffy = value; } // `setFluffy:` + + void yip(int a) @selector("bark:") { // `bark:` + // ... + } + + void doSomething(int a, int b, int c) { // `doSomething:b:c:` + // ... + } +} +--- + +$(P +These changes should not break any existing code because the automatic selector generation +was not present before. And automatic selector generation only applies to `extern(Objective-C)` methods. +) +) + +$(LI $(LNAME2 dmd.oq-compiler-switch,New compiler switch `-oq` for DMD) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.oq-compiler-switch.dd) +$(P +The switch gives fully qualified names to object files, preventing name conflicts when using the switch `-od` +while compiling multiple modules with the same name, but inside different packages. +The switch already existed in LDC, but is now in dmd as well. +) + +$(P +Example: +) + +$(P +$(CONSOLE +dmd -c -oq -od=. app.d util/app.d misc/app.d +) +) + +$(P +This will output `app.obj`, `util.app.obj`, and `misc.app.obj`, instead of just `app.obj`. +) + +$(P +The switch `-oq` also applies to other outputs, such as Ddoc (`-D -Dd=.`) and `.di` header generation (`-H -Hd=.`). +) +) + +$(LI $(LNAME2 dmd.placementNew,Added Placement New Expression) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.placementNew.dd) +$(P +Placement `new` explicitly provides the storage for `new` expression to initialize +with the newly created value, rather than using the GC. +) + +--- +struct S +{ + float d; + int i; + char c; +} + +void main() @system @nogc +{ + S s; + S* p = new (s) S(3.14, 42, 'X'); // place new object into s + assert(p.i == 42 && p.c == 'X'); +} +--- +) + +$(LI $(LNAME2 dmd.postfix-this-attributes,Postfix type qualifier method attributes for `-H` and `-D`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.postfix-this-attributes.dd) +$(P +The `.di` interface file generation and Ddoc output will now have type qualifier +attributes placed after the parameter list for methods (and constructors). +This avoids confusion with the return type. +) + +--- +struct S +{ + const int f(); // before + int f() const; // now +} +--- +) + +$(LI $(LNAME2 dmd.remove-samples,The folder *samples* has been removed from DMD installations) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.remove-samples.dd) +$(P +Every DMD release has included a folder with small D code examples. +These examples are quite old, and not a good representation of modern D. +They're also hard to discover, since D compilers are often installed through an installer or package manager. +) + +$(P +Since there are better resources available online nowadays, these samples have +been moved to the [undeaD](https://github.com/dlang/undeaD) repository. +) +) + +$(LI $(LNAME2 dmd.rvalue,New keyword `__rvalue`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.rvalue.dd) +$(P +The newly added primary expression of the form `__rvalue(expression)` +evaluates to `expression`, except that it is treated as an rvalue, +even if would be an lvalue otherwise. +) + +$(P +Overloads on `ref`: +) +``` +foo( S s); // selected if the argument is an rvalue +foo(ref S s); // selected if the argument is an lvalue + +S s; +S bar(); +... +foo(s); // selects foo(ref S) +foo(bar()); // selects foo(S) +``` +$(P +With this change: +) +``` +foo(__rvalue(s)); // selects foo(S) +``` +$(P +This also applies to constructors and assignments, meaning move constructors and +move assignments are enabled. Moving instead of copying can be much more resource +efficient, as, say, a string can be moved rather than copied/deleted. +) + +$(P +A moved object will still be destructed, so take that into account when moving +a field - set it to a benign value that can be destructed. +) + +$(P +`__rvalue` may also be used as an attribute on a function which returns by ref +to declare that the result should be treated as an rvalue at the callsite: +) +``` +ref T move(T)(return ref T source) __rvalue +{ + return source; +} + +S s; +S t = move(s); // call expression rewritten as: S t = __rvalue(move(s)) +``` +$(P +This is used as an internal tool to implement library primitives such as `move` and `forward`. +) +) + +$(LI $(LNAME2 dmd.safer,Add `-preview=safer` switch for safety checking on unattributed functions) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.safer.dd) +$(P +All the checks currently enabled in `@safe` code, that are easily fixed (as in +the fix is constrained to the function), will be enabled in `-preview=safer` code. +) + +$(P +Code not easily fixed, such as calls to `@system` or unattributed functions, will +be allowed as before. +) + +--- +void f(); +@system void g(); + +void main() +{ + int* p; + p++; // Error, pointer arithmetic + f(); // allowed + g(); // allowed +} +--- + +$(P +For more information, see [this document](https://github.com/WalterBright/documents/blob/38f0a846726b571f8108f6e63e5e217b91421c86/safer.md). +) +) + +$(LI $(LNAME2 dmd.shortened-method-constructor,Shortened method syntax can now be used in constructors) +$(CHANGELOG_SOURCE_FILE dmd, changelog/dmd.shortened-method-constructor.dd) +$(P +This used to raise an error (cannot return expression from constructor), but is now supported: +) + +--- +struct Number +{ + int x; + + void vf(int); + this(int x) => vf(x); + this(float x) => this(cast(int) x); +} +--- + +$(P +The expression body must be a `this`/`super` call or have type `void`. +) + +$(P +Postblits and destructors already supported shortened method syntax because they return `void`. +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Runtime changes, + +$(LI $(LNAME2 druntime.bcrypt,Add Windows BCrypt bindings under `core.sys.windows.bcrypt`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.bcrypt.dd) +$(P +Adds full [BCrypt API](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/) bindings +to the Windows-specific system bindings. +) + +$(P +The Windows-specific bindings under `core.sys.windows.sdkddkver` and `core.sys.windows.w32api` +have also been updated in order to facilitate the creation of the BCrypt bindings. +) +) + +$(LI $(LNAME2 druntime.criticalRegionLock,Remove `criticalRegionLock`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.criticalRegionLock.dd) +$(P +The `criticalRegionLock` feature suffer from a serious design flaw: $(LINK https://issues.dlang.org/show_bug.cgi?id=24741) +) + +$(P +It turns out it is not used, so rather than fixing the flaw, the feature was removed. +) +) + +$(LI $(LNAME2 druntime.expect-trap,Adds `expect`, `likely`, `unlikely`, and `trap` to `core.builtins`) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.expect-trap.dd) +$(P +Adds the functions `expect` and `likely`/`unlikely` for branch and value hints for the LDC/GDC compilers. +DMD ignores these hints. +) + +$(P +Adds the function `trap` to be lowered to the target-dependent trap instruction. +If the target does not have a trap instruction, this intrinsic will be lowered to a call of the `abort` function. +) +) + +$(LI $(LNAME2 druntime.segfault-message,New segfault handler showing backtraces for null access / call stack overflow on linux) +$(CHANGELOG_SOURCE_FILE dmd, changelog/druntime.segfault-message.dd) +$(P +While buffer overflows are usually caught by array bounds checks, there are still other situations where a segmentation fault occurs in D programs: +) + +$(P +- `null` pointer dereference +- Corrupted or dangling pointer dereference in `@system` code +- Call stack overflow (infinite recursion) +) + +$(P +These result in an uninformative runtime error such as: +) + +$(P +$(CONSOLE +[1] 37856 segmentation fault (core dumped) ./app +) +) + +$(P +In order to find the cause of the error, the program needs to be run again in a debugger like GDB. +) + +$(P +There is the `registerMemoryErrorHandler` function in `etc.linux.memoryerror`, which catches `SIGSEGV` signals and transforms them into a thrown `InvalidPointerError`, providing a better message. +However, it doesn't work on call stack overflow, because it uses stack memory itself, so the segfault handler segfaults. +It also relies on inline assembly, limiting it to the x86 architecture. +) + +$(P +A new function `registerMemoryAssertHandler` has been introduced, which does handle stack overflow by setting up an [altstack](https://man7.org/linux/man-pages/man2/sigaltstack.2.html). +It uses `assert(0)` instead of throwing an `Error` object, so the result corresponds to the chosen `-checkaction` setting. +) + +$(P +Example: +) + +--- +void main() +{ + version (linux) + { + import etc.linux.memoryerror; + registerMemoryAssertHandler(); + } + int* p = null; + int* q = cast(int*) 0xDEADBEEF; + + // int a = *p; // segmentation fault: null pointer read/write operation + // int b = *q; // segmentation fault: invalid pointer read/write operation + recurse(); // segmentation fault: call stack overflow +} + +void recurse() +{ + recurse(); +} +--- + +$(P +Output with `dmd -g -run app.d`: +) + +$(P +$(CONSOLE +core.exception.AssertError@src/etc/linux/memoryerror.d(82): segmentation fault: call stack overflow +$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH) +src/core/exception.d:587 onAssertErrorMsg [0x58e270d2802d] +src/core/exception.d:803 _d_assert_msg [0x58e270d1fb64] +src/etc/linux/memoryerror.d:82 _d_handleSignalAssert [0x58e270d1f48d] +??:? [0x7004139e876f] +./app.d:16 void scratch.recurse() [0x58e270d1d757] +./app.d:18 void scratch.recurse() [0x58e270d1d75c] +./app.d:18 void scratch.recurse() [0x58e270d1d75c] +./app.d:18 void scratch.recurse() [0x58e270d1d75c] +./app.d:18 void scratch.recurse() [0x58e270d1d75c] +... +... +... +) +) +) + + +) + +$(BUGSTITLE_TEXT_BODY Library changes, + +$(LI $(LNAME2 bit-cast,Added `std.conv.bitCast`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/bit-cast.dd) +$(P +This convenience function allows reinterpreting casts to be written in a more +readable way. +) + +--- +uint n = 0xDEADBEEF; + +// Before +writeln("Bytes of n are: ", *cast(const ubyte[4]*) &n); + +// After +writeln("Bytes of n are: ", n.bitCast!(const ubyte[4])); +--- +) + +$(LI $(LNAME2 formatted_read_tuple_return,Extend the functionality of formattedRead to permit a std.file.slurp like execution.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/formatted_read_tuple_return.dd) +$(P +Template argument types can now be passed to formattedRead along with a +format string to parse and read the input range as a Tuple of those arguments. +All arguments must be read successfully, otherwise, and unlike std.file.slurp +which has non exhaustive option for partial reads, it'll throw a std.format.FormatException. +) + +--- +import std.exception : assertThrown; +import std.format : FormatException; +import std.typecons : tuple; + +@safe pure unittest +{ + auto complete = "hello!34.5:124".formattedRead!(string, double, int)("%s!%s:%s"); + assert(complete == tuple("hello", 34.5, 124)); + + assertThrown!FormatException("hello!34.5:".formattedRead!(string, double, int)("%s!%s:%s")); +} + +/// The format string can be checked at compile-time: +@safe pure unittest +{ + auto expected = tuple("hello", 124, 34.5); + auto result = "hello!124:34.5".formattedRead!("%s!%s:%s", string, int, double); + assert(result == expected); + + assertThrown!FormatException("hello!34.5:".formattedRead!("%s!%s:%s", string, double, int)); +} +--- +) + +$(LI $(LNAME2 fromhexstring,Added fromHexString and fromHexStringAsRange functions to std.digest.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/fromhexstring.dd) +$(P +This new function enables the converion of a hex string to a range of bytes. +Unlike the template $(REF hexString, std, conv) that was designed to supersede +a language feature, this function is usable with runtime input. +) + +$(P +The `std.conv` module lacks facilities to conveniently transform the input +to a series of bytes directly. Both $(REF parse, std, conv) and $(REF to, std, +conv) can only handle the conversion for a single value of the requested target +integer type. Furthermore, said functions would allocate a new buffer for the +result, while `fromHexStringAsRange` operates lazily by implementing a forward +range. +) + +$(P +For further convenience, a validation function $(REF isHexString, std, digest) +was added as well. +) +) + +$(LI $(LNAME2 odbc-4,ODBC Bindings in `etc.c.odbc` have been updated to ODBC 4.0.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/odbc-4.dd) +$(P +ODBC 4.0, via these new bindings, adds the following functionality: +) + +$(P +1. Support for semi-structured data, such as JSON. +2. Collection valued columns. +3. Web-based Authorization flows. +) + +$(P +A full list of new features can be found here: https://github.com/Microsoft/ODBC-Specification/blob/master/ODBC%204.0.md +) + +$(P +Additionally these modules add support for 64-bit ODBC interfaces. +) +) + +$(LI $(LNAME2 pop-grapheme,Added popGrapheme function to std.uni.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/pop-grapheme.dd) +$(P +The new function is a cross between the existing $(REF graphemeStride, std, +uni) and $(REF decodeGrapheme, std, uni) functions. The new function both +supports `@safe pure nothrow @nogc` like `graphemeStride` does as long as you +don't rely on autodecoding (side node: `@nogc` support for `graphemeStride` +added in this release), and works with any non-array ranges just like +`decodeGrapheme` does. +) + +$(P +Example: +) + +------- +import std.uni; + +// Two Union Jacks of the Great Britain in each +string s = "\U0001F1EC\U0001F1E7\U0001F1EC\U0001F1E7"; +wstring ws = "\U0001F1EC\U0001F1E7\U0001F1EC\U0001F1E7"; +dstring ds = "\U0001F1EC\U0001F1E7\U0001F1EC\U0001F1E7"; + +// String pop length in code units, not points. +assert(s.popGrapheme() == 8); +assert(ws.popGrapheme() == 4); +assert(ds.popGrapheme() == 2); + +assert(s == "\U0001F1EC\U0001F1E7"); +assert(ws == "\U0001F1EC\U0001F1E7"); +assert(ds == "\U0001F1EC\U0001F1E7"); + +import std.algorithm.comparison : equal; +import std.algorithm.iteration : filter; + +// Also works for non-random access ranges as long as the +// character type is 32-bit. +auto testPiece = "\r\nhello!"d.filter!(x => !x.isAlpha); +// Windows-style line ending is two code point in a single grapheme. +assert(testPiece.popGrapheme() == 2); +assert(testPiece.equal("!"d)); +------- +) + +$(LI $(LNAME2 readfln,Added `readfln` and `File.readfln` to `std.stdio`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/readfln.dd) +$(P +These functions read a single line of input and parse it using a format string. +Unlike `readf`, they will not accidentally read multiple lines if the user +forgets to include a line terminator in the format string—a common mistake for +beginners. +) +) + +$(LI $(LNAME2 shared-allocator-list,Added the `SharedAllocatorList`, as the thread-safe version of the regular `AllocatorList`.) +$(CHANGELOG_SOURCE_FILE phobos, changelog/shared-allocator-list.dd) +$(P +The new $(REF SharedAllocatorList, std,experimental,allocator,building_blocks,allocator_list) has the same semantics as the regular `AllocatorList`. +Just as the regular `AllocatorList`, if the `BookkeepingAllocator` is `NullAllocator`, the `SharedAllocatorList` will switch to `ouroboros` mode, +allocationg memory for its own metadata. +) + +--- +SharedAllocatorList!((n) => SharedAscendingPageAllocator(max(n, numPages * pageSize)), NullAllocator) a; +auto b = a.allocate(100); +assert(b.length == 100); + +assert(a.deallocate(b)); +--- +) + +$(LI $(LNAME2 sumtype_procedural_api,New procedural API for `std.sumtype`) +$(CHANGELOG_SOURCE_FILE phobos, changelog/sumtype_procedural_api.dd) +$(P +`std.sumtype` has three new convenience functions for querying and retrieving +the value of a `SumType` object. +) + +$(P +* `has!T` returns `true` if the `SumType` object has a value of type `T`. +* `get!T` returns the value if its type is `T`, or asserts if it is not. +* `tryGet!T` returns the value if its type is `T`, or throws an exception if it + is not. +) + +$(P +These functions make it easier to write code using `SumType` in a procedural +style, as opposed to the functional style encouraged by `match`. +) + +$(P +Example: +) + +--- +import std.sumtype; +import std.stdio; + +SumType!(string, double) example = "hello"; + +if (example.has!string) +{ + writeln("string: ", example.get!string); +} +else if (example.has!double) +{ + writeln("double: ", example.get!double); +} + +try +{ + writeln("double: ", example.tryGet!double); +} +catch (MatchException e) +{ + writeln("Couldn't get a double."); +} +--- +) + +$(LI $(LNAME2 unicode-16,std.uni has been upgraded from Unicode 15.1.0 to 16.0.0) +$(CHANGELOG_SOURCE_FILE phobos, changelog/unicode-16.dd) +$(P +This Unicode update was released September 10, 2024, and adds new blocks with characters. +See: https://www.unicode.org/versions/Unicode16.0.0/ +) + +``` +import std; + +void main() +{ + const alphaCount = iota(0, dchar.max).filter!(std.uni.isAlpha).walkLength; + writeln(alphaCount); + // formerly: 138387 + // now: 142759 +} +``` +) + + +) + +$(BUGSTITLE_TEXT_BODY Dub changes, + +$(LI $(LNAME2 fix-cimport-paths,Fix issue where cImportPaths wasn't working with dmd and ldc) +$(CHANGELOG_SOURCE_FILE dub, changelog/fix-cimport-paths.dd) +$(P +dub was passing -I instead of -P-I as is required by those compilers +) +) + + +) + +$(CHANGELOG_SEP_TEXT_BUGZILLA) + +$(BUGSTITLE_BUGZILLA DMD Compiler regression fixes, + +$(LI $(BUGZILLA 10713): [REG2.063] ICE with typeof$(LPAREN)this.nonExistingField$(RPAREN) in method signature) +$(LI $(BUGZILLA 20562): [dmd] Memory allocation failed $(LPAREN)ERROR: This is a compiler bug$(RPAREN)) +$(LI $(BUGZILLA 20686): failed static assert using a combination of __traits and unfinished type) +$(LI $(BUGZILLA 20730): [REG 2.091] __traits$(LPAREN)compiles$(RPAREN) fails if any ungagged errors occurred in compilation) +) +$(BUGSTITLE_BUGZILLA DMD Compiler bug fixes, + +$(LI $(BUGZILLA 4101): [tdpl] DMD doesn't give error when goto skips initialization) +$(LI $(BUGZILLA 4174): Template interface functions not allowed, making operator overloads difficult) +$(LI $(BUGZILLA 9662): Implement RDMD test suite) +$(LI $(BUGZILLA 10257): .tupleof loses protection information upon iteration) +$(LI $(BUGZILLA 10370): ICE on invalid imports when module is used as package) +$(LI $(BUGZILLA 10386): Package import feature breaks with static libraries) +$(LI $(BUGZILLA 10574): "auto ref" fails to match when IFTI succeeds $(LPAREN)strip to level const$(RPAREN)) +$(LI $(BUGZILLA 10587): __traits$(LPAREN)getAttributes$(RPAREN) doesn't work on incomplete templated types) +$(LI $(BUGZILLA 10603): Refused pure attribute on the left for function pointer argument) +$(LI $(BUGZILLA 10639): Win64: wrong optimizer codegen with struct literal with complex fields) +$(LI $(BUGZILLA 10699): override inconsistently allowed for abstract functions) +$(LI $(BUGZILLA 16643): CTFE internal error with null) +$(LI $(BUGZILLA 17503): is-expression pattern in static if matches too many types) +$(LI $(BUGZILLA 20587): _rt_loadLibrary symbol not found) +$(LI $(BUGZILLA 20603): 'cannot use non-constant CTFE pointer in an initializer' in recursive structure with overlap) +$(LI $(BUGZILLA 20610): const in a .tupleof loop is ignored) +$(LI $(BUGZILLA 20621): Since DMD 2.087.0: 32 Bit Linux now uses XMM registers: SIGILL, Illegal instruction on intel Pentium III) +$(LI $(BUGZILLA 20688): Wrong code when linking to C complex number functions) +$(LI $(BUGZILLA 20691): Converting scope static array to scope dynamic array should be error) +$(LI $(BUGZILLA 20812): _d_assocarrayliteralTX segfault assigning a shared associative array an AA literal) +$(LI $(BUGZILLA 20831): __traits$(LPAREN)getAttributes$(RPAREN) failes to compile when used on a parameter with no name) +$(LI $(BUGZILLA 20912): Compiler incorrectly lists non-matching overloads as matching in diagnostic) +$(LI $(BUGZILLA 21020): named import in with block masks local symbol) +$(LI $(BUGZILLA 21995): Struct with size uint.max or greater causes ICE) +$(LI $(BUGZILLA 23131): With -vasm all the X87 instructions are printed wrong.) +$(LI $(BUGZILLA 23294): [dip1000] parameter to parameter assignment leads to incorrect scope inference) +$(LI $(BUGZILLA 23830): Azure failure for OMF: Module name not printed before struct symbol) +$(LI $(BUGZILLA 23841): isZeroInit does not take into account unions) +$(LI $(BUGZILLA 24153): Inliner breaks -betterC by requiring TypeInfo) +$(LI $(BUGZILLA 24375): ImportC: .di generator outputs C expression with `->` operator) +$(LI $(BUGZILLA 24447): ImportC: extern symbols cannot have initializers) +$(LI $(BUGZILLA 24651): Bitfield layout wrong for 48-bit field on 32-bit Linux) +$(LI $(BUGZILLA 24663): dip1000 doesn't check slice expression implicitly converted to static array) +$(LI $(BUGZILLA 24669): ImportC: C files are not compiled with '-i' flag) +$(LI $(BUGZILLA 24670): importC: .di generation does not place parentheses around const struct return types) +$(LI $(BUGZILLA 24694): [DIP1000] can escape stack pointer through struct.class.field) +$(LI $(BUGZILLA 24701): No error produced from casted noreturn variable) +$(LI $(BUGZILLA 24705): Arguments of synchronized method are unintentionally treated as shared with -preview=nosharedaccess) +$(LI $(BUGZILLA 24706): Missing errors for first operand of comma expression) +$(LI $(BUGZILLA 24707): error message has bad parameter attribute order) +$(LI $(BUGZILLA 24733): ImportC: `#pragma pack$(LPAREN)pop$(RPAREN)` restores wrong alignment) +$(LI $(BUGZILLA 24748): DMD can't output object files with fully qualified name, making -od overwirte each other file) +$(LI $(BUGZILLA 24762): @nogc false positive error) +$(LI $(BUGZILLA 24776): Struct with anonymous union has wrong isZeroInit) +$(LI $(BUGZILLA 24803): __traits$(LPAREN)location$(RPAREN) is inconsistent with modules) +$(LI $(BUGZILLA 24807): Error message missing parens for template instance) +$(LI $(BUGZILLA 24819): Optimizer changes result of float calculations on 32-bit) +$(LI $(BUGZILLA 24822): When passing a non-POD argument to an rvalue parameter, an unnecessary blit is done) +$(LI $(BUGZILLA 24830): separate compilation + circular deps + templated opCmp = missing symbols) +$(LI $(BUGZILLA 24836): struct return by hidden struct arg does not need copy to become an rvalue) +$(LI $(BUGZILLA 24845): Compiler error when trying to assign to an AA value of an enum instance) +$(LI $(BUGZILLA 24848): bad parser diagnostic for a partial MulExp) +$(LI $(BUGZILLA 24855): VRP fails to prevent overflow after division) +$(LI $(BUGZILLA 24861): Vestige of 16 bit code being accidentally generated) +$(LI $(BUGZILLA 24871): DDoc strips indent in triple slash comments) +$(LI $(BUGZILLA 24883): Speculative template overload error escapes with `-preview=rvaluerefparam`) +$(LI $(BUGZILLA 24891): Two scope attributes emitted as part of .di generation) +) +$(BUGSTITLE_BUGZILLA DMD Compiler enhancements, + +$(LI $(BUGZILLA 9811): Add static code analyzing $(LPAREN)i.e. PVS-Studio-like diagnostic$(RPAREN)) +$(LI $(BUGZILLA 9997): Missed misspell suggestions for UFCS) +$(LI $(BUGZILLA 10023): Add rtInfo $(LPAREN)or equivalent$(RPAREN) to ModuleInfo) +$(LI $(BUGZILLA 18235): Group logically similar tests into the same module in the D2 testsuite) +$(LI $(BUGZILLA 20516): [D 2.0 FAQ]) +$(LI $(BUGZILLA 20614): CTFE supports typeid$(LPAREN)stuff$(RPAREN).name but not classinfo.name) +$(LI $(BUGZILLA 20888): std.range.Cycle does not compose with `const`) +$(LI $(BUGZILLA 20960): -profile=gc does not track class objects allocated with new) +$(LI $(BUGZILLA 20982): Add a pragma to suppress deprecation messages) +$(LI $(BUGZILLA 21564): Allow assignment syntax for instantiating mixin templates) +$(LI $(BUGZILLA 23449): spellchecker should suggest corrections for pointer members) +$(LI $(BUGZILLA 23812): ImportC: allow adding function attributes to imported C functions) +$(LI $(BUGZILLA 24639): ImportC: defines of negative constants not detected for enum conversion) +$(LI $(BUGZILLA 24645): Hidden static assert error messages if more than 20 errors) +$(LI $(BUGZILLA 24738): Import core.interpolation suggestion) +$(LI $(BUGZILLA 24745): Better error message when creating an associative array with the wrong syntax) +$(LI $(BUGZILLA 24749): A clause consisting only of "throw" should be the unlikely path) +) +$(BUGSTITLE_BUGZILLA Phobos bug fixes, + +$(LI $(BUGZILLA 64): Unhandled errors should go to stderr) +$(LI $(BUGZILLA 10581): Undefined identifier "std.uni.isWhite" when passing string lambda to std.algorithm.filter) +$(LI $(BUGZILLA 10607): DirEntry has no constructor) +$(LI $(BUGZILLA 10647): AutoImplement should implement overridden member functions with 'override' attributes) +$(LI $(BUGZILLA 10680): BigInt uses deprecated std.traits.unsigned) +$(LI $(BUGZILLA 14138): std.parallelism.task breaks @safety) +$(LI $(BUGZILLA 15315): can break immutable with std.algorithm.move) +$(LI $(BUGZILLA 20870): std.outbuffer.printf is trusted) +$(LI $(BUGZILLA 20872): std.array.assocArray trusts user-provided 'front' for values) +$(LI $(BUGZILLA 20929): std.experimental.allocator.expandArray's range-based overload fails to instantiate for char and wchar arrays.) +$(LI $(BUGZILLA 23300): std.array : array wrongly propagates scopeness of source) +$(LI $(BUGZILLA 24667): goo.gl is going away) +$(LI $(BUGZILLA 24685): std.stdio.File.rawRead allows reading raw pointers from files in @safe code) +$(LI $(BUGZILLA 24704): The error message for DateTime.fromISOExtString says that valid ISO extended strings that it does not support are invalid ISO extended strings) +$(LI $(BUGZILLA 24715): std/process: Default to libc `closefrom` in spawnProcessPosix) +$(LI $(BUGZILLA 24773): Stable sort$(LPAREN)$(RPAREN) invokes the destructor on uninitialized elements) +$(LI $(BUGZILLA 24801): `RefRange` doesn’t work if range primitives are not `const`) +$(LI $(BUGZILLA 24809): In some cases, stable sort assigns to unininitialized elements) +$(LI $(BUGZILLA 24818): Tag of a single-type SumType wastes space) +) +$(BUGSTITLE_BUGZILLA Phobos enhancements, + +$(LI $(BUGZILLA 10538): std.typecons.wrap should consider opDispatch) +$(LI $(BUGZILLA 17214): std.array.Appender has an unnecessary indirection) +$(LI $(BUGZILLA 17479): Public constructor for std.process.Pid) +$(LI $(BUGZILLA 20330): json toString with outputrange) +$(LI $(BUGZILLA 20889): Support construction of std.bigint.BigInt from a sign and a byte-array magnitude) +$(LI $(BUGZILLA 21045): std.getopt: Support blank as separator of multiple values) +$(LI $(BUGZILLA 22293): Nullable should define opCast!bool) +$(LI $(BUGZILLA 24524): Very slow process fork if RLIMIT_NOFILE is too high) +$(LI $(BUGZILLA 24698): Appender needs to expose readonly property 'size_t length' without using 'data' property) +$(LI $(BUGZILLA 24823): std.json: Allow optionally preserving the order of fields in JSON objects) +$(LI $(BUGZILLA 24851): Some members of CustomFloat can have const this) +$(LI $(BUGZILLA 24875): std.traits.isAggregateType does not consider enums of aggregate types to be aggregate types) +) +$(BUGSTITLE_BUGZILLA Druntime bug fixes, + +$(LI $(BUGZILLA 10380): [AA] Wrong code using associative array as key type in associative array) +$(LI $(BUGZILLA 20763): checkaction=context does not format pointers) +$(LI $(BUGZILLA 24660): atomic_wchar_t has wrong size on Posix) +$(LI $(BUGZILLA 24661): wctype_t and wctrans_t are platform-dependent) +$(LI $(BUGZILLA 24835): hasElaborateAssign is true for structs where opAssign is disabled if a member variable has elaborate assignment) +$(LI $(BUGZILLA 24864): hasElaborateDestructor incorrectly true for structs with anonymous unions) +) +$(BUGSTITLE_BUGZILLA Druntime enhancements, + +$(LI $(BUGZILLA 17416): SocketOption.REUSEPORT not available on linux) +$(LI $(BUGZILLA 19369): core.sys.posix.setjmp lacks support for Darwin) +$(LI $(BUGZILLA 20567): GC should not start threads for parallel marking in simple programs) +) +$(BUGSTITLE_BUGZILLA dlang.org bug fixes, + +$(LI $(BUGZILLA 10565): Level-5 titles are missing in Language reference) +$(LI $(BUGZILLA 10605): Lambda grammar is not sufficient) +$(LI $(BUGZILLA 14945): unions are missing from the ABI page) +$(LI $(BUGZILLA 20601): [Oh No! Page Not Found]) +$(LI $(BUGZILLA 24680): [dip1000] final auto class method infers scope but no return) +$(LI $(BUGZILLA 24732): FAQ article is out of date on calling printf) +) +$(BUGSTITLE_BUGZILLA dlang.org enhancements, + +$(LI $(BUGZILLA 19348): Struct casts should be better documented.) +$(LI $(BUGZILLA 24659): Memory safe D page lacks information on return ref) +$(LI $(BUGZILLA 24868): Undocumented cast from struct to static array) +$(LI $(BUGZILLA 24876): Undocumented cast from slice to static array) +$(LI $(BUGZILLA 24890): spec/arrays.dd should mention comparison and warn about dangling .ptr) +) +$(BUGSTITLE_GITHUB DMD Compiler bug fixes, + +$(LI $(DMDGITHUB 17214): Missing O_NOFOLLOW enum on macOS) +$(LI $(DMDGITHUB 17479): Incorrect definition of GetMessageExtraInfo) +$(LI $(DMDGITHUB 17503): Associative Arrays improperly register a GC-allocated TypeInfo for element cleanup) +$(LI $(DMDGITHUB 18235): Add offending member to "no size because of forward reference" error) +$(LI $(DMDGITHUB 19369): getcwd is deprecated for Windows - the ISO C++ conformant _getcwd should be used instead) +$(LI $(DMDGITHUB 20330): subtracting pointers with different types is both deprecated and an error) +$(LI $(DMDGITHUB 20516): ImportC: undefined identifier `_Float16`) +$(LI $(DMDGITHUB 20562): returning __rvalue should move-construct the NRVO value) +$(LI $(DMDGITHUB 20567): returning the result of a constructor should be NRVO) +$(LI $(DMDGITHUB 20587): Add `align$(LPAREN)default$(RPAREN)`) +$(LI $(DMDGITHUB 20601): hasIndirections does not handle static arrays of length 0 correctly) +$(LI $(DMDGITHUB 20603): hasIndirections does not handle enums correctly) +$(LI $(DMDGITHUB 20610): aliasing for fields does not work) +$(LI $(DMDGITHUB 20614): Add __traits$(LPAREN)hasMoveConstructor, type$(RPAREN)) +$(LI $(DMDGITHUB 20621): Comparing addresses of rvalue reference parameters not correct) +$(LI $(DMDGITHUB 20686): Generated constructors should infer @nogc, nothrow and infer attributes) +$(LI $(DMDGITHUB 20688): SO_REUSEPORT is not defined for some linux targets) +$(LI $(DMDGITHUB 20691): SO_REUSEPORT is not defined for Solaris) +$(LI $(DMDGITHUB 20730): runnable/test23514.d test reports different AST between 32bit and 64bit) +$(LI $(DMDGITHUB 20763): Inconsistent handling of type + value in typeof expressions) +$(LI $(DMDGITHUB 20812): hasIndirections doesn't take qualifiers into account with void) +$(LI $(DMDGITHUB 20831): Mangle conflict after ImportC statement expression gets expanded from macro) +$(LI $(DMDGITHUB 20888): Compiler spits out implicit conversion technobabble when a return statement doesn't match the return type of a function) +$(LI $(DMDGITHUB 20889): ImportC: Usage of `typedef` types decays to original type.) +$(LI $(DMDGITHUB 20912): ImportC: DI Generator stops emitting enums before all #defines are emitted.) +$(LI $(DMDGITHUB 20929): #line directives mess up -verrors=context) +$(LI $(DMDGITHUB 20960): i = i && 1; fails at runtime) +$(LI $(DMDGITHUB 20982): Regression #20777: wrong line numbers diagnosed in inline asm) +$(LI $(DMDGITHUB 21020): [REG2.111] Indexing a *cast* AA yields no lvalue anymore) +$(LI $(DMDGITHUB 21024): Optimize x^^0, x^^1 and x^^2 expressions) +$(LI $(DMDGITHUB 21045): import __stdin causes compilation to pause while reading from stdin) +) +$(BUGSTITLE_GITHUB Phobos bug fixes, + +$(LI $(PHOBOSGITHUB 9662): std.getopt: improve error message for malformed arguments) +$(LI $(PHOBOSGITHUB 9811): Writelning a tuple ignores member's toString.) +$(LI $(PHOBOSGITHUB 10023): Add "eval" to phobos) +$(LI $(PHOBOSGITHUB 10257): variadic overload of std.algorithm.searching.countUntil should return which needle was found) +$(LI $(PHOBOSGITHUB 10370): Add readfln to std.stdio) +$(LI $(PHOBOSGITHUB 10380): Memoize should handle lambdas) +$(LI $(PHOBOSGITHUB 10386): Make std.math.isIdentical work in CTFE) +$(LI $(PHOBOSGITHUB 10538): Cannot swap a std.typecons.Tuple) +$(LI $(PHOBOSGITHUB 10565): BigInt multiplication of 0 by integral $(LPAREN)non-BigInt$(RPAREN) type creates "-0" $(LPAREN)negative zero$(RPAREN)) +$(LI $(PHOBOSGITHUB 10574): std.process execve depends on environ pointer not changing) +$(LI $(PHOBOSGITHUB 10581): std.logger has an ostensibly broken example and wrong docs) +$(LI $(PHOBOSGITHUB 10587): std.process.kill should fail for a terminated pid) +$(LI $(PHOBOSGITHUB 10603): `toDelegate` accepts but can’t handle a templated `opCall`) +$(LI $(PHOBOSGITHUB 10605): byLine and byLineCopy should be safe) +$(LI $(PHOBOSGITHUB 10607): Structs `lines` and `ByLineCopy` cannot be usefully constructed in `@safe` code) +$(LI $(PHOBOSGITHUB 10639): Memory corruption when calling std.process exec functions) +$(LI $(PHOBOSGITHUB 10647): sumtype: canMatch fails with handler that returns non-copyable type by ref) +$(LI $(PHOBOSGITHUB 10680): [REG2.111] std.getopt doesn't accept `const$(LPAREN)string$(RPAREN)[]` anymore) +$(LI $(PHOBOSGITHUB 10713): std.format string positions affect all further format specifiers) +) +$(BUGSTITLE_GITHUB dlang.org bug fixes, + +$(LI $(DLANGORGGITHUB 4101): grammar allows missing function body for AutoFuncDeclaration) +$(LI $(DLANGORGGITHUB 4174): Invalid C enum in ImportC spec example) +) +) +$(D_CONTRIBUTORS_HEADER 78) +$(D_CONTRIBUTORS + $(D_CONTRIBUTOR 0-v-0) + $(D_CONTRIBUTOR Adam Wilson) + $(D_CONTRIBUTOR Alexander Heistermann) + $(D_CONTRIBUTOR Amaury) + $(D_CONTRIBUTOR Anca Maxim) + $(D_CONTRIBUTOR Andrei Horodniceanu) + $(D_CONTRIBUTOR Andrei Rusanescu) + $(D_CONTRIBUTOR Andrey Penechko) + $(D_CONTRIBUTOR Anita Hammer) + $(D_CONTRIBUTOR Artha) + $(D_CONTRIBUTOR Ate Eskola) + $(D_CONTRIBUTOR bangbangsheshotmedown) + $(D_CONTRIBUTOR Chibisi Chima-Okereke) + $(D_CONTRIBUTOR Cyrodwd) + $(D_CONTRIBUTOR Dawson Frakes) + $(D_CONTRIBUTOR Denis Feklushkin) + $(D_CONTRIBUTOR Dennis Korpel) + $(D_CONTRIBUTOR Dennis O.) + $(D_CONTRIBUTOR dhawal543) + $(D_CONTRIBUTOR Elias Batek) + $(D_CONTRIBUTOR Emmanuel Ferdman) + $(D_CONTRIBUTOR Fares A. Bakhit) + $(D_CONTRIBUTOR Feldwor) + $(D_CONTRIBUTOR Georgy Markov) + $(D_CONTRIBUTOR Iain Buclaw) + $(D_CONTRIBUTOR Iain Sandoe) + $(D_CONTRIBUTOR IchorDev) + $(D_CONTRIBUTOR Ilya Yanok) + $(D_CONTRIBUTOR Inkrementator) + $(D_CONTRIBUTOR Jan Jurzitza) + $(D_CONTRIBUTOR Jeremy Baxter) + $(D_CONTRIBUTOR Johan Engelen) + $(D_CONTRIBUTOR John Colvin) + $(D_CONTRIBUTOR John Dougan) + $(D_CONTRIBUTOR Jonas Meeuws) + $(D_CONTRIBUTOR Jonathan M Davis) + $(D_CONTRIBUTOR jordan4ibanez) + $(D_CONTRIBUTOR João Lourenço) + $(D_CONTRIBUTOR Kymorphia, PBC) + $(D_CONTRIBUTOR liushuyu) + $(D_CONTRIBUTOR LunaTheFoxgirl) + $(D_CONTRIBUTOR Luís Ferreira) + $(D_CONTRIBUTOR Manu Evans) + $(D_CONTRIBUTOR Marcelo Silva Nascimento Mancini) + $(D_CONTRIBUTOR Martin Kinkelin) + $(D_CONTRIBUTOR Mathias Lang) + $(D_CONTRIBUTOR Matthew Qiu) + $(D_CONTRIBUTOR Max Haughton) + $(D_CONTRIBUTOR Mike) + $(D_CONTRIBUTOR Nicholas Wilson) + $(D_CONTRIBUTOR Nick Treleaven) + $(D_CONTRIBUTOR Nicolò Monaldini) + $(D_CONTRIBUTOR Oshlok) + $(D_CONTRIBUTOR Paul Backus) + $(D_CONTRIBUTOR Per Nordlöw) + $(D_CONTRIBUTOR Quirin F. Schroll) + $(D_CONTRIBUTOR Rainer Schuetze) + $(D_CONTRIBUTOR Razvan Nitu) + $(D_CONTRIBUTOR Richard (Rikki) Andrew Cattermole) + $(D_CONTRIBUTOR Robert burner Schadek) + $(D_CONTRIBUTOR Royal Simpson Pinto) + $(D_CONTRIBUTOR royalpinto007) + $(D_CONTRIBUTOR Runa) + $(D_CONTRIBUTOR ryuukk) + $(D_CONTRIBUTOR Sebastian Wilzbach) + $(D_CONTRIBUTOR Serg Gini) + $(D_CONTRIBUTOR Simen Kjærås) + $(D_CONTRIBUTOR Steven Schveighoffer) + $(D_CONTRIBUTOR Sönke Ludwig) + $(D_CONTRIBUTOR Teodor Dutu) + $(D_CONTRIBUTOR Tim Schendekehl) + $(D_CONTRIBUTOR tynuk) + $(D_CONTRIBUTOR Vladimir Panteleev) + $(D_CONTRIBUTOR Vladiwostok) + $(D_CONTRIBUTOR Walter Bright) + $(D_CONTRIBUTOR wolframw) + $(D_CONTRIBUTOR Xin Wang) +) +$(D_CONTRIBUTORS_FOOTER) +$(CHANGELOG_NAV_INJECT) + +Macros: + VER=2.111.0 + TITLE=Change Log: $(VER) diff --git a/changelog/changelog.ddoc b/changelog/changelog.ddoc new file mode 100644 index 0000000000..1ec727e8c7 --- /dev/null +++ b/changelog/changelog.ddoc @@ -0,0 +1,86 @@ +ROOT=.. +ROOT_DIR=../ +BODYCLASS=changelog + +CHANGELOG_NAV=$(DIVC changelog-nav, previous version: $(A $1.html, $1) +$(NDASH) next version: $(A $2.html, $2)) +CHANGELOG_NAV_FIRST=$(DIVC changelog-nav, next version: $(A $1.html, $1)) +CHANGELOG_NAV_LAST=$(DIVC changelog-nav, previous version: $(A $1.html, $1)) + +SUBNAV=$(SUBNAV_TEMPLATE + $(SUBNAV_HEADS Change Log, + $(LINK2 $(ROOT_DIR)changelog/index.html, List of all versions) + $(BR) + $(LINK2 $(ROOT_DIR)changelog/release-schedule.html, Release schedule) + ) + $(UL $(CHANGELOG_VERSIONS)) +) + +SEARCH_OPTIONS_EXTRA= + +VERSION= +$(DIVC version, +$(P +$(B $(LARGE $(LINK2 https://downloads.dlang.org/releases/2.x/$(VER), Download D $(VER))))$(BR) +$(SMALL released $1, $2) +) +$4 +) + +_= The following CHANGELOG_SEP_ macros are emitted by the ../tools/changed.d script +CHANGELOG_SEP_HEADER_TEXT_NONEMPTY=$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) +CHANGELOG_SEP_HEADER_TEXT=$(HR) +CHANGELOG_SEP_TEXT_BUGZILLA=$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) +CHANGELOG_SEP_NO_TEXT_BUGZILLA=$(BR)$(BIG List of all bug fixes and enhancements in D $(VER).) +CHANGELOG_HEADER_STATISTICS=$(DIVC changelog-header-stats, $0) +CHANGELOG_SOURCE_FILE= + +BUGSTITLE_TEXT_HEADER=$(BUGSTITLE $1, $+) +BUGSTITLE_TEXT_BODY=$(BUGSTITLE $1, $+) +BUGSTITLE_BUGZILLA=$(BUGSTITLE $1, $+) +BUGSTITLE_GITHUB=$(BUGSTITLE $1, $+) + +DMDGITHUB = $(SPANC issue, $(AHTTPS github.com/dlang/dmd/issues/$0, DMD Issue $0)) +PHOBOSGITHUB = $(SPANC issue, $(AHTTPS github.com/dlang/phobos/issues/$0, Phobos Issue $0)) +DLANGORGGITHUB = $(SPANC issue, $(AHTTPS github.com/dlang/dlang.org/issues/$0, Dlang.org Issue $0)) + +_= The following D_CONTRIBUTOR macros are emitted by the ../tools/changed.d script +D_CONTRIBUTORS_HEADER=$(H3 $(LNAME2 contributors, Contributors to this release ($1))) +$(P A huge thanks goes to all the awesome people who made this release possible.) +D_CONTRIBUTORS=$(UL $1) +D_CONTRIBUTOR=$(LI $1) +D_CONTRIBUTORS_FOOTER= + + +BUGZILLA = Bugzilla $0 +CPPBUGZILLA = Bugzilla $0 +DSTRESS = dstress $0 +BUGSFIXED =
    $(H4 Bugs Fixed) $(UL $0 )
    +DMDBUGSFIXED =
    $(H4 DMD Bugs Fixed) $(UL $0 )
    +LIBBUGSFIXED =
    $(H4 Library Bugs Fixed) $(UL $0 )
    +RUNTIMEBUGSFIXED =
    $(H4 Druntime Bugs Fixed) $(UL $0 )
    +BUGSTITLE =
    $(H4 $1) $(OL $2 )
    + +UPCOMING =
    $(H4 Under Construction) $(OL $0 )
    +WHATSNEW =
    $(H4 New/Changed Features) $(UL $0 )
    +NEWPHOBOS =
    $(H4 New/Changed Phobos) $(UL $0 )
    +LARGE=$0 +TRENAME=$(TR $(TD $(CODE $1)) $(TD $(CODE $2))) +LII= $(LI $(D $1) $(UL $+ )) + +PULL_REQUEST = $(LINK2 https://github.com/dlang/$1/pull/$2, $1#$2) +DMDPR = $(PULL_REQUEST dmd,$1) +DRUNTIMEPR = $(PULL_REQUEST druntime,$1) +PHOBOSPR = $(PULL_REQUEST phobos,$1) +_= + +CHANGELOG_VERSION = $(LI $1 ($2, $3)) +CHANGELOG_VERSION_PRE = $(LI $1 (preview) - scheduled for $+) +CHANGELOG_VERSION_NIGHTLY = $(LI Nightly (preview) - upcoming changes from $(D master)) + +SUBNAV_HEADS= + $(DIVC head, + $(H2 $1) + $(P $+) + ) diff --git a/changelog/index.dd b/changelog/index.dd new file mode 100644 index 0000000000..5e200f915b --- /dev/null +++ b/changelog/index.dd @@ -0,0 +1,27 @@ +Ddoc + +$(SCRIPT + var redir = window.location.href.replace( + /\\/changelog\\/index.html#(?:2\\.|new2_)(\\d+(?:\\.\\d+)?)$(DOLLAR)/, + "/changelog/2.$(DOLLAR)1.html" + ); + + if (redir !== window.location.href) + { + window.location = redir; + } +) + +$(D_S D Change Log, + +$(UL + $(CHANGELOG_VERSIONS) + + $(LI $(LINK2 http://www.digitalmars.com/d/1.0/changelog.html, changelog for 1.0)) +) + +) + +Macros: + +TITLE=Change Log: List of All Versions diff --git a/changelog/next_version.sh b/changelog/next_version.sh new file mode 100755 index 0000000000..44a199140b --- /dev/null +++ b/changelog/next_version.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -ueo pipefail + +# cd and pwd to account for relative paths/symlinks. See also: +# https://stackoverflow.com/questions/59895/getting-the-source-directory-of-a-bash-script-from-within +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +VERSION=$(cat "${1:-$DIR/../../dmd/VERSION}") +# v2.076.1-b1 -> 2.076.1 +VERSION=${VERSION:1:7} +# 2.076.1 -> (2 076 1) +PARTS=(${VERSION//./ }) +# use 10#076 prefix to read octal as base10 int +PARTS[1]=$(printf %03d $((10#${PARTS[1]} + 1))) +PARTS[2]=0 +# 2 077 0 -> 2.077.0 +echo "${PARTS[0]}.${PARTS[1]}.${PARTS[2]}" diff --git a/changelog/pending.ddoc b/changelog/pending.ddoc new file mode 100644 index 0000000000..255f522950 --- /dev/null +++ b/changelog/pending.ddoc @@ -0,0 +1,44 @@ +VERSION= +$(DIVC version, +$(P +$(B $(LARGE $(LINK2 https://github.com/dlang/dmd/releases/tag/nightly, Download D nightlies)))$(BR) +$(SMALL $1) + +) + +$(HR) + +$(P +This changelog has been $(B automatically generated) from all commits in $(B $(CODE master)) +since the last release. +) +$(P + $(UL + $(LI The full-text messages are assembled from the $(CODE changelog/) directories of the respective repositories: + $(LINK2 https://github.com/dlang/dmd/tree/master/changelog, $(CODE dmd)), + $(LINK2 https://github.com/dlang/druntime/tree/master/changelog, $(CODE druntime)), + $(LINK2 https://github.com/dlang/phobos/tree/master/changelog, $(CODE phobos)), + $(LINK2 https://github.com/dlang/tools/tree/master/changelog, $(CODE tools)), + $(LINK2 https://github.com/dlang/dlang.org/tree/master/changelog, $(CODE dlang.org)), + $(LINK2 https://github.com/dlang/installer/tree/master/changelog, $(CODE installer)), and + $(LINK2 https://github.com/dlang/dub/tree/master/changelog, $(CODE dub)). + ) + $(LI See the $(LINK2 https://github.com/dlang-bots/dlang-bot#automated-references, DLang-Bot documentation) for details on referencing Bugzilla. + The DAutoTest PR preview doesn't include the Bugzilla changelog.) + $(LI The pending changelog can be generated locally by $(LINK2 https://github.com/dlang/dlang.org/blob/master/CONTRIBUTING.md, setting up $(D dlang.org)) and running the $(D pending_changelog) target: + $(CONSOLE make -f posix.mak pending_changelog) + ) + ) +) + +$(HR) + +$3 +) +CHANGELOG_SEP_HEADER_TEXT_NONEMPTY=$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all upcoming bug fixes and enhancements in D $(VER).)) +CHANGELOG_SOURCE_FILE=$(DIVC changelog-source-edit-btn, $(LINK2 https://github.com/dlang/$1/edit/master/$2, $(TC i, fa fa-edit))) +EXTRA_HEADERS=$(T style, + .changelog-source-edit-btn { + float: right; + } +) diff --git a/changelog/prerelease.ddoc b/changelog/prerelease.ddoc new file mode 100644 index 0000000000..2aa33e7b47 --- /dev/null +++ b/changelog/prerelease.ddoc @@ -0,0 +1,16 @@ +VERSION= +$(DIVC version, +$(P +$(B $(LARGE $(LINK2 http://dlang.org/download.html#dmd_beta, Download D $(VER) Beta)))$(BR) +$(SMALL to be released $1, $2) +) +$4 +) + +PHOBOS_PATH=$(ROOT_DIR)phobos-prerelease/ +CHANGELOG_SOURCE_FILE=$(DIVC changelog-source-edit-btn, $(LINK2 https://github.com/dlang/$1/edit/stable/$2, $(TC i, fa fa-edit))) +EXTRA_HEADERS=$(T style, + .changelog-source-edit-btn { + float: right; + } +) diff --git a/changelog/release-schedule.dd b/changelog/release-schedule.dd new file mode 100644 index 0000000000..bc00cef931 --- /dev/null +++ b/changelog/release-schedule.dd @@ -0,0 +1,47 @@ +Ddoc + +$(D_S $(TITLE), + +$(UL + $(LI New releases are published every $(I two) months, on the first day of every even month.) + $(LI One month before a new release, `master` is merged into `stable` and a first beta is released.) + $(LI Point releases are published unscheduled when important issues or regressions get fixed.) +) + +$(P The release schedule for 2025 is as follows:) + + $(DIVC release-schedule, + $(TABLE + $(BETA_RELEASE 2025-01-01, 2.110.0) + $(MINOR_RELEASE 2025-02-01, 2.110.0) + $(BETA_RELEASE 2025-03-01, 2.111.0) + $(MINOR_RELEASE 2025-04-01, 2.111.0) + $(BETA_RELEASE 2025-05-01, 2.112.0) + $(MINOR_RELEASE 2025-06-01, 2.112.0) + $(BETA_RELEASE 2025-07-01, 2.113.0) + $(MINOR_RELEASE 2025-08-01, 2.113.0) + $(BETA_RELEASE 2025-09-01, 2.114.0) + $(MINOR_RELEASE 2025-10-01, 2.114.0) + $(BETA_RELEASE 2025-11-01, 2.115.0) + $(MINOR_RELEASE 2025-12-01, 2.115.0) + ) + ) +) + +Macros: + TITLE=D release schedule + MINOR_RELEASE=$(ROW minor, $1, $2, minor release) + BETA_RELEASE=$(ROW beta, $1, $2-beta.1, first beta for $2) + ROW=
    $(TDX2 $+) + TDX2=$(TDX $1, $+) + EXTRA_HEADERS=$(T style, + .release-schedule table { + margin: 0 auto; + } + .release-schedule-minor { + font-weight: bold; + } + .release-schedule-beta { + color: #5f0303; + } + ) diff --git a/chm-nav.dd b/chm-nav.dd new file mode 100644 index 0000000000..3f49c29c9b --- /dev/null +++ b/chm-nav.dd @@ -0,0 +1,78 @@ +Ddoc + + +Macros: +DDOC= +[ + { + "hook" : "", + "root" : "", + "nav" : [ + {"t":"D Programming Language","a":"index.html"}, + $(NAVIGATION) + {"t":"Change Log","a":"changelog/index.html"} + ] + }, + { + "hook" : "Language Reference", + "root" : "", + "nav" : [$(SUBNAV_SPEC)] + }, + { + "hook" : "Library Reference", + "root" : "phobos/", + "nav" : [{"t":"Library Reference","a":"index.html"},$(MODULE_MENU)] + }, + { + "hook" : "Articles", + "root" : "", + "nav" : [$(SUBNAV_ARTICLES)] + }, + { + "hook" : "D-Specific Tools", + "root" : "", + "nav" : [$(SUBNAV_CLI_REFERENCE)] + }, + { + "hook" : "Change Log", + "root" : "changelog/", + "nav" : [{"t":"Change Log","a":"index.html"},$(CHANGELOG_VERSIONS)] + }, +]$(LF) +_= + +DIVID=$2 +B=$0 +TT=$0 +UL=$0 +_LI=$0, +AMP=& +NBSP= +LATEST= +MENU={"t":"$2","a":"$1"}, +MENU_W_SUBMENU=[{"t":"$2"}, +MENU_W_SUBMENU_END= +MENU_W_SUBMENU_LINK=[{"t":"$2","a":"$1"}, +MENU_INTERNAL_SEPARATOR= +ITEMIZE=$(ITEMS_HELPER $1, $+)], +ITEMS_HELPER = $1$(ITEMS_HELPER $+) +SUBMENU=$(SUBMENU2 $1,$+)], +SUBMENU2={"t":"$2","a":"$1"}, + $(SUBMENU3 $+) +SUBMENU3=$(SUBMENU2 $+) +SUBMENU_MANUAL=$0], +SUBMENU_LINK={"t":"$2","a":"$1"}, +SUBMENU_LINK_DIVIDER={"t":"$2","a":"$1"}, +SUBNAV_TEMPLATE=$0 +SUBNAV_HEAD={"t":"$3","a":"$2"}, +MODULE= + {"t":"$1","a":"$2$(JOIN_LINE_TAIL $+).html"}, +PACKAGE=[$1$(ITEMIZE $+) +PACKAGE_NAME={"t":"$1"}, +CHANGELOG_VERSION_NIGHTLY= +CHANGELOG_VERSION_PRE={"t":"$1","a":"$1_pre.html"}, +CHANGELOG_VERSION={"t":"$1","a":"$1.html"}, +CHANGELOG_VERSIONS= +ESCAPES=/"/\"/ +ROOT_DIR= +_= diff --git a/chmgen.d b/chmgen.d deleted file mode 100644 index bdbfabc721..0000000000 --- a/chmgen.d +++ /dev/null @@ -1,943 +0,0 @@ -// D HTML to CHM converter/generator -// By Vladimir Panteleev (2007-2011) -// Placed in the Public Domain -// Written in the D Programming Language, version 2 - -import std.algorithm : min, canFind, sort; -import std.array; -import std.ascii; -import std.exception; -import std.file; -import std.stdio; -import std.string; -import std.regex; -import std.path; - -enum ROOT = `.`; - -// ******************************************************************** - -string backSlash(string s) -{ - return s.replace(`/`, `\`); -} - -bool contains(string s, string sub) { return s.indexOf(sub) >= 0; } - -RegexMatch!string match; - -bool test(string line, Regex!char re) -{ - match = std.regex.match(line, re); - return !match.empty; -} - -string getAnchor(string s) -{ - int i = s.indexOf('#'); - return i<0 ? "" : s[i..$]; -} - -string removeAnchor(string s) -{ - int i = s.indexOf('#'); - return i<0 ? s : s[0..i]; -} - -string absoluteUrl(string base, string url) -{ - if (url.contains("://")) - return url; - - base = base.backSlash(); - url = url.backSlash(); - enforce(url.length, "Empty URL"); - - if (url[0]=='#') - return base ~ url; - - auto baseParts = base.split(`\`); - baseParts = baseParts[0..$-1]; - - while (url.startsWith(`..\`)) - { - url = url[3..$]; - baseParts = baseParts[0..$-1]; - } - return baseParts.join(`\`) ~ `\` ~ url; -} - -string movePath(string s) -{ - if (s.startsWith(ROOT ~ `\`)) - s = "chm" ~ s[ROOT.length..$]; - if (s == `chm\phobos\phobos.html`) - s = `chm\phobos\index.html`; - return s; -} - -// ******************************************************************** - -class Nav -{ - string title, url; - Nav[] children; - - this(string title, string url) - { - this.title = title; - this.url = url; - } - - Nav findOrAdd(string title, string url) - { - title = title.strip(); - foreach (child; children) - if (child.title == title) - return child; - auto child = new Nav(title, url); - children ~= child; - return child; - } -} - -Nav nav; - -class Page -{ - string newFileName; - string title; - string src; - bool[string] anchors; -} - -struct KeyLink -{ - string anchor; - string title; - - this(string anchor, string title) - { - this.anchor = anchor.strip(); - this.title = title.strip(); - } -} - -// ******************************************************************** - -Page[string] pages; -KeyLink[string][string] keywords; // keywords[keyword][original url w/o anchor] = anchor/title -string[string] keyTable; - -void addKeyword(string keyword, string link, string title = null) -{ - keyword = keyword.strip(); - string file = link.removeAnchor(); - file = file.backSlash(); - string anchor = link.getAnchor(); - - if (!title && keyword in keywords && file in keywords[keyword]) // when title is present, it overrides any existing anchors/etc. - { - if (keywords[keyword][file].anchor > anchor) // "less" is better - keywords[keyword][file] = KeyLink(anchor, title); - } - else - keywords[keyword][file] = KeyLink(anchor, title); - - if (title && keyword in keyTable) - { - if (keyTable[keyword] > keyword) // "less" is better - keyTable[keyword] = keyword; - } - else - keyTable[keyword] = keyword; -} - -void main() -{ - // clean up - if (exists("chm")) - rmdirRecurse("chm"); - mkdir("chm"); - - string[] files; - foreach (de; dirEntries(ROOT ~ `\`, "*.{html,css,gif,jpg,png,ico}", SpanMode.breadth)) - if (!de.name.baseName.startsWith("pdf-") - && !de.name.baseName.startsWith("std_consolidated_")) - files ~= de.name; - - auto re_title = regex(`(.*) - (The )?D Programming Language( [0-9]\.[0-9])? - Digital Mars`); - auto re_title2 = regex(`(Digital Mars - The )?D Programming Language( [0-9]\.[0-9])? - (.*)`); - auto re_title3 = regex(`

    (.*)

    `); - auto re_heading = regex(`

    (.*)

    `); - auto re_heading_link = regex(`

    (.*)

    `); - auto re_nav_link = regex(`
  • (.*)`); - auto re_anchor_1 = regex(`(<.{1,2}>)*([^<]+)<`); - auto re_anchor_2 = regex(`]*)>(<.{1,2}>)*([^<]+)<`); - auto re_anchor_1h = regex(`]*)>`); - auto re_link = regex(`(<.{1,2}>)*([^<]+)<`); - auto re_link_pl = regex(`
  • `); - auto re_def = regex(`
    (.*)([^<]+)<`); - auto re_css_margin = regex(`margin-left:\s*1[35]em;`); - - nav = new Nav(null, null); - - foreach (fileName; files) - with (pages[fileName] = new Page) - { - scope(failure) writeln("Error while processing file: ", fileName); - - string destdir = fileName.getDirName().movePath(); - if (!exists(destdir)) - mkdirRecurse(destdir); - - newFileName = fileName.movePath(); - - if (fileName.endsWith(`.html`)) - { - writeln("Processing ", fileName); - src = readText(fileName); - string[] lines = splitLines(src); - string[] newlines = null; - bool skip, innavblock, intoctop; - int dl = 0; - anchors[""] = true; - - Nav[] navStack = [nav]; - if (fileName.startsWith(ROOT ~ `\phobos\`)) - { - navStack ~= navStack[$-1].findOrAdd("Documentation", null); - navStack ~= navStack[$-1].findOrAdd("Library Reference", `chm\phobos\index.html`); - navStack ~= navStack[$-1].findOrAdd(null, null); - } - else - navStack ~= null; - bool foundNav = false; - - foreach (origline; lines) - { - scope(failure) writeln("Error while processing line: ", origline); - string line = origline; - bool nextSkip = skip; - - if (line.test(re_link_pl)) - continue; // don't process link as well - - if (line.test(re_title)) - { - title = strip(/*re_title*/match.captures[1]); - line = line.replace(re_title, `` ~ title ~ ``); - } - if (line.test(re_title2)) - { - title = strip(/*re_title2*/match.captures[3]); - line = line.replace(re_title2, `` ~ title ~ ``); - } - if (line.test(re_title3)) - if (title=="") - title = strip(/*re_title2*/match.captures[1]); - - if (line.test(re_anchor_1h)) - { - auto anchor = '#' ~ /*re_anchor*/match.captures[1]; - anchors[anchor] = true; - } - else - if (line.test(re_anchor_2h)) - { - auto anchor = '#' ~ /*re_anchor_2*/match.captures[1]; - anchors[anchor] = true; - } - - if (line.contains(`
  • - - - - $(TR - - - ) - - - - - $(TR - $(TD Garbage Collection) - $(YES1 garbage.html) - ) - - $(TR - - ) - - $(TR - $(TD Function delegates) - $(YES1 type.html#delegates) - ) - - $(TR - $(TD Function overloading) - $(YES1 function.html#function-overloading) - ) - - $(TR - $(TD Out function parameters) - $(YES1 function.html#parameters) - ) - - $(TR - $(TD Nested functions) - $(YES1 function.html#nested) - ) - - $(TR - $(TD Function literals) - $(YES1 expression.html#FunctionLiteral) - ) - - $(TR - $(V1 $(TD Dynamic closures)) - $(V2 $(TD Closures)) - $(YES1 function.html#closures) - ) - - $(TR - $(TD Typesafe variadic arguments) - $(YES1 function.html#variadic) - ) - - $(TR - $(TD Lazy function argument evaluation) - $(YES1 lazy-evaluation.html) - ) - - $(TR - $(TD Compile time function evaluation) - $(YES1 function.html#interpretation) - ) - - $(TR - - ) - - $(TR - $(TD Lightweight arrays) - $(YES1 arrays.html) - ) - - $(TR - $(TD Resizeable arrays) - $(YES1 arrays.html#resize) - ) - - $(TR - $(TD Built-in strings) - $(YES1 arrays.html#strings) - ) - - $(TR - $(TD Array slicing) - $(YES1 arrays.html#slicing) - ) - - $(TR - $(TD Array bounds checking) - $(YES1 arrays.html#bounds) - ) - - $(TR - $(TD Array literals) - $(YES1 expression.html#ArrayLiteral) - ) - - $(TR - $(TD Associative arrays) - $(YES1 arrays.html#associative) - ) - - $(TR - $(TD Strong typedefs) - $(YES1 declaration.html#typedef) - ) - - $(TR - $(TD String switches) - $(YES1 statement.html#SwitchStatement) - ) - - $(TR - $(TD Aliases) - $(YES1 declaration.html#alias) - ) - - $(TR - - ) - - $(TR - $(TD Object Oriented) - $(YES) - ) - - $(TR - $(TD Multiple Inheritance) - $(NO) - ) - - $(TR - $(TD Interfaces) - $(YES1 interface.html) - ) - - $(TR - $(TD Operator overloading) - $(YES1 operatoroverloading.html) - ) - - $(TR - $(TD Modules) - $(YES1 module.html) - ) - - $(TR - $(TD Dynamic class loading) - $(NO) - ) - - $(TR - $(TD Nested classes) - $(YES1 class.html#nested) - ) - - $(TR - $(TD Inner (adaptor) classes) - $(YES1 class.html#nested) - ) - - $(TR - $(TD Covariant return types) - $(YES1 function.html) - ) - - $(TR - $(TD Properties) - $(YES1 property.html#classproperties) - ) - - $(TR - - ) - - $(TR - $(TD Inline assembler) - $(YES1 iasm.html) - ) - - $(TR - $(TD Direct access to hardware) - $(YES) - ) - - $(TR - $(TD Lightweight objects) - $(YES1 struct.html) - ) - - $(TR - $(TD Explicit memory allocation control) - $(YES1 memory.html) - ) - - $(TR - $(TD Independent of VM) - $(YES) - ) - - $(TR - $(TD Direct native code gen) - $(YES) - ) - - $(TR - - ) - - $(TR - $(TD Class Templates) - $(YES1 template.html) - ) - - $(TR - $(TD Function Templates) - $(YES1 template.html) - ) - - $(TR - $(TD Implicit Function Template Instantiation) - $(YES1 template.html) - ) - - $(TR - $(TD Partial and Explicit Specialization) - $(YES1 template.html) - ) - - $(TR - $(TD Value Template Parameters) - $(YES1 template.html) - ) - - $(TR - $(TD Template Template Parameters) - $(YES1 template.html) - ) - - $(TR - $(TD Variadic Template Parameters) - $(YES1 template.html) - ) -$(V2 - $(TR - $(TD Template Constraints) - $(YES1 concepts.html) - ) -) - $(TR - $(TD Mixins) - $(YES1 template-mixin.html) - ) - - $(TR - $(TD static if) - $(YES1 version.html#staticif) - ) - - $(TR - $(TD is expressions) - $(YES1 expression.html#IsExpression) - ) - - $(TR - $(TD typeof) - $(YES1 declaration.html#Typeof) - ) - - $(TR - $(TD foreach) - $(YES1 statement.html#ForeachStatement) - ) - - $(TR - $(TD Implicit Type Inference) - $(YES1 declaration.html#AutoDeclaration) - ) - - $(TR - - ) - - $(TR - $(TD Contract Programming) - $(YES1 dbc.html) - ) - - $(TR - $(TD Unit testing) - $(YES1 unittest.html) - ) - - $(TR - $(TD Static construction order) - $(YES1 module.html#staticorder) - ) - - $(TR - $(TD Guaranteed initialization) - $(YES1 statement.html#DeclarationStatement) - ) - - $(TR - $(TD RAII (automatic destructors)) - $(YES1 memory.html#raii) - ) - - $(TR - $(TD Exception handling) - $(YES1 statement.html#TryStatement) - ) - - $(TR - $(TD Scope guards) - $(YES1 statement.html#ScopeGuardStatement) - ) - - $(TR - $(TD try-catch-finally blocks) - $(YES1 statement.html#TryStatement) - ) - - $(TR - $(TD Thread synchronization primitives) - $(YES1 statement.html#SynchronizedStatement) - ) - - $(TR - - ) - - $(TR - $(TD C-style syntax) - $(YES) - ) - - $(TR - $(TD Enumerated types) - $(YES1 enum.html) - ) - - $(TR - $(TD Support all C types) - $(YES1 type.html) - ) - - $(TR - $(TD 80 bit floating point) - $(YES1 type.html) - ) - - $(TR - $(TD Complex and Imaginary) - $(YES1 type.html) - ) - - $(TR - $(TD Direct access to C) - $(YES1 attribute.html#linkage) - ) - - $(TR - $(TD Use existing debuggers) - $(YES) - ) - - $(TR - $(TD Struct member alignment control) - $(YES1 attribute.html#align) - ) - - $(TR - $(TD Generates standard object files) - $(YES) - ) - - $(TR - $(TD Macro text preprocessor) - $(NO1 pretod.html) - ) - - $(TR - - ) - - $(TR - $(TD Conditional compilation) - $(YES1 version.html) - ) - - $(TR - $(TD Unicode source text) - $(YES1 lex.html) - ) - - $(TR - $(TD Documentation comments) - $(YES1 ddoc.html) - ) - - - -
    D Language Feature Comparison Table
    Feature$(B D)
    Functions Arrays OOP Performance Generic Programming Reliability Compatibility Other
    - -$(SECTION2 Notes, - -
    - -
    Object Oriented -
    This means support for classes, member functions, - inheritance, and virtual function dispatch. -

    - -

    Inline assembler -
    Many C and C++ compilers support an inline assembler, but - this is not a standard part of the language, and implementations - vary widely in syntax and quality. -

    - -

    Interfaces -
    Support in C++ for interfaces is weak enough that an - IDL (Interface Description Language) was invented to compensate. -

    - -

    Modules -
    Many correctly argue that C++ doesn't really have modules. - But C++ namespaces coupled with header files share many features - with modules. -

    - -

    Garbage Collection -
    The Hans-Boehm garbage collector can be successfully used - with C and C++, but it is not a standard part of the language. -

    - -

    Implicit Type Inference -
    This refers to the ability to pick up the type of a - declaration from its initializer. -

    - -

    Contract Programming -
    The Digital Mars C++ compiler supports - Contract Programming - as an extension. - Compare some C++ techniques for - doing Contract Programming with D. -

    - -

    Resizeable arrays -
    Part of the standard library for C++ implements resizeable - arrays, however, they are not part of the core language. - A conforming freestanding implementation of C++ (C++98 17.4.1.3) does - not need to provide these libraries. -

    - -

    Built-in Strings -
    Part of the standard library for C++ implements strings, - however, they are not part of the core language. - A conforming freestanding implementation of C++ (C++98 17.4.1.3) does - not need to provide these libraries. - $(REDO Here's a comparison of C++ strings - and D built-in strings.) -

    - -

    Strong typedefs -
    Strong typedefs can be emulated in C/C++ by wrapping a type - in a struct. Getting this to work right requires much tedious - programming, and so is considered as not supported. -

    - -

    Use existing debuggers -
    By this is meant using common debuggers that can operate - using debug data in common formats embedded in the executable. - A specialized debugger useful only with that language is not required. -

    - -

    Struct member alignment control -
    Although many C/C++ compilers contain pragmas to specify - struct alignment, these are nonstandard and incompatible from - compiler to compiler.
    - The C# standard ECMA-334 25.5.8 says only this about struct member - alignment: - $(I "The order in which members are packed - into a struct is unspecified. For alignment purposes, there may be - unnamed padding at the beginning of a struct, within a struct, and at - the end of the struct. The contents of the bits used as padding are - indeterminate.") - Therefore, although Microsoft may - have extensions to support specific member alignment, they are not an - official part of standard C#. -

    - -

    Support all C types -
    C99 adds many new types not supported by C++. -

    - -

    80 bit floating point -
    While the standards for C and C++ specify long doubles, few - compilers (besides Digital Mars C/C++) actually implement - 80 bit (or longer) floating point types. -

    - -

    Mixins -
    Mixins have many different meanings in different programming - languages. D mixins mean taking an arbitrary - sequence of declarations - and inserting (mixing) them into the current scope. Mixins can be done - at the global, class, struct, or local level. -

    - -

    C++ Mixins -
    C++ mixins refer to a couple different techniques. The first - is analogous to D's interface classes. The second is to create - a template of the form: -$(CPPCODE -template <class Base> class Mixin : public Base -{ - ... mixin body ... -} -) - D mixins are different. -

    - -

    Static If -
    The C and C++ preprocessor directive #if would appear to - be equivalent to the D static if. But there are major and crucial - differences - the #if does not have access to any of the constants, - types, or symbols of the program. It can only access preprocessor - macros. - See this example. -

    - -

    Is Expressions -
    $(I Is expressions) enable conditional compilation based - on the characteristics of a type. This is done after a fashion in - C++ using template parameter pattern matching. - See this example - for a comparison of the different approaches. -

    - -

    Inner (adaptor) classes -
    A $(I nested class) is one whose definition is within the scope - of another class. An $(I inner class) is a nested class that - can also reference the members and fields of the lexically - enclosing class; one can think of it as if it contained a 'this' - pointer to the enclosing class. -

    - -

    Documentation comments -
    Documentation comments refer to a standardized way to produce - documentation from the source code file using specialized - comments. - -
    -) - -$(SECTION2 Errors, - - $(P If I've made any errors in this table, please contact me so - I can correct them. - ) +$(COMMUNITY D Concepts Overview, + +$(P Navigate D's implementation of a few key programming language concepts.) + +$(ITEMIZE + $(A spec/garbage.html, Garbage Collection) + $(ITEMIZE + $(REF_ALTTEXT Manual invocation, GC.enable, core,memory), + $(A spec/function.html#nogc-functions, `@nogc` subset) + ), + Functions + $(ITEMIZE + $(A spec/function.html#function-overloading, Function Overloading), + $(A spec/function.html#ref-params, `ref` and `out` function parameters), + $(A spec/function.html#ref-functions, `ref` functions), + $(A spec/type.html#delegates, Function Delegates), + $(A spec/function.html#nested, Nested functions), + $(A spec/expression.html#FunctionLiteral, Function literals), + $(A spec/function.html#closures, Closures), + $(A spec/function.html#variadic, Typesafe variadic arguments), + $(A lazy-evaluation.html, Lazy function argument evaluation), + $(A spec/function.html#pseudo-member, Uniform Function Call Syntax) + ), + Arrays + $(ITEMIZE + $(A spec/arrays.html, Lightweight arrays), + $(A spec/arrays.html#resize, Resizeable arrays), + $(A spec/arrays.html#strings, Built-in strings), + $(A spec/arrays.html#slicing, Array slicing), + $(A spec/arrays.html#bounds, Array bounds checking), + $(A spec/expression.html#ArrayLiteral, Array literals), + $(A spec/statement.html#string-switch, String switches), + $(A spec/arrays.html#associative, Associative arrays) + ), + OOP + $(ITEMIZE + $(A spec/class.html, Object Orientation), + $(A spec/interface.html, Interfaces), + Single inheritance of implementation/multiple inheritance of interfaces, + $(A spec/operatoroverloading.html, Operator overloading), + $(A spec/module.html, Modules), + No built-in dynamic class loading, + $(A spec/class.html#nested, Nested classes), + $(A spec/class.html#nested, Inner (adaptor) classes), + $(A spec/function.html#covariance, Covariant return types), + $(A spec/function.html#property-functions, Properties) + ), + Performance + $(ITEMIZE + $(A spec/iasm.html, Inline assembler), + Direct access to hardware, + $(A spec/struct.html, Lightweight objects), + $(A https://wiki.dlang.org/Memory_Management, Explicit memory allocation control), + Independent of VM, + Direct native code gen + ), + Generic Programming + $(ITEMIZE + $(A spec/declaration.html#AutoDeclaration, Implicit Type Inference), + $(A spec/statement.html#ForeachStatement, `foreach`), + $(MREF_ALTTEXT Ranges, std,range), + $(MREF_ALTTEXT Algorithms, std,algorithm), + $(A spec/declaration.html#alias, Aliases), + $(A spec/template.html, Templates) + $(ITEMIZE + $(A spec/template.html#aggregate_templates, Aggregate Templates), + $(A spec/template.html#function-templates, Function Templates), + $(A spec/template.html#ifti, Implicit Function Template Instantiation), + $(A spec/template.html#parameters_specialization, Partial and Explicit Template Specialization), + $(A spec/template.html#template_value_parameter, Value Template Parameters), + $(A spec/template.html#aliasparameters, Alias Template Parameters), + $(A articles/variadic-function-templates.html, Variadic Template Parameters), + $(A articles/constraints.html, Template Constraints) + ) + $(A spec/expression.html#IsExpression, `is` expressions), + $(A spec/type.html#Typeof, `typeof`) + ), + Metaprogramming + $(ITEMIZE + $(A spec/function.html#interpretation, Compile Time Function Evaluation), + $(A spec/template-mixin.html, Template Mixins), + $(A articles/mixin.html, String Mixins), + $(A spec/version.html#staticif, `static if`), + $(A spec/version.html#staticforeach, `static foreach`) + ), + Reliability + $(ITEMIZE + $(A spec/contracts.html, Contract Programming), + $(A spec/unittest.html, Unit testing), + $(A spec/const3.html, Immutable data), + $(A spec/function.html#pure-functions, Pure functions), + $(A spec/module.html#staticorder, Static construction order), + $(A spec/declaration.html#initialization, Initialization by default), + $(A spec/glossary.html#raii, RAII (implicit destructor calls)), + $(A spec/statement.html#TryStatement, Exception handling), + $(A spec/statement.html#ScopeGuardStatement, Scope guards), + $(A spec/statement.html#TryStatement, `try`-`catch`-`finally` blocks), + $(A articles/safed.html, Memory-safe subset) + ), + Concurrency & Parallelism + $(ITEMIZE + $(MREF_ALTTEXT Concurrency, std,concurrency), + $(MREF_ALTTEXT Fibers, core,thread,fiber), + $(REF parallel, std,parallelism), + $(A articles/migrate-to-shared.html, Thread Local Storage by default), + $(A spec/const3.html#shared, Shared data), + $(A spec/statement.html#SynchronizedStatement, Thread synchronization primitives) + ), + Types + $(ITEMIZE + $(A spec/struct.html, Structs and Unions), + $(A spec/enum.html, Enumerated types), + $(A spec/float.html, 80 bit floating point), + $(A phobos/std_complex.html, Complex and Imaginary), + $(A spec/type.html#pointers, Pointers), + $(REF_ALTTEXT Tuples, Tuple, std,typecons), + $(A spec/struct.html#alias-this, Alias This) + ), + Compatibility + $(ITEMIZE + C-like syntax, + $(A spec/type.html, Support for all C types), + $(A spec/statement.html#NonEmptyStatementNoCaseNoDefault, + `if`, `while`, `do`, `for`, `switch`, `goto`), + $(A spec/attribute.html#linkage, Direct access to C), + $(A spec/importc.html, Import C code), + $(A spec/betterc.html, Better C subset), + Use existing debuggers, + $(A spec/attribute.html#align, Struct member alignment control), + Generates standard object files, + $(A pretod.html, Obviates need for a macro text preprocessor) + ), + Other + $(ITEMIZE + $(A spec/version.html, Conditional compilation), + $(A spec/lex.html, Unicode source text), + $(A spec/statement.html#with-statement, `with` statement), + $(A spec/attribute.html#UserDefinedAttribute, User-Defined Attributes), + $(A spec/ddoc.html, Documentation comments), + $(A spec/ddoc.html#using_ddoc_to_generate_examples, Documented unit tests) + ) ) ) Macros: - TITLE=Comparison - WIKI=Comparison - CATEGORY_FEATURES=$0 - NO=No - NO1=No - YES=Yes - YES1=Yes - + TITLE=Features Overview diff --git a/concepts.dd b/concepts.dd deleted file mode 100644 index 561b761ceb..0000000000 --- a/concepts.dd +++ /dev/null @@ -1,246 +0,0 @@ -Ddoc - -$(D_S Template Constraints, - - $(P Templates are normally overloaded and matched based on the - template arguments being matched to the template parameters. - The template parameters can specify specializations, so that - the template argument must match particular type patterns. - Similarly, template value arguments can be constrained to - match particular types.) - - $(P But this has its limitations. Many times there are - arbitrarily more - complex criteria for what should be accepted by the template. - This can be used to: - ) - - $(UL - $(LI more finely discriminate about which - template gets instantiated for given arguments) - $(LI provides better self-documentation about what - characteristics template parameters must have) - $(LI can provide better diagnostics when arguments don't match, - rather than an obscure error message based on the irrelevant - (to the user) internal details of the template implementation) - ) - - $(P Constraints address this by simply providing an - expression that must evaluate at compile time to true - after the arguments are matched to the parameters. - If it is true, then that template is a valid match for - the arguments, if not, then it is not and is passed over - during overload matching.) - - $(P The constraint expression follows the template declaration - and the $(CODE if) keyword:) - ---- -template Foo(int N) - if (N & 1) -{ - ... -} ---- - - $(P which constrains the template $(CODE Foo) to match only if its - argument - is an odd integer. Arbitrarily complex criteria can be used, as - long as it can be computed at compile time. For example, here's - a template that only accepts prime numbers: - ) - ---- -bool isprime(int n) -{ - if (n < 1 || (n & 1) == 0) - return false; - if (n > 3) - { - for (auto i = 3; i * i < n; i += 2) - { - if ((n % i) == 0) - return false; - } - } - return true; -} - -template Foo(int N) - if (isprime(N)) -{ - ... -} - -Foo!(5) // ok, 5 is prime -Foo!(6) // no match for Foo ---- - - $(P Type constraints can be complex, too. For example, a template - Bar that will accept any floating point type using the traditional - type specializations: - ) ---- -template Bar(T:float) -{ - ... -} -template Bar(T:double) -{ - ... -} -template Bar(T:real) -{ - ... -} ---- - $(P and the template implementation body must be duplicated - three times. But with constraints, this can be specified - with one template: - ) ---- -template Bar(T) - if (is(T == float) || is(T == double) || is(T == real)) -{ - ... -} ---- - $(P This can be simplified by using the $(CODE isFloatingPoint) - template in library module $(CODE std.traits): - ) ---- -import std.traits; -template Bar(T) - if (isFloatingPoint!(T)) -{ - ... -} ---- - - $(P Characteristics of types can be tested, such as if - a type can be added: - ) - ---- -// Returns true if instances of type T can be added -template isAddable(T) -{ // Works by attempting to add two instances of type T - const isAddable = __traits(compiles, (T t) { return t + t; }); -} - -int Foo(T)(T t) - if (isAddable!(T)) -{ - return 3; -} - -struct S -{ - void opAdd(S s) { } // an addable struct type -} - -void main() -{ - Foo(4); // succeeds - S s; - Foo(s); // succeeds - Foo("a"); // fails to match -} ---- - - $(P Since any expression that can be computed at compile time - is allowed as a constraint, constraints can be composed: - ) - ---- -int Foo(T)(T t) - if (isAddable!(T) && isMultipliable!(T)) -{ - return 3; -} ---- - - $(P A more complex constraint can specify a list of operations - that must be doable with the type, such as $(CODE isStack) which - specifies the constraints that a stack type must have:) - ----- -template isStack(T) -{ - const isStack = - __traits(compiles, - (T t) - { T.value_type v = top(t); - push(t, v); - pop(t); - if (empty(t)) { } - }); -} - -template Foo(T) - if (isStack!(T)) -{ - ... -} ----- - - $(P and constraints can deal with multiple parameters:) - ---- -template Foo(T, int N) - if (isAddable!(T) && isprime(N)) -{ - ... -} ---- - -

    Overloading based on Constraints

    - - $(P Given a list of overloaded templates with the same name, - constraints act as a yes/no filter to determine the list - of candidates for a match. - Overloading based on constraints can thus be achieved by - setting up constraint expressions that are mutually exclusive. - For example, overloading template $(CODE Foo) so that one - takes odd integers and the other even: - ) ---- -template Foo(int N) if (N & 1) { ... } // A -template Foo(int N) if (!(N & 1)) { ... } // B -... -Foo!(3) // instantiates A -Foo!(64) // instantiates B ---- - - $(P Constraints are not involved with determining which - template is more specialized than another. - ) - ---- -void foo(T, int N)() if (N & 1) { ... } // A -void foo(T : int, int N)() if (N > 3) { ... } // B -... -foo!(int, 7)(); // picks B, more specialized -foo!(int, 1)(); // picks A, as it fails B's constraint -foo!("a", 7)(); // picks A -foo!("a", 4)(); // error, no match ---- - -

    References

    - - $(UL - $(LI $(LINK2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2081.pdf, Concepts (Revision 1)) - by Douglas Gregor and Bjarne Stroustrup - ) - ) - -) - -Macros: - TITLE=Template Constraints - WIKI=Constraints -META_KEYWORDS=D Programming Language, constraints, template, concepts, C++ -META_DESCRIPTION=Going beyond type patterns to constrain template instantiations. - - - diff --git a/const-faq.dd b/const-faq.dd deleted file mode 100644 index a48fa24043..0000000000 --- a/const-faq.dd +++ /dev/null @@ -1,294 +0,0 @@ -Ddoc - -$(D_S const(FAQ), - - $(P D's $(D const)/$(D immutable) system is unique, and so there - are a lot of questions about it. ) - - $(UL - - $(ITEMR const, Why does D have const?) - $(ITEMR principles, What principles drove the D const design?) - $(ITEMR transitive-const, What is $(I transitive const)?) - $(ITEMR head-const, What is $(I head const)?) - $(ITEMR tail-const, What is $(I tail const)?) - $(ITEMR logical-const, What is $(I logical const)?) - $(ITEMR readonly, Why not use $(I readonly) to mean read only view?) - $(ITEMR java-const, Why did Java reject const?) - $(ITEMR cpp-const, How does const differ in C++?) - $(ITEMR invariant-strings, Why are strings immutable?) - $(ITEMR const-parameters, Why aren't function parameters const by default?) - $(ITEMR static-members, Are static class members covered by transitive const?) - $(ITEMR invariant, What is $(I immutable) good for?) - ) - -$(ITEM const, Why does D have const?) - - $(P People often express frustration with const and immutable - in D 2.0 and wonder if it is worth it. - ) - - $(OL - - $(LI It makes function interfaces more self-documenting. Without - transitive const, for all pointer/reference parameters one must rely on - the documentation (which is always missing, out of date, or wrong). Note - that without transitivity, C++ const is nearly useless for such - self-documentation, which is why C++ programmers tend to rely on - convention instead. - ) - - $(LI It makes for interfaces that can be relied upon, which becomes - increasingly important the more people that are involved with the code. - In other words, it scales very well. People who are involved with - projects with large teams of programmers say that lack of const - makes their lives difficult because they cannot rely on the compiler to - enforce convention. The larger the team, the worse it gets. Managing - APIs is critical to a large project - it's why BASIC doesn't scale (for - an extreme example). - ) - - $(LI Const transitivity makes for some interesting optimization - opportunities. The value of this has not been explored or exploited. - ) - - $(LI Here's the biggie. Points 1..3 are insignificant in comparison. The - future of programming will be multicore, multithreaded. Languages that - make it easy to program them will supplant languages that don't. - Transitive const is key to bringing D into this paradigm. The surge in - use of Haskell and Erlang is evidence of this coming trend (the killer - feature of those languages is they make it easy to do multiprogramming). - C++ cannot be retrofitted to supporting multiprogramming in a manner - that makes it accessible. D isn't there yet, but it will be, and - transitive const will be absolutely fundamental to making it work. - ) - ) - - $(P Of course, for writing single-threaded one man programs of - fairly modest size, const is not particularly useful. - And in D const can be effectively ignored by just not using it, or - by using D 1.0. The only place const is imposed is with the immutable - string type. - ) - -$(ITEM principles, What principles drove the D const design?) - - $(OL - $(LI It will be mathematically sound. That means there - are no legal escapes from it.) - $(LI Any type can be wrapped in a struct and the resulting - struct can still exhibit the same const behavior - in other - words, no magic behavior for certain types.) - $(LI Const behavior will be transitive.) - $(LI Const behavior for type T will be equivalent for all types T.) - ) - -$(ITEM transitive-const, What is $(I transitive const)?) - - $(P Transitive const means that once const is applied to a type, - it applies recursively to every sub-component of that type. Hence: - ) - ---- -const(int*)** p; -p += 1; // ok, p is mutable -*p += 1; // ok, *p is mutable -**p += 1; // error, **p is const -***p += 1; // error, ***p is const ---- - - $(P With transitivity, there is no way to have a - $(I const pointer to mutable int). - ) - - $(P C++ const is not transitive.) - -$(ITEM head-const, What is $(I head const)?) - - $(P Head const is where the const applies only to the component - of the type adjacent to the const. For example: - ) - ---- -headconst(int**) p; ---- - $(P would be read as p being a: $(I const pointer to mutable pointer - to mutable int.) D does not have head const (the $(CODE headconst) is - there just for illustrative purposes), but C++ const is - a head const system. - ) - -$(ITEM tail-const, What is $(I tail const)?) - - $(P Tail const is the complement of head const - everything reachable - from the const type is also const except for the top level. For - example: - ) - ---- -tailconst(int**) p; ---- - $(P would be read as p being a: $(I mutable pointer to const pointer - to const int.) Head const combined with tail const yields transitive - const. - D doesn't have $(CODE tailconst) (the keyword is there just for - illustrative purposes) as a distinct type constructor. - ) - -$(ITEM logical-const, What is $(I logical const)?) - - $(P $(I Logical const) refers to data that appears to be constant - to an observer, but is not actually const. An example would be - an object that does lazy evaluation:) - ---- -struct Foo { - mutable int len; - mutable bool len_done; - const char* str; - int length() - { if (!len_done) - { len = strlen(str); - len_done = true; - } - return len; - } - this(char* str) { this.str = str; } -} -const Foo f = Foo("hello"); -bar(f.length); ---- - - $(P The example evaluates $(CODE f.len) only if it is needed. - $(CODE Foo) is logically const, because to the observer of the object - its return values never change after construction. - The $(CODE mutable) qualifier says that even if an instance - of $(CODE Foo) is const, those fields can still change. - While C++ supports the notion of logical const, D does not, - and D does not have a $(CODE mutable) qualifier. - ) - - $(P The problem with logical const is that const is no longer - transitive. Not being transitive means there is the potential - for threading race conditions, and there is no way to determine - if an opaque const type has mutable members or not. - ) - - $(P Reference: - $(LINK2 http://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter08_025.html, mutable: bitwise vs. logical const) - ) - -$(ITEM readonly, Why not use $(I readonly) to mean read only view?) - - $(P $(I Readonly) has a well established meaning in software to - mean ROM, or Read Only Memory that can never be changed. - For computers with hardware protection for memory pages, readonly - also means that the memory contents cannot be altered. - Using readonly in D to mean a read only view of memory that could - be altered by another alias or thread runs counter to this. - ) - -$(ITEM java-const, Why did Java reject const?) - - $(P $(LINK http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070) - ) - -$(ITEM cpp-const, How does const differ in C++?) - - $(P C++ has a const system that is closer to D's than any other - language, but it still has huge differences:) - - $(OL - $(LI const is not transitive) - $(LI no immutables) - $(LI const objects can have mutable members) - $(LI const can be legally cast away and the data modified) - $(LI $(CODE const T) and $(CODE T) are not always distinct types) - ) - -$(ITEM invariant-strings, Why are strings immutable?) - - $(P $(LINK2 http://drdobbs.com/blogs/architecture-and-design/228700475, Immutable Strings) - ) - -$(ITEM const-parameters, Why aren't function parameters const by default?) - - $(P Since most (nearly all?) function parameters will not be modified, - it would seem to make sense to make them all const by default, - and one would have to specifically mark as mutable those that would - be changed. The problems with this are: - ) - - $(OL - - $(LI It would be a huge break from past D practice, and practice - in C, C++, Java, C#, etc.) - $(LI It would require a new keyword, say $(CODE mutable).) - $(LI And worst, it would make declarations inconsistent: ---- -void foo(int* p) { - int* q; - ... -} ---- - $(CODE p) points to const, and $(CODE q) points to mutable. - This kind of inconsistency leads to all sorts of mistakes. - It also makes it very hard to write generic code that deals with - types. - ) - ) - - $(P Using $(CODE in) can mitigate the ugliness of having to annotate - with $(CODE const):) ---- -void str_replace(in char[] haystack, in char[] needle); ---- - -$(ITEM static-members, Are static class members covered by transitive const?) - - $(P A static class member is part of the global state of a program, - not part of the state of an object. Thus, a class having a mutable - static member does not violate the transitive constness of an object - of that class. - ) - -$(ITEM invariant, What is $(I immutable) good for?) - - $(P Immutable data, once initialized, is never changed. - This has many uses: - ) - - $(UL - $(LI Access to immutable data need not be synchronized - when multiple threads read it.) - $(LI Data races, tearing, sequential consistency, and - cache consistency are all non-issues when working with - immutable data.) - $(LI Pure functions can only accept immutable parameters.) - $(LI When doing a $(I deep copy) of a data structure, - the immutable portions need not be copied.) - $(LI Invariance allows a large chunk of data to be treated - as a value type even if it is passed around by reference - (strings are the most common case of this).) - $(LI Immutable type provides more self-documenting information - to the programmer.) - $(LI Immutable data can be placed in hardware protected read-only - memory, or even in ROMs.) - $(LI If immutable data does change, it is a sure sign of a memory - corruption bug, and it is possible to automatically check for - such data integrity.) - $(LI Immutable types provide for many program optimization - opportunities.) - ) - - $(P $(I const) acts as a bridge between the mutable and immutable - worlds, so a single function can be used to accept both types - of arguments.) -) - -Macros: - TITLE=const(FAQ) - WIKI=constFAQ - CATEGORY_FAQ=$0 - ITEMR=$(LI $(LINK2 #$1, $+)) - ITEM=

    $+

    diff --git a/const3.dd b/const3.dd deleted file mode 100644 index c8d2b28ea9..0000000000 --- a/const3.dd +++ /dev/null @@ -1,592 +0,0 @@ -Ddoc - -$(D_S Const and Immutable, - - $(P When examining a data structure or interface, it is very - helpful to be able to easily tell which data can be expected to not - change, which data might change, and who may change that data. - This is done with the aid of the language typing system. - Data can be marked as const or immutable, with the default being - changeable (or $(I mutable)). - ) - - $(P $(I immutable) applies to data that cannot change. - Immutable data values, once constructed, remain the same for - the duration of the program's - execution. - Immutable data can be placed in ROM (Read Only Memory) or in - memory pages marked by the hardware as read only. - Since immutable data does not change, it enables many opportunities - for program optimization, and has applications in functional - style programming. - ) - - $(P $(I const) applies to data that cannot be changed by - the const reference to that data. It may, however, be changed - by another reference to that same data. - Const finds applications in passing data through interfaces - that promise not to modify them. - ) - - $(P Both immutable and const are $(I transitive), which means - that any data reachable through an immutable reference is also - immutable, and likewise for const. - ) - -$(SECTION2 Immutable Storage Class, - - $(P - The simplest immutable declarations use it as a storage class. - It can be used to declare manifest constants. - ) - ---- -immutable int x = 3; // x is set to 3 -x = 4; // error, x is immutable -char[x] s; // s is an array of 3 char's ---- - - $(P The type can be inferred from the initializer: - ) ---- -immutable y = 4; // y is of type int -y = 5; // error, y is immutable ---- - - $(P If the initializer is not present, the immutable can - be initialized from the corresponding constructor: - ) - ---- -immutable int z; -void test() { - z = 3; // error, z is immutable -} -static this() { - z = 3; // ok, can set immutable that doesn't - // have static initializer -} ---- - $(P - The initializer for a non-local immutable declaration must be - evaluatable - at compile time: - ) - ---- -int foo(int f) { return f * 3; } -int i = 5; -immutable x = 3 * 4; // ok, 12 -immutable y = i + 1; // error, cannot evaluate at compile time -immutable z = foo(2) + 1; // ok, foo(2) can be evaluated at compile time, 7 ---- - - $(P The initializer for a non-static local immutable declaration - is evaluated at run time: - ) ---- -int foo(int f) -{ - immutable x = f + 1; // evaluated at run time - x = 3; // error, x is immutable -} ---- - - $(P - Because immutable is transitive, data referred to by an immutable is - also immutable: - ) - ---- -immutable char[] s = "foo"; -s[0] = 'a'; // error, s refers to immutable data -s = "bar"; // error, s is immutable ---- - - $(P Immutable declarations can appear as lvalues, i.e. they can - have their address taken, and occupy storage. - ) -) - -$(SECTION2 Const Storage Class, - - $(P - A const declaration is exactly like an immutable declaration, - with the following differences: - ) - - $(UL - $(LI Any data referenced by the const declaration cannot be - changed from the const declaration, but it might be changed - by other references to the same data.) - - $(LI The type of a const declaration is itself const.) - ) - -$(COMMENT -$(TABLE1 - -$(TR $(TH  ) $(TH AddrOf) $(TH CTFEInit) $(TH Static) $(TH Field) $(TH Stack) $(TH Ctor)) - -$(TR $(TD  ) - $(TD Can the address be taken?) - $(TD Is compile time function evaluation done on the initializer?) - $(TD allocated as static data?) - $(TD allocated as a per-instance field?) - $(TD allocated on the stack?) - $(TD Can the variable be assigned to in a constructor?) -) - - -$(TR $(TH Global data)) - -$(TR $(TD1 const T x;) $(Y) $(N) $(Y) $(N) $(N) $(Y)) -$(TR $(TD1 const T x = 3;) $(N) $(Y) $(N) $(N) $(N) $(N)) -$(TR $(TD1 static const T x;) $(Y) $(N) $(Y) $(N) $(N) $(Y)) -$(TR $(TD1 static const T x = 3;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) - - -$(TR $(TH Class Members)) - -$(TR $(TD1 const T x;) $(Y) $(N) $(N) $(Y) $(N) $(Y)) -$(TR $(TD1 const T x = 3;) $(N) $(Y) $(N) $(N) $(N) $(N)) -$(TR $(TD1 static const T x;) $(Y) $(N) $(Y) $(N) $(N) $(Y)) -$(TR $(TD1 static const T x = 3;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) - - -$(TR $(TH Local Variables)) - -$(TR $(TD1 const T x;) $(Y) $(Y) $(N) $(N) $(Y) $(N)) -$(TR $(TD1 const T x = 3;) $(Y) $(N) $(N) $(N) $(Y) $(N)) -$(TR $(TD1 static const T x;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) -$(TR $(TD1 static const T x = 3;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) - -$(TR $(TH Function Parameters)) - -$(TR $(TD1 const T x;) $(Y) $(N) $(N) $(N) $(Y) $(N)) -) - - -$(P Notes:) - -$(OL -$(LI If CTFEInit is true, then the initializer can also be used for -constant folding.) -) - - -$(TABLE1 -Template Argument Deduced Type -$(TR $(TH  ) $(TH mutable $(CODE T)) $(TH1 const(T)) $(TH1 immutable(T))) -$(TR $(TD1 foo(U)) $(TDE T) $(TDE T) $(TDE T)) -$(TR $(TD1 foo(U:U)) $(TDE T) $(TDE const(T)) $(TDE immutable(T))) -$(TR $(TD1 foo(U:const(U))) $(TDI T) $(TDE T) $(TDI T)) -$(TR $(TD1 foo(U:immutable(U))) $(NM) $(NM) $(TDE T)) -) - -$(P Where:) - -$(TABLE1 -$(TR $(TD $(GREEN green)) $(TD exact match)) -$(TR $(TD $(ORANGE orange)) $(TD implicit conversion)) -) -) -) - -$(SECTION2 Immutable Type, - - $(P - Data that will never change its value can be typed as immutable. - The immutable keyword can be used as a $(I type constructor): - ) - ---- -immutable(char)[] s = "hello"; ---- - - $(P - The immutable applies to the type within the following parentheses. - So, while $(CODE s) can be assigned new values, - the contents of $(CODE s[]) cannot be: - ) - ---- -s[0] = 'b'; // error, s[] is immutable -s = null; // ok, s itself is not immutable ---- - - $(P - Immutableness is transitive, meaning it applies to anything that - can be referenced from the immutable type: - ) - ---- -immutable(char*)** p = ...; -p = ...; // ok, p is not immutable -*p = ...; // ok, *p is not immutable -**p = ...; // error, **p is immutable -***p = ...; // error, ***p is immutable ---- - - $(P Immutable used as a storage class is equivalent to using - immutable as a type constructor for the entire type of a - declaration:) - ---- -immutable int x = 3; // x is typed as immutable(int) -immutable(int) y = 3; // y is immutable ---- -) - - -$(SECTION2 Creating Immutable Data, - - $(P - The first way is to use a literal that is already immutable, - such as string literals. String literals are always immutable. - ) - ---- -auto s = "hello"; // s is immutable(char)[5] -char[] p = "world"; // error, cannot implicitly convert immutable - // to mutable ---- - - $(P - The second way is to cast data to immutable. - When doing so, it is up to the programmer to ensure that no - other mutable references to the same data exist. - ) - ---- -char[] s = ...; -immutable(char)[] p = cast(immutable)s; // undefined behavior -immutable(char)[] p = cast(immutable)s.dup; // ok, unique reference ---- - - $(P - The $(CODE .idup) property is a convenient way to create an immutable - copy of an array: - ) - ---- -auto p = s.idup; -p[0] = ...; // error, p[] is immutable ---- - -

    Removing Immutable With A Cast

    - - $(P - The immutable type can be removed with a cast: - ) - ---- -immutable int* p = ...; -int* q = cast(int*)p; ---- - - $(P - This does not mean, however, that one can change the data: - ) - ---- -*q = 3; // allowed by compiler, but result is undefined behavior ---- - - $(P - The ability to cast away immutable-correctness is necessary in - some cases where the static typing is incorrect and not fixable, such - as when referencing code in a library one cannot change. - Casting is, as always, a blunt and effective instrument, and - when using it to cast away immutable-correctness, one must assume - the responsibility to ensure the immutableness of the data, as - the compiler will no longer be able to statically do so. - ) -) - - -$(SECTION2 Immutable Member Functions, - - $(P - Immutable member functions are guaranteed that the object - and anything referred to by the $(CODE this) reference is immutable. - They are declared as: - ) - ---- -struct S { - int x; - - void foo() immutable { - x = 4; // error, x is immutable - this.x = 4; // error, x is immutable - } -} ---- - $(P Note that using $(D_KEYWORD immutable) on the left hand side of a method does not apply to the return type: - ) - ---- -struct S { - immutable int[] bar() // bar is still immutable, return type is not! - { - } -} ---- - $(P To make the return type $(D_KEYWORD immutable), you need to surround the return type with parentheses: - ) - ---- -struct S { - immutable(int[]) bar() // bar is now mutable, return type is immutable. - { - } -} ---- - $(P To make both the return type and the method $(D_KEYWORD immutable), you can write: - ) ---- -struct S { - immutable(int[]) bar() immutable - { - } -} ---- -) - - -$(SECTION2 Const Type, - - $(P - Const types are like immutable types, except that const - forms a read-only $(I view) of data. Other aliases to that - same data may change it at any time. - ) -) - - -$(SECTION2 Const Member Functions, - - $(P - Const member functions are functions that are not allowed to - change any part of the object through the member function's - this reference. - ) -) - - -$(SECTION2 Implicit Conversions, - - $(P - Mutable and immutable types can be implicitly converted to const. - Mutable types cannot be implicitly converted to immutable, - and vice versa. - ) -) - - -$(SECTION2 Comparing D Immutable and Const with C++ Const, - - - - - - $(TR - $(TH Feature) - $(TH D) - $(TH C++98) - ) - - - - - $(TR - $(TD const keyword) - $(TD Yes) - $(TD Yes) - ) - - $(TR - $(TD immutable keyword) - $(TD Yes) - $(TD No) - ) - - $(TR - $(TD const notation) - $(TD Functional: ---- -//ptr to const ptr to const int -const(int*)* p; ---- - ) - $(TD Postfix: -$(CPPCODE -//ptr to const ptr to const int -const int *const *p; -) - ) - ) - - $(TR - $(TD transitive const) - $(TD Yes: ---- -//const ptr to const ptr to const int -const int** p; -**p = 3; // error ---- - ) - $(TD No: -$(CPPCODE -// const ptr to ptr to int -int** const p; -**p = 3; // ok -) - ) - ) - - $(TR - $(TD cast away const) - $(TD Yes: ---- -// ptr to const int -const(int)* p; -int* q = cast(int*)p; // ok ---- - ) - $(TD Yes: -$(CPPCODE -// ptr to const int -const int* p; -int* q = const_cast<int*>p; //ok -) - ) - ) - - $(TR - $(TD modification after casting away const) - $(TD No: ---- -// ptr to const int -const(int)* p; -int* q = cast(int*)p; -*q = 3; // undefined behavior ---- - ) - $(TD Yes: -$(CPPCODE -// ptr to const int -const int* p; -int* q = const_cast<int*>p; -*q = 3; // ok -) - ) - ) - - $(TR - $(TD overloading of top level const) - $(TD Yes: ---- -void foo(int x); -void foo(const int x); //ok ---- - ) - $(TD No: -$(CPPCODE -void foo(int x); -void foo(const int x); //error -) - ) - ) - - $(TR - $(TD aliasing of const with mutable) - $(TD Yes: ---- -void foo(const int* x, int* y) -{ - bar(*x); // bar(3) - *y = 4; - bar(*x); // bar(4) -} -... -int i = 3; -foo(&i, &i); ---- - ) - $(TD Yes: -$(CPPCODE -void foo(const int* x, int* y) -{ - bar(*x); // bar(3) - *y = 4; - bar(*x); // bar(4) -} -... -int i = 3; -foo(&i, &i); -) - ) - ) - - $(TR - $(TD aliasing of immutable with mutable) - $(TD No: ---- -void foo(immutable int* x, int* y) { - bar(*x); // bar(3) - *y = 4; // undefined behavior - bar(*x); // bar(??) -} -... -int i = 3; -foo(cast(immutable)&i, &i); ---- - ) - $(TD No immutables) - ) - - $(TR - $(TD type of string literal) - $(TD immutable(char)[]) - $(TD const char*) - ) - - - $(TR - $(TD implicit conversion of string literal to non-const) - $(TD not allowed) - $(TD allowed, but deprecated) - ) - - -
    Const, Immutable Comparison
    -) - - -) - -Macros: - TH1=$(CODE $0) - TD1=$(CODE $0) - TDE=$(GREEN $(CODE $0)) - TDI=$(ORANGE $(CODE $0)) - NM=$(TD $(RED no match)) - Y=$(TD $(GREEN Yes)) - N=$(TD $(RED No)) - TITLE=Const and Immutable - WIKI=ConstInvariant - CATEGORY_SPEC=$0 - NO=No - NO1=No - YES=Yes - YES1=Yes - D_CODE =
    $0
    - CPPCODE2 =
    $0
    - ERROR = $(RED $(B error)) - COMMA=, -META_KEYWORDS=D Programming Language, const, immutable -META_DESCRIPTION=Comparison of const between the -D programming language, C++, and C++0x - diff --git a/contributing.dd b/contributing.dd new file mode 100644 index 0000000000..67bf5fda4b --- /dev/null +++ b/contributing.dd @@ -0,0 +1,22 @@ +Ddoc + +$(D_S Contributing, + +$(NOTE To search the bug tracker or report issues, see $(LINK2 bugstats.html, Issues).) + +$(H2 $(LNAME2 github, GitHub Projects)) + +* $(LINK2 https://github.com/dlang, dlang) - dmd, phobos, dub, dlang.org etc +* $(LINK2 https://github.com/dlang-community, dlang-community) - dfmt, dscanner etc + + +$(H2 $(LNAME2 see-also, Getting Started)) + +* Please read: $(LINK2 https://github.com/dlang/dmd/blob/master/CONTRIBUTING.md#solving-bugs--submitting-pull-requests, + Solving bugs / Submitting pull requests) +* Get involved: $(HTTPS wiki.dlang.org/Get_involved) + +) + +Macros: + TITLE=Contributing diff --git a/cpp0x.dd b/cpp0x.dd deleted file mode 100644 index c53bcd6206..0000000000 --- a/cpp0x.dd +++ /dev/null @@ -1,737 +0,0 @@ -Ddoc - -$(COMMUNITY D and C++0x, - - - $(P - C++ is undergoing an upgrade to a new standard, commonly referred - to as C++0x. - This article covers the highlights of - $(LINK2 $(NDOCS)2008/n2597.html, C++0x core language changes) - and compares them with what is available in D. - Since C++0x is far from being finalized, - this article is subject to being obsoleted by new proposals and - revisions to existing ones. - C++0x standard library changes are not addressed here. - TBD means To Be Determined. - ) - -$(SECTION3 Proposed C++0x Features, - - $(UL - $(LI $(LINK2 #rvalue-reference, A Proposal to Add an Rvalue Reference to the C++ Language)) - $(LI $(LINK2 #class-rvalue, Clarification of Initialization of Class Objects by rvalues)) - $(LI $(LINK2 #move-semantics, Extending Move Semantics To *this (Revision 2))) - $(LI $(LINK2 #static-assert, static_assert)) - $(LI $(LINK2 #template-aliases, Template aliases for C++)) - $(LI $(LINK2 #extern-template, Extern template)) - $(LI $(LINK2 #variadic-templates, Variadic Templates)) - $(LI $(LINK2 #variadic-template-templates, Extending Variadic Template Template Parameters)) - $(LI $(LINK2 #nullptr, A name for the null pointer: nullptr)) - $(LI $(LINK2 #strong-enums, Strongly Typed Enums)) - $(LI $(LINK2 #extended-friends, Extended friend Declarations)) - $(LI $(LINK2 #constant-expressions, Generalized Constant Expressions)) - $(LI $(LINK2 #namespace-association, Namespace Association ("Strong Using"))) - $(LI $(LINK2 #c99-preprocessor, Synchronizing the C++ preprocessor with C99)) - $(LI $(LINK2 #alignment, Adding Alignment Support to the C++ Programming Language)) - $(LI $(LINK2 #conditional, Conditionally-Supported Behavior)) - $(LI $(LINK2 #undefined-behavior, Changing Undefined Behavior into Diagnosable Errors)) - $(LI $(LINK2 #long-long, Adding the long long type to C++)) - $(LI $(LINK2 #extended-integer-types, Adding extended integer types to C++)) - $(LI $(LINK2 #delegating-ctors, Delegating Constructors)) - $(LI $(LINK2 #explicit-conversion, Explicit Conversion Operators)) - $(LI $(LINK2 #char16_t, New Character Types in C++)) - $(LI $(LINK2 #right-angle-brackets, Right Angle Brackets)) - $(LI $(LINK2 #type-deduction, Deducing the type of variable from its initializer expression)) - $(LI $(LINK2 #auto-declarations, The Syntax of auto Declarations)) - $(LI $(LINK2 #inheriting-ctors, Inheriting Constructors)) - $(LI $(LINK2 #sequence-points, A finer-grained alternative to sequence points)) - $(LI $(LINK2 #lambda, (monomorphic) Lambda expressions and closures for C++)) - $(LI $(LINK2 #__func__, Proposed addition of __func__ predefined identifier from C99)) - $(LI $(LINK2 #atomic, Atomic operations with multi-threaded environments)) - $(LI $(LINK2 #concurrency, Sequencing and the concurrency memory model)) - $(LI $(LINK2 #raw-strings, Raw String Literals)) - $(LI $(LINK2 #pod, PODs unstrung)) - $(LI $(LINK2 #exceptions, Propagating exceptions when joining threads)) - $(LI $(LINK2 #decltype, Decltype)) - $(LI $(LINK2 #sizeof, Extending sizeof)) - $(LI $(LINK2 #utf8-literals, UTF8 Literals)) - $(LI $(LINK2 #ucs-in-literals, Universal Character Names in Literals)) - $(LI $(LINK2 #defaulted, Defaulted and Deleted Functions)) - $(LI $(LINK2 #unions, Unrestricted Unions)) - $(LI $(LINK2 #library, A Multi-threading Library for Standard C++)) - $(LI $(LINK2 #abandoning, Abandoning a Process)) - $(LI $(LINK2 #return-types, New function declaration syntax for deduced return types)) - $(LI $(LINK2 #atomic-signals, Allow atomics use in signal handlers)) - ) - - $(UL - $(LI $(LINK2 #local-classes, Making Local Classes more Useful)) - $(LI $(LINK2 #initializer-lists, Initializer lists)) - $(LI $(LINK2 #thread-local-storage, Thread-Local Storage)) - $(LI $(LINK2 #member-initializers, Member Initializers)) - $(LI $(LINK2 #concepts, Concepts (unified proposal))) - $(LI $(LINK2 #for-loop, Proposal for new for-loop)) - $(LI $(LINK2 #general-attributes, General Attributes for C++)) - ) - - $(UL - $(LI $(LINK2 #extensible-literals, Extensible Literals)) - $(LI $(LINK2 #dynamic-concurrency, Dynamic initialization and concurrency)) - $(LI $(LINK2 #garbage-collection, Minimal Support for Garbage Collection and Reachability-Based Leak Detection)) - $(LI $(LINK2 #forward-enums, Forward declaration of enumerations)) - ) -) - -$(SECTION3 $(LNAME2 rvalue-reference, A Proposal to Add an Rvalue Reference to the C++ Language), - - $(P $(LINK2 $(NDOCS)2005/n1770.html, N1770): TBD - ) - -) - -$(SECTION3 $(LNAME2 class-rvalue, Clarification of Initialization of Class Objects by rvalues), - - $(P $(LINK2 $(NDOCS)2004/n1610.html, N1610): TBD - ) - -) - -$(SECTION3 $(LNAME2 move-semantics, Extending Move Semantics To *this (Revision 2)), - - $(P $(LINK2 $(NDOCS)2007/n2439.htm, N2439): TBD - ) - -) - -$(SECTION3 $(LNAME2 static-assert, static_assert), - - $(P $(LINK2 $(NDOCS)2004/n1720.html, N1720): - $(LINK2 version.html#StaticAssert, static assert) is - part of D. - ) - -) - -$(SECTION3 $(LNAME2 template-aliases, Template aliases for C++), - - $(P $(LINK2 $(NDOCS)2007/n2258.pdf, N2258): - Both $(LINK2 template.html, templates and template instantiations) - can be $(LINK2 declaration.html#alias, aliased): - ) ---- -struct S(T) { T int; } -alias S X; // alias template -alias S!(int) Y; // alias template instantiation -X!(int) x; -Y y; // x and y are the same type ---- -) - -$(SECTION3 $(LNAME2 extern-template, Extern template), - - $(P $(LINK2 $(NDOCS)2006/n1987.htm, N1987): - This is a workaround for problems in the traditional compile/link - build model. - The D compiler deals with this by if multiple modules are compiled - at the same time, only one instance of a template is generated - for all the generated object files rather than one instance in each - object file. Further improvements are planned for generating library - modules that avoid multiple redundant template instantiations. - ) - -) - -$(SECTION3 $(LNAME2 variadic-templates, Variadic Templates), - - $(P $(LINK2 $(NDOCS)2007/n2242.pdf, N2242): - D's $(LINK2 template.html#variadic-templates, variadic templates). - ) - -) - -$(SECTION3 $(LNAME2 variadic-template-templates, Extending Variadic Template Template Parameters), - - $(P $(LINK2 $(NDOCS)2008/n2555.pdf, N2555): TBD - ) - -) - -$(SECTION3 $(LNAME2 nullptr, A name for the null pointer: nullptr), - - $(P $(LINK2 $(NDOCS)2007/n2431.pdf, N2431): - D has the $(LINK2 expression.html#null, null) equivalent. - ) - -) - -$(SECTION3 $(LNAME2 strong-enums, Strongly Typed Enums), - - $(P $(LINK2 $(NDOCS)2007/n2347.pdf, N2347): - D $(LINK2 enum.html, enums) are: - ) - - $(OL - $(LI Comparisons between different enum types should be an error, - but is not: ---- -void main() { - enum Color { ClrRed, ClrOrange, ClrYellow, ClrGreen, ClrBlue, ClrViolet }; - enum Alert { CndGreen, CndYellow, CndRed }; - Color c = Color.ClrRed; - Alert a = Alert.CndGreen; - a = c; // error - a = Color.ClrYellow; // error - bool armWeapons = ( a >= Color.ClrYellow ); // ok; oops -} ---- - ) - $(LI The underlying type can be specified.) - $(LI Named enums are strongly scoped. Anonymous enum members are - declared in the enclosing scope.) - $(LI Explicit qualification is needed to specify a named enum - member.) - ) - -) - -$(SECTION3 $(LNAME2 extended-friends, Extended friend Declarations), - - $(P $(LINK2 $(NDOCS)2005/n1791.pdf, N1791): - All code in a module has - $(LINK2 attribute.html#ProtectionAttribute, access) - to private members - of any struct or class declared in that module that is in - scope. - Package protected members can be accessed by any code in the - same package. - There is no need in D to have friend declarations or - complex lookup rules for them. - ) - -) - -$(SECTION3 $(LNAME2 constant-expressions, Generalized Constant Expressions), - - $(P $(LINK2 $(NDOCS)2007/n2235.pdf, N2235): - D has $(LINK2 function.html#interpretation, compile time function execution) - (CTFE). CTFE is much more flexible, as functions to be evaluated - at compile time: - ) - - $(OL - $(LI do not require a special keyword (C++0x requires $(CODE constexpr))) - $(LI can have multiple statements in the function) - $(LI can be recursive) - $(LI can modify local variables) - $(LI can have out parameters) - ) - -) - -$(SECTION3 $(LNAME2 namespace-association, Namespace Association ("Strong Using")), - - $(P $(LINK2 $(NDOCS)2008/n2535.html, N2535): - D doesn't have namespaces, - so this is irrelevant. - ) - -) - -$(SECTION3 $(LNAME2 c99-preprocessor, Synchronizing the C++ preprocessor with C99), - - $(P $(LINK2 $(NDOCS)2004/n1653.htm, N1653): - D does not have a preprocessor, - so this is not relevant to D. - ) - -) - -$(SECTION3 $(LNAME2 alignment, Adding Alignment Support to the C++ Programming Language), - - $(P $(LINK2 $(NDOCS)2007/n2341.pdf, N2341): - D has the $(LINK2 attribute.html#align, align) - attribute to specify the alignment - of declarations, and the $(LINK2 property.html#alignof, .alignof) - property to - determine the alignment size of an expression or type. - ) - -) - -$(SECTION3 $(LNAME2 conditional, Conditionally-Supported Behavior), - - $(P $(LINK2 $(NDOCS)2004/n1627.pdf, N1627): - There are some allowed vendor specific behaviors in D, - such as $(LINK2 pragma.html, pragmas). - ) - -) - -$(SECTION3 $(LNAME2 undefined-behavior, Changing Undefined Behavior into Diagnosable Errors), - - $(P $(LINK2 $(NDOCS)2004/n1727.pdf, N1727): - D does not have undefined behavior with integer literal types, - character escapes, or passing non-POD objects to ellipses. - ) - -) - -$(SECTION3 $(LNAME2 long-long, Adding the long long type to C++), - - $(P $(LINK2 $(NDOCS)2005/n1811.pdf, N1811): - D's $(LINK2 type.html, long) type is equivalent. - ) - -) - -$(SECTION3 $(LNAME2 extended-integer-types, Adding extended integer types to C++), - - $(P $(LINK2 $(NDOCS)2006/n1988.pdf, N1988): - D has the $(LINK2 type.html, cent and - ucent) types for - 128 bit integral types (not implemented in dmd or gdc). - There is no proposal for other extended - integral types, but it's hard to imagine a justification for - adding more to the core language. - ) - -) - -$(SECTION3 $(LNAME2 delegating-ctors, Delegating Constructors), - - $(P $(LINK2 $(NDOCS)2006/n1986.pdf, N1986): - D has - $(LINK2 class.html#delegating-constructors, delegating constructors). - ) - -) - -$(SECTION3 $(LNAME2 explicit-conversion, Explicit Conversion Operators), - - $(P $(LINK2 $(NDOCS)2007/n2437.html, N2437): TBD - ) - -) - -$(SECTION3 $(LNAME2 char16_t, New Character Types in C++), - - $(P $(LINK2 $(NDOCS)2007/n2249.html, N2249): - C++0x adds new character types char16_t and char32_t, - which are equivalent to D's $(LINK2 type.html, wchar and dchar types). - The u and U character literal prefixes are equivalent to the - D $(LINK2 lex.html#StringLiteral, w and d postfixes). - ) - -) - -$(SECTION3 $(LNAME2 right-angle-brackets, Right Angle Brackets), - - $(P $(LINK2 $(NDOCS)2005/n1757.html, N1757): - Since D uses !( ) to instantiate templates rather than - < >, there are no parsing ambiguities and - no fixes are necessary. - ) - -) - -$(SECTION3 $(LNAME2 type-deduction, Deducing the type of variable from its initializer expression), - - $(P $(LINK2 $(NDOCS)2006/n1984.pdf, N1984): - D has $(LINK2 declaration.html#AutoDeclaration, type inference) - from initializers. - ) - -) - -$(SECTION3 $(LNAME2 auto-declarations, The Syntax of auto Declarations), - - $(P $(LINK2 $(NDOCS)2008/n2546.html, N2546): - D $(LINK2 attribute.html#auto, auto declarations) - do not have syntactic issues. - ) - -) - -$(SECTION3 $(LNAME2 inheriting-ctors, Inheriting Constructors), - - $(P $(LINK2 $(NDOCS)2008/n2540.html, N2540): TBD - ) - -) - -$(SECTION3 $(LNAME2 sequence-points, A finer-grained alternative to sequence points), - - $(P $(LINK2 $(NDOCS)2007/n2239.htm, N2239): TBD - ) - -) - -$(SECTION3 $(LNAME2 lambda, (monomorphic) Lambda expressions and closures for C++), - - $(P $(LINK2 $(NDOCS)2008/n2550.pdf, N2550): - D has $(GLINK2 expression, FunctionLiteral)s (lambda expressions) and - $(LINK2 function.html#closures, closures). - ) - -) - -$(SECTION3 $(LNAME2 __func__, Proposed addition of __func__ predefined identifier from C99), - - $(P $(LINK2 $(NDOCS)2007/n2340.html, N2340): TBD - ) - -) - -$(SECTION3 $(LNAME2 atomic, Atomic operations with multi-threaded environments), - - $(P $(LINK2 $(NDOCS)2007/n2427.html, N2427): TBD - ) - -) - -$(SECTION3 $(LNAME2 concurrency, Sequencing and the concurrency memory model), - - $(P $(LINK2 $(NDOCS)2007/n2429.htm, N2429): TBD - ) - -) - -$(SECTION3 $(LNAME2 raw-strings, Raw String Literals), - - $(P $(LINK2 $(NDOCS)2007/n2442.html, N2442): - D has $(LINK2 lex.html#StringLiteral, wysiwyg and delimited strings), - and all strings are Unicode. - ) - -) - -$(SECTION3 $(LNAME2 pod, PODs unstrung), - - $(P $(LINK2 $(NDOCS)2007/n2294.html, N2294): - All D $(LINK2 struct.html, structs) are - $(LINK2 glossary.html#pod, POD (Plain Old Data)). - D $(LINK2 class.html, classes) are reference, polymorphic types. - ) - -) - -$(SECTION3 $(LNAME2 exceptions, Propagating exceptions when joining threads), - - $(P $(LINK2 $(NDOCS)2007/n2179.html, N2179): TBD - ) - -) - -$(SECTION3 $(LNAME2 decltype, Decltype), - - $(P $(LINK2 $(NDOCS)2007/n2343.pdf, N2343): - The equivalent D construct is $(LINK2 declaration.html#typeof, typeof). - ) - -) - -$(SECTION3 $(LNAME2 sizeof, Extending sizeof), - - $(P $(LINK2 $(NDOCS)2007/n2253.html, N2253): - Using $(LINK2 property.html#sizeof, sizeof) without a $(I this) object: ---- -struct S { - int a; - static int foo() { - return a.sizeof; - } -} - -void test() { - int x = S.a.sizeof; -} ---- - works correctly in D. - ) - -) - -$(SECTION3 $(LNAME2 utf8-literals, UTF-8 Literals), - - $(P $(LINK2 $(NDOCS)2007/n2442.html, N2442): - $(LINK2 lex.html#StringLiteral, Char string literals) - are in UTF-8 format. - ) - -) - -$(SECTION3 $(LNAME2 ucs-in-literals, Universal Character Names in Literals), - - $(P $(LINK2 $(NDOCS)2007/n2170.html, N2170): - All Unicode characters are allowed in - $(LINK2 lex.html#StringLiteral, string literals). - Surrogate pair halves are not allowed unless hex literal notation - is used. - ) - -) - -$(SECTION3 $(LNAME2 defaulted, Defaulted and Deleted Functions), - - $(P $(LINK2 $(NDOCS)2007/n2326.html#delete, N2326): - D alows individual functions to be marked as $(LINK2 attribute.html#disable, disabled). - ) - -) - - -$(SECTION3 $(LNAME2 unions, Unrestricted Unions), - - $(P $(LINK2 $(NDOCS)2008/n2544.pdf, N2544): TBD - ) - -) - -$(SECTION3 $(LNAME2 library, A Multi-threading Library for Standard C++), - - $(P $(LINK2 $(NDOCS)2007/n2447.html, N2447): TBD - ) - -) - -$(SECTION3 $(LNAME2 abandoning, Abandoning a Process), - - $(P $(LINK2 $(NDOCS)2007/n2440.html, N2440): TBD - ) - -) - -$(SECTION3 $(LNAME2 return-types, New function declaration syntax for deduced return types), - - $(P $(LINK2 $(NDOCS)2007/n2445.html, N2445): TBD - ) - -) - -$(SECTION3 $(LNAME2 atomic-signals, Allow atomics use in signal handlers), - - $(P $(LINK2 $(NDOCS)2008/n2547.htm, N2547): TBD - ) - -) - -$(SECTION3 $(LNAME2 local-classes, Making Local Classes more Useful), - - $(P $(LINK2 $(NDOCS)2007/n2402.pdf, N2402): - D has no restrictions on using local classes as template - parameters. - ) - -) - -$(SECTION3 $(LNAME2 initializer-lists, Initializer lists), - - $(P $(LINK2 $(NDOCS)2008/n2531.pdf, N2531): - D has - $(LINK2 struct.html#StructLiteral, struct literals), - $(LINK2 expression.html#ArrayLiteral, array literals), - and $(LINK2 expression.html#AssocArrayLiteral, associative array literals). - ) - -) - -$(SECTION3 $(LNAME2 thread-local-storage, Thread-Local Storage), - - $(P $(LINK2 $(NDOCS)2007/n2280.html, N2280): - Thread-local storage is the default for statics and globals - in D. Thread-global storage is done by using the - $(LINK2 migrate-to-shared.html, $(B shared)) - storage class. - ) - -) - -$(SECTION3 $(LNAME2 member-initializers, Member Initializers), - - $(P $(LINK2 $(NDOCS)2007/n2426.htm, N2426): - D has - $(LINK2 class.html#class-default-initializer, member initializers), - which are called $(I default initializers). - ) - -) - -$(SECTION3 $(LNAME2 concepts, Concepts (unified proposal)), - - $(P $(LINK2 $(NDOCS)2006/n2081.pdf, N2081): - The D equivalent of C++ concepts are $(LINK2 concepts.html, constraints). - (As of $(LINK2 http://www.ddj.com/cpp/218600111, July 2009), - Concepts have been dropped from C++0x.) - ) - - $(TABLE2 Concepts and Constraints, - - $(TR - $(TH Description) - $(TH D Constraints) - $(TH C++0x Concepts) - ) - - $(TR - $(TD Overloading based on concepts/constraints) - $(TD Yes) - $(TD Yes) - ) - - $(TR - $(TD Concepts/constraints on template type parameters) - $(TD Yes) - $(TD Yes) - ) - - $(TR - $(TD Concepts/constraints on template value parameters) - $(TD Yes) - $(TD No) - ) - - $(TR - $(TD Concepts/constraints on template template/alias parameters) - $(TD Yes) - $(TD No) - ) - - $(TR - $(TD Composition and refinement of concepts/constraints) - $(TD Yes) - $(TD Yes) - ) - - $(TR - $(TD Multi-type concepts/constraints) - $(TD Yes) - $(TD Yes) - ) - - $(TR - $(TD Expression of concepts/constraints) - $(TD Done with compile time expressions) - $(TD Done by enumeration of function signatures) - ) - - $(TR - $(TD Axioms) - $(TD Yes (as static asserts and function preconditions)) - $(TD Yes) - ) - - $(TR - $(TD new keywords) - $(TD No) - $(TD Yes: where, concept, concept_map, axiom, late_check) - ) - - $(TR - $(TD Semantic analysis of template bodies) - $(TD Lazy (done at instantiation time)) - $(TD Eager (done at definition time)) - ) - - $(TR - $(TD Template body checked against concept/constraint) - $(TD No) - $(TD Yes) - ) - - $(TR - $(TD Concept maps) - $(TD No (but could be done with proxy objects)) - $(TD Yes) - ) - - $(TR - $(TD All operations on constrained types must be specified in - concept/constraint) - $(TD No) - $(TD Yes) - ) - - $(TR - $(TD Complexity) - $(TD $(CODE if (expression)) added to template grammar) - $(TD quite a bit of new grammar and semantics added) - ) - - - ) - -) - -$(SECTION3 $(LNAME2 for-loop, Proposal for new for-loop), - - $(P $(LINK2 $(NDOCS)2007/n2394.html, N2394): - This is equivalent to the D - $(LINK2 statement.html#ForeachRangeStatement, $(I ForeachRangeStatement)). - ) - -) - -$(SECTION3 $(LNAME2 general-attributes, General Attributes for C++), - - $(P $(LINK2 $(NDOCS)2007/n2418.pdf, N2418): - Vendor specific attributes can be applied to statements - and declarations with - $(LINK2 pragma.html, pragmas). - ) - -) - -$(SECTION3 $(LNAME2 extensible-literals, Extensible Literals), - - $(P $(LINK2 $(NDOCS)2007/n2378.pdf, N2378): - D does not have user extensible literals. - ) - -) - -$(SECTION3 $(LNAME2 dynamic-concurrency, Dynamic initialization and concurrency), - - $(P $(LINK2 $(NDOCS)2008/n2513.html, N2513): TBD - ) - -) - -$(SECTION3 $(LNAME2 garbage-collection, Minimal Support for Garbage Collection and Reachability-Based Leak Detection), - - $(P $(LINK2 $(NDOCS)2008/n2527.html, N2527): - Garbage collection is optional in C++0x, - D $(LINK2 garbage.html, requires it). - The problem with an optional garbage collector is that in order - to write general purpose libraries, one must assume that there is - no garbage collector, therefore none of the productivity enhancing - advantages of it are available. - ) - -) - -$(SECTION3 $(LNAME2 forward-enums, Forward declaration of enumerations), - - $(P $(LINK2 $(NDOCS)2008/n2499.pdf, N2499): - Forward declarations are not necessary in D, as all declarations - are resolved essentially in parallel. - Incomplete $(LINK2 enum.html, enum) types, however, are possible: - ) ---- -enum E : int; ---- - $(P where the member values are hidden from the user. - ) - -) - -) - -Macros: - TITLE=D and C++0x - WIKI=Cpp0x - DOLLAR=$ - NDOCS=http://www.open-std.org/jtc1/sc22/wg21/docs/papers/ - FOO= - - diff --git a/cpp_interface.dd b/cpp_interface.dd deleted file mode 100644 index 2cb6b17a93..0000000000 --- a/cpp_interface.dd +++ /dev/null @@ -1,605 +0,0 @@ -Ddoc - -$(SPEC_S Interfacing to C++, - - $(P - While D is fully capable of - $(DDLINK interfaceToC, Interfacing to C, interfacing to C), - its ability to interface to C++ is much more limited. - There are three ways to do it: - ) - - $(OL - - $(LI Use C++'s ability to create a C interface, and then - use D's ability to - $(DDLINK interfaceToC, Interfacing to C, interface with C) - to access that interface. - ) - - $(LI Use C++'s ability to create a COM interface, and then - use D's ability to - $(DPLLINK COM.html, interface with COM) - to access that interface. - ) - - $(LI Use the limited ability described here to connect - directly to C++ functions and classes. - ) - - ) - -

    The General Idea

    - - $(P Being 100% compatible with C++ means more or less adding - a fully functional C++ compiler front end to D. - Anecdotal evidence suggests that writing such is a minimum - of a 10 man-year project, essentially making a D compiler - with such capability unimplementable. - Other languages looking to hook up to C++ face the same - problem, and the solutions have been: - ) - - $(OL - $(LI Support the COM interface (but that only works for Windows).) - $(LI Laboriously construct a C wrapper around - the C++ code.) - $(LI Use an automated tool such as SWIG to construct a - C wrapper.) - $(LI Reimplement the C++ code in the other language.) - $(LI Give up.) - ) - - $(P D takes a pragmatic approach that assumes a couple - modest accommodations can solve a significant chunk of - the problem: - ) - - $(UL - $(LI matching C++ name mangling conventions) - $(LI matching C++ function calling conventions) - $(LI matching C++ virtual function table layout for single inheritance) - ) - -

    Calling C++ Global Functions From D

    - - $(P Given a C++ function in a C++ source file:) - -$(CPPCODE -#include <iostream> - -using namespace std; - -int foo(int i, int j, int k) { - cout << "i = " << i << endl; - cout << "j = " << j << endl; - cout << "k = " << k << endl; - - return 7; -} -) - - $(P In the corresponding D code, $(CODE foo) - is declared as having C++ linkage and function calling conventions: - ) - ------- -extern (C++) int foo(int i, int j, int k); ------- - - $(P and then it can be called within the D code:) - ------- -extern (C++) int foo(int i, int j, int k); - -void main() { - foo(1,2,3); -} ------- - - $(P Compiling the two files, the first with a C++ compiler, - the second with a D compiler, linking them together, - and then running it yields:) - -$(CONSOLE -i = 1 -j = 2 -k = 3 -) - - $(P There are several things going on here:) - - $(UL - $(LI D understands how C++ function names are "mangled" and the - correct C++ function call/return sequence.) - - $(LI Because modules are not part of C++, each function with - C++ linkage must be globally unique within the program.) - - $(LI There are no __cdecl, __far, __stdcall, __declspec, or other - such nonstandard C++ extensions in D.) - - $(LI There are no volatile type modifiers in D.) - - $(LI Strings are not 0 terminated in D. See "Data Type Compatibility" - for more information about this. However, string literals in D are - 0 terminated.) - - ) - - $(P C++ functions that reside in namespaces cannot be - direcly called from D. - ) - - -

    Calling Global D Functions From C++

    - - $(P To make a D function accessible from C++, give it - C++ linkage:) - ---- -import std.stdio; - -extern (C++) int foo(int i, int j, int k) { - writefln("i = %s", i); - writefln("j = %s", j); - writefln("k = %s", k); - return 1; -} - -extern (C++) void bar(); - -void main() { - bar(); -} ---- - - $(P The C++ end looks like:) - -$(CPPCODE -int foo(int i, int j, int k); - -void bar() { - foo(6, 7, 8); -} -) - - $(P Compiling, linking, and running produces the output:) - -$(CONSOLE -i = 6 -j = 7 -k = 8 -) - - -

    Classes

    - - $(P D classes are singly rooted by Object, and have an - incompatible layout from C++ classes. - D interfaces, however, are very similar to C++ single - inheritance class heirarchies. - So, a D interface with the attribute of $(CODE extern (C++)) - will have a virtual function pointer table (vtbl[]) that - exactly matches C++'s. - A regular D interface has a vtbl[] that differs in that - the first entry in the vtbl[] is a pointer to D's RTTI info, - whereas in C++ the first entry points to the first virtual - function. - ) - -

    Calling C++ Virtual Functions From D

    - - $(P Given C++ source code defining a class like:) - -$(CPPCODE -#include <iostream> - -using namespace std; - -class D { - public: - virtual int bar(int i, int j, int k) - { - cout << "i = " << i << endl; - cout << "j = " << j << endl; - cout << "k = " << k << endl; - return 8; - } -}; - -D *getD() { - D *d = new D(); - return d; -} -) - - $(P We can get at it from D code like:) - ---- -extern (C++) { - interface D { - int bar(int i, int j, int k); - } - - D getD(); -} - -void main() { - D d = getD(); - d.bar(9,10,11); -} ---- - -

    Calling D Virtual Functions From C++

    - - $(P Given D code like:) - ---- -extern (C++) int callE(E); - -extern (C++) interface E { - int bar(int i, int j, int k); -} - -class F : E { - extern (C++) int bar(int i, int j, int k) - { - writefln("i = ", i); - writefln("j = ", j); - writefln("k = ", k); - return 8; - } -} - -void main() { - F f = new F(); - callE(f); -} ---- - - $(P The C++ code to access it looks like:) - -$(CPPCODE -class E { - public: - virtual int bar(int i, int j, int k); -}; - - -int callE(E *e) { - return e->bar(11,12,13); -} -) - - $(P Note:) - - $(UL - $(LI non-virtual functions, and static member functions, - cannot be accessed.) - - $(LI class fields can only be accessed via virtual getter - and setter methods.) - ) - -

    Function Overloading

    - - $(P C++ and D follow different rules for function overloading. - D source code, even when calling $(CODE extern (C++)) functions, - will still follow D overloading rules. - ) - - -

    Storage Allocation

    - - $(P C++ code explicitly manages memory with calls to - $(CODE ::operator new()) and $(CODE ::operator delete()). - D allocates memory using the D garbage collector, - so no explicit delete's are necessary. - D's new and delete are not compatible with C++'s - $(CODE ::operator new) and $(CODE::operator delete). - Attempting to allocate memory with C++ $(CODE ::operator new) - and deallocate it with D's $(CODE delete), or vice versa, will - result in miserable failure. - ) - - $(P D can still explicitly allocate memory using std.c.stdlib.malloc() - and std.c.stdlib.free(), these are useful for connecting to C++ - functions that expect malloc'd buffers, etc. - ) - - $(P If pointers to D garbage collector allocated memory are passed to - C++ functions, it's critical to ensure that that memory will not - be collected by the garbage collector before the C++ function is - done with it. This is accomplished by: - ) - - $(UL - - $(LI Making a copy of the data using std.c.stdlib.malloc() and passing - the copy instead.) - - $(LI Leaving a pointer to it on the stack (as a parameter or - automatic variable), as the garbage collector will scan the stack.) - - $(LI Leaving a pointer to it in the static data segment, as the - garbage collector will scan the static data segment.) - - $(LI Registering the pointer with the garbage collector with the - std.gc.addRoot() or std.gc.addRange() calls.) - - ) - - $(P An interior pointer to the allocated memory block is sufficient - to let the GC - know the object is in use; i.e. it is not necessary to maintain - a pointer to the beginning of the allocated memory. - ) - - $(P The garbage collector does not scan the stacks of threads not - created by the D Thread interface. Nor does it scan the data - segments of other DLL's, etc. - ) - -

    Data Type Compatibility

    - - $(TABLE2 D And C Type Equivalence, - - $(TR - $(TH D type) - $(TH C type) - ) - - $(TR - $(TD $(B void)) - $(TD $(B void)) - ) - - $(TR - $(TD $(B byte)) - $(TD $(B signed char)) - ) - - $(TR - $(TD $(B ubyte)) - $(TD $(B unsigned char)) - ) - - $(TR - $(TD $(B char)) - $(TD $(B char) (chars are unsigned in D)) - ) - - $(TR - $(TD $(B wchar)) - $(TD $(B wchar_t) (when sizeof(wchar_t) is 2)) - ) - - $(TR - $(TD $(B dchar)) - $(TD $(B wchar_t) (when sizeof(wchar_t) is 4)) - ) - - $(TR - $(TD $(B short)) - $(TD $(B short)) - ) - - $(TR - $(TD $(B ushort)) - $(TD $(B unsigned short)) - ) - - $(TR - $(TD $(B int)) - $(TD $(B int)) - ) - - $(TR - $(TD $(B uint)) - $(TD $(B unsigned)) - ) - - $(TR - $(TD $(B long)) - $(TD $(B long long)) - ) - - $(TR - $(TD $(B ulong)) - $(TD $(B unsigned long long)) - ) - - $(TR - $(TD $(B float)) - $(TD $(B float)) - ) - - $(TR - $(TD $(B double)) - $(TD $(B double)) - ) - - $(TR - $(TD $(B real)) - $(TD $(B long double)) - ) - - $(TR - $(TD $(B ifloat)) - $(TD no equivalent) - ) - - $(TR - $(TD $(B idouble)) - $(TD no equivalent) - ) - - $(TR - $(TD $(B ireal)) - $(TD no equivalent) - ) - - $(TR - $(TD $(B cfloat)) - $(TD no equivalent) - ) - - $(TR - $(TD $(B cdouble)) - $(TD no equivalent) - ) - - $(TR - $(TD $(B creal)) - $(TD no equivalent) - ) - - $(TR - $(TD $(B struct)) - $(TD $(B struct)) - ) - - $(TR - $(TD $(B union)) - $(TD $(B union)) - ) - - $(TR - $(TD $(B enum)) - $(TD $(B enum)) - ) - - $(TR - $(TD $(B class)) - $(TD no equivalent) - ) - - $(TR - $(TD $(I type)$(B *)) - $(TD $(I type) $(B *)) - ) - - $(TR - $(TD no equivalent) - $(TD $(I type) $(B &)) - ) - - $(TR - $(TD $(I type)$(B [)$(I dim)$(B ])) - $(TD $(I type)$(B [)$(I dim)$(B ])) - ) - - $(TR - $(TD $(I type)$(B [)$(I dim)$(B ]*)) - $(TD $(I type)$(B (*)[)$(I dim)$(B ])) - ) - - $(TR - $(TD $(I type)$(B [])) - $(TD no equivalent) - ) - - $(TR - $(TD $(I type)$(B [)$(I type)$(B ])) - $(TD no equivalent) - ) - - $(TR - $(TD $(I type) $(B function)$(B $(LPAREN))$(I parameters)$(B $(RPAREN))) - $(TD $(I type)$(B (*))$(B $(LPAREN))$(I parameters)$(B $(RPAREN))) - ) - - $(TR - $(TD $(I type) $(B delegate)$(B $(LPAREN))$(I parameters)$(B $(RPAREN))) - $(TD no equivalent) - ) - - ) - - $(P These equivalents hold for most 32 bit C++ compilers. - The C++ standard - does not pin down the sizes of the types, so some care is needed. - ) - -

    Structs and Unions

    - - $(P D structs and unions are analogous to C's. - ) - - $(P C code often adjusts the alignment and packing of struct members - with a command line switch or with various implementation specific - #pragma's. D supports explicit alignment attributes that correspond - to the C compiler's rules. Check what alignment the C code is using, - and explicitly set it for the D struct declaration. - ) - - $(P D does not support bit fields. If needed, they can be emulated - with shift and mask operations. - $(DPLLINK htod.html, htod) will convert bit fields to inline functions that - do the right shift and masks. - ) - -

    Object Construction and Destruction

    - - $(P Similarly to storage allocation and deallocation, objects - constructed in D code should be destructed in D, - and objects constructed - in C++ should be destructed in C++ code. - ) - -

    Special Member Functions

    - - $(P D cannot call C++ special member functions, and vice versa. - These include constructors, destructors, conversion operators, - operator overloading, and allocators. - ) - -

    Runtime Type Identification

    - - $(P D runtime type identification - uses completely different techniques than C++. - The two are incompatible.) - -

    C++ Class Objects by Value

    - - $(P D can access POD (Plain Old Data) C++ structs, and it can - access C++ class virtual functions by reference. - It cannot access C++ classes by value. - ) - -

    C++ Templates

    - - $(P D templates have little in common with C++ templates, - and it is very unlikely that any sort of reasonable method - could be found to express C++ templates in a link-compatible - way with D. - ) - - $(P This means that the C++ STL, and C++ Boost, likely will - never be accessible from D. - ) - -

    Exception Handling

    - - $(P D and C++ exception handling are completely different. - Throwing exceptions across the boundaries between D - and C++ code will likely not work. - ) - -

    Future Developments

    - - $(P How the upcoming C++0x standard will affect this is not - known.) - - $(P Over time, more aspects of the C++ ABI may be accessible - directly from D.) - -) - -Macros: - TITLE=Interfacing to C++ - WIKI=InterfaceToCPP - - - CATEGORY_SPEC=$0 diff --git a/cppdbc.dd b/cppdbc.dd deleted file mode 100644 index e1d1d81aea..0000000000 --- a/cppdbc.dd +++ /dev/null @@ -1,503 +0,0 @@ -Ddoc - -$(COMMUNITY D's Contract Programming vs C++'s, - - Many people have written me saying that D's Contract Programming - (DbC) does not add anything that C++ does not already support. - They go on to illustrate their point with a technique for doing DbC in - C++. -

    - - It makes sense to review what DbC is, how it is done in D, - and stack that up with what each of the various C++ DbC techniques - can do. -

    - - Digital Mars C++ adds - extensions to C++ - to support DbC, but they are not covered here because they are not - part of standard C++ and are not supported by any other C++ compiler. - -

    Contract Programming in D

    - - This is more fully documented in the D - Contract Programming document. - To sum up, DbC in D has the following characteristics: - - $(OL - - $(LI The $(I assert) is the basic contract. - ) - - $(LI When an assert contract fails, it throws an exception. - Such exceptions can be caught and handled, or allowed to - terminate the program. - ) - - $(LI Classes can have $(I class invariants) which are - checked upon entry and exit of each public class member function, - the exit of each constructor, and the entry of the destructor. - ) - - $(LI Assert contracts on object references check the class - invariant for that object. - ) - - $(LI Class invariants are inherited, that means that a derived - class invariant will implicitly call the base class invariant. - ) - - $(LI Functions can have $(I preconditions) and $(I postconditions). - ) - - $(LI For member functions in a class inheritance hierarchy, the - precondition of a derived class function are OR'd together - with the preconditions of all the functions it overrides. - The postconditions are AND'd together. - ) - - $(LI By throwing a compiler switch, DbC code can be enabled - or can be withdrawn from the compiled code. - ) - - $(LI Code works semantically the same with or without DbC - checking enabled. - ) - - ) - -

    Contract Programming in C++

    - -

    The $(D assert) Macro

    - - C++ does have the basic $(D assert) macro, which tests its argument - and if it fails, aborts the program. $(D assert) can be turned - on and off with the $(D NDEBUG) macro. -

    - - $(D assert) does not know anything about class invariants, - and does not throw an exception when it fails. It just aborts - the program after writing a message. $(D assert) relies on - a macro text preprocessor to work. -

    - - $(D assert) is where explicit support for DbC in Standard C++ - begins and ends. - -

    Class Invariants

    - - Consider a class invariant in D: - ----------- -class A -{ - $(B invariant)() { ...contracts... } - - this() { ... } // constructor - ~this() { ... } // destructor - - void foo() { ... } // public member function -} - -class B : A -{ - $(B invariant)() { ...contracts... } - ... -} ----------- - - To accomplish the equivalent in C++ (thanks to Bob Bell for providing - this): - -$(CCODE -template -inline void check_invariant(T& iX) -{ -#ifdef DBC - iX.invariant(); -#endif -} - -// A.h: - -class A { - public: -#ifdef DBG - virtual void invariant() { ...contracts... } -#endif - void foo(); -}; - -// A.cpp: - -void A::foo() -{ - check_invariant(*this); - ... - check_invariant(*this); -} - -// B.h: - -#include "A.h" - -class B : public A { - public: -#ifdef DBG - virtual void invariant() - { ...contracts... - A::invariant(); - } -#endif - void bar(); -}; - -// B.cpp: - -void B::barG() -{ - check_invariant(*this); - ... - check_invariant(*this); -} -) - - There's an additional complication with $(D A::foo()). Upon every - normal exit from the function, the $(D invariant()) should be - called. - This means that code that looks like: - -$(CCODE -int A::foo() -{ - ... - if (...) - return bar(); - return 3; -} -) - - would need to be written as: - -$(CCODE -int A::foo() -{ - int result; - check_invariant(*this); - ... - if (...) - { - result = bar(); - check_invariant(*this); - return result; - } - check_invariant(*this); - return 3; -} -) - - Or recode the function so it has a single exit point. - One possibility to mitigate this is to use RAII techniques: - -$(CCODE -int A::foo() -{ -#if DBC - struct Sentry { - Sentry(A& iA) : mA(iA) { check_invariants(iA); } - ~Sentry() { check_invariants(mA); } - A& mA; - } sentry(*this); -#endif - ... - if (...) - return bar(); - return 3; -} -) - - The #if DBC is still there because some compilers may not - optimize the whole thing away if check_invariants compiles to nothing. - -

    Preconditions and Postconditions

    - - Consider the following in D: - ----------- -void foo() - in { ...preconditions... } - out { ...postconditions... } - body - { - ...implementation... - } ----------- - - This is nicely handled in C++ with the nested Sentry struct: - -$(CCODE -void foo() -{ - struct Sentry - { Sentry() { ...preconditions... } - ~Sentry() { ...postconditions... } - } sentry; - ...implementation... -} -) - - If the preconditions and postconditions consist of nothing - more than $(D assert) macros, the whole doesn't need to - be wrapped in a $(D #ifdef) pair, since a good C++ compiler will - optimize the whole thing away if the $(D assert)s are turned off. -

    - - But suppose $(D foo()) sorts an array, and the postcondition needs - to walk the array and verify that it really is sorted. Now - the shebang needs to be wrapped in $(D #ifdef): - -$(CCODE -void foo() -{ -#ifdef DBC - struct Sentry - { Sentry() { ...preconditions... } - ~Sentry() { ...postconditions... } - } sentry; -#endif - ...implementation... -} -) - - (One can make use of the C++ rule that templates are only - instantiated when used can be used to avoid the $(D #ifdef), by - putting the conditions into a template function referenced - by the $(D assert).) -

    - - Let's add a return value to $(D foo()) that needs to be checked in - the postconditions. In D: - ----------- -int foo() - in { ...preconditions... } - out (result) { ...postconditions... } - body - { - ...implementation... - if (...) - return bar(); - return 3; - } ----------- - - In C++: - -$(CCODE -int foo() -{ -#ifdef DBC - struct Sentry - { int result; - Sentry() { ...preconditions... } - ~Sentry() { ...postconditions... } - } sentry; -#endif - ...implementation... - if (...) - { int i = bar(); -#ifdef DBC - sentry.result = i; -#endif - return i; - } -#ifdef DBC - sentry.result = 3; -#endif - return 3; -} -) - - Now add a couple parameters to $(D foo()). In D: - ----------- -int foo(int a, int b) - in { ...preconditions... } - out (result) { ...postconditions... } - body - { - ...implementation... - if (...) - return bar(); - return 3; - } ----------- - - In C++: - -$(CCODE -int foo(int a, int b) -{ -#ifdef DBC - struct Sentry - { int a, b; - int result; - Sentry(int a, int b) - { this->a = a; - this->b = b; - ...preconditions... - } - ~Sentry() { ...postconditions... } - } sentry(a,b); -#endif - ...implementation... - if (...) - { int i = bar(); -#ifdef DBC - sentry.result = i; -#endif - return i; - } -#ifdef DBC - sentry.result = 3; -#endif - return 3; -} -) - -

    Preconditions and Postconditions for Member Functions

    - - Consider the use of preconditions and postconditions for a - polymorphic function in D: - ----------- -class A -{ - void foo() - in { ...Apreconditions... } - out { ...Apostconditions... } - body - { - ...implementation... - } -} - -class B : A -{ - void foo() - in { ...Bpreconditions... } - out { ...Bpostconditions... } - body - { - ...implementation... - } -} ----------- - - The semantics for a call to $(D B.foo()) are: - - $(UL - $(LI Either Apreconditions or Bpreconditions must be satisfied.) - $(LI Both Apostconditions and Bpostconditions must be satisfied.) - ) - - Let's get this to work in C++: - -$(CCODE -class A -{ -protected: - #if DBC - int foo_preconditions() { ...Apreconditions... } - void foo_postconditions() { ...Apostconditions... } - #else - int foo_preconditions() { return 1; } - void foo_postconditions() { } - #endif - - void foo_internal() - { - ...implementation... - } - -public: - virtual void foo() - { - foo_preconditions(); - foo_internal(); - foo_postconditions(); - } -}; - -class B : A -{ -protected: - #if DBC - int foo_preconditions() { ...Bpreconditions... } - void foo_postconditions() { ...Bpostconditions... } - #else - int foo_preconditions() { return 1; } - void foo_postconditions() { } - #endif - - void foo_internal() - { - ...implementation... - } - -public: - virtual void foo() - { - assert(foo_preconditions() || A::foo_preconditions()); - foo_internal(); - A::foo_postconditions(); - foo_postconditions(); - } -}; -) - - Something interesting has happened here. The preconditions can - no longer be done using $(D assert), since the results need - to be OR'd together. I'll leave as a reader exercise adding - in a class invariant, function return values for $(D foo()), - and parameters - for $(D foo()). - -

    Conclusion

    - - These C++ techniques can work up to a point. But, aside from - $(D assert), they are not standardized and so will vary from - project to project. Furthermore, they require much tedious - adhesion to a particular convention, and add significant clutter - to the code. Perhaps that's why it's rarely seen in practice. -

    - - By adding support for DbC into the language, D offers an easy - way to use DbC and get it right. Being in the language standardizes - the way it will be used from project to project. - -

    References

    - - Chapter C.11 introduces the theory and rationale of - Contract Programming in - - Object-Oriented Software Construction -
    - Bertrand Meyer, Prentice Hall -

    - - Chapters 24.3.7.1 to 24.3.7.3 discuss Contract Programming in C++ in - - The C++ Programming Language Special Edition -
    - Bjarne Stroustrup, Addison-Wesley -

    - -) - -Macros: - TITLE=D's Contract Programming vs C++'s - WIKI=CppDbc - - - CATEGORY_OVERVIEW=$0 diff --git a/cppstrings.dd b/cppstrings.dd deleted file mode 100644 index 17b1aae2e2..0000000000 --- a/cppstrings.dd +++ /dev/null @@ -1,583 +0,0 @@ -Ddoc - -$(COMMUNITY D Strings vs C++ Strings, - - -Why have strings built-in to the core language of D rather than entirely in -a library as in C++ Strings? What's the point? Where's the improvement? - -

    Concatenation Operator

    - -$(P C++ Strings are stuck with overloading existing operators. The - obvious choice for concatenation is += and +. - But someone just looking at the code will see + and think "addition". - He'll have to look up the types (and types are frequently buried - behind multiple typedef's) to see that it's a string type, and - it's not adding strings but concatenating them. -) -$(P Additionally, if one has an array of floats, is $(SINGLEQUOTE +) overloaded to - be the same as a vector addition, or an array concatenation? -) -$(P In D, these problems are avoided by introducing a new binary - operator ~ as the concatenation operator. It works with - arrays (of which strings are a subset). ~= is the corresponding - append operator. ~ on arrays of floats would concatenate them, - + would imply a vector add. Adding a new operator makes it possible - for orthogonality and consistency in the treatment of arrays. - (In D, strings are simply arrays of characters, not a special - type.) -) - -

    Interoperability With C String Syntax

    - -$(P Overloading of operators only really works if one of the operands - is overloadable. So the C++ string class cannot consistently - handle arbitrary expressions containing strings. Consider: -) - -$(CCODE -const char abc[5] = "world"; -string str = "hello" + abc; -) - -$(P That isn't going to work. But it does work when the core language - knows about strings: -) - -$(CCODE -const char[5] abc = "world"; -char[] str = "hello" ~ abc; -) - -

    Consistency With C String Syntax

    - -$(P - There are three ways to find the length of a string in C++: -) - -$(CCODE -const char abc[] = "world"; : sizeof(abc)/sizeof(abc[0])-1 - : strlen(abc) -string str; : str.length() -) - -$(P - That kind of inconsistency makes it hard to write generic templates. - Consider D: -) - ------------------------ -char[5] abc = "world"; : abc.length -char[] str : str.length ------------------------ - -

    Checking For Empty Strings

    - -$(P - C++ strings use a function to determine if a string is empty: -) - -$(CCODE -string str; -if (str.empty()) - // string is empty -) - -$(P - In D, an empty string has zero length: -) - ------------------------ -char[] str; -if (!str.length) - // string is empty ------------------------ - - -

    Resizing Existing String

    - -$(P - C++ handles this with the resize() member function: -) - -$(CCODE -string str; -str.resize(newsize); -) - -$(P - D takes advantage of knowing that str is an array, and - so resizing it is just changing the length property: -) - ------------------------ -char[] str; -str.length = newsize; ------------------------ - -

    Slicing a String

    - -$(P - C++ slices an existing string using a special constructor: -) - -$(CCODE -string s1 = "hello world"; -string s2(s1, 6, 5); // s2 is "world" -) - -$(P - D has the array slice syntax, not possible with C++: -) - ------------------------ -string s1 = "hello world"; -string s2 = s1[6 .. 11]; // s2 is "world" ------------------------ - -$(P - Slicing, of course, works with any array in D, not just strings. -) - -

    Copying a String

    - -$(P - C++ copies strings with the replace function: -) - -$(CCODE -string s1 = "hello world"; -string s2 = "goodbye "; -s2.replace(8, 5, s1, 6, 5); // s2 is "goodbye world" -) - -$(P - D uses the slice syntax as an lvalue: -) - ------------------------ -char[] s1 = "hello world".dup; -char[] s2 = "goodbye ".dup; -s2[8..13] = s1[6..11]; // s2 is "goodbye world" ------------------------ - - $(P The $(CODE .dup) is needed because string literals are - read-only in D, the $(CODE .dup) will create a copy - that is writable. - ) - - -

    Conversions to C Strings

    - -$(P - This is needed for compatibility with C API's. In C++, this - uses the c_str() member function: -) - -$(CCODE -void foo(const char *); -string s1; -foo(s1.c_str()); -) - -$(P - In D, strings can be converted to char* using the .ptr property: -) - ------------------------ -void foo(char*); -char[] s1; -foo(s1.ptr); ------------------------ - $(P although for this to work where $(D foo) expects a 0 terminated - string, $(D s1) must have a terminating 0. Alternatively, the - function $(D std.string.toStringz) will ensure it:) - ------------------------ -void foo(char*); -char[] s1; -foo(std.string.$(B toStringz)(s1)); ------------------------ - - -

    Array Bounds Checking

    - -$(P - In C++, string array bounds checking for [] is not done. - In D, array bounds checking is on by default and it can be turned off - with a compiler switch after the program is debugged. -) - -

    String Switch Statements

    - -$(P - Are not possible in C++, nor is there any way to add them - by adding more to the library. In D, they take the obvious - syntactical forms: -) - ------------------------ -switch (str) -{ - case "hello": - case "world": - ... -} ------------------------ - -$(P - where str can be any of literal "string"s, fixed string arrays - like char[10], or dynamic strings like char[]. A quality implementation - can, of course, explore many strategies of efficiently implementing - this based on the contents of the case strings. -) - -

    Filling a String

    - -$(P - In C++, this is done with the replace() member function: -) - -$(CCODE -string str = "hello"; -str.replace(1,2,2,'?'); // str is "h??lo" -) - -$(P - In D, use the array slicing syntax in the natural manner: -) - ------------------------ -char[5] str = "hello"; -str[1..3] = '?'; // str is "h??lo" ------------------------ - -

    Value vs Reference

    - -$(P - C++ strings, as implemented by STLport, are by value and are - 0-terminated. [The latter is an implementation choice, but - STLport seems to be the most popular implementation.] - This, coupled with no garbage collection, has - some consequences. First of all, any string created must make - its own copy of the string data. The $(SINGLEQUOTE owner) of the string - data must be kept track of, because when the owner is deleted - all references become invalid. If one tries to avoid the - dangling reference problem by treating strings as value types, - there will be a lot of overhead of memory allocation, - data copying, and memory deallocation. Next, the 0-termination - implies that strings cannot refer to other strings. String - data in the data segment, stack, etc., cannot - be referred to. -) - -$(P - D strings are reference types, and the memory is garbage collected. - This means that only references need to be copied, not the - string data. D strings can refer to data in the static data - segment, data on the stack, data inside other strings, objects, - file buffers, etc. There's no need to keep track of the $(SINGLEQUOTE owner) - of the string data. -) - -$(P - The obvious question is if multiple D strings refer to the same - string data, what happens if the data is modified? All the - references will now point to the modified data. This can have - its own consequences, which can be avoided if the copy-on-write - convention is followed. All copy-on-write is is that if - a string is written to, an actual copy of the string data is made - first. -) - -$(P - The result of D strings being reference only and garbage collected - is that code that does a lot of string manipulating, such as - an lzw compressor, can be a lot more efficient in terms of both - memory consumption and speed. -) - -

    Benchmark

    - -$(P - Let's take a look at a small utility, wordcount, that counts up - the frequency of each word in a text file. In D, it looks like this: -) - ------------------------ -import std.file; -import std.stdio; - -int main (char[][] args) -{ - int w_total; - int l_total; - int c_total; - int[char[]] dictionary; - - writefln(" lines words bytes file"); - for (int i = 1; i < args.length; ++i) - { - char[] input; - int w_cnt, l_cnt, c_cnt; - int inword; - int wstart; - - input = cast(char[])std.file.read(args[i]); - - for (int j = 0; j < input.length; j++) - { char c; - - c = input[j]; - if (c == '\n') - ++l_cnt; - if (c >= '0' && c <= '9') - { - } - else if (c >= 'a' && c <= 'z' || - c >= 'A' && c <= 'Z') - { - if (!inword) - { - wstart = j; - inword = 1; - ++w_cnt; - } - } - else if (inword) - { char[] word = input[wstart .. j]; - - dictionary[word]++; - inword = 0; - } - ++c_cnt; - } - if (inword) - { char[] w = input[wstart .. input.length]; - dictionary[w]++; - } - writefln("%8s%8s%8s %s", l_cnt, w_cnt, c_cnt, args[i]); - l_total += l_cnt; - w_total += w_cnt; - c_total += c_cnt; - } - - if (args.length > 2) - { - writefln("--------------------------------------%8s%8s%8s total", - l_total, w_total, c_total); - } - - writefln("--------------------------------------"); - - foreach (char[] word1; dictionary.keys.sort) - { - writefln("%3d %s", dictionary[word1], word1); - } - return 0; -} ------------------------ - - $(P (An $(LINK2 wc.html, alternate implementation) that - uses buffered file I/O to handle larger files.)) - - $(P - Two people have written C++ implementations using the C++ standard - template library, - wccpp1 - and - $(LINK2 #wccpp2, wccpp2). - The input file - $(LINK2 http://www.gutenberg.org/files/11/old/alice30.txt, alice30.txt) - is the text of "Alice in Wonderland." - The D compiler, - dmd, - and the C++ compiler, - dmc, - share the same - optimizer and code generator, which provides a more apples to - apples comparison of the efficiency of the semantics of the languages - rather than the optimization and code generator sophistication. - Tests were run on a Win XP machine. dmc uses STLport for the template - implementation. - ) - - $(TABLE1 - $(TR - $(TH Program) - $(TH Compile) - $(TH Compile Time) - $(TH Run) - $(TH Run Time) - ) - $(TR - $(TD D wc) - $(TD dmd wc -O -release) - $(TD 0.0719) - $(TD wc alice30.txt >log) - $(TD 0.0326) - ) - $(TR - $(TD C++ wccpp1) - $(TD dmc wccpp1 -o -I\dm\stlport\stlport) - $(TD 2.1917) - $(TD wccpp1 alice30.txt >log) - $(TD 0.0944) - ) - $(TR - $(TD C++ wccpp2) - $(TD dmc wccpp2 -o -I\dm\stlport\stlport) - $(TD 2.0463) - $(TD wccpp2 alice30.txt >log) - $(TD 0.1012) - ) - ) - - $(P - The following tests were run on linux, again comparing a D compiler ($(B gdc)) - and a C++ compiler ($(B g++)) that share a common optimizer and - code generator. The system is Pentium III 800MHz running RedHat Linux 8.0 - and gcc 3.4.2. - The Digital Mars D compiler for linux ($(B dmd)) - is included for comparison. - ) - - - $(TABLE1 - $(TR - $(TH Program) - $(TH Compile) - $(TH Compile Time) - $(TH Run) - $(TH Run Time) - ) - $(TR - $(TD D wc) - $(TD gdc -O2 -frelease -o wc wc.d) - $(TD 0.326) - $(TD wc alice30.txt > /dev/null) - $(TD 0.041) - ) - $(TR - $(TD D wc) - $(TD dmd wc -O -release) - $(TD 0.235) - $(TD wc alice30.txt > /dev/null) - $(TD 0.041) - ) - $(TR - $(TD C++ wccpp1) - $(TD g++ -O2 -o wccpp1 wccpp1.cc) - $(TD 2.874) - $(TD wccpp1 alice30.txt > /dev/null) - $(TD 0.086) - ) - $(TR - $(TD C++ wccpp2) - $(TD g++ -O2 -o wccpp2 wccpp2.cc) - $(TD 2.886) - $(TD wccpp2 alice30.txt > /dev/null) - $(TD 0.095) - ) - ) - - $(P - These tests compare gdc with g++ on a PowerMac G5 2x2.0GHz - running MacOS X 10.3.5 and gcc 3.4.2. (Timings are a little - less accurate.) - ) - - $(TABLE1 - $(TR - $(TH Program) - $(TH Compile) - $(TH Compile Time) - $(TH Run) - $(TH Run Time) - ) - $(TR - $(TD D wc) - $(TD gdc -O2 -frelease -o wc wc.d) - $(TD 0.28) - $(TD wc alice30.txt > /dev/null) - $(TD 0.03) - ) - $(TR - $(TD C++ wccpp1) - $(TD g++ -O2 -o wccpp1 wccpp1.cc) - $(TD 1.90) - $(TD wccpp1 alice30.txt > /dev/null) - $(TD 0.07) - ) - $(TR - $(TD C++ wccpp2) - $(TD g++ -O2 -o wccpp2 wccpp2.cc) - $(TD 1.88) - $(TD wccpp2 alice30.txt > /dev/null) - $(TD 0.08) - ) - ) -
    -

    wccpp2 by Allan Odgaard

    - -$(CCODE -#include <algorithm> -#include <cstdio> -#include <fstream> -#include <iterator> -#include <map> -#include <vector> - -bool isWordStartChar (char c) { return isalpha(c); } -bool isWordEndChar (char c) { return !isalnum(c); } - -int main (int argc, char const* argv[]) -{ - using namespace std; - printf("Lines Words Bytes File:\n"); - - map<string, int> dict; - int tLines = 0, tWords = 0, tBytes = 0; - for(int i = 1; i < argc; i++) - { - ifstream file(argv[i]); - istreambuf_iterator<char> from(file.rdbuf()), to; - vector<char> v(from, to); - vector<char>::iterator first = v.begin(), last = v.end(), bow, eow; - - int numLines = count(first, last, '\n'); - int numWords = 0; - int numBytes = last - first; - - for(eow = first; eow != last; ) - { - bow = find_if(eow, last, isWordStartChar); - eow = find_if(bow, last, isWordEndChar); - if(bow != eow) - ++dict[string(bow, eow)], ++numWords; - } - - printf("%5d %5d %5d %s\n", numLines, numWords, numBytes, argv[i]); - - tLines += numLines; - tWords += numWords; - tBytes += numBytes; - } - - if(argc > 2) - printf("-----------------------\n%5d %5d %5d\n", tLines, tWords, tBytes); - printf("-----------------------\n\n"); - - for(map<string, int>::const_iterator it = dict.begin(); it != dict.end(); ++it) - printf("%5d %s\n", it->second, it->first.c_str()); - - return 0; -} -) - -) - -Macros: - TITLE=D Strings vs C++ Strings - WIKI=CPPstrings - CATEGORY_OVERVIEW=$0 diff --git a/cpptod.dd b/cpptod.dd deleted file mode 100644 index 0bafe9fed0..0000000000 --- a/cpptod.dd +++ /dev/null @@ -1,818 +0,0 @@ -Ddoc - -$(COMMUNITY Programming in D for C++ Programmers, - - - -Every experienced C++ programmer accumulates a series of idioms and techniques -which become second nature. Sometimes, when learning a new language, those -idioms can be so comfortable it's hard to see how to do the equivalent in the -new language. So here's a collection of common C++ techniques, and how to do the -corresponding task in D. -

    - -See also: Programming in D for C Programmers - -$(UL - $(LI $(LINK2 #constructors, Defining Constructors)) - $(LI $(LINK2 #baseclass, Base class initialization)) - $(LI $(LINK2 #structcmp, Comparing structs)) - $(LI $(LINK2 #typedefs, Creating a new typedef'd type)) - $(LI $(LINK2 #friends, Friends)) - $(LI $(LINK2 #operatoroverloading, Operator overloading)) - $(LI $(LINK2 #usingdeclaration, Namespace using declarations)) - $(LI $(LINK2 #raii, RAII (Resource Acquisition Is Initialization))) - $(LI $(LINK2 #properties, Properties)) - $(LI $(LINK2 #recursivetemplates, Recursive Templates)) - $(LI $(LINK2 #metatemplates, Meta Templates)) - $(LI $(LINK2 #typetraits, Type Traits)) -) - - -


    - -

    Defining constructors

    - -

    The C++ Way

    - - Constructors have the same name as the class: - -$(CPPCODE -class Foo -{ - Foo(int x); -}; -) - -

    The D Way

    - - Constructors are defined with the this keyword: - ------- -class Foo -{ - this(int x) { } -} ------- - - which reflects how they are used in D. - -
    -

    Base class initialization

    - -

    The C++ Way

    - - Base constructors are called using the base initializer syntax. - -$(CPPCODE -class A { A() {... } }; -class B : A -{ - B(int x) - : A() // call base constructor - { ... - } -};) - -

    The D Way

    - - The base class constructor is called with the super syntax: - ------- -class A { this() { ... } } -class B : A -{ - this(int x) - { ... - super(); // call base constructor - ... - } -} ------- - - It's superior to C++ in that the base constructor call can be flexibly placed anywhere in the derived - constructor. D can also have one constructor call another one: - ------- -class A -{ int a; - int b; - this() { a = 7; b = foo(); } - this(int x) - { - this(); - a = x; - } -} ------- - - Members can also be initialized to constants before the constructor is ever called, so the above example is - equivalently written as: - ------- -class A -{ int a = 7; - int b; - this() { b = foo(); } - this(int x) - { - this(); - a = x; - } -} ------- - -
    -

    Comparing structs

    - -

    The C++ Way

    - - While C++ defines struct assignment in a simple, convenient manner: - -$(CPPCODE -struct A x, y; -... -x = y; -) - - it does not for struct comparisons. Hence, to compare two struct - instances for equality: - -$(CPPCODE -#include <string.h> - -struct A x, y; - -inline bool operator==(const A& x, const A& y) -{ - return (memcmp(&x, &y, sizeof(struct A)) == 0); -} -... -if (x == y) - ... -) - - Note that the operator overload must be done for every struct - needing to be compared, and the implementation of that overloaded - operator is free of any language help with type checking. - The C++ way has an additional problem in that just inspecting the - (x == y) does not give a clue what is actually happening, you have - to go and find the particular overloaded operator==() that applies - to verify what it really does. -

    - - There's a nasty bug lurking in the memcmp() implementation of operator==(). - The layout of a struct, due to alignment, can have $(SINGLEQUOTE holes) in it. - C++ does not guarantee those holes are assigned any values, and so - two different struct instances can have the same value for each member, - but compare different because the holes contain different garbage. -

    - - To address this, the operator==() can be implemented to do a memberwise - compare. Unfortunately, this is unreliable because (1) if a member is added - to the struct definition one may forget to add it to operator==(), and - (2) floating point nan values compare unequal even if their bit patterns - match. -

    - - There just is no robust solution in C++. - -

    The D Way

    - - D does it the obvious, straightforward way: - ------- -A x, y; -... -if (x == y) - ... ------- - -
    -

    Creating a new typedef'd type

    - -

    The C++ Way

    - - Typedef's in C++ are weak, that is, they really do not introduce - a new type. The compiler doesn't distinguish between a typedef - and its underlying type. - -$(CPPCODE -#define HANDLE_INIT ((Handle)(-1)) -typedef void *Handle; -void foo(void *); -void bar(Handle); - -Handle h = HANDLE_INIT; -foo(h); // coding bug not caught -bar(h); // ok -) - - The C++ solution is to create a dummy struct whose sole - purpose is to get type checking and overloading on the new type. - -$(CPPCODE -#define HANDLE_INIT ((void *)(-1)) -struct Handle -{ void *ptr; - - // default initializer - Handle() { ptr = HANDLE_INIT; } - - Handle(int i) { ptr = (void *)i; } - - // conversion to underlying type - operator void*() { return ptr; } -}; -void bar(Handle); - -Handle h; -bar(h); -h = func(); -if (h != HANDLE_INIT) - ... -) - -

    The D Way

    - - No need for idiomatic constructions like the above. Just write: - ------- -typedef void* Handle = cast(void*)-1; -void bar(Handle); - -Handle h; -bar(h); -h = func(); -if (h != Handle.init) - ... ------- - - Note how a default initializer can be supplied for the typedef as - a value of the underlying type. - -
    -

    Friends

    - -

    The C++ Way

    - - Sometimes two classes are tightly related but not by inheritance, - but need to access each other's private members. This is done - using $(D friend) declarations: - -$(CPPCODE -class A -{ - private: - int a; - - public: - int foo(B *j); - friend class B; - friend int abc(A *); -}; - -class B -{ - private: - int b; - - public: - int bar(A *j); - friend class A; -}; - -int A::foo(B *j) { return j->b; } -int B::bar(A *j) { return j->a; } - -int abc(A *p) { return p->a; } -) - -

    The D Way

    - - In D, friend access is implicit in being a member of the same - module. It makes sense that tightly related classes should be - in the same module, so implicitly granting friend access to - other module members solves the problem neatly: - ------- -module X; - -class A -{ - private: - static int a; - - public: - int foo(B j) { return j.b; } -} - -class B -{ - private: - static int b; - - public: - int bar(A j) { return j.a; } -} - -int abc(A p) { return p.a; } ------- - - The $(D private) attribute prevents other modules from - accessing the members. - -
    -

    Operator overloading

    - -

    The C++ Way

    - - Given a struct that creates a new arithmetic data type, - it's convenient to overload the comparison operators so - it can be compared against integers: - -$(CPPCODE -struct A -{ - int operator < (int i); - int operator <= (int i); - int operator > (int i); - int operator >= (int i); -}; - -int operator < (int i, A &a) { return a > i; } -int operator <= (int i, A &a) { return a >= i; } -int operator > (int i, A &a) { return a < i; } -int operator >= (int i, A &a) { return a <= i; } -) - - A total of 8 functions are necessary. - -

    The D Way

    - - D recognizes that the comparison operators are all fundamentally - related to each other. So only one function is necessary: - ------- -struct A -{ - int opCmp(int i); -} ------- - - The compiler automatically interprets all the - <, <=, > and >= - operators in terms of the $(D cmp) function, as well - as handling the cases where the left operand is not an - object reference. -

    - - Similar sensible rules hold for other operator overloads, - making using operator overloading in D much less tedious and less - error prone. Far less code needs to be written to accomplish - the same effect. - -


    -

    Namespace using declarations

    - -

    The C++ Way

    - - A $(I using-declaration) in C++ is used to bring a name from - a namespace scope into the current scope: - -$(CPPCODE -namespace foo -{ - int x; -} -using foo::x; -) - -

    The D Way

    - - D uses modules instead of namespaces and #include files, and - alias declarations take the place of using declarations: - ------- -/** Module foo.d **/ -module foo; -int x; - -/** Another module **/ -import foo; -alias foo.x x; ------- - - Alias is a much more flexible than the single purpose using - declaration. Alias can be used to rename symbols, refer to - template members, refer to nested class types, etc. - -
    -

    RAII (Resource Acquisition Is Initialization)

    - -

    The C++ Way

    - - In C++, resources like memory, etc., all need to be handled - explicitly. Since destructors automatically get called when - leaving a scope, RAII is implemented by putting the resource - release code into the destructor: - -$(CPPCODE -class File -{ Handle *h; - - ~File() - { - h->release(); - } -}; -) - -

    The D Way

    - - The bulk of resource release problems are simply keeping track - of and freeing memory. This is handled automatically in D by - the garbage collector. The second common resources used are semaphores - and locks, handled automatically with D's $(D synchronized) - declarations and statements. -

    - - The few RAII issues left are handled by $(I scope) classes. - Scope classes get their destructors run when they go out of scope. - ------- -scope class File -{ Handle h; - - ~this() - { - h.release(); - } -} - -void test() -{ - if (...) - { scope f = new File(); - ... - } // f.~this() gets run at closing brace, even if - // scope was exited via a thrown exception -} ------- - -


    -

    Properties

    - -

    The C++ Way

    - - It is common practice to define a field, - along with object-oriented - get and set functions for it: - -$(CPPCODE -class Abc -{ - public: - void setProperty(int newproperty) { property = newproperty; } - int getProperty() { return property; } - - private: - int property; -}; - -Abc a; -a.setProperty(3); -int x = a.getProperty(); -) - - All this is quite a bit of typing, and it tends to make - code unreadable by filling - it with getProperty() and setProperty() calls. - -

    The D Way

    - - Properties can be get and set using the normal field syntax, - yet the get and set will invoke methods instead. - ------- -class Abc -{ - // set - void property(int newproperty) { myprop = newproperty; } - - // get - int property() { return myprop; } - - private: - int myprop; -} ------- - - which is used as: - ------- -Abc a; -a.property = 3; // equivalent to a.property(3) -int x = a.property; // equivalent to int x = a.property() ------- - - Thus, in D a property can be treated like it was a simple field name. - A property can start out actually being a simple field name, - but if later if becomes - necessary to make getting and setting it function calls, - no code needs to be modified other - than the class definition. - It obviates the wordy practice of defining get and set properties - $(SINGLEQUOTE just in case) a derived class should need to override them. - It's also a way to have interface classes, which do not have - data fields, behave syntactically as if they did. - -
    -

    Recursive Templates

    - -

    The C++ Way

    - - An advanced use of templates is to recursively expand - them, relying on specialization to end it. A template - to compute a factorial would be: - -$(CPPCODE -template<int n> class factorial -{ - public: - enum { result = n * factorial<n - 1>::result }; -}; - -template<> class factorial<1> -{ - public: - enum { result = 1 }; -}; - -void test() -{ - printf("%d\n", factorial<4>::result); // prints 24 -} -) - -

    The D Way

    - - The D version is analogous, though a little simpler, taking - advantage of promotion of single template members to the - enclosing name space: - ------- -template factorial(int n) -{ - enum { factorial = n * .factorial!(n-1) } -} - -template factorial(int n : 1) -{ - enum { factorial = 1 } -} - -void test() -{ - writefln("%d", factorial!(4)); // prints 24 -} ------- - -
    - -

    Meta Templates

    - - The problem: create a typedef for a signed integral type that is at - least $(I nbits) in size. - -

    The C++ Way

    - - This example is simplified and adapted from one written by - Dr. Carlo Pescio in - - Template Metaprogramming: Make parameterized integers portable with this novel technique. -

    - - There is no way in C++ to do conditional compilation based - on the result of an expression based on template parameters, so - all control flow follows from pattern matching of the template - argument against various explicit template specializations. - Even worse, there is no way to do template specializations based - on relationships like "less than or equal to", so the example - uses a clever technique where the template is recursively expanded, - incrementing the template value argument by one each time, until - a specialization matches. - If there is no match, the result is an unhelpful recursive compiler - stack overflow or internal error, or at best a strange syntax - error. -

    - - A preprocessor macro is also needed to make up for the lack - of template typedefs. - -$(CPPCODE -#include <limits.h> - -template< int nbits > struct Integer -{ - typedef Integer< nbits + 1 > :: int_type int_type ; -} ; - -struct Integer< 8 > -{ - typedef signed char int_type ; -} ; - -struct Integer< 16 > -{ - typedef short int_type ; -} ; - -struct Integer< 32 > -{ - typedef int int_type ; -} ; - -struct Integer< 64 > -{ - typedef long long int_type ; -} ; - -// If the required size is not supported, the metaprogram -// will increase the counter until an internal error is -// signaled, or INT_MAX is reached. The INT_MAX -// specialization does not define a int_type, so a -// compiling error is always generated -struct Integer< INT_MAX > -{ -} ; - -// A bit of syntactic sugar -#define Integer( nbits ) Integer< nbits > :: int_type - -#include <stdio.h> - -int main() -{ - Integer( 8 ) i ; - Integer( 16 ) j ; - Integer( 29 ) k ; - Integer( 64 ) l ; - printf("%d %d %d %d\n", - sizeof(i), sizeof(j), sizeof(k), sizeof(l)); - return 0 ; -} -) - -

    The C++ Boost Way

    - - This version uses the C++ Boost library. It was provided - by David Abrahams. - -$(CPPCODE -#include <boost/mpl/if.hpp> -#include <boost/mpl/assert.hpp> - -template <int nbits> struct Integer - : mpl::if_c<(nbits <= 8), signed char - , mpl::if_c<(nbits <= 16), short - , mpl::if_c<(nbits <= 32), long - , long long>::type >::type > -{ - BOOST_MPL_ASSERT_RELATION(nbits, <=, 64); -} - -#include <stdio.h> - -int main() -{ - Integer< 8 > i ; - Integer< 16 > j ; - Integer< 29 > k ; - Integer< 64 > l ; - printf("%d %d %d %d\n", - sizeof(i), sizeof(j), sizeof(k), sizeof(l)); - return 0 ; -} -) - -

    The D Way

    - - The D version could also be written with recursive templates, - but there's a better way. - Unlike the C++ example, this one is fairly easy to - figure out what is going on. - It compiles quickly, and gives a sensible compile time message - if it fails. - ------- -import std.stdio; - -template Integer(int nbits) -{ - static if (nbits <= 8) - alias byte Integer; - else static if (nbits <= 16) - alias short Integer; - else static if (nbits <= 32) - alias int Integer; - else static if (nbits <= 64) - alias long Integer; - else - static assert(0); -} - -int main() -{ - Integer!(8) i ; - Integer!(16) j ; - Integer!(29) k ; - Integer!(64) l ; - writefln("%d %d %d %d", - i.sizeof, j.sizeof, k.sizeof, l.sizeof); - return 0; -} ------- - -
    - -

    Type Traits

    - - Type traits are another term for being able to find out - properties of a type at compile time. - -

    The C++ Way

    - - The following template comes from - - C++ Templates: The Complete Guide, David Vandevoorde, Nicolai M. Josuttis - pg. 353 which determines if the template's argument type - is a function: - -$(CPPCODE -template<typename T> class IsFunctionT -{ - private: - typedef char One; - typedef struct { char a[2]; } Two; - template<typename U> static One test(...); - template<typename U> static Two test(U (*)[1]); - public: - enum { Yes = sizeof(IsFunctionT<T>::test<T>(0)) == 1 }; -}; - -void test() -{ - typedef int (fp)(int); - - assert(IsFunctionT<fp>::Yes == 1); -} -) - - This template relies on the $(SFINAE) principle. - Why it works is a fairly advanced template topic. - -

    The D Way

    - - $(ACRONYM SFINAE, Substitution Failure Is Not An Error) - can be done in D without resorting to template argument - pattern matching: - ------- -template IsFunctionT(T) -{ - static if ( is(T[]) ) - const int IsFunctionT = 0; - else - const int IsFunctionT = 1; -} - -void test() -{ - typedef int fp(int); - - assert(IsFunctionT!(fp) == 1); -} ------- - - The task of discovering if a type is a function doesn't need a - template at all, nor does it need the subterfuge of attempting to - create the invalid array of functions type. - The $(ISEXPRESSION) expression can test it directly: - ------- -void test() -{ - alias int fp(int); - - assert( is(fp == function) ); -} ------- - - -) - -Macros: - TITLE=Programming in D for C++ Programmers - WIKI=CPPtoD - CATEGORY_OVERVIEW=$0 diff --git a/css/codemirror.css b/css/codemirror.css new file mode 100644 index 0000000000..1067b3ee6b --- /dev/null +++ b/css/codemirror.css @@ -0,0 +1,334 @@ +/* BASICS */ + +.CodeMirror { + /* Set height, width, borders, and global font properties here */ + font-family: monospace; + height: 300px; + color: black; +} + +/* PADDING */ + +.CodeMirror-lines { + padding: 4px 0; /* Vertical padding around content */ +} +.CodeMirror pre { + padding: 0 4px; /* Horizontal padding of content */ +} + +.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { + background-color: white; /* The little square between H and V scrollbars */ +} + +/* GUTTER */ + +.CodeMirror-gutters { + border-right: 1px solid #ddd; + background-color: #f7f7f7; + white-space: nowrap; +} +.CodeMirror-linenumbers {} +.CodeMirror-linenumber { + padding: 0 3px 0 5px; + min-width: 20px; + text-align: right; + color: #999; + white-space: nowrap; +} + +.CodeMirror-guttermarker { color: black; } +.CodeMirror-guttermarker-subtle { color: #999; } + +/* CURSOR */ + +.CodeMirror-cursor { + border-left: 1px solid black; + border-right: none; + width: 0; +} +/* Shown when moving in bi-directional text */ +.CodeMirror div.CodeMirror-secondarycursor { + border-left: 1px solid silver; +} +.cm-fat-cursor .CodeMirror-cursor { + width: auto; + border: 0; + background: #7e7; +} +.cm-fat-cursor div.CodeMirror-cursors { + z-index: 1; +} + +.cm-animate-fat-cursor { + width: auto; + border: 0; + -webkit-animation: blink 1.06s steps(1) infinite; + -moz-animation: blink 1.06s steps(1) infinite; + animation: blink 1.06s steps(1) infinite; + background-color: #7e7; +} +@-moz-keyframes blink { + 0% {} + 50% { background-color: transparent; } + 100% {} +} +@-webkit-keyframes blink { + 0% {} + 50% { background-color: transparent; } + 100% {} +} +@keyframes blink { + 0% {} + 50% { background-color: transparent; } + 100% {} +} + +/* Can style cursor different in overwrite (non-insert) mode */ +.CodeMirror-overwrite .CodeMirror-cursor {} + +.cm-tab { display: inline-block; text-decoration: inherit; } + +.CodeMirror-ruler { + border-left: 1px solid #ccc; + position: absolute; +} + +/* DEFAULT THEME */ + +.cm-s-default .cm-header {color: blue;} +.cm-s-default .cm-quote {color: #090;} +.cm-negative {color: #d44;} +.cm-positive {color: #292;} +.cm-header, .cm-strong {font-weight: bold;} +.cm-em {font-style: italic;} +.cm-link {text-decoration: underline;} +.cm-strikethrough {text-decoration: line-through;} + +.cm-s-default .cm-keyword {color: #708;} +.cm-s-default .cm-atom {color: #219;} +.cm-s-default .cm-number {color: #164;} +.cm-s-default .cm-def {color: #00f;} +.cm-s-default .cm-variable, +.cm-s-default .cm-punctuation, +.cm-s-default .cm-property, +.cm-s-default .cm-operator {} +.cm-s-default .cm-variable-2 {color: #05a;} +.cm-s-default .cm-variable-3 {color: #085;} +.cm-s-default .cm-comment {color: #a50;} +.cm-s-default .cm-string {color: #a11;} +.cm-s-default .cm-string-2 {color: #f50;} +.cm-s-default .cm-meta {color: #555;} +.cm-s-default .cm-qualifier {color: #555;} +.cm-s-default .cm-builtin {color: #30a;} +.cm-s-default .cm-bracket {color: #997;} +.cm-s-default .cm-tag {color: #170;} +.cm-s-default .cm-attribute {color: #00c;} +.cm-s-default .cm-hr {color: #999;} +.cm-s-default .cm-link {color: #00c;} + +.cm-s-default .cm-error {color: #f00;} +.cm-invalidchar {color: #f00;} + +.CodeMirror-composing { border-bottom: 2px solid; } + +/* Default styles for common addons */ + +div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} +div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} +.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } +.CodeMirror-activeline-background {background: #e8f2ff;} + +/* STOP */ + +/* The rest of this file contains styles related to the mechanics of + the editor. You probably shouldn't touch them. */ + +.CodeMirror { + position: relative; + overflow: hidden; + background: white; +} + +.CodeMirror-scroll { + overflow: scroll !important; /* Things will break if this is overridden */ + /* 30px is the magic margin used to hide the element's real scrollbars */ + /* See overflow: hidden in .CodeMirror */ + margin-bottom: -30px; margin-right: -30px; + padding-bottom: 30px; + height: 100%; + outline: none; /* Prevent dragging from highlighting the element */ + position: relative; +} +.CodeMirror-sizer { + position: relative; + border-right: 30px solid transparent; +} + +/* The fake, visible scrollbars. Used to force redraw during scrolling + before actual scrolling happens, thus preventing shaking and + flickering artifacts. */ +.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { + position: absolute; + z-index: 6; + display: none; +} +.CodeMirror-vscrollbar { + right: 0; top: 0; + overflow-x: hidden; + overflow-y: scroll; +} +.CodeMirror-hscrollbar { + bottom: 0; left: 0; + overflow-y: hidden; + overflow-x: scroll; +} +.CodeMirror-scrollbar-filler { + right: 0; bottom: 0; +} +.CodeMirror-gutter-filler { + left: 0; bottom: 0; +} + +.CodeMirror-gutters { + position: absolute; left: 0; top: 0; + z-index: 3; +} +.CodeMirror-gutter { + white-space: normal; + height: 100%; + display: inline-block; + margin-bottom: -30px; + /* Hack to make IE7 behave */ + *zoom:1; + *display:inline; +} +.CodeMirror-gutter-wrapper { + position: absolute; + z-index: 4; + background: none !important; + border: none !important; +} +.CodeMirror-gutter-background { + position: absolute; + top: 0; bottom: 0; + z-index: 4; +} +.CodeMirror-gutter-elt { + position: absolute; + cursor: default; + z-index: 4; +} +.CodeMirror-gutter-wrapper { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.CodeMirror-lines { + cursor: text; + min-height: 1px; /* prevents collapsing before first draw */ +} +.CodeMirror pre { + /* Reset some styles that the rest of the page might have set */ + -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; + border-width: 0; + background: transparent; + font-family: inherit; + font-size: inherit; + margin: 0; + white-space: pre; + word-wrap: normal; + line-height: inherit; + color: inherit; + z-index: 2; + position: relative; + overflow: visible; + -webkit-tap-highlight-color: transparent; +} +.CodeMirror-wrap pre { + word-wrap: break-word; + white-space: pre-wrap; + word-break: normal; +} + +.CodeMirror-linebackground { + position: absolute; + left: 0; right: 0; top: 0; bottom: 0; + z-index: 0; +} + +.CodeMirror-linewidget { + position: relative; + z-index: 2; + overflow: auto; +} + +.CodeMirror-widget {} + +.CodeMirror-code { + outline: none; +} + +/* Force content-box sizing for the elements where we expect it */ +.CodeMirror-scroll, +.CodeMirror-sizer, +.CodeMirror-gutter, +.CodeMirror-gutters, +.CodeMirror-linenumber { + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +.CodeMirror-measure { + position: absolute; + width: 100%; + height: 0; + overflow: hidden; + visibility: hidden; +} + +.CodeMirror-cursor { position: absolute; } +.CodeMirror-measure pre { position: static; } + +div.CodeMirror-cursors { + visibility: hidden; + position: relative; + z-index: 3; +} +div.CodeMirror-dragcursors { + visibility: visible; +} + +.CodeMirror-focused div.CodeMirror-cursors { + visibility: visible; +} + +.CodeMirror-selected { background: #d9d9d9; } +.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } +.CodeMirror-crosshair { cursor: crosshair; } +.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } +.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } + +.cm-searching { + background: #ffa; + background: rgba(255, 255, 0, .4); +} + +/* IE7 hack to prevent it from returning funny offsetTops on the spans */ +.CodeMirror span { *vertical-align: text-bottom; } + +/* Used to force a border model for a node */ +.cm-force-border { padding-right: .1px; } + +@media print { + /* Hide the cursor when printing */ + .CodeMirror div.CodeMirror-cursors { + visibility: hidden; + } +} + +/* See issue #2901 */ +.cm-tab-wrap-hack:after { content: ''; } + +/* Help users use markselection to safely style text background */ +span.CodeMirror-selectedtext { background: none; } diff --git a/css/ddox.css b/css/ddox.css new file mode 100644 index 0000000000..4295bada76 --- /dev/null +++ b/css/ddox.css @@ -0,0 +1,104 @@ +h1 code { font-size: 1em; } +h1 code a { color: inherit; } + +#copyright p { + display: inline; +} + +pre a { text-decoration: none; } +pre a:hover { text-decoration: underline; } + +h1 code a { + text-decoration: none; + color: inherit; + border-bottom: 1px dashed #CCC; +} + +.hyphenate code { + hyphens: manual; +} + +col.caption { + min-width: 170pt; +} + +#navigation #cssmenu a.package { + background-image: none; +} + +span.tableEntryAnnotation { color: #866;} + +a.protected { + font-style: italic; + background-image: url(https://github.com/images/ddox/protected.png); + background-repeat: no-repeat; + background-position: 0pt 2pt; + padding-left: 16px; +} +a.package { + font-style: italic; + background-image: url(https://github.com/images/ddox/package.png); + background-repeat: no-repeat; + padding-left: 16px; +} +a.private { + font-style: italic; + background-image: url(https://github.com/images/ddox/private.png); + background-repeat: no-repeat; + padding-left: 16px; +} +a.inherited:after { content: url(https://github.com/images/ddox/inherited.png); padding-left: 3pt; vertical-align: bottom; } + +#symbolSearchPane label { color: #ddd; } + +#symbolSearch { width: 112pt; } + +#symbolSearchResults { + background: #F5F5F5; + border: 1px solid #CCC; + font-size: small; + list-style: none; + margin: 0; + margin-top: 5px; + padding: 0.3em; + position: absolute; + right: -1px; + top: 100%; + width: 100%; + z-index: 1000; +} + +#symbolSearchResults li { + background-repeat: no-repeat; + background-position: left center; + padding-left: 18px; +} + +#top #symbolSearchResults li a { + color: #B03931; + height: auto; + padding: 0; +} +#symbolSearchResults li a:hover +{ + background: transparent; + color: #742620; + text-decoration: underline; +} + +#symbolSearchResults .deprecated a { color: gray; } +#symbolSearchResults .module { background-image: url(https://github.com/images/ddox/module.png); } +#symbolSearchResults .functiondeclaration { background-image: url(https://github.com/images/ddox/function.png); } +#symbolSearchResults .classdeclaration { background-image: url(https://github.com/images/ddox/class.png); } +#symbolSearchResults .interfacedeclaration { background-image: url(https://github.com/images/ddox/interface.png); } +#symbolSearchResults .structdeclaration { background-image: url(https://github.com/images/ddox/struct.png); } +#symbolSearchResults .variabledeclaration { background-image: url(https://github.com/images/ddox/variable.png); } +#symbolSearchResults .property { background-image: url(https://github.com/images/ddox/property.png); } +#symbolSearchResults .enumdeclaration { background-image: url(https://github.com/images/ddox/enum.png); } +#symbolSearchResults .enummemberdeclaration { background-image: url(https://github.com/images/ddox/enummember.png); } +#symbolSearchResults .aliasdeclaration { background-image: url(https://github.com/images/ddox/alias.png); } +#symbolSearchResults .templatedeclaration { background-image: url(https://github.com/images/ddox/template.png); } + +/* Don't show simple handcrafted cheat sheets. DDOX does a good job generating + * them. */ +table.simple-cheatsheet { display: none; } diff --git a/css/html-skeleton.css b/css/html-skeleton.css new file mode 100644 index 0000000000..41497e65c3 --- /dev/null +++ b/css/html-skeleton.css @@ -0,0 +1,242 @@ +/* + +This file contains one entry for each element defined by html.ddoc. It +is otherwise content-free. Use it as a starting point in defining +display styles based upon html.ddoc. + +*/ + +/* DIV: Formats the "Authors" section */ +.Authors +{ +} + +/* DIV: Formats the "Bugs" section */ +.Bugs +{ +} + +/* DIV: class members (classes, funs, enums etc) */ +.class_members +{ +} + +/* DIV: Formats the "Copyright" section */ +.Copyright +{ +} + +/* DIV: code section introduced with --- and --- */ +.d_code +{ + font-family: "Courier New", monospace; + white-space: pre; +} + +/* SPAN: D comment in code */ +.d_comment +{ +} + +/* SPAN: Declaration, i.e. name introduced with return and parameters +*/ +.d_decl +{ +} + +/* DIV: Description of a declaration */ +.d_decl_dd +{ +} + +/* DIV DIV: Description of an entity defined in the doc */ +.d_decl_dd .sections +{ +} + +/* DIV DIV DIV: Summary of an entity defined in the doc */ +.d_decl_dd .sections .summary +{ +} + +/* SPAN: D keyword in code */ +.d_keyword +{ +} + +/* SPAN: D keyword in code */ +.d_keyword +{ +} + +/* SPAN: parameter style inside function description. Warning, +parameters will be rendered in this style everywhere.*/ +.d_param +{ +} + +/* SPAN: Symbol being introduced */ +.d_psymbol +{ +} + +/* SPAN: D string in code */ +.d_string +{ +} + +/* SPAN: D module title */ +.d_title +{ +} + +/* SPAN: link to Phobos resource */ +.phobos_src +{ +} + +/* DIV: Formats the "Date" section */ +.Date +{ +} + +/* SPAN: Highlight of D keywords? */ +.ddoc_keyword +{ +} + +/* DIV: Formats the "Deprecated" section */ +.Deprecated +{ +} + +/* DIV: Formats the description of an item */ +.description +{ +} + +/* DIV: Formats the description of enum members */ +.enum_members +{ +} + +/* DIV: Formats the "Examples" section */ +.Examples +{ +} + +/* SPAN: This is one of those "Authors:" thingies */ +.explanation_item +{ +} + +/* DIV: This is one of those "Authors: xyz" thingies */ +.explanatory +{ +} + +/* DIV: Formats the "History:" section */ +.History +{ +} + +/* DIV: Formats the "License:" section */ +.License +{ +} + +/* DIV: default style of members (inside classes, structs, enums, +templates) */ +.members +{ +} + +/* DIV: Top-level module members (classes, funs, enums etc) */ +.module_members +{ +} + +/* SPAN: Formats a parameter name all over the description. */ +.param +{ +} + +/* SPAN: Formats a parameter description */ +.param_desc +{ +} + +/* SPAN: Formats a parameter name */ +.param_id +{ +} + +/* TABLE: Formats the parameters table */ +.parameters +{ +} + +/* DIV: Formats the "Params:" section */ +.Params +{ +} + +/* SPAN: Name introduced by a declaration */ +.psymbol +{ +} + +/* DIV: Formats the "Returns:" section */ +.Returns +{ +} + +/* DIV: Formats the "See_Also:" section */ +.See_Also +{ +} + +/* SPAN: Formats a section with an undefined name */ +.section +{ +} + +/* SPAN: Formats the header of a section with an undefined name */ +.section_h +{ +} + +/* DIV: Sections of the document, pretty much the entire doc */ +.sections +{ +} + +/* DIV: Members of a struct */ +.struct_members +{ +} + +/* DIV: Formats the "Standards:" section */ +.Standards +{ +} + +/* DIV: Summary of the module or of a documented entity */ +.summary +{ +} + +/* DIV: Formats the description of a template's members */ +.template_members +{ +} + +/* DIV: Formats the "Throws:" section */ +.Throws +{ +} + +/* DIV: Formats the "Version:" section */ +.Version +{ +} diff --git a/css/print.css b/css/print.css index 19d7371980..72a3575f4c 100644 --- a/css/print.css +++ b/css/print.css @@ -8,9 +8,19 @@ pre { overflow: visible; overflow-X: hidden; + font-size: 100%; } -#search-box, #header, #navigation, #lastupdate, #tools, #google_ad, #footernav, #copyright +#search-box, +#header, +#navigation, +#lastupdate, +#tools, +#footernav, +#copyright, +#github-ribbon, +#top, +.page-contents { display: none; } @@ -22,5 +32,5 @@ div#content margin: 0; padding: 0; font-family: serif; - font-size: 12pt; + font-size: 10pt; } diff --git a/css/style.css b/css/style.css index c6fbedc407..6d7796b688 100644 --- a/css/style.css +++ b/css/style.css @@ -1,643 +1,2235 @@ +/* + +-- Colors -- + +Greys: + +white +#FCFCFC +#F5F5F5 +#E6E6E6 +#CCC +#ADADAD +#999 +#555 +#333 - main text + +Reds: + +#B03931 - our main red +#742620 - focus/hover + +#D8645E - on dark background +#F47069 - focus/hover on dark background + +#98312A +#943029 + +-- Font Sizes -- + +Keep the number of different font sizes low. The different heading levels +(h1, ... h6) get specific sizes. Other than that, try to use 'small' and +'large'. + +-- Misc -- + +border-radius: always 4px + +*/ + +@import url(https://fonts.googleapis.com/css?family=Roboto+Slab:300,400,700); + +body, .d_decl .quickindex +{ + font-family: "Roboto Slab", sans-serif; +} + +pre, code, .tt, .d_inlinecode, td.param_id, .CodeMirror pre, .d_decl +{ + font-family: Consolas, "Bitstream Vera Sans Mono", "Andale Mono", Monaco, "DejaVu Sans Mono", "Lucida Console", monospace; +} +pre, .CodeMirror pre +{ + font-size: small; +} + +pre div.blankline { display: none; } +ol div.blankline { display: none; } +ul div.blankline { display: none; } + body { - padding: 0; - border: 0; - color: black; - background-color: #1f252b; - background-image: url(https://github.com/images/gradient-red.jpg); - background-repeat: no-repeat; - font-size: 100%; - font-family: Verdana, "Deja Vu", "Bitstream Vera Sans", sans-serif; - min-width: 60em; -/* max-width: 1590px; */ - margin: 0px auto; + background: white; + color: #333; + font-size: 93.75%; + line-height: 1.4; + margin: 0; + padding: 0; +} + +#top > .helper, +body > .container, +body#Home #content #tools > div, +body#Home #content > .intro > div, +body#Home #content > .more +{ + margin: auto; + max-width: 76em; + padding: 0 1em; +} + +body > .container +{ + position: relative; +} + +body.doc input, +body.doc textarea, +body.std input, +body.std textarea +{ + background: white; + color: #333; +} + +/* top nav bar */ + +#top +{ + background: #B03931; + border-bottom: 1px #98312A solid; + position: relative; +} + +#top > .helper > .helper +{ + display: table; + width: 100%; +} + +#top #cssmenu, +#top .search-container +{ + display: table-cell; + vertical-align: middle; +} + +#top .search-container +{ + width: 0; /* shrink to content size */ +} + +#top .logo +{ + display: block; + float: left; + margin-left: -5.4em; + margin-right: -4em; + padding-top: 1px; +} + +#top img#logo +{ + height: 2.533em; + vertical-align: middle; + width: 13.69em; +} + +#top #d-language +{ + display: none; +} + +#top a.hamburger +{ + display: none; +} + +#top a +{ + color: white; + text-decoration: none; +} + +#top a:hover, +#top #cssmenu li.open > a, +#top #cssmenu li.active > a +{ + background: #98312A; +} + +#top .expand-container +{ + position: relative; +} + +/* main menu */ + +#top #cssmenu +{ + width: 100%; /* take all available space */ +} + +/* Hide expandable sections by default in #cssmenu. They have fallback URLs. */ +#top #cssmenu .expand-container > * +{ + display: none; +} +#top #cssmenu .expand-container.open > *, +#top #cssmenu .expand-container > .expand-toggle +{ + display: block; +} + +#top #cssmenu ul +{ + list-style: none; + margin: 0; + padding: 0; +} + +#top #cssmenu a, #top .search-container a +{ + display: block; + height: 1.4em; /* Not sure why, but without this the expandable items would + get half a pixel taller than the others. */ + padding: 0.6em 1em; + position: relative; + white-space: nowrap; +} + +#top #cssmenu > ul > li +{ + float: left; +} + +#top #cssmenu > ul > li > ul +{ + background: #B03931; + border: 1px solid #98312A; + + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + + -moz-box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176); + -webkit-box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176); + box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176); + + position: absolute; + z-index: 5; +} + +#top #cssmenu > ul > li > ul > li > a +{ + font-size: small; + padding-top: 0.3em; + padding-bottom: 0.3em; + padding-right: 2em; +} + +#top #cssmenu > ul > li > ul > li:first-child > a +{ + padding-top: 0.6em; +} + +#top #cssmenu > ul > li > ul > li:last-child > a +{ + padding-bottom: 0.6em; +} + + +#top #cssmenu > ul > li .menu-divider +{ + border-top: 1px solid #943029; +} + +#top #cssmenu > ul > li .menu-divider:before +{ + border-top: 1px solid rgba(255, 255, 255, 0.1); + display: block; + height: 1px; + content: ''; +} + +/* search box */ + +#top .search-container.expand-container .expand-toggle +{ + display: none; +} +#top .search-container.expand-container .expand-toggle::after +{ + content: "\f002 \f0d7"; /* f002 = search; f0d7 = caret down */ + font-family: FontAwesome; +} + +#top .search-container.expand-container .expand-toggle span +{ + display: none; +} + +#top #search-box +{ + display: block; /* Don't hide even though it's in a .expand-container. */ + padding-left: 1em; +} + +div#search-box form, span#search-query, span#search-dropdown, span#search-submit +{ + border: 1px none #CCC; +} + +div#search-box form +{ + background: white; + + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + + border-style: solid; + display: inline-block; + font-size: small; + margin: 0; + vertical-align: middle; + white-space: nowrap; +} + +span#search-query, +span#search-dropdown, span#search-dropdown > .helper, +span#search-submit +{ + display: inline-block; + height: 2em; + line-height: 1.3; + vertical-align: top; +} + +span#search-query +{ + width: 8em; +} + +span#search-query input, span#search-dropdown select, span#search-submit button +{ + background: transparent; + color: #333; + border: none; + font-size: small; + margin: 0; + padding: 0 0.5em; + width: 100%; + height: 100%; + outline: none; +} + +span#search-dropdown > .helper +{ + display: inline-block; + position: relative; + overflow: hidden; + width: 8em; +} + +span#search-dropdown > .helper::after +{ + content: "\f0d7"; /* caret down */ + font-family: FontAwesome; + position: absolute; + width: 1em; + line-height: 1em; + top: 0.5em; + right: 0.2em; +} + +span#search-dropdown select +{ + padding-right: 7.5em; + position: relative; + text-overflow: ellipsis; + width: 14em; /* Pushing the native dropdown arrow into invisibility. */ + z-index: 1; + + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +span#search-dropdown select::-ms-expand /* IE */ +{ + display: none; +} + +span#search-submit +{ + background: #E6E6E6; + border-left-style: solid; + line-height: 1.2em; + width: 3em; +} + +span#search-submit button +{ + color: #555; +} + +span#search-submit button:active +{ + position: relative; + top: 0.1em; +} + +span#search-submit span /* hide 'go' */ +{ + display: none; +} + +/* subnav */ + +.subnav, .subnav-helper +{ + background: #F5F5F5; + border: 0 solid #CCC; + border-width: 0 1px 1px; + padding-left: 1em; + padding-right: 1em; + width: 15em; +} + +.subnav +{ + float: left; + padding-bottom: 2em; + position: relative; +} + +.subnav a +{ + text-decoration: none; +} + +.subnav a:hover, .subnav .expand-toggle:hover +{ + text-decoration: underline; +} + +.subnav .smallprint a +{ + text-decoration: underline; +} + +.subnav h2 +{ + border-bottom: 1px solid #CCC; + font-size: 1em; + margin-right: -1em; +} + +/* Hide JS toggle. It's only displayed in the narrow layouts. */ +body.have-javascript .subnav.expand-container > h2.expand-toggle +{ + display: none; +} + +/* Hide links that just duplicate the subnav contents. They're only displayed +in the narrow layouts without JS. */ +.subnav .subnav-duplicate +{ + display: none; +} + +.subnav ul +{ + list-style: none; + margin: 0; + padding-left: 1em; +} +.subnav > ul +{ + padding-left: 0; +} + +.subnav li a +{ + display: block; + position: relative; + /* white-space: nowrap; */ +} + +.subnav li.active > a +{ + color: #742620; + text-decoration: underline; +} + +.subnav .hide-from-nav +{ + display: none; +} + +/* hierarchy tree lines */ + +body.std .subnav ul ul ul +{ + border-left: 1px solid #CCC; +} + +body.std .subnav .d_inlinecode +{ + display: block; + font-weight: normal; + overflow: hidden; + text-overflow: ellipsis; +} + +body.std .subnav li li > a > span, +body.std .subnav li li > h7 > span +{ + border-left: 1px solid #CCC; +} + +body.std .subnav ul ul li > a > span::before, +body.std .subnav ul ul li > h7 > span::before +{ + border-bottom: 1px solid #CCC; + content: ""; + display: inline-block; + width: 0.5ex; + margin-right: 0.5ex; + + height: 1em; + position: relative; + bottom: 0.5ex; +} + +body.std .subnav ul ul li:last-child > ul +{ + border-left: none; +} + +body.std .subnav ul ul li:last-child > a > span, +body.std .subnav ul ul li:last-child > h7 > span +{ + border-left: none; +} + +body.std .subnav ul ul li:last-child > a > span::before, +body.std .subnav ul ul li:last-child > h7 > span::before +{ + border-left: 1px solid #CCC; +} + +/* Don't show ddox package symbols in the subnav. */ +body.std .subnav a.package +{ + background: none; + padding-left: 0; + font-style: normal; +} + +.subnav-helper +{ + bottom: 0; + content: ""; + position: absolute; + top: 0; +} + +#content +{ + padding-bottom: 1em; + text-align: justify; +} + +/* This is a CSS hack to only target Blink based browsers + Targets Chrome 28 and later and Opera 14 and later +*/ +@media all and (-webkit-min-device-pixel-ratio:0) and (min-resolution: .001dpcm) { + #content + { + /* because Blink based browsers don't support hyphens */ + text-align: left; + } +} + +.subnav + #content +{ + margin-left: 19em; +} + +#content #tools +{ + padding: 0.3em 0 0.6em 0; + text-align: right; +} + +#content #tools .tip +{ + display: inline-block; + padding-left: 0.5em; +} + +.expand-container > .expand-toggle::after +{ + content: " \f0d7"; /* caret down */ + font-family: FontAwesome; +} +body.have-javascript .expand-container.open > .expand-toggle::after +{ + content: " \f0d8"; /* caret up */ +} + +body.have-javascript .expand-container > * +{ + display: none; +} + +/* Not hiding .subnav by default; only in the narrow layouts. */ +body .subnav.expand-container > * +{ + display: block; +} + +body.have-javascript .expand-container.open > *, +body.have-javascript .expand-container > .expand-toggle +{ + display: block; +} + +/* show signature download on hover */ +span.sig_btn +{ + display: inline-block; +} + +span.sig_btn > a:last-child +{ + visibility: hidden; +} + +span.sig_btn:hover > a:last-child +{ + visibility: visible; +} + +a.btn +{ + color: #333; + background: white; + border: 1px solid #CCC; + border-radius: 4px; + padding: 0.3em 0.6em; + display: inline-block; + text-decoration: none; +} + +a.btn:hover +{ + background-color: #E6E6E6; + border-color: #ADADAD; + color: #333; +} + +.btn.donate-large +{ + font-size: 22px; + padding: 0.4em 1em; + background-color: #B03931; + color: white; + border: #B03931; +} +.btn.donate-large:hover +{ + background-color: #98312A; + color: white; +} + +/* only grow as wide as necessary */ +div.btn-group-vertical +{ + display: inline-block; +} + +/* make all elements the same width */ +div.btn-group-vertical > a, +div.btn-group-vertical > span +{ + display: block; +} + +/* distribute multiple elements evenly in a row */ +div.btn-group-vertical > div.hbox +{ + display: flex; +} + +div.btn-group-vertical > div.hbox > a +{ + flex-grow: 1 +} + +/* replaces tag */ +em.big +{ + font-style: normal; + font-size: larger; +} + +/* replaces tag */ +em.tt +{ + font-style: normal; +} + +/* replaces tag */ +em.u +{ + font-style: normal; + text-decoration: underline; +} + +table.params +{ + border: 1px dotted #333; +} + +tr.param +{ + border: none; + border-bottom: 1px dotted gray; +} + +tr:last-child +{ + border-bottom: none; +} + +td.param_id +{ + border: inherit; + font-weight: bold; + padding-right: 1em; + white-space: nowrap; + vertical-align: top; +} + +td.param_desc +{ + border: inherit; + font-style: italic; +} + +.download-tables > .download-compilers { + flex-grow: 1; + flex-shrink: 0; +} + +.download-tables { + display: flex; + gap: 2.5em; + align-items: center; +} + +@media screen and (max-width: 65em) { + .download-tables { + flex-direction: column; + } +} + +table.lsp { + max-width: 30em; + background-color: white; + border: none; + border-radius: 0.5em; + border-top-left-radius: 0.25em; + border-top-right-radius: 0.25em; + /* TODO: currently with shadow, since it's new and shiny, make this fit with the other content eventually */ + box-shadow: 0 1px 2px rgba(0,0,0,0.2), 0 5px 7px rgba(0,0,0,0.2); + position: relative; +} + +table.lsp tbody > tr:nth-child(1) > td:before { + display: block; + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 0.5em; + background-color: #B03931; + border-top-left-radius: 0.25em; + border-top-right-radius: 0.25em; +} + +table.lsp img { + background-color: white; + border-radius: 0.5em; + padding: 0.5em; +} + +table.lsp td { + padding: 1em; +} + +table.lsp tbody > tr:nth-child(1) > td { + padding-bottom: 0; + padding-top: 1.5em; +} + +table.download-compilers +{ + width: 100%; + max-width: 50em; + table-layout: fixed; +} + +.download-tables table td +{ + border: none; +} + +.download-tables h2 +{ + margin: 0; + margin-bottom: 4pt; + text-align: center; +} + +.download-tables table > tbody > tr:first-child > td +{ + text-align: center; + vertical-align: middle; +} + +.download-tables table > tbody > tr:nth-child(2) > td +{ + text-align: left; +} + +.download-tables table > tbody > tr:nth-child(2) > td > ul +{ + margin-bottom: 0; + padding-left: 1em; +} + +.download-tables table div.download-link +{ + text-align: center; + margin-bottom: 1em; +} + +table.download-compilers img +{ + width: 100%; +} + +table.lsp img +{ + width: 100%; + max-width: 8em; + margin: 0; +} + +.download-tables table h3 +{ + margin-top: 0; + text-align: center; +} + +div#download-choose +{ + float: right; +} + +.download_image +{ + display: inline-block; + width: 100px; + vertical-align: top; +} + +h3.download +{ + display: inline-block; +} + +.download_paragraph +{ + display: inline-block; +} + +.download_paragraph > h3 +{ + margin: 0; +} + +/* release | beta | nightly */ +.download_channels +{ + word-spacing: 2em; +} + +.download_channel +{ + display: inline-block; + word-spacing: initial; +} + +.footnote +{ + font-style: italic; +} +.footnote::before { content: " ("; } +.footnote::after { content: ")"; } + +.gname +{ + font-style: italic; +} + +.metacode +{ + font-style: italic; +} + +.key +{ + font-weight: bold; + display: block; +} + +.hyphenate +{ + -webkit-hyphens: auto; + -moz-hyphens: auto; + -epub-hyphens: auto; + -ms-hyphens: auto; + hyphens: auto; +} + +.donthyphenate +{ + -webkit-hyphens: manual; + -moz-hyphens: manual; + -epub-hyphens: manual; + -ms-hyphens: manual; + hyphens: manual; +} + +.black { color: black; } +.blue { color: blue; } +.green { color: green; } +.red { color: red; } +.white { color: white; } +.yellow { color: yellow; } + +.bigoh +{ + font-weight: bold; +} + +div.summary, div.description, div.keyval, div.blankline +{ + margin: 1em 0; } h1, h2, h3, h4, h5, h6 { - font-family: Georgia, "Times New Roman", Times, serif; - font-weight: normal; - color: #633; - line-height: normal; - text-align: left; + font-weight: normal; + line-height: normal; + text-align: left; + margin: 2em 0 1em; } h1 { - margin-top: 0; - font-size: 2.5em; + font-size: 2.0em; + margin-top: 0; } h2 { - font-size: 1.7em; + font-size: 1.5em; } h3 { - font-size: 1.35em; + font-size: 1.35em; } h4 { - font-size: 1.15em; - font-style: italic; - margin-bottom: 0; + font-size: 1.15em; } +h5 +{ + font-size: 1em; +} +/*This is to support the "Programming in D" book*/ +h6 { + font-size: 1em; + color:#000033; + font-weight:bold; +} +.chapter { + font-size: 2em; + color:#000033; +} +.subsection { + font-size: 1.15em; + color:#000033; + font-weight:bold; +} form { - margin: 0; + margin: 0; } blockquote { - font-family: Georgia, "Times New Roman", Times, serif; - background-color: #e5e5e5; - display: block; - padding: 0.25em 1em; - margin: 1em 2em; + background-color: #e5e5e5; + display: block; + padding: 0.25em 1em; + margin: 1em 2em; } blockquote p:before { - content: "\201C"; - font-family: Georgia, "Times New Roman", Times, serif; - color: #bacaca; - display: block; - font-size: 700%; - width: 50px; - height: 0; - margin-left: -0.5em; - line-height: 0.8em; + content: "\201C"; + color: #bacaca; + display: block; + font-size: 700%; + width: 50px; + height: 0; + margin-left: -0.5em; + line-height: 0.8em; } blockquote p { - margin: 0; - font-style: italic; + margin: 0; + font-style: italic; } blockquote cite { - display: block; - text-align: right; + display: block; + text-align: right; } +/* pre.prettyprint and div.prototype come from prettyprint.js */ +pre, pre.prettyprint, div.prototype +{ + background: white; + border-radius: 4px; + padding: 1ex; + margin: 1em 0 1em 0; + line-height: normal; + border: 1px solid #ccc; + width: auto; +} pre { - background: white; - padding: 1ex; - margin: 1em 0 1em 3em; - font-family: monospace; - font-size: 1.2em; - line-height: normal; - border: 1px solid #ccc; - width: auto; - white-space: pre-wrap; /* css-3 */ - white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ } -dd +dd, .d_decl_dd { - padding: 1ex; - margin-left: 3em; - margin-bottom: 1em; + margin: 0; + margin-bottom: 2em; + padding: 1ex; + padding-left: 2em; } -table, tr, td, th +.template_param_list { - /*border-style: solid;*/ + color: #48688E; } -td +.constraint { - text-align: justify; + opacity: .35; } -hr +.constraint:before { + content: "Constraints: "; + visibility: hidden; +} + +.constraint:hover:before { + visibility: visible; +} + +.constraint:hover { + opacity: 1; +} + +table { - margin: 2em 0; + border: solid #333; + border-width: 2px 0; + border-collapse: collapse; } -a +table tr { - color: #006; + border: none; } -a:visited +table td, table th, table caption { - color: #606; + text-align: left; + vertical-align: top; + padding: 0.3em; } -/* These are different kinds of
     sections */
    -.bnf /* grammar */
    +.quickindex .book caption:empty
     {
    -	background-color: white;
    -	color: #000066;
    +    padding: 0px;
     }
     
    -.ddoccode
    +table td
     {
    -	background-color: #f3eeee;
    -	color: #000066;
    +    border: none;
    +    border-bottom: 1px solid #E6E6E6;
     }
     
    -.console /* command line console */
    +table th
     {
    -	background-color: #f7f7f7;
    -	color: #181818;
    +    border: none;
    +    border-bottom: 1px solid #333;
     }
     
    -.moddeffile /* module definition file */
    +table td:not(:last-child), table th:not(:last-child)
     {
    -	background-color: #efeffe;
    -	color: #010199;
    +    padding-right: 1em;
     }
     
    -.scini /* sc.ini configuration file */
    +/*
    +  These next two rules are for pages like:
    +  http://dlang.org/phobos-prerelease/std_regex.html
    +
    +  The idea is if we have a list of links, we want space
    +  to the right of each one. But detecting a list of links
    +  vs just a single link requires some thought: the css
    +  adjacent sibling rule does well detecting all but the first
    +  one in a list, so we'll add space to the right of them (that's
    +  the second rule here), but that leaves an inconsistent space
    +  after the first item.
    +
    +  That's where the following rule comes in: on the item directly
    +  following the first link, add some left padding to simulate the
    +  first one having the same space as the others.
    +*/
    +table.book tbody a:first-child + a
     {
    -	background-color: #fef6fe;
    -	color: #111199;
    +    padding-left: .6em;
     }
     
    -.d_code /* D code */
    +table.book tbody a + a
     {
    -	background-color: #fcfcfc;
    -	color: #000066;
    +    padding-right: .6em;
     }
     
    -.d_code2 /* D code */
    +hr
     {
    -	background-color: #fcfcfc;
    -	color: #000066;
    +    margin: 2em 0;
     }
     
    -.asmcode /* Asm code */
    +a, .question, .expand-toggle
     {
    -	background-color: #afcbde;
    -	color: #000066;
    +    color: #B03931;
    +    cursor: pointer;
     }
     
    -.ccode /* C code */
    +a:hover, .question:hover, .expand-toggle:hover
     {
    -	background-color: #f6ecf0;
    -	color: #000066;
    +    color: #742620;
     }
     
    -.cppcode /* C++ code */
    +/*
    +Styling for page anchor self-links.
    +
    +These links look like regular headers unless hovered, in which case
    +they are underlined and display a pilcrow after them.
    +*/
    +a.anchor
     {
    -	background-color: #f6ecf0;
    -	color: #000066;
    +    color: #633; /* Use the regular header text color */
    +    text-decoration: none; /* Don't underline unless hovered */
     }
     
    -.cppcode2 /* C++ code */
    +a.anchor:hover
     {
    -	background-color: #f6ecf0;
    -	color: #000066;
    +    text-decoration: underline; /* See above */
     }
     
    -td .d_code2, td .cppcode2, td .cppcode
    +a.anchor:hover::after
     {
    -	min-width: 20em;
    -	margin: 1em 0em;
    +    content: " \00B6"; /* Unicode pilcrow symbol */
    +    color: #333; /* Pilcrow should not use the regular header text color */
    +    font-style: normal; /* ... and should not be italic */
     }
     
    -.d_inlinecode
    +/* Avoid inserting the pilcrow in the middle of the line on the compiler pages */
    +
    +body.dcompiler dt a.anchor:hover::after
     {
    -	font-family: monospace;
    -	/* font-size: 1.2em; */
    -	font-weight: bold;
    +    display: none;
     }
     
    -/* Elements of D source code text */
    -.d_comment { color: green; }
    -.d_string { color: red; }
    -.d_keyword { color: blue; }
    -.d_psymbol { text-decoration: underline; }
    -.d_param { font-style: italic; }
    +body.dcompiler dt a.anchor:hover
    +{
    +    position: relative;
    +}
     
    -/* Focal symbol that is being documented */
    -.ddoc_psymbol { color: #336600; }
    +body.dcompiler dt a.anchor:hover:before
    +{
    +    content: " \00B6";
    +    color: #333;
    +    font-style: normal;
    +    position: absolute;
    +    left: -1em;
    +}
     
    -div#top
    +/* These are different kinds of 
     sections */
    +.bnf /* grammar */
     {
    -/* 	max-width: 85em; */
    +    background-color: white;
     }
     
    -div#header
    +.ddoccode
     {
    -    padding: 0.2em 1em 0.2em 1em;
    +    background-color: #f3eeee;
     }
     
    -img#logo
    +.console /* command line console */
    +{
    +    background-color: #333;
    +    border-color: #333;
    +    color: #F5F5F5;
    +}
    +.console a
     {
    -	vertical-align: bottom;
    +    color: #D8645E;
    +}
    +.console a:hover
    +{
    +    color: #F47069;
     }
     
    -/*div#d-language a*/
    -#d-language
    +.moddeffile /* module definition file */
     {
    -	color: white;
    -	font-size: 1.7em;
    -	font-family: Georgia, "Times New Roman", Times, serif;
    -	font-variant: small-caps;
    -	text-decoration: none;
    +    background-color: #efeffe;
    +    color: #010199;
     }
     
    -div#search-box
    +.scini /* sc.ini configuration file */
     {
    -	background-color: transparent;
    -	float: right;
    -	margin-top: 1em;
    -	margin-right: 1em;
    -	text-align: right;
    +    background-color: #fef6fe;
    +    color: #111199;
     }
     
    -div#search-box img, div#search-box input, div#search-box select
    +.d_code, .d_code2 /* D code */
     {
    -	margin: 0;
    -	padding: 0;
    -	vertical-align: middle;
    +    background-color: #fcfcfc;
     }
     
    -div#search-box input#q
    +.asmcode /* Asm code */
     {
    -	border: 0px;
    -	height: 22px;
    -	background-image: url(https://github.com/images/search-bg.gif);
    -	color: black;
    +    background-color: #afcbde;
    +    border-color: #afcbde;
     }
     
    -div#search-box select
    +.ccode, .cppcode, .cppcode2 /* C/C++ code */
     {
    -    width: 14em;
    +    background-color: #fcfcfc;
     }
     
    -div#search-box input#q:focus
    +td .d_code2, td .cppcode2, td .cppcode
     {
    -	outline: none;
    +    min-width: 20em;
    +    margin: 1em 0;
     }
     
    +.d_inlinecode
    +{
    +    font-weight: bold;
    +}
     
    -div#navigation
    +.d_title
     {
    -	font-size: 0.875em;
    -	float: left;
    -	width: 11.5em;
    -	padding: 0 1.5em;
    +    font-weight: bold;
    +    text-overflow: clip;
    +    overflow: hidden;
    +    display: block;
    +    word-wrap: break-word;
    +    font-family: Consolas, "Bitstream Vera Sans Mono", "Andale Mono", Monaco, "DejaVu Sans Mono", "Lucida Console", monospace;
     }
     
    -div#content
    +.phobos_src
     {
    -    text-align: justify;
    -	min-height: 440px;
    -	margin-left: 13.5em;
    -	padding: 1.6em;
    -	padding-top: 1.3em;
    -	padding-bottom: 1em;
    -	margin-right: 0.5em;
    -	border: 0.4em solid #ccd5d5;
    -	background-color: #f6f6f6;
    -	font-size: 0.875em;
    -	line-height: 1.4em;
    -	text-align: justify;
    +    text-overflow: clip;
    +    overflow: hidden;
    +    display: block;
    +    word-wrap: break-word;
     }
     
    -body.chm
    +/* syntax highlighting
    +
    +d_* classes come from Ddoc.
    +cm-* classes come from CodeMirror.
    +
    +These classes come from prettify.js:
    +.pln - plain text
    +.str - string content
    +.kwd - keyword
    +.com - comment
    +.typ - type name
    +.lit - literal value
    +.pun - punctuation
    +.opn - lisp open bracket
    +.clo - lisp close bracket
    +.tag - markup tag name
    +.atn - markup attribute name
    +.atv - markup attribute value
    +.dec - declaration
    +.var - variable name
    +.fun - function name
    +
    +*/
    +
    +.d_comment,
    +.cm-s-eclipse span.cm-comment,
    +.com
     {
    -	min-width: 0 !important;
    +    color: #999;
     }
     
    -body.chm div#content
    +.d_string,
    +.cm-s-eclipse span.cm-string, .cm-s-eclipse span.cm-string-2,
    +.str, .atv
     {
    -	padding: 20px;
    -	border: none;
    -	margin: 0 !important;
    +    color: #DC4040;
     }
     
    -body.chm div#tools
    +.d_keyword,
    +.cm-s-eclipse span.cm-keyword, .cm-s-eclipse span.cm-builtin,
    +.kwd
     {
    -	margin-right: 0;
    +    color: #4040DC;
     }
     
    -div#twitter
    +.typ
     {
    -	color: white;
    -	font-size: 0.875em;
    -	float: right;
    -	width: 16em;
    -	padding: 1em 1em;
    -    margin-top: -1em;
    +    color: #4040DC;
     }
     
    -div.navblock
    +
    +.d_param
     {
    -	margin-top: 0;
    -	margin-bottom: 1em;
    +    font-style: italic;
     }
     
    -div#navigation .navblock h2
    +/* .cm-meta is here because it and .lit both match @-attributes */
    +.cm-s-eclipse span.cm-number, .cm-s-eclipse span.cm-meta,
    +.lit
     {
    -	font-family: Verdana, "Deja Vu", "Bitstream Vera Sans", sans-serif;
    -	font-size: 1.35em;
    -	color: #ccc;
    -	margin: 0;
    +    color: #8E00DC;
     }
     
    -div#navigation .navblock ul
     {
    -	list-style-type: none;
    -	margin: 0;
    -	padding: 0;
    +    color: #333;
     }
     
    -div#navigation .navblock li
    +.cm-s-eclipse span.cm-attribute,
    +.atn
     {
    -	margin: 0 0 0 0.8em;
    -	padding: 0;
    +    color: #9ad452;
     }
     
    -#navigation .navblock a
    +.cm-s-eclipse span.cm-tag,
    +.tag
     {
    -	display: block;
    -	color: #ccc;
    -	text-decoration: none;
    -	padding: 0.1em 0;
    -	border-bottom: 1px dotted #494949;
    +    color: #ffaa00;
     }
     
    -#navigation .navblock a:hover
    +.cm-s-eclipse span.cm-error
     {
    -	color: #eee;
    +    color: #f00;
     }
     
    -#navigation .navblock a.active
    +.cm-s-eclipse span.cm-def, .cm-s-eclipse span.cm-operator,
    +.cm-s-eclipse span.cm-property, .cm-s-eclipse span.cm-variable,
    +.cm-s-eclipse span.cm-variable-2, .cm-s-eclipse span.cm-variable-3,
    +.pln, .fun
    +.dec, .var
     {
    -	color: white;
    -	border-color: white;
    +    color: #333;
     }
     
    +.cm-s-eclipse span.cm-word {color: #006;}
    +.cm-s-eclipse span.cm-atom {color: #219;}
    +.cm-s-eclipse span.cm-qualifier {color: #555;}
    +.cm-s-eclipse span.cm-bracket {color: #cc7;}
    +.cm-s-eclipse span.cm-link {color: #219;}
     
    -div#translate
    +
    +.ddoc_keyword
     {
    -	margin-top: 3em;
    -	margin-left: 0;
    -	color: #ccc;
    +    font-weight: bold;
     }
     
    +.ddoc_param
    +{
    +    font-style: italic;
    +}
     
    -div#tools
    +/* Focal symbol that is being documented */
    +.d_psymbol, .ddoc_psymbol
     {
    -	margin: -1.5em;
    -	margin-bottom: 0;
    -	text-align: right;
    +/*     color: #B03931; */
    +    font-weight: bold;
     }
     
    -div#tools span
    +.d_decl
    +{
    +    background: #F5F5F5;
    +    border-left: 5px solid #B03931;
    +    text-align: left;
    +    border-top-left-radius: 4px;
    +    border-top-right-radius: 4px;
    +}
    +.d_decl > div
     {
    -	padding-left: 0.5em;
    -	font-size: 0.8em;
    -	font-style: italic;
    -	color: #666;
    +    border: 1px solid #E6E6E6;
    +    border-top-right-radius: 4px;
    +    padding: 0.6em 1em;
     }
     
    -div#tools a
    +.d_decl + dd
     {
    -	color: #666;
    +    border: 1px solid #E6E6E6;
    +    border-top: none;
    +    border-bottom-left-radius: 4px;
    +    border-bottom-right-radius: 4px;
     }
     
    -div#tools img
    +img
     {
    -	vertical-align: middle;
    +    border: 0;
     }
     
    +body.chm div#news,
    +body.chm div.subnav-helper,
    +body.chm div.subnav,
    +body.chm div#top
    +{
    +    display: none;
    +}
     
    -div#content li
    +body.chm
     {
    -	padding-bottom: .7ex;
    +    min-width: 0 !important;
     }
     
    +body.chm div#content
    +{
    +    padding: 20px;
    +    border: none;
    +    margin: 0 !important;
    +    border-radius: 0;
    +}
     
    -div#google_ad
    +body.chm div#tools
     {
    -	margin-top: 6em;
    +    margin-right: 0;
     }
     
    +body.chm dt.d_decl
    +{
    +    width: 100%;
    +}
     
    -div#footernav
    +.boxes
     {
    -    clear: both;
    -/* 	margin-top: 2em; */
    -	padding: 1em 2em 0 2em;
    -/* 	background-color: #303333; */
    -	color: #666;
    -	text-align: center;
    -	font-size: 80%;
    +    margin: 2em 0;
     }
     
    -div#footernav a
    +.boxes .row
     {
    -	color: #ccc;
    +    display: table-row;
     }
     
    -div#footernav a:hover
    +.boxes .item
     {
    -	color: white;
    +    display: table-cell;
    +    width: 50%;
     }
     
    +.boxes > .row > .item
    +{
    +    padding: 1em 2em;
    +}
     
    -div#copyright
    +.boxes > .row > .item > h4:first-child
     {
    -	padding: 1em 2em;
    -/* 	background-color: #303333; */
    -	color: #ccc;
    -	font-size: 50%;
    -	text-align: center;
    +    margin-top: 0;
     }
     
    -div#copyright a
    +.boxes > .row:first-child > .item
     {
    -	color: #ccc;
    +    padding-top: 0;
     }
     
    +.boxes > .row:last-child > .item
    +{
    +    padding-bottom: 0;
    +}
     
    -/* These are for the newsgroup archives */
    -div#newsnav
    +.boxes > .row > .item:first-child
     {
    -	margin-top: -1.5em;
    -	margin-bottom: -1em;
    +    padding-left: 0;
     }
    -div#Posting
    +
    +.boxes > .row > .item:last-child
     {
    -	border: 1px solid #cccccc;
    -	margin-bottom: 1em;
    +    padding-right: 0;
     }
    -div#PostingHeading
    +
    +.tip
     {
    -	font-family: Georgia, "Times New Roman", Times, serif;
    -	font-size: larger;
    -	color: #633;
    -	background-color: #eeeeee;
    +    font-size: small;
    +    position: relative;
     }
    -div#PostingHeading img
    +
    +.tip > div
     {
    -	vertical-align: middle;
    +    display: none;
    +    position: absolute;
    +    top: 25px;
    +    left: auto;
    +    right: 0;
    +    width: 19em;
    +    padding: 8px;
    +    z-index: 100;
    +    background: #555;
    +    color: white;
    +    font-style: normal;
    +    text-align: left;
    +    -moz-border-radius: 4px;
    +    -webkit-border-radius: 4px;
    +    border-radius: 4px;
     }
    -div#PostingHeading a
    +
    +.tip:hover > div
     {
    -	text-decoration: none;
    +    display: block;
     }
    -div#PostingFooting
    +
    +.tip > div > *:first-child
     {
    -	font-size: smaller;
    -	background-color: #eeeeee;
    +    margin-top: 0;
     }
    -div#PostingTOC
    +.tip > div > *:last-child
     {
    -	font-size: smaller;
    +    margin-bottom: 0;
     }
    -div#PostingTOC li
    +
    +div#copyright
     {
    -	margin-left: 0;
    +    margin-top: 1.5em;
    +    text-align: center;
     }
    -div#PostingTOC a
    +
    +.smallprint, .smallprint a
     {
    -	font-family: Georgia, "Times New Roman", Times, serif;
    +    color: #999;
    +    font-size: small;
     }
    -.PostingBody /* newsgroup posting */
    +
    +.smallprint a:hover
     {
    -	border: 0;
    -	margin: 0;
    -	background-color: #fcfcfc;
    -	color: #000066;
    -	margin-left: 0em;
    -	min-width: 15em;
    -	padding-bottom: 0.5em;
    +    color: #555;
     }
    -.PostingQuote /* quote inside newsgroup posting */
    +
    +#contributors-github img
     {
    -	border: 1px solid #666666;
    -	font-size: 90%;
    -	background-color: inherit;
    -	color: #666666;
    -	margin-left: 0em;
    -	min-width: 15em;
    +    padding-right: 5px;
     }
     
     /* These are for the changelogs */
    -div#version
    +div.version
     {
    -	border-top: 1px solid black;
    -	font-size: 0.9em;
    -	padding-top: 2ex;
    +    font-size: 0.9em;
     }
    -div#version font
    +div.version font
     {
    -	font-family: Georgia, "Times New Roman", Times, serif;
    -	color: #633;
    +    color: #633;
     }
    -div#version li
    +div.version li
     {
    -	padding-bottom: 0.3ex;
    +    padding-bottom: 0.3ex;
     }
    -div#bugsfixed
    +div.changelog-nav
     {
    +    font-size: small;
    +    margin: 2em 0;
    +    text-align: center;
     }
    -div#whatsnew
    -{
    +
    +
    +.leadingrow {
    +    background-color: #E4E9EF;
    +    font-size: 110%;
    +}
    +
    +.quickindex {
    +    font-weight: normal;
    +    background-color: #F5F5F5;
    +}
    +
    +.quickindex a {
    +    text-decoration: none;
     }
     
    +.quickindex a:hover {
    +    text-decoration: underline;
    +}
     
    -/* These are for comparison.html */
    -table.comp /* "comparison with D": table */
    +.question, .question *
     {
    -	background-color:#e9e6dd;
    +    display: inline;
    +    text-decoration: underline;
    +    cursor:pointer;     /* Cursor is like a hand when someone rolls the mouse over the question */
    +}
    +
    +.answer {
    +    display:none;
    +}
    +
    +.nobr {
    +    white-space:nowrap;
    +}
    +
    +/* Openable example boxes */
    +.example-box {
    +	transition: 0.25s;
    +	overflow: hidden;
     }
    -table.comp a
    +
    +
    +/* Runnable-examples css */
    +textarea.d_code {display: none;}
    +textarea.d_code_stdin, textarea.d_code_args
     {
    -	color: black;
    +    text-align: left;
    +    border: none;
    +    width: 98%;
    +    padding: 5px;
    +    margin: 1px;
    +    word-wrap: break-word;
    +    height: auto;
    +    background: white;
    +    margin-left: 2px;
    +    outline: none;
    +    hyphens: none;
    +}
    +
    +pre.d_code_output {
    +    border: none;
    +    max-height: 30em;
    +    overflow: auto;
    +}
    +
    +div.d_code {margin: 0; padding: 0; background: #F5F5F5;}
    +div.d_run_code {display: none;}
    +div.d_code_output, div.d_code_stdin, div.d_code_args, div.d_code_unittest
    +{
    +    border: 1px solid #CCC;
    +    background: white;
    +    display: none;
    +    height: auto;
    +    width: 100%;
    +}
    +
    +.d_code_title {font-weight: bold;padding: 5px;}
    +
    +pre.d_code
    +{
    +    overflow-x: auto;
    +    white-space: pre;
    +    word-wrap: unset;
    +}
    +
    +.CodeMirror-wrap {padding: 3px;}
    +.CodeMirror {line-height: normal; border: 1px solid #CCC; background: #FCFCFC; height: auto}
    +.cm-s-eclipse .CodeMirror-matchingbracket {border:1px solid grey;color:black !important;}
    +
    +input.runButton, input.resetButton, input.argsButton, input.inputButton, input.editButton, input.openInEditorButton
    +{
    +    -moz-box-shadow:inset 0 1px 0 0 #ffffff;
    +    -webkit-box-shadow:inset 0 1px 0 0 #ffffff;
    +    box-shadow:inset 0 1px 0 0 #ffffff;
    +    background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #ededed), color-stop(1, #dfdfdf) );
    +    background:-moz-linear-gradient( center top, #ededed 5%, #dfdfdf 100% );
    +    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed', endColorstr='#dfdfdf');
    +    background-color:#ededed;
    +    border:1px solid #dcdcdc;
    +    display:inline-block;
    +    color:#777777;
    +    font-family:arial;
    +    font-size:72%;
    +    font-weight:bold;
    +    padding:3px 6px;
    +    text-decoration:none;
    +    text-shadow:1px 1px 0px #ffffff;
    +    width: 10en;
    +    margin: 2px;
    +    position: relative;
    +    z-index: 2;
    +    cursor: pointer;
    +}
    +input.openInEditorButton {
    +    float: right;
    +    width: auto;
     }
    -td.compNo  /* comparison with D: "NO" */
    +input.runButton:hover, input.resetButton:hover, input.argsButton:hover, input.inputButton:hover, input.editButton:hover,input.runButton[disabled]
     {
    -	background-color:red;
    -	text-align:center;
    +    background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #dfdfdf), color-stop(1, #ededed) );
    +    background:-moz-linear-gradient( center top, #dfdfdf 5%, #ededed 100% );
    +    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#dfdfdf', endColorstr='#ededed');
    +    background-color:#dfdfdf;
     }
    -td.compYes  /* comparison with D: "YES" */
    +input.runButton:active,
    +input.resetButton:active,
    +input.argsButton:active,
    +input.inputButton:active,
    +input.editButton:active
     {
    -	background-color:#00FF00;
    -	text-align:center;
    +    position: relative; top: 1px;
     }
    +input.resetButton{display: none}
     
    -TABLE.book
    -{
    -    border-top: 2px solid;
    -    border-bottom: 2px solid;
    -    border-spacing: 1pt;
    +div.editButton, div.openInEditorButton, div.runButton, div.resetButton {
    +    display: inline-block;
    +    margin-right: 10px;
    +    cursor: pointer;
    +    color: #333;
    +    background: white;
    +    border: 1px solid #CCC;
    +    border-radius: 4px;
    +    padding: 0.3em 0.6em;
    +    display: inline-block;
    +    text-decoration: none;
    +}
    +div.openInEditorButton {
    +    margin-right: 0;
    +    float: right;
    +}
    +div.openInEditorButton i{
    +    padding-right: 5px;
    +}
    +.unittest_examples .d_example_buttons {
    +    margin-top: 10px;
    +}
    +.unittest_examples .CodeMirror, .unittest_examples .d_code_output {
    +    margin-top: 10px;
    +}
    +
    +/* Style for the example run buttons on the Phobos library documentation */
    +.d_example_buttons {
    +    text-align: left;
    +}
    +.runnable-examples-stdin {
    +    display: none;
    +}
    +.runnable-examples-args {
    +    display: none;
    +}
    +.your-code-here-title {
    +    display: none;
     }
    +#your-code-here-select-example {
    +    padding-bottom: 0.3em;
    +}
    +.fa-select select {
    +    background: white;
    +    border: 1px solid #CCC;
    +    border-radius: 4px;
    +    padding: 0.3em 20px 0.3em 0.3em;
    +    font-size: 0.95em;
    +    -webkit-appearance: none;
    +    -moz-appearance: none;
    +    appearance: none;
    +    max-width: 120%;
    +}
    +.fa-select::after {
    +   font-family: FontAwesome;
    +   content: "\f0d7";
    +   margin-left: -15px;
    +   pointer-events: none; /* propagate click */
    +}
    +/* Runnable-examples css -end */
     
    -TABLE.book TD
    +.page-contents
     {
    -    padding: 1pt 12pt 1pt 1pt;
    -    vertical-align: top;
    -    border-bottom: 1px solid #E4E9EF;
    +    width: 300px;
    +    padding-right: 10px;
    +    border: solid #333;
    +    border-width: 2px 0;
    +    font-size: small;
    +    text-align: left;
    +    margin: 0 0 2em 2em;
     }
     
    -TABLE.book TH
    +.page-contents-header
     {
    -    border-bottom: 1px solid;
    -    padding: 1pt 12pt 1pt 1pt;
    -    vertical-align: top;
    +    text-align: center;
     }
     
    -TABLE.book CAPTION
    +.page-contents-header h3
     {
    -    width: auto;
    -    text-align: left;
    +    display: inline;
    +    color: #444;
    +    font-weight: bold;
    +    margin-top: 0;
    +}
    +
    +.page-contents li
    +{
    +    line-height: 1.3;
    +    padding-bottom: 0;
    +}
    +
    +@media only screen and (min-width: 66em)
    +{
    +    pre
    +    {
    +        overflow: auto;
    +    }
    +
    +    .page-contents
    +    {
    +        float: right;
    +    }
    +}
    +
    +/* Narrow layout stage 1: dropdown search, dropdown subnav */
    +@media only screen and (max-width: 66em)
    +{
    +    #top .search-container.expand-container .expand-toggle
    +    {
    +        display: block;
    +    }
    +
    +    #top .expand-container > #search-box
    +    {
    +        background: #B03931;
    +        border: 1px solid #98312A;
    +        border-bottom-left-radius: 4px;
    +        border-bottom-right-radius: 4px;
    +        display: none;
    +        padding: 0.6em;
    +        position: absolute;
    +        top: 100%;
    +        right: 0;
    +        width: auto;
    +        z-index: 5;
    +    }
    +
    +    #top .expand-container.open > #search-box
    +    {
    +        display: block;
    +    }
    +
    +    body#Home #content > .intro .pitch
    +    {
    +        width: 15em;
    +    }
    +
    +    .subnav
    +    {
    +        float: none;
    +        border-bottom-width: 1px;
    +        border-left-width: 0;
    +        border-right-width: 0;
    +        margin: 0 -1em;
    +        padding: 0.6em 1em;
    +        width: auto;
    +    }
    +
    +    body .subnav.expand-container > *
    +    {
    +        display: none;
    +    }
    +
    +    .subnav.open
    +    {
    +        padding-bottom: 1em;
    +    }
    +
    +    body.doc .subnav > ul,
    +    body.std .subnav > ul > li > ul
    +    {
    +        -moz-column-width: 17em;
    +        -webkit-column-width: 17em;
    +        column-width: 17em;
    +    }
    +
    +    body.changelog .subnav > ul
    +    {
    +        -moz-column-width: 10em;
    +        -webkit-column-width: 10em;
    +        column-width: 10em;
    +    }
    +
    +    body.doc .subnav > ul > li,
    +    body.std .subnav > ul > li > ul > li
    +    {
    +        /* avoid column breaks inside li */
    +        -webkit-column-break-inside: avoid; /* Chrome, Safari, Opera */
    +        page-break-inside: avoid; /* Firefox */
    +        break-inside: avoid; /* IE 10+ */
    +    }
    +
    +    .subnav h2
    +    {
    +        border-bottom-style: none;
    +        margin-right: 0;
    +        margin-top: 0;
    +        padding-top: 1em;
    +    }
    +
    +    /* Without JS, display the head section (h2, subhome link, ...) on one line.
    +    With JS, display the toggle, and hide the other h2. */
    +    .subnav > *
    +    {
    +        display: none;
    +    }
    +    .subnav > .head
    +    {
    +        display: block;
    +        word-spacing: 1em;
    +    }
    +    .subnav > .head > *
    +    {
    +        display: inline;
    +        word-spacing: 0;
    +    }
    +    .subnav > .head br
    +    {
    +        display: none;
    +    }
    +    .sunbav .subnav-duplicate
    +    {
    +        display: block;
    +    }
    +    .subnav > .head .separator::after
    +    {
    +        content: "\2013"; /* U+2013 EN DASH */
    +    }
    +    body.have-javascript .subnav.expand-container > .head > *,
    +    body.have-javascript .subnav.expand-container.open > .head > h2,
    +    body.have-javascript .subnav.expand-container.open > .head > .subnav-duplicate
    +    {
    +        display: none;
    +    }
    +
    +    body.have-javascript .subnav.expand-container > h2.expand-toggle,
    +    body.have-javascript .subnav.expand-container.open > .head > *,
    +    body.have-javascript .subnav.expand-container > .head br
    +    {
    +        display: block;
    +    }
    +    body.have-javascript .subnav > h2.expand-toggle
    +    {
    +        margin: 0;
    +        padding: 0;
    +    }
    +    body.have-javascript .head .separator::after
    +    {
    +        content: none;
    +    }
    +    body.have-javascript .subnav.open > h2
    +    {
    +        border-bottom-style: solid;
    +        margin-bottom: 1em;
    +    }
    +
    +    .subnav + #content
    +    {
    +        margin-left: 0;
    +    }
    +
    +    .subnav-helper
    +    {
    +        display: none;
    +    }
    +
    +    body#Home #content > .intro
    +    {
    +        padding: 0 0 1.5em;
    +    }
    +
    +    .org_list a img
    +    {
    +        padding: 0.5em 2em;
    +    }
    +}
    +
    +
    +/* Narrow layout stage 2: hamburger menu */
    +@media only screen and (max-width:54em)
    +{
    +
    +    #top > .helper
    +    {
    +        padding: 0;
    +    }
    +
    +    /* lay out navigation vertically */
    +
    +    #top #cssmenu, #top #search-box
    +    {
    +        display: block;
    +    }
    +
    +    #top .logo
    +    {
    +        width: auto;
    +    }
    +
    +    #top .logo > a
    +    {
    +        background: transparent; /* override :hover background change */
    +        margin-left: 1em;
    +    }
    +
    +    #top #cssmenu, #top .search-container
    +    {
    +        display: none;
    +    }
    +
    +    #top .expand-container.open #cssmenu,
    +    #top .expand-container .search-container
    +    {
    +        display: block;
    +    }
    +
    +    #top #cssmenu
    +    {
    +        border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    +        border-top: 1px solid #943029;
    +        clear: both;
    +    }
    +    #top #cssmenu > ul
    +    {
    +        border-bottom: 1px solid #943029;
    +        border-top: 1px solid rgba(255, 255, 255, 0.1);
    +    }
    +
    +    #top .search-container
    +    {
    +        padding: 0.6em 1em;
    +        width: auto;
    +    }
    +
    +    #top .search-container.expand-container .expand-toggle
    +    {
    +        display: none;
    +    }
    +
    +    #top .expand-container > #search-box
    +    {
    +        border: 0;
    +        display: block;
    +        padding: 0;
    +        position: static;
    +    }
    +
    +    #top .expand-container .search-container
    +    {
    +        display: none;
    +    }
    +
    +    #top .expand-container.open .search-container
    +    {
    +        display: block;
    +    }
    +
    +    #top #search-box form
    +    {
    +        display: table;
    +        width: 100%;
    +    }
    +
    +    #top #search-query, #top #search-dropdown, #top #search-submit
    +    {
    +        display: table-cell;
    +    }
    +
    +    #top #search-query
    +    {
    +        width: auto;
    +    }
    +
    +    #top #search-dropdown
    +    {
    +        width: 0; /* shrink to content size */
    +    }
    +
    +    #top #cssmenu > ul > li
    +    {
    +        float: none;
    +    }
    +
    +    #top #cssmenu > ul > li.expand-container.open > ul
    +    {
    +        border: none;
    +
    +        -moz-box-shadow: none;
    +        -webkit-box-shadow: none;
    +        box-shadow: none;
    +
    +        position: static;
    +    }
    +
    +    #top #cssmenu > ul > li.expand-container.open > ul > li > a
    +    {
    +        padding-left: 2em;
    +    }
    +
    +    /* menu button */
    +
    +    #top a.hamburger
    +    {
    +        display: inline;
    +        float: right;
    +        font-size: 2em;
    +        height: 1em;
    +        line-height: 1;
    +        padding: 0.15em 1em;
    +    }
    +    #top a.hamburger span
    +    {
    +        display: none;
    +    }
    +    #top a.hamburger::after
    +    {
    +        content: "\f0c9"; /* bars */
    +        font-family: FontAwesome;
    +    }
    +}
    +
    +/* Narrow layout stage 3: no more two column boxes */
    +@media only screen and (max-width: 40em)
    +{
    +    .boxes .row, .boxes .row .item
    +    {
    +        display: block;
    +        padding: 0;
    +        width: auto;
    +    }
    +}
    +
    +.decl_anchor {
    +    visibility: hidden;
    +    float: right;
    +    margin-top: 5px;
    +    margin-right: 5px;
    +    text-decoration: none;
     }
     
    -.leadingrow {
    -    background-color: #E4E9EF;
    -    font-size: 110%;
    +dt.d_decl:hover .decl_anchor {
    +    visibility: visible;
     }
     
    -.d_inlinecode
    -{
    -    font-family: "Consolas", "Bitstream Vera Sans Mono", "Andale Mono", "Monaco", "DejaVu Sans Mono", "Lucida Console", "monospace";
    -    /* font-size: 105%; */
    -    /* font-weight: bold; */
    -    /*color: #000010; */
    +/**
    + * Vertical centering - cross-platform way
    + */
    +.vcontainer-box {
    +    display: block;
    +}
    +.vcontainer-box:before {
    +    content: ' ';
    +    display: inline-block;
    +    vertical-align: middle;
    +    height: 100%;
     }
     
    -.d_decl {
    -    font-weight: bold;
    -    background-color: #E4E9EF;
    -    /* border-top: solid black 1px; */
    -    border-bottom: solid 2px #336600;
    -    padding: 2px 0px 2px 2px;
    +.vcontainer-element {
    +    display: inline-block;
    +    vertical-align: middle;
    +}
    +
    +.center {
    +    text-align: center;
    +}
    +
    +.dont-highlight-link > a {
    +    text-decoration: none;
    +    color: #333;
     }
     
    -.question
    +/**
    + * Version select box
    + */
    +.version-changer-container {
    +    float: right;
    +    margin-top: -4em;
    +}
    +@media only screen and (max-width:40em)
     {
    -    display: inline;
    -	/* font-weight:bold;	/* Bold font */
    -	color: #006;
    -    text-decoration: underline;
    -	cursor:pointer;		/* Cursor is like a hand when someone rolls the mouse over the question */
    +    .version-changer-container {
    +        margin-top: -2em;
    +        float: none;
    +        text-align: right;
    +    }
     }
     
    -.answer {
    -	display:none;
    +
    +/**
    + * Messages boxes.
    + */
    +.message-box {
    +    padding: 1em 1em 1em 1em;
    +    border-radius: 5px;
    +}
    +.message-box, .message-box a {
    +    color: white;
    +}
    +.message-box-red {
    +    background-color: #D60027;
    +}
    +.message-box-gray {
    +    background-color: #797979;
    +}
    +.message-box-orange {
    +    background-color:  #EC5315;
    +}
    +.message-box-green {
    +    background-color: #4EBA0F;
     }
     
    -.answer-nojs {
    -	display:block;
    +.modlist-internal-separator {
    +    height: 1em;
    +    border-top: 1px solid #ccc;
    +    margin-top: 1em;
    +    margin-bottom: 1em;
    +    padding-top: 0.5em;
     }
     
    -.nobr {
    -    white-space:nowrap;
    +/* Group related info together */
    +.panel
    +{
    +    padding: 0.3em 0.6em;
    +    border-radius: 5px;
    +    background-color: #F5F5F5;
    +    border: 1px solid #E6E6E6;
     }
     
    diff --git a/ctod.dd b/ctod.dd
    deleted file mode 100644
    index 106c40b01b..0000000000
    --- a/ctod.dd
    +++ /dev/null
    @@ -1,1606 +0,0 @@
    -Ddoc
    -
    -$(COMMUNITY Programming in D for C Programmers,
    -
    -$(COMMENT $(BLOCKQUOTE William Nerdspeare,
    -Et tu, D? Then fall, C!
    -))
    -
    -
    -
    -$(P Every experienced C programmer accumulates a series of idioms and techniques
    -which become second nature. Sometimes, when learning a new language, those
    -idioms can be so comfortable it's hard to see how to do the equivalent in the
    -new language. So here's a collection of common C techniques, and how to do the
    -corresponding task in D.
    -)
    -
    -$(P Since C does not have object-oriented features, there's a separate section
    -for object-oriented issues
    -Programming in D for C++ Programmers.
    -)
    -
    -$(P The C preprocessor is covered in
    -$(LINK2 pretod.html, The C Preprocessor vs D).
    -)
    -
    -$(UL
    -	$(LI $(LINK2 #sizeof, Getting the Size of a Type))
    -	$(LI $(LINK2 #maxmin, Get the max and min values of a type))
    -	$(LI $(LINK2 #types, Primitive Types))
    -	$(LI $(LINK2 #floating, Special Floating Point Values))
    -	$(LI $(LINK2 #modulus, Remainder after division of floating point numbers))
    -	$(LI $(LINK2 #nans, Dealing with NANs in floating point compares))
    -	$(LI $(LINK2 #assert, Asserts))
    -	$(LI $(LINK2 #arrayinit, Initializing all elements of an array))
    -	$(LI $(LINK2 #arrayloop, Looping through an array))
    -	$(LI $(LINK2 #arraycreate, Creating an array of variable size))
    -	$(LI $(LINK2 #strcat, String Concatenation))
    -	$(LI $(LINK2 #printf, Formatted printing))
    -	$(LI $(LINK2 #forwardfunc, Forward referencing functions))
    -	$(LI $(LINK2 #funcvoid, Functions that have no arguments))
    -	$(LI $(LINK2 #labeledbreak, Labeled break and continue statements))
    -	$(LI $(LINK2 #goto, Goto Statements))
    -	$(LI $(LINK2 #tagspace, Struct tag name space))
    -	$(LI $(LINK2 #stringlookup, Looking up strings))
    -	$(LI $(LINK2 #align, Setting struct member alignment))
    -	$(LI $(LINK2 #anonymous, Anonymous Structs and Unions))
    -	$(LI $(LINK2 #declaring, Declaring struct types and variables))
    -	$(LI $(LINK2 #fieldoffset, Getting the offset of a struct member))
    -	$(LI $(LINK2 #unioninit, Union initializations))
    -	$(LI $(LINK2 #structinit, Struct initializations))
    -	$(LI $(LINK2 #arrayinit2, Array initializations))
    -	$(LI $(LINK2 #stringlit, Escaped String Literals))
    -	$(LI $(LINK2 #ascii, Ascii vs Wide Characters))
    -	$(LI $(LINK2 #arrayenum, Arrays that parallel an enum))
    -	$(LI $(LINK2 #typedefs, Creating a new type with typedef))
    -	$(LI $(LINK2 #structcmp, Comparing structs))
    -	$(LI $(LINK2 #stringcmp, Comparing strings))
    -	$(LI $(LINK2 #sort, Sorting arrays))
    -	$(LI $(LINK2 #volatile, Volatile memory access))
    -	$(LI $(LINK2 #strings, String literals))
    -	$(LI $(LINK2 #traversal, Data Structure Traversal))
    -	$(LI $(LINK2 #ushr, Unsigned Right Shift))
    -	$(LI $(LINK2 #closures, Dynamic Closures))
    -	$(LI $(LINK2 #variadic, Variadic Function Parameters))
    -)
    -
    -
    -

    Getting the Size of a Type

    - -

    The C Way

    - -$(CCODE -sizeof(int) -sizeof(char *) -sizeof(double) -sizeof(struct Foo) -) - -

    The D Way

    - -

    Use the size property:

    - ----------------------------- -int.sizeof -(char *).sizeof -double.sizeof -Foo.sizeof ----------------------------- - -
    -

    Get the max and min values of a type

    - -

    The C Way

    - -$(CCODE -#include <limits.h> -#include <math.h> - -CHAR_MAX -CHAR_MIN -ULONG_MAX -DBL_MIN -) - -

    The D Way

    - ----------------------------- -char.max -char.min -ulong.max -double.min ----------------------------- - -
    -

    Primitive Types

    - -

    C to D types

    - -$(CCODE -bool => bit -char => char -signed char => byte -unsigned char => ubyte -short => short -unsigned short => ushort -wchar_t => wchar -int => int -unsigned => uint -long => int -unsigned long => uint -long long => long -unsigned long long => ulong -float => float -double => double -long double => real -_Imaginary long double => ireal -_Complex long double => creal -) -

    - Although char is an unsigned 8 bit type, and - wchar is an unsigned 16 bit type, they have their own separate types - in order to aid overloading and type safety. -

    - Ints and unsigneds in C are of varying size; not so in D. - -


    -

    Special Floating Point Values

    - -

    The C Way

    - -$(CCODE -#include <fp.h> - -NAN -INFINITY - -#include <float.h> - -DBL_DIG -DBL_EPSILON -DBL_MANT_DIG -DBL_MAX_10_EXP -DBL_MAX_EXP -DBL_MIN_10_EXP -DBL_MIN_EXP -) - -

    The D Way

    - ----------------------------- -double.nan -double.infinity -double.dig -double.epsilon -double.mant_dig -double.max_10_exp -double.max_exp -double.min_10_exp -double.min_exp ----------------------------- - -
    -

    Remainder after division of floating point numbers

    - -

    The C Way

    - -$(CCODE -#include <math.h> - -float f = fmodf(x,y); -double d = fmod(x,y); -long double r = fmodl(x,y); -) - -

    The D Way

    - -D supports the remainder ('%') operator on floating point operands: - ----------------------------- -float f = x % y; -double d = x % y; -real r = x % y; ----------------------------- - -
    -

    Dealing with NANs in floating point compares

    - -

    The C Way

    - - C doesn't define what happens if an operand to a compare - is NAN, and few C compilers check for it (the Digital Mars - C compiler is an exception, DM's compilers do check for NAN operands). - -$(CCODE -#include <math.h> - -if (isnan(x) || isnan(y)) - result = FALSE; -else - result = (x < y); -) - -

    The D Way

    - - D offers a full complement of comparisons and operators - that work with NAN arguments. - ----------------------------- -result = (x < y); // false if x or y is nan ----------------------------- - -
    -

    Asserts are a necessary part of any good defensive coding strategy

    - -

    The C Way

    -

    -C doesn't directly support assert, but does support __FILE__ -and __LINE__ from which an assert macro can be built. In fact, -there appears to be practically no other use for __FILE__ and __LINE__. - -$(CCODE -#include <assert.h> - -assert(e == 0); -) - -

    The D Way

    - -D simply builds assert into the language: - ----------------------------- -assert(e == 0); ----------------------------- - -
    -

    Initializing all elements of an array

    - -

    The C Way

    - -$(CCODE -#define ARRAY_LENGTH 17 -int array[ARRAY_LENGTH]; -for (i = 0; i < ARRAY_LENGTH; i++) - array[i] = value; -) - -

    The D Way

    - ----------------------------- -int array[17]; -array[] = value; ----------------------------- - -
    -

    Looping through an array

    - -

    The C Way

    -

    - The array length is defined separately, or a clumsy - sizeof() expression is used to get the length. - -$(CCODE -#define ARRAY_LENGTH 17 -int array[ARRAY_LENGTH]; -for (i = 0; i < ARRAY_LENGTH; i++) - func(array[i]); -) - -or: - -$(CCODE -int array[17]; -for (i = 0; i < sizeof(array) / sizeof(array[0]); i++) - func(array[i]); -) - -

    The D Way

    - -The length of an array is accessible through the property "length". - ----------------------------- -int array[17]; -for (i = 0; i < array.length; i++) - func(array[i]); ----------------------------- - -or even better: - ----------------------------- -int array[17]; -foreach (int value; array) - func(value); ----------------------------- - - -
    -

    Creating an array of variable size

    - -

    The C Way

    - - C cannot do this with arrays. It is necessary to create a separate - variable for the length, and then explicitly manage the size of - the array: - -$(CCODE -#include <stdlib.h> - -int array_length; -int *array; -int *newarray; - -newarray = (int *) - realloc(array, (array_length + 1) * sizeof(int)); -if (!newarray) - error("out of memory"); -array = newarray; -array[array_length++] = x; -) - -

    The D Way

    - - D supports dynamic arrays, which can be easily resized. D supports - all the requisite memory management. - ----------------------------- -int[] array; - -array.length = array.length + 1; -array[array.length - 1] = x; ----------------------------- - -
    -

    String Concatenation

    - -

    The C Way

    - - There are several difficulties to be resolved, like - when can storage be freed, dealing with null pointers, - finding the length of the strings, and memory allocation: - -$(CCODE -#include <string.h> - -char *s1; -char *s2; -char *s; - -// Concatenate s1 and s2, and put result in s -free(s); -s = (char *)malloc((s1 ? strlen(s1) : 0) + - (s2 ? strlen(s2) : 0) + 1); -if (!s) - error("out of memory"); -if (s1) - strcpy(s, s1); -else - *s = 0; -if (s2) - strcpy(s + strlen(s), s2); - -// Append "hello" to s -char hello[] = "hello"; -char *news; -size_t lens = s ? strlen(s) : 0; -news = (char *) - realloc(s, (lens + sizeof(hello) + 1) * sizeof(char)); -if (!news) - error("out of memory"); -s = news; -memcpy(s + lens, hello, sizeof(hello)); -) - -

    The D Way

    - - D overloads the operators ~ and ~= for char and wchar arrays to mean - concatenate and append, respectively: - ----------------------------- -char[] s1; -char[] s2; -char[] s; - -s = s1 ~ s2; -s ~= "hello"; ----------------------------- - -
    -

    Formatted printing

    - -

    The C Way

    - - printf() is the general purpose formatted print routine: - -$(CCODE -#include <stdio.h> - -printf("Calling all cars %d times!\n", ntimes); -) - -

    The D Way

    - - What can we say? printf() rules: - ----------------------------- -printf("Calling all cars %d times!\n", ntimes); ----------------------------- - - writefln() improves on printf() by being type-aware and type-safe: - ------------------------ -import std.stdio; - -writefln("Calling all cars %s times!", ntimes); ------------------------ - -
    -

    Forward referencing functions

    - -

    The C Way

    - - Functions cannot be forward referenced. Hence, to call a function - not yet encountered in the source file, it is necessary to insert - a function declaration lexically preceding the call. - -$(CCODE -void forwardfunc(); - -void myfunc() -{ - forwardfunc(); -} - -void forwardfunc() -{ - ... -} -) - -

    The D Way

    - - The program is looked at as a whole, and so not only is it not - necessary to code forward declarations, it is not even allowed! - D avoids the tedium and errors associated with writing forward - referenced function declarations twice. - Functions can be defined in any order. - ----------------------------- -void myfunc() -{ - forwardfunc(); -} - -void forwardfunc() -{ - ... -} ----------------------------- - -
    -

    Functions that have no arguments

    - -

    The C Way

    - -$(CCODE -void function(void); -) - -

    The D Way

    - - D is a strongly typed language, so there is no need to explicitly - say a function takes no arguments, just don't declare it has having - arguments. - ----------------------------- -void function() -{ - ... -} ----------------------------- - -
    -

    Labeled break and continue statements

    - -

    The C Way

    - - Break and continue statements only apply to the innermost nested loop or - switch, so a multilevel break must use a goto: - -$(CCODE - for (i = 0; i < 10; i++) - { - for (j = 0; j < 10; j++) - { - if (j == 3) - goto Louter; - if (j == 4) - goto L2; - } - L2: - ; - } -Louter: - ; -) - -

    The D Way

    - - Break and continue statements can be followed by a label. The label - is the label for an enclosing loop or switch, and the break applies - to that loop. - ----------------------------- -Louter: - for (i = 0; i < 10; i++) - { - for (j = 0; j < 10; j++) - { - if (j == 3) - break Louter; - if (j == 4) - continue Louter; - } - } - // break Louter goes here ----------------------------- - -
    -

    Goto Statements

    - -

    The C Way

    - - The much maligned goto statement is a staple for professional C coders. - It's - necessary to make up for sometimes inadequate control flow statements. - -

    The D Way

    - - Many C-way goto statements can be eliminated with the D feature of - labeled - break and continue statements. But D is a practical language for - practical - programmers who know when the rules need to be broken. So of course D - supports goto statements. - -
    -

    Struct tag name space

    - -

    The C Way

    - - It's annoying to have to put the struct keyword every time a type is specified, - so a common idiom is to use: - -$(CCODE -typedef struct ABC { ... } ABC; -) - -

    The D Way

    - - Struct tag names are not in a separate name space, they are in the same name - space as ordinary names. Hence: - ----------------------------- -struct ABC { ... } ----------------------------- - -
    -

    Looking up strings

    - -

    The C Way

    - - Given a string, compare the string against a list of possible - values and take action based on which one it is. A typical use - for this might be command line argument processing. - -$(CCODE -#include <string.h> -void dostring(char *s) -{ - enum Strings { Hello, Goodbye, Maybe, Max }; - static char *table[] = { "hello", "goodbye", "maybe" }; - int i; - - for (i = 0; i < Max; i++) - { - if (strcmp(s, table[i]) == 0) - break; - } - switch (i) - { - case Hello: ... - case Goodbye: ... - case Maybe: ... - default: ... - } -} -) - - The problem with this is trying to maintain 3 parallel data - structures, the enum, the table, and the switch cases. If there - are a lot of values, the connection between the 3 may not be so - obvious when doing maintenance, and so the situation is ripe for - bugs. - - Additionally, if the number of values becomes large, a binary or - hash lookup will yield a considerable performance increase over - a simple linear search. But coding these can be time consuming, - and they need to be debugged. It's typical that such just never - gets done. - -

    The D Way

    - - D extends the concept of switch statements to be able to handle - strings as well as numbers. Then, the way to code the string - lookup becomes straightforward: - ----------------------------- -void dostring(char[] s) -{ - switch (s) - { - case "hello": ... - case "goodbye": ... - case "maybe": ... - default: ... - } -} ----------------------------- - - Adding new cases becomes easy. The compiler can be relied on - to generate a fast lookup scheme for it, eliminating the bugs - and time required in hand-coding one. - -
    -

    Setting struct member alignment

    - -

    The C Way

    - - It's done through a command line switch which affects the entire - program, and woe results if any modules or libraries didn't get - recompiled. To address this, $(D #pragma)s are used: - -$(CCODE -#pragma pack(1) -struct ABC -{ - ... -}; -#pragma pack() -) - - But $(D #pragma)s are nonportable both in theory and in practice from - compiler to compiler. - -

    The D Way

    - - $(P D has a syntax for setting the alignment that is common - to all D compilers. The actual alignment done is compatible - with the companion C compiler's alignment, for ABI compatibility. - To match a particular layout across architectures, use - $(D align(1)) and manually specify it. - ) - ----------------------------- -struct ABC -{ - int z; // z is aligned to the default - - align (1) int x; // x is byte aligned - align (4) - { - ... // declarations in {} are dword aligned - } - align (2): // switch to word alignment from here on - - int y; // y is word aligned -} ----------------------------- - -
    -

    Anonymous Structs and Unions

    - -Sometimes, it's nice to control the layout of a struct with nested structs and unions. - -

    The C Way

    - - C doesn't allow anonymous structs or unions, which means that dummy tag names - and dummy members are necessary: - -$(CCODE -struct Foo -{ - int i; - union Bar - { - struct Abc { int x; long y; } _abc; - char *p; - } _bar; -}; - -#define x _bar._abc.x -#define y _bar._abc.y -#define p _bar.p - -struct Foo f; - -f.i; -f.x; -f.y; -f.p; -) - - Not only is it clumsy, but using macros means a symbolic debugger won't understand - what is being done, and the macros have global scope instead of struct scope. - -

    The D Way

    - - Anonymous structs and unions are used to control the layout in a - more natural manner: - ----------------------------- -struct Foo -{ - int i; - union - { - struct { int x; long y; } - char* p; - } -} - -Foo f; - -f.i; -f.x; -f.y; -f.p; ----------------------------- - -
    -

    Declaring struct types and variables

    - -

    The C Way

    - - $(P Is to do it in one statement ending with a semicolon:) - -$(CCODE -struct Foo { int x; int y; } foo; -) - - $(P Or to separate the two:) - -$(CCODE -struct Foo { int x; int y; }; // note terminating ; -struct Foo foo; -) - -

    The D Way

    - - $(P Struct definitions and declarations can't be done in the same - statement: - ) - ----------------------------- -struct Foo { int x; int y; } // note there is no terminating ; -Foo foo; ----------------------------- - - $(P which means that the terminating ; can be dispensed with, - eliminating the confusing difference between struct {} and function - block {} in how semicolons are used. - ) - -
    -

    Getting the offset of a struct member

    - -

    The C Way

    - - Naturally, another macro is used: - -$(CCODE -#include <stddef> -struct Foo { int x; int y; }; - -off = offsetof(Foo, y); -) - -

    The D Way

    - - An offset is just another property: - ----------------------------- -struct Foo { int x; int y; } - -off = Foo.y.offsetof; ----------------------------- - -
    -

    Union Initializations

    - -

    The C Way

    - - Unions are initialized using the "first member" rule: - -$(CCODE -union U { int a; long b; }; -union U x = { 5 }; // initialize member 'a' to 5 -) - - Adding union members or rearranging them can have disastrous consequences - for any initializers. - -

    The D Way

    - - In D, which member is being initialized is mentioned explicitly: - ----------------------------- -union U { int a; long b; } -U x = { a:5 }; ----------------------------- - - avoiding the confusion and maintenance problems. - -
    -

    Struct Initializations

    - -

    The C Way

    - - Members are initialized by their position within the { }s: - -$(CCODE -struct S { int a; int b; }; -struct S x = { 5, 3 }; -) - - This isn't much of a problem with small structs, but when there - are numerous members, it becomes tedious to get the initializers - carefully lined up with the field declarations. Then, if members are - added or rearranged, all the initializations have to be found and - modified appropriately. This is a minefield for bugs. - -

    The D Way

    - - Member initialization can be done explicitly: - ----------------------------- -struct S { int a; int b; } -S x = { b:3, a:5 }; ----------------------------- - - The meaning is clear, and there no longer is a positional dependence. - -
    -

    Array Initializations

    - -

    The C Way

    - - C initializes array by positional dependence: -$(CCODE -int a[3] = { 3,2,2 }; -) - Nested arrays may or may not have the { }: -$(CCODE -int b[3][2] = { 2,3, {6,5}, 3,4 }; -) - -

    The D Way

    - - D does it by positional dependence too, but an index can be used as well. - The following all produce the same result: - ----------------------------- -int[3] a = [ 3, 2, 0 ]; -int[3] a = [ 3, 2 ]; // unsupplied initializers are 0, just like in C -int[3] a = [ 2:0, 0:3, 1:2 ]; -int[3] a = [ 2:0, 0:3, 2 ]; // if not supplied, the index is the - // previous one plus one. ----------------------------- - This can be handy if the array will be indexed by an enum, and the order of - enums may be changed or added to: - ----------------------------- -enum color { black, red, green } -int[3] c = [ black:3, green:2, red:5 ]; ----------------------------- - Nested array initializations must be explicit: ----------------------------- -int[2][3] b = [ [2,3], [6,5], [3,4] ]; - -int[2][3] b = [[2,6,3],[3,5,4]]; // error ----------------------------- - -
    -

    Escaped String Literals

    - -

    The C Way

    - - C has problems with the DOS file system because a \ is an escape in a string. To specifiy file c:\root\file.c: -$(CCODE -char file[] = "c:\\root\\file.c"; -) -This gets even more unpleasant with regular expressions. -Consider the escape sequence to match a quoted string: -$(CCODE -/"[^\\]*(\\.[^\\]*)*"/ -) -

    In C, this horror is expressed as: -$(CCODE -char quoteString[] = "\"[^\\\\]*(\\\\.[^\\\\]*)*\""; -) -

    The D Way

    - - Within strings, it is WYSIWYG (what you see is what you get). - Escapes are in separate strings. So: - ----------------------------- -char[] file = `c:\root\file.c`; -char[] quoteString = \" r"[^\\]*(\\.[^\\]*)*" \"; ----------------------------- - - The famous hello world string becomes: ----------------------------- -char[] hello = "hello world" \n; ----------------------------- - -
    -

    Ascii vs Wide Characters

    - -

    Modern programming requires that wchar strings be supported in an easy way, for internationalization of the programs. - -

    The C Way

    - - C uses the wchar_t and the L prefix on strings: -$(CCODE -#include <wchar.h> -char foo_ascii[] = "hello"; -wchar_t foo_wchar[] = L"hello"; -) -Things get worse if code is written to be both ascii and wchar compatible. -A macro is used to switch strings from ascii to wchar: -$(CCODE -#include <tchar.h> -tchar string[] = TEXT("hello"); -) -

    The D Way

    - -The type of a string is determined by semantic analysis, so there is no need to wrap strings in a macro call: ------------------------------ -char[] foo_ascii = "hello"; // string is taken to be ascii -wchar[] foo_wchar = "hello"; // string is taken to be wchar ------------------------------ - -
    -

    Arrays that parallel an enum

    - -

    The C Way

    - - Consider: -$(CCODE -enum COLORS { red, blue, green, max }; -char *cstring[max] = {"red", "blue", "green" }; -) - This is fairly easy to get right because the number of entries is small. But suppose it gets to be fairly large. Then it can get difficult to maintain correctly when new entries are added. - -

    The D Way

    ------------------------------ -enum COLORS { red, blue, green } - -char[][COLORS.max + 1] cstring = -[ - COLORS.red : "red", - COLORS.blue : "blue", - COLORS.green : "green", -]; ------------------------------ - -Not perfect, but better. - -
    -

    Creating a new type with typedef

    - -

    The C Way

    - - Typedefs in C are weak, that is, they really do not introduce - a new type. The compiler doesn't distinguish between a typedef - and its underlying type. - -$(CCODE -typedef void *Handle; -void foo(void *); -void bar(Handle); - -Handle h; -foo(h); // coding bug not caught -bar(h); // ok -) - - The C solution is to create a dummy struct whose sole - purpose is to get type checking and overloading on the new type. - -$(CCODE -struct Handle__ { void *value; } -typedef struct Handle__ *Handle; -void foo(void *); -void bar(Handle); - -Handle h; -foo(h); // syntax error -bar(h); // ok -) - - Having a default value for the type involves defining a macro, - a naming convention, and then pedantically following that convention: - -$(CCODE -#define HANDLE_INIT ((Handle)-1) - -Handle h = HANDLE_INIT; -h = func(); -if (h != HANDLE_INIT) - ... -) - - For the struct solution, things get even more complex: - -$(CCODE -struct Handle__ HANDLE_INIT; - -void init_handle() // call this function upon startup -{ - HANDLE_INIT.value = (void *)-1; -} - -Handle h = HANDLE_INIT; -h = func(); -if (memcmp(&h,&HANDLE_INIT,sizeof(Handle)) != 0) - ... -) - - There are 4 names to remember: $(D Handle, HANDLE_INIT, - struct Handle__, value). - -

    The D Way

    - - No need for idiomatic constructions like the above. Just write: - ------------------------------ -typedef void* Handle; -void foo(void*); -void bar(Handle); - -Handle h; -foo(h); -bar(h); ------------------------------ - - To handle a default value, add an initializer to the typedef, - and refer to it with the $(D .init) property: - ------------------------------ -typedef void* Handle = cast(void*)(-1); -Handle h; -h = func(); -if (h != Handle.init) - ... ------------------------------ - - There's only one name to remember: $(D Handle). - -
    -

    Comparing structs

    - -

    The C Way

    - - While C defines struct assignment in a simple, convenient manner: - -$(CCODE -struct A x, y; -... -x = y; -) - - it does not for struct comparisons. Hence, to compare two struct - instances for equality: - -$(CCODE -#include <string.h> - -struct A x, y; -... -if (memcmp(&x, &y, sizeof(struct A)) == 0) - ... -) - - Note the obtuseness of this, coupled with the lack of any kind - of help from the language with type checking. -

    - - There's a nasty bug lurking in the memcmp(). - The layout of a struct, due to alignment, can have 'holes' in it. - C does not guarantee those holes are assigned any values, and so - two different struct instances can have the same value for each member, - but compare different because the holes contain different garbage. - -

    The D Way

    - - D does it the obvious, straightforward way: - ------------------------------ -A x, y; -... -if (x == y) - ... ------------------------------ - - -
    -

    Comparing strings

    - -

    The C Way

    - - The library function strcmp() is used: -$(CCODE -char string[] = "hello"; - -if (strcmp(string, "betty") == 0) // do strings match? - ... -) - - C uses 0 terminated strings, so the C way has an inherent - inefficiency in constantly scanning for the terminating 0. - -

    The D Way

    - - Why not use the == operator? - ------------------------------ -char[] string = "hello"; - -if (string == "betty") - ... ------------------------------ - - D strings have the length stored separately from the string. - Thus, the implementation of string compares can be much faster - than in C (the difference being equivalent to the difference - in speed between the C memcmp() and strcmp()). -

    - - D supports comparison operators on strings, too: - ------------------------------ -char[] string = "hello"; - -if (string < "betty") - ... ------------------------------ - - which is useful for sorting/searching. - -


    -

    Sorting arrays

    - -

    The C Way

    - - Although many C programmers tend to reimplmement bubble sorts - over and over, the right way to sort in C is to use qsort(): - -$(CCODE -int compare(const void *p1, const void *p2) -{ - type *t1 = (type *)p1; - type *t2 = (type *)p2; - - return *t1 - *t2; -} - -type array[10]; -... -qsort(array, sizeof(array)/sizeof(array[0]), - sizeof(array[0]), compare); -) - - A compare() must be written for each type, and much careful - typo-prone code needs to be written to make it work. - - -

    The D Way

    - - Sorting couldn't be easier: - ------------------------------ -type[] array; -... -array.sort; // sort array in-place ------------------------------ - -
    -

    Volatile memory access

    - -

    The C Way

    - - To access volatile memory, such as shared memory - or memory mapped I/O, a pointer to volatile is created: -$(CCODE -volatile int *p = address; - -i = *p; -) - -

    The D Way

    - - D has volatile as a statement type, not as a type modifier: - ------------------------------ -int* p = address; - -volatile { i = *p; } ------------------------------ - -
    -

    String literals

    - -

    The C Way

    - - String literals in C cannot span multiple lines, so to have - a block of text it is necessary to use \ line splicing: - -$(CCODE -"This text spans\n\ -multiple\n\ -lines\n" -) - - If there is a lot of text, this can wind up being tedious. - -

    The D Way

    - - String literals can span multiple lines, as in: - ------------------------------ -"This text spans -multiple -lines -" ------------------------------ - - So blocks of text can just be cut and pasted into the D - source. - -
    -

    Data Structure Traversal

    - -

    The C Way

    - - Consider a function to traverse a recursive data structure. - In this example, there's a simple symbol table of strings. - The data structure is an array of binary trees. - The code needs to do an exhaustive search of it to find - a particular string in it, and determine if it is a unique - instance. -

    - - To make this work, a helper function $(D membersearchx) - is needed to recursively - walk the trees. The helper function needs to read and write - some context outside of the trees, so a custom $(D struct Paramblock) - is created and a pointer to it is used to maximize efficiency. - -$(CCODE -struct Symbol -{ - char *id; - struct Symbol *left; - struct Symbol *right; -}; - -struct Paramblock -{ - char *id; - struct Symbol *sm; -}; - -static void membersearchx(struct Paramblock *p, struct Symbol *s) -{ - while (s) - { - if (strcmp(p->id,s->id) == 0) - { - if (p->sm) - error("ambiguous member %s\n",p->id); - p->sm = s; - } - - if (s->left) - membersearchx(p,s->left); - s = s->right; - } -} - -struct Symbol *symbol_membersearch(Symbol *table[], int tablemax, char *id) -{ - struct Paramblock pb; - int i; - - pb.id = id; - pb.sm = NULL; - for (i = 0; i < tablemax; i++) - { - membersearchx(pb, table[i]); - } - return pb.sm; -} -) - -

    The D Way

    - - This is the same algorithm in D, and it shrinks dramatically. - Since nested functions have access to the lexically enclosing - function's variables, there's no need for a Paramblock or - to deal with its bookkeeping details. The nested helper function - is contained wholly within the function that needs it, - improving locality and maintainability. -

    - - The performance of the two versions is indistinguishable. - ------------------------------ -class Symbol -{ char[] id; - Symbol left; - Symbol right; -} - -Symbol symbol_membersearch(Symbol[] table, char[] id) -{ Symbol sm; - - void membersearchx(Symbol s) - { - while (s) - { - if (id == s.id) - { - if (sm) - error("ambiguous member %s\n", id); - sm = s; - } - - if (s.left) - membersearchx(s.left); - s = s.right; - } - } - - for (int i = 0; i < table.length; i++) - { - membersearchx(table[i]); - } - return sm; -} ------------------------------ - -


    -

    Unsigned Right Shift

    - -

    The C Way

    - - The right shift operators >> and >>= are signed - shifts if the left operand is a signed integral type, and - are unsigned right shifts if the left operand is an unsigned - integral type. To produce an unsigned right shift on an int, - a cast is necessary: - -$(CCODE -int i, j; -... -j = (unsigned)i >> 3; -) - - If $(D i) is an $(D int), this works fine. But if $(D i) is - of a type created with typedef, - -$(CCODE -myint i, j; -... -j = (unsigned)i >> 3; -) - - and $(D myint) happens to be a $(D long int), then the cast to - unsigned - will silently throw away the most significant bits, corrupting - the answer. - -

    The D Way

    - - D has the right shift operators >> and >>= which - behave as they do in C. But D also has explicitly unsigned - right shift operators >>> and >>>= which will - do an unsigned right shift regardless of the sign of the left - operand. Hence, - ------------------------------ -myint i, j; -... -j = i >>> 3; ------------------------------ - - avoids the unsafe cast and will work as expected with any integral - type. - -
    -

    Dynamic Closures

    - -

    The C Way

    - - Consider a reusable container type. In order to be reusable, - it must support a way to apply arbitrary code to each element - of the container. This is done by creating an $(I apply) function - that accepts a function pointer to which is passed each - element of the container contents. -

    - - A generic context pointer is also needed, represented here by - $(D void *p). The example here is of a trivial container - class that holds an array of ints, and a user of that container - that computes the maximum of those ints. - -$(CCODE -void apply(void *p, int *array, int dim, void (*fp)(void *, int)) -{ - for (int i = 0; i < dim; i++) - fp(p, array[i]); -} - -struct Collection -{ - int array[10]; -}; - -void comp_max(void *p, int i) -{ - int *pmax = (int *)p; - - if (i > *pmax) - *pmax = i; -} - -void func(struct Collection *c) -{ - int max = INT_MIN; - - apply(&max, c->array, sizeof(c->array)/sizeof(c->array[0]), comp_max); -} -) - - $(P While this works, it isn't very flexible.) - -

    The D Way

    - - The D version makes use of $(I delegates) to transmit - context information for the $(I apply) function, - and $(I nested functions) both to capture context - information and to improve locality. - ----------------------------- -class Collection -{ - int[10] array; - - void apply(void delegate(int) fp) - { - for (int i = 0; i < array.length; i++) - fp(array[i]); - } -} - -void func(Collection c) -{ - int max = int.min; - - void comp_max(int i) - { - if (i > max) - max = i; - } - - c.apply(&comp_max); -} ------------------------------ - - Pointers are eliminated, as well as casting and generic - pointers. The D version is fully type safe. - An alternate method in D makes use of $(I function literals): - ------------------------------ -void func(Collection c) -{ - int max = int.min; - - c.apply(delegate(int i) { if (i > max) max = i; } ); -} ------------------------------ - - eliminating the need to create irrelevant function names. - -
    -

    Variadic Function Parameters

    - - The task is to write a function that takes a varying - number of arguments, such as a function that sums - its arguments. - -

    The C Way

    - -$(CCODE -#include <stdio.h> -#include <stdarg.h> - -int $(B sum)(int dim, ...) -{ int i; - int s = 0; - va_list ap; - - va_start(ap, dim); - for (i = 0; i < dim; i++) - s += va_arg(ap, int); - va_end(ap); - return s; -} - -int main() -{ - int i; - - i = $(B sum)(3, 8,7,6); - printf("sum = %d\n", i); - - return 0; -} -) - - There are two problems with this. The first is that the - $(D sum) function needs to know how many arguments were - supplied. It has to be explicitly written, and it can get - out of sync with respect to the actual number of arguments - written. - The second is that there's no way to check that the - types of the arguments provided really were ints, and not - doubles, strings, structs, etc. - -

    The D Way

    - - The ... following an array parameter declaration means that - the trailing arguments are collected together to form - an array. The arguments are type checked against the array - type, and the number of arguments becomes a property - of the array: - ------------------------------ -import std.stdio; - -int $(B sum)(int[] values ...) -{ - int s = 0; - - foreach (int x; values) - s += x; - return s; -} - -int main() -{ - int i; - - i = $(B sum)(8,7,6); - writefln("sum = %d", i); - - return 0; -} ------------------------------ -) - -Macros: - TITLE=Programming in D for C Programmers - WIKI=ctod - CATEGORY_OVERVIEW=$0 diff --git a/d-keyring.gpg b/d-keyring.gpg new file mode 100644 index 0000000000..f83945bc55 Binary files /dev/null and b/d-keyring.gpg differ diff --git a/d-keyring.gpg.sig b/d-keyring.gpg.sig new file mode 100644 index 0000000000..825a479799 Binary files /dev/null and b/d-keyring.gpg.sig differ diff --git a/d-security.asc b/d-security.asc new file mode 100644 index 0000000000..0beed48c63 --- /dev/null +++ b/d-security.asc @@ -0,0 +1,63 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFs+Y9YBEADVO7yaz+dFWq1Rioas+bfX07VC5X/dBNY/bRHPSE3k196+wHqs +j1jEigg0BDpR4bYBZeHlv65cFWu6SABLXBV7Y99kz2vCfJFRbEvDsW3dl3PYIIKM +8kASwDEy/xmHUvYOsg8rzoWqQHApTp9HHarq6cyN5QECJIeAdwNali67wd8Q3hYJ +QSspjgtSIdVNWsEXBvPJjZXE/hsYKs8uZcx5p30fCyz96uRI6/z307WNU8yXy8Co +HyyJBH68Gnbw0bYjU6NYpDZfgAbStdlU2vd0XYSWjWxcR3aqzqyWOt7gTtiCWD9I +dshMGpGnqglHt/uvayr9K4uQZ6fpY2hGuw8z7rPzPN5KFSpDaznBBZqIzKFb1s/O +/9pu3ejH0n24sFIyf83HM7M2NxBb7+krKObjSrUYrzs5mReNwTvKbzWlz03PY6Pr +FafKbhC2jO/15VppZBWXZP4tF5Zpz7QG6kBNn1buPteUQ+X1wL5QXUAjsS/OvQM/ +ctLZSMADVGRyiTnMdNMP7pJ1gTUXPv3zW6JLzJQ3SLcHj9oke71bJWd5wTV2kXHl +GLIkKHiVR9G9o2CZqWkdDJXpYT1UYwOEqlKai8iqVmyIOi8gwBo7xhYfxDEDNHOy +Iz2ie1lG/l5sy9qmeSt32Gr4YSfW2xujwuLpaQsWkeUSYrwZogW+Tla3owARAQAB +tChETGFuZyBTZWN1cml0eSBUZWFtIDxzZWN1cml0eUBkbGFuZy5vcmc+iQJFBBMB +CgAvFiEE4Fqzww7Ax91W2ZsMj/BJspY47dIFAls+Y9YCGwMFCQPCZwACFQoCHgEC +F4AACgkQj/BJspY47dKL7w//dfj9bg8XZimrp0JQ3FAlTuwb1AevpTkscln+gbzA +jlNNOFrZHWw7FaKbPCKMc0n+8yNiVRpBEZSQ7QsTRkqvYNuHL/lWPH5kRjk1FW8a +hDxgaAt7cV8DhPyfXM3OO0KnTAVzW89hfIVlMXHiQYJZynmFRV3R1VJnVfMGBbqn +PP2XZAcV0FITX2FAY0AUjGIKFfKzN5WkmX8MhZd6+8gX+7VWVlQJJS6/9INwf5JX +Hfh0WxygycT4WOghQxcsc7YEmhnfpwvKOQVppqvE4FDi48HFhS8cXtqQ3oQJnLAt +fgAjFx49gOZ+CoigpgaRqDjeAt5fF8MJcjcGjjA6HeXzrcr/85HM5r8PUPPZnjFe +4s/6MrKduIEdy6F1heQEmOf/ywAYW6Om0GCkfuk6rDxp/5wMStLmKQjNJril6TLt +lX1V4A+Kmjw/JWDXS9obxO7xWf0KVqTYKB4dHyyvflqGge3uDuhl1XYzE7ad9hib +4p2hXSJbAvgXnvFiII+1fHtpyu1aAvPVeZgaWsMQnps2sfDg0W8lU8Ae5BRBbYHb +gO+dJ3UikGTLHTv1hfw7TvvZvNoDyjN0in+NqzBdWW4MCG1hZ91DYwXF1F8htXjd +jUUmqocjVduPeqRrrPhVGgYHlfSiluWC6aWtwTzBhO7uu9T4o70o45DWHnJRjKK1 +7ruJAjMEEAEKAB0WIQSP2401evRoqUKKzjwgVfdmAaNvsAUCW0R8NAAKCRAgVfdm +AaNvsFsYD/9O3R+ZsxcZ2Pe6iFBQqmZ72H/io6ZQCk0Ue5ehb9t28n6C1V3Q50Ox +XsZWmPD9/97QjVXWkMHPg7/kdtq8a+StN6/MIFPs3kwgCedsm7BFYY1QrJMvdBu7 ++sI3uz12OP4PcFKJZuYO0AygtaZVrpumzOgo5rh2Lvn1OFQoW10KcZutwdVDGJwY +jfpF13ol7dIvtnpZUIBw3uznxI+xqGLDaeJ22dYF0SZAhFGlDwTEy7QKqUdlHS3D +KJlGJ1eKs1HA2Slo4ZGrwVBhzFfkKKLbuhH3AH+CF88sVExVRW4+j3a0LU6//YvJ +sVeNx9mbKeYmeZEXOJoR4/+A90e81+oHbxQhbTfIjokrrSFtKwkrgEvH7OkZxux8 +MrStsuq7X5xRUeXnggmw2jR/8hLcjLBz52928/RBOL2aE+WxU/heDe8GbkXryFzG +jqb3KAAPX1r3LuKWVs+trKuO/uDkU1tF1aDHCzq63P2pkgPmxILkrZvSri4ADUzs +CZppcux1Ee8rYEAd3YfFnXXifk0sXBGkHW0QJ5HYYbi82zmHZiOH9veosza8cvOv +D6KofSM2HXki8GIBB4tqqPsIPPPVywfV48mnSnmJRXWy4TSE4IvzVAH7VGf4EBq8 +9xA3NORQwotgPT8ZAv2n7Bo3sFTQ+LK7MQt2MSOt74Ca0Q6yieNdzbkCDQRbPmPW +ARAAxvUWetoIbQunoKOK8FJfx1AazxUQWT0LlQl0UPfFL5+zqGm86T9Lye3aiywN +MgwacVnh5CZXRb/XU4JibkVgUji3RQ2vnrqETfg0mfzHe7v2Wd/m0R3ijltTR3/z +ZEJxfiRiBR8bUZuVgsyDxyneTlne88SiAdQIRbcoxWDrSIbm9HMubYNQfbDOHSjB +Z0kvkFdU3smu+sl8EM2/FhlWJ2+Tdf0YzKsq7QQAUjP7XdcHg+2UjcPlLBY+eCQS +/i/N8brN4YsJR2N0DH3lYQEJuEhLEQUW2DKbUga0mJsyOutAUEAnbbxub5h4Y2AT +qztX1SCGuyuac5fgL8TbOSBDMYwdUCoWLPt8xlWC+jfvBubSc3lM9bdYU8bauxtv +skNY6MMM2OUFDBUaiXdrfWy/bwou5iJOdLJnxEUHOZl8jPqJUrMuD6yBACHaMtLi +T2Lx/nuxLGgEIWvP5tGBYV815knySaGYkZMpujkDhRFVzAqd+O8AakM2RZJ4Fmzc +i5Mi6GdAo5O3QXcKvrrO2XdF9Jq6cnqWF31X926YpCZiYP8+Fk6C1ekjRu99/tdP +wBZtptBJGoeshF9bhkR/vC/ArQWIhVlwM9mzj4i5RKCnVQZhj4to3rrnyBU2eg8O +WPTqosHl9MkQIgxtYtDWlvF0uhuSX3AsVyx0Gjw8DgjdxtsAEQEAAYkCPAQYAQoA +JhYhBOBas8MOwMfdVtmbDI/wSbKWOO3SBQJbPmPWAhsMBQkDwmcAAAoJEI/wSbKW +OO3S1p4P/RJSRx2XqThbTMVbnmayE0Le/pys1623xMfjOKedm2UUvCXlsnG1EMNU +M0roAUTT9SgdAsAF68lI94tyACOS6vfvSyzv0Nb61CbXNT3saGIOvoN6lpflsBcS +jZZZf4f8vOdw7FLqHU6n9qX24elLJuainV2VA+8zgiiTyfyepDnjRGij1AUc3s31 +2nIYZzRbF+5A+loGYhpunptBkrOPEVAaBT0mf6Ko5nH+7obm+2oXnGJvd3S3K2Ay +58C33/C7Gd6NTHW+wXL7Qb09OQfnLSZS2za6wFhNXDXzvJDGLzuGBwXDKT6DcBPm +fufL1V+sTnyt+LMs4hz/XeV6JWqLFeh102JcFeBBtI4B+eDNsl+4cHS5POWQPWNU +2dXdvJPkO48hKMslQP7VG6SWzOcorFERG0CgDWFfgSir2wIzhnyNu0LJypoMhAZQ +U+aEjW6NN4Hj/dPhow9GF7BSUAx3kYkx8prC7dtaP52Q3eu46h+4gFpdnvhOwDQo +XbJ2uK4e44oTiK4p6KM6KJ4SGe0rDkJxdMAyQqxgZ+06MldSbfQr3oAHV0q4QgSj +xZ4FXaKR/Bf8S1s5pffuTCLgihjRl9lW9N5L9cb8TN898ZyZ/1QREJNdtyar+g/j +C48HmPXN4MzQZZahw44rAUcbk2QSlFO3jj0rfY/HkOch3TU8lLOZ +=42J0 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/dbc.dd b/dbc.dd deleted file mode 100644 index c5aef0de6a..0000000000 --- a/dbc.dd +++ /dev/null @@ -1,167 +0,0 @@ -Ddoc - -$(SPEC_S Contract Programming, - - Contracts are a breakthrough technique to reduce the programming effort - for large projects. Contracts are the concept of preconditions, postconditions, - errors, and invariants. - Contracts can be done in C++ without modification to the language, - but the result is - clumsy and inconsistent. -

    - - Building contract support into the language makes for: - - $(OL - $(LI a consistent look and feel for the contracts) - $(LI tool support) - $(LI it's possible the compiler can generate better code using information gathered - from the contracts) - $(LI easier management and enforcement of contracts) - $(LI handling of contract inheritance) - ) - -$(COMMENT Contracts make D bug resistant) - - $(P The idea of a contract is simple - it's just an expression that must evaluate to true. - If it does not, the contract is broken, and by definition, the program has a bug in it. - Contracts form part of the specification for a program, moving it from the documentation - to the code itself. And as every programmer knows, documentation tends to be incomplete, - out of date, wrong, or non-existent. Moving the contracts into the code makes them - verifiable against the program.) - -

    Assert Contract

    - - The most basic contract is the - $(GLINK2 expression, AssertExpression). - An $(B assert) inserts a checkable expression into - the code, and that expression must evaluate to true: ------- -assert(expression); ------- - C programmers will find it familiar. Unlike C, however, an assert - in function bodies - works by throwing an AssertError, - which can be caught and handled. Catching the contract violation is useful - when the code must deal with errant uses by other code, when it must be - failure proof, and as a useful tool for debugging. - -

    Pre and Post Contracts

    - - The pre contracts specify the preconditions before a statement is executed. The most - typical use of this would be in validating the parameters to a function. The post - contracts validate the result of the statement. The most typical use of this - would be in validating the return value of a function and of any side effects it has. - The syntax is: - ------- -in -{ - ...contract preconditions... -} -out (result) -{ - ...contract postconditions... -} -body -{ - ...code... -} ------- - By definition, if a pre contract fails, then the body received bad - parameters. - An AssertError is thrown. If a post contract fails, - then there is a bug in the body. An AssertError is thrown. -

    - Either the in or the out clause can be omitted. - If the out clause is for a function - body, the variable result is declared and assigned the return - value of the function. - For example, let's implement a square root function: ------- -long square_root(long x) - in - { - assert(x >= 0); - } - out (result) - { - assert((result * result) <= x && (result+1) * (result+1) >= x); - } - body - { - return cast(long)std.math.sqrt(cast(real)x); - } ------- - The assert's in the in and out bodies are called contracts. - Any other D - statement or expression is allowed in the bodies, but it is important - to ensure that the - code has no side effects, and that the release version of the code - will not depend on any effects of the code. - For a release build of the code, the in and out code is not - inserted. -

    - If the function returns a void, there is no result, and so there can be no - result declaration in the out clause. - In that case, use: ------- -void func() - out - { - ...contracts... - } - body - { - ... - } ------- - In an out statement, $(I result) is initialized and set to the - return value of the function. - -

    In, Out and Inheritance

    - - $(P If a function in a derived class overrides a function in its - super class, then only one of - the $(D in) contracts of the function and its base functions - must be satisfied. - Overriding - functions then becomes a process of $(I loosening) the $(D in) - contracts. - ) - - $(P A function without an $(D in) contract means that any values - of the function parameters are allowed. This implies that if any - function in an inheritance hierarchy has no $(D in) contract, - then $(D in) contracts on functions overriding it have no useful - effect. - ) - - $(P Conversely, all of the $(D out) contracts needs to be satisfied, - so overriding functions becomes a processes of $(I tightening) the - $(D out) - contracts. - ) - -

    Class Invariants

    - - $(P Class invariants are used to specify characteristics of a class that - always - must be true (except while executing a member function). - They are described in $(DDLINK class, Classes, Classes). - ) - -

    References

    - - $(LIST - $(LINK2 http://people.cs.uchicago.edu/~robby/contract-reading-list/, Contracts Reading List), - $(LINK2 http://jan.newmarch.name/java/contracts/paper-long.html, Adding Contracts to Java) - ) - -) - -Macros: - TITLE=Contract Programming - WIKI=DBC - CATEGORY_SPEC=$0 - diff --git a/dblog_feed_example.xml b/dblog_feed_example.xml new file mode 100644 index 0000000000..c2dbcafc2f --- /dev/null +++ b/dblog_feed_example.xml @@ -0,0 +1,167 @@ + + + + + The D Blog + + https://dlang.org/blog + The official blog for the D Programming Language. + Mon, 19 Mar 2018 13:27:32 +0000 + en-US + hourly + 1 + https://wordpress.org/?v=4.9.4 +112438176 + DConf 2018 Programme & Open Registration + https://dlang.org/blog/2018/03/19/dconf-2018-programme-open-registration/ + https://dlang.org/blog/2018/03/19/dconf-2018-programme-open-registration/#respond + Mon, 19 Mar 2018 13:27:32 +0000 + + + + + http://dlang.org/blog/?p=1493 + + https://dlang.org/blog/2018/03/19/dconf-2018-programme-open-registration/feed/ + 0 + 1493 + + User Stories: Funkwerk + https://dlang.org/blog/2018/03/14/user-stories-funkwerk/ + https://dlang.org/blog/2018/03/14/user-stories-funkwerk/#comments + Wed, 14 Mar 2018 14:06:32 +0000 + + + + + + + + http://dlang.org/blog/?p=1479 + + https://dlang.org/blog/2018/03/14/user-stories-funkwerk/feed/ + 3 + 1479 + + The D Language Foundation at Open Collective + https://dlang.org/blog/2018/03/12/the-d-foundation-at-open-collective/ + https://dlang.org/blog/2018/03/12/the-d-foundation-at-open-collective/#respond + Mon, 12 Mar 2018 14:20:54 +0000 + + + + + http://dlang.org/blog/?p=1441 + + https://dlang.org/blog/2018/03/12/the-d-foundation-at-open-collective/feed/ + 0 + 1441 + + The New New DIP Process + https://dlang.org/blog/2018/03/09/the-new-new-dip-process/ + https://dlang.org/blog/2018/03/09/the-new-new-dip-process/#comments + Fri, 09 Mar 2018 12:49:07 +0000 + + + + + http://dlang.org/blog/?p=1437 + + https://dlang.org/blog/2018/03/09/the-new-new-dip-process/feed/ + 3 + 1437 + + LDC 1.8.0 Released + https://dlang.org/blog/2018/03/06/ldc-1-8-0-released/ + https://dlang.org/blog/2018/03/06/ldc-1-8-0-released/#respond + Tue, 06 Mar 2018 13:56:15 +0000 + + + + + + + http://dlang.org/blog/?p=1428 + + https://dlang.org/blog/2018/03/06/ldc-1-8-0-released/feed/ + 0 + 1428 + + DMD 2.079.0 Released + https://dlang.org/blog/2018/03/03/dmd-2-079-0-released/ + https://dlang.org/blog/2018/03/03/dmd-2-079-0-released/#respond + Sat, 03 Mar 2018 12:00:30 +0000 + + + + + + + + http://dlang.org/blog/?p=1408 + + https://dlang.org/blog/2018/03/03/dmd-2-079-0-released/feed/ + 0 + 1408 + + The State of D 2018 Survey + https://dlang.org/blog/2018/02/28/the-state-of-d-2018-survey/ + https://dlang.org/blog/2018/02/28/the-state-of-d-2018-survey/#respond + Wed, 28 Feb 2018 13:30:49 +0000 + + + + + + + http://dlang.org/blog/?p=1400 + + https://dlang.org/blog/2018/02/28/the-state-of-d-2018-survey/feed/ + 0 + 1400 + + DConf 2018 Munich: The Venue + https://dlang.org/blog/2018/02/23/dconf-2018-munich-the-venue/ + https://dlang.org/blog/2018/02/23/dconf-2018-munich-the-venue/#respond + Fri, 23 Feb 2018 13:38:00 +0000 + + + + + http://dlang.org/blog/?p=1386 + + https://dlang.org/blog/2018/02/23/dconf-2018-munich-the-venue/feed/ + 0 + 1386 + + Project Highlight: The D Community Hub + https://dlang.org/blog/2018/02/17/project-highlight-the-d-community-hub/ + https://dlang.org/blog/2018/02/17/project-highlight-the-d-community-hub/#respond + Sat, 17 Feb 2018 12:46:19 +0000 + + + + + + http://dlang.org/blog/?p=1381 + dlang-community organization at GitHub.]]> + https://dlang.org/blog/2018/02/17/project-highlight-the-d-community-hub/feed/ + 0 + 1381 + + Vanquish Forever These Bugs That Blasted Your Kingdom + https://dlang.org/blog/2018/02/07/vanquish-forever-these-bugs-that-blasted-your-kingdom/ + https://dlang.org/blog/2018/02/07/vanquish-forever-these-bugs-that-blasted-your-kingdom/#comments + Wed, 07 Feb 2018 13:07:26 +0000 + + + + + + http://dlang.org/blog/?p=1350 + + https://dlang.org/blog/2018/02/07/vanquish-forever-these-bugs-that-blasted-your-kingdom/feed/ + 4 + 1350 + + diff --git a/dcompiler.dd b/dcompiler.dd index 3e2c8f6be2..6029715d2d 100644 --- a/dcompiler.dd +++ b/dcompiler.dd @@ -2,807 +2,698 @@ Ddoc $(D_S dmd - $(WINDOWS Windows)$(LINUX Linux)$(OSX Mac OS X)$(FREEBSD FreeBSD) D Compiler, - $(UL - $(WINDOWS $(LI dmd for $(LINK2 dmd-linux.html, Linux))) - $(WINDOWS $(LI dmd for $(LINK2 dmd-osx.html, OSX))) - $(WINDOWS $(LI dmd for $(LINK2 dmd-freebsd.html, FreeBSD))) - $(LINUX $(LI dmd for $(LINK2 dmd-windows.html, Windows))) - $(LINUX $(LI dmd for $(LINK2 dmd-osx.html, OSX))) - $(LINUX $(LI dmd for $(LINK2 dmd-freebsd.html, FreeBSD))) - $(OSX $(LI dmd for $(LINK2 dmd-windows.html, Windows))) - $(OSX $(LI dmd for $(LINK2 dmd-linux.html, Linux))) - $(OSX $(LI dmd for $(LINK2 dmd-freebsd.html, FreeBSD))) - $(FREEBSD $(LI dmd for $(LINK2 dmd-windows.html, Windows))) - $(FREEBSD $(LI dmd for $(LINK2 dmd-linux.html, Linux))) - $(FREEBSD $(LI dmd for $(LINK2 dmd-osx.html, OSX))) - $(LI $(LINK2 #requirements, Requirements and Downloads)) - $(LI $(LINK2 #files, Files)) - $(LI $(LINK2 #installation, Installation)) - $(WINDOWS $(LI $(LINK2 #example, Example))) - $(LI $(LINK2 #switches, Compiler Arguments and Switches)) - $(LI $(LINK2 #linking, Linking)) - $(LI $(LINK2 #environment, Environment Variables)) - $(WINDOWS $(LI $(LINK2 #sc_ini, sc.ini Initialization File))) - $(UNIX $(LI $(DMD_CONF) Initialization File)) - $(WINDOWS $(LI $(LINK2 #problems, Common Installation Problems))) - $(LI $(LINK2 #differences, Differences between Windows and Linux versions)) - $(LI $(LINK2 #interface_files, D Interface Files)) - $(LI $(LINK2 #library, Building Libraries)) - $(LI $(LINK2 #compiling_dmd, Compiling dmd)) - $(LI $(LINK2 #compiling_phobos, Compiling Phobos)) - ) - -

    $(LNAME2 requirements, Requirements and Downloads)

    - - $(OL - $(LI $(LINK2 http://www.digitalmars.com/d/download.html, Download D Compiler)) + $(UL + $(LI $(RELATIVE_LINK2 requirements, Requirements and Downloads)) + $(LI $(RELATIVE_LINK2 installation, Installation)) + $(WINDOWS $(LI $(RELATIVE_LINK2 example, Example))) + $(LI $(RELATIVE_LINK2 switches, Compiler Arguments and Switches)) + $(LI $(RELATIVE_LINK2 files, Files)) + $(LI $(RELATIVE_LINK2 linking, Linking)) + $(LI $(RELATIVE_LINK2 environment, Environment Variables)) + $(WINDOWS $(LI $(RELATIVE_LINK2 sc-ini, sc.ini Initialization File))) + $(UNIX $(LI $(DMD_CONF) Initialization File)) + $(WINDOWS $(LI $(RELATIVE_LINK2 problems, Common Installation Problems))) + $(LI $(RELATIVE_LINK2 differences, Differences between Windows and Linux versions)) + $(LI $(RELATIVE_LINK2 interface-files, D Interface Files)) + $(LI $(RELATIVE_LINK2 library, Building Libraries)) + $(LI $(RELATIVE_LINK2 compiling-dmd, Compiling dmd)) + $(LI $(RELATIVE_LINK2 compiling-phobos, Compiling Phobos)) + ) + +$(H2 $(LNAME2 requirements, Requirements and Downloads)) + + $(OL + $(LI $(LINK2 https://dlang.org/download.html, DMD Compiler)) $(WINDOWS - $(LI 32 bit Windows (Win32) operating system, such as Windows XP) + $(LI Windows operating system, Windows 7 or later, 32 or 64 bit) - $(LI Download - - dmc.zip (C and C++ compiler) for Win32 - (not required, but it complements dmd for Windows) - ) + $(LI Download + + dmc.zip (C and C++ compiler) for Win32 + (not required, but it complements dmd for Windows) + ) ) $(LINUX - $(LI 32 bit x86 and 64 bit x86-64 Linux operating system) + $(LI 32 bit x86 and 64 bit x86-64 Linux operating system + ($(LINK2 https://github.com/ldc-developers/ldc, LDC) + and $(LINK2 https://github.com/D-Programming-GDC/GDC, GDC) + provide support for more architectures) + ) - $(LI Gnu C compiler (gcc)) + $(LI Gnu C compiler (gcc) or LLVM C compiler (clang)) ) $(OSX - $(LI 32 bit x86 Mac OSX operating system) + $(LI Mac OS X Mavericks (10.9) or later) - $(LI Gnu C compiler (gcc)) + $(LI Xcode) ) $(FREEBSD - $(LI 32 bit x86 FreeBSD 7.1 operating system) + $(LI 32 bit x86 and 64 bit x86-64 FreeBSD operating system (11 or later)) - $(LI Gnu C compiler (gcc)) + $(LI Gnu C compiler (gcc)) + ) ) - ) - -

    $(LNAME2 files, Files)

    - - $(DL - - $(DT $(D $(DMDDIR)$(SEP)src$(SEP)phobos$(SEP)) - $(DD D runtime library source) - ) - - $(DT $(D $(DMDDIR)$(SEP)src$(SEP)dmd$(SEP)) - $(DD D compiler front end source under dual (GPL and Artistic) license) - ) - $(DT $(D $(DMDDIR)$(SEP)html$(SEP)d$(SEP)) - $(DD Documentation) - ) +$(H2 $(LNAME2 installation, Installation)) - $(DT $(D $(DMDDIR)$(SEP)samples$(SEP)d$(SEP)) - $(DD Sample D programs) - ) $(WINDOWS - $(DT $(D $(DMDDIR)\windows\bin\dmd.exe) - $(DD D compiler executable) - ) - - $(DT $(D $(DMDDIR)\windows\bin\$(LINK2 http://www.digitalmars.com/ctg/shell.html, shell.exe)) - $(DD Simple command line shell) - ) +$(MESSAGE_BOX gray, $(B Hint) - The official $(LINK2 $(ROOT_DIR)download.html, installer) +performs these steps automatically. +) + $(P Open a console window (for Windows this is done by + clicking on [Start][Command Prompt]). + All the tools are command line tools, which means + they are run from a console window. + Switch to the root directory. + Unzip the files in the root directory. + $(D dmd.zip) will create + a $(D $(DMDDIR)) directory with all the files in it. + $(D dmc.zip) will create + a $(D \dm) directory with all the files in it. + ) - $(DT $(D $(DMDDIR)\windows\bin\sc.ini) - $(DD Global compiler settings) - ) + $(P A typical session might look like:) - $(DT $(D $(DMDDIR)\windows\lib\$(LIB)) - $(DD D runtime library) - ) +$(CONSOLE +C:\Documents and Settings\Your Name>cd \ +C:\\>unzip dmd.zip +C:\\>unzip dmc.zip +) ) $(LINUX - $(DT $(D $(DMDDIR)/linux/bin/dmd) - $(DD D compiler executable) - ) - $(DT $(D $(DMDDIR)/linux/bin/$(DUMPOBJ)) - $(DD Elf file dumper) - ) + $(INSTALLATION_SCRIPT_HINT) - $(DT $(D $(DMDDIR)/linux/bin/$(OBJ2ASM)) - $(DD Elf file disassembler) - ) + Unzip the archive into your home directory. + It will create a $(D ~/dmd) directory with all the files in it. - $(DT $(D $(DMDDIR)/linux/bin/$(SHELL)) - $(DD Simple command line shell) - ) - - $(DT $(D $(DMDDIR)/linux/bin/$(DMD_CONF)) - $(DD Global compiler settings (copy to $(D /etc/dmd.conf))) - ) + All the tools are command line tools, which means + they are run from a console window. + All tools can be run directly from the archive: +$(CONSOLE +~/dmd/linux/bin64/dmd +) + To install $(D dmd) globally, add the `~/dmd/linux/bin64` folder to your $(B PATH). +$(CONSOLE +export PATH="$HOME/dmd/linux/bin64:$PATH" +) - $(DT $(D $(DMDDIR)/linux/lib/$(LIB)) - $(DD D runtime library (copy to $(D /usr/lib/$(LIB)))) - ) - ) - $(FREEBSD - $(DT $(D $(DMDDIR)/freebsd/bin/dmd) - $(DD D compiler executable) - ) + Alternatively, you can install dmd locally yourself by: + $(P $(UL - $(DT $(D $(DMDDIR)/freebsd/bin/$(DUMPOBJ)) - $(DD Elf file dumper) - ) + $(LI Create a configuration file in $(D /etc/dmd.conf): - $(DT $(D $(DMDDIR)/freebsd/bin/$(OBJ2ASM)) - $(DD Elf file disassembler) - ) +--- +[Environment64] +DFLAGS=-I/usr/local/include/d/dmd -L-L/usr/local/lib -L--export-dynamic -fPIC +--- - $(DT $(D $(DMDDIR)/freebsd/bin/$(SHELL)) - $(DD Simple command line shell) - ) + ) - $(DT $(D $(DMDDIR)/freebsd/bin/$(DMD_CONF)) - $(DD Global compiler settings (copy to $(D /etc/dmd.conf))) - ) + $(LI Copy binaries to $(D /usr/local/bin): - $(DT $(D $(DMDDIR)/freebsd/lib/$(LIB)) - $(DD D runtime library (copy to $(D /usr/lib/$(LIB)))) - ) +$(CONSOLE +sudo cp $(DMDDIR)/linux/bin64/{dmd,$(DUMPOBJ),$(OBJ2ASM),rdmd,ddemangle,dub,dustmite} /usr/local/bin +) ) - $(OSX - $(DT $(D $(DMDDIR)/osx/bin/dmd) - $(DD D compiler executable) - ) - $(DT $(D $(DMDDIR)/osx/bin/$(DUMPOBJ)) - $(DD Mach-O file dumper) - ) + $(LI Copy the library to $(D /usr/local/lib): - $(DT $(D $(DMDDIR)/osx/bin/$(OBJ2ASM)) - $(DD Mach-O file disassembler) - ) +$(CONSOLE +sudo cp $(DMDDIR)/linux/lib64/$(LIB) /usr/local/lib +) + ) - $(DT $(D $(DMDDIR)/osx/bin/$(SHELL)) - $(DD Simple command line shell) - ) + $(LI Copy the standard library and runtime sources to $(D /usr/include/d/dmd): - $(DT $(D $(DMDDIR)/osx/bin/$(DMD_CONF)) - $(DD Global compiler settings (copy to $(D /etc/dmd.conf))) - ) +$(CONSOLE +sudo mkdir -p /usr/include/d/dmd +sudo cp $(DMDDIR)/{phobos/std,phobos/etc,druntime/import} /usr/include/d/dmd +) - $(DT $(D $(DMDDIR)/osx/lib/$(LIB)) - $(DD D runtime library (copy to $(D /usr/lib/$(LIB)))) - ) + ) + )) ) - ) + $(FREEBSD -

    $(LNAME2 installation, Installation)

    + $(INSTALLATION_SCRIPT_HINT) - $(WINDOWS - $(P Open a console window (for Windows XP this is done by - clicking on [Start][Command Prompt]). - All the tools are command line tools, which means - they are run from a console window. - Switch to the root directory. - Unzip the files in the root directory. - $(D dmd.zip) will create - a $(D $(DMDDIR)) directory with all the files in it. - $(D dmc.zip) will create - a $(D \dm) directory with all the files in it. - ) - - $(P A typical session might look like:) + $(P $(UL -$(CONSOLE -C:\Documents and Settings\Your Name>cd \ -C:\>unzip dmd.zip -C:\>unzip dmc.zip -) - ) - $(LINUX - $(LI Unzip the archive into your home directory. - It will create - a $(D ~/dmd) directory with all the files in it. - All the tools are command line tools, which means - they are run from a console window.) + $(LI Unzip the archive into your home directory. + It will create + a $(D ~/dmd) directory with all the files in it. + All the tools are command line tools, which means + they are run from a console window.) - $(LI Copy $(D $(DMD_CONF)) to $(D /etc): + $(LI Create a configuration file in $(D /etc/dmd.conf): -$(CONSOLE -cp $(DMDDIR)/linux/bin/$(DMD_CONF) /etc -) - ) +--- +[Environment64] +DFLAGS=-I/usr/local/include/d/dmd -L-L/usr/local/lib -L--export-dynamic -fPIC +--- + + ) - $(LI Put $(D $(DMDDIR)/linux/bin) on your $(B PATH), - or copy the linux executables - to $(D /usr/local/bin)) - $(LI Copy the library to $(D /usr/lib): + $(LI Put $(D $(DMDDIR)/freebsd/bin) on your $(B PATH), + or copy the FreeBSD executables + to $(D /usr/local/bin):) $(CONSOLE -cp $(DMDDIR)/linux/lib/$(LIB) /usr/lib +sudo cp $(DMDDIR)/linux/bin64/{dmd,$(DUMPOBJ),$(OBJ2ASM),rdmd,ddemangle,dub,dustmite} /usr/local/bin ) - ) - ) - $(FREEBSD - $(LI Unzip the archive into your home directory. - It will create - a $(D ~/dmd) directory with all the files in it. - All the tools are command line tools, which means - they are run from a console window.) - $(LI Copy $(D $(DMD_CONF)) to $(D /etc): + $(LI Copy the library to $(D /usr/lib): $(CONSOLE -cp $(DMDDIR)/freebsd/bin/dmd.conf /etc +sudo cp $(DMDDIR)/freebsd/lib/$(LIB) /usr/lib ) - ) - - $(LI Put $(D $(DMDDIR)/freebsd/bin) on your $(B PATH), - or copy the FreeBSD executables - to $(D /usr/local/bin)) + ) - $(LI Copy the library to $(D /usr/lib): + $(LI Copy the standard library and runtime sources to $(D /usr/include/d/dmd): $(CONSOLE -cp $(DMDDIR)/freebsd/lib/$(LIB) /usr/lib +sudo mkdir -p /usr/include/d/dmd +sudo cp $(DMDDIR)/{phobos/std,phobos/etc,druntime/import} /usr/include/d/dmd ) - ) + ) + )) ) $(OSX - $(LI Put the dmd zip file into your home directory, - and unzip it: + + $(INSTALLATION_SCRIPT_HINT) + + $(P $(UL + + $(LI Put the dmd zip file into your home directory, + and unzip it: $(CONSOLE unzip dmd.$(I VERSION).zip ) - where $(I VERSION) is the particular version of the zip file. - ) + where $(I VERSION) is the particular version of the zip file. + ) - $(LI It will create - a $(D ~/$(DMDDIR)) directory with all the files in it. - All the tools are command line tools, which means - they are run from a console window.) + $(LI It will create + a $(D ~/$(DMDDIR)) directory with all the files in it. + All the tools are command line tools, which means + they are run from a console window.) - $(LI Verify that this works by creating $(D hello.d) in your home directory - with these contents: + $(LI Verify that this works by creating $(D hello.d) in your home directory + with these contents: --- import std.stdio; -void main() { +void main() +{ writeln("hello world!"); } --- - and compile and run it with: + and compile and run it with: $(CONSOLE $(DMDDIR)/osx/bin/dmd hello ./hello ) - and it should print: + and it should print: $(CONSOLE hello world! ) - ) + ) - $(LI To install a global copy:) + $(LI To install a global copy:) - $(LI Copy binaries to $(D /usr/local/bin): + $(LI Copy binaries to $(D /usr/local/bin): $(CONSOLE -sudo cp $(DMDDIR)/osx/bin/{dmd,$(DUMPOBJ),$(OBJ2ASM),$(SHELL)$(V2 ,rdmd)} /usr/local/bin +sudo cp $(DMDDIR)/osx/bin/{dmd,$(DUMPOBJ),$(OBJ2ASM),rdmd,dub,ddemangle,dustmite} /usr/local/bin sudo cp $(DMDDIR)/osx/bin/dmdx.conf /usr/local/bin/$(DMD_CONF) ) - ) + ) + + $(LI Copy the library to $(D /usr/local/lib): + +$(CONSOLE +sudo cp $(DMDDIR)/osx/lib/$(LIB) /usr/local/lib +) + ) - $(LI Copy the library to $(D /usr/lib): + $(LI Copy the standard library and runtime sources to $(D /usr/local/include/d/dmd): $(CONSOLE -sudo cp $(DMDDIR)/osx/lib/$(LIB) /usr/lib +sudo mkdir -p /usr/include/d/dmd +sudo cp $(DMDDIR)/{phobos/std,phobos/etc,druntime/import} /usr/include/d/dmd ) - ) + ) + + )) ) $(WINDOWS -

    $(LNAME2 example, Example)

    +$(H2 $(H2 $(LNAME2 example, Example))) - $(P Run:) + $(P Run:) $(CONSOLE $(DMDDIR)$(SEP)$(OS)$(SEP)bin$(SEP)$(SHELL) all.sh ) - $(P in the $(D $(DMDDIR)$(SEP)samples$(SEP)d) directory for several small examples.) -) + $(P in the $(D $(DMDDIR)$(SEP)samples$(SEP)d) directory for several small examples.) +) + + +$(H2 $(LNAME2 switches, Compiler Arguments and Switches)) + + $(DL + $(DT $(B dmd) $(I files)... -$(I switches)... + $(DD ) + ) + + $(DT $(I files)... + $(DD + $(TABLE2 File Extensions, + $(TR + $(TH Extension) + $(TH File Type) + ) + $(TR + $(TD $(I none)) + $(TD D source files) + ) + $(TR + $(TD $(B .c)) + $(TD C source files) + ) + $(TR + $(TD $(B .d)) + $(TD D source files) + ) + $(TR + $(TD $(B .dd)) + $(TD $(LINK2 spec/ddoc.html, Ddoc) source files) + ) + $(TR + $(TD $(B .di)) + $(TD $(RELATIVE_LINK2 interface-files, D interface files)) + ) + $(TR + $(TD $(B .h)) + $(TD C header files) + ) + $(TR + $(TD $(B .i)) + $(TD preprocessed C source files) + ) + $(TR + $(TD $(B .$(OBJEXT))) + $(TD Object files to link in) + ) + $(TR + $(TD $(B .$(LIBEXT))) + $(TD Object code libraries to search) + ) +$(WINDOWS + $(TR + $(TD $(B .exe)) + $(TD Output executable file) + ) + $(TR + $(TD $(B .def)) + $(TD $(LINK2 http://www.digitalmars.com/ctg/ctgDefFiles.html, module definition file)) + ) + $(TR + $(TD $(B .res)) + $(TD resource file) + ) +) + ) + ) + ) + + $(SWITCH $(B @)$(I cmdfile), + If $(I cmdfile) is an environment variable, + read the compiler arguments and switches from + the value of that variable. + Otherwise, read compiler arguments and switches from + the text file $(I cmdfile). + The file may contain single-line comments starting + with the hash symbol ($(CODE #)). + ) + + $(CLI_SWITCHES) + ) + $(WINDOWS + $(P Empty switches, i.e. "", are ignored.) + ) -

    $(LNAME2 switches, Compiler Arguments and Switches)

    - - $(DL - $(DT $(B dmd) $(I files)... -$(I switches)... - $(DD ) - ) - - $(DT $(I files)... - $(DD - $(TABLE2 File Extensions, - $(TR - $(TH Extension) - $(TH File Type) - ) - $(TR - $(TD $(I none)) - $(TD D source files) - ) - $(TR - $(TD $(B .d)) - $(TD D source files) - ) - $(TR - $(TD $(B .dd)) - $(TD $(LINK2 ddoc.html, Ddoc) source files) - ) - $(TR - $(TD $(B .di)) - $(TD $(LINK2 #interface_files, D interface files)) - ) - $(TR - $(TD $(B .$(OBJEXT))) - $(TD Object files to link in) - ) - $(TR - $(TD $(B .$(LIBEXT))) - $(TD Object code libraries to search) - ) -$(WINDOWS - $(TR - $(TD $(B .exe)) - $(TD Output executable file) - ) - $(TR - $(TD $(B .def)) - $(TD $(LINK2 http://www.digitalmars.com/ctg/ctgDefFiles.html, module definition file)) - ) - $(TR - $(TD $(B .res)) - $(TD resource file) - ) -) - ) - ) - ) - - $(SWITCH $(B @)$(I cmdfile), - If $(I cmdfile) is an environment variable, - read the compiler arguments and switches from - the value of that variable. - Otherwise, read compiler arguments and switches from - the text file $(I cmdfile) - ) - - $(SWITCH $(B -c), - compile only, do not link - ) - - $(SWITCH $(B -cov), - instrument for $(LINK2 code_coverage.html, code coverage analysis) - ) - - $(SWITCH $(B -D), - generate $(LINK2 ddoc.html, documentation) from source - ) - - $(SWITCH $(B -Dd)$(I docdir), - write documentation file to $(I docdir) directory - ) - - $(SWITCH $(B -Df)$(I filename), - write documentation file to $(I filename) - ) - - $(SWITCH $(B -d), - allow deprecated features - ) - $(SWITCH $(B -debug), - compile in $(LINK2 version.html#debug, debug) code - ) - $(SWITCH $(B -debug=)$(I level), - compile in $(LINK2 version.html#debug, debug level) <= $(I level) - ) - $(SWITCH $(B -debug=)$(I ident), - compile in $(LINK2 version.html#debug, debug identifier) $(I ident) - ) - - $(SWITCH $(B -debuglib=)$(I libname), - link in $(I libname) as the default library when - compiling for symbolic debugging instead of $(B $(LIB)) - ) - $(SWITCH $(B -defaultlib=)$(I libname), - link in $(I libname) as the default library when - not compiling for symbolic debugging instead of $(B $(LIB)) - ) - $(SWITCH $(B -deps=)$(I filename), - write module dependencies as text to $(I filename) - ) +$(H2 $(LNAME2 files, Files)) - $(UNIX - $(SWITCH $(B -fPIC), - generate Position Independent Code (which is used - for building shared libraries). - $(OSX This is always on for OSX.) - ) + $(DL + + $(DT $(D $(DMDDIR)$(SEP)src$(SEP)phobos$(SEP)) + $(DD D runtime library source) ) - $(SWITCH $(B -g), - $(WINDOWS - add CodeView 4 symbolic debug info with - $(LINK2 abi.html#codeview, D extensions) - for debuggers such as - $(LINK2 http://ddbg.mainia.de/releases.html, Ddbg) + $(DT $(D $(DMDDIR)$(SEP)src$(SEP)dmd$(SEP)) + $(DD D compiler front end source under dual (GPL and Artistic) license) ) - $(UNIX - add Dwarf symbolic debug info with - $(LINK2 abi.html#dwarf, D extensions) - for debuggers $(LINUX such as - $(LINK2 http://www.zerobugs.org/, ZeroBUGS)) + + $(DT $(D $(DMDDIR)$(SEP)html$(SEP)d$(SEP)) + $(DD Documentation) ) - ) - $(SWITCH $(B -gc), + $(DT $(D $(DMDDIR)$(SEP)samples$(SEP)d$(SEP)) + $(DD Sample D programs) + ) $(WINDOWS - add CodeView 4 symbolic debug info in C format - for debuggers such as - $(D $(DMDDIR)\bin\windbg) + + $(DT $(D $(DMDDIR)\windows\bin\ddemangle.exe) + $(DD D symbol demangler) ) - $(UNIX - add Dwarf symbolic debug info in C format - for debuggers such as - $(D gdb) - ) - ) - - $(SWITCH $(B -gs), - always generate standard stack frame - ) - - $(SWITCH $(B -H), - generate $(LINK2 #interface_files, D interface file) - ) - - $(SWITCH $(B -Hd)$(I dir), - write D interface file to $(I dir) directory - ) - - $(SWITCH $(B -Hf)$(I filename), - write D interface file to $(I filename) - ) - - $(SWITCH $(B --help), - print brief help to console - ) - - $(SWITCH $(B -I)$(I path), - where to look for - $(LINK2 module.html#ImportDeclaration, imports). - $(I path) is a ; separated - list of paths. Multiple $(B -I)'s can be used, and the paths - are searched in the same order. - ) - - $(SWITCH $(B -ignore), - ignore unsupported pragmas - ) - - $(SWITCH $(B -inline), - inline expand functions at the discretion of the compiler. - This can improve performance, at the expense of making - it more difficult to use a debugger on it. - ) - - $(SWITCH $(B -J)$(I path), - where to look for files for - $(LINK2 expression.html#ImportExpression, $(I ImportExpression))s. - This switch is required in order to use $(I ImportExpression)s. - $(I path) is a ; separated - list of paths. Multiple $(B -J)'s can be used, and the paths - are searched in the same order. - ) - - $(SWITCH $(B -L)$(I linkerflag), - pass $(I linkerflag) to the - $(WINDOWS $(LINK2 http://www.digitalmars.com/ctg/optlink.html, linker)) - $(UNIX linker), for example, - $(WINDOWS $(D -L/ma/li))$(UNIX $(D -L-M)) - ) - - $(SWITCH $(B -lib), - generate library file as output instead of object file(s). - All compiled source files, as well as object files and library - files specified on the command line, are inserted into - the output library. - Compiled source modules may be partitioned into several object - modules to improve granularity. - The name of the library is taken from the name of the first - source module to be compiled. This can be overridden with - the $(B -of) switch. - ) - $(UNIX - $(SWITCH $(B -m32), - compile a 32 bit executable. This is the default for the - 32 bit dmd. - ) + $(DT $(D $(DMDDIR)\windows\bin\dman.exe) + $(DD D manual lookup tool) + ) - $(SWITCH $(B -m64), - compile a 64 bit executable. This is the default for the 64 bit dmd. - ) + $(DT $(D $(DMDDIR)\windows\bin\dmd.exe) + $(DD D compiler executable) ) - $(SWITCH $(B -man), - $(WINDOWS - open default browser on this page + $(DT $(D $(DMDDIR)\windows\bin\$(DUB)) + $(DD D's package manager) + ) + + $(DT $(D $(DMDDIR)\windows\bin\$(DUSTMITE)) + $(DD D source code minimizer) + ) + + $(DT $(D $(DMDDIR)\windows\bin\$(OPTLINK)) + $(DD OPTLINK) + ) + + $(DT $(D $(DMDDIR)\windows\bin\$(LINK2 http://www.digitalmars.com/ctg/make.html, make.exe)) + $(DD Digitalmars Make) + ) + + $(DT $(D $(DMDDIR)\windows\bin\replace.exe) + $(DD Find/replace text in files) + ) + + $(DT $(D $(DMDDIR)\windows\bin\$(RDMD)) + $(DD D build tool for script-like D code execution) + ) + + $(DT $(D $(SC_INI)) + $(DD Global compiler settings) + ) + + $(DT $(D $(DMDDIR)\windows\bin\$(LINK2 http://www.digitalmars.com/ctg/shell.html, shell.exe)) + $(DD Simple command line shell) + ) + + $(DT $(D $(DMDDIR)\windows\lib\$(LIB)) + $(DD D runtime library) + ) ) $(LINUX - open browser specified by the $(B BROWSER) - environment variable on this page. If $(B BROWSER) is - undefined, $(B x-www-browser) is assumed. + $(DT $(D $(DMDDIR)/linux/bin/ddemangle) + $(DD D symbol demangler) + ) + + $(DT $(D $(DMDDIR)/linux/bin/dman) + $(DD D manual lookup tool) + ) + + $(DT $(D $(DMDDIR)/linux/bin/dmd) + $(DD D compiler executable) + ) + + $(DT $(D $(DMDDIR)/linux/bin/$(DMD_CONF)) + $(DD Global compiler settings (copy to $(D /etc/dmd.conf))) + ) + + $(DT $(D $(DMDDIR)/linux/bin/$(DUB)) + $(DD D's package manager) + ) + + $(DT $(D $(DMDDIR)/linux/bin/$(DUMPOBJ)) + $(DD ELF file dumper) + ) + + $(DT $(D $(DMDDIR)/linux/bin/$(DUSTMITE)) + $(DD D source code minimizer) + ) + + $(DT $(D $(DMDDIR)/linux/bin/$(OBJ2ASM)) + $(DD ELF file disassembler) + ) + + $(DT $(D $(DMDDIR)/linux/bin/$(RDMD)) + $(DD D build tool for script-like D code execution) + ) + + $(DT $(D $(DMDDIR)/linux/lib/$(LIB)) + $(DD D runtime library (copy to $(D /usr/lib/$(LIB)))) + ) ) $(FREEBSD - open browser specified by the $(B BROWSER) - environment variable on this page. If $(B BROWSER) is - undefined, $(B x-www-browser) is assumed. + $(DT $(D $(DMDDIR)/freesd/bin/ddemangle) + $(DD D symbol demangler) + ) + + $(DT $(D $(DMDDIR)/freebsd/bin/dman) + $(DD D manual lookup tool) + ) + + $(DT $(D $(DMDDIR)/freebsd/bin/dmd) + $(DD D compiler executable) + ) + + $(DT $(D $(DMDDIR)/freebsd/bin/$(DMD_CONF)) + $(DD Global compiler settings (copy to $(D /etc/dmd.conf))) + ) + + $(DT $(D $(DMDDIR)/freebsd/bin/$(DUB)) + $(DD D's package manager) + ) + + $(DT $(D $(DMDDIR)/freebsd/bin/$(DUMPOBJ)) + $(DD ELF file dumper) + ) + + $(DT $(D $(DMDDIR)/freebsd/bin/$(DUSTMITE)) + $(DD D source code minimizer) + ) + + $(DT $(D $(DMDDIR)/freebsd/bin/$(OBJ2ASM)) + $(DD ELF file disassembler) + ) + + $(DT $(D $(DMDDIR)/freebsd/bin/$(RDMD)) + $(DD D build tool for script-like D code execution) + ) + + $(DT $(D $(DMDDIR)/freebsd/bin/$(SHELL)) + $(DD Simple command line shell) + ) + + $(DT $(D $(DMDDIR)/freebsd/lib/$(LIB)) + $(DD D runtime library (copy to $(D /usr/lib/$(LIB)))) + ) ) $(OSX - open browser specified by the $(B BROWSER) - environment variable on this page. If $(B BROWSER) is - undefined, $(B Safari) is assumed. + $(DT $(D $(DMDDIR)/osx/bin/ddemangle) + $(DD D symbol demangler) ) - ) - $(SWITCH $(B -map), - generate a .map file - ) + $(DT $(D $(DMDDIR)/osx/bin/dman) + $(DD D manual lookup tool) + ) -$(V2 - $(SWITCH $(B -noboundscheck), - turns off all array bounds checking, even for safe functions - ) -) - $(WINDOWS - $(SWITCH $(B -nofloat), - Prevents emission of $(B __fltused) reference in - object files, even if floating point code is present. - Useful for library code. - ) - ) - - $(SWITCH $(B -O), - Optimize generated code. For fastest executables, compile - with the $(B -O -release -inline) switches together. - ) - - $(SWITCH $(B -o-), - Suppress generation of object file. Useful in - conjuction with $(B -D) or $(B -H) flags. - ) - - $(SWITCH $(B -od)$(I objdir), - $(DD write object files relative to directory $(I objdir) - instead of to the current directory) - ) - $(SWITCH $(B -of)$(I filename), - Set output file name to $(I filename) in the output - directory. The output file can be an object file, - executable file, or library file depending on the other - switches. - ) - $(SWITCH $(B -op), - normally the path for $(B .d) source files is stripped - off when generating an object file name. $(B -op) will leave - it on. - ) - $(SWITCH $(B -profile), - $(LINK2 http://www.digitalmars.com/ctg/trace.html, profile) - the runtime performance - of the generated code - ) -$(V2 - $(SWITCH $(B -property), - enforce use of @property on property functions - ) -) - $(SWITCH $(B -quiet), - suppress non-essential compiler messages - ) - $(SWITCH $(B -release), - $(V1 compile release version, which means not generating - code for contracts, asserts and array bounds checking) - $(V2 compile release version, which means not generating - code for contracts and asserts. Array bounds checking - is not done for system and trusted functions.) - ) - $(SWITCH $(B -run) $(I srcfile args...) - compile, link, and run the program $(I srcfile) with the - rest of the - command line, $(I args...), as the arguments to the program. - No .$(OBJEXT) or executable file is left behind. - ) -$(COMMENT - $(SWITCH $(B -safe), - Statically checks the modules being compiled to ensure they - conform to the $(LINK2 safed.html, safe memory model). - ) -) - $(UNIX - $(SWITCH $(B -shared), - generate shared library - ) - ) - $(SWITCH $(B -unittest), - compile in $(LINK2 unittest.html, unittest) code, turns on asserts, and sets the - $(D unittest) $(LINK2 version.html#PredefinedVersions, version identifier) - ) - $(SWITCH $(B -v), - verbose - ) - $(SWITCH $(B -version=)$(I level), - compile in $(LINK2 version.html#version, version level) >= $(I level) - ) - $(SWITCH $(B -version=)$(I ident), - compile in $(LINK2 version.html#version, version identifier) $(I ident) - ) -$(V2 - $(SWITCH $(B -vtls), - print informational messages identifying variables defaulting - to thread local storage. Handy for migrating to shared model. - ) -) - $(SWITCH $(B -w), - enable $(LINK2 warnings.html, warnings) - ) - $(SWITCH $(B -wi), - enable $(LINK2 warnings.html, informational warnings (i.e. compilation - still proceeds normally)) - ) - $(SWITCH $(B -X), - generate JSON file - ) - $(SWITCH $(B -Xf)$(I filename), - write JSON file to $(I filename) - ) - ) + $(DT $(D $(DMDDIR)/osx/bin/dmd) + $(DD D compiler executable) + ) - $(WINDOWS - $(P Empty switches, i.e. "", are ignored.) + $(DT $(D $(DMDDIR)/osx/bin/$(DMD_CONF)) + $(DD Global compiler settings (copy to $(D /etc/dmd.conf))) + ) + + $(DT $(D $(DMDDIR)/osx/bin/$(DUB)) + $(DD D's package manager) + ) + + $(DT $(D $(DMDDIR)/osx/bin/$(DUMPOBJ)) + $(DD Mach-O file dumper) ) -

    $(LNAME2 linking, Linking)

    + $(DT $(D $(DMDDIR)/osx/bin/$(DUSTMITE)) + $(DD D source code minimizer) + ) - $(P Linking is done directly by the $(B dmd) compiler after a successful - compile. To prevent $(B dmd) from running the linker, use the - $(B -c) switch. - ) + $(DT $(D $(DMDDIR)/osx/bin/$(OBJ2ASM)) + $(DD Mach-O file disassembler) + ) + + $(DT $(D $(DMDDIR)/osx/bin/$(RDMD)) + $(DD D build tool for script-like D code execution) + ) + + $(DT $(D $(DMDDIR)/osx/bin/$(SHELL)) + $(DD Simple command line shell) + ) + + $(DT $(D $(DMDDIR)/osx/lib/$(LIB)) + $(DD D runtime library (copy to $(D /usr/local/lib/$(LIB)))) + ) + ) + + ) + + + +$(H2 $(LNAME2 linking, Linking)) + + $(P Linking is done directly by the $(B dmd) compiler after a successful + compile. To prevent $(B dmd) from running the linker, use the + $(SWLINK -c) switch. + ) $(WINDOWS - $(P The programs must be linked with the D runtime library $(B phobos.lib), - followed by the C runtime library $(B snn.lib). - This is done automatically as long as the directories for the - libraries are on the LIB environment variable path. A typical - way to set LIB would be: - ) + $(P 32 bit programs must be linked with the D runtime library $(B phobos.lib), + followed by the Digital Mars C runtime library $(B snn.lib). + This is done automatically as long as the directories for the + libraries are on the $(B LIB) environment variable path. A typical + way to set $(B LIB) would be: + ) $(CONSOLE set LIB=$(DMDDIR)\lib;\dm\lib ) - $(P If the $(B dmd) command is used to both compile and link - to an executable, it will make certain optimizations that are - valid only for Windows executable files. Do not use the resulting - .obj files in a DLL. - To compile modules into .obj files that can be used in an exe or - DLL, compile with $(B -c). - ) - - $(P Linking is done using the - $(LINK2 http://www.digitalmars.com/ctg/optlink.html, optlink) linker. - ) + $(P If the $(B dmd) command is used to both compile and link + to an executable, it will make certain optimizations that are + valid only for Windows executable files. Do not use the resulting + .obj files in a DLL. + To compile modules into .obj files that can be used in an exe or + DLL, compile with $(SWLINK -c) and $(SWLINK -shared). + ) + + $(P Linking 32 bit programs is done using Digital Mars $(OPTLINK). + ) + + $(P Linking 64 bit programs is done using the + Microsoft linker by default. If the Microsoft linker is not found, + the included LLVM linker LLD will be used. + ) ) $(UNIX - $(P The actual linking is done by running $(B gcc). - This ensures compatibility with modules compiled with $(B gcc). - ) + $(P The actual linking is done by running $(B gcc). + This ensures compatibility with modules compiled with $(B gcc). + ) ) -

    $(LNAME2 environment, Environment Variables)

    +$(H2 $(LNAME2 environment, Environment Variables)) - $(P The D compiler dmd uses the following environment variables: - ) + $(P The D compiler dmd uses the following environment variables: + ) - $(DL + $(DL $(WINDOWS -
    $(B DFLAGS) -
    The value of $(B DFLAGS) is treated as if it were appended to the - command line to $(B dmd.exe). + $(DT $(B DFLAGS)) + $(DD The value of $(B DFLAGS) is treated as if it were appended to the + command line to $(B dmd.exe).) -
    $(B LIB) -
    The linker uses $(B LIB) to search for library files. For D, it will - normally be set to: + $(DT $(B LIB)) + $(DD The linker uses $(B LIB) to search for library files. For D, it will + normally be set to:) $(CONSOLE set LIB=$(DMDDIR)\lib;\dm\lib ) -
    $(B LINKCMD) -
    $(B dmd) normally runs the linker by looking for $(B link.exe) - along the $(B PATH). To use a specific linker instead, set the - $(B LINKCMD) environment variable to it. For example: + $(DT $(B LINKCMD)) + $(DD $(B dmd) normally runs the linker by looking for $(OPTLINK) + along the $(B PATH). To use a specific linker for 32 bit programs instead, set the + $(B LINKCMD) environment variable to it. For example:) $(CONSOLE set LINKCMD=\dmd\windows\bin\link ) -
    $(B PATH) -
    If the linker is not found in the same directory as $(B dmd.exe) - is in, the $(B PATH) is searched for it. - $(B Note:) other linkers named - $(B link.exe) will likely not work. - Make sure the Digital Mars $(B link.exe) - is found first in the $(B PATH) before other $(B link.exe)'s, - or use $(B LINKCMD) to specifically identify which linker - to use. + $(DT $(B LINKCMD64)) + $(DD $(B dmd) normally runs the linker by looking for $(OPTLINK) + along the $(B PATH). To use a specific linker for 64 bit programs instead, set the + $(B LINKCMD64) environment variable to it. For example:) + +$(CONSOLE +set LINKCMD64=C:\Program Files (x86)\Microsoft Visual Studio 15.0\VC\bin\amd64\link.exe +) + + $(DT $(B PATH)) + $(DD If the linker is not found in the same directory as $(B dmd.exe) + is in, the $(B PATH) is searched for it. + $(B Note:) other linkers named + $(B link.exe) will likely not work. + Make sure the Digital Mars $(OPTLINK) + is found first in the $(B PATH) before other $(B link.exe)s, + or use $(B LINKCMD) to specifically identify which linker + to use.) ) $(UNIX -
    $(B CC) -
    $(B dmd) normally runs the linker by looking for $(B gcc) - along the $(B PATH). To use a specific linker instead, set the - $(B CC) environment variable to it. For example: + $(DT $(B CC)) + $(DD $(B dmd) normally runs the linker by looking for $(B gcc) + along the $(B PATH). To use a specific linker instead, set the + $(B CC) environment variable to it. For example:) $(CONSOLE set CC=gcc ) - $(DT $(B BROWSER) - $(DD This sets the browser used to open the manual page with - the $(B -man) switch. It defaults to $(D x-www-browser). - ) - ) + $(DT $(B BROWSER) + $(DD This sets the browser used to open the manual page with + the $(SWLINK -man) switch. It defaults to $(D x-www-browser). + ) + ) -
    $(B DFLAGS) -
    The value of $(B DFLAGS) is treated as if it were appended to the - command line to $(B dmd). + $(DT $(B DFLAGS)) + $(DD The value of $(B DFLAGS) is treated as if it were appended to the + command line to $(B dmd).) + ) ) - ) $(WINDOWS -

    $(LNAME2 sc_ini, sc.ini Initialization File)

    +$(H2 $(LEGACY_LNAME2 sc_ini, sc-ini, sc.ini Initialization File)) - $(P $(B dmd) will look for the initialization file $(B sc.ini) in the - following sequence of directories: - ) + $(P $(B dmd) will look for the initialization file $(B sc.ini) in the + following sequence of directories: + ) - $(OL - $(LI current working directory) - $(LI directory specified by the $(B HOME) environment variable) - $(LI directory $(B dmd.exe) resides in) - ) + $(OL + $(LI current working directory) + $(LI directory specified by the $(B HOME) environment variable) + $(LI directory $(B dmd.exe) resides in) + ) - $(P If found, environment variable - settings in the file will override any existing settings. - This is handy to make $(B dmd) independent of programs with - conflicting use of environment variables. - ) + $(P If found, environment variable + settings in the file will override any existing settings. + This is handy to make $(B dmd) independent of programs with + conflicting use of environment variables. + ) -

    Initialization File Format

    +$(H3 Initialization File Format) - $(P Comments are lines that begin with $(D ;) and are ignored. - ) + $(P Comments are lines that begin with $(D ;) and are ignored. + ) - $(P Environment variables follow the $(D [Environment]) section - heading, in $(I NAME)=$(I value) pairs. - The $(I NAME)s are treated as upper case. - Comments are lines that start with ;. - For example: - ) + $(P Environment variables follow the $(D [Environment]) section + heading, in $(I NAME)=$(I value) pairs. + The $(I NAME)s are treated as upper case. + Comments are lines that start with ;. + For example: + ) $(SCINI ; sc.ini file for dmd @@ -811,65 +702,66 @@ $(SCINI ; to this file. [Environment] LIB="%@P%\..\lib";\dm\lib -$(V1 DFLAGS="-I%@P%\..\src\phobos") -$(V2 DFLAGS="-I%@P%\..\src\phobos" "-I%@P%\..\src\druntime\import") + +DFLAGS="-I%@P%\..\src\phobos" "-I%@P%\..\src\druntime\import" LINKCMD="%@P%\..\..\dm\bin" DDOCFILE=mysettings.ddoc ) -

    Location Independence of sc.ini

    +$(H3 Location Independence of sc.ini) - $(P The $(B %@P%) is replaced with the path to $(D sc.ini). - Thus, if the fully qualified file name $(D sc.ini) is - $(D c:$(DMDDIR)\bin\sc.ini), then $(B %@P%) will be replaced with - $(D c:$(DMDDIR)\bin), and the above $(D sc.ini) will be - interpreted as: - ) + $(P The $(B %@P%) is replaced with the path to $(D sc.ini). + Thus, if the fully qualified file name $(D sc.ini) is + $(D c:$(DMDDIR)\bin\sc.ini), then $(B %@P%) will be replaced with + $(D c:$(DMDDIR)\bin), and the above $(D sc.ini) will be + interpreted as: + ) $(SCINI [Environment] LIB="c:$(DMDDIR)\bin\..\lib";\dm\lib -$(V1 DFLAGS="-Ic:$(DMDDIR)\bin\..\src\phobos") -$(V2 DFLAGS="-Ic:$(DMDDIR)\bin\..\src\phobos" "-Ic:$(DMDDIR)\bin\..\src\druntime\import") + +DFLAGS="-Ic:$(DMDDIR)\bin\..\src\phobos" "-Ic:$(DMDDIR)\bin\..\src\druntime\import" LINKCMD="c:$(DMDDIR)\bin\..\..\dm\bin" DDOCFILE=mysettings.ddoc ) - $(P This enables your dmd setup to be moved around without having - to re-edit $(D sc.ini). - ) + $(P This enables your dmd setup to be moved around without having + to re-edit $(D sc.ini). + ) ) $(UNIX -

    $(LNAME2 dmd_conf, dmd.conf Initialization File)

    - - $(P The dmd file $(D dmd.conf) is the same as $(D sc.ini) - for Windows, it's just that the file has a different name, - enabling a setup common to both Windows and this system to be created - without having to re-edit the file.) - - $(P $(B dmd) will look for the initialization file $(D dmd.conf) in the - following sequence of directories:) - - $(OL - $(LI current working directory) - $(LI directory specified by the $(B HOME) environment variable) - $(LI directory $(B dmd) resides in) - $(LI $(D /etc/)) - ) - - $(P If found, environment variable - settings in the file will override any existing settings. - This is handy to make $(B dmd) independent of programs with - conflicting use of environment variables. - ) - - $(P Environment variables follow the $(D [Environment]) section - heading, in $(I NAME)=$(I value) pairs. - The $(I NAME)s are treated as upper case. - Comments are lines that start with ;. - For example: - ) +$(H2 $(LEGACY_LNAME2 dmd_conf, dmd-conf, dmd.conf Initialization File)) + + $(P The dmd file $(D dmd.conf) is the same as $(D sc.ini) + for Windows, it's just that the file has a different name, + enabling a setup common to both Windows and this system to be created + without having to re-edit the file.) + + $(P $(B dmd) will look for the initialization file $(D dmd.conf) in the + following sequence of directories:) + + $(OL + $(LI current working directory) + $(LI directory specified by the $(B HOME) environment variable) + $(LI as dotfile $(D .dmd.conf) in the directory specified by the $(B HOME) environment variable) + $(LI directory $(B dmd) resides in) + $(LI $(D /etc/)) + ) + + $(P If found, environment variable + settings in the file will override any existing settings. + This is handy to make $(B dmd) independent of programs with + conflicting use of environment variables. + ) + + $(P Environment variables follow the $(D [Environment]) section + heading, in $(I NAME)=$(I value) pairs. + The $(I NAME)s are treated as upper case. + Comments are lines that start with ;. + For example: + ) $(SCINI ; dmd.conf file for dmd @@ -877,100 +769,101 @@ $(SCINI ; and inserted. The special name %@P% is replaced with the path ; to this file. [Environment] -$(V1 DFLAGS=-I%@P%/../src/phobos) -$(V2 DFLAGS=-I%@P%/../src/phobos -I%@P%/../src/druntime/import) + +DFLAGS=-I%@P%/../src/phobos -I%@P%/../src/druntime/import ) ) $(WINDOWS -

    $(LNAME2 problems, Common Installation Problems)

    - - $(UL - $(LI Using Cygwin's $(B unzip) utility has been known to cause - strange problems. - ) - $(LI Running the compiler under Cygwin's command shell has - been also known to cause problems. Try getting it to work - under the regular Windows shell $(B cmd.exe) before trying Cygwin's. - ) - $(LI Installing $(B dmd) and $(B dmc) into directory paths with spaces - in them causes problems. - ) - ) +$(H2 $(LNAME2 problems, Common Installation Problems)) + + $(UL + $(LI Using Cygwin's $(B unzip) utility has been known to cause + strange problems. + ) + $(LI Running the compiler under Cygwin's command shell has + been also known to cause problems. Try getting it to work + under the regular Windows shell $(B cmd.exe) before trying Cygwin's. + ) + $(LI Installing $(B dmd) and $(B $(DMC)) into directory paths with spaces + in them causes problems. + ) + ) )
    -

    $(LNAME2 differences, Differences between Windows and Linux versions)

    +$(H2 $(LNAME2 differences, Differences between Windows and Linux versions)) - $(UL - $(LI String literals are read-only under Linux. - Attempting to write to them - will cause a segment violation.) - ) + $(UL + $(LI String literals are read-only under Linux. + Attempting to write to them + will cause a segment violation.) + )
    -

    $(LNAME2 interface_files, D Interface Files)

    - - $(P When an import declaration is processed in a D source file, - the compiler searches for the D source file corresponding to - the import, and processes that source file to extract the - information needed from it. Alternatively, the compiler can - instead look for a corresponding $(I D interface file). - A D interface file contains only what an import of the module - needs, rather than the whole implementation of that module. - ) - - $(P The advantages of using a D interface file for imports rather - than a D source file are: - ) - - $(UL - $(LI D interface files are often significantly smaller and much - faster to process than the corresponding D source file.) - $(LI They can be used to hide the source code, for example, - one can ship an object code library along with D interface files - rather than the complete source code.) - ) - - $(P D interface files can be created by the compiler from a - D source file by using the $(B -H) switch to the compiler. - D interface files have the $(B .di) file extension. - When the compiler resolves an import declaration, it first looks - for a $(B .di) D interface file, then it looks for a D source - file. - ) - - $(P D interface files bear some analogous similarities to C++ - header files. But they are not required in the way that C++ - header files are, and they are not part of the D language. - They are a feature of the compiler, and serve only as an optimization - of the build process. - ) - -

    $(LNAME2 executable, Building Executables)

    - - $(P $(B dmd) can build an executable much faster if as many of the - source files as possible are put on the command line.) - - $(P Another advantage to putting multiple source files on the same - invocation of $(B dmd) is that $(B dmd) will be able to do some level - of cross-module optimizations, such as function inlining across modules. - ) - -

    $(LNAME2 library, Building Libraries)

    - - $(P There are three ways to build a library. For example, - given $(D foo.d) and $(D bar.d) which are to be compiled, and existing - object file $(D bar.$(OBJEXT)) and existing library - $(D def.$(LIBEXT)) which are - all to be combined into a library $(D foo.$(LIBEXT)):) - - $(OL - $(LI Compile modules separately and then run the librarian on them: +$(H2 $(LEGACY_LNAME2 interface_files, interface-files, D Interface Files)) + + $(P When an import declaration is processed in a D source file, + the compiler searches for the D source file corresponding to + the import, and processes that source file to extract the + information needed from it. Alternatively, the compiler can + instead look for a corresponding $(I D interface file). + A D interface file contains only what an import of the module + needs, rather than the whole implementation of that module. + ) + + $(P The advantages of using a D interface file for imports rather + than a D source file are: + ) + + $(UL + $(LI D interface files are often significantly smaller and much + faster to process than the corresponding D source file.) + $(LI They can be used to hide the source code, for example, + one can ship an object code library along with D interface files + rather than the complete source code.) + ) + + $(P D interface files can be created by the compiler from a + D source file by using the $(SWLINK -H) switch to the compiler. + D interface files have the $(B .di) file extension. + When the compiler resolves an import declaration, it first looks + for a $(B .di) D interface file, then it looks for a D source + file. + ) + + $(P D interface files bear some analogous similarities to C++ + header files. But they are not required in the way that C++ + header files are, and they are not part of the D language. + They are a feature of the compiler, and serve only as an optimization + of the build process. + ) + +$(H2 $(LNAME2 executable, Building Executables)) + + $(P $(B dmd) can build an executable much faster if as many of the + source files as possible are put on the command line.) + + $(P Another advantage to putting multiple source files on the same + invocation of $(B dmd) is that $(B dmd) will be able to do some level + of cross-module optimizations, such as function inlining across modules. + ) + $(P The $(D -i) flag can be used to automatically compile imported modules) + +$(H2 $(LNAME2 library, Building Libraries)) + + $(P There are three ways to build a library. For example, + given $(D foo.d) and $(D bar.d) which are to be compiled, and existing + object file $(D abc.$(OBJEXT)) and existing library + $(D def.$(LIBEXT)) which are + all to be combined into a library $(D foo.$(LIBEXT)):) + + $(OL + $(LI Compile modules separately and then run the librarian on them: $(WINDOWS $(CONSOLE dmd -c foo.d dmd -c bar.d -$(LINK2 http://www.digitalmars.com/ctg/lib.html, lib) -c -p32 foo.lib foo.obj bar.obj abc.obj def.lib +$(LIB) -c -p32 foo.lib foo.obj bar.obj abc.obj def.lib del foo.obj bar.obj ) ) @@ -983,14 +876,14 @@ ar -r foo.a foo.o bar.o abc.o def.a rm foo.o bar.o ) ) - This option is typical when using a makefile to avoid compiling - modules that have already been compiled. - ) - $(LI Compile modules together and then run the librarian on them: + This option is typical when using a makefile to avoid compiling + modules that have already been compiled. + ) + $(LI Compile modules together and then run the librarian on them: $(WINDOWS $(CONSOLE dmd -c foo.d bar.d -$(LINK2 http://www.digitalmars.com/ctg/lib.html, lib) -c -p32 foo.lib foo.obj bar.obj abc.obj def.lib +$(LIB) -c -p32 foo.lib foo.obj bar.obj abc.obj def.lib del foo.obj bar.obj ) ) @@ -1002,23 +895,23 @@ ar -r foo.a foo.o bar.o abc.o def.a rm foo.o bar.o ) ) - ) - $(LI Use $(B dmd) to compile and build library in one operation: + ) + $(LI Use $(B dmd) to compile and build library in one operation: $(CONSOLE dmd -lib foo.d bar.d abc.$(OBJEXT) def.$(LIBEXT) ) - No object files are written to disk, it's all done in memory. - Using $(B -lib) also has the advantage that modules may be compiled - into multiple object files rather than exactly one per module. - This improves granularity of the library without having to break - up the modules. - ) - ) + No object files are written to disk, it's all done in memory. + Using $(SWLINK -lib) also has the advantage that modules may be compiled + into multiple object files rather than exactly one per module. + This improves granularity of the library without having to break + up the modules. + ) + ) -

    $(LNAME2 compiling_dmd, Compiling dmd)

    +$(H2 $(LEGACY_LNAME2 compiling_dmd, compiling-dmd, Compiling dmd)) - $(P Complete source code is provided to build the compiler. - Follow these steps:) + $(P Complete source code is provided to build the compiler. + Follow these steps:) $(WINDOWS $(CONSOLE @@ -1029,54 +922,56 @@ make -f win32.mak $(UNIX $(CONSOLE cd ~/$(DMDDIR)/src/dmd -make -f $(OS).mak +make -f posix.mak ) ) -

    $(LNAME2 compiling_phobos, Compiling Phobos)

    +$(H2 $(LEGACY_LNAME2 compiling_phobos, compiling-phobos, Compiling Phobos)) + + $(P Complete source code is provided to build Phobos, the D runtime library. + Follow these steps:) - $(P Complete source code is provided to build Phobos, the D runtime library. - Follow these steps:) -$(V1 -$(WINDOWS -$(CONSOLE -cd $(DMDDIR)\src\phobos -make -f win32.mak DMD=$(DMDDIR)\$(OS)\bin\dmd -) -) -$(UNIX -$(CONSOLE -cd ~/$(DMDDIR)/src/phobos -make -f $(OS).mak DMD=~/$(DMDDIR)/$(OS)/bin/dmd -) -) -) -$(V2 $(WINDOWS $(CONSOLE cd $(DMDDIR)\src\druntime -make -f win32.mak DMD=$(DMDDIR)\$(OS)\bin\dmd +make -f win32.mak cd ..\phobos -make -f win32.mak DMD=$(DMDDIR)\$(OS)\bin\dmd +make -f win32.mak ) ) $(UNIX $(CONSOLE -cd ~/$(DMDDIR)/src/druntime -make -f posix.mak DMD=~/$(DMDDIR)/$(OS)/bin/dmd cd ../phobos -make -f $(OS).mak DMD=~/$(DMDDIR)/$(OS)/bin/dmd -) +make -f posix.mak ) ) + ) Macros: - TITLE=DMD Compiler for $(WINDOWS Windows)$(LINUX Linux)$(OSX OSX)$(FREEBSD FreeBSD) - WIKI=DCompiler - LIB=$(WINDOWS phobos.lib)$(UNIX $(V1 libphobos.a)$(V2 libphobos2.a)) - DMD_CONF=$(LINK2 #dmd_conf, dmd.conf) - SWITCH=$(DT $1)$(DD $+) - CATEGORY_DOWNLOAD=$0 + TITLE=DMD Compiler for $(WINDOWS Windows)$(LINUX Linux)$(OSX OSX)$(FREEBSD FreeBSD) + BODYCLASS=std dcompiler + LIB=$(WINDOWS phobos.lib)$(UNIX libphobos2.a) + DMD_CONF=$(RELATIVE_LINK2 dmd-conf, dmd.conf) + SC_INI=$(RELATIVE_LINK2 sc-ini, $(DMDDIR)\windows\bin\sc.ini) + DMC=$(LINK2 http://www.digitalmars.com/ctg/sc.html, dmc) + OPTLINK=$(LINK2 http://www.digitalmars.com/ctg/optlink.html, optlink.exe) + DUB=$(LINK2 https://github.com/dlang/dub, dub$(BINEXT)) + RDMD=$(LINK2 $(ROOT_DIR)rdmd.html, rdmd$(BINEXT)) + DUSTMITE=$(LINK2 https://github.com/CyberShadow/DustMite, dustmite$(BINEXT)) + OBJ2ASM=$(HTTP digitalmars.com/ctg/obj2asm.html, obj2asm$(BINEXT)) + DUMPOBJ=$(HTTP digitalmars.com/ctg/dumpobj.html, dumpobj$(BINEXT)) + CLI_SWITCHES=$1 + SHELL=$(HTTP digitalmars.com/ctg/shell.html, shell) + SUBNAV=$(SUBNAV_CLI_REFERENCE) + INSTALLATION_SCRIPT_HINT= +$(P +$(MESSAGE_BOX gray, $(B Hint) - The official $(LINK2 $(ROOT_DIR)download.html, packages) +performs these steps automatically. +Alternatively, you can install DMD in your user directory with +the $(LINK2 $(ROOT_DIR)install.html, install script). +) +) + _ = diff --git a/dcompiler.html b/dcompiler.html deleted file mode 100644 index 59b47ecc96..0000000000 --- a/dcompiler.html +++ /dev/null @@ -1,9 +0,0 @@ - - - -D Runtime Library - - - - - diff --git a/ddoc.dd b/ddoc.dd deleted file mode 100644 index 162dcb98b1..0000000000 --- a/ddoc.dd +++ /dev/null @@ -1,914 +0,0 @@ -Ddoc - -$(SPEC_S Embedded Documentation, - -$(P -The D programming language enables embedding both contracts and test -code along side the actual code, which helps to keep them all -consistent with each other. One thing lacking is the documentation, -as ordinary comments are usually unsuitable for automated extraction -and formatting into manual pages. -Embedding the user documentation into the source code has important -advantages, such as not having to write the documentation twice, and -the likelihood of the documentation staying consistent with the code. -) - -$(P -Some existing approaches to this are: -) - -$(UL -$(LI Doxygen which already has some support for D) -$(LI Java's Javadoc, - probably the most well-known) -$(LI C#'s embedded XML) -$(LI Other documentation tools) -) - -$(P -D's goals for embedded documentation are: -) - -$(OL - $(LI It looks good as embedded documentation, not just after it - is extracted and processed.) - $(LI It's easy and natural to write, - i.e. minimal reliance on <tags> and other clumsy forms one - would never see in a finished document.) - $(LI It does not repeat information that the compiler already - knows from parsing the code.) - $(LI It doesn't rely on embedded HTML, as such will impede - extraction and formatting for other purposes.) - $(LI It's based on existing D comment forms, so it - is completely independent of parsers only interested in D code.) - $(LI It should look and feel different from code, so it won't - be visually confused with code.) - $(LI It should be possible for the user to use Doxygen or other - documentation extractor if desired.) -) - -

    Specification

    - -$(P -The specification for the form of embedded documentation comments only -specifies how information is to be presented to the compiler. -It is implementation-defined how that information is used and the form -of the final presentation. Whether the final presentation form is an -HTML web page, a man page, a PDF file, etc. is not specified as part of the -D Programming Language. -) - -

    Phases of Processing

    - -$(P -Embedded documentation comments are processed in a series of phases: -) - -$(OL - $(LI Lexical - documentation comments are identified and attached - to tokens.) - $(LI Parsing - documentation comments are associated with - specific declarations and combined.) - $(LI Sections - each documentation comment is divided up into - a sequence of sections.) - $(LI Special sections are processed.) - $(LI Highlighting of non-special sections is done.) - $(LI All sections for the module are combined.) - $(LI Macro text substitution is performed to produce the final result.) -) - -

    Lexical

    - -$(P -Embedded documentation comments are one of the following forms: -) - -$(OL - $(LI $(D_COMMENT /** ... */) The two *'s after the opening /) - $(LI $(D_COMMENT /++ ... +/) The two +'s after the opening /) - $(LI $(D_COMMENT ///) The three slashes) -) - -$(P The following are all embedded documentation comments:) - ---------------------------- -/// This is a one line documentation comment. - -/** So is this. */ - -/++ And this. +/ - -/** - This is a brief documentation comment. - */ - -/** - * The leading * on this line is not part of the documentation comment. - */ - -/********************************* - The extra *'s immediately following the /** are not - part of the documentation comment. - */ - -/++ - This is a brief documentation comment. - +/ - -/++ - + The leading + on this line is not part of the documentation comment. - +/ - -/+++++++++++++++++++++++++++++++++ - The extra +'s immediately following the / ++ are not - part of the documentation comment. - +/ - -/**************** Closing *'s are not part *****************/ ---------------------------- - -$(P -The extra *'s and +'s on the comment opening, closing and left margin are -ignored and are not part -of the embedded documentation. -Comments not following one of those forms are not documentation comments. -) - -

    Parsing

    - -$(P -Each documentation comment is associated with a declaration. -If the documentation comment is on a line by itself or with only whitespace -to the left, it refers to the next -declaration. -Multiple documentation comments applying to the same declaration -are concatenated. -Documentation comments not associated with a declaration are ignored. -Documentation comments preceding the $(I ModuleDeclaration) apply to the -entire module. -If the documentation comment appears on the same line to the right of a -declaration, it applies to that. -) - -$(P -If a documentation comment for a declaration consists only of the -identifier $(D ditto) -then the documentation comment for the previous declaration at the same -declaration scope is applied to this declaration as well. -) - -$(P -If there is no documentation comment for a declaration, that declaration -may not appear in the output. To ensure it does appear in the output, -put an empty declaration comment for it. -) - ------------------------------------- -int a; /// documentation for a; b has no documentation -int b; - -/** documentation for c and d */ -/** more documentation for c and d */ -int c; -/** ditto */ -int d; - -/** documentation for e and f */ int e; -int f; /// ditto - -/** documentation for g */ -int g; /// more documentation for g - -/// documentation for C and D -class C { - int x; /// documentation for C.x - - /** documentation for C.y and C.z */ - int y; - int z; /// ditto -} - -/// ditto -class D { } ------------------------------------- - -

    Sections

    - -$(P -The document comment is a series of $(I Section)s. -A $(I Section) is a name that is the first non-blank character on -a line immediately followed by a ':'. This name forms the section name. -The section name is not case sensitive. -) - -

    Summary

    - -$(P -The first section is the $(I Summary), and does not have a section name. -It is first paragraph, up to a blank line or a section name. -While the summary can be any length, try to keep it to one line. -The $(I Summary) section is optional. -) - -

    Description

    - -$(P -The next unnamed section is the $(I Description). -It consists of all the paragraphs following the $(I Summary) until -a section name is encountered or the end of the comment. -) - -$(P -While the $(I Description) section is optional, -there cannot be a $(I Description) without a $(I Summary) section. -) - ------------------------------------- -/*********************************** - * Brief summary of what - * myfunc does, forming the summary section. - * - * First paragraph of synopsis description. - * - * Second paragraph of - * synopsis description. - */ - -void myfunc() { } ------------------------------------- - -$(P -Named sections follow the $(I Summary) and $(I Description) unnamed sections. -) - -

    Standard Sections

    - -$(P -For consistency and predictability, there are several standard sections. -None of these are required to be present. -) - -
    - -
    $(B Authors:) -
    Lists the author(s) of the declaration. ------------------------------------- -/** - * Authors: Melvin D. Nerd, melvin@mailinator.com - */ ------------------------------------- - -
    $(B Bugs:) -
    Lists any known bugs. ------------------------------------- -/** - * Bugs: Doesn't work for negative values. - */ ------------------------------------- - -
    $(B Date:) -
    Specifies the date of the current revision. The date should be in a form - parseable by std.date. - ------------------------------------- -/** - * Date: March 14, 2003 - */ ------------------------------------- - -
    $(B Deprecated:) -
    Provides an explanation for and corrective action to take if the associated - declaration is marked as deprecated. - ------------------------------------- -/** - * Deprecated: superseded by function bar(). - */ - -deprecated void foo() { ... } ------------------------------------- - -
    $(B Examples:) -
    Any usage examples ------------------------------------- -/** - * Examples: - * -------------------- - * writefln("3"); // writes '3' to stdout - * -------------------- - */ ------------------------------------- - -
    $(B History:) -
    Revision history. ------------------------------------- -/** - * History: - * V1 is initial version - * - * V2 added feature X - */ ------------------------------------- - -
    $(B License:) -
    Any license information for copyrighted code. ------------------------------------- -/** - * License: use freely for any purpose - */ - -void bar() { ... } ------------------------------------- - -
    $(B Returns:) -
    Explains the return value of the function. - If the function returns $(B void), don't redundantly document it. ------------------------------------- -/** - * Read the file. - * Returns: The contents of the file. - */ - -void[] readFile(char[] filename) { ... } ------------------------------------- - -
    $(B See_Also:) -
    List of other symbols and URL's to related items. ------------------------------------- -/** - * See_Also: - * foo, bar, http://www.digitalmars.com/d/phobos/index.html - */ ------------------------------------- - -
    $(B Standards:) -
    If this declaration is compliant with any particular standard, -the description of it goes here. ------------------------------------- -/** - * Standards: Conforms to DSPEC-1234 - */ ------------------------------------- - -
    $(B Throws:) -
    Lists exceptions thrown and under what circumstances they are thrown. ------------------------------------- -/** - * Write the file. - * Throws: WriteException on failure. - */ - -void writeFile(char[] filename) { ... } ------------------------------------- - -
    $(B Version:) -
    Specifies the current version of the declaration. ------------------------------------- -/** - * Version: 1.6a - */ ------------------------------------- -
    - -

    Special Sections

    - -$(P -Some sections have specialized meanings and syntax. -) - -
    - -
    $(B Copyright:) -
    This contains the copyright notice. The macro COPYRIGHT is set to - the contents of the section when it documents the module declaration. - The copyright section only gets this special treatment when it - is for the module declaration. - ------------------------------------- -/** Copyright: Public Domain */ - -module foo; ------------------------------------- - -
    $(B Params:) -
    Function parameters can be documented by listing them in a params - section. Each line that starts with an identifier followed by - an '=' starts a new parameter description. A description can - span multiple lines. - ------------------------- -/*********************************** - * foo does this. - * Params: - * x = is for this - * and not for that - * y = is for that - */ - -void foo(int x, int y) -{ -} -------------------------- - -
    $(B Macros:)
    -
    The macros section follows the same syntax as the $(B Params:) section. - It's a series of $(I NAME)=$(I value) pairs. - The $(I NAME) is the macro name, and $(I value) is the replacement - text. ------------------------------------- -/** - * Macros: - * FOO = now is the time for - * all good men - * BAR = bar - * MAGENTA = <font color=magenta>$0</font> - */ ------------------------------------- -
    - -

    Highlighting

    - -

    Embedded Comments

    - -$(P - The documentation comments can themselves be commented using - the $(DDOC_COMMENT comment text) syntax. These comments do not - nest. -) - -

    Embedded Code

    - -$(P - D code can be embedded using lines beginning with at least three - hyphens (ignoring whitespace) to delineate the code section: -) - ------------------------------------- -/++ - + Our function. - + - + Example: - + --- - + import std.stdio; - + - + void foo() - + { - + writefln("foo!"); /* print the string */ - + } - + --- - +/ ------------------------------------- - -$(P - Note that the documentation comment uses the $(D_COMMENT /++ ... +/) - form - so that $(D_COMMENT /* ... */) can be used inside the code section. -) - -

    Embedded HTML

    - -$(P -HTML can be embedded into the documentation comments, and it will -be passed through to the HTML output unchanged. -However, since it is not necessarily true that HTML will be the desired -output format of the embedded documentation comment extractor, it is -best to avoid using it where practical. -) - ------------------------------------- -/** - * Example of embedded HTML: - * - *
      - *
    1. Digital Mars
    2. - *
    3. Empire
    4. - *
    - */ ------------------------------------- - -

    Emphasis

    - -$(P -Identifiers in documentation comments that are function parameters or are -names that are in scope at the associated declaration are emphasized in -the output. -This emphasis can take the form of italics, boldface, a hyperlink, etc. -How it is emphasized depends on what it is - a function parameter, type, -D keyword, etc. -To prevent unintended emphasis of an identifier, it can be preceded by -an underscore (_). The underscore will be stripped from the output. -) - -

    Character Entities

    - -$(P - Some characters have special meaning - to the documentation processor, to avoid confusion it can be best - to replace them with their corresponding character entities: -) - - $(TABLE2 Characters and Entities, - $(TR $(TH Character) $(TH Entity)) - $(TR $(TD < )$(TD &lt; )) - $(TR $(TD > )$(TD &gt; )) - $(TR $(TD & )$(TD &amp; )) - ) - -$(P - It is not necessary to do this inside a code section, or if the - special character is not immediately followed by a # or a letter. -) - -

    No Documentation

    - -$(P - No documentation is generated for the following constructs, - even if they have a documentation comment: -) - - $(UL - $(LI Invariants) -$(V2 $(LI Postblits)) - $(LI Destructors) - $(LI Static constructors and static destructors) - $(LI Class info, type info, and module info) - ) - -

    Macros

    - -$(P - The documentation comment processor includes a simple macro - text preprocessor. - When a $($(I NAME)) appears - in section text it is replaced with $(I NAME)'s corresponding - replacement text. - The replacement text is then recursively scanned for more macros. - If a macro is recursively encountered, with no argument or with - the same argument text as the enclosing macro, it is replaced - with no text. - Macro invocations that cut across replacement text boundaries are - not expanded. - If the macro name is undefined, the replacement text has no characters - in it. - If a $(NAME) is desired to exist in the output without being - macro expanded, the $ should be replaced with &#36;. -) - -$(P - Macros can have arguments. Any text from the end of the identifier - to the closing $(SINGLEQUOTE $(RPAREN)) is the $0 argument. - A $0 in the replacement text is - replaced with the argument text. - If there are commas in the argument text, $1 will represent the - argument text up to the first comma, $2 from the first comma to - the second comma, etc., up to $9. - $+ represents the text from the first comma to the closing $(SINGLEQUOTE $(RPAREN)). - The argument text can contain nested parentheses, "" or '' strings, - comments, or tags. - If stray, unnested parentheses are used, they can be replaced with - the entity &#40; for ( and &#41; for ). -) - -$(P - Macro definitions come from the following sources, - in the specified order: -) - - $(OL - $(LI Predefined macros.) - $(LI Definitions from file specified by $(DPLLINK dmd-windows.html#sc_ini, sc.ini)'s - or $(DPLLINK dmd-linux.html#dmd_conf, dmd.conf) DDOCFILE setting.) - $(LI Definitions from *.ddoc files specified on the command line.) - $(LI Runtime definitions generated by Ddoc.) - $(LI Definitions from any Macros: sections.) - ) - -$(P - Macro redefinitions replace previous definitions of the same name. - This means that the sequence of macro definitions from the various - sources forms a hierarchy. -) - -$(P - Macro names beginning with "D_" and "DDOC_" are reserved. -) - -

    Predefined Macros

    - -$(P - These are hardwired into Ddoc, and represent the - minimal definitions needed by Ddoc to format and highlight - the presentation. - The definitions are for simple HTML. -) - -$(DDOCCODE -B = <b>$0</b> -I = <i>$0</i> -U = <u>$0</u> -P = <p>$0</p> -DL = <dl>$0</dl> -DT = <dt>$0</dt> -DD = <dd>$0</dd> -TABLE = <table>$0</table> -TR = <tr>$0</tr> -TH = <th>$0</th> -TD = <td>$0</td> -OL = <ol>$0</ol> -UL = <ul>$0</ul> -LI = <li>$0</li> -BIG = <big>$0</big> -SMALL = <small>$0</small> -BR = <br> -LINK = <a href="https://github.com/$0">$0</a> -LINK2 = <a href="https://github.com/$1">$+</a> -LPAREN= $(LPAREN) -RPAREN= $(RPAREN) - -RED = <font color=red>$0</font> -BLUE = <font color=blue>$0</font> -GREEN = <font color=green>$0</font> -YELLOW =<font color=yellow>$0</font> -BLACK = <font color=black>$0</font> -WHITE = <font color=white>$0</font> - -D_CODE = <pre class="d_code">$0</pre> -D_COMMENT = $(GREEN $0) -D_STRING = $(RED $0) -D_KEYWORD = $(BLUE $0) -D_PSYMBOL = $(U $0) -D_PARAM = $(I $0) - -DDOC = <html><head> - <META http-equiv="content-type" content="text/html; charset=utf-8"> - <title>$(TITLE)</title> - </head><body> - <h1>$(TITLE)</h1> - $(BODY) - </body></html> - -DDOC_COMMENT = <!-- $0 --> -DDOC_DECL = $(DT $(BIG $0)) -DDOC_DECL_DD = $(DD $0) -DDOC_DITTO = $(BR)$0 -DDOC_SECTIONS = $0 -DDOC_SUMMARY = $0$(BR)$(BR) -DDOC_DESCRIPTION = $0$(BR)$(BR) -DDOC_AUTHORS = $(B Authors:)$(BR) - $0$(BR)$(BR) -DDOC_BUGS = $(RED BUGS:)$(BR) - $0$(BR)$(BR) -DDOC_COPYRIGHT = $(B Copyright:)$(BR) - $0$(BR)$(BR) -DDOC_DATE = $(B Date:)$(BR) - $0$(BR)$(BR) -DDOC_DEPRECATED = $(RED Deprecated:)$(BR) - $0$(BR)$(BR) -DDOC_EXAMPLES = $(B Examples:)$(BR) - $0$(BR)$(BR) -DDOC_HISTORY = $(B History:)$(BR) - $0$(BR)$(BR) -DDOC_LICENSE = $(B License:)$(BR) - $0$(BR)$(BR) -DDOC_RETURNS = $(B Returns:)$(BR) - $0$(BR)$(BR) -DDOC_SEE_ALSO = $(B See Also:)$(BR) - $0$(BR)$(BR) -DDOC_STANDARDS = $(B Standards:)$(BR) - $0$(BR)$(BR) -DDOC_THROWS = $(B Throws:)$(BR) - $0$(BR)$(BR) -DDOC_VERSION = $(B Version:)$(BR) - $0$(BR)$(BR) -DDOC_SECTION_H = $(B $0)$(BR)$(BR) -DDOC_SECTION = $0$(BR)$(BR) -DDOC_MEMBERS = $(DL $0) -DDOC_MODULE_MEMBERS = $(DDOC_MEMBERS $0) -DDOC_CLASS_MEMBERS = $(DDOC_MEMBERS $0) -DDOC_STRUCT_MEMBERS = $(DDOC_MEMBERS $0) -DDOC_ENUM_MEMBERS = $(DDOC_MEMBERS $0) -DDOC_TEMPLATE_MEMBERS = $(DDOC_MEMBERS $0) -DDOC_PARAMS = $(B Params:)$(BR)\n$(TABLE $0)$(BR) -DDOC_PARAM_ROW = $(TR $0) -DDOC_PARAM_ID = $(TD $0) -DDOC_PARAM_DESC = $(TD $0) -DDOC_BLANKLINE = $(BR)$(BR) - -DDOC_PSYMBOL = $(U $0) -DDOC_KEYWORD = $(B $0) -DDOC_PARAM = $(I $0) -) - -$(P - Ddoc does not generate HTML code. It formats into the basic - formatting macros, which (in their predefined form) - are then expanded into HTML. - If output other than HTML is desired, then these macros - need to be redefined. -) - - $(TABLE2 Basic Formatting Macros, - $(TR $(TD $(B B)) $(TD boldface the argument)) - $(TR $(TD $(B I)) $(TD italicize the argument)) - $(TR $(TD $(B U)) $(TD underline the argument)) - $(TR $(TD $(B P)) $(TD argument is a paragraph)) - $(TR $(TD $(B DL)) $(TD argument is a definition list)) - $(TR $(TD $(B DT)) $(TD argument is a definition in a definition list)) - $(TR $(TD $(B DD)) $(TD argument is a description of a definition)) - $(TR $(TD $(B TABLE)) $(TD argument is a table)) - $(TR $(TD $(B TR)) $(TD argument is a row in a table)) - $(TR $(TD $(B TH)) $(TD argument is a header entry in a row)) - $(TR $(TD $(B TD)) $(TD argument is a data entry in a row)) - $(TR $(TD $(B OL)) $(TD argument is an ordered list)) - $(TR $(TD $(B UL)) $(TD argument is an unordered list)) - $(TR $(TD $(B LI)) $(TD argument is an item in a list)) - $(TR $(TD $(B BIG)) $(TD argument is one font size bigger)) - $(TR $(TD $(B SMALL)) $(TD argument is one font size smaller)) - $(TR $(TD $(B BR)) $(TD start new line)) - $(TR $(TD $(B LINK)) $(TD generate clickable link on argument)) - $(TR $(TD $(B LINK2)) $(TD generate clickable link, first arg is address)) - $(TR $(TD $(B RED)) $(TD argument is set to be red)) - $(TR $(TD $(B BLUE)) $(TD argument is set to be blue)) - $(TR $(TD $(B GREEN)) $(TD argument is set to be green)) - $(TR $(TD $(B YELLOW)) $(TD argument is set to be yellow)) - $(TR $(TD $(B BLACK)) $(TD argument is set to be black)) - $(TR $(TD $(B WHITE)) $(TD argument is set to be white)) - $(TR $(TD $(B D_CODE)) $(TD argument is D code)) - $(TR $(TD $(B DDOC)) $(TD overall template for output)) - ) - -$(P - $(B DDOC) is special in that it specifies the boilerplate into - which the entire generated text is inserted (represented by the - Ddoc generated macro $(B BODY)). For example, in order - to use a style sheet, $(B DDOC) would be redefined as: -) - -$(DDOCCODE -DDOC = <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> - <html><head> - <META http-equiv="content-type" content="text/html; charset=utf-8"> - <title>$(TITLE)</title> - <link rel="stylesheet" type="text/css" href="https://github.com/$(B%20style.css)"> - </head><body> - <h1>$(TITLE)</h1> - $(BODY) - </body></html> -) - -$(P - $(B DDOC_COMMENT) is used to insert comments into the output - file. -) - -$(P - Highlighting of D code is performed by the following macros: -) - - $(TABLE2 D Code Formatting Macros, - $(TR $(TD $(B D_COMMENT)) $(TD Highlighting of comments)) - $(TR $(TD $(B D_STRING)) $(TD Highlighting of string literals)) - $(TR $(TD $(B D_KEYWORD)) $(TD Highlighting of D keywords)) - $(TR $(TD $(B D_PSYMBOL)) $(TD Highlighting of current declaration name)) - $(TR $(TD $(B D_PARAM)) $(TD Highlighting of current function declaration parameters)) - ) - -$(P - The highlighting macros start with $(B DDOC_). - They control the formatting of individual parts of the presentation. -) - - $(TABLE2 Ddoc Section Formatting Macros, - $(TR $(TD $(B DDOC_DECL)) $(TD Highlighting of the declaration.)) - $(TR $(TD $(B DDOC_DECL_DD)) $(TD Highlighting of the description of a declaration.)) - $(TR $(TD $(B DDOC_DITTO)) $(TD Highlighting of ditto declarations.)) - $(TR $(TD $(B DDOC_SECTIONS)) $(TD Highlighting of all the sections.)) - $(TR $(TD $(B DDOC_SUMMARY)) $(TD Highlighting of the summary section.)) - $(TR $(TD $(B DDOC_DESCRIPTION)) $(TD Highlighting of the description section.)) - $(TR $(TD $(B DDOC_AUTHORS .. DDOC_VERSION)) $(TD Highlighting of the corresponding standard section.)) - $(TR $(TD $(B DDOC_SECTION_H)) $(TD Highlighting of the section name of a non-standard section.)) - $(TR $(TD $(B DDOC_SECTION)) $(TD Highlighting of the contents of a non-standard section.)) - $(TR $(TD $(B DDOC_MEMBERS)) $(TD Default highlighting of all the members of a class, struct, etc.)) - $(TR $(TD $(B DDOC_MODULE_MEMBERS)) $(TD Highlighting of all the members of a module.)) - $(TR $(TD $(B DDOC_CLASS_MEMBERS)) $(TD Highlighting of all the members of a class.)) - $(TR $(TD $(B DDOC_STRUCT_MEMBERS)) $(TD Highlighting of all the members of a struct.)) - $(TR $(TD $(B DDOC_ENUM_MEMBERS)) $(TD Highlighting of all the members of an enum.)) - $(TR $(TD $(B DDOC_TEMPLATE_MEMBERS)) $(TD Highlighting of all the members of a template.)) - $(TR $(TD $(B DDOC_PARAMS)) $(TD Highlighting of a function parameter section.)) - $(TR $(TD $(B DDOC_PARAM_ROW)) $(TD Highlighting of a name=value function parameter.)) - $(TR $(TD $(B DDOC_PARAM_ID)) $(TD Highlighting of the parameter name.)) - $(TR $(TD $(B DDOC_PARAM_DESC)) $(TD Highlighting of the parameter value.)) - $(TR $(TD $(B DDOC_PSYMBOL)) $(TD Highlighting of declaration name to which a particular section is referring.)) - $(TR $(TD $(B DDOC_KEYWORD)) $(TD Highlighting of D keywords.)) - $(TR $(TD $(B DDOC_PARAM)) $(TD Highlighting of function parameters.)) - $(TR $(TD $(B DDOC_BLANKLINE)) $(TD Inserts a blank line.)) - ) - -$(P - For example, one could redefine $(B DDOC_SUMMARY): -) - -$(DDOCCODE -DDOC_SUMMARY = $(GREEN $0) -) - -$(P - And all the summary sections will now be green. -) - -

    Macro Definitions from $(DPLLINK dmd-windows.html#sc_ini, $(D sc.ini))'s DDOCFILE

    - -$(P - A text file of macro definitions can be created, - and specified in $(D sc.ini): -) - -$(DDOCCODE -DDOCFILE=myproject.ddoc -) - -

    Macro Definitions from .ddoc Files on the Command Line

    - -$(P - File names on the DMD command line with the extension - .ddoc are text files that are read and processed in order. -) - -

    Macro Definitions Generated by Ddoc

    - - $(TABLE2 Generated Macro Definitions, - $(TR - $(TH Macro Name) - $(TH Contents) - ) - $(TR - $(TD $(B BODY)) - $(TD Set to the generated document text.) - ) - $(TR - $(TD $(B TITLE)) - $(TD Set to the module name.) - ) - $(TR - $(TD $(B DATETIME)) - $(TD Set to the current date and time.) - ) - $(TR - $(TD $(B YEAR)) - $(TD Set to the current year.) - ) - $(TR - $(TD $(B COPYRIGHT)) - $(TD Set to the contents of any $(B Copyright:) section that is part - of the module comment.) - ) - $(TR - $(TD $(B DOCFILENAME)) - $(TD Set to the name of the generated output file.) - ) - ) - -

    Using Ddoc for other Documentation

    - -$(P - Ddoc is primarily designed for use in producing documentation - from embedded comments. It can also, however, be used for - processing other general documentation. - The reason for doing this would be to take advantage of the - macro capability of Ddoc and the D code syntax highlighting - capability. -) - -$(P - If the .d source file starts with the string "Ddoc" then it - is treated as general purpose documentation, not as a D - code source file. From immediately after the "Ddoc" string - to the end of the file or any "Macros:" section forms - the document. No automatic highlighting is done to that text, - other than highlighting of D code embedded between lines - delineated with --- lines. Only macro processing is done. -) - -$(P - Much of the D documentation itself is generated this way, - including this page. - Such documentation is marked at the bottom as being - generated by Ddoc. -) - -

    References

    - -$(P - $(LINK2 http://www.dsource.org/projects/helix/wiki/CandyDoc, CandyDoc) - is a very nice example of how - one can customize the Ddoc results with macros - and style sheets. -) - -) - -Macros: - TITLE=Documentation Generator - WIKI=Ddoc - CATEGORY_SPEC=$0 - RPAREN=) diff --git a/ddoc/.gitignore b/ddoc/.gitignore new file mode 100644 index 0000000000..646b0fa1e8 --- /dev/null +++ b/ddoc/.gitignore @@ -0,0 +1,4 @@ +/libddoc_preprocessor.a +/ddoc_preprocessor +/ddoc_preprocessor-test-application +/ddoc_preprocessor-test-library diff --git a/ddoc/dub.sdl b/ddoc/dub.sdl new file mode 100644 index 0000000000..6fce22a829 --- /dev/null +++ b/ddoc/dub.sdl @@ -0,0 +1,14 @@ +name "ddoc_preprocessor" +description "Preprocesses source code before running Ddoc over it" +dependency "libdparse" version="~>0.15.1" +# we only need an isolated single module from DMD +sourceFiles "../../dmd/compiler/src/dmd/cli.d" +importPaths "source" "../../dmd/compiler/src" +versions "DdocOptions" # for dmd.cli +buildRequirements "disallowDeprecations" +configuration "executable" { + versions "IsExecutable" + targetType "executable" +} +configuration "library" { +} diff --git a/ddoc/dub.selections.json b/ddoc/dub.selections.json new file mode 100644 index 0000000000..0d6de82c2c --- /dev/null +++ b/ddoc/dub.selections.json @@ -0,0 +1,7 @@ +{ + "fileVersion": 1, + "versions": { + "libdparse": "0.15.4", + "stdx-allocator": "2.77.5" + } +} diff --git a/ddoc/source/assert_writeln_magic.d b/ddoc/source/assert_writeln_magic.d new file mode 100755 index 0000000000..353c5d24cf --- /dev/null +++ b/ddoc/source/assert_writeln_magic.d @@ -0,0 +1,325 @@ +#!/usr/bin/env dub +/++ dub.sdl: +dependency "libdparse" version="~>0.24.0" +name "assert_writeln_magic" ++/ +/* + * Tries to convert `assert`s into user-friendly `writeln` calls. + * The objective of this tool is to be conservative as + * broken example look a lot worse than a few statements + * that could have potentially been rewritten. + * + * - only EqualExpressions are "lowered" + * - static asserts are ignored + * - only single-line assers are rewritten + * + * Copyright (C) 2017 by D Language Foundation + * + * Author: Sebastian Wilzbach + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) +*/ +// Written in the D programming language. + +import dparse.ast; +import std.algorithm; +import std.conv; +import std.experimental.logger; +import std.range; +import std.stdio; +import std.typecons; + +private string formatNode(T)(const T t) +{ + import dparse.formatter; + import std.array : appender; + + auto writer = appender!string(); + auto formatter = new Formatter!(typeof(writer))(writer); + formatter.format(t); + return writer.data; +} + +class TestVisitor(Out) : ASTVisitor +{ + import dparse.lexer : tok, Token; + + this(Out fl) + { + this.fl = fl; + } + + alias visit = ASTVisitor.visit; + + override void visit(const Unittest test) + { + resetTestState(); + inTest = true; + scope(exit) inTest = false; + test.accept(this); + + processLastAssert(); + } + + override void visit(const EqualExpression expr) + { + enum eqToken = tok!"=="; + if (inAssert && expr.operator == eqToken && expr.left !is null && expr.right !is null) + lastEqualExpression = expr; + } + + override void visit(const AssertExpression expr) + { + if (inFunctionCall) + return; + + // only look at `a == b` within the AssertExpression + if (!expr.assertArguments || + typeid(expr.assertArguments.assertion) != typeid(CmpExpression)) + return; + + lastAssert = expr; + inAssert = true; + expr.accept(this); + inAssert = false; + fromAssert = true; + } + + // for now static asserts are ignored + override void visit(const StaticAssertStatement expr) + { + fromStaticAssert = true; + expr.accept(this); + } + + /** + The following code (in std.concurrency) leads to false positives: + + assertNotThrown!AssertError(assert(receiveOnly!int() == i)); + + Hence we simply ignore all asserts in function calls. + */ + override void visit(const FunctionCallExpression expr) + { + inFunctionCall = true; + expr.accept(this); + inFunctionCall = false; + } + + /// A single line + override void visit(const DeclarationOrStatement expr) + { + processLastAssert(); + expr.accept(this); + } + + void processLastAssert() + { + import std.uni : isWhite; + import std.format : format; + + if (fromAssert && !fromStaticAssert && + lastEqualExpression !is null && lastAssert !is null) + { + auto e = lastEqualExpression; + if (e.left !is null && e.right !is null) + { + // libdparse starts the line count with 1 + auto lineNr = lastAssert.line - 1; + + // only replace single-line expressions (for now) + if (fl[lineNr].endsWith(";")) + { + auto wsLen = fl[lineNr].countUntil!(u => !u.isWhite); + auto indent = fl[lineNr][0 .. wsLen]; + + if (fl[lineNr][wsLen .. $].startsWith("assert", "static assert")) + { + auto left = lastEqualExpression.left.formatNode; + auto right = lastEqualExpression.right.formatNode; + + if (left.length + right.length > 80) + fl[lineNr] = format("%s// %s\n%swriteln(%s);", indent, right, indent, left); + else + fl[lineNr] = format("%swriteln(%s); // %s", indent, left, right); + + //writefln("line: %d, column: %d", lastAssert.line, lastAssert.column); + } + } + } + } + resetTestState(); + } + +private: + + void resetTestState() + { + fromAssert = false; + fromStaticAssert = false; + lastEqualExpression = null; + lastAssert = null; + } + + /// within in the node + bool inTest; + bool inAssert; + bool inFunctionCall; + + /// at a sibling after the node was seen, but the upper parent hasn't been reached yet + bool fromAssert; + bool fromStaticAssert; + + Rebindable!(const AssertExpression) lastAssert; + Rebindable!(const EqualExpression) lastEqualExpression; + + Out fl; +} + +void parseString(Visitor)(const string filepath, ubyte[] sourceCode, Visitor visitor) +{ + import dparse.lexer; + import dparse.parser : parseModule, ParserConfig; + import dparse.rollback_allocator : RollbackAllocator; + + LexerConfig config; + auto cache = StringCache(StringCache.defaultBucketCount); + const(Token)[] tokens = getTokensForParser(sourceCode, config, &cache).array; + + RollbackAllocator rba; + auto m = parseModule(ParserConfig(tokens, filepath, &rba)); + visitor.visit(m); +} + +private auto assertWritelnModuleImpl(const string filepath, string fileText) +{ + import std.string : representation; + auto fl = FileLines(fileText); + scope visitor = new TestVisitor!(typeof(fl))(fl); + // libdparse doesn't allow to work on immutable source code + parseString(filepath, cast(ubyte[]) fileText.representation, visitor); + return fl; +} + +auto assertWritelnModule(const string filepath, string fileText) +{ + return assertWritelnModuleImpl(filepath, fileText).buildLines; +} +auto assertWritelnBlock(const string filepath, string fileText) +{ + auto source = "unittest{\n" ~ fileText ~ "}\n"; + auto fl = assertWritelnModuleImpl(filepath, source); + auto app = appender!string; + foreach (line; fl.lines[1 .. $ - 2]) + { + app ~= line; + app ~= "\n"; + } + return app.data; +} + +/** +A simple line-based in-memory representation of a file. + - will automatically write all changes when the object is destructed + - will use a temporary file to do safe, whole file swaps +*/ +struct FileLines +{ + import std.array, std.file, std.path; + + string[] lines; + string destFile; + bool hasWrittenChanges; + + this(string inputText) + { + lines = inputText.split("\n"); + } + + // writes all changes to a random, temporary file + auto buildLines() { + auto app = appender!string; + // dump file + foreach (line; lines) + { + app ~= line; + app ~= "\n"; + } + // within the docs we automatically inject std.stdio (hence we need to do the same here) + // writeln needs to be @nogc, @safe, pure and nothrow (we just fake it) + app ~= "// \nprivate void writeln(T)(T l) { }"; + return app.data; + } + + string opIndex(size_t i) { return lines[i]; } + void opIndexAssign(string line, size_t i) { + hasWrittenChanges = true; + lines[i] = line; + } +} + +version(unittest) +{ + struct FileLinesMock + { + string[] lines; + string opIndex(size_t i) { return lines[i]; } + void opIndexAssign(string line, size_t i) { + lines[i] = line; + } + } + auto runTest(string sourceCode) + { + import std.string : representation; + auto mock = FileLinesMock(sourceCode.split("\n")); + scope visitor = new TestVisitor!(typeof(mock))(mock); + parseString("unittest.d", sourceCode.representation.dup, visitor); + return mock; + } +} + + +unittest +{ + "Running tests for assert_writeln_magic".writeln; + + // purposefully not indented + string testCode = q{ +unittest +{ +assert(equal(splitter!(a => a == ' ')("hello world"), [ "hello", "", "world" ])); +assert(equal(splitter!(a => a == 0)(a), w)); +} + }; + auto res = runTest(testCode); + assert(res.lines[3 .. $ - 2] == [ + "assert(equal(splitter!(a => a == ' ')(\"hello world\"), [ \"hello\", \"\", \"world\" ]));", + "assert(equal(splitter!(a => a == 0)(a), w));" + ]); +} + +unittest +{ + string testCode = q{ +unittest +{ +assert(1 == 2); +assert(foo() == "bar"); +assert(foo() == bar); +assert(arr == [0, 1, 2]); +assert(r.back == 1); +} + }; + auto res = runTest(testCode); + assert(res.lines[3 .. $ - 2] == [ + "writeln(1); // 2", + "writeln(foo()); // \"bar\"", + "writeln(foo()); // bar", + "writeln(arr); // [0, 1, 2]", + "writeln(r.back); // 1", + ]); + + "Successfully ran tests for assert_writeln_magic".writeln; +} diff --git a/ddoc/source/preprocessor.d b/ddoc/source/preprocessor.d new file mode 100644 index 0000000000..2ca4262cb4 --- /dev/null +++ b/ddoc/source/preprocessor.d @@ -0,0 +1,505 @@ +#!/usr/bin/env rdmd +/** +A wrapper around DDoc to allow custom extensions + +Copyright: D Language Foundation 2018 + +License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). + +Example usage: + +--- +./ddoc --compiler= +--- + +Author: Sebastian Wilzbach +*/ +import std.algorithm, std.array, std.ascii, std.conv, std.file, std.format, std.functional, + std.meta, std.path, std.range, std.string, std.typecons; +import std.stdio; + +import dmd.cli; + +struct Config +{ + string dmdBinPath = "dmd"; + string cwd = __FILE_FULL_PATH__.dirName.dirName.dirName; +} +Config config; + +version(IsExecutable) +int main(string[] rootArgs) +{ + import assert_writeln_magic; + import std.getopt; + auto helpInformation = getopt( + rootArgs, std.getopt.config.passThrough, + std.getopt.config.required, + "compiler", "Compiler to use", &config.dmdBinPath, + ); + if (helpInformation.helpWanted) + { +`A wrapper around DDoc to allow custom extensions +./ddoc --compiler= + +All unknown options are passed to the compiler. +`.defaultGetoptPrinter(helpInformation.options); + return 1; + } + auto args = rootArgs[1 .. $]; + auto pos = args.countUntil!(a => a.endsWith(".dd", ".d") > 0); + assert(pos >= 0, "An input file (.d or .dd) must be provided"); + auto inputFile = args[pos]; + auto text = inputFile.readText; + + // for now only non-package modules are supported + if (!inputFile.endsWith("index.d")) + // replace only works with 2.078.1, see: https://github.com/dlang/phobos/pull/6017 + args = args[0..pos].chain("-".only, args[pos..$].dropOne).array; + + // transform and extend the ddoc page + text = genGrammar(text); + text = genHeader(text); + text = genChangelogVersion(inputFile, text); + text = genSwitches(text); + text = fixDdocBugs(inputFile, text); + + // Phobos index.d should have been named index.dd + if (inputFile.endsWith(".d") && !inputFile.endsWith("index.d")) + text = assertWritelnModule(inputFile, text); + + string[string] macros; + macros["SRC_FILENAME"] = "%s\n".format(inputFile.buildNormalizedPath); + return compile(text, args, inputFile, macros); +} + +auto createTmpDir() +{ + import std.uuid : randomUUID; + auto dir = tempDir.buildPath("ddoc_preprocessor_" ~ randomUUID.toString.replace("-", "")); + mkdir(dir); + return dir; +} + +auto compile(R)(R buffer, string[] arguments, string inputFile, string[string] macros = null) +{ + import core.time : usecs; + import core.thread : Thread; + import std.process : execute; + auto args = [config.dmdBinPath] ~ arguments; + + // Note: ideally we could pass in files directly on stdin. + // However, for package.d files, we need to imitate package directory layout to avoid conflicts + auto tmpDir = createTmpDir; + auto inputTmpFile = tmpDir.buildPath(inputFile); + inputTmpFile.dirName.mkdirRecurse; + std.file.write(inputTmpFile, buffer); + args = args.replace("-", inputTmpFile); + scope(exit) tmpDir.rmdirRecurse; + + if (macros !is null) + { + auto macroString = macros.byPair.map!(a => "%s=%s".format(a[0], a[1])).join("\n"); + auto macroFile = tmpDir.buildPath("macros.ddoc"); + std.file.write(macroFile, macroString); + args ~= macroFile; + } + + foreach (arg; ["-c", "-o-"]) + { + if (!args.canFind(arg)) + args ~= arg; + } + + auto ret = execute(args); + if (ret.status != 0) + { + stderr.writeln( + "\n------------- File content -------------\n", + buffer, + "\n------------ Compiler output -----------\n", + ret.output, + "\n----------------------------------------\n", + ); + } + return ret.status; +} + +// replaces the content of a DDoc macro call +auto updateDdocTag(string fileText, string ddocKey, string newContent) +{ + auto pos = fileText.representation.countUntil(ddocKey); + if (pos < 0) + return fileText; + + newContent ~= ")"; + + const ddocStartLength = ddocKey.representation.until('(', No.openRight).count; + auto len = fileText[pos .. $].representation.drop(ddocStartLength).untilClosingParentheses.walkLength; + return fileText.replace(fileText[pos .. pos + len + ddocStartLength + 1], newContent); +} + +// a range until the next ')', nested () are ignored +auto untilClosingParentheses(R)(R rs) +{ + return rs.cumulativeFold!((count, r){ + switch(r) + { + case '(': + count++; + break; + case ')': + count--; + break; + default: + } + return count; + })(1).zip(rs).until!(e => e[0] == 0).map!(e => e[1]); +} + +unittest +{ + import std.algorithm.comparison : equal; + assert("aa $(foo $(bar)foobar)".untilClosingParentheses.equal("aa $(foo $(bar)foobar)")); + assert("$(FOO a, b, $(ARGS e, f)))".untilClosingParentheses.equal("$(FOO a, b, $(ARGS e, f))")); +} + +// parse the ddoc file for H2 and H3 items +// H3 items are listed as subitems +auto parseToc(string text) +{ + alias TocEntry = Tuple!(string, "id", string, "name"); + alias TocTopEntry = Tuple!(TocEntry, "main", TocEntry[], "children"); + TocTopEntry[] toc; + + bool isH2 = true; + void append(string id, string name) + { + auto entry = TocEntry(id, name); + if (isH2) + { + toc ~= TocTopEntry(entry, null); + } + else + { + assert(toc.length > 0, "TOC generation error: $(H2) needs to come before $(H3)"); + toc.back.children ~= entry; + } + } + while (!text.empty) + { + enum needles = AliasSeq!("$(H2 ", "$(SECTION2 ", "$(H3", "$(SECTION3"); + auto res = text.find(needles); + if (res[0].empty) + break; + + isH2 = res[1] <= 2; + text = res[0].drop(needles.only[res[1] - 1].length); + text.skipOver!isWhite; + + enum gname = "$(GNAME "; + enum lNameNeedles = AliasSeq!("$(LNAME2", "$(LEGACY_LNAME2"); + if (text.startsWith(gname)) + { + auto name = text.drop(gname.length).untilClosingParentheses.to!string.strip; + append(name, name); + } + else if (auto idx = text.startsWith(lNameNeedles)) + { + auto arr = text.drop(lNameNeedles.only[idx - 1].length).splitter(","); + if (idx == 2) + arr.popFront; + append(arr.front.strip, arr.dropOne.joiner(",").untilClosingParentheses.to!string.strip); + } + } + return toc; +} + +// Ddoc splits arguments by commas +auto escapeDdoc(string s) +{ + return s.replace(",", "$(COMMA)"); +} + +// generated a HEADERNAV_TOC Ddoc macro with the parsed H2/H3 entries +auto genHeader(string fileText) +{ + enum ddocKey = "$(HEADERNAV_TOC"; + auto newContent = ddocKey ~ "\n"; + enum indent = " "; + if (fileText.canFind(ddocKey)) + { + foreach (entry; fileText.parseToc) + { + if (entry.children) + { + newContent ~= "%s$(HEADERNAV_SUBITEMS %s, %s,\n".format(indent, entry.main.id, entry.main.name.escapeDdoc); + foreach (child; entry.children) + newContent ~= "%s$(HEADERNAV_ITEM %s, %s)\n".format(indent.repeat(2).joiner, child.id, child.name.escapeDdoc); + newContent ~= indent; + newContent ~= ")\n"; + } + else + { + newContent ~= "%s$(HEADERNAV_ITEM %s, %s)\n".format(indent, entry.main.id, entry.main.name.escapeDdoc); + } + } + } + return updateDdocTag(fileText, ddocKey, newContent); +} + +// parse the menu from the Ddoc file +auto specTocEntries() +{ + alias Entry = Tuple!(string, "name", string, "title", string, "fileName"); + Entry[] entries; + + immutable specDir = config.cwd.buildNormalizedPath("spec"); + immutable mainFile = specDir.buildPath("./spec.ddoc"); + + auto specText = mainFile.readText; + if (!specText.findSkip("SUBMENU2")) + writeln("Menu file has an invalid format."); + foreach (line; specText.splitter("\n")) + { + enum ddocEntryStart = "$(ROOT_DIR)spec/"; + if (line.find!(not!isWhite).startsWith(ddocEntryStart)) + { + auto ps = line.splitter(ddocEntryStart).dropOne.front.splitter(","); + auto name = ps.front.stripExtension.withExtension(".dd").to!string; + auto fileName = specDir.buildPath(name); + auto title = ps.dropOne.front.idup.strip; + entries ~= Entry(name, title, fileName); + } + } + return entries; +} + +// Automatically generate spec/grammar +auto genGrammar(string fileText) +{ + import std.uni : toLower; + + enum ddocKey = "$(GRAMMAR_SUMMARY"; + auto newContent = ddocKey ~ "\n"; + + if (fileText.canFind(ddocKey)) + { + foreach (i, entry; specTocEntries) + { + if (entry.fileName.endsWith("grammar.dd", "lex.dd", "istring.dd", "simd.dd")) + continue; + + enum grammarKey = "$(GRAMMAR"; + + static string findKey(string s) + { + s = s.find(grammarKey); + // retry if no space after + if (s.length > grammarKey.length && !s[grammarKey.length].isWhite) + { + return findKey(s[grammarKey.length .. $]); + } + return s; + } + auto text = findKey(entry.fileName.readText); + if (!text.length) + continue; + + newContent ~= "$(H2 $(LNAME2 %s, %s))\n".format(entry.title.toLower, entry.title); + do + { + newContent ~= grammarKey; + text.popFrontN(grammarKey.length); + newContent ~= text.untilClosingParentheses.to!string; + newContent ~= ")\n"; + text = findKey(text); + } + while (text.length); + } + return updateDdocTag(fileText, ddocKey, newContent); + } + return fileText; +} + +// Automatically generate a versions overview +auto genChangelogVersion(string fileName, string fileText) +{ + import std.regex; + static re = regex(`^[0-9]\.[0-9][0-9][0-9](\.[0-9])?(_pre)?\.dd$`); + if (fileName.dirName.baseName == "changelog" || fileName.endsWith("chm-nav.dd")) + { + string macros = "\nCHANGELOG_VERSIONS="; + macros ~= "$(CHANGELOG_VERSION_NIGHTLY)\n"; + auto changelogFiles = dirEntries(fileName.dirName, SpanMode.depth).filter!(a => !a.name.baseName.matchFirst(re).empty).array; + changelogFiles.sort; + foreach (file; changelogFiles.retro) + { + auto arr = file.readText.findSplitAfter("$(VERSION ")[1].until!(a => a.among('\n', '=')).array; + auto date = arr.retro.findSplitAfter(",")[1].retro; + auto ver = file.name.baseName.stripExtension.until("_pre"); + macros ~= "$(CHANGELOG_VERSION%s %s, %s)\n".format(file.name.endsWith("_pre.dd") ? "_PRE" : "", ver, date); + } + + // inject the changelog footer + auto fileBaseName = fileName.baseName; + auto r = changelogFiles.chain("pending.dd".only).enumerate.find!(a => a.value.baseName == fileBaseName); + if (r.length != 0) + { + auto el = r.front; + macros ~= "\nCHANGELOG_NAV_INJECT="; + auto versions = changelogFiles.map!(a => a.baseName.until(".dd")); + auto hasPrerelease = versions[$ - 1].canFind("_pre"); + // mapping for the first and last page is different + if (el.index == 0) + { + macros ~="\n$(CHANGELOG_NAV_FIRST %s)".format(versions[1]); + } + else if ( + // latest version + nightlies (pending.dd) + el.index >= versions.length || + // prerelease pages + el.index == versions.length - 1 && hasPrerelease) + { + macros ~="\n$(CHANGELOG_NAV_LAST %s)".format(versions.retro.find!(v => !v.canFind("_pre", "pending")).front); + } + else if (el.index == versions.length - 1 && !hasPrerelease) + { + macros ~="\n$(CHANGELOG_NAV_LAST %s)".format(versions[$ - 2]); + } + else + { + const prevVersion = versions[el.index - 1].to!string; + auto nextVersion = versions[el.index + 1].to!string; + // the next version is the beta release + if (el.index == versions.length - 2 && hasPrerelease) + nextVersion = std.array.replace(nextVersion, "_pre", ""); + + macros ~="\n$(CHANGELOG_NAV %s, %s)".format(prevVersion, nextVersion); + } + macros ~= "\n_="; + } + fileText ~= macros; + } + return fileText; +} + +// generate CLI documentation +auto genSwitches(string fileText) +{ + enum ddocKey = "$(CLI_SWITCHES"; + auto content = ddocKey ~ "\n"; + + bool[string] seen; + + foreach (option; Usage.options) + { + if (!option.documented) + continue; + string flag = option.flag; + string helpText = option.helpText; + if (!option.ddocText.empty) + helpText = option.ddocText; + + // capitalize the first letter + helpText = helpText.capitalize.to!string; + + highlightSpecialWords(flag, helpText); + auto flagEndPos = flag.representation.countUntil("=", "$(", "<"); + string switchName; + + string swNameMacro = "SWNAME"; + // flags links should be unique + auto swKey = flag[0 .. flagEndPos < 0 ? $ : flagEndPos]; + if (auto v = swKey in seen) + swNameMacro = "B"; + seen[swKey] = 1; + + if (flagEndPos < 0) + switchName = "$(%s -%s)".format(swNameMacro, flag); + else + switchName = "$(%s -%s)%s".format(swNameMacro, flag[0..flagEndPos], flag[flagEndPos..$].escapeDdoc); + + auto currentFlag = "$(SWITCH %s,\n + %s + )".format(switchName, helpText); + + with(TargetOS) + switch(option.os) + { + case Windows: + currentFlag = text("$(WINDOWS ", currentFlag, ")"); + break; + case linux: + case OSX: + case OpenBSD: + case FreeBSD: + case Solaris: + case DragonFlyBSD: + currentFlag = text("$(UNIX ", currentFlag, ")"); + break; + case all: + default: + break; + } + content ~= currentFlag; + } + return updateDdocTag(fileText, ddocKey, content); +} + +auto italic(string w) +{ + return "$(I %s )".format(w); +} + + +// capitalize the first letter +auto capitalize(string w) +{ + import std.range, std.uni; + return w.take(1).asUpperCase.chain(w.dropOne); +} + +private void highlightSpecialWords(ref string flag, ref string helpText) +{ + if (flag.canFind("<", "[") && flag.canFind(">", "]")) + { + string specialWord; + + // detect special words in <...> and highlight them + static foreach (t; [["<", ">"], ["[", "]"]]) + { + if (flag.canFind(t[0])) + { + specialWord = flag.findSplit(t[0])[2].until(t[1]).to!string; + // keep [] + auto replaceWord = t[0] == "<" ? t[0] ~ specialWord ~ t[1] : specialWord; + flag = flag.replace(replaceWord, specialWord.italic); + } + } + + // highlight individual words in the description + helpText = helpText + .splitter(" ") + .map!((w){ + auto wPlain = w.filter!(c => !c.among('<', '>', '`', '\'')).to!string; + return wPlain == specialWord ? wPlain.italic: w; + }) + .joiner(" ") + .to!string; + } +} + +// Fix ddoc bugs +string fixDdocBugs(string inputFile, string text) +{ + + // __FILE__ changes on every build + // can be removed once https://github.com/dlang/phobos/pull/6321 is merged and part of a release + if (inputFile.endsWith("exception.d")) + { + text = text.replace(`typeof(new E("", __FILE__, __LINE__)`, `typeof(new E("", string.init, size_t.init)`); + text = text.replace(`typeof(new E(__FILE__, __LINE__)`, `typeof(new E(string.init, size_t.init)`); + } + return text; +} diff --git a/declaration.dd b/declaration.dd deleted file mode 100644 index b475da5048..0000000000 --- a/declaration.dd +++ /dev/null @@ -1,660 +0,0 @@ -Ddoc - -$(SPEC_S Declarations, - -$(GRAMMAR -$(V1 $(GNAME Declaration): - $(GLINK TypedefDeclaration) - $(GLINK AliasDeclaration) - $(GLINK Decl) - -$(GNAME TypedefDeclaration): - $(B typedef) $(GLINK Decl) - -$(GNAME AliasDeclaration): - $(B alias) $(GLINK Decl) -)$(V2 $(GNAME Declaration): - $(GLINK AliasDeclaration) - $(GLINK AliasThisDeclaration) - $(GLINK Decl) - -$(GNAME AliasDeclaration): - $(B alias) $(GLINK BasicType) $(GLINK Declarator) - -$(GNAME AliasThisDeclaration): - $(B alias) $(I Identifier) $(B this) -) -$(GNAME Decl): - $(GLINK StorageClasses) $(I Decl) - $(GLINK BasicType) $(GLINK Declarators) $(B ;) - $(GLINK BasicType) $(GLINK Declarator) $(GLINK2 function, FunctionBody) - $(GLINK AutoDeclaration) - -$(GNAME Declarators): - $(I DeclaratorInitializer) - $(I DeclaratorInitializer) $(B ,) $(GLINK DeclaratorIdentifierList) - -$(GNAME DeclaratorInitializer): - $(GLINK Declarator) - $(GLINK Declarator) $(B =) $(GLINK Initializer) - -$(GNAME DeclaratorIdentifierList): - $(GLINK DeclaratorIdentifier) - $(GLINK DeclaratorIdentifier) $(B ,) $(I DeclaratorIdentifierList) - -$(GNAME DeclaratorIdentifier): - $(I Identifier) - $(I Identifier) $(B =) $(GLINK Initializer) - -$(GNAME BasicType): - $(GLINK BasicTypeX) - $(B .)$(GLINK IdentifierList) - $(GLINK IdentifierList) - $(GLINK Typeof) - $(GLINK Typeof) $(B .) $(GLINK IdentifierList) -$(V2 $(B const$(LPAREN)) $(GLINK Type) $(B $(RPAREN)) - $(B immutable$(LPAREN)) $(GLINK Type) $(B $(RPAREN)) - $(B shared$(LPAREN)) $(GLINK Type) $(B $(RPAREN)) - $(B inout$(LPAREN)) $(GLINK Type) $(B $(RPAREN)) -) - -$(GNAME BasicTypeX): - $(B bool) - $(B byte) - $(B ubyte) - $(B short) - $(B ushort) - $(B int) - $(B uint) - $(B long) - $(B ulong) - $(B char) - $(B wchar) - $(B dchar) - $(B float) - $(B double) - $(B real) - $(B ifloat) - $(B idouble) - $(B ireal) - $(B cfloat) - $(B cdouble) - $(B creal) - $(B void) - -$(GNAME BasicType2): - $(B *) - $(B [ ]) - $(B [) $(VEXPRESSION) $(B ]) - $(B [) $(VEXPRESSION) .. $(VEXPRESSION) $(B ]) - $(B [) $(GLINK Type) $(B ]) - $(B delegate) $(GLINK Parameters) $(V2 $(GLINK FunctionAttributes)$(OPT)) - $(B function) $(GLINK Parameters) $(V2 $(GLINK FunctionAttributes)$(OPT)) - -$(GNAME Declarator): - $(GLINK BasicType2)$(OPT) $(B $(LPAREN)) $(I Declarator) $(B $(RPAREN)) $(GLINK DeclaratorSuffixes)$(OPT) - $(GLINK BasicType2)$(OPT) $(I Identifier) $(GLINK DeclaratorSuffixes)$(OPT) - -$(GNAME DeclaratorSuffixes): - $(GLINK DeclaratorSuffix) - $(GLINK DeclaratorSuffix) $(I DeclaratorSuffixes) - -$(GNAME DeclaratorSuffix): - $(B [ ]) - $(B [) $(VEXPRESSION) $(B ]) - $(B [) $(GLINK Type) $(B ]) - $(GLINK2 template, TemplateParameterList)$(OPT) $(GLINK Parameters) $(V2 $(GLINK MemberFunctionAttributes)$(OPT) $(GLINK2 template, Constraint)$(OPT)) - -$(GNAME IdentifierList): - $(I Identifier) - $(I Identifier) $(B .) $(I IdentifierList) - $(GLINK2 template, TemplateInstance) - $(GLINK2 template, TemplateInstance) $(B .) $(I IdentifierList) - -$(GNAME StorageClasses): - $(GLINK StorageClass) - $(GLINK StorageClass) $(I StorageClasses) - -$(GNAME StorageClass): - $(B abstract) - $(B auto) - $(B const) - $(B deprecated) -$(V2 $(B enum) -) $(B extern) - $(B final) -$(V2 $(B immutable) - $(B inout) - $(B shared) - $(B nothrow) - $(B override) - $(B pure) - $(B __gshared) - $(GLINK Property) -) $(B scope) - $(B static) - $(B synchronized) - -$(GNAME Property): - $(B @) $(GLINK PropertyIdentifier) - -$(GNAME PropertyIdentifier): - $(B property) - $(B safe) - $(B trusted) - $(B system) - $(B disable) - -$(GNAME Type): - $(GLINK BasicType) - $(GLINK BasicType) $(GLINK Declarator2) - -$(GNAME Declarator2): - $(GLINK BasicType2)$(OPT) $(GLINK DeclaratorSuffixes)$(OPT) - $(GLINK BasicType2)$(OPT) $(B $(LPAREN)) $(I Declarator2) $(B $(RPAREN)) $(GLINK DeclaratorSuffixes)$(OPT) - -$(GNAME Parameters): - $(B $(LPAREN)) $(GLINK ParameterList) $(B $(RPAREN)) - $(B ( )) - -$(GNAME ParameterList): - $(GLINK Parameter) - $(GLINK Parameter) $(B ,) $(I ParameterList) - $(B ...) - -$(GNAME Parameter): - $(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator) - $(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator) $(B ...) - $(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator) = $(GLINK DefaultInitializerExpression) - $(I InOut)$(OPT) $(GLINK Type) - $(I InOut)$(OPT) $(GLINK Type) $(B ...) - -$(GNAME InOut): - $(I InOutX) - $(I InOut InOutX) - -$(GNAME InOutX): - $(B auto) - $(B const) - $(B final) -$(V2 $(B immutable) -) $(B in) - $(B inout) - $(B lazy) - $(B out) - $(B ref) - $(B scope) - $(B shared) - -$(V2 -$(GNAME FunctionAttributes): - $(GLINK FunctionAttribute) - $(GLINK FunctionAttribute) $(I FunctionAttributes) - -$(GNAME FunctionAttribute): - $(B nothrow) - $(B pure) - $(GLINK Property) -) -$(GNAME MemberFunctionAttributes): - $(GLINK MemberFunctionAttribute) - $(GLINK MemberFunctionAttribute) $(I MemberFunctionAttributes) - -$(GNAME MemberFunctionAttribute): - $(B const) - $(B immutable) - $(B inout) - $(B shared) - $(GLINK FunctionAttribute) - -$(GNAME DefaultInitializerExpression): - $(ASSIGNEXPRESSION) -$(V2 $(B __FILE__) - $(B __LINE__)) - -$(GNAME Initializer): - $(GLINK VoidInitializer) - $(GLINK NonVoidInitializer) - -$(GNAME NonVoidInitializer): - $(ASSIGNEXPRESSION) - $(GLINK ArrayInitializer) - $(GLINK StructInitializer) - -$(GNAME ArrayInitializer): - $(B [ ]) - $(B [) $(GLINK ArrayMemberInitializations) $(B ]) - -$(GNAME ArrayMemberInitializations): - $(GLINK ArrayMemberInitialization) - $(GLINK ArrayMemberInitialization) $(B ,) - $(GLINK ArrayMemberInitialization) $(B ,) $(I ArrayMemberInitializations) - -$(GNAME ArrayMemberInitialization): - $(GLINK NonVoidInitializer) - $(ASSIGNEXPRESSION) $(B :) $(GLINK NonVoidInitializer) - -$(GNAME StructInitializer): - $(B { }) - $(B {) $(GLINK StructMemberInitializers) $(B }) - -$(GNAME StructMemberInitializers): - $(GLINK StructMemberInitializer) - $(GLINK StructMemberInitializer) $(B ,) - $(GLINK StructMemberInitializer) $(B ,) $(I StructMemberInitializers) - -$(GNAME StructMemberInitializer): - $(GLINK NonVoidInitializer) - $(I Identifier) $(B :) $(GLINK NonVoidInitializer) -) - -

    Declaration Syntax

    - -$(P Declaration syntax generally reads right to left:) - --------------------- -int x; // x is an int -int* x; // x is a pointer to int -int** x; // x is a pointer to a pointer to int -int[] x; // x is an array of ints -int*[] x; // x is an array of pointers to ints -int[]* x; // x is a pointer to an array of ints --------------------- - -$(P Arrays read right to left as well:) - --------------------- -int[3] x; // x is an array of 3 ints -int[3][5] x; // x is an array of 5 arrays of 3 ints -int[3]*[5] x; // x is an array of 5 pointers to arrays of 3 ints --------------------- - -$(P -Pointers to functions are declared using the $(B function) keyword: -) - --------------------- -int $(B function)(char) x; // x is a pointer to - // a function taking a char argument - // and returning an int -int $(B function)(char)[] x; // x is an array of - // pointers to functions - // taking a char argument - // and returning an int --------------------- - -$(P -$(V1 C-style array, function pointer and pointer to array declarations are possible as an alternative:) -$(V2 C-style array, function pointer and pointer to array declarations are deprecated:) -) - --------------------- -int x[3]; // x is an array of 3 ints -int x[3][5]; // x is an array of 3 arrays of 5 ints -int (*x[5])[3]; // x is an array of 5 pointers to arrays of 3 ints -int (*x)(char); // x is a pointer to a function taking a char argument - // and returning an int -int (*[] x)(char); // x is an array of pointers to functions - // taking a char argument and returning an int --------------------- - -$(P -In a declaration declaring multiple symbols, all the declarations -must be of the same type: -) - --------------------- -int x,y; // x and y are ints -int* x,y; // x and y are pointers to ints -int x,*y; // error, multiple types -int[] x,y; // x and y are arrays of ints -int x[],y; // error, multiple types --------------------- - -

    Implicit Type Inference

    - -$(GRAMMAR -$(GNAME AutoDeclaration): - $(GLINK StorageClasses) $(I AutoDeclarationX) $(B ;) - -$(GNAME AutoDeclarationX): - $(I Identifier) $(B =) $(GLINK Initializer) - $(I AutoDeclarationX) $(B ,) $(I Identifier) $(B =) $(GLINK Initializer) -) - - $(P If a declaration starts with a $(I StorageClass) and has - a $(I NonVoidInitializer) from which the type can be inferred, - the type on the declaration can be omitted. - ) - ----------- -static x = 3; // x is type int -auto y = 4u; // y is type uint -$(V1 auto s = "string"; // s is type char[6]) -$(V2 auto s = "string"; // s is type immutable(char)[]) - -class C { ... } - -auto c = new C(); // c is a handle to an instance of class C ----------- - - $(P The $(I NonVoidInitializer) cannot contain forward references - (this restriction may be removed in the future). - The implicitly inferred type is statically bound - to the declaration at compile time, not run time. - ) - -$(V2 - $(P An $(GLINK2 expression, ArrayLiteral) - is inferred to be a dynamic array - type rather than a static array:) - ---- -auto v = ["hello", "world"]; // type is string[], not string[2] ---- -) - -$(V1 -

    Type Defining

    - - $(P - Strong types can be introduced with the typedef. Strong types are semantically a - distinct type to the type checking system, for function overloading, and for the debugger. - ) - --------------------- -typedef int myint; - -void foo(int x) { . } -void foo(myint m) { . } - - . -myint b; -foo(b); // calls foo(myint) --------------------- - -Typedefs can specify a default initializer different from the -default initializer of the underlying type: - --------------------- -typedef int myint = 7; -myint m; // initialized to 7 --------------------- -) - -

    Type Aliasing

    - - $(P - $(GLINK AliasDeclaration)s create a symbol that is an alias for another type, - and can be used anywhere that other type may appear. - ) - --------------------- -$(B alias) abc.Foo.bar myint; --------------------- - - $(P - Aliased types are semantically identical to the types they are aliased to. The - debugger cannot distinguish between them, and there is no difference as far as function - overloading is concerned. For example: - ) - --------------------- -$(B alias) int myint; - -void foo(int x) { . } -void foo(myint m) { . } // error, multiply defined function foo --------------------- - -$(V1 - $(P - Type aliases are equivalent to the C typedef. - ) -) - -

    Alias Declarations

    - - $(P - A symbol can be declared as an $(I alias) of another symbol. - For example: - ) - --------------------- -import string; - -$(B alias) string.strlen mylen; - ... -int len = mylen("hello"); // actually calls string.strlen() --------------------- - - $(P - The following alias declarations are valid: - ) - --------------------- -template Foo2(T) { $(B alias) T t; } -$(B alias) Foo2!(int) t1; -$(B alias) Foo2!(int).t t2; -$(B alias) t1.t t3; -$(B alias) t2 t4; - -t1.t v1; // v1 is type int -t2 v2; // v2 is type int -t3 v3; // v3 is type int -t4 v4; // v4 is type int --------------------- - - $(P - Aliased symbols are useful as a shorthand for a long qualified - symbol name, or as a way to redirect references from one symbol - to another: - ) - --------------------- -version (Win32) -{ - $(B alias) win32.foo myfoo; -} -version (linux) -{ - $(B alias) linux.bar myfoo; -} --------------------- - - $(P - Aliasing can be used to $(SINGLEQUOTE import) a symbol from an import into the - current scope: - ) - --------------------- -$(B alias) string.strlen strlen; --------------------- - - $(P - Aliases can also $(SINGLEQUOTE import) a set of overloaded functions, that can - be overloaded with functions in the current scope: - ) - --------------------- -class A { - int foo(int a) { return 1; } -} - -class B : A { - int foo( int a, uint b ) { return 2; } -} - -class C : B { - int foo( int a ) { return 3; } - $(B alias) B.foo foo; -} - -class D : C { -} - - -void test() -{ - D b = new D(); - int i; - - i = b.foo(1, 2u); // calls B.foo - i = b.foo(1); // calls C.foo -} --------------------- - - $(P - $(B Note:) Type aliases can sometimes look indistinguishable from - alias declarations: - ) - --------------------- -$(B alias) foo.bar abc; // is it a type or a symbol? --------------------- - - $(P - The distinction is made in the semantic analysis pass. - ) - - $(P Aliases cannot be used for expressions:) - ------------ -struct S { static int i; } -S s; - -alias s.i a; // illegal, s.i is an expression -alias S.i b; // ok -b = 4; // sets S.i to 4 ------------ - -

    Extern Declarations

    - - Variable declarations with the storage class $(B extern) are - not allocated storage within the module. - They must be defined in some other object file with a matching - name which is then linked in. - The primary usefulness of this is to connect with global - variable declarations in C files. - -

    typeof

    - -$(GRAMMAR -$(GNAME Typeof): - $(B typeof $(LPAREN)) $(EXPRESSION) $(B $(RPAREN)) - $(B typeof $(LPAREN)) $(B return) $(B $(RPAREN)) -) - - $(P - $(I Typeof) is a way to specify a type based on the type - of an expression. For example: - ) - --------------------- -void func(int i) { - $(B typeof)(i) j; // j is of type int - $(B typeof)(3 + 6.0) x; // x is of type double - $(B typeof)(1)* p; // p is of type pointer to int - int[$(B typeof)(p)] a; // a is of type int[int*] - - writefln("%d", $(B typeof)('c').sizeof); // prints 1 - double c = cast($(B typeof)(1.0))j; // cast j to double -} --------------------- - - $(P - $(I Expression) is not evaluated, just the type of it is - generated: - ) - --------------------- -void func() { - int i = 1; - $(B typeof)(++i) j; // j is declared to be an int, i is not incremented - writefln("%d", i); // prints 1 -} --------------------- - - $(P - There are $(V1 two) $(V2 three) special cases: - $(OL - $(LI $(B typeof(this)) will generate the type of what $(B this) - would be in a non-static member function, even if not in a member - function. - ) - $(LI Analogously, $(B typeof(super)) will generate the type of what - $(B super) would be in a non-static member function. - ) -$(V2 - $(LI $(B typeof(return)) will, when inside a function scope, - give the return type of that function. - ) -) - ) - ) - --------------------- -class A { } - -class B : A { - $(B typeof(this)) x; // x is declared to be a B - $(B typeof(super)) y; // y is declared to be an A -} - -struct C { - $(B typeof(this)) z; // z is declared to be a C* - $(B typeof(super)) q; // error, no super struct for C -} - -$(B typeof(this)) r; // error, no enclosing struct or class --------------------- - - $(P - Where $(I Typeof) is most useful is in writing generic - template code. - ) - -

    Void Initializations

    - -$(GRAMMAR -$(GNAME VoidInitializer): - $(B void) -) - - $(P Normally, variables are initialized either with an explicit - $(I Initializer) or are set to the default value for the - type of the variable. If the $(I Initializer) is $(B void), - however, the variable is not initialized. If its value is - used before it is set, undefined program behavior will result. - ) - -------------------------- -void foo() { - int x = void; - writefln(x); // will print garbage -} -------------------------- - - $(P Therefore, one should only use $(B void) initializers as a - last resort when optimizing critical code. - ) - -

    Global and Static Initializers

    - - $(P The $(GLINK Initializer) for a global or static variable must be - evaluatable at compile time. - Whether some pointers can be initialized with the addresses of other - functions or data is implementation defined. - Runtime initialization can be done with static constructors. - ) - -) - -Macros: - TITLE=Declarations - WIKI=Declaration - CATEGORY_SPEC=$0 - OPT=opt - ASSIGNEXPRESSION=$(GLINK2 expression, AssignExpression) - EXPRESSION=$(GLINK2 expression, Expression) - VEXPRESSION=$(V1 $(EXPRESSION))$(V2 $(ASSIGNEXPRESSION)) - FOO= diff --git a/deprecate.dd b/deprecate.dd index 42373cf30a..0b4e2870e1 100644 --- a/deprecate.dd +++ b/deprecate.dd @@ -2,56 +2,1068 @@ Ddoc $(SPEC_S Deprecated Features, - $(P Sometimes it becomes clear that a feature is just a bad idea. - These are called $(I deprecated features) and once they are judged - to merit removal from the language, they follow a procedure in - order to allow plenty of time for users to adjust to the change. - ) - - $(TABLE2 Deprecated Features, - $(THEAD Feature, Spec, Warn, Dep, Error, Gone) - $(TROW $(DEPLINK Base Class Protection), 2.058,  ,  ,  ,  ) - ) - - $(DL - $(DT Spec) - $(DD Removal from the Specification) - $(DT Warn) - $(DD The compiler emits a warning if the feature is used) - $(DT Dep) - $(DD The compiler issues an error if not compiled with the -d switch) - $(DT Error) - $(DD It is an error to use the feature) - $(DT Gone) - $(DD The feature is completely gone) - ) - -

    $(DEPNAME Base Class Protection)

    - - Base class protections are things like: + $(P Sometimes it becomes clear that a feature is just a bad idea. + These are called $(I deprecated features) and once they are judged + to merit removal from the language, they follow a procedure in + order to allow plenty of time for users to adjust to the change. + ) ---- -class A : $(B protected) B { - ... -} ---- + $(TABLE2 Deprecated Features, + $(THEAD Feature, Spec, Dep, Error, Gone) + $(TROW $(DEPLINK Throwing from contracts of nothrow functions),  , 2.101, 2.111,  ) + $(TROW $(COMMENT DEPLINK Hexstring literals), 2.079, 2.079, 2.086,  ) + $(TROW $(DEPLINK Class allocators and deallocators),  , 2.080, 2.087, 2.100 ) + $(TROW $(DEPLINK Implicit comparison of different enums), 2.075, 2.075, 2.081,  ) + $(TROW $(DEPLINK Implicit string concatenation), 2.072, 2.072, 2.081,  ) + $(TROW $(DEPLINK Using the result of a comma expression), 2.072, 2.072, 2.079,  ) + $(TROW $(DEPLINK delete),  , 2.079, 2.099, 2.109) + $(TROW $(DEPLINK scope as a type constraint),  , 2.087,  ,  ) + $(TROW $(DEPLINK Imaginary and complex types), future, 2.097,  ,  ) + $(TROW $(DEPLINK 128-bit integer types), future, 2.100, 2.100,  ) + $(TROW $(DEPLINK Implicit catch statement), 2.072, 2.072, 2.081,   ) + $(TROW $(DEPLINK .sort and .reverse properties for arrays), ?, 2.072,  , 2.075) + $(TROW $(DEPLINK C-style array pointers), ?, 2.072, 2.082,  ) + $(TROW $(DEPLINK Floating point NCEG operators), 2.079, 2.066, 2.072, 2.080 ) + $(TROW $(DEPLINK clear), 2.060, 2.066,  , 2.068 ) + $(TROW $(DEPLINK .min property for floating point types), N/A, 2.065, 2.067, 2.072 ) + $(TROW $(DEPLINK Cast T[] to integral type), ?, 2.060,  , 2.061 ) + $(TROW $(DEPLINK Base Class Protection), 2.058, 2.058, 2.067, 2.072 ) + $(TROW $(DEPLINK Windows 3.x and Windows 9x support), 2.058, N/A, N/A, 2.058 ) + $(TROW $(DEPLINK typedef), 2.057, 2.057, 2.067, 2.072 ) + $(TROW $(DEPLINK Using * to dereference arrays), ?, 2.057, 2.067, (never) ) + $(TROW $(DEPLINK invariant as an alias for immutable), 2.057, 2.057, 2.064, 2.066 ) + $(TROW $(DEPLINK Non-final switch statements without a default case), 2.054, 2.054, 2.068, (never) ) + $(TROW $(DEPLINK Hiding base class functions), 2.054, 2.054, 2.068, (never) ) + $(TROW $(DEPLINK Octal literals), 2.054, 2.053, 2.067, (never) ) + $(TROW $(DEPLINK C-style function pointers), ?, 2.050, 2.067, (never) ) + $(TROW $(DEPLINK Using length in index expressions), ?, 2.041,  , 2.061 ) + $(TROW $(DEPLINK Escape string literals), ?, 2.026, 2.061, 2.067 ) + $(TROW $(DEPLINK volatile), 2.013, 2.013, 2.067, 2.072) + $(TROW $(DEPLINK HTML source files), ?, 2.013, N/A, 2.061 ) + $(TROW $(DEPLINK Overriding without override), ?, 2.004, 2.072, (never) ) + $(TROW $(DEPLINK Lower case 'l' suffix for integer literals), ?, 1.054, 0.174, (never) ) + $(TROW $(DEPLINK Variable shadowing inside functions), ?, 0.161,  , 2.061 ) + $(TROW $(DEPLINK Upper case 'I' suffix for imaginary literals), ?, 0.154, 2.061, (never) ) + $(TROW $(DEPLINK if (v; e)), ?, 0.149, 2.061, 2.068 ) + $(TROW $(DEPLINK Removing an item from an associative array with delete), ?, 0.127, 2.061, 2.067 ) + $(TROW $(DEPLINK .offset property), ?, 0.107, 2.061, 2.067 ) + $(TROW $(DEPLINK .size property), ?, 0.107, 0.107, 2.061 ) + $(TROW $(DEPLINK .typeinfo property), ?, 0.093, 2.061, 2.067 ) + $(TROW $(DEPLINK unannotated asm blocks),  ,  , 2.100, (never) ) + $(TROW $(DEPLINK Throwing qualified objects),  , 2.104,  , (never) ) + $(TROW $(DEPLINK Catching immutable/inout/shared objects),  , 2.106,  , (never) ) + ) + + $(DL + $(DT Spec) + $(DD Removal from the Specification) + $(DT Dep) + $(DD The compiler warns by default, issues an error with the -de switch, and can be silenced with the -d switch) + $(DT Error) + $(DD It is an error to use the feature) + $(DT Gone) + $(DD The feature is completely gone) + ) + +$(H3 $(DEPNAME Throwing from contracts of nothrow functions)) + $(P Throwing exceptions from the contracts of a $(D nothrow) function was permitted: + --- + float sqrt(float n) nothrow + in + { + if (n < 0) + throw new Exception("n must be positive"); + } + do + { + // ... + } + --- + ) +$(H4 Corrective Action) + $(P Remove the $(D nothrow) attribute or rewrite the contract using + $(LINK2 spec/expression.html#assert_expressions, assertions) instead. + --- + float sqrt(float n) nothrow + in + { + assert(n >= 0); + } + do + { + // ... + } + --- + ) +$(H4 Rationale) + $(P Since a function's preconditions and postconditions are implicitly + executed before and after the function's body, allowing them to throw + would break the guarantees of the $(D nothrow) attribute. + ) + +$(COMMENT +$(H3 $(DEPNAME Hexstring literals)) + $(P Hexstring literals can be used to enter literals in base 16. + --- + // deprecated code + // auto x = x"1234"; + --- + ) +$(H4 Corrective Action) + $(P Use the $(REF hexString, std,conv) template. + --- + auto x = hexString!"1234"; + --- + ) +$(H4 Rationale) + $(P Hexstrings are used so seldom that they don't warrant a language feature. + ) +) + +$(H3 $(DEPNAME Class allocators and deallocators)) + $(P D classes can have members customizing the (de)allocation strategy. + --- + class Foo + { + new(uint size, ...) + { + return malloc(size); + } + + delete(void* obj) + { + free(obj); + } + } + + Foo foo = new(...) Foo(); + delete foo; + --- + ) +$(H4 Corrective Action) + $(P Move the (de)allocation strategy out of the class + --- + class Foo + { + } + + T make(T, Args...)(auto ref Args args) if (is(T == Foo)) + { + enum size = __traits(classInstanceSize, T); + void* mem = malloc(size); + scope (failure) free(mem); + return mem !is null ? emplace!T(mem[0..size], args) : null; + } + + void dispose(T)(T obj) + { + auto mem = cast(void*) obj; + scope (exit) free(mem); + destroy(obj); + } + + Foo foo = make!Foo(); + if (foo !is null) dispose(foo); + --- + ) +$(H4 Rationale) + $(P Classes should not be responsible for their own (de)allocation strategy. + ) + +$(H3 $(DEPNAME Implicit comparison of different enums)) + $(P Comparison of different enumerated type was allowed: + --- + enum Status + { + good, + bad + } + enum OtherStatus + { + ok, + no + } + static assert(Status.good == OtherStatus.ok); + --- + ) +$(H4 Corrective Action) + $(P Comparison between unrelated enumerated types should be done with $(REF asOriginalType, std, conv)) + --- + import std.conv : asOriginalType; + assert(Foo.x.asOriginalType == Bar.y.asOriginalType); + --- +$(H4 Rationale) + $(P Code correctness is improved by + disallowing comparison of unrelated enumerated types. Implicit comparison of + different `enum` types often resulted in hard to spot bugs.) + + --- + enum { X } + enum { Y } + void main() { + auto b = X == Y; + assert(b); + } + --- + +$(H3 $(DEPNAME Implicit string concatenation)) + $(P Two adjacent strings were implicitly concatenated: + + --- + string foo = "Hello" "World"; + --- + + This feature was handy for a long string that spans multiple lines, + however, it is possible to get the same behaviour explicitly by + using the concatenation operator ('~'): + + --- + string foo = "Hello" ~ "World"; // No allocation is performed + --- + ) +$(H4 Corrective Action) + $(P Replace implicit string concatenation by explicit one, using '~'.) +$(H4 Rationale) + $(P This is a very early feature of the language, which is nowadays totally + covered by the concatenation operator: it is performed at compile time + for constants and doesn't result in memory allocation.) + + $(P However, having implicit concatenation can and did result in hard + to spot bugs, for example:) + + --- + string[] names = + [ + "Anna", + "Michael" + "Emma", + "David" + ]; + // The content of arr is [ "Anna", "MichaelEmma", "David" ] + --- + +$(H3 $(DEPNAME Using the result of a comma expression)) + $(P The comma operator (`,`) allows executing multiple expressions and + discards the result of them except for the last which is returned. + + --- + int a = 1; + int b = 2; + bool ret = a == 2, b == 2; // true + --- + + It's also common to use the comma operator in for-loop increment + statements to allow multiple expressions. + + --- + for (; !a.empty && !b.empty; a.popFront, b.popFront) + --- + ) +$(H4 Corrective Action) + $(P If possible, split the comma operator in two statements. Otherwise use + lambdas. + + --- + auto result = foo(), bar(); + + // split off in two statements + foo(); + auto result = bar(); + + // or use lambdas + auto result = {foo(); return bar();}(); + --- + ) +$(H4 Rationale) + $(P The comma operator leads to unintended behavior (see below for a selection) + Moreover it is not commonly used and it blocks the ability to implement tuples. + + A selection of problems through the accidental use of the comma operator: + --- + writeln( 6, mixin("7,8"), 9 ); // 6, 8, 9 + + template vec(T...)(T args) { ... } + vec v = (0, 0, 3); // 3, because vec is variadic + + int b = 2; + if (a == 1, b == 2) { + // will always be reached + } + + void foo(int x) {} + foo((++a, b)); + + synchronized (lockA, lockB) {} + // isn't currently implemented, but still compiles due to the comma operator + --- + ) + +$(H3 $(DEPNAME delete)) + $(P Memory allocated on the GC heap can be freed with $(D delete). + --- + auto a = new Class(); + delete a; + --- + ) +$(H4 Corrective Action) + $(P Use $(LINK2 phobos/object.html#.destroy, $(D object.destroy())) + to finalize the object instead. + --- + auto a = new Class(); + destroy(a); + --- + ) + $(P Note that $(D destroy) does not free the allocated memory. If + necessary, call $(LINK2 phobos/core_memory.html#.GC.free, $(D core.GC.free)) also. + ) +$(H4 Rationale) + $(P $(D delete) makes assumptions about the type of garbage collector + available that limits which implementations can be used, and can be + replaced by a library solution. + ) + + + +$(H3 $(DEPNAME scope as a type constraint)) + $(P + The `scope` keyword can be added to a class declaration to force all instances of the + class to be attributed with the `scope` storage class. + + --- + scope class C { } // `scope` type constraint. This usage of `scope` is deprecated. + + void main() + { + C c1 = new C(); // Error: reference to `scope class` must be `scope` + // This error is due to the `scope` attribution on the declaration + // of `class C` and the missing `scope` storage class attribution + // on `c1`. + + scope C c2 = new C(); // OK because the instance `c2` is attributed with the `scope` + // storage class. This usage of `scope` is not deprecated. + } + --- + ) +$(H4 Corrective Action) + There is no current counterpart in the D programming language or library that places such a + constraint on a type requiring all instances of the type to be attributed with the `scope` + storage class. + +$(H4 Rationale) + $(P + `scope` as a type constraint was a quirk in the language without a compelling + use case. + ) + $(P + Note that this deprecation only affects the usage of `scope` as a type constraint + attributed to a class declaration. `scope` as a storage class attributed to variables, + function parameters, etc. is not deprecated. + ) + + +$(H3 $(DEPNAME Imaginary and complex types)) + $(P D currently supports imaginary and complex versions of all floating point types. + --- + float a = 2; + ifloat b = 4i; + cfloat c = a + b; + assert(c == 2 + 4i); + --- + ) +$(H4 Corrective Action) + $(P Use the library types in $(STDFILEREF complex). + ) +$(H4 Rationale) + $(P These types are too specialized to be a part of the core language. + ) + + +$(H3 $(DEPNAME 128-bit integer types)) + $(P D currently reserves the `cent` and `ucent` keywords for future use as + 128-bit integral types. Using them will result in a compile-time error. + ) + --- + cent a = 18446744073709551616L; + ucent b = 36893488147419103232UL; + --- + +$(H4 Corrective Action) + $(P Use the library types in $(MREF std, int128) or $(COREFILEREF int128). + ) +$(H4 Rationale) + $(P These types are too specialized to be a part of the core language. + ) + + +$(H3 $(DEPNAME Implicit catch statement)) + $(P One can catch everything by using $(D catch) without specifying a type.) + --- + int[] arr = new int[](10); + // This will throw a RangeError + try { arr[42]++; } + catch { writeln("An error was caught and ignored"); } + --- + +$(H4 Corrective Action) + $(P Either don't catch `Throwable` or replace `catch {}` with `catch (Throwable) {}`) + --- + int[] arr = new int[](10); + // This will throw a RangeError + try { arr[42]++; } + catch (Throwable) { writeln("An error was caught and ignored"); } + --- + +$(H4 Rationale) + $(P Catching `Throwable` should not be encouraged by the language, + because certain core guarantee cannot be satisfied, e.g. the stack might not get cleaned + up and destructors might not get run. + This change helps ensure catching `Throwable` is always a conscious and visible decision + on the programmer's side. + ) + + +$(H3 $(DEPNAME .sort and .reverse properties for arrays)) + $(P D arrays can be manipulated using these built-in properties. + --- + int[] x = [2, 3, 1]; + assert(x.sort == [1, 2, 3]); + --- + ) +$(H4 Corrective Action) + $(P Use the generic functions in $(STDFILEREF algorithm). + ) +$(H4 Rationale) + $(P These operations are better implemented in the standard library. + ) + + + +$(H3 $(DEPNAME C-style array pointers)) + $(P C-style array pointers can be used in D. + --- + alias float *arrayptr[10][15]; + --- + ) +$(H4 Corrective Action) + $(P Replace with D-style array pointers. + --- + alias float[15][10]* arrayptr; + --- + ) +$(H4 Rationale) + $(P The D syntax is much cleaner and easier to use. + ) + + + +$(H3 $(DEPNAME Floating point NCEG operators)) + $(P D currently supports the NCEG floating point operators + (!<>=, <>, <>=, !>, !>=, !<, !<=, !<>) for comparisons involving NaNs. + ) +$(H4 Corrective Action) + $(P Use the normal operators and $(REF isNaN, std,math,traits). + ) +$(H4 Rationale) + $(P These operators are too specialized to be a part of the core language. + ) + + + +$(H3 $(DEPNAME clear)) + $(P Call an object's destructor. + --- + auto a = new Class(); + clear(a); + --- + ) +$(H4 Corrective Action) + $(P Use $(LINK2 phobos/object.html#.destroy, $(D object.destroy())) instead. + --- + auto a = new Class(); + destroy(a); + --- + ) +$(H4 Rationale) + $(P Due to Uniform Function Call Syntax (UFCS), $(D clear) can cause + confusion with other methods of the same name, such as a $(D clear) + method used to remove the contents of a container. + ) + + + +$(H3 $(DEPNAME .min property for floating point types)) + $(P Floating point types have the .min property to access the smallest value. + --- + enum m = real.min; + --- + ) +$(H4 Corrective Action) + $(P Replace with .min_normal + --- + enum m = real.min_normal; + --- + ) +$(H4 Rationale) + $(P The name min_normal is more accurate, as .min does not include + denormalized floating point values. + ) + + + +$(H3 $(DEPNAME Cast T[] to integral type)) + $(P At some point in time you could do: + --- + ulong u = cast(ulong)[1,2]; + --- + To get the length of the array. + ) +$(H4 Corrective Action) + $(P Use the $(LINK2 https://dlang.org/spec/arrays.html#array-properties, .length) + property instead. + ) +$(H4 Rationale) + $(P Using a cast to get the length of an array is just confusing. + ) + + + +$(H3 $(DEPNAME Base Class Protection)) + $(P Base class protections are things like: + --- + class A : $(D protected) B + { + ... + } + --- + ) +$(H4 Corrective Action) + $(P Delete the protection attribute keyword from in front of the base class + and base interfaces. + ) +$(H4 Rationale) + $(P With D's module system, it doesn't seem to serve any useful purpose, and + has never worked correctly. + ) + + + +$(H3 $(DEPNAME Windows 3.x and Windows 9x support)) + $(P There is some code in Phobos for Windows 3.x/9x support. + ) +$(H4 Corrective Action) + $(P Upgrade Windows or switch to another supported OS. + ) +$(H4 Rationale) + $(P Supporting such outdated and rarely used OS-es isn't worth the trouble. + ) -

    Corrective Action

    - $(P Delete the protection attribute keyword from in front of the base class - and base interfaces. - ) -

    Rationale

    +$(H3 $(DEPNAME typedef)) + $(P typedef can be used to construct a strongly-typed alias of a type. + --- + typedef int myint; + static assert(!is(myint == int)); + --- + ) +$(H4 Corrective Action) + $(P Replace use of typedef with alias or use $(REF Typedef, std,typecons). + ) +$(H4 Rationale) + $(P typedef is not flexible enough to cover all use cases. This is better + done with a library solution. + ) - $(P With D's module system, it doesn't seem to serve any useful purpose.) + +$(H3 $(DEPNAME Using * to dereference arrays)) + $(P D array variables can be dereferenced to get the first element, much like pointers. + --- + int[] arr = [1, 2, 3]; + assert(*arr == 1); + --- + ) +$(H4 Corrective Action) + $(P Use indexing syntax to access first member. + --- + int[] arr = [1, 2, 3]; + assert(arr[0] == 1); + --- + ) +$(H4 Rationale) + $(P D arrays are not pointers. + ) + + + +$(H3 $(DEPNAME invariant as an alias for immutable)) + $(P The invariant storage class and type modifier is an alias for immutable. + --- + static assert(is(invariant(int) == immutable(int))); + --- + ) +$(H4 Corrective Action) + $(P Replace all uses of invariant as a storage class or type modifier with + immutable. The invariant() syntax for struct and class invariants is + still supported. + ) +$(H4 Rationale) + $(P The alias is unnecessary. + ) + + + +$(H3 $(DEPNAME Non-final switch statements without a default case)) + $(P Switch statements can be declared without a default case, and the + compiler automatically adds one. + --- + switch(a) + { + case 1: + break; + case 2: + break; + // the compiler adds + // default: + // throw new SwitchError(); + } + --- + ) +$(H4 Corrective Action) + $(P Add the default case manually. + --- + switch(a) + { + case 1: + break; + case 2: + break; + default: + assert(0); + } + --- + ) +$(H4 Rationale) + $(P Missing default cases can hide bugs, and making the default case + explicit should be mandatory. + ) + + + +$(H3 $(DEPNAME Hiding base class functions)) + $(P This occurs when declaring a function in a derived class that can be called with the + same arguments as a function in a base class, without overriding that + function. The base class function gets hidden: + --- + class A + { + void fun(int x) {} + } + class B : A + { + void fun(long x) {} + } + --- + ) +$(H4 Corrective Action) + $(P Add the function to the base class, or use an alias to bring the base + class overload into the derived class: + --- + class A + { + void fun(int x) {} + void fun(long x) {} // this fixes it + } + class B : A + { + void fun(long x) {} + alias A.fun fun; // so does this + } + --- + ) +$(H4 Rationale) + $(P This is an error that is already detected at runtime, and is being + extended to compile time. + ) + + + +$(H3 $(DEPNAME Octal literals)) + $(P Octal literals can be used to enter literals in base 8. + --- + // deprecated code + // auto x = 0123; + --- + ) +$(H4 Corrective Action) + $(P Use the $(REF octal, std,conv) template. + --- + auto x = octal!123; + --- + ) +$(H4 Rationale) + $(P The use of a leading zero is confusing, as 0123 != 123. + ) + + + +$(H3 $(DEPNAME C-style function pointers)) + $(P C-style function pointers can be used in D. + --- + alias void(*fptr)(int, long); + --- + ) +$(H4 Corrective Action) + $(P Replace with D-style function pointers. + --- + alias void function(int, long) fptr; + --- + ) +$(H4 Rationale) + $(P The D syntax is much cleaner and easier to use. + ) + + + +$(H3 $(DEPNAME Using length in index expressions)) + $(P When used inside an indexing or slicing expression, length is rewritten to + be the length of the array being sliced. + --- + auto a = new int[5]; + a = a[0..length-1]; + --- + ) +$(H4 Corrective Action) + $(P Replace length with the equivalent $(LINK2 spec/arrays.html#array-length, '$') + ) +$(H4 Rationale) + $(P The implicitly defined length variable shadows existing declarations, + and is less concise than the alternative. + ) + + + +$(H3 $(DEPNAME Escape string literals)) + $(P Escape string literals can be used to describe characters using escape sequences. + --- + // deprecated code + // string x = "hello" ~ \n; + --- + ) +$(H4 Corrective Action) + $(P Put escape sequences inside a regular string literal. + --- + string x = "hello\n"; + --- + ) +$(H4 Rationale) + $(P Escape string literals are unintuitive and unnecessary. + ) + + + +$(H3 $(DEPNAME volatile)) + $(P volatile can be used to mark statement, in order to prevent some + compiler optimizations. + --- + volatile + { + ... do something involving ghared variables ... + } + --- + ) +$(H4 Corrective Action) + $(P Convert the code to use synchronized statements instead. + ) +$(H4 Rationale) + $(P volatile statements are a misfeature. + ) + + + +$(H3 $(DEPNAME HTML source files)) + $(P The D compiler can parse html files by ignoring everything not contained + in <code></code> tags. + --- + + + ... source ... + + + --- + ) +$(H4 Corrective Action) + $(P Extract code to regular source files. + ) +$(H4 Rationale) + $(P This has been replaced for documentation by the introduction of ddoc + ) + + + +$(H3 $(DEPNAME Overriding without override)) + $(P Virtual functions can currently override a function in a base class + without the 'override' attribute. + --- + class A + { + void fun() {} + } + class B : A + { + // overrides but is not marked with override + void fun() {} + } + --- + ) +$(H4 Corrective Action) + $(P Mark overriding functions with $(D override) + --- + class A + { + void fun() {} + } + class B : A + { + override void fun() {} + } + --- + ) +$(H4 Rationale) + $(P Making the $(D override) attribute mandatory makes it explicit, and can + catch errors when a base class function is accidentally overridden. + ) + + + +$(H3 $(DEPNAME Lower case 'l' suffix for integer literals)) + $(P Lower case 'l' is an alternative suffix to denote 64 bit integer literals. + --- + // deprecated code + // auto x = 123l; + --- + ) +$(H4 Corrective Action) + $(P Use the upper case 'L' suffix. + --- + auto x = 123L; + --- + ) +$(H4 Rationale) + $(P The lower case suffix is easily confused with the digit '1'. + ) +$(H4 Note) + $(P In lexical analysis phase, compiler can recognize lower case suffix 'l' + to report better error message - for the use case such as C-to-D code + translation. Thus DMD would continue to parse 'l' suffix. + ) + + + +$(H3 $(DEPNAME Variable shadowing inside functions)) + $(P Variable shadowing is when a variable in an inner scope has the same + name as a variable in an enclosing scope. + --- + void myFun() + { + int var; + if (x) + { + int var; + var = 3; // which var was meant? + } + } + --- + ) +$(H4 Corrective Action) + $(P Rename shadowing variables so they don't conflict. + ) +$(H4 Rationale) + $(P Variable shadowing can introduce hard to find bugs where the wrong + variable is modified. + ) + + + +$(H3 $(DEPNAME Upper case 'I' suffix for imaginary literals)) + $(P The 'I' suffix can be used to denote imaginary floating point values. + --- + // deprecated code + // auto x = 1.234I; + --- + ) +$(H4 Corrective Action) + $(P Use the lower case 'i' suffix. + --- + auto x = 1.234i; + --- + ) +$(H4 Rationale) + $(P The 'I' suffix is easily confused with the digit '1'. + ) + + + +$(H3 $(DEPNAME if (v; e))) + $(P This syntax can be used to declare a variable in an if statement condition. + --- + if (v; calculateAndReturnPointer()) { ... } + --- + ) +$(H4 Corrective Action) + $(P Replace with an auto declaration. + --- + if (auto v = calculateAndReturnPointer()) { ... } + --- + ) +$(H4 Rationale) + $(P The syntax is clearer with auto. + ) + + + +$(H3 $(DEPNAME Removing an item from an associative array with delete)) + $(P delete can be used to remove an item from an associative array. + --- + int[int] aa = [1 : 2]; + delete aa[1]; + assert(1 !in aa); + --- + ) +$(H4 Corrective Action) + $(P Use .remove instead. + --- + int[int] aa = [1 : 2]; + aa.remove(1); + assert(1 !in aa); + --- + ) +$(H4 Rationale) + $(P The delete syntax is confusing and conflicts with the normal delete syntax. + ) + + + +$(H3 $(DEPNAME .offset property)) + $(P The .offset property can be used to get member offset information. + --- + struct S { int a, b; } + static assert(S.b.offset == 4); + --- + ) +$(H4 Corrective Action) + $(P Use .offsetof instead + --- + struct S { int a, b; } + static assert(S.b.offsetof == 4); + --- + ) +$(H4 Rationale) + $(P The .offset syntax has been superseded by .offsetof + ) + + + +$(H3 $(DEPNAME .size property)) + $(P The .size property can be used to get type size information + --- + struct S { int a, b; } + static assert(S.size == 8); + --- + ) +$(H4 Corrective Action) + $(P Use .sizeof instead + --- + struct S { int a, b; } + static assert(S.sizeof == 8); + --- + ) +$(H4 Rationale) + $(P The .size syntax has been superseded by .sizeof + ) + + + +$(H3 $(DEPNAME .typeinfo property)) + $(P The .typeinfo property can be used to get the associated TypeInfo class. + --- + T.typeinfo + --- + ) +$(H4 Corrective Action) + $(P Use typeid() instead + --- + typeid(T) + --- + ) +$(H4 Rationale) + $(P The .typeinfo syntax has been superseded by typeid() + ) + + + +$(H3 $(DEPNAME unannotated asm blocks)) + $(P $(D asm) blocks don't affect the function annotations. + --- + void foo() @safe + { + asm { noop; } + } + --- + ) +$(H4 Corrective Action) + $(P Annotate the $(D asm) blocks instead + --- + void foo() @safe + { + asm @trusted { noop; } + } + --- + ) +$(H4 Rationale) + $(P $(D asm) blocks may throw, contain unsafe, impure code or call the GC + interfaces.) ) -Macros: - DEPLINK=$(LINK2 #$0, $0) - DEPLINK2=$(LINK2 $1.html#$2, $2) - DEPNAME=$(LNAME2 $0, $0) - TITLE=Deprecated Features - WIKI=DeprecatedFeatures +$(H3 $(DEPNAME Throwing qualified objects)) + +$(P +Previously, an `immutable`, `const`, `inout` or `shared` exception could be +thrown and then caught in an unqualified `catch (Exception e)` clause. +That breaks type safety. +Throwing a qualified object is now deprecated. This helps to prevent +possible mutation of an immutable object in a `catch` clause. +) + +$(P +The runtime also modifies a thrown object (e.g. to contain a stack +trace) which can violate `const` or `immutable` objects. Throwing +qualified objects has been deprecated for this reason also. +) +$(H3 $(DEPNAME Catching immutable/inout/shared objects)) + +$(P +It is unsafe to catch an exception as `immutable`, `inout` or `shared`. +This is because the exception may still be accessible through another +mutable or non-shared reference. +) + +--- +auto e = new Exception("first"); +try { + throw e; +} catch(immutable Exception ie) { // unsafe + e.msg = "second"; + assert(ie.msg == "first"); // would fail +} +--- + + +Macros: + DEPLINK=$(RELATIVE_LINK2 $0, $0) + DEPLINK2=$(LINK2 $1.html#$2, $2) + DEPNAME=$(LNAME2 $0, $0) + TITLE=Deprecated Features + STDFILEREF = $(D std.$1) + COREFILEREF = $(D core.$1) diff --git a/dlang.org.ddoc b/dlang.org.ddoc new file mode 100644 index 0000000000..3028e24405 --- /dev/null +++ b/dlang.org.ddoc @@ -0,0 +1,590 @@ +_=Macros for the dlang.org site look and feel. Please keep sorted by name. Multiline macros should keep one _= line before and after for clarity. Also, one _= line should be present when the first letter changes. (The "_="" is needed so there's no extra newline after the last macro defined in a group.) + +ACRONYM = $1 ($+) +ACC = $(GLOSSARY2 acc, Associated C Compiler) +ASSIGNEXPRESSION = $(GLINK2 expression, AssignExpression) +_= + +BIGOH = $(SPANC bigoh, Ο($(D $0))) +BLOCKQUOTE = $(T blockquote, $(P $0)) +BLOCKQUOTE_BY = $(BLOCKQUOTE $+ $(T cite, $1)) +BLACK=$(SPANC black, $0) +BLUE=$(SPANC blue, $0) +BODY_PREFIX= +BOOKTABLE = $(TC table, book, $(T caption, $1)$+) +BUGZILLA = $(SPANC bugzilla, $(AHTTPS issues.dlang.org/show_bug.cgi?id=$0, Bugzilla $0)) +BUGZILLA_NEW_BUG_URL=https://github.com/dlang/$(PROJECT)/issues/new?title=%5B$(TITLE)%5D%20 +_= + +CCODE=$(TC pre, ccode notranslate, $0) +CODE=$(D $0) +CODE_AMP=$(D &) +CODE_DOLLAR=$(D $) +CODE_HIGHLIGHT=$(B $(I $0)) +CODE_LCURL=$(D {) +CODE_PERCENT=$(D %) +CODE_PIPE=$(D |) +CODE_RCURL=$(D }) +_= + +COMMON_HEADERS_DLANG= + +_= +COMMON_SCRIPTS = + $(SCRIPTLOAD https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js) + $(SCRIPT window.jQuery || document.write('\x3Cscript src="https://github.com/$(STATIC%20js/jquery-1.7.2.min.js)">\x3C/script>');$(EXTRA_JS)) + $(SCRIPTLOAD $(STATIC js/dlang.js)) + $(COMMON_SCRIPTS_DLANG) +_= +COMMON_SCRIPTS_DLANG = + $(SCRIPTLOAD $(STATIC js/codemirror-compressed.js)) + $(SCRIPTLOAD $(STATIC js/run.js)) +_= + +COMPATIBILITY_BOX_DEPRECATED = $(MESSAGE_BOX red, $(B Deprecated) - $0) +COMPATIBILITY_BOX_SUPERSEDED = $(MESSAGE_BOX gray, $(B Obsolete) - $0) +COMPATIBILITY_BOX_OBSOLETE = $(MESSAGE_BOX gray, $(B Obsolete) - $0) +COMPATIBILITY_BOX_OUTDATED = $(MESSAGE_BOX gray, $(B Obsolete) - $0) +COMPATIBILITY_BOX_EXPERIMENTAL = $(MESSAGE_BOX orange, $(B Experimental) - $0) +_= + +CONSOLE=$(TC pre, console notranslate, $0) +COPYRIGHT_FOUNDATION=Copyright © 1999-$(YEAR) by the $(LINK2 $(ROOT_DIR)foundation_overview.html, D Language Foundation) +CPPCODE=$(TC pre, cppcode notranslate, $0) +CPPLISTING=$(CPPCODE $0) +CROSS=✘ +_= + +D=$(SPANC d_inlinecode donthyphenate notranslate, $0) +D_CODE=$(TC pre, d_code notranslate, $0) +OTHER_CODE=$(TC pre, $1code notranslate, $+) +_= + +DDOC= + + + + + + + +$(T title, $(FULL_TITLE)) +$(COMMON_HEADERS_DLANG) + + + + +$(EXTRA_HEADERS) + + +$(SCRIPT document.body.className += ' have-javascript') +$(DIVID top, $(DIVC helper, $(DIVC helper expand-container, + $(DIVC logo, ) + Menu + $(NAVIGATION) + $(DIVC search-container expand-container, + Search + $(SEARCH_BOX) + ) +))) +$(LAYOUT_PREFIX) +$(DIVC container, + $(SUBNAV) + $(DIVCID $(HYPHENATE), content, + $(PAGE_TOOLS) + $(LAYOUT_TITLE) + $(BODY_PREFIX) + $(BODY) + $(FOOTER) + ) +) +$(COMMON_SCRIPTS) +$(EXTRA_FOOTERS) +$(LAYOUT_SUFFIX) + + +$(LF) +_= + +DDLINK=$(LINK2 $(ROOT_DIR)$1.html, $3) +DDOC_BACKQUOTED = $(D $0) +DDOC_SUMMARY = $(DIVC summary, $0) +DDOC_DESCRIPTION = $(DIVC description, $0)$(LF) +DDOC_AUTHORS = $(DDOCKEYVAL Authors, $0)$(LF) +DDOC_BUGS = $(DDOCKEYVAL Bugs, $0)$(LF) +DDOC_COPYRIGHT = $(DDOCKEYVAL Copyright, $0)$(LF) +DDOC_DATE = $(DDOCKEYVAL Date, $0)$(LF) +DDOC_DEPRECATED = $(DDOCKEYVAL Deprecated, $0)$(LF) +DDOC_EXAMPLES = $(DDOCKEYVAL Examples, $0)$(LF) +DDOC_HISTORY = $(DDOCKEYVAL History, $0)$(LF) +DDOC_LICENSE = $(DDOCKEYVAL License, $0)$(LF) +DDOC_RETURNS = $(DDOCKEYVAL Returns, $0)$(LF) +DDOC_SEE_ALSO = $(DDOCKEYVAL2 SeeAlso, See Also, $0)$(LF) +DDOC_STANDARDS = $(DDOCKEYVAL Standards, $0)$(LF) +DDOC_THROWS = $(DDOCKEYVAL Throws, $0)$(LF) +DDOC_VERSION = $(DDOCKEYVAL Version, $0)$(LF) +DDOC_SECTION_H =

    $(SPANC key keySection, $0)$(LF) +DDOC_SECTION = $(DIVC val, $0

    )$(LF) +DDOC_PARAM_ROW = $0$(LF) +DDOC_PARAM_ID = $0$(LF) +DDOC_PARAM_DESC = $0 +DDOC_PARAMS = $(DDOCKEYVAL Parameters, $0
    )$(LF) +DDOC_BLANKLINE = +DDOC_KEYWORD = $(TC code, ddoc_keyword, $0) +DDOC_PARAM = $(TC code, ddoc_param, $0) +DDOC_PSYMBOL = $(ADEF $0)$(TC code, ddoc_psymbol, $0) +DDOC_ANCHOR = $(ADEF .$1)$(DIVCID quickindex, quickindex.$1, ) +DDOC_DECL = $(TC dt, d_decl, $(DIV, $0)) +DDOC_UNDEFINED_MACRO = $(DDOC_COMMENT UNDEFINED MACRO: "$1") +DDOCCODE=$(TC pre, ddoccode notranslate, $0) +DDOCKEYVAL=$(DIVC keyval $1, $(SPANC key key$1, $1:) $(DIVC val val$1, $+)) +DDOCKEYVAL2=$(DIVC keyval $1, $(SPANC key key$1, $2:) $(DIVC val val$1, $(TAIL $+))) +DDSUBLINK=$(LINK2 $(ROOT_DIR)$1.html#$2, $3) +_= + + +DMDSRC=$(HTTPS github.com/dlang/dmd/blob/master/src/dmd/$0, $0) +DOT_PREFIXED=.$1$(DOT_PREFIXED $+) +DOT_PREFIXED_SKIP=$(DOT_PREFIXED $+) +DRUNTIMESRC=$(HTTPS github.com/dlang/dmd/blob/master/druntime/src/$0, $0) +_= + +$(COMMENT URL prefix for the site root. + Relative (e.g. "../") for dlang.org pages; + absolute ("https://dlang.org/") for the ebook.) +DPLLINK=$(LINK2 $(ROOT_DIR)$1,$+) +_= + +ELABORATE_HEADER=$(TR DC) +$(TR 32 bit64 bit) +_= +EXTRA_HEADERS= +EXTRA_JS= +EXTRA_FOOTERS= +_= + +FAVICON=$(STATIC favicon.ico) +FOOTER = $(DIVCID smallprint, copyright, $(COPYRIGHT_FOUNDATION) | Page generated by +$(LINK2 $(ROOT_DIR)spec/ddoc.html, Ddoc) on $(GEN_DATETIME)) +FOOTNOTE=$(SPANC footnote, $0) +FULL_TITLE=$(TITLE) - D Programming Language +_= + +GDEPRECATED=$0 +GRESERVED=$0 +GEN_DATETIME=$(DATETIME) +GLINK=$(RELATIVE_LINK2 $0, $(I $0)) +GLINK2=$(DDSUBLINK spec/$1,$2,$(I $2)) +GLINK2_ALTTEXT=$(DDSUBLINK spec/$1,$2,$(I $3)) +GLINK_LEX=$(DDSUBLINK spec/lex,$1,$(I $1)) +GLOSSARY = $(HTTP dlang.org/spec/glossary.html#$0, $0) +GLOSSARY2 = $(HTTP dlang.org/spec/glossary.html#$1, $2) +GNAME=$(SPANC gname, $0) +_= +$(COMMENT GRAMMAR invocations will appear in spec/grammar.html, but NOT the suffixed macros) +GRAMMAR=$(TC pre, bnf notranslate, $0) +GRAMMAR_INFORMATIVE=$(GRAMMAR $0) +GRAMMAR_LEX=$(GRAMMAR $0) +GRAMMAR_INLINE=$(TC tt, bnf notranslate, $0) +GREEN=$(SPANC green, $0) +GSELF=$(I $0) +GT=> +_= + +HASH=# +HEADERNAV_TOC=$(DIVC page-contents quickindex, + $(DIVC page-contents-header, + $(B Contents) + ) + $(OL $0) +) +HEADERNAV_ITEM=$(LI $(RELATIVE_LINK2 $1, $+)) +HEADERNAV_SUBITEMS=$(LI $(RELATIVE_LINK2 $1, $2)$(OL $(MULTICOLS $+))) +HTMLTAG3=<$1 $2>$(TAIL $+) +HTMLTAG3V=<$1 $2>$(TAIL $+) +HYPHENATE=hyphenate +_= + + +ISEXPRESSION=$(GLINK2 expression, IsExpression) +_= + +LATEX= +LAYOUT_PREFIX= +LAYOUT_SUFFIX= +LAYOUT_TITLE=$(H1 $(TITLE)) +LEGACY_LNAME2=$(LNAME2 $+) +PHOBOS_PATH=$(ROOT_DIR)phobos/ +LIST=$(UL $(LIX $1, $+)) +LIX=$(LI $1)$(LIX $+) +LNAME2=$+ +LONGTABLE_2COLS=$(TABLE2 $2,$3 $4) +LONGTABLE_3COLS=$(TABLE2 $2,$3 $4) +LONGTABLE_5COLS=$(TABLE2 $1,$2 $3) +LT=< +LUCKY = $(HTTPS google.com/search?btnI=I%27m+Feeling+Lucky&ie=UTF-8&oe=UTF-8&q=$0,$0) +LUCKY2 = $(HTTPS google.com/search?btnI=I%27m+Feeling+Lucky&q=$+,$1) +_= + +MDASH=$(T nobr,  — ) +METACODE=$(SPANC metacode, $0) +MENU =
  • $+
  • +MENU_W_SUBMENU =
  • $(TT $1) +MENU_W_SUBMENU_LINK =
  • $+ +MENU_W_SUBMENU_END =
  • +MENU_INTERNAL_SEPARATOR = $(DIVC modlist-internal-separator, Internal API) +MESSAGE_BOX = $(DIVC message-box message-box-$1, $+) +META_KEYWORDS=D programming language +META_DESCRIPTION=D Programming Language +MODDEFFILE=$(TC pre, moddeffile notranslate, $0) +MULTICOL_CELL=$+ +MULTICOL_HEADER=$+ +MULTICOLS=$+ +MULTIROW_HEADER=$+ +MREF=$(LINK2 $(PHOBOS_PATH)$1$(UNDERSCORE_PREFIXED $+).html, $(D $1$(DOT_PREFIXED $+))) +MREF_ALTTEXT=$(LINK2 $(PHOBOS_PATH)$2$(UNDERSCORE_PREFIXED_SKIP $+).html, $1) +MREF1=$(LINK2 $(PHOBOS_PATH)$1.html, $(D $1)) +_= + + +NAVIGATION= +$(DIVID cssmenu, $(UL + $(MENU https://tour.dlang.org, Learn) + $(MENU_W_SUBMENU_LINK $(ROOT_DIR)documentation.html, Documentation) + $(NAVIGATION_DOCUMENTATION) + $(MENU $(ROOT_DIR)download.html, Downloads) + $(MENU https://code.dlang.org, Packages) + $(MENU_W_SUBMENU_LINK $(ROOT_DIR)community.html, Community) + $(NAVIGATION_COMMUNITY) + $(MENU_W_SUBMENU_LINK $(ROOT_DIR)resources.html, Resources) + $(NAVIGATION_RESOURCES) +)) +NAVIGATION_COMMUNITY= +$(SUBMENU_MANUAL + $(SUBMENU_LINK https://dlang.org/blog, Blog) + $(SUBMENU_LINK $(ROOT_DIR)orgs-using-d.html, Orgs using D) + $(SUBMENU_LINK https://twitter.com/search?q=%23dlang, Twitter) + $(SUBMENU_LINK_DIVIDER https://discord.gg/bMZk9Q4, Discord (community-run)) + $(SUBMENU_LINK https://forum.dlang.org, Forums) + $(SUBMENU_LINK irc://irc.libera.chat/d, IRC) + $(SUBMENU_LINK https://wiki.dlang.org, Wiki) + $(SUBMENU_LINK_DIVIDER $(ROOT_DIR)bugstats.html, Issues) + $(SUBMENU_LINK $(ROOT_DIR)contributing.html, Contributing) + $(SUBMENU_LINK_DIVIDER $(ROOT_DIR)foundation/contributors.html, Contributors) + $(SUBMENU_LINK $(ROOT_DIR)foundation/index.html, Foundation) + $(SUBMENU_LINK $(ROOT_DIR)/security.html, Security Team) + $(SUBMENU_LINK_DIVIDER https://store.dlang.org/, Store) + $(SUBMENU_LINK $(ROOT_DIR)foundation/donate.html, Donate) + $(SUBMENU_LINK $(ROOT_DIR)foundation/sponsors.html, Sponsors) +) +NAVIGATION_DOCUMENTATION= +$(SUBMENU_MANUAL + $(SUBMENU_LINK $(ROOT_DIR)spec/spec.html, Language Reference) + $(SUBMENU_LINK $(ROOT_DIR)phobos/index.html, Library Reference) + $(SUBMENU_LINK $(ROOT_DIR)dmd.html, Command-line Reference) + $(SUBMENU_LINK_DIVIDER $(ROOT_DIR)comparison.html, Feature Overview) + $(SUBMENU_LINK $(ROOT_DIR)articles.html, Articles) +) +NAVIGATION_RESOURCES= +$(SUBMENU_MANUAL + $(SUBMENU_LINK https://tour.dlang.org, Tour) + $(SUBMENU_LINK https://wiki.dlang.org/Books, Books) + $(SUBMENU_LINK https://wiki.dlang.org/Tutorials, Tutorials) + $(SUBMENU_LINK_DIVIDER https://wiki.dlang.org/Development_tools, Tools) + $(SUBMENU_LINK https://wiki.dlang.org/Editors, Editors) + $(SUBMENU_LINK https://wiki.dlang.org/IDEs, IDEs) + $(SUBMENU_LINK https://run.dlang.io, run.dlang.io) + $(SUBMENU_LINK $(VISUALD), Visual D) + $(SUBMENU_LINK_DIVIDER $(ROOT_DIR)acknowledgements.html, Acknowledgments) + $(SUBMENU_LINK $(ROOT_DIR)dstyle.html, D Style) + $(SUBMENU_LINK $(ROOT_DIR)spec/glossary.html, Glossary) + $(SUBMENU_LINK $(ROOT_DIR)sitemap.html, Sitemap) +) +_= + +NEWS=http://digitalmars.com/webnews/newsgroups.php?search_txt=$(AMP)group=$1$(AMP)article_id=$+ +NG_digitalmars_D = D/$0 +NG_digitalmars_D_announce = D.announce/$0 +NOTRANSLATE=$(SPANC notranslate, $0) +NO= +NOT_EBOOK=$0 +NOTE= $(DIVC note, $(B Note:) $0) +NOTICE_L=$2 +NOTICE=$1 +_= + +OPT=$(SUBSCRIPT opt) +_= + +PAGE_TOOLS= +$(DIVID tools, $(DIV, + $(DIVC tip smallprint, + $(HTMLTAG3 a, href="https://github.com/$(BUGZILLA_NEW_BUG_URL)$(AMP)label=Severity:Enhancement", Report a bug) + $(DIV, + If you spot a problem with this page, click here to create a Bugzilla issue. + ) + ) + $(DIVC tip smallprint, + Improve this page + $(DIV, + Quickly fork, edit online, and submit a pull request for this page. + Requires a signed-in GitHub account. This works well for small changes. + If you'd like to make larger changes you may want to consider using + a local clone. + ) + ) +)) +_= + +_=Group related info together +PANEL=$(DIVC panel, $0) +PC=$(TC p, $1, $+) +_= + +PHOBOSSRC=$(SPANC phobos_src, $(AHTTPS github.com/dlang/phobos/blob/master/$0, $0)) +_= + +RED=$(SPANC red, $0) +_= + +$(COMMENT + The REF macro generates a link to a phobos symbol. + + The first argument is the symbol name inside its module, without any + module/package parts, in usual dotted format. + + Arguments 2 and higher form the module name. The segments are passed + as individual arguments. + + The weird order is due to the format of the generated link, and Ddoc being + simplistic. + + The REF1 variants work around DDoc limitations and allow linking to + modules not inside packages (i.e. object.) + + Example: + + $(REF Array.back, std,container,array) generates a link to + std.container.array.Array.back + + To clarify, std.container.array is a module, Array is a struct in that + module, and back is a method of that struct. + + The generated href will be "phobos/std_container_array.html#.Array.back" + (the phobos path can be different, of course). +) +REF=$(LINK2 $(PHOBOS_PATH)$2$(UNDERSCORE_PREFIXED_SKIP $+).html#.$1, $(D $2$(DOT_PREFIXED_SKIP $+, $1))) +REF1=$(LINK2 $(PHOBOS_PATH)$2.html#.$1", $(D $1)) +_= + +$(COMMENT + The REF_ALTTEXT macro works the same as the REF macro, but it has another + parameter in front of the others that specifies the link text. + + Example: + $(REF_ALTTEXT the 'back' method, Array.back, std,container,array) + generates a link like this: + the 'back' method +) +REF_ALTTEXT=$(LINK2 $(PHOBOS_PATH)$3$(UNDERSCORE_PREFIXED_SKIP2 $+).html#.$2, $1) +REF1_ALTTEXT=$(LINK2 $(PHOBOS_PATH)$3.html#.$2", $1) +_= + +$(COMMENT + REF_SHORT takes the same arguments as REF. It displays only the + unqualified symbol name, without module or packages. +) +REF_SHORT=$(REF_ALTTEXT $(D $1), $1, $+) +_= + +RELATIVE_LINK2=$(ALOCAL $1, $+) +_= + +_=These take a ddoc example enclosed in `---` +RUNNABLE_EXAMPLE=
    +$1 +
    +RUNNABLE_EXAMPLE_COMPILE=
    +$1 +
    +RUNNABLE_EXAMPLE_FAIL=$(RUNNABLE_EXAMPLE $0) +_=These go inside a RUNNABLE_EXAMPLE macro invocation before the first `---` +RUNNABLE_EXAMPLE_STDIN=$0 +RUNNABLE_EXAMPLE_ARGS=$0 + +SCINI=$(TC pre, scini notranslate, $0) +SCRIPTLOAD= +SEARCHDEFAULT_PHOBOS= +SEARCHDEFAULT_FORUM= +SEARCHDEFAULT_SPEC= +SEARCH_BOX= + $(DIVID search-box, +
    + + + $(SPANID search-query, )$(SPANID search-dropdown, $(SPANC helper, + + ))$(SPANID search-submit, ) +
    + ) +SEARCH_OPTIONS_EXTRA= +_= + +SECTION1=$(H1 $1)$+ +SECTION2=$(H2 $1)$+ +SECTION3=$(H3 $1)$+ +SECTION4=$(H4 $1)$+ +SECTION5=$(H5 $1)$+ +_= + +$(COMMENT + SIMPLE_CHEATSHEET is used for cheat sheets that play the same role + as the listings generated by DDOX. Consequently, DDOX hides these cheat + sheets. +) +SIMPLE_CHEATSHEET=$(TC table, simple-cheatsheet, $(T caption, Cheat Sheet) $0) +_= + +SLASH_PREFIXED=/$1$(SLASH_PREFIXED $+) + + +SRC_FILENAME=$(SRCFILENAME) +STATIC=$(ROOT_DIR)$1 +SUBMENU=
      $(SUBMENU2 $1,$+)
    +SUBMENU2=
  • $2
  • $(SUBMENU3 $+) +SUBMENU3=$(SUBMENU2 $+) +SUBMENU_MANUAL=
      $1 $+
    +SUBMENU_LINK=
  • $2
  • +SUBMENU_LINK_DIVIDER= +_= + +SUBNAV= +SUBNAV_ARTICLES= +$(SUBNAV_TEMPLATE + $(SUBNAV_HEAD Articles, $(ROOT_DIR)articles/index.html, overview) + $(UL $(SUBMENU2 + $(ROOT_DIR)articles/faq.html, FAQ, + $(ROOT_DIR)articles/const-faq.html, const(FAQ), + $(ROOT_DIR)articles/d-floating-point.html, Floating Point, + $(ROOT_DIR)articles/warnings.html, Warnings, + $(ROOT_DIR)articles/rationale.html, Rationale, + $(ROOT_DIR)articles/builtin.html, Builtin Rationale, + $(ROOT_DIR)articles/ctod.html, C to D, + $(ROOT_DIR)articles/cpptod.html, C++ to D, + $(ROOT_DIR)articles/pretod.html, C Preprocessor vs D, + $(ROOT_DIR)articles/code_coverage.html, Code coverage analysis, + $(ROOT_DIR)articles/exception-safe.html, Exception Safety, + $(ROOT_DIR)articles/hijack.html, Hijacking, + $(ROOT_DIR)articles/intro-to-datetime.html, Introduction to std.datetime, + $(ROOT_DIR)articles/lazy-evaluation.html, Lazy Evaluation, + $(ROOT_DIR)articles/migrate-to-shared.html, Migrating to Shared, + $(ROOT_DIR)articles/mixin.html, String Mixins, + $(ROOT_DIR)articles/regular-expression.html, Regular Expressions, + $(ROOT_DIR)articles/safed.html, SafeD, + $(ROOT_DIR)articles/templates-revisited.html, Templates Revisited, + $(ROOT_DIR)articles/constraints.html, Template Constraints, + $(ROOT_DIR)articles/ctarguments.html, Compile-time Sequences, + $(ROOT_DIR)articles/variadic-function-templates.html, Variadic Templates, + $(ROOT_DIR)articles/template-comparison.html, Template Comparison, + $(ROOT_DIR)articles/d-array-article.html, D Slices, + $(ROOT_DIR)articles/cppcontracts.html, D's Contract Programming, + $(ROOT_DIR)articles/dll-linux.html, Writing Shared Libraries for Linux, + $(ROOT_DIR)articles/RefReturnScope.html, Coralling Wild Pointers With ref return scope, + $(ROOT_DIR)articles/dll-windows.html, Creating Windows DLLs + )) +) +SUBNAV_FOUNDATION= +$(SUBNAV_TEMPLATE + $(SUBNAV_HEAD Foundation, $(ROOT_DIR)foundation/index.html, overview) + $(UL $(SUBMENU2 + $(ROOT_DIR)foundation/about.html, About the Foundation, + $(ROOT_DIR)foundation/donate.html, Donate, + $(ROOT_DIR)foundation/upb-scholarship.html, Scholarships, + https://dconf.org, DConf, + $(ROOT_DIR)foundation/sponsors.html, Sponsors, + $(ROOT_DIR)foundation/contributors.html, Contributors, + $(ROOT_DIR)foundation/prman.html, Pull-Request/Issue Managers, + )) +) + +SUBNAV_HEAD= + $(DIVC head, + $(H2 $1) + $(TC p, $4, + $(LINK2 $2, $3)) + ) +SUBNAV_TEMPLATE=$(DIVC subnav-helper) $(DIVC subnav, $0) +_= + +SUBNAV_CLI_REFERENCE= +$(SUBNAV_TEMPLATE + $(SUBNAV_HEAD Command-line Reference, http://wiki.dlang.org/Development_tools, overview) + $(UL $(SUBMENU2 + $(ROOT_DIR)dmd-windows.html, dmd (Windows), + $(ROOT_DIR)dmd-linux.html, dmd (Linux), + $(ROOT_DIR)dmd-osx.html, dmd (OSX), + $(ROOT_DIR)dmd-freebsd.html, dmd (FreeBSD), + $(ROOT_DIR)rdmd.html, rdmd, + $(ROOT_DIR)install.html, install.sh, + $(ROOT_DIR)htod.html, htod + )) +) +SWNAME=$(LNAME2 switch$1, $(B $1)) +SWLINK=$(LINK2 #switch$1, $(B $1)) +SWITCH=$(DT $1)$(DD $+) +_= + +TABLE_10=$(TABLE2 $1, $+) +TABLE_2COLS=$(TABLE2 $1, $+) +TABLE_3COLS=$(TABLE2 $1, $+) +TABLE_SPECIAL=$(TABLE2 $1,$+) +TABLE2=$(T center, $(T table, $(T caption, $1)$(CONCAT $+))) +TDX=$(TD $1)$(TDX $+) +TH=$0 +THEAD=$(TR $(THX $1, $+)) +THX=$(TC th, donthyphenate, $(B $1))$(THX $+) +TOC=$(SPEC_S $1,$+) +TOC_LISTING=$0 +TR2=$(TR $1 $2) +TR3=$(TR $1 $2 $3) +TROW=$(TR $(TDX $1, $+)) +TROW_EXPLANATORY=$0 +_= + +UNDERSCORE=_ +UNDERSCORE_PREFIXED=_$1$(UNDERSCORE_PREFIXED $+) +UNDERSCORE_PREFIXED_SKIP=$(UNDERSCORE_PREFIXED $+) +UNDERSCORE_PREFIXED_SKIP2=$(UNDERSCORE_PREFIXED_SKIP $+) +_= + +VERTROW=$(TR $(TDX $1, $+)) +VISUALD = http://rainers.github.io/visuald/visuald/StartPage.html +_= + +WHITE=$(SPANC white, $0) +_= + +YELLOW=$(SPANC yellow, $0) +YES=$(CHECKMARK) + +PROJECT_SOURCE_DIR= + +FA_ICON= +_= + +_ = Opt-out of automatic keyword highlighting - see https://dlang.org/changelog/2.079.0.html#fix18361 +DDOC_AUTO_PSYMBOL = $0 +DDOC_AUTO_KEYWORD = $0 +DDOC_AUTO_PARAM = $0 +_ = DDOC_AUTO_PSYMBOL_SUPPRESS = FIXME_UNDERSCORE_PREFIX +DDOC_AUTO_PSYMBOL_SUPPRESS = $1 diff --git a/dlangspec.opf b/dlangspec.opf index 2ae26969db..2bb182d196 100644 --- a/dlangspec.opf +++ b/dlangspec.opf @@ -20,7 +20,7 @@ D Programming Language Specification 2011-07-08 diff --git a/dlangspec.png b/dlangspec.png index 4fd57486c9..e9eb0a9c81 100644 Binary files a/dlangspec.png and b/dlangspec.png differ diff --git a/dll.dd b/dll.dd deleted file mode 100644 index e73ce4b4c8..0000000000 --- a/dll.dd +++ /dev/null @@ -1,631 +0,0 @@ -Ddoc - -$(D_S Writing Win32 DLLs in D, - - $(P DLLs (Dynamic Link Libraries) are one of the foundations - of system programming for Windows. The D programming - language enables the creation of several different types of - DLLs. - ) - - $(P For background information on what DLLs are and how they work - Chapter 11 of Jeffrey Richter's book - $(LINK2 http://www.amazon.com/exec/obidos/ASIN/1572315482/classicempire, - Advanced Windows) is indispensible. - ) - - $(P This guide will show how to create DLLs of various types with D.) - - $(UL - $(LI DLLs with a C interface) - $(LI DLLs that are COM servers) - $(LI D code calling D code in DLLs) - ) - -

    DLLs with a C Interface

    - - $(P A DLL presenting a C interface can connect to any other code - in a language that supports calling C functions in a DLL. - ) - - $(P DLLs can be created in D in roughly the same way as in C. - A $(D DllMain()) - is required, looking like: - ) - --------------------------------- -import std.c.windows.windows; -import core.sys.windows.dll; - -__gshared HINSTANCE g_hInst; - -extern (Windows) -BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) -{ - switch (ulReason) - { - case DLL_PROCESS_ATTACH: - g_hInst = hInstance; - dll_process_attach( hInstance, true ); - break; - - case DLL_PROCESS_DETACH: - dll_process_detach( hInstance, true ); - break; - - case DLL_THREAD_ATTACH: - dll_thread_attach( true, true ); - break; - - case DLL_THREAD_DETACH: - dll_thread_detach( true, true ); - break; - } - return true; -} - -------------------------------- - - $(P Notes:) - $(UL - $(LI DllMain simply forwards to the appropriate helper functions. These setup - the runtime, create thread objects for interaction with the garbage collector - and initialize thread local storage data.) - $(LI The DLL does not share its runtime or memory with other DLLs.) - $(LI The first boolean argument to the dll-helper functions specify whether all threads - should be controlled by the garbage collector. You might need more control over - this behaviour if there are threads in the process that must not be suspended. - In this case pass false to disable the automatic handling of all threads.) - $(LI The presence of $(D DllMain()) is recognized by the compiler - causing it to emit a reference to - $(LINK2 http://www.digitalmars.com/ctg/acrtused.html, __acrtused_dll) - and the $(TT phobos.lib) runtime library.) - ) - - Link with a .def - ($(LINK2 http://www.digitalmars.com/ctg/ctgDefFiles.html, Module Definition File)) - along the lines of: - -$(MODDEFFILE -LIBRARY MYDLL -DESCRIPTION 'My DLL written in D' - -EXETYPE NT -CODE PRELOAD DISCARDABLE -DATA WRITE - -EXPORTS - DllGetClassObject @2 - DllCanUnloadNow @3 - DllRegisterServer @4 - DllUnregisterServer @5 -) - - $(P The functions in the EXPORTS list are for illustration. - Replace them with the actual exported functions from MYDLL. - Alternatively, use - $(LINK2 http://www.digitalmars.com/ctg/implib.html, implib). - Here's an example of a simple DLL with a function print() - which prints a string: - ) - -

    mydll.d:

    -------------------------------- -module mydll; -import std.c.stdio; -export void dllprint() { printf("hello dll world\n"); } -------------------------------- - - $(P Note: We use $(CODE printf)s in these examples - instead of $(CODE writefln) - to make the examples as - simple as possible.) - -

    mydll.def:

    - -$(MODDEFFILE -LIBRARY "mydll.dll" -EXETYPE NT -SUBSYSTEM WINDOWS -CODE SHARED EXECUTE -DATA WRITE -) - - $(P Put the code above that contains $(CODE DllMain()) into a file - $(TT dll.d). - Compile and link the dll with the following command: - ) - -$(CONSOLE -C:>dmd -ofmydll.dll -L/IMPLIB mydll.d dll.d mydll.def -C:> -) - - $(P which will create mydll.dll and mydll.lib. - Now for a program, test.d, which will use the dll: - ) - -

    test.d:

    -------------------------------- -import mydll; - -int main() -{ - mydll.dllprint(); - return 0; -} -------------------------------- - - $(P Create an interface file mydll.di that doesn't have the function bodies:) - -

    mydll.di:

    -------------------------------- -export void dllprint(); -------------------------------- - - Compile and link with the command: - -$(CONSOLE -C:>dmd test.d mydll.lib -C:> -) - - and run: -$(CONSOLE -C:>test -hello dll world -C:> -) - - - -

    Memory Allocation

    - - $(P D DLLs use garbage collected memory management. The question is what - happens when pointers to allocated data cross DLL boundaries? - If the DLL presents a C interface, one would assume the reason - for that is to connect with code written in other languages. - Those other languages will not know anything about D's memory - management. Thus, the C interface will have to shield the - DLL's callers from needing to know anything about it. - ) - - $(P There are many approaches to solving this problem:) - - $(UL - - $(LI Do not return pointers to D gc allocated memory to the caller of - the DLL. Instead, have the caller allocate a buffer, and have the DLL - fill in that buffer.) - - $(LI Retain a pointer to the data within the D DLL so the GC will not free - it. Establish a protocol where the caller informs the D DLL when it is - safe to free the data.) - - $(LI Notify the GC about external references to a memory block by - calling GC.addRange.) - - $(LI Use operating system primitives like VirtualAlloc() to allocate - memory to be transferred between DLLs.) - - $(LI Use std.c.stdlib.malloc() (or another non-gc allocator) when - allocating data to be returned to the caller. Export a function - that will be used by the caller to free the data.) - - ) - -

    COM Programming

    - - Many Windows API interfaces are in terms of COM (Common Object Model) - objects (also called OLE or ActiveX objects). A COM object is an object - who's first field is a pointer to a vtbl[], and the first 3 entries - in that vtbl[] are for QueryInterface(), AddRef(), and Release(). -

    - - For understanding COM, Kraig Brockshmidt's - $(LINK2 http://www.amazon.com/exec/obidos/ASIN/1556158432/classicempire, Inside OLE) - is an indispensible resource. -

    - - COM objects are analogous to D interfaces. Any COM object can be - expressed as a D interface, and every D object with an interface X - can be exposed as a COM object X. - This means that D is compatible with COM objects implemented - in other languages. -

    - - While not strictly necessary, the Phobos library provides an Object - useful as a super class for all D COM objects, called ComObject. - ComObject provides a default implementation for - QueryInterface(), AddRef(), and Release(). -

    - - Windows COM objects use the Windows calling convention, which is not - the default for D, so COM functions need to have the attribute - extern (Windows). - - So, to write a COM object: - -------------------------------- -import std.c.windows.com; - -class MyCOMobject : ComObject -{ - extern (Windows): - ... -} -------------------------------- - - The sample code includes an example COM client program and server DLL. - -

    D code calling D code in DLLs

    - - Having DLLs in D be able to talk to each other as if they - were statically linked together is, of course, very desirable - as code between applications can be shared, and different - DLLs can be independently developed. -

    - - The underlying difficulty is what to do about garbage collection (gc). - Each EXE and DLL will have their own gc instance. While - these gc's can coexist without stepping on each other, - it's redundant and inefficient to have multiple gc's running. - The idea explored here is to pick one gc and have the DLLs - redirect their gc's to use that one. The one gc used here will be - the one in the EXE file, although it's also possible to make a - separate DLL just for the gc. -

    - - The example will show both how to statically load a DLL, and - to dynamically load/unload it. -

    - - Starting with the code for the DLL, mydll.d: -------------------------------- -/* - * MyDll demonstration of how to write D DLLs. - */ - -import core.runtime; -import std.c.stdio; -import std.c.stdlib; -import std.string; -import std.c.windows.windows; - -HINSTANCE g_hInst; - -extern (C) -{ - void gc_setProxy(void* p); - void gc_clrProxy(); -} - -extern (Windows) - BOOL $(B DllMain)(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) -{ - switch (ulReason) - { - case DLL_PROCESS_ATTACH: - printf("DLL_PROCESS_ATTACH\n"); - Runtime.initialize(); - break; - - case DLL_PROCESS_DETACH: - printf("DLL_PROCESS_DETACH\n"); - Runtime.terminate(); - break; - - case DLL_THREAD_ATTACH: - printf("DLL_THREAD_ATTACH\n"); - return false; - - case DLL_THREAD_DETACH: - printf("DLL_THREAD_DETACH\n"); - return false; - } - g_hInst = hInstance; - return true; -} - -export void $(B MyDLL_Initialize)(void* gc) -{ - printf("MyDLL_Initialize()\n"); - gc_setProxy(gc); -} - -export void $(B MyDLL_Terminate)() -{ - printf("MyDLL_Terminate()\n"); - gc_clrProxy(); -} - -$(B static this)() -{ - printf("static this for mydll\n"); -} - -$(B static ~this)() -{ - printf("static ~this for mydll\n"); -} - -/* --------------------------------------------------------- */ - -class $(B MyClass) -{ - char[] $(B concat)(char[] a, char[] b) - { - return a ~ " " ~ b; - } - - void $(B free)(char[] s) - { - delete s; - } -} - -export MyClass $(B getMyClass)() -{ - return new MyClass(); -} -------------------------------- - -

    -
    $(B DllMain) -
    This is the main entry point for any D DLL. It gets called - by the C startup code - (for DMC++, the source is $(TT \dm\src\win32\dllstart.c)). - The $(B printf)'s are placed there so one can trace how it gets - called. - Notice that the initialization and termination code seen in - the earlier DllMain sample code is in this version as well. - This is because the same DLL should be usable from both C and - D programs, so the same initialization process should work - for both. -

    - -

    $(B MyDLL_Initialize) -
    - When the DLL is dynamically linked via $(B Runtime.loadLibrary)() - the runtime makes sure that any initialization steps required - by the D program are executed after the library is loaded. If - the library is statically linked, this routine is not called by - the program, so to make sure the DLL is initialized properly we - have to do some of the work ourselves. And because the library - is being statically linked, we need a function specific to this - DLL to perform the initialization. - This function takes one argument, a handle to the - caller's gc. We'll see how that handle is obtained later. - To pass this handle to the runtime and override the DLL's built-in - gc we'll call $(B gc_setProxy)(). - The function is $(B export)ed as that is how a function is made - visible outside of a DLL. -

    - -

    $(B MyDLL_Terminate) -
    Correspondingly, this function terminates the DLL, and is - called prior to unloading it. - It has only one job: informing the runtime that the DLL will - no longer be using the caller's gc via $(B gc_clrProxy)(). - This is critical, as the DLL will be unmapped from memory, - and if the gc continues to scan its data areas it will cause - segment faults. -

    - -

    $(B static this, static ~this) -
    These are examples of the module's static constructor - and destructor, - here with a print in each to verify that they are running - and when. -

    - -

    $(B MyClass) -
    This is an example of a class that can be exported from - and used by the caller of a DLL. The $(B concat) member - function allocates some gc memory, and $(B free) frees gc - memory. -

    - -

    $(B getMyClass) -
    An exported factory that allocates an instance of $(B MyClass) - and returns a reference to it. -

    - -

    - - To build the $(TT mydll.dll) DLL: - - $(OL - $(LI$(B $(TT dmd -c mydll -g)) -
    Compiles $(D mydll.d) into $(TT mydll.obj). - $(B -g) turns on debug info generation. - ) - - $(LI $(B $(TT dmd mydll.obj mydll.def -g -L/map)) -
    Links $(TT mydll.obj) into a DLL named $(TT mydll.dll). - $(TT mydll.def) is the - $(LINK2 http://www.digitalmars.com/ctg/ctgDefFiles.html, Module Definition File), - and has the contents: - -$(MODDEFFILE -LIBRARY MYDLL -DESCRIPTION 'MyDll demonstration DLL' -EXETYPE NT -CODE PRELOAD DISCARDABLE -DATA PRELOAD MULTIPLE -) - $(B -g) turns on debug info generation, and - $(B -L/map) generates a map file $(TT mydll.map). - ) - - $(LI $(B $(TT implib /noi /system mydll.lib mydll.dll)) -
    Creates an - $(LINK2 http://www.digitalmars.com/ctg/implib.html, import library) - $(TT mydll.lib) suitable - for linking in with an application that will be statically - loading $(TT mydll.dll). - ) - - ) - - $(P Here's $(TT test.d), a sample application that makes use of - $(TT mydll.dll). There are two versions, one statically binds to - the DLL, and the other dynamically loads it. - ) - -------------------------------- -import core.runtime; -import std.stdio; -import std.gc; - -import mydll; - -//version=DYNAMIC_LOAD; - -version (DYNAMIC_LOAD) -{ - import std.c.windows.windows; - - alias MyClass function() getMyClass_fp; - - int main() - { HMODULE h; - FARPROC fp; - - getMyClass_fp getMyClass; - MyClass c; - - printf("Start Dynamic Link...\n"); - - h = cast(HMODULE) Runtime.loadLibrary("mydll.dll"); - if (h is null) - { - printf("error loading mydll.dll\n"); - return 1; - } - - fp = GetProcAddress(h, "D5mydll10getMyClassFZC5mydll7MyClass"); - if (fp is null) - { printf("error loading symbol getMyClass()\n"); - return 1; - } - - getMyClass = cast(getMyClass_fp) fp; - c = (*getMyClass)(); - foo(c); - - if (!Runtime.unloadLibrary(h)) - { printf("error freeing mydll.dll\n"); - return 1; - } - - printf("End...\n"); - return 0; - } -} -else -{ // static link the DLL - extern (C) - { - void* gc_getProxy(); - } - - int main() - { - printf("Start Static Link...\n"); - MyDLL_Initialize(gc_getProxy()); - foo(getMyClass()); - MyDLL_Terminate(); - printf("End...\n"); - return 0; - } -} - -void foo(MyClass c) -{ - char[] s; - - s = c.concat("Hello", "world!"); - writefln(s); - c.free(s); - delete c; -} -------------------------------- - - $(P Let's start with the statically linked version, which is simpler. - It's compiled and linked with the command: - ) - -$(CONSOLE -C:>dmd test mydll.lib -g -) - - $(P Note how it is linked with $(TT mydll.lib), the import library - for $(TT mydll.dll). - The code is straightforward, it initializes $(TT mydll.lib) with - a call to $(B MyDLL_Initialize)(), passing the handle - to $(TT test.exe)'s gc. - Then, we can use the DLL and call its functions just as if - it were part of $(TT test.exe). In $(B foo)(), gc memory - is allocated and freed both by $(TT test.exe) and $(TT mydll.dll). - When we're done using the DLL, it is terminated with - $(B MyDLL_Terminate)(). - ) - - $(P Running it looks like this:) - -$(CONSOLE -C:>test -DLL_PROCESS_ATTACH -Start Static Link... -MyDLL_Initialize() -static this for mydll -Hello world! -MyDLL_Terminate() -static ~this for mydll -End... -C:> -) - - $(P The dynamically linked version is a little harder to set up. - Compile and link it with the command: - ) - -$(CONSOLE -C:>dmd test -version=DYNAMIC_LOAD -g -) - $(P The import library $(TT mydll.lib) is not needed. - The DLL is loaded with a call to - $(B Runtime.loadLibrary)(), - and each exported function has to be retrieved via - a call to - $(B GetProcAddress)(). - An easy way to get the decorated name to pass to $(B GetProcAddress)() - is to copy and paste it from the generated $(TT mydll.map) file - under the $(B Export) heading. - Once this is done, we can use the member functions of the - DLL classes as if they were part of $(TT test.exe). - When done, release the DLL with - $(B Runtime.unloadLibrary)(). - ) - - $(P Running it looks like this:) - -$(CONSOLE -C:>test -Start Dynamic Link... -DLL_PROCESS_ATTACH -static this for mydll -Hello world! -static ~this for mydll -DLL_PROCESS_DETACH -End... -C:> -) - -) - -Macros: - TITLE=Writing Win32 DLLs - WIKI=DLLs - CATEGORY_HOWTOS=$0 diff --git a/dmd.dd b/dmd.dd new file mode 100644 index 0000000000..90ecf0e6c3 --- /dev/null +++ b/dmd.dd @@ -0,0 +1,12 @@ +Ddoc + +$(D_S dmd - DMD Compiler, + +$(P Documentation for DMD is split up by operating system. Choose one from +the menu on the left.) + +) + +Macros: + TITLE=DMD Compiler + SUBNAV=$(SUBNAV_CLI_REFERENCE) diff --git a/doc.ddoc b/doc.ddoc index 6fca7c0cd0..2f2d9ff9fa 100644 --- a/doc.ddoc +++ b/doc.ddoc @@ -1,465 +1,23 @@ -DDOC= - - +ROOT_DIR = +ROOT = . +SELF_PATH = +BODYCLASS = doc +PROJECT = dlang.org +_= - +D_S = $(LAYOUT ,$1,$(ARGS $+)) +SPEC_S = $(LAYOUT ,$1,$(ARGS $+)) +COMMUNITY= $(LAYOUT ,$1,$(ARGS $+)) +_= - - - - -$(TITLE) - D Programming Language - - - +LAYOUT=$3 +_= - +SFINAE=$(GLOSSARY2 sfinae, $(ACRONYM SFINAE, Substitution Failure Is Not An Error)) +_= - - - - - - - - -
    - - -
    - -$(BODY) -$(FOOTER) - - - -PAGE_TOOLS= - - -GOOGLE_TRANSLATE= -
    Translate this page: -
    - -
    - -GOOGLE_FOOTER= - - -GOOGLE_REFERRAL= -

    -

    - - -GOOGLE_REFERRAL= - -COPYRIGHT= -Copyright © 1999-$(YEAR) by Digital Mars ®, All Rights Reserved - -FOOTER= - - - -NAVIGATION_COMMUNITY= - - $(BOOKS) - $(TRANSLATIONS) - $(GOOGLE_REFERRAL) - -NAVIGATION= -$(NAVBLOCK_HEADER $(TOCHEADERL index.html, D Programming Language, D Home), - $(TOCENTRYTH overview.html, D language overview, Overview, $(CATEGORY_OVERVIEW $(SUBNAV_OVERVIEW))) - $(TOCENTRYTH comparison.html, D feature list, Features, $(CATEGORY_FEATURES $(SUBNAV_FEATURES))) - $(TOCENTRYTH download.html, Download a D compiler, Downloads & Tools, $(CATEGORY_DOWNLOAD $(SUBNAV_DOWNLOAD))) - $(TOCENTRYT changelog.html, History of changes to D, Changelog) - $(TOCENTRYT bugstats.php, D issue and bug tracking system, Bug tracker) - $(TOCENTRYTH faq.html, Frequently Asked Questions, FAQ, $(CATEGORY_FAQ $(SUBNAV_FAQ))) - $(TOCENTRYH appendices.html, Appendices, $(CATEGORY_APPENDICES $(SUBNAV_APPENDICES))) - $(TOCENTRYT acknowledgements.html, Thank-you to these people who have helped with D, Acknowledgments) - $(TOCENTRYT sitemap.html, Documents on this site$(COMMA) indexed alphabetically, Sitemap) - $(TOCENTRYT http://digitalmars.com/d/1.0/index.html, D Programming Language 1.0, D1 Home) -) -$(NAVBLOCK_HEADER $(TOCHEADER Documentation), - $(LI $(AMAZONLINK 0321635361, Book)) - $(TOCENTRY http://www.informit.com/articles/article.aspx?p=1381876,  31. Tutorial) - $(TOCENTRY http://www.informit.com/articles/article.aspx?p=1609144,  13. Concurrency) - - $(TOCENTRYH language-reference.html, Language Reference, $(CATEGORY_SPEC $(SUBNAV_SPEC))) - $(TOCENTRY phobos/index.html, Library Reference) - $(TOCENTRYTH howtos.html, Helps for using D, Howtos, $(CATEGORY_HOWTOS $(SUBNAV_HOWTOS))) - $(TOCENTRYH articles.html, Articles, $(CATEGORY_ARTICLES $(SUBNAV_ARTICLES))) -) -$(NAVBLOCK_HEADER $(TOCHEADER Community), - $(TOCENTRYT http://digitalmars.com/NewsGroup.html, User forums, Forums) - $(TOCENTRYT http://github.com/D-Programming-Language, D on github, Github) - $(TOCENTRYT http://prowiki.org/wiki4d/wiki.cgi?FrontPage, Wiki for the D Programming Language, Wiki) - $(TOCENTRYT http://prowiki.org/wiki4d/wiki.cgi?ReviewQueue, Queue of current and upcoming standard library additions, Review queue) - $(TOCENTRYT http://twitter.com/#search?q=%23d_lang, #d_lang on twitter.com, Twitter) - $(TOCENTRYT http://digitalmars.com/d/dlinks.html, External D related links, Links) - $(TOCENTRYX http://d.puremagic.com/conference2008/, D Programming Language Conference, Conference) -) - -SUBNAV_OVERVIEW= -$(NAVBLOCK - $(TOCENTRYT wc.html, wc - the wordcount program, Example: wc) - $(TOCENTRYT warnings.html, Explanation of D compiler generated warning messages, Warnings) - $(TOCENTRY builtin.html, Rationale for Builtins) - $(TOCENTRY ctod.html, Converting C to D) - $(TOCENTRY cpptod.html, Converting C++ to D) - $(TOCENTRY pretod.html, The C Preprocessor vs D) - $(REDO $(TOCENTRY template-comparison.html, D templates compared)) - $(REDO $(TOCENTRY cppstrings.html, D strings vs C++ std::string)) - $(REDO $(TOCENTRY cppdbc.html, D Contract Programming vs C++)) - $(REDO $(TOCENTRY cpp0x.html, D and C++0x)) -) - -SUBNAV_FEATURES= -$(NAVBLOCK - $(TOCENTRYT features2.html, Language changes for D, Features) -) - -SUBNAV_DOWNLOAD= -$(NAVBLOCK - $(TOCENTRYT dmd-linux.html, dmd - the Digital Mars D compiler, Linux notes) - $(TOCENTRYT dmd-windows.html, dmd - the Digital Mars D compiler, Windows notes) - $(TOCENTRYT dmd-osx.html, dmd - the Digital Mars D compiler, Mac OSX notes) - $(TOCENTRYT dmd-freebsd.html, dmd - the Digital Mars D compiler, FreeBSD notes) - $(TOCENTRYT http://bitbucket.org/goshawk/gdc/wiki/Home, gdc - the Gnu D compiler, GDC D Compiler) - $(TOCENTRYT http://dnet.codeplex.com/, D Compiler for .NET, D.NET Compiler) - $(TOCENTRYT http://digitalmars.com/ctg/optlink.html, Optlink - the Digital Mars Linker, Linker) - $(TOCENTRYT http://digitalmars.com/ctg/trace.html, DMD's builtin code profiling tool, Profiler) - $(TOCENTRYT code_coverage.html, DMD's builtin code coverage analysis tool, Code Coverage) - $(TOCENTRYT rdmd.html, rdmd - run D programs as if they were scripts, DMD Script Shell) - $(TOCENTRYT windbg.html, windbg - debugging Windows programs, Windows Debugger) - $(TOCENTRYT htod.html, htod - mechanically convert C .h header files to D, C .h to D .d) - $(TOCENTRYT http://www.prowiki.org/wiki4d/wiki.cgi?EditorSupport, Editors with support for D, Editors) - $(TOCENTRYT http://www.prowiki.org/wiki4d/wiki.cgi?ReferenceForTools, Even more tools for D, More Tools) -) - -SUBNAV_FAQ= -$(NAVBLOCK - $(TOCENTRYT const-faq.html, Frequently Asked Questions about const, const(FAQ)) - $(TOCENTRYT rationale.html, Answers to questions about D design decisions, Rationale) -) - -SUBNAV_APPENDICES= -$(NAVBLOCK - $(TOCENTRYT dstyle.html, Recommended programming style conventions, Style Guide) - $(TOCENTRYT glossary.html, D acronyms and jargon explained, Glossary) - $(TOCENTRYT ascii-table.html, Handy ascii chart, Ascii Table) -) - -SUBNAV_SPEC= -$(NAVBLOCK - $(TOCENTRY lex.html, Lexical) - $(TOCENTRY module.html, Modules) - $(TOCENTRY declaration.html, Declarations) - $(TOCENTRY type.html, Types) - $(TOCENTRY property.html, Properties) - $(TOCENTRY attribute.html, Attributes) - $(TOCENTRY pragma.html, Pragmas) - $(TOCENTRY expression.html, Expressions) - $(TOCENTRY statement.html, Statements) - $(TOCENTRY arrays.html, Arrays) - $(TOCENTRY hash-map.html, Associative Arrays) - $(TOCENTRY struct.html, Structs & Unions) - $(TOCENTRY class.html, Classes) - $(TOCENTRY interface.html, Interfaces) - $(TOCENTRY enum.html, Enums) - $(TOCENTRY const3.html, Const and Immutable) - $(TOCENTRY function.html, Functions) - $(TOCENTRY operatoroverloading.html, Operator Overloading) - $(TOCENTRY template.html, Templates) - $(TOCENTRY template-mixin.html, Template Mixins) - $(TOCENTRY dbc.html, Contracts) - $(TOCENTRY version.html, Conditional Compilation) - $(TOCENTRY simd.html, Vector Extensions) - $(TOCENTRY traits.html, Traits) - $(TOCENTRY errors.html, Handling errors) - $(TOCENTRY unittest.html, Unit Tests) - $(TOCENTRY garbage.html, Garbage Collection) - $(TOCENTRY float.html, Floating Point) - $(TOCENTRY iasm.html, Inline Assembler) - $(TOCENTRY ddoc.html, Documentation Comments) - $(TOCENTRY interfaceToC.html, Interfacing To C) - $(TOCENTRY cpp_interface.html, Interfacing To C++) - $(TOCENTRY portability.html, Portability Guide) - $(TOCENTRY entity.html, Named Character Entities) - $(TOCENTRY memory-safe-d.html, Memory Safe D Spec) - $(TOCENTRY abi.html, Application Binary Interface) - ) - -SUBNAV_HOWTOS= -$(NAVBLOCK - $(TOCENTRYT windows.html, D implementation for 32 bit Windows systems, D for Win32) - $(TOCENTRYT dll.html, Writing 32 bit Windows DLLs in D, Win32 DLLs in D) - $(TOCENTRYT COM.html, Windows COM Programming, COM Programming) - $(TOCENTRYT 32-64-portability.html, Porting 32 Bit Code to 64 Bits, Porting to 64 Bits) - $(TOCENTRYT htomodule.html, converting C .h header files to D modules, C .h to D Modules) - $(TOCENTRYT http://digitalmars.com/techtips/index.html, Programming tips, Tech Tips) -) - -SUBNAV_ARTICLES= -$(NAVBLOCK - $(TOCENTRYT const3.html, Const and Immutable, Const) - $(TOCENTRYT d-floating-point.html, D Floating Point, Floating Point) - $(TOCENTRYT exception-safe.html, Exception safe programming techniques, Exception Safety) - $(TOCENTRYT hijack.html, Function Hijacking Mitigation, Hijacking) - $(TOCENTRYT intro-to-datetime.html, Introduction to std.datetime, Introduction to std.datetime) - $(TOCENTRYT lazy-evaluation.html, Lazy evaluation of function arguments, Lazy Evaluation) - $(TOCENTRYT memory.html, Memory management techniques in D, Memory Management) - $(TOCENTRYT migrate-to-shared.html, Migrating to Shared, Migrating to Shared) - $(TOCENTRYT mixin.html, String mixins compile string literals into D programs, Mixins) - $(TOCENTRYT regular-expression.html, Programming with regular expressions, Regular Expressions) - $(TOCENTRYT safed.html, SafeD - The Safe Subset of D, SafeD) - $(TOCENTRYT templates-revisited.html, D takes a fresh look at template design, Templates Revisited) - $(TOCENTRYT tuple.html, What tuples are and how to use them, Tuples) - $(TOCENTRYT variadic-function-templates.html, Variadic arguments to templates, Variadic Templates) - ) - -D_S = $(LAYOUT $(NAVIGATION),$1,$(ARGS $+)) -SPEC_S = $(LAYOUT $(NAVIGATION),$1,$(ARGS $+)) -COMMUNITY= $(LAYOUT $(NAVIGATION),$1,$(ARGS $+)) -PDF_COVER= $0 - -LAYOUT= - -
    - $(PAGE_TOOLS) -

    $(TITLE)

    - $3 - $(GOOGLE_FOOTER) -
    - - -NAVBLOCK= - -NAVBLOCK_HEADER= - - -TOCHEADER =

    $0

    -TOCHEADERL =

    $3

    -TOCENTRY = $(LI $(LINK2 $1, $2)) -TOCENTRYT = $(LI $3) -TOCENTRYH = $(LI $(LINK2 $1, $2)$3) -TOCENTRYTH = $(LI $3$4) - -ARGS=$0 -RPAREN = ) -LPAREN = ( -TABLE1 = $0
    -TABLE2 =
    $+
    $1
    -TH=$0 -BLOCKQUOTE =

    $+

    $1
    -BLOCKQUOTE_PLAIN =

    $0

    -TT=$0 -SUB=$0 -LNAME2=$+ -SECTION1=

    $1

    $+ -SECTION2=

    $1

    $+ -SECTION3=

    $1

    $+ -SECTION4=

    $1

    $+ -SINGLEQUOTE= ‘$0’ -DOUBLEQUOTE= “$0” - -NOTRANSLATE=$0 -NOTRANSLATE=$0 -D_CODE =
    $(NOTRANSLATE $0)
    -D_COMMENT = $0 -D_STRING = $0 -D_KEYWORD = $0 -D_PSYMBOL = $0 -D_PARAM = $0 - -D = $(NOTRANSLATE $0) -CODE=$(D $0) -CCODE=
    $(NOTRANSLATE $0)
    -CPPCODE=
    $(NOTRANSLATE $0)
    -GRAMMAR=
    $(NOTRANSLATE $0)
    -DDOCCODE=
    $(NOTRANSLATE $0)
    -SCINI=
    $(NOTRANSLATE $0)
    -CONSOLE=
    $(NOTRANSLATE $0)
    -MODDEFFILE=
    $(NOTRANSLATE $0)
    - -MDASH= —  - -NEWS=http://digitalmars.com/drn-bin/wwwnews?$1/$+ -NEWS=http://digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=$1&artnum=$+ -NEWS=http://digitalmars.com/webnews/newsgroups.php?search_txt=&group=$1&article_id=$+ - -NEWSGROUP=http://digitalmars.com/webnews/newsgroups.php?search_txt=&group=$0 - -NG_cpp = c++/$0 -NG_cpp_beta = c++.beta/$0 -NG_cpp_command_line = c++.command-line/$0 -NG_D = D/$0 -NG_D_gnu = D.gnu/$0 -NG_digitalmars_D = D/$0 -NG_digitalmars_D_bugs = D.bugs/$0 -NG_digitalmars_D_learn = D.learn/$0 -NG_digitalmars_D_announce = D.announce/$0 -NG_DMDScript = DMDScript/$0 - -OPT=opt -GLINK=$(LINK2 #$0, $(I $0)) -GLINK2=$(LINK2 $1.html#$2, $(I $2)) -GNAME=$(LNAME2 $0, $(I $0)) -DDLINK=$(LINK2 $1.html, $3) -DDSUBLINK=$(LINK2 $1.html#$2, $3) -DPLLINK=$(LINK2 $1, $2) -NOT_EBOOK=$0 -ASSIGNEXPRESSION=$(GLINK2 expression, AssignExpression) -ISEXPRESSION=$(GLINK2 expression, IsExpression) -META_KEYWORDS=D programming language -META_DESCRIPTION=D Programming Language -ACRONYM=$1 ($+) -SFINAE=$(LINK2 glossary.html#sfinae, $(ACRONYM SFINAE, Substitution Failure Is Not An Error)) -COMMA=, -VER=2.0 -V1= -V2=$0 -DIGG= -SLASHDOT= -HOMEIMG=digitalmars.com -SEARCHIMG=Search -DOWNLOADIMG=Download -WIKIIMG=D Wiki -DIMG=D Programming Language -NEWSIMG=User Forums -OBJ2ASM=$(LINK2 http://digitalmars.com/ctg/obj2asm.html, obj2asm) -DUMPOBJ=$(LINK2 http://digitalmars.com/ctg/dumpobj.html, dumpobj) -SHELL=$(LINK2 http://digitalmars.com/ctg/shell.html, shell) -PHOBOSSRC=$(LINK2 https://github.com/D-Programming-Language/phobos/blob/master/$0, $0) -DRUNTIMESRC=$(LINK2 https://github.com/D-Programming-Language/druntime/blob/master/src/$0, $0) -SAMPLESRC=$(LINK2 https://github.com/D-Programming-Language/dmd/blob/master/samples/$0, /dmd/samples/d/$0) -DOLLAR=$ - -AMAZON= -AMAZONLINK= $(LINK2 http://www.amazon.com/exec/obidos/ASIN/$1/classicempire, $+) - -FOO=FOO +AMAZONLINK= $(HTTP amazon.com/exec/obidos/ASIN/$1/classicempire, $+) +_= +MIDRULE= +_= diff --git a/documentation.dd b/documentation.dd new file mode 100644 index 0000000000..0664ea3e9d --- /dev/null +++ b/documentation.dd @@ -0,0 +1,6 @@ +Ddoc + +$(D_S Documentation, $(NAVIGATION_DOCUMENTATION)) + +Macros: + TITLE=Documentation diff --git a/download.dd b/download.dd index c3f7b2f412..b930aac220 100644 --- a/download.dd +++ b/download.dd @@ -2,324 +2,325 @@ Ddoc $(D_S Downloads, -$(TABLE2 DMD - Digital Mars D Programming Language version 2, - - $(TR - $(TH Download) - $(TH Version) - $(TH CPU) - $(TH Operating System) - $(TH Product) - ) - - $(TR - $(TD $(DOWNLOADIMG) dmd.$(DMDV2).zip) - $(TD $(DMDV2)) - $(TD --) - $(TDL $(WIN32) $(LINUX) $(OSX) $(FREEBSD)) - $(TD dmd D 2.0 compiler, all platforms) - ) - - $(TR - $(TD $(DOWNLOADIMG) dmd Windows installer) - $(TD $(DMDV2)) - $(TD i386) - $(TD $(WIN32)) - $(TD dmd D 2.0 compiler 1-click install for Windows) - ) - - $(TR - $(TD $(DOWNLOADIMG) dmd OSX installer (dmg)) - $(TD $(DMDV2)) - $(TD x86_64) - $(TD $(OSX)) - $(TD dmd D 2.0 compiler .dmg installer for OSX) - ) - - $(TR - $(TD $(DOWNLOADIMG) $(UBUNTU32_2)) - $(TD $(DEBV2)) - $(TD i386) - $(TD $(UBUNTU)) - $(TD dmd D 2.0 compiler 1-click install for Ubuntu) - ) - - $(TR - $(TD $(DOWNLOADIMG) $(UBUNTU64_2)) - $(TD $(DEBV2)) - $(TD x86_64) - $(TD $(UBUNTU)) - $(TD dmd D 2.0 compiler 1-click install for Ubuntu) - ) - - $(TR - $(TD $(DOWNLOADIMG) $(FEDORA32_2)) - $(TD $(RPMV2)) - $(TD i386) - $(TD $(FEDORA)) - $(TD dmd D 2.0 compiler 1-click install as rpm) - ) - - $(TR - $(TD $(DOWNLOADIMG) $(FEDORA64_2)) - $(TD $(RPMV2)) - $(TD x86_64) - $(TD $(FEDORA)) - $(TD dmd D 2.0 compiler 1-click install as rpm) - ) - - $(TR - $(TD $(DOWNLOADIMG) $(OPENSUSE32_2)) - $(TD $(RPMV2)) - $(TD i386) - $(TD $(OPENSUSE)) - $(TD dmd D 2.0 compiler 1-click install as rpm) - ) - - $(TR - $(TD $(DOWNLOADIMG) $(OPENSUSE64_2)) - $(TD $(RPMV2)) - $(TD x86_64) - $(TD $(OPENSUSE)) - $(TD dmd D 2.0 compiler 1-click install as rpm) - ) - - $(TR - $(TD $(LINK2 changelog.html, 2.0 changelog)) - $(TD all) - $(TD  ) - $(TD  ) - $(TD other dmd 2.0 versions) - ) -) -$(BR) -$(BR) - -$(TABLE2 DMD - Digital Mars D Programming Language version 1 (please note: D1 will be discontinued effective December 31, 2012), - $(TR - $(TH Download) - $(TH Version) - $(TH CPU) - $(TH Operating System(s)) - $(TH Product) - ) - - $(TR - $(TD $(DOWNLOADIMG) dmd.$(DMDV1).zip) - $(TD $(DMDV1)) - $(TD --) - $(TDL $(WIN32) $(LINUX) $(OSX) $(FREEBSD)) - $(TD dmd D 1.0 compiler, all platforms) - ) - - $(TR - $(TD $(DOWNLOADIMG) dmd Windows installer) - $(TD $(DMDV1)) - $(TD i386) - $(TD $(WIN32)) - $(TD dmd D 1.0 compiler 1-click install for Windows) - ) - - $(TR - $(TD $(DOWNLOADIMG) dmd OSX installer (dmg)) - $(TD $(DMDV1)) - $(TD x86_64) - $(TD $(OSX)) - $(TD dmd D 1.0 compiler .dmg installer for OSX) - ) - - $(TR - $(TD $(DOWNLOADIMG) $(UBUNTU32_1)) - $(TD $(DEBV1)) - $(TD i386) - $(TD $(UBUNTU)) - $(TD dmd D 1.0 compiler 1-click install for Ubuntu) - ) - - $(TR - $(TD $(DOWNLOADIMG) $(UBUNTU64_1)) - $(TD $(DEBV1)) - $(TD x86_64) - $(TD $(UBUNTU)) - $(TD dmd D 1.0 compiler 1-click install for Ubuntu) - ) - - $(TR - $(TD $(DOWNLOADIMG) $(FEDORA32_1)) - $(TD $(RPMV1)) - $(TD i386) - $(TD $(FEDORA)) - $(TD dmd D 1.0 compiler 1-click install as rpm) - ) - - $(TR - $(TD $(DOWNLOADIMG) $(FEDORA64_1)) - $(TD $(RPMV1)) - $(TD x86_64) - $(TD $(FEDORA)) - $(TD dmd D 1.0 compiler 1-click install as rpm) - ) - - $(TR - $(TD $(DOWNLOADIMG) $(OPENSUSE32_1)) - $(TD $(RPMV1)) - $(TD i386) - $(TD $(OPENSUSE)) - $(TD dmd D 1.0 compiler 1-click install as rpm) - ) - - $(TR - $(TD $(DOWNLOADIMG) $(OPENSUSE64_1)) - $(TD $(RPMV1)) - $(TD x86_64) - $(TD $(OPENSUSE)) - $(TD dmd D 1.0 compiler 1-click install as rpm) - ) - - $(TR - $(TD $(DOWNLOADIMG) dmd.1.030.zip) - $(TD 1.030) - $(TD i386) - $(TD $(WIN32) $(LINUX)) - $(TD dmd D 1.0 compiler) - ) - - $(TRCOMMENT - $(TD $(DOWNLOADIMG) dmd 1.030 bundle) - $(TD 1.030) - $(TD i386) - $(TD $(WIN32)) - $(TD dmd D 1.0 compiler bundled with various libraries) - ) - - $(TR - $(TD $(LINK2 http://digitalmars.com/d/1.0/changelog.html, 1.0 changelog)) - $(TD all) - $(TD  ) - $(TD  ) - $(TD other dmd 1.0 versions) - ) +$(DIVC download-tables, + +$(TABLEC download-compilers, + $(T caption, + $(DIVID download-choose, ($(LINK2 https://wiki.dlang.org/Compilers, more information))) + $(H2 Choose a compiler) + ) + $(TR + $(TD $(LINK2 #dmd, $(IMG compiler-dmd.png))) + $(TD $(LINK2 https://gdcproject.org/downloads, $(IMG compiler-gdc.svg))) + $(TD $(LINK2 https://github.com/ldc-developers/ldc#installation, $(IMG compiler-ldc.png))) + ) + $(TR + $(TD + $(H3 DMD) + $(UL + $(LI Official reference compiler) + $(LI Latest D version) + $(LI Simple installation) + $(LI Very fast compilation speeds) + $(LI Architectures: i386, amd64) + ) + ) + $(TD + $(H3 GDC) + $(UL + $(LI $(LINK2 https://gcc.gnu.org/, GCC)-based D compiler) + $(LI Strong optimization) + $(LI Great $(LINK2 https://www.gnu.org/software/gdb/,GDB) support) + $(LI Architectures: i386, amd64, x32, armel, armhf, $(LINK2 https://wiki.dlang.org/Compilers#Comparison,others)) + ) + ) + $(TD + $(H3 LDC) + $(UL + $(LI $(LINK2 https://llvm.org/, LLVM)-based D compiler) + $(LI Strong optimization) + $(LI + $(LINK2 https://wiki.dlang.org/Build_D_for_Android, Android support) + ) + $(LI Architectures: i386, amd64, armel, armhf, $(LINK2 https://wiki.dlang.org/Compilers#Comparison,others)) + ) + ) + ) + $(TR + $(TD + $(DIVC download-link, $(LINK2 dmd-windows.html, About) · $(LINK2 #dmd, Download)) + ) + $(TD + $(DIVC download-link, $(LINK2 https://gdcproject.org/, About) · $(LINK2 https://gdcproject.org/downloads, Download)) + ) + $(TD + $(DIVC download-link, $(LINK2 https://wiki.dlang.org/LDC, About) · $(LINK2 https://github.com/ldc-developers/ldc#installation, Download)) + ) + ) + $(TR + $(DONATE_BUTTON) + ) ) -$(BR) -$(BR) - -$(TABLE2 DMD - Digital Mars C and C++ Compiler, - $(TR - $(TH Download) - $(TH Version) - $(TH CPU) - $(TH Operating System(s)) - $(TH Product) - ) - - $(TR - $(TD $(DOWNLOADIMG) dmc.zip) - $(TD 8.50) - $(TD i386) - $(TD $(WIN32)) - $(TD C++ Compiler and Utilities) - ) +$(TABLEC lsp, + $(TR + $(TD $(LINK2 https://github.com/Pure-D/serve-d/#usage, $(IMG lsp-served-logo.png))) + ) + $(TR + $(TD + $(H3 Language Server) + $(P + To start coding effectively, we recommend using an editor supporting the + Language Server Protocol. For $(B VSCode) you can immediately install the + $(LINK2 https://marketplace.visualstudio.com/items?itemName=webfreak.code-d, VSCode extension $(B code-d)) + $(LINK2 https://open-vsx.org/extension/webfreak/code-d, [openvsx]) + ) + ) + ) + $(TR + $(TD + $(DIVC download-link, $(LINK2 https://github.com/Pure-D/serve-d/#usage, About) · $(LINK2 https://github.com/Pure-D/serve-d/releases, Download)) + ) + ) +) ) -$(BR) -$(BR) - - $(TABLE2 GDC - D Programming Language for GCC, - $(TR - $(TH Download) - $(TH Operating System) - $(TH Product) - ) - - - $(TR - $(TDXX $(LINK2 http://sourceforge.net/project/showfiles.php?group_id=154306, GDC)) - $(TD $(LINK2 http://bitbucket.org/goshawk/gdc/wiki/Home, GDC)) - $(TD all) - $(TD GDC) - ) - - $(TR - $(TD $(LINK2 http://sourceforge.net/projects/gdcmac, gdcmac)) - $(TD $(OSX)) - $(TD GDC) - ) - - $(TR - $(TD $(D sudo apt-get install gdc)) - $(TD $(DEBIAN) $(UBUNTU)) - $(TD GDC) - ) - ) - -$(SECTION2 Documentation Downloads, - - $(UL - $(LI $(LINK2 http://digitalmars.com/d/2.0/dlangspec.mobi, $(DOWNLOADIMG) D Programming Language Specification 2.0) ebook) - $(LI $(LINK2 http://www.prowiki.org/upload/duser/spec_DMD_1.00.pdf, $(DOWNLOADIMG) DMD 1.0 pdf) English) +$(DIVC download_channels, + $(DIVC download_channel, + $(H2 $(LNAME2 dmd,DMD $(DMDV2))) + $(LINK2 changelog/$(DMDV2).html, Changelog) + + $(BR)$(BR) + + $(DOWNLOAD Windows, $(WINDOWS), windows, Windows, + $(SBTN $(WINEXE), Installer) $(SBTN $(ARCH windows, 7z), 7z) + ) + + $(DOWNLOAD macOS, $(OSX), osx, macOS, + $(SBTN $(OSXDMG), dmg) $(SBTN $(ARCH osx, tar.xz), tar.xz) + ) + + $(MESSAGE_BOX orange, $(B Warning) - + MacOS 15.4 introduced an internal change causing D programs to crash on startup ($(LINK2 https://github.com/dlang/dmd/issues/21126, Issue 21126)), including DMD 2.111 itself. + Please use a $(LINK2 https://github.com/dlang/dmd/releases/download/nightly/dmd.master.osx.tar.xz, nightly release) until 2.112 releases. + ) + + $(BR) + + $(DOWNLOAD Ubuntu/Debian, $(UBUNTU)   $(DEBIAN), linux, Linux, + $(SBTN $(DEB32), i386) $(SBTN $(DEB64), x86_64) $(SBTN $(ARCH linux, tar.xz), tar.xz) + ) + + $(DOWNLOAD Fedora/CentOS, $(FEDORA)   $(CENTOS), linux, Linux, + $(SBTN $(RPM32), i386) $(SBTN $(RPM64), x86_64) $(SBTN $(ARCH linux, tar.xz), tar.xz) + ) + + $(DOWNLOAD openSUSE, $(OPENSUSE), linux, Linux, + $(SBTN $(SUSE32), i386) $(SBTN $(SUSE64), x86_64) $(SBTN $(ARCH linux, tar.xz), tar.xz) + ) + + $(DOWNLOAD FreeBSD, $(FREEBSD), freebsd, FreeBSD, + $(SBTN $(ARCH freebsd-64, tar.xz), x86_64) + ) + + $(INSTALL_SCRIPT curl -fsS https://dlang.org/install.sh | bash -s dmd) + ) + + $(BETA + $(DIVC download_channel, + $(H2 $(LNAME2 dmd_beta,DMD Beta $(B_DMDV2)-$(B_SUFFIX))) + $(LINK2 changelog/$(B_DMDV2).html, Changelog) + + $(BR)$(BR) + + $(DOWNLOAD Windows, $(WINDOWS), windows, Windows, + $(SBTN $(B_WINEXE), exe) $(SBTN $(B_ARCH windows, 7z), 7z) + ) + + $(DOWNLOAD macOS, $(OSX), osx, macOS, + $(SBTN $(B_OSXDMG), dmg) $(SBTN $(B_ARCH osx, tar.xz), tar.xz) + ) + + $(DOWNLOAD Ubuntu/Debian, $(UBUNTU)   $(DEBIAN), linux, Linux, + $(SBTN $(B_DEB32), i386) $(SBTN $(B_DEB64), x86_64) $(SBTN $(B_ARCH linux, tar.xz), tar.xz) + ) + + $(DOWNLOAD Fedora/CentOS, $(FEDORA)   $(CENTOS), linux, Linux, + $(SBTN $(B_RPM32), i386) $(SBTN $(B_RPM64), x86_64) $(SBTN $(B_ARCH linux, tar.xz), tar.xz) + ) + + $(DOWNLOAD openSUSE, $(OPENSUSE), linux, Linux, + $(SBTN $(B_SUSE32), i386) $(SBTN $(B_SUSE64), x86_64) $(SBTN $(B_ARCH linux, tar.xz), tar.xz) ) -) -$(SECTION2 Other Downloads, - $(UL - $(LI $(LINK2 http://www.digitalmars.com/download/freecompiler.html, - C and C++ compiler downloads) - ) - - $(LI - - $(DOWNLOADIMG) DMDScript source - ) - - $(LI - - $(DOWNLOADIMG) Empire 2.01 source - ) + $(DOWNLOAD FreeBSD, $(FREEBSD), freebsd, FreeBSD, + $(SBTN $(B_ARCH freebsd-64, tar.xz), x86_64) ) + + $(INSTALL_SCRIPT curl -fsS https://dlang.org/install.sh | bash -s dmd-beta) + ) + ) +) + +$(H3 + $(LINK2 https://downloads.dlang.org, Release Archive) +) +$(LINK2 gpg_keys.html, GPG keys)$(BR) +$(LINK2 https://github.com/dlang/dmd/releases/tag/nightly, Nightly Builds)$(BR) +$(LINK2 https://github.com/dlang, D on GitHub) + +$(HR) + +$(H2 Third-party downloads) + +These links are not maintained by the same people maintaining the official downloads. +$(BR)$(BR) + +$(DOWNLOAD_OTHER $(ARCHLINUX), $(LINK2 https://wiki.archlinux.org/index.php/D_(programming_language), Arch Linux), $(CONSOLE pacman -S dlang)) + +$(DOWNLOAD_OTHER $(GENTOO), $(LINK2 https://wiki.gentoo.org/wiki/Dlang, Gentoo), $(CONSOLE eselect repository enable dlang)) + +$(DOWNLOAD_OTHER $(HOMEBREW), $(LINK2 https://formulae.brew.sh/formula/dmd, Homebrew), $(CONSOLE brew install dmd)) + +$(DOWNLOAD_OTHER $(NIX), $(LINK2 https://search.nixos.org/packages?show=dmd&query=dmd, Nix/NixOS), $(CONSOLE nix-env -iA nixpkgs.dmd) +$(LINK2 https://github.com/petarkirov/dlang.nix, derivations for various compiler versions) ) +$(DOWNLOAD_OTHER $(UBUNTU) $(DEBIAN), Ubuntu/Debian, $(LINK2 https://d-apt.sourceforge.net/, APT repository) +$(CONSOLE sudo wget https://netcologne.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list +sudo apt-get update --allow-insecure-repositories +sudo apt-get -y --allow-unauthenticated install --reinstall d-apt-keyring +sudo apt-get update && sudo apt-get install dmd-compiler dub) +) + +$(DOWNLOAD_OTHER $(DOCKER), $(LINK2 https://hub.docker.com/r/dlang2/dmd-ubuntu, Docker), $(CONSOLE docker run --rm -ti -v $(DOLLAR)(pwd):/src dlang2/dmd-ubuntu dmd)) + +$(DOWNLOAD_OTHER $(OPENSUSE), $(LINK2 https://build.opensuse.org/package/show/devel:languages:D/dmd, OpenSUSE Tumbleweed), $(CONSOLE sudo zypper install dmd)) + +$(DOWNLOAD_OTHER $(SNAP), $(LINK2 https://snapcraft.io/dmd, Snap), + $(CONSOLE # install DMD compiler (including RDMD) +sudo snap install --classic dmd + +\# install DUB package/build manager +sudo snap install --classic dub + +\# install LDC compiler with LLVM backend +sudo snap install --classic ldc2)) + +$(DOWNLOAD_OTHER $(OPENBSD), $(LINK2 https://openports.pl/path/lang/dmd, OpenBSD), $(CONSOLE # install DMD compiler +doas pkg_add dmd + +\# install DUB package/build manager (and DMD if not already installed) +doas pkg_add dub + +\# install D tools +doas pkg_add dtools)) + +$(H2 Other Downloads) + +$(UL +$(LI $(LINK2 https://github.com/dlang/visuald/releases, VisualD - D Plugin for Visual Studio)) + +$(LI $(LINK2 https://dlang.org/spec/spec.html, D Programming Language Specification): $(BTN https://dlang.org/dlangspec.mobi, mobi)) + +$(LI $(LINK2 https://www.digitalmars.com/download/freecompiler.html, Digital Mars C and C++ Compiler Downloads)) +) ) Macros: - TITLE=Downloads - WIKI=Downloads - DMDV1=1.072 - DMDV2=2.057 - DEBV1=1.072 - DEBV2=2.057 - RPMV1=1.072 - RPMV2=2.057 - - OPENSUSE64_1=dmd-1.072-0.openSUSE.x86_64.rpm - OPENSUSE64_2=dmd-2.057-0.openSUSE.x86_64.rpm - OPENSUSE32_1=dmd-1.072-0.openSUSE.i386.rpm - OPENSUSE32_2=dmd-2.057-0.openSUSE.i386.rpm - - FEDORA64_1=dmd-1.072-0.fedora.x86_64.rpm - FEDORA64_2=dmd-2.057-0.fedora.x86_64.rpm - FEDORA32_1=dmd-1.072-0.fedora.i386.rpm - FEDORA32_2=dmd-2.057-0.fedora.i386.rpm - - UBUNTU64_1=dmd_$(DEBV1)-0_amd64.deb - UBUNTU64_2=dmd_$(DEBV2)-0_amd64.deb - UBUNTU32_1=dmd_$(DEBV1)-0_i386.deb - UBUNTU32_2=dmd_$(DEBV2)-0_i386.deb - - LOGO=$2 - UBUNTU=$(LOGO ubuntu, Ubuntu) - FEDORA=$(LOGO fedora, Fedora) - WIN32=$(LOGO win32, Win32) - OPENSUSE=$(LOGO opensuse, OpenSUSE) - LINUX=$(LOGO linux, Linux) - FREEBSD=$(LOGO freebsd, FreeBSD 8.1) - OSX=$(LOGO mac, OSX Lion) - DEBIAN=$(LOGO debian, Debian) - - DLMARS=http://ftp.digitalmars.com/$0 - DLGITHUB=https://github.com/downloads/D-Programming-Language/dmd/$0 - - - TDL=$0 - CATEGORY_DOWNLOAD=$0 + TITLE=Downloads + + DMDV2=$(LATEST) + + BETA=$(COMMENT $0) + _=BETA=$0 + B_DMDV2=2.111.0 + B_SUFFIX=rc.1 + + DEB32=$(DLSITE dmd_$(DMDV2)-0_i386.deb) + DEB64=$(DLSITE dmd_$(DMDV2)-0_amd64.deb) + RPM32=$(DLSITE dmd-$(DMDV2)-0.fedora.i386.rpm) + RPM64=$(DLSITE dmd-$(DMDV2)-0.fedora.x86_64.rpm) + SUSE32=$(DLSITE dmd-$(DMDV2)-0.openSUSE.i386.rpm) + SUSE64=$(DLSITE dmd-$(DMDV2)-0.openSUSE.x86_64.rpm) + OSXDMG=$(DLSITE dmd.$(DMDV2).dmg) + WINEXE=$(DLSITE dmd-$(DMDV2).exe) + ARCH=$(DLSITE dmd.$(DMDV2).$1.$2) + + B_DEB32=$(B_DLSITE dmd_$(B_DMDV2)~$(B_SUFFIX)-0_i386.deb) + B_DEB64=$(B_DLSITE dmd_$(B_DMDV2)~$(B_SUFFIX)-0_amd64.deb) + B_RPM32=$(B_DLSITE dmd-$(B_DMDV2)~$(B_SUFFIX)-0.fedora.i386.rpm) + B_RPM64=$(B_DLSITE dmd-$(B_DMDV2)~$(B_SUFFIX)-0.fedora.x86_64.rpm) + B_SUSE32=$(B_DLSITE dmd-$(B_DMDV2)~$(B_SUFFIX)-0.openSUSE.i386.rpm) + B_SUSE64=$(B_DLSITE dmd-$(B_DMDV2)~$(B_SUFFIX)-0.openSUSE.x86_64.rpm) + B_OSXDMG=$(B_DLSITE dmd.$(B_DMDV2)-$(B_SUFFIX).dmg) + B_WINEXE=$(B_DLSITE dmd-$(B_DMDV2)-$(B_SUFFIX).exe) + B_ARCH=$(B_DLSITE dmd.$(B_DMDV2)-$(B_SUFFIX).$1.$2) + + LOGO=$2 + CENTOS=$(LOGO centos, CentOS) + DEBIAN=$(LOGO debian, Debian) + DOCKER=$(LOGO docker, Docker) + FEDORA=$(LOGO fedora, Fedora) + FREEBSD=$(LOGO freebsd, FreeBSD 8.1) + LINUX=$(LOGO linux, Linux) + OPENSUSE=$(LOGO opensuse, OpenSUSE) + OSX=$(LOGO apple, OSX Lion) + UBUNTU=$(LOGO ubuntu, Ubuntu) + ARCHLINUX=$(LOGO archlinux, Arch Linux) + GENTOO=$(LOGO gentoo, Gentoo) + HOMEBREW=$(LOGO homebrew, Homebrew) + NIX=$(LOGO nix, Nix/NixOS) + SNAP=$(LOGO snapcraft, Snap) + WINDOWS=$(LOGO windows, Windows) + OPENBSD=$(LOGO openbsd, OpenBSD) + + LINK_OS=$2 + + SBTN=$(SPANC sig_btn,$(BTN $1,$+)
    $(BTN $1.sig,sig)) + BTN=$+ + H3I=

    $0

    + DLSITE=https://downloads.dlang.org/releases/2.x/$(DMDV2)/$0 + B_DLSITE=https://downloads.dlang.org/pre-releases/2.x/$(B_DMDV2)/$0 + DOWNLOAD = + $(DIV, + $(DIVC download_image, $2) + $(DIVC download_paragraph, +

    $1

    + + $(LINK_OS $3, , $4) + +
    + $5 +
    + ) + ) + EXTRA_HEADERS=$(T style, + .download_paragraph > span { + margin-left: 0.4em; + font-size: 125%; + } + .download_paragraph a > i.fa { + color: #999; + } + ) + DOWNLOAD_OTHER = + $(DIV, + $(DIVC download_image, $1) + $(DIVC download_paragraph, $(H3 $2) $3) + ) + INSTALL_SCRIPT=$(DIVC download_paragraph, +

    Install Script

    + + $(LINK2 $(ROOT_DIR)install.html, ) + + $(PRE $(CODE $1))) + CONSOLE=$(PRE $(CODE $1)) + IMG= + DONATE_BUTTON = + $(DIV style="border-radius:5px 5px 5px 5px;font-weight:normal; border:1px solid #000000;box-shadow:none;left: 50%; margin-left: -107.5px;display: block;clear: both; width:215px; height:70px; line-height:2.9; position:relative; font-size:24px; text-align:center;", + $(LINK2 https://www.flipcause.com/secure/cause_pdetails/NDMzMzE=, Leave a Tip!)$(BR)$(BR)) + + + _= for sidebard subnavigation diff --git a/dpl-docs/dub.json b/dpl-docs/dub.json new file mode 100644 index 0000000000..6be7a4c892 --- /dev/null +++ b/dpl-docs/dub.json @@ -0,0 +1,13 @@ +{ + "name": "dpl-docs", + "dependencies": { + "ddox": "~>0.16.11", + "vibe-stream:tls": "~>1.1", + "ddoc_preprocessor": { + "path": "../ddoc" + } + }, + "subConfigurations": { + "vibe-stream:tls": "notls" + } +} diff --git a/dpl-docs/dub.selections.json b/dpl-docs/dub.selections.json new file mode 100644 index 0000000000..1d24da44c5 --- /dev/null +++ b/dpl-docs/dub.selections.json @@ -0,0 +1,23 @@ +{ + "fileVersion": 1, + "versions": { + "ddoc_preprocessor": {"path":"../ddoc"}, + "ddox": "0.16.23", + "diet-ng": "1.8.3", + "eventcore": "0.9.35", + "hyphenate": "1.1.4", + "libdparse": "0.15.4", + "mir-linux-kernel": "1.2.1", + "openssl": "3.3.4", + "openssl-static": "1.0.5+3.0.8", + "stdx-allocator": "2.77.5", + "taggedalgebraic": "0.11.23", + "vibe-container": "1.4.2", + "vibe-core": "2.9.6+commit.14.g6c20b78", + "vibe-d": "0.10.2", + "vibe-http": "1.2.1", + "vibe-inet": "1.1.0+commit.2.g8840fee", + "vibe-serialization": "1.0.7", + "vibe-stream": "1.1.1" + } +} diff --git a/dpl-docs/source/app.d b/dpl-docs/source/app.d new file mode 100644 index 0000000000..feb4726652 --- /dev/null +++ b/dpl-docs/source/app.d @@ -0,0 +1,20 @@ +module app; + +import ddox_main; +import std.getopt; +import std.process; +import vibe.core.log; + +bool noExactSourceCodeLinks; + +int main(string[] args) +{ + string git_target = "master"; + getopt(args, std.getopt.config.passThrough, + "git-target", &git_target, + "no-exact-source-links", &noExactSourceCodeLinks); + environment["GIT_TARGET"] = git_target; + environment["NO_EXACT_SOURCE_CODE_LINKS"] = noExactSourceCodeLinks ? "1" : "0"; + setLogFormat(FileLogger.Format.plain); + return ddoxMain(args); +} diff --git a/dpl-docs/source/ddox_main.d b/dpl-docs/source/ddox_main.d new file mode 100644 index 0000000000..a8b2e8655c --- /dev/null +++ b/dpl-docs/source/ddox_main.d @@ -0,0 +1,259 @@ +// Copied from https://github.com/rejectedsoftware/ddox/blob/master/source/ddox/main.d +module ddox_main; + +import ddox.ddoc; +import ddox.ddox; +import ddox.entities; +import ddox.htmlgenerator; +import ddox.htmlserver; +import ddox.parsers.dparse; +import ddox.parsers.jsonparser; + +import vibe.core.core; +import vibe.core.file; +import vibe.data.json; +import vibe.inet.url; +import vibe.http.fileserver; +import vibe.http.router; +import vibe.http.server; +import vibe.stream.operations; +import std.array; +import std.exception : enforce; +import std.file; +import std.getopt; +import std.stdio; +import std.string; + + +int ddoxMain(string[] args) +{ + bool help; + getopt(args, config.passThrough, "h|help", &help); + + if( args.length < 2 || help ){ + showUsage(args); + return help ? 0 : 1; + } + + if( args[1] == "generate-html" && args.length >= 4 ) + return cmdGenerateHtml(args); + if( args[1] == "serve-html" && args.length >= 3 ) + return cmdServeHtml(args); + if( args[1] == "filter" && args.length >= 3 ) + return cmdFilterDocs(args); + if( args[1] == "serve-test" && args.length >= 3 ) + return cmdServeTest(args); + showUsage(args); + return 1; +} + +static import ddox.main; + +alias cmdGenerateHtml = ddox.main.cmdGenerateHtml; +alias cmdServeHtml = ddox.main.cmdServeHtml; +alias cmdServeTest = ddox.main.cmdServeTest; +alias parseDocFile = ddox.main.parseDocFile; +alias setupGeneratorInput = ddox.main.setupGeneratorInput; +alias showUsage = ddox.main.showUsage; + +int cmdFilterDocs(string[] args) +{ + string[] excluded, included; + Protection minprot = Protection.Private; + bool keeputests = false; + bool keepinternals = false; + bool unittestexamples = true; + bool nounittestexamples = false; + bool justdoc = false; + getopt(args, + //config.passThrough, + "ex", &excluded, + "in", &included, + "min-protection", &minprot, + "only-documented", &justdoc, + "keep-unittests", &keeputests, + "keep-internals", &keepinternals, + "unittest-examples", &unittestexamples, // deprecated, kept to not break existing scripts + "no-unittest-examples", &nounittestexamples); + + if (keeputests) keepinternals = true; + if (nounittestexamples) unittestexamples = false; + + string jsonfile; + if( args.length < 3 ){ + showUsage(args); + return 1; + } + + Json filterProt(Json json, Json parent, Json last_decl, Json mod) + { + if (last_decl.type == Json.Type.undefined) last_decl = parent; + + string templateName(Json j){ + auto n = j["name"].opt!string(); + auto idx = n.indexOf('('); + if( idx >= 0 ) return n[0 .. idx]; + return n; + } + + if( json.type == Json.Type.Object ){ + auto comment = json["comment"].opt!string; + if( justdoc && comment.empty ){ + if( parent.type != Json.Type.Object || parent["kind"].opt!string() != "template" || templateName(parent) != json["name"].opt!string() ) + return Json.undefined; + } + + Protection prot = Protection.Public; + if( auto p = "protection" in json ){ + switch(p.get!string){ + default: break; + case "private": prot = Protection.Private; break; + case "package": prot = Protection.Package; break; + case "protected": prot = Protection.Protected; break; + } + } + if( comment.strip == "private" ) prot = Protection.Private; + if( prot < minprot ) return Json.undefined; + + auto name = json["name"].opt!string(); + bool is_internal = name.startsWith("__"); + bool is_unittest = name.startsWith("__unittest"); + if (name.startsWith("_staticCtor") || name.startsWith("_staticDtor")) is_internal = true; + else if (name.startsWith("_sharedStaticCtor") || name.startsWith("_sharedStaticDtor")) is_internal = true; + + if (unittestexamples && is_unittest && !comment.empty) { + assert(last_decl.type == Json.Type.object, "Don't have a last_decl context."); + try { + string source = extractUnittestSourceCode(json, mod); + if (last_decl["comment"].opt!string.empty) { + writefln("Warning: Cannot add documented unit test %s to %s, which is not documented.", name, last_decl["name"].opt!string); + } else { + import assert_writeln_magic; + auto rewrittenSource = assertWritelnBlock(mod["file"].get!string(), source); + last_decl["comment"] ~= format("Example:\n%s$(DDOX_UNITTEST_HEADER %s)\n---\n%s\n---\n$(DDOX_UNITTEST_FOOTER %s)\n", comment.strip, name, rewrittenSource, name); + } + } catch (Exception e) { + writefln("Failed to add documented unit test %s:%s as example: %s", + mod["file"].get!string(), json["line"].get!long, e.msg); + return Json.undefined; + } + } + + if (!keepinternals && is_internal) return Json.undefined; + + if (!keeputests && is_unittest) return Json.undefined; + + if (auto mem = "members" in json) + json["members"] = filterProt(*mem, json, Json.undefined, mod); + } else if( json.type == Json.Type.Array ){ + auto last_child_decl = Json.undefined; + Json[] newmem; + foreach (m; json) { + auto mf = filterProt(m, parent, last_child_decl, mod); + if (mf.type == Json.Type.undefined) continue; + if (mf.type == Json.Type.object && !mf["name"].opt!string.startsWith("__unittest") && icmp(mf["comment"].opt!string.strip, "ditto") != 0) + last_child_decl = mf; + newmem ~= mf; + } + return Json(newmem); + } + return json; + } + + writefln("Reading doc file..."); + auto text = readText(args[2]); + int line = 1; + writefln("Parsing JSON..."); + auto json = parseJson(text, &line); + + writefln("Filtering modules..."); + Json[] dst; + foreach (m; json) { + if ("name" !in m) { + writefln("No name for module %s - ignoring", m["file"].opt!string); + continue; + } + auto n = m["name"].get!string; + bool include = true; + foreach (ex; excluded) + if (n == ex || n.startsWith(ex ~ ".")) { + include = false; + break; + } + foreach (inc; included) + if (n == inc || n.startsWith(inc ~ ".")) { + include = true; + break; + } + if (include) { + auto doc = filterProt(m, Json.undefined, Json.undefined, m); + if (doc.type != Json.Type.undefined) + dst ~= doc; + } + } + + writefln("Writing filtered docs..."); + auto buf = appender!string(); + writePrettyJsonString(buf, Json(dst)); + std.file.write(args[2], buf.data()); + + return 0; +} + +// from ddox +private string extractUnittestSourceCode(Json decl, Json mod) +{ + auto filename = mod["file"].get!string(); + enforce("line" in decl && "endline" in decl, "Missing line/endline fields."); + auto from = decl["line"].get!long; + auto to = decl["endline"].get!long; + + // read the matching lines out of the file + auto app = appender!string(); + long lc = 1; + foreach (str; File(filename).byLine) { + if (lc >= from) { + app.put(str); + app.put('\n'); + } + if (++lc > to) break; + } + auto ret = app.data; + + // strip the "unittest { .. }" surroundings + auto idx = ret.indexOf("unittest"); + enforce(idx >= 0, format("Missing 'unittest' for unit test at %s:%s.", filename, from)); + ret = ret[idx .. $]; + + idx = ret.indexOf("{"); + enforce(idx >= 0, format("Missing opening '{' for unit test at %s:%s.", filename, from)); + ret = ret[idx+1 .. $]; + + idx = ret.lastIndexOf("}"); + enforce(idx >= 0, format("Missing closing '}' for unit test at %s:%s.", filename, from)); + ret = ret[0 .. idx]; + + // unindent lines according to the indentation of the first line + app = appender!string(); + string indent; + foreach (i, ln; ret.splitLines) { + if (i == 1) { + foreach (j; 0 .. ln.length) + if (ln[j] != ' ' && ln[j] != '\t') { + indent = ln[0 .. j]; + break; + } + } + if (i > 0 || ln.strip.length > 0) { + size_t j = 0; + while (j < indent.length && !ln.empty) { + if (ln.front != indent[j]) break; + ln.popFront(); + j++; + } + app.put(ln); + app.put('\n'); + } + } + return app.data; +} diff --git a/dpl-docs/urlrewrite.d b/dpl-docs/urlrewrite.d new file mode 100644 index 0000000000..a8b8351a37 --- /dev/null +++ b/dpl-docs/urlrewrite.d @@ -0,0 +1,82 @@ +#!/usr/bin/rdmd --shebang +/* + Rewrites old DDOX based Phobos documentation URLs to the new file name style. + + Previously, the symbol names have been directly translated to the + file name: boyerMooreFinder -> boyedMooreFinder.html + To avoid name clashes on case insensitive file systems, the new scheme + is to use lower case letters and underscores: boyer_moore_finder.html + Similar symbols are then aggregated on the same page (e.g. + BoyerMooreFinder). + + Full example: + OLD: https://dlang.org/library/std/algorithm/BoyerMooreFinder.html + NEW: https://dlang.org/library/std/algorithm/boyer_moore_finder.html + + This script expects the URLs to be passed on STDIN line-by-line without the + server/schema part: + /library/std/algorithm/BoyerMooreFinder.html + /library/std/algorithm/find.html + ... +*/ + +import std.algorithm; +import std.array; +import std.stdio; +import std.string; +import std.utf; + +enum s_urlPrefix = "/library/"; +enum s_urlSuffix = ".html"; + +void main() +{ + foreach (url; stdin.byLine) { + if (!url.startsWith(s_urlPrefix) || !url.endsWith(s_urlSuffix)) { + writeln(url); + continue; + } + + // extract just the file name portion + auto last_slash = url.lastIndexOf('/'); + auto name = url[last_slash+1 .. $-s_urlSuffix.length]; + auto adjname = name.splitter('.').map!adjustStyle.join("."); + + // write back the URL with adjusted file name style + writefln("%s%s%s", url[0 .. last_slash+1], adjname, s_urlSuffix); + } +} + + +string adjustStyle(const(char)[] name) +{ + auto ret = appender!string; + size_t start = 0, i = 0; + while (i < name.length) { + // skip acronyms + while (i < name.length && (i+1 >= name.length || (name[i+1] >= 'A' && name[i+1] <= 'Z'))) { + std.utf.decode(name, i); + } + + // skip the main (lowercase) part of a word + while (i < name.length && !(name[i] >= 'A' && name[i] <= 'Z')) { + std.utf.decode(name, i); + } + + // add a single word + if( ret.data.length > 0 ) { + ret ~= "_"; + } + ret ~= name[start .. i]; + + // quick skip the capital and remember the start of the next word + start = i; + if (i < name.length) { + std.utf.decode(name, i); + } + } + if (i < name.length) { + ret ~= "_" ~ name[start .. $]; + } + return std.string.toLower(ret.data); +} diff --git a/dpl-docs/views/ddox.inc.module-tree.dt b/dpl-docs/views/ddox.inc.module-tree.dt new file mode 100644 index 0000000000..846814cce4 --- /dev/null +++ b/dpl-docs/views/ddox.inc.module-tree.dt @@ -0,0 +1,26 @@ +- import ddox.entities; + +- void moduleNavTree(Package pack, Module pack_mod) + - string pack_class = "expand-container"; + - foreach(i, p; pack.packages) + - auto subpackmod = getPackageModule(p); + - bool is_active = p.isAncestorOf(info.node) || subpackmod && subpackmod.isAncestorOf(info.node) || subpackmod is info.node; + li(class=is_active ? pack_class ~ " open" : pack_class) + a.package(href="#", class="expand-toggle") + span= p !is info.rootPackage ? p.name : null + ul.tree-view + - moduleNavTree(p, subpackmod); + + - if (pack_mod) + li + a.module(href="#{info.linkTo(pack_mod)}", class='#{info.node is pack_mod || pack_mod.isAncestorOf(info.node) ? "selected" : ""}') + span Package members + + - foreach(m; pack.modules) + - if (pack.lookup!Package(m.name, false)) + - continue; + li + a.module(href="#{info.linkTo(m)}", class='#{info.node is m || m.isAncestorOf(info.node) ? "selected" : ""}') + span= m.name + +- moduleNavTree(info.rootPackage, null); diff --git a/dpl-docs/views/ddox.layout.dt b/dpl-docs/views/ddox.layout.dt new file mode 100644 index 0000000000..cfc6e2c25e --- /dev/null +++ b/dpl-docs/views/ddox.layout.dt @@ -0,0 +1,28 @@ +extends layout + +block title + block ddox.defs + block ddox.title + +block navigation + include ddox.inc.utils + include ddox.inc.module-tree + +block body + block ddox.description + + block ddox.sections + + block ddox.members + + - if( cast(Module)info.node ) + section + h2 Authors + block ddox.authors + + section + h2 License + block ddox.license + +block copyright + block ddox.copyright diff --git a/dpl-docs/views/ddox.overview.dt b/dpl-docs/views/ddox.overview.dt new file mode 100644 index 0000000000..38f363f60e --- /dev/null +++ b/dpl-docs/views/ddox.overview.dt @@ -0,0 +1,88 @@ +extends ddox.layout + +block ddox.defs + - import ddox.api; + +block ddox.title + - title = "API documentation"; + +block ddox.members + - import std.conv : to; + + - void moduleInfoRec(Package pack) + - foreach( p; pack.packages ) + - moduleInfoRec(p); + - foreach( m; pack.modules ) + - if (!m.qualifiedName.startsWith("std.c.") && !m.qualifiedName.startsWith("core.stdc.") && !m.qualifiedName.startsWith("core.sys.")) + tr + td + a(href="#{info.linkTo(m)}") + code!= m.qualifiedName.to!string.replace(".", ".") + td + - if( m.docGroup ) + |!= info.formatDoc(m.docGroup, 0, sec => sec == "$Short") + + - void moduleInfoRecShort(Package pack, string prefix) + - foreach( p; pack.packages ) + - moduleInfoRecShort(p, prefix); + - foreach( m; pack.modules ) + - if (m.qualifiedName.startsWith(prefix)) + a(href="#{info.linkTo(m)}") + code!= m.qualifiedName.to!string.replace(".", ".") + + table + col.caption + tr + th Module + th Description + - moduleInfoRec(info.rootPackage); + + br + p Access to plattform libraries is supported by specific D header files. + + table + col.caption + tr + th + th D header files + tr + td C99 + td + - moduleInfoRecShort(info.rootPackage, "core.stdc."); + tr + td Posix + td + - moduleInfoRecShort(info.rootPackage, "core.sys.posix."); + tr + td Windows + td + - moduleInfoRecShort(info.rootPackage, "core.sys.windows."); + tr + td GNU/Linux + td + - moduleInfoRecShort(info.rootPackage, "core.sys.linux."); + tr + td FreeBSD + td + - moduleInfoRecShort(info.rootPackage, "core.sys.freebsd."); + tr + td OSX + td + - moduleInfoRecShort(info.rootPackage, "core.sys.osx."); + tr + td Solaris + td + - moduleInfoRecShort(info.rootPackage, "core.sys.solaris."); + + br + p Deprecated D header files. + + table + col.caption + tr + th + th D header files + tr + td C + td + - moduleInfoRecShort(info.rootPackage, "std.c."); diff --git a/dpl-docs/views/layout.dt b/dpl-docs/views/layout.dt new file mode 100644 index 0000000000..ffcd5ca010 --- /dev/null +++ b/dpl-docs/views/layout.dt @@ -0,0 +1,245 @@ +!!! 5 +html(lang='en-US') + - import std.datetime : Clock; + - auto year = Clock.currTime.year; + // + | Copyright (c) 1999-$#{year} by the D Language Foundation + | All Rights Reserved. + | https://dlang.org/foundation_overview.html + - import std.process : environment; + - import std.array : replace; + - import std.string : startsWith, endsWith; + - static import std.string; + - string version_id = environment["GIT_TARGET"]; + - bool noExactSourceCodeLinks = environment["NO_EXACT_SOURCE_CODE_LINKS"] == "1"; + - bool haveVersion = version_id.startsWith("v"); + - string version_name = haveVersion ? version_id[1 .. $] : "Prerelease"; + - string root_dir = info.linkTo(null) ~ (req is null ? "../" : ""); + - string ddox_dir = haveVersion ? "library/" : "library-prerelease/"; + + head + meta(charset='utf-8') + - string title; + meta(name='keywords', content='D programming language') + meta(name='description', content='D Programming Language') + block title + title #{title} - D Programming Language + link(rel='stylesheet', href='#{root_dir}css/codemirror.css') + link(rel='stylesheet', href='#{root_dir}css/style.css') + link(rel='stylesheet', href='#{root_dir}css/print.css', media='print') + link(rel='stylesheet', href='#{root_dir}css/ddox.css') + link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css') + link(rel='shortcut icon', href='#{root_dir}favicon.ico') + script(src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', type='text/javascript') + meta(name='viewport', content='width=device-width, initial-scale=1.0, minimum-scale=0.1, maximum-scale=10.0') + + body.std(id='#{info.node.moduleName}') + script(type='text/javascript'). + document.body.className += ' have-javascript'; + #top + .helper + .helper.expand-container + a.logo(href='#{root_dir}') + img#logo(width='125', height='95', alt='D Logo', src='#{root_dir}images/dlogo.svg') + a.hamburger.expand-toggle(href="#{root_dir}menu.html", title="Menu") + span Menu + #cssmenu + ul + li + a(href="https://tour.dlang.org/") + span Learn + li.expand-container + a.expand-toggle(href="#{root_dir}documentation.html") + span Documentation + ul + li + a(href="#{root_dir}spec/spec.html") Language Reference + li + a(href="#{root_dir}phobos/index.html") Library Reference + li + a(href="#{root_dir}dmd.html") Command-line Reference + li.menu-divider + a(href="#{root_dir}comparison.html") Feature Overview + li + a(href="#{root_dir}articles.html") Articles + li + a(href="#{root_dir}download.html") + span Downloads + li + a(href="https://code.dlang.org/") + span Packages + li.expand-container + a.expand-toggle(href="#{root_dir}community.html") + span Community + ul + li + a(href="https://dlang.org/blog") Blog + li + a(href="#{root_dir}orgs-using-d.html") Orgs using D + li + a(href="https://twitter.com/search?q=%23dlang") Twitter + li + a(href="#{root_dir}calendar.html") Calendar + li.menu-divider + a(href="https://forum.dlang.org/") Forums + li + a(href="/service/irc://irc.libera.chat/d") IRC + li + a(href="https://wiki.dlang.org/") Wiki + li.menu-divider + a(href="https://github.com/dlang") GitHub + li + a(href="#{root_dir}bugstats.html") Issues + li + a(href="https://wiki.dlang.org/Get_involved") Get Involved + li.menu-divider + a(href="#{root_dir}foundation") Foundation + li + a(href="#{root_dir}security.html") Security Team + li + a(href="#{root_dir}foundation/donate.html") Donate + li + a(href="#{root_dir}foundation/sponsors.html") Sponsors + li.expand-container + a.expand-toggle(href="#{root_dir}resources.html") + span Resources + ul + li + a(href="https://wiki.dlang.org/Books") Books + li + a(href="https://wiki.dlang.org/Tutorials") Tutorials + li.menu-divider + a(href="https://wiki.dlang.org/Development_tools") Tools + li + a(href="https://wiki.dlang.org/Editors") Editors + li + a(href="https://wiki.dlang.org/IDEs") IDEs + li + a(href="http://rainers.github.io/visuald/visuald/StartPage.html") Visual D + li.menu-divider + a(href="#{root_dir}acknowledgements.html") Acknowledgments + li + a(href="#{root_dir}dstyle.html") D Style + li + a(href="#{root_dir}spec/glossary.html") Glossary + li + a(href="#{root_dir}sitemap.html") Sitemap + .search-container.expand-container + a.expand-toggle(href="#{root_dir}search.html", title="Search") + span Search + #search-box + form(method='get', action='https://duckduckgo.com/', autocomplete='off') + input#domains(type='hidden', name='domains', value='dlang.org') + | + input#sourceid(type='hidden', name='sourceid', value='google-search') + | + span#search-query + input#q(name='q', placeholder='Search') + input#symbolSearch(style="display: none", type="text", name="symbolSearch", placeholder="API Search", onchange="performSymbolSearch(80);", onkeypress="this.onchange();", onpaste="this.onchange();", oninput="this.onchange();", autofocus) + span#search-dropdown + .helper + select#sitesearch(name='sitesearch', size='1') + option(value='dlang.org') Entire D Site + | + option(selected='', value='dlang.org/spec') Language + | + option(selected='', value='dlang.org/library') Library + | + option(value='forum.dlang.org') Forums + span#search-submit + button(type='submit') + i.fa.fa-search + span go + include ddox.inc.symbol-search.results + + .container + .subnav-helper + .subnav + h2 API Documentation + p + span.smallprint + - if( haveVersion ) + | version #{version_name} + p + a(href="#{root_dir}#{ddox_dir}index.html") overview + ul + block navigation + #content.hyphenate + #tools + div + - import ddox.entities : Declaration; + - auto modname = info.node.moduleName; + - string project = "dlang.org"; + - string path_prefix, line_suffix, filename; + - if( modname ) + - if( modname.startsWith("core.") || modname.startsWith("object")) + - project = "dmd", path_prefix = "druntime/src/"; + - else if( modname.startsWith("dmd.") ) + - project = "dmd", path_prefix = "compiler/src/"; + - else + - project = "phobos", path_prefix = ""; + - if (info.docGroups.length >= 1 && !noExactSourceCodeLinks) + - if (auto decl = cast(Declaration)info.docGroups[0].members[0]) line_suffix = "#L"~to!string(decl.line); + - if (info.node.module_.isPackageModule) + - filename = replace(modname, ".", "/") ~ "/package.d"; + - else + - filename = replace(modname, ".", "/") ~ ".d"; + + - if( modname ) + .tip.smallprint + a(href='https://github.com/dlang/#{project}/blob/#{version_id}/#{path_prefix}#{filename}#{line_suffix}') + | View source code + div + | Display the source code in #{filename} from which this + | page was generated on github. + + .tip.smallprint + - auto pagename = modname ? path_prefix ~ replace(modname, ".", "/") : "index"; + a(href="https://issues.dlang.org/enter_bug.cgi?bug_file_loc=http%3A%2F%2Fdlang.org/#{ddox_dir}#{pagename}.html&bug_severity=enhancement&component=#{project}&op_sys=All&priority=P3&product=D&rep_platform=All&short_desc=%5B#{title}%5D&version=D2") Report a bug + div + | If you spot a problem with this page, click here to create a + | Bugzilla issue. + + - if( modname ) + .tip.smallprint + a(href='https://github.com/dlang/#{project}/edit/master/#{path_prefix}#{filename}#{line_suffix}') + | Improve this page + div + | Quickly fork, edit online, and submit a pull request for this page. + | Requires a signed-in GitHub account. This works well for small changes. + | If you'd like to make larger changes you may want to consider using + | local clone. + + - auto hidx = std.string.lastIndexOf(title, ' '); + - auto node = info.docGroups.length ? info.docGroups[0].members[0] : null; + - if (title.endsWith(" - multiple declarations") && node) + h1 #{info.mod.qualifiedName}.#{title[0 .. $-24]} #{title[$-24 ..$]} + - else if (hidx > 0 && !title.startsWith("Module ") && node) + h1 #{title[0 .. hidx]} #{node.parent.qualifiedName}.#{node.name} + - else if (hidx > 0 && title.startsWith("Module ") && info.mod) + h1 Module #{info.mod.qualifiedName} + - else + h1= title + block body + + | + #quickindex.quickindex + + #copyright.smallprint + | Copyright © 1999-#{year} by the D Language Foundation | Page generated by ddox. + + script(type='text/javascript', src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js') + | + script(type='text/javascript'). + window.jQuery || document.write('\x3Cscript src="#{root_dir}js/jquery-1.7.2.min.js">\x3C/script>') + | + script(type='text/javascript', src='#{root_dir}js/codemirror-compressed.js') + | + script(type='text/javascript', src='#{root_dir}js/run.js') + script(type='text/javascript', src='#{root_dir}js/run_examples.js') + script(type='text/javascript', src='#{root_dir}js/dlang.js') + script(type='text/javascript', src='#{root_dir}js/listanchors.js') + script(type="text/javascript", src="#{root_dir}js/ddox.js") + script(type='text/javascript'). + jQuery(document).ready(listanchors); + setupDdox(); diff --git a/dpl_latest_htaccess b/dpl_latest_htaccess new file mode 100644 index 0000000000..520eff7938 --- /dev/null +++ b/dpl_latest_htaccess @@ -0,0 +1,7 @@ +# Enable mod_rewrite +RewriteEngine On +RewriteBase /library/ + +# rewrite any URL in dpl_rewrite_map +RewriteCond ${dpl_rewrite_map:%{REQUEST_URI}|NOT_FOUND} !NOT_FOUND +RewriteRule ^ ${dpl_rewrite_map:%{REQUEST_URI}} [R=301,L] diff --git a/dpl_prerelease_htaccess b/dpl_prerelease_htaccess new file mode 100644 index 0000000000..b531566451 --- /dev/null +++ b/dpl_prerelease_htaccess @@ -0,0 +1,7 @@ +# Enable mod_rewrite +RewriteEngine On +RewriteBase /library-prerelease/ + +# rewrite any URL in dpl_rewrite_map +RewriteCond ${dpl_rewrite_map:%{REQUEST_URI}|NOT_FOUND} !NOT_FOUND +RewriteRule ^ ${dpl_rewrite_map:%{REQUEST_URI}} [R=301,L] diff --git a/dstyle.dd b/dstyle.dd index d5fedb284a..0527eaac4b 100644 --- a/dstyle.dd +++ b/dstyle.dd @@ -2,230 +2,509 @@ Ddoc $(D_S The D Style, +D Style + $(P - $(I The D Style) is a set of style conventions for writing - D programs. The D Style is not enforced by the compiler, it is - purely cosmetic and a matter of choice. Adhering to the D Style, - however, will make it easier for others to work with your - code and easier for you to work with others' code. - The D Style can form the starting point for a project - style guide customized for your project team. + $(I The D Style) is a set of style conventions for writing + D programs. The D Style is not enforced by the compiler. It is + purely cosmetic and a matter of choice. Adhering to the D Style, + however, will make it easier for others to work with your + code and easier for you to work with others' code. + The D Style can form the starting point for a project + style guide customized for your project team. ) $(P - Submissions to Phobos and other official D source code will - follow these guidelines. + Submissions to Phobos and other official D source code will + follow these guidelines. ) -

    White Space

    +$(H3 $(LNAME2 whitespace, Whitespace)) $(UL - $(LI One statement per line.) + $(LI One statement per line.) - $(LI Use spaces instead of hardware tabs.) + $(LI Use spaces instead of hardware tabs.) - $(LI Each indentation level will be four columns.) + $(LI Each indentation level will be four columns.) +) - $(LI Operators are separated by single spaces from their operands.) +$(H3 $(LNAME2 naming_conventions, Naming Conventions)) - $(LI Two blank lines separating function bodies.) +$(DL + $(DT $(LNAME2 naming_general, General)) + $(DD Unless listed otherwise below, names should be camelCased (this + includes $(I all) variables). So, names formed by joining multiple + words have each word other than the first word capitalized. Also, names + do not begin with an underscore $(SINGLEQUOTE _) unless they are + private. - $(LI One blank line separating variable declarations from statements - in function bodies.) -) +------------------------------- +int myFunc(); +string myLocalVar; +------------------------------- + ) -

    Comments

    + $(DT $(LNAME2 naming_modules, Modules)) + $(DD Module and package names should be all lowercase, and only contain + the characters [a..z][0..9][_]. This avoids problems when dealing with + case-insensitive file systems. +------------------------------- +import std.algorithm; +------------------------------- + ) + + + + $(DT $(LNAME2 naming_classes, Classes, Interfaces, Structs, Unions, Enums, Non-Eponymous Templates)) + $(DD The names of user-defined types should be PascalCased, which is the + same as camelCased except that the first letter is uppercase. -$(UL - $(LI Use // comments to document a single line: ------------------------------- -statement; // comment -statement; // comment +class Foo; +struct FooAndBar; ------------------------------- - ) + ) + + $(DT $(LNAME2 naming_eponymous_templates, Eponymous Templates)) + + $(DD Templates which have the same name as a symbol within that template + (and instantiations of that template are therefore replaced with that + symbol) should be capitalized in the same way that the inner symbol + would be capitalized if it weren't in a template - e.g. types should + be PascalCased and values should be camelCased. + +------------------------- +template GetSomeType(T) { alias GetSomeType = T; } +template isSomeType(T) { enum isSomeType = is(T == SomeType); } +template MyType(T) { struct MyType { ... } } +template map(fun...) { auto map(Range r) { ... } } +------------------------- + ) + + $(DT $(LNAME2 naming_functions, Functions)) + $(DD Function names should be camelCased, so their first letter is lowercase. + This includes properties and member functions. - $(LI Use block comments to document a multiple line block of - statements: ------------------------------- -/* comment - * comment - */ - statement; - statement; +int done(); +int doneProcessing(); ------------------------------- - ) + ) + + $(DT $(LNAME2 naming_constants, Constants)) + $(DD The names of constants should be camelCased just like normal variables. - $(LI Use $(CODE version (none)) to $(SINGLEQUOTE comment out) a piece of trial code - that is syntactically valid: ------------------------------- - version (none) - { - /* comment - * comment - */ - statement; - statement; - } +enum secondsPerMinute = 60; +immutable hexDigits = "0123456789ABCDEF"; ------------------------------- + ) - It can be turned on with $(CODE version(all)): + $(DT $(LNAME2 naming_enum_members, Enum members)) + $(DD The members of enums should be camelCased, so their first letter is + lowercase. ------------------------------- - version (all) - { - /* comment - * comment - */ - statement; - statement; - } +enum Direction { bwd, fwd, both } +enum OpenRight { no, yes } ------------------------------- + ) - ) + $(DT $(LNAME2 naming_keywords, Keywords)) + $(DD If a name would conflict with a keyword, and it is desirable to use the + keyword rather than pick a different name, a single underscore + $(SINGLEQUOTE _) should be appended to it. Names should not be + capitalized differently in order to avoid conflicting with keywords. - $(LI Use nesting comments to $(SINGLEQUOTE comment out) a piece of syntactically invalid code: ------------------------------- -/+++++ - /* comment - * comment - */ - { statement; - statement; - +++++/ +enum Attribute { nothrow_, pure_, safe } ------------------------------- - ) -) + ) -

    Naming Conventions

    + $(DT $(LNAME2 naming_acronyms, Acronyms)) + $(DD When acronyms are used in symbol names, all letters in the acronym + should have the same case. So, if the first letter in the acronym + is lowercase, then all of the letters in the acronym are lowercase, and + if the first letter in the acronym is uppercase, then all of the + letters in the acronym are uppercase. -$(DL - $(DT General) -
    Names formed by joining multiple words should have each word - other than the first capitalized. - Names shall not begin with an underscore $(SINGLEQUOTE _) unless they are private member variables. +------------------------------- +class UTFException; +ubyte asciiChar; +------------------------------- + ) + + $(DT $(LNAME2 naming_udas, User-Defined Attributes)) + $(DD For symbols that are only to be used as user-defined attributes the + names should be camelCased, so their first letter is lowercase. This + convention takes precedence over any previously mentioned conventions. + This matches conventions of the built in attributes like `@safe`, + `@nogc` and the special compiler recognized UDA `@selector`. ------------------------------- -int myFunc(); +struct Foo {} // this struct follows the regular naming conventions + +// this struct is only intended to be used as an UDA and therefore overrides the +// regular naming conventions for structs +struct name { string value; } +@name("bar") Foo foo; ------------------------------- + ) +) + +$(H3 $(LNAME2 type_aliases, Type Aliases)) - $(DT Module) - $(DD Module and package names are all lower case, and only contain - the characters [a..z][0..9][_]. This avoids problems dealing - with case insensitive file systems.) + $(P The D programming languages offers two functionally equivalent syntaxes for type aliases, but ...) - $(DT C Modules) - $(DD Modules that are interfaces to C functions go into the "c" - package, for example: ------------------------------- -import std.c.stdio; +alias size_t = uint; ------------------------------- - Module names should be all lower case. - ) - $(DT Class, Struct, Union, Enum, Template names) - $(DD are capitalized. + $(P ... is preferred over ...) ------------------------------- -class Foo; -class FooAndBar; +alias uint size_t; ------------------------------- - ) - $(DD An exception is that eponymous templates that return a value instead of a type should not be - capitalized, as they are conceptually more similar to functions. -------------------------- -template GetSomeType(T) {} -template isSomeType(T) {} -------------------------- - ) + $(P ... because ...) - $(DT Function names) - $(DD Function names are not capitalized. + $(UL + $(LI It follows the already familiar assignment syntax instead of the inverted typedef syntax from C) + $(LI In verbose declarations, it is easier to see what is being declared) + ) ------------------------------- -int done(); -int doneProcessing(); +alias important = someTemplateDetail!(withParameters, andValues); +alias Callback = ReturnType function(Arg1, Arg2) pure nothrow; ------------------------------- - ) -$(V1 - $(DT Const names) - $(DD Are in all caps.) -) - $(DT Enum member names) - $(DD Are in lowerCamelCase.) - -) + $(P vs.) -

    Meaningless Type Aliases

    +------------------------------- +alias someTemplateDetail!(withParameters, andValues) important; +alias ReturnType function(Arg1, Arg2) pure nothrow Callback; +------------------------------- - $(P Things like:) + $(P Meaningless type aliases like ...) ------------------------------- -alias void VOID; -alias int INT; -alias int* pint; +alias VOID = void; +alias INT = int; +alias pint = int*; ------------------------------- - $(P should be avoided.) + $(P ... should be avoided.) -

    Declaration Style

    +$(H3 $(LNAME2 declaration_style, Declaration Style)) - $(P Since the declarations are left-associative, left justify them:) + $(P Since the declarations are left-associative, left justify them:) ------------------------------- -int[] x, y; // makes it clear that x and y are the same type -int** p, q; // makes it clear that p and q are the same type +int[] x, y; // makes it clear that x and y are the same type +int** p, q; // makes it clear that p and q are the same type ------------------------------- - $(P to emphasize their relationship. Do not use the C style:) + $(P to emphasize their relationship. Do not use the C style:) ------------------------------- -int []x, y; // confusing since y is also an int[] -int **p, q; // confusing since q is also an int** +int []x, y; // confusing since y is also an int[] +int **p, q; // confusing since q is also an int** ------------------------------- -

    Operator Overloading

    +$(H3 $(LNAME2 operator_overloading, Operator Overloading)) + + $(P Operator overloading is a powerful tool to extend the basic + types supported by the language. But being powerful, it has + great potential for creating obfuscated code. In particular, + the existing D operators have conventional meanings, such + as $(SINGLEQUOTE +) means $(SINGLEQUOTE add) and $(SINGLEQUOTE <<) + means $(SINGLEQUOTE shift left). + Overloading operator $(SINGLEQUOTE +) with a meaning different from $(SINGLEQUOTE add) + is arbitrarily confusing and should be avoided. + ) + +$(H3 $(LNAME2 hungarian_notation, Hungarian Notation)) + + $(P Using Hungarian notation to denote the type of a variable + is a bad idea. + However, using notation to denote the purpose of a variable + (that cannot be expressed by its type) is often a good + practice.) + +$(H3 $(LNAME2 properties, Properties)) + + $(P Functions should be property functions whenever appropriate. In + particular, getters and setters should generally be avoided in favor of + property functions. And in general, whereas functions should be verbs, + properties should be nouns, just like if they were member variables. + Getter properties should $(I not) alter state.) + +$(H3 $(LNAME2 property-syntax, Property syntax)) + +$(P Do not use $(LINK2 spec/function.html#pseudo-member, UFCS) or +$(LINK2 spec/function.html#optional-parenthesis, Optional Parentheses) outside of their intended use cases. +Omitting parentheses is useful in generic code that does not care whether a member is a field or +a function, for example the range primitive `front`. +It can also make a chain of range functions more compact. +However, when a simple call is made to a function with side effects, prefer 'regular' function call syntax. +) - $(P Operator overloading is a powerful tool to extend the basic - types supported by the language. But being powerful, it has - great potential for creating obfuscated code. In particular, - the existing D operators have conventional meanings, such - as $(SINGLEQUOTE +) means $(SINGLEQUOTE add) and $(SINGLEQUOTE <<) - means $(SINGLEQUOTE shift left). - Overloading operator $(SINGLEQUOTE +) with a meaning different from $(SINGLEQUOTE add) - is arbitrarily confusing and should be avoided. - ) +------------------------------- +import std.range, std.stdio; +void main() +{ + // good + writeln(); + writeln("hello"); + iota(0, 10).dropOne.array.front.writeln; + + // bad + writeln; + "hello".writeln; + writeln = "hello"; +} +------------------------------- -

    Hungarian Notation

    +$(H3 $(LNAME2 documentation, Documentation)) - $(P Using hungarian notation to denote the type of a variable - is a bad idea. - However, using notation to denote the purpose of a variable - (that cannot be expressed by its type) is often a good - practice.) +$(P + All public declarations will be documented in + $(LINK2 spec/ddoc.html, Ddoc) format and should have at least `Params` and + `Returns` sections. +) -

    Documentation

    +$(H3 $(LNAME2 unittest, Unit Tests)) $(P - All public declarations will be documented in - $(LINK2 ddoc.html, Ddoc) format. + As much as practical, all functions will be exercised + by unit tests using unittest blocks immediately following + the function to be tested. + Every path of code should be executed at least once, + verified by the $(LINK2 code_coverage.html, code coverage analyzer). ) -

    Unit Tests

    +$(H2 $(LNAME2 phobos, Additional Requirements for Phobos)) $(P - As much as practical, all functions will be exercised - by unit tests using unittest blocks immediately following - the function to be tested. - Every path of code should be executed at least once, - verified by the $(LINK2 code_coverage.html, code coverage analyzer). + In general, this guide does not try to recommend or require that code + conform to any particular formatting guidelines. The small section on + whitespace at the top contains its only formatting guidelines. However, for + Phobos and other official D source code, there are additional requirements: + ) + +$(H4 $(LNAME2 phobos_brackets, Brackets)) + $(P Braces should be on their own line. There are a few exceptions to this + (such as when declaring lambda functions), but with any normal function + block or type definition, the braces should be on their own line.) + +------------------------------- +void func(int param) +{ + if (param < 0) + { + ... + } + else + { + ... + } +} +------------------------------- + $(P Avoid unnecessary parentheses:) +------------------------------- +(a == b) ? "foo" : "bar"; // NO +a == b ? "foo" : "bar"; // OK +------------------------------- +$(H4 $(LNAME2 phobos_line_length, Line length)) + $(P Lines have a soft limit of 80 characters and a hard limit of 120 + characters. This means that most lines of code should be no longer than + 80 characters long but that they $(I can) exceed 80 characters when + appropriate. However, they can $(I never) exceed 120 characters.) +$(LISTSECTION phobos_whitespace, Whitespace, + $(LI Put a space after `for`, `foreach`, `if`, `while`, and `version`: ) +------------------------------- +for (…) { … } +foreach (…) { … } +static foreach (…) { … } +if (x) { … } +static if (x) { … } +while (…) { … } +do { … } while (…); +version (…) { … } +------------------------------- + $(LI Chains containing `else if (…)`, `else static if (…)` or `else version (…)` + should set the keywords on the same line:) +------------------------------- +if (…) +{ + … +} +else if (…) +{ + … +} +------------------------------- + $(LI Put a space between binary operators, assignments, `cast`, and lambdas:) +------------------------------- +a + b +a / b +a == b +a && b +arr[1 .. 2] +int a = 100; +b += 1; +short c = cast(short) a; +filter!(a => a == 42); +------------------------------- + $(LI Put no space between unary operators, after `assert`, function calls:) +------------------------------- +a = !a && !(2 == -1); +bool b = ~a; +auto d = &c; +e++; +assert(*d == 42); +callMyFancyFunction("hello world"); +------------------------------- +) +$(LISTSECTION phobos_imports, Imports, + $(LI Local, selective imports should be preferred over global imports) + $(LI Selective imports should have a space before and after the colon (`:`) like + `import std.range : zip`) + $(LI Imports should be sorted lexicographically.) +) +$(LISTSECTION phobos_return_types, Return type, + $(LI The return type should be stated $(I explicitly) wherever possible, + as it makes the documentation and source code easier to read.) + $(LI $(LINK2 https://dlang.org/spec/struct.html#nested, Function-nested) structs + (aka $(LINK2 https://wiki.dlang.org/Voldemort_types, Voldemort types)) + should be preferred over public `struct`s.) +) +$(LISTSECTION phobos_attributes, Attributes, + $(LI $(I Non-templated) functions should be annotated with + matching attributes (`@nogc`, `@safe`, `pure`, `nothrow`).) + $(LI If the template arguments for a $(I templated) function affect whether + an attribute is appropriate, then the function should $(B not) be + annotated with that attribute so that the compiler can infer it. + However, if the attribute is not affected by the template arguments + (and thus would always be inferred), then the function should be + explicitly annotated with that attribute just like a non-templated + function would be.) + $(LI Attributes should be listed in alphabetical ordering, e.g. `const @nogc nothrow pure @safe` + (the ordering should ignore the leading `@`). + ) + $(LI $(B Every) $(I unittest) should be annotated + (e.g. `pure nothrow @nogc @safe unittest { ... }`) + to ensure the existence of attributes on the templated function.) +) +$(LISTSECTION phobos_templates, Templates, + $(LI `unittest` blocks should be avoided in templates. They will generate + a new `unittest` for each instance, hence tests should be put + outside of the template.) +) +$(LISTSECTION phobos_declarations, Declarations, + $(LI Constraints on declarations should have the same indentation level as + their declaration:) +------------------------------- +void foo(R)(R r) +if (R == 1) +------------------------------- + $(LI Pre and post contracts should have the same indentation level as their + declaration. The expression-based syntax should be preferred when the + equivalent long-form syntax would have a single `assert` statement. + Put a space after `in`/`out` similar to `if` constraints:) +------------------------------- +// Prefer: +T transmogrify(T)(T value) +if (isIntegral!T) +in (value % 7 == 0) +out (result; result % 11 == 0) +{ + // ... +} + +// over this: +T transmogrify(T)(T value) +if (isIntegral!T) +in { assert(value % 7 == 0); } +out (result) { assert(result % 11 == 0); } +do +{ + // ... +} +------------------------------- + $(LI Invariants should use the expression-based syntax when the equivalent + long-form syntax would have a single `assert` statement. Put a space + between `invariant` and the opening parentheses:) +------------------------------- +struct S +{ + int x; + invariant (x > 0); +} +------------------------------- +) +$(LISTSECTION phobos_class_struct_field_declaration, Class/Struct Field Declarations, + $(LI In structs and classes, there should only be one space between the type of + the field and its name. This avoids problems with future changes generating a + larger git diff than necessary.) +------------------------------- +class MyClass +{ + // bad + int a; + double b; + + // good + int x; + double y; +} +------------------------------- +) + +$(LISTSECTION phobos_documentation, Documentation, + $(LI Every public symbol should be exposed in the documentation:) +--- +/// A public symbol +enum myFancyConstant; +--- + $(LI Every public function should have a Ddoc description and documented + `Params:` and `Returns:` sections (if applicable):) +--- +/** +Checks whether a number is positive. +`0` isn't considered as positive number. + +Params: + number = number to be checked + +Returns: `true` if the number is positive, `0` otherwise. + +See_Also: $(LREF isNegative) +*/ +bool isPositive(int number) +{ + return number > 0; +} +--- + $(LI Text in sections (e.g. `Params:`, `Returns:`, `See_Also`) should be indented by one level if it spans more than the line of the section.) + $(LI Documentation comments should not use more than two stars `/**` or two pluses `/++` in the header line.) + $(LI Either Block comments (`/**`) or nesting block comments (`/++`) should be used except when the ddoc comment is a ditto comment such as `/// Ditto`) + $(LI Documentation comments should not have leading stars on each line.) + $(LI Text example blocks should use three dashes (`---`) only.) ) +$(BR) +$(P + We are not necessarily recommending that all code follow these rules. + They're likely to be controversial in any discussion on coding standards. + However, they are required in submissions to Phobos and other official D + source code. + ) ) Macros: - TITLE=The D Style - WIKI=DStyle - CATEGORY_APPENDICES=$0 + TITLE=The D Style + LISTSECTION=$(H4 $(LNAME2 $1, $2)) $(UL $(SKIPFIRST $+)) + SKIPFIRST=$+ diff --git a/ebook.css b/ebook.css index 77bd5f455e..b4f2b47bfb 100644 --- a/ebook.css +++ b/ebook.css @@ -8,7 +8,8 @@ body, td, th { font-family: Arial, Verdana, sans-serif; font-size: 10pt; - margin-left: 10pt; + margin-left: 0pt; + margin-right: 0pt; /*font-family: Cambria, Georgia, Times New Roman, serif;*/ /*font-size: 18px;*/ @@ -47,7 +48,7 @@ blockquote margin-right: 0; font-family: "courier new", courier, serif; font-family: "Georgia", courier, serif; - background: #DEDEDE url("https://github.com/quote.gif") no-repeat top right; + background: #DEDEDE url("https://github.com/images/quote.gif") no-repeat top right; margin: 0.5em; padding: 0.5em; padding-left: 1em; @@ -364,11 +365,11 @@ div#navigation a:active div#content { line-height: 1.4em; - margin-left: 15em; - margin-right: 1.5em; + margin-left: 0em; + margin-right: 0.5em; /*border-left: 1px solid black;*/ padding-top: 1em; - padding-left: 1em; + padding-left: 0em; text-align: justify; } @@ -399,20 +400,20 @@ div#copyright /* These are for the changelogs */ -div#version +div.version { border-top: 1px solid black; font-size: 0.9em; padding-top: 2ex; } -div#version li +div.version li { padding-bottom: 0.3ex; } -div#bugsfixed +div.bugsfixed { } -div#whatsnew +div.whatsnew { } @@ -430,8 +431,8 @@ td.compYes { /* comparison with D: "YES" */ text-align:center; } -TABLE.parms -{ +TABLE.parms +{ border-top: 1px solid; border-bottom: 1px solid; border-spacing: 1pt; @@ -444,7 +445,7 @@ TABLE.parms TD } TABLE.book -{ +{ width: 100%; border-top: 2px solid; border-bottom: 2px solid; @@ -470,28 +471,28 @@ TABLE.book CAPTION text-align: left; } -.d_inlinecode -{ +.d_inlinecode +{ font-family: "Bitstream Vera Sans Mono", "Courier New", monospace; font-size: 105%; font-weight: bold; /*color: #000010; */ } -/* Try it Now editable code stuff */ -button.try-now { - border-radius: 8px; - -moz-border-radius: 8px; - -webkit-border-radius: 8px; - -o-border-radius: 8px; - border: solid 1px #333; - margin-left: 0.4em; -} - -iframe.try-now { - display: block; - width: 100%; - background-color: black; -} -/* done with try it now stuff */ +/* Try it Now editable code stuff */ +button.try-now { + border-radius: 8px; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + -o-border-radius: 8px; + border: solid 1px #333; + margin-left: 0.4em; +} + +iframe.try-now { + display: block; + width: 100%; + background-color: black; +} +/* done with try it now stuff */ diff --git a/ebook.ddoc b/ebook.ddoc index bfc5c829b9..07a467ed3c 100644 --- a/ebook.ddoc +++ b/ebook.ddoc @@ -3,15 +3,15 @@ DDOC= - + D Programming Language Specification - + @@ -20,30 +20,26 @@ $(BODY) $(FOOTER) - +$(LF) +_= -GOOGLE_FOOTER= -GOOGLE_REFERRAL= FOOTER= TOP= -NAVIGATION_COMMUNITY= -NAVIGATION_SPEC= -NAVIGATION_D= -BOOKS= +_= -TOCENTRY = $(LI $(LINK2 #$+, $+)) LAYOUT=

     

    $2

    $3
    +_= CODE=$0 -D_CODE =
    $0

    -ASMCODE=
    $0

    +D_CODE =
    $0

    +OTHER_CODE =
    $+

    CCODE=
    $0

    CPPCODE=
    $0

    GRAMMAR=
    $0

    @@ -51,9 +47,37 @@ DDOCCODE=
    $0

    SCINI=
    $0

    CONSOLE=
    $0

    MODDEFFILE=
    $0

    +_= GLINK2=$(GLINK $2) -DDLINK=$(LINK2 #$2, $3) -DDSUBLINK=$(LINK2 #$2, $3) -DPLLINK=$(LINK2 http://www.d-programming-language.org/$1, $2) +GLINK2_ALTTEXT=$(RELATIVE_LINK2 $2, $3) +GLINK_LEX=$(GLINK $1) +DDLINK=$(RELATIVE_LINK2 $2, $3) +DDSUBLINK=$(RELATIVE_LINK2 $2, $3) +DPLLINK=$(LINK2 https://dlang.org/$1, $2) NOT_EBOOK= +RAWHTML=$0 +RUNNABLE_EXAMPLE=$0 +RUNNABLE_EXAMPLE_STDIN= +RUNNABLE_EXAMPLE_ARGS= +RUNNABLE_EXAMPLE_COMPILE=$(RUNNABLE_EXAMPLE $0) +SPEC_RUNNABLE_EXAMPLE=$0 +SPEC_RUNNABLE_EXAMPLE_COMPILE=$0 +SPEC_RUNNABLE_EXAMPLE_RUN=$0 +SPEC_RUNNABLE_EXAMPLE_FAIL=$0 +SPEC_SUBNAV_NEXT= +SPEC_SUBNAV_PREV_NEXT= +SPEC_SUBNAV_PREV= +HEADERNAV_TOC= +HEADERNAV_ITEM= +HEADERNAV_SUBITEMS= +_= + + +_= specification boxes +BEST_PRACTICE= $(P $(B Best Practices:) $0) +IMPLEMENTATION_DEFINED=$(P $(B Implementation Defined:) $0) +UNDEFINED_BEHAVIOR=$(P $(B Undefined Behavior:) $0) +RATIONALE=$(P $(B Rationale:) $0) +NOTE=$(P $(B Note:) $0) +_= diff --git a/entity.dd b/entity.dd deleted file mode 100644 index 40def43869..0000000000 --- a/entity.dd +++ /dev/null @@ -1,291 +0,0 @@ -Ddoc - -$(SPEC_S Named Character Entities, - -$(GRAMMAR -$(GNAME NamedCharacterEntity): - $(B &) $(GLINK2 lex, Identifier) $(B ;) -) - - $(P These are the character entity names supported by D. - ) - - $(P $(B Note:) Not all will display properly in the $(B Symbol) - column in all browsers. - ) - - - - $(TABLE2 Named Character Entities, - $(THEAD Name, Value, Symbol) - - $(TR $(TD quot) $(TD 34) $(TD ")) - $(TR $(TD amp) $(TD 38) $(TD &)) - $(TR $(TD lt) $(TD 60) $(TD <)) - $(TR $(TD gt) $(TD 62) $(TD >)) - - $(TR $(TD OElig) $(TD 338) $(TD Œ)) - $(TR $(TD oelig) $(TD 339) $(TD œ)) - $(TR $(TD Scaron) $(TD 352) $(TD Š)) - $(TR $(TD scaron) $(TD 353) $(TD š)) - $(TR $(TD Yuml) $(TD 376) $(TD Ÿ)) - $(TR $(TD circ) $(TD 710) $(TD ˆ)) - $(TR $(TD tilde) $(TD 732) $(TD ˜)) - $(TR $(TD ensp) $(TD 8194) $(TD  )) - $(TR $(TD emsp) $(TD 8195) $(TD  )) - $(TR $(TD thinsp) $(TD 8201) $(TD  )) - $(TR $(TD zwnj) $(TD 8204) $(TD ‌)) - $(TR $(TD zwj) $(TD 8205) $(TD ‍)) - $(TR $(TD lrm) $(TD 8206) $(TD ‎)) - $(TR $(TD rlm) $(TD 8207) $(TD ‏)) - $(TR $(TD ndash) $(TD 8211) $(TD –)) - $(TR $(TD mdash) $(TD 8212) $(TD —)) - $(TR $(TD lsquo) $(TD 8216) $(TD ‘)) - $(TR $(TD rsquo) $(TD 8217) $(TD ’)) - $(TR $(TD sbquo) $(TD 8218) $(TD ‚)) - $(TR $(TD ldquo) $(TD 8220) $(TD “)) - $(TR $(TD rdquo) $(TD 8221) $(TD ”)) - $(TR $(TD bdquo) $(TD 8222) $(TD „)) - $(TR $(TD dagger) $(TD 8224) $(TD †)) - $(TR $(TD Dagger) $(TD 8225) $(TD ‡)) - $(TR $(TD permil) $(TD 8240) $(TD ‰)) - $(TR $(TD lsaquo) $(TD 8249) $(TD ‹)) - $(TR $(TD rsaquo) $(TD 8250) $(TD ›)) - $(TR $(TD euro) $(TD 8364) $(TD €)) - - $(TR Latin-1 (ISO-8859-1) Entities) - - $(TR $(TD nbsp) $(TD 160) $(TD  )) - $(TR $(TD iexcl) $(TD 161) $(TD ¡)) - $(TR $(TD cent) $(TD 162) $(TD ¢)) - $(TR $(TD pound) $(TD 163) $(TD £)) - $(TR $(TD curren) $(TD 164) $(TD ¤)) - $(TR $(TD yen) $(TD 165) $(TD ¥)) - $(TR $(TD brvbar) $(TD 166) $(TD ¦)) - $(TR $(TD sect) $(TD 167) $(TD §)) - $(TR $(TD uml) $(TD 168) $(TD ¨)) - $(TR $(TD copy) $(TD 169) $(TD ©)) - $(TR $(TD ordf) $(TD 170) $(TD ª)) - $(TR $(TD laquo) $(TD 171) $(TD «)) - $(TR $(TD not) $(TD 172) $(TD ¬)) - $(TR $(TD shy) $(TD 173) $(TD ­)) - $(TR $(TD reg) $(TD 174) $(TD ®)) - $(TR $(TD macr) $(TD 175) $(TD ¯)) - $(TR $(TD deg) $(TD 176) $(TD °)) - $(TR $(TD plusmn) $(TD 177) $(TD ±)) - $(TR $(TD sup2) $(TD 178) $(TD ²)) - $(TR $(TD sup3) $(TD 179) $(TD ³)) - $(TR $(TD acute) $(TD 180) $(TD ´)) - $(TR $(TD micro) $(TD 181) $(TD µ)) - $(TR $(TD para) $(TD 182) $(TD ¶)) - $(TR $(TD middot) $(TD 183) $(TD ·)) - $(TR $(TD cedil) $(TD 184) $(TD ¸)) - $(TR $(TD sup1) $(TD 185) $(TD ¹)) - $(TR $(TD ordm) $(TD 186) $(TD º)) - $(TR $(TD raquo) $(TD 187) $(TD »)) - $(TR $(TD frac14) $(TD 188) $(TD ¼)) - $(TR $(TD frac12) $(TD 189) $(TD ½)) - $(TR $(TD frac34) $(TD 190) $(TD ¾)) - $(TR $(TD iquest) $(TD 191) $(TD ¿)) - $(TR $(TD Agrave) $(TD 192) $(TD À)) - $(TR $(TD Aacute) $(TD 193) $(TD Á)) - $(TR $(TD Acirc) $(TD 194) $(TD Â)) - $(TR $(TD Atilde) $(TD 195) $(TD Ã)) - $(TR $(TD Auml) $(TD 196) $(TD Ä)) - $(TR $(TD Aring) $(TD 197) $(TD Å)) - $(TR $(TD AElig) $(TD 198) $(TD Æ)) - $(TR $(TD Ccedil) $(TD 199) $(TD Ç)) - $(TR $(TD Egrave) $(TD 200) $(TD È)) - $(TR $(TD Eacute) $(TD 201) $(TD É)) - $(TR $(TD Ecirc) $(TD 202) $(TD Ê)) - $(TR $(TD Euml) $(TD 203) $(TD Ë)) - $(TR $(TD Igrave) $(TD 204) $(TD Ì)) - $(TR $(TD Iacute) $(TD 205) $(TD Í)) - $(TR $(TD Icirc) $(TD 206) $(TD Î)) - $(TR $(TD Iuml) $(TD 207) $(TD Ï)) - $(TR $(TD ETH) $(TD 208) $(TD Ð)) - $(TR $(TD Ntilde) $(TD 209) $(TD Ñ)) - $(TR $(TD Ograve) $(TD 210) $(TD Ò)) - $(TR $(TD Oacute) $(TD 211) $(TD Ó)) - $(TR $(TD Ocirc) $(TD 212) $(TD Ô)) - $(TR $(TD Otilde) $(TD 213) $(TD Õ)) - $(TR $(TD Ouml) $(TD 214) $(TD Ö)) - $(TR $(TD times) $(TD 215) $(TD ×)) - $(TR $(TD Oslash) $(TD 216) $(TD Ø)) - $(TR $(TD Ugrave) $(TD 217) $(TD Ù)) - $(TR $(TD Uacute) $(TD 218) $(TD Ú)) - $(TR $(TD Ucirc) $(TD 219) $(TD Û)) - $(TR $(TD Uuml) $(TD 220) $(TD Ü)) - $(TR $(TD Yacute) $(TD 221) $(TD Ý)) - $(TR $(TD THORN) $(TD 222) $(TD Þ)) - $(TR $(TD szlig) $(TD 223) $(TD ß)) - $(TR $(TD agrave) $(TD 224) $(TD à)) - $(TR $(TD aacute) $(TD 225) $(TD á)) - $(TR $(TD acirc) $(TD 226) $(TD â)) - $(TR $(TD atilde) $(TD 227) $(TD ã)) - $(TR $(TD auml) $(TD 228) $(TD ä)) - $(TR $(TD aring) $(TD 229) $(TD å)) - $(TR $(TD aelig) $(TD 230) $(TD æ)) - $(TR $(TD ccedil) $(TD 231) $(TD ç)) - $(TR $(TD egrave) $(TD 232) $(TD è)) - $(TR $(TD eacute) $(TD 233) $(TD é)) - $(TR $(TD ecirc) $(TD 234) $(TD ê)) - $(TR $(TD euml) $(TD 235) $(TD ë)) - $(TR $(TD igrave) $(TD 236) $(TD ì)) - $(TR $(TD iacute) $(TD 237) $(TD í)) - $(TR $(TD icirc) $(TD 238) $(TD î)) - $(TR $(TD iuml) $(TD 239) $(TD ï)) - $(TR $(TD eth) $(TD 240) $(TD ð)) - $(TR $(TD ntilde) $(TD 241) $(TD ñ)) - $(TR $(TD ograve) $(TD 242) $(TD ò)) - $(TR $(TD oacute) $(TD 243) $(TD ó)) - $(TR $(TD ocirc) $(TD 244) $(TD ô)) - $(TR $(TD otilde) $(TD 245) $(TD õ)) - $(TR $(TD ouml) $(TD 246) $(TD ö)) - $(TR $(TD divide) $(TD 247) $(TD ÷)) - $(TR $(TD oslash) $(TD 248) $(TD ø)) - $(TR $(TD ugrave) $(TD 249) $(TD ù)) - $(TR $(TD uacute) $(TD 250) $(TD ú)) - $(TR $(TD ucirc) $(TD 251) $(TD û)) - $(TR $(TD uuml) $(TD 252) $(TD ü)) - $(TR $(TD yacute) $(TD 253) $(TD ý)) - $(TR $(TD thorn) $(TD 254) $(TD þ)) - $(TR $(TD yuml) $(TD 255) $(TD ÿ)) - - $(TR Symbols and Greek letter entities) - - $(TR $(TD fnof) $(TD 402) $(TD ƒ)) - $(TR $(TD Alpha) $(TD 913) $(TD Α)) - $(TR $(TD Beta) $(TD 914) $(TD Β)) - $(TR $(TD Gamma) $(TD 915) $(TD Γ)) - $(TR $(TD Delta) $(TD 916) $(TD Δ)) - $(TR $(TD Epsilon) $(TD 917) $(TD Ε)) - $(TR $(TD Zeta) $(TD 918) $(TD Ζ)) - $(TR $(TD Eta) $(TD 919) $(TD Η)) - $(TR $(TD Theta) $(TD 920) $(TD Θ)) - $(TR $(TD Iota) $(TD 921) $(TD Ι)) - $(TR $(TD Kappa) $(TD 922) $(TD Κ)) - $(TR $(TD Lambda) $(TD 923) $(TD Λ)) - $(TR $(TD Mu) $(TD 924) $(TD Μ)) - $(TR $(TD Nu) $(TD 925) $(TD Ν)) - $(TR $(TD Xi) $(TD 926) $(TD Ξ)) - $(TR $(TD Omicron) $(TD 927) $(TD Ο)) - $(TR $(TD Pi) $(TD 928) $(TD Π)) - $(TR $(TD Rho) $(TD 929) $(TD Ρ)) - $(TR $(TD Sigma) $(TD 931) $(TD Σ)) - $(TR $(TD Tau) $(TD 932) $(TD Τ)) - $(TR $(TD Upsilon) $(TD 933) $(TD Υ)) - $(TR $(TD Phi) $(TD 934) $(TD Φ)) - $(TR $(TD Chi) $(TD 935) $(TD Χ)) - $(TR $(TD Psi) $(TD 936) $(TD Ψ)) - $(TR $(TD Omega) $(TD 937) $(TD Ω)) - $(TR $(TD alpha) $(TD 945) $(TD α)) - $(TR $(TD beta) $(TD 946) $(TD β)) - $(TR $(TD gamma) $(TD 947) $(TD γ)) - $(TR $(TD delta) $(TD 948) $(TD δ)) - $(TR $(TD epsilon) $(TD 949) $(TD ε)) - $(TR $(TD zeta) $(TD 950) $(TD ζ)) - $(TR $(TD eta) $(TD 951) $(TD η)) - $(TR $(TD theta) $(TD 952) $(TD θ)) - $(TR $(TD iota) $(TD 953) $(TD ι)) - $(TR $(TD kappa) $(TD 954) $(TD κ)) - $(TR $(TD lambda) $(TD 955) $(TD λ)) - $(TR $(TD mu) $(TD 956) $(TD μ)) - $(TR $(TD nu) $(TD 957) $(TD ν)) - $(TR $(TD xi) $(TD 958) $(TD ξ)) - $(TR $(TD omicron) $(TD 959) $(TD ο)) - $(TR $(TD pi) $(TD 960) $(TD π)) - $(TR $(TD rho) $(TD 961) $(TD ρ)) - $(TR $(TD sigmaf) $(TD 962) $(TD ς)) - $(TR $(TD sigma) $(TD 963) $(TD σ)) - $(TR $(TD tau) $(TD 964) $(TD τ)) - $(TR $(TD upsilon) $(TD 965) $(TD υ)) - $(TR $(TD phi) $(TD 966) $(TD φ)) - $(TR $(TD chi) $(TD 967) $(TD χ)) - $(TR $(TD psi) $(TD 968) $(TD ψ)) - $(TR $(TD omega) $(TD 969) $(TD ω)) - $(TR $(TD thetasym) $(TD 977) $(TD ϑ)) - $(TR $(TD upsih) $(TD 978) $(TD ϒ)) - $(TR $(TD piv) $(TD 982) $(TD ϖ)) - $(TR $(TD bull) $(TD 8226) $(TD •)) - $(TR $(TD hellip) $(TD 8230) $(TD …)) - $(TR $(TD prime) $(TD 8242) $(TD ′)) - $(TR $(TD Prime) $(TD 8243) $(TD ″)) - $(TR $(TD oline) $(TD 8254) $(TD ‾)) - $(TR $(TD frasl) $(TD 8260) $(TD ⁄)) - $(TR $(TD weierp) $(TD 8472) $(TD ℘)) - $(TR $(TD image) $(TD 8465) $(TD ℑ)) - $(TR $(TD real) $(TD 8476) $(TD ℜ)) - $(TR $(TD trade) $(TD 8482) $(TD ™)) - $(TR $(TD alefsym) $(TD 8501) $(TD ℵ)) - $(TR $(TD larr) $(TD 8592) $(TD ←)) - $(TR $(TD uarr) $(TD 8593) $(TD ↑)) - $(TR $(TD rarr) $(TD 8594) $(TD →)) - $(TR $(TD darr) $(TD 8595) $(TD ↓)) - $(TR $(TD harr) $(TD 8596) $(TD ↔)) - $(TR $(TD crarr) $(TD 8629) $(TD ↵)) - $(TR $(TD lArr) $(TD 8656) $(TD ⇐)) - $(TR $(TD uArr) $(TD 8657) $(TD ⇑)) - $(TR $(TD rArr) $(TD 8658) $(TD ⇒)) - $(TR $(TD dArr) $(TD 8659) $(TD ⇓)) - $(TR $(TD hArr) $(TD 8660) $(TD ⇔)) - $(TR $(TD forall) $(TD 8704) $(TD ∀)) - $(TR $(TD part) $(TD 8706) $(TD ∂)) - $(TR $(TD exist) $(TD 8707) $(TD ∃)) - $(TR $(TD empty) $(TD 8709) $(TD ∅)) - $(TR $(TD nabla) $(TD 8711) $(TD ∇)) - $(TR $(TD isin) $(TD 8712) $(TD ∈)) - $(TR $(TD notin) $(TD 8713) $(TD ∉)) - $(TR $(TD ni) $(TD 8715) $(TD ∋)) - $(TR $(TD prod) $(TD 8719) $(TD ∏)) - $(TR $(TD sum) $(TD 8721) $(TD ∑)) - $(TR $(TD minus) $(TD 8722) $(TD −)) - $(TR $(TD lowast) $(TD 8727) $(TD ∗)) - $(TR $(TD radic) $(TD 8730) $(TD √)) - $(TR $(TD prop) $(TD 8733) $(TD ∝)) - $(TR $(TD infin) $(TD 8734) $(TD ∞)) - $(TR $(TD ang) $(TD 8736) $(TD ∠)) - $(TR $(TD and) $(TD 8743) $(TD ∧)) - $(TR $(TD or) $(TD 8744) $(TD ∨)) - $(TR $(TD cap) $(TD 8745) $(TD ∩)) - $(TR $(TD cup) $(TD 8746) $(TD ∪)) - $(TR $(TD int) $(TD 8747) $(TD ∫)) - $(TR $(TD there4) $(TD 8756) $(TD ∴)) - $(TR $(TD sim) $(TD 8764) $(TD ∼)) - $(TR $(TD cong) $(TD 8773) $(TD ≅)) - $(TR $(TD asymp) $(TD 8776) $(TD ≈)) - $(TR $(TD ne) $(TD 8800) $(TD ≠)) - $(TR $(TD equiv) $(TD 8801) $(TD ≡)) - $(TR $(TD le) $(TD 8804) $(TD ≤)) - $(TR $(TD ge) $(TD 8805) $(TD ≥)) - $(TR $(TD sub) $(TD 8834) $(TD ⊂)) - $(TR $(TD sup) $(TD 8835) $(TD ⊃)) - $(TR $(TD nsub) $(TD 8836) $(TD ⊄)) - $(TR $(TD sube) $(TD 8838) $(TD ⊆)) - $(TR $(TD supe) $(TD 8839) $(TD ⊇)) - $(TR $(TD oplus) $(TD 8853) $(TD ⊕)) - $(TR $(TD otimes) $(TD 8855) $(TD ⊗)) - $(TR $(TD perp) $(TD 8869) $(TD ⊥)) - $(TR $(TD sdot) $(TD 8901) $(TD ⋅)) - $(TR $(TD lceil) $(TD 8968) $(TD ⌈)) - $(TR $(TD rceil) $(TD 8969) $(TD ⌉)) - $(TR $(TD lfloor) $(TD 8970) $(TD ⌊)) - $(TR $(TD rfloor) $(TD 8971) $(TD ⌋)) - $(TR $(TD lang) $(TD 9001) $(TD ⟨)) - $(TR $(TD rang) $(TD 9002) $(TD ⟩)) - $(TR $(TD loz) $(TD 9674) $(TD ◊)) - $(TR $(TD spades) $(TD 9824) $(TD ♠)) - $(TR $(TD clubs) $(TD 9827) $(TD ♣)) - $(TR $(TD hearts) $(TD 9829) $(TD ♥)) - $(TR $(TD diams) $(TD 9830) $(TD ♦)) - - ) - -) - -Macros: - TITLE=Named Character Entities - WIKI=Entities - - - CATEGORY_SPEC=$0 diff --git a/enum.dd b/enum.dd deleted file mode 100644 index 80bf12035a..0000000000 --- a/enum.dd +++ /dev/null @@ -1,227 +0,0 @@ -Ddoc - -$(SPEC_S Enums, - -$(GRAMMAR -$(GNAME EnumDeclaration): - $(B enum) $(GLINK EnumTag) $(GLINK EnumBody) - $(B enum) $(GLINK EnumBody) - $(B enum) $(GLINK EnumTag) $(B :) $(GLINK EnumBaseType) $(GLINK EnumBody) - $(B enum) $(B :) $(GLINK EnumBaseType) $(GLINK EnumBody) - -$(GNAME EnumTag): - $(I Identifier) - -$(GNAME EnumBaseType): - $(GLINK2 declaration, Type) - -$(GNAME EnumBody): - $(GLINK EmptyEnumBody) - $(GLINK EnumMembersBody) - -$(GNAME EmptyEnumBody): - $(B ;) - -$(GNAME EnumMembersBody): - $(B {) $(GLINK EnumMembers) $(B }) - -$(GNAME EnumMembers): - $(GLINK EnumMember) - $(GLINK EnumMember) $(B ,) - $(GLINK EnumMember) $(B ,) $(I EnumMembers) - -$(GNAME EnumMember): - $(I Identifier) - $(I Identifier) $(B =) $(ASSIGNEXPRESSION) -$(V2 $(GLINK2 declaration, Type) $(B =) $(ASSIGNEXPRESSION)) -) - - $(P Enum declarations are used to define a group of constants. - They come in two forms: - ) - $(OL - $(LI Named enums, which have an $(I EnumTag).) - $(LI Anonymous enums, which do not have an $(I EnumTag).) - ) - -

    Named Enums

    - - $(P - Named enums are used to declare related - constants and group them by giving them a unique type. - The $(I EnumMembers) - are declared in the scope of the enum $(I EnumTag). - The enum $(I EnumTag) declares a new type, and all - the $(I EnumMembers) have that type. - ) - - $(P This defines a new type $(CODE X) which has values - $(CODE X.A=0), $(CODE X.B=1), $(CODE X.C=2):) - ------- -enum X { A, B, C } // named enum ------- - -$(V1 - $(P If the $(I EnumBaseType) is not explicitly set, it is set to - type $(CODE int).) -) -$(V2 - $(P If the $(I EnumBaseType) is not explicitly set, and the first - $(I EnumMember) has an initializer, it is set to the type of that - initializer. Otherwise, it defaults to - type $(CODE int).) - - $(P Named enum members may not have individual $(I Type)s. - ) -) - - $(P A named enum member can be implicitly cast to its $(I EnumBaseType), - but $(I EnumBaseType) types - cannot be implicitly cast to an enum type. - ) - - $(P The value of an $(I EnumMember) is given by its initializer. - If there is no initializer, it is given the value of the - previous $(I EnumMember) + 1. If it is the first $(I EnumMember), - it's value is 0. - ) - - $(P An $(I EmptyEnumBody) signifies an opaque enum - the enum members are - unknown.) - -

    Enum Default Initializer

    - - $(P The $(CODE .init) property of an enum type is the value - of the first member of that enum. - This is also the default initializer for the enum type. - ) - ------- -enum X { A=3, B, C } -X x; // x is initialized to 3 ------- - -

    Enum Properties

    - - $(P Enum properties only exist for named enums. - ) - - $(TABLE1 - $(CAPTION Named Enum Properties) - $(TR $(TD .init) $(TD First enum member value)) - $(TR $(TD .min) $(TD Smallest value of enum)) - $(TR $(TD .max) $(TD Largest value of enum)) - $(TR $(TD .sizeof) $(TD Size of storage for an enumerated value)) - ) - - $(P For example:) - ---- -enum X { A=3, B, C } -X.min // is X.A -X.max // is X.C -X.sizeof // is same as int.sizeof ---- - -$(V2 - $(P The $(I EnumBaseType) of named enums must support comparison - in order to compute the $(CODE .max) and $(CODE .min) properties. - ) -) - -

    Anonymous Enums

    - - $(P If the enum $(I Identifier) is not present, then the enum - is an $(I anonymous enum), and the $(I EnumMembers) are declared - in the scope the $(I EnumDeclaration) appears in. - No new type is created; the $(I EnumMembers) have the type of the - $(I EnumBaseType). - ) - - The $(I EnumBaseType) is the underlying type of the enum. -$(V1 - $(P It must be an integral type. - If omitted, it defaults to $(B int). - ) -) -$(V2 - $(P If omitted, the $(I EnumMembers) can have different types. - Those types are given by the first of: - ) - - $(OL - $(LI The $(I Type), if present.) - $(LI The type of the $(I AssignExpression), if present.) - $(LI The type of the previous $(I EnumMember), if present.) - $(LI $(CODE int)) - ) -) - ------- -enum { A, B, C } // anonymous enum ------- - - $(P Defines the constants A=0, B=1, C=2, all of type int.) - - $(P Enums must have at least one member. - ) - - $(P The value of an $(I EnumMember) is given by its initializer. - If there is no initializer, it is given the value of the - previous $(I EnumMember) + 1. If it is the first $(I EnumMember), - it's value is 0. - ) - ------- -enum { A, B = 5+7, C, D = 8+C, E } ------- - - $(P Sets A=0, B=12, C=13, D=21, and E=22, all of type int.) - ---- -enum : long { A = 3, B } ---- - - $(P Sets A=3, B=4 all of type long.) - -$(V2 ---- -enum : string { - A = "hello", - B = "betty", - C // error, cannot add 1 to "betty" -} ---- - ---- -enum { - A = 1.2f, // A is 1.2f of type float - B, // B is 2.2f of type float - int C = 3, // C is 3 of type int - D // D is 4 of type int -} ---- - -

    Manifest Constants

    - - $(P If there is only one member of an anonymous enum, the { } can - be omitted: - ) - ---- -enum i = 4; // i is 4 of type int -enum long l = 3; // l is 3 of type long ---- - - $(P Such declarations are not lvalues, meaning their address - cannot be taken.) -) - -) - -Macros: - TITLE=Enums - WIKI=Enum - CATEGORY_SPEC=$0 - diff --git a/errorpage.ddoc b/errorpage.ddoc new file mode 100644 index 0000000000..331fe1e674 --- /dev/null +++ b/errorpage.ddoc @@ -0,0 +1,3 @@ +ROOT_DIR=/ +_=ROOT is only used for top left dlang.org logo and cannot be empty ``, so use / even though it breaks when served under /subpath/. +ROOT=/ diff --git a/errors.dd b/errors.dd deleted file mode 100644 index 0f6e176aed..0000000000 --- a/errors.dd +++ /dev/null @@ -1,219 +0,0 @@ -Ddoc - -$(SPEC_S Error Handling, - -$(BLOCKQUOTE Julius C'ster, -I came, I coded, I crashed. -) - -All programs have to deal with errors. Errors are unexpected conditions that -are not part of the normal operation of a program. Examples of common errors -are: - -$(UL - $(LI Out of memory.) - $(LI Out of disk space.) - $(LI Invalid file name.) - $(LI Attempting to write to a read-only file.) - $(LI Attempting to read a non-existent file.) - $(LI Requesting a system service that is not supported.) -) - -

    The Error Handling Problem

    - -The traditional C way of detecting and reporting errors is not traditional, -it is ad-hoc and varies from function to function, including: - -$(UL - $(LI Returning a NULL pointer.) - $(LI Returning a 0 value.) - $(LI Returning a non-zero error code.) - $(LI Requiring errno to be checked.) - $(LI Requiring that a function be called to check if the previous - function failed.) -) - -To deal with these possible errors, tedious error handling code must be added -to each function call. If an error happened, code must be written to recover -from the error, and the error must be reported to the user in some user friendly -fashion. If an error cannot be handled locally, it must be explicitly -propagated back to its caller. -The long list of errno values needs to be converted into appropriate -text to be displayed. Adding all the code to do this can consume a large part -of the time spent coding a project - and still, if a new errno value is added -to the runtime system, the old code can not properly display a meaningful -error message. -

    - -Good error handling code tends to clutter up what otherwise would be a neat -and clean looking implementation. -

    - -Even worse, good error handling code is itself error prone, tends to be the -least tested (and therefore buggy) part of the project, and is frequently -simply omitted. The end result is likely a "blue screen of death" as the -program failed to deal with some unanticipated error. -

    - -Quick and dirty programs are not worth writing tedious error handling code -for, and so such utilities tend to be like using a table saw with no -blade guards. -

    - -What's needed is an error handling philosophy and methodology such that: - -$(UL - $(LI It is standardized - consistent usage makes it more useful.) - $(LI The result is reasonable even if the programmer fails - to check for errors.) - $(LI Old code can be reused with new code without having - to modify the old code to be compatible with new error types.) - $(LI No errors get inadvertently ignored.) - $(LI $(SINGLEQUOTE Quick and dirty) utilities can be written that still - correctly handle errors.) - $(LI It is easy to make the error handling source code look good.) -) - -

    The D Error Handling Solution

    - -Let's first make some observations and assumptions about errors: - -$(UL - $(LI Errors are not part of the normal flow of a program. Errors - are exceptional, unusual, and unexpected.) - $(LI Because errors are unusual, execution of error handling code - is not performance critical.) - $(LI The normal flow of program logic is performance critical.) - $(LI All errors must be dealt with in some way, either by - code explicitly written to handle them, or by some system default - handling.) - $(LI The code that detects an error knows more about the error - than the code that must recover from the error.) -) - -The solution is to use exception handling to report errors. All errors are -objects derived from abstract class Error. class Error has a pure virtual -function called toString() which produces a char[] with a human readable -description of the error. -

    - -If code detects an error like "out of memory," then an Error is thrown -with a message saying "Out of memory". The function call stack is unwound, -looking for a handler for the Error. -$(DDSUBLINK statement, TryStatement, Finally blocks) -are executed as the -stack is unwound. If an error handler is found, execution resumes there. If -not, the default Error handler is run, which displays the message and -terminates the program. -

    - -How does this meet our criteria? - -

    -
    It is standardized - consistent usage makes it more useful. -
    This is the D way, and is used consistently in the D - runtime library and examples. - -
    The result is reasonable result even if the programmer fails - to check for errors. -
    If no catch handlers are there for the errors, then the - program gracefully exits through the default error handler - with an appropriate message. - -
    Old code can be reused with new code without having - to modify the old code to be compatible with new error types. -
    Old code can decide to catch all errors, or only specific ones, - propagating the rest upwards. In any case, there is no more - need to correlate error numbers with messages, the correct message - is always supplied. - -
    No errors get inadvertently ignored. -
    Error exceptions get handled one way or another. There is nothing - like a NULL pointer return indicating an error, followed by trying to - use that NULL pointer. - -
    'Quick and dirty' utilities can be written that still - correctly handle errors. -
    Quick and dirty code need not write any error handling code at - all, and don't need to check for errors. The errors will be caught, - an appropriate message displayed, and the program gracefully shut down - all by default. - -
    It is easy to make the error handling source code look good. -
    The try/catch/finally statements look a lot nicer than endless - if (error) goto errorhandler; statements. -
    - -How does this meet our assumptions about errors? - -
    -
    Errors are not part of the normal flow of a program. Errors - are exceptional, unusual, and unexpected. -
    D exception handling fits right in with that. - -
    Because errors are unusual, execution of error handling code - is not performance critical. -
    Exception handling stack unwinding is a relatively slow process. - -
    The normal flow of program logic is performance critical. -
    Since the normal flow code does not have to check every - function call for error returns, it can be realistically faster - to use exception handling for the errors. - -
    All errors must be dealt with in some way, either by - code explicitly written to handle them, or by some system default - handling. -
    If there's no handler for a particular error, it is handled - by the runtime library default handler. If an error is ignored, - it is because the programmer specifically added code to ignore - an error, which presumably means it was intentional. - -
    The code that detects an error knows more about the error - than the code that must recover from the error. -
    There is no more need to translate error codes into human - readable strings, the correct string is generated by the error - detection code, not the error recovery code. This also leads to - consistent error messages for the same error between applications. -
    - -Using exceptions to handle errors leads to another issue - how to write -exception safe programs. $(DPLLINK exception-safe.html, Here's how). - -$(COMMENT - $(OL - - $(LI Programmers, especially inexperienced ones, tend to neglect - to test for the special error return value. - Their code just assumed the function completed successfully. - This leads to erratic and unpredictable - behavior if the function did fail.) - - $(LI How each function deals with errors tends to be unique and - inconsistent, leading to more unintended - programmatic errors.) - - $(LI How the error gets reported to the user tends to vary - arbitrarily from one program to the next and one - error case to the next.) - - $(LI Dealing with error cases causes tedious and error-prone code - to be written, and so can consume much - programming effort.) - - $(LI Error handling logic tends to be buggy because it rarely - gets tested by the test team.) - - $(LI Functions that should have clean interfaces wind up - cluttering them with error return parameters and - cases.) - - ) -) - -) - -Macros: - TITLE=Errors - WIKI=Errors - CATEGORY_SPEC=$0 - diff --git a/expression.dd b/expression.dd deleted file mode 100644 index 15776fa5f1..0000000000 --- a/expression.dd +++ /dev/null @@ -1,2021 +0,0 @@ -Ddoc - -$(SPEC_S Expressions, - - $(P C and C++ programmers will find the D expressions very familiar, - with a few interesting additions. - ) - - $(P Expressions are used to compute values with a resulting type. - These values can then be assigned, - tested, or ignored. Expressions can also have side effects. - ) - -

    Order Of Evaluation

    - - $(P The following binary expressions are evaluated in strictly - left-to-right order:) - - $(P -$(V2 - $(GLINK OrExpression), - $(GLINK XorExpression), - $(GLINK AndExpression), - $(GLINK CmpExpression), - $(GLINK ShiftExpression), - $(GLINK AddExpression), - $(GLINK CatExpression), - $(GLINK MulExpression), - $(GLINK PowExpression), -) - $(GLINK CommaExpression), - $(GLINK OrOrExpression), - $(GLINK AndAndExpression) - ) - - $(P The following binary expressions are evaluated in an - implementation-defined order:) - - $(P - $(GLINK AssignExpression), -$(V1 - $(GLINK OrExpression), - $(GLINK XorExpression), - $(GLINK AndExpression), - $(GLINK CmpExpression), - $(GLINK ShiftExpression), - $(GLINK AddExpression), - $(GLINK CatExpression), - $(GLINK MulExpression), -) - function parameters - ) - - $(P It is an error - to depend on order of evaluation when it is not specified. - For example, the following are illegal: - ) -------------- -i = i++; -c = a + (a = b); -func(++i, ++i); -------------- - $(P If the compiler can determine that the result of an expression - is illegally dependent on the order of evaluation, it can issue - an error (but is not required to). The ability to detect these kinds - of errors is a quality of implementation issue. - ) - -

    Expressions

    - -$(GRAMMAR -$(GNAME Expression): - $(I CommaExpression) - -$(GNAME CommaExpression): - $(GLINK AssignExpression) - $(GLINK AssignExpression) $(B ,) $(I CommaExpression) -) - - The left operand of the $(B ,) is evaluated, then the right operand - is evaluated. The type of the expression is the type of the right - operand, and the result is the result of the right operand. - - -

    Assign Expressions

    - -$(GRAMMAR -$(GNAME AssignExpression): - $(GLINK ConditionalExpression) - $(GLINK ConditionalExpression) $(B =) $(I AssignExpression) - $(GLINK ConditionalExpression) $(B +=) $(I AssignExpression) - $(GLINK ConditionalExpression) $(B -=) $(I AssignExpression) - $(GLINK ConditionalExpression) $(B *=) $(I AssignExpression) - $(GLINK ConditionalExpression) $(B /=) $(I AssignExpression) - $(GLINK ConditionalExpression) $(B %=) $(I AssignExpression) - $(GLINK ConditionalExpression) $(B &=) $(I AssignExpression) - $(GLINK ConditionalExpression) $(B |=) $(I AssignExpression) - $(GLINK ConditionalExpression) $(B ^=) $(I AssignExpression) - $(GLINK ConditionalExpression) $(B ~=) $(I AssignExpression) - $(GLINK ConditionalExpression) $(B <<=) $(I AssignExpression) - $(GLINK ConditionalExpression) $(B >>=) $(I AssignExpression) - $(GLINK ConditionalExpression) $(B >>>=) $(I AssignExpression) -$(V2 - $(GLINK ConditionalExpression) $(B ^^=) $(I AssignExpression)) -) - - The right operand is implicitly converted to the type of the - left operand, and assigned to it. The result type is the type - of the lvalue, and the result value is the value of the lvalue - after the assignment. -

    - - The left operand must be an lvalue. - -

    Assignment Operator Expressions

    - - Assignment operator expressions, such as: - --------------- -a $(I op)= b --------------- - - are semantically equivalent to: - --------------- -a = cast(typeof(a))(a $(I op) b) --------------- - - $(P except that:) - - $(UL - $(LI operand $(D a) is only evaluated once) - $(LI overloading $(I op) uses a different function than overloading $(I op)= does) - $(LI the left operand of $(D >>>=) does not undergo integral promotions before shifting) - ) - -

    Conditional Expressions

    - -$(GRAMMAR -$(GNAME ConditionalExpression): - $(GLINK OrOrExpression) - $(GLINK OrOrExpression) $(B ?) $(GLINK Expression) $(B :) $(I ConditionalExpression) -) - - The first expression is converted to bool, and is evaluated. - If it is true, then the second expression is evaluated, and - its result is the result of the conditional expression. - If it is false, then the third expression is evaluated, and - its result is the result of the conditional expression. - If either the second or third expressions are of type void, - then the resulting type is void. Otherwise, the second and third - expressions are implicitly converted to a common type which becomes - the result type of the conditional expression. - -

    OrOr Expressions

    - -$(GRAMMAR -$(GNAME OrOrExpression): - $(GLINK AndAndExpression) - $(I OrOrExpression) $(B ||) $(GLINK AndAndExpression) -) - - The result type of an $(I OrOrExpression) is bool, - unless the right operand - has type void, when the result is type void. -

    - - The $(I OrOrExpression) evaluates its left operand. - - If the left operand, converted to type bool, evaluates to - true, then the right operand is not evaluated. If the result type of - the $(I OrOrExpression) is bool then the result of the - expression is true. - - If the left operand is false, then the right - operand is evaluated. - If the result type of - the $(I OrOrExpression) is bool then the result of the - expression is the right operand converted to type bool. - - -

    AndAnd Expressions

    - -$(V1 -$(GRAMMAR -$(GNAME AndAndExpression): - $(GLINK OrExpression) - $(I AndAndExpression) $(B &&) $(GLINK OrExpression) -) -) -$(V2 -$(GRAMMAR -$(GNAME AndAndExpression): - $(GLINK OrExpression) - $(I AndAndExpression) $(B &&) $(GLINK OrExpression) - $(GLINK CmpExpression) - $(I AndAndExpression) $(B &&) $(GLINK CmpExpression) -) -) - - $(P The result type of an $(I AndAndExpression) is bool, unless the right operand - has type void, when the result is type void. - ) - - $(P The $(I AndAndExpression) evaluates its left operand. - ) - - $(P If the left operand, converted to type bool, evaluates to - false, then the right operand is not evaluated. If the result type of - the $(I AndAndExpression) is bool then the result of the - expression is false. - ) - - $(P If the left operand is true, then the right - operand is evaluated. - If the result type of - the $(I AndAndExpression) is bool then the result of the - expression is the right operand converted to type bool. - ) - - -

    Bitwise Expressions

    - - Bit wise expressions perform a bitwise operation on their operands. - Their operands must be integral types. - First, the default integral promotions are done. Then, the bitwise - operation is done. - -

    Or Expressions

    - -$(GRAMMAR -$(GNAME OrExpression): - $(GLINK XorExpression) - $(I OrExpression) $(B |) $(GLINK XorExpression) -) - - The operands are OR'd together. - -

    Xor Expressions

    - -$(GRAMMAR -$(GNAME XorExpression): - $(GLINK AndExpression) - $(I XorExpression) $(B ^) $(GLINK AndExpression) -) - - The operands are XOR'd together. - -

    And Expressions

    - -$(V1 -$(GRAMMAR -$(GNAME AndExpression): - $(GLINK CmpExpression) - $(I AndExpression) $(B &) $(GLINK CmpExpression) -) -) -$(V2 -$(GRAMMAR -$(GNAME AndExpression): - $(GLINK ShiftExpression) - $(I AndExpression) $(B &) $(GLINK ShiftExpression) -) -) - The operands are AND'd together. - - -

    Compare Expressions

    - -$(GRAMMAR -$(GNAME CmpExpression): - $(GLINK ShiftExpression) - $(GLINK EqualExpression) - $(GLINK IdentityExpression) - $(GLINK RelExpression) - $(GLINK InExpression) -) - -

    Equality Expressions

    - -$(GRAMMAR -$(GNAME EqualExpression): - $(GLINK ShiftExpression) $(B ==) $(GLINK ShiftExpression) - $(GLINK ShiftExpression) $(B !=) $(GLINK ShiftExpression) -) - - Equality expressions compare the two operands for equality ($(B ==)) - or inequality ($(B !=)). - The type of the result is bool. The operands - go through the usual conversions to bring them to a common type before - comparison. -

    - - If they are integral values or pointers, equality - is defined as the bit pattern of the type matches exactly. - Equality for struct objects means the bit patterns of the objects - match exactly (the existence of alignment holes in the objects - is accounted for, usually by setting them all to 0 upon - initialization). - Equality for floating point types is more complicated. -0 and - +0 compare as equal. If either or both operands are NAN, then - both the == returns false and != returns true. Otherwise, the bit - patterns are compared for equality. -

    - - For complex numbers, equality is defined as equivalent to: - ---- -x.re == y.re && x.im == y.im ---- - - and inequality is defined as equivalent to: - ---- -x.re != y.re || x.im != y.im ---- - - $(P For class and struct objects, the expression $(D (a == b)) - is rewritten as - $(D a.opEquals(b)), and $(D (a != b)) is rewritten as - $(D !a.opEquals(b)). - ) - - $(P For class objects, the $(CODE ==) and $(CODE !=) - operators compare the - contents of the objects. Therefore, comparing against - $(CODE null) is invalid, as $(CODE null) has no contents. - Use the $(CODE is) and $(CODE !is) operators instead. - ) - ---- -class C; -C c; -if (c == null) // error - ... -if (c is null) // ok - ... ---- - - $(P For static and dynamic arrays, equality is defined as the - lengths of the arrays - matching, and all the elements are equal. - ) - -

    Identity Expressions

    - -$(GRAMMAR -$(GNAME IdentityExpression): - $(GLINK ShiftExpression) $(B is) $(GLINK ShiftExpression) - $(GLINK ShiftExpression) $(B !is) $(GLINK ShiftExpression) -) - - $(P The $(B is) compares for identity. - To compare for not identity, use $(D $(I e1) $(B !is) $(I e2)). - The type of the result is bool. The operands - go through the usual conversions to bring them to a common type before - comparison. - ) - - $(P For class objects, identity is defined as the object references - are for the same object. Null class objects can be compared with - $(B is). - ) - - $(P For struct objects, identity is defined as the bits in the - struct being identical. - ) - - $(P For static and dynamic arrays, identity is defined as referring - to the same array elements and the same number of elements. - ) - - $(P For other operand types, identity is defined as being the same - as equality. - ) - - $(P The identity operator $(B is) cannot be overloaded. - ) - -

    Relational Expressions

    - -$(GRAMMAR -$(GNAME RelExpression): - $(GLINK ShiftExpression) $(B <) $(GLINK ShiftExpression) - $(GLINK ShiftExpression) $(B <=) $(GLINK ShiftExpression) - $(GLINK ShiftExpression) $(B >) $(GLINK ShiftExpression) - $(GLINK ShiftExpression) $(B >=) $(GLINK ShiftExpression) - $(GLINK ShiftExpression) $(B !<>=) $(GLINK ShiftExpression) - $(GLINK ShiftExpression) $(B !<>) $(GLINK ShiftExpression) - $(GLINK ShiftExpression) $(B <>) $(GLINK ShiftExpression) - $(GLINK ShiftExpression) $(B <>=) $(GLINK ShiftExpression) - $(GLINK ShiftExpression) $(B !>) $(GLINK ShiftExpression) - $(GLINK ShiftExpression) $(B !>=) $(GLINK ShiftExpression) - $(GLINK ShiftExpression) $(B !<) $(GLINK ShiftExpression) - $(GLINK ShiftExpression) $(B !<=) $(GLINK ShiftExpression) -) - - First, the integral promotions are done on the operands. - The result type of a relational expression is bool. -

    - - For class objects, the result of Object.opCmp() forms the left - operand, and 0 forms the right operand. The result of the - relational expression (o1 op o2) is: - ---- -(o1.opCmp(o2) op 0) ---- - - It is an error to compare objects if one is $(B null). -

    - - For static and dynamic arrays, the result of the relational - op is the result of the operator applied to the first non-equal - element of the array. If two arrays compare equal, but are of - different lengths, the shorter array compares as "less" than the - longer array. - - -

    Integer comparisons

    - - $(P Integer comparisons happen when both operands are integral - types. - ) - - $(TABLE2 Integer comparison operators, - $(TR - $(TH Operator)$(TH Relation) - )$(TR - $(TD <) $(TD less) - )$(TR - $(TD >) $(TD greater) - )$(TR - $(TD <=) $(TD less or equal) - )$(TR - $(TD >=) $(TD greater or equal) - )$(TR - $(TD ==) $(TD equal) - )$(TR - $(TD !=) $(TD not equal) - ) - ) - - $(P It is an error to have one operand be signed and the other - unsigned for a <, <=, > or >= expression. - Use casts to make both operands signed or both operands unsigned. - ) - -

    Floating point comparisons

    - - If one or both operands are floating point, then a floating - point comparison is performed. -

    - - Useful floating point operations must take into account NAN values. - In particular, a relational operator can have NAN operands. - The result of a relational operation on float - values is less, greater, equal, or unordered (unordered means - either or both of the - operands is a NAN). That means there are 14 possible comparison - conditions to test for: -

    - - $(TABLE2 Floating point comparison operators, - $(TR - $(TH Operator) - $(TH Greater Than) - $(TH Less Than) - $(TH Equal) - $(TH Unordered) - $(TH Exception) - $(TH Relation) - ) - $(TR - $(TD ==) $(TD F)$(TD F)$(TD T)$(TD F)$(TD no) $(TD equal) - ) - $(TR - $(TD !=) $(TD T)$(TD T)$(TD F)$(TD T)$(TD no) $(TD unordered, less, or greater) - ) - $(TR - $(TD >) $(TD T)$(TD F)$(TD F)$(TD F)$(TD yes) $(TD greater) - ) - $(TR - $(TD >=) $(TD T)$(TD F)$(TD T)$(TD F)$(TD yes) $(TD greater or equal) - ) - $(TR - $(TD <) $(TD F)$(TD T)$(TD F)$(TD F)$(TD yes) $(TD less) - ) - $(TR - $(TD <=) $(TD F)$(TD T)$(TD T)$(TD F)$(TD yes) $(TD less or equal) - ) - $(TR - $(TD !<>=) $(TD F)$(TD F)$(TD F)$(TD T)$(TD no) $(TD unordered) - ) - $(TR - $(TD <>) $(TD T)$(TD T)$(TD F)$(TD F)$(TD yes) $(TD less or greater) - ) - $(TR - $(TD <>=) $(TD T)$(TD T)$(TD T)$(TD F)$(TD yes) $(TD less, equal, or greater) - ) - $(TR - $(TD !<=) $(TD T)$(TD F)$(TD F)$(TD T)$(TD no) $(TD unordered or greater) - ) - $(TR - $(TD !<) $(TD T)$(TD F)$(TD T)$(TD T)$(TD no) $(TD unordered, greater, or equal) - ) - $(TR - $(TD !>=) $(TD F)$(TD T)$(TD F)$(TD T)$(TD no) $(TD unordered or less) - ) - $(TR - $(TD !>) $(TD F)$(TD T)$(TD T)$(TD T)$(TD no) $(TD unordered, less, or equal) - ) - $(TR - $(TD !<>) $(TD F)$(TD F)$(TD T)$(TD T)$(TD no) $(TD unordered or equal) - ) - ) - -

    Notes:

    - - $(OL - $(LI For floating point comparison operators, - $(CODE ($(I a) !$(I op) $(I b))) - is not the same as $(CODE !($(I a op b))).) - $(LI "Unordered" means one or both of the operands is a NAN.) - $(LI "Exception" means the $(I Invalid Exception) is raised if one - of the operands is a NAN. It does not mean an exception - is thrown. The $(I Invalid Exception) can be checked - using the functions in $(DPLLINK phobos/std_c_fenv.html, std.c.fenv). - ) - ) - -

    Class comparisons

    - - $(P For class objects, the relational - operators compare the - contents of the objects. Therefore, comparing against - $(CODE null) is invalid, as $(CODE null) has no contents. - ) - ---- -class C; -C c; -if (c < null) // error - ... ---- - -

    In Expressions

    - -$(GRAMMAR -$(GNAME InExpression): - $(GLINK ShiftExpression) $(B in) $(GLINK ShiftExpression) -$(V2 $(GLINK ShiftExpression) $(B !in) $(GLINK ShiftExpression)) -) - - $(P An associative array can be tested to see if an element is in the array: - ) - -------------- -int foo[char[]]; -... -if ("hello" in foo) - ... -------------- - - $(P The $(B in) expression has the same precedence as the - relational expressions $(B <), $(B <=), - etc. - The return value of the $(I InExpression) is $(B null) - if the element is not in the array; - if it is in the array it is a pointer to the element. - ) - - $(V2 $(P The $(B !in) expression is the logical negation of the $(B in) - operation. - )) - -

    Shift Expressions

    - -$(GRAMMAR -$(GNAME ShiftExpression): - $(GLINK AddExpression) - $(I ShiftExpression) $(B <<) $(GLINK AddExpression) - $(I ShiftExpression) $(B >>) $(GLINK AddExpression) - $(I ShiftExpression) $(B >>>) $(GLINK AddExpression) -) - - $(P The operands must be integral types, and undergo the usual integral - promotions. The result type is the type of the left operand after - the promotions. The result value is the result of shifting the bits - by the right operand's value. - ) - - $(P $(B <<) is a left shift. - $(B >>) is a signed right shift. - $(B >>>) is an unsigned right shift. - ) - - $(P It's illegal to shift by the same or more bits than the size of the - quantity being shifted: - ) - -------------- -int c; -c << 33; // error -------------- - -

    Add Expressions

    - -$(GRAMMAR -$(GNAME AddExpression): - $(GLINK MulExpression) - $(I AddExpression) $(B +) $(GLINK MulExpression) - $(I AddExpression) $(B -) $(GLINK MulExpression) - $(GLINK CatExpression) -) - - $(P If the operands are of integral types, they undergo integral - promotions, and then are brought to a common type using the - usual arithmetic conversions. - ) - - $(P If either operand is a floating point type, the other is implicitly - converted to floating point and they are brought to a common type - via the usual arithmetic conversions. - ) - - $(P If the operator is $(B +) or $(B -), and - the first operand is a pointer, and the second is an integral type, - the resulting type is the type of the first operand, and the resulting - value is the pointer plus (or minus) the second operand multiplied by - the size of the type pointed to by the first operand. - ) - - $(P If the second operand is a pointer, and the first is an integral type, - and the operator is $(B +), - the operands are reversed and the pointer arithmetic just described - is applied. - ) - - $(P If both operands are pointers, and the operator is $(B +), - then it is illegal. For $(B -), the pointers are subtracted and the - result is divided by the size of the type pointed to by the - operands. It is an error if the pointers point to different types. - ) - - $(P Add expressions for floating point operands are not associative. - ) - -

    Cat Expressions

    - -$(GRAMMAR -$(GNAME CatExpression): - $(I AddExpression) $(B ~) $(GLINK MulExpression) -) - - $(P A $(I CatExpression) concatenates arrays, producing - a dynmaic array with the result. The arrays must be - arrays of the same element type. If one operand is an array - and the other is of that array's element type, that element - is converted to an array of length 1 of that element, - and then the concatenation is performed. - ) - -

    Mul Expressions

    - -$(GRAMMAR -$(GNAME MulExpression): - $(GLINK UnaryExpression) - $(I MulExpression) $(B *) $(GLINK UnaryExpression) - $(I MulExpression) $(B /) $(GLINK UnaryExpression) - $(I MulExpression) $(B %) $(GLINK UnaryExpression) -) - - $(P The operands must be arithmetic types. They undergo integral - promotions, and then are brought to a common type using the - usual arithmetic conversions. - ) - - $(P For integral operands, the $(B *), $(B /), and $(B %) - correspond to multiply, divide, and modulus operations. - For multiply, overflows are ignored and simply chopped to fit - into the integral type. - ) - - $(P For integral operands of the $(B /) and $(B %) operators, - the quotient rounds towards zero and the remainder has the - same sign as the dividend. - If the divisor is zero, an Exception is thrown. - ) - - $(P For floating point operands, the * and / operations correspond - to the IEEE 754 floating point equivalents. % is not the same as - the IEEE 754 remainder. For example, 15.0 % 10.0 == 5.0, whereas - for IEEE 754, remainder(15.0,10.0) == -5.0. - ) - - $(P Mul expressions for floating point operands are not associative. - ) - -

    Unary Expressions

    - -$(GRAMMAR -$(GNAME UnaryExpression): - $(B &) $(I UnaryExpression) - $(B ++) $(I UnaryExpression) - $(B --) $(I UnaryExpression) - $(B *) $(I UnaryExpression) - $(B -) $(I UnaryExpression) - $(B +) $(I UnaryExpression) - $(B !) $(I UnaryExpression) - $(GLINK ComplementExpression) - $(B $(LPAREN)) $(GLINK2 declaration, Type) $(B $(RPAREN) .) $(IDENTIFIER) - $(GLINK NewExpression) - $(GLINK DeleteExpression) - $(GLINK CastExpression) - $(V1 $(GLINK PostfixExpression))$(V2 $(GLINK PowExpression)) -) - -

    Complement Expressions

    - -$(GRAMMAR -$(GNAME ComplementExpression): - $(B ~) $(I UnaryExpression) -) - - $(P $(I ComplementExpression)s work on integral types (except bool). - All the bits in the value are complemented.) - - $(P Note: unlike in C and C++, the usual integral promotions are not performed - prior to the complement operation. - ) - -

    New Expressions

    - -$(GRAMMAR -$(GNAME NewExpression): - $(B new) $(I AllocatorArguments)$(OPT) $(GLINK2 declaration, Type) $(B [) $(GLINK AssignExpression) $(B ]) - $(B new) $(I AllocatorArguments)$(OPT) $(GLINK2 declaration, Type) $(B $(LPAREN)) $(GLINK ArgumentList) $(B $(RPAREN)) - $(B new) $(I AllocatorArguments)$(OPT) $(GLINK2 declaration, Type) - $(GLINK2 class, NewAnonClassExpression) - -$(GNAME AllocatorArguments): - $(B $(LPAREN)) $(GLINK ArgumentList)$(OPT) $(B $(RPAREN)) - -$(GNAME ArgumentList): - $(GLINK AssignExpression) -$(V2 $(GLINK AssignExpression) $(B ,) -) $(GLINK AssignExpression) $(B ,) $(I ArgumentList) -) - - $(P $(I NewExpression)s are used to allocate memory on the garbage - collected heap (default) or using a class or struct specific allocator. - ) - - $(P To allocate multidimensional arrays, the declaration reads - in the same order as the prefix array declaration order. - ) - -------------- -char[][] foo; // dynamic array of strings -... -foo = new char[][30]; // allocate array of 30 strings -------------- - - $(P The above allocation can also be written as:) - -------------- -foo = new char[][](30); // allocate array of 30 strings -------------- - - $(P To allocate the nested arrays, multiple arguments can be used:) - ---------------- -int[][][] bar; -... -bar = new int[][][](5,20,30); ---------------- - - $(P Which is equivalent to:) - ----------- -bar = new int[][][5]; -foreach (ref a; bar) -{ - a = new int[][20]; - foreach (ref b; a) - { - b = new int[30]; - } -} ------------ - - $(P If there is a $(B new $(LPAREN)) $(GLINK ArgumentList) $(B $(RPAREN)), - then - those arguments are passed to the class or struct specific - $(LINK2 class.html#allocators, allocator function) after the size argument. - ) - - $(P If a $(I NewExpression) is used as an initializer for - a function local variable with $(B scope) storage class, - and the $(GLINK ArgumentList) to $(B new) is empty, then - the instance is allocated on the stack rather than the heap - or using the class specific allocator. - ) - -

    Delete Expressions

    - -$(GRAMMAR -$(GNAME DeleteExpression): - $(B delete) $(GLINK UnaryExpression) -) - $(P If the $(I UnaryExpression) is a class object reference, and - there is a destructor for that class, the destructor - is called for that object instance. - ) - - $(P Next, if the $(I UnaryExpression) is a class object reference, or - a pointer to a struct instance, and the class or struct - has overloaded operator delete, then that operator delete is called - for that class object instance or struct instance. - ) - - $(P Otherwise, the garbage collector is called to immediately free the - memory allocated for the class instance or struct instance. - If the garbage collector was not used to allocate the memory for - the instance, undefined behavior will result. - ) - - $(P If the $(I UnaryExpression) is a pointer or a dynamic array, - the garbage collector is called to immediately release the - memory. - If the garbage collector was not used to allocate the memory for - the instance, undefined behavior will result. - ) - - $(P The pointer, dynamic array, or reference is set to $(B null) - after the delete is performed. - Any attempt to reference the data after the deletion via another - reference to it will result in undefined behavior. - ) - - $(P If $(I UnaryExpression) is a variable allocated - on the stack, the class destructor (if any) is called for that - instance. Neither the garbage collector nor any class deallocator - is called. - ) - -

    Cast Expressions

    - -$(GRAMMAR -$(GNAME CastExpression): - $(B cast $(LPAREN)) $(GLINK2 declaration, Type) $(B $(RPAREN)) $(GLINK UnaryExpression) - $(B cast $(LPAREN)) $(I CastQual) $(B $(RPAREN)) $(GLINK UnaryExpression) - $(B cast $(LPAREN)) $(B $(RPAREN)) $(GLINK UnaryExpression) - -$(GNAME CastQual): - $(B const) - $(B const shared) - $(B shared const) - $(B inout) - $(B inout shared) - $(B shared inout) - $(B immutable) - $(B shared) -) - - $(P A $(I CastExpression) converts the $(I UnaryExpression) - to $(GLINK2 declaration, Type). - ) - -------------- -$(B cast)(foo) -p; // cast (-p) to type foo -(foo) - p; // subtract p from foo -------------- - - $(P Any casting of a class reference to a - derived class reference is done with a runtime check to make sure it - really is a downcast. $(B null) is the result if it isn't. - $(B Note:) This is equivalent to the behavior of the - dynamic_cast operator in C++. - ) - -------------- -class A { ... } -class B : A { ... } - -void test(A a, B b) { - B bx = a; // error, need cast - B bx = cast(B) a; // bx is null if a is not a B - A ax = b; // no cast needed - A ax = cast(A) b; // no runtime check needed for upcast -} -------------- - - $(P In order to determine if an object $(D o) is an instance of - a class $(D B) use a cast: - ) - -------------- -if ($(B cast)(B) o) -{ - // o is an instance of B -} -else -{ - // o is not an instance of B -} -------------- - - $(P Casting a pointer type to and from a class type is done as a type paint - (i.e. a reinterpret cast).) - - $(P Casting a dynamic array to another dynamic array is done only if the - array lengths multiplied by the element sizes match. The cast is done - as a type paint, with the array length adjusted to match any change in - element size. If there's not a match, a runtime error is generated.) - -$(V1 ---- -import std.stdio; - -int main() { - byte[] a = [1,2,3]; - auto b = cast(int[])a; // runtime array cast misalignment - - int[] c = [1, 2, 3]; - auto d = cast(byte[])c; // ok - // prints: - // [1,0,0,0,2,0,0,0,3,0,0,0] - writefln(d); - return 0; -} ---- -) -$(V2 ---- -import std.stdio; - -int main() { - byte[] a = [1,2,3]; - auto b = cast(int[])a; // runtime array cast misalignment - - int[] c = [1, 2, 3]; - auto d = cast(byte[])c; // ok - // prints: - // [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0] - writeln(d); - return 0; -} ---- -) - $(P Casting a floating point literal from one type to another - changes its type, but internally it is retained at full - precision for the purposes of constant folding. - ) - ---- -void test() { - real a = 3.40483L; - real b; - b = 3.40483; // literal is not truncated to double precision - assert(a == b); - assert(a == 3.40483); - assert(a == 3.40483L); - assert(a == 3.40483F); - double d = 3.40483; // truncate literal when assigned to variable - assert(d != a); // so it is no longer the same - const double x = 3.40483; // assignment to const is not - assert(x == a); // truncated if the initializer is visible -} ---- - - $(P Casting a value $(I v) to a struct $(I S), when value is not a struct - of the same type, is equivalent to: - ) - ---- -S(v) ---- - - $(P Casting to a $(GLINK CastQual) replaces the qualifiers to the type of - the $(GLINK UnaryExpression).) - ---- -shared int x; -assert(is(typeof(cast(const)x) == const int)); ---- - - $(P Casting with no $(GLINK Type) or $(GLINK CastQual) removes - any top level $(B const), $(B immutable), $(B shared) or $(B inout) - type modifiers from the type - of the $(GLINK UnaryExpression).) - ---- -shared int x; -assert(is(typeof(cast()x) == int)); ---- - -$(V2 -

    Pow Expressions

    - -$(GRAMMAR -$(GNAME PowExpression): - $(GLINK PostfixExpression) - $(GLINK PostfixExpression) ^^ $(GLINK UnaryExpression) -) - - $(P $(I PowExpression) raises its left operand to the power of its - right operand. - ) -) - - -

    Postfix Expressions

    - -$(GRAMMAR -$(GNAME PostfixExpression): - $(GLINK PrimaryExpression) - $(I PostfixExpression) $(B .) $(IDENTIFIER) - $(I PostfixExpression) $(B .) $(GLINK2 template, TemplateInstance) - $(I PostfixExpression) $(B .) $(GLINK NewExpression) - $(I PostfixExpression) $(B ++) - $(I PostfixExpression) $(B --) - $(I PostfixExpression) $(B ( )) - $(I PostfixExpression) $(B $(LPAREN)) $(GLINK ArgumentList) $(B $(RPAREN)) - $(GLINK IndexExpression) - $(GLINK SliceExpression) -) - -

    Index Expressions

    - -$(GRAMMAR -$(GNAME IndexExpression): - $(GLINK PostfixExpression) $(B [) $(GLINK ArgumentList) $(B ]) -) - - $(P $(I PostfixExpression) is evaluated. - - If $(I PostfixExpression) is an expression of type - static array or dynamic array, the symbol $(DOLLAR) is - set to be the the number of elements in the array. - - If $(I PostfixExpression) is an $(I ExpressionTuple), - the symbol $(DOLLAR) is - set to be the the number of elements in the tuple. - - A new declaration scope is created for the evaluation of the - $(GLINK ArgumentList) and $(DOLLAR) appears in that scope only. - ) - - $(P If $(I PostfixExpression) is an $(I ExpressionTuple), - then the $(GLINK ArgumentList) must consist of only one argument, - and that must be statically evaluatable to an integral constant. - That integral constant $(I n) then selects the $(I n)th - expression in the $(I ExpressionTuple), which is the result - of the $(I IndexExpression). - It is an error if $(I n) is out of bounds of the $(I ExpressionTuple). - ) - -

    Slice Expressions

    - -$(GRAMMAR -$(GNAME SliceExpression): - $(GLINK PostfixExpression) $(B [ ]) - $(GLINK PostfixExpression) $(B [) $(GLINK AssignExpression) $(B ..) $(GLINK AssignExpression) $(B ]) -) - - $(P $(I PostfixExpression) is evaluated. - if $(I PostfixExpression) is an expression of type - static array or dynamic array, the variable $(B length) - (and the special variable $(DOLLAR)) - is declared and set to be the length of the array. - A new declaration scope is created for the evaluation of the - $(GLINK AssignExpression)..$(GLINK AssignExpression) - and $(B length) (and $(DOLLAR)) appears in that scope only. - ) - - $(P The first $(I AssignExpression) is taken to be the inclusive - lower bound - of the slice, and the second $(I AssignExpression) is the - exclusive upper bound. - The result of the expression is a slice of the $(I PostfixExpression) - array. - ) - - $(P If the $(B [ ]) form is used, the slice is of the entire - array. - ) - - $(P The type of the slice is a dynamic array of the element - type of the $(I PostfixExpression). - ) - - $(P A $(I SliceExpression) is not a modifiable lvalue.) - - $(P If $(I PostfixExpression) is an $(I ExpressionTuple), then - the result of the slice is a new $(I ExpressionTuple) formed - from the upper and lower bounds, which must statically evaluate - to integral constants. - It is an error if those - bounds are out of range. - ) - -

    Primary Expressions

    - -$(GRAMMAR -$(GNAME PrimaryExpression): - $(IDENTIFIER) - $(B .)$(IDENTIFIER) - $(GLINK2 template, TemplateInstance) - $(B .)$(GLINK2 template, TemplateInstance) - $(LINK2 #this, $(B this)) - $(LINK2 #super, $(B super)) - $(LINK2 #null, $(B null)) - $(B true) - $(B false) - $(B $) -$(V2 $(B __FILE__) - $(B __LINE__)) - $(GLINK2 lex, IntegerLiteral) - $(GLINK2 lex, FloatLiteral) - $(GLINK CharacterLiteral) - $(GLINK StringLiterals) - $(GLINK ArrayLiteral) - $(GLINK AssocArrayLiteral) - $(GLINK Lambda) - $(GLINK FunctionLiteral) - $(GLINK AssertExpression) - $(GLINK MixinExpression) - $(GLINK ImportExpression) - $(DDSUBLINK declaration, BasicTypeX, $(I BasicType)) $(B .) $(IDENTIFIER) - $(GLINK2 declaration, Typeof) - $(GLINK TypeidExpression) - $(GLINK IsExpression) - $(B $(LPAREN)) $(I Expression) $(B $(RPAREN)) -$(V2 $(GLINK2 traits, TraitsExpression)) -) - -

    .Identifier

    - - $(IDENTIFIER) is looked up at module scope, rather than the current - lexically nested scope. - -

    $(LNAME2 this, this)

    - - $(P Within a non-static member function, $(B this) resolves to - a reference to the object for which the function was called. - If the object is an instance of a struct, $(B this) will - be a pointer to that instance. - If a member function is called with an explicit reference - to $(B typeof(this)), a non-virtual call is made: - ) - -------------- -class A { - char get() { return 'A'; } - - char foo() { return $(B typeof(this)).get(); } - char bar() { return $(B this).get(); } -} - -class B : A { - char get() { return 'B'; } -} - -void main() { - B b = new B(); - - b.foo(); // returns 'A' - b.bar(); // returns 'B' -} -------------- - - $(P Assignment to $(B this) is not allowed.) - -

    $(LNAME2 super, super)

    - - $(P $(B super) is identical to $(B this), except that it is - cast to $(B this)'s base class. - It is an error if there is no base class. - It is an error to use $(B super) within a struct member function. - (Only class $(D Object) has no base class.) - If a member function is called with an explicit reference - to $(B super), a non-virtual call is made. - ) - - $(P Assignment to $(B super) is not allowed.) - -

    $(LNAME2 null, null)

    - - $(P $(B null) represents the null value for - pointers, pointers to functions, delegates, - dynamic arrays, associative arrays, - and class objects. - If it has not already been cast to a type, - it is given the type (void *) and it is an exact conversion - to convert it to the null value for pointers, pointers to - functions, delegates, etc. - After it is cast to a type, such conversions are implicit, - but no longer exact. - ) - -

    true, false

    - - These are of type $(B bool) and when cast to another integral - type become the values 1 and 0, - respectively. - -

    Character Literals

    - - Character literals are single characters and resolve to one - of type $(B char), $(B wchar), or $(B dchar). - If the literal is a \u escape sequence, it resolves to type $(B wchar). - If the literal is a \U escape sequence, it resolves to type $(B dchar). - Otherwise, it resolves to the type with the smallest size it - will fit into. - -

    String Literals

    - -$(GRAMMAR -$(GNAME StringLiterals): - $(GLINK2 lex, StringLiteral) - $(I StringLiterals) $(GLINK2 lex, StringLiteral) -) - - $(P String literals can implicitly convert to any - of the following types, they have equal weight: - ) - -$(V1 - $(TABLE1 - $(TROW $(D char*)) - $(TROW $(D wchar*)) - $(TROW $(D dchar*)) - $(TROW $(D char[])) - $(TROW $(D wchar[])) - $(TROW $(D dchar[])) - ) -) -$(V2 - $(TABLE1 - $(TROW $(D immutable(char)*)) - $(TROW $(D immutable(wchar)*)) - $(TROW $(D immutable(dchar)*)) - $(TROW $(D immutable(char)[])) - $(TROW $(D immutable(wchar)[])) - $(TROW $(D immutable(dchar)[])) - ) -) - $(P String literals have a 0 appended to them, which makes - them easy to pass to C or C++ functions expecting a $(CODE const char*) - string. - The 0 is not included in the $(CODE .length) property of the - string literal. - ) - -

    Array Literals

    - -$(GRAMMAR -$(GNAME ArrayLiteral): - $(B [) $(GLINK ArgumentList) $(B ]) -) - - $(P Array literals are a comma-separated list of $(GLINK AssignExpression)s - between square brackets [ and ]. - The $(I AssignExpression)s form the elements of a static array, - the length of the array is the number of elements. - The type of the first element is taken to be the type of - all the elements, and all elements are implicitly converted - to that type. - If that type is a static array, it is converted to a dynamic - array. - ) - ---- -[1,2,3]; // type is int[3], with elements 1, 2 and 3 -[1u,2,3]; // type is uint[3], with elements 1u, 2u, and 3u ---- - - $(P If any of the arguments in the $(GLINK ArgumentList) are - an $(I ExpressionTuple), then the elements of the $(I ExpressionTuple) - are inserted as arguments in place of the tuple. - ) - - $(P Array literals are allocated on the memory managed heap. - Thus, they can be returned safely from functions:) - ---- -int[] foo() { - return [1, 2, 3]; -} ---- - - $(P When array literals are cast to another array type, each - element of the array is cast to the new element type. - When arrays that are not literals are cast, the array is - reinterpreted as the new type, and the length is recomputed: - ) - ---- -import std.stdio; - -void main() { - // cast array literal - const short[] ct = cast(short[]) [cast(byte)1, 1]; - writeln(ct); // writes [1, 1] - - // cast other array expression - short[] rt = cast(short[]) [cast(byte)1, cast(byte)1].dup; - writeln(rt); // writes [257] -} ---- - - -

    Associative Array Literals

    - -$(GRAMMAR -$(GNAME AssocArrayLiteral): - $(B [) $(GLINK KeyValuePairs) $(B ]) - -$(GNAME KeyValuePairs): - $(GLINK KeyValuePair) - $(GLINK KeyValuePair) $(B ,) $(I KeyValuePairs) - -$(GNAME KeyValuePair): - $(GLINK KeyExpression) $(B :) $(GLINK ValueExpression) - -$(GNAME KeyExpression): - $(GLINK AssignExpression) - -$(GNAME ValueExpression): - $(GLINK AssignExpression) -) - - $(P Associative array literals are a comma-separated list of - $(I key):$(I value) pairs - between square brackets [ and ]. - The list cannot be empty. - The type of the first key is taken to be the type of - all the keys, and all subsequent keys are implicitly converted - to that type. - The type of the first value is taken to be the type of - all the values, and all subsequent values are implicitly converted - to that type. - An $(I AssocArrayLiteral) cannot be used to statically initialize - anything. - ) - ---- -[21u:"he",38:"ho",2:"hi"]; // type is char[2][uint], - // with keys 21u, 38u and 2u - // and values "he", "ho", and "hi" ---- - - $(P If any of the keys or values in the $(I KeyValuePairs) are - an $(I ExpressionTuple), then the elements of the $(I ExpressionTuple) - are inserted as arguments in place of the tuple. - ) - -

    Lambdas

    - -$(GRAMMAR -$(GNAME Lambda): - $(IDENTIFIER) $(B =>) $(GLINK AssignExpression) - $(GLINK ParameterAttributes) $(B =>) $(GLINK AssignExpression) -) - - $(P $(I Lambda)s are a shorthand syntax for $(GLINK FunctionLiteral)s. - The first form is equivalent to: - ) ---- -delegate ( $(IDENTIFIER) ) { return $(I AssignExpression); } ---- - - $(P And the second:) - ---- -delegate $(I ParameterAttributes) { return $(I AssignExpression); } ---- - -

    Function Literals

    - -$(GRAMMAR -$(GNAME FunctionLiteral): - $(B function) $(GLINK2 declaration, Type)$(OPT) $(GLINK ParameterAttributes) $(OPT) $(GLINK2 function, FunctionBody) - $(B delegate) $(GLINK2 declaration, Type)$(OPT) $(GLINK ParameterAttributes) $(OPT) $(GLINK2 function, FunctionBody) - $(GLINK ParameterAttributes) $(GLINK2 function, FunctionBody) - $(GLINK2 function, FunctionBody) - -$(GNAME ParameterAttributes): - $(GLINK2 declaration, Parameters) -$(V2 $(GLINK2 declaration, Parameters) $(GLINK2 declaration, FunctionAttributes)) -) - - $(I FunctionLiteral)s enable embedding anonymous functions - and anonymous delegates directly into expressions. - $(I Type) is the return type of the function or delegate, - if omitted it is inferred from any $(I ReturnStatement)s - in the $(I FunctionBody). - $(B $(LPAREN)) $(GLINK ArgumentList) $(B $(RPAREN)) - forms the arguments to the function. - If omitted it defaults to the empty argument list $(B ( )). - The type of a function literal is pointer to function or - pointer to delegate. - If the keywords $(B function) or $(B delegate) are omitted, - it defaults to being a delegate. -

    - - For example: - -------------- -int function(char c) fp; // declare pointer to a function - -void test() { - static int foo(char c) { return 6; } - - fp = &foo; -} -------------- - - is exactly equivalent to: - -------------- -int function(char c) fp; - -void test() { - fp = $(B function int(char c) { return 6;}) ; -} -------------- - - And: - -------------- -int abc(int delegate(long i)); - -void test() { - int b = 3; - int foo(long c) { return 6 + b; } - - abc(&foo); -} -------------- - - is exactly equivalent to: - -------------- -int abc(int delegate(long i)); - -void test() { - int b = 3; - - abc( $(B delegate int(long c) { return 6 + b; }) ); -} -------------- - - $(P and the following where the return type $(B int) is - inferred:) - -------------- -int abc(int delegate(long i)); - -void test() { - int b = 3; - - abc( $(B (long c) { return 6 + b; }) ); -} -------------- - - Anonymous delegates can behave like arbitrary statement literals. - For example, here an arbitrary statement is executed by a loop: - -------------- -double test() { - double d = 7.6; - float f = 2.3; - - void loop(int k, int j, void delegate() statement) { - for (int i = k; i < j; i++) { - statement(); - } - } - - loop(5, 100, $(B { d += 1; }) ); - loop(3, 10, $(B { f += 3; }) ); - - return d + f; -} -------------- - - When comparing with $(DDSUBLINK function, nested, nested functions), - the $(B function) form is analogous to static - or non-nested functions, and the $(B delegate) form is - analogous to non-static nested functions. In other words, - a delegate literal can access stack variables in its enclosing - function, a function literal cannot. - - -

    Assert Expressions

    - -$(GRAMMAR -$(GNAME AssertExpression): - $(B assert $(LPAREN)) $(GLINK AssignExpression) $(B $(RPAREN)) - $(B assert $(LPAREN)) $(GLINK AssignExpression) $(B ,) $(GLINK AssignExpression) $(B $(RPAREN)) -) - - $(P Asserts evaluate the $(I AssignExpression). - If it evaluates to a non-null class reference, the class invariant is run. - Otherwise, if it evaluates to a non-null pointer to a struct, the struct invariant is run. - Otherwise, if the result is false, - an $(B AssertError) is thrown. If the result is true, then no - exception is thrown. - It is an error if the $(I expression) contains any side effects - that the program depends on. The compiler may optionally not - evaluate assert expressions at all. - The result type of an assert expression is $(D void). - Asserts are a fundamental part of the - $(DDLINK dbc, Contract Programming, Contract Programming) - support in D. - ) - - $(P The expression $(D assert(0)) is a special case; it - signifies that it is unreachable code. - Either $(B AssertError) is thrown at runtime if it is reachable, - or the execution is halted - (on the x86 processor, a $(B HLT) instruction can be used to halt - execution). - The optimization and code generation phases of compilation may - assume that it is unreachable code. - ) - - $(P The second $(I AssignExpression), if present, must be implicitly - convertible to type $(V1 $(D char[]))$(V2 $(D const(char)[])). - It is evaluated if the - result is false, and the string result is appended to the - $(B AssertError)'s message. - ) - ----- -void main() { - assert(0, "an" ~ " error message"); -} ----- - - $(P When compiled and run, it will produce the message:) - -$(CONSOLE -Error: AssertError Failure test.d(3) an error message -) - - -

    Mixin Expressions

    - -$(GRAMMAR -$(GNAME MixinExpression): - $(B mixin $(LPAREN)) $(GLINK AssignExpression) $(B $(RPAREN)) -) - - $(P The $(I AssignExpression) must evaluate at compile time - to a constant string. - The text contents of the string must be compilable as a valid - $(I AssignExpression), and is compiled as such. - ) - ---- -int foo(int x) { - return mixin("x + 1") * 7; // same as ((x + 1) * 7) -} ---- - -

    Import Expressions

    - -$(GRAMMAR -$(GNAME ImportExpression): - $(B import $(LPAREN)) $(GLINK AssignExpression) $(B $(RPAREN)) -) - - $(P The $(I AssignExpression) must evaluate at compile time - to a constant string. - The text contents of the string are interpreted as a file - name. The file is read, and the exact contents of the file - become a string literal. - ) - - $(P Implementations may restrict the file name in order to avoid - directory traversal security vulnerabilities. - A possible restriction might be to disallow any path components - in the file name. - ) - ---- -void foo() { - // Prints contents of file foo.txt - write$(V1 f)ln( import("foo.txt") ); -} ---- - -

    Typeid Expressions

    - -$(GRAMMAR -$(GNAME TypeidExpression): - $(B typeid $(LPAREN)) $(GLINK2 declaration, Type) $(B $(RPAREN)) -$(V2 $(B typeid $(LPAREN)) $(GLINK Expression) $(B $(RPAREN))) -) - -$(V1 - $(P Returns an instance of class - $(DPLLINK phobos/object.html, $(B TypeInfo)) - corresponding - to $(I Type). - ) -) -$(V2 - $(P If $(I Type), returns an instance of class - $(DPLLINK phobos/object.html, $(B TypeInfo)) - corresponding - to $(I Type). - ) - - $(P If $(I Expression), returns an instance of class - $(DPLLINK phobos/object.html, $(B TypeInfo)) - corresponding - to the type of the $(I Expression). - If the type is a class, it returns the $(B TypeInfo) - of the dynamic type (i.e. the most derived type). - The $(I Expression) is always executed. - ) - ---- -class A { } -class B : A { } - -void main() { - writeln(typeid(int)); // int - uint i; - writeln(typeid(i++)); // uint - writeln(i); // 1 - A a = new B(); - writeln(typeid(a)); // B - writeln(typeid(typeof(a))); // A -} ---- -) - -

    IsExpression

    - -$(GRAMMAR -$(GNAME IsExpression): - $(B is $(LPAREN)) $(GLINK2 declaration, Type) $(B $(RPAREN)) - $(B is $(LPAREN)) $(GLINK2 declaration, Type) $(B :) $(GLINK TypeSpecialization) $(B $(RPAREN)) - $(B is $(LPAREN)) $(GLINK2 declaration, Type) $(B ==) $(GLINK TypeSpecialization) $(B $(RPAREN)) - $(B is $(LPAREN)) $(GLINK2 declaration, Type) $(IDENTIFIER) $(B $(RPAREN)) - $(B is $(LPAREN)) $(GLINK2 declaration, Type) $(IDENTIFIER) $(B :) $(GLINK TypeSpecialization) $(B $(RPAREN)) - $(B is $(LPAREN)) $(GLINK2 declaration, Type) $(IDENTIFIER) $(B ==) $(GLINK TypeSpecialization) $(B $(RPAREN)) - $(V2 $(B is $(LPAREN)) $(GLINK2 declaration, Type) $(IDENTIFIER) $(B :) $(GLINK TypeSpecialization) $(B ,) $(GLINK2 template, TemplateParameterList) $(B $(RPAREN)) - $(B is $(LPAREN)) $(GLINK2 declaration, Type) $(IDENTIFIER) $(B ==) $(GLINK TypeSpecialization) $(B ,) $(GLINK2 template, TemplateParameterList) $(B $(RPAREN)) -) - -$(GNAME TypeSpecialization): - $(GLINK2 declaration, Type) -$(V1 $(B typedef) -) $(B struct) - $(B union) - $(B class) - $(B interface) - $(B enum) - $(B function) - $(B delegate) - $(B super) -$(V2 $(B const) - $(B immutable) - $(B inout) - $(B shared) - $(B return) -)) - - $(I IsExpression)s are evaluated at compile time and are - used for checking for valid types, comparing types for equivalence, - determining if one type can be implicitly converted to another, - and deducing the subtypes of a type. - The result of an $(I IsExpression) is an int of type 0 - if the condition is not satisified, 1 if it is. -

    - - $(I Type) is the type being tested. It must be syntactically - correct, but it need not be semantically correct. - If it is not semantically correct, the condition is not satisfied. -

    - - $(IDENTIFIER) is declared to be an alias of the resulting - type if the condition is satisfied. The $(IDENTIFIER) forms - can only be used if the $(I IsExpression) appears in a - $(GLINK2 version, StaticIfCondition). -

    - - $(I TypeSpecialization) is the type that $(I Type) is being - compared against. -

    - - The forms of the $(I IsExpression) are: - - $(OL - - $(LI $(B is $(LPAREN)) $(I Type) $(B $(RPAREN))$(BR) - The condition is satisfied if $(I Type) is semantically - correct (it must be syntactically correct regardless). - -------------- -alias int func(int); // func is a alias to a function type -void foo() { - if ($(B is)(func[]) ) // not satisfied because arrays of - // functions are not allowed - write$(V1 f)ln("satisfied"); - else - write$(V1 f)ln("not satisfied"); - - if ($(B is)([][])) // error, [][] is not a syntactically valid type - ... -} -------------- - ) - - $(LI $(B is $(LPAREN)) $(I Type) $(B :) $(I TypeSpecialization) $(B $(RPAREN))
    - The condition is satisfied if $(I Type) is semantically - correct and it is the same as - or can be implicitly converted to $(I TypeSpecialization). - $(I TypeSpecialization) is only allowed to be a $(I Type). - -------------- -alias short bar; -void foo(bar x) { - if ( $(B is)(bar : int) ) // satisfied because short can be - // implicitly converted to int - write$(V1 f)ln("satisfied"); - else - write$(V1 f)ln("not satisfied"); -} -------------- - ) - - $(LI $(B is $(LPAREN)) $(I Type) $(B ==) $(I TypeSpecialization) $(B $(RPAREN))
    - The condition is satisfied if $(I Type) is semantically - correct and is the same type as $(I TypeSpecialization). -

    - - If $(I TypeSpecialization) is one of -$(V1 $(B typedef) -) $(B struct) - $(B union) - $(B class) - $(B interface) - $(B enum) - $(B function) - $(B delegate) -$(V2 $(B const) - $(B immutable) - $(B shared) -) - then the condition is satisifed if $(I Type) is one of those. - -------------- -alias short bar; -$(V1 typedef char foo;) -void test(bar x) { - if ( $(B is)(bar == int) ) // not satisfied because short is not - // the same type as int - write$(V1 f)ln("satisfied"); - else - write$(V1 f)ln("not satisfied"); -$(V1 - if ( $(B is)(foo == typedef) ) // satisfied because foo is a typedef - write$(V1 f)ln("satisfied"); - else - write$(V1 f)ln("not satisfied"); -)} -------------- - ) - - $(LI $(B is $(LPAREN)) $(I Type) $(I Identifier) $(B $(RPAREN))
    - The condition is satisfied if $(I Type) is semantically - correct. If so, $(I Identifier) - is declared to be an alias of $(I Type). - -------------- -alias short bar; -void foo(bar x) { - static if ( $(B is)(bar T) ) - alias T S; - else - alias long S; - - write$(V1 f)ln(typeid(S)); // prints "short" - if ( $(B is)(bar T) ) // error, $(I Identifier) T form can - // only be in $(GLINK2 version, StaticIfCondition)s - ... -} -------------- - ) - - $(LI $(B is $(LPAREN)) $(I Type) $(I Identifier) $(B :) $(I TypeSpecialization) $(B $(RPAREN))
    - - $(P - The condition is satisfied if $(I Type) is the same as - $(I TypeSpecialization), or if $(I Type) is a class and - $(I TypeSpecialization) is a base class or base interface - of it. - The $(I Identifier) is declared to be either an alias of the - $(I TypeSpecialization) or, if $(I TypeSpecialization) is - dependent on $(I Identifier), the deduced type. - ) - -------------- -alias int bar; -alias long* abc; -void foo(bar x, abc a) { - static if ( $(B is)(bar T : int) ) - alias T S; - else - alias long S; - - write$(V1 f)ln(typeid(S)); // prints "int" - - static if ( $(B is)(abc U : U*) ) - { - U u; - write$(V1 f)ln(typeid(typeof(u))); // prints "long" - } -} -------------- - - $(P The way the type of $(I Identifier) is determined is analogous - to the way template parameter types are determined by - $(GLINK2 template, TemplateTypeParameterSpecialization). - ) - ) - - $(LI $(B is $(LPAREN)) $(I Type) $(I Identifier) $(B ==) $(I TypeSpecialization) $(B $(RPAREN))
    - - - $(P The condition is satisfied if $(I Type) is semantically - correct and is the same as $(I TypeSpecialization). - The $(I Identifier) is declared to be either an alias of the - $(I TypeSpecialization) or, if $(I TypeSpecialization) is - dependent on $(I Identifier), the deduced type. - ) - - $(P If $(I TypeSpecialization) is one of -$(V1 $(B typedef) -) $(B struct) - $(B union) - $(B class) - $(B interface) - $(B enum) - $(B function) - $(B delegate) -$(V2 $(B const) - $(B immutable) - $(B shared) -) - then the condition is satisifed if $(I Type) is one of those. - Furthermore, $(I Identifier) is set to be an alias of the type: - ) - - $(TABLE1 - $(TR - $(TH keyword) - $(TH alias type for $(I Identifier)) - ) -$(V1 $(TR - $(TD $(CODE typedef)) - $(TD the type that $(I Type) is a typedef of) - ) -) - $(TR - $(TD $(CODE struct)) - $(TD $(I Type)) - ) - $(TR - $(TD $(CODE union)) - $(TD $(I Type)) - ) - $(TR - $(TD $(CODE class)) - $(TD $(I Type)) - ) - $(TR - $(TD $(CODE interface)) - $(TD $(I Type)) - ) - $(TR - $(TD $(CODE super)) - $(TD $(I TypeTuple) of base classes and interfaces) - ) - $(TR - $(TD $(CODE enum)) - $(TD the base type of the enum) - ) - $(TR - $(TD $(CODE function)) - $(TD $(I TypeTuple) of the function parameter types. - For C- and D-style variadic functions, - only the non-variadic parameters are included. - For typesafe variadic functions, the ... is ignored.) - ) - $(TR - $(TD $(CODE delegate)) - $(TD the function type of the delegate) - ) - $(TR - $(TD $(CODE return)) - $(TD the return type of the function, delegate, or function pointer) - ) -$(V2 - $(TR - $(TD $(CODE const)) - $(TD $(I Type)) - ) - $(TR - $(TD $(CODE immutable)) - $(TD $(I Type)) - ) - $(TR - $(TD $(CODE shared)) - $(TD $(I Type)) - ) -) - ) - -------------- -alias short bar; -enum E : byte { Emember } -void foo(bar x) { - static if ( $(B is)(bar T == int) ) // not satisfied, short is not int - alias T S; - alias T U; // error, T is not defined - - static if ( $(B is)(E V == enum) ) // satisified, E is an enum - V v; // v is declared to be a byte -} -------------- - -$(V1 - $(P For example, to test to see if $(CODE X) is a typedef and - its base type is int: - ) ---- -typedef int X; - -static if (is(X base == typedef)) { - static assert(is(base == int), "base of typedef X is not int"); -} -else { - static assert(0, "X is not a typedef"); -} ---- -) - ) - -$(V2 - $(LI $(B is $(LPAREN)) $(I Type) $(I Identifier) $(B :) $(I TypeSpecialization) $(B ,) $(GLINK2 template, TemplateParameterList) $(B $(RPAREN))$(BR) - $(B is $(LPAREN)) $(I Type) $(I Identifier) $(B ==) $(I TypeSpecialization) $(B ,) $(GLINK2 template, TemplateParameterList) $(B $(RPAREN)) - - $(P More complex types can be pattern matched; the - $(GLINK2 template, TemplateParameterList) declares symbols based on the - parts of the pattern that are matched, analogously to the - way implied template parameters are matched. - ) - ---- -import std.stdio; - -void main() { - alias long[char[]] AA; - - static if (is(AA T : T[U], U : const char[])) - { - write$(V1 f)ln(typeid(T)); // long - write$(V1 f)ln(typeid(U)); // const char[] - } - - static if (is(AA A : A[B], B : int)) - { - assert(0); // should not match, as B is not an int - } - - static if (is(int[10] W : W[V], int V)) - { - write$(V1 f)ln(typeid(W)); // int - write$(V1 f)ln(V); // 10 - } - - static if (is(int[10] X : X[Y], int Y : 5)) - { - assert(0); // should not match, Y should be 10 - } -} ---- - - ) -) - ) - - -

    Associativity and Commutativity

    - - $(P An implementation may rearrange the evaluation of expressions - according to arithmetic associativity and commutativity rules - as long as, within that thread of execution, no observable - difference is possible. - ) - - $(P This rule precludes any associative or commutative reordering of - floating point expressions.) -) - -Macros: - TITLE=Expressions - WIKI=Expression - IDENTIFIER=$(GLINK2 lex, Identifier) - CATEGORY_SPEC=$0 - FOO= - diff --git a/faq.dd b/faq.dd deleted file mode 100644 index 8e9dfb5efd..0000000000 --- a/faq.dd +++ /dev/null @@ -1,900 +0,0 @@ -Ddoc - -$(D_S $(TITLE), - - $(P The same questions keep cropping up, so the obvious thing to do is - prepare a FAQ.) - - $(P $(LINK2 http://www.digitalmars.com/d/1.0/faq.html, D 1.0 FAQ)) - $(P $(LINK2 http://www.digitalmars.com/faq.html, C++ FAQ)) - -

    D 2.0 FAQ

    - - $(UL - $(LI $(LINK2 features2.html, What's the difference between D 2.0 and D 1.0?)) - - $(LI Where is my simple language?) - - $(REDO $(LI $(LINK2 cpp0x.html, What's D 2.0's answer to C++0x's proposed new features?))) - - $(LI What other cool features are in the plans for D 2.0?) - - $(LI I suggested a great feature. Why was the suggestion ignored?) - - $(LI Why const and immutable?) - - $(LI Why the $(I names) const and immutable?) - - $(LI How exactly is immutable related to multicores?) - - $(LI Ok, I'm fine with immutable for safe data sharing among threads. But why do we need the uninformative const?) - - $(LI Why are immutable strings favored in D 2.0?) - - $(LI I want to contribute to D 2.0. How can I effect that?) - - $(ITEMR case_range, Why doesn't the case range statement - use the $(D case X..Y:) syntax?) - - $(ITEMR shared_guarantees, What guarantees is shared supposed to provide?) - - $(ITEMR shared_synchronized, What does shared have to do with synchronization?) - - $(ITEMR shared_memory_barriers, What does shared have to do with memory barriers?) - - $(ITEMR casting_to_shared, What are the semantics of casting FROM unshared TO shared?) - - $(ITEMR casting_from_shared, What are the semantics of casting FROM shared TO unshared?) - - $(ITEMR bss, Why does a large static array bloat my executable file size?) - ) - -

    General D FAQ

    - - $(UL - - $(LI $(LINK2 http://www.prowiki.org/wiki4d/wiki.cgi?FaqRoadmap, The D wiki FAQ page) - with many more questions answered) - $(LI $(LINK2 comparison.html, What does D have that C++ doesn't?)) - $(ITEMR q1, Why the name D?) - $(LI $(LINK2 http://www.digitalmars.com/d/download.html, Where can I get a D compiler?)) - $(ITEMR q1_2, Is there linux port of D?) - $(ITEMR gdc, Is there a GNU version of D?) - $(ITEMR backend, How do I write my own D compiler for CPU X?) - $(ITEMR gui, Where can I get a GUI library for D?) - $(ITEMR ide, Where can I get an IDE for D?) - $(ITEMR q3, Why emphasize implementation ease?) - $(ITEMR q4, Why is [expletive deleted] printf left in?) - $(ITEMR q5, Will D be open source?) - $(ITEMR q6, Why $(I no) fall through on switch statements?) - $(ITEMR q7, Why should I use D instead of Java?) - $(ITEMR q7_2, Doesn't C++ support strings, etc. with STL?) - $(ITEMR q7_3, Can't garbage collection be done in C++ with an add-on library?) - $(ITEMR q7_4, Can't unit testing be done in C++ with an add-on library?) - $(ITEMR q8, Why have an asm statement in a portable language?) - $(ITEMR real, What is the point of 80 bit reals?) - $(ITEMR anonymous, How do I do anonymous struct/unions in D?) - $(ITEMR printf, How do I get printf() to work with strings?) - $(ITEMR nan, Why are floating point values default initialized to NaN rather than 0?) - $(ITEMR assignmentoverloading, Why is overloading of the assignment operator not supported?) - $(ITEMR keys, The $(SINGLEQUOTE ~) is not on my keyboard?) - $(ITEMR omf, Can I link in C object files created with another compiler?) - $(ITEMR regexp_literals, Why not support regular expression literals - with the /foo/g syntax?) - $(ITEMR dogfood, Why is the D front end written in C++ rather than D?) - $(ITEMR cpp_to_D, Why aren't all Digital Mars programs translated to D?) - $(ITEMR foreach, When should I use a foreach loop rather than a for?) - $(ITEMR cpp_interface, Why doesn't D have an interface to C++ as well as C?) - $(ITEMR reference-counting, Why doesn't D use reference counting for garbage collection?) - $(ITEMR gc_1, Isn't garbage collection slow and non-deterministic?) - $(ITEMR pure, Can't a sufficiently smart compiler figure out that a function is pure automatically?) - ) - -$(ITEM case_range, Why doesn't the case range statement - use the $(D case X..Y:) syntax?) - - $(P See the $(LINK2 statement.html#CaseRangeStatement, case range statement).) - - $(P The usages of .. would then be: - $(OL - $(LI $(D case X..Y:)) - $(LI $(D foreach(e; X..Y))) - $(LI $(D array[X..Y])) - ) - Case (1) has a VERY DIFFERENT meaning from (2) and (3). - (1) is inclusive of Y, and (2) and (3) are exclusive of Y. - Having a very different meaning means it should have a distinctly different syntax. - ) - -$(ITEM shared_guarantees, What guarantees is shared supposed to provide?) - - $(P Shared means that multiple threads can access the data. The guarantee is that if it is - not shared, and not immutable, that only the current thread can see it. - ) - -$(ITEM shared_synchronized, What does shared have to do with synchronization?) - - $(P Only shared data can be synchronized. It makes no sense to synchronize thread local - data. - ) - -$(ITEM shared_memory_barriers, What does shared have to do with memory barriers?) - - $(P Reading/writing shared data emits memory barriers to ensure sequential consistency (not - implemented). - ) - -$(ITEM casting_to_shared, What are the semantics of casting FROM unshared TO shared?) - - $(P Make sure there are no other unshared references to that same data. - ) - -$(ITEM casting_from_shared, What are the semantics of casting FROM shared TO unshared?) - - $(P Make sure there are no other shared references to that same data. - ) - -$(ITEM bss, Why does a large static array bloat my executable file size?) - - $(P Given the declaration:) ---- -char[1024 * 1024] arr; ---- - $(P the executable size increases by a megabyte in size. In C, this would not - as $(CODE arr) would be stored in the BSS segment. - In D, $(CODE arr) is not stored in the BSS segment because: - ) - - $(UL - $(LI The $(CODE char) type is initialized to 0xFF, not 0. Non-zero data - cannot be placed in BSS.) - $(LI Statically allocated data is placed in thread local storage. The BSS - segment is not thread local, and there is no thread local equivalent of BSS.) - ) - - $(P The following will be placed in BSS:) - ---- -__gshared byte[1024 * 1024] arr; ---- - - $(P as $(CODE byte)s are 0 initialized and $(CODE __gshared) puts it in the - global data.) - - $(P There are similiar issues for $(CODE float), $(CODE double), and $(CODE real) - static arrays. They are initialized to NaN (Not A Number) values, not 0. - ) - - $(P The easiest way to deal with this issue is to allocate the array dynamically - at run time rather than statically allocate it. - ) - -$(ITEM q1, Why the name D?) - - $(P The original name was the Mars Programming Language. But my friends - kept calling it D, and I found myself starting to call it D. - The idea of D being a successor to C goes back at least as far as 1988, - as in this - $(LINK2 http://groups.google.com/group/comp.lang.c/browse_thread/thread/cb4b868fab477b61/d4b5407644d16806, thread). - ) - -$(ITEM q1_2, Is there a linux port of D?) - - $(P Yes, the D compiler includes a $(LINK2 dmd-linux.html, linux version). - ) - -$(ITEM gdc, Is there a GNU version of D?) - - $(P Yes, - $(LINK2 http://bitbucket.org/goshawk/gdc/wiki/Home, gdc - the D frontend with GCC). - ) - -$(ITEM backend, How do I write my own D compiler for CPU X?) - - $(P Burton Radons has written a - $(LINK2 http://www.opend.org/dli/DLinux.html, back end). - You can use as a guide. - ) - -$(ITEM gui, Where can I get a GUI library for D?) - - $(P Since D can call C functions, any GUI library with a C interface is - accessible from D. Various D GUI libraries and ports can be found at - $(LINK2 http://www.prowiki.org/wiki4d/wiki.cgi?GuiLibraries, the D wiki). - ) - -$(ITEM ide, Where can I get an IDE for D?) - - $(P A list of IDEs and editors that support D can be found on - $(LINK2 http://prowiki.org/wiki4d/wiki.cgi?EditorSupport, the D wiki). - ) - -$(ITEM q3, Why emphasize implementation ease?) - - $(P Isn't ease of use for the user of the language more important? Yes, - it is. - But a vaporware language is useless to everyone. The easier a language - is to implement, the more robust implementations there will be. In C's - heyday, there were 30 different commercial C compilers for the IBM PC. - Not many made the transition to C++. In looking at - the C++ compilers on the market today, how many years of development - went into each? At least 10 years? Programmers waited years - for the various pieces of C++ to get implemented after they were - specified. - If C++ was not so enormously popular, it's doubtful that very complex - features - like multiple inheritance, templates, etc., would ever have been - implemented. - ) - - $(P I suggest that if a language is easier to implement, then it is - likely also easier to understand. Isn't it better to spend time learning - to write better programs than language arcana? If a language can capture - 90% of the power of - C++ with 10% of its complexity, I argue that is a worthwhile tradeoff. - ) - - -$(ITEM q4, Why is printf in D?) - - $(P $(LINK2 http://www.digitalmars.com/rtl/stdio.html#printf, printf) - is not part of D, it is part of C's standard - runtime library which is accessible from D. - D's standard runtime library has - $(LINK2 http://www.d-programming-language.org/phobos/std_stdio.html#writefln, std.stdio.writefln), - which is as powerful as $(LINK2 http://www.digitalmars.com/rtl/stdio.html#printf, printf) - but is much easier to use. - ) - - -$(ITEM q5, Will D be open source?) - - $(P The front end for the $(B dmd) D compiler is open source, and the complete - source comes with the - $(LINK2 http://www.digitalmars.com/d/download.html, compiler), - and is available on $(LINK2 https://github.com/D-Programming-Language/dmd, github). - The back end for dmd is licensed from Symantec. - The runtime library is completely open source using the - $(LINK2 http://boost.org/LICENSE_1_0.txt, Boost License 1.0). - The $(B gdc) and $(B ldc) D compilers are completely open sourced. - ) - -$(ITEM q6, Why $(I no) fall through on switch statements?) - - $(P Many people have asked for a requirement that there be a break between - cases in a switch statement, that C's behavior of silently falling through - is the cause of many bugs. - ) - - $(P In D2, implicit fall through is disallowed. You have to add a - $(LINK2 statement.html#GotoStatement, goto case;) statement to explicitly - state the intention of falling through. - ) - - $(P There was further request that the $(B break) statement be made - implicit. - The reason D doesn't change this is for the same reason that integral - promotion rules and operator precedence rules were kept the same - to - make code that looks the same as in C operate the same. If it had subtly - different semantics, it will cause frustratingly subtle bugs. - ) - - -$(ITEM q7, Why should I use D instead of Java?) - - $(P D is distinct from Java in purpose, philosophy and reality. - See this $(LINK2 comparison.html, comparison). - ) - - $(P Java is designed to be write once, run everywhere. D is designed for writing - efficient native system apps. Although D and Java share the notion that - garbage collection is good and multiple inheritance is bad, their - different design goals mean the languages have very different feels. - ) - -$(ITEM q7_2, Doesn't C++ support strings, etc. with STL?) - - $(P In the C++ standard library are mechanisms for doing strings, - dynamic arrays, associative arrays, and bounds-checked - arrays. - ) - - $(P Sure, all this stuff can be done with libraries, - following certain coding disciplines, etc. But - object oriented programming can also be done in C (it's been done). - Isn't it incongruous that something like strings, - supported by the simplest BASIC interpreter, requires a very - large and complicated infrastructure to support? - Just the implementation of a string type in STL is over two - thousand lines of code, using every advanced feature of templates. - How much confidence can you have that this is all working - correctly, how do you fix it if it is not, what do you do with the - notoriously inscrutable error messages when there's an error - using it, how can you be sure you are using it correctly - (so there are no memory leaks, etc.)? - ) - - $(P D's implementation of strings is simple and straightforward. - There's little doubt about how to use it, no worries about memory leaks, - error messages are to the point, and it isn't hard to see if it - is working as expected or not. - ) - -$(ITEM q7_3, Can't garbage collection be done in C++ with an add-on library?) - - Yes, I use one myself. It isn't part of the language, though, and - requires some subverting of the language to make it work. - Using gc with C++ isn't for the standard or casual C++ programmer. - Building it into the - language, like in D, makes it practical for everyday programming chores. -

    - - GC isn't that hard to implement, either, unless you're building one - of the more advanced ones. But a more advanced one is like building - a better optimizer - the language still works 100% correctly even - with a simple, basic one. The programming community is better served - by multiple implementations competing on quality of code generated - rather than by which corners of the spec are implemented at all. - -$(ITEM q7_4, Can't unit testing be done in C++ with an add-on library?) - - Sure. Try one out and then compare it with how D does it. - It'll be quickly obvious what an improvement building it into - the language is. - -$(ITEM q8, Why have an asm statement in a portable language?) - - An asm statement allows assembly code to be inserted directly into a D - function. Assembler code will obviously be inherently non-portable. D is - intended, however, to be a useful language for developing systems apps. - Systems apps almost invariably wind up with system dependent code in them - anyway, inline asm isn't much different. Inline asm will be useful for - things like accessing special CPU instructions, accessing flag bits, special - computational situations, and super optimizing a piece of code. -

    - - Before the C compiler had an inline assembler, I used external assemblers. - There was constant grief because many, many different versions of the - assembler were out there, the vendors kept changing the syntax of the - assemblers, there were many different bugs in different versions, and even - the command line syntax kept changing. What it all meant was that users - could not reliably rebuild any code that needed assembler. An inline - assembler provided reliability and consistency. - -$(ITEM real, What is the point of 80 bit reals?) - - More precision enables more accurate floating point computations - to be done, especially when adding together large numbers of small - real numbers. Prof. Kahan, who designed the Intel floating point - unit, has an eloquent - paper - on the subject. - -$(ITEM anonymous, How do I do anonymous struct/unions in D?) - ------------------------ -import std.stdio; - -struct Foo -{ - union { int a; int b; } - struct { int c; int d; } -} - -void main() -{ - writefln( - "Foo.sizeof = %d, a.offset = %d, b.offset = %d, c.offset = %d, d.offset = %d", - Foo.sizeof, - Foo.a.offsetof, - Foo.b.offsetof, - Foo.c.offsetof, - Foo.d.offsetof); -} ------------------------ - -$(ITEM printf, How do I get printf() to work with strings?) - - In C, the normal way to printf a string is to use the $(B %s) - format: - -$(CCODE -char s[8]; -strcpy(s, "foo"); -printf("string = '$(B %s)'\n", s); -) - - Attempting this in D, as in: - ---------------------------------- -char[] s; -s = "foo"; -printf("string = '$(B %s)'\n", s); ---------------------------------- - - usually results in garbage being printed, or an access violation. - The cause is that in C, strings are terminated by a 0 character. - The $(B %s) format prints until a 0 is encountered. - In D, strings are not 0 terminated, the size is determined - by a separate length value. So, strings are printf'd using the - $(B %.*s) format: - ---------------------------------- -char[] s; -s = "foo"; -printf("string = '$(B %.*s)'\n", s); ---------------------------------- - - $(P which will behave as expected. - Remember, though, that printf's $(B %.*s) will print until the length - is reached or a 0 is encountered, so D strings with embedded 0's - will only print up to the first 0. - ) - - $(P Of course, the easier solution is just use $(B std.stdio.writefln) - which works correctly with D strings. - ) - -$(ITEM nan, Why are floating point values default initialized to NaN rather than 0?) - - A floating point value, if no explicit initializer is given, - is initialized to NaN (Not A Number): - ---------------------------------- -double d; // d is set to double.nan ---------------------------------- - - NaNs have the interesting property in that whenever a NaN is - used as an operand in a computation, the result is a NaN. Therefore, - NaNs will propagate and appear in the output whenever a computation - made use of one. This implies that a NaN appearing in the output - is an unambiguous indication of the use of an uninitialized - variable. -

    - - If 0.0 was used as the default initializer for floating point - values, its effect could easily be unnoticed in the output, and so - if the default initializer was unintended, the bug may go - unrecognized. -

    - - The default initializer value is not meant to be a useful value, - it is meant to expose bugs. Nan fills that role well. -

    - - But surely the compiler can detect and issue an error message - for variables used that are not initialized? Most of the time, - it can, but not always, and what it can do is dependent on the - sophistication of the compiler's internal data flow analysis. - Hence, relying on such is unportable and unreliable. -

    - - Because of the way CPUs are designed, there is no NaN value for - integers, so D uses 0 instead. It doesn't have the advantages of - error detection that NaN has, but at least errors resulting from - unintended default initializations will be consistent and therefore more - debuggable. - -$(ITEM assignmentoverloading, Why is overloading of the assignment operator not supported?) - - $(P Overloading of the assignment operator for structs is supported - in D 2.0.) - -$(ITEM keys, The $(SINGLEQUOTE ~) is not on my keyboard?) - - $(P On PC keyboards, hold down the [Alt] key and press the 1, 2, and 6 - keys in sequence on the numeric pad. That will generate a $(SINGLEQUOTE ~) - character. - ) - -$(ITEM omf, Can I link in C object files created with another compiler?) - - - DMD produces OMF (Microsoft Object Module Format) object - files while other compilers such as VC++ produce COFF object - files. - DMD's output is designed to work with DMC, the Digital Mars C - compiler, which also produces object files in OMF format. -

    - - The OMF format that DMD uses is a Microsoft defined format based on an - earlier Intel designed one. Microsoft at one point decided to abandon it - in favor of a Microsoft defined variant on COFF. -

    - - Using the same object format doesn't mean that any C library in that - format will successfully link and run. There is a lot more compatibility - required - such as calling conventions, name mangling, compiler helper - functions, and hidden assumptions about the way things work. If DMD - produced Microsoft COFF output files, there is still little chance that - they would work successfully with object files designed and tested for - use with VC. There were a lot of problems with this back when - Microsoft's compilers did generate OMF. -

    - - Having a different object file format makes it helpful in identifying - library files that were not tested to work with DMD. If they are not, - weird problems would result even if they successfully managed to link - them together. It really takes an expert to get a binary built with a - compiler from one vendor to work with the output of another vendor's - compiler. -

    - - That said, the linux version of DMD produces object files in the ELF - format which is standard on linux, and it is specifically designed to - work with the standard linux C compiler, gcc. -

    - - There is one case where using existing C libraries does work - when - those libraries come in the form of a DLL conforming to the usual C ABI - interface. The linkable part of this is called an "import library", and - Microsoft COFF format import libraries can be successfully converted to - DMD OMF using the - coff2omf - tool. - -$(ITEM regexp_literals, Why not support regular expression literals - with the $(D /foo/g) syntax?) - - $(P There are two reasons: - ) - - $(OL - - $(LI The $(D /foo/g) syntax would make it impossible to separate - the lexer from the parser, as / is the divide token.) - - $(LI There are already 3 string types; adding the regex literals - would add 3 more. This would proliferate through much of the compiler, - debugger info, and library, and is not worth it.) - - ) - -$(ITEM dogfood, Why is the D front end written in C++ rather than D?) - - $(P The front end is in C++ in order to interface to the existing gcc - and dmd back ends. - It's also meant to be easily interfaced to other existing back ends, - which are likely written in C++. - The D implementation of - $(LINK2 http://www.digitalmars.com/dscript/index.html, DMDScript), - which performs better than the - $(LINK2 http://www.digitalmars.com/dscript/cppscript.html, C++ version), - shows that there is no problem - writing a professional quality compiler in 100% D. - ) - -$(ITEM cpp_to_D, Why aren't all Digital Mars programs translated to D?) - - $(P There is little benefit to translating a complex, debugged, working - application from one language to another. But new Digital Mars apps are - implemented in D.) - - -$(ITEM foreach, When should I use a foreach loop rather than a for?) - - $(P Is it just performance or readability? - ) - - $(P By using foreach, you are letting the compiler decide on the - optimization rather than worrying about it yourself. For example - are - pointers or indices better? - Should I cache the termination condition or not? - Should I rotate the loop or not? - The answers to these questions are not easy, and can vary from machine - to machine. Like register assignment, let the compiler do the - optimization.) - ---- -for (int i = 0; i < foo.length; i++) ---- - -or: - ---- -for (int i = 0; i < foo.length; ++i) ---- - -or: - ---- -for (T* p = &foo[0]; p < &foo[length]; p++) ---- - -or: - ---- -T* pend = &foo[length]; -for (T* p = &foo[0]; p < pend; ++p) ---- - -or: - ---- -T* pend = &foo[length]; -T* p = &foo[0]; -if (p < pend) -{ - do - { - ... - } while (++p < pend); -} ---- - -and, of course, should I use size_t or int? - ---- -for (size_t i = 0; i < foo.length; i++) ---- - -Let the compiler pick! - ---- -foreach (v; foo) - ... ---- - -$(P Note that we don't even need to know what the type T needs to be, thus -avoiding bugs when T changes. I don't even have to know if foo is an array, or -an associative array, or a struct, or a collection class. This will also avoid -the common fencepost bug:) - ---- -for (int i = 0; i <= foo.length; i++) ---- - -$(P And it also avoids the need to manually create a temporary if foo is a -function call.) - -$(P The only reason to use a for loop is if your loop does not fit in the -conventional form, like if you want to change -the termination condition on the fly.) - - -$(ITEM cpp_interface, Why doesn't D have an interface to C++ as well as C?) - -$(V2 - $(P D 2.0 does have a - $(LINK2 cpp_interface.html, limited interface to C++ code.) - ) Here are some reasons why it isn't a full interface: -) - - $(P Attempting to have D interface with C++ is - nearly as complicated as writing a C++ compiler, which would destroy the - goal of having D be a reasonably easy language to implement. - For people with an existing C++ code base that they must work with, they are - stuck with C++ (they can't move it to any other language, either).) - - $(P There are many issues that would have to be resolved in order for D - code to call some arbitrary C++ code that is presumed to be unmodifiable. This - list certainly isn't complete, it's just to show the scope of the - difficulties involved. - ) - - $(OL - $(LI D source code is unicode, C++'s is ASCII with code pages. Or not. - It's unspecified. This impacts the contents of string literals.) - - $(LI std::string cannot deal with multibyte UTF.) - - $(LI C++ has a tag name space. D does not. Some sort of renaming would - have to happen.) - - $(LI C++ code often relies on compiler specific extensions.) - - $(LI C++ has namespaces. D has modules. There is no obvious mapping - between the two.) - - $(LI C++ views source code as one gigantic file (after preprocessing). D - sees source code as a hierarchy of modules and packages.) - - $(LI Enum name scoping rules behave differently.) - - $(LI C++ code, despite decades of attempts to replace macro features - with inbuilt ones, relies more heavily than ever on layer after layer of - arbitrary macros. There is no D analog for token pasting or - stringizing.) - - $(LI Macro names have global scope across #include files, but are local - to the gigantic source files.) - - $(LI C++ has arbitrary multiple inheritance and virtual base classes. D - does not.) - - $(LI C++ does not distinguish between in, out and ref (i.e. inout) parameters.) - - $(LI The C++ name mangling varies from compiler to compiler.) - - $(LI C++ throws exceptions of arbitrary type, not just descendants of - Object.) - - $(LI C++ overloads based on const and volatile. D overloads - based on const and immutable.) - - $(LI C++ overloads operators in significantly different ways - for - example, operator[]() overloading for lvalue and rvalue is based on - const overloading and a proxy class.) - - $(LI C++ overloads operators like < completely independently of - >.) - - $(LI C++ does not distinguish between a class and a struct object.) - - $(LI The vtbl[] location and layout is different between C++ and D.) - - $(LI The way RTTI is done is completely different. C++ has no - classinfo.) - - $(LI D does not have two phase lookup, nor does it have Koenig (ADL) - lookup.) - - $(LI C++ relates classes with the 'friend' system, D uses packages and - modules.) - - $(LI C++ class design tends to revolve around explicit memory allocation - issues, D's do not.) - - $(LI D's template system is very different.) - - $(LI C++ has 'exception specifications'.) - - $(LI C++ has global operator overloading.) - - $(LI C++ name mangling depends on const and volatile being type - modifiers. - D name mangling depends on const and immutable being type modifiers. - D's const is also transitive, unlike C++. One cannot have a const - pointer to mutable in D. - ) - - ) - - $(P The bottom line is the language features affect the design of the code. C++ - designs just don't fit with D. Even if you could find a way to automatically - adapt between the two, the result will be about as enticing as the left side of - a honda welded to the right side of a camaro. - ) - -$(ITEM reference-counting, Why doesn't D use reference counting for garbage collection?) - - $(P Reference counting has its advantages, but some severe - disadvantages: - ) - - $(UL - - $(LI Cyclical data structures won't get freed.) - - $(LI Every pointer copy requires an increment and a corresponding - decrement - including when simply passing a reference to a function.) - - $(LI In a multithreaded app, the incs and decs must be synchronized.) - - $(LI Exception handlers (finally blocks) must be inserted to handle all the - decs so there are no leaks. Contrary to assertions otherwise, there is - no such thing as "zero overhead exceptions.") - - $(LI In order to support slicing and interior pointers, as well as - supporting reference counting on arbitrary allocations of non-object - data, a separate "wrapper" object must be allocated for each allocation - to be ref counted. This essentially doubles the number of allocations - needed.) - - $(LI The wrapper object will mean that all pointers will need to be - double-dereferenced to access the data.) - - $(LI Fixing the compiler to hide all this stuff from the programmer will - make it difficult to interface cleanly with C.) - - $(LI Ref counting can fragment the heap thereby consuming more memory - just like the gc can, though the gc typically will consume more memory - overall.) - - $(LI Ref counting does not eliminate latency problems, it just reduces - them.) - - ) - - $(P The proposed C++ shared_ptr<>, which implements ref counting, - suffers from all these faults. I haven't seen a heads up benchmark of - shared_ptr<> vs mark/sweep, but I wouldn't be surprised if shared_ptr<> - turned out to be a significant loser in terms of both performance and - memory consumption. - ) - - $(P That said, D may in the future optionally support some form of ref - counting, as rc is better for managing scarce resources like file - handles. - Furthermore, if ref counting is a must, Phobos has the - $(LINK2 phobos/std_typecons.html#RefCounted, std.typecons.RefCounted) type - which implements it as a library, similar to C++'s shared_ptr<>. - ) - -$(ITEM gc_1, Isn't garbage collection slow and non-deterministic?) - - $(P Yes, but $(B all) dynamic memory management is slow and - non-deterministic, including malloc/free. - If you talk to the people who actually do real time - software, they don't use malloc/free precisely because they are not - deterministic. They preallocate all data. - However, the use of GC instead of malloc enables advanced language - constructs (especially, more powerful array syntax), which greatly - reduce the number of memory allocations which need to be made. - This can mean that GC is actually faster than explict management. - ) - -$(ITEM pure, Can't a sufficiently smart compiler figure out that a function is pure automatically?) - - $(P The problems with the - $(LINK2 http://c2.com/cgi/wiki?SufficientlySmartCompiler, sufficently smart compiler) - argument are: - ) - - $(OL - $(LI most functions call other functions, which call other functions, - until one of them calls a library routine whose source is not available - to the compiler. So it will have to assume it is not pure. - With a pure function attribute, external library functions that are pure - can be marked as pure, and then the analysis can work for enough cases - to be useful. - ) - - $(LI Since virtual functions (and by extension delegates and function - pointers) can be extended by the user at times the compiler won't see - it, they have to be assumed to be impure. - ) - - $(LI If the programmer intends for a particular function to be pure - and the compiler detects it is not, this may go unnoticed by the - programmer. Even worse, if the programmer does notice it, it may - be arbitrarily difficult to determine why the compiler thinks it is - impure - is it a programming mistake or a compiler bug? - ) - - ) - -$(COMMENT - > Single inheritance may be easier to implement, but you are losing - >something. It's a little concerning how often folks here take the - >opinion that "Feature X has problems and I never use it anyway, so no - >body else 'really' needs it." I'm not specificly blaming you, but i've - >lost track of how many time if seen that reasoning tonight. I'm afraid - >I'll see it a lot in the 275 I still have to read. - - - Your reasoning has merit. The counterargument (and I've discussed - this at length with my colleagues) is that C++ gives you a dozen ways - and styles to do X. Programmers tend to develop specific styles and do - things in certain ways. This leads to one programmer's use of C++ to - be radically different than another's, almost to the point where - they are different languages. C++ is a huge language, and C++ - programmers tend to learn particular "islands" in the language - and not be too familiar with the rest of it. - - Hence one idea behind D is to *reduce* the number of ways X can be - accomplished, and reduce the balkanization of programmer expertise. - Then, one programmer's coding style will look more like another's, - with the intended result that legacy D code will be more maintainable. - For example, over the years I've seen dozens of different ways that - debug code was inserted into a program, all very different. D has one - way - with the debug attribute/statement. C++ has a dozen string - classes plus the native C way of doing strings. D has one way of - doing strings. - - I intend to further help this along by writing a D style guide, - "The D Way". There's a start on it all ready with the document - on how to do error handling: - - www.digitalmars.com/d/errors.html - -) - -) - -Macros: - TITLE=D 2.0 FAQ - WIKI=FAQ - CATEGORY_FAQ=$0 - ITEMR=$(LI $(LINK2 #$1, $+)) - ITEM=


    $+

    diff --git a/favicon.ico b/favicon.ico index 906a008cb0..3ead32d9b4 100644 Binary files a/favicon.ico and b/favicon.ico differ diff --git a/features2.dd b/features2.dd deleted file mode 100644 index 8c96da73b1..0000000000 --- a/features2.dd +++ /dev/null @@ -1,112 +0,0 @@ -Ddoc - -$(D_S D 2.0 Enhancements from D 1.0, - - $(P D 2.0 has many substantial language and library enhancements - compared with D 1.0. - This list does not include $(LINK2 changelog.html, bug fixes) - or $(LINK2 http://www.digitalmars.com/d/1.0/changelog.html, changes that were also made to D 1.0). - See the $(LINK2 D1toD2.html, D1 to D2 Migration Guide) for help - in converting source code. - ) - -$(SECTION2 Core Language Changes, - -$(UL - $(LI $(CODE opAssign) can no longer be overloaded for class objects.) - $(LI Added $(CODE pure) keyword.) - $(LI Extended $(LINK2 enum.html, enums) to allow declaration - of manifest constants.) - $(LI Added $(LINK2 struct.html#ConstStruct, const/immutable structs), - $(LINK2 class.html#ConstClass, classes) and - $(LINK2 interface.html#ConstInterface, interfaces).) - $(LI Added $(CODE const) and $(CODE immutable) to $(LINK2 expression.html#IsExpression, $(I IsExpression))s.) - $(LI Added $(CODE typeof(return)) type specifier.) - $(LI Added overloadable unary * operation as $(CODE opStar()).) - $(LI Full closure support added.) - $(LI Transformed all of $(CODE string), $(CODE wstring), - and $(CODE dstring) into immutable definitions). - $(LI Added $(LINK2 function.html#overload-sets, Overload Sets) for functions and templates.) - $(LI $(D std.math.sin), $(D cos), $(D tan) are now evaluated at - compile time if the argument is a constant.) - $(LI Added $(LINK2 cpp_interface.html, C++ interface) for $(SINGLEQUOTE plugins).) - $(LI Changed result type of - $(LINK2 expression.html#IsExpression, $(I IsExpression)) - from $(CODE int) to $(CODE bool).) - $(LI Added optional $(I TemplateParameterList) to $(LINK2 expression.html#IsExpression, $(I IsExpression)).) - $(LI Added warning when $(CODE override) is omitted.) - $(LI Added new syntax for string literals (delimited, heredoc, D tokens)) - $(LI Added $(CODE __EOF__) token) - $(LI Added $(LINK2 version.html#PredefinedVersions, $(B D_Version2)) - predefined identifier to indicate this is a D version 2.0 compiler) - $(LI Added $(CODE .idup) property for arrays to create immutable - copies.) - $(LI Added transitive const and immutable.) - $(LI $(CODE in) parameter storage class now means scope const.) - $(LI class and struct invariant declarations now must have a ().) - $(LI Added $(CODE isSame) and $(CODE compiles) to $(D_KEYWORD __traits).) - $(LI Added $(LINK2 statement.html#ForeachRangeStatement, ForeachRangeStatement)). -) - -) - -$(SECTION2 Phobos Library Changes, - -$(UL - $(LI $(LINK2 phobos/std_algorithm.html, std.algorithm): new module) - $(LI std.bitarray: scheduled for deprecation) - $(LI $(LINK2 phobos/std_bitmanip.html, std.bitmanip): new module with the content of std.bitarray plus the bitfields, FloatRep, and DoubleRep templates) - $(LI $(LINK2 phobos/std_contracts.html, std.contracts): new module) - $(LI $(LINK2 phobos/std_conv.html, std.conv): - Added $(CODE parse) and $(CODE assumeUnique). - Made $(CODE conv_error) a template parameterized on the types being - converted. - Massive additions.) - $(LI $(LINK2 phobos/std_file.html, std.file): added $(CODE dirEntries).) - $(LI $(LINK2 phobos/std_format.html, std.format): - Added raw ('r') format specifier for writef*.) - $(LI $(LINK2 phobos/std_functional.html, std.functional): new module) - $(LI $(LINK2 phobos/std_getopt.html,std.getopt): new module.) - $(LI std.hiddenfunc: new module) - $(LI $(LINK2 phobos/std_math.html, std.math): Made nextafter visible for all floating types. Added approxEqual template.) - $(LI $(LINK2 phobos/std_numeric.html, std.numeric): new module) - $(LI $(LINK2 phobos/std_path.html, std.path): - Added $(CODE rel2abs) (Linux version only). - Added the basename and dirname functions (which alias the - less gainful names getBaseName and getDirectoryName)) - $(LI $(LINK2 phobos/std_process.html, std.process): - Made getpid visible in Linux builds) - $(LI $(LINK2 phobos/std_stdio.html, std.stdio): - Added $(CODE writeln()) and $(CODE write()), - $(CODE writef()) can now only accept a format as its first argument. - Added optional terminator to $(CODE readln). - Added functions $(CODE fopen), $(CODE popen), - $(CODE lines) and $(CODE chunks).) - $(LI $(LINK2 phobos/std_string.html, std.string): - Added munch function and added function chompPrefix.) - $(LI $(LINK2 phobos/std_random.html, std.random): - Major addition of engines and distributions.) - $(LI $(LINK2 phobos/std_traits.html, std.traits): new module) - $(LI $(LINK2 phobos/std_typecons.html, std.typecons): new module) - $(LI $(LINK2 phobos/std_variant.html, std.variant): new module.) - - $(LI Incorporated many of the Tango GC structural differences (much more to go still).) - $(LI Overhaul phobos $(D linux.mak) and add documentation build logic) - $(LI Moved $(B next) member from $(B Object.Error) to $(B Object.Exception)) - $(LI Renamed linux library from $(B libphobos.a) to $(B libphobos2.a)) - -) - -) - - -) - -Macros: - TITLE=D 2.0 Specific Features - WIKI=D2Features - CATEGORY_FEATURES=$0 - - - - diff --git a/fetch-issue-cnt.php b/fetch-issue-cnt.php index 9164ed3e98..8f1f578d31 100644 --- a/fetch-issue-cnt.php +++ b/fetch-issue-cnt.php @@ -1,5 +1,5 @@ -

    +

    Floating Point Intermediate Values - - $(P On many computers, greater - precision operations do not take any longer than lesser - precision operations, so it makes numerical sense to use - the greatest precision available for internal temporaries. - The philosophy is not to dumb down the language to the lowest - common hardware denominator, but to enable the exploitation - of the best capabilities of target hardware. - ) - - $(P For floating point operations and expression intermediate values, - a greater precision can be used than the type of the - expression. - Only the minimum precision is set by the types of the - operands, not the maximum. $(B Implementation Note:) On Intel - x86 machines, for example, - it is expected (but not required) that the intermediate - calculations be done to the full 80 bits of precision - implemented by the hardware. - ) - - $(P It's possible that, due to greater use of temporaries and - common subexpressions, optimized code may produce a more - accurate answer than unoptimized code. - ) - - $(P Algorithms should be written to work based on the minimum - precision of the calculation. They should not degrade or - fail if the actual precision is greater. Float or double types, - as opposed to the real (extended) type, should only be used for: - ) - - $(UL - $(LI reducing memory consumption for large arrays) - $(LI when speed is more important than accuracy) - $(LI data and function argument compatibility with C) - ) - -

    Floating Point Constant Folding

    - - $(P Regardless of the type of the operands, floating point - constant folding is done in $(B real) or greater precision. - It is always done following IEEE 754 rules and round-to-nearest - is used.) - - $(P Floating point constants are internally represented in - the implementation in at least $(B real) precision, regardless - of the constant's type. The extra precision is available for - constant folding. Committing to the precision of the result is - done as late as possible in the compilation process. For example:) - ---- -const float f = 0.2f; -writefln(f - 0.2); ---- - $(P will print 0. A non-const static variable's value cannot be - propagated at compile time, so:) - ---- -static float f = 0.2f; -writefln(f - 0.2); ---- - $(P will print 2.98023e-09. Hex floating point constants can also - be used when specific floating point bit patterns are needed that - are unaffected by rounding. To find the hex value of 0.2f:) - ---- -import std.stdio; - -void main() { - writefln("%a", 0.2f); -} ---- - $(P which is 0x1.99999ap-3. Using the hex constant:) - ---- -const float f = 0x1.99999ap-3f; -writefln(f - 0.2); ---- - - $(P prints 2.98023e-09.) - - $(P Different compiler settings, optimization settings, - and inlining settings can affect opportunities for constant - folding, therefore the results of floating point calculations may differ - depending on those settings.) - -

    Rounding Control

    - - $(P IEEE 754 floating point arithmetic includes the ability to set 4 - different rounding modes. - These are accessible via the functions in std.c.fenv. - ) - -$(V2 - $(P If the floating-point rounding mode is changed within a function, - it must be restored before the function exits. If this rule is violated - (for example, by the use of inline asm), the rounding mode used for - subsequent calculations is undefined. - ) -) - -

    Exception Flags

    - - $(P IEEE 754 floating point arithmetic can set several flags based on what - happened with a - computation:) - - $(TABLE - $(TR $(TD FE_INVALID)) - $(TR $(TD FE_DENORMAL)) - $(TR $(TD FE_DIVBYZERO)) - $(TR $(TD FE_OVERFLOW)) - $(TR $(TD FE_UNDERFLOW)) - $(TR $(TD FE_INEXACT)) - ) - - $(P These flags can be set/reset via the functions in - $(DPLLINK phobos/std_c_fenv.html, std.c.fenv).) - -

    Floating Point Comparisons

    - - $(P In addition to the usual < <= > >= == != comparison - operators, D adds more that are - specific to floating point. These are - !<>= - <> - <>= - !<= - !< - !>= - !> - !<> - and match the semantics for the - NCEG extensions to C. - See $(DDSUBLINK expression, floating_point_comparisons, Floating point comparisons). - ) - -

    Floating Point Transformations

    - - $(P An implementation may perform transformations on - floating point computations in order to reduce their strength, - i.e. their runtime computation time. - Because floating point math does not precisely follow mathematical - rules, some transformations are not valid, even though some - other programming languages still allow them. - ) - - $(P The following transformations of floating point expressions - are not allowed because under IEEE rules they could produce - different results. - ) - - $(TABLE2 Disallowed Floating Point Transformations, - $(TR - $(TH transformation) $(TH comments) - ) - $(TR - $(TD $(I x) + 0 → $(I x)) $(TD not valid if $(I x) is -0) - ) - $(TR - $(TD $(I x) - 0 → $(I x)) $(TD not valid if $(I x) is ±0 and rounding is towards -∞) - ) - $(TR - $(TD -$(I x) ↔ 0 - $(I x)) $(TD not valid if $(I x) is +0) - ) - $(TR - $(TD $(I x) - $(I x) → 0) $(TD not valid if $(I x) is NaN or ±∞) - ) - $(TR - $(TD $(I x) - $(I y) ↔ -($(I y) - $(I x))) $(TD not valid because (1-1=+0) whereas -(1-1)=-0) - ) - $(TR - $(TD $(I x) * 0 → 0) $(TD not valid if $(I x) is NaN or ±∞) - ) -$(COMMENT - $(TR - $(TD $(I x) * 1 → $(I x)) $(TD not valid if $(I x) is a signaling NaN) - ) -) - $(TR - $(TD $(I x) / $(I c) ↔ $(I x) * (1/$(I c))) $(TD valid if (1/$(I c)) yields an e$(I x)act result) - ) - $(TR - $(TD $(I x) != $(I x) → false) $(TD not valid if $(I x) is a NaN) - ) - $(TR - $(TD $(I x) == $(I x) → true) $(TD not valid if $(I x) is a NaN) - ) - $(TR - $(TD $(I x) !$(I op) $(I y) ↔ !($(I x) $(I op) $(I y))) $(TD not valid if $(I x) or $(I y) is a NaN) - ) - ) - - $(P Of course, transformations that would alter side effects are also - invalid.) - -) - -Macros: - TITLE=Floating Point - WIKI=Float - CATEGORY_SPEC=$0 diff --git a/forum-template.dd b/forum-template.dd new file mode 100644 index 0000000000..98963cda68 --- /dev/null +++ b/forum-template.dd @@ -0,0 +1,80 @@ +Ddoc + +$(CONTENT) + +Macros: + +STATIC = +ROOT=https://dlang.org +ROOT_DIR=https://dlang.org/ +BODYCLASS = forum +SEARCHDEFAULT_FORUM = selected +LAYOUT_SUFFIX= + +_= +TITLE= +FULL_TITLE= - D Programming Language Discussion Forum +PAGE_TOOLS=$(DIVCID smallprint, tools,) +EXTRA_HEADERS= + + +_= +EXTRA_JS= +HYPHENATE= +COMMON_SCRIPTS_DLANG= +COMMON_HEADERS_DLANG= +FAVICON = +_= + +FOOTER= +$(DIVID footernav, + Top | + $(A /, Forum index) | + $(A /help#about, About this forum) +) +$(DIVCID smallprint, copyright, $(COPYRIGHT_FOUNDATION)) +_= + +SUBNAV= +$(SUBNAV_TEMPLATE + $(DIVC head, + $(H2 Forums) + $(P $(LINK2 /, Forum Index)) + ) + $(UL + $(LI $(UL + $(LI $(LINK2 , )) + $(LI $(LINK2 , )) + )) + $(LI $(UL + $(LI $(LINK2 , )) + $(LI $(LINK2 , )) + )) + ) +) +_= + +LAYOUT=$3 +_= + +MIDRULE= +_= + +SEARCH_BOX= + $(DIVID search-box, +
    + $(SPANID search-query, )$(SPANID search-dropdown, $(SPANC helper, + + ))$(SPANID search-submit, ) +
    + ) +_= + +CONTENT= +$(DIVID forum-content,) +_= diff --git a/foundation/about.dd b/foundation/about.dd new file mode 100644 index 0000000000..7d2664aeb9 --- /dev/null +++ b/foundation/about.dd @@ -0,0 +1,83 @@ +Ddoc + +$(D_S $(TITLE), + +$(H4 The D Language Foundation is a + $(HTTPS en.wikipedia.org/wiki/501(c)_organization, 501(c)(3) non-profit public charity) + devoted to advancing open source technology related to the D programming language. +) + +

    + +

    + +$(H3 History) + +$(P The D programming language was started by Walter Bright, as a 'better C++' +and has grown slowly, but steadily, for more than 15 years. Recent improvements +to the D development process have accelerated development of the language and +shown the need for a governing organization that overlooks and arranges the +future development of the D programming language.) + +$(H3 Current projects) + +The D Language Foundation: + +$(COMMENT keep this list in sync with donate.dd) +$(UL + $(LI holds and defends the copyright and other intellectual property rights for the D programming language.) + $(LI provides resources for furthering the development and adoption of the D programming language.) + $(LI awards $(LINK2 http://dlang.org/blog/2016/12/05/the-d-language-foundations-scholarship-program, scholarships) + to highly skilled students.) + $(LI organizes the yearly $(HTTP dconf.org, DConf), the international annual conference of D Language developers and users.) + $(LI pays for hardware costs + (e.g. this website, $(LINK2 http://dlang.org/download.html, dmd downloads), + the $(LINK2 https://tour.dlang.org, D tour) and more)) + $(LI is an accepted Google Summer of Code (GSOC) organization, with projects hosted during + $(HTTPS summerofcode.withgoogle.com/archive/2016/organizations/4688223091556352/, GSOC 2016) and + $(HTTPS summerofcode.withgoogle.com/archive/2019/organizations/6223494952517632/, GSOC 2019). + ) +) + +$(H3 Committee) + +The officers of the D Language Foundation are: + +$(UL + $(LI $(HTTP www.walterbright.com, Walter Bright), President) + $(LI $(HTTPS erdani.com/index.php/contact, Tudor Andrei Cristian Alexandrescu), Vice President and Treasurer) + $(LI $(HTTP acehreli.org, Ali Çehreli), Secretary) +) + +$(H3 How can I contribute?) + +$(P There are many ways to help the D programming language to grow further and + $(LINK2 https://wiki.dlang.org/Get_involved, get involved).) + +$(P If you don't have the time to work on the source code, +you can also $(LINK2 $(ROOT_DIR)foundation/donate.html, donate) to the D Language Foundation.) + +$(H3 The D Language Foundation is a non-profit organization) + +The D Language Foundation has been recognized as a public charity under section 501(c)(3) of the Internal Revenue Code. + +$(H3 Official contacts) + +$(P The D Language Foundation has been incorporated with the state of Washington, USA. + The employer ID is 47-5352856.) + +$(P To contact the D Language Foundation, please direct emails to +$(LINK2 mailto:foundation@dlang.org, foundation@dlang.org) and other correspondence to +6830 NE Bothell Way, Suite C-162, Kenmore WA 98028.) + +) + +Macros: + TITLE=The D Language Foundation + SUBNAV=$(SUBNAV_FOUNDATION) + EXTRA_HEADERS=$(T style, + .dlang-address { + padding-left: 30px; + } + ) + _= diff --git a/foundation/contributors.dd b/foundation/contributors.dd new file mode 100644 index 0000000000..4927637ebf --- /dev/null +++ b/foundation/contributors.dd @@ -0,0 +1,43 @@ +Ddoc + +$(D_S $(TITLE), + +$(P + A list of all the awesome people that made D possible. +) +$(P + The list of contributors is sorted alphabetically and automatically generated + from commits to the + $(GH_REPO dmd), + $(GH_REPO druntime), + $(GH_REPO phobos), + $(GH_REPO dlang.org), + $(GH_REPO installer), + $(GH_REPO tools) + repositories. + The list is updated daily. +) + +
      + $(D_CONTRIBUTORS) +
    + +) + +Macros: + TITLE=Contributors ($(NR_D_CONTRIBUTORS)) + GH_REPO=$(LINK2 https://github.com/dlang/$1, $(D $1)) + D_CONTRIBUTOR=$(LI $1) + SUBNAV=$(SUBNAV_FOUNDATION) + EXTRA_HEADERS=$(T style, + #all-d-contributors { + -moz-column-gap: 20px; + -webkit-column-gap: 20px; + column-gap: 20px; + -moz-column-width: 11.5em; + -webkit-column-width: 11.5em; + column-width: 11.5em; + list-style-type: none; + } + ) + _= diff --git a/foundation/donate.dd b/foundation/donate.dd new file mode 100644 index 0000000000..af3c7df939 --- /dev/null +++ b/foundation/donate.dd @@ -0,0 +1,142 @@ +Ddoc + +$(D_S $(TITLE), + +$(H4 The D Language Foundation is a + $(HTTPS en.wikipedia.org/wiki/501(c)_organization, 501(c) non-profit public charity) + devoted to advancing open source technology related to the D programming language. +) + +The D Language Foundation: + +$(COMMENT keep this list in sync with foundation.dd) +$(UL + $(LI holds and defends the copyright and other intellectual property rights for the D programming language.) + $(LI provides resources for furthering the development and adoption of the D programming language.) + $(LI awards $(LINK2 http://dlang.org/blog/2016/12/05/the-d-language-foundations-scholarship-program, scholarships) + to highly skilled students.) + $(LI organizes the yearly $(HTTP dconf.org, DConf), the international annual conference of D Language developers and users.) + $(LI pays for hardware costs + (e.g. this website, $(LINK2 http://dlang.org/download.html, dmd downloads), + the $(LINK2 https://tour.dlang.org, D tour) and more).) + $(LI is an accepted Google Summer of Code (GSOC) organization, with projects hosted during + $(HTTPS summerofcode.withgoogle.com/archive/2016/organizations/4688223091556352/, GSOC 2016) and + $(HTTPS summerofcode.withgoogle.com/archive/2019/organizations/6223494952517632/, GSOC 2019). + ) +) + +$(P We are always in search of ways to improve the D programming language +experience for new and existing D users. Whether that means hiring programmers +to carry out contract work, sponsoring bounties on specific tasks, providing +scholarships for students performing D-related research, or anything else that +benefits the D community and ecosystem, we cannot make any of it happen without +funding. We $(LINK2 sponsors.html, welcome contributions) from both +organizations and individuals. Your help is highly appreciated and is what +enables the D Language Foundation to fulfill its mission.) + +$(H3 How will my donation be used?) + +$(P Donations go toward supporting the D Language Foundation's regular, non-sponsored +operations (DConf expenses, part-time workers, blog post bounties, reimbursements, etc.). +One of the important ways we make use of donations is $(LINK2 +http://dlang.org/blog/2016/12/05/the-d-language-foundations-scholarship-program, +in awarding scholarships) to highly skilled students. Each $(DOLLAR)5 you donate +contributes to approximately one hour of work by a talented graduate student, +and these hours add quickly toward important projects that further the state of +the art in the D programming language.) + +$(H3 How can I donate?) + +$(DONATE_ITEM Donate through GitHub Sponsors, github, + + The D Language Foundation is enrolled in the GitHub Sponsors program. One-time donations here will go toward our general expense fund. We aim to use + monthly donations to hire part-time workers who can help us achieve our vision for the D programming language. You can see our current monthly donation target + along with multiple one-time and monthly donation tiers $(LINK2 https://github.com/sponsors/dlang, on our GitHub Sponsors page). +) + +$(DONATE_ITEM Donate through PayPal, paypal, + + Click the yellow Donate button to make a donation to the D Language Foundation via PayPal. If + you want the money to be directed toward a specific campaign, project, task, or bounty, please be sure to leave + a note letting us know! + $(BR) $(BR) + +
    + + + + +
    +) + +$(DONATE_ITEM Donate through OpenCollective, users, + + Make a $(I transparent) donation and select the package you're comfortable with. If + you want the money to be directed toward a specific campaign, project, task, or bounty, please be sure to leave + a note letting us know! + $(BR) $(BR) + + + + +) + +$(DONATE_ITEM Donate by credit card, credit-card, + Please use the PayPal button above to donate by credit card. You don't need a PayPal account to use the donation button. +) + +$(DONATE_ITEM Electronic wire transfers or bank check, money, + Wire transfer information will be announced soon. In the meantime please use PayPal or $(LINK2 mailto:foundation@dlang.org, contact the D Language Foundation). +) + +$(DONATE_ITEM smile.amazon.com, shopping-cart, + Visit $(HTTPS smile.amazon.com, smile.amazon.com) and select the D + Language Foundation as your charity. We'll receive a small percentage + of every purchase you make through smile.amazon.com (not www.amazon.com or the mobile app). +) + +$(DONATE_ITEM The DLang Swag Emporium, shopping-cart, + Visit the $(HTTPS www.zazzle.com/store/dlang_swag?rf=238129799288374326, + DLang Swag Emporium) to purchase D-themed t-shirts, coffee mugs, and other + swag. The D Language Foundation will receive between %15-25 royalties on + each purchase. And if you use the preceding link, we'll also earn a small + referral fee. +) + +$(H3 The D Language Foundation is a non-profit organization) + +$(P By the Foundation bylaws, its officers (Walter Bright, Andrei Alexandrescu +and Ali Çehreli) cannot receive income from the Foundation, which preempts a +variety of conflicts of interest.) + +$(P For US taxpayers, contributions to the D Language Foundation are +tax-deductible. The D Language Foundation is a $(HTTPS +en.wikipedia.org/wiki/501(c)_organization, 501(c) non-profit public charity) +registered in the state of Washington, USA. You should consult your tax adviser +for rules as they apply to your situation.) + +$(P Donations to the D Language Foundation are currently not tax-deductible in +most other countries as they require an organisation to be incorporated in that +country and the D Language Foundation does currently not have the resources to +do so.) + +$(P If you have a question about donations, please write to the D Language +Foundation at $(LINK2 mailto:foundation@dlang.org, foundation@dlang.org).) +) + +Macros: + TITLE=Contribute to the D Language Foundation + NOSPAM_FOUNDATION=$1 + FA_ICON= + REMOVE_FIRST=$+ + DONATE_ITEM= + SUBNAV=$(SUBNAV_FOUNDATION) + EXTRA_HEADERS=$(T style, + .donate-item { + padding-left: 30px; + } + .donate-item div { + padding-left: 30px; + } + ) + _= diff --git a/foundation/foundation.ddoc b/foundation/foundation.ddoc new file mode 100644 index 0000000000..79f6f5ac89 --- /dev/null +++ b/foundation/foundation.ddoc @@ -0,0 +1 @@ +ROOT_DIR = ../ diff --git a/foundation/index.dd b/foundation/index.dd new file mode 100644 index 0000000000..1f603a01c3 --- /dev/null +++ b/foundation/index.dd @@ -0,0 +1,63 @@ +Ddoc + +$(D_S D Language Foundation, + + $(H4 The D Language Foundation is a + $(HTTPS en.wikipedia.org/wiki/501(c)_organization, 501(c)(3) non-profit public charity) + devoted to advancing open source technology related to the D programming language. + ) + + + $(DIVC boxes, + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)foundation/about.html, About)) + $(P Learn more about the history and activities of the D Language Foundation.) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)foundation/donate.html, Donate)) + $(P Support the D Language Foundation and help to further + the development of the D language. + ) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)foundation/upb-scholarship.html, Scholarships)) + $(P The D Language Foundation offers Languages and Systems Research Scholarships + to EE and CS students at University "Politehnica" Bucharest (UPB). + ) + ) + $(DIVC item, + $(H4 $(LINK2 https://dconf.org, DConf)) + $(P The D Language Foundation is organizing the yearly D conference.) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)foundation/sponsors.html, Sponsors)) + $(P Browse the list of all sponsors donating monetary resources + to the D Language Foundation.) + ) + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)foundation/contributors.html, Contributors)) + $(P Browse the list of all the awesome people who contributed + to D's source code and helped to make D possible.) + ) + ) + $(DIVC row, + $(DIVC item, + $(H4 $(LINK2 $(ROOT_DIR)foundation/prman.html, Pull-Request/Issue Managers)) + $(P Learn about the responsibilities of the people managing our + pull requests and reported issues.) + ) + $(DIVC item, +   + ) + ) + ) +) + +Macros: + TITLE=Foundation + SUBNAV=$(SUBNAV_FOUNDATION) diff --git a/foundation/prman.dd b/foundation/prman.dd new file mode 100644 index 0000000000..263f2848f6 --- /dev/null +++ b/foundation/prman.dd @@ -0,0 +1,93 @@ +Ddoc + +$(D_S $(TITLE)) + +$(P The D Language Foundation employs two part-time pull-request managers thanks +to the sponsorship of Symmetry Investments. One of them is intended to fill an +administrative/managerial role, the other a more technically-oriented role. This +document outlines their general responsibilities in managing the pull requests +submitted to $(LINK2 https://github.com/dlang, the D Programming Language Github +organization repositories), and the issues submitted to $(LINK2 +https://issues.dlang.org/, issues.dlang.org).) + +$(P The primary goal for the creation of these positions is to streamline the +contribution process. We are grateful to the volunteers who have been doing the +work of maintaining our Issue and PR queues over the past several years, but the +loose nature of our process has been such that too many contributions grow stale +(no one takes an interest, they become bottlenecked on one maintainer, etc). +Contributors should have confidence that their submissions, be they bug reports +or content contributions, will be reviewed and shepherded to a conclusion +without languishing for long periods of time. With paid staff overseeing the +process, we expect the process will become more efficient, and contributors will +have a primary point of contact to assist with tracking and resolving their +contributions.) + +$(P The following list is divided into Administrative and Technical +responsibilities. Some may overlap, and there may be loose boundaries between +others. We trust the PR managers to establish their own approach to carrying out +these responsibilities.) + +$(P In the text below, $(B APR) refers the Administrative PR Manager Role, $(B +TPR) refers to the Technical PR Manager Role.) + +$(H2 Administrative Responsibilities) +$(P In order to effectively carry out his responsibilities, the APR needs to be +aware of which core contributors are responsible for which areas and which +community members to contact when necessary to resolve issues, and have an +understanding of the general direction the language and ecosystem are going +(i.e., for any given PR, the APR should be able to answer the question, "Do we +do this?").) + +$(UL + $(LI $(B Maintain the contribution guide) - $(LINK2 + https://github.com/dlang/dmd/blob/master/CONTRIBUTING.md, the contribution + guide) establishes best practices for submitting issues and pull requests. The + APR should work with the TPR to evolve these details as needed and ensure the + document is up to date.) + $(LI $(B Triage issues and PRs) - ensure that each issue report is properly + prioritized and, where possible, assigned to someone who can resolve it; + establish criteria to ensure that pull requests get as much time as they + need for a proper review before being merged (e.g., trivial vs. complex, + routine vs. controversial, etc); establish criteria to close issues/PRs; + recognize when a pull request should first be incorporated as a DIP; etc.) + $(LI $(B Keep track of progress) - the APR should establish some means of + keeping up to date on the status of every issue and PR in our system, and + will be the primary point of contact for queries about the status of any + issue or PR.) + $(LI $(B Communicate with relevant parties) - communication is vital to + ensuring the efficient handling of issues and pull requests. Contributors + will need to be sought out to resolve issues that are not picked up + voluntarily; non-trivial pull requests will need to be reviewed by an + appropriate core contributor/maintainer; contributors will need to be kept + abreast of the status of their contributions when they cannot be resolved + quickly; etc.) +) + +$(H2 Technical Responsibilities) +$(P In order to effectively carry out the responsibilities of this role, the TPR +needs a solid understanding of the architecture of our GitHub projects (i.e., +for any given PR, the TPR should be able to answer the question, "Can we do +this?").) + +$(UL + $(LI $(B Ensure compliance with contribution guide) - each issue and pull + request should meet the guidelines established in $(LINK2 + https://github.com/dlang/dmd/blob/master/CONTRIBUTING.md, the contribution + guide). The TPR will work with contributors to ensure these guidelines are + met (reduced test cases, proper commit message format, changelog entries, + resolve merge conflicts, etc).) + $(LI $(B Identify and resolve regressions) - sometimes bugs are reported + that are regressions, but not marked as such. The TPR should identify such + issues, attempt to pinpoint the source of all reported regressions, and take + steps to resolve them (e.g., contact the author/reviewer of the offending + PR).) + $(LI $(B Review trivial PRs) - pull requests that need no specialized review + should be reviewed and merged by the TPR.) + $(LI $(B Fix trivial issues) - the TPR is free to fix trivial issues and + submit such fixes as pull requests, but must request review from a competent + reviewer.) +) + +Macros: + TITLE=Pull-Request/Issue Manager Responsibilities + SUBNAV=$(SUBNAV_FOUNDATION) diff --git a/foundation/sponsors.dd b/foundation/sponsors.dd new file mode 100644 index 0000000000..70370fecdc --- /dev/null +++ b/foundation/sponsors.dd @@ -0,0 +1,142 @@ +Ddoc + +$(D_S $(TITLE), + +$(P Development of the D programming language is driven by the passion and dedication of its users. From +$(LINK2 contributors.html, submitting and reviewing pull requests) to +$(WEB issues.dlang.org, reporting issues), offering help in $(HTTPS forum.dlang.org, the forums), +and writing guest posts for $(HTTPS dlang.org/blog, the official blog), the members of the D +community contribute as and how they can, most often for no compensation other than personal +satisfaction. +) + +$(P Behind the scenes, the D Language Foundation sets priority tasks, works with partners to organize +$(WEB dconf.org, the annual DConf), awards scholarships, promotes the language, and more. Here, again, +members of the community keep the wheels rolling through their generous contributions. +) + +$(P On this page, we recognize some of those who have made monetary donations to the D Language Foundation. +Each $(LINK2 $(ROOT_DIR)foundation/donate.html, donation), big and small, enables us to keep working toward our goals. +) + +$(H2 Corporate and Organizational Sponsors) + +$(DIVC orgs-using-d center, + $(DORG Symmetry Investments, http://symmetryinvestments.com/about-us/, symmetry.png, + Alternative Investment Management, + Analytics and investment tools. + $(LINK_ROW + $(FA_TALK www.youtube.com/watch?v=xJy6ifCekCE&index=34&list=PL3jwVPmk_PRxo23yyoc0Ip_cP3-rCm7eB, Excel-D) $(FA_SEPARATOR) + $(FA_GITHUB symmetryinvestments) + ) + ) + $(DORG Weka.IO, http://www.weka.io, weka.png, + Software defined storage, + Complete distributed storage solution (over 200K LoC). + $(LINK_ROW + $(FA_TALK dconf.org/2016/talks/zvibel.html, DConf talk) $(FA_SEPARATOR) + $(FA_HIRING www.weka.io) + ) + ) +) + +$(H2 Backers on OpenCollective) + + + +$(H2 Backers on Other Platforms) + +$(P The following list is ordered by total donation amount, descending, and is far from exhaustive. If you have donated to +the D Language Foundation and want to see your name (or alias) in the list, please let us know at +$(LINK2 mailto:social@dlang.org, social@dlang.org). We're eager to add you to it! +) + +$(UL + $(LI Vijay Nayar) + $(LI George Toutoungis) + $(LI John Hall) + $(LI Gerhardus Jansen) + $(LI Radu Racariu) + $(LI Bastiaan Veelo) + $(LI Jared Hanson) + $(LI C. Piker) + $(LI Sepany) + $(LI JR) + $(LI Ali Çehreli) + $(LI Longinus Ulyanovsky) + $(LI Jack Applegame) + $(LI Emil Nicolaie Perhinschi) + $(LI Alex Semenikhine) + $(LI Georges Robert) + $(LI Ross Lonstein) + $(LI D. Gilliland) + $(LI Alexander Bothe) + $(LI Unity Technologies ApS) + $(LI Zhang Zongren) + $(LI Dag) + $(LI Jeffrey Buhr) + $(LI Matthew Strawbridge) + $(LI Paul) + $(LI Andrii Bazylevych) + $(LI Aaron Disibio) + $(LI Sebastian Wilzbach) + $(LI Andrei Alexandrescu) + $(LI Etienne Cimon) +) +) + +Macros: + TITLE=D Language Foundation Sponsors + SUBNAV=$(SUBNAV_FOUNDATION) + FA_HIRING=$(FA_ICON rocket) $(HTTP $1, Hiring) + FA_GITHUB=$(FA_ICON github) $(HTTPS github.com/$1, GitHub) + FA_TALK=$(FA_ICON youtube-play) $(HTTP $1, $2) + FA_SEPARATOR=  + FA_TESTIMONIAL=$(FA_ICON heart) + FA_QUOTE=$(FA_ICON quote-left) $0 $(FA_ICON quote-right) + LINK_ROW=$(DIVC orgs-using-d-linkrow, $1) + DORGIMG= + DORG=$(DIVC orgs-using-d-cell, $(DORGIMG $2, $3) $(P $(DIVC orgs-using-d-desc, $4 ) $(DIVC orgs-using-d-uses donthyphenate, $5))) + + EXTRA_HEADERS=$(T style, + #opencollective-banner h2 { + color: red; + } + .orgs-using-d-cell { + width: 280px; + display: inline-block; + vertical-align: top; + margin-bottom: 0.5em; + padding-left: 25px; + padding-right: 25px; + padding-bottom: 10px; + } + .orgs-using-d h3 { + margin: 0.4em; + margin-left: 0; + margin-right: 0; + text-align: center; + } + .orgs-using-d-img-wrapper { + width: 280px; + height: 100px; + padding-bottom: 10px; + text-align: center; + } + .orgs-using-d img { + max-width: 280px; + max-height: 100px; + } + .orgs-using-d-desc { + font-style: italic; + margin-left: -1px; + margin-right: -1px; + } + .orgs-using-d-uses { + padding-top: 10px; + } + .orgs-using-d-linkrow { + padding-top: 5px; + } + ) + _= diff --git a/foundation/upb-scholarship.dd b/foundation/upb-scholarship.dd new file mode 100644 index 0000000000..a265999e6d --- /dev/null +++ b/foundation/upb-scholarship.dd @@ -0,0 +1,78 @@ +Ddoc + +$(D_S The DLang UPB Languages and Systems Research Scholarship, + +$(P The D Language Foundation is pleased to extend the Languages and Systems +Research Scholarships to EE and CS students at University "Politehnica" +Bucharest (UPB).) + +$(P This scholarship was established to recognize outstanding full-time +students enrolled in postgraduate research in the Departments of +Electrical Engineering ("Electronica si Telecomunicatii") and Computer +Science ("Automatica si Calculatoare") at UPB. The award fosters +graduate-level (MSc and PhD) research in the fields of Programming +Languages and Systems, with an emphasis on subdomains and topics most +relevant to the mission of the Foundation. These include but are not limited to:) + +$(UL + $(LI Systems programming languages semantics and implementation) + $(LI Engines for code transformation and refactoring) + $(LI Optimizers) + $(LI Plugins for code editors) + $(LI Memory safety) + $(LI Static and dynamic program analysis) + $(LI Networking and security) + $(LI Core runtime, memory allocation, garbage collection) + $(LI Libraries and frameworks) + $(LI Static/dynamic linking and loading) + $(LI Generic and Generative Programming) +) + +$(P The scholarship award is decided on a semester basis and is dependent on students' performance. +Semester dates are defined by the UPB academic calendar. We may approve +partial scholarships that start during a semester; however, a +scholarship period always ends with the semester. The funds are intended +to cover room, board, books and other educational supplies, equipment, +and other research costs of students. Approved applicants agree to not +pursue paid employment for the duration of the scholarship.) + +$(H3 Eligibility Requirements) + +$(OL + $(LI Completed, signed, and dated + $(HTTPS docs.google.com/forms/d/e/1FAIpQLSdy5fg611KBySjZVckYdRUbIxPTS4tucglP_WGINvfy7o-zVQ/viewform, application form) + (online and scan/hardcopy).) + + $(LI Proof of enrollment in the MSc or PhD program at UPB EE ("Electronica + si Telecomunicatii") or CS ("Automatica si Calculatoare").) + + $(LI Transcript with classes attended and their respective grades.) + + $(LI Submission of an original essay (800-1200 words) describing how this + award will assist you in reaching your educational and research objectives.) + + $(LI Letter of recommendation from your program director evaluating your + research potential.) + + $(LI Public link to the completed BSc dissertation.) + + $(LI Pass one or more interviews (in person, by phone, or via Skype) with + Foundation representatives. The interviews assess technical competence, + research vision, and command of the English language of applicants.) +) + +$(P The D Language Foundation may offer to renew a scholarship for +existing/former recipients without the need to complete a new +application. The Foundation also reserves the rights to terminate a +scholarship before the end of semester if it assesses that the funds are +misused, progress in research is inadequate, or recipient behaves in a +manner unbecoming of an outstanding student and young researcher.) + +$(P We wish our applicants good luck and are looking forward to hearing from +you. Feel free to direct any related questions to foundation@dlang.org.) + +) + +Macros: + TITLE=The DLang UPB Languages and Systems Research Scholarship + SUBNAV=$(SUBNAV_FOUNDATION) diff --git a/freebsd.ddoc b/freebsd.ddoc index 2296911572..17faeb06ab 100644 --- a/freebsd.ddoc +++ b/freebsd.ddoc @@ -1,4 +1,3 @@ - OS=freebsd WINDOWS= LINUX= @@ -8,5 +7,6 @@ UNIX=$0 SEP=/ OBJEXT=o LIBEXT=a +BINEXT= DMDDIR=dmd2 -FOO= +_= diff --git a/function.dd b/function.dd deleted file mode 100644 index fca5232c90..0000000000 --- a/function.dd +++ /dev/null @@ -1,1785 +0,0 @@ -Ddoc - -$(SPEC_S Functions, - -$(GRAMMAR -$(GNAME FunctionBody): - $(GLINK2 statement, BlockStatement) - $(GLINK BodyStatement) - $(GLINK InStatement) $(GLINK BodyStatement) - $(GLINK OutStatement) $(GLINK BodyStatement) - $(GLINK InStatement) $(GLINK OutStatement) $(GLINK BodyStatement) - $(GLINK OutStatement) $(GLINK InStatement) $(GLINK BodyStatement) - -$(GNAME InStatement): - $(B in) $(GLINK2 statement, BlockStatement) - -$(GNAME OutStatement): - $(B out) $(GLINK2 statement, BlockStatement) - $(B out) $(B $(LPAREN)) $(I Identifier) $(B $(RPAREN)) $(GLINK2 statement, BlockStatement) - -$(GNAME BodyStatement): - $(B body) $(GLINK2 statement, BlockStatement) -) - - -

    Function Return Values

    - - $(P Function return values are considered to be rvalues. - This means they cannot be passed by reference to other functions. - ) - -

    Functions Without Bodies

    - - $(P Functions without bodies:) - ---- -int foo(); ---- - - $(P that are not declared as $(D abstract) are expected to have their implementations - elsewhere, and that implementation will be provided at the link step. - This enables an implementation of a function to be completely hidden from the user - of it, and the implementation may be in another language such as C, assembler, etc. - ) - -$(V2 -

    $(LNAME2 pure-functions, Pure Functions)

    - - $(P Pure functions are functions that produce the same - result for the same arguments. - To that end, a pure function: - ) - - $(UL - $(LI does not read or write any global mutable state) - $(LI cannot call functions that are not pure) - $(LI can override an impure function, but an impure function - cannot override a pure one) - $(LI is covariant with an impure function) - $(LI cannot perform I/O) - ) - - $(P As a concession to practicality, a pure function can:) - - $(UL - $(LI allocate memory via a $(GLINK2 expression, NewExpression)) - $(LI terminate the program) - $(LI read and write the floating point exception flags) - $(LI read and write the floating point mode flags, as long as those flags - are restored to their initial state upon function entry) - $(LI perform impure operations in statements that are in a - $(GLINK2 version, ConditionalStatement) - controlled by a $(GLINK2 version, DebugCondition).) - ) - - $(P A pure function can throw exceptions.) - ---- -import std.stdio; -int x; -immutable int y; -const int* pz; - -pure int foo(int i, - char* p, - const char* q, - immutable int* s) -{ - debug writeln("in foo()"); // ok, impure code allowed in debug statement - x = i; // error, modifying global state - i = x; // error, reading mutable global state - i = y; // ok, reading immutable global state - i = *pz; // error, reading const global state - return i; -} ---- - - -

    $(LNAME2 nothrow-functions, Nothrow Functions)

    - - $(P Nothrow functions do not throw any exceptions derived - from class $(I Exception). - ) - - $(P Nothrow functions are covariant with throwing ones.) - -

    $(LNAME2 ref-functions, Ref Functions)

    - - $(P Ref functions allow functions to return by reference. - This is analogous to ref function parameters. - ) - ---- -ref int foo() { - auto p = new int; - return *p; -} -... -foo() = 3; // reference returns can be lvalues ---- - -

    $(LNAME2 auto-functions, Auto Functions)

    - - $(P Auto functions have their return type inferred from any - $(GLINK2 statement, ReturnStatement)s - in the function body. - ) - - $(P An auto function is declared without a return type. - If it does not already have a storage class, use the - $(D_KEYWORD auto) storage class. - ) - - $(P If there are multiple $(I ReturnStatement)s, the types - of them must match exactly. If there are no $(I ReturnStatement)s, - the return type is inferred to be $(D_KEYWORD void). - ) - ---- -auto foo(int i) { - return i + 3; // return type is inferred to be int -} ---- - -$(V2 -

    $(LNAME2 auto-ref-functions, Auto Ref Functions)

    - - $(P Auto ref functions infer their return type just as - $(LINK2 #auto-functions, auto functions) do. - In addition, they become $(LINK2 #ref-functions, ref functions) - if the return expression is an lvalue, - and it would not be a reference to a local or a parameter. - ) - ---- -auto ref foo(int x) { return x; } // value return -auto ref foo() { return 3; } // value return -auto ref foo(ref int x) { return x; } // ref return -auto ref foo(out int x) { return x; } // ref return -auto ref foo() { static int x; return x; } // ref return ---- - - $(P The lexically first $(GLINK2 statement, ReturnStatement) - determines the ref-ness of a function: - ) - ---- -auto ref foo(ref int x) { return 3; return x; } // ok, value return -auto ref foo(ref int x) { return x; return 3; } // error, ref return, 3 is not an lvalue ---- -) - -$(V2 -

    $(LNAME2 inout-functions, Inout Functions)

    - - $(P Functions that deal with mutable, const, or immutable types with - equanimity often need to transmit their type to the return value: - ) - ---- -int[] foo(int[] a, int x, int y) { return a[x .. y]; } - -const(int)[] foo(const(int)[] a, int x, int y) { return a[x .. y]; } - -immutable(int)[] foo(immutable(int)[] a, int x, int y) { return a[x .. y]; } ---- - - $(P The code generated by these three functions is identical. - To indicate that these can be one function, the $(D_KEYWORD inout) - type constructor is employed: - ) - ---- -inout(int)[] foo(inout(int)[] a, int x, int y) { return a[x .. y]; } ---- - - $(P The $(D_KEYWORD inout) forms a wildcard that stands in for - any of mutable, const or immutable. When the function is called, - the inout of the return type is changed to whatever the mutable, - const, or immutable status of the argument type to the parameter - inout was. - ) - - $(P Inout types can be implicitly converted to const, but to nothing - else. Other types cannot be implicitly converted to inout. - Casting to or from inout is not allowed in @safe functions. - ) - - $(P If an inout appears in a function parameter list, it must also appear - in the return type. - ) - - $(P A set of arguments to a function with inout parameters is considered - a match if any inout argument types match exactly, or:) - -$(OL - $(LI No argument types are composed of inout types.) - $(LI A mutable, const or immutable argument type can be matched against each - corresponding parameter inout type.) -) - - $(P If such a match occurs, if every match is mutable, then the inout is - considered matched with mutable. If every match is immutable, then the - inout is considered matched with immutable. Otherwise, the inout is - considered matched with const. The inout in the return type is then rewritten - to be the inout matched attribute. - ) - - $(P Global and static variable types cannot have any inout components. - ) - - $(P $(B Note:) Shared types are not overlooked. Shared types cannot - be matched with inout. - ) -) - -

    $(LNAME2 property-functions, Property Functions)

    - - $(P Property functions are tagged with the $(CODE @property) - attribute. They can be called without parentheses (hence - acting like properties). - ) - ---- -struct S { - int m_x; - @property { - int x() { return m_x; } - int x(int newx) { return m_x = newx; } - } -} - -void foo() { - S s; - s.x = 3; // calls s.x(int) - bar(s.x); // calls bar(s.x()) -} ---- -) - -

    $(LNAME2 virtual-functions, Virtual Functions)

    - - $(P Virtual functions are functions that are called indirectly - through a function - pointer table, called a vtbl[], rather than directly. - All non-static non-private non-template member functions are virtual. - This may sound - inefficient, but since the D compiler knows all of the class - hierarchy when generating code, all - functions that are not overridden can be optimized to be non-virtual. - In fact, since - C++ programmers tend to "when in doubt, make it virtual", the D way of - "make it - virtual unless we can prove it can be made non-virtual" results, on - average, in many - more direct function calls. It also results in fewer bugs caused by - not declaring - a function virtual that gets overridden. - ) - - $(P Functions with non-D linkage cannot be virtual, and hence cannot be - overridden. - ) - - $(P Member template functions cannot be virtual, and hence cannot be - overridden. - ) - - $(P Functions marked as $(TT final) may not be overridden in a - derived class, unless they are also $(TT private). - For example: - ) - ------- -class A { - int def() { ... } - final int foo() { ... } - final private int bar() { ... } - private int abc() { ... } -} - -class B : A { - int def() { ... } // ok, overrides A.def - int foo() { ... } // error, A.foo is final - int bar() { ... } // ok, A.bar is final private, but not virtual - int abc() { ... } // ok, A.abc is not virtual, B.abc is virtual -} - -void test(A a) { - a.def(); // calls B.def - a.foo(); // calls A.foo - a.bar(); // calls A.bar - a.abc(); // calls A.abc -} - -void func() { - B b = new B(); - test(b); -} ------- - - $(P Covariant return types - are supported, which means that the - overriding function in a derived class can return a type - that is derived from the type returned by the overridden function: - ) - ------- -class A { } -class B : A { } - -class Foo { - A test() { return null; } -} - -class Bar : Foo { - B test() { return null; } // overrides and is covariant with Foo.test() -} ------- - - $(P Virtual functions all have a hidden parameter called the - $(I this) reference, which refers to the class object for which - the function is called. - ) - -

    $(LNAME2 function-inheritance, Function Inheritance and Overriding)

    - - A functions in a derived class with the same name and parameter - types as a function in a base class overrides that function: - ------- -class A { - int foo(int x) { ... } -} - -class B : A { - override int foo(int x) { ... } -} - -void test() { - B b = new B(); - bar(b); -} - -void bar(A a) { - a.foo(1); // calls B.foo(int) -} ------- - - $(P However, when doing overload resolution, the functions in the base - class are not considered: - ) - ------- -class A { - int foo(int x) { ... } - int foo(long y) { ... } -} - -class B : A { - override int foo(long x) { ... } -} - -void test() { - B b = new B(); - b.foo(1); // calls B.foo(long), since A.foo(int) not considered - A a = b; -$(V1 a.foo(1); // calls A.foo(int)) -$(V2 a.foo(1); // issues runtime error (instead of calling A.foo(int))) -} ------- - - $(P To consider the base class's functions in the overload resolution - process, use an $(I AliasDeclaration): - ) - ------- -class A { - int foo(int x) { ... } - int foo(long y) { ... } -} - -class B : A { - $(B alias A.foo foo;) - override int foo(long x) { ... } -} - -void test() { - B b = new B(); - bar(b); -} - -void bar(A a) { - a.foo(1); // calls A.foo(int) - B b = new B(); - b.foo(1); // calls A.foo(int) -} ------- - -$(V2 - $(P If such an $(I AliasDeclaration) is not used, the derived - class's functions completely override all the functions of the - same name in the base class, even if the types of the parameters - in the base class functions are different. If, through - implicit conversions to the base class, those other functions do - get called, a $(CODE core.exception.HiddenFuncError) exception is raised: - ) ---- -import core.exception; - -class A { - void set(long i) { } - void $(B set)(int i) { } -} -class B : A { - void set(long i) { } -} - -void foo(A a) { - int i; - try { - a.$(B set)(3); // error, throws runtime exception since - // A.set(int) should not be available from B - } - catch ($(B HiddenFuncError) o) { - i = 1; - } - assert(i == 1); -} - -void main() { - foo(new B); -} ---- - $(P If an $(CODE HiddenFuncError) exception is thrown in your program, - the use of overloads and overrides needs to be reexamined in the - relevant classes.) - - $(P The $(CODE HiddenFuncError) exception is not thrown if the - hidden function is disjoint, as far as overloading is concerned, - from all the other virtual functions is the inheritance hierarchy.) -) - - $(P A function parameter's default value is not inherited:) - ------- -class A { - void foo(int $(B x = 5)) { ... } -} - -class B : A { - void foo(int $(B x = 7)) { ... } -} - -class C : B { - void foo(int $(B x)) { ... } -} - - -void test() { - A a = new A(); - a.foo(); // calls A.foo(5) - - B b = new B(); - b.foo(); // calls B.foo(7) - - C c = new C(); - c.foo(); // error, need an argument for C.foo -} ------- - - -

    Inline Functions

    - - There is no inline keyword. The compiler makes the decision whether to - inline a function or not, analogously to the register keyword no - longer being relevant to a - compiler's decisions on enregistering variables. - (There is no register keyword either.) - - -

    $(LNAME2 function-overloading, Function Overloading)

    - - $(P Functions are overloaded based on how well the arguments - to a function can match up with the parameters. - The function with the $(I best) match is selected. - The levels of matching are: - ) - - $(OL - $(LI no match) - $(LI match with implicit conversions) - $(V2 $(LI match with conversion to const)) - $(LI exact match) - ) - - $(P Each argument (including any $(CODE this) pointer) is - compared against the function's corresponding parameter, to - determine the match level for that argument. The match level - for a function is the $(I worst) match level of each of its - arguments.) - -$(V2 - $(P Literals do not match $(CODE ref) or $(CODE out) parameters.) -) -$(V1 - $(P If two or more functions have the same match level, - it is an ambiguity error. - ) -) -$(V2 - $(P If two or more functions have the same match level, - then $(LNAME2 partial-ordering, $(I partial ordering)) - is used to try to find the best match. - Partial ordering finds the most specialized function. - If neither function is more specialized than the other, - then it is an ambiguity error. - Partial ordering is determined for functions $(CODE f()) - and $(CODE g()) by taking the parameter types of $(CODE f()), - constructing a list of arguments by taking the default values - of those types, and attempting to match them against $(CODE g()). - If it succeeds, then $(CODE g()) is at least as specialized - as $(CODE f()). - For example: - ) ---- -class A { } -class B : A { } -class C : B { } -void foo(A); -void foo(B); - -void test() { - C c; - /* Both foo(A) and foo(B) match with implicit conversion rules. - * Applying partial ordering rules, - * foo(B) cannot be called with an A, and foo(A) can be called - * with a B. Therefore, foo(B) is more specialized, and is selected. - */ - foo(c); // calls foo(B) -} ---- - $(P A function with a variadic argument is considered less - specialized than a function without. - ) -) - - $(P Functions defined with non-D linkage cannot be overloaded. - because the name mangling does not take the parameter types - into account. - ) - -$(V2 -

    Overload Sets

    - - $(P Functions declared at the same scope overload against each - other, and are called an $(I Overload Set). - A typical example of an overload set are functions defined - at module level: - ) - ---- -module A; -void foo() { } -void foo(long i) { } ---- - - $(P $(CODE A.foo()) and $(CODE A.foo(long)) form an overload set. - A different module can also define functions with the same name: - ) - ---- -module B; -class C { } -void foo(C) { } -void foo(int i) { } ---- - - $(P and A and B can be imported by a third module, C. - Both overload sets, the $(CODE A.foo) overload set and the $(CODE B.foo) - overload set, are found. An instance of $(CODE foo) is selected - based on it matching in exactly one overload set: - ) - ---- -import A; -import B; - -void bar(C c) { - foo(); // calls A.foo() - foo(1L); // calls A.foo(long) - foo(c); // calls B.foo(C) - foo(1,2); // error, does not match any foo - foo(1); // error, matches A.foo(long) and B.foo(int) - A.foo(1); // calls A.foo(long) -} ---- - - $(P Even though $(CODE B.foo(int)) is a better match than $(CODE - A.foo(long)) for $(CODE foo(1)), - it is an error because the two matches are in - different overload sets. - ) - - $(P Overload sets can be merged with an alias declaration:) - ---- -import A; -import B; - -alias A.foo foo; -alias B.foo foo; - -void bar(C c) { - foo(); // calls A.foo() - foo(1L); // calls A.foo(long) - foo(c); // calls B.foo(C) - foo(1,2); // error, does not match any foo - foo(1); // calls B.foo(int) - A.foo(1); // calls A.foo(long) -} ---- - -) - - -

    Function Parameters

    - -$(V1 - $(P Parameters are $(B in), $(B out), $(B inout) or $(B lazy). - $(B in) is the default; the others work like - storage classes. For example: - ) - ------- -int foo(in int x, out int y, inout int z, int q); ------- - - $(P x is $(B in), y is $(B out), z is $(B inout), and q is $(B in). - ) -) -$(V2 - $(P Parameter storage classes are $(B in), $(B out), - $(B ref), $(B lazy), $(B const), $(B immutable), $(B shared), - $(B inout) or - $(B scope). - For example: - ) ------- -int foo(in int x, out int y, ref int z, int q); ------- - - $(P x is $(B in), y is $(B out), z is $(B ref), and q is none. - ) -) - - $(UL - $(LI The function declaration makes it clear what the inputs and - outputs to the function are.) - $(LI It eliminates the need for IDL as a separate language.) - $(LI It provides more information to the compiler, enabling more - error checking and - possibly better code generation.) - ) - - $(TABLE2 Parameter Storage Classes, - $(THEAD Storage Class, Description) - $(TROW $(I none), parameter becomes a mutable copy of its argument) - $(V1 $(TROW $(D in), equivalent to $(I none))) - $(V2 $(TROW $(D in), equivalent to $(D const scope))) - $(TROW $(D out), parameter is initialized upon function entry with the default value - for its type) - $(V1 $(TROW $(D inout), parameter is passed by reference)) - $(V2 $(TROW $(D ref), parameter is passed by reference)) - $(V2 $(TROW $(D scope), references in the parameter - cannot be escaped (e.g. assigned to a global variable))) - $(TROW $(D lazy), argument is evaluated by the called function and not by the caller) - $(V2 - $(TROW $(D const), argument is implicitly converted to a const type) - $(TROW $(D immutable), argument is implicitly converted to an immutable type) - $(TROW $(D shared), argument is implicitly converted to a shared type) - $(TROW $(D inout), argument is implicitly converted to an inout type) - ) - ) - ------- -void foo(out int x) { - // x is set to int.init, - // which is 0, at start of foo() -} - -int a = 3; -foo(a); -// a is now 0 - - -void abc(out int x) { - x = 2; -} - -int y = 3; -abc(y); -// y is now 2 - - -void def($(V1 inout)$(V2 ref) int x) { - x += 1; -} - -int z = 3; -def(z); -// z is now 4 ------------- - - $(P For dynamic array and object parameters, which are passed - by reference, in/out/ref - apply only to the reference and not the contents. - ) - - $(P $(D lazy) arguments are evaluated not when the function is called, - but when the parameter is evaluated within the function. Hence, - a $(D lazy) argument can be executed 0 or more times. A $(D lazy) parameter - cannot be an lvalue.) - ---- -void dotimes(int n, lazy void exp) { - while (n--) - exp(); -} - -void test() { - int x; - dotimes(3, writefln(x++)); -} ---- - - $(P prints to the console:) - -$(CONSOLE -0 -1 -2 -) - - $(P A $(D lazy) parameter of type $(D void) can accept an argument - of any type.) - -

    Function Default Arguments

    - - $(P Function parameter declarations can have default values:) - ---- -void foo(int x, int y = 3) { - ... -} -... -foo(4); // same as foo(4, 3); ---- - - $(P Default parameters are evaluated in the context of the - function declaration. - If the default value for a parameter is given, all following - parameters must also have default values. - ) - -

    Variadic Functions

    - - Functions taking a variable number of arguments are called - variadic functions. A variadic function can take one of - three forms: - - $(OL - $(LI C-style variadic functions) - $(LI Variadic functions with type info) - $(LI Typesafe variadic functions) - ) - - -

    C-style Variadic Functions

    - - A C-style variadic function is declared as taking - a parameter of ... after the required function parameters. - It has non-D linkage, such as $(TT extern (C)): - ------- -extern (C) int foo(int x, int y, ...); - -foo(3, 4); // ok -foo(3, 4, 6.8); // ok, one variadic argument -foo(2); // error, y is a required argument ------- - - There must be at least one non-variadic parameter declared. - ------- -extern (C) int def(...); // error, must have at least one parameter ------- - - C-style variadic functions match the C calling convention for - variadic functions, and is most useful for calling C library - functions like $(TT printf). - The implementiations of these variadic functions have a special - local variable declared for them, - $(B _argptr), which is a $(TT void*) pointer to the first of the - variadic - arguments. To access the arguments, $(B _argptr) must be cast - to a pointer to the expected argument type: - ------- -foo(3, 4, 5); // first variadic argument is 5 - -int foo(int x, int y, ...) { - int z; - - z = *cast(int*)$(B _argptr); // z is set to 5 -} ------- - - To protect against the vagaries of stack layouts on different - CPU architectures, use $(B std.c.stdarg) to access the variadic - arguments: - ------- -import $(B std.c.stdarg); ------- - -

    D-style Variadic Functions

    - - Variadic functions with argument and type info are declared as taking - a parameter of ... after the required function parameters. - It has D linkage, and need not have any non-variadic parameters - declared: - ------- -int abc(char c, ...); // one required parameter: c -int def(...); // ok ------- - - These variadic functions have a special local variable declared for - them, - $(B _argptr), which is a $(TT void*) pointer to the first of the - variadic - arguments. To access the arguments, $(B _argptr) must be cast - to a pointer to the expected argument type: - ------- -foo(3, 4, 5); // first variadic argument is 5 - -int foo(int x, int y, ...) { - int z; - - z = *cast(int*)$(B _argptr); // z is set to 5 -} ------- - - An additional hidden argument - with the name $(B _arguments) and type $(TT TypeInfo[]) - is passed to the function. - $(B _arguments) gives the number of arguments and the type - of each, enabling the creation of typesafe variadic functions. - ------- -import std.stdio; - -class Foo { int x = 3; } -class Bar { long y = 4; } - -void printargs(int x, ...) { - writefln("%d arguments", $(B _arguments).length); - for (int i = 0; i < $(B _arguments).length; i++) - { - $(B _arguments)[i].print(); - - if ($(B _arguments)[i] == typeid(int)) - { - int j = *cast(int *)_argptr; - _argptr += int.sizeof; - writefln("\t%d", j); - } - else if ($(B _arguments)[i] == typeid(long)) - { - long j = *cast(long *)_argptr; - _argptr += long.sizeof; - writefln("\t%d", j); - } - else if ($(B _arguments)[i] == typeid(double)) - { - double d = *cast(double *)_argptr; - _argptr += double.sizeof; - writefln("\t%g", d); - } - else if ($(B _arguments)[i] == typeid(Foo)) - { - Foo f = *cast(Foo*)_argptr; - _argptr += Foo.sizeof; - writefln("\t%X", f); - } - else if ($(B _arguments)[i] == typeid(Bar)) - { - Bar b = *cast(Bar*)_argptr; - _argptr += Bar.sizeof; - writefln("\t%X", b); - } - else - assert(0); - } -} - -void main() { - Foo f = new Foo(); - Bar b = new Bar(); - - writefln("%X", f); - printargs(1, 2, 3L, 4.5, f, b); -} ------- - - which prints: - ------- -00870FE0 -5 arguments -int - 2 -long - 3 -double - 4.5 -Foo - 00870FE0 -Bar - 00870FD0 ------- - - To protect against the vagaries of stack layouts on different - CPU architectures, use $(B std.stdarg) to access the variadic - arguments: - ------- -import std.stdio; -import $(B std.stdarg); - -void foo(int x, ...) { - writefln("%d arguments", _arguments.length); - for (int i = 0; i < _arguments.length; i++) - { - _arguments[i].print(); - - if (_arguments[i] == typeid(int)) - { - int j = $(B va_arg)!(int)(_argptr); - writefln("\t%d", j); - } - else if (_arguments[i] == typeid(long)) - { - long j = $(B va_arg)!(long)(_argptr); - writefln("\t%d", j); - } - else if (_arguments[i] == typeid(double)) - { - double d = $(B va_arg)!(double)(_argptr); - writefln("\t%g", d); - } - else if (_arguments[i] == typeid(FOO)) - { - FOO f = $(B va_arg)!(FOO)(_argptr); - writefln("\t%X", f); - } - else - assert(0); - } -} ------- - -

    Typesafe Variadic Functions

    - - Typesafe variadic functions are used when the variable argument - portion of the arguments are used to construct an array or - class object. -

    - - For arrays: - ------- -int test() { - return sum(1, 2, 3) + sum(); // returns 6+0 -} - -int func() { - int[3] ii = [4, 5, 6]; - return sum(ii); // returns 15 -} - -int sum(int[] ar ...) { - int s; - foreach (int x; ar) - s += x; - return s; -} ------- - - For static arrays: - ------- -int test() { - return sum(2, 3); // error, need 3 values for array - return sum(1, 2, 3); // returns 6 -} - -int func() { - int[3] ii = [4, 5, 6]; - int[] jj = ii; - return sum(ii); // returns 15 - return sum(jj); // error, type mismatch -} - -int sum(int[3] ar ...) { - int s; - foreach (int x; ar) - s += x; - return s; -} ------- - - For class objects: - ------- -class Foo { - int x; - string s; - - this(int x, string s) { - this.x = x; - this.s = s; - } -} - -void test(int x, Foo f ...); - -... - -Foo g = new Foo(3, "abc"); -test(1, g); // ok, since g is an instance of Foo -test(1, 4, "def"); // ok -test(1, 5); // error, no matching constructor for Foo ------- - - An implementation may construct the object or array instance - on the stack. Therefore, it is an error to refer to that - instance after the variadic function has returned: - ------- -Foo test(Foo f ...) { - return f; // error, f instance contents invalid after return -} - -int[] test(int[] a ...) { - return a; // error, array contents invalid after return - return a[0..1]; // error, array contents invalid after return - return a.dup; // ok, since copy is made -} ------- - - For other types, the argument is built with itself, as in: - ------- -int test(int i ...) { - return i; -} - -... -test(3); // returns 3 -test(3, 4); // error, too many arguments -int[] x; -test(x); // error, type mismatch ------- - -

    Lazy Variadic Functions

    - - $(P If the variadic parameter is an array of delegates - with no parameters: - ) - ---- -void foo(int delegate()[] dgs ...); ---- - - $(P Then each of the arguments whose type does not match that - of the delegate is converted to a delegate. - ) - ---- -int delegate() dg; -foo(1, 3+x, dg, cast(int delegate())null); ---- - - $(P is the same as:) - ---- -foo( { return 1; }, { return 3+x; }, dg, null ); ---- - -

    $(LNAME2 Local Variables, Local Variables)

    - - $(P It is an error to use a local variable without first assigning it a - value. The implementation may not always be able to detect these - cases. Other language compilers sometimes issue a warning for this, - but since it is always a bug, it should be an error. - ) - - $(P It is an error to declare a local variable that is never referred to. - Dead variables, like anachronistic dead code, are just a source of - confusion for maintenance programmers. - ) - - $(P It is an error to declare a local variable that hides another local - variable in the same function: - ) - ------- -void func(int x) { - int x; // error, hides previous definition of x - double y; - ... - { char y; // error, hides previous definition of y - int z; - } - { wchar z; // legal, previous z is out of scope - } -} ------- - - $(P While this might look unreasonable, in practice whenever - this is done it either is a - bug or at least looks like a bug. - ) - - $(P It is an error to return the address of or a reference to a - local variable. - ) - - $(P It is an error to have a local variable and a label with the same - name. - ) - -

    $(LNAME2 Local Static Variables, Local Static Variables)

    - - $(P Local variables in functions can be declared as static - $(V2 or __gshared) in which case they are statically allocated - rather than being allocated on the stack. - As such, their value persists beyond the exit of the function. - ) - ---- -void foo() { - static int n; - if (++n == 100) - writeln("called 100 times"); -} ---- - - $(P The initializer for a static variable must be evaluatable at - compile time, and they are initialized upon the start of the thread - $(V2 (or the start of the program for __gshared). - There are no static constructors or static destructors - for static local variables.) - ) - - $(P Although static variable name visibility follows the usual scoping - rules, the names of them must be unique within a particular function. - ) - ---- -void main() { - { static int x; } - { static int x; } // error - { int i; } - { int i; } // ok -} ---- - -

    Nested Functions

    - - $(P Functions may be nested within other functions:) - ------- -int bar(int a) { - int foo(int b) { - int abc() { return 1; } - - return b + abc(); - } - return foo(a); -} - -void test() { - int i = bar(3); // i is assigned 4 -} ------- - - $(P Nested functions can be accessed only if the name is in scope.) - ------- -void foo() -{ - void A() - { - B(); // error, B() is forward referenced - C(); // error, C undefined - } - void B() - { - A(); // ok, in scope - void C() - { - void D() - { - A(); // ok - B(); // ok - C(); // ok - D(); // ok - } - } - } - A(); // ok - B(); // ok - C(); // error, C undefined -} ------- - - $(P and:) - ------- -int bar(int a) { - int foo(int b) { return b + 1; } - int abc(int b) { return foo(b); } // ok - return foo(a); -} - -void test() { - int i = bar(3); // ok - int j = bar.foo(3); // error, bar.foo not visible -} ------- - - $(P Nested functions have access to the variables and other symbols - defined by the lexically enclosing function. - This access includes both the ability to read and write them. - ) - ------- -int bar(int a) { - int c = 3; - - int foo(int b) { - b += c; // 4 is added to b - c++; // bar.c is now 5 - return b + c; // 12 is returned - } - c = 4; - int i = foo(a); // i is set to 12 - return i + c; // returns 17 -} - -void test() { - int i = bar(3); // i is assigned 17 -} ------- - - $(P This access can span multiple nesting levels:) - ------- -int bar(int a) { - int c = 3; - - int foo(int b) { - int abc() { - return c; // access bar.c - } - return b + c + abc(); - } - return foo(3); -} ------- - - $(P Static nested functions cannot access any stack variables of - any lexically enclosing function, but can access static variables. - This is analogous to how static member functions behave. - ) - ------- -int bar(int a) { - int c; - static int d; - - static int foo(int b) { - b = d; // ok - b = c; // error, foo() cannot access frame of bar() - return b + 1; - } - return foo(a); -} ------- - - $(P Functions can be nested within member functions:) - ------- -struct Foo { - int a; - - int bar() { - int c; - - int foo() { - return c + a; - } - return 0; - } -} ------- - - $(P Member functions of nested classes and structs do not have - access to the stack variables of the enclosing function, but - do have access to the other symbols: - ) - ------- -void test() { - int j; - static int s; - - struct Foo { - int a; - - int bar() { - int c = s; // ok, s is static - int d = j; // error, no access to frame of test() - - int foo() { - int e = s; // ok, s is static - int f = j; // error, no access to frame of test() - return c + a; // ok, frame of bar() is accessible, - // so are members of Foo accessible via - // the 'this' pointer to Foo.bar() - } - - return 0; - } - } -} ------- - - $(P Nested functions always have the D function linkage type. - ) - - $(P Unlike module level declarations, declarations within function - scope are processed in order. This means that two nested functions - cannot mutually call each other: - ) - ------- -void test() { - void foo() { bar(); } // error, bar not defined - void bar() { foo(); } // ok -} ------- - - $(P The solution is to use a delegate:) - ------- -void test() { - void delegate() fp; - void foo() { fp(); } - void bar() { foo(); } - fp = &bar; -} ------- - - $(P Nested functions cannot be overloaded.) - -

    Delegates, Function Pointers, and $(V1 Dynamic) Closures

    - - $(P A function pointer can point to a static nested function:) - ------- -int function() fp; - -void test() { - static int a = 7; - static int foo() { return a + 3; } - - fp = &foo; -} - -void bar() { - test(); - int i = fp(); // i is set to 10 -} ------- - - $(P A delegate can be set to a non-static nested function:) - ------- -int delegate() dg; - -void test() { - int a = 7; - int foo() { return a + 3; } - - dg = &foo; - int i = dg(); // i is set to 10 -} ------- - -$(V1 - $(P The stack variables, however, are not valid once the function - declaring them has exited, in the same manner that pointers to - stack variables are not valid upon exit from a function: - ) - ------- -int* bar() { - int b; - test(); - int i = dg(); // error, test.a no longer exists - return &b; // error, bar.b not valid after bar() exits -} ------- -) -$(V2 - $(P The stack variables referenced by a nested function are - still valid even after the function exits (this is different - from D 1.0). This is called a $(I closure). - Returning addresses of stack variables, however, is not - a closure and is an error. - ) - ------- -int* bar() { - int b; - test(); - int i = dg(); // ok, test.a is in a closure and still exists - return &b; // error, bar.b not valid after bar() exits -} ------- -) - - $(P Delegates to non-static nested functions contain two pieces of - data: the pointer to the stack frame of the lexically enclosing - function (called the $(I frame pointer)) and the address of the - function. This is analogous to struct/class non-static member - function delegates consisting of a $(I this) pointer and - the address of the member function. - Both forms of delegates are interchangeable, and are actually - the same type: - ) - ------- -struct Foo { - int a = 7; - int bar() { return a; } -} - -int foo(int delegate() dg) { - return dg() + 1; -} - -void test() { - int x = 27; - int abc() { return x; } - Foo f; - int i; - - i = foo(&abc); // i is set to 28 - i = foo(&f.bar); // i is set to 8 -} ------- - - $(P This combining of the environment and the function is called - a $(I dynamic closure). - ) - - $(P The $(B .ptr) property of a delegate will return the - $(I frame pointer) value as a $(TT void*). - ) - - $(P The $(B .funcptr) property of a delegate will return the - $(I function pointer) value as a function type. - ) - - $(P $(B Future directions:) Function pointers and delegates may merge - into a common syntax and be interchangeable with each other. - ) - -

    Anonymous Functions and Anonymous Delegates

    - - $(P See $(GLINK2 expression, FunctionLiteral)s. - ) - -

    main() Function

    - - $(P For console programs, $(TT main()) serves as the entry point. - It gets called after all the module initializers are run, and - after any unittests are run. - After it returns, all the module destructors are run. - $(TT main()) must be declared using one of the following forms: - ) - ----- -void main() { ... } -void main(string[] args) { ... } -int main() { ... } -int main(string[] args) { ... } ----- - -

    $(LNAME2 interpretation, Compile Time Function Execution (CTFE))

    - - $(P Functions which are both portable and free of side-effects can be - executed at compile time. This is useful when constant folding - algorithms need to include recursion and looping. Compile time function - execution is subject to the following restrictions: - ) - - $(OL - $(LI the function source code must be available to the compiler. Functions - which exist in the source code only as $(D_KEYWORD extern) declarations - cannot be executed at compile time) - - $(LI executed expressions may not reference any global or local - static variables) - - $(LI $(D_KEYWORD asm) statements are not permitted) - - $(LI non-portable casts (eg, from $(I int[]) to $(I float[])), including - casts which depend on endianness, are not permitted. - Casts between signed and unsigned types are permitted. - Any pointer may be cast to $(I void *) and from $(I void *) back to - its original type. Casting between pointer and non-pointer types is - prohibited. - ) - - $(LI C-style semantics on pointer arithmetic are strictly enforced. - $(P - Pointer arithmetic is permitted only on pointers which point to static - or dynamic array elements. Such pointers must point to an element of - the array, or to the first element past the array. - Ordered comparison (<, <=, >, >=) between pointers is permitted only - between pointers which point to the same array. - Pointer arithmetic is completely forbidden on pointers which are null, - or which point to a non-array. - ) - $(P - Equality comparisons (==, !=, $(D_KEYWORD is), $(D_KEYWORD !is)) are - permitted between all pointers, without restriction. - ) - ) - $(LI Non-recoverable errors (such as $(D_KEYWORD assert) failures) do not - throw exceptions; instead, they end interpretation immediately. - ) - ) - - $(P Note that the above restrictions apply only to expressions which are - actually executed. For example: - ) ---- -static int y = 0; - -int countTen(int x) { - if (x > 10) - ++y; - return x; -} - -static assert(countTen(6) == 6); // OK -static assert(countTen(12) == 12); // invalid, modifies y. ---- -$(V2 - $(P The $(D_KEYWORD __ctfe) boolean pseudo-variable, which evaluates to $(D_KEYWORD true) - at compile time, but $(D_KEYWORD false) at run time, can be used to provide - an alternative execution path to avoid operations which are forbidden - at compile time. - ) -) - - $(P In order to be executed at compile time, the function - must appear in a context where it must be so executed, for - example:) - - $(UL - $(LI initialization of a static variable) - $(LI dimension of a static array) - $(LI argument for a template value parameter) - ) - ---- -template eval( A... ) { - const typeof(A[0]) eval = A[0]; -} - -int square(int i) { - return i * i; -} - -void foo() { - static j = square(3); // compile time - writefln(j); - writefln(square(4)); // run time - writefln(eval!(square(5))); // compile time -} ---- - - $(P Executing functions at compile time can take considerably - longer than executing it at run time. - If the function goes into an infinite loop, it will hang at - compile time (rather than hanging at run time). - ) - - $(P Functions executed at compile time can give different results - from run time in the following scenarios: - ) - - $(UL - - $(LI floating point computations may be done at a higher - precision than run time) - $(LI dependency on implementation defined order of evaluation) - $(LI use of uninitialized variables) - - ) - - $(P These are the same kinds of scenarios where different - optimization settings affect the results.) - -

    String Mixins and Compile Time Function Execution

    - - $(P Any functions that execute at compile time must also - be executable at run time. The compile time evaluation of - a function does the equivalent of running the function at - run time. This means that the semantics of a function cannot - depend on compile time values of the function. For example:) - ---- -int foo(char[] s) { - return mixin(s); -} - -const int x = foo("1"); ---- - - $(P is illegal, because the runtime code for foo() cannot be - generated. A function template would be the appropriate - method to implement this sort of thing.) - -$(V2 -

    $(LNAME2 function-safety, Function Safety)

    - - $(P $(I Safe functions) are functions that are statically checked - to exhibit no possibility of - $(LINK2 $(WEBURL)glossary.html#undefined_behavior, $(I undefined behavior)). - Undefined behavior is often used as a vector for malicious - attacks. - ) - -

    $(LNAME2 safe-functions, Safe Functions)

    - - $(P Safe functions are marked with the $(CODE @safe) attribute.) - - $(P The following operations are not allowed in safe - functions:) - - $(UL - $(LI No casting from a pointer type to any type other than $(CODE void*).) - $(LI No casting from any non-pointer type to a pointer type.) - $(LI No modification of pointer values.) - $(LI Cannot access unions that have pointers or references overlapping - with other types.) - $(LI Calling any system functions.) - $(LI No catching of exceptions that are not derived from $(CODE class Exception).) - $(LI No inline assembler.) - $(LI No explicit casting of mutable objects to immutable.) - $(LI No explicit casting of immutable objects to mutable.) - $(LI No explicit casting of thread local objects to shared.) - $(LI No explicit casting of shared objects to thread local.) - $(LI No taking the address of a local variable or function parameter.) - $(LI Cannot access $(D_KEYWORD __gshared) variables.) - ) - - $(P Functions nested inside safe functions default to being - safe functions. - ) - - $(P Safe functions are covariant with trusted or system functions.) - - $(P $(B Note:) The verifiable safety of functions may be compromised by - bugs in the compiler and specification. Please report all such errors - so they can be corrected. - ) - -

    $(LNAME2 trusted-functions, Trusted Functions)

    - - $(P Trusted functions are marked with the $(CODE @trusted) attribute.) - - $(P Trusted functions are guaranteed by the programmer to not exhibit - any undefined behavior if called by a safe function. - Generally, trusted functions should be kept small so that they are - easier to manually verify. - ) - - $(P Trusted functions may call safe, trusted, or system functions. - ) - - $(P Trusted functions are covariant with safe or system functions.) - -

    $(LNAME2 system-functions, System Functions)

    - - $(P System functions are functions not marked with $(CODE @safe) or - $(CODE @trusted) - and are not nested inside $(CODE @safe) functions. - System functions may be marked with the $(CODE @system) attribute. - A function being system does not mean it actually is unsafe, it just - means that the compiler is unable to verify that it cannot exhibit - undefined behavior. - ) - - $(P System functions are $(B not) covariant with trusted or safe functions. - ) -) - -$(V2 -

    $(LNAME2 function-attribute-inference, Function Attribute Inference)

    - - $(P $(GLINK2 expression, FunctionLiteral)s and - $(LINK2 $(WEB template.html)#function-templates, function template)s, since their function bodies - are always present, infer the - $(LINK2 #pure-functions, $(B pure)), - $(LINK2 #nothrow-functions, $(B nothrow)), and - $(LINK2 #safe-functions, $(B @safe)) attributes unless - specifically overridden. - ) - - $(P Attribute inference is not done for other functions, even if the function - body is present. - ) - - $(P The inference is done by determining if the function body follows the - rules of the particular attribute. - ) - - $(P Cyclic functions (i.e. functions that wind up directly or indirectly - calling themselves) are inferred as being impure, throwing, and @system. - ) - - $(P If a function attempts to test itself for those attributes, then - the function is inferred as not having those attributes. - ) -) - -) - -Macros: - TITLE=Functions - WIKI=Function - - - CATEGORY_SPEC=$0 diff --git a/future.dd b/future.dd deleted file mode 100644 index e2e5af398e..0000000000 --- a/future.dd +++ /dev/null @@ -1,20 +0,0 @@ -Ddoc - -$(D_S Future Directions, - - $(P The following new features for D are planned for post 1.0, - but the details have - not been worked out:) - - $(OL - $(LI Template inheritance.) - $(LI Array operations.) - ) - -) - -Macros: - TITLE=Future Directions - WIKI=Future - CATEGORY_FAQ=$0 - diff --git a/garbage.dd b/garbage.dd deleted file mode 100644 index 0319817410..0000000000 --- a/garbage.dd +++ /dev/null @@ -1,400 +0,0 @@ -Ddoc - -$(SPEC_S Garbage Collection, - - $(P D is a fully garbage collected language. That means that it is never - necessary - to free memory. Just allocate as needed, and the garbage collector will - periodically return all unused memory to the pool of available memory. - ) - - $(P C and C++ programmers accustomed to explicitly managing memory - allocation and - deallocation will likely be skeptical of the benefits and efficacy of - garbage collection. Experience both with new projects written with - garbage collection in mind, and converting existing projects to garbage - collection shows that: - ) - - $(UL - - $(LI Garbage collected programs are faster. This is counterintuitive, - but the reasons are: - - $(UL - $(LI Reference counting is a common solution to solve explicit - memory allocation problems. The code to implement the increment and - decrement operations whenever assignments are made is one source - of slowdown. Hiding it behind smart pointer classes doesn't help - the speed. (Reference counting methods are not a general solution - anyway, as circular references never get deleted.) - ) - - $(LI Destructors are used to deallocate resources acquired by an object. - For most classes, this resource is allocated memory. - With garbage collection, most destructors then become empty and - can be discarded entirely. - ) - - $(LI All those destructors freeing memory can become significant when - objects are allocated on the stack. For each one, some mechanism must - be established so that if an exception happens, the destructors all - get called in each frame to release any memory they hold. If the - destructors become irrelevant, then there's no need to set up special - stack frames to handle exceptions, and the code runs faster. - ) - - $(LI All the code necessary to manage memory can add up to quite a - bit. The larger a program is, the less in the cache it is, - the more paging it does, and the slower - it runs. - ) - - $(LI Garbage collection kicks in only when memory gets tight. When - memory is not tight, the program runs at full speed and does not - spend any time freeing memory. - ) - - $(LI Modern garbage collectors are far more advanced now than the - older, slower ones. Generational, copying collectors eliminate much - of the inefficiency of early mark and sweep algorithms. - ) - - $(LI Modern garbage collectors do heap compaction. Heap compaction - tends to reduce the number of pages actively referenced by a program, - which means that memory accesses are more likely to be cache hits - and less swapping. - ) - - $(LI Garbage collected programs do not suffer from gradual deterioration - due to an accumulation of memory leaks. - ) - ) - ) - - $(LI Garbage collectors reclaim unused memory, therefore they do not suffer - from "memory leaks" which can cause long running applications to gradually - consume more and more memory until they bring down the system. GC programs - have longer term stability. - ) - - $(LI Garbage collected programs have fewer hard-to-find pointer bugs. This - is because there are no dangling references to freed memory. There is no - code to explicitly manage memory, hence no bugs in such code. - ) - - $(LI Garbage collected programs are faster to develop and debug, because - there's no need for developing, debugging, testing, or maintaining the - explicit deallocation code. - ) - - $(LI Garbage collected programs can be significantly smaller, because - there is no code to manage deallocation, and there is no need for exception - handlers to deallocate memory. - ) - ) - - $(P Garbage collection is not a panacea. There are some downsides: - ) - - $(UL - - $(LI It is not predictable when a collection gets run, so the program - can arbitrarily pause. - ) - - $(LI The time it takes for a collection to run is not bounded. While in - practice it is very quick, this cannot be guaranteed. - ) - - $(LI All threads other than the collector thread must be halted while - the collection is in progress. - ) - - $(LI Garbage collectors can keep around some memory that an explicit - deallocator - would not. In practice, this is not much of an issue since explicit - deallocators usually have memory leaks causing them to eventually use - far more memory, and because explicit deallocators do not normally - return deallocated memory to the operating system anyway, instead just - returning it to its own internal pool. - ) - - $(LI Garbage collection should be implemented as a basic operating - system - kernel service. But since they are not, garbage collecting programs must - carry around with them the garbage collection implementation. While this - can be a shared DLL, it is still there. - ) - ) - - $(P These constraints are addressed by techniques outlined - in $(DPLLINK memory.html, Memory Management). - ) - -

    How Garbage Collection Works

    - - $(P The GC works by:) - - $(OL - $(LI Looking for all the pointer $(SINGLEQUOTE roots) into GC allocated memory.) - - $(LI Recursively scanning all allocated memory pointed to by - roots looking for more pointers into GC allocated memory.) - - $(LI Freeing all GC allocated memory that has no active pointers - to it.) - - $(LI Possibly compacting the remaining used memory by copying the - allocated objects (called a copying collector).) - ) - -

    Interfacing Garbage Collected Objects With Foreign Code

    - - $(P The garbage collector looks for roots in:) - $(OL - $(LI its static data segment) - $(LI the stacks and register contents of each thread) - $(LI any roots added by std.gc.addRoot() or std.gc.addRange()) - ) - - $(P If the only root of an object - is held outside of this, then the collecter will miss it and free the - memory. - ) - - $(P To avoid this from happening,) - - $(UL - $(LI Maintain a root to the object in an area the collector does scan - for roots.) - - $(LI Add a root to the object using std.gc.addRoot() or std.gc.addRange().) - - $(LI Reallocate and copy the object using the foreign code's storage - allocator - or using the C runtime library's malloc/free. - ) - ) - -

    Pointers and the Garbage Collector

    - - $(P Pointers in D can be broadly divided into two categories: those that - point to garbage collected memory, and those that do not. Examples - of the latter are pointers created by calls to C's malloc(), pointers - received from C library routines, pointers to static data, - pointers to objects on the stack, etc. For those pointers, anything - that is legal in C can be done with them. - ) - - $(P For garbage collected pointers and references, however, there are - some - restrictions. These restrictions are minor, but they are intended - to enable the maximum flexibility in garbage collector design. - ) - - $(P Undefined behavior:) - - $(UL - - $(LI Do not xor pointers with other values, like the - xor pointer linked list trick used in C. - ) - - $(LI Do not use the xor trick to swap two pointer values. - ) - - $(LI Do not store pointers into non-pointer variables using casts and - other tricks. - ------- -void* p; -... -int x = cast(int)p; // error: undefined behavior ------- - - The garbage collector does not scan non-pointer types for roots. - ) - - $(LI Do not take advantage of alignment of pointers to store bit flags - in the low order bits: - ------- -p = cast(void*)(cast(int)p | 1); // error: undefined behavior ------- - ) - - $(LI Do not store into pointers values that may point into the - garbage collected heap: - ------- -p = cast(void*)12345678; // error: undefined behavior ------- - - A copying garbage collector may change this value. - ) - - $(LI Do not store magic values into pointers, other than $(D null). - ) - - $(LI Do not write pointer values out to disk and read them back in - again. - ) - - $(LI Do not use pointer values to compute a hash function. A copying - garbage collector can arbitrarily move objects around in memory, - thus invalidating - the computed hash value. - ) - - $(LI Do not depend on the ordering of pointers: - ------- -if (p1 < p2) // error: undefined behavior - ... ------- - since, again, the garbage collector can move objects around in - memory. - ) - - $(LI Do not add or subtract an offset to a pointer such that the result - points outside of the bounds of the garbage collected object originally - allocated. - ------- -char* p = new char[10]; -char* q = p + 6; // ok -q = p + 11; // error: undefined behavior -q = p - 1; // error: undefined behavior ------- - ) - - $(LI Do not misalign pointers if those pointers may - point into the gc heap, such as: - ------- -align (1) struct Foo { - byte b; - char* p; // misaligned pointer -} ------- - - Misaligned pointers may be used if the underlying hardware - supports them $(B and) the pointer is never used to point - into the gc heap. - ) - - $(LI Do not use byte-by-byte memory copies to copy pointer values. - This may result in intermediate conditions where there is - not a valid pointer, and if the gc pauses the thread in such a - condition, it can corrupt memory. - Most implementations of $(D memcpy()) will work since the - internal implementation of it does the copy in aligned chunks - greater than or equal to a pointer size, but since this kind of - implementation is not guaranteed by the C standard, use - $(D memcpy()) only with extreme caution. - ) - - $(LI Do not have pointers in a struct instance that point back - to the same instance. The trouble with this is if the instance - gets moved in memory, the pointer will point back to where it - came from, with likely disastrous results. - ) - - ) - - $(P Things that are reliable and can be done:) - - $(UL - - $(LI Use a union to share storage with a pointer: - ------- -union U { void* ptr; int value } ------- - ) - - $(LI A pointer to the start of a garbage collected object need not - be maintained if a pointer to the interior of the object exists. - ------- -char[] p = new char[10]; -char[] q = p[3..6]; -// q is enough to hold on to the object, don't need to keep -// p as well. ------- - ) - ) - - $(P One can avoid using pointers anyway for most tasks. D provides - features - rendering most explicit pointer uses obsolete, such as reference - objects, - dynamic arrays, and garbage collection. Pointers - are provided in order to interface successfully with C APIs and for - some low level work. - ) - -

    Working with the Garbage Collector

    - - $(P Garbage collection doesn't solve every memory deallocation problem. - For - example, if a root to a large data structure is kept, the garbage - collector cannot reclaim it, even if it is never referred to again. To - eliminate this problem, it is good practice to set a reference or - pointer to an object to null when no longer needed. - ) - - $(P This advice applies only to static references or references embedded - inside other objects. There is not much point for such stored on the - stack to be nulled, since the collector doesn't scan for roots past the - top of the stack, and because new stack frames are initialized anyway. - ) - -

    Object Pinning and a Moving Garbage Collector

    - - $(P Although D does not currently use a moving garbage collector, by following - the rules listed above one can be implemented. No special action is required - to pin objects. A moving collector will only move objects for which there - are no ambiguous references, and for which it can update those references. - All other objects will be automatically pinned. - ) - -

    D Operations That Involve the Garbage Collector

    - - $(P Some sections of code may need to avoid using the garbage collector. - The following constructs may allocate memory using the garbage collector: - ) - - $(UL - $(LI $(GLINK2 expression, NewExpression)) - $(LI Array appending) - $(LI Array concatenation) - $(LI Array literals (except when used to initialize static data)) - $(LI Associative array literals) - $(LI Any insertion, removal, or lookups in an associative array) - $(LI Extracting keys or values from an associative array) - $(V2 - $(LI Taking the address of (i.e. making a delegate) a nested function that - accesses variables in an outer scope) - $(LI A function literal that access variables in an outer scope) - ) - $(LI An $(GLINK2 expression, AssertExpression) that fails its condition) - ) - -

    References

    - - $(UL - $(LI $(LINK2 http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29, Wikipedia)) - $(LI $(LINK2 http://www.iecc.com/gclist/GC-faq.html, GC FAQ)) - $(LI $(LINK2 ftp://ftp.cs.utexas.edu/pub/garbage/gcsurvey.ps, Uniprocessor Garbage Collector Techniques)) - $(LI $(AMAZONLINK 0471941484, Garbage Collection : Algorithms for Automatic Dynamic Memory Management)) - ) - -) - -Macros: - TITLE=Garbage Collection - WIKI=Garbage - CATEGORY_SPEC=$0 - diff --git a/glossary.dd b/glossary.dd deleted file mode 100644 index 3a4f90bea0..0000000000 --- a/glossary.dd +++ /dev/null @@ -1,230 +0,0 @@ -Ddoc - -$(D_S Glossary, - -$(DL - - $(DT $(LNAME2 blit, $(ACRONYM BLIT, Block Transfer))) - $(DD Also known as BLT, blit refers to copying memory - byte for byte. In C, this is referred to as a memcpy - operation. - The name originated with the BLT instruction on the - DEC PDP-10 computer. - ) - - $(DT $(LNAME2 ctfe, $(ACRONYM CTFE, Compile Time Function Evaluation))) - $(DD Refers to the ability to execute regular D - functions at compile time rather than at run time.) - - $(DT code point) $(DD In Unicode terminology, a$(LUCKY code point) - is a logical character. The range of code points is $(D 0) - through $(D 0x10FFFF). Only $(D dchar)s can store code points - directly; arrays of $(D char) and $(D wchar) need to use the - variable-length encodings $(LUCKY UTF-8) and $(LUCKY UTF-16).) - - $(DT $(LNAME2 cow, $(ACRONYM COW, Copy On Write))) - $(DD COW is a memory allocation strategy where arrays are copied - if they are to be modified. - ) - - $(DT $(LNAME2 data_race, Data Race)) $(DD One thread reading or writing - a memory location while another thread is reading or writing that same location. - ) - - $(DT $(LNAME2 functor, Functor)) $(DD An user-defined type (struct or - class) that defines the function call operator ($(DC opCall) in D) and - as such can be used similarly to a function. - ) - - $(DT $(LNAME2 gc, $(ACRONYM GC, Garbage Collection))) - $(DD Garbage collection is the common name for the - term automatic memory management. Memory can be allocated and used, - and the GC will automatically free any chunks of memory no longer - referred to. In contrast, explicit memory management - is where the programmer must carefully match up each allocation with - one and only one free. - ) - - $(DT Higher-order function) $(DD A function that either accepts another - function as a parameter, returns a function, or both. - ) - - $(DT Illegal) - $(DD A code construct is illegal if it does not conform to the - D language specification. - This may be true even if the compiler or runtime fails to detect - the error. - ) - - $(DT Input range) $(DD A type (i.e., a struct or a class) that - defines the member functions empty, head, and next. Input ranges - are assumed to be strictly one-pass: there is no way to save the - state of the iteration in a copy of the range. See also $(LINK2 - phobos/std_range.html,range).) - - $(DT Implementation Defined Behavior) - $(DD This is variation in behavior of the D language in a manner - that is up to the implementor of the language. - An example of implementation defined behavior would be the size in - bytes of a pointer: on a 32 bit machine it would be 4 bytes, on - a 64 bit machine it would be 8 bytes. - Minimizing implementation defined behavior in the language will - maximize the portability of code. - ) - - $(DT $(LNAME2 nrvo, $(ACRONYM NRVO, Named Return Value Optimization))) - $(DD - $(P NRVO is a technique invented by Walter Bright around - 1991 (the term for it was coined later) to minimize copying of struct - data. - Functions normally return their function return values in - registers. For structs, however, they often are too big to - fit in registers. The usual solution to this is to pass to - the function a $(I hidden pointer) to a struct instance in the - caller's stack frame, and the return value is copied there. - For example: - ) ---- -struct S { int a, b, c, d; } - -S foo() -{ - S result; - result.a = 3; - return result; -} - -void test() -{ - S s = foo(); -} ---- - - $(P is rewritten as:) - ---- -S* foo(S* hidden) -{ - S result; - result.a = 3; - *hidden = result; - return hidden; -} - -void test() -{ - S tmp; - S s = *foo(&tmp); -} ---- - $(P This rewrite gives us an extra temporary object $(D tmp), - and copies the struct contents twice. - What NRVO does is recognize that the sole purpose of $(D result) - is to provide a return value, and so all references to $(D result) - can be replaced with $(D *hidden). - $(D foo) is then rewritten as: - ) ---- -S* foo(S* hidden) -{ - hidden.a = 3; - return hidden; -} ---- - $(P A further optimization is done on the call to $(D foo) to eliminate - the other copy, giving:) ---- -void test() -{ - S s; - foo(&s); -} ---- - $(P The result is written directly into the destination $(D s), - instead of passing through two other instances.) - ) - - $(DT $(LNAME2 narrow strings, narrow strings)) $(DD All arrays - that use $(D char), $(D wchar), and their qualified versions are - narrow strings. (Those include $(D string) and $(D - wstring)). Range-oriented functions in the standard library handle - narrow strings specially by automatically decoding the UTF-encoded - characters.) - - $(DT $(LNAME2 opApply, opApply)) - $(DD A special member function used to iterate over a - collection; this is used by the - $(LINK2 statement.html#opApply, $(I ForeachStatement)). - ) - - $(DT $(LNAME2 opApplyReverse, opApplyReverse)) - $(DD A special member function used to iterate over a - collection in the reverse order; this is used by the - $(LINK2 statement.html#opApplyReverse, $(I ForeachStatement)). - ) - - $(DT $(LNAME2 pod, $(ACRONYM POD, Plain Old Data))) - $(DD Refers to a struct that contains no hidden members, - does not have virtual functions, does not inherit, - has no destructor, - and can be initialized and copied via simple bit copies. - D structs are POD. - ) - - $(DT $(LNAME2 predicate, Predicate)) $(DD A function or - delegate returning a Boolean result. Predicates can be nullary - (take no arguments), unary (take one argument), binary (take - two arguments), or n-ary (take n arguments). Usually - predicates are mentioned within the context of higher-order - functions, which accept predicates as parameters. - ) - - $(DT $(LNAME2 raii, $(ACRONYM RAII, Resource Acquisition Is Initialization))) - $(DD RAII refers to the technique of having the destructor - of a class object called when the object goes out of scope. - The destructor then releases any resources acquired by - that object. - RAII is commonly used for resources that are in short supply - or that must have a predictable point when they are released. - RAII objects in D are created using the $(D scope) storage class. - ) - - $(DT $(LNAME2 sequential_consistency, Sequential Consistency)) - $(DD Data being written in one order in one thread - being visible in the same order to another thread. - ) - - $(DT $(LNAME2 sfinae, $(ACRONYM SFINAE, Substitution Failure Is Not An Error))) - $(DD If template argument deduction results in a type - that is not valid, that specialization of the template - is not considered further. It is not a compile error. - See also $(LINK2 http://www.semantics.org/once_weakly/w02_SFINAE.pdf, SFINAE). - ) - - $(DT $(LNAME2 tmp, $(ACRONYM TMP, Template Metaprogramming))) - $(DD TMP is using the template features of the language to - execute programs at compile time rather than runtime.) - - $(DT $(LNAME2 tls, $(ACRONYM TLS, Thread Local Storage))) - $(DD TLS allocates each thread its own instance of the - global data. See also - $(LINK2 http://en.wikipedia.org/wiki/Thread-local_storage, Wikipedia).) - - $(DT $(LNAME2 undefined_behavior, $(ACRONYM UB, Undefined Behavior))) - $(DD Undefined behavior happens when an illegal code construct is - executed. Undefined behavior can include random, erratic results, - crashes, faulting, etc. - A buffer overflow is an example of undefined behavior. - ) - -) - -) - -Macros: - TITLE=Glossary - WIKI=Glossary - D=$0 - LUCKY=$(WEB google.com/search?btnI=I%27m+Feeling+Lucky&ie=UTF-8&oe=UTF-8&q=$0,$0) - WEB=$(LINK2 http://$1,$2) - CATEGORY_APPENDICES=$0 diff --git a/gpg_keys.dd b/gpg_keys.dd new file mode 100644 index 0000000000..50c8876b6b --- /dev/null +++ b/gpg_keys.dd @@ -0,0 +1,73 @@ +Ddoc + +$(H2 D Release Team) + +$(P Since 2.067.0 dmd binaries and git tags are signed by D's release managers. The following GnuPG keys can be used to verify those signatures.) + +$(PRE +pub rsa4096 2014-09-01 [SC] [expired: 2020-03-25] + AFC7 DB45 693D 62BB 472B F27B AB8F E924 C2F7 E724 +uid Martin Nowak (dawg) $(LT)me@dawg.eu$(GT) +uid Martin Nowak $(LT)martin.nowak@plugintheworld.com$(GT) +uid Martin Nowak $(LT)code@dawg.eu$(GT) +uid Martin Nowak $(LT)martin@dlang.org$(GT) + +pub rsa2048 2016-01-29 [SC] + BBED 1B08 8CED 7F95 8917 FBE8 5004 F0FA D051 576D +uid Vladimir Panteleev $(LT)gpg@thecybershadow.net$(GT) +sub rsa2048 2016-01-29 [E] + +pub rsa4096 2015-11-24 [SC] [expires: 2026-03-23] + 8FDB 8D35 7AF4 68A9 428A CE3C 2055 F766 01A3 6FB0 +uid Sebastian Wilzbach $(LT)seb@wilzba.ch$(GT) +uid Sebastian Wilzbach $(LT)sebi@wilzbach.me$(GT) + +pub rsa4096 2025-01-09 [SC] + F3F896F3274BBD9BBBA59058710592E7FB7AF6CA +uid Dennis Korpel +sub rsa4096 2025-01-09 [E] + +pub rsa4096 2018-03-26 [SC] [expired: 2020-03-25] + F771 5881 4C19 E5E0 7BA1 079A 6539 4AFE F4A6 8565 +uid DLang Nightly (bot) $(LT)builder@nightlies.dlang.org$(GT) + +pub rsa4096 2020-03-12 [SC] [revoked: 2022-03-22] + F46A 10D0 AB44 C3D1 5DD6 5797 BCDD 73FF C3EB 6146 +uid Martin Nowak $(LT)code@dawg.eu$(GT) +uid Martin Nowak $(LT)martin.nowak@7learnings.com$(GT) +uid Martin Nowak $(LT)martin@dlang.org$(GT) + +pub rsa4096 2013-09-28 [SC] [expires: 2024-02-13] + 30AE 2FC4 5DE4 1532 68ED 9175 4CF5 FA53 26CC 62EB +uid Iain Buclaw $(LT)ibuclaw@gdcproject.org$(GT) +uid Iain Buclaw $(LT)iain.buclaw@dlang.org$(GT) +uid Iain Buclaw $(LT)ibuclaw@gcc.gnu.org$(GT) +sub rsa4096 2013-09-28 [E] [expires: 2024-02-13] +sub rsa4096 2023-02-13 [S] [expires: 2024-02-13] + +pub ed25519 2022-03-22 [SC] [expires: 2024-03-21] + F8A2 6D5D 7572 ECA0 6EC7 9731 82C5 2E37 A8BC 8393 +uid Martin Nowak $(LT)code@dawg.eu$(GT) +uid Martin Nowak $(LT)martin@dlang.org$(GT) +uid Martin Nowak $(LT)martin.nowak@7learnings.com$(GT) +sub cv25519 2022-03-22 [E] [expires: 2024-03-21] +sub ed25519 2022-03-22 [S] [expires: 2024-03-21] +) + +$(P You can also download them as $(LINK2 d-keyring.gpg,keyring) file.) + +$(H2 D Security Team) + +The $(DDLINK security, $(DASH) ,security team) has its own key: + +$(PRE +pub rsa4096/0x8FF049B29638EDD2 2018-07-05 [SC] [expires: 2020-07-04] + Key fingerprint = E05A B3C3 0EC0 C7DD 56D9 9B0C 8FF0 49B2 9638 EDD2 +uid DLang Security Team $(LT)security@dlang.org$(GT) +sub rsa4096/0x65301656B271FEA0 2018-07-05 [E] [expires: 2020-07-04] +) + +$(P You can also download the $(LINK2 d-security.asc,public key).) + +Macros: + TITLE=GPG Keys diff --git a/gsoc2011.dd b/gsoc/gsoc2011.dd similarity index 92% rename from gsoc2011.dd rename to gsoc/gsoc2011.dd index c5cb4bec0a..b138a39373 100644 --- a/gsoc2011.dd +++ b/gsoc/gsoc2011.dd @@ -1,6 +1,6 @@ Ddoc -$(D_S D Programming Language $(VER), +$(D_S D Programming Language, $(HTMLTAG h2, Digital Mars participates in the 2011 Google Summer of Code program) @@ -54,15 +54,14 @@ visible projects.) $(HTMLTAG h3, Application) $(P To apply as a mentor or a student, refer to our $(LINK2 -http://www.google-melange.com/gsoc/org/google/gsoc2011/dprogramminglanguage, +http://www.google-melange.com/gsoc/org2/google/gsoc2011/dprogramminglanguage, GSoC 2011 page). Applications for students open on Monday March 28, 2011. For additional information, write email to $(LINK2 -mail:gsoc@digitalmars.com, gsoc@digitalmars.com).) +mailto:gsoc@digitalmars.com, gsoc@digitalmars.com).) $(P Good luck!) ) Macros: - TITLE=GSoC2011 - WIKI=GSoC2011 + TITLE=GSoC2011 HTMLTAG=<$1>$+ diff --git a/gsoc/gsoc2012-template.dd b/gsoc/gsoc2012-template.dd new file mode 100644 index 0000000000..04c56f999d --- /dev/null +++ b/gsoc/gsoc2012-template.dd @@ -0,0 +1,68 @@ +Ddoc + +$(D_S D Programming Language, + +$(HTMLTAG h2, Application template for the 2012 Google Summer of +Code program) + +$(HTMLTAG h3, Personal Details) + +$(P +$(UL +$(LI Name ) +$(LI Email ) +$(LI Personal website ) +$(LI Skype/GTalk ID ) +$(LI IRC nickname ) +$(LI Phone number ) +) +) + +$(HTMLTAG h3, Skills) + +$(P +$(UL +$(LI School ) +$(LI Years completed ) +$(LI Anticipated graduation ) +$(LI Academic performance (list relevant coursework taken and grades) ) +$(LI Programming experience level ) +$(LI D experience level ) +$(LI If you participated to past D projects or others (preferably open source), include a brief description of each) +$(LI Also list any specific skills in the specific project area (classes taken, research conducted, blogs and publications etc.)) +$(UL References (names and emails of up to four relevant professors, employers or collaborators)) +) +) + +$(HTMLTAG h3, Your Project) + +$(P +$(UL +$(LI One-sentence elevator pitch ) +$(LI Detailed description ) +$(LI How many hours per week do you expect to spend on the project? ) +$(LI Your current progress on the idea—e.g. research, gathering information, concrete work if applicable ) +$(LI Anticipated impact—if you implemented your idea to perfection, how will it have made the world a better place?) +$(LI Anticipated challenges) +$(LI Potential mentors) +) +) + +$(HTMLTAG h3, Major Milestones) + +$(P Put together a broad project plan. What are the major deliverables that would mark progress in your work, and when do you plan on delivering them? For example:) + +$(UL +$(LI 06/01 Revise project plan with mentor, discuss strategy of approach) +$(LI 06/15 Mocks, small prototype available, finish research on the topic, begin coding) +$(LI 07/15 First reviewable code submitted implementing X, Y, and Z) +$(LI 08/15 Feature complete, review overall progress) +$(LI 09/01 Rule the world) +) + +$(P Good luck!) +) + +Macros: + TITLE=GSoC2012 + HTMLTAG=<$1>$+ diff --git a/gsoc/gsoc2012.dd b/gsoc/gsoc2012.dd new file mode 100644 index 0000000000..3c275424ab --- /dev/null +++ b/gsoc/gsoc2012.dd @@ -0,0 +1,65 @@ +Ddoc + +$(D_S D Programming Language, + +$(HTMLTAG h2, Digital Mars is participating to the 2012 Google Summer of +Code program) + +$(P We welcome mentor applications (student applications will open on +March 26) for any project that adds value to the D programming +language environment. That includes the compiler, the standard +library, additional library support, interoperability, editor and IDE +support, and more. Please refer to the $(LINK2 +http://prowiki.org/wiki4d/wiki.cgi?GSOC_2012_Ideas, ideas wiki page) +for possible projects, and by all means feel free to add your +own. Discuss any initiative you may have with the vibrant D community +on the $(LINK2 https://forum.dlang.org, forums).) + +$(HTMLTAG h3, Mentors) + +$(P Mentor applicants should be domain experts and/or seasoned users +of the D programming language. Experience with managing or teaching is +helpful. Knowledge of D is not a strict requirement because we already +have student applicants who are fluent in D but need specialized +guidance in project-specific topics.) + +$(P Mentors should include a resumé unless they are well known +within the programming community at large, or within the D community.) + +$(P Current mentors: Walter Bright (Digital Mars), Andrei Alexandrescu +(Facebook), David Simcha (Johns Hopkins University), Alex Rønne +Petersen (MCI), Adam Wilson (Prospective Software), Jens Mueller +(Friedrich Schiller University, Jena) Jonas Drewsen (Unity +Technologies), and $(LINK2 http://www.russel.org.uk/, Russel Winder) +(Independent Consultant).) + +$(HTMLTAG h3, Students) + +$(P Student applicants should be familiar with the D programming +language and environment. However, students may use a different +language that helps D's integration within an existing framework +(e.g. Java for Eclipse). Please state in your application other +commitments you may have for the summer so we have a shared notion of +the time you plan to spend on your GSoC project.) + +$(P Student applications should include a project proposal (possibly +starting from one of the $(LINK2 +http://prowiki.org/wiki4d/wiki.cgi?GSOC_2012_Ideas, ideas page)) and a +resumé, unless they already have a known track record in +visible projects. Follow the $(LINK2 gsoc/gsoc2012-template.html, +application template) when putting together your application.) + +$(HTMLTAG h3, Application) + +$(P To apply as a mentor, please email $(LINK2 +http://walterbright.com, Walter) and/or $(LINK2 +http://erdani.com/index.php/contact, Andrei).) + +$(P Student applications will open on March 26, 2012; refer to the +$(LINK2 http://www.google-melange.com/gsoc/events/google/gsoc2012, +timeline) for details.) +) + +Macros: + TITLE=GSoC2012 + HTMLTAG=<$1>$+ diff --git a/gsoc/gsoc2013-template.dd b/gsoc/gsoc2013-template.dd new file mode 100644 index 0000000000..49343c7d24 --- /dev/null +++ b/gsoc/gsoc2013-template.dd @@ -0,0 +1,68 @@ +Ddoc + +$(D_S D Programming Language, + +$(HTMLTAG h2, Application template for the 2013 Google Summer of +Code program) + +$(HTMLTAG h3, Personal Details) + +$(P +$(UL +$(LI Name ) +$(LI Email ) +$(LI Personal website ) +$(LI Skype/GTalk ID ) +$(LI IRC nickname ) +$(LI Phone number ) +) +) + +$(HTMLTAG h3, Skills) + +$(P +$(UL +$(LI School ) +$(LI Years completed ) +$(LI Anticipated graduation ) +$(LI Academic performance (list relevant coursework taken and grades) ) +$(LI Programming experience level ) +$(LI D experience level ) +$(LI If you participated to past D projects or others (preferably open source), include a brief description of each) +$(LI Also list any specific skills in the specific project area (classes taken, research conducted, blogs and publications etc.)) +$(UL References (names and emails of up to four relevant professors, employers or collaborators)) +) +) + +$(HTMLTAG h3, Your Project) + +$(P +$(UL +$(LI One-sentence elevator pitch ) +$(LI Detailed description ) +$(LI How many hours per week do you expect to spend on the project? ) +$(LI Your current progress on the idea—e.g. research, gathering information, concrete work if applicable ) +$(LI Anticipated impact—if you implemented your idea to perfection, how will it have made the world a better place?) +$(LI Anticipated challenges) +$(LI Potential mentors) +) +) + +$(HTMLTAG h3, Major Milestones) + +$(P Put together a broad project plan. What are the major deliverables that would mark progress in your work, and when do you plan on delivering them? For example:) + +$(UL +$(LI 06/01 Revise project plan with mentor, discuss strategy of approach) +$(LI 06/15 Mocks, small prototype available, finish research on the topic, begin coding) +$(LI 07/15 First reviewable code submitted implementing X, Y, and Z) +$(LI 08/15 Feature complete, review overall progress) +$(LI 09/01 Rule the world) +) + +$(P Good luck!) +) + +Macros: + TITLE=GSoC2013 + HTMLTAG=<$1>$+ diff --git a/gsoc/gsoc2013.dd b/gsoc/gsoc2013.dd new file mode 100644 index 0000000000..2d80fd8a8d --- /dev/null +++ b/gsoc/gsoc2013.dd @@ -0,0 +1,66 @@ +Ddoc + +$(D_S D Programming Language, + +$(HTMLTAG h2, Digital Mars is applying to the 2013 Google Summer of +Code program) + +$(P We welcome mentor applications (student applications will open on +April 22) for any project that adds value to the D programming +language environment. That includes the compiler, the standard +library, additional library support, interoperability, editor and IDE +support, and more. Please refer to the $(LINK2 +https://wiki.dlang.org/GSOC_2013_Ideas, ideas wiki page) +for possible projects, and by all means feel free to add your +own. Discuss any initiative you may have with the vibrant D community +on the $(LINK2 https://forum.dlang.org, forums).) + +$(HTMLTAG h3, Mentors) + +$(P Mentor applicants should be domain experts and/or seasoned users +of the D programming language. Experience with managing or teaching is +helpful. Knowledge of D is not a strict requirement because we already +have student applicants who are fluent in D but need specialized +guidance in project-specific topics.) + +$(P Mentors should include a resumé unless they are well known +within the programming community at large, or within the D community.) + +$(P Current mentors: $(HTTP erdani.com, Andrei Alexandrescu) +(Facebook), $(HTTP walterbright.com, Walter Bright) (Digital Mars), +Jens Mueller (Friedrich Schiller University, Jena), Dmitry Olshansky, +Alex Rønne Petersen (MCI), Amaury Sechet (Facebook), Edwin +Smith (Facebook), Adam Wilson (Prospective Software), $(LINK2 +http://www.russel.org.uk/, Russel Winder) (Independent Consultant), +Timothee Cour.) + +$(HTMLTAG h3, Students) + +$(P Student applicants should be familiar with the D programming +language and environment. However, students may use a different +language that helps D's integration within an existing framework +(e.g. Java for Eclipse). Please state in your application other +commitments you may have for the summer so we have a shared notion of +the time you plan to spend on your GSoC project.) + +$(P Student applications should include a project proposal (possibly +starting from one of the $(LINK2 https://wiki.dlang.org/GSOC_2013_Ideas, ideas page)) and a +resumé, unless they already have a known track record in +visible projects. Follow the $(LINK2 gsoc/gsoc2013-template.html, +application template) when putting together your application.) + +$(HTMLTAG h3, Application) + +$(P To apply as a mentor, please email $(LINK2 +http://walterbright.com, Walter) and/or $(LINK2 +http://erdani.com/index.php/contact, Andrei).) + +$(P Student applications will open on April 22, 2013; refer to the +$(LINK2 http://www.google-melange.com/gsoc/events/google/gsoc2013, +timeline) for details.) +) + +Macros: + TITLE=GSoC2013 + HTMLTAG=<$1>$+ + HTTP=$(LINK2 http://$1,$+) diff --git a/hash-map.dd b/hash-map.dd deleted file mode 100644 index 133a81d5aa..0000000000 --- a/hash-map.dd +++ /dev/null @@ -1,367 +0,0 @@ -Ddoc - -$(SPEC_S Associative Arrays, - - $(P Associative arrays have an index that is not necessarily an integer, - and can be sparsely populated. The index for an associative array - is called the $(I key), and its type is called the $(I KeyType). - ) - - $(P Associative arrays are declared by placing the $(I KeyType) - within the [ ] of an array declaration: - ) - ---------- -int[string] b; // associative array b of ints that are - // indexed by an array of characters. - // The $(I KeyType) is string -b["hello"] = 3; // set value associated with key "hello" to 3 -func(b["hello"]); // pass 3 as parameter to func() ---------- - - $(P Particular keys in an associative array can be removed with the - remove function: - ) - ---------- -b.$(B remove)("hello"); ---------- - - $(P The $(I InExpression) yields a pointer to the value - if the key is in the associative array, or $(B null) if not: - ) - ---------- -int* p; -p = ("hello" $(B in) b); -if (p !is (B null)) - ... ---------- - - $(P $(I KeyType)s cannot be functions or voids. - ) - - $(P The element types of an associative array cannot be functions or voids.) - -

    Using Classes as the KeyType

    - - $(P Classes can be used as the $(I KeyType). For this to work, - the class definition must override the following member functions - of class $(D Object):) - - $(UL - $(LI $(D hash_t toHash())) -$(V1 $(LI $(D int opEquals(Object)))) -$(V2 $(LI $(D bool opEquals(Object)))) - $(LI $(D int opCmp(Object))) - ) - - $(P $(D hash_t) is an alias to an integral type.) - - $(P Note that the parameter to $(D opCmp) and $(D opEquals) is - of type - $(D Object), not the type of the class in which it is defined.) - - $(P For example:) - ---- -class Foo { - int a, b; - - hash_t $(B toHash)() { return a + b; } - -$(V1 int $(B opEquals)(Object o))$(V2 bool $(B opEquals)(Object o)) - { Foo foo = cast(Foo) o; - return foo && a == foo.a && b == foo.b; - } - - int $(B opCmp)(Object o) - { Foo foo = cast(Foo) o; - if (!foo) - return -1; - if (a == foo.a) - return b - foo.b; - return a - foo.a; - } -} ---- - - $(P The implementation may use either $(D opEquals) or $(D opCmp) or - both. Care should be taken so that the results of - $(D opEquals) and $(D opCmp) are consistent with each other when - the class objects are the same or not.) - -

    Using Structs or Unions as the KeyType

    - - $(P If the $(I KeyType) is a struct or union type, - a default mechanism is used - to compute the hash and comparisons of it based on the binary - data within the struct value. A custom mechanism can be used - by providing the following functions as struct members: - ) - ---------- -$(V2 const) hash_t $(B toHash)(); -$(V1 int $(B opEquals)($(I KeyType)* s);)$(V2 const bool $(B opEquals)(ref const $(I KeyType) s);) -$(V1 int $(B opCmp)($(I KeyType)* s);)$(V2 const int $(B opCmp)(ref const $(I KeyType) s);) ---------- - - $(P For example:) - -$(V1 ---------- -import std.string; - -struct MyString { - string str; - - hash_t $(B toHash)() - { hash_t hash; - foreach (char c; str) - hash = (hash * 9) + c; - return hash; - } - - bool $(B opEquals)(MyString* s) - { - return std.string.cmp(this.str, s.str) == 0; - } - - int $(B opCmp)(MyString* s) - { - return std.string.cmp(this.str, s.str); - } -} ---------- -) -$(V2 ---------- -import std.string; - -struct MyString { - string str; - - const hash_t $(B toHash)() - { hash_t hash; - foreach (char c; str) - hash = (hash * 9) + c; - return hash; - } - - const bool $(B opEquals)(ref const MyString s) - { - return std.string.cmp(this.str, s.str) == 0; - } - - const int $(B opCmp)(ref const MyString s) - { - return std.string.cmp(this.str, s.str); - } -} ---------- -) - - - $(P The implementation may use either $(D opEquals) or $(D opCmp) or - both. Care should be taken so that the results of - $(D opEquals) and $(D opCmp) are consistent with each other when - the struct/union objects are the same or not.) - -

    Properties

    - -Properties for associative arrays are: - - $(TABLE2 Associative Array Properties, - $(TR $(TH Property) $(TH Description)) - - $(TR - $(TD $(B .sizeof)) - $(TD Returns the size of the reference to the associative - array; it is 4 in 32-bit builds and 8 on 64-bit builds. - ) - ) - - $(TR - $(TD $(B .length)) - $(TD Returns number of values in the associative array. - Unlike for dynamic arrays, it is read-only. - ) - ) - - $(TR - $(TD $(B .keys)) - $(TD Returns dynamic array, the elements of which are the keys in - the associative array. - ) - ) - - $(TR - $(TD $(B .values)) - $(TD Returns dynamic array, the elements of which are the values in - the associative array. - ) - ) - - $(TR - $(TD $(B .rehash)) - $(TD Reorganizes the associative array in place so that lookups - are more efficient. rehash is effective when, for example, - the program is done loading up a symbol table and now needs - fast lookups in it. - Returns a reference to the reorganized array. - ) - ) - -$(V2 - $(TR - $(TD $(B .byKey())) - $(TD Returns a delegate suitable for use as an $(I Aggregate) to - a $(GLINK2 statement, ForeachStatement) - which will iterate over the keys - of the associative array. - ) - ) - - $(TR - $(TD $(B .byValue())) - $(TD Returns a delegate suitable for use as an $(I Aggregate) to - a $(GLINK2 statement, ForeachStatement) - which will iterate over the values - of the associative array. - ) - ) - - $(TR - $(TD $(B .get(Key key, lazy Value defaultValue))) - $(TD Looks up $(I key); if it exists returns corresponding $(I value) - else evaluates and returns $(I defaultValue). - ) - ) -) - ) - -
    -

    Associative Array Example: word count

    - - $(P Let's consider the file is ASCII encoded with LF EOL. - In general case we should use $(I dchar c) for iteration - over code points and functions from $(STD_UNI). - ) - ---------- -import std.file; // D file I/O -import std.stdio; -import std.$(V1 ctype)$(V2 ascii); - -void main (string[] args) { - ulong totalWords, totalLines, totalChars; - ulong[string] dictionary; - - writefln(" lines words bytes file"); - foreach (arg; args[1 .. $]) // for each argument except the first one - { - ulong wordCount, lineCount, charCount; - - $(V1 bool inWord; - size_t wordStart; - - // read file into input buffer - auto input = cast(string)std.file.read(arg); - - foreach (i, char c; input) - { - if (std.ctype.isdigit(c)) - { // c is a digit (0..9) - } - else if (std.ctype.isalpha(c)) - { // c is an ASCII letter (A..Z, a..z) - if (!inWord) - { - wordStart = i; - inWord = true; - ++wordCount; - } - } - else if (inWord) - { - auto word = input[wordStart .. i]; - ++dictionary[word]; // increment count for word - inWord = false; - } - ++charCount; - - // Let's consider the file has LF EOL. - if (c == '\n') - ++lineCount; - } - if (inWord) - { - auto word = input[wordStart .. $]; - ++dictionary[word]; - } -)$(V2 foreach(line; File(arg).byLine()) - { - bool inWord; - size_t wordStart; - - void tryFinishWord(size_t wordEnd) - { - if (inWord) - { - auto word = line[wordStart .. wordEnd]; - ++dictionary[word.idup]; // increment count for word - inWord = false; - } - } - - foreach (i, char c; line) - { - if (std.ascii.isDigit(c)) - { // c is a digit (0..9) - } - else if (std.ascii.isAlpha(c)) - { // c is an ASCII letter (A..Z, a..z) - if (!inWord) - { - wordStart = i; - inWord = true; - ++wordCount; - } - } - else - tryFinishWord(i); - ++charCount; - } - tryFinishWord(line.length); - ++lineCount; - } -) - writefln("%8s%8s%8s %s", lineCount, wordCount, charCount, arg); - totalWords += wordCount; - totalLines += lineCount; - totalChars += charCount; - } - - if (args.length > 2) - { - writefln("-------------------------------------\n%8s%8s%8s total", - totalLines, totalWords, totalChars); - } - - write$(V1 f)ln("-------------------------------------"); - foreach (word; dictionary.keys.sort) - { - writefln("%3s %s", dictionary[word], word); - } -} ---------- - -) - -Macros: - TITLE=Associative Arrays - WIKI=AssociativeArrays - DOLLAR=$ - STD_UNI=std.uni - FOO= - CATEGORY_SPEC=$0 diff --git a/howto-promote.dd b/howto-promote.dd index 175f7217ee..f3f2755ee6 100644 --- a/howto-promote.dd +++ b/howto-promote.dd @@ -1,96 +1,92 @@ Ddoc -$(D_S Promoting D Projects (or Internet Marketing 101), - - $(P So you've written a cool project in D, and it's ready for others - to use or to get involved with helping develop it further. - Just posting a zip file isn't going to work. All your blood, sweat - and effort will just go to waste. - You'll need to provide a way for people who want to know about - your project to be able to find it. - ) - - $(P The steps are: - ) - - $(OL - $(LI Create a web page for the project) - $(LI Let people know about it) - ) - -

    Creating a Web Page

    - - $(P A good web page should include the following: - ) - - $(UL - $(LI The keywords and phrases that someone who would be interested - in your project might type into Google to find it.) - - $(LI The phrase $(B D programming language) somewhere on the page. - This helps build the brand on the internet. - If you just use $(B D), nobody will find it via search.) - - $(LI Screen shots of the program. Even better, for graphics - and game demos, make a short video of it with - $(LINK2 http://windows.microsoft.com/en-US/windows/help/windows-xp?tab=xpmm, Windows Movie Maker), - which can capture movies directly from the screen.) - - $(LI List the capabilities of the package and what it's good for.) - - $(LI Identify who this package is intended for and why they'd - want to use it.) - - $(LI Copyright and license information for any source code. - If you intend for it to be - $(LINK2 http://en.wikipedia.org/wiki/Public_domain, public domain), - make sure to - explicitly mark it so.) - - ) - -

    Promoting the Project

    - - $(P Submit the page or article to the following: - ) - - $(UL - $(LI $(LINK2 http://www.digitalmars.com/pnews/indexing.php?server=news.digitalmars.com&group=digitalmars.D.announce, digitalmars.D.announce) newsgroup) - $(LI $(LINK2 http://www.google.com/addurl/?continue=/addurl, Google web crawler)) - $(LI $(LINK2 http://groups.google.com/group/google-code-search/post?subject=Please+add+the+following+repositories+to+Code+Search&body=Enter+your+code+repository+type+(SVN%2C+CVS%2C+Hg%2C+Git%2C+Archive)+and+URL+here%3A, Google code search) for source code zips) - $(LI $(LINK2 http://www.dzone.com/, dzone) developer news) - $(LI $(LINK2 http://www.betamarker.com/, beta marker) for releases, including betas) - $(LI $(LINK2 http://www.digg.com/, Digg) under the Developer category) - $(LI $(LINK2 http://slashdot.org/, Slashdot) news for nerds) - $(LI $(LINK2 http://www.gamedev.net/, gamedev.net) anything game related) - $(LI $(LINK2 http://www.artima.com/, Artima Developer) developer articles) - $(LI $(LINK2 http://www.download.com/, download.com) software downloads) - $(LI $(LINK2 http://www.wikipedia.org/, Wikipedia) if it genuinely adds to an article on the subject) - $(LI $(B comp.programming) newsgroup) - ) - - $(P Send me a cut-and-paste html snippet to place on - $(LINK2 http://www.digitalmars.com/d/dlinks.html, dlinks). - ) - - $(P If your project is a conversion of an existing project to D, - email the project leader of that existing project and suggest - that he incorporate a link to your project on his page. - ) - - $(P For the absolutely most effective results, submit - articles to: - ) - - $(UL - $(LI $(LINK2 http://www.ddj.com, Dr. Dobb's Journal)) - $(LI $(LINK2 http://www.sdexpo.com/, SDWest)) - $(LI $(LINK2 http://www.oopsla.org/, OOPSLA)) - ) +$(D_S $(TITLE), + + $(P So you've written a cool project in D, and it's ready for others + to use or to get involved with helping develop it further. + Just posting a Github link isn't going to work. All your blood, sweat + and effort will just go to waste. + You'll need to provide a way for people who want to know about + your project to be able to find it. + ) + + $(P The steps are: + ) + + $(OL + $(LI Create a good starting point for the project) + $(LI Let people know about it) + ) + +$(H3 Creating a good starting point) + + $(P For many using a Github README is enough, but rolling + out your own website creates a more professional look. + (Don't forget that with $(LINK2 https://pages.github.com, Github Pages) + hosting is free.) + ) + + $(UL + $(LI The keywords and phrases that someone who would be interested + in your project might type into Google to find it.) + + $(LI The phrase $(B D programming language) and $(B dlang) somewhere on the page. + This helps build the brand on the internet. + If you just use $(B D), nobody will find it via search.) + + $(LI Screen shots of the program. Even better, for graphics + and game demos, make a short video of it.) + + $(LI List the capabilities of the package and what it's good for.) + + $(LI Identify who this package is intended for and why they'd + want to use it.) + + $(LI Copyright and license information for any source code. + If you intend for it to be + $(LINK2 https://en.wikipedia.org/wiki/Public_domain, public domain), + make sure to + explicitly mark it so.) + + ) + +$(H3 Promoting the Project) + + $(P Submit the page or article to the following: + ) + + $(UL + $(LI $(HTTPS forum.dlang.org/group/announce, newsgroup)) + $(LI $(HTTPS wiki.dlang.org, D wiki)) + $(LI $(HTTPS github.com/zhaopuming/awesome-d, awesome-d) - A curated list of awesome D documents, frameworks, libraries and software) + $(LI $(HTTPS reddit.com/r/programming, Reddit Programming) - User-contributed news platform) + $(LI $(HTTPS twitter.com, Twitter) using the `#dlang` hashtag.) + $(LI $(HTTPS news.ycombinator.com, Hacker News) - Reddit for nerds) + $(LI $(HTTPS slashdot.org, Slashdot) - news for nerds) + $(LI $(HTTPS dzone.com, dzone) - Developer news) + $(LI $(HTTP gamedev.net, gamedev.net) - anything game related) + $(LI $(HTTPS wikipedia.org, Wikipedia) if it genuinely adds to an article on the subject) + ) + + $(P If your project is a conversion of an existing project to D, + email the project leader of that existing project and suggest + that he incorporate a link to your project on his page. + ) + + $(P For the absolutely most effective results, submit + articles to: + ) + + $(UL + $(LI $(LINK2 http://www.sdexpo.com/, SDWest)) + $(LI $(LINK2 http://www.oopsla.org/, OOPSLA)) + ) + + $(P Have a look whether there are conferences in your field at which + you could present your project. + ) ) Macros: - TITLE=Promoting D Projects (or Internet Marketing 101) - WIKI=PromotingDProjects - + TITLE=Promoting D Projects (or Internet Marketing 101) diff --git a/howtos.html b/howtos.html deleted file mode 100644 index 1aa2ace881..0000000000 --- a/howtos.html +++ /dev/null @@ -1,9 +0,0 @@ - - - -D Runtime Library - - - - - diff --git a/html.dd b/html.dd deleted file mode 100644 index d94a14e9ea..0000000000 --- a/html.dd +++ /dev/null @@ -1,58 +0,0 @@ -Ddoc - -$(SPEC_S Embedding D in HTML, - - The D compiler is designed to be able to extract and compile D code - embedded within HTML files. This capability means that D code can - be written to be displayed within a browser utilizing the full formatting - and display capability of HTML. -

    - For example, it is possible to make all uses of a class name actually be - hyperlinks to where the class is defined. There's nothing new to learn for - the person browsing the code, he just uses the normal features of an - HTML browser. Strings can be displayed in green, - comments in red, and - keywords in $(B boldface), for one possibility. It is even possible - to embed pictures in the code, as normal HTML image tags. -

    - Embedding D in HTML makes it possible to put the documentation for code and - the code itself all together in one file. It is no longer necessary to - relegate documentation in comments, to be extracted later by a tech writer. - The code and the documentation for it can be maintained simultaneously, - with no duplication of effort. -

    - How it works is straightforward. If the source file to the compiler ends - in .htm or .html, the code is assumed to be embedded in HTML. The source - is then preprocessed by stripping all text outside of <code> and - </code> tags. Then, all other HTML tags are stripped, and embedded - character encodings are converted to ASCII. - The processing does not attempt to diagnose errors in the HTML itself. - All newlines in the original - HTML remain in their corresponding positions in the preprocessed text, - so the debug line numbers remain consistent. The resulting text is then - fed to the D compiler. -

    - Here's an example of the D program "hello world" embedded in - this very HTML file. This file can be compiled and run. - -

    -
    -import std.stdio;
    -
    -int $(B main)()
    -{
    - $(RED writefln)("hello world");
    - return 0;
    -}
    -
    -
    - -) - -Macros: - TITLE=Embedding D in HTML - WIKI=HTML - CATEGORY_SPEC=$0 -META_KEYWORDS=D Programming Language, html -META_DESCRIPTION=Extracting D code from HTML files. - diff --git a/html.ddoc b/html.ddoc new file mode 100644 index 0000000000..2fd73d19ae --- /dev/null +++ b/html.ddoc @@ -0,0 +1,440 @@ +_=General macros for HTML generation. Even predefined macros are present +here for completeness. Macros defer wherever possible to style classes. + +_=Simple tags, ordered alphabetically + +A = $+ +ADEF = +AHTTP = $+ +AHTTPS = $+ +ALOCAL = $+ +BIG = $(EMC big, $0) +BR =
    +CAPTION = $(T caption, $0) +CHECKMARK = ✔ +DD = $(T dd, $0) +DIV =
    $+
    +DIVC = $(TC div, $1, $+) +DIVCID = $(DIV class="$1" id="$2", $3) +DIVID = $(DIV id="$1", $+) +DL = $(T dl, $0) +DOLLAR=$ +DOUBLEQUOTE = $(LDQUO)$0$(RDQUO) +DT = $(T dt, $0) +EMC = $(TC em, $1, $+) +ENUMERATE = $(OL $(ITEMS_HELPER $1, $+)) +GREATER = > +ITEMIZE = $(UL $(ITEMS_HELPER $1, $+)) +ITEMS_HELPER = $(LI $1)$(ITEMS_HELPER $+) +H1 = $(T h1, $0) +H2 = $(T h2, $0) +H3 = $(T h3, $0) +H4 = $(T h4, $0) +H5 = $(T h5, $0) +HR =
    +I = $(T i, $0) +LI = $(T li, $0) +LESS = < +OL = $(T ol, $0) +P = $(T p, $0) +PRE = $(T pre, $0) +SCRIPT = +SINGLEQUOTE = $(LSQUO)$0$(RSQUO) +SMALL = $(T small, $0) +SPAN = $+ +SPANC = $(TC span, $1, $+) +SPANID = $(SPAN id="$1", $+) +SUBSCRIPT = $(T sub, $0) +SUPERSCRIPT = $(T sup, $0) +TABLE = $(T table, $0) +TABLEC = $(TC table, $1, $+) +T=<$1>$+ +TC=<$1 class="$2">$(TAIL $+) +TD = $(T td, $0) +TD_HELPER = $(TD $1)$(TD_HELPER $+) +TH_HELPER = $(TH $1)$(TH_HELPER $+) +THEAD = $(TR $(TH_HELPER $1, $+)) +TR = $(T tr, $0) +TT = $(EMC tt, $0) +U = $(EMC u, $0) +UL = $(T ul, $0) +_= + +_=Defining anchors and linking + +LINK = $(A $0, $0) +LINK2 = $(A $1, $+) +HTTP = $(LINK2 http://$1,$2) +HTTPS = $(LINK2 https://$1,$2) +WEB = $(HTTP $1,$2) +_= + +_=Colors + +RED = $(SPAN style="color:red", $0) +GREEN = $(SPAN style="color:green", $0) +BLUE = $(SPAN style="color:blue", $0) +YELLOW = $(SPAN style="color:yellow", $0) +BLACK = $(SPAN style="color:black", $0) +WHITE = $(SPAN style="color:white", $0) +_= + +_=Explanatory stuff of the kind "Throws: blah" or "Returns: +blah". Note that if you want to make a SPAN-like (brief) explanation, +you can do it with the DIV block using "display: inline-block;", see +e.g. https://stackoverflow.com/questions/1611065/span-vs-div-inline-block + +DDOC_EXPLANATORY=$(DIVC explanatory, $(SPANC explanation_item, $1:) $(DIVC $1, $+)) +_= + +_=Predefined D-related stuff + +D_CODE = $(TC pre, d_code, $0) +OTHER_CODE = $(TC pre, code $1, $+) +D_COMMENT = $(SPANC d_comment, $0) +D_STRING = $(SPANC d_string, $0) +D_KEYWORD = $(SPANC d_keyword, $0) +D_PSYMBOL = $(SPANC d_psymbol, $0) +D_PARAM = $(SPANC d_param, $0) +D_TITLE = $(SPANC d_title, $0) +_= + +_=Main entry point + +DDOC = $(T html, +$(T head, + + + $(T title, $(TITLE)) +) +$(T body, $(H1 $(TITLE))$(BODY)))$(LF) +_= + +_=DDoc-related stuff + +DDOC_COMMENT = +DDOC_MEMBER = $0 +DDOC_MEMBER_HEADER = +DDOC_HEADER_ANCHOR = +DDOC_DECL = $(DT $(BIG $0)) +DDOC_DECL_DD = $(DD $0) +DDOC_DITTO = $(BR)$0 +DDOC_SECTIONS = $0$(LF) +DDOC_SUMMARY = $0$(BR)$(BR)$(LF) +DDOC_DESCRIPTION = $0$(BR)$(BR)$(LF) +DDOC_AUTHORS = $(B Authors:)$(BR) + $0$(BR)$(BR) +DDOC_BUGS = $(RED BUGS:)$(BR) + $0$(BR)$(BR)$(LF) +DDOC_COPYRIGHT = $(B Copyright:)$(BR) + $0$(BR)$(BR)$(LF) +DDOC_DATE = $(B Date:)$(BR) + $0$(BR)$(BR) +DDOC_DEPRECATED = $(RED Deprecated:)$(BR) + $0$(BR)$(BR) +DDOC_EXAMPLES = $(B Examples:)$(BR) + $0$(BR)$(BR) +DDOC_HISTORY = $(B History:)$(BR) + $0$(BR)$(BR) +DDOC_LICENSE = $(B License:)$(BR) + $0$(BR)$(BR) +DDOC_RETURNS = $(B Returns:)$(BR) + $0$(BR)$(BR) +DDOC_SEE_ALSO = $(B See Also:)$(BR) + $0$(BR)$(BR) +DDOC_STANDARDS = $(B Standards:)$(BR) + $0$(BR)$(BR) +DDOC_THROWS = $(B Throws:)$(BR) + $0$(BR)$(BR) +DDOC_VERSION = $(B Version:)$(BR) + $0$(BR)$(BR)$(LF) +DDOC_SECTION_H = $(B $0)$(BR)$(BR)$(LF) +DDOC_SECTION = $0$(BR)$(BR)$(LF) +DDOC_MEMBERS = $(DL $0) +DDOC_MODULE_MEMBERS = $(DDOC_MEMBERS $0)$(LF) +DDOC_CLASS_MEMBERS = $(DDOC_MEMBERS $0)$(LF) +DDOC_STRUCT_MEMBERS = $(DDOC_MEMBERS $0)$(LF) +DDOC_ENUM_MEMBERS = $(DDOC_MEMBERS $0)$(LF) +DDOC_TEMPLATE_MEMBERS = $(DDOC_MEMBERS $0)$(LF) +DDOC_PARAMS = $(B Params:)$(BR)$(LF) +$(TABLE $0)$(BR) +DDOC_PARAM_ROW = $(TR $0)$(LF) +DDOC_PARAM_ID = $(TD $0)$(LF) +DDOC_PARAM_DESC = $(TD $0) +_= + +DDOC_ANCHOR = $(ADEF $1) +DDOC_PSYMBOL = $(U $0) +DDOC_KEYWORD = $(B $0) +DDOC_PARAM = $(I $0) +DDOC_OVERLOAD_SEPARATOR = $(BR) +DDOC_CONSTRAINT=$(BR)$(SPAN class="constraint", if ($0)) +DDOC_TEMPLATE_PARAM_LIST=$(SPAN class="template_param_list" title="Template parameter list", $0) +_= + +_=Generic blurb to describe C header bindings + +C_HEADER_DESCRIPTION = This module contains bindings to selected types and +functions from the standard C header $(HTTP $1, $(D $(LESS)$2$(GREATER))). Note that this +is not automatically generated, and may omit some types/functions from the +original C header. +_= + +_=HTML named entities, ordered approximately as in https://dlang.org/entity.html + +QUOT = " +AMP = & +PERCENT = % +TAB = +_= + +OELIG_CAP = Œ +OELIG = œ +SCARON_CAP = Š +SCARON = š +YUML = Ÿ +CIRC = ˆ +TILDE = ˜ +ENSP =   +EMSP =   +THINSP =   +ZWNJ = ‌ +ZWJ = ‍ +LRM = ‎ +RLM = ‏ +NDASH = – +MDASH = — +LSQUO = ‘ +RSQUO = ’ +SBQUO = ‚ +LDQUO = “ +RDQUO = ” +BDQUO = „ +DAGGER = † +DAGGER_CAP = ‡ +PERMIL = ‰ +LSAQUO = ‹ +RSAQUO = › +EURO = € +NBSP =   +IEXCL = ¡ +CENT = ¢ +POUND = £ +CURREN = ¤ +YEN = ¥ +BRVBAR = ¦ +SECT = § +UML = ¨ +COPY = © +REG = ® +ORDF = ª +LAQUO = « +NOT = ¬ +SHY = ­ +REG = ® +MACR = ¯ +DEG = ° +PLUSMN = ± +SUP2 = ² +SUP3 = ³ +ACUTE = ´ +MICRO = µ +PARA = ¶ +MIDDOT = · +CEDIL = ¸ +SUP1 = ¹ +ORDM = º +RAQUO = » +FRAC14 = ¼ +FRAC12 = ½ +FRAC34 = ¾ +IQUEST = ¿ +AGRAVE_CAP = À +AACUTE_CAP = Á +ACIRC_CAP =  +ATILDE_CAP = à +AUML_CAP = Ä +ARING_CAP = Å +AELIG_CAP = Æ +CCEDIL_CAP = Ç +EGRAVE_CAP = È +EACUTE_CAP = É +ECIRC_CAP = Ê +EUML_CAP = Ë +IGRAVE_CAP = Ì +IACUTE_CAP = Í +ICIRC_CAP = Î +IUML_CAP = Ï +ETH_CAP = Ð +NTILDE_CAP = Ñ +OGRAVE_CAP = Ò +OACUTE_CAP = Ó +OCIRC_CAP = Ô +OTILDE_CAP = Õ +OUML_CAP = Ö +TIMES = × +OSLASH_CAP = Ø +UGRAVE_CAP = Ù +UACUTE_CAP = Ú +UCIRC_CAP = Û +UUML_CAP = Ü +YACUTE_CAP = Ý +THORN_CAP = Þ +SZLIG = ß +AGRAVE = à +AACUTE = á +ACIRC = â +ATILDE = ã +AUML = ä +ARING = å +AELIG = æ +CCEDIL = ç +EGRAVE = è +EACUTE = é +ECIRC = ê +EUML = ë +IGRAVE = ì +IACUTE = í +ICIRC = î +IUML = ï +ETH = ð +NTILDE = ñ +OGRAVE = ò +OACUTE = ó +OCIRC = ô +OTILDE = õ +OUML = ö +DIVIDE = ÷ +OSLASH = ø +UGRAVE = ù +UACUTE = ú +UCIRC = û +UUML = ü +YACUTE = ý +THORN = þ +YUML = ÿ +FNOF = ƒ +ALPHA_CAP = Α +BETA_CAP = Β +GAMMA_CAP = Γ +DELTA_CAP = Δ +EPSILON_CAP = Ε +ZETA_CAP = Ζ +ETA_CAP = Η +THETA_CAP = Θ +IOTA_CAP = Ι +KAPPA_CAP = Κ +LAMBDA_CAP = Λ +MU_CAP = Μ +NU_CAP = Ν +XI_CAP = Ξ +OMICRON_CAP = Ο +PI_CAP = Π +RHO_CAP = Ρ +SIGMA_CAP = Σ +TAU_CAP = Τ +UPSILON_CAP = Υ +PHI_CAP = Φ +CHI_CAP = Χ +PSI_CAP = Ψ +OMEGA_CAP = Ω +ALPHA = α +BETA = β +GAMMA = γ +DELTA = δ +EPSILON = ε +ZETA = ζ +ETA = η +THETA = θ +IOTA = ι +KAPPA = κ +LAMBDA = λ +MU = μ +NU = ν +XI = ξ +OMICRON = ο +PI = π +RHO = ρ +SIGMAF = ς +SIGMA = σ +TAU = τ +UPSILON = υ +PHI = φ +CHI = χ +PSI = ψ +OMEGA = ω +THETASYM = ϑ +UPSIH = ϒ +PIV = ϖ +BULL = • +HELLIP = … +PRIME = ′ +PRIME_CAP = ″ +OLINE = ‾ +FRASL = ⁄ +WEIERP = ℘ +IMAGE = ℑ +REAL = ℜ +TRADE = ™ +ALEFSYM = ℵ +LARR = ← +UARR = ↑ +RARR = → +DARR = ↓ +HARR = ↔ +CRARR = ↵ +LARR_CAP = ⇐ +UARR_CAP = ⇑ +RARR_CAP = ⇒ +DARR_CAP = ⇓ +HARR_CAP = ⇔ +FORALL = ∀ +PART = ∂ +EXIST = ∃ +EMPTY = ∅ +NABLA = ∇ +ISIN = ∈ +NOTIN = ∉ +NI = ∋ +PROD = ∏ +SUM = ∑ +MINUS = − +LOWAST = ∗ +RADIC = √ +PROP = ∝ +INFIN = ∞ +ANG = ∠ +AND = ∧ +OR = ∨ +CAP = ∩ +CUP = ∪ +INT = ∫ +THERE4 = ∴ +SIM = ∼ +CONG = ≅ +ASYMP = ≈ +NE = ≠ +EQUIV = ≡ +LE = ≤ +GE = ≥ +SUB = ⊂ +SUP = ⊃ +NSUB = ⊄ +SUBE = ⊆ +SUPE = ⊇ +OPLUS = ⊕ +OTIMES = ⊗ +PERP = ⊥ +SDOT = ⋅ +LCEIL = ⌈ +RCEIL = ⌉ +LFLOOR = ⌊ +RFLOOR = ⌋ +LOZ = ◊ +SPADES = ♠ +CLUBS = ♣ +HEARTS = ♥ +DIAMS = ♦ +LANG = ⟨ +RANG = ⟩ +_= diff --git a/htod.dd b/htod.dd index 7ddc8954bd..4c53bb6c0e 100644 --- a/htod.dd +++ b/htod.dd @@ -2,29 +2,34 @@ Ddoc $(D_S htod, -$(P While D is binary compatible with C code, it cannot - compile C code nor C header files. In order for - D to link with C code, the C declarations residing - in C header files need to be converted to a D - module. $(B htod) is a migration tool to aid in - convering C header files. +$(MESSAGE_BOX orange, $(B Warning) - `htod` is not developed actively. + Please see $(LINK2 https://wiki.dlang.org/Bindings#Binding_generators, + Binding generators on the D Wiki) for a list of alternatives.) + + +$(P While D is binary compatible with C code, it cannot + compile C code nor C header files. In order for + D to link with C code, the C declarations residing + in C header files need to be converted to a D + module. $(B htod) is a migration tool to aid in + converting C header files. ) -$(P $(B htod) is built from the front end of the Digital - Mars C and C++ compiler. It works just like a C or - C++ compiler except that its output is a D module - rather than object code. +$(P $(B htod) is built from the front end of the Digital + Mars C and C++ compiler. It works just like a C or + C++ compiler except that its output is a D module + rather than object code. ) -$(P The macro $(B __HTOD__) is predefined and set to $(B 1), - which is handy for improving C header files to give better - D output. +$(P The macro $(B __HTOD__) is predefined and set to $(B 1), + which is handy for improving C header files to give better + D output. ) -

    Download

    +$(H3 Download) -$(P $(LINK2 http://ftp.digitalmars.com/htod.zip, htod) +$(P $(LINK2 http://ftp.digitalmars.com/htod.zip, htod) ) -

    Usage

    +$(H3 Usage) $(GRAMMAR $(B htod) $(I cheader.h) [$(I dimport.d)] [$(B -cpp)] [$(B -hc)] [$(B -hi)] [$(B -hs)] [$(B -ht)] { $(I C compiler switches) } @@ -94,7 +99,7 @@ for $(LINK2 http://www.digitalmars.com/ctg/sc.html, dmc). ) -

    Example

    +$(H3 Example) $(P The C test.h file:) @@ -120,115 +125,114 @@ extern (C): uint u; //C #define MYINT int //C void bar(int x, long y, long long z); -alias int MYINT; +alias MYINT = int; void bar(int x, int y, long z); --- $(P The C declarations are prefixed by the string $(D "//C ").) -

    Type Mappings

    - -$(P C types are mapped as follows. These mappings are correct - for Digital Mars C/C++, but may not be correct for your - C compiler. D basic types have fixed sizes, while C basic - type sizes are implementation defined. -) - - $(TABLE1 - Mapping C to D types - $(TR $(TH C type) $(TH D type)) - $(TR $(TD void) $(TD void)) - $(TR $(TD _Bool) $(TD bool)) - $(TR $(TD wchar_t) $(TD wchar)) - $(TR $(TD char) $(TD char)) - $(TR $(TD signed char) $(TD byte)) - $(TR $(TD unsigned char) $(TD ubyte)) - $(TR $(TD short) $(TD short)) - $(TR $(TD unsigned short) $(TD ushort)) - $(TR $(TD int) $(TD int)) - $(TR $(TD unsigned) $(TD uint)) - $(TR $(TD long) $(TD int)) - $(TR $(TD unsigned long) $(TD uint)) - $(TR $(TD long long) $(TD long)) - $(TR $(TD unsigned long long) $(TD ulong)) - $(TR $(TD float) $(TD float)) - $(TR $(TD double) $(TD double)) - $(TR $(TD long double) $(TD real)) - $(TR $(TD _Imaginary float) $(TD ifloat)) - $(TR $(TD _Imaginary double) $(TD idouble)) - $(TR $(TD _Imaginary long double) $(TD ireal)) - $(TR $(TD _Complex float) $(TD cfloat)) - $(TR $(TD _Complex double) $(TD cdouble)) - $(TR $(TD _Complex long double) $(TD creal)) - ) - -

    Limitations

    - -$(P There is no one to one correspondence of C declarations - to D declarations. A review of the D module output will - be necessary to ensure the right decisions are made. - Furthermore: +$(H3 Type Mappings) + +$(P C types are mapped as follows. These mappings are correct + for Digital Mars C/C++, but may not be correct for your + C compiler. D basic types have fixed sizes, while C basic + type sizes are implementation defined. +) + + $(TABLE + Mapping C to D types + $(TR $(TH C type) $(TH D type)) + $(TR $(TD void) $(TD void)) + $(TR $(TD _Bool) $(TD bool)) + $(TR $(TD wchar_t) $(TD wchar)) + $(TR $(TD char) $(TD char)) + $(TR $(TD signed char) $(TD byte)) + $(TR $(TD unsigned char) $(TD ubyte)) + $(TR $(TD short) $(TD short)) + $(TR $(TD unsigned short) $(TD ushort)) + $(TR $(TD int) $(TD int)) + $(TR $(TD unsigned) $(TD uint)) + $(TR $(TD long) $(TD int)) + $(TR $(TD unsigned long) $(TD uint)) + $(TR $(TD long long) $(TD long)) + $(TR $(TD unsigned long long) $(TD ulong)) + $(TR $(TD float) $(TD float)) + $(TR $(TD double) $(TD double)) + $(TR $(TD long double) $(TD real)) + $(TR $(TD _Imaginary float) $(TD ifloat)) + $(TR $(TD _Imaginary double) $(TD idouble)) + $(TR $(TD _Imaginary long double) $(TD ireal)) + $(TR $(TD _Complex float) $(TD cfloat)) + $(TR $(TD _Complex double) $(TD cdouble)) + $(TR $(TD _Complex long double) $(TD creal)) + ) + +$(H3 Limitations) + +$(P There is no one to one correspondence of C declarations + to D declarations. A review of the D module output will + be necessary to ensure the right decisions are made. + Furthermore: ) $(OL - $(LI Whereever - practical, C headers should be written using $(B typedef)'s and - $(B enum)'s rather than macros. - $(B htod) will attempt to convert simple macro $(B #define)'s - to $(B alias) and $(B const) declarations. - Even so, macros are fully expanded before further analysis.) + $(LI Wherever + practical, C headers should be written using $(B typedef)s and + $(B enum)s rather than macros. + $(B htod) will attempt to convert simple macro $(B #define)s + to $(B alias) and $(B const) declarations. + Even so, macros are fully expanded before further analysis.) - $(LI No attempt is made to convert C conditional compilation - into D $(B version) or $(B static if) declarations.) + $(LI No attempt is made to convert C conditional compilation + into D $(B version) or $(B static if) declarations.) - $(LI No output is generated for false conditional compilation - sections.) + $(LI No output is generated for false conditional compilation + sections.) - $(LI $(B htod) converts declarations only, it does not convert - C code.) + $(LI $(B htod) converts declarations only, it does not convert + C code.) - $(LI Declarations with C++ linkage cannot be converted. - A C interface must be made for any C++ code.) + $(LI Declarations with C++ linkage cannot be converted. + A C interface must be made for any C++ code.) - $(LI C language extensions present in the C .h file - may not be recognized.) + $(LI C language extensions present in the C .h file + may not be recognized.) - $(LI Pragmas are not translated.) + $(LI Pragmas are not translated.) - $(LI The tag names are assumed to not collide with - names in the regular name space.) + $(LI The tag names are assumed to not collide with + names in the regular name space.) - $(LI Any character data that is not ASCII will need - to be converted as necessary to UTF.) + $(LI Any character data that is not ASCII will need + to be converted as necessary to UTF.) - $(LI The C $(B char) type is assumed to map to the - D $(B char) type. However, these should be examined individually - to see if they should instead be translated to $(B byte) or - $(B ubyte) types. Whether the C $(B char) type is signed or - unsigned is implementation defined. The D $(B char) type - is unsigned.) + $(LI The C $(B char) type is assumed to map to the + D $(B char) type. However, these should be examined individually + to see if they should instead be translated to $(B byte) or + $(B ubyte) types. Whether the C $(B char) type is signed or + unsigned is implementation defined. The D $(B char) type + is unsigned.) - $(LI Named C enum members are not inserted into the surrounding - scope as they are in C.) + $(LI Named C enum members are not inserted into the surrounding + scope as they are in C.) - $(LI D modules are each in their own name space, but C - header files are all in the same global name space. This means - that D references to names defined in other modules may - need to be qualified.) + $(LI D modules are each in their own name space, but C + header files are all in the same global name space. This means + that D references to names defined in other modules may + need to be qualified.) ) -

    Bugs

    +$(H3 Bugs) $(OL - $(LI Anything other than the default struct member - alignment is not accounted for.) + $(LI Anything other than the default struct member + alignment is not accounted for.) - $(LI No Linux version.) + $(LI No Linux version.) ) ) Macros: - TITLE=htod - WIKI=htod - CATEGORY_DOWNLOAD=$0 + TITLE=htod + SUBNAV=$(SUBNAV_CLI_REFERENCE) diff --git a/htomodule.dd b/htomodule.dd deleted file mode 100644 index 242e87def9..0000000000 --- a/htomodule.dd +++ /dev/null @@ -1,452 +0,0 @@ -Ddoc - -$(D_S Converting C $(D .h) Files to D Modules, - - While D cannot directly compile C source code, it can easily - interface to C code, be linked with C object files, and call - C functions in DLLs. - The interface to C code is normally found in C $(D .h) files. - So, the trick to connecting with C code is in converting C - $(D .h) files to D modules. - This turns out to be difficult to do mechanically since - inevitably some human judgement must be applied. - This is a guide to doing such conversions. - -

    Preprocessor

    - - $(D .h) files can sometimes be a bewildering morass of layers of - macros, $(D #include) files, $(D #ifdef)'s, etc. D doesn't - include a text preprocessor like the C preprocessor, - so the first step is to remove the need for - it by taking the preprocessed output. For DMC (the Digital - Mars C/C++ compiler), the command: - -$(CONSOLE -dmc -c program.h -e -l -) - - will create a file $(D program.lst) which is the source file after - all text preprocessing. -

    - - Remove all the $(D #if), $(D #ifdef), $(D #include), - etc. statements. - -

    Linkage

    - - Generally, surround the entire module with: - ---------------------------- -extern (C) -{ - /* ...file contents... */ -} ---------------------------- - - to give it C linkage. - -

    Types

    - - A little global search and replace will take care of renaming - the C types to D types. The following table shows a typical mapping - for 32 bit C code: -

    - - $(TABLE1 - Mapping C type to D type - - C type - D type - - long double - real - - unsigned long long - ulong - - long long - long - - unsigned long - uint - - long - int - - unsigned - uint - - unsigned short - ushort - - signed char - byte - - unsigned char - ubyte - - wchar_t - wchar or dchar - - bool - bool, byte, int - - size_t - size_t - - ptrdiff_t - ptrdiff_t - ) - -

    NULL

    - - $(D NULL) and $(D ((void*)0)) should be replaced - with $(D null). - -

    Numeric Literals

    - - Any $(SINGLEQUOTE L) or $(SINGLEQUOTE l) numeric literal suffixes should be removed, - as a C $(D long) is (usually) the same size as a D $(D int). - Similarly, $(SINGLEQUOTE LL) suffixes should be replaced with a - single $(SINGLEQUOTE L). - Any $(SINGLEQUOTE u) suffix will work the same in D. - -

    String Literals

    - - In most cases, any $(SINGLEQUOTE L) prefix to a string can just be dropped, - as D will implicitly convert strings to wide characters if - necessary. However, one can also replace: - -$(CCODE -L"string" -) - - with: - ---------------------------- -"string"w // for 16 bit wide characters -"string"d // for 32 bit wide characters ---------------------------- - -

    Macros

    - - Lists of macros like: - -$(CCODE -#define FOO 1 -#define BAR 2 -#define ABC 3 -#define DEF 40 -) - - can be replaced with: - ---------------------------- -enum -{ FOO = 1, - BAR = 2, - ABC = 3, - DEF = 40 -} ---------------------------- - - or with: - ---------------------------- -const int FOO = 1; -const int BAR = 2; -const int ABC = 3; -const int DEF = 40; ---------------------------- - - Function style macros, such as: - -$(CCODE -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -) - - can be replaced with functions: - ---------------------------- -int MAX(int a, int b) { return (a < b) ? b : a; } ---------------------------- - - - - The functions, however, won't work if they appear inside static - initializers that must be evaluated at compile time rather than - runtime. To do it at compile time, a template can be used: - -$(CCODE -#define GT_DEPTH_SHIFT (0) -#define GT_SIZE_SHIFT (8) -#define GT_SCHEME_SHIFT (24) -#define GT_DEPTH_MASK (0xffU << GT_DEPTH_SHIFT) -#define GT_TEXT ((0x01) << GT_SCHEME_SHIFT) - -/* Macro that constructs a graphtype */ -#define GT_CONSTRUCT(depth,scheme,size) \ - ((depth) | (scheme) | ((size) << GT_SIZE_SHIFT)) - -/* Common graphtypes */ -#define GT_TEXT16 GT_CONSTRUCT(4, GT_TEXT, 16) -) - - The corresponding D version would be: - ---------------------------- -const uint GT_DEPTH_SHIFT = 0; -const uint GT_SIZE_SHIFT = 8; -const uint GT_SCHEME_SHIFT = 24; -const uint GT_DEPTH_MASK = 0xffU << GT_DEPTH_SHIFT; -const uint GT_TEXT = 0x01 << GT_SCHEME_SHIFT; - -// Template that constructs a graphtype -template GT_CONSTRUCT(uint depth, uint scheme, uint size) -{ - // notice the name of the const is the same as that of the template - const uint GT_CONSTRUCT = (depth | scheme | (size << GT_SIZE_SHIFT)); -} - -// Common graphtypes -const uint GT_TEXT16 = GT_CONSTRUCT!(4, GT_TEXT, 16); ---------------------------- - - -

    Declaration Lists

    - - D doesn't allow declaration lists to change the type. - Hence: - -$(CCODE -int *p, q, t[3], *s; -) - - should be written as: - ---------------------------- -int* p, s; -int q; -int[3] t; ---------------------------- - -

    Void Parameter Lists

    - - Functions that take no parameters: - -$(CCODE -int foo(void); -) - - are in D: - ---------------------------- -int foo(); ---------------------------- - -$(V1 - -

    Const Type Modifiers

    - - D has $(D const) as a storage class, not a type modifier. Hence, just - drop any $(D const) used as a type modifier: - -$(CCODE -void foo(const int *p, char *const q); -) - - becomes: - ---------------------------- -void foo(int* p, char* q); ---------------------------- -) -

    Extern Global C Variables

    - - Whenever a global variable is declared in D, it is also defined. - But if it's also defined by the C object file being linked in, - there will be a multiple definition error. To fix this problem, - use the extern storage class. - For example, given a C header file named - $(D foo.h): - -$(CCODE -struct Foo { }; -struct Foo bar; -) - - It can be replaced with the D modules, $(D foo.d): - ---------------------------- -struct Foo { } -extern (C) -{ - extern Foo bar; -} ---------------------------- - - -

    Typedef

    - - $(D alias) is the D equivalent to the C $(D typedef): - -$(CCODE -typedef int foo; -) - - becomes: - ---------------------------- -alias int foo; ---------------------------- - -

    Structs

    - - Replace declarations like: - -$(CCODE -typedef struct Foo -{ int a; - int b; -} Foo, *pFoo, *lpFoo; -) - - with: - ---------------------------- -struct Foo -{ int a; - int b; -} -alias Foo* pFoo, lpFoo; ---------------------------- - -

    Struct Member Alignment

    - - A good D implementation by default will align struct members the - same way as the C compiler it was designed to work with. But - if the $(D .h) file has some $(D #pragma)'s to control alignment, they - can be duplicated with the D $(D align) attribute: - -$(CCODE -#pragma pack(1) -struct Foo -{ - int a; - int b; -}; -#pragma pack() -) - - becomes: - ---------------------------- -struct Foo -{ - align (1): - int a; - int b; -} ---------------------------- - -

    Nested Structs

    - -$(CCODE -struct Foo -{ - int a; - struct Bar - { - int c; - } bar; -}; - -struct Abc -{ - int a; - struct - { - int c; - } bar; -}; -) - - becomes: - ---------------------------- -struct Foo -{ - int a; - struct Bar - { - int c; - } - Bar bar; -} - -struct Abc -{ - int a; - struct - { - int c; - } -} ---------------------------- - -

    $(D __cdecl), $(D __pascal), $(D __stdcall)

    - -$(CCODE -int __cdecl x; -int __cdecl foo(int a); -int __pascal bar(int b); -int __stdcall abc(int c); -) - - becomes: - ---------------------------- -extern (C) int x; -extern (C) int foo(int a); -extern (Pascal) int bar(int b); -extern (Windows) int abc(int c); ---------------------------- - -

    $(D __declspec(dllimport))

    - -$(CCODE -__declspec(dllimport) int __stdcall foo(int a); -) - - becomes: - ---------------------------- -export extern (Windows) int foo(int a); ---------------------------- - -

    $(D __fastcall)

    - - Unfortunately, D doesn't support the $(D __fastcall) convention. - Therefore, a shim will be needed, either written in C: - -$(CCODE -int __fastcall foo(int a); - -int myfoo(int a) -{ - return foo(int a); -} -) - - and compiled with a C compiler that supports $(D __fastcall) and - linked in, or compile the above, disassemble it with - obj2asm - and insert it in a D $(D myfoo) shim with - inline assembler. - -) - -Macros: - TITLE=Converting C .h Files to D Modules - WIKI=HToModule - CATEGORY_HOWTOS=$0 diff --git a/iasm.dd b/iasm.dd deleted file mode 100644 index 3f0d51f4dc..0000000000 --- a/iasm.dd +++ /dev/null @@ -1,1196 +0,0 @@ -Ddoc - -$(SPEC_S Inline Assembler, - - - Some Assembly Required - - - $(P D, being a systems programming language, provides an inline - assembler. - The inline assembler is standardized for D implementations across - the same CPU family, for example, the Intel Pentium inline assembler - for a Win32 D compiler will be syntax compatible with the inline - assembler for Linux running on an Intel Pentium. - ) - - $(P Implementations of D on different architectures, however, are - free to innovate upon the memory model, function call/return conventions, - argument passing conventions, etc. - ) - - $(P This document describes the x86 implementation of the inline - assembler. - ) - -$(GRAMMAR -$(GNAME AsmInstruction): - $(I Identifier) $(B :) $(I AsmInstruction) - $(B align) $(GLINK IntegerExpression) - $(B even) - $(B naked) - $(B db) $(I Operands) - $(B ds) $(I Operands) - $(B di) $(I Operands) - $(B dl) $(I Operands) - $(B df) $(I Operands) - $(B dd) $(I Operands) - $(B de) $(I Operands) - $(I Opcode) - $(I Opcode Operands) - -$(GNAME Operands): - $(I Operand) - $(I Operand) $(B ,) $(I Operands) -) - -

    Labels

    - - $(P Assembler instructions can be labeled just like other statements. - They can be the target of goto statements. - For example: - ) - --------------- -void *pc; -asm -{ - call L1 ; - L1: ; - pop EBX ; - mov pc[EBP],EBX ; // pc now points to code at L1 -} --------------- - -

    align $(I IntegerExpression)

    - -$(GRAMMAR -$(GNAME IntegerExpression): - $(GLINK2 lex, IntegerLiteral) - $(I Identifier) -) - - $(P Causes the assembler to emit NOP instructions to align the next - assembler instruction on an $(I IntegerExpression) boundary. - $(I IntegerExpression) must evaluate at compile time to an integer that is - a power of 2. - ) - - $(P Aligning the start of a loop body can sometimes have a dramatic - effect on the execution speed. - ) - -

    even

    - - $(P Causes the assembler to emit NOP instructions to align the next - assembler instruction on an even boundary. - ) - -

    naked

    - - $(P Causes the compiler to not generate the function prolog and epilog - sequences. This means such is the responsibility of inline - assembly programmer, and is normally used when the entire function - is to be written in assembler. - ) - -

    db, ds, di, dl, df, dd, de

    - - These pseudo ops are for inserting raw data directly into - the code. - $(B db) is for bytes, - $(B ds) is for 16 bit words, - $(B di) is for 32 bit words, - $(B dl) is for 64 bit words, - $(B df) is for 32 bit floats, - $(B dd) is for 64 bit doubles, - and $(B de) is for 80 bit extended reals. - Each can have multiple operands. - If an operand is a string literal, it is as if there were $(I length) - operands, where $(I length) is the number of characters in the string. - One character is used per operand. - For example: - --------------- -asm -{ - db 5,6,0x83; // insert bytes 0x05, 0x06, and 0x83 into code - ds 0x1234; // insert bytes 0x34, 0x12 - di 0x1234; // insert bytes 0x34, 0x12, 0x00, 0x00 - dl 0x1234; // insert bytes 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - df 1.234; // insert float 1.234 - dd 1.234; // insert double 1.234 - de 1.234; // insert real 1.234 - db "abc"; // insert bytes 0x61, 0x62, and 0x63 - ds "abc"; // insert bytes 0x61, 0x00, 0x62, 0x00, 0x63, 0x00 -} --------------- - -

    Opcodes

    - - A list of supported opcodes is at the end. -

    - - The following registers are supported. Register names - are always in upper case. - -$(GRAMMAR -$(GNAME Register): - $(B AL) $(B AH) $(B AX) $(B EAX) - $(B BL) $(B BH) $(B BX) $(B EBX) - $(B CL) $(B CH) $(B CX) $(B ECX) - $(B DL) $(B DH) $(B DX) $(B EDX) - $(B BP) $(B EBP) - $(B SP) $(B ESP) - $(B DI) $(B EDI) - $(B SI) $(B ESI) - $(B ES) $(B CS) $(B SS) $(B DS) $(B GS) $(B FS) - $(B CR0) $(B CR2) $(B CR3) $(B CR4) - $(B DR0) $(B DR1) $(B DR2) $(B DR3) $(B DR6) $(B DR7) - $(B TR3) $(B TR4) $(B TR5) $(B TR6) $(B TR7) - $(B ST) - $(B ST(0)) $(B ST(1)) $(B ST(2)) $(B ST(3)) $(B ST(4)) $(B ST(5)) $(B ST(6)) $(B ST(7)) - $(B MM0) $(B MM1) $(B MM2) $(B MM3) $(B MM4) $(B MM5) $(B MM6) $(B MM7) - $(B XMM0) $(B XMM1) $(B XMM2) $(B XMM3) $(B XMM4) $(B XMM5) $(B XMM6) $(B XMM7) -) - -

    Special Cases

    - -$(DL - - $(DT $(B lock), $(B rep), $(B repe), $(B repne), - $(B repnz), $(B repz)) - $(DD These prefix instructions do not appear in the same statement - as the instructions they prefix; they appear in their own statement. - For example: - --------------- -asm { - rep ; - movsb ; -} --------------- - ) - - $(DT $(B pause)) - $(DD This opcode is not supported by the assembler, instead use - --------------- -asm { - rep ; - nop ; -} --------------- - - which produces the same result. - ) - - $(DT $(B floating point ops)) - $(DD Use the two operand form of the instruction format; - --------------- -fdiv ST(1); // wrong -fmul ST; // wrong -fdiv ST,ST(1); // right -fmul ST,ST(0); // right --------------- - ) -) - -

    Operands

    - -$(GRAMMAR -$(GNAME Operand): - $(I AsmExp) - -$(GNAME AsmExp): - $(I AsmLogOrExp) - $(I AsmLogOrExp) $(B ?) $(I AsmExp) $(B :) $(I AsmExp) - -$(GNAME AsmLogOrExp): - $(I AsmLogAndExp) - $(I AsmLogAndExp) $(B ||) $(I AsmLogAndExp) - -$(GNAME AsmLogAndExp): - $(I AsmOrExp) - $(I AsmOrExp) $(B &&) $(I AsmOrExp) - -$(GNAME AsmOrExp): - $(I AsmXorExp) - $(I AsmXorExp) $(B |) $(I AsmXorExp) - -$(GNAME AsmXorExp): - $(I AsmAndExp) - $(I AsmAndExp) $(B ^) $(I AsmAndExp) - -$(GNAME AsmAndExp): - $(I AsmEqualExp) - $(I AsmEqualExp) $(B &) $(I AsmEqualExp) - -$(GNAME AsmEqualExp): - $(I AsmRelExp) - $(I AsmRelExp) $(B ==) $(I AsmRelExp) - $(I AsmRelExp) $(B !=) $(I AsmRelExp) - -$(GNAME AsmRelExp): - $(I AsmShiftExp) - $(I AsmShiftExp) $(B <) $(I AsmShiftExp) - $(I AsmShiftExp) $(B <=) $(I AsmShiftExp) - $(I AsmShiftExp) $(B >) $(I AsmShiftExp) - $(I AsmShiftExp) $(B >=) $(I AsmShiftExp) - -$(GNAME AsmShiftExp): - $(I AsmAddExp) - $(I AsmAddExp) $(B <<) $(I AsmAddExp) - $(I AsmAddExp) $(B >>) $(I AsmAddExp) - $(I AsmAddExp) $(B >>>) $(I AsmAddExp) - -$(GNAME AsmAddExp): - $(I AsmMulExp) - $(I AsmMulExp) $(B +) $(I AsmMulExp) - $(I AsmMulExp) $(B -) $(I AsmMulExp) - -$(GNAME AsmMulExp): - $(I AsmBrExp) - $(I AsmBrExp) $(B *) $(I AsmBrExp) - $(I AsmBrExp) $(B /) $(I AsmBrExp) - $(I AsmBrExp) $(B %) $(I AsmBrExp) - -$(GNAME AsmBrExp): - $(I AsmUnaExp) - $(I AsmBrExp) $(B [) $(I AsmExp) $(B ]) - -$(GNAME AsmUnaExp): - $(I AsmTypePrefix) $(I AsmExp) - $(B offsetof) $(I AsmExp) - $(B seg) $(I AsmExp) - $(B +) $(I AsmUnaExp) - $(B -) $(I AsmUnaExp) - $(B !) $(I AsmUnaExp) - $(B ~) $(I AsmUnaExp) - $(I AsmPrimaryExp) - -$(GNAME AsmPrimaryExp): - $(GLINK2 lex, IntegerLiteral) - $(GLINK2 lex, FloatLiteral) - $(B __LOCAL_SIZE) - $(B $) - $(GLINK Register) - $(I DotIdentifier) - -$(GNAME DotIdentifier): - $(I Identifier) - $(I Identifier) $(B .) $(I DotIdentifier) -) - - $(P The operand syntax more or less follows the Intel CPU documentation - conventions. - In particular, the convention is that for two operand instructions - the source is the right operand and the destination is the left - operand. - The syntax differs from that of Intel's in order to be compatible - with the D language tokenizer and to simplify parsing. - ) - - $(P The $(B seg) means load the segment number that the symbol is - in. This is not relevant for flat model code. - Instead, do a move from the relevant segment register. - ) - -

    Operand Types

    - -$(GRAMMAR -$(GNAME AsmTypePrefix): - $(B near ptr) - $(B far ptr) - $(B byte ptr) - $(B short ptr) - $(B int ptr) - $(B word ptr) - $(B dword ptr) - $(B qword ptr) - $(B float ptr) - $(B double ptr) - $(B real ptr) -) - - $(P In cases where the operand size is ambiguous, as in:) - --------------- -add [EAX],3 ; --------------- - - $(P it can be disambiguated by using an $(I AsmTypePrefix):) - --------------- -add byte ptr [EAX],3 ; -add int ptr [EAX],7 ; --------------- - - $(P $(B far ptr) is not relevant for flat model code. - ) - -

    Struct/Union/Class Member Offsets

    - - $(P To access members of an aggregate, given a pointer to the aggregate - is in a register, use the qualified name of the member: - ) - --------------- -struct Foo { int a,b,c; } -int bar(Foo *f) { - asm { - mov EBX,f ; - mov EAX,Foo.b[EBX] ; - } -} --------------- - -

    Stack Variables

    - - $(P Stack variables (variables local to a function and allocated - on the stack) are accessed via the name of the variable indexed - by EBP: - ) - ---- -int foo(int x) { - asm { - mov EAX,x[EBP] ; // loads value of parameter x into EAX - mov EAX,x ; // does the same thing - } -} ---- - - $(P If the [EBP] is omitted, it is assumed for local variables. - If $(B naked) is used, this no longer holds. - ) - -

    Special Symbols

    - - $(DL - - $(DT $(B $)) - $(DD Represents the program counter of the start of the next - instruction. So, - --------------- -jmp $ ; --------------- - - branches to the instruction following the jmp instruction. - The $(B $) can only appear as the target of a jmp or call - instruction. - ) - - $(DT $(B __LOCAL_SIZE)) - $(DD This gets replaced by the number of local bytes in the local - stack frame. It is most handy when the $(B naked) is invoked - and a custom stack frame is programmed. - ) - - ) - -

    Opcodes Supported

    - - $(TABLE1 - $(TROW aaa, aad, aam, aas, adc) - - add - addpd - addps - addsd - addss - - and - andnpd - andnps - andpd - andps - - arpl - bound - bsf - bsr - bswap - - bt - btc - btr - bts - call - - cbw - cdq - clc - cld - clflush - - cli - clts - cmc - cmova - cmovae - - cmovb - cmovbe - cmovc - cmove - cmovg - - cmovge - cmovl - cmovle - cmovna - cmovnae - - cmovnb - cmovnbe - cmovnc - cmovne - cmovng - - cmovnge - cmovnl - cmovnle - cmovno - cmovnp - - cmovns - cmovnz - cmovo - cmovp - cmovpe - - cmovpo - cmovs - cmovz - cmp - cmppd - - cmpps - cmps - cmpsb - cmpsd - cmpss - - cmpsw - cmpxch8b - cmpxchg - comisd - comiss - - cpuid - cvtdq2pd - cvtdq2ps - cvtpd2dq - cvtpd2pi - - cvtpd2ps - cvtpi2pd - cvtpi2ps - cvtps2dq - cvtps2pd - - cvtps2pi - cvtsd2si - cvtsd2ss - cvtsi2sd - cvtsi2ss - - cvtss2sd - cvtss2si - cvttpd2dq - cvttpd2pi - cvttps2dq - - cvttps2pi - cvttsd2si - cvttss2si - cwd - cwde - - da - daa - das - db - dd - - de - dec - df - di - div - - divpd - divps - divsd - divss - dl - - dq - ds - dt - dw - emms - - enter - f2xm1 - fabs - fadd - faddp - - fbld - fbstp - fchs - fclex - fcmovb - - fcmovbe - fcmove - fcmovnb - fcmovnbe - fcmovne - - fcmovnu - fcmovu - fcom - fcomi - fcomip - - fcomp - fcompp - fcos - fdecstp - fdisi - - fdiv - fdivp - fdivr - fdivrp - feni - - ffree - fiadd - ficom - ficomp - fidiv - - fidivr - fild - fimul - fincstp - finit - - fist - fistp - fisub - fisubr - fld - - fld1 - fldcw - fldenv - fldl2e - fldl2t - - fldlg2 - fldln2 - fldpi - fldz - fmul - - fmulp - fnclex - fndisi - fneni - fninit - - fnop - fnsave - fnstcw - fnstenv - fnstsw - - fpatan - fprem - fprem1 - fptan - frndint - - frstor - fsave - fscale - fsetpm - fsin - - fsincos - fsqrt - fst - fstcw - fstenv - - fstp - fstsw - fsub - fsubp - fsubr - - fsubrp - ftst - fucom - fucomi - fucomip - - fucomp - fucompp - fwait - fxam - fxch - - fxrstor - fxsave - fxtract - fyl2x - fyl2xp1 - - hlt - idiv - imul - in - inc - - ins - insb - insd - insw - int - - into - invd - invlpg - iret - iretd - - ja - jae - jb - jbe - jc - - jcxz - je - jecxz - jg - jge - - jl - jle - jmp - jna - jnae - - jnb - jnbe - jnc - jne - jng - - jnge - jnl - jnle - jno - jnp - - jns - jnz - jo - jp - jpe - - jpo - js - jz - lahf - lar - - ldmxcsr - lds - lea - leave - les - - lfence - lfs - lgdt - lgs - lidt - - lldt - lmsw - lock - lods - lodsb - - lodsd - lodsw - loop - loope - loopne - - loopnz - loopz - lsl - lss - ltr - - maskmovdqu - maskmovq - maxpd - maxps - maxsd - - maxss - mfence - minpd - minps - minsd - - minss - mov - movapd - movaps - movd - - movdq2q - movdqa - movdqu - movhlps - movhpd - - movhps - movlhps - movlpd - movlps - movmskpd - - movmskps - movntdq - movnti - movntpd - movntps - - movntq - movq - movq2dq - movs - movsb - - movsd - movss - movsw - movsx - movupd - - movups - movzx - mul - mulpd - mulps - - mulsd - mulss - neg - nop - not - - or - orpd - orps - out - outs - - outsb - outsd - outsw - packssdw - packsswb - - packuswb - paddb - paddd - paddq - paddsb - - paddsw - paddusb - paddusw - paddw - pand - - pandn - pavgb - pavgw - pcmpeqb - pcmpeqd - - pcmpeqw - pcmpgtb - pcmpgtd - pcmpgtw - pextrw - - pinsrw - pmaddwd - pmaxsw - pmaxub - pminsw - - pminub - pmovmskb - pmulhuw - pmulhw - pmullw - - pmuludq - pop - popa - popad - popf - - popfd - por - prefetchnta - prefetcht0 - prefetcht1 - - prefetcht2 - psadbw - pshufd - pshufhw - pshuflw - - pshufw - pslld - pslldq - psllq - psllw - - psrad - psraw - psrld - psrldq - psrlq - - psrlw - psubb - psubd - psubq - psubsb - - psubsw - psubusb - psubusw - psubw - punpckhbw - - punpckhdq - punpckhqdq - punpckhwd - punpcklbw - punpckldq - - punpcklqdq - punpcklwd - push - pusha - pushad - - pushf - pushfd - pxor - rcl - rcpps - - rcpss - rcr - rdmsr - rdpmc - rdtsc - - rep - repe - repne - repnz - repz - - ret - retf - rol - ror - rsm - - rsqrtps - rsqrtss - sahf - sal - sar - - sbb - scas - scasb - scasd - scasw - - seta - setae - setb - setbe - setc - - sete - setg - setge - setl - setle - - setna - setnae - setnb - setnbe - setnc - - setne - setng - setnge - setnl - setnle - - setno - setnp - setns - setnz - seto - - setp - setpe - setpo - sets - setz - - sfence - sgdt - shl - shld - shr - - shrd - shufpd - shufps - sidt - sldt - - smsw - sqrtpd - sqrtps - sqrtsd - sqrtss - - stc - std - sti - stmxcsr - stos - - stosb - stosd - stosw - str - sub - - subpd - subps - subsd - subss - sysenter - - sysexit - test - ucomisd - ucomiss - ud2 - - unpckhpd - unpckhps - unpcklpd - unpcklps - verr - - verw - wait - wbinvd - wrmsr - xadd - - xchg - xlat - xlatb - xor - xorpd - - xorps - - - - - - ) - -

    Pentium 4 (Prescott) Opcodes Supported

    - - $(TABLE1 - - addsubpd - addsubps - fisttp - haddpd - haddps - - hsubpd - hsubps - lddqu - monitor - movddup - - movshdup - movsldup - mwait - - - - - ) - -

    AMD Opcodes Supported

    - - $(TABLE1 - - pavgusb - pf2id - pfacc - pfadd - pfcmpeq - - pfcmpge - pfcmpgt - pfmax - pfmin - pfmul - - pfnacc - pfpnacc - pfrcp - pfrcpit1 - pfrcpit2 - - pfrsqit1 - pfrsqrt - pfsub - pfsubr - pi2fd - - pmulhrw - pswapd - - ) - -$(COMMENT -SSE4.1 - -blendpd -blendps -blendvpd -blendvps -dppd -dpps -extractps -insertps -movntdqa -mpsadbw -packusdw -pblendub -pblendw -pcmpeqq -pextrb -pextrd -pextrq -pextrw -phminposuw -pinsrb -pinsrd -pinsrq -pmaxsb -pmaxsd -pmaxud -pmaxuw -pminsb -pminsd -pminud -pminuw -pmovsxbd -pmovsxbq -pmovsxbw -pmovsxwd -pmovsxwq -pmovsxdq -pmovzxbd -pmovzxbq -pmovzxbw -pmovzxwd -pmovzxwq -pmovzxdq -pmuldq -pmulld -ptest -roundpd -roundps -roundsd -roundss - -SSE4.2 - -crc32 -pcmpestri -pcmpestrm -pcmpistri -pcmpistrm -pcmpgtq -popcnt - -VMS - -invept -invvpid -vmcall -vmclear -vmlaunch -vmresume -vmptrld -vmptrst -vmread -vmwrite -vmxoff -vmxon - -SMX - -getsec -) - -) - -Macros: - TITLE=Inline Assembler - WIKI=IAsm - CATEGORY_SPEC=$0 - diff --git a/images/Thumbs.db b/images/Thumbs.db deleted file mode 100644 index dbc96ebf4d..0000000000 Binary files a/images/Thumbs.db and /dev/null differ diff --git a/images/apple_logo.png b/images/apple_logo.png new file mode 100644 index 0000000000..fde1854a00 Binary files /dev/null and b/images/apple_logo.png differ diff --git a/images/archlinux_logo.png b/images/archlinux_logo.png new file mode 100644 index 0000000000..28b60224b4 Binary files /dev/null and b/images/archlinux_logo.png differ diff --git a/images/centos_logo.png b/images/centos_logo.png new file mode 100644 index 0000000000..35c10acc22 Binary files /dev/null and b/images/centos_logo.png differ diff --git a/images/compiler-dmd.png b/images/compiler-dmd.png new file mode 100644 index 0000000000..a6f8066946 Binary files /dev/null and b/images/compiler-dmd.png differ diff --git a/images/compiler-dmd_hq.png b/images/compiler-dmd_hq.png new file mode 100644 index 0000000000..e55607fb58 Binary files /dev/null and b/images/compiler-dmd_hq.png differ diff --git a/images/compiler-gdc.svg b/images/compiler-gdc.svg new file mode 100644 index 0000000000..0c7a0c1125 --- /dev/null +++ b/images/compiler-gdc.svg @@ -0,0 +1,314 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Created by potrace 1.7, written by Peter Selinger 2001-2005 + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/compiler-ldc.ai b/images/compiler-ldc.ai new file mode 100644 index 0000000000..5a65eb3292 --- /dev/null +++ b/images/compiler-ldc.ai @@ -0,0 +1,2205 @@ +%PDF-1.5 %���� +1 0 obj <> endobj 2 0 obj <>stream + + + + + application/vnd.adobe.illustrator + + + LLVM_final + + + + + Adobe Illustrator CS6 (Windows) + 2015-05-30T10:14:41Z + 2015-08-18T15:48:34Z + 2015-08-18T15:48:34Z + + + + 256 + 228 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgA5AEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq4gEUPT FUJJObNgZTW0Y09U/wC6yez/AOT79u+FCLwJdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsV dirsVdiqHvb6O1RAQZJpW4QQL9p360HsOpPYYqrRer6a+qQZKfHxrxr7VxVdirsVdirsVdirsVdi rsVdirTKrKVYAqRQg7gg4qk7TvosixzEvpMjcYpTubcnoj/8V/ynt0w80ck5BBAINQdwRgS7FXYq 7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FUNqOoQWNs08u9NkQdWbsoxVC6TY3HqNqN/Q3860 C9oY+ojX9beJwoCvcavYQXcNm8vK6nbhHCgLNWhb4qfZHFSd8FLaMxS7FXYq7FXYq7FVG5vrK1AN 1cRwBuhldUr8uRGKoGbzNo0K83mcp/OkMzr/AMEiMMNItLNT8/aJBZPNZzpNcJ8QtpRJC0igjkEL qPip0xpBkmFh5m0+5mW2nrZ3jfYhmoA5/wCK3+y/6/bGk2mssUc0TRSqHjcFXU9CDgSx2K7l8vXi 2V45bSJa/VLltzFTcox/lUfcPi6cuB5o5MkBBFR0wJdirsVdirsVdirsVdirsVdirsVdirsVdirs Vdiq2WVIo2kc0Vevc+wAHUnsMVSa0Q314+p3ZC2tsSLdWI4gr9p69KLTr3O/QLhQl+u+cdNtrdp7 m9XT9MXrcMwSWUHp6fIgRoeztuf2fHCAgl4/5x/OnyVLGkGl3NzA1vyMc1lGxYs1K8mkMPLlxp17 9cmIsSW/KP8AzkBpkUyQXupz8GIAkuQ5P+yEjSJT5SJ88BgoL3TQfMmn6xbxy28qP6i8o3jbkki0 Bqh6991O4+VCYEMwU2wJdiqEvtTtbPishLzP/dwRjlI3yGEBbeKfmR/zkRbaDqd1o0MEr6hbHhNb xHgqMQG4vMaNXcfYG3Q5MQYGTyHUvz7833UkhtIobOOT7XEv6h9mdDFy/wBkDk+FjaQyfmT5omkL ySQsWNTyiVvxap/HDSprpH5satZScpNNsJ69WMbrIK/ytzNPuwcKvStG/wCcgtEv4haa/p5jifZg wEqD3DoFYH/YfTkTBNvS/LXnmIwJNpN2db0o/atCwa9gA6+k1aTqP5a8hkCEgs1SbR/MekFreYT2 k32ZYzR45F3BFd0dDvuMDLmkeh6vcaRqB0HVWAUFVtZuigOaRAf8VyUIT+R6x9OFUoBZfgZOxV2K uxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ksf1zUY3vBY+sII4wXuZy3ERoFq7k7U4owC/wCU4P7OEBBL yv8AMn84bWyQafp0YaCNR9VtOgYD7Ekw/ZTuqdT18CLIxYkvAvMPmDWddu2utTuXnkJJVSfgWvZV 6D9fjlgDFIpVxVCSDFWd/k5511/RvN+l6TaTlrHVLyC1a3ckqkk0gjSVP5WVn38RWoORkEh9paXq BvID6i+ndQt6d1CequB9OxG4yhmF9xLO7GC1oH/3ZMwqqD5d29vv9yl1pp9vbFnUF5n/ALyd/ikY +5/gNsbV8I/mxcfWPzO80yVJ46ndR1P/ABVKY/8AjXLo8mssXXChVUYVV0GKq6DFUy0vUtQ024W4 sbh7eUEHkhpWm4qOh+nFXqnk784L+G+Wa4lW11NqCS4Nfq90Afs3K+P+X19+2VmCbezvq2l+eNHd 7OMR69YIWfTpWAZ0cD1IuW3KOUfZcfZbidiMhyZXaa+RPM/6TtWsLiQyXtqiukrijzW7bJIw7OpB SQfzD3wEKCyrAydirsVdirsVdirsVdirsVdirsVdirsVUb6aSCyuJo1LyRRu6IBUsVUkAAda4q8u 8233lu/tn/RerW1nqWoMP319KTEzLUg8D3UtUL9mu9DQZZFhs8Q86/lt5u0BX1G/Rb6zkYs+o27m ZOTb1kJAZSa78hlgIQQwWXChBy4qhJOuKpr5Gdk88eXXQlXXU7Mqw6gi4Qg5E8lD7wvYvqt/FqUY or8be9A7oxpG/wA43P8AwJPhlLYmKqqiiig6/SeuBLeKvgH8yv8AyZHmv/tsah/1FSZeOTWWPrhQ qrhVXTFUQmKohBiqIQYqyvyp5p1PS7iB0klUW5rb3MNTLCf8n+ZD3Q7UyJjavfPIek6hquqxecXv o7aNvU/0KFKpI8hX1nBJBRZacuJrRicqPcyA6vUYpVkTkviQfmMizXYq7FXYqluuayNMjgbgJGlk 4spbiRGBVnGxrTYU8SMUEsC0fzP5n117O8sFSCyhe4Y6hec2jmaV3ANvbK4Z1SMqFLMoG4DH4slS LTm2gnt1Thqd7csJTO7StCodyFHxBYjt8GwrhpUWde8wWyDhBFfKKlgzmOQ1JNOVOP8AwuPCtqum ef8ARrq7Wwvkl0rUHIWOC8UIkhPaOUExt8q19siYptk2BLsVdirsVdir5M/OMoPNiFej2ytt03lk /hl8OTWh/I/5m6joEgsL8/XdCm/dz2svxhYzseNa/D/k/dhMbW0t/M/yfaaNdwato59Xy7qwMlk4 PIRvTk0JPsDVfEfLBEqXn8pySEJIcVTr8vIln/MHyxC1eMmrWKtTrQ3KA5E8lD78liSWJ4nFUkUq w9iKHKG1dirsVfAP5lf+TI81/wDbY1D/AKipMvHJrLH1woVVwqrpiqITFU48v6FqeuajHYadF6s7 AsxOyIg+07sdlVe5xJV6Cmj+U/LNqJZPS1G73DahdKWg5jqttb9ZafzNt8shZKpVe/mBeynhamT0 x9kyOY1FP5YIDHGny+LDwqyDyX+Yuvr6lu0tVTi7sFBJDypFsvJBUGQd+mAxV9NaNAYdLtlZzI5j VnkPUswqTt88qLYEZgS7FVK7u7eztZbq4cRwQqXkc9lUVOKvMPONxe68IrG55QLPLDNJGjtG0VnG 9Zk5KQwaT4EY+5GTAYlGWQ1rV5GttAiihs7Y+lJqM4IhUpt6cMa/aKjbsB0xJQrXH5Ya/cJv5uuo XpQ+jCqLX2HOv44OJPCl7eQPzK0nlJpvmGPV41FRb3kfpuTXoGJlB+9cIkiipW2u2+ou+ieaNPFl fH4WhlH7tiehBNaV/ZNSPfCtp5pOr3nlqVLTUJmudBchILuQ8pLUnYLI3Vo/AndflgISCzsEEAg1 B6HIMnYq7FXYq+RfzjYjzJZsaVewhag36ySZfHk1sCZ8khm/ka/i17SL7yLqEgC3ymXR5X6RXafE gB7BjsfYnInvS8wu45YJpIJkMc0TFJI2FCrKaEEeIOSQg3OKsv8AyYtTdfmr5ZiHVb1JfohBl7/6 mRlySOb7syhsdirsVfB/5yW7W/5qeZ0apJv5ZNxTaSkg/wCJZfHk1nmxBcKFVThVXQ4qmOk6de6p qFvp9jEZ7u6cRwxL1LH+HicVerare6L5E0AaNZMt1fTit5KtQbqVSQSzCjLbRtUKB9s/SchzS81v NTvNQumuruUyzNtU7AAdFUDZVHYDJoaR8VZf+XES3WtzWpFWmgUR+AK3EL/qU4JJfXujy+tpFjN/ vy3ifb/KQHMctgReKuxVJfMcbXclhp1KxzzGa4UmitHbL6nE+zScMIQXnHmK9vzqt7qFnZSOj2C6 c9KOYrgXRkcuoJoqinxUyQYvVtJ0230zTbbT7f8AuraMID3Yj7TH3Y7nIM0XirsVSXzV5XstfsTF KoW7iBNrcd1bwP8AknuMIKCLYboVy9xbT6Rqak3FvWORG3JVTxIPiVOWMWQ+Sr+W3eby/cuXazUS WEjdWtiaBfnGdvlTISCQyvIsnYqp3MvpW8sv++0ZvuFcVfIH5xycfNMENd7eyhhIPijODl8eTWwM vkkN217PaXUN1A3GaB1kjbwZTUYqm/5oQwz6ta+YrVaWnmC3W7YClFuV+C5Q0/a5jmf9bIhSwhmw q9R/5xk083f5t2M4FRYW11ct7AxGCv3zZGfJMeb7NylsdirsVfFH/OR9kbX839ZcCiXSWs6D520a N/wyHLocmuXN5spySFVThVVQ4q9W8mQWfk7yhN5t1Ff9yWpo0OlRHZ1gNVLL/K05BUHsgYjrkTvs l55f6pd6ley3t2/OeU1J6AAbBVHZVGwGSQtR8VVlkxVk35d6kLPzjpshP947Qgdi0yMif8OwwFL7 E8ryI2jRQqai1Z7cf6sbER/fHxOUFmE1wJdiqQ+ZtRjsJbeZqAmKZVPzMeEIecWvmhYfNomjoyXS UuIuzGPv/rFO/tkqYl6dDcJaW0d7auZ9KkUO6DcxKR9uMdeI/aTt28DFkmyOjorowZGAKsDUEHcE EYEt4q7FWB+b7UWHmez1CP4UvRwl/wBdKKT/AMCy/dk4liVO+n+pahp2qK1Pq0yxzkf75l+B6/Kt cJQ9Aytm7FUFrTU0m6A2MkbRqf8AKk+Afi2EIL40/Ni/W68+alIhrGPSCf8AIlGP/DE5eOTAsQMm FCmz4qyFZf0p+Xl9ZtvPoNwl7bk9fQuSIZkUf65Rz8sj1VgzNhV9Bf8AOH2k+prnmLWCP95raG0U 06/WJDI2/t9XGVzZRfUOVs3Yq7FXyf8A85c6YYPPGk6iBRLzTxETvu8Ez1P/AAMq5bDkwk8NU5Ni qoCTQZGcxEWW7T6eeaYhAXIo+GxbgJJXWJD9lpCd/kqhmI96UzV5O0JH6dg9hpfZnHEfvSZS7hsP mnGt65qmti3XU9UimS1QR20axtEiIqhFVUiiRdlUAbZT+cyd7nf6H9J/Ml/pv2pWLaEdLuL7pf8A qnj+dyd/2L/of0n8yX+m/auEUY/4/Ivul/6p4/ncnf8AYv8Aof0n8yX+m/a3wX/lsi/4GX/qnj+d y9/2L/of0n8yX+m/aqW80tvPHPDfxJNCyyRuFkqGU1B/u+xx/O5O/wCxf9D+k/mS/wBN+1mll+df 5m2SMlr5mijRuNV+qQkfAoQfatj+yoGD83k70/yBpf5h/wBN+1E/8r7/ADZ/6mmL/pDt/wDslwfm p96f5B0v8w/6b9rv+V+fmz/1NMX/AEh2/wD2S4/mp96/yDpf5h/037WV+T/PfmzzPYXt15i1NdV+ rPHDYoIkgVDIGaZj6UcBb7KUrXM3SZJTBJLzXb+kw6cxjjBBNk737v0p/pthavex3XpD6wKhWBI+ 1t06ZmvPMw8i+bw2rahoDRyCG39OW3uDT0+cqc3hDE/a2LqoHTl4ZUJXIhzJ6cxxxn0LEvzn81/m F5Ols7ry9rQsNDuSYhbPbwSiOY1eis8Mr0IrtWg7Zjaqc4UQdncdh6XT6gyhkiTIbjfp+PveY/8A K/fza/6miP8A6Q7b/smzD/NT73ov5A0v8w/6b9rv+V+/m1/1M8f/AEh23/ZNj+an3r/IGl/mH/Tf tQepfnN+ZWpJGl75ijlWJucf+iwLRqUrVbdTj+byd6/yBpf5h/037VC5/Nr8wbmB4J9fjeJxRl+r QivfqIAcP5zJ3o/0P6T+Yf8ATftTIfn5+bQAA8zx0H/Lnbf9k2D81PvT/IGl/mH/AE37Xf8AK/fz a/6meP8A6Q7b/smx/NT71/kDS/zD/pv2qVz+en5qXMJhm8yo0bEEr9UtxupqNxbg9Rj+byd6/wAg aX+Yf9N+1hF9dXF9eTXl1dpJc3DmSWTiwqzGpNFQAfRkvzuTv+xH+h7SfzD/AKY/rUPTr9mZHPhu v4sFGSjr8g50WvL7N6aQ2Eo/G/1qLllJDAgjYg9s2Wn1Ucm3IvKdpdkZNKbPqh/O/X3Mg8gFp/MP 6N39HU7a5tLgjfjE8LF3p/kBeWZEnUsKnWSKR4pAVkQlXU9QQaEYq+v/APnFHQzY/lo+outH1e9m mRvGKECBf+HjfKpndnF7PkGTsVdirwH/AJy+0f1vK+hawBVrK8ktmI7LdR86n6bcZODGT5ZU5awT WxhRIGuJBULQKp/ac9B8gNz93fNJrM3HKugfQuwdAMOESP15Nz5DoPx+hMLLT3uj9YuWJVug7mn8 MxQLd1PJw7BNY9NsgKeip+Yr+vJcIcc5Jd6ummWHe3T/AIEYeEMDll3q6aTp5620f/AjDwhicsu9 WTR9MPW1j/4EYeEMDml3q6aJpZ/49Iv+BGPCGJzz7yrJoWkH/jzi/wCAGHhDE5595Vk0DRj/AMeU P/ADDwBgdRPvKp+gNE/5YYf+AGPAEfmMneU20h7PTImhggWKF25uIxTcgCtB7DMvTZBHZ0PbGmyZ iJj1ECmceWjHdxTT27rJ6SEJRgP3jfCo36EV5b+GZspAc3ncWKUzURZRd15ZubjUodR0ucWWvWhV UZyTbymNTGI7hFO44EpyHxAHBwi76tozTEeA/T3IP8xX1698vR2vmDQUtIhOtJTcJco7gMf3YVVb jt1cKfbKNTvF2PYxrNYNGi8z/QGif8sMP/ADNfwB6n8xk7y79AaJ/wAsMP8AwAx4Av5jJ3l36A0T /lhh/wCAGPAF/MZO8u/QGif8sMP/AAAx4Av5jJ3l36A0T/lhh/4AY8AX8xk7y79AaJ/yww/8AMeA L+Yyd5d+gNE/5YYf+AGPAF/MZO8u/QGif8sMP/ADHgC/mMneUs1TyVptxEWsx9VuAPhoSUJ8CDWn 0ZGWMdHIxa2UT6twwaaCZJJLWdSs8NRQ9fh6r93TKoyMTY5h2GTHDLAg7wk9a/5xk8nQav5k1bUb z/ee0spLWEHYtJeKY2K+PGLkD/rDN9DLxwBfMdZpDgzSxnp93R5D5+s5bTzjqkDrSV5zK6AdHmAk ZR8mcjLg4T7w8g+Xv8O+StE0QgLJY2cMU9Ohm4Ayn6ZCxykltCfYFdirsVYB+fOhHWfyo1+BF5TW sAvYvEG1cTPT/nmrDJRO6DyfDEe7AeJy2RoIxxuQHeU9kX/R7SIdH5SE/wCUzmM/RSMZzRfW4AC6 6bMkijCqFAoAKAewywOGSnuieVPMWsRPLpmnzXUUZ4vJGvwhutORoK+2TjAnkHEz6vHjNTkAm6fl v54HXR7j7h/XJ+DLucc9pYP54Vk/LrzqOukXH3D+uHwZdzE9o4P54Vl/L3zn30mf7h/XD4Uu5ge0 MH84Kyfl/wCcB/0qZ/uH9cfCl3MT2hh/nBXTyF5uH/Sqm+4f1w+FLuYHX4f5wVR5F82j/pVzfcP6 4fCl3Mfz2H+cFCXyr5miFX0q7A8RC5Ap40BwcEu5mNViP8Ufml89pdW543ELwt4SKVP4gZEhujMH kbXQ+Yl0JYXdh6d3cxNLHuCy2wblv7iamZETcR/WdbOMY551zlj+0/2Mj8ta9+itcubbUZeMM8zL LK52WYMRyJP8x2OSwTIkQerT2hp4zwjINuED5PS9YvNMvNIn07XpAbZ1EkEwHxpxHVj027HMqcQR vydHgnOMwY/V0eHXCwrPIsLF4gxEbkUJUHY0zVmr2ezxkmIMhRU8DN2KuxV2KuxVmflf8s9R1i0S 9upxZWko5Q1XnI6/zcaqAp7VP0ZfDCTu6zVdpxxnhA4imWr/AJQXMNu8umXn1mRRUW8qhC1OyuCR X5jJS0/c0Ye2ATUxXm88kjkjkaORSkiEq6MKEEGhBBzHdyDYsMC88wpBrFvcoBykQMw8WRqVP0UG Y+Xm7fQyuBD1H/nHq9ntdP1SKI0FrerJGe5LpxNfmIxmfoj6SPN5P2mgPGjLqYpTqvkka3/zk1p9 n6QeyllXV7rb4fRRmuuLbd/gjPzzYXs8zW76vytm7FXYq7FVK7tYLu1mtZ15wXEbRSoe6OCrD6Qc VfnXrWkz6N5gvtIuK+vp91LayV2q0MhQn6aZbL6SuH+8j7wmT9LD/U/5nPnOPrQ/i/HQMpjTLXAJ fS35QIq/l7pZAALG4LEDqfrEgqfoGbLT/QHh+2D/AITL4fcGY5c6x2KuxV2KuxV2KuxVplV1KsAy nqCKjFILy38yvyiufM8lbKWK2USCSFowFaM8eLgp8KMrUr9oGv4tCqZDLISu7am/Jm4l0q2D30c2 pRRIs4lSsUkka8OYO5VmAq3XcnKJ4rNguz03aQjERnGwGJa3pHmLSFSz1JJo7ddoQWLQGnTgQSn0 Zjz4hsXcaeeGfqhV+7dKMrctwBJoOuKpra+VfMl0oaDTLlkO4cxsqn5FgBkxCR6OPLVYo85BfP5O 80wryfS7mnfjGX/4jXE45dyI6zEf4glMkckTmORSjrsyMCCPmDkXIBB5Oj4eovP7FRyp4d8VL6Th 9L0U9GnpcR6fHpxptT2pmyeIld781+KHhX5ifVv8Y6j9Xpx5JzpSnqemvPp/ldffMHN9Res7OvwY 3+N3kn5g/wC9lp/xjb/iWYmXm9D2f9Jej/kL/vNr3/MTH+psztFyPveY9p/7yH9X9L2XyX5TtovN d95ocBrq4sobSF+6p6jeqPp9GPM23mAN2d4EuxV2KuxV2KvjD/nJvy1+h/zVlvI142+tww3q06CQ fuZR8y0fM/62Tv0lOL+8j7wwd/8Ajw/1P+Zz5z3c+s/zvx0Zei5a60l9JflIKfl9pQ/5iP8AqJkz ZYPoDxPa/wDjMvh/uQy/LnWuxV2KuxV2KuxV2KuxV2KuxVSurS2u4Ht7mJZoJBR43AZT9BwEWyjM xNg0XnmrflDHLqUb6ZciCwkb9/HJVmjH/Ff83yY/TmPLT77O5w9rkR9YuTL9C8o6DosaiztlM4+1 dSAPKT/rHp8lpl0cYjyddn1eTKfUdu7onOTcV2KoDVtB0jV4fS1C1ScUorkUdf8AVcUYffkZRB5t 2HPPGbiaeT+c/wAvLvRA17ZFrnTK/ET/AHkXhzp1H+UPpzEyYuHccnoNF2gMvpltL71Tyt+Zt/pF qljeQ/XbSIcYW5cZEX+WpBDAdh+OGGYjYo1XZkch4onhKZ6t+cE0lu0emWXoSsKevMwbj7hAKE/M 5KWo7mjF2OAbmbDzmWWSWV5ZWLySMWd23JZjUkn3zHd0AAKDBfzB/wB7LT/jG3/Esoy83a9n/SXo 35C/7y69/wAxMf6mzO0XI+95j2n/ALyH9X9L6M8sAfoiI96tv/sjmY8ymuKuxV2KuxV2KvDP+cs/ Kx1Dybp3mCFKy6JdhJiB0t7sqjEn2lWMfThvYs8X1x94fNjddP8A9T/mc+aDufV/5346M0RMudWS +jvyoFPIGlf89/8AqJkzY4PoDxXa3+MS+H3BluXOudirA/zA87azoGp21tYrCY5YfUb1VLHlzZdq MvhlGXIYnZ2/Z+ihmgTK+bF/+Vteaf5LX/kW3/NeVePJzv5Jxebv+Vteaf5LX/kW3/NePjyX+ScX m3/ytrzT/Ja/8i2/5rx8eS/yTi80TB+cWuhv39lauvggkQ/eWfCNQWEux8fQlPtM/N3RJyEv7eWy Y9XX98g+fEBv+FyyOoHVw8vZGQfSRL7GZ6fqmnajB69jcx3MXdo2BofBh1B+eXCQPJ1uTFKBqQpE 4Wt2KuxV2KuxV2KuxVbLFHLG0Uqh43BV0YVBB2IIOKQSDYeEedvLn6C12S2jB+qTD1rUnf4GP2a/ 5JFMwMkOEvWaLU+Ljs8xzSDK3MdirB/zB/3stP8AjG3/ABLKcvN2nZ/0l6N+Qn+8uvf8xMf6mzO0 XI+95j2n/vIf1f0vozyx/wAceL/Wf/iRzMeZTXFXYq7FXYq7FWPfmHptvqXkTzBZXCho5dPuaV7O sTMjfNXUMMEuTZh+se8Pho/a0/8A1R/yefNF3Pqv878dGdomXuqJfRH5VCnkLS/+e/8A1ESZsMH0 B4ztX/GJfD7gyzLnXOxV5L+cX/Hcsv8AmF/5mNmJqOb0XY/92fewHMd27sVdirsVdiqJ0/Ur/T7l bmyne3nXo6Gn0HsR7HCCRya8mOMxUhYet+SPzCg1njYahxg1OnwMNkmA/l8G9vuzMx5eLY83ndd2 ecXqjvH7maZc6x2KuxV2KuxV2KuxV59+cVmjaTYXlPjinMNe9JULf8y8x9QNgXcdjz9co+X4+95R mI9C7FWD/mD/AL2Wn/GNv+JZTl5u07P+kvRvyE/3l13/AJiY/wBTZnaLkfe8x7T/AN5D+r+l9GeW P+OPF/rP/wASOZjzKa4q7FXYq7FXYqlXm3/lFdZ/5gbn/ky2CXItmH6x7w+Dv29P/wBUf8nnzRdz 6r/O/HR6Ci5kOnJfQn5WinkTTP8Anv8A9REmbDB9AeO7U/xiXw+4Mqy117sVeS/nF/x3LL/mF/5m NmJqOb0XY/8Adn3sBzHdu7FXYq7FXYq7FVyO8brIjFXQhlYGhBG4IOFBFvc/InmU67oiyTEfXbY+ ldDxIHwvT/KH41zOxT4g8pr9N4WSh9J5MjyxwnYq7FXYq7FXYqwP84bpU0Kztq0ea5DgeKxowP4u Mx9Qdnb9jxvIT3B5HmI9E7FWD/mD/vZaf8Y2/wCJZTl5u07P+kvRvyE/3l13/mJj/U2Z2i5H3vMe 0/8AeQ/q/pfRnlj/AI48X+s//EjmY8ymuKuxV2KuxV2KpV5t/wCUV1n/AJgbn/ky2CXItmH6x7w+ Dh9vT/8AVH/J580Xc+q9Jfjo9HRMyHSkvf8A8sBTyNpn/Pf/AKiJM2GH6Q8f2p/jEvh9wZTlrgOx V5L+cX/Hcsv+YX/mY2Ymo5vRdj/3Z97Acx3buxV2KuxV2KuxV2Ks4/KO/aHzDNaV/d3cDfD4vGQy n6F5ZfgO7qu18d4we4vYMzHm3Yq7FXYq7FXYq8R/MXzHHrOulbduVlZAwwsDUM1au4+Z2+QzBzTs vU9nabw8e/1SYrlTsHYqwf8AMH/ey0/4xt/xLKcvN2nZ/wBJejfkJ/vLrv8AzEx/qbM7Rcj73mPa f+8h/V/S+jPLH/HHi/1n/wCJHMx5lNcVdirsVdirsVSrzb/yius/8wNz/wAmWwS5Fsw/WPeHwnaf 726T80/6iGzRDmH1Sf0y/HR9Ax5sHjy9Q8nADy5ZgCg/ebf89WzKx/S6HWf3p/HROcm4rsVef/mN ptnd6nbNOnJlgoCCRtzY9jmPmAJdx2dklGBrvYc/lvT26GRfkR/EHKeAOyGpkov5XiP2Lhh/rKD+ ojBwMxqj3Id/LF0PsSo3zqP4HBwMhqh3IeTQNTTpGHHirD+NMHAWwaiCFksL2P7cEgHjxNPvwUWY yRPVQIINDscDN2Kss/K9WPnC2IGyxyk/LgR/HLsH1Ou7U/uT8HtmZry7sVdirsVU7m5t7aFp7mVI YUFXkkYKoHuTgJplGJkaAsvL/PH5krdxSaZorMLd6rcXm6lx3WMdQvie/wCvGy5r2DvdD2bwnjyc +553mM7p2KuxVg/5g/72Wn/GNv8AiWU5ebtOz/pL0b8g/wDeTXf+YmP9TZnaLkfe8x7T/wB5D+r+ l9GeWP8Ajjxf6z/8SOZjzKa4q7FXYq7FXYqlXm3/AJRXWf8AmBuf+TLYJci2YfrHvD4TtP8Ae3Sf mn/UQ2aIcw+qT+mX46PoGPNg8eXqHk//AJRy0/56f8nWzKx/S6HWf3p/HROcm4rsVYT57/46Nv8A 8Yf+NjlGXm7TQfSfexnK3OdirsVdirsVWyQxSCkiK48GAP68UgkckLLo2mydYAp8Vqv6sjwhsGaQ 6sp/Ljy3b2t9c6lHyoE9BAxBFWIZqbdgo+/LcMKNuB2lqTKIifez/Mh07sVS3zJqjaVoV7qC09SC ImLl09RvhSv+yIyM5ULb9Ni8TII95eTz/ml5ulBCTRQV7xxKaf8AB88xDnk9DHsvCOhPxY9qWs6t qbh7+7luSN1DsSo/1V6D6MrMiebmY8MIfSAEFkW12KuxV2KsH/MH/ey0/wCMbf8AEspy83adn/SX o35B/wC8mu/8xMf/ABFszdFyPveY9p/7yH9X9L6M8sf8ceL/AFn/AOJHM15lNcVdirsVdirsVSrz b/yius/8wNz/AMmWwS5Fsw/WPeHwnZ/726T/AKyf8n2zRDmH1Sf0y/HR9AIc2Dx5eoeTf+Ubs/8A np/ydbMrH9LodZ/en8dE6ybiuxVhPnv/AI6Nv/xh/wCNjlGXm7TQfSfexnK3OdirsVdirsVdiqIs bK4vblLe3XlI5+gDuT7DCBbGcxEWXpWmafDYWUdrFuEHxN3Zj1JzJAoOjy5DOVlFYWt2KsU8+3cT WsWnEB/VPqSqRUcV+zUHxP6sqyno7DQQNmTz2bQNNl3CGM+KGn4GozHMA7mOokEBP5YkG8Ewb/Jc U/EVyJg2x1Q6hLp9J1CCvOFiv8y/EPwyJiW6OWJ6oTItrsVdirB/zB/3stP+Mbf8SynLzdp2f9Je jfkH/vJrv/MTH/xFszdFyPveY9p/7yH9X9L6M8sf8ceL/Wf/AIkczXmU1xV2KuxV2KuxVKvNv/KK 6z/zA3P/ACZbBLkWzD9Y94fCdn/vbpX+sn/J9s0Q5h9Un9Mvx0e+q2Z7yBep+TP+Uas/+en/ACdf MvH9LoNb/en4fcnWTcV2KsJ89/8AHRt/+MP/ABscoy83aaD6T72M5W5zsVdirsVdiqZ6X5e1LUGB jjMcJ6zOCFp7fzfRkowJaMuojDnzZ1pGi2mlwcIRykb+9mb7TH+A9svjGnVZs0sh3R+SaXYqo3l3 BaW0lxO3GOMVPifAD3OAmmUIGRoPMtRvpb68lupftSHZewA2AHyGYxNl3uPGIRACGwM3Yq7FVG4s rS4/volc/wAxG/3jfAQGcZkcillz5Zt2qbeQxn+VviH9ciYN8dSeqVXOi6hBUmP1EH7Ufxfh1yBi W+OaJedfmDteWn/GNv8AiWY+Xm7rs/6S9F/IP/eTXf8AmJj/AOItmbouR97zHtP/AHkP6v6X0Z5Y /wCOPF/rP/xI5mvMprirsVdirsVdiqVebf8AlFdZ/wCYG5/5MtglyLZh+se8PhK0/wB7NK+af8n2 zRDmH1Sf0y/HR70rZnvJF6v5K38sWX/PX/k6+ZWP6Xntb/en4fcneWOK1iqTa55bj1WeOVpzCY14 UC8q718RkJQtycGpOMVVpb/gKH/lsb/kWP8AmrI+E3/nz3O/wFD/AMtjf8ix/wA1Y+Ev589y5fId rT4rtyfZQP4nHwkfnz3K8fkfSVNXkmf2LKB+C1w+GGJ10/JMrTQNHtSDFapyHRn+M/e1aZIRAaJ6 icuZTDJNLsVdiqyeeGCJppnCRoKsx6AYCUxiSaDz/wAw+YJNTm4R1SzjP7tO7H+ZsonO3cafTjGP NJsg5LsVdirsVdirsVdiryb86FUalppAAJhep8fiGYmo5h6LsU+mXvZV+QX+8euf8xMf/EWzK0XI +90PtP8A3kP6v6X0b5Y/448X+s//ABI5mvMprirsVdirsVdiqVebf+UV1n/mBuf+TLYJci2YfrHv D4StP97NL+af8n2zRDmH1Sf0y/HR7spzPeTeteRzXyvZf89f+Tr5lY/pee1396fh9yeZY4jWKuxV 2KuxV2KuxV2KuxV2KpdquvafpqkTPymp8MCbufn4fTkZSAbsWCU+XJg2sa9e6pJ+8PCBTWOBfsj3 PicolIl22HBHGNuaW5FudirsVdirsVdirsVdiryf86f+Ojpn/GGT/iQzE1PMPQ9i/TL3sp/IL/eP XP8AmIj/AOItmVouR97ovaf+8h/V/S+jfLH/ABx4v9Z/+JHM15lNcVdirsVdirsVSrzb/wAorrP/ ADA3P/JlsEuRbMP1j3h8I2v+9ml/NP8Ak+2aIdH1Sf0y/HR7orZnPKPVvIN3by+XYII3Bmty6ypX ccpGYGngQ2ZeI+l5/XwIyk9CyTLHCaOKtYq7FXYq0zKoqxAHidsUrWuLdRVpUA8SwGC08JQs2taT CKyXcQp2DBj9y1OAyDOOGZ5ApVd+d9MiBFuj3DdjTgv3tv8AhkTkDkQ0Mzz2SC/83atdApGwtoz2 i+1T3Y7/AHUys5CXLx6SEfNJWZmJZiSx3JO5JyDlNYq7FXYq7FXYq7FXYq7FXYq8n/On/jo6Z/xh k/4kMxNTzD0PYv0y97KfyC/3j1z/AJiI/wDiLZlaLkfe6L2n/vIf1f0vo3yx/wAceL/Wf/iRzNeZ TXFXYq7FXYq7FULqtiL/AEu8sS3AXcEkBfrT1EK1/HAQyhKiD3PgW5jubORFkXhdWMrwSof2Xjfl 8X+yLD6M0RFH3PquOQnGxykL+b2nTb+C+sobuA1jmQOvtXqD7g7Zmg2LeZyYzCRieiNVsLWqK2Fi VVWxYqinChVVsLFVU4sV4OFDeKHYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq8W/NPVodR8zrawsGh sEELsP8AfhJaTf8Aydh9GYWeVyeo7KwmGKzzlu9E/IWwlj8uX9++wvboiNf8mJQKj/ZMR9GZ2ijU L73lvaXKJZxEfwxfQflj/jjxfN/+JHMt55NcVdirsVdirsVdir5d/wCcify1n0fXJ/NdjCX0XVmB 1EIK/V7s9ZCPCQ/FX+YsNqjNbq8NHiHIvaez/aInAYZH1R+nzHd+P0PMPL/mnUtAPAKLiwkNfTJ+ Gvco3Y+IP3ZiwmYu91Gljm8pMvi/NDQyoMkFwjd14ofx5Zd4wdcey8neFUfmj5eH+6rj/gF/5qw+ MGP8l5PJePzU8vD/AHVc/wDAL/zVj44R/JWTvC8fmv5dH+6rn/gF/wCasfHCP5Ky94XD82vLg/3T c/8AAJ/zVh8eKP5Jy94Xj83fLY/3Tdf8An/NePjxR/JGXvC8fnB5aH+6Lr/gE/5rx/MRR/I+XvC7 /lcPln/fF1/wCf8ANeH8xFH8j5e+Lv8AlcPln/fF1/wCf814/mIr/I+Xvi7/AJXD5Z/3xdf8An/N eP5iK/yPl74u/wCVw+Wf98XX/AJ/zXj+Yiv8j5e+Lv8AlcPln/fF1/wCf814/mIr/I+Xvi7/AJXD 5Z/3xdf8An/NeP5iK/yPl74u/wCVw+Wf98XX/AJ/zXj+Yiv8j5e+Lv8AlcPln/fF1/wCf814/mIr /I+Xvi7/AJXD5Z/3xdf8An/NeP5iK/yPl74u/wCVw+Wf98XX/AJ/zXj+Yiv8j5e+Lv8AlcPln/fF 1/wCf814/mIr/I+Xvi7/AJXD5Z/3xdf8An/NeP5iK/yPl74u/wCVw+Wf98XX/AJ/zXj+Yiv8j5e+ KQ+YPzeubqBrbRbdrUyChuZCDIK/yKKgH3qcrnqL5OXp+yBE3kN+TDvL2galr2rxaZYqZLq4NZJD usadXd2/X93U5VjxmZoOfrNXDT4zOXIch3l9R6Fo9pouj2ml2g/cWkYjUnqx6sx92YknN3CIiKD5 lnzSyzM5c5F6bo9u1vplvEwowXkw8Cx5EfjhakZirsVdirsVdirsVU7m2t7q3kt7mJJ7eZSksMih 0dWFCrK1QQR2OKQSDYeB+fP+ccNMjuZL/wAt3cmnW0xrJaMDNCp/l3IYJ8+XhmJPRxPLZ6HTe0eW ArIBPz5Fg/8AyonzJ/1crD/kT/zZlX5I97n/AOifH/Ml/pnf8qI8x/8AVysf+RP/ADZj+SPev+if H/Ml/pnf8qI8x/8AVysf+RP/ADZj+SPev+ifH/Ml/pnf8qI8x/8AVysf+RP/ADZj+SPev+ifH/Ml /pnf8qI8x/8AVysf+RJ/5ox/JHvX/RPj/mS/0zX/ACofzH/1crH/AJEn/mjH8ie9f9E+P+ZL/TO/ 5UP5j/6uVj/yJP8AzRj+RPev+ifH/Ml/pnf8qH8x/wDVysf+RR/5ox/InvX/AET4/wCZL/TO/wCV D+Y/+rlY/wDIo/8ANGP5E96/6KMf8yX+md/yobzF/wBXKx/5FH/mjH8ie9f9FGP+ZL/TO/5UN5i/ 6uVj/wAij/zRj+RPev8Aoox/zJf6Zr/lQ3mL/q5WX/Io/wDNGP5E96/6KMf8yX+md/yoXzF/1crL /kUf+aMfyJ71/wBFGP8AmS/0zv8AlQvmL/q5WX/Io/8ANGD8ie9P+ijH/Ml/pnf8qF8xf9XKy/5F N/zRj+RPev8Aoox/zJf6Z3/KhfMX/Vysv+RTf80Y/kT3r/oox/zJf6Z3/KhPMX/Vysv+Rbf804/k T3r/AKKIfzJfN3/KhPMP/Vzsv+Rbf804/kT3r/ooh/Ml82v+VCeYf+rnZf8AItv+acfyJ71/0UQ/ mS+bv+VCeYf+rnZf8i2/5px/InvX/RRD+Yfmi9P/ACBvDL/uS1dEg/aS1i+Jh4cm4gf8CclHQ95a svtRt6Ib+ZeneWfKeh+W7L6rpVuIw1DNM3xSyEd3fv8ALoOwzMx44wFB5vV6zJqJcWQ3+hmPl7RX upluZlpbRmoB/bI7D28cm4zMcVdirsVdirsVdirsVdirTceJ5U40+KvSnvirFtT/AMK+oePPn+19 Wpx/4b4fuxVA/wDOtf8AL5/ySwq7/nWv+Xz/AJJYq7/nWv8Al8/5JYq7/nWv+Xz/AJJYq7/nWv8A l8/5JYq7/nWv+Xz/AJJYq7/nWv8Al8/5JYq7/nWv+Xz/AJJYq7/nWv8Al8/5JYq7/nWv+Xz/AJJY q7/nWv8Al8/5JYq7/nWv+Xz/AJJYq7/nWv8Al8/5JYq7/nWv+Xz/AJJYq7/nWv8Al8/5JYq7/nWv +Xz/AJJYq7/nWv8Al8/5JYq7/nWv+Xz/AJJYq7/nWv8Al8/5JYq7/nWv+Xz/AJJYqjdN/wAK+oOX qc6/D9Zpxr/sfh+/ArKl48RwpxoONOlO1MVbxV2KuxV//9k= + + + + + + xmp.did:053E376AB306E511B6F29BFCAE084907 + uuid:de49a440-3bbf-4568-8d94-ff2453f3acd9 + uuid:A737E8EBAD7EDE11BF41D77851D9C732 + default + + xmp.iid:043E376AB306E511B6F29BFCAE084907 + xmp.did:043E376AB306E511B6F29BFCAE084907 + uuid:A737E8EBAD7EDE11BF41D77851D9C732 + default + + + + + saved + xmp.iid:043E376AB306E511B6F29BFCAE084907 + 2015-05-30T10:05:35Z + Adobe Illustrator CS6 (Windows) + / + + + saved + xmp.iid:053E376AB306E511B6F29BFCAE084907 + 2015-05-30T10:14:42Z + Adobe Illustrator CS6 (Windows) + / + + + + + + Print + Document + + + 1 + True + False + + 1024.000000 + 1024.000000 + Pixels + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + R=0 G=0 B=0 1 + RGB + PROCESS + 0 + 0 + 0 + + + CMYK Red + RGB + PROCESS + 192 + 33 + 32 + + + CMYK Yellow + RGB + PROCESS + 255 + 242 + 0 + + + CMYK Green + RGB + PROCESS + 37 + 148 + 61 + + + CMYK Cyan + RGB + PROCESS + 0 + 152 + 234 + + + CMYK Blue + RGB + PROCESS + 36 + 31 + 128 + + + CMYK Magenta + RGB + PROCESS + 190 + 14 + 123 + + + C=15 M=100 Y=90 K=10 + RGB + PROCESS + 146 + 30 + 36 + + + C=0 M=90 Y=85 K=0 + RGB + PROCESS + 196 + 56 + 44 + + + C=0 M=80 Y=95 K=0 + RGB + PROCESS + 200 + 78 + 34 + + + C=0 M=50 Y=100 K=0 + RGB + PROCESS + 216 + 133 + 26 + + + C=0 M=35 Y=85 K=0 + RGB + PROCESS + 226 + 163 + 50 + + + C=5 M=0 Y=90 K=0 + RGB + PROCESS + 243 + 236 + 35 + + + C=20 M=0 Y=100 K=0 + RGB + PROCESS + 207 + 218 + 24 + + + C=50 M=0 Y=100 K=0 + RGB + PROCESS + 142 + 187 + 46 + + + C=75 M=0 Y=100 K=0 + RGB + PROCESS + 92 + 165 + 55 + + + C=85 M=10 Y=100 K=10 + RGB + PROCESS + 64 + 129 + 51 + + + C=90 M=30 Y=95 K=30 + RGB + PROCESS + 41 + 85 + 42 + + + C=75 M=0 Y=75 K=0 + RGB + PROCESS + 89 + 166 + 94 + + + C=80 M=10 Y=45 K=0 + RGB + PROCESS + 73 + 149 + 138 + + + C=70 M=15 Y=0 K=0 + RGB + PROCESS + 82 + 149 + 217 + + + C=85 M=50 Y=0 K=0 + RGB + PROCESS + 53 + 94 + 173 + + + C=100 M=95 Y=5 K=0 + RGB + PROCESS + 36 + 38 + 126 + + + C=100 M=100 Y=25 K=25 + RGB + PROCESS + 28 + 23 + 79 + + + C=75 M=100 Y=0 K=0 + RGB + PROCESS + 71 + 29 + 127 + + + C=50 M=100 Y=0 K=0 + RGB + PROCESS + 107 + 27 + 125 + + + C=35 M=100 Y=35 K=10 + RGB + PROCESS + 118 + 26 + 81 + + + C=10 M=100 Y=50 K=0 + RGB + PROCESS + 173 + 29 + 75 + + + C=0 M=95 Y=20 K=0 + RGB + PROCESS + 193 + 37 + 106 + + + C=25 M=25 Y=40 K=0 + RGB + PROCESS + 176 + 166 + 136 + + + C=40 M=45 Y=50 K=5 + RGB + PROCESS + 130 + 115 + 102 + + + C=50 M=50 Y=60 K=25 + RGB + PROCESS + 91 + 83 + 70 + + + C=55 M=60 Y=65 K=40 + RGB + PROCESS + 68 + 58 + 51 + + + C=25 M=40 Y=65 K=0 + RGB + PROCESS + 169 + 137 + 89 + + + C=30 M=50 Y=75 K=10 + RGB + PROCESS + 139 + 106 + 63 + + + C=35 M=60 Y=80 K=25 + RGB + PROCESS + 108 + 77 + 46 + + + C=40 M=65 Y=90 K=35 + RGB + PROCESS + 88 + 61 + 31 + + + C=40 M=70 Y=100 K=50 + RGB + PROCESS + 69 + 44 + 16 + + + C=50 M=70 Y=80 K=70 + RGB + PROCESS + 41 + 27 + 17 + + + R=144 G=154 B=157 1 + RGB + PROCESS + 144 + 154 + 157 + + + R=38 G=45 B=58 1 + RGB + PROCESS + 38 + 45 + 58 + + + + + + Print Color Group + 1 + + + + C=0 M=30 Y=70 K=0 + RGB + PROCESS + 230 + 175 + 81 + + + C=5 M=70 Y=90 K=0 + RGB + PROCESS + 194 + 95 + 41 + + + C=5 M=90 Y=75 K=0 + RGB + PROCESS + 185 + 55 + 55 + + + C=30 M=0 Y=95 K=0 + RGB + PROCESS + 185 + 207 + 42 + + + C=60 M=5 Y=95 K=0 + RGB + PROCESS + 121 + 169 + 56 + + + C=30 M=0 Y=10 K=0 + RGB + PROCESS + 176 + 214 + 221 + + + C=60 M=10 Y=5 K=0 + RGB + PROCESS + 106 + 165 + 213 + + + C=80 M=5 Y=10 K=0 + RGB + PROCESS + 64 + 157 + 206 + + + + + + Grayscale + 1 + + + + K=100 + GRAY + PROCESS + 255 + + + K=90 + GRAY + PROCESS + 229 + + + K=80 + GRAY + PROCESS + 203 + + + K=70 + GRAY + PROCESS + 178 + + + K=60 + GRAY + PROCESS + 152 + + + K=50 + GRAY + PROCESS + 127 + + + K=40 + GRAY + PROCESS + 101 + + + K=30 + GRAY + PROCESS + 76 + + + K=20 + GRAY + PROCESS + 50 + + + K=10 + GRAY + PROCESS + 25 + + + K=5 + GRAY + PROCESS + 12 + + + + + + + + + Adobe PDF library 8.00 + + + + + + + + + + + + + + + + + + + + + + + + + +endstream endobj 3 0 obj <> endobj 6 0 obj <>/Resources<>>>/Thumb 73 0 R/TrimBox[0.0 0.0 1024.0 1024.0]/Type/Page>> endobj 69 0 obj <>stream +H���;�0E�~V1�0��}D��D) +�/и�d=�U��'0 +��o��{�>�A�6 J8ej�yFq�t����`\^����H:�y/N�-2�3�$����.Jn���[?������w�W�0��S� +endstream endobj 70 0 obj <> endobj 73 0 obj <>stream +8;Z\u;%CJt#X`h9$g'L6>)AkK(D[7@eF,=/@%3H:KFgHU+bUE$4Wg$&-UO`he$B)K +n;P!CA0n3(<<<@PCC7R1I\33+DBm/S-FXZ`7hETjVbRo(@G/#lCicm$d31;"0j+ph +Vk\5:+Ed6=J9'^GFTgJEh:u711RGYVf?6,9k9"YGCD:3QC2cOA<;\DJ[L*qEA?ZCn'o#oK26 +.Gu93'%W3"LmaauG1u(BXk!Vi=>h`^'B1Tk#65=hld>~> +endstream endobj 74 0 obj [/Indexed/DeviceRGB 255 75 0 R] endobj 75 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> +endstream endobj 72 0 obj <>/Font<>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream +BT +0 0 0 rg +/GS0 gs +/T1_0 1 Tf +0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 12 0 0 -12 -103.0967 -61.2773 Tm +[(T)7(his is an A)11.9(dobe\256 I)-10(llustr)5.1(a)4(t)5.9(or\256 F)25.9(ile tha)4(t w)4(as)]TJ +0 -1.2 TD +[(sa)8(v)10(ed without PDF C)11(on)4(t)6(en)4(t)3(.)]TJ +0 -1.2 TD +[(T)71(o P)5(lac)6(e or open this \037le in other)]TJ +0 -1.2 TD +[(applica)4(tions)10.9(, it should be r)10(e)-28(-sa)8(v)10(ed fr)10(om)]TJ +0 -1.2 TD +[(A)12(dobe I)-10.1(llustr)5(a)4(t)6(or with the ")3(C)3.1(r)9.9(ea)4(t)6(e PDF)]TJ +0 -1.2 TD +[(C)11(ompa)4(tible F)26(ile" option tur)-4(ned on. )41(T)7(his)]TJ +T* +[(option is in the I)-10(llustr)5(a)4(t)6(or Na)4(tiv)10(e F)31(or)-4(ma)4.1(t)]TJ +0 -1.2 TD +[(Options dialog bo)14(x, which appears when)]TJ +0 -1.2 TD +[(sa)8(ving an A)12(dobe I)-10(llustr)5(a)4(t)6.1(or \037le using the)]TJ +0 -1.2 TD +[(S)-3(a)8(v)10(e A)6(s c)6.1(ommand)10(.)]TJ +ET + +endstream endobj 68 0 obj <> endobj 77 0 obj <> endobj 78 0 obj <> endobj 79 0 obj <>stream +H�|TiTY��� +�S�)ZS�UqE�iTVQqDG\�qa���E�$D�(�%@���썊2H �� �(� ��.C�(\i�>=ݷ�ѧ�B��_s�9����{�w��޹8&��p���6(`�7��i��u��o7�B�"k�����"���4��2>��/��q���[_����8.�}�{g����~�Z'�����d�n���I�2gΜQ�&�QF����:��|eTH�&&Z�Щ��r��H�(�V�QiU�u��aZ�*L�Vi� +!&�ר�r�F�T�Qh"���������<,J.`��¬Q�N���Q��J�(KHt\�N��:�� ظ/F%�'W�vc.,���?�`S0l�9b��6�sñ%��j@b�1�(�9 +�b��u�~,+�Z�����Yds�f��&�E EDC���$r<��L#��8HvHN���ږ��y��ڽ�<��^��v��� v� "Mħ �I!!ݥ�"8!��$��[4X���rǨ���|m��5�P �����0~�w�׈�t7�}��>.h��ϼ�1�kNZ����g�m�nN`M'M�Nɨ�I<ցW��Kڨ ?���fi;�>����Ec�i��M��ݞ��A.��f���gŒ֛yYg9��ة��ڭW@�EZ�;Ѩ�$���܇Acg"�t9���{U��Y�Pi����L��ZU��J\G2���)���~��@�:��/~����]���e� FeJj��-0��| �^|0�����s +d +�� ��$h�10 f=���S�Z��UF����`o��[���{��En��B�?���w��x;��`�ٝ�<����sG��٬6���L�΃�\�Ұz�L�|Eۈ��jB�v���ۍ�"�뗾����t�������^#�B��!Y�t������3��Z�m�ڭ�l� +q���2�m95u\]��6 dP&���g�l.g�R�`J8b`���z�s�!��|��bK���~� ��~�w /�w[�h!�,PK�g�b���^����d�7�J-���S�� +�L2IJ1���[4� +茀��'�'<|�E���xבx��SͰ'��F�9�--?St!�+���*�V���J:$��KgA��Lw���>�n�>��\s�l�&�JM#�,`���A�$/#/3���{�� ��,��C�}P)��N�~�#�ؽ�x�!��D��o���Y�c���LV}LSWMӽ[�,<�վ�υe[6P�`��L��5� ��v˖���RZ`��� �a[�R;6EE�tJ����蜄�f��l&�ܷ\��{f$��&���;��s��C�l+�(M��"����]V�A���.: +�1"�fD8�<�^r��}�E�b�C��ؖU�5zM�q���@7 ����J}�&|��f�.�z�cD��+��wG������'B�0�F��=�h�mͪ����@��fP�s��&��� _K� �gɾ���d��n��"�D�E��i�����ڥqbi8� ��߶A*��H���p���}f�9���X&|"�䮝�ev�#���7Gg���ĝs<|���b�yr��#��=�G�|Ŧ���^;Ɏ=2E��O ���Gȋ�ߛ.�8CJ�˼���=�_ ����O�����"Y��eo�p�9Y�?|P����ܒ"���Y�v�)��w�^�8I����:K���j�Yu�� X;<�.��5���DA}�8 ]0i +%A�ǿ��*صL��������0��T�Z�)�P���o< �/�硭���0<|��9��,l����"�c,���.�+� �>����ѵ�F���~�*iPj�qz��W�S�)�/���<���������/x٫�2Wg� ���[���Ž1��8d�BO�����Ơ� v"%S�\�N4C �uc�*�����O�װ�Mau�a4� ��g&�|K��Y�L�EdĖ�����xN�{֙���]q���� ��ga�K�^�*�*����*]`犐��9� ���~��)8:��R� �_Ws����ZT�o�@g�w��[O69([��w��bb���l�w46X5��D�}<\/0�w���n�VU_�RC�?|K�*�N�p'��ht�~v4����H^�����Ǣӣף$����W3X�t�"]�z�yw�K���*��?�y��b�$�Dk���"Xc�:l�Ív����g�����N��m6�ا(I�7&&L��%����ʵ�Q��O9g +endstream endobj 76 0 obj <> endobj 71 0 obj <> endobj 80 0 obj <> endobj 81 0 obj <>stream +%!PS-Adobe-3.0 +%%Creator: Adobe Illustrator(R) 16.0 +%%AI8_CreatorVersion: 16.0.0 +%%For: (vladimir) () +%%Title: (DragonD2.ai) +%%CreationDate: 8/18/2015 3:48 PM +%%Canvassize: 16383 +%%BoundingBox: 18 76 1015 960 +%%HiResBoundingBox: 18.8701 76.6641 1014.2324 959.165 +%%DocumentProcessColors: Cyan Magenta Yellow Black +%AI5_FileFormat 12.0 +%AI12_BuildNumber: 682 +%AI3_ColorUsage: Color +%AI7_ImageSettings: 0 +%%RGBProcessColor: 0 0 0 ([Registration]) +%AI3_Cropmarks: 0 0 1024 1024 +%AI3_TemplateBox: 512.5 511.5 512.5 511.5 +%AI3_TileBox: 224 156 800 890 +%AI3_DocumentPreview: None +%AI5_ArtSize: 14400 14400 +%AI5_RulerUnits: 6 +%AI9_ColorModel: 1 +%AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 +%AI5_TargetResolution: 800 +%AI5_NumLayers: 4 +%AI9_OpenToView: -1093 1464 1 2564 1975 18 0 0 93 125 0 0 0 1 1 0 1 1 0 1 +%AI5_OpenViewLayers: 7737 +%%PageOrigin:0 0 +%AI7_GridSettings: 32 32 32 32 1 0 0.8 0.8 0.8 0.9 0.9 0.9 +%AI9_Flatten: 1 +%AI12_CMSettings: 00.MO +%%EndComments + +endstream endobj 82 0 obj <>stream +%%BoundingBox: 18 76 1015 960 +%%HiResBoundingBox: 18.8701 76.6641 1014.2324 959.165 +%AI7_Thumbnail: 128 116 8 +%%BeginData: 20636 Hex Bytes +%0000330000660000990000CC0033000033330033660033990033CC0033FF +%0066000066330066660066990066CC0066FF009900009933009966009999 +%0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 +%00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 +%3333663333993333CC3333FF3366003366333366663366993366CC3366FF +%3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 +%33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 +%6600666600996600CC6600FF6633006633336633666633996633CC6633FF +%6666006666336666666666996666CC6666FF669900669933669966669999 +%6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 +%66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF +%9933009933339933669933999933CC9933FF996600996633996666996699 +%9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 +%99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF +%CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 +%CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 +%CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF +%CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC +%FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 +%FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 +%FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 +%000011111111220000002200000022222222440000004400000044444444 +%550000005500000055555555770000007700000077777777880000008800 +%000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB +%DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF +%00FF0000FFFFFF0000FF00FFFFFF00FFFFFF +%524C45FD98FFA8FD57FFA8FD28FFAFFD55FFA8FD2AFFA8A8FD52FFA8FD2D +%FFA8FD50FFA8FD2EFFA8A8FD4EFFA8A8FD2FFFA8A8FD4CFFA8A8FD31FFA8 +%A8FD4AFFA8A8A8FD05FF7DFD2CFFA8A8FD49FFA8A8FFFFFFA8AFA8A884FF +%A9FD2AFF7EA8FD46FFAFA8A8FFFFFFA8A8A8FF7D595284A8FFA8FD1EFF7D +%A8A8FD07FF7DA8FD46FFA8FFFFFFA8FFFFAF7D84597D5284A8FFA8FD14FF +%A8FFA8A87EA87DA87D7E7E847DFD07FF7DA8FD44FFA8FFFFFF84A9A87D28 +%280527002727527DA8A8FD12FFA8A984A87D847D7D597D7DFFA8A97DA8FD +%06FF7DA8FD42FFA8FFFFFFA8A87D5227272728FD0427052752AFFD0FFFA8 +%A87D7D5252282E275252537DA884A8A8FF7D7DA8FD04FFA87DA8FD40FFA8 +%A8FFFF7DA8522705282727052727270027000528A8FD0BFFA8A97E7D282E +%27270027052700FD042752527D84FFA87DA8FD04FFA87DAFFD3FFFA8A8FF +%7D7D2828272827282728272827270527272753FD0AFFA8A87D27F805F827 +%002700270527002705270027272E52A8A87D7DFFFFFFA8A87DAFFD3DFFA8 +%A8FF7D7D27272728FD0627002705270027F87DA8A8FD07FFA8FFFFA80027 +%05FD042728272727282728272827282728277DA8A87DFFFFFFA8847DFD3D +%FF7DA87D7D282E2752272E272E272827282727272827277DFFA8FD06FFA8 +%FFFFFF7D2700270027052700270527052727270528272727282728528459 +%A8FFFFA87D7DFD3BFFA8A97E532728272827282728272827270527052700 +%27F853FFFFA8FD04FFA8FD04FF84F82727270527272705FD042728272827 +%282728272E2728527D59A8FFFF7D7DA8FD39FFA8FFFFFF7D53272E272E27 +%2E27282728FD0627052752FFFFA9FFFFFFA8FD05FF5900F8270027002700 +%270027052705FD042728272727282727277D527DFFFF7D7DA8FD38FFA87D +%A87DA8FFA852282728272827270527052700270027F859FFFFA8A8FD08FF +%7DF8FD04272827272728272827282728272E27282752272E27522859527D +%FFA87DA8FD1AFFA8FD1EFFA852522E7DA8FF7D2827522728272E27282728 +%FD042752FFFFFFA8FD08FF7D000027052700270527002727270528272727 +%28272827282728272E2752527DA85952FD15FFA8FF7DA87DA87DA8A8FFA8 +%FD19FFA853275227527DFF59272728FD062700270527F87DFD0CFF7DF827 +%0527272705FD042728272827282728272E27282752272E27522752527D7D +%A8AFFD13FFA8A87D7D7DFFA9FFA8A9A8A87DA8FD18FF532E285227527DFF +%52272728272827282727052727057DFD0CFF530000270027002700270527 +%0027272705FD0427282728272827282728272E52FFFFFFA8FD11FFA8A852 +%7DA8FFA8A9A8A9A8AFA8A8597D7DFD15FFA87D2728272E27287DA8FD0627 +%002705270027F87DFD0CFF7D002705FD042728272727282728272E272827 +%2E272E2752272E527D7D7D527DA8FFA9FD12FFA87D7EAFFFA8FFA8AFA8FF +%A8FFA9FFA87D59FD14FFAF592E285228522752A87D272E27282728272727 +%2827277DFD0CFF53050027002705270027052705FD042728272727282728 +%27527D7E7D7D5359527D7DA87EFD10FFA97D52A8AFA8A8537D525227527D +%A8A8FFA8A852A8FD12FFA87D272827522728277DA82E0528272705270527 +%0027F87EFD0CFF7DF8272727052727270528272727282728272827282728 +%277D7E7E597D52522852287D7DFD10FFA884A87DFF7E7D7DFD05A87D7D52 +%7D7EFFAFA97DA8FD11FFA8532E28522752282E27A87D2727282727052727 +%270027A8FD0CFF530000270027002700270027052705FD0427282727277D +%7D7D52522728272E2728527DA8FD0EFFA87DA87DA87D7DA8FD08FFA85952 +%7DA9A8A859A8FD10FFA87D272E27282728272728A8272700270527002700 +%27F8A8FD0CFF7EF8FD04272827272728272827282728272E272827A8847D +%5252275227522852277D59FD0FFF7DFF7DA8A87DA8FD0BFFA87D7DFFA9FF +%7DA9FD0FFFA8532E28522752282E27287D7D00282727272827270528A9FD +%0CFF7D0500270527002705270027272705FD042728277D7D7D5227272E27 +%2827522728527DA8FD0DFFA8A8FF7D7DA87DFD0DFFA87D7DA9A8A87DFD0F +%FFA859272E27282728272827527D27002705270027002727FD0DFFA80027 +%0527272705FD042728272727282728057DA87D2E28272E27522852275227 +%7D7DFD0EFFA8A8FF7D7D7DFD0FFFA87D84FFA8A87DFD0DFFA8A853282752 +%2728272E272827A852270527272705270052FD0DFF7D2700270027002700 +%2705270027052705270052847D282727282728272827282728527EA8FD0D +%FF84FF7DA8597DFD10FF7D7DA8A9A87DA8FD0DFF7D532728272827272728 +%2727527D002700270027F80552FD0EFF272705FD04272827272728272827 +%282752A8A852272752272E27522852275227537DFD0EFFAFFFAF7DFFA8FD +%11FF7DA8A8FFA8A8FD0CFFA8A852282752272E272E272827527D2E052727 +%270527F87DFD0DFFA827002700270527002705270027272705277DA852FD +%042728272827282728272828A884FD0DFFA8FFA87D7DFFA8A9FD0FFFA87D +%A8A8A97DFD0CFFAF7D5227282728272727282727007D5205002700270005 +%7DFD0EFFFD04270527272705FD042728272752FF592727282728272E2728 +%2752272E27527DA8FD0EFFA8A87D7DA8FFA8AFFD0EFFA87EA8FFA8A8A8FD +%0BFFA8A827282728272E272827282727527D05270527052700A8FD0EFF2E +%F82700270027002700270527002705A87D28002705FD0427282728272827 +%28277DA8FD0DFF84A87D7D5284A8FFA8A8FD0EFF7DA8A8A97DA8FD0BFFA8 +%7D280528FD0627052705277D270027F827F827A8FD0EFF5227272705FD04 +%272827272728057DA8520528272E2728272E272E272E282E272853AFAFFD +%0CFFA87D7D527D7DA8FFFFA8A9FD0DFFA884FFA9FF84FD0BFFAF7E272E27 +%28272E272827282728277D52270527052727FD0FFF7DF827002700270527 +%00270527004B7676204B214B204B214B214B274B214B274B214C76FD0DA1 +%7D847D7D52A87DA8FFFFA8FD0DA1767677A17676FD0CA14C27214B214B27 +%280527052727272E7DF8270027F853FD0FFF7D0500272727052727270527 +%44FD04688C688C688C688C688C688C688C688C688CFD0F68A87D7E7DA87D +%A87DFFFFFF76FD1E688C688C688C6868444B27282728272E532705270027 +%7DFD0FFFA8F827F827002700270527448C68936893686F6893686F689368 +%6F6893686F6893686F6893686F6893686F6893686F68937D7D597D7D847D +%6F7DFFA8AF6F686893686868936868689368686893686868936868689368 +%6868936868689368686893688C684B05270027057D05270005F8A8FD0FFF +%A827002727270527054B68936F93688C688C688C688C688C688C688C688C +%688C688C688C688C688C688C688C688C688C6F847D847DA884A86FA1A8FF +%FF9B688C688C688C688C688C688C688C688C688C688C688C688C688C688C +%688C688C688C688C6893686F2728272E7D5200270028FD11FF2705002700 +%270027688CFD056893686F6893689368936F9368936F936F936F936F936F +%936F936F936F936F936F76597D597D7DA87EA14BA8A8FFA1936F936F936F +%936F936F936F936F936F936F936F936F936F936F936F936F936F936F9368 +%6868936844052752AF280500002EFD11FF52002700270527449368686893 +%6F936F936F936F936F936F9A939A6F9A939A6F9A999A6FFD0B9A76FD047D +%A884A8A8A8527D84A1FD249A68686893684B0084FF53F827F87DFD11FF52 +%000027F82720FD066893689368936F936F936F936F936F936F9A6F936F9A +%6F9A6F9A6F9A6F9A6F9A6F9A6F9A767D597D7EA87DA8A8A8527D769A6F9A +%6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A +%6F9A769A6868688C4427A8FF5227F805A8FD11FFA800270527056F689368 +%936F936F936F936F936F9A93936F9A939A6F9A939A939A999A93FD0D9A76 +%7D59CAC3CA7DA9A8FFFFCA93FD259A688C68684CFFFF84002727FD12FFA8 +%270027002768936868689368936F936F936F936F936F936F9A6F936F9A6F +%9A6F9A6F9A6F9A6F9A6F9A769A6F9A769A6F9A7659A1C39A9A84A8A8FFA8 +%A16F9A6F9A769A6F9A769A6F9A769A6F9A769A6F9A769A6F9A769A6F9A6F +%9A6F9A769A6F9A9A6F6893687684FF8427F853FD13FF2727052721936868 +%68936F936F936F936F936F936F936F936F9A939A6F9A939A6F9A939A6F9A +%9A9A99FD099A769A9AA193A1A8A9A8FFA8A1FD1A9AA1C9A19A6FFD059A6F +%68688C6FA8A8A827F87DFD13FF52F82700276893686868936F9368936F93 +%6F936F936F9A6F9A6F9A6F9A6F9A6F9A6F9A769A6F9A769A6F9A6F9A6F9A +%6F9A6FA16F76769A76FD04A8AF769A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F +%9A6F9A6F9A6F9A6FA1A8FFA8FFA8A16F9A6F9A6F936868686F84A8A82EF8 +%FD14FF7D2705272193686868936F936F939AFFA8FFA8FFA8FFA8FFA8FFA8 +%FFA8FFCAFFA8FFCAFFA8FFCAFFA8CFA8CAA1CAA1A19A9A76524BA19A9A52 +%A9A8A89BFD179A93C3FFFFCFFD04FFC3FD049A938C68936FA8A8FF2852FD +%14FFA8F82700276893686868936F936FFFAFFFA8FFAFFFA8FFAEFFA8FFAE +%FFA8FFAEFFA8FFAEFFA8FFAEFFA8FFAFFFA8FFA8FFA87E2727529A6F7676 +%A19A9A6F9A769A6F9A769A6F9A769A6F9A769A6F9A769A6F9A6F9AA8FFA8 +%FFA8FFA8FFA89A759A769A6868686FA8A8A8527DFD15FF27F827218C688C +%68936F936F99A8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFF +%A8FFFFFFA8FFFFFFA8FFFFFF7D7D2752A1A19A9A93FD0F9A99FD0A9AFFA8 +%FFFFFFA8FFFFFFFD049A6F8C688C6FA8A8A859FD16FF2E00F827686F6868 +%6F936F936FCFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FF +%A8FFA8FFA8FFA8FFA8FFA8A87DA8A8FFA8CA9A9A6F9A6F9A6F9A6F9A6F9A +%6F9A6F9A769A6F9A6F9A6F9A6F9A6F9AA8FFA8FFA8FFA8FFA89A6F9A7693 +%6868686F7DFD04A8FD15FF7DF8272193688C68936F936F9AA8FFFFFFCFFF +%FFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFD07FF +%CFFFFFFFA8A1FD069A939A9AC3A1CAA8CFA8CAA1A1FD079ACAFD04FFCFFF +%FFCAFD049A6F8C688C6FFD04A8FD16FFA805F827689368926F936F936FFF +%A8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FF +%A8FFA8FFA8FFA8FFA8FFA8FFA8FFA8CA9A9A6F9A6FA1A1FFAFFFA8FFAEFF +%A8FFAFFFA19A6F9A6F9A9AFFAEFFA8FFAEFF9A9A6F9A9A936868686F84A8 +%A8FD18FF27052093686868936F936F9ACAFFA8FFFFFFA8FFFFFFA8FFFFFF +%A8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FD +%05FF9A9A9ACAFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8CAFD059ACAA8FFFFCA +%FD069A9368688C6FA8A8A8FD18FF59F827689368686F936F936FFFA8FFA8 +%FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8 +%FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA1CAA8FFA8FFA8FFA8FFA8FFA8FFA8 +%FFA8FFA8CA769A6F9A6F9A9A9A6F9A6F9A6F9A6F936868686F84A87DFD18 +%FF7D0520936868689A93936F9ACAFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFF +%FFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCF +%FD07FFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFFD0E9A938C68936FA8A8A8 +%FD19FF0521689368686F936F936FFFA8FFA8FFA8FFA8FFA8FFA8FFAFFFA8 +%FFAFFFA8FFAFFFA8FFAFFFAFFFAFFFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8 +%FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFAFCA6F9A769A6F +%9A769A6F9A769A769A6868686FA8A884FD19FF52208C688C68936F9A6F9A +%A8FFFFFFA8FFFFFFA8FFFFFFA8FD04A1C3A1A1A1C3A1A1A1C3A1A1A1CAA8 +%FFAEFFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8 +%FFFFFFA8FFFFFFA8FFFFCA6FFD0B9A6F8C688C6FA8A8A8FD19FF7D20686F +%68686F936F936FCFA8FFA8FFA8FFA8FFA8FFAFA16F9A6F9A6F9A6F9A6F9A +%6F9A6F9A6F9A6F9A76A1A1CAA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FF +%A8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA89A6F9A6F9A6F9A6F9A6F9A +%76936868686F7DA8A8FD1AFF278C688C689A6F9A939AA8FFFFFFCFFFFFFF +%CFFFFFFFA1FD139A939A9AA1A8FFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFF +%FFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFA1FD0B9A6F8C688C6FA8A8A8 +%FD1AFF76689368936F936F936FFFA8FFA8FFA8FFA8FFA8FFAFA86F9A769A +%6F9A769A6F9A769A6F9A769A6F9A769A6F9A6F9A9ACAAFFFA8FFA8FFA8FF +%A8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8CF769A769A +%6F9A769A6F9A9A936868686F84A8A8FD1AFF7DFD04689A939A6F9ACAFFA8 +%FFFFFFA8FFFFFFA8FFA1FD199A6FC3FFFFA8FFFFFFA8FFFFFFA8FFFFFFA8 +%FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFA16FFD099A9368688C6FA8A8 +%A8FD1AFFA1689368686F936F936FFFA8FFA8FFA8FFA8FFA8FFA8A86F9A6F +%9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6FA1A8FFA8FFA8 +%FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA19A6F +%9A6F9A6F9A6F9A6F936868686F84A87DFD1AFFA18C6868689A939A6F9ACA +%FFCFFFFFFFCFFFFFFFCFFFA7FD1B9A93A1A8FFFFFFCFFFFFFFCFFFFFFFCF +%FFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFCA93FD099A938C68936FA8A8 +%A8FD1AFFA1689368686F9A6F936FFFA8FFA8FFA8FFA8FFA8FFAECA6F9A6F +%9A769A6F9A769A6F9A769A6F9A769A6F9A769A6F9A769A6F9A6FA1A8FFA8 +%FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA19A6F +%9A769A6F9A769A769A6868686FA8A884FD1AFFA168688C689A6F9A939AA8 +%FFFFFFA8FFFFFFA8FFFFFFA1FD1D9A93A1FD04FFA8FFFFFFA8FFFFFFA8FF +%FFFFA8FFFFFFA8FFFFFFA8FD04FFCA93FD099A6F8C688C6FA8A8A8FD1AFF +%A86868686F6F936F9A6FFFA8FFA8FFA8FFA8FFA8FFAFA86F9A6F9A6F9A6F +%9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6FCAA8FFA8FFA8 +%FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA19A6F9A6F9A6F +%9A6F9A76936868686F7DA8A8FD1AFFA168688C689A6F9A939AA8FFFFFFCF +%FFFFFFCFFFFFFFA1FD1F9AA1FFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFF +%FFCFFFFFFFCFFD04FFA1FD0A9A6F8C688C6FA8A8A8FD1AFFA8686F68936F +%9A6F9A6FFFA8FFA8FFA8FFA8FFA8FFAFA86F9A769A6F9A769A6F9A769A6F +%9A769A6F9A769A6F9A769A6F9A769A6F9A6F9AA8FFA8FFA8FFA8FFA8FFA8 +%FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFAECA6F9A769A6F9A769A6F9A9A9368 +%68686F84A8A8FD1AFFA1FD04689A939A6F9ACAFFA8FFFFFFA8FFFFFFA8FF +%A1FD1F9A99CAFD04FFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8 +%FFA1FD0B9A9368688C6FA8A8A8FD1AFFA1689368686F9A6F9A6FFFA8FFA8 +%FFA8FFA8FFA8FFA8A86F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F +%9A6F9A6F9A6F9A6F9A6F9AA1FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8 +%FFA8FFA8FFA8FFA89A6F9A6F9A6F9A6F9A6F9A6F936868686F84A87DFD1A +%FFA18C6868689A939A939ACAFFCFFFFFFFCFFFFFFFCFFFA7FD209AA1FD04 +%FFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFD04FFC3FD0C9A938C68936F +%A8A8A8FD1AFFA16893686F9AA19A9A9AFFA8FFA8FFA8FFA8FFA8FFAECA6F +%9A6F9A6F9A6F9A769A6F9A769A6F9A769A6F9A769A6F9A769A6F9A769A6F +%9A9AFFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFAFA86F9A76 +%9A6F9A769A6F9A769A769A6868686FA8A884FD1AFFA16868686FFD05A1A8 +%FFFFFFA8FFFFFFA8FFFFFFA8A19AA19AA1FD069A99FD139A6FA1FFFFA8FF +%FFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FD04FFCAFD0E9A6F8C688C6FA8A8A8 +%FD1AFFA8686868939AA19AA1A1FFA8FFA8FFA8FFA8FFA8FFA8CA9AFD07A1 +%9AA19A9A769A769A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A76FFA8FFA8FF +%A8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFAEA16F9A6F9A6F9A6F9A6F9A6F9A +%6F9A76936868686F7DA8A8FD1AFFA168688C6FA1A1C3A1A1A8FFFFFFCFFF +%FFFFCFFFFFFFA8C3A1A1A1C3A1C3A1C3A1C3A1C3A1A1A1C39AA1FD0C9A99 +%A1FFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFD05FFCAA193FD0F9A6F8C688C6F +%A8A8A8FD1AFFA8686F68939AA19AA1A1FFA8FFA8FFA8FFA8FFA8FFAECA9A +%FD15A19AA1FD049A6F9A6F9A9AFFA8FFA8FFA8FFA8FFA8FFA8FFAFFFAEFF +%A8CAA19A6F9A6F9A769A6F9A769A6F9A769A6F9A9A936868686F84A8A8FD +%1AFFA16868686FA1A1A19AC3CAFFA8FFFFFFA8FFFFFFA8FFA8A1A1C3A1A1 +%A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A19AA19ACAFD04 +%FFA8FFFFFFA8FFFFFFA8CAA1CAA1A1FD149A9368688C6FA8A8A8FD1AFFA1 +%6893686F9AA19AA19AFFA8FFA8FFA8FFA8FFA8FFA8CAA0A19AA1A1A19AA1 +%A1A19AA1A1A19AA1A1A19AA1A1A19AA1A1A1A0FD05A1A8FFA8FFA8FFA8FF +%A8FFA8FFAFA16F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A +%6F936868686F84A87DFD1AFFA18C68686FC3A1A1A1C3CFFFCFFFFFFFCFFF +%FFFFCFFFA8A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1 +%A1C3A1A1A1C3A1FFCFFFFFFFCFFFFFFFCFFFFFFFFD1A9A938C688C6FA8A8 +%A8FD1AFFA1689368939AA19AA19AFFA8FFA8FFA8FFA8FFA8FFA8CAFD1EA1 +%9ACAAEFFA8FFA8FFA8FFA8FFA8FFA89A6F9A6F9A6F9A769A6F9A769A6F9A +%769A6F9A769A6F9A769A769A6868686FA8A884FD1AFFA168688C6FA19AA1 +%A1A1A8FFFFFFA8FFFFFFA8FFFFFFA8FD04A1C3A1A1A1C3A1A1A1C3A1A1A1 +%C3A1A1A1C3A1A1A1C3A1A1A1C3A1CAA8FFFFFFA8FFFFFFA8FFFFFFAFCAA1 +%A19AA19A9A6FFD139A6F8C688C6FA8A8A8FD1AFFA8686868939AA19AA19A +%FFA8FFA8FFA8FFA8FFA8FFA8A89AA1A1A19AA1A1A19AA1A1A19AA1A1A19A +%A1A1A19AA1A1A19AA1A1A19AA1A8FFA8FFA8FFA8FFA8FFA8FFA8FFFD06A1 +%9AA0769A6F9A6F9A6F9A6F9A6F9A6F9A6F9A6F9A76936868686F7DA8A8FD +%1AFFA168688C6FA1A1C3A1A1A8FFFFFFCFFFFFFFCFFFFFFFA8C3A1A1A1C3 +%A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A8FFCFFFFFFF +%CFFFFFFFCFFFFFFFA8C3A1A1A1C3A1C3A1C3A1A19AA0FD0E9A6F8C688C6F +%A8A8A8FD1AFFA8686868939AA19AA1A1FFA8FFA8FFA8FFA8FFA8FFAECA9A +%FD1BA1A8FFA8FFA8FFA8FFA8FFA8FFA8FFAEA89AFD0DA19A9A6F9A6F9A6F +%9A769A6F9A9A936868686F84A8A8FD1AFFA16868686FA1A1A19AA1CAFFA8 +%FFFFFFA8FFFFFFA8FFA8A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1 +%A1A1C3A1A1A1C3A8FFA8FFFFFFA8FFFFFFA8FFFFFFAFFFA1A1A1C3A1A1A1 +%C3A1A1A1C3A1A1A1C3A1A19AA19A9A93FD059A9368688C6FA8A8A8FD1AFF +%A16893686F9AA19AA19AFFA8FFA8FFA8FFA8FFA8FFA8CAA0A19AA1A1A19A +%A1A1A19AA1A1A19AA1A1A19AA1A1A19AA19AA1A8FFA8FFA8FFA8FFA8FFA8 +%FFA8FFA8FFFD04A19AA1A1A19AA1A1A19AA1A1A19AFD05A19A9A6F9A6F9A +%6F936868686F84A87DFD1AFFA18C68686FC3A1A19AC3CFFFCFFFFFFFCFFF +%FFFFCFFFA8A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1CA +%CFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFA8C3A1A1A1C3A1A1A1C3A1A1A1C3 +%A1A1A1C3A1A1A1C3A1C3A1C39AA09A9A938C688C6FA8A8A8FD1AFFA16893 +%68939AA19AA19AFFA8FFA8FFA8FFA8FFA8FFA8CAFD12A19AA1A1A1A7FFAE +%FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FD1DA19A9A6868686FA8A884FD1A +%FFA168688C6FA19AA19AA1A8FFFFFFA8FFFFFFA8FFFFFFA8FD0CA1C3A1A1 +%A1C3A1CAA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8C3A1A1A1C3 +%A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A19A8C688C +%6FA8A8A8FD1AFFA8686868939AA19AA19AFFA8FFA8FFA8FFA8FFA8FFA8CF +%A1CAA8A8A1CAA8A8A1CAA7CAA8CAA8CAA8FFA8FFA8FFA8FFA8FFA8FFA8FF +%A8FFA8FFA8FFA8FFA8A19AA1A1A19AA1A1A19AA1A1A19AA1A1A19AA1A1A1 +%9AA1A1A19AA1A1A19AA1A19A6868686F7DA8A8FD1AFFA168688C6FA19AA1 +%9AA1A8FFFFFFCFFFFFFFCFFD17FFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFF +%CFFFCAC9A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3 +%A1A1A1C3A1C39A8C688C6FA8A8A8FD1AFFA8686868939AA19AA19AFFA8FF +%A8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FF +%A8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FD22A19A6868686F84A8A8FD1A +%FFA1FD0468A19AA19AA1CAFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FF +%FFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFA8A1 +%A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3 +%A1A1A1C99A68688C6FA8A8A8FD1AFFA16893686F9AA19AA09AFFA8FFA8FF +%A8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FF +%A8FFA8FFA8FFA8FFA8FFA8FFFD04A19AA1A1A19AA1A1A19AA1A1A19AA1A1 +%A19AA1A1A19AA1A1A19AA1A1A19AFD04A19A6868686F84A87DFD1AFFA18C +%68686FA19AA19AC3CFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFF +%CFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFCAA1C3A1A1A1C3 +%A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1 +%A1CA9A8C688C6FA8A8A8FD1AFFA1689368939AA19AA09AFFA8FFA8FFA8FF +%A8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FF +%A8FFA8FFAEFFA8CAFD27A19A6868686FA8A884FD1AFFA168688C6FA19AA1 +%9AA1A8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFF +%A8FFFFFFA8FFFFFFA8FFFFFFA8CFA1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3 +%A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A19A8C688C +%6FA8A8A8FD1AFFA8686868939A9A76A19AFFA8FFA8FFA8FFA8FFA8FFA8FF +%A8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8CAA1A19AA1 +%A1A19AA1A1A19AA1A1A19AA1A1A19AA1A1A19AA1A1A19AA1A1A19AA1A1A1 +%9AA1A1A19AA1A1A19AA1A19A6868686F7DA8A8FD1AFFA168688C6FA19AA1 +%9AA1A8FD21FFCACAA1CAA1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3 +%A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1C39A8C688C +%6FA8A8A8FD1AFFA8686868939A9A9AA19AA1A8CAA8CAA8CAA8CAA8CAA8CA +%A8CAA8CAA8CAA8CAA8CAA8CAA8CAA8CAA8CAA1A7FD04A19AFD2EA19A6868 +%686F84A8A8FD1AFFA1FD0468A19AA19AA19AA19AA19AA19AA19AA19AA19A +%A19AA1A1A19AFD10A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3 +%A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1CA9A68 +%688C6FA8A8A8FD1AFFA86893686876A19A9A76A19AA09AA19AA19AA19AA1 +%9AA19AA19AA19AA19AA1A1A19AA1A1A19AA1A1A19AA1A1A19AA1A1A19AA1 +%A1A19AA1A1A19AA1A1A19AA1A1A19AA1A1A19AA1A1A19AA1A1A19AA1A1A1 +%9AA1A1A19AA1A1A19AFD04A19A6868686F84A87DFD1BFF93688C689AA0A1 +%9AA19AA19AA19AA19AA1A1A19AC3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3 +%A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1 +%A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C36868688C +%76AFA8A8FD1BFF6FFD0468A19A9A9AA19AA19AA19AA19AA19AA19AA19AA1 +%9AA19AA19AA1A1A1A0FD3BA16FFD0468A1A8A884FD1BFFCA689368686FA1 +%9AA19AA19AA19AA19AA19AA1A1A19AA1A1A1A0FD08A1C3A1A1A1C3A1A1A1 +%C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1 +%A1A1C3A1A1A1C3A1A1A1C3A1A1A1C3A1A1A1CA9A686893686FFD04A8FD1C +%FF6F68936868689A9AA19AA19AA19AA19AA19AA19AA19AA1A0A19AFD3FA1 +%6FFD05687DA87DA8A8FD1CFFA8936893688C68936F936F936F936F936F93 +%6F936F9A6F936F9A6F936F9A93936F9A93936F9A93936F9A93936F9A9393 +%6F9A93936F9A93936F9A93936F9A93936F9A93936F9A93936F9A93936F9A +%93936F9A93936F9A9393688C688C688C76AFA8A8A8FD1EFFA168686FFD55 +%688C68686FA8A8A87DA8AFFD1EFFA893688C689368936893689368936893 +%689368936893689368936893689368936893689368936893689368936893 +%6893689368936893688C6893688C6893688C6893688C6893688C6893688C +%6893688C6893688C6893688C686876FD06A8FD20FFA8A1FD5568767DA8A8 +%A87DA8A8FD23FFA87DA17DA17DA17DA17DA17DA17DA17DA17DA17DA17DA1 +%7DA17DA17DA17DA17DA17DA17DA17DA17DA17DA17DA17DA17DA17DA17DA1 +%7DA17DA17DA17DA17DA17DA17DA17DA17DA17DA17DA17DA17DA17DA17DA1 +%7DA8A8AFFD05A8FD24FFAFA884FD53A87EFD04A8FD28FFFD57A8FD2AFFA8 +%FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8 +%FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8 +%FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FD10FFFF +%%EndData + +endstream endobj 83 0 obj <>stream +%AI12_CompressedDatax��Y�$�q.�^@��������Dh8E��4D�]�ꪺ�Q�-]ͯ3;���##+��FzwV�g���͎-�}�W��o��勏�����c����_�����o>~����������Ox����zx��]˯�?�;������}��7����3~������/�}���/��x��y������ㇽy|����p���7������h��h���~�kz˛������o�kکŋ��o?|��ß׏��N��P�����z���_'�y�ƪ�7>CW㻻Ǧm�����Ǐ����o?|��O���믷��?~��o��~����o� y����}���=�����?�3˯�?�߽ ����7uC����n��~��������zd��������_���������՗p��o������[���U:��_~����hh����/�Ο>~��O��ux_]A����o���=�3�GO���~�ky+�����-��a���i����Oo�����������-w���߇��:���?����o?��w��tm���_�}��[�߿������~�;���ӟ�~c��������[������Ł��K~�����O���������aM���c�s�����������F��؎8R����ͧw~��o�1�?�ݧw_؈���G�y������� =��7o?H��|�~�fG�������>|�}��kZ0/>��y����W;���-����B�c��O�>��_����鏿}�-���>}���_}����_�u� �X��>����S����_X�_����o� V�� \=}�Ϸ�?~�n�W�|����y��kn���o>���@�{������������U�����퟾��{������k���?�����7����nA������ ��M,?���o�|�7��;�����Z8�&�.^���/����w_�7�W��U}���Ӈ�|���ۯ���?��� o�?ټ��M���K�ͥ/�?�po��y��ݟ?�������t�����>{�,��z��?���!}�L���`iH��������O��_?�����k����}���߾�歍��/�B�������+���<�w�}�?�᷀_�����{X?�=��>�6[ (p���Û/A:��/=�p��U������ׯ��������*��:R�UW�p �XM�\-p��V�� ���n���걞�^���>��j�A�����o�fl�fn�fm�foN͹�ڦm۾EMqn�vk��Ԟ�����k�v�����[��ۺSw���{P��������������?�����a�a�a�aN�y��zl@��~-�o}KC[Á-����������^�48o�m߶mݖmަm����ڭ�a���zZ�u[�uY�uZ�uX��[۵Y�Zί_-�e_�e]�e^�e\��_���IQ/�|�O�>o�:/�?N����&���6���}y��ҟ�� ��_�L�4M#��M�;��8U�y<�����8ß�q���6�F� � +� +�0���t� �C���^Ay�@��aiA�h`۬h �h��A�a2u� �vT�<���V���Xli�}�`Um��-��M�� ��এ�b�� �d�ms�Mt�ʹ�> �l.n�+)��%�A�ׂدe�QA�Ezz�~����{:Y~p�+�}��00�_�8�����<�������2L=������W4>������T4Va�ˆ�5�fHF�����=_�h|Az�#��G���1�BO��S# cm# 23�F�`��h���Ԉ?5懣��ᣱ��c��c�0�Gk�h��V�J{FiE����U �L<�G+����&3|$����V������`���|��F]~�vi�PQ���� +�YZ�'-<���ZYc+���Ȫ\[e�o��6��Q�[>�=)�3[�8�=������ ��z�IIK�a�����u�e�Ө˸����w4�=[83�U�U��̼��Վ�Ӟt�۬:�_��������-={x�޽t�Nl3�V,��K�V�ɛ�E�[S���b�8ҧ��e;j<��b���%��Y�{vxzX�G��_� ϯOX�]�{��������'-�@]ޣ���$'�7A�x\�4��t��>ޑ���z5����š���w��y��e����ß��O��@�,���1P7>/T�6��Bu����x� ��߮��'�<�d�Q`�9 b���q��>N�ʦ =}��d5��#�-��Q�C��eǽ^���=���+�ȧÐ>*�ߤo9����kyk�B������x���]��:���g9nE2��B��� d�Da̱���˜h�� ��U?MM/�z�M_����o���k���7<+( #���Τ@������ps�A�!X�����^$Q١��n�������� ��J�|�D=p�����k0���>;�9\F5����;T�1!n� ;�\��[p���Ѓcb3�Į��K2W/M*�T:u��*��s_��]���v&�b=�S�z��Y�/�1m�o���?mi���6O6#��C;� |P��T��(���,�Q�)�G �+q��O�N ��b�5L^�R{�Z> ���]���5� poa� ���Њ��R��u7��7|��4c�)/��eP n��5J��~{��)΋�R���-)�P � &N�t���� +�~��۽�{��W<�WmI�x�X$��B�a&^��eqI0�8,��c4X��ڴ� �QG8 A;����^b�m Y�X����}�2H���8菧��g�d��/ELT��(�b{��Ê��WƊ���􌟿���P���� l�GW�W�&�jQ��&^� +�T��Z}M���l7��ک�O�F�Í<�����.���5��];�����*J�FZ� +���}-���y��x��=�,^� 9Rk��Ġ�4ω�#L>�Ql$Ķ�Ȩ3o�B�Z0�Ġ�����"0>�%}Tqm.a���L!�(O�J�Z%��:���^��@{@c{b���XXg�i�\~�U�M[��ѳ\�%�M_����lw��;[D�sg���E�,�"@E� �� �,T�G�C�p ������kgY�Q��Vw�]�r�'��n���~���A��} �m=�2d�V��<��M6�xk���hKq� ��G�\<����2b2&��M���o��cK5��g�V�,Μ��ie�e�j�U0��k�\+�m��V��3C�,, V��@�`l`��HHΉ���;�g�cw��$ ��6(nCAY�Y%o�꼵�1`�����%`N쫝��R�nj���&��mI�������<5�G�����x6��?����9��92�dnn>P�geJ.���x�N�K9�Y+?kvl�cO�#�����F�'����%�h"��8X�QAᇹ�$R+1�.��c�9�P~j.y���7Y��Cf̥�A��c$c5�Q'7��Ѹ�f�u�Q�s1W�S��{<�*7�dn�LS84��ctL�1�#� �3�Y����?��K���EN:9 k�Pqv�e���9�,+����4��NPϰo��W���=z��<3�'=��a{ܳe�'b�O01�v�����Ȭ���atw� q�hA8�0 ���z"�D�2��g#߷��[����9��)J�H���W!R��x��g}��l�\ E�����1J�\��n%�` x�n�,�8FUŸ�v�U[U7�� Ye���w(�V �jR���M)��>��s�>��s�9�"7�؃R@ j�A��6b..Ve��c�Ł��3>|�4�Ǿ���<'����O��I� �*=�2�V6�`/@�h�s41F��s�Iy 8�&��~:)��.g@i��>/Is�4�(�;���F�X����"@wb:G��T* ���{��?yV.͕�*��\�2W�֤�>& +��'�mI qPk����@O`4���9�::�pQʞULB��SP���o�� � ��S�[r@!�b�(+$-���TL ZJ|pwQ��1,� ���Qj5 +���M�b��tB���SՒ�Z�sې`S̄��9)�i?}�8�w�:�Hn�O��UKI��0vt'�=5}Iۅ,���?�rNr�nu�o}y��S��g:1�pGo�XĎA=��2i��B� ��7��ƞٝ2g�k`\9�zj{ =O��n�f�����'7x���1�N����_h��1�1]����++���6��� c�\���N���<#�� +<��o���ΐ��R��1�q ���?��7�D�4�����9��)�؉���!O��~9'!@�"����k�<��7;�֦����G)Bt�"y�"�Q��S�T�^�t��5$+ǯ ^=pG[9�~v�v���x�p4�V�Jz�n �N��l%����rWQ����#�Dki�mn啴��$����_Mq� ��&�������3x��*���.�5���uF(YO=��Қ�,���8xɤ8�2�|N�u ��1���<�i�VY��6����� +��I���/nіN9ˌ�lv����}��1�E�Ȼ����|��W����U�AKZ#�Jx}v�Bt��U2�5k��� +��vM�ی�D�dv;�F���+����ѭ�uN��*+��r����,���������Q#فʫ�CQ�NT�*9�!�(R!.���FJ논0)ߓHR��H>jn�%������Q�B)�Q�d�>�;��!�N�W9friv���$P7��H�� :桢!b���(D2��):���bd3aYδ�[Ʊ�d(#A󃻤#�w%��B<�w��Ǧ�,��Z%�9��ƥ�Sv�ѱ�c��?���\frL|�|PY�s�G�G�`����u�>C���W�'����j��?{&�6z�G���ɿ��«q�_��f���M�iqY�'0D����"���� L|�*��3�w<���8�NŪ?c��C�C��� �sa��M�^t�8��>���)^���x�s�:{� Gev��;n6�e������ 5GRF��P;r�%.<ؓ�Y&�dI��VIy���į��Vɚ��IWɠ���U"kį�Fl�\�Fd�l�J.���k�e�}���Yq"$��+���D�$�#M����?���D��@.�������D� ���B��#~_%�Ur_%W��at���:��[����r�*����O�J|2KT�n�j�ɸZ���쪊5����ի�Zu���E_�Zu�h�����i �V0C�C��皃F�Z�h2�A�l�9��� �1�q��F=���ȓF?��M�#��́y ��j!�W��8:�;��U��I��W����x�pZ5���V��*w����y6s峉9���\5�sZ�TQ�Y#hPR�G0hO1�m*1<�x@_�h�������.�������Q+3>��� ]uw\}�\3���u%: imOj���1��"):�(�/ѣ��C��&�7V�Q�)�f����S��!�|\�����~9��j�Z�fV�[����.~•�搁!9��!Cj +k�Hz����_ +��N<�'�X��& �K<s��[��%�%����|>�k���Gg��֐=�� 9c���J��J��Z�0�/S�ן,WE�0{6�S�W�<��T��s�ԦL�1�b���xN������g;�PoӁR����0I �:��xt�������d/��nuˣ܇axl�}��jl���{��؎�-L���6���b�P��i�i�¶tDw� � /���\{=C.�������{I1���� 0���0A~. ���/"�~���y�SWVL2�~�@�z��C� ���E�0�c1ǎ��h�;2�` �1rim��D��Q����Q�x+�����c0�(q�Z>&��U���V��P)d,��q��Pd��A+��B�DE�}��?��yfO�py��0C����d��H+�wⰣ��ۥ�-�XѨ�5��:�( ,���1ܱ:���%��adG9�G��'m�/g��Jb�����D����15.]�*9�[�Q�'������N!L=��I +�XE��]���AA�:t���3�f���q��ɥRA����^[�P��b���`����l�����������5����X ��{��0iH�-G��J\�‡�V�y+ ���%~�*}�; �T�DO�Q�Ԥ|0o�-׀} =T�S��y����2��"&��і���AÝ{M�H㮌d؅0-}�shk��%�ĤGn�2@���K�{�@��lN47i�{ \B3-�g�v��,xv :���9UD��� �t����| R��q�@�"Vq����oR�t�ׯ��~f�?ʈ~V�r�23CqC�-�H��!�.���6��1��E���*'f8� I��06WR�_ɔH�i�#�� +��f8��S?��� �S�+?<�}���_x#||@L����E�����R�,��u����‹n�rs��<~���)���UE!/]�R%ht�P� &�7�jIdA��;�*�0H2|g��^��e[K�U{�"�GǀfEj��c{l�<���P.q>W�k#�6�o3�'�5A��-릡 +�>ߦw�|��r;�l�|M��ZIh�.����! pԊ7��+��/�JU�J9hsP�V�Tsf�D8��_B,PC?�\ 9�k�m�3ʴ��<8�Ϫ����MK̦�2��f���'|Ni��9���{ҧ��:�gmS�(��α֦������J˯ׯ�(ˑ�����*���vG���E����RQ�G1�ո��{��,�� �}��X�n�<�2v�ƌ��L�#�+Y������a��R��_�ٔ�_�� -�RϬ�f�H��j�؇�8��DO +{��,�r=7��8k��h̔��Iud�h�/�b3b�Ӛ��VB}ҕ�2w�J��(��� 9�in#�qp���s���ps�'E!x� \Y�Ց���P��C�F����|¥f�}\.�`��R��>�k�K�M���>���Xre� +=[��Ϫ'��.֐��6�����)MQ��ڻ� \GH��1��=S�*�Ӆ2� 9�!�~+��0Ԩ��R��~�4�k��z���f�T���o��;,e�鉷j���n�o� {|�Vs�a�b��n�=��V�xy�mPi �>!1�)&�;2ɔ��0���ɇ��0��;J�A�r�H�����J��*�'GmC�W��L2U����l�1�{Pvf\F P4'y��T�N�ܝ�[՜�Q��4����eAM��T����TJT�="��Sd�)ҲZ�'}T��|P���^�Ƞ<�mx�2�`���)lT[K��D]�y,]�X2S�[GP3:����c� ;���7�xV���T@[� �נ����zo"�C^�1���`R)�1es=w��0�۩$��3��Y��Օ��E0"���F\� -@pP�� �d%/�³�S.���1�_,o�Z)��0[����}��(퉱i68�����r1��fxf�5�$} �a��Ѹz�+�q�fgTfá��k�b&����(��Ψ��u_,���6��I� ��z A�/�Q.�A_��X��'gjww,���l��ŤE��LQ��ӖԴ'�"5�uG�bZ�C�?i1����Z̃�1��GT�#*�S���\,�AI���G��xоNTER�CP#R�#�"&�Ex�H(��G�:rܐ� '$� Cu��G~�j� ����-%�����%�-���� +b`�2�}(���\��5���8�k�f���1a�<�O��t��E}��$�ox���ܙR +���� IO� +���D@-<>�&$��3�L��3�~�p����l����l���[��;�Νt�N�s'ݹ���Iw�;wҝ;�Νt�~G~��t�N�s'ݹӕ��J~t%�Y|��?�Y��,"�O�}=�W�����LeH�� �� x���g��3p�87��g��3p�8� �{�Q�M�PbU�f����Z� +;�Tؒ�)��5w��V���X��K����E�2��L�\|Oh_t>E��ӑ���%�ҫ@N��=ȅ�֙�7��]���}PU��=�6ֺyO�}O�<���9m�(z��Xu65��O^��9�=�@�R��/S�n��d�U�d:h��w�n�8��6�����棚�����( yk�Q�9���� +vAMȷlD֓[�mf���E�a�kU��?�� +{?z�*� ��^ڱou��w�n��u� �ۮ���c(ctLr�&&Ǣۙ�(�%RW��Q-I٫��o9 �(�Lj&X��5�0o�|�$z���Y��(� �)�� ��KP��2���bw +�\^�B��:r9��5���`%{���C !�K��Q�8em֚ݳ�MGRFpGX +�;W:~�F<�xN �Z�$L�V���F?��l��ñ���l�!�f��6��jM��� +� ߅�l{b Ǭ��X2�����9 �6�U-�w���!%3Sp�j%ȉ%�֎Z�u)���f�}p��Q�nBv�?([s*�)���^��i�Z?�;�DF��9b䣣/]t�2X�h�3e�OV�dG������S5~��;����ׯH�WU�RBOQ�2�4� +�*�U��Q%���GGG�19Rr��*._;� +�-I���l)!���_R����'�ݼ���%�*]�A���G����U�� � +���XE���+kaǣrr��qz���R�&�=3TF��ꩩ���\u�&���87�hW��v5����� s�Ѓ6�֠#��c�OQ��&� !��Q�"��.�u�NCh٣P@`�r�$/ ��d�4U�9 �fB"�K{9(���L��� +��/� ��u2�i��qVDZ���(7C��w �{�V�� >G�X��Ʒ�a��2�|��}��צ$pK-��e�����+���(E��������'��hطg�g��d���j.u�B��J;7������b���ER�z��K����ZB�* )fkW��PJı���<�Y#d�=�PqbJ+N�fV�a�f�VQ�BS�Zm!�9q2��#i�Q�Fkˠ�B�m����0kch!)��V����=CA[�ы�/��튱�]��|���Z��3�|D�~������=jt��?���=j�s���.��v��ۙ��Vh���L��~��lh�)`$�����RՐ��&*(�`DŽm}�� j�Qz��Z���Pv.PlN�5��6s�M�ٰ���n�qb���f�ҧ��cZ">]$'�A� ��A���R��}��(�������-9�cB�Q2D�G��Y���6Y�Ľ�׳��.�S�k�(���J�dT�q�&˼@8X$����p� ��\�,)զb� +���*P�@� +!T�${`�Љ�����--ծ�+אT�k��rM��kJDw��_Fs��� .��+� +����=B��<]�暪:3)�+�<]['r����Q��吰�%��J�bJ�{i���H���*>%�$襌*�2�׽����?���P�j�j��[�$C� �V��{`h�=��X�N_�t������X_V��b%��,�p���r)3�"e��1`³�'�ox��l0 +R�835g��FA3�&�E@ �>�ʰ"���1E�p��k ��E�&Jռ1�my��-��<�G�g-��C��qvY�#'�a���m��)�{���s�^M�ㄾ��s_�ȩ�^��x�皟s� +�������4��J�~U�۪?��ʫ+xv`��� +��I ?0�� �O��ra ��'�2�k�9�Z�6�e�7Kʴ��#Ə�KR����J��s��&x'a���\�I6����)(aT�y������O��]ݱ��c�rҜ���k�5��I����\e���w��.�D�d3��1� ���T4�G�*�Z �RA��*�ïC��Aa�a�#@/<���7�GL"@+|{v���8��ĘA�D����)p���1D#��&�!�"�!�J�9b��Av�����Ey�,vr�;R\��8:u;NT�w��� ��}��vЎZ��8�����3�T�BB,���S�v����Y�V��y��W�U-7rAeN(���i�(�'�GdIL7D�v�-�1�h.���:�7�Pn���IQt%(Χ!���"�'Z+��R�K3��QY-�ײ�5Y+K뙸����8.��rP���'�D<��+�. !�JpNM$W�a�'҂�cMWF`������8A�F"�&�U�3��~����a�z�ax�a�;��-���[�Bo� �k[��0�c�Eo;�5 �N������s�{�؁2�(����l�d]&�����,{d�� �j����'DM�l�ByrI7��A?\���x��Qݔ���T����-)�NN�Zi,3��腼|!��`+\��ZK5ތP4w.`���uq�7W,&%W�O�p�_��dE��+�b�|�������/��5�p�NY��/�P�`�8f����O�W��"�˽��h�m�$��p�{~�0�r5�&�&��C@� +i8K�Hhc���� )�c��r-%ju[(19��%�O!�™����r�XO��Y�Z�M�9���[�7�����AH�5I!�Ǭ8���)$J�lÆ��q�,g��&J�P��j���1��9#y_����!HC��Pl��+R�f�j~���*�d�8I��PIÐ����l��}'��NK�Lؾ��cGKs ��Đ�O 1�076������d�6�� �D�%����8{�o{U��L l����$FʑC�y�8��fm ��A��0T�M"^L!o]�H7NuS�lF���S��j�"���j�Ez��S{ ���)�'���>�ʧ߁BuY͹/��D#)7^m�T�����i�b�4lH)��)� R������~&Ê���:�n�7�u!�-��u�C�=��A|� !��E���GB�}'?-�z(�K�~�3W�9����LW��� #�x0��H�c \���/k[�i�_�*��\@B�9'�r��C���e5J&�{��C3W|U#�h�~��6'5a�z0��+-f\���� +[I=�²j0R������(�%�`���Ճ�5��C�u���D#.�'��+��Gq���7�1��<�7P�A��!� GH��&�&��4�A�`F�q=�S!�>'�� ��S�ɦ��K��)?�ᥰ��\��C~��W�:����wbw�`TZ������%��T��_�+�e��8�F۷�n�)��~�K�Ѯ��|f9��8��n���iR�(��uU&���� + �y�h��l?����¥�[�ҽ���xC>#���ސ�a� ňK� +��C. j� �c�����Hq�2�` b�h�R�C9'K�!��UFZ�����}��i�źZ�s���i+0���cWXy-�rp���r�M�a� +�\*��nu�0��Ɋ�hM; �E�C�$<_�_�S��w�c>޷�ߋgB�3��8C.��0��P��H�(8�.(8*�#�,�=��������9�r����0I�V�vF�\K���?�wC܉9����!��+2 1���'t�(T��lu����K�JRf�K�B�.D�B���G~�bRy�H.{$�QI;"�N#�z%q�B��@Nf��6x����DRI"R֎�V]ijI�D!�0�Vx���Ds�N�5�� �lh����Q �,��R�En���Lf2�e��~��G�]t��M9w�������5�^p��1ρf�2��•L��L�d�g��:��k�����b�m��ݼ��2N�VI��\ ��[�H���b�J�ڰk�ՕI�frtK�Ё9�Y-�3��>��3� M0Cc �B��Fp�E��N� ��@Z I�Ai� ��<ԒV;`Z@P[Xp $��4� +%=r|���!��^ܠ�$A������b��ݢ'u��a"����;"2 �c��b�0)�ELa��+N0_�BW=�a+��"BU`���#*�kw�T�� V��*x\��rbY૪�0��z������U}e��R6�� R5��+�:����CʑH�E�!�,��+PS!ĸ$XU�zlR Xx-<� ���Ϛv_%�Ur_%W�`u<�c��Hg�6c��[������\�m�V>����u�%u��zR����&&��HC�UCݨs�&̜:҈`�0����!ц�&�Z�������>�������Rz�gzΉ��^˙8�%�/��Y�z��|��/쵞t΅@8!G%MåfXZ�%d%��0:���tQa�&[�l���r!�b($V���(�G$���#}Y�Ge�s���͈X��2`��T `����aF�*[ , �\��,& �9�2i*Fy6�,ed�FeMi�k���`1�T��Q �0F<"!�e����Z�gj����gB��5"`�_��r�"f9��LV|j� +�=[�'jͿ�'�/|G�ţ���y�l�:[/�b��g�Ik��2�����`�R���9h>z����y1���3��t�SЅܮ�� n�뼏������b0�'48,� �R��l�u�G�t�)oF�����ުp��{P�nxʹ�ߩ�� �����b�u$��f#L�R`r�k]�Z֛"dX1u��;���O�y�՗�E��5�•�L��a/�AV�0�{��f��t���BsP�.0��c �,��ퟸo֤j�0O���j��x΀�ƽ�ya�G-�4�!GR�^ ���P�J�TR`΀JV.��FG�嬼�$���k�J�6�$�W�H�}�T�y�Qf�#�=9���E'S:��5�n���0�|n#�8Ns�\����pN��H�Ĉ���he�\�S�Ao�t�0������땣�{�S��$)Va����W8���ˀ=-�,�>fŲ����j�Z�}��v_�$C-HE�����c2� �뗬Q���>���Eċ���������}ޱG<��,>d�:,��P& ��G|G�)��\`i�q�'�f����H������RE�8�r��j��+�k�t��9��/0C(�d��"�-� #�R��PLR9�J +�<�a =������ЂA'� )�Y� )�)�p���o +��PnN�&Qj*�0�^�����҄��'$(U�C��/��򌼔^����0ߛ�ʹ��,����,�ks�LD��M���&)�HG��Ԃk����_U��-�2s���$�>mH����$�᱙�˥Uc�xr���|��7�[X�� �����Yf�d��Z���!e�|ɷZ!���9�rs��t�}Q�҂o",V�$XgbgE�:U�b%iʕ%-Z���2���(����N�re��2�IO�h��R�]�$��� q7>6B�4%��S�m��G�<�e57/ � $v(M@7-nV.���sBq?�Vț��A�j^lSړ��ܢE �l +0���9{�M�����K��ZQA���1�cv�Q���6�_l`� �PN� ͝4?��Y��̜�\%�? ��2$��B��3q�!(T7 ` dO�`G iաY�MM��I����K�9� +�Qsd�����wO�qD�qĭcy�)�N��|F�����`��_V>�\���a�2k���}{L{B� WUZ���h�t�+8��/�=Y��z��u�#z}�� z�u+��M��+����K��~��ݏ���O4g�L�ڎ��a:F�8 +�1�sl.:�Y�8YQ��rX�d�4g�b�P��9Di�Lh��%�.$���O����(/ \h ��X�_���Vђ�Eᖅ�RG8��=B66&@�}K^��L��i����H�F�/��, ����(�(C�i�t�y&C������ *?*�N">�'ˊ�'m��FT�G2c��S7V֏�l +����HPq�0qE�t�=���[G��Q�\���@�JuA<6a|������$1Ć��A��;�'Z�8%��R���6X�'FD�GD�����@4PB��E��Ϥ:��ckO�-�M���ir�ܼ�Z����ew J�-/�p�L؋dϡx��@��P x�����ϕ��'��_="O����͵c�䨄1y��SG�zj 2Y��g�@���#�̱�����(�F���h��G�% FQ�N�OaN��-U����dNI��EQ��2��QʼO�`�B*��5Yq�q�rl �K�j�!*P���WJ��3��=Z����;K�� �G~cF� >cK�7��H�AM4�7���kN#���_�" Y���r1� � v2d>�8�Ov�͕ꕕ��G� ����0�8Z/�a+�g����d��ī� R��ݭ��~|a�p4���*�� +����JZIw����*R֛h-�Dki + +ZI)�R-��=@�K�g��>}�e/|�46���� �3a�zr��`"5{��XLJ�+j���g�7��uv��!S�o���V�(e�#�� +�/ ���FfV[k>�U��x���a�8�w�J�+V���*I�3�.��������K{��3�B����v���h��n�I�.t�4�~�R\l +�9Em��� +\��h-h߁U�"Oy�J��b�v��V��B3׊�Y�~�#ýS�'5+ ��% +�rDs�D/�L#�w +���/�Y���eU��z* �A>:m�i�P��΃�NQ���J�Fc�2A�P���L\�U��@b1{u�""�S�u���5�����N�gU�Ҹ��Z�E�RX��ӎ�������i������xli�q�qT�����v�S��v1�}n�1�oʁ�k��E0ZIhEWC\q���d a���9�}�%��jԗ������ G��$� {rh�:����Oο'��),��JnJa���|�~����w�ؽ^���U��c��~GR���2.�\�K2p{x7��ȕG֜����uQ^�ȑ�� ��Yhao�ٸ���YrL�o��d��B1���3�`OE�4G�����9�^?qDke��ĵ*�lItK"\�HG��|Ƭi�F +����$SG�u$V��������+� cJq�K6�P��v�jq^qG +{hp������V��xܩ�3�3w����(���HqppuV�fmɔ�����8�5g��3�F�U�Cy���^l��� '#���Ŗ<� w��q��b��)�MhoBΊ�ʵ�s]*�z='�ke4Pʘ�x�"6)��@gER��m����l�C�K[��m�!��$H�%�ݹ��k�tm�؏:�ȸ����g_����dS����qM�gB�a�ܴ�l��ѐ��:X��<� ���R|F�C��)����B�s���8����ݷ�ZH5�E�֥� rㄙ Ö���!���1��>Hq(aa��;�@���y���>�"r]8�{9e&u0{�r�� UÌU��ݒ�`����{;�R��Ќ�(���#E������� F�����ݯ}l�:*�y������]��"\���아�����k�����U����Iy���<ј�i2z&%#:�1[����^^��<��1q��U $U�W��W{�ˊ��6U��5Ww7E��mB��dZӽ�+�S-6�{`�J�*.ˆ�⤄2I����̑#aMKG�c�>��H�}��,:�������RR�cZh� k�,t�$����=)��B(�n>;�&�?¼�҂ ���ԎTe����=܎L3�b +��G��GxAA����t��ND 5PD�'S�u�xn��9 ���P��(�&$�҅�Z�ґ̅Α|U�.�t�Z��<��,Mg�'��h�œ[�r���XC���js�DO�(1�3���AnӘ{j;����,�Μ�N$���}9'eYQB�IRK�~53;���˹Ly�d Og��2��l�I��xK��X��Ƙ'(��1��j�EQ/k�+78º�1!&oy&3Z�$q�2��愈�fq,}�Y<\��maן?��ܮer�� +L�ۥ!�a�<��wd����a��l���P�����v;��LR�4JJ i)�� 6PZJ0�$-e&�1%�#Z;#���2�UE�Hj�A� �ULk'#`���v�U~(X���#r�+ɔ�oGI: �� i!�T�,1�'#��� ���� ���)O�KJ 刉�����*}��ȼ' �*IԔNiR:��@�T+�R���RL��� I�G����Or��yZ� ϱ�~�+ �#N���>{��ƒ��化t=F���K!��a�$��e�d9���4�+)���~� +�s[*�m!?�傮yvK��-�Ju��~�m�U������7<#�՜�;.�j9.�Q(����q6��Ꝯ]_��2.s��� +�����R~˥�Ŝ�Bk�P�5g�Kr[�$���G +�{v�� 1�B����G���2��f��.��U�E{b�#Fe��&�nҌ2�;櫮>�b����;dS�+[t������� �8��*�'Cr�����g��e��ZX}5A>l�L32.X���g_.YvӁ�!I�������:l2��2��7�qġY��L4o�s��쎥r(e�X�:��H��s����嬩�b��y�J/� `J��Q��h�;g��X�l�K/� �*�Q&�p��UnB���z:S�e�[���/�U�嗅o�ĸ:^øzu��u9 +�f(����Jo��w�L� 9o�L�ì7��5[As���l ���e�MY��d,TG Z~qT�K�x·�,���`���1�[(�y��QނK���p%�sMs��%��c�����E��3�"gJlw����(��,^��ʻ���ʻ���ʻ����ʻq��wQ�R&_V,��2����~�"���_�f��<���A�{��4���A�{��4���A�{��gz�{��4�;��������ʻ���ʻ�����s))w�; ̝�Ns'�����I`�$0w�; ����w�; ̝�N�q�����g�g�}��gq ����!���p�"�v_�i����ql�ie�Q���z�s�ZM$q���0�j�eҚzG���fC�~�����������b�&��ff��V� wxw�iyT����`0���9�kL�.��67�st{e^]'��; +A��#���s��BJ�J�{��m Ga_[�TT�XR�ji�z?6\�,�kK-��:��b�ʨ�l�&��s2 �Sw�0�1�89�@ϖ��pS�hF�ȯ�#߻�m��G_ +�~�c�D#��(����>��K<*�0�� +�����Ҫ_�J��&�O�Z�z9��+��=#���-�l��ٲ�,�����ן�� +�p�( cg�̶b�BX��q��&�:��r�<����]O�-�M�^��Z(9���T�'Ub� +['�W��] �νT�'�٩��>��خ�j�忤��*�P9�]V +{ �$X�x)���X ��$��OV<[v(��W0�TʙTɍ�3)� )�=)�)�+��'3X��'�DF���1yrT˜��\5*׍ � +U|z\�����F�c�����Q���#��率��;��+��X<�W�Qyb�\��#syՔ�&6�� vYT��j��bl�sۇ*?so5��E7V��/Ʃk�rm���ȔJʹ㷼� �ɘ�&�3��&�71ωx�{���&yi���[ʹ�$�c/7�G’�ʄ��I��}-���쫐3�e_Q4qUOxX�5�}Hƕ�](Ӄ�dù� �f���� �X��c�E�m��������������{�3���g�&�0�m�> '�3R,��B�Ѕ+�b �����\{T�c�6i�"D�c'Υ#x�J��5�0��L�?�_�!TRe��Z�^��������+��'��.�q;kI�6��V<�<���Ό�;�yb#_r�?�z�VRef��`��2k��H�=�pΏ���gmX5O�ذ|������R���&7=�.��Xc�4�J�<���n'��6ڰ�eM��V�l���R!畷U�T��#�X�܄�T�Q�D�/*���׺�g�\��ZZI�nd�De�E�C�����9�6̤��Fp�����X��v��y��� ^��Y-�T��j��Bh8�N;s���;�5�����PQu�j���#.�9v7TG��V[�4�hsŘ�3�=N�^ +�X��cZ�0�if4��A�n�\�^��m�fk�uKa_��Ό ���#Wu]�&8�p0l��޼yo������Z��� +�;Zq�’+\�/�_�'�Y�O�gLƞ��E$떙0���.޴&��ց�u��w�� �� Vm�'�01�$%f��Z����1�]���؋ }�)N�ʌ?ݍ\� �Ev�P�q��Jut�+�)���F]��;p���LJ���(����i�eyX�em�< �ϰ܌4/#��H32����$��s2$##��ؘ(��2�]�>��]����g��_�W��?�vE�~��j�34�͡0�P�T:X�Z���U[~�A�t��pÛ��*,���wO���&�#\UH:�K_�U��a�z�fz���oyWv�<�]߄��}]����~�O�ɧ#?ɳ?�RJ?(p9q��z��91�sM�c"'���p@�����!B 3����a�脊 +��J��R*{pcA�Ė$Y�BP\�� �HA#����b����q"�����%D(� b�ol +�dfsg3�$&?+ F�$FwÞ�j�X7�WÿO ��1�Cnٲ�H�&�Y�w!��~���Վ�|o:Q}(8gR�#���;L�w<�T:B��i@d\� �3����( +���\��@���ѻ0�~`ej�x�IU����Q�VZr��̘��f;)O��if#>����+��*�#)N)N52 f��ԜN�iZU�����t��*~c:I��ĉ��8QSXT'$m�'N���Nx�&�I���F����l�S($�m�j�� �����h��h��Ϥ�������I׬����D�/+w +���V[p� ��V��t?�MK��Ԣ�&���t���M����V��[�t�*�U�h������G,A�`���Ӹ����| ��Q/�e�h�`�9?B�(j&��u0���ky��md + +�YҦR~DFYSʐ���?�;*$���?�Q?��U�l��AE׎��1X���1�ƣ�&$͕�]�T,0�1����a�?ӰF��K^�����"`yr���z)�?I���{bM�=E��ݕ�2D�gq���T8����E��̞wU�'k0��:�l>��eMJ�����]J��Sx�qۘ�1�i4�FOjY�I7�y7�;��ɒPF�)�1�'*Q�_x.z&��>��F�4|F�[�;�k��e�w�{�qn9���Tp��������7������y��웍� z(�j��y$j���+x� �n$�s�w��3ȱ���'�s ��5L���>��e���iְsG�� Z);�R\åG(;�E���(��Z��/�>�g؞絆CPО�-)՞ʰua� ���fz|�U�+́�Wİ✕Nܻ�UrJzx�jQX�@�Dɪ8���t�&�: �I��l#o ��.��6��6b�����:x�G6��6^ذ6����FF�(R"��N����9�Rf��1�"�U׍E�.���������Fo,��â�6=_ i�-a%�'[X�eU%)��6U��6��ϯ +���s�U�z�H�jcW��_)k��qKq)��YAj+��m`+.6](��M��� �A��VB嬅 u��T�<&�P&VR�}\[��ɂ���<4�A;��S��JՂ���i�i:3 H��aR/h�,ѐa�=�jnC�p�q� Ɔr'Z��ʄC �?L��K����bOW)�`&1{!�K��K�$ 1>��t8S5�P�@k)l-�E�5Gubd'M�4��w�wLE�ION��ܹƜkN���9�}�"���HDbg~�Q����=��=�4b?�!�9H2�:��`� ��6(呆�V�;%�f�5 �̇}F=v�|�Ǟ��V'giVN�'L�j��Ͼ�s��sTᒫ���=f�Kr�J�,��%?dõ�;Ut}�X_��2��B��P#�Շ u*�*��c�6l��I)A$/L�L�F�&]^��;���L ��X�Ĝ=������ʌ�x�K5C��R�ԾP3��S��QfS +�].��Q~V啉7���+��Y��@`"Y�Dl��b.Q�3Ɖa��*�w������<�������D&J0R�L+1�z�Q�o�g[�B�c7����v�ycA2��q\u�fΑ$ +2Uf�J���P�c�gM͛�4�45B%U��U&�Q*Q�D�J �# '�7�y �'��SS�F�I��f�j[jzE�c� �yh2�Uכ���������q��9�f��'����=��r�����?�;>U�Idx�`�ٱSrU�z�<�k��]��]��wE-��:p�^������[�]��k�qT�-�.~���%�8�-�y�i���a"���Z\�Mk�Q�N�Sj������<��� FM������gJ�P +�Rp����mM��q-�:����p�<%X��8!� �����>on7��!� O�����i +V9��i��'�o/"�=S�S|��}�=��>�`�}�` �5޴�H)Z����rv ������n���#���a���g��|ַ������.7���M��z�_f���OU��Ծ��-��L�����~z��w����?|�����5���>�}��A�<Ԉ��/&in��JLҢ��,E%Mm������;��..5.�J�1�8"��E4C��.�V��]ʮ-)���N��|��s� ��4�6ʲ��}�_;k8M�)D��ё=ց�!1#kG��I���pW����KHF�aS>���#�4�f�'�e��2ós�!�e�_f߾b�#�S�p�i���)Js�Ɵ+*�3 ���g�����›�2�9��5؈L���1My�k�5Onvϼ�ee�"��.q�%#�k�|�.a*����t�+m�$4��cF�S1��e��$�=E�2���"*s�a�R����dM����k;I/n��v��;�CZuG{����xU��N�t-��-���S����5��axz%b>��뉒o]�it"�g%�f"C�'����$ЃT\6;nF�J������U��V�2�y ��a���fF��ϻh<aߝ#h!9�̑��շ��;����$ݿ&�}��>q�4���ԫ9P����0�$��kN�������u�&���RC�?2��������Q��ZWV*su�\�k�u?�RD]�V'���љyLd :A�Q�W!߁]�WP��w��wp~��t=K�F)u�#c���C*R8cc��ʎ +�\�#�B��3�Ѳ�a:9� 5� eyB�Ns�f~�.;�2�z� +���)�t褔�w��N5���9���8���b�:�q�� ���1�3�*w@_r���$ �x˙jr���1��F�8)8W��v����zS^m���+������A�aV����b��qհR-�(���� +���+UY��J�K�8ߐ滔��Ui-��� ��;i�c:튾�t +�$-�"f��Պ�96_�c����w�۠6�L�J7�;���`�f��L,�"���VgRR:�>�� #]G� %g� Xh` ��S�� 3C�X�ycN�^]v�b 1+&�\�5v��6AH�p�9W�i�H�f\�j�����UZ�*hh;k]njX~Ep�M +`7���}�෱C�daHF�C�R�F=�(��E��g]2 �NĊ��T-gQ�+�:��)q�ge1�i�T%�JV���̦�#K`:f���Ϡd3��THM�v�S��2���taR!�peW+��#�k��V +!�M姶C+���Bd4�nV-u�C,��i�=Y:�"��;�vzR�t�C5�H;�Cx�:�- �_�^u�^���Ta�A�ׂY��Q��Y�S���$������%bl&1�3n�%�'��N�Ҹ;rz.a�ua���38�O���D�g�ҩ�G2�ӱ�%q��@$�R�D*q�R��ܡ-�ʹ5��)��vR�74�I�Y�{�vZ��d]�t"�6�s �0���% +$R�:��'.��G\9������1����;��x6��m��# �=�[~R :�.�%ц]4�:X™ėb�t�?̪'��Q��8�G#�xD1 +E̿i42�G�cQ���#��� ��Ɋ�*:+멚5���(֕���2���!)xgqв����M�>t��Ӵ��9ִ�쒎��k���~�։N���'�� �T$�L<���2�)$~�CJ�˞J�UR��cn���U�J���W<9�V��=�B��ʜ8���2��in���2����,���))�3f��V\"����k Y��g��$��ՒʙT=\��t�c�Nc��¸��(��%3e7�4κ�p���;*o2�ȴM��pF(}���F�i`�}��������p�ǀ��wM�.߬yD�3��������z�>� �t�Bw�� t�B�y�;@���~2`�;@�7�?W��u���aD/0š�֤F�s����R־��̎��х�J��6g{���b��*� �C�$9FG�(#�C7��EAJU�R|l�{������‰����>�[U��T��M������'�^fh!������gV:%�0�5.ݴD�� '��B?��Jm�IJ����pP.|dz1!�BڰN�����������3Ňɤt(|�[٨o2�#{T�㬝��j4yW��F�kY�WR.�c "W�)kT���ꄷس�N$�W�]H$�`>Q������Y����a��A����L��ӁHJLĖܑ)A5�# ��n�q�m^H|K +��ģb�0>�/(��� �t5:�һ{��}-6��D(����)*I1I�^\Z ��IE�yj���^Y��i%���kȕ�̇�-�mA�R���B��P7W�͂�\��ֺ:g�Z�R��"�K �I��N��\uG 礚���X��"M��#�<`v�ZJE'�M�2�y��`�#���� e(�k�P���z�Z��=��V/�G�v�ї?��4�Tu�����r�SG�ٽ^�+���a쒈ƍn��SM��9\NU���"�L���` +V����S�N����V@`ľ5��1����a�]T�Д-s�w���P+�P=+R=s ���^�;΄��R��O�1xk�J8�ϳG^[d-i�����H+�A풴EۡU&[�����F4�BQ5QK��ۺ���:��x݈������"��X���7=�=�x����zwx�}�2m�k����"h�k�-Z#\�����U���_n��b��z�ZV�\�1"�6#���DHDNI\>�̷�kƈ�S�C`���k545�� +vv����E*fH/���ip�Y!-�6��܏������QS@�~�\Uy�z��JA���_|���!S��0\N�3_#�vW�`W�`g�xUeaˍh�c�"�!�1q���9\5�{5�I�Q�H����"��M�F̉�k戡�"\��Ys&�?F>,o��{�=�� �(3�aQd +pP��{�rBB��Х+��Qi _t|��!#D�\�f�����\��rAX���䂈gk��\�/*�7iI����jE�$s��<� !'��P.bF +�n`� ܐ�]{tF��� �� �)�� �S��E�~N8�X��`D�^ʨ�; +BꡔM��3�6�;U�*�7v2��ka�äB�*��DSƥ 6����gHY]A��I�ɸd�H����<ƛ��a,Г3��D'���X�(K<*>W(��si��0r��o���I ��F|��K��2u4�,F[e��xR�iL�Q�ؙ�hr3��w����g9S|�/��B`�p��$��̖] 1q1&-�TYY&eQ��<���h�n����ںĕ�0� �P��ɚ�B� �$ZZ �r"Ҭ�8/B��:ʒ�9'��Hz�ʞ�q �A�zP������֚aLٽ��Jά�ˆL�Msd�ž���k���r^%ǕsZCބrkWʁ�0T�S&�Aِ'r�*fe$����'t�0C�p�6ʔ�1�����\�g*Hu�uXsU����]Z�eޏXӼ�͞P5�����//������߾�曷�>�v�ۏ����������i~�y�����}����#*�C�]K��� ��6�ʖ��Ś�������� ��\��������?��/^Ӈ��˗}�����{���.��]�>�!<�o>���o��'�7��J{ӳƅ���q��ՏC߶�A�⌗���9�o�i�z4��<�f~�d�d;4-� �MzSUч�f�=m��gz�}x ���=�Q��j��Txsv���?��*�X�π���Pu�؊p��!߃������{�a�s���y���5�k�/��7ћ@��y�&>\]�Uh�j/T �F�B�M-�c�<��K�}7�7� ��"�#�p�؂��0L��~��oG:�G����[���w�-�;?���#c5#��~�i���/�UCo����7u0��������Z��p�8��g�{j_ݎ�3Nxl����5Njt�O�=¶�ЛF�O�{ݶ�!�]����,i:��p +� u6��|d�[ֺ��cG����D��^<� T?�����Ճ�(q�{� 8F:��>ԏ�!�v=����C�O�����@�e:������=|Q-���N����3 <]V^�6-֡�nh;>#L�� �ڄ� of�#��xNc&�+zSW�[s�{48T�/�x��n�N�E���T�>��aѲ���^�Ӡ+#�����4aEt��'X +ἧ���P��?i�@gR��g�D���0YD.`����,��>���L��0AS�>t�_} �OD ^lZ��xZ7&�k?��x� �M���1�&��Hµi�L�yݛ ��Od`�KuP��iz��t^�2��;� �� �Y�y��@�H}�2���d ޴k���*���u��@8oX&� ���0� ��kM��N�X�=șNd �5ce2λfNd \��d �O�h2����c�0�Be ��L0���D�Ŗ6��pޏ��@8�>��pq�{����XA�� �ӱNd ^���t�U� ����H�E�c"��o*�!��+��&(��!��ք �i4!H�C"�bkB��Ƅ 6�d,�?�Ʉ lmB���&B&�L�AA�):�T��!�u�M�9�(&�> A��x�$qF�t>%B�.�&i�&IBU�D 4�&�|2!���\�`�t��@��� +A<�mB� ��� A�آS\� �WդBΛ`� �K���?N��?bA ����V��M���k���� ��83�33.Ff0�{3�33�y3�#3��������o�=3��93ϽL������ Ƈ��`l�7��� ��α ��ι ל g��U3.FfpW�f0�gfpW�fpW�f0��fpW�f0�GfpW�`���`8�f0�ff0^�f0�;3�� f0\��`<�f0�gf0^�f�� I��`wulӛ�L�L�L_��`�ifcwz3�՛�8U23�3��96�q +ff0�Sg�7�qrgfp;�f0�g�yj�Eg�7��<1��7��ܙ�x^6�ۺ`�Eg�7��<7��7��*6��<5�1ޛ�m��x���X�Ù��o�yb�}��V�L������ ƛff0�қ��u� n��ֱ ��ֹ�6� ��� ��� ��� �ܶ� �"3�#3����p12��<2��<7��7��.2��43��7��ܙ�mW0��7��<2��<3��C� v7A!����v�Lorf0��f0]tf0�{3����؟� ��uf0Ε� n�� n�� �9���8Q��ֱ ��Sޛ�$q�L�L�L�ș�$�3%�7��ܙ�x^6��67��7��ܛ�x���p12��ܛ�p���p)2��ܛ�x���M+����`:O�`���`<�f0�gfp��f0�ə�x�����48�k��M��8���y�= ��ip�������ǿz��n���?���է��q����i�{�4 ~��4x�1 ~ol����M�������6 ~��4�=�9 ^�> ~��4�=�9 ~o�����< ����q���4 ^�_L���48��ip��Ǎ�4xz�(`���O��M��<����48��i�c��y��< ��ʏip���i�z�ip�L��u:M��x�Nj��4x=�48��48����y�4 ��y��_��m���4 ��_O���wO���e �xW(��'���G��ip�:�~�4x�8�wL���;���������;��g��ݦ�ŵ�g��;g�kk`��?1�]?n`.�v7�ɻ������0/��$xs�_L��6&���x��>9�Z���Q��s�� |r|�"���絅��K΂���ĸ�oW0�D��9����A����~K��3ᥒ�FS��%\r2\i�.9�n�B��ZWwp����i!��xGR¥~��S����T+G ��e�F�O����K̊��k^�䴸Җ=\r^�����E\bf�F�ߜ5��0��k���p�67����mO�˜[N��17���q͍cj\٬�q���17����=7���4.�bdp���S��ki0��Ƣ�����*�cj\c��`N�ױ6S��k�1�گ������k��cj\a������6�S�}� �f��`N��������X$)� ��x�Z�S�=g�cj��bf���x1�un��� ߦqa�G���v�%����&�+�P83�KN���U\rn\ �#���{�-����X.�1o�OĖƸ5l��8g)�� �f���S��]u�v̑kx�}\r�<��G��_��?��_������w���w�c���._P���o���w���������?���ÿ��?�u��_��ȟ�_����������������w��_�������?� ?�W�ٟ����~�����T�� �Ƶ��������~��������W׃����������[�{=4n��C�m~Mׇ~�ݺ����8��Lׇ~��fN����O_�������F�3]�����M롙�i=43��-�c� ����8����y=4g�zhV�{=4~x^}�o[�b}��f��zh�c������zh�����Hͼ����zh<��zh>��zh�׾�C�9���k_� �X��x=tό���88��c=4n��C�`�zhV�{=4n|�1�4��q�c=4n��C�A6�����zh�����Zw�Z����4��Ư�G����zh<��������LՏ_��/����|�N�q<���s�c=4��i=4_:�ti���y�>j?ŧ. ��\͈M�y<������q���R�����0g�L�x�|���_�݌���Ү�b��@b����u�4�_Ok�қ��۹�8��ް�K��x�D.u�~��1�T����Ӱ�<� ���;1�> +���\�W@�&���G�O <��#5����Yw?Ӡ�\�O��a��Z�h���qt-����1�k��\��i�-5@֠�Y?��6��|j�D��m��_���ElӘ�Z�c\C�3��`�����_K=����.x'�G-/��sԴ@#���c����s��s�#�l���?�k���5�������~M�����R���� -z�x?��{�/�u ̄�z�i����y�����;Q���hI~M"�F���#�m]�}���z��/�k�?�V�s%�}&>��� �?�Y���n�&�5���g�����>� �����y�Nc}'IC��������g�?������x���������yp�e�C�py�ç���=F�q��id^�oո<5�]��x�� �5�i\^7nZ�qy�3:q���_1.�xi��,<��IB��}�F�q�V�ѵn����HF�q�|��,�Txo�>5썑y`���92���?�F��^�12��h�fjd/���;u�}�o�F�\����}?]�g��|�d���9�u�K:u��`�����ec��c��������cd�u=��߷��"#��ƧN���<~Hgurd�������q_j�W*����_9�F�14�'EW ��<�����<��Xp���e �ch�Ͼ�o��yB�c�)��qcx��uwcl~��,��f��;f��׉�y��ߩ��������8�_��94�򪀏���N�ǝrh�ޘK� ���w�p24������|+_��5C��a���}e��N�V���r����[.—_ �<�|�5b����Z����k�sm�|���V�,�y� �����{��Z��|���g=/�/@�~~z��_�E���/��ۣ}yc}7L�/�/�/˴=�}�����/�P�٫��}�Kﳵ/n����W͎�}�M׫�/��]��hu_��Q���W} ��ōk�2��k�o�8~�x�/��Z������Ϙc�q%g���%{�/���/��}������d�/��q���k 8�&�5���}0��^�ȑ�������s�R L�\s����Η,^u���ֻ'0\��i�����Y���?�������v�?��y��� (�8/0P���^0 �Q��@��fC?��̏�ZR�XJ` +�M��o_�� ��{ߜ�D���7��f� J`��Z* �?�|�����e�X�������q��/[o`�B5\���?n`�V��� �W�Y��Y �W�~��Ku�h`��f��}�{O`��ϱ9�����[���#�ycͻ3�y\�� �Bm[o`>�z��y��n ��Gӿ�Gk�!c��Jf50�j�-G���y����Z������;_:�&����7���k�$�|��7iz���y�}M~�k�� ��� ���<�����1�-Y��)�kL8�_����k�i`�{���&.���!��� L��|�}S:�9,������kժ�S�٪�q"�3�����}1^7p������N`\�z��o������s�~��?ט�&����JઅӖ�\���<���7�y}�M |o<�1�=⯵�����l�W�����@��qU��8���FU�j�T \ǜ� ���1�?���"�����{��|V+^Y�x��Z p�E�9��w�!���ܿ��B��w�|�0�G����$��8^�{�2d�7�1� Z��Z����9�����c��˘'�_1���p�5p�����힯�e0N�=��_��u�%w��1~0��u��I�:�o����.%U�8^���#�9� +`�u�/�绮��-Z��֯�������qھ�Z�[�Yu����R�xS�r�����>�Я!` �O�[V�6�-�$��:���o�e�BN燉$~�U�9�oy~�� pop�s� +�� �� ��h�|���V�=^j�����5<pg3pg�Fܙ +��)����0 ����8�uZ�,8��~0��:������Ờ�y�4���XݿD���0~�K �������,��_�Y�E�W�*�ĘƋ��T���j `�(jxW|_GgͿ��uƤ�y��8����U�\5#��Μ��Ż�Q�P�ub� +�j��]�-/��Z7�9V��\�&I���H`��F��8�k� -�(#�k�J`8��������5���c\�~w�x���#�ip"�Z���ï����1?�����8�����#���^�1 �� +q'0������-�N��>�9���j�����{͕����ːn�M�Oo`��g$0�����p���� ��J��P��:�N��5| c*��w'07gH��-�J�<8|-3dӘo_k�q�9ƀy��yp������gL�����`���9���Z�4����r}M��O��T���j�� ��O��cL���$0���5 ������|^+_��x��uRd40^U�1��[� ���5 �W�Q_��U���9�f��=��fn�1 ����(`�mF�νd3O�C�M��m�y� �kP��� ��/���r��qN��_\`��/n��ɼS��PP��� G����8 ��9.�������&4|=l�/E}-/f��x���&��gd����)��_r�z��ō�5.�)��q�����_�3�լߪ�h�~�����J�52o�/,�9̀�.�+m9+�~!�+l�5�ttF��{od���{��@��}]��~��s]M� �?�J������ò��?�E���k_�A�X#9Dž6i�뚙����e�����2 R���o5��K��� m֘����ǫN�9q㲌 m� �_�ׅ6����?��z���/����q�M��}\h���-!�g\h�O�9�b������5���Wڬ�X�˗��u�M�V���'_A������˾]i/���bd37���&�k�=�g�?� �}Z����GZƕ6q�s�Y�<^~q�M~��݇����.`|��ƗQ���kH^k�w�U��j`,��dو B���?�lqF0��B��x�^c|�u�Lj`/���x�gg�㍼,�L��E0m�gsÿo���q���5 �$Ds�`���k�~������y�Yp~��>.7�7�]A� &�m� +���ĥ�h?���������Z!����k;����,8<<��.�"�E��ި`\�����8U2*���R�`,&�*CUpպf�`�1 ��û�U ����۟1 ���{|.�W��͖1 ��P����+���L�"?3��u�> ���1 N���Y�/Q� |��3f��n�X�������*m�� ���� &^���5 �u��������jm&�}uߺ�g$��s�u�L`�����$wO`~u�:Ng�Α�Ԣ9��ި�ᲀO��'��? h 3'�>����$��Ǵ +��9}�u��qL a�O=KhC +�cZ �c�a�s�lja��C| =��!��1��K��qq�} M�Ǵ&�(�*3g�>��!>��!>�� 2� G�jp��i�C� Sc f��if,�����&��1̋�1, �c�� >���|��y1@�/ +�xiPs#Vd���o�� ^���ʠ�L_���� �ʠ�L_ "3� !2^�ik�2^���ڠ�L_����XB�#C �>2����PD�#C��E���h!C-dZ-d(c +�e�ȴ4.��mn#J�6Zɴ8�ɐG3�h&�#�� c�w���ʵ�R ���n7_sv��-�&�g���WΧ�����벧��O}qF�.�0��|�|��Q�����ĥz�p�aO���I���y���>Ɵ��qM�%� /q��{�3�1���4q��^�%��ʋ ���9�����������cOׁݻ9 [�p������g�s��+ +Ns淆���i��N�g���+yV8��}���+=��$���t%�4yQ��j�Ƨ�r^�׎P����$�;%�����ՠ&~(��L�&��r���&W�=M�*��5�i��}M�IOOJ|:�i�Z�m���㸪�w + +�W�����g_�==M^A��;�bc�����ƃ� O���\�Ӝ񍏛9M�v?�O��!�}�}��1{�x�� �i���T�Sz��Ft3���4�YǪ�+�����&I�9M<���!9M\���z�N�Q�B��&�_��l����^�o�HOWe�^������E�ϔ�z���Ü&~f�� N�ybvu�W^�[�69M���{\.��;�?����qij\Z��^Z��V�ƥ���qj�j�Z���Z���L�s+S�s+S����8�25=�25έL�{+S�{+S�����[���[��V���^"5���H ����ҵ� ����K���^Aj��%R�j{ �P�K���^B5���P �� +��K�����Ql�25��:���h�%SCk/�Z{�Դ�^1��*SCj�25���L ���&�25���L�J{��P�K���������L ���Դ�^25 +�%RCh/��V�K���^d�Ҋ����qhejZ���25�L̈́ �������Y�w�HMϬH�3+R�̊���,���TC�@5�U������j����O���k��f�����j��\M�����j����WC�p5�O���WC��j�>��V>���!|��>X ��>XM ����jh���XC��5�X����}�։�`Mk�F���?���>\ ����>\Mk$���j����WC�����jZ�p5�����jZ��j�����jZ�p5�����jZ�`5�VC�`5�~��!���?\ ���L��\gi��ըb5�V���������?\M����k����YC��5\� +�!������!����i ���@l �ִbkh ��bkZ�5D[� +BkZ�5tZC�5���5dZC�5-��2�!��5���*�����VAp �PApM� �F�֐AlM�l �֐AlM� ,� bk� ��e[C�� bkZ�5� �� BkZ�5t[C�5���uZC�5���:���К�Ah ��!�ؚ�Al �֐AlM� �F���AhM� ��Bk� ��g�5���:�����At ���A�M� ��l� �f� ���k� ��u_C�5t_�:�����:��i���A|�:�i���A�2�i���Ax�;(^�;(^��q�kzl���Ѯ���ql�A��A2(_� ��� �׸��5���%ݩ��1�|�;(_�;(_���������A�wp��g�|�;(_���������5T^�*����*�i��PA| �״ �k� �� �kZ�5� �� �״ +�k� �� +�k~QA��^AWpe�"(a�#(a���8�B6=�B6����#(d�"(c���8�26=�26�`7PƦ7p�ı(c�����ظ�264p�p�o�W)��"6�`��@7py�BlZ!64bC!6-� "�!� �VA� �PA�M� �F��PA�M� Ɔ +bl� ƦUC16Tc�*����ӃdelZel�@� �شblh ƆblZ16����#(b�#(b�d"(b�#(b���8�26=�26����#(c�#(cCElA�^AWP��\=��� ƦUdCA6de�2��!�82�iڐA� ���ِA� �ٴ ��PA� �ٴ �l� Ά �lZq6dg� �lZa6dfCa6��0:���0��A12�!�0��A� ڐA�M� І m� Цeh� �l� ΦePΆ +�l���M� D��l� ΦEgC���lZq6� ̆ �lZq6dgCq6-�8efCa6��0:(fCa6-�02(gCq6��8*����8�VA9EfCa6-�0"�!�0���ٴm� І��i Dڐ@� �i�P@� ����!�X��i��P@� �ڴbm( ֆbmZ�6k�BmZ�6jC�6��P +(jC�6-�P +���P�V@� �P@�M+�� �@�M �F��@�M ֆbm( ֦%&C�6$k���!�Ӄd�6-�X%jC�6-�X��!�X��@���!�P��@� ���@�Mk Ԇbm� ֦EkC�6Dk�"��Q�6Tj�*���P*��YA�M� ؆ +�m� ڦumC�6tp�B�!��B��C(oC�6�o�B��!�xB��i!��B� !�۴�m!�F!�۴�m!܆�mZ�6�P܆�mZ�6�n���� +�8���]!��!�q n\�e�>%����6.��M/���K(o��^q�J(*��۸��6���6.�x�*ay�ByBX��\=�:(o��۸��6���6� ܆�mZ�m� ܆ �mZ�6doC�6-�x2��!�x��A��2�!�p��Aq*���p����i4���7��⦕�����B��C�jhtC�n���PD��hsӚ����67D��U��,���E�M�� a��QMnZ!7#��x�(r�Lj"7#N��A��M$��x�\�Ƴd��>K.t�I�Ѝ'�B7}�\��sd�/ +���B�� +en�T(sӗ +en�T��+�27}�P\�+�27^)���+�27^)R+�27}�P憵B������B����x�P榯��0I��Q䦏En6o-�����2q'n[���d\ư,ck�#F͇���+��$n�gl-��LN ׈�6m:���=�� +n�x��?%��{c�i*pS�㌭%�‰}��Z2��Hn.p��bJ)n⢈�)��04��C��N��Z�)��3�]�gn7&o�����d\��x�y.d��ĝ>��Z2�{��;��ąMڀ5/̈��g[Kƥ����M^�%�.�6q.��$o����2��_e�*��&~��r��6q��[K��-���d<��u�2yY�3���cmM��&��z����?���An���^�Hm-�����[K� y���%�~n�א�&/���֒�.��;�&���-��Sz��h�s���SK�&.�'��C�������ChO��6qYV��J�of{��6q�>ckɸ ���Jo�W)��M\��o�o�++oCe�m\Yq�^YqWV�ƕ�i���qf�m�Yi��YqZ[�Ʃ��i��qj�m�Za��Za�V�ƭ���qk�m�Zi��Zi�Vچ֢m�ւm�Z� ��ڴ�bm���am(-֦�kCi�6�k�J�����6��Ɯ�6-�XB+l��bmZg�6tkCg�6��@:+kCfemZe�6Tvz}�YR�VY� ���PY�M�,ֆ�bm���M�,ֆȂm�,ئUl��bm\YY�^ٲ6����#���ݧȖ�qcem�XY��XY7V�ƍ-l�+k����8��6?{��־S�F�;Emh�)j��w��о�6�j3�O҆�!mҦ�j��!m(���>� ��>�M І�m��M�І�m��YҦU�,iC�NI�wJ���;m�SΆ�r6-z���`]�!gC�N9�ֽSΆ��(4�45:�;/�Q3�q1q��(gӺw���=���'gӺ���{8���i݃��=� ��ٴ��l(�� ��>�o7���|8ʇ�i哳!|8‡�i�;�l(�)hC�NA�V�S�F�;�l(�)g��w�ِ�SΆ��r6-}�� �;�lh�)g��w��о�� �;m��������r6���Ei?ۇ�i��٨}0��i���>� �����Cِ?� �Cٴ��l�?� �C�����?� �ٴ��l�� �@� �P@�MK ʆ�lh �fn�����!���@���!26$PƦcC16c� +���� +��i �ؐ@����i ��!���i �ǐ@� �شblH�� w���شBlH ƆblZ164cC16����� ��@��������@� ��!���@� �ؐ@�MK Ɔ�lh �fn Ɔblh ��g16��5bC!6��������������@��������������@� ��@�Mk ��lh ¦5aC%lH �fN �F �׸��5���Gl���5N�|Mo�|���\g�����8��5N�|MO�|�(`C�kz�k�@�7P��7P4� ��q�kz�k��� ��vM��5n�|�����h�|�(_������ql( ��`��k( ��_C�5$_���!����i �א@� �� ����� +���E�kz�k(`�P��P���q�kZ�k@�P��P��J�8��5-��5`��O���O����q��kz��k�?��o5mۂ���t�X���O���mN[�[��������i��@l �ִbk( ��bkZ�5\�bkZ�5[C�5��� +����ؚV@l �䖁��@�����ؚ�?l ����?lM+ �� +�8��5=��5�@ٚ@�P�������qek@ٚ@�p���(\� +([��ָ����_�ִbkT@h �ִBkH ��Bk�"kH ��"kZ�5J ��"k� +�P@` ִkH ��kZ�5$XC�5-����!�Ț���5WCq5��r5$WCq5-����!����@\ �Ր@\MK ��k�@\MK�\ ��P@��@H ��@\M ��NrK�,��4VCq5$W���!����i �Ր@` ִk�@���i �Ր@� +��i��P@\ �մ��@` ����@\ ��� ��W��j`���?X ��Ր?���~�ꇪ�~��V?��UC�P5s�@5�TC�@5�~����~��V?P ��P?TM�����j��f��F���!~��?L ���P?LM����aj����O���aj����SC�@5����SC�05�S���!��i��Ԑ��Anɗ 5-��!���?L ��Ԑ?LM�����j����oK��?L ��Դ�aj���bjZ15SC15-�� +�������� +��������ԴbjT@H �ԴBjh ��Bj�"j� ��"jZEjAD D���A@ Դj� ��jZ5DPC5-��"��!���9��EP���iZ�4DO������8��vFP��GP����q�q�dTP������4���4��<�+(O�+( +� +�Ӹ��4���4��x�����} ��,O��c�3(O��Ӹ��4���44PC5��5J ���iZ�4$OC�4-�x��!�x��@< Ԑ@@͜@y +����x����i ��Q�i��9M��9 4����4s�i(�5 )��i-4�Q �iȡ5��C0 =4�!��4���4$ј�&�iZ�i��1 U��iYD�xl(M㱡4M +�06ɫ��,M��xj\��3cY�>3.K㉱,�'Ʋ4}b\���bY/ ����AY/ +Ӱ4(Kӗei�4��+��4}eP �+��4^���+��4^r�x�tM�4(J�AY� ����AY� ��xmP��� ��xb,L㑡0M +�02����P��eKCmi�-M �- e��PF[��F[�����4smiȣ- }����1�fMU�)�;�ȝn�4K^�iJ�S*�}�ҼO�I���D�4�i�����ĭ�4KIS�7�׺J��di����Y��9��q^����P@b���9��7KL' �2.q�U���3������ ����տm�4q��=8������ u#(_�q2�:v[�8���5��yo�"��4q">�A��q\��}�3,n�IMǩJ�i���0M��,�1M�f��&�E���0M����0���U&0M��e���4q�-4�&~�Wٚ�4�.��N�i�9�-3�i�㼠L�cWP9�x^�s3��'_��$�ٓ��;�J�/�,q���&�q)MS�u�2`|��f���>�i�L�g�&N)ޟ�i���]r +Ӭq��>0�����i�z�x5��s���i�X�� M�֧�x��H�1a���4��7�3��k���4�v|�hdϝ +Ӽ�L�^b���r4�Y��Ӆ^� �&~�sM��?���+ ���XUJ�* �Qe�4TI�2 �!�P2 �i����ZYR��i��qj�i�Za��Za�V��������Ҹ��4n�,Mo�,�[+KCk�4��`Z��!�h�[4 �MMCi�4si�4�LCi�4��`J+LCh�4sh�4�V��΂iZg�4tLCg�4��H:+LCf�iZe�iTYcU֚f��5�*kM��Z�L�5�Qe�iTY0�YcE֘F�5��+kL��Z�PY4M��4�" �!�`�Ya ���`��X0 ���Xa����4$MCb�4_�����gJ����T�Li����T�$iT>K��|P�ϔF�3���gJ���Ҩ|X�9|`��!|`�>0 ��(|�4�{X�'KC�diZ�di����aiZ��4DMC��4-zh����{h��{`���{`��=0 ��*|�4s��4tKC��iZ��4tLC��4�{8��!|`�V>c�ϘF峦��gM��YӨ|�4S��4 +�1��gL3�ϘF�3�Q��i��Ө|�4*�5�\>k�J�1��gL3�ϘF�3�Q��i��Ө}`�Ϙfn�5��gM��Y�|����L�;�4j߁���P��}���w iT�I3���(�F�;�4s�(��w`i��K3�����0 �;�iZ�a�����,M �!KCY +x�Ҵ�44𐥡��,Mk�Q����ۺh�.� 8���Ը4�g��4mf\��caO��i�ĸ0����4^�iK��4^���Ҡ0M_���`͍�2(L�W�`�2(L�Aa��2�aeL�� ��- �iXDӰ6�����4� �iXӴ�A0 c0 #C0M�i�i�i�,Z�T�Q���80��hL�2L3�q`�јFm�f���4���4���4�tc�weib�>TU�4q�z�4���K�ib�?^rԝR����s���Z-���|�{�&n� 8����s|�i��}�����)㒣Э�4q�����HM��Ik��NaX�l��ǝJ�l�߶,Pj�X߮�i�<�}��2�|�y_�E�JӬ��}ԍyq�5�Ro)k�� �~vi ��Yj�14M|���Lk��.��>�!��<ݚf��h�i��@���Y�J�{p�xϝ��4Q�8͚;�Y��9����=���}�4�z>�Ӭ�QbN��Uyܩ8M��^��i����lu-�f� ��ij_���y���ŝr�1n̯���=�q���\�}_���4�R�}����S�� N�No�wfNȍ� A�&O�4�an�%M����ӯ��4qc�7�4�ڮ)5M�}�5��Z=�;�r�=8MG��4q�霶�JN����Ӝ&����5��~r�z���� M�1rB��o!(�ܱj�~�N�i�WM^-��������4��5.�@�K+Q�K+Q�ҊԸ�"5=�"5N�H�S+R�R+Q�ޖ�qn%jzn5�QCn5-��r�������[H ��Ԩ����[D �E�,|���E�zkQ��Z�����QpKԨ�5smMjT[��֤f��IM�Q��Z�̱5�Ql!5j�I��Z��֤F�5��[kR��Bj�ZH�\ZH ��"��i��Ԩ��J��i���PZH ��i���(��B��i�E�PZD�K+Q�K[�ơ�qhEjzh�Ը�"5�HM�H ���qgK���J�8�5άD���bjZ�@5�TC�P5���W����jZ��j�����j���j����Iմ�Y�(~V5��U�?��ϪF����3�Q�`5�>T�\>T��gU��7����gU��Y�(|V5s��j>��Ϫfn�Y��gV������3���Y�(~���}f5j�Y�����gV���լc�>�F��j�>��Ϭf����M���մ��jT?T �Cմ���?X �մ��jT?T �Cմ��j�����jZ�P5�VC�`5-�������?X��'UC�P5�����������մ�k����!kZ��5�ZC�5����!�К9����!�Ț�@˚�_^�f��o���hY�Z֨��5sMkAӚ��e͜A�uвF���;��Q-k�A˚9��5ʠe��=�R��4�QMkTAӚ���5UA�UвfΠi�2hZ� �����(��5��汫&�#��5ʠi�2hZ3gZC��oY�i��(��2��i���Ah �ִBk�Ad Dִ"k� ��"kZ�5tP�� BkZ�5dZC�5-��eYC�5���:����Ț��ִ�k� ���kZ�5t^C�5���:���𚹃�:������A��w���|�t隹��5�u�:h^3wмF4��Z����Q�5��C�9��5�u D״�k�t D״�k��2����?���(��2��i�אAx �״ �k� �f�N����Ax ���AxM�x�;8�o�I^�;(^C�k���3����5�x�;���WP�� +J�PAtM� �� +�k� ��U]C�5d^�2�!��2�i��(��2(]�*�����*���E�kzl\��u����M����#(b������8�"6���M����#(a��\� †J��@�Mk †"lh Ħ5bC!6j ¦5aC6���g� +Z����y�Z�� ��Y��P�f�K �9����QFp��(�;�f���� +�UpG���!6����*hb3W��F4�QMl� +�ب�&6����\A� ��N�i�Q64a�����i�ElTA GP¦GP��$�DP¦GP���qElzElAGPĦGPĆJ�8�6��6����+�z��UA�M� Ȇ +�l� ʦeeCa6df�2�!�02��3��!�(2��iD٨�V6ʠ�͜A+e��F4��3hf� ��T�l� Z�(�V6��C)���V6ꠕ�:he3we� Z�(�V6s�l�A3e��fΠ�Me��F���3hf� ��(�f6sa6����*��#hf���(�f6sa6Dpz�� ̦Uf� �l� ʦefCa6df�2�QQ6te�:����R6de�2��!�b6Tf�*���0*�i�QQ6De�"��!�("���A�M� Іm�`I��@� �ڐ@Q�V@� ��P@��\@I��!�H�@K��F��� hi�Zڨ��6sMmT@S�*���\@K��f1y(i3��FD�(��6s-mT@K��f.��� +hj������T-m@K�9��6 +���hj3��F4�QMm���(��6J��͜@� �$�i ��(�H��i �ڐ@� �ڴBm�@� Dڴ"mH ҆"mZ�64jC�6-�P"�!�P�A��*����H�VA� D�PA��� +bmZ�6TlC�6��h:���p�B� !��B��BiB��!�h�Bk���F!���Chm�Z�(��6s�mBs� +���Bk���f>H��!��Q�6 +���Bk��چ�mZ�6�p���mZ�6*!چ.���(!܆�m(!ܦ�nC �6�n�J���pJ�i%�q ǃT �������6�����A]Y��۸��6���6� چ�mZ��dp�vI�m� ڦemC�6dn�2�!�p2�i��(�h2��i����h*���YA{��A�:hpC-nZ -nH�� -4�i14���&7���f�� E��!�7��7j�7��7s��Q��QMn�.r�0rSe�fN�� cD� cD�M#"n#��� q�����7̒7m���:&ɐ&ɐ�6I��q�R!�-BnX*�ܰT�iK��� +5Qb�r�V +!7�BnX)�ܴ�B�����B���T(r�Z�č� +%n�Z�ȍ� +En�V(r�� +En�$K�x�(q�G�7!J�x�(q�҈�!�&7������:Bn���Mˣɍ�����7-�7$��FZ����s�T�������c����xKan6����;���E��`n����M����&���4��E]l�����;�mnb�������&�f����!aXӹNmXk0q��Hr���$���jQ�2Dnr�賛��:�}�L��m/6�y��k�mn��{W��5�w���3��� �U�m�7�烶���� + m�k�޴E�&�} ʤ��5�P'�6�X��`h�X؍�0�f�k.���E\Ki���ϫ�M�P(�M��]�lZ �2�m��x~�m�W}N�Im�Gn�)m��Km���Y�ZA�56�M<�ږ&�M�.�iK�\q�}��x��P&�M����N~-��[ k���H]���>�)�M�>�eko���QZ�x��Jkˠ�r�lq1Ny���s>e���}>��ͦ�W�6�q~�������lW���6ۼ��&�cc<�������A��=Nʝ�y;��m�M�P���6����K��M1���Ϭ��&.��ƽkzaem\XYV֦V�ƅ��qaemZbEm�XQ'VԦ'Vֆ��qfEmzfEm�YQgVԦgV�ƙ�qgEmzgEm�YQwV֦wV�Ɲ����X: �QgQ6�e�B��!��l�,ʦUeCeQ6Te�*����b6Df�" �!�b6j,ʦ5eCcQ64e37!Cc�lH��M+,Ȇ�NQ��$�i���PX� ��ش�bl(,Ɔ��ش�bl,Ȇ��lZaA6*,�ƅ���-c����8�26=�el�W�UƦ�U��}]}���ZȦ�U��y��q^el~�cӺ���{���i���н26Tc3WOĆ�Al�ĦEc��Al���M�Ć�Al�ĦEbC� 6DOĦ5bC�DlH��M+�� ���<� ���(x����i�C�h �ִ�Akh���V��5-~����~ؚ�?l ����?l ��Q�P5�U��!��'U�ꇪ�~�ꇪi�C�P?X ��մ��j��F�Cմ�IՐ?T �C����Ð?P �մ��j��� �D��e[����aj����SC�05�S��������i�ը����i����?��i��Ԑ?L ��Դ�aj�����j��aj����aj~�S���������i����?L ��������?H ��Դ�aj�?H ��Դ�Aj����AjZ� 5�RC� 5��������?L����q ��Ԑ?8����q��iz��Ԑ0�r��������q�g��W���O����q��iz��i�?q�'M��'M��IӸ�4�r0�0��'L��'L���ѷ?����q�diܿuLqF�di�?Y�/-M��,��'LC��4�~`�KC��4�~Xꇥ!X��?, ��Ґ?,M�����iȟ0�\?, ���P?,�/�'K��'K����q�diz�di?Y�O���O����q�Diz�di��(��'J��'J���q�Diz�Di�>Q�O���O����q�V_����˲� ���8~ei�>1ڷ��-7�b��> �C�?M�����h����EC�`4�F����~0�E�ꇢ�~(ꇢ���~ ��i��P��At5�u�����> ��д�ahh���ahZ�04�O�������!~�x|!H�?�O�����q�dh?�?�O����i���q�dh\��s��m24�~� ��dh�߶{h9��А�M���m24s�6�А�M���o��Q�6�д�mEh��&BC�6��� ���m"4�o�i��Dh�E#� M��&C���!� ���gԿMz��m�3���8 ���B��Mz��o��!��L�i��i�ۤg��&>C��3-���Q��3-�3�=C��g���^�x���gZ��3�oz��8&�L�t��ag�v��;C��3�;��!�� �ۄgZ�6��o+;C�6ٙ��Mv��meg��&;����P�Mv��m�3�~[�� ��m�K���Kˆ߶�|}�o���?�L�v��ag�_ٙ�>� ��ΐ>ٙ�|����|ЙV>��:C��3-|����|ЙV>� ��P>�L+t��Ag(v��;C��3�;C�`3*�� �Cʹ�f(j��fZ�P3�5C�P3�|R3�6C�`3-|���Q�P3-|�ʇ��|��9}x��!}���>� ��6�I2���!}�҇�i��̐>� ��̴�afHh��fZ�@3Jf��afZ�03�3C�03-~�⇙!~��?� ��P?��\?� ���P?����afZ�03�3C�03��������9���!���@�2C!3-���!���@� ��@�L d�Bf f�3C133C�2 +�� D˴�e Z������q��(-�(-��˸��O�L�q�e(��L/��� (-�J˴ʹ���2.��L/��� 8D[�|_��q�ʸ����ʸ�2L ���?�L��3d�籕!X��?� ��ʐ?�L�V��ae�V��+C��2�,3�OV��ae�V�g�leZ�le蟭 ��i��!��24�Vf��� 4�!��2���2*�� )4�i-���BSbh*�jh*CMe�!T���T� ��PD[��D��DŽ�2��xL(&Øp�] +�d��PJ���R2� K��ٰ�Ɂɰ��'�R2}2\J�sa1/����@1/�ɰ(%ӗ�d��)+�R2m%P��+�B2^ ��+�B2^ �����K�"2^ ���Z��L_ ���Z����ed�Z���'�B2 +���� #B�edZ12$�F�&�ȴ(��PE� U��iY���� �h$3��F�4���F��q��bd�9B�Lk�� �Cː>�LKZ���eh��LK\���eH\��.C��2J��L+Z��I�>i��=i���!{h��=� ��̐=�L�f��af(ff.d��Af(d���'!�|��'2����|��'3�ʇ��|�ʇ�i�ûP>� �ʹ��fh�D�ʹ��fhl���f��I͐>� �Cʹ��fhj���fZ�P3�6C�`3�}��5C�P3-~�ꇚ�~��V?� ���!~��V?� ���P?�̏��f���f�hF��̴�afT?� ��̴�af f�bfZ134CA3��� +�����V@� ͨ����@� ���@�L� f� +bf� f�UPp�"g� r�E9C�3DPrfn p�gh p�58C�348�"�!��"��i��!��"��iD�A� �δBg��Dϴ�g� x��g�bg� v� +bgZ�3T;C�3���*�����VA��*(;C�3-��"��!�ؙA� ��PA�L� x� +�g� x�G�3s�3T:� +"gZ�3� p� +gZ�3T9C�3���*���ЙVA� ��PA�L� t� +BgTA�L� r� +"g� r�U9C%g� r�E>C�3���L���a[U���#(?�*(>� +.��Y��3=��3����#(>�#(>���8��3=��3����+(?�+(�� + +и�4��4� BEhzEh\AWp����߈F%h\�4��4n� Dд"hh ��BhZ!4j ��"hZ4DAC4-�"��!�4������� ��i �q А@���@�(>������8��3N��LO���(@� +�� +�8�h\@�^@P������ϸ��3.���@o;|��.���X~�P����څ@��ECQ4$E3'DCA4$D���� �i ��@ DѴ�hh ���hZ04FCa4��0�QiZi( ��i��h( ���hZq44P�� ��� ��q�1 �� �!�r4N�MO��(G������8�r4N�Mo� �(H���v��h��hh �FDѴ�hA Ѵ�h� ���hZQ4DFCa4-�b44FCa4-�0"�QQ4-�("8]�.\u��� �h� ���hZ�4TKC�4���4DKC�4s�4DJC�4-�P"�!�P�A( ��A,M��, ���@Y��@ Ӑ@0MK ���A�@8Mk ���i� �f� ���i� ��EMC�4TM�*�����4DN�"�Q�ih ��5MC�44M�(MC�4$M��!�p���@4͜@0 �(�eiZ�4 + ���Ҵ�ai����aiZ�di�����iZ��4�(�?0M�����i�?,M����ai����o����, �[eiZ�V���^�� Q����e�V���J���[j��*PC�V��ֿ�@ �[j��*P�� +Ԑ�U�����b�����+S!�o��i\�a�*RCW���U���A�U��p�!��3��m�S��f��!������U��p��!��L \ejZW�����g�մ�B5*�*SCW����U���25$p��i \ejh�*SCW����U���B54p==�� ��� ���@H���iDԨ��*�iDԐAD DԴ JԐAH �Դ Bj� �� BjZ!5dR� "jZ5dQC5-��2��!����AX ��!����A\ ��8�r5-�b5��2�����q�j��e�4�q�j�A���A�wP�������qk�A���A�w���EkzEk���5���i�9�%��vW��� +J�� +J�PAd Dִ +>cDz#��Ek� ��EZ�"k� ��EYC�5DY�"��!��"��i�������@˚9��5TаF��i��Q�j(�YMK�] -��!�v5��v5�а� ִ"k(�a I4�iM4�!��5�"��UѮ�,���E��F\�LJr5����p�LJ#z5@���D�O�K�x~,]������p����5}z\�Ƴc�/ +��%B�/ +�x�P��/J�x�P3$V�k� +�d�W�k�B(^�W�k�Bȃ�B(`ӗl�F(`�5B��F(_�5B�����5B�O��k<:���C��l<:�ia�(��5�Ѿ��Ѿ�6�kh�}M��} u��PG���Gi`C! l~$�_��YJZu`��f�h�> �%>�ǵ�%l�Z�5����}��,�(�}��,�\��ĵ�g��\$�S��5����_���㰯y�r˸8X���˼#��k޿L>����x��k>y�ֆ��3��5���yX,�r�6��_>�5q��ZN���{s��>���2������5�o�T#i����g�k�C5.#��ć����}�bx͝A�&�ާ +_3�� _o��,F��q�s�Nw��S\�5On���<��;����*.g��<���f_����yr��;�������~v�t��D���k��|��i_/屉�|M\{�r�_� Ň���X���E�z�5�\�[Ѽ/�g�&'}��nx���So��pξ&ޫ��;�z\���kާ�_�x���ؕ�xM�Էc�B/��5k}����k#�51���k�-��k�U�9��Y���f) ʝ��,����Yb�}^�4v����ݱ]���ig��p�=ޞ�M���|M�,���l�,¦uaCg!6tb�B �!�"6���Z�׶|�c+_�c+_����8��5=��5��|�k+`�k+`Cm�k\[��V[��V����kZm�5�^Cn�5-��r�����kZk�5�_Ck�5���Z+_Cj�5-��R+_Ci�5���J������VZp ���!��5���:;�:��i����Y| ���̝��Qg�k�Y|͜Y��ʬy�2k^3wּF�5�����Y�2��!����Y�*������VY|�* ����5K'w�k�,����k~D־f�����g`��Y�����Q�Dl�>��}�bC� 6#}�҇��}�5-}�҇�!}���>| ��א>�V>���'_C��k��א=x ك״��k�����kZ��5d^C��5�|�ʇ��|��V���rS��א>��V>| ��א>��V>| ���P>|M+4���kH���_C�ƃT��5�}�ڇ��}���}��ϾF鳯��g_S�3�Q��k���ר}�5j�y��>��ϾF񳯙�g_���ר~�5s��k�~��ϼf��y��g^�������}�\?���F�����ga���ب&6s�Ll@� �،�k ���kZ�5_C�5��� +������@��������9��*����VA�"�!��Ax ��A��@| ���@|Mk ���kh ��E_C�5D_�*(_C�5D_�"�!��"��i���� A|M� ���k� �f��}�*h_� +������ +�ר��5s�kTA�Uмf��y�*��Q�k���(��5��}�A����y�*h^�tzW�F4�Q�k~Tоf����*h`� +Z����QMlTA���&6� Ć +BlF�5T_C�5���*������VA| ��PA�M� �F��PA|�\Ax �!��Ax �׸��5���5�`�GP��WP��\H�*X��GP����q�kz�kA�GP��GP����q�kzEc\A�WP��WP��􃨂�5���5��|�+�z�3*�����*X��5_��k�@󚹁�5j�y�h^37мF ��Q�k���(��5��}�A����y�"�Y:��5����y�h^����@� \Y�"lZ6$bC!6-�(b���L ��q�k�@���@�'�|� (_� (_��׸�6��6P����i�q�k���5���5.�Fܪ��V@x �א@xMK ���kH ��5_C�54_��������i ���@| �״Bch ���kZ�54p �˱EM��q�� +n��"rI����!+����,)Ѧ=m +c,_�����\ ��H#އǶ�}m޿�s�{ݵT��V?��&��meG޼?��{��'y��'�=�6e�mY��[�����{��6�'IJ�ck��ㄽcp��x��Tމx�XC9om�۩Mkjg�X���^-E��-DS��=����6�����;b����7[\𷌍m�8 �O�+�pGma*y��9ۑ����s.��1.��.ӛ�!.ι����čWQқ��w�fOq���!�֯�m�ڢy'*��Uʛ8����]��f���,m�NK^P���R���F�����:Tc*�M\���?8h����7�C�v��D�.�������N��)޿��_����������g��?��q�q��tg!�g!�,��8���:���2:���N����'�cFF���%�}pH4���h��i�f�>84��p�F�������j���h��� ��F�,v:�4P�E��H��q��:��X��B�u�B�u\hi���׉_Xn�Ɇ8�7ę�� q�go��>{C�����F}fC��3���u�~8��x����Ù��Q��:����ס�x�,����!΀� �iu�Pg���,���\`�8��8��:=��u�fy�Y^��Y^�m�q� ��4 �8�;N��i�n�N+!`�v(!`�����ס�x��Ay2��!�x��A�,�s8�l�3W�[⨂�G��8s�%�*�-qTA�ę"�-qA�7Pf�'Pj�������^@��b��bvZ1;. h�D���vA܎#ܙ#��q�;���N� t���8� {����8����Q�7�Aok�zo����ƙ3�q����Ao�3g�� "w� r�ePt� +Bw� t�e�C�;d��2��!��2��i��:�i��B�!��Bw����bw!v�bw~���B��!��B��i!��(��R�i)���B�-���whaj�{�ڽ;�Czw�л��1��8��w�Q �=�TC�w�C�N�!��AD�8��D��z�=���w�C��{(��s��q!<�!�g�!��9��8� ��C�{�mr�Co�3�mr�Co��z������F=�69�C�3�л䨇�1���%g�!�G=��CO�!�� �x"���Ca<�ӂ�!�0��iA��(�R<���z�⡇(z��i=D��CA�� �x"�� �x~�ӂ�!�0��iA��(�(���iAD�DAD� yb<�SA�F9s�Q���rDo�3��(��(GA�N9S�Q���q�<=�XQ��=D���yC�DI�ąaA,�3z(��Da����V��J�����|�P�g��s�!;��cAd��Ȏ9-�lvC�1GAdÜD6�!�~ � sZz�<���2)��(�� +�8� zzz�C�r��i9D��CD9D��"z�C@=��z�!��zZ=��C%zZ=��C=�ȡDOϡD�sX��5���5�衆=��@O��@�k(�� +������q�0'S�!{��g5Ԟ9Đ=sZ �3��g1dӜ9��C ezF �z�b(�3b(�3jX��+��=�M�c�i1�8�����k��q �=�!�g�!��9D�8�О�Cl�s��s�Co�3�Л�(���!ʧ���z�����=d����(��3��[ਆ�G�j�mt�z�pQ·�|Zq>ꡘ9����|�!̇�|Z�|�!·�|Z q>��C q>?k��i5��PC�5,��Z��Q a>�P̧��C +a>���R(�C K��.�wҙK�t�B藍z'�9��IG)�N:J��ҙR�t�B��S��)�8�h���S��Y�>.!ԧ���b}�B�OO!��)��8�x�9��>.!��%��"~\Bo��zK����RG)��:J���ޗ6�y\�~w����*IL�K�Ɇ�Tn�KY��]�n� ���.JV~�}���w�3��ဓ�&�����+�3�B��3 +#H���B��3�B����p�!��*�̴?��s�uPh!~V�?����-D�ϊ"��!?���Y�B���"��!?+b��%���5D�ϊ"��?����YQCD��"��!?+r���C���"��19D�ϊ"��!? ��YD��(AD�""~V?����ED�ϊ"j�("�i�g�PD+�3SD+��ъ�(E��:3E��:J���RD��3QD+��A?F������1�������YSD��8�ED�ϊ""��("�~EԸ� ���?�":��J5�gE5�g�D �$љ�e&��3H"��$��Ί$��H"��$��Ί$�0H"��(IDq�IDq�D�CI��YQD �E��#�2�L5����A���5A��DD�� "�gE5���?����Y�CD�(=D��!�V��?���=D�ϊ"���?����Y�C��9D��!��C��Y�C��A��=���("�t�ߙ$r���'��YE��I�-�h�? �������H�?j��8��̴���(m�u�8��:3u����W�8��(}��:}�u�@Z��QH��Y�HD �QC�Ө1@L��o�\�����F��� ����!?K��5h����%hH�4����M�0 sg�d�f����&�����*�D��Y)����v-���DT�Y�Qe�D�ʓ.�J�����>"ȴ���&j�i5 +ȴ���&j�I�d���9F 2�QÀ�c�0��D�RH���(���( I�C�PI Z�����IH���h���JZȤ���M�G zj�֗E�j����3~�+�����������V�;���}��՛��?}� @ +�Q�m�3�@���w�|ud�?���ӷ��o�t�4�������ۓt�������O�G�We���3��:9��X` ���O��ୌ�z`[�j^Y�,�V��� [�;�y�� b��Z�~�����b�����|�������U�:'�y 7 �I�� +��.�Tň��96�^�;{œ⭐]ؙzyU:,Q���g��b�x��N� ʼn�����f��d�e��B��TIγ7 �(�*��5Q9�Ϙ�/B-뙒�A��f��(0մP�L'x�*��:մ<�U�I�TS���T�צD�*���i� �#G�y�Kǝl��x��TCO-L�Ҧ�#�K�zz�J��.2r�Re���爜�穒6.;���\�b���������ǖf����$P� �*��(��<����#�m�>�ȁ�R�[����sm�m����S�$t�}5A�_-� ��ك���˚��Iΰ�� +YMrg�����.��.���h(�kCEb�@��k���7���H�͎ZI�A2�E�_v;Ӧe +� ��=�.@��$�.E�/f/�˗x���v�0[���Σy��דPp�/�d7񌅓_p�Q�#} +M�Ό���_���r�a8⊒��:HU�� ���z�q6�]�+�/���▖�[�\ {8-��i��q+G��B{6�i��\��#�eօ#�C�}�p�I[�\ e˶r�����n�x ����2�.�K���K��B��Ϛ�tF%��%�ʢ�d~%��"�I��O_� ^x�N�m�3���F�c)��&(�XuT+�Ub�Ua,wuԋ`VHaQ�T�;���h���J�FSxx̸��I+�9��K_O/���A�C�K)�jD��M����b��f�������V�tgJ��|��[��K���=�ґ� �[,]� qoKG^$1���E��X�H�^b��#�����|3��$y4Q"N�t��h�륣E��X�X�CK���y�ؿ�|�u��� �y鸈dMX:��� ��t���bj�}fNac��wY�:�߻a ��A���$u�׀�B�"���պ"���$�~!{��� G�ޜ�v�E+��B^ˍ�J�̭P]��_��]!(����#� �ۢ��gr"]����eW&~�g�<�G*��� �+l�_�F�J�5�� �(�eYޟSRSd�X��c��;�Gb���-S��l�NW�GޔA����E�^�5"e��j>�W�8 r���1D5zt��*�� �%]<�8��,q@��)M�GP�J��x �W�Y 6�L��,���d�Zn�.�Ш��i�{yD�xT��B��f&�ϓ��$������ʶx�Sq��i�"�,�y*z�u�6y��S-���L����c�����eT�z�U����qUm�v��0�_&������n�L���Tq� +���g�����ɿ���훯�����ۋ�W/O�?}��o��ֲ�Ӓ��}���">]��&��k�Qܷ~��6��~�����q.R �2Xe�;Ο���‚_m�S4,��;�=\O�B�@��AOb�������� _�‘�S��~���S�.� �N^NQ܌��+8����� +D +�3|�7[��1�P��bCg����ʓNh:O�rsa����l���3N�h�3A��I ��F�<� +� =��Wz��������1���*B��_���R �5�\8Iu�t���w���z�ڭ��6~r 6����� ))ux�|g���x�s�hg���%H���Q���-�A��f���7�����ӎ3�ng����FA;)�F��!�гgb�8�� +�˜��ay�[�_����r{0.L���pЖ 4@pX>� +V듼��O��� +�8��l�f��u��LK +g=(�(x*c#�_A�c�H��M�]ɴ�����Hx�S�d ��y$�Q(X�$���؁u�u�^IC�P>|͑�@b�11O����� W ��.A�Ҙ�L�����X��[}ꡔfD2$��8 +�3, ��(�鶎n�����x��kύ'l'OD����8�Q{^ؐ�����S��|Σ۞���r\�80[g]�s�6Ljt��쑫FxI�n��I���W�&'���^��(��.��rlr�˲�쉻��D�~��9u��H��x>�FU���d�@\��)ΐ����k�~�b61�W�8ڳ���`�ǻ�� B��t�٣Z��1>�FNY=����K�]��s#OH +U�k\y�C�q��RtY�V=�B��ѣ�QfGt��F̎p{��;��Q ���R��A��Iɱ� =��B�L6fDoa��I=���θm���>�ı�2hu��Bѵ�^Z�9;�xT]z^�0��JT�V�L��' SN��7���ֆ�!���B4i�T�PR{�b�։$�I#=~����d)T�0�Uu���SH��j��+�օ�Y��i[��LP��t����q  ���a�a��>�{u\�N*]pel�'0K�f��"��<���Dio8T�O_sN�e��� y �I���y�΁g +Mg�@��05��i}����2�u���I�0�6hϝ� H +endstream endobj 84 0 obj <>stream +�GuՌ�ο�M^��9�RA��yY&c�RR�D;}��Z�R�Җ�ot�F���уT��u���.���&4�����*\���ɫL�'��Þ�mqރ�:z3���7;�,]�e����mEc��TĪ�9@W2t}Ɠ̉-��p����c�F���6vx:�?B[f|n᫦�qP���6�(�3�* +ȩ�4�փ��p���;`���a0λ�>碝����d���z��Ip2��)+R6S�2�&KA���]x/�F�޹��"����>�zJ�Zjn�*{�A�JHK�|Q��Gt/j�w���ơ1e�t�R�߻��a��L�H &�S�6^�I]t>� +����Ж+�u�����ʥ=y�Ix�N߮G!�ci?gӣ�`y:;%v :zW,����O½��'W�q��y�/�2hK���c�e Dw��L �b��=���#�S��EY��[�AWfa� �rX���|w/9e N��N�~�u�����:p�i�N���A�y3E�o 2o&C�_�)����b:�18Y�d^R~���.��8�C���1� ⌋�ߒ�m����N�mY�ҍP�y�U�{]Ġ�q��SFI< +r�k]�%aP.�*%��x�_���o�9N 4��M� +2��1��Cx�]a�L"�Vp��(X&��}Xo�� "6��jc ��ԩ��4�E��ewq� u�y�M4M5I�=xB�j���{��1 ��"�6?�,0�7���q�)jW�^�D�0�t~��P��f���2���U��Dy��&O,8'��%�� � �Nެs�, &Yq� +&<ȝ|Y��<�x[jq�:FS�������.7tb�3�DZ�R��F�&����.�f��2i/]A_lX��1���ϋ ����i%l�ʎ��C�� cr�쳫���r ��k��'5 � q�O� �� 7� uh��J@�Fܞ +�YB�fvny�L��)~T�s�!8{� ���1�<{rb3�,�0q�t���(S2�X%����M��"��z�d�1Mr' ���� � �fρGS�JL ��晫���T �3Y!q�J��3i� +�.7:�_(���ѫ�ۆ���h,��J��q]eU�64��=a[��S��;C�r����ai:bO��S����B����QDO��P�ŔƲ�*/>z��8��B8� +6��h�ء� +��(Sܥ!��l7�s��q��P�'��anɆ���(i��,m�>e:F�G����O(ؽ T����9�g,�X+����I�+9��?��^n�%  +v�pN\��)�#<�tM�)���1�E�>��X7��v�_ݾ\[I�i=e�|m7��;�P+��m�O��2���.#�?��5^��V!g������tyK:;�WRa�/*���E\�&tw��da����d��/�[�|����Ϲ�4���&F�0b :a������%9�!��兩j�`��#�-EL6�3��tɎ��֌����1s������dEd;�4&ރ�x�6�/`� �o���4�dOjdbE� +�� ���D����j) faK�X(�$č��.��Zq��_��̑3�H8���u�ɉ�� �d嗇�cP�� ���#l7yGj"Zv'��U��7�}���*����B��,����V^��6g�>£�t�P]>:`��ȼ�����Q���:��_x��=u��':�Hb��l1[@� )��\�3�>���9���I�>�����qNL9.��$Q[���ږ+�, �}�Rm4ZN�u��les��PVё�A���|��Gy�IRo�'֢�2��������37.�>zٚd�^F�Ĭ$�])@#9,���dY"y y=�9������.���d���$���n9�����:ii�$ '�]D�FT�&�6IS�4�"+<�@�td��_��V盿��f� +�u�b���{�X�8���ױGN��u",0��ܖ�gb�%%�4^�`m=_�e����t5�5&�i�Bk8��z"�0���E�J�a���i���!H�u��xU���E�L�|O8��EJs1�b��U����2[�@!M� �h|�Rz�_��p��A`��w�W��Ҹ���WI,�†�F��F�������/D��~�k�ɾ���~Z�Y�y�e�j�Wl��s���J����Y�3t@��d]86N��R��{�}#�m"y0MYV�{&���+L*#=o�K�1��bZ����.L�%�E6xYC��Ppb����;;?P�J!�)��cM9�̱�13/T�"��&z^��T��qCc*I�2vN�� h(e�+�h#Y��J�aM����u�X� ��؎e��޸1��ŎL2���I���BP��:?���~�g�f=yry�о�{-���J����k�ug�W��SH�9��-J�r�9s�>�N���%)��N�cc&1/w����r9��qQ�! +��G�5���c� +ԥt�z���� bb2���(4#Na,%*��2��N3�N�[�r����^��Q�����R ������vy�c��<��RJ��׏U<�YZx1���7&���o���q �:� +�"LX������h4���гJ�B]�}i�#�{D��z_8��2�(j�?K�"*^ ]�DrArI&A"���q�1�\���&')�g�M�Pڃ���kQ�%�G�<���"[�m9ZشH�a��$9�8IĿ�U���ʓ�4��%��,2���c�Hz�D�e���OJ��ZD,�Q$�����>�,�f�dg +��˾ ��@J�M� ϰ����8aeG���n9���}��Ǎ�d�0D����%Nl�rX����"�o9�U2*�q��2�gy��� O-s�b�W�����r +$��&p��\�@9 t\\AG�3E:qq[fS��-;�Yl�ˉ���ɢ-b�����0p�3y�Hcv��S��Y䫝Xz#��U#E�8ܸF��)q�@��?��ƌmv+]Eb���-��z��^�#�=K�ZO�%�eN��8�3K�?u�n��Ai�G�����'ٟ�>>�O���].��!�K��m�����=~��?��߷O�����������9 3��J����tR2 }GD�$,w�Sd,;�Py���v!�͞��/��z��}��x�P>��~����c���=<�� �Ӭ���!O2-O�7O�/��=�l=z�ξ�=�ާ�I���{ȮY|U����\��?I�D��j^����}�������o�ُ�%~m�zb�bE������7^[Q�>���P�yh�)!�$�!{X~�̫\��(,'�"�Tj�R;ӸE�*̬�r}��M�"�v} �T�������:ۜ��ݳ)WLJ�V1H�B�3Q�I˅Ε��J�d�_7.t�t�r`Y����N��^���pc��+T�}H�K�\s��K���Ǎ[��Q�l��1��5b�Ra�B�Um�6�@Zig�m%��.�K��E+� +�"�� +d�#:X�5���J��24I�� k>h=86S�Ƞ���v���9�s������:V��lu/�8�U�]7�\�s�M� �}�%��V��>�� +誈�]�v�� +��.=4(�遊��� s\5��%�X�WrIܯց���q��?fo�{��} �o�Ìs������*6� ��e]�0hi���;̴�Q�F~6ip-)��N��W�c��5�ķ�0�9��ã����X�Ͳ�Ox�F`�J�Rn��A0���bj��v5�c��@f(bC��nF�������I�eKa�0N �h� '���{���.�r�t���� ���jU��׍���u�A�Vo=(^U-`�I� U �2Z�Ե؍�q�� +�d�b��ȑ������A��5���9b��"�ߺ1�h��Y��8�����(�;�ޗ�ZaW@����@���sR\7�ʤJ�>���- '�]��� �b�&0-�9�:�?L���L�Kyu'����}�;� ����Y��6 +�P�f���%hc�:����.Z���~� =p� 㪧�)wK[ǻA6m�B}zb�����f)�Ø��:a����:UD���Ze�y�IvRA[E>���}cg���]t.ڽ�9���1�J6&ps�s�,���)��D��K_"�����)a\�[T[ +�A^C�h=� +s���~���^C�Bv�.MH��=�H�+9����Je՘C cǶA2Pжm�c7W�(�8r����'��k+�+�M[&Z6�u��e��T��}���%Y/)� �ޝ���8W��%�1�V�(�H\�ݵ^X�ի�l�,د�AU��`��My�`\�b���P�F0ȐJncʉ_�g��yN�r��ß��^��h�΋�� {Nl�S�&$[\f6!����T +Z��&ZF����J�~��C���c^��X�#�n��YA��+�1@��cO�3��kO��l����ۧ5ȁñ�K���rF�Q����dGa!�;���RN����݉dE��r�0�B�%�:��ș����:'q͓���LT $�_�Uc�*���Gd'�W�:�u�����$��8�(Ȫn�38o3�|�ǐ���h���D���`E ����sG��io �tc�j�����ځwk}Չ�#/�iO��u](0�K͵�G���\t[ؓ�T�c((�׉I�8�P2,�r�%��*�k�6���#�B�����m`�P~v�f�M�؁W��������A���5�F8���x��0*��/ Az��\n�j�S߻\ +a��R���O�t���u�9 ��� �R����Ʃy�eh�Z.��85�P>?�X)B�3���Uęc���~N��Z����=�Ǡ�k��}�ҋ�$��So�0���U��qԙQ'o�e�U+ܤ|���E���6 N�2�� .r��,��a 2������4�T,� zI�0��_b=��K����8U�WJ#�掍^X?�v�8�`ݘ�ʙkU6夀t5�I�z8�"(��|�uK7U�PHv�� +��x'��z�1��C ++�VL�]�j�$0T%��}��g0Q�N����O+<�H��m3B���S�Rq�e�r�d'��jB"�X�ʙp�m����[B35�,*\��"L`+�)��g 6�r]8�����>�*T��U���V�� +d���̵��a��f^#�ym؆"��:j�v�%��AQ������O���'߱U�&���ׇ|��k��֠���+����8�!d���0�k�1�"�1'l%����DZ)'8��)�W�i]�V��'� ����i�SF�4�t����,#��o{�e��&��ux�N�Gu���l�|mFM�_��j2�;)���,�b�s1X����y�>����7}��.֭�\���ug�\k��^����׽M�rO�{/"@��������ޚ�tl����.,p��Z�l�+��b�hC���Ƥ�K�g�a�$ǾŰјl2��'%��w&�T�a� +���T�ƹ��*�I�Ve� +Z"Jn4����aA��R��,V��wڸ��c`l��&\�zuPS3+� �6�,��5q�u�t�KfpH1ۭ7��^�P����gW8<"�ӠqY +����h��qJ�9�N�;�i�P x�k{��ig��ͳ��]��1���$>�!�H0��{�ٗna��CoKa�N}\�k�g�������v�r��LOյ�񆓣����Ӑ� ]$r��DƪS��E��|�6���&E3�1An��H�SG̑�)�Xw3 �İJ���L��!@��5hϳ�����AW�&��j�Br�+�h���o�!_��>�c �o25�Y �`���� ���MQ�L“��h���j��Rݷ 4{�W���8�-5�j��`O��.�)캐I�}n��p�z�ӭ`y%�e���P�k�~�A\S�* xD ��X$� ����lϢ`��u�hb%� m�1U�p8 �� q�$U�M�he�8������*�Wc�z�o9�j�s'��Ec�� �*��Ơ;Q����Y�׍�o{�n�$�����w��Fu.z � Ng�f�!����pxm4<�Sc�Q� ���`z�ʀk.��bgm�mbMqT�J��M%�X��>��L���q�N����6%}���mcd~����I�~��Y�H��������~n�jj��v���£O*Yi'Q�b +W9` ω#���[D��& ?��mBi��|�ڞ ���j�`1'�� #�4^$���:��~yx�� �#]�~X��p�#|�1Nm-x�4)j��$�x�Q�,��d�3V(!���S���.��B��g]-R�˩ M�9k�-����Ġ��[pLTL 0��,���e ���ʾ�[��6�]�C(Zgn �j�+mE���X �A� ���!8F�rD2ρ�f�^<�3��,��%���6+br��_�&�4����{��%s���&Gt���n�6��N*����8 +b�98��)'�\)mt�Y���zt�Ԩӈ[������o����K��&�>�&�w��D�(-�U�UO S �m#|WW(�R�03�$kp��Xx5J��xz�)�niz��=�zA�{���S�ވC%Y���#��錛Yk +�$��M�� (�0�*KcU�Ĉ{�踬?�W��:O�h��I���p�FX݂/υ�yQٺ"�fҭ����(I�4ۤ�@� ����dJ��s�@1� +e (��)V��SJ1d�����ϸ��i��l�8���a�>�\��8�V������C����Pp� �q��SW����Nj���M9Y3*J���#�x��kFJ�[����Tsf�7*���66���<��Bi1���K8��}��(j���YG�h��Ъ�%��y�|���E +�M0���R +X����c.�ޡ(vq�AM��)�i�l�o���A:�2 �}4z�.s��8����v���.���_00yo"��4X��_vV�A�b9֔��YP�V�3�iZ̺U�_��(��7�Vc���EY��xl�ۀ��3&<Q�� �S*�Z�AqF�U��9�q+�7�����P5d�k�&��&�!���,j=��o�^)�m���t�����PƏ�{�ԋ����$�㺔dZ��R�ҳ� +R�]#�6mb��eX{hƀx����é�_��� +gl���rH�9p�P�#��R�ȔP�\1�8��99�H�A'P#كBװh��`�"Oy#�OF��� ������NԴO��1���wGFuY��g\�5W� '�� +h������"j�78���Y������^1/l=�B͕�� �]����DG�:�?a�[����k% �X�#��I��j�{%�����!N�O#\��W�6���z7�D��H��ɮU��Rf�%k��6�@�<��1�Q�*�A���� �gJ{&LyIbvc6�Wo�br��N=�d�EKN�a=HJJ�EQ�B��z�)��R:����T +���↨dZ׆k��L~t F�Y��c��ѧҫ)�b������:���ܸn1��"= P0�O�c�\зB�i�8 �]�*,�ק=4u���@)�XT�E��<����mν��j�\ub��N��7��m[� +Gi��N<0�\g�� � �V�~���z��s�X���B{�bdT��K�&9$�83�{����$���cR �AhD4ק�P\�[�����3���z,/A"�Y]!��SD��G J��&���2wP&�d}|�n�����qUt�ӧ=��c�w0� +UH��71�Ia�{ʃ�-��(x���p;ڰ�Q����tN�`���%�y�x3h�HU�}�4��f[�O!D\ q4{��*�c� ��8�v��&����U���"�!�PV,�D�`/c��O7�\�#��l/�x49��/�X�3 ��̓I�^m���m��A Imރ������zh�6tX��})Jd�I�>�����-^f�����'�+�O�~*���zJ@ �87�X�6�'%u��p3�`Zȡ|�i�� +š��<�r���8j�_�!-*!�D��'g*��q�)ifF9���^�Y�� +��Tf <���e��g]�R��8`>=�1�{�7)�윊TT�F���xK(#|p��a�_ǫ$�g~&� �1Q���h�R1-��S1�E�m�}7M�-o5S����wbb�W>& +0�7�kN��LЂO�C�Ty�[8�2�(!����j| �n�x�����z6�(XM�0�wj�=��Q"k�E��jg˜�� 91E��|j��L@7�j�k&=e��4� e U|�{b��xS��+�y��,=��f5�������4�:�z{S:z���:�vg �k瀧#B��,��{B�F�� �T�o�����(j�I�U�Z��� �A���g}ts0�2�'(ؖ����C�2���ZhpR��1@8ї�T��f��׉��G��`z +�-��jV� k: �6���oTP�w6�bJZ�U���.X�Z������nd�㺤%����2���S� x-JT�]�!�U���bw6Y&5I`+��� Y�̈M�zc,-V�f{Z�V"�b� F#~�{>�e3K��j��3A�H K۠L#��)n̡�2W�l�ø�����ut��U |B�T@�\gT)�d"�/v؃�=�z��L�#?! ��iK�;�F��3��}ӂLk=�>�5Zց�s���r62�R(ŋvp$s`f�G7XLq���ɣ `cEGPul��� �BCc���n<�<�j�%'�.ⲩH��D�`u�8!8���FX��*��M����ߋS- � ���j�� �7u� �9���`EyYuv�l ++ uی��b�z���O=pui����R-KD K�!��F`�(BFc��|�U�*N���M���P�j�8�$������2����5��!�B.�XF�䗡��͎�L��>:��G�����|%�o.F%�O�ӿ� "��� 66�>�;�N���44he�&����3/dR7d +ڈ'{�R��}8ԸB'��%k�8n�-|��1�L +P<%����y��O9�}nc;��bj�i��� �>W@��ևg(僅�S � Q�P�$N��jl[�4~���{ϛ( g���� �`�k��q!���/b�h&�XF LR����$#����vej\҆��{K-��z���꤭�� ���&�I ڶ>��Pg�^�X���f<� �7�>out��u����K��(�>s1�#�F��4+d)�A�����Ա�S���sเ�s�\���Do���-�ta���X3�bz��O*2���R%T����T���j�`�r���3�� �ѯ7���� +`y�逝=a!������4�`� #�M2�ɱS�(�cQ��9�Q�|�A�5U��>���L^3�k�=��,�X*V� ��~��wf$� +ۇ$u@�?aM8��Uac���#�����hmɭ�&� j֤���ņ����� �=+�C>6�c��$��|N�z��i��dfb!�.1��Eje-6Ї:�[�h��*t�Zń��S�laP$[k�O)#1x�fm�H�ˎ��4ِ���{5������唺��#�s$S��b8�Q6�j�vc����0+�`G�����b�S����ȑu;c9����a:?` �b�pc�0��…}T��E)+_�GA���g���x�4��1�8<3��:]v�0 +�b�,������K�=�M{�<�5`]����$#�L:ʫL%?�!�lһ*kV&�`9�!�R�Q�f�u 奦��|�����ٴ��0��j�)��eZ@��3�Fzy*L��,���̋P��w�L�E���{�5i����c?(\�*o��v��d/=�!i�>WzЇ�j[ڣ�c�FV�>%�M~*&"9K�!FRL�N �"" +��%�9p6x���!!VUIK�딊�0Xq� ]���H��m�9hӦ4K>�}���F��Gz�yb{�);�sfh=LF �)�8���� ��5����_ �zIk��/*���R$��)�=�T�7�d(� c`��i�Tyx�Q�=�.S�V󧋏��l���O��H^�Q)��H��ڏ�_ uk��Ta��(xh�k�� �$1_�WH���)�dY@5��\�d����ZR��2���㽡�I�I��PB镼��L�sު>%OϜ��/T�"q���� +2MZ���dT�����Y)����TI[F�˘�x������Xʩ�� �<�3���˛��kó�Ũ�=k����#�a���a�ڟ��RC�aXV����c�r�����r�}e��!joLb�ϙ7>���|4�F ���6���3�F��g���%�kӒ���5�j��#=x�pq⠭S5Q�pԜo��)X��`:�k��!�M���glt�52����(�E)���p�E�l0�6ː^d��m�` �RE�9�7������7$�n�����M��@U��Ĵ4�A5b�8�r ��< �Pa�v�A�������0��n0�� *jl^P!�\Aj;�=50;�C �6S���s��bQ,\r��`�����c��2�y�^��zD�R��C��d�U�0u\`�F;0��²�x�c�N��ۿ6�[� +�87�AE�*����G���ɘ�d�%#��8� !�`ғ��s��O@��e���V Di�E��Z(7��*�us�Ņ�Z^���c��K��"�C�EV�dM�O�G/��S�]�k\�Z7���t89h9 +�Y^��2��Ǖa��� }Q+Z҈�4X�����Fug��u�[׬�0=����5fSdiOaS/VY�H����p �2P���o�"�k�x������WF�Sr�7_����6��^�c�+�����C�#sFc��R��T�oo� ܨ{���=����{�f�o�Ջ����x� Ʃ����Շ6/vQ�Y��!X1h=HD�Fc�� +M�yd�]�V,��S�f(����:�ڊI\z��A�-$fe79�#�cr�Ux� +a�� Υ �:�qQ�Q��y��Gզ:��J<��ϢqC"����j �K�| Gr`6��nZ@�+S���F���-��Ԙ�0º�+Y�0�­pCVGQy���Si݁�Q=<�?�UC��ꓵ����8IA:�Z5�� +� +�.�f��EJ‘툫[&�h��Ibi���0Gq������Z�e�9�'S +B0�St���G�G�$���>)�SWp�E`u_鬱�w�VC+]��w*� �!У�ʣ�Y�Z� ΅Nfu����^�F�Y���ख़�j�T��,m9Ǫ�p���h5WJE� �7E����,�7{�@ۊTC�hL���^�քQJ1[��V&�D��f�r�B6F��γ�dH�0�uU8k��"�� �Q��U&�u����ڪ1EP@��<�&� ��0�v�f��M�e�1�͕5ht�T;lxD9`���-q�1��mw�vlЪ�Մ�����)���ĥ:�U-��~1�Ɣ@Q��T��=9��:�9��Q\�e`%������u���&$ I!Q�<�[����5��5=hY� 9�吋W��P�x�Ü��f�: +_in_�E��9 q'�e+�rY��, �:�~r�բ���D`J�t� +\��D����-Ck����jQ5�� +^B�%y�V���q������T�iMp���`'Ze�֢%\��oI��9OE�8� +�Tu�%'l�9�N0�@Ŀ�@���V��8���Tl�G���1�-�u��\8��"y�x9�����U��pV�6G� +�-N\�@�6+�x;���b8����Y�C�*ɚ��P' ������t��K�#Ӣ�s��`5O�e3&�Q+%�fl.��G�!ɦ�*�6������Q⍵Bz�Q���Q503���L5v���������"M�ްO������+'�)��3�m�;I&�Q������\(H��vE�͊JP���*���U{(f�f���g�Q �N+K�����Eb��/WM�B M+��<�Y�X��赦C�g۵ص-Bp(�@���i�� =�c� +�5���zO�r U�F�m�RFu��1�.0��ȷ��zP�_���ȹ�y�8*/��|���a�*;�+������� �]�"gM}@�䋗�1��Bs�4tL�b�~ Rq�Q�o‹y�JAv/��Uiom����7mn�!�R�M}t�`]����C��h�gңfŪ�)����o��T�� vjd7����P��i�+zj�A�O����8ON�^^c�{��b5 �:��p�����[�����A�ܮ@vM%+�԰J-[������M��n1 +D����T�4������>L� +W��7@��B�G:���[���R���-�\S���,c��݀8������I�@7jB��]��wg�=uR*�[ek�(� F+X?�?`�3�z��C��De�=9Z�kn�4�3ǀ��}��i<{�7 m�z�]��z)a"C�Z�TA#������D���9���c�fPs^ J���@Ҳ��b��0�� �*��qn�5� -���@�1�8]3�sA�D���Ɉ7�� +s��>.ߥ�� �15� �7�>G��%�a�|;cZs��!U�,V"-AO�Y3ˑ�Z�J~�̔����6�n�������Ca�g֣���Ƴ�*T��ǼRT��#3�%�A���)K�����1xU%i5<��+�(���p�Q�h��0}���O�4E����5a��T�zM��ѫR�UAS�I>���.[VmZ��acP�u�1��� ��/׫.*��S�5���4�X�㝸4/�N9�QR��~��`r�z�8�J�)Π)s��͍I� N��._f��)~��`2�>�>�AJ��)���)%��Xb�T��T�X��k�d�Ib#�M��$����<������^[��yu�T磭���`$��� 5�Mc��M��(�\d��� @ۤ*��ucɃ/ T�L'���%��G���U���hy<5����e���&B���H�ZyJ��aT]�5�'~� �9�+N�$_W}?�+Ws)� �A� ��I�DW/X* ���F3kvZ x�Y��Dc +b~�˰���K�V)N����������^�`V4r��:�ȹ +�ࣾ�P�z�Y�`E�ۨ(�(��$AX��gwEc�m��"Fλ�_Ǯ�Ǧ�*���c}Z�@��AE�cŎ�԰� �S$� �ި�P5۟���b�yj\�YQ�UN2"2�����J&����ԣh2���u��� �&�Q>��R�a���7i:�JOM���SdJ��W"��J�;¡ �ZL�[�bzC�ֈ��zP�-~ j؃]q'yk�W5]�{?N;ɶC�NELDE?�):lJ�����hi��*i;�E�]�ܫ��X���J�O����(��J��u�>ӟS|b}Դ��46Ub_�Y#�a �J�C�s��k�ms�s;j,�-�����71�r[��3�K~'rH��9ת��H/?�.� �0̄�ڽB�ee֩���=�Ь�ޭ�a���xՠ]cuP�xMi4A,�vؘ���� ����>����pr0��0p�9���5K$���j�����1����E������r�櫞�e�y��K���jY��m4�?�i��2[Q�a�^I a���g|�H�������B�����@�©��� � +h���l�4؟� +?7e�X@���TU�8 +Ek����ʒ�JVjb��[<4��F�AQ�}׻�J��7/bo�J�8�� +\���GZ��y� 9�p�+/!�-����Ci|L��9-�)f�e��+�(1��j�a��v��h�d�����lK[�4*��8H�ѤB�\2,���1��ժ����ۛ>���K��So$@�ҋ\�1i�*8XN���yq(>�@?A�׆3�Z3rcȵ��SP �6���4����}�᥇���r���].fR��a�v�+W�+x �\��o4���A�I���-'�E���Z'�sj��b���e��d�j���iidD�?��r��<�*�� �I�r��]g�86Ӆ�x�8�:CA�c� Y���z�P)�$}h+.��W�u���ԋKV���]2f�RvU3��@WT�5Д�x�V���V�*�z��{<�f>��4��9�ٷL�%�QӞ̍Qio��*B�6CJ�#'z�"0V-Uޔlou��e�㘭��x浀LUQ���Z��OJi�ğ`͓Vs��7ͫ:K�F�HCp6SD�I�y��ȵEɠ~)�N9����LS��gL�\K��b����uvRlA`���nFa�Zh��;@;m-l�zrh��ј��P.�u/5a�%���u�u�[����*>`�\oE�U��P���`����¸0�,�1�����FfU� �̧��)�;����$�d����� ��fe��ta���D#|��Of-ߗ��[Γ� !�B�h�R��6���-""� !��.O����cQ �Y�"U�C��d){A��:,�4�X7Nɒ8�@�����N�Ϡe ����s��FÎ7�Cޝ�-��� �X4���t��� ���c�GfQP9<����nn�5H��U�0�C��Ȯ��\$��B��z ���W�����%G��ruBDR �bW;��f��0h�Q���.�\u�t `�n�Scb�bB� +�) s�}��ʽz���l!�47_⹱:��������$ȶ�|ԙ�\�ZQxp�}X�tl¯͍#u�{xr,��#�tZ�eB�3�:�W}� ���4���pFj�rjz����w���Uw�{_�Ū�Nu1��1���u�j+�ei�����"���YF������F�fI�� M�: 'y_�<���e�qU��Ș��Zz|�{B��t +7=7��>V��3����z8���+�h�d:�m�����Ë�� W� �� +3 %h� qXehw04$˙�2��NC7�Ϲ��������q&�`h�*�z +ju6�)Ȅ���J���mr%j�S�h(%S�a�|3�C3�{@f��d�fp�H^������b��=�I���Ձ�o4.�`P��W gɳ���jb�rf�s��!(ns���eĆ�6�L�uPt�� N7�!�k[T[=@{T5;7*���]2�ꄓ¯A��Ճ5[f���<4(���q���!�sg��d �=qH6W�,���j�dj��ؒ��ן�4�Mx�L���@ +H�%Q ������'Sm�q0�Q?�Mp9�SbM~�4���M\���~,�D��QB�Q�H�j�n�)�Fܽ�bR +r���A�% ���4�"��l��f<` +`�j5փ�=��&'�RG!�L�*�=��{e��5a1E�td��ښAv[1���K�1�ρk/�\zW,>E�$�Ʀ{���^6�*9�7���e��0b[x�q��`�ȿD���7�e,�)2n*��#�g5���š���[a��mI��$�֣14��@����3��NE�!+�n��$�8+1�,9� +\�R��T�~Ԕ[�Ae������MBR���q�,��!�@#ʾ��ј�%RGR��n��vNLӽ�U�q���$#+���P� |B�)и9�� +�g1�p��$���E� +(hc�11O�ۀ��FRm�f��˭0X9񜝥� G���J���4ZI*+>`�Ɇf�^�/A@�Ҥ ��$^�P��`��;��T'x\��\�)��L�������|ٓ�w" I��lҐ��w37vV3c��8ѱ��ء�����h� +�M^fM�}�����8v����X��Pz��2��KJY~�ķM&9A��Ь���Ĩ�a����ժ�(�����EScN��z-W ��a����ZI4o��yP��ؖ��Sl�dI��G�"+j��-(V ����㋴(^צkUnm/�)��x��πV���2� )��M&P���5�䪱� �'�y��9Gy)kV|���oO( +?3��%��ײÄA#�yk%�PB�d:�!��`N�S�g���e�.�Aa�fϯ����&P�_cg�>V�x�29�H!�7@���C�L#fH���]�Õ�J7HN����,O�J|��!k�7���F@I�h���?j��-Rhdn��^��!`��(�nlrq�a�؊j>C�/����IES�dQ.C�5�Y�j3�8��$�Js�'5� +�N�ܱKU�R�� ���k �y���*���"I���3�Н�-�f螣7󕢚�F*�6�x��t8��L���Y�W�'�*�+pm�pVYw�\��o0:�YT�,�؛05F�U�x��L��X4�^j�(���M��ȷ b��T�Y˱��rd>���}�6�z8'�nUv�cF@$\T ԙ݇��BN�Fн�E�y����U��$Z_�h%SGp@�!RJ���8(S�ٟ4��jiD;���C�s�,3��������cn�-'��l���!����[� ��,�Ïm�%� ��Gd2���+p2%�p؝G��d��C-�2g�d��QG�JX� �0��p�߭�I`�޲gβ��!MM�-Rƫ-{U~R�*<���ԍ$)�0�Fߪ%$��AT|M +��'+��5�<��� jF)��ĉ*f#X8-�����J@�g�-���[5vT}lC�5Pj�C��q�1��s�ގ 7��b��8j���{gW�>��~ATMF+� �e��slv6��͹2��B>y0��9�v:�+F^��,�N�N�S�bk1<��^^r���`w��7�����\���%T]�j9� �z�j��԰k�QIJ��&��G�N?���u�� #90�0i +,�g��YSZ0�A�|Ld�ʈ��]�l�)�t�0�~���S�c6N~z��i��5J��Z^7q����l�鈁W�C(������6p�P�3 !uԴ���)lj�gp� +��d��24A +�,`�S��f��&��0�`��]����Y�P�{�bY����8h���x�z�k����Z!�N$��D7h�S4�`��I}�j�4�'�j{=�d�qSM��y���R(��7 &�Ob��v7� HL��C������ԴY ���'0Ϟ�GR�!�{)=o��s�Ψ%��NMS��!���ϾE�o��ը&|���K�4Ww���8K_0��Gڼ��h_FpŴ���h���:�g8�)!����M|\���I~}���a,�H�/��X2���e Z��A�V݂ĥ��5=L֚7�������h�S�OU���t��番�P{���DZm3��3�bx���J��6��'P�l��چT@3W5r#�O҈��})��m��8�y�ແ� >��D�x��H�o��l�-S�qYƃ��f]n��$��o�nw}�p}���✠d��O~����߼�������7KW���_��'����O�>����+��/�/��n/�{�?}z�}}s����2���/�>\����Y����b���W�7/�n�E8����}�H�����W������:������\�ϖ�o�\�����6����˯�vsJ�­�����侽~����s�������}u������/�a���[���ť�Û�g��Ѿ��f�c9��� &����n��~�󛯿���o=��K�wM���v������/��\�^^m�$��m��>���m=���7oovx?�~o�s�ѷ��o�������]�z�ۺ�}M����w<��t�p�?\�\����~������x���o/.��e��o�$Y�7 ����4ќ���?̤���ۛ��}���z���x���~��/�u ?�{{y��_u}��s��EY����.\߾�N�g�~���^}���a���#��Y�w�_y���ӣz�C���У�ˡ�(���_,l��o��%��D�ר�D�'NGA�(�ѣ ��f�\VK�Y�er�%���g'��4���~q����g_]����h&������;���^��`�����3�o^���� �.����=��q��͛��_�i=_��� ������~;o�޿������b��~u��?�����-��������훇��n��_�m�n����_��^��t�/TLZD���^���~��g�r~�eN���;m��ڋ}r8����}8W��޴�W��>�W� Y�gn[y���;��4V��x��Q���뇯^_=�`�Ƈ(ֿ��=��>���W�_^Ѻ$��3�w�G�ё��ȵ����u��#�N���y ��]n��������������7�>wǵ��7;X�Q�� +��t/��1Ͽ�>������;<h��H&?����T�Gc����������RN����<��C"�;uI�O�/�k��@�Gx��G�B���߁�v�~��'���=0��v`";��.��@�G�Mc{�� �ƇNd�i;�!_���倩�3���\���"�ˤ�?�ov t�s���{��;��v���.no�n>�����IO�������7l��l�r���/��|}sqy������_���b�n{��AIk۫=�ށ^�{�N�'���W�z�����?�{`��E������ۋ�GJv8tBJv-�a��|�g�G��-}���֫뛛�<o��ٷw��O��������Q��7�f_���@?������oF7�^|�d�v<\���x��5���۫���9./n.}�r�s9~��)�_�����{������]��bo7o�3��]�;+��=�$������y�`ɒ�>�����O��׬����ˆ1�����[�l���������v>����G�Ñ�N۳�G���������j�/��?�GS�u�q �#rH�!��z$�@f�q;p������ ��.��`<��g��#i��u�H:z$=��I[��둴 �<���nH�G���8�C�H�|�I��!%�G�g����i;DϪ]vv�+�ϝ=쌝����$�9�m�QG��<��?�����>�Q���]�?�_ϻ~����O��WJ�[�#!܅�#!<��A�?�GBx$�Fu� G�Ж���H� ��#|o2xd�d�y��#7x$��Ag���;��2z ����_�n~ws���;��>c�y���]YG4��?�w����d��O�?/����'���������3$���r$m=�c��'O��3$�� S$�=EҖ�܏�Ih/�}y��z�˶��˭��x��.gu��^�]R&}hl�7�Z��xΕfr�ć�G��>����N�wG���84�ok��1o��8��y��d����n�� �1��A�X�臡6G��� 4� �G��;w�h����D�z4� �{ώ����� ��>�����������~uW�@�㮦�wn��}�񻫛��o������_=, N/)���s��݇��J���na�v�����뮔�#)q����r�?������Ӆ$_}��P�_�}������ç�W/?�����r���wG�O>����y(�E�I�� sw�2��?55i��E/����ۇwO]�F�`_�l?����o�)⦟�Ya��k�Ή����"�+�;�+���˅�����A;X �"p~<��� 8���ʥǿ<�k����_�^�������Q���)�T�$J'�@���t:*��J����t:*��J��7�t: ��t���N��.���?{U�g*��.�g��T��3�CQ��?x +�d���~������xLFv��q �a�wE���Hf�ft� ����^{|�����Ӵ�k�3u(�1E��!>��c}��{b�G�}G��<��li�Ͼ�xy�����19ơs�ۧ���g~h�l�B�/�A�W>?����{����m����ݮء��g���É�n����i�o�`~����q%��D���Of�:�-: +�� 4���a����ջ���3���z}�ar�^��ŕR��W���S����x�=��;Mi���A%sL%T��HU�*����Q%s�d�Y�dv8�G��a��G��a<G�̣-:�dA%�1��$4>\��;��E�W��7������[~������2������ʺ��*����տ�_���W��;��?��&��r{ʭ������;T�+ɟ����f� B��k�;d�}��� =�f�9ο9*sLG�=<��d�(�b��Qz�ہ��ߜ����<��z���=���������������׼vଏy��}��K�����_��Y��ajI�y�]���O�yy~�������=gG�]&wt��Э;l�a���0��q�����ȭ�Ymfn���lhz��j�>��Gd����0q�e> +�� ��<��GQ�(�E�͹Eџ�)<��%�n��?wQ��;>sat�lGY�@d����(�e��peѣ,��e���e�]&w�E?tY��?;it�)�<����^~y��܅я �s-v�����@��聕�<��.�T�L�e^�5��O�s%�?L������T��Шë��W>�9��7���D���/.����]�o����|���5��6��.ܿ�&�}{��ߏ������w�{}�^&��3Ȟ=g +y��Nw-F{h�c{?�7o�_]\^}vy����Q6�!�;�wn��}��ۯv �!3���t�q����>�U�tvw����]oW����5ם�|Y�|ܞ"_���뷻�2�����}"����o�iا��k�LI�����b�~y�D�\��晱 ��ǹ���,ߧ����~�,�37�| ����PX����OA.��z}�K��C�$7����~7x�dd{y�/�h:ϊ��xY�vO�}h��Ǔ>�����D��~���|�<�닥��3�һ�˯߼۹퀟��x��V����ԟ �z���( ��]����5��ᑗ�"�9�,?y��}޶��fs������� *��tm�9��K���f�T���F\9=�Qz�_s��S�z׆�1�u��5�X�6֋�v�F�}��x��u��ҽ��~�GZk�G[���oZ���כs}��Ƿ>�ӏ�k�Z�d}��? v������� �f�Qr�f��q��z�{�J��[��o�ֳ�6�/� V�$���H����}�G�6~����`�܁��:�� }m��=1>����-ØC��׼�E�G�������u�X�'Z�q��^i��}�i�C0<�ѹbX��i�B.�z��)ü�ú�z�тL��;o���=�Z���w�9� �W+�fe��X��qx�zrn�u�����T��5�+��u/����֏ֲ\zm��'[O�rҀOnZ�5��qϸWz#U_fMZ�b����w�E�ص떳���q��zZ�u�c����Ψ䩫 �%Eʘ����_��eZ�ؙ9\m-dd㶍أ;}m����y��?�dܥ���8K�E�[ /�u���z����!��&�Qy>s� /�f��Zi\5��õQB���L�ؽ�c���kA�S��ik��uO-A^��f� ̵qq��^g� ]$��-��zXH��N�Zޜ!G�f_��� +V|}�����k��V��y���)#�f�w 筽g�T �,im����-���)��gl���� � +�`]e��ů a�}#w�Z�R�jk���Ͱ$~6c� +�<kw��٧�-��G����ޥЅ�g^_���7w�Ǣ����Z����� �~]'~˥\�д�0��b��9Q�-���j�Ѓ{�=b�_���3�~�gw�w��?� ���}�]�ֆ���/o�k[��F���/l�k[����}/mޫ[�/^���T��aiو��!�?ip)�)���Dᓔj�:����e�� �J�B{��r�1� +L_ �� ���3y0V��@�|�:97ӈxu����%E>x����#�׺^���c9y=��6�̡��F���hˬy�5N\K��]+-��� � k����'����W�q.����i�&�"�a�tpz�ч1�CO����}N��ۋ�O�a!/�21�� ��|42F��2��u�+-�_`CV �m����Zko��6x�R�����4� cWZ��EFGᙨ�YV5?�|�����r4.�Y[[3�� mx;�h�"���@�Us���oj\�z4)E}��]�3�+�w����9�7��/�6u�M{mM} 4�<5q�ֱZ����k*8���2�T +-T�m�]�^wp��J�׊2� +ܮ� ���O�o�[����E�kz��[pY�1�m�t�eG��?s�I[6@0vn�y!�L��#ʉ� ���k�2��ե����:!��:,����[���K�%i0ǵOtq�+mL�N�� ��-��C�&�o���n�(�p�0�yR Z��3�-�|I@΋ҕK��+��:T����|�ʥ�s��Z�Y�����9�S�B�D٠��؎4��ԕ ��yȴ�!��]�w�����k,_g��R�t�(S�k�����􄗦���@�KyR�$��Ƿ���/ߴ�����X�� N6�z;p�;� tw([�P.`�£��?��0��ګ�#z�YSzl�0 <4�� �(b�����D�BXK��,(쨱�c}/�~mK@�,/?�<=�p�$��M8�C2{9Լ�:��4��k�l�5V�P.!YC���4=���[B\R���]��Y�/|� ˙���Y]�2�� ��S�ı��"�^�@�X��Yi�Pa Y(T,�8?9T�l�S��~Y���n7���@��tz�����g]�`��i�9K?��VY��/��z��נ�N��}��A,�e���F #Fm�%�'��� ��Gw['�߸Rݭ��QgF1_Z{_/�����χ/y���!*�b�"���z�(���<ʑZ B�)ܟ梧q_i�j��ba5������Q���hc�P� z�`-���%�cLD'1��.yS���׊o����a.���0t�� ����[�K]�������/@{�#KD3��(��!@��!6�9������kO,����Ѥ8ܦ ;��k[qbi{�~�T�Vu�/��gMQ�V�����'�˪8G�n_�z�r��Y��W�2~�F�k�����r��\ � x�� �:`Y�\�%��b����t�� ��c��n�I��w���&�����9x��¡m��z���J��,��yN�h�؊ , �H�s����S2��ܡ�s�/p��a�9a>p-汬��|I����6���ٚ� y��,��aIl��\�IZŁ�!-���Y� ���j�^Kۈ�(��pH� &o7����4�RY�T���*�1�u3~�%�`�k�;�Z�{#AA�F���1��i J��d'6K%�$6!��L+y��Ip8u��y��� t\����y�yf�}��n5�9:�œݔс�8�0i����I�N���������hQ����X 4fR� ]"�:�8�")R5�τ �,\�5.�z ����:k� ڲ��X���\S[��4Y���a.�W�c�����bs��%�Ȅ�P��eLA�'6�4��d\C��H k21@�P[+�:�6=�&!��0��F��4�=�օc�"w�b���i�������8����@��3�~�+����O3�(�Ͽ� �pD���f=��}��c� Uw���?O acpa��\"´4��Ma�N>-�z�=�*,��ϸ|H�-.�s� ��˞��Q�6�ƅ�X'�(۰��Z����&IJCA����d�2?�wLY�5;Q��`�%�F�f]R�^D�Ѻ�"[�k/-eu��K�߆�TM�Ft��y��i�5*ХO��=9Ô/�;�aJR`��t���̀�, m�e��(A�DH�� K�(�pm�2a�^�Z�>���@�{H}3Q ۴��hY��5F'L�ŐG�-S��ef�R �J�)�m�>*�g���a-rT<�"~Txܓ��P�v��%/E�0m>,��i��l�>�:ȫ��d��x�8MF�Ғ���?Z" �`�r����T�4׷^ΛY��_��%��qoơ�K���j�"�ocX�9��C�䃄��� ,��nz��c�6 ��9<�`���Ľ��&� +����0��U�S��s����V,���sÊ�1 +o�*fR�{#��k�m�t��������[�T��o��#��}��'?��7����O�����_����x���~�����o���ϘkZ������?�"��deX~�:�!�"����Y�n������B��jYӗ����! �����^"���p����>�1���<�9_|&����`"�WK��rf�6� �W�㻣��8FO{��u��>47MH������ �+1]�>�t4u�A,�N?N��$��#��ؙP��H�VȢu� ? "��Q��[D<����xC��7q�`O"c4%!p%� ���@�(�R�,NfAa��MB���I� j�RS� ���X?���[�g�o��L�M���rD��-�1��3�H��G!k�"��y#���R ��햪z�qud�\�??��z�/?@��Nka# +xG5��+���8R��߾�Ӥ��z�7���'z#�w��I�QJr�:�!�,_L��J�1�|��}x�^���8��H�{:⮜��*�� +P /.��q:���v�����X����z��N��Ec�rV��> F��u5���� D<���~�?H���O +h���1}�˧� +;�z�B�z�~�L��R|�!�z��7ʇ��5R�ͼ�?08���6Ɛ��T%������HO���G� Tt�I�4�x�����b�N�b���*� pUQ��0��!#�wy5��-d��W�-;���)�Wv*�c�ŋ3ޏk�����z����jcL��fJa����С�1�|�0u6mn�����*M) �}��F���e��1>*q�@���&��P!WS� � +��u:GB�A���R;�I����O�$|�5q�o��c�����O��Y;y�2=���<�u ؅�����eFwH�HU{�Z/}r��v��|�.�f�!Ʒ�(�J� ������eq:����֠ݲ�]m��}�'[��\���L��5Ri�/Á�^m:CS�D@ft��:hF�#�ь�`4&b08��t�GVd�iY&���f�`<�畠�Gi��G��`q��O��r���z�Jw����-�Y�i��Fd�zze�1���7�Ĕ�HF"~VŚ��*�`�> @ R87�!κ���行�� ���I�֠��^ ��c0�j�D�Y��\B�Y\�)��9c\0���!�ZӪ�ol�x� 7�؆���)H�"^5�2���D���(ձ+�r�Ϯ�g�J0g�v�2����ߤ��q����N�k�f�����!i���6��0����$���NW�No����-��"�"~ 4x�ڬV��v7����n܊��M�U +�٨i_mㄊ�"�F%���r$�{��D5ƈ#l�b|1��0HX������y����! ��#Te���J��D}��Ww� +�D��@چ�` �'}M/j���A�%A�/����d�.����@�`$l�+8��P��)� +�F���d����D k(��8��m�I��o�us�.������u��]۹���pcc6"�Һn&����-�������X�%�"d6��"��^����yl��D�,�Wϑ���TgpiC2UҴ��1�y@�}��d:����/���a�c#5-�L�{�%!���`RHV���Ѩy)%$��.��s���m�A� ���$y%4@��v� �G����G���*�N��`$g�7JF�x+�1 %=Ns��g��&����^��H����=��w����=%���ɤ߃�9��4���^�Zv����A�9n���Ư�� +��~��sS��_��H��?aP1h�?EsP��M����jאuC6 ++ �TA�7���gz�>oPI���$G���l���#Ҷ= +���xzk��<,�/ӉMٗ��+(��PzS�ơ�냴M9���ph>��-�[��,p�����C>����_����y��.ځ��m���ڽ���!R��=n����=; +7[��/oBI�v}��J����&���> K�dD��E������}����^@������_�^EtA���)ۺ +"š����Hm�d�*��aa��c��3�� ���g�U�@/�1�9UE��Ds@���Qe}H�!���=��Ӡ%�Ϣ B����j�~.���b=xO�%�*I��� ��=Dz��X�C��R�5�h8� +[�=+��r՛�f`�j#��vĢ���!�o|l�_�W�Dc��Š�d�k����X�����=Af��2b��|�\d�Ѵ'�m +-y[��[��g+ǧ�*���\8b�����S�J'?m/��R־�v?~��S�-��7j�h�}E��|ZP�f��Q�:�����V�����I�]*:gJd� ��qA 6 ��Y +�3e[fGm������>���S�vn�j��ڃL��{�j�Rv����S�"?� +G�Fkr�Q�C����J��F�|pW��i��I��3 I����t��,Mw D*%��Ey�J�Vu���� M�.�40"ۛ�<�v�f<�z���<�r¥��]�9Q�)O��.���g�����>�4:J�0����i?�(��+���)Q{=6�H���öis26f���.Y;t�� s���b� q�{�;O,`֔�rl�B�R?�ޒQ�g�U�J89���$��`Q�4!�o�=4%iϒ��q�&��(�G>���Tl:*er�9Y 8ٞ���ؐMw�J2u��$UzD��B��,���J瑦�����?� ؆@S��d�dH������>��{P{�R�����(g<��+eT���<2�r؅����U����}Qt1 �#<W��[4��$�Spp��wY�c�R�H.�{�J�輥��ԭ���y��|Nϓ���?���q@'�/��Ι�a*I��A���� ��D�1����(^=�;;��Ew��$b��g� O�өZ�� 1H�-:��`8��ބ���0>9%�U�-�iֱp"a� ����82��}�Q�J�E�����T�V +ڤl9>@��۾�<���%�'.�F�0��:��Y�t�йP��sL1��_���G�����O)G6�/���y \�5]�[��݆)�["��o��fS�)�=h����=6e{LK���ʮx��Թ����RO/��!y|P�^ܨ������G�W�o�M��Qx-����*c��iCM��3� |a�0�-gKp�1-����/���!| �fd��9e�.���.~Y�YF���(�����gk���jP|d������^T�8��X!8�(D��m:“���Df�Xg�w��B�X�2��ߏ�D|f�?� �"�=���� �R��c�@�8���ԩ� +�*�b���rZy|/�^<�_��[.؝Q+�[�Qc�����Vt� +�"�p c�����_6&_*�ϑ&��ll8����jY}X�+?3�r�uZnAS�Il�R�oQ��%U8��ml �H�lKp_-F��%7���h������Օ������bl%Z���5������W*m�./�� +��[�;HP�x�Ah��g�ͳ� ��"��i�E�m���F Q��x� [��_������ġ�J�2��I�U��w,lc�Up��?H�U���`w���p��oQ�u�5�Q�J%���3���v��Ea��-n������g���vyX�HE�I���}���Q�e����@����?���veA5�.)~���׻��_|������ۜ_ִl �B B��c-Î�e�����fo��P�0��t��)��^ܪ�c̽ �?:�(I^e +������ &47>�w�D�\��~vԶ��*�?�A���e���/oW��h�#�`�+uJ�����>�qZ8=ȡ">i��j �B��`�ȷ�"������\���3�z� �ۡ�t �4W#��[������t|X�^@S����@Fg�A�9�!a�}5�Q*c#��z�m_�A|�jO�t�_n�06�����\����w�����j7 ������g;b� QI�Vjٵ�I�&������� +�%Gb�ǩ�,3��4�߱S���CU��=XuT*qk{�&��<� �x�-!X��u��r�r���Bv,�c��v �x���J��Y� ����k� W����a� J�n�����1V竩� +��\a��F���`c��ҍU��=V��BB�A���$����L�t��,�^��L�|>C�w�5���}u��;�T؎��mU�:k��$�at)���ޤ���-^��y3��Fk�;���ZP���2��T� Ef�n� �Wr:�I�dCZ�j�1B����/��G���Y'��]޽Tx1 �[ Z͔���,��t���Dp"cx,���u��R'߄���&EZoA٬� �fL�K����4�j�@�B5Z>�m�L�[K@�Wg�Y>,��Ė({��2�m =l=��J� �Ʈ�ǫ�+;��"�1>L�bO��)蟞�Z�v�� %�bת�.��q<��L 5b;V�v�e� ��Hz�P���mKJ��w�~(��y[G����3�n��F�ݲ�h��Gպ��~֤���@�h�b�~c���#,��L�:n���g����|.(��5խ����p�ǫ���v8��x���,*p3 +�b�����3��~p �캟��)[o*sy�����v?ЄɅ����y2[�鹶� �5-(ڶJ��ީ��k=*2� �g59��#i�Ҹ���^�T�[a����v/- +q��0Nj���l�0�lܰ 4`�*i�c��X�[�&��jn�� �e-4QT��.qIh����GrO��I=nէ� +Գ�����S�A2��1tC�Ҝ�5��n �5��>L�7��Ke+�U�9�c��Z�>�:U?���(���$�f�9��Ь�Մ�#��Ʊ-�*qn�6"ud�A+[7��-]V�d�a��,���J�v���k{�v%^`ە�����Z��E�� kc X���*I[ �[xQQT����F_4�!W_lX�e垣Z�x2���3\2� +� +k�^�~�b��{{m�B�\�tY:5q��1�N�{������cz���`UW���/�S?�ϳ�xs _zb����ݳ�������?�!��?�M��c�ڎ,�������_20�����d�Ňk\6_|x?�͚s��F���h��\�Y���j�&]��C^`�yk\���.0ސ'���7\� �7_|��{�Ň_����7?p��o�}���t��H���yZ +1�I���a���������l9��o��h�̘��3g�[��YIo1�x�̝� �b�����g���CG�WXtl�]����ť��Wl:o����oq�h�̪c��ݼ:4�_1��K�:_|x�]��u`���a��ϱ���%��Wxv��ʴ��^���ƾȶ��W�v�Q�fܡ�u�s�S/�yw�̫�;�֗�w�̋�;_|�ƿ�]��c�Xx(�.��Cz��gͻ��C���l<��~>�5�#��W�<=���K�<��+fr���Y�.��py.���k�b�Y��8zh�������Ӄ��n��d���#��^�̺�ף�W{pNj�=����G�Wx{���b�Q��w���ޣ�K�={�M���#K����^�����&M}�壇���c� +����b����飩'V^���ƿ�샩׸}$j.��Hf�����������Q��ˏ���x~���Ϟy��G��Wl?z��|?B����G��n�m����h����G�������r�H������ػ�8�� @��.p�C;�q��F��D3�\@��b��u�����8��t���s�� ���{���ڽ���� �@��^�9�n� ���r������K�S�A$��唾��u�lZ>�i�q�gH�7X�q�i�;���3?��/1��x��s]` ��W�a�����x��w\a�?s�y� +{�-��G�0�m p��Hy?��&��;d!�΃I��g.��IσLo0�yX��)����_߬���6�N�bo������K)~�h�-/�^�]�wAn������)�tq�7�������g +��.����"B��'*4��жwx���C�)Ѷ�x�����>Z�g��5�>�����R�L��GO$iމ�Y��E��y����\�J�Su&K��.�ç���P���<��9�t�6���L����4o�3y���:i�O�f<�y� +�ڞz"Qs� +��� +��?��J�q�+dj�z�N�;O�eJ5GΤj��7��,�K�j�O�j6D/��ٲ=ӫi���}�3��i�V�|�f�N��5��ּ�W���ѯЭ9�s�p���M�+�kۅ8Ѯ�,\ ^�S�y�)���+Z6_!f�B��gr6 _�g��Km�院MïH����6�2��i�+�6_!k��� tm��g�6+�+�m�z����3m��_�y�D���+�m�ί��<|��͑�3��H$n8Ӹi����g*7���<|�s��Û�n_|�L�f��L궇O�n�B즩���4|��͛���nޏg�7 _�x�G�D�O4o�)W��,��To�@�fa{�{��y�����L���+�o[g�h߬�.�Y#��ߤ����m��D���3ܶ�OpoD���^����w�Zn��3!�6�N�po���0�� ��`�w��?O��?4��,u����}�\�����X�ϝEz����g>;��޺�s�������v����l� +���g83��G;qܽ���o���>qݽ��Wz�x��O�w��z���x�4�����g�;����EN\ +���4�́�O���g<_`��?s���g6<�������gN<�Y�,�N�x��͌��+�xH��so�ɐ��3G����<��Kng�=����\x���G�����83�y��ɷ}b峦��˷�뉙����ͷ�O�|2^���a��y��G�'�Y�l؜y�<|��φ͙������u�����O~��O3_��y�o���3s��/p���������7�{9��N?��i�����L~>s�����[n�K���>��}�/z^q��a#����C��D���b���/����c��o�3o�?�/1|��׿�����|����g_���z��g_}���/���_������[n���g�m\ jdV��\��u��d �Cc� ��{"��[}fa���Ѥ�IˣyQ������WJ0��"@H�I�@=������F3��6ܴ�'�(�t9R��U��N�-��N ��Rv]���o_�ZєD��{v9��9�'J�2���u܈����լw,۫(d!ZeTk]��#�}��-(���Wߗil=��W�C�_�.*Xo�ōU�ڸc�ck�.�_آ>#^�i[��/�K@��;V���g�tK�,�������F[�}Λ�-�݌� +6b$�t���/��w�)6���t����eU7D�%5]��[�}A����zױAF ��ݫc�H�ළJ��O����/Q�D���o>��o�����������7���@YB�'��W��/������-��/�d�f<�'������W/ᱜ:�����~c�t���+Z��ͤ��֩Ž��Fn;Ęv}�}��� ��ʿ�*��Ix�����e�C�P�f�(�tǘ,�&U{-'ń�ӈ���5B��6�;Fp����A�4>��Y��ܑCf�"4������W�����~� H�d����/����y����_Z��8� ꋡ&eG@�*A���ӂ��Z��f���y�>�F��ub���/�����X��_6Y����j]բ{��-����u�U���B�-��얽�)�����z8�2}Ʒ)�RtЊ~�x���T�����N���r�}�M�L�D�U�nO��2+�=+� �j���\>� u$���q]�S�k�F�^��e�׽�M&Ž��Bkv� ���>q�D��h '=��UW^�Z/��������ܽ7 ���N�<s���}��{j�'�7%w�}���נ&�xc`���Ż���IU0��0mQ"���=�`�!�ڇ�j��u��SB��̉���H�h����'��A����E��d�W��K�F��KV���j���`m/���*��3��e{��M���z��k�4��K\=T6�7� n�w��Q���t�K��Uv.d.�sI�S�E��US��&�7�/kw\-+_��BVɻ�-���-�g�<�<6_b�TAK��\y�ө",lr��Jݸګ�^2�k#Y_���:*�6dХ�}���ҝw��C̮~�C֬�}� w��EGʅ�>V��?Y��w�nX����C����ȶ�����X� �% ���R��3ɷ��Fo��j�F4�c���Zw��q��ξ�ԗ;77uRPly4��δ��xx�lc��z�@�[���w�Q��[��1��Q>�]��C� ą>Y�#A��Wq��m��`����<�)�%�/w�F�r �ʃ�&�RoA>�W�OR� >M��VC����D�[��9z��ARF�H�Ɗ[�a4)�w�;'����`c&��Q�IEd/㭨 4��͆�@Фֲ�鸏�s�}*�TV����$�jq��>��Ɓ(b��ZZ��� +bp��g��xXPe�4T"��q0:�β�.��a���բ����e�+��2�# �Bw�ܕ8G"BlbHCt��F��M� �x�)?�>a�1C*07�-(�!3���r?��!L�"�$}T��� +��Cgtǧ��P\��Xk� �4k��S���d�1��_aq%I0� +P�����όs�Ǎ�X +ÚT�Hw95�$g++Hr�'���Fk�TM0�Y�>�^�o��&���.��zh�`4u-) '@��)iח2���sd�+��������(� \NSU�C���v�u/=�psS�q�\<N�$�,G��Xy����Kp�ⷅ�|����DF�D� �l�@��v1����r��FZB]#<�L=w� \f�+f��G�:�t�dii�����+&�]Xj�>V �I�iX_-���ȵ��̚Հ�2�G�/k�!^�P[tT�8������(f���ˉ�:�q �@K�#�T�w�CxֻbK�v��W�M��n�p���">�`a$u_�&d^��Ga�=+z��t����C�0�kj&Q�]qt�40儐48�q��8,���;�c�*�}d'{SC�wJ��y�`�v��TS��O�>�P<�w�<P�Yur��@����4�?���𻍼[81/��M38���¬�9��Tj�JTF!�;%�а����B���z�F*ֈ����k��N������qV��O���h��m>@hkFyQ�%�k�7a#�(�.�- ,H�b���;�`�G�Q���̯P���� ��>�b@Z�O�ᛃB��i����� >jih���3"!hr�hS6�/�#�A������׵��?l���~z��)�@�z��!�G`��b�h`98p�3A��^)��h@0Y�R,S�a�?��b[h�jWww.`��i�,BN���]�v%0���w��&n�f����☑�@,��"� �X ��Y���ų���7�g]���f��'�V�:��j�nɐR +D�V��7ÓC<�>��"I��NQ.b��H���%��j��]��4�  R݅5^&�ɈZ��F?^����61?���y��o_�-����wH7�;;�����o~������|ys���7_���׿��������ӯ���V__꯾��������삗�>�_}����0{�asS� :�}�$��q8G�0>oAu�0��\�h�B�=�:w����C,���.�2��xݽ��I�� �z<��xDOfT�������"C�a�c ��[��F g�8�a�nfZ��o�PE�+bw��� +�C���.:��I��'�.�r��2�ڬɃ���dD�բ}�yc�h(ۓ�͊(nh�������is�L��[͝�t�-^[_�9�aB��a�ge��]�WJ�E����1�t`XP{1�\��W���K�ƀ�@�@�0��c�ab�&wn@��$C��SG��&L#F����ư�{�Z��ME�`{ Ýp�l��v�`����36��c��FF'�=��[�S$l���A�(]�1=��}$�{�3B7��V�j�R#� K��H�p_.�I�쨉m���.�t> +5{J��.3���!�o4W4u�"��l�ojx���zW��4�Y�X.�#K��L���~d>tr�5w��#: &�T��<���H��8����:�m�GClM +c]�m�h�Aq��-�v�څ��Ӊf���pQ��m�3��~��.N 41W!�AIB����� �@�{v�@���u����2�]]�<gYoJ�+�Ԣ#E5��9&�*ݧ�(�\l���My�mȷ���D�}���H�DcdA/�H���Ԯ\�G�c���J�T����XĈ��T�acvqh���qDw'�����8��� E;� � ��{y6���\���͉�l������b��i�!�ܲ�ʁ"^��B� �����n� �!b�k*)5ȹ�$��\���u"�ء3khy�I���Ƞ�T�2�����ƶ�J��7[�W�Ep��%Z$�Y���`��o~������N�D�c�JC�< +����lԡ�[vK5Z��Ga��[G�����s[vk�����PL���x�>�X"��� +I��j�!��{����TeBc؛S.���! +F�!��C`��Z)4�w�(�8�8Kǵ:�~2��=t�)�+EtӮ��(&e<�z �.��E�4j:^4�0 ���@q&�����~bۆ���]�����1aA\�u� dY85 ����f��:am�>F����[�mgsH�p�p���;�����Wa��u�����롗H������T o��YTZ]��);c�H��I/l��/ �`Ih�h���Zj�F�E�T�eĕ��P�������P(�W��=H,�n+נ a����u�D��Wf��z_��ޝ�ۏ?�P��v3��������,y�?hT�rZ� *� +{:��X� �w������ �ӐO�&�� �%��'�M]�ސ�0 i��X�؈-�=K�6�e &f�1D�Yñ�iHe��.�B��ۍ������#�4�8��13��$���Wag��4� ���_Y���i^U�)R|T��8�s�@��R\z7���wc�o_n(�� +�-7 �q8��p�;b�x�aw��]�¬a�a[ҁ���[�ΰ����$`� +���tI� h�u�t�Ś�>P#Rs��p;��t�e5iWl ����S?R��)ҿ�B� &7��B%��4�\�����šԍ4yC�:"I�:!@G�x�[C���6;��+�W�H1�[��C����o̲G�"&�Ю�լ:�Ϋ=3�/�rVbDw��C�%\��M6�Hփ�+~�E~%.�Q�_b#�(S�p8H3��Ѐ� ��[�aY��yZ�Ʉ� p�Pq3fe�X,��Pg \T@�-�k��@@���)45�F�&d��C*jE$�Rپ�]Sv4+�9����|���&_2p߳��C�g+(2* �Vl[�@:�4`�mb�8��<���:���O��R 6�ர�6���Ka%!a� �f��FΠ���'��;���o�,���=Ή��{�պ�dc0�Au4��� �W�� + ؇ĪZ��b6��?Ӏ���/�Y ���Ä*V��7ɠ���x�#M�}b��gQd�(uH��]�!|�Q�ۑ�kʈ�d�G"�@�V�R7�8��zu\����6dž0��M`P15P��i1U�t�)Hʸinu��Z�mF3L�u�{���$a¯�0���@���T �0�J#����7��(��^Qu6!�8V�U�*Dv�@\�Q +��4�-ԭz4#���Ӽ�}s@1�0��v�%)>�nnY����`MNV��ڏ�e�ŵX{�o�\��7��y@Aw�D��/���˲>�'ܲEQ7f��� I� X��.n�Z� ��A��J��>2�\5U��QD���*x�HvS�]�_��6t�>���%��E/t�'l����OQ��n;�4A�2h�����6,K[����(�.v�f� ���!) Ƭb���A��ă1icd��֙�]�| �ݏ@{����� ��P=��"S���KP���͎���8�j�:Y\�<,wg�V��� ��������ި���3�~���=b� ٬KH�'��$ �� ��b+�8^8���'wt��qt��.���:��~��?�"�l�R��� �%���Q��\�d?Ո���%8 �����bD�㊀��r�2Ձ���9�ԩ���~���Ɇ,�$�� Up�$B����xF�9/�a�t�����Aw�R���"�~S��D��\j�16�p3�1�cE<���e���} ?"|�D@Q�Y�4%�а߉������AP��\�D拾����Pz65�0&B�O +g��ɈmBj��!�!�(�P|=��d�1�E&C�{Pp�|�ST��^~� .�T�@���%�K'��B&��!'E�{�az +,�D�ԹWd�W#Jɩ��N�Y2hެ9TXL%X�Y�8�ߑ ��M�5g4-���bHe�h7;@��>f�(5����N(�D�����t�7��`l T��e�]�cR�����[��� �X��o��ʚ�k�KWUUB���� �1�Jlo�VZ�� �gd*Y[kY4��K��SO�G�U:v*����2�HD7��Y|`�,��H�0~�����Իfz5���=�TT\jVc�;E���)�ȩؑ���� ���� �T��Qw �:�є6��7���bSQL�y���LԢ#@���445>'[RU��tk���^T�׸!k�$o���z�EDR6�G������K���6aX%���@e/#G��mP'�FN��{"�{3꛰-,& �ڒ:��cY[զ<�Cx�&�m�<´Ddwre��p�u�/r7Bw�Cv����~@k�&��f�қ#�V�i��yX�M=m����jc"���B���L�%��ri��,^ ��ڳ�eP+���=�IJI �s���#�h��=� &�!&��J��EA�y��|�����Ut��D&,<۹4!-0�~#܂S3��J��T����쵶�d�qigApQkX�;����v���!zj ��A7ԏ��kV +C���� EٴpIK��FDz�l2�|)bb HL -���4>6�尝���K���ZG��N����9�ժ+|b�i��r���[NjuG���Z0u� *�B]в��X݊�� ^�Ɔ-��6]Ul�O��P�xb В�B�0����R/���7�;(R�ra٤� +��!1�g"���a♁. s(����w�N-o"�2�e6`}��pBv!�7Dz�h"\% j� '��Qڍ]��G=��H8� ˇ������7� Q�(O+l�WA�^Œ7>%�RY�w��ݧȻuD�*1��cϊ�������f1t���;�;�b1"5IX9)7�Њ��k�*I��KG��E���N߈�W��#4'��Vk}">��9�/�5�w&^�P�0Ȉ����*�6�Eb�Vb �'��&1o����!��]�B��Ԙ�$qˢW�^�]j��~$ԉ �a�����ې�|�$ly�DN���ed��Q�U��p������HEc� a��{`�?mU�^w��g߉@5���в}*�0��- ��O�N�C�q��X�\ +rNY���/ɜ�w���~Y��q����c�+ul\� ~H����9�4=Uz/�4��!�����I3���!�0JS0��fᱻ��Fr��j�u�d�HFFG������p7F�?gv?��́˰�I �ƞ�\�2�w���LV��j�j2`g0����o������ b!p*ttR�A��a8"d#������D�|��,*��]ܡ��"�z`K�BL`mP)D,a+���DkP m#���XTL��i�t � ������:>;��':QMn x��zYh*��'��;b׎FPyPq�j +[��Z�f���(�'�.�Ih�2 ���]��.XS!]��xɹ?)+���&��M�y�`u�j�JW A���S����<��rp9z�- �#T�L( n�����`��U���s4�$%�b'0,eX/FXģ�%f�\9 ІAf���0������(��'�����1��cL�c,�c��C�G���Bc������W�n}��"���"(�w���M f �`!OV�w9OesEp) �e/��l� �L�p� '+��j�����L�]7�.S��d|��T~��"#lW����q�N3��]P�#�ձo��rS�HY&�ր�I(��v}e?�~{/���6Q�Ý���0��?*.5 J#�i@�4@��+q�¬���T�H�@A +�N�R��hꇃz�����=�"��o��\��h,|�Dܨ�h8��{�!ʠ�=��\�L�# �,��� ]��=ȏG#]#;[�����W�L���*{X������4�+<* i'�u����,�.`���ذm�$��Ġ�U��T��j��� ��u:L���� _����\Xn�� J� ���I�vZ�,~"Pg�d���,D�$ң/�_�F���w����#��ܱ�1gZ��������N�On +��>%�!�P*��F�����Am-z ӕT3�d)�CJ���ˊ��<��T�h��4����d��W| +�19@!Z�.+�� 2�w����$ (��TFy/ �(�m= �@�"�����ѳԆ ���E_�r��Y=�fe��C�-kS�mZʷ�ʹùT>-��XOH{��@�x��� +�c<�Iz�=�:lmQ'��WGI8� ��!#���Ro A�à��cJ�{7QX]�[�2P�c��vZ���*�*!:���㈯�\��7���!���sӦ`�bm��x�J�k����C~����a#���~uN�=�`,�4�-��OF\�W,W�z`o� �,Bu�)Q2���]q��8�02s;:X�#�FH��'���9U��_J�月��Џ�W�{%��L��D���t� '�M*���>i J� M��1���} �Ot�ɻg�g�u�$�� ��[S�c�0 �U'��gP��C�=�g,^��z~Y�4 ���b"?p��� h �}���m���q��h� �y��~t�8�m'Yb)��Kp�Uo}��"�x7ؚ���Q�](-JT�a � +��?� P:�=���車�Q6j�*(�v�>7Z�#~tL�3�Pu���r��u�� s��`��\�n\NX��F/�x5#�T���<��P�@��A�^��I� #����~*�U�Ğ8�o��qH���J35��DOc=��Oļ��XUn-�"Xt�Ml&b14�D�1C�~�[zC�G��(������W�-@ ��E�`� OQL��A��,ŶEƫ�O�e��o��'4E�b��P�j�B�r��P�:�<˾�Y�'" ��5�›�"�,#�x��򐍬�V}D����qi��*�P8P�Mn��;��Q�:��i#�3Q�Er}��!rps�b�I��3��w�����Ue^��"�jٺ��Q%�ا�6�xD��� �����~s+��im�)�I�����j��A}�e�H�D�LCبe-$X�1��宓�$x�p��:$�L��*N�M|��kn�Rb�Wdޙ��x.� ��*nbŁ*1��z��/��`��Q��c-GN�bh�5�<���>����g����t����R�G[+d�'��`�N�Y*PH��i��K�N��]T��c������yxQV8c��y��>:��t +��>��� ��s���\ۤ�=����-����%)D�[�0Z���Vo:`T#Lp�e/�nb�l���<����pp���9�=3Rj`��� j��Ek@BR�<�~d�)�GU����U"�F��ܗ�m��m3���l�w�!�{a���?�L�6����,<�.D��_����J�*�Jдj�B� �r�����$y,UĮ�>;;dc�|��D�� ]��"m�6�?֕:��E��BP"�p.z6�{H�'i<��vf���n�����8 �ҎUf�5Gw��{�D���*4�0 ;�!> +�Q�f�L�"ڤ�Y�0�1�� +�G��g�� j +TOڽ.�hR����l$�ݔ��t�C��,����GK�pg�z+'ӵ��%�������� ^��]w��������f�.�W\������יV���� +�m��l̆�Fa1���@h[�v�!�)fjV(�1�T >�[ �:����2��$l֭e�W��� �����-����� �E`og�X���*D��IYK%�Ed� ��gA �B2��O� �����(v�tl�V��FX��[�� ?3�?m/%D,Y��� ���98Ɍz�9n�/��F����~8+�U`v��=Q1���m:l�����E�m|�.`9� [��T�X.d�f���kDJ� q*�1�� ;�`uB��*q��EW +;�IU��9 i��J9S�sF�9)iz��-�<��!�2�S��F��x$f�:�%�� �H��EL�n\&�0F���9�=y��(��$K��EUL@�g��eS�E�_�������U8�c2��. �|U���tQ୐�Y^݀�Pi�أ�\���M�B�1��̒�?̯�΁�.���AҬ �#Z@�N��#�l����mr�1e�:�NlWD�h�=^H��6�M*Z:�,O@:)L�X�X���y�D��+d�ao�A��1�C��w67�N�TJH��>6MMG�L�?�7�n��FG��X��q�Q���i=8�A�l�" Sv~N�n���(N�)�Y�� +�2�X� *���b�A'w�B���lTR*���>�$���4�t��YfD������� R�ӝ�"(q#*���C�����=)�L��N� ,�%�L�tf�7�k��l��:a�M�S��t� rP]^�l6��S@vO�f ����8�k���0l�b��@��u�!+B��C�Ml�4���z�����s�4�!L�}��A 8���K�Ȯ���g�xl�D��~4˱л�u��NI� �(��%�27��� +U��n��'�ҋg�`�f/�ݭ����)���T���U����tp�M"A��5 +cN�L$��bL0� ��dIc�'ꦫ@��Xm�NT���l��8t9�P�tE�?��,��Y }�겂��PG"��s�8O^ue$��z�3�2ŋw��"�3����_��(�3dTI0���Pe +@Q\x�|$�0s�эb��5����h Y�-iE�ۂH�v�R�ra��Y��N#�b�mN�u�βfW��}gP�u��_?L�d�vlq0��B��D�a�q�Qڣ71�9|=(6�\�_��8�M�Fx��(B���U��#�'_լ}��>D���Հ�;u�p��[�o�v@�!H��fn5��S�,'d��#�#f�t����t$`�/s$��K��֭/���;~}ӛ������������/�����o���?���7�|�g��6������RkW.#h�߲8^�_Կ�e�-���m���B��e �5����~�w����K�>�1���<�w4�|�����~h<�C����x��c?4��6���@-u��7_߭���:�;�������/u������/�F��sg��߮ �A`Iq���H�� ���T�� y�U�x +�D� Y>���sH�E�."���Цc�� ���!��)tBg�mW2]rE�@T^eA��n�65����-FR*KO)i�JK6$C�D`�����%�`uS�Ž0g�=K�)N��Tޘ�Fl��B)%Q�ME����`QP]���8�P ;�]�:Zu?vL�����m�v l�/ +c�o+cS����֘�bl0$��pQI|�X*&���>2<�؏i-�>�uӑ.A����#��7D$��p4��8��'��I��fŊf����l��G��;F {sd!�~��07���jp��s������ � �d��i*��Q�A�7�y,n P��ӏ��-ӕ�<"?��@�Ѱ�7�Z�Mg�v���=���C��� +�gw�!�;0[� �Z,Y�#}��O���o�������秐]�&&>C4{H-��]��h-ؤ�w�4�-2hYD/��֛���F3D4F���D�/�� I�3M9( %۠��D�O�RER��N?0�ɮ � �QLY����[��z��(D���Z(6AF�}DH6t�+Mi�l+�#K����G�U��.�XP��)]k񑛙Y�F돕ȟX����0aA����"`4�գ��8��,?�A�Ba��]�XD��K�5�����b� �a7�a�Iw�&��J����8�Y����4�z �k�����;S��f�@�,���������qѫ�������>q�I� +���A� ��:1<*� +`��V�q� o�׍`"���dkR�uMA�ܐ���]fU�(�DTZ ܺe�OM��$�I��b�ć����?���Җo]��B ����S�B�� �-�]M�M]�$+�g��`��G”�q�L-lx�Q�i��@�+�KD�r��fBp��$�sc#A�Aa�,13��TL+A�v+�}If�Ӌ�K���83��%�mS�p�4d0����a� |�?�jI��x,��̒|��e |���� +���h4��BjR2��4���& +dAH5]rA��� Yo�4�3B�_(�I�7r�\���Ϋ���Ji0�Ս ���Z� �Qv�Z�⌰q�Q{���G����uK6��Ӄ��'�o��W�>ql0�l�����ҒQ-f1��e�� ���Ț-�D�-O��[�������G~2� 7�1g�>��b��:��VHEz��R����FKp���!dU�#b���x`ݒ��A퓥��w]%��j=�4��A%��;����, Gx<Tn�c�P�5 +�����&��p��M$A�U\as���O;o� � +�q���?�aI�A ��`lEB/� ^X1���)�E�5.�Z�a��d$E��H�����u�0�J�}�����]�8�sn��_�5#�w�I™Uf(6:7M� �b��w²�m�O��<1�|fr+1����K� +=��^���ʭk1C��8�hu�ja��N�N�J d]'U�X�� ����^f�5�Œ �S��(�o�M6���0e77,���d�؝K �/��'r��G�Y�%Tr7 ,�Q{ �qxT�=w+�(@) 8��d!� ɶ��U6��ʛ����)/�jΊ��9Q���ø�#�C�H� )"~ʓ��Dz�r���H���(p)}T�9bE�]Q!�2�ҵI(u�ew�fN'#-]��� ��JNz�0�&mşY�Z2��=p�do�� +�����շ��K�p"�R��@�jEO:��S�ohE�՟�eɼ�g��'l/�h�e�b%�:�LW�d� I�ہPZb����!���,��� N�W�� +�N�%|�/�i��N�L�4� b�<��,jQr�ȓ*��.���-�m����JU8��۔��5�و� ��T�즪���|+Kz���U��> �+�]4�s�ʟq]�=��"yzPQ�Ȃ��T l���(fG�6R:�(Q2�5� �ÀA-�Y:��EF��|C�O11���~��Q���]3 ���{���m�`�����T�kPP� �SYg�8��YMz�uy�*���[�w���:[�H��'���i����MS|�W!T��)�5���l׾�C�z����"�l��?h�i,�n�!f5 l�3��yө�y��b�}?D��D/I:J��8�,�3l�FB�;;���ZKQd�@�(�J�$�tһ�dM0׎������3>%��&����64�Xv�`g���~ȼX���.<��FTY ������w�8N���0�`*�Z�?ђ��`v18�� � !1��a�F� 6 {��OB��L}��Ǿ��0e�S��{���F��?����;�L�0�H�0 ��d�$&��g�ϩ��v<��ݝY�U]��N>��$l.�h?�A1�‘� H��� % v5/�m��Gd�%��(��%u���4�O�ӛIԍ"�]$k45��aP��Ux6Y����&}b� %N�.*��ft +T�/��\��\�QЀ +G{�"����W����cG2�%V��HRS3F�Yֱ�S��Wj����(��H�䑆a����ɍ��c��8]!�|�T�D �2֥N�/� Jl����J�H�c��i�g∲���C$� ��z�~W����g��U�H���F��N��)�3o �a�$n#�I8��lÞ]E;�]��~��tM�|�W���J��Ba �E�eQ����J���)��y�%A*p\D�$ K��"��nIR�(�;�)l���4�4Dz�t�qii�� �����ע��/ѥӎ� +s4#[�z��|�ȷX��q*� ��Ȑ@�x��0��u1ȯI,�7H��e�(V_J�b�RuC�$" 5�ٙ�Y@̠d�둆b\�k ��p�:�� q=�*fSSIz�� �τ���=X��#���G� �z �J෗ CIՇ3���I%(�$ȕG�=�)�9G��-΍�xĬ1WJ@fIEd�B���)�A�7":*�������P��7�,�Y�p�'m��:����w9*ܡ&�� ����8�Abˁg�L���4!��$������T�&)s��]g(��9'Ω��i:AVi��J�q� �zƹ�=�_ݥ]&�M��n#��PSJA�� +�&Ia�PC�Е'uGgբ���K�8 ��䋰*_����A,�űU^�/�L.~ V�E�/|T���,i�jU�����k�ݎ��8���Sᡪ +xĪ|�:K�BA�/4� ݡ��G2���?$T8ۣO��W����p +3��r��Q��&�Je #[^ �����R�r���|��(��tX;�B�|�����m f��E�����P�9�`"��?hL���GJ�� o��u�?�a������3�yPU�U���W&�����+M%[���:�:� SnSb�WjC�\k�H��oA|y/��3I�ԈdF��#! ��Ǟ���K?k�i�@Ls��p�ֲ�"I,�/��2F����:e���P&`�Ab�;�G�V*�z����0�d8x��3%�`�P���u,��,0G�&<��u��@E�N� G�X �]��}�b���-M2k-�����!��"�e�;xd�`��5 � >��.���:͛�?�K�^�З�� +)�o���$ �����Z*=r� �Ҡ/� +��p�X�@��2x�f�W�X����IrvR��D,OR�.%W |�2IL�T���rq����V�R�x��P�1�� Q�����l��2"h�kci���o�ĹJn� ���i���`��SPq\�aҔ:��n��'Xh�/C���^����̡1j푇��� +�PEc��ɞ��TU2k� +�a�U�I�?L�i���;�>�{m'f�哷]]X���V=��nb�]I,5.č�0��I��b��w�0�2z � +t�����F���W�\��¶X���"�T��HԂ�VEx����j)�������$�|�� \9��I�&�g�|B��Xm��h8�cb���)l��bt� ����#"��1�!�T�B�*� +L?��/����g{C�'$鉭S�J��bw(ӀܤNak�A��n G�q��� Ll8�`���p�@$��a=�c댝�`v��Rȋ� �Ol��;��K�o��N5�(�@�Y�=���0ɾ0���B��P����ǜE�b��r�0k^��z ]�+b"��D S�'@�B�K�lB+j4����Mɘ�:뛈R�JQ{R#h3��`����|�Rq���x�K�L�0�+��#d�)�+�#�)��\��0�+9L��`#�_�[�Hm��Z�(�D+��0�?Bc,Ec �� �qȸzƬ8��i,د�xAU�����6��ts�8��%^AB��Xpm�]J] ٬�ȇq���Q�?�t"Y4��P [�@X���I� �=%C�6e�XQ�4���b4�X�6\�+� iBi&oV��<{��0|[FCb�ě�6W�R�W��$��G2�XG0U�5��ѐJ!2���*Ѭ?��Td�� �#�l��}1b5 ����di!FA���,�1�pꋊ�d�cܟ��ଈ�)e6�TfTJ��c"ٷ�"(ZK'�1?\D�S\Xnό20��`y��j(�T,pE!,��z������gM���ZI�` -3�b�+� �H�FS���z�G�Q?�!E����s��ߕ,YJ,�=�L�W�4� +���tcFB;�$78p.sM7�L�33A�7)���gx�/1������0��'���X� +A#% �IaF)�O�i�΂��H�����6A�X��D\�NBȨ*�!'ޕ�� �HN=N��#�3�,�#.Y�U��'`$�,eNG9�")�ĨvBO��TgD�7�OD��?��uD�%�� +2E��m ++@]�H]�  �UMЭ�Ey��i����XDh��#�s &�$ay��ɚ�Ar�P d�f��x��LvƴG���# �8ى����ۈ�p���6 SA�YLF�+ �� 60��J!�%Hh#$�e���W�#��%L�0 +������!DNW�&x��qd Qv�*�����P$8&��̦"��F���h@�0ܑ�Ȯ���6���XQR�B��'$u���~����KT��k�d�H�1E{�i������4K��W� �D�ߢ�[��QN�6���f"LB�3J��=��`�'Ft'�[U�5&���Z""��P�F�xCb �*_�Ox%�3J2�?=�,&� NDuǕ�4+�bv�y�0Ũ]� �̙�̒ 0���3�2$����.��$� i�i��e�o�*��y�2؉� !ȇ��\�u6I8(� Y +m�Q�i�q�A���m��[0a.����B�cH3�PS��,�I�.�α'eB"��m�����C�F,�W�0�aN!�U�er���ń� Ra E.����B�� +���R[�C�u��R���:�X����K��&�_���L�$^��ȱSy�@���[<���R�Qn�c$�]w't����%F��yS�e���� @�H2�j�H�Ȑ%B=� +)�*� �J�Ȉ�@��x�=a�RdB�-�5Z��� ��W��SZ��PkX 1����I_n�c S���O� �� �T�� ��� + ��R54z9|qk�@lM¼�)&R��22�X�U�N!K�:S����Z��"4�_��B�>!�Yi��W#k��������a��pkCq�C`�=We����*-r�i-=�1(��i�8$ �R�o�PAnd7�^+G���kNU +אgc�XA�!��,/�f4��^5��oKkey� ۹�u +f�X��C��U��#yc�Jb FZ�7�JT\^��D��T�[@fu��X%��N�t�x6�}��e�dR�&��|��.�"$�5$�5�F$�U�+�6({�"���G��?�>�i������0g�*��������ud^�j-#��h�F���l-��[[�rMH 2ͩ'�K���F��5٘��8`�J���I@}��sK�EC�X���@A��A�|0�\�R�ٷt����/H���)�X� �� ҂��Fr��g�����������j�E�Zƒ���[ʏ2\A�AC�vP͔�P /4)���3��hQ��� R�p�X�*�8�?n0�/��5Ȋ�(��#Kg�w��Y�1�03k!�mm=W� {H� \�������6f�9ұ����P��:��ks�+皀�XH�PGyn)�!. �p,k��!+�4yL�#�3��z �S���`6��`����f1�e��D�V�������q��%>&��/�Qѐ\-��# +�C�������۞x�Ac z��Z�Tc�5������R�� �ck�14q&M��8R�JTbTf $g�T�?���$b���{*a�-g�zѨ�P8�d�� �^��y��Q���&��d+3�Y8Օ{��`L؏� �m��a���:�6����D��ZFjk��([��n�=a�T�CO� �L��Y�T�-L]�\�2M +�!�)��fE�%t�XyZ[ ��D1�u�h� �Ar=8�г-�f������jR�� +� �P��\�V��L/�%á��br �*Q�i )"V�Pۺ� ���:6����| <x�=����&����x:��6�J$H���az}��|ή �j ��/D�Q7J5��?�y���&T g�`|��P��0)!$.@�f�����F�ɼ'��L(���Le$ ";�5��$H�L�k=f�����21� ���U@����ϴ���! ���&�hwp� �4D;W0la �5�xXf d�>�r�}�G�v�����q`�x���~m���ɑ�b}$I�5"~)�2 +Z�~KL$S�_s�����v)�8.`(@� � + �`1p�A�D�.�1 � �o��$��&C��䆀���E����H�Wb�6�Ջ ��4s&�l�1,!�z���0[���0{l�M��(H2 κ�E-��������'�R@{L��%b�DЭ}-=K���0$d{��t1AFi\a���NH6�՝�v���u l��0��,(��S)S��j +{��Ę���V��T �j|"� a�-W���� " en���CR�I�K��8� PĊ��b���+؏�g�:P{+�?�O�\�� ��+CxA����֚�'�u~��j�f�!#-����@L)�GPwV験IH�u�`��ɋ<�r�q)� ��C���SE`q������b��P�ec")� Θ��)X�� g�RHX����A�P�Bw��D�J��,��#�AŔ42�YF:�̸C1������a�+�G���W%/V�1p�R�)�Qȧ�FE�X���yi@�ل�)�Z�ǯ�Xm#�*xQ� ��,�� �s�%Y����O�����Z���$b6� �RG#o�F g��+ +C���I⻙a���ʙ���Hf�FS�e�D�ɳА��" � �u� @�s {s�� � ��C4f���S�@��0��Q��L$_����HJ)b ~;�®�|>>,�| �hQU��V$��P��`�b�b����"��5'�ʿ�f�‡U#C�|n�Lm�"0A��U�lF��a�(-�� ?�*���DP �7H�F�����Ҧ�>��b"[��-Q��b����gD�# ��9Iz�$� +fmyТ:�O���E�qB�M"MNSc���(��|H�m�� +�9�T4n� Ŏ��[�ʥ�MC�ITM���&xhX�YK�|��8e��2��V4�l<�\$#^��Fb���Ry�0�a*�ߚŴ�X��S�_ź ��B�wh)b�� ����=9� +��@P[�C�|pb��Z|/����Z��|�RUG�AH�ɬ�!(�-/�ĺ�9a�A�+��IV� �A� +�XJ0!���J@ +銲�R�� �ۑx?/�[�8ZF�8!���[w�-$�x��S;.��� L��ڢj$�b�eY�а�\ƨ�����U�[,��l�8��V�@�-s�c���Q0!ƞ@���I���(�JE���aI��:�w�#��0 +�ݳ�&�$�hQ��B��L�0�r�F��Z��‰6B�';V�"A�)y,]H+���aKy�W�c� l#���e�:����6�@�M�z͒�X�u����Ǯ�7�����v\A�~�Us,��^ +Ņ"*W�f)K�I�,�a |���ЋˏIA�� �/h� �_G�g(� ��!.��T8�y�U?���_I@��ٵ��9k˱d1�/8\JV� 29]I���gD �$Dl3�A�0pDa����3�燎 �JĚb�e���Ć-�(*�<�)ڠ���x�Z�6e)6�~�=�TXD��IF�]��%�(� �4�ȷ����k,��*���AC����t�e@��\�(���`��6KX�l�($� ��Q�6H�n�`)�Ll�Mn:L�3 a�Ɨ$ 2yh��� �ʬ��a�B�#G�RV(�^^�.A<󄴉kX�R��jā( ��栰�o��9I,�<� x�LEr +6*�?��U�C s��QD��̴�����+�SO(����s-��q|.h�6+pшmK�P��)@�0���T�$�/�'0�F� C\� �����<�BB�G'8 �W(ш & oWʠN��iO,�'4���&(!��Q�T�I�f�x���`���#9`�/EF8�P,S�1*�8�����x�����`� +^��#_`��H=��F~�.��CV�u�. �D�;��<"0�'�����Y���\9��dB�@�\��Ƕ�t*5V2"{A�R'��������D�/ ���� ��uՐ\r'�6_/����-T(��R��WC,6FW�h��֝ ����B���~�DRV�C& y8��� L�����$�ĕ6�,~���<�V.D��P�h +�B쉷w��D$%�5w�߉�B[-���SBFl�@Mƽr#3!��lA��k�g-ԇ먪�J�w��xY���w��hȐ���:�:�d7)��O�K��*4!%A�"@$���nFr�@��UYWG�g�,�- ��%\/��j+cĎ�"�4b1������b�j'�� �'��&9j�E� ku�V5K���x`[P%�]���h{��oJ+����£ c�����.��(ٸ�E��+A�G8V�9M"WL|�+�3\ ^�<����M�ac�sJ�oxJ(��yp���&�Y����� ���R���)f����ːT|I�4�I�U��$�X�Q� D �#�߱:,x����Z�/�d����j'୨U��>�cC ;C~X�,V�g�62�$X"�hg�]$�*z�c��cN<,��+��S��A�C�G|�J�*O@TR��������H�@5.X��ʭ���Ւ/���� �DG�K7K��E�B>�=���1z��_ �*R��Zml,���B�:xQ�1���X���E8-��`0���p�Z$`�q$F�]�sg��aV ��g�MM0Pr�9�Ѻ�j�I$�~DR��� ��Y>�a�� �(Q �P�\@�Pķ��P�����$C; ���Dp�=x?��Z�/����J����Nf������%}�,,���i�A��is�h�P6�.J� ��p� 2$�B�G��[��. �ֳ�H�3h�tu�3�� ߔ�\��$29���ga�ˣ�@�"{"DZd~�c̞� =�K��T�a�PY��Didz8V� +��A5i}�P_����$L�i.�/P�K�n�R-� ��Ʃ�7 +8h�X `��c 4R�`��y�` tQ20yn�����A�ĔD��"D�Ӏ��fM�>����r#� �� +�r,r;�M(f��{�H�H�V���=%����r��z�\!:(vE-�/C�I����KGoL �8g�9��`ed�VYں�"�+t?���_=ɽF�S"H��NdKvq"� ZRH��xJ~�%�v5n &���J�ϧV�֎��z7��`��8� a��$��|̢�����Yg�:˲"S��t�\�D������ ���4��W���fxft,'� +Ĝj���;*�.���&�� v�(YG�Tbq�m�~�����TJg�)|�$��c�_U� ����c̵� �UH�0| TM,�-᚝�N�G�k�@�����@�K��,��UZ1=&����%!߰{*7�:�`R&����� �Ъ� Q\����#8�$|�[�σc  +�b) v�:�P�؞R�3��4�"�/J:�1� �����g���PU����*�"@l<��3�$�R ���Z�!|�#T@��DFrxB��vk|H�֦AV>����W��+�J;��Ad4u܍$��e�I��!�H}I�@Q��<`$��f���k��MD N��R(�e�2Z���ܾ�i ު$��\4�̠�#�P�!�&`�(�9��A���K�'�X�p�`���8֒?X�F�@5��2԰��r;��e9��IZ*9 S���"i�TL}�~!�LjKKhbȚV�dq:��H����&Z��z�2vov�P�6�������:�bJJ��Ř+?Au֚���)��+9)��<�Dvu#���h�mB���='�t��O�̯���H=q���M�(1�`��^��|� ��G�ru�Q� +KT��9��ě��� 0B�����joY^��m�,v' �>���0��`�iB�6Z�����H}4�$��;��Ǚ�n(�(��G�"�8AI�RIE��d���B�Vk�R�0IGZz�Hcb�תQ��!���.�K�a�%J������K#I�a�����f">,�j#zk�5!@��W �BR�N/�#z, ���B����!�>��$�/X\k,���5�K�`�(v +\i�#���\8�^� ����'��8g<ɂ�勰;c�� +� ��q�5"�O���,��� +/��zh�5`_���q%t�0*���@P�C[��6���nM2���-�2�!O��ZH�,�.?�s���D\'}U��<3� >�D��8b^'�E�%։�U�y�Y/�5��Tϡ������*�k�$�cra$cF#. ���2wdV?õ��+P� o ��T.`Y@ܨ1>IN�'���5@�rjB0>#��n|� �m�2���(�� !�*�ҽ��m�b�^����ؾѸ��h�� Ԕ8��iҢ�s��f�)8�Ύd7�%�|��98١D�>�����#����;�Q9����f�* 6�N��(&�^� \O ���M���a�9�P1�W���.�X$��Z�[\� �!>stream +�n�͕�G����J>�+u��'IЄDJ1�2vS�E�@)�݉Y�[q����Ąa(��;�H���E�����p��+x���R:��>�@cC;8@B[DH"��1o��M��> �sH�/:�14ڹ�GR� N����f��PCdM��I.:��z,�E`�ЪD[�{ �3����#'��A�$�3 ���h]� S^b '�H�`���9!ql2��`�!��� +� ;t0h�H��SZa �kL1J,~� $��.� 3�0��=K��%�!��o�.�]�AC��8zll�r �v�xJ�}H�C�hG5i�� ��!�RG4;i�T� +��uA��c������"�%h:�z�&B���Ӡ��z��`Rȯ�9��t+����,�&�,UƯ�ق�О�#�6cz3, mjp�qpPV���Z쁬�3��%��ȝ0w �1�z���DR��-�tc�b����Գ�l�pa'U a/���Yx-i�u�����D0��6�< )��K4�A�)핾�X�c�X�� >�'ʉF��k�l�E;�%9�Ӻ8CLÉ2�\�'�^��1AR�W�;R�!'S�t��p�8���T�:�zL�h�J�YE5�X4Y]�,�ǘ.O��0WB���*$Z�� ��O%�����ؖ����2�[���J6��� +n5!�CE��iR�u� 4������ +)G���n*1�@w�8��;*�H�6ȍ��{���� �=:���$RW���d_T���>�*��J���P��T��`�a�82A�g9 -M��shN`*k�[�x1n�z���_ �ٷ� l�v�p�l �h��0�bE����4.bG��U���!�# ��'I� ��N��'`v�Q��?�2��,&����p(������1�t`X�̌>'Bq����K䷝ֹ�����F}��M���R�w�?)m�:��F���;l�&���$�.�Z��q�vvҬk��n�5W�Jg����O5��M'K3��Bx� CM}6�>�������1M���F��w��\��/�a��vg�68j���ԛ��Li��ٱM���/,��z�n�-�[Uj�G���ٖ�Ѡ��i����ڍΠ�*U���s��Y='�l ��?��]��8X���� ��a�(1 ����W��7��g�D�6�f)-���Ο<2�O>�!8����?e�pd�aI��������.G�A�|m�O<������Wc����*5\m�!s��\�Cm��f� d�Ԩ�1�����[r�Kd�q�6��o}��-�t�� _f3W┌�R�����_��i�"ңs�����m�}|.��X���׈�= />��1�{��gdg��,����$ +�}w褏?m�R��|����F������t��o�&�!枛��1W6"�O�����n� T��l���+�<7;%i"�'9�9m3��s����AK:��ޠV?��N*�~�>�C�{���.<������(��m�vu��C�* u7J��0t{�:�z�VG�G���4Q�V�G%^2Roin���]�r�sx��l��]�!�nt>������ 6/V�-M��7Vjt��7�N���"^�'���z�#D;!���# �A 晤jMa93�����~�lF���*�F���ۭ9��o |O�˺� +��;�|5��忽N���sVh�Y��Q?�d�Gv1�N��(�{��+8>w�Ҟr�l��<3��d�7�6��th~�o~#�5��m�<�wV�6��ч�Z�>�[3\q�|��҈�R�r�sE�j�ɄNz���S�{�iֻ� k�_i��Z�_寓C�k��=�������zg��|=� s =^��r뿣?�<�7+��M��=����G�0#W�O*1�5$� PF) p5�����J�K�ɘ�J�� ��Vt�1�����On��K��`L�G�C�˩��W����P���_HucCPS���8� ��.e��g��P +������������Coz�Co������Ī��~Ă� �0��:/�>�֖��9�E��H�?$�G&��?$����Dr���P��a��m��a���j �N�T�O�����}]�8�R���$��+����J���AK�����e�+�ӟ#GǨD�b�+����'T��r�?���k����a��'a��!��Oh�n�~�`W�E� H�1���$A�&e����Pq�?�r(����r�����rS���ˌEW�x���k�SkL��pVk�.EsC�A�c�qQ�G��q��� t�>� �~�'��[25�N����ϐ-����Ŕ2�FݳZ}��A�#',�MZ�#=��� ~,��&�k��+}���U)�xv�K����*�k��� (��:ҵ�j���ڠۛm��O����)���� θ ^���\��I��l�%����w���A~�*'ؖ �ܫ6f��h�p������1ޮT~��!�z����Zڪ�O��sQm��Ϳ�2v�k�~����9�M�J�W�5ZS��?��5���Ka�%� �;��-��D�C���N�%��� +;t���F<�pSo�D�y�3�R��>Z�@��N��W�#�'V��F�h�TH�^�~�<� �Vx�U��,8���42dc���̇� |�;�a컱��'�W:n0���E�)�Ns`C�aX�A�����N����y�����q�����q#?.a]D(-w{�F������oʿ����w�@���炽�T����w�=��.\e��]�F�D�F��G��;ZA.��ϕ�R�����w%�2L&��̷�̕'% �ǥ��T���fN�S�/xU�Q��7�$+���v��c�������y��5�X�����V.�_����G�;����~1Z�]V;�h��1bvj��`А��p1!�`c-)���ǣ�:�$+�x�k�'�0��q����?�����������x}�4��7�/�>vJk柊���:pc/��;MQM�[�@�%Rq��\�wI�����ۍ�n�0�����:�= ]���X���I𭷍|���3��#ĝ�|�f��!�J Hb�ύ +����N�!��>���ugC+��.`� +�/�Z�� sr#/d(�c�#�r-��a�'��˼�J�<�*^���cg����: b�"'��A :?� }mՎ��w�1�c�.7!����-����ܒ1PY_6i����������)m�?�G "r3���7��l�\�Ϧ�zf����p̑�B�o'���w�\�Y#�T�q�(\1���;\ �S�4�G:�}` ��P̒���|G��sB����b�!:�f ��O�9{)�2{�:�����`H��"���йai��I|���X P��_��v�B��X���̧�]tV���2�kbOU�����p��D'�����r�C�2� ��ta� 7l��S~��t��=HR�Lc�Q������r����}�J�Nߗ�5���1���L�%NZD����0DO�=�a�N?D�nK0ܹ��)��{Nz̓�g�v�p�v�� '~��%a��F�9�ʇl�T�\�+t;��x9��)U����#�#�ʖ�y|�-|���� �����l�|*��C��8��J|2ԝPPza��$1��� �Y�. �'+a���4q����t;r���n��&$���ɏdT��@f]���: �Dy?S����a�M�"W�y��^~�e��پ�p�^H[��a$L��c7�҅}�F>W�m8B��H�R�¢�x�2h׈d��^e�B0DY��� w훯�\B�=;,��:NIQ#{�] �������w0�ձ�p���bAW �#�*<��lڶ�SB��Y3�����"�EA 7 �(�v;|e,b�,޲�>ǡ%~�,�*W��D�Q���PϚOs�����1FP����) Y煾�@d��PE�ߩ˹:A%�WC�G�,Ȟ�lK�#��Jظ>�y�+j�:C`���1�����%�pC��T8"�J�ʥ����1� :u/9�$JZ9�/|M���0q�$"�k����D%�� �A �W(v�<4,i�Jg ˰@�54�r]��a��S S����I����m�F�J��N��3� ����y'�r$� �=���u�+g���{7��M����t?��S�o�^'�����/���tv��g��:��V������k���c��`A$$9R�JJb@qStʨ@�w�A`T]�齃�u71��HB���] =�V�p-��W ������\ylX��I����j�B�������t����X� j,nbH]�!#9���|�=l\����/�V�4�1<�l���!�l�M1G����4J��9��^�?����g�k��YC��������?*�Q+���#�6��K"0\��l����o�A�sh���d�̖�5Ϲ'7خb��b��n粩-�1��-�6�#����ꍸٷn� ��͸����?�����nN���8�Xg��?������~ NX�PChn~R���L�G����U�����%﷚��2n�a� mH̥�>i4�Ont��?�N�p֏<���,�7X��Y��_�<� �o��~�ٍ�AVG�M\��_o��_�Ueax���;0b�f�h��k����]|金(H*���z���?�j��h�Θ��6pP�7Fրţ��r�q���O�<_�j�׮]�G��~�l5�l=��b��%���TcЫu�g5�c�fq���p8׮� �V�~C;B���d�G������?��&�T���\�6�vtw�h���?�Z��������q���_O�����0g�!��=4ۊ��CM���?�<ڍA��6���I�d��[�F���zH\[�u�ʽFMR�lj�4)���Q�����)O잷�!�ݎ���[6��L��tk�C�o������S޵��R��6Z��]Xf���71i��e��7~��Z��v���|>��6�C�����g@jg���|�d�6Q��u��j��%�nh���9��k�mHqy�T>tK���a���\��u�-��R:�t���A�X�9�j��w[�A�t�4��0�:-����R��>o� +��D��=�� + �R��W�����#�/����gfw~��L��a�\��HsyS�8�k��pm�|n�'~��:��k��j��|�ܡO��k������/���asP;h��{�'�o5����n�|�sM����*s[^r~V�� t̷��R�9(�Y�V��O��p��� ��}>83g����l;.�o��9>�7J;ݳ��HSH�Խ@�v��Y�Ts���0Z��u���l�]�m�hޤ��V�Ө� r��8��N��g���/m�<<~꽁��׼Vmu����^�G�w�T���uS}g�Q�v�)���l��F7ߙ�F���� g�I��+���;?3����9��:a�cd��62���N:���q����S��h�v�9�s��QF;z��3?�� �;��Y�3*������N�g�i��;?0���� �� �_�о�(g� +vj���ӿ�z�yfh0|��|lh�}%��]kǘwg�~N�.Zi�5��F�im`��f�^k�h��D�KZ��h��2Զ��><zDV1UR R�⼆�R�l��h�a��=0B��J�:F�}���*p ̷�-���hi>G�"j��>h����� }��M_�4�'�^��>���7�e����ɱt�R�x��W�鵢0���{E��|ψ�W���Lf��� ��6��I|������.�5,m��\і�!O�g`ėAv ���{#��t���vW.���f�gs��4(�� �jc��z#U��5�f����:�NA�4צz�jYI����A�����OwQt�|wH|��l� /��HC�_s�V�ɣ���c%�L ��eA��.��STZ�v�}��%��c�3+*�Zg�,�]�_l�W}]Z���J�����ޥLh��q�9[FWO��6K�Z��!�r}ͽ�eiDb,Β/��7J�m��~�� F��cț�?�+��Z�֮��D}�cұ i��n��|�aKFq}�Ҳ��7b�So�6Jo�v����=����\���o�B�pɐ�_��]l���9��|ɡ*6�R�†~���Y86{���������v���&��s�uo�K�+�|�X��ռ�[����t��o)�w��)��Z��^�~�k�}��62=SW|�����K��/�pW���q�s�|��%�y��o}��r����y�{C�����Dz���3�̋�+�Ɖ9��h�l�d����3� �r���,kXXÚ�D40s*hF��A`�!��{�T��Mi��sRqbP��]|i��id K�[���+�Ym� ~��3�s ���B|�!�1��jgyǻAs��{ߣ��G,� F�,T|#5Y��\�j��\@��ױY�l_Yd�%�Ղa�+�ׯ4�˅��C ,C �M�Em�=ru�j��2`\h��*�ިJ<��~n(�u�F �s�ĞS�猴�5�\�Yniug�;v ���.���%��߰�v��4��i�W��R��[�J� Xp�e��k�r��s�c�k�`����^�s<:� �0t�պ�Y��yv`z:B:F��f9��ػ�i��j����E'�� ���=˲� ��Y��Ϻ띣n�`��nLJ箘0V�`O�*ȅ����C钓����{�B��|������V���:;�y��ޒ�2�����@#��v� r~�a1�:N/m6N�&�5�r9�jݴ�kVa\ݴW�A^:Si,�v���3��t�ki�g����_�t��š꣛wy����κEC�ݍ��p،��k(�a��<���*�p���W�ɖ�Pߤa���kg7'f����[�Y��k�Ի�"6��i�g �_E���Y#��o��v��a��*}-c��i`Ǖǂ�^}��M�+��F�I ��چ?]��~��U�k\lT�\�64[C���R +g�`;��U 8;n��6:�9]I�Ѭ���^{��^(y���%s!����±�m �T6B��O�,���{ݳ��@�j��v�b����zP������2 �,2���u]�"'�.mޮ�N�#3�A�|&7h\�ɸ�u��������w��\I Ѯ~��R����9\�59hBL��M�q\+D�]Ҫ~���BCÕ:���r�4'���|�a��f�� >��V��YI�BP�Hˑf�8n����p��7�Y�7>�ٍ4=������0 �q�-o����W6m5��&��~�n7��y��ҭW���zzپY�ԋ֛0�!�4i�v��F}P$6TQLY]�s��W8�[@Ƀ��o1@��[�c� ���n0�w�Sڏ��j �X�cr��OO� ���Q6��v�Xl~�o�� +� ���q�s�ۛڅ�f�t����a$Ʒ֍7z�z��?G:b���/��N�K=Sxwe��q۫���:o �g�Fy��T왕<0����Il� ��� P��/�?�e�Q��R�l���M]4��a��Uj�m��8F�U�mZ5_�Pb��X�b�]��k� �+�q�ԷN��O�R_�N�N��O ̥Z����! ��e0���w�k��du��� #�/Z�;Fݟ��@�%3X�j�lai�E�F�Io�Ԫ��p�ڙ��(�?��`z��2�nd��! �J��G���~�s�r�W}P/~�F��k�]#$����5��Ou��Y1���.���ƕ�8�m���o0�C�֯V��^�����k�{��k�����e~s�6Xɵ�K����&������f����m�n�[?�uۆ��Ԟ�\튩I����$ �����m������D_��U*��U��˵3I�hf*�x b�\� �w�:ƽM�h����~�u�"m7������4Z�F���o^����z՜���S�ΓZا�����+&�h��h�@��/Z���m� ��N7�1�\�b�Z!��Ww���\�fNɾ_��y�.�߂ r�i�� Eq{���$1]r�n�Xp����߄����Am�Y��q#��V�>�� �����d3��‹�h�װ��� j��S�~h:k5�Tkoy{��G�r�h���p��<^x-i7�4��R=�8t�B�ڿ�r�ۿ�qíת_���fw�J�#Ob6�5�Qy�u�cqA�5B�����8{oQ�������P���^��s� �/�a(���:�f���1x��8N*��Qi�4���i��:󅌍���O��L�uj�p���Y��Y��Ӳ�}C�ߴ���z!�����;�%�KE�T�������z�4���5x�}��������L?��o�T�zk���έg�[���������������˵ŭ����[K��z\]���{n�q���ו�i��ңO�����K� o� ��h�V϶z6�?}���4�����+���/��y�� �T�����+_?V�w3��vw�_^��L-FwΫ+��ו����0+Gγ���ݍӣ�Ջ���˳�.��n����i���|�=�2}�:�vxd��~U���r��u\i-���UN�'�;whG��_���ߖ��eji����r����gwN��S��9�z�y"C��\-�5�~�o~zvXi�{�`�7�Ἴ�w�0���ىo�����T����o=���7�x��{�uw�t�ͺ��<�2;?hį}�p�����u����Z��NF3z@_n:��;[+s����[S�z&��� ��a�����2�X]�?-�^ݐ��ӫ_�7ﭷnN�gjqqu�[yr�X;z�x������5����+�ƴ�<˦�1��;�x����*+��݆�= �w��zy������Ʒ�Z���Jt��E�s�����reg�h��m����c3L%x��Y6�]t�n��;���)oWW�������=:j�;�.=t�.~����n>`����Q��|�Q]�<ܐݱ{-WG`p6�b�ɫ�7Y�b�Ԗ�n��� �/.nds ;a?ƛ�-�՞�A��ȅ[}wx�����dũ~X�y�,TW�y8=U馟F����?��r|���ϹOXMq��m��??syn��}�Nm̖���w���O 2����w�Fu�����I�{�:�9[�ϫ�o�$6{��8�K�v���ݙ\>>Y�Ǐ�/w��;���w�y�z5����ՙ�t�gIO�f�����!6��Je�����i������\�U��ւ���g�S��i=���Iŵ/�:�/ͬ�~T]] �J4����g�}�j����}9{X�:8lWZ�W���ɛ�����������s�z&~_�=:y`^�x�Mm�(�\9z�42��I\}�橥�f����~u�����/+�����{��p��������kkf��-� &o�}�,TN'ΚՅ5w�@���>�����v���Չ��^�g�W�A|l&�ػ� �2�h�d�w�NXq�[��{_�-�i������Y���+C6�W�w��{��A�+���'��^}��|��E�{��d{���;γ��%gc��j�uXq6�ò����lL�Y4�jK�g�q�o`�bӚ��1q�l��j�4���K��A:��Ϊ�ݓ]�+�D��0�Ѫ��i���Q�~�Ƴ����� �c/fFV�.1��ʞ<�޸.��Gw)��訛 �;�?Y��'�ן �L��O̿ޗ����'>-ٍ\xQ���w��^>����0�_k���ޏ1�%�a�[kv��T���E�UC;"��ʡ����'q�jn�Y����R�+���%�㊳���fq]�y��_��Ì�/Y.7��Ha�hu�^���?2��4�0���^��LOgV��~ѓv���Z]���M��f�؋���i���&�����k\� ����G��~3��a�*V�-�tyk@��� 3���wז7Zl2�&��� +L���7޺��-o��h�Y�RX �gg�~{p�Y���}d,�vݭ�GG��/���7]���}�p��څSf�G��?\�����y���H�G�O�����??~�\��s � ��^X���<|�v_3bs�,��޲u"�͓������WOF��>z����ۮ��K� +b�v�̚~���������nD��귧 +��0��C~�sk�h�Kw�y�nh�w�]�,�w�$~���n�,�:�s���K�*gE�\�0�ԛI�A�������+G闹�w����-M���Y���r�d�!6m��dR��!���֓��QY|��NIzZ^�/��.���+G/�`�B5t�O�T�����KǻO�>v����iy|��ïK���kՅ�Aa:�.߹�4��q����>Ӕ9f�Uo�!��9K;'7]��ý,����S���S�o��;�o��j&��|����h����b��|ev�pfi���ӂ�n��ݮv��u���oe��J��áO�5w����nw#(����󕧟���������{/͉|����^ /�� ;;}G�;a�^p��p�s+G�=�:G��U\���v�zkc�w��`�ۛsnS�G�'�zS]>z�����7�b�oE���}��x�����⽆�;�H,��W��Y���뇯��~�x��X�E�|*�37��pb2 {�^ai�kyۭ�Fr���xv�x)�td�t8W�H�?�.Z|��Ù� �a؊S�T���2�����j=옡gf'��׃r��U5���N�[>��d���e}L��9�ߚ� oݿ�FWv��뷹�dv{g`��~��xO�/�������•��g�l��.�HN��ۥݏV�z��ݳ�6��Ҋ��R�P�h�D���cw~�h����h��z:�TZ��/#z~�X��ꁳ�(�k���Pn��i܁��)�v7+����uz�M{��p������G����UW�ݧ�ȷ���T����7���(��H[�~���c�+�G�W��L�=�4sU��-s7���6�d��^ZhU'��ho{�_@��o��W�/d0S��wiN(A:���/&�B�y>׼3����mU�ܚ� ��ZK���r����>S�x6�j�}��?j��o�U�N�^�֦xI +���&�������!H~߽�=5B`�ytt����Õ�����'V�on�g��ju��������qD͘;-a˜�מR��{�K��?� �3�Z?������ކ��2ß:�Jpzx�z��U?Y~�|���6T��K /�O+ �3���k�Ӫ���K�>�4i�b��� �wj���Yy��"ɵ7K��7�W6����ߩ����6`�]���UL���+�at{a��C3Z��pըI�U�u=���Ȕ%OJ���s�ܟz��^a0�����xﰻQ���":xXߟ�jw*�w�ͻ7�m���'M�:8�~�x~��T�f:��?F�;,�._�hn���/'ʝ��~F熺��� qC��2r��s��o���<�UO�����x?߾�t��Y|����;���YgN��,A���O�ַ��F�o^��4�*;��t�1�I3‡��?����FQKa�yjuk*5�oj�ܥ��j}�����������w���Ф�ܞ¦?���R`��o1���T�f�R����?��'qIL!�$��n���E!�1���Њ͆�/B�)���W;�6�s�S��\i7;�*�?��_��,>8�~����:�s榶f��� |�� ^���/�?�G���A�H%k�O��>�A�X�~���F'�&���o��=�a�����­����[�'M�ۗ��[S��{���ެܚq��?�Z�)�_�4;v�Ow�C�85jn��?�­�^߽�?��!���?�GE�i6p�����%��'�oWǏL~�Z��ǯ�v��Yw^��6�-שV6�.5�s�ӛ||ɨo?9գ�{��M� �vk������Qמz����nq� G5'�`u��"̵��|qO^��o��-wҌt/�M����P��[�?j���SM��cG�]=���q�B�~�X�d�ѝ{�����F�9k�_^�u�)?hL�o9�ft�w���og&F6���������Ш���x�ŨGF5��o?mt��ڌg��F����w�KF��ħ��O����l=��rT�����_��{�;vԽG�KG�h��θQ���3������ۿ������ɉ���z�9�tԽ�_8���r߯9�6�Ə���{Y]Zx<~Գg�Ǎ + +��_}^�=�d��o;��l��ukq��?�����:G%���ܯo���%�~H������Q�=ko��?2*�>���L��M��ۛ�uɨo_:������&�gn�Z�8�������F/������z�O�\��w����{�8�tx��Η��e�:���a0����7��FG�w�?�QO�F�z�C����Zy���^��"�x�"�Z��rͨ˃ t���HF}�ň���p����G�0:��^�v����Ȩ�^�ѵ��٭�Q���y�]�Δ~����ϭ�o��֝��o������Dz�iM�o��>���nŦ]?<9x����S7��Y����'ǥ�>�w���M�?�g�K� ���;7�O��[)�{~ ����l +��j�a�+���{[:+ɔ�TVOK>.�B��B��z��� K:1q���21�э��Y�6��j2; ۠����S����8��wt�l��J&#����iR���tV�� �|V����40�?���vլ�gKgeE�?+s���P4^�^�qܝ�?��1����G��}���$�J~j��>��>��]�՝>�7:����wYg��?����H8sV6~�;>s�� �#2���g����+gӃ=9������?{C��+���_���x��1�����ٔ�e���g�ɩ����� }��VD�w��*�"�Y�z�v��ϋ�6�|l�z?^�4�����n�E��٦+7������ ��sN<�����\t�b�ap�:��c�&cF-�[� ������ ~��g�z �[ƁȻ���W�Q����|1� �pv�� 9����O�k�×����t� ovOZ�CB�ݩد���O�3<�W�h�f篍ҡ�����~�j t���+-��|m�?|� ��T���=������a����W� �����42�\�yZ�Y��<���E����p�����Κ���-�/�?n��I�����J�x)y������ �p)���g�~��n�7�p��•�-d�+%��u�ݾ�@����4�Oz�BfC'�,������1y�?�ߠ������ş����/�����\p=]��=>�����T�ъ��O��n� ��FS��>H���vU��i����ϻ�D�#w6�Mέ?*z�ش�[�?�V����'���y�������i.7 ׶�ypQ�����˝��v�- ���B��m�igM�з~�RI�@����t�w��b +��/y۲5�RU��6�\�`����eqŚ.�>,���^�5��hM�^����l��jm��"H�Ɠ����ps�G(w�G��I���<��0�.�,v��U9���]���6�k�� Z��I�ZC�Ƹ�a�tS��V.����J�:��~�h%Y�s�m�a��8Kz�Df}ق������6���>jH�8h'\������3��?HE���l +9I �<��E�n/kzHV�a����׫%uSV�� +�ʟp���;�z�Ƨ�z�GV�Ox�z����q��K���b��#�h�B˨�t'�j���nЫj��{�Y$f�׀Ğگ��f&������4ib/4��}Qtx�5t�T9f���T9r�Δ��}��\�ȥ�KT� �Qy�Ó�����]��_iI=�#�Ù�GL�5_)[�$rzZ�_��Cĉ�Fracx3L�ķ� ��t���\?Sj��_Y5�C���ˡh���GY5{��sz��z���:"�ݝp6s,���@��QFK�n���W?\�qԗ�}y3��磬 ,{$ ᕝx:Ai18 +��s=��iC��~�����h��K��|ur)�溧I?Ļf��<]kr"J�/y�WiE�������}Y$�2��ơL��K[�u�G��� @��M3r���\� �G +kJ��-�a��F%E�gq�G�q�A\��������t�qVT�Ź�2�ʈر�'V�ڋ�T�c��t{�Ha�f���F��PL���b-��.����ŷl�w+v�����;�����[��D�ώV���~��F����s������"�68���ny/� 4:w�(c���@���\/ +���lR���Tz}Zeg'#�Ŋ���"��$�(�UǵQC�=y���Y9Kj����?�,�j����h��⸈x�1�!i�~�w�`Fm�7�L�2����)����φU������@~�@�~C�tQ(�G��[�#=��i�H�[�h�����ڋ�э��7M�_I/G�||3��_��h�k��ϊ���b onpX�X�@�h��Qz�q��h�E��Mܒ����j�(������1%��!g��.��VT���J�4��(���+^Kr7���vwGqrgc4ڨt�XX�נ�+6��&�}���6����1�e,�Yf�r��@I�����ad����(0����:_��gƣB��t� zm��c��hI*��V��5�)�U�� ��6�f:��*ϑ+O©V� ���w�N�-�^Q�h�;�G�7�%m�����p�iNat^��Su"2�x�6����~ܤ41f������vˎ�i������݆۴��Xwv�Zi�V�?Q�P�L�͹��vX��_��:�S�2c� ��ZFH��IT��S%�o5��Fa�=�e��=X6@ 9�uu\�]O��4���-�{ �MW�)&$��{#&�U��Fz\���;�U�z�`ŎT�3�H��Y�蓮��|�K!�[�l����Jف���`��[�)P5�z9T��uY(����4��>��i=�T��' �U_k\�n����7�5��,K�)�XS������򛮩_��W��\��v�o,iQ���M)�i<�y<�8`{ՙyQ�qf�®��;3o��2�*�����cw���� 3�X�!�����Zuo�wf�D���$�;3/��f�g楃^ ��e�嬵��r�Ɛ��76�% ��^�j�M���OA/k���73�j�ʘ�f����k�@Á�d�����4h e9lD򾞻!ϯ܁��WO$���@�g�n� ֳg5/#C�审�ף�c?�)�~�i��28�<���~6��*U{>�MYx��T����M\h,y�kK �Z�@����J������k˹��ٙ(��ż� Yp��j����umX�I�˪&��h� �Z�&�~�v�ķP�v8�$��gcJ��@cI�E���I�e,I��Y���\�dB)/;0~i��=iz��3Iy%����b��V��5���p�t�e���ݯ�{M3�h����T;3�D�O�e�~vz���z_�v��*��GM���W���x|���l��>��w�g]�n�t�gṊ��Y���^-��{p���r���*��s?�~��hH~[~��c[��>�Q+��gel�Ϲ�7��.���IE��o��'��6�`)��u�`M��ZŲ�p�u�g⎳�^Q˕�� +0 |QU��s۽[k�ĬIΔ +�`�:�Uc�����z�O��߬5h��� tWh��u=V���Fh�7�l��c*��6��W� &�oH�͠�}EVB�m7�ľ��lFL�+�"��f�ľ����a1�����%�Q�R㈷)[b_�P5�L�H�VH��W��Kϱ%�e����I�+��k� ���K�5qǘ�W��A<�ľ"�'�ROb_QV�DIi���k�:]�@ ��W���7���A�FL��U߁y�ľR�s��}l�(�}��r�1%� �i'�Ugz�-��$�{܉}E`�1'�[���1$�1���;�ľ��ʘ�țq$�mGBUWb_mB�x�����!#[c�[}1�i=��TyO�|ό�8�ꬆ�S��#t�˭��D���W�r4۪˅ف���Oi�%�Dk���� �1Q��]��̚�2�^4�bY���Pk�M�e ԧ�jM�،rfS�U}�K�'����tW=�ȘLf&�Y��ڕ�k���Fn�7����P_��_)�I����ze�&�ʚ��5�\�����F{_�{?'��٩tj5j�W��ތ�����T����߄d����k~��h5���U�"��x46���G}u�������7=��a"���E8֝R$��Įv�7��k���4u���Ȑ�Ɏ���8H T�,��f��h���lJJ��>�DQU�������!���P+:Z5��P+���jE�5�W#���'s�H +z-VT=���5�[4J8�r�ȣ���' +��3�y�Fپ��/�پ/O�پ/O�X����ﳜ4ZoƖf����h7��M�جBm��G����lW�e���o�I��Uv\����W#��I +)}�]mn�vj�]�C/��u �>:�@�(c ���[F�c_zԌ(�=[�B1X�x~��_7H�h����D7߳����X�ר�ic��W����#7���A��8��5�ٌ���D�����X��o"��$;e��U}q��o��˷#k�l��g}���m��K��+?=3�.���ِپ�D�`To���i��Q ���<�XL�x ��ځ��s3�T=�<� +]ɾ/J�J�W�+s�����;P"U)8 }%+��`���,� AFc,����'ӌ%�v�]^��A�� � �w�BO�_U�= �)�v��������@�0�. �w� ��c�A:v}�-��y:vUޭs�e<�'��Ƚۺ�j�Z�,=|�6}����� /_�9��`���6�n��8ҳ+��D�G8�sv�R��O�HΚ�̣i.�_�m'=[��t˫��J2�����}ZV�I �n�%"�������|�����i�m�4���mN��)�u��A�KYk��������&o:1k:G�b6���h2I��sw�}/����&g;�R?g�;���vɬv���t�S�s�M�ۯ�usƖϺ�|�mѬ� /�J�zfg}Q�a����Y��w6��1�x?X�}rY��n�YJ��ߙU��w�|O����� �\X>�\� Nz�=?����=]�PZ��V��{��!:��5��pRR�Yk�l �i�;��zgJyZT�U�&>���Zm�_U�\u11��4��kL���V �*}}]�&����`ܪ��4GH��A��>M��٩��}¾�9���,YS����?���ZV�y�5�u���܊r8� �Z�r3 _/�3��A�?hP޻�s�q}\�(�ZSYf3|FT�[�q����(%v'����wC��ǿ��F)��y��(UNI��nQ���Ҽ�:�&_��@*񧥡(����x�`6c��?o�Ͱ1t��+#h z�7�K�-#���Mp��R��C$|��WRJ vz����` m�>#t��Φ�(�+�CbM�����*�s���ZS"C��N��y��f�N$ktU�%�u��y��@��f}�P��i=Q�fg��� ��R~+F�H�7�6���c�#��nZmK��6����d�\s���ݴ!S��#����'�5�G���7HIl��X��$%�i>b ;TJb�|Dqw���:/Vhs;XJb�|D޴�S�[Z�A&ҙ^��$6�G�[�C�$��)����{ʊ��5z�‰�M�FiV�|��ج0�~�-� +'�ԍ�Y��X�V[FoV8����؛��v��Ya!Dq�� +'���Ya���e��e�]��X.�vX�3@��j�D=ڮa��fU�Fnx�x�qT�*kx8 j؆������C5<�v!��7<,>��U��hx��@���a5ܤ����amB٘������f䆇���r ��0��\�Ô�s���ՏT���aarde���{�8{��O��auݲ~�}Ć���oU��V{�'*�U���.�]��(k�O�ß�L���Q��5<��c�hxX��FlxX��;�M���a���v����5�nx��G/��0�������⎥�au������a5�;�܎��FVt"�Δ�R.r ��P��14<����o�a軾�a�(=jԆ������7J! �J�kxX�rQ�=��a����K��2��� 9\Y]����Ǻ��ձ� ,a���� ��è� �GI�lFjxX6J��� �Xb"�Ea.Iv���)�x�ۡV��𰗯U�{u䆇��O�I��au�É��M����z6T��2D��jYQ"��a��p��R��x[��=�)��d+b}��Y�I��=��x�Le�H�NZ?��r�g2K_\Yn����l����[zvl{[�4e�>F������:Eb���»�3���P~�����'+������ở�9��pc������͹֏���Y�������ٯ��z���ЧO��ѭ�O���ξ���G������n�Q�|*x�����s�����������?f�ܟ������ţo��o�ߝ;9�Ϯ��;�O��<�;;c�6��?�=x0����;����r� p���Ϋ���� �M�/g�n��{�F�Q�����io�8?�ϝ_Do\L�����^�竅;K�7m�8��M��k����):��Ӣ��T�뭷���������5�D��_������=~X�_����7�ݘ�����˹ϳ��ӯ߾Z�99_ڸ��/���M!��a7]u���O�)qON8Cr��ƫW׽��#� l����2���^M�������#W�+��*��ko7�w���������ѵ{K���[�8��O�^s�|��;Y���z���-;u@�>�+�E��·��{��z��@�~}�����%�-�}4�C��O<������޴x���U��7K����?��vuo�ӄ�7]����'_�X���ҟoݐ�����.uo��>%� �v����4��n����ᷳ�[��W�}����7?y������<���z&���4�B��H����Y >��+27�ak?�?{o��I�>���|�q�/X��O��V��y��l�?y9A{�#���-j��ܾ�ic���dX�H�;5�C��º�J�l���p�����S���霽&�ysm!��]&��.}���گ����;w7�G�No����x�-��^��=���XH���Lq�_�>��nc��_�/��R�Ͼ�?�sf��z�)�)����'��{�����Oz��kǜ���ۢH������#���{�G_��. O˲څ.���g�˝����O=oie������߾w�_;�P��_{�q�� +;�||���Z����{ xyOX�S���ҵ���pq������|����<�z�������\;�x��ѡ�Ȥ� 7�aS>��Ȅ��d��򹺳�WJ��K}]�����s������|!������i%[ރ����_Wv�oBO~q�ΝT����F��8�%�獷�aBM��3?~��Wb�f��֍��2쿔� 8���jd���_�Z��v��R���ŗgP���zs�����VzM�?u��;��p��v0��=Q�������ɟ� s�5�^�x ���(��ڧ�t�}�i�+j��«7�����=�&��\IuD�\9��C��Y��pM�=��<��1z���2�M�a�\�mI�Kig� ��[9O�^��|(y���ed�Dp�P�c�O�q�Nj��o5�|����#����φ\D�>�\�7���$�Ѓ��,�oZ����?_���<�L��}*3������NS�����m�ۯ�{�?S�eN��qj����?���;I~>���׵�o��3�yp�Z���Y�ϯ��|K���$����_]kyknB��8�'\(7�pjq�(�Z����Vg�gu�Bgd�p�Ú��hAt1Rin9�c?an�v5�?Iw��"z�X�߮��v�]~\Bf-񟈆͹O��o�˄̞A?�Z�?���h��~��wc�Nv�U�x}=���|������/�ϰrg��8���;��V[��t��������ح/��_:�杛�k<5M�~�����.1��64ܛdӿ_`����_�{6_(���ݙ�?����gX]�X�On2���q�����_D��q��gKЍi���s�ǽ)/hi��Yz���ԫ���{t�M������|JL�޾}�Z[�|���ٝ����_ O��q6w�'�;�O���OV3��4� �57x�����8�ܸ7{�j��ѝ)w��v�QΜ�Ic����;d{����N��g-��8O��Β;���:x�`�>�S}���^�hze�M�ӑ�c������ ����|;��y�O�g�@��}�������w��>��G�ӓ��]���em�t"�:�8���W���=���T��E��������}k���ˏ��T����g��t���sv��_~n9��덛�+���u�ړ�OO��̵̍���{���B�����Y�J��f���:�[l��S�����F!�� �Z^۾��Z]>Ӟ��fGq�?/v��V��"� pk�o���a�o�9�@� m��aq�������R �a��9sn$� +d-�1�W��ɧ����� W�$�v�������[ _o�~�v�(��{]S0붃���3�ݭ읲+���~�(d�&��N�����/�Z�ZJ��\�\��r���(X;><=:���y�)�q��[�;��PI�J����淭�w>�����$���ٺ3�Z�����S׏�#�ؗ�sC�"q���-ݜ^;>��Z_x��MƝdžl��`�l��F����`�+���|z�_����]�?[]�.�Td*M)����zycj��S��@gjf-Z�Z��w�N-<��tj��_ܝj�7GS�Ov��n�M�T�|5�2*����k ����ߠ5dT�$��֐Q�/v�ZCFe���������2�9��ص�����,�YkȨ ��� ZCFe����!�2$�f�ZCFe��-��#���x�LVtm�8`��S��?��|�;5���c�����`����}55���������`�1d�L™�pIyiw����ܟ���]=��O���g�n`џ�{��Y1 �u.8� �]�u:�>�g�M}�WϬs��ȵV��_�,��{�E�����&O[X�i�~�(s�Ŏ��w���i)d�,�;��bmsp�}u"���: �������}�@�#%{��3���!m~�ldO�̽�'~�'�4��7w4� �g!�0�n��}�,�w'���=M" �?�s"n�V�m}=ʸ���.�.zcl�����Ͷ�u�G׽~�kg�򰷞�=�z.�3)����ޙY�qx#��,%P���C �=�q �N<��K�쬳ƀ��ǽ{��Y����ҟ�Nz�G|�Rf��:��.Dfg)�q�+��~aC\�X'AӤ�NwKWz�A��ݽ� +�O�U��x)�Q���0���ߢ��+ϸ��fS���\��'͵�>�p�rT_����ˁ^F�Mpf����*1ƽ77?w�h�J�p�2U����\�k94�"��2� ���.@�x����1h?$�_oZ�0N��=X� ���Q�&1�ş�^<��h�*����͵���υ�:K���e9\\,�/��� ϡ�@�1����o���kwo�����x���;�^Aߤ�8/��ށ�P����������N\=;>qZ���:Zd�A�,.����G��5��*���k��n����Nm`�,�ג??\�i1������A�u��.f�������e$��Q=�Уv�/w�H��/z�s7�wr���i24����C��z��U9�>�y�}�_�"� ��= ����z��c����_/Tϭ�i~��x�t/�u�W� ��3s�y�ekN���H�ۺ��C��CdX��,�l��L X�n�3��$K�i*���X@�S7�,N<�{m�hnn���Y��Kr�{�b�']y��椹 �.@(�B���u�;7��h�i ��GV��1c!N��8����i_�.�{���B<�t/ૅ������7�._�K/�/�����/�<���1�_5)�������0���&\||0�/Z��/�'�Oh�����k^�yz�����e�����΃����ޏoM�т�}�5}3�^�}5��9=���^n��\����痓���W���/_6���?/�<�~���?�/o�>���?������K�ே��/��&��'��>x�G�q� P��F�d��؏����v�L@M��^<۶����6�L�Ưl;��ѵ��:� ��m��d�mM�N�S4���u�,�_�+��������G�_�?� ��2��d�k�����O��?Y;V:T>������r�uWm���j}�ڂ��M�=��~{��&���e`h��V�0�G�?١����t�NĜ[���'�^^��y�er�ӹH�����g�ؽ��体KOO/_������>�ҋ��ߟ|�9� �Oέ��������?����3vtzp��A���������%eϗ��=ʿ6=�k뒞��W"�j'��'w�С����(j{��e���5ݎbc'��v��c�BC+>��mG�'���[�m�k�o�=��27��X�u�a��0�~�S�K����x^]�߱�t�<>4!N��q,m�c�㢦W�IK�ȋ����J�I��m��o��U�F�cM\��c�F�}�j��8$.h�H��! Xb��&�}~�V���o��F1����Qћ� +HA����'����uLb�i��(��d������R����= �f�$E�hz���)���i���E�Y�Ԙ(h�m���њp�CM���4�� ɜ�i�!pL� �v���� P�S�K�!�H��2~���K�MU�QDL>��Nv����|ZK�G�8��X^b�:���i���k����B +�9R�ԩSZ��7|�#z8"9�*�%�2���)3���S���o�,$�#>�����8��(�� +�h���3�,f��ozʿ+((�������MơϤcZ�#�HªH$��\ "^b�7*9(����]588�N�h3�*��,ql:s�Bg��+��I�4����+���͆��{�d� ��&�@h��m�L��1čh�0����O��#W�O�7��yDb=�s�ށn��ja7B�� �l�D� �/�:cz&�^C��u!�1�z����,�C~D�vdU@[H 44�ĝ��1$�l ��:����X�Ac���� Zz���d�_3���/��ˑ S�%Ex&�+�HЀ^+��T��`��(�"hߊ�+���WD�t��yXyƾ�[0O�����fN�����L��"�3d�H ��I!pR+��բɴN:Ҷ�t$��|�d���~$�6\1+���@(��iZ�����ظ%$�h���ɐ���Β�G�6�8�}�l�I��t8����X���z0a��������*�NX�t#�(f#�3��(��.�-r#IHC���/��@E&���5И���o W�E�{Ϗ-îx� I\��{&��5"��IzTZ�oL6+1�I�Ald� �?� +��]%ݎ֨}"�� �,y -Z� )2�C�-�udk�dƙ�g���m,{L[�o�=�2��虡G���K�%�RL�/��� �I&�!f�4��_�2��H<���L�ŞY:��8hw�w񟖏�G��_RC�����X���H�$FJ:!;f���\�E2�`� z�lJR�ȸ�bY��#b2l�j���p��|#��@��Et�x]����tp#��a�����*4��V�|�,����F��2�F,�,�0��4E�[��+x���A�b׌mE8��<�W�Ђ_�ԇ&u &F�1�T�&D�v��5���q�U��Z��Lb�f��Wm�ED��j�Z����|^x +�@�7"��M��7�Qc��A���lz�J�E*�VV�Y7Uħc"�!��JL�T)�G=%�\\����8hk�����$�!n$2�0fL ��Ý;�-I^v�) f�aI�+>= �b\���YW��dKGӆ!��A�Uc�d-��D��d� ��O�U�,]�=$j������S:�����&4�c{��E�_c��Yg|�~��~n�"���k��B�Ɉ�?�!�`f�N�Iqo�b��l�+"�p<���Q� +���P�S���h⛚�DJ�5X'qKRd�SZR! ��X7������/�H/ ��!j+�d����-�d�7�1�"#7*�}߭���"56BԐ� �*��sL�GG�X<&�1%���F!�4���k�!"UQ�}?�C"߷̻�#Qb2$AD��Q�3��F� �'�G����b]t%$"�1U����=b�^�����ʈ�f/V]�w�i;��Ž>�^ � ��t ��ɴ�`Փ� ���ѩ@�)����� +j� ,O2b���]ːtRz�B72��D�Zb�͌�&DX��?��ؑ[�� �@��muX�4/ d� +�<0F�X+=��~k`K�6:u0��t�B���A�3d����ȶV��$ߵ�L�;m��X�A��l +�� HC FH+�aL��I?��N[D�� �/� AѽʤM���i��;ܼ����^�Jo����Pk㠥G��P�N##$�C.���߈,%�k5_�������O$�]H�&Fh& z�!�����W|�A��i+!+�\)'�����h@r~��X �]!:d���� �(t�xY�[���Щ�{�r�=��P�����7�̇�DJF3#@��H��B�^�- E��.8N���ZJK&�!ՇUǦ+P����xZ�ë`��ί��w�,�� �< ������ ��t�9���?�Aw`�q��G�m܃��L�B(GD��v�Cm�/� q(�X2Y,�6M#��{|EB�3�� N�,7���*�֒(�H��l�<��?�h�Q���'�{����׏x��;��vJ�"���C}���������Y�P�����B���ޖ1t�F8�^��T3̼���Z�̀'��{75Q�g`�:���o@�ÇFi�n���J<�x�F��hl �`��������=����H�a�0���UH]Q@X��kH��,&ˎF&"�:5��g�8���º,�? 5�iH�?��K����P��B���x�'�O���� h�W�xK|l���7�6���I4 ���J�k-��I�%M&3٨d�@��oV������i>+��1��!�'�����7NC�Ig��&V�xm쑥j�2@���ܚ#�CR�ō�!�1U`�$�ͶٯE�A�zjTD9�b�`�{��DL/`����H��] �V�n8;�N$�OW"_�]tI����L��P|���sD�‡ +o��jF�������3!���{�C�B=�Q$MIӦE�Aӯ����*��>�d3+M6����9�c +�$�I�k0�p4R� i`V��w_)@��"� l��h�X؂���YGG{�B;^7�̝�3�ء�h/��46"�OD3���?��jOX-����{�'q8�;� �0ՙ�K�� +���&���ז��609�7�(�>�^�FpB�J�B�?�`����t`��a���P����o���#���z�M'��h4PQ�'= ���cH�˃�� +6�n2�� +�1���#�;#F;Yx;m����扴c��3A׶1��[�V�Cݳ%¶. 1^�=^�!�D�Փ>�q��r��("�X�0�(���-7Z�-2�;A؎|�N�9}ģ�Зa���^Bʍ�ơ� ����Zw�j �7�"zd%Dx�L������ �O8�ҧ�I��#�� e�o�V��q�L�A1�����f¶@��~�T�`@�얣sM׬�)��2�����Q�}�%ΡX`i�G�����L!9�0�he��8'��ME��4� ���M��r��U�K��0ȃ��\��"᧝&͞ ��d :Fz!�8,aE�:e���ļ���Ği.U�F����������jt��o������=A>[W��t��h��/eX�7���{�����C+�G��ƒ��.2�Z�"�$�6���Y��`��Ԍ� �G�� SZ%fI��Q��2�`�g�{��`��@E�vH'W!=vȪt� �9b�����. ��Cc8�UU��U%*_Z-e s#�s��� y�/9J��A](��uy���w�c�T���@�KaPp���’@Y�`}�[\��?d�B���I�m7�Gޥk G�B�EP�aV)�@�����҆��6�2��� Vp��B��x�!��?l��4������}�}ңK���c\Q� �V*�Z-i�w8!8#5���=:��_� ."�o�ydF��_D�8c|Dmp��GJ��OA�1�z!O�#CC ���7҈)IE���$�Ɔ���Ug湜���A��<+ ���;`�����;��,BYP-)����@��������-��aQ ��� Hg�cC��IЀ��a���OR�dzߡ$Kp��U��l:�xk�t���A$e9"ː� ��"�[���(�� ��?�7|!�p�� +D���pP�5 ��,ǚ�b@64G\#K3i z3PF�0��,�.�5bT� \��,Gq(��U�b5��At.X�^�2�\��e��f�pG^�9�IY'����F����m�͸:����wV�'��5���U�T=���  ��(&��/��hЁI��O�J�l� �\�"���6N�=��x ��P�&;`D�o��$�7Pᐒ����A��|.;=0t�$�2ad�����X<0�}����7�����$��H�N��~ H@���) +�e��R�J~�~G�E[ +k�c!�\�п��A��i�GN��HDF�5�ĩ�"�(��9#�K�&�a���#�պBA� ~@����$�=]dO�k9�Rx� �tqyRī|��s�0��N�M��!�u�D��!�;��ȥ�B#����1 z� E�:�X�Uo����E&���POsUR���8�T}>LM���$�0Ap�!`AEa�=>�(�*��'� �;��}xBŶ�)�Ҵ�j˱\ lP�a(v?��,��h=�heZ���`�G��§ �B �}!��0 lT(F_� p��Iyտ���2oU~�1G�" �I��G�������������u�:�����Q����"�����Ւ������{�0����T���'�����c�� %I����ᅒ0��y,Pb��99G��e�c����}��>�8�p�`�����H�N�?�5� �lD �Z dKħ�KC��<+VP�!# �&��r) ��Kd��Vh���i,Y����L�� ?,6��+��E\�����"��w�VH6W���/��A��$TA<9���Z�Ж�K� �ˑ9C?���JM7����5���# ��Q A*RZH�U +WX�� +~�u"�v� #�X=�4d���m��҄�����q�3.��tX)2A$b�[��6Va��@j�ݲ�FI�,k +C��i>3���NBZKR���@�g��&��@Z:�<��\���0���ڇR��ϕ�ً�U,I&٢\+Z�.�$���P� �$R� +h(��. G����b7>k�tц΍1���%T��U��P �ֆC)@4�(b��R�ń&~¨��)Ѷ��fPM��&��\3+VN27u��Ԝ��_�~a��+��H50�-Yqrc����""�a���$�ic�O��x�t��̦.�� dj"�=��(��\4�(H�"��E@Q�'eq1�8wd8�h���;^�"�mF�C�� ��hq���n�i��'�!��Ox�,�9�j-�j���X¬d@��f��5�"�Mp �>t��S1b 9�~t�j�{a z�H��.�-��"�]Qt +8m#pxD��܇ ��H�¾�b�ȵ6����N�z��=�hP�>7�o�h�r,Ny�J�� m�"&z<��%�DKݯ�%��[��IhzQѭ����J#��\ˇa��4��)����I��R��%��*!<8k�c}.!bP)��C ���m=s�3K�)׻�A5h�����A�%��?�}c.� }uQA $��v姹p��G���P*& Q�Q��7����GF��j)$����#��h�+B�k�s�K��OШgǽ�|��ɞ��� +%���02m�+E�]�!�G\+i�J{���8�8�&6>��\��ؤAB��$����0��l�7/l�ײ6.����fa��o&��?*�*-e�[Z�ʦld:i�Ja�툸�>�s�5K�\�zF7[��A o��� C��i>3�όE�Ȇq3�4��g*K���Ht�PND��|i�ѫ �4H7��L +�2./ �Ѐ3�8��s�v�O��>�̌���h�(!��q�p�n�H���"�o!:��E��h#�ٟ�A��c�#�4%�6�U�ъi�r�t���9��pk�96%�]�1�7oMӬ�5������W�ݵ21���9�`�ĵQK�g���´Z��\�s�E��۲�w��0Z'J�d�1q����6q�N�)�i�p�Q���w��jP�;[*��Q u8��$��"�Cz�Ն�nB�o���B �G�&�����YuAk�?���m��CgK��v g�Ӑ{$CS afB��fPH +��Oȅܬ4�a�-�w�M�7�Y���҇�\R�y�� .|`#�z��1�_�qbF� ]�~hp�r�TƝ �zFvH �ِ�Ţ_�$�`c���{�P��p��@��"܊�[9Q*�J���q�Uq�})��i5tW%>6�e KW�^ p��P��B�!�3�W�>����p��l/��e���#bF�l�8�ĝ�C�Fxu�^�-U���d�C��� �е9�JJ41h��"�d�G�{��M��WB�@vX�z1H��{�1����{��m%�(v\���(�>K�$�kQO�X %.�U��(�F�m,�([�Yф�4�eҢ�5w�C�/꬐�� � ��1�$�rU���0_`��G� I�%��w��&4���]��� ��.��j������ ��@ɂy�a�N��!%�U����CO3��r��8XGȱG��S�'C��`|�� +�rbTsW�U�����N'�1�����\H(����)��{�:�O��^��zЇR�^iO���>Ni����n��A'�I�u�}I;c�K$3��P������E����C�csc�HF<�C0�ޘ��`��6���jPUs�2��(a@�0A)�4x�� ������-�I<+▍�g6.�5��>B7�&�4��VM�B��ST�5�jge�2Z���\! א��DX���v��f�E�b̀$*bל��ͭ=�MGpY�MP�Ncf*��d�2HlFPHPa�S������L��(Ȑ E�xT���N�Nu�6"�R��9�}���͎�녤<6{Wq#�h).�!��X�>�Y + rvah��w:s#k���C:�|P�j9K/� ZJ�*���$$Qm:�uxò?@N�L����b��H�Dǚ�SQ�;rMvt(�%Yw��C���L�����²Da�� �����i�xƺ0r��>L�v c�~ |i���!�RE�n�bD���Iae$��=º��ʓ�u>8��r����Hk@Dh��W��"�Cv�p|09�-��*��/��d UG[t��l� {��-�8���D�B8 �b�Y|�5b�N�I1���C�Bc���_I��'�YS'�f)���5Jj{I{��+� t�H�ݲ�jǭ_%=�+̡Sb��ύ_� + +���,����r0�v�����bsYr�����ד�)�>�d2V c���*� 8�nC���s�����_�m�מI�����KZ�h�?��i��}Э�T��3�b�zP}�_�F#%�;K +$�B(�CcNdR�n%��g��G���Ԝ!f�4��2@01�N_Qq��\z�W�)E +W� E�2�4��>��CL�260R?�� Iܓ\ߨ�h�#�RE -Y�v͡b�����m`�0��r�j�5��P�f-� �0ᰠ�D_x~�8��^#�ء��p��S�B�����5�o'o��>E�&o�"�,��Cw�}]&��z�7��Q�~P�i���Yp#"� �$�D`u�}_P}}T�57��.b�>��w���A�i1���BF_x���0�3�mXe�?�EJE��dd$��F�&�z���o"j�.L .k6�|H��7$xdĿ�n�b�E9�Gƒ�:��KW:�uq�hۘ������f�5j,��4�߸H�� ��nd�*V@�p�(̤I��������0#���3��A����tNd��Ot�_��O_��.�N� ��TOIzh�b��u�fD&"X9�� D3EH=��!�)������mA_F1+�8������3��gl��w���:cQ�F��.�8c�L�)<+�;�ZB��r���=�ߵ�G����`>\��[d VB��#н�+: �C����Er�R�A؉��x�����-w�B����ao �5m��P~"x����E�ȴF!.;U��܋���8�0�������4ʅ� ��w�D[���3���'�FI��$P��V��J����})��u$��Q� +��>��+�f�hӈ�_\��� +�n�@<�tg��^���3.�G�4@ ��Rr +-��T�b1{���ߎ��j�ʉ��ixR=��[Kl���V��+���2��]�3�W��� �A�y��9�63(�̵N�7���%R�X!F� i@�9�Ѣ�9�_��<�i��d�IYW�ى �+�P�J���5�b��H>4�Y��z� +���� R�N@�HN�Eb���ⅉ�Ņ��� �B��!.��PX���X+���1�� QlY�(�W�/�߮K���C���8i$��� +�}*�_ ��C�G�+Q�}�RF���o���T��d"��6=Ĭ���"�Z�!���.���v�$�搅� +d� + �`�rqĄ|$�,�CAU\+&b!��J��XRmPe�3��`"�"�^G^� +����QW�̆����_0�� IX4�D� �R�#�ڊ �\�.�½\�|3������%��� +�9����ُy�޳�]�2q�E-A8}pxc�)�]y����C��s��'1���WV�P���6x͑�$���v���e��}8=\ |OK�3�tYG��^j��6���m���,�9"�� +��{��abU�r�wPk +�s(|���q;!�*P��h������Z��э�̵���1h���x���6���m��L�t�C�:D�U���Zi3�&@J`X%�M�u�P��G�[A�`IS�%J2"��B9 ���D���h�����҃�øJd�jvn��yi23�dH�� w/)��;T�@�X�x�G W�a�&�]t��6P�������5T�>�HL�W�%�>H�E�$K8�O���YQ0�~��t�,wŠ�?r���S ڄ�W0��lW(�"S�rH6�p"5jR�3��?� ~�Q�x8� ��!W6Q�+����`�.` �B N����u ���e��_з;�4[F�ѻ 9�� +)��9�I�VO���Ě���YTa�k�=�\>QJ����;p# =(6�]�K9� �a8-�U��1�z�)& �G�<W��f���dB�_RKy�V!���� +�q-׭���2��L�i<-G�c�\�9�v�+*3NG��4��?� �����pm@#.�PW�DłUB���\�%ss�XPd gK�'4�vK���� ��1ÍP5T(\��L"��g9��Y�W�L�Z +���f��έ��r3�@UF]̎2��@2x���cdž;� I��>�/q�cT�o�灦-x��\�c�p������� ��jEY���n�1�"� � ��ń:̼���]'7��O{E��R��l *�=-e��_�/)rhA���I��#X����3 �;�]C��W.F-ΐ�����x��Z�Ĭj�%��,#�}�t_�à)/�q ��� g���%�a�;U�5,\�ФE�A���� �8�|��.n/Ma��� ��cV�Xc��(�j��(~=V�N�9sFth(��šH��C�*�ש%��PԈ)�� �c�K��z@�Pv���WH�`����u�(��4��6�Oa �7�U v1�iù��R��T�NEp��=Up/���ڣ&�p�g��"��M���Ht��2#���Kq +���e�7Z/ޮ2h��-����B��g%p��!��b d�Y<|z(�$��0��l��������P@l�y#c ,����`z-�E����'ցDl���� !�h��<� `l��c!���qD6-8�ѱ����C�,x�C��j-��t :�����x�5��c/*���쳻�j�,{�C��f\���,l�HW���)�N�$JA0��P�$�̰���dS0��g��,���KP +�V�����i��b\Ҙ��&%v����f("����@!,����1�N +�;��2�(�ō�il���� ��e|W��� 5*5P�Ɔ�z#�{�H!7@h�Q �c#��o���P���Ah��#Tp��0���eС�sF���U1��@ ������i���P֊1�gPh��Q��P�3�a���8�BT��w��F��r���x�'j��N柺aWf?#��f� p����S�ƅ���-Z�������u?�|�� ��b�PL�PC�66���0Ɯ#� ��na��YA��q1�����C�0f���`с�}=��� ��-!���3V�BpOCF�A�d)��@�@��ҵ�#NE�j:�­�6��0� �D%��F��-�K�4��ݬJ����!Y�aS�/�E[(b��*v.�ph1Z�h�`q>w�P���4_-`.:m��\%�V)�5���ym����."߲z+%���_�/�߹|��b�sBj# A^A(�j���"�`x�48�X�z� ����j�#��I`'p�F����r��Gя !��@�2�cM" �/t�CS���� "��nȞrD}9�(fc䠤��� +���O0HZ��B>b���� �.���Ң}���P�\ФN@. U?�� u9�����}6BQ1-��,K�+��Ax��A`B���,* r�6���2���l���R�4��>��M��g�m$�`?��[�U�r����xq�`���-�|E򵲷� (z�����!�K�p�x�8�tCrɧ���L�&Kr��v(�%c%.���v�+pξS��ar���PX� �9t�h �p�mx��I��pu��n�W����n�BE���p�u��]%e����E�3�t�� +�a�������MW?rpj�v�Z�v�%S{>P���ׂ'}��#�X��9i����V�38"�?3\�"�"*��χ �A�C�X@��|Ӣ��* JC�"n�L*@m ���1R�,BO0 ����!m���5��I/�t����U������^ �Q�9Y��6�C�E��l��'��Nõ"=UkOsim���Le�:R{�T�����x�{u���;�рhxo=)��5��" C��ޮ�)z�"����H_��h��AhpB�Rf9�h.�Ű]�ه�&���� �x���旀��|XsA��� ���!*��cd�� �ڬ��n�Z��;P������H���EdGs#�@*����bĨ3�����d�����m��C�ϢNa �G��pz�K��c�ʙ �џ�r�(��z{��(��pf�a���&�4�8�·�� �6�8ƿ ~�=�?D�2�͠�z6��L5�ko[���J`١�b=0�l ^Aq�~�m}��PJ���Md,�����%LȥKV�˝Ϲ����& ��Z!$cn��E�h(�6B�@N?� ��B�K��CU>��* �\�G��M%4ɼ�����ͤ�+(��3ҳ�ÖU�Oa������}����E�V�b��E�=4������!&�4�4��0M��tE�5P��#5(P���c �S�,fA����)\�eBֆ��d8(���[�D�Kkt�e������v�5�|�ᨧ�};���i팥�#����()�r0ٹ�6/>~Dΐ, ~��{�r�� W|�E�X� ��Zkd:��y��Q+A�Ch��p�K���da~��Phќ�Ē�\�S!�#����g� x�XD-�ȁjP�/s�&P\�d�T�q?�ĝ�s�ThF�_���})�h�G�C.i���`��z(�T� b��C��/���-`W#�jn�f\���I�V,�G�"�����=���Dz8� ��!�#��d�(��L0�AP+$�[��F(���忸-�h_<��\��!J^左���⨚l ��I�kB�J�I;Ñ9����77�b6��I�d y,(�o��W,D�8~�nx���"���V�H���.hm�Y;Mge� +,%�4�����:�5�����.<.Z� �B5Q����!)�� �@�h���2�}U`�����G�S�G��aƙ:�v0�jr,D���@,{6Ѷ�q}��Q0���8M%b�c�XÆ��̎戠悗��@�g�ð'QQs�8��{~Tps�!�(���w��c����|^ �E�p3��+����!(���֤ �n">���u^$��l����ZZ��Ls�D�1ܨ@׉k`g�ǀS ��:��R���E��8��*�DR�>0�����h�nH�X��qhɨ#��6ph +��D�֊6i n%��ҹi�,̙憛��tZ� �/��m�+����bh��#�=��x$ZRC" @!�'����mU�Q��p*���/��"Z_K}���޻�8�4ٹ��r� ���2�H����� �O7 ��z{ٷ�#���LF�/fI� �������0�۲�)�}�Te8p 8{y#�����4�O��Eϕ���g ��m�7���"�*t6p����e�����?��'�d����Zyc,>ѻ����oLZ��eqς�C��gvI��Pc�*J e���P��X���wj;!˅3랠��VQ\JɷH�fY�I�������q��\�TGӄIgVE"��f����׫�2�&��(~�*��&j[A��Q*��w^�M���8� 1�D�h�4�U�QH�#�@��QY6���hM��4�' q������\�@�tp�b,.aÍ*��Q �f�o)�N��!~���x���N@ +��=L�s8���t&7��>?���T5��$�}��v��A�pu�)���~kwS�ݳ����B;�6%B1�y��{���f�橧�C��em�!)]l�ؾH +a2Ѩ@+�Q2�%��z ���� �=%������”bv?,.���l�g���<�f���3 +j8�i$ +C��0�1�Zq1� +��,�����c�k!m*N&Y +l`D�s,)���O��  b%�����(�@��i@�W�@�������|ɉ����@" +�Y���JU����q���B���i珘�>��"<�r��Ai\ �''usNi�z�_��kg��&3�̅�1&r&H����ZSq��:uAV �9�<��H�O�n�,�>I�%,�Kj�oK8b�� �˰]'�f�����g%h�# ��W�G۷B�5����ܮ-���#p@�l�S��*�c�]~�Y���G@$B� �.zbjέ)�˚�+�7k7���:�\.�)2�/۠�z���|l��ɵ�t���?иy�ԕ�~�nw�^��M���f<EY�i�3x�,�V��@�Œ`�5�C�PBCx-L�?\m����*Kjz5��Ɓ�!����4��\�T��J�bw��hڭ�D��P��G��S�|� +��^_a\�m4��<{�&�7��6�2�� +��F� ���0��nQl������||_���3��K���閅1~K||�A���GEd���#Dl�KgrQC>)�K��:&Q|��HP >G��D0]�)D�?�i�R���s���\�=�����b]N������x�L�<���v���AtUUy(7z�?��K+�c�0~��5n�ݪF3��n$�f�K�I�K�2�$X0QJM��e yN�����`���$�h�-ܱ�����O$��ݑ*�A���o1Ώ<�����7cOK��p���a%�4�Q!��!g��In��&҄5 +�A��j���DP o��u�X'������J�x楗lאb��SP���~�gd4řCRM`�����TqO��b���]Z��(5@�ǟ~];�|��H���fs���||[��Т2�P�O��~qg�;%�I�ab'��o���2��/���Gd���7�,������J�J.�3ظ95`I=7�YY(�/�W�8cI��#�O�0�� E�ˍ�~�p�R3�=T�C��~��L��[�Q��,Q����n�p@H�E�K�y-��Q�e�u�����|tS�S�)������_�,�X�x�@�t!C��� +a+�%�@�GV�����v��A����ugѥT�%>�8� ���MH�Źс����FQ) �� ������s�ݠuF�5i����I[QM�m�\"�- +���Ǎ��ƣ�+B \{�B�����z��L%� i��O� �(V �MOð:p�Q]�$��;M���ܔ0�#�$� �5~J������OU������3Q���'�[�����!#N>uv^�� �7e!fh���x��.T��1��a/ ]lZR���ov�hfm��`��i����ע�m��~a$�hݽ��_����[��m��=�?*��t���Ÿ����[8��Xb`� ɉ�.@��4%���)��}$ �� +�n����Xt%��N�*�q��h�q��6�;w�."L�RPi�t�����"A.�"3��]��&9� ¾�z3����$�{t>N� "��=�UŵE������C��|� E�x8��ܹdFh�" +��M]�P��&~�"�VX���)6�蟴�g8I�^媫���5�_�xP��q}�i���}?��mϱB�t�k�:.!�{�^�nJk���!���~�bQ,��@|�$H������;b3�^��B����hiɗ�⇷=߶NF1ɧ���'0㝀���꣄&0��iK|�����>���j��]F(��o�A$%����`��0ɒ�v�3���3Ε�QfH�EJa�N������l���[(.��{�似��Xɜ�-�Z4w���H��+%���� �=ؔ��{Ҭ��s��=���"]O����iJ^��+kO��c�`kj>B��{�[2�ÔƑ]�xO������~!Z)����S·/��u�\�'o� f�w_��"vC1F��۽y!��A�0���Ks �m�X8�E#X`����˪N��gJ!�Ҁ�¦��T[H��B��/����={��(�͍ZBՇ�he�l�ԱڐY�Kt,o�K]�-���ެs���Kb�P���$��=cJb�_�؝q}��_����e~��'�%3��4!.�䃾�>����Byh���a�"CA+q/�Y\^�;J9��9F�� ��pԖ���.�+��!$0O�u��[��E�&�Ғ�Ip��';2��t����A� X�r�wly>����pظ�Os|!u�}�0`�����.�D��1��a�o�l�AI$7&q�?�>4ޗ6�8���"�I|�8)4� vXt]b��n���!�7 �a+�C�9��A����o,B-��$E���-Թh`�N�/�;h9�dą�a�V��@�����4�P��'S�kD� 1�I鍽�S% o~�z�~*$>㍅v���|h�e�9@1W���ԲF��,�ÙV��Ѫ#$�q��dT�/E61%�>ڟ�Yi)�<i'���ɢ,Wr��֦�G�r�L��@��jy��}z�2�C�D�����0Ee_���o/h��7 @(��/�K�i%�Ř��d�4J�O�����w��PYR��"�1��ӈ�VW���BܡB�����w���3Ѝ�Qb�/.�{/M�����@/ E��$��q��2�o/��z�0Re�">�Y xZ�ŧf�����i �0��x����||_��\nFsTO�{��n�Y����n~�����%D�u���N?��y�^���ʑ�pq؞���ds�.5�b��S6 \m�frKKEhI�\\�{ +��p1r����u�D���� Ұ r�Y���� ������K���XT�d^�n���������Hd�`.���IV1�Ak�����p�n���uj��A�d����/��q��s �O�x����;y{�8��Kk�J��[�O,�41Qd⓲ +c���Cͧ)��m��wiq���F����%Z�d�8~�@KT)�݉D���0ӌ�:�=8�sabi՝h],ԓ.y�m�����<���sv�u��KF�i�n�z+��~v`g�K� , G.ř��W,�o:�j��Jx�I۶{�.�zxj`�- r�? yyqT��Ѕ���V H}�c\��'����*fy��5��d��Rs�q��� N�H��df|\fS���烛�%��`^S{��Էީ;�^��,1�:�jz�dz����@�9^U�ic�A>�G[^����� @+q�X��kD�O"� �-��+��S�WpD�q>���� ~$�&KO^����8��XH&�l�xt/�A���>����U�ɽJԲ°¹Q\�Z,�����$������v�E�Ņ +�K��q���f� �h���hJ�]����C�1�K���8���z�D &�\*ɥ��B�&�c�7G8�-h +.]�[��%��P�|�s���}��a�= +���6ϳ�F��W��P��\Ts���+0��@�����)��>�������L�5�C!�� e����w���kTֺT�\�Bi���ɏQ�4�Տ�_/�@�_E�9 |��K������:$x���(4�Y�r�K��o֫#�s������iT� �;gFK��ړ�eR� �N�%=��S�a@y�Ⱦ���Sݪ�����'�Au���*JA/���x�����N~Ա�䌮�$F��=��X<^OY�s$ k�$|b�{�Y�f ��L:����Ҧҩ]�)�����f!ŧ/>��&PTv;�C��%8����4�Z��� �ѻ4-|@�O$?f*��4<���z�ı�&���5���dg��{.v��,������$����Մ�un��枻���&�g��y�8 +��w�>��LBw�{>����]�\I�i�s�jF�*�����ퟱ�%� �WO�W=џ��Һ�৫��2�tJ��X�ऐZg ��.�pR���� ��4D,��| �����1��V}��tP��@��)0/���Ҵ�a�'�3� ��O|�]�([��2c"L���5�GT�U;���>�(���T���"Z������5�c2B�ܨ3�~|��-�&\��:J����z��^T�v�,�������Zs_t )0Õ�� ���� �I31��Y l�>c̗�� �=EYT�J�ɽ�F_R�>b�~�BYI���s�D(Hʁ��S��Yy�٧L����� +�x�n����Q�4��c�L�����Ez>3��aG��=��V_�aBy��*!��+��BS��f�gd���i�1JEth趬A�;�=`[^/'�-.��4�#m�XLj�V z�:s`�ku� +�A],��5�ZTB=��)&�>i�w��|wKZM1yk +l�'DYazJ�D�ǫ+�`��\���>$�J��CRF����"����ZA�>$b�Qfj���pm- ��CT�9�Z��=����K*���{ѳ=� �,h#��>4��u ׊�tgG�� �Z���^Vb�z�~0l���qɼxi��X� vAa���ƛ�҉�z "��(>�ɼ*i'��j�\�{�W�mѿj1�*4����(�`�4��@�З�Q%� ,划�+i�8��T-}�JNP�&���m�ǷUί���+��i��q��~���G�5w/>���斷81,��]XoK~F�J1o�ļ�f�p|W�BEj��� ,)�U�*�\ߘ�T�y �bfQ�s{M�۸��9�P��'`�#����~c��׺�Xtaof�S���vxQ�1�W?̯�?��� N8v��/Q������ �W�`��X���d�p�ވG���|p�"�?�q���ٿ�m���7���:�+ ) �����w�u�P@'��4���TJÌ�W���Z�Lǘ���[֟i���΢����Z��$��i���bq�S@A�Ф; 9n�pf�׽�ЇG��ot濐�qd��΍BZ�x ��)@Ȅ�ǹ7�Pe���7_+�s�Ja�׵��e�?N�լt +������D��uU��'� !�R���W&I2� @ݞ��~�r����Q�D�� _�7O�%�ĵI��2��#�zqMJ��[����O���]��YI�-m@+�����>�a�s����Ԧ_�tK� ��FՏ��S̜G����V � X!��RC@S2�F<�T�1 2�hp���}�t�t�S���<�q""_ݹh��"IQJ��Y��A�6��u�w����5���ɼ�%ID�3S��,��j��m��ǔ9 +�L ז�R���*1�.dMI��v �� ��x{U����|xS��*��-)��x$�կ�y� q��R�h�GӺb Ċ�qX�i�h�-���tT�#-R��2���Ep?�Z���?�M���W�&F9�5kZP;;���k,P#u�UIʔ����$p��_��x�] C �f ��ל=��~�}�|��^O�,,���5eg�G����,� b��K'�|)e���8�SpT��]H��ӈ#{�d�t��kwl��{Q�K��t��N�#�z�e?���M�����/O�ޡ�ZG�V�A铋#>#�w +#�^��w8K��\�V��T�WУ J�8�|�w�� �����\�6��]q��I �'W��3�)K����:� j ��������R�+6�"HX��wې����z���M��B dD8(��ơ�X��=FћƋC~GM��SbT<�[{J��(b\�CP���.r�Hћ"��m�F�-V��r�ö�[W�tӔ ~�Y�C�K��z���dO�~ ��Ƚd�� ��`�GZ���%�*�7T��N��E_c�A�K�� `ɗ4rS�� +�<�~sT5� + +%P��*���`��Kͳ� ���a���]B2�֜�hbʤ^�n�j��4o�_*2 �� 9zRN� M�ުx����M�������s�2;��[��Ć�1�ҩ!93X��p?A�à �ڨM#�y�cVz7��Hz���)5O�,M�.��b�#dp�� THh슙�h��C����q�^����c���9�bV��<�;�}�.R�]]�o��>��a�1��R`��$�zr�zr�<�&�qhB2)� _:P�����Ν.tal�Ä毀�x��("�η�L.8��ˢ�x�*�>wd��5UU�@�Z't��,��5ta�=�B��~�픖 +I��SK��^hsQ܇�Ss�iRn�7��m����W?e�b����|�`� NBـ�f���_�|��q2Έb��� �7_[S�Q� �MH�SJ�� ��UP�l�!oa�;V����C{��Q޽�I��9��%���ڇ i�VxL�����@Fk��T�xB[��<%~j0M�+���?H�i�C�v�*�J���tl +Q�Ҵ?B�l��e��z��3VNQ�2ѕ��᲼M�d��/��I�M8�B��yX�Y���J�.\��E�G� �� z�KV�2j��'ZWk�EM��5�$�C�,��9I@r��]���� � +� �@�§�''ʗ�Wm!K���?��!RmX��2����L�љ}UPb�<��Ss5�K�2�O;H�I=q��=�o.(�u #�G���)Ʃ6��}q����k) �p)��ѝ;g�� QJ��=o7��T��_�]��; "qM\> ��O����8�K��b��e�T� ���d�t�/>�E�� +�A�;lPqV�ۮ�) ���8���T<� �j_�C�+6f��'�����y�ܹ�F�R, + I��.� ʤ�^`b�0��:��瘆9* -����nuR#i�0B�q��Y%�э^{0�Ҳ-7sR6�6: +� +b")u�#15C?���I��s�|� 3T3�7���ry��}��ߤ����G{��?��^������/����//�����ח����������5H�����4�I5z�|��d�M�� +¬goJ ���·u�wɃGo~��rޖz���%�۝S5[��$�Œh(���=�_�s����1���F>G�~{��:���s& �K��_�� ����9j����C��x5 ��)~t��4�א�B�/�L{ +�$0�� "��&|�7�}�G�޻�Fi غC�"�:>QR����$:���)��D8��TD�@�+�U5yV���+�VA:� �{�e�/����X�X�?�m�2�`���� �l `��͠�_��i9s��"B��Ӣ��j�J%�Վ�-=��IWFӕq������]�GwU�)�z�̞~��9�w^���ş�Ŏ †�#�K B����}��D`����q�̜lX��'e�WM�X\�E/s[(��+tG�B��6*�Y񣌘����Ň��X�L����iQ�˜�7'b���e���)#.s�0��z>��q�#��l�R)`��i>�P�HB��^��΃*�_�zA�NJ�.�Z�*PA����-�5MG�]$�l���f;}�C�A�ӫ#-�� ���Q(%o +=�r� 5߽@Z���\Nq"�PRT�˯��s�T�F%�c*Jͯ�D��A��Q�U�!TZqa��M�ݰ����Ѳ8�%O�R;�H�X��p���o�29A�P���\ M/��k�(/���P]��Y��I\��ж����M��\t8�V�N�������L%�Y ���y@����,'my�#"ۢA!�����Q�9C�LjZJs/��vP U%��\9����*��Ш*>�θ��O�UU�A5���, ���|f�M� �1'���<�1�k�� #A=�x�վ���yߘ�Le�8W_�Ɔ��&q� U �'�{})�������T&?mi���ͥbD�J��|���X�M<���{�����/����?����G����d �ܐ�O�oo�HM��Zv�қy�@Y�ym��I�^���AW·t+ˤC*i�� >с�H�گ>6�I732 �o�x��lx�b ������n�e ,�����;N�����į����)ի�K��n�� ��[�� `�=>�IQC(U�;1ՌU��i.����|h��S��Q��Z +�p>��m�,~�Jߠ�#� d[4�`����LqݾZ�vO�u�|�qz�򨏽]��lp���FW �0�����淀ћ`��eu�� +? �����`_�FlAd*�i�m#��+-��� P;�@E,���y>�'�A���M�F�[Pr��v�’�2s�V���, ��q2��fF���~=V�O**e{����X<с���ƽ5�L�ٛ�H������'��t�`0�@�i����� x +�㐴jI��©�Ҟ�Pb˜&�dHxd�l�H��e�J���������d���:�ed t'�� ��7Ggj���]��0���g���R�qP).zx�1R� �ΒD)pg�n� x%,�� +qK��fꝎ�s��>1��j�E2�d�����S�؝B��wR��J����ST����?GaR�}���H�2/M��u����|;�������?�i�/p����G(K���g� �uX\�~�Y!��j:g �)~x���M���I[l��&z���5W�~7'=�f���!2����XD�5�fq�E����hrM�dP��e�6N�F~!Tom��Q݇ ��菔��$6)�pHq�"�C^���M����<g��-��[D9�<���T�����TW��ȶK?��W�&5�� QCL,d������� T!/ȲF���������b�n&gM�2��������JMʩ�0Q�B=�sI�܊̎��u. �1�(� cU�M���uRu���SU��*RE� wH~Ω� �nw?��r�)IYX mg �՞7-�"Q`�����m� �D�jد�ӱ��i�E�lΑ˥��i���N}�c�.1dk�c]�*-0�_�5�G����PaN�T8��� Q�L� Tigs�T:� �Ub� a�-��F ����F��-���)Z$�~���n��كl)�,� �˝R�x�X��R]Μ��&��Q懈��Ȁ�������#j�o�~���'�8O��JL[.1a9t9��,��aGW�͕�ie����ޢyO %��Y �i�o��7M5CU"J�Q�ϙڃ�|�3�$��^M��`�H$pݢ�Aa��P�ۊ �� �H`�fG` �%;��{�v�����֢����F���\�x2�KBM&� ( �zٝ�d�Nn�$�ݭ5��J��t*0*W�ӥ�u�X�no�Bj��)�0qS��ɀ��^�q�L�^�TN9[a�x�L=��wzP�!�э%傪��d'aaP���hN�K�q�P:"a��n=�.�AZ����@]��%V!)�opt�gQ"��]�m���o��Z�33�)(c��B>Yk����dx��^�H,�m���/4-*K_Ym։�8���8V}4� ��5N<�5fF��A'��7.�?>1H3m�y� %[�n!��&�cMt��;=��:pf�&��� �3wFr�}� ��O=�*����k���ݡ�%��ݎ���7��O��!^�N��D,$���d��R�4����&'ұ�zr�_kV�?���(� %�I�����.ȲYB9��� �gu^4 H��E��@�Bڂ�#\2 +?9I���'��G��5ׅ8�9�%�:�_� +E| p�� ��(�h\E�H��y�c����f������A��,A8v���/Q�N�.n�@��m�-�[G�N�pޯž�{opQ���o��XԦ��U��1��ʦ����ez�����}K�\n�rC�0�O�z�y����h�eH6h�ķG@b�|�+��d0uG�o�ޔ`8�@Ph��gXPYK�j�K��Ew]I" �n�e�"f���=��̻cI�YX�-d�r�YA����j�otX���\���C��nk�KO�b��'���!�p�V�XT���T�!e�N-\�VNJo@�zX��B,j�ˑ X�!���j��}���4ԟ���(@�[a���7�("Es|�D�.(��L��~��&��/h�F��T����R�x����8�� $_E�� ��~�mg^S*,fnh�,�[������wh_����+��*`��,DkK� ��� ����������ft�+�����9b�} +q�뜋Թ��ٙ� � ( +��� � �h�!u{�3����ԃ��yA��6�����}�����D88�Al�:hDAV���YԈ��\Y��G�ct��%�5�$��������÷:s���3��t�a\bǮ<��B��"�x���lN|ݱ�j�Z�]�O +�|1�OQ�@>���QQ���ī� �K�>�D�Q+�_�mw;˱ i0��h�[�[[z�N���C��gu�ϓN��0��1��AWU��M�-=� ��(�V��}Y� ��m����A�E_�]+�6�[q�{��е�����D&�3s�ieo����  +� +X=����_��jr��^6��d��(�& \#(��+`�@Nݼș�c�f{}8�>$���Mo{��ll�H���`` +�t7ZSN�Q�����L�w�7��$]` T81�n��F���$��=G�o�>�-��*k��=�,c��e�����em.�/�kqP����il� .�!�al� a0I�i�MbmUQ$שg���������)����y��AA��{޶�2�4�?��^$����;1��b#`�x��WA\J�>2��t�x�u戽Xt�ZP6H�~mmIҎ�W��Sb�OwL絅�M�@�2���J����:�:V ��M·/� n���8�&��ɽ�BH�`� ..�I�����H c@��G�&b�Sƒ�����QN��c�›F�`R���a�p��/<�~����Nu�7���] 8���+i ���I� ��q{��ܝo]�R��0�!���\�ז ʙ(0�l(Iڱ � +:����gT�F�͈ѵuyi��P� �u�r�}SB-�'o�����7������势�>��@q8D��[|�����"��A�b���ګ���>zG�� �� M3�y�9�l���U9sR +X,��dZ��I k�N�fGq_3ꤎ�֬� 4Ŵv 0I�� �.��h2s�Oq �/�A��BN��O��h�{EU|�ݗ����ަ�vظ�8j����� ��Xn?"������D� �\m"G���hN h��c�I����v���S- -'Dq�$4'���������O�U3�Z�ˤ( %�ޗ��B' �&��\%���gfT"k�?�iH1r�7��͗���E� l���H�#�Rn:P�<����P����@cFůB6CQy���Ȼ�� �rA;���\�|�F򈩡�� �'aDU�A�\��]_]!�ɮb+����H�!M7_��xZ�GU i���#|�wș�$g���1j���sK/J���(˫J��P��ܵSK0V���/>�Q�)�&&2�[�E�� +x��j��6^!t��h!p��ĵ[��g@a\����+�9n'��WܬO��}�D�B���(1�+�>j�!Kma�k~�ےo,ݞ�����R �3��I��әqe�%��$���Y��[�S��f�YF0�U���%�HΗ +L)c�3�?��-Zhq�_l�5�D��P���6�r!�9�͠3�[�H"�֞D�jN�˱�%{F!��k��1�V���W�}m��g1(i@�X����rv=�/�?�PS[~�����/��;�8`�7'P��oN���dVo)\H.��#P���}���j�4�"�����"���G�� �CW`^���b�י�����7TZ����1��FP +)r�PFWXPѐ)�h@���]�T��D�����~�j �`��O�Xm���%��g9��h����ᤑ{� �t�W�"1��_-[z�"k"�zZ��,�GC+T���A��ī�$L8��}��4�u$�MY�Y��L ?%9ʣ����C�/űf�N�����%�c��*\��y5�s����\ ��Š��c���.�E,2�Pf��N"����x�Tt�*0$��5*[���o����� oN"��lC���V�3!]x-����GeKt�[W�� +���"�9w�n�&c��i��{��p�&d �������FW��j�IO��(�g7�Gů����҃�_bnX YrI7D�@c���LH���O�q�Æ�)�bP�E�#txu;*39j�Rg�< l| ����7����"�P��v{�4W�J�g�a���A� �_d����މ-� H�z-dIc��e��enHQ��})��h4d��߉7��- Jҙ�9e��h��W��?�Oi��:�̂e Ù.��|��nq��j�A2%{�>�����%�G% +dd���������X���F\X�o�p�G1�*�^��LU���W�]ю�N�����i.�\�4���١F��� �ov�KƊ�N�12v�1ƑF c�R�dȖ�@��Җ�iD�z�����W�ot�D'������D�F&�SL��:K�~yk���[TC��&�i�*�܀f�>q��K%�����)%B��E_L}�8[��q��6-�Ȼ�=ߗ����� �O3��?k:E�3����{�}I�G�LX���&C�xm�t����A &����EõZ�-�#��9�"�� +i�&ns�'��%V�XM8>�����D�@��Fre��k�=���h��[�d b�0�SJ,��@�.�T7���8�P�`(�ʼn��4;Q�z�n�wl|���~W�lR��O���$��H ��d�B���Z�b+3 2[�7%Q:5���dX)��@i��#0�he��c�B]c9+�VHQ��ٴ�!4 ��`o�lZ�etgJ׷� +#C�}&����f����uR�K���N�ۃ/�5u�t����4��f�}��e�1RY�i���^l����1h���Ӓߴ�[/���xr3+=�BLNC�j �����X=+H�!fy�^|(�ɹ��Y)�^�r �(�&�����I�=�|68o � ᢑ>���nD����g��̃��]�o��ũ�%S����I��}��PqD:�&z8Յ�Cn�T���3�p�syʏoz>���p�X�QS~&��;�wߩ���g��h��&���n{���W��c�ΰe�f"�xȊU�d8�3�=*l�0�D �+-%�f�G/�*%�)�-�.�m��Ô�=*0��f��^4=�H���x�(�J�r�L�Xl&?y~��.0�RD�� í?��R(ǐ�R�n���T�g���}��"�D⡍��ݴ��߬�Ъ���sbw�yڪ4�y\���㼄����/5� +���C<�5E�>"��1��m��,��oI9�.�9IO�.�x�]���K����6@��,[�wh�~>���?�DJ3CAIjU�E��� �J^�E5��l�ze�F�K�ha�?� +޵���Q /;�,r��<ӻ���[��퐐�y��3uԬ�jT�j����u�@tRp�@@%-�M��ut�y� �1TҨ�@.=��b�,N2$�� ��-ΔLC�$�;��5"b��z,�[N��Q����r����z�U �sx���e���#�I*�]�;���P�Ξ]�s$�cѽ8�'L��N> T�w š����8��}���m�0>�!��Ӥ���n��/�m��+/�Hw]�d�ĔL^W9dȮ2np��8��� ���a��i�fʒ�l�u�� #��yw��Qjhk��7$��51�������^��Va�%=~R*' +�U��5,���̧�ErFa��B �3/���S4㥇`� =�2����o��nZ4 �Kx&e�tmT5]n������jy���f]���)�pZ��ߜ >JYmIb'��*�.�D��,��X���hjU��?�Q���uP�?+EP�̀!׆ʎk��C�z�� �6��r�O�2.��O8���Z���R,�ͳY&���K0�z#��b���2�G��_I(jiZ��Q��]� ���r�*>�����s ��ϰ( ���9��lҴ����b�1<�̂�̞:W*ёR�7ziW֞Х�S}#$8���m�o���}��iO�y�����u��~J�aX��=ɤ�)����k[���`�1��ۂ�M�!ӥ�I�mY +��I!1�������g���:u��j����O (ϫ����:I��!Py�ȗ:��o��.p��n{�AN0G��i;9���QA�g�"�G�(���(�4�;˄ V�E�8��Փ�E�Q���g0�Gw(4����k����">�'e�ӳ����z�4��1�WMf�b�� k�{��5�������|�TJ�W���Y��!6�r�&�@j_��[�xr��}�3�{?�?��u��bW�03���(��wf�v��13<��Qm8q�ԉ'�J`V��Y�('�פ�v����\z��,jFn� ++=���磛r�%h����iX7z�o�R�\���#!����ӓv��1 b1� l�u#�ve�@Q�R� +8-��`��:#-Q�U�H� #)��妷1��vO�Z4~JtP5̻}���8/A���s2k9�W�;:�__c��v����>�k����N +/�tǮ��n�H��ܟŕ�>���vG1hԑ9ڋf�$7f�����j�˝��Z�F�01ހ vR)i�'� 3]n�Nd)��W�|�p4��Wm gW�^��q�>���۝�dokV�&4c����"9�x;4�4�M�oE����F�,]{�DU�� �Lh~Z�>���S�{O�̝��<p�έ�Ƿ�ӏ���l�ii�,�ͷ���!�,�ْY|ް9�#��tfVɃ���̘.�A�NGyb� G�d���D��#�kQ��4i��5ЅA�j7u�5���p��`��6�h�e�u��҈e�/��B� �Q�uM�����1J]|�Qyu�ʘ�w�U�1ys� �Q���S�;��W������SC��4�� ����!yF4Jb��e t�aunwK�NLi�W���wϮ磻�����>��}c~�:��2�u�H+љ����6�n�J��5_�y�^�c�IJ"��Jet� D��}��UfZ=����F��DžӢ�m��;ץ"#=Zwfa.�ON��տ?���Q�$��7~��Zx����yi8���I�r�Cl�!�� +y�RF�p������R�R���:���Xx���z>�+�d�R�%(���?�Ju�-��H$���f� +��&����he�W����C{j>'*�Sx} �s ��|���񀕙 t*Ԃh���7��JY�Sm����#Ȥ�����1C��б��YE�ۥ� ��5PN����������N��0���O��0�@�fζ��O�hw�~~�F���%Y$A�eH�OW��������W�I�ҍ��nq�d���LxK&�;�l|>�1���.�c��~Z�{V���u��a�� +�=r��K_V�_h9l�d���t uoJf�̀ƛS*k��&��rD.R�X��Sd�T��Sv����ޮ�܈�� c��i�'�"w��$� f ���5;|gԶ����m�@�Le���x�G|i��� �QQ�����я�z>�k/��ӈ���N\�z�n[۬΃HK��?ril�,�\�)���Zr.J�JE�gBT��������{��S"�I����k�6�ꛛ.T���Ri�_�@��V��= H��Q��F"L 5cJԏF*tc�#��3{(�ifs�6� �2�~4�s϶��۲vv�<��l�?ûW^~͵�wwu��K�5:ci���� �q,�B$������2��۩.d�a�U g 5�ƌ�@�ŝݦ� 7�c�ʉ��}[iY��_�[��P#��+�f@����l��v,� ���ye1�V�h~�`�%מ�������.0�G6vMCAJ�����/L�S B1���_qg��X�)�?��q|���O�W����0g��� N4*�Ti� Q6XO���W�B�`�p:skLqH��~�~ 7�Ci�C]m6Q�\^�{>�Qv�c�P�ZMU��ýB uP��7��\Z����Hs�r-V���@�Q| �,��г��m����.�QKƅwiI��uK�O���1�����Jq�<1��5I�U�km8�*���.�.�b�Y��� �mP�/N�^�Ӥi������$���b�Я��M��b��-�d���[�lZ+�ϰ8 � �a,*0�Rq|q����F�`FW�F� +a�%����,�rqj�����_�R!���~��}���?��Ή- ��>�a`h,���Ώ�� R�g�y������֒���$�!��ExN�B�D�N�qh_�Nٔ�V(�,��L�hv����� ��'��HӦ��4�O�C��'("�J��YT~V�ؼ���a��7�[T!+2G<]�5Fq���9����2;ŞJhﳧ � ��h�JD(�����y���0�� +e����ڽQ��Y ��ӏ�0� �y_��\�o���`��� ?A��E��:�� UM��6����v��6X�7��'U{��q�/0������X��G�x����7;՝C��r)d%�4ᓻ�N��>����.�J�@��@xX��R6'�B +�� cH�F�T ៖�P��N�_� +���Q9�I�j̐,��2�}f:O��V� [N�2 �X �gXsL�4�s&[�� P����̗a�3ڀ��@\�aw��Q�A���(�,�D�I���(������i��Q��N��jT���~��ɡ���z ���۞oے�/a�G������f�6:��Jȃ�����X�jy��ZM���iCf%hEu��la������]q�\L�ؒ��L� ��V��ud��Hv�2ĺ!�����je��2Ѥ�#9mTJ"�o� H�n��ߑ _&6W�^v�ls][�OH�I��p9���y>�g��gYNu{Z�C� �D��"�ˁ5YeJ5;Al�X�ʫq��I�&���w�7 � ��������Lp�����9�u��@�`�ƴ#F�0K��ofCNJ��|L^>�rq�}2"c;����w�{>�/?�[*"�i=<�]j=�ȉfA�]iuF��BȇUΪ ti��5�I�!r9JMT -w6��fA�=���>2:��E�)c�AU� 8;�!��O2��l��0z-S���[{*�A�I�Hp���Ԑ0-���*�B+Xq��\���.�g�Y_$�G.���P¼����@�.��2o���u��:s�BҬ�~�_��\���W���5Ѱ6! �Ppa����>��I����IΒ92<�`�LAs��͚�f^��*y_��(���}����+������j���?3�sd[���$p�_[H�N̠c���D���6Hh��ɪ|�'��6}�+����Z��()��n)�� ���9�qPzT��+#���"��7%[B�~�,*OJ!q��7��Ƨ��[��T��O��Qv�4KXq�;tb� +�%�@ ��˥�4 ���_]E:��{? �oo逞`Q� 7W�/cp���(��m����2�����\euOc{����������:�F"�xQ"k��QtT +JZ�Ȑ�f�e�'2��|Y��EVu����|S(��@�{����C��.t"@��Q�SJYb7��%S�ۭ=���C�R#s�@醒�y��x�o�+9 ݱʺ��ؽ��^����-�>stream +Q��1����q�]c)M��8(�������w��(d��zG˪���L*F'Z~�3˔FO�?i�� 7P����F��&|�k�v/[f�k��/'M���U���h�o��5�1k�Q� ������,���-6J�m*g�w��Q��]!��r@����,v ,7�����~- �L���d�����m�X �|���\�S�����<@M#��2�0*�%��f�^��9?Oł����*�t�+��#U��11 Y��g��1�m�2��� q����ZT�jB��\T�2϶2�E�m��X'ʗ ��NAj���+q�]�0N x�ǪZ]��D��l�8��s�Aӫ�v�M�y'E1�� Q].���4G�\G�c��I��i�����#Blf�i�-\ w�S��}>~�5'#� ���8h�������� �G����]��h���������M9ԗ��vn��*�r�=.����L$�|��G���B�/�[���:܂Q��p��� �+��_�� �Ud�����+Zg�{v$4"�O�R�)�z7�]_�Qr�G��leD>}�cB���bԃs�Y��Btɵ+k ������_���|x_�Ft��O�wL���u�o�O�ʠ,�T�Z�P(gv� +߿� �qiגUJ���2IH�5�>��<��J ��RD��n�I�����6�j��c_|[G�ڌ��"�m�gȸ�F�� ���8��7�����3�v-��ZaLOCwʉe��� +����C�,e���nT,S��ޭ�]χwe�ZS<�����i��aƥ����2�����'�������w����W�IM��M��R��a<]zv +���(\�a�%f\�7�+����_�b�L>i��ɕD8��|������V�ޠ�_�B6Q��b, +�b�����h��+6uM�-� ��--0��*mR�֖�?����Zڃ��Of��a�.��I�T�"B���g� s�@4�=�ڱ|P���]�,Jb�E�/������Gl$u�+Hc%ݓ(ǀ�)^�_AM�_�~�f%��ÕW��Y���=^_VrϾ�����zl`�+秝<�N.*�i�e X1����׈!I����s�J3���k� ��h^� �qT?,�J��& Z�;����J���ЩX��>� �@*��찤'1|� ++��F�>�Mڭ=�<,���_-�f6ܤ���m��6H.�D 9�qe�4]%N1��χ/��-����7B�|H���(|����ڻ��8��*w[��C��I�S��E"��Q��ё���􈗎��{2�&�zG_z��ŧ8�lP5Du�d �I�� A��6�|ȶ� ͑a�T��2��-u�f��% ��m����X��SgP]�(�p +>*�J݁�� +uM���n +���C����9��� [@�>,YȺ�-���1pQ��95 B���4�b/'�U���7���׻a<�^TB��R3���^�c��.� ��:�V1����}�� +\�\����Օ���U��w>z�,�Q�i8����iwL�v��a���H"��vԤ���� *����S��Q:%y�h���M��b�r�?bt�5� ��^p���5����1����g�cޤa9E* �Ϥ&�~-F�v� ��$��F�,3�}Ɖ��fo��V�JQc��ܯ.��so���h��<�w �SX��;�D x;��xf֫��� �j��O�vH�9���3����:K|2,���1R���N+s��1>˓4TlN��U�uG����RC�XY�8Z���,�n#�c����Z�> ����r����lى����o��k�Ae�R���WV"*�B +���׫ۃ�3ݚ��ix�4�*] +�ݔ�l>�M2f�4aW���i���N��0;��ŗ��@���-�^�����5A �=�Eu�P�J��P_�j. ����Y::`�q�N��EY@6ܣ�*�V�|Ε�'���D�! QOq3��%QXO�Kd���˦}N/�'u����DaS�;: ��E��P�'gl�Ya�#��;�����r���{g��%�5]�g�4 ���2���ΰw�T����#��<�/�81�nS��A��у _�'��Pc�|��MB�&y��_��~i�h�C[.VeN��j,�.��wL�/��$�K�w���f �n�h9.� ��T�/��_a�-���=�6��dB ����/��R�SfA.I��/#K)w�xl�eij�V6Af��T�0��ԩ�G���N��H1�4Q�Y�W���x�����^�O���MG�@�=� =���@>����1���A�1]��"��zh���w�A�]�־gؓi��L����wW�]��?�F���矇X��:��������̴jS����fg��9�zG�8S�����v��& +�>Q��dH >V_�S��_�3��ļ�\ L�(���=Y��u�6�/R~�^�"�lt�D*�д� MJ��jrz�n��@���.���4�vlW�� �&J\������(�#x�D XzZ�;Ƞw��Ws:{d*�jn-��ŋ��F?&Ln%�]�����n��8pH�rznon7ߦCp���E''b6�.�W�.��� �u�X�G����-'|ea: +��ޜ=E��'�N����d�\"i �I+���gQ�.����D���������� �,�,1�K�$E�p�1j���~ ��8�5,�<ʐ��8�Ō���T��Gi��iؤ��.� +�yE�f9�fP���mh��ߵL����q� õ�u.מ�21u +bus����(�̕�#� +K��"<�'!w/�Q{:;�rَ�Ck��\?��ғ��@����x`Z��ի�Mϐ�E[�c�����F�5,7"��~��]����j9� + $=~�p � ���d�/�;Z� ��F �%߼�ǵAT@��0�M�t�%2���O��C����vxͽ�F���~�;S�r�nQS��:����9%��E���˟�-�: ��P\�/ƥW��QH)����;7>ߘ�'ie4>=+��ّѨ�3�m�� �pQ�g���`kp�^ٵM�o�k)���KB� bV�Wiݘ���V�(`�Ɛ���T��Zز�� d⌇s������7��D��"^ &"��UE������eCKE���jI3�R�XΠZ��)�]�a}�v�rѪ X$��n).�:~�iSL�g#e�=�.��ۻ��;�;�J��e"���3�Z���բW���Z,e)��g���u���H)��e68�2 �VM�gJV]��‡�}��2D���l��=M��I�}� �_ꓕk�8�K��zg�m��� 7UhX(�0�D�8�9q��D�?J1��+���f����lOs�w�{>���2&�0�O��D7[�C�i%����؜w��p����K�9��Y%�*�h8��Ij8T�T��� $�!F�F�������2B��N�Ӻ��zi���ګ����6�D�Q�nhI��Z���xJ��'G�k�L' }��hqC���I~F������6���o*�|pLH����2�����y`{>z�m.�I�k�<���#�jS��7�i�i�!�=%���]� v5��5.� Qb�-C��Vt��J��&��x�!Xu�L}[ �u�]ԊM��k�����dņ2E�"YZڃ;���3���۫gL�u��%������xFD�HС�Q�/�x������h��̣������� +�<�������.���D�<���x����et�S��g�����aM�m^F=G���aU؜V}����D~ϖ z�݅}�c,v}��'��E ���G�� mkd� ���a�$��o��V��K� �bK#3Xo��:v'�'���ݪn��r�Y�b�/;t����*��Y"�\�/0K$�}�M%L�r61��7"�ײ ��`�;{���ɜE/8zw�1�/P�?k�@���`�A �7�i��薵5�AW���P�N��O���"84$��bF�oCFb�C{(��1�ı����%V:�cae�wm|>�q�Y��z�=��S�!��� �'3���D���\H#��T��?7��=`�(�Ф��m��)���$�C�Շ��3i�atj�a�b͗�A'�l�R��]�p�q���Kч�-�U?��N)��Ot�{I ���4S~!0f�vk�)ڦ����7SN1�`bE�@��l+��1>���˅̌��R��|�r;hHZhzD���P?�1rL +��h����E�+# ��&�Կ%S<_�.['�,�1���,��J2P����)����h���}bo�����=�!���K�|���r�$_,zejȉNMk>���b��!"���IM���/6��` _�s8�<���||�N� 0(.Ve���}�s4�7����@��i� �%��� Ӗ� M�66����P5�Yj�LʝW��ٲ��J3�o[*��p̶]�i�W������{D�Cx 4�'q�9^0��&Au���7����^ �C6�ҕ��G�ف&lp�h�9(�v�g����#�JA^�v���±�$8X�n��_/r0�������U�1`��+��W�F�em'�l�#rLlo�N�"b��@_^���Y�����3�� �'�������ܗ`������-I�fK �Ka`'��,��U W�������=�W����p���'WHaU�{�r粢)�eF��ّ�0����+�&��<@q�aQ���a)--K� �p+A�_�x`��7{�L-��/�D�e� vtDx�T��]���nֶ�'j����/0��~��1�'SY����]�����Ȯ�O���hт�^��I�g�[�^��o��W˓Ҵ�P��4��sb��;��ܕ@�n�|��d�A�БU攒�����y�a1�2�g���4�I��8�~�g�'��٢9Gnal%���(�F)�ɒ6*(�I� p 1Y����d��W�����/��}�ּr7��![[b���|xWf%Q`��hzZ��6�iʀ���f]��O6�=_��A�Ȏ�ͺzQ6���%(�^7��YW���?S�x�.�������wx(}gƳ�[]�,��5Θ����X��wɶ +���� �5�-��������)eu��Ԃt8E����"dCj��Y���-����Q=�m�m�`8L������SψdH��:�3Õ)�c1mj���={WA(Pp��ϵ���}~a�R��D ��[�y��N@�u0�/�2Kئ���h���2���,��Y=��j�b�����R��m���� ����i�֫W\�,.G���=�b����a����\?�?ꌄ��B ��?��*4~J-��t�f�\��oA� Č��N-i|�#E�����V�eM��|�i��qh�6���+�|�Ƞ��_pJL꒕�:Q��b��e]<�� kdfK�b�pm1ŽI��ļ��]��o\q��8�CO��>1���������9b�y�R܂� g^�$X$, X]�V ;�L$bu���Ie:&1G�Ĺ�|��}�}(�6ơh����]$��R(��{+:�ɮ;�.R�'�L|��qgmD�l��a���,��4��d��0�A�֞S����:��_Yf�C�O~�\p�� +']���_�P� + ���C.1JfV��&E���QqH���kA��V�BQdoWӰ[�E�=�o�ޭG�-��|/)��� �%,X��cZPբtRe��R�J%Q��� @�}�}�o�e�-ܶۉ��ƪ��`_����s�ۘc���t�l�Κy*�0��"�̫}$4ٿ��@�+Z?�����C���/����" z�Bx�ELHz-jw��R��S��c��b\�?6f�#7���6>���ە��^7�7l Ƽ�'��~#'��m�t�0{��D����\k�uB�A�A�����7/mZ ��:���8����?-��!����L���;8��c +�b�ݜ���}���ѳ�2ܭ*Ze�� +i�KJ:�E��z17 �K�2���Zt�Ծo_�Ν���f��<[�@�t������~g�"�$����۩��-Ը%m�1�,�oO�|��Ξ/`P�}Nu��py�1Mz:�ՙ��G�3q�t1�G������^ӱظ�!�!��2`sc�%_�/백.��t�!��Ҋ�r�*!�Us,t����qa�#E�9d���c9e�����{[�:jOi"(v���������†�)~�QC�:CnL~6 �����@���%|J^L0jx��Q \�(��/��@m�x�,��\S��ߙ򰽳�PN���k��.�3I#,0�"h�/dH� ʯ�{+C\c쳯6����FС�oEzD3y�����%9�]���Sl�8TC���&�y4w�� u�^q�R|K߈��g �H���/�� ��^z�h����_a.�W� �� + tX~����ITS,wO�mfn +k�L�7-�248w�$M�����I4���l����F�Ȃ���0�:+?͠�v#��)X���Y4}��3+j(�f�?%�u�iL2n>/Z���m��`�y����ԝ��i@AI��s}�5�4u[��n��wJ��"&>�_8�"�9��k�I�n�WL����%��T��щR�U��f^�<�6`#%�7���`��@�i\����IrE�,-Z�4:֖Xij �q���!���@�\,�6wZ٩r8k�Bf�I�Adp�M�;X��AR�Ň"}ޡ@�q�s5/,�_l��={6�o|gx���5�xqaE|b��u1��c�� =�����価���s5��?�Zn�?7.-]H G�ùF�[|Z�Jr8�:T ����k�%�ǿ�(bl�^�*����؝���& +����z{?H��^�Y��� �$K�Y�nP<�a�_Y���g(z�5Q/�=PG^4t�eexS�3���@�=B�c_�6�NU\V��D��2��AaX���߮�7���s��=|K�,��\�Sg�0Qc��������oIS2T0Ս��`BBLI@9.�Z�l��"frvEd�Q�.�逴�p1hgf�Shp15,���O{N������yi{Ei��������d�Jb�Y� |�oi�@�6x�Я?�1��(�>&� B�Ԣhg���t�H�}'�S*\�*0�M�̶�� �y�ó���z�t]��@O����\�k��g�o�{S_�R��*���k6NU��b38��<jd5�5�x�Ld�}�����iT��xq�yh+0�,����i!7!���⛓�І�a�U���+���QӐ����Af�B�*�Ƕ�r u�5t$�)}̥�)y���f�<�x']��2oݧ���~�e��i�a�UT!˧.��K�V�4��!�^�"��jӧ��|���E�Ę+p"�k\}���).�dQ�O��Eϯi×�a�����!�kdI��7\\d� ��:a�����U�ϔz*����jI_���o⎨�Iv D�-Z��TQ�j.R���r�$(�غ@��#�_�UF�*�R�9r�R�,��ǥ�RECF�a}8�Lp�nn� +h�|�&�D��A���:�Y���������q��O�K�ji���yF�O!@�I�b"�Ro���sEį��oK�n�E����&�T��z�*�d�١]fEZ�H�f���D޻��n������t��#?��G�4�[��-!-���/�\ğAl��"@��{�zF����77+�Z��_��м4SP�*���w[��c��E^v���#�2e�,=�m�բ;�����^��q���$:b�Tf�gM�p{�F1K3���B�a��K������6�� Z$WY��������"�fӖ2�n��К�ֆ�ٔR�7����&9,F��{������ٙ���e!P +��I�u_������/�'u z|�?�� +�C`�C�hԒ�(�&�U�1C��"Y?���Z�#l�~qPjn�t����/,��2A;,j��D�4N �R��v}K��1����*�̅�(�D����>y��@����pA +���{�d=M� u?��&�_|���C��i31�D���(�қ���]�׀���D0S2��'�_�#H�X�D�#�0z +N����5�!s�muLE�cݼ�т������5}�������*c���a}��?Q Ol��2��"��+,iL�i�IK�i ��_o�+�+��'�-gR\��0���yuK�&1����'��竲�1�F4S���{ϝ +K�w�,Au��/6|.�~��Gb�]�P �Jc��9}B)� +}r���5OYhG� m�2� ��G��+x���"jJ�۹���=Q�mc]�����+P��h~�A�ę�uVV�%J��{y)��H��(�9�Gu�r{���-l׺ Ϊ�B���$�}�Y� RV{�U���jeC�ƶ�\8$?t]5�}�K`/���0/����%�`j��C�b�Nװ�#0�SS�_K�(�;�����ϐNׄ�t��p�0𛈟6)O�,������L�״1fE�ݫ]� +�i=b����s{�!�t%ˉ�uF& ���Zl,��t����@�n�2d���=���&���z�L��nV/ d�C8�Q�_��D}�OB"w��6�I�IIr���YiW�bG�����+�M�AE��$8M�4�] ,Q���Y.R��d�uK�����#`��Iv���P8&Q"�!@�$&�Eg�Q]���/ų��f\`��~�#)�b��-;�� ����O���jf7h+1�W�$$�1��ɑ�d\ �t8�k�J�B��]J{�B{��(Pv$�F �������TF�9���W��cm�%ɧ۷ �Ӈ�Q���!��Y�5�CYL��U�� ���7ɯ�����H�� +_����B���E�?:*p�rp5���*��bT�'�� �_�^V��=n%g���a�����*�m1�����q� �.��T-�{�q���,$ �p���/��!��0,M@���� ��j����c�xK�ۥX�|g���蝫�ü�]�Rر�N�{�O@$}��ؑ ���.$Ǟ\�&���]u��#�:, �]��#��, �;��[��ewfp�ɑ���d��Я� Հ}�;R�0�lb���Onf||�:�v|G��%�+�͆�eNAէ,����[{ɒ[p��� 8��e���c�Ւ50_g�E����#������W���H=q^U_���}ط�,<��|���,�yW�*+�"G�P����M�6��4tcA�D�{��i��l*�i���y��ѣ��=�m�%���&^/0%���#/@Sy7q�Blj +z!��I )wǬ���y�U�=��x�U�L�]�ɣR��:t'[�G[5��#O�������P-���h�6�O�'� ��Y�\!2���M�Lq�aŢ��<�9 ���ǿ3�� ;�*5��d/�J״)�S�f�VԤ��E�@��%��~(�uo��oX^œ�$��m3�q�B/*"�G�.���<=��=�2���|�\G�DP�hj�2v�XNV����\�R���*u�E�ɵ?_��E��I�ThA�J���b��l0�J�`��9���s!Ȏ�Q�~�|��� |ҽ)0u3r7RE��w�H�V� ��Yt��%u��v�9s��i��; =� L��9nR�W���`'y�3" �yS���4eBvcR��v(2�Ćy�E�l�m���gۯ�#'�=S� +fLq���ڭ�D�-� +�ܠ�D�����>�GJ�&� �8K!�@ 4���u�k��`�WO�Dt�4��`��SRO�Ћ���u[4����v��ꝍ���8ԂH�^����/��K����lWk�A��fxB"�*�@���r�F��t���Z/�E("a0{+.�� w������ȕ�nH�g��%�9ㄅ񴌪K��� �/,A� ̃1�z��oIp�z*��Ht���b�����Pa[u�&:� �uK�n�V�n3hv�Ut���j�qa�E�.3�Hxg�BJܥ����)T�5T��bGރ��'�ӯ����۳b���g�Q�F^�6�2&4�a���v� �夶KJ\4��a����� &O�j���7�{ܽ/$0�q�ŧ�r��oˋ���S D��&:WEr�1��T��O��vY�d]�^*b����e1±�!�L TD�, �OK�w�GɘG���~��V��u�? ����i�>0��}����u�� ���CΤ����v�M։(�Hс/�y���ԃ۳���� 4ɼ�'T@�O����ݻ����$���T�Py�HW�񙖩��txG-�r��z>9_aGԁ�(���6�ZuR�Eh��̴CƢ�I���|ENϧ1�:�;�D���}�H >�� � xS2 xS�Z�'��xJe{��B�k�8ץ\�t�9Gr=Qi�/S�e���}���T�������⾭s�����!ٽ���L� x�?�f���PG���29Z��h`K0�lAV���$�C0&��'�[�\!���+��L�p��K���wp�������"�b�D=�.T~ k��ϒ�o�$���uj�{�Ye��1�K�E�P�Op��W��H�B��p�[v0(�J������>fZ!�G�o� ׼� �؛=ɚ��q�A�҂z�^�L|������j߀�R��\+ō�A �6��tz�G���־��̊�� Wct�h����.,�2�� 9{I�� +4DDF�|-�Η� +"��G-�xö���*��\��������=�5LK�UtY,���,%#��0|�K��x���H*�3{S��em �G��lC}��� L�'�O � {���w�c�N���"$���z�G��C;zĸF��W�h�& +#2/,�3�\U%�A`^ʙ�Z i>�� }m�#5�c���#/�#$� @����w�pQ��b�,*����[:F:h��`B%Žάm[ �2��L��k%��� :͕���\�.@p�s�,n76���}�?�錂ܭ��,�QH%/H ~{g��/&�]�^�e���@� "�t+7�"���٠9�oB�7��Zs���� +�wC/B~�m���%�I��R�] �m�"��)h=ho?���5��j��V�ь$sZ3�t%S>�lqZ2�.O��X�� L79�;<��cr@Ydr����9����w���f���O��W�{Ef�2��-&S�2es�m璛�)�I�/�=���Z���~r�"<�c���o��cHP���v�s�G�I=���xQ�,��y�������:T�!.-��Y@� +zf� �q�&!5ג���L�c2N5��������+lcĸ��E���,;�5UY�p(���N�1��T�)>~�j@�* ��ϞOw�B�ً���榺�˅��mC�-���#���m�����!��S����-ݣ������Nw� �1���橙 +h9 S%�!�t�����%@�V�H�_!��8�y��� +�-�[�_����ʠ�\`6h{g��;f!n��"\��6.�3ua�ibsa[���C�gj�F|���m:�ez��&k�'��x1�Xs?������J!&���)�a��D4��w��J1��?OY���v�|��N���D"���l(;Ǝ��k� KI"�#l�UdJx�j��&��E���4X/�<�K���ZD��K%�������")�FO�Ġ�W�j��I[����[��{�2�9�W +��|1��-y /yö���zBΠmp���Ž���uc����D��>P25�rs�H�MtƞO��)���D;zTj�\��br�%�4 <�<���ܚ�S:�j��޾�\=�Q2��o���yT}��WU��5�5~E�i��Z>_{P�EI[F~��XQ�Af�?�ԃȯ�d�'C��&h�-�q���?����� �V��.���11�E�9IM/ +���FT:�ր��'@U�ij:&&���Rsr������DU���艩0�&����G|Z��)� +�M�����#Efn�0��!X�uU�o�T F6�����}�'��O�>W��m�{�l��7������ƍ��7V6�(P��>���@[�;�B��u��[���*�q���NvR �gRSb�:Z�f7ǩ_s�����D`q�*B�O���p�\`v���w��H,�s�s�X�����L]�Q�JH�{�'�м��J$������ul��{D�,ju�?�m,�;������b�S}l� �c�)�b�;�7u�9;�.y�-��B ��c�.,�)��(�"5�]\��Ȧ1�ş5d� �,$�&���%i@�q�ׅZ�Ce"��:��{{��}��]zs�� +�>��@���PT;Cr�G�e�f�i�qa1�q:q��k��Ro���_��:2�@�/p7��t��.� +^��ԉυ���'�7��0���2��H\��D�&y��t�R��zq.4�Q@�xx��W���������ы�7Yl���ϑ��E_�?�����E1mo�;$��PDǒٽ����|�`:�}��Ѡ�ᮑ�P����O�'��5jʭ�(%�<%��l|ܿq�>�,D��m�m}c:Mo�$��`�Oo��,��B��mg@��� *#^�a(�ߜ�]Nr�x���e���G����[�(��N�"\�H]mo�;�Gf��3\ �"�h9���. ��g�#g�cw���'%/s.*H�za1��Q�7(�(�v! +;��rGK�Zڵ�6�HǠ/ռ��|a҇#m���Inq�'�$�Yaj�Bϛ�H�Z %��m�G����F�4��A_�A����.`��b��q�F�z�X�qq:} ؤS)&��˰��=���c>l��� j[d`3��$|>m�N�t�?g��#���<I�鳥8��A~�]��%�}æǽ�&�?Ph�9ֻ,ӛ:G�S����J�N]fs�E2�XaZv��O^��������y��&� �E�z_X99G��3��^H�嬏�r�љa���w�584gh6�^A%��-~��<��N YO�#�O�TV>��۬��c�Щ�aE�d�"�h"�+��=�u$� ��6F�ī�s*�TX�sÜ��:'�ջ��]���]�S�+���A�āDl �4Z������,9Î�MX�r���Y��ӡ�_ك���q@�ٻ��T�a��(v�F����#��ӭ���AݐtP��C�ȀKF�qUUy��� �����E�Ab�l�B��[�=�ݖ�VI�.t���3�uڸ*f��B�~t��Gr!T١��HO�:�f_��*q��V�rv�{�*�hN*�B�� �b�,��pU�8 +��{�y���1��H>��Κq�~�0��,���v��p�G +��{���Z��0 �+���chxD 8αkc��� W�pZ6P���)��&����;�`�p����uH� ��|c�k�)d�0{ K:���KpUmJ �)z��Y �`�c�8S�CΖ�O*�?�����\���?��Y�o�N�,��Q�EШD�z"j��i�N�,��؆�SI�y&&�G���]_�s�aƉr��n�z���}�e�_� �ަxk߇pB큾3���Lr�<����z�yc4��ۡ��$�P���╔>�OS�DuJ����WT +��S�CV�.tq�J���9�$M�H$nȵ x ����g܀�W���}Z�5�髋]�HY�e� xw�+vUt'��H����uHdH�i0���7 '�&@pW1x[�& -v �$_-Pxu�C�y�ҫ��O��9j?`E���eU_��L�,ٙʂ��͞�ũ�Z��T��� M���4��Wx���ͭ}�XQp;ใ�C��%ކl@w��ܒ�X�4�g)�$�6Gri���$r�a�k���P7 u*6;6^��a3��2 :�pVIs��v&���>kc�����co���6���H'�:� e:��t$V�HK�$��(ľ��rk��_��?:EjL� i�w�L5*����;�Tp�Wu�7���@I�.��" X��3�K�W"�S�7���4"Q�i>��g�����Z�1}�4�i�������w�:Ak���[3��5����cbt=:0�g"����B\��=.�H�)�~�%�Fh)���Iw�{��ɍ���y�$���F��#��j�q�@�@��חX��&���4ƛ?Ә&M�t�|a-��೷PayLH3� ,�{�lsϾ�X�V� ��%�~ä:��c#��oX�?�JxҸk���EZ��T�5C�R �V0��N���9�bA�O��� R ,�D�� *� �g�y��"�""6�G�Öf" Q�`�fy~ko���Ip�f��H����c��4}�Q�%C;�b�;DQV��k*�{��odi��xt�x�o���{ے 3�� �t�;�o�Ah�� �诿{�}:�h���)���ƴ����b���r�� *�g����'���'7���L������p�t]TجqL�!�Qs��eq4���̧n#�X�*��0��6k��Ƣk��sD����>���0/����r�" )S��خ�D�2u0��Ij���M�3�����X��=VbS� �o��$�,ۧ�h�U�Ulkdn\� +������������j^M��Iao7|{�L�/�ާU1%vq$�]�4�w���Gi�Y28��PB��^Ĉ��ۃ*����q�gߴ�q�����u1���4����J:���I�-I6;�Z�0��t�;�-��151��;:�� ��{cMaYE�&M>l�|{��݁��U��T$��n��w�ؗ��Qw�#����*���Gѧ?_�%M�"���1�/5�. ��kcwh��IX�]��.-� �ǀg��o�� +��t�s~z��7ri�G3� +�B�p$��Y��sᅨmj�Ap�P(��$����"Ɏ��P� ����`�f˷�iP������!��Z�RsAf�h^�эf�C8��h�Vun �S�E�.Ƨe瑄Mo�Vi󆍏�767�.9���;4�}�iP����� �F��_\║0�)�����,]I� ������-A'��Q�2LJ� �{��ۻ4��>�$��j}8�t�U�m�8�Ra�f�ć��D;Y��ؕ +�M�[��g ���v��|VoP"%�������fk�B<���=Z�#�sB�7oT�>r9w�����x째2���j�� g��.ƣqם����8u�_��q��5��� +Ԅ����ui��X~~����T���9 z);Q�諏��T|�sҤ�֜-�}D7���y�jV}���H�r�L��rh>�-lk�Mu�6�h2(����(���\j����!Q�̴�9@s^��<��س�gj��R��Υ�(o0���)S�w�v\��X�������B��t �ZݱiҒ����C-�ٚ�ޚ]�����X#D4��� Kå>�]�tn���n���-����X��P������%E��Ϳ �s�\��!�ȼ�������6�3�v=�ߵ���:�d����^ 2�<�֕2��e`y1RQU��U�[�\C�;� c��� L��"�Z�ꆃ�n��m�|{�fF����pqN�X�չK�oy\��̓hn��^Qރ�L[�|-.-,6�Ƭj<�:�ëY.�����5[�^+S��ۅ�C�$��5ƾB�T�6�{����7G;$�����I�ҳ1?�dtIr�U�v�un�ԔyU�maV��H��v�@Ȧ;9�v����b���sr�:��v{��V߽�,ܣ1�Ә/1�J*��x��j���r�h7�{ܿo�`vhhvoM��K�"�# �9 6T�D€�I��%�����B��M1�6� 9q�%MJ�.���,���=�YM�}3��(#d)7Kܯ6}�0QW��Z�am�B���N��l�A71kb��G<�힉n��}ݝ�<��l����� ��H��q�W:2 eŁ�*~o��Z�>݃E$�ܙ�R��.4�69?pAҶrg��P$��G� w�8�EA�@�;��=s��wqgz x���9]TUn�����􋶯��Dȷ��[��; *�0FjR�'w��}���ma1!*I�^�xS���$>����n'��q�����P=Q�45�*[����4E<�����|q��4�n���{x�����ؔ��!���˖�Ų:@tV���Y�]ڄ}�C�hfr���$T��t�I}�i%J[!(G���cc�i�pb Gf6����j� +��9E�u�J$Q���{��[��������[{�V�G�|l�;�1 ��|�P�����T2imIK���O{U��2�����(R�W�>��F�ͪ-so�9�� Gx��� +��c��t���4���&F2�%�=�A\ �{k������������'����j�A���Fk?DM�#c7?�y���g(�4��Җ��Y��<�=X�9��B��پ셵E<�̻گV����� +A`x�;��h�4�4�gh�²��H��s�J���P)��������"KHw�פ+/�h�v!��!��C�ʛ�+�}�xV X�uO"���QC\fiO7��4Z��%�e2���$�r�:�����i@΀�w{��YV*�es#��˔w:a�a���l�1}~{_���Dx-�Y��� +���X���f��99�n�ԇ������g�}�[E�=���;�dD��^�dY��Ղ-� �����`�0�7`�Zt;���������(3�q�������3��2"��?������p�$ K��+��(�y9�[����;|մ"�v�֐��K�I>y ��'�rQ�I��Q_�v���dg>?G��X��*!�_Q^�*�j�����h�iu:⦂%jg,�����j*�ۼn�D�[e!��F#��,`�n�k�EC�&Ȳ��5��@���K��0�@��I���I��08 +�l��iםZiX޻Bf �SB�CLP��Ӹ��L�� +������߬�ى(�•��u ����]�H{��R"���m{�e-��=9�ujU;��i��n�/X�_�׷_f��d1�K�k���b��`A3�s�u}K��M;��(�*�תxR�Ȑ�ڃl�Ï|@��M�9 ���VQ4b����}j�m�b� � +V���0�1�_<�r��F3D����>���"wa����ߎ+{�4�#��~��~�J2�~��\ V�}g���e��9��2�������b ����<�������G��c@p�?L������-�w�jGXZ�6�5^6�koի#p�|�*�h��p�ZyPiZ�ܚ��z��qޭ�I~^�]��&#tS��� �N���y�̅�m+3/.cV�#��@;L7�۷�u�O��,0�������3/�ZO�+�&ƭ����Q�0"B�V!��׼#�i�9D���H�m��, $P�f�!NK�m��PH��oj��kq�m��W >�(Z`���.��m�qk�y*���ܖ�� ���YԂ"��\���U�4؇�,���m�%g��ۼ�Y8�X*��"�S`̑w4g:��ȉc��E9�+���tk77� �`�������O�N��礆f�L4�vP@.z#1\&jI��C� +���]Ԇ�C���h�z�Z����:�� ��-��c(�=5���#����aj�>��X��݃��$� ��,�H '��F׸�b$�wǹ��W��39���^(}���jp�K;x' ��������a*U�7��#MW"&6`��������ü�Р��{˄�pk&2 �(‰��� ^S��'�1�U�n;[�O�g�M^� ���<��Ss���J��C�q��KzT�I����]B��%�DM��=���`�+�=�75��ģ�Ixj� �J�K�;�z�p5�e�]M3,�P�0}�j'��P�bZ�:E¸x�)l��A�9Ar�[�{���~h�1�ڀ:�|�Y�\��Z����N_2��sG��`w(lY`�ײ��f��]���>�=hֳ�*4�f��:33�m��-&�L̚Rܮ=�ŭ�����v�i���E�_;�G�4x��/���/�+��8�rK������2�_�@�>!Ic�gٌT���T-d��5Pb��;�B�˧'�&}Rit57�]�V|u��.�Ȟ�-����QZf�l�8]�Z�<[Q�UQz!N@RlWJ"�gٙ%�i#;�C�V}�'�W6X�;�����WJ��q@M/�_q�)0�E���Q���s�zԠ�-yW� :g�������w�e~"4�>Y>2 +�����e���3I^�t��P;(ʴ����U�,V���I a(<]Q�F��h���V�{�,� +E{Q/|�Jo�wS��w���J"F���&5�l�d6�;"I ���B�34�e���H��b ��`/t��*,��7>��xh���hD��z�~��z�3��#�ˆ�g�0��ӕ���)3$f?!�``�3������`ڠ���(+��(��QD���;����=0��_��f��盡�����D�9��Y�&��Ι�[��Ś1 +����,=4; ��3�,�aoK�T�(q +�=�� R� +�!R.-��{��GNw +B�����%\Ow��_����/S7�j���<���uK�HD��B��P��|ʔ�J.� �&}!�[h�]譟�2jM۰�ɇ��/Y^�:.sT�� ��-�ͤ�q+U��@�� ���Ÿ�|�@�!a �ku6Eo(AbU�R�i�.F�+vz)�5>��hvJE�7ڞ��k̆�P{1.,��t���?����~�� +��f��F�E���^5:Z����U,Gv���ʸQ0�}�r� �;d�؊`x)%h��{�z���efg�����rPVN(�a�M�L�|�n�ٱ��{�Y��c�!��0��jgBz��N�<��� ;��ZDl;R����@L�!̲c�DM'�cxx� �ڼ����v=�̜��|u� ����h��Vp |^`ܧ.zt��"���k�!�ͯ����4��J�s=_��?�c� "n�0�d0�Je$���.XP(����֛eL�0 R۠dQN����J��Y;�VA�~4\9��2^=�W�  a8d�a���hVLD�X�g��D�M�ykІ����U +s?�g�IcZ(�>�!�bj[�;��f0��s��@������=�~ �}��.��y���� g좮�"qh������s]�(� 1����� ���B�ʹ5@��n���=Bzd�t jp�_ԙF�x2u{a�vWy^�wx�cŸ]֧�t���1��١^� + ㅻ˾n�_|��%�!�fi�;�Y��#6�-3�^��㷕��T�O�`�=$��A�WyJ)���/��*e�ĉ�|�q�W6�B���;<�ed�R��10���n:�h3H&ٚE ~@X>[]�g��l �!�b�9Æ�1�⟩�m�{vU�4z�4���^�ٲ��p�q���ܬ=\ ��(�m�[ښP/�}.nk͕7�k.��j�)���h�ZӐ�@���Z(� +��z�|X�Y�^�U{��k�k:�(w���} η��j6�-%%>��S�RpG��x[�Fɟ&�iz��s��`6kfoq�����ޢ�����������/����Bhσ�%sh3hZ�Sn +��z���q15����?��ׇ_����5.�q�;<�7����_�_bx��������g���=UM���,l�橔��ɶ������QI��|q���Ą���u�T�ް���k`uJ�[���E����?<�`��n�t����=]��ôl�/�֝&��џ����=(�u�t�?<�v�B�?����^��_�x���w�`N��&�� /`x��?7���_�����/���������?���+t�M���\|v���O�.�����7���˯z�����S4���9�� O���W>�?�͞��(�Ox������g@Č�:�Qv���n̿�9<�^��D3 ������0"��a�]}���&51~e��F�d�|�%���.F�%�,�| M�G���T�;8]x��NO�07`*�k��*���ٟ�� `��K�������9��+o~+7�}��������S��r ���B�}�ȣ�@�3=_�{���E�!>_!�� 4�����T ~x|�Ҝw�x&!̖�8_y��~�uҊH���Q�~��� �x\���V�|���N�|������������T!U +b`����S�w�/�x���<�{ S@"V����6X-�oXR�+�!�$s��:7I<��|�ھ1��!9d�g�� k'�R ��N��[��-�wo 9c���,K����xa�f�b��O�{�W_�k�����?㬷���� �2 ��PЭx� �s��5 +%� gq��O 2h�%q�"�m� V+��E�*#��IS��-�_�&���g�pE3��v�hΟ&d��A�yt�j���:$�zv�����o�+�QZ ���h�p�� ��[$?��\)p [��Z.���H"U�бG��.����V�[�:|�ȕ�KzE��Of&óG�U�!wg h"�~�pE|k�N��E])����f���,,N��E�Ҥ⇌O|2����\��A��:,��JC���W�B���W��i�GU�1•V��F?`�������d����@�5M��֦��n*�I\t� +��u��n�s�e�ΆPc�|�|���m>��?YL�0�C����Q�����$��VŹ���KEPK4��g����L�6@ZИqt9�Rp�^�։ԇ�z�[�����O�L},��f(B-qǐ64z0�p+&�,Ԩ˜�]kE�<��CX@�2��e�G� ����;�H�m�ݤ�N��"���'�d���>~�����G�٘;G%�}k{����N�A7�<����S�� ^Bˑ����k��������?c�.��S������g=����S�g��Y���X"�@�(�ks�8(L�4~�@0d���MTu�5�I��*`>`�[��`��:��1E�������^�P�g|�_�����XƜg��b��;8��3Y7W:Ƒ�}��y ,Y�Wha�Pg�|���U�)�H�� ���Ν�"L�s��I8=8P�3/V#��c�ښh٩M�]TK�t��@ ܖe�v6s+q=���M8#p&`�2>�� �%��Ҫ�����[�D�Ps� �åW�K�e��{�p���?�����˙L���3: ���TS�k +GE_3[�W�n�c�fm/����A�����r3�����O*�*]�Ld?q�`�\T����u�^񒙮*(諑8r �um�i��S�5qE��}T?t/��A'P<�mO~���s���� +B���tg}Ɵg�?�y���Nn��,q��@^ ����P��g� ��qQ�f�{{�H�!]��"cSD�`�5L|��\ �ts��p�_���O�J�Ϗqь�o�|eE���EJ.C����bDL����?_9������ �����{�?��ݷ����"N��:'����a��8��T��͟?�Qm�|��у>���K^/�[�VM- �������H��e����S�<{� +�X@� J�����Tч�:ƊY.�=�H�&��H�'��T�_��q�ƉHoO��>�͋�_�R���>��C�7P���v�<~Zi~������%?��W �T=��)��1Ci�1�ІA,�5���űr�⒞��t�wmg�Jt1O����o��<��{<-�V+�T�vo�`>���=��+�9��*��"Z���M}�(���(M$�O�Q�z�����5�@�i�ݞ4��&�˻��f�2�Q���,� +3�I������đ[ �O@��l��_������ۿ�gL�1�~����/��?�������yS�o����8���- �3~�u~'�эȄ��o��@O����>�"yH�X ��O�{pU/�w;~k�Z���~��|��W��A������>�E���盀���~'��e�����t���y�蒸�+��s,[� ��_��|/X]x ����;�9H+��oRu�Z��JS���c��� �z�F�rF?��_�ֵ�&� ҋ@�1J�:�t ����݇�u�ǿ��7�m�~'� +т wD1��Y��YY‚~���_���㑾7��9������]���xlWCA������� ���K{���k?�֣WCG�W^_%�R�E� ����r�����_Kͪ�q�N��_���9�u̗���Z��kـs�!� .g'����Z�4�|�k�'��]t�,�%Eu� �"LLo �F?g&]��+�ѣ#kY� Y�\�HM�mu [�a@mɛq(>��Q!�+��.F&]}!�����˽4��nF�L���T�tY%Db������EKG������g�Ť��d�h�5�D�dć�0Y,������L����C��5����~T�5�K��m�����+ OK�r�8���9|{�� ��,ŕW�lS�j �3�U��aH!��2$�W�e�BwY�3P���@]���q2K^%����t�lSUx�.�] ����-6h��n�;-�6;�����y��_|�^�A�+Ibm�0��;�`��`�JGSpe8�U�Ш���W����^����o2��(�F�d(���0�V5|8{�#���E WzI����1���Y|(P?�톓O���L� O=-�l����l�-����I��»�߱�v��v����e���ƾ������N�v[����E�O�#��S��rP��FX���~L���i�>�j">W����tQ��#V_؜Pʢ��0'ɆC@%��>��W��?xy���y�JU���]_��3��x�E��j����ԇ�W.��]�~&��rrV��F�GT̛�e�Q��Y��0��n���Z�4P#i�0����R��5�!���w�خ��J�z*����_��q��z�����}7[Tn�Ύ�a��|��?��j��K�.&�����U��WQT�Œ����3�.�Ӕ ��"9�@L�xZ�8Ch7Z.uE�^���:tiqr$�PRd/��K����Ps�ٍ�5wH\�P�T�I ?g�f��ßf�vg�E"�B Q-j(B�R� �D�����A\iNKS�v����` �ea �a�v�/��6�ěKN=[�`�X_CK��8��� ���K�@�]����ګ�o ������y���W�Ԩgb���6��uA �L���꩎|�Pj��F��*�U �8�1 �/��� �,l>�9�Rr��8W��<�ʹ��5�f�����#�1+W����>��႐����Dd^&��;Ny� ��� }IS%6�QS�����ax=ht.�*Q��T��)鸴�|� ��]�G��ks�� �ռ�-�wo��Y�X�Th{+Fь���ѿ�.� Y�_��V���a̋��3��I2�NF:D��(S�anIs3�ex�S��"ҏ��z�fϧw�2&S�oP1(yh������ ��X���,��1j�f���:4x��ii{��A��D�Ͽߎ +���� ����7��0:�ʅ��C��},��z绢6�]���#��C[�ts [��P��ݛ����#�=���-�wo�Z��HrX��;R�^���G4�/�X��4��� +���Δ����e����L��-�N�|� #���S�Y=>Lη����B�CV�i��x��\�6T����z�M�x}샚�d ���:��6H�N�C갠Z�&�������삹x��rk�6m��х�Z"��(y饯��Mz�M���Rq;E�4��e篘��lת���2T�����n���_�2�SҌ��P��A��j]7�2����&��/��p��1G40��Q2x(6�zbrJƆ�nv͊>qp9�W�hˌQ��]���l�u� �i�:t�����]5��ѯ&�t��r�"���'�/�� +79�l/|nв;'��53%��`�S*���N�n7�D�yim�4�Y��>��|r�7l{ܽ-k'U�ʏ�q~��o�Wh� �����SoA�>=!Dg�c:���k8�g�!!y�C;�{���Х�S��Z��:��h��O(C|�fl��Ц�(Z�NwCs}��uE������w*0L��$9l�0�;]�8��_�5G�K�O�}���_M��*锨�ifƜ��Ec��:��Q,`���!����c�г��ü����-J���1�0�I�����ۀ��'j��ν)j�_�T_�4� �����^�>�-�*�<��� # �B�^ Ύ�^��҂��4����7�y��AXS�m�!�%"�܈�����q���m��7��?�I5� +�W������7Zt���z�:�)n��w��Z��[��/|+ TR^�k;���,V�E��,Çk��-G�$gBݨ.��v=�ߕ��H����C��~�> Jx:�j�k�7H?�\�����lIu, +���!��ꩪ�� ~B���43��Aw߲S�5�:�Hb��u�Ga‘������2�k�� iTpT�y����r_ih֜+�<$�E:� �� %��P��fC<0rkPD�0��[�V�_�03p��W �m�W�Bq�8{ ztx-�]��SA�g��" ���d?w�m3�_��w�DJ Q�K���=ٓVX��Q*ه�34�i��9e��`-#��RT���Zc�8'B�����$�����-m^��(Mob�C���y-R���v;�eR�W���?�jD�}(��E G뜃l)!�v�Пٴ�OLP�#@7$���I=R@:�zI�d���څ��4�c!#��8Q�߶�q��i.4��-�N"b1��*��W>��y�]}îvb���?"z�ܟ}׌s�pB+��l�G��0Y���۟{†�C! +|�#P�o$��*:y��,uD#��c�r�k�C�+�?bz��ǽ{�@&����m����߷;��G��(-���ԻB|���� Hk����9;'#���xx�*]ظ�`1HT�L���VBsصYy���աN�pe�����wSZ�y�g' �����g�_�8�����ڱ��K9#˿�Ż�f�E�)��9c�#+�Es3A�W2Rt��g����M�1�v���Eͩ�*�T>�(�q���0�i0�A�F��JQ��� ?,L�ПE�>��Rl_��#�~���X}J����uR!�3r6 ��nj��� ��K� �����O�-����b��j"���o�4L�u��@}4 ��=����nyܹ%'�~Zj6�}s }�3���S �W"�����C2�aO�����x�Ta�"���_C������X��{=b��^�+��X.��Ԩ���q�Oݜ��P8��d�U��w�=� />��yŬ1�4�>^y�-P���u���B׆K���n�=�֑+ +~�]�.K�_���;�u��s=bp��Ak$�^�p� gB�,/�=k8�Ȑ����>�dnkP���r}i�_�nQ����;D��õ���O�5 �)L�oAXn���^Ov�"�UX 6�/1(;u;h}|p��xt� _��K���M�{7�����-��5{@���UZ�����W�UZ�d�:�thN�[r���+ �$�`Qdɓ�ҼW� M�0�E�@��5s�Bw�4U�R���KUHL�h %��L=����M��O��>x�;&UJ�B���-"�Ԓ�� ���Z��Bk�jL LC�L����N=P(Ω�8���Ɛ4Au���3KQ���A_J���p�̙@��8���Q�@}�r�72�C=O|�tV�P&Xڼ�t �@�!��U�U���l-E˾Ǝ]�3�x3�%`�\X�mDO�=�]j�s����2�]������ ��G� +h�T�+��P�)��Nn�3�MN�� +�5Q�!3��e��� ������Ī�@qޡ���gAG1@�\#�Ə=*�$��tͪvҸ)���,���ր4FNZ��l-!Hw���ʩ�P��q��DiDC��!v�W�`,1< Q�I�1������@Yֲ����;c�@s�ZQyp�~~��Ȋ3S�Br��v-S��n=4p��gP+�}���eN�H9RC�.]~����I��� .�wN|W����� *q�'gP�L�I�@0�����p���=ڮ65�+�d�YY��ya[1pU�_ioY�]�=�#��y ���7r;�*G���Ȁd��4la����0�J�"�*�H1�f��_�=�O��/g� +*Кerӹ�9{�qϾ*tC�DQ;�m��]�iK�)V�y�W T���`��t�� ��0" +gꗁ�Y�Gϖ��e����dh��)�6=��T�|?��������4�ߨ}�b5�5ez�}N���D3m��-g�䋗�q��j)��%I��԰��W25P��j>�e&�,���1�� X�A1td#%�xm ���tإhe�I�� �kD���* H�~jX#T�ʲ!>�Dl��2³��z�l��,�H�$pT#�7�h.EY�Ф> q�!3 �o�Rʘ%����g΃y9�3�ˀ��,Ek�?��u���p��-����YY)���.��_ ���N�>pF��c�?tw���`S��F$����X1�~r>��3{���υ��E 4)s��T��p(�"�0�hcG��P���5�ˈ +3$�d? +���f�<�X57OO�R<;)��I�@�}Idž4Z�2=��\/�=���W-��'S�,aH���;(��U]=@�e��Ӽ��W� +;�DW����/D0�n���(�[�y���M�`�! ">������/�kc�Kn�� �%u&F��ɬKi�w��8;D��0��o.WK���%k%P�-��Z�^0�d��ǩa�࠲B�,&\��P�Cݑ��~����-�Vz��o���(�$;]�e +� �w���w8Ǫ�lQ�}���,^ Ů��ڏ�Yj��YC������� {��)ƒ��S��垼~�x��lΠ�r �^�a7�U�ҋ΂�0�c�����L�yі�5����UqM��lK4Bӡ[����Ti8�q��;_C9�j�U#W��`.(�M��ijr�ys1�0���+g �"��N������h�� yZ�z j[�%`SsnW��+�r;H�K|����zܹ+})�����ޑW�/�S��_5��60fFb��#L��вu�;ڂD��zw��V} �R���כ��k�ϘPn^\|S��̛Wʪ8�&u[g*�r�Q����E�YGn �Q4�-L���s=�M�gQ�1������!����N�6;�%���J���@� a�T�A��q��N�\��P����������S��2'�\l�!4�bq���]��JPK3F���@�o�0�:I|��S�Y%��K�#2��M-i��eZ��q���_|�_�m}���9���e��`��;B}:� uQa�\"C%%����f�^��+ U"ْ�E?F���w�C�5�7��P��I{����7�}�?f��a���ۅB+���sm��Kd��*f��������N@)6�'E/�Z���H�G�fU��%/�^&�E���,��1���P��q���3��i �nu�x i��x���� r�]2g'��1 +U�ᕼ���,��⬲ +4 �)��{@ S,�흻���Q�������a�=��wg$'@+P:��a�����ħ� ��Qa8u��'#�˷l�$OC_<��k�d2��ڼ�/�j}���/��"s�Չ�=Db y2R;���} ~5� ���/,>��q�N�Q}<�($d�I��(F��Y1�^I�P�]\V.k�O�M���Zd�Z�v!@*�nl���ߕ�tqQ,#wO�V-��l!`I&�c��{� UET��$��t������=cI�/��X�4Wn����4�\����ߊ.�n ���*U����\�������[*#f��꒢���d�Dx����8A�?�dBFG$��w�k�9���Pӟ;'�-���K�Q�(����7�v�O �u�&��͗j T"�k��sW�P~�-��m�4�X�H�z�T��;NGȼ� U�qV ��]�ʜc�u� �6t&!(d&Ʃ�&�"{(+t�S��y^8�CJ�w�z�&Q���4˚�PPz'�Í�wo dAs��'$�{��/:�k/�ku"5ٲ���&��h�p[���D {_�:bC������HTl�K𚕆�4y�@ &Ũ� "b���to�uD�e݆���B2�� +�M8;(S��"к ��2%�A!_O�qog�to!hat]/Әa�U�@v-%�����5h�:_˷������meϼ?������5�aodƛp���5�kO���y����[?�!� + :�\�nê(�G�~45 i4׸s�t-���K\�\؂%)����%���pJ�-�8G�W���c�hP;� f��z��@���G[��=��:�,�a���g1�u���RX�e��Z$3���ڀ�`������9�n�*s:�-f��\}b� �E~�,O��|�Dܘ��p{��Ď�LD��pP +�WH����+�3��:Tj� �(y�T���_*5uN���Qp�7�ꢴ����,��hY(�<�6�k +ip��6�13IXl�:]K�V ���o���5��"�tQh���h{v���6ط���=��?�j�q�݂� OOk��>!���6�=.P�,\���L��?:��qI�:u�Ƹ��}&���Q�a^��� �"�B>�F�Kq�m�I`����3w%l � 5c(⃨"�+c�����Z9I���(E��%�\�Z��9��� i �}�����R;xf���7MW~�h10J��Ϥ��a���g �!b� E%�{��Ȳ�������~�0����BK�jK��6��;�?�Vw��d-�^�u! ���W2�U���%��#9�"�]��XcЁ!o7���cB��頯���J/UƑ!��{���i�����"j���?���jq� �xg�u�)�I؃�=�A ��YH!����*,4��!/��g���{�<�7n�R1��l�9W)�t �+Μ _2j�Cj?�g) K��Nr� ���f�BF�ku16��@�T!�L?r�jI(�K!F>/�-�>�"LXH}����R,P>Y�$�٭/G$^���r�p Y-A��]=��d�I쿢EH�(��hW�a�:�����)�T)�y�j*�FF]�*�\�|}��åS0_��7櫥�?�R*�|7�wEv .]'� � 2� ���S��������MV8*�jF���?�i���n���V���������;u�ZW�����K�f/ρ9ݞ�V���cG��ơXE�1 <��*�dKmG;7�c.��צ��ѽW��E�D8,4�D?��C]�2T�1���^`:?�+�zt�y��ƒZ�v����Q��@�*��n��6g\4���Τ�_�� +o(3���[A +��-��m��Z2�����gų'T�Z��{�uo� ����'-�?b�N�5�� +����=n�$f�͈�3����Dߡ�V�Wڷ�:�w�@I:=�Dg�x���ҭN[��yP�+t[���l�Wf�^�.�5桉��'r�&�:{%����\1~5����������԰�*j�R?�چ���W�����Y�?:�B ��� +z�5�9�jd·�_� ( �ĄR����=��(�G�T��( 2�#N�pK/��u[�%UʯV_�e���_n����o)W%wS��_�����C�0ϒ�Ё�c����~��ؽ%rs@��#��j�����,vC�W��Du�c���I�G'��V��) �gP�F���z+f�A�$����$����(g U �������w����y ���5��u�q VU=�� u�4P~p0�"2��9�#�* ZU�a��|��NT6d�8��ƺx*���`ݱꐟ�i�����4T�,�9w�3kP����gc��0�F��U�)�IG&!���� �rh��`(����k� P8�q���ɠ²߲��߂��~� �7i��1��C��O,��![G*��8�=�|WH�����P־���G�P)�K[L�0� ���cpkni/� ��ξ[�Y6�c�Gq@��� `wm5*�Jv���4���bF +M�m���ۏ����Ca�H��d��t�)b��Y�GgՂ +�Q�\�g|�18��[u?����Z���Ss���0R�����/Fl��6'���g �`�6v� �|P����rF���ĕ$yz��>�~����a�T �^�_�W�;p�v�bc�,0�w-v��岖�v��������6��Y�~� t}�1d�*K���y���md��1XO�p︡ +��q+ ����'�={�UC�Ǵ�j+�*��ps� �RD[����R'�&2Y���CM��N�J��U�k~�_�o:�d�nl?i�����%# /��An�������.���d�2�BΎJ������A��|tZ:��� C��x�w�8Tf��$������,�����Ŧ����r�9e���;�)YĢх��)�7�Ģ$*p �� �F9:�������ݢ�����{�Kf�7���2� +H�8�p,*�e�[�毀����7?T�w���2]ۻ8us �&>��c�\ ��YO�H_>)��� ϲ6c��Ru�hAXp���� +�ʅ2�~@+����6��x"��Xj������3���5�Y)ձ4aҗFN� ���e]�����_��lkѮ.Q���l:�:}"8���g7���.��1��zTp�h��E����M��wT�M�9�/} =n��������\���鞒��]*��Y ����[R���Ilp`�$��A��A8 +��=�s���@}B�4��y.�c+����' �k�H���f�:����F~��jw�J��<2�����:���CŬ�rrs9��f�(��� �ˊ6`�HJ��7�/�H!M�/��d�:FF��Y\�_����k���7œ������DIR�}�/�����>Ƣ��t��g �eB�xb�K��(j����}���({�@�T�6�X +�Rd�s,�� �w��Lr����(�@�+i�W��Y�%4QO��)'v�%�hh�,�謣�� +���!�@�\4��/0��v���'<����A��(�8����Y��������_�"�-��v~� �C��!���a!��Pru0V����5;x���oBф�]$@3L*?�W&z��S����#�]�5O56l h@��C�$����^�-���]��!�0H�Κ�A��Y��ZdA܀@uy�����ܯ-��mG����F� h�U�ǂ�|{��j ��L�.�^D�ɩY����N�T�� +n�-�̃�Մ���k��+��+y��c3�`O�5g���o0�x���?��w�^�d����Ya75}�&�g���:ɂ���H�M���ܫ[��V�*�f��Jǒ��CMe�q�]�Rt�� �ꁭ�*��ʾ`w���[�7H,,]0�O`H��Ձ�e+,G�(������<�Q�#�G�i}Cy oL�ylq�h��X���!g�[�&����=��o'� ����:q�ea�_�}�����X�8 �H�ҙ�͎O +�`y>TG$J��z9� �CK�Эr�"E�?�i�}��C�7I��/�{~z�Z�ź6Q�䠬h7�eg����|���_�����F�����B9v���7���fU���O���@���R���� +(� "�JS�x�"c��64���VQ��-���<�r�DЋ�)���i{r�%�����ZE�{Z�$�_և�����ē4�H8c���*�- &,��!�8���s�I �-!��܎2�R�+�ڙ�M�]C��3O�������"�( ����nc�B�l�ͩ��_�\���2Ј�5�mO�C������*H��Dj$�7۶��i�ǧ�� -*� !��?bW�E��NG�$�.)���5J�w|�B�+���G��&x;�==oZ%D.����:��u��cܗ�Tw �}��P�Z+�?�AdƧ^����_w������-���=T����~�v�f�n-F�iY�8õ�7Ŏ]u� +h���h{���(�~',�Ȥ磓�J��y��X��+���bx�%���M���� ɉy�"�wDi���QL�T���9p|0�kEĶ���齼W�>cV?~� w���j�e����2?z?̀����m3�\�Ə���Б �԰�ZfkC��)v��I�n�@�H��Qڻ��o���{>>����!����?bG��(iӏ`D]��R��k��+�NS8- �"�6���(5� �#�U�Kf8z�����G�Ò�Di��жXxŽ�cy��27�>�oJB�h��3dfw������ m���ѡ�Q!�6�ǐ�l�Ym���Ҵ������{l��~`$�h����?��·Oy>6�2����QS��F��F�=N�R�v;��Mud&Cr(sBHǙv��:@q�f�S�������3H�V~ bOty�����+�~��?lr��:�T3�H��%; �2::KT@*�0�%b�%�#,Fyn�6��7�tFL$�vDz�.�i�A�q���XUܞ}�)M�?�`��_(޵á#��˩��~)�1gm�b��C���(4@���HQ=�?r�jvX$Frg��QW%eES�-�0韀&��*<�����H��X�x:��G���ǣ0/�6 ���hJr� {^I����,�' +�s �r�#��M�]�W���n,B��{;^9�\��Ӟ�O['L�R%� ɸ�N�|��*d�L7�_үd �mW����Ԍ�v�+� �յ�d�5�cwŸ�%'d��� +�@�}�s�j;!�,�m^DN� �c]�rIa�f���+L�$�=�r^^�-52_ �1.N�X���-�ǃ()��%/6M}A�D��I,���{�t�!ݒ����iʡ��+cO���c�`kjN�\0 -����82��iH��� "����ڗ�R�R����B�U`��Ͼ��{�|��^w�E��慓��ø"V����'D�A>W��H��wv��Μb�m�YER��D�c]�콚�j@(y]h2��,�)�'pS�����Qm��M�*e8������%߿|���D\�K� vx�j��oŭS���dw-�i��n\yXHӾ����Q`PIГm�z�Op&�� +�����;�K�$���k9Wۍ풚��H�N�k��ӞO�Q��ҷ8�s����w��z�F�>��j ���2.���NnG���>���]� �g?7zҒ�U�N�+|����O��Y0{� �h�Vw��e�N��77/c����\�x"�y��(�q�"7�W�&���pA K��/�u-�t<|�fA�/l�p�;�g�H5�¬� �0fi�~�Ww��g�Xi��b��!�vW&��7����.�jy`�~���c:���h��"�ۚ,�~��� �!�e���c -˞���9 [5[����G�rǴ]��0��� � ԇ9�tl-���]$ax�CŻ���S��3~2�Vr���Z���r��MC-�|eh���AK���H���#'��C��e)I�������"�s������ɲ,�SB�r.s��w�w��(O��Z��?_��ӡT"�G`E����������S�&����GZv b�&�=ժ��t��No���O��PYRr�R�+��ˇ�VW���B��%�����YB� �� ��ٸ!r�}T�p9�@h@��, ����W�*t|{���c���*����b�Ϛ� >5[}m�GHc���?��d���yy&��fĠzF��"���f�p����/��� �\"`+�C�U�������j|�J�̬����\�i���w �I�vV��9�[�jc��[� +�����n9ۯ��ȱ{KS���}�L�`�!$� 6�կ�p��H (�y�i%)�h+*S�]�n������հ�!R�\�W(�ޣ~̮u`b�jp1n���qj�����d����/��qpLg� ����b�O�����d@pa&-�3bf�m <����ĉ�O�*�!pK��LS�϶ ~ť�n��E�xM�K�X(����M�Y�Z����>>4��I��+H‚��k����z�|�26#*�Y:%� �c�l7�ЄT�W �˸.�|9M ��C�wT���[^X��`s�K�F���,Q� -t�y�滅f�չ���9 �V}�K}z�%/ޢ�C��<���w��nU��rɘ6M��QoŰ��-��1��qI�ҟKq����G򛎙��2�j2��~Z�V= +5(ٖ7՟��vqܥ0�E�2+�r>ө�\�o#y�H���E��e�N���3�g���+K_@\�n�nޭ�ڹdv~ ��Kf��A���a�;�k��ȵ��vT�`J@w�9 �zbv�_������bGs��\w#j@r�?Y�'�8=�퓞N�.�$��s1��S�{�hz�b[&�u������",w�A� rvU5�i�UH|b����Y �����S��ߋ��'���M[�؟�5�^� ��t�FZ6��ћ"=ye� 㤞Fb!{ 4���ѽl�َ��I|U���/�Uf�m֍��b�\��OR�3d����-o�=t���3x��=��=%���CK �����>�H4��4����� +n�'�b�Ke"�ş��9F����%M�-Kv�Y#>0Cc�* ���{>>/�?L��� +d�?hi��Q>�=���W_gzA�}��I�@����.��uo�Z����k^(-ն��2#�@�F��2��H���eA��x)0�4=XXG�����yֲ��V{���jI�,238f�U`��Κ�R�2�$p�����U�ƥE�c� ��#ǁ�s�~�8Lu�r��6oW��\W���(UI�-p-8� F���Z��:���_E��M�y��%���&>)~��_�~�v�{Ūx˰D`�b�k�YiV�IT<���Q0�k���7e���wc��<�v� }�Q�}���cSV\��:����z�����,�'�E����Z�/->>�+%�vZGf>t�(0�� �R�-��� �LZ�`a�6N'�eΛ�pOQ����n�][ԗ�Clя^(+I����> +�r`o���c������,�ǵ�8u��eZ�c��f�� +F�r((��ݼ?Z�����[yD���[}Q� �]>@���vBE94uJ�E@;����֢D��e������iy�\9��#�3�o�n�WoG��Q v�*s�ڵzb��.uN1 ��0�}k� w��FZ�7��G�%�����b0<�@"���S*O]�Kxswi�%P��HF���v�V5�Bnϱ9A(���Q��T8u�6����!�œܣ����y���� ��{ɳ==�"rY���C]��+���Gf�� �Y���^T�[�?�Z�i�s\�.^�"u*v���z0Iu��M���h=�g�gm�V��Iq����Wz�{�N�-���?-�W}��lr�Vq�R'��ܷqn )G�=^I��4�*�cTN%o��o��||Z��u�����;}���d����X�~>�(´�8���N-.�z�ێ>�y���7"^��C� �ݕ�Oq�8�8��-��Z��U��d�HI�2v J�P�$��j�Mz><)��귵- ��.�W?��9lHK���[35�֕�X"VԊ#�����Z�X� ܨ�KZ�hGa*�݋�~ȵ`��?7�M�e�W�&59Ț5- ����Av>�"�P�_���R��ր���Ϯ�g�0�l����؁���Ar����HY���J����a�6w�;���.}4�K)+���#�,K�m� �#Ifqd��μ|�-�x�)~ +�e���݉|dR?aُ�B��]]��@�剅��:TV���ժ9(_r c�g&x�0r�u|#v������ ��n��L%oq%=�O��9��;ۅ�^�[��!DB�����ʣD{��\2�҃��CY~�t�ԏ`퀦%8ol�;����e�@]��H@��`�}F�ۆe���������o:�1�1ߠ��bUB�'o�.�5Et�Ĩ||7���PL���x"�pYJ��M���r�#vSY���ٍ��i�����咂�[�n�:�3���C�ށ��`9�іG����*�7��AN�SD�_�A�K~��r^�n+�v"��P�t��NP3��P��:S%�0*�`�y�u�"���WU��G�I�5�<��2G/ѳ���1͛엊�B�� =GN� q$nU����\M��玸��˳��Kr���>,aé1��)��,�_���Ձf��RM�&�y^ژ�� �5RF�(�nlJ͏NvL�n��&�#dP��T$h�J�s���B����y�^����c���9�aV��\n�7�����#����ţ�:"|���ĘdQOnW�Y>���I5G +�H�L�>���몧���N�@��4��+ 0�<΄ر�m� ��/pY�Ven+Gv[ZSU \.�uR���0!l�� K�I*��b6�Ijs�^����B��9��/F���9�S�p�+4��s�Ή�C����O�{��?{�ތ��V�.^�T�E��*�r J�_�l;d��k� +U%`W�Q�b u�,�XJl����?�'2�"�T3�7Ȏ��ry��}��ߤ��?����������?������/�������˗���?�o]C™ά�Mc��c�31��5�V*���](#4CK�֝K�]�Q +R��ؾ�yItA=�SxW�p8�RS��_���ɳ�7P��Z��B������h�cns���� ��eb�@w??�#�����Z �Ab�E�L�8�aN�r�����I��U��`���Jhf`E�H�T���&��o"��Q�Y��awX�rU�Zd +��MK^\�@4x4�v�O�p��[ �m���Y=��3��?�/]���ݣS�$"����D�T?�}����`(��$j��@��6�����čn���G8�Qep)Z�tA��`�N��D��7�RN,"��)O�������Њ���ry)�r �8���*�X�N�kT��1�r���jL_T-��[�B-�7������_�-K_��n���䉑�J wO(�F#��k�O�JhyaL�G�ly�}u|�BG��`Z'�D�C�:�f ���V���n�}����Jq� �4�� ��%�� U�'�{}��ܟ����Tx�6����ӡRC����|��5X�M<��4�{�������/ߎ�Q�����^u!1ᑖ�o�HE��Zu�›�쁢 +lmI�I�^�G�AW·�*ˤ?*[���>т�L���N��#7 ���7o +��5�ۉ��d>��筗8bYt%��Ty��]�𵻟������#�vU(y���cx,���=-X�sO��� )*��p'��� +w1��n\\��-!�{*���@ +G��K��d�S�� I1:0����E�K�tOg���՚�{ +1�As��� +�Q'�]��;Jp���FWQc 7 ��p?��-�x���.�^Q�@��v����o� �"�F�f@x�iY����r&b �}���9y �d%oj剹�ü��:�w��h-!��l��P�G���`�h����Y8H~}d�xQ��]�J,S.�U�Ť3�)6�b)�0u�u�����['�����`\��ݰ�d���_��$>K�������Ȃp]������i�e{����V<��ƣ5��ɳ7O�^s%�c�O����`X��3 ���=��A��<�ɐ4j9t��Ry�<�����,Hxd�l��d�ղ�K�4n{��UW1V�H�]�2�������$#0�ձ���a��ei+�R:v���_?^� *�% ��"��&5!�Y�<��^��iE�%L؅�z����=��E٤�:���lkh��D�0,��L��q�C��vM�k�Yv��`�a2㠍��+�aJ��+�^�>���ؼ�,�+��5yjJj.#9�&��N?����N[���C6P����A��ԅ�x 0$� +�bR��4 �+��Q�\�� �Б�����Ku3���������% �? Cƥ9G�![v��� GP�~X�<�hQ�%�F��m��pe�~���SWq�sډ�C��%���-� :�9����v���h +톉UNb���;�����_��`uޏ�yIP�Ā9��M����o�\b~�C�y��.1M��R���@W�P�O`v �\�?*ɂ�Ma�F���D{� zcR�R�MO�O��ֻ\��®��yS��}b������ +`1���C��Z��ڲ����]�z� �+C-H�f ������b�b�{NdQ&Uu-��0��N�IP@�/pC��j\��6`B���8X�ca�j)��~$NYF6O[�3P�/P],���Z2���+ +"L띣e!qFԬ�ƍ��@ی�5"(�T��!ƚ�V��)@�����؟�̇ܶ8c��ۻ���_X��\��Y�$���IZ���6��N3���Q5�ȝy�WD���?\���j�iJN ح�62Uآ��0���޵TBx��*��q��N^����`P$}$]9�.�v'ˣ�;���9��T�bwW��2Zt�j�T X� \������f��_��I4L$�A\霯�o}���<��E�b��%�Z��9Qq{R�/pr�SBu"���"�Ţ��׺��4�V<贀HA/i�U��KZ�pO�n!^�zg.��G4�sc��ȵ�(��1�fo�7״��� l[@��Y�ήh6�&�b�IMWۤi���/�3,AZ#~Z<4��� �W�}m?�g1(i�Lu=�-�\�$����wlO��w �A�/�e۾�8��4v]�� +`�l(�� +�W�ʨ8��8y_g�C�y�^��N�*��� �Y*$�ŷ�1ύJ@4�$S��� +K�*�:S���k��@E� +d9f��l�p�`H *H�����iJ���4�n�B܏�@Eؘ>V�|"ARO��7e|?�A��϶� +V��p��_C.ō\(e��9�Zvli��=�zF��E���'�&�H���ˢ`�����Ie �:7��\�)��1\�[D� J�9�0��ɵTxD���[C �Qb��؇�t +��4��נ� � F�e��� G��v���|7D +AY�����x��5P���W��S�RФ=00�� + m�����Ł��097'�a�Os�@A�%�^%$�j�R9�6ԙ-�O�S��'T�왠͈�RK�Z� j}�>6�FN�t���y}$Pc�q �*0��[��rA�Se!���T��R��|wG\J�����P9��㤀�dM�;�3!�!��VB�B�PKYA���lCI�=M�p�%�)��)z��e+r�|"�n��P���~i ������A��R��I6Jx��>� �ֽ���ԑ�|�Z)H +�&5�".�>��]�E<��f�qx��}d�(�"��%%�P�C8�6��"R_���PCδ�s���$�f�с�m��]{Vř��`�j����D����d=��*�>���� ��AҼE�.���p��[���w�#F��c-���bg+:5K�Lvd�p�L�d��Ժba~e��B(a�s�a�\��Ug��eyf�����[� d�2��_N;T��E�\ ��]�U��b�V�F\<8,��L ���R���0����� % v �Q +�d����� "�t�-��Ԭ�ID�a<����+_>Y暜;Ҥ����,��\9�Ozh^<:���%}W/��PS�G�J�/�3�'�l9�'��]�9�d�$$�;*B����;aP�R3�ý���9!�l��,G��/Y�a�P�&`>�i��"�'���Q�0�ܔrv�S�i;��U����0���4�w�E�;�N����%e�[�� E��s"���>�X�`v_�N�<���2�)��`\N�ǯ�Ǔ��� �3��1��b�Pd�R���]�%L��S[0�5i0@I�*fJמş �F˴�� \"asZ֊��"�4�a!�K����]�W �$v��G�*7}8����ӧ�G���� [���Y �ZV-8V �eYo��`o!��� vK���R����p(I�pz��8!����?�O��(�6'�}0k�qH=�笝�{�rY��vD��5�I��F3�m�x�i����)��%if��R����*����bE���T�lTB����Tm� F�s��pq�]K�����!�cq\{�Xyڄ�K����!鿢K����^���||8LU�ECE��8ZӖ�`s��Q�����o �&�S(W��]�fת�l���$�J�&V݊f�*�=^��2�"�����>r�4 *�d^��!��! -\����GHK2�dI�!��ܛ �P�qQ����X� ��C;� m)��~a��<�t稁i*}�b����ֳD�]ӊ�XGD� ċB�[x����I�^�|v�KY��H��/�n�,��Ip*��ȻT4�K�j͵�z��&Q���b5.~�[�<�ӑi�9(��{��U&G�"rD��s�ގ�N#��37v�D@M��,�(��k}�^J4Tt5Ta��?�r)5�� +���3��$!M�� �3xe�+(� :��6tFG�ULR�!]���Z��Y ���IDm� +�#��E�� +v�V@�!*��A��Jⱴv��yJ�D�]v�C�L #�{���X;d$ '�F;������CӞO�?����D���� �/�� ��Iwܴ�/*9�l¾&£��*�*��3dK��R`�eǥaO�g:%n���|�2խЖ�&��,�|0�8��1�_�o��_O U�H��Dc �d:r�+����Pc{�g�?���>��^�!�(���|xN��)%$��yV}��b["�K�)UQh9�&��L��f�|G�S)� +��6g*%]��?�$�k"P��ݔw��+��S�S��#Ui[�m�����J�Z۷��0J{�KYG����B�dXFA�4ϳ}[z`���y��]���d��=c�}b�1�Ru��VZQ%o����j�*�Lۤ<��p;V.#��m�Df�"S�Kh��������5� � �*� ���R��$R��9Az�I�!S}��{*����ȣ�,��0��&�+d�zw�%�2��=A=)|7���8uU�������2@�7�3��� 3��ռ�Mt��e��5Kq[���;� +|�yu=2�\q�-�|�Hv�<��rz�Gi��e��Q�.�1�����:"������0�U���p��T��a�w��}V�xA�1Ut�z)�M\�c-�C~LS��t��3�����+����pڌ؟�}��� x�})��%��fy�r����r׍O[߾-�[""L,�.�a���I%�`�x�1�])�}�ڢd�e�9�`gQ���E5��<���FJ� �ޥ߉��npI� 'ƕ�ч�=��{[�cPy�[�\޳��{vH����/$|��4?�Ҷ�\*�$Ԉ�!�3�ukڠ=wHv����!ɁfI�,+�N��I��es8� +�I��/�mi�j6מ�_��*1�;AV/@�Mg�KP�WaE��:�X7i7������\�\�}&�(�&�.�O�J�aH\�r���8����X�z?�\�n��Ϗn�yt{ߒ'��/�vh�F5�K+Q�LU��"��>�竷�������2 +_��#�.x ��e$��)C�EX�4�3�TZhYG�Fo5��t\�j�^�S�5�ӫ88z�,�.����jH�$n�-&�|ڤ�ydb�"v�5 w$�����&�ԙSX����,\���7�yF�;F��2(� +� +ɅP��LE�� +uM�]7�t�!�;��C[�qU���ˣׇ% Ww9�o�<�0�I���#`@�?������i��T*�^�F�t{QI��C-�o�%wp�ݦ�"��S�*h����#���˅~���,�,�HT����#W�����+ +>��=��oW��/�2�E��8R��dt@P6:x �6 �,��ct0q�K�q%���WA?���]�AM4�0��X6{ ��t~ op�����C�b��-nKȒ����]p�ف`Wi� ��&�g�X9�~hf��T�� X�~u�L��ԪD��E3���[��`�w���=݊�\����^�J���**��*�Vh�,�|8��C�Sg�O�|��|lt9��IK��9I�b�T�����B����RC�,!M�B�+�hcJTb����X�>p����@�K-��g�.�`S[�?��^�1�EJm�_)[SP��l�w�zu{~xh��h|�{^��� ���9��ØH��@��.���6�����ٵ�.������[�w������������-����l��r�r`��@�؆m���W��@I�����v�S�Ȫ۞se��ö�������\�������μb +����|R���H�65��R^4� E��掄�9R�"���,���U �; �.K��=SrI�4�����FToٶS�����s�g(21~nS��A��q�༂:�šH�|��MB�&y��_�?�Ҕ���$�\�ʜ4��X�]�7B��w��7/�d� `���K}�w($�ˠ��W���TD{(]�a9 ɠ��/��P�2��iզ�J�����us��&en)�������[*N(4:�D�'���T�J��a�˪pg(Iu �����@�U��l��%�>��A�y9JTR��EƔc���@ÇR⯢� I��-�ؕ^ޅ�Nj.�i�v�N�#4۸���+$0a(;,�uo�KO�x�P�j[����V����Zf~yj�c��V��u_l�>�����0�I���������t.�~���2BP��w%Q��j�p��堩P<� ~� +Eb9�ګ�R��In���X���>��aB-�5T7��rYg��7`i]��}�F[Q�p�MZV�� +ơt`QE;�bN\�l��?�I1��+�}��$��CŞx��{>>��)&�0��g�}�6[�C�i%���pbλ�y�~K̡�K�9��Y%�*h��I��X��xM�P��S�؝k,D� +��� ��i=�~���?�ګ���8m",�+�Zݨ���4�+ +�@}o�,M$�9�N�b([�� �~�%��"=S<�ڼ2r?�����m0!]&f��0]ǒ�����赶��%ydn�� ҏ� ��`q�S��즁& +Tè{�ã�E]�� q5��E�kH(�p�H�����RL��D-1i V]S�V�j�w��b�!|���~��h�a��2%�"Yڃ;���Q���ugLl�ԍKT�#�+����『�������||�6��;���I�н�"�R&�8 �t= ���#��mz�g�����Y��#�kD�ܚW�!�QmanD1��� z�9I�3eC\owa�1�>�&�I�F�#�ׅ��5B�D(�ב�E���w#��� �b;2F��K�� ޟ� :v'�0+�E�Q���ʚf��-x>�ХvT��Fx7�g��c�E�w�Y� ��m�+az��I��s#V}-+@{�go�t_���G��1&�j�g �6�����&8-t��2��B3��>~?��`*�œ�whT��D��A�h�m�H�����>�-��ze0��r +���N�M|>>q�Y��z�=��C�C�.Q�Jf�[�I��\H#+�T�A=7����{ThRv�6}�TС`|C��It��l�:5ވ^i�+�P�t�QYn���7l��n���K�I�v�U?��N�(��Ot�{I ��l��}08p���)ڦ����7S�b��Ĉ�V�V�"�������/�/��R��|�r;hHZhzD��3P?rcd��y��}�E��D"5M;��"��y��l��dY���FginV����ɟ-J��լ�Gۗ��{�<fNH�|����//���,��$�b��H(S$':5�9�C�+<�}wD�d��Mj�)�~�� % ����s�S��y��������Ū �����m�rՌ�<�s�~ᷤ��0�mi���oc�9�O�o O���fr���bΆU�W�|��(��c�-芳�:Ze/�K� �#^��4����9�4���@����m{L�k��pl��`�G�ف&lp�h�sp1풣�>tZm�x*��6k����&a��������AH]<�P�Z~\P��n��]�l�^��A��Q\̲I��19��Q;m�(D�:�h�<|y-�Rg�^W��v���N{��2��^G��s_f�پ��O�$oIF7ۑM�;)�xe0�^�mUy|��zh���yu�YO8��tA�� +)��z�U�\Q4�sY�F�iq$>1���i ��V%C���Ҋ� ��[ ��r���_��ej����������7�F��mֶ�'^���l_���~�mcDO��B$�E�]������ȬrOB��lђ�^��9��l� +^��o��W˓ۃ��� �����w��)�+�4�������A�БU攏�b�E�<��ba��"<���$S�`?��ȓ�'�h�’[`�����78J�Qv럲�̀ +Jx,d�!��H�]���s���|a�?�d_��cmw@N�q;bkˊ����� +W�)��gt}���;-@�1Cܢ�vR���F�狿2 �l�ܢ���P�K]�rp��-n�Ѿ���#ޢ�>�o����7<�>�+��ͭ�@�%͚ kL�[n�X�{w)� +���� �5�-�����������ꎻ��pJV���-Ȇ�$PA��n�6pFw���l���y���8��ڟu����@s��?���A�� ��I �"<3��@�@L� ����zPxP�g���F��%�.����@����-�2g�Y(���}|i3)�s"��`W!��s�q�L@�=QX�+T�/��� \�Q�c���-����+�P�)�iχ��V0PB_S�kπ����;3�� \s� IIeY h���"|�H���+t���ː��Cu�gȕ��ױ�65P��@��] +\�plϵ���}|a�R��D ��[�y��N@ҵ0H/�3K��O�G*�g'�����+�)lVO��Z�ؼ�!��)��d�xhb� �GLi˴V��+.��� }��=�b��u��B%�g�~���5�Kq,���q T��Sjq�����yrc��} 1!fl���"�6A�'9R��k�6��Rq�� v��#M�2m�f�dxe�?B���� .�I]��!����*� T֥��d�p�tbSN� f�D�cR����n�����W�Udy¡����{$V�5�B;m����pH%��q �w��yٓ���uY-�$�H$�d"�� +'��`b$0�(�s+��1�����۠C�f�_��o��6ˡ����&� 옺H6eN@�8���&�l7��1�6e���'�X����΀Y +��攙�<��1���0;:d������>p�h�U˘�u����?��lfu~YdbPd���^瀅Oo`��o�+E�v5��z�(j�cM�N�Ϧ�Y���/s�,N�y���&�w�Hr?���7h�pr.�Fp�A��_�@P�` r���o��R��,���~0[�?6�֑���C��O�v���sj���c^擜�\~#��m�t�{��D��+��k��u"�A�D���%���7-�Z]�ZR]M���q���ts}��+� bp�©Xf7窨v��?z�;�ժ�U��+��.+�<��^�M��,�/l�\v?0�� ��!��ؼn�;�� ���׹�A�|�����|�z�3f�D�����,�>zg 7nY[���� �O���� *�����k���-���� [� +y��&��.E�(��mv�A�k:�`5,���\0�PW���'��=�Fbu\�"�7{W��"1lȽ�����Gw��\b���+��a� w��'IMu��Y:�˴�њa�7-�244w�,M�����I4�����~�F�ʂ���@n��[3�=���V;{�LF�G��� +��O�}�k�7�����퇞ʀk��EkRh��PPR���`�O�OSY�eA �~x�D1),a����E�,���m�(�=C�N���}<�D\j57:Q*����‹3� ԈF��Mv}"T�;���D��b?y�|�x�-Z�/k�,�b��@�_m؃ơ�$�#7K��7��R9�5t!3�$� +�ܦ���BR���"ޡD�q�s5/,������{�L������lŬ)ī+�C7�ץH���B2�L���ϐ{ǐ��y5ҟK-7̟-_HG�ùF�[|]�Jrl|u�����׌J2�uQ��Ƈzx�(�fK�bw ��1����u}�>�QK�p�L��`�$K�Y�nP>�Q�_�D{��g(z�Ũ�Wƞ�#/:�Bޔ� p�"Px�D�W� 6S��U*Q�2 �F{P�&��+� ��<�ܟn��������:u6 +�{����(�78�%YN �`�������0@r\ȵI0�"H\��J ����E~��f|�R@}L���+�E��D��t�H�u'v����w��$1K.�ZN��)��fR� )Kȡ���G�]����$+�zm�3K�~>9�\t�Ѷ�q���\ +�o)���W {�N>�˗�?�G�#�&�"I)�&���]3�V� ��VZ, mX%~PC�"��nO�"PE���g�@��ʆ� �xr�����n�0�b� �O��Y�4�9�) �{�4�K&;�����9 �Rs����x�*/��IJp|TEXi���i��C8Ts����f�U�- T�zr�2m@�t�o):Ǽ*�#~]P��f|���62kP�P��b�y�8]�ގ�M���jhI�N��O�繾|7��������,^�"{v��Q$缱4�L렋4ŒN�P�WDZ֡!���c$�F��ߋ���v~/ӕ�e�~>�C��s�_��T���~�}�T���7�w�zfM�/_���N��P�Z�D��:�Z��rN���e�X&ՆODFm[�~^�ƃ��+W;$�S���)��ʴQB���V��C�Ї$2<�����Q9_���Kqˈ��<�/i�.D�Ӳk�T]�坸�/�H���.�h ڬۣI ޖ� �dOI�[^!�Db'W�Eӥ����F��KC�o� �r��BP��Mrȓ����7֯��#@{N�3ĝ]!�5�ʕr'I;y�5_�\i ��, +ϥ�f*s�|{"�9��c����乚A+K%�E��0QC~q8U�my�� o�}���Q~�a�+�,���ҋ߃��|2�Q/7<ˀ๶��U�:l��N�BP-NTE)At���|H�D������]|�i�ze�m�e�� |�T��� +�au�-sT����^v�^*aM̿�q<���s�!P=?���XL �re2�H�N9��� � l�>y +ﻻ����&�K��ҽ�;�l������|�I�e�h���hY[�/��L{�g٪k_s`)�>��T�\UP.��,�?� +ޖx���� �zFt]���)��':Y��k��3�7ӽ�/\��q�]��5�*�n�� x� �?EYMo�OFF>6�6Z��6Q�k�W��`��R���}=-�&����@��$5��fX��?�Xàte�� �wM�m���W-��l�/�;.ґ#��1��d��]-6�쑤;�6v�v�}*n˾��~�9-?캊*�� ���A{2������D\H��,���5��{-| )AsEN"�a���O��BH�w7���Z����7|"�ߞR�����!Վ��� �eؽ׉R]^�K��L��������X��&Ȋ8�Q�A�0�2U���[��s��. �e�.P��������d���%N����6 &�qy��T�ȿ��=� M�݅�m���{�HL!*�ǃѩ�Ύ�:�Z�����>�4�9���Z��Q�Ķ��� դˁ��8w�7�E�2�Ny>6%y��"KX���ռ�6��P%�L4[�۬�� �L�Yރ�{�1���FN/^N��1:�syx�J#�����"�M��ȇ�g��п������c��_ڇ����@�/�ah�4,�Zu���w[l�D����"��bx�x��2�V�j�������y���YyB�I�OO�����˚�P��!���T%%��M ��Rf!�x�:������,��InO�(��Ҍ�vYȂ>/n��<�XN�]�nj3qB��D��*+:���>c��@�#j6m) ���9��6�Ϧ��ф�<�l<�Q1��k�.����|���-(�ZP�tO����5v��w���5T��-�+��c�٨�Кt�V��M�l�0��k�����IGs�H�ms����H�V�c����O4I����,��S�&00���<�T�e� @�F� ��H{����K�����)d/G��uc� �\��X��]��u�f��D���$�қ���}h����$0S_2��W�_�#H�X�D�� �(z +N����5��as�U�ꘊP����ɩ 0*ݟ�u�k��-����Uh���Q}A�?Q O/l���6���b��+*i����@`Ҏ��4f�_���;�+��'�-WR\��(���ywJ�&�dFh�K;�rT�>�Ј�u�{�Ra� �.�ZP=�� �k�����d2�@��M!�<�3��6d���x*�Em�,�#�@��E�Zm�'��<��P 5����\���=Q�mc}H�qwew�d�0�bCR�5C5�Sa�!(��b�y䥤#�N���%�����j���18���8��� ��kD���̫zQA� *�h���%�p +H>nt]5�c�Kb/�a����>y05Qݡ��0��N�{س#@���8�׎K��MB�㇤�Ű���-�~���&��Z$cT^�S��T���+R�Z��QM�!#]M���(ӕ,�� 4�-�0 ���Xb,��t����@��ۜ�T��"֎̫��v�,��peܬ^�<���Q�^��$}�7#�g�����9r�a���Eá,�V�*������뛜��s�=p"��+|ߵ�/�̢<�����W(wӨ����Y�*u�X���%�e����g[ə:�Rl��F{G��xҶؖ���$�K5�T��ڎ@�~q4 H-�n�� �q��D ;&�WaWi�`A�[�d�1���~(�<)�ټp7~�j��7�O���)��^�0Iߏ*���cw�M���'���$"��G!����n����߇ԑ��r�������|};38 +u��H��o2�B�W��脆j ��)e��l_b�WӮ?A�Y�e��0��A�C�h��7.<U��4#�2�.�V$��N;j��LCW�fӣ�,���u����Y{��W�Ny���-�z&R7ͫ�����N�kvO������2�JXe%U��v���;��F��H7�tO��w�`S%lS9�����J=za���3&o��7�~�)�D��y�ʻ���8VT� mNJH�;f�3���D���k�7�_��$ߕ�<.���X�Cw�5�U����� �/ �<H��j����?a�L�?���������F�o�fJ[�(�L끄��c�̟=��Q��U��!���H���tM��+5S��&EV/:��nA5u�dֽ��|xJ`�x���0�?.�� � ���9��<ҷ��H��L� +� �r$�������<�7dlM�3Y}i�8ۋrJ�:���ͦ��rTʖ=�r�&aS!>���H��y�~e؀�J�`������̅@v|��0����2N���D���qv�ȿٝ%-�u<�,�WՒ:�:v�9��-���;=� L$��YnR�W���`'y�5! Ѽ)PJ�M��ݘ��-���0/١�� �a��l��� b�T��� �)[?���h&Q˭A&�t�h�Ӿ���~���5!W)dh�Fހ*X�Q��cO~ų�*&l[m٢Ӓ������] A��~U��r�{�v�{_!m�+g�� ��r\��KD�jχ$B-B$��|Ǟ+���������m]��\���=���,x �kV�Q���x$z6c�ꀂ &߰�'���yj�����LQ�:0_��:��j;3�?yqa��9�.�L�����sA ���B�Nq�Ҍ��,^�>ٯ��+����e���� ��)hF����� ���.�X����������*#9�uv�;����jp�L����E3��i�5�{q��4� � E� �� �8��b�?���Q}�u>����A�n[�X�H)���0�1� 0t:�sv��)�ں-L�� +B� �g��F�~uj��S��]��ݥ� *�:�U�q����G���sC%d0WZMad/I�W�z�."qB���w.;��՞ �;�D�5�V�/C%-4(���`M�%l6A�%��{k�i�u�]� b���߿AWgdDf�����쭸|r%� ��}t��+�nH�g��%�9p�B��-���.�dn� ˘ ��`̫^�S���J� ����x��>����T�^]��N C|��j��o+W �4;t�*���a��sa�E�.�o$<�3��w�>��i"���f �c�ؑ���r�{��������y��7J��K�&_B�/n)��wX,��.)qr/�(3.�=5']AL�4�R}N������(��,>=��������Q��s� 3���U�\yL28���d)l�%I��R��]��(��e.q05P9��4����G���q���4�Q���g�PO�w6}�ɹ{Z�~���E�� �SΤ���a���&։(���_��N��3%vd��+�ɞ��I�=��箛v�C��D�~%�i�L����E¸*�ϴL����s��R��Gns^Oý�vDH�2Iij�!�U'�P�&�͠2MM���+rz� ���#�O� Α|:&�� �d�M9��'�����=�~!µo�9ץ\������Da$ f_���}����i�p��+�������1�]���Q����@���Q6��� �pu��,���k��Ñc �P]e&Y��0�&�>�߲� +��4\��dʇ+,aw�gp�������"�b�D=�.T� kl�g�ҷM|G�:� ��=⬂2��3�K�E�P�Op�W���v�p��-�0SX�b����a��VDo��U�#ᚷ�!�݊��3�,DД�����$)-�]V�޽�;�`0$�d�z�o��R��\+ō*�����-?m�p$�h�� 2+�S07\ ��"�e��]�Xdb�p����aH�U�!"2��kq�t�,W5=j��'l{>��������,��1/0-ErT�eq�@�[��)(�^��p��dw�p��H*ۃ�)��em���"نf����nn�4��~J��3L�yw�g�c�N���"$���z�K��C;zĸ�DP�+X4G5#2/,�3�\U%�A`^�[>j I�.'�co���CNooyi!)\m�������J�eQy�p�t�tФ�B%Žֶ-�F�BK���Zɑ�tA���Q�]�K܅\��M�L ���Ο�tFAw�z3�R� R�ߟ��b��2�� /�e�� �,C��r3Y�~�q6(GN�����m��ܢ��X_!�n�E�/>a���m�gDҟ�_ʸ�A\�/�J�-� ��+�t�a.���p4#���� OW"�� d�Ӓ����� �5w �t�s�3�gy=&�(�L�)�����=�w 4˗8|jr\%���e�� Z S�2es�m璛�)�I.�=2/Y5hI�6��Dx��\�9>��r�!A������� �c=j�����'Ƌr�f�$��x�U�#Ùj@�X��<ĥ%��eHYAό���r�IH͵$^ӝɖbLƩ��~G޾��(8}�m�W����6�e�|��*+���X��cY^J����KTJTa�����tg@[�������.�q���ܣm��E��c��s|�m�Ƿ��!g�/�v���5ݣ������?��DŽ��[xjP-'�TI}H&�5ظ><�dП���+d�G������ߢ��e��m<� ���A��=�w̚��?D�D3m\��ԅ嫉���m��G�:=S�5�Dml���!-��54YcܼcC�żc�A�p�o,�PV�1����N��5�ќ��s�b0�?OYo�z=�H>��[�'�Zq]"R���6�}Ǝ��k�i��:D����V�)ᡪ��BXk�L�� X/�<�K���XD��K%��P=h�gp��v�'rb�ëS5��-75����b��0ቜ�+5��p1��d[ +endstream endobj 87 0 obj <>stream +�^.� ۞�o� 9@��ڃ7�����uc���;"ev�L��ᯝQn�m���D�|^�0{��Uk���\�=&Yt������r�jD�Sm ����OS�1�8�"�2K��MVu���9o$�b�?DO�˜5�_�������e+�T���d���Q���arUC�a毓������j0��}�-� ��3?��\e�m���ce � ݝ���'n|>���yXF �Z�7�u=$mE�hx AV�](�n��p� ����mvR ��)�e]�M�ͱ� a�U��ق !n���@E�u�^������\���X��&}̥B`��b.�0u�G��H�{�+h��M%��b����u\l[�=�I�,ju�?�X�v6���39.��bԭ>�ȅ�cE +GE�n�2g'�%anKd�Ђ��ؼ  �x +y0 +s�Bc�m �i �xYCFY�pʚ��+8_��(s��^��* +(�%� ����sn�.��lu�M�Gw���G (��ɕw�Ő6�S��Dž�x���|W��*K}¾����oՑ�e$@�7���s�uU��7��N�/�u��W=i�Au��Ş��--@�ذ=�JDPo��X0Lg(E+��B�< +S?ަ�Յ����� ��hZpA��fo�SԬJ�bd��m�����uרA��>�p����sɤ�}�7ɷ�ĉV��}�q�B� ��.���Wլ��b��ϛ��[$ҽ��5c��\�i�u�&'�LJ`N�T��*ӆ�LJ� ��޶�s�X��ˎς�H�ݢ�ӎ���m6�G1�� �#"�g���+��L���א7�4 �5�ʴ��qQ��bw�B�������)��o�ĸO� Q)7���oLz�� �h&P��6��.���v��nP�r����91��*� �ݵ.�.?��4�2�@i3;aE�[G�j�g��`��3\ �"�h9���. ��d��!g�cw���'%/s.*H�za1�(�x���_U���s-�xI�v�cЗj^�y�0�͑6@�v�[�RYy���n���9P�B������x��Ю�w�u$^���6F�ī�s*a+�907l� �M`�f�����`�q�p7h�q [�<��)�E�86�%�ڄ�,gA�`�ȟw�&���o�{��f�^"R�tQ�X����z�����VZB��nH :(� �C��%�⸪�<�^܄���R��� 4�����)۞�nKo�$B:�����6��_�&D_���?��B�*�Ci���+td� ,�L�*q��V�r�ឰ�8�S���P� p�P�����j2���lϐ7Z<����x�T: ���0��,��m��p�G +��{���>�:qa&DWz]=����p����r���,�l��K ��S��M���'�`���k뒸�|c�k�h�=�%��y�%�*�6�����{�,�R0ޱD���!gK�'��7��d�h%�������j?V;���GEA��㉨����;Q�Hl,~_�6ĝJ��3�,��bw}�Ρ������x�}���e.C�"�6ŵ}� �i��A�r3ȹ�==�գ� h�ۡ~1�I��R���+)}���My?#�S҇7}D��Gpj�c�jڅ.�P�1�8��$ԉD�\ˀ�`��؝ ~��s� kݧ��PP�����U����Yv��}Ů�����o�_Z�D�i�&`��|����� ��n*�ui����na��5^��pn]zu�N ���㧢CbXQ��� �� ;�)�%;SYP2���Y�Z�E�a��j�+�Ă���5C��#��Ρ���&P>H�;�B�Ù�>-����=�W���}!^c��s�2:�2'F���i,�a��; �\�a�cM# �G B̷ D, ��w��K�g/F�O4�C}�G_�H�R�a�G�� [(�U����}��R|�$�s:p��[/���B�ښ�E�� +��=Y�C `���ScЊQ`�ĔU��ɮn=eHe�.���#�g�>m@J���D�u81�`���������d�0�T?|İ�*"߷h��\�w{��fʽ^��H��o���b��v�b�l��6�{�}����:o6�G��Ǎ���{I�%w]�9c�Euh?ۢF�NAĴ��#v�?�G�'�d +��ա1y�/+���p�1��O�J  �߻�w������ɮ_Ĵg_0���?kJ�E�������+c�P`#4����?�d�/���Zhi�7��)�k8��'�7-�H%��q`_�b@���␔j���;[��= ���?;�pI�\o��U�#"�5-j�l�&A��|Q��K c���|o��a~�H;\ۂ�2�T�?! ��T�%�gP�V���;�F qjO���� �`:8I~�z����"ê�p�/K ��"!�a�*�;�(��R�c�������6�������� i���#�P���~�(�v[ �4d�S��F$OYj�.$͏�r�85H��w*��`o}�(M鸋�o���$i�w��z������,ޱ��v�sׇ�-K� ـ� +.%T�%�xi �R�I�m���bw�5H�2�R�����n�4Tll�ܣ�͐��h\Xt.�ᬒ���v&��Ҿ�ƺ���co`�T�RZ$��O�E�2}��t$V�HK�$��(ľ��r�E�/��7N�F�؆4�;l��1��}�E*8ѫ:��]�;2PҤ�n�H|/���{)^�J�J�f�hM#�B���z� ��J��ӷ��O��||c*5�Y�n��o6wmfӱ��98=&Fף�`{��MM\��=.�H�)���?J���Rԡ�M�;� �^�=VbS� �oz�$�,ۧ�Ѡ������8ܸ +�).(K�]1G'%�щ� +��(Q�2������3���{�VŔ�ő�]�6�g����Ҳ���Y-�2,�"F|���T�6O�K=�I����[*C9�.��qCC\��Uҁ菶nZlI��ٹ�ꄱ���l)�����i���d8��k0˚(��5 ������3v�� +��H2ݎ��d�a�F���؊*���؏�w��u+J��"�o�c�_ +�. �|hcwh��IX�E��.-� �ǀg���؉K��g�����f�Wri�GCe�B�p$�����sၨm +Ǡq�PSV�I0'23,kE�{��H���#��ݖ��iP������!��Z�RsAf��t�Y�GV-�J��-�~ +�h�����<�����*m>a���͍��D�|��6se���4S|��1AY�!@��_\�HƔCs�zL��$�D|yH�̖��y�/�U�I)�aqw��K����%�6�<��ч�LZ�3�����X5�!�9�"v�ta�+��<��Xt�X 9���t4~r`c���� ����n��Z��X�l�T�c��˯b_�� ��Ҫ$�� Y�X�*��Km2 +�.�t��P�s���~�=/Kh紳���^�Ae��lv��*�C\��U +�p��{� +G&愦nި<r�w8d�a�Y<�-��L�0�j�� g��/ƣq��!��2����o|>�q��V���ܻ�K���E��7 �nN��ʘ�F/e'J���#�9�8�Za���>G���ej�ˡ9:�#lk8�:Z�6�h2(����(���\j����!Q�̴.�Cs^;a`=������/B�si!���T��2�cG���-��%o����� +�j�-H�ju�&�%ɳ�%��Z��5��5�6=4W�!�1gX.����R&�s �~�뻶�� +N�8�C�iLsJ�*)�A �[g�r���D慵��7��i�Ao��#��ˊ&'Mh�K���!'�K�ӭ�۱ֹ�RS�UA�¬ +���u��!���pl�=�ß�:|����I��2��t�V߽�,ܣ��i �K 솒�n1-���-��l� ����[;3;�4hvkM_ץA���l� �)�0�F�o�|X��z!K�FS�� �AB@��nI�������1ˇ�=�;�I�1�F!K�Y�~��󆉺R�� + k�~r�g�p�kOB��,�%�����D�7ά�}ݝ�<��l�9� +�ڬH�����+&eŁn*~W�g-TG�` "wP[*XӅF�&�;� i[���t( HΑ�W���7s�ܢ��N ��ž���Y�Y��^� ~�bNW�U�c6���L�O�h�l�XA�|{���p��3�AE�&�������||��"�TnՎ��3�$$�aF`�v�!aς���F�0�eLS V�R��Ǡ�(���������v�����Ѧ�LƦ��.�T�\�,����� y�%ܥMhЇ<����-Ƨ5 �e�]��>�Di+�t�l�>�Nl��`�/-��Ʈ�{�M��X�$�2�x+���.��d~׽�m5y����Q�0|�3�8��d�� X�n*�����{^ѧ=*>��2��=��(R�W���CA�ͪ-so�9�� Gx��� +��c��t ��ДB~��<��dtz��K�[{��<������x��+����j�A����~�B�#c��<[ ���,P@i��-a_-�#y{�s�lv 6g����̂w�o�x# :�#,���@��"ii�#����e57��58P�Z�P�#n�R�/. �ۃ}uE�����IW^s�� �|o��^�<ɇ���%�UK��I$֚;j��,��f��N�5θD�LFH�{і{hչ(�`��i���c��~e �,+������˔w:a�f���l�1�?���]"��|-��f���r����f��99�_��X(af�����ڭ"���\��Ѩ��:YV�pi�`Kbçf&l��"�8 � ئ�N(����t0���ո_FR�����!� �1��{�XU~\8 š�9�a �b�!g7�~IJ�~Դ"�v�֐��K�I>y ��'�rQ٦�Ш�C��T\�;��#��},�d����D�W�ʰ�t��mޭN���̋���i�魚���TYH$��H�1 3`O�k�EC�&Ȳ���V���g����0�@��I�O��I��4� +���mםZiX޻Bf �[B�SLP���xl[�� +��O����߭�ى(�•��u!����^�H{��R"���.m�y�Zx�sri�֪vǗ yu��wX�>��_�����(t�]9��AVrr��ξ���틦Bc\��0����N� +� c��vSد.������-f�it�'] ��-H�!*����n���i��+�P�گ���n� ��=8M���7hP˽�o1�)�e_W�@.�>�Sz�P��+�Lb�c.�bz �rAbb����r�C� ����b�m�r ]�d�sTQ��Bx��Gw�KG��c@�G����S����c�����bX�# q�K���i�ok>,���O�DMO���P^�� �7�8���ĕ�ۻ�ѹ{�pW'�ب�q�l&�:6L��eƗ��Gb}���_�w��Òr}):�֠�� U@�y�1Xg�����|쥾Auk��Cm��Koi��?��?��|������_~��ǟ�y����p~��Ͽԟ��������t�?Ia\�ۓ�O��g�>�����>����O������/�������x�������ϯ_�?��W����~�����@w�}���~w�����7���/�����������?������������o�㙿���w�}`��[�-I^� �����G"��+��_AkR̴4�� �Z� x +�LԒ�?:�Z@�%�P ��<Q�d|�˚x���j@ذ�`��_��N\å�l"MO���UU���o>��*M�%{~�6�ٚ3L�1S��ަ��\��,�c�ȹ,ƛ*f* ]p�[�~,n͜��oi�*䆱�R���!�'� ��{G|]'w_��-,��hX��R5z"QI@qh�������Yѿ�|�-Z�j�7ͺ��d�� ރK�O9X.:`��N�\����6Ͱ��>����D���0�g/-��nߪd����KvX1��[c����'�Qo\�ZIGQ 3C��'RE�*�((���!���{���/m|�N�uf��߽��n�U1A(�Bz�Lؿv,��MU�`�bY�Y,��|F���xz�o���e�Ř���d�(��|2�¥����5 |ۇ�XU�oQ� Lc�)��E���yG��t��,�T?I{��u���U52 GL�r�c1 u)W��2�Nf2�b�<%��;�� ��_�!��%����i�B�� 1Br���+��K�B\;a�K �WGx����V8?r�j(���6�����G��ہ�\�T�2J� +K|��A0j?Iu��E�b)���2�o��?�� O�h���6�m ���@��D��?d�8�ST^��'�n�B����s~��JX���?0'R�^�tʐ�{�9�����#��3w�77�����6���#����}���W��������'_��{����?�l�W�8��_��g�r�����//��'�A��o>�y�ɗ_�5�����6{���^�������Eo�����ͯ>�����1� +endstream endobj 88 0 obj <> endobj xref +0 89 +0000000004 65535 f +0000000016 00000 n +0000000076 00000 n +0000052465 00000 n +0000000005 00000 f +0000000007 00000 f +0000052516 00000 n +0000000008 00000 f +0000000009 00000 f +0000000010 00000 f +0000000011 00000 f +0000000012 00000 f +0000000013 00000 f +0000000014 00000 f +0000000015 00000 f +0000000016 00000 f +0000000017 00000 f +0000000018 00000 f +0000000019 00000 f +0000000020 00000 f +0000000021 00000 f +0000000022 00000 f +0000000023 00000 f +0000000024 00000 f +0000000025 00000 f +0000000026 00000 f +0000000027 00000 f +0000000028 00000 f +0000000029 00000 f +0000000030 00000 f +0000000031 00000 f +0000000032 00000 f +0000000033 00000 f +0000000034 00000 f +0000000035 00000 f +0000000036 00000 f +0000000037 00000 f +0000000038 00000 f +0000000039 00000 f +0000000040 00000 f +0000000041 00000 f +0000000042 00000 f +0000000043 00000 f +0000000044 00000 f +0000000045 00000 f +0000000046 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000055194 00000 n +0000052838 00000 n +0000053036 00000 n +0000059486 00000 n +0000054116 00000 n +0000053101 00000 n +0000053554 00000 n +0000053602 00000 n +0000059373 00000 n +0000055709 00000 n +0000055793 00000 n +0000056175 00000 n +0000059554 00000 n +0000059816 00000 n +0000060846 00000 n +0000081689 00000 n +0000147278 00000 n +0000212867 00000 n +0000278456 00000 n +0000344045 00000 n +0000351801 00000 n +trailer +<<28DFC798E413B2439FF20528DA0B2896>]>> +startxref +351975 +%%EOF diff --git a/images/compiler-ldc.png b/images/compiler-ldc.png new file mode 100644 index 0000000000..ebfeca82c6 Binary files /dev/null and b/images/compiler-ldc.png differ diff --git a/images/compiler-ldc_hq.png b/images/compiler-ldc_hq.png new file mode 100644 index 0000000000..a8fc70484a Binary files /dev/null and b/images/compiler-ldc_hq.png differ diff --git a/images/d3.gif b/images/d3.gif deleted file mode 100644 index e13d9ababe..0000000000 Binary files a/images/d3.gif and /dev/null differ diff --git a/images/d3.png b/images/d3.png new file mode 100644 index 0000000000..55d790b500 Binary files /dev/null and b/images/d3.png differ diff --git a/images/d3_hq.png b/images/d3_hq.png new file mode 100644 index 0000000000..ba701c6897 Binary files /dev/null and b/images/d3_hq.png differ diff --git a/images/ddox/alias.png b/images/ddox/alias.png new file mode 100644 index 0000000000..d707303b15 Binary files /dev/null and b/images/ddox/alias.png differ diff --git a/images/ddox/class.png b/images/ddox/class.png new file mode 100644 index 0000000000..d57bd1a243 Binary files /dev/null and b/images/ddox/class.png differ diff --git a/images/ddox/enum.png b/images/ddox/enum.png new file mode 100644 index 0000000000..159c03438a Binary files /dev/null and b/images/ddox/enum.png differ diff --git a/images/ddox/enummember.png b/images/ddox/enummember.png new file mode 100644 index 0000000000..5dd6254dca Binary files /dev/null and b/images/ddox/enummember.png differ diff --git a/images/ddox/function.png b/images/ddox/function.png new file mode 100644 index 0000000000..a119b20ee5 Binary files /dev/null and b/images/ddox/function.png differ diff --git a/images/ddox/inherited.png b/images/ddox/inherited.png new file mode 100644 index 0000000000..5d69b601a2 Binary files /dev/null and b/images/ddox/inherited.png differ diff --git a/images/ddox/interface.png b/images/ddox/interface.png new file mode 100644 index 0000000000..0f47de3210 Binary files /dev/null and b/images/ddox/interface.png differ diff --git a/images/ddox/module.png b/images/ddox/module.png new file mode 100644 index 0000000000..3f2927be1a Binary files /dev/null and b/images/ddox/module.png differ diff --git a/images/ddox/package.png b/images/ddox/package.png new file mode 100644 index 0000000000..c1f35b5d81 Binary files /dev/null and b/images/ddox/package.png differ diff --git a/images/ddox/private.png b/images/ddox/private.png new file mode 100644 index 0000000000..e26710ffdc Binary files /dev/null and b/images/ddox/private.png differ diff --git a/images/ddox/property.png b/images/ddox/property.png new file mode 100644 index 0000000000..f08ea74bba Binary files /dev/null and b/images/ddox/property.png differ diff --git a/images/ddox/protected.png b/images/ddox/protected.png new file mode 100644 index 0000000000..e88da6a983 Binary files /dev/null and b/images/ddox/protected.png differ diff --git a/images/ddox/struct.png b/images/ddox/struct.png new file mode 100644 index 0000000000..1cc411d053 Binary files /dev/null and b/images/ddox/struct.png differ diff --git a/images/ddox/template.png b/images/ddox/template.png new file mode 100644 index 0000000000..c45de38d37 Binary files /dev/null and b/images/ddox/template.png differ diff --git a/images/ddox/variable.png b/images/ddox/variable.png new file mode 100644 index 0000000000..ef28375161 Binary files /dev/null and b/images/ddox/variable.png differ diff --git a/images/debian_logo.png b/images/debian_logo.png index b7e7d4e5ec..ea733905e4 100644 Binary files a/images/debian_logo.png and b/images/debian_logo.png differ diff --git a/images/declaration.dot b/images/declaration.dot new file mode 100644 index 0000000000..17321c29d4 --- /dev/null +++ b/images/declaration.dot @@ -0,0 +1,16 @@ +/* +Source file for declaration.svg and declaration.eps. The +commands to run (assuming graphviz is installed) are: + +cd /path/to/dlang.org/images +dot -Tsvg declaration.dot >declaration.svg +dot -Teps declaration.dot >declaration.eps + +These commands are not part of the makefile because the files are fairly stable +and so as to not make the build depending on graphviz being installed. +*/ + +digraph "Declaration" { + rankdir="LR"; + "Declaration" -> {"VarDeclarations", "FuncDeclaration", "AggregateDeclaration"}; +} diff --git a/images/declaration.eps b/images/declaration.eps new file mode 100644 index 0000000000..95b34883be --- /dev/null +++ b/images/declaration.eps @@ -0,0 +1,293 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: graphviz version 2.43.0 (0) +%%Title: Declaration +%%Pages: 1 +%%BoundingBox: 36 36 434 188 +%%EndComments +save +%%BeginProlog +/DotDict 200 dict def +DotDict begin + +/setupLatin1 { +mark +/EncodingVector 256 array def + EncodingVector 0 + +ISOLatin1Encoding 0 255 getinterval putinterval +EncodingVector 45 /hyphen put + +% Set up ISO Latin 1 character encoding +/starnetISO { + dup dup findfont dup length dict begin + { 1 index /FID ne { def }{ pop pop } ifelse + } forall + /Encoding EncodingVector def + currentdict end definefont +} def +/Times-Roman starnetISO def +/Times-Italic starnetISO def +/Times-Bold starnetISO def +/Times-BoldItalic starnetISO def +/Helvetica starnetISO def +/Helvetica-Oblique starnetISO def +/Helvetica-Bold starnetISO def +/Helvetica-BoldOblique starnetISO def +/Courier starnetISO def +/Courier-Oblique starnetISO def +/Courier-Bold starnetISO def +/Courier-BoldOblique starnetISO def +cleartomark +} bind def + +%%BeginResource: procset graphviz 0 0 +/coord-font-family /Times-Roman def +/default-font-family /Times-Roman def +/coordfont coord-font-family findfont 8 scalefont def + +/InvScaleFactor 1.0 def +/set_scale { + dup 1 exch div /InvScaleFactor exch def + scale +} bind def + +% styles +/solid { [] 0 setdash } bind def +/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def +/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def +/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def +/bold { 2 setlinewidth } bind def +/filled { } bind def +/unfilled { } bind def +/rounded { } bind def +/diagonals { } bind def +/tapered { } bind def + +% hooks for setting color +/nodecolor { sethsbcolor } bind def +/edgecolor { sethsbcolor } bind def +/graphcolor { sethsbcolor } bind def +/nopcolor {pop pop pop} bind def + +/beginpage { % i j npages + /npages exch def + /j exch def + /i exch def + /str 10 string def + npages 1 gt { + gsave + coordfont setfont + 0 0 moveto + (\() show i str cvs show (,) show j str cvs show (\)) show + grestore + } if +} bind def + +/set_font { + findfont exch + scalefont setfont +} def + +% draw text fitted to its expected width +/alignedtext { % width text + /text exch def + /width exch def + gsave + width 0 gt { + [] 0 setdash + text stringwidth pop width exch sub text length div 0 text ashow + } if + grestore +} def + +/boxprim { % xcorner ycorner xsize ysize + 4 2 roll + moveto + 2 copy + exch 0 rlineto + 0 exch rlineto + pop neg 0 rlineto + closepath +} bind def + +/ellipse_path { + /ry exch def + /rx exch def + /y exch def + /x exch def + matrix currentmatrix + newpath + x y translate + rx ry scale + 0 0 1 0 360 arc + setmatrix +} bind def + +/endpage { showpage } bind def +/showpage { } def + +/layercolorseq + [ % layer color sequence - darkest to lightest + [0 0 0] + [.2 .8 .8] + [.4 .8 .8] + [.6 .8 .8] + [.8 .8 .8] + ] +def + +/layerlen layercolorseq length def + +/setlayer {/maxlayer exch def /curlayer exch def + layercolorseq curlayer 1 sub layerlen mod get + aload pop sethsbcolor + /nodecolor {nopcolor} def + /edgecolor {nopcolor} def + /graphcolor {nopcolor} def +} bind def + +/onlayer { curlayer ne {invis} if } def + +/onlayers { + /myupper exch def + /mylower exch def + curlayer mylower lt + curlayer myupper gt + or + {invis} if +} def + +/curlayer 0 def + +%%EndResource +%%EndProlog +%%BeginSetup +14 default-font-family set_font +% /arrowlength 10 def +% /arrowwidth 5 def + +% make sure pdfmark is harmless for PS-interpreters other than Distiller +/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse +% make '<<' and '>>' safe on PS Level 1 devices +/languagelevel where {pop languagelevel}{1} ifelse +2 lt { + userdict (<<) cvn ([) cvn load put + userdict (>>) cvn ([) cvn load put +} if + +%%EndSetup +setupLatin1 +%%Page: 1 1 +%%PageBoundingBox: 36 36 434 188 +%%PageOrientation: Portrait +0 0 1 beginpage +gsave +36 36 398 152 boxprim clip newpath +1 1 set_scale 0 rotate 40 40 translate +% Declaration +gsave +1 setlinewidth +0 0 0 nodecolor +64.3443 72 64.189 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +22.8443 68.3 moveto 83 (Declaration) alignedtext +grestore +% VarDeclarations +gsave +1 setlinewidth +0 0 0 nodecolor +277.1286 126 85.2851 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +219.6286 122.3 moveto 115 (VarDeclarations) alignedtext +grestore +% Declaration->VarDeclarations +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 110.7741 84.6307 moveto +127.6742 89.2546 147.0319 94.4626 164.6886 99 curveto +179.1791 102.7238 194.7663 106.5882 209.5572 110.1897 curveto +stroke +0 0 0 edgecolor +newpath 209.1035 113.6811 moveto +219.6467 112.6362 lineto +210.7531 106.8782 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 209.1035 113.6811 moveto +219.6467 112.6362 lineto +210.7531 106.8782 lineto +closepath stroke +grestore +% FuncDeclaration +gsave +1 setlinewidth +0 0 0 nodecolor +277.1286 72 87.1846 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +218.1286 68.3 moveto 118 (FuncDeclaration) alignedtext +grestore +% Declaration->FuncDeclaration +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 128.8724 72 moveto +144.8827 72 162.4321 72 179.6612 72 curveto +stroke +0 0 0 edgecolor +newpath 179.7543 75.5001 moveto +189.7543 72 lineto +179.7543 68.5001 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 179.7543 75.5001 moveto +189.7543 72 lineto +179.7543 68.5001 lineto +closepath stroke +grestore +% AggregateDeclaration +gsave +1 setlinewidth +0 0 0 nodecolor +277.1286 18 112.3801 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +198.6286 14.3 moveto 157 (AggregateDeclaration) alignedtext +grestore +% Declaration->AggregateDeclaration +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 110.7741 59.3693 moveto +127.6742 54.7454 147.0319 49.5374 164.6886 45 curveto +177.2104 41.7821 190.5511 38.4593 203.4893 35.2918 curveto +stroke +0 0 0 edgecolor +newpath 204.3979 38.6728 moveto +213.2845 32.9041 lineto +202.7401 31.872 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 204.3979 38.6728 moveto +213.2845 32.9041 lineto +202.7401 31.872 lineto +closepath stroke +grestore +endpage +showpage +grestore +%%PageTrailer +%%EndPage: 1 +%%Trailer +end +restore +%%EOF diff --git a/images/declaration.svg b/images/declaration.svg new file mode 100644 index 0000000000..59c8908e46 --- /dev/null +++ b/images/declaration.svg @@ -0,0 +1,55 @@ + + + + + + +Declaration + + + +Declaration + +Declaration + + + +VarDeclarations + +VarDeclarations + + + +Declaration->VarDeclarations + + + + + +FuncDeclaration + +FuncDeclaration + + + +Declaration->FuncDeclaration + + + + + +AggregateDeclaration + +AggregateDeclaration + + + +Declaration->AggregateDeclaration + + + + + diff --git a/images/dlogo.png b/images/dlogo.png index d2cefd79ce..c4e4a53034 100644 Binary files a/images/dlogo.png and b/images/dlogo.png differ diff --git a/images/dlogo.svg b/images/dlogo.svg new file mode 100644 index 0000000000..4fb6f49201 --- /dev/null +++ b/images/dlogo.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/dlogo_2015.svg b/images/dlogo_2015.svg new file mode 100644 index 0000000000..f2492bc3f7 --- /dev/null +++ b/images/dlogo_2015.svg @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/images/dlogo_opengraph.png b/images/dlogo_opengraph.png new file mode 100644 index 0000000000..6a78666241 Binary files /dev/null and b/images/dlogo_opengraph.png differ diff --git a/images/dlogo_opengraph_hq.png b/images/dlogo_opengraph_hq.png new file mode 100644 index 0000000000..ea1aa36681 Binary files /dev/null and b/images/dlogo_opengraph_hq.png differ diff --git a/images/dman-error.jpg b/images/dman-error.jpg new file mode 100644 index 0000000000..efb4db45df Binary files /dev/null and b/images/dman-error.jpg differ diff --git a/images/dman-error_hq.jpg b/images/dman-error_hq.jpg new file mode 100644 index 0000000000..3515765bd2 Binary files /dev/null and b/images/dman-error_hq.jpg differ diff --git a/images/dman-rain.jpg b/images/dman-rain.jpg new file mode 100644 index 0000000000..78ec8c5fdb Binary files /dev/null and b/images/dman-rain.jpg differ diff --git a/images/dman-rain_hq.jpg b/images/dman-rain_hq.jpg new file mode 100644 index 0000000000..93fa269a92 Binary files /dev/null and b/images/dman-rain_hq.jpg differ diff --git a/images/dman-scared.jpg b/images/dman-scared.jpg new file mode 100644 index 0000000000..a949c25562 Binary files /dev/null and b/images/dman-scared.jpg differ diff --git a/images/dman-time.jpg b/images/dman-time.jpg new file mode 100644 index 0000000000..c8023b823e Binary files /dev/null and b/images/dman-time.jpg differ diff --git a/images/dman-time_hq.jpg b/images/dman-time_hq.jpg new file mode 100644 index 0000000000..5d640c95a7 Binary files /dev/null and b/images/dman-time_hq.jpg differ diff --git a/images/docker_logo.png b/images/docker_logo.png new file mode 100644 index 0000000000..84341eae9f Binary files /dev/null and b/images/docker_logo.png differ diff --git a/images/download.png b/images/download.png deleted file mode 100644 index 855d1b61d3..0000000000 Binary files a/images/download.png and /dev/null differ diff --git a/images/expression.dot b/images/expression.dot new file mode 100644 index 0000000000..c25a2b8b76 --- /dev/null +++ b/images/expression.dot @@ -0,0 +1,17 @@ +/* +Source file for expression.svg and expression.eps. The +commands to run (assuming graphviz is installed) are: + +cd /path/to/dlang.org/images +dot -Tsvg expression.dot >expression.svg +dot -Teps expression.dot >expression.eps + +These commands are not part of the makefile because the files are fairly stable +and so as to not make the build depending on graphviz being installed. +*/ + +digraph "Expression" { + rankdir="LR"; + "Expression" -> {"PrimaryExpression", "AssignExpression", "PostfixExpression"} + "PrimaryExpression" -> {"Identifier", "LiteralExpression"}; +} diff --git a/images/expression.eps b/images/expression.eps new file mode 100644 index 0000000000..8163826cb7 --- /dev/null +++ b/images/expression.eps @@ -0,0 +1,351 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: graphviz version 2.43.0 (0) +%%Title: Expression +%%Pages: 1 +%%BoundingBox: 36 36 627 215 +%%EndComments +save +%%BeginProlog +/DotDict 200 dict def +DotDict begin + +/setupLatin1 { +mark +/EncodingVector 256 array def + EncodingVector 0 + +ISOLatin1Encoding 0 255 getinterval putinterval +EncodingVector 45 /hyphen put + +% Set up ISO Latin 1 character encoding +/starnetISO { + dup dup findfont dup length dict begin + { 1 index /FID ne { def }{ pop pop } ifelse + } forall + /Encoding EncodingVector def + currentdict end definefont +} def +/Times-Roman starnetISO def +/Times-Italic starnetISO def +/Times-Bold starnetISO def +/Times-BoldItalic starnetISO def +/Helvetica starnetISO def +/Helvetica-Oblique starnetISO def +/Helvetica-Bold starnetISO def +/Helvetica-BoldOblique starnetISO def +/Courier starnetISO def +/Courier-Oblique starnetISO def +/Courier-Bold starnetISO def +/Courier-BoldOblique starnetISO def +cleartomark +} bind def + +%%BeginResource: procset graphviz 0 0 +/coord-font-family /Times-Roman def +/default-font-family /Times-Roman def +/coordfont coord-font-family findfont 8 scalefont def + +/InvScaleFactor 1.0 def +/set_scale { + dup 1 exch div /InvScaleFactor exch def + scale +} bind def + +% styles +/solid { [] 0 setdash } bind def +/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def +/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def +/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def +/bold { 2 setlinewidth } bind def +/filled { } bind def +/unfilled { } bind def +/rounded { } bind def +/diagonals { } bind def +/tapered { } bind def + +% hooks for setting color +/nodecolor { sethsbcolor } bind def +/edgecolor { sethsbcolor } bind def +/graphcolor { sethsbcolor } bind def +/nopcolor {pop pop pop} bind def + +/beginpage { % i j npages + /npages exch def + /j exch def + /i exch def + /str 10 string def + npages 1 gt { + gsave + coordfont setfont + 0 0 moveto + (\() show i str cvs show (,) show j str cvs show (\)) show + grestore + } if +} bind def + +/set_font { + findfont exch + scalefont setfont +} def + +% draw text fitted to its expected width +/alignedtext { % width text + /text exch def + /width exch def + gsave + width 0 gt { + [] 0 setdash + text stringwidth pop width exch sub text length div 0 text ashow + } if + grestore +} def + +/boxprim { % xcorner ycorner xsize ysize + 4 2 roll + moveto + 2 copy + exch 0 rlineto + 0 exch rlineto + pop neg 0 rlineto + closepath +} bind def + +/ellipse_path { + /ry exch def + /rx exch def + /y exch def + /x exch def + matrix currentmatrix + newpath + x y translate + rx ry scale + 0 0 1 0 360 arc + setmatrix +} bind def + +/endpage { showpage } bind def +/showpage { } def + +/layercolorseq + [ % layer color sequence - darkest to lightest + [0 0 0] + [.2 .8 .8] + [.4 .8 .8] + [.6 .8 .8] + [.8 .8 .8] + ] +def + +/layerlen layercolorseq length def + +/setlayer {/maxlayer exch def /curlayer exch def + layercolorseq curlayer 1 sub layerlen mod get + aload pop sethsbcolor + /nodecolor {nopcolor} def + /edgecolor {nopcolor} def + /graphcolor {nopcolor} def +} bind def + +/onlayer { curlayer ne {invis} if } def + +/onlayers { + /myupper exch def + /mylower exch def + curlayer mylower lt + curlayer myupper gt + or + {invis} if +} def + +/curlayer 0 def + +%%EndResource +%%EndProlog +%%BeginSetup +14 default-font-family set_font +% /arrowlength 10 def +% /arrowwidth 5 def + +% make sure pdfmark is harmless for PS-interpreters other than Distiller +/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse +% make '<<' and '>>' safe on PS Level 1 devices +/languagelevel where {pop languagelevel}{1} ifelse +2 lt { + userdict (<<) cvn ([) cvn load put + userdict (>>) cvn ([) cvn load put +} if + +%%EndSetup +setupLatin1 +%%Page: 1 1 +%%PageBoundingBox: 36 36 627 215 +%%PageOrientation: Portrait +0 0 1 beginpage +gsave +36 36 591 179 boxprim clip newpath +1 1 set_scale 0 rotate 40 40 translate +% Expression +gsave +1 setlinewidth +0 0 0 nodecolor +62.3945 72 62.2891 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +22.3945 68.3 moveto 80 (Expression) alignedtext +grestore +% PrimaryExpression +gsave +1 setlinewidth +0 0 0 nodecolor +260.88 126 100.1823 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +191.88 122.3 moveto 138 (PrimaryExpression) alignedtext +grestore +% Expression->PrimaryExpression +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 107.9898 84.4074 moveto +124.5645 89.007 143.5315 94.2568 160.7889 99 curveto +171.826 102.0335 183.5587 105.2435 194.9442 108.3506 curveto +stroke +0 0 0 edgecolor +newpath 194.2655 111.7933 moveto +204.834 111.0476 lineto +196.1072 105.0399 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 194.2655 111.7933 moveto +204.834 111.0476 lineto +196.1072 105.0399 lineto +closepath stroke +grestore +% AssignExpression +gsave +1 setlinewidth +0 0 0 nodecolor +260.88 72 92.8835 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +197.38 68.3 moveto 127 (AssignExpression) alignedtext +grestore +% Expression->AssignExpression +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 125.0246 72 moveto +135.4508 72 146.519 72 157.6556 72 curveto +stroke +0 0 0 edgecolor +newpath 157.8858 75.5001 moveto +167.8857 72 lineto +157.8857 68.5001 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 157.8858 75.5001 moveto +167.8857 72 lineto +157.8857 68.5001 lineto +closepath stroke +grestore +% PostfixExpression +gsave +1 setlinewidth +0 0 0 nodecolor +260.88 18 93.6835 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +196.88 14.3 moveto 128 (PostfixExpression) alignedtext +grestore +% Expression->PostfixExpression +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 107.9898 59.5926 moveto +124.5645 54.993 143.5315 49.7432 160.7889 45 curveto +172.2733 41.8435 184.5108 38.4961 196.3266 35.2722 curveto +stroke +0 0 0 edgecolor +newpath 197.3999 38.6074 moveto +206.127 32.6001 lineto +195.5584 31.8539 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 197.3999 38.6074 moveto +206.127 32.6001 lineto +195.5584 31.8539 lineto +closepath stroke +grestore +% Identifier +gsave +1 setlinewidth +0 0 0 nodecolor +489.9129 153 53.8905 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +456.4129 149.3 moveto 67 (Identifier) alignedtext +grestore +% PrimaryExpression->Identifier +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 344.8078 135.8622 moveto +372.6525 139.1737 403.1505 142.8007 428.891 145.8619 curveto +stroke +0 0 0 edgecolor +newpath 428.5294 149.3434 moveto +438.8728 147.049 lineto +429.3561 142.3924 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 428.5294 149.3434 moveto +438.8728 147.049 lineto +429.3561 142.3924 lineto +closepath stroke +grestore +% LiteralExpression +gsave +1 setlinewidth +0 0 0 nodecolor +489.9129 99 92.8835 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +426.4129 95.3 moveto 127 (LiteralExpression) alignedtext +grestore +% PrimaryExpression->LiteralExpression +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 344.8078 116.1378 moveto +362.8702 113.9897 382.0491 111.7088 400.3216 109.5358 curveto +stroke +0 0 0 edgecolor +newpath 400.8502 112.9977 moveto +410.3669 108.3411 lineto +400.0235 106.0466 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 400.8502 112.9977 moveto +410.3669 108.3411 lineto +400.0235 106.0466 lineto +closepath stroke +grestore +endpage +showpage +grestore +%%PageTrailer +%%EndPage: 1 +%%Trailer +end +restore +%%EOF diff --git a/images/expression.svg b/images/expression.svg new file mode 100644 index 0000000000..647cc712e3 --- /dev/null +++ b/images/expression.svg @@ -0,0 +1,79 @@ + + + + + + +Expression + + + +Expression + +Expression + + + +PrimaryExpression + +PrimaryExpression + + + +Expression->PrimaryExpression + + + + + +AssignExpression + +AssignExpression + + + +Expression->AssignExpression + + + + + +PostfixExpression + +PostfixExpression + + + +Expression->PostfixExpression + + + + + +Identifier + +Identifier + + + +PrimaryExpression->Identifier + + + + + +LiteralExpression + +LiteralExpression + + + +PrimaryExpression->LiteralExpression + + + + + diff --git a/images/faster-aa-1.svg b/images/faster-aa-1.svg new file mode 100644 index 0000000000..700d61b3e2 --- /dev/null +++ b/images/faster-aa-1.svg @@ -0,0 +1 @@ +AA Benchmark Comparison (Linux/64, Core i5-2400S)old_aanew_aaresizeintstringbulkptrobj0.00.20.40.60.81.01.2relative time diff --git a/images/faster-gc-1.svg b/images/faster-gc-1.svg new file mode 100644 index 0000000000..7be0bc8832 --- /dev/null +++ b/images/faster-gc-1.svg @@ -0,0 +1 @@ +GC Benchmark Comparison (Linux/64, Core i5-2400S)2.066.12.067.0tree1tree2vdparsertestgc3wordsrand_largedlistrand_smallslist01234time / s diff --git a/images/fedora_logo.png b/images/fedora_logo.png index 314e6b8f3a..8e8f4f518e 100644 Binary files a/images/fedora_logo.png and b/images/fedora_logo.png differ diff --git a/images/freebsd_logo.png b/images/freebsd_logo.png index 65e4cfb836..dd0493d362 100644 Binary files a/images/freebsd_logo.png and b/images/freebsd_logo.png differ diff --git a/images/gentoo_logo.png b/images/gentoo_logo.png new file mode 100644 index 0000000000..27328de407 Binary files /dev/null and b/images/gentoo_logo.png differ diff --git a/images/github-ribbon.png b/images/github-ribbon.png new file mode 100644 index 0000000000..b9e117db26 Binary files /dev/null and b/images/github-ribbon.png differ diff --git a/images/gradient-green.jpg b/images/gradient-green.jpg deleted file mode 100644 index 67eca9dbdb..0000000000 Binary files a/images/gradient-green.jpg and /dev/null differ diff --git a/images/gradient-red.jpg b/images/gradient-red.jpg deleted file mode 100644 index 32b3b8c8b4..0000000000 Binary files a/images/gradient-red.jpg and /dev/null differ diff --git a/images/hamburger.svg b/images/hamburger.svg new file mode 100644 index 0000000000..b4f1233ac2 --- /dev/null +++ b/images/hamburger.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/images/homebrew_logo.png b/images/homebrew_logo.png new file mode 100644 index 0000000000..cab648e258 Binary files /dev/null and b/images/homebrew_logo.png differ diff --git a/images/icon_minus.svg b/images/icon_minus.svg new file mode 100644 index 0000000000..d9362c1672 --- /dev/null +++ b/images/icon_minus.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + diff --git a/images/icon_plus.svg b/images/icon_plus.svg new file mode 100644 index 0000000000..77ac54c121 --- /dev/null +++ b/images/icon_plus.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + diff --git a/images/linux_logo.png b/images/linux_logo.png deleted file mode 100644 index 49f3e0a721..0000000000 Binary files a/images/linux_logo.png and /dev/null differ diff --git a/images/lsp-served-logo.png b/images/lsp-served-logo.png new file mode 100644 index 0000000000..e92a9a6995 Binary files /dev/null and b/images/lsp-served-logo.png differ diff --git a/images/mac_logo.png b/images/mac_logo.png deleted file mode 100755 index 549eb638ca..0000000000 Binary files a/images/mac_logo.png and /dev/null differ diff --git a/images/nix_logo.png b/images/nix_logo.png new file mode 100644 index 0000000000..6ab219d946 Binary files /dev/null and b/images/nix_logo.png differ diff --git a/images/openbsd_logo.png b/images/openbsd_logo.png new file mode 100644 index 0000000000..75c34dbdf5 Binary files /dev/null and b/images/openbsd_logo.png differ diff --git a/images/opensuse_logo.png b/images/opensuse_logo.png index 932269b0e2..2c3e00bfbf 100644 Binary files a/images/opensuse_logo.png and b/images/opensuse_logo.png differ diff --git a/images/orgs-using-d/ahrefs.svg b/images/orgs-using-d/ahrefs.svg new file mode 100644 index 0000000000..fbdb4281bf --- /dev/null +++ b/images/orgs-using-d/ahrefs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/orgs-using-d/arabiaweather.png b/images/orgs-using-d/arabiaweather.png new file mode 100644 index 0000000000..5e8eed7c06 Binary files /dev/null and b/images/orgs-using-d/arabiaweather.png differ diff --git a/images/orgs-using-d/arabiaweather_hq.png b/images/orgs-using-d/arabiaweather_hq.png new file mode 100644 index 0000000000..3fc22af111 Binary files /dev/null and b/images/orgs-using-d/arabiaweather_hq.png differ diff --git a/images/orgs-using-d/arex.png b/images/orgs-using-d/arex.png new file mode 100644 index 0000000000..41dae20475 Binary files /dev/null and b/images/orgs-using-d/arex.png differ diff --git a/images/orgs-using-d/auburn.png b/images/orgs-using-d/auburn.png new file mode 100644 index 0000000000..8e9b7f4ceb Binary files /dev/null and b/images/orgs-using-d/auburn.png differ diff --git a/images/orgs-using-d/auburn_hq.svg b/images/orgs-using-d/auburn_hq.svg new file mode 100644 index 0000000000..4ce834c6a1 --- /dev/null +++ b/images/orgs-using-d/auburn_hq.svg @@ -0,0 +1,1099 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/orgs-using-d/bildhuus.svg b/images/orgs-using-d/bildhuus.svg new file mode 100644 index 0000000000..2929aa6e9a --- /dev/null +++ b/images/orgs-using-d/bildhuus.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/orgs-using-d/cereris.png b/images/orgs-using-d/cereris.png new file mode 100644 index 0000000000..d82684d5dc Binary files /dev/null and b/images/orgs-using-d/cereris.png differ diff --git a/images/orgs-using-d/cereris_hq.png b/images/orgs-using-d/cereris_hq.png new file mode 100644 index 0000000000..f0fe9dcb9f Binary files /dev/null and b/images/orgs-using-d/cereris_hq.png differ diff --git a/images/orgs-using-d/ctrecordings.png b/images/orgs-using-d/ctrecordings.png new file mode 100644 index 0000000000..af12eabe9f Binary files /dev/null and b/images/orgs-using-d/ctrecordings.png differ diff --git a/images/orgs-using-d/da_roll.png b/images/orgs-using-d/da_roll.png new file mode 100644 index 0000000000..fb085bc0ba Binary files /dev/null and b/images/orgs-using-d/da_roll.png differ diff --git a/images/orgs-using-d/da_roll_hq.png b/images/orgs-using-d/da_roll_hq.png new file mode 100644 index 0000000000..9d7ac79f08 Binary files /dev/null and b/images/orgs-using-d/da_roll_hq.png differ diff --git a/images/orgs-using-d/ebay.jpg b/images/orgs-using-d/ebay.jpg new file mode 100644 index 0000000000..43388fc367 Binary files /dev/null and b/images/orgs-using-d/ebay.jpg differ diff --git a/images/orgs-using-d/ebay_hq.jpg b/images/orgs-using-d/ebay_hq.jpg new file mode 100644 index 0000000000..17c1bb0340 Binary files /dev/null and b/images/orgs-using-d/ebay_hq.jpg differ diff --git a/images/orgs-using-d/ecratum.png b/images/orgs-using-d/ecratum.png new file mode 100644 index 0000000000..b1a8b35c5b Binary files /dev/null and b/images/orgs-using-d/ecratum.png differ diff --git a/images/orgs-using-d/ecratum_hq.png b/images/orgs-using-d/ecratum_hq.png new file mode 100644 index 0000000000..3b9019f6a5 Binary files /dev/null and b/images/orgs-using-d/ecratum_hq.png differ diff --git a/images/orgs-using-d/emsi.png b/images/orgs-using-d/emsi.png new file mode 100644 index 0000000000..c7ab2339a7 Binary files /dev/null and b/images/orgs-using-d/emsi.png differ diff --git a/images/orgs-using-d/facebook.svg b/images/orgs-using-d/facebook.svg new file mode 100644 index 0000000000..d1d6bce71c --- /dev/null +++ b/images/orgs-using-d/facebook.svg @@ -0,0 +1,13 @@ + + + + + + + diff --git a/images/orgs-using-d/funatics.png b/images/orgs-using-d/funatics.png new file mode 100644 index 0000000000..6be53f2f72 Binary files /dev/null and b/images/orgs-using-d/funatics.png differ diff --git a/images/orgs-using-d/funatics_hq.png b/images/orgs-using-d/funatics_hq.png new file mode 100644 index 0000000000..972170a6c6 Binary files /dev/null and b/images/orgs-using-d/funatics_hq.png differ diff --git a/images/orgs-using-d/funkwerk.png b/images/orgs-using-d/funkwerk.png new file mode 100644 index 0000000000..f5042b757d Binary files /dev/null and b/images/orgs-using-d/funkwerk.png differ diff --git a/images/orgs-using-d/funkwerk_hq.png b/images/orgs-using-d/funkwerk_hq.png new file mode 100644 index 0000000000..6ddb949ef4 Binary files /dev/null and b/images/orgs-using-d/funkwerk_hq.png differ diff --git a/images/orgs-using-d/infognition.svg b/images/orgs-using-d/infognition.svg new file mode 100644 index 0000000000..68283d2e84 --- /dev/null +++ b/images/orgs-using-d/infognition.svg @@ -0,0 +1,101 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/images/orgs-using-d/jumiafood.png b/images/orgs-using-d/jumiafood.png new file mode 100644 index 0000000000..5c0517edc9 Binary files /dev/null and b/images/orgs-using-d/jumiafood.png differ diff --git a/images/orgs-using-d/jumiafood_hq.png b/images/orgs-using-d/jumiafood_hq.png new file mode 100644 index 0000000000..b937292934 Binary files /dev/null and b/images/orgs-using-d/jumiafood_hq.png differ diff --git a/images/orgs-using-d/magikcraft.jpg b/images/orgs-using-d/magikcraft.jpg new file mode 100644 index 0000000000..332481360d Binary files /dev/null and b/images/orgs-using-d/magikcraft.jpg differ diff --git a/images/orgs-using-d/magikcraft_hq.jpg b/images/orgs-using-d/magikcraft_hq.jpg new file mode 100644 index 0000000000..4a03df504c Binary files /dev/null and b/images/orgs-using-d/magikcraft_hq.jpg differ diff --git a/images/orgs-using-d/mbrdna.png b/images/orgs-using-d/mbrdna.png new file mode 100644 index 0000000000..0370ae29a5 Binary files /dev/null and b/images/orgs-using-d/mbrdna.png differ diff --git a/images/orgs-using-d/microline.png b/images/orgs-using-d/microline.png new file mode 100644 index 0000000000..c875296bfd Binary files /dev/null and b/images/orgs-using-d/microline.png differ diff --git a/images/orgs-using-d/netflix.jpg b/images/orgs-using-d/netflix.jpg new file mode 100644 index 0000000000..48b294e43d Binary files /dev/null and b/images/orgs-using-d/netflix.jpg differ diff --git a/images/orgs-using-d/netflix_hq.jpg b/images/orgs-using-d/netflix_hq.jpg new file mode 100644 index 0000000000..04d1ea430f Binary files /dev/null and b/images/orgs-using-d/netflix_hq.jpg differ diff --git a/images/orgs-using-d/netflix_small.png b/images/orgs-using-d/netflix_small.png new file mode 100644 index 0000000000..61761857e8 Binary files /dev/null and b/images/orgs-using-d/netflix_small.png differ diff --git a/images/orgs-using-d/pelock.png b/images/orgs-using-d/pelock.png new file mode 100644 index 0000000000..b652e764db Binary files /dev/null and b/images/orgs-using-d/pelock.png differ diff --git a/images/orgs-using-d/pelock_hq.png b/images/orgs-using-d/pelock_hq.png new file mode 100644 index 0000000000..5fd2489011 Binary files /dev/null and b/images/orgs-using-d/pelock_hq.png differ diff --git a/images/orgs-using-d/putao.png b/images/orgs-using-d/putao.png new file mode 100644 index 0000000000..a0ecc6e1f2 Binary files /dev/null and b/images/orgs-using-d/putao.png differ diff --git a/images/orgs-using-d/putao_hq.png b/images/orgs-using-d/putao_hq.png new file mode 100644 index 0000000000..c90318dfc5 Binary files /dev/null and b/images/orgs-using-d/putao_hq.png differ diff --git a/images/orgs-using-d/remedy.png b/images/orgs-using-d/remedy.png new file mode 100644 index 0000000000..4b7777147a Binary files /dev/null and b/images/orgs-using-d/remedy.png differ diff --git a/images/orgs-using-d/remedy_hq.svg b/images/orgs-using-d/remedy_hq.svg new file mode 100644 index 0000000000..c4cdd718bb --- /dev/null +++ b/images/orgs-using-d/remedy_hq.svg @@ -0,0 +1,2368 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + eJzsvWtzHbl1KPpdVfoPvB9SNa6boRtvwDeVKnKTPPEJ7bjGdpJb8SmXrJEnOhalKY3GvnN+/V1v +oLuxN6kRJ3Zssm0N9yI2GlhYWG8s/N3/9Ytffn7x5bvfvfo8nC9nz5/93d8d3r968eHd+5+cEfjs +p2/efPvNh/cI+uyLH5255XzBVhc/rb+Vlv/66v03r9+9/Yn97Qa//Rl9/Udnn/0IQb96/eHNKwAe +fvKb31y9e/nt3au3H745e/H2y7Nfvvrw4fXbr775zW++eP2Hb3/zm19995uS89f4z3cfflNihD+8 +unv15Xfnr77+5kc2QHjh1YsP0GX+sWs/9stSzspP/HL2i59hk8t33779Enq9fPf/wbBaOws+nIXm +z5LL+Pd/ev3Fq29mjc59jA5auvOSUtPmOuJfvH/38tU33xzevXn3/pufnF2+efHyD/D3i5+m3968 +fvMK5n334sNZJixc/DT8lhr++psXX8E46XeCl9/+9A5AOvGfnBHSDj/7f/957B+GJM9n//HFq69e +0xrArP/Xjxj9mXv/5auvX/AfoD/+zmfwx7OrV79/8e2bD/zas94K8f0jWuf/++xfvkbIN/StfLbA +f/j//MjrqwH0+dzh/3qz/W/4uz8LZ5Hf84tfXOE7PDfIy1lM8GcvX3C7F+DzGQ0SkfirV3dfv4Gl +pmXyLZ+ns+ga/Dv8rk1hEXg1Pf4v1eWs+ip/7Iv46o+vX/3pJ2c/f/f2lazexfsPv3z9f2CVEtBI +jYuAv/j2zav3v377+gPiiGCNsf6zd1++egOj6V+/efPiK8JknxL9Ky1+9eL9V68+ANG9e/PtB9os +ddG//fzbu9sX3716P7zkX75+9fZX7/6Vhvl58OmsFloQn+pZc+XM83I5d5brsFjaI34dv6zdFlyH +XwDN/cv711+9fvsTQg+TUfjtL158/er9F69efvjJ5wCvYQG8BVhha/AzGDt/6XNHf+AvIyH/j/ev +v+x0XODr/A9N/bwO/2/6f5kh4OvDh1dvhfiv3355eHdHTIG2L9D7W9gMb959JX/tH+hv8M5vv5bJ +EuC3sJi/eP/6LY7k+bOfw99cPLt8Ozb5H+9ffPka3gBciDbu35/923++/vDq7AsAv3gDu2oKJkq+ +/PL5s/94/uwfnj+7ubm5vrm6Odxc3lzctJt6U27yTbqJN+HG37ib5frm+vr66vpwfXl9cd2u63W5 +ztfpOl6Ha3/trperm6vrq6urw9Xl1cVVuwLavCpX+Spdxatw5a/c1XK4OVwfrg6Hw+Xh4tAO9VAO ++ZAO8RAO/uAOy+XN5fXl1eXh8vLy4rJd1stymS/TZbwMl/7SXQI6L24uri+uLg4XlxcXF+2iXpSL +fJEu4kW48BfuYmk37bpdtUO7bBettdpKyy212IBBNteWelOv61U91Mt6UVuFMdZSc0011gDbydWl +3JTrclUO5bJclFZqKSWXVGIJxRdXlnyTr/NVPuTLfJFbrhmYeU455pB9dhnGmG7SdbpKh3SZLlJL +NZWUU0oxheSTS0u8idfxKh7iZbyILdZYYo4pxhiijy4u4SZch6twCJfhIrQAYwwl5JBCDAHYuAuL +v/HX/sof/KW/8M1XX3z2yUcfvPfOL+7GXbsrd3CX7sI1V11x2SUXXXDeOQdjXGA5F1iQ5XIBpC0w +7SUvMLQFOl8cbt9/hEZnf/fby/dEHp33JfwPwH8J9PfbDfjyG23pGAQ9bdoOf8DWl1dCxrAPlIiP +EPbh3dewmZGW5TforQzkC0hHtDPiEfWIfEQ/LgAuAS4CLgMuBC4FLQYtBy4ILgkuCi4LLszF82ew +OLg8uEC4RLxIuEy4ULhUsFi0XLhguGS4aLhsvHCwdPAUWjxcPuDk+NUQaBlxIWEpaTF5OXFBcUlx +UXFZcWFxaXFxcXlxgXmJcZFhmT0sEyw1LjYuNy44LjkuOi47LjwvPS4+Lj8SAJIAEoGjJQa8yUZZ +b5X1ZrHtQptl3C7rDUNb5vkz2zTrbbPeOOutI5tHts568wCHX22g9RZab6L1Nho3Em0l3Ui0EuNm +Wm+n9YZab6mD4g0Z0mOyI2BFiuFHYkfPnw04fRR2BHgbsPhx7EjxRvTXn+3Psn6AUa2f680D/QIj +G5/D7rncPBebp60f6LFunrJ58uZJmyeuH+gRWev68ZtnN3X+Ibw5YcWAvxI+6vG7xw0PTAV65Cnd +2HMtz5U8B3ou6bmgp8kORnorRHNIdUh38ADd8Y7GPe0IPTdIhbZzDg94tj8X9jR5qjzAH5D18PAu +ifkjW7gkRozsFFkiLfsN7VfcsbhnedfivuWdq3sXdi8oGn7YwbaHdQag3syfunvK8ChCkzwkclBs +QI+oInlSkxwR8Q0916QwscqEShOqTaw4seqkypOqT6ZAAU4uZkqUzoC4XH8mZLJ78uZJwwNrTtKJ +JZQ+3mSVyCviBSqxWGax1OpyyyQXEH2ZSa/tfgDuBtRF2xAb49AC0SHSI/4gfSKlNqJcJBKkZlwI +pPEbon58FU4SdswgFy8B2Vew+qANA5twQBEBqCPRFihAMw2o5xIWBenp+uIGaMwBjgNRX4IXFcB+ +g1XAn1FucJt1iwOs2/XlDbArB6sZYF0TDLPAal/Ayh+ABq4PN0AZDmgkANUkmEAB+moDX0X8IJ4S +YQ0nhSIa8Yl4vSQ8I8YR97AKtCKO1ghXC9cO1xJRWNC0XOMZWBFyJfwSci/ka8jpEPGIwkq8E7kp +bjXkukjGyKGBaxNDc0QGNkbofDtOHuWxcbrpOAvRL6ossDtJe8LtgFsJpTroVsRs8bX45UAaGCqA +yKJwuVFHQ10NNYRL0t9wQ6I+B/oD6IA4URwwvha/HEnLQAJDrRC1Q9QSkW3gsh9oS6M2CVoliQIk +XhwuvjQmmDXIXiRNVI9QN0UdFXVVZFu4oa9Qj9U1JZwrvhNhuhqWD4TfG8KsI8zyyndsXhIeCYu8 +0oChYNgrhLcLw9g14coRlgJhKRN+GDuXhBnAimDEMy4AQ4qJRjg46Pxp7p5mHWnOhWarM8V53tCe +1R2baK8C3ZFsuaB9inv0hvaoo90ZAW24oQtoQg1Y9iUwQmSt1+UGxLQDUgi4JIDYDJpUBY3qgjSr +S9CxrkDXugEixQ3hYVIRUJ9BI0Pdt3XebjhfY3yN7zW2R1wLpgXPgGXitYrnNZZHHK8xbPgl7K5x +C1Q54HaN2TVeB6yuMbrBZyGdveNzjc0Rl2s8rrHYRo4JEnTNMdf8UrjlgHP92WpBynO2z1abCjt9 +KxqP2j5b7U152PpZaYCmE7bJs9UnL3Yap/LE4YEelUuun62GKzx0++zRBBx19rPWt3fyc2tTinxe +25PdmixTa1I1dRgr6eOqdV+Ie6Ga1pzEzRBM512UCtThITbzKQvjfpcHjBWmuXJ77Jwec7fHPyDX +3zphPs7m2Y6GdJnTYzkykul+mD8P+lnttQd+Y6NvqVeF/SrsWWHfCntX2L8SRDV0bLGbp4V9Lext +IX8LYJvtePK6kA2qfhf2vLDvha179sCwDyaIwunUEyM2P/Aekt/skWGfjHplLsQzw76ZKkZSVg8N +rbD6aIKosbBk0KMTo+1G/DXX4rNhrw37bdhzw76bttKsR42ZBq3ru7FEuh2iXgSyQsyTwHbI5cpn +ox4F8imA3qp+BfUssO9m7b1Z+2/Ux8BeBvUziA8HZEMUO9KJnXgtVuGleR2q2YDdm6O+B/Y+qP8B +aAdoSP1xcePVUV/EQaihmfet+3a8+d3U53ZpdtnGBf2pDmiyLFcu6E/1+IAusnFBf6rHB/SljQv6 +Uz0+xnuOe13E9zJ99v4XkQbQ40wu7qXnxCcjTz0ilffSe+6nmXtrBp/NoDnos9c05v6buRfHrfgn +utLPF1iss+XcgYqF/3EBg0jAacPEaf6QxuR2Pw+5YhAqLxHb5xY9NgSxww1rGjq9vy33GRNG485B +Q8X/VMARjiEl9OKXcN5cyGdl7PiBX3jQiHN4+IihbQ8+SDwixHmcAuD8fhdagV5QVcf/JEeY9U0w +O3z9/qYyI9hOOLzSsEEtKWA7jDlSOz9O6L6mHxke+eLF67e/e/cnjI/orxiQHuN7jxDTGxkqsNtH +iOmNDBXE4SPE9EaGCuz2EWJ6I0MlBeiTY3qjOsnKxafG9EaFEkhxo1JyPO8csOOZtc9Z4Pd+pMc5 +u/1eD/T4iL1tejwmLj7ygR4fqacjPW7DEN/j2QczmBZWOv11XT3txHNx4rnUB3q83DyHE8/ViUd+ +oMf9z83xZ2Iwm+HMDzBEN3n8iSccfUh1hR7j9Eknnnz0Aa4FPZYjTz3xtPEx//AD/VUP9VYB23qg +v+qh3irQZB/or3qotwrY/wP9VQ/xVqHfHmTyQz339X7fPQhVGCOI1ysg9RtQqR2I3QDiN4EYLrQT +L2jv4D64Idr1RG2J6ANXGoZ2Y7GFI1rzw54HMY/HZ0d/Fib85xI9nyRi92z7FFM9/WzZ8zG2/YnP +rsdT4uNBD/T4sd85Jc7ggR7vafGxj/RYv+9jLDs87vMX3iP58UhQPerzl9ejru+nWF8z2+v5s0+x +vma21/Nnn2J9zWyv588+xfqa2V7Pn32K9TWzvZ4/+xTra2kTVv2pUcStVgba1ydGEbdaGRi2nxhF +3GploH19YhRxq5U9f3ZML/u+WhloX0f0svu1MtO6HhZhHJ/7NZr7dan79LnBmwo9znysM2/siYjl +JHo5i1/eH82cRjZX/uZ7Ip2b58jPEA/19zwTwSYs+qFC/3HVl09RsT7G8p4+JxXLU7b60Qd6PGnd +f/zPx/oDxmfGno85+Y892yDBLOHz0565h+1xfXY/nIftkTxtDzDuvocBqpv7sTzhqouB/vVInnDV +xUDgPZInXHUx0L8eyROuuhiltD2KJ1x1MdC/HskTrn5w3D3qA3ehrLY/x+SWQke5aqXAEuhlGi7a +hONOtuMoUCs5DW1cy9qmjl2dbCY9LY3CfaVGehsGiSTgterpVDPpyadETSK9E7CuTeKqp1PNuCee +s4yXsKlN/ApRp5pJT84RLvNSN01WHZ1o9ZExsl+9f/f165cv3pz98tu337z6gLGyLQg6TRozWzhf +99S2vc+ImmxcO3FT1pkbm6yNMWcjTU/c6DaGHtcZG/fmazTJ29eMjThm66NT2k5THVanqU6fpdqf +purnqUBL2eT2HMvs0dweze7xK8t5kI+cm2tZ1Tf6nFBa9XH3P8DK/QOf8LAHekQr5OOedOqBHo// +NX+fB3qcwcv3f8glUeYG8fz5nq7cB2szHxvT/Dit7aTWONEz50kkx59dcsn3SwocTNdHSHHuzgmS +3I+Q4tydE5Iw/8kpzt05QRrQI6Q4d+cEaWkngkbHnBMbI1P9v8UePYmV7JHsyWvJcLz29siZGrSp +oUfOz7qRp1tc+nOw51KeC3u2h5kAXXSWe3aESQ8xxatgjx+OMjk90DQcaroRXfnajg== + + + N/ERJ/3RM2AX9jR5qj3KYDqT6uyws09lvsqqO4PXrLSby5k5aLttFiK+njxXu2clTqDzfspp+1xM +nrZ76vqBHjUfe/vkyZMmz8ypPXPLz/wls59JPvrUn/PQTMJJDuE0g/Ch2YPrBIh/oHMmddCE+gnG +sD2/qCcY5XTyWi+yc+aU17rVj9Ya0lpHWp85v9xrSHS6Jlv265j3bNrQ6vz51STXeZXn/PzZJstZ +T6KPZ9GvN+fR1yfS12fSk5z8W5/3W5/0O3HKb6BZo0kJKnU6G04XCK30U7262l15ECH/dJ7nv/48 +z8d44oFdPzBD4pQnfsK8H9cDcwGE9LgemAIG6+N6YOhY4aN6YDyM8bgHZrW19EhoPxBalvVx0H4Y +dHYUNNkxUBZq4zHQq+H44v4IqBxU1eOfw+FPO/pJuZX7o59lONi4PvZ5MxxwXB/4lOOeVBZkctyT +TAYn27gfesyrY56rQ55ybNlRmYbx2HI/tGzkvXFXUQ4y5lnXqZdq/mdJkD4vSf6BP4V0DngMZ6mc +AxdbJUyfbHefKyil8+zqg9xB0lRSsmnc0fVs7RjPWwxjV8fbcB91TPZ27Rzpbfj69M8f6Uj69du3 +L+5efXn2lYDQk7SDPaVfP6VfP6Vfz3r8xKDQRwSHPq3HHyTf8Xuc7HzQ89+qx0f7+fjzrH8JPW7P +1D7l3z/l3z/l3z/l3z8gW/7R5dGfRQr/uXSPT9Kx/pETBUJ7SsJ/SsL/y0iZf/we/0JT5h+/x6ck +/L+BJPzvk9p5z/PgHh8c1IcePzYN4C+rxz+LdbmrT/h0wuLphEV/7tdZ79eWn05Y6PN0wuLphMXH +nrD4h0f2pP2wHslPe/6Spfmn6DDT7/7j09GZp6MzT0dnno7O/NccnSGX2wPPz6zbHj9EM7S79yTN +uu3x4zR8UuVhZ2rWbf/bH6zZ5j6cuVlGBECh/zEn4kl2PMmOJ9nxtyk7nlw2Ty6bJ5fNk8vmyWXz +5LJ5ctn8l7psnlIWHvQ8pSz8EAkGj9/jX2iCwVPKwlPKwlPKwl9oj38WzeMp7fsp7fsp7fsp7fsp +7fuBbuzHcox/krt+nvb9dJzz6Tjn03FOej6Rk3wSR/mYHn8QPvp0nHN5Os65v+LvUSLwj5kT8ENk +LPwgmRU/QAbI42WofFJOhJ8nRfhV0dF/oByGXqnoWIB0blZMDYsTFYvmgdJj5oUZGM+frUyMuZFx +LGA6mBnGPB8h+DsaTKAE3B/8/ShzCRSVTw79orlkN9WynX3Tn1UEsJeW88MThicOD6AZDHUuEJiH +pwzP3M0wD6+tA17HQlNzo39n1G/qcPVKXL0WV6fwTgedEjotrOicqvQ5qjgWVuWAGlUru+yFgIgy +ujHd6X1D8VRR1g000s3qTimdVjq1dHohitm6eVaq8DFleO6mnKrDMM5jKvFcKb73FnXA5agYz1Xj +Y5keg3Ksa/1nMhM+wnmLqSKPYSRYThO7qkbqH0sedhfZ+DPurE2QzVx5xwJSfT+XScHQSdFQ6HFd +OnRdPtQPPGcszDhwKB6ozrjf5y3r0lemr01fnW7G9TVa0S2syKVVLCxyH7u62pV6+3r1FetrtqFg +2ISXUmuwWo1BXr1Ox52SLWupG3rkKN5V63iSz0/y+Uk+P8nnJ/n8JJ+f5PNfmHwm9wu8Dh0DwAYa +2vMR/w0pt5nRf39bPVSRCnoFErWoMA51DpR6vtTWVo6d+9pyn6ffncJ5Cz4/eKza/r7x+o8Yr/+I +8T4cq5/uTJn7UsiV4tf3tyzb+s/3VYC+R7cBXnxav7kv+XwXsgV5sdZyToZt79VzQNN5/uyErnNf +RehJIrpVTP9k/Wr9RpBEn5T6vg8XA1V9Uur7PlwMuuADU9/vCxejEnlzc6++1WmzU2enz657K4UK +jcqtBUqnXQuvQ3HkKy2MvKPVTq1KryBJJjTbEw26bn6vxkW027X0Tr+dkjotdWpSeuoU1WmKqGrH ++ZHloJcaGNCM2c//LIWRkUPViZt+95dP5l1lzrwKHo+LgyM4BFkirVyd+GYCWa6xgvW8hrVb17Cm +6wS6obhSmTdLqMxH2U9nQN1kHHNHRnawZghbljBnCsYWgCUcOxHzAMagm+sJc0+Ye8LcfwvMDYb4 +PXlgHy3U8S4IXZ2nvjd9r2/MuIC/Z2jrwda6pvyiRrlFmFmEeUWYVcS53j2faJ9NJPlEz59RRhHn +FFFW0XC54RVd4HRJ+UUXds1hpUyjQtlGWa485GsP6QE6wwwkffzq2d6NpM/JVA46h/moz8N71LV9 +wvsT3p/w/oT3HxTvK8cY5rX0/4M9085B4Vh5bo42YRdQxvSd1T/7XJ/jbeyGluH/7swF+Nt5Wl/S +Mm3B3yfPkv1/4tM70uCTDbc2N9waGm7B3E7nbvfPIGzXVvuDomb7gwCDX0ms9OWBcRGNoql/qV9Q +pNcTAYJWnia21SeXE5EC2VVI8T2Z5e7oDmKy3p8/o+t+E6mVbMerctlIwbwQm/5S7nWU2yYH1/nm +HAZuAjti8YTRJ4w+YfRvCaMroYb+vP7/XShi+me5bmzzJ7zmrAV/Fk98vbc5Kox8Ovd1aacFkjb6 +VKEUpzIpriIhGAC9ubm+ubo53FzeXDzG2RW6EfjkqeKPPbsCtu49p4o/9uwKeSdOnir+2KA3OrBP +nyr+2LMrsJHvOVX8sWFvqhmzK8VkIVMNmC4rt/nEVT5qTY4/9r8b4FPJN6Up/QJ44wzfxfEe8x7X +j73JdXro8vmzeyN4s5yrbSxtcMcBB13HP9YOOXXJ9bgaR9Y0mtfqxaqsix7c8KsiI+u6d+sjPWxH +rIsnURmk58+sFNK2qNG6PNG62NCqZIPEszjmCsYcrRo/als1iXNd2KWglyJHD3I9qF4RSjlHktYk +E4QV1lpG+hPkifYkebI9xZ46uX4Ts2ceNWJ56R4Ys9w78yhuqStsdmqT61AvJM9Kr0U96L3sklCi +p6uZDHRpFEVBHNpx4tDOcp90MUu5yXMhz+Ucc8Ml78MN9ENqjVwPb5WydIl54HrBPF84D1sJhFCS +C+lVeeAr6/kC+wuK215S7PZA8dsriuFKZt8ql0/y954/k9y9nq3X8/N6Tl4/Wq9Zdz3TTjPr5Ig6 +HU/XI+f9CHmjqDDGhS95yhQdhi56hJgCBRosOMjkrzlksAoaKEfqEdpt2IB0QeZPKw51Qh8cggcz +XkXcinLnrjbR/3X8fx8+OFb8jnYU7K6P3FNHr8iVW15jPsdBn7VzRNA6rDtrIFodOi5cSl4b1fOl +5HYWwznuilG1u6dld3n4oBfPtnOQ2PGsuHNkjRu/x9FmIojP8dDT7ADT7G8fKZ7/9fW7N68+nF1/ +9wql8vAJe1xrk/yzLQCxyke7OWyey81zoQ/0qL+33TOrtTCrzbCq4wA98m/z+g/zihHxRK0Jb0mE +s2dW02Kaajg+0OMsBfH483EV4D6+Jt3H1r17UHWwR6gW9vi1vR6jx+9T2+vxq4U99fjJPf5jt5Cv +hWtdGi+qxluScQivu1r2pO6dS6MLqsZmKb9JLOlgibyauntNVvWVKCiXZF1fkPJSqT5EIeWGsqeu +QJUgazuIOoSK0UJ29w3Z3teiTh3IBr8kO/yCbHG0xitZ5IWscrTL8YEeUTdg/YJ1RNGtSbMXNs2b +UDQp7viSfy7kafRQsAXETb0Ur84leYkukzxRHtVrvD2q2UuJ1YsuGACdz5/Jhruy52CPDeFi/GnD +U4dHfE7QYyHfwvik1RNXT9g8fvtAj273TIrL7oUbPROyfP6M/nt18jnc+1z2B3q8PPFcfPwDPfJv +j/YDPR77qd/vgR6/5zf/e/coZv+pGh7fvzJJIm/Sozw/aLW7P1dtur+u6h79efTKGU89PvX48B5N +T0MdDbWzQjoZaGOkh6H+hZoX6luoaaGGhZoV6lMcq0DNieMUqCFxjCKRDhQkQqHxCY1OaF2tHpfo +UYl1TGKISAA/H2MSD6lyejQiwTGJ588sKjHGJXpkoh/I09iERifWh78oRoFRCnIGcaSCYxUcreB4 +RT8GFsi95JBVkxmshxgPpMJdDAfCCh3q1WNheqxRDocRM76xI2JXpGqy8sdHxZo4L4scGcOIBx61 +YSct+yT5ABk+zGTZuL6W42RXFBM5UFzkUg6W8eGyRlESep4/EwdzlifJow5p9YOq57j/dCY4GO14 +wFBP4g1PvxNgfXfAShU8VgfQakw9pHreXE6fvhbnEarADhLxsaXNI/KLx+vrh+txUxG2GwD7+t5l +8+Tdk7aPHSodn7B5/O5xu8eiO9Dj7OipHT9dPfsf8/krN2+fXBl6zTHx6NsDji5/RAQXOOUn1oXm +CO48JGIYMQNbjNxmXoAqoY3BE3DUD4CXIV2LF0A9AGr/d8s/SlTes6UvVv6VSL9LsejZjs9g0SeL +03u20iVSrzJRo/UqGTVi3+XjKncTVl3XfFh1C2RtQ3ISjLPgVg9saVDr2o61LRbEChq2kmITegbj +QgK6Bw2mDGk020NubQifDIk0z5+tTl2sj7kdO6J58rAkVTffnbX4Qe7kWO7hY39e6+Mem0v30BiN +/SR2sWcWoGp9ZCH5+1I+MFfr+zCM4ykfpMbce/vWLuUDsTXDxx4jewa6xwlhBbbCGi97zOxxs2em +A3YAW/v6AoqhPY72WNqlxgC2Zpja42qHrb9Cs//TmMORb6w35X/grxiMXLAIAP7qJMTq03mNvgwR +y5PNpCIklbM8Ty27HtuMmJVe/VgM8lQzCcKCLMFgbUzaJLvzFGo6y/EcWHYZI7H3tpVAccZ4LSX2 +LYuV3SzLufdx7O90OzuCPNSJyMmVSbh6+ONHBnf/7T9ff3j192eXb168/AOGd1efn9IFn9IFPyJd +cDlz0/P16z/syHrb9qFn6gHy25+/e/uL96/ffnj99qvPPx9JfPzL82c//5r+Fvhvv3jx4cOr92+B ++i/+z7fvX519AW2+QeIfP555DxuT/klV/sExfvscx+lkpP/+HY/7f8Lv/xugfzqLZz87+4//tZx9 +Se3+/Qv8e+/qzj5Sp7f40bofPlKT2/V36eNb6vYLYW9YPAVL87ZIo/ln4p/nJZ39CZrFRfult9LH +CB9TzWfBn8e4tDMCUu/020vqAD6m5hgShy9F7Y+a4adcoRsXz/QrJWt39Bu101cRhPrUb/UBUsNv +dMwdU/SROh/HbEPejViA+g1raQOmPoYBz+a/wg39o9/qrdcDpn/6gMOyHnBfwv5dHYBNRL8UV2Mh +lC/rMXcC6bjTVxGE8boMY+4d4pg7wd0Zweka09dWkx8Qs+yQJt/ajIY+6irrt/r6d9rQtxGEvq/f +6mNcD7vTBn3UlbZh26h3g9Yv61c2C0K/6UKvZrrBwgpDNAj9Vh/gesydPLj5sh5zJ7/+XR1AH6R+ +a0OsjPllPeyBCup22B2x+q3e2obd14OGzUsna00rtJr/QK51hzflHevRrPlAHSiE2g== + + + dArRtxGE/tFv9dbrYXcKoY+63DZsG/Vu0DpmYx/rNVmzgnGmGyysMESD0G/1Aa7H3CmEmy/rMfft +NYymjgxkZDsbel1zgzpQyGaP6dv6Cui3+hht2L9+fi0iFcSwCNS5jD28uHv37e/fvPiK0geHT6QU +lAD/W8tV/2C5ih3c8S/QD8lH6s9+dfyb019Yev6LnEglVd75oZy9B9H5B37zWsLTC+5WffXuh3f2 +gfz+OZU8a9FRlTNPgpr/4/kdDvAcY+s9y2fpNebzUoPffrQ39W8P73Ncpt5xYf3Gldaokhu/0sEY +nDe0ycd4XhyMrJ17LG/vz2t1QT9lPNlUeeEF5DAfNQAxnfu0+RDOawkmuxBSzjGrF5uhG2732bvz +pQFBslBUYDynmUPXS91+gnnnFO0LCIPtFZYCVH2e/JJ2H/P5EkFRYjYosHZeFg9r6WCyML3tZ0zU +TVleorByvqScz2AGGXf3+iPsFVDjBVEKi+dxiQEGUsDG2H2sWFzP67gIBvYk+gUBmzkHt/uYAHmL +oZdh7dyBaXGmawmfg6vRPgN9HEhQFNATYXxKL/pZ2wMfWcCGsP7s8/hOA8q4YDFW49TPq6kZUKYP +lrxLKew/jxhUoGIZOqlgd+8/DwulMF1MGK0D62b/eSQIAwrR+HweWky7zyu6MyCTJvwHLLO6+zjS +tgJ1A3isHxYmn8ctZEDZZB7dDCntPo+bVGGyjXWdZY/rR8dU0RnCwESad8gbPReAbOTt4Is/iIlE +2A8lKQ+RT9g9cgHAWkVvDb682sdxfAozxoH+mTj5vOIlChRswVvB5Pa7zyuUG5CXBUgFC0jvPtLC +CjUokFc/I+mASd/2n0cSMiDRGTUqWDVz+3mkVYMJPccEWGl593m1KQwoOycip4el3n0et58CjZeA +5PO17T+vmIsChRvIKiuzkI/KW1ID8khdNulnaB69a1iElLouMJQGS6yfcz7PDsbNHFCBHt12MMl0 +XnGPbT9D50CZ+iUFAl9fPM5pQZm3/QhTrVUwr0BQhVzEKaIfLqT9Z9AH3SLvMeAC7ys4huZL2X4M +5dxX4+gKDKBygZBKwDNy9rvPvgHXMvGkwIwHRngGDaXe9jPQY1BupEBQCXKFzZw8cACUvdvPCTSc +LF8yoDsPHnoGlJWY3e5zAULIybBNsHDeSj3TVY68ZfSjcBbjEsZYHq4y/tO7t6++e/nu7neoMfYP +qJi3CvTk4JUJeCmQbF1gs8Dq5JKqqpHu7OLrmRJ3nzqp3Wn3d2Kor955OwLlxQzcjGYNXH39LQ3y +isckvpyjxXHJqePJo5Mj6HKAf+ByoS2ZB6hAYOwLMKFbWVxgpYB9EKJRNiVu6YibdminMO1w9WVg +jC4UL/PYvPpWDYEfX7z/cPX65YfX796+eP/d2U8Q/uMd4OL9+xfyuz/78U/ffjj7e/z9/zn77Jev +3vzTiw/QCQBfvf/p1TfU9Ef89/F7n7Ufnf34lx/ev3771f7LVy8+vBi/OP7tVy9+9+YVjkj/hv8w +7pVOeCmovE1kH39rnu57wk/sVmOfGpB+Qm0LOFsNTUSgAGEjL9WtkRhhqyyKQ+DlyLnGdgrTDtcr +EGEvOiGa7au//wqEv5gV0J2qm+FBuwC4bCyNKTHyCggISRvsk1tRIEuLkbeAbtuIltG6ncKoO+fW +X8YtEJXa1+/9G90AqHA5v9kAChwJW1E4boAAuC5xvQEUtiJrw/+4Abav/uvYAB9B+IiNjD4n4MWg +QkswQYDo/YmpmXzKNYKVFACPzXwT6zbcT8rrr6DCWZMs2PaNfx1E/3BuD0o/QMBicaDXCbNnGHr0 +kt/gDowr0GeL4A60ssyGZG+pQO1y9fWYzxtYysLu1+/+myP2grp0IdILpQjyFQiEXKsqNqBi5YWc +Rg7D+ixBQVi6mtYNFUhd5rT6NpgIzusqbd/9N0b2CabvgWcD7YGN6yV0IUAg59LcGnnoVEDVRLyh +rBuvGipQuxy/DSZv6HrT5t1/c3SP/Ddu6V6BK3IODXlJWxM+LAV9bdVSgSvC168T5QcNPm/e/jdG ++YC1XL1bU74CVwRtyEfSd8LygZJjDHXdUoHYZ9eE5OtE+01Voc3b/zpo//tr+BmQk1pbqfjAw2s2 +YlcdsyDz1mCPKPSrlgrULldfL/hHJfbNu/86NsD3VvPRKYjKy0rNRzdQiRskJoqirXX6VUMCFm9d +rpcABtWWtFb0Vy3/FveBOl1WG0GBK/o2d8O4E9S7s2qpwBWB69dXO2H79r/RraB+l9VWUOCKwhWL +41ZQ/86qoQJXBG5rMG6F7cv/GrbCw/3A//Pbt1+9eXWGb//6FWXobSBngGZHMfC0Sc57eBIBdyEy +BvqxmP7wq1MeVuxX9OF+25Px3Bm/95/5lZvsgSpiDcd7J33Cr2/w119SzC1ITjFoADloP+2er/36 +uRIpvetLoq2zz3509u//9nGI/tmrL1/Dr+9fvH314u3Zr16/YWzPwOjQicBMHGY+B4/BLY8egkQR +v/UiPNz1vun0boBJz6Y3DW9bwfS7t5P+bMU0+UMGJ7ke4oKncGdJPZUSloWxe+5io3yeYmEBTNmu +gWHqUUH7HZcIvS4dhEqfD5ilKTyBvtvCGbVXINYLWxrDajXY8F4C/e65dEp5K5gs3McDnP+soJ4T +T7xnOiKfz6tv5C9qYVEpHliLpW/4DRDeA1ZD/3YgaYY5xMNr+hhXY+84Oo5KhCXSKvJShz7RPwI2 +IgjK4eUeVg6BZQl9lLWQMys7twHie8zBJRPnaR1dRhz5Fh13RxE363T2cgo2lyQwFSI4Y1hB+nLY +AOk1amjT1wFIA1LgdNF+x2H94pPF85X4TcZlXDpZVRVxBJsu/700semRYBgE3CLs7tQqIJ3OYFNs +r4D4KiV/2RKd1mZbD5MsJrDZdhphv3/e10GW9m5cmykB3kuVmx7XM+o7ZbV7VjtFGMcMtttlm533 +cZHaX3z3/sXd6y9JWtjvfG6nYSZl2ybNf6/kPuqLR6y9jh/Vnz1L8tOEOEqRh4UjDc+B6DiS5kc9 +KmIlvS2xxO3vfjO0faNIw4wJYoKRJLj9p8AC/GEY7JHO4S/DW8ZuJXnQ80Wsnl+y4JmoP6zxNOlz +HO3YZ2yEiQD850yVj3PvYBv9YT3VU6iYouUk/XyfQxuV/3b5/ttv/tP6+uznr/50Jp9Ayv8Ij5Rc +4D///qfnz759vl7XOaUxnX1eKlBGBe56judycb6fl5LRexbCAL/dwhPKospw6WIC6t9++xyH9S84 +mq+2fRUUOFXf7RDNBK3oN7pVaMhgPQO8chLNbkTSC8B/f8RA+OxzzIhaSstdp//s8vLi5ctv7754 +9+EFNl5r6/gGf44WEbwgn4OAdTrMAMNsleE1tqwD8pQSw+PPwL24LRZ3ZWAqIA+4YWg18ox8A53n +oB0siV+ICQi1nAlSGn+/oGdeMNLA1CUgpUUdFFM5LgKPwWV52bIE6aH6xUZQtIcMdlYfgXcxSg+L +DNedV1cVGFoSYA5OJkZ5W70HHi/gDHqwIRRpG5ZYBEi5kQR0ObrewRrpj76qsCRFZlNcrH1VAyYj +8UqF5s50qbOOvK+pz0VG7j0M9mA9YP4QN24lSeMcvPSQXQhnsyEcHn+ORUgUFh02jU4ygnCvXsnJ +6WhICeP1jcmALehcFlveeO4jLDaR6BJZdE5f+OjLls6jyzLykqLOCHP3ZC1wwAzCFEAZik8Cy4t+ +vQbQbg/69RSywBtm/GufSSeTgvawfv+jr1k+92FJw1vvFL7kItxiqYuT0dSs26/pmh2fJOnQwgKi +18auKLuCDahAXxSbaeigJhkZZdhKU0wQ4f0LHFqA3nYGdN+pplbdGS5lHm3EdNuoO6N4AaZahBYD +pjTbCJaYIrOFFpKJJRgFWlkMxyMHDIRfZWg5g+o3Re+jL+BRCg2dRBPwQUVUUhaAmYUMdK35AWiT +900bo5yVXtE12XnIfwmN4vIoIYXFdbYSlJRKiCahMfFbuU0KxXX4updH5xXwumrcCAXkncKjEYZP +SQmjb4RmsIQ+BWaJOZqEBlkXlXPH5phmMW6iPGQBZVWAsD5CmJQUaT00dGey8lCMjit7C3iHqJiA +wTfdtzSh6dwefZEr2V40Qo8y4s7AzTE4BMFThQVMIu5hgZ0Ca5UORtkBcNDhBZ5ljhVzsa1bfzYb +wGPPsDh9QSFBzBMsYhWw6tHJuCxGNdlkBALxIkBhf6yrlWWQgh5sZZl5ocoJAgZLW9qCJSMEUhFL +OHMwJrIgA7QyYwANlDHbSNE6iEZJrTELwTdlL7QIumToPdQlCZGnRUipAZNuMq5YQxTktxpkSRtI +i7560RXVOWPthKuyZYU0ogyF03EtfuFSgnTio3DrZjpnJhFuI/Y1y/QSVrOQDpIC6aCRvKoxepHe +Qh56MD096b5s1hg9qVnXLQfGb2LvzkHpJIqIAiEsOiEAwRBVzTezfrGlqB+AYuuitJnz4pVmndoc +gI+FM6gEHBSltlb7Th6b8ZbApySEzMyyKx4rkQh+lmYmE8JdUSUisRpTMF3AuLQg3WPYUJAe0Zlx +0A4inuLpGgcDfVJ7g048CBBPQvB+q772HrJfBG6bM5y74kS6LoWNphL4lCkPtgTrAcWZsKuG21Ta +igCBt6USBdhw6EyoSyezgA4UASP6BOZcVUoXUN8osdX+7Rq5ZWJuzGOiUyzcNvLWLokPGfL64661 +CTSnDE70i4IqWxyNXOk1K8vB8iHaAXRcqrEiJixpH1Wbi0lYFJgQZlokQ9eGbh59A3k846qGeN8/ +ntdcOGtUUgmt9KZCZ07VLfrNqCcgcrgtWFRGfzrD3AT52wE8+gxBS9QFQ650Z9AlOF1b74QQnFEH +HWE5RR2JrQ5mo9bWKce1WW/e/+jzw8NrqnsF70OfIYidkQXcKtyELtnzt51WtXlabLtUM91J35u+ +8LGn1CgxRNk38rc7g4vTILOXBIHAPWKR9Sli6zbkSdkP4pcXDeCYYMj8C31K0quJ6ibKKwC7dTIw +NegAVPOsEq02bZwMp6KHAND76NSwSmkYgm1+lbQADE31k1hkYB6tFd2E3ZcE8K60kDdRGpsxVCrT +HgIxrYDfhb416cGBODdLsBXGGeYgVGkcl4UourbRZux4qG1gEIL0Whn/Mq6YBLg41W2iMYgKJllT +SyJnVnmqRwehKlNoqCNw4SNL3BINatl/Dd4m6F1cMtHZBvs7iFEPQKfYXURnAphyAGRdtXcbkjkR +A2uEACSrRlATgwDBiFajx3nXe1jMEmmJX4aOS2cOs8yjQrdhklcl4Q0Mx2LDKh6cNu6SqzlhWMXY +b2ZnhfUQi/W8sG2NNRua7qoq7sYi55a5Jf7ZuFtu5hFrIgCyuZy7VwFbRkWuW0LqPSRT5JXGsAfh +HagUZAVGjHAz22zmtwU4rJ8aPEDI8jowfZLu7BoUGFNRVWEZMKke1sybXIhBdWVZng== + + + urABw3MAGlQqRcNF3SuEMiay6rAEnapBvNcq6EZB6XRprgqwmg4Tc7HtA0ygqQZd2byro0gCEyUK +cBHciIZo+8e3FpQcFu1hWB+xyGpiTza/Cm1R64HKR/Ccka3K3LJFGxzzIYAQB2SUewPiCWdRpW1b +ZzPvhRikaVR0eTZOKi6/V20HHfHSwUj7lHnGPKQ7zxNvSWI2CozB2CvCfVMZHK1xrotq+KUVAXb7 +Fc0C66DmoPJERguwZdFV6J12N4TLnbU19qF0YhKgayqQfM4KXJzKuWaOLYDXJAMLif2KbeHDyIxE +9NgxMAfd0i0UkzGYwlbUTb14pVvg+64zRxQ4DLSVJCWVBUc0LuicC4PoMV3IsZ+8oVGl9qQit2Ge +jcYrBk8RwHNVIg+iNrUei0H+4FR20frz3h2Fn1o8mc+SM7Cpu6UIo0CRqs7ZxZnPFZsWM5V9VfHb +eqdiP++1kEfXc7ZTvFOwiszMokRENi4wA73MEc1c5r0SauzyPQcNQTbFUddjsQSyIjmqlUcmoWHJ +mf94kfgcAoXDZTwhcGyV/st0wep0HSUkh0Bjq0F1q8jhUQZisOqgPWi8KnPgUYDRyEPE7A9PCbjj +mxp6ZUnqQUb1y1zFJDEEmNXHlmtSBjNV1BpW0FHmm5nvtGXQ9cWwRf7isiqVaH8ejozssZ0j8IYQ +1aRH3cqm7prJ7uKUETdlNcTXTkuC7oQlh54AzQlLpD8bwaMvbzTlHIaY+vJiDYCk8xFnJzYOCvSq +W0dzxeE+M2WzYrRIGzuxBVBp8Po6n5N1ux7DD8DOOhclpnGnFk80bxwJxFuzhGyFfQ3qHtn388gk +B5rcoPWSJXTH8GBe0MruNAaq7xgPf5NZUxcPyoVGH0kcH7gHp+7gyjKN28ZFnXQU3uKGQbUvsBNz +/77qP/Vc8uQQvPCRIe5XHG+t2tpXC9s0tLd0v8dBJBRKQWd9q7AB0gqf7eK97RbrwFtiRGhDB6RZ +M1zMh4a8QkVCyqKVoN6k2hYWyu09pKbWd+Q0jJYZz6yRVBHH2XqVKK50kDX4jshtqrE2pCoLVIn9 +joVx1HNBnTEfb1V9TeSAMklAWYSCM9+0B6dmnGqi0LJU5Zzk/pEeYMdpB0uI6kLo7sMi+jwAbSuk +OHw9JvWAFnG2AlDlfRZG1VAfsHBv7BPoVlxma4y/X83ci0kxSxuwWvjBOsimHJDLx1DbFSulsGxh +V4wfeF1zoHM/aFDWsQbkM1vvTAga5cW3ia9CxBa/qzY3UE1SJypJu1uFdz3d6LEOY8viOG+4bYU+ +KMouHVc2jaVttTlj1UNlqa1pKkdryIzV85s5Lg/A1NQjtWARH96sWbzkmV32B9vERhDiHqTGpmkV +9tQjsHSnPC6H9RCC0uSSXZLGPqj/OylvoIoK+i5UFw86i2L6DZmmMjAzMlVSQstmIYT1LNImBIBc +a/FqNUpICYEke8QuUNcCwrVj9IhGYZF+Kbp/mhOYmoiZXfnyfW8JbplD/LfKvBcLThubBdkTLRLE +mj0CuwK1YAD+oD30cAwJWes5O2XgYjYhsDRzCS38tniuwWoqk3lQabM45XuB82aOA5sTIPk+rAen +6Vbil0ZYXx/JdKgL5oPoStaQ+veL1yhlY/8VCcGe2aUrSTnTuwg/jcAyYJbgdLTi4ZGkp6lofXQ1 +oww+JJisqRnHGUV3L9Fek06qOoipFN2050cee11WmRaZT/EwvAVdTFF2K3mY1bh30QmsmG+ghGA0 +Ri4SM3dDkcY9m4aEt/SwqON26ABXq1rQuzI1VD53yYvJ1hACU7McK4v5ILyvvPgBqLHlOIq+TUDL +ZiJT1Hoog+fEcWOwA4LKBRtDGyLQ3bFNPZjD27N3sNJJmKyu4ta0WzrPLoRejdCxZw1jS2Yp9SAu +3arGNwK7r0vTigRuTFpiZwh0Xj0vib2D+K5myRKpT6KxDiA4y/a2Zq6bWIoA1YuO+kBTfuEcp45W +ixwgEIOJOuPkEgM9UENWjbct1oO35J1qiwlAbwpYZP8iAtWvUJkRWg9ilQFpot2obTUfgOKoPNhm +eULGiwGai+Xhsbg9Mi+H2TDG3FS+I1ydt5X9qbe6PpqoAANOSqZdxxfHQSUPgMAoK8N2CuxQ7RdV +91uFLxo+aSppxNknmmyI2m+0jGjz2lfy4Wv8hDyutwrv+Yse5SQDKaeDG/tkA7bYhYWcKpmG5gur +OogunZUes9G+uOzl+2lQ4pJ8H7TTrH5WCa8jMJjJjRcl9gFI/qMll9CgvBkJQXlTd4j2DO4J23x0 +izAxQTM6MFvhTuFZJa+3NB6aqFf3NflSbo908wMMVF3RQKmoO9tAgeIZLE5nGrztQSe6XjIHLFBk +XUYaMQY1rBGpeMz3bOE3A3hsIemcxTwAiRgwuDOWYDnjZGXdKlxJGRX8NsJN/C3K8BzWMFSpmliT +2b/x0eeELpkimKTdLHOKzFoITrmgzKmb5LVVLoHLQNCGhe30aCHy1GSySSUsNPbGd8QjTj2oMoCW +tnw/4Ikky8LjjYxAb/4GzourVH+3RX1TthHEQekk85iBJPuESwqrRkNb6RHNVOtgcGS0cLaFiU0+ +weKjr1PBCJcaEZ30qiV7lC7Nqm32rjI5jD8pq+qZ2pVKr3YenLQD8zss7G1ydYgekYln39cMgdy1 +ispnKkVTYMPENTahqjkTpAeAL1GDxcJx3RjtairSK2f78RiAKnsPTQLWGG5y+rrUA/yFZ+bBgM2K +Rlc19xDhXeOR6Hz1UmlLgMynqG6zapk5WwduiMRJGAyBPemUuDQCewpTtsR2gWdz4STyG2APmt3Z +dSMCqpzu3pbqw7lrqmRKigACvZiwVcMrCKSIWjWvm/XQzCOYEmvrAOxTk9w0BJJ1wi2XoYNsMY0m +1qcHXhIs/4Kjcwi0UDXpitJBpGQk/j4uGrNMDxvMjPss2E1s8fF0+fxO9XnIyV/Mv4DwRVR7dGeY +cuRR894cdahe9DIZRWSstyGO7tR/iWC1zcfTZTWgq0S1P88nq7DjaIewgiCiJ86WcVsAPGocqaZF +x1DtJJrjkx34plS01+KrThkLa3XNXPYV9WD6PidwY0sfLeQu7IvhPfsHLwqVxlSOuZovgIEtO2Pi +5hPh4l4mwMicBSnPFd6FFbH4BmA3GchtJj1405bRYWqe52Ch1e76CIH3LhNVYIoIc0rF75tOKnll +lY44q5uc2AMD1UwTS1J6cLhZhOmTWswTXlRsAsUmWXXNrKqc4iwrXDm4zlMLrOt6PHSi4tTnkgWo +UWv6s9EIwIUNJOb9WEDNIgWgxzYFip7cVSPeFORKqXZUU/os6utp1YBEQTKA1HoPtgpZ3AM+W+JN +ZQEswKpsyBdT4XFfBrXn1BWAjZeyIXOfzc8JQ0C96qCsAduJQMak1VtlRVWGXDV5HVmnN4e4JOWR +WFF7inwcXS6ZN4DORt6azLUDa00Ei0MEqYtGTuqBCYXnL7WHxcRV7j4rMktuFaypM4N9nrg+yGo1 +sKVf/A6Z2Fhi8ZjXtWgPGqFDJca61TRCtDC7eZ2GTDeiqVuFp6V7BIp2Yp5Cus5C1CM8hCBDyKWr +Ut4pgyiL89JBV1QkyELjdcYkfXdfoOmnnF1OxSGwaERH1xhVpTHXddBT1KwLi7bsSR9kc8w0rUdX +5bJ5eER3ujO4BLKqpqDQUid1bSivPLr+2eRW1YO71K3kylbTCvZjeOxZ7tjunYI1moK8S3hu0fid +5AQisEf3+7kYoH/QFY1jRmsbLB1VlIMZ13/cVdyaDGY3NdtXavSMsCBUfnyfqMK3aazmxdhrUyLY +GC1Y0KGOYeH161Qhn1g9j40jCm1U9e8YjkocIzW3Cu4bnCTf7byXx3ZdBBRYSZVOXUmCFnP6anYA +wc0h4Vxm/QfTztSIlTjGttvHxm6MZo1nPql3p/AiJ2c5f/DWwHZAqzQWywAE9Uy1TOEY+44fe+i5 +p5IUMqx55KtTtlIQodLpYMsQyMwBcx68zj3BkOBqAZVFJWvOQ+611FSoeDBTzoB1XS9nszAruy+s +39qZqFwrwXDXdR0xmHAQkouPpyWLTkPTXCpHTQ46Z81oq3wBh+Cnu445dQCBIEJ1vybNPoC9zm5d +Ufko9b9q+EvlCJZIlNQqmJhvw5eTMhF1/2PBhGIe48DqV/Z8txjjMJmNkNGdzj7UZtG67Mj1K3Kd +9ZC8jE76HrdNGPn1Jp9YtcArWuT0TeX6NAisdnKEbsBRzQDgRVVLSSGpCdd/2axuKmyhEdBSUBAM +Oo+mmFHaWcXreiQfC+w+l7wAi5no/ehETf3kSZVEYmq783SlaG+qHKO0DnIyHU06mHUa7URaZYeC +fR/QISQQ+WwpAsdjTYVxuHLhFfMdAHxJZiJkQWLgyL8QAu/HFAZHEJGM9OD5kLCoy2wX4t09TgMr +GiRL3vwqlbe59bCoga0qWnJ8/FWI2ymQ7hgSzdN8xVggumoYRpVwvFJJLZTs9fvDqZbQ11EKm/LU +xFeS8EIlE1esYsaV0Y+nbbgDgJO5Iiq8s++rS6NyOic2LKYOU7ZwH4FZsEXcSKlnXRQWkTJXyYus +HJO0HmB3q9njWJ2KXHiQ24oDJtYBCZZmXmOx1N1iFnscLViN/EXyCBqBlt4B0IGsGDfMQzmJJG6P +2JP3RZ2Xr2eLYFRK3BXplYY+JCWMRJqar5JOWCOlTGtowJmPEC+GsPN8lLUhwGaVEMQZjD30bCw8 +2997WJzyL8+i0g9nzpx835tDvHB+lXzfD/ak92w3Rjd4A5tsc6xyZtlCFGOUHrAcmxqDGkxHYDJZ +KvuOgNqSjn9LDw6GXtTby4ehCZhsycWgxescFosy9kRCvKpOfRYU2ZW3ZXXAD0PonjjK87JJhKr0 +MYQ/QwONXuEqB/DyOatQEkQ6horJd+oJcDY5LFWOHj9eel/MVYRuy2weDXbDhmQGQjVrG8wLS37s +KYYI9pYGxEdgEVbN4Kc4sQCbpq0PofeAZ5FUE2QLDO/lk/oMhc80iMrYz5T11KQTumg/2ZY8eweo +Lrj5OPhYDAI78ZExcVDcpKT+F3VThjLY5Ulc0aGoFVPY3rIOAI0q68VJHsrA9tWJRUDNKOvlbnA5 +9TSyHFC67T1rPlZVF181V5aFhwMyuqwZeq6M9KA2pBq+AdMoLO9KaX1hrxh3kPLQQTV4xdwGI9X1 +CSUhd9ubcsKIOraiE3Z8C8HJanNoYAo3vTcHqAw3okRTGyJb1S3ahaahV84cwXvsFiuCwicPcBv3 +pI/QE1Ki5xQB7oHP8iDn81biS6cQdEtkPtMp3w/DnnKVXa10F4N3wwozMEY98+OSH9hpCarsU+yc +2byedC586kyBuntM0EU852zH+DnSgJZLr/SWjlsz0ms/f2ZnkQhuxCQbAmF20EJOiBPQclt7KAmv +vmx69lF9ogCMdqxsyUk7KGEfD0OwHhuQDGGEpbToASfOH+VOsyY52xk8FKE9G1c9Kg== + + + EZvoLqPDmSyrNW8l8x2QJsO7Iabac6wsMWRtyplqC041LqsGgm3NNagZpfh9b52KKofXfNuwaMGt +g+GASRX6bMyiGIvC7gDYPUqhMyaALy3aurNGS401kKQeb9TaNPfY8nxQxbOT2opEUK7IVyPinokD +gNX1yGg3S1axD4noE1CzxqozBQ/EvWYIWnk/1PG85avnpHpftJI1smtQxY26SWtqsX+/ODfupltV +tF2xkiheLAM8Qmd55ZwRjcq+5mLKEUczFywCSfk0t2bHFE3UKUIjZAmp9AyieeH1oUFV7cGAT1lr +axQ9h4v2GdgmalnwEXICWnCfDnVbB+rpKpwDzUA6YcrjbaKYyzld4ZeWn5XKUHRPrddUBsJZlBxk +jCIntUAIGapDwUB2tSRMN7DQc+FEObzBPgbzbZlMTM1Ssq2kHVnVTmlHEtwRGIpm+/WzAwhXZahb +fxkrqMatQddYsvC76jKMoUrjnlyI1voSVV8QkmwcKqgbdzReLxrURAli0AGwa9dVorZYndIUyKXb +lNmN5eW6AEanQ6rG+YK6Lao3EzY19XusPU2P7cpKeSyWiRv6TuF2ckIrYTNYT1RgSbPQOhzUEpWG +IvgSepcswU6CJvsX/gBT2oyxTykpV/e6DzNXgJYlCvXk1sLdvSpNIN2aXJDzjjSGoIZKCMPu3qPv +cV2T2Qhc5OSdeQBdMJ8Wq1y5WN5P6RRehmj6kGyYi1lUWqeGe+1VT4ICN0N4dP9rGVJTc49e4HyC +8ihi9+bmbD1S3TNA9/089nJUFG0aUEcfBg+0eq4RQ2ByNt0qXLNzq1YhA3nLbkFuzIc4AOarMrde +hAzhJanjkfYtAiNnXBNQj9/VaKfnGivpBx3CYn7lJopWqZapivndxPRKVkWzjvpj6Vm1lYtZ8NRK +rzZZKf8eYRGj6uKllMqZlepeqZs09uRrgCtZNfaf3SpchFjjLYWwMc1a8/6pHlkSnPVDHAjW4FQa +unVW36GaDohALxa66tFYtS1qRt2g/RQ8cqhjSHVxvePFnFFBFDss5Zc1cyNwAa9KF9Soy5l2l/QM +8Kw9F8ljLMtwwlHqmyKwO2Zzzw2gcoIaZBPrBysE1jCgHTdIs6y7yla+8IJmFnalEq7atumgOGsP +YTbSwUuGZfyqtJXCPgjTg8lNHcZY6zIEFdfF0qGGcpeoqS/KzfohBVVYsaWphb1MB76tswpd3qG6 +YOHqRzwHb1uKSNhwoHZ/Zel2q3A9x9HMW4kIs6NgUj2R1zcrJfS0bFwJ61mzcAi96jtfVHvCmIV5 +9Dt+kRiCqpwaUym9GkvV+hdEpZZ9RfmgnXp7bW899EMbwKrS6HEJqgqoQsCxtwR2IM2dWWvPycK6 +ZObidhyswO97K1krJ8zwTZbYSbmUNrBe4UTXqPTSDhhkYcu5dIdl5XHZEILlPUlohAqueWXIcuqr +ePNIYAda6wLhHZEa5J6zHN8dcr3QI4JL070GS5k7K/N2tiOdKcTbArNLH4C9wFF2eqSTOKQdcGni +QTnWQ2cW3tkpHSwZaAWsyJPEnLsnl+rpkpKHpGVvPkwshpRUVqmBWjInPHEHSjSYwmGWUvVDB1ao +poo/DusNSd3Gyr8J0NyloWfclTIo43qYpcgpnJX06Ra2EIJ0IHKPmd5iKXtYrcorM1U81MWqC2G2 +GLMykPrd+Rz6OVOAW/AqBBP6jmvZiiznjAcsheSaxCUXsQOrt2I1lWlfZbZwYsk1Q63DqezSPJOd +KvLYWhnWTFg09NFQWNwpPDs9yURZubfWXhykVavgVay1FFT7ELc0FmWSuGUbw4a1n8psHIUWZcca +q3hFoDfdoVm6CjVmsdvsgCwCk+5O4MrpbDq5x0ZfW+xce+NjFYy+5uwgWNMD8wRcnCo9bM4jLGlD +uk1cJokV3VSwBsdJg1j7aVHUiSeo9qBz4xCRdFDOe4ic6+YgTKu/VC1vVGv3/1dO+pUOejWCNlqN +WAHLqRrM9XRosSX9o1kSbE3mZ6hjYALhxfRoiRZiBS7hrpICya/qWlfryYwIX2rda+L53BQnYkMG +Ds2Yi5V5JHRUS8KU1EUsxiWu42ZJvrVYDLxRHqXhuNPXuEnqUBAjiRcDq60Yx7BpI7qq8sPV8seo +uVNZUsSxNIsdegGm8K/aVI+3VL0+BIGARMvwYGWvEtWolt9JBcvdyFmipmWkqAenWSlZkdNQBdTh +NvPMt8Vq9FauV4BAb2nujUmGgd1Q6KV1EC56d7NaIVixUZhf08rhtYW+B0IPl2FdFeH/zTyJDa0M +o9QqffZMtaGaAHWrunyRuC6WzVLDLnt7f4/hdZLEprqNVdHDMYkF27R24frmG5u7VFpxiyLOhKTG +O/ec5tF5mbMSg42qUxor0/AIgCVhFdmWaLsS3DrBy7DjRRm2MAeAaWnJZg7P1vPx25jRvxvZo1r8 +v37e9FbIXz+nK5Wu3365vlDpYRctxe1FS3yt7fy6JdA85xcuBaro35ga7taglNnDx2wGSWkPwa/d +7nu61UuWeEh01RIetcBLHfF2K7qGy8PgHOrieLPj5xTAYWM2YUVmu96I8zjo9WjIsxxBRRZTVhIq +yuJMLMiokFHb91+qxyNQCmAqyRojhdMktS1vIYEFZrW22wQ8VishBkfuilQKF9sR1ZL0LwSq2KVC +xNIBpau9VH/HklA0IdzLgfcSRUMnoMS2ARjxBkcCYiTnpdpwnN2NEyPj8XOKcnCtHwSqchvrMAXM +EXqpgTgO2uFoNY8PsziyY5i6OwMa7Lw0mc9KcQcBbX7pl67sYZgjlw0B5cRe0JsjDImHgWrigHOJ +UfphzaXeGAY6HZVGpflq/HdHNS9xvyK9JbwYDa93RmpbEVLlqkF3GixKjdaBPF7cbYrW1lv2AkY4 ++F3VU3n9l+qsl3HVoMWNUR3sL9MZGCnpmzYUVuXEpqkMnC+cUPZ7sUmSUjmqNt6sWwWKw/aleRoE +Xq1xwpwgnm/uOUFNF6JilkMZSCTL3PoYMJ9Gx1t92aywTmK7wjrn7QoPWO8rjMVTF69pWOtlswXe +MJTtNPqdReOci0Z1BuQ0W7YVJiniZZtV4bmvcV+gakQyLmZJfrvEVJ26L3FV2kP9Q9aCNh4xrLbw +WqwGpsCX6inggqGbxlwXm4Ditqcq8LRbCWjUS4cSAoP19CNmh5JTDNSPHstzOgeBvdRtJbgd2hqJ +tCTVbAdKUBzsKKTqJZsrImt2uG+gxo7w/ZobgcB04N+KpDIjEELXjkD6pphun2N7bboxp1t4t933 +XKCjYUpjU2o8RrpTOp9tiCkij2J9sjy7lZws8ED8MzYy5zcz5jTn8Z1GhcZkeTs9RzsUv6Z8SZs7 +skuO7ajp3ptv1Nmunu7/Ha/YspDEQeitHtKSZYeXaC/z3Jj1BVaa0C7ChsYA2GeE8CpbPev2xSM0 +rEVjUrKMVYBb8hgaoxYhjbMxhYEDpDGOvucMGwLpTGRgNn0hd4veGUDLeM8y3a+6oxDhVjsK6Vxs +yhsfxEeFmqZ0Nxvusak9iI++fAC2TrPxY/J0WPO8YpdGH9loeaCjPv5Oc4G3s2yGTp9Bw0MDIec9 +r8RCib5stkJeFs64222FZkklRYv+pNbzUPE+HRlrGTW5JqeFEhbjFFaJWR5SkZ8vgWb2aQPoX6cs +dA7HWcuu52DJwrRZQpvAbiPwdE1X0lUoJlqGbdfXYL9eJ2ThfkNvF7fv5xmTOMJPprxnyqV2HG3L +6EYkTMljRkdHSG5KnjM6nuLwGMKnS7Nbxt3qrjj4lFdOueqUBR8RhAOFDmu7ImZb3JHsTVqMW2Rg +96v9lGW0tjjY7bJZXoSFst+7gRFmmrDuHd9labB3NVtz02fy4ojRyfomMb3HDhBh1jaqOlEN6EcN +LqYBLsQUg+3UZJmEw/YNq8O747YOpexMnUaO9nC25RW2vttFOynINjxossDFLJ09WzvCAqfscspY +d0x4z5s7DqYEMiWlY3Q3JdIpOc+weAzj07XZreNkeQexM2XxM1kwkRpHDdliIQo3hsrwqJTBVe9e +kb4OYLVNQtfmSy/MKrPY7j7tYdype0sWNwSd17/VQIsiJ5oDHm98kYEFe5f67rAD30VvFU5OeQMy +sdRv+qhGdx2Ldfg+sUYrrZ/Mn6CHKUAnkpQXWC69KTyxH1+cWeNdjksM5s1qehOjuikGQkijH2fF +FwZLduQhamtFW8eO8P2in5beGsL1ww2MhB45H+bt3A9dk11lHeR8PSa48Mwcn68V+nCWX4wpR5zi +PNBHmPD3OBPf2LRfgbImMbdY9oIaS83Qm5uRs5TiMQ4vhOMszDTdD1M8HkV6GAjXS2LHaiUD1nPe +rXAcKuevl9jVpo6rxpEVb4jcr9oDJHhl2Sfr2/dEM41j2D3VxNS40Ubde9yUanevt+92/ycWqJv1 +Per7324R+vKteoy1Pk3iM0mf08mg3lgFrzfOzjBbwqhjkpamFHEuRXFbJqFzf4AkZY6yQ3RnPlM2 +NedoU+Y3ZZM7lrrdSBJKN49Q817ZidpZmEldpA89XIUXgUatrhj7Fs9tyBLRgiJTupqh8RjK8biQ +01L2WkwLT1c5PapDx1rNWNUsnl7FFC3YqIUw1Gc+UJIcK9htxcT1/uzsGiBb2XvlMud0AjRLIVSN +akQMz7o4AE0PhD1a143RarY6RYVvDpuJoqN7mUNAeDfwuJVF1cHsP8llMQpLxelOtHBXbiuXY7Pv +d5PIKCxh8vLWpYS3JvudLo5RFtL1JLK3dLCoLqsgmsiwIeAWRg1yiM2ptOshvIHx9sjN+PUhyhOZ +ea9ULEy5Sy6vKMOGv7WzdLbGe6RnhY+8B4EWDVHmY8A19xnb4ol2xkzueul2vU9xnx0edmHPjrMJ +bo+swmzBJuu6o4A9YQxhuVnUdBpePRaLncVtZ/HdaVRvTRxpdQR0FyzcRxYnEceB5qcUNqfFCd0e +U+P7xpXMmLu1spsw5VbVnkVxRgnFehZG4smYeYwyRBiw7/2qQTcSp5y+WNFxWmyLjTQvTU0wExnL +0qx20nB4cZ0joMRhPGYGq+P5vBWP0pD+yMyMjrb4OxXa2U72brdnZa4z7B3D9GxVslZqG5evmBdn +GOvn5PePbTOt2fx3qDrsMDjwMszZSnh8CHsoeqhB7hHkPpopAcqf2ujOypjug7f3pNJdI1OJNGFm +x/jejEEeZaYzzjvl0XuGPmH0A3lNaXlG9LP9cTR3QLwPlAFRc08e4HMOK+63cOlXYlJSnvhYDsc6 +34Mrsa4zQ5qG/HoSSXahU9eQcCK32KxTUzIfMFilseQJp28ba00CU6Uaoy2GBM1f/nz00Wmms9HX +IiKgGVfuuwmxoFa6RSnwBch6jdn7kmVsWW6liE5sOAIuO02gDRfZb9JO+r0ySGWlWY6K5rgMuSxJ +rf9p3gt6bCOjl0oCsdLoqawpAptTA3BDNCf1gG2SzpCesk3omab+nEgT2lLjlGynww== + + + PTa1PQZOIWubUDTPPJpkKR31j1WLEy/Mw80/xveTIC21xMdo0D/m8QA8koedXCpKt3ihdRoCvUrj +i/mR+m4YgD1e78az0R0c2EC0XPae76JypCcOedsiqySjxWT2kJDkbMWG1KXQvR89XyZsvB/6ttiV +cD80nsTxBbgL5MuULU4rexLgtedq9AyqYatvlu2UQN9NZJew1cc8x88cl1O8zxZot5bbJV6lNE1T +vqbJYUcSyeZJZ7P0tFlO1HqJh/ypWabVPi1rt8Qr8p3SyZyiZuT3++dTPm8hi71QmIqPY7JmKpim +Imwn7rYruiLs6b6fcogj3GTKeaY8arozjm6j2Ybb786dEFyJ+KkkncvcmYD+/fNHy2VOj5LLjHXo +WM2mRHhJKI8DaMhbxhugOoi/OgWOX/74nGZyqlHaENmxbozSeQKHc++8HqF2DPPmEcMDIp4N0MDF +Jw/KahJVwEH53Zyzo8OVTwaQriC3KeQo5S9I1suJSiw8QeclWNh2MVO4wNAol5NeljtKcCwxGFRf +GqQ9ugZTzqpHKcHTkZxVSjDuArpaaJMSPMBXvgfytSk8LFZlhQvJjf6APdKPqvVYrIM7XaUEZy2d +NLJMqhHAbb2dsCiLvmvFyTGI4piheCv1SKMpIgkkvlSKqup4YL+N5yz5wi5MeaNTt7eqVfOBeMrb +k/rusMJcTIVSEpMJHsEjJc1ZekbSmzo5wy5VWWI+PsO5eNmvV2idqDjAV/Kvr9CYSG0rRCJJSt5u +0X5C01vNY5QaUQp/UbqjHOJCxwrVxEdgqT0jj3cFzriXRcWMrcrJWd7ujOKFDpksYzzTU7h6WU58 +HoqzpmQTRd1ECjSfAVcGGBt3FPf8rI7JdarfCvM9kDisEiZdSnWbvp7VyHKPtBN61p5SDMMTspoR +4J5aD6pMbzBvVLxfpvmCziZybNZz/GxxOUHxkHM43wmzPTPdYEfYTCeUVVpqTnK94SotVbg0Aal6 +GdMk37SDwOFmIGjMBYQoI8jZ4ZysReEIrqUOIh/T5OwheVswWhXgFsFDY5QE0jh3wu5EvErj2hP3 +FsN9Iww7ZkDEDmunzOf9ZjQc7zfudIfv2MFB2cEG9bfa8WSdpis6m8ixWT+MT7x8CCrv4VRHOW4Y +VnnkB3jhiHMDnHvmy38ZGBXI9dcY6IeCWVoLfBnLXWGFJKmIsXDZaATCSJl50J3Ky5rYNllHA4bG +pMGBYHt63kDawzx2kz7FMXebxjjmfoNNd+Ju2x60gw3ibDtPsDxdj9k8jk16jp4tKncYXmUvznnC +jHtMWc2ReGmzAhoLO73uVD2VMK7nonpGP4tvVRNvZGp6VUi0asYD9awS91ZU1ZPWsGa4XD63cDEY +fldMkj7ltQT3briHU5xqtwvujkx6KKm2feN0aNtpTGY35K3NN9hsK+5HfDiRM14sOSBwuTPLsNc7 +nmD5s10fnpLVT8UNoiUVA5aFFpjT6vR6x7wAX+o8dH5D414eA92mbss9EtsQOwyNiVtUS36RDKcs +9WJTsmqC0XwN+zkfTmRubYn47gjeDD+TF/ahJavfM0wjTiUxZzNZAeLVHvExa7W63V7aDvhwdN8u +UrzTjhMThL5suUHDcMpYF4nMRLtNUKsBApFKsRa7AhdvDuCj8omPyh92L789le6zI0TLnFt3a8VE +qUgAZ6XI+bjVUCVpbD2vXrZ7T3W3aipraepktdzmxHyM8o9sk9l+2kz56BJmqSy8yVWhrHryIgyR +QXQ0RY5K9RgiFbVIEjEdJFDVrDzsuEmN0ipeJg4Ciiek4QkVb2E5q3hbpbwquQDoLkPzerA2h6e0 +emJwcpppEFUoqV9gzJQYfAgDEru3oacDrFwTZHRsReM6SJu0zP0YzLQFXiWR6AJvYqRJb28cG2dv +CB4yobfLdjLhbYuJ7pXaIm2C2/0yyPLsnFW2PDvH1swBNvXbrBcojQe0J+6gne9o4lOihdv5lIZV +ntLDhHaOCcBqGhFlAjjlL+gKqryYDciaM3OruUKwfpt6LJqUwUBg7fcZliR1d6lx0oqDokpicphz +mvztZbeusxkSFz+T1AenVX47kWmKxEiQPXNkRbzadKRyY9vjliDgYS0OdlkidQcTxximsaFjzBIf ++NJ6hBvL0QLKCKw1aUBnswynNPodwu7UkVcN40tatKAD1/lCoF76cmzNsE4X6U4El+IjMDbKEiZg +loRsLB3Ut7AM+HOKQnBxJJydlpZZpBA1wrRAIuKM6hEjMOR+JMPLlScIBzmqmgVW0vFJ0lCscE/V +3Z21xtwwMMw/zFrBAmmXGdGQqjiTEzPmdIyRTVneUf44ZaZTtrvj0RPevVFG9lQ9I/8jO2Wyqaa7 +b7pVKV72UZJ4shRHl22/wlNK2JONkNNOPNvW3MvyudQ/piLM9IkHUxQhbb8N74xWd3x2zpFnfOMo +k5mxoz3vsijjZn/aPtxv5tmuP8ohpuxkxnimXOqIIqhlazcpT+hLolKaKI6rJH+UKjVQKfIkt6Rh +lKo4AZLb1Fgil1zFICOldIuikKXUO8YZl36OiW8ZoGHobW/m5FqnDFEdfA1p1kVLHQQR3T3OOWgE +bWoJWlxssE16CMsOHlB5MQ51cUDnaFwsSq34MWXG7mvjzBpxIe7wftLtuQvk2Srto36z8OA+lNhD +jOvFM21uv9JTmphO5Nis5/g5gcx9RHISupyGOY/6PZ15+Rdmz+b35OKiHK9PmuHMVVM5si+aMV6O +HSV6PuRiL1yUksFydgCAVLAQYXq5MCUURKHfivMSva9IgVUMJw61//CAB3ubKZElWlVbslcp6UXi +KKs45ZAJ02Oazm4tHqKfwcIoQ8gurEzQHt+L3c8Sh8aTQIwAd5EYxz2Yci77lpIczNHSg7CWK7Jb +uFOa3m4iu5jvMOsZfo7gco736QrtltOWeRMMtmXeB46nEeZ5NHoauZ7HuCeB2fUi9yDuPNy7iw3v +Flmwu4sZD5Qyo6kpAbKetBMGd6rT7yXHVMbsBdJBN+5mP94qfLZ3p5t8xhCmzGPKZqakfWwfzHfM +bnvtJF3bOAUn4nIiV6cyeJUV9O0xAznwEbWecXOnDoRkRTyHTJyaxzsEpTZ6tczp1qzQuLXEEANp +Uqa7cTHaBMor6VoMZEcZYiYmK3Hro/g2fCyDNOTbTkmcwrx7zh/dX8gMQtXKKDedYQxZ66hjdiCP +YOGMXVPd+CYqhJdmKihfJp+ozGVRQU1HdwlIQ3up2ORLo6gGhtxdifdEyI3AuM9FPO3wflT5w6ME +dGUi7jZUcsT2CGRccMg71+GGBe+ixMc14Rz9MlS0nSLscv4V/S9lEdQMC4SuFoY3Zyowpg9I6flg +V/zgySetNaxz4AEvM9pBJWVh16mEn7ixxOnw6LO3wxOrGZ8IcVB9d6YcmcWdwoHhOF34RQvdc71p +BC6tKTAzQVYxuA5q3NGVfkQlzhLWUa0PVQK9mpWQi12kkew+hDzHDpb21pK3I3YwjbvEDYb1QrvN +WmymfELG7lfZyGdKElPiWROaJZRs0GbzmOJ4uhr7eZyY9AQ9O1za2Naot6FNiHhK7rO9ccQ2K6xM +cDy/LRpjo1wFZhxi8rOkX5xwT708AW8ilzvLVpPY0c+tvm9PajOa3NHv4ch4b0/o4UnOyCMTp1uO +71Q/r447r1wu5Nb0dp6K77FmyegcLh1axHbezjhYqez1lAM7vvnSOz4jnaNE3CkOqmbObrgnYn9H +F27XiQX+J2+cDW03DUsQ2iy0Za/siWJKPbsRH4/+Vb2xAS/ADj2uqXfG4kGSpsZayHo9kbNUwVYW +v5/CAi2WPfOiC9flIojuF2hy02+wqvVZ42xINy00u2trM9xTMcN9HxYymbxwOrDNHGxuG6q0uW3p +d0blux1xODLaE9sNI/5ye1Rgm6KXAZMbT1IvvoLiVIOhdDE4A51Ual9NDvX4mdRJxap8V853YWAO +XBkjWWF4PI+4MAMG8wmUs97zZsy3J+Ltu06MMCdvRB1U67Db2LKIqO0Ey3biNsHEF/N24p7ugg0F +Ho6M9/beePtakcYFkcsc1+NKw01ULlatUag3P2arfI+FCzUzYDgtuHvfPXH2dR82uMn74niHko4s +2FXpa7QjvcU9y8brBLNenmfEOSXjHf0c5kM+inmsVE+zoCqQuIXv1AnOYyYDWGyVpndVYkhRr5dH +S4RYAp4iHvR5hNM1VxzkSxoSL1x0MssNJwwkpxiHDvrFYlgzVmO25HfrhUPoIrRE18ywywDbZtVE +MlfLqLpvt1YUnkFl+Mrk0k0+GGfFFKfVyuFtA8XV3coNty8AiYrtS1cTJEndpMNAU7yf8o7uZ3Jn +GNrN+hh6Vqg0DK+tRMPw1KKc2J7HDNWTVu0KxTtj2Ya2Qf3tGhWrTk6u6Di2Y9IDaZBDEqibI2nb +TQ6R7r6gKLpc/4ImLqNNzooyjG9jImdYcBa0XPBuX3EC6aVHVICCLetsN3T2DUPKf9bwYiPHmBjM +GhnHuzfYUoDJadIbAtl3g/ISXXPSAzbme6k8L4F0a5y86R0V3pZoTfAS2t7S+xDxjnYLJd5LwhY+ +JchbSRuEL00iOTDTZLuDT+WCtD+bLsUJE21AGnCZaJVdAcO4ZGeShd+jza4UcQtKFPzEwmlAoZpn +ksycojkcoemAxRYjUy0NC+f4cHB3uh7DwQZhFqHcMMZbhU+56JTfHmPOe05e5cYYJlW5XA43gFhz +gmCjKYmrYM62yoKgGqOzC6X2vNJ46IbUjEo4rIIb3OdmHS9SGTAq1k5QO91URjVaQ1K8C8rgNz1p +vice9cXuZ93F4gxFfPn2A8UiVXnixuKDxIrmjEy8fkscqVMRIdQiVSyx8hOfhD8qedao7xjaLdN0 +PWeLrwia77spnqcrcopZ7TjblAceY5hT7nqEDx/b+1NGMWEpcxKaqVoYkA9a9Id6snwqvsGHXPlL +vzTM8hMwCtI0MidyFa8ai0mBIoSruOHFF4SXcRVBpArFfsFUZAuB39RvJB1lcJCsoa0M9nZh+Mor +60OSyuPmv42aKrBx9kbez+wYzuoY5jRediFr6P2It7lwJKly5ijDSLPhqIG4GPY4P5xSs3be8bsj +K9e95rNXzsZ2bBozB/sRV/xqZCfcuqj3LRqVwVQV8VpavLqKXL1VuDrend3jitdThiSWRcxyA1Bh +zrBzGdbh/rfRZ9hEko/EZkA6mSYsFOmadbUaRhIGuOz76rlwHQMlQRPV0ygXvW0nfcJ7Vaqdv/d8 +l+XdPFpg+Rx7N/sRf/wy02X3eLOOp0jm6EaiG+KY1e1HfBBGvN/8lig04RQzlrJjP4c5FVnMcIL8 +I8s0XdMpAcxJZUdXNrQNvzK+tGduUy4445iPVwnA+20lgHkNADevABD1BuSUMt8JJ7I1DaBbA2VL +8bcvTkDjF7kAAB/9P8OhmRdGclfwnFZ2dqID+JAn8Y1HaTU5DH4NnIiGGwD22HemeA== + + + s36jL3xzpPM3GvdOXD2C87B96jGAnLi8ROBSUawctGqqNmb1fWdmQFkszTHoW3d960s7XjAZDVmv +nfPgu9P5Ah2rIMtXNaI6QEbgd6oN1lbFRCA/y5sN0rXzYa7VySEzqpNhc9VLN7LdZg9vrTEIEDZa +63OlM1/Ej8jnbXNd960vTehyJeeuG2rPkGKEIECuFELm6xRhnULt76KLBisfuYHd/EZJonf55jH3 +Tl4+ae/obX40zUJFkvXADn1CM6vXz1h/Gq7867U7drsk4sWseG9r9Gn0FEQMYmCORPR43y/bKDHL +CfHoHZcv4Zbs94sOMw6aar5Yn4Syz6JLdoN1wuNrKA6iw3sgmpVfpmh7dKSaWDE7YLRUChZ7UPMk +RXHc4OuCJHyiTxIzN2lgEdPiXiph8AkbnIXeVYzuUiw0D8BsesoeD2obJLzxnJANzQvecds98XRx +K8L9YnnHbUG1MXqc32LeayJxHF2Obki54wN80TXjCQltY7xNPDpJSEIgWtco1XDSEa/6fqkhBSyK +RB0sixziQD0L3SP4Nr3BEIAu+8zjSjnpIlGVH560yq7EN6UCDGvXyfmnHQ4szQeNoUgdt/PUY4KU +mwhA6EzMJgDSZbrUR5Zq3BlvgEeORgvkxmJQzF+j93aSLke5xDB6Mn8YmLhCHM02hiG7iuueIbyU +qFEzUn3wZXRmXBhzpN2D1GAF+XPmmr40BVgaK+lRaV5h4dud9xgwxDQu5A5DGjkypg0HmkNwemUL +JiknnlfreQS4fZbA60DH2mRgeMWvC7xmxdvJksb4jqbFYMq5I+rCHYyOUcuIo5KE1EFcguZv0C3K +9DY1uAHItyPTzJC8pAd1BuAckiTCoF+ArAKccA1aM36NA8sHxwPzxDMCmiAx9VQEV1G1RHj0ctgJ +jXDuGa36qjVIKV5DY1CKZDjnHBAuhT1g6UbHs0MXZzX1NjKh463IQ2XQpfKeaF3rKiIy8W125VRR +BhcCFYR8aWowXU2Nc9B7iEuy4a6uFd1gQaxt5NWfU5nuEpy8NPWrV7E2t3O8l7WsPfKSzGuyULTk +j7q/KcmcxggEqwHzTNeQG/CPakgAzcvIg0RqityoDXolJxZLWzz1ilSYJIWXSZNrjUc8HQBv/aNJ +8kA7DC2SpVi1VtSmIyqveCrhj6YmEbjRAQ4NN2aKvIHJAAwz6RCwFBQtYMJD0ZFTOyNmq+DlzBGF +PTq3uDHWQS80jyphOJYlFSN5fWQyiihqU0T9ywurMlTS0e+gPSPLJ+sfNp7d1YxVG1FNj9GzS0FG +4ThjDwQHyEGO7+9W+Y+7hD2nFAHrIp4caOyRv9n1wFR/AOCAlLBo6Uep/4J7uvFp9FCEWyVkFcmK +tYVM9zID2HFkDmGR750HAY3F5/lQCmxlYIeIdb/wle/SwaKBGr/wiXkGSjorikPxdAbHaQw0rsVZ +BjoyxJR4DiBDuYZo4Ox3mrC6EvdYUL6CkoU9YMhxvGXIwYsacVj8hliKwAoihRUTbnQ56OuRfMhH +jdIPHXovtQMf6MAMMlPhj6gpENvF2YE4YSDKscINl2z3Cns7ZeLRmONcKJBtmYqI+myRUWjIl7nj +sBxuPetA8qaQTkQh81iHjixVZLqiyuyRYOgBkVDJIwAoXPAOc0EPOjcJFbDkKXMxUQA2PhQYUL1m +8vF43jTKGpm0RhGL1wYg0tTKQOognxiKVUmxdpV1Pp5wsPiaK3ooxktiGQOdo1MCvpkHDoCF1yGI +jiE9VLlTBmfg2Q0NRNsWsjiQYJh69xhQ3KCKuRDeQ2Gjn3HjcLNXBsfMCqvLrBJTL5EzoR1uIEZN +YBtERoZ2DMMd37qAwMhXpjMeAxcTdujH5rmhq8SO0zkvWXe4xSRE6ByjhN62SKoaNOSMdJpbHb5f +MlMO8k+nIyBWCsDKGvMUB4adhWrXAsdE+deRo4YTwilPWsYWiEPgrQ/Cap3eIZ+UV8ng9MgxYlKu +f6I74jOvpd5GgldasB8JgAVFKX+f76Tw3AElQiEwS9oVvmwJjDJsSRwOJlxrGDqohVL2Iwgt4fWL +HciKpqXtULAR1ouefsF3di9cKKwiARmD7qHbCC+BICcc8F3yQfxRNzlYzpUHSeyU6RjDvwOQG2Oi +RtKRNymmgtPhJaQaDV6llMMqJZQwlumSgiY0C++WXHzKNv+j7ia9nNaf274T325i2fhH3bkMx0w4 +kqXMlfAvHN/C0DK3DUH0ACrlIOfhAtpGfDFg5guPpHE71ztcixghpF7LkOTtAKlS8x9w589WKMzi +WxTUVvZJAmI8eUNZkIizkC4nUiHtefcBNHANxOnybsW0CemV0b42zNdG+9qgXxvtn+KA+PXbty/u +Xn155tzW+dArZT7YCREXkg6wnCB9AYdh4aQaYFpyAU+H367hGa+gDFJxYOjnGHzsh90WO4dFXJBx +eZDQ0AuunoTqAA4kAFYlw6l6OLWF1SUIldzgVnh2DWCg/hc5SUBwqqFCcLQC+dto0BCIy/YSLKMS +SMAU7euRr+ciMLmibhWekbnw6zwaHgRMGK2mcSWqEjSbFrvECT0eTwqCUo3p2VJ1ieBLBT2C4Mwm +CcjdIBA2VlRgoIUCYI5cKkZ6Bv2QwSgVGRawCDsD/aK9ygphr4vUaiS49Eq8Wb6OOCMY1X+YTUCn +hvyHGmccYNWVzGxbEzwsjcblMFAUmgDdkgSYkI0SkHa9LIdUpAB4kVvNCAgMqjGQ7prjd0U0wQgI +GjtrswRPaDwSvKHNz8DStC3GzRgGxM6wAhZG/z75PQjuEY5AFL+ZR4tXXUiXKB14Wl4KIRI8c9PE +xh7DHI6Q2mZUjSYoNKpZuAAF1p4HddDpNkF4oEUHOKmRtwqPRDcIbjQ2BKFLjGDknWYgZTEQEMi0 +6IAbprQyOJVmG6CxvsbDIF5KQBLP3DGpRAzEc2HcMQ7MOkYHPIFLYypDDoOiHoBqARNwQXOdgAvY +CtoB7o4sjRPuwVuFO6ftuTY5LRHKHgZmnjJqp0RMyDxQ9Fm/dLkXwCP5D7gpRmcIFOMSFSYTw7Rx +bxMDfbIyJpM4k/hdMTKMfJ8Ma7R9AJaT5BPyUKVlSUZglNwIwCylDPj9jKvcz1QTOAm6MpcMvVV4 +Ll76SMqyMOM5NwZm9NBIx5jnzMDm4tBzTQo2JERPc0D3Sm3aqePRSjKefX+JgcHBC14wr85zn2xc +Mp8oXtqFoDuPNox8nShRgJ7XCrd5UJaSeT85LHSxpL73XGDyrHzNIAOp+hcB0Y8kQGRnAuuozXiA +OjBcNlNHCnozqiIlL02+v6RxaUphbCNNL7qMZEDLaFsQmncLsSkn1qz10PCwI8FLjtmGUKXblJoC +Y84yVorUGnUvC3EgdC2Tj4+APjmBKcVW3JaBgWRdWAe0qQgetQYq7Wdm2diHCij0JGjHOQblNImX +Fy+hzLq+aMGVJAPma34IWJKsGFs4BKvoT6A1j1lFlqPkbgLSEQyGgVqtFIvfka8n3R/Rpf59io/z +dqJL9ggYg5ftkdAdLUBhJRmnF3sPIsmIKqMXGYnmNL/MZ5WbTsgDt3iXuk73AvrIir4MOLQwmVCa +AgtOkTmXXjbLHbAgQ5Mz1SroVqaMjRddg5akA4dnbjsSMYwh/LcmbVuYdwEDz06HQNHRzr4PKm4o +MMjyApm1DEHFgu6RvRwz5QEv7dTGi2pFTjJcReAEplGYMFqZPLSlAxeZ72JTcxSlqAxmVzoBm2dS +GoCeuD7DcrKNA/ITHR8ED5FnhsBYRIZw5IGBmOTOYhBX+qX2EITyPFGejKDjK/KibzHwUjETz43w +abZ3powmZawNmQUDo1uEry2ONwTSkFNmR7vE1NwgwrhK5psAF+UgQjio4wblCovLufdQhY1ikmDw +wohBkjLMK7NC/39wus1d7Oy9oL3IQ3BROwgis4C9e+H5Wywo4SzoVSDmiAd5Ft8EP5j6wjtgUVcP +AWsWhRaIMQmsLKINRz2mQP3GRFxgwWBijtI2sORBnwKW/2RgK6wRA2+rJfQeHMbICZ689BCVHBCY +mfHju5p0EHIcO1BNW1UaLGMYWUmmUttNgIC7wEAKE0kHoIqUJEqyCg48dkG7hy5xdjaqNRINvUV5 +xnBHNoHJu0LkqlsAO1xks4bK+go2XFSTzMZ49YJPURplJbiInXCXIKDgDZaNdtFyiS0rI1m8NM5F +YEHUbDKctAMXzSRYqkoOLPJQ9PVCd05cc5P5G2LQzZyFR2dUEAQzDePYieHFC86xqhJv+GgkjUDH +78OCkc3mJg5sEgl0+QsDS2b+kKScNgGb9IA1sbPSrltQ0QgyBidZm9Ke2YNeJiM9O1FzuSb8bHYD +QXhX1Y6ornaKUOUlSDSEgEs00cRGEsJaUPZbykASITnhqkmYCZKUF21ftD8016K+KHabBbd0WKTf +4IoOQDkUOtCcramx6jZseTT6lC2XugRprMx+BdwgwdCDRaOiLF7CwwN3RrAliH0AKnlT6k5N1i/7 +qkDhyomUTJudM3DzXlFJBYjYQihFZwfvVU0FXZQ2uxacwIPovNRDE73ICBM3ZxX93gXTZBcqqRFF +BwtsNyyt6+0cyGDKzmwkZVavD31vLE0VI6+kRhddsmKEdjIDvWfBj/4fyQ7nt6Uq8Jx131Yx6RIn +F03XwTQN4AO8F1EbwYJkpmuEhYSDx6ob2Uwox/VF/n/u3qXHlqRJDtsP8P2H3gggBXUz4x0hrcia +Za0kSABXBHEJEgRRJEAMF/r3Ou5m5pF5Mqs11BR7ITTQfa93nMh4h4c/zF5yuhukWAzIZudD2MM3 +XLhTDaGZzAxppp0g/4FHjemqDYeXyQ4f9JxhRwoNxBHfXI4wCTdweayJC8P6URC/60J39YU1bLJm +KEmo9aVsdsiyvfUhnHgD28j00HFd91qUD3sjXfQdE9ahat/GNvZF98AObO40peBZGkUr3My9Qll/ +CV8HiDTdylk2q1/iA/3Y4+Omks7jK+0achk8hF2ZYBMSj7RW6qmCbiSdKGtvex5SufHAzlvWKs+S +QPF6k+u9Y0ahIqGrkE+DcFJiaKByk2YPJcYUg8YrotC2cniyFzsHYFcfHj26THEJW6ZlXPA1ZEaM +WqREcBe9qu141JsZf1UKgx3V5XrhvLrdYTwzIQ+TgphvVlviBJ/pVEOiqlqYsode1BWTDIPufRxi +hA6a0NIBOwYH6HBjgYtl3zRk9wMNtlcQL7QjXhLJEk9Cxzps2UGcj64KJo/lpC172NOnUhFIOceB +lGJ8D7QYwsRD8QCi70MHpN9b2hvfdQMwlexa1t1p+Gt431sOc0sUDi7LHLr1wPH3od9TGxqwe3xK +3I5FTTpr5l51HMfSiU+99tYwNPl18HUL7Ckn2z98CCYvs1JueaUShgPBNRcIs+lvJuyZyc8uzxYT +i8KmL36G3LQ/yB18E0JY7zNZO5+a9sFGzxnb5sBNhUYbZc2sWi72mnTZXJxs6M0u8w== + + + UB8XNj2CXnKzPxfWi9PchQfUjgTQAJN1mRMTdjV/38Mwm5AnBWGmDcSWAeoMk7fJDlqnXT5651Pd +M+cg7DR7JeLnupC2BgM1oDIOcdazHqE3qABXjOs9UxW4sQrqlB11UUMdWYZWO0XY3nzoSPLoUAjL +4ME6ZKZDJ3R8rZJ7NEEnUjfzERvL1z+TUaICOG28YscG82FsuPr8VdoahSrZzI2a90RMHoCEd//U +BGe8okwX8TAmF06quw157lgicAlYBWYz+dAK42XUnGWCIj5LGq9UF9akBrgtKX4v06r5Yqu+1eYh +3d8DIl5CU486m5oansmQ61HSYNL63PLK8YEZEpWkrPeHmSIg1MxX3yVRsYWxYND9NeqyPka8gNKg +cLSeTnMZFejOIC/LS6icQt4u2O3L4ogOrr28t88yxDUtSXOaQDgLF3QfIVtFC7ruxb/M+6Kic+yR +gVXAwzC4qZdD0mFLlRrjcmTu9LZm39UeiWXFduGT9jrTuANtG6AkR5vZCY9nVZxixpCO/XOKGYN8 +Jl1kdmRFP/b9tEpvW56nLsk4tZYpGWyeP5Yfv6i22DRRxzY2jaYT1eVHWN1K5fTp8VCwKSmcM0lj +GNoxVkPHBVoYq+bCWluXGtHTb49tOD1U2/AzOA88/eKh2hd0VHNZHDJd0OLqhWWOsJMXonx+JfIR +nTt8ZqzUW2GyrS++NeA0ia/1I1VrMrANy3Zm6WWZjmcsfZrZK3Cltzw2T47du8/BrHP79sFoSpOn +z2LKGZXqZ+FBLSHBm0Nh5ZXigWqQJThn/fmzj9KDV5VDZetGWTiLEzxsD1+PZpkqvqguRUgx5F0K +H3Q7CGmzPBimD6EKevDThyqoqtY0zc8txTkoLQ5CntuHxRHW3x4bdmryS8GTAaSstJvcZZY4Ztlf +9BQ4HFvH0U/yeBDFXVw9qBQyXfC3z0VDzEMfLyXzDLEhOd7OxVxV6I8l7OihEzekzYas3nMccdam +eGQUOD8hrEW2LQcIgPCAplFdAebvHfCdYjxGXChzvMVYjkrha01krexTAw56fyufrWjtWOzvqC1J +WA8K47HmFc/w8/oh/qmaC+8BiyjmlWHnfCu6NlGxqdtTt6PFw/3S6M4ceombV1xYomldl1M+qTW5 +h5aQLdCQFeBcwtcST9JQi27zGzPfY9Ts+sqn3dwqHXIwIVzUzsW0SBd2PFzygdzn2M/0gWajqRqh +41LvXAhTe2xCNO4IH2RGLCgfDSv8dRlRjBCG2dhzCCibcpEEUBUq6LLQeQw5vha25NcILsloLkOs +TCwJGSTtxUN9xY5cGaiTucMfu6DOGRtL4vvJgzXZN7v/ZPCCneYltJdNpc3NdWwIqUi9jsRetCgM +ZYSPi07kA5SFwyEclC4cMrkp4ohlwxvqF5PLNHEjdpwhnMhn6a5D/j6pXYOeSBYttPnBlunCkuWP +dgUkKuip0MtUeLSO7c015zV0YoNblvd7igkeZYs8Umu/CBWbZNJZNIgvJYKOcp3YzojDVRowlxgv +uuXNWrlrXTQTLFyUKsrtk2uSbHZ9aslX7zN+0Pjw0gAXZ9wQjArHBgYtCJcacPRVdg1tKo4ABmcX +jpE5OKXh7LaMkxRBBC2vXUOl73biWkXhNGXpXZVj875sYz3XiBtBOg3Xc4VHHUOxWO8eRup6BkeU +E8MNvLVsWIvjeyFGg8JwLuplT1YgjE0OvWKEF3AhW4cNyBpGZ8N+aH70y6K2ocxarNac6ljSOdsR ++PUpceHa63CDbPm1ms/9gbzk6LR9fKpfQSSubu+KNFOuuYT4WouqN0ydU2xElfpvuVlDvlzP3IKw +dG1JhGNDmNiQYDuHuHa2pDbYC+xrXesWwQlPTfjYjdMVuMxinHfjZAtdwGJX4cTCL/WlU7gO3VQe +Ph+tU1zLpQZ6aD2CbNZo3eDu6XNq5QikiBPA/k3zXUwOhhksTWhRX/Kh9xQHhsmHBg6qS9++oRn2 +LhMONUs2cMj1Qlt0Pr+EPeJqJnyAEGZtiJzjJLVsKnZhuW7LoqVzwEy5g0yeuAUoX/6+hbfQHoXL +d4olXA7NjS5KAzRtqrVmciS4nCbFtTmOXLyDg6QW2tdyqBKdY9PgxHWh62+74j4ld4upC+nIMmEu +Xe2tiSVfCtWphtejMkFecYdbrQeVFiRFQLYWm+UgAbsFK1E+tNTNjKPmLo8UcSEP0nxs4Af0DcGn +5lLp0QTGNpqjqGjO6bEwP40CzThicgClrivJclfpf7LMHTx7jV15+rXu3iLcU5apD9NYzmDx2QsH +BplckCaD5diTWuE0nhDSOmcZToot9o2SsPSscOcqse3hJkZLLjqS9l9K8kyNsNKYmM41Rg7xoDt0 +XXo/0IpxnDxu7ruDUBN0MuC7nIYpn7issmVokdCmMg5ol1iQx1axbB1pVbd4oFlxBhku5tuhZbyb +F0nKn4492cmNaoia3sRy/9JRoDfEtHT7mOpb+c9dk/xRdmaF8mwcTTsUssS43svHBTXlM7b8W7uN +eUNNJLNDfsj0YOAu0B9LgXdhy32xvsTD9maI32r/3D6DiRVbEpZQ+Awm3rGWzFcPuQeWX8eWRdhh +XLUEXZgkPFlsazsDOg4KF6j/I2y89jUz6z02IW4uRfYjmCqsas65IyeKL/FPyd/Kf+6aSiyG3Neu +yPOweaJy4ZjqVLnEeCOZ5qSj1G2gH/r9PmKBs47WlTKka2ZVem3AqY+L2/VArOaXjp2jNR6znl4V +fZQNEvnoW3ytJrpunqUesbpDr8+eI/5shEJrhdn2wWwfF9LX7SVnnB5Ze99dXDxpwivtgdJ49t/b +EN0vEZ+33K7Hxln0F95NC0+6T8n1bFl4ZIf8Wk30PoX3vcBLwA8ky/uslNO98xIeiMC2vFKPm30J +DwtGyRA6Ui97b5auBnEdvFeSP+Zcpieks7ccLDhznJCOas1vefIiZDyzckNEHwbvgKU3kxPml4Y/ +Ix4kG2RaUwsY4W/9ath290HQ8Ld1upva1AZrphp23iEIXnUh3+l2j3n8rAvhEvD8l66NYWUzQyl4 ++luGOcMVMgOuXci0FYv5ZUAT5CWCI4CM8hJ6HhxvbT0uL8LXM13TY0DUcYUhyMmFjCWzLtDSZXyF +cCTZhamAL5dn6GCWLnzghrfP+RMgm117qF2VM1yQfRgVMJruNBct/JWWbJxxtZoQqrhP5ep7GPCK +s7IDZ1FbtOH5x7BtfRph6C5wHcU0bBVD/pK29EpyFQOrtJmtaHBk2jYxtSXDUVZMLKqFqczjXFb/ +7Wkpnd4ffrh7Ombbjw+8dyzjl07I/UiwfM4a7xruyTI8/DA0lwORjmWG6cueHgcuyxkWFPsSHAvK +fIsaVhTW02qELeollH5S864zHFQjIhfKcLwB6iyNffWlSBl2iHeqnfSbNCl2ly2aRCuz5e+OeO2d +hy92rkEZN+q14zh0cjrezWAM1JjhrLBVDpOR7bTWpFDd6/ncRzNtr5abvvbJnBHPZ4nvCyaPXqSI +loyrGUJqZQZncNTQWgvdsS+xXFyO7+IqvcF80AThl8CiLIzNRvfQpRFl2GM7QVQhm9AKu4UIQdko +AAyOSzvDMu75/HwXVdnJrAdSxh0GiSUdlCaa8Lr3JsfAgtx4NcGoWPKe0bcxDBX0UFJdJvLuly4V +ZIjlhXAhyKR3LwbGY79yE5tFLAwGtgv54Fpx/fqOdzOECcdqcZzj4Fw4iH7pzJk4SwqfYvwcFNqX +MDedI1LmDqhBcTEySNAq0IP2oMHScvEtxoqDAF+5DUIK1fE+OFqSdWmdeWJI0aJ3eaKZVBvHhDNy +S2AjrYuXrslq16jVdcqy8sTHT8mzrLeZZ63J6DFlrtdjw+L04+Yt5ax1MrzeDj+OsKmisB6XwcB2 +llTW7rGDWww7pVbKY7s005Qoy/HQpaWsXMy/9q4uWMEzDNgmnDppHT4HMihcdnyVeXpW+7HNA7zo +FZ+RomOH2pys9TQAcXodCjPz/JkkS6Zh6cFnaFd8Dr//vbyWhMHSIfnR9DDzxbAme8QP6leNho5m +25ga06Rxq2XdsRUBk9xIRdZ40+UGtZ3sQAUuQ9qJy1aidhYEei7utEfUiOGwRqXGjymG496D8OTv +dLQFzzs9+c4ARbkuv0XoIKrAEh0yFHr8z4d+Hzaz16oeLFvDOCyD7Rrh06I5HWeEJWuHMU1xMpYA +3mm10wJetqSU+ZZyuCwtfZy2vEKnnCVvFyXkNf16FSUPuoE+ft1nDfMcgxZaxO2vOGJWA58BStaj +7hoU4r1wq5uwRii27XvcIuvy9NuWrbVd3otB4i9hiYYt9ypDxnC9BVWavy+mZsmQwUiwVU/Oh8xo +KYPNzHoL+XG4W1AYGC3b8ip0N5lsRAP4pvPo33xqADSofIR/zn6P293scDR8GqpkVgi2Xx9Rw6iy +BMqvsxyqExtVCrKDYRbu3lbDxmPD1Wlak2nOSKD4IjAHOkxoPrdQOAtUzw+twwPWapPzCWSLE2k3 +ucTLzFYybKcmPNppK+RRhgrjarT9kST0K4rCQzq2k1lEDV1f89xok80wh+bdrhmmV0aHs4J1epTI +FWesRgjgsJdKVMBtb4+ttBezOaQwCimekguwcFD3FvzIK64uy5tc8VBZiooyWx1vE2ttk60uerXz +yvrejeYrrFqI0fywlaejalTfTjOdc9UgUuU59Vx1Xuuv6U2VV+1kaIsVpl+5E3wOwrJ4sa8jvAO1 +yWPTwajyGWLMul3s27FUa7hE8K0qoAYL/VsIwzAssa54Qs9I4LfyHxHMx4DVmuOQsMBznGrVEiU7 +e7XClvQSKyNxhGJtyDiHXMIZZ2q1MFP6fnPPp98zaGeQk9aL0t0+IviykiECVhsLh43mH4zus1Qe +nJ8uHPIqJZj8aj75TUsLN6C1IA57NxB/qmamcNjNwEgQA4AZckCfhDLgLbj3o23y6Jj9DbYDr1a3 +oM7wSgLiGp7iqKEvne0K4Kkl0AUW0xwwvevkgebvzczK29EvvFgwR5IBUUGVlYH6PPLhkK01Zn0h +0vxDNbTI1Q7CDl+ih/aaXgI1vCx2m40W+yFy1t3O/aHN87rhOBuAenMhUUpslSBE4b77QksriiEy +KLGcwjxUIienI88KwgxfuCHO4cw0GTyVJlvbPGTPIt8rhkWm90T5oykuz/NkIBs8SKlRRgXMBbDI +PgYdNoufagz380Dqxz58bM1RvWg45UNzTNOnz+R8CrbMjPrc4jg1WZ8UnlXHTDOAAb62UPJ43VvZ +gUdnAwwIPzSGXmCZ+SiZKDWsEzlamZHWjz34IIK9//OfsA4sS6BTpfbYvC/JZQFNwD79/Kb85640 +qdLOc9WhgNfYB3bGe8Vuna4lV2XJ63ho1H1DIwtrr1heJAmOMv68LOkTRbLr15+6nQHMiFU9ooUZ +EQoQtwjwqzucZWxGDcibsp49qvPzufqnQTJVaDHtyjOCviRnxsFCtHqcJelQntexow== + + + we/VxHM4KcmvA4foS20+lFGIXGbICovKVF+TbofuWmOc4jq9OhGLUDRCm6iU3b7+cWoWQ0cGrKxs +l0UPLiUlzojkv5c/d5D4KcwCjx4y0c7OPNpa6hEZi5P5TBDmCKDo89RLRV0yrIldfwuJqoEDMSPt +06U1EEF0DqdTiIO8m/cOaJAchLEoLbuFwy9v12GOkybvbDoDRMBjw6GJFQxfzRKDxuUWMf2Z8FQu +FHYF3dgUCkzCnzBRQToUfO+oCxA2ZZbJZpGrFE+L/S/l1AJ/QaJwxIaZuGRlFXbcafYSp5+3EBfE +hR1OYc80CLuHfZCfGwwztd/vn0/9fDF3qOApGj/H892CaqnMWKMY8FJ1I9oA8JasGOM9MJHUqK1h +QpyjJsQB95IxSLYrQt2FlVE0FkelL9VIhDmyfrwOJc665yJ+v47FEFeF5mRyu7iw0lGSW8RZNcAo +fmhtEZDAWkBLol2sLRJ9qaPmEUEtlgQfTq88kdSCBjOjKM/wyW9TSZ68BB2JLTfebQb0HU0oNL7m +cHInuj8oJDILMxGjCUUoHzJzWbN4gmyXxn2HfWwzYoX5Ii8EwYQZMeyOCro20yAfXStsFSYssr5W +szyGHbHxtloRWOrUDt5it77yWlvIKkG1VLoopw6zwops1UKVMyHNRvdOqHtmkTsUNO0gAuieGeW6 +FpCfmp+Sv5WP8zeMkrYjaxjXapgkTD4jfcWU2SX7VvBUQ86ci0qYP2q+ravyLuHbF2PSSqRBVzj9 +v6SZTyoT9RzDJ3ea0wR/qujKsskpec5+P/jzyVDa+7c+9ogcofN52m20ome0oiMOZl/etMefLNMO +/sPCHovG65/62CXUt1bhAGUGQULIwCwPyVAFigbvMOj8UgXLYUxyJzwAZHg0WHNX1buFsX/Wt7Az +2TzhqjRxQjieP3wqVc+4Am+DE7ednSKFSSqzSCOww5c52uS62DfFoYzIEprQrZbTOuXNkokEHOv0 +iKaPtbU6I6HM0sZTO73/3+rRF+wV5s8IB6pcsfrs0WZRWi53aINPyWuAVQZswVM9pz5o75Akeu81 +vH09X6mm+15jedXk96zgB92e86Xh60pU9ZCe07V8Kf65Zy2HhuFukaiohDLhdvCYH8VsZaDKhfyt +nvhCiaQLOs34BcMaESJhGgiQzySJq8gIgOvPhFPKyskcYt7xQxhV8t5nmUe9VmQk3ZtwWrSyBFS4 ++aL7M66rdoQaI9Wi0KtvyzUp3SbvDWVleTHV8N6YsEm3KAxGv7fg4zTHQ/hk2/trikdRTqpuCtuh +1JYb+Qmgz51+HioGnSaAi1LJFAnDM2TXz3/sCZX6Sn7gPaGRD5p3pOG9/Gnx6RcVPt29iomhVqGd +xiIbLUAZzPIc8k6IlgqegZC/1R87McdJPDYqBi1sjTtxFp66OWzbY9soM943LnTD0rZjZdk9Wgob +W56NmY+1ybb11oTT44q5qmZSiYgdf6eUsKiEqW/J+pIb9DKTHcyoVJYSxEN2Gj4ZahJ0o10yfejn +18+f2jXx0snmksztNGg0ZM8I2PTXM6whUzHT1uWCLs9zEHLNyvecEWfrv8/8WEpVT9y3FnzsCeUl +XC5pi2ZBxNIw1PcWNsiC5e40JIdsrh33pbEh5HWa0BY1L/oaapYXp5DO4rENp9bxVWHg9Tm2jMkd ++NI+2UasC3gVnRUmSchMeKtgZ2DdKz69qwG4VhK4hbdxBP5Ck4/jZARhiLrJd77FrZpT/QM2pJIQ +S33aQQd/4ZGXUdGAPd7x+9fpA2/16AtlSZUzposSgYMv+ewjuoCLox7CoCo7BtyEfjgXIod8yEjB +lA2rmIZi+9pipQqav7fgY+sKevRbrHxcmxvL2/kKats6gYzIPV73ZiUONFiP/6C2gYAUy0dLEXJh +xmfgBiXHkOksTGezCfnkv7ftdNsh4d0j2/ZNXJWxaUe4DAc1Qg9JHwYhHbCZ1JRx3UlRKWEYsWoZ +plRI5/rQhGjbQS3LPY1HrCfH02Ts+AklwP52yHn1Jr9W83njoTtA/HnCbX/999/97e/6LvIDoPH/ +NLbHK/h9sVjJms8o9yFqdSI/cKPfP4hOLHYEg/8PfyNRELiT9scuos9/rEhEhp48P7uBtxm/Gqts +DgIN8SLLUQMCnAtbIjkQrctb+EtfA73BW+GZwD9/qnZAldlN+Pjv6dWtAzD6mlFlaci+62SF+c95 +Rs12E1WCNMvFE9Q7HnNzkMPhIPf1qfMURuedYOdSlmFFrBUMF13EU2iBCOPvQxL9fxi/b0b6eVoe +5/B5st/GDPZ8U4uGxvV9/DishWzjxoLhUTSfKl5aF/t7iW97QK8LW6vjrfUU/opx6eu98LSQxqlq +wQ/UzRc3mtowxAh+G/BPVfwwOU+z+N2MPy6Px4X0Pmgc1/rSozSutwGMgS0k17WI8j7U+uwRcbNZ +LEEZMd6E53U5gMfI8IV5tUv1KG+9ojDG25ODroUt6sgJXU/VWmoRaIa9DT3Ge8FszSbPaPJtfkL+ +MJmP0/7dGnlcUI9L7zbMnIr2en1oKt6HljNxOI/BS+yMXGKYPovF6WOyBh7oRrYICLvzABvdm8I0 +/XMp+4Vglog+2XYPenvJNl999D6EvzR+BaQ+p8IW7gwmJq91kCTRrcJsAV+bkM+h1oJabjBahf0C +zftF6GPACm4rYc/4bdk8L7DvVuPj0n1c5O+zxokdpiafrtHLAMad8DDaT9Py3RQeCNRwomp3iP0O +ulIzq76EhhsOYmBLCzEj80tIR3Isgl6c/8toko2yG+0yC4Z/zdX6ax8ojEVAiqtz4eUY46wUlEGe +/OfkYdcWWE41Ky7E8XSh+8PRsTrrny6jhyX3uDYfF7LN1euaSfe5avtp9M2YPA7e9yNtLiVnYO4D +pJsWIZ8wf+YnBF+dxbcnsTLtn1dy+lpRoHrg0AeFlMP1tbdOQhbHq8V5XYv6INW3Omd0yhbxPls9 +NfLSUkthSGle+/TdPD+tiefF87TS/v3fHiYIHQkl8j4Uj2P23fBiziyDI2lwcY6bMNW6R7emkzCG +91hg0j4VHuC7vFb7PL6PU/E0Zw/Ta3EHW0s6nBXOAqaPTRbeEKn+rvxbzrOlXe/yoZa6Nd7lYKWB +3uFEiibrRaqqG/O2MM7PqxgyzxK4Vnpr8ceTTv32kf1weGjQQ8tv3dy67+EHsEUJEdCBai7YAC1Q +aXffjSAQ1jLf+k9h9L87td25bKW+gVqTlmOVrPZ8Wo9vwxJ67eMY3gf7aWLedepb979CMWqgt3OH +cd+aa2KvGrFKsCArZSDauHycwhiV4tv9XJbhBKi0xKVKbjxvwRHvtPfRilF5GNmnKfhuuh7n9nEV +3MbsQae+jV+Ma5rOHWnktivHpC5xUjb6fLeC2vzScXbeOB7dYeVCEOdc+kXhL43XS3fPb4UznNTX +amkhZBtS39eWZ3fc2nybof0QuE/n07x/t0ae1tPjwruN8oNKfRvZL6kMwyymzl8oj/e7HLw3EHZX +qOy+xi1vsuY3hmWzDeaM+geLK2pGEJ9AANkHyU1NjZugId29lzAmzAMProUTWV69UrIqL6l+3gDy +1kBeFhsm0lPP3nJy0lO3LkIfA3bhthJOM35bNo8L7LvV+Lh0Hxf5bd4etOrbEAb5+324H6bluyk0 +BWagAksUBJOrvTT4sQauadTq42Snx5r7Jp+W9eg/L7OLfD5bZol/Kw9Qm586QGGsgTKO/lbYGu7s +wedq7Q6o7daEQ9Y/b2zTdC9ocNatjNfud6voacU9L82ndfyuUt/6GRP1MCiPw/c40AtUtC+xofWA +Lbobto+RfzernSTUfcTYOa/C2tc/V0o3Fiw9CM3m798aray3TlIY1xnuh3PZgnS6a6U5OnVtQEZQ +9LW1jknV1S++Kr6Z6cdV8bh+nhbbSau+dTHMvffheBq274a4g9jxJZ/k5oQ6huPcmN9LUwOpokoY +g8wL5Vy4AALqWu13o/w4JU9z9zTPW7m2oNPqzbbMq2P1bX+vtDZUePZwYFbL8E7+usvIvgh5SXiW +WF4yZr0aim6h8HUsS9iwPjxZK06I6vYAiD0+ADKHJPNW+FPoscl37bpmbK6VcVagU7XoWLbG+2FR +DTVxsTWZfMEeykRjQ+SmPX04+v7QyufufNf1x3F6HNG34Y+mvc6peAEeMS3uLfWHWRK7ufnrwW6+ +kgNPP4zXXa++fyHGlDeLoYTnMERaNNIA7/MKLm4L+2q+i5c/swuFDsriwtNzqzYkVKGdPNwte+rQ +k9iDFCF8HegVQ5VGPDhu8xhNe5zz29q4D8r3w3cf5tuA3ZXqe9e/JH8Yp8cRvQ1/dH1VP7uMS+BI +sSAMQd7f9LMBUSzkwx+ThkCfYKGzjAQLQPU6kGzuwlX9GnU49TDgGw92z+oKqe2rZbhWjsuc2YXt +CAtG3nmPqDk1TmI5YrZukxvyh5XwuGaeFtibUn3v1pfkD2PwNFi3gf3QuDjDutOPR4CaDw2svCbO +oGA3mSW1QpiqxtBCvlzW157ggcDyl7yS8Q0fw6k9icxqwgXWNC6FIrW8WWJj5bAktKB5WBkteoUm +m2ZmQojc00yl/HXWDdn5xqrQ4AugSl2I0BEXGiYDNlIKQ8V9HcTI3BfN8/J6WotvGvW9918xL/eh +ehzUbybAPDClQ+7gzPia9mhCmjc6uprf9ibs+1lzIB3wJbeAg0OFadaZ5kBoGFagmHtb55B9ziYL +drspZFuflsSyr1PCYspMaJGr6IMBZISVuRnrRZI58ICNoTUAqrsQAUTfroHH5fKwrh7X4JtK/d7J +rz1It/H4ZuSeh9nwp6bktNI6koH2n+9wLFSPSsVU97Z7Cb+Jf23ETnnpsR1LpWeOc0F6pjfWVjQn +qsgS4+jYmaPs8a0ui5USNr1JrY4tMGp59wZMSyZamYVz9WPNGD5K/tOJflwVj+vnvtS2Rn3r35cG +6GEsHkftmxGuCOXzsinB+9ssnBu1llBnWwNCET51tNgLDcRs3rJ4CXbAIrtwGmjHn43x44Q8zdzD +JG+F2oay+D3gZs2q82YdMpHbU3UAy87KWzat9PNlUxvy1NpZb4fw6JNCkCr6Fz1Z1IWOgPxLLXFb +E17MdqFC2Afep44BMX97bPNdo56dLgZD+DwiVsGGxQ5elyeY841QiG9g8Q++hG6N7BDKWfz47U/J +Hxv62KXn/j8O1jfD+jYHbNvwOceDLO6nabGolQ9cOcidhKlBBnbahyG7a9XvX+CgWs6SH7dmoqmh +pBn1UYchYBGszoWe9uV1dDwEbW/oCf661OTanxUJbS5HIPVLaOgYhSaHmiRLOB1tlFaXQn2fxE+t +gocZf14atyH5bvS+GebLeN1V6vvYxZg61YLLHU6VTbdkOp97g1lP8dCd8Ro3vy1tjtNgT/zEdChY +WCFmRjCzz8qxQwmmZxpztBUTY6wSLbNXR8fNNank+7CUlHUs2tV0aLhPyvp9enZfbg== + + + U/k459+sj6el9M2aexvku5n6PixfauTDGH4z2m9T86GBtSydl7gjMvhT4mMOymuGQiYWDwhpujca +kO4PwOHMFGNX3OvhTbMciKYa6vJraOTd3kPmKIf0bbKejeV5fBhAD+F+yRxflCYcv/1MaCgggwax +lcNQe18Ku3P3dfO4wp6W45tSfG/+l77y0NfHUflmCI0gA5e2Yehm1DDM/ulP5mHm0Vw5LDP75Wyo +uqXOXcMBk/xojp0AWYY1ZRTSAXmtjAmxNTOm3jX+jYT+zwbb+/Cbgda5pQgcAx/G1lgb59PljtoO +6xyNwgbzz4kZ4GfxWt17hEk5woJ5n9xPtexhJTwsmcfl9aYu37v/pfF7GKunQf1uAgz+AntxhDlr +NNk8RweaEoRU/40KUcgmXkPpfo7Y17jc+XyzwWVUlRE3HVxsJ2eZjWoePAs6Lf3DsGvRgQSsURMa +ctnBIZiGoMLvG7ksvn+E3mdsGd3tCwaS2dmt75bA43p5WlhPi3ArzPc+fkn+NB7vo/bd+JI820sO +GrBshGqBLCeoRsNe3u44GxWkAb+0wlP2i8VKKD4pw/nubR2em/EnQ/w4H48z9zTNW1/eUd3mSTb4 +vq8nedJ9/Y+XP1b+fzFu22y2o3OPBwqdyydeWh7TkmXLRUyfO3LmoKzFcvIMxm3LNd4q3Je8cMyW +a2PnwpdWqxo86QYLMg6Pe5v/8R18Cf91mKSv3btHdX87BAVZzhiCY5v+i9anA+8XGSWP4Q/7bsnh +U+bQmdxoZtFUF9Opgxa6fOCVZ5lJ2GlOdEKTS5aCA/YebcvbkG3nw9PwPk7Ed7P2NMOPS+Ft0D7u +pvLbAIYtsR2L3iBPmgnb62psPeg9XYbYWr8BOq4Fg08arrd5gGGX+uyJ034yGd2S2W4grAjUMqIh +vr8NxQmRVqPAFPoRfoLrgIf/4HF2nqbxecof18c3K+lt1B7s5bcRjJGdQ8f1ufkLMOg4xuc8mRid +QRRHOa39w56Z7MGSYX8wwNH0oTak2ptNuur4Bh2wC6uHWQzEpVNUM7XPfPIkVaRSetlkBpNPyd+m +J+SPc/kw698tkW/W033h3Yb4rtrfRmWbVO8j+DTUt2n5kHmp90PrgtnfkDuwAeRzm2aOycJZ5iG7 +lha7VPIRNWecjjg4nIHODYavWZhc3Jn9N1iKPDEFeQexVJL64H7lop9GB9WgKTkhKCqoy0N4TBOr +YYKrpARzOWguXejPaAhrVw18A5jaJqZSWJwPP6XGidjpaZVt+X1BPizch0V+t6K/jUpYZ+9D+DzY +382M4VtkPldmOWSvpldr2MIrsnemrjPK6b+ihtLQ/hQpOWbfbR5IAQq8Rtum9MKKNvyShfh13nAA +D26ElgBt4aPtyFWoti4//sfatMte2GmtXQ4UIA5O5zy6rfLPlsfjWnpadE8L9G5Kf+toGGofRuVx +/L4b7G6qJ2vI0DKboTt1LirlFZiwuanHn1MtXAZElXO5HhKtApPO2wuoc9isj4a+e6BxGNNlKujh +kbPDADbA1+j1xmCwGqMwN/kRKu5QdG1HIfLOwiFb5QwCpfZPp/thbXyziu5L7mRQf+/jl8QP4/E4 +ct8NM6z3XoEH+kE2Mt7mwgCEa6EXPuyKedt+qQJPm8brkO6txvQVF066oL8d5sc5eZy9h5neLwQL +ua9yrp8euub2LT4JixniFK7MmP60YBJZWb5ZC/Q/4hpekdEQsRwrO8yci3MKK6F5LjMD1A8k+FkB +TIf7P/GevLf1103vvn3iS+bqUhQtv+bRtiOgH4PyRouKsTc3CfVGN4rmqaiBU0bXcv4ziI+JxWoE +154/1pyUHBEGi1xW8B5ti8B9/GJUHgf7cVru4/Ing/gw2Ncxu2vd9/E7eSiyQgLKdrzQPoVOGRcN +hBU+RMtuyDSBDhqtRSAf/pXXEen+qYnwEggZWvz61epVbgs//l2YwshwH+5PyR/n5mkSHyf8cXV8 +t47eBu3Bon4bwLCoO7sUnMIlsimnsbUUyluPZ45ZorvGVgGr00CRXIGw9i0EprpfjY7NdoTWbUzf +ozLuohS4GV/CUj1AzunBm9wM1JdfH50Cj+BMNjn9xbH1MEEhfpzMh2n/Zol8s5weFt5tkB8s6reB +DYufQ+G6vO68CuOf7krVAd2Zm4dfx279jZ5geFWKTIbWYFsF4S9KRb53B/qlMNMrK9e7/TGh/+kc +pXifh/AXPU7aw/R+sxQel83jArsN2sfdHH7r/5dcGPexehrU+wx8yEb7emrpLFyRBOEXIrbOgTit +32F3hVJhe11WcmPeqAr6mmXumhHPPtfZreEcqQgIYIyMOQ4YvtId33M7p8wOjEiXPmXpdxwv9857 +ahxqdbpen9vgMoQXBs6iyYxNjFjyF4r5B8wPgNFNyw9vrz/wCe6LJs6J+wJ7XIlPy/ZNE751/yvc +LLehehrTb8e/GTCaFiaVPVOr3FEyB2D+IKt43xjh+YijaPSImRh4A6IFCU5vKzyr/ByjDEYx+Pxs +X9ORubk8KpSFa+cUDpmBxx8NEqUdsLcNEYIpHBrmHU+UKUX1TxbAw2r5Zl3d1uDJRn7r35fkD4Px +OGzfjXGLFWbo9TFHlmLoDVydaRMNfGwYSrNS/QpHxjEYw8IQm0GIZYaw5PRnI/wwF9/N2m2K//3f +/uf/9re/S7/9/d/+7pr/0+Q7sN6mnTm4AA265b+7/d5j8L0HYZLfQpvbOBS23JRz5hdHrUO0Eecm +SIgKLM+713Qt3JZ0vF3rll1bcJLv5u5aTx27jwIfDX+vQVpuSLOZTzujNoMUmBFBWJ79kL3CTpyD +4BWHXnPTyKF2+xjqbb4xPqEsnQz+wmHgbVVZef0YtL685jbyKybjwgdpUX73JHC/HOBcm3jn27sb +vzcjShhU7Y0O46udqwzZc0ruwm7paXgbAqyp//Nvf3daV9fco8che6r7sRXft/jeu6dh+HbInsb3 +eSYeJ+15fh9XwuOQxZoyKyksLwvhGDFCPXu7bf9rSkZEgloUeqRfTxi+p1kve2QWl2hMCUXTEmki +8NRZWn735Bj6picDI1mDRZsX2jRiOMzGNzjyp3RRJ1SAtXBuBBaLsK0snLWGloIJhoAAn8bhaWWd +LuH7JwOP5aF9jz35rtuPY/Q4mt8N/eM8Pc7oU7e/HaPH0Xwa+suZxXwju/oEx4oUQ9Y1cRLiA4rK +mIb7qpxSxPXYqVr72n0k1MgkdDtq1YCkcHHbKPGBRNg81lBjSDMYA35nnmQb1BbWUuqzFIADKkQs +8VkSTWkxrTUGxDhTp2bqbRhiecWCeu/n1/9f+vlPnu435Lf/j1huNyi3//a3/y44t9e7KAeZ90QY +CvECHXg5neSfb/JEvfLzrZ7v5Kd6DOxtH0FAffN/XtoZ6CucgucgjKVzchF0b4qKpBRAHv/uGOKT +5IEbJrAOETw6V+imGjrLAxN0CMHUGDgnGXoGThdwiI5NFRIMeMbtSYauOv+QKHciUltw3iJZqIf0 +8ffm/O5sgRMD/e4kgy+VbkAYlH0JT02SntcThQ14B4y0/ABbk0dWC3yyFlEOE0rcISwDxt5C0ruw +Nh0q2oRV/HEl+FOahXmrAWvTPJiDoopa9MhDBIMOKIyRbSIoJPW4Ea5WHueQdwfxLfa8FM0NAYeN +QJ4ckB7FPckeP0oTsLhRLLcs0lYyGjit+GLhnoBj3C26/CCOpwNboA8WkzM04m6leAk9tBILwXQY +wKdauiAQ/rWGUYMx5gE7U4S9oMujpHaQHCxjjHegcePBfD239897qaIRrmB0sMILXXjdeKVIWMkm +awasLnhaay2oR4uu1Ve/Yh7zRFTb7yCuBfGW7aA0RaZo+amAaXXcWlJ2Z3MfsIbcwOTn2EKgHZiO +OvWhCsirYmjDBZQhfoECjXMgtN+EdjQSYr7XGEQPbV2EmF+VZJ4Tby7ijpdEoZu3ASl84nw12tkl ++OEWzMkBXA5JAjk1GtqCwM7koDN9yUXG7l7SzCq9eRIe7NViLCnFhA4uBNx1uKhMjGG/PUxoGdd5 +SpijgirKpfkHEK7t7ZoEUeyhoyYMmtc8t7HU5bkJj3gdGEB/vna2apIK0YRdi2AKHum1vAxB1+Wv +w9axfupxeEBZ5e5w27QZYv8YWfTJ7q768EPesLmDbRkYDy+hoXgX8jI7KKDLctdx4Mc6K2hBnu1g +dpmFSYBnq9vWLGuIw9PXSNRA9ic/kUoUBlteMT5q2x+sIRF81yHrfqEGiyPq5LRY5fA2HF0skRN4 +aSZLwQc74CRGBcehhWBsjeCJM3pE8K7YQk7BbEoWdWawcBomlBpwKBgTLSslVm0jnrO3YCwAYZNL +AYNwNLEtNJhBvFfinuxA+sV8lSzuLhfGPAr5u+ES+pSc27nxFYg5j7Kvv2UJcRMb8rnFYkXFC1qA +ofeaPQDCHpi9HlwAoWdLQZjiqF3iHVzBZm92xdZJOHoUMCRbxG6vZILteoH48UXwaiMTnINX5lGC +pW7hurC0xmPzKwX9j936Ixiett4A0GAj29O1b5zqZDF9fVLkM9VxZEhP5lnIEK5SxXfWQaZrLcDd +6MIZ1Gz1xJYuqs2eEDFcncdUZ/WIoyIjU/KXTsp1FMrFG59JMnXCQrYohsGJcS5anjSO0yGI5Kpj +9aUCEY1ZJ52FCy3yqJyIo80WK+DmSQXBkF0AeZ09ewyqCCFYsAhsrDkCBk9xkFuliUjReDZEaOLW +YlMJg73TkKFrkAfb3VVIdzoFB52DqXjEaWuHT+3kLdjEtWnTSDVRkyYGeLEoFImTnmxYQlmUi8Yb +kEXW7Vm2LAzac6MGn1AbnPCgkyKtp6BstckP6kkcaqBBShpG56SwQfC0Ue19Uw65FEtQ4M1NMmiZ +oZMnlVvQMRFl6ERaNeZhiZfY2V7EFM+NZzItzaPxZj8pn0YEK7j/AU6jNsCPdrmELZAClMiG3q/Y +Ft8fOn+nkSIIOV849PbOG+x/WUTYPxRV/RIfcOfxoG9vfBn2sYIL09mVMaoT0dOcRE9l4wAmkokZ +81ouLOxJUxCmNUmplHucBnbggIHU28DPTR6zxQAooDXdH0LuF/uf/s2/+Jf/9R/+/j/++of/+F/+ +87/9r//3b//r67X4b/7Z7xY0+Hrlpn/+27/4P/7hv/7H//wffvtn/+pf/ctfv/7b1//+X/7h31rh +f/7b/2JF/zf7l727/h6apDU+8YB2swveW+Zn5dFvsZB4Vsxg/XQkdTxgzHMYFMUn9cScNIfOArcU +Q6FOwTq+wJZnrMODjExjnMi688zkBarkyk5iprd7LoNu9t6DHx0oM2v8DjrqOsX1WwKp3vAkWiGB +baUSZi6nGrS4pHgwTyrImpz+t2tbm1v1GALib6B+mE5CDpkzxVFGytQGAKxfUUETDj851O1j4Boy +2YEnhnl1yfraNviWNzcOoTU4KZY1EHzBRxep98BDz46rkk6s3isfHBwEDWGuOQgWsg== + + + Gk+iozUK3cUaTyJRppsNmizoBRn8aEM6JHybiF8/Od1Y0IWM0w2aJqbavCOk0ktB2mWvGGjAKQGc +jicdKeSznaN1P37JSCSYNLtNXz+rYtvhzWTPStCkJ4bc8gQzIM5OQhs/GU1YtFYK8hFMZlRVi3SM +6Yinp73wSS2ZPR0FMlJtOcEVrkErmMmR5fP0S78fB8iALewQ6pR9bNECxBPNdPFVz1YhHuEH0Ekv +vTW0gAJmp0R8SYxhjHbLRXeYPxszW+tqFqZGg5jAP4F57Aepdoat+1+a3oFngMkHeDVMSEbDGm9n +E2oPuYb0oQp6P8RX1JcqcE41kBNlNOu+kn70aOLq6eyjIziTTfgwkzfljXdqzZ0d9Ex8Xt3gvXPK +ynYyDrzGnnLqzKbEkZO2hOXHMgG6uDHtSOPDNov+OG2SPTO7kFe9Qbv93V+mtWmMBTXj4jY2i8jo +LOt6vQsRruvCAZYVO9PCOuHiJi1Mj3Pj25446Ph3X1g8ZUd83aIode402vk8Yyrx64ikhmmjibHS +1RcO4CGikSQ3qe9+0cUzTft9+3dbTB+a2DKD3rIHFTeJ5SsjxCCbRefHtlF5WRFNlShLBkXnIsVV +cVtCP32emoEfO7ZUGJ2+YpXUSqNdG1B7xkSgNs1+eNY4QAUMaf3MeT2De7v04NOdhSdXUYKry8hr +UwYABX+pgtpgEhig1YYwq6yOqEk4NxTMcRaYu4AG1QpDKzpGQrNSQ1G3TNPkh1wx/Ja917p0dZOv +MF1ytxamBrisgESnVNwJH6qgTJUttPgY6Bz0ahvzQePabSJ+eqoNPBu8PcYynZas9zOIR53znuqI +KZaJj2gS65pNCwYO4y2qM8bZeQ5R9NB5UINqaAENFtvUOC3we6Z/QVyDr17v7ZEA5ujCNjD0F2HO +8QQd244wzjWQuW6cD4opsvsIvfA39DFHlhzXjnWhtFAUB8/JNps0yv36MTlpeweMPJAVnKkDcbcq +WFmpe7hiDMS52+Ot5c4s8XHzDW3W9EFF1U2nXGhOEtAl57VgNrFGIbJmKKSi6pm8YYpZINayszrD +5NCzrIV+AyQ1YDYe6q+N2/deWTDunh7cNgdLWjE9ChbgTwNPDwpDyBOvkM78eReWpeM+lyphI2VV +x8nAI+dwrwX0VxJHe0ySptyDh373B5S09eHPml9SldvB9R2a8vzjpU2SitzjLs2kV5G4jGVg5h8a +G61DseYyzKuHWaYOLu/s2KluAewkLp14LdHemWFqgNzeEbQM9iyTGG2QuBZZQxiuX/JJg6ftZh+E +emQ7LmABTNAs3QdYoB+4qSUsruYbxKM/w7oAGQv6AX/xIJrNpi5ZfK1W8iBnxJhACK54k7ljy2Vu +ukUFepl6Uw9oF5m5M9anIZcbeiKTMf1odu4otO4lT6H1T4LfVBjSbaA8msBnMKXBjewoRTTWmuUs +yOEPLYHMPWtnIV1Ct9P0R8/rv56BrNy91v99FGSwDJ+YwSRpa+LtzFzsCnrrb+WbX+tc55WOzP5J +7pZ+/dDjEUhq5CbnL8ktIIBywryasB6DwsVM8AaHgAtTVgikVyxpR7SyyXoih5PHez624IOp8rtT +R4WB+kud9Ze/y0H47NWAtwTCsv68bUgu9k8mwBiYe7Sg1gLqvccmROMaYzOcg2jM08ABpdPkbjT7 +lNydmC73OCMKSyFpEkyUTzWfvjnML+hNPCVDFlLNuzwIxF2+PE3Gy1uSS8jf6glWOcP/KA3kYXmn +XPSDmEhOKrYjFfNSYU8NZMnUyVM2I33vXnF8MjGXxwi4qnk7+ckEk6HLhRzXzZGPSWrnwK2RwdbV +YAj6UA29FdYQsX5WbVdh8iTd26AhN3txE+3aYWHFTJRbyGJ1ecrah20RxwbFR2XEILI5XFgVm/pW +r75o2JINBFsNpKSRaj7s1e7ySToqS5r2EOl+9ABZsvRbZ1YyoRYQ5JOT2IXFYrLGj+F4fmqB2mY6 +PaDq1kJmXQSKiUxoAZ4nqD9GZvHJJF2TASne6mBO9b3ij708wMJl3FG2hWN1oBYTOwk2hR2TYt7y +LgRwnWQH9MdYHW7ehTzNYHbKTUJJHBTU6zSd72M34Nwurec28ebzUXY0KK6Yl7wvyQ8mJ5sQFIAm +ZEaoCRNkDkP+oQpAYIPpi2S4Npnta3KnR2YdZlxmYQY/35oWo2xW/SHiLQOADZKN3JEm99ITyhAs +PIC9XneQB7NRBgyXl9ANGx9RQQXDzoz85O4B9qxBqAL3JlyWwNG0vyMP0+Wx7UlucSmbAgR+F9xw +XiauVYeJOmJZUOle6TcHDNDIcJbEEaVLspE7+qkLH/vEtRZheY3IQbCztZAxTdmqfrRShrgMl72W +zTrtgzhvdTYfG+j9IKybF2YW7a0B/68H0YAejcNSmBB2imnYVhWwRUo6f4WXzrJVo951DK2lqagJ +y+T7c6jsmivUal6EBvxPaUOGhdk6PJPC9QIi65aB56kLg0sev+c0VaTp8WOjFtYAAIt7A9Q0ewcV +nBcdhB+h0AGC3eUbXcfk4+DuFQKpCVsIkZB1r1ifNGxCj2a2/7O2nmTyLNLRg5RX0xNG/NZiopDl +MJkJAVdzDQDpy8+1WvxbU/ces0juDfhQFsnvnpp1tKSNPXYaZxZ6hBEAMqNmZjjS/WgYAceXAI5s +MnnvXS4cZ2JoRR5oBXaqHVAGDrzlAO5YC2n0ISd0nNVzDOX0ERVmOU20hHOCn9BaF1CiL3GautLW +zoNsSuOzc+6UWW1YKY0NccUp5J59a+PB3PvZYb/GATymUk8X613+5GIzuiKDl2kcAWRuxYFH6p8j +oqkR1vcYjKTZ1cG8QO0dSyEGzm/YSFM91uLt4Pc3hEEMKVpHS04ln+pxwWBdRILzA4nIZpbv5qBK +fiJxE3q+cOM55zlZUYO/AGb312cTrKrHbKENFldH4RyqViFGaIP5MryG3JkVu4LrlTiOEDrzgQv7 +xji2bGho9smiTNRjJD27Zs/YfCvYk2hLW92/B9S7V5Cz1rGlY6/M7xVming6NqrQy8XSuSfbuqmI +LQYO53oCDTBKJse8xeR0CV9PBs7YCWPbPKWlVA059IolTEZrgLLYLMm+8cmzYRhW5rLzorUpSf/g +obJZHleGK8OFykFmvXFM+wDs9P+hx6kS9BxOYfKSTszMdUqFznN6KfYJXxw60oHZvEoQ3tJnC6EH +vkFoQxe/B3yfn/98WixeaqIJNZKHNqhunTiR7if5vgoonMAwWgUEA1uTZ7FDiuTrrdJ2tXMMKXf1 +dMEAeuWsHlpnU+IFM4hCbp3l89zSWvc0FNLlmNyxkaNmqlUzMk3M6lAxsjNSpsIU8ZIpAo7QDGtb +KDixCSrOihTHlZHk78LKnGWbgJYp9HmLSlOp/L6HvUGYncnBCisf0jD+06TwdO0ZHgF3nZsvYxwN +2x2LdOKNQ+GBp9YK1FGvAbO2/tg52Y4ugX26T1wTSnaULMwJcDF5C9r++cEez71A6MR2YeMVb/nm +ZWq8A8POkv659RwWdbIscmltbhGd7cKStRA8gnPX0FSx8twdNALj9SpcukAjUutqrN2jcdT5Me+F +HRAvsEYWK7FI4RJnaOayq3kIRrvwtB7wwMYprkfQODPoGUY31+MAqTGEwOB3xZLJNsYP0Fc7qTsf +qsG9olRugtDE4BgO7tdJ9WCQWdi3oL3hvlOOJM/cr4N0VSa06FUXIvEDClrWe75uqB1DKzjaUJ+n +2uAQQNjuBH7ofwy1KuAeXSvQs9FNZ1QhluwgfHaYUpCphTuhS/y+Z1nhRLdlwl7Z/kxbh4F01yTV +d6OJWtwPb+Sd4GmJ2rw1zGK2JJQqSqCeqIFHXgNGKGTcUQXaJhS01xrk748NvW+KGOem4WwMJICx +JsfmKHgFmkbYdMAiOhfCKaNMTyeNcBtrlgayImUB/QW9hcnKwRa0efr9UWXN7Hx0wCvMhXSU0Jd5 +zZubSz+P660jrwCyFWaCg9Y6E/KosljWeKJZhnnYw6hU7WN4bFR7htJjF+y7aCpz2tfc5oJ1ggxd +iYgmQep+LlyyWkgJnhF2NkjKJ9ygWAhjChJ6j8tMwg7w2Dxc/GvTWy+yCHuH+agZOKbR2JkDOpoT +w0g1VjBP61MIIg5foDet1DKrNfWzCTxqkNXArOBZAAxtVjUXJ4dn4WmHjeNcAYiefc1UUr1P/I7X +fwlgCT74+5mq1xNcdf17oMBn1DzK1PEDFh2rhAa0CzaEq+YoaegpUXMvqll+Aw8mkMJz0GDvCYmJ +Y+ZvHNYw4oqwbRZEbwaCvDrNX6LJsMTXQ23zTA4Ko4YTNJnhic2qwkIv7kDBhuV3Cv4Y+AnehBq/ +b9Ao0GLbVp+SIxfYR5MGEUMUK4szGmDWIhz2mVO1ldRRfsBuUGUQTsDoICRwmdYtlWtzbNaYtZ2m +buntVD5rcGA7qFthrSsHrNwQ/qU3oUINMaTlY0r3pW4xSugLFVph1KBbrmB2ODaZ2DLejwV97CVM +TcvMM+x+Z2Y/h8ZBpFhxCrtJA2IphKuXULeJmGIBgZPD46/RqKFwjTSocCa0VAZ5hsbCEWd4vW6R +8Ok5tq13nW61RDwegyeIPSRYb8vcMs8sdJZ92VsNU6bbQiSCRYoXv757UOEmuRX8aorfy9ytkBC3 +mNaqY/6o2FZ9nnQ3xwvZhtiU6XBw3X/TIvsb3hWknMSwOqncjNBNrOQh/fFIm+J2kBPJLwbrXBBc +y65k4bc09E83WODCXVUV+0VNBSU0jKAfxX5TyyyiBnN5shzXdrvcDS5/6b5G+hJ6dkz5DnmLGV8o +FZQKNOGooUrrEDizuzpUq8wFzi1auEAMk1gVdNjCZ5jsIYyxPTauyapNT6+aw232GqU0dOlWkW3q +vd6ZGeFCHTe2cAIu/SXXW6AjkpE1tNK0/6Aj9Ysmsp8NVsOQH27xdjQqoTn72zxU4IpyV8azwShz ++Egp8ULwhrVQq4XDUbocVH7iRAVynbSdmE4GEpxlfBYa33XWtnYk15gIvX22O7rT4Mozq8kTdRQJ +zwb1FiYsS7cbkV4/cBMXAHb+7on40qkqEi9YQ4lFUsP0YYWTnDo6ySxMtQ95gFY/1QCSaeyoqUPW +yiddxn6dQwiUZmzLpc/Jlj3+OLesDFmFzR8d1R50Tg1seBNm5KqgMM9jwzShfj1gzo6Kj/BC9dRO +fOdzlHiSdFXS4j0ygrm+LXXYUl8+9Pv9TNLJkIGB5Vstp/Yuc6Uifg5qGag5Q0Tush91mMEgBIQY +NvA4cQ3Lq9BxykUN8q+WqMEynLjXNhK3OaerjgyhjfWMpYVFRnLG771XclW2M1yJ26p5kk25tF4H +nZwV+wXX0+lsyOJ8PuLE6WF9vXvvT179wVPHr5dwg8vd5endJ/f4jPIyqlthOswGCM5+f/Cvf6gC +oABjqQYJg7nTY/IEquOc7FWvmCWm95wH1Qx3eIdzFQRTWH0yH5g4VopwFL2s9Ei9pA== + + + 2oyojbYzWB+cuVGxhwfgMOCp2hyfQb0b0DPaILQQFsrGLLcRL7Lr0WuhtDMsQcJgjQg1oJqwK6jS +iyY4YdogijuUbxLe93ind/CVRQVHmjEOezIa4cJxbqx2ki8pBE3En9xs3ElVgMGlZt78bsrnF82O +OuMQxm1mOBHsn92iHMpmGq0uqFVPKNBdTZZZ3hCHtyWmBuix85PMt0eEyYvsK0jcdSGY+bxaD3QE +ZjFPSrvN4oFjSbo7EICnlwEvp31PE2qqRncHzDGsoUYN9NhBCER36BVCsn69saUVbJJeQ97mi/ti +LbNWtNBphbJtMN2DCy1thOtDN5Ebs6NiQDL7BBFK0mGv9ZRGzDag9Xto5VtTtq8tKnPp2CeHweBV +hizFRtzW14az9XcHP5+N9ebto3N6SdYrZ4Zl32Y9QTNBgC1tdEq98qgAVnDEs70TqAUfS0s3iXDn +DjKyQxuMcAHjJ816RjhfWpBFzDi8Ms2qBteeNffB9bs8zwpNO2qwk1gwkV7StYp8Nxb6ZGhCXXE7 +tDdGWV3HDUBp0TC5iwxFhNwNt0rQNT2BG66+3eWSuDe74pPsbC9DNexqY5FEYhWw7HOoBTrZzeJz +8BR3BE8I1/YKHWGLaolkRrZ0JkNCrAZev+U8m1QXCjChowkHVb+66SUMj0Jq8UsZQc921I2d6hH9 +9pKnTGOU/YHDa5nBUmBpz7P8+UM6RC3BEJK18nKtJ4ZnAF77KBiwT9Sr06hhLUOYpLALr+xPAjQq +95Xt5xJEyPngKBSqFk5mXGhtPfV3RFjaSwPLWQzqWmWeIKHAjx2eMU596yfXX6Pf26LdSuE7LViS +mciNwZ2hI9ZtxDHHWHDT7LsihreaqTqswKETGJV51m0jeoFaNWnbWGOEKBENUhUQjYoVjkLAXmOG +n+nN/1kL6dm85MxBbV702DUfHt5NNcclSqMgCvZ4YZ28IkYZnxj/6SZDk5kTJ5XTeL2EZYXBu4IM +gwExK8arBtf5RchLwmScxwIjLFsQcUwFWA+QzYhW5XVQEwhHfMV4CHr8nmHEhphSxKVUy8EnWudj +zqiY2tF1QcQTpB4R2lkUfPmSjVGqZGuGcNFdffJ+WgUYQ5qk2SvqXtmT8zACilbKZ1N4NZzRztae +vL3FMoIW346LF3ZZMZF2/SEgoswdSn06liyX9iiyIxOt3ctyHpHyQZm+FHkvLpfqZVmOuP4MpImn +aJYxvpgRiMO9YpMb9tPU6nLsHHZMbDxuN1R4tucGSZYo+i4Iq+wocaKumnBmjZZ5wyCsHPICi8Yv +1bAjtlKGgdwy6aiyVLgxIexhYu+hZxa7zHPTyMS7xrL0mo6aFKFguYVpgfGs1tyqSe/bFGKFl8JC +Jo/mQpsR5mcsNVdP34IwuahBoWH+PNfn+HROcPZjenYget5RUzZtTevcH8pB87ZbkQ+taRkTMzDS +eVbERklHWGl87SYG0ixYC0yW2TDZv0w2FS9T9xPMqNDWUL1kka37QWvIcMED9lrFPBU8KjUO7LSw +exLC24JATs9quppCPriCszRbowijIe0AExYLMsTnpWSUdLohFL5r3L5DJGNtHez0ESc8X4EJHIn7 +gkgRk0Tvg187ms1Za/CnMZ4znY3blbk4OCAZQWVfmywrXFDrQtX5us3rTvClVaL4qaq4NV8ifKjV +FjaXw5+LcVHT0WnWhCJ6qlwUnC3iVtNdd8R2b2d6qsX4U5G1mOJJDfqI6GWrgNrvAdtGVNBzY9zc +7Es6eONDNoWyYUJu62ODOUG1H5oGx+z8ne8IhYAB0gM6Js0E6XUwjKghMXDOQ7UYjt78y1yNPJ8N +AFExvH4fxu9l4Uxgkf8MOS+PhHyHkK/C4u5v3GJmGhxwdVCeI9L5iJPeGHGmRl5E560CKd+FXvOv +eHIeMaWEV2811N0U0eFtW6ITwlziYTdirStUxl7T4AO1xAGqQ/b6b52z72Tr8fqPVaUY4Wa4HAcj +C3uNB72yVTy2Le8KZJZisPSn5DpkrJIVj86BKA7Us5ai8+EO9cDJNRRuP+bSsJX9xQlkau8JUcXb +jOi1I2yHJqQD4DjTMrcZKTybUdasYHSMHAQBeI7jpjgpxFLEawZXPdWu3sLIt4XOUB817I3rzjwI +99CErfMI+9Xxx8nwfZwuBre0fEq+YiAUhNYt1FHLx9vz+5/mcMQ2yGFvHVkZC66G/X4xe9vbPAwp +ZvjmNX2EqmLG6UMjtmqg7krZOc6edKsBoPwWcyuzdQm7hI1YCkt/LYqt3VYB89wA596Pr20jrxxh +RP72k3wqhLNRjekMjlbaWmdYEyKgZ4RkmvxQGzwoG0LPlbmEP3dCRaC1+ezL6bWpgi7vF3jVLcq5 +tfDOlMrQ57ajjnowVJtczfe4DSY1MnLTXGdVQcsn01WnnQUVUCUxT87cTZCb7SCb0/LLfTegKPZ6 +HllOPU9YRYR0iUrlyyVf/FsLsKmnCssseMj6ds+KigpAuoBEjqAAMzekh495ODWj80+u2CPC/h5z +ZSDP/kZHBDi0ZPMIJ05v04aa4pczYd0/x4vCk3VWZJeaq5uB9ob+GP6hyQwq718tp+KKVzsQyQih +o7Ogjjnl7SadnU9mxNwZ+WKs0wiHSYyTsMIHKe4T3bl+GB+bJTrxWkCSWQ3+m4ywdg7QUDhCWdza +eeKeHoVObQ95348TAxfk+l1hh3RhUa4AlVQLXCiZmQzVwp8fasDYGJ8iNwuDGn9HVEfp7G7toWpY +WMaQXJYrY20Fr9Hacahe8iinEP+oAYZ/n2bemU7VuZautWjDmCrpyF8RCeMJ6GhDERcKvKnnZADD +XYzLcuwg29EBNsIVFYyijmMwuNJcl9sE9ivuINHmLHEHr4Fb4XcP/EKQvtVwyp6bYAxmiyOq14DV +W+EH045tNmqhotSNzrScmf7IS2koh0Tuk2MOSgS6GitATap3J2qbvNehER0KrSOZtq1K+m/vaTMf +O1nPjV9MlqzllKzHrluYczvtUy2vBRRfHiE8MneotQkjDfOsAnxf886oUTSdNU/HVVPQx1uDP8DD +8/ey1Cmax9TgUXfGqxxXCXFNQS+bh55zTvPFSqgopYiKqD1CghJQt+PRIhtYijTiut1WyVTYEF7b +9nFhTpiRwEJzYExFp+LXEHEeA7ajCE6Ol3s9Sie1UKcIknXD7ZdOuP2FvvPJTE6jToNLKeRvIVNb +fq0/vrwDLA6Asn9p8yMlCdpysE3tfFzjBqCs6OoaOZ/YkWhFOeCOvlVKm969BXF6HF3vuEwbqB0d +XbognzjOLKr3kLujooKUlLgkC7lxMdWpe6Cn8W0TsAsjaPSAvrhZa0KLVsC53YgzV71ougLI4MTA +2VhOsWJgqFm8MiGTq/6AushaGWB1XPz6i0xTUOSDTknr4oiQiUUlzXXJU8jPcoxoPHJ5IX53qV/H +4GOn7PZ4dbjqEym7svF4NkJEoZnTLWlLj/1EuNVzQipIRS/jtqk4nJ4n0XbxOiaKHkxMWTXT0lJ4 +QAp70ynSx+Spx0lCj/Q6vYsVRGgBBkeK3mwd9Zy8O6KCfZBE9M+tExpAQ1ViGFICNuWXtAcFvCbE +NUOo5IcSFMIGzl7CBzPnSYMpQ8adbMkdWzXiSs/YVCHXHkqAfNvl6bQoiDhj82SlmtKObl1RJ1s/ +ndnriIusdbBTYGbqUKCAG8QnADTqZosO0A5ipFJO916OnKHWT14pvfYa858o3E6/Hidy3kgOPbw3 +O/3u3otz/5icnfHU/ZJdQf77sgNIBpklYXNuEspRX5BbuGM3aPTz/BwWXTJNKQDK+TIqx/5sViDO +OwZT9OkjcCPK3jq3ZsX4vPXt83ynW11Ty91HKrreI1kxvdTibWqRDzyFLtccTJyt7Dw224xgzXS2 +BfxJzTr4UqxTJ9tYYYerCpR5a/Plrjd7GW/chPvnS/JZZHkZJZ9CFmT2ODYVtoH4ybwM6Nenmj9U +Q42V5ZwOUfMMG0mEUZWdBSpD8GPFWJojzEIJqnhsPUV7JuAfhIlMFsS0N9QgDTBOyliHbzXHN81N +JIOoPzZiAJX8n3YsVI1Irxy+llbD5WXacYnlXEnUhjUhwu9tqg3L4K0Jalzd6XV0i1AJ3SF5BUFy +VEJThLJZmme4iO716MYyA/qUh9Iv7i+pv7I+F7xJPyUXWlJBXlnI3+q57DyLrihdkQ0pEGvqigij +gixOCnN8e8JfWHfsXTlnwpmhnW7uAksFhXECyz6xg0+IB7wrKAqXlb247pC+EsG9f9IEmXvLjiFY +EaRZwiJbd3h+uYQFiGkUjpCiwopjzHJd2ad4Guaz29MqyNp84V2ZESBZI9bcokHCEbTmOdymVl1v +Thz8OyIpQm9hNJ6HjSytsVFP4SQtyVWnbABzj9QsL+LaoTbXxRCdUKCXmSVjHLePlibdup16dWMF +cyqjAoGAnKdSGFePTTidqjV0lwo/55fk8Oq4d1hxdlXrqoYO6n4Fhbz6QbFD0Ur0sKisXNNlq3Y1 +rp4CC1NUIHWhhFWm1ZOXdO0wu++aoGT5GjHjVq2ywgRKdR+EODP3ydYcdYej00JxrLj2I4BvHarI +laQIvdw+dcPX2OIIYjpIJuwxfAofGoqKe2/H5QX/qqdFgNSRTq3sKVrZdphhi5RhszrVtOXXarZY +wV6uZceVlLvivU5v7KdaTi92M/lrAl96cFD4lVjQLTAjuhHtKmpQGbYefB5hr32eo8qnYjdqXopK +l0u6hofXY+h3wtZxiipXdMCOVLPPFUVunZlpm2pwkuTdhq6V6GZ7CJ0HCF1WVLkp0Ynbsve5K2g5 +gnOObaDIEf2YNyBRibeuhT7QYH0b4MtS6eOEqODW86BQlAGhujth28RHiGeAXt2rucyymQYzD4/X +S14fGftSaKHUG6T2oRReRl+MtYNIjx3easDaNUL2UlL2qMLH6h/KcHv//mUMjC8+CZXCXctExCmR +W1TP1s+54xRaXDkGzurUjl44D6UT16Rt6k+cD31RgXc4SWc9jR9fjPdmXU5qy27Pjf10RTlghpgz +zrjAzyjO2giO9flNNZ8bx8iDNnxjucU8PhDhj4J7nOfkLocwhLBG+rod/h/6/Vu9F4XJ4FOycrjd +XPIl+U67d3KBgGXZgBrjAtfyVo86ZjVF0rE7tOMLcpU3YplDmAQVJo+io76wgt5PaAppZ5kTldGh +FBTNKAuBQ9doBY0SyozjV3M/ZEEOWSBboCMw7NGhazqbWsMd4qA6XG4nqB630KO3jN8yLIcRodZj +nBGAeol84R6tzUKDOEZSDR4fimGPyIlFW90EIFXg3AhRx2K485+PoW7GRthhTliLtTsC6OI6i7qk +p3le4wBoQiMz5IiqiDOqdIYycQr15Mab0YeKR+yHKshFcGRnp8WMzdvIjAFhdMTTDZ5aFhXXSPun +K226B47rRoldhpShPezxC/F77WEjXCFm0oSTyQfdjyZ2YSh35Iy6NOl0jih7NiEgPw== + + + B+P55wx82L5JR9GGSEvXa8QLCw7BQx3ZichqP7loJh6bPFcC12MjTRE9lmWVgFhxxH8/NEKJaNAO +KLRpwjxwT/uAH9TVxjrNjXJGqztbOVpdqdgKQn2a231aL5jhqWLsA0fm16qAiUUj/jynea9DUV0F +Cy82i7CyCtIrAxsnZV3SND2dYKUqHm33Vl1vxSM2uL1rh97HMxI6SgQ3ziOywmu4YV9CaR4VFqBw +/clOTnCF8PG9VDoFNxdi2R0B/7NxhI3VuWr8/e3Gmo34Tk8HeS2shio0K9mW7p179yPpeAXB3Pbo +qSZFi5qrSO+iRhSSvlFuShCTuXk+RUIEQ+vcZadchMjve//8u8qmhNaLGdPkWfZCN51CONWSQ6mV +AwoKhBtLw1hGcmC1VP1et2vd0SgjUvgLEJOjAtk8S6wxy/suivhWgopVmzRT7mDYTTgCz6zU/tYG +2q7/vBNzHF2jExnlSuvNkZN2H8fLGjBnO2+9fL5GBrRKF3tUZKBOFCJEZGR+fX5TTTj05h9droOT +x8QhO+SEWKH/ChgnR+qvKbVClBvbmWriFNb6mYQ8MnmKZqAU8UtEHTM3eBx5Dn7CCmr8XunhGTvu +d2KvKOzer4/9e8bDGbR+DUSV1qNZAYjyXQv6EoSdcGkwMDLsM5rmIgzCV3wuC4jQTJCBqKJxMBfX +dtO+z0UowQ2o4TMCzXgKWpajPNaCazRYgiLgQOH87GzGdDa+zaYr7EDMDGSCKToic+zegstpYAQS +Q8vFIfG4jGSnpjfBgVVkk118Do8eOysDbSIcssp2y9AdIh5EmTFZcKCDBBUTob3QekdXqkxy5qao +VoBce5hZBQ2RjEH0DgRGgAWFcMkFri28plGvtNZjI7700A8PIHs8jtavy5tKMY05DF+zn6AnBTBk +DHeERV2wmEC4Hchn8KYO6lZGGi4VLhEf6lau989fZ3kh7noGRHO8oOFb9jiaFq89ewRnBVadwwuW +H+w7Puvzm+p9/Rsn4R4amM+hOZ6em12ocD3iWecO4O2IU4LwEfVsw3dUovj5QCY9EIXbdvt+OLd7 +JEtdMOH7XqzdgTgpE8rFLCH6BiyEdoiu14JHCurpuzrRO26fj4a1CKi11MAVUPotoN5GOG9M2Fo6 +FabwGxySVYQRzEuyRXbc2BAILe49krvs319bpvPulO3T8CgJKOcwssmQVfxm1xMuHYJndm8GhaXs +JKDHwoq9brCbPTZBA2o5NKPJWGvZUGycoZ0rJUv4FZZYo0xGhcUUs+BLWxtHjIeVTQHJkLsKb3yn +cxrPtQm/9si1gBBwFOEYOZmoaxzqntYltdaT3/6sdQPJq2gIXUVlnMg7iggsbm0If1o62Xjds0Q3 +VAobZ0Uqze+e+iPnR8VF/K9VeOcaRwLysW0WeDfWYyNkzHjf2ZeEwz64gkwWoGNJKZW3pv7aTsFa +1S5PMA+nYOkzSw5PSY5c+xqBPzVHUn6F8vYRFWj9yO5Sczihahzb9xacHJYjCeHORyna5oEymBLG ++1YL0VhKfmOeet1R8UwFicbNHg4RYuC/hDLgVCBvfNc6Ft7YkMQZtgZHjim4nJ56EZ6PI9R4g/qY +EUFwxIYYJOZyoeABRiS1uvDQobN1fkv3aUJF8Pn+lFyJVyO4A9pxQmBKO939rW3R6hxwWqZbhRu5 +GXOkLBvEqTPW1C4zl64dLyhwEV8FH1FBCrIC84hGas/bB3WyWjJQpMZ4vACb8p6CFLlDSqo7AkbR +hFPY0Hrc3LOMPlTD2wejKeV0j41TtIEFOOhacV9BBDjoCBs7lqUATMEr0al0rzlmwp1FcZX1CC4y +a7kQ7MfY7qQWHq5xdZG9VROd6uHt7Ej+29FLVcBLnnUdgSgb98Nh5MOP9VZPPNhKZCD0i6p99lUx +PW/ks9WWdouR98HoJrIIAduAE2LzsSD0OL/kZLi34GO/U1ypx/8ZQRw1ibqB9buH154aUyCfvSCA +brbQdfvGkL3V7N+88HT90ym72j+JsgtkbWBKs4vRCB3BCJmHGOsk/7zKuxsY8cA5VfON+FyLUXg9 +kHg5bZ2jFYLZs/Caesktb6OQRdQ8gOCI6+Mg5WjrhzjuPBzKuTqL7H1kpKvgLEX+20uWgAj4EtqJ +MQYZ6RyeHMz0iSvNC7uiBFZ4d5eD0i5lCmHz95IT9JRGVy+HpMvJw/iSI7Nhc+q9VL9S52+XAcsD +Ebbxc5BW5g5Q0ItsGlj4pCxn56mzibL789ffSKnnwaBeAXAzzkNgzOwe4HnpaoHx+kM1cGxzBcgG +hHM5aWpuCDjx2eqgZabs4zqJmXZmTLhnkHmduYEp0ISF35eFEWLHqEO7PFjaKy31YGEHAoVwoE1l +B4y6eBpIi8uBsuPCxmZlwF1BmMHuLeGvt/WZiccPXsLVVC0wll3odDZbyDYQMMprAFqaC9M8RHc4 +SXdoaV/OHJqPDePgcrd7Qu7miLPQ2Am3kGTEm4qKX8tkovQbGuSSlWziVyHoHV+9SUeJiXB4RDFv +Jo6CAZIcZP5E6pAL2yjktB5KvkMNq5ES+aXBoLnFAotJnuxPNggtUAYkywqcd4bMlQ5SVbvmdq3A +XsrVOSqTZQwXsnG6QSZqKCLv9MQzyMTx2KGCQHgMsEGy1qigDSe5NK5Uj4m5FK40dF+qtdCjOnYN +h8XEghh6ktAymZOAxNRuxHSZmK0ZAsQKEk4IjIK/3rzWTYPbDdUATKMTe9foL3sXU2fyRHKInScb +Mj8fQFXqPjEXHqaroaScV7bEX/sjLdL24gw1mViD4dJwWZukF3Z/N3/uwRJcozOD1NS1B8zjIDr/ +S9gQ4w0KVjPNsQbi0F5aa0hThxfOh7+dIHu93hs2We7HqQmnsg6E418jEbmdm419cCikfNpk0YQD +3NWqGcLp/LZ2xjokoZPAHqAMd1rVpKvB5F5vriQz8mbV7DsyK1rGKx0HhGbja1oIDmjqQ26HfsLK +96cwTjahObvQQxu8pGd/sgY4dv0qcWQm1DqTD202dDZwvprSA55tu7SEgY9JQ9dOFZhfJfU34R4E +wyRsc8+DCi/63jAKY14vWFszkBQhpZyHcJHGxNcc2VlN6HB4XrBbZKVf8NV4X2IOGgiJi5HElM7C +2YJzXYhkidOnyunR4OK0fImXRKyWS61pEwcbGYbfAS9hG6mclgFGptgbdY3LCLzKAob8vAxKovcR +3T1waZWM8B3ftq9XXYU+NPLUiVahtjj7Vy37VC4NjR0wQPHCIk+5pcM9Kmm//oT01qGC2ir/WM7b +g5rrf/I//lFOiuxFEbSoyiNt/TANJ4h2PveRqH3ue9zkhTgJD9V8/ngPEnpwVsRBs95n5XR6cl/Q +ry9cteUA2PW18IF0RhNOJPftRf0LNZgKKF0U2OlOcc2bJy/wqZrQIuB7OVXLGgyTbVx2gNfAOypW +tZcEcbY68YEKDDIXi03r1zuRykGh6yiPw/Dx1y2hUDlf3177iWGWUOeCLtnVps/30tnVppsYlfzk +AoJa/Tp++62RocFaIwve8Nfi51beavnhViZPsD4tmGil+Std7OnFsek62LbLAcCDz+dafr6V+7uO +/XRvZubovBfP3zT/YPN/eM47r1tebV/v7y7u+M97+SZcjad6fnpA9ytoIW16b6GKl8mCZeTzLj81 +9F7PX3UMLzMMNXzYcw1wCi8j9ZAWoTN0WdBm4fAjRs3Z4Avu9bMS4/KGqz0TB4LU8fmgEMgmXu0y +jQi60VpRg7nSIIXLw1nmM/TOUKO8C3nKnOARvB/qmuSn5pr3o/SzJvQwCH/dGZydf6u8TQDkewK4 +It7La0k/1vOjS91no1bpxT7KsVJG1uz5/L8XRr6BCxubOLdvwuWuO+2mQ5jnMd+WTwsTy9zIok81 +fEquSqQ0o3DYr6BdP/XuJ5cAmj5yL6emfEneR0qnLn1KnrMaBMwjF6763h0jUjjOm/JDFWz5qbC+ +dhG+Ne2n+z7CkHddOoOmyPMOP5dtmp198JwMiZDTaDcRQ/ZeGAH9T0340T7iMcWTfSBS5OvtMZUH +0FIgrKMnCD3d/L3kEjgM5LPXk/wm9IP0qQ0/3ElTuspKp8d16A8yc+5H98mcSPPrWcORnffjXoG6 +k5ybdZ0KPzbhpyfSojvGuYlfks8+zq35vMsdVP3zXs93ctXzwyuRr+/8usRn2QuR90nbKf8XW4MR +AZykw981kF5+35Gx9fSpn783n7WW0h2kwk1KHg/3JfHA+Sj7lcvw6LIXsCdmuqwmfzyYjVf8Cy95 +c1zgbRqkjGY9GRFfQqeYpQkuOKFe8vJaDJX2YHDSvIQ5jHjV4/UgaziPUkH4DivIyGZyuWOuuGxa +cNc2HUOYm2yuHhWPp6vZUWCBM4v0wPlZHM/vYpEuy/SfDhseDcdogh2Q0/etNdcNyi4s42yKPXvF +zIat9A+vd03YeGWQRqUlXcyr3tajYCsY3bLe79Y1mvYsLGR4BcX9FL7vM+m2fBocTQWmxRaaY7G0 +DzfRmqtpognF1j00v4QwxqeF9NcZcOwSMEepf9sBTG43hgBoXeh+JjQ+wadwFY6c9o3xVvNf85p4 +fdkIKee9SxYR4rNvXfKU9HPZ7byx/HpaabiD2aPiKS0uLjx7dtFErpyH7/91ivzFeL4UHOXyg5oH +QXrOFvHTDG+DtkFLpJNJva1b4WGetHrq6GML/prj+G3azn3P5vVopz59flP+hx8rtSGLbjtTcEHU +0A3TBFWQCaeHF++z/CVzvo/E4zVYql5lF+JrXN4cecQLt7pYGBCcXnLK/bXftNWxqXhoOig/hAds +66khNfbSqrYB3r0HqU/eMJ03jMFK4CANz89LaEwzrZxuPtbAmJvtgDKh2cm7vE/Dbw2DzV6Lu9YR +A1iB5RT5JRc+WhfyCb2v3vss/LSuZmDlxzy1MNbdUdvY58XnN8V/WvWK756Xncs9OK6GD+2hQYcl +P1FIt+d2YN9r/umhNOyTRY/eEOqdy3u0pp+absH3491daXju4Xv3MH4Xuudyd/JDNazSeLDJM2kQ +U/Wt67eW/fDzdFhi3KDC4952HBbDAMChOpY/fEcMT871Tme6hVzoGcwvYYpwNchpq0qvQ84RIF9P +H8eXhsxD00xm5MEJskCreokHgrld7gnnECYMhhG+W2acCRE+7wU9bYcVdDOM2+o6mL5rQmNFcpPo +sXAOQNiSSnqeaNTgSPL+NQ8KhnAUPyo8LjP13y6NlZA1WDiyn6NOubVYdpRCmQeIuay5gmBOVUZ1 +utQXTpC8eoV0N5hPlu4hB7n108eiveXJvLSK9JifalVFnIrnTM655bngizVMQ93job0SAz+A/t4d +hAuyQpQ8VHAk14kPgi5AuBpqLQzUdeHEW92TqXaXd1cyYQUvoyjQrMsw5k0dfFkiiWCyGMmCkbBE +FvWhD3+9Ofj6Oo2aA1O5PDetO0fP2mXP687ST45Y+N0SW+xF3D2HZXYusddUDwiBpg== + + + 7yV9rbyEc7NhXwqb27lr5drKcBmoZ0+ruTu2bD9VgAVt8mNyzgw7V4UPW8IQwv/WzW5kORysodJZ +Z3IkM7vwdbsXCBEhhWrTQq3J+ObxijEmRrc9WocBev4SHpiRl7D/wZdck9XGZOMIo6axD7pPwD7m +GdAmtAyIWjliDRvKiActtgsD3oteYlYYqqdj5sPh6KGs4zRpkPEhdp3JZpng/LmKRnyF03+U387F +Eqi0+OOqd6BlkHEdNqdHn1y0CTY/I4IbrDJQmbzaksZ5gaOpdXL7g70EIwgzhM6EGMGFd5CFouKg +cXxHN5w5YduUsByTp5d7Zn+pggHF7ADbF2SIRTsdiYbTBxuQBTSU3YMYa/PKwzRuiHRQQU8HcAvl +347wUeaeQRY+3QEGoYd4mFcNIOS7NHVtllzvWtZxH00wKPKDzfWtjqVJO4f11fKpYh0z4sqMQgfe +0gaiUzyaTR02odGR5HobBdtiGctQ7ArYoYPtAgfC6Tiw3kYW1fnOShY5OjO3nUMtXS8yS+Pllesk +JexDNDd5EnxjHxpjzghqByHV84RbnRUUAw7ruPhBNOTNOhBcaWFtngBwOiLCsPNLg1Bd00uFvNNe +K1V5Rfl5udJyOj0QbmOwLUueNqYov8LjKO42FWQDQvPwDNNJ1eWAiTY1JmY/qUM/rG8hHYJDFBlY +L7kpioU2Mdq+XmX7oXHbskZd+BQD6HJaGZJhIiUVnkOWq0xt496Cn1Ypu7pitpjjCJXyLAeShAt7 +86eiMejCwOgox9iiwyFOqFM6Iva6qFMvWW865eyGhIzPV5PNHDpp9ZRarxXsdy4bAyfHiFgVQ4NH +DCtPvl/6fsnQhSbTW1zoi8+FnokJ4cxdh8GEZQ0dy6mlqwJrGbVV1eo4uY/hX2XMwTiXwS7ltWcP +kbanY3MQF+V8RRiWNS+pCcKKD/3+JO9MtPWvjcHbZzFL5a3mrKmmoUFDwjmZUtJD9bVVcbTbRA2N +MrWB947+ZRajcDBo0fG5GYGKkcYCN0MtVNe7WyfOAYlnMMiTbU3ii8/FVJGeCmM62yrtpN5EBGkr +KgwkRoSVZr8YBGb9+znWVJp2NCHD0e2wvdv+YAjGKs7EhSP0mYus9EXFJ61yCiytuc7T2yDqZR15 +h7yGMdDpDLsiVmlLPDOGXccsq+xASvm7kJHD53ePy131Pb2RzuZpp/JrEcZK5YU5hzv8GUJH6DxJ +mMd4XTT8bUS80p1qccm9KN6UvimnOGYQ6m7/iDyk07c6EnOu3zotxIEkilAo30O3ndi8/3adq/5H +7W+jPwCB/R40HafyRchHcj2FYouS+j3m2dEd67ourE4u28s+IGfPx9vCbOTfOdutPSFtqlKt7Iro +mahAFTdEil2HoCGEhYOAIPVbE+j0EccBOuYPIhRWyO/enw1BdQ+j4EaAT8nrVM1dHdmbv+4oaXtw +ND7/HXomambAvZZn1HzAreZYmKX99l446bA6CxViYfKIoz8bIlzOfhsXVYs6jsvuR0HEU9mxlGIw +jWQWNxWfZCjqJvi6jQgoiRgp2SZ2DZTTcsKPwWMorYJz1E/neEynjjBcXjhQUjqrGU/XwF96x0tD +Ga5Gf71f/RB/3sVN9HxvtXwnZzU/HKbAsAMZ3La7CZ4hKo7vBw8Cj+sptcRzY+fpKrjW+5f5DmN9 +8MCNDunCuJzjum/6TibYXedp8Z7Wcj7K48r75nh028BO6OBQXQojy0O2hYce/A8ITTk0FOchOrc7 +MW74sfzPz+W37tB9lrJNX+9npvAtL6dx28klhuZR2/2m2Gfp5VLYhXNcl29N+Au1W+lObOLXgzxF +hpaEpxGJpXSyaGEpw013Hqjz+j7tkLcm/PRi3Ec3r9XoY6/11kIpSI0A2deCVeyLWxU7aTL7BLgI +VeV1dShM6bw4nG+Paw4Q4U/t//nd+qbRxG6VDnVic3qTe771572e7+Sq56/b3TX3dtK4v953Pdv6 +rrCluwLWQCp2e31dChf43cLq+9SGn57As3p37qQSBK+qEQKTzw08yVKO3OuTznfpjM6vy8C9NeAv +PMC4N9nF2Nt7H3uX3oMIz362h2p+Ov3CCGv0XTcMMB7VvFX5NG6fEic6vK7yWzU/r6wdK58eG7Fb +ZFSoyAaBcMLrbI0pcReO8/DGXtlFI6tzP4NOL5v3BvywvXNGkKQ9HCxA+0tyZ+euZ8elAZqPytcJ +qG5ewqKYNbO6rCof1sx/nA0skFTOIo0YEMoDU865BdOCBcvlNebfOtmTChzL0wASxtsYsbVpXl6K +3i8mhttKOuCRuA/CTwYT2iwaM1Sn19lxMyK8BFFv4WirhxOcYw+IRPslPGAU7E6Ju1/vB626PUhq +XXhUOQ/BIl+WU0UO1hBkki7vAE1wejovavDKXa1ym5sLE02oeWdtn1OATuvEvLQtnOxKgbCc+8lB +HqdkoYUoqesBegCUwQsLFsQhkvLDKz/iUc4bLwOPsV5sWLd5+OmJju3Kxfz1fuMXZE99Phf/6eMr +lNFiLrNTZKP2VkFWxudz8b9QLznCFUH75Jfkzjy9zRzcDXScnCych4GXnU0vsUckP61QxfidN96u +lcKoYMtHjavT2N4Trc1hWN6bl072eoqtOh+QLj/CguzyCNByeKgq01CIqQrr7EUbaKv4ph8n09IR +3gahh106cTi4xXXvkTExKtjnyoiiI5+r9KFdS5fE6T7YQ34QCwKyPNnUA041Y92lI4GV3k6q03C9 +yyviiuK4+1Z4zLr7lY42zoP4Vnalt97mP44I1rKSI4/TyXgdhMy0mPMIXEKPrCxce5kc6JfJKgG0 +dNkLNe2o8bM8jI6vuVva40WZSrdd9sPqhDOgX674L8nTMdhJODX8Rpizv+kDFh0zYruuiF11AmmN +ftRw+9y//qv0bAMFTek0a/HE0BshI+cr7MJ8erD1n99U89OKdijU/O5XKM5t3Fp5Lj135tOtkh++ +Fx4uAy3oDPrEr/dLgvK3XRk+tL2lc+SaXY82yj/fj4A9De8ffNibeUPK3Jr8P8gezhPvUJd9i8Qm +05l18jI+lf9pNSOupvfp0uWSgdNzVeJOc7ivwnwB5Hmv+IezDablJumYjpZf3hlq5LvwwG03i/Bu +rtGgF3nfc3GpRHGml2YoXu7etp8PHK+KQvUWRty41I896E/FfzpN/XWWM5rlMheXq0NzcRUeoXns +2yDtcEQL42z5vF9RAXDWTkN+qbWdHjm3pv38Bhp9nRr+HsL/dlydin8j9lr+MiiKZC7AdTp4viQf +633/Qi6zDWfv85t6/sIHiJEl6ArYeCAXsQb1qtS/y6/V/GVzkCP2G6+UL4krMBzf7oRzcXc0P8j5 +2Plh06zszPzu1psybQ7dMJxvjno05yo73b+3en/4tLQc4qyI95mOk8USAxaR8KEzYeA96l2gnuaw +belUyWPNPx22yYCSviz+cmhpGGm443+8LtzXRQ2UFcM/9uiVvghIDaHTVbiwzBaB4rLuG15uRyhw +qy+Zl3VOrsEw8ezGI+HqMkjb2M4zUXhbKwr7rJ6PZsLX80DC7JlI3oAdW9sMpX3lt9ZabzDyGZCf +5xBTE3pWE9tgMKzLp88IrXqExR9ILTBCz6VQ++so/qjpyI2QtsC9fue3oirSiY9ps5QT4sAdqrmj +253Rv9PY5zQWHhIcZlBHrTzNkVFYegSeyZS2GBqLCoYdtlf+XCnsYciNT9GQm/h5x/GM38PHae1P +zGAPo68JFzM3Z0Z2iI9ALa1tVYqtXYaAX/J1BAqpAx5G8Cdn6AJzbffHq/9nfOrXf//d3/6u/yQq +9vonoWKPuUyXBsmiUQyKL+HIwbsK8edV3FYHPdfntZbv5Kdq/vMTJParamNqzWT+cRLFL8mnnZ2Q +JzCqWB5FHaLcWWAutKQ7C6CDUGHRLnfYM9TQ4vckc3L0DnxomTHEhaHYudwdAy4HUIkL+8oU1gxw +9HsX/uyQNkK8OXr/R2//V7NTcFGmMy1pMszNJCIkwMubbKkomOReotMAKREQ8tVJ/CTSZEuRiM54 +xgiFs5FKXTDH/w9779ZzWZJUCb6PxH/Il5aYh8jx++WxKhCaVue0Wn3T9BOCoIAeIqoQUDmqfz9n +ma1l7ud8X2RlFVmIaSgJJWm5Pz++bfvFLsuW+QBspPz0bF1qpJR7TOHlDX5qFRXn6PBPO9W3ACTG +MXG1egY1clb/KLWhRwnISFRGrUO9ElAFEjNXD3gM21uRMGvY5yn89KvAkiS+IHNqZxXMNNRma3jz +cgi73iafT8vNjS3F9jvPUl/R9r1neyt7dw3MlrVPvQMfOJ63OmMZ99sPKTh7EwN+DW/HY6MmKti4 +XN5VwD+fhg0EaPLZpOA6tMzXWfqZGkIILRRcQxvODsC9N/nWzgH9z/GCj2/A/nvoOl3OLjGH19tU +gIWcwjLYc8jZKEzY2DLzYcuN6NycActPaoxbvYcfiqKidy0MBcjQqzN3CYdOW9RF5am2w2y0A5KE +aFqjKwC4Hk3LeoFygBHfo0VbeBAn9MluLm5LoLtydJkG/LMOfafuu8cbtHhXH1AGq0es5Va5z2fj +K9Qe3Uvx9aLV+x5LN1ajqKetO6TUrGbso+g4RunMUsPPnL3xG+oRe7RK3d7sBejb0tSV6HTzQQVI +zEAtOUGbvDubBO0eN9ZiPyFT+7kxi3qfGs+jv1biF2tev/feQvqJFypCqlOHQnhUDzkyHotH9/be +RkhXtMqWkBlrz3tSGdx66Oxna097h/Gy7/BxoyWktRqmPmFIdg7cvAMWvnla7EPq0SUT5u09hhEx +ikY71sKrsLmm+rdYI7GWNd8VIyS98MPbnWeEwoPwceewvydSPGVSaA3xXGXqtFu8r8xHqXLQZoJL +7I2sPU6nVqJsNPdW6T/9V7VV6eoobR2rkw3ZSrRXwv9b+TZOR/KDr9h3pfqNZolC3le4rVcoaapd +qvXcihEaytI4wtYUSte0eHhcBnK5GwybPNqgskmfva+erWV8864OfuozfrhD7d/7tEIDSy1b8xYH +084Fjo6lFrQeLnkIi3oZg7Ok6Ygv1lBCjWKb97tGk49RQsneRfghNA4b6qhfIyx11bUmNC7bMYDx +ykBYnbbdhWrMYXLatoXF9yazrikuZAt69ErpTU/2aChWmjP58GE/y9CUoGe9cPJ+St6uRfMqsVBM +3kO+djw8l3Z0OsIdx1JZvGYK8CmzS+dFc6izcMJ1nznMWMHs6cQJj84RBrvK49WGHp5uh0ENnNWa +5EH3J6v6ETuNq485t46UsfdvmUBLXccduzmXdrfxzd5CszTrVMO1GM090Y1naQA1cCv9bDevuzFZ +r9puZYfRiGeLllheTfo6X/0SfmUGPdSltpX2Xnu+LMYfWAk0u0t0qLRPU/PLamzXchYVhM9Mq4bv +Gp7b7m7AgIGxyvvY6WzG4S94rgsXWnyZI3BUFJHfV9snDWBl//5WmRMFvLzx/UvdEg== + + + Dm6P7A0pOYX57RyawhzeKQ/Mp1O2rjNZmNDibzSfjwJOq8scrS4h7LL8HZnnQnYay6d+3uU0Blbi +iYTmU/qt4ecwZF23XRSXmbyHdr3j0kO4HVThRji7C4PYO+mnRh4xAkAqUrlmW0+UohCgYcI2ddRa +Bb+PAFL4Ladhsak2iOV3/BzypP9dDxvhIj87+33CqU9xLLp/gXYcdbe3P5f9kXN/+bArHp70cTGx +6BZ+NQ80NvnU3Uh0JkjXQzhxdPhMZ9o4O0W/1/eefXfQH5jBO9N998W+rgXpt1jQGTIcvPejLjsW +UZCYmNwuMJMbcxEHnREwmh5r+IEZvPPR3v28b9bCDy+cl1X2P/Tw2yX57uL92krHyH2pQ7d0BhDZ +lond01Hk5JPWut2/e0UOpLCRtTcXe7gTYNYYFK7h91bPTsdhQkti+gi9eWsmk3ux5EO40ASieedq +dewc+WrDbSeyjwAqJ3Nm0M46sf/0ZPWm976mg76M1IehTQMD+wireo96kyealWhOAhoWE3qd6+O+ +TRYqP7FRV+Ru/utqrLqxluQjUK9ITsSN0Ue4mI8h02DLRif6tt82j2OZ0+dG5gJJfmMPx3waxq7p +Nssyty27ubZK3CX19H/f1ovbBqjsQvSQokGz2U852VOYz2QXaWe+sBbStObty8jsMKImt71W2D2j +xOJe8Ub4eLyGlsclffa9OrvjQw7aEw8otBkeIdi7PPJQt6dDfIQw/9AOyF90hYONPorcBJOEMQ9h +lX+MksFdz7Y3kiuTd5qP2LRtqss3CDB9F236E9PX2SfdOGWpvbazVdldbNwtNuxgVBuWT2MP1eDh +tRsvNXVVb7IS0Btn8HPPnDSFRUd1OMj5U9whpfLl1KEelx775CK+0jhqAU5xeZzjWOHGkuViua+g +DV6Z7UdL4qBgteSYW3zMbpFETGYN2X6PL6mmqGwWjz6KSau1rF4uwykm5qX1Jlzs1MwGqC4cU918 +N52tD+40aGaTtl9BFwJ1Cp9NnkxpW7GPel7BiIkZqlnLz17j8N38sXQ8LF124M0cMYNzt3Xv4eTC +2hYfLjKIsMcUGKuRnsiWAeUA5qa5UEdsD/8GhKA8YkFaGuYXqB9BJ+MvR+sHI+TGmJu8PKNojBMC +2b0YoW2ePEnRsW0NekxW2NMcrfO6+qWbFf9Jf//22ffH/NrvvzvZd1/rfR2AT6Lw5yI/AA5WhcGs +gfIHiw7aFE1oN+RHRQ3ptVRnJJDMl3iNTQphvEQrNQYYTnTsA7OFshUvdY1QvYd7Phb3Y7GKKcLk +lUu3PtYKR5iy+6t3oXaZMhT10M+aXIZ4JeeVqSYpRhjR2+UxSJp0o54BWpc7plwZekxm+dUWK+bb +5syfSn2Mo8axdeMtfUp4fwpZTHCi/Xc9XJOsHBkNJ1hc7dj5IZWfYFuNsFx2FiXXzXTHPp/4XT3k +Hj5AWG8LvTc+vBd4+SHA8e8R2cG51xQnu1KlOOWqoholhTvedg1fdsrBdbPoNbbT4ga6vEGUYupj +xzH7OEdpBtKQDIf8hGHaDo/WoBlcAXEmv7zFD6Xif1c1/cTNp038DeWvKfffLeHe3Gr6IjvUj6OH +5LsnSYftBjPku2MtvhXx7+5G048vy/n87Zuf+PL6h++P/JU5vEz2r/4of/PXz/8Bh2qd/f4dia45 +wzhptbyO+jXxGcD6mJ/JbZ/cl+s19ludob487zdv9hXxGcB+TEa6mS38IXaVNOfD8pdukFtaaTn2 +wFPJa195dStn+STr24JlvkdSURP1rCOuZT9JFlG07piVrGPnrdxfYyEXQi/VccMms23o3tby3buy +d0k0oTkvnzTAolOz493wa+YsmCKsTsXdH9w87lilSB29lXNqj1N5LPpWo7ttu2gou3DIhQJLnv99 +2TIR4PFYNAaTcAwWeOfoYfY9lY/d1eNt5m5Z6TkHqJ5Ufsg7ORpNKNwKGNU81ujfHG3V7YP9KdYB +6J7tBrFp5aGM6SxOA803sBlMT6+5aLrVAG43ZBP87+tUTngOX9z+WsNNn4kI/Rp8LQbPJjm3/b12 +VQBvEccEejF3EPwr2P3+0HPci0BDobzEhGavx2o0awN9k73Rli/d0VNzYau+noH7hOJsBGD3jmqN +hdfkdj270AgyH8LqWXMXenrYJiuEnY1sCxdiuSKbSTz7Fk57b1/cunabMKXwp6wBaCn+aw+/aPGN +LVZjw/bFN0PgsLjCgwjV1Gscur4jmF97fIi8hKhwjJ99MiO08M2XIqQwmzeBXncwfJY7GpU9nD6A +E1JoZfLm81NIrssJrYDxM9Wq/esG3Fie7vPZInseIzhWyfYvbnj9XNX29Sm8Xc+fXo9X2wFbqbmx +PbJqCvZSWdCy+g7zD9/5wpMfglji0M6cvWmVNWpy4/TjIuOYLFLmIhtaZCsR4+SLLHUGZ+xc5SLz +r7aSJ9m4yPI+IwA7wEXmx9jcjlXlInOLdy6ejr7IynkFP859jXFjP1Zu823pGErXFSoHucT6uj7O +TNzrjYcFPi8aMJrQQtJP32C5k2LH0B/SpPkm/9ONGs+/c8FM3IhDnovJv3uWdxDQ5qe7+o3k/ttf +yr5Z3/jcDOH+nyEBa0yCU1zxH5CE+eY/QG7J/v8XqzoRA7t64friLEG9YNE9RDM8NTsR0Bt2LSHK +4vtwbrRGsh1TuoNcP/oISJhlGxlYCAv7QOhojZ51MU0ULgAtgrcEqiTyxcaTak8WEFx9cKxZG/yt +NZngTAyt9Nq8R1dEEMw/63Wh0FfQFsZCG6iSi5yYbWZHb82v4PB93Wl7nBIn4oHQq80LMbRUlBH2 +UChaMIFsNKIoudsnrYMMnkyXQfRQwApHwqC5PtUaichaXKGPCQy/8z9YPG7763Z2Yv8A0IlRGa4O +IuaapIJWPaX3kK8AaDRrDvWQ4ZRqHg/FZOCH9McdHaSg9qhnfju2MzP8DQllOzcn29t88DC1bW3Q +6J/8UyNzh8lH8pMMDVLK5MPL769GNiTONMnw6tXrBR8/BsJfj+LAuPCjIZMA+vFgQpHM5uFWZkTz +tvPJuiWjMFDzZiMPu7Z41fJvIuy17IR8nH+pMU3DNvcP4bS2Kv9dIa5R7YhFKHhlBTaM5/ExsEV+ +BTCywgUbYM4W6JnlyemHfDiWF8L5rRsjoNLbHtdwqiuMCibjHOsDmKlhFso81zA2joU1+zimm1XW +2Aod6Y7TIQLUzSYbmRTENi8/pvHsvKCFw1YdKzI4wGT47jHKDb/xvIk93NymRabCcscdvPEnWmo0 +HHbZgfZdBJYmhzMBadZbJM8j29IHehOnB8w/UxhqDEAI8cmPH/CP2ldr4ImyGCbOqti7TtlsMkut +Ps6UdWG9MHByyxSxX4+4Tm8/wIf38hDm2zP0MYW/+IrDnr75P/79L//xmz/+2b9/OIuffvXl7371 +61/+5Tf/8Dd//ne/+ObLr/7yFy9FSzrUHzrCuZ55aiNCjOg5jrE2w9dDK5VsN3HvYe2hiV2yrzGz ++xrYb0CyzeyrFyZmJJAM8PfYLck/htvojruDTWT88nEL5Rvig5qTuuhD4zcWAQ99rQjcNexOLDjU +ZpRz1FWQFGnjMEEUKBWcNGZwfrAoElNJI7nZzc0AakNbtm0dzBdMf7P7KoJPe3LJTDtVCxEPZkVY +0w+72lHcnyNM0KZ37rOzMaP7jeu6Z0ZMsXsVD+topeJKnd21h2W5i5013e0cqppcoa6J7Y5bb3J7 +4H0wUmlC2/5wkA9E4SFfvqkfI9TuySW0mrAgG37O/7x6l1GLWvRzrjp4tVuprD1XnHzdDkXrzOVv +OabdAIuBev49dqdrBa1bMr+3w+ihkYd56cLp4V9o73E062tB7NOcNYCfUHXaFCo6/1b/n77yXT7T +Ui8k8H/oInutzRflVYaBVR9nwMOp4d27HLpm50Q5qX2z/R/CaVdN3Md8Fo3SiPitCNfZcoJO6dai +1eYePKmM1OSTEmzWcMyOy9I9qb25I0Yhqaelgs1ksUPccLWRIjZmbbs6DTLgPzbtu03L+y/Oqlu+ +Cpvergxm6JondiBexBDBaPFjdSZWSdmgCXA15CUOF6M9/FD28ocHwWAYITVNwUOpaDw5za14DLBn +18qpYVnC/ypJU5jDjiP4CPDbKGy2/c2tOwk60hnS2Kh8lv7K4MRdaKvIzKKF4+6TlOBJRrv1PJSO +dqV+pKIDTWTv5zbrpXendDgADT9qOl7Xs1APn224pfYwAGTp5W5nWgNcNJzR4mloEwcuqAEDrzVr +bbPeW8gHIfcs19JHesIwV4+j7HF+bB1WIJOcdoTAxCmq0UAnUMiQc0jKCAzDZ+Eua4irRCaqmkNb +yZ7i9nHqmRb2YyUoJdG6v125DTnLPmQX1xFmGKECZqh2WeNhdKs3qR/7ZZlZU8EZ4+EcdLywwx2J +rCzgdXavvnpAg7cDipX8joY555egsf7agWXYPF8ISNwU91vyjWuAXbWp2UUAIjIp7pND3ULFvvkG +HOCN3L7aT+WnprcFb/mbn/3da7VzOKzTYx7vuq3osNIGgQQ7it9CjBsiurYrnvxGpD/+7v0x6br6 +FM2BTQ9PFdcvQnTmryKOdayexymgQFK2HDxDjYDhbMad92CLags3ChqZ3JgP+c70v1Mp/YhLUfLQ +TMqQJ8WkwzjFoVoEhBwpBnkzRYuX/xrGRfvG4mfrm2NaIHRjm+phOeW9Ina6DX5sNpj5hZ9dPGWo +opgVEZHPelzy6ZG7z4o4W4rcoBR2OIZ8V8/I+of4fMKdHnx7Enf6/JZ9xU0Uo1gUy351gyHl8/vv +pKNpTY9OWZzWqIy/6AeKO7mIOWQNUyxqbN6c+cBn7plBoXRNZvg3smAxf/Tdn9Rk5rRryiJWFXHg +0DzHGZ5I+KwAF+MeG/dIfJFhVp6P0sG6+/llmyAit99IkUuJN4IT7i+Kxbvn+djPE+RZEeEtkJdN +7Jb2sK7vrNb5GTg7ejEyN5oNaDBoagjvY6cqIuM11g4i13ky02WwoyOnf8te4Z8Vp34sPMak7U47 +z6e6r3x4yAkUergKnIp3Z3mWPD4EMzSWMgm5XcamHAPlnxGSclsTdsxZqh6zX8Z+rMmhMU2yST/+ +suYY/1LhNPzlG7FpVmvpOthQLtXGlcKsTWC0Hj870Jd2EoiTYdZwOohj+U4DmXfbRz6WQ6bBqd8v +uTX/tg1rZdwh94i0b+Qh9YzpNSvvygUxM2jxy/uavMY8376vaeIxS3OeMhzEOOEMWeVr/hSdwg/J +HgtHUOCcHWZv+QGHp89RwJOm3e9piUEuOZBVxlHg5w/4U9Z9QjxNJA6C7Sl2O8Y6EmxfYstzit3l +oVw93+6pX3u++T34RlnpXqszzrftDDqxJHm+7ftQndNf1WB159hDxuWdE9tBw6/SwhcywCKqD+L2 +eFEAv+YVTX5+j3q4kZ/k+b4IcckmgXYs6fNd7DmCx6vr7zsdUG4rG+4v5UvcHOHGNQ== + + + +53Ut/Zq78l5txPz9cb2qBcl8x8gW/BTpAu2R2legBASvybmcSu38mSJvRHdf/yjIBHPc3gd4v0f ++sqU3nuBv/qjm5TNLkH3irFNZ9ibEtsBCk+Rv42O8l5L+748hvnu/dF9Bq8vDwOwmh2Fi+QUN4fc +QHSpB6hgMSzzNXmM891Xxn/CiuAqTn7izMu6XRa3usRu13gpr+XGpnubIbTb8uT3L3mOuFiM6sVQ +39y/T9GF5h7PD5aouLwGPMLnX5f8aaoa9H6n19dX3vX6D8mT5G8UQ/mzZnKg+i4hfZQXzfjFQujF +GbazU+zTHCh80c7Tw+eVr2GP8HkOR35N+Ax7vdobPXw6xqzxg71qaK5ILZ9hEO41dPP9g5fwaXaX +/LzKNex56WsOTxpCA6HW18vDTc74PewRPs/hyK8Jn2GvV3ujhzca4ir+8jy3s7bjx+61fQmf1vY1 +s7O2r5nF2r4mFmv7WZHn0aPxa8wdiPTnCRz5NVuNer3Vy+t/enP5/eT3YHm9B+9YRPlxt+HqPwzO +Q1HHd+fJ538T/k8Bhv98eHX+w2tMJD/mkb/5fwzXRr+4h3eqf3+M9l9+smBN/f+retqLetYfRD3t +n2RFLVR0Cog41CTModVN+3isAFSE3KAGgAl99zzO1+T3OL+0eNufKJZ1kw0+6/aDFfUUz7oi1jx1 +Xg+LEpv4cQlVT7z2QC51gNM9xIgW554GQBNwOEcsAAL83DzaDliRpyd7Z7V57zlAxqB0G561AEwk +GB06w1mrt31GQGJiFhcWFkR3Fo5bvi262JscHqOPXEpRGqlYLrWdEiD8cPaQ93D+ASZ2rMcCM7dE +mSC3lIs/jPAVkQzDSao8foyf4ghglbTUUMvBbFCHspENyXKHgCHtaM4PRkUdAoEbD6fMAsttk1vb +kgZWEeBpccEeEt0cJG8s2sgZMLJvclVgNqPnZaZnqTyrkoXBhDkq2QA5MRy5yQlfaZ2lG5bbLx6G +BzbEyoggXCeXi8+yPPsxydJqSldWpgfYy/j9TOPIk4j9374aMVxjOLGEC73EwbIvWpDC8AyjkVXC +DAvHgS0ImE4iNUiIaMkiC8D4yqXJM9NtPwxBPRDV4NodAnGO4XEJf879e3QSb4FeHEfl1VMwLjSU +mgmtDoU/ZJVBpm8yBrvcYscmFxB1oNzWMTjbq87f29WPAX7+OJX+xJBYyFOhJnPiHyPvgXAw6jH+ +Vj9jjJeW67JUBLPMLORztM72tAcgEd0/wTbMoKNXGloxJmZEY+8ikDH4XoZ58IdBP9k8w5jNQWO8 +Aukh22dggsxNyi1cScWxeN/rYQIKrX+7b0rophSuj8fW3nj4T79WvvDB+MAfW+VH07gigQpU20Qm +FhCvUS2y/tCoq7JWoVtb88pPV2VFzH4y0zun59arQX6Ln2IbddWunoo0uuORHgunOtIMh0TL3KtG +rUTFD0bW8D2EcO3W8Z7JR4MyhuKdiwUjG8GOax5oLgeL4ShBjIRydMe17CzOHdQu8kshOeBgmCKM +eC+aIHYpyoy+10YeOc4+Vg8C82WOTgMnZ9t8tgJZ1ylmwampNFOlxnv003zTP/759ch/AQbm559/ +8cu/fNgBf/Pv/0TP/IevPvNff/N3b/EyqHVNqJCyHdYtRp5yzWd1+A3ZmnN7cHEooITFsQl8qYbK +5uKI1HwFxbfLBPZxsWGe7dpLg5n16hlEv3p54uMiITqqGAA5oAGpDJ0pRMECqFAnhbM6SOSxDBHU +8BVhPYo+ahkSWT6sVEuojrFa9mWlMidwyjoYefC9eeBDrmtr7dHj4ZklfJyyv4mHp05GTRiYlGwx +XJytRCPDGOH9coUWunUd48FUfIfhVBrm/iAzn71yAcKio8r2ziftJB1LOaoIsb143iWPrrvwcY/d +uo0Raqd40IsEf60jW3AnpSpht9psQ54d59Tma3dRb9/qXWuzjEovHtLknel5YhhCJeozAR/IxJPs +5XUp3RDoOpEc84nlVw1l9zjj6wEyNFiunatWB3Cz03q6UTNHbPZk96BBWU/B9wARIS2o2kqAV6yK +3h5mqRqOhc1BS9L9Wvu3BKgaHXHl+h6eKW/Nyle16+yrABE6nCgHmCsL2KHVwcKZnnzzJqTJ/1bn +8OPT89C24owv2m7Ly2Zg/vT4ZWcZg5rizQ+yYjnbdIBAHn4yjTyh1oEYGZvGq5i2aveiDt/FB3FW +p+p/+gj6qkYcpdnrrPMGYrb66pl3ubyheqcvVcNG+VLR36N4d8jWHom7opbASJu4S7xyPNpv4W/i +WQdyYbPIGgQDXNW9vnRt1cq/t7KKAIxN7vbs1wX/fvrEEpu4OgvB1g4EwUMMsHPmqWWWNIWO8AN8 +VL/P/bM9IR9/LmUvL8GhkPtqRmFIr8wA9eENfcIW5Yv1FigngPi8KKofori2VVGB741VHQb1qP5w +imqcx0pb7moAG+muUTNOCV9xBqL8JJOefw+DoRPk9DiQiJcBfL7JV+E5DBMmlXq2a+LObIHnNvjW +IGJmh6wkAmvGY3ucNc/j6rFfSXUIpNjikIMGpu26PLnrQHbF7doRkYI1O+sVOYef4LUaWLM9amN6 +kgfSZ+B7HiMuWwZwcuUCtTkJs7JaNOoroSFd8y+mop264igtcckBXp+LfE4UC7xizeAM1cCaEUX8 ++HYGHKQWPAYAJPoM/6M2/zfCA7dOs7CcJksTMIAfsC2a4/EsNcYa/Jgh3PlifdJ1rkTs4e84g8dK +Apg7cI46fVKUUuORlcL4K3LCjMTc9Hjfchm1bkRedzlcoPfb/GaiR4BKe+XWNaczNl8ZiyaAqoEQ +AHBUBC7VGY7+y1L49JUl8vkHipp/BwvyZz+1BflEvv044r3yzKZdAkoKCKJDSe3o3tp0rAgwc+Jx +8oRF7Uuju7f2WRbnw6Pm0xZd+qybLRFnb7YOpUmXOmI8MNBDzgDE49vab7qQxRTwFMFn/b3CGo4I +sgVCd7zc9SQG7uDDnTxjeFjxErAR8uHubGl8uHnxpm1VEQaAg21IhuXIZ4G68ylfAw8BSDq9pXjY +A0e9RkUw+FGs0qPT7gw1WyGhKVTmoBXeLFebldt8/5Xv+tMsx8NF0Dbr/e1cBzgxzsRcaFvpFkRU +rRSe4HKv/MJZEd86wAyzYxbR/wefAkC01+U08E/nePyhWjehgB4GB1HICZkFAplHGyZb7TvU5R0k +OJWmJQUI8/Izr1UGXSrJX75X+O1xiFeXLyLjYTYaU4zhMoFP+V6RMgtDGbJU9EItAo64yODzfq8b +1KlAIBcItIETlTJzw2Ng1pVg/xU+mxyxwodbP5refXZ9FreDUb9QC+vCZmyMt1/2J107WB+PKxbX +7AQIsilEhNU+PSLYvZzii+TdODsRDxMy9Zy3YzqA7ieOwszWMbuNKofLEgAX7WR4seUwBIDYZpxI +boI5atWg6MnJSkO9KlcpUR/9Ztzvf1KVA3Ra7W0QnFvHrOGZhKjmzmcHr+6G7HLYnz87vCh7bA9F +fx9md1GsU1Zz17oa213UE5JzLw8oo0AI4lMa+QxCgGPV8YO/l1Hrzoo/c7koHJXFddcWgXnrPziG +l+tzORkhKFRtZe/x8GQY4ARD3qjoJ/8urVmsD2WsRd9lOiOzB1rVPtJipfRbrfopqyIne0IDFyoK +Tb7XIKxExQ2gnEYnI6PZPzj9TqjDCwasECCCCnbomZtgI/xG02ARobknLMt5M+ff/LPsR6C8m6oa +ItOEl1ciQuyMFt7OLIowE5tB3ubNTv1mVlTpddx/jv0Ix5Mm63Qb4YsioQwv9VNmCy/XOFWt3PAs +Y0RunS4CK4PxGYTGfJEMVu7/JtIHzzqJKPmmxzKdruGHfjE7w6BHBEh79hA+rBmm9dKJvnaL/rMa +UtGj6WRWNmXb09/rvcdI9H5VXPtWST/5p8k7Po1i7iM5B7krJF07sltLC3vLPcVH6RYQiCmPvQnj +mEU1NUxq226MZ1t9xfdxn/ieLs7S8lnKY82SBSYYEBmkorOlutp1ABBpgaI92BIRb58RFCw14Kbd +GCn5iotIljfv/ZMq+9c3TI5GwWlbZ+EXpyLFPj7dKjpZ1W3Rzi5bxplBIZTR3eA2K/6zTxwZvRGS +Ar5rqMCbhUFY5wp+ZAFbBgEoERkjRcm4qFcLucIgLJvF+0uRLR4urHDKquLBvcnKnBzlOsD7s0AR +dUGlCXjbg00zy8tnMSpq97xmCjCilBXucw9lgf0wCCkQLPUo4Do017B7x2Z1YxpJdffLYkqzex+X +SGF7Z4Vu5CcnMudF52NGn4E3n9BrUbHLzAL0JIbaLpZ/+/7/Sr7/D+FxUKnsFVH/tgD+l1wABqT6 +ie4Q1M69abD31GjuB26XF+SAry6kmph4BjcU46fbGavNSWkzyR8Bkiaznn0xhAtWEZaoL8+8hK/U +CJxOwTDeu4A/4LioM0yA8a3VIQED4jHvjprxLeKLE37rRjz3DTOS4yuoiO+JSv+R5+6/Ps386BPp +X5dq/uFfyl51Ynw7nMGM9SWyZh4ThDHLrmGGElmM7IoEAM4dPbrqmLmABIQFrhxMF9MjhIM9twwv +ZAdZW088F5n84576JYF9UjayHZgRRnA+iwq6XKVZka5DL3fjXCnM6k6E3S1KAQJp4cqByDAc5/JS +Cx/AKbSqJ84/GObeC+16LYfjfog2x4GCAWBvZLJFQFTvCgZ3Z08Bpo8hmdFJ1d4jxzwG+41Z+LrQ +/0H80NM0h9ns7Qf8HQ3Bf/v8/0t+/h996v7b9/9f7vv/CzED38REg/+IJr4hvqc6U/TcxKYTsRZw +tzmdbC1hOk+7xwUzAuUJHy4ipEVCkoEgRNyKWJ+MEjNiYNkxAkBNDjIZrQjXbk9bRdioE8DxlXDv +72QF/itUzI88jv6VaeYPbgP+9AVab+qzfgtbzPuVNuDSaWncdUghQhlwjnpwYwnt+aviU7r0NOZ3 +aot+scT00rE5MxMeqxn+G2QYf3sGIDWL0T8d+PeMloeQf5ar7nKnxhiBz9isPHgWY3RHOoBPckR9 +/ZtfZRm9BcsdkmwIx33PspAOxBprBBDZb5FFbN3z8O+Jn0b5/FLbB+6ZhJ834NaKzNDjOjMqOZ8w +3u+LXCSX2y+d2DruvNreysEy09Y1TPAbtGiSecmxazzKL4LB+ArvPf52lr9FrTZ+I+WLAbIjA916 +jF8uLos88zvyN8O8p9ffthJVcnmtQvCHD/W2vVYhUrseXXtebiuoxZ/lKrW9VuDTr/0WNdm+85r4 +p9WHynTu3qd1pl4It+jNEK8q+ulPrTdlk7/XqTWmuuqAOyKiphLbCQXM5DPTwYso/vi798f8fU6u +x52X2Mv6aWaXvDvHf3yC5HmwNd+X7+VolmAGYXOT7fTZn7/ys79l9eDXLKN5lZ/W6EjXnNX286v8 +jP06xO+zt47CuXEPZUTd+c2GfqxRpvvt+DocQAvEx/2NPBbDZvXk5/d/9bcdR1PuAw== + + + Nkk+zBbFefvenLKxBt+Kn4b5w++1NzW4P8luG/m93Vbq62Z7kryQvLwZ0fbazY11b7qvLuIhMvqM +WH18meUQWcoDXWePi2IMxXef3x+FC+K3bvWtxmuxhTDUVMLi84sokZcxbovWLBVhP7vWvU7qu2Ln +7NzwrEsMc0/ix6zk6kq3ut/rM7JhllXdBdeJNeV68+kWGTmf+vpQpJG/e/8Hv/vDUPb0n7Br0Xp6 +M6cz2u+W5D/1KHr1q/7Z+Qjm273+T+ndNNVN+HxkiSyhVoOjUcyRL6LQzNOlEKxFRnsHjNAhLrrH +t9BSTIXuGu1ULjhrPYJDNjeWuC6VnSzUbUYjM9DR8s/VSPwSCQ41lkCsOLsQEPqotZ0bn02dXUcm +uonas8nbabw7/4+iLklehelTQFU7z6kkDjXQLY3oJzSTOFXfyF/G+U6/wI5mlgS1TjhxRx25FZH4 +ybMd8AJ66e6gf6MY3rfwo46p6XEyjfzVYYMG5yFcKcKPaBPjRRFke/supuYc4GCPrB6Ve36P04bk +5eU+ntdmLrl7WcW5mZ30QX8QP8k+TXo+5M/DvB5TQQtxMUIAQfocTDL4ZCeXjLHJR3sZ05Exwll4 +1L/lTLaEHg+rFgsehCftH0LLsH18mTjaLnENA1o7Eiks+s4SPq4Ekt/cn7GQmRG97xgCRTn+piEk +vLT5MOoAWXK08rx+jF1L+GOZNDXf+I3h5XjGUZOCigEdD4o3PrV608qH9/D+kahH3qLpsayhdWNF +yv2jrFvfb0/PdufxtIdFQj3Rj3FTaL2yOMJgGZM1hGUYd06iro2wjnvbItCJVI22yT7qojWE8/PD +m7vGWP34FVeyxgYm0znglnve+2UKYGSnCu2YUxsnPTm90OajHElqh2KX9VZFYOZwChx/1MxwINxH ++flHrlYgD6EoKKeO16W6d6OdndFZubG8/eltI3hwCgVWu75CPtwmOABSdbG10/Bn/dQ2ykwCWe0M +yvylq6M4jord98sIXcyKzQG6tLq8oWyzhf9RHou+IaroZjRqI51hR4BGTGyr02jrUVu9thO2PykA +QRAyb67mX3UX9nDAJeh/ugvpXsyaqkNNx6TQ/S3rRMGcxZW6nB0/BtCzZ6VY85T9rDvMR3vIVMS/ +P138qp///kIzq/1l9JjarF623uaHRuN6++Rs8D6sc3rfJ8tOLA9yH+tu7b2L2ovxfeENdTUS1D3w +9FOGw40BXNcp+slvazLP7nPalztH7ywemPz7rPJN9BBjYXPMFkLugJ11meMsP5uYrKbe/orHnvXy +quohWGIJOFGFsRzHOXT91gyif3QTMxNjD6ekuJeQsfGecvPrx3o0uUervywOO1UoenipgZRfVzFa +1KV6iTlRdq3ji3frdg5i3nP+XwotcdmAupfdAEt0GkEjvSry1nN27SwqDXuzPu7l2/2PottkWWTT +u6w4LLTiF2YK9Mn1cIqG2Ee4tpPTvI4AVmLeIggqWBbTFjJPn60S3ecBgFphuMyJjl2WnGcIRMPa +VitsG9K8xPnjtyvAb7HdJkraCyNAZKcBzaUXt4HTu0ZbcJ1rGIDFv2aCuVUIVp6tjpvMhcq6igOU +RTjrNIrT//tkiuEM98Jf2Xhxicgc706j4DeWX+Y2B9oSugfjwbhIZVGOWIWgsPXSdOiOzXlx5Xpf +zLXvowz+vfVX7nZ+eSt4sG3zjZ+E6iiVHGIY5gDJtxDM5Zn/MCj8JoSQrViMH3DXt1OQRRID+6j0 +SnAosXnKjGyTFn4YRb5ufBOowSArTLTfnsxf7JIdxzEs882OfVb54M+6yq3pJNsAhqyG9exidfxr +QRID/mrHFTyEWkvAX63JYLWh+mMCXLhoKtdWGOteWWdRt5ZfXmH4vRsj0BMBWTv9qOMv7Okm3Kuw +AvgVI2huM75Z8qnb2dtWUt/CF+P8oxv56SVd/iZxl95nhHuTS8YH7WqhWEadJ/JLTinJuVS6eEt1 +ms3hRgdkRj/z8XWAFrQ051lmHZ4f5C0RW5byNeLHsKudq+gS7hTvwGBVXP18WPKvCpfm9bUBhk/N +j3/Nd8WLXVOgD/RJh6+jD8362N4pBKfvzmzgHofRZvWHcQufHYedmivldcp8mSGzkq97XiONewrv +P/zOqF+bAcyaJgNaTKpGdFppAFvdz62Ft1N4+/C7w351DiD9pwX90KfYdZfl3s0uFoPtYD2txQX7 +LPcVIi5la67oS8x6NbuQ3xf+Cl+ivbseQ65g2+vzfrXI7u2xfS7heNoqO0bu916jLV/PVglZumcW +29KMUf19j0HL2X/tNlvxZByrXP/r3tfa7GejvD0uPv5hgqP7Jw0Mnj4xU+ETuF1DTcfek79wmp6Q +qUUC32k5EKZr1AfCHieXf7sbGcBaiMYCVqQQUfeH8brPMJ/DiaJ4mwV3p12TGf+f38zg8+l+0sqa +cj/uVi+yoB9OYQTmpyhdtnd+jTi+EU961CaefjO2fhQNtmKYHF0Ce1dbUfQtiW4pqPVo3vJ33YyA +r4No9E5wtv3sjJq/trw0w54/SqkbcBmGoQ5pQc/RliBdSn0ztn603c0gUgAd0dptTukxXgmEUHza ++6iHmN2wnsRvxtaPohhlidF7RiF4XqGwZk07fZiMiKBGT/GV8vmmywahePObPosLLNLGmZcjfp2J +ppjr9ZVQyf0ltlF/s5IlfV62CE1tfaHzk29GZqLoa82a/KLpWVTyZ7FvoubtMF3RRcddLolDjUhO +2dewmEN0LwL3AcduWuwfvNI0esWcQRoavri+6vVOYDXicinXRqrviwsQsVXt3WMm5Rwr924sSfpC +P8yYSdUmhXjHlm7xnZ+ebjsWbroOgN6jccp9XIwSW25dm2homT8fFyh04GfI2lsfLKZ6xGcm8M6m +2P7Pvn3zibUQU4/uM8lpCr9o+bfzJeJX84rl/yTe6ldkLVs19bSc19S/cot2RW9/9PN7TUwMssJW +VlcPE5hm0dDg6jU1IzCyLRUZ61KfpjqsMM5sLbVyHUGzObMC4xTlfBudHcWTUPGFtQmLM0ZSXjlH +W4Nn+WwlgpeVWsfjU0f8uu8qYJSZZiFDUXz7Eo9PUMHEO5GVF/J9Nec63zKdX1XuwLoOf35f5XGQ +90uNNZJOoOQK8dkm9b75zhYElVfcHke5qBXiPh7XAffmJ2PNIiWXhzwB2Q25USvPBxOag56DKXZE +cKbZIKGrmnjvWbPcc3iU2Jv5OsbSdn4UT8GU+E3E3A0f/iqHmVSVstkBGLnkxqcX8tc35T55rzvd +nGpDV63NUOTHvC4TOjw200AHtKbbDbG/WHF7Mc90wBQwdIu8/2uU158MU2OHbrM38f6iXzX+FH+d +86toBl4aL4l81jmw/VPyszDKimN1XbPMm+yI2IpnktZkuXArnr11rloE4eP7h/ip61seMjWe9ic6 +zisMZYHSuIBKHJL1LMR2La2nZa6XfKw4vEFckS9KlHp3O/O7LHXrXhd7/vQkKdeqRzjNr56naw1J +oHOtnau+PSnCTuh3u9hFe6Gw8NTX7frpFmffus5nXG9U7byt/Zq0Qq3bWxxa5wPdgx9pdUAZv8RW +R9l17/0eYHUk189Udhyf1Xl34vw8j1936vXS96fxPmu9X5p4acmGzCuPpH2/Wy3xyZ+eP97VV+Xd +o4lxoLqqLbc6L0qMsZWqO+KnOX/+8Y5ph/TP/uOvfvmf/v5//vIf/+cv//rDB8rNYb3/yx/9b//x +7+y/5eT/8b/85stf/OrxW3/888+//sU3//XPf/nX78HX3ha8/C7e7E6LGOiRcawUOlTbkr122mYQ +BSU47njYi+hHDs9/IyPZTWO5OtL2k4/QH6aExUvs0pn+MIvTIetIPf7Gnx1kUhu5exMHCDd7H468 +I7CyjdkIt4m1Is5RETVJHjUKQtHOA4iws0eHSo/iesRrjJ91PC4sYxKMWEm2Fsz4uU2e3CkT72E2 +Rftz1HEUh/OjF3uJ3jXI95t2spFp+q3gpEKQPc7qTeHj6O0utEz9Jy15b9ML+UOcv5GweJzgsdur +hn2szU7hwxjTCLqEIG/MvkyyVttOEgO2tYBt7ELX2rhGkDm6vI7BX9j4fDy8xFoUNPCzZuW4eGZv +IilAmoPpUrgWTe2fNsHwYFqY3/wPf3Z4t3r3oKdH/S1755H84S4YFkOKZoTLDWOuMrTOYOAqdcvD +YeHsLNxuMk5aLLzTEbJostcifYj7WpvPVrYNA8ihn0VqRPimXCZLIezeS1af53s9/LBW+fCKnbKn +WTw5K1uKjeYEzzZqW7F94FwVIkV7teWINyvRZrNbNG1nmF2NuXnLP/oAWc3KLXpYbUdA6PSLhkRw +pBKE1lqKIdsVIzRPrFuKfTg1L35uW6QR5YfeRwQDOEvZ42D2w4ADCOOLLfVwLisffrzNcqG1dfKf +GrH5rO96TMH7mUJenJd229q2oxuuljeVeecg+/jk1BcAtdGPdo0nz95+gqQaVmJPnB3kk6+UStN7 +juyAyCVwx87V+7CbsKpNx86Z9OoYwJjM/KOWZpeXFW/28iKEY5rnWQGSJ98R/pqbcdYZQqyc5LmA +Ad75M4UxiqC21UBK9lHZYZPL5UnNGKDtphEeNuuYPA1SKpsroOzWdM7lb95VIrU/cDAkJ5EFXeB8 +jqtsGK3eohrkJkMgMcidIRAHb3Y24J2iu5kZm23pSmlmMKP/99JpugGpsJcv+JAO1IMNbhotyDIx +Yz3RkWf6fVBPrxnYN9NaIpUDzsjk2rRlOh26hvbQqXFVpBWEKRN9TsxRRK8lVfkCB2H5BlyhLS4E +CZPbOnEYF/Y9W/Fz6MZWKr/VYx8oNVx5vIEbvsZLINmpzmlGlOs3YGV6A7zpTiqIrFfLjDes0a48 +U1En8jIin/NYfgwbCwQJ53aqLaLhqngzr2+d/B0hWG+Mt3EztNp0bNuo27Bsi9Vsj89azxnt1yoe +0GG+BT0jZep9km9fgfHXzjJs52gukydxXQzFe+8AF1oLSxPaZXROYn704o2rNIJhb3IRWb9dRm3R +vDHciRgPLv5lgx5u3fLrNOouzhXrt0OL5G+xFhx2jRCTAvth9aW7Ree1GRt1UJyIyKuwD/js42xZ +FKq9/PZuHmHAWASFNvfUr20/3CGcMwYYBGX1Hb2J5mOvNtnKK3tqCC2QCarKwX6KdtbERmY/vFTZ +Hsml7JvJl0vKas9shfjv3bAfdfGurI/oDQxM1luXFnv8/eSfW3uC+Hs+yEZftv7YK3E7DI/Lai6e +jKvGrQvn3GjbDT5Yuv8+2gv0piXsLFEwbtagWgwm9Ukxusd1MzyFr0p8a4u4WYtZRhFec0Ymz8Ap +/Ao98JJdd4R9sjKJrDRuelp7W2+RZ7pWkpcO+/elwReta/fBIWRvTu+LA4CDMGWXb4+HfLY45UZj +AUX3K9ViLytzyQ0A12Ip2tf3AXhw2QLnrhWDzSRYzGQ9COIn95DLyQMLobF12RbLUw== + + + wjFldeOeOMb42FNG+tAEaErjbiWXJZRonQ3s/s7rfAWrS6EHRX1NnXElOd7kg+ONrCeZeySxn3dl +pxxcV4nNNICZbotXUFo5c4HhBKex0UusRjW/cfdlLJ6zjVuExZZ+yBH1masjuD7q8LO+DzjmDH1G +w8T6K0BokExupxAGTA37xMk/hyddJmdQfEfBWki0pLMDgDDVHVQZdmlUGoA6Fe2QcCfwxk0SN1vy +jdEFANqqYUv20LbfijRs8fe7qk2pMwdDh3aqBroqJdu8j4kZr5kfdMzvZ4C5fQqzxwjV6YSDcGM2 +6nDs1GI7Li7FUbZ2yMvV8MljJs/OtB2sX+K06r24Jqv39DI/45hJ+j7gf8s0k/rDLDu3W3XraYdJ +i8CmQ7YRGCbuCkg2N2ceq/QCwO2ikF1BSwuntUN6wd0EMObzAz++Wmpc++Zkxg3tpxgWdO46sZ1v +3RZu0pH7ooOPP8xMmvJD9f3HE9y/dRJDycwtTh1FZhQEqp2eNoRESyBemeIFsYKWTKtKnO5Suwvb +5ktGGEPiQAAEzhpRy0ioWh7fP1KanQFn8/Rcx6upt3Wp5yuPqF0HZmppuo/fpdtg//k9Hfw2JT/2 +UJs/nmv3r0OlmegHz858gaVExTrU+bGJcsTFzfGhbTWEtoaH8ziUiq+dWpIczOKnfEn+ruGN0mRD +PrPS94UXZSnCbKihSmHaclHvER639/bDDHHqsuj/0f177BqHS29rvzoCQ38GGHIKETNpRVOQyUA2 +NrqaSxAkO/c4wvH2j1dvC2ywkICQf1MxjcGBtMgxj9z2z+DM9FfA2TCHAhNpanVkI1qyT9TrPgeG +tVGxBdIMswsHNPtpdgcmIk/WHdwbcYnMpOzjyPL+lVsA/cHLAM73iXSk0s8XYPAO1nryuEquEb/A +CdLG82fJV3cziKtX/mCoWYeiD9Xff7q9zWUUfr15pjF/bwcHOdu2WgSkZy3E5IZjbm5Ee5xin6BG +8VCTj1xypwqLl22AEpQX7XKb38Ol+Y4N7d140aRM92mSIBDXTOcyerubPpIO6PJIAH1MkzdcS0mF +Wrg7t3xVsy8ZPk2bylbfnIeJvxiGg6kdcFSM7FYY7EsWxgFxF5aCOj69ncMr/OvXf1RT+uZnfx+H +iDWaX5Yiz6hK6aqQBBqOe3oYRQajkpmHR5vymceeEU0oYbitiEUdADmsgFKun3Jjbq/JtfQwiC+L +wY92k3sBBaLL3E3g59hRLtUyX7o8RVDz888vjyj7X7O+8+3rf1Qd4JLBkR2BHcgsJzkzmzgJlO7g +YLOz81KYoxraHg9au+KIJjjC2WOVQ9VVPHz0axQ2HihXE2Jk2duSPOvH3Oe0sN7Q6zqM2YR5HsVw +stfvA29WJz3c7rvprQZMNYsLyIfKjpiEATeiaeZjNIfNh5yKo8WMc59Y+jBx7LAa4+QRWBqIE6RX +LT/mPXr4U6h16+OSfdLqJTrlfhY2deGSUkuzS1i/Pb7XJUZBonvxpvkTr2BNA5jqOtVkybz4TIkH +Sa5NdXVklcHpUlZ9I7TPHDOQnAwv/mNl7GfFvv0Kn7SE32g3uAysLxdDLKzcXF475L/HbmCX8NbO +JS5O0Oq/NlvlurQK46fvQ1l8H4VkrmczObXcMez1B9WbwzPM4Zvi11pjtHdXlt0d/VAYocWkfahn +52KrNE817fUifPpCl7zGtse5NSaXuRo5vbvM/ypYM9KV4cbfeyQVl+9uN/8E5cWxGtxTle61RVL8 +dRmbljBU7kxCTw8Xd2OeRr2EnEKsSMlbVIRdw3YPuz7PoT/FYmO+59nrxc6ob7Xwya/cv5YyDM3l +TmIAti7xaTuKo41LrUQLMqzV3NcljMOxFM+hnodRj8/g+Bn2EvoUYoAjthjD86jNwzfPU6AwdKT5 +Xg/fL6xh32jh01u+nHdWGOobiFN5WDuwq4PjKU9RmSSVDcNXqgxd2332waJrVixhwt1OmHu67WmO +UzzcEYc2yxyt2roKRVqR8Grda1EcySfjPTgCKsE8qyetUfPbDKt4lAeYxTQWBiB4H9rhj7F58DYc +kSrczIYxz2+d7zfE67dP5cUMz7FHgdwbJdqO/vVvz9Z4bTDdUBT0fZG0p8kq0ggXoHXbCqSmSou9 +uboFfXNvR/l5DXEQraVC6r0rSyiwTqS7FZxMqKE6lyYLz+EWJVVFKHvVooc5nmQpbfUOM8e2qeIb +M9ZT13Qqyk+XviT0QIhBU9sZgbgwj9t6pApZFaLCQGe1T4X1pcUf8rATHnns5t+hmc1t2efwjBib +EamLG7z2cdSRFxWOzTH00zPR/lKTGDA2T4zFZuvZYbtsZoC6mbn5cFH9k3NOIctW4q+XGsYDWlf4 +uZYB1z3TxBak+PO6CR68CHDxSznCHEVprVJJybDdM8Y7KYzc7oJHq3idXInxtad6GqMamqQOWLNe +zbHB1ZvuML2tRNtF7EgBPENxlMLwrIDPi13hrMa5n/NieROqvYgQcNtP3n2uXcv45SP+8IJ5qLnn +Hx2R+Rrh1ldpuHICpkngpHfxSr/+i7/4/Iv3wEr/7s/wf247/Ls/M+DS4x9Rb/i3Ln0uQITkPQgT +5AAx/bs/+2DhVBkOWOJPMsc6N54pTiaF6lVWlvXzr5/8Ly1IMp8es8iNCiB8sBDhN/WXISswwpVn +ciexlm8FYurnX/mXMbXrsXipGOzpPe0vv7oOfv5TNZH945999927z/1ff/6Pn/7mv/7q57/4q1/9 +/UvHWfuKz5+0PH9TWVSNPo1FQL+8+S8GTqK3gybEk8CFxAJdZKJ32ZdQ+tzoHj/28+NAGTWlqzTw +EWoeMUb8l5I88fM0cGnRX/vMQ8L4rjHt6/HzgtfAb/Xxw1/4J2sT/Nu+8M/+6h9/8fevHxj0wG/Y +6a7tnp9YIm904mt98Q9W271s7N93W/++m/r33dK/74b+l7md+XnRNrw8f8kGrpPnsm8Yv4k+3AGU +HrmZt3moTNa7j6BquHqoy8q6Zr6E8f0eF/18ehhxV/ZJPKMeYUwhIreUl8Kk9BkVnymzhFkzkOx8 +ULNPzpPnZWPEdxTg/h98/vaivaPPUzQfsbQ6DjZEYssLTS36kmyZo9pskWmmgWp/XMILQ9P308Pb +Upd9PQ17CTWFiLxTXgrJPs6oD7Pp29mfJkBRqM7neh6MV4rh3r68FIc692fFAZ/0qrjq1ZWIyiCR +/OVFbqxgNGpRcE1KlVmqPnpp5RYe/FBZT89CF94a/Br0EmoGoTjKUSCzp5BsNir0IWyaJiDZUV0v +T0+edzojvqMAaS+19aK9sxCP9k42eoLx5MuL/KBxbEakjijejvODo7/Wnpcw8DBsDXEetiSMYxgu +kM8Rag4nY+Ny4PMmAQ8aFhnqTRXEHEJ4VGgTvh8+r3aGfUcPVGKNY046bKm/0eHOiurtHFUeRw4Y +0NK5V6tzrHqJoM9+VqeEcNkBFNGr16OWQBpPIx6RfvykmkxcwEbYpTsfEeoYJeenXw9h6M5nej98 +XukM+877S3d9virvbGgpD5ClxpxQ2uMiC6HcWMBraG9lamo3d6qNzaW2SxgQmIeK+tPDyBs79uuM +emSaATUoMbA5AuFqTChF7x8TCOHRoM32fvi81xn2HSVIg7XWFw0im/CqwTYHo/5GKvjlRZ4YA/U5 +Ne8EsFtAUrbqBEIYGky1laeHka7cq+6nYS+h5kAdhryg4Nb1HcOOgvZpqzzNIYShRJ/w/fB5tTPs +O3qQEnEBPSvxnIxHid5Y12KoIzhXjxyz7kO3SHOSJ7CM1SL6MHa0l5BKFGbzetjS5lshQw57CTWH +UKIgNVmdRs6w0EsjhWHMIYRHiU4xeT18Xu0M+44eqMSy+nxWYt3szn2UOJScKGheFBFuibF7iIFE +ZRgZ2JAVbcH4V/q4hFRh9lzH/TAqIlqaz8NeQk2BI4S85IBfxLDQSqZhGnMIYajQJ3w/HG92Rn2r +BCkQynxW4BsLOkxSi9mvfBRIOXAi2sekgN/R/g/3rGXIJAvtsetCPAp8gXDAHPES6ccDw0R5yWFo +x5iPS/NxfdB+1++H8KjOKfmvh887nWHfUYCU9+YaRkXVq/KEIwA0Iqo/jxwQXDLjLUISGZ1d+vSl +pHIJqYHExOH1sIFhPFN+hr2EmsNBzrgcWERH7p9hoZYq3inNIYRHhzbh++HzamfYd/QgHeb2cpdc +9/NR4toCMho+8suLPB2yxVVJEGudGXbQJu4x6yUMJZZdnp419FGrT4MemSYQGnQxMJ7wAa4hRyEc +4/75EJ4ci5PZXg+ftzqjvqOCTyKTTy/XyMPsfvXiEBGuKpKa4QKH2BBRTbfIsBpFC0IQDQNfgxSY +FPr8Uf3Y2vPDVjxp3eSuYS8hpxBONMUF8fSlAJiPCq0Mkg3GFEJ4VMiayvPwebNr2DdakAbHeL1D +jn1zNEg6KSTvwU355UWOSsTUdYtMRt3ByFPFWPq4uNolDBXmoELlwwYtHaM+DXsJNYfwCCkHejgX +6dCHhVoMeHnPIYShQ5/w/fB5tWvYt3qQElt5vUdQOvqqRKuO8yQ/LqYvL3LgPsOpMxjmctIilc8S +M+oiKnCpK5QedG9sznvAS6YfvxxCd4dhFXqaOsYsSCut9vTrkh3d+USvZ88bXYO+fX3p7s0VfExD +qc6Aef6nuwR9RogBruRJa3XwzFCJQxlBlvDQTBi6Y5nceRiG8AoY7ta1EELNIIxxytElctByj2EL +W109zUHCUKDP93o23usa9I0KqL2Hrl6CgGXPV3duRUlc88jSlxc5gImkosSEOh2UnLYmPx1JICEV +OKN6MR6GTnLyaylGvYSaQiiQcqDQmWY8wwKu7iXD1xwkPArs4/nZ82LXqG+1IBXO/BIJvOzqo8Lu +5UHAUtxQGhYNTQdCcUJbqWuhDIwxMZVLGBpMT2L3IjwgcAY9Mv/58GJc+HjLkZZ05wOWh9OgHEn8 +uIRHdT7T6+HzTteor68vzbX5EgosuGJeNbdGVOEB4vvlRQ7gsugUqyCYhuYoYpvMjgyVkLoDnLSM +p4etuKu0/TTsJdQcwgqnHPU/2qkxbEFuKXg/OQcJQ4Wc8PXwebVr2Ld6kBJLfYkIXl6JlLiBEuQL +WB+uLy9yVSJzTu6FIkMdVOqCw7iMKgSkpj09arX9Hns6Y15CTSAsSMoLTFdu1Ri1oG6Y4LmYgYRH +g6u/PHze6xr2rRI+vYt9e5Pf/PCV7OaT/PfKbX74J2c2n+S/V17zacK/V1bzX2RO87+RBzR/8xXm +4z/+2V/+6i9+ASLRv/nGxvqH/90efngf//d/eozRUNNcWn64W/G/lVr6aP+bf5Kby/JIP/t5Bo3R +ee7x5+m9/xX/R8vv/tf0p/zfO3/eytvHV/r5n77+KWbFP3+X7fmkcX9wwRsxhIO7Mkn3v0je9uAC +qK2psuGCmu6icISgl07LGKEHlTsPp9DjsySGeJh5aYgcoezKYjark4oRUqr0enJPUQ== + + + H+N9Wkvg9cy2D9YA633zMZLHjs4t3RnUPJy0PLJbEANtquPYvPrYsCwi8YpLLq+NZeWK11EbMYcX +Jr9V5A/tmA+IY/bHofk71LlZiSd9iiruTyN7qIKTpxK0GntWVaUr7rNUVGnQ23O7LV37gL72iIWw +AIR2kX2OmVV1vNr15zVNcVuQ3sEw6JWXQ/emyRCSGgilxFgHkSu66gZ6JEtYzNW+dbfqjQJ+SMGA +YK/HD/1TAVU/Cjr18e9/9Q//8M3/iTPqPZriV9L134W2uHqWy8zWniMoAeMj0/WyAiE36Zx3H1sj +mlNEYxKYaWtfPBs7Z9XWOO4YhqKKpICHT7LTGcRHBfFVABoLD/LMSsZKusyh6rS3QjWy8TD41M/N +KsOsOKAQ5Xjq0bGdBsPv+Rr15lZnnIUNyEUl+tkoeB66YZ2W6dFrssq40B4QG1A31Puuzr//yrcI +brTqYTE7f/op3QEgMW3GqFomHUoRVSCOjJlmaF485/PKI5aIVA51LIGwE4uMWiM/wUw4KCx7Relg +jiM3UvY7EN9wvFswgRhpur2E9XI4OuJLNC+Xo5CHKCnB3lXDGeFZHoorasqK4s4RWQcwjLcixpbw +WLRimwOg/U1S1B7Yxz4htyn2rNRkmza/OowSjrRVKzgxmq+sjxEvIZEdU/QUbpFnsY4RQuM+c+Gs +65i8mym86URcfIm0mGEQ1T86OxNWz+srTEYGTVBcmMgkgCp6Z0PYolEyPSZ+T+vvwQGyKg6LDlZ7 +1PvSQuWzxN8/fwcO8EauL2etlhMtb8swB7Xy5PS6TATM2WI+9jUE0QXWlgGU6tsp3LXtdTaJxJ48 +7/jtSA7uws6en8W7ZH/UelPr3RVdSZDgKGFVU5lre6cBP1f2CVfhvJlLiotOEcpmpugX+FYPMcKL +/LNIAVRgi8uuzaiUbvyEElPm7bZyfCsTkhKAwo8xQGfX1qeHa1DLadjXGcSB/iyOGaMLwWaJyXgc +BppylpYuYg4LcW8Rvqps/jF0Cn/9VMjXIKmpsc0x48Q9ltw8g9CaoJvsopkAx1qJ0v1WuM1370Q0 +0NX26K9/e8vYfoyYcFXBW2tBI6cAqHFKvquAgzJ6lofKSgQC+3Vv+3muYh1WvuMqbjoTal7yrqPt +gMdGzytzzT8OtjpzbKXOSC6tLcN0jSoKzd3iUGg6jY2Qaelh7z5t0czovRV86Kh96Fc4Tzt3OY2z +v1lh3DbBrZdBQcoO8w3audUcW2/0Ycygm8o6heyK944ez734LL80n8pg+Xbb7bqL19T1ERHsKWo4 +K84+ndDYGmS5BRKHIRPxkvO8yxIuApKMXCMrNFLyPge6N9u2sl32W0KJ0FQlrHUc9UuF9gCcjXIt +eGIEshP9MxVJCBkqv1dwL9XBMnjLcIbekrckhLxH0JBbDsJv3lXi+fNnedzkO2KxWOKB5NskBvTo +gpr7Le5GMHPQQEOhFD9niwJAsGZTNzU4kbCAXbs4qMZQ4mgFocOhKbGE2BZfFIs27VabqhGtISzC +f/Ygj7A7hi6vM/H79OmDijqO554TNxYWNp7MlVdJGVEdqXBubU32En2rwrPln+Wh9BEgCKgtWofD +At4yiw2TSZuq+A0zH5ZeICaMHMc3XQ0KgE1z+tkKL9dKM3f6ey1rsQGuY1IEFUaxnGRc44rh2R18 +lJwUNU3chSDC6JQZv9m7L3xshmf5ZWGyhBTKgzURrViqE+fBNN9aQ8WbVoK6VuWmYF91/hpUJu59 +LvjpLokRTUQEPfFGeZyM5IJFTJiKX75BY2ny57A1SpDfdh8By0hWbtHiRgeItK8TiSYx5Cw6t+YW +gvzu08/wRQ0xwos8DLxwrfK46QiQJHAvM18u1/ZW9HanOCXN2iRNW0Mn1EfdP+YDLDXIcNkgYBB3 +dg6rkT5R9nMzrh8ylOgMtP6HvQb2JOoWZWuTpoJfDi1dGuVBnrCCD3mIaucdHXCEN/LQGgAI4qyz +Ercwi2tl01sLKPkOIX8L7k5pstFSso4BqV63tg9sFX1rSW3uQFtPO3L0GZbb+griukFWIfTOsxs6 +1v5nMavngMXjMNhUz6LSF0HA8EYQjN9sFc9ZJZ6/sQpo36ghRniRh+K6V1+ahqzq/ou2GS8yrKyW +5H0SfQMYibYZkNbNX/t40LbL7CRzCF8gNbz0xFSUIm8+Eotu7xuk8AAHgkgVwjvdAHWpYnt8xAGq +PW5tawY5iHaTy7ZGkKx05wt1LST1d+5hsVlzYW8qAlqtLEYXQaMeChtbpc8vWuQIb+RxPnadnBY2 +OFcIOOjUrHqStQ9nHtvkZg8mcbWw+hGw3HWtliaoKdODWCtFqFZZmejQlunEWY4slDZ8QyY2WnO1 +M3CBMmAyqtgVP9SI7Vy8VTEja98ch5Lc+nGc8kHOWYu9RLdxE1eJk1xOLcchIuV3dHiyZs/y+1Yi +R/O2KcfZythX4l3jihDrKmmg/YMqLtR9i37Uh15skd6DRGfExkewMLReUuOL2OVz1O40XIjqnRtM +ftb24JWMXHFVlas970M+Bk2u0udBh2bxucptedXCuZOexKG1HCNXvxDijDiBbd4+KPTlUvO+D76P +ujgnz8kKaZL9rb+GO1RkNu5o8d2TiFrzuK4Trz82f7NFQ95BLhUEt7suYSHFmxUFfHw+YFzcpRuG +aYwHJbpEvyggzrgX+bvNDn57IPtPP//5l1/8w9di2IBuLLBx8x+PVXoSS6v+6Ki20UTvROaujOYD +X+RPM74GA3MuUVQy7ArfoCYJHb5glBX9AnmtLgxn0Hd34V3hS9USlHve38Yotk7JVYvobD1w5XZ9 +DKPM8nAJaXeRqK8tggo1uNqaoiIWLGceqcq09Ai61si4A+uMVSMe0LN+rTdxIw0RMlfFfDNhQzEF +qQxfq8gXJy016KHIAI5g9EqxWQ9kJPvWtZ/bIqzLwghDu0JMKN8PsvLgUbf0gjowEO8FISP76HI7 +NID3MYFxbBQ8ET0dg1x+VRjpTQYNY/2bkeAwPKNjePAGH+U1sdoK0Ikit2u4X5TRdWpJWKv43g6B +tDtuSTNjv0v45Z3OAA028KK5PTxvqgXEinuifKR03PpGOs/MYtK9AvEG+oF6BrDAuokD4b4iyNdP +SPiwIfaboAM+9RALzFapw2QPYsvhKiEw1D8FkbAchAvw7Da33jwR7DUYLCC3rL3sUkKhPsE2SdZm +udYkhXOLFWY9fFiS5iFHgIrNeAe/hOHY6TNOt2s9EbMjGEzVlsd/3rEMpltiDjws8bqkmuynBpMh +ds8V3xEIWqzgSZ1Oj6Gu9+5i9RCypwQ8t2inAHntAnp39Qd+zKCWILgtcgj2Fpa09xPmfNxGKRFu +P2eJ8J5zSxdUuEpWOa/H/9cP+NN7TLkSyX3lBCBVipkKrQyrkCrLT7z4e57Lhe1W9GNWRlq2R9Hc +6OpLRXu97Sc/02pzs7PM0whPLLW2Ag/KrCP5QMdM0Ol8lGU0PDxey9m5j7PDgxcYYYcbsGtlKasx +cMQMBuu9023DMFb8eIfSIhK0/eRAxulKhTidLFay+PK2mpsVrKipMbXillccfNQlLcD/cqp7Oh3u +MkDYAobPM/ExAyOx/iQlOJF2AffoksLIAF2GTqTz5917E4aVkJfaKJQtM6NwcZtpQnPE239gYdV+ +/fkWU7M2DfInXNvpWxYHYYVs7u6yr3yIJlXFH2pe1BoUDhYS4cktZmKz8T9GTqYLvFTyVgLncRkt +H6HXpc+ibLEFT/exbSfL1BDK3eKv0cPF4gouS9wH9U6HGWXSVpyqL5l6aRBZL453PFi1BkyHH6/A +AT8h+zOZqTrZ7mhlekrRgwUfC9bLcaCTStct9sOHo8pHDJFLaQw0lr3TUsLGLQFwPIwk6swguk9K +jRmlar6cWdluTbz697DjkBeuiJBNn8NHaVEXK4N1HDYLOM2iQGwvJ1YGnGScDEby7gVu3rAThnWQ +Nx8ZnMJVgG5+LyPKL1fsTgXSU91U3M/azHYUxmTRCF6Yl4urH9+8qbkAO1+ZErz5FvozjKnv0Js6 +OdgFFUtJkfwcN+Oaodvszcq5ZorI3M2QCDXWzZBX0RSG+TruihARbktGvkxPfZ+lNP1hTNc5dY3k +KnwvlZjig7EjDdv5nO1QlCiRNbNmNKWcwfQx1YPJOlFF24hrgH7I05aiyemmo/IuQTDbc7mcVbWd +qB4t9veqTBbWu32YoEf1bv61mu4b69vYRRWWo1m7WN6NQC7Ti7Z1f0IrjZEVRdWMO4poW/ZJMVmX +b289xc7fJzK5qkQWHnssGkvB8cEuiofdTkytC3JsqSLeTNETYIkl7HF2Cs63b/azlActvJabokhz +izs/l2DVS1PNCkqOphPQYMoM/g+y8q+sRFdJMSfw5uZgkkcojws5qTUOyOzZAQVkpIVWZuMXyO7L +2LTMJ/G/B69hVa5CGWdDovPsEQfgnBF93J6c8FdAe4c8OTFr2OFCK7b1e6xl1TiysZwZXZEMmN15 +wxyV2IKrgCncUgWxgjAu4bTVcAEDEy1AbI/LaPqmsNpmj2NjXVhJm0Cc1rUVNYyZU/SZxuP2gSWu +i8uonSK7q7wILT+Jj0hSQjpu2Ixj2cJacaDgOxRl43Pdeph9mlITv7WhiyPvX0tUqYHbeTEU2EoR +B696kuRIAUI41Gh+HBvF6Fg3a8o60zqg9i0iOmRDNGOkreo8fmq8HmJa1da6bvPRxIRFjlY6KD2Z +DKaveRqgRNMBdAvsVLgOr3J02D3absIeqCN83qGXteY3PgD5m9Ecq7G1zInRJy9/jAl4WNk0wMoI +PNw8qYA7mTB5y2xusW/G5YgayuwVsyPwXmCebWszLZGruJRLzQqtB32Fb3QnFEQ2Y4op1+1CCDMb +5IC8lGV9MLTC2F6ss/LWr4o+A1rkEyMhNYT1Wy8uL7ffCVZP1vM/5CnrYjAycxMmcSrMQypj9mPc +LL2K44jc/GZXDq/bjlaC5pnwFSgMn8lirZRHltu4rv3nCsG2KVpw4fuWq+pk90y5oXg8YCPd4odH +AHrKJsnSTuPq0dGohqwMo/cScA7Icho1IvFvkpIDl2vtpMamFt1FPE0D7GFvLWbwaU4guw/rI2SB +D42Hh9gEI7rfeq2kdohs04tJrdMO0fxrTtYi9y6s3sgc1Ahdg5bsS7y5VxgDeFMIb1TvP5Zj0O4N +OyisSpuNXut5BccoGT9r2mqnWEhp8FC5JuBRO+N8vdr5FQYrbJvxk2f1DHUy0qK2GGYCG49lXNEu +TqRkVRsRTKApAbaqyGSWurMZjJd/3xgIw/GTqmuwMilmwrljTIchIq7Y74aE6gTWoqksDNToVhUN +CXHoyXS7esHBEHGXGFnGNoTmpjeWnHWBc03KudhPcQB0F1D3POJ0IFwO3jU0zenAEVbSMTW9W2Yj +KmzUNflwzuL/VrdOo8ySYf1MpcXklTFET7VgnIyTInbPiXkvZZOdtgrWWMLrZfGAeg== + + + oTS5mojz56UuGIqDF3g1++jxvITa1yig7Eb/nurEQS8cRj+M4FCkfJQVFRy5RHv56QSrvqUnbet9 +YQ7sUGC7JGCa2XWjKOhiuCQHOiNW3tUcwkAN8SkUiAYbB5lpyrdFIa5W1ozltGVAocT2o7YUI301 +zkVbvFkxsiBcUvQxefeTUGNhdmd7B4jnD7G/LVtv8FgqDAHnqKY3cqvJKK4bBLYfouiMUT7okK08 +rSZklqNDBbJHNE/Cer1qY7iUkkLmy1sncAIp+nOtm8eHvpt1b2fTxa3GQHD4+2mhu53Xy193Nj08 +A/Za1lb3WoUc0iHCNXERf0p1q/sxhW+IOWLOYUdQtXhs4/w6eeSqc/h/sKIT2lQIAavbUXip6BAd +7T4s0+NebbFGVP5w08siHsctmpoC1ojnwS3/GEmokKeSVBO/Rme4uI4oL1IPrX51u7OGlgLMM45t +XBeJwavWSjSY8le9dgH2H9vEFe/WwRE3QUk8Eu3A43fqh+DKurl1wsALGe5QgMPIyibZoXWdKVrD +sx4MJqzaqdXiTZy9HW/nGoxE17IsrKdtLkIFFKpmFnhNFYXu4LPrp+vijIzY8O5F8Q4P84IHRCyZ +AYQiW/gWNb/rStsjyZLr9QWsUYUnI0ooke47VnFe0T5vCI9t6L3I96nqIYxrS+FVKbdnlmjgOFOZ +Wk09vgScu8odZsTiPmzZajcUtluje5NpBsYUBP9HSCeprepaepik/O/kTT/9QAnUn/xUVZniE30s +GFAQgpUB/3gYrePK/843pYUpGtcQDP9FcsNH3jFIa6TE9YzTb1PGAwGtvVq/OLVOvLJogOzdwTwz +JpMm0gm41YNTy8v9VOddhjipRtG1TzvJWjll8irt0+PZKhb9zq59a+Wnodrx6F++DD1gc7K2b/H3 +6mHUxSRig/oNBrNEDR4RPnbIAHoKxBWGLdXVizEO0BUNwYZjwLTPlYhdY97bv1O3wTG4GIXAok1N +M9B+xIlVzwQUdFkMm1umPi9e7H0JeD/Z4Hs/UZu2IJdLYjWzXeNkmtiMzs5uO5Q1WsV7esf5rZKu +HBYoRhiTici5Ytjh5wwOhDSu00O5fvSF3kILrCkzYA5dQlqcyx/kAIduaCp65sdP4qkmSxMHe+YH +N78vBsjRYajoDJW3bgvBm/5Ym2Pn/oeF1U6ifdAptmXXDtMxGyUjrzOilWT0Cn0c7dF6d8aRXeMi +x00SFmjrrFyDtzMYj7eukzGHA49Ino81NSwBKeaaIrHUndG8SC1WA6+YblUwOrDDRprp2dE13V61 +VjWsnOviD3hFj9X4EDXBFVrEUE1OawhBOz56FBv8TE0EV80vi5i+Rxa8kCRunCzUyY6lXIYayR+e +RLsBpj5NEcNdd2SLaXumIq2ozVT2SE6M4IGv2wlIweqr8ma+whA0ZJ4q3holGfns/frtIaftXdeg +Tu/stCMfNQAvUmvd10W5KZs2n87MRe0SbAozNkOJ+G46BSAw8TOdvHiHKu6x7c1FP2qAteQQthRN +y3l+4TBPWUWm7EdlDSqPUZSFesR9dKgGH05AlKmWoAqJDrkX8ahhXHTjJLqU1rC9Nt0NVWiapCyY +3UEcAGW62gtbxMPpWy/6sdZ4rELYsZem5zmYZ94ByRnyKA06QyMlkFWGznCPp3sS65MGoLAzZmxt +VHhIMdMEEIfizQYYib9NKrKz7cNHt3zk1kNWDxTuoGa2UvrwvSZrOxZTJHB1SV6Cth5dD+ZDcbFP +Cg1IcJY+TGbxrMfSkqyLtdXQGtTeCHg7oPZLE6C7gm+ShdpZWxmGNIO2GEr1TBOsmxZv22WDbyGB +6IjjThqnwmdejI1R3zWd43M522cSYubwSfcoarMXS8LcJOFNGOY099r7pXrJjYqA0xNepSqnX2bS +26b87G3gwSkT99B12hsoc8NktHUsUtJCVTwjMlLrzi8DyS5VqVPcJmeOW5LkAAI2yQ9TYI5OCB4x +PdHLls0PCONJnA+xhLtb257MWZETs2D2JnuKaGM3vU+H1uxgH5fHClOiXiXTouYbvjY+OADFLwmg +ljzuaUKPMBR04blaBz/cTLqhVpjnQn3YK01f40lYFumewpBzKmgF6i2H3O7t8aNbWDytFiNYbz/3 +raqQKTPCNAEaqoFhqU9bqQQfAYL4XaUsY4fQbwR7szpIFl7KvDA3D9OWm8HAxhRuGYlFNOxob9i5 +aNe8oMR+cgAE2E95Pz2rfb5DvINlMSO5utl/1d0StpJCmF4MBdbR2mT+zE7BfryT4N+0nP1PS94C +FQoVmMPyX/6aHCBHqO2CXR9k5o6WZ9s6VPNJiyd/PFOolFedhlmtfM1pTipoULHMw8TNfZyXOAQo +qUb1AwEn2KREr63TFnU5HDmwEs3XET6CaCmS1+t6uC5nQYfqEGu3hRY/aoQZXMfKD2/5L5ZMroJK +8HXxU+dMBqg9y4cZaqO5FJvK834JhY+HB9bjJQQXHoH8AVy/6BKMjgRJbiQSsTf4SpZnk69BwlgV +G9csGrPL5xzpAq2cS4w2AGTH0G/BoCWocHMb8aO0UJoC2Nbigl+nC2PDKJh936om0nYLx2LoYqua +OzYDFym82lK0HnmEwlFNpxJmfxvFBfngPahaCAlCw+d1nCviZO0gRjaocImxyYfuqrAAJGKZhj4i +QSHTkaEFXgXHynSh2ni2U3cxxE5yQRGBx1kywa2wwtOI6r+BzuiBAptqkdsP3GEy7zosEJL0qMBH ++1TzzOhZuJ96mc6rDiuamJ2MNGDMWcMShIyPU/cFvFFSHdfOVMlEd3sQHyIH9od+vuHw7xq6pJKk +NKNFtPXYtPTPJGQCwiRUwGmbiGCHWLHXQSqdQp6iwrzBJLNX91zAFZbBNzl8VvySlVFSI0v095vC +Hu3VL9jMJrThYb8tglyGzE/vo64ZuO2DmOs4S3EI0YhYyBjxa0vl4IVAEBNW4oHmaTGg8HHihuXb +DpUxiycQDxIHl5/wjP2YsNq6q8nKyOxK5w8m2cQn9mmt9xTGul5gyVNR1hrP0SuCFZSvLHtPgRMa +VGEJNLtZfeqQRzwQoID7NAhAtWfJul6rcD7sJoAgtJg6crjY0+twPmqEVRUjJLwEfRIdjY5DXKCu +8m0EptOqB3s0FTRMBDOimbQvowufOOPgQZA234AR7iSrCJhCjKiF8A5QmDGzyuI3+AFHmGpCDJxP +aQJnyOLHCcze1UMJWsvEzOhcPsWvhNufrZ/nZZ0zhO0ojqHyA/msxniaebcxC2pAGLJodFXZAlM1 +E92gpz8fXU7fCBZLZb6abVTK6BnVK8Nuwya1BGbiy6YaqU4ZXjOggQBTHnZNyLtKuHQN4q3ilJTF +ji+z6fd3tBChBrdM1cNlZd2hB3nNKgsdsF5IuHxn9Lz/8CJB5mIB80qKLwL7dFraM05skZjaz0pM +rlxLNFwjUDbKjKbkXlqWSMIUU2C4HZAi2rXYS0vUxfcG8zBrYvvq2I2HZHvT97Ie6IvE284DaDgt +UqIn3/ifpMZAJbQaGt8HUcVKPKwu1ZGmdkHQtqSybLG2HSKO2IwzOWEjENgGRBR2R2wEYhRRlUt7 +HyPkRETU2n4g2bDeV2FfZHaG+hveYmU5+6oLfd9ZBTC9MRvBa4gnMJQ3mJCwKkARinbOKCwtLnOq +I7QXb3VjatkXhs09Omt9o46oiTad9RNiCcgCwqESEHWMXfUvNywO6TGsrZ2DfrIjCvz8FpQnP8Hc +O0/lblZrXM7qh5oVqjb7oiXCpA7mxAD0y6Fa6TRW50eHrJFrZSnBYiipFpy9ZsN6NXdS9Nerf61N +GuzeERXsnsd0YQ/vq7GK1OVFIQ9P7Nl8ld7NAWNLXlsS8Uh9iOTGE8OfAesyG5eh3p4428O6b2lL +dglIAsJZ1jMH5KyJr1EgsnwsBOSUCN5i3a+lySyvaELBFHJgnLK7N8xyZZa72S/lIbDH4M8nxaXN +LBj84Ga9fhTOIRfhwpgLMUSK45yK0wq50IM5Bsk62dUsX93WsiAvJXYOGI6PsE/it/aN//KosjEc +kN3Sfs3fFxZfDnLJ2oXTWvPCX01fNFYKFmCtwo4MKM5rGoHLaxNXHiNY8YHJVU1pL+ENhrccQvut +zT4Pp4bN8EA8mZPqt0znIdzMQeaovbECygP8ydHypUS/HATlixur1QFjLpRZi1zJrQYhqICxCtAN +Xc3UVBlu6JhN/i3jq+EALRD0/aB24GDqirxAM1smcG9HB0yIp3UQXFXtF4xCWuSq5DyzhOy+voIy +HEmEfCZ0MynnSLyog5SnLYYKiDYJfDztUAMipDw9dm7Tt/VW61Ypmy4w46EvVRsPWCdDVjx55R2g +KF/M6I9CCQStwBcZkeVWHcYQ6tmS0U3kmneaZilNg7PBjUXLctOsO/3iLD8k675fQLjiXRXMiFMh +sTkbsqLV4+Zt/v4jmci933yf9o/9MNEPDADR8ScUANAjzDzQMvoSOXTGPlBYOZVsprMHlyQnCVno +Ut2rO0n04NEMpjbkD2RLssTLsvCM0+Rv1+G7W1oPOY4hQHWitEgInBnpzeQOeaQ9BUpJJ0GnelWs +vUwUwQi8AgNYJ33cxBwQlGlDdSI5IOCWEu45vLp55Y+LvjtxbOamT2klMspMoec7xGvyrm4ReSQB +jpoqsa6EMiMsWMIRjnGwjliiSw8GPSGLmliJHPuiavlV9oW/iTySEEtVmLfu0EVmY5vqyc1bj6yj +4AUobY0uHMz3I2GlD1MJ+MeZdWrtW/iaTcyUlo5VMlgnHV7qJKZyuyHWhw5pN9kD1aMj+DDCdzQV +DWO9XbSL7aoEKy0wTCQ6yRcSoqu8V3VvZw6M8iYFpCFkRBwwGkoG/Twi0j/qzxk8RqRMaBjSo7j3 +1ItG4HvhfBrt+ojicdxhlUAJWbMNWsNmXDB+3F4U1AhAdPFVrwBcqXyFl6ELo+rtVDib+ARHX7LE +z4wJ2sv5CclRnT3WP8LsYj7WEUXM2NMEks/5IAgY/U7Cn0LGUvl00yn3+ApWZ3MgDF2cDQI12e5o +vF3W1ADqfbHdLzkD+AVplLeBgWDdNA7BMbTB9BmXR9xOAr6ItHtVMQEu3cZWGuAyMozhEsp5nvw7 +vyLWzAy64643SF6g67SQqsu8QUklqG6WQw35sFdnWUgtlxAqemdrI6ZQd9ybWYl2A/86vJl3ZjLi +KwpHrVe7QlXrrNOZ8HjROwDS1guo6kP2eZVttDjti6c2nE9Dm3+UpKz+QZrnva+edYKHIX8VVSKq +xy1hvlgHaIVUKpjoP2qERDRHUIHbwwyhFa9Z+uDAAF7y5YKnGrqACY8ie9Fy26RlLk7f5ULyucFu +mvtKhB9ECbfv/XA+ic0dWyLfcW5QeFT1pi2sAjJ+2cGdGkmxdUFH1jpZl6XSBezKPJXNV+b5ZADQ +2W6JSsXgfyebTswTicn9Ya4ofIsWypF62ezq6IFHy8XCsYW0Q+K46CV0YiMMfXgCVw== + + + DDyi4tpcFCFBg9ljCZVuLl68AUkKELlMVZQhQhwNT/5LOIUcGYcBzXjPCD/JQ4wfzDsDvrJDiYKY +dac4iAEEZm1R1gbNhu2gtN6OUmMI1yEfGAHQ6ioacnbQzXikqrDB2sXA4e0HGnNXwDXOAAylWVi6 +hTAQCDUygBALw6CSXBB2cAPv4OuCo5qE2LYi7ghI8GHjsM8i3GBxN+K8vYrWTwwI5CL9qGS0MO/J +6c35MDkJklxZ5/5dKqkdqZ05LA+8AcehFsjtqim9GqvviNhfWchLDjNvCYSgJPHwPNgdgHkp/wcZ +yVSdQ21JDwuKeSryBQ03dR9QQhGOaYzogk007zjsJFXs64DspMOq066C57KGNEBPGqtOgaXm2DK3 +bds6AygpX28mM0HairfLcSETttWvncAkzIBFRh5YyXe8Sg1hkeOUn+jR9pnXiubBV9cosRyCdEXd +uCxO91EjKBCPh5MwGMSs5BaZ1R0uc31SYok4/NV+K6t21cCNweciYGa765V3jqO9HSqnEo7DySdZ +Q0Elcyyc9fF1hKHYg+XOCcrq8AHEZDF1dBz/0XLUXtCfL0RP+raFld9PW8DalZBP46IW1iVbDo9x +2A+4T3VY5zi9iC2PEdjrCrfhWQyEJeGCY+wUWfYgzpwXXi4x6uX5whYlqfy+4dkanwcPsOyo5Y+K +tIY5ahFclzGLaV7wIQQh6SZC5gcnlLTKLMfMczyp84DZYfuMQJPrNNl2bMViFEmAtYtMY6pG86Lr +T3cZiMkdBoFoQyvxMHliwQWQBZjgDQVzFLdtJPVnE11gkPgthUpMGMQqhI0ABIH6lBjhRIeMXYQh +72AyLCOYWYh32A7OvnAFYSkrnXtqz2FzZAXSU6T6xxO/jcg7lkIqPsKk0Bje+Fsk6VjOWHzS8oIF +iHLgkJLg8+wh0EbqYiodbV+snZrvcLI4vvFm9WfhPjF+GjU2yRc57wr2ju4FiD4FEat2L/P+YAkJ +DygkMmuctLxffYbkn0qrE4BrkP0dGQ03zLAeI9jqcoEAmhiGh8pLrEayzhBqPZ7CMJM3IlqCWSVC +OPg4LB6HkAWzSJj28/cMx8HrKlk/1pY88jmDRTY81JrrlcFRYQJ8jCR4hI6mYAV0WhMdQae+zLAF +zPWWwyrSg0O/fNuTuE4UJSTdSoADlAOnOfxheiP2SfPO/OUPlpkXiyGsw8PNUsJ9BvlxVm6fu9rq +dKfIQlR40jww8lEjTMHyu5A6VclPK4Ooaud8ojsFbkmgCzy+nZ+zblV2vqjIkJ+r+inr5nCSeV3X +kZ7MTcVwjQxO87hFCAxf6dRCA0qG+1yaEc7QEZluYhCmBzUiq63quBHIKuRus2qS8pm+Mxt429hx +5ZQPyr2KnQYIyx0hL+rEwoe+Ws5ezMFDmSOzv05DonwOpBzOAJogzGsE4vEQm9LXyoGLWmdhZMG1 +rJVDviAm3OKEP+LBHZTX6oWZ4/zvN2nbKuS9GArfuVBBlR5cUyvo3YzoZN06iN4lQfmVoiV7C69y +BYgTUTK0WgtkgAI7NVpMGC1KFTRgNAlFOFyv8hb7PI7nS0UlSTZh5mmyu2cUMtGUn3Zz1omWzjdL +cRMm78LkQlajQ7gOzVFSebWFIXwlgTGGqY8UaxHkMJEYMyxG7AbWkkAujp0VJ3DyOgQXOsTCMv51 +BTxgsS1Ct4KGgylZnuUFjD362Br4k9wocT9Owda6sTo2bb9sJhQyj4O4SvutXVxo3DsxQiW7SnMI +i7+aez/dvIslxJE4IurNAggNe0YU8NAtWIrHP4ypY+T6tNA9gXyaGxVizIxvZE/1w47kvJDWwYzc +zYS+cWPWvMTkwrIuJTksMZ4CY5uomuQNnOOWd4exr33IBJfHL+6E/fLKE4gMBBT2njMrdSP+3wG8 +deYbYFoVb8p8LZddbrCjDkwcXT1yFwygpKzaH+nw5gnySKUYV0q7QsOLMICoJUb54prigTkVW50x +EVOi2HAnbWzjRolejuJrYcOIAAd4oRDkxCdZzs6sHxOenHAxiloTnvyTZcPEDsMshZo6cCEM0YXk +RehHC+Itz+l2jruzqCs8AdcNkn9y3ebn2JpdKXLKJV6tigLUhMTrVCGObFrcpU+Ez7mQ/qeJdssH +JdZGdfWWbE8kd7GIdfy5w3Ztl7ICNMtt7mr+8uEJyTCdjffk1blLp7wfZ7ipPCaWuBEKrxiDF+R6 +JYXFdbTd9vhAlEYmFIs4JOet4Xl7LQTDAUwezisP5YRlQuaoBbach+PJ8sVVbLniLtoqMU7nUyNX +ZPwYQIFOSvFGVOdLEnpbvYKDL+GFBkgQ1ZMwJ89Yf1oLmWlHJCWdwMwWLu3+cWhqsoNS3JQ/NDl3 +uz2688/CJW6UFDjn5bVwHzXCzIsWRPR6TZfdHwxINfzVWq8J0C7ExFhomFW4l6JUxPYoub9ogFwa +KDQrguh8q08NUoKrqaZbHsq4WjV61a6c5lGToATHmRjqBbuD8Dk5Si1eojBgXsRFf3ftrQ5z/PBe +Xl/oAHx9XAH2D3MdDzqgz1d4wDjpNAtmfTmJ7YhAELWT5OzAAcotZOG4P27vOF4Hzyb3sk9lNbHg +B7TjTqmvhnkxoI+A4ixnqWRSdWa6hpNUSPgwJaIStV1Vwdtpqs3JjuQ4y2ehwJIiY17FDdlrK/cI +AaWZVQW80Z3M2hy6TCgUxDpOZXZTeVlanm+lkNtyCRBpwsY9caxnE3vuARpznL8JFcA4yd6uilzL +isWfKzDzTKQRvE3C3MCKZURi+/ROYpfdILdwwJatZUxjn1xYjVp6lK/MqzA5J61/3ScYgeD9/a2Y +RypzMpa9PDqs1/4RW1iqYSejgDjeQTnFdQVFvLGivPzoKYBaVmUql6cDrqJzHC3IoJ7cbpW8dKWy +xRU4g3oqtUjbzyfGiRZKGH7qUjiWDiwWZze18UNgZ8Vdb9n8xmM3kqgtINbjcLW0iEINz8WfHP9U +i1sxJJkWOsNABiyhxtOiap4bIzARBu30+BIsBMOWnCmy1k7jg60X1rfJ6bIsL9h04YhwzazkWygC +S9i539dJMI+YQ/febyb0goPT3smy4eKFPXBEy5HH5TG6stmqVZoHhVICLDbdyzxZetJvTgc/Uws9 +VNYIBSrBHEdWhKMFOpTjIKeKwRb866zo3sg+quOJ9wjwNn5Iup4GlmWKfDg3hAsFVSf2MpSoNj7R +gJDH6jiYpxJLGbMPOCZMFx6rg0EVezbF2qpRt89UFRZiykEcEjyyBrhLStCThnfIufQafwU57y+Q +GZex2XaBDFjkbsHtHcI4aQ9G3OQ67usiQ0gWlMrC6FP5fcY4l7eKDoCAGPn2t3oBWBWTkZIgP0ji +SEnMRQY+wEu/BeDgs4RJbJbpG2SALH8sZIkJMIiFCYwlfIFusR1QfeALgkH2UGZ4Lw8FdtI6YAQe +aZs8ICYrusLO7WoABWJXV1SAnQYfiWxnLmQ9JDQ77+YUzCBBniOLr8Zey4hZXcbvvZx39GOAC2Ky +jC7i0TBHdnAdeNrDnLO8759nQxc7m/nnJAjJEeOwniOT6ZwZuGRvXS3QU1Jbh+hbnQ/b7MVfUFwD +8QYs0xT4w4XC+pXT8WJFgPD/Y+/ddi27jivBdwP8h3wRIBvI9Lxf0E/kUanaVcdwQSqpZTQaBHVE +22ozRZdKKrf/vldEjBEx994nKZJJC34oARat4Dpzr2vMuIwYo1iS4ufATuBBNrC46ys61oW2C+fS +hudPlnV7/TmR7oCT5567KAihEa558G8HDcLBmS7UBslPiwWCiWEaRbT0QDeYiVOboiW5KMuTw4Yq +eTWyNAcFsCBebSDSjEEUudsgqgChp3Rtgz5bYAWZYTQlkDumKnyA14y9c7C4jFAp66TMlDicPLPd +I/Zm5UwzkhikWYHjhSuQIa6GHkt3Ho1qb+2tsRh/QKywWNIl+7SMulSqciXMtek5JEBWr7cgx1VA +x0HJzQclREGpmJ0aXS4XaJZ8wMONtIGslKGnQsnvbHOLt8ZkcJxYoDATAd+PnhaQpIlIUj2tTUe5 +jm5uP3TLKu9j8xLniougzAqB5F6WgoJMUjfikiwoNu+A7zTvuW4DvMUKTozjMAyI5aQdhC7tBHJ6 +rKzYjMXmJkcB5WAy8LD5JngNhwCGyoeiLhrcn/euq9cGtpMx7+r8sVLgSAfAgwC+HWgpRzFmzNeY +MWDZWgh94goYpOOQ4FtDN2T2yQcBVxSlURxYyEsUE5q0RKINHpv5yBbf8HIMo/dCflLTeeP23Kiw +XXzobrOWob1+byaXcYrVeN+Y+yBPVjcxFz1mvX9ZYc5xBa17y7exEhozCQ63ygBF6e80F00SQpWN +Y51xJ3nRYVl7AkbPNxQDH6AAMP5Ol1qRCi3QrNMVXHby+4Luf9R4C7vGm2zf278QKJLD2AnlPFTx +dIZsebLefAV8pJP1zSD21rSg+jyhgBCgE7JsYAjGzN75QaPAgGhpTcgXwDtqkw2sc2/vBFNbeflg +6jR4b+ASMBI/ObCmxkwahRl8B3BVygLqW5RyX0TCksl3ENkNFbDFyPH/drQwPcxITsipBXyoYUwW +TkNzJmG7jJb+8Oh+uKpJ8ygeyafBJSiYGWS1ukLjCpypFGYCi5VULNWRAs1j/nPQfHKkR84Nil1r +HvmkT8xOn8OdN93oyWYq6UxpxAtNZ7VccUy7/yGcM71/tYL3wUdDFLKxiFaAQHE66QaVH6EyEEU1 +U42pedRd2IwJp9/2gWyAZ1OcfiICALymqpTJif8YtlKMSuAKgB8UXpjp9AQOvnXNmH6AbGOAyXgb +iG6CmMJqHnFKcdgbUlTQlOQuWtIyCZ0Y2vGh1QOtwDl+BRtwgaOdWp2hLbuA3arks8g5GGIqvY2e +az9QBRwhaJQqKs4Q6XOZOonLAaV+qEdnj3Wqy3Jo+3oxwgSeNvq2yqUdA7rpgAYm78oDlB9M5NYr +LE7nsM+WsgOYZ/TgGQFlajYqtGL5w13zAGcQE5zOJiKH/La8lRnGyVgnEC7NJ7VXuDAZwWEVk1vk +aofDPulwZIyH1XoSPzjRp4yvFF91WlnvBpMsZhc4ppKv/NiuGKnssSqNwEg+cQWWJouHyKu6A6qx +bCH5j87xxzkUz5hrvPjZpyuqMVSbkTFnM5HlJ3+XsENV66XBOFzUKGAX06WTe8h9rMzsUq9ukMSD +zAURu4v+DsqYAoU/sQGLA/4EIMu75PIqpEHJQFBrqz4f8+7oQu5gckk+Vy50ek6GYDooKpAQNFkC +Lagcu83kytiQ++sK1u/EG3CwfRm53xOhBcZR0zX1zM74YUwA0/vZ0qjXgo60BpdXhKyBDwQAOqlK +fADxje64SAExoDMoUt8OjxD7pExF6n6woYK6RsUjoDp9oMG6atwEiqNk0kYq0UOn/Ebr/iIYG7f2 +mA/HKiHyQLe/UXSqYkRRW9rkBCI3tXbvD7TQMEkja9dj2kLIirSRqbGbq6pZ3aErcg== + + + Mx+RgnUG1J6msztN9OpLCJGPxqH/Q9hNA1f8fQrwrRWI+wpiJEFETEMAnJU1pfmzQXyxj+b0j9ZU +15DyjVXrTPdBL3XFxD9GUQ3E0JMPNGoXxpANi5X67hQJ6YYSmKQOeNLW2OtAtCSSbOmsq12Yki/M +g1wfd1FQuN6HDKIGXJe3XM2WjklrqyXfMgSsRJvK2L21zvXc6P9nnzhRRYoxQVJA3lglF6Z6D56N +GjNgK6rk4i1xEm44nF6NLYFLgHNVYkzgyujzFGiwwrPyDozqx+YNwg0Oq2ZQP6pRK2exQsPH6xIx +BfphiiII5RoiE/o5miuVNsAzBqFzarT3VpVjCu+teWYxqqZj9NQrkQXDhTZIZrJsYtGe4zROiHVH +/2BjoUpR4Co3BqvunMSCEeJOUAL0BSCPovViZx1Im9wvKAeoEe20dDO0nzltoZQunDU3ZTZtLzS2 +ozGsLg2h4q9i8skw+YZ285Y4xL+86LYVKFuwQYb67tae3QYszwUZNtPeFlTFy4PuZh1QlMo9MWv+ +KiaCMMWWBlUSBmF+46RZh+yA8lm72BKRvC1ay4tIfiVoCA2nQKw3g1CZP9jO5pA5pD2JoGg2Te4O +ZVlW5qRs6k8mOxvaTTEje5rTePkDVYDu1gqu+XEAM0dysY7bZr5BAt5IDPAmEwaQbxAAWhlF0tes +w/uedj7mRqUrHfkiOYUXe6mdpz3sehT0oH6tPNiVhS8IXEh/H0mYkHwieR8n4lARTJntTTKNZoJt +Bb/SSdmITsA4kD1a2phslLXkW1e0bTlboVUJJKL6Q14+6N4+AwmOEjbyZNF9UqOT3I01+lE+iK4c +o1Ef3dNMNjFrBSuhxN4R2Uh62Vm+XIX6mHz2un5mmI3bvU9OqOXjXvbdMl3qHANvpDgqJP7NVrL3 +bKt7r99x89VJAZfBkBCnv3moXvRjzmCS2WuYGI3lCUSuTgfod9vNPG+HUiC63bABqlNJnKJGLABl +tFhgEWjreUJAdQRDuZzwsdE7axb55Hl7QjTNATcP1yxuz7yvLLVIYtgj5bVKmIXT0P+bLrnWybWh +gXfiln4SRnIy2+KlzbtQDIVptIb2yttoitj0ubHNYyboXqssRHJcpZUCZc+1LF7xptvDieb7WKc8 +p4kdAaBbQkAIjANyo31kz4g6MuDPDtb00r6CelyfANzAcoKB0ZNdCS1j12jWGBDlmEZaceutd2xO +yvLnTefwRhQHlj3Ya0o+JXXWiXb3Xt0gOZpgSLZPy2KD7krO+ao7ffkGjZj/9ENrxLyRN1TkYOS/ +tKT8z3b9zl2hIPZGnFdjeYEaCriHcLE1sCaVu1uxEuATnwzxVIWjmwZ8wN9TYVAxGnguB/oyZUfi +1wjYgyCv2oyXtbeJBJSWSgwibmc96DHXu0jMq/G806BjzFMqlvKmP7GFyXMYxhkM4+Kmkrwxinaj +vL3SxfAFWBBuoUNvqlNacaAhgUhBYvFxtCA3MDg1GNPHcV+cBT78Zj1QuNb/K7Rn51zHxUZjs5lq +kZ1nzQfLNs/gkA2obKMquq2zExShk6J9fAVjOFUxJedW59BXU3diNiOm088wypI7ii6X84/2Smz1 +0InTyUYUeLpNznvPhDyz3QvaSvvG4tMwgh0bUi14YbST7StQf7EHh/Dm/jvMM5uN7/w427CqYM4R +mEY57El2TQWmLC8aZ5bv9cKjQAz2ixk67u1AWpB3Xrb7GjM4vUdRLPCydbKAhqqxeuJOOWu2crox +nEYRAd2cbiwIZsQIrjqMzCtjyF9tTN73W7KIFOul4GCnjHRJ7clRfyByolKPCn6yL/3tUWfXOlVN +vI8HC9xRY6a2nFLGrcYqoNe/rtCVdT0ojSnHSCwAtVNN/jhwI1Um5GmVamdaeSZeXwnyIuwytLl2 +ZRj4dUvsl6Pf9CU3+PlaRx3CJrc109Sx0uUdTzdVtjBRaONxhFVwpkVnRStBTsHgqNw6tjV0LxHt +kEXjPKwOTrAIkBlfaHDdqYAZ1REdU/fAoQ9wByJsMuWvAjrAVpwgDD2FdFLzqsgVcHmZ90CjiUEp +eRAAPG5vL8x8rsBMiIJ0N7wO+GdGJETLFZOHe++7JOK3YhGH7ZGsEhfqV2/Whi2mqfvYDwHjK5wP +vNk6XeaqeuhwLUrBAJ1rWVTmTpT8yVSakbhqZhqplJ2NLBYrSJOXYSmJHLa36pTHljskUAHN2qjw +gouNBQW44lDiamuQZMRwdrW8wP++wVU4LZyijBJvAQP+7VxvSrbo0+SuDKOxwabYSlsxLFe4AOcQ +8w3rzKB4lizcGsEsgBCJVyKoSfi0Fy6ixIRVsGzoljxAh+HJXNUes9m6hzpBzy4bLRAIArCtpMmA +Vq2+uJtGguCqiXTEhjr5YypWat86VObFDQeGAQFvs/6ygyBaYYnCoSTFhusthsIOJcZM2veWHceR +/eNr70bsyMCtdCpSa/bN4fAz/08ebAxyQyopAHo2I1jfl7Pky5xsOvZTiOgqn7yT+kP7wkogHMMG +wY1kmTXa9zGz3U8mXbT6NFrzHfls5NRjnH0yFKZu07E/FY9LZItEd6acfnwpegJvOagd9dcqpzS9 +Q+QsgeoF27GCXbHWDH0S3PA02l6JugBnG9dBMKcdQOimH0CM7CSui67OhmWxqraXvcs1S0Hl1sf3 +k09kZQOGvkW/oqHU3qLHhDfgMgtqYLlgSbKy/AyIW2xnUyFU/jlYGZFms9nclf19SOwoO5saD4jc +AmBK7IOEfvmYQzSFGFUKnMyM0zi3Q6skGn0yd8Pq/RJQPetu2Af7OwIu8N0Qc4iNr6JNAE6WozMr +qVSYX9bE9ROwGEwDoLFZc+RmmG385tXdzXdDUQy9PtI3Oqw7uRtOnzlINqfuQ0DcVBMHa22ABq+z +z4M0To8nyBI9MbtkOAsMge18C0MLhXwWxsrHT0q7ib4fEr4MFmBukuw3rkkEuqGntTlZco28nyN3 +ySjgsEei4ChxZyXKmDF5NiZJzy8BhNC1sku3+QoVGgliBJ4lW3PAV2CYG2ICSo3Gm965Jbq2iUS+ +MUQvdlO/ShheMyMnL+Rg12XjFFyyFqtvqjEXPiD9IkjZie4Axj8VEItBoGy5IDdVPN5KhCuTkmyk +PGYkqBDYf89PWWUoJqCB/LR7VWg51hG8aPKQ97khs61fvIwoxeTC9n0CAklJ2z2blsj9iR4EZfhK +xLzuyEB3HUl29QHJ6lV0sxcgSSuHwXRHdgZnP4WT6/mWbojJRgu5oeyhQvP+v+QSm3XEmXo+91Q2 +OSiPsr1mJnl6dXmmhrKOlri8Hg2mUgUhNGeo8fIc8vSjPFqOcVuTvln4SMAHrluyfyG8CbJxoiyT +jATJtwJOHCUKNJruS28ct02RoU44wqBbVQiTQwt66K5wJt4FnzUJQ/8dpDFR0wZiYbA2sjLhA4Xb +m0V7Ch8IzL7AJdABLAF7ywevfYJkySJUWlPAdKa33HUmfVrIivV1iJqRW06NEZRs1DvVvlMnax3q +yesggYt++tBi5gs9EvjXJS+nXmsxL2J7d3M6ZMcfiJqg70X2jZi+wOJ0Mzqua7M5tHOUvrMSJfpm +uNDfrWwu3bZyAcfRGWS0mGXSwPlapQAN+Yblg+7K4tOwNfho0cP2xu1QSLSL7oWXd/tn5g4MsU1s +670nBI3ZQ6WaQXX/0xyNt2MQCSmkB7MKpLHtm5Cc4bCTZbuixVC2gryOcwf5xQQtocoBhEhKQ7yD +yVMEqCYHIG9YwAfl5VQUprwN/Mw8A+la+vGBCytl6ZGO0tchJXtuipzcHH6zSN/oIAbHelffqBRU +x85pPzUPMl1kTvcjBsMEor41ADBoP+6Fbw2CO+Ex6JlvmImhaHA6fdgfXBL9EJ3SlwmSEtO+Nzuj +gYMny79W/aCTOU9/egFEJFQ3YyJi2UTMtLpWcmfc389R0o5yE2b6ZfPajAK1fGJGvvbD2ktRIJgF +V6AeD0FOMfe5DHWLICcoDNI5e2bj9xY+Fc6OWatVfW3nQFrzIppW3CKcQW1sOXhZauugmNjBR3r/ +MX1TK+TTH74Vcn3add/EugZ9YgVMTvg9O73Q9dDCWGeCYnysCmeaQXFY2WGr85gYsAFf+eQ83a6k +nFAUlk8XWZ9Tj2ztHCdDwW46ZiYl+knFM3W+MMPlToLZUgfhwZqTDMgCqEHZuAgHP0lmkcAoUoPE +QWe8bR8rzNMMmWHbowBEEbBPtNHlC9NcM74PczGCH+iDY/uUxBme+2jyvfkp9qPVt5AnTeaaxoyd +EepmbC0ps7wIh+odpYJkdVs9wu4j2XEGmQBdAVpPtdUVH4hiJ41ppDHeZwY8QQSuWsmRLcsUvFfA +9nYdkzFZQwNlzj5qv9TLVNyjE7vox5SpmeIKoZPBgHx2Y7DbiG1UvvGTZRVjXqp4khnYNtY2tWqO +kHSQ00ThNS/8Htbi7rpGY5xn4y7W9GWQMxv2quGwHyVpw+5c/R4ozhyen/Wvh+/x2JvLbdXWejH2 +zk5pWb/3tk1hvt0phbgJycrecJdfNUUi+ZMdc5yZfEw6BFLIhWp3sOsZVmYnWmrrWrGaBzWxMd4s +Znb0myl2A3+pkhUn/WU1gjcDg9bbYXLdOsEspO1RIgNi/lJzbzTtBalBYoEEb15DkEAef0IRR0nI +Xrij8OPs8XFm63Yb0q7ze7MWeleK5nkMIw9g2pwTWIeRJ2tOa3TqmIeST4qBr2UID7UujtHi9ssG +DuSslqYrWIS2qGhHyTlVvIQKreY3tPEZs/y4iTHR7kN3KLlXko1XzPu1LVFhDK/7PlXHVF3R0QGU +epoxTTz8I5gcKVf3vxquVqW8/ZPtuXtVw2MzaKwkNCft1bQWnxIWTScmU1lkXIPGPPiO8XBl+qgz +4aOI1TiZkReFQ7pxRHtyh6aXcE524qVuvsTjo70c4gk8OOC/kplLM++9n63RhYkdBPcroLPNxSvl +K3LFK5WT9GjWhisMqVsILEZhVDFdXhNozlc2Q0J0RyaZbkjJeycOm5X3GV2+U+RsHlpvaTd2Vvpm +zuSlkW0ipnbLIg2rixH9QfJPlrzqLHk6g86bNfo6YwbcLsjm7uX3tQUd8PSktZsQd7Ra8NJ1J8iV +awUF2Yhch+m8Guv53iN2Hs6HKW8VxPK6i/gplxeN2sX2FcjP1sP7Rsl7hN69CWHaT0VxWitRs/EU +ppenMKswyMOmxpp4Db0eKxh6zw5uPNhAiRqA0/1f71uhSwmcIad59SMj2ERqS4zJ9YEiYwTUeJrs +tkeP4ZcySeRJEKl5AUhkXZ3aZNacmH1BjllvIz2FVqXNM7fg6H74IJ/86zWIKE4ItGrD8F3vWQSz +bobb4brwwg9KFtlNofRc2Tf87wXpHtUVFRXKr4OCygofmdhGFczjnz1j14QNT/1RXr7fT3cmKMpc +zqT241YZ2sX2q0anmqaPkDSv7t3dhW9KYJ5+4ATmF58YVjcDq6uY3d988hfjzY//8g== + + + za/+LzngR5/+TU6f/6ff/ebn//b+119/df2dGj778h9/+zuafvyfv/zi938pf/6p/Nev/vWTv/jj +J3/85K/+KP/r7+4BwenNf7n+v//3sv3rm/bmb9/83/9PevOb60R+9TP5d/9ohYhKRQvBv8hHby/H +bE7ZNTxyvow7E2yD6Gz2g4NOm572ISqbaAf2RN/4Z9pNYEBJG60pLTNDjTgVrcWbkW0E1VZ25tHt +Q5qNZE+qM0xkOZEyyWmaQE7sRT8bXdC6aXe+WHDLSS+/kt33mOY6TmA6+ZJptD17SWexw+J0wsOJ +R7fTb8wIRkCA7kWhtTyvIK/rOhwV6iR6b5CZLYMOeHNvb+ZLUwZ8nlkkDYnWxWnA4vNIElk4Gpia +nNs6JN53JHnnthj9LTqEG9mRigUgM9BJfs1t1gFmigoEWwQrBnecuEuPhAtXLvE4g0r/p9mzXxrp +WsUz+KgVaWRtqOX2ZIs9wBeeGCkqixNuSL2XAzbsDywqlJgXdEDx9DplN2z8M+17kidzEtktCUgh +/hZaMTqYbjFcN9KQJy9ktH039SbuMdHohcrks3QAzzzRv3aeGiXYbegI95EcGDI3aKfVbBDF//7y +EIgOdcTl2f32RPY3gxNhJNQm9nani/hHk9BTesQGMWzkKyosSPQSP2LJeRCjZ1PyevIIe/IB6/zu +cyTLZXOXLGxlcQyskbVRA4XNPvg4MDOdpQyZlChO4DIG3rGZvCBGidNm6ErPIAk8dyJVja0m56U4 +o6sjSpNPoh8ySQetMSb3tEI4UbghT7B6BD42BeJ6Ve96RdDOV1zFs8eolXVc5wZLJKRNVnZAiWWR +rXi0qCllb6Q4tbEykGGYLNsOgKRzT45W1mgj5yjmXokLnpua0TTqZylU4yrdsjP4YBV0VDoj2tTO +YirzRkLQC0Z7dMQ0J+bOSihjkZ+LhmslDkNmk3Gq0vrVzWBubvL68dUZB8GEyk3OiY9bSaSeWUe7 +vnmE8a02VuLSyuSpJthaGskN784B35P9ccKV+OSTgDJwH7w9so6CW/ImmaL5MXII3pnjzDgbjNqS +GhsKvYqGwwKOZwla/BOzcL0ybXN2gB3mSjJGFyOVh1qm33SZHS5EFeTNzg+mRAqm0Y141XEGTn6X +Ac+xGrws+0w7gW/q2VxMF7NX2ajYrA1xvSE42x1Tk5CxQY8ag5vNnqpGCSO7xG9NEz1qHfh7Yk8L +C8gjm7zjlMZFuLRcHbYR8gSxHjXuAXBUQJt1BX2bjLclkQf3+mlS5m3OqYZW33aQfcA2dTxpOHql +UFJ4zEJIDCMtEAt4w+960mDa0Ugb19Yp56SUsGCbHlSDVKbZ7cZKiYJD7y8PorEEjkPiYUEcTBAs +JKuKCRwV4kLFkqUnNoWoc2mqGs802+akpG0lu9R3WTBCKUpvTqlUaZAWpd+01ckeAdZQVa2s5CHb +ftd1btQIx0Y73ocBStUe+tAJO79Krs7B3qsSbKlx1YMhvI8EuQr9Lp/9VYWIlsyddYpJg7wvLyuO +4cjRILGmjRF/2fEN5M15dxva1S9bJNa6T+2CzKgko9t4ooMy36krS2HxmXZSD29jaoOTKsZ/t7HP +qx8Y9ty2keu6f6gKyZDfW51/n6rOXpR0ig3rXqtG3drcQXXdLkT/rYSwsE7LqlEBQVih6rmWcuM7 +4TEve7NpPr+23fXrKI1yGmq016d06/JjBZ1lK1Dei8a7Jr+jiIzezH4dmcbUeGpWNZMV9LN4YpMo +aclHTkHVgZ9ZR7b5WTljdFFlJ5t+Gc2hWjaKrgtI+8/3QpxEs8wHlWzLkYrQLWB/VZkbNWlnwPdi +o4EuoHHDvj15LCANSmpqOVoZVqv1BYYp+WkkM3ldotKgu0XZpJsxUVR9wlV4Gxg46G2p2eJML27r +vlRz4CQS+rXyx1Q40oFBfT0qdDe8Nt0Vt1SmRZ/PNFfDDZXp/UYNzRT9Jc8R7CeKXNk4Ul23R3wW +C4gdc8laZMPNnT4XKYFQ4oE76DM7IiU9Bc7sOABezncNIrXAs1bmMZqt1HhVcbtyFwV16wG1zTnI +XaOMlY5MqCOpJVQChcZw05jLIXAHVspaIAMuyUKvXJXkFFru0adek5Uan1hd7ol3RyF3z7QDMl6i +pi++097y4ZRkW/k8qhlnjATrkFDCwSN7t2nZfi5fKwWnGIDpe5rTMROM6kmJSpOAN+zi5GDieUnZ +KT+1vL8o4GED05dlXI3PtAN5UrZD/ER0ygB1ZTuxo6SvClco+13w7q34sDdDZxtdrfZbhVBnINL1 +Jh6TeMvp0kuzD+M5+gobdp+LaqQqLC3k1hoBhKXe4LjFizbYW2CNraUqRpfIqiR3KiqO5HUAIGJL +IYO+1jJMCK5AXMKMgM2XYmmQV5AA75bTFU//TDtYewveequ/2AioXC+QWNNnBwvmALyAY/M/Yuek +4pyQQbxOAiATVbTRaE32n9oOPBqYIHUXTDyxlUhvCwUDs0G1OR+ocXC2iK0HB6Gsa6D8vBz8IHfB +nrxoilpvXYtr0Fa+cTBScDI3kMeN1M6gkDyEmFVUC8yowxpeWKH7z0Fr4pl2wGFFTBayRc01yDyZ +s4qkuoeMkb4Xr2BSjJ4fxWyc3hOpzGo3Z/ZTmEvoK7yehxlCiQMlnvBKZfD0TrTQpKzpQpVOZbRc +2qtYkztqoJBog64IjYXD+Widz3UqzEdHZTq9hfJnTookBVfmREN+zkN5Xks1ft8pe75sk3hmgZc8 +gMtF+GZ1TvdpL/bb10rE31A5/+t7w//x5sef/ubrX3/5+ad/sz+//uDnf/i3r778PI66rZPnN5/+ +i/z3T7itXTkdisUKxHnPLQWOW0rDnOQQhAhnM7c3TUKJWt1CdFjKBC8xZQmlgmVOXiTeCqdscZcy +xhO92QYGUHnL8VUr44sxJTcjZbIIg9S9t4P00vFcuP+kiJLSKCfmNzfxu1tw/flnv5Z79ONf/O53 +X7z/8jdv/vH3X/zmt1/+7g9vyl++eSswqev49ObtFQFKESZtlQ4Z2ssVFei3+Cesl2eRe3jZu8YJ +V5z52T9+8hddkl2ZjxvS0JEXrwrYSc6qKG2razoV9WRdJASvvPFX1yOqKokiEcvlDiXK2K/99SqQ +n7lCOBkyv17Sz16+/w9/9q1/eK4GvQCrb0kA8xna3p99pm/xD/9m/9UvvvXC3/Vx/fXPvvziq7/9 +4g+//+3/J3/+5sdPn/7Nf8Y78d//4evfv7d/x/P5bqetraWfeMPolff5PWuLDy//Bz6TD31Tr3x/ +r36o3/BVP3iAV13Fqx/Va5/fq1/p65/0v5tD/AmrytdeiprjdZvfM/7ELJZkAJSDRYnLSSMTeK6s +ApMPnjyTnsmThRnF6dv0T2k+3CXDWRYW9RjjMsjeRvQMfIeCtrOOppTkxGJKVT0hdVp8AkKT5c1J +9Lydyy0RZ5MhIXh/8X/SBUr5nB5QeZi+jwesCcFW1arUdSnyb1XMToLU1kgfrl2nK2uR2OpKAcQD +FoHaiBtqOpS0XvvblZVTUB7fFoJEidzEDX3f3/3sW/7uvP7EZ2WKxev/2/19e/dXrTwIbvz3NKdB +bXYdVYT3s8pRHiT7Ms17pQgWzdqVD8SXSpKpnYTeIbEt1b/qtNsgllf1s6CskARwOjtFZVZeIDDT +jd0R/g/U9N1SMPd/ODfpwxsRrcLJNxmUkc4+3oY/gwcUJqnCEvex8VTJQobZC1SupTbQqGI+KTaQ +mT9rkbYf4vOoQkl1mIA/SM4b3S9IT6UaYgQgGTxo0fMz3YxG1CSmVFEyZrotd7jxxqk8id/5njPY +pK8ohuWiNEg34likh9vwLbxhVuxJFXeog6Xfxx2+lcxEvIZU1qU3pcXgK1CTtzBnMt2kkYBh1v6g +OMO3pStcvb6pSnJ27bGPfzuqlDykuFf4PMQpfb9f/ezb/qpx703mc/I5/m9X+G1d4Qa/mW7rNTsP +1SI1k9TnbaLNerkJlTIfEK9UHC79nE+V4ffBKnoCREeJhQf6HGskTvaR4GsbWd8LKx4xAAxVJkVk +pAGchQ4u4uVZ7KOeSGiZN+zAiy12yRIq+RKldG9N3t2GP4svXD4hfV1dOUZfMP24yBarZT8n/nQ1 +4UJdIInCWj4EjSlvNEydx24cipfFaYMVE2mlaCnOrSOvrUXL7KVSPlmJeNdEAapnnyob1mFSeVRv +R6mgRW7cnVyVTJvkesWDnG0Pt+FP+sImbIj0hUt4oA0xZ/+tfq5KDnmFq/ynVHEFHMN/8k1SWMAU +Qs8r9lU/l3WSvL3hP1/5y7E4oNCX4U7Vy32v3/zs2/3mlrJ5Mu36aTv4fyQf990W/sUn+ztCJv/P +L/7w8k8C0vz5H77+5y8fwZNJS07wbD/DrNn1PvzXD8EphXvgFUSlvo9v0MxbXqoCwmOPK/S6Tufn +n3z3K3j+7T/+0x9+/cevfv148nL6fxfn/MAJ+00QUHunBsnH9cN+f2tWKP10QRISZI81CdXNs9XD ++MK09PFYX1PFc/atrdjU6cvdzx+cY75kpVTk+fMwPtEF0S3A7iCj0ebNGupXfAq1uV6l2+K0DrNf +wbGkX+n58+ddef1YXzNFC5g2PpS7n9fBf1dKtCWXsmuV25+n8e7nz2N9zSnqGLd3RDhsanv4dTCM +3azYDLh6++swOpYRz4r259tXJdY43kr/rcN2nNVh9fM/VvTrPH/9vCevH+tr+n1+/E7Uf2Z4jjuw +vSHlFxix3j+YryycKlaYGBF+hRm0UJU0AWp0SJ8pKNDsiD6td55rbBKvnb92a9Qz84/lzv58b19U +jT5/br1DIyrObB1o3eM6zPxMM685FvB7c/zQ/W18ev3uPstzsAc8Fz+u5bf9xqy9wLcGlgUGMXl0 +Kd8kOf3V5re9+lCRmP22q8DuuYSWBbMPG5W6HozrvOu35ud7czZh9NsfyzZveHNisHlLG5cBs+N1 +ecmxxHFz4scebuTT441cvPG2ddZ0/fP314cgI7SNFAwCja+T34XyDxmJa1WUWGayAG4HRQdAAFtp +8Q24IF3zO1M1rJbjvVLR7l/BML3D7NgPDqqgHO1VUcosZMDPCY3Nkg7QT9qsxihCBAiY1hGYhnK0 +2Yxmqx0QGLz/GxRlDmEhcr+bPJo50isqA463gQtBx8XzYQtHuonfVrs7Uk7W+RpK3wkcr/+aTgEO +jk7pqTkWgbM0uJTnW3tctqomeZqA+6N0Ks0KU8e91DkK4L38tpv6ixeKQVOrMi9jHE/Tu6DMKPH0 +n+/t6zizvvSB+gtlQAI9ji+f55ndymt1GruV3R4bl5bCqgp92AdkBZ66TT3GK0cgIqxykctpAA1f +2YJARkJAVYel7cXd+ta6YRyrCGXj6qrLGNdf/YB0D1r8+CIChJ8exj8Arar3LDOBklwAE6u7IKsm +wDI90ls+T9dtL6y1Uf/lODZzuORcNOlkYZzA0wdO7NmS5T9e/0dHInWPD7mSH31uNw== + + + CGLctZoC+3v+m2HppQGLJrHLeH/L5AznaWzGzvHEJQQOgLx24/vivzDeAEFtYKMyaB4hla3xUemO +qIBMGZx+irMrTRF/WT7MxBguGXhA2cjnvDMWq4X4GhzVUPIv2dyf499wdG8TAyy7eHLy3Ow60rn2 +04jF1bmMmo9/88x/I3PGFEvhQhI1OY/vQf0Pbk6cny8+cVt4Sc8P/8JvgMp5GVQubpUa4XVu76zq +YZXdbp6DuoI5bh+YYmkSQUEbftXWSFQ/5ivx/PhvQDtuPzmnfaV81RTbBN+BF/OFSwybGZavd2DA +TLt32tysg0z4Ckoz7KIQIZp+hq6gMDj7PYF6TNKTYZ+TLlBxnVxAd2n0NeQvV7s5fCvrnTm3YToD +r35iusYHByY/+4EHJn/0uUXXP/p83XiFbRxPyoufBR7vXkF18GxgsEDi4/3jvwEnnRkxXyggLtJa +DOzEbnyJlxSAvOPoza+0HLNnMqpagRjTNpvffYeAayOVM+7Z5gGkLgrqzsM4Tfv1eAn4b7aNs2Fz +MqyeIFtJgrrIRUfjcSUJgNnj8GFoY8N/knmuYwBNgbCQmeMdvX4c+EJu38dtXmSkfuWpfPOL9ENT +B/3o819cP+UlF1Z7jiqKx69aSfngzvNdCiuv71AfvT99YHf62L3p43emD+1LH70rfWhP+ugd6QP7 +0UfvRh+/F31oJ/rofehjd6GP34M+fgf6s+0/60xql/kD2XqWtES82CMMbYViQs2H52V0ukyyFHYM +SyQwsiiPE4l1at+YilN2Nf+WOG0n9u20bpXM7Y2jdmKkDoky0/kKfVBj3efqJN3BS7yz6wUUIoaV +zN39gc6CGhIZ00oK/0x4h0HEoSRhpmFX6p2jSru4vXFKh0NFjfwed8ZjnFKLV3jZVyX7mM5U2cse +E50FxmqD7N6KmkPRUFVQ+9WZgFrFKwwZPKXCSLnR6NRXwmCte1cVv5I5u4ApqjqdstTYobDqlYcf +atumpSIvNuU+5CO04YceAhyCLp942+fJvYV5ItmrOTUvEGHcF7IXqISi3UFnfV+uMq/mcET6/clj +wSWprZpN9Yf97yELIM97FtdBtZsqbwZrrsU0W/UtKkFRW3hXpGVL4Pp0AMPi3JQaydiuOjHuovOm +fi8EEpW3duLjcPLNyexYjeMYzu+Z450lxSZh80kpcbzJnhRZHfRv/AkWECb7OKwSgLr8LqsfmxAg +GmP/yhOzqBn6u6ouuUHhTKqHR3fypFU2CaCyuqAlWN4l9abDBSFEEyd6/e9wQdc+iAZ45SCMIMND +uKX4tJPBLhN6wp6q28SjmGejD7L9I3QI1FZcgbEd1JSUsRQYRqb8xrRyR17k5toUfrTmcPExU8Eg +VZaI0izsJEPlociDTnRMZWMco+10BjVoUVcPPYZNdeo3MboT4wKVI8YRXnQA5VSWyejZWRnpjX6R +3jKB2uP18WqE4Q6oGHWfQPmqD+0jgKrzpJ8d7j/0U3MH1AxxUF0CaCuLLmxUqdc6dIenWbHA8jjy +sivBGD3QhAfKVGhvlFKQi0jlUCdPJqwmFxxi6Drpb7cmJ9b/jK9Lb6OkKeFHcoWDd0afRCESeTjd +HdEVJNHYzhWucGfaUycrg9DlJpv/SiGsXWy02wZf5zqE5ovNh+YVjmCYyizQIw52yIBLQDw0fBH5 +ultyFkWq5AmZyiTMBCA62Pzvr88M31mt3tWaVD3ZrbIAiUmZBBbm8ETQaDKxYbNR9Q6aR2bck0qx +B+v5ojC22bfD1Jaz30MI6dGrhCfq5onkH0sga+6JphPEFmOr9ZpjH6TR4eu+OfAofDskNtvvqouz +1nSQWVxhD2XtYtTi+oZQioeIsxozVSfHzQpwezJvnSrnYdNKeCHm2mHEGDJ9gIy/2TCtpNmdYQjn +AX0kXcAqNv+oFYIIhDoh5GInT3D3GcFms2Q0EnytI12+Qi+ocitbL+FJG4GBqi5bHK0MBPoJtxmU +JJsM8BXx09tpdG8dLiehzSq16+TG1g9Ss2Lfu9gPNXDLacTnLOen2R7KzxvlTyvVV+WHj0jIsuHm +mo1Sl0GOUY2t0/1QSRtlC3I0iWMw5STxQxDnW64UJ/fx0E4RsTjO8kHsWA9ujF+JFFVjRpQ0dmqR +2uGK5blnVEmyjFVuvCEMs4rRkurrtYNQVpiYMPywOK2vVSd7xZUJorsyDb7WbqMH7kcQWKu9uX7b +cBYKqtNPbIsqO+Tqekc+DC5FeKKCDzJtj9SuF7fQk9VDWh4TvToAntl2p6pTcQUXIWFdrsE1XIBT +cc0DPkFfVHMgMw04Tk7LPXqV8ERGB70kNJI8/XBEzJ6qNaTcEaU1QN8hbTJ4ug5tpkbKcmVoLLz1 +ZR/cpKtSITQ5QSQFaUXUjgSPV5ADraMZjTCl5Zlgt1BWRTR7ulcLmCfVg6nh7Co2KnALywEJlWVY +lfA8l2ETUiOE/sqG6QsMuh2oO2hQZtqrgrZcK4wWO3XjOPYFiOP0IWLlQbfYWT7NQnCI9pT1M1by +GfdFHAfvrqEkXEomalaHaygJsNuguWIENan5IhtUH6HPKWQrmXnW2OxvL7uzGvqEnN+kBFvt5Cu6 +dUUeCjTOdVbksO6KTF5c+QUGo5FsPBMrvBPpGfXOCk413Ij1KIU6Yrd8u4B8wSVsCeVo5Wv2BXTa +XB95rTyBYRu5vBt4PeVMd0G2Vn1LUZhnbYi5d3EpZ9O7M2p9+hCwPkhJoKfDiaQGcprGUfTpc6nd +Nwktp41BYzpSO1CJqNaZix1QS70ZqRSeV6HQmW4dkVsvJo0uRCX8wZvyeG0TPDYxFgW69SeusN1M +8kjpBGNNyIc8OhT3QVXB2ZLeaa68wgmB5tMuW/aM93ROA6yE3agt4Jkm+Q/7SCQUN84mu/M9hxfS +MM3sY3MFkxLQwd3twwZXwIJRAS0j+QqBWEZuqDlM3WBlcebngjxXiGF6OuhBWIfMLKyoWiIC+kKK +MyUYWRypV2JVX2EFqUrerrJQFgbNtCBIo9ZjxVjacQ7qAM0RkWJk9go3lEYi7gmfRZUBqHzMugQm +oGSXWFFafasYjc0Rwm2vVAX7ihdDjZdW7N66EamZyXwLYqPLNRtrNyam8ESWU4gvHP4VmqiGeCJq +0rg0Ya2mCeWOCBxRVTwgvFZmUiKuaNDmjCw6gRd+xCpnpVN+S/8+MUVmfilHbtaS8go2zQwmcudY +MOMqCfwGGTU2OVeLg/MOWiPV7yk0F9IkDgjaKTQcgWXAUKYpZwZsBdyfM26iVOEK6Uu7Z1umGGLG +cmR2lfv6ta5L/RYmGApvMKPqJKsxjyMeSgVOixKVgiyslGdeTgyiBUfYTi9UndC0O/sL3mVZNMiY +75xKOKJhjkhaV1NS5cMRNeS4wyaL3BFl0IhJlYPCH8aqqIHL9Ck2DgtevitPZ4yZRkdvdhQClfZG +7/ByOKfY4JuWfbPuhnIx3oXKPqSmMNkZprb3nDaIPJLFrg6yAtZHikFlkI4QPyfVTLC0JQWu2Nsb +auFmzrTvQlE7nFfpoUaEtczY2j5X0Kp+WUb+YaeQEr/K7bV+UJ7VYlma+yHEApIDQdaSXNsoHPko +87BBNzGOeUwODm/gXEEG60EQtROXg/dHBqQHjTr27n5oWvYg9aA9qGuZsrm3Ztx65oiGsXVUSQnG +DEc0Gi95gXRfEiNbQWPFEDlSqQ9tgqf4CGVib6M5TkmLlUl/IRXsCIrscpWR5eS+7SCYAo2HGS0L +K9n5pQurAQU8/O6IMA69LUawe9BI9qGq8EjWNt5mHQEMN1Q5KL6Cb98YjY7RRBXK5q5cupN2ineC +ZLmkg50eh/v6kIqB16+N7Uk/3XxT62t0esUFWa2Tl4bzUKl+VXLjGuGJQnrV65USPDPDyag7PXoV +90TWPJeAaEjd5PBDCe0rpWSjGxqGIVfrWPQ4aUzcNqofSFwGyb5lPLHuhmrieOrcLkfM8U8X8zTB +CNqu6CMWGEYZJTx4MzF70YF0fUmgi2SK2xUccypzAB+QoRygFD+GGFRqs5Xghpyzs/AipAJR9+HI +yuTuusKLQMtXpuNIxFnIJdeNxP9YYMANud5bRidbg4PGwhkSAvmAkxOpu1CzpD+DHP2okEmelFx1 +2AiM1SgRujshgB7FjrhH1VWRaJEfSKaUTateu1/hQaQpk+BuKHl3+KBKT6o+yJjsajmlW1aBpIhB +WNwBGF2y+iDidrIBO82Z73UEM3gVxD5dXHcMwnkiGhqmAioV7Sv3iAUgHlZCa1oK6Jb2l8xOinob +Y0wsyR6ue6EJaqgUhXX5xiwcqlakhx8ybg0h/HFtWtNPHmi89OThTIKqqzReJgvNOZMCqPZ+A4xI ++Cj9hCf483W7X8PnIroPI8c89FE5ck1CLRvNQm/IRoIQVZlIOpoZ4YqsJZMOUr0rPLf7IHy0zeGr +t44lPJG5omE6udeH7b6ouyQniE3dGRlgJi3PoE3rwu4mOCpMa5WMGkEAvEzjj3aqGA9ihAWsHpp8 +ZMPKtme7M1IqDWOzyoWhAwRTxe+MHYpuxoWYtTPkvijZ2Lqwo4GDNRGhK6+l8sKZUZXANPTPpzOD +Zxc7nZns5AkDubuj8Zf56AqE+WKF0ZF/oEGup2tcH9UZeU13viMmGocA2ySypgoPbyZtjE49muOY +HKHJgzYtvbo3ul4ZFplIrpRYtemm5GreqI0BoxLb+QsMoWDxhyZSZt7I4AA1HExj06sW+zbdG+1i +KycfWJVwBICfxbTXsiXyqxxixWLPs9HXD7qu5f3Lo0wEV1BAhuQrAEJTnLBYK9No3QnuyZOzOQ0C +AA1bd0eL/KvEFvEjEdLb0gibBAYpp4Pt23yUFRDSKTGb0LvZnuBONhnVdvbvM1ImmdMo9Dp1Jjgz +aBjrQBDjr+vRnMW+wk+90ZctTncopUX1AnZ2WmTZmNwTXU+vYQWqh2ktAq7CFZ8f3Eq4ommuSMpF +Q/htDldkkkxyh1RWm3OjNnGm5uaT6ho4K31BoiciwW4+yrRqB5uIotE2gzZ7HYQ0ubpuNCuBRR+s +L0BeBNnPK6ECs/MtacknkdizzZa+OgDAZtE1Hh+TyL+OvbDFCE4COb6G/qJO4SsMY9AonY0VBfUY +KbXQDk2fspqGsyk3UzzJWvzmiYDTUIXBgjBhkWpDhPxS5lcctebhTfFmE+bmiayvIj6jEbG7WeDR +fND9kD2y2kMoMOkZWpyznLuuou6khLuHFzKgbqN23K0T6iGObFqPOvRyLFCJSamJ+a3FIwaXWKQH +VqPBGsSZ7+gZayqL7WCzWVQMuodyUokVSOagEKhYAXlZdZUgqUtP+KDZm+uRTDA1nzBNKb+xzT85 +pDOMftr2SQIypSGQ2V/p64iIEBhq38XDJ0VcmmsamV7EKjlKSx4LzOMjVUQHvBB6/5v4NHVDUL3Z +BqaM6LbT53l2uVjpk0gN3LpSODLuSzF6qULdUMexgxTBDZOByuyF2/joUdwLdUMRCQ== + + + PeA72dPcCamqBXgqFePkTqh4Q4ADqs4QJhrRLrBxeTv4kOJZidpBuCPtUD8/VUdG2ccjO4iCirF7 +QK0R2SYT6HagAPjKxePEGGpqGchopXGN5r8V8oSPYvnBKxFgS+8tyjjcbrVz4AusCSfEYXax7SDk +TsONFZ5JyQljgUYYEZXetW+4QTztKiEqZIh4SCP+F95HtrekAVEoSoZutviMnMl7NIw5W4wCQsAK +idqgYie3ZLKWuQU502vVBcdpadnfXxRX1A+uIx7CaXlE1bhdVkg1uCsqBgISV0QAgLwWFdnZlV7Q +mPcgsZy04twRZAsAy1HTVUY5eB2vEBXCBnXjGLFAQXbWYmiBA5nDCNLonq5kk33+3Y/uvU3xCYh7 +Dw5J2IOUjbJ67QyFtlxOMlbxRBVEeN1KDagndXxQowYyyb+ycbbdNApSe0UPW5v/oCNU5YC3KBwx +WjgR4DPiilUcPLkrbLN71ai0QVvEpMs9RXJRI6E0m4W/1TnveOdSwgsZgkj/0YVx/3BDBXoKxSr8 +LtgOvKZKgVdyvyh1sxpVGw4OC8yMVfC0MxxRUP82ehz0H4XfK2cKBTZDqYix9ePvqW8wQxpRPDU3 +MXeP0p1LyL+WN7w01XGM7eRN2ixvSNmH3/V2jEk3UEygB6bnYGRQ2o6+HkFdtsm2U6DhFytUAonw +oAXpZaoHFUyo5nXBHi5U7rUdfqia65bYg9W6SiiWRimuRcyx7nbDMJeoF6PNre7ShpmezIsTm9UC +8TgByV7UwDZfuJl/pEwHmajX1XzUIBu82z1R7YM889nF0IjeWkH7XmzHMDe/TjdgOpdqb8Nb7auj +gA2UmcU5iJ702472e84UbliZx5oUuLwiEOq1CG6itqixy5NHdoDXZyXlNE+ENqNwN0GCSxnmsbEq +qtM90VgJXwS55RYKz1bvZoIrhe2SacwnDsloQZU5bQYEwPKREnhEkXEzDyf10XryvJSElRO0fiVh +M4C6tP6qJ2zAZKpxHfz7Awzk2Wv+tjHi14bPM9+5lnBHBiPS2Oh6kUe4Ixkm2Ki6KZmquyOMUNV3 +ro9J/u9mwzTwWqYzmNvBTqN2CwWFLLBwgWUIAxG72b6qjXrlbkQk7ouyocQFyUpG2+liEVJArGy8 +ocwv1cjpsHxpyDn/PbVIHVyqnWD3cGW29rATqxb6NnMBgEZV/ah6oPP+NGZ8KNpZjwUssiwr5uYn +mz3iiojpHJj+0o/4mESSVql9xNXUIe2Jod9SW+hE59ORJA/JpThthMViR4osnXo/mCDfTXSGFKFT +ObIzJQw0b7iiaZZQDfKJB4F4bjgibSO5I8JsZfVg5nKqyMx6IJqBny1Dfyb65rb/iTmOZFoGQSM7 +rnE7SftI7EysTGtGwQo3F8dfN7GFlQzyomoQsUw13TgNwlnK6tSmyi7JIb381v19b4cDAp1/M2Af +4qNNlaXhVTfUktV4du1T4ufp6h0+8lgJhdNEDR6lGqwkdhJEEJXabtbi56oe6C6Xq6qKbwvvY8O4 +YkbkJgha1SrXXxuLULY7V+LuZ9hAc5MZszbO4bLrzyfqbIcw664catLMF2R8jdMeWSKdRIbgYnhK +LeEcSi+IgsVMV1WtFqyctM2p71cBxUeMZVhk16D1RKkOiRgme+5AXaltQ9Nj9qPEXTgjUOi8GubK +gvBpe+dTsqm+469RsJXXPoUU/KoYiUqO42qTU7WKE4sFEjf6zRqWxuVwPb1vRohQb5DP1hkO9cZk +RiCYrZNKNMvA1UEkAktEB64KA2kJ11Os2ioxTHLg9HWqcCcENgaUX4cy2hHGK8OvpV4YbdMZ7s3G +GD+pRsyICPiUekRBo1UU5EsbdBbwVOKATI9MnQKla47Gq5ihlyV3r7oDMbSfFuLcBc1KlZzcx7lC +I/ro2nwYRqFursgweLZqb7U1U3s9fBAVfNBuNSekSrs2jZbcC5n8rLz1qmjpbgiJrdiZPA1rbdo3 +dvTbQN0rxujbD/tfap/NR8xyHtz8p/ftgaES9uAx17mRDKxc+2BSB3UwMSbP6nRKBMZxNO67RYm6 +QnJBpsbGNkVsH7xKOCJDEGnTrEmj5KA0Az5JePlHjJhVFniF7gePb1NjKId6kgw32fhBHudkt7iy +2mgnH2t9h1rd9BRZbMha5zlYpKqnA9gxT4n0HcO70lcP40ampfLFXl9ir6oH0GYQCikibtOnJWbG +O3xFCEehHd3hYV84j7UCxjSCdx64INFVDzDmsA60+aOVXXB2MkOhkkGzvpl+yDrd8uJ3cVkVRr6n +zjY90lDxD6GDhfOSyYoesgcymVyQ1jWcgnTGrL/IMQx7z1Aj04rPPCJ55D7iEkF5dOOO6vTpjutB +IRaSMSn3RnMZOirZkzLjlcvBVY8ymahtpFSokURppvABOaI5nMkwvwGjNXpIuREr5ELZuub6WGkQ +gUTpX80gJzI13UPcHeHUVJMOzgjJpowZDe/na1NSX/wxDiRjt0lKMbPANViwEXDXESZRVkNZ+sIV +IdHq3mRdziIu+z2Vu73Fn/v5MmmqtnFwr8UZEQHU6xyB0jzNas8Z/jZckUmy6grLUSNjwvseVId3 +fsV9kXXL1BOlnE9PRM8+jcnY2RWvXYD0DJ25gKW9IMs1EyA5KoMVJeLqxa4VEU0l+iajoQhjPM1U +T09WMAHkmtod2DHVRCteX6rEIc5AO0ihHFKQ3YchpVCODv1wOhVDKCMs2lEc6pxpKDM4DTs9RpkU +yrQjC7llfDJET8HgZ6K5CPEzqZsVfpbUatvNjdLpL4cjKo3V6zYT+W3YBq8yoUpH1AzoLZhsyQLw +9m2nXqsWKJix1o5ML+3NggBJL6rBZMIRVTbC5vIKa0oLjojRqQjZJYLFs0tcqxKdBaPCecNSUmXC +u0KNL2Ci0xqRkRelTo3GkLLLRsEs+wTjouqkhlKnWy1WSDaTJPsPO/TVwWcyONB4DpdXQxKnLslX +QNtSeq/MYzuT7rxJwq3Qokn12OtPjrgI4bfYZ2UINAxCIepw0/GQivcy4+nMoJEnum7JXVEmqyI2 +Vp38z/ACN63PCrIKuWE+HQIdPGymiJN6hy/U7or7oYYKumzYnaPTGw5kxGb74FXCD9l4h/ojGbw8 +WV4NgyrOQSBj7ogw9CR2UnUWm5VX49qLP4pwQGDvNdCIBQrgBoeH7EQh7invEBIpHo/udwcestKz +axu1s5SkItbW78KsQ7M8xSo+gWET6r86b18+LbYP5ACcWqTIuYU5Yx1dv+Qqp8pUyIPJWsEJ7t2J +SivzzBAbk55DvFJYLQGJTk5GoUTOCa5IG4wvfhetx66dILbowfclrqFUUmdhS1A4pIsKSjIG9qzi +8P3tjFriWwYjInQGKgpv/v4iOK7l/NigViDFrMyibbKXWlCaUZxoHvtsT/P1s65Izyb70C5AXqa1 +84/caOPmeoooRuZnXiKqHA6BMmMs0BxpgT1Ufs3mV8sRC1TWP3Ww1mNbsQ/0PArLyd1n4iQLLsxc +TeZZttWcjtQKmMO8nKtFoqSF7K5MhwPMhKHa401UNrc+ubEv+ivIGSpZifftM7WwNBM5nmKn5sTy +WVvkDGLsjkkCOF+N+xjuAIGDku64EA2A8XJeLLY++JRwQxYP6bBZreeUWTaJTfUBWjB7TztCB0mM +amY+SCa2ZIg/M+beQZTbHNOsA9+A2SSb+4PRbofEOcXHozDpIsZ1MkBjXyjRHxCiHRtYkjdltx5G +7Hcj5nKEQwph1YhKd2MrT95gwqCavV8IavbhSQCPUg2E2v1g6m5rRZRHUll5x3SRnIPld5t6Zhbt +JfTuXaxHolmKTudyDKvmmdiEKt4dA4lJ1flMkgmiz1LLObwviRhmvErgeTepiPXg6mQQi0jEfIRE +ur8YNqiXyM0mRlidor9jSEbx05HceZZdNoeOtXzUSb3LxFf80ybXnxatIxwx361qZINlZeQEsn1E +SNRcNjsfrfvqDbNxswI8Ea+gYppA9cijVSUny5LAKMQpAP8jvfzi5fuCWGbb+Kc7EkZJIqHXGA2h +E6k69szshrUr1HbT+Edlexu+BZ7IEtG8I5ySdA37v9af4ynmhQVSwJUohLhDqGGyXyDGdhSrkaKL +GWG04NMMSSOnSxzLg1NxR7QMQKST90WqFocjwrydIiNiyiwT2Ca40sGGDGmpDsaRzHklmdQZ3qdU +vvIGyCGr/Fso78y00bgPrGy++XyLDzhW0aVh1FAm+yQeoFSfoBj6/Xo4BUSAxOiMW6rXpqXA0+gV +mtUBy7T2eayAgaf5DiA+tXU0enJhlQzEZGLb/u5pzgnGTydtAaISxdtD6nIjQtrHlContuQWD2IQ +MacgIB2+TZvdJ4mapBPtDghlS1V7L/Q1y6AwYhw+a4SBYzGWdGyjxu5VEX/TAw14oNYRTfV3GC4R +gNrO4YHAkyceKBd+6ypErfdrVQZIY048GGUxPRyA2zl64M5CYVfOFG7cjRI0rXUsAJoI7W7OO1px +2Z8Y31SL0PXl0oDQV0A7ogbss/ngUBZ+fd4YDVl1P539rDMDGFjSSVuALKdgSABOyEU4bydlSfSQ +zBkgRkLlQJSbvGMPMjSdkUtHVqZ0UWavjudmAJqC9nW6y082PRhuqG5feXJYEdlFCpDfg0cJL2QA +ImUiKqL46l4oseWutAgeDSV2ECUSCcQuMayFXGb6o3j8kiP4TI3Yl7mRKCvokEFDFRAZ7o7Z6Woj +6L7ANMVZwT0jn1WJwe7DXGO4kanWAdiQhNH6NbIzpuFZJKaIBADgkQjAZ8KJc8yWFHKMiYPpnvxC +hKuoNCHVN8i8Bsi7r4BW8jY1LngdNL6S3SR6czaXgs1wK2oO3GmewyXrWFibjXTEW2BWZlulnrrd +DKZWd8DstMcgxub1obpm4QJnzz5jTjVHBjX4tishsucp1kmWGG/tIxgC2um6B15NbQzdxRUtb5sD +06E8jelwBKuxVKeAURgLkzgX7q2EYRVMWIcraYx2qZGr/qVj//JB/AoVCt3UxjhPgUMkbBfJWB0G +Fss79y65krR2BoBEwqQxOHcd0UzDkHY2zCNiJKSx2XpQ0f1fA2BvQvrEFVmMl53YQmKkNjhyIAJn +/iAx0C0EBK5SV+BMT4K2ScSmRpDuhgg8zT4Won2QjiDCR0nvfUq4IaOFLdLAL/UcL0seSkgC3Hr4 +oeYyFoeyRCf8lNhg4QlnN33FJMqOeQghdOpOOFE3cu+0Jgcv50aWlYPvRDVmWVjUKQKEThX9lBJK +qbAJCZWP84h5cnfs7Hxn09y097y5d5UpGLqVdTjS1TMCH5JXBZGGdJ1Jf5LRByyRDcORgpdo2/tg +RtRFxAcV9yubow+jHKgfBfbrt35Qd24L0cQvoUInvmYhbtIe3AvfHBKZZU4G20D1ZJOdY9qOiNLO +ez9f3Z0Z+cz5yL/ulED9HVr3yQh53AdpIKf3gKrqkqU13rBN3arTMam45ZNXl4rTNw== + + + rsHWHHLCMl3cQ8rhixn0kd2LPXtvgS3ySmh/maSXsoI6IicNS2KByr4aEmtxrpbV6vhskMQBqCRC +k/OIh7DxKN+MD6dVqzoLHQlj1UGKETEeJeLhY8DFsg8ESX3z4LzpxiKC0OQoHmXmuTmKcto3Z8bl +UncsnRSLccIRNf7aKMTDgp9HA4vGT/rOqTwdGmQfVEbAc33QRbi1fx9VBLuoj9BEoKf73ooIt/bv +o4eAR/gRagh2yz5GC+HPpoTwi09MwiC7hMH1z9988heD2gimw/lG/vqNrvM//1IPvt6sX/23aw3h +Fbg8bk45+X9WaulJ/zN/ckVWN/9pNf7/68/Ta/8pODS/+m/TT/Ef+fNyt3p5PHylz356Rd03fypn +hV9/5ZqpB/F3N0J+STrPh9qDsZEXg1mwG+uKDpvzcdXY85UPb/O1dg1c71UonUNxZcVqm8NyQAOM +jQ46dyexqaOiEKdlQ18B3DTKezUoYskpwUJ2U6GBKEC8luRjlgrKBuHU9ek6/x/7ItRPE1bVRFhK +zJTILSCv5o6hTkGoIfJETvfKPfym9/+tqkdf+/Lxjn/22acvL398/7Ov//CFHHz7gtsvVLC1NnPu +72nHOIpDnpVZDCSfxYaHwWKGcE+KmZwoFzs/8mZDEKQaYvYdDymEzahJjIc3WZYb3dmscUdLClHP +SQxxyTcCoJMDyjKURLHQ4VjuHhKeD3fhm+6zAG4uj5e+7W2+EbD9rlq2f/vFV1++/emX769/vKZm +KyLj2aR4VYxlCQZEECDv2vdRYZGduCFglu0FL0O/M9/zO9U2743TjPcfnHyIPNibmRJErsIncWfE +CvuVg4UKojWUucpe98ZpRlvhsHc/WIbkH67s/iZ8w7uQ3vz13/zuD29+LA/uzcvX7//l6z/+7jdv +/qdsLG/ef/2bL++/N5sQ6JjWkCK8s8+jJ5R7EAkJtp6demo/JP/7qX8Pl5T80P0uZHXDxj/PXslN +559nHlqKH1oOG5esd7YXvh87s9rDQw27fmMa/uM3fy1hf5u3h667Q9+qGuWt7YnP9fHQ8ng9ub56 +6bk+3qVXbe3uxuOtao/PSCFbnfh52Mbdc8efDz80+aGTNuFVuP/z9Pqvqwe7P/n0eO34dVx7eeVE +X7fxz9vtn2dAMjrLKvI4tiFpsvNnibGDO7wbysWfHdBHuTOivj24md6FGOeHToGUeKDnFUQ/bkrV +Q//+7j2B+atbc1cAXHlza7Pb9b/uD03HS2mTxp3sueZVjI3RjfGmaxfh5mA+7mPVw3a+LYe5GjL1 +NAr1vLPHhNE+gLsFVB4kfsvoHYLlWbdO2yVp9AXKaweXV1Ytr59A8ZPVltBp7NoofjDe3YIwl47Y +iwgFva87UXfCLsGNWKFpYe/22Hrc74h2Xn0GYe6PbhGv1r/Rqd+aXdEW2ZYOvLiwuHE5yOstBZVf +8teSDeML7NS0UFS+BzODgjjyBcDiyO/Og1VC0IZxYePXErGorlVyfuXHI4svL9zz67bwMcefJ8ID +xR215CLPN+7M7tYrLk7ZNB8Ojbdoue1+Y/3Bdu2/+oX88wdY54+W/SZvwzWtmFsEMNedWWzD213D +QaqHcZnRblTYa6h0z3XwnKRdyeB/Z0ReXl47uHnnMxkq9MYo55CCwynsIw4uj1f2cBN+yBhrQn9n +GZlA5/zFYXc1ntOI9tGtcdkKT3crSP4C2P4s3hxITjFwHJlvVqgcoizKsGortMPICYzZ7414zjLR +Qf0FP1im6Eu9M24/h5sVhOVqkeGDBwuYv7Natn0O89aGElx/5VCpVXIWG/pnByZVULWrHRgv8IOX +7Kp4UthzWqRJ7iw3yoOoZ1GZ9kF+tdPYHMV4GFUaaDyuIO9iqMMY0kJCL7aanHqOxhfehtb6/cHC +S/3GWLmo6QBTzmeD060Cm2/dD+SgtOOGwtiNSuf4+4Y4i4B90eduDL5cKqwblWoYvaatXbbbg5uD +/UaIRIaxG2fvsUJFrHiuME1Rsuoc3K1Nv8hwFzQH2ywk7TQc8kYXsWJu9DfZpvpuDk5QwJBVHSwW +xnKUgk57C+btdGhoJHYnTuN6ZQXd5ePnQOQjKhmu9o66FWz+9+WVQ+tra9YPnADtghZxvanq1+XC +AGG8vwnV79ic1h28vIc1TeTekvXh8jP51uhOKT8ePDD3oMtiFOgwFms9+PZF+6CGuxoNwy9fNADs +h7GfnCWH3SMdNTrFAwkPpkNpaMQ5dAxunsd2bop5UD/tNHbr5x4LdM5oY0T+MFbHdR7GbBq29yuk +7fJjs3PcOK3w7u3e+MI9aj0eHBtaturGq/vkf7iY6aiXJaty/eyxyvVfpQT2X96UN//6yVtizaAy +oJfq05dm70JAJHWdKwH8+SffvSL337747XUBP/ni14/1uLMs/q5/1/KbsdLFWFSZ0Xgihhz2t+gH +MhY5jCTvgtE74SodY6XbnCfC6DU28AMglZD0SL8pK/y6iIzKelWyiPfhqlzK9Wk1tVBMTmMBLdgX +e1eSFVMEY3DaWioTrXHgsIzNaofOG9yvIBqIo9Xbn5PZnE0YhY4FW/9B6ICtJRX3Z1NwSis74CU6 +jhQ0PbUiZGFgmEQZL5vAh4zsVCLkXzFOG07ACmH3ISYxxlDOYdQGchifuALt3UoltydWPCmM20Dj +y91tyByh2ILqMuSlSk1as0OrZ81sOryAv29GxKjuJA/Tj4zbmCCvYU9nGvmJ0vnvFXcB16ASR1aG +Pw5OpnNyGvveB/9KrCB20LLGfRQ5a3Yj/M1RjWvngLm1+8ENqBwxFlyEXM/IYXthnUnLTDd/LtHF +6IcRZSLp9cx6d/BpBNrgNN5e7584+ANG/S1fwdSzfWX7AHWvujkx/yrv7tiN/dWDXzWW7nozEkuP +dnu+2lY6b6/5i6VcGHfXcGN/7dhH2zwIW1SSWYmZ3X46pw8alabL+3RhL5TL+BPGYYA2r4ybgxQ7 +xVPpSW8WCKMd+HTrdX3db2Gcx8C+tl6UmP/m1zLg0DcrEBjFU/ACjIXoMvTWyaRYlSNLa2Ak1bs+ +TcFp3v25gKE1AIs7oFhoybjOczoPnDe8O+fBnD4R4HRL7cFodG1udMSCTqLcHjyNMul8PRW3ITtF +GCNGN6yQMOQ2S3SuVF75325WGNMA2fLdHRjGsQyverq7y/FytkeKZBgNm9mQi/FTiG5P+ysHK48l +ojr0uWBDWCitajPDO1vYDkZ898wS4o9EOVYdJcAC2wY7T58vxmYYQpEaAxJtJRvGD+PT/V2Mg+em +RuCN7W5VP4WwE+lyGLtVVP6NuSHIOlX2sTs1U3bpouGqdQi7RLAjB47/tIMC9LBNax//L6bjfZZ6 +2L8y+zA+dmOnhUaj0I+vso699uZG4EC/Zjdjqw6bsu5a5HfaFFPmby6eBe1f3dsFZ3o9+q9Yhsyg +HoHd8iUl+rw18vV34xNfNJ22vj24AfRx2oQSvJfHBU47ykuHrZibQK5UWYU+ppeOMzgO9s/iWDUZ +KfddzHR8mLk4bvQ4uDrHTXyASooZb2qxwnzYb+/YYfQ7c7vAYVZ041f3lxZCiDc/BqTEeb048uXO +j0REea4wnKHpMmIOR1qbAsrxa+PKg2Cdc9kbY7E4/iaqvV2Zw/3HpR0rxHPHkZEmV3ZjE6hHjtd0 +OofLYRTBWx/7Pl706exR8REtL125G5Ggd6SjiKqTIpp25ObDvnfp16tZnQIRv0/i+S9f/v7N8xe/ ++8OXv//da2AQYEB0ZFrgMaI4LZQ0gvH97sloBUV8X1BSeu8bugy0XfZySltocHAZqxEfWrCXFazo +K3gPL6v6e5dRBJk+fj5+cX7Afp7JV1an+OP1f365eV2OGyDOH30uX/F4lyipojSr7+/+hUQvrB3L +7lY0kJZK9uYU//G/X+yvNeSePBscuQVfbrFLyH3Q5r/PFfxfZFdNiVVNl5mEAcf/xl/HmZ5H+rXG +ko/Xryt8ENX02Q+Fnvzxp8/Prx73t1/84eWf/vvXn335D1///q7O86PPDZcbz1NmBNbxNFczqmYN +S8ou/jT9X2gsC05gCRq1wSlVxsYp4sa2PI18IhKU6djHcbjikzTgORYOI0/Dl4h/IQ31XN6c6yq1 +avfJaWo1wshH62d9Hn5cuC/8eDe++dn+YMjYP/VsP/2HyzfdP9rLvX2+7/Gjh+u6dVvnd/ydHNZr +3/vHfO0f+61/zJf+sd/5f8yvPJ7xkE1p11PuzrtRWh3c3G7mxi2k2ZKsK9YGVc40KN9hVIQx8x43 +9x3KkFy0mwIz6V3sBNzo70BKdd8cLMUyZtW+ahhvzuAwx9nGqud1Pd6DF8xO4ba1KZyDmgac961U +1ESVVel9tKXIrg3ZFwlsAYjOntGEjbLJHgSbXS6RSi6+qtwMztT6KbjRC742LH8crKXDlW9Wddvt +GYTZTzaWPK/q8Rbc3TYBaCnP2DhvG/WUQR76nmHd2BwZ87Awew21O4l/GAX+GFJubtcrhACaL9tV +XnLwvO0c3OgwMSWuOw/W2qjXUbBsGG/P4bDHCcey56U93oe7e2dEu1OmW8971wjYVM7y98SPGG1w +CSrzWYxTSdOQ+WAU+e6ajszC7H0HfwlX1aAQDTE/AzdGZJn6zbHbEoSbNd12+/thjnP1Jc+LerwB +tzctbW1QDcFjnTcN32PSWcH3jG3JjJAozXVlQuAcIpbzxpj6KWbrdu2bdicbsVW7chEMhj/8dmH0 +KqeRqxwHC4hStcPPZcN4ew6HPU44lj2u7OEm3N03eckE4F/P24bCmUBxl/NkSEvM1WfVblkh9NCV +eR9prBsFkhyjaG7vqujlpSBbVtGBefFts3Nwoxd3s2reHQdvVQ0Y7WbZMN6ew2GPE45lz0t7vA93 +t07YFASTlG/kQSgDAhrc96xVIaeG+a1WAkmIm0WWftwaBTTZHC/gdq3plkTsia4qCIBal1P66xm4 +0ZuJxrR9HCz9FJsZPFYN4+0pHPY431j2vLLHu3B355oOAjZxF8edA7B52Cjrexbzss0/0m6xhM2c +qvALykK0pWpShh7SFVbIKUnlayr8F98vf99tL6zlF1To/ViJJDIO9lXDeHsGhz3ONpY9L+vhFtzd +NWXVEnm8fXPXbI5Thhh68lDkcqs11cOOSKJtFEapf3sYq3EoBcZG7XqNK5MI0ZZVnA/ocv0c3Ihb +J+BWrVrEwbIjGnnSsWwYb8/htPsJx7LnpT3eh7t7Z+Fvla3uvHc5o7qoHsLvHeTdabctEQSMopsI +NpvDCIm4F+7KZpeLnKiG+rJyO1SZ+TwHN+LK8wEPwsHi3o0b5Vg2jLfncNr9hGPZ89Ie78PLzdTu +fW3gA5WBj68LfHRV4ONrAh9dEfgPWQ/4d5+qTZ/+u07V1tt/9cGp2nr7p3JWH56qFWy4VUbOYT4B +OFXd1TX5uxKjh5qIRc0aoCnUT+vqyJxlQqPpJlt9R14J9IX2LV9Z0y89GupszCsB7g== + + + MxuXUB9PISY5Qskxm7CzGalIK5JD1BSV8oRlBTIcIoHLM83gLxM7SCGH9Ho7luiBtZsTjc8cklBz +GBeaYW2lM/PMvBWKkgJ1Q21HzzhBUYlbb5xxBvXiE0sGbVPqaQnt0zPtvU344gUWmLE5FJuL3+U5 +KEAtHbp1NEBBLSaUcqIQ8swYXkk0DFYO/oJZKcIpDQZMOUgLqRLsVOvY0fKicGvR8RZfeKC2VFzp +bnYjWbA10GhZ2SHZMj2wD0ZQkmiJLlnxmvwkR6/UuIQX9ZletyPJzCFkXlytaZts8i8ZiE6whe7I +9yS+beAmpfypQIn3YQI0oVP57Tx0uMrC8j6dKqZs3vjsHFHTiaMPUcnhkrvViMj/ngeDoFk0W2TX +t0veiwwrShR4Pd9nRmsQShSsmQkG6XzrJpQv1zFR1Rh7I1UKeXQ5eHnyCWkPnV8yHSDRIRqYbks9 +dNP6qJw1Esy5M/S0NAvtgrLeyGCh4qF4KExvFNL5GEiKr9AKeI/kfI1KIlqefKa9mEaFEAsOpI1l +b7wTYGPWOcG2kAoqeZFjvUA7oUKOvBCBrHVID+k3ZLZqhHTSkcX+LAdmYOhV4eKJf3/tvNs+U3WL +WDfzw5ENtliJKqNvpaewB0sGHYpqyfiJ/XxhV6z4yLEwgbyV5MdSDwZtfZJn1xeNqIW4WJQYQfYp +Abzwej7TDoJWGbA3mmOtMBqJZiqRAsSJJbvrDyecDKGFB1cgPdaViJbWCZke2VxUFcrKSyaI3LX0 +5gWqbLuNTY34a6K6eLaqyY7JO7Wzw9Cv/++XzIa3Kmjo3pSBjExHUKrUSr9kSGkutitD3trx1SFY +VRfV+MYneQlRUwPpkk45WslX0lBhZPilx2229Cavj07teUlF8463OrOmyBJdVUtCT3QJyeY8wfUO +TzGAIpRugtAuPtOxVKVzklOGLrI4m8yyl678Sy6himpmT5OqA9Me3ToEcxtDXRX9O4RtmyEGxUy6 +mcFBDCkBUZ+a5ERydw6nKeM/ymSkVTZI5y2AQ61KLmQdf8+DlY3DasBr+D6RIYWrAwOT75tskdse +q0x0CFvUM0sOqkll+VuKeo/F59mFXCZlGXRsc8V0QPUfrNTyfIycfqmJmoRg9gwGCKaFymm5vKoU +dgoqCqtm8rWDxEir/NOJj/dh8qCeIUMcKlzC8C8rBlEyubMUGhtIqkzxQUE6TI76UZRDWMvQ6JLu +B6eclNj1yZPCQXntBAZJpWavmBzIkI9h+c+MKTlN6vSxleW8YKIKb8p3cnAG4eE2RgMzhmqD7JvQ +mE1WTcR7v1liyWtx3vPuQSiC4q3NxVuskEyD4z19GcbC06LwgeJENR4eSrWCbF+RzMOMAQ9RO4a7 +umngmdFCS0P35U2j0gdL5KzZvm/e6Dv6GIacF29mgu5aXIKObwcG2M3VJBJubIviXY93wG9NQqTR +lbKcVOdib+ZBxPsaKaV6WVW+1FTXqiNiK/bJFRN2c2yxxTvdNBng0asS0utNMGVS9f1GOCZX25tv +8WCY1IPH8KkB1GfkjZ5+a/NC2ecg2t9gklQnoVB49/0m2q1OZSBhB8uh+AMoGr1yb3jXJDu3QUoZ +1s/BWYQATVDNE09D9TUJzUMlQOapAR3LJvXp+yCk6yX+MNFfWQFM5fJ5g3RIbi/HFhTZ5HBqSCEI +/N/8ts2yI1QmqlTyt7IxjBCqWZskufJdYfhCHwuFrNOi7eYG4MboApa7yIstZ/KeXzHEbdLgKLnu +aKmwE4qmu3oSA5aOoFteqlQFI2UbijWy9bcoTSVF57UBmlSc5xN3hmZDpvIKdT84F+SiJXfa0AgC +85n7UgWW6dvoxbTpbxjkdc90Q43VAdIDAZWaSZk98RTUOKl3b0QnikPuh061zWfKic1GmWpGdN1A +s68+An84HP/VrVpQdP5wlAAfVc9JdwybSOd2H77Pmfj1NEckSEZgqVU+0L/KBafMqunsfm8S2mxK +++2P18CCugBkHl1XXm6E19GnzxvirB2oZ0mirgwVhkVBAPVB2CYEVmsxk4yT9qAM7NDQVrfQnTPQ +COYl5JmbAlI5TfJIFJ82lpTSPJ7y8gUHgd3GZJf46nPQJyTTcLcVzFfAeYi46gBFkbL4OuQuGQen +pivDP9RFPdldJguwqDhyBS/Awv0oQXEPZB3pbh/MN+fx1U0B+zz5mo+Tx3jXso/2/b1d1Yxcjqrg +B0gKvCHPGkYvP5dGtYt5DFyYVp6KRvkOT+PW7TUuPpHZ1ON5X1W0P0nu7KdAo7/FEDmOY+O6aooh +9oebYKX/1x++/GPmo0GsVYe6rADzPoLQfpjta13ZjCNKyGGsBwrjtOfQv/VQT4jjc6fX5kuyzZFF +lSST7VUDIM9bdiF7Pcek5eO1OLaCF+HWeHtuYe82bGhf2zKxwHpIYvrdgQ0LFEiXn4d6cHwuGsbb +Mwh7MZ03M0I+Si5sunwUBODlLoRWR9jlrkkh85krAyYtt7htypAYiassTFUOt92cWZiPZ1xssPn2 +bbh/cV4e4MXfFWn88y//xx+//u0XHxpwvV4j6dOXN6puUa/v4bti9XTaeyHxqt7t8mltsXNMVYy7 +I0vr4N6V6m/eWEFjSIeWVwM5yLyveUVFkeeOXYxClbKvYCpoGDmFN2nn4tZvFSE9dmJQp0zvmKP6 +lKB27HXpbMJGKQQ4pMJrvbl8oDyiwuN8OTqnY/q6MuMCCgkZWLeqYXIaICV88SCrBmX7dWJ7VURP +JJ3Wsx1ACUKfaw7TMdeISkcBXngFVtXQmRGLVfXXgPGQ8N1SO8k5O4LasUN7JRlZ9g2ARTL+yimF +VRIjPfNNQm8kAHJPT0um0G0mN7vRiautU8+vsMAtI/spps4qld1FjQ9K40I3sZh3g3pUqxngApBY +5+C9L4nQTe3mvrVevbFPSgzeGiEjVA3eBoN58f5jo1hNa0G3bCKgghxyWZxhTlBql/EmSP2K5OeJ +9PDLJJxQg+50IFA4L/UUUhE2E9TipQ8QbCbFRrabsaraTQBviCLo9sHUu+ytEbrhFBufJbHFUwk1 +ThpVJ9kfhNWrlA4bwfEK0JkUGpy6xJ6DcJqvKJaMdyBClsoUm9dWa1KpN2o5SXNGmzm6yR9S0aCG +rznYlRe19YSsNRdWsA713ZaOFYC8kR1iLZ5Cydz6enLi7Wkc+aqNFywlg2+CcMtSTmlQP0ulO/0F +M6hKrae03SD3fkVNDz9mktt1uAa8EO5gAQiPxF3oJtcuAXfnuwSXUGcgMBbfJdlN1l6xG5ViP7dM +ituM3L5FinmzfwNd4Sqku/vYaSGc1lJgrq8blbU10GTOprq8mSEtWjn4XE0SUXfUVkN8SZRg1QM0 +9MAsMulbM6WGGW+PN6xMIXblwbZIEFzbLVkTzMq9eBualBKGV3Wy6O01sztPcGY35TJmU03TABN3 +bB8i3scKcn+CvQ0ilFUYzRJLzgjDL2Ow3mjp2+qHdcQJywSOGa8dpGSeQ7cEv4o3qjekcBlqsA7Y +qxTWVq3qTUgVIE/yVVSv6wvUCnFMMbpvZY5oCUbQL4nxyoUQDupcpCM1W6ZqLKJS5VC2qS7h7ycA +s/CZKYnz8AH1aiKc6jCcYFh2qYS0YNZMqAolqcXVBiutwhaRLEE6XRn3ZoPLm8CLpgyIfemHfLW+ +OZs8FWCfTBVyZCU6PAL62wUtu5ZLjpuIRrPqU0zeBKjOlmh1CfWyK2G0Y8a9UZRX5LpG4QoJDV4h +lyrkY82+nWgLyW9CdAILcTzSiaGwCJsl2oHDIFxIMevdZZdTH489XZIRLrrHrUVlgzKtmzMI5j7R +lwRXwRJVMg7+YUDdJeVzP8lrTRpXrVcoyRNgxVjm3yfbPc6QoT0Cr2cae7RUjafl0UKYiu3fVS+2 +LsV4adThoLpKPg6lI+SUx0hgzVDm76MSqeFWTv2o7G3CeSDSo0B3e4bytZOHVYAArAoduEAZ+5xW +rHaRSGWysN62PE0UQ6V3aW5N+CK7OyUhAGqcDm+AeAkKGmSf2fH7Gqg1FHVrMB0o10lDUbdM+J8N +Bm4xNlK1T5uX1AC7zCi5L1T9LCB3wL9dmham6ubwRKvE7U3Ha2VywCtEfqCKvd4VNDWxS8px4Ito +xtrw5O3HTOIyLd7ZPTCND20b2TkJF1UBrma4RohyjGyr41UvsepHUVBYh56eDjaMiTKRoJm4gtSk +BvuRhMWKhFNGsZtOUchnagGwtrThz1E2Z7KnqWIJjGjYSamr+X3p5EwNgQh5jqVmjLvsDbaWYu+7 +HuyMMxlC1Go8SIkTn6P8nEGG9H1W1Qgtoa1NqKWJ23SSPLhHsAKjBKvWeskZfPTdAtiJ01IlTTOm +VeJJmvaj2NMiscuwK2gBeKiWmOvU6omSraYNriOuLC7JGTRrLBdO3eubqMGOGGuaI7a3raLQfeX4 +pjsZUaTLaXVI3S9wY5IqCHiksmz6RlgToOwiLXjrsUsyBfpJeQGSdZUlOT0zmKpbYZeMtnplHSxr +k/wpkvDa0LIcqMX6FxZetbYi61LzShLhhMtKnKKnUIgYdT+LPBQDVUFOMXhS15lQUEmMGEwo74rf +Asn7NQmUp1MReEsmvOyRjRhfl/tiz+van5tTh8hsxKh8P5CC6cAEp5IgH6ErADWwTqZKtVfMRqhy +jRl1n0BvHjWGRhg2jb4CABRiHzYOJPP2HU3ujH692BabV9kpYMTOUncyX/gW4/aDRictnegjZJWz +xd8LFSG75OwLD3HMxP9q9+EtkHMGbQWv4gtX0FlD1FQy4Wmm62ZeFGQG92WdJwPvSov/pljEwF13 +zTass+MFz2bM8a1bnxzFbgOGS+g/Ue7NhLw2MJEf9UoLZDc/E23oJsvYmnFY28eH3pEUdmXoAp/v +5gpS02NjLb0zRVqJQ3sl8zPIvCT1dvlaJc9PFJVvySv2g+pJlOSVbh30e7NNgHjLwd4GnZRpa3A7 +BaxQkCS+QWK6cFiE98Ima2qbLNMYFZUG0yJiKs3CiLe0jC7gGAepP44VN834unOYQiPPgjOoqwAB +pRqQL2x5YtA1OSekRpFg8lyUAFXu6pTBJ6Sf1gtDfAuFlZt9dCLo8mrYUQcr/4vbg8gruq69cslj ++87m4e3E8KEoRMjxaHjJJdVdgXMrUPCUg6FBJ1v94mZUuKF2wWJjh9FKg98G0wRUvgT2y8mA0VUv +DBCzbCAkNZ5jH0J6lrlNtQixW8XOw1kQUVjAlRUTC31hmjAG9o0Tfm9Dm4c0uYg1K0OYuPJgUJJK +v1KWq9sm+GlwREw4H6rPYk447XaQwKnq5bQz6wZcRf1AMlUDDblyGMqycr9XYGchI2v2CSeUUeGS +VakcNrOPow6Tz/HKqr2n8i64CmSCUq6+IIPtSZ0itYKz4xbEbmUjxcItR9PahSkv0zZdb2k/A4x/ +vbjd9b8mMlUUd33opW2E3lATUnaRjsEr3dBeeAbk/JxRuFKgARrjBbVdLYxW4BA0LQ== + + + 83rcle055yePJR6p6cZhx13fCCl/cz4oe6cTL7e8qMua6wTkAJo6S/HlGWndaM5IpL1ZitcuDixO +g+ksk9DuFPYdg5qXKpn35NWsSiG7K/GaOAdkNmKkbLQgXBLqmgeFjZzwQJeumxs0zWVTCxosHWhV +slCjesto8pN3ZAsFFFfuFFZtVHg+xFYx512HAbx8ARSBZswxb3z/tskBf/WwTV6X8FMnP+kyuzZv +eE+0LZfRJNq2rxpFhbwJqDgOCs9uVgZFp9m8vBoXqUX3tE3J1hbkjfFR1ncz0aV3Tr1PevT6LpPI +sYMQ086hmsogvDc3UbIxyExm5qpLdY8lKk3diqG2BBVKru+K2tRqtOhc4O1pusyAxX9Cp2S3jrfI +WoxdadE67/S1YXYzMt7UjWctMyq3va/hI92yOEiiFEjJNXzUbZoimJ4w30Ij/GBdVi6yz+Y0dqW6 +Ex8OSOkgrx3lZgXPRWseZOLDGKQCqKxoLnHiItBNYbZ+IQVlCZ0Vd11n65hZESrzi7aRW2mAQs6P +twII+IitTMm+ooLqOBOZr9WwpglZazrerMEKVytWNrboqFgYpYXVTYgg3+/pWeOPPv/pvzvlhROa +nJ/d5Xvjyyv21kvcqXElOWq2QGnRxM+Odri+rmGOgZSCEjavhSC1oSdpK0i9NVF1sTpcAQHlfEf1 +3WY3z9o7/XznG2ZSVZoYKGPh/x/w0Qr0gNGktqTMhoYWLwP0Vjm2Ku3ULgxy+sP3ppgQE4yg2pGv +rJqgrXzh6CNKKDFIV6oRCI3NmSPz+arYrIrmIyAbv9ZFWqdYbkdslbQZYMzaztPAHJTqVifif6xY +LRFNKhu0MHhQmrVLHeVYA1URybDHPPoRlmAjMdNlFS4vWLWbT0+2lwnPQASz+CELkQXfTNViFUsr +ZmSAy+fatX6pbgvbzma1YyKCsbdz1gqnp2PnhwdANij/prAzA4ik2LIDI4DF0oGjg7pIM8YNNwl1 +WhWH73CGow76IeCzOZz0FEuY2LlcYmuZSsWIaKWvvhzhoRuZ2DTkOs4CgFEBPiciP0CFO5eFCGa0 +xqY8Ot32j3txxUeZsXIi7sKaxBLV+j0uxMaptvbN7bSxHa0ZNv+qhuUR24cK9JFgSGR4RZlr1MKv +aoGac2vCi1I14xa5GSYGrWpA+2aH6o3t6gTuScuPOJ+TAV6vVAJv5oWPl4utk+laHxJq2diVgpy6 +G03GtkbxgJfS60QLCfJOSiELvflK6KtStENvsxtXyeF57Eoq+DT5i9bcmmwA6X0zhom6bG7mmzeH +H1oz9luzXd0Gbt8JPPNagPfR4d1HBncfHdp9dGD38WHdxwd1HxvSfXRA97Hh3McHcx8fyv3ZArmb +MC7VVVmZlPaTlQpxZ70yeT3yavEdYLhWBSlAMBBwZrEWIAUNMYM9m8EAcQzfW5gIatkJu5MV/2qz +4dp4NGujQ9/A/ioHdzTY02pustgy23SP//1qFRibRY4WydM3GdaALdMVKIh7NBX05egAO5WJ+Cbb +NJvWD7zUKNXShmZpuVEwr3Zu4lHAQSYV70KimTqTI7RNZ0r77KFWs60jC/z5plq5jSMp9nsuIlxM +SVIrQVIueXFglDZXtT80FjN1G/s1V+VwmJHYWZhHc2XpDBkqcomY5mF9hRxI92V6SRYirnz8PU5X +OWGa61cZsyo5uM2YEWSus6AmLqVr9U1JvDNdyh4V0RLp2WSo0CjXpnXDvIoyrSJ3OVZGB9L90B1Y +/eLCx59AWyO2so9CDgZGNZJr3JQ17hebF84r4IC2QPS4Oih4xd6yT44YVFNsjC02471u9XzsF4mV +YImJVyG9hpU6Zw/VaIGYLPhqnSF94Y7ZGXs7Kvxy0d3uKvewDAhZ11GEVuKvhx0qExWdLQnMTMlz +rYPoEUPbiLH5fqt22ypknAGyFoexgINYIUOFpWXtfvgCqzakN4ADqzo5Gawwnam2gS54dXJwRR3Z +CyePolD2N2HmappGH05AG9NKSp9rjRMAkbNrV2mjZRf0DdL0QVmIZGVNIUqEHIZ1kfkoEEnJGM7c +mGpyrrxlE+katvZ+IrrCPqaPIQK/XbLzQ6qRfAo7pKvEbnDz4gGG6TEb7cEmqEQnZwxhKC/02apV +Ig3gzTt/jXHotAY9Npau/RtpTE0byf7pJ7f7kIB/fR9CC0fKBoIk9vlTcDLUcB6Sd9rcvWw5bZCo +zpyEYs0EjO/7kH37iixjoCRV3A1EYZ2FGQp7aRIN7Pj2kd/XYlr23MkwJgCVFrUZnLmmkwpL5+5Y +gh2FCZX1lkooMcpxhfWMFgDfncnUfTTo9IMEmhjasOK8rqcDMLNOkvs+hFKLdlLAgJSc8KxzgFB3 +LFCQSbnZmUV38kEqGeAuhEQCFKF3DoBV0Rra2G/qCuk3AINtf2KLXmpHDc2lhMmmjXFd3ZuiMysN +lIV6Bcsm2lRpbLvvxAgy2ZCqyLqNfOgo0t9vJ5mVRrUduy4X3LiRzcXMWjn8fAHFcqqdTSDdSq0k +MQj70ep4RRyvnbYnLmACUBZxg+FIbljjNgQiP3k4JWoMTg4mpQffc8bYfJnPFTo3p925Ye3objXD +9dqeg1MQZJFhcSRtGKhTLZNmsJ1ox1C9VL4aLg4gOE2zqu0bEL02oybdljb04BJMkPjS+1hMV0qM +uwKtkQA5sWYqQ4d8slU1a3vJLgPZbDX2xefe8oNR0dnHCgVADiT7eg4dIIxCFlY/BVUIXfH3fPOc +Ul/33pk56B908YGqUokA30+cqxOs/rqhAyzhaAs7gwRomkLb/RQsr9Ox7ebjUkZXoWC87hNJ1oWS +Ukpo4Mr48gJV3RzJddL6IP1MJqGM6TMosU45MtCdJ+lCu4+CZu0LqRh9ivnQStD/WvX4fRvzVQXd +HmOFGXNtPoWpw/SYG6rxRSr3hAoWVNnPCn7N3g3FfxeMRMmosk5vVJlm2O2V3Ugafw7XyCY7W5dt +aO9pv15yFCOgmSDHts46eGL9a22OLhWnbI3SmlZxmleYwEhYDz+snXhcsKIVfYUE3HKJKWgCnRT3 +D3i9FocaQMcKW/YV2ug+Bul5mUFsbDvy8tK1VSzbjrpUiGM/1JqtagBXZnF9kUIx701jyhyj0dqZ +byajNgyTX28rszAVUdZciUIvW8evjFZm5/hz8vlNG0DHBrU4wA8YrwbzmwCq63PssQJBWJfPTpUH +Q9x+RBCTEH3Y/rSOxK5lgBc4Tyt4eiP/kOZ6DN4OKwBvlvWxbW3z4osAPxsw0GKswNVQH4/dVGJ0 +iRN8BYXxi2dd8MEqVsEC+/UJcYdENUZKSqW3oyebWTWnw9YxvI569YygghWsy3glN0f5KHl5fLDg +CrCqHMuP1xEvE9hd34psQ1dJaHSKBvr7uhNVftDD6FZmN+VV//hrmkiJOltNC9rMneg5hL0VW/T1 +nY7YyZhTxWi2RukN+1BbqMzLrd1IbUft516oE5Vil8SAByODSXEKvoKgMKQVFOewO9EmY3AFNEAE +HJMGPTsVRvopD60rk5fnmHG3WRPFf+zhiUmzzlOzLdZXuGIgUFGD6kOzgl6gQ0hKSTkxg4AlsMj5 +oxgrgdmgFn9uhlMyzojKvSSIMHXKKupoVJ7l4D0kP0XtcTrTANhVhbXL4wGz2yADiLto5PzZZo9F +iBE4aHakVtND9BHdPsnPMTecydkpkOGKxGjcUMRko/OrIOWxazAxyCqTWc2bW1VTRkloirHU3O9E +olblk9KGv5StRNPh97RrhKk7DLO+Rv5CmVuqKFJU17SXMT//+Crov2XidmTmP7VujtW0yZ3IiBxs +xjmfIKeOCeGZvMXz/7f3rc1t3NiC+zlV+g9975Zv2VtjuvFsIKnZKj6kTO51xl47mcncqSkXRdEW +xxSpJSlnnA/72/c8ADSaL1Fv2hGVyOJpAA0cnBeAg3Pqiy7xEl50Rmf/Ql3l67Jwk8+lDObYrTJd +XyltVGW28uEaH4maWhnyNTj0ronchxeWw71HodMOH0fIEOT+J2spzsdzFDAohDMmC9uFOKY23Huk +fTYRLh1Q4sB6ZSZ98Pm3wc0K9ZM3wWkvOucIvtfMUbIaV7I5iBBpqErEU67oXms5kF0AsqMW6SeV +iWGpq7A952wqHEJcoDJSMvp0Bk98SiMnMmUWvOMrVx9PlVEuVVnmjhRKBvfh6utuqDf4HBEFbPS0 +8mEDlo52TXSCC959uIulq8zFqD5rrfdJtYobafFsMt6r4224KtueY1oiuE5nZlpWMi6BTLqEx9H0 +q5A/LCmjEOIiJg9kXg1ZD1EbRbFiyRZhbeRrYqzCAQFtxkVSqKKKs+wxH8SiiSc/zb0ZusTAq84q +hi4ohQk2gY/GGhYM2iWzaRAqGBxPXah6FY7zU+QDF4ODOY6+U1vzNioio1NP2RNSk/8kw1xwy7e8 +T1NXD6fGvr7c6MLJPJmMVYLxlhuuREW2FmHXL44h433qqguZJGPYCTQH+C4chkCqr4KjZOabo+gv +GPMA2CDCYyAnhpXB54PdRNIOLW8wWroW4uKJRylEcOCLqeXxxg0fKarM8ZTAdOpNV9HiURDd6XYM +TMmo07V5PKKSmQ4MuhGjh6R3hehCquRzpzgqF5QQxYqqG+CDdHTAi2fmhlmSr77WqqK0vN3meR2x +Rgth2piPUVsEt2kV/ArqPOOeUIFnWtE7UcdlHS7AovhScYGACiezwdLlMzz+qUT03ggbbooz7UXd +EjbhhMq1SHR1FxzQJqgcz3d1y3qXUgZqRj1EIdFqTcgXpNGzqPLxWm5Y6TX1kDc88eHAoN7fi66b +6dAVd25jiLuws4VSmW0HETxV6gUNe+ZjkCwRy/I+DUURV8m8jiHnTEP8yXA/Gm01VaYjzxA9kU5X +ky1eiqBZSJ7UmlRKE9WTT14xLJBo9ZQBXbyT4l22tOUbeOTkrdMmZ2nL4F+SdjlF2J+vQl+zVZ1h +SWe1j/qGNyNIJLraqUZHq53shnpVKdjNxaabGxRwMa4daPESdZuPJ+q1r23ctAmbbiZqTR833Cpp +oj0RW8UVjcx3itPyJ9x9Jy2kosqqz0ErOtzkgvW6UoW7pKSFwkX3tBvBayIXVVNw/CZNajIhFG4h +4oDT9p4xETMxLyueJ5IYRTTKbFln2YrgZWgUN+S8xlMWO2BxhREubek6mATDg699Fdy2CajCxa9k +itt0C0FwjOHUQoi2j55pQkWRqdmlXtemng1Bh5uZzOqgxnwpr4yGuxHRKkuHJxWvielQiFy5ki4x +KTN6kpk2OSGIGFYk6Re6jJqObT1dnQ7RC2Xc09VxvwxD7caAkXh0WIWk96WoFyQ6XvXHyHZVHXgs +XHYumbkZyHFk6FqO1VkEAZkiZRBVBSCnopc6RMFjmA/7PKIOZ4bOJDGWVXw9b6eQI7ix0e1Q85kD +Xrt3PotXTYt6PmGJbmQ6nq1FbwMmeo5ERrqIL5MtqSKZlkNrvE65iev7nAbr79oepw== + + + of71/U0D/AbepozvG/iaRvD1PU2DoLqBn2mAX9vLNMBv4GMacX5tD9Nop1zbvzQol+t7l3LhG/iW +Btvl+p6lwVC6vl9pAN/Aq5ThN/EpDSO+vkcpk9JN/EkD/AbepAF+fV/Se/Mkvfs8KeYu86SkvCeX +5ElZ/mCvNudJCc6zDg8XMSWKWI5B9wYjbTavG//XmpwpFFFThvkm869Ox8frWFVyHJhomcrgGJEk +jWFfIF58oeXSTWqPg2Zkiy+KIeVDZKi47nDsYcSHekb5TFQpFTwmZAzLZDlcEa29tA67SSZe/cWw +NDr37AIpFcLSGFFrjGTR+BDACZfyIeiW4PBpaRAsyOnmnXPRDdaEo0mR3dZ07CdDgS5cdpQSMlcI +CvwQ0chOJxgUptZ6IbsLRqnwafeLeqbC/UOyO4PAjjnmk7OCDw4IBDS1YwJYDxx1nFLa8yKF8rOH +PU8fs7dVVoUg5Mqlg1xUi1YH95CUHRDDALHvokkxz+lIxIc4gJQSPrSA1nmMfRKv6NN+Cm/olGFn +k4LllTFwSr3ocGh/VUG0pzQtVXRrIJ8Tk2Jb8p4UBWM2mcXtRDB0yMINeOVVLSWu9RGvrF5pNlQW +NUx5HoFhZHK3BB8mUZSTAMQwBj6E46U0CQEHVfBFw1Vg0JrB14+OZnSKIFGyiUJxd10K5lhlO8Eh +2QVGKWBeQp1pRMpU6D3v6un8VBN1sObVNsJdjLJWBvfPKsaJIXSruNdHBz41HbGbH97JVSH0og8O +tlg4bqMiKem0iZjFsfC85iO4iH6SJh3DlnUwgBRJGvcbK52tP/mCLjlh2GTMU/yLcKM6JRzg9RT5 +q7qanXSLjS1ySDVxz1SmrBHhfJocK6qYx8GlmJB4s1xVYd/DcbYmulwf9j1U3IqkhCFhpWp4p5V6 +QHGDOC8mLkDjHfQY6pWIoQwhw2g4wZVXS5dFA3AiXr/WJl7lp/1el+W4wvAtwY8F7fd0ukIZTjia +QB3EHfMDsFHlU8ggPGynZTFlnCrr7LJoV3HKA9GqQug3kwJ1k+qIMV1CLMOSt+6Tc4qtOB5+Vfsk +GD4yY3/ouByRKYZouGbQjRwdpGLpo8VKcXhCRCYdHRU4OE8wAetFOILD1iKFuDAxlrLlt1FgJZuy +kMoIpI3qbiQEG2Jg2pQtFgM4sMemYXce7KuP5hcG1sTtiW48WfWcycfH2CecKM+GGynpkodKtqLk +q+ZpGmJhVbs1VLgKieHNXDrtJBLm69+qRiPF0Qh604kY/Y5uY6B6DLEFKR5dCPlhecsi9ACDDcTt +0Urb6FXlgpOOS6GmMAigc9Ge8GVylRK8VGZfSRujxAkZYo4AHiIlCT5EVjKzgikoHr9M6bQQ92lT +WwOn2DqPDL/IsitEN9KiscHBxps6erYKYQXJ5Sq4GFfhZJZ2phIpc7opXdbOk3h9KERjMTEhiA+7 +nRyI0WcnMyHKrTYc04SBZUlo1RXTDss+jv6L99/z7SQdz3C1TaFJ8WSYiVPXQWlQT3FsAeiYz874 +0l0GLWq5TF508RBApajNS9YitHB8EOIg6+XINii8bQybJmyWkT2EmkakBg8G3AR24eAmHmZhQA8v +ww4axWUNqsiwlziZHylCQQwkgJEiYvoFEQKhkfypRLYnHiLtIVyU6X4U+4aVYbMq6IuUwTb3ddYx +ORtRcNw6BsMyxH+hjYtgALJRJJn5k0lhmB4oVkzAASonGSMmy5jitInDQUh1QFfGYn4nj9GmEnZZ +CpKKC+eKmNWulEGbxeS8mPsmRn/J7k2RwWhFVIfBb1anaGiu9rA1HJHPpRRKoQXUkT5os3gHhU6Y +VWiBwsAy0PCyvyK1mozmeEKNN6iCKyxe0wgjiDtQdMwQNgiEq2N7oPCN5pKPVjtKlZh0KrrCpIgf +dGJp05kHbk04He6kUQ5Htq1siO9V751UHLCFt5mNUbXFxl5+bFrFmGHBxQYxEK61kO9XwABZfLS0 +ZiEQMvUJjhKd7l4FnYzwOuYHhWHhQ6K4pglUzKEfM2+UOgNLCNLPzbJfNF151DodEVc+3oPUMvNL +ciGTtIpbOBRap3JhUQGCKypPHYJKh/VTN5owfJ2ING0dFqouXNnks9VEw2BLJC3Jbtrs+o9b4Mkf +JiT/wyt3Jh0QAK8F58x0tEd7+zFilrFZ+g8hw4W3dIBu0n6xy3c0gxMShg1Od0JpfypECK7qXCFJ +p1S8uRTlbrpzJ33uX842k3Lx/BcdAF306aHN+SBwOB8herPWZwZlDOdKCiyIBfQ1JOlCdxF1dC9n +Z0UEZlIXD9ziVT66ohhHQBILMe5qR7/mNAxWAvHvFH3/r6fD4Xhw2h/NivZgMJzPV+Pwh2wiIRo/ +bhKQ92VFexxXvU9sXVzn0aIhpR3J4CrYuxgLLmzbUpQkE0PXCVdlsGDyo+2hMnBIKejD9dCsCcrD +GC7axXflsNAvbjfB2aaxLsvlWEZX5JAOMr2M5l9qWWQdS7AgvMIwEjiknotDzpqocVO/K4eFfnU3 +4PclEsZFTAtSfOBNK9zTog0/nDMgDPPuaDQefhv+Jhp5058vhjOgEdzq++X7g2/+Hiaaw3QSW1fF +PwpY7APTwAyfbiyCIC7Gv12Bhoxw/AB+cBvuCb2111/0vy0E2Inq4Jtffti0Objj50rVO0fL/6bq +naP1VW7x7b+H6qsY3vTvCuavNgN7OPb7rb47ppf/fcT8FT5NHD1i/u6qb0ffI+Zvv/pu6HvE/O1V +vxr6bhvzN+z8F1n9eui7LczfsPNfXvUt/H4PmP+iUXfN6jtI2jvE/A07/0VWv4KOuwPM37DzX2T1 +a1gXt4D5W+r8F139fjB/R53/oqvfAeav8PbNn6+3+g3WMruJjj0e+8NUv4VV5G4iZA/H/jDVH9fv +9139Ftfvj7bNlao/Yv5eq9/C+v0R81f63GAVeT+Y3/3zhWD+GlR3v5i/+mfPMH+L/H4/mL/+5/e7 +T3uNtzc/XxDm71fH3QLmt3/2GPOP1sV9Vd8P6+Krl/N7M/avHvN7O/avFvN7P/avBvN3MPbNTX+h +mOfPbWH+Fse+/PnqaJ4/18L83Yz98rfd5dvvAfPNz0OtZa7w9t8z5vdj3m+h+sNg/hqdf9i3X/75 +wmzaHTp/C2/f7fP7wvwWSXuLb9/tc1eY3085vwbzt/j2q32+gNXEHUib23379T57uJq4Bw37xWL+ +Fvj9fjC/ueM3fvvjycjaR5d3/MZv/+JORppN3zW/38+8X+/zUOdxNxj7Uucvf8tDcdx+8Pv6z067 +RpdU3/Z5WC2z9xx3h9W/OszXn0fMX6vqzm/f/HnE/LWqbnz77p9HzF+r6k6d3/7Z8+r7hfkrdn77 +Z8+rPwzmb6nzX1X135N1cb3qIvzc8ttFqcqq7MFPBX+JW+28xHDw0iinnDQC37MmX8Lm6ps/suxI +oZV1zjtvnVZSlt1S3UrnRVlJYYwvO76neqrT9sK0pYP2b9x5UR6qrut0u4edI3tkDzs96Q+Nl/DK +m2JeQnWhdKddHZqj9tEh/HSPRK90XdUtD29KNoBsU7YPodu9kNGic2jaVneEZKxcv/PUNFTf1vr1 +Oy8DTuwRJuXYgJPrdZ4ns9fDiTuS0H7VnM9d21n/dqbCTlv3uoe9Xq/T3USF1+k8MIs8rGSn2yPM +O3ukNXPQVVta/3YtvKnatiMqpZTQm/n+6p0HctFH/rCtTU+QhrW7Y/rytyO5tL1vQ99lVbrtTV+t +80guPdfuSNdWPaS+W5W0onSysm3sO7CNLnUpGz8riuMqb1cwnaYt2tJ0pBVWaKFR2ujwI2E0djdG +Xfd2mtG26GinTVcf6cP009NOGeFWp3hnNUHcL7rdzlHb+UPf9R38gerwT9sd2Y4SQPVXJKD4dlke +qUN31O32RAd4M7Z+WdOXdZ4UsihlF/SD7jhAQSfDSg+qb0LLJR/UxqQmjmQleyBbZFuZnqx4Rneb +zE2dVyBRoLZpQ2ehw8CgpalEpzRNKsTqV+s0Nowxtp3vOKQ6I03bg0627csZ9LLOY9vedL3ulNBa +pbVuuw4x6KHAp00WQtRt4qalj6ROQ8PtQ++sV0dSSJw422l3/JFBYyjHef2jAPsbhGXsPCoGaRy1 +bWD6elAJeBMYVHfQzOo0WKhBNl51oOnOxtlVwC4w+k7pHTTswSRUBGv7LlTvlh3VoHL86dJPDyge +E1Vs0ns0705aW7Ur0DYd2aO2WShWVQUTWkIj3UbDPRiVbtv2UQcxDwMGbl6roLCL2gGzuEMM5B7K +iNIKryrt9SGOvYEOUxpnMdb1kdPtXruy8OcaYkJUG1uhiuy2D5dUggQ2ORRyaQKN6ChlgHVNBfMv +YUbo7XpN11khHHbLNua3rBrPkcBWqE5CkSOFKbOlBZq1h223oess90D80NvVYXl0qXgWZU85J9tg +nuojI90Rdl2TnF/uOgps4G/ASPcyHqyJNqknI5W3Huig7nrdADUNM4/avVea3eS8ET3TayvfBWFT +aQuUgF0HFsPqHt5gwhuupN2589zxDvYc9CrIBiBhB9Knp6DzwMY6SOGmdid0X9Z5VB+pihAwciRi +B5LIWWvaUF0eAZuIDH1tsC7FEqms+yiBRGsEYBIYiLDsifsOu6Zj2yAm1JGIee9Yu+vmdG7ufN2X +XugLiw0P0uHQ+0oqU/ZqOZ9I0WPuYr216yrggPg94hGZsNSHtmfBTFCV8EnvsQHe7vTaR5lI2dB5 +VYKohIlEloGJC4JKgugEHSCR/5Ley5eB3gM/eJ/E4aqIwIbhOZQrXRtlFFaPo0QhgR1WNJD6ExWE +SUJcA+ZVVJElsb8qndCgqHtUTIPakEvydaN1kTQbTontgICpYIRHxAuuPBIVZk6zHe+o4W69rtiF +42LjoGraR0BXXWDpQ3gBmBIobYAsbNuBcAI9gm373dcVzc67zmEXJGjbOCBNA5MHjHfYBoZpVw6A +1Gm1Wv3yzmOurDZYKqorQPrCWoIaRY7zh65tLayFxNUXQ3XnhQKU2K5DIVmScgQuNEL1tm2C7NJ5 +nH+aPNXTbVJlbdXFnNAlLYWqNQR6pc4HqgO9ppI54laI95qdL8uGXsvl/hUWI1D0yeHkBIP3H3zz +y58OOI0AQGISgaODC0pC8IYTbeLPSq5MzLXldPHrAac6KUOOLMc54s9iXhRLGUXKquWVMcU4JjCs +lA/pzigh1Djmw6P84JjCkDLajGO+RGl8yIMIlo5C+NtGpovQL8xvgWm1FHULk5RYzpElfctjMo6U +MibCMSddSOztMZW0Drm/hC1iMi5Rg1K6Oe99s6DhpNV5izkwvD4lCQtwJVtS6ZhljBtVmvOs5K+P +sJRtJvS0LpuNqW50DQI4PRVhDpNclSJNIKjMkOuX8padcVddmEBRcootzhTH2Qwxg5wBWbgEFC3t +Y96gGm4oLZeNyf04rzpm/JOVT/hXnPo6AFNqKlTmzcKYHUlUutFsDWz2IYfLkFKN0g== + + + ZboqpNdKKbeqlK9Ktxym/Owioa1P61sWL36YLIqnmKalGEzPzqcXk5Nijrl7i7PpyVLO3ga3iJay +lDxHVJy67SzmkzGc5SzCic4baWLW/fnk3QX0cRMb4pO1jEgP1rIiPVnHjPxgHTs+eYd4YpZE3Lzi +fxJbwpfImNyhday5/OTKzMlYuAl7cgs3YdCI75uw6JN3xweIPsZmYtQ4yausyk9uxKzUxA3Zlcd+ +M4ZlsrwRyzIx3pxpn7xLbMsIXse4POZ1rMvd+BkU1dOfJ5P+2fCkqKo1jLwu9ROp43d/nk5ez0aT +xWjy4fnzgyzbT/7k4Js/n9Mzx89ejy/g96vjfw4Hi5QLvDO7mJ8WP/Yn/Q/DWfFqdjKcPbvsYcFP +u/3xePRh1j8/HQ1C0Z+m0/GLQhXni+INYvDFlqLPCuj5U6pgscLRuL8otlWgojA9UPbVp/44L8pt +ra8gY4XLG5cGynJb3P/Lq5gy9j0WfTvoL8BYolLcVizbAURO+sXLYf/9usKx2Jv+yagPxPh20Z9l +5bitldJ/ujjrT4qj4XBtB2Kpo/FnTCHfgWLj4YuC29pc/IfJx+LtOcG3tYrFetzWbHoeSwJ7vZpw +jvms7OvhZDAaby/TDfjqzwbT/iVljy5OhltLhHnsAYtDP7c39n1/3P/X581lAq1CybeD2XQ8xtEU +f+nPRv3j8RAmdPJhcRprvyY8Tda8BTj3+SK09Ry+FL3+/BSY/+1iNv04vLz+q/7HpULc1jpsT8ef +J8M50NHlzXbH/fl8NOC2arRvrvC2fzaFhp8VrSBeYCxN4XIHgmqV/lAUZSyFX0XxIkpULhcGUQjg +1AIsDfgfVL02mDwN1npGe2BxMEVairOpIVwFyhFpWSOMb2ECw+eYR9BXkh9sH//Vx9Lg0e2j0Twc +A4pN0R9WV6XFjH5KKDC8eEygI0HL5qOBGgXoKswH+Vy0oAb8kvTFwSjxfyx12wOrRVQY1Z+Hv6ax +2JLGQj8vitCDDPdl4em/8i56RgIMRNdWbFehg5jr2EtKmVj/+YLR6gN+LWNbA2KtYCxbnBcgHrRs +RAF23J3gOJPYS4MxjFXuqEU690TALW3Dr+I5EQb0ktL5lYEcsJNEOrfe2VzDLfVWSKZdiSa5jugN +2JX8B3Y3QCONXNLF2xZGG8wBGksyUHhk8APEYeg/VdL/cpcuX/f1tbnD7wderwpt8D98612+m8yn +YDiFwZeFhjGX/P9dv7+2OyPqTXo3ErS829fXpiC/HkZuy5g0E/7biVKv+e7agg7vLhwiX0TpudO4 +b5tL1tla2L1uMPAC6xeR99WLIv6wxCJuZ3VwQ9Rt6kqwDpd7IvOeoCIFaS/vpUNo1i73xt8/Xtgg +Xu6IEPffE143xJ7klsND9Gaz+b+uhzKjo9rGKdRVennbTLnJrCfG5JXAKmc2DKINYJqPlSdh1ZrP +F+puS4Zq06bSXgvheBrL25nGbYPl1djqOmzr2NGaerHxIRov2RMee/5crVDqjRXStiHCgnEt4+gX +yxCTTQ1PA6yD4upClLjQCMbgfU1PvYLdPiF+y3SU9ahkvbCrYLFEtjB+qnsbEK+atw9GbnqgVx/U ++0GTqDkNGfS4vm2sc2n6rjzO6wgez89Aer5dfB4P5wffvPivyfTXCX3Dndan4jmapxeL+ehkGBkO +FoQwMtxhfdEeLEafhqn4i27Yij0ajXEZ8S1bD6NJwUUY/IwFayjzh/XVYK0x+Hj1aru8rdMHoZnV +gT/Hl1TJ959h+NPFm+FgOjuB6cWn2EDAQbFyjtk4bC2L/4S//gmwX8Hm+7H4+z/K4uQAnr3hkr+c +4MuG74vvioNviqepYdrPhi51gDiLpz/Ph4efhpNXJycE/66g/hXfQZUXr/uzxdpRdsbDycmNhkkt +1OMsdxxXNp66hc0d3z4KJsHtw5D0ZfxqFgpfPjIuWA8tnZeL1fNyAUMVMFS5ZqhYbmkKs6avMFnd +6eTkYrTYNMIrIOzWpz0KpNufdqhz+K/h4AL7wg+piVWh1BlfDIvvp9P9kUQPQ6a7S5YHIMt7EbNX +la2d41o4d05xDtKRHizUT0bDyaIw5hluWSlRSvxXeumK50a2cPNZtITXVXgt/+58wCY7ndsS3NuR +yHYL7oEWb0/7J9Nfn1E3MiQ+zR62+qNzYBK2FaDIMLLL00YLL34aLcY7ECAYX2+GfRjH6XT227MG +5NNwtiCICCezx+PJSbPI8fhixkXKMsJO+rOPsRpDpuf9QYQw0s77o9kVaJQxxLta3elsMpzNV3HU +eLwZS0ut7IonYeJokKbwWPHhtPSuHHKH4rrb5zI/9c/3yHh8OMuiVdKCjaZmxbyIc2TjHAlZ3IWF +8fCGVKLGcl8sqbtWWTfQ13emUL5GgfOn6WT4eTA9Oy7ejsYf90fk3NJ6lTXcq/fv58MF7jicruq3 +7OFm7dZoYVfd9lwmTf1+zipfR8jZeHT2LAgOMgL+OVmc76VMakk8WJV6uwxeR7bXFUx7M3IdXBBK +4/FsWeNvZazfQRU9uHze2w2fWuQ8C+ouO+sGHV6vF/5RnH+9m0LuDqX/F7CyXLeaFPIZHZugJwct +I4U26Mjh0Vn44daRX6Paf33anyz687P+h+kM/eP2Re0/bg59QZL8VvaU/jKajsGyOvw8pK0kU/r0 +jzYtaYDzW7qs/J0KgLvmeSHuR9p/3aSyqjCIZEpbWdp9NHhpwuMxb4leirhz8EUTzV1qii/TRHhW +xC2SR3PgNs2BNyAjTnCbu/vj3/7r0Rp4tAbuVcQLaVvGC1xqK+nlRnEv/f3w/12zvHk0Bu7AGJDV +I3XsldZ/2u2fTS/ej/sfhnu90/M7VPcX88VogK6++6Prb0la7c9Z3Z1uBYdzjYvFeDSpnQ2vd7Sx +1MiupxtXdDH4cIrUtsa5AB9sdSvgmrt2S8UTlvnot2HzzOVk0R9H8RB8DpDiJsP5vOlY0T+eT8cX +i2F6khqF0f12XUnyeLz6+5O0bwez0fHx+HNx1P/1LoTtg7ObWWE3Ua7jNyaS+Rmen15ReAQcDos+ +kMdPvw77H1cHtlpm8xhT2f+IrV15sMmpy6xz6uKx9ieD0yZkNFn6Po9dacKnF4stSPqi1tLsw1NW +eEdB0kUFOlEt8URno+bUd6k579lA2HJkXu3NWfE9LPlapazosgpfiDJOq3BF6iE9/3+HCmk0BlFV +vAGxM71XhfRFuJjekmzdfqd5ZfgbCm5GxGqFHBu3Kb1acoucLluA2mvJsPxCeYGvx+ggT3uj+fm4 +/5m/UrkX3786/ucbaObbolHlMgy/yK98QR+eBiRd0fL4GmZw2/Tpx+nb3+lrefQ0K1uVFmQ9GYc3 +V4VSatuUVl/rlO6TQfO4er4nY2X6fgEkNV/U12/2ZLfy8WTyYVYR3mpcPngjyRe3knRoiMCHvD+8 +xydtvEm9T5erWVEczYbDAtTLYor7JssKOX+6WQs329h5OVC6tGc1G5Ssg5TUOfATb8i4MgOKdSVF +KNloU3JJaWQOXNemWldScUkvW6YSqd2T+SL0VSrfElrJ/Elo3CvgCSGyJ2JjndWuA3C16whc6ToA +V7uOwE9XIITXb9sn/XP49u6c5vbd98fjN6u08H3/Yo6xMorO+GLWcsfv1xNDo9gVqCHS8ocpj0eH ++xgn/UX/bdzTfNEZxfrtt90ffnCmB22cUPtP/g0+//7dD/88/fhb2w1+/nfzf7qDPgL/7f/9b8QF +NfWAbmQUT+7uT5R/h+bJoj8rOhczvNtzTxspbyls8+H792BFr9lIocf8dMv+9ylfLt2RQ54egkl/ +Ph9uXRbEW0yh7T9kZ2ztcJjG0tNm4L+OTsJxQAP8p+How+mi2cib4bgunUOzwj6CeYfozT1t9tzI +Rrr3m7SwQKRVpeN7tfezB3+rLPDTrD+Zv5/OzlbJPz0qDvuDLUfeWRO7ckGyeRaxbohfNG+S5Nn0 +0/BP714v1oD/koOJWyYXZ93p+Wg4j+fUBD0fTV5PR5PEAfxeeO3J9CwqpOwEe9FfDN/1hh/AGJqv +fcYhScOzVn1gN+iPoatH/QHYT3yYVS49ez2cDYbLHaFnL0eT4foW/7Klxb+sb3E2fD8GifXLWujf +rmxavr6YfKRzwM542l9jXL6+GHyEP1OJzXQSSv5HbGnni59OtcqyrC2jd+9rnOw2lDtZC7RkWZEM +kAYtgr05eHmUD4/y4VE+XEk+PNJ6onW7jdhFq9SV3ELxYjO9Z8F3rkDwYjO5Lzd41/R+N0rEWiK2 +R+3x1XKU2qo+WkbW67VHHfLl6pC72W/+emXDQ4WRScR/+2FkeGD/PfrwW//D6pgAXvx3/8Pm8YQC +VxJ06zyvE3jF8zrRN94lCUxdq/PhuF2DRS2URicfhlcJJfdVnrz8zndn8/xzj8fGv9tj43301XjQ +yKRpfZKc2BNkc2TSVCRFJq2SVkqBScn76PLYpHcnLOeD8azR/8F8Nni4kzcei3xYMfh3gPcvxot/ +5FLw7ejsfFxLwdVA7DsFo1x7RBAm5TXI0EWjYxRD/3BykkXQvzwU/2uw6GEhxL15fcwvwJ+nf38D +z+ewXkIM/APn6Zc5DncJ/HrQGNnTv56O8CiqBhPVAdZBeDdKtxw9cOWTYs1DSw/t+oeaHur1DyU9 +lMsPRbSbn74BUvrxj7hV8Df8nWq3yH++Chu3TyvzpOCiAPob/KoLmnDi+5Hc+mIxgw2arD3ynZGx +oEztSWxPxvZaMfwqFvoeVoGTovtH1+xcyxblct9iUVvmvWtRrqhG72JB3ehfSxblcvdiSVlmHayP +t3keL4ZQArH3Y9YYoU5VdTnsYSgL0B//qKpW6mJCS93HUNSUhJ7URcogkhWVdasSWxWy1ZiWiMZX +sNz+MIxz0phktTrLqTR2cmmq5fJcp8I0i/l0i9X5ToWxo41Jx6I+jSvEaAoI8Amt3Fm7hNdUmvr7 +4x9thlvqg24iN5UnnMHDWDj0eAnBqTh1GgZaI5loNZZt/3YxGxKtNqg062gsYcsGdWZdiyV0kyyz +3sQSssZ0mua/Dcdj1MyJ/Zvzuvo4n8jVp42pyx+HYDkk2v4QxUqUbutDISwVjq1ESRliLNDTPxRU +lnP3ji9teG2drJfd6fl51KtbmonFspoYpOYYx3xJ1VRuw6jyiGOXNJUXzXryE9hdmEuqeHsxgfX8 +pc2slMe2nv44PAEczYAHh/1J8RMYdvOd4iSsr0hNvv4865+NTnZspy5Nla8WlzMvTtX/82LyYUzX +yEfnu45kuQ41xCz1BmyBHVtpVKAmrhh5olEeG3jdqY2TZIJcLUHQS7BCGubXwXKYpYOlcO9Nj6KD +5btaB8u3iQ9WojcfZPk+Dta4Tx+sT1J0sBIP8qARI2LVduPBXTOTkij5Iad+x6b+R+z4T6CPaBQX +dCsWMTSbzufFn/qLwSknEgYTdk5p/IacYJUeoVfS20UYy0v0CDq+GB/jlx9h9p4fDQ== + + + z/rcHJulvf4xfwERU7yEkWO+aUTY8P9eTEf9ZyQfh8Px4BTWLEV7MMDdqNj3lLQ+9Pzaiex4Qff9 +bHpx/sPk/fQgy7R1WtAyYJ7uVfDXgqsA9OXoUwTS8vDyJhdrk3cVzQIxA1d8TcoVuMtL1iYWLOqH +N2p848WSzc/Ti7Zd77nktWuS/BZrH6WXrdbY/h5EwHsQC1Dl7QWtTeKIwhZTEXzqqORRVnKX/oP0 +wQOrGucEPZx8Go6n58ManiB4YvHX/ux8J+QQG4zmZzVOMkj6e5emgK9nWXfoa/y3rr+Jz4Lo7U0H +F2fDyaLXX/QB/u5FBOAaF79mS3cC/PLjyz+jFy99e/o/T0LxzNPxX2fjCZR4jr9wO5HW5E/erS/w +qQ8yLJTwYQcif774fB4fv2iD+l7fjbPhos8ewzfvhbh2Lz6FFKBvh3iquCc92Y+O3Dc+vqtLgaYb +n8yGk1hqmaKzoiCFwFi4WIRzEHz2h3WD+nbex70g5JkHmOsrjG2p41hth94+/Y/J/N0AbJnp2Xcb +Suddlw8wLXEo66aHHn37acdxAoXO93uU335qArZR6vVpA/AAtPxnws6liDsGlQoFxL7iLR/MOhIZ +Twcfhyc7DHQCi4V9HWQcxN3TxlXkxv7z0+4YW0LD/P2vD6tN5+PR4OtSpTSit9OL2WDYQcN9jwe3 +zBOX91T4dL1mv7hgvVD8fPmIlFQtqbXYy2F9Xj+sX/kO1OWTJVuVMfs5Y7+me1wrwzsNl7m+6PGd +1jfSVgZ4PF2AIfpy+H7xajaipe6lQ43H53s1xtVx7JfiBu32tejt21VZtzeMbLeEQNYYZQI+2z/4 +oj9bHE/7s5NiMB1PZ4UoZsm+u7QoOhtPdi18XM+nkVq6zWVl1odLi+Z9uLTw8arCXi23RHRYgNy9 +z/swC4PP8MbRSZHCaD55lxyOsOQ57VXPR2cXY3JtiEqsvlGApV5dLM4vFsWb/nwxnI1+o5LFmyH5 +VNaVhGlU+nE4P72sygp1xCmBkcWBVXFkJ+ej1vIY+uPRfBl21p9/jONIvpvn/ZNsHdD+oWhfLKap +ewnLZZnQKMri/Rg3XSeAoRkVfP5piL7QxXF/3J8M1iC0UWcaIiAvhv9a7Fh0TicnKyNaKj0Yj85h +7nF/5V9Aex8AgZdVOZ8N58PZp2Ex/TScneM2Z81zL3JXo6U5WXFFylQHTvJkWrdYjCbUq+l8tFgW +hW//8v3RdLJ4e3E8Hy4W8Xp3Tdbh+cvpICfD7Onh2fHwhKcrzm398PVsOBjN63rZWw8ng+lJ/T5d +P6ETp59qsZzGBc9o9xjXxsBFg3UFfhoC9vuLdY9ef3i/PBkA/aV/vqbsW7Dt6859twbbmYfT0j70 +EzwxGi4u+NwnnAm97H8ezmp3pngeiXmuQNTw/UyD0JfHeKSFpTHd0ctJUEyLddry5x96GJeLSr+D +0t8xeb2D4vDoWd3Rd3g03cZfv/x68M3FAYqR9mydI9jljl+CHb9gfWCELc4OvlFesHWG38fZ92Rx +j7n88vdQPvvz/cH/umg4aknhWqKyrtBKt5wBdJ3lQCtb0oO6kEa2nPO20E63jDa6kN60rM0AA+iY +ci3t4f0JqCqFd2TrhhIgvg6rRVhZYYZQV6R2lDPQEeHT2xJgQJFSuE91qdTv2NLq8AbrxkyYEUUP +h2BaxkroqIdCJfQYJ0BJaK700K5oKY2vlA4GaBGiW0ppQr1zlgdRGugqDkzKlrJOEtDrSkExTK+l +DUBcy9MQoTPSaSzjW1YKwYiEEXmrCi0M9BDmTmkLCIQ515jbBTqUQQBblZKMygQ0DrohK24fY+zA +64FqPODEKXhRBkCUWNGygPYaOOYYN6WtoKS1LWiiKiSMspI46wbKW5MBcvwmIIy/sgrqKSgO44Dx +AOliejEgU8CzRgQC4kRpqKKzLS+xayX2ouJewNpEWlnVQOltSzhvCKIUDgkmy5oSK8JMaS8JFyWm +LBOKZs3iHwrKw1iQPmAaEPllICtfQf8UT1ppoYsGgRHTMFfKOcCl10CXJUBE2dKqRAjiQfOkCd8y +HoSNgh47AZOMVFJWBsoD+ZZQrlglr8E6miN6LJEepUGCgWcaqL0SgvnTEDoRiNQHfDZmYOVLBmoF +PI8QoDrHEEAssbEotakhhHWgH4NTEYHYmsO5d3ldgCgnGSIBczlEtbyw3FgGq0pLY0EEljIMwhhE +CHKGAIRoJFjhqwwC5Gyk0omBGFi2nAT2qpuS2C9RZb2QRA262Q0ACqgZxxSAMEHWcV0eJUAsMGZR +IyNCgqRhtEVgwDdjN9VNM4AQg+2niYqcMMinFIagUGZga7oCyVKqTcBsFACUrrLZKABSSpP1WQJW +iVgaowCW84DN5igAaAVYmlld6IAJfQ7tA6RUsu5GaI2BYfJDY1w1kUhqPpFR6kVOgqm/OQmmYdV1 +49Dr9iOGMhKsYYFlxuv4aBMQVOTPSLJAKwqkMchvkBlAIqgHJOZCBPmUgEjcUmCKXVcDESKtswSR +KEwJIkKZ0pSOibsE+WLxFcjFkhvLYGVVssaQEuhcWRwhaQwPohawnCADZjHQuL4GBr5TymZAhIjK +c2uuxD7mEAuMx62B/tSgf5QBmSYMmx05UAuJrVXAzjAahIDctASpcgCNE1SD9KIG0kANxk+zWVWA +6NJw86WvKoIog3IRlJkDcGzNorIHQmsJ6z23loBAXaVDAYOk6DRBoJQkDe29kDUk6IjSIBoikAaK +QWIRW6kuQLSTOmu/xIlCSRa7Qa0BoQrUDxUQqpDcNwRa7BsAdaURSbpVVagNqqB2UA8J0Ow1hEYa +tUcEjhmoyOhJdSXqPqGz9tE48c7W3aDWwAQRjgwwslzGTZh0JJah0TKYaWVlGSIVWi4RQpquBM1a +yRo4Zo6hfsWa8N2VaIFUsuUrVJY5BERcmAEUwV4Ra1TI06GtEkw0AppKc2uiUjmXrXDoYB3bEkej +0Cl9Xpu0KBCcMbZRFoGV9aYGSmNbpRKq5mYs4yvfYGaEgRWicmZuwIiZJZKP07pmSISAgKwazCw1 +aDJizoyZEVh6ZKNUVwNitfA1MzcgkZkRiMZrzss5jFgZAQqJKLIjAjTNWsbKEpsgislYGYGg9TKg +tEAf6MWeWJkggtilZmWsqB1KxYyVCai0rVkNIUKWGTtKg0pa+QYrS7CinMR5ylgZgaasMiBCJKZB +r9tHCM1nxspo+4Ilahus3AASqyHEKJexI0I8ibGMlcF+hVFXvsHKEuZIGJEBEaKFytsHCKgD1WBl +bI0M/pyXEWgxC0hiZoQoa6uaJaWVDT5OujjnYwRWUmYlk62eOLkBiZyMBOrQXM4YOYcRHyPAqypj +rxXWDB1rApmNoUeiREoAbMDiRhEbO1of4DvCAmrMQCBnT0BjHRp2iI2KixEbIERXpFkDZMAVTWWr +ZjHrhGw2VSnl6zdiRY9oC3NHfRszEAzOQB4gnAqEeGcy2Y9L2xXZnxY0DYIBoLfa5XWRIG1OMD7K +yZxgPNJ8JZqMVgMjI2DfQHpmzOJxnq1uMhoYzbiEbfCZi3I3VY2mdd28Qz5Gasv5DBdQCscEuJTI +0+MlIIsngBjpXTYtAAHqs83Z82R5iWYxKUxoykpPEGGVqCE0JjTdBdtUxD1jBoIZx0CykRAC3VAM +gQERBLohakhoLbwiKwYiUuRNYdRlZes3YkVcfbsy6+04AGU+AgCAdM2RgYKgIh2VIaNCaaJFsxgl +9a7xmkMI/VQR7R9k0pxcKrR9RWYCIQSoLCMOhJRWNanFInmLpoUlLfJFlZOLRUozefM2asacXFAe +eDIhMrGMwkVrn4tN0DLGNUQrcopZ4rIqsnbOZdWyrEaI90ZkXLwiiAK+m8C04Ra2llCz2cy4OmMg +kEJmXyFESJWZTRkgWU0KNymsbRroCBQq0+oIcZXITG+lcFHlVNNChxWTwN2fhoWuXVghpLoGJxz3 +GUGbgwHsCGIc4hn3j0pee4NVDFNDeg3oqFK0zkSgloI1BhnQBlnV56amhqHopoZaxdl4AzDslyiF +fXSZaXDGwDISV1gMRFO0XjDEVVVu0CtkPepkZtAj0EmZGdwK1ZWtMqNcZSuBZNAn/OUGPVmhmUwn +m0mQzgCWICVocBlXZQilxnCySUYG1I8ZCFOGo4d1mCMGQ/mUjzzuEDaWQStYG28AhtUxdJaQFk1R +RHKFm3fUobjYrCxv9tWLTYSwNM4Wm5VpSdMQNggSPphtPD2ADId7N/VAED3C2uZAUCPrqqmcSLYR +j6W6ACkrkbdfQ7Lpr5C8fdbd8RIwjApXh7lVjxBYhWW2emitFCoz9alvqHPzxTzOJ94DBdMNFATZ +HcAxxlTN6Sfj0agmZVreSK8JEwBGCpNRF3baVVWTMNFiIy2QE6ZFsZMvUi3qeJW3nmRXts6EtgTb +oRn3W1hoNkyt1HpazkFx3unOl3MVNpYDaQKQU6u8LmhXLau8eVTdyi7hDO0250UTZwB0WrhsWC5D +LY/c4b6xX0KaA670wjaRhtuHZVQVXBeNNttoHyDCNLHmqpYTZBZmWHMolomjIimQyaptTmkV9GJ5 +M2iZPcfrYZlyoj37ymd6iM6B0EYR2QpizMDKa52tDwBiFW0HxPWBQB4xzeUBrv6NFM31QQ7kBQJu +I5h8gUCbDcsLBEkL3eZOnMRdIGHzuhJPCoiZogkEEOWbdIEw2q6NukniVpTR2bpoFT2DdTjL9u0V +kiRySxTPiE+F+b9EU9YRUHiZWT4yLiGTdSRx3V26hqyj4VqvG7JO0r6XyavSUkrlzWuwyJY0HQ4Z +FsG6oU4QaHhrM8wjNU96M21C4L6xXNq/gDkEPecaxIZAS+ucVLXE9b/R2f5FDkn7F3h4ZivVxBoC +RWOboMS9qzLTBwiBxVdTQ8hScn6TBtZKyTs5WV0RZEXdvkBB0dQQsjRBoeX2KAJpFZLs0dIy8yWT +skQytKYhURDdpTJNiYLkIYTOpJEkowR1ezQQEFJqq5tUrWiXQLNqQ/MYadI4xJCt2BirKQ0kjAh7 +PFBKIAGQarIl16toDxB3I9AQWaXuwTqST/bCzwfrz9ifYsZK/GS+ZZ1OezC4OHuDcRBrxwaUQpmL +zQ9n51O8AEluwcVP0+hioKTaXKxDTnar/rerJdERL7bot7T4JvNMDG4Avnj6rPjlrwffvMyuPJMD +Ad2te/K6/2H406w/GqO3wod5/xNeEZxQ0MdzeIRuUph/ZVjMT6e/IgQrpQpPnhy+Ojr45v8DWdSM +yg== + + + diff --git a/images/orgs-using-d/sarc.svg b/images/orgs-using-d/sarc.svg new file mode 100644 index 0000000000..f2198f54eb --- /dev/null +++ b/images/orgs-using-d/sarc.svg @@ -0,0 +1 @@ +SARC_Logo+slogan_blauw_CMYK \ No newline at end of file diff --git a/images/orgs-using-d/sociomantic.png b/images/orgs-using-d/sociomantic.png new file mode 100644 index 0000000000..a54818b6df Binary files /dev/null and b/images/orgs-using-d/sociomantic.png differ diff --git a/images/orgs-using-d/sociomantic_hq.png b/images/orgs-using-d/sociomantic_hq.png new file mode 100644 index 0000000000..1b2e7efc91 Binary files /dev/null and b/images/orgs-using-d/sociomantic_hq.png differ diff --git a/images/orgs-using-d/symmetry.png b/images/orgs-using-d/symmetry.png new file mode 100644 index 0000000000..1e375de307 Binary files /dev/null and b/images/orgs-using-d/symmetry.png differ diff --git a/images/orgs-using-d/symmetry_hq.png b/images/orgs-using-d/symmetry_hq.png new file mode 100644 index 0000000000..4dcca0f3d2 Binary files /dev/null and b/images/orgs-using-d/symmetry_hq.png differ diff --git a/images/orgs-using-d/tagion.svg b/images/orgs-using-d/tagion.svg new file mode 100644 index 0000000000..e0a73c57e2 --- /dev/null +++ b/images/orgs-using-d/tagion.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/images/orgs-using-d/tamedia.png b/images/orgs-using-d/tamedia.png new file mode 100644 index 0000000000..1ffc4d3d20 Binary files /dev/null and b/images/orgs-using-d/tamedia.png differ diff --git a/images/orgs-using-d/tamedia_hq.png b/images/orgs-using-d/tamedia_hq.png new file mode 100644 index 0000000000..b454510daf Binary files /dev/null and b/images/orgs-using-d/tamedia_hq.png differ diff --git a/images/orgs-using-d/thatneedle.png b/images/orgs-using-d/thatneedle.png new file mode 100644 index 0000000000..f44a65c4ec Binary files /dev/null and b/images/orgs-using-d/thatneedle.png differ diff --git a/images/orgs-using-d/thatneedle_hq.png b/images/orgs-using-d/thatneedle_hq.png new file mode 100644 index 0000000000..a71541b7e2 Binary files /dev/null and b/images/orgs-using-d/thatneedle_hq.png differ diff --git a/images/orgs-using-d/tripaneer.png b/images/orgs-using-d/tripaneer.png new file mode 100644 index 0000000000..49d459e581 Binary files /dev/null and b/images/orgs-using-d/tripaneer.png differ diff --git a/images/orgs-using-d/tripaneer_hq.png b/images/orgs-using-d/tripaneer_hq.png new file mode 100644 index 0000000000..f2ad010cab Binary files /dev/null and b/images/orgs-using-d/tripaneer_hq.png differ diff --git a/images/orgs-using-d/ucora.svg b/images/orgs-using-d/ucora.svg new file mode 100644 index 0000000000..c0b902c564 --- /dev/null +++ b/images/orgs-using-d/ucora.svg @@ -0,0 +1,28 @@ + + + + + + + + + + diff --git a/images/orgs-using-d/undergroundrekordz.png b/images/orgs-using-d/undergroundrekordz.png new file mode 100644 index 0000000000..fbe440113f Binary files /dev/null and b/images/orgs-using-d/undergroundrekordz.png differ diff --git a/images/orgs-using-d/weka.png b/images/orgs-using-d/weka.png new file mode 100644 index 0000000000..07e68c2ef4 Binary files /dev/null and b/images/orgs-using-d/weka.png differ diff --git a/images/orgs-using-d/weka_hq.png b/images/orgs-using-d/weka_hq.png new file mode 100644 index 0000000000..877ae142d7 Binary files /dev/null and b/images/orgs-using-d/weka_hq.png differ diff --git a/images/pattern.png b/images/pattern.png new file mode 100644 index 0000000000..c7e815ddca Binary files /dev/null and b/images/pattern.png differ diff --git a/images/qualifier-combinations.dot b/images/qualifier-combinations.dot new file mode 100644 index 0000000000..23614cf8fe --- /dev/null +++ b/images/qualifier-combinations.dot @@ -0,0 +1,27 @@ +/* +Source file for qualifier-combinations.svg and qualifier-combinations.eps. The +commands to run (assuming graphviz is installed) are: + +cd /path/to/dlang.org/images +dot -Tsvg qualifier-combinations.dot >qualifier-combinations.svg +dot -Teps qualifier-combinations.dot >qualifier-combinations.eps + +These commands are not part of the makefile because the files are fairly stable +and so as to not make the build depending on graphviz being installed. +*/ + +digraph "Qualifer Combinations" { + rankdir="TB"; + "T" -> "const T" [label="const"]; + "T" -> "inout T" [label="inout"]; + "T" -> "shared T" [label="shared"]; + "const T" -> "const inout T" [label="inout"]; + "const T" -> "const shared T" [label="shared"]; + "inout T" -> "const inout T" [label="const"]; + "inout T" -> "inout shared T" [label="shared"]; + "shared T" -> "const shared T" [label="const"]; + "shared T" -> "inout shared T" [label="inout"]; + "const inout T" -> "const inout shared T" [label="shared"]; + "const shared T" -> "const inout shared T" [label="inout"]; + "inout shared T" -> "const inout shared T" [label="const"]; +} diff --git a/images/qualifier-combinations.eps b/images/qualifier-combinations.eps new file mode 100644 index 0000000000..b81dddc638 --- /dev/null +++ b/images/qualifier-combinations.eps @@ -0,0 +1,550 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: graphviz version 2.38.0 (20140413.2041) +%%Title: Qualifer Combinations +%%Pages: 1 +%%BoundingBox: 36 36 444 341 +%%EndComments +save +%%BeginProlog +/DotDict 200 dict def +DotDict begin + +/setupLatin1 { +mark +/EncodingVector 256 array def + EncodingVector 0 + +ISOLatin1Encoding 0 255 getinterval putinterval +EncodingVector 45 /hyphen put + +% Set up ISO Latin 1 character encoding +/starnetISO { + dup dup findfont dup length dict begin + { 1 index /FID ne { def }{ pop pop } ifelse + } forall + /Encoding EncodingVector def + currentdict end definefont +} def +/Times-Roman starnetISO def +/Times-Italic starnetISO def +/Times-Bold starnetISO def +/Times-BoldItalic starnetISO def +/Helvetica starnetISO def +/Helvetica-Oblique starnetISO def +/Helvetica-Bold starnetISO def +/Helvetica-BoldOblique starnetISO def +/Courier starnetISO def +/Courier-Oblique starnetISO def +/Courier-Bold starnetISO def +/Courier-BoldOblique starnetISO def +cleartomark +} bind def + +%%BeginResource: procset graphviz 0 0 +/coord-font-family /Times-Roman def +/default-font-family /Times-Roman def +/coordfont coord-font-family findfont 8 scalefont def + +/InvScaleFactor 1.0 def +/set_scale { + dup 1 exch div /InvScaleFactor exch def + scale +} bind def + +% styles +/solid { [] 0 setdash } bind def +/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def +/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def +/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def +/bold { 2 setlinewidth } bind def +/filled { } bind def +/unfilled { } bind def +/rounded { } bind def +/diagonals { } bind def +/tapered { } bind def + +% hooks for setting color +/nodecolor { sethsbcolor } bind def +/edgecolor { sethsbcolor } bind def +/graphcolor { sethsbcolor } bind def +/nopcolor {pop pop pop} bind def + +/beginpage { % i j npages + /npages exch def + /j exch def + /i exch def + /str 10 string def + npages 1 gt { + gsave + coordfont setfont + 0 0 moveto + (\() show i str cvs show (,) show j str cvs show (\)) show + grestore + } if +} bind def + +/set_font { + findfont exch + scalefont setfont +} def + +% draw text fitted to its expected width +/alignedtext { % width text + /text exch def + /width exch def + gsave + width 0 gt { + [] 0 setdash + text stringwidth pop width exch sub text length div 0 text ashow + } if + grestore +} def + +/boxprim { % xcorner ycorner xsize ysize + 4 2 roll + moveto + 2 copy + exch 0 rlineto + 0 exch rlineto + pop neg 0 rlineto + closepath +} bind def + +/ellipse_path { + /ry exch def + /rx exch def + /y exch def + /x exch def + matrix currentmatrix + newpath + x y translate + rx ry scale + 0 0 1 0 360 arc + setmatrix +} bind def + +/endpage { showpage } bind def +/showpage { } def + +/layercolorseq + [ % layer color sequence - darkest to lightest + [0 0 0] + [.2 .8 .8] + [.4 .8 .8] + [.6 .8 .8] + [.8 .8 .8] + ] +def + +/layerlen layercolorseq length def + +/setlayer {/maxlayer exch def /curlayer exch def + layercolorseq curlayer 1 sub layerlen mod get + aload pop sethsbcolor + /nodecolor {nopcolor} def + /edgecolor {nopcolor} def + /graphcolor {nopcolor} def +} bind def + +/onlayer { curlayer ne {invis} if } def + +/onlayers { + /myupper exch def + /mylower exch def + curlayer mylower lt + curlayer myupper gt + or + {invis} if +} def + +/curlayer 0 def + +%%EndResource +%%EndProlog +%%BeginSetup +14 default-font-family set_font +1 setmiterlimit +% /arrowlength 10 def +% /arrowwidth 5 def + +% make sure pdfmark is harmless for PS-interpreters other than Distiller +/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse +% make '<<' and '>>' safe on PS Level 1 devices +/languagelevel where {pop languagelevel}{1} ifelse +2 lt { + userdict (<<) cvn ([) cvn load put + userdict (>>) cvn ([) cvn load put +} if + +%%EndSetup +setupLatin1 +%%Page: 1 1 +%%PageBoundingBox: 36 36 444 341 +%%PageOrientation: Portrait +0 0 1 beginpage +gsave +36 36 408 305 boxprim clip newpath +1 1 set_scale 0 rotate 40 40 translate +% T +gsave +1 setlinewidth +0 0 0 nodecolor +208.39 279 27 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +203.89 275.3 moveto 9 (T) alignedtext +grestore +% const T +gsave +1 setlinewidth +0 0 0 nodecolor +111.39 192 37.09 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +90.89 188.3 moveto 41 (const T) alignedtext +grestore +% T->const T +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 192.38 263.96 moveto +177.16 250.63 154.06 230.39 136.42 214.93 curveto +stroke +0 0 0 edgecolor +newpath 138.57 212.16 moveto +128.75 208.21 lineto +133.96 217.43 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 138.57 212.16 moveto +128.75 208.21 lineto +133.96 217.43 lineto +closepath stroke +0 0 0 edgecolor +14 /Times-Roman set_font +166.39 231.8 moveto 29 (const) alignedtext +grestore +% inout T +gsave +1 setlinewidth +0 0 0 nodecolor +304.39 192 36.29 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +284.39 188.3 moveto 40 (inout T) alignedtext +grestore +% T->inout T +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 224.39 264.07 moveto +231.72 257.67 240.51 249.97 248.39 243 curveto +258.62 233.96 269.84 223.96 279.54 215.28 curveto +stroke +0 0 0 edgecolor +newpath 282.16 217.64 moveto +287.28 208.36 lineto +277.49 212.42 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 282.16 217.64 moveto +287.28 208.36 lineto +277.49 212.42 lineto +closepath stroke +0 0 0 edgecolor +14 /Times-Roman set_font +264.39 231.8 moveto 28 (inout) alignedtext +grestore +% shared T +gsave +1 setlinewidth +0 0 0 nodecolor +208.39 192 41.69 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +184.39 188.3 moveto 48 (shared T) alignedtext +grestore +% T->shared T +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 208.39 260.8 moveto +208.39 249.16 208.39 233.55 208.39 220.24 curveto +stroke +0 0 0 edgecolor +newpath 211.89 220.18 moveto +208.39 210.18 lineto +204.89 220.18 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 211.89 220.18 moveto +208.39 210.18 lineto +204.89 220.18 lineto +closepath stroke +0 0 0 edgecolor +14 /Times-Roman set_font +208.39 231.8 moveto 36 (shared) alignedtext +grestore +% const inout T +gsave +1 setlinewidth +0 0 0 nodecolor +200.39 105 57.69 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +163.89 101.3 moveto 73 (const inout T) alignedtext +grestore +% const T->const inout T +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 114.54 174.05 moveto +117.23 163.5 122.05 150.23 130.39 141 curveto +136.82 133.89 145.02 128.05 153.52 123.31 curveto +stroke +0 0 0 edgecolor +newpath 155.12 126.42 moveto +162.43 118.76 lineto +151.93 120.19 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 155.12 126.42 moveto +162.43 118.76 lineto +151.93 120.19 lineto +closepath stroke +0 0 0 edgecolor +14 /Times-Roman set_font +130.39 144.8 moveto 28 (inout) alignedtext +grestore +% const shared T +gsave +1 setlinewidth +0 0 0 nodecolor +62.39 105 62.29 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +22.39 101.3 moveto 80 (const shared T) alignedtext +grestore +% const T->const shared T +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 88.58 177.58 moveto +80.92 171.9 73.13 164.6 68.39 156 curveto +64.62 149.16 62.76 141 61.92 133.27 curveto +stroke +0 0 0 edgecolor +newpath 65.41 132.96 moveto +61.34 123.18 lineto +58.42 133.36 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 65.41 132.96 moveto +61.34 123.18 lineto +58.42 133.36 lineto +closepath stroke +0 0 0 edgecolor +14 /Times-Roman set_font +68.39 144.8 moveto 36 (shared) alignedtext +grestore +% inout T->const inout T +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 293.54 174.79 moveto +285.95 164.28 275.12 150.78 263.39 141 curveto +256.42 135.17 248.32 129.84 240.31 125.18 curveto +stroke +0 0 0 edgecolor +newpath 241.81 122.01 moveto +231.36 120.22 lineto +238.41 128.13 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 241.81 122.01 moveto +231.36 120.22 lineto +238.41 128.13 lineto +closepath stroke +0 0 0 edgecolor +14 /Times-Roman set_font +279.39 144.8 moveto 29 (const) alignedtext +grestore +% inout shared T +gsave +1 setlinewidth +0 0 0 nodecolor +338.39 105 61.99 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +298.89 101.3 moveto 79 (inout shared T) alignedtext +grestore +% inout T->inout shared T +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 311.11 174.21 moveto +315.88 162.29 322.37 146.06 327.82 132.42 curveto +stroke +0 0 0 edgecolor +newpath 331.11 133.63 moveto +331.57 123.05 lineto +324.61 131.03 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 331.11 133.63 moveto +331.57 123.05 lineto +324.61 131.03 lineto +closepath stroke +0 0 0 edgecolor +14 /Times-Roman set_font +324.39 144.8 moveto 36 (shared) alignedtext +grestore +% shared T->const shared T +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 195.42 174.73 moveto +186.09 163.92 172.68 150.11 158.39 141 curveto +145.63 132.86 130.72 126.26 116.5 121.08 curveto +stroke +0 0 0 edgecolor +newpath 117.39 117.69 moveto +106.8 117.72 lineto +115.1 124.3 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 117.39 117.69 moveto +106.8 117.72 lineto +115.1 124.3 lineto +closepath stroke +0 0 0 edgecolor +14 /Times-Roman set_font +177.39 144.8 moveto 29 (const) alignedtext +grestore +% shared T->inout shared T +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 212.42 174.04 moveto +215.81 163.22 221.69 149.65 231.39 141 curveto +239.56 133.73 261.02 126.13 282.6 119.87 curveto +stroke +0 0 0 edgecolor +newpath 283.79 123.17 moveto +292.47 117.1 lineto +281.9 116.44 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 283.79 123.17 moveto +292.47 117.1 lineto +281.9 116.44 lineto +closepath stroke +0 0 0 edgecolor +14 /Times-Roman set_font +231.39 144.8 moveto 28 (inout) alignedtext +grestore +% const inout shared T +gsave +1 setlinewidth +0 0 0 nodecolor +200.39 18 83.39 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +144.39 14.3 moveto 112 (const inout shared T) alignedtext +grestore +% const inout T->const inout shared T +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 200.39 86.8 moveto +200.39 75.16 200.39 59.55 200.39 46.24 curveto +stroke +0 0 0 edgecolor +newpath 203.89 46.18 moveto +200.39 36.18 lineto +196.89 46.18 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 203.89 46.18 moveto +200.39 36.18 lineto +196.89 46.18 lineto +closepath stroke +0 0 0 edgecolor +14 /Times-Roman set_font +200.39 57.8 moveto 36 (shared) alignedtext +grestore +% const shared T->const inout shared T +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 87.71 88.41 moveto +109.47 75.01 141.07 55.54 165.28 40.63 curveto +stroke +0 0 0 edgecolor +newpath 167.15 43.59 moveto +173.83 35.36 lineto +163.48 37.62 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 167.15 43.59 moveto +173.83 35.36 lineto +163.48 37.62 lineto +closepath stroke +0 0 0 edgecolor +14 /Times-Roman set_font +140.39 57.8 moveto 28 (inout) alignedtext +grestore +% inout shared T->const inout shared T +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 313.08 88.41 moveto +291.32 75.01 259.71 55.54 235.51 40.63 curveto +stroke +0 0 0 edgecolor +newpath 237.31 37.62 moveto +226.96 35.36 lineto +233.64 43.59 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 237.31 37.62 moveto +226.96 35.36 lineto +233.64 43.59 lineto +closepath stroke +0 0 0 edgecolor +14 /Times-Roman set_font +278.39 57.8 moveto 29 (const) alignedtext +grestore +endpage +showpage +grestore +%%PageTrailer +%%EndPage: 1 +%%Trailer +end +restore +%%EOF diff --git a/images/qualifier-combinations.svg b/images/qualifier-combinations.svg new file mode 100644 index 0000000000..73dda71041 --- /dev/null +++ b/images/qualifier-combinations.svg @@ -0,0 +1,125 @@ + + + + + + +Qualifer Combinations + + +T + +T + + +const T + +const T + + +T->const T + + +const + + +inout T + +inout T + + +T->inout T + + +inout + + +shared T + +shared T + + +T->shared T + + +shared + + +const inout T + +const inout T + + +const T->const inout T + + +inout + + +const shared T + +const shared T + + +const T->const shared T + + +shared + + +inout T->const inout T + + +const + + +inout shared T + +inout shared T + + +inout T->inout shared T + + +shared + + +shared T->const shared T + + +const + + +shared T->inout shared T + + +inout + + +const inout shared T + +const inout shared T + + +const inout T->const inout shared T + + +shared + + +const shared T->const inout shared T + + +inout + + +inout shared T->const inout shared T + + +const + + + diff --git a/images/qualifier-conversions.dot b/images/qualifier-conversions.dot new file mode 100644 index 0000000000..6278aa5fb9 --- /dev/null +++ b/images/qualifier-conversions.dot @@ -0,0 +1,23 @@ +/* +Source file for qualifier-conversions.svg and qualifier-conversions.eps. The +commands to run (assuming graphviz is installed) are: + +cd /path/to/dlang.org/images +dot -Tsvg qualifier-conversions.dot >qualifier-conversions.svg +dot -Teps qualifier-conversions.dot >qualifier-conversions.eps + +These commands are not part of the makefile because the files are fairly stable +and so as to not make the build depending on graphviz being installed. +*/ + +digraph "Qualifier Conversions" { + rankdir="BT"; + "mutable" -> "const"; + "const inout" -> "const"; + "inout" -> "const inout"; + "immutable" -> "const inout"; + "immutable" -> "const inout shared"; + "inout shared" -> "const inout shared"; + "shared" -> "const shared"; + "const inout shared" -> "const shared"; +} diff --git a/images/qualifier-conversions.eps b/images/qualifier-conversions.eps new file mode 100644 index 0000000000..fed94e242d --- /dev/null +++ b/images/qualifier-conversions.eps @@ -0,0 +1,437 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: graphviz version 2.38.0 (20140413.2041) +%%Title: conversions +%%Pages: 1 +%%BoundingBox: 36 36 513 224 +%%EndComments +save +%%BeginProlog +/DotDict 200 dict def +DotDict begin + +/setupLatin1 { +mark +/EncodingVector 256 array def + EncodingVector 0 + +ISOLatin1Encoding 0 255 getinterval putinterval +EncodingVector 45 /hyphen put + +% Set up ISO Latin 1 character encoding +/starnetISO { + dup dup findfont dup length dict begin + { 1 index /FID ne { def }{ pop pop } ifelse + } forall + /Encoding EncodingVector def + currentdict end definefont +} def +/Times-Roman starnetISO def +/Times-Italic starnetISO def +/Times-Bold starnetISO def +/Times-BoldItalic starnetISO def +/Helvetica starnetISO def +/Helvetica-Oblique starnetISO def +/Helvetica-Bold starnetISO def +/Helvetica-BoldOblique starnetISO def +/Courier starnetISO def +/Courier-Oblique starnetISO def +/Courier-Bold starnetISO def +/Courier-BoldOblique starnetISO def +cleartomark +} bind def + +%%BeginResource: procset graphviz 0 0 +/coord-font-family /Times-Roman def +/default-font-family /Times-Roman def +/coordfont coord-font-family findfont 8 scalefont def + +/InvScaleFactor 1.0 def +/set_scale { + dup 1 exch div /InvScaleFactor exch def + scale +} bind def + +% styles +/solid { [] 0 setdash } bind def +/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def +/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def +/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def +/bold { 2 setlinewidth } bind def +/filled { } bind def +/unfilled { } bind def +/rounded { } bind def +/diagonals { } bind def +/tapered { } bind def + +% hooks for setting color +/nodecolor { sethsbcolor } bind def +/edgecolor { sethsbcolor } bind def +/graphcolor { sethsbcolor } bind def +/nopcolor {pop pop pop} bind def + +/beginpage { % i j npages + /npages exch def + /j exch def + /i exch def + /str 10 string def + npages 1 gt { + gsave + coordfont setfont + 0 0 moveto + (\() show i str cvs show (,) show j str cvs show (\)) show + grestore + } if +} bind def + +/set_font { + findfont exch + scalefont setfont +} def + +% draw text fitted to its expected width +/alignedtext { % width text + /text exch def + /width exch def + gsave + width 0 gt { + [] 0 setdash + text stringwidth pop width exch sub text length div 0 text ashow + } if + grestore +} def + +/boxprim { % xcorner ycorner xsize ysize + 4 2 roll + moveto + 2 copy + exch 0 rlineto + 0 exch rlineto + pop neg 0 rlineto + closepath +} bind def + +/ellipse_path { + /ry exch def + /rx exch def + /y exch def + /x exch def + matrix currentmatrix + newpath + x y translate + rx ry scale + 0 0 1 0 360 arc + setmatrix +} bind def + +/endpage { showpage } bind def +/showpage { } def + +/layercolorseq + [ % layer color sequence - darkest to lightest + [0 0 0] + [.2 .8 .8] + [.4 .8 .8] + [.6 .8 .8] + [.8 .8 .8] + ] +def + +/layerlen layercolorseq length def + +/setlayer {/maxlayer exch def /curlayer exch def + layercolorseq curlayer 1 sub layerlen mod get + aload pop sethsbcolor + /nodecolor {nopcolor} def + /edgecolor {nopcolor} def + /graphcolor {nopcolor} def +} bind def + +/onlayer { curlayer ne {invis} if } def + +/onlayers { + /myupper exch def + /mylower exch def + curlayer mylower lt + curlayer myupper gt + or + {invis} if +} def + +/curlayer 0 def + +%%EndResource +%%EndProlog +%%BeginSetup +14 default-font-family set_font +1 setmiterlimit +% /arrowlength 10 def +% /arrowwidth 5 def + +% make sure pdfmark is harmless for PS-interpreters other than Distiller +/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse +% make '<<' and '>>' safe on PS Level 1 devices +/languagelevel where {pop languagelevel}{1} ifelse +2 lt { + userdict (<<) cvn ([) cvn load put + userdict (>>) cvn ([) cvn load put +} if + +%%EndSetup +setupLatin1 +%%Page: 1 1 +%%PageBoundingBox: 36 36 513 224 +%%PageOrientation: Portrait +0 0 1 beginpage +gsave +36 36 477 188 boxprim clip newpath +1 1 set_scale 0 rotate 40 40 translate +% mutable +gsave +1 setlinewidth +0 0 0 nodecolor +39.65 90 39.79 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +17.15 86.3 moveto 45 (mutable) alignedtext +grestore +% const +gsave +1 setlinewidth +0 0 0 nodecolor +93.65 162 29.5 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +79.15 158.3 moveto 29 (const) alignedtext +grestore +% mutable->const +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 52.17 107.24 moveto +59.08 116.2 67.79 127.49 75.45 137.41 curveto +stroke +0 0 0 edgecolor +newpath 72.68 139.55 moveto +81.56 145.33 lineto +78.22 135.28 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 72.68 139.55 moveto +81.56 145.33 lineto +78.22 135.28 lineto +closepath stroke +grestore +% const inout +gsave +1 setlinewidth +0 0 0 nodecolor +147.65 90 50.09 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +117.15 86.3 moveto 61 (const inout) alignedtext +grestore +% const inout->const +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 134.85 107.59 moveto +128 116.47 119.44 127.56 111.9 137.33 curveto +stroke +0 0 0 edgecolor +newpath 108.95 135.43 moveto +105.61 145.49 lineto +114.49 139.71 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 108.95 135.43 moveto +105.61 145.49 lineto +114.49 139.71 lineto +closepath stroke +grestore +% inout +gsave +1 setlinewidth +0 0 0 nodecolor +128.65 18 28.7 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +114.65 14.3 moveto 28 (inout) alignedtext +grestore +% inout->const inout +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 133.25 35.95 moveto +135.36 43.74 137.92 53.18 140.3 61.92 curveto +stroke +0 0 0 edgecolor +newpath 136.96 62.99 moveto +142.96 71.72 lineto +143.72 61.16 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 136.96 62.99 moveto +142.96 71.72 lineto +143.72 61.16 lineto +closepath stroke +grestore +% immutable +gsave +1 setlinewidth +0 0 0 nodecolor +224.65 18 49.29 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +194.65 14.3 moveto 60 (immutable) alignedtext +grestore +% immutable->const inout +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 207.17 34.88 moveto +197.01 44.13 184.02 55.93 172.77 66.16 curveto +stroke +0 0 0 edgecolor +newpath 170.36 63.62 moveto +165.32 72.94 lineto +175.07 68.8 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 170.36 63.62 moveto +165.32 72.94 lineto +175.07 68.8 lineto +closepath stroke +grestore +% const inout shared +gsave +1 setlinewidth +0 0 0 nodecolor +308.65 90 75.29 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +258.65 86.3 moveto 100 (const inout shared) alignedtext +grestore +% immutable->const inout shared +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 243.71 34.88 moveto +254.75 44.08 268.83 55.82 281.07 66.02 curveto +stroke +0 0 0 edgecolor +newpath 278.86 68.74 moveto +288.78 72.45 lineto +283.34 63.36 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 278.86 68.74 moveto +288.78 72.45 lineto +283.34 63.36 lineto +closepath stroke +grestore +% const shared +gsave +1 setlinewidth +0 0 0 nodecolor +371.65 162 54.69 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +337.65 158.3 moveto 68 (const shared) alignedtext +grestore +% const inout shared->const shared +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 323.9 107.95 moveto +331.64 116.54 341.18 127.14 349.69 136.6 curveto +stroke +0 0 0 edgecolor +newpath 347.25 139.12 moveto +356.54 144.21 lineto +352.45 134.44 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 347.25 139.12 moveto +356.54 144.21 lineto +352.45 134.44 lineto +closepath stroke +grestore +% inout shared +gsave +1 setlinewidth +0 0 0 nodecolor +345.65 18 53.89 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +312.15 14.3 moveto 67 (inout shared) alignedtext +grestore +% inout shared->const inout shared +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 336.69 35.95 moveto +332.44 43.99 327.25 53.8 322.51 62.77 curveto +stroke +0 0 0 edgecolor +newpath 319.36 61.25 moveto +317.78 71.72 lineto +325.55 64.52 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 319.36 61.25 moveto +317.78 71.72 lineto +325.55 64.52 lineto +closepath stroke +grestore +% shared +gsave +1 setlinewidth +0 0 0 nodecolor +435.65 90 33.6 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +417.65 86.3 moveto 36 (shared) alignedtext +grestore +% shared->const shared +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 421.44 106.54 moveto +413.23 115.52 402.71 127.02 393.47 137.13 curveto +stroke +0 0 0 edgecolor +newpath 390.87 134.79 moveto +386.7 144.53 lineto +396.03 139.51 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 390.87 134.79 moveto +386.7 144.53 lineto +396.03 139.51 lineto +closepath stroke +grestore +endpage +showpage +grestore +%%PageTrailer +%%EndPage: 1 +%%Trailer +end +restore +%%EOF diff --git a/images/qualifier-conversions.svg b/images/qualifier-conversions.svg new file mode 100644 index 0000000000..4ab00bf8be --- /dev/null +++ b/images/qualifier-conversions.svg @@ -0,0 +1,98 @@ + + + + + + +conversions + + +mutable + +mutable + + +const + +const + + +mutable->const + + + + +const inout + +const inout + + +const inout->const + + + + +inout + +inout + + +inout->const inout + + + + +immutable + +immutable + + +immutable->const inout + + + + +const inout shared + +const inout shared + + +immutable->const inout shared + + + + +const shared + +const shared + + +const inout shared->const shared + + + + +inout shared + +inout shared + + +inout shared->const inout shared + + + + +shared + +shared + + +shared->const shared + + + + + diff --git a/images/quote.gif b/images/quote.gif new file mode 100644 index 0000000000..54bdaf84d8 Binary files /dev/null and b/images/quote.gif differ diff --git a/images/search-bg.gif b/images/search-bg.gif deleted file mode 100644 index e6df1a51ec..0000000000 Binary files a/images/search-bg.gif and /dev/null differ diff --git a/images/search-button.gif b/images/search-button.gif deleted file mode 100644 index 58bfb833fd..0000000000 Binary files a/images/search-button.gif and /dev/null differ diff --git a/images/search-left.gif b/images/search-left.gif deleted file mode 100644 index 16c7e411ea..0000000000 Binary files a/images/search-left.gif and /dev/null differ diff --git a/images/snapcraft_logo.png b/images/snapcraft_logo.png new file mode 100644 index 0000000000..f0a292248f Binary files /dev/null and b/images/snapcraft_logo.png differ diff --git a/images/statement.dot b/images/statement.dot new file mode 100644 index 0000000000..2efb824ce8 --- /dev/null +++ b/images/statement.dot @@ -0,0 +1,16 @@ +/* +Source file for statement.svg and statement.eps. The +commands to run (assuming graphviz is installed) are: + +cd /path/to/dlang.org/images +dot -Tsvg statement.dot >statement.svg +dot -Teps statement.dot >statement.eps + +These commands are not part of the makefile because the files are fairly stable +and so as to not make the build depending on graphviz being installed. +*/ + +digraph "Statement" { + rankdir="LR"; + "Statement" -> {"BlockStatement", "DeclarationStatement", "ExpressionStatement"}; +} diff --git a/images/statement.eps b/images/statement.eps new file mode 100644 index 0000000000..bb7a58f24d --- /dev/null +++ b/images/statement.eps @@ -0,0 +1,293 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: graphviz version 2.43.0 (0) +%%Title: Statement +%%Pages: 1 +%%BoundingBox: 36 36 426 188 +%%EndComments +save +%%BeginProlog +/DotDict 200 dict def +DotDict begin + +/setupLatin1 { +mark +/EncodingVector 256 array def + EncodingVector 0 + +ISOLatin1Encoding 0 255 getinterval putinterval +EncodingVector 45 /hyphen put + +% Set up ISO Latin 1 character encoding +/starnetISO { + dup dup findfont dup length dict begin + { 1 index /FID ne { def }{ pop pop } ifelse + } forall + /Encoding EncodingVector def + currentdict end definefont +} def +/Times-Roman starnetISO def +/Times-Italic starnetISO def +/Times-Bold starnetISO def +/Times-BoldItalic starnetISO def +/Helvetica starnetISO def +/Helvetica-Oblique starnetISO def +/Helvetica-Bold starnetISO def +/Helvetica-BoldOblique starnetISO def +/Courier starnetISO def +/Courier-Oblique starnetISO def +/Courier-Bold starnetISO def +/Courier-BoldOblique starnetISO def +cleartomark +} bind def + +%%BeginResource: procset graphviz 0 0 +/coord-font-family /Times-Roman def +/default-font-family /Times-Roman def +/coordfont coord-font-family findfont 8 scalefont def + +/InvScaleFactor 1.0 def +/set_scale { + dup 1 exch div /InvScaleFactor exch def + scale +} bind def + +% styles +/solid { [] 0 setdash } bind def +/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def +/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def +/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def +/bold { 2 setlinewidth } bind def +/filled { } bind def +/unfilled { } bind def +/rounded { } bind def +/diagonals { } bind def +/tapered { } bind def + +% hooks for setting color +/nodecolor { sethsbcolor } bind def +/edgecolor { sethsbcolor } bind def +/graphcolor { sethsbcolor } bind def +/nopcolor {pop pop pop} bind def + +/beginpage { % i j npages + /npages exch def + /j exch def + /i exch def + /str 10 string def + npages 1 gt { + gsave + coordfont setfont + 0 0 moveto + (\() show i str cvs show (,) show j str cvs show (\)) show + grestore + } if +} bind def + +/set_font { + findfont exch + scalefont setfont +} def + +% draw text fitted to its expected width +/alignedtext { % width text + /text exch def + /width exch def + gsave + width 0 gt { + [] 0 setdash + text stringwidth pop width exch sub text length div 0 text ashow + } if + grestore +} def + +/boxprim { % xcorner ycorner xsize ysize + 4 2 roll + moveto + 2 copy + exch 0 rlineto + 0 exch rlineto + pop neg 0 rlineto + closepath +} bind def + +/ellipse_path { + /ry exch def + /rx exch def + /y exch def + /x exch def + matrix currentmatrix + newpath + x y translate + rx ry scale + 0 0 1 0 360 arc + setmatrix +} bind def + +/endpage { showpage } bind def +/showpage { } def + +/layercolorseq + [ % layer color sequence - darkest to lightest + [0 0 0] + [.2 .8 .8] + [.4 .8 .8] + [.6 .8 .8] + [.8 .8 .8] + ] +def + +/layerlen layercolorseq length def + +/setlayer {/maxlayer exch def /curlayer exch def + layercolorseq curlayer 1 sub layerlen mod get + aload pop sethsbcolor + /nodecolor {nopcolor} def + /edgecolor {nopcolor} def + /graphcolor {nopcolor} def +} bind def + +/onlayer { curlayer ne {invis} if } def + +/onlayers { + /myupper exch def + /mylower exch def + curlayer mylower lt + curlayer myupper gt + or + {invis} if +} def + +/curlayer 0 def + +%%EndResource +%%EndProlog +%%BeginSetup +14 default-font-family set_font +% /arrowlength 10 def +% /arrowwidth 5 def + +% make sure pdfmark is harmless for PS-interpreters other than Distiller +/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse +% make '<<' and '>>' safe on PS Level 1 devices +/languagelevel where {pop languagelevel}{1} ifelse +2 lt { + userdict (<<) cvn ([) cvn load put + userdict (>>) cvn ([) cvn load put +} if + +%%EndSetup +setupLatin1 +%%Page: 1 1 +%%PageBoundingBox: 36 36 426 188 +%%PageOrientation: Portrait +0 0 1 beginpage +gsave +36 36 390 152 boxprim clip newpath +1 1 set_scale 0 rotate 40 40 translate +% Statement +gsave +1 setlinewidth +0 0 0 nodecolor +59.7947 72 59.5901 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +21.7947 68.3 moveto 76 (Statement) alignedtext +grestore +% BlockStatement +gsave +1 setlinewidth +0 0 0 nodecolor +268.6794 126 85.2851 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +211.1794 122.3 moveto 115 (BlockStatement) alignedtext +grestore +% Statement->BlockStatement +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 103.1623 84.4696 moveto +119.505 89.1738 138.3771 94.4778 155.5894 99 curveto +170.1394 102.8228 185.8071 106.7281 200.6822 110.3379 curveto +stroke +0 0 0 edgecolor +newpath 200.2884 113.8432 moveto +210.8303 112.7852 lineto +201.9295 107.0383 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 200.2884 113.8432 moveto +210.8303 112.7852 lineto +201.9295 107.0383 lineto +closepath stroke +grestore +% DeclarationStatement +gsave +1 setlinewidth +0 0 0 nodecolor +268.6794 72 113.18 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +189.6794 68.3 moveto 158 (DeclarationStatement) alignedtext +grestore +% Statement->DeclarationStatement +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 119.8027 72 moveto +127.9595 72 136.5715 72 145.3721 72 curveto +stroke +0 0 0 edgecolor +newpath 145.3741 75.5001 moveto +155.3741 72 lineto +145.3741 68.5001 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 145.3741 75.5001 moveto +155.3741 72 lineto +145.3741 68.5001 lineto +closepath stroke +grestore +% ExpressionStatement +gsave +1 setlinewidth +0 0 0 nodecolor +268.6794 18 111.2805 18 ellipse_path stroke +0 0 0 nodecolor +14 /Times-Roman set_font +191.1794 14.3 moveto 155 (ExpressionStatement) alignedtext +grestore +% Statement->ExpressionStatement +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 103.1623 59.5304 moveto +119.505 54.8262 138.3771 49.5222 155.5894 45 curveto +168.1626 41.6966 181.5704 38.3316 194.5802 35.1488 curveto +stroke +0 0 0 edgecolor +newpath 195.5404 38.5174 moveto +204.4308 32.7545 lineto +193.8871 31.7155 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 195.5404 38.5174 moveto +204.4308 32.7545 lineto +193.8871 31.7155 lineto +closepath stroke +grestore +endpage +showpage +grestore +%%PageTrailer +%%EndPage: 1 +%%Trailer +end +restore +%%EOF diff --git a/images/statement.svg b/images/statement.svg new file mode 100644 index 0000000000..9e6e6e49fc --- /dev/null +++ b/images/statement.svg @@ -0,0 +1,55 @@ + + + + + + +Statement + + + +Statement + +Statement + + + +BlockStatement + +BlockStatement + + + +Statement->BlockStatement + + + + + +DeclarationStatement + +DeclarationStatement + + + +Statement->DeclarationStatement + + + + + +ExpressionStatement + +ExpressionStatement + + + +Statement->ExpressionStatement + + + + + diff --git a/images/style3.gif b/images/style3.gif new file mode 100644 index 0000000000..5d10c3ef5d Binary files /dev/null and b/images/style3.gif differ diff --git a/images/style3_hq.gif b/images/style3_hq.gif new file mode 100644 index 0000000000..de2b6ac843 Binary files /dev/null and b/images/style3_hq.gif differ diff --git a/images/tdpl.jpg b/images/tdpl.jpg index 7ec94e91b1..e25c8adce5 100644 Binary files a/images/tdpl.jpg and b/images/tdpl.jpg differ diff --git a/images/tdpl_hq.jpg b/images/tdpl_hq.jpg new file mode 100644 index 0000000000..7ec94e91b1 Binary files /dev/null and b/images/tdpl_hq.jpg differ diff --git a/images/ubuntu_logo.png b/images/ubuntu_logo.png index df596f62ea..7432d68df6 100644 Binary files a/images/ubuntu_logo.png and b/images/ubuntu_logo.png differ diff --git a/images/win32_logo.png b/images/win32_logo.png deleted file mode 100644 index 28aa325f9c..0000000000 Binary files a/images/win32_logo.png and /dev/null differ diff --git a/images/windows_logo.png b/images/windows_logo.png new file mode 100644 index 0000000000..5b5d2dca65 Binary files /dev/null and b/images/windows_logo.png differ diff --git a/index.dd b/index.dd index 94df8d647a..b0de3429bf 100644 --- a/index.dd +++ b/index.dd @@ -2,148 +2,593 @@ Ddoc $(D_S D Programming Language, -$(SECTION3 The D programming language. Modern -convenience. Modeling power. Native efficiency., +$(SECTION1 , + +$(DIVC intro, $(DIV, $(DIV, + $(DIV, + $(TC p, pitch, $(B D) is a general-purpose programming language with + static typing, systems-level access, and C-like syntax. + With the $(B D Programming Language), write fast, + read fast, and run fast. + $(BR)$(BR)Fast code, fast.) + + $(BR) + + $(DIVC download, + $(DIVC btn-group-vertical, + Downloads + $(SPANC smallprint, Latest version: $(LATEST) + – $(LINK2 changelog/$(LATEST).html, Changelog)) + ) + ) + ) + $(DIVID your-code-here, + $(DIVCID fa-select, your-code-here-select-example,) + $(DIVC tip, + $(LINK2 https://forum.dlang.org/newpost/general?subject=%5Byour+code+here%5D, your code here) + $(DIV, + $(P Got a brief example illustrating D?) + $(P Submit your code to the digitalmars.D forum specifying + "[your code here]" in the subject.) + $(P Upon approval it will be showcased here on a random schedule.) + ) + ) +$(EXTRA_EXAMPLE_RUNNABLE Compute average line length for stdin, +$(RUNNABLE_EXAMPLE_STDIN +The D programming language +Modern convenience. +Modeling power. +Native efficiency.) +---- +void main() +{ + import std.range, std.stdio; - +---- +) +$(EXTRA_EXAMPLE_RUNNABLE Sort lines, +$(RUNNABLE_EXAMPLE_STDIN +Mercury +Venus +Earth +Mars +Jupiter +Saturn +Uranus +Neptune) +---- +import std.stdio, std.array, std.algorithm; +void main() +{ + stdin + .byLineCopy + .array + .sort!((a, b) => a > b) // descending order + .each!writeln; +} ---- -#!/usr/bin/rdmd -// Computes average line length for standard input. -import std.stdio; +) +$(EXTRA_EXAMPLE_RUNNABLE Sort an Array at Compile-Time, +---- +void main() +{ + import std.algorithm, std.stdio; + + "Starting program".writeln; + + enum a = [ 3, 1, 2, 4, 0 ]; + // Sort data at compile-time + static immutable b = sort(a); + + // Print the result _during_ compilation + pragma(msg, "Finished compilation: ", b); +} +---- +) +$(EXTRA_EXAMPLE_RUNNABLE Invoke external programs, +---- +void main() +{ + import std.exception, std.stdio, std.process; -void main() { - ulong lines = 0; - double sumLength = 0; - foreach (line; stdin.byLine()) { - ++lines; - sumLength += line.length; + auto result = ["whoami"].execute; + enforce(result.status == 0); + result.output.write; +} +---- +) +$(EXTRA_EXAMPLE_RUNNABLE Print hex dump, +---- +void main() +{ + import std.algorithm, std.stdio, std.file, std.range; + enum cols = 14; + // Split file into 14-byte chunks per row + thisExePath.File("rb").byChunk(cols).take(20).each!(chunk => + // Use range formatting to format the + // hexadecimal part and align the text part + writefln!"%(%02X %)%*s %s"( + chunk, + 3 * (cols - chunk.length), "", // Padding + chunk.map!(c => // Replace non-printable + c < 0x20 || c > 0x7E ? '.' : char(c)))); +} +---- +) +$(EXTRA_EXAMPLE Start a minimal web server, +---- +#!/usr/bin/env dub +/+ dub.sdl: +dependency "vibe-d" version="~>0.9.0" ++/ +void main() +{ + import vibe.d; + listenHTTP(":8080", (req, res) { + res.writeBody("Hello, World: " ~ req.path); + }); + runApplication(); +} +---- +) +$(EXTRA_EXAMPLE_RUNNABLE Initialize an Array in parallel, +---- +void main() +{ + import std.datetime.stopwatch : benchmark; + import std.math, std.parallelism, std.stdio; + + auto logs = new double[100_000]; + auto bm = benchmark!({ + foreach (i, ref elem; logs) + elem = log(1.0 + i); + }, { + foreach (i, ref elem; logs.parallel) + elem = log(1.0 + i); + })(100); // number of executions of each tested function + writefln("Linear init: %s msecs", bm[0].total!"msecs"); + writefln("Parallel init: %s msecs", bm[1].total!"msecs"); +} +---- +) +$(EXTRA_EXAMPLE_RUNNABLE Sort in-place across multiple arrays, +---- +void main() +{ + import std.stdio : writefln; + import std.algorithm.sorting : sort; + import std.range : chain; + + int[] arr1 = [4, 9, 7]; + int[] arr2 = [5, 2, 1, 10]; + int[] arr3 = [6, 8, 3]; + // @nogc functions are guaranteed by the compiler + // to be without any GC allocation + () @nogc { + sort(chain(arr1, arr2, arr3)); + }(); + writefln("%s\n%s\n%s\n", arr1, arr2, arr3); +} +---- +) +$(EXTRA_EXAMPLE_RUNNABLE Count frequencies of character pairs, +---- +void main() +{ + import std.stdio : writefln; + // An associative array mapping pairs of characters to integers + int[char[2]] aa; + auto arr = "ABBBA"; + + // Iterate over all pairs in the string + // ['A', 'B'], ['B', 'B'], ..., ['B', 'A'] + foreach (i; 0 .. arr.length - 1) + { + // String slicing doesn't allocate a copy + char[2] pair = arr[i .. i + 2]; + // count occurrences + aa[pair]++; } - writeln("Average line length: ", - lines ? sumLength / lines : 0); + foreach (key, value; aa) + writefln("key: %s, value: %d", key, value); } ---- - +) +$(EXTRA_EXAMPLE_RUNNABLE Tiny RPN calculator, +$(RUNNABLE_EXAMPLE_STDIN 2 3 3 4 + * *) +---- +void main() +{ + import std.stdio, std.string, std.algorithm, std.conv; -$(TAG2 div, id="your-code-info" style="display:block; position:relative; width: 50%; margin-left:auto; top:-2.5em; bottom:0em; background:white; border:1px solid #ccc; font-size:80%; padding:0px 5px 0px 5px; line-height:1.4em;", -Got a brief example illustrating D? Submit your code to the -$(LINK2 http://digitalmars.com/NewsGroup.html, digitalmars.D forum)$(COMMA) -specifying "[your code here]" in the title. Upon approval$(COMMA) it will be showcased -on a random schedule on D‘s homepage. + // arr is real[] and sym is the current symbol + readln.split.fold!((arr, sym) + { + static foreach (c; "+-*/") + if (sym == [c]) + // replace the last 2 elements with the binary op + return arr[0 .. $-2] ~ + mixin("arr[$-2] " ~ c ~ " arr[$-1]"); + + // sym must be a number + return arr ~ sym.to!real; + })((real[]).init).writeln; +} +---- +) +$(EXTRA_EXAMPLE_RUNNABLE Subtyping with alias this, +---- +struct Point +{ + private double[2] p; + // Forward all undefined symbols to p + alias p this; + double dot(Point rhs) + { + return p[0] * rhs.p[0] + p[1] * rhs.p[1]; + } +} +void main() +{ + import std.stdio : writeln; + // Point behaves like a `double[2]` ... + Point p1, p2; p1 = [2, 1], p2 = [1, 1]; + assert(p1[$ - 1] == 1); + // ... but with extended functionality + writeln("p1 dot p2 = ", p1.dot(p2)); +} +---- ) - -D is a language with C-like syntax and static typing. It pragmatically combines -efficiency, control, and modeling power, with safety and programmer productivity. +) $(COMMENT your-code-here) +))) $(COMMENT intro, div, div) -$(SECTION3 Convenience, +$(COMMENT +Picking the frontpage example after the page has loaded leads to reflows +and re-rendering. Hence, we pick the example as soon as possible +) +$(SCRIPT + (function() { + // randomly pick one example and bootstrap the runnable editor + var examples = document.getElementsByClassName('your-code-here-extra'); + var rouletteIndex = Math.floor(Math.random() * examples.length); + var rouletteChild = examples[rouletteIndex]; + rouletteChild.style.display = "block"; + + // build a list of the titles of all examples and add an option chooser to + // allow switching between them + var titles = Array.prototype.map.call(examples, function(e) { + return e.getElementsByClassName("your-code-here-title")[0].innerText; + }); + var sel = document.createElement("select"); + Array.prototype.forEach.call(titles, function(title, i) { + var el = document.createElement("option"); + el.value = i; + el.innerText = title; + sel.appendChild(el); + }); + sel.selectedIndex = rouletteIndex; + sel.addEventListener("change", function(e) { + examples[rouletteIndex].style.display = "none"; + rouletteIndex = sel.selectedIndex; + examples[rouletteIndex].style.display = "block"; + }); + var selEl = document.getElementById("your-code-here-select-example"); + selEl.appendChild(sel); + })(); +) -$(UL +$(DIVC call_to_donate, +

    Support the D language

    +

    D is made possible through the hard work and dedication of many volunteers, + with the coordination and outreach of the D Language Foundation, a 501(c)(3) non-profit organization. + You can help further the development of the D language and help grow our + community by supporting the Foundation. +

    +

    + Donate + Learn More About The Foundation + $(BR) + $(BR) + Lots of $(WHY_D_ICON heart) to our $(LINK2 $(ROOT_DIR)foundation/sponsors.html, sponsors) and + $(LINK2 $(ROOT_DIR)foundation/contributors.html, contributors). +

    +) -$(LI D allows writing large code fragments without redundantly specifying types, -in the style of dynamic languages. Yet static inference deduces types and other +$(DIVC org_list_header, +

    + Industry Proven +

    +) + +$(DIVC org_list, + + + + + + +) + +$(DIVC org_list_footer, +
    +
    +
    + $(FA_ICON quote-left) D shines from low-level control + to high-level abstraction $(FA_ICON quote-right) $(BR) +
    + $(FA_ICON heart) $(LINK2 $(ROOT_DIR)orgs-using-d.html, Success stories) + $(FA_ICON history) $(LINK2 $(ROOT_DIR)areas-of-d-usage.html, What is D used for?) +
    +
    +) + +$(DIVC more, + +$(DIVID news, + $(DIVID forum-summary, + + + ) +) + +$(DIVC boxes, + + $(DIVC row, + $(TOUR newspaper-o, News, + $(P Stay updated with the latest posts in the + $(LINK2 http://blog.dlang.org, + Official D Blog) from $(DBLOG_LATEST_DATE_1): + $(LINK2 $(DBLOG_LATEST_LINK_1), $(DBLOG_LATEST_TITLE_1)) by + $(DBLOG_LATEST_AUTHOR_1). + ) + $(P + From $(DBLOG_LATEST_DATE_2): + $(LINK2 $(DBLOG_LATEST_LINK_2), $(DBLOG_LATEST_TITLE_2)) by + $(DBLOG_LATEST_AUTHOR_2). + ) + ) + $(TOUR graduation-cap, Learn, + $(P Take the $(LINK2 https://tour.dlang.org, + Tour), explore + $(LINK2 $(ROOT_DIR)overview.html, major features) in D, + browse the $(LINK2 $(ROOT_DIR)comparison.html, quick overview), + start with $(LINK2 $(ROOT_DIR)ctod.html, C) or + $(LINK2 $(ROOT_DIR)cpptod.html, C++) background, + and ask questions in the + $(LINK2 https://forum.dlang.org/group/digitalmars.D.learn, + Learn forum). + ) + $(P For a deeper dive into D + check out $(LINK2 https://wiki.dlang.org/Books, books) or + $(LINK2 https://wiki.dlang.org/Videos, videos) + such as Ali Çehreli's free book + $(LINK2 http://ddili.org/ders/d.en/index.html, + Programming in D). + ) + ) + ) + $(DIVC row, + $(TOUR comments, Community, + $(P Discuss D on the $(LINK2 https://forum.dlang.org/, forums), join + the $(LINK2 irc://irc.libera.chat/d, IRC channel), read our + $(LINK2 https://dlang.org/blog, official Blog), or follow us + on $(LINK2 https://twitter.com/D_Programming, Twitter). + Browse the $(LINK2 https://wiki.dlang.org/, wiki), where among + other things you can find the + $(LINK2 https://wiki.dlang.org/Vision/2018H1, high-level vision) + of the $(LINK2 $(ROOT_DIR)foundation_overview.html, D Language Foundation). + ) + ) + $(TOUR book, Documentation, + $(P Refer to the + $(LINK2 $(ROOT_DIR)spec/spec.html, language specification) and + the documentation of + $(LINK2 $(ROOT_DIR)phobos/index.html, Phobos), D's standard + library. The + $(LINK2 $(ROOT_DIR)dmd.html, DMD manual) tells you how + to use the compiler. Read + $(LINK2 $(ROOT_DIR)articles.html, various articles) to deepen + your understanding. + ) + ) + ) + $(DIVC row, + $(TOUR code-fork, Contribute, + $(P Report any bugs you find to our $(LINK2 $(ROOT_DIR)bugstats.html, + bug tracker). If you can fix an issue, make a pull request on + $(LINK2 https://github.com/dlang, GitHub). + There are $(LINK2 https://wiki.dlang.org/Get_involved, many other ways) + to help, too! + ) + ) + $(TOUR cubes, Packages, + $(P DUB is the package manager for D. + $(LINK2 https://code.dlang.org/getting_started, + Get started with DUB), and check out the + $(LINK2 https://code.dlang.org/, available packages). + ) + ) + ) + $(DIVC row, + $(TOUR play, Run, + $(P Configure linting, + formatting or + completion for + your favorite $(LINK2 https://wiki.dlang.org/IDEs, IDE), + $(LINK2 https://wiki.dlang.org/Editors, editor) or + use $(LINK2 https://run.dlang.io, run.dlang.io) to play and experiment + with D code. + ) + ) + $(TOUR forward, Explore, + $(P + Learn about $(LINK2 https://qznc.github.io/d-tut, pragmatic D), + the $(LINK2 $(ROOT_DIR)dstyle.html, DStyle), + $(LINK2 https://p0nce.github.io/d-idioms, common D idioms) and + $(LINK2 https://github.com/PhilippeSigaud/D-templates-tutorial, templates), + + See what's coming upcoming with $(LINK2 $(ROOT_DIR)changelog/pending.html, next version), + explore $(LINK2 https://github.com/dlang/DIPs, D Improvement Proposals), + and don't fear $(LINK2 https://dlang.org/blog/the-gc-series, D's garbage collection). + + ) + ) + ) +) + +$(DIVC whyd, $(SECTION2 Fast code$(COMMA) fast., + +$(DIVC section, +$(DIV, $(SECTION3 $(WHY_D_ICON magic) Write Fast, + +$(P D allows writing large code fragments without redundantly specifying types, +like dynamic languages do. On the other hand, static inference deduces types and other code properties, giving the best of both the static and the dynamic worlds. $(EXAMPLE 1, ---- -void main() { - // Define an array of numbers, double[]. Compiler recognizes the common +void main() +{ + // Define an array of numbers, double[]. + // Compiler recognizes the common // type of all initializers. auto arr = [ 1, 2, 3.14, 5.1, 6 ]; - // Dictionary that maps string to int, type is spelled int[string] - auto dictionary = [ "one" : 1, "two" : 2, "three" : 3 ]; + // Dictionary that maps string to int, + // type is spelled int[string] + auto dictionary = [ "one" : 1, "two" : 2, + "three" : 3 ]; // Calls the min function defined below auto x = min(arr[0], dictionary["two"]); } -// Type deduction works for function results. This is important for generic -// functions, such as min below, which works correctly for all comparable -// types. -auto min(T1, T2)(T1 lhs, T2 rhs) { +// Type deduction works for function results. +// This is important for generic functions, +// such as min below, which works correctly +// for all comparable types. +auto min(T1, T2)(T1 lhs, T2 rhs) +{ return rhs < lhs ? rhs : lhs; } ---- + )) -$(LI Automatic memory management makes for safe, simple, and robust code. +$(P Automatic memory management makes for safe, simple, and robust code. D also supports scoped resource management (aka the -$(WEB en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization, RAII) idiom) -and $(LINK2 statement.html#ScopeGuardStatement, $(D scope) statements) for +$(HTTPS en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization, RAII) idiom) +and $(LINK2 spec/statement.html#ScopeGuardStatement, $(D scope) statements) for deterministic transactional code that is easy to write and read. $(EXAMPLE 2, + ---- import std.stdio; -class Widget { ... } +class Widget { } -void main() { +void main() +{ // Automatically managed. auto w = new Widget; // Code is executed in any case upon scope exit. scope(exit) { writeln("Exiting main."); } // File is closed deterministically at scope's end. - foreach (line; File("text.txt").byLine()) { + foreach (line; File(__FILE_FULL_PATH__).byLine()) + { writeln(line); } + writeln(); } ---- ) ) -$(LI Built-in linear and associative arrays, slices, and ranges make daily -programming simple and pleasant for tasks small and large. $(EXAMPLE 3, +$(P Built-in linear and associative arrays, slices, and ranges make daily +programming simple and pleasant for tasks, both small and large. $(EXAMPLE 3, +$(RUNNABLE_EXAMPLE_STDIN +The D programming language +Modern convenience. +Modeling power. +Native efficiency.) ---- -#!/usr/bin/rdmd -import std.range, std.stdio; - // Compute average line length for stdin -void main() { - ulong lines = 0, sumLength = 0; - foreach (line; stdin.byLine()) { - ++lines; - sumLength += line.length; - } +void main() +{ + import std.range, std.stdio; + + auto sum = 0.0; + auto count = stdin.byLine + .tee!(l => sum += l.length).walkLength; + writeln("Average line length: ", - lines ? cast(double) sumLength / lines : 0.0); + count ? sum / count : 0); } ---- )) -)) - -$(SECTION3 Power, +))) -$(UL +$(DIVC section, $(DIV, $(SECTION3 $(WHY_D_ICON rocket) Read Fast, -$(LI The best paradigm is to not impose one at the expense of others. +$(P The best paradigm is to not impose something at the expense of others. D offers classic polymorphism, value semantics, functional style, generics, generative programming, contract programming, and more—all harmoniously integrated. $(EXAMPLE 4, ---- // Interfaces and classes -interface Printable { +interface Printable +{ void print(uint level) - in { assert(level > 0); } // contract is part of the interface + // contract is part of the interface + in { assert(level > 0); } } // Interface implementation -class Widget : Printable { - void print(uint level) { ... } +class Widget : Printable +{ + void print(uint level) + in{ } + do{ } } // Single inheritance of state -class ExtendedWidget : Widget { +class ExtendedWidget : Widget +{ override void print(uint level) in { /* weakening precondition is okay */ } - body { - ... level may be 0 here ... + do + { + //... level may be 0 here ... } } @@ -155,64 +600,79 @@ int perThread = 42; shared int perApp = 5; // Structs have value semantics -struct BigNum { +struct BigNum +{ // intercept copying - this(this) { ... } + this(this) { } // intercept destructor - ~this() { ... } + ~this() { } +} + +void main() +{ + // ... } ---- )) -$(LI D offers an innovative approach to concurrency featuring true +$(P D offers an innovative approach to concurrency, featuring true immutable data, message passing, no sharing by default, and -controlled mutable sharing across threads. $(WEBX +controlled mutable sharing across threads. $(HTTP informit.com/articles/article.aspx?p=1609144, Read more).) -$(LI From simple scripts to large projects, D has the breadth +$(P From simple scripts to large projects, D has the breadth to scale with any application's needs: unit testing, information hiding, refined modularity, fast compilation, precise -interfaces. $(WEBX drdobbs.com/high-performance-computing/217801225, +interfaces. $(HTTP drdobbs.com/high-performance-computing/217801225, Read more).) -)) - -$(SECTION3 Efficiency, +))) -$(UL +$(DIVC section, $(DIV, $(SECTION3 $(WHY_D_ICON bolt) Run Fast, -$(LI D compiles naturally to efficient native code.) +$(P D compiles naturally to efficient native code.) -$(LI D is designed such that most "obvious" code is fast $(I and) +$(P D is designed such that most "obvious" code is fast $(I and) safe. On occasion a function might need to escape the confines of type safety for ultimate speed and control. For such rare cases D offers native pointers, type casts, access to any C function without any -intervening translation, and even inline assembler. $(EXAMPLE 5, +intervening translation, manual memory management, custom allocators +and even inline assembly code. $(EXAMPLE 5, ---- -void livingDangerously() { +import core.stdc.stdlib; + +void livingDangerously() +{ // Access to C's malloc and free primitives - auto buf = malloc(1024 * 1024); - scope(exit) free(buf); // free automatically upon scope exit + enum bytes = float.sizeof * 1024 * 1024; + auto buf = malloc(bytes); + // free automatically upon scope exit + scope(exit) free(buf); // Interprets memory as an array of floats - auto floats = cast(float[]) buf[0 .. 1024 * 1024]; + auto floats = cast(float[]) buf[0 .. bytes]; // Even stack allocation is possible auto moreBuf = alloca(4096 * 100); - ... + //... } // Using inline asm for extra speed on x86 -uint checked_multiply(uint x, uint y) { +uint checked_multiply(uint x, uint y) +{ uint result; - version (D_InlineAsm_X86) { - // Inline assembler "sees" D variables. - asm { + version (D_InlineAsm_X86) + { + // Inline assembler "sees" D variables and labels. + asm + { mov EAX,x ; mul EAX,y ; mov result,EAX ; jc Loverflow ; } return result; - } else { + } + else + { result = x * y; if (!y || x <= uint.max / y) return result; @@ -220,352 +680,368 @@ uint checked_multiply(uint x, uint y) { Loverflow: throw new Exception("multiply overflow"); } + +void main() +{ + // ... +} ---- )) -$(LI The $(D @safe), $(D @trusted), and $(D @system) modular -attributes allow the programmer to best decide the safety/efficiency -tradeoffs of a particular application, and have the compiler check for -consistency. $(LINK2 safed.html, Read more.)) - -) - -)) +$(P The $(D @safe), $(D @trusted), and $(D @system) function +attributes allow the programmer to best decide the safety-efficiency +tradeoffs of an application, and have the compiler check for +consistency. $(LINK2 spec/memory-safe-d.html, Read more).) -$(XXXXSECTION2 Community, - -$(P D is the center of a growing, vibrant community. Get D-related -news from the $(D digitalmars.D.announce) forum $(TAG2 span, -style="font-size:80%", $(WEB -digitalmars.com/pnews/indexing.php?server=news.digitalmars.com&group=digitalmars.D.announce, -[browse]) $(LINK2 news://news.digitalmars.com/digitalmars.D.announce, -[usenet]) $(WEB -lists.puremagic.com/cgi-bin/mailman/listinfo/digitalmars-d-announce, -[mailing list])). On Twitter, subscribe to D's official announcements -channel, $(WEB twitter.com/#!/D_Programming,@D_Programming), and -search for (and disseminate) news using tag $(WEB -twitter.com/#!/search/%23d_lang, #d_lang).) - -$(P Learning D and have a question about the best way to do X? The $(D -digitalmars.D.learn) forum $(TAG2 span, style="font-size:80%", $(WEB -digitalmars.com/pnews/indexing.php?server=news.digitalmars.com&group=digitalmars.D.learn, -[browse]) $(LINK2 news://news.digitalmars.com/digitalmars.D.learn, -[usenet]) $(WEB -lists.puremagic.com/cgi-bin/mailman/listinfo/digitalmars-d-learn, -[mailing list])) is the hangout place where many D experts are ready -to help fellow hackers.) - -$(P The $(D digitalmars.D) forum $(TAG2 span, style="font-size:80%", -$(WEB -digitalmars.com/pnews/indexing.php?server=news.digitalmars.com&group=digitalmars.D, -[browse]) $(LINK2 news://news.digitalmars.com/digitalmars.D, [usenet]) -$(WEB lists.puremagic.com/cgi-bin/mailman/listinfo/digitalmars-d, -[mailing list])) is the best place to discuss anything and everything -related to D: language design ideas, suggestions, status and future, -contributions to the language and its standard library. Reach and -engage all major D contributors, including the very creator of D, -$(WEB walterbright.com, Walter Bright). For real-time conversation, use #d IRC channel on freenode.) - -$(SECTION3 To contribute, - -$(P Many D enthusiasts are not only using, but also contributing to -the language, its implementation, and its standard library. The main -hub of D development is $(WEB github.com/D-Programming-Language, -D-Programming-Language on github). The project has been awash in -contributions ever since creating the github repository on January 23, -2011, with an average of over 3 pull requests per day. (That doesn't -mean there's not a lot more to do!) You are welcome to fork any -subproject ($(WEB github.com/D-Programming-Language/dmd, compiler), -$(WEB github.com/D-Programming-Language/druntime, runtime), $(WEB -github.com/D-Programming-Language/phobos, standard library), $(WEB -github.com/D-Programming-Language/d-programming-language.org, -website), $(WEB github.com/D-Programming-Language/tools, tools), or -$(WEB github.com/D-Programming-Language/installer, installer)), change -it in useful ways, and propose your changes back to the community. - -$(P The reference compiler $(LINK2 download.html, dmd) has inspired -work on alternate implementations that add value by using distinct -back-ends:) - -$(UL - -$(LI GNU D compiler $(LINK2 http://bitbucket.org/goshawk/gdc/wiki/Home, gdc).) - -$(LI LLVM D Compiler $(WEB dsource.org/projects/ldc, ldc).) +))) -) +)) $(COMMENT SECTION2 Why D?, DIVC whyd) +) $(COMMENT more) +) $(COMMENT SECTION1) +) $(COMMENT D_S) -$(P The gdc compiler is of particular interest because it taps into -gcc's extremely portable back-end and large installation base. The D -development team has signed the appropriate documents with FSF and is -pursuing integration of gdc with gcc version 4.8 starting March 2012. -$(WEB https://launchpad.net/~ibuclaw, Iain Buclaw) is leading that -effort.) +Macros: + TITLE=Home + TAG=<$1>$+ + TAG2=<$1 $2>$3 + D=$0 + EXAMPLE=$(TAG2 a, id="a$1-control" class="example-control", )$(TAG2 div, id="a$1" class="example-box", $(RUNNABLE_EXAMPLE $2)) + EXTRA_EXAMPLE= + EXTRA_EXAMPLE_RUNNABLE=$(EXTRA_EXAMPLE $1, $(RUNNABLE_EXAMPLE $+)) + _= + LAYOUT_PREFIX= + LAYOUT_SUFFIX= + $(SCRIPTLOAD $(ROOT_DIR)js/platform-downloads.js, data-latest="$(LATEST)") + LAYOUT_TITLE= + TOUR=$(DIVC item, $(SECTION4 $(LINK2 $1, $(TC i, fa fa-$2 big-icon)$3), $4)) + TOUR=$(DIVC item, $(SECTION4 $(TC i, fa fa-$1 big-icon)$2, $3)) + WHY_D_ICON=$(TC i, fa fa-$1 why-d-icon) + _= + META_DESCRIPTION=D is a general-purpose programming language with static typing, systems-level access, and C-like syntax. + EXTRA_HEADERS=$(T style, + .why-d-icon { + padding-right: 0.2em; + } + .call_to_donate + { + padding: 40px 140px; + } + .call_to_donate h2 + { + text-align: center; + margin: 0 0 20px 0; + } + .call_to_donate p + { + font-size: 14px; + max-width: 1000px; + margin: 20px auto; + } + .call_to_donate .btn + { + font-size: 16px; + padding: 0.6em 1em; + } + a.call_to_donate_btn + { + background-color: #B03931; + border-color: #98312A; + color: white; + } + a.call_to_donate_btn:hover + { + background-color: #742620; + border-color: #98312A; + color: white; + } + #front-testimonial + { + display: inline-block; + padding-top: 15px; + } + #front-testimonial-quote + { + padding-bottom: 10px; + font-size: 16px; + } -) + body#Home #content > .intro #your-code-here + { + padding-left: 1em; + position: relative; + width: 32em; + max-width: 32em; + } -) -) -) + body#Home #content > .intro #your-code-here .tip + { + position: absolute; + top: 0.1em; + right: 0.3em; + z-index: 1; + } + body#Home #content #tools, + body#Home #content > .intro + { + background: #F5F5F5; + } + body#Home #content > h1 + { + margin: 0; + } + body#Home #content > .intro + { + padding: 1em 0 1em; + border-bottom: 1px solid #E6E6E6; + } -$(COMMENT + body#Home #content > .intro > div > div + { + display: table; + width: 100%; + } -$(COMMENT $(AMAZONLINK 0321635361, The D Programming Language book)) - -$(P The K&R of D is here! Get $(AMAZONLINK 0321635361, The D -Programming Language) by Andrei Alexandrescu—the authoritative -source on everything D. From the book's introduction: - -$(BLOCKQUOTE $(AMAZONLINK 0321635361, The D Programming Language) by -Andrei Alexandrescu, D is a language that attempts to consistently do -the right thing within the constraints it chose: system-level access -to computing resources, high performance, and syntactic similarity -with C-derived languages. In trying to do the right thing, D -sometimes stays with tradition and does what other languages do, and -other times it breaks tradition with a fresh, innovative solution. On -occasion that meant revisiting the very constraints that D ostensibly -embraced. For example, large program fragments or indeed entire -programs can be written in a well-defined memory-safe subset of D, -which entails giving away a small amount of system-level access for a -large gain in program debuggability.)) - -$(P D is a multi-paradigm programming language that combines a -principled approach with a focus on practicality. In D you get to -harness the power and high performance of C and C++ and also the -safety and programmer productivity of modern languages such as Ruby -and Python. Special attention is given to the needs of quality -assurance, documentation, portability, and reliability.) - -$(P The D language is statically typed and compiles directly to machine code. -It’s multiparadigm, supporting many programming styles: -imperative, object oriented, and metaprogramming. It’s a member of the C -syntax family, and its appearance is very similar to that of C++. -Here’s a quick list of $(LINK2 comparison.html, features). -) + body#Home #content > .intro > div > div > * + { + display: table-cell; + } -$(P This site does not refer to the first edition of the language, -known as "D version 1" or "D1". Currently, D1 is in maintenance mode -and has documentation available $(LINK2 -http://www.digitalmars.com/d/1.0/index.html,here). We recommend the -current edition of the D programming language (formerly known as "D2") -for new projects. ) - -$(P There are currently three implementations: -$(OL - $(LI Digital Mars dmd for - $(LINK2 dmd-windows.html, Windows), - $(LINK2 dmd-linux.html, x86 Linux), - $(LINK2 dmd-osx.html, Mac OS X), and - $(LINK2 dmd-freebsd.html, x86 FreeBSD). - ) + body#Home #content > .intro .pitch + { + font-size: large; + font-weight: 300; + margin: auto; + width: 22em; + } - $(LI LLVM D Compiler $(LINK2 http://www.dsource.org/projects/ldc, ldc). - ) + body#Home #content > .intro .download + { + margin-top: 3em; + text-align: center; + } -$(COMMENT - $(LI Gnu D compiler $(LINK2 http://dgcc.sourceforge.net/, gdc) - for several platforms, including - $(LINK2 http://gdcwin.sourceforge.net/, Windows) and - $(LINK2 http://gdcmac.sourceforge.net/, Mac OS X) - for D versions 1.030 and 2.014. - ) -) - $(LI Gnu D compiler $(LINK2 http://bitbucket.org/goshawk/gdc/wiki/Home, gdc). - ) + body#Home #content > .intro .download .btn + { + margin: 0 0.3em 0.3em 0.3em; + } - $(COMMENT $(LINK2 http://dnet.codeplex.com/, D.NET compiler) - alpha for .NET for D version 2.) -) -) + body#Home #content > .intro .download .btn.action + { + border-color: #98312A; + background-color: #B03931; + color: white; + } -$(P A large and growing collection of D source code and projects -are at $(LINK2 http://www.dsource.org, dsource). -More links to innumerable D wikis, libraries, tools, media articles, -etc. are at $(LINK2 http://www.digitalmars.com/d/dlinks.html, dlinks). -) + body#Home #content > .intro .download .btn.action:hover + { + border-color: #943029; + background-color: #742620; + color: white; + } -$(COMMENT $(P -This document is available as a -$(LINK2 http://www.prowiki.org/wiki4d/wiki.cgi?LanguageSpecification/PDFArchive, pdf), -as well as in -$(LINK2 http://www.kmonos.net/alang/d/, Japanese) -and -$(LINK2 http://elderane.50webs.com/tuto/d/, Portugese) -translations. -A German book -$(LINK2 http://www.amazon.de/Programmieren-D-Einf%C3%BChrung-neue-Programmiersprache/dp/3939084697/, Programming in D: Introduction to the new Programming Language) -is available, as well as -a Japanese book -$(LINK2 http://www.gihyo.co.jp/books/syoseki-contents.php/4-7741-2208-4, D Language Perfect Guide), -and a Turkish book -$(LINK2 http://ddili.org/ders/d/, D Programlama Dili Dersleri). -)) + body#Home #content > .intro #your-code-here pre + { + margin: 0; + } -$(COMMENT: Japanese by Kazuhiro Inaba, Portugese by Christian Hartung) + body#Home div#news + { + float: right; + width: 252px; + } -$(P This is an example D program illustrating some of the capabilities:) ----- -#!/usr/bin/rdmd -/* shebang is supported */ + body#Home div#forum-summary + { + color: white; + width: 100%; + margin-right: 1em; + } -/* Hello World in D - To compile: - dmd hello.d (or on Unix just make hello.d executable and run it) - or to optimize: - dmd -O -inline -release hello.d -*/ + body#Home div#forum-summary > iframe + { + border: 0; + width: 100%; + height: 210px; + } -import std.stdio; + body#Home .more .boxes, body#Home .more .whyd + { + margin-right: 252px; /* prevent overlapping with #news */ + padding-right: 4em; + } -void main(string[] args) -{ -$(V1 writefln("Hello World, Reloaded");)$(V2 writeln("Hello World, Reloaded");) + body#Home .boxes .item .big-icon + { + padding-right: 0.5em; + } - // auto type inference and built-in foreach - foreach (argc, argv; args) - { - // Object Oriented Programming - auto cl = new CmdLin(argc, argv); - // Improved typesafe printf - writeln(cl.argnum, cl.suffix, " arg: ", cl.argv); - // Automatic or explicit memory management - delete cl; - } + body#Home .whyd .section + { + margin-bottom: 1.5em; + border-left: 5px solid #B03931; + border-radius: 4px; + } + body#Home .whyd .section > div + { + border: 1px solid #E6E6E6; + border-left: none; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + padding: 1.5em; + } + body#Home .whyd .section > div > *:first-child + { + margin-top: 0; + } + body#Home .whyd .section > div > *:last-child + { + margin-bottom: 0; + } - // Nested structs and classes - struct specs - { - // all members automatically initialized - size_t count, allocated; - } + body#Home > .container + { + max-width: none; + padding: 0; + } - // Nested functions can refer to outer - // variables like args - specs argspecs() - { - specs* s = new specs; - // no need for '->' - s.count = args.length; // get length of array with .length - s.allocated = typeof(args).sizeof; // built-in native type properties - foreach (argv; args) - s.allocated += argv.length * typeof(argv[0]).sizeof; - return *s; - } + .org_list_header h3 + { + margin: 1em 0 .5em; + } - // built-in string and common string operations - writefln("argc = %d, " ~ "allocated = %d", - argspecs().count, argspecs().allocated); -} + .org_list + { + max-width: 1400px; + margin: 0 auto; + padding: 20px 0; + + display: flex; + align-items: center; + flex-direction: row; + justify-content: space-evenly; + flex-wrap: wrap; + } -class CmdLin -{ - private size_t _argc; - private string _argv; + .org_list a img + { + max-width: 150px; + max-height: 60px; + } -public: - this(size_t argc, string argv) // constructor - { - _argc = argc; - _argv = argv; - } + .org_list_footer + { + margin-bottom: 3em; + } - size_t argnum() - { - return _argc + 1; - } + .org_list_footer a + { + display: inline-block; + padding: 0; + } + .org_list_footer a:not(:last-child) + { + padding-right: 10px; + } - string argv() - { - return _argv; - } + body#Menu #content li.expand-container a::after + { + content: ""; + } - string suffix() - { - string suffix = "th"; - switch (_argc) - { - case 0: - suffix = "st"; - break; - case 1: - suffix = "nd"; - break; - case 2: - suffix = "rd"; - break; - default: - break; - } - return suffix; - } -} ----- + body#Menu #content li.expand-container ul + { + display: block; + } -$(P $(B Notice:) We welcome feedback about the D compiler or language, but please be explicit about -any claims to intellectual property rights with a copyright or patent notice if you have such for -your contributions. We want D to remain open and free to use, and do not wish to be caught by -someone posting a patch to the compiler, and then later claim compensation for that work.) + /* Narrow layout stage 2: forum/twitter widgets disappear from + the home page, intro pitch and your-code-here layed out vertically */ + @media only screen and (max-width:54em) + { + body#Home #content > .intro > div > div + { + display: block; + width: auto; + } + + body#Home #content > .intro > div > div > * + { + display: block; + } + + body#Home #content > .intro .pitch + { + max-width: 22em; + width: auto; + } + + body#Home #content > .intro #your-code-here + { + padding: 0; + margin: auto; + margin-top: 2em; + } + + body#Home #news + { + display: none; + } + + body#Home .more .boxes, body#Home .more .whyd + { + margin-right: 0; + padding-right: 0; + } + + .org_list a img + { + padding: 1em 2em; + } + + .call_to_donate + { + padding: 40px 80px; + } + } -) + /* Narrow layout stage 3: no more two column boxes */ + @media only screen and (max-width: 40em) + { + body#Home #content > .intro #your-code-here + { + /* change width to max-width */ + width: auto; + max-width: 32em; + } + + body#Home #content > .intro #your-code-here .tip { + display: none; + } + + #your-code-here-select-example select { + width: 100%; + } + + .call_to_donate + { + padding: 5px; + } + .call_to_donate .call_to_donate_btn + { + margin-bottom: 0.75em; + } + } -Macros: - TITLE=Home - WIKI=Intro - TAG=<$1>$+ - TAG2=<$1 $2>$3 - WEB=$(LINK2 http://$1,$2) - WEBX=$(LINK2 http://$1,$2) - D=$0 - EXAMPLE= - - -$(TAG2 div, id="a$1" class="answer-nojs", $2) - - LAYOUT= - -
    - - -
    -
    - $(PAGE_TOOLS) - $3 -
    + ) + $(COMMENT index.html only for now, until we can figure out + how to generate a URL to the current page for og:url) + + + + + diff --git a/install.dd b/install.dd new file mode 100644 index 0000000000..234897511e --- /dev/null +++ b/install.dd @@ -0,0 +1,399 @@ +Ddoc + + +$(D_S $(TITLE), + +$(H2 Introduction) + +The $(LINK2 https://dlang.org/install.sh, `dlang.org/install.sh`) script is the +official D compiler version manager. It supports DMD, GDC and LDC on FreeBSD, +Linux, macOS and Windows (although not every combination is available). It +provides a convenient way to fetch and install a D compiler, and switch between +installed versions, without requiring administrative privileges. + +Its features include: + +$(UL + $(LI Maintaining one or more portable compiler installations in a directory of choice + (default `~/dlang` on POSIX, `%USERPROFILE%/dlang` on Windows).) + $(LI Maintaining the latest stable version of the D package manager, $(LINK2 http://code.dlang.org/docs/commandline, `dub`).) + $(LI Self-updating via `install.sh update`.) + $(LI Supporting nested activation of compilers. Activating a compiler will set + up the relevant environment variables, and offer means to revert the + modified variables to their prior values.) + $(LI Supporting the Fish shell, in addition to Bash-compatible shells.) + $(LI Verifying binary signatures via the $(LINK2 $(ROOT_DIR)gpg_keys.html,D keyring) (automatic if `gpg` is installed)) + $(LI For `dmd`, installation of the following versions is supported: + $(UL + $(LI `dmd` - latest stable version) + $(LI `dmd-beta` - latest beta version) + $(LI `dmd-nightly` - the latest nightly release) + $(LI `dmd-` - specific official release (including beta releases)) + $(LI `dmd-branch` - experimental compiler branches) + ) + ) + $(LI For `ldc`, installation of the following versions is supported: + $(UL + $(LI `ldc` - latest stable version) + $(LI `ldc-beta` - latest beta version) + $(LI `ldc-latest-ci` - latest build version (built on every commit to master by CIs)) + $(LI `ldc-` - specific official release (including beta releases)) + ) + ) + $(LI For `gdc`, installation of the following versions is supported: + $(UL + $(LI `gdc` - latest stable version, Linux only) + ) + ) + $(LI For `dub`, installation of the following versions is supported: + $(UL + $(LI `dub` - latest stable version) + $(LI `dub-` - specific official release (including beta releases)) + ) + ) + $(LI For all compilers optionally installing a different version to the bundled dub is supported: + $(UL + $(LI `,dub` - selected compiler and latest stable DUB version) + $(LI `,dub-` - selected compiler and a specific stable DUB version) + ) + ) +) + +$(H3 Content) + +$(UL + $(LI $(RELATIVE_LINK2 get, Downloading the installer)) + $(UL + $(LI $(RELATIVE_LINK2 get_posix, On FreeBSD, Linux and macOS)) + $(LI $(RELATIVE_LINK2 get_windows, On Windows)) + $(UL + $(LI $(RELATIVE_LINK2 get_git, Using Git BASH)) + $(LI $(RELATIVE_LINK2 get_msys, Using MSYS BASH)) + ) + ) + $(LI $(RELATIVE_LINK2 usage, Usage)) + $(UL + $(LI $(RELATIVE_LINK2 install, Installation)) + $(LI $(RELATIVE_LINK2 activate, Activation)) + $(UL + $(LI $(RELATIVE_LINK2 activate_posix, On POSIX)) + $(LI $(RELATIVE_LINK2 activate_windows, On Windows)) + ) + $(LI $(RELATIVE_LINK2 uninstall, Uninstallation)) + $(LI $(RELATIVE_LINK2 list, Listing available compilers)) + $(LI $(RELATIVE_LINK2 update, Update)) + $(LI $(RELATIVE_LINK2 get-path, Get compiler executable path)) + ) +) + +$(H2 $(LNAME2 get, Downloading the installer)) + +$(UL + $(LI $(RELATIVE_LINK2 get_posix, On FreeBSD, Linux and macOS)) + $(LI $(RELATIVE_LINK2 get_windows, On Windows)) + $(UL + $(LI $(RELATIVE_LINK2 get_git, Using Git BASH)) + $(LI $(RELATIVE_LINK2 get_msys, Using MSYS BASH)) + ) +) + +$(H3 $(LNAME2 get_posix, Downloading on FreeBSD, Linux and macOS)) + +$(CONSOLE +mkdir -p ~/dlang && wget https://dlang.org/install.sh -O ~/dlang/install.sh +) + +Alternatively, the script can be invoked directly: + +$(CONSOLE +curl https://dlang.org/install.sh | bash -s +) + +In this case the installer makes a copy of itself at `~/dlang/install.sh`. +If no arguments are provided, the latest DMD compiler will be installed. + +$(H3 $(LNAME2 get_windows, Downloading on Windows)) + +The instructions above work unaltered when using a POSIX-like environment on +Windows, such as Cygwin or MSYS2, but then compilers are installed inside that +environment. For better integration with a typical Windows development +environment, you may follow the instructions below instead, which makes +compilers available from the Windows Command Prompt. + +$(CONSOLE +mkdir %USERPROFILE%\dlang +powershell.exe -Command "wget https://dlang.org/install.sh -OutFile %USERPROFILE%\dlang\install.sh" +) + +The script is interpreted by `bash.exe`, which comes as part of MSYS2 as well +as Git for Windows. The following two sections provide two alternatives for +defining `%BASH%` so that the POSIX-tailored examples further down will work +from the Windows command prompt by replacing "`~/dlang/install.sh`" with +"`%BASH% %USERPROFILE%\dlang\install.sh`". With either one of these +alternatives, this will work: + +$(CONSOLE +%BASH% %USERPROFILE%\dlang\install.sh --help +) + +$(H4 $(LNAME2 get_git, Using Git BASH)) + +Download and install $(LINK2 https://gitforwindows.org/, Git for Windows) to +"`C:\Program Files\Git`" and $(LINK2 https://www.7-zip.org/, 7-Zip) to +"`C:\Program Files\7-Zip`". `7z.exe` needs to be in the `PATH`: + +$(CONSOLE +set PATH=%PATH%;C:\Program Files\7-Zip +set BASH="\Program Files\Git\usr\bin\bash.exe" +) + +$(H4 $(LNAME2 get_msys, Using MSYS BASH)) + +Follow the $(LINK2 https://www.msys2.org, installation instructions for MSYS2). +We'll assume MSYS2 is now available in `C:\msys64`, which is the default for +the 64-bit installer. This will install the necessary decompression tools: + +$(CONSOLE +C:\msys64\usr\bin\pacman.exe --sync unzip p7zip +set BASH=C:\msys64\usr\bin\bash.exe +) + + +$(H2 $(LNAME2 usage, Usage)) + +$(CONSOLE +~/dlang/install.sh [<command>] [<args>] +) + +$(UL + $(LI $(RELATIVE_LINK2 install, Installation)) + $(LI $(RELATIVE_LINK2 activate, Activation)) + $(UL + $(LI $(RELATIVE_LINK2 activate_posix, On POSIX)) + $(LI $(RELATIVE_LINK2 activate_windows, On Windows)) + ) + $(LI $(RELATIVE_LINK2 uninstall, Uninstallation)) + $(LI $(RELATIVE_LINK2 list, Listing available compilers)) + $(LI $(RELATIVE_LINK2 update, Update)) + $(LI $(RELATIVE_LINK2 get-path, Get compiler executable path)) +) + +$(H3 $(LNAME2 global_options, Global options)) + +$(DL + $(DT + $(SWITCH $(SWNAME -p) $(SWNAME --path), + Changes the install location (default `~/dlang` on POSIX, `%USERPROFILE/dlang` on Windows)) + $(SWITCH $(SWNAME -v), + Produces more verbose output) + $(SWITCH $(SWNAME -h), + Displays a help page) + ) +) + +$(H3 $(LNAME2 install, Install)) + +$(CONSOLE +~/dlang/install.sh install <compiler> +) + +Download and install a D compiler. +By default the latest release of the DMD compiler is selected. + +$(H4 Options) + +$(DL + $(DT + $(SWITCH $(SWNAME -a) $(SWNAME --activate), + Prints the path to the activate script) + $(SWITCH $(SWNAME dmd|ldc|gdc), + Installs the latest version of a compiler) + $(SWITCH $(SWNAME dmd|ldc|gdc-<version>), + Installs a specific version of a compiler (e.g. dmd-2.071.1, ldc-1.1.0-beta2)) + $(SWITCH $(SWNAME dmd|ldc-beta), + Installs the latest beta version of a compiler) + $(SWITCH $(SWNAME dmd-nightly), + Installs DMD nightly) + $(SWITCH $(SWNAME dmd-2017-02-10), + Installs specific DMD nightly) + $(SWITCH $(SWNAME dub), + Installs the latest version of a dub) + $(SWITCH $(SWNAME dub-<version>), + Installs a specific version of a dub (e.g. dub.1.23.0)) + $(SWITCH $(SWNAME <compiler>,<dub>), + Installs a version of compiler and a version of dub. + All compiler and version strings listed above are supported. + ) + ) +) + +$(EXAMPLES +~/dlang/install.sh +~/dlang/install.sh dmd +~/dlang/install.sh install dmd +~/dlang/install.sh install dmd-2.071.1 +~/dlang/install.sh install ldc-1.1.0-beta2 +~/dlang/install.sh install dmd-beta +~/dlang/install.sh install dmd-nightly +) + +By default, the `dub` binary bundled in the compiler installation will be exposed. +Optionally, a different dub version can be installed standalone or as part of the compiler +installation: + +$(EXAMPLES +~/dlang/install.sh install dub +~/dlang/install.sh install dub-1.22.0 +~/dlang/install.sh install dmd-2.071.1,dub-1.23.0 +~/dlang/install.sh install ldc-1.23.0,dub +) + +An installed compiler can be used directly, but the exact path varies between +compiler vendors: + +$(CONSOLE +~/dlang/<installed-dmd-compiler>/bin64/dmd +~/dlang/<installed-ldc-compiler>/ldc2 +) + +Therefore it is recommended to $(RELATIVE_LINK2 activate, activate) a compiler +after installation. For scripting needs the path to compiler executable can be +queried with [`get-path`](#get-path). + +$(H3 $(LNAME2 activate, Activate)) + +Once a compiler is installed, it can be activated for the current session. +Supplying the `-a` or `--activate` option to the `install` command will print +the path to the appropriate activation script: either a +$(RELATIVE_LINK2 activate_posix, shell script) or a +$(RELATIVE_LINK2 activate_windows, Windows batch file). + +$(H4 $(LNAME2 activate_posix, In POSIX environments)) + +$(CONSOLE +~/dlang/install.sh install <compiler> -a +) + +This will show where to find the `activate` script (or `activate.fish` for +users of the $(LINK2 https://fishshell.com, Fish shell).) The script should be +executed $(I in the current shell): + +$(CONSOLE +source ~/dlang/<installed-compiler>/activate +) + +This will set up the `PATH`, `LIBRARY_PATH`, `LD_LIBRARY_PATH`, `DMD`, `DC`, +and `PS1` environment variables. +It's also possible to combine this into one command: + +$(CONSOLE +source $(DOLLAR)(~/dlang/install.sh dmd -a) +) + +The activated compiler can be removed from the current session by restoring +the previous environment: + +$(CONSOLE +deactivate +) + +$(H4 $(LNAME2 activate_windows, On the Windows command line)) + +$(CONSOLE +%BASH% %USERPROFILE%\dlang\install.sh install <compiler> -a +) + +This will show where to find the `activate.bat` file. Calling it will change +the `PATH` environment variable, and show how to restore its prior value. + +$(CONSOLE +%USERPROFILE%\dlang$(BACKSLASH)<installed-compiler>\activate.bat +) + +To install and activate `%COMPILER%` in a batch file, this will do: + +$(CONSOLE +set INSTALL=%BASH% %USERPROFILE%\dlang\install.sh install %COMPILER% +%INSTALL% +for /f "usebackq tokens=*" %%a in (`%INSTALL% -a`) do call %%a +) + +$(H3 $(LNAME2 get-path, Get compiler executable path)) + +$(CONSOLE +~/dlang/install.sh get-path <compiler> +) + +Returns the path to the selected compiler executable. +The command fails if the compiler is not installed locally and `--install` +hasn't been passed. + +$(H4 Options) + +$(DL + $(DT + $(SWITCH $(SWNAME --dmd), + Prints the path to the DMD-alike executable) + $(SWITCH $(SWNAME --dub), + Prints the path to the DUB executable) + $(SWITCH $(SWNAME --install), + Installs the compiler if it is not installed) + ) +) + +$(EXAMPLES +$ ~/dlang/install.sh get-path dmd +/home/user/dlang/dmd-2.094.0/linux/bin64/dmd +$ ~/dlang/install.sh get-path dmd-2.093.0 --install +/home/user/dlang/dmd-2.093.0/linux/bin64/dmd +$ ~/dlang/install.sh get-path ldc-1.23.0 +/home/user/dlang/ldc-1.23.0/bin/ldc2 +$ ~/dlang/install.sh get-path --dmd ldc-1.23.0 +/home/user/dlang/ldc-1.23.0/bin/ldmd2 +$ ~/dlang/install.sh get-path --dub ldc-1.23.0 +/home/user/dlang/ldc-1.23.0/bin/dub +$ ~/dlang/install.sh get-path --dub dub-1.21.0 +/home/user/dlang/dub-1.21.0/bin/dub +$ ~/dlang/install.sh get-path --dub ldc-1.23.0,dub-1.21.0 +/home/user/dlang/dub-1.21.0/bin/dub +) + +$(H3 $(LNAME2 uninstall, Uninstall)) + +Uninstall a D compiler. + +$(CONSOLE +~/dlang/install.sh uninstall <compiler> +) + +$(EXAMPLES +~/dlang/install.sh uninstall dmd +~/dlang/install.sh uninstall dmd-2.071.1 +~/dlang/install.sh uninstall ldc-1.1.0-beta2 +) + +$(H3 $(LNAME2 list, List)) + +List all installed D compilers. + +$(CONSOLE +~/dlang/install.sh list +) + +$(H3 $(LNAME2 update, Update)) + +Update the installer itself and the keyring. + +$(CONSOLE +~/dlang/install.sh update +) + +) +Macros: + TITLE=Install.sh script + SWNAME=$(LNAME2 switch$1, $(B $1)) + SWLINK=$(LINK2 #switch$1, $(B $1)) + SWITCH=$(DT $1)$(DD $+) + EXAMPLES=$(H4 Examples)$(CONSOLE $0) + SUBNAV=$(SUBNAV_CLI_REFERENCE) + BACKSLASH = \ diff --git a/interface.dd b/interface.dd deleted file mode 100644 index 015241d0f0..0000000000 --- a/interface.dd +++ /dev/null @@ -1,307 +0,0 @@ -Ddoc - -$(SPEC_S Interfaces, - -$(GRAMMAR -$(GNAME InterfaceDeclaration): - $(B interface) $(I Identifier) $(GLINK BaseInterfaceList)$(OPT) $(GLINK InterfaceBody) - $(GLINK2 template, InterfaceTemplateDeclaration) - -$(GNAME BaseInterfaceList): - $(B :) $(GLINK2 class, InterfaceClasses) - -$(GNAME InterfaceBody): - $(B {) $(GLINK2 module, DeclDefs)$(OPT) $(B }) -) - - $(P Interfaces describe a list of functions that a class that inherits - from the interface must implement. - A class that implements an interface can be converted to a reference - to that interface.) - - $(P Some operating system objects, like COM/OLE/ActiveX for Win32, - have specialized interfaces. D interfaces that are compatible with - COM/OLE/ActiveX are called $(LINK2 #COM-Interfaces, $(I COM Interfaces)). - ) - -$(V2 - $(P $(LINK2 #CPP-Interfaces, $(I C++ Interfaces)) are another - form of interfaces, meant to be binary compatible with C++. - ) -) - - $(P Interfaces cannot derive from classes; only from other interfaces. - Classes cannot derive from an interface multiple times. - ) - ------- -interface D -{ - void foo(); -} - -class A : D, D // error, duplicate interface -{ -} ------- - - An instance of an interface cannot be created. - - ------- -interface D -{ - void foo(); -} - -... - -D d = new D(); // error, cannot create instance of interface ------- - -$(V1 - $(P Interface member functions do not have implementations.) - ------- -interface D -{ - void bar() { } // error, implementation not allowed -} ------- -) -$(V2 - $(P Virtual interface member functions do not have implementations. - Interfaces are expected to implement static or final functions. - ) - ------- -interface D -{ - void bar() { } // error, implementation not allowed - static void foo() { } // ok - final void abc() { } // ok -} ------- - - $(P Classes that inherit from an interface may not override final or - static interface member functions.) - ------- -interface D { - void bar(); - static void foo() { } - final void abc() { } -} - -class C : D { - void bar() { } // ok - void foo() { } // error, cannot override static D.foo() - void abc() { } // error, cannot override final D.abc() -} ------- - -) - $(P All interface functions must be defined in a class that inherits - from that interface: - ) ------- -interface D -{ - void foo(); -} - -class A : D -{ - void foo() { } // ok, provides implementation -} - -class B : D -{ - int foo() { } // error, no void foo() implementation -} ------- - - Interfaces can be inherited and functions overridden: - ------- -interface D -{ - int foo(); -} - -class A : D -{ - int foo() { return 1; } -} - -class B : A -{ - int foo() { return 2; } -} - -... - -B b = new B(); -b.foo(); // returns 2 -D d = cast(D) b; // ok since B inherits A's D implementation -d.foo(); // returns 2; ------- - - $(P Interfaces can be reimplemented in derived classes:) - ------- -interface D -{ - int foo(); -} - -class A : D -{ - int foo() { return 1; } -} - -class B : A, D -{ - int foo() { return 2; } -} - -... - -B b = new B(); -b.foo(); // returns 2 -D d = cast(D) b; -d.foo(); // returns 2 -A a = cast(A) b; -D d2 = cast(D) a; -d2.foo(); // returns 2, even though it is A's D, not B's D ------- - - $(P A reimplemented interface must implement all the interface - functions, it does not inherit them from a super class: - ) - ------- -interface D -{ - int foo(); -} - -class A : D -{ - int foo() { return 1; } -} - -class B : A, D -{ -} // error, no foo() for interface D ------- - -$(V2 -$(SECTION2 $(LNAME2 InterfaceContracts, Interfaces with Contracts), - - $(P Interface member functions can have contracts even though there - is no body for the function. The contracts are inherited by any - class member function that implements that interface member function. - ) - ---- -interface I -{ - int foo(int i) - in { assert(i > 7); } - out (result) { assert(result & 1); } - - void bar(); -} ---- -) - -$(SECTION2 $(LNAME2 ConstInterface, Const and Immutable Interfaces), - $(P If an interface has $(CODE const) or $(CODE immutable) storage - class, then all members of the interface are - $(CODE const) or $(CODE immutable). - This storage class is not inherited. - ) -) -) - -$(SECTION2 $(LNAME2 COM-Interfaces, COM Interfaces), - - $(P A variant on interfaces is the COM interface. A COM interface is - designed to map directly onto a Windows COM object. Any COM object - can be represented by a COM interface, and any D object with - a COM interface can be used by external COM clients. - ) - - $(P A COM interface is defined as one that derives from the interface - $(D std.c.windows.com.IUnknown). A COM interface differs from - a regular D interface in that: - ) - - $(UL - $(LI It derives from the interface $(D std.c.windows.com.IUnknown).) - $(LI It cannot be the argument of a $(I DeleteExpression).) - $(LI References cannot be upcast to the enclosing class object, nor - can they be downcast to a derived interface. To accomplish this, - an appropriate $(D QueryInterface()) would have to be implemented - for that interface in standard COM fashion.) - $(LI Classes derived from COM interfaces are COM classes.) - $(LI The default linkage for member functions of COM classes - is $(D extern(System)).) - $(LI The first member of the $(D vtbl[]) is not the pointer - to the InterfaceInfo, but the first virtual function pointer.) - ) -) - -$(V2 -$(SECTION2 $(LNAME2 CPP-Interfaces, C++ Interfaces), - - $(P C++ interfaces are interfaces declared with C++ linkage: - ) - ---- -extern (C++) interface Ifoo -{ - void foo(); - void bar(); -} ---- - - $(P which is meant to correspond with the following C++ declaration:) - -$(CPPCODE -class Ifoo -{ - virtual void foo(); - virtual void bar(); -}; -) - - $(P Any interface that derives from a C++ interface is also - a C++ interface. - A C++ interface differs from a D interface in that: - ) - - $(UL - $(LI It cannot be the argument of a $(I DeleteExpression).) - $(LI References cannot be upcast to the enclosing class object, nor - can they be downcast to a derived interface.) - $(LI The C++ calling convention is the default convention - for its member functions, rather than the D calling convention.) - $(LI The first member of the $(D vtbl[]) is not the pointer - to the $(D Interface), but the first virtual function pointer.) - ) - - $(P For more information, see - $(LINK2 http://lunesu.com/uploads/ModernCOMProgramminginD.pdf, Modern COM Programming in D) - ) -) -) - -) - -Macros: - TITLE=Interfaces - WIKI=Interface - CATEGORY_SPEC=$0 - diff --git a/interfaceToC.dd b/interfaceToC.dd deleted file mode 100644 index 4feaaf7bd3..0000000000 --- a/interfaceToC.dd +++ /dev/null @@ -1,481 +0,0 @@ -Ddoc - -$(SPEC_S Interfacing to C, - - $(P D is designed to fit comfortably with a C compiler for the target - system. D makes up for not having its own VM by relying on the - target environment's C runtime library. It would be senseless to - attempt to port to D or write D wrappers for the vast array of C APIs - available. How much easier it is to just call them directly. - ) - - $(P This is done by matching the C compiler's data types, layouts, - and function call/return sequences. - ) - -

    Calling C Functions

    - - $(P C functions can be called directly from D. There is no need for - wrapper functions, argument swizzling, and the C functions do not - need to be put into a separate DLL. - ) - - $(P The C function must be declared and given a calling convention, - most likely the "C" calling convention, for example: - ) - ------- -extern (C) int strcmp(char* string1, char* string2); ------- - - $(P and then it can be called within D code in the obvious way:) - ------- -import std.string; -int myDfunction(char[] s) { - return strcmp(std.string.toStringz(s), "foo"); -} ------- - - $(P There are several things going on here:) - - $(UL - $(LI D understands how C function names are "mangled" and the - correct C function call/return sequence.) - - $(LI C functions cannot be overloaded with another C function - with the same name.) - - $(LI There are no __cdecl, __far, __stdcall, - $(LINK2 http://www.digitalmars.com/ctg/ctgLanguageImplementation.html#declspec, __declspec), - or other such C - $(LINK2 http://www.digitalmars.com/ctg/ctgLanguageImplementation.html#extended, extended type modifiers) - in D. These are handled by - $(LINK2 $(WEBURL)attribute.html#linkage, linkage attributes), - such as $(D extern (C)).) - - $(LI There are no const or volatile type modifiers in D. To declare - a C function that uses those type modifiers, just drop those - keywords from the declaration.) - - $(LI Strings are not 0 terminated in D. See "Data Type Compatibility" - for more information about this. However, string literals in D are - 0 terminated.) - - ) - - $(P C code can correspondingly call D functions, if the D functions - use an attribute that is compatible with the C compiler, most likely - the extern (C):) - ------- -// myfunc() can be called from any C function -extern (C) { - void myfunc(int a, int b) { - ... - } -} ------- - -

    Storage Allocation

    - - $(P C code explicitly manages memory with calls to - $(LINK2 http://www.digitalmars.com/rtl/stdlib.html#malloc, malloc()) and - $(LINK2 http://www.digitalmars.com/rtl/stdlib.html#free, free()). - D allocates memory using the D garbage collector, - so no explicit free's are necessary. - ) - - $(P D can still explicitly allocate memory using std.c.stdlib.malloc() - and std.c.stdlib.free(), these are useful for connecting to C - functions that expect malloc'd buffers, etc. - ) - - $(P If pointers to D garbage collector allocated memory are passed to - C functions, it's critical to ensure that that memory will not - be collected by the garbage collector before the C function is - done with it. This is accomplished by: - ) - - $(UL - - $(LI Making a copy of the data using std.c.stdlib.malloc() and passing - the copy instead.) - - $(LI Leaving a pointer to it on the stack (as a parameter or - automatic variable), as the garbage collector will scan the stack.) - - $(LI Leaving a pointer to it in the static data segment, as the - garbage collector will scan the static data segment.) - - $(LI Registering the pointer with the garbage collector with the - $(V1 std.gc.addRoot()) - $(V2 $(LINK2 $(WEBURL)phobos/core_memory.html#addRoot, std.gc.addRoot())) - or - $(V1 std.gc.addRange()) - $(V2 $(LINK2 $(WEBURL)phobos/core_memory.html#addRange, std.gc.addRange())) - calls.) - - ) - - $(P An interior pointer to the allocated memory block is sufficient - to let the GC - know the object is in use; i.e. it is not necessary to maintain - a pointer to the beginning of the allocated memory. - ) - - $(P The garbage collector does not scan the stacks of threads not - created by the D Thread interface. Nor does it scan the data - segments of other DLL's, etc. - ) - -

    Data Type Compatibility

    - - $(TABLE2 D And C Type Equivalence, - - $(TR DC) - $(TR $(TH 32 bit) $(TH 64 bit)) - - $(TR - $(TD $(B void)) - $(TD2 $(B void)) - ) - - $(TR - $(TD $(B byte)) - $(TD2 $(B signed char)) - ) - - $(TR - $(TD $(B ubyte)) - $(TD2 $(B unsigned char)) - ) - - $(TR - $(TD $(B char)) - $(TD2 $(B char) (chars are unsigned in D)) - ) - - $(TR - $(TD $(B wchar)) - $(TD2 $(B wchar_t) (when sizeof(wchar_t) is 2)) - ) - - $(TR - $(TD $(B dchar)) - $(TD2 $(B wchar_t) (when sizeof(wchar_t) is 4)) - ) - - $(TR - $(TD $(B short)) - $(TD2 $(B short)) - ) - - $(TR - $(TD $(B ushort)) - $(TD2 $(B unsigned short)) - ) - - $(TR - $(TD $(B int)) - $(TD2 $(B int)) - ) - - $(TR - $(TD $(B uint)) - $(TD2 $(B unsigned)) - ) - -$(V1 - $(TR - $(TD $(B long)) - $(TD $(B long long)) - $(TD $(B long)) - ) - - $(TR - $(TD $(B ulong)) - $(TD $(B unsigned long long)) - $(TD $(B unsigned long)) - ) -) - -$(V2 - $(TR - $(TD $(B c_long (in core.stdc.config))) - $(TD $(B long)) - $(TD $(B long)) - ) - - $(TR - $(TD $(B c_ulong (in core.stdc.config))) - $(TD $(B unsigned long)) - $(TD $(B unsigned long)) - ) - - $(TR - $(TD $(B long)) - $(TD $(B long long)) - $(TD $(B long (or long long))) - ) - - $(TR - $(TD $(B ulong)) - $(TD $(B unsigned long long)) - $(TD $(B unsigned long (or unsigned long long))) - ) -) - $(TR - $(TD $(B float)) - $(TD2 $(B float)) - ) - - $(TR - $(TD $(B double)) - $(TD2 $(B double)) - ) - - $(TR - $(TD $(B real)) - $(TD2 $(B long double)) - ) -$(V1 - $(TR - $(TD $(B ifloat)) - $(TD2 $(B float _Imaginary)) - ) - - $(TR - $(TD $(B idouble)) - $(TD2 $(B double _Imaginary)) - ) - - $(TR - $(TD $(B ireal)) - $(TD2 $(B long double _Imaginary)) - ) - - $(TR - $(TD $(B cfloat)) - $(TD2 $(B float _Complex)) - ) - - $(TR - $(TD $(B cdouble)) - $(TD2 $(B double _Complex)) - ) - - $(TR - $(TD $(B creal)) - $(TD2 $(B long double _Complex)) - ) -) - $(TR - $(TD $(B struct)) - $(TD2 $(B struct)) - ) - - $(TR - $(TD $(B union)) - $(TD2 $(B union)) - ) - - $(TR - $(TD $(B enum)) - $(TD2 $(B enum)) - ) - - $(TR - $(TD $(B class)) - $(TD2 no equivalent) - ) - - $(TR - $(TD $(I type)$(B *)) - $(TD2 $(I type) $(B *)) - ) - - $(TR - $(TD $(I type)$(B [)$(I dim)$(B ])) - $(TD2 $(I type)$(B [)$(I dim)$(B ])) - ) - - $(TR - $(TD $(I type)$(B [)$(I dim)$(B ]*)) - $(TD2 $(I type)$(B (*)[)$(I dim)$(B ])) - ) - - $(TR - $(TD $(I type)$(B [])) - $(TD2 no equivalent) - ) - - $(TR - $(TD $(I type)$(B [)$(I type)$(B ])) - $(TD2 no equivalent) - ) - - $(TR - $(TD $(I type) $(B function)$(B $(LPAREN))$(I parameters)$(B $(RPAREN))) - $(TD2 $(I type)$(B (*))$(B $(LPAREN))$(I parameters)$(B $(RPAREN))) - ) - - $(TR - $(TD $(I type) $(B delegate)$(B $(LPAREN))$(I parameters)$(B $(RPAREN))) - $(TD2 no equivalent) - ) - - $(TR - $(TD $(B size_t)) - $(TD2 $(B size_t)) - ) - - $(TR - $(TD $(B ptrdiff_t)) - $(TD2 $(B ptrdiff_t)) - ) - - ) - - $(P These equivalents hold for most C compilers. The C standard - does not pin down the sizes of the types, so some care is needed. - ) - -$(V2 -

    Passing D Array Arguments to C Functions

    - - $(P In C, arrays are passed to functions as pointers even if the function - prototype says its an array. In D, static arrays are passed by value, - not by reference. Thus, the function prototype must be adjusted to match - what C expects.) - - $(TABLE2 D And C Function Prototype Equivalence, - - $(TR - $(TH D type) - $(TH C type) - ) - - $(TR - $(TD $(I T)$(B *)) - $(TD $(I T)$(B [])) - ) - - $(TR - $(TD $(B ref) $(I T)$(B [)$(I dim)$(B ])) - $(TD $(I T)$(B [)$(I dim)$(B ])) - ) - - ) - - $(P For example:) - -$(CCODE -void foo(int a[3]) { ... } // C code -) ---- -extern (C) -{ - void foo(ref int[3] a); // D prototype -} ---- -) - -

    Calling printf()

    - - $(P This mostly means checking that the - $(LINK2 http://www.digitalmars.com/rtl/stdio.html#printf, printf format specifier) - matches the corresponding D data type. - Although printf is designed to handle 0 terminated strings, - not D dynamic arrays of chars, it turns out that since D - dynamic arrays are a length followed by a pointer to the data, - the $(D %.*s) format works: - ) - ------- -void foo(char[] string) { - printf("my string is: %.*s\n", string.length, string.ptr); -} ------- - - $(P The $(CODE printf) format string literal - in the example doesn't end with $(CODE '\0'). - This is because string literals, - when they are not part of an initializer to a larger data structure, - have a $(CODE '\0') character helpfully stored after the end of them. - ) - - $(P An improved D function for formatted output is - $(CODE std.stdio.writef()). - ) - -

    Structs and Unions

    - - $(P D structs and unions are analogous to C's. - ) - - $(P C code often adjusts the alignment and packing of struct members - with a command line switch or with various implementation specific - #pragma's. D supports explicit alignment attributes that correspond - to the C compiler's rules. Check what alignment the C code is using, - and explicitly set it for the D struct declaration. - ) - - $(P D does not support bit fields. If needed, they can be emulated - with shift and mask operations, - or use the $(LINK2 phobos/std_bitmanip.html#bitfields, std.bitmanip.bitfields) - library type. - $(DPLLINK htod.html, htod) will convert bit fields to inline functions that - do the right shift and masks. - ) - -

    $(LNAME2 Using C Libraries, Using Existing C Libraries)

    - - $(P Since D can call C code directly, it can also call any C library - functions, giving D access to the smorgasbord of existing C libraries. - To do so, however, one needs to write a D interface (.di) file, which - is a translation of the C .h header file for the C library into D. - ) - - $(P For popular C libraries, the first place to look for the corresponding - D interface file is the $(LINK2 https://github.com/D-Programming-Deimos/, Deimos Project). - If it isn't there already, and you write one, please contribute it - to the Deimos Project. - ) - -

    $(LNAME2 C Globals, Accessing C Globals)

    - - $(P C globals can be accessed directly from D. C globals have the C naming - convention, and so must be in an $(D extern (C)) block. - Use the $(D extern) storage class to indicate that the global is allocated - in the C code, not the D code. - $(V2 C globals default to being in global, not thread local, storage. - To reference global storage - from D, use the $(D __gshared) storage class.) - ) - ---- -extern (C) extern __gshared int x; ---- - -$(V1 -
    -

    Interfacing to C++

    - - $(P D does not provide an interface to C++, other than - through $(DPLLINK COM.html, COM programming). Since D, however, - interfaces directly to C, it can interface directly to - C++ code if it is declared as having C linkage. - ) - - $(P D class objects are incompatible with C++ class objects. - ) -) - -) - -Macros: - TD2=$0 - TITLE=Interfacing to C - WIKI=InterfaceToC - diff --git a/intro.dd b/intro.dd deleted file mode 100644 index 254aac152f..0000000000 --- a/intro.dd +++ /dev/null @@ -1,77 +0,0 @@ -Ddoc - -$(SPEC_S Introduction, - - $(P The D programming language is a general purpose systems programming language. - To that end, a D program is a collection of modules that can be compiled separately - to native code that is combined with libraries and compiled C code by a linker to create a - native executable. - ) - -

    Phases of Compilation

    - - The process of compiling is divided into multiple phases. Each phase - has no dependence on subsequent phases. For example, the scanner is - not perturbed by the semantic analyzer. This separation of the passes - makes language tools like syntax - directed editors relatively easy to produce. - It also is possible to compress D source by storing it in - $(SINGLEQUOTE tokenized) form. - -$(OL - $(LI $(B source character set)$(BR) - - The source file is checked to see what character set it is, - and the appropriate scanner is loaded. ASCII and UTF - formats are accepted. - ) - - $(LI $(B script line) $(BR) - - If the first line starts with $(GREEN #!) then the first line - is ignored. - ) - - $(LI $(B lexical analysis)$(BR) - - The source file is divided up into a sequence of tokens. - $(DDSUBLINK lex, specialtokens, Special tokens)) - are replaced with other tokens. - $(GLINK2 lex, SpecialTokenSequence)s - are processed and removed. - ) - - $(LI $(B syntax analysis)$(BR) - - The sequence of tokens is parsed to form syntax trees. - ) - - $(LI $(B semantic analysis)$(BR) - - The syntax trees are traversed to declare variables, load symbol tables, assign - types, and in general determine the meaning of the program. - ) - - $(LI $(B optimization)$(BR) - - Optimization is an optional pass that tries to rewrite the program - in a semantically equivalent, but faster executing, version. - ) - - $(LI $(B code generation)$(BR) - - Instructions are selected from the target architecture to implement - the semantics of the program. The typical result will be - an object file, suitable for input to a linker. - ) -) - - - -) - -Macros: - TITLE=Introduction - WIKI=SpecIntro - CATEGORY_SPEC=$0 - diff --git a/js/codemirror-compressed.js b/js/codemirror-compressed.js new file mode 100644 index 0000000000..69ce1d04da --- /dev/null +++ b/js/codemirror-compressed.js @@ -0,0 +1,15 @@ +/* CodeMirror - Minified & Bundled + Generated on 1/19/2016 with http://codemirror.net/doc/compress.html + Version: 5.10 + + CodeMirror Library: + - codemirror.js + Modes: + - d.js + */ + +!function(a){if("object"==typeof exports&&"object"==typeof module)module.exports=a();else{if("function"==typeof define&&define.amd)return define([],a);(this||window).CodeMirror=a()}}(function(){"use strict";function x(a,b){if(!(this instanceof x))return new x(a,b);this.options=b=b?mg(b):{},mg(Dd,b,!1),K(b);var c=b.value;"string"==typeof c&&(c=new df(c,b.mode,null,b.lineSeparator)),this.doc=c;var d=new x.inputStyles[b.inputStyle](this),e=this.display=new y(a,c,d);e.wrapper.CodeMirror=this,G(this),E(this),b.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),b.autofocus&&!p&&e.input.focus(),O(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,cutIncoming:!1,selectingText:!1,draggingText:!1,highlight:new bg,keySeq:null,specialChars:null};var i=this;f&&11>g&&setTimeout(function(){i.display.input.reset(!0)},20),sc(this),Gg(),Yb(this),this.curOp.forceUpdate=!0,hf(this,c),b.autofocus&&!p||i.hasFocus()?setTimeout(ng(ad,this),20):bd(this);for(var j in Ed)Ed.hasOwnProperty(j)&&Ed[j](this,b[j],Gd);T(this),b.finishInit&&b.finishInit(this);for(var k=0;kg&&(e.gutters.style.zIndex=-1,e.scroller.style.paddingRight=0),h||c&&p||(e.scroller.draggable=!0),a&&(a.appendChild?a.appendChild(e.wrapper):a(e.wrapper)),e.viewFrom=e.viewTo=b.first,e.reportedViewFrom=e.reportedViewTo=b.first,e.view=[],e.renderedView=null,e.externalMeasured=null,e.viewOffset=0,e.lastWrapHeight=e.lastWrapWidth=0,e.updateLineNumbers=null,e.nativeBarWidth=e.barHeight=e.barWidth=0,e.scrollbarsClipped=!1,e.lineNumWidth=e.lineNumInnerWidth=e.lineNumChars=null,e.alignWidgets=!1,e.cachedCharWidth=e.cachedTextHeight=e.cachedPaddingH=null,e.maxLine=null,e.maxLineLength=0,e.maxLineChanged=!1,e.wheelDX=e.wheelDY=e.wheelStartX=e.wheelStartY=null,e.shift=!1,e.selForContextMenu=null,e.activeTouch=null,d.init(e)}function z(a){a.doc.mode=x.getMode(a.options,a.doc.modeOption),A(a)}function A(a){a.doc.iter(function(a){a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null)}),a.doc.frontier=a.doc.first,lb(a,100),a.state.modeGen++,a.curOp&&lc(a)}function B(a){a.options.lineWrapping?(Cg(a.display.wrapper,"CodeMirror-wrap"),a.display.sizer.style.minWidth="",a.display.sizerWidth=null):(Bg(a.display.wrapper,"CodeMirror-wrap"),J(a)),D(a),lc(a),Ib(a),setTimeout(function(){P(a)},100)}function C(a){var b=Ub(a.display),c=a.options.lineWrapping,d=c&&Math.max(5,a.display.scroller.clientWidth/Vb(a.display)-3);return function(e){if(ze(a.doc,e))return 0;var f=0;if(e.widgets)for(var g=0;gb.maxLineLength&&(b.maxLineLength=c,b.maxLine=a)})}function K(a){var b=ig(a.gutters,"CodeMirror-linenumbers");-1==b&&a.lineNumbers?a.gutters=a.gutters.concat(["CodeMirror-linenumbers"]):b>-1&&!a.lineNumbers&&(a.gutters=a.gutters.slice(0),a.gutters.splice(b,1))}function L(a){var b=a.display,c=b.gutters.offsetWidth,d=Math.round(a.doc.height+qb(a.display));return{clientHeight:b.scroller.clientHeight,viewHeight:b.wrapper.clientHeight,scrollWidth:b.scroller.scrollWidth,clientWidth:b.scroller.clientWidth,viewWidth:b.wrapper.clientWidth,barLeft:a.options.fixedGutter?c:0,docHeight:d,scrollHeight:d+sb(a)+b.barHeight,nativeBarWidth:b.nativeBarWidth,gutterWidth:c}}function M(a,b,c){this.cm=c;var d=this.vert=ug("div",[ug("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),e=this.horiz=ug("div",[ug("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");a(d),a(e),Mf(d,"scroll",function(){d.clientHeight&&b(d.scrollTop,"vertical")}),Mf(e,"scroll",function(){e.clientWidth&&b(e.scrollLeft,"horizontal")}),this.checkedZeroWidth=!1,f&&8>g&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")}function N(){}function O(a){a.display.scrollbars&&(a.display.scrollbars.clear(),a.display.scrollbars.addClass&&Bg(a.display.wrapper,a.display.scrollbars.addClass)),a.display.scrollbars=new x.scrollbarModel[a.options.scrollbarStyle](function(b){a.display.wrapper.insertBefore(b,a.display.scrollbarFiller),Mf(b,"mousedown",function(){a.state.focused&&setTimeout(function(){a.display.input.focus()},0)}),b.setAttribute("cm-not-content","true")},function(b,c){"horizontal"==c?Lc(a,b):Kc(a,b)},a),a.display.scrollbars.addClass&&Cg(a.display.wrapper,a.display.scrollbars.addClass)}function P(a,b){b||(b=L(a));var c=a.display.barWidth,d=a.display.barHeight;Q(a,b);for(var e=0;4>e&&c!=a.display.barWidth||d!=a.display.barHeight;e++)c!=a.display.barWidth&&a.options.lineWrapping&&aa(a),Q(a,L(a)),c=a.display.barWidth,d=a.display.barHeight}function Q(a,b){var c=a.display,d=c.scrollbars.update(b);c.sizer.style.paddingRight=(c.barWidth=d.right)+"px",c.sizer.style.paddingBottom=(c.barHeight=d.bottom)+"px",d.right&&d.bottom?(c.scrollbarFiller.style.display="block",c.scrollbarFiller.style.height=d.bottom+"px",c.scrollbarFiller.style.width=d.right+"px"):c.scrollbarFiller.style.display="",d.bottom&&a.options.coverGutterNextToScrollbar&&a.options.fixedGutter?(c.gutterFiller.style.display="block",c.gutterFiller.style.height=d.bottom+"px",c.gutterFiller.style.width=b.gutterWidth+"px"):c.gutterFiller.style.display=""}function R(a,b,c){var d=c&&null!=c.top?Math.max(0,c.top):a.scroller.scrollTop;d=Math.floor(d-pb(a));var e=c&&null!=c.bottom?c.bottom:d+a.wrapper.clientHeight,f=of(b,d),g=of(b,e);if(c&&c.ensure){var h=c.ensure.from.line,i=c.ensure.to.line;f>h?(f=h,g=of(b,pf(jf(b,h))+a.wrapper.clientHeight)):Math.min(i,b.lastLine())>=g&&(f=of(b,pf(jf(b,i))-a.wrapper.clientHeight),g=i)}return{from:f,to:Math.max(g,f+1)}}function S(a){var b=a.display,c=b.view;if(b.alignWidgets||b.gutters.firstChild&&a.options.fixedGutter){for(var d=V(b)-b.scroller.scrollLeft+a.doc.scrollLeft,e=b.gutters.offsetWidth,f=d+"px",g=0;g=c.viewFrom&&b.visible.to<=c.viewTo&&(null==c.updateLineNumbers||c.updateLineNumbers>=c.viewTo)&&c.renderedView==c.view&&0==rc(a))return!1;T(a)&&(nc(a),b.dims=ca(a));var e=d.first+d.size,f=Math.max(b.visible.from-a.options.viewportMargin,d.first),g=Math.min(e,b.visible.to+a.options.viewportMargin);c.viewFromg&&c.viewTo-g<20&&(g=Math.min(e,c.viewTo)),w&&(f=xe(a.doc,f),g=ye(a.doc,g));var h=f!=c.viewFrom||g!=c.viewTo||c.lastWrapHeight!=b.wrapperHeight||c.lastWrapWidth!=b.wrapperWidth;qc(a,f,g),c.viewOffset=pf(jf(a.doc,c.viewFrom)),a.display.mover.style.top=c.viewOffset+"px";var i=rc(a);if(!h&&0==i&&!b.force&&c.renderedView==c.view&&(null==c.updateLineNumbers||c.updateLineNumbers>=c.viewTo))return!1;var j=zg();return i>4&&(c.lineDiv.style.display="none"),da(a,c.updateLineNumbers,b.dims),i>4&&(c.lineDiv.style.display=""),c.renderedView=c.view,j&&zg()!=j&&j.offsetHeight&&j.focus(),wg(c.cursorDiv),wg(c.selectionDiv),c.gutters.style.height=c.sizer.style.minHeight=0,h&&(c.lastWrapHeight=b.wrapperHeight,c.lastWrapWidth=b.wrapperWidth,lb(a,400)),c.updateLineNumbers=null,!0}function Z(a,b){for(var c=b.viewport,d=!0;(d&&a.options.lineWrapping&&b.oldDisplayWidth!=tb(a)||(c&&null!=c.top&&(c={top:Math.min(a.doc.height+qb(a.display)-ub(a),c.top)}),b.visible=R(a.display,a.doc,c),!(b.visible.from>=a.display.viewFrom&&b.visible.to<=a.display.viewTo)))&&Y(a,b);d=!1){aa(a);var e=L(a);gb(a),_(a,e),P(a,e)}b.signal(a,"update",a),(a.display.viewFrom!=a.display.reportedViewFrom||a.display.viewTo!=a.display.reportedViewTo)&&(b.signal(a,"viewportChange",a,a.display.viewFrom,a.display.viewTo),a.display.reportedViewFrom=a.display.viewFrom,a.display.reportedViewTo=a.display.viewTo)}function $(a,b){var c=new W(a,b);if(Y(a,c)){aa(a),Z(a,c);var d=L(a);gb(a),_(a,d),P(a,d),c.finish()}}function _(a,b){a.display.sizer.style.minHeight=b.docHeight+"px";var c=b.docHeight+a.display.barHeight;a.display.heightForcer.style.top=c+"px",a.display.gutters.style.height=Math.max(c+sb(a),b.clientHeight)+"px"}function aa(a){for(var b=a.display,c=b.lineDiv.offsetTop,d=0;dg){var i=e.node.offsetTop+e.node.offsetHeight;h=i-c,c=i}else{var j=e.node.getBoundingClientRect();h=j.bottom-j.top}var k=e.line.height-h;if(2>h&&(h=Ub(b)),(k>.001||-.001>k)&&(mf(e.line,h),ba(e.line),e.rest))for(var l=0;l=b&&m.lineNumber;m.changes&&(ig(m.changes,"gutter")>-1&&(o=!1),ea(a,m,k,c)),o&&(wg(m.lineNumber),m.lineNumber.appendChild(document.createTextNode(U(a.options,k)))),g=m.node.nextSibling}else{var n=ma(a,m,k,c);f.insertBefore(n,g)}k+=m.size}for(;g;)g=i(g)}function ea(a,b,c,d){for(var e=0;eg&&(a.node.style.zIndex=2)),a.node}function ga(a){var b=a.bgClass?a.bgClass+" "+(a.line.bgClass||""):a.line.bgClass;if(b&&(b+=" CodeMirror-linebackground"),a.background)b?a.background.className=b:(a.background.parentNode.removeChild(a.background),a.background=null);else if(b){var c=fa(a);a.background=c.insertBefore(ug("div",null,b),c.firstChild)}}function ha(a,b){var c=a.display.externalMeasured;return c&&c.line==b.line?(a.display.externalMeasured=null,b.measure=c.measure,c.built):Te(a,b)}function ia(a,b){var c=b.text.className,d=ha(a,b);b.text==b.node&&(b.node=d.pre),b.text.parentNode.replaceChild(d.pre,b.text),b.text=d.pre,d.bgClass!=b.bgClass||d.textClass!=b.textClass?(b.bgClass=d.bgClass,b.textClass=d.textClass,ja(b)):c&&(b.text.className=c)}function ja(a){ga(a),a.line.wrapClass?fa(a).className=a.line.wrapClass:a.node!=a.text&&(a.node.className="");var b=a.textClass?a.textClass+" "+(a.line.textClass||""):a.line.textClass;a.text.className=b||""}function ka(a,b,c,d){if(b.gutter&&(b.node.removeChild(b.gutter),b.gutter=null),b.gutterBackground&&(b.node.removeChild(b.gutterBackground),b.gutterBackground=null),b.line.gutterClass){var e=fa(b);b.gutterBackground=ug("div",null,"CodeMirror-gutter-background "+b.line.gutterClass,"left: "+(a.options.fixedGutter?d.fixedPos:-d.gutterTotalWidth)+"px; width: "+d.gutterTotalWidth+"px"),e.insertBefore(b.gutterBackground,b.text)}var f=b.line.gutterMarkers;if(a.options.lineNumbers||f){var e=fa(b),g=b.gutter=ug("div",null,"CodeMirror-gutter-wrapper","left: "+(a.options.fixedGutter?d.fixedPos:-d.gutterTotalWidth)+"px");if(a.display.input.setUneditable(g),e.insertBefore(g,b.text),b.line.gutterClass&&(g.className+=" "+b.line.gutterClass),!a.options.lineNumbers||f&&f["CodeMirror-linenumbers"]||(b.lineNumber=g.appendChild(ug("div",U(a.options,c),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+d.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+a.display.lineNumInnerWidth+"px"))),f)for(var h=0;h1)if(wa&&wa.join("\n")==b){if(d.ranges.length%wa.length==0){i=[];for(var j=0;j=0;j--){var k=d.ranges[j],l=k.from(),m=k.to();k.empty()&&(c&&c>0?l=qa(l.line,l.ch-c):a.state.overwrite&&!g&&(m=qa(m.line,Math.min(jf(f,m.line).text.length,m.ch+gg(h).length))));var n=a.curOp.updateInput,o={from:l,to:m,text:i?i[j%i.length]:h,origin:e||(g?"paste":a.state.cutIncoming?"cut":"+input")};kd(a.doc,o),Sf(a,"inputRead",a,o)}b&&!g&&za(a,b),wd(a),a.curOp.updateInput=n,a.curOp.typing=!0,a.state.pasteIncoming=a.state.cutIncoming=!1}function ya(a,b){var c=a.clipboardData&&a.clipboardData.getData("text/plain");return c?(a.preventDefault(),b.isReadOnly()||b.options.disableInput||fc(b,function(){xa(b,c,0,null,"paste")}),!0):void 0}function za(a,b){if(a.options.electricChars&&a.options.smartIndent)for(var c=a.doc.sel,d=c.ranges.length-1;d>=0;d--){var e=c.ranges[d];if(!(e.head.ch>100||d&&c.ranges[d-1].head.line==e.head.line)){var f=a.getModeAt(e.head),g=!1;if(f.electricChars){for(var h=0;h-1){g=yd(a,e.head.line,"smart");break}}else f.electricInput&&f.electricInput.test(jf(a.doc,e.head.line).text.slice(0,e.head.ch))&&(g=yd(a,e.head.line,"smart"));g&&Sf(a,"electricInput",a,e.head.line)}}}function Aa(a){for(var b=[],c=[],d=0;de?i.map:j[e],g=0;ge?a.line:a.rest[e]),l=f[g]+d;return(0>d||h!=b)&&(l=f[g+(d?1:0)]),qa(k,l)}}}var d=a.text.firstChild,e=!1;if(!b||!yg(d,b))return Ga(qa(nf(a.line),0),!0);if(b==d&&(e=!0,b=d.childNodes[c],c=0,!b)){var f=a.rest?gg(a.rest):a.line;return Ga(qa(nf(f),f.text.length),e)}var g=3==b.nodeType?b:null,h=b;for(g||1!=b.childNodes.length||3!=b.firstChild.nodeType||(g=b.firstChild,c&&(c=g.nodeValue.length));h.parentNode!=d;)h=h.parentNode;var i=a.measure,j=i.maps,l=k(g,h,c);if(l)return Ga(l,e);for(var m=h.nextSibling,n=g?g.nodeValue.length-c:0;m;m=m.nextSibling){if(l=k(m,m.firstChild,0))return Ga(qa(l.line,l.ch-n),e);n+=m.textContent.length}for(var o=h.previousSibling,n=c;o;o=o.previousSibling){if(l=k(o,o.firstChild,-1))return Ga(qa(l.line,l.ch+n),e);n+=m.textContent.length}}function Ja(a,b,c,d,e){function i(a){return function(b){return b.id==a}}function j(b){if(1==b.nodeType){var c=b.getAttribute("cm-text");if(null!=c)return""==c&&(c=b.textContent.replace(/\u200b/g,"")),void(f+=c);var l,k=b.getAttribute("cm-marker");if(k){var m=a.findMarks(qa(d,0),qa(e+1,0),i(+k));return void(m.length&&(l=m[0].find())&&(f+=kf(a.doc,l.from,l.to).join(h)))}if("false"==b.getAttribute("contenteditable"))return;for(var n=0;n=0){var g=ua(f.from(),e.from()),h=ta(f.to(),e.to()),i=f.empty()?e.from()==e.head:f.from()==f.head;b>=d&&--b,a.splice(--d,2,new La(i?h:g,i?g:h))}}return new Ka(a,b)}function Na(a,b){return new Ka([new La(a,b||a)],0)}function Oa(a,b){return Math.max(a.first,Math.min(b,a.first+a.size-1))}function Pa(a,b){if(b.linec?qa(c,jf(a,c).text.length):Qa(b,jf(a,b.line).text.length)}function Qa(a,b){var c=a.ch;return null==c||c>b?qa(a.line,b):0>c?qa(a.line,0):a}function Ra(a,b){return b>=a.first&&b=b.ch:h.to>b.ch))){if(e&&(Qf(i,"beforeCursorEnter"),i.explicitlyCleared)){if(f.markedSpans){--g;continue}break}if(!i.atomic)continue;if(c){var k,j=i.find(0>d?1:-1);if((0>d?i.inclusiveRight:i.inclusiveLeft)&&(j=fb(a,j,-d,f)),j&&j.line==b.line&&(k=ra(j,c))&&(0>d?0>k:k>0))return db(a,j,b,d,e)}var l=i.find(0>d?-1:1);return(0>d?i.inclusiveLeft:i.inclusiveRight)&&(l=fb(a,l,d,f)),l?db(a,l,b,d,e):null}}return b}function eb(a,b,c,d,e){var f=d||1,g=db(a,b,c,f,e)||!e&&db(a,b,c,f,!0)||db(a,b,c,-f,e)||!e&&db(a,b,c,-f,!0);return g?g:(a.cantEdit=!0,qa(a.first,0))}function fb(a,b,c,d){return 0>c&&0==b.ch?b.line>a.first?Pa(a,qa(b.line-1)):null:c>0&&b.ch==(d||jf(a,b.line)).text.length?b.lineb&&(b=0),b=Math.round(b),d=Math.round(d),f.appendChild(ug("div",null,"CodeMirror-selected","position: absolute; left: "+a+"px; top: "+b+"px; width: "+(null==c?i-a:c)+"px; height: "+(d-b)+"px"))}function k(b,c,d){function m(c,d){return Nb(a,qa(b,c),"div",f,d)}var k,l,f=jf(e,b),g=f.text.length;return Tg(qf(f),c||0,null==d?g:d,function(a,b,e){var n,o,p,f=m(a,"left");if(a==b)n=f,o=p=f.left;else{if(n=m(b-1,"right"),"rtl"==e){var q=f;f=n,n=q}o=f.left,p=n.right}null==c&&0==a&&(o=h),n.top-f.top>3&&(j(o,f.top,null,f.bottom),o=h,f.bottoml.bottom||n.bottom==l.bottom&&n.right>l.right)&&(l=n),h+1>o&&(o=h),j(o,n.top,p-o,n.bottom)}),{start:k,end:l}}var d=a.display,e=a.doc,f=document.createDocumentFragment(),g=rb(a.display),h=g.left,i=Math.max(d.sizerWidth,tb(a)-d.sizer.offsetLeft)-g.right,l=b.from(),m=b.to();if(l.line==m.line)k(l.line,l.ch,m.ch);else{var n=jf(e,l.line),o=jf(e,m.line),p=ve(n)==ve(o),q=k(l.line,l.ch,p?n.text.length+1:null).end,r=k(m.line,p?0:null,m.ch).start;p&&(q.top0?b.blinker=setInterval(function(){b.cursorDiv.style.visibility=(c=!c)?"":"hidden"},a.options.cursorBlinkRate):a.options.cursorBlinkRate<0&&(b.cursorDiv.style.visibility="hidden")}}function lb(a,b){a.doc.mode.startState&&a.doc.frontier=a.display.viewTo)){var c=+new Date+a.options.workTime,d=Md(b.mode,ob(a,b.frontier)),e=[];b.iter(b.frontier,Math.min(b.first+b.size,a.display.viewTo+500),function(f){if(b.frontier>=a.display.viewFrom){var g=f.styles,h=f.text.length>a.options.maxHighlightLength,i=Ne(a,f,h?Md(b.mode,d):d,!0);f.styles=i.styles;var j=f.styleClasses,k=i.classes;k?f.styleClasses=k:j&&(f.styleClasses=null);for(var l=!g||g.length!=f.styles.length||j!=k&&(!j||!k||j.bgClass!=k.bgClass||j.textClass!=k.textClass),m=0;!l&&mc?(lb(a,a.options.workDelay),!0):void 0}),e.length&&fc(a,function(){for(var b=0;bg;--h){if(h<=f.first)return f.first;var i=jf(f,h-1);if(i.stateAfter&&(!c||h<=f.frontier))return h;var j=cg(i.text,null,a.options.tabSize);(null==e||d>j)&&(e=h-1,d=j)}return e}function ob(a,b,c){var d=a.doc,e=a.display;if(!d.mode.startState)return!0;var f=nb(a,b,c),g=f>d.first&&jf(d,f-1).stateAfter;return g=g?Md(d.mode,g):Nd(d.mode),d.iter(f,b,function(c){Pe(a,c.text,g);var h=f==b-1||f%5==0||f>=e.viewFrom&&f2&&f.push((i.bottom+j.top)/2-c.top)}}f.push(c.bottom-c.top)}}function wb(a,b,c){if(a.line==b)return{map:a.measure.map,cache:a.measure.cache};for(var d=0;dc)return{map:a.measure.maps[d],cache:a.measure.caches[d],before:!0}}function xb(a,b){b=ve(b);var c=nf(b),d=a.display.externalMeasured=new jc(a.doc,b,c);d.lineN=c;var e=d.built=Te(a,d);return d.text=e.pre,xg(a.display.lineMeasure,e.pre),d}function yb(a,b,c,d){return Bb(a,Ab(a,b),c,d)}function zb(a,b){if(b>=a.display.viewFrom&&b=c.lineN&&bb?(e=0,f=1,g="left"):j>b?(e=b-i,f=e+1):(h==a.length-3||b==j&&a[h+3]>b)&&(f=j-i,e=f-1,b>=j&&(g="right")),null!=e){if(d=a[h+2],i==j&&c==(d.insertLeft?"left":"right")&&(g=c),"left"==c&&0==e)for(;h&&a[h-2]==a[h-3]&&a[h-1].insertLeft;)d=a[(h-=3)+2], +g="left";if("right"==c&&e==j-i)for(;hm;m++){for(;i&&tg(b.line.text.charAt(e.coverStart+i));)--i;for(;e.coverStart+jg&&0==i&&j==e.coverEnd-e.coverStart)l=h.parentNode.getBoundingClientRect();else if(f&&a.options.lineWrapping){var n=vg(h,i,j).getClientRects();l=n.length?n["right"==d?n.length-1:0]:Cb}else l=vg(h,i,j).getBoundingClientRect()||Cb;if(l.left||l.right||0==i)break;j=i,i-=1,k="right"}f&&11>g&&(l=Fb(a.display.measure,l))}else{i>0&&(k=d="right");var n;l=a.options.lineWrapping&&(n=h.getClientRects()).length>1?n["right"==d?n.length-1:0]:h.getBoundingClientRect()}if(f&&9>g&&!i&&(!l||!l.left&&!l.right)){var o=h.parentNode.getClientRects()[0];l=o?{left:o.left,right:o.left+Vb(a.display),top:o.top,bottom:o.bottom}:Cb}for(var p=l.top-b.rect.top,q=l.bottom-b.rect.top,r=(p+q)/2,s=b.view.measure.heights,m=0;mc.from?g(a-1):g(a,d)}d=d||jf(a.doc,b.line),e||(e=Ab(a,d));var i=qf(d),j=b.ch;if(!i)return g(j);var k=bh(i,j),l=h(j,k);return null!=ah&&(l.other=h(j,ah)),l}function Pb(a,b){var c=0,b=Pa(a.doc,b);a.options.lineWrapping||(c=Vb(a.display)*b.ch);var d=jf(a.doc,b.line),e=pf(d)+pb(a.display);return{left:c,right:c,top:e,bottom:e+d.height}}function Qb(a,b,c,d){var e=qa(a,b);return e.xRel=d,c&&(e.outside=!0),e}function Rb(a,b,c){var d=a.doc;if(c+=a.display.viewOffset,0>c)return Qb(d.first,0,!0,-1);var e=of(d,c),f=d.first+d.size-1;if(e>f)return Qb(d.first+d.size-1,jf(d,f).text.length,!0,1);0>b&&(b=0);for(var g=jf(d,e);;){var h=Sb(a,g,e,b,c),i=te(g),j=i&&i.find(0,!0);if(!i||!(h.ch>j.from.ch||h.ch==j.from.ch&&h.xRel>0))return h;e=nf(g=j.to.line)}}function Sb(a,b,c,d,e){function j(d){var e=Ob(a,qa(c,d),"line",b,i);return g=!0,f>e.bottom?e.left-h:fq)return Qb(c,n,r,1);for(;;){if(k?n==m||n==dh(b,m,1):1>=n-m){for(var s=o>d||q-d>=d-o?m:n,t=d-(s==m?o:q);tg(b.text.charAt(s));)++s;var u=Qb(c,s,s==m?p:r,-1>t?-1:t>1?1:0);return u}var v=Math.ceil(l/2),w=m+v;if(k){w=m;for(var x=0;v>x;++x)w=dh(b,w,1)}var y=j(w);y>d?(n=w,q=y,(r=g)&&(q+=1e3),l=v):(m=w,o=y,p=g,l-=v)}}function Ub(a){if(null!=a.cachedTextHeight)return a.cachedTextHeight;if(null==Tb){Tb=ug("pre");for(var b=0;49>b;++b)Tb.appendChild(document.createTextNode("x")),Tb.appendChild(ug("br"));Tb.appendChild(document.createTextNode("x"))}xg(a.measure,Tb);var c=Tb.offsetHeight/50;return c>3&&(a.cachedTextHeight=c),wg(a.measure),c||1}function Vb(a){if(null!=a.cachedCharWidth)return a.cachedCharWidth;var b=ug("span","xxxxxxxxxx"),c=ug("pre",[b]);xg(a.measure,c);var d=b.getBoundingClientRect(),e=(d.right-d.left)/10;return e>2&&(a.cachedCharWidth=e),e||10}function Yb(a){a.curOp={cm:a,viewChanged:!1,startHeight:a.doc.height,forceUpdate:!1,updateInput:null,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Xb},Wb?Wb.ops.push(a.curOp):a.curOp.ownsGroup=Wb={ops:[a.curOp],delayedCallbacks:[]}}function Zb(a){var b=a.delayedCallbacks,c=0;do{for(;c=c.viewTo)||c.maxLineChanged&&b.options.lineWrapping,a.update=a.mustUpdate&&new W(b,a.mustUpdate&&{top:a.scrollTop,ensure:a.scrollToPos},a.forceUpdate)}function bc(a){a.updatedDisplay=a.mustUpdate&&Y(a.cm,a.update)}function cc(a){var b=a.cm,c=b.display;a.updatedDisplay&&aa(b),a.barMeasure=L(b),c.maxLineChanged&&!b.options.lineWrapping&&(a.adjustWidthTo=yb(b,c.maxLine,c.maxLine.text.length).left+3,b.display.sizerWidth=a.adjustWidthTo,a.barMeasure.scrollWidth=Math.max(c.scroller.clientWidth,c.sizer.offsetLeft+a.adjustWidthTo+sb(b)+b.display.barWidth),a.maxScrollLeft=Math.max(0,c.sizer.offsetLeft+a.adjustWidthTo-tb(b))),(a.updatedDisplay||a.selectionChanged)&&(a.preparedSelection=c.input.prepareSelection())}function dc(a){var b=a.cm;null!=a.adjustWidthTo&&(b.display.sizer.style.minWidth=a.adjustWidthTo+"px",a.maxScrollLeftf;f=e){var g=new jc(a.doc,jf(a.doc,f),f);e=f+g.size,d.push(g)}return d}function lc(a,b,c,d){null==b&&(b=a.doc.first),null==c&&(c=a.doc.first+a.doc.size),d||(d=0);var e=a.display;if(d&&cb)&&(e.updateLineNumbers=b),a.curOp.viewChanged=!0,b>=e.viewTo)w&&xe(a.doc,b)e.viewFrom?nc(a):(e.viewFrom+=d,e.viewTo+=d);else if(b<=e.viewFrom&&c>=e.viewTo)nc(a);else if(b<=e.viewFrom){var f=pc(a,c,c+d,1);f?(e.view=e.view.slice(f.index),e.viewFrom=f.lineN,e.viewTo+=d):nc(a)}else if(c>=e.viewTo){var f=pc(a,b,b,-1);f?(e.view=e.view.slice(0,f.index),e.viewTo=f.lineN):nc(a)}else{var g=pc(a,b,b,-1),h=pc(a,c,c+d,1);g&&h?(e.view=e.view.slice(0,g.index).concat(kc(a,g.lineN,h.lineN)).concat(e.view.slice(h.index)),e.viewTo+=d):nc(a)}var i=e.externalMeasured;i&&(c=e.lineN&&b=d.viewTo)){var f=d.view[oc(a,b)];if(null!=f.node){var g=f.changes||(f.changes=[]);-1==ig(g,c)&&g.push(c)}}}function nc(a){a.display.viewFrom=a.display.viewTo=a.doc.first,a.display.view=[],a.display.viewOffset=0}function oc(a,b){if(b>=a.display.viewTo)return null;if(b-=a.display.viewFrom,0>b)return null;for(var c=a.display.view,d=0;db)return d}function pc(a,b,c,d){var f,e=oc(a,b),g=a.display.view;if(!w||c==a.doc.first+a.doc.size)return{index:e,lineN:c};for(var h=0,i=a.display.viewFrom;e>h;h++)i+=g[h].size;if(i!=b){if(d>0){if(e==g.length-1)return null;f=i+g[e].size-b,e++}else f=i-b;b+=f,c+=f}for(;xe(a.doc,c)!=c;){if(e==(0>d?0:g.length-1))return null;c+=d*g[e-(0>d?1:0)].size,e+=d}return{index:e,lineN:c}}function qc(a,b,c){var d=a.display,e=d.view;0==e.length||b>=d.viewTo||c<=d.viewFrom?(d.view=kc(a,b,c),d.viewFrom=b):(d.viewFrom>b?d.view=kc(a,b,d.viewFrom).concat(d.view):d.viewFromc&&(d.view=d.view.slice(0,oc(a,c)))),d.viewTo=c}function rc(a){for(var b=a.display.view,c=0,d=0;d400}var b=a.display;Mf(b.scroller,"mousedown",gc(a,xc)),f&&11>g?Mf(b.scroller,"dblclick",gc(a,function(b){if(!Uf(a,b)){var c=wc(a,b);if(c&&!Ec(a,b)&&!vc(a.display,b)){Gf(b);var d=a.findWordAt(c);Ua(a.doc,d.anchor,d.head)}}})):Mf(b.scroller,"dblclick",function(b){Uf(a,b)||Gf(b)}),u||Mf(b.scroller,"contextmenu",function(b){cd(a,b)});var c,d={end:0};Mf(b.scroller,"touchstart",function(a){if(!h(a)){clearTimeout(c);var e=+new Date;b.activeTouch={start:e,moved:!1,prev:e-d.end<=300?d:null},1==a.touches.length&&(b.activeTouch.left=a.touches[0].pageX,b.activeTouch.top=a.touches[0].pageY)}}),Mf(b.scroller,"touchmove",function(){b.activeTouch&&(b.activeTouch.moved=!0)}),Mf(b.scroller,"touchend",function(c){var d=b.activeTouch;if(d&&!vc(b,c)&&null!=d.left&&!d.moved&&new Date-d.start<300){var g,f=a.coordsChar(b.activeTouch,"page");g=!d.prev||i(d,d.prev)?new La(f,f):!d.prev.prev||i(d,d.prev.prev)?a.findWordAt(f):new La(qa(f.line,0),Pa(a.doc,qa(f.line+1,0))),a.setSelection(g.anchor,g.head),a.focus(),Gf(c)}e()}),Mf(b.scroller,"touchcancel",e),Mf(b.scroller,"scroll",function(){b.scroller.clientHeight&&(Kc(a,b.scroller.scrollTop),Lc(a,b.scroller.scrollLeft,!0),Qf(a,"scroll",a))}),Mf(b.scroller,"mousewheel",function(b){Pc(a,b)}),Mf(b.scroller,"DOMMouseScroll",function(b){Pc(a,b)}),Mf(b.wrapper,"scroll",function(){b.wrapper.scrollTop=b.wrapper.scrollLeft=0}),b.dragFunctions={enter:function(b){Uf(a,b)||Jf(b)},over:function(b){Uf(a,b)||(Ic(a,b),Jf(b))},start:function(b){Hc(a,b)},drop:gc(a,Gc),leave:function(){Jc(a)}};var j=b.input.getField();Mf(j,"keyup",function(b){Zc.call(a,b)}),Mf(j,"keydown",gc(a,Xc)),Mf(j,"keypress",gc(a,$c)),Mf(j,"focus",ng(ad,a)),Mf(j,"blur",ng(bd,a))}function tc(a,b,c){var d=c&&c!=x.Init;if(!b!=!d){var e=a.display.dragFunctions,f=b?Mf:Pf;f(a.display.scroller,"dragstart",e.start),f(a.display.scroller,"dragenter",e.enter),f(a.display.scroller,"dragover",e.over),f(a.display.scroller,"dragleave",e.leave),f(a.display.scroller,"drop",e.drop)}}function uc(a){var b=a.display;(b.lastWrapHeight!=b.wrapper.clientHeight||b.lastWrapWidth!=b.wrapper.clientWidth)&&(b.cachedCharWidth=b.cachedTextHeight=b.cachedPaddingH=null,b.scrollbarsClipped=!1,a.setSize())}function vc(a,b){for(var c=Kf(b);c!=a.wrapper;c=c.parentNode)if(!c||1==c.nodeType&&"true"==c.getAttribute("cm-ignore-events")||c.parentNode==a.sizer&&c!=a.mover)return!0}function wc(a,b,c,d){var e=a.display;if(!c&&"true"==Kf(b).getAttribute("cm-not-content"))return null;var f,g,h=e.lineSpace.getBoundingClientRect();try{f=b.clientX-h.left,g=b.clientY-h.top}catch(b){return null}var j,i=Rb(a,f,g);if(d&&1==i.xRel&&(j=jf(a.doc,i.line).text).length==i.ch){var k=cg(j,j.length,a.options.tabSize)-j.length;i=qa(i.line,Math.max(0,Math.round((f-rb(a.display).left)/Vb(a.display))-k))}return i}function xc(a){var b=this,c=b.display;if(!(c.activeTouch&&c.input.supportsTouch()||Uf(b,a))){if(c.shift=a.shiftKey,vc(c,a))return void(h||(c.scroller.draggable=!1,setTimeout(function(){c.scroller.draggable=!0},100)));if(!Ec(b,a)){var d=wc(b,a);switch(window.focus(),Lf(a)){case 1:b.state.selectingText?b.state.selectingText(a):d?Ac(b,a,d):Kf(a)==c.scroller&&Gf(a);break;case 2:h&&(b.state.lastMiddleDown=+new Date),d&&Ua(b.doc,d),setTimeout(function(){c.input.focus()},20),Gf(a);break;case 3:u?cd(b,a):_c(b)}}}}function Ac(a,b,c){f?setTimeout(ng(va,a),0):a.curOp.focus=zg();var e,d=+new Date;zc&&zc.time>d-400&&0==ra(zc.pos,c)?e="triple":yc&&yc.time>d-400&&0==ra(yc.pos,c)?(e="double",zc={time:d,pos:c}):(e="single",yc={time:d,pos:c});var i,g=a.doc.sel,h=q?b.metaKey:b.ctrlKey;a.options.dragDrop&&Ig&&!a.isReadOnly()&&"single"==e&&(i=g.contains(c))>-1&&(ra((i=g.ranges[i]).from(),c)<0||c.xRel>0)&&(ra(i.to(),c)>0||c.xRel<0)?Bc(a,b,c,h):Cc(a,b,c,e,h)}function Bc(a,b,c,d){var e=a.display,i=+new Date,j=gc(a,function(k){h&&(e.scroller.draggable=!1),a.state.draggingText=!1,Pf(document,"mouseup",j),Pf(e.scroller,"drop",j),Math.abs(b.clientX-k.clientX)+Math.abs(b.clientY-k.clientY)<10&&(Gf(k),!d&&+new Date-200=p;p++){var r=jf(g,p).text,s=dg(r,m,f);m==o?e.push(new La(qa(p,s),qa(p,s))):r.length>s&&e.push(new La(qa(p,s),qa(p,dg(r,o,f))))}e.length||e.push(new La(c,c)),$a(g,Ma(j.ranges.slice(0,i).concat(e),i),{origin:"*mouse",scroll:!1}),a.scrollIntoView(b)}else{var t=h,u=t.anchor,v=b;if("single"!=d){if("double"==d)var w=a.findWordAt(b);else var w=new La(qa(b.line,0),Pa(g,qa(b.line+1,0)));ra(w.anchor,u)>0?(v=w.head,u=ua(t.from(),w.anchor)):(v=w.anchor,u=ta(t.to(),w.head))}var e=j.ranges.slice(0);e[i]=new La(Pa(g,u),v),$a(g,Ma(e,i),_f)}}function r(b){var c=++q,e=wc(a,b,!0,"rect"==d);if(e)if(0!=ra(e,n)){a.curOp.focus=zg(),o(e);var h=R(f,g);(e.line>=h.to||e.linep.bottom?20:0;i&&setTimeout(gc(a,function(){q==c&&(f.scroller.scrollTop+=i,r(b))}),50)}}function s(b){a.state.selectingText=!1,q=1/0,Gf(b),f.input.focus(),Pf(document,"mousemove",t),Pf(document,"mouseup",u),g.history.lastSelOrigin=null}var f=a.display,g=a.doc;Gf(b);var h,i,j=g.sel,k=j.ranges;if(e&&!b.shiftKey?(i=g.sel.contains(c),h=i>-1?k[i]:new La(c,c)):(h=g.sel.primary(),i=g.sel.primIndex),b.altKey)d="rect",e||(h=new La(c,c)),c=wc(a,b,!0,!0),i=-1;else if("double"==d){var l=a.findWordAt(c);h=a.display.shift||g.extend?Ta(g,h,l.anchor,l.head):l}else if("triple"==d){var m=new La(qa(c.line,0),Pa(g,qa(c.line+1,0)));h=a.display.shift||g.extend?Ta(g,h,m.anchor,m.head):m}else h=Ta(g,h,c);e?-1==i?(i=k.length,$a(g,Ma(k.concat([h]),i),{scroll:!1,origin:"*mouse"})):k.length>1&&k[i].empty()&&"single"==d&&!b.shiftKey?($a(g,Ma(k.slice(0,i).concat(k.slice(i+1)),0),{scroll:!1,origin:"*mouse"}),j=g.sel):Wa(g,i,h,_f):(i=0,$a(g,new Ka([h],0),_f),j=g.sel);var n=c,p=f.wrapper.getBoundingClientRect(),q=0,t=gc(a,function(a){Lf(a)?r(a):s(a)}),u=gc(a,s);a.state.selectingText=u,Mf(document,"mousemove",t),Mf(document,"mouseup",u)}function Dc(a,b,c,d){try{var e=b.clientX,f=b.clientY}catch(b){return!1}if(e>=Math.floor(a.display.gutters.getBoundingClientRect().right))return!1;d&&Gf(b);var g=a.display,h=g.lineDiv.getBoundingClientRect();if(f>h.bottom||!Wf(a,c))return If(b);f-=h.top-g.viewOffset;for(var i=0;i=e){var k=of(a.doc,f),l=a.options.gutters[i];return Qf(a,c,a,k,l,b),If(b)}}}function Ec(a,b){return Dc(a,b,"gutterClick",!0)}function Gc(a){var b=this;if(Jc(b),!Uf(b,a)&&!vc(b.display,a)){Gf(a),f&&(Fc=+new Date);var c=wc(b,a,!0),d=a.dataTransfer.files;if(c&&!b.isReadOnly())if(d&&d.length&&window.FileReader&&window.File)for(var e=d.length,g=Array(e),h=0,i=function(a,d){if(!b.options.allowDropFileTypes||-1!=ig(b.options.allowDropFileTypes,a.type)){var f=new FileReader;f.onload=gc(b,function(){var a=f.result;if(/[\x00-\x08\x0e-\x1f]{2}/.test(a)&&(a=""),g[d]=a,++h==e){c=Pa(b.doc,c);var i={from:c,to:c,text:b.doc.splitLines(g.join(b.doc.lineSeparator())),origin:"paste"};kd(b.doc,i),Za(b.doc,Na(c,ed(i)))}}),f.readAsText(a)}},j=0;e>j;++j)i(d[j],j);else{if(b.state.draggingText&&b.doc.sel.contains(c)>-1)return b.state.draggingText(a),void setTimeout(function(){b.display.input.focus()},20);try{var g=a.dataTransfer.getData("Text");if(g){if(b.state.draggingText&&!(q?a.altKey:a.ctrlKey))var k=b.listSelections();if(_a(b.doc,Na(c,c)),k)for(var j=0;ji.clientWidth,l=i.scrollHeight>i.clientHeight;if(e&&j||f&&l){if(f&&q&&h)a:for(var m=b.target,n=g.view;m!=i;m=m.parentNode)for(var o=0;op?r=Math.max(0,r+p-50):s=Math.min(a.doc.height,s+p+50),$(a,{top:r,bottom:s})}20>Mc&&(null==g.wheelStartX?(g.wheelStartX=i.scrollLeft,g.wheelStartY=i.scrollTop,g.wheelDX=e,g.wheelDY=f,setTimeout(function(){if(null!=g.wheelStartX){var a=i.scrollLeft-g.wheelStartX,b=i.scrollTop-g.wheelStartY,c=b&&g.wheelDY&&b/g.wheelDY||a&&g.wheelDX&&a/g.wheelDX;g.wheelStartX=g.wheelStartY=null,c&&(Nc=(Nc*Mc+c)/(Mc+1),++Mc)}},200)):(g.wheelDX+=e,g.wheelDY+=f))}}function Qc(a,b,c){if("string"==typeof b&&(b=Od[b],!b))return!1;a.display.input.ensurePolled();var d=a.display.shift,e=!1;try{a.isReadOnly()&&(a.state.suppressEdits=!0),c&&(a.display.shift=!1),e=b(a)!=Zf}finally{a.display.shift=d,a.state.suppressEdits=!1}return e}function Rc(a,b,c){for(var d=0;dg&&27==a.keyCode&&(a.returnValue=!1);var c=a.keyCode;b.display.shift=16==c||a.shiftKey;var d=Uc(b,a);k&&(Wc=d?c:null,!d&&88==c&&!Pg&&(q?a.metaKey:a.ctrlKey)&&b.replaceSelection("",null,"cut")),18!=c||/\bCodeMirror-crosshair\b/.test(b.display.lineDiv.className)||Yc(b)}}function Yc(a){function c(a){18!=a.keyCode&&a.altKey||(Bg(b,"CodeMirror-crosshair"),Pf(document,"keyup",c),Pf(document,"mouseover",c))}var b=a.display.lineDiv;Cg(b,"CodeMirror-crosshair"),Mf(document,"keyup",c),Mf(document,"mouseover",c)}function Zc(a){16==a.keyCode&&(this.doc.sel.shift=!1),Uf(this,a)}function $c(a){var b=this;if(!(vc(b.display,a)||Uf(b,a)||a.ctrlKey&&!a.altKey||q&&a.metaKey)){var c=a.keyCode,d=a.charCode;if(k&&c==Wc)return Wc=null,void Gf(a);if(!k||a.which&&!(a.which<10)||!Uc(b,a)){var e=String.fromCharCode(null==d?c:d);Vc(b,a,e)||b.display.input.onKeyPress(a)}}}function _c(a){a.state.delayingBlurEvent=!0,setTimeout(function(){a.state.delayingBlurEvent&&(a.state.delayingBlurEvent=!1,bd(a))},100)}function ad(a){a.state.delayingBlurEvent&&(a.state.delayingBlurEvent=!1),"nocursor"!=a.options.readOnly&&(a.state.focused||(Qf(a,"focus",a),a.state.focused=!0,Cg(a.display.wrapper,"CodeMirror-focused"),a.curOp||a.display.selForContextMenu==a.doc.sel||(a.display.input.reset(),h&&setTimeout(function(){a.display.input.reset(!0)},20)),a.display.input.receivedFocus()),kb(a))}function bd(a){a.state.delayingBlurEvent||(a.state.focused&&(Qf(a,"blur",a),a.state.focused=!1,Bg(a.display.wrapper,"CodeMirror-focused")),clearInterval(a.display.blinker),setTimeout(function(){a.state.focused||(a.display.shift=!1)},150))}function cd(a,b){vc(a.display,b)||dd(a,b)||Uf(a,b,"contextmenu")||a.display.input.onContextMenu(b)}function dd(a,b){return Wf(a,"gutterContextMenu")?Dc(a,b,"gutterContextMenu",!1):!1}function fd(a,b){if(ra(a,b.from)<0)return a;if(ra(a,b.to)<=0)return ed(b);var c=a.line+b.text.length-(b.to.line-b.from.line)-1,d=a.ch;return a.line==b.to.line&&(d+=ed(b).ch-b.to.ch),qa(c,d)}function gd(a,b){for(var c=[],d=0;d=0;--e)ld(a,{from:d[e].from,to:d[e].to,text:e?[""]:b.text});else ld(a,b)}}function ld(a,b){if(1!=b.text.length||""!=b.text[0]||0!=ra(b.from,b.to)){var c=gd(a,b);vf(a,b,c,a.cm?a.cm.curOp.id:NaN),od(a,b,c,ie(a,b));var d=[];gf(a,function(a,c){c||-1!=ig(d,a.history)||(Ff(a.history,b),d.push(a.history)),od(a,b,null,ie(a,b))})}}function md(a,b,c){if(!a.cm||!a.cm.state.suppressEdits){for(var e,d=a.history,f=a.sel,g="undo"==b?d.done:d.undone,h="undo"==b?d.undone:d.done,i=0;i=0;--i){var l=e.changes[i];if(l.origin=b,k&&!jd(a,l,!1))return void(g.length=0);j.push(sf(a,l));var m=i?gd(a,l):gg(g);od(a,l,m,ke(a,l)),!i&&a.cm&&a.cm.scrollIntoView({from:l.from,to:ed(l)});var n=[];gf(a,function(a,b){b||-1!=ig(n,a.history)||(Ff(a.history,l),n.push(a.history)),od(a,l,null,ke(a,l))})}}}}function nd(a,b){if(0!=b&&(a.first+=b,a.sel=new Ka(jg(a.sel.ranges,function(a){return new La(qa(a.anchor.line+b,a.anchor.ch),qa(a.head.line+b,a.head.ch))}),a.sel.primIndex),a.cm)){lc(a.cm,a.first,a.first-b,b);for(var c=a.cm.display,d=c.viewFrom;da.lastLine())){if(b.from.linef&&(b={from:b.from,to:qa(f,jf(a,f).text.length),text:[b.text[0]],origin:b.origin}),b.removed=kf(a,b.from,b.to),c||(c=gd(a,b)),a.cm?pd(a.cm,b,d):_e(a,b,d),_a(a,c,$f)}}function pd(a,b,c){var d=a.doc,e=a.display,f=b.from,g=b.to,h=!1,i=f.line;a.options.lineWrapping||(i=nf(ve(jf(d,f.line))),d.iter(i,g.line+1,function(a){return a==e.maxLine?(h=!0,!0):void 0})),d.sel.contains(b.from,b.to)>-1&&Vf(a),_e(d,b,c,C(a)),a.options.lineWrapping||(d.iter(i,f.line+b.text.length,function(a){var b=I(a);b>e.maxLineLength&&(e.maxLine=a,e.maxLineLength=b,e.maxLineChanged=!0,h=!1)}),h&&(a.curOp.updateMaxLine=!0)),d.frontier=Math.min(d.frontier,f.line),lb(a,400);var j=b.text.length-(g.line-f.line)-1;b.full?lc(a):f.line!=g.line||1!=b.text.length||$e(a.doc,b)?lc(a,f.line,g.line+1,j):mc(a,f.line,"text");var k=Wf(a,"changes"),l=Wf(a,"change");if(l||k){var m={from:f,to:g,text:b.text,removed:b.removed,origin:b.origin};l&&Sf(a,"change",a,m),k&&(a.curOp.changeObjs||(a.curOp.changeObjs=[])).push(m)}a.display.selForContextMenu=null}function qd(a,b,c,d,e){if(d||(d=c),ra(d,c)<0){var f=d;d=c,c=f}"string"==typeof b&&(b=a.splitLines(b)),kd(a,{from:c,to:d,text:b,origin:e})}function rd(a,b){if(!Uf(a,"scrollCursorIntoView")){var c=a.display,d=c.sizer.getBoundingClientRect(),e=null;if(b.top+d.top<0?e=!0:b.bottom+d.top>(window.innerHeight||document.documentElement.clientHeight)&&(e=!1),null!=e&&!n){var f=ug("div","\u200b",null,"position: absolute; top: "+(b.top-c.viewOffset-pb(a.display))+"px; height: "+(b.bottom-b.top+sb(a)+c.barHeight)+"px; left: "+b.left+"px; width: 2px;");a.display.lineSpace.appendChild(f),f.scrollIntoView(e),a.display.lineSpace.removeChild(f)}}}function sd(a,b,c,d){null==d&&(d=0);for(var e=0;5>e;e++){var f=!1,g=Ob(a,b),h=c&&c!=b?Ob(a,c):g,i=ud(a,Math.min(g.left,h.left),Math.min(g.top,h.top)-d,Math.max(g.left,h.left),Math.max(g.bottom,h.bottom)+d),j=a.doc.scrollTop,k=a.doc.scrollLeft;if(null!=i.scrollTop&&(Kc(a,i.scrollTop),Math.abs(a.doc.scrollTop-j)>1&&(f=!0)),null!=i.scrollLeft&&(Lc(a,i.scrollLeft),Math.abs(a.doc.scrollLeft-k)>1&&(f=!0)),!f)break}return g}function td(a,b,c,d,e){var f=ud(a,b,c,d,e);null!=f.scrollTop&&Kc(a,f.scrollTop),null!=f.scrollLeft&&Lc(a,f.scrollLeft)}function ud(a,b,c,d,e){var f=a.display,g=Ub(a.display);0>c&&(c=0);var h=a.curOp&&null!=a.curOp.scrollTop?a.curOp.scrollTop:f.scroller.scrollTop,i=ub(a),j={};e-c>i&&(e=c+i);var k=a.doc.height+qb(f),l=g>c,m=e>k-g;if(h>c)j.scrollTop=l?0:c;else if(e>h+i){var n=Math.min(c,(m?k:e)-i);n!=h&&(j.scrollTop=n)}var o=a.curOp&&null!=a.curOp.scrollLeft?a.curOp.scrollLeft:f.scroller.scrollLeft,p=tb(a)-(a.options.fixedGutter?f.gutters.offsetWidth:0),q=d-b>p;return q&&(d=b+p),10>b?j.scrollLeft=0:o>b?j.scrollLeft=Math.max(0,b-(q?0:10)):d>p+o-3&&(j.scrollLeft=d+(q?0:10)-p),j}function vd(a,b,c){(null!=b||null!=c)&&xd(a),null!=b&&(a.curOp.scrollLeft=(null==a.curOp.scrollLeft?a.doc.scrollLeft:a.curOp.scrollLeft)+b),null!=c&&(a.curOp.scrollTop=(null==a.curOp.scrollTop?a.doc.scrollTop:a.curOp.scrollTop)+c)}function wd(a){xd(a);var b=a.getCursor(),c=b,d=b;a.options.lineWrapping||(c=b.ch?qa(b.line,b.ch-1):b,d=qa(b.line,b.ch+1)),a.curOp.scrollToPos={from:c,to:d,margin:a.options.cursorScrollMargin,isCursor:!0}}function xd(a){var b=a.curOp.scrollToPos;if(b){a.curOp.scrollToPos=null;var c=Pb(a,b.from),d=Pb(a,b.to),e=ud(a,Math.min(c.left,d.left),Math.min(c.top,d.top)-b.margin,Math.max(c.right,d.right),Math.max(c.bottom,d.bottom)+b.margin); +a.scrollTo(e.scrollLeft,e.scrollTop)}}function yd(a,b,c,d){var f,e=a.doc;null==c&&(c="add"),"smart"==c&&(e.mode.indent?f=ob(a,b):c="prev");var g=a.options.tabSize,h=jf(e,b),i=cg(h.text,null,g);h.stateAfter&&(h.stateAfter=null);var k,j=h.text.match(/^\s*/)[0];if(d||/\S/.test(h.text)){if("smart"==c&&(k=e.mode.indent(f,h.text.slice(j.length),h.text),k==Zf||k>150)){if(!d)return;c="prev"}}else k=0,c="not";"prev"==c?k=b>e.first?cg(jf(e,b-1).text,null,g):0:"add"==c?k=i+a.options.indentUnit:"subtract"==c?k=i-a.options.indentUnit:"number"==typeof c&&(k=i+c),k=Math.max(0,k);var l="",m=0;if(a.options.indentWithTabs)for(var n=Math.floor(k/g);n;--n)m+=g,l+=" ";if(k>m&&(l+=fg(k-m)),l!=j)return qd(e,l,qa(b,0),qa(b,j.length),"+input"),h.stateAfter=null,!0;for(var n=0;n=0;b--)qd(a.doc,"",d[b].from,d[b].to,"+delete");wd(a)})}function Bd(a,b,c,d,e){function k(){var b=f+c;return b=a.first+a.size?j=!1:(f=b,i=jf(a,b))}function l(a){var b=(e?dh:eh)(i,g,c,!0);if(null==b){if(a||!k())return j=!1;g=e?(0>c?Xg:Wg)(i):0>c?i.text.length:0}else g=b;return!0}var f=b.line,g=b.ch,h=c,i=jf(a,f),j=!0;if("char"==d)l();else if("column"==d)l(!0);else if("word"==d||"group"==d)for(var m=null,n="group"==d,o=a.cm&&a.cm.getHelper(b,"wordChars"),p=!0;!(0>c)||l(!p);p=!1){var q=i.text.charAt(g)||"\n",r=qg(q,o)?"w":n&&"\n"==q?"n":!n||/\s/.test(q)?null:"p";if(!n||p||r||(r="s"),m&&m!=r){0>c&&(c=1,l());break}if(r&&(m=r),c>0&&!l(!p))break}var s=eb(a,qa(f,g),b,h,!0);return j||(s.hitSide=!0),s}function Cd(a,b,c,d){var g,e=a.doc,f=b.left;if("page"==d){var h=Math.min(a.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight);g=b.top+c*(h-(0>c?1.5:.5)*Ub(a.display))}else"line"==d&&(g=c>0?b.bottom+3:b.top-3);for(;;){var i=Rb(a,f,g);if(!i.outside)break;if(0>c?0>=g:g>=e.height){i.hitSide=!0;break}g+=5*c}return i}function Fd(a,b,c,d){x.defaults[a]=b,c&&(Ed[a]=d?function(a,b,d){d!=Gd&&c(a,b,d)}:c)}function Qd(a){for(var c,d,e,f,b=a.split(/-(?!$)/),a=b[b.length-1],g=0;g0||0==g&&f.clearWhenEmpty!==!1)return f;if(f.replacedWith&&(f.collapsed=!0,f.widgetNode=ug("span",[f.replacedWith],"CodeMirror-widget"),d.handleMouseEvents||f.widgetNode.setAttribute("cm-ignore-events","true"),d.insertLeft&&(f.widgetNode.insertLeft=!0)),f.collapsed){if(ue(a,b.line,b,c,f)||b.line!=c.line&&ue(a,c.line,b,c,f))throw new Error("Inserting collapsed marker partially overlapping an existing one");w=!0}f.addToHistory&&vf(a,{from:b,to:c,origin:"markText"},a.sel,NaN);var j,h=b.line,i=a.cm;if(a.iter(h,c.line+1,function(a){i&&f.collapsed&&!i.options.lineWrapping&&ve(a)==i.display.maxLine&&(j=!0),f.collapsed&&h!=b.line&&mf(a,0),fe(a,new ce(f,h==b.line?b.ch:null,h==c.line?c.ch:null)),++h}),f.collapsed&&a.iter(b.line,c.line+1,function(b){ze(a,b)&&mf(b,0)}),f.clearOnEnter&&Mf(f,"beforeCursorEnter",function(){f.clear()}),f.readOnly&&(v=!0,(a.history.done.length||a.history.undone.length)&&a.clearHistory()),f.collapsed&&(f.id=++Wd,f.atomic=!0),i){if(j&&(i.curOp.updateMaxLine=!0),f.collapsed)lc(i,b.line,c.line+1);else if(f.className||f.title||f.startStyle||f.endStyle||f.css)for(var k=b.line;k<=c.line;k++)mc(i,k,"text");f.atomic&&bb(i.doc),Sf(i,"markerAdded",i,f)}return f}function $d(a,b,c,d,e){d=mg(d),d.shared=!1;var f=[Yd(a,b,c,d,e)],g=f[0],h=d.widgetNode;return gf(a,function(a){h&&(d.widgetNode=h.cloneNode(!0)),f.push(Yd(a,Pa(a,b),Pa(a,c),d,e));for(var i=0;i=b:f.to>b);(e||(e=[])).push(new ce(g,f.from,i?null:f.to))}}return e}function he(a,b,c){if(a)for(var e,d=0;d=b:f.to>b);if(h||f.from==b&&"bookmark"==g.type&&(!c||f.marker.insertLeft)){var i=null==f.from||(g.inclusiveLeft?f.from<=b:f.from0&&h)for(var l=0;ll;++l)o.push(q);o.push(i)}return o}function je(a){for(var b=0;b0)){var k=[i,1],l=ra(j.from,h.from),m=ra(j.to,h.to);(0>l||!g.inclusiveLeft&&!l)&&k.push({from:j.from,to:h.from}),(m>0||!g.inclusiveRight&&!m)&&k.push({from:h.to,to:j.to}),e.splice.apply(e,k),i+=k.length-1}}return e}function me(a){var b=a.markedSpans;if(b){for(var c=0;c=0&&0>=l||0>=k&&l>=0)&&(0>=k&&(ra(j.to,c)>0||i.marker.inclusiveRight&&e.inclusiveLeft)||k>=0&&(ra(j.from,d)<0||i.marker.inclusiveLeft&&e.inclusiveRight)))return!0}}}function ve(a){for(var b;b=se(a);)a=b.find(-1,!0).line;return a}function we(a){for(var b,c;b=te(a);)a=b.find(1,!0).line,(c||(c=[])).push(a);return c}function xe(a,b){var c=jf(a,b),d=ve(c);return c==d?b:nf(d)}function ye(a,b){if(b>a.lastLine())return b;var d,c=jf(a,b);if(!ze(a,c))return b;for(;d=te(c);)c=d.find(1,!0).line;return nf(c)+1}function ze(a,b){var c=w&&b.markedSpans;if(c)for(var d,e=0;ee;e++){d&&(d[0]=x.innerMode(a,c).mode);var f=a.token(b,c);if(b.pos>b.start)return f}throw new Error("Mode "+a.name+" failed to advance stream.")}function Le(a,b,c,d){function e(a){return{start:k.start,end:k.pos,string:k.current(),type:h||null,state:a?Md(f.mode,j):j}}var h,f=a.doc,g=f.mode;b=Pa(f,b);var l,i=jf(f,b.line),j=ob(a,b.line,c),k=new Vd(i.text,a.options.tabSize);for(d&&(l=[]);(d||k.posa.options.maxHighlightLength?(h=!1,g&&Pe(a,b,d,k.pos),k.pos=b.length,l=null):l=Ie(Ke(c,k,d,m),f),m){var n=m[0].name;n&&(l="m-"+(l?n+" "+l:n))}if(!h||j!=l){for(;ij;){var d=e[i];d>a&&e.splice(i,1,a,e[i+1],d),i+=2,j=Math.min(a,d)}if(b)if(h.opaque)e.splice(c,i-c,a,"cm-overlay "+b),i=c+2;else for(;i>c;c+=2){var f=e[c+1];e[c+1]=(f?f+" ":"")+"cm-overlay "+b}},f)}return{styles:e,classes:f.bgClass||f.textClass?f:null}}function Oe(a,b,c){if(!b.styles||b.styles[0]!=a.state.modeGen){var d=ob(a,nf(b)),e=Ne(a,b,b.text.length>a.options.maxHighlightLength?Md(a.doc.mode,d):d);b.stateAfter=d,b.styles=e.styles,e.classes?b.styleClasses=e.classes:b.styleClasses&&(b.styleClasses=null),c===a.doc.frontier&&a.doc.frontier++}return b.styles}function Pe(a,b,c,d){var e=a.doc.mode,f=new Vd(b,a.options.tabSize);for(f.start=f.pos=d||0,""==b&&Je(e,c);!f.eol();)Ke(e,f,c),f.start=f.pos}function Se(a,b){if(!a||/^\s*$/.test(a))return null;var c=b.addModeClass?Re:Qe;return c[a]||(c[a]=a.replace(/\S+/g,"cm-$&"))}function Te(a,b){var c=ug("span",null,null,h?"padding-right: .1px":null),d={pre:ug("pre",[c],"CodeMirror-line"),content:c,col:0,pos:0,cm:a,splitSpaces:(f||h)&&a.getOption("lineWrapping")};b.measure={};for(var e=0;e<=(b.rest?b.rest.length:0);e++){var i,g=e?b.rest[e-1]:b.line;d.pos=0,d.addToken=Ve,Mg(a.display.measure)&&(i=qf(g))&&(d.addToken=Xe(d.addToken,i)),d.map=[];var j=b!=a.display.externalMeasured&&nf(g);Ze(g,d,Oe(a,g,j)),g.styleClasses&&(g.styleClasses.bgClass&&(d.bgClass=Dg(g.styleClasses.bgClass,d.bgClass||"")),g.styleClasses.textClass&&(d.textClass=Dg(g.styleClasses.textClass,d.textClass||""))),0==d.map.length&&d.map.push(0,0,d.content.appendChild(Kg(a.display.measure))),0==e?(b.measure.map=d.map,b.measure.cache={}):((b.measure.maps||(b.measure.maps=[])).push(d.map),(b.measure.caches||(b.measure.caches=[])).push({}))}return h&&/\bcm-tab\b/.test(d.content.lastChild.className)&&(d.content.className="cm-tab-wrap-hack"),Qf(a,"renderLine",a,b.line,d.pre),d.pre.className&&(d.textClass=Dg(d.pre.className,d.textClass||"")),d}function Ue(a){var b=ug("span","\u2022","cm-invalidchar");return b.title="\\u"+a.charCodeAt(0).toString(16),b.setAttribute("aria-label",b.title),b}function Ve(a,b,c,d,e,h,i){if(b){var j=a.splitSpaces?b.replace(/ {3,}/g,We):b,k=a.cm.state.specialChars,l=!1;if(k.test(b))for(var m=document.createDocumentFragment(),n=0;;){k.lastIndex=n;var o=k.exec(b),p=o?o.index-n:b.length-n;if(p){var q=document.createTextNode(j.slice(n,n+p));f&&9>g?m.appendChild(ug("span",[q])):m.appendChild(q),a.map.push(a.pos,a.pos+p,q),a.col+=p,a.pos+=p}if(!o)break;if(n+=p+1," "==o[0]){var r=a.cm.options.tabSize,s=r-a.col%r,q=m.appendChild(ug("span",fg(s),"cm-tab"));q.setAttribute("role","presentation"),q.setAttribute("cm-text"," "),a.col+=s}else if("\r"==o[0]||"\n"==o[0]){var q=m.appendChild(ug("span","\r"==o[0]?"\u240d":"\u2424","cm-invalidchar"));q.setAttribute("cm-text",o[0]),a.col+=1}else{var q=a.cm.options.specialCharPlaceholder(o[0]);q.setAttribute("cm-text",o[0]),f&&9>g?m.appendChild(ug("span",[q])):m.appendChild(q),a.col+=1}a.map.push(a.pos,a.pos+1,q),a.pos++}else{a.col+=b.length;var m=document.createTextNode(j);a.map.push(a.pos,a.pos+b.length,m),f&&9>g&&(l=!0),a.pos+=b.length}if(c||d||e||l||i){var t=c||"";d&&(t+=d),e&&(t+=e);var u=ug("span",[m],t,i);return h&&(u.title=h),a.content.appendChild(u)}a.content.appendChild(m)}}function We(a){for(var b=" ",c=0;cj&&m.from<=j)break}if(m.to>=k)return a(c,d,e,f,g,h,i);a(c,d.slice(0,m.to-j),e,f,null,h,i),f=null,d=d.slice(m.to-j),j=m.to}}}function Ye(a,b,c,d){var e=!d&&c.widgetNode;e&&a.map.push(a.pos,a.pos+b,e),!d&&a.cm.display.input.needsContentAttribute&&(e||(e=a.content.appendChild(document.createElement("span"))),e.setAttribute("cm-marker",c.id)),e&&(a.cm.display.input.setUneditable(e),a.content.appendChild(e)),a.pos+=b}function Ze(a,b,c){var d=a.markedSpans,e=a.text,f=0;if(d)for(var k,l,n,o,p,q,r,h=e.length,i=0,g=1,j="",m=0;;){if(m==i){n=o=p=q=l="",r=null,m=1/0;for(var t,s=[],u=0;ui||w.collapsed&&v.to==i&&v.from==i)?(null!=v.to&&v.to!=i&&m>v.to&&(m=v.to,o=""),w.className&&(n+=" "+w.className),w.css&&(l=(l?l+";":"")+w.css),w.startStyle&&v.from==i&&(p+=" "+w.startStyle),w.endStyle&&v.to==m&&(t||(t=[])).push(w.endStyle,v.to),w.title&&!q&&(q=w.title),w.collapsed&&(!r||qe(r.marker,w)<0)&&(r=v)):v.from>i&&m>v.from&&(m=v.from)}if(t)for(var u=0;u=h)break;for(var x=Math.min(h,m);;){if(j){var y=i+j.length;if(!r){var z=y>x?j.slice(0,x-i):j;b.addToken(b,z,k?k+n:n,p,i+z.length==m?o:"",q,l)}if(y>=x){j=j.slice(x-i),i=x;break}i=y,p=""}j=e.slice(f,f=c[g++]),k=Se(c[g++],b.cm.options)}}else for(var g=1;gc;++c)f.push(new Fe(j[c],e(c),d));return f}var h=b.from,i=b.to,j=b.text,k=jf(a,h.line),l=jf(a,i.line),m=gg(j),n=e(j.length-1),o=i.line-h.line;if(b.full)a.insert(0,g(0,j.length)),a.remove(j.length,a.size-j.length);else if($e(a,b)){var p=g(0,j.length-1);f(l,l.text,n),o&&a.remove(h.line,o),p.length&&a.insert(h.line,p)}else if(k==l)if(1==j.length)f(k,k.text.slice(0,h.ch)+m+k.text.slice(i.ch),n);else{var p=g(1,j.length-1);p.push(new Fe(m+k.text.slice(i.ch),n,d)),f(k,k.text.slice(0,h.ch)+j[0],e(0)),a.insert(h.line+1,p)}else if(1==j.length)f(k,k.text.slice(0,h.ch)+j[0]+l.text.slice(i.ch),e(0)),a.remove(h.line+1,o);else{f(k,k.text.slice(0,h.ch)+j[0],e(0)),f(l,m+l.text.slice(i.ch),n);var p=g(1,j.length-1);o>1&&a.remove(h.line+1,o-1),a.insert(h.line+1,p)}Sf(a,"change",a,b)}function af(a){this.lines=a,this.parent=null;for(var b=0,c=0;bb||b>=a.size)throw new Error("There is no line "+(b+a.first)+" in the document.");for(var c=a;!c.lines;)for(var d=0;;++d){var e=c.children[d],f=e.chunkSize();if(f>b){c=e;break}b-=f}return c.lines[b]}function kf(a,b,c){var d=[],e=b.line;return a.iter(b.line,c.line+1,function(a){var f=a.text;e==c.line&&(f=f.slice(0,c.ch)),e==b.line&&(f=f.slice(b.ch)),d.push(f),++e}),d}function lf(a,b,c){var d=[];return a.iter(b,c,function(a){d.push(a.text)}),d}function mf(a,b){var c=b-a.height;if(c)for(var d=a;d;d=d.parent)d.height+=c}function nf(a){if(null==a.parent)return null;for(var b=a.parent,c=ig(b.lines,a),d=b.parent;d;b=d,d=d.parent)for(var e=0;d.children[e]!=b;++e)c+=d.children[e].chunkSize();return c+b.first}function of(a,b){var c=a.first;a:do{for(var d=0;db){a=e;continue a}b-=f,c+=e.chunkSize()}return c}while(!a.lines);for(var d=0;db)break;b-=h}return c+d}function pf(a){a=ve(a);for(var b=0,c=a.parent,d=0;d1&&!a.done[a.done.length-2].ranges?(a.done.pop(),gg(a.done)):void 0}function vf(a,b,c,d){var e=a.history;e.undone.length=0;var g,f=+new Date;if((e.lastOp==d||e.lastOrigin==b.origin&&b.origin&&("+"==b.origin.charAt(0)&&a.cm&&e.lastModTime>f-a.cm.options.historyEventDelay||"*"==b.origin.charAt(0)))&&(g=uf(e,e.lastOp==d))){var h=gg(g.changes);0==ra(b.from,b.to)&&0==ra(b.from,h.to)?h.to=ed(b):g.changes.push(sf(a,b))}else{var i=gg(e.done);for(i&&i.ranges||yf(a.sel,e.done),g={changes:[sf(a,b)],generation:e.generation},e.done.push(g);e.done.length>e.undoDepth;)e.done.shift(),e.done[0].ranges||e.done.shift()}e.done.push(c),e.generation=++e.maxGeneration,e.lastModTime=e.lastSelTime=f,e.lastOp=e.lastSelOp=d,e.lastOrigin=e.lastSelOrigin=b.origin,h||Qf(a,"historyAdded")}function wf(a,b,c,d){var e=b.charAt(0);return"*"==e||"+"==e&&c.ranges.length==d.ranges.length&&c.somethingSelected()==d.somethingSelected()&&new Date-a.history.lastSelTime<=(a.cm?a.cm.options.historyEventDelay:500)}function xf(a,b,c,d){var e=a.history,f=d&&d.origin;c==e.lastSelOp||f&&e.lastSelOrigin==f&&(e.lastModTime==e.lastSelTime&&e.lastOrigin==f||wf(a,f,gg(e.done),b))?e.done[e.done.length-1]=b:yf(b,e.done),e.lastSelTime=+new Date,e.lastSelOrigin=f,e.lastSelOp=c,d&&d.clearRedo!==!1&&tf(e.undone)}function yf(a,b){var c=gg(b);c&&c.ranges&&c.equals(a)||b.push(a)}function zf(a,b,c,d){var e=b["spans_"+a.id],f=0;a.iter(Math.max(a.first,c),Math.min(a.first+a.size,d),function(c){c.markedSpans&&((e||(e=b["spans_"+a.id]={}))[f]=c.markedSpans),++f})}function Af(a){if(!a)return null;for(var c,b=0;b-1&&(gg(h)[l]=j[l],delete j[l])}}}return e}function Df(a,b,c,d){c0?d.slice():Nf:d||Nf}function Sf(a,b){function f(a){return function(){a.apply(null,d)}}var c=Of(a,b,!1);if(c.length){var e,d=Array.prototype.slice.call(arguments,2);Wb?e=Wb.delayedCallbacks:Rf?e=Rf:(e=Rf=[],setTimeout(Tf,0));for(var g=0;g0}function Xf(a){a.prototype.on=function(a,b){Mf(this,a,b)},a.prototype.off=function(a,b){Pf(this,a,b)}}function bg(){this.id=null}function fg(a){for(;eg.length<=a;)eg.push(gg(eg)+" ");return eg[a]}function gg(a){return a[a.length-1]}function ig(a,b){for(var c=0;c-1&&pg(a)?!0:b.test(a):pg(a)}function rg(a){for(var b in a)if(a.hasOwnProperty(b)&&a[b])return!1;return!0}function tg(a){return a.charCodeAt(0)>=768&&sg.test(a)}function ug(a,b,c,d){var e=document.createElement(a);if(c&&(e.className=c),d&&(e.style.cssText=d),"string"==typeof b)e.appendChild(document.createTextNode(b));else if(b)for(var f=0;f0;--b)a.removeChild(a.firstChild);return a}function xg(a,b){return wg(a).appendChild(b)}function zg(){for(var a=document.activeElement;a&&a.root&&a.root.activeElement;)a=a.root.activeElement;return a}function Ag(a){return new RegExp("(^|\\s)"+a+"(?:$|\\s)\\s*")}function Dg(a,b){for(var c=a.split(" "),d=0;d2&&!(f&&8>g))}var c=Jg?ug("span","\u200b"):ug("span","\xa0",null,"display: inline-block; width: 1px; margin-right: -1px");return c.setAttribute("cm-text",""),c}function Mg(a){if(null!=Lg)return Lg;var b=xg(a,document.createTextNode("A\u062eA")),c=vg(b,0,1).getBoundingClientRect();if(!c||c.left==c.right)return!1;var d=vg(b,1,2).getBoundingClientRect();return Lg=d.right-c.right<3}function Rg(a){if(null!=Qg)return Qg;var b=xg(a,ug("span","x")),c=b.getBoundingClientRect(),d=vg(b,0,1).getBoundingClientRect();return Qg=Math.abs(c.left-d.left)>1}function Tg(a,b,c,d){if(!a)return d(b,c,"ltr");for(var e=!1,f=0;fb||b==c&&g.to==b)&&(d(Math.max(g.from,b),Math.min(g.to,c),1==g.level?"rtl":"ltr"),e=!0)}e||d(b,c,"ltr")}function Ug(a){return a.level%2?a.to:a.from}function Vg(a){return a.level%2?a.from:a.to}function Wg(a){var b=qf(a);return b?Ug(b[0]):0}function Xg(a){var b=qf(a);return b?Vg(gg(b)):a.text.length}function Yg(a,b){var c=jf(a.doc,b),d=ve(c);d!=c&&(b=nf(d));var e=qf(d),f=e?e[0].level%2?Xg(d):Wg(d):0;return qa(b,f)}function Zg(a,b){for(var c,d=jf(a.doc,b);c=te(d);)d=c.find(1,!0).line,b=null;var e=qf(d),f=e?e[0].level%2?Wg(d):Xg(d):d.text.length;return qa(null==b?nf(d):b,f)}function $g(a,b){var c=Yg(a,b.line),d=jf(a.doc,c.line),e=qf(d);if(!e||0==e[0].level){var f=Math.max(0,d.text.search(/\S/)),g=b.line==c.line&&b.ch<=f&&b.ch;return qa(c.line,g?0:f)}return c}function _g(a,b,c){var d=a[0].level;return b==d?!0:c==d?!1:c>b}function bh(a,b){ah=null;for(var d,c=0;cb)return c;if(e.from==b||e.to==b){if(null!=d)return _g(a,e.level,a[d].level)?(e.from!=e.to&&(ah=d),c):(e.from!=e.to&&(ah=c),d);d=c}}return d}function ch(a,b,c,d){if(!d)return b+c;do b+=c;while(b>0&&tg(a.text.charAt(b)));return b}function dh(a,b,c,d){var e=qf(a);if(!e)return eh(a,b,c,d);for(var f=bh(e,b),g=e[f],h=ch(a,b,g.level%2?-c:c,d);;){if(h>g.from&&h0==g.level%2?g.to:g.from);if(g=e[f+=c],!g)return null;h=c>0==g.level%2?ch(a,g.to,-1,d):ch(a,g.from,1,d)}}function eh(a,b,c,d){var e=b+c;if(d)for(;e>0&&tg(a.text.charAt(e));)e+=c;return 0>e||e>a.text.length?null:e}var a=navigator.userAgent,b=navigator.platform,c=/gecko\/\d/i.test(a),d=/MSIE \d/.test(a),e=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(a),f=d||e,g=f&&(d?document.documentMode||6:e[1]),h=/WebKit\//.test(a),i=h&&/Qt\/\d+\.\d+/.test(a),j=/Chrome\//.test(a),k=/Opera\//.test(a),l=/Apple Computer/.test(navigator.vendor),m=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(a),n=/PhantomJS/.test(a),o=/AppleWebKit/.test(a)&&/Mobile\/\w+/.test(a),p=o||/Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(a),q=o||/Mac/.test(b),r=/win/i.test(b),s=k&&a.match(/Version\/(\d*\.\d*)/);s&&(s=Number(s[1])),s&&s>=15&&(k=!1,h=!0);var t=q&&(i||k&&(null==s||12.11>s)),u=c||f&&g>=9,v=!1,w=!1;M.prototype=mg({update:function(a){var b=a.scrollWidth>a.clientWidth+1,c=a.scrollHeight>a.clientHeight+1,d=a.nativeBarWidth;if(c){this.vert.style.display="block",this.vert.style.bottom=b?d+"px":"0";var e=a.viewHeight-(b?d:0);this.vert.firstChild.style.height=Math.max(0,a.scrollHeight-a.clientHeight+e)+"px"}else this.vert.style.display="",this.vert.firstChild.style.height="0";if(b){this.horiz.style.display="block",this.horiz.style.right=c?d+"px":"0",this.horiz.style.left=a.barLeft+"px";var f=a.viewWidth-a.barLeft-(c?d:0);this.horiz.firstChild.style.width=a.scrollWidth-a.clientWidth+f+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&a.clientHeight>0&&(0==d&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:c?d:0,bottom:b?d:0}},setScrollLeft:function(a){this.horiz.scrollLeft!=a&&(this.horiz.scrollLeft=a),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz)},setScrollTop:function(a){this.vert.scrollTop!=a&&(this.vert.scrollTop=a),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert)},zeroWidthHack:function(){var a=q&&!m?"12px":"18px";this.horiz.style.height=this.vert.style.width=a,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new bg,this.disableVert=new bg},enableZeroWidthBar:function(a,b){function c(){var d=a.getBoundingClientRect(),e=document.elementFromPoint(d.left+1,d.bottom-1);e!=a?a.style.pointerEvents="none":b.set(1e3,c)}a.style.pointerEvents="auto",b.set(1e3,c)},clear:function(){var a=this.horiz.parentNode;a.removeChild(this.horiz),a.removeChild(this.vert)}},M.prototype),N.prototype=mg({update:function(){return{bottom:0,right:0}},setScrollLeft:function(){},setScrollTop:function(){},clear:function(){}},N.prototype),x.scrollbarModel={"native":M,"null":N},W.prototype.signal=function(a,b){Wf(a,b)&&this.events.push(arguments)},W.prototype.finish=function(){for(var a=0;a=9&&b.hasSelection&&(b.hasSelection=null),b.poll()}),Mf(e,"paste",function(a){Uf(c,a)||ya(a,c)||(c.state.pasteIncoming=!0,b.fastPoll())}),Mf(e,"cut",h),Mf(e,"copy",h),Mf(a.scroller,"paste",function(d){vc(a,d)||Uf(c,d)||(c.state.pasteIncoming=!0,b.focus())}),Mf(a.lineSpace,"selectstart",function(b){vc(a,b)||Gf(b)}),Mf(e,"compositionstart",function(){var a=c.getCursor("from");b.composing&&b.composing.range.clear(),b.composing={start:a,range:c.markText(a,c.getCursor("to"),{className:"CodeMirror-composing"})}}),Mf(e,"compositionend",function(){b.composing&&(b.poll(),b.composing.range.clear(),b.composing=null)})},prepareSelection:function(){var a=this.cm,b=a.display,c=a.doc,d=hb(a);if(a.options.moveInputWithCursor){var e=Ob(a,c.sel.primary().head,"div"),f=b.wrapper.getBoundingClientRect(),g=b.lineDiv.getBoundingClientRect();d.teTop=Math.max(0,Math.min(b.wrapper.clientHeight-10,e.top+g.top-f.top)),d.teLeft=Math.max(0,Math.min(b.wrapper.clientWidth-10,e.left+g.left-f.left))}return d},showSelection:function(a){var b=this.cm,c=b.display;xg(c.cursorDiv,a.cursors),xg(c.selectionDiv,a.selection),null!=a.teTop&&(this.wrapper.style.top=a.teTop+"px",this.wrapper.style.left=a.teLeft+"px")},reset:function(a){if(!this.contextMenuPending){var b,c,d=this.cm,e=d.doc;if(d.somethingSelected()){this.prevInput="";var h=e.sel.primary();b=Pg&&(h.to().line-h.from().line>100||(c=d.getSelection()).length>1e3);var i=b?"-":c||d.getSelection();this.textarea.value=i,d.state.focused&&hg(this.textarea),f&&g>=9&&(this.hasSelection=i)}else a||(this.prevInput=this.textarea.value="",f&&g>=9&&(this.hasSelection=null));this.inaccurateSelection=b}},getField:function(){return this.textarea},supportsTouch:function(){return!1},focus:function(){if("nocursor"!=this.cm.options.readOnly&&(!p||zg()!=this.textarea))try{this.textarea.focus()}catch(a){}},blur:function(){this.textarea.blur()},resetPosition:function(){this.wrapper.style.top=this.wrapper.style.left=0},receivedFocus:function(){this.slowPoll()},slowPoll:function(){var a=this;a.pollingFast||a.polling.set(this.cm.options.pollInterval,function(){a.poll(),a.cm.state.focused&&a.slowPoll()})},fastPoll:function(){function c(){var d=b.poll();d||a?(b.pollingFast=!1,b.slowPoll()):(a=!0,b.polling.set(60,c))}var a=!1,b=this;b.pollingFast=!0,b.polling.set(20,c)},poll:function(){var a=this.cm,b=this.textarea,c=this.prevInput;if(this.contextMenuPending||!a.state.focused||Og(b)&&!c&&!this.composing||a.isReadOnly()||a.options.disableInput||a.state.keySeq)return!1;var d=b.value;if(d==c&&!a.somethingSelected())return!1;if(f&&g>=9&&this.hasSelection===d||q&&/[\uf700-\uf7ff]/.test(d))return a.display.input.reset(),!1;if(a.doc.sel==a.display.selForContextMenu){var e=d.charCodeAt(0);if(8203!=e||c||(c="\u200b"),8666==e)return this.reset(),this.cm.execCommand("undo")}for(var h=0,i=Math.min(c.length,d.length);i>h&&c.charCodeAt(h)==d.charCodeAt(h);)++h;var j=this;return fc(a,function(){xa(a,d.slice(h),c.length-h,null,j.composing?"*compose":null),d.length>1e3||d.indexOf("\n")>-1?b.value=j.prevInput="":j.prevInput=d,j.composing&&(j.composing.range.clear(),j.composing.range=a.markText(j.composing.start,a.getCursor("to"),{className:"CodeMirror-composing"}))}),!0},ensurePolled:function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},onKeyPress:function(){f&&g>=9&&(this.hasSelection=null),this.fastPoll()},onContextMenu:function(a){function o(){if(null!=e.selectionStart){var a=c.somethingSelected(),f="\u200b"+(a?e.value:"");e.value="\u21da",e.value=f,b.prevInput=a?"":"\u200b",e.selectionStart=1,e.selectionEnd=f.length,d.selForContextMenu=c.doc.sel}}function p(){if(b.contextMenuPending=!1,b.wrapper.style.position="relative",e.style.cssText=m,f&&9>g&&d.scrollbars.setScrollTop(d.scroller.scrollTop=j),null!=e.selectionStart){(!f||f&&9>g)&&o();var a=0,h=function(){d.selForContextMenu==c.doc.sel&&0==e.selectionStart&&e.selectionEnd>0&&"\u200b"==b.prevInput?gc(c,Od.selectAll)(c):a++<10?d.detectingSelectAll=setTimeout(h,500):d.input.reset()};d.detectingSelectAll=setTimeout(h,200)}}var b=this,c=b.cm,d=c.display,e=b.textarea,i=wc(c,a),j=d.scroller.scrollTop;if(i&&!k){var l=c.options.resetSelectionOnContextMenu;l&&-1==c.doc.sel.contains(i)&&gc(c,$a)(c.doc,Na(i),$f);var m=e.style.cssText;if(b.wrapper.style.position="absolute",e.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(a.clientY-5)+"px; left: "+(a.clientX-5)+"px; z-index: 1000; background: "+(f?"rgba(255, 255, 255, .05)":"transparent")+"; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",h)var n=window.scrollY;if(d.input.focus(),h&&window.scrollTo(null,n),d.input.reset(),c.somethingSelected()||(e.value=b.prevInput=" "),b.contextMenuPending=!0,d.selForContextMenu=c.doc.sel,clearTimeout(d.detectingSelectAll),f&&g>=9&&o(),u){Jf(a);var q=function(){Pf(window,"mouseup",q),setTimeout(p,20)};Mf(window,"mouseup",q)}else setTimeout(p,50)}},readOnlyChanged:function(a){a||this.reset()},setUneditable:kg,needsContentAttribute:!1},Ca.prototype),Ea.prototype=mg({init:function(a){function e(a){if(c.somethingSelected())wa=c.getSelections(),"cut"==a.type&&c.replaceSelection("",null,"cut");else{if(!c.options.lineWiseCopyCut)return;var b=Aa(c);wa=b.text,"cut"==a.type&&c.operation(function(){c.setSelections(b.ranges,0,$f),c.replaceSelection("",null,"cut")})}if(a.clipboardData&&!o)a.preventDefault(),a.clipboardData.clearData(),a.clipboardData.setData("text/plain",wa.join("\n"));else{var d=Da(),e=d.firstChild;c.display.lineSpace.insertBefore(d,c.display.lineSpace.firstChild),e.value=wa.join("\n");var f=document.activeElement;hg(e),setTimeout(function(){c.display.lineSpace.removeChild(d),f.focus()},50)}}var b=this,c=b.cm,d=b.div=a.lineDiv;Ba(d),Mf(d,"paste",function(a){Uf(c,a)||ya(a,c)}),Mf(d,"compositionstart",function(a){var d=a.data;if(b.composing={sel:c.doc.sel,data:d,startData:d},d){var e=c.doc.sel.primary(),f=c.getLine(e.head.line),g=f.indexOf(d,Math.max(0,e.head.ch-d.length));g>-1&&g<=e.head.ch&&(b.composing.sel=Na(qa(e.head.line,g),qa(e.head.line,g+d.length)))}}),Mf(d,"compositionupdate",function(a){b.composing.data=a.data}),Mf(d,"compositionend",function(a){var c=b.composing;c&&(a.data==c.startData||/\u200b/.test(a.data)||(c.data=a.data),setTimeout(function(){c.handled||b.applyComposition(c),b.composing==c&&(b.composing=null)},50))}),Mf(d,"touchstart",function(){b.forceCompositionEnd()}),Mf(d,"input",function(){b.composing||(c.isReadOnly()||!b.pollContent())&&fc(b.cm,function(){lc(c)})}),Mf(d,"copy",e),Mf(d,"cut",e)},prepareSelection:function(){var a=hb(this.cm,!1);return a.focus=this.cm.state.focused,a},showSelection:function(a){a&&this.cm.display.view.length&&(a.focus&&this.showPrimarySelection(),this.showMultipleSelections(a))},showPrimarySelection:function(){var a=window.getSelection(),b=this.cm.doc.sel.primary(),d=Ha(this.cm,a.anchorNode,a.anchorOffset),e=Ha(this.cm,a.focusNode,a.focusOffset);if(!d||d.bad||!e||e.bad||0!=ra(ua(d,e),b.from())||0!=ra(ta(d,e),b.to())){var f=Fa(this.cm,b.from()),g=Fa(this.cm,b.to());if(f||g){var h=this.cm.display.view,i=a.rangeCount&&a.getRangeAt(0);if(f){if(!g){var j=h[h.length-1].measure,k=j.maps?j.maps[j.maps.length-1]:j.map;g={node:k[k.length-1],offset:k[k.length-2]-k[k.length-3]}}}else f={node:h[0].measure.map[2],offset:0};try{var l=vg(f.node,f.offset,g.offset,g.node)}catch(m){}l&&(!c&&this.cm.state.focused?(a.collapse(f.node,f.offset),l.collapsed||a.addRange(l)):(a.removeAllRanges(),a.addRange(l)),i&&null==a.anchorNode?a.addRange(i):c&&this.startGracePeriod()),this.rememberSelection()}}},startGracePeriod:function(){var a=this;clearTimeout(this.gracePeriod),this.gracePeriod=setTimeout(function(){a.gracePeriod=!1,a.selectionChanged()&&a.cm.operation(function(){a.cm.curOp.selectionChanged=!0})},20)},showMultipleSelections:function(a){xg(this.cm.display.cursorDiv,a.cursors),xg(this.cm.display.selectionDiv,a.selection)},rememberSelection:function(){var a=window.getSelection();this.lastAnchorNode=a.anchorNode,this.lastAnchorOffset=a.anchorOffset,this.lastFocusNode=a.focusNode,this.lastFocusOffset=a.focusOffset},selectionInEditor:function(){var a=window.getSelection();if(!a.rangeCount)return!1;var b=a.getRangeAt(0).commonAncestorContainer;return yg(this.div,b)},focus:function(){"nocursor"!=this.cm.options.readOnly&&this.div.focus()},blur:function(){this.div.blur()},getField:function(){return this.div},supportsTouch:function(){return!0},receivedFocus:function(){function b(){a.cm.state.focused&&(a.pollSelection(),a.polling.set(a.cm.options.pollInterval,b))}var a=this;this.selectionInEditor()?this.pollSelection():fc(this.cm,function(){a.cm.curOp.selectionChanged=!0}),this.polling.set(this.cm.options.pollInterval,b)},selectionChanged:function(){var a=window.getSelection();return a.anchorNode!=this.lastAnchorNode||a.anchorOffset!=this.lastAnchorOffset||a.focusNode!=this.lastFocusNode||a.focusOffset!=this.lastFocusOffset},pollSelection:function(){if(!this.composing&&!this.gracePeriod&&this.selectionChanged()){var a=window.getSelection(),b=this.cm;this.rememberSelection();var c=Ha(b,a.anchorNode,a.anchorOffset),d=Ha(b,a.focusNode,a.focusOffset);c&&d&&fc(b,function(){$a(b.doc,Na(c,d),$f),(c.bad||d.bad)&&(b.curOp.selectionChanged=!0)})}},pollContent:function(){var a=this.cm,b=a.display,c=a.doc.sel.primary(),d=c.from(),e=c.to();if(d.lineb.viewTo-1)return!1;var f;if(d.line==b.viewFrom||0==(f=oc(a,d.line)))var g=nf(b.view[0].line),h=b.view[0].node;else var g=nf(b.view[f].line),h=b.view[f-1].node.nextSibling;var i=oc(a,e.line);if(i==b.view.length-1)var j=b.viewTo-1,k=b.lineDiv.lastChild;else var j=nf(b.view[i+1].line)-1,k=b.view[i+1].node.previousSibling;for(var l=a.doc.splitLines(Ja(a,h,k,g,j)),m=kf(a.doc,qa(g,0),qa(j,jf(a.doc,j).text.length));l.length>1&&m.length>1;)if(gg(l)==gg(m))l.pop(),m.pop(),j--;else{if(l[0]!=m[0])break;l.shift(),m.shift(),g++}for(var n=0,o=0,p=l[0],q=m[0],r=Math.min(p.length,q.length);r>n&&p.charCodeAt(n)==q.charCodeAt(n);)++n;for(var s=gg(l),t=gg(m),u=Math.min(s.length-(1==l.length?n:0),t.length-(1==m.length?n:0));u>o&&s.charCodeAt(s.length-o-1)==t.charCodeAt(t.length-o-1);)++o;l[l.length-1]=s.slice(0,s.length-o),l[0]=l[0].slice(n);var v=qa(g,n),w=qa(j,m.length?gg(m).length-o:0);return l.length>1||l[0]||ra(v,w)?(qd(a.doc,l,v,w,"+input"),!0):void 0},ensurePolled:function(){this.forceCompositionEnd()},reset:function(){this.forceCompositionEnd()},forceCompositionEnd:function(){this.composing&&!this.composing.handled&&(this.applyComposition(this.composing),this.composing.handled=!0,this.div.blur(),this.div.focus())},applyComposition:function(a){this.cm.isReadOnly()?gc(this.cm,lc)(this.cm):a.data&&a.data!=a.startData&&gc(this.cm,xa)(this.cm,a.data,0,a.sel)},setUneditable:function(a){a.contentEditable="false"},onKeyPress:function(a){a.preventDefault(),this.cm.isReadOnly()||gc(this.cm,xa)(this.cm,String.fromCharCode(null==a.charCode?a.keyCode:a.charCode),0)},readOnlyChanged:function(a){this.div.contentEditable=String("nocursor"!=a)},onContextMenu:kg,resetPosition:kg,needsContentAttribute:!0},Ea.prototype),x.inputStyles={textarea:Ca,contenteditable:Ea},Ka.prototype={primary:function(){return this.ranges[this.primIndex]},equals:function(a){if(a==this)return!0;if(a.primIndex!=this.primIndex||a.ranges.length!=this.ranges.length)return!1;for(var b=0;b=0&&ra(a,d.to())<=0)return c}return-1}},La.prototype={from:function(){return ua(this.anchor,this.head)},to:function(){return ta(this.anchor,this.head)},empty:function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch}};var Tb,yc,zc,Cb={left:0,right:0,top:0,bottom:0},Wb=null,Xb=0,Fc=0,Mc=0,Nc=null;f?Nc=-.53:c?Nc=15:j?Nc=-.7:l&&(Nc=-1/3);var Oc=function(a){var b=a.wheelDeltaX,c=a.wheelDeltaY;return null==b&&a.detail&&a.axis==a.HORIZONTAL_AXIS&&(b=a.detail),null==c&&a.detail&&a.axis==a.VERTICAL_AXIS?c=a.detail:null==c&&(c=a.wheelDelta),{x:b,y:c}};x.wheelEventPixels=function(a){var b=Oc(a);return b.x*=Nc,b.y*=Nc,b};var Sc=new bg,Wc=null,ed=x.changeEnd=function(a){return a.text?qa(a.from.line+a.text.length-1,gg(a.text).length+(1==a.text.length?a.from.ch:0)):a.to};x.prototype={constructor:x,focus:function(){window.focus(),this.display.input.focus()},setOption:function(a,b){var c=this.options,d=c[a];(c[a]!=b||"mode"==a)&&(c[a]=b,Ed.hasOwnProperty(a)&&gc(this,Ed[a])(this,b,d))},getOption:function(a){return this.options[a]},getDoc:function(){return this.doc},addKeyMap:function(a,b){this.state.keyMaps[b?"push":"unshift"](Ud(a))},removeKeyMap:function(a){for(var b=this.state.keyMaps,c=0;cc&&(yd(this,e.head.line,a,!0),c=e.head.line,d==this.doc.sel.primIndex&&wd(this));else{var f=e.from(),g=e.to(),h=Math.max(c,f.line);c=Math.min(this.lastLine(),g.line-(g.ch?0:1))+1;for(var i=h;c>i;++i)yd(this,i,a);var j=this.doc.sel.ranges;0==f.ch&&b.length==j.length&&j[d].from().ch>0&&Wa(this.doc,d,new La(f,j[d].to()),$f)}}}),getTokenAt:function(a,b){return Le(this,a,b)},getLineTokens:function(a,b){return Le(this,qa(a),b,!0)},getTokenTypeAt:function(a){a=Pa(this.doc,a);var f,b=Oe(this,jf(this.doc,a.line)),c=0,d=(b.length-1)/2,e=a.ch;if(0==e)f=b[2];else for(;;){var g=c+d>>1;if((g?b[2*g-1]:0)>=e)d=g;else{if(!(b[2*g+1]h?f:0==h?null:f.slice(0,h-1)},getModeAt:function(a){var b=this.doc.mode;return b.innerMode?x.innerMode(b,this.getTokenAt(a).state).mode:b},getHelper:function(a,b){return this.getHelpers(a,b)[0]},getHelpers:function(a,b){var c=[];if(!Ld.hasOwnProperty(b))return c;var d=Ld[b],e=this.getModeAt(a);if("string"==typeof e[b])d[e[b]]&&c.push(d[e[b]]);else if(e[b])for(var f=0;fe&&(a=e,c=!0),d=jf(this.doc,a)}else d=a;return Lb(this,d,{top:0,left:0},b||"page").top+(c?this.doc.height-pf(d):0)},defaultTextHeight:function(){return Ub(this.display)},defaultCharWidth:function(){return Vb(this.display)},setGutterMarker:hc(function(a,b,c){return zd(this.doc,a,"gutter",function(a){var d=a.gutterMarkers||(a.gutterMarkers={});return d[b]=c,!c&&rg(d)&&(a.gutterMarkers=null),!0})}),clearGutter:hc(function(a){var b=this,c=b.doc,d=c.first;c.iter(function(c){c.gutterMarkers&&c.gutterMarkers[a]&&(c.gutterMarkers[a]=null,mc(b,d,"gutter"),rg(c.gutterMarkers)&&(c.gutterMarkers=null)),++d})}),lineInfo:function(a){if("number"==typeof a){if(!Ra(this.doc,a))return null;var b=a;if(a=jf(this.doc,a),!a)return null}else{var b=nf(a);if(null==b)return null}return{line:b,handle:a,text:a.text,gutterMarkers:a.gutterMarkers,textClass:a.textClass,bgClass:a.bgClass,wrapClass:a.wrapClass,widgets:a.widgets}},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(a,b,c,d,e){var f=this.display;a=Ob(this,Pa(this.doc,a));var g=a.bottom,h=a.left;if(b.style.position="absolute",b.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(b),f.sizer.appendChild(b),"over"==d)g=a.top;else if("above"==d||"near"==d){var i=Math.max(f.wrapper.clientHeight,this.doc.height),j=Math.max(f.sizer.clientWidth,f.lineSpace.clientWidth);("above"==d||a.bottom+b.offsetHeight>i)&&a.top>b.offsetHeight?g=a.top-b.offsetHeight:a.bottom+b.offsetHeight<=i&&(g=a.bottom),h+b.offsetWidth>j&&(h=j-b.offsetWidth)}b.style.top=g+"px",b.style.left=b.style.right="","right"==e?(h=f.sizer.clientWidth-b.offsetWidth,b.style.right="0px"):("left"==e?h=0:"middle"==e&&(h=(f.sizer.clientWidth-b.offsetWidth)/2),b.style.left=h+"px"),c&&td(this,h,g,h+b.offsetWidth,g+b.offsetHeight)},triggerOnKeyDown:hc(Xc),triggerOnKeyPress:hc($c),triggerOnKeyUp:Zc,execCommand:function(a){return Od.hasOwnProperty(a)?Od[a].call(null,this):void 0},triggerElectric:hc(function(a){za(this,a)}),findPosH:function(a,b,c,d){var e=1;0>b&&(e=-1,b=-b);for(var f=0,g=Pa(this.doc,a);b>f&&(g=Bd(this.doc,g,e,c,d),!g.hitSide);++f);return g},moveH:hc(function(a,b){var c=this;c.extendSelectionsBy(function(d){return c.display.shift||c.doc.extend||d.empty()?Bd(c.doc,d.head,a,b,c.options.rtlMoveVisually):0>a?d.from():d.to()},ag)}),deleteH:hc(function(a,b){var c=this.doc.sel,d=this.doc;c.somethingSelected()?d.replaceSelection("",null,"+delete"):Ad(this,function(c){var e=Bd(d,c.head,a,b,!1);return 0>a?{from:e,to:c.head}:{from:c.head,to:e}})}),findPosV:function(a,b,c,d){var e=1,f=d;0>b&&(e=-1,b=-b);for(var g=0,h=Pa(this.doc,a);b>g;++g){var i=Ob(this,h,"div");if(null==f?f=i.left:i.left=f,h=Cd(this,i,e,c),h.hitSide)break}return h},moveV:hc(function(a,b){var c=this,d=this.doc,e=[],f=!c.display.shift&&!d.extend&&d.sel.somethingSelected();if(d.extendSelectionsBy(function(g){if(f)return 0>a?g.from():g.to();var h=Ob(c,g.head,"div");null!=g.goalColumn&&(h.left=g.goalColumn),e.push(h.left);var i=Cd(c,h,a,b);return"page"==b&&g==d.sel.primary()&&vd(c,null,Nb(c,i,"div").top-h.top),i},ag),e.length)for(var g=0;g0&&h(c.charAt(d-1));)--d;for(;e.5)&&D(this),Qf(this,"refresh",this)}),swapDoc:hc(function(a){var b=this.doc;return b.cm=null,hf(this,a),Ib(this),this.display.input.reset(),this.scrollTo(a.scrollLeft,a.scrollTop),this.curOp.forceScroll=!0,Sf(this,"swapDoc",this,b),b}),getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},Xf(x);var Dd=x.defaults={},Ed=x.optionHandlers={},Gd=x.Init={toString:function(){return"CodeMirror.Init"}};Fd("value","",function(a,b){a.setValue(b)},!0),Fd("mode",null,function(a,b){a.doc.modeOption=b,z(a)},!0),Fd("indentUnit",2,z,!0),Fd("indentWithTabs",!1),Fd("smartIndent",!0),Fd("tabSize",4,function(a){A(a),Ib(a),lc(a)},!0),Fd("lineSeparator",null,function(a,b){if(a.doc.lineSep=b,b){var c=[],d=a.doc.first;a.doc.iter(function(a){for(var e=0;;){var f=a.text.indexOf(b,e);if(-1==f)break;e=f+b.length,c.push(qa(d,f))}d++});for(var e=c.length-1;e>=0;e--)qd(a.doc,b,c[e],qa(c[e].line,c[e].ch+b.length))}}),Fd("specialChars",/[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g,function(a,b,c){a.state.specialChars=new RegExp(b.source+(b.test(" ")?"":"| "),"g"),c!=x.Init&&a.refresh()}),Fd("specialCharPlaceholder",Ue,function(a){a.refresh()},!0),Fd("electricChars",!0),Fd("inputStyle",p?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),Fd("rtlMoveVisually",!r),Fd("wholeLineUpdateBefore",!0),Fd("theme","default",function(a){E(a),F(a)},!0),Fd("keyMap","default",function(a,b,c){var d=Ud(b),e=c!=x.Init&&Ud(c);e&&e.detach&&e.detach(a,d),d.attach&&d.attach(a,e||null)}),Fd("extraKeys",null),Fd("lineWrapping",!1,B,!0),Fd("gutters",[],function(a){K(a.options),F(a)},!0),Fd("fixedGutter",!0,function(a,b){a.display.gutters.style.left=b?V(a.display)+"px":"0",a.refresh()},!0),Fd("coverGutterNextToScrollbar",!1,function(a){P(a)},!0),Fd("scrollbarStyle","native",function(a){O(a),P(a),a.display.scrollbars.setScrollTop(a.doc.scrollTop),a.display.scrollbars.setScrollLeft(a.doc.scrollLeft)},!0),Fd("lineNumbers",!1,function(a){K(a.options),F(a)},!0),Fd("firstLineNumber",1,F,!0),Fd("lineNumberFormatter",function(a){return a},F,!0),Fd("showCursorWhenSelecting",!1,gb,!0),Fd("resetSelectionOnContextMenu",!0),Fd("lineWiseCopyCut",!0),Fd("readOnly",!1,function(a,b){"nocursor"==b?(bd(a),a.display.input.blur(),a.display.disabled=!0):a.display.disabled=!1,a.display.input.readOnlyChanged(b)}),Fd("disableInput",!1,function(a,b){b||a.display.input.reset()},!0),Fd("dragDrop",!0,tc),Fd("allowDropFileTypes",null),Fd("cursorBlinkRate",530),Fd("cursorScrollMargin",0),Fd("cursorHeight",1,gb,!0),Fd("singleCursorHeightPerLine",!0,gb,!0),Fd("workTime",100),Fd("workDelay",100),Fd("flattenSpans",!0,A,!0),Fd("addModeClass",!1,A,!0),Fd("pollInterval",100),Fd("undoDepth",200,function(a,b){a.doc.history.undoDepth=b}),Fd("historyEventDelay",1250),Fd("viewportMargin",10,function(a){a.refresh()},!0),Fd("maxHighlightLength",1e4,A,!0),Fd("moveInputWithCursor",!0,function(a,b){b||a.display.input.resetPosition()}),Fd("tabindex",null,function(a,b){a.display.input.getField().tabIndex=b||""}),Fd("autofocus",null);var Hd=x.modes={},Id=x.mimeModes={};x.defineMode=function(a,b){x.defaults.mode||"null"==a||(x.defaults.mode=a),arguments.length>2&&(b.dependencies=Array.prototype.slice.call(arguments,2)),Hd[a]=b},x.defineMIME=function(a,b){Id[a]=b},x.resolveMode=function(a){if("string"==typeof a&&Id.hasOwnProperty(a))a=Id[a];else if(a&&"string"==typeof a.name&&Id.hasOwnProperty(a.name)){var b=Id[a.name];"string"==typeof b&&(b={name:b}),a=lg(b,a),a.name=b.name}else if("string"==typeof a&&/^[\w\-]+\/[\w\-]+\+xml$/.test(a))return x.resolveMode("application/xml");return"string"==typeof a?{name:a}:a||{name:"null"}},x.getMode=function(a,b){var b=x.resolveMode(b),c=Hd[b.name];if(!c)return x.getMode(a,"text/plain");var d=c(a,b);if(Jd.hasOwnProperty(b.name)){var e=Jd[b.name];for(var f in e)e.hasOwnProperty(f)&&(d.hasOwnProperty(f)&&(d["_"+f]=d[f]),d[f]=e[f])}if(d.name=b.name,b.helperType&&(d.helperType=b.helperType),b.modeProps)for(var f in b.modeProps)d[f]=b.modeProps[f];return d},x.defineMode("null",function(){return{token:function(a){a.skipToEnd()}}}),x.defineMIME("text/plain","null");var Jd=x.modeExtensions={};x.extendMode=function(a,b){var c=Jd.hasOwnProperty(a)?Jd[a]:Jd[a]={};mg(b,c)},x.defineExtension=function(a,b){x.prototype[a]=b},x.defineDocExtension=function(a,b){df.prototype[a]=b},x.defineOption=Fd;var Kd=[];x.defineInitHook=function(a){Kd.push(a)};var Ld=x.helpers={};x.registerHelper=function(a,b,c){Ld.hasOwnProperty(a)||(Ld[a]=x[a]={_global:[]}),Ld[a][b]=c},x.registerGlobalHelper=function(a,b,c,d){x.registerHelper(a,b,d),Ld[a]._global.push({pred:c,val:d})};var Md=x.copyState=function(a,b){if(b===!0)return b;if(a.copyState)return a.copyState(b);var c={};for(var d in b){var e=b[d];e instanceof Array&&(e=e.concat([])),c[d]=e}return c},Nd=x.startState=function(a,b,c){return a.startState?a.startState(b,c):!0};x.innerMode=function(a,b){for(;a.innerMode;){var c=a.innerMode(b);if(!c||c.mode==a)break;b=c.state,a=c.mode}return c||{mode:a,state:b}};var Od=x.commands={selectAll:function(a){a.setSelection(qa(a.firstLine(),0),qa(a.lastLine()),$f)},singleSelection:function(a){a.setSelection(a.getCursor("anchor"),a.getCursor("head"),$f)},killLine:function(a){Ad(a,function(b){if(b.empty()){var c=jf(a.doc,b.head.line).text.length;return b.head.ch==c&&b.head.line0)e=new qa(e.line,e.ch+1),a.replaceRange(f.charAt(e.ch-1)+f.charAt(e.ch-2),qa(e.line,e.ch-2),e,"+transpose");else if(e.line>a.doc.first){var g=jf(a.doc,e.line-1).text;g&&a.replaceRange(f.charAt(0)+a.doc.lineSeparator()+g.charAt(g.length-1),qa(e.line-1,g.length-1),qa(e.line,1),"+transpose")}c.push(new La(e,e))}a.setSelections(c)})},newlineAndIndent:function(a){fc(a,function(){for(var b=a.listSelections().length,c=0;b>c;c++){var d=a.listSelections()[c];a.replaceRange(a.doc.lineSeparator(),d.anchor,d.head,"+input"),a.indentLine(d.from().line+1,null,!0)}wd(a)})},toggleOverwrite:function(a){a.toggleOverwrite()}},Pd=x.keyMap={};Pd.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},Pd.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext", +"Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Pd.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars"},Pd.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Pd["default"]=q?Pd.macDefault:Pd.pcDefault,x.normalizeKeyMap=function(a){var b={};for(var c in a)if(a.hasOwnProperty(c)){var d=a[c];if(/^(name|fallthrough|(de|at)tach)$/.test(c))continue;if("..."==d){delete a[c];continue}for(var e=jg(c.split(" "),Qd),f=0;f=this.string.length},sol:function(){return this.pos==this.lineStart},peek:function(){return this.string.charAt(this.pos)||void 0},next:function(){return this.posb},eatSpace:function(){for(var a=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>a},skipToEnd:function(){this.pos=this.string.length},skipTo:function(a){var b=this.string.indexOf(a,this.pos);return b>-1?(this.pos=b,!0):void 0},backUp:function(a){this.pos-=a},column:function(){return this.lastColumnPos0?null:(f&&b!==!1&&(this.pos+=f[0].length),f)}var d=function(a){return c?a.toLowerCase():a},e=this.string.substr(this.pos,a.length);return d(e)==d(a)?(b!==!1&&(this.pos+=a.length),!0):void 0},current:function(){return this.string.slice(this.start,this.pos)},hideFirstChars:function(a,b){this.lineStart+=a;try{return b()}finally{this.lineStart-=a}}};var Wd=0,Xd=x.TextMarker=function(a,b){this.lines=[],this.type=b,this.doc=a,this.id=++Wd};Xf(Xd),Xd.prototype.clear=function(){if(!this.explicitlyCleared){var a=this.doc.cm,b=a&&!a.curOp;if(b&&Yb(a),Wf(this,"clear")){var c=this.find();c&&Sf(this,"clear",c.from,c.to)}for(var d=null,e=null,f=0;fa.display.maxLineLength&&(a.display.maxLine=i,a.display.maxLineLength=j,a.display.maxLineChanged=!0)}null!=d&&a&&this.collapsed&&lc(a,d,e+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,a&&bb(a.doc)),a&&Sf(a,"markerCleared",a,this),b&&$b(a),this.parent&&this.parent.clear()}},Xd.prototype.find=function(a,b){null==a&&"bookmark"==this.type&&(a=1);for(var c,d,e=0;ec;++c){var e=this.lines[c];this.height-=e.height,He(e),Sf(e,"delete")}this.lines.splice(a,b)},collapse:function(a){a.push.apply(a,this.lines)},insertInner:function(a,b,c){this.height+=c,this.lines=this.lines.slice(0,a).concat(b).concat(this.lines.slice(a));for(var d=0;da;++a)if(c(this.lines[a]))return!0}},bf.prototype={chunkSize:function(){return this.size},removeInner:function(a,b){this.size-=b;for(var c=0;ca){var f=Math.min(b,e-a),g=d.height;if(d.removeInner(a,f),this.height-=g-d.height,e==f&&(this.children.splice(c--,1),d.parent=null),0==(b-=f))break;a=0}else a-=e}if(this.size-b<25&&(this.children.length>1||!(this.children[0]instanceof af))){var h=[];this.collapse(h),this.children=[new af(h)],this.children[0].parent=this}},collapse:function(a){for(var b=0;b=a){if(e.insertInner(a,b,c),e.lines&&e.lines.length>50){for(;e.lines.length>50;){var g=e.lines.splice(e.lines.length-25,25),h=new af(g);e.height-=h.height,this.children.splice(d+1,0,h),h.parent=this}this.maybeSpill()}break}a-=f}},maybeSpill:function(){if(!(this.children.length<=10)){var a=this;do{var b=a.children.splice(a.children.length-5,5),c=new bf(b);if(a.parent){a.size-=c.size,a.height-=c.height;var e=ig(a.parent.children,a);a.parent.children.splice(e+1,0,c)}else{var d=new bf(a.children);d.parent=a,a.children=[d,c],a=d}c.parent=a.parent}while(a.children.length>10);a.parent.maybeSpill()}},iterN:function(a,b,c){for(var d=0;da){var g=Math.min(b,f-a);if(e.iterN(a,g,c))return!0;if(0==(b-=g))break;a=0}else a-=f}}};var cf=0,df=x.Doc=function(a,b,c,d){if(!(this instanceof df))return new df(a,b,c,d);null==c&&(c=0),bf.call(this,[new af([new Fe("",null)])]),this.first=c,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.cleanGeneration=1,this.frontier=c;var e=qa(c,0);this.sel=Na(e),this.history=new rf(null),this.id=++cf,this.modeOption=b,this.lineSep=d,this.extend=!1,"string"==typeof a&&(a=this.splitLines(a)),_e(this,{from:e,to:e,text:a}),$a(this,Na(e),$f)};df.prototype=lg(bf.prototype,{constructor:df,iter:function(a,b,c){c?this.iterN(a-this.first,b-a,c):this.iterN(this.first,this.first+this.size,a)},insert:function(a,b){for(var c=0,d=0;d=0;f--)kd(this,d[f]);h?Za(this,h):this.cm&&wd(this.cm)}),undo:ic(function(){md(this,"undo")}),redo:ic(function(){md(this,"redo")}),undoSelection:ic(function(){md(this,"undo",!0)}),redoSelection:ic(function(){md(this,"redo",!0)}),setExtending:function(a){this.extend=a},getExtending:function(){return this.extend},historySize:function(){for(var a=this.history,b=0,c=0,d=0;d=a.ch)&&b.push(e.marker.parent||e.marker)}return b},findMarks:function(a,b,c){a=Pa(this,a),b=Pa(this,b);var d=[],e=a.line;return this.iter(a.line,b.line+1,function(f){var g=f.markedSpans;if(g)for(var h=0;hi.to||null==i.from&&e!=a.line||e==b.line&&i.from>b.ch||c&&!c(i.marker)||d.push(i.marker.parent||i.marker)}++e}),d},getAllMarks:function(){var a=[];return this.iter(function(b){var c=b.markedSpans;if(c)for(var d=0;da?(b=a,!0):(a-=e,void++c)}),Pa(this,qa(c,b))},indexFromPos:function(a){a=Pa(this,a);var b=a.ch;return a.lineb&&(b=a.from),null!=a.to&&a.toh||h>=b)return g+(b-f);g+=h-f,g+=c-g%c,f=h+1}},dg=x.findColumn=function(a,b,c){for(var d=0,e=0;;){var f=a.indexOf(" ",d);-1==f&&(f=a.length);var g=f-d;if(f==a.length||e+g>=b)return d+Math.min(g,b-e);if(e+=f-d,e+=c-e%c,d=f+1,e>=b)return d}},eg=[""],hg=function(a){a.select()};o?hg=function(a){a.selectionStart=0,a.selectionEnd=a.value.length}:f&&(hg=function(a){try{a.select()}catch(b){}});var vg,og=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/,pg=x.isWordChar=function(a){return/\w/.test(a)||a>"\x80"&&(a.toUpperCase()!=a.toLowerCase()||og.test(a))},sg=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;vg=document.createRange?function(a,b,c,d){var e=document.createRange();return e.setEnd(d||a,c),e.setStart(a,b),e}:function(a,b,c){var d=document.body.createTextRange();try{d.moveToElementText(a.parentNode)}catch(e){return d}return d.collapse(!0),d.moveEnd("character",c),d.moveStart("character",b),d};var yg=x.contains=function(a,b){if(3==b.nodeType&&(b=b.parentNode),a.contains)return a.contains(b);do if(11==b.nodeType&&(b=b.host),b==a)return!0;while(b=b.parentNode)};f&&11>g&&(zg=function(){try{return document.activeElement}catch(a){return document.body}});var Jg,Lg,Bg=x.rmClass=function(a,b){var c=a.className,d=Ag(b).exec(c);if(d){var e=c.slice(d.index+d[0].length);a.className=c.slice(0,d.index)+(e?d[1]+e:"")}},Cg=x.addClass=function(a,b){var c=a.className;Ag(b).test(c)||(a.className+=(c?" ":"")+b)},Fg=!1,Ig=function(){if(f&&9>g)return!1;var a=ug("div");return"draggable"in a||"dragDrop"in a}(),Ng=x.splitLines=3!="\n\nb".split(/\n/).length?function(a){for(var b=0,c=[],d=a.length;d>=b;){var e=a.indexOf("\n",b);-1==e&&(e=a.length);var f=a.slice(b,"\r"==a.charAt(e-1)?e-1:e),g=f.indexOf("\r");-1!=g?(c.push(f.slice(0,g)),b+=g+1):(c.push(f),b=e+1)}return c}:function(a){return a.split(/\r\n?|\n/)},Og=window.getSelection?function(a){try{return a.selectionStart!=a.selectionEnd}catch(b){return!1}}:function(a){try{var b=a.ownerDocument.selection.createRange()}catch(c){}return b&&b.parentElement()==a?0!=b.compareEndPoints("StartToEnd",b):!1},Pg=function(){var a=ug("div");return"oncopy"in a?!0:(a.setAttribute("oncopy","return;"),"function"==typeof a.oncopy)}(),Qg=null,Sg=x.keyNames={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",106:"*",107:"=",109:"-",110:".",111:"/",127:"Delete",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"};!function(){for(var a=0;10>a;a++)Sg[a+48]=Sg[a+96]=String(a);for(var a=65;90>=a;a++)Sg[a]=String.fromCharCode(a);for(var a=1;12>=a;a++)Sg[a+111]=Sg[a+63235]="F"+a}();var ah,fh=function(){function c(c){return 247>=c?a.charAt(c):c>=1424&&1524>=c?"R":c>=1536&&1773>=c?b.charAt(c-1536):c>=1774&&2220>=c?"r":c>=8192&&8203>=c?"w":8204==c?"b":"L"}function j(a,b,c){this.level=a,this.from=b,this.to=c}var a="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",b="rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm",d=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,e=/[stwN]/,f=/[LRr]/,g=/[Lb1n]/,h=/[1n]/,i="L";return function(a){if(!d.test(a))return!1;for(var m,b=a.length,k=[],l=0;b>l;++l)k.push(m=c(a.charCodeAt(l)));for(var l=0,n=i;b>l;++l){var m=k[l];"m"==m?k[l]=n:n=m}for(var l=0,o=i;b>l;++l){var m=k[l];"1"==m&&"r"==o?k[l]="n":f.test(m)&&(o=m,"r"==m&&(k[l]="R"))}for(var l=1,n=k[0];b-1>l;++l){var m=k[l];"+"==m&&"1"==n&&"1"==k[l+1]?k[l]="1":","!=m||n!=k[l+1]||"1"!=n&&"n"!=n||(k[l]=n),n=m}for(var l=0;b>l;++l){var m=k[l];if(","==m)k[l]="N";else if("%"==m){for(var p=l+1;b>p&&"%"==k[p];++p);for(var q=l&&"!"==k[l-1]||b>p&&"1"==k[p]?"1":"N",r=l;p>r;++r)k[r]=q;l=p-1}}for(var l=0,o=i;b>l;++l){var m=k[l];"L"==o&&"1"==m?k[l]="L":f.test(m)&&(o=m)}for(var l=0;b>l;++l)if(e.test(k[l])){for(var p=l+1;b>p&&e.test(k[p]);++p);for(var s="L"==(l?k[l-1]:i),t="L"==(b>p?k[p]:i),q=s||t?"L":"R",r=l;p>r;++r)k[r]=q;l=p-1}for(var v,u=[],l=0;b>l;)if(g.test(k[l])){var w=l;for(++l;b>l&&g.test(k[l]);++l);u.push(new j(0,w,l))}else{var x=l,y=u.length;for(++l;b>l&&"L"!=k[l];++l);for(var r=x;l>r;)if(h.test(k[r])){r>x&&u.splice(y,0,new j(1,x,r));var z=r;for(++r;l>r&&h.test(k[r]);++r);u.splice(y,0,new j(2,z,r)),x=r}else++r;l>x&&u.splice(y,0,new j(1,x,l))}return 1==u[0].level&&(v=a.match(/^\s+/))&&(u[0].from=v[0].length,u.unshift(new j(0,0,v[0].length))),1==gg(u).level&&(v=a.match(/\s+$/))&&(gg(u).to-=v[0].length,u.push(new j(0,b-v[0].length,b))),2==u[0].level&&u.unshift(new j(1,u[0].to,u[0].to)),u[0].level!=gg(u).level&&u.push(new j(u[0].level,b,b)),u}}();return x.version="5.10.0",x}),function(a){"object"==typeof exports&&"object"==typeof module?a(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],a):a(CodeMirror)}(function(a){"use strict";function b(a){for(var b={},c=a.split(" "),d=0;d!?|\/]/;return{startState:function(a){return{tokenize:null,context:new r((a||0)-d,0,"top",!1),indented:0,startOfLine:!0}},token:function(a,b){var c=b.context;if(a.sol()&&(null==c.align&&(c.align=!1),b.indented=a.indentation(),b.startOfLine=!0),a.eatSpace())return null;m=null;var d=(b.tokenize||n)(a,b);if("comment"==d||"meta"==d)return d;if(null==c.align&&(c.align=!0),";"!=m&&":"!=m&&","!=m||"statement"!=c.type)if("{"==m)s(b,a.column(),"}");else if("["==m)s(b,a.column(),"]");else if("("==m)s(b,a.column(),")");else if("}"==m){for(;"statement"==c.type;)c=t(b);for("}"==c.type&&(c=t(b));"statement"==c.type;)c=t(b)}else m==c.type?t(b):(("}"==c.type||"top"==c.type)&&";"!=m||"statement"==c.type&&"newstatement"==m)&&s(b,a.column(),"statement");else t(b);return b.startOfLine=!1,d},indent:function(b,c){if(b.tokenize!=n&&null!=b.tokenize)return a.Pass;var f=b.context,g=c&&c.charAt(0);"statement"==f.type&&"}"==g&&(f=f.prev);var h=g==f.type;return"statement"==f.type?f.indented+("{"==g?0:e):f.align?f.column+(h?0:1):f.indented+(h?0:d)},electricChars:"{}"}});var c="body catch class do else enum for foreach foreach_reverse if in interface mixin out scope struct switch try union unittest version while with";a.defineMIME("text/x-d",{name:"d",keywords:b("abstract alias align asm assert auto break case cast cdouble cent cfloat const continue debug default delegate delete deprecated export extern final finally function goto immutable import inout invariant is lazy macro module new nothrow override package pragma private protected public pure ref return shared short static super synchronized template this throw typedef typeid typeof volatile __FILE__ __LINE__ __gshared __traits __vector __parameters "+c),blockKeywords:b(c),builtin:b("bool byte char creal dchar double float idouble ifloat int ireal long real short ubyte ucent uint ulong ushort wchar wstring void size_t sizediff_t"),atoms:b("exit failure success true false null"),hooks:{"@":function(a,b){return a.eatWhile(/[\w\$_]/),"meta"}}})}); \ No newline at end of file diff --git a/js/ddox.js b/js/ddox.js new file mode 100644 index 0000000000..eb3bf78e2f --- /dev/null +++ b/js/ddox.js @@ -0,0 +1,140 @@ +function setupDdox() +{ + $(".tree-view").children(".package").click(toggleTree); + $(".tree-view.collapsed").children("ul").hide(); + $("#symbolSearch").attr("tabindex", "1000"); + + updateSearchBox(); + $('#sitesearch').change(updateSearchBox); +} + +function updateSearchBox() +{ + var ddox = $('#sitesearch').val() == "dlang.org/library"; + $('#q').toggle(!ddox); + $('#symbolSearch').toggle(ddox); +} + +function toggleTree() +{ + node = $(this).parent(); + node.toggleClass("collapsed"); + if( node.hasClass("collapsed") ){ + node.children("ul").hide(); + } else { + node.children("ul").show(); + } + return false; +} + +var searchCounter = 0; +var lastSearchString = ""; + +function performSymbolSearch(maxlen) +{ + if (maxlen === 'undefined') maxlen = 26; + + var searchstring = $("#symbolSearch").val().toLowerCase(); + + if (searchstring == lastSearchString) return; + lastSearchString = searchstring; + + var scnt = ++searchCounter; + $('#symbolSearchResults').hide(); + $('#symbolSearchResults').empty(); + + var terms = $.trim(searchstring).split(/\s+/); + if (terms.length == 0 || (terms.length == 1 && terms[0].length < 2)) return; + + var results = []; + for (i in symbols) { + var sym = symbols[i]; + var all_match = true; + for (j in terms) + if (sym.name.toLowerCase().indexOf(terms[j]) < 0) { + all_match = false; + break; + } + if (!all_match) continue; + + results.push(sym); + } + + function compare(a, b) { + // prefer non-deprecated matches + var adep = a.attributes.indexOf("deprecated") >= 0; + var bdep = b.attributes.indexOf("deprecated") >= 0; + if (adep != bdep) return adep - bdep; + + // normalize the names + var aname = a.name.toLowerCase(); + var bname = b.name.toLowerCase(); + + var anameparts = aname.split("."); + var bnameparts = bname.split("."); + + var asname = anameparts[anameparts.length-1]; + var bsname = bnameparts[bnameparts.length-1]; + + // prefer exact matches + var aexact = terms.indexOf(asname) >= 0; + var bexact = terms.indexOf(bsname) >= 0; + if (aexact != bexact) return bexact - aexact; + + // prefer elements with less nesting + if (anameparts.length < bnameparts.length) return -1; + if (anameparts.length > bnameparts.length) return 1; + + // prefer matches with a shorter name + if (asname.length < bsname.length) return -1; + if (asname.length > bsname.length) return 1; + + // sort the rest alphabetically + if (aname < bname) return -1; + if (aname > bname) return 1; + return 0; + } + + results.sort(compare); + + for (i = 0; i < results.length && i < 100; i++) { + var sym = results[i]; + + var el = $(document.createElement("li")); + el.addClass(sym.kind); + for (j in sym.attributes) + el.addClass(sym.attributes[j]); + + var name = sym.name; + + // compute a length limited representation of the full name + var nameparts = name.split("."); + var np = nameparts.length-1; + var shortname = "." + nameparts[np]; + while (np > 0 && nameparts[np-1].length + shortname.length <= maxlen) { + np--; + shortname = "." + nameparts[np] + shortname; + } + if (np > 0) shortname = ".." + shortname; + else shortname = shortname.substr(1); + + el.append(''+shortname+''); + $('#symbolSearchResults').append(el); + } + + if (results.length > 100) { + $('#symbolSearchResults').append("
  • …"+(results.length-100)+" additional results
  • "); + } + + $('#symbolSearchResults').show(); +} + +$(function(){ + $("#search-box form").on("submit", function(e) { + var searchResults = $('#symbolSearchResults').children(); + if (searchResults.length > 0) { + window.location = searchResults.first().find("a").attr("href"); + e.preventDefault(); + } + }); +}); diff --git a/js/dlang.js b/js/dlang.js new file mode 100644 index 0000000000..2ff4b721d5 --- /dev/null +++ b/js/dlang.js @@ -0,0 +1,78 @@ +(function($) { + $(function() { + if (typeof cssmenu_no_js === 'undefined') { + // add subnav toggle + $('.subnav').addClass('expand-container'); + $('.subnav').prepend( + $('.subnav h2').clone().addClass('expand-toggle') + ); + + // highlight menu entry of the current page + var href = window.location.href.split('#')[0]; + var current; + var res = $('#top a, .subnav a').each(function (_, a) { + if (a.href == href) { + current = a; + return false; + } + }); + current = $(current); + // direct li parent containing the link + current.parent('li').addClass('active'); + // topmost li parent, e.g. 'std' + current.parents('#top .expand-container').addClass('active'); + current.parents('.subnav .expand-container') + .addClass('open'); + + var open_main_item = null; + $('.expand-toggle').click(function(e) { + var container = $(this).parent('.expand-container'); + container.toggleClass('open'); + + /* In the main menu, let only one dropdown be open at a + time. Also close any open main menu dropdown when clicking + elsewhere. */ + if (open_main_item !== container && open_main_item !== null) { + open_main_item.removeClass("open"); + } + var clicking_main_bar = container.parents("#top").length > 0; + var clicking_hamburger = this === $('.hamburger')[0]; + if (clicking_main_bar && !clicking_hamburger) { + open_main_item = container.hasClass('open') + ? container : null; + } + return false; + }); + + $('html').click(function(e) { + var clicking_main_bar = $(e.target).parents("#top").length > 0; + if (clicking_main_bar) return; + if (open_main_item !== null) { + open_main_item.removeClass('open'); + } + open_main_item = null; + }); + } + + $('.search-container .expand-toggle').click(function() { + $('#search-query input').focus(); + }); + + // Insert the show/hide button if the contents section exists + $('.page-contents-header').append('[hide]'); + + // Event to hide or show the "contents" section when the hide button + // is clicked + $(".page-contents-header a").click(function () { + var elem = $('.page-contents > ol'); + + if (elem.is(':visible')) { + $(this).text("[show]"); + elem.hide(); + } else { + $(this).text("[hide]"); + elem.show(); + } + }); + }); +})(jQuery); diff --git a/js/hyphenate.js b/js/hyphenate.js deleted file mode 100644 index 648dc68184..0000000000 --- a/js/hyphenate.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Hyphenator X.Y.Z - client side hyphenation for webbrowsers - * Copyright (C) 2010 Mathias Nater, Zürich (mathias at mnn dot ch) - * Project and Source hosted on http://code.google.com/p/hyphenator/ - * - * This JavaScript code is free software: you can redistribute - * it and/or modify it under the terms of the GNU Lesser - * General Public License (GNU LGPL) as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) - * any later version. The code is distributed WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. - * - * As additional permission under GNU GPL version 3 section 7, you - * may distribute non-source (e.g., minimized or compacted) forms of - * that code without the copy of the GNU GPL normally required by - * section 4, provided you include this license notice and a URL - * through which recipients can access the Corresponding Source. - */ - -var Hyphenator=(function(window){var -supportedLang={'be':'be.js','cs':'cs.js','da':'da.js','bn':'bn.js','de':'de.js','el':'el-monoton.js','el-monoton':'el-monoton.js','el-polyton':'el-polyton.js','en':'en-us.js','en-gb':'en-gb.js','en-us':'en-us.js','es':'es.js','fi':'fi.js','fr':'fr.js','grc':'grc.js','gu':'gu.js','hi':'hi.js','hu':'hu.js','hy':'hy.js','it':'it.js','kn':'kn.js','la':'la.js','lt':'lt.js','lv':'lv.js','ml':'ml.js','no':'no-nb.js','no-nb':'no-nb.js','nl':'nl.js','or':'or.js','pa':'pa.js','pl':'pl.js','pt':'pt.js','ru':'ru.js','sl':'sl.js','sv':'sv.js','ta':'ta.js','te':'te.js','tr':'tr.js','uk':'uk.js'},languageHint=(function(){var k,r='';for(k in supportedLang){if(supportedLang.hasOwnProperty(k)){r+=k+', ';}}r=r.substring(0,r.length-2);return r;}()),prompterStrings={'be':'Мова гэтага сайта не можа быць вызначаны аўтаматычна. Калі ласка пакажыце мову:','cs':'Jazyk této internetové stránky nebyl automaticky rozpoznán. Určete prosím její jazyk:','da':'Denne websides sprog kunne ikke bestemmes. Angiv venligst sprog:','de':'Die Sprache dieser Webseite konnte nicht automatisch bestimmt werden. Bitte Sprache angeben:','en':'The language of this website could not be determined automatically. Please indicate the main language:','es':'El idioma del sitio no pudo determinarse autom%E1ticamente. Por favor, indique el idioma principal:','fi':'Sivun kielt%E4 ei tunnistettu automaattisesti. M%E4%E4rit%E4 sivun p%E4%E4kieli:','fr':'La langue de ce site n%u2019a pas pu %EAtre d%E9termin%E9e automatiquement. Veuillez indiquer une langue, s.v.p.%A0:','hu':'A weboldal nyelvét nem sikerült automatikusan megállapítani. Kérem adja meg a nyelvet:','hy':'Չհաջողվեց հայտնաբերել այս կայքի լեզուն։ Խնդրում ենք նշեք հիմնական լեզուն՝','it':'Lingua del sito sconosciuta. Indicare una lingua, per favore:','kn':'ಜಾಲ ತಾಣದ ಭಾಷೆಯನ್ನು ನಿರ್ಧರಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ. ದಯವಿಟ್ಟು ಮುಖ್ಯ ಭಾಷೆಯನ್ನು ಸೂಚಿಸಿ:','lt':'Nepavyko automatiškai nustatyti šios svetainės kalbos. Prašome įvesti kalbą:','lv':'Šīs lapas valodu nevarēja noteikt automātiski. Lūdzu norādiet pamata valodu:','ml':'ഈ വെ%u0D2C%u0D4D%u200Cസൈറ്റിന്റെ ഭാഷ കണ്ടുപിടിയ്ക്കാ%u0D28%u0D4D%u200D കഴിഞ്ഞില്ല. ഭാഷ ഏതാണെന്നു തിരഞ്ഞെടുക്കുക:','nl':'De taal van deze website kan niet automatisch worden bepaald. Geef de hoofdtaal op:','no':'Nettstedets språk kunne ikke finnes automatisk. Vennligst oppgi språk:','pt':'A língua deste site não pôde ser determinada automaticamente. Por favor indique a língua principal:','ru':'Язык этого сайта не может быть определен автоматически. Пожалуйста укажите язык:','sl':'Jezika te spletne strani ni bilo mogoče samodejno določiti. Prosim navedite jezik:','sv':'Spr%E5ket p%E5 den h%E4r webbplatsen kunde inte avg%F6ras automatiskt. V%E4nligen ange:','tr':'Bu web sitesinin dili otomatik olarak tespit edilememiştir. Lütfen dökümanın dilini seçiniz%A0:','uk':'Мова цього веб-сайту не може бути визначена автоматично. Будь ласка, вкажіть головну мову:'},basePath=(function(){var s=document.getElementsByTagName('script'),i=0,p,src,t;while(!!(t=s[i++])){if(!t.src){continue;}src=t.src;p=src.indexOf('Hyphenator.js');if(p!==-1){return src.substring(0,p);}}return'http://hyphenator.googlecode.com/svn/trunk/';}()),isLocal=(function(){var re=false;if(window.location.href.indexOf(basePath)!==-1){re=true;}return re;}()),documentLoaded=false,documentCount=0,persistentConfig=false,contextWindow=window,doFrames=false,dontHyphenate={'script':true,'code':true,'pre':true,'img':true,'br':true,'samp':true,'kbd':true,'var':true,'abbr':true,'acronym':true,'sub':true,'sup':true,'button':true,'option':true,'label':true,'textarea':true,'input':true},enableCache=true,storageType='local',storage,enableReducedPatternSet=false,enableRemoteLoading=true,displayToggleBox=false,hyphenateClass='hyphenate',dontHyphenateClass='donthyphenate',min=6,orphanControl=1,isBookmarklet=(function(){var loc=null,re=false,jsArray=document.getElementsByTagName('script'),i,l;for(i=0,l=jsArray.length;i0){for(i=0;i0){return;}else{init(window);}};}else if(document.attachEvent){DOMContentLoaded=function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",DOMContentLoaded);if(doFrames&&window.frames.length>0){return;}else{init(window);}}};}if(document.addEventListener){document.addEventListener("DOMContentLoaded",DOMContentLoaded,false);window.addEventListener("load",doOnLoad,false);}else if(document.attachEvent){document.attachEvent("onreadystatechange",DOMContentLoaded);window.attachEvent("onload",doOnLoad);toplevel=false;try{toplevel=window.frameElement===null;}catch(e){}if(document.documentElement.doScroll&&toplevel){doScrollCheck();}}},getLang=function(el,fallback){if(!!el.getAttribute('lang')){return el.getAttribute('lang').toLowerCase();}try{if(!!el.getAttribute('xml:lang')){return el.getAttribute('xml:lang').toLowerCase();}}catch(ex){}if(el.tagName!=='HTML'){return getLang(el.parentNode,true);}if(fallback){return mainLanguage;}return null;},autoSetMainLanguage=function(w){w=w||contextWindow;var el=w.document.getElementsByTagName('html')[0],m=w.document.getElementsByTagName('meta'),i,text,e,ul;mainLanguage=getLang(el,false);if(!mainLanguage){for(i=0;i0){Expando.appendDataForElem(elements[elements.length-1],{isLast:true});}},convertPatterns=function(lang){var plen,anfang,ende,pats,pat,key,tmp={};pats=Hyphenator.languages[lang].patterns;for(plen in pats){if(pats.hasOwnProperty(plen)){plen=parseInt(plen,10);anfang=0;ende=plen;while(!!(pat=pats[plen].substring(anfang,ende))){key=pat.replace(/\d/g,'');tmp[key]=pat;anfang=ende;ende+=plen;}}}Hyphenator.languages[lang].patterns=tmp;Hyphenator.languages[lang].patternsConverted=true;},convertExceptionsToObject=function(exc){var w=exc.split(', '),r={},i,l,key;for(i=0,l=w.length;i0&&ZWNJpos[0]===i){ZWNJpos.shift();s.splice(i+inserted-1,0,String.fromCharCode(8204));inserted++;}if(!!(hypos[i]&1)){s.splice(i+inserted+1,0,hyphen);inserted++;}}hyphenatedword=s.slice(1,-1).join('');if(enableCache){lo.cache[word]=hyphenatedword;}return hyphenatedword;},hyphenateURL=function(url){return url.replace(/([:\/\.\?#&_,;!@]+)/gi,'$&'+urlhyphen);},removeHyphenationFromElement=function(el){var h,i=0,n;switch(hyphen){case'|':h='\\|';break;case'+':h='\\+';break;case'*':h='\\*';break;default:h=hyphen;}while(!!(n=el.childNodes[i++])){if(n.nodeType===3){n.data=n.data.replace(new RegExp(h,'g'),'');n.data=n.data.replace(new RegExp(zeroWidthSpace,'g'),'');}else if(n.nodeType===1){removeHyphenationFromElement(n);}}},registerOnCopy=function(el){var body=el.ownerDocument.getElementsByTagName('body')[0],shadow,selection,range,rangeShadow,restore,oncopyHandler=function(e){e=e||window.event;var target=e.target||e.srcElement,currDoc=target.ownerDocument,body=currDoc.getElementsByTagName('body')[0],targetWindow='defaultView'in currDoc?currDoc.defaultView:currDoc.parentWindow;if(target.tagName&&dontHyphenate[target.tagName.toLowerCase()]){return;}shadow=currDoc.createElement('div');shadow.style.overflow='hidden';shadow.style.position='absolute';shadow.style.top='-5000px';shadow.style.height='1px';body.appendChild(shadow);if(!!window.getSelection){selection=targetWindow.getSelection();range=selection.getRangeAt(0);shadow.appendChild(range.cloneContents());removeHyphenationFromElement(shadow);selection.selectAllChildren(shadow);restore=function(){shadow.parentNode.removeChild(shadow);selection.addRange(range);};}else{selection=targetWindow.document.selection;range=selection.createRange();shadow.innerHTML=range.htmlText;removeHyphenationFromElement(shadow);rangeShadow=body.createTextRange();rangeShadow.moveToElementText(shadow);rangeShadow.select();restore=function(){shadow.parentNode.removeChild(shadow);if(range.text!==""){range.select();}};}window.setTimeout(restore,0);};if(!body){return;}el=el||body;if(window.addEventListener){el.addEventListener("copy",oncopyHandler,false);}else{el.attachEvent("oncopy",oncopyHandler);}},hyphenateElement=function(el){var hyphenatorSettings=Expando.getDataForElem(el),lang=hyphenatorSettings.language,hyphenate,n,i,controlOrphans=function(part){var h,r;switch(hyphen){case'|':h='\\|';break;case'+':h='\\+';break;case'*':h='\\*';break;default:h=hyphen;}if(orphanControl>=2){r=part.split(' ');r[1]=r[1].replace(new RegExp(h,'g'),'');r[1]=r[1].replace(new RegExp(zeroWidthSpace,'g'),'');r=r.join(' ');}if(orphanControl===3){r=r.replace(/[ ]+/g,String.fromCharCode(160));}return r;};if(Hyphenator.languages.hasOwnProperty(lang)){hyphenate=function(word){if(!Hyphenator.doHyphenation){return word;}else if(urlOrMailRE.test(word)){return hyphenateURL(word);}else{return hyphenateWord(lang,word);}};if(safeCopy&&(el.tagName.toLowerCase()!=='body')){registerOnCopy(el);}i=0;while(!!(n=el.childNodes[i++])){if(n.nodeType===3&&n.data.length>=min){n.data=n.data.replace(Hyphenator.languages[lang].genRegExp,hyphenate);if(orphanControl!==1){n.data=n.data.replace(/[\S]+ [\S]+$/,controlOrphans);}}}}if(hyphenatorSettings.isHidden&&intermediateState==='hidden'){el.style.visibility='visible';if(!hyphenatorSettings.hasOwnStyle){el.setAttribute('style','');el.removeAttribute('style');}else{if(el.style.removeProperty){el.style.removeProperty('visibility');}else if(el.style.removeAttribute){el.style.removeAttribute('visibility');}}}if(hyphenatorSettings.isLast){state=3;documentCount--;if(documentCount>(-1000)&&documentCount<=0){documentCount=(-2000);onHyphenationDone();}}},hyphenateDocument=function(){function bind(fun,arg){return function(){return fun(arg);};}var i=0,el;while(!!(el=elements[i++])){if(el.ownerDocument.location.href===contextWindow.location.href){window.setTimeout(bind(hyphenateElement,el),0);}}},removeHyphenationFromDocument=function(){var i=0,el;while(!!(el=elements[i++])){removeHyphenationFromElement(el);}state=4;},createStorage=function(){try{if(storageType!=='none'&&typeof(window.localStorage)!=='undefined'&&typeof(window.sessionStorage)!=='undefined'&&typeof(window.JSON.stringify)!=='undefined'&&typeof(window.JSON.parse)!=='undefined'){switch(storageType){case'session':storage=window.sessionStorage;break;case'local':storage=window.localStorage;break;default:storage=undefined;break;}}}catch(f){}},storeConfiguration=function(){if(!storage){return;}var settings={'STORED':true,'classname':hyphenateClass,'donthyphenateclassname':dontHyphenateClass,'minwordlength':min,'hyphenchar':hyphen,'urlhyphenchar':urlhyphen,'togglebox':toggleBox,'displaytogglebox':displayToggleBox,'remoteloading':enableRemoteLoading,'enablecache':enableCache,'onhyphenationdonecallback':onHyphenationDone,'onerrorhandler':onError,'intermediatestate':intermediateState,'selectorfunction':selectorFunction,'safecopy':safeCopy,'doframes':doFrames,'storagetype':storageType,'orphancontrol':orphanControl,'dohyphenation':Hyphenator.doHyphenation,'persistentconfig':persistentConfig,'defaultlanguage':defaultLanguage};storage.setItem('Hyphenator_config',window.JSON.stringify(settings));},restoreConfiguration=function(){var settings;if(storage.getItem('Hyphenator_config')){settings=window.JSON.parse(storage.getItem('Hyphenator_config'));Hyphenator.config(settings);}};return{version:'X.Y.Z',doHyphenation:true,languages:{},config:function(obj){var assert=function(name,type){if(typeof obj[name]===type){return true;}else{onError(new Error('Config onError: '+name+' must be of type '+type));return false;}},key;if(obj.hasOwnProperty('storagetype')){if(assert('storagetype','string')){storageType=obj.storagetype;}if(!storage){createStorage();}}if(!obj.hasOwnProperty('STORED')&&storage&&obj.hasOwnProperty('persistentconfig')&&obj.persistentconfig===true){restoreConfiguration();}for(key in obj){if(obj.hasOwnProperty(key)){switch(key){case'STORED':break;case'classname':if(assert('classname','string')){hyphenateClass=obj[key];}break;case'donthyphenateclassname':if(assert('donthyphenateclassname','string')){dontHyphenateClass=obj[key];}break;case'minwordlength':if(assert('minwordlength','number')){min=obj[key];}break;case'hyphenchar':if(assert('hyphenchar','string')){if(obj.hyphenchar==='­'){obj.hyphenchar=String.fromCharCode(173);}hyphen=obj[key];}break;case'urlhyphenchar':if(obj.hasOwnProperty('urlhyphenchar')){if(assert('urlhyphenchar','string')){urlhyphen=obj[key];}}break;case'togglebox':if(assert('togglebox','function')){toggleBox=obj[key];}break;case'displaytogglebox':if(assert('displaytogglebox','boolean')){displayToggleBox=obj[key];}break;case'remoteloading':if(assert('remoteloading','boolean')){enableRemoteLoading=obj[key];}break;case'enablecache':if(assert('enablecache','boolean')){enableCache=obj[key];}break;case'enablereducedpatternset':if(assert('enablereducedpatternset','boolean')){enableReducedPatternSet=obj[key];}break;case'onhyphenationdonecallback':if(assert('onhyphenationdonecallback','function')){onHyphenationDone=obj[key];}break;case'onerrorhandler':if(assert('onerrorhandler','function')){onError=obj[key];}break;case'intermediatestate':if(assert('intermediatestate','string')){intermediateState=obj[key];}break;case'selectorfunction':if(assert('selectorfunction','function')){selectorFunction=obj[key];}break;case'safecopy':if(assert('safecopy','boolean')){safeCopy=obj[key];}break;case'doframes':if(assert('doframes','boolean')){doFrames=obj[key];}break;case'storagetype':if(assert('storagetype','string')){storageType=obj[key];}break;case'orphancontrol':if(assert('orphancontrol','number')){orphanControl=obj[key];}break;case'dohyphenation':if(assert('dohyphenation','boolean')){Hyphenator.doHyphenation=obj[key];}break;case'persistentconfig':if(assert('persistentconfig','boolean')){persistentConfig=obj[key];}break;case'defaultlanguage':if(assert('defaultlanguage','string')){defaultLanguage=obj[key];}break;default:onError(new Error('Hyphenator.config: property '+key+' not known.'));}}}if(storage&&persistentConfig){storeConfiguration();}},run:function(){documentCount=0;var process=function(){try{if(contextWindow.document.getElementsByTagName('frameset').length>0){return;}documentCount++;autoSetMainLanguage(undefined);gatherDocumentInfos();prepare(hyphenateDocument);if(displayToggleBox){toggleBox();}}catch(e){onError(e);}},i,haveAccess,fl=window.frames.length;if(!storage){createStorage();}if(!documentLoaded&&!isBookmarklet){runOnContentLoaded(window,process);}if(isBookmarklet||documentLoaded){if(doFrames&&fl>0){for(i=0;i=min){n.data=n.data.replace(Hyphenator.languages[lang].genRegExp,hyphenate);}else if(n.nodeType===1){if(n.lang!==''){Hyphenator.hyphenate(n,n.lang);}else{Hyphenator.hyphenate(n,lang);}}}}}else{onError(new Error('Language "'+lang+'" is not loaded.'));}},getRedPatternSet:function(lang){return Hyphenator.languages[lang].redPatSet;},isBookmarklet:function(){return isBookmarklet;},getConfigFromURI:function(){var loc=null,re={},jsArray=document.getElementsByTagName('script'),i,j,l,s,gp,option;for(i=0,l=jsArray.length;i'); -} diff --git a/js/jquery-1.7.2.min.js b/js/jquery-1.7.2.min.js new file mode 100644 index 0000000000..16ad06c5ac --- /dev/null +++ b/js/jquery-1.7.2.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.7.2 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"":"")+""),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;e=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
    a",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="
    "+""+"
    ",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="
    t
    ",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="
    ",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function( +a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&j.push({elem:this,matches:d.slice(e)});for(k=0;k0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

    ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
    ";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*",""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
    ","
    "]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f +.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(;d1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]===""&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
    ").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/js/listanchors.js b/js/listanchors.js new file mode 100644 index 0000000000..a5d381f899 --- /dev/null +++ b/js/listanchors.js @@ -0,0 +1,183 @@ +/** +Generates 'Jump to' links. + +Copyright: 1999-2016 by Digital Mars + +License: http://boost.org/LICENSE_1_0.txt, Boost License 1.0 + +Authors: Andrei Alexandrescu, Nick Treleaven +*/ + +function lastName(a) { + var pos = a.lastIndexOf('.'); + return a.slice(pos + 1); +} + +// adds a anchor link to every documented declaration +function addAnchors() +{ + var items = document.getElementsByClassName('d_decl'); + if(!items) return; + for (var i = 0; i < items.length; i++) + { + // we link to the first children + var da = items[i].querySelector('span.def-anchor'); + if(!da) continue; + var permLink = document.createElement("a"); + permLink.setAttribute('href', '#' + da.id); + permLink.className = "fa fa-anchor decl_anchor"; + items[i].insertBefore(permLink, items[i].firstChild); + } +} + +// Add a version selector button +function addVersionSelector() { + // Latest version offered by the archive builds + // This needs to be manually updated after new versions have been archived + var currentArchivedVersion = 110; + // build URLs for dlang.org: DDoc + Dox + var ddocModuleURL = document.body.id.replace(/[.]/g, "_") + ".html"; + var ddoxModuleURL = document.body.id.replace(/[.]/g, "/") + ".html"; + var root = "phobos/"; + + var isSpec = window.location.pathname.indexOf("/spec/") >= 0; + if (isSpec) { + root = "spec/"; + var uriParts = window.location.pathname.split("/"); + ddocModuleURL = uriParts[uriParts.length - 1]; + // these versions use a different layout + var plainSpecVersions = ["2.066", "2.067", "2.068", "2.069"]; + } + + // build list of versions available in the docarchives + var archivedVersions = []; + while (currentArchivedVersion >= 66) { + if (currentArchivedVersion < 100) { + archivedVersions.push("2.0" + currentArchivedVersion--); + } else { + archivedVersions.push("2." + currentArchivedVersion--); + } + } + archivedVersions = archivedVersions.map(function(e) { + var currentRoot = root; + if (isSpec && plainSpecVersions.indexOf(e) >= 0) { + currentRoot = ""; + } + return { + name: e, + url: "https://docarchives.dlang.io/v" + e + ".0/" + currentRoot + ddocModuleURL, + }; + }); + + var onlineVersions; + if (isSpec) { + onlineVersions = [{ + name: "master", + url: "https://dlang.org/spec/" + ddocModuleURL, + }]; + } else { + onlineVersions = [{ + name: "master", + url: "https://dlang.org/phobos-prerelease/" + ddocModuleURL, + },{ + name: "master (ddox)", + url: "https://dlang.org/library-prerelease/" + ddoxModuleURL, + },{ + name: "stable", + url: "https://dlang.org/phobos/" + ddocModuleURL, + },{ + name: "stable (ddox)", + url: "https://dlang.org/library/" + ddoxModuleURL, + }]; + } + + // set the current URL as selected + var currentURL = location.href.split(/[#?]/)[0]; + var versions = onlineVersions.concat(archivedVersions); + versions.forEach(function(v, i) { + versions[i].selected = v.url === currentURL; + }); + // Don't show the option chooser if the page hasn't been recognized + // For example, Ddox symbol pages are currently not supported + if (versions.filter(function(v){return v.selected}).length === 0) + return; + + // build select box of all versions and append to current DOM + var options = versions.map(function(e, i){ + return ""; + }); + $("h1").after("
    "); + // attach event listener to select box -> change URL + $("#version-changer").change(function(){ + var selected = parseInt($(this).find("option:selected").val()); + var option = versions[selected]; + if (!option.selected) { + window.location.href = option.url; + } + }); +} + +function listanchors() +{ + var hideTop = (typeof inhibitQuickIndex !== 'undefined'); + var a = document.getElementById("quickindex"); + if (!a) return; + + // build hash of parent anchor names -> array of child anchor names + var parentNames = []; + var lastAnchor = ''; + var items = document.getElementsByClassName('quickindex'); + for (var i = 0; i < items.length; i++) + { + var text = items[i].id; + // ignore top-level quickindex + var pos = text.indexOf('.'); + if (pos < 0) continue; + // skip 'quickindex' + text = text.slice(pos); + // ignore any ditto overloads (which have the same anchor name) + if (text == lastAnchor) continue; + lastAnchor = text; + + var pos = text.lastIndexOf('.'); + if (hideTop && pos == 0) continue; + var parent = (pos == 0) ? '' : text.slice(0, pos); + + if (!parentNames[parent]) + parentNames[parent] = [text]; + else + parentNames[parent].push(text); + } + // populate quickindex elements + for (var key in parentNames) + { + var arr = parentNames[key]; + // we won't display the qualifying names to save space, so sort by last name + arr.sort(function(a,b){ + var aa = lastName(a).toLowerCase(); + var bb = lastName(b).toLowerCase(); + return aa == bb ? 0 : (aa < bb ? -1 : 1); + }); + var newText = ""; + for (var i = 0; i < arr.length; i++) { + var a = arr[i]; + var text = lastName(a); + if (i != 0) newText += " ·"; + newText += ' ' + text + ''; + } + if (newText != "") + { + newText = '

    Jump to:' + + newText + '

    '; + } + var id = 'quickindex'; + id += key; + var e = document.getElementById(id); + e.innerHTML = newText; + + } + + addAnchors(); + addVersionSelector(); +} diff --git a/js/platform-downloads.js b/js/platform-downloads.js new file mode 100644 index 0000000000..48872e1719 --- /dev/null +++ b/js/platform-downloads.js @@ -0,0 +1,43 @@ +(function() { + var script = document.currentScript; + if (!script) { // polyfill for IE + var scripts = document.getElementsByTag('script'); + script = scripts[scripts.length - 1]; // depends on synchronous load + } + var latest = script.dataset.latest, + platform = navigator.platform.toLowerCase(); + + var model = 64; + if (platform.match('i.86')) + model = 32; + + var files; + if (platform.indexOf('win') != -1) + files = [{name: 'dmd-' + latest, suffix: '.exe', text: 'Windows Installer'}]; + else if (platform.indexOf('mac') != -1) + files = [{name: 'dmd.' + latest, suffix: '.dmg', text: 'DMG File'}]; + else if (model == null) // platforms with multiple archs follow + return; + else if (platform.indexOf('linux') != -1) + files = [{name: 'dmd_' + latest + '-0_' + (model == 64 ? 'amd64' : 'i386'), suffix: '.deb', text: 'DEB File'}, + {name: 'dmd-' + latest + '-0.fedora.' + (model == 64 ? 'x86_64' : 'i386'), suffix: '.rpm', text: 'RPM File'} + ]; + else if (platform.indexOf('freebsd') != -1) + files = [{name: 'dmd.' + latest + '.freebsd-' + model.toString(), suffix: '.tar.xz', text: 'Compressed Archive'}]; + else + return; + + var html = ''; + for (var i = 0; i < files.length; ++i) { + var f = files[i]; + var url = 'https://downloads.dlang.org/releases/2.x/' + latest + '/' + f.name + f.suffix; + html += 'Download ' + f.text + ''; + } + if (files.length > 1) { + html = '
    ' + html + '
    '; + } + + var btn = $('.download a.btn'); + btn.before(html); + btn.text('Other Downloads'); +})(); diff --git a/js/run.js b/js/run.js new file mode 100644 index 0000000000..48c85f26d8 --- /dev/null +++ b/js/run.js @@ -0,0 +1,503 @@ +/** +Runnable examples functionality + +Copyright: 2012 by Digital Mars + +License: http://boost.org/LICENSE_1_0.txt, Boost License 1.0 + +Authors: Andrei Alexandrescu, Damian Ziemba +*/ + +/** +Script workflow: + +1. Scan current document DOM tree for
     elements with class=d_code.
    +    
    ...
    blocks are generated by DDOC example sections. +2. Iterate each pre element and apply our custom form, replacing default
     block
    +3. Get text from original 
     block, strip any spaces and newlines from it and compute md5sum
    +4. Look up mainPage map with md5sum as a key and see if there are any elements associated with this key
    +5. If yes: Add to our custom form default Standard input and/or Standard Arguments, stdin being 0 key, stdout 1 key.
    +6. If no: Just skip to point 7
    +7. Continue to next 
     element and repeat begging from point 2 if there are still nodes left
    +
    +How to add new example or update existing:
    +
    +If example doesn't require any standard input neither standard argugments by default you are done.
    +Otherwise, copy example text without example separator ie:
    +
    +------
    +[start here]
    +import std.stdio;
    +
    +void main(string[] args) {
    +    writeln("Hello world. ", args);
    +    writeln("What's your name?");
    +    writeln("Hello ", readln());
    +}
    +[end here]
    +------
    +
    +TL;DR
    +All examples are replaced with custom form by default. You need to do additional work only if you want
    +your example to have default standard input or default standard arguments.
    +*/
    +
    +var nl2br = function()
    +{
    +    return this.replace(/\n/g, "
    "); +} + +function safeVar(data, path) +{ + var p = path.split("."); + var res = null; + + try + { + res = data[p[0]][p[1]]; + if (typeof res == "object") + res = ""; + } + catch (e) + { + return ""; + } + + return res; +} + +// compile the examples on the prerelease pages with dmd-nightly +var dmdCompilerBranch = location.href.indexOf("-prerelease/") >= 0 ? "dmd-nightly" : "dmd"; + +var backends = { + dpaste: { + url: "https://dpaste.dzfl.pl/request/", + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + requestTransform: function(data) { + return data; + }, + parseOutput: function(data, opts) { + var r = {}; + if (data.compilation === "undefined") + return null; + r.cout = safeVar(data, "compilation.stdout"); + r.stdout = safeVar(data, "runtime.stdout"); + r.stderr = safeVar(data, "runtime.stderr"); + r.ctime = parseInt(safeVar(data, "compilation.time")); + r.rtime = parseInt(safeVar(data, "runtime.time")); + r.cstatus = parseInt(safeVar(data, "compilation.status")); + r.rstatus = parseInt(safeVar(data, "runtime.status")); + r.cerr = safeVar(data, "compilation.err"); + r.rerr = safeVar(data, "runtime.err"); + r.defaultOutput = data.output || opts.defaultOutput; + return r; + } + }, + tour: { + url: "https://tour.dlang.org/api/v1/run", + // send json as text/plain to avoid an additional preflight OPTIONS request + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests + contentType: "text/plain; charset=UTF-8", + requestTransform: function(data) { + var req = { + source: data.code, + // always execute unittests and main for backwards compatibility with examples + args: "-unittest -main", + runtimeArgs: "--DRT-testmode=run-main", + compiler: dmdCompilerBranch + } + // only send set attributes + if (data.stdin) { + req.stdin = data.stdin; + } + if (data.args) { + req.args = data.args; + } + return JSON.stringify(req); + }, + parseOutput: function(data, opts) { + var r = {}; + if (data.success === "undefined") { + return null; + } + var success = !(data.errors && data.errors.length > 0); + r.cout = !success ? data.output : ""; + r.stdout = success ? data.output : ""; + r.stderr = !success ? data.output : ""; + r.ctime = ""; + r.rtime = ""; + r.cstatus = success ? 0 : 1; + r.rstatus = 0; // not supported + r.cerr = ""; + r.rerr = ""; + r.defaultOutput = data.output || opts.defaultOutput; + return r; + } + } +}; + +function parseOutput(res, o, oTitle) +{ + if (!res) + { + o.text("Temporarily unavailable"); + return; + } + + var output = ""; + var defaultOutput = res.defaultOutput || '-- No output --'; + + if (res.cstatus != 0) + { + oTitle.text("Compilation output ("+res.cstatus+": "+res.cerr+")"); + if ($.browser.msie) + o.html(nl2br(res.cout)); + else + o.text(res.cout); + + return; + } + else + { + oTitle.text("Application output");// (compile "+ctime+"ms, run "+rtime+"ms)"); + if ( res.cout != "") + output = 'Compilation output: \n' + res.cout + "\n"; + + output += (res.stdout == "" && res.stderr == "" ? res.defaultOutput : res.stdout); + + if (res.stderr != "") + output += res.stderr; + + if (res.rstatus != 0) + oTitle.text("Application output ("+res.rstatus+": "+res.rerr+")"); + } + + if ($.browser.msie) + o.html(nl2br(res.cout)); + else + o.text(output); +} + +// wraps a unittest into a runnable script +function wrapIntoMain(code, compile) { + var currentPackage = $('body')[0].id; + + // dynamically wrap into main if needed + if (compile || code.indexOf("void main") >= 0 || code.indexOf("int main") >= 0) { + return code; + } + else { + var codeOut = "void main()\n{\n"; + // writing to the stdout is probably often used + codeOut += " import std.stdio: write, writeln, writef, writefln;\n "; + codeOut += "#line 1\n"; + codeOut += code.split("\n").join("\n "); + codeOut += "\n}"; + return codeOut; + } +} + +$(document).ready(function() +{ + setUpExamples(); + + var currentPage = $(location).attr('pathname'); + + $('.runnable-examples').each(function(index) + { + var root = $(this); + var el = root.children("pre"); + + var stdin = root.children(".runnable-examples-stdin").text(); + var args = root.children(".runnable-examples-args").text(); + + // only show stdin or args if they are set + if (stdin.length > 0) + { + stdin = '
    Standard input
    ' + + '
    '; + } + if (args.length > 0) + { + args = '
    Command line arguments
    ' + + '
    '; + } + + var compile = el.parent()[0].hasAttribute('data-compile'); + var runAttrs = `value="${compile ? 'Compile' : 'Run'}"`; + if (!compile) + runAttrs += ' title="Note: Wraps code in `main` automatically if `main` is missing' + + ' & imports std.stdio.write[f][ln]"'; + var currentExample = el; + var orig = currentExample.html(); + + currentExample.replaceWith( + '
    '+orig+'
    ' + + '
    ' + + '' + + stdin + args + + '
    Application output
    Running...
    ' + + '' + + (args.length > 0 ? '' : '') + + (stdin.length > 0 ? '' : '') + + `` + + '' + + '
    ' + ); + }); + + $('textarea[class=d_code]').each(function(index) { + var parent = $(this).parent(); + var outputDiv = parent.children("div.d_code_output"); + var hasStdin = parent.children(".inputButton").length > 0; + var hasArgs = parent.children(".argsButton").length > 0; + var compile = parent.parent()[0].hasAttribute('data-compile'); + setupTextarea(this, { + parent: parent, + outputDiv: outputDiv, + stdin: hasStdin, + args: hasArgs, + compile: compile, + defaultOutput: "Succeed without output.", + transformOutput: wrapIntoMain, + }); + }); +}); + +function setupTextarea(el, opts) +{ + opts = opts || {}; + // set default opts + opts = jQuery.extend({}, { + stdin: false, + args: false, + transformOutput: function(out) { return out } + }, opts); + + var backend = backends[opts.backend || "tour"]; + + if (!!opts.parent) + var parent = opts.parent; + else + console.error("parent node node not found"); + + if (!!opts.outputDiv) + var outputDiv = opts.outputDiv; + else + console.error("outputDiv node not found"); + + var thisObj = $(el); + parent.css("display", "block"); + var orgSrc = parent.parent().children("div.d_code").children("pre.d_code"); + + var prepareForMain = function() + { + var src = orgSrc.text(); + var arr = src.split("\n"); + var str = ""; + for (var i = 0; i < arr.length; i++) + { + str += arr[i]+"\n"; + } + return str; + }; + + var editor; + var code; + function initializeEditor(){ + if (typeof editor !== "undefined") + return; + editor = CodeMirror.fromTextArea(thisObj[0], { + lineNumbers: true, + tabSize: 4, + indentUnit: 4, + indentWithTabs: true, + mode: "text/x-d", + lineWrapping: true, + theme: "eclipse", + readOnly: false, + matchBrackets: true + }); + editor.setValue(prepareForMain()); + code = $(editor.getWrapperElement()); + code.css('display', 'none'); + + } + + var height = function(diff) { + var par = code != null ? code : parent.parent().children("div.d_code"); + return (parseInt(par.css('height')) - diff) + 'px'; + }; + + var runBtn = parent.children(".runButton"); + var editBtn = parent.children(".editButton"); + var resetBtn = parent.children(".resetButton"); + var openInEditorBtn = parent.children(".openInEditorButton"); + + var plainSourceCode = parent.parent().children("div.d_code"); + + var output = outputDiv.children("pre.d_code_output"); + var outputTitle = outputDiv.children("span.d_code_title"); + if (opts.args) { + var argsBtn = parent.children("input.argsButton"); + var argsDiv = parent.children("div.d_code_args"); + var args = argsDiv.children("textarea.d_code_args"); + var orgArgs = args.val(); + } + if (opts.stdin) { + var inputBtn = parent.children("input.inputButton"); + var stdinDiv = parent.children("div.d_code_stdin"); + var stdin = stdinDiv.children("textarea.d_code_stdin"); + var orgStdin = stdin.val(); + } + + var hideAllWindows = function(optArguments) + { + optArguments = optArguments || {}; + if (opts.stdin) { + stdinDiv.css('display', 'none'); + } + if (opts.args) { + argsDiv.css('display', 'none'); + } + outputDiv.css('display', 'none'); + if (!optArguments.keepPlainSourceCode) { + plainSourceCode.css('display', 'none'); + } + if (!optArguments.keepCode) { + code.css('display', 'none'); + } + }; + + if (opts.args) { + argsBtn.click(function(){ + resetBtn.css('display', 'inline-block'); + args.css('height', height(31)); + hideAllWindows(); + argsDiv.css('display', 'block'); + args.focus(); + }); + } + + if (opts.stdin) { + inputBtn.click(function(){ + resetBtn.css('display', 'inline-block'); + stdin.css('height', height(31)); + hideAllWindows(); + stdinDiv.css('display', 'block'); + stdin.focus(); + }); + } + + editBtn.click(function(){ + initializeEditor(); + resetBtn.css('display', 'inline-block'); + hideAllWindows(); + code.css('display', 'block'); + editor.refresh(); + editor.focus(); + }); + resetBtn.click(function(){ + resetBtn.css('display', 'none'); + editor.setValue(prepareForMain()); + if (opts.args) { + args.val(orgArgs); + } + if (opts.stdin) { + stdin.val(orgStdin); + } + hideAllWindows(); + plainSourceCode.css('display', 'block'); + }); + runBtn.click(function(){ + initializeEditor(); + resetBtn.css('display', 'inline-block'); + $(this).attr("disabled", true); + var optArguments = {}; + // check what boxes are currently open + if (opts.keepCode) { + optArguments.keepCode = code.is(":visible"); + optArguments.keepPlainSourceCode = plainSourceCode.is(":visible"); + } + hideAllWindows(optArguments); + output.css('height', opts.outputHeight || height(31)); + outputDiv.css('display', 'block'); + outputTitle.text("Application output"); + output.html("Running..."); + output.focus(); + + var data = { + code: opts.transformOutput(editor.getValue(), opts.compile) + }; + if (opts.stdin) { + data.stdin = stdin.val(); + } + if (opts.args) { + data.args = args.val(); + } + $.ajax({ + type: 'POST', + url: backend.url, + contentType: backend.contentType, + dataType: "json", + data: backend.requestTransform(data), + success: function(data) + { + parseOutput(backend.parseOutput(data, opts), output, outputTitle); + runBtn.attr("disabled", false); + }, + error: function(jqXHR, textStatus, errorThrown ) + { + output.html("Temporarily unavailable"); + if (typeof console != "undefined") + { + console.log(textStatus + ": " + errorThrown); + } + + runBtn.attr("disabled", false); + } + }); + }); + openInEditorBtn.click(function(){ + var text = (editor && editor.getValue()) || prepareForMain(); + var url = "https://run.dlang.io/?compiler=" + dmdCompilerBranch + "&args=-unittest&source=" + encodeURIComponent(opts.transformOutput(text)); + window.open(url, "_blank"); + }); + return editor; +}; + + +function setUpExamples() +{ + /* Sets up expandable example boxes. + * max-height and CSS transitions are used to animate the closing and opening for smooth animations even on less powerful devices + */ + $('.example-box').each(function() { + var $box = $(this); + var boxId = $box.attr('id'); + // A little juggling here because the content needs to be a block element and the control needs to be an inline + // element in the previous paragraph. + var $control = $('#' + boxId + '-control'); + $control.attr('aria-controls', boxId); + var $showLabel = $('Show example '); + var $hideLabel = $('Hide example '); + function toggle() { + if ($box.attr('aria-hidden') === 'true') { + $box.attr('aria-hidden', false); + $control.attr('aria-expanded', true); + $control.empty().append($hideLabel); + $box.css('max-height', $box[0].scrollHeight); + } else { + $box.attr('aria-hidden', true); + $control.attr('aria-expanded', false); + $control.empty().append($showLabel); + $box.css('max-height', 0); + } + return false; + } + $control.on('click', toggle); + toggle(); + }); + // NB: href needed for browsers to include the controls in the (keyboard) tab order + $('.example-control').attr('href', '#'); +} diff --git a/js/run_examples.js b/js/run_examples.js new file mode 100644 index 0000000000..063fea193a --- /dev/null +++ b/js/run_examples.js @@ -0,0 +1,101 @@ +/** + * Run all unittest examples + * + * Copyright 2016 by D Language Foundation + * + * License: http://boost.org/LICENSE_1_0.txt, Boost License 1.0 + */ + +// turns asserts into writeln +function reformatExample(code) { + return code.replace(/(assert<\/span>(?:)?\((.*)==(.*)\);)+/g, function(match, text, left, right) { + return "writeln(" + left.trim() + "); " + + "// " + right.trim() + ""; + }); +} + +// wraps a unittest into a runnable script +function wrapIntoMain(code) { + var currentPackage = $('body')[0].id; + var codeOut = ""; + + // dynamically wrap into main if needed + if (code.indexOf("void main") >= 0) { + codeOut = "import " + currentPackage + "; "; + codeOut += "#line 1\n"; + codeOut += code; + } + else { + var codeOut = "void main()\n{\n"; + codeOut += " import " + currentPackage + ";\n"; + // writing to the stdout is probably often used + codeOut += (currentPackage == "std.file") ? " import std.stdio: writeln, writef, writefln;\n " : " import std.stdio: write, writeln, writef, writefln;\n "; + codeOut += "#line 1\n"; + codeOut += code.split("\n").join("\n "); + codeOut += "\n}"; + } + return codeOut; +} + +$(document).ready(function() +{ + if ($('body')[0].id == "Home") + return; + + // only for std at the moment + if (!$('body').hasClass("std")) + return; + + // first selector is for ddoc - second for ddox + var codeBlocks = $('pre[class~=d_code]').add('pre[class~=code]'); + codeBlocks.each(function(index) + { + var currentExample = $(this); + var orig = currentExample.html(); + + // disable regex assert -> writeln rewrite logic (for now) + //orig = reformatExample(orig); + + // check whether it is from a ddoced unittest + // 1) check is for ddoc, 2) for ddox + // manual created tests most likely can't be run without modifications + if (!($(this).parent().parent().prev().hasClass("dlang_runnable") || + $(this).prev().children(":last").hasClass("dlang_runnable"))) + return; + + currentExample.replaceWith( + '
    ' + + '
    ' + + '
    '+orig+'
    ' + + '
    ' + + '
    ' + + '' + + '
    ' + + '
    ' + + '
    Edit
    ' + + '
    Run
    ' + + '' + + '
    Open in IDE
    ' + + '
    ' + + '
    Application output
    Running...
    ' + + '
    ' + ); + }); + + $('textarea[class=d_code]').each(function(index) { + var parent = $(this).parent(); + var btnParent = parent.parent().children(".d_example_buttons"); + var outputDiv = parent.parent().children(".d_code_output"); + var editor = setupTextarea(this, { + parent: btnParent, + outputDiv: outputDiv, + stdin: false, + args: false, + transformOutput: wrapIntoMain, + defaultOutput: "All tests passed", + keepCode: true, + outputHeight: "auto", + backend: "tour" + }); + }); +}); diff --git a/js/show_contributors.js b/js/show_contributors.js new file mode 100644 index 0000000000..a049189503 --- /dev/null +++ b/js/show_contributors.js @@ -0,0 +1,67 @@ +/** +Shows a list of the contributors to a Phobos module +It queries the backend contribs.dlang.io +Backend source: https://github.com/wilzbach/phobos-contribs + +License: http://boost.org/LICENSE_1_0.txt, Boost License 1.0 + +Authors: Sebastian Wilzbach +*/ + +// find out whether the current page is a module or package +function isPackage() +{ + return $('.tip.smallprint a[href*="package.d"]').length > 0; +} + +$(document).ready(function() +{ + // only for library documentation + if (!$('body').hasClass("std")) + return; + + // for index modules (package.d), we want to display all contributors of the package + var modulePath = document.body.id.replace(/[.]/g, '/'); + if (!isPackage()) + modulePath += '.d'; + + // enable only for std, etc and core + var repo; + if (modulePath.indexOf("core") == 0 || modulePath.indexOf("object") == 0) + { + repo = "dmd"; + modulePath = "druntime/src/" + modulePath; + } + else if (modulePath.indexOf("std") == 0 || modulePath.indexOf("etc") == 0) + { + repo = "phobos"; + } + else + { + return; + } + + $.getJSON( "https://contribs.dlang.io/contributors/file/dlang/" + repo + "?file=" + modulePath, function(contributors) + { + + var posToInsert = $('#copyright'); + var contentNode = $("
    "); + + var totalContributors = contributors.length; + // ignore invalid files + if (totalContributors == 0) + return; + + contentNode.append("

    " + totalContributors + " Contributors

    "); + + // list contributors with github avatar + $.each(contributors, function(i, contributor) + { + var contributorDiv = ''; + contributorDiv += '' + contributor.login + ''; + contributorDiv += ""; + contentNode.append(contributorDiv); + }); + contentNode.insertBefore(posToInsert); + }); +}); diff --git a/keywords.ddoc b/keywords.ddoc new file mode 100644 index 0000000000..aeb861654f --- /dev/null +++ b/keywords.ddoc @@ -0,0 +1,163 @@ +_= These are to make it easier to have keywords highlighted as keywords inside +a ddoc comment, whereas by default, they only get highlighted in code examples. + +K_ABSTRACT=$(D_KEYWORD abstract) +K_ALIAS=$(D_KEYWORD alias) +K_ALIGN=$(D_KEYWORD align) +K_ASM=$(D_KEYWORD asm) +K_ASSERT=$(D_KEYWORD assert) +K_AUTO=$(D_KEYWORD auto) +_= + +K_BOOL=$(D_KEYWORD bool) +K_BREAK=$(D_KEYWORD break) +K_BYTE=$(D_KEYWORD byte) +_= + +K_CASE=$(D_KEYWORD case) +K_CAST=$(D_KEYWORD cast) +K_CATCH=$(D_KEYWORD catch) +K_CHAR=$(D_KEYWORD char) +K_CLASS=$(D_KEYWORD class) +K_CONST=$(D_KEYWORD const) +K_CONTINUE=$(D_KEYWORD continue) +_= + +K_DCHAR=$(D_KEYWORD dchar) +K_DEBUG=$(D_KEYWORD debug) +K_DEFAULT=$(D_KEYWORD default) +K_DELEGATE=$(D_KEYWORD delegate) +K_DEPRECATED=$(D_KEYWORD deprecated) +K_DO=$(D_KEYWORD do) +K_DOUBLE=$(D_KEYWORD double) +_= + +K_ELSE=$(D_KEYWORD else) +K_ENUM=$(D_KEYWORD enum) +K_EXPORT=$(D_KEYWORD export) +K_EXTERN=$(D_KEYWORD extern) +_= + +K_FALSE=$(D_KEYWORD false) +K_FINAL=$(D_KEYWORD final) +K_FINALLY=$(D_KEYWORD finally) +K_FLOAT=$(D_KEYWORD float) +K_FOR=$(D_KEYWORD for) +K_FOREACH=$(D_KEYWORD foreach) +K_FOREACH_REVERSE=$(D_KEYWORD foreach_reverse) +K_FUNCTION=$(D_KEYWORD function) +_= + +K_GOTO=$(D_KEYWORD goto) +_= + +K_IF=$(D_KEYWORD if) +K_IMMUTABLE=$(D_KEYWORD immutable) +K_IMPORT=$(D_KEYWORD import) +K_IN=$(D_KEYWORD in) +K_INOUT=$(D_KEYWORD inout) +K_INT=$(D_KEYWORD int) +K_INTERFACE=$(D_KEYWORD interface) +K_INVARIANT=$(D_KEYWORD invariant) +K_IS=$(D_KEYWORD is) +_= + +K_LAZY=$(D_KEYWORD lazy) +K_LONG=$(D_KEYWORD long) +_= + +K_MACRO=$(D_KEYWORD macro) +K_MIXIN=$(D_KEYWORD mixin) +K_MODULE=$(D_KEYWORD module) +_= + +K_NEW=$(D_KEYWORD new) +K_NOTHROW=$(D_KEYWORD nothrow) +K_NULL=$(D_KEYWORD null) +_= + +K_OUT=$(D_KEYWORD out) +K_OVERRIDE=$(D_KEYWORD override) +_= + +K_PACKAGE=$(D_KEYWORD package) +K_PRAGMA=$(D_KEYWORD pragma) +K_PRIVATE=$(D_KEYWORD private) +K_PROTECTED=$(D_KEYWORD protected) +K_PUBLIC=$(D_KEYWORD public) +K_PURE=$(D_KEYWORD pure) +_= + +K_REAL=$(D_KEYWORD real) +K_REF=$(D_KEYWORD ref) +K_RETURN=$(D_KEYWORD return) +_= + +K_SCOPE=$(D_KEYWORD scope) +K_SHARED=$(D_KEYWORD shared) +K_SHORT=$(D_KEYWORD short) +K_STATIC=$(D_KEYWORD static) +K_STRUCT=$(D_KEYWORD struct) +K_SUPER=$(D_KEYWORD super) +K_SWITCH=$(D_KEYWORD switch) +K_SYNCHRONIZED=$(D_KEYWORD synchronized) +_= + +K_TEMPLATE=$(D_KEYWORD template) +K_THIS=$(D_KEYWORD this) +K_THROW=$(D_KEYWORD throw) +K_TRUE=$(D_KEYWORD true) +K_TRY=$(D_KEYWORD try) +K_TYPEID=$(D_KEYWORD typeid) +K_TYPEOF=$(D_KEYWORD typeof) +_= + +K_UBYTE=$(D_KEYWORD ubyte) +K_UINT=$(D_KEYWORD uint) +K_ULONG=$(D_KEYWORD ulong) +K_UNION=$(D_KEYWORD union) +K_UNITTEST=$(D_KEYWORD unittest) +K_USHORT=$(D_KEYWORD ushort) +_= + +K_VERSION=$(D_KEYWORD version) +K_VOID=$(D_KEYWORD void) +_= + +K_WCHAR=$(D_KEYWORD wchar) +K_WHILE=$(D_KEYWORD while) +K_WITH=$(D_KEYWORD with) +_= + +K___GSHARED=$(D_KEYWORD __gshared) +K___PARAMETERS=$(D_KEYWORD __parameters) +K___RVALUE=$(D_KEYWORD __rvalue) +K___TRAITS=$(D_KEYWORD __traits) +K___VECTOR=$(D_KEYWORD __vector) +_= + +_= These aren't technically keywords per the spec, but they're effectively +keywords, so we're treating them as such. The spec treats the @ attributes +differently because of the @, but they're arguably just keywords listed in +another part of the spec, and the types are aliases from object.d. + +K_DISABLE=$(D_KEYWORD @disable) +K_NOGC=$(D_KEYWORD @nogc) +K_PROPERTY=$(D_KEYWORD @property) +K_SAFE=$(D_KEYWORD @safe) +K_SYSTEM=$(D_KEYWORD @system) +K_TRUSTED=$(D_KEYWORD @trusted) +_= + +K_NORETURN=$(D_KEYWORD noreturn) +_= + +K_STRING=$(D_KEYWORD string) +K_WSTRING=$(D_KEYWORD wstring) +K_DSTRING=$(D_KEYWORD dstring) +_= + +K_PTRDIFF_T=$(D_KEYWORD ptrdiff_t) +K_SIZEDIFF_T=$(D_KEYWORD sizediff_t) +K_SIZE_T=$(D_KEYWORD size_t) +_= diff --git a/language-changelog/README.md b/language-changelog/README.md new file mode 100644 index 0000000000..a650fdead4 --- /dev/null +++ b/language-changelog/README.md @@ -0,0 +1,32 @@ +How to add a new changelog entry to the pending changelog? +========================================================== + +This will get copied to dlang.org and cleared when master gets +merged into stable prior to a new release. + +``` +My fancy new feature X + +A long description of the new feature. +------- +import std.range; +import std.algorithm.comparison; + +assert([1, 2, 3, 4, 5].padLeft(0, 7).equal([0, 0, 1, 2, 3, 4, 5])); + +assert("Hello World!".padRight('!', 15).equal("Hello World!!!!")); +------- +``` + +The title can't contain links (it's already one). +For more infos, see the [Ddoc spec](https://dlang.org/spec/ddoc.html). + +Preview changes +--------------- + +If you have cloned the [tools](https://github.com/dlang/tools) and [dlang.org](https://github.com/dlang/dlang.org) repo), +you can preview the changelog with: + +``` +make -C ../dlang.org -f posix.mak pending_changelog +``` diff --git a/language-reference.html b/language-reference.html deleted file mode 100644 index 057cd5342d..0000000000 --- a/language-reference.html +++ /dev/null @@ -1,9 +0,0 @@ - - - -D Runtime Library - - - - - diff --git a/lex.dd b/lex.dd deleted file mode 100644 index 98ffddad0d..0000000000 --- a/lex.dd +++ /dev/null @@ -1,1150 +0,0 @@ -Ddoc - -$(SPEC_S Lexical, - - The lexical analysis is independent of the syntax parsing and the - semantic analysis. The lexical analyzer splits the source text up into - tokens. The lexical grammar describes what those tokens are. The - grammar is designed to be suitable for high speed scanning, it - has a minimum of special case rules, there is only one phase of - translation, and to make it easy to write a correct scanner - for. The tokens are readily recognizable by those familiar with C and - C++. - -

    Source Text

    - - D source text can be in one of the following formats: - - $(LIST - ASCII, - UTF-8, - UTF-16BE, - UTF-16LE, - UTF-32BE, - UTF-32LE - ) - - UTF-8 is a superset of traditional 7-bit ASCII. - One of the - following UTF BOMs (Byte Order Marks) can be present at the beginning - of the source text: -

    - - $(TABLE2 UTF Byte Order Marks, - $(THEAD Format, BOM) - $(TROW UTF-8, EF BB BF) - $(TROW UTF-16BE, FE FF) - $(TROW UTF-16LE, FF FE) - $(TROW UTF-32BE, 00 00 FE FF) - $(TROW UTF-32LE, FF FE 00 00) - $(TROW ASCII, no BOM) - ) - - $(P If the source file does not start with a BOM, then the first - character must be less than or equal to U0000007F.) - - $(P There are no digraphs or trigraphs in D.) - - $(P The source text is decoded from its source representation - into Unicode $(GLINK Character)s. - The $(GLINK Character)s are further divided into: - - $(GLINK WhiteSpace), - $(GLINK EndOfLine), - $(GLINK Comment)s, - $(GLINK SpecialTokenSequence)s, - $(GLINK Token)s, - all followed by $(GLINK EndOfFile). - ) - - $(P The source text is split into tokens using the maximal munch - technique, i.e., the - lexical analyzer tries to make the longest token it can. For example - >> is a right shift token, - not two greater than tokens. An exception to this rule is that a .. - embedded inside what looks like two floating point literals, as in - 1..2, is interpreted as if the .. was separated by a space from the - first integer. - ) - -

    Character Set

    - -$(GRAMMAR -$(GNAME Character) - $(I any Unicode character) -) - -

    End of File

    - -$(GRAMMAR -$(GNAME EndOfFile): - $(I physical end of the file) - \u0000 - \u001A -) - - The source text is terminated by whichever comes first. - -

    End of Line

    - -$(GRAMMAR -$(GNAME EndOfLine): - \u000D - \u000A - \u000D \u000A - $(GLINK EndOfFile) -) - - There is no backslash line splicing, nor are there any limits - on the length of a line. - -

    White Space

    - -$(GRAMMAR -$(GNAME WhiteSpace): - $(GLINK Space) - $(GLINK Space) $(I WhiteSpace) - -$(GNAME Space): - \u0020 - \u0009 - \u000B - \u000C -) - - -

    $(LNAME2 comment, Comments)

    - -$(GRAMMAR -$(GNAME Comment): - $(GLINK BlockComment) - $(GLINK LineComment) - $(GLINK NestingBlockComment) - -$(GNAME BlockComment) - $(B /*) $(GLINK Characters) $(B */) - -$(GNAME LineComment) - $(B //) $(GLINK Characters) $(GLINK EndOfLine) - -$(GNAME NestingBlockComment): - $(B /+) $(GLINK NestingBlockCommentCharacters) $(B +/) - -$(GNAME NestingBlockCommentCharacters): - $(GLINK NestingBlockCommentCharacter) - $(GLINK NestingBlockCommentCharacter) $(I NestingBlockCommentCharacters) - -$(GNAME NestingBlockCommentCharacter): - $(GLINK Character) - $(GLINK NestingBlockComment) - -$(GNAME Characters): - $(GLINK Character) - $(GLINK Character) $(I Characters) -) - - $(P D has three kinds of comments:) - - $(OL - $(LI Block comments can span multiple lines, but do not nest.) - $(LI Line comments terminate at the end of the line.) - $(LI Nesting block comments can span multiple lines and can nest.) - ) - - $(P - The contents of strings and comments are not tokenized. Consequently, - comment openings occurring within a string do not begin a comment, and - string delimiters within a comment do not affect the recognition of - comment closings and nested "/+" comment openings. With the exception - of "/+" occurring within a "/+" comment, comment openings within a - comment are ignored. - ) - -------------- -a = /+ // +/ 1; // parses as if 'a = 1;' -a = /+ "+/" +/ 1"; // parses as if 'a = " +/ 1";' -a = /+ /* +/ */ 3; // parses as if 'a = */ 3;' -------------- - - Comments cannot be used as token concatenators, for example, - abc/**/def is two tokens, $(D abc) and $(D def), - not one $(D abcdef) token. - -

    Tokens

    - -$(GRAMMAR -$(GNAME Token): - $(GLINK Identifier) - $(GLINK StringLiteral) - $(GLINK CharacterLiteral) - $(GLINK IntegerLiteral) - $(GLINK FloatLiteral) - $(GLINK Keyword) - $(B /) - $(B /=) - $(B .) - $(B ..) - $(B ...) - $(B &) - $(B &=) - $(B &&) - $(B |) - $(B |=) - $(B ||) - $(B -) - $(B -=) - $(B --) - $(B +) - $(B +=) - $(B ++) - $(B <) - $(B <=) - $(B <<) - $(B <<=) - $(B <>) - $(B <>=) - $(B >) - $(B >=) - $(B >>=) - $(B >>>=) - $(B >>) - $(B >>>) - $(B !) - $(B !=) - $(B !<>) - $(B !<>=) - $(B !<) - $(B !<=) - $(B !>) - $(B !>=) - $(B $(LPAREN)) - $(B $(RPAREN)) - $(B [) - $(B ]) - $(B {) - $(B }) - $(B ?) - $(B ,) - $(B ;) - $(B :) - $(B $) - $(B =) - $(B ==) - $(B *) - $(B *=) - $(B %) - $(B %=) - $(B ^) - $(B ^=) - $(B ~) - $(B ~=) - $(V2 $(B @)) - $(V2 $(B =>)) -) - -

    Identifiers

    - -$(GRAMMAR -$(GNAME Identifier): - $(GLINK IdentifierStart) - $(GLINK IdentifierStart) $(GLINK IdentifierChars) - -$(GNAME IdentifierChars): - $(GLINK IdentifierChar) - $(GLINK IdentifierChar) $(I IdentifierChars) - -$(GNAME IdentifierStart): - $(B _) - $(I Letter) - $(I UniversalAlpha) - -$(GNAME IdentifierChar): - $(GLINK IdentifierStart) - $(B 0) - $(GLINK NonZeroDigit) -) - - - Identifiers start with a letter, $(B _), or universal alpha, - and are followed by any number - of letters, $(B _), digits, or universal alphas. - Universal alphas are as defined in ISO/IEC 9899:1999(E) Appendix D. - (This is the C99 Standard.) - Identifiers can be arbitrarily long, and are case sensitive. - Identifiers starting with $(B __) (two underscores) are reserved. - -

    String Literals

    - -$(GRAMMAR -$(GNAME StringLiteral): - $(GLINK WysiwygString) - $(GLINK AlternateWysiwygString) - $(GLINK DoubleQuotedString) -$(V1 - $(GLINK EscapeSequence)) - $(GLINK HexString) -$(V2 - $(GLINK DelimitedString) - $(GLINK TokenString)) - -$(GNAME WysiwygString): - $(B r") $(GLINK WysiwygCharacters) $(B ") $(GLINK StringPostfix)opt - -$(GNAME AlternateWysiwygString): - $(B `) $(GLINK WysiwygCharacters) $(B `) $(GLINK StringPostfix)opt - -$(GNAME WysiwygCharacters): - $(GLINK WysiwygCharacter) - $(GLINK WysiwygCharacter) $(I WysiwygCharacters) - -$(GNAME WysiwygCharacter): - $(GLINK Character) - $(GLINK EndOfLine) - -$(GNAME DoubleQuotedString): - $(B ") $(GLINK DoubleQuotedCharacters) $(B ") $(GLINK StringPostfix)opt - -$(GNAME DoubleQuotedCharacters): - $(GLINK DoubleQuotedCharacter) - $(GLINK DoubleQuotedCharacter) $(I DoubleQuotedCharacters) - -$(GNAME DoubleQuotedCharacter): - $(GLINK Character) - $(GLINK EscapeSequence) - $(GLINK EndOfLine) - -$(GNAME EscapeSequence): - $(B \') - $(B \") - $(B \?) - $(B \\) - $(B \a) - $(B \b) - $(B \f) - $(B \n) - $(B \r) - $(B \t) - $(B \v) - $(B \) $(GLINK EndOfFile) - $(B \x) $(GLINK HexDigit) $(GLINK HexDigit) - $(B \) $(GLINK OctalDigit) - $(B \) $(GLINK OctalDigit) $(GLINK OctalDigit) - $(B \) $(GLINK OctalDigit) $(GLINK OctalDigit) $(GLINK OctalDigit) - $(B \u) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) - $(B \U) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) - $(GLINK2 entity, NamedCharacterEntity) - -$(GNAME HexString): - $(B x") $(GLINK HexStringChars) $(B ") $(GLINK StringPostfix)opt - -$(GNAME HexStringChars): - $(GLINK HexStringChar) - $(GLINK HexStringChar) $(I HexStringChars) - -$(GNAME HexStringChar): - $(GLINK HexDigit) - $(GLINK WhiteSpace) - $(GLINK EndOfLine) - -$(GNAME StringPostfix): - $(B c) - $(B w) - $(B d) - -$(V2 -$(GNAME DelimitedString): - $(B q") $(I Delimiter) $(GLINK WysiwygCharacters) $(I MatchingDelimiter) $(B ") - -$(GNAME TokenString): - $(B q{) $(GLINK Token)s $(B }) -) -) - - $(P - A string literal is either a double quoted string, a wysiwyg quoted - string, an escape sequence, - $(V2 a delimited string, a token string,) - or a hex string. - ) - - $(P In all string literal forms, an $(GLINK EndOfLine) is regarded as a single - \n character.) - -

    Wysiwyg Strings

    - - $(P - Wysiwyg quoted strings are enclosed by r" and ". - All characters between - the r" and " are part of the string. - There are no escape sequences inside r" ": - ) - ---------------- -r"hello" -r"c:\root\foo.exe" -r"ab\n" // string is 4 characters, - // 'a', 'b', '\', 'n' ---------------- - - $(P - An alternate form of wysiwyg strings are enclosed by backquotes, - the ` character. The ` character is not available on some keyboards - and the font rendering of it is sometimes indistinguishable from - the regular ' character. Since, however, the ` is rarely used, - it is useful to delineate strings with " in them. - ) - ---------------- -`hello` -`c:\root\foo.exe` -`ab\n` // string is 4 characters, - // 'a', 'b', '\', 'n' ---------------- - -

    Double Quoted Strings

    - - Double quoted strings are enclosed by "". Escape sequences can be - embedded into them with the typical \ notation. - ---------------- -"hello" -"c:\\root\\foo.exe" -"ab\n" // string is 3 characters, - // 'a', 'b', and a linefeed -"ab -" // string is 3 characters, - // 'a', 'b', and a linefeed ---------------- - -$(V1 -

    Escape Strings

    - - $(P Escape strings start with a \ and form an escape character sequence. - Adjacent escape strings are concatenated: - ) - -$(TABLE1 -$(TROW \n, the linefeed character) -$(TROW \t, the tab character) -$(TROW \", the double quote character) -$(TROW \012, octal) -$(TROW \x1A, hex) -$(TROW \u1234, wchar character) -$(TROW \U00101234, dchar character) -$(TROW \&reg;, ® dchar character) -$(TROW \r\n, carriage return, line feed) -) - - $(P Undefined escape sequences are errors. - Although string literals are defined to be composed of - UTF characters, the octal and hex escape sequences allow - the insertion of arbitrary binary data. - \u and \U escape sequences can only be used to insert - valid UTF characters. - ) -) - -

    Hex Strings

    - - $(P Hex strings allow string literals to be created using hex data. - The hex data need not form valid UTF characters. - ) - --------------- -x"0A" // same as "\x0A" -x"00 FBCD 32FD 0A" // same as - // "\x00\xFB\xCD\x32\xFD\x0A" --------------- - - Whitespace and newlines are ignored, so the hex data can be - easily formatted. - The number of hex characters must be a multiple of 2. -

    - - Adjacent strings are concatenated with the ~ operator, or by simple - juxtaposition: - --------------- -"hello " ~ "world" ~ $(V1 \n)$(V2 "\n") // forms the string - // 'h','e','l','l','o',' ', - // 'w','o','r','l','d',linefeed --------------- - - The following are all equivalent: - ------------------ -"ab" "c" -r"ab" r"c" -r"a" "bc" -"a" ~ "b" ~ "c" -$(V1 \x61"bc") ------------------ - - $(P The optional $(I StringPostfix) character gives a specific type - to the string, rather than it being inferred from the context. - This is useful when the type cannot be unambiguously inferred, - such as when overloading based on string type. The types corresponding - to the postfix characters are: - ) - -$(V1 - $(TABLE2 String Literal Postfix Characters, - $(THEAD Postfix, Type, Aka) - $(TROW $(B c), $(D char[]), $(D string)) - $(TROW $(B w), $(D wchar[]), $(D wstring)) - $(TROW $(B d), $(D dchar[]), $(D dstring)) - ) -) -$(V2 - $(TABLE2 String Literal Postfix Characters, - $(THEAD Postfix, Type, Aka) - $(TROW $(B c), $(D immutable(char)[]), $(D string)) - $(TROW $(B w), $(D immutable(wchar)[]), $(D wstring)) - $(TROW $(B d), $(D immutable(dchar)[]), $(D dstring)) - ) -) ---- -"hello"c // string -"hello"w // wstring -"hello"d // dstring ---- - - $(P The string literals are assembled as UTF-8 char arrays, - and the postfix is applied - to convert to wchar or dchar as necessary as a final step.) - - $(P String literals are read only. Writes to string literals - cannot always be detected, but cause undefined behavior.) - -$(V2 -

    Delimited Strings

    - - $(P Delimited strings use various forms of delimiters. - The delimiter, whether a character or identifer, - must immediately follow the " without any intervening whitespace. - The terminating delimiter must immediately precede the closing " - without any intervening whitespace. - A $(I nesting delimiter) nests, and is one of the - following characters: - ) - - $(TABLE2 Nesting Delimiters, - $(THEAD Delimiter, Matching Delimiter) - $(TROW [, ]) - $(TROW $(LPAREN), $(RPAREN)) - $(TROW <, >) - $(TROW {, }) - ) - ---- -q"(foo(xxx))" // "foo(xxx)" -q"[foo{]" // "foo{" ---- - - $(P If the delimiter is an identifier, the identifier must - be immediately followed by a newline, and the matching - delimiter is the same identifier starting at the beginning - of the line: - ) ---- -writefln(q"EOS -This -is a multi-line -heredoc string -EOS" -); ---- - $(P The newline following the opening identifier is not part - of the string, but the last newline before the closing - identifier is part of the string. The closing identifier - must be placed on its own line at the leftmost column. - ) - - $(P Otherwise, the matching delimiter is the same as - the delimiter character:) - ---- -q"/foo]/" // "foo]" -q"/abc/def/" // error ---- - -

    Token Strings

    - - $(P Token strings open with the characters $(B q{) and close with - the token $(B }). In between must be valid D tokens. - The $(B {) and $(B }) tokens nest. - The string is formed of all the characters between the opening - and closing of the token string, including comments. - ) - ---- -q{foo} // "foo" -q{/*}*/ } // "/*}*/ " -q{ foo(q{hello}); } // " foo(q{hello}); " -q{ __TIME__ } // " __TIME__ ", i.e. it is not replaced with the time -q{ __EOF__ } // error, as __EOF__ is not a token, it's end of file ---- - -) - -

    $(LNAME2 characterliteral, Character Literals)

    - -$(GRAMMAR -$(GNAME CharacterLiteral): - $(B ') $(GLINK SingleQuotedCharacter) $(B ') - -$(GNAME SingleQuotedCharacter): - $(GLINK Character) - $(GLINK EscapeSequence) -) - - Character literals are a single character or escape sequence - enclosed by single quotes, ' '. - -

    $(LNAME2 integerliteral, Integer Literals)

    - -$(GRAMMAR -$(GNAME IntegerLiteral): - $(GLINK Integer) - $(GLINK Integer) $(I IntegerSuffix) - -$(GNAME Integer): - $(GLINK DecimalInteger) - $(GLINK BinaryInteger) -$(V1 $(GLINK OctalInteger) -) $(GLINK HexadecimalInteger) - -$(GNAME IntegerSuffix): - $(B L) - $(B u) - $(B U) - $(B Lu) - $(B LU) - $(B uL) - $(B UL) - -$(GNAME DecimalInteger): - $(B 0) - $(GLINK NonZeroDigit) - $(GLINK NonZeroDigit) $(I DecimalDigitsUS) - -$(GNAME BinaryInteger): - $(GLINK BinPrefix) $(GLINK BinaryDigits) - -$(GNAME BinPrefix): - $(B 0b) - $(B 0B) - -$(V1 $(GNAME OctalInteger): - $(B 0) $(GLINK OctalDigitsUS) - -)$(GNAME HexadecimalInteger): - $(GLINK HexPrefix) $(GLINK HexDigitsNoSingleUS) - -$(GNAME NonZeroDigit): - $(B 1) - $(B 2) - $(B 3) - $(B 4) - $(B 5) - $(B 6) - $(B 7) - $(B 8) - $(B 9) - -$(GNAME DecimalDigits): - $(GLINK DecimalDigit) - $(GLINK DecimalDigit) $(I DecimalDigits) - -$(GNAME DecimalDigitsUS): - $(GLINK DecimalDigitUS) - $(GLINK DecimalDigitUS) $(I DecimalDigitsUS) - -$(GNAME DecimalDigitsNoSingleUS): - $(GLINK DecimalDigit) - $(GLINK DecimalDigit) $(GLINK DecimalDigitsUS) - $(GLINK DecimalDigitsUS) $(GLINK DecimalDigit) - -$(GNAME DecimalDigitsNoStartingUS): - $(GLINK DecimalDigit) - $(GLINK DecimalDigit) $(GLINK DecimalDigitsUS) - -$(GNAME DecimalDigit): - $(B 0) - $(GLINK NonZeroDigit) - -$(GNAME DecimalDigitUS): - $(GLINK DecimalDigit) - $(B _) - -$(GNAME BinaryDigitsUS): - $(GLINK BinaryDigitUS) - $(GLINK BinaryDigitUS) $(I BinaryDigitsUS) - -$(GNAME BinaryDigit): - $(B 0) - $(B 1) - -$(GNAME BinaryDigitUS): - $(GLINK BinaryDigit) - $(B _) - -$(GNAME OctalDigits): - $(GLINK OctalDigit) - $(GLINK OctalDigit) $(I OctalDigits) - -$(GNAME OctalDigitsUS): - $(GLINK OctalDigitUS) - $(GLINK OctalDigitUS) $(I OctalDigitsUS) - -$(GNAME OctalDigit): - $(B 0) - $(B 1) - $(B 2) - $(B 3) - $(B 4) - $(B 5) - $(B 6) - $(B 7) - -$(GNAME OctalDigitUS): - $(GLINK OctalDigit) - $(B _) - -$(GNAME HexDigits): - $(GLINK HexDigit) - $(GLINK HexDigit) $(I HexDigits) - -$(GNAME HexDigitsUS): - $(GLINK HexDigitUS) - $(GLINK HexDigitUS) $(I HexDigitsUS) - -$(GNAME HexDigitsNoSingleUS): - $(GLINK HexDigit) - $(GLINK HexDigit) $(GLINK HexDigitsUS) - $(GLINK HexDigitsUS) $(GLINK HexDigit) - -$(GNAME HexDigit): - $(GLINK DecimalDigit) - $(GLINK HexLetter) - -$(GNAME HexLetter): - $(B a) - $(B b) - $(B c) - $(B d) - $(B e) - $(B f) - $(B A) - $(B B) - $(B C) - $(B D) - $(B E) - $(B F) - $(B _) -) - - $(P Integers can be specified in decimal, binary, octal, or hexadecimal.) - - $(P Decimal integers are a sequence of decimal digits.) - - $(P $(LNAME2 binary-literals, Binary integers) are a sequence of binary digits preceded - by a $(SINGLEQUOTE 0b). - ) - - $(V1 $(P Octal integers are a sequence of octal digits preceded by a $(SINGLEQUOTE 0).)) - - $(P Hexadecimal integers are a sequence of hexadecimal digits preceded - by a $(SINGLEQUOTE 0x). - ) - - $(P Integers can have embedded $(SINGLEQUOTE _) characters, which are ignored. - The embedded $(SINGLEQUOTE _) are useful for formatting long literals, such - as using them as a thousands separator: - ) - -------------- -123_456 // 123456 -1_2_3_4_5_6_ // 123456 -------------- - - $(P Integers can be immediately followed by one $(SINGLEQUOTE L) or one of - $(SINGLEQUOTE u) or $(SINGLEQUOTE U) or both. - Note that there is no $(SINGLEQUOTE l) suffix. - ) - - $(P The type of the integer is resolved as follows:) - - $(TABLE2 Decimal Literal Types, - - $(THEAD Decimal Literal, Type) - $(TROW 0 .. 2_147_483_647, int) - $(TROW 2_147_483_648 .. 9_223_372_036_854_775_807L, long) - - $(THEAD $(ARGS Decimal Literal, L Suffix), Type) - $(TROW 0L .. 9_223_372_036_854_775_807L, long) - - $(THEAD $(ARGS Decimal Literal, U Suffix), Type) - $(TROW 0U .. 4_294_967_296U, uint) - $(TROW 4_294_967_296U .. 18_446_744_073_709_551_615UL, ulong) - - $(THEAD $(ARGS Decimal Literal, UL Suffix), Type) - $(TROW 0UL .. 18_446_744_073_709_551_615UL, ulong) - - $(THEAD Non-Decimal Literal, Type) - $(TROW 0x0 .. 0x7FFF_FFFF, int) - $(TROW 0x8000_0000 .. 0xFFFF_FFFF, uint) - $(TROW 0x1_0000_0000 .. 0x7FFF_FFFF_FFFF_FFFF, long) - $(TROW 0x8000_0000_0000_0000 .. 0xFFFF_FFFF_FFFF_FFFF, ulong) - - $(THEAD $(ARGS Non-Decimal Literal, L Suffix), Type) - $(TROW 0x0L .. 0x7FFF_FFFF_FFFF_FFFFL, long) - $(TROW 0x8000_0000_0000_0000L .. 0xFFFF_FFFF_FFFF_FFFFL, ulong) - - $(THEAD $(ARGS Non-Decimal Literal, U Suffix), Type) - $(TROW 0x0U .. 0xFFFF_FFFFU, uint) - $(TROW 0x1_0000_0000UL .. 0xFFFF_FFFF_FFFF_FFFFUL, ulong) - - $(THEAD $(ARGS Non-Decimal Literal, UL Suffix), Type) - $(TROW 0x0UL .. 0xFFFF_FFFF_FFFF_FFFFUL, ulong) - - ) - - -

    $(LNAME2 floatliteral, Floating Literals)

    - -$(GRAMMAR -$(GNAME FloatLiteral): - $(GLINK Float) - $(GLINK Float) $(GLINK Suffix) - $(GLINK Integer) $(GLINK ImaginarySuffix) - $(GLINK Integer) $(GLINK FloatSuffix) $(GLINK ImaginarySuffix) - $(GLINK Integer) $(GLINK RealSuffix) $(GLINK ImaginarySuffix) - -$(GNAME Float): - $(GLINK DecimalFloat) - $(GLINK HexFloat) - -$(GNAME DecimalFloat): - $(GLINK LeadingDecimal) $(B .) - $(GLINK LeadingDecimal) $(B .) $(GLINK DecimalDigits) - $(GLINK DecimalDigits) $(B .) $(GLINK DecimalDigitsNoSingleUS) $(GLINK DecimalExponent) - $(B .) $(GLINK DecimalInteger) - $(B .) $(GLINK DecimalInteger) $(GLINK DecimalExponent) - $(GLINK LeadingDecimal) $(GLINK DecimalExponent) - -$(GNAME DecimalExponent) - $(GLINK DecimalExponentStart) $(GLINK DecimalDigitsNoSingleUS) - -$(GNAME DecimalExponentStart) - $(B e) - $(B E) - $(B e+) - $(B E+) - $(B e-) - $(B E-) - -$(GNAME HexFloat): - $(GLINK HexPrefix) $(GLINK HexDigitsNoSingleUS) $(B .) $(GLINK HexDigitsNoSingleUS) $(GLINK HexExponent) - $(GLINK HexPrefix) $(B .) $(GLINK HexDigitsNoSingleUS) $(GLINK HexExponent) - $(GLINK HexPrefix) $(GLINK HexDigitsNoSingleUS) $(GLINK HexExponent) - -$(GNAME HexPrefix): - $(B 0x) - $(B 0X) - -$(GNAME HexExponent): - $(GLINK HexExponentStart) $(GLINK DecimalDigitsNoSingleUS) - -$(GNAME HexExponentStart): - $(B p) - $(B P) - $(B p+) - $(B P+) - $(B p-) - $(B P-) - - -$(GNAME Suffix): - $(GLINK FloatSuffix) - $(GLINK RealSuffix) - $(GLINK ImaginarySuffix) - $(GLINK FloatSuffix) $(GLINK ImaginarySuffix) - $(GLINK RealSuffix) $(GLINK ImaginarySuffix) - -$(GNAME FloatSuffix): - $(B f) - $(B F) - -$(GNAME RealSuffix): - $(B L) - -$(GNAME ImaginarySuffix): - $(B i) - -$(GNAME LeadingDecimal): - $(GLINK DecimalInteger) - $(B 0) $(GLINK DecimalDigitsNoSingleUS) -) - - $(P Floats can be in decimal or hexadecimal format.) - - $(P Hexadecimal floats are preceded with a $(B 0x) and the - exponent is a $(B p) - or $(B P) followed by a decimal number serving as the exponent - of 2. - ) - - $(P Floating literals can have embedded $(SINGLEQUOTE _) characters, which are ignored. - The embedded $(SINGLEQUOTE _) are useful for formatting long literals to - make them more readable, such - as using them as a thousands separator: - ) - ---------- -123_456.567_8 // 123456.5678 -1_2_3_4_5_6_._5_6_7_8 // 123456.5678 -1_2_3_4_5_6_._5e-6_ // 123456.5e-6 ---------- - - $(P Floating literals with no suffix are of type double. - Floats can be followed by one $(B f), $(B F), - or $(B L) suffix. - The $(B f) or $(B F) suffix means it is a - float, and $(B L) means it is a real. - ) - - $(P If a floating literal is followed by $(B i), then it is an - $(I ireal) (imaginary) type. - ) - - $(P Examples:) - ---------- -0x1.FFFFFFFFFFFFFp1023 // double.max -0x1p-52 // double.epsilon -1.175494351e-38F // float.min -6.3i // idouble 6.3 -6.3fi // ifloat 6.3 -6.3Li // ireal 6.3 ---------- - - $(P It is an error if the literal exceeds the range of the type. - It is not an error if the literal is rounded to fit into - the significant digits of the type. - ) - - $(P Complex literals are not tokens, but are assembled from - real and imaginary expressions during semantic analysis: - ) - ---------- -4.5 + 6.2i // complex number (phased out) ---------- - -

    Keywords

    - - Keywords are reserved identifiers. - -$(GRAMMAR -$(GNAME Keyword): - $(B abstract) - $(B alias) - $(B align) - $(B asm) - $(B assert) - $(B auto) - - $(B body) - $(B bool) - $(B break) - $(B byte) - - $(B case) - $(B cast) - $(B catch) - $(B cdouble) - $(B cent) - $(B cfloat) - $(B char) - $(B class) - $(B const) - $(B continue) - $(B creal) - - $(B dchar) - $(B debug) - $(B default) - $(B delegate) - $(B delete) - $(B deprecated) - $(B do) - $(B double) - - $(B else) - $(B enum) - $(B export) - $(B extern) - - $(B false) - $(B final) - $(B finally) - $(B float) - $(B for) - $(B foreach) - $(B foreach_reverse) - $(B function) - - $(B goto) - - $(B idouble) - $(B if) - $(B ifloat) -$(V2 - $(B immutable) -) $(B import) - $(B in) - $(B inout) - $(B int) - $(B interface) - $(B invariant) - $(B ireal) - $(B is) - - $(B lazy) - $(B long) - - $(B macro) - $(B mixin) - $(B module) - - $(B new) -$(V2 - $(B nothrow) -) $(B null) - - $(B out) - $(B override) - - $(B package) - $(B pragma) - $(B private) - $(B protected) - $(B public) -$(V2 - $(B pure) -) - $(B real) - $(B ref) - $(B return) - - $(B scope) -$(V2 - $(B shared) -) $(B short) - $(B static) - $(B struct) - $(B super) - $(B switch) - $(B synchronized) - - $(B template) - $(B this) - $(B throw) - $(B true) - $(B try) - $(B typedef) - $(B typeid) - $(B typeof) - - $(B ubyte) - $(B ucent) - $(B uint) - $(B ulong) - $(B union) - $(B unittest) - $(B ushort) - - $(B version) - $(B void) - $(B volatile) - - $(B wchar) - $(B while) - $(B with) -$(V2 - $(B __FILE__) - $(B __LINE__) - $(B __gshared) - $(B __thread) - $(B __traits)) -) - -

    $(LNAME2 specialtokens, Special Tokens)

    - - $(P - These tokens are replaced with other tokens according to the following - table: - ) - - $(TABLE2 Special Tokens, - $(THEAD Special Token, Replaced with...) -$(V1 - $(TROW $(CODE __FILE__), string literal containing source file name) - $(TROW $(CODE __LINE__), integer literal of the current source line number) -) - $(TROW $(CODE __DATE__), string literal of the date of compilation "$(I mmm dd yyyy)") -$(V2 - $(TROW $(CODE __EOF__), sets the scanner to the end of the file) -) - $(TROW $(CODE __TIME__), string literal of the time of compilation "$(I hh:mm:ss)") - $(TROW $(CODE __TIMESTAMP__), string literal of the date and time of compilation "$(I www mmm dd hh:mm:ss yyyy)") - $(TROW $(CODE __VENDOR__), $(ARGS Compiler vendor string, such as "Digital Mars D")) - $(TROW $(CODE __VERSION__), $(ARGS Compiler version as an integer, such as 2001)) - ) - -

    $(LNAME2 Special Token Sequence, Special Token Sequences)

    - -$(GRAMMAR -$(GNAME SpecialTokenSequence): - $(B # line) $(GLINK IntegerLiteral) $(GLINK EndOfLine) - $(B # line) $(GLINK IntegerLiteral) $(GLINK Filespec) $(GLINK EndOfLine) - -$(GNAME Filespec): - $(B ") $(GLINK Characters) $(B ") -) - - $(P Special token sequences are processed by the lexical analyzer, may - appear between any other tokens, and do not affect the syntax - parsing. - ) - - $(P There is currently only one special token sequence, $(D #line). - ) - - $(P This sets the source line number to $(GLINK IntegerLiteral), - and optionally the source file name to $(GLINK Filespec), - beginning with the next line of source text. - The source file and line number is used for printing error messages - and for mapping generated code back to the source for the symbolic - debugging output. - ) - - $(P For example: - ) - ------------------ -int #line 6 "foo\bar" -x; // this is now line 6 of file foo\bar ------------------ - - $(P Note that the backslash character is not treated specially inside - $(GLINK Filespec) strings. - ) -) - -Macros: - TITLE=Lexical - WIKI=Lex - CATEGORY_SPEC=$0 - diff --git a/linux.ddoc b/linux.ddoc index f235ee735f..977df5e75e 100644 --- a/linux.ddoc +++ b/linux.ddoc @@ -7,5 +7,6 @@ UNIX=$0 SEP=/ OBJEXT=o LIBEXT=a +BINEXT= DMDDIR=dmd2 -FOO= +_= diff --git a/macros.ddoc b/macros.ddoc index 0731352277..236e41693e 100644 --- a/macros.ddoc +++ b/macros.ddoc @@ -1,46 +1,14 @@ -TRANSLATIONS= - -TRANSLATIONS= -
    - - - -
    - - -TRANSLATIONS= - - -RED = $0 -GREEN = $0 -BLUE = $0 -YELLOW = $0 -ORANGE = $0 -BLACK = $0 -WHITE = $0 - -COMMA=, -THX=
    $(THX $+) -TDX=$(TDX $+) -THEAD=$(TR $(THX $1, $+)) -TROW=$(TR $(TDX $1, $+)) -LIX=
  • $1
  • $(LIX $+) -LIST=$(UL $(LIX $1, $+)) +_=Fundamental macros that apply to all generated formats +ARGS = $0 +CONCAT = $1$(CONCAT $+) +COMMA = , +COMMENT = +DOLLAR = $ +LPAREN = ( +RPAREN = ) +TAIL = $+ +COLON = : +LF = $(LF) +$(LF) +_= diff --git a/memory-safe-d.dd b/memory-safe-d.dd deleted file mode 100644 index 818a8a3d95..0000000000 --- a/memory-safe-d.dd +++ /dev/null @@ -1,59 +0,0 @@ -Ddoc - -$(SPEC_S Memory Safety, - - $(P $(I Memory Safety) for a program is defined as it being - impossible for the program to corrupt memory. - Therefore, the Safe D consists only of programming language - features that are guaranteed to never result in memory - corruption. - ) - - $(P Safe D is enabled on a per-module basis by compiling with - the $(B -safe) compiler switch. - ) - -

    Proscribed Forms

    - -$(UL - $(LI $(DDLINK iasm, Inline Assembler, Inline assembler). - ) - - $(LI Casting away const or immutable attributes. - ) - - $(LI Casting away shared attributes. - ) - - $(LI Casting from one pointer type to another pointer type, - except for: - $(UL - $(LI casting to $(CODE void*) is allowed) - $(LI casting from a pointer to an arithmetic type to - a pointer to another arithmetic type of the same or - smaller size is allowed) - ) - ) - - $(LI Casting from a non-pointer type to a pointer type. - ) -) - - $(P A safe module can import and use the public interface of - a system module. - ) - -

    Limitations

    - - $(P Safe D does not imply that code is portable, uses only - sound programming practices, is free of byte order dependencies, - or other bugs. It is focussed only on eliminating memory corruption - possibilities. - ) - -) - -Macros: - TITLE=Memory-Safe-D-Spec - WIKI=SafeDSpec - CATEGORY_SPEC=$0 diff --git a/memory.dd b/memory.dd deleted file mode 100644 index 54586e33d6..0000000000 --- a/memory.dd +++ /dev/null @@ -1,553 +0,0 @@ -Ddoc - -$(D_S Memory Management, - - $(P Most non-trivial programs needs to allocate and free memory. - Memory management techniques become more and more important as - programs increase in complexity, size, and performance. - D offers many options for managing memory. - ) - - $(P The three primary methods for allocating memory in D are:) - - $(OL - $(LI Static data, allocated in the default data segment.) - $(LI Stack data, allocated on the CPU program stack.) - $(LI $(LINK2 garbage.html, Garbage collected data), - allocated dynamically on the - garbage collection heap.) - ) - - $(P The techniques for using them, as well - as some advanced alternatives are: - ) - - $(UL - $(LI $(LINK2 #copy-on-write, Strings (and Array) Copy-on-Write)) - $(LI Real Time) - $(LI Smooth Operation) - $(LI Free Lists) - $(LI Reference Counting) - $(LI Explicit Class Instance Allocation) - $(LI Mark/Release) - $(LI RAII (Resource Acquisition Is Initialization)) - $(LI Allocating Class Instances On The Stack) - $(LI Allocating Uninitialized Arrays On The Stack) - $(LI $(LINK2 #isr, Interrupt Service Routines)) - ) - -

    $(LNAME2 copy-on-write, Strings (and Array) Copy-on-Write)

    - - $(P Consider the case of passing an array to a function, possibly - modifying the contents of the array, and returning the modified - array. As the contents of an array are accessed through a reference, - a crucial issue is who owns the contents of the array? - For example, a function to convert an array of characters to - upper case: - ) - ------- -char[] toupper(char[] s) -{ - int i; - - for (i = 0; i < s.length; i++) - { - char c = s[i]; - if ('a' <= c && c <= 'z') - s[i] = cast(char)(c - ('a' - 'A')); - } - return s; -} ------- - - $(P Note that the caller's version of s[] is also modified. This may - be not at all what was intended, or worse, s[] may be a slice - into a read-only section of memory. - ) - - $(P If a copy of s[] was always made by toupper(), then that will - unnecessarily consume time and memory for strings that are already - all upper case. - ) - - $(P The solution is to implement copy-on-write, which means that a copy - is made only if the string needs to be modified. Some string - processing languages do do this as the default behavior, but there - is a huge cost to it. The string "abcdeF" will wind up being copied 5 - times by the function. To get the maximum efficiency using the protocol, - it'll have to be done explicitly in the code. Here's toupper() - rewritten to implement copy-on-write in an efficient manner: - ) - ------- -char[] toupper(char[] s) -{ - int changed; - int i; - - changed = 0; - for (i = 0; i < s.length; i++) - { - char c = s[i]; - if ('a' <= c && c <= 'z') - { - if (!changed) - { - char[] r = new char[s.length]; - r[] = s; - s = r; - changed = 1; - } - s[i] = cast(char)(c - ('a' - 'A')); - } - } - return s; -} - ------- - - $(P Copy-on-write is the protocol implemented by array processing - functions in the D Phobos runtime library. - ) - -

    Real Time

    - - $(P Real time programming means that a program must be able to - guarantee a maximum latency, or time to complete an operation. - With most memory allocation schemes, including malloc/free and - garbage collection, the latency is theoretically not bound. - The most reliable way to guarantee latency is to preallocate - all data that will be needed by the time critical portion. - If no calls to allocate memory are done, the GC will not run - and so will not cause the maximum latency to be exceeded. - ) - -

    Smooth Operation

    - - $(P Related to real time programming is the need for a program to - operate smoothly, without arbitrary pauses while the garbage - collector stops everything to run a collection. - An example of such a program would be an interactive shooter - type game. Having the game play pause erratically, while not - fatal to the program, can be annoying to the user. - ) - - $(P There are several techniques to eliminate or mitigate the effect:) - -$(UL - $(LI Preallocate all data needed before the part of the code - that needs to be smooth is run.) - - $(LI Manually run a GC collection cycle at points in program - execution where it is already paused. An example of such a place - would be where the program has just displayed a prompt for user - input and the user has not responded yet. - This reduces the odds that a collection cycle will be needed - during the smooth code.) - - $(LI Call std.gc.disable() before the smooth code is run, and - std.gc.enable() afterwards. This will cause the GC to favor allocating - more memory instead of running a collection pass.) -) - -

    Free Lists

    - - $(P Free lists are a great way to accelerate access to a frequently - allocated and discarded type. The idea is simple - instead of - deallocating an object when done with it, put it on a free list. - When allocating, pull one off the free list first. - ) ------- -class Foo -{ - static Foo freelist; // start of free list - - static Foo allocate() - { Foo f; - - if (freelist) - { f = freelist; - freelist = f.next; - } - else - f = new Foo(); - return f; - } - - static void deallocate(Foo f) - { - f.next = freelist; - freelist = f; - } - - Foo next; // for use by FooFreeList - ... -} - -void test() -{ - Foo f = Foo.allocate(); - ... - Foo.deallocate(f); -} ------- - - Such free list approaches can be very high performance. - - $(UL - $(LI If used by multiple threads, the allocate() and - deallocate() functions need to be synchronized.) - - $(LI The Foo constructor is not re-run by allocate() when - allocating from the free list, so the allocator may need - to reinitialize some of the members.) - - $(LI It is not necessary to practice RAII with this, since - if any objects are not passed to deallocate() when done, because - of a thrown exception, they'll eventually get picked up by - the GC anyway.) - ) - -

    Reference Counting

    - - $(P The idea behind reference counting is to include a count - field in the object. Increment it for each additional reference - to it, and decrement it whenever a reference to it ceases. - When the count hits 0, the object can be deleted. - ) - - $(P D doesn't provide any automated support for reference counting, - it will have to be done explicitly. - ) - - $(P Win32 COM programming - uses the members AddRef() and Release() - to maintain the reference counts. - ) - -

    Explicit Class Instance Allocation

    - - $(P D provides a means of creating custom allocators and deallocators - for class instances. Normally, these would be allocated on the - garbage collected heap, and deallocated when the collector decides - to run. For specialized purposes, this can be handled by - creating $(I NewDeclaration)s and $(I DeleteDeclaration)s. - For example, to allocate using the C runtime library's - $(TT malloc) and $(TT free): - ) - ------- -import std.c.stdlib; -import core.exception; -import core.memory : GC; - -class Foo -{ - new(size_t sz) - { - void* p; - - p = std.c.stdlib.malloc(sz); - - if (!p) - throw new OutOfMemoryError(); - - GC.addRange(p, sz); - return p; - } - - delete(void* p) - { - if (p) - { - GC.removeRange(p); - std.c.stdlib.free(p); - } - } -} ------- - - $(P The critical features of new() are:) - - $(UL - $(LI new() does not have a return type specified, - but it is defined to be void*. new() must return - a void*.) - - $(LI If new() cannot allocate memory, it must - not return null, but must throw an exception.) - - $(LI The pointer returned from new() must be to memory - aligned to the default alignment. This is 8 on win32 - systems.) - - $(LI The $(I size) parameter is needed in case the - allocator is called from a class derived from Foo and is - a larger size than Foo.) - - $(LI A null is not returned if storage cannot be allocated. - Instead, an exception is thrown. Which exception gets thrown - is up to the programmer, in this case, OutOfMemory() is.) - - $(LI When scanning memory for root pointers into the garbage - collected heap, the static data segment and the stack are - scanned automatically. The C heap is not. Therefore, if Foo - or any class derived from Foo using the allocator contains - any references to data allocated by the garbage collector, the - GC needs to be notified. This is done with the std.gc.addRange() - method.) - - $(LI No initialization of the memory is necessary, as code - is automatically inserted after the call to new() to set the - class instance members to their defaults and then the constructor - (if any) is run.) - ) - - The critical features of delete() are: - - $(UL - $(LI The destructor (if any) has already been called on the - argument p, so the data it points to should be assumed to - be garbage.) - - $(LI The pointer p may be null.) - - $(LI If the GC was notified with std.gc.addRange(), a corresponding - call to std.gc.removeRange() must happen in the deallocator.) - - $(LI If there is a delete(), there should be a corresponding new().) - ) - - $(P If memory is allocated using class specific allocators and deallocators, - careful coding practices must be followed to avoid memory leaks - and dangling references. In the presence of exceptions, it is - particularly important to practice RAII to prevent memory leaks. - ) - - $(P Custom allocators and deallocators can be done for structs - and unions, too.) - -

    Mark/Release

    - - $(P Mark/Release is equivalent to a stack method of allocating and - freeing memory. A $(SINGLEQUOTE stack) is created in memory. Objects are allocated - by simply moving a pointer down the stack. Various points are - $(SINGLEQUOTE marked), and then whole sections of memory are released - simply by resetting the stack pointer back to a marked point. - ) - ------- -import std.c.stdlib; -import core.exception; -import core.memory : GC; - -class Foo -{ - static void[] buffer; - static int bufindex; - static const int bufsize = 100; - - static this() - { - void* p; - p = malloc(bufsize); - - if (p is null) - throw new OutOfMemoryError; - - GC.addRange(p, bufsize); - buffer = p[0 .. bufsize]; - } - - static ~this() - { - if (buffer.length) - { - GC.removeRange(buffer.ptr); - free(buffer.ptr); - buffer = null; - } - } - - new(size_t sz) - { - void* p; - - p = &buffer[bufindex]; - bufindex += sz; - - if (bufindex > buffer.length) - throw new OutOfMemoryError; - - return p; - } - - delete(void* p) - { - assert(0); - } - - static int mark() - { - return bufindex; - } - - static void release(int i) - { - bufindex = i; - } -} - -void main() -{ - int m = Foo.mark(); - Foo f1 = new Foo; // allocate - Foo f2 = new Foo; // allocate - - Foo.release(m); // deallocate f1 and f2 -} ------- - - $(P The allocation of buffer[] itself is added as - a region to the GC, so there is no need for a separate - call inside Foo.new() to do it.) - -

    RAII (Resource Acquisition Is Initialization)

    - - $(P RAII techniques can be useful in avoiding memory leaks - when using explicit allocators and deallocators. - Adding the scope attribute - to such classes can help. - ) - -

    $(LNAME2 stackclass, Allocating Class Instances On The Stack)

    - - $(P Class instances are normally allocated on the garbage - collected heap. However, if they:) - - $(UL - $(LI are allocated as local symbols in a function and) - $(LI are allocated using $(B new) and) - $(LI use $(B new) with no arguments (constructor arguments are allowed) and) - $(LI have the $(B scope) storage class) - ) - - $(P then they are allocated on the stack. This is more efficient - than doing an allocate/free cycle on the instance. But be - careful that any reference to the object does not survive - the return of the function.) - ---- -class C { ... } - -scope c = new C(); // c is allocated on the stack -scope c2 = new C(5); // allocated on stack -scope c3 = new(5) C(); // allocated by a custom allocator ---- - - $(P If the class has a destructor, then that destructor is - guaranteed to be run when the class object goes out of scope, - even if the scope is exited via an exception.) - - -

    Allocating Uninitialized Arrays On The Stack

    - - $(P Arrays are always initialized in D. So, the following declaration:) - ------- -void foo() -{ byte[1024] buffer; - - fillBuffer(buffer); - ... -} ------- - - $(P will not be as fast as it might be since the buffer[] contents - are always initialized. If careful profiling of the program shows - that this initialization is a speed problem, it can be eliminated using - a $(I VoidInitializer): - ) - ------- -void foo() -{ byte[1024] buffer = $(B void); - - fillBuffer(buffer); - ... -} ------- - - $(P Uninitialized data on the stack comes with some caveats that need - to be carefully evaluated before using: - ) - - $(UL - - $(LI The uninitialized data that is on the stack will get scanned by the - garbage collector looking for any references to allocated memory. Since - the uninitialized data consists of old D stack frames, it is highly - likely that some of that garbage will look like references into the GC - heap, and the GC memory will not get freed. This problem really does - happen, and can be pretty frustrating to track down.) - - $(LI It's possible for a function to pass out of it a reference to data - on that function's stack frame. By then allocating a new stack frame - over the old data, and not initializing, the reference to the old data - may still appear to be valid. The program will then behave erratically. - Initializing all data on the stack frame will greatly increase the - probability of forcing that bug into the open in a repeatable manner.) - - $(LI Uninitialized data can be a source of bugs and trouble, even when - used correctly. One design goal of D is to improve reliability and - portability by eliminating sources of undefined behavior, and - uninitialized data is one huge source of undefined, unportable, erratic - and unpredictable behavior. Hence this idiom should only be used after - other opportunities for speed optimization are exhausted and if - benchmarking shows that it really does speed up the overall execution.) - - ) - -

    Interrupt Service Routines

    - - $(P When the garbage collector does a collection pass, it must - pause all running threads in order to scan their stacks and register - contents for references to GC allocated objects. - If an ISR (Interrupt Service Routine) thread is paused, - this can break the program. - ) - - $(P Therefore, the ISR thread should not be paused. - Threads created with the $(LINK2 phobos/core_thread.html, core.thread) - functions will be paused. But threads created with C's - $(TT _beginthread()) or equivalent won't be, the GC - won't know they exist. - ) - - $(P For this to work successfully:) - - $(UL - - $(LI The ISR thread cannot allocate any memory using the GC. - This means that the global $(TT new) cannot be used. - Nor can dynamic arrays be resized, nor can any elements be - added to associative arrays. Any use of the D runtime library - should be examined for any possibility of allocating GC memory - - or better yet, the ISR should not call any D runtime library - functions at all.) - - $(LI The ISR cannot hold the sole reference to any GC allocated - memory, otherwise the GC may free the memory while the ISR - is still using it. The solution is to have one of the paused - threads hold a reference to it too, or store a reference to - it in global data.) - - ) -) - -Macros: - TITLE=Memory Management - WIKI=Memory - CATEGORY_ARTICLES=$0 - diff --git a/menu.dd b/menu.dd new file mode 100644 index 0000000000..03fe1ccd10 --- /dev/null +++ b/menu.dd @@ -0,0 +1,6 @@ +Ddoc + +$(D_S Menu, $(NAVIGATION) $(SEARCH_BOX)) + +Macros: + TITLE=Menu diff --git a/migrate-to-shared.dd b/migrate-to-shared.dd deleted file mode 100644 index ae5a4dfdd4..0000000000 --- a/migrate-to-shared.dd +++ /dev/null @@ -1,232 +0,0 @@ -Ddoc - -$(D_S $(TITLE), - - $(P Starting with $(LINK2 changelog.html#new2_030, dmd version 2.030), - the default storage class - for statics and globals will be - $(LINK2 glossary.html#tls, thread local storage (TLS)), rather - than the classic global data segment. - While most D code should just compile and run successfully without - change, there can be some issues. - ) - -$(OL - $(LI $(LINK2 #performance, Performance of TLS variables).) - $(LI $(LINK2 #vtls, Identifying TLS variables).) - $(LI $(LINK2 #immutable, Switch to Immutable).) - $(LI $(LINK2 #shared, Marking as shared).) - $(LI $(LINK2 #__gshared, Cowboying with __gshared).) - $(LI $(LINK2 #compile-errors, Compile errors).) - $(LI $(LINK2 #link-errors, Link errors).) -) - -$(H3 $(LNAME2 performance, Performance of TLS variables)) - - $(P Yes, reading or writing TLS variables will be slower - than for classic global variables. It'll be about 3 - instructions rather than one. - But on Linux, at least, TLS will be slightly faster - than accessing classic globals using PIC (position - independent code) compiler code generation settings. - So it's hard to see that this would be an unacceptable - problem. But let's presume it is. What can we do about it? - ) - - $(OL - $(LI Minimize use of global variables. Reducing the use - of globals can improve the modularization and maintainability - of the code anyway, so this is a worthy goal.) - $(LI Make them immutable. Immutable data doesn't have - synchronization problems, so the compiler doesn't place it - in TLS.) - $(LI Cache a reference to the global. Making a local cache - of it, and then accessing the cached value rather than the - original, can speed things up especially if the cached value - gets enregistered by the compiler.) - $(LI Cowboy it with $(B __gshared).) - ) - -$(H3 $(LNAME2 vtls, Identifying TLS variables)) - - $(P The first step is to find all the global variables, - so they can be reviewed for disposition. - ) - - $(P Given the complexity of source code, it isn't always - easy to identify the global variables. Since it (used to be) - implicit, there's no way to grep for them. It's hard - to be sure you've found them all. - ) - - $(P A new dmd compiler switch was added, $(B -vtls). - Compiling with it on will print a list of all the global - variables that are now defaulting to thread local storage. - ) - ---- -int x; - -void main() -{ - static int y; -} ---- - -$(CONSOLE -dmd test $(B -vtls) -test.d(2): x is thread local -test.d(6): y is thread local -) - -$(H3 $(LNAME2 immutable, Switch to Immutable)) - - $(P Immutable data, once initialized, never changes. - This means that there are no synchronization issues - with multithreading, and so no need to put immutable data - into TLS. The compiler will put immutable data into - classic global storage, not TLS. - ) - - $(P A good chunk of global data falls into this category. - Just mark it as $(B immutable) and it's done. - ) - ---- -int[3] table = [6, 123, 0x87]; ---- - $(P becomes:) ---- -immutable int[3] table = [6, 123, 0x87]; ---- - - $(P Immutability is also nice because it opens the door - for further compiler optimizations. - ) - -$(H3 $(LNAME2 shared, Marking As Shared)) - - $(P Global data that is meant to be shared among multiple - threads should be marked with the $(B shared) keyword: - ) - ---- -shared int flag; ---- - - $(P Not only does this cause $(CODE flag) to be put into - classic global storage, it is also typed as being shared: - ) - ---- -int* p = &flags; // error, flags is shared -shared(int)* q = &flags; // ok ---- - - $(P The $(CODE shared) type attribute is transitive (like - $(CODE const) and $(CODE immutable)) are. This enables - static checking and sharing correctness. - ) - -$(H3 $(LNAME2 __gshared, Cowboying With __gshared)) - - $(P Sometimes, none of the above solutions will be - acceptable: - ) - - $(OL - $(LI interfacing with C code that uses classic globals) - $(LI just get it working, and go back and fix it later) - $(LI the app is single threaded only, so no sharing issues) - $(LI you need every erg of performance) - $(LI you want to handle all the synchronization issues - yourself) - ) - - $(P As D is a systems language, of course there's a way to - do this. Use the storage class $(B __gshared): - ) - ---- -__gshared int x; - -void main() -{ - __gshared int y; -} ---- - - $(P $(B __gshared) stores the variable in the classic global - data segment. - ) - - $(P Naturally, $(B __gshared) is not allowed in safe mode. - ) - - $(P Using $(B __gshared) makes such code easily searchable - when doing QA code reviews or when going back later to - fix any workarounds. - ) - -$(H3 $(LNAME2 compile-errors, Compile Errors)) - - $(P The most common compiler error related to TLS will be: - ) - ---- -int x; -int* p = &x; ---- -$(CONSOLE -test.d(2): Error: non-constant expression & x -) - - $(P While this works with classic global variables, it - won't work with TLS variables. The reason is because - TLS variables don't have a location in memory known to - either the linker or the loader. It's a runtime computed - value.) - - $(P The solution is to initialize such things in - a static constructor.) - -$(H3 $(LNAME2 link-errors, Link Errors)) - - $(P Sometimes you may encounter strange error messages from the linker - about the global variables. - These are nearly always caused by one module putting the variable - in TLS, and another putting that same variable in classic global - storage. - This can happen when linking code with libraries that were built - with earlier versions of dmd. Check that libphobos2.a was properly - replaced with the latest. - It can also happen when interfacing with C. C globals default - to being classic global, although C does support TLS declarations. - Make sure the corresponding D declarations match the C ones in - terms of TLS or classic global. - ) - -$(CCODE -int x; -extern int y; -__thread int z; -) - ---- -extern (C) -{ - extern shared int x; - shared int y; - extern int z; -} ---- - -) - -Macros: - H2=

    $0

    - H3=

    $0

    - TITLE=Migrating to Shared - WIKI=Migrating To Shared - CATEGORY_ARTICLES=$0 - diff --git a/mixin.dd b/mixin.dd deleted file mode 100644 index 3c12e82491..0000000000 --- a/mixin.dd +++ /dev/null @@ -1,99 +0,0 @@ -Ddoc - -$(D_S Mixins, - - $(P Mixins (not to be confused with - $(LINK2 template-mixin.html, template mixins)) - enable string constants to be compiled as regular D code - and inserted into the program. - Combining this with compile time manipulation of strings - enables the creation of domain-specific languages. - ) - - $(P For example, here we can create a template that generates - a struct with the named members: - ) - ---- -template GenStruct(string Name, string M1) -{ - const char[] GenStruct = "struct " ~ Name ~ "{ int " ~ M1 ~ "; }"; -} - -mixin(GenStruct!("Foo", "bar")); ---- - $(P which generates:) ---- -struct Foo { int bar; } ---- - - - $(P Superficially, since D mixins can manipulate text and compile - the result, it has some similar properties to the C preprocessor. - But there are major, fundamental differences: - ) - -$(UL - - $(LI The C preprocessing step occurs $(B before) lexical analysis. - This makes it impossible to lex or parse C without access to - all of the context, including all #include'd files, paths and all - relevant compiler switches. - - Mixins occur during semantic analysis, and do not affect - the lexing or parsing process. - Lexing and parsing can still occur without semantic analysis. - ) - - - $(LI The C preprocessor can be used to create what appears to - be different syntax: - -$(CCODE -#define BEGIN { -#define END } - -BEGIN - int x = 3; - foo(x); -END -) - - This monkey business is impossible with mixins. - Mixed in text must form complete declarations, - statements, or expressions. - ) - - $(LI C macros will affect everything following that has - the same name, even if they are in nested scopes. - C macros cut across all scopes. - This problem is called being not "coding hygenic". - - Mixins follow the usual scoping rules, and is - hygenic. - ) - - $(LI C preprocessing expressions follow a different syntax - and have different semantic rules than the C language. - The C preprocessor is technically a different language. - - Mixins are in the same language. - ) - - $(LI C const declarations and C++ templates are invisible - to C preprocessing. - - Mixins can be manipulated using templates and const - declarations. - ) -) - -) - -Macros: - TITLE=Mixins - WIKI=Mixins - CATEGORY_ARTICLES=$0 - - - diff --git a/module.dd b/module.dd deleted file mode 100644 index 820712efe1..0000000000 --- a/module.dd +++ /dev/null @@ -1,510 +0,0 @@ -Ddoc - -$(SPEC_S Modules, - -$(GRAMMAR -$(GNAME Module): - $(GLINK ModuleDeclaration) $(GLINK DeclDefs) - $(GLINK DeclDefs) - -$(GNAME DeclDefs): - $(GLINK DeclDef) - $(GLINK DeclDef) $(I DeclDefs) - -$(GNAME DeclDef): - $(GLINK2 attribute, AttributeSpecifier) - $(GLINK ImportDeclaration) - $(GLINK2 enum, EnumDeclaration) - $(GLINK2 class, ClassDeclaration) - $(GLINK2 interface, InterfaceDeclaration) - $(GLINK2 struct, AggregateDeclaration) - $(GLINK2 declaration, Declaration) - $(GLINK2 class, Constructor) - $(GLINK2 class, Destructor) - $(GLINK2 unittest, UnitTest) - $(GLINK2 class, StaticConstructor) - $(GLINK2 class, StaticDestructor) -$(V2 $(GLINK2 class, SharedStaticConstructor) - $(GLINK2 class, SharedStaticDestructor) -) $(GLINK2 version, ConditionalDeclaration) - $(GLINK2 version, DebugSpecification) - $(GLINK2 version, VersionSpecification) - $(GLINK2 version, StaticAssert) - $(GLINK2 template, TemplateDeclaration) - $(GLINK2 template-mixin, TemplateMixinDeclaration) - $(GLINK2 template-mixin, TemplateMixin) - $(GLINK MixinDeclaration) - $(B ;) -) - - - $(P Modules have a one-to-one correspondence with source files. - The module name is the file name with the path and extension - stripped off. - ) - - $(P Modules automatically provide a namespace scope for their contents. - Modules superficially resemble classes, but differ in that: - ) - - $(UL - $(LI There's only one instance of each module, and it is - statically allocated.) - - $(LI There is no virtual table.) - - $(LI Modules do not inherit, they have no super modules, etc.) - - $(LI Only one module per file.) - - $(LI Module symbols can be imported.) - - $(LI Modules are always compiled at global scope, and are unaffected - by surrounding attributes or other modifiers.) - ) - - $(P Modules can be grouped together in hierarchies called $(I packages). - ) - - $(P Modules offer several guarantees:) - - $(UL - - $(LI The order in which modules are imported does not affect the - semantics.) - - $(LI The semantics of a module are not affected by what imports - it.) - - $(LI If a module C imports modules A and B, any modifications to B - will not silently change code in C that is dependent on A.) - - ) - -

    Module Declaration

    - - $(P The $(I ModuleDeclaration) sets the name of the module and what - package it belongs to. If absent, the module name is taken to be the - same name (stripped of path and extension) of the source file name. - ) - -$(GRAMMAR -$(GNAME ModuleDeclaration): - $(B module) $(I ModuleFullyQualifiedName) $(B ;) - -$(GNAME ModuleFullyQualifiedName): - $(I ModuleName) - $(I Packages) $(B .) $(I ModuleName) - -$(GNAME ModuleName): - $(I Identifier) - -$(GNAME Packages): - $(I PackageName) - $(I Packages) $(B .) $(I PackageName) - -$(GNAME PackageName): - $(I Identifier) -) - - $(P The $(I Identifiers) preceding the rightmost are the $(I Packages) - that the module is in. The packages correspond to directory names in - the source file path. - Package names cannot be keywords, hence the corresponding - directory names cannot be keywords, either. - ) - - $(P If present, the $(I ModuleDeclaration) appears syntactically first - in the source file, and there can be only one per source file. - ) - - $(P Example:) - ---------- -module c.stdio; // this is module $(B stdio) in the $(B c) package ---------- - - $(P By convention, package and module names are all lower case. This is - because those names have a one-to-one correspondence with the operating - system's directory and file names, and many file systems - are not case sensitive. All lower case package and module names will - minimize problems moving projects between dissimilar file systems. - ) - -

    Import Declaration

    - - $(P - Symbols from one module are made available in another module - by using the $(I ImportDeclaration): - ) - -$(GRAMMAR -$(GNAME ImportDeclaration): - $(B import) $(I ImportList) $(B ;) - $(B static import) $(I ImportList) $(B ;) - -$(GNAME ImportList): - $(I Import) - $(I ImportBindings) - $(I Import) $(B ,) $(I ImportList) - -$(GNAME Import): - $(I ModuleFullyQualifiedName) - $(I ModuleAliasIdentifier) $(B =) $(I ModuleFullyQualifiedName) - -$(GNAME ImportBindings): - $(I Import) $(B :) $(I ImportBindList) - -$(GNAME ImportBindList): - $(I ImportBind) - $(I ImportBind) $(B ,) $(I ImportBindList) - -$(GNAME ImportBind): - $(I Identifier) - $(I Identifier) = $(I Identifier) - -$(GNAME ModuleAliasIdentifier): - $(I Identifier) -) - - $(P There are several forms of the $(I ImportDeclaration), - from generalized to fine-grained importing.) - - $(P The order in which $(I ImportDeclaration)s occur has no - significance.) - - $(P $(I ModuleFullyQualifiedName)s in the $(I ImportDeclaration) must be - fully qualified - with whatever packages they are in. They are not considered to - be relative to the module that imports them.) - -

    Basic Imports

    - - $(P The simplest form of importing is to just list the - modules being imported:) - ---------- -import std.stdio; // import module $(B stdio) from the $(B std) package -import foo, bar; // import modules $(B foo) and $(B bar) - -void main() -{ - writefln("hello!\n"); // calls std.stdio.writefln -} ---------- - - $(P How basic imports work is that first a name is searched for in the - current namespace. If it is not found, then it is looked for in the - imports. - If it is found uniquely among the imports, then that is used. If it is - in more than one import, an error occurs. - ) - ---- -module A; -void foo(); -void bar(); ---- - ---- -module B; -void foo(); -void bar(); ---- - ---- -module C; -import A; -void foo(); -void test() -{ foo(); // C.foo() is called, it is found before imports are searched - bar(); // A.bar() is called, since imports are searched -} ---- - ---- -module D; -import A; -import B; -void test() -{ foo(); // error, A.foo() or B.foo() ? - A.foo(); // ok, call A.foo() - B.foo(); // ok, call B.foo() -} ---- - ---- -module E; -import A; -import B; -alias B.foo foo; -void test() -{ foo(); // call B.foo() - A.foo(); // call A.foo() - B.foo(); // call B.foo() -} ---- - -

    Public Imports

    - - $(P By default, imports are $(I private). This means that - if module A imports module B, and module B imports module - C, then C's names are not searched for. An import can - be specifically declared $(I public), when it will be - treated as if any imports of the module with the $(I ImportDeclaration) - also import the public imported modules. - ) - ---- -module A; -void foo() { } ---- - ---- -module B; -void bar() { } ---- - ---- -module C; -import A; -public import B; -... -foo(); // call A.foo() -bar(); // calls B.bar() ---- - ---- -module D; -import C; -... -foo(); // error, foo() is undefined -bar(); // ok, calls B.bar() ---- - -

    Static Imports

    - - $(P Basic imports work well for programs with relatively few modules - and imports. If there are a lot of imports, name collisions - can start occurring between the names in the various imported modules. - One way to stop this is by using static imports. - A static import requires one to use a fully qualified name - to reference the module's names: - ) - ---- -static import std.stdio; - -void main() -{ - writefln("hello!"); // error, writefln is undefined - std.stdio.writefln("hello!"); // ok, writefln is fully qualified -} ---- - - -

    Renamed Imports

    - - $(P A local name for an import can be given, through which - all references to the module's symbols must be qualified - with:) - ---- -import io = std.stdio; - -void main() -{ - io.writefln("hello!"); // ok, calls std.stdio.writefln - std.stdio.writefln("hello!"); // error, std is undefined - writefln("hello!"); // error, writefln is undefined -} ---- - - $(P Renamed imports are handy when dealing with - very long import names.) - -

    Selective Imports

    - - $(P Specific symbols can be exclusively imported from - a module and bound into the current namespace:) - ---- -import std.stdio : writefln, foo = writef; - -void main() -{ - std.stdio.writefln("hello!"); // error, std is undefined - writefln("hello!"); // ok, writefln bound into current namespace - writef("world"); // error, writef is undefined - foo("world"); // ok, calls std.stdio.writef() - fwritefln(stdout, "abc"); // error, fwritefln undefined -} ---- - - $(P $(B static) cannot be used with selective imports.) - -

    Renamed and Selective Imports

    - - $(P When renaming and selective importing are combined:) - ------------- -import io = std.stdio : foo = writefln; - -void main() -{ - writefln("bar"); // error, writefln is undefined - std.stdio.foo("bar"); // error, foo is bound into current namespace - std.stdio.writefln("bar"); // error, std is undefined - foo("bar"); // ok, foo is bound into current namespace, - // FQN not required - io.writefln("bar"); // ok, io=std.stdio bound the name io in - // the current namespace to refer to the entire module - io.foo("bar"); // error, foo is bound into current namespace, - // foo is not a member of io --------------- - -

    Scoped Imports

    - - $(P Import declarations may be used at any scope. For example:) - --------------- -void main() { - import std.stdio; - writeln("bar"); -} --------------- - - $(P The imports are looked up to satisfy any unresolved symbols at that scope. - Imported symbols may hide symbols from outer scopes.) - - - $(P In function scopes, imported symbols only become visible after the - import declaration - lexically appears in the function body. In other words, imported symbols - at function scope cannot be forward referenced. - ) - --------------- -void main() { - void writeln(string) {} - void foo() { - writeln("bar"); // calls main.writeln - import std.stdio; - writeln("bar"); // calls std.stdio.writeln - void writeln(string) {} - writeln("bar"); // calls main.foo.writeln - } - writeln("bar"); // calls main.writeln - std.stdio.writeln("bar"); // error, std is undefined -} --------------- - -

    Module Scope Operator

    - - Sometimes, it's necessary to override the usual lexical scoping rules - to access a name hidden by a local name. This is done with the - global scope operator, which is a leading $(SINGLEQUOTE .): - ---------- -int x; - -int foo(int x) -{ - if (y) - return x; // returns foo.x, not global x - else - return .x; // returns global x -} ---------- - - The leading $(SINGLEQUOTE .) means look up the name at the module scope level. - -

    Static Construction and Destruction

    - - $(P Static constructors are code that gets executed to initialize - a module or a class before the main() function gets called. - Static destructors are code that gets executed after the main() - function returns, and are normally used for releasing - system resources.) - - $(P There can be multiple static constructors and static destructors - within one module. The static constructors are run in lexical order, - the static destructors are run in reverse lexical order.) - -$(V2 - $(P Static constructors and static destructors run on thread local - data, and are run whenever threads are created or destroyed.) - - $(P Shared static constructors and shared static destructors are run - on global shared data, and constructors are run once on program startup - and destructors are run once on program termination. - ) -) - -

    Order of Static Construction

    - -$(V2 - $(P Shared static constructors on all modules are run before any static - constructors. - ) -) - - $(P The order of static initialization is implicitly determined by - the $(I import) declarations in each module. Each module is - assumed to depend on any imported modules being statically - constructed first. - Other than following that rule, there is no imposed order - on executing the module static constructors. - ) - - $(P Cycles (circular dependencies) in the import declarations are - allowed as long as not both of the modules contain static constructors - or static destructors. Violation of this rule will result - in a runtime exception. - ) - -

    Order of Static Construction within a Module

    - - Within a module, the static construction occurs in the lexical - order in which they appear. - -

    Order of Static Destruction

    - - $(P It is defined to be exactly the reverse order that static - construction was performed in. Static destructors for individual - modules will only be run if the corresponding static constructor - successfully completed. - ) -$(V2 - $(P Shared static destructors are executed after static destructors. - ) -) - - -

    Order of Unit tests

    - - Unit tests are run in the lexical order in which they appear - within a module. - -

    $(LNAME2 MixinDeclaration, Mixin Declaration)

    - -$(GRAMMAR -$(GNAME MixinDeclaration): - $(B mixin) $(B $(LPAREN)) $(ASSIGNEXPRESSION) $(B $(RPAREN)) $(B ;) -) - - $(P The $(ASSIGNEXPRESSION) - must evaluate at compile time - to a constant string. - The text contents of the string must be compilable as a valid - $(GLINK DeclDefs), and is compiled as such. - ) - -) - -Macros: - TITLE=Modules - WIKI=Module - CATEGORY_SPEC=$0 - FOO= - diff --git a/nodatetime.ddoc b/nodatetime.ddoc new file mode 100644 index 0000000000..93dd35c662 --- /dev/null +++ b/nodatetime.ddoc @@ -0,0 +1,2 @@ +GEN_DATETIME=(no date time) +_= diff --git a/operatoroverloading.dd b/operatoroverloading.dd deleted file mode 100644 index be26ab0e80..0000000000 --- a/operatoroverloading.dd +++ /dev/null @@ -1,1263 +0,0 @@ -Ddoc - -$(SPEC_S Operator Overloading, - -$(V2 - $(P Operator overloading is accomplished by rewriting operators whose - operands are class or struct objects into calls to specially named - member functions. No additional syntax is used. - ) - - $(UL - $(LI $(LINK2 #Unary, Unary Operator Overloading)) - $(LI $(LINK2 #Cast, Cast Operator Overloading)) - $(LI $(LINK2 #Binary, Binary Operator Overloading)) - $(LI $(LINK2 #equals, Overloading == and !=)) - $(LI $(LINK2 #compare, Overloading < <=, > and >=)) - $(LI $(LINK2 #FunctionCall, Function Call Operator Overloading)) - $(LI $(LINK2 #Assignment, Assignment Operator Overloading)) - $(LI $(LINK2 #OpAssign, Op Assignment Operator Overloading)) - $(LI $(LINK2 #Array, Index Operator Overloading)) - $(LI $(LINK2 #Slice, Slice Operator Overloading)) - $(LI $(LINK2 #Dispatch, Forwarding)) - ) - -

    Unary Operator Overloading

    - - $(TABLE2 Overloadable Unary Operators, - - $(TR $(TH$(I op)) $(TH$(I rewrite)) ) - - $(TR - $(TD -$(I e)) - $(TD $(CODE $(I e).opUnary!("-")())) - ) - - $(TR - $(TD +$(I e)) - $(TD $(CODE $(I e).opUnary!("+")())) - ) - - $(TR - $(TD ~$(I e)) - $(TD $(CODE $(I e).opUnary!("~")())) - ) - - $(TR - $(TD *$(I e)) - $(TD $(CODE $(I e).opUnary!("*")())) - ) - - $(TR - $(TD ++$(I e)) - $(TD $(CODE $(I e).opUnary!("++")())) - ) - - $(TR - $(TD --$(I e)) - $(TD $(CODE $(I e).opUnary!("--")())) - ) - - ) - - $(P For example, in order to overload the - (negation) operator for struct S, and - no other operator:) - ---- -struct S { - int m; - - int opUnary(string s)() if (s == "-") { - return -m; - } -} - -int foo(S s) { - return -s; -} ---- - -

    Postincrement $(I e)++ and Postdecrement $(I e)-- Operators

    - - $(P These are not directly overloadable, but instead are rewritten - in terms of the ++$(I e) and --$(I e) prefix operators: - ) - - $(TABLE2 Postfix Operator Rewrites, - - $(TR $(TH$(I op)) $(TH$(I rewrite)) ) - - $(TR - $(TD $(I e)--) - $(TD $(CODE (auto t = e, --$(I e), t))) - ) - - $(TR - $(TD $(I e)++) - $(TD $(CODE (auto t = e, ++$(I e), t))) - ) - ) - -

    Overloading Index Unary Operators

    - - $(TABLE2 Overloadable Index Unary Operators, - - $(TR $(TH$(I op)) $(TH$(I rewrite)) ) - - $(TR - $(TD $(CODE -$(I a)[$(ARGUMENTS)])) - $(TD $(CODE $(I a).opIndexUnary!("-")($(ARGUMENTS)))) - ) - - $(TR - $(TD $(CODE +$(I a)[$(ARGUMENTS)])) - $(TD $(CODE $(I a).opIndexUnary!("+")($(ARGUMENTS)))) - ) - - $(TR - $(TD $(CODE ~$(I a)[$(ARGUMENTS)])) - $(TD $(CODE $(I a).opIndexUnary!("~")($(ARGUMENTS)))) - ) - - $(TR - $(TD $(CODE *$(I a)[$(ARGUMENTS)])) - $(TD $(CODE $(I a).opIndexUnary!("*")($(ARGUMENTS)))) - ) - - $(TR - $(TD $(CODE ++$(I a)[$(ARGUMENTS)])) - $(TD $(CODE $(I a).opIndexUnary!("++")($(ARGUMENTS)))) - ) - - $(TR - $(TD $(CODE --$(I a)[$(ARGUMENTS)])) - $(TD $(CODE $(I a).opIndexUnary!("--")($(ARGUMENTS)))) - ) - - ) - -

    Overloading Slice Unary Operators

    - - $(TABLE2 Overloadable Slice Unary Operators, - - $(TR $(TH$(I op)) $(TH$(I rewrite)) ) - - $(TR - $(TD $(CODE -$(I a)[$(SLICE)])) - $(TD $(CODE $(I a).opSliceUnary!("-")($(SLICE2)))) - ) - - $(TR - $(TD $(CODE +$(I a)[$(SLICE)])) - $(TD $(CODE $(I a).opSliceUnary!("+")($(SLICE2)))) - ) - - $(TR - $(TD $(CODE ~$(I a)[$(SLICE)])) - $(TD $(CODE $(I a).opSliceUnary!("~")($(SLICE2)))) - ) - - $(TR - $(TD $(CODE *$(I a)[$(SLICE)])) - $(TD $(CODE $(I a).opSliceUnary!("*")($(SLICE2)))) - ) - - $(TR - $(TD $(CODE ++$(I a)[$(SLICE)])) - $(TD $(CODE $(I a).opSliceUnary!("++")($(SLICE2)))) - ) - - $(TR - $(TD $(CODE --$(I a)[$(SLICE)])) - $(TD $(CODE $(I a).opSliceUnary!("--")($(SLICE2)))) - ) - - $(TR - $(TD $(CODE -$(I a)[ ])) - $(TD $(CODE $(I a).opSliceUnary!("-")())) - ) - - $(TR - $(TD $(CODE +$(I a)[ ])) - $(TD $(CODE $(I a).opSliceUnary!("+")())) - ) - - $(TR - $(TD $(CODE ~$(I a)[ ])) - $(TD $(CODE $(I a).opSliceUnary!("~")())) - ) - - $(TR - $(TD $(CODE *$(I a)[ ])) - $(TD $(CODE $(I a).opSliceUnary!("*")())) - ) - - $(TR - $(TD $(CODE ++$(I a)[ ])) - $(TD $(CODE $(I a).opSliceUnary!("++")())) - ) - - $(TR - $(TD $(CODE --$(I a)[ ])) - $(TD $(CODE $(I a).opSliceUnary!("--")())) - ) - ) - -

    Cast Operator Overloading

    - - $(TABLE2 Cast Operators, - - $(TR $(TH$(I op)) $(TH$(I rewrite)) ) - - $(TR - $(TD cast($(I type))$(I e)) - $(TD $(CODE $(I e).opCast!($(I type))())) - ) - - ) - - -

    Boolean Operations

    - - $(P Notably absent from the list of overloaded unary operators is the ! - logical negation operator. More obscurely absent is a unary operator - to convert to a bool result. - Instead, these are covered by a rewrite to: - ) ---- -opCast!(bool)(e) ---- - - $(P So,) - ---- -if (e) => if (e.opCast!(bool)) -if (!e) => if (!e.opCast!(bool)) ---- - - $(P etc., whenever a bool result is expected. This only happens, however, for - instances of structs. Class references are converted to bool by checking to - see if the class reference is null or not. - ) - -

    Binary Operator Overloading

    - - $(P The following binary operators are overloadable:) - - $(TABLE2 Overloadable Binary Operators, - - $(TR $(TD +) $(TD -) $(TD *) $(TD /) $(TD %) $(TD ^^) $(TD &) ) - $(TR $(TD |) $(TD ^) $(TD <<) $(TD >>) $(TD >>>) $(TD ~) $(TD in) ) - - ) - - $(P The expression:) ---- -a $(I op) b ---- - $(P is rewritten as both:) ---- -a.opBinary!("$(I op)")(b) -b.opBinaryRight!("$(I op)")(a) ---- - - $(P and the one with the $(SINGLEQUOTE better) match is selected. - It is an error for both to equally match. - ) - - $(P Operator overloading for a number of operators can be done at the same time. - For example, if only the + or - operators are supported:) - ---- -T opBinary(string op)(T rhs) { - static if (op == "+") return data + rhs.data; - else static if (op == "-") return data - rhs.data; - else static assert(0, "Operator "~op~" not implemented"); -} ---- - - $(P To do them all en masse:) - ---- -T opBinary(string op)(T rhs) { - return mixin("data "~op~" rhs.data"); -} ---- - - -

    Overloading == and !=

    - - $(P Expressions of the form $(CODE a != b) are rewritten as $(CODE !(a == b)).) - - $(P Given $(CODE a == b) :) - -$(OL - $(LI If a and b are both class objects, then the expression is rewritten as: ---- -.object.opEquals(a, b) ---- - $(P and that function is implemented as:) ---- -bool opEquals(Object a, Object b) { - if (a is b) return true; - if (a is null || b is null) return false; - if (typeid(a) == typeid(b)) return a.opEquals(b); - return a.opEquals(b) && b.opEquals(a); -} ---- - ) - $(LI Otherwise the expressions $(CODE a.opEquals(b)) and - $(CODE b.opEquals(a)) are tried. If both resolve to the same opEquals - function, then the expression is rewritten to be $(CODE a.opEquals(b)). - ) - $(LI If one is a better match then the other, or one compiles and the other - does not, the one is selected.) - $(LI Otherwise, an error results.) -) - - $(P If overridding Object.opEquals() for classes, the class member function - signature should look like:) ---- -class C { - override bool opEquals(Object o) { ... } -} ---- - - $(P If structs declare an opEquals member function, it should follow the following - form:) ---- -struct S { - int opEquals(ref const S s) { ... } -} ---- - -

    Overloading < <=, > and >=

    - - $(P Comparison operations are rewritten as follows:) - - $(TABLE2 Overloadable Unary Operators, - $(TR $(TH comparison) $(TH rewrite 1) $(TH rewrite 2) ) - - $(TR $(TD $(CODE a < b)) $(TD $(CODE a.opCmp(b) < 0)) $(TD $(CODE b.opCmp(a) > 0))) - $(TR $(TD $(CODE a <= b)) $(TD $(CODE a.opCmp(b) <= 0)) $(TD $(CODE b.opCmp(a) >= 0))) - $(TR $(TD $(CODE a > b)) $(TD $(CODE a.opCmp(b) > 0)) $(TD $(CODE b.opCmp(a) < 0))) - $(TR $(TD $(CODE a >= b)) $(TD $(CODE a.opCmp(b) >= 0)) $(TD $(CODE b.opCmp(a) <= 0))) - ) - - $(P Both rewrites are tried. If only one compiles, that one is taken. - If they both resolve to the same function, the first - rewrite is done. If they resolve to different functions, the best matching one - is used. If they both match the same, but are different functions, an ambiguity - error results. - ) - - $(P If overriding Object.opCmp() for classes, the class member function - signature should look like:) ---- -class C { - override int opCmp(Object o) { ... } -} ---- - - $(P If structs declare an opCmp member function, it should follow the following - form:) ---- -struct S { - int opCmp(ref const S s) const { ... } -} ---- - -

    Function Call Operator Overloading $(I f)()

    - - $(P The function call operator, (), can be overloaded by - declaring a function named $(B opCall): - ) - -------- -struct F { - int $(B opCall)(); - int $(B opCall)(int x, int y, int z); -} - -void test() { - F f; - int i; - - i = f$(B ()); // same as i = f.opCall(); - i = f$(B (3,4,5)); // same as i = f.opCall(3,4,5); -} -------- - - $(P In this way a struct or class object can behave as if it - were a function. - ) - -

    Assignment Operator Overloading

    - - $(P The assignment operator $(CODE =) can be overloaded if the - lvalue is a struct aggregate, and $(CODE opAssign) - is a member function of that aggregate.) - - $(P The assignment operator cannot be overloaded for rvalues - that can be implicitly cast to the lvalue type. - Furthermore, the following parameter signatures for $(CODE opAssign) - are not allowed:) - ---- -opAssign(...) -opAssign(T) -opAssign(T, ...) -opAssign(T ...) -opAssign(T, U = defaultValue, etc.) ---- - - $(P where $(I T) is the same type as the aggregate type $(I A), - is implicitly - convertible to $(I A), or if $(I A) is a struct and $(I T) - is a pointer to a type that is - implicitly convertible to $(I A). - ) - -

    Index Assignment Operator Overloading

    - - $(P If the left hand side of an assignment is an index operation - on a struct or class instance, - it can be overloaded by providing an opIndexAssign member function. - Expressions of the form $(CODE a[$(ARGUMENTS)] = c) are rewritten - as $(CODE a.opIndexAssign(c, $(ARGUMENTS))). - ) - -------- -struct A { - int $(B opIndexAssign)(int value, size_t i1, size_t i2); -} - -void test() { - A a; - - a$(B [)i,3$(B ]) = 7; // same as a.opIndexAssign(7,i,3); -} -------- - -

    Slice Assignment Operator Overloading

    - - $(P If the left hand side of an assignment is a slice operation - on a struct or class instance, - it can be overloaded by providing an opSliceAssign member function. - Expressions of the form $(CODE a[$(SLICE)] = c) are rewritten - as $(CODE a.opSliceAssign(c, $(SLICE2))), and - $(CODE a[] = c) as $(CODE a.opSliceAssign(c)). - ) - -------- -struct A { - int $(B opSliceAssign)(int v); // overloads a[] = v - int $(B opSliceAssign)(int v, size_t x, size_t y); // overloads a[i .. j] = v -} - -void test() { - A a; - int v; - - a$(B []) = v; // same as a.opSliceAssign(v); - a$(B [)3..4$(B ]) = v; // same as a.opSliceAssign(v,3,4); -} -------- - -

    Op Assignment Operator Overloading

    - - $(P The following op assignment operators are overloadable:) - - $(TABLE2 Overloadable Op Assignment Operators, - - $(TR $(TD +=) $(TD -=) $(TD *=) $(TD /=) $(TD %=) $(TD ^^=) $(TD &=) ) - $(TR $(TD |=) $(TD ^=) $(TD <<=) $(TD >>=) $(TD >>>=) $(TD ~=) $(TD  ) ) - - ) - - $(P The expression:) ---- -a $(I op)= b ---- - - $(P is rewritten as:) - ---- -a.opOpAssign!("$(I op)")(b) ---- - -

    Index Op Assignment Operator Overloading

    - - $(P If the left hand side of an $(I op)= is an index expression on - a struct or class instance and opIndexOpAssign is a member:) - ---- -a[$(ARGUMENTS)] $(I op)= c ---- - - $(P it is rewritten as:) - ---- -a.opIndexOpAssign!("$(I op)")(c, $(ARGUMENTS)) ---- - -

    Slice Op Assignment Operator Overloading

    - - $(P If the left hand side of an $(I op)= is a slice expression on - a struct or class instance and opSliceOpAssign is a member:) - ---- -a[$(SLICE)] $(I op)= c ---- - - $(P it is rewritten as:) - ---- -a.opSliceOpAssign!("$(I op)")(c, $(SLICE2)) ---- - - $(P and) - ---- -a[] $(I op)= c ---- - - $(P it is rewritten as:) - ---- -a.opSliceOpAssign!("$(I op)")(c) ---- - -

    Index Operator Overloading

    - - $(P The array index operator, $(CODE a[$(ARGUMENTS)]), can be overloaded by - declaring a function named $(B opIndex) with one - or more parameters. - ) - -------- -struct A { - int $(B opIndex)(size_t i1, size_t i2, size_t i3); -} - -void test() { - A a; - int i; - - i = a$(B [)5,6,7$(B ]); // same as i = a.opIndex(5,6,7); -} -------- - - $(P In this way a struct or class object can behave as if it - were an array. - ) - - $(P If an index expression can be rewritten using opIndexAssign or opIndexOpAssign, - those are preferred over opIndex. - ) - - -

    Slice Operator Overloading

    - - $(P Overloading the slicing operator means overloading expressions - like $(CODE a[]) and $(CODE a[$(SLICE)]). - This can be done by declaring a member function named $(B opSlice). - ) - -------- -class A { - int $(B opSlice)(); // overloads a[] - int $(B opSlice)(size_t x, size_t y); // overloads a[i .. j] -} - -void test() { - A a = new A(); - int i; - int v; - - i = a$(B []); // same as i = a.opSlice(); - i = a$(B [)3..4$(B ]); // same as i = a.opSlice(3,4); -} -------- - - $(P If a slice expression can be rewritten using opSliceAssign or opSliceOpAssign, - those are preferred over opSlice. - ) - -

    Forwarding

    - - $(P Member names not found in a class or struct can be forwarded - to a template function named $(CODE opDispatch) for resolution. - ) - ---- -import std.stdio; - -struct S { - void opDispatch(string s, T)(T i) - { - writefln("S.opDispatch('%s', %s)", s, i); - } -} - -class C { - void opDispatch(string s)(int i) { - writefln("C.opDispatch('%s', %s)", s, i); - } -} - -struct D { - template opDispatch(string s) { - enum int opDispatch = 8; - } -} - -void main() { - S s; - s.opDispatch!("hello")(7); - s.foo(7); - - auto c = new C(); - c.foo(8); - - D d; - writefln("d.foo = %s", d.foo); - assert(d.foo == 8); -} ---- -) - -$(V1 - $(P Overloading is accomplished by interpreting specially named - struct and class member functions as being implementations of unary and - binary operators. No additional syntax is used. - ) - - $(UL - $(LI $(LINK2 #Unary, Unary Operator Overloading)) - $(LI $(LINK2 #Binary, Binary Operator Overloading)) - $(LI $(LINK2 #FunctionCall, Function Call Operator Overloading)) - $(LI $(LINK2 #Array, Array Operator Overloading)) - $(LI $(LINK2 #Assignment, Assignment Operator Overloading)) -$(V2 - $(DOT $(LI $(LINK2 #Dot, Forwarding))) -) - $(LI $(LINK2 #Future, Future Directions)) - ) - -

    Unary Operator Overloading

    - - - $(TABLE2 Overloadable Unary Operators, - - $(TR $(TH$(I op)) $(TH$(I opfunc)) ) - - $(TR - $(TD -$(I e)) - $(TD $(CODE opNeg)) - ) - - $(TR - $(TD +$(I e)) - $(TD $(CODE opPos)) - ) - - $(TR - $(TD ~$(I e)) - $(TD $(CODE opCom)) - ) - - $(TR - $(TD $(I e)++) - $(TD $(CODE opPostInc)) - ) - - $(TR - $(TD $(I e)--) - $(TD $(CODE opPostDec)) - ) - - $(TR - $(TD cast($(I type))$(I e)) - $(TD $(CODE opCast)) - ) - - ) - - - $(P Given a unary - overloadable operator $(I op) and its corresponding - class or struct member - function name $(I opfunc), the syntax: - ) - ---- -$(I op) a ---- - - $(P where $(I a) is a class or struct object reference, - is interpreted as if it was written as: - ) ---- -a.$(I opfunc)() ---- - -

    Overloading ++$(I e) and --$(I e)

    - - $(P Since ++$(I e) is defined to be semantically equivalent - to ($(I e) += 1), the expression ++$(I e) is rewritten - as ($(I e) += 1), and then checking for operator overloading - is done. The situation is analogous for --$(I e). - ) - -

    Examples

    - - $(OL - $(LI -------- -class A { int $(B opNeg)(); } -A a; --a; // equivalent to a.opNeg(); -------- - ) - $(LI -------- -class A { int $(B opNeg)(int i); } -A a; --a; // equivalent to a.opNeg(), which is an error -------- - ) - ) - -

    Overloading cast($(I type))$(I e)

    - - $(P The member function $(I e).$(B opCast()) is called, - and the return value of $(B opCast()) is implicitly converted - to $(I type). Since functions cannot be overloaded based on - return value, there can be only one $(B opCast) per struct or - class. - Overloading the cast operator does not affect implicit casts, it - only applies to explicit casts. - ) - -------- -struct A { - int $(B opCast)() { return 28; } -} - -void test() { - A a; - - long i = cast(long)a; // i is set to 28L - void* p = cast(void*)a; // error, cannot implicitly - // convert int to void* - int j = a; // error, cannot implicitly convert - // A to int -} -------- - -

    Binary Operator Overloading

    - - - $(TABLE2 Overloadable Binary Operators, - - $(TR $(TH $(I op)) - $(TH commutative?) - $(TH $(I opfunc)) - $(TH $(I opfunc_r)) - ) - - $(TR $(TD +) $(TD yes) $(TD $(CODE opAdd)) $(TD $(CODE opAdd_r))) - - $(TR $(TD -) $(TD no) $(TD $(CODE opSub)) $(TD $(CODE opSub_r))) - - $(TR $(TD *) $(TD yes) $(TD $(CODE opMul)) $(TD $(CODE opMul_r))) - - $(TR $(TD /) $(TD no) $(TD $(CODE opDiv)) $(TD $(CODE opDiv_r))) - - $(TR $(TD %) $(TD no) $(TD $(CODE opMod)) $(TD $(CODE opMod_r))) - - $(TR $(TD &) $(TD yes) $(TD $(CODE opAnd)) $(TD $(CODE opAnd_r))) - - $(TR $(TD |) $(TD yes) $(TD $(CODE opOr)) $(TD $(CODE opOr_r))) - - $(TR $(TD ^) $(TD yes) $(TD $(CODE opXor)) $(TD $(CODE opXor_r))) - - $(TR $(TD <<) $(TD no) $(TD $(CODE opShl)) $(TD $(CODE opShl_r))) - - $(TR $(TD >>) $(TD no) $(TD $(CODE opShr)) $(TD $(CODE opShr_r))) - - $(TR $(TD >>>) $(TD no) $(TD $(CODE opUShr)) $(TD $(CODE opUShr_r))) - - $(TR $(TD ~) $(TD no) $(TD $(CODE opCat)) $(TD $(CODE opCat_r))) - - $(TR $(TD ==) $(TD yes) $(TD $(CODE opEquals)) $(TD -)) - - $(TR $(TD !=) $(TD yes) $(TD $(CODE opEquals)) $(TD -)) - - $(TR $(TD <) $(TD yes) $(TD $(CODE opCmp)) $(TD -)) - - $(TR $(TD <=) $(TD yes) $(TD $(CODE opCmp)) $(TD -)) - - $(TR $(TD >) $(TD yes) $(TD $(CODE opCmp)) $(TD -)) - - $(TR $(TD >=) $(TD yes) $(TD $(CODE opCmp)) $(TD -)) - - $(TR $(TD =) $(TD no ) $(TD $(CODE opAssign)) $(TD -) ) - - $(TR $(TD +=) $(TD no) $(TD $(CODE opAddAssign)) $(TD -)) - - $(TR $(TD -=) $(TD no) $(TD $(CODE opSubAssign)) $(TD -)) - - $(TR $(TD *=) $(TD no) $(TD $(CODE opMulAssign)) $(TD -)) - - $(TR $(TD /=) $(TD no) $(TD $(CODE opDivAssign)) $(TD -)) - - $(TR $(TD %=) $(TD no) $(TD $(CODE opModAssign)) $(TD -)) - - $(TR $(TD &=) $(TD no) $(TD $(CODE opAndAssign)) $(TD -)) - - $(TR $(TD |=) $(TD no) $(TD $(CODE opOrAssign)) $(TD -)) - - $(TR $(TD ^=) $(TD no) $(TD $(CODE opXorAssign)) $(TD -)) - - $(TR $(TD <<=) $(TD no) $(TD $(CODE opShlAssign)) $(TD -)) - - $(TR $(TD >>=) $(TD no) $(TD $(CODE opShrAssign)) $(TD -)) - - $(TR $(TD >>>=) $(TD no) $(TD $(CODE opUShrAssign)) $(TD -)) - - $(TR $(TD ~=) $(TD no) $(TD $(CODE opCatAssign)) $(TD -)) - - $(TR $(TD in ) $(TD no ) $(TD $(CODE opIn) ) $(TD $(CODE opIn_r) )) - - ) - - $(P Given a binary - overloadable operator $(I op) and its corresponding - class or struct member - function name $(I opfunc) and $(I opfunc_r), - and the syntax: - ) - ---- -a $(I op) b ---- - - the following sequence of rules is applied, in order, to determine - which form is used: - - $(OL - $(LI The expression is rewritten as both: ---- -a.$(I opfunc)(b) -b.$(I opfunc_r)(a) ---- - If any $(I a.opfunc) or $(I b.opfunc_r) functions exist, - then overloading is applied - across all of them and the best match is used. If either exist, - and there is no argument match, then it is an error. - ) - - $(LI If the operator is commutative, then the following - forms are tried: ---- -a.$(I opfunc_r)(b) -b.$(I opfunc)(a) ---- - ) - - $(LI If $(I a) or $(I b) is a struct or class object reference, - it is an error. - ) - ) - -

    Examples

    - - $(OL - $(LI - -------- -class A { int $(B opAdd)(int i); } -A a; -a + 1; // equivalent to a.opAdd(1) -1 + a; // equivalent to a.opAdd(1) -------- - ) - $(LI - -------- -class B { int $(B opDiv_r)(int i); } -B b; -1 / b; // equivalent to b.opDiv_r(1) -------- - ) - $(LI -------- -class A { int $(B opAdd)(int i); } -class B { int $(B opAdd_r)(A a); } -A a; -B b; -a + 1; // equivalent to a.opAdd(1) -a + b; // equivalent to b.opAdd_r(a) -b + a; // equivalent to b.opAdd_r(a) -------- - ) - $(LI -------- -class A { int $(B opAdd)(B b); int $(B opAdd_r)(B b); } -class B { } -A a; -B b; -a + b; // equivalent to a.opAdd(b) -b + a; // equivalent to a.opAdd_r(b) -------- - ) - $(LI -------- -class A { int $(B opAdd)(B b); int $(B opAdd_r)(B b); } -class B { int $(B opAdd_r)(A a); } -A a; -B b; -a + b; // ambiguous: a.opAdd(b) or b.opAdd_r(a) -b + a; // equivalent to a.opAdd_r(b) -------- - ) - ) - -

    Overloading == and !=

    - - $(P Both operators use the $(CODE $(B opEquals)()) function. - The expression - $(CODE (a == b)) is rewritten as $(CODE a.$(B opEquals)(b)), - and $(CODE (a != b)) is rewritten as $(CODE !a.$(B opEquals)(b)). - ) - - $(P The member function $(CODE $(B opEquals)()) is defined as part of - Object as: - ) - -------- -$(V1 int)$(V2 bool) $(B opEquals)(Object o); -------- - - $(P so that every class object has a default $(CODE $(B opEquals)()). - But every class definition which will be using == or != should - expect to need to override opEquals. The parameter to the overriding - function must be of type $(CODE Object), not the type for the class. - ) - - $(P Structs and unions (hereafter just called structs) can - provide a member function: - ) - -------- -$(V1 int)$(V2 bool) $(B opEquals)(S s) -------- - $(P or:) -------- -$(V1 int)$(V2 bool) $(B opEquals)(S* s) -------- - - $(P where $(CODE S) is the struct name, to define how equality is - determined.) - - $(P If a struct has no $(B opEquals) function declared for it, - a bit compare of the contents of the two structs is done to - determine equality or inequality. - ) - - $(P $(B Note:) Comparing a reference to a class object against $(B null) - should be done as: - ) -------- -if (a is null) -------- - $(P and not as:) -------- -if (a == null) -------- - $(P The latter is converted to:) -------- -if (a.$(B opEquals)(null)) -------- - $(P which will fail if $(CODE $(B opEquals)()) is a virtual function.) - -

    Overloading <, <=, > and >=

    - - $(P These comparison operators all use the $(CODE $(B opCmp)()) function. - The expression - $(CODE (a $(I op) b)) is rewritten as $(CODE (a.$(B opCmp)(b) $(I op) 0)). - The commutative operation is rewritten as $(CODE (0 $(I op) b.$(B opCmp)(a))) - ) - - $(P The member function $(CODE $(B opCmp)()) is defined as part of Object - as: - ) - -------- -int $(B opCmp)(Object o); -------- - - $(P so that every class object has a $(CODE $(B opCmp)()). - ) - - $(P $(CODE $(B opCmp)) for structs works analogously to - $(CODE $(B opEquals)) for structs: - ) -$(V1 -------- -struct Pair { - int a, b; - int $(B opCmp)(Pair rhs) { - if (a!=rhs.a) - return a-rhs.a; - return b-rhs.b; - } -} -------- -) -$(V2 -------- -struct Pair { - int a, b; - int $(B opCmp)(ref const Pair *rhs) const { - if (a!=rhs.a) - return a-rhs.a; - return b-rhs.b; - } -} -------- -) - $(P If a struct has no $(CODE $(B opCmp)()) function declared for it, - attempting - to compare two structs is an error. - ) - -

    Rationale

    - - $(P The reason for having both $(CODE $(B opEquals)) and - $(CODE $(B opCmp)) is that:) - - $(UL - $(LI Testing for equality can sometimes be a much more efficient - operation than testing for less or greater than.) - $(LI Having an $(CODE $(B opCmp)) defined in $(CODE Object) - makes it possible to - make associative arrays work generically for classes.) - $(LI For some objects, testing for less or greater makes no sense. - This is why $(CODE Object.$(B opCmp)) throws a runtime error. - $(CODE $(B opCmp)) must be overridden in each class for which comparison - makes sense.) - ) - - $(P The parameter to $(B opEquals) and $(B opCmp) - for class definitions must - be of type $(CODE Object), rather than the type of the particular class, - in order to override the $(CODE Object.$(B opEquals)) and - $(CODE Object.$(B opCmp)) - functions properly. - ) - -

    Function Call Operator Overloading $(I f)()

    - - $(P The function call operator, (), can be overloaded by - declaring a function named $(B opCall): - ) - -------- -struct F { - int $(B opCall)(); - int $(B opCall)(int x, int y, int z); -} - -void test() { - F f; - int i; - - i = f$(B ()); // same as i = f.opCall(); - i = f$(B (3,4,5)); // same as i = f.opCall(3,4,5); -} -------- - - $(P In this way a struct or class object can behave as if it - were a function. - ) - -

    Array Operator Overloading

    - -

    Overloading Indexing $(I a)[$(I i)]

    - - $(P The array index operator, [], can be overloaded by - declaring a function named $(B opIndex) with one - or more parameters. - Assignment to an array can be overloaded with a function - named $(B opIndexAssign) with two or more parameters. - The first parameter is the rvalue of the assignment expression. - ) - -------- -struct A { - int $(B opIndex)(size_t i1, size_t i2, size_t i3); - int $(B opIndexAssign)(int value, size_t i1, size_t i2); -} - -void test() { - A a; - int i; - - i = a$(B [)5,6,7$(B ]); // same as i = a.opIndex(5,6,7); - a$(B [)i,3$(B ]) = 7; // same as a.opIndexAssign(7,i,3); -} -------- - - $(P In this way a struct or class object can behave as if it - were an array. - ) - -$(V1 - $(P $(B Note:) Array index overloading currently does not - work for the lvalue of an $(I op)=, ++, or -- operator. - ) -) -$(V2 - $(P $(B Note:) To use array index overloading - with the $(I op)=, ++, or -- operators, - have the opIndex function return a reference type. - This reference is then used as the lvalue for those operators. - ) -) - -

    Overloading Slicing $(I a)[] and $(I a)[$(I i) .. $(I j)]

    - - $(P Overloading the slicing operator means overloading expressions - like $(CODE a[]) and $(CODE a[i .. j]). - This can be done by declaring a function named $(B opSlice). - Assignment to a slice can be done by declaring $(B opSliceAssign). - ) - -------- -class A { - int $(B opSlice)(); // overloads a[] - int $(B opSlice)(size_t x, size_t y); // overloads a[i .. j] - - int $(B opSliceAssign)(int v); // overloads a[] = v - int $(B opSliceAssign)(int v, size_t x, size_t y); // overloads a[i .. j] = v -} - -void test() { - A a = new A(); - int i; - int v; - - i = a$(B []); // same as i = a.opSlice(); - i = a$(B [)3..4$(B ]); // same as i = a.opSlice(3,4); - - a$(B []) = v; // same as a.opSliceAssign(v); - a$(B [)3..4$(B ]) = v; // same as a.opSliceAssign(v,3,4); -} -------- - -

    Assignment Operator Overloading

    - - $(P The assignment operator $(CODE =) can be overloaded if the - lvalue is a struct $(V1 or class) aggregate, and $(CODE opAssign) - is a member function of that aggregate.) - - $(P The assignment operator cannot be overloaded for rvalues - that can be implicitly cast to the lvalue type. - Furthermore, the following parameter signatures for $(CODE opAssign) - are not allowed:) - ---- -opAssign(...) -opAssign(T) -opAssign(T, ...) -opAssign(T ...) -opAssign(T, U = defaultValue, etc.) ---- - - $(P where $(I T) is the same type as the aggregate type $(I A), - is implicitly - convertible to $(I A), or if $(I A) is a struct and $(I T) - is a pointer to a type that is - implicitly convertible to $(I A). - ) - -$(V2 -$(DOT -

    Forwarding

    - - $(P Providing a struct or class member function $(CODE opDot) enables - the forwarding - of any names not found in the struct's scope to be forwarded - to the return type of the $(CODE opDot) function. In other words: - ) - ---- -struct T { - ... - S opDot() { ... } -} -T t; -... -t.m ---- - - $(P is rewritten as:) - ---- -t.opDot().m ---- - - $(P if m does not exist as a member of the struct T.) - - $(P The members .sizeof, .init, .offsetof, .alignof, .mangleof - and .stringof are not forwarded to $(CODE opDot).) - ---- -struct S { - int a, b, c; -} - -struct T { - S s; - int b = 7; - - S* opDot() { - return &s; // forwards to member s - } -} - -void main() { - T t; - t.a = 4; - t.b = 5; - t.c = 6; - assert(t.a == 4); - assert(t.b == 5); // T.b overrides S.b - assert(t.c == 6); - assert(t.s.b == 0); - assert(t.sizeof == 4*4); // sizeof T, not sizeof S -} ---- -) -) - -

    Future Directions

    - - $(P The operators $(CODE ! && || ?:) and a few others will - likely never be overloadable. - ) -) -) - -Macros: - TITLE=Operator Overloading - WIKI=OperatorOverloading - CATEGORY_SPEC=$0 - SUB=$0 - ARGUMENTS=$(I b)$(SUB 1), $(I b)$(SUB 2), ... $(I b)$(SUB n) - SLICE=$(I i)..$(I j) - SLICE2=$(I i), $(I j) - FOO= diff --git a/orgs-using-d.dd b/orgs-using-d.dd new file mode 100644 index 0000000000..7677973e0e --- /dev/null +++ b/orgs-using-d.dd @@ -0,0 +1,378 @@ +Ddoc + +$(COMMENT + - Put your logo (svg or transparent png) to images/orgs-using-d + - SVGs are preferred (`org-name.svg`) + - If you have a better quality logo, please name it `_hq.png` + - At the moment our setup requires manual resizing to 200x100, please save this file as `.png` + (on Linux you can conveniently do this with `convert -resize 200x100 org_hg.png org.png`) + - Organizations are sorted alphabetically +) + + +$(D_S $(TITLE), + +$(DIVC orgs-using-d center, + + $(DORG AdRoll, https://www.adroll.com, da_roll.png, + Marketing Platform, + $(HTTP tech.adroll.com/blog/data-science/2015/12/08/data-science_event_processing.html, Integral parts) of $(HTTP tech.adroll.com/blog/data-science/2015/08/25/factorization-machines.html,AdRoll's business) are built on D. + $(LINK_ROW + $(FA_TESTIMONIAL) $(I $(HTTP tech.adroll.com/blog/data/2014/11/17/d-is-for-data-science.html, D is for Data Science)) + ) + ) + $(DORG Ahrefs, https://ahrefs.com/, ahrefs.svg, + SEO tools and a search engine, + $(FA_QUOTE + Ahrefs is processing petabytes of data to build a web search engine with D. + ) + $(LINK_ROW + $(FA_HIRING ahrefs.com/jobs/d-c++-developer) + ) + ) + $(DORG ArabiaWeather, http://corporate.arabiaweather.com, arabiaweather.png, + Leading weather services provider in the Arab world, + $(FA_QUOTE + Only D drawback: it's so pleasant that coding in any other language becomes a nuisance. + ) + $(LINK_ROW + $(FA_TALK youtube.com/watch?v=egKU2xOlgbw, D TechTalk (Arabic)) + ) + ) + $(DORG AREX, https://arex.io/, arex.png, + Real-time exchange for B2B credit, + $(FA_QUOTE + D is a superb language for high volume, low latency order matching. + ) + $(LINK_ROW + $(FA_GITHUB arexio) $(FA_SEPARATOR) + $(FA_HIRING arex.recruiterbox.com/jobs/fk0hjlh) + ) + ) + $(DORG Auburn Sounds, http://www.auburnsounds.com, auburn.png, + Audio processing, + $(FA_QUOTE + Nothing quite matches D's power. + ) + $(LINK_ROW + $(FA_GITHUB AuburnSounds/dplug) $(FA_SEPARATOR) + $(FA_TESTIMONIAL) $(LINK2 http://www.auburnsounds.com/blog/2016-02-08_Making-a-Windows-VST-plugin-with-D.html, Testimonial) + ) + ) + $(DORG Bildhuus, https://bildhuus.com, bildhuus.svg, + Photography Software, + $(FA_QUOTE + The meta programming capabilites of D are unmatched and are essential for our whole software stack. + ) + $(LINK_ROW + $(FA_GITHUB bildhuus) $(FA_SEPARATOR) + $(FA_TESTIMONIAL aspect.bildhuus.com/blog/how-we-are-using-d-to-develop-aspect, Testimonial) + ) + ) + $(DORG CERERIS, http://www.myriad-corp.com, cereris.png, + Hardware and Software development, + $(FA_QUOTE + We use D to develop MVC web framework for embedded systems. + ) + $(LINK_ROW + $(FA_GITHUB LLC-CERERIS) + ) + ) + $(DORG Cut Through Recordings, http://www.modernmetalproduction.com, ctrecordings.png, + Digital Signal Processing, + $(FA_QUOTE + If you are looking for a powerful language that can support many programming styles, compiles natively, and is blazing fast, then D may be worth checking out. + ) + $(LINK_ROW + $(FA_GITHUB ctrecordings/Ddsp) $(FA_SEPARATOR) + $(FA_TESTIMONIAL) $(LINK2 http://www.modernmetalproduction.com/dplug-developing-vst-plugins-for-linux/, Testimonial) + ) + ) + $(DORG eBay, https://ebay.com, ebay.jpg, + One of the world’s largest marketplaces, + Large scale data mining tools. + $(HTTPS dlang.org/blog/2017/05/24/faster-command-line-tools-in-d/, Command line tools in D) + $(LINK_ROW + $(FA_GITHUB eBay/tsv-utils) + ) + ) + $(DORG ecratum, http://www.ecratum.com, ecratum.png, + Supplier Management tool for SME, + Core applications (Public API, Support app) use D. + $(LINK_ROW + $(FA_HIRING www.ecratum.com/ecratum/jobs) + ) + ) + $(DORG Emsi, http://www.economicmodeling.com, emsi.png, + Data-driven modelling, + N-dimensional dataset processing$(COMMA) + in-memory data manipulation + $(LINK_ROW + $(FA_TALK dconf.org/2014/talks/crapuchettes.html, DConf talk) $(FA_SEPARATOR) + $(FA_GITHUB economicmodeling) + ) + ) + $(DORG Facebook, https://www.facebook.com, facebook.svg, + Online social networking service, + $(HTTPS github.com/facebookarchive/warp, C Preprocessor warp) and $(HTTP www.drdobbs.com/mobile/facebook-adopts-d-language/240162694, more infrastructure tools). + $(LINK_ROW + $(FA_TALK dconf.org/2014/talks/simpkins.html, DConf talk) + ) + ) + $(DORG Funatics, http://www.funatics.de, funatics.png, + MMO Game Developer, + $(FA_QUOTE + D, with its elegance, simplicity and performance, + turned out to be the perfect replacement for Node.js + ) + $(LINK_ROW + $(FA_TALK dconf.org/2014/talks/dilly.html, DConf talk) + ) + ) + $(DORG Funkwerk AG, http://www.funkwerk.com/en/, funkwerk.png, + Passenger information systems, + $(FA_QUOTE + We use D to achieve perfect, well-readable code. + ) + $(LINK_ROW + $(FA_TALK dconf.org/talks/rohe.html, DConf talk) $(FA_SEPARATOR) + $(FA_HIRING www.funkwerk.com/karriere/stellenangebote) + ) + ) + $(DORG Infognition, http://www.infognition.com, infognition.svg, + Video processing, + $(FA_QUOTE + D shines from low-level control to high-level abstractions. + ) + $(LINK_ROW + $(FA_TESTIMONIAL) $(HTTP www.infognition.com/blog/2014/why_d.html, Testimonial) + ) + ) + $(DORG JumiaFood, https://food.jumia.com, jumiafood.png, + Instant delivery platform, + $(FA_QUOTE + D tremendously helps us to monitor our entire Kubernetes infrastructure. + ) + $(LINK_ROW + $(FA_GITHUB JumiaFood) + ) + ) + $(DORG Magikcraft, http://www.magikcraft.io, magikcraft.jpg, + Interactive teaching platform, + $(FA_QUOTE + We use D language for microservices and other awesome things! + ) + $(LINK_ROW + $(FA_GITHUB Magikcraft) + ) + ) + $(DORG Mercedes-Benz R&D NA, http://mbrdna.com, mbrdna.png, + Automotive Research, + $(FA_QUOTE D is used for software development tools.) + $(LINK_ROW + $(FA_HIRING mbrdna.com/careers/) + ) + ) + $(DORG Microline, http://www.microline.eu/?lang=en, microline.png, + Electrical appliances testing company, + $(FA_QUOTE + D is the preferred choice to develop web apps for our equipments! + ) + $(LINK_ROW + $(FA_HIRING www.microline.eu/work-with-us/?lang=en) + ) + ) + $(DORG Netflix, https://www.netflix.com, netflix.jpg, + Entertainment company, + $(FA_QUOTE + A modern systems language with a very gentle learning curve. multiple orders of magnitude of + performance gain ... seasoned developers leverage an excellent templating engine, compile-time + functionalities and lower-level features. + ) + $(LINK_ROW + $(FA_GITHUB netflix/vectorflow) $(FA_SEPARATOR) + $(FA_TESTIMONIAL) $(HTTPS medium.com/@NetflixTechBlog/introducing-vectorflow-fe10d7f126b8, Vectorflow) + ) + ) + $(DORG Putao, http://www.putao.com, putao.png, + Science and technology for kids, + Large scale use of D for distributed systems and cloud storage. + $(LINK_ROW + $(FA_GITHUB huntlabs) $(FA_SEPARATOR) + $(FA_HIRING job.oschina.net/position/792_118197_21895) + ) + ) + $(DORG Remedy Games, http://remedygames.com, remedy.png, + Triple-A game development, + First Triple-A game $(I $(HTTP quantumbreak.com, Quantum Break)) with D code. + $(LINK_ROW + $(FA_TALK dconf.org/2016/talks/watson.html, DConf talk). + ) + ) + $(DORG SARC, https://www.sarc.nl, sarc.svg, + Software and services for ship design$(COMMA) fairing and on-board loading calculations, + Translating ca. 500K LoC of ISO 10206 Extended Pascal to D. + $(LINK_ROW + $(FA_TALK www.youtube.com/watch?v=t5y9dVMdI7I, DConf talk) $(FA_SEPARATOR) + $(FA_TESTIMONIAL) $(HTTPS dlang.org/blog/2018/06/20/how-an-engineering-company-chose-to-migrate-to-d/, Testimonial) + ) + $(LINK_ROW + $(FA_GITHUB veelo/Pascal2D) + ) + ) + $(DORG Symmetry Investments, http://symmetryinvestments.com/about-us/, symmetry.png, + Alternative Investment Management, + Analytics and investment tools. + $(LINK_ROW + $(FA_TALK www.youtube.com/watch?v=xJy6ifCekCE&index=34&list=PL3jwVPmk_PRxo23yyoc0Ip_cP3-rCm7eB, Excel-D) $(FA_SEPARATOR) + $(FA_GITHUB symmetryinvestments) + ) + $(LINK_ROW + $(FA_TESTIMONIAL) $(HTTPS dlang.org/blog/symmetry-autumn-of-code, Testimonial) + $(FA_HIRING github.com/symmetryinvestments/overview/blob/master/hiring.md) + ) + ) + $(DORG Tagion, https://www.tagion.org/, tagion.svg, + Tagion is a decentralized network for high volume transactions and distributed solutions, + $(FA_QUOTE + D is not just a programming language; it is a paradigm shift towards effiency, safety and expressiveness. + ) + $(LINK_ROW + $(FA_GITHUB tagion) + ) + ) + $(DORG Tamedia, https://www.tamedia.ch/en/group/dts, tamedia.png, + Largest Swiss media company, + $(FA_QUOTE + D is not only a highly productive language, but also a great hiring filter. + ) + $(LINK_ROW + $(FA_GITHUB tamediadigital) + ) + ) + $(DORG ThatNeedle, http://thatneedle.com, thatneedle.png, + Natural Language Processing and information retrieval/search, + D is used for data processing, and rapid prototyping. + ) + $(DORG Tripaneer.com, https://www.tripaneer.com, tripaneer.png, + Themed vacation websites, + $(FA_QUOTE + Very good ratio of performance to productivity. + ) + $(LINK_ROW + $(FA_GITHUB ebookingservices) $(FA_SEPARATOR) + $(FA_HIRING www.tripaneer.com/news/work-with-us-software-developer-d-language-) + ) + ) + $(DORG ucora, https://www.ucora.com, ucora.svg, + Software development services, + $(FA_QUOTE + We have been using D for 6+ years to develop and sell our GamePlanPro platform. + Our company has been operating for 32 years and we are committed to using D as our preferred programming language. + ) + $(LINK_ROW + $(HTTPS www.ucora.com, Website) + ) + ) + $(DORG Weka.IO, http://www.weka.io, weka.png, + Software defined storage, + Complete distributed storage solution (over 200K LoC). + $(LINK_ROW + $(FA_TALK dconf.org/2016/talks/zvibel.html, DConf talk) $(FA_SEPARATOR) + $(FA_HIRING www.weka.io) + ) + ) + $(DORG PELock, https://www.pelock.com/, pelock.png, + Software protection and licensing solution, + $(FA_QUOTE + The D programming language is a first-class citizen in our SDKs. + ) + $(LINK_ROW + $(FA_GITHUB PELock/PELock-Software-Protection-and-Licensing-SDK) + ) + ) + + $(COMMENT + Please see the header of this file for instructions on how to add + your organization. + ) + + $(COMMENT + + More links or information is needed: + + $(DORG SR Labs, http://www.srlabs.it, srlabs.png, + Eye tracking, + ) + + Permission pending: + + $(DORG RandomStorm, https://www.randomstorm.com, randomstorm.png, + Network security products and services. + ) + + ) + +) + +$(P + Is your organization missing from this page? Please + $(LINK2 https://issues.dlang.org/enter_bug.cgi?component=dlang.org&short_desc=Add%20(insert%20your%20organization)%20to%20organizations%20using%20D, create an issue) + or $(LINK2 https://github.com/dlang/$(PROJECT)/edit/master/$(SRC_FILENAME), open a pull request). +) +) + +Macros: + TITLE=Organizations using the D Language + FA_HIRING=$(FA_ICON rocket) $(HTTP $1, Hiring) + FA_GITHUB=$(FA_ICON github) $(HTTPS github.com/$1, GitHub) + FA_TALK=$(FA_ICON youtube-play) $(HTTP $1, $2) + FA_SEPARATOR=  + FA_TESTIMONIAL=$(FA_ICON heart) + FA_QUOTE=$(FA_ICON quote-left) $0 $(FA_ICON quote-right) + LINK_ROW=$(DIVC orgs-using-d-linkrow, $1) + DORGIMG= + DORG=$(DIVC orgs-using-d-cell, $(DORGIMG $2, $3) $(P $(DIVC orgs-using-d-desc, $4 ) $(DIVC orgs-using-d-uses donthyphenate, $5))) + + EXTRA_HEADERS=$(T style, + #content, #content h1 { + text-align: center; + } + .orgs-using-d-cell { + width: 280px; + display: inline-block; + vertical-align: top; + margin-bottom: 0.5em; + padding-left: 25px; + padding-right: 25px; + padding-bottom: 10px; + } + .orgs-using-d h3 { + margin: 0.4em; + margin-left: 0; + margin-right: 0; + text-align: center; + } + .orgs-using-d-img-wrapper { + width: 280px; + height: 100px; + padding-bottom: 10px; + text-align: center; + } + .orgs-using-d img { + max-width: 280px; + max-height: 100px; + } + .orgs-using-d-desc { + font-style: italic; + margin-left: -1px; + margin-right: -1px; + } + .orgs-using-d-uses { + padding-top: 10px; + } + .orgs-using-d-linkrow { + padding-top: 5px; + } + ) + _= diff --git a/osx.ddoc b/osx.ddoc index 2724618a84..5569259d92 100644 --- a/osx.ddoc +++ b/osx.ddoc @@ -1,4 +1,3 @@ - OS=osx WINDOWS= LINUX= @@ -8,5 +7,6 @@ UNIX=$0 SEP=/ OBJEXT=o LIBEXT=a +BINEXT= DMDDIR=dmd2 -FOO= +_= diff --git a/overview.dd b/overview.dd index fab3a2ad41..89cfa118bf 100644 --- a/overview.dd +++ b/overview.dd @@ -2,516 +2,426 @@ Ddoc $(D_S Overview, -$(SECTION2 What is D?, - - $(P D is a general purpose systems and applications programming language. - It is a high level language, but retains the ability - to write high performance code and interface directly with the - operating system - API's - and with hardware. - D is well suited to writing medium to large scale - million line programs with teams of developers. D is easy - to learn, provides many capabilities to aid the programmer, - and is well suited to aggressive compiler optimization technology. - - D Man - ) - - $(P D is not a scripting language, nor an interpreted language. - It doesn't - come with a VM, - a religion, or an overriding - philosophy. It's a practical language for practical programmers - who need to get the job done quickly, reliably, and leave behind - maintainable, easy to understand code. - ) - - $(P D is the culmination of decades of experience implementing - compilers for many diverse languages, and attempting to construct - large projects using those languages. D draws inspiration from - those other languages (most especially C++) and tempers it with - experience and real world practicality. - ) +$(DIVC page-contents quickindex, + $(DIVC page-contents-header, + $(H3 Contents) + ) + $(OL + $(LI $(RELATIVE_LINK2 what_is_d, What is D?)) + $(LI $(RELATIVE_LINK2 why_d, Why D?)$(OL + $(LI $(RELATIVE_LINK2 goals, Major Design Goals of D)) + $(LI $(RELATIVE_LINK2 features_to_keep, Transitioning To D)) + $(LI $(RELATIVE_LINK2 features_to_drop, Features To Leave Behind)) + $(LI $(RELATIVE_LINK2 for_d, Who D is For?)) + $(LI $(RELATIVE_LINK2 not_for_d, Who D is Not For?)) + )) + $(LI $(RELATIVE_LINK2 major_features, Major Features of D)$(OL + $(LI $(RELATIVE_LINK2 OOP, Object Oriented Programming)) + $(LI $(RELATIVE_LINK2 functional, Functional Programming)) + $(LI $(RELATIVE_LINK2 productivity, Productivity)) + $(LI $(RELATIVE_LINK2 functions, Functions)) + $(LI $(RELATIVE_LINK2 arrays, Arrays)) + $(LI $(RELATIVE_LINK2 ranges, Ranges)) + $(LI $(RELATIVE_LINK2 resource, Resource Management)) + $(LI $(RELATIVE_LINK2 performance, Performance)) + $(LI $(RELATIVE_LINK2 reliability, Reliability)) + $(LI $(RELATIVE_LINK2 compatibility, Compatibility)) + $(LI $(RELATIVE_LINK2 management, Project Management)) + )) + $(LI $(RELATIVE_LINK2 sample, Sample D Program)) + ) ) +$(SECTION2 $(LNAME2 what_is_d, What is D?), + + D Man + + $(P D is a general purpose systems and applications programming language. + It is a high level language, but retains the ability + to write high performance code and interface directly with the + operating system + API's + and with hardware. + D is well suited to writing medium to large scale + million line programs with teams of developers. D is easy + to learn, provides many capabilities to aid the programmer, + and is well suited to aggressive compiler optimization technology. + ) + + $(P D is not a scripting language, nor an interpreted language. + It doesn't + come with a VM, + a religion, or an overriding + philosophy. It's a practical language for practical programmers + who need to get the job done quickly, reliably, and leave behind + maintainable, easy to understand code. + ) + + $(P D is the culmination of decades of experience implementing + compilers for many diverse languages, and attempting to construct + large projects using those languages. D draws inspiration from + those other languages (most especially C++) and tempers it with + experience and real world practicality. + ) +) + +$(SECTION2 $(LNAME2 why_d, Why D?), + + $(P Why, indeed. Who needs another programming language? + ) + + $(P The software industry is continuously evolving at a breakneck pace. + New ideas appear, and older ideas are either validated or discarded. + What programmers need and want out of a programming language changes. + Available memory and computing power have increased by orders of + magnitude, as well as the scale of programs being developed. + ) + + $(P Compilers are no longer terribly constrained by available computing + resources, and so are able to do much more for the programmer. + Much more powerful language features have become practical. + These features can be difficult to retrofit into existing languages, + and when there are enough of these, a new language is justified. + ) + + +$(SECTION3 $(LNAME2 goals, Major Design Goals of D), -$(SECTION2 Why D?, - - $(P Why, indeed. Who needs another programming language? - ) - - $(P The software industry has come a long way since the C language was - invented. - Many new concepts were added to the language with C++, but backwards - compatibility with C was maintained, including compatibility with - nearly all the weaknesses of the original design. - There have been many attempts to fix those weaknesses, but the - compatibility issue frustrates it. - Meanwhile, both C and C++ undergo a constant accretion of new - features. These new features must be carefully fitted into the - existing structure without requiring rewriting old code. - The end result is very complicated - the C standard is nearly - 500 pages, and the C++ standard is about 750 pages! - C++ is a difficult and costly language to implement, - resulting in implementation variations that make it frustrating - to write fully portable C++ code. - ) - - $(P C++ implements things like resizable arrays and string - concatenation as part of the standard library, not as part of the - core language. $(REDO Not being part of the core language has - several $(LINK2 cppstrings.html, suboptimal consequences).)) - - $(P Can the power and capability of C++ be extracted, redesigned, - and recast into a language that is simple, orthogonal, - and practical? - Can it all be put into a package - that is easy for compiler - writers to correctly implement, and - which enables compilers to efficiently generate aggressively - optimized code? - ) - - $(P Modern compiler technology has progressed to the point where language - features for the purpose of compensating for primitive compiler - technology can be omitted. (An - example of this would be the $(SINGLEQUOTE register) keyword in C, a more - subtle example is the macro - preprocessor in C.) - We can rely on modern compiler optimization technology to not - need language features necessary to get acceptable code quality out of - primitive compilers. - ) - -$(SECTION3 Major Design Goals of D, - - $(P Everything in designing a language is a tradeoff. Keeping some - principles in mind will help to make the right decisions.) + $(P Everything in designing a language is a tradeoff. Keeping some + principles in mind will help to make the right decisions.) $(OL - $(LI Make it easier to write code that is portable from compiler - to compiler, machine to machine, and operating system to operating - system. Eliminate undefined and implementation defined behaviors - as much as practical.) - $(LI Provide syntactic and semantic constructs that eliminate or - at least reduce common mistakes. Reduce or even eliminate the need - for third party static code checkers.) + $(LI Enable writing fast, effective code in a straightforward manner.) + + $(LI Make it easier to write code that is portable from compiler + to compiler, machine to machine, and operating system to operating + system. Eliminate undefined and implementation defined behaviors + as much as practical.) + + $(LI Provide syntactic and semantic constructs that eliminate or + at least reduce common mistakes. Reduce or even eliminate the need + for third party static code checkers.) - $(LI Support memory safe programming.) + $(LI Support memory safe programming.) - $(LI Support multi-paradigm programming, i.e. at a minimum support - imperative, structured, object oriented, generic and even - functional programming paradigms.) + $(LI Support multi-paradigm programming, i.e. at a minimum support + imperative, structured, object oriented, generic and even + functional programming paradigms.) - $(LI Make doing things the right way easier than the wrong way.) + $(LI Make doing things the right way easier than the wrong way.) - $(LI Have a short learning curve for programmers comfortable with - programming in C, C++ or Java.) + $(LI Have a short learning curve for programmers comfortable with + programming in C, C++ or Java.) - $(LI Provide low level bare metal access as required. Provide a means - for the advanced programmer to escape checking as necessary.) + $(LI Provide low level bare metal access as required. Provide a means + for the advanced programmer to escape checking as necessary.) - $(LI Make D reasonably easy to implement a compiler for.) + $(LI Be compatible with the local C application binary interface.) - $(LI Be compatible with the local C application binary interface.) + $(LI Where D code looks the same as C code, have it either behave the + same or issue an error.) - $(LI Where D code looks the same as C code, have it either behave the - same or issue an error.) + $(LI Have a context-free grammar. Successful parsing must not require + semantic analysis.) - $(LI Have a context-free grammar. Successful parsing must not require - semantic analysis.) + $(LI Easily support writing internationalized applications - Unicode everywhere.) - $(LI Easily support writing internationalized applications.) + $(LI Incorporate Contract Programming and unit testing methodology.) - $(LI Incorporate Contract Programming and unit testing methodology.) + $(LI Be able to build lightweight, standalone programs.) - $(LI Be able to build lightweight, standalone programs.) + $(LI Reduce the costs of creating documentation.) - $(LI Reduce the costs of creating documentation.) + $(LI Provide sufficient semantics to enable advances in compiler optimization + technology.) - $(LI Provide sufficient semantics to enable advances in compiler optimization - technology.) + $(LI Cater to the needs of numerical analysis programmers.) - $(LI Cater to the needs of numerical analysis programmers.) + $(LI Obviously, sometimes these goals will conflict. Resolution will be + in favor of usability.) - $(LI Obviously, sometimes these goals will conflict. Resolution will be - in favor of usability.) ) ) -$(SECTION3 Features To Keep, +$(SECTION3 $(LNAME2 features_to_keep, Transitioning to D), - $(P The general look of D is like C and C++. This makes it easier to learn - and port code to D. Transitioning from C/C++ to D should feel natural. - The - programmer will not have to learn an entirely new way of doing things. - ) + $(P The general look of D is like C and C++. This makes it easier to learn + and port code to D. Transitioning from C/C++ to D should feel natural. + The + programmer will not have to learn an entirely new way of doing things. + ) - $(P Using D will not mean that the programmer will become restricted to a - specialized runtime vm (virtual machine) like the Java vm or the - Smalltalk vm. - There is no D vm, it's a straightforward compiler that generates - linkable object files. - D connects to the operating system just like C does. - The usual familiar tools like $(B make) will fit right in with - D development. - ) + $(P Using D will not mean that the programmer will become restricted to a + specialized runtime vm (virtual machine) like the Java vm or the + Smalltalk vm. + There is no D vm, it's a straightforward compiler that generates + linkable object files. + D connects to the operating system just like C does. + The usual familiar tools like $(B make) will fit right in with + D development. + ) $(UL - $(LI The general $(B look and feel) of C/C++ is maintained. - It uses the same algebraic syntax, most of the same expression - and statement forms, and the general layout. - ) - - $(LI D programs can be written either in - C style $(B function-and-data), - C++ style $(B object-oriented), - C++ style $(B template metaprogramming), - or any mix of the three. - ) - - $(LI The $(B compile/link/debug) development model is - carried forward, - although nothing precludes D from being compiled into bytecode - and interpreted. - ) - - $(LI $(B Exception handling). - More and more experience with exception handling shows it to be a - superior way to handle errors than the C traditional method of using - error codes and errno globals. - ) - - $(LI $(B Runtime Type Identification). - This is partially implemented in C++; - in D it is taken to its - next logical step. Fully supporting it enables better garbage - collection, better debugger support, more automated persistence, etc. - ) - - $(LI D maintains function link compatibility with the $(B C calling - conventions). This makes - it possible for D programs to access operating system API's directly. - Programmers' knowledge and experience with existing programming API's - and paradigms can be carried forward to D with minimal effort. - ) - - $(LI $(B Operator overloading). - D programs can overload operators enabling - extension of the basic types with user defined types. - ) - - $(LI $(B Template Metaprogramming). - Templates are a way to implement generic programming. - Other ways include using macros or having a variant data type. - Using macros is out. Variants are straightforward, but - inefficient and lack type checking. - The difficulties with C++ templates are their - complexity, they don't fit well into the syntax of the language, - all the various rules for conversions and overloading fitted on top of - it, etc. D offers a much simpler way of doing templates. - ) - - $(LI $(B RAII) - (Resource Acquisition Is Initialization). - RAII techniques are an essential component of writing reliable - software. - ) - - $(LI $(B Down and dirty programming). D retains the ability to - do down-and-dirty programming without resorting to referring to - external modules compiled in a different language. Sometimes, - it's just necessary to coerce a pointer or dip into assembly - when doing systems work. D's goal is not to $(I prevent) down - and dirty programming, but to minimize the need for it in - solving routine coding tasks. - ) + $(LI The general $(B look and feel) of C/C++ is adopted. + It uses the same algebraic syntax, most of the same expression + and statement forms, and the general layout. + ) + + $(LI D programs can be written in familiar paradigms, + $(B function-and-data), + $(B object-oriented), + $(B template metaprogramming), + $(B functional), + or any mix of them. + ) + + $(LI The $(B compile/link/debug) development model is + carried forward from languages like C, + although nothing precludes D from being compiled into bytecode + and interpreted. + ) + + $(LI $(B Exception handling). + More and more experience with exception handling shows it to be a + superior way to handle errors than error codes. + ) + + $(LI $(B Runtime Type Identification). + Fully supporting RTTI it enables better garbage + collection, better debugger support, more automated persistence, etc. + ) + + $(LI D maintains function link compatibility with the $(B C calling + conventions). This makes + it possible for D programs to access operating system APIs directly. + Programmers' knowledge and experience with existing programming APIs + and paradigms can be carried forward to D with minimal effort. ) -) -$(SECTION3 Features To Drop, + $(LI Limited support for function link compatibility with $(B C++ + calling conventions). In particular, there is compatibility with + C++ name mangling, namespaces, templates, and exceptions. + ) + $(LI $(B Operator overloading). + D programs can overload operators enabling + extension of the basic types with user-defined types. + ) + + $(LI $(B Template Metaprogramming). + Parametric polymorphism (aka template metaprogramming) is straightforward + in D. + ) + + $(LI $(B RAII) + (Resource Acquisition Is Initialization). + RAII techniques are an essential component of writing reliable + software. + ) + + $(LI $(B Custom memory management). + There are times in systems programming where developers need + alternatives to garbage collection. D also allows for manual memory + management, techniques such as reference counting, and the use of + specialized memory allocators. + ) + + $(LI $(B Down and dirty programming). D retains the ability to + do down-and-dirty programming without resorting to referring to + external modules compiled in a different language. Sometimes, + it's just necessary to coerce a pointer or dip into assembly + when doing systems work. D's goal is not to $(I prevent) down + and dirty programming, but to minimize the need for it in + solving routine coding tasks. + ) + ) +) + +$(SECTION3 $(LNAME2 features_to_drop, Features To Leave Behind), $(UL - $(LI C source code compatibility. Extensions to C that maintain - source compatibility - have already been done (C++ and ObjectiveC). Further work in this - area is hampered by so much legacy code it is unlikely that significant - improvements can be made. - ) - - $(LI Link compatibility with C++. The C++ runtime object model is just - too complicated - properly supporting it would essentially imply - making D a full C++ compiler too. - ) - - $(LI The C preprocessor. Macro processing is an easy way to extend - a language, adding in faux features that aren't really there (invisible - to the symbolic debugger). Conditional compilation, layered with - #include text, macros, token concatenation, etc., essentially forms - not one language but two merged together with no obvious distinction - between them. Even worse (or perhaps for the best) the C preprocessor - is a very primitive macro language. It's time to step back, look at - what the preprocessor is used for, and design support for those - capabilities directly into the language. - ) - - $(LI Multiple inheritance. It's a complex - feature of debatable value. It's very difficult to implement in an - efficient manner, and compilers are prone to many bugs in implementing - it. Nearly all the value of - MI can be handled with - single inheritance - coupled with interfaces and aggregation. What's left does not - justify the weight of MI implementation. - ) - - $(LI Namespaces. An attempt to deal with the problems resulting from - linking together independently developed pieces of code that - have conflicting names. The idea of modules is simpler and works - much better. - ) - - $(LI Tag name space. This misfeature of C is where the tag names - of structs are in a separate but parallel symbol table. C++ - attempted to merge the tag name space with the regular name space, - while retaining backward compatibility with legacy C code. The - result is needlessly confusing. - ) - - $(LI Forward declarations. C compilers semantically only know - about what has lexically preceded the current state. C++ extends this - a little, in that class members can rely on forward referenced class - members. D takes this to its logical conclusion, forward declarations - are no longer necessary at the module level. - Functions can be defined in a natural - order rather than the typical inside-out order commonly used in C - programs to avoid writing forward declarations. - ) - - $(LI Include files. A major cause of slow compiles as each - compilation unit - must reparse enormous quantities of header files. Include files - should be done as importing a symbol table. - ) - - $(LI Trigraphs and digraphs. Unicode is the future. - ) - - $(LI Non-virtual member functions. In C++, a class designer decides - in advance if a function is to be virtual or not. Forgetting to retrofit - the base class member function to be virtual when the function gets - overridden is a common (and very hard to find) coding error. - Making all member functions virtual, and letting the compiler decide - if there are no overrides and hence can be converted to non-virtual, - is much more reliable. - ) - - $(LI Bit fields of arbitrary size. - Bit fields are a complex, inefficient feature rarely used. - ) - - $(LI Support for 16 bit computers. - No consideration is given in D for mixed near/far pointers and all the - machinations necessary to generate good 16 bit code. The D language - design assumes at least a 32 bit flat memory space. D will fit smoothly - into 64 bit architectures. - ) - - $(LI Mutual dependence of compiler passes. In C++, successfully parsing - the source text relies on having a symbol table, and on the various - preprocessor commands. This makes it - impossible to preparse C++ source, and makes writing code analyzers - and syntax directed editors painfully difficult to do correctly. - ) - - $(LI Compiler complexity. Reducing the complexity of an implementation - makes it more likely that multiple, $(I correct) implementations - are available. - ) - - $(LI Dumbed down floating point. If one is using hardware that - implements modern floating point, it should be available to the - programmer rather than having floating point support dumbed down - to the lowest common denominator among machines. In particular, - a D implementation must support IEEE 754 arithmetic and if - extended precision is available it must be supported.) - - $(LI Template overloading of < and > symbols. - This choice has caused years of bugs, grief, and confusion - for programmers, C++ implementors, and C++ source parsing tool - vendors. It makes it - impossible to parse C++ code correctly without doing a nearly complete - C++ compiler. D uses !( and ) which fit neatly and - unambiguously into the grammar. - ) + + $(LI Support for 16 bit computers. + No consideration is given in D for mixed near/far pointers and all the + machinations necessary to generate good 16 bit code. The D language + design assumes at least a 32 bit flat memory space and supports 64 bit as + well. + ) + + $(LI Mutual dependence of compiler passes. + Having a clean separation between the lexer, parser, and semantic + passes makes for an easier to implement and understand language. + This means no user-defined tokens and no user-defined syntax. + ) + + $(LI Macro systems. + Macros are an easy way for users to add very powerful features. + Unfortunately, the complexity is pushed off on to the user trying + to understand the macro usage, and the result is rarely worth + it and not justifiable. + ) + + $(LI C/C++ source code compatibility. + The use of the preprocessor has made this difficult to achieve without + inevitably requiring manual touch up. It's best to leave this + to external tools. + ) + + $(LI Multiple inheritance. It's a complex + feature of debatable value. It's very difficult to implement in an + efficient manner, and compilers are prone to many bugs in implementing + it. Nearly all the value of + MI can be handled with + single inheritance + coupled with interfaces and aggregation. What's left does not + justify the weight of MI implementation. + ) ) ) -$(SECTION3 Who D is For, +$(SECTION3 $(LNAME2 for_d, Who is D For?), $(UL - $(LI Programmers who routinely use lint or similar code analysis tools - to eliminate bugs before the code is even compiled. - ) - - $(LI People who compile with maximum warning levels turned on and who - instruct the compiler to treat warnings as errors. - ) - - $(LI Programming managers who are forced to rely on programming style - guidelines to avoid common C bugs. - ) - - $(LI Those who decide the promise of C++ object oriented - programming is not fulfilled due to the complexity of it. - ) - - $(LI Programmers who enjoy the expressive power of C++ but are - frustrated by - the need to expend much effort explicitly managing memory and finding - pointer bugs. - ) - - $(LI Projects that need built-in testing and verification. - ) - - $(LI Teams who write apps with a million lines of code in it. - ) - - $(LI Programmers who think the language should provide enough - features to obviate - the continual necessity to manipulate pointers directly. - ) - - $(LI Numerical programmers. D has many features to directly - support features needed by numerics programmers, like - extended floating point precision, - core support for complex and imaginary floating types - and defined behavior for - NaN's and infinities. - (These are added in the new - C99 standard, but not in C++.) - ) - - $(LI Programmers who write half their application in scripting - langauges like Ruby and Python, and the other half in C++ to - speed up the bottlenecks. D has many of the productivity features - of Ruby and Python, making it possible to write the entire app - in one language.) - - $(LI D's lexical analyzer and parser are totally independent of each other and of the - semantic analyzer. This means it is easy to write simple tools to manipulate D source - perfectly without having to build a full compiler. It also means that source code can be - transmitted in tokenized form for specialized applications. - ) + $(LI Programmers who routinely use lint or similar code analysis tools + to eliminate bugs before the code is even compiled. + ) + + $(LI People who compile with maximum warning levels turned on and who + instruct the compiler to treat warnings as errors. + ) + + $(LI Programming managers who are forced to rely on programming style + guidelines to avoid common bugs. + ) + + $(LI Projects that need built-in testing and verification. + ) + + $(LI Teams who write apps with a million lines of code in it. + ) + + $(LI Programmers who think the language should provide enough + features to obviate + the continual necessity to manipulate pointers directly. + ) + + $(LI Programmers who write half their application in scripting + languages the other half in native langauges to + speed up the bottlenecks. + D has productivity features that make using such hybrid approaches + unnecessary. + ) + + $(LI D's lexical analyzer and parser are totally independent of each other and of the + semantic analyzer. This means it is easy to write simple tools to manipulate D source + perfectly without having to build a full compiler. It also means that source code can be + transmitted in tokenized form for specialized applications. + ) ) ) -$(SECTION3 Who D is Not For, +$(SECTION3 $(LNAME2 not_for_d, Who D is Not For?), $(UL - $(LI Realistically, nobody is going to convert million line C or C++ - programs into D. - Since D does not compile unmodified C/C++ - source code, D is not for - legacy apps. - (However, D supports legacy C API's very well. D can connect - directly to any code that exposes a C interface.) - ) - - $(LI As a first programming language - Basic or Java is more suitable - for beginners. D makes an excellent second language for intermediate - to advanced programmers. - ) - - $(LI Language purists. D is a practical language, and each feature - of it is evaluated in that light, rather than by an ideal. - For example, D has constructs and semantics that virtually eliminate - the need for pointers for ordinary tasks. But pointers are still - there, because sometimes the rules need to be broken. - Similarly, casts are still there for those times when the typing - system needs to be overridden. - ) + $(LI Realistically, nobody is going to convert million line legacy + programs into D. + D, however, can connect directly to any code that exposes a C ABI interface + or (to a limited extent) a C++ ABI interface. ) -) - -) + $(LI As a first programming language - Python or JavaScript is more suitable + for beginners. D makes an excellent second language for intermediate + to advanced programmers. + ) + $(LI Language purists. D is a practical language, and each feature + of it is evaluated in that light, rather than by an ideal. + For example, D has constructs and semantics that virtually eliminate + the need for pointers for ordinary tasks. But pointers are still + there, because sometimes the rules need to be broken. + Similarly, casts are still there for those times when the typing + system needs to be overridden. + ) + ) +) -$(SECTION2 Major Features of D, +) +$(SECTION2 $(LNAME2 major_features, Major Features of D), - $(P This section lists some of the more interesting features of D - in various categories. - ) + $(P This section lists some of the more interesting features of D + in various categories. + ) -$(SECTION3 Object Oriented Programming, +$(SECTION3 $(LNAME2 OOP, Object Oriented Programming), $(SECTION4 Classes, - $(P D's object oriented nature comes from classes. - The inheritance model is single inheritance enhanced - with interfaces. The class Object sits at the root - of the inheritance hierarchy, so all classes implement - a common set of functionality. - Classes are instantiated - by reference, and so complex code to clean up after exceptions - is not required. - ) + $(P D's object oriented nature comes from classes. + The inheritance model is single inheritance enhanced + with interfaces. The class Object sits at the root + of the inheritance hierarchy, so all classes implement + a common set of functionality. + Classes are instantiated + by reference, and so complex code to clean up after exceptions + is not required. + ) + ) + + $(P See the $(LINK2 spec/class.html, Classes) page for more + information. ) $(SECTION4 Operator Overloading, - $(P Classes can be crafted that work with existing operators to extend - the type system to support new types. An example would be creating - a bignumber class and then overloading the +, -, * and / operators - to enable using ordinary algebraic syntax with them. - ) + $(P Classes can be crafted that work with existing operators to extend + the type system to support new types. An example would be creating + a bignumber class and then overloading the +, -, * and / operators + to enable using ordinary algebraic syntax with them. + ) + ) + + $(P See the $(LINK2 spec/operatoroverloading.html, Operator Overloading) + page for more information. ) ) -$(SECTION3 Functional Programming, +$(SECTION3 $(LNAME2 functional, Functional Programming), - $(P Functional programming has a lot to offer in terms of encapsulation, - concurrent programming, memory safety, and composition. D's support for - functional style programming include: - ) + $(P Functional programming has a lot to offer in terms of encapsulation, + concurrent programming, memory safety, and composition. D's support for + functional style programming include: + ) - $(UL - $(LI Pure functions) - $(LI Immutable types and data structures) - $(LI Lambda functions and closures) - ) + $(UL + $(LI Pure functions) + $(LI Immutable types and data structures) + $(LI Lambda functions and closures) + ) ) -$(SECTION3 Productivity, +$(SECTION3 $(LNAME2 productivity, Productivity), $(SECTION4 Modules, - $(P Source files have a one-to-one correspondence with modules. - Instead of #include'ing the text of a file of declarations, - just import the module. There is no need to worry about - multiple imports of the same module, no need to wrapper header - files with $(D #ifndef/#endif) or $(D #pragma once) kludges, - etc. - ) + $(P Source files have a one-to-one correspondence with modules. + ) + ) + + $(P See the $(LINK2 spec/module.html, Module) + page for more information. ) $(SECTION4 Declaration vs Definition, - $(P C++ usually requires that functions and classes be declared twice - the declaration - that goes in the .h header file, and the definition that goes in the .c source - file. This is an error prone and tedious process. Obviously, the programmer - should only need to write it once, and the compiler should then extract the - declaration information and make it available for symbolic importing. This is - exactly how D works. - ) + $(P Functions and classes are defined once. There is no need + for declarations when they are forward referenced. + A module can be imported, and all its public declarations + become available to the importer. + ) - $(P Example: - ) + $(P Example: + ) ----------------------- class ABC @@ -522,37 +432,8 @@ class ABC int q; ----------------------- - $(P There is no longer a need for a separate definition of member functions, static - members, externs, nor for clumsy syntaxes like: - ) - -$(CCODE -int ABC::func() { return 7; } -int ABC::z = 7; -extern int q; -) - - $(P Note: Of course, in C++, trivial functions like $(D { return 7; }) - are written inline too, but complex ones are not. In addition, if - there are any forward references, the functions need to be prototyped. - The following will not work in C++: - ) - -$(CCODE -class Foo -{ - int foo(Bar *c) { return c->bar(); } -}; - -class Bar -{ - public: - int bar() { return 3; } -}; -) - - $(P But the equivalent D code will work: - ) + $(P All members are defined in the class or struct, not separately. + ) ----------------------- class Foo @@ -566,550 +447,746 @@ class Bar } ----------------------- - $(P Whether a D function is inlined or not is determined by the - optimizer settings. - ) + $(P Whether a D function is inlined or not is determined by the + optimizer settings. + ) ) $(SECTION4 Templates, - $(P D templates offer a clean way to support generic programming while - offering the power of partial specialization. - Template classes and template functions are available, along - with variadic template arguments and tuples. - ) + $(P D templates offer a clean way to support generic programming while + offering the power of partial specialization. + Template classes and template functions are available, along + with variadic template arguments and tuples. ) - - $(SECTION4 Associative Arrays, - - $(P Associative arrays are arrays with an arbitrary data type as - the index rather than being limited to an integer index. - In essence, associated arrays are hash tables. Associative - arrays make it easy to build fast, efficient, bug-free symbol - tables. - ) ) -$(V1 - $(SECTION4 Real Typedefs, - - $(P C and C++ typedefs are really type $(I aliases), as no new - type is really introduced. D implements real typedefs, where: - ) + $(P See the $(LINK2 spec/template.html, Templates) + page for more information. + ) ------------------------ -typedef int handle; ------------------------ + $(SECTION4 Associative Arrays, - $(P really does create a new type $(B handle). Type checking is - enforced, and typedefs participate in function overloading. - For example: - ) + $(P Associative arrays are arrays with an arbitrary data type as + the index rather than being limited to an integer index. + In essence, associated arrays are hash tables. Associative + arrays make it easy to build fast, efficient, bug-free symbol + tables. + ) + ) ------------------------ -int foo(int i); -int foo(handle h); ------------------------ + $(P See the $(LINK2 spec/hash-map.html, Associative Arrays) + page for more information. ) -) $(SECTION4 Documentation, - $(P Documentation has traditionally been done twice - first there - are comments documenting what a function does, and then this gets - rewritten into a separate html or man page. - And naturally, over time, they'll tend to diverge as the code - gets updated and the separate documentation doesn't. - Being able to generate the requisite polished documentation directly - from the comments embedded in the source will not only cut the time - in half needed to prepare documentation, it will make it much easier - to keep the documentation in sync with the code. - $(LINK2 ddoc.html, Ddoc) is the specification for the D - documentation generator. This page was generated by Ddoc, too. - ) + $(P Documentation has traditionally been done twice - first there + are comments documenting what a function does, and then this gets + rewritten into a separate html or man page. + And naturally, over time, they'll tend to diverge as the code + gets updated and the separate documentation doesn't. + Being able to generate the requisite polished documentation directly + from the comments embedded in the source will not only cut the time + in half needed to prepare documentation, it will make it much easier + to keep the documentation in sync with the code. + $(LINK2 spec/ddoc.html, Ddoc) is the specification for the D + documentation generator. This page was generated by Ddoc, too. + ) - $(P Although third party tools exist to do this for C++, they have some - serious shortcomings: + $(P Although third party tools exist to do this for other languages. + they have some serious shortcomings: - $(UL + $(UL - $(LI It is spectacularly difficult to parse C++ 100% correctly. To - do so really requires a full C++ compiler. Third party tools tend to - parse only a subset of C++ correctly, so their use will constrain - the source code to that subset.) + $(LI It is difficult to parse the language correctly. + Third party tools tend to + parse only a subset of a language correctly, so their use will constrain + the source code to that subset.) - $(LI Different compilers support different versions of C++ and have - different extensions to C++. Third party tools have a problem matching - all these variations.) + $(LI Different compilers support different versions of a language and have + different extensions to it. Third party tools have a problem matching + all these variations.) - $(LI Third party tools may not be available for all the desired - platforms, and they're necessarily on a different upgrade cycle - from the compilers.) + $(LI Third party tools may not be available for all the desired + platforms, and they're necessarily on a different upgrade cycle + from the compilers.) - $(LI Having it builtin to the compiler means it is standardized across - all D implementations. Having a default one ready to go at all times - means it is far more likely to be used.) + $(LI Having it builtin to the compiler means it is standardized across + all D implementations. Having a default one ready to go at all times + means it is far more likely to be used.) - ) - ) + ) + ) ) ) -$(SECTION3 Functions, +$(SECTION3 $(LNAME2 functions, Functions), - $(P D has the expected support for ordinary functions including - global functions, overloaded functions, inlining of functions, - member functions, virtual functions, function pointers, etc. - In addition: - ) + $(P D has the expected support for ordinary functions including + global functions, overloaded functions, inlining of functions, + member functions, virtual functions, function pointers, etc. + In addition: + ) $(SECTION4 Nested Functions, - $(P Functions can be nested within other functions. - This is highly useful for code factoring, locality, and - function closure techniques. - ) + $(P Functions can be nested within other functions. + This is highly useful for code factoring, locality, and + function closure techniques. + ) ) $(SECTION4 Function Literals, - $(P Anonymous functions can be embedded directly into an expression. - ) + $(P Anonymous functions can be embedded directly into an expression. + ) ) $(SECTION4 Dynamic Closures, - $(P Nested functions and class member functions can be referenced - with closures (also called delegates), making generic programming - much easier and type safe. - ) + $(P Nested functions and class member functions can be referenced + with closures (also called delegates), making generic programming + much easier and type safe. + ) ) $(SECTION4 In$(COMMA) Out$(COMMA) and Ref Parameters, - $(P Not only does specifying this help make functions more - self-documenting, it eliminates much of the necessity for pointers - without sacrificing anything, and it opens up possibilities - for more compiler help in finding coding problems. - ) + $(P Not only does specifying this help make functions more + self-documenting, it eliminates much of the necessity for pointers + without sacrificing anything, and it opens up possibilities + for more compiler help in finding coding problems. + ) - $(P Such makes it possible for D to directly interface to a - wider variety of foreign API's. There would be no need for - workarounds like "Interface Definition Languages". - ) + $(P Such makes it possible for D to directly interface to a + wider variety of foreign APIs. There would be no need for + workarounds like "Interface Definition Languages". + ) ) ) -$(SECTION3 Arrays, +$(SECTION3 $(LNAME2 arrays, Arrays), - $(P C arrays have several faults that can be corrected: - ) + $(P C arrays have several faults that can be corrected: + ) - $(UL + $(UL - $(LI Dimension information is not carried around with - the array, and so has to be stored and passed separately. - The classic example of this are the argc and argv - parameters to $(D main(int $(D_PARAM argc), char *$(D_PARAM argv)[])). - (In D, main is declared as $(D main(char[][] $(D_PARAM args))).) - ) + $(LI Dimension information is not carried around with + the array, and so has to be stored and passed separately. + The classic example of this are the argc and argv + parameters to $(D main(int $(D_PARAM argc), char *$(D_PARAM argv)[])). + (In D, main is declared as $(D main(string[] $(D_PARAM args))).) + ) - $(LI Arrays are not first class objects. When an array is passed to a function, it is - converted to a pointer, even though the prototype confusingly says it's an - array. When this conversion happens, all array type information - gets lost. - ) + $(LI Arrays are not first class objects. When an array is passed to a function, it is + converted to a pointer, even though the prototype confusingly says it's an + array. When this conversion happens, all array type information + gets lost. + ) - $(LI C arrays cannot be resized. This means that even simple aggregates like a stack - need to be constructed as a complex class.) + $(LI C arrays cannot be resized. This means that even simple aggregates like a stack + need to be constructed as a complex class.) - $(LI C arrays cannot be bounds checked, because they don't know - what the array bounds are.) + $(LI C arrays cannot be bounds checked, because they don't know + what the array bounds are.) - $(LI Arrays are declared with the [] after the identifier. This leads to - very clumsy - syntax to declare things like a pointer to an array: + $(LI Arrays are declared with the [] after the identifier. This leads to + very clumsy + syntax to declare things like a pointer to an array: $(CCODE int (*array)[3]; ) - $(P In D, the [] for the array go on the left: - ) + $(P In D, the [] for the array go on the left: + ) ----------------------- -int[3]* array; // declares a pointer to an array of 3 ints -long[] func(int x); // declares a function returning an array of longs +int[3]* array; // declares a pointer to an array of 3 ints +long[] func(int x); // declares a function returning an array of longs ----------------------- - $(P which is much simpler to understand. - ) - ) - ) + $(P which is much simpler to understand. + ) + ) + ) - $(P D arrays come in several varieties: pointers, static arrays, dynamic - arrays, and associative arrays. - ) + $(P D arrays come in several varieties: pointers, static arrays, dynamic + arrays, and associative arrays. + ) - $(P See $(LINK2 arrays.html, Arrays). - ) + $(P See the $(LINK2 spec/arrays.html, Arrays) page for more information. + ) $(SECTION4 Strings, - $(P String manipulation is so common, and so clumsy in C and C++, that - it needs direct support in the language. Modern languages handle - string concatenation, copying, etc., and so does D. Strings are - a direct consequence of improved array handling. - ) + $(P String manipulation + needs direct support in the language. Modern languages handle + string concatenation, copying, etc., and so does D. Strings are + a direct consequence of improved array handling. + ) + ) +) + + +$(SECTION3 $(LNAME2 ranges, Ranges), + $(P D uses the concept of a range in lieu of iterators or generators found in + other languages. A range is any type that provides a common interface to a + sequence of values. The purpose of a range is to allow for a simpler way to + write code that works on arbitrary data, thereby making it reusable. + ) + + $(P The most basic type of range is called an input range, + which provides three methods. + ) + +----------------------- +struct MyRange +{ + auto front() + { + // return the next value in the sequence + } + + void popFront() + { + // move the front of the sequence to the next value + } + + bool empty() + { + // true if the range has no more values to return + } +} +----------------------- + + $(P To understand the power of this simple interface, let's run through an + example. Say we wanted to write a program that took all of the employees in + a company, took out the ones younger than 40, and grouped the remaining into + an array of arrays by their organization. + ) + +----------------------- +struct Employee +{ + uint id; + uint organization_id; + string name; + uint age; +} + +struct Employees +{ + Employee[] data; + + this(Employee[] employees) + { + data = employees; + } + + Employee front() + { + return data[0]; + } + + void popFront() + { + data = data[1 .. $]; + } + + bool empty() + { + return data.length == 0; + } +} +----------------------- + + $(P Here the data is coming from a constructor as a simple example, but it + could come from any source, like a CSV or a database. + ) + + $(P Please note that this code should not be used in actual code, because in D, + the basic dynamic array also acts as a range, so any algorithm that accepts + ranges also accepts arrays. However, static arrays are not considered ranges, + as the operation $(D popFront) is based on mutating the length of the range, + which is impossible with static arrays. To get a range out of a static array, + create a slice containing all of its elements, like so: + ) + +----------------------- +int[4] array = [1, 2, 3, 4]; // not a range +array[]; // valid range +----------------------- + + + $(P Now that the range is defined, we can populate it and write the filtering code. + ) + +----------------------- +void main() +{ + import std.algorithm.iteration : filter, chunkBy; + + Employees employees = Employees([ + Employee(1, 1, "George", 50), + Employee(2, 3, "John", 65), + Employee(3, 2, "David", 40), + Employee(4, 1, "Eli", 40), + Employee(5, 2, "Hal", 35) + ]); + + auto older_employees = employees + .filter!(a => a.age > 40) // lambdas in D use the => syntax + .chunkBy!((a,b) => a.organization_id == b.organization_id); +} +----------------------- + + $(P All of the algorithms in std.algorithm work with ranges to avoid the + problem of rewriting common functionality for every project. std.algorithm + implements sorts, filters, maps, reductions, and more. + ) + + $(P Because our Employees struct conforms to the input range definition, + it can also be used in $(D foreach) loops, which automatically detects if the + value passed is an input range. + ) + +----------------------- +foreach(employee; employees) +{ + writeln(employee); +} +----------------------- + + $(P which is equivalent to) + +----------------------- +for(; !employees.empty; employees.popFront()) +{ + writeln(employees.front); +} +----------------------- + + $(SECTION4 Types of Ranges, + $(P The input range is just the most basic form of range, there are also + ) + + $(UL + $(LI forward ranges) + $(LI bidirectional ranges) + $(LI random access ranges) + $(LI output ranges) + ) + + $(P Each of these ranges represents a distinct way of accessing the + underlying data. Or, in the case of the output range, a way to send data + to another source. To learn more about each type of range, see the + $(MREF_ALTTEXT range primitives, std, range, primitives) + page in the standard library documentation. + ) + + $(P Each of these types of ranges give you access to different algorithms + in the standard library. For example, a filter can be run on an input + range, but not a sort, which requires a random access range with the + slice operator overload defined. The requirements for each function can + be seen in the function signature in the documentation in the template + constraints. See the $(LINK2 spec/template.html, template) + page and the range primitives link above for more details on template + constraints. + ) + + $(P As stated before, dynamic arrays and associative arrays in D act + as ranges. Specifically, they are random access ranges, so any of the + functions in std.algorithm work with these basic types. + ) + ) + + $(SECTION4 Advanced Range Code, + $(P The following example uses input ranges and an output range to take + data from stdin, take only the unique lines, sort them, and then print + the result to stdout. + ) + +----------------------- +// Sort lines +import std.stdio; +import std.array; +import std.algorithm; + +void main() +{ + stdin + .byLine(KeepTerminator.yes) + .uniq + .map!(a => a.idup) + .array + .sort + .copy(stdout.lockingTextWriter()); +----------------------- + + $(P For more examples of range based code, see the + $(LINK2 http://ddili.org/ders/d.en/ranges.html, Ranges) chapter in Ali + Çehreli's book "Programming In D". Also, see the article + $(LINK2 https://wiki.dlang.org/Component_programming_with_ranges, + Component programming with ranges) by H. S. Teoh. + ) ) + ) -$(SECTION3 Resource Management, +$(SECTION3 $(LNAME2 resource, Resource Management), $(SECTION4 Automatic Memory Management, - $(P D memory allocation is fully garbage collected. Empirical experience - suggests that a lot of the complicated features of C++ are necessary - in order to manage memory deallocation. With garbage collection, the - language gets much simpler. - ) - - $(P There's a perception that garbage collection is for lazy, junior - programmers. I remember when that was said about C++, after all, - there's nothing in C++ that cannot be done in C, or in assembler - for that matter. - ) - - $(P Garbage collection eliminates the tedious, error prone memory - allocation - tracking code necessary in C and C++. This not only means much - faster development time and lower maintenance costs, - but the resulting program frequently runs - faster! - ) - - $(P Sure, garbage collectors can be used with C++, and I've used them - in my own C++ projects. The language isn't friendly to collectors, - however, impeding the effectiveness of it. Much of the runtime - library code can't be used with - collectors. - ) - - $(P For a fuller discussion of this, see - $(LINK2 garbage.html, garbage collection). - ) + $(P D memory allocation is fully garbage collected. + With garbage collection, programming gets much simpler. + Garbage collection eliminates the need for tedious, error prone memory + allocation tracking code. This not only means much + faster development time and lower maintenance costs, + but the resulting program frequently runs + faster. + ) + + $(P For a fuller discussion of this, see + $(LINK2 spec/garbage.html, garbage collection). + ) ) $(SECTION4 Explicit Memory Management, - $(P Despite D being a garbage collected language, the new and delete - operations can be overridden for particular classes so that - a custom allocator can be used. - ) + $(P Despite D being a garbage collected language, the new and delete + operations can be overridden for particular classes so that + a custom allocator can be used. + ) ) $(SECTION4 RAII, - $(P RAII is a modern software development technique to manage resource - allocation and deallocation. D supports RAII in a controlled, - predictable manner that is independent of the garbage collection - cycle. - ) + $(P RAII is a modern software development technique to manage resource + allocation and deallocation. D supports RAII in a controlled, + predictable manner that is independent of the garbage collection + cycle. + ) ) ) -$(SECTION3 Performance, +$(SECTION3 $(LNAME2 performance, Performance), $(SECTION4 Lightweight Aggregates, - $(P D supports simple C style structs, both for compatibility with - C data structures and because they're useful when the full power - of classes is overkill. - ) + $(P D supports simple C style structs, both for compatibility with + C data structures and because they're useful when the full power + of classes is overkill. + ) ) $(SECTION4 Inline Assembler, - $(P Device drivers, high performance system applications, embedded systems, - and specialized code sometimes need to dip into assembly language - to get the job done. While D implementations are not required - to implement the inline assembler, it is defined and part of the - language. Most assembly code needs can be handled with it, - obviating the need for separate assemblers or DLL's. - ) + $(P Device drivers, high performance system applications, embedded systems, + and specialized code sometimes need to dip into assembly language + to get the job done. While D implementations are not required + to implement the inline assembler, it is defined and part of the + language. Most assembly code needs can be handled with it, + obviating the need for separate assemblers or DLLs. + ) + + $(P Many D implementations will also support intrinsic functions + analogously to C's support of intrinsics for I/O port manipulation, + direct access to special floating point operations, etc. + ) + ) - $(P Many D implementations will also support intrinsic functions - analogously to C's support of intrinsics for I/O port manipulation, - direct access to special floating point operations, etc. - ) + $(P See the $(LINK2 spec/iasm.html, Inline Assembler) + page for more information. ) ) -$(SECTION3 Reliability, +$(SECTION3 $(LNAME2 reliability, Reliability), - $(P A modern language should do all it can to help the programmer flush - out bugs in the code. Help can come in many forms; - from making it easy to use more robust techniques, - to compiler flagging of obviously incorrect code, to runtime checking. - ) + $(P A modern language should do all it can to help the programmer flush + out bugs in the code. Help can come in many forms; + from making it easy to use more robust techniques, + to compiler flagging of obviously incorrect code, to runtime checking. + ) $(SECTION4 Contracts, - $(P Contract Programming (invented by B. Meyer) is a revolutionary - technique - to aid in ensuring the correctness of programs. D's version of - DBC includes function preconditions, function postconditions, class - invariants, and assert contracts. - See $(LINK2 dbc.html, Contracts) for D's implementation. - ) + $(P $(LINK2 https://en.wikipedia.org/wiki/Design_by_contract, Contract Programming) + (invented by Dr. Bertrand Meyer) is a + technique + to aid in ensuring the correctness of programs. D's version of + Contracts includes function preconditions, function postconditions, class + invariants, and assert contracts. + See $(LINK2 spec/contracts.html, Contracts) for D's implementation. + ) ) $(SECTION4 Unit Tests, - $(P Unit tests can be added to a class, such that they are automatically - run upon program startup. This aids in verifying, in every build, - that class implementations weren't inadvertently broken. The unit - tests form part of the source code for a class. Creating them - becomes a natural part of the class development process, as opposed - to throwing the finished code over the wall to the testing group. - ) - - $(P Unit tests can be done in other languages, but the result is kludgy - and the languages just aren't accommodating of the concept. - Unit testing is a main feature of D. For library functions it works - out great, serving both to guarantee that the functions - actually work and to illustrate how to use the functions. - ) - - $(P Consider the many C++ library and application code bases out there for - download on the web. How much of it comes with *any* verification - tests at all, let alone unit testing? Less than 1%? The usual practice - is if it compiles, we assume it works. And we wonder if the warnings - the compiler spits out in the process are real bugs or just nattering - about nits. - ) - - $(P Along with Contract Programming, unit testing makes D far and away - the best language for writing reliable, robust systems applications. - Unit testing also gives us a quick-and-dirty estimate of the quality - of some unknown piece of D code dropped in our laps - if it has no - unit tests and no contracts, it's unacceptable. - ) + $(P Unit tests can be added to a class, such that they are automatically + run upon program startup. This aids in verifying, in every build, + that class implementations weren't inadvertently broken. The unit + tests form part of the source code for a class. Creating them + becomes a natural part of the class development process, as opposed + to throwing the finished code over the wall to the testing group. + ) + + $(P Unit tests can be done in other languages, but the result is kludgy + and the languages just aren't accommodating of the concept. + Unit testing is a main feature of D. For library functions it works + out great, serving both to guarantee that the functions + actually work and to illustrate how to use the functions. + ) + + $(P Consider the many library and application code bases out there for + download on the web. How much of it comes with *any* verification + tests at all, let alone unit testing? The usual practice + is if it compiles, we assume it works. And we wonder if the warnings + the compiler spits out in the process are real bugs or just nattering + about nits. + ) + + $(P Along with Contract Programming, unit testing makes D far and away + the best language for writing reliable, robust systems applications. + Unit testing also gives us a quick-and-dirty estimate of the quality + of some unknown piece of D code dropped in our laps - if it has no + unit tests and no contracts, it's unacceptable. + ) + ) + + $(P See the $(LINK2 spec/unittest.html, Unit Tests) + page for more information. ) $(SECTION4 Debug Attributes and Statements, - $(P Now debug is part of the syntax of the language. - The code can be enabled or disabled at compile time, without the - use of macros or preprocessing commands. The debug syntax enables - a consistent, portable, and understandable recognition that real - source code needs to be able to generate both debug compilations and - release compilations. - ) + $(P Now debug is part of the syntax of the language. + The code can be enabled or disabled at compile time, without the + use of macros or preprocessing commands. The debug syntax enables + a consistent, portable, and understandable recognition that real + source code needs to be able to generate both debug compilations and + release compilations. + ) ) $(SECTION4 Exception Handling, - $(P The superior $(I try-catch-finally) model is used rather than just - try-catch. There's no need to create dummy objects just to have - the destructor implement the $(I finally) semantics. - ) + $(P The superior $(I try-catch-finally) model is used rather than just + try-catch. There's no need to create dummy objects just to have + the destructor implement the $(I finally) semantics. + ) ) $(SECTION4 Synchronization, - $(P Multithreaded programming is becoming more and more mainstream, - and D provides primitives to build multithreaded programs with. - Synchronization can be done at either the method or the object level. - ) + $(P Multithreaded programming is becoming more and more mainstream, + and D provides primitives to build multithreaded programs with. + Synchronization can be done at either the method or the object level. + ) ----------------------- synchronized int func() { ... } ----------------------- - $(P Synchronized functions allow only one thread at a time to be - executing that function. - ) + $(P Synchronized functions allow only one thread at a time to be + executing that function. + ) - $(P The synchronize statement puts a mutex around a block of statements, - controlling access either by object or globally. - ) + $(P The synchronize statement puts a mutex around a block of statements, + controlling access either by object or globally. + ) ) $(SECTION4 Support for Robust Techniques, - $(UL - $(LI Dynamic arrays instead of pointers) + $(UL + $(LI Dynamic arrays instead of pointers) - $(LI Reference variables instead of pointers) + $(LI Reference variables instead of pointers) - $(LI Reference objects instead of pointers) + $(LI Reference objects instead of pointers) - $(LI Garbage collection instead of explicit memory management) + $(LI Garbage collection instead of explicit memory management) - $(LI Built-in primitives for thread synchronization) + $(LI Built-in primitives for thread synchronization) - $(LI No macros to inadvertently slam code) + $(LI No macros to inadvertently slam code) - $(LI Inline functions instead of macros) + $(LI Inline functions instead of macros) - $(LI Vastly reduced need for pointers) + $(LI Vastly reduced need for pointers) - $(LI Integral type sizes are explicit) + $(LI Integral type sizes are explicit) - $(LI No more uncertainty about the signed-ness of chars) + $(LI No more uncertainty about the signed-ness of chars) - $(LI No need to duplicate declarations in source and header files.) + $(LI No need to duplicate declarations in source and header files.) - $(LI Explicit parsing support for adding in debug code.) - ) + $(LI Explicit parsing support for adding in debug code.) + ) ) $(SECTION4 Compile Time Checks, - $(UL - $(LI Stronger type checking) + $(UL + $(LI Stronger type checking) - $(LI No empty ; for loop bodies) + $(LI No empty ; for loop bodies) - $(LI Assignments do not yield boolean results) + $(LI Assignments do not yield boolean results) - $(LI Deprecating of obsolete API's) - ) + $(LI Deprecating of obsolete APIs) + ) ) $(SECTION4 Runtime Checking, - $(UL - $(LI assert() expressions) + $(UL + $(LI assert() expressions) - $(LI array bounds checking) + $(LI array bounds checking) - $(LI undefined case in switch exception) + $(LI undefined case in switch exception) - $(LI out of memory exception) + $(LI out of memory exception) - $(LI In, out, and class invariant Contract Programming support) - ) + $(LI In, out, and class invariant Contract Programming support) + ) ) ) -$(SECTION3 Compatibility, +$(SECTION3 $(LNAME2 compatibility, Compatibility), $(SECTION4 Operator precedence and evaluation rules, - $(P D retains C operators and their precedence rules, order of - evaluation rules, and promotion rules. This avoids subtle - bugs that might arise from being so used to the way C - does things that one has a great deal of trouble finding - bugs due to different semantics. - ) + $(P D retains C operators and their precedence rules, order of + evaluation rules, and promotion rules. This avoids subtle + bugs that might arise from being so used to the way C + does things that one has a great deal of trouble finding + bugs due to different semantics. + ) ) - $(SECTION4 Direct Access to C API's, + $(SECTION4 Direct Access to C APIs, - $(P Not only does D have data types that correspond to C types, - it provides direct access to C functions. There is no need - to write wrapper functions, parameter swizzlers, nor code to copy - aggregate members one by one. - ) + $(P Not only does D have data types that correspond to C types, + it provides direct access to C functions. There is no need + to write wrapper functions, parameter swizzlers, nor code to copy + aggregate members one by one. + ) ) $(SECTION4 Support for all C data types, - $(P Making it possible to interface to any C API or existing C - library code. This support includes structs, unions, enums, - pointers, and all C99 types. - D includes the capability to - set the alignment of struct members to ensure compatibility with - externally imposed data formats. - ) + $(P Making it possible to interface to any C API or existing C + library code. This support includes structs, unions, enums, + pointers, and all C99 types. + D includes the capability to + set the alignment of struct members to ensure compatibility with + externally imposed data formats. + ) ) $(SECTION4 OS Exception Handling, - $(P D's exception handling mechanism will connect to the way - the underlying operating system handles exceptions in - an application. - ) + $(P D's exception handling mechanism will connect to the way + the underlying operating system handles exceptions in + an application. + ) ) $(SECTION4 Uses Existing Tools, - $(P D produces code in standard object file format, enabling the use - of standard assemblers, linkers, debuggers, profilers, exe compressors, - and other analyzers, as well as linking to code written in other - languages. - ) + $(P D produces code in standard object file format, enabling the use + of standard assemblers, linkers, debuggers, profilers, exe compressors, + and other analyzers, as well as linking to code written in other + languages. + ) ) ) -$(SECTION3 Project Management, +$(SECTION3 $(LNAME2 management, Project Management), $(SECTION4 Versioning, - $(P D provides built-in support for generation of multiple versions - of a program from the same text. It replaces the C preprocessor - #if/#endif technique. - ) + $(P D provides built-in support for generation of multiple versions + of a program from the same text. It replaces the C preprocessor + #if/#endif technique. + ) ) $(SECTION4 Deprecation, - $(P As code evolves over time, some old library code gets replaced - with newer, better versions. The old versions must be available - to support legacy code, but they can be marked as $(I deprecated). - Code that uses deprecated versions will be normally flagged - as illegal, but would be allowed by a compiler switch. - This will make it easy for maintenance - programmers to identify any dependence on deprecated features. - ) + $(P As code evolves over time, some old library code gets replaced + with newer, better versions. The old versions must be available + to support legacy code, but they can be marked as $(I deprecated). + Code that uses deprecated versions will be normally flagged + as illegal, but would be allowed by a compiler switch. + This will make it easy for maintenance + programmers to identify any dependence on deprecated features. + ) ) ) ) -$(SECTION2 Sample D Program (sieve.d), - --------------------------- +$(SECTION2 $(LNAME2 sample, Sample D Program (sieve.d)), +---- /* Sieve of Eratosthenes prime numbers */ import std.stdio; -bool[8191] flags; - -int main() -{ int i, count, prime, k, iter; - - writefln("10 iterations"); - for (iter = 1; iter <= 10; iter++) - { count = 0; - flags[] = 1; - for (i = 0; i < flags.length; i++) - { if (flags[i]) - { prime = i + i + 3; - k = i + prime; - while (k < flags.length) - { - flags[k] = 0; - k += prime; - } - count += 1; - } - } +void main() +{ + size_t count; + bool[8191] flags; + + writeln("10 iterations"); + + // using iter as a throwaway variable + foreach (iter; 1 .. 11) + { + count = 0; + flags[] = 1; + + foreach (index, flag; flags) + { + if (flag) + { + size_t prime = index + index + 3; + size_t k = index + prime; + + while (k < flags.length) + { + flags[k] = 0; + k += prime; + } + + count += 1; + } + } } + writefln("%d primes", count); - return 0; } --------------------------- -) +---- +$(P NB: The expectation may be that array index $(D x) represents the number x, with $(D i + i + 3) seeming odd at first glance. + +However, if one were to consider each index, it would mean that the first element would represent 0 + 0 + 3 = 3; +the second element would represent 1 + 1 + 3 = 5; +the third element would represent 2 + 2 + 3 = 7; +and so on. + +So the numbers represented by the array actually go from 3 to (8190 + 8190 + 3), or 16383. +) +) ) Macros: - TITLE=Overview - WIKI=Overview - CATEGORY_OVERVIEW=$0 + TITLE=Overview diff --git a/pdf-intro-cover.dd b/pdf-intro-cover.dd deleted file mode 100644 index 55c7e55ce5..0000000000 --- a/pdf-intro-cover.dd +++ /dev/null @@ -1,15 +0,0 @@ -Ddoc - -$(PDF_COVER - -

    Introduction to the D Programming Language $(VER)

    - -
    -

    Published $(DATETIME)

    -

    Copyright © 1999-$(YEAR) by Digital Mars ®, All Rights Reserved.

    -
    - -) - -Macros: - TITLE=Introduction diff --git a/pdf-spec-cover.dd b/pdf-spec-cover.dd deleted file mode 100644 index 0396036189..0000000000 --- a/pdf-spec-cover.dd +++ /dev/null @@ -1,15 +0,0 @@ -Ddoc - -$(PDF_COVER - -

    The D Programming Language $(VER) Specification

    - -
    -

    Published $(DATETIME)

    -

    Copyright © 1999-$(YEAR) by Digital Mars ®, All Rights Reserved.

    -
    - -) - -Macros: - TITLE=Specification diff --git a/pdf-tools-cover.dd b/pdf-tools-cover.dd deleted file mode 100644 index 321c8e01f4..0000000000 --- a/pdf-tools-cover.dd +++ /dev/null @@ -1,15 +0,0 @@ -Ddoc - -$(PDF_COVER - -

    The D Programming Language $(VER) Tool Reference

    - -
    -

    Published $(DATETIME)

    -

    Copyright © 1999-$(YEAR) by Digital Mars ®, All Rights Reserved.

    -
    - -) - -Macros: - TITLE=Tool Reference diff --git a/plaintext.ddoc b/plaintext.ddoc new file mode 100644 index 0000000000..ced94c62b0 --- /dev/null +++ b/plaintext.ddoc @@ -0,0 +1,90 @@ +_=****************************************************************************** +_=Macros that generate a plain text document without any formatting. These are +_=useful for e.g. indexing, summarization, extracting word counts etc. +_=****************************************************************************** + +B = $0 +BIG = $0 +BLACK = $0 +BLUE = $0 +BR = +$0 +DD = $0 +DL = $0 +DT = $0 +GREEN = $0 +I = $0 +LI = $0 +LINK = $0 +LINK2 = $+ +LPAREN = ( +OL = $0 +P = $0 +RPAREN = ) +RED = $0 +SMALL = $0 +TABLE = $0 +TD = $0 +TH = $0 +TR = $0 +U = $0 +UL = $0 +WHITE = $0 +YELLOW = $0 +_= + +D_CODE = $0 +OTHER_CODE = $+ +D_COMMENT = $0 +D_STRING = $0 +D_KEYWORD = $0 +D_PSYMBOL = $0 +D_PARAM = $0 +_= + +DDOC = $(BODY)$(LF) +DDOC_ANCHOR = $0 +DDOC_AUTHORS = $0 +DDOC_BLANKLINE = $(BR) +DDOC_BUGS = $0$(LF) +DDOC_CLASS_MEMBERS = $0$(LF) +DDOC_COMMENT = $0 +DDOC_COPYRIGHT = $0 +DDOC_DATE = $0 +DDOC_DECL = $0 +DDOC_DECL_DD = $0 +DDOC_DEPRECATED = $0 +DDOC_DESCRIPTION = $0 +DDOC_DITTO = $0 +DDOC_ENUM_MEMBERS = $0 +DDOC_EXAMPLES = $0 +DDOC_HEADER_ANCHOR = +DDOC_HISTORY = $0 +DDOC_KEYWORD = $0 +DDOC_LICENSE = $0 +DDOC_MEMBER = $0 +DDOC_MEMBERS = $0 +DDOC_MEMBER_HEADER = +DDOC_MODULE_MEMBERS = $0$(LF) +DDOC_PARAM_DESC = $0 +DDOC_PARAM = $0 +DDOC_PARAM_ID = $0$(LF) +DDOC_PARAM_ROW = $0$(LF) +DDOC_PARAMS = $0$(LF) +DDOC_PSYMBOL = $0 +DDOC_RETURNS = $0 +DDOC_SECTION = $0$(LF) +DDOC_SECTION_H = $0$(LF) +DDOC_SECTIONS = $0$(LF) +DDOC_SEE_ALSO = $0$(LF) +DDOC_STRUCT_MEMBERS = $0$(LF) +DDOC_SUMMARY = $0$(LF) +DDOC_STANDARDS = $0 +DDOC_TEMPLATE_MEMBERS = $0$(LF) +DDOC_THROWS = $0 +DDOC_UNDEFINED_MACRO = $(NOCOMMAS $+) +DDOC_VERSION = $0 +_= + +NOCOMMAS=$1 $(NOCOMMAS $+) +_ = diff --git a/portability.dd b/portability.dd deleted file mode 100644 index 993243f2d0..0000000000 --- a/portability.dd +++ /dev/null @@ -1,126 +0,0 @@ -Ddoc - -$(SPEC_S Portability Guide, - - $(P It's good software engineering practice to minimize gratuitous - portability problems in the code. - Techniques to minimize potential portability problems are: - ) - - $(UL - - $(LI The integral and floating type sizes should be considered as - minimums. - Algorithms should be designed to continue to work properly if the - type size increases.) - - $(LI Floating point computations can be carried out at a higher - precision than the size of the floating point variable can hold. - Floating point algorithms should continue to work properly if - precision is arbitrarily increased.) - - $(LI Avoid depending on the order of side effects in a computation - that may get reordered by the compiler. For example: - -------- -a + b + c -------- - - $(P can be evaluated as (a + b) + c, a + (b + c), (a + c) + b, (c + b) + a, - etc. Parentheses control operator precedence, parentheses do not - control order of evaluation. - ) - - $(P Function parameters can be evaluated either left to right - or right to left, depending on the particular calling conventions - used. - ) - - $(P If the operands of an associative operator + or * are floating - point values, the expression is not reordered. - ) - ) - - $(LI Avoid dependence on byte order; i.e. whether the CPU - is big-endian or little-endian.) - - $(LI Avoid dependence on the size of a pointer or reference being - the same size as a particular integral type.) - - $(LI If size dependencies are inevitable, put an $(D assert) in - the code to verify it: - -------- -assert(int.sizeof == (int*).sizeof); -------- - ) - ) - -

    32 to 64 Bit Portability

    - - $(P 64 bit processors and operating systems are here. - With that in mind: - ) - - $(UL - - $(LI Integral types will remain the same sizes between - 32 and 64 bit code.) - - $(LI Pointers and object references will increase in size - from 4 bytes to 8 bytes going from 32 to 64 bit code.) - - $(LI Use $(B size_t) as an alias for an unsigned integral - type that can span the address space. - Array indices should be of type $(B size_t).) - - $(LI Use $(B ptrdiff_t) as an alias for a signed integral - type that can span the address space. - A type representing the difference between two pointers - should be of type $(B ptrdiff_t).) - - $(LI The $(B .length), $(B .size), $(B .sizeof), $(B .offsetof) - and $(B .alignof) - properties will be of type $(B size_t).) - - ) - -

    Endianness

    - - $(P Endianness refers to the order in which multibyte types - are stored. The two main orders are $(I big endian) and - $(I little endian). - The compiler predefines the version identifier - $(B BigEndian) or $(B LittleEndian) depending on the order - of the target system. - The x86 systems are all little endian. - ) - - $(P The times when endianness matters are:) - - $(UL - $(LI When reading data from an external source (like a file) - written in a different - endian format.) - $(LI When reading or writing individual bytes of a multibyte - type like $(B long)s or $(B double)s.) - ) - -

    OS Specific Code

    - - $(P System specific code is handled by isolating the differences into - separate modules. At compile time, the correct system specific - module is imported. - ) - - $(P Minor differences can be handled by constant defined in a system - specific import, and then using that constant in an - $(I IfStatement) or $(I StaticIfStatement). - ) -) - -Macros: - TITLE=Portability - WIKI=Portability - CATEGORY_SPEC=$0 - diff --git a/posix.mak b/posix.mak index c66f9edb4b..688a5ec94e 100644 --- a/posix.mak +++ b/posix.mak @@ -1,242 +1,944 @@ -# Makefile to build the entire dlang.org website +# dlang.org Makefile +# ================== # -# To run: +# This Makefile is used to build the dlang.org website. +# To build the entire dlang.org website run: # -# make -f posix.mak all +# make -f posix.mak all # -# To also upload to the website: +# Build flavors +# ------------- # -# make -f posix.mak rsync +# This makefile supports 3 flavors of documentation: # +# latest Latest released version (by git tag) +# prerelease Master (uses the D repositories as they exist locally) +# release Documentation build that is shipped with the binary release +# +# For `release` the LATEST version is not yet published at build time, +# hence a few things differ from a `prerelease` build. +# +# To build `latest` and `prerelease` docs: +# +# make -f posix.mak all +# +# To build `release` docs: +# +# make -f posix.mak release +# +# Individual documentation targets +# -------------------------------- +# +# The entire documentation can be built with: +# +# make -f posix.mak docs +# +# This target is an alias for two targets: +# +# A) `docs-prerelease` (aka master) +# +# The respective local repositories are used. +# This is very useful for testing local changes. +# Individual targets include: +# +# dmd-prerelease +# druntime-prerelease +# phobos-prerelease +# apidocs-prerelease Ddox documentation +# +# B) `docs-latest` (aka stable) +# +# Based on the last official release (git tag), the repositories are freshly cloned from GitHub. +# Individual targets include: +# +# dmd-latest +# druntime-latest +# phobos-latest +# apidocs-latest Ddox documentation +# +# Documentation development Ddox web server +# ----------------------------------------- +# +# A development Ddox webserver can be started: +# +# make -f posix.mak apidocs-serve +# +# This web server will regenerate requested documentation pages on-the-fly +# and has the additional advantage that it doesn't need to build any +# documentation pages during its startup. +# +# Options +# ------- +# +# Commonly used options include: +# +# DIFFABLE=1 Removes inclusion of all dynamic content and timestamps +# CSS_MINIFY=1 Minify the CSS via an online service +# DOC_OUTPUT_DIR Folder to build the documentation (default: `web`) +# +# Other targets +# ------------- +# +# html Builds all HTML files and static content +# pending_changelog Collects and assembles the changelog for the next version +# (This is based on references Bugzilla issues and files +# in the `/changelog` folders) +# rebase Rebase all DLang repos to upstream/master +# kindle Generates the D specification as an ebook (Amazon mobi) +# verbatim Copies the Ddoc plaintext files to .verbatim files +# (i.e. doesn't run Ddoc on them) +# rsync Publishes the built website to dlang.org +# test Runs several sanity checks +# clean Removes the .generated folder +# diffable-intermediaries Adds intermediary eBook files to the output, useful for diffing +# dautotest Special target called by the DAutoTestCI and deployment +# +# Ddoc vs. Ddox +# -------------- +# +# It's a long-lasting effort to transition from the Ddoc documentation build +# to a Ddox documentation build of the D standard library. +# +# https://dlang.org/phobos Stable Ddoc build (`docs-latest`) +# https://dlang.org/phobos-prerelease Master Ddoc build (`docs-prerelease`) +# https://dlang.org/library Stable Ddox build (`apidocs-latest`) +# https://dlang.org/library-release Master Ddox build (`apidocs-prerelease`) +# +# For more documentation on Ddox, see https://github.com/rejectedsoftware/ddox +# For more information and current blocking points of the Ddoc -> Ddox tranisition, +# see https://github.com/dlang/dlang.org/pull/1526 +# +# Assert -> writeln magic +# ----------------------- +# +# There is a toolchain in place will allows to perform source code transformation. +# At the moment this is used to beautify the code examples. For example: +# +# assert(a == b) +# +# Would be rewritten to: +# +# writeln(a); // b +# +# For this local copies of the respective DMD, DRuntime, and Phobos are stored +# in the build folder `.generated`, s.t. Ddoc can be run on the modified sources. +# +# See also: https://dlang.org/blog/2017/03/08/editable-and-runnable-doc-examples-on-dlang-org +# +# Custom DDoc wrapper +# ------------------- +# +# `ddoc.d` is a wrapper around Ddoc and allows expanding Ddoc macros dynamically +# before actually running Ddoc. +# Currently this is used for: +# - TOC +# - dynamic TOC generation +# - GRAMMAR overview generation +# - CHANGELOG menu generation +# - assert -> writeln magic +PWD=$(shell pwd) +MAKEFILE=$(firstword $(MAKEFILE_LIST)) +SHELL:=/bin/bash + +# Latest released version +ifeq (,${LATEST}) + LATEST:=$(shell cat VERSION) +endif -# Externals -DMD=dmd +# DLang directories DMD_DIR=../dmd PHOBOS_DIR=../phobos -DRUNTIME_DIR=../druntime -DOC_OUTPUT_DIR=./web -GIT_HOME=git@github.com:D-Programming-Language +DRUNTIME_DIR=../dmd/druntime +TOOLS_DIR=../tools +INSTALLER_DIR=../installer +DUB_DIR=../dub + +# Auto-cloning missing directories +$(shell [ ! -d $(DMD_DIR) ] && git clone --depth=1 ${GIT_HOME}/dmd $(DMD_DIR)) +include $(DMD_DIR)/compiler/src/osmodel.mak + +# External binaries +DMD=$(DMD_DIR)/generated/$(OS)/release/$(MODEL)/dmd +PHOBOS_LIB=$(PHOBOS_DIR)/generated/$(OS)/release/$(MODEL)/dmd/libphobos2.a + +# External directories +DOC_OUTPUT_DIR:=$(PWD)/web +W:=$(DOC_OUTPUT_DIR) +GIT_HOME=https://github.com/dlang +DPL_DOCS_PATH=dpl-docs +DPL_DOCS=$(DPL_DOCS_PATH)/dpl-docs +DPL_DOCS_FLAGS=--DRT-gcopt=parallel:0 +REMOTE_DIR=d-programming@digitalmars.com:data +TMP?=/tmp +GENERATED=.generated +G=$(GENERATED) + +# Last released versions +DMD_LATEST_DIR=$G/dmd-${LATEST} +DMD_LATEST=$(DMD_LATEST_DIR)/generated/$(OS)/release/$(MODEL)/dmd +DRUNTIME_LATEST_DIR=$G/dmd-${LATEST}/druntime +PHOBOS_LATEST_DIR=$G/phobos-${LATEST} + +# stable dub and dmd versions used to build dpl-docs +STABLE_DMD_VER=2.100.2 +STABLE_DMD_VER_SUFFIX= +STABLE_DMD_VER_PREFIX= +STABLE_DMD_ROOT=$(GENERATED)/stable_dmd-$(STABLE_DMD_VER)$(STABLE_DMD_VER_SUFFIX) +STABLE_DMD_URL=http://downloads.dlang.org/$(STABLE_DMD_VER_PREFIX)releases/2.x/$(STABLE_DMD_VER)/dmd.$(STABLE_DMD_VER)$(STABLE_DMD_VER_SUFFIX).$(OS).zip +STABLE_DMD_BIN_ROOT=$(STABLE_DMD_ROOT)/dmd2/$(OS)/$(if $(filter $(OS),osx),bin,bin$(MODEL)) +STABLE_DMD=$(STABLE_DMD_BIN_ROOT)/dmd +STABLE_DMD_CONF=$(STABLE_DMD).conf +STABLE_RDMD=$(STABLE_DMD_BIN_ROOT)/rdmd --compiler=$(STABLE_DMD) -conf=$(STABLE_DMD_CONF) +DUB=$(STABLE_DMD_BIN_ROOT)/dub + +# exclude lists +MOD_EXCLUDES_PRERELEASE=$(addprefix --ex=, \ + core.internal core.stdc.config core.sys \ + std.algorithm.internal std.c std.internal std.regex.internal \ + std.digest.digest \ + std.windows.registry etc.linux.memoryerror \ + std.typetuple \ + msvc_dmc msvc_lib \ + dmd.libmach dmd.libmscoff \ + dmd.scanmach dmd.scanmscoff \ + dmd.libmach dmd.libmscoff \ + dmd.scanmach dmd.scanmscoff) + +MOD_EXCLUDES_LATEST=$(MOD_EXCLUDES_PRERELEASE) +MOD_EXCLUDES_RELEASE=$(MOD_EXCLUDES_PRERELEASE) + +# rdmd must fetch the model, imports, and libs from the specified version +DFLAGS=-m$(MODEL) -I$(DRUNTIME_DIR)/import -I$(PHOBOS_DIR) -L-L$(PHOBOS_DIR)/generated/$(OS)/release/$(MODEL) +RDMD=rdmd --compiler=$(DMD) $(DFLAGS) + +# Tools +REBASE=MYBRANCH=`git rev-parse --abbrev-ref HEAD` && \ + git checkout master && \ + git pull --ff-only git@github.com:dlang/$1.git master && \ + git checkout $$MYBRANCH && \ + git rebase master + +CHANGE_SUFFIX = \ + for f in `find "$3" -iname '*.$1'`; do \ + mv $$f `dirname $$f`/`basename $$f .$1`.$2 ; \ + done + +# Disable all dynamic content that could potentially have an unrelated impact +# on a diff +ifeq (1,$(DIFFABLE)) + NODATETIME := nodatetime.ddoc + DPL_DOCS_PATH_RUN_FLAGS := --no-exact-source-links +else + CHANGELOG_VERSION_MASTER := "v${LATEST}..upstream/master" + CHANGELOG_VERSION_STABLE := "v${LATEST}..upstream/stable" +endif -# Latest released version -LATEST:=$(shell cd ${DMD_DIR} && git fetch --tags && \ -git tag | grep '^v[0-9]\.[0-9]*$$' | sed 's/^v//' | sort -nr | head -n 1) -$(info Current release: ${LATEST}) - -# Documents - -DDOC=macros.ddoc doc.ddoc ${LATEST}.ddoc - -IMAGES=favicon.ico $(addprefix images/, c1.gif cpp1.gif d002.ico \ -d3.gif d4.gif d5.gif debian_logo.png dlogo.png dmlogo.gif \ -dmlogo-smaller.gif download.png fedora_logo.png freebsd_logo.png \ -gradient-green.jpg gradient-red.jpg globe.gif linux_logo.png \ -mac_logo.png opensuse_logo.png pen.gif search-left.gif search-bg.gif \ -search-button.gif Thumbs.db tdpl.jpg ubuntu_logo.png win32_logo.png) - -STYLES=css/style.css css/print.css - -PREMADE=dcompiler.html language-reference.html appendices.html \ -howtos.html articles.html fetch-issue-cnt.php - -TARGETS=32-64-portability.html cpptod.html ctod.html download.html \ - pretod.html gsoc2011.html index.html overview.html spec.html \ - intro.html lex.html module.html declaration.html type.html \ - property.html attribute.html pragma.html expression.html \ - statement.html arrays.html struct.html class.html enum.html \ - function.html operatoroverloading.html template.html mixin.html \ - dbc.html version.html errors.html garbage.html memory.html \ - float.html iasm.html interface.html portability.html entity.html \ - abi.html windows.html dll.html htomodule.html faq.html \ - dstyle.html wc.html changelog.html glossary.html \ - acknowledgements.html builtin.html interfaceToC.html \ - comparison.html rationale.html ddoc.html code_coverage.html \ - exception-safe.html rdmd.html templates-revisited.html \ - warnings.html ascii-table.html windbg.html htod.html \ - regular-expression.html lazy-evaluation.html \ - variadic-function-templates.html howto-promote.html tuple.html \ - template-comparison.html template-mixin.html traits.html COM.html \ - cpp_interface.html hijack.html const3.html features2.html \ - safed.html const-faq.html concepts.html memory-safe-d.html \ - d-floating-point.html migrate-to-shared.html D1toD2.html \ - unittest.html hash-map.html pdf-intro-cover.html \ - pdf-spec-cover.html pdf-tools-cover.html intro-to-datetime.html \ - std_consolidated_header.html simd.html dmd-windows.html \ - dmd-linux.html dmd-freebsd.html dmd-osx.html bugstats.php - -PDFINTRO=index.html overview.html wc.html warnings.html builtin.html \ - ctod.html cpptod.html pretod.html template-comparison.html - -PDFFEATURES=comparison.html features2.html - -PDFFAQ=faq.html const-faq.html rationale.html - -PDFSPEC=spec.html intro.html lex.html module.html declaration.html \ - type.html property.html attribute.html pragma.html \ - expression.html statement.html arrays.html hash-map.html \ - struct.html class.html interface.html enum.html const3.html \ - function.html operatoroverloading.html template.html \ - template-mixin.html dbc.html version.html traits.html errors.html \ - unittest.html garbage.html float.html iasm.html ddoc.html \ - interfaceToC.html cpp_interface.html portability.html entity.html \ - memory-safe-d.html abi.html simd.html - -PDFHOWTOS=windows.html dll.html COM.html htomodule.html - -PDFARTICLES=d-floating-point.html migrate-to-shared.html hijack.html \ - const3.html memory.html exception-safe.html \ - templates-revisited.html regular-expression.html \ - lazy-evaluation.html variadic-function-templates.html tuple.html \ - mixin.html safed.html intro-to-datetime.html - -PDFTOOLS=dmd-linux.html dmd-freebsd.html dmd-osx.html dmd-windows.html \ - http://digitalmars.com/ctg/optlink.html \ - http://digitalmars.com/ctg/trace.html code_coverage.html rdmd.html \ - windbg.html htod.html - -PDFAPPENDICES=dstyle.html glossary.html ascii-table.html \ -acknowledgements.html - -PDFOPTIONS=--header-left [section] --header-right [page] \ ---header-spacing 3 --header-font-name Georgia --print-media-type \ ---outline - -PDFTARGETS=d-intro.pdf d-spec.pdf d-tools.pdf - -ALL_FILES_BUT_SITEMAP = $(addprefix $(DOC_OUTPUT_DIR)/, $(TARGETS) \ -$(PREMADE) $(STYLES) $(IMAGES)) - -ALL_FILES = $(ALL_FILES_BUT_SITEMAP) $(DOC_OUTPUT_DIR)/sitemap.html +################################################################################ +# Ddoc build variables +################################################################################ +DDOC_VARS_LATEST_HTML= \ + DOC_OUTPUT_DIR="$W/phobos" \ + STDDOC="$(addprefix $(PWD)/, $(STD_DDOC_LATEST))" \ + DMD="$(abspath $(DMD_LATEST))" \ + DMD_DIR="$(abspath ${DMD_LATEST_DIR})" \ + DRUNTIME_PATH="$(abspath ${DRUNTIME_LATEST_DIR})" \ + DOCSRC="$(PWD)" \ + VERSION="$(abspath ${DMD_DIR}/VERSION)" + +DDOC_VARS_RELEASE_HTML= \ + DOC_OUTPUT_DIR="$W/phobos" \ + STDDOC="$(addprefix $(PWD)/, $(STD_DDOC_RELEASE))" \ + DMD="$(abspath $(DMD))" \ + DMD_DIR="$(abspath ${DMD_DIR})" \ + DRUNTIME_PATH="$(abspath ${DRUNTIME_DIR})" \ + DOCSRC="$(PWD)" \ + VERSION="$(abspath ${DMD_DIR}/VERSION)" + +DDOC_VARS_PRERELEASE= \ + DMD="$(abspath ${DMD})" \ + DMD_DIR="$(abspath ${DMD_DIR})" \ + DRUNTIME_PATH="$(abspath ${DRUNTIME_DIR})" \ + DOCSRC="$(PWD)" \ + VERSION="$(abspath $G/changelog/next-version)" + +DDOC_VARS_PRERELEASE_HTML=$(DDOC_VARS_PRERELEASE) \ + DOC_OUTPUT_DIR="$W/phobos-prerelease" \ + STDDOC="$(addprefix $(PWD)/, $(STD_DDOC_PRERELEASE))" + +DDOC_VARS_PRERELEASE_VERBATIM=$(DDOC_VARS_PRERELEASE) \ + DOC_OUTPUT_DIR="$W/phobos-prerelease-verbatim" \ + STDDOC="$(PWD)/verbatim.ddoc" + +DDOCFLAGS=-c -o- -# Pattern rulez +################################################################################ +# Ddoc binaries +################################################################################ -$(DOC_OUTPUT_DIR)/%.html : %.dd $(DDOC) - $(DMD) -c -o- -Df$@ $(DDOC) $< +DDOC_BIN:=$G/ddoc_preprocessor +DDOC_BIN_DMD:=$(DDOC_BIN) --compiler=$(DMD) -$(DOC_OUTPUT_DIR)/%.php : %.php.dd $(DDOC) - $(DMD) -c -o- -Df$@ $(DDOC) $< +################################################################################ +# Resources +################################################################################ -$(DOC_OUTPUT_DIR)/% : % - @mkdir -p $(dir $@) - cp $< $@ +# Set to 1 in the command line to minify css files +CSS_MINIFY= + +IMAGES=favicon.ico images/d002.ico $(filter-out $(wildcard images/*_hq.*) images/dlogo_2015.svg, \ + $(wildcard images/*.jpg images/*.png images/*.svg images/*.gif)) \ + $(wildcard images/ddox/*) \ + $(filter-out $(wildcard images/orgs-using-d/*_hq.*), $(wildcard images/orgs-using-d/*)) + +JAVASCRIPT=$(addsuffix .js, $(addprefix js/, \ + codemirror-compressed dlang ddox listanchors platform-downloads run \ + run_examples show_contributors jquery-1.7.2.min)) -$(DOC_OUTPUT_DIR)/dmd-%.html : %.ddoc dcompiler.dd $(DDOC) - $(DMD) -c -o- -Df$@ $(DDOC) dcompiler.dd $< +STYLES=$(addsuffix .css, $(addprefix css/, \ + style print codemirror ddox)) + +################################################################################ +# HTML Files +################################################################################ + +DDOC=$(addsuffix .ddoc, macros html dlang.org keywords doc ${GENERATED}/${LATEST}) $(NODATETIME) $G/dblog_latest.ddoc +STD_DDOC_LATEST=$(addsuffix .ddoc, macros html keywords dlang.org ${GENERATED}/${LATEST} std std_navbar-release ${GENERATED}/modlist-${LATEST}) $(NODATETIME) +STD_DDOC_RELEASE=$(addsuffix .ddoc, macros html keywords dlang.org ${GENERATED}/${LATEST} std std_navbar-release ${GENERATED}/modlist-release) $(NODATETIME) +STD_DDOC_PRERELEASE=$(addsuffix .ddoc, macros html keywords dlang.org ${GENERATED}/${LATEST} std std_navbar-prerelease ${GENERATED}/modlist-prerelease) $(NODATETIME) +SPEC_DDOC=${DDOC} spec/spec.ddoc +CHANGELOG_DDOC=${DDOC} changelog/changelog.ddoc $(NODATETIME) +CHANGELOG_PRE_DDOC=${CHANGELOG_DDOC} changelog/prerelease.ddoc +CHANGELOG_PENDING_DDOC=${CHANGELOG_DDOC} changelog/pending.ddoc + +PREMADE=fetch-issue-cnt.php robots.txt .htaccess .dpl_rewrite_map.txt ads.txt \ + d-keyring.gpg d-keyring.gpg.sig d-security.asc + +# Language spec root filenames. They have extension .dd in the source +# and .html in the generated HTML. These are also used for the mobi +# book generation, for which reason the list is sorted by chapter. +SPEC_ROOT=$(addprefix spec/, \ + spec intro lex istring grammar module declaration type property attribute \ + pragma expression statement arrays hash-map struct class interface enum \ + const3 function operatoroverloading template template-mixin contracts \ + version traits errors unittest garbage float iasm ddoc \ + interfaceToC cpp_interface objc_interface portability entity memory-safe-d \ + abi simd betterc importc ob windows glossary legacy) +SPEC_DD=$(addsuffix .dd,$(SPEC_ROOT)) + +CHANGELOG_FILES:=$(basename $(subst _pre.dd,.dd,$(wildcard changelog/*.dd))) +ifneq (1,$(ENABLE_RELEASE)) + CHANGELOG_FILES+=changelog/pending +endif + +MAN_PAGE=docs/man/man1/dmd.1 + +ARTICLE_FILES=$(addprefix articles/, index builtin code_coverage const-faq \ + constraints cpptod ctarguments ctod d-array-article d-floating-point \ + exception-safe faq hijack intro-to-datetime lazy-evaluation \ + migrate-to-shared mixin pretod rationale regular-expression \ + safed templates-revisited variadic-function-templates warnings \ + cppcontracts template-comparison dll-linux \ + RefReturnScope dll-windows \ + ) + +# Website root filenames. They have extension .dd in the source +# and .html in the generated HTML. Save for the expansion of +# $(SPEC_ROOT), the list is sorted alphabetically. +PAGES_ROOT=$(SPEC_ROOT) 404 acknowledgements areas-of-d-usage $(ARTICLE_FILES) \ + ascii-table bugstats $(CHANGELOG_FILES) community comparison contributing \ + deprecate dmd dmd-freebsd dmd-linux dmd-osx dmd-windows \ + documentation download dstyle forum-template gpg_keys \ + howto-promote htod index install \ + menu orgs-using-d overview rdmd resources search security tuple wc windbg \ + $(addprefix foundation/, index about donate prman sponsors upb-scholarship) \ + $(addprefix gsoc/, gsoc2011 gsoc2012 gsoc2012-template gsoc2013 gsoc2013-template) + +# The contributors listing is dynamically generated +ifneq (1,$(DIFFABLE)) +ifneq (1,$(ENABLE_RELEASE)) + PAGES_ROOT+=foundation/contributors +endif +endif + +TARGETS=$(addsuffix .html,$(PAGES_ROOT)) + +ALL_FILES_BUT_SITEMAP = $(addprefix $W/, $(TARGETS) \ +$(PREMADE) $(STYLES) $(IMAGES) $(JAVASCRIPT) $(MAN_PAGE)) + +ALL_FILES = $(ALL_FILES_BUT_SITEMAP) $W/sitemap.html ################################################################################ # Rulez ################################################################################ -all : html phobos-prerelease druntime-prerelease druntime-release phobos-release +all : docs html -all+pdf : $(ALL_FILES) $(PDFTARGETS) +ifneq (1,$(ENABLE_RELEASE)) +release : + $(MAKE) -f $(MAKEFILE) ENABLE_RELEASE=1 release +else +release : html dmd-release druntime-release phobos-release d-release.tag +endif -html : $(ALL_FILES) +docs-latest: dmd-latest druntime-latest phobos-latest apidocs-latest +docs-prerelease: dmd-prerelease druntime-prerelease phobos-prerelease apidocs-prerelease -$(DOC_OUTPUT_DIR)/sitemap.html : $(ALL_FILES_BUT_SITEMAP) - cp -f sitemap-template.dd sitemap.dd - (true $(foreach F, $(TARGETS), \ - && echo \ - "$F\t`sed -n 's/\(.*\) - D Programming Language.*<\/title>/\1/'p $(DOC_OUTPUT_DIR)/$F`")) \ - | sort --ignore-case --key=2 | sed 's/^\([^ ]*\) \(.*\)/<a href="https://github.com/1">\2<\/a><p>/' >> sitemap.dd - $(DMD) -c -o- -Df$@ $(DDOC) sitemap.dd - rm -rf sitemap.dd +docs : docs-latest docs-prerelease + +html : html_files makebook + +html_files : $(ALL_FILES) -${LATEST}.ddoc : +makebook : book/build.d | $(STABLE_DMD) + cd book && PATH="$(abspath $(STABLE_DMD_BIN_ROOT)):$$PATH" rdmd build.d 6 + +html-verbatim: $(addprefix $W/, $(addsuffix .verbatim,$(PAGES_ROOT))) + +verbatim : html-verbatim phobos-prerelease-verbatim + +kindle : $W/dlangspec.mobi + +diffable-intermediaries : $W/dlangspec.html + +$W/sitemap.html : $(ALL_FILES_BUT_SITEMAP) $(DMD) + cp -f sitemap-template.dd $G/sitemap.dd + (true $(foreach F, $(TARGETS), \ + && echo \ + "$F `sed -n 's/<title>\(.*\) - D Programming Language.*<\/title>/\1/'p $W/$F`")) \ + | sort --ignore-case --key=2 | sed 's/^\([^ ]*\) \([^\n\r]*\)/<a href="https://github.com/1">\2<\/a><br>/' >> $G/sitemap.dd + $(DMD) -conf= $(DDOCFLAGS) -Df$@ $(DDOC) $G/sitemap.dd + rm $G/sitemap.dd + +${GENERATED}/${LATEST}.ddoc : + mkdir -p $(dir $@) echo "LATEST=${LATEST}" >$@ -zip: - rm doc.zip - zip32 doc win32.mak style.css $(DDOC) - zip32 doc $(SRC) download.html - zip32 doc $(IMG) +${GENERATED}/modlist-${LATEST}.ddoc : tools/modlist.d ${STABLE_DMD} $(DRUNTIME_LATEST_DIR) $(PHOBOS_LATEST_DIR) $(DMD_LATEST_DIR) + mkdir -p $(dir $@) + $(STABLE_RDMD) $< $(DRUNTIME_LATEST_DIR)/src $(PHOBOS_LATEST_DIR) $(DMD_LATEST_DIR)/compiler/src $(MOD_EXCLUDES_LATEST) \ + $(addprefix --internal=, dmd rt core.internal) \ + $(addprefix --dump , object std etc core dmd rt core.internal.array core.internal.util) >$@ + +${GENERATED}/modlist-release.ddoc : tools/modlist.d ${STABLE_DMD} $(DRUNTIME_DIR) $(PHOBOS_DIR) $(DMD_DIR) + mkdir -p $(dir $@) + $(STABLE_RDMD) $< $(DRUNTIME_DIR)/src $(PHOBOS_DIR) $(DMD_DIR)/compiler/src $(MOD_EXCLUDES_RELEASE) \ + $(addprefix --internal=, dmd rt core.internal) \ + $(addprefix --dump , object std etc core dmd rt core.internal.array core.internal.util) >$@ + +${GENERATED}/modlist-prerelease.ddoc : tools/modlist.d ${STABLE_DMD} $(DRUNTIME_DIR) $(PHOBOS_DIR) $(DMD_DIR) + mkdir -p $(dir $@) + $(STABLE_RDMD) $< $(DRUNTIME_DIR)/src $(PHOBOS_DIR) $(DMD_DIR)/compiler/src $(MOD_EXCLUDES_PRERELEASE) \ + $(addprefix --internal=, dmd rt core.internal) \ + $(addprefix --dump , object std etc core dmd rt core.internal.array core.internal.util) >$@ + +# Run "make -j rebase" for rebasing all dox in parallel! +rebase: rebase-dlang rebase-dmd rebase-phobos +rebase-dlang: ; $(call REBASE,dlang.org) +rebase-dmd: ; cd $(DMD_DIR) && $(call REBASE,dmd) +rebase-phobos: ; cd $(PHOBOS_DIR) && $(call REBASE,phobos) clean: - rm -rf $(DOC_OUTPUT_DIR) ${LATEST}.ddoc - @echo You should issue manually: rm -rf ${DMD_DIR}.${LATEST} ${DRUNTIME_DIR}.${LATEST} ${PHOBOS_DIR}.${LATEST} + rm -rf $W ${GENERATED} $(DPL_DOCS_PATH)/.dub $(DPL_DOCS) + +RSYNC_FILTER=-f 'P /Usage' -f 'P /.dpl_rewrite*' -f 'P /install.sh*' + +rsync : all kindle + rsync -avzO --chmod=u=rwX,g=rwX,o=rX --delete $(RSYNC_FILTER) $W/ $(REMOTE_DIR)/ + +rsync-only : + rsync -avzO --chmod=u=rwX,g=rwX,o=rX --delete $(RSYNC_FILTER) $W/ $(REMOTE_DIR)/ + +dautotest: all verbatim diffable-intermediaries d-latest.tag d-prerelease.tag + +################################################################################ +# Pattern rulez +################################################################################ + +# NOTE: Depending on the version of make, order matters here. Therefore, put +# sub-directories before their parents. + +$W/changelog/%.html : changelog/%_pre.dd $(CHANGELOG_PRE_DDOC) $(DDOC_BIN) | $(DMD) + $(DDOC_BIN_DMD) -conf= $(DDOCFLAGS) -Df$@ $(CHANGELOG_PRE_DDOC) $< + +$W/changelog/pending.html : changelog/pending.dd $(CHANGELOG_PENDING_DDOC) $(DDOC_BIN) | $(DMD) + $(DDOC_BIN_DMD) -conf= $(DDOCFLAGS) -Df$@ $(CHANGELOG_PENDING_DDOC) $< + +$W/changelog/%.html : changelog/%.dd $(CHANGELOG_DDOC) $(DDOC_BIN) | $(DMD) + $(DDOC_BIN_DMD) -conf= $(DDOCFLAGS) -Df$@ $(CHANGELOG_DDOC) $< -rsync : all - rsync -avz $(DOC_OUTPUT_DIR)/ d-programming@digitalmars.com:data/ +$W/spec/%.html : spec/%.dd $(SPEC_DDOC) $(DMD) $(DDOC_BIN) + $(DDOC_BIN_DMD) -Df$@ $(SPEC_DDOC) $< -pdf : $(PDFTARGETS) +$W/404.html : 404.dd $(DDOC) $(DMD) + $(DMD) -conf= $(DDOCFLAGS) -Df$@ $(DDOC) errorpage.ddoc $< -d-intro.pdf: - wkhtmltopdf $(PDFOPTIONS) cover pdf-intro-cover.html toc \ - $(addprefix $(DOC_OUTPUT_DIR)/, $(PDFINTRO)) $(addprefix \ - $(DOC_OUTPUT_DIR)/, $(PDFFEATURES)) $(addprefix \ - $(DOC_OUTPUT_DIR)/, $(PDFFAQ)) $(addprefix $(DOC_OUTPUT_DIR)/, \ - $(PDFAPPENDICES)) $(DOC_OUTPUT_DIR)/d-intro.pdf +$(DOC_OUTPUT_DIR)/foundation/contributors.html: foundation/contributors.dd \ + $G/contributors_list.ddoc foundation/foundation.ddoc $(DDOC) $(DMD) + $(DMD) -conf= $(DDOCFLAGS) -Df$@ $(DDOC) $(word 2, $^) $(word 3, $^) $< -d-spec.pdf: - wkhtmltopdf $(PDFOPTIONS) cover pdf-spec-cover.html toc \ - $(addprefix $(DOC_OUTPUT_DIR)/, $(PDFSPEC)) $(addprefix \ - $(DOC_OUTPUT_DIR)/, $(PDFAPPENDICES)) \ - $(DOC_OUTPUT_DIR)/d-spec.pdf +$W/articles/%.html : articles/%.dd $(DDOC) $(DMD) $(DDOC_BIN) articles/articles.ddoc + $(DDOC_BIN_DMD) -conf= $(DDOCFLAGS) -Df$@ $(DDOC) $< articles/articles.ddoc -d-tools.pdf: - wkhtmltopdf $(PDFOPTIONS) cover pdf-tools-cover.html toc \ - $(addprefix $(DOC_OUTPUT_DIR)/, $(PDFTOOLS)) $(addprefix \ - $(DOC_OUTPUT_DIR)/, $(PDFHOWTOS)) $(addprefix \ - $(DOC_OUTPUT_DIR)/, $(PDFARTICLES)) $(addprefix \ - $(DOC_OUTPUT_DIR)/, $(PDFAPPENDICES)) \ - $(DOC_OUTPUT_DIR)/d-tools.pdf +$W/foundation/%.html : foundation/%.dd $(DDOC) $(DMD) $(DDOC_BIN) foundation/foundation.ddoc + $(DDOC_BIN_DMD) -conf= $(DDOCFLAGS) -Df$@ $(DDOC) $< foundation/foundation.ddoc + +$W/%.html : %.dd $(DDOC) $(DMD) $(DDOC_BIN) + $(DDOC_BIN_DMD) -conf= $(DDOCFLAGS) -Df$@ $(DDOC) $< + +$W/%.verbatim : %_pre.dd verbatim.ddoc $(DDOC_BIN) + $(DDOC_BIN_DMD) $(DDOCFLAGS) -Df$@ verbatim.ddoc $< + +$W/%.verbatim : %.dd verbatim.ddoc $(DDOC_BIN) + $(DDOC_BIN_DMD) $(DDOCFLAGS) -Df$@ verbatim.ddoc $< + +$W/%.php : %.php.dd $(DDOC) $(DMD) + $(DMD) -conf= $(DDOCFLAGS) -Df$@ $(DDOC) $< + +$W/css/% : css/% + @mkdir -p $(dir $@) +ifeq (1,$(CSS_MINIFY)) + curl -X POST -fsS --data-urlencode 'input@$<' http://cssminifier.com/raw >$@ +else + cp $< $@ +endif + +$W/%.css : %.css.dd $(DMD) + $(DMD) $(DDOCFLAGS) -Df$@ $< + +$W/% : % + @mkdir -p $(dir $@) + cp $< $@ + +$W/dmd-%.html : %.ddoc dcompiler.dd $(DDOC) $(DDOC_BIN) + $(DDOC_BIN_DMD) -Df$@ $(DDOC) dcompiler.dd $< + +$W/dmd-%.verbatim : %.ddoc dcompiler.dd verbatim.ddoc $(DMD) + $(DMD) $(DDOCFLAGS) -Df$@ verbatim.ddoc dcompiler.dd $< + +$W: + mkdir -p $@ + +################################################################################ +# Ebook +################################################################################ + +$G/dlangspec.d : $(SPEC_DD) ${STABLE_DMD} + $(STABLE_RDMD) $(TOOLS_DIR)/catdoc.d -o$@ $(SPEC_DD) + +$G/dlangspec.html : $(DDOC) ebook.ddoc $G/dlangspec.d $(DMD) $(DDOC_BIN) + $(DDOC_BIN_DMD) -conf= -Df$@ $(DDOC) ebook.ddoc $G/dlangspec.d + +$G/dlangspec.zip : $G/dlangspec.html ebook.css + rm -f $@ + zip --junk-paths $@ $G/dlangspec.html ebook.css + +$W/dlangspec.mobi : \ + dlangspec.opf dlangspec.ncx dlangspec.png $G/dlangspec.html ebook.css + rm -f $@ $G/dlangspec.mobi dlangspec.html + # kindlegen has warnings, ignore them for now + -cp -f $G/dlangspec.html dlangspec.html; \ + trap "rm -f dlangspec.html" EXIT; \ + kindlegen dlangspec.opf + mv dlangspec.mobi $@ + +$W/dlangspec.html: $G/dlangspec.html | $W + cp $< $@ + +################################################################################ +# Plaintext/verbatim generation - not part of the build, demo purposes only +################################################################################ + +$G/dlangspec.txt : $G/dlangspec-consolidated.d $(DDOC_BIN) macros.ddoc plaintext.ddoc + $(DDOC_BIN_DMD) -conf= -Df$@ macros.ddoc plaintext.ddoc $< + +$G/dlangspec.verbatim.txt : $G/dlangspec-consolidated.d $(DDOC_BIN) verbatim.ddoc + $(DDOC_BIN_DMD) -conf= -Df$@ verbatim.ddoc $< + +################################################################################ +# Fetch the latest article from the official D blog +################################################################################ + +ifeq (1,$(DIFFABLE)) +$G/dblog_latest.xml: dblog_feed_example.xml + @echo "Create a dummy DBlog XML stream due to DIFFABLE=1" + cp $< $@ +else +$G/dblog_latest.xml: + @echo "Receiving the latest DBlog article. Disable with DIFFABLE=1" + curl -s --fail --retry 3 --retry-delay 5 -L http://feeds.feedburner.com/OfficialDBlog -o $@ +endif + +$G/dblog_latest.ddoc: $G/dblog_latest.xml $(STABLE_DMD) tools/ddoc_xml_extractor.d + $(STABLE_RDMD) tools/ddoc_xml_extractor.d -i $< -o $@ + +################################################################################ +# Git rules +################################################################################ + +# Druntime is in the DMD repository. +${DRUNTIME_DIR}: ${DMD_DIR} +${DRUNTIME_LATEST_DIR}: ${DMD_LATEST_DIR} + +# Clone snapshots of the latest official release of all main D repositories +$G/%-${LATEST} : + git clone -b v${LATEST} --depth=1 ${GIT_HOME}/$(notdir $*) $@ + +# Clone all main D repositories +${DMD_DIR} ${PHOBOS_DIR} ${TOOLS_DIR} ${INSTALLER_DIR} ${DUB_DIR}: + git clone ${GIT_HOME}/$(notdir $(@F)) $@ + +${DMD_DIR}/VERSION : ${DMD_DIR} ################################################################################ # dmd compiler, latest released build and current build ################################################################################ -${DMD_DIR}.${LATEST}/src/dmd : - [ -d ${DMD_DIR}.${LATEST} ] || \ - git clone ${GIT_HOME}/dmd ${DMD_DIR}.${LATEST}/ - cd ${DMD_DIR}.${LATEST} && git checkout v${LATEST} - make --directory=${DMD_DIR}.${LATEST}/src -f posix.mak clean - make --directory=${DMD_DIR}.${LATEST}/src -f posix.mak -j 4 +BUILD_JOBS_ARG:=$(if $(BUILD_JOBS),-j$(BUILD_JOBS),) + +$(DMD) : ${DMD_DIR} + bash ${DMD_DIR}/compiler/src/bootstrap.sh $(BUILD_JOBS_ARG) + +$(DMD_LATEST) : ${DMD_LATEST_DIR} + bash ${DMD_LATEST_DIR}/compiler/src/bootstrap.sh $(BUILD_JOBS_ARG) + sed -i -e "s|../druntime/import |../../dmd-${LATEST}/druntime/import |" -e "s|../phobos |../phobos-${LATEST} |" $@.conf + +dmd-prerelease : $(STD_DDOC_PRERELEASE) druntime-target $G/changelog/next-version + bash $(DMD_DIR)/compiler/src/bootstrap.sh html $(DDOC_VARS_PRERELEASE_HTML) $(BUILD_JOBS_ARG) -${DMD_DIR}/src/dmd : - [ -d ${DMD_DIR} ] || git clone ${GIT_HOME}/dmd ${DMD_DIR}/ - make --directory=${DMD_DIR}/src -f posix.mak clean - make --directory=${DMD_DIR}/src -f posix.mak -j 4 +dmd-release : $(STD_DDOC_RELEASE) druntime-target + bash $(DMD_DIR)/compiler/src/bootstrap.sh html $(DDOC_VARS_RELEASE_HTML) $(BUILD_JOBS_ARG) + +dmd-latest : $(STD_DDOC_LATEST) druntime-latest-target + bash $(DMD_LATEST_DIR)/compiler/src/bootstrap.sh html $(DDOC_VARS_LATEST_HTML) $(BUILD_JOBS_ARG) + +dmd-prerelease-verbatim : $W/phobos-prerelease/mars.verbatim +$W/phobos-prerelease/mars.verbatim: $(STD_DDOC_PRERELEASE) druntime-target \ + verbatim.ddoc $G/changelog/next-version + mkdir -p $(dir $@) + bash $(DMD_DIR)/compiler/src/bootstrap.sh html $(DDOC_VARS_PRERELEASE_VERBATIM) + $(call CHANGE_SUFFIX,html,verbatim,$W/phobos-prerelease-verbatim) + mv $W/phobos-prerelease-verbatim/* $(dir $@) + rm -r $W/phobos-prerelease-verbatim ################################################################################ # druntime, latest released build and current build +# TODO: remove DOCDIR and DOCFMT once they have been removed at Druntime ################################################################################ -druntime-prerelease : ${DOC_OUTPUT_DIR}/phobos-prerelease/object.html -${DOC_OUTPUT_DIR}/phobos-prerelease/object.html : ${DMD_DIR}/src/dmd - make --directory=${DRUNTIME_DIR} -f posix.mak \ - DOCDIR=${DOC_OUTPUT_DIR}/phobos-prerelease \ - DOCFMT=../d-programming-language.org/std.ddoc \ - doc -j 4 - -druntime-release : ${DOC_OUTPUT_DIR}/phobos/object.html -${DOC_OUTPUT_DIR}/phobos/object.html : ${DMD_DIR}.${LATEST}/src/dmd - [ -d ${DRUNTIME_DIR}.${LATEST} ] || \ - git clone ${GIT_HOME}/druntime ${DRUNTIME_DIR}.${LATEST}/ - cd ${DRUNTIME_DIR}.${LATEST} && git checkout v${LATEST} - make --directory=${DRUNTIME_DIR}.${LATEST} -f posix.mak clean - make --directory=${DRUNTIME_DIR}.${LATEST} -f posix.mak \ - DMD=${DMD_DIR}.${LATEST}/src/dmd \ - DOCDIR=${DOC_OUTPUT_DIR}/phobos \ - DOCFMT=../d-programming-language.org/std.ddoc doc -j 4 +druntime-target: ${DRUNTIME_DIR} ${DMD} + ${MAKE} --directory=${DRUNTIME_DIR} target ${DDOC_VARS_PRERELEASE_HTML} + +druntime-latest-target: ${DRUNTIME_LATEST_DIR} ${DMD_LATEST} + ${MAKE} --directory=${DRUNTIME_LATEST_DIR} target ${DDOC_VARS_LATEST_HTML} + +druntime-prerelease : druntime-target $(STD_DDOC_PRERELEASE) $G/changelog/next-version + ${MAKE} --directory=${DRUNTIME_DIR} doc $(DDOC_VARS_PRERELEASE_HTML) \ + DOCDIR=$W/phobos-prerelease \ + DOCFMT="$(addprefix `pwd`/, $(STD_DDOC_PRERELEASE))" + +druntime-release : druntime-target $(STD_DDOC_RELEASE) + ${MAKE} --directory=${DRUNTIME_DIR} doc $(DDOC_VARS_RELEASE_HTML) \ + DOCDIR=$W/phobos \ + DOCFMT="$(addprefix `pwd`/, $(STD_DDOC_RELEASE))" + +druntime-latest : druntime-latest-target $(STD_DDOC_LATEST) + ${MAKE} --directory=${DRUNTIME_LATEST_DIR} doc $(DDOC_VARS_LATEST_HTML) \ + DOCDIR=$W/phobos \ + DOCFMT="$(addprefix `pwd`/, $(STD_DDOC_LATEST))" + +druntime-prerelease-verbatim : $W/phobos-prerelease/object.verbatim +$W/phobos-prerelease/object.verbatim : $(DMD) druntime-target $G/changelog/next-version + ${MAKE} --directory=${DRUNTIME_DIR} target doc $(DDOC_VARS_PRERELEASE_VERBATIM) \ + DOCDIR=$W/phobos-prerelease-verbatim \ + DOCFMT="`pwd`/verbatim.ddoc" + mkdir -p $(dir $@) + $(call CHANGE_SUFFIX,html,verbatim,$W/phobos-prerelease-verbatim) + mv $W/phobos-prerelease-verbatim/* $(dir $@) + rm -r $W/phobos-prerelease-verbatim ################################################################################ # phobos, latest released build and current build ################################################################################ -phobos-prerelease : ${DOC_OUTPUT_DIR}/phobos-prerelease/index.html -${DOC_OUTPUT_DIR}/phobos-prerelease/index.html : \ - ${DOC_OUTPUT_DIR}/phobos-prerelease/object.html - cd ${PHOBOS_DIR} && make -f posix.mak \ - DOC_OUTPUT_DIR=${DOC_OUTPUT_DIR}/phobos-prerelease html -j 4 - -phobos-release: ${DOC_OUTPUT_DIR}/phobos/index.html -${DOC_OUTPUT_DIR}/phobos/index.html : \ - ${DOC_OUTPUT_DIR}/phobos/object.html - [ -d ${PHOBOS_DIR}.${LATEST} ] || \ - git clone ${GIT_HOME}/phobos ${PHOBOS_DIR}.${LATEST}/ - cd ${PHOBOS_DIR}.${LATEST} && git checkout v${LATEST} - make --directory=${PHOBOS_DIR}.${LATEST} -f posix.mak -j 4 \ - release html \ - DMD=${DMD_DIR}.${LATEST}/src/dmd \ - DDOC=${DMD_DIR}.${LATEST}/src/dmd \ - DRUNTIME_PATH=${DRUNTIME_DIR}.${LATEST} \ - DOC_OUTPUT_DIR=${DOC_OUTPUT_DIR}/phobos +.PHONY: phobos-prerelease +phobos-prerelease : druntime-target $(STD_DDOC_PRERELEASE) $(DDOC_BIN) $(DMD) \ + $G/changelog/next-version + $(MAKE) --directory=$(PHOBOS_DIR) html $(DDOC_VARS_PRERELEASE_HTML) \ + DMD="$(abspath $(DDOC_BIN)) --compiler=$(abspath $(DMD))" + +phobos-release : druntime-target $(STD_DDOC_RELEASE) $(DDOC_BIN) $(DMD) + $(MAKE) --directory=$(PHOBOS_DIR) html $(DDOC_VARS_RELEASE_HTML) \ + DMD="$(abspath $(DDOC_BIN)) --compiler=$(abspath $(DMD))" + +phobos-latest : druntime-latest-target $(STD_DDOC_LATEST) $(DDOC_BIN) $(DMD_LATEST) + $(MAKE) --directory=$(PHOBOS_LATEST_DIR) html $(DDOC_VARS_LATEST_HTML) \ + DMD="$(abspath $(DDOC_BIN)) --compiler=$(abspath $(DMD_LATEST))" + +phobos-prerelease-verbatim : $W/phobos-prerelease/index.verbatim +$W/phobos-prerelease/index.verbatim : druntime-target verbatim.ddoc \ + $W/phobos-prerelease/object.verbatim \ + $W/phobos-prerelease/mars.verbatim $G/changelog/next-version $(DMD) $(DDOC_BIN) + ${MAKE} --directory=${PHOBOS_DIR} html $(DDOC_VARS_PRERELEASE_VERBATIM) \ + DOC_OUTPUT_DIR=$W/phobos-prerelease-verbatim DMD="$(abspath $(DDOC_BIN)) --compiler=$(abspath $(DMD))" + $(call CHANGE_SUFFIX,html,verbatim,$W/phobos-prerelease-verbatim) + mv $W/phobos-prerelease-verbatim/* $(dir $@) + rm -r $W/phobos-prerelease-verbatim + +$(PHOBOS_LIB): $(DMD) + ${MAKE} --directory=${PHOBOS_DIR} lib + +################################################################################ +# phobos and druntime, latest released build and current build (DDOX version) +################################################################################ + +apidocs-prerelease : $W/library-prerelease/sitemap.xml $W/library-prerelease/.htaccess +apidocs-latest : $W/library/sitemap.xml $W/library/.htaccess +apidocs-serve : $G/docs-prerelease.json + ${DPL_DOCS} ${DPL_DOCS_FLAGS} serve-html --std-macros=html.ddoc --std-macros=dlang.org.ddoc --std-macros=std.ddoc \ + --std-macros=keywords.ddoc --std-macros=macros.ddoc --std-macros=std-ddox.ddoc \ + --override-macros=std-ddox-override.ddoc --package-order=std \ + --git-target=master --web-file-dir=. $< + +$W/library-prerelease/sitemap.xml : $G/docs-prerelease.json + @mkdir -p $(dir $@) + ${DPL_DOCS} ${DPL_DOCS_FLAGS} generate-html --file-name-style=lowerUnderscored --std-macros=html.ddoc --std-macros=dlang.org.ddoc \ + --std-macros=std.ddoc --std-macros=keywords.ddoc --std-macros=macros.ddoc --std-macros=std-ddox.ddoc \ + --override-macros=std-ddox-override.ddoc --package-order=std \ + --git-target=master $(DPL_DOCS_PATH_RUN_FLAGS) \ + $< $W/library-prerelease + +$W/library/sitemap.xml : $G/docs-latest.json + @mkdir -p $(dir $@) + ${DPL_DOCS} ${DPL_DOCS_FLAGS} generate-html --file-name-style=lowerUnderscored --std-macros=html.ddoc --std-macros=dlang.org.ddoc \ + --std-macros=std.ddoc --std-macros=keywords.ddoc --std-macros=macros.ddoc --std-macros=std-ddox.ddoc \ + --override-macros=std-ddox-override.ddoc --package-order=std \ + --git-target=v${LATEST} $(DPL_DOCS_PATH_RUN_FLAGS) \ + $< $W/library + +$W/library/.htaccess : dpl_latest_htaccess + @mkdir -p $(dir $@) + cp $< $@ + +$W/library-prerelease/.htaccess : dpl_prerelease_htaccess + @mkdir -p $(dir $@) + cp $< $@ + +$G/docs-latest.json : ${DMD_LATEST} ${DMD_LATEST_DIR} \ + ${DRUNTIME_LATEST_DIR} | dpl-docs + find ${DMD_LATEST_DIR}/compiler/src -name '*.d' -o -name '*.di' | sort -r | \ + gawk '!n[gensub(/\.di?$$/, "", 1)]++' > $G/.latest-files.txt + find ${DRUNTIME_LATEST_DIR}/src -name '*.d' | \ + sed -e /unittest.d/d -e /gcstub/d >> $G/.latest-files.txt + find ${PHOBOS_LATEST_DIR}/etc ${PHOBOS_LATEST_DIR}/std -name '*.d' | \ + sed -e /unittest.d/d | sort >> $G/.latest-files.txt + ${DMD_LATEST} -J$(DMD_LATEST_DIR)/compiler/src/dmd/res -J$(dir $(DMD_LATEST)) -c -o- -version=CoreDdoc \ + -version=MARS -version=CoreDdoc -version=StdDdoc -Df$G/.latest-dummy.html \ + -Xf$@ -I${PHOBOS_LATEST_DIR} @$G/.latest-files.txt + ${DPL_DOCS} ${DPL_DOCS_FLAGS} filter $@ --min-protection=Protected \ + --only-documented $(MOD_EXCLUDES_LATEST) + rm -f $G/.latest-files.txt $G/.latest-dummy.html + +$G/docs-prerelease.json : ${DMD} ${DMD_DIR} ${DRUNTIME_DIR} | dpl-docs + find ${DMD_DIR}/compiler/src -name '*.d' -o -name '*.di' | sort -r | \ + gawk '!n[gensub(/\.di?$$/, "", 1)]++' > $G/.prerelease-files.txt + find ${DRUNTIME_DIR}/src -name '*.d' | \ + sed -e /unittest/d >> $G/.prerelease-files.txt + find ${PHOBOS_DIR}/etc ${PHOBOS_DIR}/std -name '*.d' | \ + sed -e /unittest.d/d | sort >> $G/.prerelease-files.txt + ${DMD} -J$(DMD_DIR)/res -J$(DMD_DIR)/compiler/src/dmd/res -J$(dir $(DMD)) -c -o- -version=MARS -version=CoreDdoc \ + -version=StdDdoc -Df$G/.prerelease-dummy.html \ + -Xf$@ -I${PHOBOS_DIR} @$G/.prerelease-files.txt + ${DPL_DOCS} ${DPL_DOCS_FLAGS} filter $@ --min-protection=Protected \ + --only-documented $(MOD_EXCLUDES_PRERELEASE) + rm -f $G/.prerelease-files.txt $G/.prerelease-dummy.html + +################################################################################ +# binary targets for DDOX +################################################################################ + +# workardound Issue 15574 +ifneq (osx,$(OS)) + DPL_DOCS_DFLAGS=-conf=$(abspath ${STABLE_DMD_CONF}) -L--no-as-needed +else + DPL_DOCS_DFLAGS=-conf=$(abspath ${STABLE_DMD_CONF}) +endif + +.PHONY: dpl-docs +dpl-docs: ${DUB} ${STABLE_DMD} + DFLAGS="$(DPL_DOCS_DFLAGS)" ${DUB} -v build --root=${DPL_DOCS_PATH} \ + --compiler=${STABLE_DMD} + +# .tar.xz's archives are smaller (and don't need a temporary dir) -> prefer if available +${STABLE_DMD_ROOT}/.downloaded: + @mkdir -p $(dir $@) + @if command -v xz >/dev/null 2>&1 ; then \ + curl -fSL --retry 3 $(subst .zip,.tar.xz,$(STABLE_DMD_URL)) | tar -Jxf - -C $(dir $@); \ + else \ + TMPFILE=$$(mktemp deleteme.XXXXXXXX) && curl -fsSL ${STABLE_DMD_URL} > ${TMP}/$${TMPFILE}.zip && \ + unzip -qd ${STABLE_DMD_ROOT} ${TMP}/$${TMPFILE}.zip && rm ${TMP}/$${TMPFILE}.zip; \ + fi + @touch $@ + +${STABLE_DMD} ${STABLE_RDMD} ${DUB}: ${STABLE_DMD_ROOT}/.downloaded + +################################################################################ +# chm help files +################################################################################ + +# testing menu generation +chm-nav-latest.json : $(DDOC) std.ddoc spec/spec.ddoc ${GENERATED}/modlist-${LATEST}.ddoc changelog/changelog.ddoc chm-nav.dd $(DMD) $(DDOC_BIN) + $(DDOC_BIN_DMD) -conf= -c -o- -Df$@ $(filter-out $(DMD) $(DDOC_BIN),$^) + +chm-nav-release.json : $(DDOC) std.ddoc spec/spec.ddoc ${GENERATED}/modlist-release.ddoc changelog/changelog.ddoc chm-nav.dd $(DMD) $(DDOC_BIN) + $(DDOC_BIN_DMD) -conf= -c -o- -Df$@ $(filter-out $(DMD) $(DDOC_BIN),$^) + +chm-nav-prerelease.json : $(DDOC) std.ddoc spec/spec.ddoc ${GENERATED}/modlist-prerelease.ddoc changelog/changelog.ddoc chm-nav.dd $(DMD) $(DDOC_BIN) + $(DDOC_BIN_DMD) -conf= -c -o- -Df$@ $(filter-out $(DMD) $(DDOC_BIN),$^) + +################################################################################ +# Dman tags +################################################################################ + +d-latest.tag d-tags-latest.json : tools/chmgen.d $(STABLE_DMD) $(ALL_FILES) phobos-latest druntime-latest chm-nav-latest.json + $(STABLE_RDMD) $< --root=$W --target latest --dir ${GENERATED}/chmgen-latest + +d-release.tag d-tags-release.json : tools/chmgen.d $(STABLE_DMD) $(ALL_FILES) phobos-release druntime-release chm-nav-release.json + $(STABLE_RDMD) $< --root=$W --target release --dir ${GENERATED}/chmgen-release + +d-prerelease.tag d-tags-prerelease.json : tools/chmgen.d $(STABLE_DMD) $(ALL_FILES) phobos-prerelease druntime-prerelease chm-nav-prerelease.json + $(STABLE_RDMD) $< --root=$W --target prerelease --dir ${GENERATED}/chmgen-prerelease + +################################################################################ +# Style tests +################################################################################ + +test_dspec: tools/dspec_tester.d $(DMD) $(PHOBOS_LIB) + @echo "Test the D Language specification" + $(DMD) -run $< --compiler=$(DMD) + +.PHONY: +test: test_dspec test/next_version.sh all | $(STABLE_DMD) $(DUB) + @echo "Searching for trailing whitespace" + @grep -n '[[:blank:]]$$' $$(find . -type f -name "*.dd" | grep -v .generated) ; test $$? -eq 1 + @echo "Searching for tabs" + @grep -n -P "\t" $$(find . -type f -name "*.dd" | grep -v .generated) ; test $$? -eq 1 + @echo "Checking DDoc's output" + $(STABLE_RDMD) -main -unittest tools/check_ddoc.d + $(STABLE_RDMD) tools/check_ddoc.d $$(find $W -type f -name "*.html" -not -path "$W/phobos/*") + @echo "Executing ddoc_preprocessor tests" + $(DUB) test --compiler=${STABLE_DMD} --root ddoc + @echo "Executing next_version tests" + test/next_version.sh + +################################################################################ +# Changelog generation +# -------------------- +# +# The changelog generation consists of two parts: +# +# 1) Closed Bugzilla issues since the latest release +# - The git log messages after the ${LATEST} release are parsed +# - From these git commit messages, referenced Bugzilla issues are extracted +# - The status of these issues is checked against the Bugzilla instance (https://issues.dlang.org) +# +# See also: https://github.com/dlang-bots/dlang-bot#bugzilla +# +# 2) Full-text messages +# - In all dlang repos, a `changelog` folder exists and can be used to add +# small, detailed changelog messages (see e.g. https://github.com/dlang/phobos/tree/master/changelog) +# - The changelog generation script searches for all Ddoc files within the `changelog` folders +# and adds them to the generated changelog +# +# The changelog script is at https://github.com/dlang/tools/blob/master/changed.d +# +# Changelog targets +# ----------------- +# +# The changelog generation has two targets: +# +# a) Preview upcoming changes +# +# make -f posix.mak pending_changelog +# +# This will look at changes up to `upstream/master` and can be used to +# preview the changelog locally. +# +# b) Generate the changelog for an upcoming release +# +# make -f posix.mak prerelease_changelog +# +# This will look at changes to upstream/stable and is run by the release manager. +################################################################################ +LOOSE_CHANGELOG_FILES:=$(wildcard $(DMD_DIR)/changelog/*.dd) \ + $(wildcard $(DRUNTIME_DIR)/changelog/*.dd) \ + $(wildcard $(PHOBOS_DIR)/changelog/*.dd) \ + $(wildcard $(TOOLS_DIR)/changelog/*.dd) \ + $(wildcard $(INSTALLER_DIR)/changelog/*.dd) \ + $(wildcard $(DUB_DIR)/changelog/*.dd) + +$G/changelog/next-version: ${DMD_DIR}/VERSION + $(eval NEXT_VERSION:=$(shell changelog/next_version.sh ${DMD_DIR}/VERSION)) + @mkdir -p $(dir $@) + @echo $(NEXT_VERSION) > $@ + +changelog/prerelease.dd: $G/changelog/next-version $(LOOSE_CHANGELOG_FILES) | \ + ${STABLE_DMD} $(TOOLS_DIR) $(INSTALLER_DIR) $(DUB_DIR) + $(STABLE_RDMD) -version=Contributors_Lib $(TOOLS_DIR)/changed.d \ + $(CHANGELOG_VERSION_STABLE) -o $@ --version "${NEXT_VERSION}" \ + --prev-version="${LATEST}" --date "To be released" + +changelog/pending.dd: $G/changelog/next-version $(LOOSE_CHANGELOG_FILES) | \ + ${STABLE_DMD} $(TOOLS_DIR) $(INSTALLER_DIR) $(DUB_DIR) + $(STABLE_RDMD) -version=Contributors_Lib $(TOOLS_DIR)/changed.d \ + $(CHANGELOG_VERSION_MASTER) -o $@ --version "${NEXT_VERSION}" \ + --prev-version="${LATEST}" --date "To be released" + +pending_changelog: changelog/pending.dd html + @echo "Please open file:///$(shell pwd)/web/changelog/pending.html in your browser" + +prerelease_changelog: changelog/prerelease.dd html + @echo "Please open file:///$(shell pwd)/web/changelog/prerelease.html in your browser" + @echo "To proceed, rename $@ to changelog/${NEXT_VERSION}_pre.dd" + +################################################################################ +# Contributors listing: A list of all the awesome who made D possible +################################################################################ + +$G/contributors_list.ddoc: | $(STABLE_RDMD) $(TOOLS_DIR) $(INSTALLER_DIR) + $(STABLE_RDMD) $(TOOLS_DIR)/contributors.d --format=ddoc "master" > $G/contributors_list.tmp + echo "NR_D_CONTRIBUTORS=$$(wc -l < $G/contributors_list.tmp)" > $@ + echo "D_CONTRIBUTORS=" >> $@ + cat $G/contributors_list.tmp >> $@ + +################################################################################ +# Custom DDoc wrapper +# ------------------ +# +# This allows extending Ddoc files and D source code files dynamically on-the-fly. +################################################################################ + +$(DDOC_BIN): ddoc/source/preprocessor.d ddoc/source/assert_writeln_magic.d | $(STABLE_DMD) + $(STABLE_DMD_BIN_ROOT)/dub build --compiler=$(STABLE_DMD) --root=ddoc && \ + mv ddoc/ddoc_preprocessor $@ + +################################################################################ +# Build and render the DMD man page +# --------------------------------- +# +# This allows previewing changes to the automatically generated DMD man page +################################################################################ + +$(DMD_DIR)/generated/$(MAN_PAGE): $(DMD_DIR)/compiler/docs/gen_man.d $(DMD_DIR)/compiler/src/dmd/cli.d | ${STABLE_DMD} + ${MAKE} -C $(DMD_DIR)/compiler/docs DMD=$(abspath $(STABLE_DMD)) DIFFABLE=$(DIFFABLE) build + +$W/$(MAN_PAGE): $(DMD_DIR)/generated/$(MAN_PAGE) | ${STABLE_DMD} + mkdir -p $(dir $@) + cp $< $@ + # CircleCi + nightlies.dlang.org might not have `man` installed + if [ $(OS) != "osx" ] -a [ command -v man > /dev/null ] ; then \ + ${MAKE} -s -C $(DMD_DIR)/compiler/docs DMD=$(abspath $(STABLE_DMD)) DIFFABLE=$(DIFFABLE) preview > $(dir $@)dmd.txt; \ + fi + +man: $W/$(MAN_PAGE) + +.DELETE_ON_ERROR: # GNU Make directive (delete output files on error) diff --git a/pragma.dd b/pragma.dd deleted file mode 100644 index 119de0ed4a..0000000000 --- a/pragma.dd +++ /dev/null @@ -1,126 +0,0 @@ -Ddoc - -$(SPEC_S Pragmas, - -$(GRAMMAR -$(GNAME Pragma): - $(B pragma) $(B $(LPAREN)) $(I Identifier) $(B $(RPAREN)) - $(B pragma) $(B $(LPAREN)) $(I Identifier) $(B ,) $(GLINK2 expression, ArgumentList) $(B $(RPAREN)) -) - - - $(P Pragmas are a way to pass special information to the compiler - and to add vendor specific extensions to D. - Pragmas can be used by themselves terminated with a $(SINGLEQUOTE ;), - they can influence a statement, a block of statements, a declaration, or - a block of declarations. - ) - - $(P Pragmas can appear as either declarations, - $(I Pragma) $(GLINK2 attribute, DeclarationBlock), - or as statements, - $(GLINK2 statement, PragmaStatement). - ) - ------------------ -pragma(ident); // just by itself - -pragma(ident) declaration; // influence one declaration - -pragma(ident): // influence subsequent declarations - declaration; - declaration; - -pragma(ident) { // influence block of declarations - declaration; - declaration; -} - -pragma(ident) statement; // influence one statement - -pragma(ident) { // influence block of statements - statement; - statement; -} ------------------ - - $(P The kind of pragma it is is determined by the $(I Identifier). - $(I ExpressionList) is a comma-separated list of - $(ASSIGNEXPRESSION)s. The $(ASSIGNEXPRESSION)s must be - parsable as expressions, but what they mean semantically - is up to the individual pragma semantics. - ) - -<h2><a name="Predefined-Pragmas">Predefined Pragmas</a></h2> - - $(P All implementations must support these, even if by just ignoring - them: - ) - - $(DL - - $(DT $(B msg)) - $(DD Prints a message to the standard error stream while compiling, the - $(ASSIGNEXPRESSION)s must be string literals: ------------------ -pragma(msg, "compiling..."); ------------------ - ) - - $(DT $(B lib)) - $(DD Inserts a directive in the object file to link in the library - specified by the $(ASSIGNEXPRESSION). - The $(ASSIGNEXPRESSION)s must be a string literal: ------------------ -pragma(lib, "foo.lib"); ------------------ - ) -$(V2 - $(DT $(B startaddress)) - $(DD Puts a directive into the object file saying that the - function specified in the first argument will be the - start address for the program: ------------------ -void foo() { ... } -pragma(startaddress, foo); ------------------ - This is not normally used for application level programming, - but is for specialized systems work. - For applications code, the start address is taken care of - by the runtime library. - ) -) - - ) - -<h2>Vendor Specific Pragmas</h2> - - $(P Vendor specific pragma $(I Identifier)s can be defined if they - are prefixed by the vendor's trademarked name, in a similar manner - to version identifiers: - ) - ------------------ -pragma(DigitalMars_funky_extension) { ... } ------------------ - - $(P Compilers must diagnose an error for unrecognized $(I Pragma)s, - even if they are vendor specific ones. This implies that vendor - specific pragmas should be wrapped in version statements: - ) - ------------------ -version (DigitalMars) -{ - pragma(DigitalMars_funky_extension) - { ... } -} ------------------ - -) - -Macros: - TITLE=Pragmas - WIKI=Pragma - CATEGORY_SPEC=$0 - diff --git a/pretod.dd b/pretod.dd deleted file mode 100644 index 1c32a14a46..0000000000 --- a/pretod.dd +++ /dev/null @@ -1,731 +0,0 @@ -Ddoc - -$(COMMUNITY The C Preprocessor Versus D, - - $(P Back when C was invented, compiler technology was primitive. - Installing a text - macro preprocessor onto the front end was a straightforward - and easy way to add many - powerful features. The increasing size & complexity of programs - have illustrated - that these features come with many inherent problems. - D doesn't have a preprocessor; but - D provides a more scalable means to solve the same problems. - ) - -$(UL - $(LI <a href="#headerfiles">Header Files</a>) - $(LI <a href="#pragmaonce">#pragma once</a>) - $(LI <a href="#pragmapack">#pragma pack</a>) - $(LI <a href="#macros">Macros</a>) - $(LI <a href="#conditionalcompilation">Conditional Compilation</a>) - $(LI <a href="#codefactoring">Code Factoring</a>) - $(LI <a href="#staticassert">#error and Static Asserts</a>) - $(LI <a href="#mixins">Template Mixins</a>) -) - -<hr><!-- -------------------------------------------- --> -$(SECTION3 <a name="headerfiles">Header Files</a>, - -$(CWAY - - $(P C and C++ rely heavily on textual inclusion of header files. - This frequently results in the compiler having to recompile tens of thousands - of lines of code over and over again for every source file, an obvious - source of slow compile times. What header files are normally used for is - more appropriately done doing a symbolic, rather than textual, insertion. - This is done with the import statement. Symbolic inclusion means the compiler - just loads an already compiled symbol table. The needs for macro "wrappers" to - prevent multiple #inclusion, funky #pragma once syntax, and incomprehensible - fragile syntax for precompiled headers are simply unnecessary and irrelevant to - D. - ) - -$(CCODE -#include <stdio.h> -) -) - -$(DWAY - - $(P D uses symbolic imports:) - ---------- -import std.c.stdio; ---------- -) -) - -<hr><!-- -------------------------------------------- --> -<h3><a name="pragmaonce">#pragma once</a></h3> - -$(CWAY - - $(P C header files frequently need to be protected against - being #include'd multiple times. - To do it, a header file will contain the line: - ) - -$(CCODE -#pragma once -) - - $(P or the more portable:) - -$(CCODE -#ifndef __STDIO_INCLUDE -#define __STDIO_INCLUDE -... header file contents -#endif -) -) - -$(DWAY - $(P Completely unnecessary since D does a symbolic include of import - files; they only get imported once no matter how many times - the import declaration appears. - ) -) - -<hr><!-- -------------------------------------------- --> -<h3><a name="pragmapack">#pragma pack</a></h3> - -$(CWAY - $(P This is used in C to adjust the alignment for structs.) -) - -$(DWAY - $(P For D classes, there is no need to adjust the alignment (in fact, the - compiler is free to rearrange the data fields to get the optimum layout, - much as the compiler will rearrange local variables on the stack frame). - For D structs that get mapped onto externally defined data structures, - there is a need, and it is handled with: - ) - ---------- -struct Foo -{ - align (4): // use 4 byte alignment - ... -} ---------- -) - -<hr><!-- -------------------------------------------- --> -<h3><a name="macros">Macros</a></h3> - - $(P Preprocessor macros add powerful features and flexibility to C. But - they have a downside: - ) - -$(UL - $(LI Macros have no concept of scope; they are valid from the point of definition - to the end of the source. They cut a swath across .h files, nested code, etc. When - #include'ing tens of thousands of lines of macro definitions, it becomes - problematical to avoid inadvertent macro expansions. - ) - - $(LI Macros are unknown to the debugger. Trying to debug a program with - symbolic data is undermined by the debugger only knowing about macro - expansions, not the macros themselves. - ) - - $(LI Macros make it impossible to tokenize source code, as an earlier macro change - can arbitrarily redo tokens. - ) - - $(LI The purely textual basis of macros leads to arbitrary and inconsistent usage, - making code using macros error prone. (Some attempt to resolve this was - introduced with templates in C++.) - ) - - $(LI Macros are still used to make up for deficits in the language's expressive - capability, such as for "wrappers" around header files. - ) -) - - - $(P Here's an enumeration of the common uses for macros, and the - corresponding feature in D: - ) - -$(OL - $(LI Defining literal constants: - - $(CWAY - -$(CCODE -#define VALUE 5 -) - ) - - $(DWAY - ---------- -const int VALUE = 5; ---------- - ) - ) - - $(LI Creating a list of values or flags: - - $(CWAY - -$(CCODE -int flags: -#define FLAG_X 0x1 -#define FLAG_Y 0x2 -#define FLAG_Z 0x4 -... -flags |= FLAG_X; -) - ) - - $(DWAY - ---------- -enum FLAGS { X = 0x1, Y = 0x2, Z = 0x4 }; -FLAGS flags; -... -flags |= FLAGS.X; ---------- - ) - ) - - $(LI Distinguishing between ascii chars and wchar chars: - - $(CWAY - -$(CCODE -#if UNICODE - #define dchar wchar_t - #define TEXT(s) L##s -#else - #define dchar char - #define TEXT(s) s -#endif - -... -dchar h[] = TEXT("hello"); -) - ) - - $(DWAY - ---------- -dchar[] h = "hello"; ---------- - - - D's optimizer will inline the function, and will do the conversion of the - string constant at compile time. - <p> - ) - ) - - $(LI Supporting legacy compilers: - - $(CWAY - -$(CCODE -#if PROTOTYPES -#define P(p) p -#else -#define P(p) () -#endif -int func P((int x, int y)); -) - ) - - $(DWAY - By making the D compiler open source, it will largely - avoid the problem of syntactical backwards compatibility. - ) - ) - - $(LI Type aliasing: - - $(CWAY - -$(CCODE -#define INT int -) - ) - - $(DWAY - ---------- -alias int INT; ---------- - ) - ) - - $(LI Using one header file for both declaration and definition: - - $(CWAY - -$(CCODE -#define EXTERN extern -#include "declarations.h" -#undef EXTERN -#define EXTERN -#include "declarations.h" -) - - In declarations.h: - -$(CCODE -EXTERN int foo; -) - ) - - $(DWAY - - The declaration and the definition are the same, so there is no need - to muck with the storage class to generate both a declaration and a definition - from the same source. - ) - ) - - $(LI Lightweight inline functions: - - $(CWAY - -$(CCODE -#define X(i) ((i) = (i) / 3) -) - ) - - $(DWAY - ---------- -int X(ref int i) { return i = i / 3; } ---------- - - The compiler optimizer will inline it; no efficiency is lost. - ) - ) - - $(LI Assert function file and line number information: - - $(CWAY - -$(CCODE -#define assert(e) ((e) || _assert(__LINE__, __FILE__)) -) - ) - - $(DWAY - - assert() is a built-in expression primitive. Giving the compiler - such knowledge of assert() also enables the optimizer to know about things - like the _assert() function never returns. - ) - ) - - $(LI Setting function calling conventions: - - $(CWAY - -$(CCODE -#ifndef _CRTAPI1 -#define _CRTAPI1 __cdecl -#endif -#ifndef _CRTAPI2 -#define _CRTAPI2 __cdecl -#endif - -int _CRTAPI2 func(); -) - ) - - $(DWAY - - Calling conventions can be specified in blocks, so there's no - need to change it for every function: - ---------- -extern (Windows) -{ - int onefunc(); - int anotherfunc(); -} ---------- - ) - ) - - $(LI Hiding __near or __far pointer weirdness: - - $(CWAY - -$(CCODE -#define LPSTR char FAR * -) - ) - - $(DWAY - - D doesn't support 16 bit code, mixed pointer sizes, and different - kinds of pointers, and so the problem is just - irrelevant. - ) - ) - - $(LI Simple generic programming: - - $(CWAY - - Selecting which function to use based on text substitution: - -$(CCODE -#ifdef UNICODE -int getValueW(wchar_t *p); -#define getValue getValueW -#else -int getValueA(char *p); -#define getValue getValueA -#endif -) - ) - - $(DWAY - - D enables declarations of symbols that are $(I aliases) of - other symbols: - ---------- -version (UNICODE) -{ - int getValueW(wchar[] p); - alias getValueW getValue; -} -else -{ - int getValueA(char[] p); - alias getValueA getValue; -} ---------- - ) - ) - -) - -<hr><!-- -------------------------------------------- --> -<h3><a name="conditionalcompilation">Conditional Compilation</a></h3> - - -$(CWAY - - $(P Conditional compilation is a powerful feature of the C preprocessor, - but it has its downside:) - - $(UL - $(LI The preprocessor has no concept of scope. #if/#endif can be - interleaved with code in a completely unstructured and disorganized - fashion, making things difficult to follow. - ) - - $(LI Conditional compilation triggers off of macros - macros that - can conflict with identifiers used in the program. - ) - - $(LI #if expressions are evaluated in subtly different ways than - C expressions are. - ) - - $(LI The preprocessor language is fundamentally different in concept - than C, for example, whitespace and line terminators mean things to - the preprocessor that they do not in C. - ) - ) -) - -$(DWAY - - $(P D supports conditional compilation:) - - $(OL - $(LI Separating version specific functionality into separate modules. - ) - - $(LI The debug statement for enabling/disabling debug harnesses, - extra printing, etc. - ) - - $(LI The version statement for dealing with multiple versions - of the program generated from a single set of sources. - ) - - $(LI The if (0) statement. - ) - - $(LI The /+ +/ nesting comment can be used to comment out blocks - of code. - ) - ) -) - -<hr><!-- -------------------------------------------- --> -<h3><a name="codefactoring">Code Factoring</a></h3> - -$(CWAY - - $(P It's common in a function to have a repetitive sequence - of code to be executed in multiple places. Performance - considerations preclude factoring it out into a separate - function, so it is implemented as a macro. For example, - consider this fragment from a byte code interpreter: - ) - -$(CCODE -unsigned char *ip; // byte code instruction pointer -int *stack; -int spi; // stack pointer -... -#define pop() (stack[--spi]) -#define push(i) (stack[spi++] = (i)) -while (1) -{ - switch (*ip++) - { - case ADD: - op1 = pop(); - op2 = pop(); - result = op1 + op2; - push(result); - break; - - case SUB: - ... - } -} -) - - $(P This suffers from numerous problems: - ) - - $(OL - $(LI The macros must evaluate to expressions and cannot declare - any variables. Consider the difficulty of extending them to - check for stack overflow/underflow. - ) - $(LI The macros exist outside of the semantic symbol table, so - remain in scope even outside of the function they are declared in. - ) - $(LI Parameters to macros are passed textually, not by value, - meaning that the macro implementation needs to be careful to not - use the parameter more than once, and must protect it with (). - ) - $(LI Macros are invisible to the debugger, which sees only the - expanded expressions. - ) - ) -) - -$(DWAY - - $(P D neatly addresses this with nested functions:) - ---------- -ubyte* ip; // byte code instruction pointer -int[] stack; // operand stack -int spi; // stack pointer -... - -int pop() { return stack[--spi]; } -void push(int i) { stack[spi++] = i; } - -while (1) -{ - switch (*ip++) - { - case ADD: - op1 = pop(); - op2 = pop(); - push(op1 + op2); - break; - - case SUB: - ... - } -} ---------- - - $(P The problems addressed are:) - - $(OL - $(LI The nested functions have available the full expressive - power of D functions. The array accesses already are bounds - checked (adjustable by compile time switch). - ) - $(LI Nested function names are scoped just like any other name. - ) - $(LI Parameters are passed by value, so need to worry about - side effects in the parameter expressions. - ) - $(LI Nested functions are visible to the debugger. - ) - ) - - $(P Additionally, nested functions can be inlined by the implementation - resulting in the same high performance that the C macro version - exhibits. - ) -) - -<hr><!-- -------------------------------------------- --> -<h3><a name="staticassert">#error and Static Asserts</a></h3> - - $(P Static asserts are user defined checks made at compile time; - if the check fails the compile issues an error and fails. - ) - -$(CWAY - - $(P The first way is to use the $(D #error) preprocessing directive: - ) - -$(CCODE -#if FOO || BAR - ... code to compile ... -#else -#error "there must be either FOO or BAR" -#endif -) - - $(P This has the limitations inherent in preprocessor expressions - (i.e. integer constant expressions only, no casts, no $(D sizeof), - no symbolic constants, etc.). - ) - - $(P These problems can be circumvented to some extent by defining a - $(D static_assert) macro (thanks to M. Wilson): - ) - -$(CCODE -#define static_assert(_x) do { typedef int ai[(_x) ? 1 : 0]; } while(0) -) - - $(P and using it like:) - -$(CCODE -void foo(T t) -{ - static_assert(sizeof(T) < 4); - ... -} -) - - $(P This works by causing a compile time semantic error if the condition - evaluates - to false. The limitations of this technique are a sometimes very - confusing error message from the compiler, along with an inability - to use a $(D static_assert) outside of a function body. - ) -) - -$(DWAY - - $(P D has the <a href="https://github.com/version.html#StaticAssert">static assert</a>, - which can be used anywhere a declaration - or a statement can be used. For example: - ) - ---------- -version (FOO) -{ - class Bar - { - const int x = 5; - static assert(Bar.x == 5 || Bar.x == 6); - - void foo(T t) - { - static assert(T.sizeof < 4); - ... - } - } -} -else version (BAR) -{ - ... -} -else -{ - static assert(0); // unsupported version -} ---------- -) - -<hr><!-- -------------------------------------------- --> -<h3><a name="mixins">Template Mixins</a></h3> - - $(P D $(LINK2 template-mixin.html, template mixins) - superficially look just - like using C's preprocessor to insert blocks of code and - parse them in the scope of where they are instantiated. - But the advantages of mixins over macros are: - ) - - $(OL - $(LI Mixins substitute in parsed declaration trees that pass muster with - the language syntax, macros substitute in arbitrary preprocessor tokens - that have no organization. - ) - - $(LI Mixins are in the same language. Macros are a separate and - distinct language layered on top of C++, with its own expression rules, - its own types, its distinct symbol table, its own scoping rules, etc. - ) - - $(LI Mixins are selected based on partial specialization rules, macros - have no overloading. - ) - - $(LI Mixins create a scope, macros do not. - ) - - $(LI Mixins are compatible with syntax parsing tools, macros are not. - ) - - $(LI Mixin semantic information and symbol tables are passed through to - the debugger, macros are lost in translation. - ) - - $(LI Mixins have override conflict resolution rules, macros just - collide. - ) - - $(LI Mixins automatically create unique identifiers as required using a - standard algorithm, macros have to do it manually with kludgy token - pasting. - ) - - $(LI Mixin value arguments with side effects are evaluated once, macro - value arguments get evaluated each time they are used in the expansion - (leading to weird bugs). - ) - - $(LI Mixin argument replacements don't need to be $(SINGLEQUOTE protected) with - parentheses to avoid operator precedence regrouping. - ) - - $(LI Mixins can be typed as normal D code of arbitrary length, multiline - macros have to be backslash line-spliced, can't use // to end of line - comments, etc. - ) - - $(LI Mixins can define other mixins. Macros cannot create other macros. - ) - - ) - -) - -Macros: - TITLE=The C Preprocessor vs D - WIKI=PreToD - CATEGORY_OVERVIEW=$0 - CWAY=$(SECTION4 The C Preprocessor Way, $0) - DWAY=$(SECTION4 The D Way, $0) - diff --git a/property.dd b/property.dd deleted file mode 100644 index 98b90eb217..0000000000 --- a/property.dd +++ /dev/null @@ -1,286 +0,0 @@ -Ddoc - -$(SPEC_S Properties, - - $(P Every type and expression has properties that can be queried:) - -$(TABLE2 Property Examples, -$(TR $(TH Expression) $(TH Value)) -$(TR $(TD int.sizeof) $(TD yields 4)) -$(TR $(TD float.nan) $(TD yields the floating point nan (Not A Number) value)) -$(TR $(TD (float).nan) $(TD yields the floating point nan value)) -$(TR $(TD (3).sizeof) $(TD yields 4 (because 3 is an int))) -$(TR $(TD 2.sizeof) $(TD syntax error, since "2." is a floating point number)) -$(TR $(TD int.init) $(TD default initializer for int's)) -$(TR $(TD int.mangleof) $(TD yields the string "i")) -$(TR $(TD int.stringof) $(TD yields the string "int")) -$(TR $(TD (1+2).stringof) $(TD yields the string "1 + 2")) -) - -$(BR) - -$(TABLE2 Properties for All Types, -$(TR $(TH Property) $(TH Description)) -$(TR $(TD $(LINK2 #init, .init)) $(TD initializer)) -$(TR $(TD $(LINK2 #sizeof, .sizeof)) $(TD size in bytes (equivalent to C's sizeof(type)))) -$(TR $(TD $(LINK2 #alignof, .alignof)) $(TD alignment size)) -$(TR $(TD .mangleof) $(TD string representing the $(SINGLEQUOTE mangled) representation of the type)) -$(TR $(TD $(LINK2 #stringof, .stringof)) $(TD string representing the source representation of the type)) -) - -$(BR) - -$(TABLE2 Properties for Integral Types, -$(TR $(TH Property) $(TH Description)) -$(TR $(TD .init) $(TD initializer (0))) -$(TR $(TD .max) $(TD maximum value)) -$(TR $(TD .min) $(TD minimum value)) -) - -$(BR) - -$(TABLE2 Properties for Floating Point Types, -$(TR $(TH Property) $(TH Description)) -$(TR $(TD .init) $(TD initializer (NaN))) -$(TR $(TD .infinity) $(TD infinity value)) -$(TR $(TD .nan) $(TD NaN value)) -$(TR $(TD .dig) $(TD number of decimal digits of precision)) -$(TR $(TD .epsilon) $(TD smallest increment to the value 1)) -$(TR $(TD .mant_dig) $(TD number of bits in mantissa)) -$(TR $(TD .max_10_exp) $(TD maximum int value such that 10<sup>max_10_exp</sup> is representable)) -$(TR $(TD .max_exp) $(TD maximum int value such that 2<sup>max_exp-1</sup> is representable)) -$(TR $(TD .min_10_exp) $(TD minimum int value such that 10<sup>min_10_exp</sup> is representable as a normalized value)) -$(TR $(TD .min_exp) $(TD minimum int value such that 2<sup>min_exp-1</sup> is representable as a normalized value)) -$(TR $(TD .max) $(TD largest representable value that's not infinity)) -$(V1 $(TR $(TD .min) $(TD smallest representable normalized value that's not 0))) -$(V2 $(TR $(TD .min_normal) $(TD smallest representable normalized value that's not 0))) -$(TR $(TD .re) $(TD real part)) -$(TR $(TD .im) $(TD imaginary part)) -) - -$(BR) - -$(TABLE2 Properties for Class Types, -$(TR $(TH Property) $(TH Description)) -$(TR $(TD $(LINK2 #classinfo, .classinfo)) $(TD Information about the dynamic type of the class)) -) - -$(SECTION2 $(LNAME2 init, .init) Property, - - $(P $(B .init) produces a constant expression that is the default - initializer. If applied to a type, it is the default initializer - for that type. If applied to a variable or field, it is the - default initializer for that variable or field's type. - For example: - ) - ----------------- -int a; -int b = 1; -typedef int t = 2; -t c; -t d = cast(t)3; - -int.init // is 0 -a.init // is 0 -b.init // is 0 -t.init // is 2 -c.init // is 2 -d.init // is 2 - -struct Foo { - int a; - int b = 7; -} - -Foo.init.a // is 0 -Foo.init.b // is 7 ----------------- -) - -$(SECTION2 $(LNAME2 stringof, .stringof) Property, - - $(P $(B .stringof) produces a constant string that is the - source representation of its prefix. - If applied to a type, it is the string for that type. - If applied to an expression, it is the source representation - of that expression. Semantic analysis is not done - for that expression. - For example: - ) - ----------------- -module test; -import std.stdio; - -struct Foo { } - -enum Enum { RED } - -typedef int myint; - -void main() { - writeln((1+2).stringof); // "1 + 2" - writeln(Foo.stringof); // "Foo" - writeln(test.Foo.stringof); // "Foo" - writeln(int.stringof); // "int" - writeln((int*[5][]).stringof); // "int*[5u][]" - writeln(Enum.RED.stringof); // "cast(enum)0" - writeln(test.myint.stringof); // "myint" - writeln((5).stringof); // "5" -} ----------------- -) - -$(SECTION2 $(LNAME2 sizeof, .sizeof Property), - - $(P $(CODE $(I e).sizeof) gives the size in bytes of the expression - $(I e). - ) - - $(P When getting the size of a member, it is not necessary for - there to be a $(I this) object: - ) - ---- -struct S { - int a; - static int foo() { - return a.sizeof; // returns 4 - } -} - -void test() { - int x = S.a.sizeof; // sets x to 4 -} ---- - - $(P $(CODE .sizeof) applied to a class object returns the size of - the class reference, not the class instantiation.) - -) - -$(SECTION2 $(LNAME2 alignof, .alignof Property), - - $(P $(CODE .alignof) gives the aligned size of an expression or type. - For example, an aligned size of 1 means that it is aligned on - a byte boundary, 4 means it is aligned on a 32 bit boundary. - ) -) - -$(SECTION2 $(LNAME2 classinfo, .classinfo) Property, - - $(P $(CODE .classinfo) provides information about the dynamic type - of a class object. - $(V1 It returns a reference to type $(DPLLINK phobos/object.html, object.ClassInfo).) - $(V2 It returns a reference to type $(DPLLINK phobos/object.html#TypeInfo_Class, object.TypeInfo_Class).) - ) - - $(P $(CODE .classinfo) applied to an interface gives the information for - the interface, not the class it might be an instance of. - ) -) - -$(SECTION3 $(LNAME2 classproperties, User Defined Properties), - - $(P Properties are functions that can be syntactically treated - as if they were fields or variables. Properties can be read from or written to. - A property is read by calling a methhod or function with no arguments; - a property is written by calling a method or function with its argument - being the value it is set to. - ) - - $(P A simple property would be:) - -$(V1 ----------------- -struct Foo -{ - int data() { return m_data; } // read property - - int data(int value) { return m_data = value; } // write property - -private: - int m_data; -} ----------------- -) -$(V2 ----------------- -struct Foo { - @property int data() { return m_data; } // read property - - @property int data(int value) { return m_data = value; } // write property - -private: - int m_data; -} ----------------- - - $(P Properties are marked with the $(CODE @property) attribute. - Properties may only have zero or one parameter, and may not be variadic. - Property functions may not be overloaded with non-property functions. - ) -) - $(P To use it:) - ----------------- -int test() { - Foo f; - - f.data = 3; // same as f.data(3); - return f.data + 3; // same as return f.data() + 3; -} ----------------- - - $(P The absence of a read method means that the property is write-only. - The absence of a write method means that the property is read-only. - Multiple write methods can exist; the correct one is selected using - the usual function overloading rules. - ) - - $(P In all the other respects, these methods are like any other methods. - They can be static, have different linkages, $(V1 be overloaded with - methods with multiple parameters,) have their address taken, etc. - ) - -$(V1 - $(P $(B Note:) Properties cannot be the lvalue of an - $(I op)=, ++, or -- operator. - ) -) -$(V2 - $(P $(B Note:) Properties can be the lvalue of an - $(I op)=, ++, or -- operator if they return a ref. - ) -) - $(P The built in properties $(CODE .sizeof), $(CODE .alignof), and $(CODE .mangleof) - may not be declared as fields or methods in structs, unions, classes or enums. - ) - - $(P If a .property is applied to a user-defined property, the .property is applied - to the result of the function call. - ) - -$(V2 ---- -void main() { - @property int[] delegate() bar1 = { return [1, 2]; }; - auto x1 = bar1.ptr; // points to array data - - struct Foo { int* ptr; } - @property Foo delegate() bar2 = { return Foo(); }; - auto x2 = bar2.ptr; // gets value of Foo.ptr -} ---- -) - -) - -) - -Macros: - TITLE=Properties - WIKI=Property - CATEGORY_SPEC=$0 - diff --git a/rationale.dd b/rationale.dd deleted file mode 100644 index cfb6966dfc..0000000000 --- a/rationale.dd +++ /dev/null @@ -1,226 +0,0 @@ -Ddoc - -$(D_S Rationale, - - $(P Questions about the reasons for various design decisions for - D often come up. This addresses many of them. - ) - -<h2>Operator Overloading</h2> - -<h3>Why not name them operator+(), operator*(), etc.?</h3> - - $(P This is the way C++ does it, and it is appealing to be able - to refer to overloading $(SINGLEQUOTE +) with $(SINGLEQUOTE operator+). The trouble is - things don't quite fit. For example, there are the - comparison operators <, <=, >, and >=. In C++, all four must - be overloaded to get complete coverage. In D, only a cmp() - function must be defined, and the comparison operations are - derived from that by semantic analysis. - ) - - $(P Overloading operator/() also provides no symmetric way, as a member - function, to overload the reverse operation. For example, - ) - ------- -class A -{ - int operator/(int i); // overloads (a/i) - static operator/(int i, A a) // overloads (i/a) -} ------- - - $(P The second overload does the reverse overload, but - it cannot be virtual, and so has a confusing asymmetry with - the first overload. - ) - -<h3>Why not allow globally defined operator overload functions?</h3> - - $(OL - $(LI Operator overloading can only be done with an argument - as an object, so they logically belong as member functions - of that object. That does leave the case of what to do - when the operands are objects of different types: - ------- -class A { } -class B { } -int opAdd(class A, class B); ------- - - Should opAdd() be in class A or B? The obvious stylistic solution - would be to put it in the class of the first operand, - ------- -class A -{ - int opAdd(class B) { } -} ------- - ) - - $(LI Operator overloads usually need access to private members - of a class, and making them global breaks the object oriented - encapsulation of a class. - ) - - $(LI (2) can be addressed by operator overloads automatically gaining - "friend" access, but such unusual behavior is at odds with D - being simple. - ) - - ) - -<h3>Why not allow user definable operators?</h3> - - $(P These can be very useful for attaching new infix operations - to various unicode symbols. The trouble is that in D, - the tokens are supposed to be completely independent of the - semantic analysis. User definable operators would break that. - ) - -<h3>Why not allow user definable operator precedence?</h3> - - $(P The trouble is this affects the syntax analysis, and the syntax - analysis is supposed to be completely independent of the - semantic analysis in D. - ) - -<h3>Why not use operator names like __add__ and __div__ instead - of opAdd, opDiv, etc.?</h3> - - $(P __ keywords should indicate a proprietary language extension, - not a basic part of the language. - ) - -<h3>Why not have binary operator overloads be static members, so both -arguments are specified, and there no longer is any issue with the reverse -operations?</h3> - - $(P This means that the operator overload cannot be virtual, and - so likely would be implemented as a shell around another - virtual function to do the real work. This will wind up looking - like an ugly hack. Secondly, the opCmp() function is already - an operator overload in Object, it needs to be virtual for several - reasons, and making it asymmetric with the way other operator - overloads are done is unnecessary confusion. - ) - -<h2>Properties</h2> - -<h3>Why does D have properties like T.infinity in the core language to give the -infinity of a floating point type, rather than doing it in a library like C++: - $(CODE std::numeric_limits<T>::infinity) -?</h3> - - Let's rephrase that as $(DOUBLEQUOTE if there's a way to express it in the existing - language, why build it in to the core language?) - In regards to T.infinity: - - $(OL - $(LI Building it in to the core language means the core language knows - what a floating point infinity is. Being layered in templates, typedefs, - casts, const bit patterns, etc., it doesn't know what it is, and is - unlikely to give sensible error messages if misused. - ) - - $(LI A side effect of (1) is it is unlikely to be able to use it - effectively in constant folding and other optimizations. - ) - - $(LI Instantiating templates, loading $(CODE #include) files, etc., all costs - compile time and memory. - ) - - $(LI The worst, though, is the lengths gone to just to get at infinity, - implying $(DOUBLEQUOTE the language and compiler don't know anything about IEEE 754 - floating point - so it cannot be relied on.) And in fact - many otherwise excellent C++ compilers - do not handle NaN's correctly in floating point comparisons. - (Digital Mars C++ does do it correctly.) - C++98 doesn't say anything about NaN or Infinity handling in expressions - or library functions. So it must be assumed it doesn't work. - ) - - ) - - $(P To sum up, there's a lot more to supporting NaNs and infinities than - having a template that returns a bit pattern. It has to be built in to - the compiler's core logic, and it has to permeate all the library code - that deals with floating point. And it has to be in the Standard. - ) - - $(P To illustrate, if either op1 or op2 or both are NaN, then:) - ------- -(op1 < op2) ------- - $(P does not yield the same result as:) ------- -!(op1 >= op2) ------- - $(P if the NaNs are done correctly.) - -<h2>Why use $(D static if(0)) rather than $(D if (0)?)</h2> - - $(P Some limitations are:) - - $(OL - $(LI if (0) introduces a new scope, static if(...) does not. Why does this - matter? It matters if one wants to conditionally declare a new variable: - ------- -static if (...) int x; else long x; -x = 3; ------- - - whereas: - ------- -if (...) int x; else long x; -x = 3; // error, x is not defined ------- - ) - - $(LI False static if conditionals don't have to semantically work. For - example, it may depend on a conditionally compiled declaration somewhere - else: - ------- -static if (...) int x; -int test() -{ - static if (...) return x; - else return 0; -} ------- - ) - - $(LI Static if's can appear where only declarations are allowed: - ------- -class Foo -{ - static if (...) - int x; -} ------- - ) - - $(LI Static if's can declare new type aliases: - ------- -static if (0 || is(int T)) T x; - ) ------- - ) - -) - -Macros: - TITLE=Rationale - WIKI=Rationale - CATEGORY_FAQ=$0 - diff --git a/rdmd.dd b/rdmd.dd index a6af1b9ba3..48d48ce01f 100644 --- a/rdmd.dd +++ b/rdmd.dd @@ -2,40 +2,45 @@ Ddoc $(D_S rdmd, -<h2>Synopsis</h2> +$(H2 Synopsis) In a command prompt: -<pre> -% cat myprog.d + +$(CONSOLE > cat myprog.d) +--- import std.stdio; void main() { writeln("Hello, world without explicit compilations!"); } -% rdmd myprog +--- +$(CONSOLE +\> rdmd myprog Hello, world without explicit compilations! -% <blink>_</blink> -</pre> +) Inside a D program: -<pre> -% cat myprog.d -#!/usr/bin/rdmd + +$(CONSOLE > cat myprog.d) +--- +#!/usr/bin/env rdmd import std.stdio; void main() { writeln("Hello, world with automated script running!"); } -% ./myprog.d +--- + +$(CONSOLE +\> ./myprog.d Hello, world with automated script running! -% <blink>_</blink> -</pre> +) -(Under Windows replace $(B cat) with $(B type) and $(B -#!/usr/bin/rdmd) with $(B #!rdmd), the latter assuming that $(B rdmd) +$(MESSAGE_BOX gray, $(B Windows): replace $(B cat) with $(B type) and $(B +#!/usr/bin/env rdmd) with $(B #!rdmd), the latter assuming that $(B rdmd) can be found in your path.) -<h2>Description</h2> +$(H2 Description) $(P $(B rdmd) is a companion to the $(B dmd) compiler that simplifies the typical edit-compile-link-run or edit-make-run cycle to a rapid @@ -66,18 +71,18 @@ source file does not produce the executable again.) )) -<h2>Usage</h2> +$(H2 Usage) -$(P - $(B rdmd) [$(I dmd and rdmd options)] $(I progfile)[.d] [$(I program arguments)] +$(CONSOLE +$(B rdmd) [$(I dmd and rdmd options)] $(I progfile)[.d] [$(I program arguments)] ) -$(P In addition to $(B dmd)'s options, $(B rdmd) recognizes the following: +$(P In addition to $(LINK2 $(ROOT_DIR)dmd.html, `dmd`)'s options, $(B rdmd) recognizes the following: ) $(DL -$(DT $(B --build-only)) $(DD just build the executable, don't run it) +$(DT $(B --build-only)) $(DD just build the executable, don't run it. By default, the executable is placed into the source file directory) $(DT $(B --chatty)) $(DD write dmd commands to stdout before executing them) @@ -88,45 +93,71 @@ compiler (e.g. gdmd) instead of dmd) $(DT $(B --dry-run)) $(DD do not compile, just show what commands would be run (implies --chatty)) -$(DT $(B --eval)=code) $(DD evaluate code including it in $(D_PARAM -void main(char[][] args) { ... }) (multiple --eval allowed, will be +$(DT $(B --eval)=code) $(DD evaluate code including it in +--- +void main(string[] args) { ... } +--- +(multiple --eval allowed, will be evaluated in turn)) +$(DT $(B --exclude)=package) $(DD exclude a package from the build (multiple --exclude allowed)) + +$(DT $(B --include)=package) $(DD negate $(B --exclude) or a standard package (std, etc, core)) + +$(DT $(B --extra-file)=file) $(DD include an extra source or object in the compilation (multiple --extra-file allowed)) + $(DT $(B --force)) $(DD force a rebuild even if apparently not necessary) $(DT $(B --help)) $(DD show a help message and exit) $(DT $(B --loop)=code) $(DD like --eval, but code will be additionally -included in a loop $(D_PARAM foreach (line; stdin.byLine()) { ... })) +included in a loop +--- +foreach (line; stdin.byLine()) { ... } +--- +) -$(DT $(B --main)) $(DD add an empty $(D_PARAM void main() {}) function +$(DT $(B --main)) $(DD add an empty +--- +void main() {} +--- (useful for running unittests)) $(DT $(B --makedepend)) $(DD print dependencies in makefile format and exit) $(DT $(B --man)) $(DD open web browser on manual page) -$(DT $(B --shebang)) $(DD rdmd is in a shebang line (put as first argument)) +$(DT $(B --shebang)) $(DD rdmd is in a shebang line (put as first argument). Example: +$(CONSOLE > cat myprog.d) +--- +#!/usr/bin/rdmd --shebang -version=test -O +import std.stdio; +void main() +{ + writeln("Hello, world with automated script running!"); +} +--- +) + +$(DT $(B --tmpdir)) $(DD use a different temporary directory) ) -<h2>Download</h2> +$(H2 Download) $(UL $(LI View syntax-colored $(LINK2 -https://github.com/D-Programming-Language/tools/blob/master/rdmd.d, source +https://github.com/dlang/tools/blob/master/rdmd.d, source code)) $(LI $(LINK2 -https://raw.github.com/D-Programming-Language/tools/master/rdmd.d, +https://raw.github.com/dlang/tools/master/rdmd.d, Download))) -<h2>Author</h2> +$(H2 Author) $(LINK2 http://erdani.org/, Andrei Alexandrescu) ) Macros: - TITLE=rdmd - WIKI=rdmd - CATEGORY_DOWNLOAD=$0 - + TITLE=rdmd + SUBNAV=$(SUBNAV_CLI_REFERENCE) diff --git a/regular-expression.dd b/regular-expression.dd deleted file mode 100644 index 0f38c02d57..0000000000 --- a/regular-expression.dd +++ /dev/null @@ -1,187 +0,0 @@ -Ddoc - -$(D_S Regular Expressions, - - $(P Regular expressions are a powerful tool for - pattern matching on strings of text. They - are built in to the core of languages like Perl, - Ruby, and Javascript. Perl and Ruby are particulary - reknowned for adroitly handling regular expressions. - So why aren't they part of the D core language? - Read on and see how they're done in D compared with Ruby. - ) - - $(P This article explains how to use regular expressions - in D. It doesn't explain regular expressions themselves, - after all, people have written entire books on that topic. - D's specific implementation of regular expressions - is entirely contained in the Phobos library module - $(LINK2 phobos/std_regexp.html, std.regexp). - For a more advanced treatment of using regular expressions - in conjuction with template metaprogramming, see - $(LINK2 templates-revisited.html, Templates Revisited). - ) - - $(P In Ruby a regular expression can be created - as a special literal: - ) - -$(RUBY -r = /pattern/ -s = /p[1-5]\s*/ -) - - $(P D doesn't have special literals for them, but they can - be created:) - ---- -r = RegExp("pattern"); -s = RegExp(r"p[1-5]\s*"); ---- - - $(P If the $(I pattern) contains backslash characters \, - wysiwyg string literals are used, which have the $(SINGLEQUOTE r) prefix - to the string. $(I r) and $(I s) are of type $(B RegExp), but - we can use type inference to declare and assign them automatically: - ) - ---- -auto r = RegExp("pattern"); -auto s = RegExp(r"p[1-5]\s*"); ---- - - $(P To check for a match of a string $(I s) with a regular expression - in Ruby, use the =~ operator, which returns the index of the - first match:) - -$(RUBY -s = "abcabcabab" -s =~ /b/ /* match, returns 1 */ -s =~ /f/ /* no match, returns nil */ -) - - $(P In D this looks like: - ) - ---- -auto s = "abcabcabab"; -std.regexp.find(s, "b"); /* match, returns 1 */ -std.regexp.find(s, "f"); /* no match, returns -1 */ ---- - - $(P Note the equivalence to std.string.find, which searches for - substring matches rather than regular expression matches.) - - $(P The Ruby =~ operator sets some implicitly defined variables - based on the result:) - -$(RUBY -s = "abcdef" -if s =~ /c/ - "#{$`}[#{$&}]#{$'}" /* generates string ab[c]def -) - - $(P The function std.regexp.search() returns a RegExp object - describing the match, which can be exploited: - ) - ---- -auto m = std.regexp.search("abcdef", "c"); -if (m) - writefln("%s[%s]%s", m.pre, m.match(0), m.post); ---- - - $(P Or even more concisely as: - ) - ---- -if (auto m = std.regexp.search("abcdef", "c")) - writefln("%s[%s]%s", m.pre, m.match(0), m.post); // writes ab[c]def ---- - -<h2>Search and Replace</h2> - - $(P Search and replace gets more interesting. To replace the - occurrences of "a" with "ZZ" in Ruby; the first occurrence, then - all: - ) - -$(RUBY -s = "Strap a rocket engine on a chicken." -s.sub(/a/, "ZZ") // result: StrZZp a rocket engine on a chicken. -s.gsub(/a/, "ZZ") // result: StrZZp ZZ rocket engine on ZZ chicken. -) - - $(P In D:) - ---- -s = "Strap a rocket engine on a chicken."; -sub(s, "a", "ZZ"); // result: StrZZp a rocket engine on a chicken. -sub(s, "a", "ZZ", "g"); // result: StrZZp ZZ rocket engine on ZZ chicken. ---- - - $(P The replacement string can reference the matches using - the $&, $$, $', $`, $0 .. $99 notation:) - ---- -sub(s, "[ar]", "[$&]", "g"); // result: St[r][a]p [a] [r]ocket engine on [a] chicken. ---- - - $(P Or the replacement string can be provided by a delegate:) - ---- -sub(s, "[ar]", - (RegExp m) { return toupper(m.match(0)); }, - "g"); // result: StRAp A Rocket engine on A chicken. ---- - -($(D toupper()) comes from $(LINK2 phobos/std_string.html, std.string).) - -<h2>Looping</h2> - - $(P It's possible to search over all matches within - a string:) - ---- -import std.stdio; -import std.regexp; - -void main() -{ - foreach(m; RegExp("ab").search("abcabcabab")) - { - writefln("%s[%s]%s", m.pre, m.match(0), m.post); - } -} -// Prints: -// [ab]cabcabab -// abc[ab]cabab -// abcabc[ab]ab -// abcabcab[ab] ---- - -<h2>Conclusion</h2> - - $(P D regular expression handling is as powerful as Ruby's. But - its syntax isn't as concise:) - - $(UL - - $(LI Regular expression literal syntax - doing so would - make it impossible to perform lexical analysis without also - doing syntactic or semantic analysis.) - - $(LI Implicit naming of match variables - this causes problems - with name collisions, and just doesn't - fit with the rest of the way D works.) - - ) - - $(P But it is just as powerful. - ) -) -Macros: - TITLE=Regular Expressions - WIKI=RegularExpression - CATEGORY_ARTICLES=$0 - RUBY=$(CCODE $0) diff --git a/resources.dd b/resources.dd new file mode 100644 index 0000000000..8ae7de6762 --- /dev/null +++ b/resources.dd @@ -0,0 +1,6 @@ +Ddoc + +$(D_S Resources, $(NAVIGATION_RESOURCES)) + +Macros: + TITLE=Resources diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000000..42bebf3b15 --- /dev/null +++ b/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Disallow: /phobos-prerelease/ +Disallow: /library-prerelease/ +Disallow: /cutting-edge/ diff --git a/safed.dd b/safed.dd deleted file mode 100644 index af41c5a7b2..0000000000 --- a/safed.dd +++ /dev/null @@ -1,265 +0,0 @@ -Ddoc - -$(D_S SafeD—The Safe Subset of D, - - $(P - $(SMALL by Bartosz Milewski, a member of the D design team) - ) - -<div align="right">$(DIGG)</div> - - $(P - I've seen some very good programmers move away from C++ in favor of languages like Java or C#. Being a hard-core C++ programmer myself, I wondered why anyone would want to switch to a less powerful and less efficient language. Mind you, I could understand why a newcomer would opt for a simpler, flatter-learning-curve language but, once somebody invested the time and effort to become proficient in C++, why in the world would they want to abandon it? - ) - - $(P - The universal reason I've heard from the turncoats was $(DOUBLEQUOTE productivity.) The consensus seems to be that programmers are more productive using Java, C#, Ruby, or Python then they are using C++. - ) - - $(P - What are the major impediments to productive programming in C++? - ) - - $(P - $(B Horrible syntax) is one. This is actually more serious than it sounds. A good programmer can probably master some pretty horrible syntaxes given enough time. The problem is that C++ syntax and grammar is not only human-unfriendly but also parser-hostile. The fact that the Java market is saturated with productivity boosting tools is the reflection of the language's parseability. I have to yet see a C++ programming environment that would offer such powerful refactoring tools as are commonplace in Java. - ) - - $(P - Language safety is the other major factor. C++ is notorious for presenting a never ending gallery of opportunities to shoot yourself in the foot. In fact C++ not only provides the opportunity to write dangerous code, it $(I encourages ) it. At some point a major C++ compiler vendor marked a portion of STL algorithms as "deprecated" because of safety concerns. In particular the C++ Standard Library, in accordance with the spirit of C++, extends the number of ways a buffer overflow bug might sneak into your program. - ) - - $(P - One notorious example is the $(CODE std::swap_ranges) algorithm, which takes three iterators. The first two iterators are supposed to delimit one range, the third one marks the beginning of the second range. No testing is done whether the second range doesn't extend past the end of the container. When it does, virus writers rejoice! - ) - - $(P - The pipe dream of programming language designers is to be able to guarantee that if a program compiles successfully, it will work. Of course you have to be reasonable about your definition of a "working" program. For instance, you might require that the program will never get "stuck"—a term which has a precise meaning in computer science, but loosely means that the program will not GP-fault on you (it is stuck in the sense that there is no well-defined system-independent next step). Languages that have such a property are called "sound". - ) - - $(P - Guess what, there is a well-defined (and meaningful) subset of Java that is sound. Real-life Java programs, for practical reasons, stray outside of this sound subset; but at least the use of unsafe features is less prevalent and easier to spot in a Java program than it is in a C++ program. In practice, a Java compiler will detect more bugs in your program than a C++ compiler, and that translates directly into less time spent debugging—ergo, higher productivity. - ) - - $(P - So what are the good features of C++? - ) - - $(P - Performance is one. It's really hard to beat C++ performance. If your program has to be fast and responsive you have little choice but to write it in C++ (or, in rare cases, in C or assembly). - ) - - $(P - Then there are the low-level features of C++ that let you write programs interacting directly with hardware. For instance, C and C++ are still kings of embedded programming. - ) - - $(P - C++ offers powerful abstractions, in particular the ability to write generic code. Java and C# have their own generics but they are feeble compared to what C++ has to offer. - ) - - $(P - All these features make C++ an ideal language for writing operating - systems. Operating systems are huge programs that have to be fast and - interact directly with hardware. But even outside operating systems - there are a lot of applications that have to be large and fast. - ) - - $(P - So it looks like the programming world could be nicely partitioned between C++, Java, C# and the likes. And it all makes sense as long as you believe in the unavoidability of tradeoffs. But there is no law of nature that says, $(I You have to trade productivity for power). - ) - - $(P - What about a language that is built like an onion. It has a reasonably simple and safe core, which is not unlike Java or C#. A programmer can quickly master a safe subset of it and be as productive as a Java programmer (if not more). And what if the safe subset offered performance that was comparable to C++? - ) - - $(P - And then, the same language has outer layers that can be mastered gradually, as the need arises. It offers low-level features to grind the hardware, and high-level features to generate code on demand. It offers modularity and implementation hiding. It has unrivaled compile time features that enable lightning fast runtime performance. - ) - - $(P - I'll let you in on a secret, this language is D. - ) - - $(SECTION2 Programming Pitfalls, - - - $(P - Did you know that the famous $(CODE"Hello World!") program, which is usually the first program people write in C, exposes some of the most dangerous features of the language? It contains this statement: - ) - - $(CCODE -printf ("Hello World!\n");) - - Consider the signature of $(CODE printf): - - $(CCODE -int printf (const char * restrict format, ...); ) - - $(P - ($(CODE restrict) is a new C keyword.) First of all, it's a function that takes a variable number of arguments. The number and the types of arguments are encoded in the format string. - ) - - $(P - When is the match between the format and the argument list checked? Not at compile time—the compiler has no understanding of the format string (although some compilers may issue warnings if the string is statically known). At runtime then? Well, guess again. Consider this: If the programmer makes a mistake of calling printf with too few arguments, he or she will not get a nice error code or exception. Here's what the C Standard says about this situation: - ) - -<table border="1" cellpadding="4" cellspacing="0"><tr><td bgcolor="#ffffcc"> - If there are insufficient arguments for the format, the behavior is undefined. -</td></tr></table> - - $(P - Undefined behavior is the worst thing that may happen to a program. If you're lucky, the program will fault and terminate without prejudice. If you're not so lucky, the program will continue in a compromised state and, in the worst case, it will execute malicious code that will take over your computer. - ) - - $(P - The second dangerous feature of $(CODE printf) is its use of a pointer. It is up to the diligence of the programmer to ensure that a pointer points to a valid piece of data. In the $(CODE"Hello World!") example, the pointer points to a null-terminated static string, so we're fine. But the following program will compile too: - ) - - - $(CCODE -char * format = 0; -printf (format); ) - - $(P - Guess what happens. Inside $(CODE printf) the pointer is dereferenced and then all bets are off. Again, citing the C Standard, - ) - -<table border="1" cellpadding="4" cellspacing="0"><tr><td bgcolor="#ffffcc"> - If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined. -</td></tr></table> - - $(P - Let's talk about pointers some more. Every memory allocation returns a valid pointer (unless the program runs out of memory). You might think that dereferencing such a pointer would be safe. That is correct as long as your program doesn't free the allocated memory thus ending the lifetime of the object. After that, you are dealing with a dangling pointer and all bets are off. Again, C Standard is pretty upfront about it. - ) - -<table border="1" cellpadding="4" cellspacing="0"><tr><td bgcolor="#ffffcc"> - Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime. -</td></tr></table> - - $(P - As you can see, C was not designed for the faint of heart. It's a low-level language and the programmer better know what he or she is doing or suffer the consequences. - ) - - $(P - C++ is different though, right? - ) - - $(P - Throughout its history, C++ has been struggling with C legacy. A lot of constructs have been provided to patch the unsafe features of C. For instance, the $(CODE"Hello World!") program in C++ might be transformed to a safer version. - ) - - - $(CCODE -std:cout << "Hello World!" << std::endl; ) - - $(P - There is no variable argument count, and the $(CODE std::cout) object is smart enough to understand the types of arguments passed to it (still, many programmers continue using $(CODE printf) in C++, if only for its syntactic simplicity). - ) - - $(P - Unlike in C, memory allocation in C++ is typed and combined with object construction (as long as you stay away from $(CODE malloc) and $(CODE free)). That's the good part. However, objects still have to be explicitly recycled (deleted). And after recycling, the program is still left with dangling pointers, whose dereferencing—you guessed it—leads to undefined behavior. - ) - - $(P - Whereas pointers were important in C, C++ embraced them as the main vehicle for the Standard Library. STL algorithms use iterators, objects that are either pointers themselves or imitate the behavior (and the pitfalls) of pointers. Just like with pointers, a programmer's error in using iterators leads to undefined behavior (see the $(CODE swap_range) example). - ) - - $(P - In response to C/C++'s inherent lack of safety, languages like Java and C# took a different path. They either ban pointers altogether or relegate them to special "unsafe" blocks. Memory management, with its risk of accessing recycled data, is taken away from the programmer and dealt with by automatic garbage collection. There are many other simplifications and safety improvements over C++. Unfortunately they all come at the expense of expressive power and performance. - ) -) - - -$(SECTION2 The SafeD Subset, - - - $(P - In D, we expect the vast majority of programmers to operate within the safe subset of D, which we call SafeD. The safety and the ease of use of SafeD is comparable to Java—in fact Java programs can be machine-translated into this safe subset of D. SafeD is easy to learn and it keeps the programmers away from undefined behaviors. It is also very efficient. - ) - - $(P - When you enter SafeD, you leave your pointers, unchecked casts and unions at the door. Memory management is provided to you courtesy of Garbage Collection. Class objects are passed around using opaque handles. Arrays and strings are bound-checked (it's possible to turn the checks off with a compiler switch, but then you're no longer in SafeD). You may still write code that will throw a runtime exception (e.g., array out-of-bounds error, or uninitialized-class-object error), but you won't be able to overwrite memory that hasn't been allocated to you or that has already been recycled. - ) - - $(P - Let's look at the $(CODE "Hello World!") program in D. On the face of it, it's not much different than its C counterpart: - ) - - --- -writeln ("Hello Safe World!"); - --- - - $(P - The function $(CODE writeln) is the equivalent of the C $(CODE printf) (more precisely, it's the representative of a family of output functions including $(CODE write) and its formatting versions, $(CODE writef) and $(CODE writefln)). Just like $(CODE printf), $(CODE writeln) accepts a variable number of arguments of arbitrary types. But here the similarity ends. As long as you pass SafeD-arguments to $(CODE writeln), you are guaranteed not to encounter any undefined behavior. Here, $(CODE writeln) is called with a single argument of the type $(CODE string). In contrast to C, D $(CODE string) is not a pointer. It is an array of $(CODE immutable char), and arrays are a built into the safe subset of D. - ) - - $(P - You might be interested to know how the safety of $(CODE writeln) is accomplished in D. One possible approach would have been to make $(CODE writeln) a compiler intrinsic, so that correct code would be generated on a case-by-case basis. The beauty of D is that it gives a sophisticated programmer tools that allow such case-by-case code generation of code. The advanced features used in the implementation of writeln are: - $(UL - $(LI Compile-time code generation using templates, and) - $(LI A safe mechanism for dealing with variable number of arguments using tuples.) - ) - -) - -$(SECTION2 SafeD Libraries, - - $(P - One of the major differences between Java and D is that D has enough power to let an advanced programmer implement libraries that can be used within SafeD. - ) - - $(P - A lot of advanced features of D are compatible with SafeD, as long as they don't force the user to use unsafe types. For instance, a library may provide the implementation of a generic list. The list can be instantiated with any type, in particular with a pointer type. A list of pointers, by definition, cannot be safe, because pointer arithmetic is unsound. However, a list of ints or class objects can and should be safe. That's why such ageneric lists can be used in SafeD, even though their usage outside of SafeD may be unsafe. - ) - - $(P - Moreover, it might be more efficient to base the internal implementation of a list on pointers. As long as these pointers are not exposed to the client, such an implementation might be certified to be SafeD compatible<sup>1</sup> . You can have a cake (advanced features of D) and eat it too (take advantage of them in SafeD). - ) -) - - -$(SECTION2 One User's Experience, - - $(P - Even before I came up with the idea of SafeD<sup>2</sup>, I tried to - restrict myself to the safe subset of D for most of my projects. I was - surprised how much could be accomplished and how my productivity soared. - I also showed SafeD to my co-worker, a C++ programmer, and he was able - to learn it in a very short time. - ) - - $(P - So far my experience has been that if a SafeD program compiles without - errors then, in a vast majority of cases, it runs without errors, and - does what I want it to do. That definitely hasn't been my experience - with C++. - ) - - $(P - What is even more surprising to me is that I was able to accomplish all - that with almost non-existing support from tools and with a compiler - that excels in cryptic error messages. D is still lacking a lot of - infrastructure, but I can imagine how easy programming will be when a - critical mass of productivity tools sprouts around it. And unlike C++, D - is easy to parse and its front end is open source. So there are no - barriers to entry for tool writers. - ) - -$(SECTION2 Footnotes, - $(P - $(OL - $(LI There is no central authority to issue such certifications, each library provider has to establish a level of trust with its clients. In particular, you should expect the D standard library to be SafeD certified by the compiler provider.) - $(LI The name, SafeD, was proposed by David B. Held.) - ) - ) -) -) -$(SECTION2 Acknowledgments, -$(P Many thanks go to the rest of the D design team for valuable feedback and corrections to this article) -) -) -) - -Macros: - TITLE=SafeD - WIKI=SafeD - CATEGORY_ARTICLES=$0 diff --git a/search.dd b/search.dd new file mode 100644 index 0000000000..d92a9891c5 --- /dev/null +++ b/search.dd @@ -0,0 +1,6 @@ +Ddoc + +$(D_S Search, $(SEARCH_BOX)) + +Macros: + TITLE=Search diff --git a/security.dd b/security.dd new file mode 100644 index 0000000000..2d1af34a2c --- /dev/null +++ b/security.dd @@ -0,0 +1,24 @@ +Ddoc + +$(D_S $(TITLE), + +If you have any security-related concerns, please don't hesitate to contact us at +$(LINK2 mailto:security@dlang.org, security@dlang.org). + +$(H3 Sending encrypted messages) + +You can encrypt your message using our public PGP key: + +$(PRE +pub rsa4096/0x8FF049B29638EDD2 2018-07-05 [SC] [expires: 2020-07-04] + Key fingerprint = E05A B3C3 0EC0 C7DD 56D9 9B0C 8FF0 49B2 9638 EDD2 +uid DLang Security Team $(LT)security@dlang.org$(GT) +sub rsa4096/0x65301656B271FEA0 2018-07-05 [E] [expires: 2020-07-04] +) + +$(P You can download the public key $(LINK2 d-security.asc,here).) + +) + +Macros: + TITLE=D Security Team diff --git a/simd.dd b/simd.dd deleted file mode 100644 index 996963fa94..0000000000 --- a/simd.dd +++ /dev/null @@ -1,212 +0,0 @@ -Ddoc - -$(SPEC_S Vector Extensions, - - $(P Modern CPUs often support specialized vector types and vector - operations, sometimes called "media instructions". - Vector types are a fixed array of floating or integer types, and - vector operations operate simultaneously on them, thus achieving - great speedups.) - - $(P When the compiler takes advantage of these instructions with standard D code - to speed up loops over arithmetic data, this is called auto-vectorization. - Auto-vectorization, however, has had only limited success and has not - been able to really take advantage of the richness (and often quirkiness) - of the native vector instructions. - ) - - $(P D has the array operation notation, such as: - ) - ---- -int[] a,b; -... -a[] += b[]; ---- - - $(P which can be vectorized by the compiler, but again success is limited - for the same reason auto-vectorization is. - ) - - $(P The difficulties with trying to use vector instructions on regular arrays - are:) - - $(OL - $(LI The vector types have stringent alignment requirements that are not - and cannot be met by conventional arrays.) - $(LI C ABI's often have vector extensions and have special name mangling - for them, call/return conventions, and symbolic debug support.) - $(LI The only way to get at the full vector instruction set would be to use - inline assembler - but the compiler cannot do register allocation across - inline assembler blocks (or other optimizations), leading to poor code - performance.) - $(LI Interleaving conventional array code with vector operations on the same - data can unwittingly lead to extremely poor runtime performance.) - ) - - $(P These issues are cleared up by using special vector types. - ) - -<h2>$(D core.simd)</h2> - - $(P Vector types and operations are introduced to D code by importing - $(CORE_SIMD):) - ---- -import core.simd; ---- - - $(P These types and operations will be the ones defined for the architecture - the compiler is targetting. If a particular CPU family has varying - support for vector types, an additional runtime check may be necessary. - The compiler does not emit runtime checks; those must be done by the programmer. - ) - - $(P The types defined will all follow the naming convention:) - -$(GRAMMAR -$(I typeNN) -) - $(P where $(I type) is the vector element type and $(I NN) is the number - of those elements in the vector type. - The type names will not be keywords. - ) - -<h3>Properties</h3> - - $(P Vector types have the property:) - - $(TABLE2 Vector Type Properties, - $(THEAD Property, Description) - $(TROW .array, Returns static array representation) - ) - - $(P All the properties of the static array representation also work.) - -<h3>Conversions</h3> - - $(P Vector types of the same size can be implicitly converted among - each other. Vector types can be cast to the static array representation.) - - $(P Integers and floating point values can be implicitly converted - to their vector equivalents:) - ---- -int4 v = 7; -v = 3 * v; // multiply each element in v by 3 ---- - -<h3>Accessing Individual Vector Elements</h3> - - $(P They cannot be accessed directly, but can be when converted to - an array type:) - ----- -int4 v; -(cast(int*)&v)[3] = 2; // set 3rd element of the 4 int vector -cast(int[4])v[3] = 2; // set 3rd element of the 4 int vector -v.array[3] = 2; // set 3rd element of the 4 int vector -v.ptr[3] = 2; // set 3rd element of the 4 int vector ----- - - -<h3>Conditional Compilation</h3> - - $(P If vector extensions are implemented, the - $(LINK2 version.html#PredefinedVersions, version identifier) - $(D D_SIMD) is set.) - - $(P Whether a type exists or not can be tested at compile time with - an $(LINK2 expression.html#IsExpression, $(I IsExpression)): - ) - ---- -static if (is($(I typeNN))) - ... yes, it is supported ... -else - ... nope, use workaround ... ---- - - $(P Whether a particular operation on a type is supported can be tested - at compile time with: - ) - ---- -float4 a,b; -static if (__traits(compiles, a+b)) - ... yes, it is supported ... -else - ... nope, use workaround ... ---- - - $(P For runtime testing to see if certain vector instructions are - available, see the functions in $(LINK2 phobos/core_cpuid.html, core.cpuid). - ) - - $(P A typical workaround would be to use array vector operations instead:) - ---- -float4 a,b; -static if (__traits(compiles, a/b)) - c = a / b; -else - c[] = a[] / b[]; ---- - -<h2>X86 And X86_64 Vector Extension Implementation</h2> - - $(P The rest of this document describes the specific implementation of the - vector types for the X86 and X86_64 architectures. - ) - - $(P The vector extensions are currently implemented for the OS X 32 - bit target, and all 64 bit targets.) - - $(P $(CORE_SIMD) defines the following types: ) - - $(TABLE2 Vector Types, - $(THEAD Type Name, Description, gcc Equivalent) - $(TROW void16, 16 bytes of untyped data, $(I no equivalent)) - $(TROW byte16, 16 $(D byte)'s, $(D unsigned char __attribute((vector_size(16))))) - $(TROW ubyte16, 16 $(D ubyte)'s, $(D signed char __attribute((vector_size(16))))) - $(TROW short8, 8 $(D short)'s, $(D short __attribute((vector_size(16))))) - $(TROW ushort8, 8 $(D ushort)'s, $(D ushort __attribute((vector_size(16))))) - $(TROW int4, 4 $(D int)'s, $(D int __attribute((vector_size(16))))) - $(TROW uint4, 4 $(D uint)'s, $(D unsigned __attribute((vector_size(16))))) - $(TROW long2, 2 $(D long)'s, $(D long __attribute((vector_size(16))))) - $(TROW ulong2, 2 $(D ulong)'s, $(D unsigned long __attribute((vector_size(16))))) - $(TROW float4, 4 $(D float)'s, $(D float __attribute((vector_size(16))))) - $(TROW double2, 2 $(D double)'s, $(D double __attribute((vector_size(16))))) - ) - - $(P Note: for 32 bit gcc, it's $(D long long) instead of $(D long).) - - $(TABLE2 Supported Vector Operators, - $(THEAD Operator,void16,byte16,ubyte16,short8,ushort8,int4,uint4,long2,ulong2,float4,double2) - $(TROW =,$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) - $(TROW + +=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) - $(TROW - -=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) - $(TROW * *=,$(N),$(N),$(N),$(Y),$(Y),$(N),$(N),$(N),$(N),$(Y),$(Y)) - $(TROW / /=,$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(Y),$(Y)) - $(TROW & &=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) - $(TROW | |=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) - $(TROW ^ ^=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) - $(TROW $(I unary)~,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) - $(TROW $(I unary)+,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) - $(TROW $(I unary)-,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) - ) - - $(P Operators not listed are not supported at all.) - -<h3>Vector Operation Intrinsics</h3> - - $(P See $(CORE_SIMD) for the supported intrinsics.) -) - -Macros: - TITLE=Vector Extensions - WIKI=Float - Y=× - N=– - CORE_SIMD=$(LINK2 phobos/core_simd.html, $(D core.simd)) - CATEGORY_SPEC=$0 diff --git a/sitemap-template.dd b/sitemap-template.dd index b252704eb0..362fd5ca36 100644 --- a/sitemap-template.dd +++ b/sitemap-template.dd @@ -3,6 +3,5 @@ Ddoc $(D_S Sitemap, $(LINKS)) Macros: - TITLE=Sitemap - WIKI=Sitemap - LINKS= \ No newline at end of file + TITLE=Sitemap + LINKS= diff --git a/spec.dd b/spec.dd deleted file mode 100644 index 6c34bae7d1..0000000000 --- a/spec.dd +++ /dev/null @@ -1,60 +0,0 @@ -Ddoc - -$(SPEC_S Table of Contents, - - $(P This is the specification for the D Programming Language. - For more information see - $(LINK2 http://www.d-programming-language.org, d-programming-language.org). - ) - - $(NOT_EBOOK $(P This is also available as a - $(LINK2 http://www.digitalmars.com/d/2.0/dlangspec.mobi, Mobi ebook) or as a - $(AMAZONLINK B005CCQPKK, Kindle ebook).)) - - $(UL - $(TOCENTRY intro, Introduction) - $(TOCENTRY lex, Lexical) - $(TOCENTRY module, Modules) - $(TOCENTRY declaration, Declarations) - $(TOCENTRY type, Types) - $(TOCENTRY property, Properties) - $(TOCENTRY attribute, Attributes) - $(TOCENTRY pragma, Pragmas) - $(TOCENTRY expression, Expressions) - $(TOCENTRY statement, Statements) - $(TOCENTRY arrays, Arrays) - $(TOCENTRY hash-map, Associative Arrays) - $(TOCENTRY struct, Structs & Unions) - $(TOCENTRY class, Classes) - $(TOCENTRY interface, Interfaces) - $(TOCENTRY enum, Enums) - $(V2 $(TOCENTRY const3, Const and Immutable)) - $(TOCENTRY function, Functions) - $(TOCENTRY operatoroverloading, Operator Overloading) - $(TOCENTRY template, Templates) - $(TOCENTRY template-mixin, Template Mixins) - $(TOCENTRY dbc, Contract Programming) - $(TOCENTRY version, Conditional Compilation) - $(V2 $(TOCENTRY traits, Traits)) - $(TOCENTRY errors, Error Handling) - $(TOCENTRY unittest, Unit Tests) - $(TOCENTRY garbage, Garbage Collection) - $(TOCENTRY float, Floating Point) - $(TOCENTRY iasm, Inline Assembler) - $(TOCENTRY ddoc, Embedded Documentation) - $(TOCENTRY interfaceToC, Interfacing To C) - $(V2 $(TOCENTRY cpp_interface, Interfacing To C++)) - $(TOCENTRY portability, Portability Guide) - $(XTOCENTRY html, Embedding D in HTML) - $(TOCENTRY entity, Named Character Entities) - $(V2 $(TOCENTRY memory-safe-d, Memory Safety)) - $(TOCENTRY abi, Application Binary Interface) - ) - -) - -Macros: - TITLE=Table of Contents - WIKI=TOC - CATEGORY_SPEC=$0 - diff --git a/spec/abi.dd b/spec/abi.dd new file mode 100644 index 0000000000..4562a043ca --- /dev/null +++ b/spec/abi.dd @@ -0,0 +1,1086 @@ +Ddoc + +$(SPEC_S Application Binary Interface, + +$(HEADERNAV_TOC) + + $(P A D implementation that conforms to the D ABI (Application Binary + Interface) + will be able to generate libraries, DLLs, etc., that can interoperate + with + D binaries built by other implementations. + ) + +$(H2 $(LNAME2 c_abi, C ABI)) + + $(P The C ABI referred to in this specification means the C Application + Binary Interface of the target system. + C and D code should be freely linkable together, in particular, D + code shall have access to the entire C ABI runtime library. + ) + +$(H2 $(LNAME2 endianness, Endianness)) + + $(P The $(LINK2 https://en.wikipedia.org/wiki/Endianness, endianness) + (byte order) of the layout of the data + will conform to the endianness of the target machine. + The Intel x86 CPUs are $(I little endian) meaning that + the value 0x0A0B0C0D is stored in memory as: + $(D 0D 0C 0B 0A). + ) + +$(H2 $(LNAME2 basic_types, Basic Types)) + + $(TABLE + $(TROW bool, 8 bit byte with the values 0 for false and 1 for true) + $(TROW byte, 8 bit signed value) + $(TROW ubyte, 8 bit unsigned value) + $(TROW short, 16 bit signed value) + $(TROW ushort, 16 bit unsigned value) + $(TROW int, 32 bit signed value) + $(TROW uint, 32 bit unsigned value) + $(TROW long, 64 bit signed value) + $(TROW ulong, 64 bit unsigned value) + $(TROW cent, 128 bit signed value) + $(TROW ucent, 128 bit unsigned value) + $(TROW float, 32 bit IEEE 754 floating point value) + $(TROW double, 64 bit IEEE 754 floating point value) + $(TROW real, implementation defined floating point value$(COMMA) for x86 it is + 80 bit IEEE 754 extended real) + $(TROW char, 8 bit unsigned value) + $(TROW wchar, 16 bit unsigned value) + $(TROW dchar, 32 bit unsigned value) + ) + +$(H2 $(LNAME2 delegates, Delegates)) + + $(P Delegates are $(I fat pointers) with two parts:) + + $(TABLE2 Delegate Layout, + $(THEAD offset, property, contents) + $(TROW $(D 0), $(D .ptr), context pointer) + $(TROW $(I ptrsize), $(D .funcptr), pointer to function) + ) + + $(P The $(I context pointer) can be a class $(I this) + reference, a struct $(I this) pointer, a pointer to + a closure (nested functions) or a pointer to an enclosing + function's stack frame (nested functions). + ) + +$(H2 $(LNAME2 structs, Structs and Unions)) + + $(P These conform to the target's C ABI struct layout, except:) + + * An `extern(D)` struct or union with no fields has size 1, not 0. + See $(DDSUBLINK spec/struct, struct_layout, Struct Layout). + * Unions are $(RELATIVE_LINK2 name_mangling, name-mangled) as if they were structs. + * The rest of this document treats unions extrinsically the same as structs. + +$(H2 $(LNAME2 classes, Classes)) + + $(P An object consists of:) + + $(TABLE_3COLS Class Object Layout, + $(THEAD size, property, contents) + $(TROW $(I ptrsize), $(D .__vptr), pointer to vtable) + $(TROW $(I ptrsize), $(D .__monitor), monitor) + $(TROW $(I ptrsize)..., $(NBSP), $(ARGS vptrs for any interfaces implemented by this class in left to right, most to least derived, order)) + $(TROW $(D ...), $(D ...), $(ARGS super's non-static fields and super's interface vptrs, from least to most derived)) + $(TROW $(D ...), named fields, non-static fields) + ) + + $(P The vtable consists of:) + +$(TABLE2 Virtual Function Pointer Table Layout, +$(THEAD size, contents) +$(TROW $(I ptrsize), pointer to instance of TypeInfo) +$(TROW $(I ptrsize)..., pointers to virtual member functions) +) + + $(P Casting a class object to an interface consists of adding the offset of + the interface's corresponding vptr to the address of the base of the object. + Casting an interface ptr back to the class type it came from involves getting + the correct offset to subtract from it from the object.Interface entry at vtbl[0]. + Adjustor thunks are created and pointers to them stored in the method entries in the vtbl[] + in order to set the this pointer to the start of the object instance corresponding + to the implementing method. + ) + + $(P An adjustor thunk looks like:) + +$(CCODE + ADD EAX,offset + JMP method +) + + $(P The leftmost side of the inheritance graph of the interfaces all share + their vptrs, this is the single inheritance model. + Every time the inheritance graph forks (for multiple inheritance) a new vptr is created + and stored in the class' instance. + Every time a virtual method is overridden, a new vtbl[] must be created with + the updated method pointers in it. + ) + + $(P The class definition:) + +--------- +class XXXX +{ + .... +}; +--------- + + $(P Generates the following:) + + $(UL + $(LI An instance of Class called ClassXXXX.) + + $(LI A type called StaticClassXXXX which defines all the static members.) + + $(LI An instance of StaticClassXXXX called StaticXXXX for the static members.) + ) + +$(H2 $(LNAME2 interfaces, Interfaces)) + + $(P An interface is a pointer to a pointer to a vtbl[]. + The vtbl[0] entry is a pointer to the corresponding + instance of the object.Interface class. + The rest of the $(D vtbl[1..$]) entries are pointers to the + virtual functions implemented by that interface, in the + order that they were declared. + ) + + $(P A COM interface differs from a regular interface in that + there is no object.Interface entry in $(D vtbl[0]); the entries + $(D vtbl[0..$]) are all the virtual function pointers, in the order + that they were declared. + This matches the COM object layout used by Windows. + ) + $(P A C++ interface differs from a regular interface in that + it matches the layout of a C++ class using single inheritance + on the target machine. + ) + +$(H2 $(LNAME2 arrays, Arrays)) + + $(P A dynamic array consists of:) + +$(TABLE2 Dynamic Array Layout, +$(THEAD offset, property, contents) +$(TROW $(D 0), $(D .length), array dimension) +$(TROW $(D size_t), $(D .ptr), pointer to array data) +) + + $(P A dynamic array is declared as:) + +--------- +type[] array; +--------- + + whereas a static array is declared as: + +--------- +type[dimension] array; +--------- + + $(P Thus, a static array always has the dimension statically available as part of the type, and + so it is implemented like in C. Static arrays and Dynamic arrays can be easily converted back + and forth to each other. + ) + +$(H2 $(LNAME2 associative_arrays, Associative Arrays)) + + $(P Associative arrays consist of a pointer to an opaque, implementation + defined type.) + + $(P The current implementation is contained in and defined by + $(DRUNTIMESRC rt/aaA.d). + ) + +$(H2 $(LNAME2 references_types, Reference Types)) + + $(P D has reference types, but they are implicit. For example, classes are always + referred to by reference; this means that class instances can never reside on the stack + or be passed as function parameters. + ) + + +$(H2 $(LNAME2 name_mangling, Name Mangling)) + + $(P D accomplishes typesafe linking by $(I mangling) a D identifier + to include scope and type information. + ) + +$(GRAMMAR +$(GNAME MangledName): + $(B _D) $(GLINK QualifiedName) $(GLINK Type) + $(B _D) $(GLINK QualifiedName) $(B Z) $(GREEN // Internal) +) + + $(P The $(GLINK Type) above is the type of a variable or the return type of a function. + This is never a $(GLINK TypeFunction), as the latter can only be bound to a value via a pointer + to a function or a delegate.) + +$(GRAMMAR +$(GNAME QualifiedName): + $(GLINK SymbolFunctionName) + $(GLINK SymbolFunctionName) $(GSELF QualifiedName) + +$(GNAME SymbolFunctionName): + $(GLINK SymbolName) + $(GLINK SymbolName) $(GLINK TypeFunctionNoReturn) + $(GLINK SymbolName) $(B M) $(GLINK TypeModifiers)$(OPT) $(GLINK TypeFunctionNoReturn) +) + + $(P The $(B M) means that the symbol is a function that requires + a $(D this) pointer. Class or struct fields are mangled without $(B M). + To disambiguate $(B M) from being a $(GLINK Parameter) with modifier `scope`, the + following type needs to be checked for being a $(GLINK TypeFunction).) + +$(GRAMMAR +$(GNAME SymbolName): + $(GLINK LName) + $(GLINK TemplateInstanceName) + $(GLINK IdentifierBackRef) + $(B 0) $(GREEN // anonymous symbols) +) + + $(P Template Instance Names have the types and values of its parameters + encoded into it: + ) + +$(GRAMMAR +$(GNAME TemplateInstanceName): + $(GLINK TemplateID) $(GLINK LName) $(GLINK TemplateArgs) $(B Z) + +$(GNAME TemplateID): + $(B __T) + $(B __U) $(GREEN // for symbols declared inside template constraint) + +$(GNAME TemplateArgs): + $(GLINK TemplateArg) + $(GLINK TemplateArg) $(GSELF TemplateArgs) + +$(GNAME TemplateArg): + $(GLINK TemplateArgX) + $(B H) $(GLINK TemplateArgX) +) + + $(P If a template argument matches a specialized template parameter, the argument + is mangled with prefix $(B H).) + +$(GRAMMAR +$(GNAME TemplateArgX): + $(B T) $(GLINK Type) + $(B V) $(GLINK Type) $(GLINK Value) + $(B S) $(GLINK QualifiedName) + $(B X) $(GLINK Number) $(I ExternallyMangledName) +) + + $(P $(I ExternallyMangledName) can be any series of characters allowed on the + current platform, e.g. generated by functions with C++ linkage or annotated + with `pragma(mangle,...)`.) + +$(GRAMMAR +$(GNAME Values): + $(GLINK Value) + $(GLINK Value) $(GSELF Values) + +$(GNAME Value): + $(B n) + $(B i) $(GLINK Number) + $(B N) $(GLINK Number) + $(B e) $(GLINK HexFloat) + $(B c) $(GLINK HexFloat) $(B c) $(GLINK HexFloat) + $(GLINK CharWidth) $(GLINK Number) $(B _) $(GLINK HexDigits) + $(B A) $(GLINK Number) $(GLINK Values) + $(B S) $(GLINK Number) $(GLINK Values) + $(B f) $(GLINK MangledName) + +$(GNAME HexFloat): + $(B NAN) + $(B INF) + $(B NINF) + $(B N) $(GLINK HexDigits) $(B P) $(GLINK Exponent) + $(GLINK HexDigits) $(B P) $(GLINK Exponent) + +$(GNAME Exponent): + $(B N) $(GLINK Number) + $(GLINK Number) + +$(GNAME HexDigits): + $(GLINK HexDigit) + $(GLINK HexDigit) $(GLINK HexDigits) + +$(GNAME HexDigit): + $(GLINK Digit) + $(B A) + $(B B) + $(B C) + $(B D) + $(B E) + $(B F) + +$(GNAME CharWidth): + $(B a) + $(B w) + $(B d) +) + + $(DL + $(DT $(B n)) + $(DD is for $(B null) arguments.) + + $(DT $(B i) $(GLINK Number)) + $(DD is for positive numeric literals (including + character literals).) + + $(DT $(B N) $(GLINK Number)) + $(DD is for negative numeric literals.) + + $(DT $(B e) $(GLINK HexFloat)) + $(DD is for real and imaginary floating point literals.) + + $(DT $(B c) $(GLINK HexFloat) $(B c) $(GLINK HexFloat)) + $(DD is for complex floating point literals.) + + $(DT $(GLINK CharWidth) $(GLINK Number) $(D _) $(GLINK HexDigits)) + $(DD $(GLINK CharWidth) is whether the characters + are 1 byte ($(B a)), 2 bytes ($(B w)) or 4 bytes ($(B d)) in size. + $(GLINK Number) is the number of characters in the string. + The $(GLINK HexDigits) are the hex data for the string. + ) + + $(DT $(B A) $(GLINK Number) $(GLINK Values)) + $(DD An array or asssociative array literal. + $(GLINK Number) is the length of the array. + $(GLINK Value) is repeated $(GLINK Number) times for a normal array, + and 2 * $(GLINK Number) times for an associative array. + ) + + $(DT $(B S) $(GLINK Number) $(GLINK Values)) + $(DD A struct literal. $(GLINK Value) is repeated $(GLINK Number) times. + ) + ) + +$(GRAMMAR +$(GNAME Name): + $(GLINK Namestart) + $(GLINK Namestart) $(GLINK Namechars) + +$(GNAME Namestart): + $(B _) + $(I Alpha) + +$(GNAME Namechar): + $(GLINK Namestart) + $(GLINK Digit) + +$(GNAME Namechars): + $(GLINK Namechar) + $(GLINK Namechar) $(GSELF Namechars) +) + + $(P A $(GLINK Name) is a standard D $(DDSUBLINK spec/lex, identifiers, identifier).) + +$(GRAMMAR +$(GNAME LName): + $(GLINK Number) $(GLINK Name) + $(GLINK Number) $(B __S) $(GLINK Number) $(GREEN // function-local parent symbols) + +$(GNAME Number): + $(GLINK Digit) + $(GLINK Digit) $(GSELF Number) + +$(GNAME Digit): + $(B 0) + $(B 1) + $(B 2) + $(B 3) + $(B 4) + $(B 5) + $(B 6) + $(B 7) + $(B 8) + $(B 9) +) + + $(P An $(GLINK LName) is a name preceded by a $(GLINK Number) giving + the number of characters in the $(GLINK Name). + ) + +$(H3 $(LNAME2 back_ref, Back references)) + + $(P Any $(GLINK LName) or non-basic $(GLINK Type) (i.e. any type + that does not encode as a fixed one or two character sequence) that has been + emitted to the mangled symbol before will not be emitted again, but is referenced + by a special sequence encoding the relative position of the original occurrence in the mangled + symbol name.) + + $(P Numbers in back references are encoded with base 26 by upper case letters $(B A) - $(B Z) for higher digits + but lower case letters $(B a) - $(B z) for the last digit.) + +$(GRAMMAR +$(GNAME TypeBackRef): + $(B Q) $(GLINK NumberBackRef) + +$(GNAME IdentifierBackRef): + $(B Q) $(GLINK NumberBackRef) + +$(GNAME NumberBackRef): + $(I lower-case-letter) + $(I upper-case-letter) $(GLINK NumberBackRef) +) + + $(P To distinguish between the type of the back reference a look-up of the back referenced character is necessary: + An identifier back reference always points to a digit $(B 0) to $(B 9), while a type back reference always points + to a letter.) + +$(H3 $(LNAME2 type_mangling, Type Mangling)) + + $(P Types are mangled using a simple linear scheme:) + +$(GRAMMAR +$(GNAME Type): + $(GLINK TypeModifiers)$(OPT) $(GLINK TypeX) + $(GLINK TypeBackRef) + +$(GNAME TypeX): + $(GLINK TypeArray) + $(GLINK TypeStaticArray) + $(GLINK TypeAssocArray) + $(GLINK TypePointer) + $(GLINK TypeFunction) + $(GLINK TypeIdent) + $(GLINK TypeClass) + $(GLINK TypeStruct) + $(GLINK TypeEnum) + $(GLINK TypeTypedef) + $(GLINK TypeDelegate) + $(GLINK TypeVoid) + $(GLINK TypeByte) + $(GLINK TypeUbyte) + $(GLINK TypeShort) + $(GLINK TypeUshort) + $(GLINK TypeInt) + $(GLINK TypeUint) + $(GLINK TypeLong) + $(GLINK TypeUlong) + $(GLINK TypeCent) + $(GLINK TypeUcent) + $(GLINK TypeFloat) + $(GLINK TypeDouble) + $(GLINK TypeReal) + $(GLINK TypeIfloat) + $(GLINK TypeIdouble) + $(GLINK TypeIreal) + $(GLINK TypeCfloat) + $(GLINK TypeCdouble) + $(GLINK TypeCreal) + $(GLINK TypeBool) + $(GLINK TypeChar) + $(GLINK TypeWchar) + $(GLINK TypeDchar) + $(GLINK TypeNoreturn) + $(GLINK TypeNull) + $(GLINK TypeTuple) + $(GLINK TypeVector) + +$(GNAME TypeModifiers): + $(GLINK Const) + $(GLINK Wild) + $(GLINK Wild) $(GLINK Const) + $(GLINK Shared) + $(GLINK Shared) $(GLINK Const) + $(GLINK Shared) $(GLINK Wild) + $(GLINK Shared) $(GLINK Wild) $(GLINK Const) + $(GLINK Immutable) + +$(GNAME Shared): + $(B O) + +$(GNAME Const): + $(B x) + +$(GNAME Immutable): + $(B y) + +$(GNAME Wild): + $(B Ng) + +$(GNAME TypeArray): + $(B A) $(GLINK Type) + +$(GNAME TypeStaticArray): + $(B G) $(GLINK Number) $(GLINK Type) + +$(GNAME TypeAssocArray): + $(B H) $(GLINK Type) $(GLINK Type) + +$(GNAME TypePointer): + $(B P) $(GLINK Type) + +$(GNAME TypeVector): + $(B Nh) $(GLINK Type) + +$(GNAME TypeFunction): + $(GLINK TypeFunctionNoReturn) $(GLINK Type) + +$(GNAME TypeFunctionNoReturn): + $(GLINK CallConvention) $(GLINK FuncAttrs)$(OPT) $(GLINK Parameters)$(OPT) $(GLINK ParamClose) + +$(GNAME CallConvention): + $(B F) $(GREEN // D) + $(B U) $(GREEN // C) + $(B W) $(GREEN // Windows) + $(B R) $(GREEN // C++) + $(B Y) $(GREEN // Objective-C) + +$(GNAME FuncAttrs): + $(GLINK FuncAttr) + $(GLINK FuncAttr) $(GSELF FuncAttrs) + +$(GNAME FuncAttr): + $(GLINK FuncAttrPure) + $(GLINK FuncAttrNothrow) + $(GLINK FuncAttrRef) + $(GLINK FuncAttrProperty) + $(GLINK FuncAttrNogc) + $(GLINK FuncAttrReturn) + $(GLINK FuncAttrScope) + $(GLINK FuncAttrTrusted) + $(GLINK FuncAttrSafe) + $(GLINK FuncAttrLive) +) + + $(P Function attributes are emitted in the order as listed above, with the exception of `return` and `scope`. + `return` comes before `scope` when `this` is a $(DDSUBLINK spec/function, return-scope-parameters, `return scope`) parameter, + and after `scope` when `this` is a $(DDSUBLINK spec/function, scope-parameters, `scope`) and $(DDSUBLINK spec/function, return-ref-parameters, `return ref`) parameter. + ) + +$(GRAMMAR +$(GNAME FuncAttrPure): + $(B Na) + +$(GNAME FuncAttrNogc): + $(B Ni) + +$(GNAME FuncAttrNothrow): + $(B Nb) + +$(GNAME FuncAttrProperty): + $(B Nd) + +$(GNAME FuncAttrRef): + $(B Nc) + +$(GNAME FuncAttrReturn): + $(B Nj) + +$(GNAME FuncAttrScope): + $(B Nl) + +$(GNAME FuncAttrTrusted): + $(B Ne) + +$(GNAME FuncAttrSafe): + $(B Nf) + +$(GNAME FuncAttrLive): + $(B Nm) + +$(GNAME Parameters): + $(GLINK Parameter) + $(GLINK Parameter) $(GSELF Parameters) + +$(GNAME Parameter): + $(GLINK Parameter2) + $(B M) $(GLINK Parameter2) $(GREEN // scope) + $(B Nk) $(GLINK Parameter2) $(GREEN // return) + +$(GNAME Parameter2): + $(GLINK Type) + $(B I) $(GLINK Type) $(GREEN // in) + $(B J) $(GLINK Type) $(GREEN // out) + $(B K) $(GLINK Type) $(GREEN // ref) + $(B L) $(GLINK Type) $(GREEN // lazy) + +$(GNAME ParamClose): + $(B X) $(GREEN // variadic T t...$(RPAREN) style) + $(B Y) $(GREEN // variadic T t,...$(RPAREN) style) + $(B Z) $(GREEN // not variadic) + +$(GNAME TypeIdent): + $(B I) $(GLINK QualifiedName) + +$(GNAME TypeClass): + $(B C) $(GLINK QualifiedName) + +$(GNAME TypeStruct): + $(B S) $(GLINK QualifiedName) + +$(GNAME TypeEnum): + $(B E) $(GLINK QualifiedName) + +$(GNAME TypeTypedef): + $(B T) $(GLINK QualifiedName) + +$(GNAME TypeDelegate): + $(B D) $(GLINK TypeModifiers)$(OPT) $(GLINK TypeFunction) + +$(GNAME TypeVoid): + $(B v) + +$(GNAME TypeByte): + $(B g) + +$(GNAME TypeUbyte): + $(B h) + +$(GNAME TypeShort): + $(B s) + +$(GNAME TypeUshort): + $(B t) + +$(GNAME TypeInt): + $(B i) + +$(GNAME TypeUint): + $(B k) + +$(GNAME TypeLong): + $(B l) + +$(GNAME TypeUlong): + $(B m) + +$(GNAME TypeCent): + $(B zi) + +$(GNAME TypeUcent): + $(B zk) + +$(GNAME TypeFloat): + $(B f) + +$(GNAME TypeDouble): + $(B d) + +$(GNAME TypeReal): + $(B e) + +$(GNAME TypeIfloat): + $(B o) + +$(GNAME TypeIdouble): + $(B p) + +$(GNAME TypeIreal): + $(B j) + +$(GNAME TypeCfloat): + $(B q) + +$(GNAME TypeCdouble): + $(B r) + +$(GNAME TypeCreal): + $(B c) + +$(GNAME TypeBool): + $(B b) + +$(GNAME TypeChar): + $(B a) + +$(GNAME TypeWchar): + $(B u) + +$(GNAME TypeDchar): + $(B w) + +$(GNAME TypeNoreturn): + $(B Nn) + +$(GNAME TypeNull): + $(B n) + +$(GNAME TypeTuple): + $(B B) $(GLINK Parameters) $(B Z) +) + +$(H2 $(LNAME2 function_calling_conventions, Function Calling Conventions)) + + $(P The $(D extern (C)) and $(D extern (D)) calling convention matches the C + calling convention + used by the supported C compiler on the host system. + Except that the extern (D) calling convention for Windows x86 is described here. + ) + +$(H3 $(LNAME2 register_conventions, Register Conventions)) + + $(UL + + $(LI EAX, ECX, EDX are scratch registers and can be destroyed + by a function.) + + $(LI EBX, ESI, EDI, EBP must be preserved across function calls.) + + $(LI EFLAGS is assumed destroyed across function calls, except + for the direction flag which must be forward.) + + $(LI The FPU stack must be empty when calling a function.) + + $(LI The FPU control word must be preserved across function calls.) + + $(LI Floating point return values are returned on the FPU stack. + These must be cleaned off by the caller, even if they are not used.) + + ) + +$(H3 $(LNAME2 return_value, Return Value)) + + $(UL + + $(LI The types bool, byte, ubyte, short, ushort, int, uint, + pointer, Object, and interfaces + are returned in EAX.) + + $(LI long and ulong + are returned in EDX,EAX, where EDX gets the most significant + half.) + + $(LI float, double, real, ifloat, idouble, ireal are returned + in ST0.) + + $(LI cfloat, cdouble, creal are returned in ST1,ST0 where ST1 + is the real part and ST0 is the imaginary part.) + + $(LI Dynamic arrays are returned with the pointer in EDX + and the length in EAX.) + + $(LI Associative arrays are returned in EAX.) + + $(LI References are returned as pointers in EAX.) + + $(LI Delegates are returned with the pointer to the function + in EDX and the context pointer in EAX.) + + $(LI 1, 2 and 4 byte structs and static arrays are returned in EAX.) + + $(LI 8 byte structs and static arrays are returned in EDX,EAX, where + EDX gets the most significant half.) + + $(LI For other sized structs and static arrays, + the return value is stored through a hidden pointer passed as + an argument to the function.) + + $(LI Constructors return the this pointer in EAX.) + + ) + +$(H3 $(LNAME2 parameters, Parameters)) + + $(P The parameters to the non-variadic function:) + +--- +foo(a1, a2, ..., an); +--- + + are passed as follows: + + $(TABLE + $(TR $(TD a1)) + $(TR $(TD a2)) + $(TR $(TD ...)) + $(TR $(TD an)) + $(TR $(TD hidden)) + $(TR $(TD this)) + ) + + $(P where $(I hidden) is present if needed to return a struct + value, and $(I this) is present if needed as the this pointer + for a member function or the context pointer for a nested + function.) + + $(P The last parameter is passed in EAX rather than being pushed + on the stack if the following conditions are met:) + + $(UL + $(LI It fits in EAX.) + $(LI It is not a 3 byte struct.) + $(LI It is not a floating point type.) + ) + + $(P Parameters are always pushed as multiples of 4 bytes, + rounding upwards, + so the stack is always aligned on 4 byte boundaries. + They are pushed most significant first. + $(B out) and $(B ref) are passed as pointers. + Static arrays are passed as pointers to their first element. + On Windows, a real is pushed as a 10 byte quantity, + a creal is pushed as a 20 byte quantity. + On Linux, a real is pushed as a 12 byte quantity, + a creal is pushed as two 12 byte quantities. + The extra two bytes of pad occupy the $(SINGLEQUOTE most significant) position. + ) + + $(P The callee cleans the stack.) + + $(P The parameters to the variadic function:) + +--- +void foo(int p1, int p2, int[] p3...) +foo(a1, a2, ..., an); +--- + + are passed as follows: + + $(TABLE + $(TR $(TD p1)) + $(TR $(TD p2)) + $(TR $(TD a3)) + $(TR $(TD hidden)) + $(TR $(TD this)) + ) + + $(P The variadic part is converted to a dynamic array and the + rest is the same as for non-variadic functions.) + + $(P The parameters to the variadic function:) + +--- +void foo(int p1, int p2, ...) +foo(a1, a2, a3, ..., an); +--- + + are passed as follows: + + $(TABLE + $(TR $(TD an)) + $(TR $(TD ...)) + $(TR $(TD a3)) + $(TR $(TD a2)) + $(TR $(TD a1)) + $(TR $(TD $(D _)arguments)) + $(TR $(TD hidden)) + $(TR $(TD this)) + ) + + $(P The caller is expected to clean the stack. + $(D _argptr) is not + passed, it is computed by the callee.) + +$(H2 $(LNAME2 exception_handling, Exception Handling)) + + $(H3 $(LNAME2 windows_eh, Windows 32 bit)) + + $(P Conforms to the Microsoft Windows Structured Exception Handling + conventions. + ) + + $(H3 $(LNAME2 ninux_fbsd_osx_eh, Linux$(COMMA) FreeBSD and OS X)) + + $(P Conforms to the DWARF $(LPAREN)debugging with attributed record + formats$(RPAREN) Exception Handling conventions. + ) + + $(H3 $(LNAME2 win64_eh, Windows 64 bit)) + + $(P Uses static address range/handler tables. + It is not compatible with the MSVC x64 exception handling tables. + The stack is walked assuming it uses the EBP/RBP stack frame + convention. The EBP/RBP convention must be used for every + function that has an associated EH (Exception Handler) table. + ) + + $(P For each function that has exception handlers, + an EH table entry is generated. + ) + + $(TABLE2 EH Table Entry, + $(THEAD field, description) + $(TROW $(D void*), pointer to start of function) + $(TROW $(D DHandlerTable*), pointer to corresponding EH data) + $(TROW $(D uint), size in bytes of the function) + ) + + $(P The EH table entries are placed into the following special + segments, which are concatenated by the linker. + ) + + $(TABLE2 EH Table Segment, + $(THEAD Operating System, Segment Name) + $(TROW Win32, $(D FI)) + $(TROW Win64, $(D ._deh$B)) + $(TROW Linux, $(D .deh_eh)) + $(TROW FreeBSD, $(D .deh_eh)) + $(TROW OS X, $(ARGS $(D __deh_eh), $(D __DATA))) + ) + $(BR) + + $(P The rest of the EH data can be placed anywhere, + it is immutable.) + + $(TABLE2 DHandlerTable, + $(THEAD field, description) + $(TROW $(D void*), pointer to start of function) + $(TROW $(D uint), offset of ESP/RSP from EBP/RBP) + $(TROW $(D uint), offset from start of function to return code) + $(TROW $(D uint), number of entries in $(D DHandlerInfo[])) + $(TROW $(D DHandlerInfo[]), array of handler information) + ) + $(BR) + + $(TABLE2 DHandlerInfo, + $(THEAD field, description) + $(TROW $(D uint), offset from function address to start of guarded section) + $(TROW $(D uint), offset of end of guarded section) + $(TROW $(D int), previous table index) + $(TROW $(D uint), if != 0 offset to DCatchInfo data from start of table) + $(TROW $(D void*), $(ARGS if not null, pointer to finally code to execute)) + ) + $(BR) + + $(TABLE2 DCatchInfo, + $(THEAD field, description) + $(TROW $(D uint), number of entries in $(D DCatchBlock[])) + $(TROW $(D DCatchBlock[]), array of catch information) + ) + $(BR) + + $(TABLE2 DCatchBlock, + $(THEAD field, description) + $(TROW $(D ClassInfo), catch type) + $(TROW $(D uint), offset from EBP/RBP to catch variable) + $(TR $(D void*), catch handler code) + ) + +$(H2 $(LNAME2 garbage_collection, Garbage Collection)) + + $(P The interface to this is found in Druntime's $(DRUNTIMESRC core/gc/gcinterface.d).) + +$(H2 $(LNAME2 ModuleInfo, ModuleInfo Instance)) + + $(P An instance of $(LINK2 https://dlang.org/phobos/object.html#.ModuleInfo, `ModuleInfo`) + is generated by the compiler and inserted into the object file for every module. + `ModuleInfo` contains information about the module that is useful to the D runtime library: + ) + + $(UL + $(LI If the module has a static constructor, static destructor, shared static constructor, or shared static destructor.) + $(LI A reference to any unit tests defined by the module.) + $(LI An array of references to any imported modules that have one or more of: + $(OL + $(LI static constructors) + $(LI static destructors) + $(LI shared static constructors) + $(LI shared static destructors) + $(LI unit tests) + $(LI transitive imports of any module that contains one or more of 1..5) + $(LI order independent constructors (currently needed for implementing + $(DDSUBLINK dmd, switch-cov, $(TT -cov)))) + ) + This enables the runtime to run the unit tests, + the module constructors in a depth-first order, + and the module destructors in the reverse order. + ) + + $(LI An array of references to `ClassInfo` for each class defined in the module. + $(NOTE this feature may be removed.)) + ) + + $(P `ModuleInfo` is defined in Druntime's $(DRUNTIMESRC object.d), which must match the compiler's output in both the values of flags and layout of fields.) + + $(P Modules compiled with $(DDSUBLINK dmd, switch-betterC, $(TT -betterC)) + do not have a `ModuleInfo` instance generated, because such modules must work + without the D runtime library. + Similarly, $(DDLINK spec/importc, ImportC, ImportC) modules do not generate a `ModuleInfo`. + ) + +$(H3 $(LNAME2 module_init_and_fina, Module Initialization and Termination)) + + $(P All the static constructors for a module are aggregated into a + single function, and a pointer to that function is inserted + into the ctor member of the `ModuleInfo` instance for that + module. + ) + + $(P All the static destructors for a module are aggregated into a + single function, and a pointer to that function is inserted + into the dtor member of the `ModuleInfo` instance for that + module. + ) + +$(H3 $(LNAME2 unit_testing, Unit Testing)) + + $(P All the unit tests for a module are aggregated into a + single function, and a pointer to that function is inserted + into the unitTest member of the `ModuleInfo` instance for that + module. + ) + +$(H2 $(LNAME2 runtime_helper_functions, Runtime Helper Functions)) + + $(P These are found in Druntime's $(DRUNTIMESRC rt/).) + +$(H2 $(LNAME2 symbolic_debugging, Symbolic Debugging)) + + $(P D has types that are not represented in existing C or C++ debuggers. + These are dynamic arrays, associative arrays, and delegates. + Representing these types as structs causes problems because function + calling conventions for structs are often different than that for + these types, which causes C/C++ debuggers to misrepresent things. + For these debuggers, they are represented as a C type which + does match the calling conventions for the type. + ) + + $(TABLE2 Types for C Debuggers, + $(THEAD D type, C representation) + $(TROW dynamic array, $(D unsigned long long)) + $(TROW associative array, $(D void*)) + $(TROW delegate, $(D long long)) + $(TROW $(D dchar), $(D unsigned long)) + ) + + $(P For debuggers that can be modified to accept new types, the + following extensions help them fully support the types. + ) + +$(H3 $(LNAME2 codeview, Codeview Debugger Extensions)) + + $(P The D $(B dchar) type is represented by the special + primitive type 0x78.) + + $(P D makes use of the Codeview OEM generic type record + indicated by $(D LF_OEM) (0x0015). The format is:) + + $(TABLE2 Codeview OEM Extensions for D, + $(TROW field size, 2, 2, 2, 2, 2, 2) + $(THEAD D Type, Leaf Index, OEM Identifier, recOEM, num indices, + type index, type index) + $(TROW dynamic array, $(D LF_OEM), $(I OEM), 1, 2, @$(I index), @$(I element)) + $(TROW associative array, $(D LF_OEM), $(I OEM), 2, 2, @$(I key), @$(I element)) + $(TROW delegate, $(D LF_OEM), $(I OEM), 3, 2, @$(I this), @$(I function))) + + where: + + $(TABLE_2COLS , + $(TROW $(ARGS $(I OEM)), $(ARGS 0x42)) + $(TROW $(ARGS $(I index)), $(ARGS type index of array index)) + $(TROW $(ARGS $(I key)), $(ARGS type index of key)) + $(TROW $(ARGS $(I element)), $(ARGS type index of array element)) + $(TROW $(I this), $(ARGS type index of context pointer)) + $(TROW $(I function), $(ARGS type index of function))) + + $(P These extensions can be pretty-printed + by $(LINK2 http://www.digitalmars.com/ctg/obj2asm.html, obj2asm). The $(LINK2 http://ddbg.mainia.de/releases.html, Ddbg) debugger + supports them.) +$(SPEC_SUBNAV_PREV_NEXT memory-safe-d, Memory Safety, simd, Vector Extensions) +) + +Macros: + CHAPTER=39 + TITLE=Application Binary Interface diff --git a/spec/arrays.dd b/spec/arrays.dd new file mode 100644 index 0000000000..c7dee05508 --- /dev/null +++ b/spec/arrays.dd @@ -0,0 +1,1570 @@ +Ddoc + +$(SPEC_S Arrays, + +$(HEADERNAV_TOC) + +$(H2 $(LNAME2 array-kinds, Kinds)) + + $(P There are four kinds of arrays:) + + $(TABLE2 Kinds of Arrays, + $(THEAD Syntax, Description) + $(TROW $(ARGS $(I type)[$(I integer)]), $(ARGS $(RELATIVE_LINK2 static-arrays, Static arrays))) + $(TROW $(ARGS $(I type)[]), $(ARGS $(RELATIVE_LINK2 dynamic-arrays, Dynamic arrays))) + $(TROW $(ARGS $(I type)*), $(ARGS $(RELATIVE_LINK2 pointers, Pointer arrays))) + $(TROW $(ARGS $(I type)[$(I type)]), $(ARGS $(DDLINK spec/hash-map, Associative Arrays, Associative arrays))) + ) + +$(H3 $(LNAME2 static-arrays, Static Arrays)) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +int[3] s; +--------- +) + + $(P Static arrays have a length fixed at compile time. + ) + + $(P The total size of a static array cannot exceed 16Mb. + ) + + $(P A static array with a dimension of 0 is allowed, but no + space is allocated for it. + ) + + $(P Static arrays are value types. + They are passed to and returned by functions by value. + ) + + $(BEST_PRACTICE + $(OL + $(LI Use dynamic arrays for larger arrays.) + $(LI Because static arrays are passed to functions by value, + a larger array can consume a lot of stack space. Use dynamic arrays + instead.) + )) + +$(H3 $(LNAME2 dynamic-arrays, Dynamic Arrays)) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +int[] a; +--------- +) + + $(P Dynamic arrays consist of a length and a pointer to the array data. + Multiple dynamic arrays can share all or parts of the array data. + ) + + $(BEST_PRACTICE + $(OL + $(LI Use dynamic arrays instead of pointer arrays as much as practical. + Indexing of dynamic arrays are bounds checked, avoiding buffer underflow and + overflow problems.) + )) + +$(H3 $(LNAME2 pointers, Pointer Arrays)) + +--------- +int* p; +--------- + + $(P A $(DDSUBLINK spec/type, pointers, pointer) + can manipulate a block of multiple contiguous values in memory. + Accessing more than one value cannot be + $(DDLINK spec/memory-safe-d, Memory-Safe-D-Spec, `@safe`) as it + requires $(RELATIVE_LINK2 pointer-arithmetic, pointer arithmetic). + This is supported for interfacing with C and for + specialized systems work. + A pointer has no length associated with it, so there is no way for the + compiler or runtime to do bounds checking, etc., on it. + ) + + $(BEST_PRACTICE Most conventional uses for pointers can be replaced with + dynamic arrays, $(D ref) and $(D out) $(DDSUBLINK spec/function, parameters, parameters), + and reference types. + ) + + +$(H2 $(LNAME2 declarations, Array Declarations)) + + $(P Declarations appear before the identifier being + declared and read right to left, so: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +int[] a; // dynamic array of ints +int[4][3] b; // array of 3 arrays of 4 ints each +int[][5] c; // array of 5 dynamic arrays of ints. +int*[]*[3] d; // array of 3 pointers to dynamic arrays of pointers to ints +int[]* e; // pointer to dynamic array of ints +--------- +) + +$(H2 $(LNAME2 literals, Array Initializers & Literals)) + + $(P An $(GLINK ArrayInitializer) initializes a dynamic or static array:) +--- +auto a1 = [1,2,3]; // type is int[], with elements 1, 2, and 3 +auto a2 = [1u,2,3]; // type is uint[], with elements 1u, 2u, and 3u +int[2] a3 = [1,2]; // type is int[2], with elements 1, and 2 +--- + + $(P An $(DDSUBLINK spec/expression, array_literals, array literal) is an expression:) +--- +void f(int[] a); + +f([1, 2]); // pass 2 elements +f([]); // pass an empty array +--- + +$(H2 $(LNAME2 comparison, Array Comparison)) + + $(P For static and dynamic arrays:) + + * The `.length` property will give the number of elements in the array. + * The $(RELATIVE_LINK2 ptr-property, `.ptr` property) will give a pointer to + the first element in the array. + * `a == b` compares both the array lengths and array elements. + * `a is b` compares each `.ptr` and each `.length`. Note that this is + deprecated for static arrays because those are value types, so checking + identity should not compare the `.ptr` fields.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int[3] s = [1, 2, 3]; +int[] a = [1, 2, 3]; + +assert(s.length == 3); +assert(a.length == 3); +assert(s == a); +assert(s.ptr != a.ptr); // here `a` is not a slice of `s` +assert(s !is a); +--- +) + $(P See also: $(DDSUBLINK spec/expression, array_comparisons, *RelExpression*.) + +$(LEGACY_LNAME2 usage) +$(H2 $(LNAME2 assignment, Array Assignment)) + + $(P There are two broad kinds of operations to do on dynamic arrays and + pointer arrays - those affecting the handle to the array, + and those affecting the contents of the array. Assignment only affects + the handle for these types. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int* p; +int[3] s; +int[] a; + +p = s.ptr; // p points to the first element of the array s. +assert(p !is null); +p = a.ptr; +assert(p is null); + +// error, since the length of the array pointed to by p is unknown +//s = p; + +//a = p; // error, length unknown +a = s; // a points to the elements of s +assert(a.ptr == s.ptr); + +int[] b = [1, 2, 3]; +a = b; // a points to the same array as b does +assert(a.ptr == b.ptr); +assert(a is b); +--------- +) + $(NOTE The two error lines above can be made to copy elements + using pointer $(RELATIVE_LINK2 slicing, slicing), so that the number of elements + to copy is then known.) + + +$(H3 $(LNAME2 static-array-assign, Static Array Assignment)) + + $(P A static array can be assigned from a dynamic array - the data is copied. + If the lengths do not match at runtime, a `RangeError` is thrown:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +int[3] s; +int[] a; + +//s = [1, 2]; // error +s = [1, 2, 3]; // OK +//s = [1, 2, 3, 4]; // error + +a = [4, 5, 6]; +s = a; // OK +assert(s == a); +assert(s.ptr != a.ptr); + +a = [1, 2]; +//s = a; // RangeError, length mismatch + +a = s; +assert(a.ptr == s.ptr); +//s = a; // RangeError, overlap +--- +) + $(P The dynamic array data must not $(RELATIVE_LINK2 overlapping-copying, overlap) + with the static array memory. + See also $(RELATIVE_LINK2 array-copying, Copying).) + + +$(H2 $(LNAME2 indexing, Indexing)) + + $(P Indexing allows access to an element of an array:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +auto a = [1,2,3]; +assert(a[0] == 1); +assert(a[2] == 3); +a[2] = 4; +assert(a[2] == 4); +assert(a == [1,2,4]); +//writeln(a[3]); // runtime error (unless bounds checks turned off) + +int[2] b = [1,2]; +assert(b[1] == 2); +//writeln(b[2]); // compile-time error, index out of bounds +--------- +) + + $(P Dynamic and static array indexing is $(RELATIVE_LINK2 bounds, bounds checked) + by default.) + + $(P See also $(GLINK2 expression, IndexOperation).) + +$(H3 $(LNAME2 pointer-arithmetic, Pointer Arithmetic)) + + $(P A pointer can also be indexed, but no bounds checks are done. + Unlike arrays, a pointer value can also be used in certain + arithmetic expressions to produce another pointer:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +int[] a = [1,2,3]; +int* p = a.ptr; + +p[2] = 4; +assert(a[2] == 4); +writeln(p[3]); // undefined behaviour + +assert(p == &a[0]); +p++; // point to a[1] +assert(*p == 2); +--- +) + + $(P See $(DDSUBLINK spec/expression, pointer_arithmetic, *AddExpression*) for details.) + + +$(H2 $(LNAME2 slicing, Slicing)) + + $(P $(I Slicing) an array means to specify a subarray of it. + This is done by supplying two index expressions. + The elements from the start index up until the end index are selected. + Any item at the end index is not included. + ) + $(P + An array slice does not copy the data, it is only another + reference to it. Slicing produces a dynamic array. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int[3] a = [4, 5, 6]; // static array of 3 ints +int[] b; + +b = a[1..3]; // a[1..3] is a 2 element dynamic array consisting of + // a[1] and a[2] +assert(b == [5, 6]); +assert(b.ptr == a.ptr + 1); + +a[2] = 3; +assert(b == [5, 3]); + +b = b[1..2]; +assert(b == [3]); +--------- +) + + $(P Each index in the slice expression is $(RELATIVE_LINK2 bounds, bounds checked) + by default.) + + $(P $(I Expression)`[]` is shorthand for a slice of the entire array. + ) + + $(P Slicing + is not only handy for referring to parts of other arrays, + but for converting pointers into bounds-checked arrays: + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int[10] a = [ 1,2,3,4,5,6,7,8,9,10 ]; + +int* p = &a[2]; +writeln(p[7]); // 10 +writeln(p[8]); // undefined behaviour + +int[] b = p[0..8]; // convert pointer elements to dynamic array +assert(b is a[2..10]); +writeln(b); +writeln(b[7]); // 10 +//writeln(b[8]); // runtime error (unless bounds checks turned off) +--------- +) + + $(P See also $(GLINK2 expression, SliceOperation).) + + +$(H3 $(LNAME2 array-length, Array Length)) + + $(P When indexing or slicing a static or dynamic array, + the symbol $(D $) represents the length of the array. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int[4] foo; +int[] bar; + +// These assignments are equivalent: +bar = foo; +bar = foo[]; +bar = foo[0 .. 4]; +bar = foo[0 .. $]; +bar = foo[0 .. foo.length]; +assert(bar.length == 4); + +int* p = foo.ptr; // a pointer has no length property +bar = p[0 .. 4]; // OK +//bar = p[0 .. $]; // error, '$' is not defined, since p is not an array + +int i; +//i = foo[0]+$; // error, '$' is not defined, out of scope of [ ] +i = bar[$-1]; // retrieves last element of the array +--------- +) + + +$(H2 $(LNAME2 array-copying, Array Copying)) + + $(P When a slice expression is the left-hand side of an + assignment expression, it means that the contents of the slice are the + target of the assignment rather than an array reference. + The right-hand side must implicitly convert to an array type.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int[3] s, t; +int[] a; + +s = t; // the 3 elements of t are copied into s +s[] = t; // the 3 elements of t are copied into s +s[] = t[]; // the 3 elements of t are copied into s +s[1..2] = t[0..1]; // same as s[1] = t[0] +s[0..2] = t[1..3]; // same as s[0] = t[1], s[1] = t[2] +//s[0..4] = t[0..4]; // error, only 3 elements in s and t +//s[0..2] = t; // error, operands have different lengths + +a = [1, 2]; +s[0..2] = a; +assert(s == [1, 2, 0]); + +//a[] = s; // RangeError, lengths don't match +a[0..2] = s[1..3]; +assert(a == [2, 0]); +--------- +) + + $(P If the number of elements does not match at runtime, a `RangeError` is thrown.) + + $(RATIONALE Indexing past the end of a slice is a programming error.) + + +$(H3 $(LNAME2 overlapping-copying, Overlapping Copying)) + + $(P Overlapping copies are an error:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +void main() +{ + int[3] s; + + s[0..2] = s[1..3]; // error, overlapping copy + s[1..3] = s[0..2]; // error, overlapping copy +} +--------- +) + + $(P Disallowing overlapping makes it possible for more aggressive + parallel code optimizations than possible with the serial + semantics of C. + ) + + $(P If overlapping is required, use + $(REF copy, std,algorithm,mutation): + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +import std.algorithm; +int[] s = [1, 2, 3, 4]; + +copy(s[1..3], s[0..2]); +assert(s == [2, 3, 3, 4]); +--------- +) + + +$(H2 $(LNAME2 array-setting, Array Filling)) + + $(P If a slice operator appears as the left-hand side of an assignment + expression, and the type of the right-hand side is the same as the + element type of the left-hand side, then each element of the slice + expression will be assigned to the value on the right-hand side. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int[3] s; +int[] a; +int* p; + +s[] = 3; +assert(s == [3, 3, 3]); + +a = s; +a[] = 1; +assert(s == [1, 1, 1]); + +p = s.ptr; +p[0..2] = 2; +assert(s == [2, 2, 1]); +--------- +) + +$(H2 $(LNAME2 array-concatenation, Array Concatenation)) + + $(P The binary operator `~` is the $(I cat) operator. It is used + to concatenate arrays: + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +int[] a = [1, 2]; +assert(a ~ 3 == [1, 2, 3]); // concatenate array with a single value + +int[] b = a ~ [3, 4]; +assert(b == [1, 2, 3, 4]); // concatenate two arrays +--- +) + + $(P Many languages overload the `+` operator for concatenation. + This confusingly leads to a dilemma - does: + ) + +--------- +"10" + 3 + 4 +--------- + + $(P produce the number `17`, the string `"1034"` or the string `"107"` as the + result? It isn't obvious, and the language designers wind up carefully + writing rules to disambiguate it - rules that get incorrectly + implemented, overlooked, forgotten, and ignored. It's much better to + have `+` mean addition, and a separate operator to be array + concatenation. + ) + + $(P Concatenation always creates a copy of its operands, even + if one of the operands is a 0 length array, so: + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +auto b = [7]; +auto a = b; // a refers to b +assert(a is b); + +a = b ~ []; // a refers to a copy of b +assert(a !is b); +assert(a == b); +--------- +) + + $(P See also: $(DDSUBLINK spec/expression, identity_expressions, `is` operator).) + +$(H2 $(LNAME2 array-appending, Array Appending)) + + $(P Similarly, the `~=` operator means append, as in: + ) + +--------- +a ~= b; // a becomes the concatenation of a and b +--------- + + $(P Appending does not always create a copy, see $(RELATIVE_LINK2 resize, + setting dynamic array length) for details. + ) + +$(H2 $(LNAME2 array-operations, Vector Operations)) + + $(P Many array operations + can be expressed at a high level rather than as a loop. + For example, the loop: + ) + +--- +T[] a, b; +... +for (size_t i = 0; i < a.length; i++) + a[i] = b[i] + 4; +--- + + $(P assigns to the elements of $(CODE a) the elements of $(CODE b) + with $(CODE 4) added to each. This can also be expressed in + vector notation as: + ) + +--- +T[] a, b; +... +a[] = b[] + 4; +--- + + $(P A vector operation is indicated by the slice operator appearing + as the left-hand side of an assignment or an op-assignment expression. + The right-hand side can be certain combinations of:) + + * An array $(GLINK2 expression, SliceOperation) of the same length + and type as the left-hand side + * A scalar expression of the same element type as the left-hand side + + $(P The following operations are supported:) + + * Unary: `-`, `~` + * Add: `+`, `-` + * Mul: `*`, `/`, `%`, + * Bitwise: `^`, `&`, `|` + * Pow: `^^` + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +int[3] a = 0; +int[] b = [1, 2, 3]; + +a[] += 10 - (b[] ^^ 2); +assert(a == [9, 6, 1]); +--- +) + + $(NOTE In particular, an expression using + $(GLINK2 expression, ConditionalExpression), + $(DDSUBLINK spec/expression, logical_expressions, logical expressions), + $(GLINK2 expression, CmpExpression), + concatenation `~` or a function call is *not* a vector op.) + + $(P The slice on the left and any slices on the right must not overlap. + All operands are evaluated exactly once, even if the array slice + has zero elements in it. + ) + + $(P If the element type defines matching overloaded operators, + those methods must be `pure nothrow @nogc`.) + + $(P The order in which the array elements are computed + is implementation defined, and may even occur in parallel. + An application must not depend on this order. + ) + + $(P $(B Implementation Note:) Many vector operations are expected + to take advantage of any vector math instructions available on + the target computer. + ) + +$(H2 $(LNAME2 rectangular-arrays, Rectangular Arrays)) + + $(P Experienced FORTRAN numerics programmers know that multidimensional + "rectangular" arrays for things like matrix operations are much faster than trying to + access them via pointers to pointers resulting from "array of pointers to array" semantics. + For example, the D syntax: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +double[][] matrix; +--------- +) + + $(P declares matrix as an array of pointers to arrays. (Dynamic arrays are implemented as + pointers to the array data.) Since the arrays can have varying sizes (being dynamically + sized), this is sometimes called "jagged" arrays. Even worse for optimizing the code, the + array rows can sometimes point to each other! Fortunately, D static arrays, while using + the same syntax, are implemented as a fixed rectangular layout in a contiguous block of + memory: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +import std.stdio : writeln; + +double[6][3] matrix = 0; // Sets all elements to 0. + +void main() +{ + writeln(matrix); // [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]] +} +--------- +) + + $(P Note that dimensions and indices appear in opposite orders. Dimensions in the + $(RELATIVE_LINK2 declarations, declaration) are read right to left whereas indices are read + left to right: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +import std.stdio : writeln; + +void main() +{ + double[6][3] matrix = 0; + matrix[2][5] = 3.14; // Assignment to bottom right element. + writeln(matrix); // [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 3.14]] + + static assert(!__traits(compiles, matrix[5][2])); // Array index out of bounds. +} +--------- +) + +$(P More information can be found at $(LINK2 https://wiki.dlang.org/Dense_multidimensional_arrays, Dlang Wiki - Dense Multidimensional Arrays).) + +$(H2 $(LNAME2 array-properties, Array Properties)) + + $(P Static array properties are:) + + $(TABLE_2COLS Static Array Properties, + $(THEAD Property, Description) + $(TROW $(D .init), +Returns an array literal with each element of the literal being the $(D .init) property of the array element type.) + $(TROW $(D .sizeof), Returns the array length multiplied by + the number of bytes per array element.) + $(TROW $(D .length), $(ARGS Returns the number of elements in the array. + This is a fixed quantity for static arrays, known at compile-time. + It is of type $(D size_t)).) + $(TROW $(RELATIVE_LINK2 ptr-property, `.ptr`), Returns a pointer to the first + element of the array.) + $(TROW $(D .dup), Create a dynamic array of the same size and copy the contents of the array into it. The copy will have any immutability or const stripped. If this conversion is invalid the call will not compile.) + $(TROW $(D .idup), Create a dynamic array of the same size and copy the contents of the array into it. The copy is typed as being immutable. If this conversion is invalid the call will not compile.) + $(TROW $(D .tupleof), $(ARGS Returns an $(DDSUBLINK spec/template, lvalue-sequences, lvalue sequence) of each element in the array: + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + void foo(int, int, int) { /* ... */ } + + int[3] ia = [1, 2, 3]; + foo(ia.tupleof); // same as `foo(1, 2, 3);` + + float[3] fa; + //fa = ia; // error + fa.tupleof = ia.tupleof; + assert(fa == [1F, 2F, 3F]); + --- + ) + )) + ) + + $(P Dynamic array properties are:) + + $(TABLE_2COLS Dynamic Array Properties, + $(THEAD Property, Description) + $(TROW $(D .init), Returns $(D []).) + $(TROW $(D .sizeof), $(ARGS Returns the size of the dynamic array reference, + which is 8 in 32-bit builds and 16 on 64-bit builds.)) + $(TROW $(RELATIVE_LINK2 resize, `.length`), Get/set number of elements in the + array. It is of type $(D size_t).) + $(TROW $(RELATIVE_LINK2 capacity-reserve, `.capacity`), Returns the length an array can grow to without reallocating.) + $(TROW $(RELATIVE_LINK2 ptr-property, `.ptr`), Returns a pointer to the first + element of the array.) + $(TROW $(D .dup), Create a dynamic array of the same size and copy the contents of the array into it. The copy will have any immutability or const stripped. If this conversion is invalid the call will not compile.) + $(TROW $(D .idup), Create a dynamic array of the same size and copy the contents of the array into it. The copy is typed as being immutable. If this conversion is invalid the call will not compile.) + ) + + $(P Examples:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int* p; +int[3] s; +int[] a; + +size_t len; +//len = p.length; // error, pointer has no length property +enum sl = s.length; // compile time constant +static assert(sl == 3); + +len = a.length; // runtime value +assert(len == 0); + +//a = p.dup; // error, length not known +a = s.dup; // allocates an array of 3 elements, copies + // elements of `s` into it +assert(a == s[]); +assert(a.ptr != s.ptr); + +int[] b = a.dup; // allocates a new array of `a.length` elements, copies + // elements of `a` into it +assert(b !is a); // b is an independent copy of a +--------- +) + +$(H3 $(LNAME2 ptr-property, `.ptr` Property)) + + $(P The `.ptr` property will give a pointer to the first element in a + static or dynamic array. It may be a + $(LINK2 https://en.wikipedia.org/wiki/Dangling_pointer, dangling pointer) + if the array length is zero. For this reason, `.ptr` is not accessible in + `@safe` code.) + + $(P A dynamic array's `.ptr` is $(RELATIVE_LINK2 default-initialization, + default-initialized) to `null`.) + + $(P An array with zero length may have a non-null `.ptr`. That can occur:) + + * From $(RELATIVE_LINK2 slicing, slicing) a dynamic array `a` with + zero-width: `a[$..$]`. + * For a zero-length static array. + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +int[] a; +assert(a.ptr is null); + +int[0] z; +assert(z.ptr !is null); +--- +) + +$(H3 $(LNAME2 resize, Setting Dynamic Array Length)) + + $(P The $(D .length) property of a dynamic array can be set + as the left-hand side of an `=` operator: + ) + +--------- +array.length = 7; +--------- + + $(P This causes the array to be reallocated in place, and the existing + contents copied over to the new array. If the new array length is + shorter, the array is not reallocated, and no data is copied. It is + equivalent to slicing the array:) + +--------- +array = array[0..7]; +--------- + + $(P If the new array length is longer, the array is reallocated if necessary, + preserving the existing elements. The new elements are filled out with the + default initializer. + ) + +$(H4 $(LNAME2 growing, Growing an Array)) + + $(P To maximize efficiency, the runtime always tries to resize the array + in place to avoid extra copying. It will do a copy if the new size + is larger and either:) + + * The array was not $(DDSUBLINK spec/garbage, op_involving_gc, allocated by the GC). + * There is no spare $(RELATIVE_LINK2 capacity-reserve, capacity) for the array. + * Resizing in place would overwrite valid data still accessible in another slice. + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +char[] a = new char[20]; +char[] b = a[0..10]; +char[] c = a[10..20]; +char[] d = a; + +b.length = 15; // always reallocates because extending in place would + // overwrite other data in a. +b[11] = 'x'; // a[11] and c[1] are not affected +assert(a[11] == char.init); + +d.length = 1; +assert(d.ptr == a.ptr); // unchanged + +d.length = 20; // also reallocates, because doing this will overwrite a and c +assert(d.ptr != a.ptr); + +c.length = 12; // may reallocate in place if space allows, because nothing + // was allocated after c. +c[5] = 'y'; // may affect contents of a, but not b or d because those + // were reallocated. + +a.length = 25; // This always reallocates because if c extended in place, + // then extending a would overwrite c. If c didn't + // reallocate in place, it means there was not enough space, + // which will still be true for a. +a[15] = 'z'; // does not affect c, because either a or c has reallocated. +--------- +) + + + $(P To guarantee copying behavior, use the `.dup` property to ensure + a unique array that can be resized. + ) + + $(NOTE These issues also apply to + $(RELATIVE_LINK2 array-appending, appending arrays) with the `~=` operator. + Concatenation using the `~` operator is not affected since it always + reallocates. + ) + + $(P Resizing a dynamic array is a relatively expensive operation. + So, while the following method of filling an array: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +void fun() +{ + int[] array; + while (1) + { + import core.stdc.stdio : getchar; + auto c = getchar; + if (!c) + break; + ++array.length; + array[array.length - 1] = c; + } +} +--------- +) + + will work, it will be inefficient. A more practical + approach would be to minimize the number of resizes: + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +void fun() +{ + int[] array; + array.length = 100; // guess + int i; + for (i = 0; ; i++) + { + import core.stdc.stdio : getchar; + auto c = getchar; + if (!c) + break; + if (i == array.length) + array.length *= 2; + array[i] = c; + } + array.length = i; +} +--------- +) + + $(P Base selection of the initial size on expected common + use cases, which can be determined by instrumenting the code, + or simply using good judgement. + For example, when gathering user + input from the console - it's unlikely to be longer than 80. + ) + +$(H3 $(LNAME2 capacity-reserve, `capacity` and `reserve`)) + + $(P The $(D capacity) property gives the maximum length a dynamic array + can grow to without reallocating. + The spare capacity for an array *a* is `a.capacity - a.length`. + The capacity for a slice is zero:) + + * If it does not point to GC-allocated dynamic array memory. + * By default, when an element has been stored after the slice. + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + int[] a; + assert(a.capacity == 0); + a.length = 3; // may allocate spare capacity too + assert(a.capacity >= 3); + + auto b = a[1..3]; + assert(b.capacity >= 2); // either a or b can append into any spare capacity + b = a[0..2]; + assert(b.capacity == 0); + --- + ) + + $(RATIONALE This behaviour helps prevent accidental overwriting of + elements in another slice. It is also necessary to protect immutable + elements from being overwritten.) + + $(P The $(REF1 reserve, object) function requests a minimum capacity for an array. + It returns the new capacity, which may be more than requested. + Any spare capacity can be used by the + $(RELATIVE_LINK2 array-appending, append operator) or `.length` assignment.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int[] array; +const size_t cap = array.reserve(10); // request +assert(cap >= 10); // allocated may be more than request +assert(array.ptr != null); +assert(array.length == 0); + +int[] copy = array; +assert(copy.capacity == cap); // array and copy have same capacity +array ~= [1, 2, 3, 4, 5]; // grow in place +assert(cap == array.capacity); // array memory was not reallocated +assert(copy.ptr == array.ptr); +assert(copy.capacity == 0); +copy ~= 0; // allocates a new array +assert(copy.ptr != array.ptr); +assert(array[0] == 1); +--------- +) + $(P Above, `copy`'s length remains zero but it points to the same + memory allocated by the `reserve` call. Because `array` is then appended + to, `copy.ptr + 0` no longer points to unused memory - instead that + is the address of `array[0]`. So `copy.capacity` will be zero to + prevent any appending to `copy` from overwriting elements in `array`.) + + $(NOTE The runtime uses the last element of a slice to track the + start of the spare capacity for the memory allocation.) + + $(P When an array with spare capacity has its length reduced, or is + assigned a slice of itself that ends before the previous last element, + the capacity will be zero.) + + $(P The `@system` function $(REF1 assumeSafeAppend, object) allows the + capacity to be regained, but care must be taken not to overwrite + immutable elements that may exist in another slice.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + int[] a = [1, 2, 3]; + a.length--; + assert(a.capacity == 0); + a.assumeSafeAppend(); + assert(a.capacity >= 3); + --- + ) + + $(NOTE Accessing `.capacity` may require the runtime to + acquire a global lock and perform a cache lookup.) + + $(BEST_PRACTICE Avoid intensive use of `.capacity` in performance-sensitive code. + Instead, track the capacity locally when building an array via a unique reference. + E.g. $(REF Appender, std,array).) + + +$(H3 $(LNAME2 func-as-property, Functions as Array Properties)) + + $(P See $(DDSUBLINK spec/function, pseudo-member, Uniform Function Call Syntax (UFCS)).) + +$(H2 $(LNAME2 bounds, Array Bounds Checking)) + + $(P It is an error to index an array with an index that is less than + 0 or greater than or equal to the array length. If an index is + out of bounds, an `ArrayIndexError` is thrown + if detected at runtime, and an error is raised if detected at compile + time. A program may not rely on array bounds checking happening, for + example, the following program is incorrect: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +void main() +{ + import core.exception; + try + { + auto array = [1, 2]; + for (auto i = 0; ; i++) + { + array[i] = 5; + } + } + catch (ArrayIndexError) + { + // terminate loop + } +} +--------- +) + + The loop is correctly written: + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +void main() +{ + auto array = [1, 2]; + for (auto i = 0; i < array.length; i++) + { + array[i] = 5; + } +} +--------- +) + + $(P $(B Implementation Note:) Compilers should attempt to detect + array bounds errors at compile time, for example: + ) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--------- +int[3] foo; +int x = foo[3]; // error, out of bounds +--------- +) + + $(P Insertion of array bounds checking code at runtime should be + turned on and off + with a compile time switch. + ) + + $(UNDEFINED_BEHAVIOR An out of bounds memory access will cause undefined behavior, + therefore array bounds check is normally enabled in `@safe` functions. + The runtime behavior is part of the language semantics. + ) + + $(P See also $(DDSUBLINK spec/function, safe-functions, Safe Functions).) + +$(H3 $(LNAME2 disable-bounds-check, Disabling Array Bounds Checking)) + + $(P Insertion of array bounds checking code at runtime may be + turned off with a compiler switch $(LINK2 $(ROOT_DIR)dmd.html#switch-boundscheck, `-boundscheck`). + ) + + $(P If the bounds check in `@system` or `@trusted` code is disabled, + the code correctness must still be guaranteed by the code author. + ) + + $(P On the other hand, disabling the bounds check in `@safe` code will + break the guaranteed memory safety by compiler. It's not recommended + unless motivated by speed measurements. + ) + +$(H2 $(LNAME2 array-initialization, Array Initialization)) + +$(H3 $(LNAME2 default-initialization, Default Initialization)) + + $(UL + $(LI Pointers are initialized to $(D null).) + $(LI Static array contents are initialized to the + $(DDSUBLINK spec/property, init, default initializer) for the array element type.) + $(LI Dynamic arrays are initialized to having 0 elements and a null `.ptr`.) + $(LI Associative arrays are initialized to having 0 elements.) + ) + +$(H3 $(LNAME2 length-initialization, Length Initialization)) + + $(P The $(D new) expression can be used to allocate a dynamic array + with a specified length by specifying its type and then using the + `(size)` syntax: + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int[] i = new int[](5); +i = new int[5]; // same allocation, alternate syntax +assert(i.length == 5); + +int[][] j = new int[][](10, 5); +assert(j.length == 10); +assert(j[0].length == 5); +--------- +) + $(P See $(GLINK2 expression, NewExpression) for details.) + +$(H3 $(LNAME2 void-initialization, Void Initialization)) + + $(P Void initialization happens when the $(GLINK2 declaration, Initializer) for + an array declaration is $(D void). For a static array, + it means no initialization + is done - i.e. the contents of the array will be undefined. + This is most useful as an efficiency optimization. + ) + --- + int[256] arr = void; // elements of `arr` have undefined bit-patterns + --- + $(BEST_PRACTICE + Void initializations are an advanced technique and should only be used + when profiling indicates that it matters. + ) + $(P To void initialise the *elements* of a dynamic array use + $(REF uninitializedArray, std,array). + ) + +$(H3 $(LNAME2 array-initializers, Array Initializers)) + +$(GRAMMAR +$(GNAME ArrayInitializer): + $(D [) $(I ArrayElementInitializers)$(OPT) $(D ]) + +$(GNAME ArrayElementInitializers): + $(I ArrayElementInitializer) + $(I ArrayElementInitializer) $(D ,) + $(I ArrayElementInitializer) $(D ,) $(GSELF ArrayElementInitializers) + +$(GNAME ArrayElementInitializer): + $(GLINK2 declaration, NonVoidInitializer) + $(GLINK2 expression, AssignExpression) $(D :) $(GLINK2 declaration, NonVoidInitializer) +) + + $(P An *ArrayInitializer* is a list of array + element values enclosed in `[ ]`. The values can be optionally + preceded by an index and a `:`. + If an index is not supplied, it is set to the previous index + plus 1, or 0 if it is the first value. + Any missing elements will be initialized to the default value + of the element type. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int[3] a = [ 1:2, 3 ]; // a[0] = 0, a[1] = 2, a[2] = 3 + +assert(a == [0, 2, 3]); +--------- +) + + $(PANEL This is most handy when the array indices are given by $(DDLINK spec/enum, Enums, enums): + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +enum Color { red, blue, green } + +int[Color.max + 1] value = + [ Color.blue :6, + Color.green:2, + Color.red :5 ]; + +assert(value == [5, 6, 2]); +--------- +) + ) + + $(P Any indices must be known at compile-time. + Note that if the array type is not specified and every element has an index, + it will be inferred as an + $(DDSUBLINK spec/expression, associative_array_literals, associative array + literal).) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + int n = 4; + auto aa = [0:1, 3:n]; // associative array `int[int]` + + int[] a = [1, 3:n, 5]; + assert(a == [1, 0, 0, n, 5]); + + //int[] e = [n:2]; // error, n not known at compile-time + --- + ) + +$(H3 $(LNAME2 static-init-static, Static Initialization of Statically Allocated Arrays)) + + $(P All elements of a static array can be initialized to a specific value with:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int[4] a = 42; // set all elements of a to 42 + +assert(a == [42, 42, 42, 42]); +--------- +) + + $(P These arrays are statically allocated when they appear in global scope. + Otherwise, they need to be marked with $(D const) or $(D static) + storage classes to make them statically allocated arrays.) + +$(H4 $(LNAME2 static-string, String Literal Initializers)) + + $(P A static array of character type is $(RELATIVE_LINK2 default-initialization, + default-initialized) the same as other + static arrays. However, when initialized from a string literal:) + + * The literal can be of a shorter length than the array. + * Any remaining elements are initialized to `\0`. + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +char[10] s1; +assert(s1[9] == '\xFF'); // char.init + +char[10] s2 = "hi"; +assert(s2[9] == '\0'); +--- +) + $(RATIONALE A mutable character array's `.ptr` property can be used to + obtain a C string (if it has an element which is zero). When that array + is initialized with a shorter string literal, it's likely the subsequent + code will need zero-termination.) + + +$(H2 $(LNAME2 special-array, Special Array Types)) + +$(H3 $(LNAME2 strings, Strings)) + + $(P A string is an array of $(DDSUBLINK spec/const3, immutable_type, immutable) + (read-only) characters. String literals essentially are + an easy way to write character array literals. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +char[] arr; +//arr = "abc"; // error, cannot implicitly convert expression `"abc"` of type `string` to `char[]` +arr = "abc".dup; // ok, allocates mutable copy + +string str1 = "abc"; // ok, same types +//str1 = arr; // error, cannot implicitly convert expression `arr` of type `char[]` to `string` +str1 = arr.idup; // ok, allocates an immutable copy of elements +assert(str1 == "abc"); + +string str2 = str1; // ok, mutable slice of same immutable array contents +--------- +) + + $(P The name $(CODE string) is aliased to $(CODE immutable(char)[]). + The type $(D immutable(char)[]) represents an array of $(D immutable char)s. However, the reference to the string is + mutable. + ) +--- +immutable(char)[] s = "foo"; +s[0] = 'a'; // error, s[0] is immutable +s = "bar"; // ok, s itself is not immutable +--- + + $(P If the reference to the string needs to be immutable as well, it can be declared $(D immutable char[]) + or $(D immutable string): + ) +--- +immutable char[] s = "foo"; +s[0] = 'a'; // error, s refers to immutable data +s = "bar"; // error, s is immutable +--- + + $(P Strings can be copied, compared, concatenated, and appended:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +string s1; +immutable s2 = "ello"; +s1 = s2; +s1 = "h" ~ s1; +if (s1 > "farro") + s1 ~= " there"; + +assert(s1 == "hello there"); +--------- +) + + $(P with array semantics. Any generated temporaries get cleaned up + by the garbage collector (or by using $(CODE alloca())). + Not only that, this works with any + array not just a special String array. + ) + +$(H4 $(LNAME2 string-literal-types, String Literal Types)) + + $(P The type of a $(DDSUBLINK spec/expression, string_literals, string literal) + is determined by the semantic phase of compilation. The type is + determined by implicit conversion rules. + If there are two equally applicable implicit conversions, + the result is an error. To + disambiguate these cases, a cast or a postfix of $(D c), + $(D w) or $(D d) can be used: + ) + +--------- +cast(immutable(wchar)[]) "abc" // this is an array of wchar characters +"abc"w // so is this +--------- + + $(P String literals that do not have a postfix character and that + have not been cast can be implicitly converted between + `string`, `wstring`, and `dstring` (see below) as necessary. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +void fun() +{ + char c; + wchar w; + dchar d; + + c = 'b'; // c is assigned the character 'b' + w = 'b'; // w is assigned the wchar character 'b' + //w = 'bc'; // error - only one wchar character at a time + w = "b"[0]; // w is assigned the wchar character 'b' + w = "\r"[0]; // w is assigned the carriage return wchar character + d = 'd'; // d is assigned the character 'd' +} +--------- +) + +$(H4 $(LEGACY_LNAME2 strings_unicode, strings-unicode, Strings and Unicode)) + + $(P String data is encoded as follows:) + + $(TABLE2, + $(THEAD Alias, Type, Encoding) + $(TROW `string`, $(CODE immutable(char)[]), UTF-8) + $(TROW `wstring`, $(CODE immutable(wchar)[]), UTF-16) + $(TROW `dstring`, $(CODE immutable(dchar)[]), UTF-32) + ) + + $(P Note that built-in comparison operators operate on a + $(LINK2 http://www.unicode.org/glossary/#code_unit, code unit) basis. + The end result for valid strings is the same as that of + $(LINK2 http://www.unicode.org/glossary/#code_point, code point) + for $(LINK2 http://www.unicode.org/glossary/#code_point, code point) + comparison as long as both strings are in the same + $(LINK2 http://www.unicode.org/glossary/#normalization_form, normalization form). + Since normalization is a costly operation not suitable for language + primitives it's assumed to be enforced by the user. + ) + $(P The standard library lends a hand for comparing strings with mixed encodings + (by transparently decoding, see $(REF cmp, std,algorithm)), + $(REF_ALTTEXT case-insensitive comparison, icmp, std,uni) and $(REF_ALTTEXT normalization, normalize, std,uni). + ) + $(P Last but not least, a desired string sorting order differs + by culture and language and is usually nothing like code point + for code point comparison. The natural order of strings is obtained by applying + $(HTTP www.unicode.org/reports/tr10/, the Unicode collation algorithm) + that should be implemented in the standard library. + ) + +$(H4 $(LNAME2 char-pointers, Character Pointers and C strings)) + + $(P A pointer to a character can be generated: + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +string str = "abcd"; +immutable(char)* p = &str[3]; // pointer to 4th element +assert(*p == 'd'); +p = str.ptr; // pointer to 1st element +assert(*p == 'a'); +--------- +) + + $(P Only string *literals* are zero-terminated in D. + In general, when transferring a pointer + to string data to C, append a terminating `'\0'`: + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +string str = "ab"; +assert(str.ptr[2] == '\0'); // OK +str ~= "cd"; +// str is no longer zero-terminated +str ~= "\0"; +assert(str[4] == '\0'); // OK +str.length = 2; +// str is no longer correctly zero-terminated +assert(str.ptr[2] != '\0'); +--------- +) + + The function $(REF toStringz, std,string) can also be used. + +$(H4 $(LNAME2 printf, Example: `printf`)) + + $(P $(REF printf, core,stdc,stdio) is a C function and is not part of D. $(D printf()) + will print C strings, which are 0 terminated. There are two ways + to use $(D printf()) with D strings. The first is to add a + terminating 0: + ) + +--------- +str ~= "\0"; +printf("the string is '%s'\n", str.ptr); +--------- + + or: + +--------- +import std.string; +printf("the string is '%s'\n", std.string.toStringz(str)); +--------- + + $(P String literals already have a 0 appended to them, so + can be used directly:) + +----------- +printf("the string is '%s'\n", "string literal".ptr); +----------- + + $(P So, why does the first string literal to `printf` not need + the `.ptr`? The first parameter is prototyped as a `const(char)*`, and + a string literal can be implicitly converted to a `const(char)*`. + The rest of the arguments to `printf`, however, are variadic + (specified by `...`), + and a string literal typed `immutable(char)[]` cannot be passed + to variadic parameters.) + + $(P The second way is to use the precision specifier. + The length comes first, followed by the pointer:) + +--------- +printf("the string is '%.*s'\n", cast(int)str.length, str.ptr); +--------- + + $(P The best way is to use $(REF writefln, std,stdio), which can handle + D strings:) + +--------- +import std.stdio; +writefln("the string is '%s'", str); +--------- + +$(H3 $(LNAME2 void_arrays, Void Arrays)) + + $(P There are special types of array with a $(DDSUBLINK spec/type, void, `void`) + element type which can hold arrays of any kind. Void arrays are used for + low-level operations where some kind of array data is being handled, but + the exact type of the array elements are unimportant. The $(D .length) of a + void array is the length of the data in bytes, rather than the number of + elements in its original type. Array indices in slicing + operations are interpreted as byte indices. A void array cannot be indexed.) + + $(P Another array can be $(RELATIVE_LINK2 array-copying, copied) into a void array's elements, but not in a + $(DDSUBLINK spec/function, safe-functions, `@safe` function). + This is because the void array may hold pointers. + A void array cannot be $(RELATIVE_LINK2 array-setting, filled).) + + $(P Arrays of any type can be $(DDSUBLINK spec/type, implicit-conversions, + implicitly converted) to a (tail qualified) void array - the + compiler inserts the appropriate calculations so that the $(D .length) of + the resulting array's size is in bytes rather than number of elements. Void + arrays cannot be converted back to the original type without using an + $(DDSUBLINK spec/expression, cast_array, array cast), + and it is an error to convert to an array type whose element size does not + evenly divide the length of the void array.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +void main() +{ + int[] data1 = [1,2,3]; + + void[] arr = data1; // OK, int[] implicit converts to void[]. + assert(data1.length == 3); + assert(arr.length == 12); // length is implicitly converted to bytes. + + arr[0..4] = [5]; // Assign first 4 bytes to 1 int element + assert(data1 == [5,2,3]); + + arr ~= [6]; // Append the 4 bytes of an int + //data1 = arr; // Error: void[] does not implicitly + // convert to int[]. + int[] data2 = cast(int[]) arr; // OK, can convert with explicit cast. + assert(data2 is arr); // both point to the same set of bytes + assert(data2 == [5,2,3,6]); +} +--------- +) +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +void main() +{ + void[] arr = new void[12]; + long[] bad = cast(long[]) arr; // Runtime error: long.sizeof == 8, which + // does not divide arr.length, which is 12 + // bytes. +} +--------- +) + + $(P Void arrays can be static arrays if their length is known at + compile-time. The length is specified in bytes:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--------- +void main() +{ + byte[2] x; + int[2] y; + + void[2] a = x; // OK, lengths match + void[2] b = y; // Error: int[2] is 8 bytes long, doesn't fit in 2 bytes. +} +--------- +) + + $(P While it may seem that void arrays are just fancy syntax for + $(D ubyte[]), there is a subtle distinction. The garbage collector + generally will not scan $(D ubyte[]) arrays for pointers, $(D ubyte[]) + being presumed to contain only pure byte data, not pointers. However, it + $(I will) scan $(D void[]) arrays for pointers, since such an array may + have been implicitly converted from an array of pointers or an array of + elements that contain pointers. Allocating an array that contains pointers + as $(D ubyte[]) may run the risk of the GC collecting live memory if these + pointers are the only remaining references to their targets.) + +$(H2 $(LNAME2 implicit-conversions, Implicit Conversions)) + + $(P A pointer $(D T*) can be implicitly converted to + one of the following:) + + $(UL + $(LI $(D void*)) + ) + + $(P A static array $(D T[dim]) can be implicitly + converted to + one of the following ($(D U) is a base class of $(D T)): + ) + + $(UL + $(LI $(D T[])) + + $(LI $(D const(U)[])) + $(LI $(D const(U[]))) + $(LI $(D void[])) + ) + + $(P A dynamic array $(D T[]) can be implicitly converted to one of the + following ($(D U) is a base class of $(D T)):) + + $(UL + $(LI $(D const(U)[])) + $(LI $(D const(U[]))) + $(LI $(D void[])) + ) + + $(P Array literals can also be implicitly converted to static array + types. See $(DDSUBLINK spec/expression, array_literals, Array Literals) + for details.) + + $(P String literals can also be implicitly converted to static array + types and character pointer types. See $(DDSUBLINK spec/expression, string_literals, + String Literals) for details.) + +$(SPEC_SUBNAV_PREV_NEXT statement, Statements, hash-map, Associative Arrays) +) + +Macros: + CHAPTER=13 + TITLE=Arrays + _= diff --git a/spec/attribute.dd b/spec/attribute.dd new file mode 100644 index 0000000000..1491ce3b93 --- /dev/null +++ b/spec/attribute.dd @@ -0,0 +1,1291 @@ +Ddoc + +$(SPEC_S Attributes, + +$(HEADERNAV_TOC) + +$(H2 $(LNAME2 grammar, Grammar)) + +$(GRAMMAR +$(GNAME AttributeSpecifier): + $(GLINK Attribute) $(D :) + $(GLINK Attribute) $(GLINK DeclarationBlock) + +$(GNAME Attribute): + $(GLINK AlignAttribute) + $(GLINK AtAttribute) + $(GLINK DeprecatedAttribute) + $(GLINK FunctionAttributeKwd) + $(GLINK LinkageAttribute) + $(GLINK2 pragma, Pragma) + $(GLINK VisibilityAttribute) + $(RELATIVE_LINK2 abstract, $(D abstract)) + $(RELATIVE_LINK2 auto, $(D auto)) + $(RELATIVE_LINK2 const, $(D const)) + $(RELATIVE_LINK2 final, `final`) + $(RELATIVE_LINK2 gshared, $(D __gshared)) + $(RELATIVE_LINK2 linkage, $(D extern)) + $(RELATIVE_LINK2 immutable, $(D immutable)) + $(RELATIVE_LINK2 inout, $(D inout)) + $(RELATIVE_LINK2 override, $(D override)) + $(RELATIVE_LINK2 ref, $(D ref)) + $(RELATIVE_LINK2 return, $(D return)) + $(RELATIVE_LINK2 __rvalue, $(D __rvalue)) + $(RELATIVE_LINK2 scope, $(D scope)) + $(RELATIVE_LINK2 shared, $(D shared)) + $(RELATIVE_LINK2 static, $(D static)) + $(RELATIVE_LINK2 synchronized, `synchronized`) + +$(GNAME FunctionAttributeKwd): + $(RELATIVE_LINK2 nothrow, $(D nothrow)) + $(RELATIVE_LINK2 pure, $(D pure)) + +$(GNAME AtAttribute): + $(D @) $(RELATIVE_LINK2 disable, $(D disable)) + $(D @) $(RELATIVE_LINK2 future, $(D __future)) + $(D @) $(RELATIVE_LINK2 nogc, $(D nogc)) + $(D @) $(DDLINK spec/ob, Live Functions, `live`) + $(GLINK Property) + $(D @) $(RELATIVE_LINK2 safe, $(D safe)) + $(D @) $(RELATIVE_LINK2 safe, $(D system)) + $(D @) $(RELATIVE_LINK2 safe, $(D trusted)) + $(GLINK UserDefinedAttribute) + +$(GNAME Property): + $(D @) $(RELATIVE_LINK2 property, $(D property)) + +$(GNAME DeclarationBlock): + $(GLINK2 module, DeclDef) + $(D {) $(GLINK2 module, DeclDefs)$(OPT) $(D }) +) + + $(P Attributes are a way to modify one or more declarations. + The general forms are: + ) + +--- +attribute declaration; // affects the declaration + +attribute: // affects all declarations until the end of + // the current scope + declaration; + declaration; + ... + +attribute // affects all declarations in the block +{ + declaration; + declaration; + ... +} +--- + $(P Function attributes `@nogc`, `nothrow` and `pure` do not propagate inside + aggregate declarations.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +const pure @safe +{ + int i; // function attributes ignored for non-functions + void f(); // const attribute ignored for free function + + struct S + { + int i; + void f(); // pure ignored inside struct + } +} +static assert(is(typeof(i) == const int)); +static assert(is(typeof(&f) == void function() pure @safe)); +static assert(is(typeof(S.i) == const int)); +static assert(is(typeof(&S().f) == void delegate() const @safe)); +--- +) + $(P See also: $(MREF core, attribute) for other compiler-recognized attributes.) + + +$(H2 $(LNAME2 linkage, Linkage Attribute)) + +$(GRAMMAR +$(GNAME LinkageAttribute): + $(D extern) $(D $(LPAREN)) $(GLINK LinkageType) $(D $(RPAREN)) + $(D extern) $(D $(LPAREN)) $(D C) $(D ++) $(D ,) $(D $(RPAREN)) + $(D extern) $(D $(LPAREN)) $(D C) $(D ++) $(D ,) $(GLINK2 type, QualifiedIdentifier) $(D $(RPAREN)) + $(D extern) $(D $(LPAREN)) $(D C) $(D ++) $(D ,) $(GLINK NamespaceList) $(D $(RPAREN)) + $(D extern) $(D $(LPAREN)) $(D C) $(D ++) $(D ,) $(D class) $(D $(RPAREN)) + $(D extern) $(D $(LPAREN)) $(D C) $(D ++) $(D ,) $(D struct) $(D $(RPAREN)) + +$(GNAME LinkageType): + $(D C) + $(D C) $(D ++) + $(D D) + $(D Windows) + $(D System) + $(D Objective) $(D -) $(D C) + +$(GNAME NamespaceList): + $(GLINK2 expression, ConditionalExpression) + $(GLINK2 expression, ConditionalExpression) $(D ,) + $(GLINK2 expression, ConditionalExpression) $(D ,) $(GSELF NamespaceList) +) + + $(P D provides an easy way to call C functions and operating + system API functions, as compatibility with both is essential. + The $(I LinkageType) is case sensitive, and is meant to be + extensible by the implementation ($(I they are not keywords)). + $(D C) and $(D D) must be supplied, the others are what + makes sense for the implementation. + $(D C++) offers limited compatibility with C++, see the + $(LINK2 cpp_interface.html, Interfacing to C++) + documentation for more information. + $(D Objective-C) offers compatibility with Objective-C, + see the $(LINK2 objc_interface.html, Interfacing to Objective-C) + documentation for more information. + $(D System) is the same as $(D Windows) on Windows platforms, + and $(D C) on other platforms. + ) + $(P $(B Implementation Note:) + for Win32 platforms, $(D Windows) should exist. + ) + + $(P C function calling conventions are + specified by: + ) + +--------------- +extern (C): + int foo(); // call foo() with C conventions +--------------- + Note that `extern(C)` can be provided for all types of + declarations, including `struct` or `class`, even though + there is no corresponding match on the `C` side. In that case, + the attribute is ignored. This behavior applies for nested + functions and nested variables as well. However, for `static` member + methods and `static` nested functions, adding `extern(C)` will + change the calling convention, but not the mangling. + + $(P D conventions are:) + +--------------- +extern (D): +--------------- + + $(P Windows API conventions are:) + +--------------- +extern (Windows): + void *VirtualAlloc( + void *lpAddress, + uint dwSize, + uint flAllocationType, + uint flProtect + ); +--------------- + + $(P The Windows convention is distinct from the C convention only on Win32 platforms, + where it is equivalent to the + $(LINK2 https://en.wikipedia.org/wiki/X86_calling_conventions, stdcall) convention.) + + $(P Note that a $(DDSUBLINK spec/declaration, extern, lone $(D extern) keyword) + is used as a storage class.) + +$(H3 $(LNAME2 namespace, C++ Namespaces)) + + $(P The linkage form $(D extern $(LPAREN)C++, )$(I QualifiedIdentifier)$(D $(RPAREN)) + creates C++ declarations that reside in C++ namespaces. The $(I QualifiedIdentifier) + specifies the namespaces. + ) + + --- + extern (C++, N) { void foo(); } + --- + + $(P refers to the C++ declaration:) + + $(CPPCODE namespace N { void foo(); }) + + $(P and can be referred to with or without qualification:) + + --- + foo(); + N.foo(); + --- + + $(P Namespaces create a new named scope that is imported into its enclosing scope.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + extern (C++, N) { void foo(); void bar(); } + extern (C++, M) { void foo(); } + + void main() + { + bar(); // ok + //foo(); // error - N.foo() or M.foo() ? + M.foo(); // ok + } + --- + ) + + $(P Multiple dotted identifiers in the $(I QualifiedIdentifier) create nested namespaces:) + + --- + extern (C++, N.M) { extern (C++) { extern (C++, R) { void foo(); } } } + N.M.R.foo(); + --- + + $(P refers to the C++ declaration:) + + $(CPPCODE namespace N { namespace M { namespace R { void foo(); } } }) + + +$(H2 $(LNAME2 align, $(D align) Attribute)) + +$(GRAMMAR +$(GNAME AlignAttribute): + $(D align $(LPAREN) default $(RPAREN)) + $(D align) + $(D align) $(D $(LPAREN)) $(GLINK2 expression, AssignExpression) $(D $(RPAREN)) +) + + + $(P Specifies the alignment of:) + + $(OL + $(LI variables) + $(LI struct fields) + $(LI union fields) + $(LI class fields) + $(LI struct, union, and class types) + ) + + $(P $(D align$(LPAREN)default$(RPAREN)) (re)sets it to the default, which matches the default member alignment + of the companion C compiler. $(D align) by itself is the same as $(D align$(LPAREN)default$(RPAREN)).) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +-------- +struct S +{ + align(default): // same as `align:` + byte a; // placed at offset 0 + int b; // placed at offset 4 + long c; // placed at offset 8 +} +static assert(S.alignof == 8); +static assert(S.c.offsetof == 8); +static assert(S.sizeof == 16); +-------- +) + $(P The $(I AssignExpression) specifies the alignment + which matches the behavior of the companion C compiler when non-default + alignments are used. It must be a non-negative power of 2. + ) + + $(P A value of 1 means that no alignment is done; + fields are packed together. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +-------- +struct S +{ + align (1): + byte a; // placed at offset 0 + int b; // placed at offset 1 + long c; // placed at offset 5 +} +static assert(S.alignof == 1); +static assert(S.c.offsetof == 5); +static assert(S.sizeof == 13); +-------- +) + $(P The natural alignment of an aggregate is the maximum alignment of its + fields. It can be overridden by setting the alignment outside of the + aggregate.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +-------- +align (2) struct S +{ + align (1): + byte a; // placed at offset 0 + int b; // placed at offset 1 + long c; // placed at offset 5 +} +static assert(S.alignof == 2); +static assert(S.c.offsetof == 5); +static assert(S.sizeof == 14); +-------- +) + $(P Setting the alignment of a field aligns it to that power of 2, regardless + of the size of the field.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +-------- +struct S +{ + byte a; // placed at offset 0 + align (4) byte b; // placed at offset 4 + align (16) short c; // placed at offset 16 +} +static assert(S.alignof == 16); +static assert(S.c.offsetof == 16); +static assert(S.sizeof == 32); +-------- +) + $(P The $(I AlignAttribute) is reset to the default when + entering a function scope or a non-anonymous struct, union, class, and restored + when exiting that scope. + It is not inherited from a base class. + ) + + $(P See also: $(DDSUBLINK spec/struct, struct_layout, Struct Layout).) + +$(H3 $(LNAME2 align_gc, GC Compatibility)) + + $(P Do not align references or pointers that were allocated + using $(GLINK2 expression, NewExpression) on boundaries that are not + a multiple of $(D size_t). The garbage collector assumes that pointers + and references to GC allocated objects will be on $(D size_t) + byte boundaries. + ) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +struct S +{ + align(1): + byte b; + int* p; +} + +static assert(S.p.offsetof == 1); + +@safe void main() +{ + S s; + s.p = new int; // error: can't modify misaligned pointer in @safe code +} +--- +) + $(UNDEFINED_BEHAVIOR If any pointers and references to GC + allocated objects are not aligned on `size_t` byte boundaries.) + + +$(H2 $(LNAME2 deprecated, $(D deprecated) Attribute)) + +$(GRAMMAR +$(GNAME DeprecatedAttribute): + $(D deprecated) + $(D deprecated $(LPAREN)) $(GLINK2 expression, AssignExpression) $(D $(RPAREN)) +) + + $(P It is often necessary to deprecate a feature in a library, + yet retain it for backwards compatibility. Such + declarations can be marked as $(D deprecated), which means + that the compiler can be instructed to produce an error + if any code refers to deprecated declarations: + ) + + --------------- + deprecated + { + void oldFoo(); + } + + oldFoo(); // Deprecated: function test.oldFoo is deprecated + --------------- + + $(P Optionally a string literal or manifest constant can be used + to provide additional information in the deprecation message. + ) + + --------------- + deprecated("Don't use bar") void oldBar(); + oldBar(); // Deprecated: function test.oldBar is deprecated - Don't use bar + --------------- + + $(P Calling CTFE-able functions or using manifest constants is also possible. + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --------------- + import std.format; + + enum message = format("%s and all its members are obsolete", Foobar.stringof); + deprecated(message) class Foobar {} + deprecated(format("%s is also obsolete", "This class")) class BarFoo {} + + void main() + { + auto fb = new Foobar(); // Deprecated: class test.Foobar is deprecated - Foobar + // and all its members are obsolete + auto bf = new BarFoo(); // Deprecated: class test.BarFoo is deprecated - This + // class is also obsolete + } + --------------- + ) + + $(P $(B Implementation Note:) The compiler should have a switch + specifying if $(D deprecated) should be ignored, cause a warning, or cause an error during compilation. + ) + + +$(H2 $(LNAME2 future, `@__future` attribute)) + + $(P The `@__future` attribute is used to mark a new symbol which could + cause a name clash in another module. The other module using a symbol with the + same name will continue to compile as before but will show a deprecation message. + The message indicates that the new symbol will break the existing code in future, + and the other module should be updated. + ) + + $(NOTE Currently only methods that implicitly override a `@__future` base class + method show a deprecation message.) + + $(P See $(LINK2 https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1007.md, + DIP1007) for details.) + + $(COMMENT + --- + module a; + @__future int i; + + module b; + import a; + import c : i; + enum e = i; // Deprecation: `c.i` will conflict with `@__future` symbol `a.i` + --- + ) + + +$(H2 $(LNAME2 visibility_attributes, Visibility Attributes)) + +$(GRAMMAR +$(GNAME VisibilityAttribute): + $(D export) + $(D package) + $(D package) $(D $(LPAREN)) $(GLINK2 type, QualifiedIdentifier) $(D $(RPAREN)) + $(D private) + $(D protected) + $(D public) +) + +$(P Visibility is an attribute that is one of $(D private), $(D package), +`protected`, $(D public), or $(D export). They may be referred to as protection +attributes in documents predating $(LINK2 http://wiki.dlang.org/DIP22, DIP22).) + + $(P Visibility participates in $(DDSUBLINK spec/module, name_lookup, symbol name lookup). + ) + +$(H3 $(LNAME2 export, $(D export) Attribute)) + + $(P $(D export) means that a symbol can be accessed from outside the executable, + shared library, or DLL. The symbol is said to be exported from where it is defined + in an executable, shared library, or DLL, and imported by another executable, shared library, + or DLL.) + + $(P $(D export) applied to the definition of a symbol will export it. $(D export) applied to + a declaration of a symbol will import it. + A variable is a definition unless `extern` is applied to it.) + + --- + export int x = 3; // definition, exporting `x` + export int y; // definition, exporting `y` + export extern int z; // declaration, importing `z` + + export __gshared h = 3; // definition, exporting `h` + export __gshared i; // definition, exporting `i` + export extern __gshared int j; // declaration, importing `j` + --- + + $(P A function with a body is a definition, without a body is a declaration.) + + --- + export void f() { } // definition, exporting `f` + export void g(); // declaration, importing `g` + --- + + $(P In Windows terminology, $(I dllexport) means exporting a symbol from a DLL, and $(I dllimport) means + a DLL or executable is importing a symbol from a DLL.) + +$(H3 $(LNAME2 package, $(D package) Attribute)) + + $(P $(D package) extends $(D private) so that package members can be accessed + from code in other modules that are in the same package. + If no identifier is provided, this applies to the innermost package only, + or defaults to $(D private) if a module is not nested in a package. + ) + + $(P $(D package) may have an optional parameter in the form of a dot-separated identifier + list which is resolved as the qualified package name. The package must be either the module's + parent package or one of its ancestors. If this parameter is present, the symbol + will be visible in the specified package and all of its descendants. + ) + +$(H3 $(LNAME2 private, $(D private) Attribute)) + + $(P Symbols with $(D private) visibility can only be accessed from + within the same module. + Private member functions are implicitly $(DDSUBLINK spec/function, final, `final`) + and cannot be overridden. + ) + +$(H3 $(LNAME2 protected, $(D protected) Attribute)) + + $(P $(D protected) only applies inside classes (and templates as they can be mixed in) + and means that a symbol can only be seen by members of the same module, + or by a derived class. + If accessing a protected instance member through a derived class member + function, that member can only be accessed for the object instance + which can be implicitly cast to the same type as $(SINGLEQUOTE this). + $(D protected) module members are illegal. + ) + +$(H3 $(LNAME2 public, $(D public) Attribute)) + + $(P $(D public) means that any code within the executable can see the member. + It is the default visibility attribute. + ) + + +$(H2 $(LNAME2 mutability, Mutability Attributes)) + +$(H3 $(LNAME2 const, $(D const) Attribute)) + + $(P The $(DDLINK spec/const3, Type Qualifiers, $(D const) type qualifier) + changes the type of the declared symbol from $(D T) to $(D const(T)), + where $(D T) is the type specified (or inferred) for the introduced symbol in the absence of $(D const). + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --------------- + const int foo = 7; + static assert(is(typeof(foo) == const(int))); + + const double bar = foo + 6; + static assert(is(typeof(bar) == const(double))); + --- + ) + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + class C + { + const void foo(); + const + { + void bar(); + } + void baz() const; + } + pragma(msg, typeof(C.foo)); // const void() + pragma(msg, typeof(C.bar)); // const void() + pragma(msg, typeof(C.baz)); // const void() + + static assert(is(typeof(C.foo) == typeof(C.bar)) && + is(typeof(C.bar) == typeof(C.baz))); + --------------- + ) + + $(P See also: $(DDSUBLINK spec/declaration, methods-returning-qualified, Methods Returning a Qualified Type).) + +$(H3 $(LNAME2 immutable, $(D immutable) Attribute)) + + $(P The $(D immutable) attribute modifies the type from $(D T) to $(D immutable(T)), + the same way as $(D const) does. See: + ) + * $(DDSUBLINK spec/const3, immutable_storage_class, `immutable` storage class) + * $(DDSUBLINK spec/const3, immutable_type, $(D immutable) type qualifier) + +$(H3 $(LNAME2 inout, $(D inout) Attribute)) + + $(P The $(DDSUBLINK spec/const3, inout, $(D inout) attribute) modifies the type from $(D T) to $(D inout(T)), + the same way as $(D const) does. + ) + + +$(H2 $(LNAME2 shared-storage, Shared Storage Attributes)) + +$(H3 $(LNAME2 shared, $(D shared) Attribute)) + + $(P See $(DDSUBLINK spec/const3, shared, $(D shared)).) + +$(H3 $(LNAME2 gshared, $(D __gshared) Attribute)) + + $(P By default, non-immutable global declarations reside in thread local + storage. When a global variable is marked with the $(D __gshared) + attribute, its value is shared across all threads.) + + --- + int foo; // Each thread has its own exclusive copy of foo. + __gshared int bar; // bar is shared by all threads. + --- + + $(P $(D __gshared) may also be applied to member variables and local + variables. In these cases, $(D __gshared) is equivalent to $(D static), + except that the variable is shared by all threads rather than being + thread local.) + + --- + class Foo + { + __gshared int bar; + } + + int foo() + { + __gshared int bar = 0; + return bar++; // Not thread safe. + } + --- + + $(P $(RED Warning:) + Unlike the $(RELATIVE_LINK2 shared, `shared`) attribute, $(D __gshared) provides no + safeguards against data races or other multi-threaded synchronization + issues. It is the responsibility of the programmer to ensure that + access to variables marked $(D __gshared) is synchronized correctly.) + + $(P $(D __gshared) is disallowed in `@safe` code.) + +$(H3 $(LNAME2 synchronized, $(D synchronized) Attribute)) + + $(P See $(DDSUBLINK spec/class, synchronized-classes, Synchronized Classes).) + + +$(H2 $(LNAME2 disable, $(D @disable) Attribute)) + +$(P A reference to a declaration marked with the $(CODE @disable) attribute +causes a compile time error. This can be used to explicitly disallow certain +operations or overloads at compile time rather than relying on generating a +runtime error.) + +--- +@disable int x; +@disable void foo(); + +void main() +{ + x++; // error, x is disabled + foo(); // error, foo is disabled +} +--- + + $(P $(DDSUBLINK spec/struct, disable_default_construction, `@disable this();`) + inside a struct disallows default construction. + ) + + $(P $(DDSUBLINK spec/struct, disable-copy, Disabling a struct copy constructor) + makes the struct not copyable. + ) + + +$(H2 $(LNAME2 safe, $(D @safe), $(D @trusted), and $(D @system) Attributes)) + + $(P See $(DDSUBLINK spec/function, function-safety, Function Safety).) + +$(H3 $(LNAME2 system-variables, System Variables)) + + $(P Variables marked `@system` cannot be accessed from `@safe` code.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +@system int* p; + +struct S +{ + @system int i; +} + +void main() @safe +{ + int x = *p; // error with `-preview=systemVariables`, deprecation otherwise + + S s; + s.i = 0; // ditto +} +--- +) + + +$(H2 $(LNAME2 function-attributes, Function Attributes)) + +$(H3 $(LNAME2 nogc, $(D @nogc) Attribute)) + + $(P See $(DDSUBLINK spec/function, nogc-functions, No-GC Functions).) + +$(H3 $(LNAME2 property, $(D @property) Attribute)) + + $(P See $(DDSUBLINK spec/function, property-functions, Property Functions).) + +$(H3 $(LNAME2 nothrow, $(D nothrow) Attribute)) + + $(P See $(DDSUBLINK spec/function, nothrow-functions, Nothrow Functions).) + +$(H3 $(LNAME2 pure, $(D pure) Attribute)) + + $(P See $(DDSUBLINK spec/function, pure-functions, Pure Functions).) + +$(H2 $(LNAME2 ref, $(D ref) Attribute)) + + $(P See $(DDSUBLINK spec/declaration, ref-storage, `ref` Storage Class).) + +$(H2 $(LNAME2 return, $(D return) Attribute)) + + * $(DDSUBLINK spec/function, return-ref-parameters, Return Ref Parameters). + * $(DDSUBLINK spec/function, return-scope-parameters, Return Scope Parameters). + +$(H2 $(LNAME2 __rvalue, $(D __rvalue) Attribute)) + + * $(DDSUBLINK spec/expression, __rvalue-function-attribute, $(I RvalueExpression)). + +$(H2 $(LNAME2 static, $(D static) Attribute)) + + $(P The $(D static) attribute applies to types, functions and data. + $(D static) is ignored when applied to other declarations.) + + $(P Inside an aggregate type, a `static` + declaration does not apply to a particular + instance of an object, but to the type of the object. In + other words, it means there is no $(D this) reference. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------------- +class Foo +{ + static int x; + static int bar() { return x; } + int foobar() { return 7; } +} + +Foo.x = 6; // no instance needed +assert(Foo.bar() == 6); +//Foo.foobar(); // error, no instance of Foo + +Foo f = new Foo; +assert(f.bar() == 6); +assert(f.foobar() == 7); +--------------- +) + +$(P + Static methods are never $(DDSUBLINK spec/function, virtual-functions, virtual). +) +$(P + Static data has one instance per thread, not one per object. +) + +$(P A static $(DDSUBLINK spec/function, nested, nested function) +or $(DDSUBLINK spec/struct, nested, type) cannot +access variables in the parent scope.) + +$(P Inside a function, a $(DDSUBLINK spec/function, local-static-variables, +static local variable) persists after the function returns.) + +$(P + Static does not have the additional C meaning of being local + to a file. Use the $(RELATIVE_LINK2 VisibilityAttribute, `private`) + attribute in D to achieve that. + For example: +) + +--------------- +module foo; +int x = 3; // x is global +private int y = 4; // y is local to module foo +--------------- + + +$(H2 $(LNAME2 auto, $(D auto) Attribute)) + + $(P The $(D auto) attribute is used when there are no other attributes + and $(DDSUBLINK spec/declaration, auto-declaration, type inference) is desired. + ) + +--- +auto i = 6.8; // declare i as a double +--- + + $(P For functions, the `auto` attribute means return type inference. + See $(DDSUBLINK spec/function, auto-functions, Auto Functions). + ) + +$(H2 $(LNAME2 scope, $(D scope) Attribute)) + +$(P + The `scope` attribute signifies a variable's pointer values will not escape the scope that the variable is declared in. +) + +$(P + If the variable has a type that does not contain any indirections, the `scope` attribute is ignored. +) + +$(P + When applied to a global variable, `scope` is also ignored, since there is no scope larger than global scope that pointers could escape to. +) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +scope int* x; // scope ignored, global variable + +void main() +{ + // scope static int* x; // cannot be both scope and static + scope float y; // scope ignored, no indirections + scope int[2] z; // scope ignored, static array is value type + scope int[] w; // scope dynamic array +} +--- +) + +$(P + When applied to a local variable with a type that has indirections, + its value may not be assigned to a variable with longer lifetime: +) + $(UL + $(LI Variables outside the $(DDSUBLINK spec/statement, scope-statement, Scope Statement) that the variable is declared in) + $(LI Variables declared before the `scope` variable$(COMMA) since local variables are destructed in the reverse order that they are declared in) + $(LI `__gshared` or `static` variables) + ) + +$(P + Other operations implicitly assigning them to variables with longer lifetime are also disallowed: +) + $(UL + $(LI Returning a `scope` variable from a function) + $(LI Assigning a `scope` variable to a non-scope parameter by calling a function) + $(LI Putting a `scope` variable in an array literal) + ) + + $(NOTE escape analysis is only done in `@safe` code. The $(D -preview=dip1000) switch + must also be enabled.) +$(P + The `scope` attribute is part of the variable declaration, not the type, and it only applies to the first level of indirection. + For example, it is impossible to declare a variable as a dynamic array of scope pointers, because `scope` only applies to the `.ptr` + of the array itself, not its elements. `scope` affects various types as follows: +) + + $(TABLE_2COLS , + $(THEAD Type of local variable, What `scope` applies to) + + $(TROW Any $(DDSUBLINK spec/type, basic-data-types, Basic Data Type), nothing) + $(TROW $(DDSUBLINK spec/type, pointers, Pointer) `T*`, the pointer value) + $(TROW $(DDSUBLINK spec/arrays, dynamic-arrays, Dynamic Array) `T[]`, the `.ptr` to the elements) + $(TROW $(DDSUBLINK spec/arrays, static-arrays, Static Array) `T[n]`, each element `T`) + $(TROW $(GLINK2 hash-map, Associative Array) `K[V]`, the pointer to the implementation defined structure) + $(TROW `struct` or `union`, each of its member variables) + $(TROW `function` pointer, the pointer value) + $(TROW $(DDSUBLINK spec/function, closures, delegate), both the `.funcptr` and `.ptr` (closure context) pointer values) + $(TROW `class` or `interface`, the class reference) + $(TROW $(GLINK2 enum, enum), the base type) + ) + +--- +struct S +{ + string str; // note: string = immutable(char)[] + string* strPtr; +} + +string escape(scope S s, scope S* sPtr, scope string[2] sarray, scope string[] darray) +{ + return s.str; // invalid, scope applies to struct members + return *s.strPtr; // valid, scope struct member is dereferenced + return sPtr.str; // valid, struct pointer is dereferenced + return *sPtr.strPtr; // valid, two pointers are dereferenced + return sarray[0]; // invalid, scope applies to static array elements + return sarray[1]; // invalid, ditto + return darray[0]; // valid, scope applies to array pointer, not elements +} +--- + +$(H3 $(LNAME2 scope-values, Scope Values)) + +$(P + A "`scope` value" is the value of a `scope` variable, or a generated value pointing to stack allocated memory. + Such values are generated by $(DDSUBLINK spec/arrays, slicing, slicing) a static array + or creating $(DDSUBLINK spec/type, pointers, a pointer) + to a variable that is (or may be) allocated on the stack: +) + $(UL + $(LI A function parameter) + $(LI A local variable) + $(LI A struct member accessed through the implicit `this` parameter) + $(LI The return value of a $(DDSUBLINK spec/function, ref-functions, Ref Function)) + ) + +$(P + The variadic parameter from $(DDSUBLINK spec/function, typesafe_variadic_functions, Typesafe Variadic Functions) is also a scope value, + since the arguments are passed on the stack. +) + +$(P + When a local variable is assigned a `scope` value, it is inferred `scope`, even when the variable has an explicit type and does not use the `auto` keyword. +) + +--- +@safe: +ref int[2] identity(return ref int[2] x) {return x;} + +int* escape(int[2] y, scope int* z) +{ + int x; + + auto xPtr = &x; // inferred `scope int*` + int[] yArr = identity(y)[]; // inferred `scope int[]` + int* zCopy = z; // inferred `scope int*` + + return zCopy; // error +} + +void variadic(int[] a...) +{ + int[] x = a; // inferred `scope int[]` +} + +void main() +{ + variadic(1, 2, 3); +} +--- + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct S +{ + int x; + + // this method may be called on a stack-allocated instance of S + void f() @safe + { + int* p = &x; // inferred `scope int* p` + int* q = &this.x; // equivalent + } +} +--- +) + +$(P + $(DDSUBLINK spec/function, scope-parameters, Scope Parameters) are treated the same as scope local variables, + except that returning them is allowed when the function has $(DDSUBLINK spec/function, function-attribute-inference, Function Attribute Inference). + In that case, they are inferred as $(DDSUBLINK spec/function, return-scope-parameters, Return Scope Parameters). +) + +$(H3 $(LNAME2 scope-class-var, $(D scope) Class Instances)) +$(P + When used to allocate a class instance directly, a `scope` variable signifies the RAII + (Resource Acquisition Is Initialization) protocol. + This means that the destructor for an object is automatically called when the + reference to it goes out of scope. The destructor is called even + if the scope is exited via a thrown exception, thus $(D scope) + is used to guarantee cleanup. +) +$(P + When a class is constructed with `new` and assigned to a local `scope` variable, + it may be allocated on the stack and permitted in a `@nogc` context. +) +$(P + If there is more than one `scope` class variable going out of scope + at the same point, then the destructors are called in the reverse + order that the variables were constructed. +) +$(P + Assignment to a $(D scope) variable with class type, + other than initialization, is not allowed, because that would complicate + proper destruction of the variable. +) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import core.stdc.stdio : puts; + +class C +{ + ~this() @nogc { puts(__FUNCTION__); } +} + +void main() @nogc +{ + { + scope c0 = new C(); // allocated on the stack + scope c1 = new C(); + + //c1 = c0; // Error: cannot rebind scope variables + + // destructor of `c1` and `c0` are called here in that order + } + puts("bye"); +} +--- +) + + +$(H2 $(LNAME2 class-attributes, OOP Attributes)) + +$(H3 $(LNAME2 abstract, $(D abstract) Attribute)) + +$(P + An $(DDSUBLINK spec/class, abstract, abstract class) must be overridden by a derived class. + Declaring an abstract member function makes the class abstract. +) + +$(H3 $(LNAME2 final, `final` Attribute)) + +$(UL +$(LI A class can be declared $(DDSUBLINK spec/class, final, `final`) to prevent + subclassing.) +$(LI A class method can be declared $(DDSUBLINK spec/function, final, `final`) + to prevent a derived class overriding it.) +$(LI Interfaces can define $(DDSUBLINK spec/interface, method-bodies, `final` methods).) +) + +$(H3 $(LNAME2 override, $(D override) Attribute)) + + $(P See $(DDSUBLINK spec/function, virtual-functions, Virtual Functions).) + + +$(H2 $(LNAME2 mustuse-attribute, `@mustuse` Attribute)) + + $(P + The `@mustuse` attribute is a compiler-recognized $(RELATIVE_LINK2 uda, + UDA) defined in the D runtime module $(DPLLINK phobos/core_attribute.html, + `core.attribute`). + ) + + + $(P + An expression is considered to be discarded if and only if either of the + following is true: + ) + $(UL + $(LI + it is the top-level $(GLINK2 expression, Expression) in an $(GLINK2 + statement, ExpressionStatement), or + ) + $(LI + it is the $(GLINK2 expression, AssignExpression) on the left-hand + side of the comma in a $(GLINK2 expression, CommaExpression). + ) + ) + + $(P + It is a compile-time error to discard an expression if all of the + following are true: + ) + + $(UL + $(LI + it is not an assignment expression, an increment expression, or a + decrement expression; and + ) + + $(LI + its type is a `struct` or `union` type whose declaration is + annotated with `@mustuse`. + ) + ) + + $(P + "Assignment expression" means either a $(DDSUBLINK spec/expression, simple_assignment_expressions, + simple assignment expression) or an + $(DDSUBLINK spec/expression, assignment_operator_expressions, assignment + operator expression). + ) + + $(P + "Increment expression" means a $(GLINK2 expression, UnaryExpression) or + $(GLINK2 expression, PostfixExpression) whose operator is `++`. + ) + + $(P + "Decrement expression" means a $(GLINK2 expression, UnaryExpression) or + $(GLINK2 expression, PostfixExpression) whose operator is `--`. + ) + + $(P + It is a compile-time error to attach `@mustuse` to a function + declaration or to any aggregate declaration other than a `struct` or + `union` declaration. The purpose of this rule is to reserve such usage + for possible future expansion. + ) + +$(H2 $(LNAME2 uda, User-Defined Attributes)) + +$(GRAMMAR +$(GNAME UserDefinedAttribute): + $(D @ $(LPAREN)) $(GLINK2 template, TemplateArgumentList) $(D $(RPAREN)) + $(D @) $(GLINK2 template, TemplateSingleArgument) + $(D @) $(GLINK_LEX Identifier) $(D $(LPAREN)) $(GLINK2 expression, NamedArgumentList)$(OPT) $(D $(RPAREN)) + $(D @) $(GLINK2 template, TemplateInstance) + $(D @) $(GLINK2 template, TemplateInstance) $(D $(LPAREN)) $(GLINK2 expression, NamedArgumentList)$(OPT) $(D $(RPAREN)) +) + + $(P + User-Defined Attributes (UDA) are compile-time annotations that can be attached + to a declaration. These attributes can then be queried, extracted, and manipulated + at compile time. There is no runtime component to them. + ) + +A user-defined attribute is defined using: +* A list of one or more $(GLINK2 template, TemplateArgument)s +* A compile-time expression (matching the above grammar) +* A symbol identifier +* An expression (matching the above grammar) to invoke with an argument list at compile-time + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +@3 int a; // value attribute +@("string", 7) int b; // multiple values + +// using compile-time constant +enum val = 3; +@val int a2; // has same attribute as `a` + +enum Foo; +@Foo int c; // type name attribute + +struct Bar +{ + int x; +} +@Bar() int d; // type instance attribute +@Bar(3) int e; // type instance attribute using initializer +--- +) + $(P For `e`, the attribute is an instance of struct `Bar` which is + $(DDSUBLINK spec/struct, static_struct_init, statically initialized) + using its argument.) + + $(P + If there are multiple UDAs in scope for a declaration, they are concatenated: + ) + +--- +@(1) +{ + @(2) int a; // has UDAs (1, 2) + @("string") int b; // has UDAs (1, "string") +} +--- + + $(P A function parameter can have a UDA. Parameters do not inherit UDAs from outside the parameter list.) +--- +@2 void f(@3 int p) +{ + pragma(msg, __traits(getAttributes, p)); // prints AliasSeq!(3) +} + +--- + +$(H3 $(LNAME2 getAttributes, `__traits(getAttributes)`)) + + $(P + UDAs can be extracted into a + $(DDSUBLINK spec/template, variadic-templates, compile-time sequence) using $(D __traits): + ) + +--- +@('c') string s; +pragma(msg, __traits(getAttributes, s)); // prints AliasSeq!('c') +--- + + $(P + If there are no user-defined attributes for the symbol, an empty sequence is returned. + The result can be used just like any compile-time sequence - it can be indexed, + passed as template parameters, etc. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +enum e = 7; +@("hello") struct SSS { } +@(3) +{ + @(4) @e @SSS int foo; +} + +alias TP = __traits(getAttributes, foo); + +pragma(msg, TP); // prints AliasSeq!(3, 4, 7, (SSS)) +pragma(msg, TP[2]); // prints 7 +--- +) + + $(P + Any types in the sequence can be used to declare things: + ) + +--- +TP[3] a; // a is declared as an SSS +--- + + $(P + The attribute of the type name is not the same as the attribute of the variable: + ) + +--- +pragma(msg, __traits(getAttributes, a)); // prints AliasSeq!() +pragma(msg, __traits(getAttributes, typeof(a))); // prints AliasSeq!("hello") +--- + +$(H3 $(LNAME2 uda-usage, Usage)) + + $(P + Of course, the real value of UDAs is to be able to create user-defined types with + specific values. Having attribute values of basic types does not scale. + ) + + $(P + Whether the attributes are values or symbols is up to the user, and whether later + attributes accumulate or override earlier ones is also up to how the user + interprets them. + ) + +$(H3 $(LNAME2 uda-templates, Templates)) + + $(P + If a UDA is attached to a template declaration, then it will be automatically + attached to all direct members of instances of that template. If any of those + members are templates themselves, this rule applies recursively: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +@("foo") template Outer(T) +{ + struct S + { + int x; + } + int y; + void fun() {} + @("bar") template Inner(U) + { + int z; + } +} + +pragma(msg, __traits(getAttributes, Outer!int.S)); +// prints AliasSeq!("foo") +pragma(msg, __traits(getAttributes, Outer!int.S.x)); +// prints AliasSeq!() +pragma(msg, __traits(getAttributes, Outer!int.y)); +// prints AliasSeq!("foo") +pragma(msg, __traits(getAttributes, Outer!int.fun)); +// prints AliasSeq!("foo") +pragma(msg, __traits(getAttributes, Outer!int.Inner)); +// prints AliasSeq!("foo", "bar") +pragma(msg, __traits(getAttributes, Outer!int.Inner!int.z)); +// prints AliasSeq!("foo", "bar") +--- +) + + $(P + UDAs cannot be attached to template parameters. + ) +$(SPEC_SUBNAV_PREV_NEXT property, Properties, pragma, Pragmas) +) + +Macros: + CHAPTER=9 + TITLE=Attributes diff --git a/spec/betterc.dd b/spec/betterc.dd new file mode 100644 index 0000000000..2ee111b876 --- /dev/null +++ b/spec/betterc.dd @@ -0,0 +1,156 @@ +Ddoc + +$(SPEC_S Better C, + +$(HEADERNAV_TOC) + +$(P BetterC is a subset of D that doesn't depend on the D runtime library, only the C runtime library. +) + +$(P $(RED Warning:) While the D runtime library and standard library are not linked in, +it is still possible to import several packages (``core.*`` and ``std.*``) and use some templates, types and function declarations without bodies. +However, these libraries were not written for BetterC, so you will need to determine which symbols may be used. +Expect cryptic compiler or linker errors. +) + +$(H2 $(LNAME2 linking, Linking)) + + $(P It is straightforward to link C functions and libraries into D programs. + But linking D functions and libraries into C programs is not straightforward. + ) + + $(P D programs generally require:) + + $(OL + $(LI The D runtime library to be linked in, because many features of + the core language require runtime library support.) + $(LI The `main()` function to be written in D, to ensure that the required + runtime library support is properly initialized.) + ) + + $(P To link D functions and libraries into C programs, it's necessary to only + require the C runtime library to be linked in. This is accomplished by defining + a subset of D that fits this requirement, called $(B BetterC). + ) + +$(H2 $(LNAME2 better-c, Better C)) + + $(IMPLEMENTATION_DEFINED $(B BetterC) is typically enabled by setting the $(TT -betterC) + command line flag for the implementation. + ) + + $(P When $(B BetterC) is enabled, the predefined + $(DDLINK spec/version, Conditional Compilation, version) `D_BetterC` + can be used for conditional compilation. + ) + + + $(P An entire program can be written in $(B BetterC) by supplying a C `main()` function:) + + --- + extern(C) void main() + { + import core.stdc.stdio : printf; + printf("Hello betterC\n"); + } + --- + +$(CONSOLE +$(GT) dmd -betterC hello.d && ./hello +Hello betterC +) + + $(P Limiting a program to this subset of runtime features is useful + when targeting constrained environments where the use of such features + is not practical or possible. + ) + + $(P $(B BetterC) makes embedding D libraries in existing larger projects easier by: + ) + + $(OL + $(LI Simplifying the process of integration at the build-system level) + $(LI Removing the need to ensure that Druntime is properly initialized on + calls to the library, for situations when an initialization step is not + performed or would be difficult to insert before the library is used.) + $(LI Mixing memory management strategies (GC + manual memory management) can + be tricky, hence removing D's GC from the equation may be worthwhile sometimes.) + ) + + $(NOTE BetterC and $(DDLINK spec/importc, ImportC, ImportC) are very different. + ImportC is an actual C compiler. BetterC is a subset of D that relies only on the + existence of the C Standard library.) + + +$(H2 $(LNAME2 retained, Retained Features)) + + $(P Nearly the full language remains available. Highlights include:) + + $(OL + $(LI Unrestricted use of compile-time features) + $(LI Full metaprogramming facilities) + $(LI Nested functions, nested structs, delegates and $(DDSUBLINK spec/expression, function_literals, lambdas)) + $(LI Member functions, constructors, destructors, operating overloading, etc.) + $(LI The full module system) + $(LI Array slicing, and array bounds checking) + $(LI RAII (yes, it can work without exceptions)) + $(LI `scope(exit)`) + $(LI Memory safety protections) + $(LI $(DDLINK spec/cpp_interface, Interfacing to C++, Interfacing to C++)) + $(LI COM classes and C++ classes) + $(LI `assert` failures are directed to the C runtime library) + $(LI `switch` with strings) + $(LI `final switch`) + $(LI `unittest`) + $(LI $(DDSUBLINK spec/interfaceToC, calling_printf, `printf` format validation)) + ) + +$(H3 $(LNAME2 unittests, Running unittests in `-betterC`)) + +While testing can be done without the $(TT -betterC) flag, it is sometimes desirable to run the testsuite in `-betterC` too. +`unittest` blocks can be listed with the $(DDSUBLINK spec/traits, getUnitTests, `getUnitTests`) trait: + +--- +unittest +{ + assert(0); +} + +extern(C) void main() +{ + static foreach(u; __traits(getUnitTests, __traits(parent, main))) + u(); +} +--- + +$(CONSOLE +$(GT) dmd -betterC -unittest -run test.d +dmd_runpezoXK: foo.d:3: Assertion `0' failed. +) + +However, in `-betterC`, `assert` expressions don't use Druntime's assert and are directed to `assert` from the C runtime library instead. + +$(H2 $(LNAME2 consequences, Unavailable Features)) + + $(P D features not available with $(B BetterC):) + +$(OL + $(LI Garbage Collection) + $(LI TypeInfo and $(DDSUBLINK spec/abi, ModuleInfo, $(TT ModuleInfo))) + $(LI Classes) + $(LI Built-in threading (e.g. $(MREF core, thread))) + $(LI Dynamic arrays (though slices of static arrays and pointers work)) + $(LI Associative arrays) + $(LI Exceptions) + $(LI `synchronized` and $(MREF core, sync)) + $(LI Static module constructors or destructors) +) + + +$(SPEC_SUBNAV_PREV_NEXT simd, Vector Extensions, importc, ImportC) + +) + +Macros: + CHAPTER=41 + TITLE=Better C diff --git a/spec/class.dd b/spec/class.dd new file mode 100644 index 0000000000..183cd8936f --- /dev/null +++ b/spec/class.dd @@ -0,0 +1,1576 @@ +Ddoc + +$(SPEC_S Classes, + +$(HEADERNAV_TOC) + +$(H2 $(LNAME2 overview, Overview)) + + $(P The object-oriented features of D all come from classes. The class + hierarchy + has as its root the class Object. Object defines a minimum level of functionality + that each derived class has, and a default implementation for that functionality. + ) + + $(P Classes are programmer defined types. Support for classes are what + make D an object oriented language, giving it encapsulation, inheritance, + and polymorphism. D classes support the single inheritance paradigm, extended + by adding support for interfaces. Class objects are instantiated by reference + only. + ) + + $(P A class can be exported, which means its name and all its + non-private + members are exposed externally to the DLL or EXE. + ) + +$(H2 $(LNAME2 declaration, Class Declarations)) + + $(P A class declaration is defined: + ) + +$(GRAMMAR +$(GNAME ClassDeclaration): + $(D class) $(GLINK_LEX Identifier) $(D ;) + $(D class) $(GLINK_LEX Identifier) $(GLINK BaseClassList)$(OPT) $(GLINK2 struct, AggregateBody) + $(GLINK2 template, ClassTemplateDeclaration) + +$(GNAME BaseClassList): + $(D :) $(GLINK SuperClassOrInterface) + $(D :) $(GLINK SuperClassOrInterface) $(D ,) $(GLINK Interfaces) + +$(GNAME SuperClassOrInterface): + $(GLINK2 type, BasicType) + +$(GNAME Interfaces): + $(GLINK Interface) + $(GLINK Interface) $(D ,) $(GSELF Interfaces) + +$(GNAME Interface): + $(GLINK2 type, BasicType) +) + +$(P A class consists of:) + +$(COMMENT list of notable components, not exhaustive) +$(UL + $(LI a $(RELATIVE_LINK2 super_class, super class)) + $(LI $(DDLINK spec/interface, Interfaces, interfaces) + $(LI dynamic fields) + $(LI $(DDSUBLINK spec/attribute, static, static) fields) + $(LI $(RELATIVE_LINK2 nested, nested classes)) + $(LI $(RELATIVE_LINK2 member-functions, member functions)) + $(UL + $(LI static member functions) + $(LI $(DDSUBLINK spec/function, virtual-functions, Virtual Functions)) + $(LI $(RELATIVE_LINK2 constructors, Constructors)) + $(LI $(RELATIVE_LINK2 destructors, Destructors)) + $(LI $(RELATIVE_LINK2 invariants, Class Invariants)) + $(LI $(DDLINK spec/operatoroverloading, Operator Overloading, Operator Overloading)) + ) + $(LI other declarations (see $(GLINK2 module, DeclDef))) + ) +) + +$(P A class is defined:) + +------ +class Foo +{ + ... members ... +} +------ + +$(PANEL + $(NOTE Unlike C++, there is no trailing $(D ;) after the closing $(D }) of the class + definition. + It is also not possible to declare a variable `var` inline:) + +------ +class Foo { } var; +------ + + Instead, use: + +------ +class Foo { } +Foo var; +------ +) + +$(H3 $(LNAME2 access_control, Access Control)) + + $(P Access to class members is controlled using + $(DDSUBLINK spec/attribute, visibility_attributes, + visibility attributes). + The default visibility attribute is $(D public). + ) + + +$(H3 $(LNAME2 super_class, Super Class)) + + $(P + All classes inherit from a super class. If one is not specified, + a class inherits from $(REF1 Object, object). `Object` forms the root + of the D class inheritance hierarchy. + ) + +--- +class A { } // A inherits from Object +class B : A { } // B inherits from A +--- + + $(P Multiple class inheritance is not supported, however a class can inherit from + multiple $(DDLINK spec/interface, Interfaces, interfaces). + If a super class is declared, it must come before any interfaces. + Commas are used to separate inherited types.) + + +$(H3 $(LNAME2 fields, Fields)) + + $(P Class members are always accessed with the `.` operator. + ) + + $(P Members of a base class can be accessed by prepending the name of + the base class followed by a dot:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +class A { int a; int a2;} +class B : A { int a; } + +void foo(B b) +{ + b.a = 3; // accesses field B.a + b.a2 = 4; // accesses field A.a2 + b.A.a = 5; // accesses field A.a +} +--- +) + + $(IMPLEMENTATION_DEFINED + The D compiler is free to rearrange the order of fields in a class to + optimally pack them. + Consider the fields much like the local + variables in a function - + the compiler assigns some to registers and shuffles others around all to + get the optimal + stack frame layout. This frees the code designer to organize the fields + in a manner that + makes the code more readable rather than being forced to organize it + according to + machine optimization rules. Explicit control of field layout is provided + by struct/union + types, not classes. + ) + + $(P Fields of `extern(Objective-C)` classes have a dynamic offset. That + means that the base class can change (add or remove instance variables) + without the subclasses needing to recompile or relink. + ) + + +$(H2 $(LNAME2 class_properties, Class Properties)) + +$(TABLE2 Class Properties, +$(THEAD Property, Description) +$(TROW $(RELATIVE_LINK2 tupleof, `.tupleof`), + Symbol sequence of fields in the class.) +) + +$(TABLE2 Class Instance Properties, +$(THEAD Property, Description) +$(TROW $(DDSUBLINK spec/property, classinfo, $(D .classinfo)), + Information about the dynamic type of the class.) +$(TROW $(RELATIVE_LINK2 outer-property, `.outer`), $(ARGS For + a nested class instance, provides either the parent class instance, + or the parent function's context pointer when there is no parent + class.)) +) + +$(H3 $(LNAME2 tupleof, `.tupleof`)) + + $(P The $(D .tupleof) property provides a symbol sequence + of all the non-static fields in the class, excluding the initial + $(RELATIVE_LINK2 hidden-fields, hidden fields) and + the fields in the base class. + When used on an instance, `.tupleof` gives an + $(DDSUBLINK spec/template, lvalue-sequences, lvalue sequence).) + + $(P The order of the fields in the tuple matches the order in which the fields are declared.) + + $(NOTE `.tupleof` is not available for `extern(Objective-C)` classes due to + their fields having a dynamic offset. + ) +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +class Foo { int x; long y; } + +static assert(__traits(identifier, Foo.tupleof[0]) == "x"); +static assert(is(typeof(Foo.tupleof)[1] == long)); + +void main() +{ + import std.stdio; + + auto foo = new Foo; + foo.tupleof[0] = 1; // set foo.x to 1 + foo.tupleof[1] = 2; // set foo.y to 2 + foreach (ref x; foo.tupleof) + x++; + assert(foo.x == 2); + assert(foo.y == 3); + + auto bar = new Foo; + bar.tupleof = foo.tupleof; // copy fields + assert(bar.x == 2); + assert(bar.y == 3); +} +--- +) + +$(H3 $(LNAME2 hidden-fields, Accessing Hidden Fields)) + + $(P The properties $(D .__vptr) and $(D .__monitor) give access + to the class object's vtbl[] and monitor, respectively, but + should not be used in user code. + See $(DDSUBLINK spec/abi, classes, the ABI) for details. + ) + $(P See also: $(RELATIVE_LINK2 nested-context, Context Pointer).) + +$(H3 $(LNAME2 field_properties, Field Properties)) + + $(P The $(D .offsetof) property gives the offset in bytes of the field + from the beginning of the class instantiation. + Note that the compiler can $(RELATIVE_LINK2 fields, rearrange class field offsets). + See $(DDSUBLINK spec/attribute, align, the `align` attribute) for a struct-based + example. + ) + $(NOTE `.offsetof` is not available for fields of `extern(Objective-C)` classes + due to their fields having a dynamic offset. + ) + + +$(H2 $(LNAME2 member-functions, Member Functions (a.k.a. Methods))) + + $(P Non-static member functions must be called on an instance of their class. + They have an extra hidden parameter + called $(DDSUBLINK spec/expression, this, `this`) through which the class object's other members + can be accessed. + Inside the function body, the class instance members are in scope. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +class C +{ + int a; + + void foo() + { + a = 3; // assign to `this.a` + } +} + +auto c = new C; +c.foo(); +assert(c.a == 3); +--- +) + $(P Non-static member functions can have, in addition to the usual + $(GLINK2 function, FunctionAttribute)s, the attributes + $(D const), $(D immutable), $(D shared), $(D inout), $(D scope) or $(D return scope). + These attributes apply to the hidden $(I this) parameter. + ) +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +class C +{ + int a; + + void foo() const + { + a = 3; // error, 'this' is const + } + void foo() immutable + { + a = 3; // error, 'this' is immutable + } + C bar() @safe scope + { + return this; // error, 'this' is scope + } +} +--- +) + +$(H3 $(LNAME2 objc-member-functions, Objective-C linkage)) + + $(P Static member functions with + `Objective-C` linkage also have an extra hidden parameter called $(I this) + through which the class object's other members can be accessed. + ) + + $(P Member functions with Objective-C linkage have an additional + hidden, anonymous, parameter which is the selector the function was + called with. + ) + + $(P Static member functions with Objective-C linkage are placed in + a hidden nested metaclass as non-static member functions. + ) + + +$(H2 $(LNAME2 synchronized-methods, Synchronized Method Calls)) + + $(P Member functions of a (non-`synchronized`) class can be individually + marked as `synchronized`. + The class instance's monitor object will be locked when the method is + called and unlocked when the call terminates. + ) + + $(P A synchronized method can only be called on a + $(DDSUBLINK spec/const3, shared, `shared`) class instance.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +class C +{ + void foo(); + synchronized int bar(); +} + +void test(C c) +{ + c.foo; // OK + //c.bar; // Error, `c` is not `shared` + + shared C sc = new shared C; + //sc.foo; // Error, `foo` not callable using a `shared` object + sc.bar; // OK +} +--- +) + $(P See also $(GLINK2 statement, SynchronizedStatement).) + +$(H3 $(LNAME2 synchronized-classes, Synchronized Classes)) + + $(P Each member function of a `synchronized` class is implicitly `synchronized`. + A static member function is synchronized on the $(I classinfo) + object for the class, which means that one monitor is used + for all static member functions for that synchronized class. + For non-static functions of a synchronized class, the monitor + used is part of the class object. For example: + ) + + --- + synchronized class Foo + { + void bar() { ...statements... } + } + --- + + $(P is equivalent to (as far as the monitors go): + ) + + --- + synchronized class Foo + { + void bar() + { + synchronized (this) { ...statements... } + } + } + --- + $(NOTE `bar` uses a $(GLINK2 statement, SynchronizedStatement).) + + $(P Member fields of a synchronized class cannot be public: + ) + + --- + synchronized class Foo + { + int foo; // Error: public field + } + + synchronized class Bar + { + private int bar; // ok + } + --- + + $(NOTE struct types cannot be marked `synchronized`.) + + +$(H2 $(LNAME2 class-instantiation, Class Instantiation)) + + $(P Fields are by default initialized to the + $(DDSUBLINK spec/property, init, default initializer) + for their type (usually 0 for integer types and + NaN for floating point types). + If the field declaration has an optional $(GLINK2 declaration, Initializer) + that will be used instead of the default. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------ + class Abc + { + int a; // default initializer for a is 0 + long b = 7; // default initializer for b is 7 + float f; // default initializer for f is NAN + } + + void main() + { + Abc obj = new Abc; + assert(obj.b == 7); + } + ------ + ) + + $(P The $(I Initializer) is evaluated at compile time.) + + $(P This initialization is done before any + $(RELATIVE_LINK2 constructors, constructors) are called.) + + $(P Instances of class objects are created with a $(GLINK2 expression, NewExpression).) + + * A class `C` without a constructor (or with a nullary constructor) is instantiated + using `new C`, without passing any arguments. + * Otherwise, a class can be instantiated with an argument list, e.g. + `new C(arguments)`. The arguments are passed to a constructor with a matching + parameter list (and resolved like $(DDSUBLINK spec/function, function-overloading, + overloaded methods)). + + $(P By default, a class instance is allocated on the garbage-collected heap. + A $(DDSUBLINK spec/attribute, scope-class-var, `scope` class instance) + is allocated on the stack.) + + +$(H3 $(LNAME2 constructors, Constructors)) + + $(P A constructor is a special $(RELATIVE_LINK2 member-functions, member function) + which is normally $(RELATIVE_LINK2 instantiation-process, invoked by the compiler) + when the class instance is created.) + +$(GRAMMAR +$(GNAME Constructor): + $(D this) $(GLINK2 function, Parameters) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK2 function, FunctionBody) + $(D this) $(GLINK2 function, Parameters) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK2 function, MissingFunctionBody) + $(GLINK2 template, ConstructorTemplate) +) + + $(P A constructor is declared with a function name of $(D this) + and no return type:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------ + class A + { + int i; + + this() // constructor taking no arguments + { + i = 2; // initialize `this.i` + } + + this(int i) // constructor taking an int argument + { + this.i = i; // initialize field `i` from parameter `i` + } + } + + void main() + { + A a = new A; // instantiate A and call `A.this()` + assert(a.i == 2); + + a = new A(3); // instantiate A and call `A.this(3)` + assert(a.i == 3); + } + ------ + ) + $(P Explicitly returning a value in a constructor is not allowed, + however `return;` may be used to exit the function early.) + + +$(H3 $(LNAME2 base-construction, Base Class Construction)) + + $(P Base class construction is done by calling the base class + constructor by the name $(D super):) + + ------ + class A { this(int y) { } } + + class B : A + { + int j; + this() + { + ... + $(CODE_HIGHLIGHT super)(3); // call base constructor A.this(3) + ... + } + } + ------ + +$(H3 $(LNAME2 delegating-constructors, Delegating Constructors)) + + $(P A constructor can call another constructor for the same class + in order to share common initializations. + This is called a $(I delegating constructor): + ) + + ------ + class C + { + int j; + this() + { + ... + } + this(int i) + { + $(CODE_HIGHLIGHT this)(); // delegating constructor call + j = i; + } + } + ------ + +$(H3 $(LNAME2 ctor-restrictions, Restrictions)) + + $(P The following restrictions apply:) + + $(OL + $(LI It is illegal for constructors to mutually call each other. + + ------ + this() { this(1); } + this(int i) { this(); } // illegal, cyclic constructor calls + ------ + + $(IMPLEMENTATION_DEFINED The compiler is not required to detect + cyclic constructor calls.) + + $(UNDEFINED_BEHAVIOR If the program executes with cyclic constructor + calls.) + ) + + $(LI If a constructor's code contains a delegating/base constructor call, all + possible execution paths through the constructor must make exactly one + of those calls: + + ------ + this() { a || super(); } // illegal, 0 or 1 call + + this() { (a) ? this(1) : super(); } // OK + + this() { super(); this(1); } // illegal, 2 calls + + this() + { + for (...) + { + super(); // illegal, inside loop + } + } + ------ + ) + + $(LI It is illegal to refer to $(D this) implicitly or explicitly + prior to making a delegating/base constructor call.) + + $(LI Delegating/base constructor calls cannot appear after labels.) + ) + + $(P See also: $(RELATIVE_LINK2 field-init, field initialization).) + + +$(H3 $(LNAME2 implicit-base-construction, Implicit Base Class Construction)) + + $(P If there is no constructor for a class, but there is a constructor + for the base class, a default constructor is implicitly generated with + the form:) + + ------ + this() { } + ------ + + $(P If no calls to a delegating constructor or $(D super) appear in a + constructor, and the base class has a nullary constructor, a call to + `super()` is inserted at the beginning of the constructor. If that + base class has a constructor that requires arguments and no + nullary constructor, a matching call to `super` is required.) + +$(H3 $(LNAME2 instantiation-process, Instantiation Process)) + + $(P The following steps happen:) + + $(OL + $(LI Storage is allocated for the object. + If this fails, rather than return $(D null), an + $(LINK2 $(ROOT_DIR)library/core/exception/out_of_memory_error.html, OutOfMemoryError) is thrown. + Thus, tedious checks for null references are unnecessary. + ) + + $(LI The raw data is statically initialized using the values provided + in the class definition. + The pointer to the vtbl[] (the array of pointers to virtual functions) + is assigned. + Constructors are + passed fully formed objects for which virtual functions can be called. + This operation is equivalent to doing a memory copy of a static + version of the object onto the newly allocated one. + ) + + $(LI If there is a constructor defined for the class, + the constructor matching the + argument list is called. + ) + + $(LI If a delegating constructor is not called, a call to the base + class's default constructor is issued.) + + $(LI The body of the constructor is executed.) + + $(LI If class invariant checking is turned on, the + $(RELATIVE_LINK2 invariants, class invariant) is called at the end of the constructor. + ) + ) + +$(H3 $(LNAME2 constructor-attributes, Constructor Attributes)) + + $(P Constructors can have one of these member function attributes: + $(D const), $(D immutable), and $(D shared). Construction of qualified + objects will then be restricted to the implemented qualified constructors. + ) + ------ + class C + { + this(); // non-shared mutable constructor + } + + // create mutable object + C m = new C(); + + // create const object using mutable constructor + const C c2 = new const C(); + + // a mutable constructor cannot create an immutable object + // immutable C i = new immutable C(); + + // a mutable constructor cannot create a shared object + // shared C s = new shared C(); + ------ + + $(P Constructors can be overloaded with different attributes. + ) + ------ + class C + { + this(); // non-shared mutable constructor + this() shared; // shared mutable constructor + this() immutable; // immutable constructor + } + + C m = new C(); + shared s = new shared C(); + immutable i = new immutable C(); + ------ + +$(H4 $(LNAME2 pure-constructors, Pure Constructors)) + + $(P If the constructor can create a unique object (e.g. if it is `pure`), + the object can be implicitly convertible to any qualifiers. + ) + ------ + class C + { + this() pure; + // Based on the definition, this creates a mutable object. But the + // created object cannot contain any mutable global data. + // Therefore the created object is unique. + + this(int[] arr) immutable pure; + // Based on the definition, this creates an immutable object. But + // the argument int[] never appears in the created object so it + // isn't implicitly convertible to immutable. Also, it cannot store + // any immutable global data. + // Therefore the created object is unique. + } + + immutable i = new immutable C(); // this() pure is called + shared s = new shared C(); // this() pure is called + C m = new C([1,2,3]); // this(int[]) immutable pure is called + ------ + +$(H3 $(LNAME2 field-init, Field initialization inside a constructor)) + + $(P In a constructor body, the first instance of field assignment is + its initialization. + ) + + ------ + class C + { + int num; + this() + { + num = 1; // initialization + num = 2; // assignment + } + } + ------ + + $(P If the field type has an $(LINK2 operatoroverloading.html#assignment, `opAssign`) + method, it will not be used for initialization.) + + ------ + struct A + { + this(int n) {} + void $(CODE_HIGHLIGHT opAssign)(A rhs) {} + } + class C + { + A val; + this() + { + val = A(1); // val is initialized to the value of A(1) + val = A(2); // rewritten to val.opAssign(A(2)) + } + } + ------ + + $(P If the field type is not mutable, multiple initialization will be rejected.) + + ------ + class C + { + immutable int num; + this() + { + num = 1; // OK + num = 2; // Error: multiple field initialization + } + } + ------ + + $(P If the field is initialized on one path, it must be initialized on all paths.) + --- + class C + { + immutable int num; + immutable int ber; + this(int i) + { + if (i) + num = 3; // initialization + else + num = 4; // initialization + } + this(long j) + { + j ? (num = 3) : (num = 4); // ok + j || (ber = 3); // error, intialized on only one path + j && (ber = 3); // error, intialized on only one path + } + } + --- + + $(P A field initialization may not appear in a loop or after + a label.) + + ------ + class C + { + immutable int num; + immutable string str; + this() + { + foreach (i; 0..2) + { + num = 1; // Error: field initialization not allowed in loops + } + size_t i = 0; + Label: + str = "hello"; // Error: field initialization not allowed after labels + if (i++ < 2) + goto Label; + } + } + ------ + + $(P If a field's type has disabled default construction, then it must be initialized + in the constructor.) + --- + struct S { int y; @disable this(); } + + class C + { + S s; + this(S t) { s = t; } // ok + this(int i) { this(); } // ok + this() { } // error, s not initialized + } + --- + +$(H2 $(LNAME2 destructors, Destructors)) + +$(GRAMMAR +$(GNAME Destructor): + $(D ~ this ( )) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK2 function, FunctionBody) + $(D ~ this ( )) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK2 function, MissingFunctionBody) +) + + $(P The destructor function is called when:) + + * A live object is deleted by the garbage collector + * A live $(DDSUBLINK spec/attribute, scope-class-var, `scope` class instance) goes out of scope + * $(REF1 destroy, object) is called on the object + + $(P Example:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------ + import std.stdio; + + class Foo + { + ~this() // destructor for Foo + { + writeln("dtor"); + } + } + + void main() + { + auto foo = new Foo; + destroy(foo); + writeln("end"); + } + ------ + ) + + * Only one destructor can be declared per class, although + other destructors $(DDSUBLINK spec/template-mixin, destructors, can be mixed in). + * A destructor does not have any parameters or attributes. + * A destructor is always virtual. + + $(P The destructor is expected to release any non-GC resources held by the + object. + ) + + $(P The program can explicitly call the destructor of a live + object immediately with $(REF1 destroy, object). + The runtime marks the object so the destructor is never called twice. + ) + + $(P The destructor for the $(RELATIVE_LINK2 super_class, super class) automatically gets called when + the destructor ends. There is no way to call the super class destructor + explicitly. + ) + + $(IMPLEMENTATION_DEFINED The garbage collector is not guaranteed to run the destructor + for all unreferenced objects.) + + $(PANEL + $(DIVC spec-boxes, $(B Important:) The order in which the + garbage collector calls destructors for unreferenced objects + is not specified. + This means that + when the garbage collector calls a destructor for an object of a class + that has + members which are references to garbage collected objects, those + references may no longer be valid. This means that destructors + cannot reference sub objects.) + + $(NOTE This rule does not apply to a `scope` class instance or an object destructed + with `destroy`, as the destructor is not being run + during a garbage collection cycle, meaning all references are valid.) + ) + + $(P Objects referenced from the static data segment never get collected + by the GC. + ) + +$(H2 $(LNAME2 static-ctor-dtor, Static Constructors and Destructors)) + +$(H3 $(LNAME2 static-constructor, Static Constructors)) + +$(GRAMMAR +$(GNAME StaticConstructor): + $(D static this ( )) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK2 function, FunctionBody) + $(D static this ( )) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK2 function, MissingFunctionBody) +) + + $(P A static constructor is a function that performs initializations of + thread local data before the $(D main()) function gets control for the main + thread, and upon thread startup.) + + $(P Static constructors are used to initialize static class members with + values that cannot be computed at compile time.) + + $(PANEL + Static constructors in other languages are built implicitly by using + member + initializers that can't be computed at compile time. The trouble with + this stems from not + having good control over exactly when the code is executed, for example: + +------ +class Foo +{ + static int a = b + 1; + static int b = a * 2; +} +------ + + What values do `a` and `b` end up with, what order are the initializations + executed in, what + are the values of `a` and `b` before the initializations are run, is this a + compile error, or is this + a runtime error? Additional confusion comes from it not being obvious if + an initializer is + static or dynamic. + + $(P D makes this simple. All member initializations must be determinable by + the compiler at + compile time, hence there is no order-of-evaluation dependency for + member + initializations, and it is not possible to read a value that has not + been initialized. Dynamic + initialization is performed by a static constructor, defined with + a special syntax $(D static this()).) + +------ +class Foo +{ + static int a; // default initialized to 0 + static int b = 1; + static int c = b + a; // error, not a constant initializer + + $(CODE_HIGHLIGHT static this)() // static constructor + { + a = b + 1; // a is set to 2 + b = a * 2; // b is set to 4 + } +} +------ + ) + +$(P If $(D main()) or the thread returns normally, (does not throw an +exception), the static destructor is added to the list of functions to be called +on thread termination.) + +$(P Static constructors have empty parameter lists.) + + $(P + Static constructors within a module are executed in the lexical + order in which they appear. + All the static constructors for modules that are directly or + indirectly imported + are executed before the static constructors for the importer. + ) + + $(P + The $(D static) in the static constructor declaration is not + an attribute, it must appear immediately before the $(D this): + ) + +------ +class Foo +{ + static this() { ... } // a static constructor + static private this() { ... } // Error: not a static constructor + static + { + this() { ... } // not a static constructor + } + static: + this() { ... } // not a static constructor +} +------ + +$(H3 $(LNAME2 static-destructor, Static Destructors)) + +$(GRAMMAR +$(GNAME StaticDestructor): + $(D static ~ this ( )) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK2 function, FunctionBody) +) + + A static destructor is defined as a special static function with the + syntax $(D static ~this()). + +------ +class Foo +{ + static ~this() // static destructor + { + } +} +------ + + $(P + A static destructor gets called on thread termination, + but only if the static constructor + completed successfully. + Static destructors have empty parameter lists. + Static destructors get called in the reverse order that the static + constructors were called in. + ) + + $(P + The $(D static) in the static destructor declaration is not + an attribute, it must appear immediately before the $(D ~this): + ) + +------ +class Foo +{ + static ~this() { ... } // a static destructor + static private ~this() { ... } // Error: not a static destructor + static + { + ~this() { ... } // not a static destructor + } + static: + ~this() { ... } // not a static destructor +} +------ + +$(H3 $(LNAME2 shared_static_constructors, Shared Static Constructors)) + +$(GRAMMAR +$(GNAME SharedStaticConstructor): + $(D shared static this ( )) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK2 function, FunctionBody) + $(D shared static this ( )) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK2 function, MissingFunctionBody) +) + + $(P Shared static constructors are executed before any $(GLINK StaticConstructor)s, + and are intended for initializing any shared global data. + ) + +$(H3 $(LNAME2 shared_static_destructors, Shared Static Destructors)) + +$(GRAMMAR +$(GNAME SharedStaticDestructor): + $(D shared static ~ this ( )) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK2 function, FunctionBody) + $(D shared static ~ this ( )) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK2 function, MissingFunctionBody) +) + + $(P Shared static destructors are executed at program termination + in the reverse order that + $(GLINK SharedStaticConstructor)s were executed. + ) + + +$(H2 $(LNAME2 invariants, Class Invariants)) + +$(GRAMMAR +$(GNAME Invariant): + $(D invariant $(LPAREN) $(RPAREN)) $(GLINK2 statement, BlockStatement) + $(D invariant) $(GLINK2 statement, BlockStatement) + $(D invariant $(LPAREN)) $(GLINK2 expression, AssertArguments) $(D $(RPAREN) ;) +) + + $(P Class $(I Invariant)s specify the relationships among the members of a class instance. + Those relationships must hold for any interactions with the instance from its + public interface. + ) + + $(P The invariant is in the form of a $(D const) member function. The invariant is defined + to $(I hold) if all the $(GLINK2 expression, AssertExpression)s within the invariant that are executed + succeed. + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + class Date + { + this(int d, int h) + { + day = d; // days are 1..31 + hour = h; // hours are 0..23 + } + + invariant + { + assert(1 <= day && day <= 31); + assert(0 <= hour && hour < 24); + } + + private: + int day; + int hour; + } + --- + ) + + $(P Any class invariants for base classes are applied before the class invariant for the derived class.) + + $(P There may be multiple invariants in a class. They are applied in lexical order.) + + $(P Class $(I Invariant)s must hold at the exit of the class constructor (if any), and + at the entry of the class destructor (if any).) + + $(P Class $(I Invariant)s must hold + at the entry and exit of all public or exported non-static member functions. + The order of application of invariants is:) + $(OL + $(LI preconditions) + $(LI invariant) + $(LI function body) + $(LI invariant) + $(LI postconditions) + ) + + $(P If the invariant does not hold, then the program enters an invalid state.) + + $(IMPLEMENTATION_DEFINED + $(OL + $(LI Whether the class $(I Invariant) is executed at runtime or not. This is typically + controlled with a compiler switch.) + $(LI The behavior when the invariant does not hold is typically the same as + for when $(GLINK2 expression, AssertExpression)s fail.) + ) + ) + + $(UNDEFINED_BEHAVIOR happens if the invariant does not hold and execution continues.) + + $(P Public or exported non-static member functions cannot be called from within an invariant.) + + --- + class Foo + { + public void f() { } + private void g() { } + + invariant + { + f(); // error, cannot call public member function from invariant + g(); // ok, g() is not public + } + } + --- + + $(BEST_PRACTICE + $(OL + $(LI Do not indirectly call exported or public member functions within a class invariant, + as this can result in infinite recursion.) + $(LI Avoid reliance on side effects in the invariant. as the invariant may or may not + be executed.) + $(LI Avoid having mutable public fields of classes with invariants, + as then the invariant cannot verify the public interface.) + ) + ) + + +$(H2 $(LNAME2 auto, Scope Classes)) +$(NOTE Scope classes have been $(DDSUBLINK deprecate, scope as a type constraint, deprecated). See also +$(DDSUBLINK spec/attribute, scope-class-var, `scope` class instances).) + + $(P A scope class is a class with the $(D scope) attribute, as in:) + +------ +scope class Foo { ... } +------ + +$(P The scope characteristic is inherited, so any classes derived from a scope +class are also scope.) + + $(P A scope class reference can only appear as a function local variable. + It must be declared as being $(D scope):) + +------ +scope class Foo { ... } + +void func() +{ + Foo f; // error, reference to scope class must be scope + scope Foo g = new Foo(); // correct +} +------ + +$(P When a scope class reference goes out of scope, the destructor (if any) for +it is automatically called. This holds true even if the scope was exited via a +thrown exception.) + + +$(H2 $(LNAME2 abstract, Abstract Classes)) + +$(P + An abstract member function must be overridden by a derived class. + Only virtual member functions may be declared abstract; non-virtual + member functions and free-standing functions cannot be declared + abstract. +) + +$(P + A class is abstract if any of its virtual member functions + are declared abstract or if they are defined within an + abstract attribute. + Note that an abstract class may also contain non-virtual member functions. + Abstract classes cannot be instantiated directly. + They can only be instantiated as a base class of + another, non-abstract, class. +) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +class C +{ + abstract void f(); +} + +auto c = new C; // error, C is abstract + +class D : C {} + +auto d = new D; // error, D is abstract + +class E : C +{ + override void f() {} +} + +auto e = new E; // OK +--- +) + +$(P + Member functions declared as abstract can still have function + bodies. This is so that even though they must be overridden, + they can still provide $(SINGLEQUOTE base class functionality), + e.g. through $(DDSUBLINK spec/expression, super, $(D super.foo())) in a derived class. + Note that the class is still abstract and cannot be instantiated directly. +) + +$(P + A class can be declared abstract: +) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +abstract class A +{ + // ... +} + +auto a = new A; // error, A is abstract + +class B : A {} + +auto b = new B; // OK +--- +) + + +$(H2 $(LNAME2 final, Final Classes)) + + $(P Final classes cannot be subclassed:) + +--- +final class A { } +class B : A { } // error, class A is final +--- + + $(P Methods of a final class are always + $(DDSUBLINK spec/function, final, `final`).) + +$(H2 $(LNAME2 nested, Nested Classes)) + +$(P A $(I nested class) is a class that is declared inside the scope of a +function or another class. A nested class has access to the variables and other +symbols of the classes and functions it is nested inside:) + +------ +class Outer +{ + int m; + + class Inner + { + int foo() + { + return m; // Ok to access member of Outer + } + } +} +--- +--- +void func() +{ + int m; + + class Inner + { + int foo() + { + return m; // Ok to access local variable m of func() + } + } +} +------ + +$(H3 $(LNAME2 static-nested, Static Nested Classes)) + +$(P If a nested class has the $(D static) attribute, then it can not access +variables of the enclosing scope that are local to the stack or need a +`this` reference:) + +------ +class Outer +{ + int m; + static int n; + + static class Inner + { + int foo() + { + return m; // Error, Inner is static and m needs a this + return n; // Ok, n is static + } + } +} +--- +--- +void func() +{ + int m; + static int n; + + static class Inner + { + int foo() + { + return m; // Error, Inner is static and m is local to the stack + return n; // Ok, n is static + } + } +} +------ + +$(H3 $(LNAME2 nested-context, Context Pointer)) + +$(P Non-static nested classes work by containing an extra hidden member (called +the context pointer) that is the frame pointer of the enclosing function if it +is nested inside a function, or the $(D this) reference of the enclosing class's instance +if it is nested inside a class.) + + $(P When a non-static nested class is instantiated, the context pointer + is assigned before the class's constructor is called, therefore + the constructor has full access to the enclosing variables. + A non-static nested class can only be instantiated when the necessary + context pointer information is available:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +class Outer +{ + class Inner { } + + static class SInner { } +} + +void main() +{ + Outer o = new Outer; // Ok + //Outer.Inner oi = new Outer.Inner; // Error, no 'this' for Outer + Outer.SInner os = new Outer.SInner; // Ok +} +--- +) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +void main() +{ + class Nested { } + + Nested n = new Nested; // Ok + + static f() + { + //Nested sn = new Nested; // Error, no 'this' for Nested + } +} +------ +) + +$(H3 $(LNAME2 nested-explicit, Explicit Instantiation)) + + $(P A `this` reference can be supplied to the creation of an + inner class instance by prefixing it to the $(I NewExpression): + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +class Outer +{ + int a; + + class Inner + { + int foo() + { + return a; + } + } +} + +void main() +{ + Outer o = new Outer; + o.a = 3; + Outer.Inner oi = o.new Inner; + assert(oi.foo() == 3); +} +--------- +) + + $(P Here $(D o) supplies the `this` reference to the inner class + instance of $(D Outer). + ) + +$(H3 $(LNAME2 outer-property, `outer` Property)) + + $(P For a nested class instance, the $(D .outer) property provides + the $(D this) reference of the enclosing class's instance. + If there is no accessible parent class instance, the property + provides a $(D void*) to the enclosing function frame.) + +---- +class Outer +{ + class Inner1 + { + Outer getOuter() + { + return this.$(CODE_HIGHLIGHT outer); + } + } + + void foo() + { + Inner1 i = new Inner1; + assert(i.getOuter() is this); + } +} +--- +--- +class Outer +{ + void bar() + { + // x is referenced from nested scope, so + // bar makes a closure environment. + int x = 1; + + class Inner2 + { + Outer getOuter() + { + x = 2; + // The Inner2 instance has access to the function frame + // of bar as a static frame pointer, but .outer returns + // the enclosing Outer class instance property. + return this.$(CODE_HIGHLIGHT outer); + } + } + + Inner2 i = new Inner2; + assert(i.getOuter() is this); + } +} +--- +--- +class Outer +{ + // baz cannot access an instance of Outer + static void baz() + { + // make a closure environment + int x = 1; + + class Inner3 + { + void* getOuter() + { + x = 2; + // There's no accessible enclosing class instance, so the + // .outer property returns the function frame of baz. + return this.$(CODE_HIGHLIGHT outer); + } + } + + Inner3 i = new Inner3; + assert(i.getOuter() !is null); + } +} +---- + +$(H3 $(LNAME2 anonymous, Anonymous Nested Classes)) + + $(P An anonymous nested class is both defined and instantiated with + a $(I NewAnonClassExpression): + ) + +$(GRAMMAR +$(GNAME NewAnonClassExpression): + $(D new) $(GLINK2 expression, PlacementExpression)$(OPT) $(D class) $(GLINK ConstructorArgs)$(OPT) $(GLINK AnonBaseClassList)$(OPT) $(GLINK2 struct, AggregateBody) + +$(GNAME ConstructorArgs): + $(D $(LPAREN)) $(GLINK2 expression, NamedArgumentList)$(OPT) $(D $(RPAREN)) + +$(GNAME AnonBaseClassList): + $(GLINK SuperClassOrInterface) + $(GLINK SuperClassOrInterface) $(D ,) $(GLINK Interfaces) +) + +which is equivalent to: + +$(GRAMMAR_INFORMATIVE +$(D class) $(GLINK_LEX Identifier) $(D :) $(I AnonBaseClassList) $(I AggregateBody) +// ... +$(D new) $(I Identifier) $(I ConstructorArgs) +) + +where $(I Identifier) is the name generated for the anonymous nested class. + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +interface I +{ + void foo(); +} + +auto obj = new class I +{ + void foo() + { + writeln("foo"); + } +}; +obj.foo(); +--- +) + +$(SECTION2 $(LEGACY_LNAME2 ConstClass, const-class, $(ARGS Const, Immutable and Shared Classes)), + + $(P If a $(I ClassDeclaration) has a $(D const), $(D immutable) + or $(D shared) storage class, then it is as if each member of the class + was declared with that storage class. + If a base class is const, immutable or shared, then all classes derived + from it are also const, immutable or shared. + ) +) +$(SPEC_SUBNAV_PREV_NEXT struct, Structs and Unions, interface, Interfaces) +) + +Macros: + CHAPTER=16 + TITLE=Classes + _= diff --git a/spec/const3.dd b/spec/const3.dd new file mode 100644 index 0000000000..f7a85b1aa5 --- /dev/null +++ b/spec/const3.dd @@ -0,0 +1,798 @@ +Ddoc + +$(D_S Type Qualifiers, + +$(HEADERNAV_TOC) + + $(P Type qualifiers modify a type by applying a $(GLINK2 type, TypeCtor). + $(I TypeCtor)s are: $(D const), $(D immutable), $(D shared), and $(D inout). + Each applies transitively to all subtypes. + ) + +$(H2 $(LNAME2 const_and_immutable, Const and Immutable)) + + $(P When examining a data structure or interface, it is very + helpful to be able to easily tell which data can be expected to not + change, which data might change, and who may change that data. + This is done with the aid of the language typing system. + Data can be marked as const or immutable, with the default being + changeable (or $(I mutable)). + ) + + $(P $(D immutable) applies to data that cannot change. + Immutable data values, once constructed, remain the same for + the duration of the program's + execution. + Immutable data can be placed in ROM (Read Only Memory) or in + memory pages marked by the hardware as read only. + Since immutable data does not change, it enables many opportunities + for program optimization, and has applications in functional + style programming. + ) + + $(P $(D const) applies to data that cannot be changed by + the const reference to that data. It may, however, be changed + by another reference to that same data. + Const finds applications in passing data through interfaces + that promise not to modify them. + ) + + $(P Both immutable and const are $(I transitive), which means + that any data reachable through an immutable reference is also + immutable, and likewise for const. + ) + +$(H2 $(LNAME2 immutable_storage_class, Immutable Storage Class)) + + $(P + The simplest immutable declarations use it as a storage class. + It can be used to declare manifest constants. + ) + +--- +immutable int x = 3; // x is set to 3 +x = 4; // error, x is immutable +char[x] s; // s is an array of 3 chars +--- + + $(P The type can be inferred from the initializer: + ) +--- +immutable y = 4; // y is of type int +y = 5; // error, y is immutable +--- + + $(P If the initializer is not present, the immutable can + be initialized from the corresponding constructor: + ) + +--- +immutable int z; +void test() +{ + z = 3; // error, z is immutable +} +static this() +{ + z = 3; // ok, can set immutable that doesn't + // have static initializer +} +--- + $(P + The initializer for a non-local immutable declaration must be + evaluatable + at compile time: + ) + +--- +int foo(int f) { return f * 3; } +int i = 5; +immutable x = 3 * 4; // ok, 12 +immutable y = i + 1; // error, cannot evaluate at compile time +immutable z = foo(2) + 1; // ok, foo(2) can be evaluated at compile time, 7 +--- + + $(P The initializer for a non-static local immutable declaration + is evaluated at run time: + ) +--- +int foo(int f) +{ + immutable x = f + 1; // evaluated at run time + x = 3; // error, x is immutable +} +--- + + $(P + Because immutable is transitive, data referred to by an immutable is + also immutable: + ) + +--- +immutable char[] s = "foo"; +s[0] = 'a'; // error, s refers to immutable data +s = "bar"; // error, s is immutable +--- + + $(P Immutable declarations can appear as lvalues, i.e. they can + have their address taken, and occupy storage. + ) + +$(H2 $(LNAME2 const_storage_class, Const Storage Class)) + + $(P + A const declaration is exactly like an immutable declaration, + with the following differences: + ) + + $(UL + $(LI Any data referenced by the const declaration cannot be + changed from the const declaration, but it might be changed + by other references to the same data.) + + $(LI The type of a const declaration is itself const.) + ) + +$(COMMENT +$(TABLE + +$(TR $(TH $(NBSP)) $(TH AddrOf) $(TH CTFEInit) $(TH Static) $(TH Field) $(TH Stack) $(TH Ctor)) + +$(TR $(TD $(NBSP)) + $(TD Can the address be taken?) + $(TD Is compile time function evaluation done on the initializer?) + $(TD allocated as static data?) + $(TD allocated as a per-instance field?) + $(TD allocated on the stack?) + $(TD Can the variable be assigned to in a constructor?) +) + + +$(TR $(TH Global data)) + +$(TR $(TD1 const T x;) $(Y) $(N) $(Y) $(N) $(N) $(Y)) +$(TR $(TD1 const T x = 3;) $(N) $(Y) $(N) $(N) $(N) $(N)) +$(TR $(TD1 static const T x;) $(Y) $(N) $(Y) $(N) $(N) $(Y)) +$(TR $(TD1 static const T x = 3;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) + + +$(TR $(TH Class Members)) + +$(TR $(TD1 const T x;) $(Y) $(N) $(N) $(Y) $(N) $(Y)) +$(TR $(TD1 const T x = 3;) $(N) $(Y) $(N) $(N) $(N) $(N)) +$(TR $(TD1 static const T x;) $(Y) $(N) $(Y) $(N) $(N) $(Y)) +$(TR $(TD1 static const T x = 3;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) + + +$(TR $(TH Local Variables)) + +$(TR $(TD1 const T x;) $(Y) $(Y) $(N) $(N) $(Y) $(N)) +$(TR $(TD1 const T x = 3;) $(Y) $(N) $(N) $(N) $(Y) $(N)) +$(TR $(TD1 static const T x;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) +$(TR $(TD1 static const T x = 3;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) + +$(TR $(TH Function Parameters)) + +$(TR $(TD1 const T x;) $(Y) $(N) $(N) $(N) $(Y) $(N)) +) + + +$(P Notes:) + +$(OL +$(LI If CTFEInit is true, then the initializer can also be used for +constant folding.) +) + + +$(TABLE +<caption>Template Argument Deduced Type</caption> +$(TR $(TH $(NBSP)) $(TH mutable $(CODE T)) $(TH1 const(T)) $(TH1 immutable(T))) +$(TR $(TD1 foo(U)) $(TDE T) $(TDE T) $(TDE T)) +$(TR $(TD1 foo(U:U)) $(TDE T) $(TDE const(T)) $(TDE immutable(T))) +$(TR $(TD1 foo(U:const(U))) $(TDI T) $(TDE T) $(TDI T)) +$(TR $(TD1 foo(U:immutable(U))) $(NM) $(NM) $(TDE T)) +) + +$(P Where:) + +$(TABLE +$(TR $(TD $(GREEN green)) $(TD exact match)) +$(TR $(TD $(ORANGE orange)) $(TD implicit conversion)) +) +) + +$(H2 $(LNAME2 immutable_type, Immutable Type)) + + $(P + Data that will never change its value can be typed as immutable. + The immutable keyword can be used as a $(I type qualifier): + ) + +--- +immutable(char)[] s = "hello"; +--- + + $(P + The immutable applies to the type within the following parentheses. + So, while $(CODE s) can be assigned new values, + the contents of $(CODE s[]) cannot be: + ) + +--- +s[0] = 'b'; // error, s[] is immutable +s = null; // ok, s itself is not immutable +--- + + $(P + Immutability is transitive, meaning it applies to anything that + can be referenced from the immutable type: + ) + +--- +immutable(char*)** p = ...; +p = ...; // ok, p is not immutable +*p = ...; // ok, *p is not immutable +**p = ...; // error, **p is immutable +***p = ...; // error, ***p is immutable +--- + + $(P Immutable used as a storage class is equivalent to using + immutable as a type qualifier for the entire type of a + declaration:) + +--- +immutable int x = 3; // x is typed as immutable(int) +immutable(int) y = 3; // y is immutable +--- + + +$(H2 $(LNAME2 creating_immutable_data, Creating Immutable Data)) + + $(P + The first way is to use a literal that is already immutable, + such as string literals. String literals are always immutable. + ) + +--- +auto s = "hello"; // s is immutable(char)[5] +char[] p = "world"; // error, cannot implicitly convert immutable + // to mutable +--- + + $(P + The second way is to cast data to immutable. + When doing so, it is up to the programmer to ensure that any mutable + references to the same data are not used to modify the data after the + cast. + ) + +--- +char[] s = ['a']; +s[0] = 'b'; // ok +immutable(char)[] p = cast(immutable)s; // ok, if data is not mutated + // through s anymore +s[0] = 'c'; // undefined behavior +immutable(char)[] q = cast(immutable)s.dup; // always ok, unique reference + +char[][] s2 = [['a', 'b'], ['c', 'd']]; +immutable(char[][]) p2 = cast(immutable)s2.dup; // dangerous, only the first + // level of elements is unique +s2[0] = ['x', 'y']; // ok, doesn't affect p2 +s2[1][0] = 'z'; // undefined behavior +immutable(char[][]) q2 = [s2[0].dup, s2[1].dup]; // always ok, unique references +--- + + $(P + The $(CODE .idup) property is a convenient way to create an immutable + copy of an array: + ) + +--- +auto p = s.idup; +p[0] = ...; // error, p[] is immutable +--- + +$(H2 $(LNAME2 removing_with_cast, Removing Immutable or Const with a Cast)) + + $(P + An immutable or const type qualifier can be removed with a cast: + ) + +--- +immutable int* p = ...; +int* q = cast(int*)p; +--- + + $(P + This does not mean, however, that one can change the data: + ) + +--- +*q = 3; // allowed by compiler, but result is undefined behavior +--- + + $(P + The ability to cast away immutable-correctness is necessary in + some cases where the static typing is incorrect and not fixable, such + as when referencing code in a library one cannot change. + Casting is, as always, a blunt and effective instrument, and + when using it to cast away immutable-correctness, one must assume + the responsibility to ensure the immutability of the data, as + the compiler will no longer be able to statically do so. + ) + + $(UNDEFINED_BEHAVIOR + casting away a `const` qualifier and then mutating it, + even when the referenced data is mutable. This is so that + compilers and programmers can make assumptions based on `const` alone. For + example, here it may be assumed that $(D f) does not alter $(D x): + ) + +--- +void f(const int* a); +void main() +{ + int x = 1; + f(&x); + assert(x == 1); // guaranteed to hold +} +--- + +$(H2 $(LNAME2 immutable_member_functions, Immutable Member Functions)) + + $(P + Immutable member functions are guaranteed that the object + and anything referred to by the $(DDSUBLINK spec/expression, this, `this` reference) + is immutable. + They are declared as: + ) + +--- +struct S +{ + int x; + + void foo() immutable + { + x = 4; // error, x is immutable + this.x = 4; // error, x is immutable + } +} +--- + $(P Note that using $(D_KEYWORD immutable) on the left hand side of a method does not apply to the return type: + ) + +--- +struct S +{ + immutable int[] bar() // bar is still immutable, return type is not! + { + } +} +--- + $(P To make the return type $(D_KEYWORD immutable), surround it with parentheses: + ) + +--- +struct S +{ + immutable(int[]) bar() // bar is now mutable, return type is immutable. + { + } +} +--- + $(P To make both the return type and the method $(D_KEYWORD immutable), write: + ) +--- +struct S +{ + immutable(int[]) bar() immutable + { + } +} +--- + + +$(H2 $(LNAME2 const_type, Const Type)) + + $(P + Const types are like immutable types, except that const + forms a read-only $(I view) of data. Other aliases to that + same data may change it at any time. + ) + + +$(H2 $(LNAME2 const_member_functions, Const Member Functions)) + + $(P + Const member functions are functions that are not allowed to + change any part of the object through the member function's + $(DDSUBLINK spec/expression, this, `this` reference). + ) + + +$(H2 $(LNAME2 inout, Inout)) + + $(P Functions that differ only in whether the parameters are mutable, `const` or `immutable`, + and have corresponding mutable, `const` or `immutable` return types, can be combined + into one function using the $(D inout) type constructor. Consider the following + overload set: + ) + --- + int[] slice(int[] a, int x, int y) { return a[x .. y]; } + + const(int)[] slice(const(int)[] a, int x, int y) { return a[x .. y]; } + + immutable(int)[] slice(immutable(int)[] a, int x, int y) { return a[x .. y]; } + --- + + $(P The code generated by each of these functions is identical. + The $(D_KEYWORD inout) type constructor can combine them into one function:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + inout(int)[] slice(inout(int)[] a, int x, int y) { return a[x .. y]; } + --- + ) + + $(P The $(D_KEYWORD inout) keyword forms a wildcard that stands in for + mutable, `const`, `immutable`, `inout`, or `inout const`. + When calling the function, the `inout` state of the return type is changed to + match that of the argument type passed to the `inout` parameter. + ) + + $(P `inout` can also be used as a type constructor inside a function that has a + parameter declared with `inout`. The `inout` state of a type declared with + `inout` is changed to match that of the argument type passed to the `inout` + parameter: + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + inout(int)[] asymmetric(inout(int)[] input_data) + { + inout(int)[] r = input_data; + while (r.length > 1 && r[0] == r[$-1]) + r = r[1..$-1]; + return r; + } + --- + ) + + $(P Inout types can be implicitly converted to `const` or `inout const`, + but to nothing else. Other types cannot be implicitly converted to `inout`. + Casting to or from `inout` is not allowed in `@safe` functions. + ) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + void f(inout int* ptr) + { + const int* p = ptr; + int* q = ptr; // error + immutable int* r = ptr; // error + } + --- + ) + + $(H3 $(LNAME2 matching-an-inout-parameter, Matching an `inout` Parameter)) + + $(P A set of arguments to a function with `inout` parameters is considered + a match if any `inout` argument types match exactly, or:) + + $(OL + $(LI No argument types are composed of `inout` types.) + $(LI A mutable, `const` or `immutable` argument type can be matched against each + corresponding parameter `inout` type.) + ) + + $(P If such a match occurs, `inout` is considered the common qualifier of + the matched qualifiers. If more than two parameters exist, the common + qualifier calculation is recursively applied. + ) + + $(TABLE2 Common qualifier of the two type qualifiers, + $(TROW , $(I mutable), $(D const), $(D immutable), $(D inout), $(D inout const)) + $(TROW $(I mutable) $(LPAREN)= m$(RPAREN), m, c, c, c, c) + $(TROW $(D const) $(LPAREN)= c$(RPAREN), c, c, c, c, c) + $(TROW $(D immutable) $(LPAREN)= i$(RPAREN), c, c, i, wc, wc) + $(TROW $(D inout) $(LPAREN)= w$(RPAREN), c, c, wc, w, wc) + $(TROW $(D inout const) $(LPAREN)= wc$(RPAREN), c, c, wc, wc, wc) + ) + + $(P The `inout` in the return type is then rewritten to match the `inout` + qualifiers:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + int[] ma; + const(int)[] ca; + immutable(int)[] ia; + + inout(int)[] foo(inout(int)[] a) { return a; } + void test1() + { + // inout matches to mutable, so inout(int)[] is + // rewritten to int[] + int[] x = foo(ma); + + // inout matches to const, so inout(int)[] is + // rewritten to const(int)[] + const(int)[] y = foo(ca); + + // inout matches to immutable, so inout(int)[] is + // rewritten to immutable(int)[] + immutable(int)[] z = foo(ia); + } + + inout(const(int))[] bar(inout(int)[] a) { return a; } + void test2() + { + // inout matches to mutable, so inout(const(int))[] is + // rewritten to const(int)[] + const(int)[] x = bar(ma); + + // inout matches to const, so inout(const(int))[] is + // rewritten to const(int)[] + const(int)[] y = bar(ca); + + // inout matches to immutable, so inout(int)[] is + // rewritten to immutable(int)[] + immutable(int)[] z = bar(ia); + } + --- + ) + + $(P $(B Note:) Shared types cannot + be matched with `inout`. + ) + + +$(H2 $(LNAME2 shared, Shared)) + +$(P Mutable data that is meant to be shared among multiple threads should be +declared with the `shared` qualifier. This prevents unsynchronized +reading and writing to the data, which would otherwise cause data races. +The `shared` type attribute is transitive (like `const` and `immutable`). +) +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +shared int x; +shared(int)* p = &x; +//int* q = p; // error, q is not shared +--- +) +$(P For basic data types, reading and writing can normally be done with +atomic operations. Use $(MREF core, atomic) for portability: +) +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import core.atomic; + +shared int x; + +void fun() +{ + //x++; // error, use atomicOp instead + x.atomicOp!"+="(1); +} +--- +) +$(P $(RED Warning:) An individual read or write operation on shared +data is not an error yet by default. To detect these, use the +`-preview=nosharedaccess` compiler option. Normal initialization is +allowed without an error.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +import core.atomic; + +int y; +shared int x = y; // OK + +//x = 5; // write error with preview flag +x.atomicStore(5); // OK +//y = x; // read error with preview flag +y = x.atomicLoad(); // OK +assert(y == 5); +--- +) + +$(H3 $(LNAME2 shared_cast, Casting)) + +$(P When working with larger types, manual synchronization +can be used. To do that, `shared` can be cast away for the +duration while mutual exclusion has been established: +) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct T; +shared T* x; + +void fun() +{ + synchronized + { + T* p = cast(T*)x; + // operate on `*p` + } +} +--- +) + +$(P An unshared reference can be cast to shared only if the source data +will not be accessed for the lifetime of the cast result.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +class C {} + +@trusted shared(C) create() +{ + auto c = new C; + // work with c without it escaping + return cast(shared)c; // OK +} +--- +) + +$(H3 $(LNAME2 shared_global, Shared Global Variables)) + +$(P Global (or static) shared variables are stored in common storage which +is accessible across threads. Global mutable variables are stored in +thread-local storage by default.) + +$(P To declare global/static data to be implicitly shared across +multiple threads without any compiler checks, see $(DDSUBLINK +spec/attribute, gshared, `__gshared`). +) + + +$(H2 $(LNAME2 combining_qualifiers, Combining Qualifiers)) + +$(P More than one qualifier may apply to a type. The order of application is +irrelevant, for example given an unqualified type `T`, $(D const shared T) and +$(D shared const T) are the same type. For that reason, this document depicts +qualifier combinations without parentheses unless necessary and in alphabetic +order.) + +$(P Applying a qualifier to a type that already has that qualifier is legal but +has no effect, e.g. given an unqualified type `T`, $(D shared(const shared T)) +yields the type $(D const shared T).) + +$(PANEL Applying the `immutable` qualifier to any type (qualified or not) results in +$(D immutable T). Applying any qualifier to $(D immutable T) results in +`immutable T`. This makes `immutable` a fixed point of qualifier combinations and +makes types such as $(D const(immutable(shared T))) impossible to create. + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +alias SInt = shared int; +alias IInt = immutable int; +static assert(is(immutable(SInt) == IInt)); +static assert(is(shared(IInt) == IInt)); +--- +) +) + +$(P Assuming `T` is an unqualified type, the graph below illustrates how +qualifiers combine (combinations with `immutable` are omitted). For each node, +applying the qualifier labeling the edge leads to the resulting type.) + +$(COMMENT To generate images/qualifier-combinations.{svg,eps} refer to +images/qualifier-combinations.dot.) + +$(HTMLTAG3 center, , + <img id="conversions" alt="Qualifier combination rules" + src="https://github.com/$(STATIC%20images/qualifier-combinations.svg)"> +) +$(LATEX +{\centering +\includegraphics{images/qualifier-combinations.eps} +} +) + +$(H2 $(LNAME2 implicit_qualifier_conversions, Implicit Qualifier Conversions)) + +$(P Values that have no mutable indirections (including structs that don't +contain any field with mutable indirections) can be implicitly converted across +$(I mutable), $(D const), $(D immutable), $(D const shared), $(D inout) and +$(D inout shared).) + +$(P References to qualified objects can be implicitly converted according to the +following rules:) + +$(COMMENT To generate images/qualifier-conversions.{svg,eps} refer to +images/qualifier-conversions.dot.) + +$(HTMLTAG3 center, , + <img id="conversions" alt="Qualifier conversion rules" + src="https://github.com/$(STATIC%20images/qualifier-conversions.svg)"> +) +$(LATEX +{\centering +\includegraphics{images/qualifier-conversions.eps} +} +) + +$(P In the graph above, any directed path is a legal implicit conversion. No +other qualifier combinations than the ones shown is valid. If a directed path +exists between two sets of qualifiers, the types thus qualified are called +$(GLOSSARY qualifier-convertible). The same information is shown below in tabular +format:) + + $(TABLE_10 $(ARGS Implicit Conversion of Reference Types), + $(VERTROW from/to, $(I mutable), $(D const), $(D shared), $(D inout), $(D const shared), $(D const inout), $(D inout shared), $(D const inout shared), $(D immutable)), + $(TROW $(I mutable), $(YES), $(YES), $(NO), $(NO), $(NO), $(NO), $(NO), $(NO), $(NO) ) + $(TROW $(D const), $(NO), $(YES), $(NO), $(NO), $(NO), $(NO), $(NO), $(NO), $(NO) ) + $(TROW $(D shared), $(NO), $(NO), $(YES), $(NO), $(YES), $(NO), $(NO), $(NO), $(NO) ) + $(TROW $(D inout), $(NO), $(YES), $(NO), $(YES), $(NO), $(YES), $(NO), $(NO), $(NO) ) + $(TROW $(D const shared), $(NO), $(NO), $(NO), $(NO), $(YES), $(NO), $(NO), $(NO), $(NO) ) + $(TROW $(D const inout), $(NO), $(YES), $(NO), $(NO), $(NO), $(YES), $(NO), $(NO), $(NO) ) + $(TROW $(D inout shared), $(NO), $(NO), $(NO), $(NO), $(YES), $(NO), $(YES), $(YES), $(NO) ) + $(TROW $(D const inout shared), $(NO), $(NO), $(NO), $(NO), $(YES), $(NO), $(NO), $(YES), $(NO) ) + $(TROW $(D immutable), $(NO), $(YES), $(NO), $(NO), $(YES), $(YES), $(NO), $(YES), $(YES)) + ) + +$(H3 $(LNAME2 unique-expressions, Unique Expressions)) + + $(P If an implicit conversion is disallowed by the table, an $(GLINK2 expression, Expression) + may be implicitly converted as follows: + ) + $(UL + $(LI From mutable or shared to immutable if the expression + is unique and all expressions it transitively refers to are either unique or immutable. + ) + $(LI From mutable to shared if the expression + is unique and all expressions it transitively refers to are either unique, immutable, + or shared. + ) + $(LI From immutable to mutable if the expression is unique. + ) + $(LI From shared to mutable if the expression is unique. + ) + ) + + $(P A $(I Unique Expression) is one for which there are no other references to the + value of the expression and all expressions it transitively refers to are either + also unique or are immutable. For example:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +void main() +{ + immutable int** p = new int*(null); // ok, unique + + int x; + //immutable int** q = new int*(&x); // error, there may be other references to x + + immutable int y; + immutable int** r = new immutable(int)*(&y); // ok, y is immutable +} +--- +) + $(P See also: $(DDSUBLINK spec/function, pure-factory-functions, Pure Factory Functions).) + + $(P Otherwise, a $(GLINK2 expression, CastExpression) can be used to force a conversion + when an implicit version is disallowed, but this cannot be done in $(D @safe) code, + and the correctness of it must be verified by the user. + ) + +$(SPEC_SUBNAV_PREV_NEXT enum, Enums, function, Functions) +) + +Macros: + CHAPTER=19 + TH1=<th class="nobr">$(CODE $0)</th> + TD1=<td class="nobr">$(CODE $0)</td> + TDE=<td class="nobr">$(GREEN $(CODE $0))</td> + TDI=<td class="nobr">$(ORANGE $(CODE $0))</td> + NM=$(TD $(RED no match)) + Y=$(TD $(GREEN Yes)) + N=$(TD $(RED No)) + TITLE=Type Qualifiers + ERROR = $(RED $(B error)) + META_KEYWORDS=D Programming Language, const, immutable + META_DESCRIPTION=Comparison of const between the D programming language, C++, and C++0x diff --git a/spec/contracts.dd b/spec/contracts.dd new file mode 100644 index 0000000000..13798216bd --- /dev/null +++ b/spec/contracts.dd @@ -0,0 +1,55 @@ +Ddoc + +$(SPEC_S Contract Programming, + +$(HEADERNAV_TOC) + + $(P Contracts enable specifying conditions that must hold true + when the flow of runtime execution reaches the contract. + If a contract is not true, then the program is assumed to have entered + an undefined state.) + + $(RATIONALE + $(P Building contract support into the language provides:) + + $(OL + $(LI a consistent look and feel for the contracts) + $(LI tool support) + $(LI the implementation can generate better code using information gathered + from the contracts) + $(LI easier management and enforcement of contracts) + $(LI handling of contract inheritance) + ) + ) + +$(HTMLTAG3V img, src="https://github.com/$(ROOT_DIR)images/d4.gif" style="max-width:100%" alt="Contracts make D bug resistant" border="0") + +$(H2 $(LNAME2 assert_contracts, Assert Contract)) + + $(P See $(GLINK2 expression, AssertExpression).) + +$(H2 $(LNAME2 pre_post_contracts, Pre and Post Contracts)) + + $(P See:) + * $(DDSUBLINK spec/function, preconditions, $(D in) contracts). + * $(DDSUBLINK spec/function, postconditions, $(D out) contracts). + + +$(H2 $(LNAME2 Invariants, Invariants)) + + $(P See $(DDSUBLINK spec/struct, Invariant, Struct Invariants) and $(DDSUBLINK spec/class, invariants, Class Invariants).) + + +$(H2 $(LNAME2 references, References)) + + $(LIST + $(LINK2 https://web.archive.org/web/20080919174640/http://people.cs.uchicago.edu/~robby/contract-reading-list/, Contracts Reading List), + $(LINK2 http://jan.newmarch.name/java/contracts/paper-long.html, Adding Contracts to Java) + ) + +$(SPEC_SUBNAV_PREV_NEXT template-mixin, Template Mixins, version, Conditional Compilation) +) + +Macros: + CHAPTER=24 + TITLE=Contract Programming diff --git a/spec/cpp_interface.dd b/spec/cpp_interface.dd new file mode 100644 index 0000000000..65f472f4a5 --- /dev/null +++ b/spec/cpp_interface.dd @@ -0,0 +1,1244 @@ +Ddoc + +$(SPEC_S Interfacing to C++, + +$(HEADERNAV_TOC) + + $(P This document specifies how to interface with C++ directly.) + + $(P It is also possible to indirectly interface with C++ code, either + through a $(DDLINK spec/interfaceToC, Interfacing to C, C interface) or a + COM interface.) + +$(H2 $(LNAME2 general_idea, The General Idea)) + + $(P Being 100% compatible with C++ means more or less adding + a fully functional C++ compiler front end to D. + Anecdotal evidence suggests that writing such is a minimum + of a 10 man-year project, essentially making a D compiler + with such capability unimplementable. + Other languages looking to hook up to C++ face the same + problem, and the solutions have been: + ) + + $(OL + $(LI Support the COM interface (but that only works for Windows).) + $(LI Laboriously construct a C wrapper around + the C++ code.) + $(LI Use an automated tool such as SWIG to construct a + C wrapper.) + $(LI Reimplement the C++ code in the other language.) + $(LI Give up.) + ) + + $(P D takes a pragmatic approach that assumes a couple + modest accommodations can solve a significant chunk of + the problem: + ) + + $(UL + $(LI matching C++ name mangling conventions) + $(LI matching C++ function calling conventions) + $(LI matching C++ virtual function table layout for single inheritance) + ) + +$(H2 $(LNAME2 platform-compiler-support, Platform-Compiler Support)) + + * On Windows, prefer linking D code to MSVC compiled binaries. + * On Linux, linking to both GCC and Clang compiled binaries is supported. + * On MacOS, prefer linking to Clang compiled binaries. + +$(H2 $(LNAME2 global-functions, Global Functions)) + + $(P C++ global functions, including those in namespaces, can be declared + and called in D, or defined in D and called in C++.) + +$(H3 $(LNAME2 calling_cpp_global_from_d, Calling C++ Global Functions from D)) + + $(P Given a C++ function in a C++ source file:) + +$(CPPLISTING +#include $(LT)iostream$(GT) + +using namespace std; + +int foo(int i, int j, int k) +{ + cout << "i = " << i << endl; + cout << "j = " << j << endl; + cout << "k = " << k << endl; + + return 7; +} +) + + $(P In the corresponding D code, $(CODE foo) + is declared as having C++ linkage and function calling conventions: + ) + +------ +extern (C++) int foo(int i, int j, int k); +------ + + $(P and then it can be called within the D code:) + +------ +extern (C++) int foo(int i, int j, int k); + +void main() +{ + foo(1, 2, 3); +} +------ + + $(P Compiling the two files, the first with a C++ compiler, + the second with a D compiler, linking them together, + and then running it yields:) + +$(CONSOLE +$(GT) g++ -c foo.cpp +$(GT) dmd bar.d foo.o -L-lstdc++ && ./bar +i = 1 +j = 2 +k = 3 +) + + $(P There are several things going on here:) + + $(UL + $(LI D understands how C++ function names are "mangled" and the + correct C++ function call/return sequence.) + + $(LI Because modules are not part of C++, each function with C++ linkage + in the global namespace must be globally unique within the program.) + + $(LI There are no $(D __cdecl), $(D __far), $(D __stdcall), $(D __declspec), or other + such nonstandard C++ extensions in D.) + + $(LI There are no volatile type modifiers in D.) + + $(LI Strings are not 0 terminated in D. See "Data Type Compatibility" + for more information about this. However, string literals in D are + 0 terminated.) + + ) + +$(H3 $(LNAME2 calling_global_d_functions_from_cpp, Calling Global D Functions From C++)) + + $(P To make a D function accessible from C++, give it + C++ linkage:) + +--- +import std.stdio; + +extern (C++) int foo(int i, int j, int k) +{ + writefln("i = %s", i); + writefln("j = %s", j); + writefln("k = %s", k); + return 1; +} + +extern (C++) void bar(); + +void main() +{ + bar(); +} +--- + + $(P The C++ end looks like:) + +$(CPPLISTING +int foo(int i, int j, int k); + +void bar() +{ + foo(6, 7, 8); +} +) + + $(P Compiling, linking, and running produces the output:) + +$(CONSOLE +$(GT) dmd -c foo.d +$(GT) g++ bar.cpp foo.o -lphobos2 -pthread -o bar && ./bar +i = 6 +j = 7 +k = 8 +) + +$(H2 $(LNAME2 cpp-namespaces, C++ Namespaces)) + + $(P C++ symbols that reside in namespaces can be + accessed from D. A $(LINK2 attribute.html#namespace, namespace) + can be added to the `extern (C++)` + $(LINK2 attribute.html#linkage, LinkageAttribute): + ) +------ +extern (C++, N) int foo(int i, int j, int k); + +void main() +{ + N.foo(1, 2, 3); // foo is in C++ namespace 'N' +} +------ + + $(P C++ can open the same namespace in the same file and multiple files. + In D, this can be done as follows:) + +--- +module ns; +extern (C++, `ns`) +{ + int foo() { return 1; } +} +--- + $(P Any expression that resolves to either a tuple of strings or an empty tuple is accepted. + When the expression resolves to an empty tuple, it is equivalent to `extern (C++)`) +--- +extern(C++, (expression)) +{ + int bar() { return 2; } +} +--- + +$(P or in multiple files, by organizing them in a package consisting of several modules:) +--- +ns/ +|-- a.d +|-- b.d +|-- package.d +--- + +$(P File `ns/a.d`:) +--- +module a; extern (C++, `ns`) { int foo() { return 1; } } +--- + +$(P File `ns/b.d`:) +--- +module b; extern (C++, `ns`) { int bar() { return 2; } } +--- + +$(P File `ns/package.d`:) +--- +module ns; +public import a, b; +--- +$(P Then import the package containing the extern C++ declarations as follows:) + +--- +import ns; +static assert(foo() == 1 && bar() == 2); +--- + +$(P Note that the `extern (C++, `ns`)` linkage attribute affects only the ABI (name mangling and calling convention) of + these declarations. Importing them follows the usual + $(LINK2 spec/module.html, D module import semantics).) + +$(P Alternatively, the non-string form can be used to introduce a scope. Note that the + enclosing module already provides a scope for the symbols declared in the namespace. + This form does not allow closing and reopening the same namespace with in the same module. That is:) +--- +module a; extern (C++, ns1) { int foo() { return 1; } } +--- +--- +module b; extern (C++, ns1) { int bar() { return 2; } } +--- +--- +import a, b; +static assert(foo() == 1 && bar() == 2); +--- + $(P works, but:) +--- +extern (C++, ns1) { int foo() { return 1; } } +extern (C++, ns1) { int bar() { return 2; } } +--- + $(P does not. Additionally, aliases can be used to avoid collision of symbols:) +--- +module a; extern (C++, ns) { int foo() { return 1; } } +--- +--- +module b; extern (C++, ns) { int bar() { return 2; } } +--- +--- +module ns; +import a, b; +alias foo = a.ns.foo; +alias bar = b.ns.bar; +--- +--- +import ns; +static assert(foo() == 1 && bar() == 2); +--- + +$(H2 $(LNAME2 classes, Classes)) + + $(P C++ classes can be declared in D by using the $(CODE extern (C++)) + attribute on $(CODE class), $(CODE struct) and $(CODE interface) + declarations. $(CODE extern (C++)) interfaces have the same restrictions as + D interfaces, which means that Multiple Inheritance is supported to the + extent that only one base class can have member fields.) + + $(P $(CODE extern (C++)) structs do not support virtual functions but can + be used to map C++ value types.) + + $(P Unlike classes and interfaces with D linkage, $(CODE extern (C++)) + classes and interfaces are not rooted in $(CODE Object) and cannot be used + with $(CODE typeid).) + + $(P D structs and classes have different semantics whereas C++ structs and + classes are basically the same. The use of a D struct or class depends on + the C++ implementation and not on the used C++ keyword.) + + $(UL + $(LI If the C++ implementation has one or more $(CODE virtual) member + functions (including inherited member functions), it should be declared as + an $(CODE extern(C++) class) in D.) + + $(LI If the C++ implementation does not have any $(CODE virtual) member + functions (including inherited member functions), it should be declared as + an $(CODE extern(C++) struct) in D.) + ) + + $(P When mapping a D $(CODE class) onto a C++ $(CODE struct), + use $(CODE extern(C++, struct)) to avoid linking problems with C++ compilers + (notably MSVC) that distinguish between C++'s $(CODE class) and $(CODE struct) + when mangling. Conversely, use $(CODE extern(C++, class)) to map a D + $(CODE struct) onto a C++ $(CODE class).) + + $(P $(CODE extern(C++, class)) and $(CODE extern(C++, struct)) can be combined + with C++ namespaces:) +--- +extern (C++, struct) extern (C++, foo) +class Bar +{ +} +--- + +$(H3 $(LNAME2 using_cpp_classes_from_d, Using C++ Classes From D)) + + $(P The following example shows binding of a pure virtual function, its + implementation in a derived class, a non-virtual member function, and a + member field:) + +$(CPPLISTING +#include $(LT)iostream$(GT) + +using namespace std; + +class Base +{ + public: + virtual void print3i(int a, int b, int c) = 0; +}; + +class Derived : public Base +{ + public: + int field; + Derived(int field) : field(field) {} + + void print3i(int a, int b, int c) + { + cout << "a = " << a << endl; + cout << "b = " << b << endl; + cout << "c = " << c << endl; + } + + int mul(int factor); +}; + +int Derived::mul(int factor) +{ + return field * factor; +} + +Derived *createInstance(int i) +{ + return new Derived(i); +} + +void deleteInstance(Derived *&d) +{ + delete d; + d = 0; +} +) + + $(P We can use it in D code like:) + +--- +extern(C++) +{ + abstract class Base + { + void print3i(int a, int b, int c); + } + + class Derived : Base + { + int field; + @disable this(); + override void print3i(int a, int b, int c); + final int mul(int factor); + } + + Derived createInstance(int i); + void deleteInstance(ref Derived d); +} + +void main() +{ + import std.stdio; + + auto d1 = createInstance(5); + writeln(d1.field); + writeln(d1.mul(4)); + + Base b1 = d1; + b1.print3i(1, 2, 3); + + deleteInstance(d1); + assert(d1 is null); + + auto d2 = createInstance(42); + writeln(d2.field); + + deleteInstance(d2); + assert(d2 is null); +} +--- + +$(P Compiling, linking, and running produces the output:) + +$(CONSOLE +$(GT) g++ base.cpp +$(GT) dmd main.d base.o -L-lstdc++ && ./main +5 +20 +a = 1 +b = 2 +c = 3 +42 +) + +$(P Note how in the above example, the constructor is not bindable and is +instead disabled on the D side; an alternative would be to reimplement the +constructor in D. See the $(DDSUBLINK spec/cpp_interface, lifetime-management, +section below on lifetime management) for more information.) + +$(H3 $(LNAME2 using_d_classes_from_cpp, Using D Classes From C++)) + + $(P Given D code like:) + +--- +extern (C++) int callE(E); + +extern (C++) interface E +{ + int bar(int i, int j, int k); +} + +class F : E +{ + extern (C++) int bar(int i, int j, int k) + { + import std.stdio : writefln; + writefln("i = %s", i); + writefln("j = %s", j); + writefln("k = %s", k); + return 8; + } +} + +void main() +{ + F f = new F(); + callE(f); +} +--- + + $(P The C++ code to access it looks like:) + +$(CPPLISTING +class E +{ + public: + virtual int bar(int i, int j, int k); +}; + + +int callE(E *e) +{ + return e->bar(11, 12, 13); +} +) + +$(CONSOLE +$(GT) dmd -c base.d +$(GT) g++ klass.cpp base.o -lphobos2 -pthread -o klass && ./klass +i = 11 +j = 12 +k = 13 +) + + +$(H2 $(LNAME2 structs, Structs)) + + $(P C++ allows a struct to inherit from a base struct. This is done in D using + `alias this`:) + +--- +struct Base { ... members ... }; + +struct Derived +{ + Base base; // make it the first field + alias base this; + + ... members ... +} +--- + + $(P In both C++ and D, if a struct has zero fields, the struct still has a + size of 1 byte. But, in C++ if the struct with zero fields is used as a base + struct, its size is zero (called the + $(LINK2 https://en.cppreference.com/w/cpp/language/ebo, Empty Base Optimization)). + There are two methods for emulating this behavior in D. + The first forwards references to a function returning a faked reference to the base:) + +--- +struct Base { ... members ... }; + +struct DerivedStruct +{ + static if (Base.tupleof.length > 0) + Base base; + else + ref inout(Base) base() inout + { + return *cast(inout(Base)*)&this; + } + alias base this; + + ... members ... +} +--- + + $(P The second makes use of template mixins:) + +--- +mixin template BaseMembers() +{ + void memberFunction() { ... } +} + +struct Base +{ + mixin BaseMembers!(); +} + +struct Derived +{ + mixin BaseMembers!(); + + ... members ... +} +--- + + $(P Note that the template mixin is evaluated in the context of its + instantiation, not declaration. If this is a problem, the template mixin + can use local imports, or have the member functions forward to the + actual functions.) + + +$(H2 $(LNAME2 cpp-templates, C++ Templates)) + + $(P C++ function and type templates can be bound by using the + $(CODE extern (C++)) attribute on a function or type template declaration.) + + $(P Note that all instantiations used in D code must be provided by linking + to C++ object code or shared libraries containing the instantiations.) + + $(P For example:) + +$(CPPLISTING +#include $(LT)iostream$(GT) + +template$(LT)class T$(GT) +struct Foo +{ + private: + T field; + + public: + Foo(T t) : field(t) {} + T get(); + void set(T t); +}; + +template$(LT)class T$(GT) +T Foo$(LT)T$(GT)::get() +{ + return field; +} + +template$(LT)class T$(GT) +void Foo$(LT)T$(GT)::set(T t) +{ + field = t; +} + +Foo$(LT)int$(GT) makeIntFoo(int i) +{ + return Foo$(LT)int$(GT)(i); +} + +Foo$(LT)char$(GT) makeCharFoo(char c) +{ + return Foo$(LT)char$(GT)(c); +} + +template$(LT)class T$(GT) +void increment(Foo$(LT)T$(GT) &foo) +{ + foo.set(foo.get() + 1); +} + +template$(LT)class T$(GT) +void printThreeNext(Foo$(LT)T$(GT) foo) +{ + for(size_t i = 0; i $(LT) 3; ++i) + { + std::cout $(LT)$(LT) foo.get() $(LT)$(LT) std::endl; + increment(foo); + } +} + +// The following two functions ensure that the required instantiations of +// printThreeNext are provided by this code module +void printThreeNexti(Foo$(LT)int$(GT) foo) +{ + printThreeNext(foo); +} + +void printThreeNextc(Foo$(LT)char$(GT) foo) +{ + printThreeNext(foo); +} +) + +--- +extern(C++): +struct Foo(T) +{ + private: + T field; + + public: + @disable this(); + T get(); + void set(T t); +} + +Foo!int makeIntFoo(int i); +Foo!char makeCharFoo(char c); +void increment(T)(ref Foo!T foo); +void printThreeNext(T)(Foo!T foo); + +extern(D) void main() +{ + auto i = makeIntFoo(42); + assert(i.get() == 42); + i.set(1); + increment(i); + assert(i.get() == 2); + + auto c = makeCharFoo('a'); + increment(c); + assert(c.get() == 'b'); + + c.set('A'); + printThreeNext(c); +} +--- + +$(P Compiling, linking, and running produces the output:) + +$(CONSOLE +$(GT) g++ -c template.cpp +$(GT) dmd main.d template.o -L-lstdc++ && ./main +A +B +C +) + +$(H2 $(LNAME2 function-overloading, Function Overloading)) + + $(P C++ and D follow different rules for function overloading. + D source code, even when calling $(CODE extern (C++)) functions, + will still follow D overloading rules. + ) + +$(H2 $(LNAME2 memory-allocation, Memory Allocation)) + + $(P C++ code explicitly manages memory with calls to + $(CODE ::operator new()) and $(CODE ::operator delete()). + D's $(CODE new) operator allocates memory using the D garbage collector, + so no explicit delete is necessary. D's $(CODE new) operator is not + compatible with C++'s $(CODE ::operator new) and $(CODE::operator delete). + Attempting to allocate memory with D's $(CODE new) and deallocate with + C++ $(CODE ::operator delete) will result in miserable failure. + ) + + $(P D can explicitly manage memory using a variety of library tools, such as + with $(MREF std, experimental, allocator). Additionally, + $(CODE core.stdc.stdlib.malloc) and $(CODE core.stdc.stdlib.free) can be + used directly for connecting to C++ functions that expect $(CODE malloc)'d + buffers. + ) + + $(P If pointers to memory allocated on the D garbage collector heap are + passed to C++ functions, it's critical to ensure that the referenced memory + will not be collected by the D garbage collector before the C++ function is + done with it. This is accomplished by: + ) + + $(UL + + $(LI Making a copy of the data using + $(MREF std, experimental, allocator) or $(CODE core.stdc.stdlib.malloc) + and passing the copy instead.) + + $(LI Leaving a pointer to it on the stack (as a parameter or + automatic variable), as the garbage collector will scan the stack.) + + $(LI Leaving a pointer to it in the static data segment, as the + garbage collector will scan the static data segment.) + + $(LI Registering the pointer with the garbage collector using the + $(CODE core.memory.GC.addRoot) or $(CODE core.memory.GC.addRange) + functions.) + + ) + + $(P An interior pointer to the allocated memory block is sufficient to let + the GC know the object is in use; i.e. it is not necessary to maintain + a pointer to the $(I beginning) of the allocated memory. + ) + + $(P The garbage collector does not scan the stacks of threads not + registered with the D runtime, nor does it scan the data segments of + shared libraries that aren't registered with the D runtime. + ) + +$(H2 $(LNAME2 data-type-compatibility, Data Type Compatibility)) + + $(TABLE2 D And C++ Type Equivalence, + + $(THEAD D type, C++ type) + + $(TROW + $(ARGS $(B void)), + $(ARGS $(B void)) + ) + + $(TROW + $(ARGS $(B byte)), + $(ARGS $(B signed char)) + ) + + $(TROW + $(ARGS $(B ubyte)), + $(ARGS $(B unsigned char)) + ) + + $(TROW + $(ARGS $(B char)), + $(ARGS $(B char) (chars are unsigned in D)) + ) + + $(TROW + $(ARGS $(D core.stdc.stddef.wchar_t)), + $(ARGS $(D wchar_t)) + ) + + $(TROW + $(ARGS $(B short)), + $(ARGS $(B short)) + ) + + $(TROW + $(ARGS $(B ushort)), + $(ARGS $(B unsigned short)) + ) + + $(TROW + $(ARGS $(B int)), + $(ARGS $(B int)) + ) + + $(TROW + $(ARGS $(B uint)), + $(ARGS $(B unsigned)) + ) + + $(TROW + $(ARGS $(B long)), + $(ARGS $(B long) if it is 64 bits wide, otherwise $(B long long)) + ) + + $(TROW + $(ARGS $(B ulong)), + $(ARGS $(B unsigned long) if it is 64 bits wide, otherwise $(B unsigned long long)) + ) + + $(TROW + $(ARGS $(D core.stdc.config.cpp_long)), + $(ARGS $(B long)) + ) + + $(TROW + $(ARGS $(D core.stdc.config.cpp_ulong)), + $(ARGS $(B unsigned long)) + ) + + $(TROW + $(ARGS $(B float)), + $(ARGS $(B float)) + ) + + $(TROW + $(ARGS $(B double)), + $(ARGS $(B double)) + ) + + $(TROW + $(ARGS $(B real)), + $(ARGS $(B long double)) + ) + + $(TROW + $(ARGS $(CODE extern (C++)) $(B struct)), + $(ARGS $(B struct) or $(B class) without virtual member functions) + ) + + $(TROW + $(ARGS $(CODE extern (C++)) $(B class)), + $(ARGS $(B struct) or $(B class) with virtual member functions) + ) + + $(TROW + $(ARGS $(CODE extern (C++)) $(B interface)), + $(ARGS $(B struct) or $(B class) with no member fields) + ) + + $(TROW + $(ARGS $(B union)), + $(ARGS $(B union)) + ) + + $(TROW + $(ARGS $(B enum)), + $(ARGS $(B enum)) + ) + + $(TROW + $(ARGS $(I type)$(B *)), + $(ARGS $(I type) $(B *)) + ) + + $(TROW + $(ARGS $(B ref) $(I type) (in parameter lists only)), + $(ARGS $(I type) $(CODE_AMP)) + ) + + $(TROW + $(ARGS $(I type)$(B [)$(I dim)$(B ])), + $(ARGS $(I type)$(B [)$(I dim)$(B ]) for a variable/field declaration, + or $(DDSUBLINK spec/interfaceToC, passing_d_array, use `ref` for function parameter)) + ) + + $(TROW + $(ARGS $(I type)$(B [)$(I dim)$(B ]*)), + $(ARGS $(I type)$(B (*)[)$(I dim)$(B ])) + ) + + $(TROW + $(ARGS $(I type)$(B [])), + $(ARGS no `extern (C++)` equivalent, $(RELATIVE_LINK2 dynamic-arrays, see below)) + ) + + $(TROW + $(ARGS $(I type)$(B [)$(I type)$(B ])), + $(ARGS no equivalent) + ) + + $(TROW + $(ARGS $(I type) $(B function)$(B $(LPAREN))$(I parameters)$(B $(RPAREN))), + $(ARGS $(I type)$(B (*))$(B $(LPAREN))$(I parameters)$(B $(RPAREN))) + ) + + $(TROW + $(ARGS $(I type) $(B delegate)$(B $(LPAREN))$(I parameters)$(B $(RPAREN))), + $(ARGS no equivalent) + ) + ) + + $(P These equivalents hold when the D and C++ compilers used are companions + on the host platform.) + +$(H3 $(LNAME2 dynamic-arrays, Dynamic Arrays)) + + $(P These are not supported for `extern (C++)`. For `extern (C)`, they + are equivalent to a struct template. For example:) + +--- +extern (C) const(char)[] slice; +--- + + $(P `dmd -HC` generates the following C++ declaration:) + +``` +extern "C" _d_dynamicArray< const char > slice; +``` + $(P `_d_dynamicArray` is generated as follows:) + +``` +/// Represents a D [] array +template<typename T> +struct _d_dynamicArray final +{ + size_t length; + T *ptr; + + _d_dynamicArray() : length(0), ptr(NULL) { } + + _d_dynamicArray(size_t length_in, T *ptr_in) + : length(length_in), ptr(ptr_in) { } + + T& operator[](const size_t idx) { + assert(idx < length); + return ptr[idx]; + } + + const T& operator[](const size_t idx) const { + assert(idx < length); + return ptr[idx]; + } +}; +``` + + +$(H2 $(LNAME2 packing-and-alignment, Packing and Alignment)) + + $(P D structs and unions are analogous to C's. + ) + + $(P C code often adjusts the alignment and packing of struct members + with a command line switch or with various implementation specific + $(HASH)pragmas. D supports explicit alignment attributes that correspond + to the C compiler's rules. Check what alignment the C code is using, + and explicitly set it for the D struct declaration. + ) + + $(P D supports bitfields in the standard library: see + $(REF bitfields, std, bitmanip). + ) + +$(H2 $(LNAME2 lifetime-management, Lifetime Management)) + + $(P C++ constructors, copy constructors, move constructors and destructors + cannot be called directly in D code, and D constructors, postblit operators + and destructors cannot be directly exported to C++ code. Interoperation of + types with these special operators is possible by either 1$(RPAREN) + disabling the operator in the client language and only using it in the host + language, or 2$(RPAREN) faithfully reimplementing the operator in the + client language. With the latter approach, care needs to be taken to ensure + observable semantics remain the same with both implementations, which can be + difficult, or in some edge cases impossible, due to differences in how the + operators work in the two languages. For example, in D all objects are + movable and there is no move constructor.) + +$(H2 $(LNAME2 operator-overloading, Operator Overloading)) + $(P D's operator overloading is primarily involved with overloading its unary + and binary operators including the increment, index, slice, cast, function call, + comparison operator etc. Overloads of these operators that exist in C++ can be + directly called from D provided the D operator and its C++ counterpart semantically agree. + Below is a simple use case involving the assignment, index, and function call operator + overloads interoperating between D and C++. + ) + + $(P In a foo.cpp file: ) + +$(CPPLISTING +#include $(LT)iostream$(GT) + +class A +{ +public: + int a; + int b; + int buffer[3]; + A() + { + a = 0; + b = 0; + } + A(int a, int b); + A& operator=(const A& obj); //overloading the assignment operator + void operator()(int a, int b, int c); // overloading the call operator + int& operator[](int value); // overloading the index operator + void printbuffer(); +}; + +A::A(int a, int b) +{ + this->a = a; + this->b = b; +} + +A& A::operator=(const A& obj) +{ + a = obj.a; + b = obj.b; + return *this; +} + +void A::operator()(int a, int b, int c) +{ + std::cout << "value of a is "<< a << std::endl; + std::cout << "value of b is "<< b << std::endl; + std::cout << "value of c is "<< c << std::endl; +} + +int& A::operator[](int value) +{ + return buffer[value]; +} + +void A::printbuffer() +{ + for (int i = 0; i < 3; i++) + { + std::cout << "the buffer numbers of index "<< i << " is "<< buffer[i] << std:: endl; + } +} +) + + $(P In a bar.d file: ) + +------ +import std.stdio; + +extern(C++) struct A +{ + int a; + int b; + int[3] buffer; + this(int a, int b); + ref A opAssign(ref const A); // links with A::operator= + void opCall(int a, int b, int c); // links with A::operator() + ref int opIndex(int value); // links with A::operator[] + void printbuffer(); +} + +void main() +{ + auto obj1 = A(1, 3); + auto obj2 = A(13, 43); + obj2 = obj1; // opAssign called here + writeln("obj2's a is ", obj2.a); + writeln("obj2's b is ", obj2.b); + obj2(20, 40, 60); + obj2[0] = 30; + obj2[1] = 60; + obj2[2] = 90; + obj2.printbuffer(); +} +------ + + $(P Compiling, linking, and running produces the output:) + +$(CONSOLE +$(GT) g++ -c foo.cpp +$(GT) dmd bar.d foo.o -L-lstdc++ && ./bar +obj2's a is 1 +obj2's b is 3 +value of a is 20 +value of b is 40 +value of c is 60 +the buffer numbers of index 0 is 30 +the buffer numbers of index 1 is 60 +the buffer numbers of index 2 is 90 +) + +$(H2 $(LNAME2 rtti, Runtime Type Identification)) + + $(P D runtime type identification + uses completely different techniques than C++. + The two are incompatible.) + +$(H2 $(LNAME2 exception-handling, Exception Handling)) + + $(P Exception interoperability is a work in progress.) + + $(P At present, C++ exceptions cannot be caught in or thrown from D, and D + exceptions cannot be caught in or thrown from C++. Additionally, objects + in C++ stack frames are not guaranteed to be destroyed when unwinding the + stack due to a D exception, and vice versa.) + + $(P The plan is to support all of the above except throwing D exceptions + directly in C++ code (but they will be throwable indirectly by calling into + a D function with C++ linkage).) + +$(SECTION2 $(LNAME2 comparing-d-immutable-and-const-with-cpp-const, Comparing D Immutable and Const with C++ Const), + +$(TABLE_SPECIAL $(ARGS Const, Immutable Comparison), + $(THEAD Feature, D, C++98) + $(TROW $(D const) keyword, Yes, Yes) + $(TROW $(D immutable) keyword, Yes, No) + $(TROW const notation, +--- +// Functional: +//ptr to const ptr to const int +const(int*)* p; +--- +, +$(CPPLISTING +// Postfix: +//ptr to const ptr to const int +const int *const *p; +) + ) + + $(TROW transitive const, +--- +// Yes: +//const ptr to const ptr to const int +const int** p; +**p = 3; // error +--- +, +$(CPPLISTING +// No: +// const ptr to ptr to int +int** const p; +**p = 3; // ok +) + ) + + $(TROW cast away const, +--- +// Yes: +// ptr to const int +const(int)* p; +int* q = cast(int*)p; // ok +--- +, +$(CPPLISTING +// Yes: +// ptr to const int +const int* p; +int* q = const_cast$(LT)int*$(GT)p; //ok +) + ) + + $(TROW cast+mutate, +--- +// No: +// ptr to const int +const(int)* p; +int* q = cast(int*)p; +*q = 3; // undefined behavior +--- +, +$(CPPLISTING +// Yes: +// ptr to const int +const int* p; +int* q = const_cast$(LT)int*$(GT)p; +*q = 3; // ok +) + ) + + $(TROW overloading, +--- +// Yes: +void foo(int x); +void foo(const int x); //ok +--- +, +$(CPPLISTING +// No: +void foo(int x); +void foo(const int x); //error +) + ) + + $(TROW const/mutable aliasing, +--- +// Yes: +void foo(const int* x, int* y) +{ + bar(*x); // bar(3) + *y = 4; + bar(*x); // bar(4) +} +... +int i = 3; +foo(&i, &i); +--- +, +$(CPPLISTING +// Yes: +void foo(const int* x, int* y) +{ + bar(*x); // bar(3) + *y = 4; + bar(*x); // bar(4) +} +... +int i = 3; +foo(&i, &i); +) + ) + + $(TROW immutable/mutable aliasing, +--- +// No: +void foo(immutable int* x, int* y) +{ + bar(*x); // bar(3) + *y = 4; // undefined behavior + bar(*x); // bar(??) +} +... +int i = 3; +foo(cast(immutable)&i, &i); +--- +, + No immutables + ) + + $(TROW type of string literal, + $(D immutable(char)[]), + $(D const char*) + ) + + + $(TROW string literal to non-const, + not allowed, + $(ARGS allowed, but deprecated) + ) +) +) + +$(SPEC_SUBNAV_PREV_NEXT interfaceToC, Interfacing to C, objc_interface, Interfacing to Objective-C) +) + +Macros: + CHAPTER=34 + TITLE=Interfacing to C++ diff --git a/spec/ddoc.dd b/spec/ddoc.dd new file mode 100644 index 0000000000..c14ff3f0e8 --- /dev/null +++ b/spec/ddoc.dd @@ -0,0 +1,1349 @@ +Ddoc + +$(SPEC_S Embedded Documentation, + +$(HEADERNAV_TOC) + +$(P +The D programming language enables embedding both contracts and test +code along side the actual code, which helps to keep them all +consistent with each other. One thing lacking is the documentation, +as ordinary comments are usually unsuitable for automated extraction +and formatting into manual pages. +Embedding the user documentation into the source code has important +advantages, such as not having to write the documentation twice, and +the likelihood of the documentation staying consistent with the code. +) + +$(P +Some existing approaches to this are: +) + +$(UL +$(LI $(LINK2 https://www.doxygen.nl/, Doxygen) which already has some support for D) +$(LI Java's $(LINK2 https://docs.oracle.com/javase/7/docs/technotes/guides/javadoc/index.html, Javadoc), + probably the most well-known) +$(LI C$(HASH)'s $(LINK2 https://msdn.microsoft.com/en-us/library/b2s063f7.aspx, embedded XML)) +$(LI Other $(LINK2 https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html, documentation tools)) +) + +$(P +D's goals for embedded documentation are: +) + +$(OL + $(LI It looks good as embedded documentation, not just after it + is extracted and processed.) + $(LI It's easy and natural to write, + i.e. minimal reliance on $(LT)tags$(GT) and other clumsy forms one + would never see in a finished document.) + $(LI It does not repeat information that the compiler already + knows from parsing the code.) + $(LI It doesn't rely on embedded HTML, as such will impede + extraction and formatting for other purposes.) + $(LI It's based on existing D comment forms, so it + is completely independent of parsers only interested in D code.) + $(LI It should look and feel different from code, so it won't + be visually confused with code.) + $(LI It should be possible for the user to use Doxygen or other + documentation extractor if desired.) +) + +$(H2 $(LNAME2 specifications, Specification)) + +$(P +The specification for the form of embedded documentation comments only +specifies how information is to be presented to the compiler. +It is implementation-defined how that information is used and the form +of the final presentation. Whether the final presentation form is an +HTML web page, a man page, a PDF file, etc. is not specified as part of the +D Programming Language. +) + +$(H3 $(LNAME2 phases_of_processing, Phases of Processing)) + +$(P +Embedded documentation comments are processed in a series of phases: +) + +$(OL + $(LI Lexical - documentation comments are identified and attached + to tokens.) + $(LI Parsing - documentation comments are associated with + specific declarations and combined.) + $(LI Sections - each documentation comment is divided up into + a sequence of sections.) + $(LI Special sections are processed.) + $(LI Highlighting of non-special sections is done.) + $(LI All sections for the module are combined.) + $(LI Macro and Escape text substitution is performed to produce the final result.) +) + +$(H3 $(LNAME2 lexical, Lexical)) + +$(P +Embedded documentation comments are one of the following forms: +) + +$(OL + $(LI $(D_COMMENT /** ... */) The two *'s after the opening /) + $(LI $(D_COMMENT /++ ... +/) The two +'s after the opening /) + $(LI $(D_COMMENT ///) The three slashes) +) + +$(P The following are all embedded documentation comments:) + +--------------------------- +/// This is a one line documentation comment. + +/** So is this. */ + +/++ And this. +/ + +/** + This is a brief documentation comment. + */ + +/** + * The leading * on this line is not part of the documentation comment. + */ + +/********************************* + The extra *'s immediately following the /** are not + part of the documentation comment. + */ + +/++ + This is a brief documentation comment. + +/ + +/++ + + The leading + on this line is not part of the documentation comment. + +/ + +/+++++++++++++++++++++++++++++++++ + The extra +'s immediately following the / ++ are not + part of the documentation comment. + +/ + +/**************** Closing *'s are not part *****************/ +--------------------------- + +$(P +The extra *'s and +'s on the comment opening, closing and left margin are +ignored and are not part +of the embedded documentation. +Comments not following one of those forms are not documentation comments. +) + +$(H3 $(LNAME2 parsing, Parsing)) + +$(P +Each documentation comment is associated with a declaration. +If the documentation comment is on a line by itself or with only whitespace +to the left, it refers to the next +declaration. +Multiple documentation comments applying to the same declaration +are concatenated. +Documentation comments not associated with a declaration are ignored. +Documentation comments preceding the $(I ModuleDeclaration) apply to the +entire module. +If the documentation comment appears on the same line to the right of a +declaration, it applies to that. +) + +$(P +If a documentation comment for a declaration consists only of the +identifier $(D ditto) +then the documentation comment for the previous declaration at the same +declaration scope is applied to this declaration as well. +) + +$(P +If there is no documentation comment for a declaration, that declaration +may not appear in the output. To ensure it does appear in the output, +put an empty declaration comment for it. +) + +------------------------------------ +int a; /// documentation for a; b has no documentation +int b; + +/** documentation for c and d */ +/** more documentation for c and d */ +int c; +/** ditto */ +int d; + +/** documentation for e and f */ int e; +int f; /// ditto + +/** documentation for g */ +int g; /// more documentation for g + +/// documentation for C and D +class C +{ + int x; /// documentation for C.x + + /** documentation for C.y and C.z */ + int y; + int z; /// ditto +} + +/// ditto +class D { } +------------------------------------ + +$(H3 $(LNAME2 sections, Sections)) + +$(P +The document comment is a series of $(I Section)s. +A $(I Section) is a name that is the first non-blank character on +a line immediately followed by a ':'. This name forms the section name. +The section name is not case-sensitive. +) + +$(P +Section names starting with 'http://' or 'https://' are not recognized as section names. +) + +$(H4 $(LNAME2 summary, Summary)) + +$(P +The first section is the $(I Summary), and does not have a section name. +It is first paragraph, up to a blank line or a section name. +While the summary can be any length, try to keep it to one line. +The $(I Summary) section is optional. +) + +$(H4 $(LNAME2 description, Description)) + +$(P +The next unnamed section is the $(I Description). +It consists of all the paragraphs following the $(I Summary) until +a section name is encountered or the end of the comment. +) + +$(P +While the $(I Description) section is optional, +there cannot be a $(I Description) without a $(I Summary) section. +) + +------------------------------------ +/*********************************** + * Brief summary of what + * myfunc does, forming the summary section. + * + * First paragraph of synopsis description. + * + * Second paragraph of + * synopsis description. + */ + +void myfunc() { } +------------------------------------ + +$(P +Named sections follow the $(I Summary) and $(I Description) unnamed sections. +) + +$(H3 $(LNAME2 standard_sections, Standard Sections)) + +$(P +For consistency and predictability, there are several standard sections. +None of these are required to be present. +) + +$(DL +$(DT $(B Authors:)) +$(DD Lists the author(s) of the declaration.) +------------------------------------ +/** + * Authors: Melvin D. Nerd, melvin@mailinator.com + */ +------------------------------------ + +$(DT $(B Bugs:)) +$(DD Lists any known bugs.) +------------------------------------ +/** + * Bugs: Doesn't work for negative values. + */ +------------------------------------ + +$(DT $(B Date:)) +$(DD Specifies the date of the current revision. The date should be in a form + parseable by std.date.) + +------------------------------------ +/** + * Date: March 14, 2003 + */ +------------------------------------ + +$(DT $(B Deprecated:)) +$(DD Provides an explanation for and corrective action to take if the associated + declaration is marked as deprecated.) + +------------------------------------ +/** + * Deprecated: superseded by function bar(). + */ + +deprecated void foo() { ... } +------------------------------------ + +$(DT $(B Examples:)) +$(DD Any usage examples) +------------------------------------ +/** + * Examples: + * -------------------- + * writeln("3"); // writes '3' to stdout + * -------------------- + */ +------------------------------------ + +$(DT $(B History:)) +$(DD Revision history.) +------------------------------------ +/** + * History: + * V1 is initial version + * + * V2 added feature X + */ +------------------------------------ + +$(DT $(B License:)) +$(DD Any license information for copyrighted code.) +------------------------------------ +/** + * License: use freely for any purpose + */ + +void bar() { ... } +------------------------------------ + +$(DT $(B Returns:)) +$(DD Explains the return value of the function. + If the function returns $(B void), don't redundantly document it.) +------------------------------------ +/** + * Read the file. + * Returns: The contents of the file. + */ + +void[] readFile(const(char)[] filename) { ... } +------------------------------------ + +$(DT $(B See$(UNDERSCORE)Also:)) +$(DD List of other symbols and URLs to related items.) +------------------------------------ +/** + * See_Also: + * foo, bar, http://www.digitalmars.com/d/phobos/index.html + */ +------------------------------------ + +$(DT $(B Standards:)) +$(DD If this declaration is compliant with any particular standard, +the description of it goes here.) +------------------------------------ +/** + * Standards: Conforms to DSPEC-1234 + */ +------------------------------------ + +$(DT $(B Throws:)) +$(DD Lists exceptions thrown and under what circumstances they are thrown.) +------------------------------------ +/** + * Write the file. + * Throws: WriteException on failure. + */ + +void writeFile(string filename) { ... } +------------------------------------ + +$(DT $(B Version:)) +$(DD Specifies the current version of the declaration.) +------------------------------------ +/** + * Version: 1.6a + */ +------------------------------------ +) + +$(H3 $(LNAME2 special_sections, Special Sections)) + +$(P +Some sections have specialized meanings and syntax. +) + +$(DL +$(DT $(B Copyright:)) +$(DD This contains the copyright notice. The macro COPYRIGHT is set to + the contents of the section when it documents the module declaration. + The copyright section only gets this special treatment when it + is for the module declaration.) + +------------------------------------ +/** Copyright: Public Domain */ + +module foo; +------------------------------------ + +$(DT $(B Params:)) +$(DD Function parameters can be documented by listing them in a params + section. Each line that starts with an identifier followed by + an '=' starts a new parameter description. A description can + span multiple lines.) + +------------------------ +/*********************************** + * foo does this. + * Params: + * x = is for this + * and not for that + * y = is for that + */ + +void foo(int x, int y) +{ +} +------------------------- + +$(DT $(B Macros:)) +$(DD The macros section follows the same syntax as the $(B Params:) section. + It's a series of $(I NAME)=$(I value) pairs. + The $(I NAME) is the macro name, and $(I value) is the replacement + text.) +------------------------------------ +/** + * Macros: + * FOO = now is the time for + * all good men + * BAR = bar + * MAGENTA = <font color="magenta">$0</font> + */ +------------------------------------ +) + + +$(H2 $(LNAME2 highlighting, Highlighting)) + +$(H3 $(LNAME2 embedded_comments, Embedded Comments)) + +$(P + The documentation comments can themselves be commented using + the $(DOLLAR)$(D (DDOC_COMMENT comment text)) syntax. These comments do not + nest. +) + +$(H3 $(LNAME2 embedded_code, Embedded Code)) + +$(P + D code can be embedded using lines beginning with at least three hyphens `-`, + backticks $(DDOC_BACKQUOTED $(BACKTICK)) or tildes `~` (ignoring whitespace) to + delineate the code section: +) + +------------------------------------ +/++ + + Our function. + + + + Example: + + --- + + import std.stdio; + + + + void foo() + + { + + writeln("foo!"); /* print the string */ + + } + + --- + +/ +------------------------------------ + +$(P + Note that in the above example the documentation comment uses the + $(D_COMMENT /++ ... +/) form so that $(D_COMMENT /* ... */) can be used + inside the code section. +) + +$(P + D code gets automatic syntax highlighting. To include code in another + language without syntax highlighting, add a language string at the end of + the top delimiter line: +) + +------------------------------------ +/++ + + Some C++ + + ``` cpp + + #include <iostream> + + + + void foo() + + { + + std::cout << "foo!"; + + } + + ``` + +/ +------------------------------------ + +$(H3 $(LNAME2 inline_code, Inline Code)) + +$(P + Inline code can be written between backtick characters (`$(BACKTICK)`), similarly + to the syntax used on GitHub, Reddit, Stack Overflow, and other websites. Both + the opening and closing `$(BACKTICK)` character must appear on the same line to trigger this + behavior. + Note that macros are still expanded inside backticks. See also + $(RELATIVE_LINK2 punctuation_escapes, escaping). +) + +$(P + Text inside these sections will be escaped according to the rules described above, + then wrapped in a `$(DOLLAR)(DDOC_BACKQUOTED)` macro. By default, this macro expands + to be displayed as an inline text span, formatted as code. +) + +$(P + A literal backtick character can be output either as a non-paired `$(BACKTICK)` on a single + line or by using the `$(DOLLAR)(BACKTICK)` macro. +) + +--- + /// Returns `true` if `a == b`. + void foo() {} + + /// Backquoted `<html>` will be displayed to the user instead + /// of passed through as embedded HTML (see below). + void bar() {} +--- + +$(H3 $(LNAME2 embedded_html, Embedded HTML)) + +$(P +HTML can be embedded into the documentation comments, and it will +be passed through to the HTML output unchanged. +However, since it is not necessarily true that HTML will be the desired +output format of the embedded documentation comment extractor, it is +best to avoid using it where practical. +) + +------------------------------------ +/** + * Example of embedded HTML: + * + * <ol> + * <li><a href="http://www.digitalmars.com/">Digital Mars</a></li> + * <li><a href="http://www.classicempire.com/">Empire</a></li> + * </ol> + */ +------------------------------------ + +$(H3 $(LNAME2 headings, Headings)) + +$(P +A long documentation section can be subdivided by adding headings. A heading is +a line of text that starts with one to six `#` characters followed by whitespace +and then the heading text. The number of `#` characters determines the heading +level. Headings may optionally end with any number of trailing `#` characters. +) + +--- +/** + * # H1 + * ## H2 + * ### H3 + * #### H4 ### + * ##### H5 ## + * ###### H6 # + */ +--- + +$(H3 $(LNAME2 links, Links)) + +$(P +Documentation may link to other documentation or to a URL. There are four +styles of links: +) + +--- +/** + * Some links: + * + * 1. A [reference link][ref] and bare reference links: [ref] or [Object] + * 2. An [inline link](https://dlang.org) + * 3. A bare URL: https://dlang.org + * 4. An ![image](https://dlang.org/images/d3.png) + * + * [ref]: https://dlang.org "The D Language Website" + */ +--- + +$(H4 $(LNAME2 reference_links, Reference Links)) + +$(P +Reference-style links enclose a reference label in square brackets. They may +optionally be preceded by some link text, also enclosed in square brackets. +) + +$(P +The reference label must match a reference defined elsewhere. This may be a D +symbol in scope of the source code being documented, like `[Object]` in the +example above, or it may be an explicit reference that is defined in the same +documentation comment, like `[ref]` in the example above. In the example both +instances of `[ref]` in item `1.` will be replaced with the URL and title text +from the matching definition at the bottom of the example. The first link will +read `reference link` and the second will read `ref`. +) + +$(P +Reference definitions start with a label in square brackets, followed by a +colon, a URL and an optional title wrapped in single or double quotes, or in +parentheses. If a reference label would match both a D symbol and a reference +definition then the reference definition is used. +) + +$(P +The generated links to D symbols are relative if they have the same root package +as the module being documented. If not, their URLs are preceded by a +`$(DOLLAR)(DDOC_ROOT_pkg)` macro, where `pkg` is the root package of the symbol +being linked to. Links to D symbols are generated with a `$(DOLLAR)(DOC_EXTENSION)` +macro after the module name. Then the generated URL for `[Object]` in the above +example is as if it had been written: +) + +--- +$(DOLLAR)(DOC_ROOT_object)object$(DOLLAR)(DOC_EXTENSION)#.Object +--- + +$(P +`DOC_ROOT_` macros can be defined for any external packages +to link to using a $(LINK2 #macros, Macros section). +) + +$(H4 $(LNAME2 inline_links, Inline Links)) + +$(P +Inline-style links enclose link text in square brackets and the link URL in +parentheses. Like reference links, the URL may optionally be followed by title +text wrapped in single or double quotes, or in parentheses: +) + +--- +/// [a link with title text](https://dlang.org 'Some title text') +--- + +$(H4 $(LNAME2 urls, Bare URLs)) + +$(P +Bare URLs are sequences of characters that start with `http://` or `https://`, +continue with one or more characters from the set of letters, digits and +`-_?=%&/+#~.`, and contain at least one period. +URL recognition happens before all macro text substitution. +The URL is wrapped in a `$(DOLLAR)(DDOC_LINK_AUTODETECT)` macro and is otherwise +left untouched. +) + +$(H4 $(LNAME2 images, Images)) + +$(P +Images have the same form as reference or inline links, but add an exclamation +point `!` before the initial square bracket. What would be the link text in a +normal link is used as the image's alt text. +) + +$(H3 $(LNAME2 lists, Lists)) + +$(P +Documentation may contain lists. Start an ordered list with a number followed by +a period: +) + +--- +/** + * 1. First this + * 2. Then this + * 1. A sub-item + */ +--- + +$(P +Start an unordered list with a hyphen (`-`), an asterisk (`*`) or a plus (`+`). +Subsequent items in the same list must also start with the same symbol: +) + +--- +/** + * - A list + * - With a second item + * + * + A different list + * - With a sub-item + * + * * A third list (note the double asterisks) + */ +--- + +$(P +Note the double asterisks in the example above. This is because the list is +inside a documentation comment that is delimited with asterisks, so the initial +asterisk is considered part of the documentation comment, not a list item. This +is even true when other lines don't start with an asterisk: +) + +--- +/** + - A list + * Not a list because the asterisk is part of the documentation comment + */ + +/++ + + + The caveat also applies to plus-delimited documentation comments + +/ +--- + +$(P +List items can include content like new paragraphs, headings, embedded code, or +child list items. Simply indent the content to match the indent of the text +after the list symbol: +) + +---- +/** + * - A parent list item + * + * With a second paragraph + * + * - A sub-item + * --- + * // A code example inside the sub-item + * --- + */ +---- + +$(H3 $(LNAME2 tables, Tables)) + +$(P +Data may be placed into a table. Tables consist of a single header row, a +delimiter row, and zero or more data rows. Cells in each row are separated by +pipe (`|`) characters. Initial and trailing `|`'s are optional. The number of +cells in the delimiter row must match the number of cells in the header row: +) + +--- +/** + * | Item | Price | + * | ---- | ----: | + * | Wigs | $10 | + * Wheels | $13 + * | Widgets | $200 | + */ +--- + +$(P +Cells in the delimiter row contain hyphens (`-`) and optional colons (`:`). +A `:` to the left of the hyphens creates a left-aligned column, a `:` to the +right of the hyphens creates a right-aligned column (like the example above), +and `:`'s on both sides of the hyphens create a center-aligned column. +) + +$(H3 $(LNAME2 quotes, Quotes)) + +$(P +Documentation may include a section of quoted material by prefixing each line of +the section with a `>`. Quotes may include headings, lists, embedded code, etc. +) + +--- +/** + * > To D, or not to D. -- Willeam NerdSpeare + */ +--- + +$(P +Lines of text that directly follow a quoted line are considered part of the quote: +) + +--- +/** + * > This line + * and this line are both part of the quote + * + * This line is not part of the quote. + */ +--- + +$(H3 $(LNAME2 hrules, Horizontal Rules)) + +$(P +Create a horizontal rule by adding a line containing three or more asterisks, +underscores or hyphens: +) + +--- +/** + * *** + * ___ + */ +--- + +$(P +As with $(LINK2 #lists, lists), note that the initial `*` in the example above +will be stripped because it is part of a documentation comment that is delimited +with asterisks. At least three subsequent asterisks are needed. +) + +$(P +To create a horizontal rule with hyphens, add spaces between the hyphens. +Without the spaces they would be treated as the start or end of an $(LINK2 +#embedded_code, embedded code block). Note that any horizontal rule may contain +spaces: +) + +--- +/** + * - - - + * _ _ _ + * * * * + */ +--- + +$(H3 $(LNAME2 text_emphasis, Text Emphasis)) + +$(P +A span of text wrapped in asterisks (`*`) is emphasized, and text wrapped in +two asterisks (`**`) is strongly emphasized: +) + +$(P +`*single asterisks*` is rendered as $(EM single asterisks). +) + +$(P +`**double asterisks**` is rendered as $(STRONG double asterisks). +) + +$(P +Insert a literal asterisk by $(LINK2 #punctuation_escapes, +backslash-escaping) it: `\*` is rendered as *. +) + +$(P +Unlike $(LINK2 https://daringfireball.net/projects/markdown/syntax, Markdown), +underscores (`$(UNDERSCORE)`) are not supported for emphasizing text because it +would break snake$(UNDERSCORE)case names and underscore prefix processing in +$(LINK2 #emphasis, identifier emphasis). +) + +$(H3 $(LNAME2 emphasis, Identifier Emphasis)) + +$(P +Identifiers in documentation comments that are function parameters or are +names that are in scope at the associated declaration are emphasized in +the output. +This emphasis can take the form of italics, boldface, a hyperlink, etc. +How it is emphasized depends on what it is $(MDASH) a function parameter, type, +D keyword, etc. +To prevent unintended emphasis of an identifier, it can be preceded by +an underscore ($(UNDERSCORE)). The underscore will be stripped from the output. +) + +$(H3 $(LNAME2 character_entities, Character Entities)) + +$(P + Some characters have special meaning + to the documentation processor, to avoid confusion it can be best + to replace them with their corresponding character entities: +) + + $(TABLE2 Characters and Entities, + $(THEAD Character, Entity) + $(TROW $(D <), $(AMP)lt;) + $(TROW $(D >), $(AMP)gt;) + $(TROW $(CODE_AMP), $(AMP)amp;)) + +$(P + It is not necessary to do this inside a code section, or if the + special character is not immediately followed by a $(HASH) or a letter. +) + +$(H3 $(LNAME2 punctuation_escapes, Punctuation Escapes)) + +$(P + Escape any ASCII punctuation symbol with a backslash `\`. + Doing so outputs the original character without the backslash, except for + the following characters which output predefined macros instead: +) + + $(TABLE2 Characters and Escape Macros, + $(THEAD Character, Macro) + $(TROW $(D $(LPAREN)), $(DOLLAR)(LPAREN)) + $(TROW $(D $(RPAREN)), $(DOLLAR)(RPAREN)) + $(TROW $(D $(COMMA)), $(DOLLAR)(COMMA)) + $(TROW $(D $(DOLLAR)), $(DOLLAR)(DOLLAR))) + +$(P + To output a backslash, simply use two backslashes in a row: `\\`. + Note that backslashes inside embedded or inline code do $(EM not) escape + punctuation and are included in the output as-is. Backslashes before + non-punctation are also included in the output as-is. For example, + `C:\dmd2\bin\dmd.exe` does not require escaping its embedded backslashes. +) + +$(H3 $(LNAME2 no_documentation, No Documentation)) + +$(P + No documentation is generated for the following constructs, + even if they have a documentation comment: +) + + $(UL + $(LI Invariants) + $(LI Postblits) + $(LI Destructors) + $(LI Static constructors and static destructors) + $(LI Class info, type info, and $(DDSUBLINK abi, ModuleInfo, module info)) + ) + +$(H2 $(LNAME2 macros, Macros)) + +$(P + The documentation comment processor includes a simple macro + text preprocessor. + When $(D $)`(NAME)` appears + in section text it is replaced with the corresponding `NAME` macro's + replacement text. + Macros can take arguments: $(D $)`(NAME argument)`. +) + + For example: + --------- + /** + Macros: + PARAM = <u>$1</u> + MATH_DOCS = <a href="https://dlang.org/phobos/std_math.html">Math Docs</a> + */ + module math; + + /** + * This function returns the sum of $(PARAM a) and $(PARAM b). + * See also the $(MATH_DOCS). + */ + int sum(int a, int b) { return a + b; } + --------- + +$(P + The above would generate output such as:) + + ------------------------------------ + <h1>math</h1> + <dl><dt><big><a name="sum"></a>int <u>sum</u>(int <i>a</i>, int <i>b</i>); + </big></dt> + <dd>This function returns the <u>sum</u> of <u><i>a</i></u> and <u><i>b</i></u>. + See also the <a href="https://dlang.org/phobos/std_math.html">Math Docs</a>. + </dd> + </dl> + ------------------------------------ + +$(P + The replacement text is recursively scanned for more macros. + If found, they are expanded in turn. + If a macro already expanded is recursively encountered, with no argument or with + the same argument text as the enclosing macro, it is replaced + with no text. +) +$(UL + $(LI + Macro invocations that cut across replacement text boundaries are + not expanded. + ) + $(LI + If the macro name is undefined, the replacement text will + be $(D $)`(DDOC_UNDEFINED_MACRO(NAME))`. This defaults to empty. + ) + $(LI + If $(D $)`(NAME)` is required to exist in the output without being + macro expanded, the `$` can be $(RELATIVE_LINK2 punctuation_escapes, + backslash-escaped): `\$`. + ) +) + +$(H3 $(LNAME2 macro_arguments, Macro Arguments)) + +$(P + When invoking a macro, any text from the end of the identifier + to the closing $(SINGLEQUOTE $(RPAREN)) is passed as arguments to + the macro, and can be referred to using the + $(D $)`0` parameter inside the macro definition. + A $(D $)`0` in the replacement text is + replaced with the text of each argument, separated by commas. +) +$(P + If there are commas in the argument text, this denotes multiple arguments. + Inside a macro definition, $(D $)`1` will represent the + argument text up to the first comma, $(D $)`2` from the first comma to + the second comma, etc., up to $(D $)`9`. + $(D $)`+` represents the text from the first comma to the closing $(SINGLEQUOTE $(RPAREN)). +) +$(UL + $(LI + The argument text can contain nested parentheses, `""` or `''` strings, + $(D <)$(D !--) $(D ...) $(D --)$(D >) comments, or tags. + ) + $(LI + If stray, unnested parentheses are used, they can be + $(RELATIVE_LINK2 punctuation_escapes, backslash-escaped): `\(` or `\)`. + ) + $(LI + Any literal commas not intended as an argument separator can be + escaped when invoking a macro expecting separate arguments. + Defining an `ARGS=`$(D $)`0` macro can be useful to handle commas - + these are equivalent: + * $(D $)`(FOO one, `$(D $)`(ARGS two, dwa, dos), three)` + * $(D $)`(FOO one, two\, dwa\, dos, three)`. + ) +) + +$(H3 $(LNAME2 macro_definitions, Macro Definitions)) + +$(P + Macro definitions come from the following sources, + in the specified order: +) + + $(OL + $(LI Predefined macros.) + $(LI Definitions from file specified by + $(DPLLINK dmd-windows.html, sc.ini)'s + or $(DDSUBLINK dmd-linux, dmd_conf, dmd.conf) DDOCFILE setting.) + $(LI Definitions from *.ddoc files specified on the command line.) + $(LI Runtime definitions generated by Ddoc.) + $(LI Definitions from any `Macros:` sections.) + ) + +$(P + Macro redefinitions replace previous definitions of the same name. + This means that the sequence of macro definitions from the various + sources forms a hierarchy. +) + +$(P + Macro names beginning with "D$(UNDERSCORE)" and "DDOC$(UNDERSCORE)" are reserved. +) + +$(H3 $(LNAME2 predefined_macros, Predefined Macros)) + +$(P + A number of macros are predefined Ddoc, and represent the + minimal definitions needed by Ddoc to format and highlight + the presentation. + The definitions are for simple HTML.) + +$(P The implementations of all predefined macros are implementation-defined. The +reference implementation's macro definitions can be found $(HTTPS +github.com/dlang/dmd/blob/master/compiler/src/dmd/res/default_ddoc_theme.ddoc, here).) + +$(P + Ddoc does not generate HTML code. It formats into the basic + formatting macros, which (in their predefined form) + are then expanded into HTML. + If output other than HTML is desired, then these macros + need to be redefined. +) + + $(LONGTABLE_2COLS 0.7, Predefined Formatting Macros, + $(THEAD Name, Description), + $(TROW $(ARGS $(D B)), $(ARGS boldface the argument)) + $(TROW $(ARGS $(D I)), $(ARGS italicize the argument)) + $(TROW $(ARGS $(D U)), $(ARGS underline the argument)) + $(TROW $(ARGS $(D P)), $(ARGS argument is a paragraph)) + $(TROW $(ARGS $(D DL)), $(ARGS argument is a definition list)) + $(TROW $(ARGS $(D DT)), $(ARGS argument is a definition in a definition list)) + $(TROW $(ARGS $(D DD)), $(ARGS argument is a description of a definition)) + $(TROW $(ARGS $(D TABLE)), $(ARGS argument is a table)) + $(TROW $(ARGS $(D TR)), $(ARGS argument is a row in a table)) + $(TROW $(ARGS $(D TH)), $(ARGS argument is a header entry in a row)) + $(TROW $(ARGS $(D TD)), $(ARGS argument is a data entry in a row)) + $(TROW $(ARGS $(D OL)), $(ARGS argument is an ordered list)) + $(TROW $(ARGS $(D UL)), $(ARGS argument is an unordered list)) + $(TROW $(ARGS $(D LI)), $(ARGS argument is an item in a list)) + $(TROW $(ARGS $(D BIG)), $(ARGS argument is one font size bigger)) + $(TROW $(ARGS $(D SMALL)), $(ARGS argument is one font size smaller)) + $(TROW $(ARGS $(D BR)), $(ARGS start new line)) + $(TROW $(ARGS $(D LINK)), $(ARGS generate clickable link on argument)) + $(TROW $(ARGS $(D LINK2)), $(ARGS generate clickable link, first arg is address)) + $(TROW $(ARGS $(D RED)), $(ARGS argument is set to be red)) + $(TROW $(ARGS $(D BLUE)), $(ARGS argument is set to be blue)) + $(TROW $(ARGS $(D GREEN)), $(ARGS argument is set to be green)) + $(TROW $(ARGS $(D YELLOW)), $(ARGS argument is set to be yellow)) + $(TROW $(ARGS $(D BLACK)), $(ARGS argument is set to be black)) + $(TROW $(ARGS $(D WHITE)), $(ARGS argument is set to be white)) + $(TROW $(ARGS $(D D_CODE)), $(ARGS argument is D code)) + $(TROW $(ARGS $(D D_INLINECODE)), $(ARGS argument is inline D code)) + $(TROW $(ARGS $(D LF)), $(ARGS Insert a line feed (newline))) + $(TROW $(ARGS $(D LPAREN)), $(ARGS Insert a left parenthesis)) + $(TROW $(ARGS $(D RPAREN)), $(ARGS Insert a right parenthesis)) + $(TROW $(ARGS $(D BACKTICK)), $(ARGS Insert a backtick)) + $(TROW $(ARGS $(D DOLLAR)), $(ARGS Insert a dollar sign)) + $(TROW $(ARGS $(D DDOC)), $(ARGS overall template for output)) + $(TROW $(ARGS $(D ESCAPES)), $(ARGS characters to substitute)) + ) + +$(P + $(D DDOC) is special in that it specifies the boilerplate into + which the entire generated text is inserted (represented by the + Ddoc generated macro $(D BODY)). For example, in order + to use a style sheet, $(D DDOC) would be redefined as: +) + +$(DDOCCODE +DDOC = $(LT)!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"$(GT) + $(LT)html$(GT)$(LT)head$(GT) + $(LT)META http-equiv="content-type" content="text/html; charset=utf-8"$(GT) + $(LT)title$(GT)$(DOLLAR)(TITLE)$(LT)/title$(GT) + $(LT)link rel="stylesheet" type="text/css" href="https://github.com/style.css"$(GT) + $(LT)/head$(GT)$(LT)body$(GT) + $(LT)h1$(GT)$(DOLLAR)(TITLE)$(LT)/h1$(GT) + $(DOLLAR)(BODY) + $(LT)/body$(GT)$(LT)/html$(GT) +) + +$(P + $(D ESCAPES) defines a series of substitutions which replace special + characters with a string. It's useful when the output format requires + escaping of certain characters, for example in HTML $(D $(AMP)) should be + escaped with $(D $(AMP)amp;). + The syntax is $(D /c/string/), where $(D c) + is either a single character, or multiple characters separated by + whitespace or commas, and $(D string) is the replacement text.) + +------------------------------------ +ESCAPES = /&/AddressOf!/ + /!/Exclamation/ + /?/QuestionMark/ + /,/Comma/ + /{ }/Parens/ + /<,>/Arrows/ +------------------------------------ + +$(P + Highlighting of D code is performed by the following macros: +) + + $(LONGTABLE_2COLS 0.7, D Code Formatting Macros, + $(THEAD Name, Description), + $(TROW $(ARGS $(D D_COMMENT)), $(ARGS Highlighting of comments)) + $(TROW $(ARGS $(D D_STRING)), $(ARGS Highlighting of string literals)) + $(TROW $(ARGS $(D D_KEYWORD)), $(ARGS Highlighting of D keywords)) + $(TROW $(ARGS $(D D_PSYMBOL)), $(ARGS Highlighting of current declaration name)) + $(TROW $(ARGS $(D D_PARAM)), $(ARGS Highlighting of current function declaration parameters)) + ) + +$(P + The highlighting macros start with $(D DDOC_). + They control the formatting of individual parts of the presentation. +) + + $(LONGTABLE_2COLS 0.55, Ddoc Section Formatting Macros, + $(THEAD Name, Description), + $(TROW $(ARGS $(D DDOC_CONSTRAINT)), $(ARGS Highlighting of a template constraint.)) + $(TROW $(ARGS $(D DDOC_COMMENT)), $(ARGS Inserts a comment in the output.)) + $(TROW $(ARGS $(D DDOC_DECL)), $(ARGS Highlighting of the declaration.)) + $(TROW $(ARGS $(D DDOC_DECL_DD)), $(ARGS Highlighting of the description of a declaration.)) + $(TROW $(ARGS $(D DDOC_DITTO)), $(ARGS Highlighting of ditto declarations.)) + $(TROW $(ARGS $(D DDOC_SECTIONS)), $(ARGS Highlighting of all the sections.)) + $(TROW $(ARGS $(D DDOC_SUMMARY)), $(ARGS Highlighting of the summary section.)) + $(TROW $(ARGS $(D DDOC_DESCRIPTION)), $(ARGS Highlighting of the description section.)) + $(TROW $(ARGS $(D DDOC_AUTHORS)), $(ARGS Highlighting of the authors section.)) + $(TROW $(ARGS $(D DDOC_BUGS)), $(ARGS Highlighting of the bugs section.)) + $(TROW $(ARGS $(D DDOC_COPYRIGHT)), $(ARGS Highlighting of the copyright section.)) + $(TROW $(ARGS $(D DDOC_DATE)), $(ARGS Highlighting of the date section.)) + $(TROW $(ARGS $(D DDOC_DEPRECATED)), $(ARGS Highlighting of the deprecated section.)) + $(TROW $(ARGS $(D DEPRECATED)), $(ARGS Wrapper for deprecated declarations.)) + $(TROW $(ARGS $(D DDOC_EXAMPLES)), $(ARGS Highlighting of the examples section.)) + $(TROW $(ARGS $(D DDOC_HISTORY)), $(ARGS Highlighting of the history section.)) + $(TROW $(ARGS $(D DDOC_LICENSE)), $(ARGS Highlighting of the license section.)) + $(TROW $(ARGS $(D DDOC_OVERLOAD_SEPARATOR)), $(ARGS Inserts a separator between overloads of a given name.)) + $(TROW $(ARGS $(D DDOC_RETURNS)), $(ARGS Highlighting of the returns section.)) + $(TROW $(ARGS $(D DDOC_SEE_ALSO)), $(ARGS Highlighting of the see-also section.)) + $(TROW $(ARGS $(D DDOC_STANDARDS)), $(ARGS Highlighting of the standards section.)) + $(TROW $(ARGS $(D DDOC_THROWS)), $(ARGS Highlighting of the throws section.)) + $(TROW $(ARGS $(D DDOC_VERSION)), $(ARGS Highlighting of the version section.)) + $(TROW $(ARGS $(D DDOC_SECTION_H)), $(ARGS Highlighting of the section name of a non-standard section.)) + $(TROW $(ARGS $(D DDOC_SECTION)), $(ARGS Highlighting of the contents of a non-standard section.)) + $(TROW $(ARGS $(D DDOC_MEMBERS)), $(ARGS Default highlighting of all the members of a class, struct, etc.)) + $(TROW $(ARGS $(D DDOC_MODULE_MEMBERS)), $(ARGS Highlighting of all the members of a module.)) + $(TROW $(ARGS $(D DDOC_CLASS_MEMBERS)), $(ARGS Highlighting of all the members of a class.)) + $(TROW $(ARGS $(D DDOC_STRUCT_MEMBERS)), $(ARGS Highlighting of all the members of a struct.)) + $(TROW $(ARGS $(D DDOC_ENUM_MEMBERS)), $(ARGS Highlighting of all the members of an enum.)) + $(TROW $(ARGS $(D DDOC_TEMPLATE_PARAM)), $(ARGS Highlighting of a template's individual parameters.)) + $(TROW $(ARGS $(D DDOC_TEMPLATE_PARAM_LIST)), $(ARGS Highlighting of a template's parameter list.)) + $(TROW $(ARGS $(D DDOC_TEMPLATE_MEMBERS)), $(ARGS Highlighting of all the members of a template.)) + $(TROW $(ARGS $(D DDOC_ENUM_BASETYPE)), $(ARGS Highlighting of the type an enum is based upon)) + $(TROW $(ARGS $(D DDOC_PARAMS)), $(ARGS Highlighting of a function parameter section.)) + $(TROW $(ARGS $(D DDOC_PARAM_ROW)), $(ARGS Highlighting of a name=value function parameter.)) + $(TROW $(ARGS $(D DDOC_PARAM_ID)), $(ARGS Highlighting of the parameter name.)) + $(TROW $(ARGS $(D DDOC_PARAM_DESC)), $(ARGS Highlighting of the parameter value.)) + $(TROW $(ARGS $(D DDOC_BLANKLINE)), $(ARGS Inserts a blank line.)) + $(TROW $(ARGS $(D DDOC_ANCHOR)), $(ARGS Expands to a named anchor used for hyperlinking to a + particular declaration section. Argument $(DOLLAR)1 expands to the qualified declaration name.)) + $(TROW $(ARGS $(D DDOC_PSYMBOL)), $(ARGS Highlighting of declaration name to which a particular section is referring.)) + $(TROW $(ARGS $(D DDOC_PSUPER_SYMBOL)), $(ARGS Highlighting of the base type of a class.)) + $(TROW $(ARGS $(D DDOC_KEYWORD)), $(ARGS Highlighting of D keywords.)) + $(TROW $(ARGS $(D DDOC_PARAM)), $(ARGS Highlighting of function parameters.)) + $(TROW $(ARGS $(D DDOC_BACKQUOTED)), $(ARGS Inserts inline code.)) + $(TROW $(ARGS $(D DDOC_AUTO_PSYMBOL_SUPPRESS)), $(ARGS Highlighting of auto-detected symbol that starts with underscore)) + $(TROW $(ARGS $(D DDOC_AUTO_PSYMBOL)), $(ARGS Highlighting of auto-detected symbol)) + $(TROW $(ARGS $(D DDOC_AUTO_KEYWORD)), $(ARGS Highlighting of auto-detected keywords)) + $(TROW $(ARGS $(D DDOC_AUTO_PARAM)), $(ARGS Highlighting of auto-detected parameters)) + ) + +$(P + For example, one could redefine $(D DDOC_SUMMARY): +) + +$(DDOCCODE +DDOC_SUMMARY = $(DOLLAR)(GREEN $(DOLLAR)0) +) + +$(P + And all the summary sections will now be green. +) + +$(H3 $(LNAME2 macro_def_scini, Macro Definitions from `sc.ini`'s DDOCFILE)) + +$(P + A text file of macro definitions can be created, + and specified in $(D sc.ini): +) + +$(DDOCCODE +DDOCFILE=myproject.ddoc +) + +$(H3 $(LNAME2 macro_def_ddoc_file, Macro Definitions from .ddoc Files on the Command Line)) + +$(P + File names on the DMD command line with the extension + .ddoc are text files that are read and processed in order. +) + +$(H3 $(LNAME2 macro_def_ddocgenerated, Macro Definitions Generated by Ddoc)) + + $(LONGTABLE_2COLS 0.6, Generated Macro Definitions, + $(THEAD Macro Name, Content), + $(TROW + $(ARGS $(B BODY)), + $(ARGS Set to the generated document text.) + ) + $(TROW + $(ARGS $(B TITLE)), + $(ARGS Set to the module name.) + ) + $(TROW + $(ARGS $(B DATETIME)), + $(ARGS Set to the current date and time.) + ) + $(TROW + $(ARGS $(B YEAR)), + $(ARGS Set to the current year.) + ) + $(TROW + $(ARGS $(B COPYRIGHT)), + $(ARGS Set to the contents of any $(B Copyright:) section that is part + of the module comment.) + ) + $(TROW + $(ARGS $(B DOCFILENAME)), + $(ARGS Set to the name of the generated output file.) + ) + $(TROW + $(ARGS $(B SRCFILENAME)), + $(ARGS Set to the name of the source file the documentation is being + generated from.) + ) + ) + +$(H2 $(LNAME2 using_ddoc_to_generate_examples, Using Ddoc to generate examples from unit tests)) + +$(P + Ddoc can automatically generate usage examples for declarations + using unit tests. If a declaration is followed by a documented + unit test, the code from the test will be inserted into the + example section of the declaration. This avoids the frequent + problem of having outdated documentation for pieces of code. +) + +$(P + To create a documented unit test just add three forward + slashes before the unittest block, like this:) + +------ +/// +unittest +{ + ... +} +------ + + $(P For more information please see the full section on + $(LINK2 unittest.html#documented-unittests, documented unit tests). +) + +$(H2 $(LNAME2 using_ddoc_for_other_documentation, Using Ddoc for other Documentation)) + +$(P + Ddoc is primarily designed for use in producing documentation + from embedded comments. It can also, however, be used for + processing other general documentation. + The reason for doing this would be to take advantage of the + macro capability of Ddoc and the D code syntax highlighting + capability. +) + +$(P + If the .d source file starts with the string "Ddoc" then it + is treated as general purpose documentation, not as a D + code source file. From immediately after the "Ddoc" string + to the end of the file or any "Macros:" section forms + the document. No automatic highlighting is done to that text, + other than highlighting of D code embedded between lines + delineated with --- lines. Only macro processing is done. +) + +$(P + Much of the D documentation itself is generated this way, + including this page. + Such documentation is marked at the bottom as being + generated by Ddoc. +) + +$(H2 $(LNAME2 security, Security considerations)) + +$(P + Note that DDoc comments may embed raw HTML, including + $(LT)script$(GT) tags. Be careful when publishing or distributing + rendered DDoc HTML generated from untrusted sources, as this may + allow $(LINK2 https://en.wikipedia.org/wiki/Cross-site_scripting, + cross-site scripting). +) + +$(H2 $(LNAME2 links_to_d_documentation_generators, Links to D documentation generators)) + +$(P + A list of current D documentation generators which use Ddoc + can be found on our $(LINK2 https://wiki.dlang.org/Open_Source_Projects#Documentation_Generators, wiki page). +) + +$(SPEC_SUBNAV_PREV_NEXT iasm, D x86 Inline Assembler, interfaceToC, Interfacing to C) +) + +Macros: + CHAPTER=32 + TITLE=Documentation Generator diff --git a/spec/declaration.dd b/spec/declaration.dd new file mode 100644 index 0000000000..844231dc37 --- /dev/null +++ b/spec/declaration.dd @@ -0,0 +1,948 @@ +Ddoc + +$(SPEC_S Declarations, + +$(HEADERNAV_TOC) + +$(H2 $(LNAME2 grammar, Grammar)) + +$(P *Declaration* can be used inside a function body for a $(GLINK2 statement, DeclarationStatement), +as well as outside a function as it is included in $(GLINK2 module, DeclDef).) + +$(GRAMMAR +$(GNAME Declaration): + $(GLINK2 function, FuncDeclaration) + $(GLINK VarDeclarations) + $(GLINK AliasDeclaration) + $(GLINK AliasAssign) + $(GLINK AggregateDeclaration) + $(GLINK2 enum, EnumDeclaration) + $(GLINK2 module, ImportDeclaration) + $(GLINK2 version, ConditionalDeclaration) + $(GLINK2 version, StaticForeachDeclaration) + $(GLINK2 version, StaticAssert) + $(GLINK2 template, TemplateDeclaration) + $(GLINK2 template-mixin, TemplateMixinDeclaration) + $(GLINK2 template-mixin, TemplateMixin) +) + + +$(H3 $(LNAME2 aggregates, Aggregates)) + +$(GRAMMAR +$(GNAME AggregateDeclaration): + $(GLINK2 class, ClassDeclaration) + $(GLINK2 interface, InterfaceDeclaration) + $(GLINK2 struct, StructDeclaration) + $(GLINK2 struct, UnionDeclaration) +) + +$(H3 $(LNAME2 variable-declarations, Variable Declarations)) + +$(GRAMMAR +$(GNAME VarDeclarations): + $(GLINK StorageClasses)$(OPT) $(GLINK2 type, BasicType) $(GLINK2 type, TypeSuffixes)$(OPT) $(GLINK IdentifierInitializers) $(D ;) + $(GLINK AutoDeclaration) + +$(GNAME IdentifierInitializers): $(LEGACY_LNAME2 Declarators, DeclaratorIdentifierList) + $(GLINK IdentifierInitializer) + $(GLINK IdentifierInitializer) $(D ,) $(GSELF IdentifierInitializers) + +$(GNAME IdentifierInitializer): $(LEGACY_LNAME2 DeclaratorInitializer, DeclaratorIdentifier) + $(GLINK_LEX Identifier) + $(GLINK_LEX Identifier) $(GLINK2 template, TemplateParameters)$(OPT) $(D =) $(GLINK Initializer) + +$(GNAME Declarator): $(LEGACY_LNAME2 VarDeclarator) + $(GLINK2 type, TypeSuffixes)$(OPT) $(GLINK_LEX Identifier) +) + + $(P See also:) + * $(RELATIVE_LINK2 declaration_syntax, Declaration Syntax) + * $(GLINK AutoDeclaration) + * $(DDSUBLINK spec/template, variable-template, Variable Templates) + +$(H3 $(LNAME2 storage-classes, Storage Classes)) + + $(P See $(RELATIVE_LINK2 typequal_vs_storageclass, Type Classes vs. Storage Classes).) + +$(GRAMMAR +$(GNAME StorageClasses): + $(GLINK StorageClass) + $(GLINK StorageClass) $(GSELF StorageClasses) + +$(GNAME StorageClass): + $(GLINK2 attribute, LinkageAttribute) + $(GLINK2 attribute, AlignAttribute) + $(GLINK2 attribute, AtAttribute) + $(DDSUBLINK spec/attribute, deprecated, `deprecated`) + $(DDSUBLINK spec/enum, manifest_constants, `enum`) + $(DDSUBLINK spec/attribute, static, `static`) + $(RELATIVE_LINK2 extern, $(D extern)) + $(DDSUBLINK spec/class, abstract, `abstract`) + $(DDSUBLINK spec/class, final, `final`) + $(DDSUBLINK spec/function, virtual-functions, `override`) + $(DDSUBLINK spec/class, synchronized-classes, `synchronized`) + $(RELATIVE_LINK2 auto-declaration, `auto`) + $(DDSUBLINK spec/attribute, scope, `scope`) + $(DDLINK spec/const3, Type Qualifiers, `const`) + $(DDLINK spec/const3, Type Qualifiers, `immutable`) + $(DDSUBLINK spec/const3, inout, `inout`) + $(DDSUBLINK spec/const3, shared, `shared`) + $(DDSUBLINK spec/attribute, gshared, `__gshared`) + $(GLINK2 attribute, Property) + $(DDSUBLINK spec/function, nothrow-functions, `nothrow`) + $(DDSUBLINK spec/function, pure-functions, `pure`) + $(RELATIVE_LINK2 ref-storage, `ref`) +) + + +$(H2 $(LNAME2 declaration_syntax, Declaration Syntax)) + +$(P Declaration syntax generally reads right to left, including arrays:) + +-------------------- +int x; // x is an int +int* x; // x is a pointer to int +int** x; // x is a pointer to a pointer to int + +int[] x; // x is an array of ints +int*[] x; // x is an array of pointers to ints +int[]* x; // x is a pointer to an array of ints + +int[3] x; // x is a static array of 3 ints +int[3][5] x; // x is a static array of 5 static arrays of 3 ints +int[3]*[5] x; // x is a static array of 5 pointers to static arrays of 3 ints +-------------------- + +$(P See $(DDSUBLINK spec/type, pointers, Pointers), $(DDLINK spec/arrays, Arrays, Arrays) +and $(GLINK2 type, TypeSuffix).) + +$(H3 $(LNAME2 pointers-to-functions, Function Pointers)) + +$(P +$(DDSUBLINK spec/function, function-pointers, Function Pointers) +are declared using the $(D function) keyword: +) + +-------------------- +int function(char) x; // x is a pointer to + // a function taking a char argument + // and returning an int +int function(char)[] x; // x is an array of + // pointers to functions + // taking a char argument + // and returning an int +-------------------- + +$(H3 $(LNAME2 c-style-declarations, C-Style Declarations)) + +$(P +C-style array, function pointer and pointer to array declarations are +not supported. The following C declarations are for comparison only: +) + +$(CPPCODE +int x[3]; // C static array of 3 ints +int x[3][5]; // C static array of 3 arrays of 5 ints + +int (\*x[5])[3]; // C static array of 5 pointers to static arrays of 3 ints +int (\*x)(char); // C pointer to a function taking a char argument + // and returning an int +int (\*[] x)(char); // C array of pointers to functions + // taking a char argument and returning an int +) + +$(RATIONALE +* In D types are straightforward to read from right to left, + unlike in C where parentheses are sometimes required and the type is + read iteratively using the clockwise/spiral rule. +* For a C function pointer declaration `a (*b)(c);` a C parser needs + to attempt a type lookup in order to parse it unambiguously - it + could be a call to a function called `a` which returns a function + pointer, which is immediately called. D function pointer syntax + is unambiguous, avoiding the need for types to be forward declared. +) + +$(H3 $(LNAME2 declaring-multiple-symbols, Declaring Multiple Symbols)) + +$(P +In a declaration declaring multiple symbols, all the declarations +must be of the same type: +) + +-------------------- +int x, y; // x and y are ints +int* x, y; // x and y are pointers to ints +int[] x, y; // x and y are arrays of ints +--- + +$(P This is in contrast to C:) + +$(CPPCODE +int x, *y; // x is an int, y is a pointer to int +int x[], y; // x is an array/pointer, y is an int +) + +$(H2 $(LNAME2 initialization, Initialization)) + + $(P When no *Initializer* is given, a variable is set to the + $(DDSUBLINK spec/property, init, default `.init` value) for + its type.) + +$(H3 $(LNAME2 initializers, Initializers)) + +$(GRAMMAR +$(GNAME Initializer): + $(GLINK VoidInitializer) + $(GLINK NonVoidInitializer) + +$(GNAME NonVoidInitializer): + $(GLINK2 arrays, ArrayInitializer)$(LEGACY_LNAME2 ArrayInitializer) + $(GLINK2 struct, StructInitializer)$(LEGACY_LNAME2 StructInitializer) + $(GLINK2 expression, AssignExpression)$(LEGACY_LNAME2 ExpInitializer) +) + + $(P A variable can be initialized with a $(I NonVoidInitializer). + An *ArrayInitializer* or *StructInitializer* takes precedence over + an expression initializer.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct S { int i; } + +S s = {}; // struct initializer, not a function literal expression +S[] a = [{2}]; // array initializer holding a struct initializer +//a = [{2}]; // invalid array literal expression +--- +) + +$(H3 $(LNAME2 void_init, Void Initialization)) + +$(GRAMMAR +$(GNAME VoidInitializer): + $(D void) +) + + $(P Normally a variable will be initialized. + However, if a variable initializer is $(D void), the variable is *not* initialized. + Void initializers for variables with a type that may contain + $(DDSUBLINK spec/function, safe-values, unsafe values) (such as types with pointers) + are not allowed in `@safe` code. + ) + + $(IMPLEMENTATION_DEFINED If a void initialized variable's value is + used before it is set, its value is implementation defined. + + --- + void bad() + { + int x = void; + writeln(x); // print implementation defined value + } + --- + ) + + $(UNDEFINED_BEHAVIOR If a void initialized variable's value is + used before it is set, and the value is a reference, pointer or an instance + of a struct with an invariant, the behavior is undefined. + + --- + void muchWorse() + { + char[] p = void; + writeln(p); // may result in apocalypse + } + --- + ) + + $(BEST_PRACTICE + $(OL + $(LI Void initializers are useful when a static array is on the stack, + but may only be partially used, such as a temporary buffer. + Void initializers will potentially speed up the code, but they introduce risk, since one must ensure + that array elements are always set before read.) + $(LI The same is true for structs.) + $(LI Use of void initializers is rarely useful for individual local variables, + as a modern optimizer will remove the dead store of its initialization if it is + initialized later.) + $(LI For hot code paths, it is worth profiling to see if the void initializer + actually improves results.) + ) + ) + +$(H3 $(LEGACY_LNAME2 AutoDeclaration, auto-declaration, Implicit Type Inference)) + +$(GRAMMAR +$(GNAME AutoDeclaration): + $(GLINK StorageClasses) $(GLINK AutoAssignments) $(D ;) + +$(GNAME AutoAssignments): + $(GLINK AutoAssignment) + $(GSELF AutoAssignments) $(D ,) $(GLINK AutoAssignment) + +$(GNAME AutoAssignment): + $(GLINK_LEX Identifier) $(GLINK2 template, TemplateParameters)$(OPT) $(D =) $(GLINK Initializer) +) + + $(P If a declaration starts with a $(I StorageClass) and has + a $(I NonVoidInitializer) from which the type can be inferred, + the type on the declaration can be omitted. + ) + +---------- +static x = 3; // x is type int +auto y = 4u; // y is type uint + +auto s = "Apollo"; // s is type immutable(char)[] i.e., string + +class C { ... } + +auto c = new C(); // c is a handle to an instance of class C +---------- + + $(P The $(I NonVoidInitializer) cannot contain forward references + (this restriction may be removed in the future). + The implicitly inferred type is statically bound + to the declaration at compile time, not run time. + ) + + $(P An $(GLINK2 expression, ArrayLiteral) + is inferred to be a dynamic array + type rather than a static array:) + + --- + auto v = ["resistance", "is", "useless"]; // type is string[], not string[3] + --- + +$(H3 $(LNAME2 global_static_init, Global and Static Initializers)) + + $(P The $(GLINK Initializer) for a global or static variable must be + evaluatable at compile time. + Runtime initialization is done with $(DDSUBLINK spec/module, staticorder, static constructors). + ) + + $(IMPLEMENTATION_DEFINED + $(OL + $(LI Whether some pointers can be initialized with the addresses of other + functions or data.) + )) + + +$(H2 $(LNAME2 alias, Alias Declarations)) + + $(NOTE New code should use the *AliasAssignments* form only.) + +$(GRAMMAR +$(GNAME AliasDeclaration): + $(D alias) $(GLINK StorageClasses)$(OPT) $(GLINK2 type, BasicType) $(GLINK2 type, TypeSuffixes)$(OPT) $(GLINK Identifiers) $(D ;) + $(D alias) $(GLINK StorageClasses)$(OPT) $(GLINK2 type, BasicType) $(GLINK2 function, FuncDeclarator) $(D ;) + $(D alias) $(GLINK AliasAssignments) $(D ;) + +$(GNAME Identifiers): + $(GLINK_LEX Identifier) + $(GLINK_LEX Identifier) `,` $(GSELF Identifiers) + +$(GNAME AliasAssignments): + $(GLINK AliasAssignment) + $(GSELF AliasAssignments) $(D ,) $(GLINK AliasAssignment) + +$(GNAME AliasAssignment): + $(GLINK_LEX Identifier) $(GLINK2 template, TemplateParameters)$(OPT) $(D =) $(GLINK StorageClasses)$(OPT) $(GLINK2 type, Type) + $(GLINK_LEX Identifier) $(GLINK2 template, TemplateParameters)$(OPT) $(D =) $(GLINK2 expression, FunctionLiteral) + $(GLINK_LEX Identifier) $(GLINK2 template, TemplateParameters)$(OPT) $(D =) $(GLINK StorageClasses)$(OPT) $(GLINK2 type, Type) $(GLINK2 function, Parameters) $(GLINK2 function, MemberFunctionAttributes)$(OPT) +) + + $(P An $(I AliasDeclaration) creates a symbol name that refers to a type or another symbol. + That name can then be used anywhere that the target may appear. + The following can be aliased: + ) + * $(RELATIVE_LINK2 alias-type, Types) + * $(RELATIVE_LINK2 alias-function, Function Types) (with default arguments) + * $(RELATIVE_LINK2 alias-variable, Variables) + * Manifest Constants + * Modules + * Packages + * Functions + * $(RELATIVE_LINK2 alias-overload, Overload Sets) + * $(DDSUBLINK spec/expression, function-literal-alias, Function Literals) + * Templates + * Template Instantiations + * Other Alias Declarations + +$(H3 $(LNAME2 alias-type, Type Aliases)) + +-------------------- +alias myint = abc.Foo.bar; +-------------------- + + $(P + Aliased types are semantically identical to the types they are aliased to. The + debugger cannot distinguish between them, and there is no difference as far as function + overloading is concerned. For example: + ) + +-------------------- +alias myint = int; + +void foo(int x) { ... } +void foo(myint m) { ... } // error, multiply defined function foo +-------------------- + + $(P + Type aliases can sometimes look indistinguishable from + other symbol aliases: + ) + +-------------------- +alias abc = foo.bar; // is it a type or a symbol? +-------------------- + + $(BEST_PRACTICE Other than when aliasing simple basic type names, + type alias names should be Capitalized.) + +$(H3 $(LNAME2 alias-symbol, Symbol Aliases)) + + $(P A symbol can be declared as an $(I alias) of another symbol. + For example: + ) + + --- + import planets; + + alias myAlbedo = planets.albedo; + ... + int len = myAlbedo("Saturn"); // actually calls planets.albedo() + --- + + $(P + The following alias declarations are valid: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +-------------------- +template Foo2(T) { alias t = T; } +alias t1 = Foo2!(int); +alias t2 = Foo2!(int).t; +alias t3 = t1.t; +alias t4 = t2; + +t1.t v1; // v1 is type int +t2 v2; // v2 is type int +t3 v3; // v3 is type int +t4 v4; // v4 is type int +--- +) + + $(P + Aliased symbols are useful as a shorthand for a long qualified + symbol name, or as a way to redirect references from one symbol + to another: + ) + +-------------------- +version (Win32) +{ + alias myfoo = win32.foo; +} +version (linux) +{ + alias myfoo = linux.bar; +} +-------------------- + + $(P + Aliasing can be used to 'import' a symbol from an + $(DDSUBLINK spec/module, import-declaration, + imported module or package) into the current scope: + ) + +-------------------- +static import string; +... +alias strlen = string.strlen; +-------------------- + +$(H3 $(LNAME2 alias-overload, Aliasing an Overload Set)) + + $(P + Aliases can also 'import' a set of overloaded functions, that can + be overloaded with functions in the current scope: + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +-------------------- +class B +{ + int foo(int a, uint b) { return 2; } +} + +class C : B +{ + // declaring an overload hides any base class overloads + int foo(int a) { return 3; } + // redeclare hidden overload + alias foo = B.foo; +} + +void main() +{ + import std.stdio; + + C c = new C(); + c.foo(1, 2u).writeln; // calls B.foo + c.foo(1).writeln; // calls C.foo +} +-------------------- +) + +$(H3 $(LNAME2 alias-variable, Aliasing Variables)) + + $(P Variables can be aliased, expressions cannot:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +----------- +int i = 0; +alias a = i; // OK +alias b = a; // alias a variable alias +a++; +b++; +assert(i == 2); + +//alias c = i * 2; // error +//alias d = i + i; // error +----------- +) + + $(P Members of an aggregate can be aliased, however non-static + field aliases cannot be accessed outside their parent type.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +----------- +struct S +{ + static int i = 0; + int j; + alias a = j; // OK + + void inc() { a++; } +} + +alias a = S.i; // OK +a++; +assert(S.i == 1); + +alias b = S.j; // allowed +static assert(b.offsetof == 0); +//b++; // error, no instance of S +//S.a++; // error, no instance of S + +S s = S(5); +s.inc(); +assert(s.j == 6); +//alias c = s.j; // scheduled for deprecation +----------- +) + +$(H3 $(LNAME2 alias-function, Aliasing a Function Type)) + + $(P $(DDSUBLINK spec/type, functions, Function types) can be + aliased:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +alias Fun = int(string); +int fun(string) {return 0;} +static assert(is(typeof(fun) == Fun)); + +alias MemberFun1 = int() const; +alias MemberFun2 = const int(); +// leading attributes apply to the func, not the return type +static assert(is(MemberFun1 == MemberFun2)); +-------------------- +) + $(P Type aliases can be used to call a function with different default + arguments, change an argument from required to default or vice versa:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +----------- +import std.stdio : writeln; + +void fun(int v = 6) +{ + writeln("v: ", v); +} + +void main() +{ + fun(); // prints v: 6 + + alias Foo = void function(int=7); + Foo foo = &fun; + foo(); // prints v: 7 + foo(8); // prints v: 8 +} +----------- +) +$(SPEC_RUNNABLE_EXAMPLE_RUN +----------- +import std.stdio : writefln; + +void main() +{ + fun(4); // prints a: 4, b: 6, c: 7 + + Bar bar = &fun; + //bar(4); // compilation error, because the `Bar` alias + // requires an explicit 2nd argument + bar(4, 5); // prints a: 4, b: 5, c: 9 + bar(4, 5, 6); // prints a: 4, b: 5, c: 6 + + Baz baz = &fun; + baz(); // prints a: 2, b: 3, c: 4 +} + +alias Bar = void function(int, int, int=9); +alias Baz = void function(int=2, int=3, int=4); + +void fun(int a, int b = 6, int c = 7) +{ + writefln("a: %d, b: %d, c: %d", a, b, c); +} +----------- +) + +$(H3 $(LNAME2 AliasAssign, Alias Assign)) + +$(GRAMMAR +$(GNAME AliasAssign): + $(GLINK_LEX Identifier) $(D =) $(GLINK2 type, Type) +) + + $(P An $(GLINK AliasDeclaration) can have a new value assigned to it with an + $(I AliasAssign):) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +template Gorgon(T) +{ + alias A = long; + A = T; // assign new value to A + alias Gorgon = A; +} +pragma(msg, Gorgon!int); // prints int +--- +) + +$(UL +$(LI The $(I AliasAssign) and its corresponding $(I AliasDeclaration) must both be +declared in the same $(GLINK2 template, TemplateDeclaration).) + +$(LI The corresponding $(I AliasDeclaration) must appear lexically before the +$(I AliasAssign).) + +$(LI The corresponding $(I AliasDeclaration) may not refer to overloaded symbols.) + +$(LI The value of an $(I AliasDeclaration) or left hand side (lvalue) of an $(I AliasAssign) may not be used prior +to another $(I AliasAssign) to the same lvalue other than in the right hand side of that $(I AliasAssign).) + +) + + $(BEST_PRACTICE + $(I AliasAssign) is particularly useful when using an iterative + computation rather than a recursive one, as it avoids creating + the large number of intermediate templates that the recursive one + engenders.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.meta : AliasSeq; + +static if (0) // recursive method for comparison +{ + template Reverse(T...) + { + static if (T.length == 0) + alias Reverse = AliasSeq!(); + else + alias Reverse = AliasSeq!(Reverse!(T[1 .. T.length]), T[0]); + } +} +else // iterative method minimizes template instantiations +{ + template Reverse(T...) + { + alias A = AliasSeq!(); + static foreach (t; T) + A = AliasSeq!(t, A); // Alias Assign + alias Reverse = A; + } +} + +enum X = 3; +alias TK = Reverse!(int, const uint, X); +pragma(msg, TK); // prints tuple(3, (const(uint)), (int)) +--- +) + +$(H3 $(LNAME2 alias-reassignment, Alias Reassignment)) + +$(GRAMMAR +$(GNAME AliasReassignment): + $(GLINK_LEX Identifier) $(D =) $(GLINK StorageClasses)$(OPT) $(GLINK2 type, Type) + $(GLINK_LEX Identifier) $(D =) $(GLINK2 expression, FunctionLiteral) + $(GLINK_LEX Identifier) $(D =) $(GLINK StorageClasses)$(OPT) $(GLINK2 type, BasicType) $(GLINK2 function, Parameters) $(GLINK2 function, MemberFunctionAttributes)$(OPT) +) + + $(P An alias declaration inside a template can be reassigned a new value.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + import std.meta : AliasSeq; + + template staticMap(alias F, Args...) + { + alias A = AliasSeq!(); + static foreach (Arg; Args) + A = AliasSeq!(A, F!Arg); // alias reassignment + alias staticMap = A; + } + + enum size(T) = T.sizeof; + static assert(staticMap!(size, char, wchar, dchar) == AliasSeq!(1, 2, 4)); + --- + ) + + $(P The $(I Identifier) must resolve to a lexically preceding $(GLINK AliasDeclaration). + Both must be members of the same $(GLINK2 template, TemplateDeclaration). + ) + + $(P The right hand side of the $(I AliasReassignment) replaces the right hand side of the + $(I AliasDeclaration). + ) + + $(P Once the $(I AliasDeclaration) has been referred to in any context other than the + right hand side of an $(I AliasReassignment) it can no longer be reassigned. + ) + + $(RATIONALE Alias reassignment can result in faster compile times and lowered memory consumption, + and requires significantly simpler code than the alternative recursive method.) + + + +$(H2 $(LNAME2 extern, Extern Declarations)) + +$(P Variable declarations with the storage class $(D extern) are not allocated +storage within the module. They must be defined in some other object file with a +matching name which is then linked in.) + +$(P An $(D extern) declaration can optionally be followed by an $(D extern) +$(DDSUBLINK spec/attribute, linkage, linkage attribute). If there is no linkage +attribute it defaults to $(D extern(D)):) + +--------------- +// variable allocated and initialized in this module with C linkage +extern(C) int foo; +// variable allocated outside this module with C linkage +// (e.g. in a statically linked C library or another module) +extern extern(C) int bar; +--------------- + + $(BEST_PRACTICE + $(OL + $(LI The primary usefulness of $(I Extern Declarations) is to + connect with global variables declarations and functions in C or C++ files.) + )) + + +$(H2 $(LNAME2 typequal_vs_storageclass, Type Qualifiers vs. Storage Classes)) + + $(P $(DDLINK spec/const3, Type Qualifiers, Type qualifers) and + $(RELATIVE_LINK2 storage-classes, storage classes) are distinct concepts.) + + $(P A $(I type qualifier) creates a derived type from an existing base + type, and the resulting type may be used to create multiple instances + of that type.) + + $(P For example, the $(D immutable) type qualifier can be used to + create variables of immutable type, such as:) + +-------- +immutable(int) x; // typeof(x) == immutable(int) +immutable(int)[] y; // typeof(y) == immutable(int)[] + // typeof(y[0]) == immutable(int) + +// Type constructors create new types that can be aliased: +alias ImmutableInt = immutable(int); +ImmutableInt z; // typeof(z) == immutable(int) +-------- + + $(P A $(I storage class), on the other hand, does not create a new + type, but describes only the kind of storage used by the variable or + function being declared. For example, a member function can be declared + with the $(D const) storage class to indicate that it does not modify + its implicit $(D this) argument:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +-------- +struct S +{ + int x; + int method() const + { + //x++; // Error: this method is const and cannot modify this.x + return x; // OK: we can still read this.x + } +} +-------- +) + $(P Although some keywords can be + $(RELATIVE_LINK2 methods-returning-qualified, used as both) a type qualifier and a + storage class, there are some storage classes that cannot be used to + construct new types, such as $(D ref).) + +$(H3 $(LNAME2 ref-storage, `ref` Storage Class)) + + $(P A parameter $(DDSUBLINK spec/function, ref-params, declared with `ref`) + is passed by reference:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +-------- +void func(ref int i) +{ + i++; // modifications to i will be visible in the caller +} + +void main() +{ + auto x = 1; + func(x); + assert(x == 2); + + // However, ref is not a type qualifier, so the following is illegal: + //ref(int) y; // Error: ref is not a type qualifier. +} +-------- +) + $(P Functions can also be $(DDSUBLINK spec/function, ref-functions, declared as `ref`), + meaning their return value is passed by reference:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +-------- +ref int func2() +{ + static int y = 0; + return y; +} + +void main() +{ + func2() = 2; // The return value of func2() can be modified. + assert(func2() == 2); + + // However, the reference returned by func2() does not propagate to + // variables, because the 'ref' only applies to the return value itself, + // not to any subsequent variable created from it: + auto x = func2(); + static assert(is(typeof(x) == int)); // N.B.: *not* ref(int); + // there is no such type as ref(int). + x++; + assert(x == 3); + assert(func2() == 2); // x is not a reference to what func2() returned; it + // does not inherit the ref storage class from func2(). +} +-------- +) + +$(H4 $(LNAME2 ref-variables, `ref` Variables)) + + $(P From version 2.111, `ref` can be used to declare local, static, extern, and global variables.) + +$(COMMENT SPEC_RUNNABLE_EXAMPLE_RUN) +--- +struct S { int a; } + +void main() +{ + S s; + ref int r = s.a; + r = 3; + assert(s.a == 3); +} +--- + + $(BEST_PRACTICE Use a `ref` variable instead of a pointer when pointer + arithmetic is not needed.) + + $(P `auto ref` can also be used to declare local, static, extern, and global variables.) + +$(COMMENT SPEC_RUNNABLE_EXAMPLE_COMPILE) +--- +void f() +{ + auto ref x = 0; + auto ref y = x; + static assert(!__traits(isRef, x)); + static assert( __traits(isRef, y)); +} +--- + + $(P See also: $(DDSUBLINK spec/template, auto-ref-parameters, `auto ref`) + template function parameters.) + +$(H3 $(LNAME2 methods-returning-qualified, Methods Returning a Qualified Type)) + + $(P Some keywords, such as $(D const), can be used + both as a type qualifier and a storage class. + The distinction is determined by the syntax where it appears.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S + { + /* Is const here a type qualifier or a storage class? + * Is the return value const(int), or is this a const function that returns + * (mutable) int? + */ + const int* func() // a const function + { + //++p; // error, this.p is const + //return p; // error, cannot convert const(int)* to int* + return null; + } + + const(int)* func() // a function returning a pointer to a const int + { + ++p; // ok, this.p is mutable + return p; // ok, int* can be implicitly converted to const(int)* + } + + int* p; + } + --- + ) + + $(BEST_PRACTICE To avoid confusion, the type qualifier + syntax with parentheses should be used for return types, + and function storage classes should be written on the right-hand side of the + declaration instead of the left-hand side where it may be visually + confused with the return type: + + --- + struct S + { + // Now it is clear that the 'const' here applies to the return type: + const(int) func1() { return 1; } + + // And it is clear that the 'const' here applies to the function: + int func2() const { return 1; } + } + --- + ) + +$(SPEC_SUBNAV_PREV_NEXT module, Modules, type, Types) +) + + +Macros: + CHAPTER=6 + TITLE=Declarations diff --git a/spec/entity.dd b/spec/entity.dd new file mode 100644 index 0000000000..7ad1b30431 --- /dev/null +++ b/spec/entity.dd @@ -0,0 +1,295 @@ +Ddoc + +$(SPEC_S Named Character Entities, + +$(HEADERNAV_TOC) + +$(GRAMMAR_LEX +$(GNAME NamedCharacterEntity): + $(B $(AMP)) $(GLINK_LEX Identifier) $(B ;) +) + + $(P The full list of named character entities from the + $(LINK2 https://w3.org/TR/html5/syntax.html#named-character-references, HTML 5 Spec) + is supported. + Named entities which contain multiple code points can only be used in string literals, + not in character literals, since they do not fit in any character type. + Below is a $(I partial) list of the named character entities. + ) + + $(P $(B Note:) Not all glyphs will display properly in the $(B Glyph) + column in all browsers. + ) + + $(LONGTABLE_3COLS 0.4, Named Character Entities, + $(THEAD Name, Value, Glyph), + $(TROW $(D quot), $(ARGS 34), $(QUOT)) + $(TROW $(D amp), $(ARGS 38), $(AMP)) + $(TROW $(D lt), $(ARGS 60), $(D <)) + $(TROW $(D gt), $(ARGS 62), $(D >)) + + $(TROW $(D OElig), $(ARGS 338), $(OELIG_CAP)) + $(TROW $(D oelig), $(ARGS 339), $(OELIG)) + $(TROW $(D Scaron), $(ARGS 352), $(SCARON_CAP)) + $(TROW $(D scaron), $(ARGS 353), $(SCARON)) + $(TROW $(D Yuml), $(ARGS 376), $(YUML)) + $(TROW $(D circ), $(ARGS 710), $(CIRC)) + $(TROW $(D tilde), $(ARGS 732), $(TILDE)) + $(TROW $(D ensp), $(ARGS 8194), $(ENSP)) + $(TROW $(D emsp), $(ARGS 8195), $(EMSP)) + $(TROW $(D thinsp), $(ARGS 8201), $(THINSP)) + $(TROW $(D zwnj), $(ARGS 8204), $(ZWNJ)) + $(TROW $(D zwj), $(ARGS 8205), $(ZWJ)) + $(TROW $(D lrm), $(ARGS 8206), $(LRM)) + $(TROW $(D rlm), $(ARGS 8207), $(RLM)) + $(TROW $(D ndash), $(ARGS 8211), $(NDASH)) + $(TROW $(D mdash), $(ARGS 8212), $(MDASH)) + $(TROW $(D lsquo), $(ARGS 8216), $(LSQUO)) + $(TROW $(D rsquo), $(ARGS 8217), $(RSQUO)) + $(TROW $(D sbquo), $(ARGS 8218), $(SBQUO)) + $(TROW $(D ldquo), $(ARGS 8220), $(LDQUO)) + $(TROW $(D rdquo), $(ARGS 8221), $(RDQUO)) + $(TROW $(D bdquo), $(ARGS 8222), $(BDQUO)) + $(TROW $(D dagger), $(ARGS 8224), $(DAGGER)) + $(TROW $(D Dagger), $(ARGS 8225), $(DAGGER_CAP)) + $(TROW $(D permil), $(ARGS 8240), $(PERMIL)) + $(TROW $(D lsaquo), $(ARGS 8249), $(LSAQUO)) + $(TROW $(D rsaquo), $(ARGS 8250), $(RSAQUO)) + $(TROW $(D euro), $(ARGS 8364), $(EURO))) + +$(BR) + + $(LONGTABLE_3COLS 0.4, Latin-1 (ISO-8859-1) Entities, + $(THEAD Name, Value, Glyph), + $(TROW $(D nbsp), $(ARGS 160), $(NBSP)) + $(TROW $(D iexcl), $(ARGS 161), $(IEXCL)) + $(TROW $(D cent), $(ARGS 162), $(CENT)) + $(TROW $(D pound), $(ARGS 163), $(POUND)) + $(TROW $(D curren), $(ARGS 164), $(CURREN)) + $(TROW $(D yen), $(ARGS 165), $(YEN)) + $(TROW $(D brvbar), $(ARGS 166), $(BRVBAR)) + $(TROW $(D sect), $(ARGS 167), $(SECT)) + $(TROW $(D uml), $(ARGS 168), $(UML)) + $(TROW $(D copy), $(ARGS 169), $(COPY)) + $(TROW $(D ordf), $(ARGS 170), $(ORDF)) + $(TROW $(D laquo), $(ARGS 171), $(LAQUO)) + $(TROW $(D not), $(ARGS 172), $(NOT)) + $(TROW $(D shy), $(ARGS 173), $(SHY)) + $(TROW $(D reg), $(ARGS 174), $(REG)) + $(TROW $(D macr), $(ARGS 175), $(MACR)) + $(TROW $(D deg), $(ARGS 176), $(DEG)) + $(TROW $(D plusmn), $(ARGS 177), $(PLUSMN)) + $(TROW $(D sup2), $(ARGS 178), $(SUP2)) + $(TROW $(D sup3), $(ARGS 179), $(SUP3)) + $(TROW $(D acute), $(ARGS 180), $(ACUTE)) + $(TROW $(D micro), $(ARGS 181), $(MICRO)) + $(TROW $(D para), $(ARGS 182), $(PARA)) + $(TROW $(D middot), $(ARGS 183), $(MIDDOT)) + $(TROW $(D cedil), $(ARGS 184), $(CEDIL)) + $(TROW $(D sup1), $(ARGS 185), $(SUP1)) + $(TROW $(D ordm), $(ARGS 186), $(ORDM)) + $(TROW $(D raquo), $(ARGS 187), $(RAQUO)) + $(TROW $(D frac14), $(ARGS 188), $(FRAC14)) + $(TROW $(D frac12), $(ARGS 189), $(FRAC12)) + $(TROW $(D frac34), $(ARGS 190), $(FRAC34)) + $(TROW $(D iquest), $(ARGS 191), $(IQUEST)) + $(TROW $(D Agrave), $(ARGS 192), $(AGRAVE_CAP)) + $(TROW $(D Aacute), $(ARGS 193), $(AACUTE_CAP)) + $(TROW $(D Acirc), $(ARGS 194), $(ACIRC_CAP)) + $(TROW $(D Atilde), $(ARGS 195), $(ATILDE_CAP)) + $(TROW $(D Auml), $(ARGS 196), $(AUML_CAP)) + $(TROW $(D Aring), $(ARGS 197), $(ARING_CAP)) + $(TROW $(D AElig), $(ARGS 198), $(AELIG_CAP)) + $(TROW $(D Ccedil), $(ARGS 199), $(CCEDIL_CAP)) + $(TROW $(D Egrave), $(ARGS 200), $(EGRAVE_CAP)) + $(TROW $(D Eacute), $(ARGS 201), $(EACUTE_CAP)) + $(TROW $(D Ecirc), $(ARGS 202), $(ECIRC_CAP)) + $(TROW $(D Euml), $(ARGS 203), $(EUML_CAP)) + $(TROW $(D Igrave), $(ARGS 204), $(IGRAVE_CAP)) + $(TROW $(D Iacute), $(ARGS 205), $(IACUTE_CAP)) + $(TROW $(D Icirc), $(ARGS 206), $(ICIRC_CAP)) + $(TROW $(D Iuml), $(ARGS 207), $(IUML_CAP)) + $(TROW $(D ETH), $(ARGS 208), $(ETH_CAP)) + $(TROW $(D Ntilde), $(ARGS 209), $(NTILDE_CAP)) + $(TROW $(D Ograve), $(ARGS 210), $(OGRAVE_CAP)) + $(TROW $(D Oacute), $(ARGS 211), $(OACUTE_CAP)) + $(TROW $(D Ocirc), $(ARGS 212), $(OCIRC_CAP)) + $(TROW $(D Otilde), $(ARGS 213), $(OTILDE_CAP)) + $(TROW $(D Ouml), $(ARGS 214), $(OUML_CAP)) + $(TROW $(D times), $(ARGS 215), $(TIMES)) + $(TROW $(D Oslash), $(ARGS 216), $(OSLASH_CAP)) + $(TROW $(D Ugrave), $(ARGS 217), $(UGRAVE_CAP)) + $(TROW $(D Uacute), $(ARGS 218), $(UACUTE_CAP)) + $(TROW $(D Ucirc), $(ARGS 219), $(UCIRC_CAP)) + $(TROW $(D Uuml), $(ARGS 220), $(UUML_CAP)) + $(TROW $(D Yacute), $(ARGS 221), $(YACUTE_CAP)) + $(TROW $(D THORN), $(ARGS 222), $(THORN_CAP)) + $(TROW $(D szlig), $(ARGS 223), $(SZLIG)) + $(TROW $(D agrave), $(ARGS 224), $(AGRAVE)) + $(TROW $(D aacute), $(ARGS 225), $(AACUTE)) + $(TROW $(D acirc), $(ARGS 226), $(ACIRC)) + $(TROW $(D atilde), $(ARGS 227), $(ATILDE)) + $(TROW $(D auml), $(ARGS 228), $(AUML)) + $(TROW $(D aring), $(ARGS 229), $(ARING)) + $(TROW $(D aelig), $(ARGS 230), $(AELIG)) + $(TROW $(D ccedil), $(ARGS 231), $(CCEDIL)) + $(TROW $(D egrave), $(ARGS 232), $(EGRAVE)) + $(TROW $(D eacute), $(ARGS 233), $(EACUTE)) + $(TROW $(D ecirc), $(ARGS 234), $(ECIRC)) + $(TROW $(D euml), $(ARGS 235), $(EUML)) + $(TROW $(D igrave), $(ARGS 236), $(IGRAVE)) + $(TROW $(D iacute), $(ARGS 237), $(IACUTE)) + $(TROW $(D icirc), $(ARGS 238), $(ICIRC)) + $(TROW $(D iuml), $(ARGS 239), $(IUML)) + $(TROW $(D eth), $(ARGS 240), $(ETH)) + $(TROW $(D ntilde), $(ARGS 241), $(NTILDE)) + $(TROW $(D ograve), $(ARGS 242), $(OGRAVE)) + $(TROW $(D oacute), $(ARGS 243), $(OACUTE)) + $(TROW $(D ocirc), $(ARGS 244), $(OCIRC)) + $(TROW $(D otilde), $(ARGS 245), $(OTILDE)) + $(TROW $(D ouml), $(ARGS 246), $(OUML)) + $(TROW $(D divide), $(ARGS 247), $(DIVIDE)) + $(TROW $(D oslash), $(ARGS 248), $(OSLASH)) + $(TROW $(D ugrave), $(ARGS 249), $(UGRAVE)) + $(TROW $(D uacute), $(ARGS 250), $(UACUTE)) + $(TROW $(D ucirc), $(ARGS 251), $(UCIRC)) + $(TROW $(D uuml), $(ARGS 252), $(UUML)) + $(TROW $(D yacute), $(ARGS 253), $(YACUTE)) + $(TROW $(D thorn), $(ARGS 254), $(THORN)) + $(TROW $(D yuml), $(ARGS 255), $(YUML))) + +$(BR) + + $(LONGTABLE_3COLS 0.4, Symbols and Greek letter entities, + $(THEAD Name, Value, Glyph), + $(TROW $(D fnof), $(ARGS 402), $(FNOF)) + $(TROW $(D Alpha), $(ARGS 913), $(ALPHA_CAP)) + $(TROW $(D Beta), $(ARGS 914), $(BETA_CAP)) + $(TROW $(D Gamma), $(ARGS 915), $(GAMMA_CAP)) + $(TROW $(D Delta), $(ARGS 916), $(DELTA_CAP)) + $(TROW $(D Epsilon), $(ARGS 917), $(EPSILON_CAP)) + $(TROW $(D Zeta), $(ARGS 918), $(ZETA_CAP)) + $(TROW $(D Eta), $(ARGS 919), $(ETA_CAP)) + $(TROW $(D Theta), $(ARGS 920), $(THETA_CAP)) + $(TROW $(D Iota), $(ARGS 921), $(IOTA_CAP)) + $(TROW $(D Kappa), $(ARGS 922), $(KAPPA_CAP)) + $(TROW $(D Lambda), $(ARGS 923), $(LAMBDA_CAP)) + $(TROW $(D Mu), $(ARGS 924), $(MU_CAP)) + $(TROW $(D Nu), $(ARGS 925), $(NU_CAP)) + $(TROW $(D Xi), $(ARGS 926), $(XI_CAP)) + $(TROW $(D Omicron), $(ARGS 927), $(OMICRON_CAP)) + $(TROW $(D Pi), $(ARGS 928), $(PI_CAP)) + $(TROW $(D Rho), $(ARGS 929), $(RHO_CAP)) + $(TROW $(D Sigma), $(ARGS 931), $(SIGMA_CAP)) + $(TROW $(D Tau), $(ARGS 932), $(TAU_CAP)) + $(TROW $(D Upsilon), $(ARGS 933), $(UPSILON_CAP)) + $(TROW $(D Phi), $(ARGS 934), $(PHI_CAP)) + $(TROW $(D Chi), $(ARGS 935), $(CHI_CAP)) + $(TROW $(D Psi), $(ARGS 936), $(PSI_CAP)) + $(TROW $(D Omega), $(ARGS 937), $(OMEGA_CAP)) + $(TROW $(D alpha), $(ARGS 945), $(ALPHA)) + $(TROW $(D beta), $(ARGS 946), $(BETA)) + $(TROW $(D gamma), $(ARGS 947), $(GAMMA)) + $(TROW $(D delta), $(ARGS 948), $(DELTA)) + $(TROW $(D epsilon), $(ARGS 949), $(EPSILON)) + $(TROW $(D zeta), $(ARGS 950), $(ZETA)) + $(TROW $(D eta), $(ARGS 951), $(ETA)) + $(TROW $(D theta), $(ARGS 952), $(THETA)) + $(TROW $(D iota), $(ARGS 953), $(IOTA)) + $(TROW $(D kappa), $(ARGS 954), $(KAPPA)) + $(TROW $(D lambda), $(ARGS 955), $(LAMBDA)) + $(TROW $(D mu), $(ARGS 956), $(MU)) + $(TROW $(D nu), $(ARGS 957), $(NU)) + $(TROW $(D xi), $(ARGS 958), $(XI)) + $(TROW $(D omicron), $(ARGS 959), $(OMICRON)) + $(TROW $(D pi), $(ARGS 960), $(PI)) + $(TROW $(D rho), $(ARGS 961), $(RHO)) + $(TROW $(D sigmaf), $(ARGS 962), $(SIGMAF)) + $(TROW $(D sigma), $(ARGS 963), $(SIGMA)) + $(TROW $(D tau), $(ARGS 964), $(TAU)) + $(TROW $(D upsilon), $(ARGS 965), $(UPSILON)) + $(TROW $(D phi), $(ARGS 966), $(PHI)) + $(TROW $(D chi), $(ARGS 967), $(CHI)) + $(TROW $(D psi), $(ARGS 968), $(PSI)) + $(TROW $(D omega), $(ARGS 969), $(OMEGA)) + $(TROW $(D thetasym), $(ARGS 977), $(THETASYM)) + $(TROW $(D upsih), $(ARGS 978), $(UPSIH)) + $(TROW $(D piv), $(ARGS 982), $(PIV)) + $(TROW $(D bull), $(ARGS 8226), $(BULL)) + $(TROW $(D hellip), $(ARGS 8230), $(HELLIP)) + $(TROW $(D prime), $(ARGS 8242), $(PRIME)) + $(TROW $(D Prime), $(ARGS 8243), $(PRIME_CAP)) + $(TROW $(D oline), $(ARGS 8254), $(OLINE)) + $(TROW $(D frasl), $(ARGS 8260), $(FRASL)) + $(TROW $(D weierp), $(ARGS 8472), $(WEIERP)) + $(TROW $(D image), $(ARGS 8465), $(IMAGE)) + $(TROW $(D real), $(ARGS 8476), $(REAL)) + $(TROW $(D trade), $(ARGS 8482), $(TRADE)) + $(TROW $(D alefsym), $(ARGS 8501), $(ALEFSYM)) + $(TROW $(D larr), $(ARGS 8592), $(LARR)) + $(TROW $(D uarr), $(ARGS 8593), $(UARR)) + $(TROW $(D rarr), $(ARGS 8594), $(RARR)) + $(TROW $(D darr), $(ARGS 8595), $(DARR)) + $(TROW $(D harr), $(ARGS 8596), $(HARR)) + $(TROW $(D crarr), $(ARGS 8629), $(CRARR)) + $(TROW $(D lArr), $(ARGS 8656), $(LARR_CAP)) + $(TROW $(D uArr), $(ARGS 8657), $(UARR_CAP)) + $(TROW $(D rArr), $(ARGS 8658), $(RARR_CAP)) + $(TROW $(D dArr), $(ARGS 8659), $(DARR_CAP)) + $(TROW $(D hArr), $(ARGS 8660), $(HARR_CAP)) + $(TROW $(D forall), $(ARGS 8704), $(FORALL)) + $(TROW $(D part), $(ARGS 8706), $(PART)) + $(TROW $(D exist), $(ARGS 8707), $(EXIST)) + $(TROW $(D empty), $(ARGS 8709), $(EMPTY)) + $(TROW $(D nabla), $(ARGS 8711), $(NABLA)) + $(TROW $(D isin), $(ARGS 8712), $(ISIN)) + $(TROW $(D notin), $(ARGS 8713), $(NOTIN)) + $(TROW $(D ni), $(ARGS 8715), $(NI)) + $(TROW $(D prod), $(ARGS 8719), $(PROD)) + $(TROW $(D sum), $(ARGS 8721), $(SUM)) + $(TROW $(D minus), $(ARGS 8722), $(MINUS)) + $(TROW $(D lowast), $(ARGS 8727), $(LOWAST)) + $(TROW $(D radic), $(ARGS 8730), $(RADIC)) + $(TROW $(D prop), $(ARGS 8733), $(PROP)) + $(TROW $(D infin), $(ARGS 8734), $(INFIN)) + $(TROW $(D ang), $(ARGS 8736), $(ANG)) + $(TROW $(D and), $(ARGS 8743), $(AND)) + $(TROW $(D or), $(ARGS 8744), $(OR)) + $(TROW $(D cap), $(ARGS 8745), $(CAP)) + $(TROW $(D cup), $(ARGS 8746), $(CUP)) + $(TROW $(D int), $(ARGS 8747), $(INT)) + $(TROW $(D there4), $(ARGS 8756), $(THERE4)) + $(TROW $(D sim), $(ARGS 8764), $(SIM)) + $(TROW $(D cong), $(ARGS 8773), $(CONG)) + $(TROW $(D asymp), $(ARGS 8776), $(ASYMP)) + $(TROW $(D ne), $(ARGS 8800), $(NE)) + $(TROW $(D equiv), $(ARGS 8801), $(EQUIV)) + $(TROW $(D le), $(ARGS 8804), $(LE)) + $(TROW $(D ge), $(ARGS 8805), $(GE)) + $(TROW $(D sub), $(ARGS 8834), $(SUB)) + $(TROW $(D sup), $(ARGS 8835), $(SUP)) + $(TROW $(D nsub), $(ARGS 8836), $(NSUB)) + $(TROW $(D sube), $(ARGS 8838), $(SUBE)) + $(TROW $(D supe), $(ARGS 8839), $(SUPE)) + $(TROW $(D oplus), $(ARGS 8853), $(OPLUS)) + $(TROW $(D otimes), $(ARGS 8855), $(OTIMES)) + $(TROW $(D perp), $(ARGS 8869), $(PERP)) + $(TROW $(D sdot), $(ARGS 8901), $(SDOT)) + $(TROW $(D lceil), $(ARGS 8968), $(LCEIL)) + $(TROW $(D rceil), $(ARGS 8969), $(RCEIL)) + $(TROW $(D lfloor), $(ARGS 8970), $(LFLOOR)) + $(TROW $(D rfloor), $(ARGS 8971), $(RFLOOR)) + $(TROW $(D loz), $(ARGS 9674), $(LOZ)) + $(TROW $(D spades), $(ARGS 9824), $(SPADES)) + $(TROW $(D clubs), $(ARGS 9827), $(CLUBS)) + $(TROW $(D hearts), $(ARGS 9829), $(HEARTS)) + $(TROW $(D diams), $(ARGS 9830), $(DIAMS)) + $(TROW $(D lang), $(ARGS 10216), $(LANG)) + $(TROW $(D rang), $(ARGS 10217), $(RANG)) + ) +$(SPEC_SUBNAV_PREV_NEXT portability, Portability Guide, memory-safe-d, Memory Safety) +) + +Macros: + CHAPTER=37 + TITLE=Named Character Entities diff --git a/spec/enum.dd b/spec/enum.dd new file mode 100644 index 0000000000..4e7ada52a0 --- /dev/null +++ b/spec/enum.dd @@ -0,0 +1,409 @@ +Ddoc + +$(SPEC_S Enums, + +$(HEADERNAV_TOC) + +$(GRAMMAR +$(GNAME EnumDeclaration): + $(D enum) $(GLINK_LEX Identifier) $(GLINK EnumBody) + $(D enum) $(GLINK_LEX Identifier) $(D :) $(GLINK EnumBaseType) $(GLINK EnumBody) + $(GLINK AnonymousEnumDeclaration) + +$(GNAME EnumBaseType): + $(GLINK2 type, Type) + +$(GNAME EnumBody): + $(D {) $(GLINK EnumMembers) $(D }) + $(D ;) + +$(GNAME EnumMembers): + $(GLINK EnumMember) + $(GLINK EnumMember) $(D ,) + $(GLINK EnumMember) $(D ,) $(GSELF EnumMembers) + +$(GNAME EnumMember): + $(GLINK EnumMemberAttributes)$(OPT) $(GLINK_LEX Identifier) + $(GLINK EnumMemberAttributes)$(OPT) $(GLINK_LEX Identifier) $(D =) $(ASSIGNEXPRESSION) + +$(GNAME EnumMemberAttributes): + $(GLINK EnumMemberAttribute) + $(GLINK EnumMemberAttribute) $(GSELF EnumMemberAttributes) + +$(GNAME EnumMemberAttribute): + $(GLINK2 attribute, DeprecatedAttribute) + $(GLINK2 attribute, UserDefinedAttribute) + $(D @) $(LINK2 attribute.html#disable, $(D disable)) +) +$(GRAMMAR +$(GNAME AnonymousEnumDeclaration): + $(D enum) $(D :) $(GLINK EnumBaseType) $(D {) $(GLINK EnumMembers) $(D }) + $(D enum) $(D {) $(GLINK AnonymousEnumMembers) $(D }) + +$(GNAME AnonymousEnumMembers): + $(GLINK AnonymousEnumMember) + $(GLINK AnonymousEnumMember) $(D ,) + $(GLINK AnonymousEnumMember) $(D ,) $(GSELF AnonymousEnumMembers) + +$(GNAME AnonymousEnumMember): + $(GLINK EnumMember) + $(GLINK EnumMemberAttributes)$(OPT) $(GLINK2 type, Type) $(GLINK_LEX Identifier) $(D =) $(ASSIGNEXPRESSION) +) + + $(P Enum declarations are used to define a group of constants. + ) + +$(H2 $(LNAME2 named_enums, Named Enums)) + + $(P + Named enums are used to declare related + constants and group them by giving them a unique type. + The $(GLINK EnumMembers) are declared in the scope of the named enum. The named + enum declares a new type, and all the $(I EnumMembers) have that type. + ) + + $(P This defines a new type $(CODE X) which has values + $(CODE X.A = 0), $(CODE X.B = 1), $(CODE X.C = 2):) + + --- + enum X { A, B, C } // named enum + --- + + $(LEGACY_LNAME2 enum_default_initializer, enum_variables) + + $(P A variable can be of named enum type. + Its default initializer is the first member defined for the enum type. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------ +enum X { A = 3, B, C } + +X x; +assert(x == X.A); +x |= X.B; +assert(x & X.A); +------ +) + + $(P The result type of a binary operation on a named enum is defined + $(DDSUBLINK spec/type, enum-ops, here).) + + $(P If the $(GLINK EnumBaseType) is not explicitly set, and the first + $(I EnumMember) has an *AssignExpression*, it is set to the type of that + *AssignExpression*. Otherwise, it defaults to + type $(CODE int).) + + * A named enum member can be implicitly cast to its $(I EnumBaseType). + * An $(I EnumBaseType) instance cannot be implicitly cast to a named enum type. + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +------------------- +enum Foo { E } + +Foo f; +int i; +i = f; // OK +f = i; // error +f = cast(Foo)i; // OK +f = 0; // error +f = Foo.E; // OK +------------------- +) + + $(P A named enum member cannot declare its own $(I Type).) + + $(P See also: $(DDSUBLINK spec/statement, final-switch-statement, `final switch`) on a named enum.) + +$(H3 $(LNAME2 member_values, Enum Member Values)) + + $(P The value of an $(GLINK EnumMember) is given by its *AssignExpression* if present. + If there is no *AssignExpression* and it is the first $(I EnumMember), + its value is converted to $(GLINK EnumBaseType) from `0`. + If there is no *AssignExpression* and it is not the first $(I EnumMember), + it is given the value of the previous $(I EnumMember)` + 1`:) + + * If the value of the previous $(I EnumMember) is $(GLINK EnumBaseType)`.max`, + it is an error. This prevents value overflow. It is an error if the previous + member cannot be compared with *EnumBaseType*`.max` at compile-time. + * It is an error if the base type does not define a compile-time + evaluable `+ 1` operation. + * If the value of the previous $(I EnumMember)` + 1` is the same as the + value of the previous $(I EnumMember), it is an error. (This can happen + with floating point types). + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +enum E : char +{ + a, + b = char.max, + c // overflow +} + +static assert(E.a == 0); +--- +) + + $(P All $(I EnumMember)s are in scope for the *AssignExpression*s. + ) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +enum A = 3; +enum B +{ + A = A // error, circular reference +} +enum C +{ + A = B, // A = 4 + B = D, // B = 4 + C = 3, // C = 3 + D // D = 4 +} +enum E : C +{ + E1 = C.D, + E2 // error, C.D is C.max +} +--- +) + + $(P An empty enum body signifies an opaque enum - the enum members are unknown.) + --- + enum X; // opaque enum + writeln(X.init); // error: enum X is opaque and has no default initializer + --- + +$(H3 $(LNAME2 enum_properties, Enum Properties)) + + $(P Enum properties only exist for named enums. + ) + + $(TABLE + $(CAPTION Named Enum Properties) + $(TROW $(D .init), First enum member value) + $(TROW $(D .min), Smallest enum member value) + $(TROW $(D .max), Largest enum member value) + $(TROW $(D .sizeof), Size of storage for an enumerated value) + ) + + $(P For example:) + +--- +enum X { A = 3, B = 1, C = 4, D, E = 2 } +X.init // is X.A +X.min // is X.B +X.max // is X.D +X.sizeof // is same as int.sizeof +--- + + $(P The $(GLINK EnumBaseType) of named enums must support comparison + in order to compute the $(CODE .max) and $(CODE .min) properties. + ) + +$(H3 $(LNAME2 enum_copying_and_assignment, Enum Copying and Assignment)) + + $(P A named enum type never has a + $(DDSUBLINK spec/struct, struct-copy-constructor, copy constructor), + $(DDSUBLINK spec/struct, struct-postblit, postblit), or + $(DDSUBLINK spec/struct, assign-overload, identity assignment overload), + even if one is defined by its $(GLINK EnumBaseType).) + + $(P When copying a named enum value whose base type is a `struct` with + a copy constructor, the copy constructor is not called:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + struct S + { + this(ref S rhs) { assert(0); } + } + + enum E : S { A = S.init } + + void main() + { + E e1; + E e2 = e1; // ok - copy constructor not called + } + --- + ) + + $(P When copying a named enum value whose base type is a `struct` with + a postblit, the postblit is not called:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + struct S + { + this(this) { assert(0); } + } + + enum E : S { A = S.init } + + void main() + { + E e1; + E e2 = e1; // ok - postblit not called + } + --- + ) + + $(P When assigning a named enum value to another object of the same + type, if the base type of those values is a `struct` with an identity + assignment overload, the identity assignment overload is not called:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + struct S + { + void opAssign(S rhs) { assert(0); } + } + + enum E : S { A = S.init } + + void main() + { + E e1, e2; + e2 = e1; // ok - opAssign not called + } + --- + ) + + +$(H2 $(LNAME2 anonymous_enums, Anonymous Enums)) + + $(P If the enum $(I Identifier) is not present, then the enum + is an $(I anonymous enum), and the $(GLINK EnumMembers) are declared + in the scope the $(GLINK EnumDeclaration) appears in. + No new type is created. + ) + + $(P The $(I EnumMembers) can have different types. + Those types are given by the first of: + ) + + $(OL + $(LI The $(I Type), if present. Types are not permitted when an + $(GLINK EnumBaseType) is present.) + $(LI The $(I EnumBaseType), if present.) + $(LI The type of the $(I AssignExpression), if present.) + $(LI The type of the previous $(I EnumMember), if present.) + $(LI $(CODE int)) + ) + + +------ +enum { A, B, C } // anonymous enum +------ + + $(P Defines the constants $(CODE A = 0), $(CODE B = 1), $(CODE C = 2), all of type `int`.) + + $(P Enums must have at least one member. + ) + + $(P The value of an $(I EnumMember) is given by its *AssignExpression* if present. + If there is no *AssignExpression* and it is the first $(I EnumMember), + its value is the $(CODE .init) property of the $(I EnumMember)'s type. + If there is no *AssignExpression* and it is not the first $(I EnumMember), + it is given the value of the previous $(I EnumMember)` + 1`:) + + * If the value of the previous $(I EnumMember) is the `.max` property + of the previous $(I EnumMember)'s type, it is an error. + This prevents value overflow. It is an error if the previous + member cannot be compared with its `.max` property at compile-time. + * It is an error if the type of the previous member does not define a compile-time + evaluable `+1` operation. + * If the value of the previous $(I EnumMember)`+1` is the same as the + value of the previous $(I EnumMember), it is an error. (This can happen + with floating point types). + + $(P All $(I EnumMember)s are in scope for the *AssignExpression*s. + ) + +------ +enum { A, B = 5 + 7, C, D = 8 + C, E } +------ + + $(P Sets $(CODE A = 0), $(CODE B = 12), $(CODE C = 13), $(CODE D = 21), and $(CODE E = 22), all of type `int`.) + +--- +enum : long { A = 3, B } +--- + + $(P Sets $(CODE A = 3) and $(CODE B = 4), both of type `long`.) + +--- +enum : string +{ + A = "hello", + B = "betty", + C // error, cannot add 1 to "betty" +} +--- + +--- +enum +{ + A = 1.2f, // A is 1.2f of type float + B, // B is 2.2f of type float + int C = 3, // C is 3 of type int + D // D is 4 of type int +} +--- + +$(H2 $(LNAME2 single_member, Single Member Anonymous Enum)) + + $(P If there is only one member of an anonymous enum, the `{ }` can + be omitted. Gramatically speaking, this is an $(GLINK2 declaration, AutoDeclaration). + ) + +--- +enum i = 4; // i is 4 of type int +enum long l = 3; // l is 3 of type long +--- + +$(H2 $(LNAME2 manifest_constants, Manifest Constants)) + + $(P Enum members are manifest constants, which exist only at compile-time.) + + $(P Manifest constants are not lvalues, meaning their address + cannot be taken. They exist only in the memory of the compiler.) + +--- +enum size = __traits(classInstanceSize, Foo); // evaluated at compile-time +--- + + $(P The initializer for a manifest constant is evaluated using compile-time function evaluation.) + +--- +template Foo(T) +{ + // Not bad, but the 'size' variable will be located in the executable. + const size_t size = T.sizeof; // evaluated at compile-time + + // ... use of 'size' at compile-time ... +} + +template Bar(T) +{ + // Better, the manifest constant has no runtime location in the executable. + enum size_t size = T.sizeof; // evaluated at compile-time + + // ... use of 'size' at compile time ... + + // Taking the address of Foo!T.size also causes it to go into the exe file. + auto p = &Foo!T.size; +} +--- + + +$(SPEC_SUBNAV_PREV_NEXT interface, Interfaces, const3, Type Qualifiers) +) + +Macros: + CHAPTER=18 + TITLE=Enums + CATEGORY_SPEC=$0 diff --git a/spec/errors.dd b/spec/errors.dd new file mode 100644 index 0000000000..6b61653fe8 --- /dev/null +++ b/spec/errors.dd @@ -0,0 +1,216 @@ +Ddoc + +$(SPEC_S Error Handling, + +$(HEADERNAV_TOC) + +$(BLOCKQUOTE_BY Julius C'ster, +I came, I coded, I crashed. +) + +$(HTMLTAG3 img, src="https://github.com/$(ROOT_DIR)images/dman-error.jpg" border="0" align="right" alt="Erroneous D-Man" height="200") + +All programs have to deal with errors. Errors are unexpected conditions that +are not part of the normal operation of a program. Examples of common errors +are: + +$(UL + $(LI Out of memory.) + $(LI Out of disk space.) + $(LI Invalid file name.) + $(LI Attempting to write to a read-only file.) + $(LI Attempting to read a non-existent file.) + $(LI Requesting a system service that is not supported.) +) + +$(H2 $(LNAME2 the_error_handling_problem, The Error Handling Problem)) + +The traditional C way of detecting and reporting errors is not traditional, +it is ad-hoc and varies from function to function, including: + +$(UL + $(LI Returning a NULL pointer.) + $(LI Returning a 0 value.) + $(LI Returning a non-zero error code.) + $(LI Requiring errno to be checked.) + $(LI Requiring that a function be called to check if the previous + function failed.) +) + +$(P To deal with these possible errors, tedious error handling code must be added +to each function call. If an error happened, code must be written to recover +from the error, and the error must be reported to the user in some user friendly +fashion. If an error cannot be handled locally, it must be explicitly +propagated back to its caller. +The long list of errno values needs to be converted into appropriate +text to be displayed. Adding all the code to do this can consume a large part +of the time spent coding a project - and still, if a new errno value is added +to the runtime system, the old code can not properly display a meaningful +error message.) + +$(P Good error handling code tends to clutter up what otherwise would be a neat +and clean looking implementation.) + +$(P Even worse, good error handling code is itself error prone, tends to be the +least tested (and therefore buggy) part of the project, and is frequently +simply omitted. The end result is likely a "blue screen of death" as the +program failed to deal with some unanticipated error.) + +$(P Quick and dirty programs are not worth writing tedious error handling code +for, and so such utilities tend to be like using a table saw with no +blade guards.) + +What's needed is an error handling philosophy and methodology such that: + +$(UL + $(LI It is standardized - consistent usage makes it more useful.) + $(LI The result is reasonable even if the programmer fails + to check for errors.) + $(LI Old code can be reused with new code without having + to modify the old code to be compatible with new error types.) + $(LI No errors get inadvertently ignored.) + $(LI $(SINGLEQUOTE Quick and dirty) utilities can be written that still + correctly handle errors.) + $(LI It is easy to make the error handling source code look good.) +) + +$(H2 $(LNAME2 the_d_error_handling_solution, The D Error Handling Solution)) + +Let's first make some observations and assumptions about errors: + +$(UL + $(LI Errors are not part of the normal flow of a program. Errors + are exceptional, unusual, and unexpected.) + $(LI Because errors are unusual, execution of error handling code + is not performance critical.) + $(LI The normal flow of program logic is performance critical.) + $(LI All errors must be dealt with in some way, either by + code explicitly written to handle them, or by some system default + handling.) + $(LI The code that detects an error knows more about the error + than the code that must recover from the error.) +) + +$(P The solution is to use exception handling to report errors. All +errors are objects derived from the abstract class $(LINK2 https://dlang.org/phobos/object.html#.Error, $(D Error)). $(D Error) +has a pure virtual function called toString() which produces a $(D string) +with a human readable description of the error.) + +$(P If code detects an error like "out of memory," then an $(D Error) is thrown +with a message saying "Out of memory". The function call stack is unwound, +looking for a handler for the Error. +$(DDSUBLINK spec/statement, TryStatement, Finally blocks) +are executed as the +stack is unwound. If an error handler is found, execution resumes there. If +not, the default Error handler is run, which displays the message and +terminates the program.) + +$(P How does this meet our criteria?) + +$(DL + $(DT It is standardized - consistent usage makes it more useful.) + $(DD This is the D way, and is used consistently in the D + runtime library and examples.) + + $(DT The result is reasonable result even if the programmer fails + to check for errors.) + $(DD If no catch handlers are there for the errors, then the + program gracefully exits through the default error handler + with an appropriate message.) + + $(DT Old code can be reused with new code without having + to modify the old code to be compatible with new error types.) + $(DD Old code can decide to catch all errors, or only specific ones, + propagating the rest upwards. In any case, there is no more + need to correlate error numbers with messages, the correct message + is always supplied.) + + $(DT No errors get inadvertently ignored.) + $(DD Error exceptions get handled one way or another. There is nothing + like a NULL pointer return indicating an error, followed by trying to + use that NULL pointer.) + + $(DT 'Quick and dirty' utilities can be written that still + correctly handle errors.) + $(DD Quick and dirty code need not write any error handling code at + all, and don't need to check for errors. The errors will be caught, + an appropriate message displayed, and the program gracefully shut down + all by default.) + + $(DT It is easy to make the error handling source code look good.) + $(DD The try/catch/finally statements look a lot nicer than endless + `if (error) goto errorhandler;` statements.) +) + +How does this meet our assumptions about errors? + +$(DL + $(DT Errors are not part of the normal flow of a program. Errors + are exceptional, unusual, and unexpected.) + $(DD D exception handling fits right in with that.) + + $(DT Because errors are unusual, execution of error handling code + is not performance critical.) + $(DD Exception handling stack unwinding is a relatively slow process.) + + $(DT The normal flow of program logic is performance critical.) + $(DD Since the normal flow code does not have to check every + function call for error returns, it can be realistically faster + to use exception handling for the errors.) + + $(DT All errors must be dealt with in some way, either by + code explicitly written to handle them, or by some system default + handling.) + $(DD If there's no handler for a particular error, it is handled + by the runtime library default handler. If an error is ignored, + it is because the programmer specifically added code to ignore + an error, which presumably means it was intentional.) + + $(DT The code that detects an error knows more about the error + than the code that must recover from the error.) + $(DD There is no more need to translate error codes into human + readable strings, the correct string is generated by the error + detection code, not the error recovery code. This also leads to + consistent error messages for the same error between applications.) +) + +Using exceptions to handle errors leads to another issue - how to write +exception safe programs. $(LINK2 $(ROOT_DIR)articles/exception-safe.html, Here's how). + +$(COMMENT + $(OL + + $(LI Programmers, especially inexperienced ones, tend to neglect + to test for the special error return value. + Their code just assumed the function completed successfully. + This leads to erratic and unpredictable + behavior if the function did fail.) + + $(LI How each function deals with errors tends to be unique and + inconsistent, leading to more unintended + programmatic errors.) + + $(LI How the error gets reported to the user tends to vary + arbitrarily from one program to the next and one + error case to the next.) + + $(LI Dealing with error cases causes tedious and error-prone code + to be written, and so can consume much + programming effort.) + + $(LI Error handling logic tends to be buggy because it rarely + gets tested by the test team.) + + $(LI Functions that should have clean interfaces wind up + cluttering them with error return parameters and + cases.) + + ) +) + +$(SPEC_SUBNAV_PREV_NEXT traits, Traits, unittest, Unit Tests) +) + +Macros: + CHAPTER=27 + TITLE=Errors diff --git a/spec/expression.dd b/spec/expression.dd new file mode 100644 index 0000000000..b3600db952 --- /dev/null +++ b/spec/expression.dd @@ -0,0 +1,3872 @@ +Ddoc + +$(SPEC_S Expressions, + +$(HEADERNAV_TOC) + +$(H2 $(LEGACY_LNAME2 Expression, expression, Expressions)) + +$(GRAMMAR +$(GNAME Expression): + $(GLINK CommaExpression) +) + +$(P An expression is a sequence of operators and operands that specifies an evaluation. +The syntax, order of evaluation, and semantics of expressions are as follows.) + + $(P Expressions are used to compute values with a resulting type. + These values can then be assigned, + tested, or ignored. Expressions can also have side effects. + ) + +$(H2 $(LNAME2 definitions-and-terms, Definitions and Terms)) + +$(H3 $(LNAME2 .define-full-expression, Full Expression)) + +$(P For any expression +$(I expr), the full expression of $(I expr) is defined as follows. If $(I expr) parses as a +subexpression of another expression $(I expr$(SUBSCRIPT 1)), then the full expression of $(I expr) is the +full expression of $(I expr$(SUBSCRIPT 1)). Otherwise, $(I expr) is its own full expression.) + +$(P Each expression has a unique full expression. Example:) + +--- +return f() + g() * 2; +--- + +$(P The full expression of `g() * 2` above is `f() + g() * 2`, but not the +full expression of `f() + g()` because the latter is not parsed as a subexpression.) + +$(P Note: Although the definition is straightforward, a few subtleties exist related to function literals:) + +--- +return (() => x + f())() * g(); +--- + +$(P The full expression of `f()` above is `x + f()`, not the expression passed +to `return`. This is because the parent of `x + f()` has function literal type, not expression type.) + +$(H3 $(LNAME2 .define-lvalue, Lvalue)) + +$(P The following expressions, and no others, are called *lvalue expressions* or *lvalues*:) +$(OL +$(LI $(RELATIVE_LINK2 this, `this`) inside `struct` and `union` member functions;) +$(LI a variable, function name, or invocation of a function that +$(DDSUBLINK spec/function, ref-functions, returns by reference);) +$(LI the result of the `.` $(GLINK PostfixExpression) and +$(DDSUBLINK spec/module, module_scope_operators, Module Scope Operator) +when the rightmost side of the dot is a variable, +field (direct or `static`), function name, or invocation of a function that returns by reference;) +$(LI the result of the following expressions: +$(UL +$(LI built-in $(RELATIVE_LINK2 unary-expression, unary operators) `+` (when applied to an lvalue), `*`, `++` (prefix only), `--` (prefix only);) +$(LI built-in $(RELATIVE_LINK2 index_expressions, indexing operator) `[]` (but not the slicing operator);) +$(LI built-in $(RELATIVE_LINK2 assign_expressions, assignment operators), i.e. `=`, `+=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `~=`, +`<<=`, `>>=`, `>>>=`, and `^^=`;) +$(LI $(DDLINK spec/operatoroverloading, Operator Overloading, user-defined operators) +if and only if the function called as a result of lowering returns +by reference;) +$(LI the $(GLINK ConditionalExpression) operator $(I e) `?` $(I e$(SUBSCRIPT 1)) `:` $(I e$(SUBSCRIPT 2)) under the following +circumstances:) +$(OL + $(LI $(I e$(SUBSCRIPT 1)) and $(I e$(SUBSCRIPT 2)) are lvalues of the same type; OR) + $(LI One of $(I e$(SUBSCRIPT 1)) and $(I e$(SUBSCRIPT 2)) is an lvalue of type `T` and the other has + an `alias this` which converts it to an lvalue of `T`;)) +$(LI $(RELATIVE_LINK2 mixin_expressions, `mixin` expressions) if and only if the +compilation of the expression resulting from compiling +the argument(s) to `mixin` is an lvalue;) +$(LI $(RELATIVE_LINK2 cast_expressions, `cast(U)` expressions) applied to lvalues +of type `T` when `T*` is implicitly convertible to `U*`;) +$(LI $(RELATIVE_LINK2 cast_qualifier, `cast(`$(I TypeCtors)$(OPT)`)`) when applied to an lvalue.) +))) + +$(H3 $(LNAME2 .define-rvalue, Rvalue)) + +$(P Expressions that are not lvalues are *rvalues*. Rvalues include all literals, special value keywords such as `__FILE__` and `__LINE__`, +`enum` values, and the result of expressions not defined as lvalues above.) + +$(P The built-in address-of operator (unary `&`) may only be applied to lvalues.) + +$(H3 $(LNAME2 .define-smallest-short-circuit, Smallest Short-Circuit Expression)) + +$(P Given an expression $(I expr) that is a subexpression of a full +expression $(I fullexpr), the *smallest short-circuit expression*, if any, is the shortest +subexpression $(I scexpr) of $(I fullexpr) that is an $(GLINK AndAndExpression) (`&&`) or an +$(GLINK OrOrExpression) (`||`), such that $(I expr) is a subexpression of $(I scexpr). Example:) +--- +((f() * 2 && g()) + 1) || h() +--- +$(P The smallest short-circuit expression +of the subexpression `f() * 2` above is `f() * 2 && g()`. Example:) +--- +(f() && g()) + h() +--- +$(P The subexpression `h()` above has no smallest short-circuit expression.) + + +$(H2 $(LNAME2 order-of-evaluation, Order Of Evaluation)) + +$(BEST_PRACTICE Even when the order of evaluation is well-defined, writing code that +depends on it is rarely recommended.) + +$(H3 $(LNAME2 order-increment, Increment and Decrement)) + +$(P Built-in prefix unary expressions `++` and `--` are evaluated as if lowered (rewritten) to +$(RELATIVE_LINK2 assignment_operator_expressions, assignments) as follows:) + +$(TABLE + $(THEAD Expression, Equivalent) + $(TROW `++expr`, `((expr) += 1)`) + $(TROW `--expr`, `((expr) -= 1)`) +) +$(P +Therefore, the result of prefix `++` and `--` is the lvalue after the side effect has been +effected.) + +$(P Built-in postfix unary expressions `++` and `--` are evaluated as if lowered (rewritten) to +$(DDSUBLINK spec/expression, function_literals, lambda) +invocations as follows:) + +$(TABLE + $(THEAD Expression, Equivalent) + $(TROW `expr++`, `(ref x){auto t = x; ++x; return t;}(expr)`) + $(TROW `expr--`, `(ref x){auto t = x; --x; return t;}(expr)`) +) +$(P Therefore, the result of postfix +`++` and `--` is an rvalue just before the side effect has been effected.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +int i = 0; +assert(++i == 1); +assert(i++ == 1); +assert(i == 2); + +int* p = [1, 2].ptr; +assert(*p++ == 1); +assert(*p == 2); +--- +) + +$(H3 $(LNAME2 order-binary, Binary Expressions)) + +$(P Binary expressions except for $(GLINK AssignExpression), $(GLINK OrOrExpression), and +$(GLINK AndAndExpression) are evaluated in lexical order (left-to-right). Example:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------------- +int i = 2; +i = ++i * i++ + i; +assert(i == 3 * 3 + 4); +------------- +) + +$(P $(GLINK OrOrExpression) and $(GLINK AndAndExpression) evaluate their left-hand side argument +first. Then, $(GLINK OrOrExpression) evaluates its right-hand side if and only if its left-hand +side does not evaluate to nonzero. $(GLINK AndAndExpression) evaluates its right-hand side if and +only if its left-hand side evaluates to nonzero.) + + $(IMPLEMENTATION_DEFINED The order of evaluation of the operands of $(GLINK AssignExpression).) + +$(H3 $(LNAME2 order-conditional, Conditional Expressions)) + +$(P $(GLINK ConditionalExpression) evaluates its left-hand side argument +first. Then, if the result is nonzero, the second operand is evaluated. Otherwise, the third operand +is evaluated.) + +$(H3 $(LNAME2 order-calls, Function Calls)) + +$(P Calls to functions with `extern(D)` $(DDSUBLINK spec/attribute, linkage, linkage) (which is +the default linkage) are evaluated in the following order:) +1. If necessary, the address of the + function to call is evaluated (e.g. in the case of a computed function pointer or delegate). +1. Arguments are evaluated left to right. +1. Transfer of execution is passed to the function. + +$(P Example calling a $(DDSUBLINK spec/function, function-pointers, function pointer):) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +void function(int a, int b, int c) fun() +{ + writeln("fun() called"); + static void r(int a, int b, int c) { writeln("callee called"); } + return &r; +} +int f1() { writeln("f1() called"); return 1; } +int f2() { writeln("f2() called"); return 2; } +int f3(int x) { writeln("f3() called"); return x + 3; } +int f4() { writeln("f4() called"); return 4; } + +// evaluates fun() then f1() then f2() then f3() then f4() +// after which control is transferred to the callee +fun()(f1(), f3(f2()), f4()); +--- +) + + $(IMPLEMENTATION_DEFINED The order of evaluation of function arguments for functions with linkage other than `extern(D)`.) + + +$(H2 $(LNAME2 temporary-lifetime, Lifetime of Temporaries)) + +$(P Expressions and statements may create and/or consume rvalues. Such values are called +$(I temporaries) and do not have a name or a visible scope. Their lifetime is managed automatically +as defined in this section.) + +$(P For each evaluation that yields a temporary value, the lifetime of that temporary begins at the +evaluation point, similarly to creation of a usual named value initialized with an expression.) + +$(P Termination of lifetime of temporaries does not obey the customary scoping rules and is defined +as follows:) + +$(UL +$(LI If: +$(OL $(LI the full expression has a smallest short-circuit expression $(I expr); and) +$(LI the temporary is created on the right-hand side of the `&&` or `||` operator; and) +$(LI the right-hand side is evaluated,)) +then temporary destructors are evaluated right after the right-hand side +expression has been evaluated and converted to `bool`. Evaluation of destructors proceeds in +reverse order of construction.) + +$(LI For all other cases, the temporaries generated for the purpose of invoking functions are +deferred to the end of the full expression. The order of destruction is inverse to the order of +construction.)) + +$(P If a subexpression of an expression throws an exception, all temporaries created up to the +evaluation of that subexpression will be destroyed per the rules above. No destructor calls will +be issued for temporaries not yet constructed.) + +$(P Note: An intuition behind these rules is that destructors of temporaries are deferred to the end of full +expression and in reverse order of construction, with the exception that the right-hand side of +`&&` and `||` are considered their own full expressions even when part of larger expressions.) + +$(P Note: The $(GLINK ConditionalExpression) $(I e$(SUBSCRIPT 1) ? e$(SUBSCRIPT 2) : e$(SUBSCRIPT 3)) is not +a special case although it evaluates expressions conditionally: $(I e$(SUBSCRIPT 1)) and one of +$(I e$(SUBSCRIPT 2)) and $(I e$(SUBSCRIPT 3)) may create temporaries. Their destructors are inserted +to the end of the full expression in the reverse order of creation.) + +$(P Example:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +struct S +{ + int x; + this(int n) { x = n; writefln("S(%s)", x); } + ~this() { writefln("~S(%s)", x); } +} + +void main() +{ + bool b = (S(1) == S(2) || S(3) != S(4)) && S(5) == S(6); +} +--- +) + +The output of the code above is: + +$(CONSOLE +S(1) +S(2) +S(3) +S(4) +~S(4) +~S(3) +S(5) +S(6) +~S(6) +~S(5) +~S(2) +~S(1) +) + +First, `S(1)` and `S(2)` are evaluated in lexical order. Per the rules, they will be destroyed at +the end of the full expression and in reverse order. The comparison $(D S(1) == S(2)) yields +`false`, so the right-hand side of the `||` is evaluated causing `S(3)` and `S(4)` to be evaluated, +also in lexical order. However, their destruction is not deferred to the end of the full +expression. Instead, `S(4)` and then `S(3)` are destroyed at the end of the `||` expression. +Following their destruction, `S(5)` and `S(6)` are constructed in lexical order. Again they are not +destroyed at the end of the full expression, but right at the end of the `&&` expression. +Consequently, the destruction of `S(6)` and `S(5)` is carried before that of `S(2)` and `S(1)`. + +$(H2 $(LNAME2 comma_expression, Comma Expression)) + +$(GRAMMAR +$(GNAME CommaExpression): + $(GLINK AssignExpression) + $(GSELF CommaExpression) $(D ,) $(GLINK AssignExpression) +) + + $(P The left operand of the $(D ,) is evaluated, then the right operand + is evaluated. + In C, the result of a comma expression is the result of the right operand. + In D, using the result of a comma expression isn't allowed. + Consequently a comma expression is only useful when each operand has + a side effect. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +int x, y; +// expression statement +x = 1, y = 1; +// evaluate a comma expression at the end of each loop iteration +for (; y < 10; x++, y *= 2) + writefln("%s, %s", x, y); +--- +) + $(RATIONALE The comma expression has been used unintentionally, either by + bracket nesting mistakes or when users expect a sequence of arguments instead + of a single expression. Those bugs can be hard to detect in code review. + Disallowing use of the result turns those bugs into errors.) + + +$(H2 $(LNAME2 assign_expressions, Assign Expressions)) + +$(GRAMMAR +$(GNAME AssignExpression): + $(GLINK ConditionalExpression) + $(GLINK ConditionalExpression) $(D =) $(GSELF AssignExpression) + $(GLINK ConditionalExpression) $(D +=) $(GSELF AssignExpression) + $(GLINK ConditionalExpression) $(D -=) $(GSELF AssignExpression) + $(GLINK ConditionalExpression) $(D *=) $(GSELF AssignExpression) + $(GLINK ConditionalExpression) $(D /=) $(GSELF AssignExpression) + $(GLINK ConditionalExpression) $(D %=) $(GSELF AssignExpression) + $(GLINK ConditionalExpression) $(D &=) $(GSELF AssignExpression) + $(GLINK ConditionalExpression) $(D |=) $(GSELF AssignExpression) + $(GLINK ConditionalExpression) $(D ^=) $(GSELF AssignExpression) + $(GLINK ConditionalExpression) $(D ~=) $(GSELF AssignExpression) + $(GLINK ConditionalExpression) $(D <<=) $(GSELF AssignExpression) + $(GLINK ConditionalExpression) $(D >>=) $(GSELF AssignExpression) + $(GLINK ConditionalExpression) $(D >>>=) $(GSELF AssignExpression) + $(GLINK ConditionalExpression) $(D ^^=) $(GSELF AssignExpression) +) + + $(P For all assign expressions, the left operand must be a modifiable + lvalue. The type of the assign expression is the type of the left + operand, and the result is the value of the left operand after assignment + occurs. The resulting expression is a modifiable lvalue. + ) + + $(UNDEFINED_BEHAVIOR + If either operand is a reference type and one of the following: + $(OL + $(LI the operands have partially overlapping storage) + $(LI the operands' storage overlaps exactly but the types are different) + )) + + $(IMPLEMENTATION_DEFINED + If neither operand is a reference type and one of the following: + $(OL + $(LI the operands have partially overlapping storage) + $(LI the operands' storage overlaps exactly but the types are different) + )) + +$(H3 $(LNAME2 simple_assignment_expressions, Simple Assignment Expression)) + + $(P If the operator is $(D =) then it is simple assignment. + ) + + $(UL + $(LI If the left operand is a struct that + $(DDSUBLINK spec/operatoroverloading, assignment, defines `opAssign`), + the behaviour is defined by the overloaded function. + ) + + $(LI If the left and right operands are of the same struct type, and the struct + type has a $(GLINK2 struct, Postblit), then the copy operation is + as described in $(DDSUBLINK spec/struct, struct-postblit, Struct Postblit). + ) + + $(LI If the lvalue is the `.length` property of a dynamic array, the behavior is + as described in $(DDSUBLINK spec/arrays, resize, Setting Dynamic Array Length). + ) + + $(LI If the left operand is a slice expression, the behavior is as + described in $(DDSUBLINK spec/arrays, array-copying, Array Copying) and + $(DDSUBLINK spec/arrays, array-setting, Array Filling). + ) + + $(LI If the lvalue is an array, the behavior is as described in + $(DDSUBLINK spec/arrays, assignment, Array Assignment). + ) + + $(LI If the lvalue is a user-defined property, the behavior is as + described in $(DDSUBLINK spec/function, property-functions, Property Functions). + ) + ) + + $(P Otherwise, the right operand is implicitly converted to the type of the + left operand, and assigned to it.) + +$(H3 $(LNAME2 assignment_operator_expressions, Assignment Operator Expressions)) + + $(P For arguments of built-in types, assignment operator expressions such as) + + -------------- + a op= b + -------------- + + are semantically equivalent to: + + -------------- + a = cast(typeof(a))(a op b) + -------------- + + except that: + + $(UL + $(LI operand $(D a) is only evaluated once,) + $(LI overloading $(I op) uses a different function than overloading $(I op)`=` does, and) + $(LI the left operand of $(D >>>=) does not undergo $(INTEGER_PROMOTIONS) before shifting.) + ) + + $(P Narrowing conversions are allowed. Truncating conversions will be an error.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + void f(short s) + { + byte b; + b += s; // OK, though it may overflow + //b += 1.5F; // Deprecated, truncation + } + --- + ) + + $(P For user-defined types, assignment operator expressions are + $(DDSUBLINK spec/operatoroverloading, op-assign, overloaded separately) from + the binary operators. Still the left operand must be an lvalue. + ) + +$(H2 $(LNAME2 conditional_expressions, Conditional Expressions)) + +$(GRAMMAR +$(GNAME ConditionalExpression): + $(GLINK OrOrExpression) + $(GLINK OrOrExpression) $(D ?) $(GLINK Expression) $(D :) $(GSELF ConditionalExpression) +) + + $(P The first expression is $(DDSUBLINK spec/statement, boolean-conditions, + converted to $(D bool)), and is evaluated. + ) + + $(P If it is $(D true), then the second expression is evaluated, and + its result is the result of the conditional expression. + ) + + $(P If it is $(D false), then the third expression is evaluated, and + its result is the result of the conditional expression. + ) + + $(P If either the second or third expressions are of type $(D void), + then the resulting type is $(D void). Otherwise, the second and third + expressions are implicitly converted to a common type which becomes + the result type of the conditional expression. + ) + + $(PANEL + $(NOTE + When a conditional expression is the left operand of + an $(RELATIVE_LINK2 assign_expressions, assign expression), + parentheses are required for disambiguation: + ) + --- + bool test; + int a, b, c; + ... + test ? a = b : c = 2; // error + (test ? a = b : c) = 2; // OK + --- + + $(P This makes the intent clearer, because the first statement can + easily be misread as the following code: + ) + --- + test ? a = b : (c = 2); + --- + ) + +$(H2 $(LNAME2 logical_expressions, Logical Expressions)) + +$(DDOC_SEE_ALSO $(GLINK UnaryExpression) for `!expr`.) + +$(H3 $(LNAME2 oror_expressions, OrOr Expressions)) + +$(GRAMMAR +$(GNAME OrOrExpression): + $(GLINK AndAndExpression) + $(GSELF OrOrExpression) $(D ||) $(GLINK AndAndExpression) +) + + $(P The result type of an $(I OrOrExpression) is $(D bool), unless the right operand + has type $(D void), when the result is type $(D void). + ) + + $(P The $(I OrOrExpression) evaluates its left operand. + ) + + $(P If the left operand, $(DDSUBLINK spec/statement, boolean-conditions, + converted to type $(D bool)), evaluates to + $(D true), then the right operand is not evaluated. If the result type of + the $(I OrOrExpression) is $(D bool) then the result of the + expression is $(D true). + ) + + $(P If the left operand is $(D false), then the right + operand is evaluated. + If the result type of + the $(I OrOrExpression) is $(D bool) then the result of the + expression is the right operand converted to type $(D bool). + ) + +$(H3 $(LNAME2 andand_expressions, AndAnd Expressions)) + +$(GRAMMAR +$(GNAME AndAndExpression): + $(GLINK OrExpression) + $(GSELF AndAndExpression) $(D $(AMP)$(AMP)) $(GLINK OrExpression) +) + + $(P The result type of an $(I AndAndExpression) is $(D bool), unless the right operand + has type $(D void), when the result is type $(D void). + ) + + $(P The $(I AndAndExpression) evaluates its left operand. + ) + + $(P If the left operand, $(DDSUBLINK spec/statement, boolean-conditions, + converted to type $(D bool)), evaluates to + $(D false), then the right operand is not evaluated. If the result type of + the $(I AndAndExpression) is $(D bool) then the result of the + expression is $(D false). + ) + + $(P If the left operand is $(D true), then the right + operand is evaluated. + If the result type of + the $(I AndAndExpression) is $(D bool) then the result of the + expression is the right operand converted to type $(D bool). + ) + +$(H2 $(LNAME2 bitwise_expressions, Bitwise Expressions)) + + $(P Bit wise expressions perform a + $(LINK2 https://en.wikipedia.org/wiki/Bitwise_operation, bitwise operation) on their operands. + Their operands must be integral types. + First, the $(USUAL_ARITHMETIC_CONVERSIONS) are done. Then, the bitwise + operation is done. + ) + $(DDOC_SEE_ALSO $(GLINK ShiftExpression), $(GLINK ComplementExpression)) + + $(PANEL + $(NOTE If an *OrExpression*, *XorExpression* or *AndExpression* appears on + either side of an *EqualExpression*, *IdentityExpression* or *RelExpression*, + it is a compile error. Instead, disambiguate by using parentheses. + ) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +int x, a, b; +x = a & 5 == b; // error +x = a & 5 is b; // error +x = a & 5 <= b; // error + +x = (a & 5) == b; // OK +x = a & (5 == b); // OK +--- +) +) + +$(H3 $(LNAME2 or_expressions, Or Expressions)) + +$(GRAMMAR +$(GNAME OrExpression): + $(GLINK XorExpression) + $(GSELF OrExpression) $(D |) $(GLINK XorExpression) +) + + $(P The operands are OR'd together.) + +$(H3 $(LNAME2 xor_expressions, Xor Expressions)) + +$(GRAMMAR +$(GNAME XorExpression): + $(GLINK AndExpression) + $(GSELF XorExpression) $(D ^) $(GLINK AndExpression) +) + + $(P The operands are XOR'd together.) + +$(H3 $(LNAME2 and_expressions, And Expressions)) + +$(GRAMMAR +$(GNAME AndExpression): + $(GLINK CmpExpression) + $(GSELF AndExpression) $(D &) $(GLINK CmpExpression) +) + + $(P The operands are AND'd together.) + +$(H2 $(LNAME2 compare_expressions, Compare Expressions)) + +$(GRAMMAR +$(GNAME CmpExpression): + $(GLINK EqualExpression) + $(GLINK IdentityExpression) + $(GLINK RelExpression) + $(GLINK InExpression) + $(GLINK ShiftExpression) +) + +$(H3 $(LNAME2 equality_expressions, Equality Expressions)) + +$(GRAMMAR +$(GNAME EqualExpression): + $(GLINK ShiftExpression) $(D ==) $(GLINK ShiftExpression) + $(GLINK ShiftExpression) $(D !=) $(GLINK ShiftExpression) +) + + $(P Equality expressions compare the two operands for equality ($(D ==)) + or inequality ($(D !=)). + The type of the result is $(D bool). + ) + + $(P Inequality is defined as the logical negation of equality.) + + - If the operands are integral values, the $(USUAL_ARITHMETIC_CONVERSIONS) are applied + to bring them to a common type before comparison. Equality is defined as the bit patterns + of the common type match exactly. + + - If the operands are pointers, equality is defined as the bit patterns of the operands + match exactly. Both types must match, or one can be `typeof(null)`. + + - For float, double, and real values, the $(USUAL_ARITHMETIC_CONVERSIONS) are applied + to bring them to a common type before comparison. + The values $(D -0) and $(D +0) are considered equal. + If either or both operands are NaN, then $(D ==) returns false and $(D !=) returns $(D true). + Otherwise, the bit patterns of the common type are compared for equality. + + - For static and dynamic arrays, equality is defined as the + lengths of the arrays + matching, and the elements in each compare equal. + The element types must have a common type. + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + assert(5 == 5L); + assert(byte(4) == 4F); + + int i = 1, j = 1; + assert(&i != &j); + assert(&i != null); + + // elements of different types are comparable, even when different sizes + int[] ia = ['A', 'B', 'C']; + assert(ia == "ABC"); + byte[] ba = [1, 2]; + assert(ba == [1F, 2F]); + --- + ) + + $(DDOC_DEPRECATED For complex numbers, equality is defined as equivalent to:) + + --- + x.re == y.re && x.im == y.im + --- + + $(H4 $(LNAME2 class_struct_equality, Class & Struct Equality)) + + $(P For class references, `a == b` is rewritten to `.object.opEquals(a, b)`, + which handles `null`. + This is intended to compare the contents of two objects, however an + appropriate $(D opEquals) method override must be defined for this to work. + The default $(D opEquals) provided by the root $(D Object) class is + equivalent to the $(RELATIVE_LINK2 identity_expressions, $(D is) operator).) + + $(P For struct objects, the expression $(D (a == b)) + is rewritten as $(D a.opEquals(b)), or failing that, $(D b.opEquals(a)).) + + $(P For both class references and struct objects, $(D (a != b)) is rewritten as + $(D !(a == b)).) + + $(P See $(DDSUBLINK spec/operatoroverloading, equals, `opEquals`) for details.) + + $(H5 $(LNAME2 struct_equality, Struct Equality)) + + $(P For struct objects, equality means the result of the + $(LINK2 https://dlang.org/spec/operatoroverloading.html#equals, `opEquals()` member function). + If an `opEquals()` is not provided, one will be generated. + Equality is defined as the logical product of all equality + results of the corresponding object fields. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + struct S + { + int i = 4; + string s = "four"; + } + + S s; + assert(s == S()); + s.s = "foul"; + assert(s != S()); + --- + ) + + $(IMPLEMENTATION_DEFINED The contents of any $(DDSUBLINK spec/struct, struct_layout, + alignment gaps) in the struct object.) + + $(P If there are overlapping fields, which happens with unions, the default + equality will compare each of the overlapping fields.) + + $(BEST_PRACTICE + An `opEquals()` can account for which of the overlapping fields contains valid data. + An `opEquals()` can override the default behavior of floating point NaN values + always comparing as unequal. + Be careful using `memcmp()` to implement `opEquals()` if:) + + $(UL + $(LI there are any alignment gaps) + $(LI any fields have an `opEquals()`) + $(LI there are any floating point fields that may contain NaN or `-0` values) + ) + +$(H3 $(LNAME2 identity_expressions, Identity Expressions)) + +$(GRAMMAR +$(GNAME IdentityExpression): + $(GLINK ShiftExpression) $(D is) $(GLINK ShiftExpression) + $(GLINK ShiftExpression) $(D ! is) $(GLINK ShiftExpression) +) + + $(P The $(D is) operator compares for identity of expression values. + To compare for nonidentity, use $(D e1 !is e2). + The type of the result is $(D bool). The operands + undergo the $(USUAL_ARITHMETIC_CONVERSIONS) to bring them to a common type before + comparison. + ) + + $(P For class / interface objects, identity is defined as the object references being identical. + Class references can be efficiently compared against `null` using `is`. + Note that interface objects need not have the same reference of the class they were cast from. + To test whether an `interface` shares a class instance with another `interface` / `class` value, cast both operands to `Object` before comparing with `is`. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + interface I { void g(); } + interface I1 : I { void g1(); } + interface I2 : I { void g2(); } + interface J : I1, I2 { void h(); } + + class C : J + { + override void g() { } + override void g1() { } + override void g2() { } + override void h() { } + } + + void main() @safe + { + C c = new C; + I i1 = cast(I1) c; + I i2 = cast(I2) c; + assert(i1 !is i2); // not identical + assert(c !is i2); // not identical + assert(cast(Object) i1 is cast(Object) i2); // identical + } + --- + ) + + $(P For struct objects and floating point values, identity is defined as the + bits in the operands being identical. + ) + + $(P For static and dynamic arrays, identity of two arrays is given when + both arrays refer to the same memory location and contain the same number + of elements. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + Object o; + assert(o is null); + + auto a = [1, 2]; + assert(a is a[0..$]); + assert(a !is a[0..1]); + + auto b = [1, 2]; + assert(a !is b); + --- + ) + + $(DDOC_DEPRECATED Use of `is` to compare static arrays by address and + length is deprecated. To do so, use the slice operator and compare slices + of the arrays instead; for example, `a1[] is a2[]`.) + + $(P For other operand types, identity is defined as being the same + as equality. + ) + + $(P The identity operator $(D is) cannot be overloaded. + ) + +$(H3 $(LNAME2 relation_expressions, Relational Expressions)) + +$(GRAMMAR +$(GNAME RelExpression): + $(GLINK ShiftExpression) $(D <) $(GLINK ShiftExpression) + $(GLINK ShiftExpression) $(D <=) $(GLINK ShiftExpression) + $(GLINK ShiftExpression) $(D >) $(GLINK ShiftExpression) + $(GLINK ShiftExpression) $(D >=) $(GLINK ShiftExpression) +) + + $(P First, the $(USUAL_ARITHMETIC_CONVERSIONS) are done on the operands. + The result type of a relational expression is $(D bool). + ) + +$(H3 $(LNAME2 array_comparisons, Array Comparisons)) + + $(P For static and dynamic arrays, the result of a *CmpExpression* + is the result of the operator applied to the first non-equal + element of the array. If two arrays compare equal, but are of + different lengths, the shorter array compares as "less" than the + longer array. + ) + +$(H3 $(LNAME2 integer_comparisons, Integer Comparisons)) + + $(P Integer comparisons happen when both operands are integral + types. + ) + + $(TABLE2 Integer comparison operators, + $(THEAD Operator, Relation) + $(TROW $(D <), less) + $(TROW $(D >), greater) + $(TROW $(D <)$(D =), less or equal) + $(TROW $(D >=), greater or equal) + $(TROW $(D ==), equal) + $(TROW $(D !=), not equal) + ) + + $(P It is an error to have one operand be signed and the other + unsigned for a $(D <), $(D <)$(D =), $(D >) or + $(D >)$(D =) expression. + Use $(RELATIVE_LINK2 cast_integers, casts) to make both operands signed or both operands unsigned. + ) + +$(H3 $(LEGACY_LNAME2 floating_point_comparisons, floating-point-comparisons, Floating Point Comparisons)) + + $(P If one or both operands are floating point, then a floating + point comparison is performed. + ) + + $(P A *CmpExpression* can have `NaN` operands. + If either or both operands is `NaN`, the floating point + comparison operation returns as follows:) + + $(TABLE2 Floating point comparison operators, + $(THEAD Operator, Relation, Returns) + $(TROW $(D <),$(ARGS less), `false`) + $(TROW $(D >),$(ARGS greater), `false`) + $(TROW $(D <)$(D =),$(ARGS less or equal), `false`) + $(TROW $(D >=),$(ARGS greater or equal), `false`) + $(TROW $(D ==),equal, `false`) + $(TROW $(D !=),$(ARGS unordered, less, or greater), `true`) + ) + + $(BEST_PRACTICE Although *IdentityExpression* can be used to check for `T.nan`, + there are other floating-point values for NaN produced at runtime. + Use $(REF isNaN, std,math,traits) to handle all of them.) + +$(H3 $(LEGACY_LNAME2 class_comparisons, class-comparisons, Class and Struct Comparisons)) + + $(P For struct objects, a *RelExpression* performs a comparison which first + evaluates $(DDSUBLINK spec/operatoroverloading, compare, a matching `opCmp` + method) call.) + + $(P For class references, a *RelExpression* performs a comparison which first + evaluates to an `int` which is either:) + + - `0` if the two object references are identical + - `-1` if the left-hand expression is `null` + - `1` if the right-hand expression is `null` + - the result of $(DDSUBLINK spec/operatoroverloading, compare, + a matching `opCmp`) call + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + class C + { + override int opCmp(Object o) { assert(0); } + } + + void main() + { + C c; + //if (c < null) {} // compile-time error + assert(c is null); + assert(c < new C); // C.opCmp is not called + } + --- + ) + + $(P Secondly, for class and struct objects, the evaluated `int` is compared + against zero using the given operator, which forms the result of the + *RelExpression*. For more information, see + $(DDSUBLINK spec/operatoroverloading, compare, `opCmp`).) + + +$(H2 $(LNAME2 in_expressions, In Expressions)) + +$(GRAMMAR +$(GNAME InExpression): + $(GLINK ShiftExpression) $(D in) $(GLINK ShiftExpression) + $(GLINK ShiftExpression) $(D ! in) $(GLINK ShiftExpression) +) + +$(P A container such as an associative array + $(DDSUBLINK spec/hash-map, testing_membership, can be tested) to see if it contains a certain key:) + + ------------- + int[string] foo; + ... + if ("hello" in foo) + { + // the string was found + } + ------------- + + $(P The result of an $(I InExpression) is a pointer for associative + arrays. + The pointer is $(D null) if the container has no matching key. + If there is a match, the pointer points to a value associated + with the key. + ) + + $(P The $(D !in) expression is the logical negation of the $(D in) + operation. + ) + + $(P The $(D in) expression has the same precedence as the + relational expressions $(D <), $(D <)$(D =), etc.) + + $(NOTE When $(DDSUBLINK spec/operatoroverloading, binary, overloading) + `in`, normally only $(TT opBinaryRight) would be defined. This is + because the operation is usually not defined by the key type but by + the container, which appears on the right hand side of the `in` + operator.) + +$(H2 $(LNAME2 shift_expressions, Shift Expressions)) + +$(GRAMMAR +$(GNAME ShiftExpression): + $(GLINK AddExpression) + $(GSELF ShiftExpression) $(D <<) $(GLINK AddExpression) + $(GSELF ShiftExpression) $(D >>) $(GLINK AddExpression) + $(GSELF ShiftExpression) $(D >>>) $(GLINK AddExpression) +) + + $(P The operands must be integral types, and undergo the $(INTEGER_PROMOTIONS). + The result type is the type of the left operand after + the promotions. The result value is the result of shifting the bits + by the right operand's value. + ) + + $(UL + $(LI $(D <)$(D <) is a left shift.) + $(LI $(D >)$(D >) is a signed right shift.) + $(LI $(D >)$(D >)$(D >) is an unsigned right shift.) + ) + + $(IMPLEMENTATION_DEFINED + The result of a shift by a negative value or by the same or more bits + than the size of the quantity being shifted is undefined. + When the shift amount is known at compile time, doing this results in + a compile error. + + ------------- + int c; + + int s = -3; + auto y = c << s; // implementation defined value + + auto x = c << 33; // error, max shift count allowed is 31 + ------------- + ) + +$(H2 $(LNAME2 additive_expressions, Additive Expressions)) + +$(GRAMMAR +$(GNAME AddExpression): + $(GLINK MulExpression) + $(GSELF AddExpression) $(D +) $(GLINK MulExpression) + $(GSELF AddExpression) $(D -) $(GLINK MulExpression) + $(GSELF AddExpression) $(D ~) $(GLINK MulExpression) +) + +$(H3 $(LNAME2 add_expressions, Add Expressions)) + $(P In the cases of the Additive operations $(D +) and $(D -): + ) + + $(P If the operands are of integral types, they undergo the $(USUAL_ARITHMETIC_CONVERSIONS), + and then are brought to a common type using the + $(USUAL_ARITHMETIC_CONVERSIONS). + ) + + $(P If both operands are of integral types and an overflow or underflow + occurs in the computation, wrapping will happen. For example:) + $(UL + $(LI $(D uint.max + 1 == uint.min)) + $(LI $(D uint.min - 1 == uint.max)) + $(LI $(D int.max + 1 == int.min)) + $(LI $(D int.min - 1 == int.max)) + ) + + $(P If either operand is a floating point type, the other is implicitly + converted to floating point and they are brought to a common type + via the $(USUAL_ARITHMETIC_CONVERSIONS). + ) + + $(P Add expressions for floating point operands are not associative. + ) + + $(H4 $(LNAME2 pointer_arithmetic, Pointer Arithmetic)) + + $(P If the first operand is a pointer, and the second is an integral type, + the resulting type is the type of the first operand, and the resulting + value is the pointer plus (or minus) the second operand multiplied by + the size of the type pointed to by the first operand. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +int[] a = [1,2,3]; +int* p = a.ptr; +assert(*p == 1); + +*(p + 2) = 4; // same as `p[2] = 4` +assert(a[2] == 4); +--- +) + + $(P $(GLINK IndexOperation) can also be used with a pointer and has + the same behaviour as adding an integer, then dereferencing the result.) + + $(P If the second operand is a pointer, and the first is an integral type, + and the operator is $(D +), + the operands are reversed and the pointer arithmetic just described + is applied. + ) + + $(P Producing a pointer through pointer arithmetic is not allowed in + $(DDLINK spec/memory-safe-d, Memory-Safe-D-Spec, `@safe`) code.) + + $(P If both operands are pointers, and the operator is $(D +), + then it is illegal. + ) + + $(P If both operands are pointers, and the operator is $(D -), + the pointers are subtracted and the + result is divided by the size of the type pointed to by the + operands. In this calculation the assumed size of $(D void) is one byte. + It is an error if the pointers point to different types. + The type of the result is $(D ptrdiff_t). + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +int[] a = [1,2,3]; +ptrdiff_t d = &a[2] - a.ptr; +assert(d == 2); +--- +) + + +$(H3 $(LNAME2 cat_expressions, Cat Expressions)) + $(P In the case of the Additive operation $(D ~): + ) + + $(P A $(I CatExpression) concatenates a container's data with other data, producing + a new container.) + + $(P For a dynamic array, the other operand must either be another array or a + single value that implicitly converts to the element type of the array. + See $(DDSUBLINK spec/arrays, array-concatenation, Array Concatenation).) + +$(H2 $(LNAME2 mul_expressions, Mul Expressions)) + +$(GRAMMAR +$(GNAME MulExpression): + $(GLINK UnaryExpression) + $(GSELF MulExpression) $(D *) $(GLINK UnaryExpression) + $(GSELF MulExpression) $(D /) $(GLINK UnaryExpression) + $(GSELF MulExpression) $(D %) $(GLINK UnaryExpression) +) + + $(P The operands must be arithmetic types. + They undergo the $(USUAL_ARITHMETIC_CONVERSIONS). + ) + + $(P For integral operands, the $(D *), $(D /), and $(D %) + correspond to multiply, divide, and modulus operations. + For multiply, overflows are ignored and simply chopped to fit + into the integral type. + ) + +$(H3 $(LNAME2 division, Division)) + + $(P For integral operands of the $(D /) and $(D %) operators, + the quotient rounds towards zero and the remainder has the + same sign as the dividend. + ) + + $(P The following divide or modulus integral operands:) + + $(UL + $(LI denominator is 0) + $(LI signed `int.min` is the numerator and `-1` is the denominator) + $(LI signed `long.min` is the numerator and `-1L` is the denominator) + ) + + $(P are illegal if encountered during Compile Time Execution.) + + $(UNDEFINED_BEHAVIOR is exhibited if they are encountered during run time. + $(LINK2 https://dlang.org/phobos/core_checkedint.html, `core.checkedint`) + can be used to check for them and select a defined behavior. + ) + +$(H3 $(LNAME2 mul_floating, Floating Point)) + + $(P For floating point operands, the `*` and `/` operations correspond + to the IEEE 754 floating point equivalents. `%` is not the same as + the IEEE 754 remainder. For example, `15.0 % 10.0 == 5.0`, whereas + for IEEE 754, `remainder(15.0,10.0) == -5.0`. + ) + + $(P Mul expressions for floating point operands are not associative. + ) + +$(H2 $(LEGACY_LNAME2 UnaryExpression, unary-expression, Unary Expressions)) + +$(GRAMMAR +$(GNAME UnaryExpression): + $(D $(AMP)) $(GSELF UnaryExpression) + $(D ++) $(GSELF UnaryExpression) + $(D --) $(GSELF UnaryExpression) + $(D *) $(GSELF UnaryExpression) + $(D -) $(GSELF UnaryExpression) + $(D +) $(GSELF UnaryExpression) + $(D !) $(GSELF UnaryExpression) + $(GLINK ComplementExpression) + $(GLINK DeleteExpression) + $(GLINK CastExpression) + $(GLINK ThrowExpression) + $(GLINK PowExpression) +) + +$(TABLE + $(THEAD Operator, Description) + $(TROW `&`, Take memory address of an $(RELATIVE_LINK2 .define-lvalue, lvalue) - see $(DDSUBLINK spec/type, pointers, pointers)) + $(TROW `++`, Increment before use - see $(RELATIVE_LINK2 order-of-evaluation, order of evaluation)) + $(TROW `--`, Decrement before use) + $(TROW `*`, Dereference/indirection - typically for pointers) + $(TROW `-`, Negative) + $(TROW `+`, Positive) + $(TROW `!`, Logical NOT) +) + + $(P The usual $(INTEGER_PROMOTIONS) are performed prior to unary + `-` and `+` operations.) + +$(H3 $(LNAME2 complement_expressions, Complement Expressions)) + +$(GRAMMAR +$(GNAME ComplementExpression): + $(D ~) $(GLINK UnaryExpression) +) + + $(P $(I ComplementExpression)s work on integral types (except $(D bool)). + All the bits in the value are complemented. + The usual $(INTEGER_PROMOTIONS) are performed + prior to the complement operation. + ) + +$(H3 $(LNAME2 delete_expressions, Delete Expressions)) + +$(GRAMMAR +$(GNAME DeleteExpression): + $(D delete) $(GLINK UnaryExpression) +) + $(DDOC_DEPRECATED `delete` has been deprecated. Instead, please use $(REF1 destroy, object) + if feasible, or $(REF __delete, core, memory) as a last resort.) + + $(P If the $(I UnaryExpression) is a class object reference, and + there is a destructor for that class, the destructor + is called for that object instance. + ) + + $(P Next, if the $(I UnaryExpression) is a class object reference, or + a pointer to a struct instance, and the class or struct + has overloaded operator delete, then that operator delete is called + for that class object instance or struct instance. + ) + + $(P Otherwise, the garbage collector is called to immediately free the + memory allocated for the class instance or struct instance. + ) + + $(P If the $(I UnaryExpression) is a pointer or a dynamic array, + the garbage collector is called to immediately release the + memory. + ) + + $(P The pointer, dynamic array, or reference is set to $(D null) + after the delete is performed. + Any attempt to reference the data after the deletion via another + reference to it will result in undefined behavior. + ) + + $(P If $(I UnaryExpression) is a variable allocated + on the stack, the class destructor (if any) is called for that + instance. The garbage collector is not called. + ) + + $(UNDEFINED_BEHAVIOR + $(OL + $(LI Using `delete` to free memory not allocated by the garbage collector.) + $(LI Referring to data that has been the operand of `delete`.) + )) + +$(H3 $(LNAME2 cast_expressions, Cast Expressions)) + +$(GRAMMAR +$(GNAME CastExpression): + $(D cast $(LPAREN)) $(GLINK2 type, Type) $(D $(RPAREN)) $(GLINK UnaryExpression) + $(GLINK CastQual) +) + + $(P A $(I CastExpression) converts the $(I UnaryExpression) + to $(I Type).) + + ------------- + cast(foo) -p; // cast (-p) to type foo + (foo) - p; // subtract p from foo + ------------- + +$(H4 $(LNAME2 cast_basic_data_types, Basic Data Types)) + $(P For situations where $(DDSUBLINK spec/type, implicit-conversions, implicit conversions) + on basic types cannot be performed, the type system may be forced to accept the + reinterpretation of a memory region by using a cast. + ) + + $(P An example of such a scenario is represented by trying to store a wider type + into a narrower one: + ) + + ------------- + int a; + byte b = a; // cannot implicitly convert expression a of type int to byte + ------------- + + $(P When casting a source type that is wider than the destination type, + the value is truncated to the destination size. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + int a = 64389; // 00000000 00000000 11111011 10000101 + byte b = cast(byte) a; // 10000101 + ubyte c = cast(ubyte) a; // 10000101 + short d = cast(short) a; // 11111011 10000101 + ushort e = cast(ushort) a; // 11111011 10000101 + + writeln(b); + writeln(c); + writeln(d); + writeln(e); + ------------- + ) + + $(P For integral types casting from a narrower type to a wider type + is done by performing sign extension. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + ubyte a = 133; // 10000101 + byte b = a; // 10000101 + + writeln(a); + writeln(b); + + ushort c = a; // 00000000 10000101 + short d = b; // 11111111 10000101 + + writeln(c); + writeln(d); + ------------- + ) + + $(P See also: $(RELATIVE_LINK2 cast_integers, Casting Integers).) + +$(H4 $(LNAME2 cast_class, Class References)) + + $(P Any casting of a class reference to a + derived class reference is done with a runtime check to make sure it + really is a downcast. $(D null) is the result if it isn't. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + class A {} + class B : A {} + + void main() + { + A a = new A; + //B b = a; // error, need cast + B b = cast(B) a; // b is null if a is not a B + assert(b is null); + + a = b; // no cast needed + a = cast(A) b; // no runtime check needed for upcast + assert(a is b); + } + ------------- + ) + + $(P In order to determine if an object $(D o) is an instance of + a class $(D B) use a cast:) + + ------------- + if (cast(B) o) + { + // o is an instance of B + } + else + { + // o is not an instance of B + } + ------------- + + $(P Casting a pointer type to and from a class type is done as a type paint + (i.e. a reinterpret cast). + ) + +$(H4 $(LNAME2 cast_pointers, Pointers)) + $(P Casting a pointer variable to another pointer type modifies the value that + will be obtained as a result of dereferencing, along with the number of bytes + on which pointer arithmetic is performed. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + int val = 25185; // 00000000 00000000 01100010 01100001 + char *ch = cast(char*)(&val); + + writeln(*ch); // a + writeln(cast(int)(*ch)); // 97 + writeln(*(ch + 1)); // b + writeln(cast(int)(*(ch + 1))); // 98 + ------------- + ) + + $(P Similarly, when casting a dynamically allocated array to a type of smaller size, + the bytes of the initial array will be divided and regrouped according to the new + dimension. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + import core.stdc.stdlib; + + int *p = cast(int*) malloc(5 * int.sizeof); + for (int i = 0; i < 5; i++) { + p[i] = i + 'a'; + } + // p = [97, 98, 99, 100, 101] + + char* c = cast(char*) p; // c = [97, 0, 0, 0, 98, 0, 0, 0, 99 ...] + for (int i = 0; i < 5 * int.sizeof; i++) { + writeln(c[i]); + } + ------------- + ) + + $(P When casting a pointer of type A to a pointer of type B and type B is wider than type A, + attempts at accessing the memory exceeding the size of A will result in undefined behaviour. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + char c = 'a'; + int *p = cast(int*) (&c); + writeln(*p); + ------------- + ) + + $(P It is also possible to cast pointers to basic data types. + A common practice could be to cast the pointer to an int value + and then print its address: + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + import core.stdc.stdlib; + + int *p = cast(int*) malloc(int.sizeof); + int a = cast(int) p; + writeln(a); + ------------- + ) + + +$(H4 $(LNAME2 cast_array, Arrays)) + + --- + T[] a; + ... + cast(U[]) a + --- + $(P Casting a non-literal dynamic array `a` to another dynamic array type `U[]` + is allowed only when the result will contain every byte of data that was + referenced by `a`. + This is enforced with a runtime check that the byte length of `a`'s elements + is divisible by `U.sizeof`. If there is a remainder, a runtime error is generated. + The cast is done as a type paint, and the resulting array's length is set to + `(a.length * T.sizeof) / U.sizeof`.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + byte[] a = [1,2,3]; + //auto b = cast(int[])a; // runtime error: array cast misalignment + + int[] c = [1, 2, 3]; + auto d = cast(byte[])c; // ok + // prints: + // [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0] + writeln(d); + --- + ) + + $(UNDEFINED_BEHAVIOR Casting a non-literal array to `bool[]` when any + element has a byte representation $(DDSUBLINK spec/type, bool, other than 0 or 1).) + + $(P $(B See also:) $(RELATIVE_LINK2 cast_array_literal, Casting array literals).) + + $(P A slice of statically known length can be cast to a static array type when the + byte counts of their respective data match.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + void f(int[] b) + { + char[4] a; + static assert(!__traits(compiles, a = cast(char[4]) b)); // unknown length + static assert(!__traits(compiles, a = cast(char[4]) b[0..2])); // too many bytes + + a = cast(char[4]) b[0..1]; // OK + const i = 1; + a = cast(char[4]) b[i..2]; // OK + } + --- + ) + + $(P $(B See also:) $(RELATIVE_LINK2 slice_to_static_array, Slice conversion to static array).) + +$(H4 $(LNAME2 cast_static_array, Static Arrays)) + + $(P Casting a static array to another static array is done only if the + array lengths multiplied by the element sizes match; a mismatch + is illegal. + The cast is done as a type paint (aka a reinterpret cast). + The contents of the array are not changed.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + byte[16] b = 3; // set each element to 3 + assert(b[0] == 0x03); + int[4] ia = cast(int[4]) b; + // print elements as hex + foreach (i; ia) + writefln("%x", i); + /* prints: + 3030303 + 3030303 + 3030303 + 3030303 + */ + --- + ) + +$(H4 $(LNAME2 cast_integers, Integers)) + + $(P Casting an integer to a smaller integral will truncate the + value towards the least significant bits. + If the target type is signed and the most significant bit is set + after truncation, that bit will be lost from the value and + the sign bit will be set.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + uint a = 260; + auto b = cast(ubyte) a; + assert(b == 4); // truncated like 260 & 0xff + + int c = 128; + assert(cast(byte)c == -128); // reinterpreted + --- + ) + + $(P Converting between signed and unsigned types will reinterpret the + value if the destination type cannot represent the source + value.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + short c = -1; + ushort d = c; + assert(d == ushort.max); + assert(uint(c) == uint.max); + + ubyte e = 255; + byte f = e; + assert(f == -1); // reinterpreted + assert(short(e) == 255); // no change + --- + ) + +$(H4 $(LNAME2 cast_floating, Floating Point)) + + $(P Casting a floating point literal from one type to another + changes its type, but internally it is retained at full + precision for the purposes of constant folding.) + + --- + void test() + { + real a = 3.40483L; + real b; + b = 3.40483; // literal is not truncated to double precision + assert(a == b); + assert(a == 3.40483); + assert(a == 3.40483L); + assert(a == 3.40483F); + double d = 3.40483; // truncate literal when assigned to variable + assert(d != a); // so it is no longer the same + const double x = 3.40483; // assignment to const is not + assert(x == a); // truncated if the initializer is visible + } + --- + + $(P Casting a floating point value to an integral type is the equivalent + of converting to an integer using truncation. If the floating point + value is outside the range of the integral type, the cast will produce + an invalid result (this is also the case in C, C++).) + + --- + void main() + { + int a = cast(int) 0.8f; + assert(a == 0); + long b = cast(long) 1.5; + assert(b == 1L); + long c = cast(long) -1.5; + assert(c == -1); + + // if the float overflows, the cast returns the integer value of + // 80000000_00000000H (64-bit operand) or 80000000H (32-bit operand) + long d = cast(long) float.max; + assert(d == long.min); + int e = cast(int) (1234.5 + int.max); + assert(e == int.min); + + // for types represented on 16 or 8 bits, the result is the same as + // 32-bit types, but the most significant bits are ignored + short f = cast(short) float.max; + assert(f == 0); + } + --- + +$(H4 $(LNAME2 cast_struct, Structs)) + + $(P An expression `e` can be cast to a struct type `S`:) + + * The compiler attempts a + $(RELATIVE_LINK2 type-constructor-arguments, *PostfixExpression*) `S(e)`. + If that would fail: + * When `e` is a struct or static array instance, its data is reinterpreted as + the target type `S`. The data sizes must match. + * Otherwise, it is an error. + + $(NOTE The following examples assume a `LittleEndian` byte order.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + struct S + { + int i; + } + struct R + { + short[2] a; + } + + S s = cast(S) 5; // same as S(5) + assert(s.i == 5); + static assert(!__traits(compiles, cast(S) long.max)); // S(long.max) is invalid + + R r = R([1, 2]); + s = cast(S) r; // reinterpret r + assert(s.i == 0x00020001); + + byte[4] a = [1, 0, 2, 0]; + assert(r == cast(R) a); // reinterpret a + --- + ) + + $(P A struct instance can be cast to a static array type when + their `.sizeof` properties each give the same result.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + struct S { short a, b, c; } + + S s = S(1, 2, 3); + static assert(!__traits(compiles, cast(short[2]) s)); // size mismatch + + short[3] x = cast(short[3]) s; + assert(x.tupleof == s.tupleof); + + auto y = cast(byte[6]) s; + assert(y == [1, 0, 2, 0, 3, 0]); + --- + ) + +$(H4 $(LNAME2 cast_qualifier, Qualifier Cast)) + +$(GRAMMAR +$(GNAME CastQual): + $(D cast $(LPAREN)) $(GLINK2 type, TypeCtors)$(OPT) $(D $(RPAREN)) $(GLINK UnaryExpression) +) + + $(P A $(I CastQual) replaces the qualifiers in the type of + the $(I UnaryExpression):) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + shared int x; + static assert(is(typeof(cast(const)x) == const int)); + --- + ) + + $(P Casting with no type or qualifiers removes + any top level $(D const), $(D immutable), $(D shared) or $(D inout) + type modifiers from the type + of the $(I UnaryExpression).) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + shared int x; + static assert(is(typeof(cast()x) == int)); + --- + ) + +$(H4 $(LNAME2 cast_void, Casting to `void`)) + + $(P Casting an expression to $(D void) type is allowed to mark that + the result is unused. On $(GLINK2 statement, ExpressionStatement), + it could be used properly to avoid a "has no effect" error.) + + ---- + void foo(lazy void exp) {} + void main() + { + foo(10); // NG - expression '10' has no effect + foo(cast(void)10); // OK + } + ---- + +$(H2 $(LNAME2 throw_expression, Throw Expression)) + +$(GRAMMAR +$(GNAME ThrowExpression): + $(D throw) $(GLINK AssignExpression) +) + +$(P + $(I AssignExpression) is evaluated and must yield a reference to a `Throwable` + or a class derived from `Throwable`. The reference is thrown as an exception, + interrupting the current control flow to continue at a suitable $(D catch) clause + of a $(GLINK2 statement, try-statement). This process will execute any applicable + $(LINK2 statement.html#ScopeGuardStatement, `scope (exit)` / `scope (failure)`) + passed since entering the corresponding `try` block. +) + + --- + throw new Exception("message"); + --- + +$(P + The `Throwable` must not be a qualified as `immutable`, `const`, `inout` or + `shared`. The runtime may modify a thrown object (e.g. to contain a stack + trace) which would violate `const` or `immutable` objects. +) +$(P + A $(I ThrowExpression) may be nested in another expression: +) + --- + void foo(int function() f) {} + + void main() { + foo(() => throw new Exception()); + } + --- + + $(P The type of a *ThrowExpression* is $(DDSUBLINK spec/type, noreturn, `noreturn`).) + +$(BEST_PRACTICE Use $(DDSUBLINK spec/expression, assert_expressions, Assert Expressions) +rather than $(LINK2 $(ROOT_DIR)library/object#.Error, Error) to report program bugs +and abort the program. +) + +$(H2 $(LNAME2 pow_expressions, Pow Expressions)) + +$(GRAMMAR +$(GNAME PowExpression): + $(GLINK PostfixExpression) + $(GLINK PostfixExpression) $(D ^^) $(GLINK UnaryExpression) +) + + $(P $(I PowExpression) raises its left operand to the power of its + right operand. + ) + +$(H2 $(LNAME2 postfix_expressions, Postfix Expressions)) + +$(GRAMMAR +$(GNAME PostfixExpression): + $(GLINK PrimaryExpression) + $(GSELF PostfixExpression) $(D .) $(IDENTIFIER) + $(GSELF PostfixExpression) $(D .) $(GLINK2 template, TemplateInstance) + $(GSELF PostfixExpression) $(D .) $(GLINK NewExpression) + $(GSELF PostfixExpression) $(D ++) + $(GSELF PostfixExpression) $(D --) + $(GSELF PostfixExpression) $(D $(LPAREN)) $(GLINK NamedArgumentList)$(OPT) $(D $(RPAREN)) + $(GLINK2 type, TypeCtors)$(OPT) $(GLINK2 type, BasicType) $(D $(LPAREN)) $(GLINK NamedArgumentList)$(OPT) $(D $(RPAREN)) + $(GSELF PostfixExpression) $(GLINK IndexOperation) + $(GSELF PostfixExpression) $(GLINK SliceOperation) +) + +$(TABLE + $(THEAD Operation, Description) + $(TROW `.` *Identifier*, + Either: + * Access a $(DDLINK spec/property, Properties, property) of a type or expression. + * Access a member of a module, package, aggregate type or instance, enum + or template instance. + * Dereference a $(DDSUBLINK spec/struct, struct-pointer, pointer to a struct/union) + instance and access a member of it. + * Call a free function using $(DDSUBLINK spec/function, pseudo-member, UFCS). + ) + $(TROW `.` *NewExpression*, Instantiate a $(DDSUBLINK spec/class, nested-explicit, + nested class)) + $(TROW `++`, Increment after use - see $(RELATIVE_LINK2 order-of-evaluation, order of evaluation)) + $(TROW `--`, Decrement after use) + $(TROW `(args)`, + Either: + * $(RELATIVE_LINK2 callable_expressions, Call an expression) with optional arguments + * Call $(DDSUBLINK spec/operatoroverloading, static-opcall, + static `opCall`) on a user-defined type + * $(RELATIVE_LINK2 type-constructor-arguments, Construct a type) with optional arguments + ) + $(TROW *IndexOperation*, Select a single element) + $(TROW *SliceOperation*, Select a series of elements) +) + +$(H3 $(LNAME2 argument-list, Postfix Argument Lists)) + +$(GRAMMAR +$(GNAME ArgumentList): + $(GLINK AssignExpression) + $(GLINK AssignExpression) $(D ,) + $(GLINK AssignExpression) $(D ,) $(GSELF ArgumentList) + +$(GNAME NamedArgumentList): + $(GLINK NamedArgument) + $(GLINK NamedArgument) $(D ,) + $(GLINK NamedArgument) $(D ,) $(I NamedArgumentList) + +$(GNAME NamedArgument): + $(IDENTIFIER) $(D :) $(GLINK AssignExpression) + $(GLINK AssignExpression) +) + +$(H4 $(LNAME2 callable_expressions, Callable Expressions)) + + $(P A callable expression can precede a list of named arguments in parentheses. + The following expressions can be called:) + + * A function + * A function pointer + * A delegate + * An aggregate type instance which defines + $(DDSUBLINK spec/operatoroverloading, function-call, `opCall`) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +void f(int, int); + +void g() +{ + f(5, 6); + (&f)(5, 6); +} +--- +) + +$(H4 $(LNAME2 argument-parameter-matching, Matching Arguments to Parameters)) + + $(P + Arguments in a `NamedArgumentList` are matched to function parameters as follows: + ) + + 1. If the first argument has no name, it will be assigned to the first function parameter. + 1. A named argument is assigned to a function parameter with the same name. + It is an error if no such parameter exists. + 1. Any unnamed argument is assigned to the next parameter relative to the preceding argument's parameter. + It is an error if no such parameter exists, i.e. when the preceding argument assigns to the last parameter. + 1. Assigning a parameter more than once is an error. + 1. Not assigning a parameter an argument is also an error, + unless the parameter has a $(DDSUBLINK spec/function, function-default-args, Default Argument). + +$(H4 $(LNAME2 type-constructor-arguments, Constructing a Type with an Argument List)) + + $(P A type can precede a list of arguments. See:) + + * $(DDSUBLINK spec/struct, struct-literal, Struct Literals) + * $(DDSUBLINK spec/struct, struct-constructor, Struct Constructors) + * $(RELATIVE_LINK2 uniform_construction_syntax, Uniform construction syntax for built-in scalar types) + +$(H3 $(LEGACY_LNAME2 index_operations, index_expressions, Index Operations)) + +$(GRAMMAR +$(GNAME IndexOperation): + $(D [) $(GLINK ArgumentList) $(D ]) +) + + $(P The base $(I PostfixExpression) is evaluated. + The special variable `$` is declared and set to be the number + of elements in the base $(I PostfixExpression) (when available). + A new declaration scope is created for the evaluation of the + $(I ArgumentList) and `$` appears in that scope only. + ) + + * If the $(I PostfixExpression) is an expression of static or + dynamic array type, the result of the indexing is an lvalue + of the *i*th element in the array, where `i` is an integer + evaluated from $(I ArgumentList). + See $(DDSUBLINK spec/arrays, indexing, array indexing). + + * If $(I PostfixExpression) is a $(DDSUBLINK spec/type, pointers, pointer) `p`, the result is + `*(p + i)` (see $(RELATIVE_LINK2 pointer_arithmetic, Pointer Arithmetic)). + + * If the base $(I PostfixExpression) is a $(DDSUBLINK spec/template, variadic-templates, $(I ValueSeq)) + then the $(I ArgumentList) must consist of only one argument, + and that must be statically evaluatable to an integral constant. + That integral constant $(I n) then selects the $(I n)th + expression in the $(I ValueSeq), which is the result + of the $(I IndexOperation). + It is an error if $(I n) is out of bounds of the $(I ValueSeq). + + $(P The index operator can be $(DDSUBLINK spec/operatoroverloading, array, overloaded). + Using multiple indices in *ArgumentList* is only supported for operator + overloading.) + +$(H3 $(LEGACY_LNAME2 slice_operations, slice_expressions, Slice Operations)) + +$(GRAMMAR +$(GNAME SliceOperation): + $(D [ ]) + $(D [) $(GLINK Slice) $(D ]) + $(D [) $(GLINK Slice) $(D ,) $(D ]) + +$(GNAME Slice): + $(GLINK AssignExpression) + $(GLINK AssignExpression) $(D ,) $(GSELF Slice) + $(GLINK AssignExpression) $(D ..) $(GLINK AssignExpression) + $(GLINK AssignExpression) $(D ..) $(GLINK AssignExpression) $(D ,) $(GSELF Slice) +) + + $(P The base $(I PostfixExpression) is evaluated. + The special variable `$` is declared and set to be the number + of elements in the $(I PostfixExpression) (when available). + A new declaration scope is created for the evaluation of the + $(GRAMMAR_INLINE *AssignExpression* .. *AssignExpression*) and `$` appears in + that scope only. + ) + + * If the base $(I PostfixExpression) is a static or dynamic + array `a`, the result of the slice is a dynamic array + referencing elements `a[i]` to `a[j-1]` inclusive, where `i` + and `j` are integers evaluated from the first and second $(I + AssignExpression) respectively. + See $(DDSUBLINK spec/arrays, slicing, array slicing). + + * If the base $(I PostfixExpression) is a $(DDSUBLINK spec/type, pointers, pointer) `p`, the result + will be a dynamic array referencing elements from `p[i]` to `p[j-1]` + inclusive, where `i` and `j` are integers evaluated from the + first and second $(I AssignExpression) respectively. + + * If the base $(I PostfixExpression) is a $(DDSUBLINK spec/template, variadic-templates, $(I ValueSeq)), then + the result of the slice is a new $(I ValueSeq) formed + from the upper and lower bounds, which must statically evaluate + to integral constants. + It is an error if those bounds are out of range. + + $(P The first $(I AssignExpression) is taken to be the inclusive + lower bound + of the slice, and the second $(I AssignExpression) is the + exclusive upper bound. + The result of the expression is a slice of the elements in $(I PostfixExpression). + ) + + $(P If the $(D [ ]) form is used, the slice is of all the elements in the base $(I PostfixExpression). + The base expression cannot be a pointer. + ) + + $(P The slice operator can be $(DDSUBLINK spec/operatoroverloading, slice, overloaded). + Using more than one *Slice* is only supported for operator + overloading.) + + $(P A $(I SliceOperation) is not a modifiable lvalue.) + +$(H4 $(LNAME2 slice_to_static_array, Slice Conversion to Static Array)) + + $(P If the slice bounds can be known at compile time, the slice expression + may be implicitly convertible to a static array lvalue. For example:) + + ------------- + arr[a .. b] // typed T[] + ------------- + + $(P + If both $(CODE a) and $(CODE b) are integers (which may be constant-folded), + the slice expression can be converted to a static array of type + $(D T[b - a]). + ) + $(NOTE a static array can also be $(DDSUBLINK spec/arrays, assignment, + assigned from a slice), performing a runtime check that the lengths match.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + void f(int[2] sa) {} + + int[] arr = [1, 2, 3]; + + void test() + { + //f(arr); // error, can't convert + f(arr[1 .. 3]); // OK + //f(arr[0 .. 3]); // error + + int[2] g() { return arr[0 .. 2]; } + } + --- + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + void bar(ref int[2] a) + { + assert(a == [2, 3]); + a = [4, 5]; + } + + void main() + { + int[] arr = [1, 2, 3]; + + // slicing an lvalue gives an lvalue + bar(arr[1 .. 3]); + assert(arr == [1, 4, 5]); + } + ------------- + ) + + $(COMMENT Not implemented yet - https://issues.dlang.org/show_bug.cgi?id=13700 + $(P Certain other forms of slice expression can be implicitly converted to a static array + when the slice length can be known at compile-time.) + + $(COMMENT SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + int[] da = [1, 2, 3]; + int i = da[0]; // runtime variable + + int[2] f() { return da[i .. i + 2]; } + assert(f() == [2, 3]); + ------------- + ) + + $(P The table below shows all the forms recognized:) + + $(DL + $(DT $(D e)) $(DD An expression that contains no side effects.) + $(DT $(D a), $(D b)) $(DD Integers (that may be constant-folded).) + ) + + $(TABLE2 , + $(THEAD Form, The length calculated at compile time) + $(TROW $(D arr[]), The compile time length of $(D arr) if it's known.) + $(TROW $(D arr[a .. b]), $(D b - a)) + $(TROW $(D arr[e-a .. e]), $(D a)) + $(TROW $(D arr[e .. e+b]), $(D b)) + $(TROW $(D arr[e-a .. e+b]), $(D a + b)) + $(TROW $(D arr[e+a .. e+b]), $(D b - a) $(I if) $(D a <= b)) + $(TROW $(D arr[e-a .. e-b]), $(D a - b) $(I if) $(D a >= b)) + ) + ) + +$(H2 $(LNAME2 primary_expressions, Primary Expressions)) + +$(GRAMMAR +$(GNAME PrimaryExpression): + $(IDENTIFIER) + $(D .) $(IDENTIFIER) + $(GLINK2 template, TemplateInstance) + $(D .) $(GLINK2 template, TemplateInstance) + $(RELATIVE_LINK2 IndexOperation, `$`) + $(GLINK LiteralExpression) + $(GLINK AssertExpression) + $(GLINK MixinExpression) + $(GLINK ImportExpression) + $(GLINK NewExpression) + $(GLINK2 type, FundamentalType) $(D .) $(IDENTIFIER) + $(GLINK2 type, TypeCtor)$(OPT) $(D $(LPAREN)) $(GLINK2 type, Type) $(D $(RPAREN) .) $(IDENTIFIER) + $(D $(LPAREN)) $(GLINK2 type, Type) $(D $(RPAREN) .) $(GLINK2 template, TemplateInstance) + $(GLINK2 type, FundamentalType) $(D $(LPAREN)) $(GLINK NamedArgumentList)$(OPT) $(D $(RPAREN)) + $(GLINK2 type, TypeCtor)$(OPT) $(D $(LPAREN)) $(GLINK2 type, Type) $(D $(RPAREN)) $(D $(LPAREN)) $(GLINK NamedArgumentList)$(OPT) $(D $(RPAREN)) + $(GLINK2 type, Typeof) + $(GLINK TypeidExpression) + $(GLINK IsExpression) + $(D $(LPAREN)) $(GLINK Expression) $(D $(RPAREN)) + $(GLINK SpecialKeyword) + $(GLINK RvalueExpression) + $(GLINK2 traits, TraitsExpression) + +$(GNAME LiteralExpression): + $(RELATIVE_LINK2 this, $(D this)) + $(RELATIVE_LINK2 super, $(D super)) + $(RELATIVE_LINK2 null, $(D null)) + $(LEGACY_LNAME2 true_false)$(DDSUBLINK spec/type, bool, `true`) + $(DDSUBLINK spec/type, bool, `false`) + $(GLINK_LEX IntegerLiteral) + $(GLINK_LEX FloatLiteral) + $(LEGACY_LNAME2 CharacterLiteral)$(LEGACY_LNAME2 character-literal)$(GLINK_LEX CharacterLiteral) + $(RELATIVE_LINK2 string_literals, *StringLiteral*) + $(GLINK2 istring, InterpolationExpressionSequence) + $(GLINK ArrayLiteral) + $(GLINK AssocArrayLiteral) + $(GLINK FunctionLiteral) +) + +$(TABLE +$(THEAD Expression, Description) +$(TROW $(LNAME2 identifier, `.` *Identifier*), + $(DDSUBLINK spec/module, module_scope_operators, Module Scope Operator)) +$(TROW `$`, Number of elements in an object $(RELATIVE_LINK2 IndexOperation, + being indexed/sliced).) +$(TROW `(` *Type* `).` *Identifier*, + Access a $(DDLINK spec/property, Properties, type property) or a + $(DDSUBLINK spec/attribute, static, static member) of a type.) +$(TROW *FundamentalType* `(arg)`, + $(RELATIVE_LINK2 uniform_construction_syntax, Uniform construction) of scalar + type with optional argument.) +$(TROW `(` *Type* `)(args)`, + Construct a type with optional arguments.) +$(TROW `(` *Expression* `)`, Evaluate an expression - useful as a + $(RELATIVE_LINK2 .define-full-expression, subexpression).) +) + +$(H3 $(LNAME2 this, this)) + + $(P Within a constructor or $(DDSUBLINK spec/class, member-functions, + non-static member function), $(D this) resolves to + a reference to the object for which the function was called. + ) + $(P $(DDSUBLINK spec/type, typeof-this, `typeof(this)`) is valid anywhere + inside an aggregate type definition. + If a class member function is called with an explicit reference + to $(D typeof(this)), a non-virtual call is made:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + class A + { + char get() { return 'A'; } + + char foo() { return typeof(this).get(); } // calls `A.get` + char bar() { return this.get(); } // dynamic, same as just `get()` + } + + class B : A + { + override char get() { return 'B'; } + } + + void main() + { + B b = new B(); + + assert(b.foo() == 'A'); + assert(b.bar() == 'B'); + } + ------------- + ) + + $(P Assignment to $(D this) is not allowed for classes.) + $(P See also:) + * $(DDSUBLINK spec/class, delegating-constructors, Delegating Constructors) + * $(DDSUBLINK spec/template, template_this_parameter, template `this` parameters) + +$(H3 $(LNAME2 super, super)) + + $(P $(D super) is identical to $(D this), except that it is + cast to $(D this)'s base class. + It is an error if there is no base class. + (The only `extern(D)` class without a base class is `Object`, + however, note that `extern(C++)` classes have no base class unless specified.) + If a member function is called with an explicit reference + to $(D super), a non-virtual call is made. + ) + + $(P Assignment to $(D super) is not allowed.) + $(P See also: $(DDSUBLINK spec/class, base-construction, Base Class Construction).) + +$(H3 $(LNAME2 null, null)) + + $(P $(D null) represents the null value for + pointers, pointers to functions, delegates, + dynamic arrays, associative arrays, + and class objects. + If it has not already been cast to a type, + it is given the singular type $(D typeof(null)) and it is an exact conversion + to convert it to the null value for pointers, pointers to + functions, delegates, etc. + After it is cast to a type, such conversions are implicit, + but no longer exact. + ) + +$(H3 $(LEGACY_LNAME2 StringLiteral, string_literals, String Literals)) + + $(P See $(GLINK_LEX StringLiteral) grammar.) + + $(P String literals are read-only. + A string literal without a $(DDSUBLINK spec/lex, string_postfix, StringPostfix) + can implicitly convert to any + of the following types, which have equal weight: + ) + + $(TABLE + $(TROW $(D immutable(char)*)) + $(TROW $(D immutable(wchar)*)) + $(TROW $(D immutable(dchar)*)) + $(TROW $(D immutable(char)[])) + $(TROW $(D immutable(wchar)[])) + $(TROW $(D immutable(dchar)[])) + ) + + $(UNDEFINED_BEHAVIOR writing to a string literal. This is not allowed in `@safe` code.) + + $(P By default, a string literal is typed as a dynamic array, but the element + count is known at compile time. So all string literals can be + implicitly converted to an immutable static array:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + void foo(char[2] a) + { + assert(a[0] == 'b'); + } + void bar(ref const char[2] a) + { + assert(a == "bc"); + } + + void main() + { + foo("bc"); + foo("b"); // OK + //foo("bcd"); // error, too many chars + bar("bc"); // OK, same length + //bar("b"); // error, lengths must match + } + ------------- + ) + $(P A string literal converts to a static array rvalue of the same or longer length. + Any extra elements are padded with zeros. A string literal + can also convert to a static array lvalue of the same length.) + + $(P String literals have a `'\0'` appended to them, which makes + them easy to pass to C or C++ functions expecting a null-terminated + $(CODE const char*) string. + The `'\0'` is not included in the $(CODE .length) property of the + string literal. + ) + + $(P Concatenation of string literals requires the use of + $(RELATIVE_LINK2 cat_expressions, the `~` operator), and is resolved at compile time. + C style implicit concatenation without an intervening operator is + error prone and not supported in D.) + + +$(H3 $(LNAME2 hex_string_literals, Hex String Literals)) + $(P Because hex string literals contain binary data not limited to textual data, they allow additional conversions over other string literals.) + + $(P A hex string literal implicitly converts to a constant `byte[]` or `ubyte[]`.) + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + immutable ubyte[] b = x"3F 80 00 00"; + const byte[] c = x"3F 80 00 00"; + ------------- + ) + + $(P A hex string literal can be explicitly cast to an array of integers with a larger size than 1. + A big endian byte order in the hex string will be assumed.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + static immutable uint[] data = cast(immutable uint[]) x"AABBCCDD"; + static assert(data[0] == 0xAABBCCDD); + ------------- + ) + + $(P This requires the length of the hex string to be a multiple of the array element's size in bytes.) + $(SPEC_RUNNABLE_EXAMPLE_FAIL + ------------- + static e = cast(immutable ushort[]) x"AA BB CC"; + // Error, length of 3 bytes is not a multiple of 2, the size of a `ushort` + ------------- + ) + + $(P When a hex string literal gets constant folded, the result is no longer considered a hex string literal) + $(SPEC_RUNNABLE_EXAMPLE_FAIL + ------------- + static immutable byte[] b = x"AA" ~ "G"; // Error: cannot convert `string` to `immutable byte[]` + ------------- + ) + +$(H3 $(LNAME2 array_literals, Array Literals)) + +$(GRAMMAR +$(GNAME ArrayLiteral): + $(D [) $(GLINK ArgumentList)$(OPT) $(D ]) +) + + $(P An array literal is a comma-separated list of expressions + between square brackets $(D [) and $(D ]). + The expressions form the elements of a dynamic array. + The length of the array is the number of elements. + ) + $(P + The element type of the array is inferred as the common type of all the + elements, and each expression is implicitly converted to that type. + When there is an expected array type, the elements of the + literal will be implicitly converted to the expected element + type.) + + --- + auto a1 = [1, 2, 3]; // type is int[], with elements 1, 2 and 3 + auto a2 = [1u, 2, 3]; // type is uint[], with elements 1u, 2u, and 3u + byte[] a3 = [1, 2, 3]; // OK + byte[] a4 = [128]; // error + --- + + $(PANEL + By default, an array literal is typed as a dynamic array, but the element + count is known at compile time. Therefore, an array literal can be + implicitly converted to a static array of the same length. + + ------------- + int[2] sa = [1, 2]; // OK + int[2] sb = [1]; // error + ------------- + + $(NOTE Slicing a dynamic array with a statically known slice length also + $(RELATIVE_LINK2 slice_to_static_array, allows conversion) to a static array.) + ) + + $(P If any $(I ArrayMemberInitialization) is a + $(DDSUBLINK spec/template, TemplateParameterSequence, ValueSeq), + then the elements of the $(I ValueSeq) + are inserted as expressions in place of the sequence. + ) + +$(H4 $(LNAME2 array-literal-heap, GC Allocation)) + + $(P Escaping array literals are always allocated on the memory managed heap. + Thus, they can be returned safely from functions:) + + --- + int[] foo() + { + return [1, 2, 3]; + } + --- + + $(P An array literal is not GC allocated if:) + + * It initializes or assigns to a static array. + * It is an argument to a $(DDSUBLINK spec/function, scope-parameters, `scope` + function parameter). + * It initializes a $(DDSUBLINK spec/attribute, scope, `scope`) slice (`-preview=dip1000` + $(LINK2 $(ROOT_DIR)changelog/2.102.0.html#dmd.scope-array-on-stack, + is required for this)). + * It is used on one side of an $(GLINK EqualExpression) or $(GLINK RelExpression). + * It is immediately $(RELATIVE_LINK2 index_operations, indexed) and used as an rvalue. + * It is used as a `foreach` aggregate where the element variable is not `ref`. + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + void f(scope int[] a, int[2] sa) @nogc + { + sa = [7, 8]; + } + void g(int[] b) @nogc; // `b` is not scope, so may escape + + void main() @nogc + { + int[3] sa = [1, 2, 3]; + f([1, 2], [3, 4]); + //scope int[] a = [5, 6]; // requires `-preview=dip1000` + //g([1, 2]); // error, array literal heap allocated + assert([1, 2] < [3, 2]); + assert([1, 2][1] == 2); + foreach (e; [4, 2, 9]) + assert(e > 0); + } + --- + ) + +$(H4 $(LNAME2 cast_array_literal, Casting)) + + $(P When array literals are cast to another array type, each + element of the array is cast to the new element type. + When arrays that are not literals $(RELATIVE_LINK2 cast_array, are cast), the array is + reinterpreted as the new type, and the length is recomputed:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + // cast array literal + const ubyte[] ct = cast(ubyte[]) [257, 257]; + // this is equivalent to: + // const ubyte[] ct = [cast(ubyte) 257, cast(ubyte) 257]; + writeln(ct); // writes [1, 1] + + // cast other array expression + // --> normal behavior of CastExpression + byte[] arr = [1, 1]; + short[] rt = cast(short[]) arr; + writeln(rt); // writes [257] + --- + ) + + In other words, casting an array literal will change the type of each initializer element. + + $(BEST_PRACTICE Avoid casting an array literal when the elements could + implicitly convert to an expected type. Instead, declare a variable of that type + and initialize it with the array literal. + Casting is more bug-prone than implicit conversions.) + + +$(H3 $(LNAME2 associative_array_literals, Associative Array Literals)) + +$(GRAMMAR +$(GNAME AssocArrayLiteral): + $(D [) $(GLINK KeyValuePairs) $(D ]) + +$(GNAME KeyValuePairs): + $(GLINK KeyValuePair) + $(GLINK KeyValuePair) $(D ,) $(GSELF KeyValuePairs) + +$(GNAME KeyValuePair): + $(GLINK KeyExpression) $(D :) $(GLINK ValueExpression) + +$(GNAME KeyExpression): + $(GLINK AssignExpression) + +$(GNAME ValueExpression): + $(GLINK AssignExpression) +) + + $(P Associative array literals are a comma-separated list of + $(I key)$(D :)$(I value) pairs + between square brackets $(D [) and $(D ]). + The list cannot be empty. + The common type of the all keys is taken to be the key type of + the associative array, and all keys are implicitly converted + to that type. + The common type of the all values is taken to be the value type of + the associative array, and all values are implicitly converted + to that type. + An $(I AssocArrayLiteral) cannot be used to statically initialize + anything.) + + --- + [21u: "he", 38: "ho", 2: "hi"]; // type is string[uint], + // with keys 21u, 38u and 2u + // and values "he", "ho", and "hi" + --- + + $(P If any of the keys or values in the $(I KeyValuePairs) are + a $(I ValueSeq), then the elements of the $(I ValueSeq) + are inserted as arguments in place of the sequence. + ) + + $(P Associative array initializers may contain duplicate keys, + however, in that case, the last $(I KeyValuePair) lexicographically + encountered is stored. + ) + + --- + auto aa = [21: "he", 38: "ho", 2: "hi", 2:"bye"]; + assert(aa[2] == "bye") + --- + +$(H3 $(LNAME2 function_literals, Function Literals)) + +$(GRAMMAR +$(GNAME FunctionLiteral): + $(D function) $(GLINK RefOrAutoRef)$(OPT) $(GLINK BasicTypeWithSuffixes)$(OPT) $(GLINK ParameterWithAttributes)$(OPT) $(GLINK FunctionLiteralBody) + $(D delegate) $(GLINK RefOrAutoRef)$(OPT) $(GLINK BasicTypeWithSuffixes)$(OPT) $(GLINK ParameterWithMemberAttributes)$(OPT) $(GLINK FunctionLiteralBody) + $(GLINK RefOrAutoRef)$(OPT) $(GLINK ParameterWithMemberAttributes) $(GLINK FunctionLiteralBody) + $(GLINK2 statement, BlockStatement) + $(IDENTIFIER) $(D =>) $(GLINK AssignExpression) + +$(GNAME BasicTypeWithSuffixes): + $(GLINK2 type, BasicType) $(GLINK2 type, TypeSuffixes)$(OPT) + +$(GNAME ParameterWithAttributes): + $(GLINK2 function, Parameters) $(GLINK2 function, FunctionAttributes)$(OPT) + +$(GNAME ParameterWithMemberAttributes): + $(GLINK2 function, Parameters) $(GLINK2 function, MemberFunctionAttributes)$(OPT) + +$(GNAME FunctionLiteralBody): + $(D =>) $(GLINK AssignExpression) + $(GLINK2 function, SpecifiedFunctionBody) + +$(GNAME RefOrAutoRef): + $(D ref) + $(D auto ref) +) + + $(P $(I FunctionLiteral)s enable embedding anonymous functions + and anonymous delegates directly into expressions. + Short function literals are known as $(LNAME2 lambdas, $(I lambdas)). + ) + * $(I Type) is the return type of the function or delegate - + if omitted it is $(RELATIVE_LINK2 lambda-return-type, inferred). + * $(I ParameterWithAttributes) or $(I ParameterWithMemberAttributes) + can be used to specify the parameters for the function. If these are + omitted, the function defaults to the empty parameter list $(D ( )). + * Parameter types can be $(RELATIVE_LINK2 lambda-parameter-inference, omitted). + * The type of a function literal is a + $(DDSUBLINK spec/function, closures, delegate or a pointer to function). + + $(P For example:) + + ------------- + int function(char c) fp; // declare pointer to a function + + void test() + { + static int foo(char c) { return 6; } + + fp = &foo; + } + ------------- + + is exactly equivalent to: + + ------------- + int function(char c) fp; + + void test() + { + fp = function int(char c) { return 6; }; + } + ------------- + + $(P A delegate is necessary if the $(I FunctionLiteralBody) accesses any non-static + local variables in enclosing functions.) + + ------------- + int abc(int delegate(int i)); + + void test() + { + int b = 3; + int foo(int c) { return 6 + b; } + + abc(&foo); + } + ------------- + + is exactly equivalent to: + + ------------- + int abc(int delegate(int i)); + + void test() + { + int b = 3; + + abc( delegate int(int c) { return 6 + b; } ); + } + ------------- + + $(P The use of `ref` declares that the return value is returned by reference:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + void main() + { + int x; + auto dg = delegate ref int() { return x; }; + dg() = 3; + assert(x == 3); + } + --- + ) + + $(NOTE When comparing function literals with $(DDSUBLINK spec/function, nested, nested functions), + the $(D function) form is analogous to static + or non-nested functions, and the $(D delegate) form is + analogous to non-static nested functions. I.e. + a delegate literal can access non-static local variables in an enclosing + function, a function literal cannot. + ) + +$(H4 $(LNAME2 lambda-type-inference, Delegate Inference)) + + $(P If a literal omits $(D function) or $(D delegate) and there's no + expected type from the context, then + it is inferred to be a delegate if it accesses a + variable in an enclosing function, otherwise it is a function pointer. + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------------- + void test() + { + int b = 3; + + auto fp = (uint c) { return c * 2; }; // inferred as function pointer + auto dg = (int c) { return 6 + b; }; // inferred as delegate + + static assert(!is(typeof(fp) == delegate)); + static assert(is(typeof(dg) == delegate)); + } + ------------- + ) + $(P If a delegate is expected, the literal will be inferred as a delegate + even if it accesses no variables from an enclosing function:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------------- + void abc(int delegate(int i)) {} + void def(uint function(uint s)) {} + + void test() + { + int b = 3; + + abc( (int c) { return 6 + b; } ); // inferred as delegate + abc( (int c) { return c * 2; } ); // inferred as delegate + + def( (uint c) { return c * 2; } ); // inferred as function + //def( (uint c) { return c * b; } ); // error! + // Because the FunctionLiteral accesses b, its type + // is inferred as delegate. But def cannot accept a delegate argument. + } + ------------- + ) + +$(H4 $(LNAME2 lambda-parameter-inference, Parameter Type Inference)) + + $(P If the type of a function literal can be uniquely determined from its context, + parameter type inference is possible.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------------- + void foo(int function(int) fp); + + void test() + { + int function(int) fp = (n) { return n * 2; }; + // The type of parameter n is inferred as int. + + foo((n) { return n * 2; }); + // The type of parameter n is inferred as int. + } + ------------- + ) + --- + auto fp = (i) { return 1; }; // error, cannot infer type of `i` + --- + +$(H4 $(LNAME2 function-literal-alias, Function Literal Aliasing)) + + $(P Function literals can be $(DDSUBLINK spec/declaration, alias, aliased). + Aliasing a function literal with unspecified parameter types produces a + $(DDSUBLINK spec/template, function-template, function template) + with type parameters for each unspecified parameter type of the literal. + Type inference for the literal is then done when the template is instantiated.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + alias fpt = (i) { return i; }; // ok, infer type of `i` when used + //auto fpt(T)(T i) { return i; } // equivalent + + auto v = fpt(4); // `i` is inferred as int + auto d = fpt(10.3); // `i` is inferred as double + + alias fp = fpt!float; + auto f = fp(0); // f is a float + --- + ) + +$(H4 $(LNAME2 lambda-return-type, Return Type Inference)) + + $(P The return type of the $(GLINK FunctionLiteral) can be + inferred from either the *AssignExpression*, or + any $(GLINK2 statement, ReturnStatement)s in the $(I BlockStatement). + If there is a different expected type from the context, and the + initial inferred return type implicitly converts to the expected type, + then the return type is inferred as the expected type.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + auto fi = (int i) { return i; }; + static assert(is(typeof(fi(5)) == int)); + + long function(int) fl = (int i) { return i; }; + static assert(is(typeof(fl(5)) == long)); + --- + ) + +$(H4 $(LNAME2 lambda-short-syntax, Nullary Short Syntax)) + + $(P *Parameters* can be omitted completely for a function literal + when there is a *BlockStatement* function body.) + + $(NOTE This form is not allowed to be immediately called as an *ExpressionStatement*, + because it would require arbitrary lookahead to distinguish it from a *BlockStatement*.) + +--- +auto f = { writeln("hi"); }; // OK, f has type `void function()` +f(); +{ writeln("hi"); }(); // error +() { writeln("hi"); }(); // OK +--- + + $(PANEL Anonymous delegates can behave like arbitrary statement literals. + For example, here an arbitrary statement is executed by a loop: + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------------- + void loop(int n, void delegate() statement) + { + foreach (_; 0 .. n) + { + statement(); + } + } + + void main() + { + int n = 0; + + loop(5, { n += 1; }); + assert(n == 5); + } + ------------- + ) + ) + +$(H4 $(LNAME2 lambda-short-body, Shortened Body Syntax)) + + $(P The syntax $(D => AssignExpression) is equivalent to $(D { return AssignExpression; }).) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + void main() + { + auto i = 3; + auto twice = function (int x) => x * 2; + assert(twice(i) == 6); + + auto square = delegate () => i * i; + assert(square() == 9); + + auto n = 5; + auto mul_n = (int x) => x * n; + assert(mul_n(i) == 15); + } + --- + ) + + $(P The syntax $(D Identifier => AssignExpression) is equivalent to $(D (Identifier) { return AssignExpression; }).) + + --- + // the following two declarations are equivalent + alias fp = i => 1; + alias fp = (i) { return 1; }; + --- + + $(BEST_PRACTICE The minimal form of the function literal is most useful as + an argument to a template alias parameter: + --- + int motor(alias fp)(int i) + { + return fp(i) + 1; + } + + int engine() + { + return motor!(i => i * 2)(6); // returns 13 + } + --- + ) + + $(NOTE The syntax `Identifier { statement; }` is not supported because it is + easily confused with statements `x = Identifier; { statement; };` + if the semicolons were accidentally omitted. + ) + + +$(H3 $(LNAME2 uniform_construction_syntax, Uniform construction syntax for built-in scalar types)) + + $(P The implicit conversions of built-in scalar types can be explicitly + represented by using function call syntax. For example:) + + --- + auto a = short(1); // implicitly convert an integer literal '1' to short + auto b = double(a); // implicitly convert a short variable 'a' to double + auto c = byte(128); // error, 128 cannot be represented in a byte + --- + + $(P If the argument is omitted, it means default construction of the + scalar type:) + + --- + auto a = ushort(); // same as: ushort.init + auto b = wchar(); // same as: wchar.init + --- + + $(P The argument may not be given a name:) + + --- + auto a = short(x: 1); // Error + --- + + $(P See also: $(DDSUBLINK spec/type, usual-arithmetic-conversions, Usual Arithmetic Conversions).) + + +$(H3 $(LNAME2 assert_expressions, Assert Expressions)) + +$(GRAMMAR +$(GNAME AssertExpression): + $(D assert $(LPAREN)) $(GLINK AssertArguments) $(D $(RPAREN)) + +$(GNAME AssertArguments): + $(GLINK AssignExpression) + $(GLINK AssignExpression) $(D ,) + $(GLINK AssignExpression) $(D ,) $(GLINK AssignExpression) + $(GLINK AssignExpression) $(D ,) $(GLINK AssignExpression) $(D ,) +) + + $(P The first $(I AssignExpression) is evaluated and + $(DDSUBLINK spec/statement, boolean-conditions, converted to a boolean value). + If the value is not `true`, an $(I Assert Failure) + has occurred and the program enters an $(I Invalid State). + ) + + --- + int i = fun(); + assert(i > 0); + --- + + $(P $(I AssertExpression) has different semantics if it is in a + $(DDLINK spec/unittest, Unit Tests, $(D unittest)) or + $(DDSUBLINK spec/function, preconditions, $(D in) contract). + ) + + $(P If the first $(I AssignExpression) is a reference to a class instance for + which a $(DDSUBLINK spec/class, invariants, class *Invariant*) exists, the class $(I Invariant) must hold. + ) + + $(P If the first $(I AssignExpression) is a pointer to a struct instance for + which a $(DDSUBLINK spec/struct, Invariant, struct $(I Invariant)) exists, the struct $(I Invariant) must hold. + ) + + $(P The type of an $(I AssertExpression) is $(D void). + ) + + $(UNDEFINED_BEHAVIOR Once in an $(I Invalid State) the behavior of the continuing execution + of the program is undefined.) + + $(PANEL + $(IMPLEMENTATION_DEFINED Whether the first $(I AssertExpression) is evaluated + or not (at runtime) is typically set with a compiler switch. If it is not evaluated, + any side effects specified by the $(I AssertExpression) may not occur. + The behavior when the first $(I AssertExpression) evaluates to `false` + is also typically set with a compiler switch, and may include these options: + $(OL + $(LI Immediately halting via execution of a special CPU instruction) + $(LI Aborting the program) + $(LI Calling the assert failure function in the corresponding C + runtime library) + $(LI Throwing the $(D AssertError) exception in the D runtime library) + ) + ) + + $(NOTE Throwing $(D AssertError) is the default for $(B dmd), with an optional + $(DDSUBLINK dmd, switch-checkaction, $(B -checkaction=context)) + switch to show certain sub-expressions used in the first *AssertExpression* + in the error message:) + + --- + auto x = 4; + assert(x < 3); + --- + When in use, the above will throw an `AssertError` with a message `4 >= 3`. + ) + + $(BEST_PRACTICE + $(OL + $(LI Do not have side effects in either $(I AssignExpression) that subsequent code + depends on.) + $(LI $(I AssertExpression)s are intended to detect bugs in the program. + Do not use them for detecting input or environmental errors.) + $(LI Do not attempt to resume normal execution after an $(I Assert Failure).) + ) + ) + +$(H4 $(LNAME2 assert-ct, Compile-time Evaluation)) + + $(P If the first $(I AssignExpression) consists entirely of compile time constants, + and evaluates to `false`, it is a special case - it + signifies that subsequent statements are unreachable code. + Compile Time Function Execution (CTFE) calls are not attempted for the evaluation. + Such an $(GLINK AssertExpression) has type $(DDSUBLINK spec/type, noreturn, `noreturn`). + ) + + $(P This allows the compiler to suppress an error when there is a + missing return statement:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + int f(int x) + { + if (x > 0) + { + return 5 / x; + } + assert(0); + // no need to use a dummy return statement here + } + --- + ) + + $(P The implementation may handle the case of the first $(I AssignExpression) evaluating to `false` + at compile time differently - even when other `assert`s are ignored, + it may still generate a $(D HLT) instruction or equivalent. + ) + + $(RATIONALE Halting the program prevents undefined behaviour from occurring.) + + $(P See also: $(DDSUBLINK spec/version, static-assert, `static assert`).) + +$(H4 $(LNAME2 assert-message, Assert Message)) + + $(P The second $(I AssignExpression), if present, must be implicitly + convertible to type $(D const(char)[]). + When present, the implementation may evaluate it and print the + resulting message upon assert failure: + ) + ---- + void main() + { + assert(0, "an" ~ " error message"); + } + ---- + + $(P When compiled and run, typically it will produce the message:) + + $(CONSOLE core.exception.AssertError@test.d(3) an error message) + + +$(H3 $(LNAME2 mixin_expressions, Mixin Expressions)) + +$(GRAMMAR +$(GNAME MixinExpression): + $(D mixin $(LPAREN)) $(GLINK ArgumentList) $(D $(RPAREN)) +) + + $(P Each $(GLINK AssignExpression) in the $(I ArgumentList) is + evaluated at compile time, and the result must be representable + as a string. + The resulting strings are concatenated to form a string. + The text contents of the string must be compilable as a valid + $(GLINK Expression), and is compiled as such.) + + --- + int foo(int x) + { + return mixin("x +", 1) * 7; // same as ((x + 1) * 7) + } + --- + +$(H3 $(LNAME2 import_expressions, Import Expressions)) + +$(GRAMMAR +$(GNAME ImportExpression): + $(D import $(LPAREN)) $(GLINK AssignExpression) $(D $(RPAREN)) +) + + $(P The $(I AssignExpression) must evaluate at compile time + to a constant string. + The text contents of the string are interpreted as a file + name. The file is read, and the exact contents of the file + become a $(RELATIVE_LINK2 hex_string_literals, hex string literal). + ) + + $(P Implementations may restrict the file name in order to avoid + directory traversal security vulnerabilities. + A possible restriction might be to disallow any path components + in the file name. + ) + + $(P Note that by default an import expression will not compile unless + one or more paths are passed via the $(B -J) switch. This tells the compiler + where it should look for the files to import. This is a security feature.) + + --- + void foo() + { + // Prints contents of file foo.txt + writeln(import("foo.txt")); + } + --- + +$(H3 $(LNAME2 new_expressions, New Expressions)) + +$(GRAMMAR +$(GNAME NewExpression): + $(D new) $(GLINK PlacementExpression)$(OPT) $(GLINK2 type, Type) + $(D new) $(GLINK PlacementExpression)$(OPT) $(GLINK2 type, Type) $(D [) $(GLINK AssignExpression) $(D ]) + $(D new) $(GLINK PlacementExpression)$(OPT) $(GLINK2 type, Type) $(D $(LPAREN)) $(GLINK NamedArgumentList)$(OPT) $(D $(RPAREN)) + $(GLINK2 class, NewAnonClassExpression) + +$(GNAME PlacementExpression): + $(LPAREN) $(GLINK AssignExpression) $(RPAREN) +) + + $(P $(I NewExpression)s allocate memory on the + $(DDLINK spec/garbage, Garbage Collection, garbage + collected) heap unless there is a $(RELATIVE_LINK2 placement-expression, *PlacementExpression*). + ) + + $(P `new T` constructs an instance of type `T` and default-initializes it. + The result's type is:) + * `T` when `T` is a reference type (e.g. classes, + $(DDSUBLINK spec/hash-map, construction_and_ref_semantic, associative arrays)) + * `T*` when `T` is a value type (e.g. basic types, structs) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + int* i = new int; + assert(*i == 0); // int.init + + Object o = new Object; + //int[] a = new int[]; // error, need length argument + --- + ) + $(P The $(GRAMMAR_INLINE *Type(NamedArgumentList)*) form allows passing either a single initializer + of the same type, or multiple arguments for more complex types:) + + * For class and struct types, *NamedArgumentList* is passed to the constructor. + * For a dynamic array, the argument sets the initial array length. + * For multidimensional dynamic arrays, each argument corresponds to + an initial length (see $(RELATIVE_LINK2 new_multidimensional, below)). + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + int* i = new int(5); + assert(*i == 5); + + Exception e = new Exception("info"); + assert(e.msg == "info"); + + int[] a = new int[](2); + assert(a.length == 2); + a = new int[2]; // same, see below + --- + ) + + $(P The $(GRAMMAR_INLINE *Type[AssignExpression]*) form allocates a dynamic array with + length equal to *AssignExpression*. + It is preferred to use the $(GRAMMAR_INLINE *Type(NamedArgumentList)*) form when allocating + dynamic arrays instead, as it is more general.) + + $(NOTE It is not possible to allocate a static array directly with + `new` (only by using a type alias).) + + $(P The result is a $(DDSUBLINK spec/const3, unique-expressions, unique expression) + which can implicitly convert to other qualifiers:) + + --- + immutable o = new Object; + --- + +$(H4 $(LNAME2 new_class, Class Instantiation)) + + $(P If a $(I NewExpression) is used with a class type as an initializer for + a function local variable with $(DDSUBLINK spec/attribute, scope, `scope`) storage class, + then the instance is $(DDSUBLINK spec/attribute, scope-class-var, allocated on the stack). + ) + + $(P `new` can also be used to allocate a + $(DDSUBLINK spec/class, nested-explicit, nested class).) + +$(H4 $(LNAME2 new_multidimensional, Multidimensional Arrays)) + + $(P To allocate multidimensional arrays, the declaration reads + in the same order as the prefix array declaration order.) + + ------------- + char[][] foo; // dynamic array of strings + ... + foo = new char[][30]; // allocate array of 30 strings + ------------- + + $(P The above allocation can also be written as:) + + ------------- + foo = new char[][](30); // allocate array of 30 strings + ------------- + + $(P To allocate the nested arrays, multiple arguments can be used:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --------------- + int[][][] bar; + bar = new int[][][](5, 20, 30); + + assert(bar.length == 5); + assert(bar[0].length == 20); + assert(bar[0][0].length == 30); + --------------- + ) + + The assignment above is equivalent to: + + ---------- + bar = new int[][][5]; + foreach (ref a; bar) + { + a = new int[][20]; + foreach (ref b; a) + { + b = new int[30]; + } + } + ----------- + +$(H4 $(LNAME2 placement-expression, Placement Expression)) + + $(P The $(I PlacementExpression) explicitly provides the storage for $(I NewExpression) to initialize with + the newly created value, rather than using the $(DDLINK spec/garbage, Garbage Collection, garbage + collected) heap.) + + $(P If $(I Type) is a basic type or a struct, the $(I PlacementExpression) must produce an lvalue that has a size + larger or equal to $(D sizeof($(I Type))).) + + $(P The $(I Type) of the $(I PlacementExpression) need not be the same as the $(I Type) of the object being created.) + + $(P Alternatively, the $(I PlacementExpression) can be a dynamic array, which must represent sufficient memory + for the object being created.) + + $(BEST_PRACTICE Using a static array of `void` is preferred for the $(I PlacementExpression).) + + $(P The lifetime of the object presented as an lvalue ends with the execution of the $(I NewExpression), + and a new lifetime of the placed object starts after the execution.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + struct S + { + float d; + int i; + char c; + } + + void main() + { + S s; + S* p = new (s) S(); // lifetime of s ends, lifetime of *p begins + assert(p.i == 0 && p.c == 0xFF); + } + --- + ) + + (If Type is a class, the $(I PlacementExpression) must produce an lvalue of a type that is of a + sufficient size to hold the class object such as `void[__traits(classInstanceSize, Type)]` + or a dynamic array representing sufficient memory for the class object.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + class C + { + int i, j = 4; + } + + void main() + { + void[__traits(classInstanceSize, C)] k = void; + C c = new(k) C; + assert(c.j == 4); + assert(cast(void*) c == k.ptr); + } + --- + ) + + $(P $(I PlacementExpression) cannot be used for associative arrays, as associative arrays + are designed to be on the GC heap. The size of the associative array allocated is determined + by the runtime library, and cannot be set by the user.) + + $(P The use of $(I PlacementExpression) is not allowed in `@safe` code.) + + $(P To allocate storage with an allocator function such as `malloc()`, a simple template can be used:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + import core.stdc.stdlib; + + struct S { int i = 1, j = 4, k = 9; } + + ref void[T.sizeof] mallocate(T)() + { + return malloc(T.sizeof)[0 .. T.sizeof]; + } + + void main() + { + S* ps = new(mallocate!S()) S; + assert(ps.i == 1); + assert(ps.j == 4); + assert(ps.k == 9); + } + --- + ) + + + + +$(H3 $(LNAME2 typeid_expressions, Typeid Expressions)) + +$(GRAMMAR +$(GNAME TypeidExpression): + $(D typeid $(LPAREN)) $(GLINK2 type, Type) $(D $(RPAREN)) + $(D typeid $(LPAREN)) $(GLINK Expression) $(D $(RPAREN)) +) + + $(P If $(I Type), returns an instance of class + $(DPLLINK library/object/type_info.html, $(D TypeInfo)) + corresponding + to $(I Type). + ) + + $(P If $(I Expression), returns an instance of class + $(DPLLINK library/object/type_info.html, $(D TypeInfo)) + corresponding + to the type of the $(I Expression). + If the type is a class, it returns the $(D TypeInfo) + of the dynamic type (i.e. the most derived type). + The $(I Expression) is always executed.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + class A { } + class B : A { } + + void main() + { + import std.stdio; + + writeln(typeid(int)); // int + uint i; + writeln(typeid(i++)); // uint + writeln(i); // 1 + A a = new B(); + writeln(typeid(a)); // B + writeln(typeid(typeof(a))); // A + } + --- + ) + +$(H3 $(LNAME2 is_expression, Is Expressions)) + +$(GRAMMAR +$(GNAME IsExpression): + $(D is $(LPAREN)) $(GLINK2 type, Type) $(D $(RPAREN)) + $(D is $(LPAREN)) $(GLINK2 type, Type) $(D :) $(GLINK TypeSpecialization) $(D $(RPAREN)) + $(D is $(LPAREN)) $(GLINK2 type, Type) $(D ==) $(GLINK TypeSpecialization) $(D $(RPAREN)) + $(D is $(LPAREN)) $(GLINK2 type, Type) $(D :) $(GLINK TypeSpecialization) $(D ,) $(GLINK2 template, TemplateParameterList) $(D $(RPAREN)) + $(D is $(LPAREN)) $(GLINK2 type, Type) $(D ==) $(GLINK TypeSpecialization) $(D ,) $(GLINK2 template, TemplateParameterList) $(D $(RPAREN)) + $(D is $(LPAREN)) $(GLINK2 type, Type) $(IDENTIFIER) $(D $(RPAREN)) + $(D is $(LPAREN)) $(GLINK2 type, Type) $(IDENTIFIER) $(D :) $(GLINK TypeSpecialization) $(D $(RPAREN)) + $(D is $(LPAREN)) $(GLINK2 type, Type) $(IDENTIFIER) $(D ==) $(GLINK TypeSpecialization) $(D $(RPAREN)) + $(D is $(LPAREN)) $(GLINK2 type, Type) $(IDENTIFIER) $(D :) $(GLINK TypeSpecialization) $(D ,) $(GLINK2 template, TemplateParameterList) $(D $(RPAREN)) + $(D is $(LPAREN)) $(GLINK2 type, Type) $(IDENTIFIER) $(D ==) $(GLINK TypeSpecialization) $(D ,) $(GLINK2 template, TemplateParameterList) $(D $(RPAREN)) + + +$(GNAME TypeSpecialization): + $(GLINK2 type, Type) + $(GLINK2 type, TypeCtor) + $(D struct) + $(D union) + $(D class) + $(D interface) + $(D enum) + $(D __vector) + $(D function) + $(D delegate) + $(D super) + $(D return) + $(D __parameters) + $(D module) + $(D package) +) + + $(P An $(I IsExpression) is evaluated at compile time and is + used to check if an expression is a valid type. In addition, + there are forms which can also:) + $(UL + $(LI compare types for equivalence) + $(LI determine if one type can be implicitly converted to another) + $(LI deduce the subtypes of a type using + $(RELATIVE_LINK2 is-parameter-list, pattern matching)) + $(LI deduce the template arguments of a type template instance) + ) + $(P + The result of an $(I IsExpression) is a boolean which is `true` + if the condition is satisfied and `false` if not. + ) + + $(P $(I Type) is the type being tested. It must be syntactically + correct, but it need not be semantically correct. + If it is not semantically correct, the condition is not satisfied. + ) + + $(P $(I TypeSpecialization) is the type that $(I Type) is being + pattern matched against. + ) + + $(P $(I IsExpression)s may be used in conjunction with + $(DDSUBLINK spec/type, typeof, `typeof`) to check + whether an expression type checks correctly. For example, $(D is(typeof(foo))) + will return $(D true) if $(D foo) has a valid type. + ) + +$(H4 $(LNAME2 basic-forms, Basic Forms)) + + $(H5 $(LNAME2 is-type, $(D is $(LPAREN)) $(I Type) $(D $(RPAREN)))) + + $(P + The condition is satisfied if $(I Type) is semantically + correct. *Type* must be syntactically correct regardless. + ) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +pragma(msg, is(5)); // error +pragma(msg, is([][])); // error +--- +) +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------------- +int i; +static assert(is(int)); +static assert(is(typeof(i))); // same + +static assert(!is(Undefined)); +static assert(!is(typeof(int))); // int is not an expression +static assert(!is(i)); // i is a value + +alias Func = int(int); // function type +static assert(is(Func)); +static assert(!is(Func[])); // fails as an array of functions is not allowed +------------- +) + $(H5 $(LNAME2 is-type-convert, $(D is $(LPAREN)) $(I Type) $(D :) $(I TypeSpecialization) $(D $(RPAREN)))) + + $(P + The condition is satisfied if $(I Type) is semantically + correct and it is the same as + or can be implicitly converted to $(I TypeSpecialization). + $(I TypeSpecialization) is only allowed to be a $(I Type). + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------------- +alias Bar = short; +static assert(is(Bar : int)); // short implicitly converts to int +static assert(!is(Bar : string)); +------------- +) + $(H5 $(LNAME2 is-type-equal, $(D is $(LPAREN)) $(I Type) $(D ==) $(I TypeSpecialization) $(D $(RPAREN)))) + + $(P + If *TypeSpecialization* is a type, + the condition is satisfied if $(I Type) is semantically correct and is + the same type as $(I TypeSpecialization). + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------------- +alias Bar = short; +static assert(is(Bar == short)); +static assert(!is(Bar == int)); +------------- +) + $(P + If *TypeSpecialization* is a $(GLINK2 type, TypeCtor) + then the condition is satisfied if *Type* is of that *TypeCtor*: + ) +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +static assert(is(const int == const)); +static assert(is(const int[] == const)); +static assert(!is(const(int)[] == const)); // head is mutable +static assert(!is(immutable int == const)); +--- +) + $(P + If $(I TypeSpecialization) is one of + $(D struct) + $(D union) + $(D class) + $(D interface) + $(D enum) + $(D __vector) + $(D function) + $(D delegate) + $(D module) + $(D package) + then the condition is satisfied if $(I Type) is one of those. + ) +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +Object o; +static assert(!is(o == class)); // `o` is not a type +static assert(is(Object == class)); +static assert(is(ModuleInfo == struct)); +static assert(!is(int == class)); + +void f(); +static assert(!is(f == function)); // `f` is not a type +static assert(is(typeof(f) == function)); +static assert(!is(typeof(&f) == function)); // function pointer is not a function +--- +) + $(P The `module` and `package` forms are satisfied when *Type* is a symbol, not a *type*, + unlike the other forms. The $(DDSUBLINK spec/traits, isModule, isModule) + and $(DDSUBLINK spec/traits, isPackage, isPackage) `__traits` should be used instead. + $(DDSUBLINK spec/module, package-module, Package modules) are considered to be both + packages and modules. + ) + $(P + *TypeSpecialization* can also be one of these keywords: + ) + $(TABLE + $(THEAD keyword, condition) + $(TROW `super`, `true` if *Type* is a class or interface) + $(TROW `return`, + $(ARGS `true` if *Type* is a function, delegate or function pointer)) + $(TROW `__parameters`, + $(ARGS `true` if *Type* is a function, delegate or function pointer)) + ) + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + class C {} + static assert(is(C == super)); + + void foo(int i); + static assert(!is(foo == return)); + static assert(is(typeof(foo) == return)); + static assert(is(typeof(foo) == __parameters)); + --- + ) + $(P $(B See also:) $(DDLINK spec/traits, Traits, Traits).) + + +$(H4 $(LNAME2 is-identifier, Identifier Forms)) + + $(P *Identifier* is declared to be an alias of the resulting + type if the condition is satisfied. The *Identifier* forms + can only be used if the $(I IsExpression) appears in a + $(GLINK2 version, StaticIfCondition) or the first argument of a + $(GLINK2 version, StaticAssert). + ) + + $(H5 $(LNAME2 is-type-identifier, $(D is $(LPAREN)) $(I Type) $(I Identifier) $(D $(RPAREN)))) + + $(P + The condition is satisfied if $(I Type) is semantically + correct. If so, $(I Identifier) + is declared to be an alias of $(I Type). + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct S +{ + int i, j; +} +static assert(is(typeof(S.i) T) && T.sizeof == 4); +--- +) +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------------- +alias Bar = short; + +void foo() +{ + static if (is(Bar T)) + alias S = T; + else + alias S = long; + + pragma(msg, S); // short + + // if T was defined, it remains in scope + if (is(T)) + pragma(msg, T); // short + + //if (is(Bar U)) {} // error, cannot declare U here +} +------------- +) + + $(H5 $(LNAME2 is-identifier-convert, $(D is $(LPAREN)) $(I Type) $(I Identifier) $(D :) $(I TypeSpecialization) $(D $(RPAREN)) + ) + + $(P + If *TypeSpecialization* is a type, + the condition is satisfied if $(I Type) is semantically + correct and it is the same as + or can be implicitly converted to $(I TypeSpecialization). + $(I Identifier) is declared to be an alias of the + $(I TypeSpecialization). + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + alias Bar = int; + + static if (is(Bar T : int)) + alias S = T; + else + alias S = long; + + static assert(is(S == int)); + --- + ) + $(P + If $(I TypeSpecialization) is a type pattern involving + $(I Identifier), type deduction of $(I Identifier) is attempted + based on either *Type* or a type that it implicitly converts to. + The condition is only satisfied if the type pattern is matched. + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S + { + long* i; + alias i this; // S converts to long* + } + + static if (is(S U : U*)) // S is matched against the pattern U* + { + U u; + } + static assert(is(U == long)); + --- + ) + + $(P + The way the type of $(I Identifier) is determined is analogous + to the way template parameter types are determined by + $(GLINK2 template, TemplateTypeParameterSpecialization). + ) + + $(H5 $(LNAME2 is-identifier-equal, $(D is $(LPAREN)) $(I Type) $(I Identifier) $(D ==) $(I TypeSpecialization) $(D $(RPAREN)))) + + $(P + If *TypeSpecialization* is a type, + the condition is satisfied if $(I Type) is semantically correct and is + the same type as $(I TypeSpecialization). + $(I Identifier) is declared to be an alias of the + $(I TypeSpecialization). + ) + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + const x = 5; + + static if (is(typeof(x) T == const int)) // satisfied, T is now defined + alias S = T; + + static assert(is(T)); // T is in scope + pragma(msg, T); // const int + --- + ) + + $(P + If $(I TypeSpecialization) is a type pattern involving + $(I Identifier), type deduction of $(I Identifier) is attempted + based on *Type*. + The condition is only satisfied if the type pattern is matched. + ) + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + alias Foo = long*; + + static if (is(Foo U == U*)) // Foo is matched against the pattern U* + { + U u; + } + static assert(is(U == long)); + --- + ) + $(P + If *TypeSpecialization* is a valid keyword for the + $(RELATIVE_LINK2 is-type-equal, `is(Type == Keyword)` form), + the condition is satisfied in the same manner. + $(I Identifier) is set as follows: + ) + + $(TABLE_2COLS , + $(THEAD keyword, alias type for $(I Identifier)) + + $(TROW $(CODE struct), $(I Type)) + $(TROW $(D union), $(I Type)) + $(TROW $(D class), $(I Type)) + $(TROW $(D interface), $(I Type)) + $(TROW $(D super), $(I TypeSeq) of base classes and interfaces) + $(TROW $(D enum), the base type of the enum) + $(TROW $(D __vector), the static array type of the vector) + $(TROW $(D function), $(ARGS $(I TypeSeq) of the function parameter types. + For C- and D-style variadic functions, + only the non-variadic parameters are included. + For typesafe variadic functions, the $(D ...) is ignored.)) + $(TROW $(CODE delegate), the function type of the delegate) + $(TROW $(CODE return), $(ARGS the return type of the function, delegate, or function pointer)) + $(TROW $(CODE __parameters), $(ARGS the parameter sequence of a function, delegate, or function pointer. + This includes the parameter types, names, and default values.)) + $(TROW $(D const), $(I Type)) + $(TROW $(D immutable), $(I Type)) + $(TROW $(D inout), $(I Type)) + $(TROW $(D shared), $(I Type)) + $(TROW $(D module), the module) + $(TROW $(D package), the package) + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + enum E : byte { Emember } + + static if (is(E V == enum)) // satisfied, E is an enum + V v; // v is declared to be a byte + + static assert(is(V == byte)); + --- + ) + +$(H4 $(LNAME2 is-parameter-list, Parameter List Forms)) + +$(GRAMMAR_INFORMATIVE +$(D is $(LPAREN)) $(I Type) $(D :) $(I TypeSpecialization) $(D ,) $(GLINK2 template, TemplateParameterList) $(D $(RPAREN)) +$(D is $(LPAREN)) $(I Type) $(D ==) $(I TypeSpecialization) $(D ,) $(GLINK2 template, TemplateParameterList) $(D $(RPAREN)) +$(D is $(LPAREN)) $(I Type) $(I Identifier) $(D :) $(I TypeSpecialization) $(D ,) $(GLINK2 template, TemplateParameterList) $(D $(RPAREN)) +$(D is $(LPAREN)) $(I Type) $(I Identifier) $(D ==) $(I TypeSpecialization) $(D ,) $(GLINK2 template, TemplateParameterList) $(D $(RPAREN)) +) + + $(P + More complex types can be pattern matched. The + $(I TemplateParameterList) declares symbols based on the + parts of the pattern that are matched, analogously to the + way $(DDSUBLINK spec/template, parameters_specialization, + implied template parameters) are matched. + ) + +$(P $(B Example:) Matching a Template Instantiation)) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct Tuple(T...) + { + // ... + } + alias Tup2 = Tuple!(int, string); + + static if (is(Tup2 : Template!Args, alias Template, Args...)) + { + static assert(__traits(isSame, Template, Tuple)); + static assert(is(Template!(int, string) == Tup2)); // same struct + } + static assert(is(Args[0] == int)); + static assert(is(Args[1] == string)); + --- +) + + $(P *Type* cannot be matched when *TypeSpecialization* is an + $(DDSUBLINK spec/template, alias-template, alias template) instance: + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S(T) {} + alias A(T) = S!T; + + static assert(is(A!int : S!T, T)); + //static assert(!is(A!int : A!T, T)); + --- + ) + +$(P $(B Example:) Matching an Associative Array) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + alias AA = long[string]; + + static if (is(AA T : T[U], U : string)) // T[U] is the pattern + { + pragma(msg, T); // long + pragma(msg, U); // string + } + + // no match, B is not an int + static assert(!is(AA A : A[B], B : int)); + --- +) + +$(P $(B Example:) Matching a Static Array) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + static if (is(int[10] W : W[len], int len)) // W[len] is the pattern + { + static assert(len == 10); + } + static assert(is(W == int)); + + // no match, len should be 10 + static assert(!is(int[10] X : X[len], int len : 5)); + --- +) + + +$(H3 $(LNAME2 RvalueExpression, Rvalue Expression)) + +$(GRAMMAR +$(GNAME RvalueExpression): + $(D __rvalue $(LPAREN)) $(GLINK AssignExpression) $(D $(RPAREN)) +) + + $(P The $(I RvalueExpression) causes the embedded $(I AssignExpression) to be + treated as an rvalue whether it is an rvalue or an lvalue.) + +$(H4 Overloading) + + $(P If both ref and non-ref parameter overloads are present, an rvalue is preferably matched to the + non-ref parameters, and an lvalue is preferably matched to the ref parameter. + An $(I RvalueExpression) will preferably match with the non-ref parameter.) + +$(H4 Semantics of Arguments Matched to Rvalue Parameters) + + $(P An rvalue argument is owned by the function called. Hence, if an lvalue is matched + to the rvalue argument, a copy is made of the lvalue to be passed to the function. The function + will then call the destructor (if any) on the parameter at the conclusion of the function. + An rvalue argument is not copied, as it is assumed to already be unique, and is also destroyed at + the conclusion of the function.) + + $(P The called function's semantics are the same whether a parameter originated as an rvalue + or is a copy of an lvalue. + This means that an $(I RvalueExpression) argument destroys the expression upon function return. + Attempts to continue to use the lvalue expression are invalid. The compiler won't always be able + to detect a use after being passed to the function, which means that the destructor for the object + must reset the object's contents to its initial value, or at least a benign value that can + be destructed more than once. + ) + +--- +struct S +{ + ubyte* p; + ~this() + { + free(p); + // add `p = null;` here to prevent double free + } +} + +void aggh(S s) +{ +} + +void oops() +{ + S s; + s.p = cast(ubyte*)malloc(10); + aggh(__rvalue(s)); + // destructor of s called at end of scope, double-freeing s.p +} +--- + + $(P $(I RvalueExpression)s enable the use of $(I move constructor)s and $(I move assignment)s.) + +$(H4 $(LNAME2 __rvalue-function-attribute, As a function attribute)) + + $(P It is also allowed to use the $(CODE __rvalue) keyword as a function attribute. The presence of this + attribute will infer the $(I RvalueExpression) upon the function call expression at the call-site, + as if applied to the function's return value. This is only accepted on functions that return by reference. + ) + +--- +ref S fun(return ref S s) __rvalue +{ + return s; +} + +S s; +S t = fun(s); // call inferred as: __rvalue(fun(s)) +--- + +$(H3 $(LNAME2 specialkeywords, Special Keywords)) + +$(GRAMMAR +$(GNAME SpecialKeyword): + $(RELATIVE_LINK2 specialkeywords, $(D __FILE__)) + $(RELATIVE_LINK2 specialkeywords, $(D __FILE_FULL_PATH__)) + $(RELATIVE_LINK2 specialkeywords, $(D __MODULE__)) + $(RELATIVE_LINK2 specialkeywords, $(D __LINE__)) + $(RELATIVE_LINK2 specialkeywords, $(D __FUNCTION__)) + $(RELATIVE_LINK2 specialkeywords, $(D __PRETTY_FUNCTION__)) +) + + + $(P $(CODE __FILE__) and $(CODE __LINE__) expand to the source + file name and line number at the point of instantiation. The path of + the source file is left up to the compiler. ) + + $(P $(CODE __FILE_FULL_PATH__) expands to the absolute source + file name at the point of instantiation.) + + $(P $(CODE __MODULE__) expands to the module name at the point of + instantiation.) + + $(P $(CODE __FUNCTION__) expands to the fully qualified name of the + function at the point of instantiation.) + + $(P $(CODE __PRETTY_FUNCTION__) is similar to $(CODE __FUNCTION__), + but also expands the function return type, its parameter types, + and its attributes.) + + $(P Example:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + module test; + import std.stdio; + + void test(string file = __FILE__, size_t line = __LINE__, + string mod = __MODULE__, string func = __FUNCTION__, + string pretty = __PRETTY_FUNCTION__, + string fileFullPath = __FILE_FULL_PATH__) + { + writefln("file: '%s', line: '%s', module: '%s',\nfunction: '%s', " ~ + "pretty function: '%s',\nfile full path: '%s'", + file, line, mod, func, pretty, fileFullPath); + } + + int main(string[] args) + { + test(); + return 0; + } + --- + ) + + $(P Assuming the file was at /example/test.d, this will output:) + +$(CONSOLE +file: 'test.d', line: '13', module: 'test', +function: 'test.main', pretty function: 'int test.main(string[] args)', +file full path: '/example/test.d' +) + + $(PANEL $(P $(RED Warning): Do not use $(D mixin(__FUNCTION__)) to get the + symbol for the current function. This seems to be a common + thing for programmers to attempt when trying to get the symbol + for the current function in order to do introspection on it, + since D does not currently have a direct way to get that + symbol. However, using $(D mixin(__FUNCTION__)) means that the + symbol for the function will be looked up by name, which means + that it's subject to the various rules that go with symbol + lookup, which can cause various problems. One such problem + would that if a function is overloaded, the result will be the + first overload whether that's the current function or not.) + + $(P Given that D doesn't currently have a way to directly get the + symbol for the current function, the best way to do it is to + get the parent symbol of a symbol within the function, since + that avoids any issues surrounding symbol lookup rules. An + example of that which doesn't rely on any other symbols is + $(D __traits(parent {})). It declares an anonymous, nested + function, whose parent is then the current function. So, + getting its parent gets the symbol for the current function.)) + +$(H2 $(LNAME2 associativity, Associativity and Commutativity)) + + $(P An implementation may rearrange the evaluation of expressions + according to arithmetic associativity and commutativity rules + as long as, within that thread of execution, no observable + difference is possible. + ) + + $(P This rule precludes any associative or commutative reordering of + floating point expressions. + ) +$(SPEC_SUBNAV_PREV_NEXT pragma, Pragmas, statement, Statements) +) + +Macros: + CHAPTER=11 + TITLE=Expressions + IDENTIFIER=$(GLINK_LEX Identifier) + USUAL_ARITHMETIC_CONVERSIONS=$(DDSUBLINK spec/type, usual-arithmetic-conversions, Usual Arithmetic Conversions) + INTEGER_PROMOTIONS=$(DDSUBLINK spec/type, integer-promotions, Integer Promotions) + _= diff --git a/spec/float.dd b/spec/float.dd new file mode 100644 index 0000000000..43af194722 --- /dev/null +++ b/spec/float.dd @@ -0,0 +1,163 @@ +Ddoc + +$(SPEC_S Floating-Point, + +$(HEADERNAV_TOC) + +$(H2 $(LNAME2 fp_intermediate_values, Floating-Point Intermediate Values)) + + $(P For floating-point operations and expression intermediate values, + a greater precision can be used than the type of the + expression. + Only the minimum precision is set by the types of the + operands, not the maximum. $(B Implementation Note:) On Intel + x86 machines, for example, + it is expected (but not required) that the intermediate + calculations be done to the full 80 bits of precision + implemented by the hardware. + ) + + $(P Execution of floating-point expressions may yield a result of greater precision than dictated + by the source.) + +$(H2 $(LNAME2 fp_const_folding, Floating-Point Constant Folding)) + + $(P Regardless of the type of the operands, floating-point + constant folding is done in $(D real) or greater precision. + It is always done following $(LINK2 https://standards.ieee.org/standard/754-2019.html, IEEE-754) rules and round-to-nearest + is used.) + + $(P Floating-point constants are internally represented in + the implementation in at least $(D real) precision, regardless + of the constant's type. The extra precision is available for + constant folding. Committing to the precision of the result is + done as late as possible in the compilation process. For example:) + +--- +const float f = 0.2f; +writeln(f - 0.2); +--- + $(P will print 0. A non-const static variable's value cannot be + propagated at compile time, so:) + +--- +static float f = 0.2f; +writeln(f - 0.2); +--- + $(P will print 2.98023e-09. Hex floating-point constants can also + be used when specific floating-point bit patterns are needed that + are unaffected by rounding. To find the hex value of 0.2f:) + +--- +import std.stdio; + +void main() +{ + writefln("%a", 0.2f); +} +--- + $(P which is 0x1.99999ap-3. Using the hex constant:) + +--- +const float f = 0x1.99999ap-3f; +writeln(f - 0.2); +--- + + $(P prints 2.98023e-09.) + + $(P Different compiler settings, optimization settings, + and inlining settings can affect opportunities for constant + folding, therefore the results of floating-point calculations may differ + depending on those settings.) + +$(H2 $(LNAME2 rounding_control, Rounding Control)) + + $(P IEEE 754 floating-point arithmetic includes the ability to set 4 + different rounding modes. + These are accessible via the functions in $(D core.stdc.fenv). + ) + + $(P If the floating-point rounding mode is changed within a function, + it must be restored before the function exits. If this rule is violated + (for example, by the use of inline asm), the rounding mode used for + subsequent calculations is undefined. + ) + + +$(H2 $(LNAME2 exception_flags, Exception Flags)) + + $(P IEEE 754 floating-point arithmetic can set several flags based on what + happened with a + computation:) + + $(TABLE + $(TR $(TD $(D FE_INVALID))) + $(TR $(TD $(D FE_DENORMAL))) + $(TR $(TD $(D FE_DIVBYZERO))) + $(TR $(TD $(D FE_OVERFLOW))) + $(TR $(TD $(D FE_UNDERFLOW))) + $(TR $(TD $(D FE_INEXACT))) + ) + + $(P These flags can be set/reset via the functions in $(D core.stdc.fenv).) + +$(H2 $(LNAME2 floating-point-transformations, Floating-Point Transformations)) + + $(P An implementation may perform transformations on + floating-point computations in order to reduce their strength. + ) + + $(P Not all transformations are valid: The following + transformations of floating-point expressions + are not allowed because under IEEE rules they could produce + different results. + ) + + $(TABLE2 Disallowed Floating-Point Transformations, + $(THEAD transformation, comments) + $(TROW + $(ARGS $(I x) + 0 $(RARR) $(I x)) , $(ARGS not valid if $(I x) is -0) + ) + $(TROW + $(ARGS $(I x) - 0 $(RARR) $(I x)) , $(ARGS not valid if $(I x) is $(PLUSMN)0 and rounding is towards -$(INFIN)) + ) + $(TROW + $(ARGS -$(I x) $(HARR) 0 - $(I x)) , $(ARGS not valid if $(I x) is +0) + ) + $(TROW + $(ARGS $(I x) - $(I x) $(RARR) 0) , $(ARGS not valid if $(I x) is NaN or $(PLUSMN)$(INFIN)) + ) + $(TROW + $(ARGS $(I x) - $(I y) $(HARR) -($(I y) - $(I x))) , $(ARGS not valid because (1-1=+0) whereas -(1-1)=-0) + ) + $(TROW + $(ARGS $(I x) * 0 $(RARR) 0) , $(ARGS not valid if $(I x) is NaN or $(PLUSMN)$(INFIN)) + ) +$(COMMENT + $(TROW + $(ARGS $(I x) * 1 $(RARR) $(I x)) , $(ARGS not valid if $(I x) is a signaling NaN) + ) +) + $(TROW + $(ARGS $(I x) / $(I c) $(HARR) $(I x) * (1/$(I c))) , $(ARGS valid if (1/$(I c)) yields an e$(I x)act result) + ) + $(TROW + $(ARGS $(I x) != $(I x) $(RARR) false) , $(ARGS not valid if $(I x) is a NaN) + ) + $(TROW + $(ARGS $(I x) == $(I x) $(RARR) true) , $(ARGS not valid if $(I x) is a NaN) + ) + $(TROW + $(ARGS $(I x) !$(I op) $(I y) $(HARR) !($(I x) $(I op) $(I y))) , $(ARGS not valid if $(I x) or $(I y) is a NaN) + ) + ) + + $(P Of course, transformations that would alter side effects are also + invalid.) + +$(SPEC_SUBNAV_PREV_NEXT garbage, Garbage Collection, iasm, D x86 Inline Assembler) +) + +Macros: + CHAPTER=30 + TITLE=Floating-Point diff --git a/spec/footer_gen.d b/spec/footer_gen.d new file mode 100755 index 0000000000..7650aafb4d --- /dev/null +++ b/spec/footer_gen.d @@ -0,0 +1,75 @@ +#!/usr/bin/env rdmd +/* + * Footer generator for the specification pages. + * This script can be used to update the nav footers. + * + * Copyright (C) 2017 by D Language Foundation + * + * Author: Sebastian Wilzbach + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) +*/ +// Written in the D programming language. + +void main() +{ + import std.algorithm, std.array, std.ascii, std.conv, std.file, std.path, std.range, std.string, std.typecons; + import std.stdio : File, writeln, writefln; + auto specDir = __FILE_FULL_PATH__.dirName.buildNormalizedPath; + auto mainFile = specDir.buildPath("./spec.ddoc"); + enum ddocKey = "$(SPEC_SUBNAV_"; + + alias Entry = Tuple!(string, "name", string, "title"); + Entry[] entries; + + // parse the menu from the Ddoc file + auto specText = mainFile.readText; + if (!specText.findSkip("SUBMENU2")) + writeln("Menu file has an invalid format."); + foreach (line; specText.splitter("\n")) + { + enum ddocEntryStart = "$(ROOT_DIR)spec/"; + if (line.canFind(ddocEntryStart)) + { + auto ps = line.splitter(ddocEntryStart).dropOne.front.splitter(","); + entries ~= Entry(ps.front.stripExtension.withExtension(".dd").to!string, + ps.dropOne.front.idup.strip); + } + } + + foreach (i, entry; entries) + { + // build the prev|next Ddoc string + string navString = ddocKey; + if (i == 0) + navString ~= text("NEXT ", entries[i + 1].name.stripExtension, ", ", entries[i + 1].title); + else if (i < entries.length - 1) + navString ~= text("PREV_NEXT ", entries[i - 1].name.stripExtension, ", ", entries[i - 1].title, ", ", + entries[i + 1].name.stripExtension, ", ", entries[i + 1].title); + else + navString ~= text("PREV ", entries[i - 1].name.stripExtension, ", ", entries[i - 1].title); + + navString ~= ")"; + writefln("%s: %s", entry.name, navString); + auto fileName = specDir.buildPath(entry.name); + + auto text = fileName.readText; + // idempotency - check for existing tags, otherwise insert new + auto pos = text.representation.countUntil(ddocKey); + if (pos > 0) + { + auto len = text[pos .. $].representation.countUntil(")"); + text = text.replace(text[pos .. pos + len + 1], navString); + } + else + { + // insert at the end of the ddoc page + auto v = text[0 .. $ - text.retro.countUntil((newline ~ "Macros:").retro)]; + pos = v.length - v.retro.countUntil(")"); + text.insertInPlace(pos - 1, navString ~ "\n"); + } + fileName.write(text); + } +} diff --git a/spec/function.dd b/spec/function.dd new file mode 100644 index 0000000000..928492bd1f --- /dev/null +++ b/spec/function.dd @@ -0,0 +1,4451 @@ +Ddoc + +$(SPEC_S Functions, + +$(HEADERNAV_TOC) + +$(H2 $(LNAME2 grammar, Function Declarations)) + +$(GRAMMAR +$(GNAME FuncDeclaration): + $(GLINK2 declaration, StorageClasses)$(OPT) $(GLINK2 type, BasicType) $(GLINK FuncDeclarator) $(GLINK FunctionBody) + $(GLINK2 declaration, StorageClasses)$(OPT) $(GLINK2 type, BasicType) $(GLINK FuncDeclarator) $(GLINK MissingFunctionBody) + $(GLINK AutoFuncDeclaration) + +$(GNAME AutoFuncDeclaration): + $(GLINK2 declaration, StorageClasses) $(GLINK_LEX Identifier) $(GLINK FuncDeclaratorSuffix) $(GLINK FunctionBody) + +$(GNAME FuncDeclarator): + $(GLINK2 type, TypeSuffixes)$(OPT) $(GLINK_LEX Identifier) $(GLINK FuncDeclaratorSuffix) + +$(GNAME FuncDeclaratorSuffix): + $(GLINK Parameters) $(GLINK MemberFunctionAttributes)$(OPT) + $(GLINK2 template, TemplateParameters) $(GLINK Parameters) $(GLINK MemberFunctionAttributes)$(OPT) $(GLINK2 template, Constraint)$(OPT) +) + + * A *FuncDeclaration* with a function body is called a + $(RELATIVE_LINK2 function-bodies, function definition). + * A *FuncDeclaration* without a function body is called a + $(RELATIVE_LINK2 function-declarations, function prototype). + * A *FuncDeclaration* with *TemplateParameters* defines a + $(DDSUBLINK spec/template, function-templates, function template). + + +$(H3 Function Parameters) + +$(GRAMMAR +$(GNAME Parameters): + $(D $(LPAREN)) $(GLINK ParameterList)$(OPT) $(D $(RPAREN)) + +$(GNAME ParameterList): + $(GLINK Parameter) + $(GLINK Parameter) $(D ,) $(GSELF ParameterList)$(OPT) + $(GLINK VariadicArgumentsAttributes)$(OPT) $(D ...) + +$(GNAME Parameter): + $(GLINK ParameterDeclaration) + $(GLINK ParameterDeclaration) $(D ...) + $(GLINK ParameterDeclaration) $(D =) $(ASSIGNEXPRESSION) + $(GLINK ParameterDeclaration) $(D =) $(ASSIGNEXPRESSION) $(D ...) + +$(GNAME ParameterDeclaration): + $(GLINK ParameterAttributes)$(OPT) $(GLINK2 type, BasicType) $(GLINK2 declaration, Declarator) + $(GLINK ParameterAttributes)$(OPT) $(GLINK2 type, Type) + +$(GNAME ParameterAttributes): + $(GLINK ParameterStorageClass) + $(GLINK2 attribute, UserDefinedAttribute) + $(GSELF ParameterAttributes) $(GLINK ParameterStorageClass) + $(GSELF ParameterAttributes) $(GLINK2 attribute, UserDefinedAttribute) + +$(GNAME ParameterStorageClass): + $(D auto) + $(GLINK2 type, TypeCtor) + $(D final) + $(D in) + $(D lazy) + $(D out) + $(D ref) + $(D return) + $(D scope) + +$(GNAME VariadicArgumentsAttributes): + $(GLINK VariadicArgumentsAttribute) + $(GLINK VariadicArgumentsAttribute) $(GSELF VariadicArgumentsAttributes) + +$(GNAME VariadicArgumentsAttribute): + $(D const) + $(D immutable) + $(D return) + $(D scope) + $(D shared) +) + +$(NOTE In D2, declaring a parameter `final` is a semantic error, but not a parse error.) + +$(P See also: $(RELATIVE_LINK2 param-storage, parameter storage classes).) + +$(H3 Function Attributes) + +$(GRAMMAR +$(GNAME FunctionAttributes): + $(GLINK FunctionAttribute) + $(GLINK FunctionAttribute) $(GSELF FunctionAttributes) + +$(GNAME FunctionAttribute): + $(GLINK2 attribute, FunctionAttributeKwd) + $(GLINK2 attribute, Property) + $(GLINK2 attribute, AtAttribute) + +$(GNAME MemberFunctionAttributes): + $(GLINK MemberFunctionAttribute) + $(GLINK MemberFunctionAttribute) $(GSELF MemberFunctionAttributes) + +$(GNAME MemberFunctionAttribute): + $(D const) + $(D immutable) + $(D inout) + $(D return) + $(D scope) + $(D shared) + $(GLINK FunctionAttribute) +) + +$(H3 $(LNAME2 function-bodies, Function Bodies)) + +$(GRAMMAR +$(GNAME FunctionBody): + $(GLINK SpecifiedFunctionBody) + $(GLINK ShortenedFunctionBody) + +$(GNAME SpecifiedFunctionBody): + $(D do)$(OPT) $(GLINK2 statement, BlockStatement) + $(GLINK FunctionContracts)$(OPT) $(GLINK InOutContractExpression) $(D do)$(OPT) $(GLINK2 statement, BlockStatement) + $(GLINK FunctionContracts)$(OPT) $(GLINK InOutStatement) $(D do) $(GLINK2 statement, BlockStatement) + +$(GNAME ShortenedFunctionBody): + $(GLINK InOutContractExpressions)$(OPT) $(D =>) $(GLINK2 expression, AssignExpression) $(D ;) +) + + $(P Examples:) + + --- + int hasSpecifiedBody() { return 1; } + int hasShortenedBody() => 1; // equivalent + --- + +$(LEGACY_LNAME2 FunctionLiteralBody) + $(P The *ShortenedFunctionBody* form implies a + $(DDSUBLINK spec/statement, ReturnStatement, return statement). + This syntax also applies for $(DDSUBLINK spec/expression, function_literals, function literals).) + + +$(H3 $(LNAME2 function-declarations, Function Prototypes)) + +$(GRAMMAR +$(GNAME MissingFunctionBody): + $(D ;) + $(GLINK FunctionContracts)$(OPT) $(GLINK InOutContractExpression) $(D ;) + $(GLINK FunctionContracts)$(OPT) $(GLINK InOutStatement) +) + + $(P Function declarations with a *MissingFunctionBody*, e.g.:) + +--- +int foo(); +--- + + $(P that are not declared as $(DDSUBLINK spec/class, abstract, `abstract`) + are expected to have their implementations + elsewhere, and that implementation will be provided at the link step. + This enables an implementation of a function to be completely hidden from the user + of it, and the implementation may be in another language such as C, assembler, etc. + Typically a function prototype would have non-`extern(D)` + $(DDSUBLINK spec/attribute, linkage, linkage). + ) + + $(P A function prototype can have `extern(D)` linkage. + This is useful for $(DDSUBLINK dmd, interface-files, D interface files). + ) + + +$(H2 $(LNAME2 contracts, Function Contracts)) + +$(GRAMMAR +$(GNAME FunctionContracts): + $(GLINK FunctionContract) + $(GLINK FunctionContract) $(GSELF FunctionContracts) + +$(GNAME FunctionContract): + $(GLINK InOutContractExpression) + $(GLINK InOutStatement) + +$(GNAME InOutContractExpressions): + $(GLINK InOutContractExpression) + $(GLINK InOutContractExpression) $(GSELF InOutContractExpressions) + +$(GNAME InOutContractExpression): + $(GLINK InContractExpression) + $(GLINK OutContractExpression) + +$(GNAME InOutStatement): + $(GLINK InStatement) + $(GLINK OutStatement) +) + + $(P Function Contracts specify the preconditions and postconditions of a function. + They are used in $(LINK2 contracts.html, Contract Programming). + ) + + $(P Preconditions and postconditions do not affect the type of the function.) + + $(H3 $(LNAME2 preconditions, Preconditions)) + +$(GRAMMAR +$(GNAME InContractExpression): + $(D in $(LPAREN)) $(GLINK2 expression, AssertArguments) $(D $(RPAREN)) + +$(GNAME InStatement): + $(D in) $(GLINK2 statement, BlockStatement) +) + + $(P An $(I InContractExpression) is a precondition.) + + * The first $(GLINK2 expression, AssignExpression) of the $(I AssertArguments) + must evaluate to true. If it does not, the precondition has failed.) + + * The second $(I AssignExpression), if present, must be implicitly convertible to type `const(char)[]`. + + $(P An $(GLINK InStatement) is also a precondition. Any $(GLINK2 expression, AssertExpression) appearing + in an $(I InStatement) will be an $(I InContractExpression). + ) + + $(P Preconditions must semantically be satisfied before the function starts executing. + If a precondition fails, the program enters an $(I Invalid State). + ) + + $(IMPLEMENTATION_DEFINED Whether the preconditions are actually run or not is implementation defined. + This is usually selectable with a compiler switch. + Its behavior upon precondition failure is also usually selectable with a compiler switch. + One option is to throw an `AssertError` with a message consisting of the optional second + $(I AssignExpression). + ) + + $(BEST_PRACTICE Use preconditions to validate that input arguments have values that are + expected by the function.) + + $(BEST_PRACTICE Since preconditions may or may not be actually checked at runtime, avoid + using preconditions that have side effects.) + + $(P The expression form is:) + + --- + in (expression) + in (expression, "failure string") + { + ...function body... + } + --- + + $(P The block statement form is:) + + --- + in + { + ...contract preconditions... + } + do + { + ...function body... + } + --- + + + $(H3 $(LNAME2 postconditions, Postconditions)) + +$(GRAMMAR +$(GNAME OutContractExpression): + $(D out $(LPAREN) ;) $(GLINK2 expression, AssertArguments) $(D $(RPAREN)) + $(D out $(LPAREN)) $(GLINK_LEX Identifier) $(D ;) $(GLINK2 expression, AssertArguments) $(D $(RPAREN)) + +$(GNAME OutStatement): + $(D out) $(GLINK2 statement, BlockStatement) + $(D out) $(D $(LPAREN)) $(GLINK_LEX Identifier) $(D $(RPAREN)) $(GLINK2 statement, BlockStatement) +) + + $(P An $(I OutContractExpression) is a postcondition.) + + * The first $(GLINK2 expression, AssignExpression) of the $(I AssertArguments) + must evaluate to true. If it does not, the postcondition has failed. + + * The second $(I AssignExpression), if present, must be implicitly convertible to type `const(char)[]`. + + $(P An $(I OutStatement) is also a postcondition. Any $(GLINK2 expression, AssertExpression) appearing + in an $(I OutStatement) will be an $(I OutContractExpression). + ) + + $(P Postconditions must semantically be satisfied after the function finishes executing. + If a postcondition fails, the program enters an $(I Invalid State). + ) + + $(IMPLEMENTATION_DEFINED Whether the postconditions are actually run or not is implementation defined. + This is usually selectable with a compiler switch. + Its behavior upon postcondition failure is also usually selectable with a compiler switch. + One option is to throw an `AssertError` with a message consisting of the optional second + $(I AssignExpression). + ) + + $(BEST_PRACTICE Use postconditions to validate that on leaving the function:) + * Any mutable input arguments each have the expected value/range of values. + * Any return value has a correct value/range of values. + + $(BEST_PRACTICE Since postconditions may or may not be actually checked at runtime, avoid + using postconditions that have side effects.) + + $(P The expression form is:) + + --- + out (identifier; expression) + out (identifier; expression, "failure string") + out (; expression) + out (; expression, "failure string") + { + ...function body... + } + --- + + $(P The block statement form is:) + + --- + out + { + ...contract postconditions... + } + out (identifier) + { + ...contract postconditions... + } + do + { + ...function body... + } + --- + + $(P The optional identifier in either type of postcondition is set to the return value + of the function, and can be accessed from within the postcondition. + It is implicitly `const`.) + + $(H3 $(LNAME2 example-contracts, Example)) + + --- + int fun(ref int a, int b) + in (a > 0) + in (b >= 0, "b cannot be negative!") + out (r; r > 0, "return must be positive") + out (; a != 0) + { + // function body + } + --- + + --- + int fun(ref int a, int b) + in + { + assert(a > 0); + assert(b >= 0, "b cannot be negative!"); + } + out (r) + { + assert(r > 0, "return must be positive"); + assert(a != 0); + } + do + { + // function body + } + --- + + $(P The two functions are identical semantically.) + + $(H3 $(LNAME2 in_out_inheritance, In, Out and Inheritance)) + + $(P If a function in a derived class overrides a function from its + super class, then only the preconditions of one of the + function and its overridden functions + must be satisfied. + Overriding + functions then becomes a process of $(I loosening) the preconditions. + ) + + $(P A function without preconditions means its precondition is always + satisfied. + Therefore if any + function in an inheritance hierarchy has no preconditions, + then any preconditions on functions overriding it have no meaningful + effect. + ) + + $(P Conversely, all of the postconditions of the function and its + overridden functions must to be satisfied. + Adding overriding functions then becomes a processes of $(I tightening) the + postconditions. + ) + + +$(H2 $(LNAME2 function-return-values, Function Return Values)) + + $(P One $(DDSUBLINK spec/statement, return-statement, return statement) per execution path + is required if the function specifies a return type that is not `void`, + unless:) + $(UL + $(LI the path executes an infinite loop) + $(LI the path evaluates an $(DDSUBLINK spec/expression, assert-ct, + `assert(0)` expression)) + $(LI the path evaluates an expression of type + $(DDSUBLINK spec/type, noreturn, `noreturn`)) + $(LI the path contains inline assembler code) + ) + + $(P Simple forms of the first 3 cases above can be recognized by the compiler, + but not all.) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +int error(int i) +{ + if (i & 1) + i++; + else + return i; + + // Error: no return statement +} +--- +) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +int f(int i) +{ + if (i >= 0) + return i; + + assert(0); + // OK, no return needed +} +--- +) + $(P Function return values not marked as $(RELATIVE_LINK2 ref-functions, `ref`) + are considered to be rvalues by the calling function. + This means they cannot be passed by reference to other functions. + ) + + +$(H2 $(LNAME2 pure-functions, Pure Functions)) + + $(P Pure functions are annotated with the `pure` attribute. + Pure functions cannot directly access global or static + mutable state. + Pure functions can only call pure functions.) + + $(P Pure functions can:) + $(UL + $(LI Modify the local state of the function.) + $(LI Throw exceptions.) + ) + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + int x; + immutable int y; + + pure int foo(int i) + { + i++; // ok, modifying local state + //x = i; // error, modifying global state + //i = x; // error, reading mutable global state + i = y; // ok, reading immutable global state + throw new Exception("failed"); // ok + } + --- + ) + + $(P A pure function can override an impure function, + but cannot be overridden by an impure function. + I.e. it is covariant with an impure function. + ) + +$(H3 $(LNAME2 weak-purity, Strong vs Weak Purity)) + + $(P A $(I weakly pure function) has parameters with mutable indirections. + Program state can be modified transitively through the matching + argument. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + pure size_t foo(int[] arr) + { + arr[] += 1; + return arr.length; + } + int[] a = [1, 2, 3]; + foo(a); + assert(a == [2, 3, 4]); + --- + ) + + $(P A $(I strongly pure function) has no parameters with mutable indirections + and cannot modify any program state external to the function. + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S { double x; } + + pure size_t foo(immutable(int)[] arr, int num, S val) + { + //arr[num] = 1; // compile error + num = 2; // has no side effect on the caller side + val.x = 3.14; // ditto + return arr.length; + } + --- + ) + + $(P A strongly pure function can call a weakly pure function.) + +$(H3 $(LNAME2 pure-special-cases, Special Cases)) + + $(P A pure function can:) + + $(UL + $(LI read and write the floating point exception flags) + $(LI read and write the floating point mode flags, as long as those + flags are restored to their initial state upon function entry) + ) + + $(UNDEFINED_BEHAVIOR occurs if these flags are not restored to their + initial state upon function exit. It is the programmer's responsibility + to ensure this. Setting these flags is not allowed in `@safe` code.) + +$(H4 $(LNAME2 pure-debug, Debugging)) + + $(P A pure function can perform impure operations in statements that are in a + $(GLINK2 version, ConditionalStatement) + controlled by a $(GLINK2 version, DebugCondition). + ) + + $(BEST_PRACTICE this relaxation of purity checks in *DebugCondition*s is + intended solely to make debugging programs easier.) + + --- + pure int foo(int i) + { + debug writeln("i = ", i); // ok, impure code allowed in debug statement + ... + } + --- + +$(H4 $(LNAME2 pure-nested, Nested Functions)) + + $(P $(RELATIVE_LINK2 nested, Nested functions) inside a pure function are implicitly marked as pure.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + pure int foo(int x, immutable int y) + { + int bar() + // implicitly marked as pure, to be "weakly pure" + // since hidden context pointer to foo stack context is mutable + { + x = 10; // can access states in enclosing scope + // through the mutable context pointer + return x; + } + pragma(msg, typeof(&bar)); // int delegate() pure + + int baz() immutable + // qualifies hidden context pointer with immutable, + // and has no other parameters, therefore "strongly pure" + { + //return x; // error, cannot access mutable data + // through the immutable context pointer + return y; // ok + } + + // can call pure nested functions + return bar() + baz(); + } + --- + ) + +$(H3 $(LNAME2 pure-factory-functions, Pure Factory Functions)) + + $(P A $(I pure factory function) is a strongly pure function + that returns a result that has only mutable indirections. + All mutable + memory returned by the call cannot be referenced by any other part of the + program, i.e. it is newly allocated by the function. + The mutable + references of the result similarly cannot refer to any object that + existed before the function call. + This allows the result to be implicitly cast + from anything to `immutable` or `const shared`, + and from `shared` and `const shared` to (unshared) `const`. + For example:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct List { int payload; List* next; } + + pure List* make(int a, int b) + { + auto result = new List(a, null); + result.next = new List(b, null); + return result; + } + + void main() + { + auto list = make(1, 2); + pragma(msg, typeof(list)); // List* + + immutable ilist = make(1, 2); + pragma(msg, typeof(ilist)); // immutable List* + pragma(msg, typeof(ilist.next)); // immutable List* + } + --- + ) + + $(P All references in `make`'s result refer to `List` + objects created by `make`, and no other part of the program refers to + any of these objects. Hence the result can initialize an immutable + variable.) + + $(P This does not affect any *Exception* or *Error* thrown from the function. + ) + +$(H3 $(LNAME2 pure-optimization, Optimization)) + + $(IMPLEMENTATION_DEFINED An implementation may assume that a strongly pure + function called with arguments that have only immutable indirections (or none) + that returns a result + without mutable indirections will have the same effect for all invocations + with equivalent arguments. It is allowed to memoize the result of the + function under the assumption that equivalent arguments always produce + equivalent results.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + int a(int) pure; // no mutable indirections + int b(const Object) pure; // depends on argument passed + immutable(Object) c(immutable Object) pure; // always memoizable + + void g(); + + void f(int n, const Object co, immutable Object io) + { + const int x = a(n); + g(); // `n` does not change between calls to `a` + int i = a(n); // same as `i = x` + + const int y = b(co); + // `co` may have mutable indirection + g(); // may change fields of `co` through another reference + i = b(co); // call is not memoizable, result may differ + + const int z = b(io); + i = b(io); // same as `i = z` + } + --- + ) + + $(P + Such a function may still have behavior + inconsistent with memoization by e.g. using `cast`s or by changing behavior + depending on the address of its parameters. An implementation is currently + not required to enforce validity of memoization in all cases. + ) + $(P + If a function throws an *Exception* or an *Error*, the + assumptions related to memoization do not carry to the thrown + exception.) + + $(P Pure destructors do not benefit of special elision.) + + +$(H2 $(LNAME2 nothrow-functions, Nothrow Functions)) + + $(P Nothrow functions can only throw exceptions derived + from $(LINK2 https://dlang.org/phobos/object.html#.Error, $(D class Error)). + ) + + $(P Nothrow functions are covariant with throwing ones.) + +$(H2 $(LNAME2 ref-functions, Ref Functions)) + + $(P A `ref` function returns by reference (instead of by value). + The return value of a `ref` function must be an lvalue + (whereas the return value of a non-`ref` function can be an rvalue, too). + An expression formed by calling a `ref` function is an lvalue + (whereas an expression formed by calling a non-`ref` function is an rvalue). + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +int *p; + +ref int foo() +{ + p = new int(2); + return *p; +} + +void main() +{ + int i = foo(); + assert(i == 2); + + foo() = 3; // reference returns can be lvalues + assert(*p == 3); +} +--- +) + + $(P Returning a reference to an expired function context is not allowed. + This includes local variables, temporaries and parameters that are part + of an expired function context. + ) + +--- +ref int sun() +{ + int i; + return i; // error, escaping a reference to local variable i +} +--- + + $(P A `ref` parameter may not be returned by `ref`, unless it is + $(RELATIVE_LINK2 return-ref-parameters, `return ref`).) +--- +ref int moon(ref int i) +{ + return i; // error +} +--- + + +$(H2 $(LNAME2 auto-functions, Auto Functions)) + + $(P Auto functions have their return type inferred from any + $(GLINK2 statement, ReturnStatement)s in the function body. + ) + + $(P An auto function is declared without a return type. + Auto functions can use any valid $(GLINK2 declaration, StorageClass), not just `auto`. + ) + + $(P If there are multiple $(I ReturnStatement)s, the types + of them must be implicitly convertible to a common type. + If there are no $(I ReturnStatement)s, the return type is inferred + to be $(D_KEYWORD void).) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + auto foo(int x) { return x + 3; } // inferred to be int + pure bar(int x) { return x; return 2.5; } // inferred to be double + --- + ) + + $(NOTE Return type inference also triggers + $(RELATIVE_LINK2 function-attribute-inference, attribute inference).) + + +$(H2 $(LNAME2 auto-ref-functions, Auto Ref Functions)) + + $(P Auto ref functions can infer their return type just as + $(RELATIVE_LINK2 auto-functions, auto functions) do. + In addition, they become $(RELATIVE_LINK2 ref-functions, ref functions) + if all of these apply:) + + * All expressions returned from the function are lvalues + * No local variables are returned + * Any parameters returned are reference parameters + * Each returned expression must implicitly convert to an lvalue of the deduced return type + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + auto ref f1(int x) { return x; } // value return + auto ref f2() { return 3; } // value return + auto ref f3(ref int x) { return x; } // ref return + auto ref f4(out int x) { return x; } // ref return + auto ref f5() + { + static int x; + return x; // ref return + } + --- + ) + + $(P The ref-ness of a function is determined from all + $(GLINK2 statement, ReturnStatement)s in the function body:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + auto ref f1(ref int x) { return 3; return x; } // ok, value return + auto ref f2(ref int x) { return x; return 3; } // ok, value return + auto ref f3(ref int x, ref double y) + { + return x; return y; + // The return type is deduced to be double, but cast(double)x is not an lvalue, + // so f3 has a value return. + } + --- + ) + + $(P Auto ref functions can have an explicit return type.) + + --- + auto ref int bar(ref int x) { return x; } // ok, ref return + auto ref int foo(double x) { return x; } // error, cannot convert double to int + --- + +$(H2 $(LNAME2 inout-functions, Inout Functions)) + + $(P For extensive information see $(DDSUBLINK spec/const3, inout, $(D inout) type qualifier).) + +$(H2 $(LNAME2 optional-parenthesis, Optional Parentheses)) + + $(P If a function call passes no explicit argument, i.e. it would syntactically use $(D ()), then these parentheses + may be omitted, similar to a getter invocation of a + $(RELATIVE_LINK2 property-functions, property function). + A $(RELATIVE_LINK2 pseudo-member, UFCS) call can also omit empty parentheses. + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + void foo() {} // no arguments + void fun(int x = 10) {} + void bar(int[] arr) {} + + void main() + { + foo(); // OK + foo; // also OK + fun; // OK + + int[] arr; + arr.bar(); // UFCS call + arr.bar; // also OK + } + --- + ) + + $(P Due to ambiguity, parentheses are required to call a delegate or a function pointer:) + + --- + void main() + { + int function() fp; + + assert(fp == 6); // Error, incompatible types int function() and int + assert(*fp == 6); // Error, incompatible types int() and int + + int delegate() dg; + assert(dg == 6); // Error, incompatible types int delegate() and int + } + --- + + $(P If a function returns a delegate or a function pointer, any parentheses + apply first to the function call, not the result. Two sets of parentheses are required + to call the result directly: + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + int getNum() { return 6; } + int function() getFunc() { return &getNum; } + + void main() + { + int function() fp; + + fp = getFunc; // implicit call + assert(fp() == 6); + + fp = getFunc(); // explicit call + assert(fp() == 6); + + int x = getFunc()(); + assert(x == 6); + } + --- + ) + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S + { + int getNum() { return 6; } + int delegate() getDel() return { return &getNum; } + } + + void main() + { + S s; + int delegate() dg; + + dg = s.getDel; // implicit call + assert(dg() == 6); + + dg = s.getDel(); // explicit call + assert(dg() == 6); + + int y = s.getDel()(); + assert(y == 6); + } + --- + ) + +$(H2 $(LNAME2 property-functions, Property Functions)) + + $(P WARNING: The definition and usefulness of property functions is being reviewed, and the implementation + is currently incomplete. Using property functions is not recommended until the definition is + more certain and implementation more mature.) + + $(P Properties are functions that can be syntactically treated + as if they were fields or variables. Properties can be read from or written to. + A property is read by calling a method or function with no arguments; + a property is written by calling a method or function with its argument + being the value it is set to. + ) + + $(P Simple getter and setter properties can be written using $(RELATIVE_LINK2 pseudo-member, UFCS). + These can be enhanced with the additon of the $(D @property) attribute to the function, which + adds the following behaviors: + ) + + $(UL + $(LI $(D @property) functions cannot be overloaded with non-$(D @property) functions with the same name.) + $(LI $(D @property) functions can only have zero, one or two parameters.) + $(LI $(D @property) functions cannot have variadic parameters.) + $(LI For the expression $(D typeof(exp)) where $(D exp) is an $(D @property) function, + the type is the return type of the function, rather than the type of the function.) + $(LI For the expression $(D __traits(compiles, exp)) where $(D exp) is an $(D @property) function, + a further check is made to see if the function can be called.) + $(LI $(D @property) are mangled differently, meaning that $(D @property) must be consistently + used across different compilation units.) + $(LI The ObjectiveC interface recognizes $(D @property) setter functions as special and modifies + them accordingly.) + ) + + $(P A simple property would be:) + + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct Foo + { + @property int data() { return m_data; } // read property + + @property int data(int value) { return m_data = value; } // write property + + private: + int m_data; + } + --- + ) + + $(P To use it:) + + --- + int test() + { + Foo f; + + f.data = 3; // same as f.data(3); + return f.data + 3; // same as return f.data() + 3; + } + --- + + $(P The absence of a read method means that the property is write-only. + The absence of a write method means that the property is read-only. + Multiple write methods can exist; the correct one is selected using + the usual function overloading rules. + ) + + $(P In all the other respects, these methods are like any other methods. + They can be static, have different linkages, have their address taken, etc. + ) + + $(P The built in properties $(D .sizeof), $(D .alignof), and $(D .mangleof) + may not be declared as fields or methods in structs, unions, classes or enums. + ) + + $(P If a property function has no parameters, it works as a getter. + If has exactly one parameter, it works as a setter. + ) + + +$(H2 $(LNAME2 virtual-functions, Virtual Functions)) + + $(P Virtual functions are class member functions that are called indirectly through a + function pointer table, called a `vtbl[]`, rather than directly. + Member functions that are virtual can be overridden in a derived class: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +class A +{ + void foo(int x) {} +} + +class B : A +{ + override void foo(int x) {} + //override void foo() {} // error, no foo() in A +} + +void test() +{ + A a = new B(); + a.foo(1); // calls B.foo(int) +} +------ +) + + $(P The `override` attribute is required when overriding a function. + This is useful for catching errors when a base class's member function + has its parameters changed, and all derived classes need to have + their overriding functions updated.) + + $(P The $(LNAME2 final, `final`) method attribute + prevents a subclass from overriding the method.) + + $(P The following are not virtual:) + $(UL + $(LI Struct and union member functions) + $(LI `final` member functions) + $(LI $(DDSUBLINK spec/attribute, static, `static`) member functions) + $(LI Member functions which are $(D private) or $(D package)) + $(LI Member template functions) + ) + + $(P $(B Example:)) + +------ +class A +{ + int def() { ... } + final int foo() { ... } + final private int bar() { ... } + private int abc() { ... } +} + +class B : A +{ + override int def() { ... } // ok, overrides A.def + override int foo() { ... } // error, A.foo is final + int bar() { ... } // ok, A.bar is final private, but not virtual + int abc() { ... } // ok, A.abc is not virtual, B.abc is virtual +} + +void test() +{ + A a = new B; + a.def(); // calls B.def + a.foo(); // calls A.foo + a.bar(); // calls A.bar + a.abc(); // calls A.abc +} +------ + + $(P Member functions with `Objective-C` linkage are virtual even if marked + with `final` or `static`, and can be overridden. + ) + +$(H3 $(LNAME2 covariance, Covariance)) + + $(P An overriding function may be covariant with the overridden function. + A covariant function has a type that is implicitly convertible to the + type of the overridden function. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +class A { } +class B : A { } + +class Foo +{ + A test() { return null; } +} + +class Bar : Foo +{ + // overrides and is covariant with Foo.test() + override B test() { return null; } +} +------ +) + +$(H3 $(LNAME2 base-methods, Calling Base Class Methods)) + + $(P To directly call a member function of a base class `Base`, + write `Base.` before the function name. + This avoids dynamic dispatch through a function pointer. For + example: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +class B +{ + int foo() { return 1; } +} +class C : B +{ + override int foo() { return 2; } + + void test() + { + assert(B.foo() == 1); // translated to this.B.foo(), and + // calls B.foo statically. + assert(C.foo() == 2); // calls C.foo statically, even if + // the actual instance of 'this' is D. + } +} +class D : C +{ + override int foo() { return 3; } +} +void main() +{ + auto d = new D(); + assert(d.foo() == 3); // calls D.foo + assert(d.B.foo() == 1); // calls B.foo + assert(d.C.foo() == 2); // calls C.foo + d.test(); +} +------ +) + $(P Base class methods can also be called through the + $(DDSUBLINK spec/expression, super, `super`) reference.) + + $(IMPLEMENTATION_DEFINED Normally calling a virtual function implies getting the + address of the function at runtime by indexing into the class's `vtbl[]`. + If the implementation can determine that the called virtual function will be statically + known, such as if it is `final`, it can use a direct call instead. + ) + +$(H3 $(LNAME2 function-inheritance, Overload Sets and Overriding)) + + $(P When doing overload resolution, the functions in the base + class are not considered, as they are not in the same + $(RELATIVE_LINK2 overload-sets, Overload Set): + ) + +------ +class A +{ + int foo(int x) { ... } + int foo(long y) { ... } +} + +class B : A +{ + override int foo(long x) { ... } +} + +void test() +{ + B b = new B(); + b.foo(1); // calls B.foo(long), since A.foo(int) is not considered + + A a = b; + a.foo(1); // issues runtime error (instead of calling A.foo(int)) +} +------ + + $(P To include the base class's functions in the overload resolution + process, use an $(GLINK2 declaration, AliasDeclaration): + ) + +------ +class A +{ + int foo(int x) { ... } + int foo(long y) { ... } +} + +class B : A +{ + $(CODE_HIGHLIGHT alias foo = A.foo;) + override int foo(long x) { ... } +} + +void test() +{ + A a = new B(); + a.foo(1); // calls A.foo(int) + B b = new B(); + b.foo(1); // calls A.foo(int) +} +------ + + $(P If such an $(I AliasDeclaration) is not used, the derived + class's functions completely override all the functions of the + same name in the base class, even if the types of the parameters + in the base class functions are different. + It is illegal if, through + implicit conversions to the base class, those other functions do + get called: + ) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +class A +{ + void $(CODE_HIGHLIGHT set)(long i) { } + void set(int i) { } +} +class B : A +{ + override void set(long i) { } +} + +void test() +{ + A a = new B; + a.set(3); // error, use of A.set(int) is hidden by B + // use 'alias set = A.set;' to introduce base class overload set +} +--- +) + +$(H3 $(LNAME2 override-defaults, Default Values)) + + $(P A function parameter's default value is not inherited:) + +------ +class A +{ + void $(CODE_HIGHLIGHT foo)(int x = 5) { ... } +} + +class B : A +{ + void foo(int $(CODE_HIGHLIGHT x = 7)) { ... } +} + +class C : B +{ + void foo(int $(CODE_HIGHLIGHT x)) { ... } +} + +void test() +{ + A a = new A(); + a.foo(); // calls A.foo(5) + + B b = new B(); + b.foo(); // calls B.foo(7) + + C c = new C(); + c.foo(); // error, need an argument for C.foo +} +------ + +$(H3 $(LNAME2 inheriting-attributes, Inherited Attributes)) + + $(P An overriding function inherits any unspecified $(GLINK FunctionAttributes) + from the attributes of the overridden function.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +class B +{ + void foo() pure nothrow @safe {} +} +class D : B +{ + override void foo() {} +} +void main() +{ + auto d = new D(); + pragma(msg, typeof(&d.foo)); + // prints "void delegate() pure nothrow @safe" in compile time +} +------ +) + +$(H3 $(LNAME2 override-restrictions, Restrictions)) + + $(P The attributes + $(LINK2 attribute.html#disable, $(D @disable)) and + $(LINK2 attribute.html#deprecated, $(D deprecated)) + are not allowed on overriding functions. + ) + + $(RATIONALE To stop the compilation or to output the deprecation message, the implementation + must be able to determine the target of the call, which can't be guaranteed + when it is virtual. + ) + + --- + class B + { + void foo() {} + } + + class D : B + { + @disable override void foo() {} // error, can't apply @disable to overriding function + } + --- + + +$(H2 $(LNAME2 inline-functions, Inline Functions)) + + $(P The compiler makes the decision whether to inline a function or not. + This decision may be controlled by $(LINK2 pragma.html#inline, `pragma(inline)`).) + + $(IMPLEMENTATION_DEFINED + Whether a function is inlined or not is implementation defined, though + any $(GLINK2 expression, FunctionLiteral) should be inlined + when used in its declaration scope. + ) + +$(H2 $(LNAME2 function-overloading, Function Overloading)) + + $(P $(I Function overloading) occurs when two or more functions in the same scope + have the same name. + The function selected is the one that is the $(I best match) to the arguments. + The matching levels are: + ) + + $(OL + $(LI No match) + $(LI Match with implicit conversions) + $(LI Match with qualifier conversion (if the argument type is + $(GLOSSARY qualifier-convertible) to the parameter type)) + $(LI Exact match) + ) + + $(P Named arguments are resolved for a candidate according to + $(DDSUBLINK spec/expression, argument-parameter-matching, Matching Arguments to Parameters). + If this fails (for example, because the overload does not have a parameter matching a named argument), + the level is $(I no match). Other than that, named arguments do not affect the matching level. + ) + + $(P Each argument (including any $(CODE this) reference) is + compared against the function's corresponding parameter to + determine the match level for that argument. The match level + for a function is the $(I worst) match level of each of its + arguments.) + + $(P Literals do not match $(CODE ref) or $(CODE out) parameters.) + + $(P $(CODE scope) parameter storage class does not affect function overloading.) + + $(P If two or more functions have the same match level, + then $(LNAME2 partial-ordering, $(I partial ordering)) + is used to disambiguate to find the best match. + Partial ordering finds the most specialized function. + If neither function is more specialized than the other, + then it is an ambiguity error. + Partial ordering is determined for functions $(I f) + and $(I g) by taking the parameter types of $(I f), + constructing a list of arguments by taking the default values + of those types, and attempting to match them against $(I g). + If it succeeds, then $(I g) is at least as specialized + as $(I f). + For example: + ) +--- +class A { } +class B : A { } +class C : B { } +void foo(A); +void foo(B); + +void test() +{ + C c; + /* Both foo(A) and foo(B) match with implicit conversions (level 2). + * Applying partial ordering rules, + * foo(B) cannot be called with an A, and foo(A) can be called + * with a B. Therefore, foo(B) is more specialized, and is selected. + */ + foo(c); // calls foo(B) +} +--- + $(P A function with a variadic argument is considered less + specialized than a function without. + ) + + $(P A static member function can be overloaded with a member + function. The struct, class + or union of the static member function is inferred from the + type of the `this` argument.) + + --- + struct S { + void eggs(int); + static void eggs(long); + } + S s; + s.eggs(0); // calls void eggs(int); + S.eggs(0); // error: need `this` + s.eggs(0L); // calls static void eggs(long); + S.eggs(0L); // calls static void eggs(long); + + struct T { + void bacon(int); + static void bacon(int); + } + T t; + t.bacon(0); // error: ambiguous + T.bacon(0); // error: ambiguous + --- + + $(RATIONALE A static member function that doesn't need + the `this` parameter does not need to pass it.) + +$(H3 $(LNAME2 overload-sets, Overload Sets)) + + $(P Functions declared at the same scope overload against each + other, and are called an $(I Overload Set). + An example of an overload set are functions defined + at module level: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +module A; +void foo() { } +void foo(long i) { } +--- +) + + $(P $(CODE A.foo()) and $(CODE A.foo(long)) form an overload set. + A different module can also define another overload set of + functions with the same name: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +module B; +class C { } +void foo(C) { } +void foo(int i) { } +--- +) + + $(P and A and B can be imported by a third module, C. + Both overload sets, the $(CODE A.foo) overload set and the $(CODE B.foo) + overload set, are found when searching for symbol `foo`. + An instance of $(CODE foo) is selected + based on it matching in exactly one overload set: + ) + +--- +import A; +import B; + +void bar(C c , long i) +{ + foo(); // calls A.foo() + foo(i); // calls A.foo(long) + foo(c); // calls B.foo(C) + foo(1,2); // error, does not match any foo + foo(1); // error, matches A.foo(long) and B.foo(int) + A.foo(1); // calls A.foo(long) +} +--- + + $(P Even though $(CODE B.foo(int)) is a better match than $(CODE + A.foo(long)) for $(CODE foo(1)), + it is an error because the two matches are in + different overload sets. + ) + + $(P Overload sets can be merged with an alias declaration:) + +--- +import A; +import B; + +alias foo = A.foo; +alias foo = B.foo; + +void bar(C c) +{ + foo(); // calls A.foo() + foo(1L); // calls A.foo(long) + foo(c); // calls B.foo(C) + foo(1,2); // error, does not match any foo + foo(1); // calls B.foo(int) + A.foo(1); // calls A.foo(long) +} +--- + + +$(H2 $(LNAME2 parameters, Function Parameters)) + +$(H3 $(LNAME2 param-storage, Parameter Storage Classes)) + + $(P Parameter storage classes are $(D in), $(D out), $(D ref), $(D lazy), `return` and $(D scope). + Parameters can also take the type constructors $(D const), $(D immutable), $(D shared) and `inout`. + ) + + $(P $(D in), $(D out), $(D ref) and $(D lazy) are mutually exclusive. The first three are used to + denote input, output and input/output parameters, respectively. + For example: + ) + + --- + int read(in char[] input, ref size_t count, out int errno); + + void main() + { + size_t a = 42; + int b; + int r = read("Hello World", a, b); + } + --- + + $(P `read` has three parameters. $(D input) will only be read and no reference to it will be retained. + $(D count) may be read and written to, and $(D errno) will be set to a value from + within the function.) + + $(P The argument $(D "Hello World") gets bound to parameter $(D input), + $(D a) gets bound to $(D count) and $(D b) to $(D errno). + ) + + $(TABLE_2COLS Parameter Storage Class and Type Constructor Overview, + $(THEAD Storage Class, Description) + + $(TROW $(I none), The parameter will be a mutable copy of its argument.) + + $(TROW $(D in), The parameter is an input to the function.) + + $(TROW $(D out), The argument must be an lvalue$(COMMA) which will be passed by reference and initialized + upon function entry with the default value (`T.init`) of its type. + ) + + $(TROW $(D ref), The parameter is an $(I input/output) parameter$(COMMA) passed by reference. + ) + + $(TROW $(D scope), $(ARGS + The parameter must not escape the function call + (e.g. by being assigned to a global variable). + Ignored for any parameter that is not a reference type. + )) + + $(TROW $(D return), $(ARGS Parameter may be returned or copied to the first parameter, + but otherwise does not escape from the function. + Such copies are required not to outlive the argument(s) they were derived from. + Ignored for parameters with no references. + See $(DDSUBLINK spec/memory-safe-d, scope-return-params, Scope Parameters).)) + + $(TROW $(D lazy), argument is evaluated by the called function and not by the caller) + + $(THEAD Type Constructor, Description) + + $(TROW $(D const), argument is implicitly converted to a const type) + $(TROW $(D immutable), argument is implicitly converted to an immutable type) + $(TROW $(D shared), argument is implicitly converted to a shared type) + $(TROW $(D inout), argument is implicitly converted to an inout type) + ) + +$(H3 $(LNAME2 in-params, In Parameters)) + + $(P The parameter is an input to the function. Input parameters behave as if they have + the $(D const) storage class.) + + $(NOTE The following requires the $(D -preview=in) switch and a compiler compliant with + $(LINK2 $(ROOT_DIR)changelog/2.094.0.html#preview-in, dmd v2.094.0) or higher.) + + $(P `in` parameters also behave like $(RELATIVE_LINK2 scope-parameters, `scope`) parameters.) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +const(int[]) g(in int[] a) @safe +{ + a[0]++; // Error: cannot modify const expression + return a; // Error: scope parameter `a` may not be returned +} +--- +) + + $(P Input parameters may also be passed by reference by the compiler. + Unlike $(D ref) parameters, $(D in) parameters can bind to both lvalues and rvalues + (such as literals).) + + - Types that would trigger a side effect if passed by value (such as types with + a copy constructor, postblit, or destructor) will always be passed by reference. + - Types which cannot be copied (e.g. if their copy constructor is marked as + $(D @disable)) will always be passed by reference. + - Dynamic arrays, classes, associative arrays, function pointers, and delegates + will always be passed by value. + + $(IMPLEMENTATION_DEFINED If the type of the parameter does not fall in one of those categories, + whether or not it is passed by reference is implementation defined, and the backend is free + to choose the method that will best fit the ABI of the platform. + ) + + +$(H3 $(LNAME2 ref-params, Ref and Out Parameters)) + + $(P By default, parameters take rvalue arguments. + A `ref` parameter takes an lvalue argument, so changes to its value will operate + on the caller's argument.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + void inc(ref int x) + { + x += 1; + } + + void seattle() + { + int z = 3; + inc(z); + assert(z == 4); + } + --- + ) + + $(P A `ref` parameter can also be returned by reference, see + $(RELATIVE_LINK2 return-ref-parameters, Return Ref Parameters.)) + + $(P An `out` parameter is similar to a `ref` parameter, except it is initialized + by $(DDSUBLINK spec/property, init-vs-construction, default construction) upon + function invocation.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + void zero(out int x) + { + assert(x == 0); + } + + void two(out int x) + { + x = 2; + } + + void tacoma() + { + int a = 3; + zero(a); + assert(a == 0); + + int y = 3; + two(y); + assert(y == 2); + } + --- + ) + + $(P For dynamic array and class object parameters, which are always passed + by reference, `out` and `ref` + apply only to the reference and not the contents. + ) + +$(H3 $(LNAME2 lazy-params, Lazy Parameters)) + + $(P An argument to a $(D lazy) parameter is not evaluated before the function is called. + The argument is only evaluated if/when the parameter is evaluated within the function. Hence, + a $(D lazy) argument can be executed 0 or more times. ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio : writeln; + +void main() +{ + int x; + 3.times(writeln(x++)); + writeln("-"); + writeln(x); +} + +void times(int n, lazy void exp) +{ + while (n--) + exp(); +} +--- +) + + $(P prints to the console:) + +$(CONSOLE +0 +1 +2 +$(MINUS) +3 +) + + $(P A $(D lazy) parameter cannot be an lvalue.) + + $(P The underlying delegate of the $(D lazy) parameter may be extracted + by using the $(D &) operator:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +void test(lazy int dg) +{ + int delegate() dg_ = &dg; + assert(dg_() == 7); + assert(dg == dg_()); +} + +void main() +{ + int a = 7; + test(a); +} +--- +) + + $(P A $(D lazy) parameter of type $(D void) can accept an argument + of any type.) + + $(P See Also: $(RELATIVE_LINK2 lazy_variadic_functions, Lazy Variadic Functions)) + +$(H3 $(LNAME2 function-default-args, Default Arguments)) + + $(P Function parameter declarations can have default values:) + +--- +void foo(int x, int y = 3) +{ + ... +} +... +foo(4); // same as foo(4, 3); +--- + + $(P Default parameters are resolved and semantically checked in the context of the + function declaration.) +--- +module m; +private immutable int b; +pure void g(int a = b) {} +--- +--- +import m; +int b; +pure void f() +{ + g(); // ok, uses m.b +} +--- + + $(P The attributes of the $(ASSIGNEXPRESSION) are applied where the default expression + is used.) +--- +module m; +int b; +pure void g(int a = b) {} +--- +--- +import m; +enum int b = 3; +pure void f() +{ + g(); // error, cannot access mutable global `m.b` in pure function +} +--- + + $(P See also: function type aliases + $(DDSUBLINK spec/declaration, alias-function, with default values).) + + +$(H3 $(LNAME2 return-ref-parameters, Return Ref Parameters)) + + $(P Return ref parameters are used with + $(RELATIVE_LINK2 ref-functions, ref functions) to ensure that the + returned reference will not outlive the matching argument's lifetime. + ) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +ref int identity(return ref int x) { + return x; // pass-through function that does nothing +} + +ref int fun() { + int x; + return identity(x); // Error: escaping reference to local variable x +} + +ref int gun(return ref int x) { + return identity(x); // OK +} +--- +) + $(P Returning the address of a `ref` variable is also checked in `@safe` code.) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +int* pluto(ref int i) @safe +{ + return &i; // error: returning &i escapes a reference to parameter i +} + +int* mars(return ref int i) @safe +{ + return &i; // OK with -preview=dip1000 +} +--- +) + +$(PANEL +If a function returns `void`, and the first parameter is `ref` or `out`, then +all subsequent `return ref` parameters are considered as being assigned to +the first parameter for lifetime checking. + +--- +void f(ref scope int* p, return ref int i) @safe +{ + p = &i; // OK with -preview=dip1000 +} + +void main() @safe +{ + int i; + int* p; + f(p, i); // OK, lifetime of p is shorter than i + *p = 5; + assert(i == 5); + + int j; + //f(p, j); // error, lifetime of p is longer than j +} +--- + +The `this` reference parameter to a struct non-static member function is +considered the first parameter. + +--- +struct S +{ + private int* p; + + void f(return ref int i) scope @safe + { + p = &i; // OK with -preview=dip1000 + } +} + +void main() @safe +{ + int i; + S s; + s.f(i); // OK, lifetime of `s` is shorter than `i` + *s.p = 2; + assert(i == 2); +} +--- +) + +$(P If there are multiple `return ref` parameters, the lifetime of the return +value is the smallest lifetime of the corresponding arguments.) + +$(P Neither the type of the `return ref` parameter(s) nor the type of the return +value is considered when determining the lifetime of the return value.) + +$(P It is not an error if the return type does not contain any indirections.) + +--- +int mercury(return ref int i) +{ + return i; // ok +} +--- + +$(P Template functions, auto functions, nested functions and $(DDSUBLINK spec/expression, function_literals, lambdas) + can deduce the `return` attribute.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +@safe: + +ref int templateFunction()(ref int i) +{ + return i; // ok +} + +ref auto autoFunction(ref int i) +{ + return i; // ok +} + +void uranus() +{ + ref int nestedFunction(ref int i) + { + return i; // ok + } + auto lambdaFunction = + (ref int i) + { + return &i; // ok + }; +} +--- +) + +$(H4 $(LNAME2 struct-return-methods, Struct Return Methods)) + + $(P Struct non-static methods can be marked with the `return` attribute to ensure a returned + reference will not outlive the struct instance. + ) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +struct S +{ + private int x; + ref int get() return { return x; } +} + +ref int escape() +{ + S s; + return s.get(); // Error: escaping reference to local variable s +} +--- +) + $(P The hidden `this` ref-parameter then becomes `return ref`.) + + $(P The `return` attribute can also be used to limit + the lifetime of the returned value, even when the method is not `ref`: + ) + +--- +struct S +{ + private int i; + int* get() return @safe => &i; +} + +void f() @safe +{ + int* p; + { + S s; + int *q = s.get(); // OK, q has shorter lifetime than s + p = s.get(); // error, p has longer lifetime + p = (new S).get(); // OK, heap allocated S + } +} +--- + +$(H3 $(LNAME2 scope-parameters, Scope Parameters)) + + $(P A `scope` parameter of reference type must not escape the function call + (e.g. by being assigned to a global variable). It has no effect for non-reference types. + `scope` escape analysis is only done for `@safe` functions. For other functions `scope` + semantics must be manually enforced.) + + $(NOTE `@safe` escape analysis is only done with the $(D -preview=dip1000) switch.) + +--- +@safe: + +int* gp; +void thorin(scope int*); +void gloin(int*); +int* balin(scope int* q, int* r) +{ + gp = q; // error, q escapes to global gp + gp = r; // ok + + thorin(q); // ok, q does not escape thorin() + thorin(r); // ok + + gloin(q); // error, gloin() escapes q + gloin(r); // ok that gloin() escapes r + + return q; // error, cannot return 'scope' q + return r; // ok +} +--- + + $(IMPLEMENTATION_DEFINED + As a `scope` parameter must not escape, the compiler can potentially avoid heap-allocating a + unique argument to a `scope` parameter. Due to this, passing an array literal, delegate + literal or a $(GLINK2 expression, NewExpression) to a scope parameter may be allowed in a + `@nogc` context.) + +$(H3 $(LNAME2 return-scope-parameters, Return Scope Parameters)) + + $(P Parameters marked as `return scope` that contain indirections + can only escape those indirections via the function's return value.) + +--- +@safe: + +int* gp; +void thorin(scope int*); +void gloin(int*); +int* balin(return scope int* p) +{ + gp = p; // error, p escapes to global gp + thorin(p); // ok, p does not escape thorin() + gloin(p); // error, gloin() escapes p + return p; // ok +} +--- + + $(P Class references are considered pointers that are subject to `scope`.) + +--- +@safe: + +class C { } +C gp; +void thorin(scope C); +void gloin(C); +C balin(return scope C p, scope C q, C r) +{ + gp = p; // error, p escapes to global gp + gp = q; // error, q escapes to global gp + gp = r; // ok + + thorin(p); // ok, p does not escape thorin() + thorin(q); // ok + thorin(r); // ok + + gloin(p); // error, gloin() escapes p + gloin(q); // error, gloin() escapes q + gloin(r); // ok that gloin() escapes r + + return p; // ok + return q; // error, cannot return 'scope' q + return r; // ok +} +--- + + $(P `return scope` can be applied to the `this` of class and interface member functions.) + +--- +class C +{ + C bofur() return scope { return this; } +} +--- + + $(P Template functions, auto functions, nested functions and + $(DDSUBLINK spec/expression, function_literals, lambdas) can deduce + the `return scope` attribute.) + +$(H3 $(LNAME2 ref-return-scope-parameters, Ref Return Scope Parameters)) + + $(P It is not possible to have both `return ref` and `return scope` semantics + for the same parameter. + When a parameter is passed by `ref` and has both the `return` and `scope` storage classes, + it gets $(LINK2 #return-scope-parameters, `return scope`) semantics if and only if the `return` and `scope` + keywords appear adjacent to each other, in that order. + Specifying a `return ref` and `scope` parameter enables returning a reference to a scope pointer. + In all other cases, the parameter has $(LINK2 #return-ref-parameters, `return ref`) semantics + and regular $(LINK2 #scope-parameters, `scope`) semantics.) + +--- +U xerxes( ref return scope V v) // (1) ref and return scope +U sargon(return ref scope V v) // (2) return ref and scope + +struct S +{ + // note: in struct member functions, the implicit `this` parameter + // is passed by `ref` + + U xerxes() return scope; // return scope + U sargon() scope return; // return ref, `return` comes after `scope` + U xerxes() return const scope; // return ref, `return` and `scope` are not adjacent +} +--- + +$(P Example of combinations of `return scope`, `return ref`, and `scope` semantics:) +--- +@safe: + +int* globalPtr; + +struct S +{ + int val; + int* ptr; + + this(return scope ref int* p) { ptr = p; } + + // note: `this` is passed by `ref` in structs + + int* retRefA() scope return // return-ref, scope + { + globalPtr = this.ptr; // disallowed, `this` is `scope` + return &this.val; // allowed, `return` means `return ref` + } + + ref int retRefB() scope return // return-ref, scope + { + globalPtr = this.ptr; // disallowed, `this` is `scope` + return this.val; // allowed, `return` means `return ref` + } + + int* retScopeA() return scope // ref, return-scope + { + return &this.val; // disallowed, escaping a reference to `this` + return this.ptr; // allowed, returning a `return scope` pointer + } + + ref int retScopeB() return scope // ref, return-scope + { + return this.val; // disallowed, escaping a reference to `this` + return *this.ptr; // allowed, returning a `return scope` pointer + } + + ref int* retRefScopeC() scope return // return-ref, scope + { + return this.ptr; // allowed, returning a reference to a scope pointer + } +} + +int* retRefA(return ref scope S s) +{ + globalPtr = s.ptr; // disallowed, `s` is `scope` + return &s.val; // allowed, returning a reference to `return ref s` +} + +ref int retRefB(return ref scope S s) +{ + globalPtr = s.ptr; // disallowed, `s` is `scope` + return s.val; +} + +int* retScopeA(ref return scope S s) +{ + return &s.val; // disallowed, escaping a reference to `s` + return s.ptr; // allowed, returning a `return scope` pointer +} + +ref int retScopeB(ref return scope S s) +{ + return s.val; // disallowed, escaping a reference to `s` + return *s.ptr; // allowed, returning a `return scope` pointer +} + +ref int* retRefScopeC(return ref scope int* p) +{ + return p; // allowed, returning a reference to a scope pointer +} +--- + +$(H3 $(LNAME2 pure-scope-inference, Inferred `scope` parameters in `pure` functions)) + + When a parameter is not marked or inferred `scope`, it may still be `@safe` to assign it a `scope` pointer in a function call. + The following conditions need to be met: + + $(UL + $(LI The function is $(RELATIVE_LINK2 pure-functions, `pure`), hence the argument cannot be assigned to a global variable) + $(LI The function is $(RELATIVE_LINK2 nothrow-functions, `nothrow`), hence the argument cannot be assigned to a thrown `Exception` object) + $(LI None of the other parameters have mutable indirections, hence the argument cannot be assigned to a longer-lived variable) + ) + + Then, the parameter is still treated as `scope` or `return scope` depending on the return type of the function: + $(UL + $(LI If the function returns by `ref` or has a return type that contains pointers, the argument could be returned, so it is treated as `return scope`) + $(LI Otherwise, the argument cannot escape the function, so it is treated as `scope`) + ) + +--- +@safe: + +int dereference(int* x) pure nothrow; +int* identity(int* x) pure nothrow; +int* identityThrow(int* x) pure; +void assignToRef(int* x, ref int* escapeHatch) pure nothrow; +void assignToPtr(int* x, int** escapeHatch) pure nothrow; +void cannotAssignTo(int* x, const ref int* noEscapeHatch) pure nothrow; + +int* globalPtr; + +int* test(scope int* ptr) +{ + int result = dereference(ptr); // allowed, treated as `scope` + int* ptr2 = identity(ptr); // allowed, treated as `return scope` + int* ptr3 = identityThrow(ptr); // not allowed, can throw an `Exception` + assignToRef(ptr, globalPtr); // not allowed, mutable second parameter + assignToPtr(ptr, &globalPtr); // not allowed, mutable second parameter + cannotAssignTo(ptr, globalPtr); // allowed + + return ptr2; // not allowed, ptr2 is inferred `scope` now +} +--- + +$(H3 $(LNAME2 udas-parameters, User-Defined Attributes for Parameters)) + +See also: $(GLINK2_ALTTEXT attribute, UserDefinedAttribute, User-Defined Attributes) + +$(H3 $(LNAME2 variadic, Variadic Functions)) + + $(P $(I Variadic Functions) take a variable number of arguments. + There are three forms:) + + $(OL + $(LI $(RELATIVE_LINK2 c_style_variadic_functions, C-style variadic functions)) + $(LI $(RELATIVE_LINK2 d_style_variadic_functions, Variadic functions with type info)) + $(LI $(RELATIVE_LINK2 typesafe_variadic_functions, Typesafe variadic functions)) + ) + + +$(H4 $(LNAME2 c_style_variadic_functions, C-style Variadic Functions)) + + $(P A C-style variadic function is declared with + a parameter `...` as the last function parameter. + It has non-D linkage, such as $(D extern (C)).) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + extern (C) void dry(int x, int y, ...); // C-style Variadic Function + + void spin() + { + dry(3, 4); // ok, no variadic arguments + dry(3, 4, 6.8); // ok, one variadic argument + //dry(2); // error, no argument for parameter y + } + --- + ) + + $(P There must be at least one non-variadic parameter declared.) + + --- + extern (C) int def(...); // error, must have at least one parameter + --- + + $(P + C-style variadic functions match the C calling convention for + variadic functions, and can call C Standard library + functions like $(REF_SHORT printf, core,stdc,stdio). + ) + + --- + extern (C) int printf(const(char)*, ...); + + void main() + { + printf("hello world\n"); + } + --- + + $(P C-style variadic functions cannot be marked as $(D @safe).) + + $(P To access the variadic arguments, + import the standard library + module $(LINK2 $(ROOT_DIR)phobos/core_stdc_stdarg.html, $(D core.stdc.stdarg)). + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------ + import core.stdc.stdarg; + import std.stdio; + + extern (C) void rinse(int x, int y, ...) + { + va_list args; + va_start(args, y); // y is the last named parameter + int z; + va_arg(args, z); // z is set to 5 + va_end(args); + writeln(z); + } + + void main() + { + rinse(3, 4, 5); // first variadic argument is 5 + } + --- + ) + + +$(H4 $(LNAME2 d_style_variadic_functions, D-style Variadic Functions)) + + $(P D-style variadic functions have D linkage and `...` as the last + parameter.) + + $(P `...` can be the only parameter.) + + $(P If there are parameters preceding the `...` parameter, there + must be a comma separating them from the `...`.) + + $(NOTE If the comma is omitted, it is a + $(RELATIVE_LINK2 typesafe_variadic_functions, Typesafe Variadic Function).) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------ + int abc(char c, ...); // one required parameter: c + int def(...); // no required parameters + int ghi(int i ...); // a typesafe variadic function + //int boo(, ...); // error + ------ + ) + + $(P Two hidden arguments are passed to the function:) + + $(UL + $(LI `_argptr`) + $(LI `TypeInfo[] _arguments`) + ) + + $(P $(D _argptr) is a pointer to the first of the variadic + arguments. To access the variadic arguments, + import $(LINK2 $(ROOT_DIR)phobos/core_vararg.html, $(D core.vararg)). + Use $(D _argptr) in conjunction with $(REF_SHORT va_arg, core,stdc,stdarg):) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +import core.vararg; +import std.stdio; + +@system void foo(int x, int y, ...) +{ + int z = va_arg!int(_argptr); // z is set to 5 and _argptr is advanced + // to the next argument + writeln(z); // 5 +} + +void main() +{ + foo(3, 4, 5); // first variadic argument is 5 +} +------ +) + $(P $(D _arguments) gives the number of arguments and the `typeid` + of each, enabling type safety to be checked at run time.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +import std.stdio; + +void main() +{ + Foo f = new Foo(); + Bar b = new Bar(); + + writefln("%s", f); + printargs(1, 2, 3L, 4.5, f, b); +} + +class Foo { int x = 3; } +class Bar { long y = 4; } + +import core.vararg; + +@system void printargs(int x, ...) +{ + writefln("%d arguments", _arguments.length); + for (int i = 0; i < _arguments.length; i++) + { + writeln(_arguments[i]); + + if (_arguments[i] == typeid(int)) + { + int j = va_arg!(int)(_argptr); + writefln("\t%d", j); + } + else if (_arguments[i] == typeid(long)) + { + long j = va_arg!(long)(_argptr); + writefln("\t%d", j); + } + else if (_arguments[i] == typeid(double)) + { + double d = va_arg!(double)(_argptr); + writefln("\t%g", d); + } + else if (_arguments[i] == typeid(Foo)) + { + Foo f = va_arg!(Foo)(_argptr); + writefln("\t%d", f.x); + } + else if (_arguments[i] == typeid(Bar)) + { + Bar b = va_arg!(Bar)(_argptr); + writefln("\t%d", b.y); + } + else + assert(0); + } +} +------ +) + + which prints: + +------ +0x00870FE0 +5 arguments +int + 2 +long + 3 +double + 4.5 +Foo + 3 +Bar + 4 +------ + + $(P D-style variadic functions cannot be marked as $(D @safe) (if + they call `va_arg`).) + + +$(H4 $(LNAME2 typesafe_variadic_functions, Typesafe Variadic Functions)) + + $(P A typesafe variadic function has D linkage and a variadic + parameter, which is typically an array followed by `...`. + The variadic parameter must be the last one. When passing component + arguments (e.g. array elements), the variadic parameter is + implicitly constructed from the given arguments. + ) + + $(P A dynamic array variadic parameter accepts either a + dynamic array argument or any number of arguments, each of + which must implicitly convert to the array element type:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + int sum(int[] ar ...) // typesafe variadic function + { + int s; + foreach (int x; ar) + s += x; + return s; + } + + void main() + { + assert(sum(1, 2, 3) == 6); + assert(sum() == 0); + + int[3] ii = [4, 5, 6]; + assert(sum(ii) == 15); + } + --- + ) + + $(P A static array variadic parameter accepts either a static + array argument or a fixed number of arguments which matches + the array dimension:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + int sum(int[3] ar ...) // typesafe variadic function + { + int s; + foreach (int x; ar) + s += x; + return s; + } + + void main() + { + int i; + //i = sum(2, 3); // error, need 3 values for array + i = sum(1, 2, 3); + assert(i == 6); + + int[3] ii = [4, 5, 6]; + i = sum(ii); + assert(i == 15); + + int[] jj = ii; + //i = sum(jj); // error, type mismatch + } + --- + ) + + $(DDOC_DEPRECATED For class objects:) + + --- + int tesla(int x, C c ...) + { + return x + c.x; + } + + class C + { + int x; + string s; + + this(int x, string s) + { + this.x = x; + this.s = s; + } + } + + void edison() + { + C g = new C(3, "abc"); + tesla(1, c); // ok, since c is an instance of C + tesla(1, 4, "def"); // ok + tesla(1, 5); // error, no matching constructor for C + } + --- + + $(P The lifetime of the variadic class object or array + instance ends at the end of the function. + ) + + --- + C orville(C c ...) + { + return c; // error, c instance contents invalid after return + } + + int[] wilbur(int[] a ...) + { + return a; // error, array contents invalid after return + return a[0..1]; // error, array contents invalid after return + return a.dup; // ok, since copy is made + } + --- + + $(IMPLEMENTATION_DEFINED the variadic object or array instance + may be constructed on the stack.) + + $(P For other types, the variadic parameter matches exactly one + argument, which is passed by value.) + + --- + int neil(int i ...) + { + return i; + } + + void buzz() + { + neil(); // error, missing argument + neil(3); // returns 3 + neil(3, 4); // error, too many arguments + int[] x; + neil(x); // error, type mismatch + } + --- + +$(H4 $(LNAME2 lazy_variadic_functions, Lazy Variadic Functions)) + + $(P If the variadic parameter of a function is an array of delegates + with no parameters, + then each of the arguments whose type does not match that + of the delegate is converted to a delegate of that type. + ) + + --- + void hal(scope int delegate()[] dgs ...); + + void dave() + { + int delegate() dg; + hal(1, 3+x, dg, cast(int delegate())null); // (1) + hal( { return 1; }, { return 3+x; }, dg, null ); // same as (1) + } + --- + + $(P The variadic delegate array differs from using a lazy + variadic array. With the latter each array element access + would evaluate every array element. + With the former, only the element being accessed would be evaluated.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + import std.stdio; + + void main() + { + int x; + ming(++x, ++x); + + int y; + flash(++y, ++y); + } + + // lazy variadic array + void ming(lazy int[] arr...) + { + writeln(arr[0]); // 1 + writeln(arr[1]); // 4 + } + + // variadic delegate array + void flash(scope int delegate()[] arr ...) + { + writeln(arr[0]()); // 1 + writeln(arr[1]()); // 2 + } + --- + ) + + $(BEST_PRACTICE Use `scope` when declaring the array of delegates + parameter. This will prevent a closure being generated for the delegate, + as `scope` means the delegate will not escape the function.) + +$(LEGACY_LNAME2 this-reference) +$(H3 $(LNAME2 hidden-parameters, Hidden Parameters)) + + $(UL + $(LI + Non-static member functions all have a hidden parameter called the + $(DDSUBLINK spec/expression, this, `this` reference), which refers to the object for which + the function is called. + ) + $(LI D-style variadic functions have + $(RELATIVE_LINK2 d_style_variadic_functions, hidden parameters).) + $(LI + Functions with `Objective-C` linkage have an additional hidden, + unnamed, parameter which is the selector it was called with. + ) + ) + + + +$(H2 $(LNAME2 refscopereturn, Ref Scope Return Cases)) + + +$(H3 $(LNAME2 rsr_definitions, Definitions)) + + $(TABLE2 Definitions, + $(THEAD Term, Description) + $(TROW I, type that contains no indirections) + $(TROW P, type that contains indirections) + $(TROW X, type that may or may not contain indirections) + $(TROW p, parameter of type P) + $(TROW i, parameter of type I) + $(TROW ref, `ref` or `out` parameter) + + $(TROW returned, returned via the `return` statement) + $(TROW escaped, stored in a global or other memory not in the function$(RSQUO)s stack frame) + ) + +$(H3 $(LNAME2 rsr_classification, Classification)) + +$(P A parameter must be in one of the following states:) + + $(TABLE2 Classification, + $(THEAD Term, Description) + $(TROW None, + `p` may be returned or escaped) + + $(TROW ReturnScope, + `p` may be returned but not escaped) + + $(TROW Scope, + `p` may be neither returned nor escaped) + + $(TROW Ref, + `p` may be returned or escaped$(COMMA) + `ref` may not be returned nor escaped) + + $(TROW ReturnRef, + `p` may be returned or escaped$(COMMA) + `ref` may be returned but not escaped) + + $(TROW RefScope, + `p` may be neither returned nor escaped$(COMMA) + `ref` may not be returned nor escaped) + + $(TROW ReturnRef-Scope, + `p` may be neither returned nor escaped$(COMMA) + `ref` may be returned but not escaped) + + $(TROW Ref-ReturnScope, + `p` may be returned but not escaped$(COMMA) + `ref` may not be returned nor escaped) + + $(TROW ReturnRef-ReturnScope, + `p` may be returned but not escaped$(COMMA) + `ref` may be returned but not escaped. + This isn't expressible with the current syntax + and so is not allowed.) + ) + +$(H3 $(LNAME2 rsr_mapping, Mapping Syntax Onto Classification)) + + $(P The juxtaposition of `return` immediately preceding `scope` means ReturnScope. + Otherwise, `return` and `ref` in any position means ReturnRef.) + + $(TABLE2 Mapping, + $(THEAD Example, Classification, Comments) + $(TROW `X foo(P p)`, + None,) + + $(TROW `X foo(scope P p)`, + Scope,) + + $(TROW `P foo(return scope P p)`, + ReturnScope,) + + $(TROW `I foo(return scope P p)`, + Scope, + The `return` is dropped because the return type `I` contains no pointers.) + + $(TROW `P foo(return P p)`, + ReturnScope, + Makes no sense to have `return` without `scope`.) + + $(TROW `I foo(return P p)`, + Scope, + The `return` is dropped because the return type `I` contains no pointers.) + + + $(TROW `X foo(ref P p)`, + Ref,) + + $(TROW `X foo(ref scope P p)`, + RefScope,) + + $(TROW `P foo(ref return scope P p)`, + Ref-ReturnScope,) + + $(TROW `P foo(return ref scope P p)`, + ReturnRef-Scope,) + + $(TROW `I foo(ref return scope P p)`, + RefScope,) + + $(TROW `P foo(ref return P p)`, + ReturnRef,) + + $(TROW `I foo(ref return P p)`, + Ref,) + + + $(TROW `ref X foo(P p)`, + None,) + + $(TROW `ref X foo(scope P p)`, + Scope,) + + $(TROW `ref X foo(return scope P p)`, + ReturnScope,) + + $(TROW `ref X foo(return P p)`, + ReturnScope, + Makes no sense to have `return` without `scope`.) + + + $(TROW `ref X foo(ref P p)`, + Ref,) + + $(TROW `ref X foo(ref scope P p)`, + RefScope,) + + $(TROW `ref X foo(ref return scope P p)`, + Ref-ReturnScope,) + + $(TROW `ref X foo(return ref scope P p)`, + ReturnRef-Scope,) + + $(TROW `ref X foo(ref return P p)`, + ReturnRef,) + + $(TROW `X foo(I i)`, + None,) + + $(TROW `X foo(scope I i)`, + None,) + + $(TROW `X foo(return scope I i)`, + None,) + + $(TROW `X foo(return I i)`, + None,) + + + $(TROW `X foo(ref I i)`, + Ref,) + + $(TROW `X foo(ref scope I i)`, + Ref,) + + $(TROW `X foo(ref return scope I i)`, + Ref,) + + $(TROW `P foo(ref return I i)`, + ReturnRef,) + + $(TROW `I foo(ref return I i)`, + Ref,) + + + $(TROW `ref X foo(I i)`, + None,) + + $(TROW `ref X foo(scope I i)`, + None,) + + $(TROW `ref X foo(return scope I i)`, + None,) + + $(TROW `ref X foo(return I i)`, + None,) + + + + $(TROW `ref X foo(ref I i)`, + Ref,) + + $(TROW `ref X foo(ref scope I i)`, + Ref,) + + $(TROW `ref X foo(ref return scope I i)`, + ReturnRef,) + + $(TROW `ref X foo(ref return I i)`, + ReturnRef,) +) + +$(H3 $(LNAME2 rsr_memberfunctions, Member Functions)) + + $(P Member functions are rewritten as if the `this` parameter is the first + parameter of a non-member function, + ) + +--- +struct S { + X foo(); +} +--- + + $(P is treated as:) + +--- +X foo(ref S); +--- + + $(P and:) + +--- +class C { + X foo() +} +--- + + $(P is treated as:) + +--- +X foo(P) +--- + +$(H3 $(LNAME2 rsr_PandRef, P and ref)) + + $(P The rules account for switching between `ref` and P, such as:) + +--- +int* foo(return ref int i) { return &i; } +ref int foo(int* p) { return *p; } +--- + +$(H3 $(LNAME2 rsr_covariance, Covariance)) + + $(P Covariance means a parameter with restrictions can be converted to a parameter with + fewer restrictions. This is deducible from the description of each state. + ) + + $(NOTE `ref` is not covariant with non-`ref`, so those entries are omitted from the + table for simplicity. + ) + + $(TABLE2 Covariance, + $(THEAD From\To, None, ReturnScope, Scope) + $(TROW None, $(CHECK), , ) + $(TROW ReturnScope, $(CHECK), $(CHECK) , ) + $(TROW Scope, $(CHECK), $(CHECK) , $(CHECK)) + ) + + $(TABLE2 Ref Covariance, + $(THEAD From\To, Ref , ReturnRef, RefScope, ReturnRef-Scope, Ref-ReturnScope) + $(TROW Ref, $(CHECK), $(CHECK) , , , ) + $(TROW ReturnRef, , $(CHECK) , , , ) + $(TROW RefScope, $(CHECK), $(CHECK) , $(CHECK), $(CHECK) , $(CHECK)) + $(TROW ReturnRef-Scope, , $(CHECK) , , $(CHECK) , ) + $(TROW Ref-ReturnScope, $(CHECK), $(CHECK) , , , $(CHECK)) + ) + + $(P For example, `scope` matches all non-ref parameters, and `ref scope` matches all + ref parameters.) + + + +$(H2 $(LEGACY_LNAME2 Local Variables, local-variables, Local Variables)) + + $(P Local variables are declared within the scope of a function. + Function parameters are included.) + + $(P A local variable cannot be read without first assigning it a + value.) + + $(IMPLEMENTATION_DEFINED The implementation may not always be able + to detect these cases. + ) + + $(P The address of or reference to a + local non-static variable cannot be returned from the function. + ) + + $(P A local variable and a label in the same function cannot have the same + name. + ) + + $(P A local variable cannot hide another local + variable in the same function. + ) + + $(RATIONALE whenever + this is done it often is a + bug or at least looks like a bug. + ) + + --- + ref double func(int x) + { + int x; // error, hides previous definition of x + double y; + { + char y; // error, hides previous definition of y + int z; + } + { + wchar z; // Ok, previous z is out of scope + } + z: // error, z is a local variable and a label + return y; // error, returning ref to local + } + --- + + +$(H3 $(LEGACY_LNAME2 Local Static Variables, local-static-variables, Local Static Variables)) + + $(P Local variables in functions declared as `static`, `shared static` + or $(D __gshared) are statically allocated + rather than being allocated on the stack. + The lifetime of `__gshared` and `shared static` variables begins + when the function is first executed and ends when the program ends. + The lifetime of `static` variables begins when the function is first + executed within the thread and ends when that thread terminates. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio : writeln; + +void foo() +{ + static int n; + if (++n == 100) + writeln("called 100 times"); +} +--- +) + + $(P The initializer for a static variable must be evaluatable at + compile time. + There are no static constructors or static destructors + for static local variables. + ) + + $(P Although static variable name visibility follows the usual scoping + rules, the names of them must be unique within a particular function. + ) + +--- +void main() +{ + { static int x; } + { static int x; } // error + { int i; } + { int i; } // ok +} +--- + +$(H2 $(LNAME2 nested, Nested Functions)) + + $(P Functions may be nested within other functions:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +int bar(int a) +{ + int foo(int b) + { + int abc() { return 1; } + + return b + abc(); + } + return foo(a); +} + +void test() +{ + int i = bar(3); // i is assigned 4 +} +------ +) + + $(P Nested functions can be accessed only if the name is in scope.) + +------ +void foo() +{ + void A() + { + B(); // error, B() is forward referenced + C(); // error, C undefined + } + void B() + { + A(); // ok, in scope + void C() + { + void D() + { + A(); // ok + B(); // ok + C(); // ok + D(); // ok + } + } + } + A(); // ok + B(); // ok + C(); // error, C undefined +} +------ + + and: + +------ +int bar(int a) +{ + int foo(int b) { return b + 1; } + int abc(int b) { return foo(b); } // ok + return foo(a); +} + +void test() +{ + int i = bar(3); // ok + int j = bar.foo(3); // error, bar.foo not visible +} +------ + + $(P Nested functions have access to the variables and other symbols + defined by the lexically enclosing function. + This access includes both the ability to read and write them. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +int bar(int a) +{ + int c = 3; + + int foo(int b) + { + b += c; // 4 is added to b + c++; // bar.c is now 5 + return b + c; // 12 is returned + } + c = 4; + int i = foo(a); // i is set to 12 + return i + c; // returns 17 +} + +void test() +{ + int i = bar(3); // i is assigned 17 +} +------ +) + + $(P This access can span multiple nesting levels:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +int bar(int a) +{ + int c = 3; + + int foo(int b) + { + int abc() + { + return c; // access bar.c + } + return b + c + abc(); + } + return foo(3); +} +------ +) + + $(P Static nested functions cannot access any stack variables of + any lexically enclosing function, but can access static variables. + This is analogous to how static member functions behave. + ) + +------ +int bar(int a) +{ + int c; + static int d; + + static int foo(int b) + { + b = d; // ok + b = c; // error, foo() cannot access frame of bar() + return b + 1; + } + return foo(a); +} +------ + + $(P Functions can be nested within member functions:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +struct Foo +{ + int a; + + int bar() + { + int c; + + int foo() + { + return c + a; + } + return 0; + } +} +------ +) + + $(P Nested functions always have the D function linkage type. + ) + +$(H3 $(LNAME2 nested-declaration-order, Declaration Order)) + + $(P Unlike module level declarations, declarations within function + scope are processed in order. This means that two nested functions + cannot mutually call each other: + ) + +------ +void test() +{ + void foo() { bar(); } // error, bar not defined + void bar() { foo(); } // ok +} +------ + + $(P There are several workarounds for this limitation:) + +$(UL + + $(LI Declare the functions to be static members of a nested struct:) + +------ +void test() +{ + static struct S + { + static void foo() { bar(); } // ok + static void bar() { foo(); } // ok + } + + S.foo(); // compiles (but note the infinite runtime loop) +} +------ + + $(LI Declare one or more of the functions to be function templates + even if they take no specific template arguments:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +void test() +{ + void foo()() { bar(); } // ok (foo is a function template) + void bar() { foo(); } // ok +} +------ +) + + $(LI Declare the functions inside of a mixin template:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +mixin template T() +{ + void foo() { bar(); } // ok + void bar() { foo(); } // ok +} + +void main() +{ + mixin T!(); +} +------ +) + + $(LI Use a delegate:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +void test() +{ + void delegate() fp; + void foo() { fp(); } + void bar() { foo(); } + fp = &bar; +} +------ +) + + ) + + $(P Nested functions cannot be overloaded.) + +$(H2 $(LNAME2 function-pointers-delegates, Function Pointers, Delegates and Closures)) + +$(H3 $(LNAME2 function-pointers, Function Pointers)) + + $(P A function pointer is declared with the `function` keyword:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +void f(int); +void function(int) fp = &f; // fp is a pointer to a function taking an int +--- +) + $(P A function pointer can point to a static nested function:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------ +int function() fp; // fp is a pointer to a function returning an int + +void test() +{ + static int a = 7; + static int foo() { return a + 3; } + + fp = &foo; +} + +void main() +{ + assert(!fp); + test(); + int i = fp(); + assert(i == 10); +} +------ +) + + $(IMPLEMENTATION_DEFINED Two functions with identical bodies, or two functions + that compile to identical assembly code, are not guaranteed to have + distinct function pointer values. The implementation may merge + functions bodies into one if they compile to identical code.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +int abc(int x) { return x + 1; } +uint def(uint y) { return y + 1; } + +int function(int) fp1 = &abc; +uint function(uint) fp2 = &def; +// Do not rely on fp1 and fp2 being different values; the compiler may merge +// them. +------ +) + +$(H3 $(LNAME2 closures, Delegates & Closures)) + + $(P A $(DDSUBLINK spec/type, delegates, delegate) can be set to a + non-static $(RELATIVE_LINK2 nested, nested function):) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------ +int delegate() dg; + +void test() +{ + int a = 7; + int foo() { return a + 3; } + + dg = &foo; + int i = dg(); // i is set to 10 +} + +void main() +{ + test(); + int i = dg(); // ok, test.a is in a closure and still exists + assert(i == 10); +} +------ +) + + $(P The stack variables referenced by a nested function are + still valid even after the function exits (NOTE this is different + from D 1.0). + This combining of the environment and the function is called + a $(I dynamic closure). + ) + + $(P Those referenced stack variables that make up the closure + are allocated on the GC heap, unless:) + + * The closure is passed to a $(RELATIVE_LINK2 scope-parameters, `scope` parameter). + * The closure is an initializer for a + $(DDSUBLINK spec/attribute, scope, `scope` variable). + * The closure is assigned to a `scope` variable. + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +@nogc: +void f(scope int delegate()); +void g(int delegate()); + +void main() +{ + int i; + int h() { return i; } + h(); // OK + scope x = &h; // OK + x(); // OK + //auto y = &h; // error, can't allocate closure in @nogc function + f(&h); // OK + //g(&h); // error + + // delegate literals + f(() => i); // OK + scope d = () => i; // OK + d = () => i + 1; // OK + f(d); + //g(() => i); // error, can't allocate closure in @nogc function +} +--- +) + + $(NOTE Returning addresses of stack variables, however, is not + a closure and is an error. + ) + +$(H3 $(LNAME2 method-delegates, Method Delegates)) + + $(P Delegates to non-static nested functions contain two pieces of + data: the pointer to the stack frame of the lexically enclosing + function (called the $(I context pointer)) and the address of the + function. This is analogous to struct/class non-static member + function delegates consisting of a $(I this) pointer and + the address of the member function. + Both forms of delegates are indistinguishable, and are + the same type. + ) + $(P A delegate can be set to a particular object and method using `&obj.method`:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------ +struct Foo +{ + int a; + int get() { return a; } +} + +int add1(int delegate() dg) +{ + return dg() + 1; +} + +void main() +{ + Foo f = {7}; + int delegate() dg = &f.get; // bind to an instance of Foo and a method + int i = add1(dg); + assert(i == 8); + + int x = 27; + int abc() { return x; } + + i = add1(&abc); + assert(i == 28); +} +------ +) + +$(H3 $(LNAME2 function-delegate-init, Initialization)) + + $(P Function pointers are zero-initialized by default. + They can be initialized to the address of any function (including a function literal). + Initialization with the address of a function that requires a context pointer + is not allowed in @safe functions. + ) + + $(UNDEFINED_BEHAVIOR Calling a function pointer that was set to point to + a function that requires a context pointer. + ) + + --- + struct S + { + static int sfunc(); + int member(); // has hidden `this` reference parameter + } + + @safe void sun() + { + int function() fp = &S.sfunc; + fp(); // Ok + fp = &S.member; // error + } + + @system void moon() + { + int function() fp = &S.member; // Ok because @system + fp(); // undefined behavior + } + --- + + $(P Delegates are zero-initialized by default. + They can be initialized by taking the address of a non-static member function, + but a context pointer must be supplied. + They can be initialized by taking the address of a non-static nested function + or function literal, + where the context pointer will be set to point to the stack frame, closure, or `null`. + ) + + $(P Delegates cannot be initialized by taking the address of a global function, + a static member function, or a static nested function. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + struct S + { + static int sfunc(); + int member() { return 1; } + } + + void main() + { + S s; + int delegate() dg = &s.member; // Ok, s supplies context pointer + assert(dg() == 1); + + //dg = &S.sfunc; // error + //dg = &S.member; // error + + int moon() { return 2; } + dg = &moon; // Ok + assert(dg() == 2); + + static int mars() { return 3; } + //dg = &mars; // error + + dg = () { return 4; }; // Ok + assert(dg() == 4); + } + --- + ) + $(P The last assignment uses a $(GLINK2 expression, FunctionLiteral), which + $(DDSUBLINK spec/expression, lambda-type-inference, is inferred) + as a delegate.) + + $(NOTE Function pointers can be passed to functions taking a delegate argument by passing + them through the $(REF toDelegate, std,functional) template, which converts any callable + to a delegate with a `null` context pointer. + ) + + +$(H3 $(LNAME2 anonymous, Anonymous Functions and Anonymous Delegates)) + + $(P See $(GLINK2 expression, FunctionLiteral)s. + ) + +$(H2 $(LNAME2 main, $(D main()) Function)) + + $(P For console programs, $(D main()) serves as the entry point. + It gets called after all the $(DDSUBLINK spec/module, staticorder, module initializers) + are run, and after any $(DDLINK spec/unittest, Unit Tests, unittests) are run. + After it returns, all the module destructors are run. + $(D main()) must be declared as follows: + ) + +$(GRAMMAR +$(GNAME MainFunction): + $(GLINK MainReturnDecl) $(D main$(LPAREN)$(RPAREN)) $(GLINK FunctionBody) + $(GLINK MainReturnDecl) $(D main$(LPAREN)string[]) $(GLINK_LEX Identifier)$(D $(RPAREN)) $(GLINK FunctionBody) + +$(GNAME MainReturnDecl): + $(D void) + $(D int) + $(GLINK2 type, noreturn) + $(RELATIVE_LINK2 auto-functions, $(D auto)) +) + + $(UL + $(LI If `main` returns `void`, the OS will receive a zero value on success.) + $(LI If `main` returns `void` or `noreturn`, the OS will receive a non-zero + value on abnormal termination, such as an uncaught exception.) + $(LI If `main` is declared as `auto`, the inferred return type must be + one of `void`, `int` and `noreturn`.) + ) + + $(P If the $(D string[]) parameter is declared, the parameter will hold + arguments passed to the program by the OS. The first argument is typically + the executable name, followed by any command-line arguments.) + + $(NOTE The runtime can remove any arguments prefixed `--DRT-`.) + + $(NOTE The aforementioned return / parameter types may be annotated with $(D const), + $(D immutable). They may also be replaced by $(D enum)'s with matching base types.) + + $(P The main function must have D linkage.) + + $(P Attributes may be added as needed, e.g. `@safe`, `@nogc`, `nothrow`, etc.) + + $(H3 $(LNAME2 betterc-main, $(D extern(C) main()) Function)) + + $(P Programs may define an $(D extern(C) main) function as an alternative to the + standard $(RELATIVE_LINK2 main, entry point). This form is required for + $(DDLINK spec/betterc, Better C, $(B BetterC)) programs.) + + $(P A C $(D main) function must be declared as follows:) + +$(GRAMMAR +$(GNAME CMainFunction): + $(D extern (C)) $(GLINK MainReturnDecl) $(D main$(LPAREN)$(GLINK CmainParameters)$(OPT)$(RPAREN)) $(GLINK2 statement, BlockStatement) + +$(GNAME CmainParameters): + $(D int) $(GLINK_LEX Identifier), $(D char**) $(GLINK_LEX Identifier) + $(D int) $(GLINK_LEX Identifier), $(D char**) $(GLINK_LEX Identifier), $(D char**) $(GLINK_LEX Identifier) +) + + $(P When defined, the first two parameters denote a C-style array (length + pointer) + that holds the arguments passed to the program by the OS. The third parameter is a POSIX + extension called $(D environ) and holds information about the current environment variables.) + + $(NOTE The exemption for storage classes / $(D enum)'s defined for a D $(D main) function + also applies to C $(D main) functions.) + + $(P This function takes the place of the C main function and is executed immediately without + any setup or teardown associated with a D $(D main) function. Programs reliant on module + constructors, module destructors, or unittests need to manually perform (de)initialization + using the appropriate $(DDSUBLINK phobos/core_runtime, Runtime, runtime functions).) + + $(IMPLEMENTATION_DEFINED Other system-specific entry points may exist, such as + `WinMain` and `DllMain` on Windows systems. + ) + + $(NOTE Programs targeting platforms which require a different signature for $(D main) can use + a function with $(DDSUBLINK spec/pragma, mangle, explicit mangling): + + --- + pragma(mangle, "main") + int myMain(int a, int b, int c) + { + return 0; + } + --- + + ) + + +$(H2 $(LNAME2 function-templates, Function Templates)) + + $(P Functions can have compile time arguments in the form of a template. + See $(DDSUBLINK spec/template, function-templates, function templates).) + + +$(H2 $(LNAME2 interpretation, Compile Time Function Execution (CTFE))) + + $(P In contexts where a compile time value is required, functions + can be used to compute those values. This is called $(I Compile Time Function + Execution), or $(I CTFE).) + + $(P These contexts are:) + + $(UL + $(LI initialization of a static variable or a + $(DDSUBLINK spec/enum, manifest_constants, manifest constant)) + $(LI static initializers of struct/class members) + $(LI dimension of a $(DDSUBLINK spec/arrays, static-arrays, static array)) + $(LI argument for a $(DDSUBLINK spec/template, template_value_parameter, + template value parameter)) + $(LI $(DDSUBLINK spec/version, staticif, `static if`)) + $(LI $(DDSUBLINK spec/version, staticforeach, `static foreach`)) + $(LI $(DDSUBLINK spec/version, static-assert, `static assert`)) + $(LI $(DDSUBLINK spec/statement, mixin-statement, + `mixin` statement)) + $(LI $(DDLINK spec/pragma, Pragmas, `pragma` argument)) + $(LI $(DDLINK spec/traits, Traits, `__traits` argument)) + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +enum eval(alias arg) = arg; + +int square(int i) +{ + return i * i; +} + +void main() +{ + import std.stdio; + + static j = square(3); // CTFE + writeln(j); + assert(square(4) == 16); // run time + static assert(square(3) == 9); // CTFE + writeln(eval!(square(5))); // CTFE +} +--- +) + + $(P The function must have a $(GLINK FunctionBody).) + + $(P CTFE is subject to the following restrictions:) + + $(OL + $(LI Expressions may not reference any mutable static variables.) + + $(LI $(DDSUBLINK spec/iasm, asmstatements, AsmStatements) are not permitted) + + $(LI Non-portable casts (e.g., from $(D int[]) to $(D float[])), including + casts which depend on endianness, are not permitted. + Casts between signed and unsigned types are permitted.) + + $(LI Reinterpretation of overlapped fields in a union is not permitted.) + + $(LI Undefined behavior must not occur.) + ) + + $(P Pointers are permitted in CTFE, provided they are used safely:) + + $(UL + $(LI + Pointer arithmetic is permitted only on pointers which point to static + or dynamic array elements. + A pointer may also point to the first element past the array, although + such pointers cannot be dereferenced. + Pointer arithmetic on pointers which are null, + or which point to a non-array, is not allowed. + ) + + $(LI + Ordered comparison ($(D <), $(D <)$(D =), $(D >), $(D >=)) between two pointers is permitted + when both pointers point to the same array, or when at least one + pointer is $(D null). + ) + + $(LI + Pointer comparisons between discontiguous memory blocks are illegal, + unless two such comparisons are combined + using $(D &&) or $(CODE_PIPE)$(CODE_PIPE) to yield a result which is independent of the + ordering of memory blocks. Each comparison must consist of two pointer + expressions compared with $(D <), $(D <)$(D =), $(D >), + or $(D >)$(D =), and may optionally be + negated with $(D !). + For example, the expression $(D (p1 > q1 && p2 <= q2)) + is permitted when $(D p1), $(D p2) are expressions yielding pointers + to memory block $(I P), and $(D q1), $(D q2) are expressions yielding + pointers to memory block $(I Q), even when $(I P) and $(I Q) are + unrelated memory blocks. + It returns true if $(D [p1..p2]) lies inside $(D [q1..q2]), and false otherwise. + Similarly, the expression $(D (p1 < q1 || p2 > q2)) is true if + $(D [p1..p2]) lies outside $(D [q1..q2]), and false otherwise. + ) + + $(LI + Equality comparisons ($(D ==), $(D !=), $(D is), $(D !is)) are + permitted between all pointers, without restriction. + ) + + $(LI + Any pointer may be cast to $(D void*) and from $(D void*) back to + its original type. Casting between pointer and non-pointer types is + illegal. + ) + ) + + $(P The above restrictions apply only to expressions which are + actually evaluated. For example: + ) +--- +static int y = 0; + +int countTen(int x) +{ + if (x > 10) + ++y; // access static variable + return x; +} + +static assert(countTen(6) == 6); // OK +static assert(countTen(12) == 12); // invalid, modifies y. +--- + $(P The $(D __ctfe) boolean pseudo-variable evaluates to $(D_KEYWORD true) + during CTFE but $(D_KEYWORD false) otherwise. + ) + + $(NOTE `__ctfe` can be used to provide + an alternative execution path to avoid operations which are forbidden + in CTFE. Every usage of $(D __ctfe) is statically evaluated + and has no run-time cost. + ) + + $(P Non-recoverable errors (such as $(D_KEYWORD assert) failures) are illegal. + ) + + $(IMPLEMENTATION_DEFINED Executing functions via CTFE can take considerably + longer than executing it at run time. + If the function goes into an infinite loop, it may cause the compiler to hang. + ) + + $(IMPLEMENTATION_DEFINED + Functions executed via CTFE can give different results + from run time when implementation-defined behavior occurs. + ) + + +$(H3 $(LNAME2 string-mixins, String Mixins and Compile Time Function Execution)) + + $(P All functions that execute in CTFE must also + be executable at run time. The compile time evaluation of + a function does the equivalent of running the function at + run time. The semantics of a function cannot + depend on compile time values of the function. For example:) + +--- +int foo(string s) +{ + return mixin(s); +} + +const int x = foo("1"); +--- + + $(COMMENT Intentionally not a $(P ...) so that it doesn't get a + paragraph number, because this continues the paragraph above.) + + is illegal, because the runtime code for `foo` cannot be + generated. + + $(BEST_PRACTICE A function template, where `s` is a template argument, + would be the appropriate + method to implement this sort of thing. + ) + + +$(H2 $(LNAME2 nogc-functions, No-GC Functions)) + + $(P No-GC functions are functions marked with the $(D @nogc) attribute. + Those functions do not allocate memory on the GC heap. + These operations are not allowed in No-GC functions: + ) + + $(OL + $(LI $(DDSUBLINK spec/expression, array-literal-heap, constructing an array) on the heap) + $(LI resizing an array by writing to its $(D .length) property) + $(LI $(DDSUBLINK spec/expression, CatExpression, array concatenation)) + $(LI $(DDSUBLINK spec/expression, simple_assignment_expressions, array appending)) + $(LI $(DDSUBLINK spec/expression, AssocArrayLiteral, constructing an associative array)) + $(LI $(DDSUBLINK spec/expression, IndexOperation, indexing) an associative array + $(RATIONALE Indexing may throw a $(D RangeError) if the specified key is not present.)) + $(LI $(DDSUBLINK spec/expression, NewExpression, allocating an object with `new`) on the heap + $(NOTE `new` declarations of $(D class) types in function scopes are compatible with + $(D @nogc) if used to initialize a $(DDSUBLINK spec/attribute, scope-class-var, $(D scope) variable), + as they result in allocations on the stack.)) + $(LI calling functions that are not `@nogc`, unless the call is + in a $(GLINK2 version, ConditionalStatement) + controlled by a $(GLINK2 version, DebugCondition)) + ) + + --- + @nogc void foo() + { + auto a = ['a']; // (1) error, allocates + a.length = 1; // (2) error, array resizing allocates + a = a ~ a; // (3) error, arrays concatenation allocates + a ~= 'c'; // (4) error, appending to arrays allocates + + auto aa = ["x":1]; // (5) error, allocates + aa["abc"]; // (6) error, indexing may allocate and throws + + auto p = new int; // (7) error, operator new allocates + scope auto p = new GenericClass(); // (7) Ok + bar(); // (8) error, bar() may allocate + debug bar(); // (8) Ok + } + void bar() { } + --- + + $(P No-GC functions can only use a closure if it is `scope` - + see $(RELATIVE_LINK2 closures, Delegates & Closures). + ) + + --- + @nogc int delegate() foo() + { + int n; // error, variable n cannot be allocated on heap + return (){ return n; } // since `n` escapes `foo()`, a closure is required + } + --- + + $(P $(D @nogc) affects the type of the function. A $(D @nogc) + function is covariant with a non-$(D @nogc) function. + ) + + --- + void function() fp; + void function() @nogc gp; // pointer to @nogc function + + void foo(); + @nogc void bar(); + + void test() + { + fp = &foo; // ok + fp = &bar; // ok, it's covariant + gp = &foo; // error, not contravariant + gp = &bar; // ok + } + --- + + $(BEST_PRACTICE Since a function marked `@nogc` will not do any GC allocations, + that implies it will not cause any GC collections to run. However, + another thread may still allocate with the GC and trigger a collection. + The recommended way to prevent GC collections from being run is to call + $(LINK2 https://dlang.org/phobos/core_memory.html#GC.disable, core.memory.GC.disable()) + instead. This will stop collections from being run in any thread until a corresponding + call to `core.memory.GC.enable()` is run. GC allocations can still be performed + when `GC.disable()` is in effect.) + +$(H2 $(LNAME2 function-safety, Function Safety)) + +$(H3 $(LNAME2 safe-functions, Safe Functions)) + + $(P Safe functions are marked with the $(CODE @safe) attribute. + `@safe` can be inferred, + see $(RELATIVE_LINK2 function-attribute-inference, Function Attribute Inference).) + + $(P Safe functions have $(RELATIVE_LINK2 safe-interfaces, safe + interfaces). An implementation must enforce this by restricting the + function's body to operations that are known to be safe, + except for calls to $(RELATIVE_LINK2 trusted-functions, `@trusted` functions).) + + $(P The following restrictions are enforced by the compiler in safe + functions:) + + $(UL + $(LI No casting from a pointer type `T` to any type `U` with pointers, except when:) + * `T` implicitly converts to `U` + * `U` $(DDSUBLINK spec/expression, cast_class, implements) class or interface + `T`, and both types are `extern(D)` + * `T.opCast!U` is `@safe` + * Both types $(DDSUBLINK spec/expression, cast_array, are dynamic arrays), or + both types $(DDSUBLINK spec/expression, cast_pointers, are raw pointers), and: + * The target element type is not a pointer type + * The target element type is not mutable when the source element type is a pointer type + * Either the target element type is a dynamic array, or the target element + type is no larger than the source element type + * Any source element type modifiers implicitly convert to the target element type modifiers + * Neither element type is a function type + * The target element type is not mutable when the source type is `void[]` + * The target element type only stores $(RELATIVE_LINK2 safe-values, safe values) + * The source element type only stores safe values when the target element type is mutable + * Neither element type is $(DDSUBLINK spec/struct, opaque_struct_unions, opaque). + $(LI No casting from any non-pointer type to a pointer type.) + $(LI No $(DDSUBLINK spec/expression, pointer_arithmetic, pointer arithmetic) + (including pointer indexing & slicing).) + $(LI Cannot access array $(DDSUBLINK spec/arrays, ptr-property, `.ptr` property).) + $(LI Cannot copy into a $(DDSUBLINK spec/arrays, void_arrays, void array).) + $(LI Cannot access union fields that:) + * Have pointers or references overlapping with other types + * Have invariants overlapping with other types + * Overlap with fields that could become $(RELATIVE_LINK2 safe-values, unsafe values) + $(LI Calling any $(RELATIVE_LINK2 system-functions, System Functions).) + $(LI No catching of exceptions that are not derived from + $(LINK2 https://dlang.org/phobos/object.html#.Exception, $(D class Exception)).) + $(LI $(DDSUBLINK spec/iasm, asmstatements, Inline assembler) must be marked as + `@trusted`.) + $(LI No explicit casting (except with a matching `@safe` `opCast`) of:) + * mutable objects to immutable (except basic data types) + * immutable objects to mutable (except basic data types) + * thread local objects to shared + * shared objects to thread local + $(LI Cannot access $(DDSUBLINK spec/attribute, system-variables, `@system`) + or $(D __gshared) variables.) + $(LI Cannot use $(D void) initializers for types containing:) + * Pointers/reference types + * Types with invariants + * Unsafe values + ) + + $(NOTE When indexing or slicing an array, an out of bounds access + will cause a runtime error. + ) + + $(P Functions nested inside safe functions default to being + safe functions. + ) + + $(P Safe functions are covariant with trusted or system functions.) + + $(BEST_PRACTICE Mark as many functions `@safe` as practical.) + +$(H4 Safe External Functions) + + $(P External functions don't have a function body visible to the compiler: + ) + --- + @safe extern (C) void play(); + --- + and so safety cannot be verified automatically. + + $(BEST_PRACTICE Explicitly set an attribute for external functions rather + than relying on default settings.) + +$(H3 $(LNAME2 trusted-functions, Trusted Functions)) + + $(P Trusted functions are marked with the $(CODE @trusted) attribute.) + + $(P Like $(RELATIVE_LINK2 safe-functions, safe functions), trusted + functions have $(RELATIVE_LINK2 safe-interfaces, safe interfaces). + Unlike safe functions, this is not enforced by restrictions on the + function body. Instead, it is the responsibility of the programmer to + ensure that the interface of a trusted function is safe.) + + $(P Example:) + + --- + immutable(int)* f(int* p) @trusted + { + version (none) p[2] = 13; + // Invalid. p[2] is out of bounds. This line would exhibit undefined + // behavior. + + version (none) p[1] = 13; + // Invalid. In this program, p[1] happens to be in-bounds, so the + // line would not exhibit undefined behavior, but a trusted function + // is not allowed to rely on this. + + version (none) return cast(immutable) p; + // Invalid. @safe code still has mutable access and could trigger + // undefined behavior by overwriting the value later on. + + int* p2 = new int; + *p2 = 42; + return cast(immutable) p2; + // Valid. After f returns, no mutable aliases of p2 can exist. + } + + void main() @safe + { + int[2] a = [10, 20]; + int* mp = &a[0]; + immutable(int)* ip = f(mp); + assert(a[1] == 20); // Guaranteed. f cannot access a[1]. + assert(ip !is mp); // Guaranteed. f cannot introduce unsafe aliasing. + } + --- + + $(P Trusted functions may call safe, trusted, or system functions. + ) + + $(P Trusted functions are covariant with safe or system functions.) + + $(BEST_PRACTICE Trusted functions should be kept small so + that they are easier to manually verify. + ) + +$(H3 $(LNAME2 system-functions, System Functions)) + + $(P System functions are functions not marked with $(CODE @safe) or + $(CODE @trusted) + and are not nested inside $(CODE @safe) functions. + System functions may be marked with the $(CODE @system) attribute. + A function being system does not mean it actually is unsafe, it just + means that its safety must be manually verified. + ) + + $(P System functions are $(B not) covariant with trusted or safe functions. + ) + + $(P System functions can call safe and trusted functions.) + + $(BEST_PRACTICE When in doubt, mark `extern (C)` and `extern (C++)` functions as + `@system` when their implementations are not in D, as the D compiler will be + unable to check them. Most of them are `@safe`, but will need to be manually + checked.) + + $(BEST_PRACTICE The number and size of system functions should be minimized. + This minimizes the work necessary to manually check for safety.) + +$(H3 $(LNAME2 safe-interfaces, Safe Interfaces)) + + $(P When a function call's arguments, $(RELATIVE_LINK2 closures, any context) + and accessible globals each have $(RELATIVE_LINK2 safe-values, safe + values) with $(RELATIVE_LINK2 safe-aliasing, safe aliasing), that + function has a safe interface when:) + $(OL + $(LI it cannot exhibit + $(DDSUBLINK spec/glossary, undefined_behavior, undefined behavior), + and) + $(LI it cannot create unsafe values that are accessible from + `@safe` code (e.g., via return values, global variables, + or `ref` parameters), and) + $(LI it cannot introduce unsafe aliasing that is accessible from + `@safe` code.) + ) + + $(P Functions that meet these requirements may be + $(RELATIVE_LINK2 safe-functions, `@safe`) or + $(RELATIVE_LINK2 trusted-functions, `@trusted`). Function that do not + meet these requirements can only be + $(RELATIVE_LINK2 system-functions, `@system`).) + + $(P Examples:) + + $(UL + $(LI + C's `free` does not have a safe interface: + --- + extern (C) @system void free(void* ptr); + --- + because `free(p)` invalidates `p`, making its value unsafe. + `free` can only be `@system`. + ) + $(LI + C's `strlen` and `memcpy` do not have safe interfaces: + --- + extern (C) @system size_t strlen(char* s); + extern (C) @system void* memcpy(void* dst, void* src, size_t nbytes); + --- + because they iterate pointers based on unverified assumptions + (`strlen` assumes that `s` is zero-terminated; `memcpy` assumes + that the memory objects pointed to by `dst` and `src` are at least `nbytes` big). Any function + that traverses a C string passed as an argument can only be + `@system`. Any function that trusts a separate parameter for + array bounds can only be `@system`. + ) + $(LI + C's `malloc` does have a safe interface: + --- + extern (C) @trusted void* malloc(size_t sz); + --- + It does not exhibit undefined behavior for any input. It returns + either a valid pointer, which is safe, or `null` which is also + safe. It returns a pointer to a fresh allocation, so it cannot + introduce any unsafe aliasing. + $(NOTE The implementation of `malloc` is most likely @system code.) + ) + $(LI + A D version of `memcpy` can have a safe interface: + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + @safe void memcpy(E)(E[] src, E[] dst) + { + import std.math : min; + foreach (i; 0 .. min(src.length, dst.length)) + { + dst[i] = src[i]; + } + } + --- + ) + because the rules for $(RELATIVE_LINK2 safe-values, safe + values) ensure that the lengths of the arrays are correct. + ) + ) + +$(H3 $(LNAME2 safe-values, Safe Values)) + + $(P A variable or field $(DDSUBLINK spec/attribute, system-variables, + marked as `@system`) does not hold a safe value, regardless of its type.) + + $(P For a $(DDSUBLINK spec/type, bool, `bool`), only 0 and 1 are safe values.) + + $(P For all other $(DDSUBLINK spec/type, basic-data-types, basic data types), all + possible bit patterns are safe.) + + $(P A pointer is a safe value when it is one of:) + $(OL + $(LI `null` - $(RELATIVE_LINK2 null-dereferences, see below)) + $(LI it points to a memory object that is live and + the pointed to value in that memory object is safe.) + ) + $(P Examples:) + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + int* n = null; /* n is safe because dereferencing null must either crash + or abort. */ + int* x = cast(int*) 0xDEADBEEF; /* x is (most likely) unsafe because it + is not a valid pointer and cannot be dereferenced. */ + + import core.stdc.stdlib: malloc, free; + int* p1 = cast(int*) malloc(int.sizeof); /* p1 is safe because the + pointer is valid and *p1 is safe regardless of its actual value. */ + free(p1); /* This makes p1 unsafe. */ + int** p2 = &p1; /* While it can be dereferenced, p2 is unsafe because p1 + is unsafe. */ + p1 = null; /* This makes p1 and p2 safe. */ + --- + ) + + $(P A dynamic array is safe when:) + $(OL + $(LI its pointer is safe, and) + $(LI its length is in-bounds with the corresponding memory object, + and) + $(LI all its elements are safe.) + ) + + $(P Examples:) + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + int[] f() @system + { + bool b = true; /* b is initialized safe */ + *(cast(ubyte*) &b) = 0xAA; /* b is now unsafe because it's not 0 or 1 */ + int[3] a; + int[] d1 = a[0 .. 3]; /* d1 is safe. */ + int[] d2 = a.ptr[0 .. 4]; /* d2 is unsafe because it goes beyond a's + bounds. */ + int*[] d3 = [cast(int*) 0xDEADBEEF]; /* d3 is unsafe because the + element is unsafe. */ + return d1; /* Up to here, d1 was safe, but its pointer becomes + invalid when the function returns, so the returned dynamic array + is unsafe. */ + } + --- + ) + + $(P A static array is safe when all its elements are safe. Regardless + of the element type, a static array with length zero is always safe.) + + $(P An associative array is safe when all its keys and elements are + safe.) + + $(P A struct/union instance is safe when:) + $(OL + $(LI the values of its accessible fields are safe, and) + $(LI it does not introduce $(RELATIVE_LINK2 safe-aliasing, unsafe + aliasing) with unions.) + ) + + $(P Examples:) + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + + void fun() + { + struct S { int* p; } + S s1 = S(new int); /* s1 is safe. */ + S s2 = S(cast(int*) 0xDEADBEEF); /* s2 is unsafe, because s2.p is + unsafe. */ + + union U { int* p; size_t x; } + U u = U(new int); /* Even though both u.p and u.x are safe, u is unsafe + because of unsafe aliasing. */ + } + --- + ) + + $(P A class reference is safe when it is `null` or:) + $(OL + $(LI it refers to a valid class instance of the class type or a + type derived from the class type, and) + $(LI the values of the instance's accessible fields are safe, and) + $(LI it does not introduce unsafe aliasing with unions.) + ) + + $(P A function pointer is safe when it is `null` or it refers to a valid + function that has the same or a covariant signature.) + + $(P A `delegate` is safe when:) + $(OL + $(LI its `.funcptr` property is `null` or refers to a function that matches + or is covariant with the delegate type, and) + $(LI its `.ptr` property is `null` or refers to a memory object that is in a form + expected by the function.) + ) + +$(H3 $(LNAME2 null-dereferences, Null Dereferences)) + + $(P When generating `@safe` code, a compliant implementation:) + + - Must not assume that a null dereference will not occur. Optimizations + that require that assumption cannot be used for `@safe` functions. + - Must generate code that will detect and abort execution: + - When a null dereference occurs on systems that by default do not protect + access to the first page of memory addresses. (Note that e.g. calling + [`mprotect`](https://pubs.opengroup.org/onlinepubs/007904875/functions/mprotect.html) + is `@system`). + - On all systems when an expression causes a null pointer to be indexed, + causing a memory access that is not prevented by the system. + $(RED Warning:) $(TT dmd) + [has not implemented](https://github.com/dlang/dmd/issues/17776) this yet. + +$(H3 $(LNAME2 safe-aliasing, Safe Aliasing)) + + $(P When one memory location is accessible with two different types, that + aliasing is considered safe if:) + $(OL + $(LI both types are `const` or `immutable`; or) + $(LI one of the types is mutable while the other is a `const`-qualified + $(DDSUBLINK spec/type, basic-data-types, basic data type); or) + $(LI both types are mutable basic data types; or) + $(LI one of the types is a static array type with length zero; or) + $(LI one of the types is a static array type with non-zero length, and + aliasing of the array's element type and the other type is safe; or) + $(LI both types are pointer types, and aliasing of the target types is + safe, and the target types have the same size.) + ) + + $(P All other cases of aliasing are considered unsafe.) + + $(NOTE Safe aliasing may be exposed to functions with + $(RELATIVE_LINK2 safe-interfaces, safe interfaces) without affecting their + guaranteed safety. Unsafe aliasing does not guarantee safety.) + + $(NOTE Safe aliasing does not imply that all aliased + views of the data have $(RELATIVE_LINK2 safe-values, safe values). + Those must be examined separately for safety.) + + $(P Examples:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + void f1(ref ubyte x, ref float y) @safe { x = 0; y = float.init; } + union U1 { ubyte x; float y; } // safe aliasing + + void test1() + { + U1 u1; + f1(u1.x, u1.y); // Ok + } + + void f2(ref int* x, ref int y) @trusted { x = new int; y = 0xDEADBEEF; } + union U2 { int* x; int y; } // unsafe aliasing + + void test2() + { + U2 u2; + version (none) f1(u2.x, u2.y); // not safe + } + --- + ) + +$(H2 $(LNAME2 function-attribute-inference, Function Attribute Inference)) + + $(P $(GLINK2 expression, FunctionLiteral)s, + $(RELATIVE_LINK2 auto-functions, Auto Functions), + $(RELATIVE_LINK2 auto-ref-functions, Auto Ref Functions), + $(RELATIVE_LINK2 nested, nested functions) and + $(DDSUBLINK spec/template, function-templates, function templates), + since their function bodies are always present, infer the + following attributes unless specifically overridden: + ) + * $(RELATIVE_LINK2 pure-functions, $(D pure)) + * $(RELATIVE_LINK2 nothrow-functions, $(D nothrow)) + * $(RELATIVE_LINK2 safe-functions, $(D @safe)) + * $(RELATIVE_LINK2 nogc-functions, $(D @nogc)) + * $(RELATIVE_LINK2 return-ref-parameters, return ref parameters) + * $(RELATIVE_LINK2 scope-parameters, scope parameters) + * $(RELATIVE_LINK2 return-scope-parameters, return scope parameters) + * $(RELATIVE_LINK2 ref-return-scope-parameters, ref return scope parameters) + + $(P Attribute inference is not done for other functions, even if the function + body is present. + ) + + $(P The inference is done by determining if the function body follows the + rules of the particular attribute. + ) + + $(P Cyclic functions (i.e. functions that wind up directly or indirectly + calling themselves) are inferred as being impure, throwing, and `@system`. + ) + + $(P If a function attempts to test itself for those attributes, then + the function is inferred as not having those attributes. + ) + + $(RATIONALE Function attribute inference greatly reduces the need for the user to add attributes + to functions, especially for templates.) + +$(H2 $(LNAME2 pseudo-member, Uniform Function Call Syntax (UFCS))) + + $(P A free function can be called like a member function when both:) + $(UL + $(LI The member function does not (or cannot) exist for the object expression) + $(LI The free function's first parameter type matches the object expression) + ) + $(P The object expression can be any type. + This is called a $(I UFCS function call).) + + --- + void sun(T, int); + + void moon(T t) + { + t.sun(1); + // If `T` does not have a member function `sun`, + // `t.sun(1)` is interpreted as if it were written `sun(t, 1)` + } + --- + + $(RATIONALE This provides a way to add external functions to a class as if they were + public $(RELATIVE_LINK2 final, `final`) member functions. + This enables minimizing the number of functions in a class to only the essentials that + are needed to take care of the object's private state, without the temptation to add + a kitchen-sink's worth of member functions. + It also enables + $(HTTP www.drdobbs.com/architecture-and-design/component-programming-in-d/240008321, + function chaining and component programming). + ) + This general idea has different names in other programming languages. + The following is a short list: + $(UL + $(LI C#: Extension methods) + $(LI Kotlin: Extension functions) + $(LI Zig: Dot notation) + ) + + $(P A more complex example:) + + --- + stdin.byLine(KeepTerminator.yes) + .map!(a => a.idup) + .array + .sort + .copy(stdout.lockingTextWriter()); + --- + + $(P is the equivalent of:) + + --- + copy(sort(array(map!(a => a.idup)(byLine(stdin, KeepTerminator.yes)))), lockingTextWriter(stdout)); + --- + + $(P UFCS works with $(D @property) functions:) + + --- + @property prop(X thisObj); + @property prop(X thisObj, int value); + + X obj; + obj.prop; // if X does not have member prop, reinterpret as prop(obj); + obj.prop = 1; // similarly, reinterpret as prop(obj, 1); + --- + + $(P Functions declared in a local scope are not found when searching for a matching + UFCS function. Neither are other local symbols, although local imports are searched:) + + --- + module a; + + void foo(X); + alias boo = foo; + + void main() + { + void bar(X); // bar declared in local scope + import b : baz; // void baz(X); + + X obj; + obj.foo(); // OK, calls a.foo; + //obj.bar(); // NG, UFCS does not see nested functions + obj.baz(); // OK, calls b.baz, because it is declared at the + // top level scope of module b + + import b : boo = baz; + obj.boo(); // OK, calls aliased b.baz instead of a.boo (== a.foo), + // because the declared alias name 'boo' in local scope + // overrides module scope name + } + --- + + $(P Member functions are not found when searching for a matching + UFCS function.) + + --- + class C + { + void mfoo(X); // member function + static void sbar(X); // static member function + import b : ibaz = baz; // void baz(X); + + void test() + { + X obj; + //obj.mfoo(); // NG, UFCS does not see member functions + //obj.sbar(); // NG, UFCS does not see static member functions + obj.ibaz(); // OK, ibaz is an alias of baz which is declared at + // the top level scope of module b + } + } + --- + + $(P Otherwise, UFCS function lookup proceeds normally.) + + $(RATIONALE Local function symbols are not considered by UFCS + to avoid unexpected name conflicts. See below for problematic examples.) + + --- + int front(int[] arr) { return arr[0]; } + + void main() + { + int[] a = [1,2,3]; + auto x = a.front(); // call .front by UFCS + + auto front = x; // front is now a variable + auto y = a.front(); // Error, front is not a function + } + + class C + { + int[] arr; + int front() + { + return arr.front(); // Error, C.front is not callable + // using argument types (int[]) + } + } + --- + +$(SPEC_SUBNAV_PREV_NEXT const3, Type Qualifiers, operatoroverloading, Operator Overloading) +) + +Macros: + CHAPTER=20 + TITLE=Functions + ASSIGNEXPRESSION=$(GLINK2 expression, AssignExpression) + CHECK=✔ diff --git a/spec/garbage.dd b/spec/garbage.dd new file mode 100644 index 0000000000..984f711b7d --- /dev/null +++ b/spec/garbage.dd @@ -0,0 +1,596 @@ +Ddoc + +$(SPEC_S Garbage Collection, + +$(HEADERNAV_TOC) + + $(P D is a systems programming language with support for garbage collection. + Usually it is not necessary + to free memory explicitly. Just allocate as needed, and the garbage collector will + periodically return all unused memory to the pool of available memory. + ) + + $(P D also provides the mechanisms to write code where the garbage collector + is $(B not involved). More information is provided below. + ) + + $(P Programmers accustomed to explicitly managing memory + allocation and + deallocation will likely be skeptical of the benefits and efficacy of + garbage collection. Experience both with new projects written with + garbage collection in mind, and converting existing projects to garbage + collection shows that: + ) + + $(UL + + $(LI Garbage collected programs are often faster. This is + counterintuitive, but the reasons are: + + $(UL + $(LI Reference counting is a common solution to solve explicit + memory allocation problems. The code to implement the increment and + decrement operations whenever assignments are made is one source + of slowdown. Hiding it behind smart pointer classes doesn't help + the speed. (Reference counting methods are not a general solution + anyway, as circular references never get deleted.) + ) + + $(LI Destructors are used to deallocate resources acquired by an object. + For most classes, this resource is allocated memory. + With garbage collection, most destructors then become empty and + can be discarded entirely. + ) + + $(LI All those destructors freeing memory can become significant when + objects are allocated on the stack. For each one, some mechanism must + be established so that if an exception happens, the destructors all + get called in each frame to release any memory they hold. If the + destructors become irrelevant, then there's no need to set up special + stack frames to handle exceptions, and the code runs faster. + ) + + $(LI Garbage collection kicks in only when memory gets tight. When + memory is not tight, the program runs at full speed and does not + spend any time tracing and freeing memory. + ) + + $(LI Garbage collected programs do not suffer from gradual deterioration + due to an accumulation of memory leaks. + ) + ) + ) + + $(LI Garbage collectors reclaim unused memory, therefore they do not suffer + from "memory leaks" which can cause long running applications to gradually + consume more and more memory until they bring down the system. GC programs + have longer term stability. + ) + + $(LI Garbage collected programs have fewer hard-to-find pointer bugs. This + is because there are no dangling references to freed memory. There is no + code to explicitly manage memory, hence no bugs in such code. + ) + + $(LI Garbage collected programs are faster to develop and debug, because + there's no need for developing, debugging, testing, or maintaining the + explicit deallocation code. + ) + + ) + + $(P Garbage collection is not a panacea. There are some downsides: + ) + + $(UL + + $(LI It is not always obvious when the GC allocates memory, which in + turn can trigger a collection, so the program can pause unexpectedly. + ) + + $(LI The time it takes for a collection to complete is not bounded. + While in practice it is very quick, this cannot normally be guaranteed. + ) + + $(LI Normally, all threads other than the collector thread must be + halted while the collection is in progress. + ) + + $(LI Garbage collectors can keep around some memory that an explicit + deallocator would not. + ) + + $(LI Garbage collection should be implemented as a basic operating + system + kernel service. But since it is not, garbage collecting programs must + carry around with them the garbage collection implementation. While this + can be a shared library, it is still there. + ) + ) + + $(P These constraints are addressed by techniques outlined + in $(LINK2 https://wiki.dlang.org/Memory_Management, Memory Management), including the mechanisms provided by + D to control allocations outside the GC heap. + ) + + $(P There is currently work in progress to make the runtime library free of GC heap allocations, + to allow its use in scenarios where the use of GC infrastructure is not possible. + ) + +$(H2 $(LNAME2 how_gc_works, How Garbage Collection Works)) + + $(P The GC works by:) + + $(OL + $(LI Stopping all other threads than the thread currently trying to + allocate GC memory.) + + $(LI $(SINGLEQUOTE Hijacking) the current thread for GC work.) + + $(LI Scanning all $(SINGLEQUOTE root) memory ranges for pointers into + GC allocated memory.) + + $(LI Recursively scanning all allocated memory pointed to by + roots looking for more pointers into GC allocated memory.) + + $(LI Freeing all GC allocated memory that has no active pointers + to it and do not need destructors to run.) + + $(LI Queueing all unreachable memory that needs destructors to run.) + + $(LI Resuming all other threads.) + + $(LI Running destructors for all queued memory.) + + $(LI Freeing any remaining unreachable memory.) + + $(LI Returning the current thread to whatever work it was doing.) + ) + +$(H2 $(LNAME2 gc_foreign_obj, Interfacing Garbage Collected Objects With Foreign Code)) + + $(P The garbage collector looks for roots in:) + $(OL + $(LI the static data segment) + $(LI the stacks and register contents of each thread) + $(LI the TLS (thread-local storage) areas of each thread) + $(LI any roots added by core.memory.GC.addRoot() or core.memory.GC.addRange()) + ) + + $(P If the only pointer to an object + is held outside of these areas, then the collector will miss it and free the + memory. + ) + + $(P To avoid this from happening, either) + + $(UL + $(LI maintain a pointer to the object in an area the collector does scan + for pointers;) + + $(LI add a root where a pointer to the object is stored using core.memory.GC.addRoot() + or core.memory.GC.addRange().) + + $(LI reallocate and copy the object using the foreign code's storage + allocator + or using the C runtime library's malloc/free. + ) + ) + +$(H2 $(LNAME2 pointers_and_gc, Pointers and the Garbage Collector)) + + $(P Pointers in D can be broadly divided into two categories: Those that + point to garbage collected memory, and those that do not. Examples + of the latter are pointers created by calls to C's malloc(), pointers + received from C library routines, pointers to static data, + pointers to objects on the stack, etc. For those pointers, anything + that is legal in C can be done with them. + ) + + $(P For garbage collected pointers and references, however, there are + some + restrictions. These restrictions are minor, but they are intended + to enable the maximum flexibility in garbage collector design. + ) + + $(UNDEFINED_BEHAVIOR + + $(UL + + $(LI Do not xor pointers with other values, like the + xor pointer linked list trick used in C. + ) + + $(LI Do not use the xor trick to swap two pointer values. + ) + + $(LI Do not store pointers into non-pointer variables using casts and + other tricks. + +------ +void* p; +... +int x = cast(int)p; // error: undefined behavior +------ + + The garbage collector does not scan non-pointer fields for GC pointers. + ) + + $(LI Do not take advantage of alignment of pointers to store bit flags + in the low order bits: + +------ +p = cast(void*)(cast(int)p | 1); // error: undefined behavior +------ + ) + + $(LI Do not store into pointers values that may point into the + garbage collected heap: + +------ +p = cast(void*)12345678; // error: undefined behavior +------ + + A copying garbage collector may change this value. + ) + + $(LI Do not store magic values into pointers, other than $(D null). + ) + + $(LI Do not write pointer values out to disk and read them back in + again. + ) + + $(LI Do not use pointer values to compute a hash function. A copying + garbage collector can arbitrarily move objects around in memory, + thus invalidating + the computed hash value. + ) + + $(LI Do not depend on the ordering of pointers: + +------ +if (p1 < p2) // error: undefined behavior + ... +------ + since, again, the garbage collector can move objects around in + memory. + ) + + $(LI Do not add or subtract an offset to a pointer such that the result + points outside of the bounds of the garbage collected object originally + allocated. + +------ +char* p = new char[10]; +char* q = p + 6; // ok +q = p + 11; // error: undefined behavior +q = p - 1; // error: undefined behavior +------ + ) + + $(LI Do not misalign pointers if those pointers may + point into the GC heap, such as: + +------ +struct Foo +{ + align (1): + byte b; + char* p; // misaligned pointer +} +------ + + Misaligned pointers may be used if the underlying hardware + supports them $(B and) the pointer is never used to point + into the GC heap. + ) + + $(LI Do not use byte-by-byte memory copies to copy pointer values. + This may result in intermediate conditions where there is + not a valid pointer, and if the GC pauses the thread in such a + condition, it can corrupt memory. + Most implementations of $(D memcpy()) will work since the + internal implementation of it does the copy in aligned chunks + greater than or equal to the pointer size, but since this kind of + implementation is not guaranteed by the C standard, use + $(D memcpy()) only with extreme caution. + ) + + $(LI Do not have pointers in a struct instance that point back + to the same instance. The trouble with this is if the instance + gets moved in memory, the pointer will point back to where it + came from, with likely disastrous results. + ) + + ) + ) + + $(P Things that are reliable and can be done:) + + $(UL + + $(LI Use a union to share storage with a pointer: + +------ +union U { void* ptr; int value } +------ + ) + + $(LI A pointer to the start of a garbage collected object need not + be maintained if a pointer to the interior of the object exists. + +------ +char[] p = new char[10]; +char[] q = p[3..6]; +// q is enough to hold on to the object, don't need to keep +// p as well. +------ + ) + ) + + $(P One can avoid using pointers anyway for most tasks. D provides + features + rendering most explicit pointer uses obsolete, such as reference + objects, + dynamic arrays, and garbage collection. Pointers + are provided in order to interface successfully with C APIs and for + some low level work. + ) + +$(H2 $(LNAME2 working_with_the_gc, Working with the Garbage Collector)) + + $(P Garbage collection doesn't solve every memory deallocation problem. + For + example, if a pointer to a large data structure is kept, the garbage + collector cannot reclaim it, even if it is never referred to again. To + eliminate this problem, it is good practice to set a reference or + pointer to an object to null when no longer needed. + ) + + $(P This advice applies only to static references or references embedded + inside other objects. There is not much point for such stored on the + stack to be nulled because new stack frames are initialized anyway. + ) + +$(H2 $(LNAME2 obj_pinning_and_gc, Object Pinning and a Moving Garbage Collector)) + + $(P Although D does not currently use a moving garbage collector, by following + the rules listed above one can be implemented. No special action is required + to pin objects. A moving collector will only move objects for which there + are no ambiguous references, and for which it can update those references. + All other objects will be automatically pinned. + ) + +$(H2 D $(LNAME2 op_involving_gc, Operations That Involve the Garbage Collector)) + + $(P Some sections of code may need to avoid using the garbage collector. + The following constructs may allocate memory using the garbage collector: + ) + + $(UL + $(LI $(GLINK2 expression, NewExpression)) + $(LI Array appending) + $(LI Array concatenation) + $(LI Array literals (see $(DDSUBLINK spec/expression, array-literal-heap, exceptions))) + $(LI Associative array literals) + $(LI Any insertion or removal in an associative array) + $(LI Extracting keys or values from an associative array) + $(LI Taking the address of (i.e. making a delegate to) a nested function that + accesses variables in an outer scope) + $(LI A function literal that accesses variables in an outer scope) + $(LI An $(GLINK2 expression, AssertExpression) that fails its condition) + ) + + $(P There is a $(DDSUBLINK spec/function, nogc-functions, `@nogc` function attribute) + which will error at compile-time if any construct is used which would make a GC + allocation.) + +$(H2 $(LNAME2 gc_config, Configuring the Garbage Collector)) + + $(P Since version 2.067, The garbage collector can now be configured + through the command line, the environment or by options embedded + into the executable. + ) + + $(P By default, GC options can only be passed on the command line of the program + to run, e.g.) + + --------- + app "--DRT-gcopt=profile:1 minPoolSize:16" arguments to app + --------- + + $(P Available GC options are:) + $(UL + $(LI disable:0|1 - start disabled) + $(LI profile:0|1 - enable profiling with summary when terminating program) + $(LI gc:conservative|precise|manual - select GC implementation (default = conservative)) + $(LI initReserve:N - initial memory to reserve in MB) + $(LI minPoolSize:N - initial and minimum pool size in MB) + $(LI maxPoolSize:N - maximum pool size in MB) + $(LI incPoolSize:N - pool size increment MB) + $(LI parallel:N - number of additional threads for marking) + $(LI heapSizeFactor:N - targeted heap size to used memory ratio) + $(LI cleanup:none|collect|finalize - how to treat live objects when terminating + $(UL + $(LI collect: run a collection (the default for backward compatibility)) + $(LI none: do nothing) + $(LI finalize: all live objects are finalized unconditionally) + ) + )) + + + $(P In addition, --DRT-gcopt=help will show the list of options and their current settings. + ) + $(P Command line options starting with "--DRT-" are filtered out before calling main, + so the program will not see them. They are still available via `rt_args`. + ) + $(P Configuration via the command line can be disabled by declaring a variable for the + linker to pick up before using its default from the runtime:) + --------- + extern(C) __gshared bool rt_cmdline_enabled = false; + --------- + + $(P Likewise, declare a boolean `rt_envvars_enabled` to enable configuration via the + environment variable `DRT_GCOPT`:) + --------- + extern(C) __gshared bool rt_envvars_enabled = true; + --------- + + $(P Setting default configuration properties in the executable can be done by specifying an + array of options named `rt_options`:) + --------- + extern(C) __gshared string[] rt_options = [ "gcopt=initReserve:100 profile:1" ]; + --------- + + $(P Evaluation order of options is `rt_options`, then environment variables, then command + line arguments, i.e. if command line arguments are not disabled, they can override + options specified through the environment or embedded in the executable. + ) + +$(H2 $(LNAME2 precise_gc, Precise Heap Scanning)) + + $(P Selecting `precise` as the garbage collector via the options above means type + information will be used to identify actual or possible pointers or + references within heap allocated data objects. Non-pointer data will not + be interpreted as a reference to other memory as a "false pointer". The collector + has to make pessimistic assumptions if a memory slot can contain both a pointer or + an integer value, it will still be scanned (e.g. in a `union`). + ) + + $(P To use the GC memory functions from `core.memory` + for data with a mixture of pointers and non-pointer data, pass the + TypeInfo of the allocated struct, class, or type as the optional parameter. + The default `null` is interpreted as memory that might contain pointers everywhere.) + --------- + struct S { size_t hash; Data* data; } + S* s = cast(S*)GC.malloc(S.sizeof, 0, typeid(S)); + --------- + + $(P $(RED Attention:) Enabling precise scanning needs slightly more caution with + type declarations. For example, when reserving a buffer as part of a struct and later + emplacing an object instance with references to other allocations into this memory, + do not use basic integer types to reserve the space. Doing so will cause the + garbage collector not to detect the references. Instead, use an array type that + will scan this area conservatively. Using `void*` is usually the best option as it also + ensures proper alignment for pointers being scanned by the GC. + ) + +$(H2 $(LNAME2 precise_dataseg, Precise Scanning of the DATA and TLS segment)) + + $(P $(B Windows only:) As of version 2.075, the DATA (global shared data) + and TLS segment (thread local data) of an executable + or DLL can be configured to be scanned precisely by the garbage collector + instead of conservatively. This takes + advantage of information emitted by the compiler to + identify possible mutable pointers inside these segments. Immutable pointers + $(DDSUBLINK spec/const3, immutable_storage_class, with initializers) + are excluded from scanning, too, as they can only point to preallocated memory. + ) + + $(P Precise scanning can be enabled with the D runtime option "scanDataSeg". Possible option + values are "conservative" (default) and "precise". As with the GC options, it can be + specified on the command line, in the environment or embedded into the executable, e.g.) + --------- + extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise" ]; + --------- + + + $(P $(RED Attention:) Enabling precise scanning needs slightly more caution typing + global memory. For example, to pre-allocate memory in the DATA/TLS segment and later + emplace an object instance with references to other allocations into this memory, + do not use basic integer types to reserve the space. Doing so will cause the + garbage collector not to detect the references. Instead, use an array type that + will scan this area conservatively. Using `void*` is usually the best option as it also + ensures proper alignment for pointers being scanned by the GC.) + --------- + class Singleton { void[] mem; } + align(__traits(classInstanceAlignment, Singleton)) + void*[(__traits(classInstanceSize, Singleton) - 1) / (void*).sizeof + 1] + singleton_store; + static this() + { + emplace!Singleton(singleton_store).mem = allocateMem(); + } + Singleton singleton() { return cast(Singleton)singleton_store.ptr; } + --------- + For precise typing of that area, let the compiler generate the class + instance into the DATA segment: + --------- + class Singleton { void[] mem; } + shared(Singleton) singleton = new Singleton; + shared static this() { singleton.mem = allocateSharedMem(); } + --------- + This doesn't work for TLS memory, though. + + See also: $(DDSUBLINK spec/arrays, void_arrays, void arrays). + +$(H2 $(LNAME2 gc_parallel, Parallel marking)) + + $(P By default the garbage collector uses all available CPU cores to mark the heap.) + + $(P This might affect your application if it has threads that are not suspended + during the mark phase of the collection. Configure the number of + additional threads used for marking by GC option `parallel`, + e.g. by passing `--DRT-gcopt=parallel:2` on the command + line or embedding the option into the binary via `rt_options`. + The number of threads actually created is limited to + $(LINK2 $(ROOT_DIR)library/core/cpuid/threads_per_cpu.html, `core.cpuid.threadsPerCPU-1`). + A value of `0` disables parallel marking completely.) + +$(H2 $(LNAME2 gc_registry, Adding your own Garbage Collector)) + + $(P GC implementations are added to a registry that allows to supply + more implementations by just linking them into + the binary. To do so add a function that is executed before the + D runtime initialization using `pragma(crt_constructor)`:) + --- + import core.gc.gcinterface, core.gc.registry; + extern (C) pragma(crt_constructor) void registerMyGC() + { + registerGCFactory("mygc", &createMyGC); + } + + GC createMyGC() + { + __gshared instance = new MyGC; + instance.initialize(); + return instance; + } + + class MyGC : GC { /*...*/ } + --- + + $(P [The GC modules defining the interface (gc.interface) and registration + (gc.registry) are currently not public and are subject to + change from version to version. Add an import search path to the + druntime/src path to compile the example.]) + + $(P The new GC is added to the list of available garbage collectors that + can be selected via the usual configuration options, e.g. by embedding + `rt_options` into the binary:) + --- + extern (C) __gshared string[] rt_options = ["gcopt=gc:mygc"]; + --- + + $(P The standard GC implementation from a statically + linked binary can be removed by redefining the function `extern(C) void* register_default_gcs()`. + If no custom garbage collector has been registered + all attempts to allocate GC managed memory will terminate + the application with an appropriate message.) + +$(H2 $(LNAME2 references, References)) + + $(UL + $(LI $(LINK2 https://en.wikipedia.org/wiki/Garbage_collection_$(PERCENT)28computer_science$(PERCENT)29, Wikipedia)) + $(LI $(LINK2 http://www.iecc.com/gclist/GC-faq.html, GC FAQ)) + $(LI $(LINK2 ftp://ftp.cs.utexas.edu/pub/garbage/gcsurvey.ps, Uniprocessor Garbage Collector Techniques)) + $(LI $(AMAZONLINK 0471941484, Garbage Collection: Algorithms for Automatic Dynamic Memory Management)) + ) + +$(SPEC_SUBNAV_PREV_NEXT unittest, Unit Tests, float, Floating Point) +) + +Macros: + CHAPTER=29 + TITLE=Garbage Collection diff --git a/spec/glossary.dd b/spec/glossary.dd new file mode 100644 index 0000000000..66d4c85da3 --- /dev/null +++ b/spec/glossary.dd @@ -0,0 +1,287 @@ +Ddoc + +$(SPEC_S Glossary, + +$(HEADERNAV_TOC) + +$(DL + $(DT $(LNAME2 acc, $(ACRONYM ACC, Associated C Compiler))) + $(DD The D compiler is matched to the Associated C Compiler. + For example, on Win32 ImportC is matched to the Digital Mars C compiler, + and can be matched to the Visual C compiler using the + command line switch $(DDSUBLINK dmd, switch-m32mscoff, $(TT -m32mscoff)). + Win64 ImportC is matched to the Visual C compiler. + On Posix targets, the matching C compiler is Gnu C or Clang C. + ) + + $(DT $(LNAME2 blit, $(ACRONYM BLIT, Block Transfer))) + $(DD Also known as BLT, blit refers to copying memory + byte for byte. In C, this is referred to as a memcpy + operation. + The name originated with the BLT instruction on the + DEC PDP-10 computer. + ) + + $(DT $(LNAME2 ctfe, $(ACRONYM CTFE, Compile Time Function Evaluation))) + $(DD Refers to the ability to execute regular D + functions at compile time rather than at run time.) + + $(DT $(LNAME2 code-point, Code Point)) $(DD In Unicode terminology, a $(LUCKY code point) + is a logical character. The range of code points is $(D 0) + through $(D 0x10FFFF). Only $(D dchar)s can store code points + directly; arrays of $(D char) and $(D wchar) need to use the + variable-length encodings $(LUCKY UTF-8) and $(LUCKY UTF-16).) + + $(DT $(LNAME2 cow, $(ACRONYM COW, Copy On Write))) + $(DD COW is a memory management strategy where (usually large) reference + objects are copied if they are to be modified. The constant overhead of COW can be + high, but may be preferable in applications that would otherwise do a lot of + preemptive copying. + ) + + $(DT $(LEGACY_LNAME2 data_race, data-race, Data Race)) $(DD Two or more threads writing to + the same memory location. Program behavior may depend on the arbitrary + sequencing of these memory accesses. + ) + + $(DT $(LNAME2 functor, Functor)) $(DD A user-defined type (struct or + class) that defines the function call operator ($(D opCall) in D) so it + can be used similarly to a function. + ) + + $(DT $(LNAME2 gc, $(ACRONYM GC, Garbage Collection))) + $(DD Garbage collection is the common name for the + term automatic memory management. Memory can be allocated and used, + and the GC will automatically free any chunks of memory no longer + referred to. In contrast, explicit memory management + is where the programmer must carefully match up each allocation with + one and only one call to free(). + ) + + $(DT $(LNAME2 hof, Higher-Order Function)) $(DD A function that either accepts another + function as a parameter, returns a function, or both. + ) + + $(DT $(LNAME2 ies, $(ACRONYM IES, Interpolated Expression Sequence))) + $(DD A $(DDSUBLINK spec/template, homogeneous_sequences, value sequence) + of interspersed string literals and expressions. + See $(LINK2 $(ROOT_DIR)spec/istring.html, spec). + ) + + $(DT $(LNAME2 ifti, $(ACRONYM IFTI, Implicit Function Template Instantiation))) + $(DD Refers to the ability to instantiate a template function + without having to explicitly pass in the types to the template. + Instead, the types are inferred automatically from the types of the + runtime arguments. See $(LINK2 spec/template.html#ifti, spec) for details.) + + $(DT $(LNAME2 illegal, Illegal)) + $(DD A code construct is illegal if it does not conform to the + D language specification. + This may be true even if the compiler or runtime fails to detect + the error. + ) + + $(DT $(LNAME2 input-range, Input Range)) $(DD A type (i.e., a struct or a class) that + defines the member functions `empty`, `front`, and `popFront`. Input ranges + are assumed to be strictly one-pass: there is no way to save the + state of the iteration in a copy of the range. See also $(MREF std, range).) + + $(DT $(LNAME2 implementation-defined, Implementation-Defined Behavior)) + $(DD This is variation in behavior of the D language in a manner + that is up to the implementor of the language. + An example of implementation defined behavior would be the size in + bytes of a pointer: on a 32 bit machine it would be 4 bytes, on + a 64 bit machine it would be 8 bytes. + Minimizing implementation defined behavior in the language will + maximize the portability of code. + ) + + $(DT $(LNAME2 lvalue, Lvalue)) + $(DD An lvalue is an abstract term referring to a value with an accessible + address (through e.g. the unary $(D &) operator). Typical examples of + lvalues include variables, constants introduced with `const` or `immutable` + (but not `enum`), and elements of arrays and associative arrays. Calls to + functions that return `ref` and pointer dereference expressions are also + lvalues. Lvalues can be passed to (or be returned from) functions by + reference. An lvalue is the counterpart to an rvalue. + ) + + $(DT $(LNAME2 nrvo, $(ACRONYM NRVO, Named Return Value Optimization))) + $(DD + $(P NRVO is a technique invented by Walter Bright around + 1991 (the term for it was coined later) to minimize copying of struct + data. + Functions normally return their function return values in + registers. For structs, however, they often are too big to + fit in registers. The usual solution to this is to pass to + the function a $(I hidden pointer) to a struct instance in the + caller's stack frame, and the return value is copied there. + For example: + ) +--- +struct S { int a, b, c, d; } + +S foo() +{ + S result; + result.a = 3; + return result; +} + +void test() +{ + S s = foo(); +} +--- + + $(P is rewritten as:) + +--- +S* foo(S* hidden) +{ + S result; + result.a = 3; + *hidden = result; + return hidden; +} + +void test() +{ + S tmp; + S s = *foo(&tmp); +} +--- + $(P This rewrite gives us an extra temporary object $(D tmp), + and copies the struct contents twice. + What NRVO does is recognize that the sole purpose of $(D result) + is to provide a return value, and so all references to $(D result) + can be replaced with $(D *hidden). + $(D foo) is then rewritten as: + ) +--- +S* foo(S* hidden) +{ + hidden.a = 3; + return hidden; +} +--- + $(P A further optimization is done on the call to $(D foo) to eliminate + the other copy, giving:) +--- +void test() +{ + S s; + foo(&s); +} +--- + $(P The result is written directly into the destination $(D s), + instead of passing through two other instances.) + ) + + $(DT $(LEGACY_LNAME2 narrow strings, narrow-strings, Narrow Strings)) + $(DD All arrays + that use $(D char), $(D wchar), and their qualified versions are + narrow strings. (Those include $(D string) and $(D + wstring)). Range-oriented functions in the standard library handle + narrow strings specially by automatically decoding the UTF-encoded + characters.) + + $(DT $(LEGACY_LNAME2 opApply, op-apply, opApply)) + $(DD A special member function used to iterate over a + collection; this is used by the + $(LINK2 spec/statement.html#opApply, $(I ForeachStatement)). + ) + + $(DT $(LEGACY_LNAME2 opApplyReverse, op-apply-reverse, opApplyReverse)) + $(DD A special member function used to iterate over a + collection in the reverse order; this is used by the + $(LINK2 spec/statement.html#opApplyReverse, $(I ForeachStatement)). + ) + + $(DT $(LNAME2 pod, $(ACRONYM POD, Plain Old Data))) + $(DD Refers to a struct that contains no hidden members, + has no destructor, + and can be initialized and copied via simple bit copies. + See $(DDSUBLINK spec/struct, POD, Structs). + ) + + $(DT $(LNAME2 predicate, Predicate)) $(DD A function or + delegate returning a Boolean result. Predicates can be nullary + (take no arguments), unary (take one argument), binary (take + two arguments), or n-ary (take n arguments). Usually + predicates are mentioned within the context of $(ALOCAL hof, higher-order + functions), which accept predicates as parameters. + ) + + $(DT $(LNAME2 qualifier-convertible, Qualifier-Convertible)) $(DD A type `T` is + qualifer-convertible to type `U` if and only if they only differ in qualifiers + and if a reference to `T` can be implicitly converted to a reference to `U` per + the $(LINK2 $(ROOT_DIR)spec/const3.html, language rules).) + + $(DT $(LNAME2 raii, $(ACRONYM RAII, Resource Acquisition Is Initialization))) + $(DD RAII refers to the technique of having the + $(DDSUBLINK spec/struct, struct-destructor, destructor + of a struct) or class object called when the object goes out of scope. + The destructor then releases any resources acquired by + that object. + RAII is commonly used for resources that are in short supply + or that must have a predictable point when they are released. + RAII can be used for class variables declared with the + $(DDSUBLINK spec/attribute, scope-class-var, $(D scope) storage class). + ) + + $(DT $(LNAME2 rvalue, Rvalue)) + $(DD An rvalue is an abstract term referring to a value resulting from an + expression that has no accessible memory address. This lack of address is + only conceptual; the implementation has the liberty to store an rvalue in + addressable memory. Rvalues cannot be changed and cannot be passed to (or + be returned from) functions by reference. An rvalue is the counterpart to + an lvalue. + ) + + $(DT $(LEGACY_LNAME2 sequential_consistency, sequential-consistency, Sequential Consistency)) + $(DD Data being written in one order in one thread + being visible in the same order to another thread. + ) + + $(DT $(LNAME2 sfinae, $(ACRONYM SFINAE, Substitution Failure Is Not An Error))) + $(DD If template argument deduction results in a type + that is not valid, that specialization of the template + is not considered further. It is not a compile error. + See also $(LINK2 https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error, SFINAE). + ) + + $(DT $(LNAME2 tmp, $(ACRONYM TMP, Template Metaprogramming))) + $(DD TMP is using the template features of the language to + execute programs at compile time rather than runtime.) + + $(DT $(LNAME2 tls, $(ACRONYM TLS, Thread Local Storage))) + $(DD TLS allocates each thread its own instance of the + global data. See also + $(LINK2 https://en.wikipedia.org/wiki/Thread-local_storage, Wikipedia).) + + $(DT $(LEGACY_LNAME2 undefined_behavior, undefined-behavior, $(ACRONYM UB, Undefined Behavior))) + $(DD Undefined behavior happens when an illegal code construct is + executed. Undefined behavior can include random, erratic results, + crashes, faulting, etc. + A buffer overflow is an example of undefined behavior. + ) + + $(DT $(LNAME2 uda, $(ACRONYM UDA, User-Defined Attribute))) + $(DD $(LINK2 spec/attribute.html#uda, $(I User-defined attributes)) are + metadata attached to symbols used for compile-time reflection.) + + $(DT $(LNAME2 ufcs, $(ACRONYM UFCS, Uniform Function Call Syntax))) + $(DD $(LINK2 spec/function.html#pseudo-member, Uniform function call + syntax) refers to the ability to call a function as if it were a method of + its first argument. For example `funct(arg)` may be written as + `arg.funct()`.) +) + +$(SPEC_SUBNAV_PREV_NEXT windows, Windows Programming, legacy, Legacy Code) +) + +Macros: + CHAPTER=45 + TITLE=Glossary + D=<span class="d_inlinecode">$0</span> diff --git a/spec/grammar.dd b/spec/grammar.dd new file mode 100644 index 0000000000..04cbadf432 --- /dev/null +++ b/spec/grammar.dd @@ -0,0 +1,108 @@ +Ddoc + +$(SPEC_S Grammar, + + $(P After the $(DDLINK spec/lex, Lexical, lexical analyzer) has created tokens + from the source text, the tokens are parsed into the following key constructs:) + +$(COMMENT Don't use GLINK2 macros for reference links because they are retargeted to +this page.) + + * A $(DDSUBLINK spec/module, Module, *Module*) normally has + $(DDSUBLINK spec/module, DeclDef, *DeclDef*)s. + * *DeclDef* can be a $(DDSUBLINK spec/declaration, Declaration, *Declaration*). + * *Declaration* includes + $(DDSUBLINK spec/declaration, VarDeclarations, *VarDeclarations*), + $(DDSUBLINK spec/function, FuncDeclaration, *FuncDeclaration*) and + $(DDSUBLINK spec/declaration, AggregateDeclaration, *AggregateDeclaration*) + (e.g. class and struct declarations). + +$(NOTE Many nodes are omitted from these diagrams.) + +$(COMMENT To generate images/declaration.{svg,eps} refer to +images/declaration.dot.) + +$(HTMLTAG3 center, , + <img id="conversions" alt="Declaration sub nodes" + src="https://github.com/$(STATIC%20images/declaration.svg)"> +) +$(LATEX +{\centering +\includegraphics{images/declaration.eps} +} +) + + * *VarDeclarations* declares one or more variables with a + $(DDSUBLINK spec/type, Type, *Type*). + * Each concrete *AggregateDeclaration* has *DeclDef* members. + * *FuncDeclaration* can have a $(DDSUBLINK spec/statement, BlockStatement, *BlockStatement*). + * *BlockStatement* can have $(DDSUBLINK spec/statement, Statement, *Statement*)s. + * *Statement* includes *BlockStatement*, + $(DDSUBLINK spec/statement, DeclarationStatement, *DeclarationStatement*), + $(DDSUBLINK spec/statement, ExpressionStatement, *ExpressionStatement*) and + control-flow statements. + +$(COMMENT To generate images/statement.{svg,eps} refer to +images/statement.dot.) + +$(HTMLTAG3 center, , + <img id="conversions" alt="Statement sub nodes" + src="https://github.com/$(STATIC%20images/statement.svg)"> +) +$(LATEX +{\centering +\includegraphics{images/statement.eps} +} +) + + * *DeclarationStatement* has a *Declaration*. + * *ExpressionStatement* has an $(DDSUBLINK spec/expression, Expression, *Expression*). + * *Expression* includes $(DDSUBLINK spec/expression, PrimaryExpression, *PrimaryExpression*), + $(DDSUBLINK spec/expression, AssignExpression, *AssignExpression*) and + $(DDSUBLINK spec/expression, PostfixExpression, *PostfixExpression*) (e.g. for a function call). + +$(COMMENT To generate images/expression.{svg,eps} refer to +images/expression.dot.) + +$(HTMLTAG3 center, , + <img id="conversions" alt="Expression sub nodes" + src="https://github.com/$(STATIC%20images/expression.svg)"> +) +$(LATEX +{\centering +\includegraphics{images/expression.eps} +} +) + + * *PrimaryExpression* includes $(GLINK_LEX Identifier) and + $(DDSUBLINK spec/expression, LiteralExpression, *LiteralExpression*). + * *AssignExpression* and *PostfixExpression* each have at least one kind of *Expression*. + * Every *Expression* has a $(DDSUBLINK spec/type, Type, *Type*). + + $(NOTE The remainder of this page is auto-generated, see the other pages for + semantic details.) + +$(HEADERNAV_TOC) + +$(GRAMMAR_SUMMARY) + +$(SPEC_SUBNAV_PREV_NEXT istring, Interpolation Expression Sequence, module, Modules) +) + +Macros: + CHAPTER=4 + TITLE=D Grammar + IDENTIFIER=$(GLINK Identifier) + EXPRESSION=$(GLINK Expression) + ASSIGNEXPRESSION=$(GLINK AssignExpression) + PSSEMI_PSCURLYSCOPE=$(GLINK Statement) + PSSEMI_PSCURLYSCOPE_LIST=$(GLINK ScopeStatementList) + PS0=$(GLINK NoScopeNonEmptyStatement) + PSSCOPE=$(GLINK ScopeStatement) + PSCURLY=$(GLINK BlockStatement) + PSSEMI=$(GLINK NoScopeStatement) + PSCURLY_PSSCOPE=$(GLINK ScopeBlockStatement) + PSCURLYSCOPE=$(GLINK NonEmptyOrScopeBlockStatement) + TRAITS_LINK2=$(LINK2 traits.html#$1, $(D $1)) + GLINK2=$(GLINK $2) + GRAMMAR_SUMMARY=$0 diff --git a/spec/hash-map.dd b/spec/hash-map.dd new file mode 100644 index 0000000000..77b3b78e29 --- /dev/null +++ b/spec/hash-map.dd @@ -0,0 +1,576 @@ +Ddoc + +$(SPEC_S Associative Arrays, + +$(HEADERNAV_TOC) + + $(P Associative arrays have an index that is not necessarily an integer, + and can be sparsely populated. The index for an associative array + is called the $(I key), and its type is called the $(I KeyType).) + + $(P Associative arrays are declared by placing the $(I KeyType) + within the $(D [ ]) of an array declaration: + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --------- + int[string] aa; // Associative array of ints that are + // indexed by string keys. + // The KeyType is string. + aa["hello"] = 3; // set value associated with key "hello" to 3 + int value = aa["hello"]; // lookup value from a key + assert(value == 3); + --------- + ) + + $(P Neither the $(I KeyType)s nor the element types of an associative + array can be function types or $(D void). + ) + + $(IMPLEMENTATION_DEFINED The built-in associative arrays do not preserve the order + of the keys inserted into the array. In particular, in a $(D foreach) loop the + order in which the elements are iterated is typically unspecified.) + +$(H2 $(LNAME2 literals, Literals)) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +auto aa = [21u: "he", 38: "ho", 2: "hi"]; +static assert(is(typeof(aa) == string[uint])); +assert(aa[2] == "hi"); +--- +) + $(P See $(DDSUBLINK spec/expression, associative_array_literals, Associative Array Literals).) + +$(H2 $(LNAME2 removing_keys, Removing Keys)) + + $(P Particular keys in an associative array can be removed with the + $(D remove) function: + ) + + --------- + aa.$(CODE_HIGHLIGHT remove)("hello"); + --------- + + $(P $(D remove(key)) does nothing if the given $(I key) does not exist and + returns $(D false). If the given $(I key) does exist, it removes it + from the AA and returns $(D true). + ) + + $(P All keys can be removed by using the method `clear`.) + +$(H2 $(LNAME2 testing_membership, Testing Membership)) + + $(P The $(GLINK2 expression, InExpression) yields a pointer to the value + if the key is in the associative array, or $(D null) if not: + ) + + --------- + int* p; + + p = "hello" $(CODE_HIGHLIGHT in) aa; + if (p !is null) + { + *p = 4; // update value associated with key + assert(aa["hello"] == 4); + } + --------- + + $(UNDEFINED_BEHAVIOR Adjusting the pointer to point before or after + the element whose address is returned, and then dereferencing it.) + +$(H2 $(LNAME2 using_classes_as_key, Using Classes as the KeyType)) + + $(P Classes can be used as the $(I KeyType). The behavior is controlled by the following member functions + of class $(D Object):) + + $(UL + $(LI $(D size_t toHash() @trusted nothrow)) + $(LI $(D bool opEquals(Object))) + ) + + $(P Note that the parameter to $(D opEquals) is of type + $(D Object), not the type of the class in which it is defined.) + + $(P For example:) + + --- + class Foo + { + int a, b; + + override size_t $(CODE_HIGHLIGHT toHash)() { return a + b; } + + override bool $(CODE_HIGHLIGHT opEquals)(Object o) + { + Foo foo = cast(Foo) o; + return foo && a == foo.a && b == foo.b; + } + } + --- + The default implementation of $(D opEquals) uses the address of the instance for comparisons, + and the default implementation of $(D toHash) hashes the address of the instance. + + $(IMPLEMENTATION_DEFINED + `opCmp` is not used to check for equality by the + associative array. However, since the actual `opEquals` or + `opCmp` called is not decided until runtime, the compiler cannot always + detect mismatched functions. Because of legacy issues, the compiler may + reject an associative array key type that overrides `opCmp` but not + `opEquals`. This restriction may be removed in future versions.) + + $(UNDEFINED_BEHAVIOR + $(OL + $(LI If $(D toHash) must consistently be the + same value when $(D opEquals) returns true. In other words, two objects + that are considered equal should always have the same hash value. + Otherwise, undefined behavior will result.) + )) + + $(BEST_PRACTICE + $(OL + $(LI Use the attributes `@safe`, `@nogc`, `pure`, `const`, and `scope` as much as possible + on the `toHash` and `opEquals` overrides.) + )) + +$(H2 $(LNAME2 using_struct_as_key, Using Structs or Unions as the KeyType)) + + $(P If the $(I KeyType) is a struct or union type, + a default mechanism is used + to compute the hash and comparisons of it based on the + fields of the struct value. A custom mechanism can be used + by providing the following functions as struct members: + ) + + --------- + size_t $(CODE_HIGHLIGHT toHash)() const @safe pure nothrow; + bool $(CODE_HIGHLIGHT opEquals)(ref const typeof(this) s) const @safe pure nothrow; + --------- + + $(P For example:) + + --------- + import std.string; + + struct MyString + { + string str; + + size_t $(CODE_HIGHLIGHT toHash)() const @safe pure nothrow + { + size_t hash; + foreach (char c; str) + hash = (hash * 9) + c; + return hash; + } + + bool $(CODE_HIGHLIGHT opEquals)(ref const MyString s) const @safe pure nothrow + { + return std.string.cmp(this.str, s.str) == 0; + } + } + --------- + + $(P The functions can use $(D @trusted) instead of $(D @safe).) + + $(IMPLEMENTATION_DEFINED `opCmp` is not used to check for equality by the + associative array. For this reason, and for legacy reasons, an + associative array key is not allowed to define a specialized `opCmp`, + but omit a specialized `opEquals`. This restriction may be + removed in future versions of D.) + + $(UNDEFINED_BEHAVIOR + $(OL + $(LI If $(D toHash) must consistently be the + same value when $(D opEquals) returns true. In other words, two structs + that are considered equal should always have the same hash value. + Otherwise, undefined behavior will result.) + )) + + $(BEST_PRACTICE + $(OL + $(LI Use the attributes `@nogc` as much as possible + on the `toHash` and `opEquals` overrides.) + )) + +$(H2 $(LNAME2 construction_assignment_entries, Construction or Assignment on Setting AA Entries)) + + $(P When an AA indexing access appears on the left side of an assignment + operator, it is specially handled for setting an AA entry associated with + the key.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN + --------- + string[int] aa; + string s; + + //s = aa[1]; // throws RangeError in runtime + aa[1] = "hello"; // handled for setting AA entry + s = aa[1]; // succeeds to lookup + assert(s == "hello"); + --------- +) + $(P If the assigned value type is equivalent with the AA element type:) + + $(OL + $(LI If the indexing key does not yet exist in AA, a new AA entry will be + allocated, and it will be initialized with the assigned value.) + $(LI If the indexing key already exists in the AA, the setting runs normal + assignment.) + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN + --------- + struct S + { + int val; + void opAssign(S rhs) { this.val = rhs.val * 2; } + } + S[int] aa; + aa[1] = S(10); // first setting initializes the entry aa[1] + assert(aa[1].val == 10); + aa[1] = S(10); // second setting invokes normal assignment, and + // operator-overloading rewrites it to member opAssign function. + assert(aa[1].val == 20); + --------- +) + + $(P If the assigned value type is $(B not) equivalent with the AA element + type, the expression could invoke operator overloading with normal indexing + access:) + + --------- + struct S + { + int val; + void opAssign(int v) { this.val = v * 2; } + } + S[int] aa; + aa[1] = 10; // is rewritten to: aa[1].opAssign(10), and + // throws RangeError before opAssign is called + --------- + + $(P However, if the AA element type is a struct which supports an + implicit constructor call from the assigned value, implicit construction + is used for setting the AA entry:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN + --------- + struct S + { + int val; + this(int v) { this.val = v; } + void opAssign(int v) { this.val = v * 2; } + } + S s = 1; // OK, rewritten to: S s = S(1); + s = 1; // OK, rewritten to: s.opAssign(1); + + S[int] aa; + aa[1] = 10; // first setting is rewritten to: aa[1] = S(10); + assert(aa[1].val == 10); + aa[1] = 10; // second setting is rewritten to: aa[1].opAssign(10); + assert(aa[1].val == 20); + --------- +) + This is designed for efficient memory reuse with some value-semantics + structs, eg. $(REF BigInt, std,bigint). + + --------- + import std.bigint; + BigInt[string] aa; + aa["a"] = 10; // construct BigInt(10) and move it in AA + aa["a"] = 20; // call aa["a"].opAssign(20) + --------- + +$(H2 $(LNAME2 inserting_if_not_present, Inserting if not present)) + + $(P When AA access requires that there must be a value corresponding to the + key, a value must be constructed and inserted if not present. The + $(D require) function provides a means to construct a new value via a + lazy argument. The lazy argument is evaluated when the key is not + present. The $(D require) operation avoids the need to perform multiple + key lookups.) + + --------- + class C{} + C[string] aa; + + auto a = aa.require("a", new C); // lookup "a", construct if not present + --------- + + $(P Sometimes it is necessary to know whether the value was constructed or + already exists. The $(D require) function doesn't provide a boolean + parameter to indicate whether the value was constructed but instead + allows the construction via a function or delegate. This allows the use + of any mechanism as demonstrated below.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN + --------- + class C{} + C[string] aa; + + bool constructed; + auto a = aa.require("a", { constructed=true; return new C;}()); + assert(constructed == true); + + C newc; + auto b = aa.require("b", { newc = new C; return newc;}()); + assert(b is newc); + --------- +) + +$(H2 $(LNAME2 advanced_updating, Advanced updating)) + + $(P Typically updating a value in an associative array is simply done with + an assign statement.) + + --------- + int[string] aa; + + aa["a"] = 3; // set value associated with key "a" to 3 + --------- + + $(P Sometimes it is necessary to perform different operations depending on + whether a value already exists or needs to be constructed. The + $(D update) function provides a means to construct a new value via the + $(D create) delegate or update an existing value via the $(D update) + delegate. The $(D update) operation avoids the need to perform multiple + key lookups.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN + --------- + int[string] aa; + + // create + aa.update("key", + () => 1, + (int) {} // not executed + ); + assert(aa["key"] == 1); + + // update value by ref + aa.update("key", + () => 0, // not executed + (ref int v) { + v += 1; + }); + assert(aa["key"] == 2); + --------- +) + + $(P For details, see $(REF1 update, object).) + +$(H2 $(LNAME2 runtime_initialization, Runtime Initialization of Immutable AAs)) + + $(P Immutable associative arrays are often desirable, but sometimes + initialization must be done at runtime. This can be achieved with + a constructor (static constructor depending on scope), + a buffer associative array and $(D assumeUnique):) + +$(SPEC_RUNNABLE_EXAMPLE_RUN + --------- + immutable long[string] aa; + + shared static this() + { + import std.exception : assumeUnique; + import std.conv : to; + + long[string] temp; // mutable buffer + foreach (i; 0 .. 10) + { + temp[to!string(i)] = i; + } + temp.rehash; // for faster lookups + + aa = assumeUnique(temp); + } + + void main() + { + assert(aa["1"] == 1); + assert(aa["5"] == 5); + assert(aa["9"] == 9); + } + --------- +) + +$(H2 $(LNAME2 construction_and_ref_semantic, Construction and Reference Semantics)) + + $(P An Associative Array defaults to `null`, and is constructed upon assigning the first key/value + pair. However, once constructed, an associative array has $(I reference semantics), meaning that + assigning one array to another does not copy the data. This is especially important when attempting + to create multiple references to the same array.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN + ------ + int[int] aa; // defaults to null + int[int] aa2 = aa; // copies the null reference + + assert(aa is null); + aa[1] = 1; + assert(aa2.length == 0); // aa2 still is null + aa2 = aa; + aa2[2] = 2; + assert(aa[2] == 2); // now both refer to the same instance + ------ +) + + $(P A $(GLINK2 expression, NewExpression) allows constructing an associative array instance + immediately, rather than when $(DDSUBLINK spec/hash-map, construction_assignment_entries, inserting a key).) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + int[string] a = new int[string]; + auto b = a; // a and b point to the same AA instance + + assert(b !is null); + a["1"] = 1; + assert(b["1"] == 1); + --- + ) + +$(H2 $(LNAME2 properties, Properties)) + +$(P Properties for associative arrays are:) + + $(TABLE_2COLS Associative Array Properties, + $(THEAD Property, Description) + $(TROW $(D .sizeof), Returns the size of the reference to the associative + array; it is 4 in 32-bit builds and 8 on 64-bit builds.) + $(TROW $(D .length), $(ARGS Returns number of values in the + associative array. Unlike for dynamic arrays, it is read-only.)) + $(TROW $(D .dup), Create a new associative array of the same size + and copy the contents of the associative array into it.) + $(TROW $(D .keys), $(ARGS Returns dynamic array, the elements of which are the keys in + the associative array.)) + $(TROW $(D .values), $(ARGS Returns dynamic array, the elements of which are the values in + the associative array.)) + $(TROW $(D .rehash), $(ARGS Reorganizes the associative array in place so that lookups + are more efficient. $(D rehash) is effective when, for example, + the program is done loading up a symbol table and now needs + fast lookups in it. Returns a reference to the reorganized array.)) + $(TROW $(D .clear), $(ARGS Removes all remaining keys and values from an associative array. + The array is not rehashed after removal, to allow for the existing storage to be reused. + This will affect all references to the same instance and is not equivalent to `destroy(aa)` + which only sets the current reference to `null`)) + $(TROW $(D .byKey()), $(ARGS Returns a forward range suitable for use + as a $(I ForeachAggregate) to a $(GLINK2 statement, ForeachStatement) + which will iterate over the keys of the associative array.)) + $(TROW $(D .byValue()), $(ARGS Returns a forward range suitable for use + as a $(I ForeachAggregate) to a $(GLINK2 statement, ForeachStatement) + which will iterate over the values of the associative array.)) + $(TROW $(D .byKeyValue()), $(ARGS Returns a forward range suitable for + use as a $(I ForeachAggregate) to a $(GLINK2 statement, + ForeachStatement) which will iterate over key-value pairs of the + associative array. The returned pairs are represented by an opaque type + with $(D .key) and $(D .value) properties for accessing the key and + value of the pair, respectively. Note that this is a low-level + interface to iterating over the associative array and is not compatible + with the $(LINK2 $(ROOT_DIR)phobos/std_typecons.html#.Tuple,`Tuple`) + type in Phobos. For compatibility with `Tuple`, use + $(LINK2 $(ROOT_DIR)phobos/std_array.html#.byPair,std.array.byPair) instead.)) + $(TROW $(D .get(Key key, lazy Value defVal)), + $(ARGS Looks up $(D key); if it exists returns corresponding value + else evaluates and returns $(D defVal).)) + $(TROW $(D .require(Key key, lazy Value value)), + $(ARGS Looks up $(D key); if it exists returns corresponding value + else evaluates $(D value), adds it to the associative array and returns it.)) + $(TROW $(D .update(Key key, Value delegate() create, Value delegate(Value) update)), + $(ARGS Looks up $(D key); if it exists applies the $(D update) delegate + else evaluates the $(D create) delegate and adds it to the associative array)) + ) + +$(H2 $(LNAME2 examples, Examples)) + +$(H3 $(LNAME2 aa_example, Associative Array Example: word count)) + +$(RUNNABLE_EXAMPLE +$(RUNNABLE_EXAMPLE_STDIN +too many cooks +too many ingredients +) + --------- + import std.algorithm; + import std.stdio; + + void main() + { + ulong[string] dictionary; + ulong wordCount, lineCount, charCount; + + foreach (line; stdin.byLine(KeepTerminator.yes)) + { + charCount += line.length; + foreach (word; splitter(line)) + { + wordCount += 1; + if (auto count = word in dictionary) + *count += 1; + else + dictionary[word.idup] = 1; + } + + lineCount += 1; + } + + writeln(" lines words bytes"); + writefln("%8s%8s%8s", lineCount, wordCount, charCount); + + const char[37] hr = '-'; + + writeln(hr); + foreach (word; sort(dictionary.keys)) + { + writefln("%3s %s", dictionary[word], word); + } + } + --------- +) + $(P See $(DDLINK wc, wc, wc) for the full version.) + +$(H3 $(LNAME2 aa_example_iteration, Associative Array Example: counting pairs)) + + $(P An Associative Array can be iterated in key/value fashion using a + $(DDSUBLINK spec/statement, ForeachStatement, foreach statement). As + an example, the number of occurrences of all possible substrings of + length 2 (aka 2-mers) in a string will be counted:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN + ------ + import std.range : slide; + import std.stdio : writefln; + import std.utf : byCodeUnit; // avoids UTF-8 auto-decoding + + int[string] aa; + + // The string `arr` has a limited alphabet: {A, C, G, T} + // Thus, for better performance, iteration can be done _without_ decoding + auto arr = "AGATAGA".byCodeUnit; + + // iterate over all pairs in the string and count each pair + // ('A', 'G'), ('G', 'A'), ('A', 'T'), ... + foreach (window; arr.slide(2)) + aa[window.source]++; // source unwraps the code unit range + + // iterate over all key/value pairs of the Associative Array + foreach (key, value; aa) + { + writefln("key: %s, value: %d", key, value); + } + ------ +) +$(CONSOLE +$(GT) rdmd count.d +key: AT, value: 1 +key: GA, value: 2 +key: TA, value: 1 +key: AG, value: 2 +) +) + +$(SPEC_SUBNAV_PREV_NEXT arrays, Arrays, struct, Structs and Unions) + +Macros: + CHAPTER=14 + TITLE=Associative Arrays diff --git a/spec/iasm.dd b/spec/iasm.dd new file mode 100644 index 0000000000..ad1e46e6b8 --- /dev/null +++ b/spec/iasm.dd @@ -0,0 +1,1392 @@ +Ddoc + +$(SPEC_S D x86 Inline Assembler, + +$(HEADERNAV_TOC) + + $(HTMLTAG3 a, + href="http://digitalmars.com/gift/index.html" title="Gift Shop" target="_top", + $(HTMLTAG3V img, src="https://github.com/$(ROOT_DIR)images/d5.gif" border="0" align="right" alt="Some Assembly Required" width="284" height="186") + ) + + $(P D, being a systems programming language, provides an inline + assembler. + The inline assembler is standardized for D implementations across + the same CPU family, for example, the Intel Pentium inline assembler + for a Win32 D compiler will be syntax compatible with the inline + assembler for Linux running on an Intel Pentium. + ) + + $(P Implementations of D on different architectures, however, are + free to innovate upon the memory model, function call/return conventions, + argument passing conventions, etc. + ) + + $(P This document describes the $(D x86) and $(D x86_64) implementations of + the inline assembler. The inline assembler platform support that a compiler + provides is indicated by the $(D D_InlineAsm_X86) and + $(D D_InlineAsm_X86_64) version identifiers, respectively. + ) + +$(H2 $(LNAME2 asmstatements, Asm statement)) + +$(GRAMMAR +$(GNAME AsmStatement): + $(D asm) $(GLINK2 function, FunctionAttributes)$(OPT) $(D {) $(GLINK AsmInstructionList)$(OPT) $(D }) + +$(GNAME AsmInstructionList): + $(GLINK AsmInstruction) $(D ;) + $(GLINK AsmInstruction) $(D ;) $(GSELF AsmInstructionList) +) + + $(P Assembler instructions must be located inside an `asm` block. + Like functions, `asm` statements must be anotated with adequate function attributes to be compatible with the caller. + Asm statements attributes must be explicitly defined, they are not inferred. + ) + $(P `@safe` is not allowed as an attribute, as the compiler does no safety checking of + assembly statements - use `@trusted` instead.) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +void ok() pure nothrow @safe @nogc +{ + asm pure nothrow @trusted @nogc + {} +} + +void error() @safe @nogc +{ + asm @nogc // Error: asm statement is assumed to be @system - mark it with '@trusted' if it is not + {} + asm @safe @nogc // Deprecation: asm statement cannot be @safe, use @trusted instead + {} +} +--- +) + +$(H2 $(LNAME2 asminstruction, Asm instruction)) + +$(GRAMMAR +$(GNAME AsmInstruction): + $(GLINK_LEX Identifier) $(D :) $(GSELF AsmInstruction) + $(D align) $(GLINK IntegerExpression) + $(D even) + $(D naked) + $(D db) $(GLINK Operands) + $(D ds) $(GLINK Operands) + $(D di) $(GLINK Operands) + $(D dl) $(GLINK Operands) + $(D df) $(GLINK Operands) + $(D dd) $(GLINK Operands) + $(D de) $(GLINK Operands) + $(D db) $(GLINK_LEX StringLiteral) + $(D ds) $(GLINK_LEX StringLiteral) + $(D di) $(GLINK_LEX StringLiteral) + $(D dl) $(GLINK_LEX StringLiteral) + $(D dw) $(GLINK_LEX StringLiteral) + $(D dq) $(GLINK_LEX StringLiteral) + $(GLINK Opcode) + $(GLINK Opcode) $(GLINK Operands) + +$(GNAME Opcode): + $(GLINK_LEX Identifier) + $(D int) + $(D in) + $(D out) + +$(GNAME Operands): + $(GLINK Operand) + $(GLINK Operand) $(D ,) $(GSELF Operands) +) + +$(H2 $(LNAME2 labels, Labels)) + + $(P Assembler instructions can be labeled just like other statements. + They can be the target of goto statements. + For example: + ) + +-------------- +void *pc; +asm +{ + call L1 ; + L1: ; + pop EBX ; + mov pc[EBP],EBX ; // pc now points to code at L1 +} +-------------- + +$(H2 $(LNAME2 align, align $(I IntegerExpression))) + +$(GRAMMAR +$(GNAME IntegerExpression): + $(GLINK_LEX IntegerLiteral) + $(GLINK_LEX Identifier) +) + + $(P Causes the assembler to emit NOP instructions to align the next + assembler instruction on an $(I IntegerExpression) boundary. + $(I IntegerExpression) must evaluate at compile time to an integer that is + a power of 2. + ) + + $(P Aligning the start of a loop body can sometimes have a dramatic + effect on the execution speed. + ) + +$(H2 $(LNAME2 even, even)) + + $(P Causes the assembler to emit NOP instructions to align the next + assembler instruction on an even boundary. + ) + +$(H2 $(LNAME2 naked, naked)) + + $(P Causes the compiler to not generate the function prolog and epilog + sequences. This means such is the responsibility of inline + assembly programmer, and is normally used when the entire function + is to be written in assembler. + ) + +$(H2 $(LNAME2 raw_data, db, ds, di, dl, df, dd, de)) + + $(P These pseudo ops are for inserting raw data directly into + the code. + $(D db) is for bytes, + $(D ds) is for 16 bit words, + $(D di) is for 32 bit words, + $(D dl) is for 64 bit words, + $(D df) is for 32 bit floats, + $(D dd) is for 64 bit doubles, + and $(D de) is for 80 bit extended reals. + Each can have multiple operands. + If an operand is a string literal, it is as if there were $(I length) + operands, where $(I length) is the number of characters in the string. + One character is used per operand. + For example:) + + -------------- + asm + { + db 5,6,0x83; // insert bytes 0x05, 0x06, and 0x83 into code + ds 0x1234; // insert bytes 0x34, 0x12 + di 0x1234; // insert bytes 0x34, 0x12, 0x00, 0x00 + dl 0x1234; // insert bytes 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + df 1.234; // insert float 1.234 + dd 1.234; // insert double 1.234 + de 1.234; // insert real 1.234 + db "abc"; // insert bytes 0x61, 0x62, and 0x63 + ds "abc"; // insert bytes 0x61, 0x00, 0x62, 0x00, 0x63, 0x00 + } + -------------- + +$(H2 $(LNAME2 opcodes, Opcodes)) + + $(P A list of supported opcodes is at the end. + ) + + $(P The following registers are supported. Register names + are always in upper case. + ) + +$(GRAMMAR +$(GNAME Register): + $(D AL) + $(D AH) + $(D AX) + $(D EAX) + + $(D BL) + $(D BH) + $(D BX) + $(D EBX) + + $(D CL) + $(D CH) + $(D CX) + $(D ECX) + + $(D DL) + $(D DH) + $(D DX) + $(D EDX) + + $(D BP) + $(D EBP) + + $(D SP) + $(D ESP) + + $(D DI) + $(D EDI) + + $(D SI) + $(D ESI) + + $(D ES) + $(D CS) + $(D SS) + $(D DS) + $(D GS) + $(D FS) + + $(D CR0) + $(D CR2) + $(D CR3) + $(D CR4) + + $(D DR0) + $(D DR1) + $(D DR2) + $(D DR3) + $(D DR6) + $(D DR7) + + $(D TR3) + $(D TR4) + $(D TR5) + $(D TR6) + $(D TR7) + + $(D ST) + + $(D ST(0)) + $(D ST(1)) + $(D ST(2)) + $(D ST(3)) + $(D ST(4)) + $(D ST(5)) + $(D ST(6)) + $(D ST(7)) + + $(D MM0) + $(D MM1) + $(D MM2) + $(D MM3) + $(D MM4) + $(D MM5) + $(D MM6) + $(D MM7) + + $(D XMM0) + $(D XMM1) + $(D XMM2) + $(D XMM3) + $(D XMM4) + $(D XMM5) + $(D XMM6) + $(D XMM7) +) + + $(P $(D x86_64) adds these additional registers.) + +$(GRAMMAR +$(GNAME Register64): + $(D RAX) + $(D RBX) + $(D RCX) + $(D RDX) + + $(D BPL) + $(D RBP) + + $(D SPL) + $(D RSP) + + $(D DIL) + $(D RDI) + + $(D SIL) + $(D RSI) + + $(D R8B) + $(D R8W) + $(D R8D) + $(D R8) + + $(D R9B) + $(D R9W) + $(D R9D) + $(D R9) + + $(D R10B) + $(D R10W) + $(D R10D) + $(D R10) + + $(D R11B) + $(D R11W) + $(D R11D) + $(D R11) + + $(D R12B) + $(D R12W) + $(D R12D) + $(D R12) + + $(D R13B) + $(D R13W) + $(D R13D) + $(D R13) + + $(D R14B) + $(D R14W) + $(D R14D) + $(D R14) + + $(D R15B) + $(D R15W) + $(D R15D) + $(D R15) + + $(D XMM8) + $(D XMM9) + $(D XMM10) + $(D XMM11) + $(D XMM12) + $(D XMM13) + $(D XMM14) + $(D XMM15) + + $(D YMM0) + $(D YMM1) + $(D YMM2) + $(D YMM3) + $(D YMM4) + $(D YMM5) + $(D YMM6) + $(D YMM7) + + $(D YMM8) + $(D YMM9) + $(D YMM10) + $(D YMM11) + $(D YMM12) + $(D YMM13) + $(D YMM14) + $(D YMM15) +) + +$(H3 $(LNAME2 special_cases, Special Cases)) + +$(DL + $(DT $(D lock), $(D rep), $(D repe), $(D repne), $(D repnz), $(D repz)) + $(DD These prefix instructions do not appear in the same statement + as the instructions they prefix; they appear in their own statement. + For example:) + + -------------- + asm + { + rep ; + movsb ; + } + -------------- + + $(DT $(D pause)) + $(DD This opcode is not supported by the assembler, instead use + + -------------- + asm + { + rep ; + nop ; + } + -------------- + + which produces the same result. + ) + + $(DT $(D floating point ops)) + $(DD Use the two operand form of the instruction format; + + -------------- + fdiv ST(1); // wrong + fmul ST; // wrong + fdiv ST,ST(1); // right + fmul ST,ST(0); // right + -------------- + ) +) + +$(H2 $(LNAME2 operands, Operands)) + +$(GRAMMAR +$(GNAME Operand): + $(GLINK AsmExp) + +$(GNAME AsmExp): + $(GLINK AsmLogOrExp) + $(GLINK AsmLogOrExp) $(D ?) $(GSELF AsmExp) $(D :) $(GSELF AsmExp) + +$(GNAME AsmLogOrExp): + $(GLINK AsmLogAndExp) + $(GSELF AsmLogOrExp) $(D ||) $(GLINK AsmLogAndExp) + +$(GNAME AsmLogAndExp): + $(GLINK AsmOrExp) + $(GSELF AsmLogAndExp) $(D &&) $(GLINK AsmOrExp) + +$(GNAME AsmOrExp): + $(GLINK AsmXorExp) + $(GSELF AsmOrExp) $(D |) $(GLINK AsmXorExp) + +$(GNAME AsmXorExp): + $(GLINK AsmAndExp) + $(GSELF AsmXorExp) $(D ^) $(GLINK AsmAndExp) + +$(GNAME AsmAndExp): + $(GLINK AsmEqualExp) + $(GSELF AsmAndExp) $(D &) $(GLINK AsmEqualExp) + +$(GNAME AsmEqualExp): + $(GLINK AsmRelExp) + $(GSELF AsmEqualExp) $(D ==) $(GLINK AsmRelExp) + $(GSELF AsmEqualExp) $(D !=) $(GLINK AsmRelExp) + +$(GNAME AsmRelExp): + $(GLINK AsmShiftExp) + $(GSELF AsmRelExp) $(D <) $(GLINK AsmShiftExp) + $(GSELF AsmRelExp) $(D <=) $(GLINK AsmShiftExp) + $(GSELF AsmRelExp) $(D >) $(GLINK AsmShiftExp) + $(GSELF AsmRelExp) $(D >=) $(GLINK AsmShiftExp) + +$(GNAME AsmShiftExp): + $(GLINK AsmAddExp) + $(GSELF AsmShiftExp) $(D <<) $(GLINK AsmAddExp) + $(GSELF AsmShiftExp) $(D >>) $(GLINK AsmAddExp) + $(GSELF AsmShiftExp) $(D >>>) $(GLINK AsmAddExp) + +$(GNAME AsmAddExp): + $(GLINK AsmMulExp) + $(GSELF AsmAddExp) $(D +) $(GLINK AsmMulExp) + $(GSELF AsmAddExp) $(D -) $(GLINK AsmMulExp) + +$(GNAME AsmMulExp): + $(GLINK AsmBrExp) + $(GSELF AsmMulExp) $(D *) $(GLINK AsmBrExp) + $(GSELF AsmMulExp) $(D /) $(GLINK AsmBrExp) + $(GSELF AsmMulExp) $(D %) $(GLINK AsmBrExp) + +$(GNAME AsmBrExp): + $(GLINK AsmUnaExp) + $(GSELF AsmBrExp) $(D [) $(GLINK AsmExp) $(D ]) + +$(GNAME AsmUnaExp): + $(GLINK AsmTypePrefix) $(GLINK AsmExp) + $(D offsetof) $(GLINK AsmExp) + $(D seg) $(GLINK AsmExp) + $(D +) $(GSELF AsmUnaExp) + $(D -) $(GSELF AsmUnaExp) + $(D !) $(GSELF AsmUnaExp) + $(D ~) $(GSELF AsmUnaExp) + $(GLINK AsmPrimaryExp) + +$(GNAME AsmPrimaryExp): + $(GLINK_LEX IntegerLiteral) + $(GLINK_LEX FloatLiteral) + $(D __LOCAL_SIZE) + $(D $) + $(GLINK Register) + $(GLINK Register) $(D :) $(GLINK AsmExp) + $(GLINK Register64) + $(GLINK Register64) $(D :) $(GLINK AsmExp) + $(GLINK DotIdentifier) + $(D this) + +$(GNAME DotIdentifier): + $(GLINK_LEX Identifier) + $(GLINK_LEX Identifier) $(D .) $(GSELF DotIdentifier) + $(GLINK2 type, FundamentalType) $(D .) $(GLINK_LEX Identifier) +) + + $(P The operand syntax more or less follows the Intel CPU documentation + conventions. + In particular, the convention is that for two operand instructions + the source is the right operand and the destination is the left + operand. + The syntax differs from that of Intel's in order to be compatible + with the D language tokenizer and to simplify parsing. + ) + + $(P The $(D seg) means load the segment number that the symbol is + in. This is not relevant for flat model code. + Instead, do a move from the relevant segment register. + ) + + $(P A dotted expression is evaluated during the compilation and then + must either give a constant or indicate a higher level variable + that fits in the target register or variable. + ) + +$(H3 $(LNAME2 operand_types, Operand Types)) + +$(GRAMMAR +$(GNAME AsmTypePrefix): + $(D near ptr) + $(D far ptr) + $(D word ptr) + $(D dword ptr) + $(D qword ptr) + $(GLINK2 type, FundamentalType) $(D ptr) +) + + $(P In cases where the operand size is ambiguous, as in:) + +-------------- +add [EAX],3 ; +-------------- + + it can be disambiguated by using an $(GLINK AsmTypePrefix): + + -------------- + add byte ptr [EAX],3 ; + add int ptr [EAX],7 ; + -------------- + + $(P $(D far ptr) is not relevant for flat model code. + ) + +$(H3 $(LNAME2 agregate_member_offsets, Struct/Union/Class Member Offsets)) + + $(P To access members of an aggregate, given a pointer to the aggregate + is in a register, use the $(D .offsetof) property of the qualified name + of the member:) + + -------------- + struct Foo { int a,b,c; } + int bar(Foo *f) + { + asm + { + mov EBX,f ; + mov EAX,Foo.b.offsetof[EBX] ; + } + } + void main() + { + Foo f = Foo(0, 2, 0); + assert(bar(&f) == 2); + } + -------------- + + $(P Alternatively, inside the scope of an aggregate, only the member name is needed:) + + -------------- + struct Foo // or class + { + int a,b,c; + int bar() + { + asm + { + mov EBX, this ; + mov EAX, b[EBX] ; + } + } + } + void main() + { + Foo f = Foo(0, 2, 0); + assert(f.bar() == 2); + } + -------------- + +$(H3 $(LNAME2 stack_variables, Stack Variables)) + + $(P Stack variables (variables local to a function and allocated + on the stack) are accessed via the name of the variable indexed + by EBP:) + + --- + int foo(int x) + { + asm + { + mov EAX,x[EBP] ; // loads value of parameter x into EAX + mov EAX,x ; // does the same thing + } + } + --- + + $(P If the [EBP] is omitted, it is assumed for local variables. + If $(D naked) is used, this no longer holds. + ) + +$(H3 $(LNAME2 special_symbols, Special Symbols)) + +$(DL + $(DT $(DOLLAR)) + $(DD Represents the program counter of the start of the next instruction. So, + + -------------- + jmp $ ; + -------------- + + branches to the instruction following the jmp instruction. + The $(DOLLAR) can only appear as the target of a jmp or call + instruction. + ) + + $(DT $(D __LOCAL_SIZE)) + $(DD This gets replaced by the number of local bytes in the local + stack frame. It is most handy when the $(D naked) is invoked + and a custom stack frame is programmed. + ) +) + +$(H2 $(LNAME2 supported_opcodes, Opcodes Supported)) + + $(LONGTABLE_5COLS Opcodes, , + $(TROW $(TT aaa) + , $(TT aad) + , $(TT aam) + , $(TT aas) + , $(TT adc)) + $(TROW $(TT add) + , $(TT addpd) + , $(TT addps) + , $(TT addsd) + , $(TT addss) + )$(TROW $(TT and) + , $(TT andnpd) + , $(TT andnps) + , $(TT andpd) + , $(TT andps) + )$(TROW $(TT arpl) + , $(TT bound) + , $(TT bsf) + , $(TT bsr) + , $(TT bswap) + )$(TROW $(TT bt) + , $(TT btc) + , $(TT btr) + , $(TT bts) + , $(TT call) + )$(TROW $(TT cbw) + , $(TT cdq) + , $(TT clc) + , $(TT cld) + , $(TT clflush) + )$(TROW $(TT cli) + , $(TT clts) + , $(TT cmc) + , $(TT cmova) + , $(TT cmovae) + )$(TROW $(TT cmovb) + , $(TT cmovbe) + , $(TT cmovc) + , $(TT cmove) + , $(TT cmovg) + )$(TROW $(TT cmovge) + , $(TT cmovl) + , $(TT cmovle) + , $(TT cmovna) + , $(TT cmovnae) + )$(TROW $(TT cmovnb) + , $(TT cmovnbe) + , $(TT cmovnc) + , $(TT cmovne) + , $(TT cmovng) + )$(TROW $(TT cmovnge) + , $(TT cmovnl) + , $(TT cmovnle) + , $(TT cmovno) + , $(TT cmovnp) + )$(TROW $(TT cmovns) + , $(TT cmovnz) + , $(TT cmovo) + , $(TT cmovp) + , $(TT cmovpe) + )$(TROW $(TT cmovpo) + , $(TT cmovs) + , $(TT cmovz) + , $(TT cmp) + , $(TT cmppd) + )$(TROW $(TT cmpps) + , $(TT cmps) + , $(TT cmpsb) + , $(TT cmpsd) + , $(TT cmpss) + )$(TROW $(TT cmpsw) + , $(TT cmpxchg) + , $(TT cmpxchg8b) + , $(TT cmpxchg16b) + , $(TT ) + )$(TROW $(TT comisd) + , $(TT comiss) + , $(TT ) + , $(TT ) + , $(TT ) + )$(TROW $(TT cpuid) + , $(TT cvtdq2pd) + , $(TT cvtdq2ps) + , $(TT cvtpd2dq) + , $(TT cvtpd2pi) + )$(TROW $(TT cvtpd2ps) + , $(TT cvtpi2pd) + , $(TT cvtpi2ps) + , $(TT cvtps2dq) + , $(TT cvtps2pd) + )$(TROW $(TT cvtps2pi) + , $(TT cvtsd2si) + , $(TT cvtsd2ss) + , $(TT cvtsi2sd) + , $(TT cvtsi2ss) + )$(TROW $(TT cvtss2sd) + , $(TT cvtss2si) + , $(TT cvttpd2dq) + , $(TT cvttpd2pi) + , $(TT cvttps2dq) + )$(TROW $(TT cvttps2pi) + , $(TT cvttsd2si) + , $(TT cvttss2si) + , $(TT cwd) + , $(TT cwde) + )$(TROW $(TT da) + , $(TT daa) + , $(TT das) + , $(TT db) + , $(TT dd) + )$(TROW $(TT de) + , $(TT dec) + , $(TT df) + , $(TT di) + , $(TT div) + )$(TROW $(TT divpd) + , $(TT divps) + , $(TT divsd) + , $(TT divss) + , $(TT dl) + )$(TROW $(TT dq) + , $(TT ds) + , $(TT dt) + , $(TT dw) + , $(TT emms) + )$(TROW $(TT enter) + , $(TT f2xm1) + , $(TT fabs) + , $(TT fadd) + , $(TT faddp) + )$(TROW $(TT fbld) + , $(TT fbstp) + , $(TT fchs) + , $(TT fclex) + , $(TT fcmovb) + )$(TROW $(TT fcmovbe) + , $(TT fcmove) + , $(TT fcmovnb) + , $(TT fcmovnbe) + , $(TT fcmovne) + )$(TROW $(TT fcmovnu) + , $(TT fcmovu) + , $(TT fcom) + , $(TT fcomi) + , $(TT fcomip) + )$(TROW $(TT fcomp) + , $(TT fcompp) + , $(TT fcos) + , $(TT fdecstp) + , $(TT fdisi) + )$(TROW $(TT fdiv) + , $(TT fdivp) + , $(TT fdivr) + , $(TT fdivrp) + , $(TT feni) + )$(TROW $(TT ffree) + , $(TT fiadd) + , $(TT ficom) + , $(TT ficomp) + , $(TT fidiv) + )$(TROW $(TT fidivr) + , $(TT fild) + , $(TT fimul) + , $(TT fincstp) + , $(TT finit) + )$(TROW $(TT fist) + , $(TT fistp) + , $(TT fisub) + , $(TT fisubr) + , $(TT fld) + )$(TROW $(TT fld1) + , $(TT fldcw) + , $(TT fldenv) + , $(TT fldl2e) + , $(TT fldl2t) + )$(TROW $(TT fldlg2) + , $(TT fldln2) + , $(TT fldpi) + , $(TT fldz) + , $(TT fmul) + )$(TROW $(TT fmulp) + , $(TT fnclex) + , $(TT fndisi) + , $(TT fneni) + , $(TT fninit) + )$(TROW $(TT fnop) + , $(TT fnsave) + , $(TT fnstcw) + , $(TT fnstenv) + , $(TT fnstsw) + )$(TROW $(TT fpatan) + , $(TT fprem) + , $(TT fprem1) + , $(TT fptan) + , $(TT frndint) + )$(TROW $(TT frstor) + , $(TT fsave) + , $(TT fscale) + , $(TT fsetpm) + , $(TT fsin) + )$(TROW $(TT fsincos) + , $(TT fsqrt) + , $(TT fst) + , $(TT fstcw) + , $(TT fstenv) + )$(TROW $(TT fstp) + , $(TT fstsw) + , $(TT fsub) + , $(TT fsubp) + , $(TT fsubr) + )$(TROW $(TT fsubrp) + , $(TT ftst) + , $(TT fucom) + , $(TT fucomi) + , $(TT fucomip) + )$(TROW $(TT fucomp) + , $(TT fucompp) + , $(TT fwait) + , $(TT fxam) + , $(TT fxch) + )$(TROW $(TT fxrstor) + , $(TT fxsave) + , $(TT fxtract) + , $(TT fyl2x) + , $(TT fyl2xp1) + )$(TROW $(TT hlt) + , $(TT idiv) + , $(TT imul) + , $(TT in) + , $(TT inc) + )$(TROW $(TT ins) + , $(TT insb) + , $(TT insd) + , $(TT insw) + , $(TT int) + )$(TROW $(TT into) + , $(TT invd) + , $(TT invlpg) + , $(TT iret) + , $(TT iretd) + )$(TROW $(TT iretq) + , $(TT ja) + , $(TT jae) + , $(TT jb) + , $(TT jbe) + )$(TROW $(TT jc) + , $(TT jcxz) + , $(TT je) + , $(TT jecxz) + , $(TT jg) + )$(TROW $(TT jge) + , $(TT jl) + , $(TT jle) + , $(TT jmp) + , $(TT jna) + )$(TROW $(TT jnae) + , $(TT jnb) + , $(TT jnbe) + , $(TT jnc) + , $(TT jne) + )$(TROW $(TT jng) + , $(TT jnge) + , $(TT jnl) + , $(TT jnle) + , $(TT jno) + )$(TROW $(TT jnp) + , $(TT jns) + , $(TT jnz) + , $(TT jo) + , $(TT jp) + )$(TROW $(TT jpe) + , $(TT jpo) + , $(TT js) + , $(TT jz) + , $(TT lahf) + )$(TROW $(TT lar) + , $(TT ldmxcsr) + , $(TT lds) + , $(TT lea) + , $(TT leave) + )$(TROW $(TT les) + , $(TT lfence) + , $(TT lfs) + , $(TT lgdt) + , $(TT lgs) + )$(TROW $(TT lidt) + , $(TT lldt) + , $(TT lmsw) + , $(TT lock) + , $(TT lods) + )$(TROW $(TT lodsb) + , $(TT lodsd) + , $(TT lodsw) + , $(TT loop) + , $(TT loope) + )$(TROW $(TT loopne) + , $(TT loopnz) + , $(TT loopz) + , $(TT lsl) + , $(TT lss) + )$(TROW $(TT ltr) + , $(TT maskmovdqu) + , $(TT maskmovq) + , $(TT maxpd) + , $(TT maxps) + )$(TROW $(TT maxsd) + , $(TT maxss) + , $(TT mfence) + , $(TT minpd) + , $(TT minps) + )$(TROW $(TT minsd) + , $(TT minss) + , $(TT mov) + , $(TT movapd) + , $(TT movaps) + )$(TROW $(TT movd) + , $(TT movdq2q) + , $(TT movdqa) + , $(TT movdqu) + , $(TT movhlps) + )$(TROW $(TT movhpd) + , $(TT movhps) + , $(TT movlhps) + , $(TT movlpd) + , $(TT movlps) + )$(TROW $(TT movmskpd) + , $(TT movmskps) + , $(TT movntdq) + , $(TT movnti) + , $(TT movntpd) + )$(TROW $(TT movntps) + , $(TT movntq) + , $(TT movq) + , $(TT movq2dq) + , $(TT movs) + )$(TROW $(TT movsb) + , $(TT movsd) + , $(TT movss) + , $(TT movsw) + , $(TT movsx) + )$(TROW $(TT movupd) + , $(TT movups) + , $(TT movzx) + , $(TT mul) + , $(TT mulpd) + )$(TROW $(TT mulps) + , $(TT mulsd) + , $(TT mulss) + , $(TT neg) + , $(TT nop) + )$(TROW $(TT not) + , $(TT or) + , $(TT orpd) + , $(TT orps) + , $(TT out) + )$(TROW $(TT outs) + , $(TT outsb) + , $(TT outsd) + , $(TT outsw) + , $(TT packssdw) + )$(TROW $(TT packsswb) + , $(TT packuswb) + , $(TT paddb) + , $(TT paddd) + , $(TT paddq) + )$(TROW $(TT paddsb) + , $(TT paddsw) + , $(TT paddusb) + , $(TT paddusw) + , $(TT paddw) + )$(TROW $(TT pand) + , $(TT pandn) + , $(TT pavgb) + , $(TT pavgw) + , $(TT pcmpeqb) + )$(TROW $(TT pcmpeqd) + , $(TT pcmpeqw) + , $(TT pcmpgtb) + , $(TT pcmpgtd) + , $(TT pcmpgtw) + )$(TROW $(TT pextrw) + , $(TT pinsrw) + , $(TT pmaddwd) + , $(TT pmaxsw) + , $(TT pmaxub) + )$(TROW $(TT pminsw) + , $(TT pminub) + , $(TT pmovmskb) + , $(TT pmulhuw) + , $(TT pmulhw) + )$(TROW $(TT pmullw) + , $(TT pmuludq) + , $(TT pop) + , $(TT popa) + , $(TT popad) + )$(TROW $(TT popf) + , $(TT popfd) + , $(TT por) + , $(TT prefetchnta) + , $(TT prefetcht0) + )$(TROW $(TT prefetcht1) + , $(TT prefetcht2) + , $(TT psadbw) + , $(TT pshufd) + , $(TT pshufhw) + )$(TROW $(TT pshuflw) + , $(TT pshufw) + , $(TT pslld) + , $(TT pslldq) + , $(TT psllq) + )$(TROW $(TT psllw) + , $(TT psrad) + , $(TT psraw) + , $(TT psrld) + , $(TT psrldq) + )$(TROW $(TT psrlq) + , $(TT psrlw) + , $(TT psubb) + , $(TT psubd) + , $(TT psubq) + )$(TROW $(TT psubsb) + , $(TT psubsw) + , $(TT psubusb) + , $(TT psubusw) + , $(TT psubw) + )$(TROW $(TT punpckhbw) + , $(TT punpckhdq) + , $(TT punpckhqdq) + , $(TT punpckhwd) + , $(TT punpcklbw) + )$(TROW $(TT punpckldq) + , $(TT punpcklqdq) + , $(TT punpcklwd) + , $(TT push) + , $(TT pusha) + )$(TROW $(TT pushad) + , $(TT pushf) + , $(TT pushfd) + , $(TT pxor) + , $(TT rcl) + )$(TROW $(TT rcpps) + , $(TT rcpss) + , $(TT rcr) + , $(TT rdmsr) + , $(TT rdpmc) + )$(TROW $(TT rdtsc) + , $(TT rep) + , $(TT repe) + , $(TT repne) + , $(TT repnz) + )$(TROW $(TT repz) + , $(TT ret) + , $(TT retf) + , $(TT rol) + , $(TT ror) + )$(TROW $(TT rsm) + , $(TT rsqrtps) + , $(TT rsqrtss) + , $(TT sahf) + , $(TT sal) + )$(TROW $(TT sar) + , $(TT sbb) + , $(TT scas) + , $(TT scasb) + , $(TT scasd) + )$(TROW $(TT scasw) + , $(TT seta) + , $(TT setae) + , $(TT setb) + , $(TT setbe) + )$(TROW $(TT setc) + , $(TT sete) + , $(TT setg) + , $(TT setge) + , $(TT setl) + )$(TROW $(TT setle) + , $(TT setna) + , $(TT setnae) + , $(TT setnb) + , $(TT setnbe) + )$(TROW $(TT setnc) + , $(TT setne) + , $(TT setng) + , $(TT setnge) + , $(TT setnl) + )$(TROW $(TT setnle) + , $(TT setno) + , $(TT setnp) + , $(TT setns) + , $(TT setnz) + )$(TROW $(TT seto) + , $(TT setp) + , $(TT setpe) + , $(TT setpo) + , $(TT sets) + )$(TROW $(TT setz) + , $(TT sfence) + , $(TT sgdt) + , $(TT shl) + , $(TT shld) + )$(TROW $(TT shr) + , $(TT shrd) + , $(TT shufpd) + , $(TT shufps) + , $(TT sidt) + )$(TROW $(TT sldt) + , $(TT smsw) + , $(TT sqrtpd) + , $(TT sqrtps) + , $(TT sqrtsd) + )$(TROW $(TT sqrtss) + , $(TT stc) + , $(TT std) + , $(TT sti) + , $(TT stmxcsr) + )$(TROW $(TT stos) + , $(TT stosb) + , $(TT stosd) + , $(TT stosw) + , $(TT str) + )$(TROW $(TT sub) + , $(TT subpd) + , $(TT subps) + , $(TT subsd) + , $(TT subss) + )$(TROW $(TT syscall) + , $(TT sysenter) + , $(TT sysexit) + , $(TT sysret) + , $(TT test) + )$(TROW $(TT ucomisd) + , $(TT ucomiss) + , $(TT ud2) + , $(TT unpckhpd) + , $(TT unpckhps) + )$(TROW $(TT unpcklpd) + , $(TT unpcklps) + , $(TT verr) + , $(TT verw) + , $(TT wait) + )$(TROW $(TT wbinvd) + , $(TT wrmsr) + , $(TT xadd) + , $(TT xchg) + , $(TT xlat) + )$(TROW $(TT xlatb) + , $(TT xor) + , $(TT xorpd) + , $(TT xorps) + , $(TT ) + ) + ) + +$(H3 $(LNAME2 P4_opcode_support, Pentium 4 (Prescott) Opcodes Supported)) + + $(LONGTABLE_5COLS Pentium 4 Opcodes, , + $(TROW $(TT addsubpd) + , $(TT addsubps) + , $(TT fisttp) + , $(TT haddpd) + , $(TT haddps) + )$(TROW $(TT hsubpd) + , $(TT hsubps) + , $(TT lddqu) + , $(TT monitor) + , $(TT movddup) + )$(TROW $(TT movshdup) + , $(TT movsldup) + , $(TT mwait) + , $(TT ) + , $(TT ) + ) + ) + +$(H3 $(LNAME2 amd_opcode_support, AMD Opcodes Supported)) + + $(LONGTABLE_5COLS AMD Opcodes, , + $(TROW $(TT pavgusb) + , $(TT pf2id) + , $(TT pfacc) + , $(TT pfadd) + , $(TT pfcmpeq) + )$(TROW $(TT pfcmpge) + , $(TT pfcmpgt) + , $(TT pfmax) + , $(TT pfmin) + , $(TT pfmul) + )$(TROW $(TT pfnacc) + , $(TT pfpnacc) + , $(TT pfrcp) + , $(TT pfrcpit1) + , $(TT pfrcpit2) + )$(TROW $(TT pfrsqit1) + , $(TT pfrsqrt) + , $(TT pfsub) + , $(TT pfsubr) + , $(TT pi2fd) + )$(TROW $(TT pmulhrw) + , $(TT pswapd) + , $(TT ) + , $(TT ) + , $(TT ) + ) + ) + +$(H3 $(LNAME2 simd, SIMD)) + + $(P SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 and AVX are supported.) + +$(COMMENT +$(H3 $(LNAME2 other, Other)) + $(P AES, CMUL, FSGSBASE, RDRAND, FP16C and FMA are supported.) +) + +$(COMMENT +SSE4.1 + +blendpd +blendps +blendvpd +blendvps +dppd +dpps +extractps +insertps +movntdqa +mpsadbw +packusdw +pblendub +pblendw +pcmpeqq +pextrb +pextrd +pextrq +pextrw +phminposuw +pinsrb +pinsrd +pinsrq +pmaxsb +pmaxsd +pmaxud +pmaxuw +pminsb +pminsd +pminud +pminuw +pmovsxbd +pmovsxbq +pmovsxbw +pmovsxwd +pmovsxwq +pmovsxdq +pmovzxbd +pmovzxbq +pmovzxbw +pmovzxwd +pmovzxwq +pmovzxdq +pmuldq +pmulld +ptest +roundpd +roundps +roundsd +roundss + +SSE4.2 + +crc32 +pcmpestri +pcmpestrm +pcmpistri +pcmpistrm +pcmpgtq +popcnt + +VMS + +invept +invvpid +vmcall +vmclear +vmlaunch +vmresume +vmptrld +vmptrst +vmread +vmwrite +vmxoff +vmxon + +SMX + +getsec +) + +$(H2 $(LNAME2 gcc, GCC syntax)) + +$(P The $(LINK2 https://gdcproject.org/, GNU D Compiler) uses an alternative, GCC-based syntax for inline assembler:) + +$(GRAMMAR +$(GNAME GccAsmStatement): + $(D asm) $(GLINK2 function, FunctionAttributes)$(OPT) $(D {) $(GLINK GccAsmInstructionList) $(D }) + +$(GNAME GccAsmInstructionList): + $(GLINK GccAsmInstruction) $(D ;) + $(GLINK GccAsmInstruction) $(D ;) $(GSELF GccAsmInstructionList) + +$(GNAME GccAsmInstruction): + $(GLINK GccBasicAsmInstruction) + $(GLINK GccExtAsmInstruction) + $(GLINK GccGotoAsmInstruction) + +$(GNAME GccBasicAsmInstruction): + $(GLINK2 expression, GccAsmStringExpression) + +$(GNAME GccExtAsmInstruction): + $(GLINK2 expression, GccAsmStringExpression) $(D :) $(GLINK GccAsmOperands)$(OPT) + $(GLINK2 expression, GccAsmStringExpression) $(D :) $(GLINK GccAsmOperands)$(OPT) $(D :) $(GLINK GccAsmOperands)$(OPT) + $(GLINK2 expression, GccAsmStringExpression) $(D :) $(GLINK GccAsmOperands)$(OPT) $(D :) $(GLINK GccAsmOperands)$(OPT) $(D :) $(GLINK GccAsmClobbers)$(OPT) + +$(GNAME GccGotoAsmInstruction): + $(GLINK2 expression, GccAsmStringExpression) $(D :) $(D :) $(GLINK GccAsmOperands)$(OPT) $(D :) $(GLINK GccAsmClobbers)$(OPT) $(D :) $(GLINK GccAsmGotoLabels)$(OPT) + +$(GNAME GccAsmStringExpression): + $(GLINK_LEX StringLiteral) + $(D $(LPAREN)) $(GLINK2 expression, ConditionalExpression) $(D $(RPAREN)) + +$(GNAME GccAsmOperands): + $(GLINK GccSymbolicName)$(OPT) $(GLINK_LEX GccAsmStringExpression) $(D $(LPAREN)) $(GLINK2 expression, AssignExpression) $(D $(RPAREN)) + $(GLINK GccSymbolicName)$(OPT) $(GLINK_LEX GccAsmStringExpression) $(D $(LPAREN)) $(GLINK2 expression, AssignExpression) $(D $(RPAREN)) $(D ,) $(GSELF GccAsmOperands) + +$(GNAME GccSymbolicName): + $(D [) $(GLINK_LEX Identifier) $(D ]) + +$(GNAME GccAsmClobbers): + $(GLINK_LEX GccAsmStringExpression) + $(GLINK_LEX GccAsmStringExpression) $(D ,) $(GSELF GccAsmClobbers) + +$(GNAME GccAsmGotoLabels): + $(GLINK_LEX Identifier) + $(GLINK_LEX Identifier) $(D ,) $(GSELF GccAsmGotoLabels) +) + +$(SPEC_SUBNAV_PREV_NEXT float, Floating Point, ddoc, Embedded Documentation) +) + +Macros: + CHAPTER=31 + TITLE=Inline Assembler diff --git a/spec/importc.dd b/spec/importc.dd new file mode 100644 index 0000000000..5e0d9f34aa --- /dev/null +++ b/spec/importc.dd @@ -0,0 +1,1102 @@ +Ddoc + +$(SPEC_S ImportC, + +$(HEADERNAV_TOC) + + $(P ImportC is a C compiler embedded into the D implementation. + It enables direct importation of C files, without + needing to manually prepare a D file corresponding to the declarations + in the C file. It directly compiles C files into modules that can be + linked in with D code to form an executable. It can be used + as a C compiler to compile and link 100% C programs. + ) + + $(NOTE ImportC and $(LINK2 https://dlang.org/spec/betterc.html, BetterC) are very different. + ImportC is an actual C compiler. BetterC is a subset of D that relies only on the + existence of the C Standard library. BetterC code can be linked with ImportC code, too.) + +$(H2 $(LNAME2 examples, Quick Examples)) + + $(P C code in file $(TT hello.c):) + +$(CCODE +#include <stdio.h> +int main() +{ + printf("hello world\n"); + return 0; +}) + + $(P Compile and run:) + +$(CONSOLE +dmd hello.c +./hello +hello world) + + $(P C function in file $(TT functions.c):) + +$(CCODE +int square(int i) +{ + return i * i; +}) + + $(P D program in file $(TT demo.d):) + + --- + import std.stdio; + import functions; + void main() + { + int i = 7; + writefln("The square of %s is %s", i, square(i)); + } + --- + + $(P Compile and run:) + +$(CONSOLE +dmd demo.d functions.c +./demo +The square of 7 is 49) + +$(H2 $(LNAME2 dialect, ImportC Dialect)) + + $(P There are many versions of C. ImportC is an + implementation of $(LINK2 https://en.wikipedia.org/wiki/C11_(C_standard_revision), ISO/IEC 9899:2011), + which will be referred to as $(B C11). + References to the C11 Standard will be C11 followed by the paragraph number. + Prior versions, such as C99, C89, and K+R C, are not supported. + ) + + $(IMPLEMENTATION_DEFINED Adjustment to the ImportC dialect is made to match the + behavior of the C compiler that the D compiler is matched to, + i.e. the $(ACC). + ) + + $(P Further adjustment is made to take advantage of some of the D + implementation's capabilities.) + + $(NOTE This is not a C reference manual nor programming tutorial. + It describes the specifics of the dialect of C that + ImportC is, and how to use it effectively.) + + +$(H2 $(LNAME2 command-line, Invoking ImportC)) + + $(P The ImportC compiler can be invoked:) + + $(UL + $(LI directly via the command line) + $(LI indirectly via importing a C file) + ) + + $(H3 $(LNAME2 command-line, ImportC Files on the Command Line)) + + $(P ImportC files have one of the extensions `.i`, `.h`, or `.c`. + ) + +$(CONSOLE +dmd hello.c) + + $(P will compile `hello.c` with ImportC and link it to create the executable + file `hello` (`hello.exe` on Windows) + ) + + $(BEST_PRACTICE explicitly use a `.i`, `.h`, or `.c` extension when + specifying C files on the command line.) + + $(H3 $(LNAME2 importing, Importing C Files from D Code)) + + $(P Use the D $(GLINK2 module, ImportDeclaration):) + + --- + import hello; + --- + + $(P which will, if `hello` is not a D file, and has an extension `.i`, + `.h`, or `.c`, compile `hello` with ImportC. + ) + + $(P A C file that is imported through a package and gets compiled needs + to have a module declaration that includes that package. It is done by giving it a + label as an importC module using the __module keyword guarded by __IMPORTC__ macro.) + + $(P In C file living in project/net/hi.c) + --- + #if __IMPORTC__ + __module net.hi + #endif + + int sqrt(int x) { return x * x; } + --- + + $(P D file in project/hello.d) + --- + import net.hi; // C file you need in your D source + + void main() + { + assert(sqrt(3) == 9); + } + --- + +$(CONSOLE +user@ -- project % dmd hello.d net/hi.c +) + +$(H2 $(LNAME2 preprocessor, Preprocessor)) + + $(P ImportC does not have a preprocessor. It is designed to compile C + files after they have been first run through the C preprocessor. + ImportC can automatically run the C preprocessor associated with the + $(ACC), or a preprocessor can be run manually. + ) + + $(H3 $(LNAME2 auto-cpp, Running the Preprocessor Automatically)) + + $(P If the C file has a $(TT .c) extension, ImportC will run the preprocessor + for it automatically.) + + $(OL + $(LI When compiling for Windows with the $(DDSUBLINK dmd, switch-m32omf, $(TT -m32omf)) switch, + $(TT sppn.exe) will be used as the preprocessor.) + $(LI When compiling for Windows with the $(DDSUBLINK dmd, switch-m32mscoff, $(TT -m32mscoff)) + or the $(DDSUBLINK dmd, switch-m64, $(TT -m64)) switch, $(TT cl.exe /P /Zc:preprocessor) will be used + as the preprocessor.) + $(LI When compiling for OSX, the $(TT clang -E) preprocessor will be used.) + $(LI Otherwise the $(TT cpp) preprocessor will be used.) + ) + + $(P The $(DDSUBLINK dmd, switch-v, $(TT -v)) switch can be used to observe the command + that invokes the preprocessor. + ) + + $(P The $(DDSUBLINK dmd, switch-P, $(TT -P$(I preprocessorflag))) switch passes $(TT $(I preprocessorflag)) + to the preprocessor. + ) + + $(H4 $(LNAME2 importc-h, $(TT importc.h))) + + $(P The druntime file $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/importc.h, $(TT src/importc.h)) + will automatically be $(TT #include)d first. $(TT importc.h) provides adjustments to the source code to + account for various C compiler extensions not supported by ImportC.) + + $(H4 $(LNAME2 no-builtin-macro-redefined, no-builtin-macro-redefined)) + + $(P On Posix systems, ImportC will pass the switch $(TT -Wno-builtin-macro-redefined) to the C preprocessor + used by $(TT gcc) and $(TT clang). + This $(LINK2 https://gcc.gnu.org/legacy-ml/gcc-patches/2008-07/msg02321.html, switch) + does not exist in $(TT gcc) preprocessors made before 2008. + The workaround is to run the preprocessor manually.) + + $(H3 $(LNAME2 manual-cpp, Running the Preprocessor Manually)) + + $(P If the C file has a $(TT .i) extension, the file + is presumed to be already preprocessed. + Preprocessing can be run manually: + ) + + $(H4 $(LNAME2 spp,Digital Mars C Preprocessor sppn.exe)) + + $(P $(LINK2 https://www.digitalmars.com/ctg/sc.html, $(TT sppn.exe)) runs on Win32 and is invoked as:) + +$(CONSOLE +sppn file.c) + + $(P and the preprocessed output is written to $(TT file.i).) + + $(H4 $(LNAME2 gcc-preprocessor, Gnu C Preprocessor)) + + $(P The $(LINK2 https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html, Gnu C Preprocessor) can be invoked as:) + +$(CONSOLE +gcc -E file.c > file.i) + + $(H4 $(LNAME2 clang-preprocessor, Clang C Preprocessor)) + + $(P The Clang Preprocessor can be invoked as:) + +$(CONSOLE +clang -E file.c -o file.i) + + $(H4 $(LNAME2 vc-preprocessor, Microsoft VC Preprocessor)) + + $(P The $(LINK2 https://docs.microsoft.com/en-us/cpp/preprocessor/c-cpp-preprocessor-reference?view=msvc-170, + VC Preprocessor) can be invoked as:) + +$(CONSOLE +cl /P /Zc:preprocessor file.c -Fifile.i) + + $(P and the preprocessed output is written to $(TT file.i).) + + $(H4 $(LNAME2 dmpp, dmpp C Preprocessor)) + + $(P The $(LINK2 https://github.com/DigitalMars/dmpp, dmpp C Preprocessor) can be invoked as:) + +$(CONSOLE +dmpp file.c) + + $(P and the preprocessed output is written to $(TT file.i).) + + $(H3 $(LNAME2 defines, Preprocessor Macros)) + + $(P ImportC collects all the $(TT #define) macros from the preprocessor run when it is run automatically. + Some can be made available to D code by interpreting them as declarations. + The variety of macros that can be interpreted as D declarations may be expanded, + but will never encompass all the metaprogramming uses of C macros. + ) + + $(H4 Manifest Constants) + + $(P Macros that look like manifest constants, such as:) + +$(CCODE +#define COLOR 0x123456 +#define HELLO "hello") + + $(P are interpreted as D manifest constant declarations of the form:) + + --- + enum COLOR = 0x123456; + enum HELLO = "hello"; + --- + + $(H4 Function-Like Macros) + + $(P Many macros look like functions, and can be treated as template functions:) + +$(CCODE +#define ABC a + b +#define DEF(a) (a + x)) + + --- + auto ABC() { return a + b; } + auto DEF(T)(T a) { return a + x; } + --- + + $(P Some macro formulations, however, will not produce the same result:) + +$(CCODE +#define ADD(a, b) a + b +int x = ADD(1, 2) * 4; // sets x to 9) + +--- +auto ADD(U, V)(U a, V b) { return a + b; } +int x = ADD(1, 2) * 4; // sets x to 12 +--- + + $(BEST_PRACTICE Always use parentheses around arguments and entire expressions:) + +$(CCODE +#define ADD(a, b) ((a) + (b))) + + $(P Another area of trouble is side effects in the arguments:) + +$(CCODE +#define DOUBLE(x) ((x) + (x))) + +--- +int i = 0; +DOUBLE(i++); +assert(i == 2); // D result will be 1, C result will be 2 +--- + + $(P and treating arguments as references:) + +$(CCODE +#define INC(x) (++x)) + +--- +int i = 0; +INC(i); +assert(i == 1); // D result will be 0, C result will be 1 +--- + +$(H2 $(LNAME2 predefined-macros, Predefined Macros)) + + $(P ImportC does not predefine any macros.) + + $(P To distinguish an ImportC compile vs some other C compiler, use:) + +$(CCODE +#if __IMPORTC__ +) + + $(P $(TT __IMPORTC__) is defined in + $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/importc.h, $(TT src/importc.h)) + which is automatically + included when the preprocessor is run. $(TT importc.h) contains many macro + definitions that are used to adapt various C source code vagaries to ImportC.) + +$(H2 $(LNAME2 preprocessor-directives, Preprocessor Directives)) + + $(P ImportC supports these preprocessor directives:) + + $(H3 $(LNAME2 line-control, Line control)) + + $(P C11 6.10.4) + + $(H3 $(LNAME2 linemarker, Linemarker)) + + $(P $(LINK2 https://gcc.gnu.org/onlinedocs/gcc-11.1.0/cpp/Preprocessor-Output.html, linemarker) + directives are normally embedded in the output of C preprocessors.) + + $(H3 $(LNAME2 pragma, Pragmas)) + + $(P The following pragmas are supported:) + + $(UL + $(LI $(TT #pragma pack ( ))) + $(LI $(TT #pragma pack ( show ))) + $(LI $(TT #pragma pack ( push ))) + $(LI $(TT #pragma pack ( push , identifier ))) + $(LI $(TT #pragma pack ( push , integer ))) + $(LI $(TT #pragma pack ( push , identifier , integer ))) + $(LI $(TT #pragma pack ( pop ))) + $(LI $(TT #pragma pack ( pop PopList ))) + ) + + $(H4 $(LNAME2 pragma-attribute, `#pragma attribute`)) + + The following pragma for ImportC allows to set default storage + classes for function declarations: + --- + #pragma attribute(push, [storage classes...]) + --- + The storage classes `nothrow`, `nogc` and `pure` are supported. + Unrecognized attributes are ignored. + Enabling a default storage class affects all function declarations + after the pragma until it is disabled with another pragma. + Declarations in includes are also affected. The following example + enables `@nogc` and `nothrow` for a library: + + --- + #pragma attribute(push, nogc, nothrow) + #include <somelibrary.h> + --- + + The changed storage classes are pushed on a stack. The last change can + be undone with the following pragma: + --- + #pragma attribute(pop) + --- + This can also disable multiple default storage classes at the same time, + if they were enabled with a single `#pragma attribute(push, ...)` directive. + +$(H2 $(LNAME2 _builtins, $(TT src/__builtins.di))) + + $(P The first thing the compiler does when preprocessing is complete is to import + $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/__builtins.di, $(TT src/__builtins.di)). + It provides support for various builtins provided by other C compilers. + $(TT __builtins.di) is a D file.) + +$(H2 $(LNAME2 implementation, Implementation)) + + $(P The implementation defined characteristics of ImportC are:) + + $(H3 $(LNAME2 enums, Enums)) + + $(P $(I enumeration-constants) are always typed as integers.) + + $(P The expression that defines the value of an $(I enumeration-constant) must + be an integer. if an underlying `int` is specified in the enumeration, + the defining expression must evaluate to a value that fits in an `int`. + if no underlying `int` is specfied, the compiler chooses a large enough + integer type to accomodate the size of the expression.) + + --- + enum E { a = -10, b = 0x81231234 }; // ok + enum F { c = 0x812312345678 }; // ok, c expands to 8 byte to accomodate expression + enum G : int { c = 0x80000000 }; // error, doesn't fit in int + enum G { d = 1.0 }; // error, not integral type + --- + + $(H3 $(LNAME2 bitfields, Bit Fields)) + + $(P There are many implementation defined aspects of C11 bit fields. + ImportC's behavior adjusts to match the behavior of the $(I associated + C compiler) on the target platform. + ) + + $(H3 $(LNAME2 implicit-function-declaration, Implicit Function Declarations)) + + $(P Implicit function declarations:) + +$(CCODE +int main() +{ + func(); // implicit declaration of func() +}) + + $(P were allowed in K+R C and C89, but were invalidated in C99 and C11. Although many + C compilers still support them, ImportC does not. + ) + + $(RATIONALE Implicit function declarations are very error-prone and cause hard + to find bugs.) + + $(H3 $(LNAME2 pragma-STDC-FENV_ACCESS, `#pragma STDC FENV_ACCESS`)) + + $(P This is described in C11 7.6.1) + +$(GRAMMAR_INFORMATIVE +#pragma STDC FENV_ACCESS on-off-switch + +on-off-switch: + ON + OFF + DEFAULT +) + + $(P It is completely ignored.) + + +$(H2 $(LNAME2 limitations, Limitations)) + + $(H3 $(LNAME2 exceptions, Exception Handling)) + + $(P ImportC is assumed to never throw exceptions. `setjmp` and `longjmp` are not supported.) + + $(H3 $(LNAME2 const, Const)) + + $(P C11 specifies that `const` only applies locally. `const` in ImportC applies transitively, + meaning that although:) + + $(CCODE int *const p;) + + $(P means in C11 that `p` is a const pointer to `int`, + in ImportC it means `p` is a `const` pointer to a `const int`.) + + $(H3 $(LNAME2 volatile, Volatile)) + + $(P The `volatile` type-qualifier (C11 6.7.3) is ignored. Use of `volatile` to implement shared + memory access is unlikely to work anyway, $(RELATIVE_LINK2 _atomic, _Atomic) is for that. + To use `volatile` as a device register, call a function to do it that is compiled separately, + or use inline assembler. + ) + + $(H3 $(LNAME2 restrict, Restrict)) + + $(P The `restrict` type-qualifier (C11 6.7.3) is ignored.) + + $(H3 $(LNAME2 _atomic, `_Atomic`)) + + $(P The `_Atomic` type-qualifier (C11 6.7.3) is ignored. + To do atomic operations, use an externally compiled function for that, or the inline assembler.) + + $(H3 $(LNAME2 compatible_types, Compatible Types)) + + $(P $(I Compatible Types) (C11 6.7.2) are identical types in ImportC.) + + +$(H2 $(LNAME2 impedance-mismatch, Impedance Mismatch)) + + $(P While every effort is made to match up C and D so it "just works", the languages have some + fundamental differences that appear now and then. + ) + + $(H3 $(LNAME2 keyword-mismatch, Keyword Mismatch)) + + $(P D and C use mostly the same keywords, C has keywords that D doesn't have, and vice versa. This + does not affect compilation of C code, but it can cause difficulty when accessing C variables and types + from D. For example, the D `version` keyword is not uncommonly used as a struct member in C:) + + $(P C code in file $(TT defs.c):) +$(CCODE +struct S { int version; };) + + $(P Accessing it from D:) + --- + import defs; + int tech(S* s) { + return s.version; // fails because version is a D keyword + } + --- + + $(P A workaround is available:) + --- + import defs; + int tech(S* s) { + return __traits(getMember, *s, "version"); + } + --- + + + + $(H3 $(LNAME2 same_only_different, Same only Different Types)) + + $(P On some platforms, C `long` and `unsigned long` are the same size as `int` and `unsigned int`, respectively. + On other platforms, C `long` and `unsigned long` are the same size as `long long` and `unsigned long long`. + `long double` and `long double _Complex` can be the same size as `double` and `double _Complex`. + In ImportC, these types that are the same size and signed-ness are treated as the same types. + ) + + $(H3 $(LNAME2 _generic, `_Generic`)) + + $(P $(B Generic selection) expressions (C11 6.5.1.1) differ from ImportC. + The types in $(RELATIVE_LINK2 same_only_different, Same only Different Types) are + indistinguishable in the $(I type-name) parts of $(I generic-association). + Instead of giving an error for duplicate types per C11 6.5.1.1-2, ImportC + will select the first compatible $(I type-name) in the $(I generic-assoc-list). + ) + + +$(H2 $(LNAME2 extensions, Extensions)) + + $(H3 $(LNAME2 asmstatements, Asm statement)) + + $(P For the D language, `asm` is a standard keyword, and its construct is + shared with ImportC. For the C language, `asm` is an extension (J.5.10), + and the recommendation is to instead use `__asm__`. All alternative + keywords for `asm` are translated by the druntime file $(TT src/importc.h) + during the preprocessing stage.) + + $(P The `asm` keyword may be used to embed assembler instructions, its + syntax is implementation defined. The Digital Mars D compiler only supports + the dialect of inline assembly as described in the documentation of the + $(LINK2 https://dlang.org/spec/iasm.html, D x86 Inline Assembler).) + + $(P `asm` in a function or variable declaration may be used to specify the + mangle name for a symbol. Its use is analogous to + $(LINK2 https://dlang.org/spec/pragma.html#mangle, pragma mangle).) + +$(CCODE +char **myenviron asm("environ") = 0; + +int myprintf(char *, ...) asm("printf"); +) + + $(P Using `asm` to associate registers with variables is ignored.) + + $(H3 $(LNAME2 forward-references, Forward References)) + + $(P Any declarations in scope can be accessed, not just + declarations that lexically precede a reference.) + +$(CCODE +Ta *p; // Ta is forward referenced +struct Sa { int x; }; +typedef struct Sa Ta; // Ta is defined +) + +$(CCODE +struct S s; +int* p = &s.t.x; // struct S definition is forward referenced +struct S { int a; struct T t; }; // T still forward referenced +struct T { int b; int x; }; // definition of struct T +) + + $(H3 $(LNAME2 cpp-tag-symbols, C++ Style Tag Symbols)) + + $(P In C++, `struct`, `union` or `enum` tag symbols can be accessed without needing + to be prefixed with the `struct`, `union` or `enum` keywords, as long + as there is no other declaration with the same name at the same scope. + ImportC behaves the same way.) + + $(P For example, the following code is accepted by both C++ and ImportC:) + +$(CCODE +struct s { int a; }; + +void g(int s) +{ + struct s* p = (struct s*)malloc(sizeof(struct s)); + p->a = s; +} +) + + $(P Whereas this is rejected by both C++ and ImportC, for the same reason.) + +$(CCODE +struct s { int a; }; + +void g(int s) +{ + s* p = (s*)malloc(sizeof(s)); + p->a = s; +} +) + + $(H3 $(LNAME2 ctfe, Compile Time Function Execution)) + + $(P Evaluating constant expressions includes executing functions in the + same manner as D's CTFE can. + A $(I constant-expression) invokes CTFE.) + + $(P Examples:) + +$(CCODE +_Static_assert("\x1"[0] == 1, "failed"); + +int mint1() { return -1; } +_Static_assert(mint1() == -1, "failed"); + +const int a = 7; +int b = a; // sets b to 7 +) + + $(H3 $(LNAME2 inlining, Function Inlining)) + + $(P Functions for which the function body is present can + be inlined by ImportC as well as by the D code that calls them.) + + $(H3 $(LNAME2 enumbasetype, Enum Base Types)) + + $(P Enums are extended with an optional $(I EnumBaseType):) + +$(GRAMMAR +$(GNAME EnumDeclaration): + $(D enum) $(GLINK Identifier) $(D :) $(GLINK EnumBaseType) $(GLINK EnumBody) + +$(GNAME EnumBaseType): + $(GLINK Type) +) + + $(P which, when supplied, causes the enum members to be implicitly cast to the + $(I EnumBaseType). + ) + +$(CCODE +enum S : byte { A }; +_Static_assert(sizeof(A) == 1, "A should be size 1"); +) + + + $(H3 $(LNAME2 register, Register Storage Class)) + + $(P Objects with `register` storage class are treated as `auto` declarations.) + + $(P Objects with `register` storage class may have their address taken. C11 6.3.2.1-2) + + $(P Arrays can have `register` storage class, and may be enregistered by the compiler. C11 6.3.2.1-3) + + + $(H3 $(LNAME2 typeof, `typeof` Operator)) + + $(P The `typeof` operator may be used as a type specifier:) +$(GRAMMAR_INFORMATIVE +$(GNAME type-specifier): + $(GNAME typeof-specifier) + +$(GNAME typeof-specifier): + $(D typeof $(LPAREN)) $(GNAME expression) $(D $(RPAREN)) + $(D typeof $(LPAREN)) $(GNAME type-name) $(D $(RPAREN)) +) + + $(H3 $(LNAME2 __import, Import Declarations)) + + $(P Modules can be imported with a $(I CImportDeclaration):) + +$(GRAMMAR_INFORMATIVE +$(GNAME CImportDeclaration): + $(D __import) $(GLINK2 module, ImportList) $(D ;) +) + + $(P Imports enable ImportC code to directly access D declarations and functions + without the necessity of creating a $(TT .h) file representing those declarations. + The tedium and brittleness of keeping the $(TT .h) file up-to-date with the D + declarations is eliminated. + D functions are available to be inlined. + ) + + $(P Imports also enable ImportC code to directly import other C files without + needing to create a `.h` file for them, either. + Imported C functions become available to be inlined. + ) + + $(P The $(I ImportList) works the same as it does for D.) + + $(P The ordering of $(I CImportDeclaration)s has no significance.) + + $(P An ImportC file can be imported, the name of the C file to be + imported is derived from the module name.) + + $(P All the global symbols in the ImportC file become available to the + importing module.) + + $(P If a name is referred to in the importing file is not found, + the global symbols in each imported file are searched for the name. + If it is found in exactly one module, that becomes the resolution of the + name. If it is found in multiple modules, it is an error.) + + $(NOTE Since ImportC has no scope resolution operator, only global symbols + can be found, and a qualification cannot be added to specifiy which module + a symbols is in.) + + $(P Preprocessor symbols in the imported module are not available to the + importing module, and preprocessing symbols in the importing file are not + available to the imported module.) + + $(P A D module can be imported, in the same manner as that + of a $(GLINK2 module, ImportDeclaration).) + + $(P Imports can be circular.) + +$(CCODE +__import core.stdc.stdarg; // get D declaration of va_list +__import mycode; // import mycode.c + +int foo() +{ + va_list x; // picks up va_list from core.stdc.stdarg + return 1 + A; // returns 4 +}) + + $(P $(TT mycode.c) looks like:) + +$(CCODE +enum E { A = 3; } +) + + $(BEST_PRACTICE Avoid using preprocessor $(TT #define)s like $(TT #define A 3). + Use the enum form shown in the above example. + Prefer $(TT const) declarations over $(TT #define)s. + Rewrite function-style preprocessor macros as inline functions. + ) + + $(H3 $(LNAME2 controlZ, Control Z is End Of File)) + + $(P A control-Z character `\x1A` in the source text means End Of File.) + + $(H3 $(LNAME2 largeDecimal, Signed Integer Literal Larger Than `long long`)) + + $(P A signed integer constant with no suffix that is larger than a `long long` type, + but will fit into an `unsigned long long` type, is accepted and typed as `unsigned long long`. + This matches D behavior, and that of some C compilers.) + + $(H3 $(LNAME2 dotArrow, Dot and Arrow Operators)) + + $(P The `.` operator is used to designate a member of a struct or union value. + The `->` operator is used to designate a member of a struct or union value pointed to + by a pointer. The extension is that `.` and `->` can be used interchangeably on + values and pointers. This matches D's behavior for `.`.) + +$(H2 $(LNAME2 gnu-clang-extensions, Gnu and Clang Extensions)) + + $(P `gcc` and `clang` are presumed to have the same behavior w.r.t. extensions, + so `gcc` as used here refers to both.) + + + $(H3 $(LNAME2 __attribute__, `__attribute__` Extensions)) + + $(P The following $(LINK2 https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html, `__attribute__` extensions):) + + $(OL + $(LI `__attribute__((aligned(N)))`) + $(LI `__attribute__((always_inline))`) + $(LI `__attribute__((deprecated))`) + $(LI `__attribute__((dllexport))`) + $(LI `__attribute__((dllimport))`) + $(LI `__attribute__((naked))`) + $(LI `__attribute__((noinline))`) + $(LI $(RELATIVE_LINK2 noreturn, `__attribute__((noreturn))`)) + $(LI `__attribute__((nothrow))`) + $(LI `__attribute__((pure))`) + $(LI `__attribute__((vector_size(N)))`) + $(LI others are ignored) + ) + + $(H3 $(LNAME2 noreturn, `__attribute__((noreturn))`)) + + $(P `__attribute__((noreturn))` marks a function as never returning. + `gcc` set this as an attribute of the function, it is + not part of the function's type. In D, a function that never returns + has the return type $(GLINK2 type, noreturn). The difference can be + seen with the code:) + +$(CCODE +attribute((noreturn)) int foo(); +size_t x = sizeof(foo());) + + $(P This code is accepted by `gcc`, but makes no sense for D. Hence, + although it works in ImportC, it is not representable as D code, + meaning one must use judgement in creating a `.di` file to interface + with C `noreturn` functions.) + + $(P Furthermore, the D compiler takes advantage of `noreturn` functions + by issuing compile time errors for unreachable code. Such unreachable + code, however, is valid C11, and the ImportC compiler will accept it.) + + $(BEST_PRACTICE C code that uses the `noreturn` attribute should at the + very least set the return type to `void`.) + + +$(H2 $(LNAME2 visualc-extensions, Visual C Extensions)) + + $(P All the $(RELATIVE_LINK2 digital-mars-extensions, Digital Mars C Extensions).) + + $(H3 $(LNAME2 __stdcall, `__stdcall` Function Calling Convention)) + + $(P `__stdcall` sets the calling convention for a function to the Windows API calling convention.) + + --- + int __stdcall foo(int x); + --- + + $(H3 $(LNAME2 __declspec, `__declspec` Attribute Extensions)) + + $(P The following $(LINK2 https://learn.microsoft.com/en-us/cpp/cpp/declspec?view=msvc-170, `__declspec` extensions):) + + $(OL + $(LI `__declspec()`) + $(LI `__declspec(align(N))`) + $(LI `__declspec(deprecated)`) + $(LI `__declspec(dllexport)`) + $(LI `__declspec(dllimport)`) + $(LI `__declspec(naked)`) + $(LI `__declspec(noinline)`) + $(LI `__declspec(noreturn)`) + $(LI `__declspec(nothrow)`) + $(LI `__declspec(thread)`) + $(LI others are ignored) + ) + + $(H3 $(LNAME2 __pragma, `__pragma` Attribute Extensions)) + + $(P The following + $(LINK2 https://learn.microsoft.com/en-us/cpp/preprocessor/pragma-directives-and-the-pragma-keyword?view=msvc-170, `__pragma` extensions):) + + $(OL + $(LI `__pragma(pack(N))`) + $(LI others are ignored) + ) + +$(H2 $(LNAME2 digital-mars-extensions, Digital Mars C Extensions)) + + $(H3 $(LNAME2 __stdcall, `__stdcall` Function Calling Convention)) + + $(H3 $(LNAME2 __declspec, `__declspec` Attribute Extensions)) + + $(P The following $(LINK2 https://digitalmars.com/ctg/ctgLanguageImplementation.html#declspec, `__declspec` extensions):) + + $(OL + $(LI `__declspec(dllexport)`) + $(LI `__declspec(dllimport)`) + $(LI `__declspec(naked)`) + $(LI `__declspec(thread)`) + ) + + +$(H2 $(LNAME2 d-side, ImportC from D's Point of View)) + + $(P There is no one-to-one mapping of C constructs to D constructs, although + it is very close. What follows is a description of how the D side views + the C declarations that are imported.) + + $(H3 $(LNAME2 module-name, Module Name)) + + $(P The module name assigned to the ImportC file is the filename stripped + of its path and extension. This is just like the default module name assigned + to a D module that does not have a module declaration.) + + $(H3 $(LNAME2 extern-C, `extern (C)`)) + + $(P All C symbols are `extern (C)`.) + + $(H3 $(LNAME2 enums, Enums)) + + $(P The C enum:) + + $(CCODE enum E { A, B = 2 };) + + $(P appears to D code as:) + + --- + enum E : int { A, B = 2 } + alias A = E.A; + alias B = E.B; + --- + + $(P The `.min` and `.max` properties are available:) + + --- + static assert(E.min == 0 && E.max == 2); + --- + + $(H3 $(LNAME2 tag-symbols, Tag Symbols)) + + $(P Tag symbols are the identifiers that appear after the `struct`, `union`, and `enum` + keywords, (C11 6.7.2.3). In C, they are placed in a different symbol table from other + identifiers. This means two different symbols can use the same name:) + +$(CCODE +int S; +struct S { int a, b; }; +S = 3; +struct S *ps;) + + $(P D does not make this distinction. Given a tag symbol that is the only declaration of an + identifier, that's what the D compiler recognizes. Given a tag symbol and a non-tag symbol + that share an identifier, the D compiler recognizes the non-tag symbol. This is normally + not a problem due to the common C practice of applying `typedef`, as in:) + +$(CCODE +typedef struct S { int a, b; } S;) + + $(P The D compiler recognizes the `typedef` applied to `S`, and the code compiles as expected. But when `typedef` is absent, as in:) + +$(CCODE +int S; +struct S { int a, b; };) + + $(P The most pragmatic workaround is to add a `typedef` to the C code:) + +$(CCODE +int S; +struct S { int a, b; }; +typedef struct S S_t; // add this typedef) + + $(P Then the D compiler can access the struct tag symbol via `S_t`.) + + +$(H2 $(LNAME2 wrapping, Wrapping C Code)) + + $(P Many difficulties with adapting C code to ImportC can be done without + editing the C code itself. Wrap the C code in another C file and then + `#include` it. Consider the following problematic C file $(TT file.c):) + +$(CCODE +void func(int *__restrict p); +int S; +struct S { int a, b; };) + + $(P The problems are that `__restrict` is not a type qualifier recognized by ImportC + (or C11), + and the struct `S` is hidden from D by the declaration `int S;`. + To wrap $(TT file.c) with a fix, create the file $(TT file_ic.c) with the contents:) + +$(CCODE +#define __restrict restrict +#include "file.c" +typedef struct S S_t;) + + $(P Then, `import file_ic;` instead of `import file;`, and use `S_t` when `struct S` is desired.) + +$(H2 $(LNAME2 ctod, Converting C Code to D Code)) + + $(P Sometimes its desirable to go further than importing C code, to actually do a C source to + D source conversion. Reasons include:) + + $(UL + $(LI Migrating a C project to a D project.) + $(LI Equivalent D code can compile much faster, due to not needing a preprocessor, etc.) + $(LI Tweaking the D code to add attributes for memory safety, purity, etc.) + $(LI Eliminating the need for C-isms in the D part of the project.) + ) + + $(P This can be done with the D compiler by using the $(TT -Hf) switch:) + +$(CONSOLE +dmd -c mycode.c -Hf=mycode.di) + + $(P which will convert the C source code in $(TT mycode.c) to D source code in $(TT mycode.di). + If the $(TT -inline) switch is also used, it will emit the C function bodies as well, instead + of just the function prototypes.) + +$(H3 Impedance Mismatch) + + $(P A precise mapping of C semantics, with all its oddities, to D source code is not + always practical. ImportC uses C semantics in its semantic analysis to get much closer + to exact C semantics than is expressible in D source code. Hence, the translation to + D source code will be less than perfect. For example:) + +$(CCODE +int S; +struct S { int a, b; }; +int foo(struct S s) +{ + return S + s.a; +}) + + $(P will work fine in ImportC, because the `int S` and the `struct S` are in different + symbol tables. But in the generated D code, both symbols would be in the same symbol table, and will collide. + Such D source code translated from C will need to be adjusted by the user.) + + $(P Nevertheless, reports from the field are that this conversion capability is a huge + timesaver for users who need to deal with existing C code.) + +$(H2 $(LNAME2 warnings, Warnings)) + + $(P Many suspicious C constructs normally cause warnings to be emitted by default by + typical compilers, such as:) + + $(CCODE int *p = 3; // Warning: integer implicitly converted to pointer) + + $(P ImportC does not emit warnings. The presumption is the user will be importing existing C + code developed using another C compiler, and it is written as intended. + If C11 says it is legal, ImportC accepts it.) + + +$(H2 $(LNAME2 importcpp, ImportC++)) + + $(P ImportC will not compile C++ code. For that, use $(TT dpp).) + + +$(H2 $(LNAME2 other-solutions, Other Solutions)) + + $(H3 $(LNAME2 dpp, dpp by Atila Neves)) + + $(P $(LINK2 https://code.dlang.org/packages/dpp/0.2.1, dpp code)) + + $(P $(LINK2 https://dlang.org/blog/2019/04/08/project-highlight-dpp/, dpp Article)) + + $(P From the Article:) + + $(BLOCKQUOTE dpp is a compiler wrapper that will parse a D source + file with the `.dpp` extension and expand in place any `#include` directives + it encounters, translating all of the C or C++ symbols to D, and then + pass the result to a D compiler (DMD by default).) + + $(P Like DStep, dpp relies on libclang.) + + + $(H3 $(LNAME2 dstep, DStep by Jacob Carlborg)) + + $(P $(LINK2 https://code.dlang.org/packages/dstep, DStep code)) + + $(P $(LINK2 https://dlang.org/blog/2019/04/22/dstep-1-0-0/, DStep Article)) + + $(P From the Article:) + + $(BLOCKQUOTE DStep is a tool for automatically generating D + bindings for C and Objective-C libraries. This is implemented by + processing C or Objective-C header files and outputting D modules. + DStep uses the Clang compiler as a library (libclang) to process the header files.) + + + $(H3 $(LNAME2 htod, htod by Walter Bright)) + + $(P $(LINK2 https://dlang.org/htod.html, htod) converts a C $(TT .h) file + to a D source file, suitable for importing into D code. + $(B htod) is built from the front end of the Digital Mars C and C++ compiler. + It works just like a C or C++ compiler except that its output is source + code for a D module rather than object code.) + + +$(H2 $(LNAME2 internals, How ImportC Works)) + + $(P ImportC's implementation is based on the idea that D's semantics are very similar + to C's. ImportC gets its own parser, which converts the C syntax into the same AST + (Abstract Syntax Tree) that D uses. The lexer for ImportC is the same as for D, but with + some modifications here and there, such as the keywords and integer literals being different. + Where the semantics of C differ from D, there are adjustments in the semantic analysis + code in the D compiler.) + + $(P This co-opting of the D semantic implementation allows ImportC to be able to do things + like handle forward references, CTFE (Compile Time Function Execution), and inlining of C functions + into D code. Being able to handle forward references means it is not necessary to even + write a `.h` file to be able to import C declarations into D. Being able to perform CTFE is + very handy for testing that ImportC is working without needing to generate an executable. + But, in general, the strong temptation to add D features to ImportC has been resisted.) + + $(P The optimizer and code generator are, of course, the same as D uses.) + +$(SPEC_SUBNAV_PREV_NEXT betterc, Better C, ob, Live Functions) +) + +Macros: + CHAPTER=42 + TITLE=ImportC diff --git a/spec/interface.dd b/spec/interface.dd new file mode 100644 index 0000000000..e48c67136b --- /dev/null +++ b/spec/interface.dd @@ -0,0 +1,364 @@ +Ddoc + +$(SPEC_S Interfaces, + +$(HEADERNAV_TOC) + +$(H2 $(LNAME2 declarations, Interface Declarations)) + + $(P An $(I Interface) describes a list of functions that a class which inherits + from the interface must implement.) + +$(GRAMMAR +$(GNAME InterfaceDeclaration): + $(D interface) $(GLINK_LEX Identifier) $(D ;) + $(D interface) $(GLINK_LEX Identifier) $(GLINK BaseInterfaceList)$(OPT) $(GLINK2 struct, AggregateBody) + $(GLINK2 template, InterfaceTemplateDeclaration) + +$(GNAME BaseInterfaceList): + $(D :) $(GLINK2 class, Interfaces) +) + + $(IMPLEMENTATION_DEFINED $(P Specialized interfaces may be supported:) + + $(OL + $(LI $(RELATIVE_LINK2 com-interfaces, $(I COM Interfaces)) + are binary compatible with COM/OLE/ActiveX objects for Windows. + ) + + $(LI $(RELATIVE_LINK2 cpp-interfaces, $(I C++ Interfaces)) + are binary compatible with C++ abstract classes. + ) + + $(LI [Objective-C Interfaces](objc_interface.html#protocols) + are binary compatible with Objective-C protocols. + ) + ) + ) + + + $(P A class that implements an interface can be implicitly converted to a reference + to that interface.) + + $(P Interfaces cannot derive from classes; only from other interfaces. + Classes cannot derive from an interface multiple times. + ) + +------ +interface I +{ + void foo(); +} + +class A : I, I // error, duplicate interface +{ +} +------ + +$(P An instance of an interface cannot be created.) + +------ +interface I +{ + void foo(); +} + +... + +I iface = new I(); // error, cannot create instance of interface +------ + +$(H3 $(LNAME2 method-bodies, Interface Method Bodies)) + + $(P Virtual interface member functions do not have implementations. + Interfaces are expected to implement static or final functions. + ) + +------ +interface I +{ + void bar() { } // error, implementation not allowed + static void foo() { } // ok + final void abc() { } // ok +} +------ + + $(P Interfaces can have function templates in the members. + All instantiated functions are implicitly `final`. + ) + +--- +interface I +{ + void foo(T)() { } // ok, it's implicitly final +} +--- + + $(P Classes that inherit from an interface may not override final or + static interface member functions.) + +------ +interface I +{ + void bar(); + static void foo() { } + final void abc() { } +} + +class C : I +{ + void bar() { } // ok + void foo() { } // error, cannot override static I.foo() + void abc() { } // error, cannot override final I.abc() +} +------ + +$(H3 $(LNAME2 implementing-interfaces, Implementing Interfaces)) + + $(P All virtual interface functions must be defined in a class that inherits + from that interface: + ) +------ +interface I +{ + void foo(); +} + +class A : I +{ + void foo() { } // ok, provides implementation +} + +class B : I +{ + int foo() { } // error, no `void foo()` implementation +} +------ + +$(P Interfaces can be inherited from a base class, and interface functions overridden:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------ +interface I +{ + int foo(); +} + +class A : I +{ + int foo() { return 1; } +} + +class B : A +{ + override int foo() { return 2; } +} + +B b = new B(); +assert(b.foo() == 2); + +I i = b; // ok since B inherits A's I implementation +assert(i.foo() == 2); +------ +) + +$(H4 $(LNAME2 reimplementing-interfaces, Reimplementing Interfaces)) + + $(P Interfaces can be reimplemented in derived classes:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------ +interface I +{ + int foo(); +} + +class A : I +{ + int foo() { return 1; } +} + +class B : A, I +{ + override int foo() { return 2; } +} + +B b = new B(); +assert(b.foo() == 2); +I i = b; +assert(i.foo() == 2); + +A a = b; +I i2 = a; +assert(i2.foo() == 2); // i2 has A's virtual pointer for foo which points to B.foo +------ +) + + $(P A reimplemented interface must implement all the interface + functions, it does not inherit them from a super class: + ) + +------ +interface I +{ + int foo(); +} + +class A : I +{ + int foo() { return 1; } +} + +class B : A, I +{ +} // error, no foo() for interface I +------ + +$(SECTION3 $(LEGACY_LNAME2 InterfaceContracts, interface-contracts, Interface Method Contracts), + + $(P Interface member functions can have contracts even though there + is no body for the function. The contracts are inherited by any + class member function that implements that interface member function. + ) + +--- +interface I +{ + int foo(int i) + in { assert(i > 7); } + out (result) { assert(result & 1); } + + void bar(); +} +--- +) + +$(SECTION3 $(LEGACY_LNAME2 ConstInterface, const-interface, Const and Immutable Interfaces), + $(P If an interface has $(CODE const) or $(CODE immutable) storage + class, then all members of the interface are + $(CODE const) or $(CODE immutable). + This storage class is not inherited. + ) +) + + +$(SECTION2 $(LEGACY_LNAME2 COM-Interfaces, com-interfaces, COM Interfaces), + + $(P A variant on interfaces is the COM interface. A COM interface is + designed to map directly onto a Windows COM object. Any COM object + can be represented by a COM interface, and any D object with + a COM interface can be used by external COM clients. + ) + + $(P A COM interface is defined as one that derives from the interface + $(D core.sys.win)$(SHY)$(D dows.com.IUnknown). A COM interface differs from + a regular D interface in that: + ) + + $(UL + $(LI It derives from the interface $(D core.sys.windows.com.IUnknown).) + $(LI It cannot be the argument to $(REF1 destroy, object).) + $(LI References cannot be upcast to the enclosing class object, nor + can they be downcast to a derived interface. + Implement $(D QueryInterface()) + for that interface in standard COM fashion to convert to another COM interface.) + $(LI Classes derived from COM interfaces are COM classes.) + $(LI The default linkage for member functions of COM classes + is $(D extern(System)). + + $(NOTE To implement or override any base-class methods of + D interfaces or classes (ones which do not inherit from $(D IUnknown)), + explicitly mark them as having the $(D extern(D)) linkage.) + + --- + import core.sys.windows.windows; + import core.sys.windows.com; + + interface IText + { + void write(); + } + + abstract class Printer : IText + { + void print() { } + } + + class C : Printer, IUnknown + { + // Implements the IText `write` class method. + extern(D) void write() { } + + // Overrides the Printer `print` class method. + extern(D) override void print() { } + + // Overrides the Object base class `toString` method. + extern(D) override string toString() { return "Class C"; } + + // Methods of class implementing the IUnknown interface have + // the extern(System) calling convention by default. + HRESULT QueryInterface(const(IID)*, void**); + uint AddRef(); + uint Release(); + } + --- + + $(P The same applies to other $(D Object) methods such as $(D opCmp), $(D toHash), etc.) + + ) + $(LI The first member of the COM $(D vtbl[]) is not the pointer + to the InterfaceInfo, but the first virtual function pointer.) + ) + + $(P See also + $(LINK2 http://www.lunesu.com/uploads/ModernCOMProgramminginD.pdf, Modern COM Programming in D) + ) + +) + +$(SECTION2 $(LEGACY_LNAME2 CPP-Interfaces, cpp-interfaces, C++ Interfaces), + + $(P C++ interfaces are interfaces declared with C++ linkage: + ) + +--- +extern (C++) interface Ifoo +{ + void foo(); + void bar(); +} +--- + +which is meant to correspond with the following C++ declaration: + +$(CPPLISTING +class Ifoo +{ + virtual void foo(); + virtual void bar(); +}; +) + + $(P Any interface that derives from a C++ interface is also + a C++ interface. + A C++ interface differs from a D interface in that: + ) + + $(UL + $(LI It cannot be the argument to $(REF1 destroy, object).) + $(LI References cannot be upcast to the enclosing class object, nor + can they be downcast to a derived interface.) + $(LI The C++ calling convention is the default convention + for its member functions, rather than the D calling convention.) + $(LI The first member of the $(D vtbl[]) is not the pointer + to the $(D Interface), but the first virtual function pointer.) + ) +) + + +$(SPEC_SUBNAV_PREV_NEXT class, Classes, enum, Enums) +) + +Macros: + CHAPTER=17 + TITLE=Interfaces diff --git a/spec/interfaceToC.dd b/spec/interfaceToC.dd new file mode 100644 index 0000000000..f8030726ce --- /dev/null +++ b/spec/interfaceToC.dd @@ -0,0 +1,426 @@ +Ddoc + +$(SPEC_S Interfacing to C, + +$(HEADERNAV_TOC) + + $(P D is designed to fit comfortably with a C compiler for the target + system. It is able to call C functions directly without requiring + wrapper functions. + ) + + $(P This is done by matching the C compiler's data types, layouts, + and function call/return sequences. + ) + + $(P The $(DDLINK spec/importc, ImportC, ImportC) compiler extension allows + importing or compiling `.c` files directly. ) + + $(P Bindings for popular C libraries can be found in the + $(LINK2 https://dlang.org/phobos/index.html, standard library) and + $(LINK2 https://code.dlang.org/?sort=updated&limit=20&category=library.binding, package repository).) + + $(P The rest of this page describes the manual, low-level side of interfacing with C.) + +$(H2 $(LNAME2 calling_c_functions, Calling C Functions)) + + $(P C functions can be called directly from D. There is no need for + wrapper functions, argument swizzling, and the C functions do not + need to be put into a separate DLL. + ) + + $(P The C function must be declared and given a calling convention, + most likely the "C" calling convention, for example: + ) + +------ +extern (C) int strcmp(const char* string1, const char* string2); +------ + + and then it can be called within D code in the obvious way: + +------ +import std.string; +int myDfunction(char[] s) +{ + return strcmp(std.string.toStringz(s), "foo"); +} +------ + + $(P There are several things going on here:) + + $(UL + $(LI D understands how C function names are "mangled" and the + correct C function call/return sequence.) + + $(LI C functions cannot be overloaded with another C function + with the same name.) + + $(LI There are no $(D __cdecl), $(D __far), $(D __stdcall), + $(LINK2 + http://www.digitalmars.com/ctg/ctgLanguageImplementation.html#declspec, + $(D __declspec)), + or other such C + $(LINK2 http://www.digitalmars.com/ctg/ctgLanguageImplementation.html#extended, extended type modifiers) + in D. These are handled by + $(LINK2 attribute.html#linkage, linkage attributes), + such as $(D extern (C)).) + + $(LI There is no volatile type modifier in D. To declare a C function that uses + volatile, just drop the keyword from the declaration.) + + $(LI Strings are not 0 terminated in D. See "Data Type Compatibility" + for more information about this. However, string literals in D are + 0 terminated.) + + ) + + $(P C code can correspondingly call D functions, if the D functions + use an attribute that is compatible with the C compiler, most likely + the extern (C):) + +------ +// myfunc() can be called from any C function +extern (C) +{ + void myfunc(int a, int b) + { + ... + } +} +------ + +$(H2 $(LNAME2 storage_allocation, Storage Allocation)) + + $(P C code explicitly manages memory with calls to + $(LINK2 http://www.digitalmars.com/rtl/stdlib.html#malloc, malloc()) and + $(LINK2 http://www.digitalmars.com/rtl/stdlib.html#free, free()). + D allocates memory using the D garbage collector, + so no explicit frees are necessary. + ) + + $(P D can still explicitly allocate memory using core.stdc.stdlib.malloc() + and core.stdc.stdlib.free(), these are useful for connecting to C + functions that expect malloc'd buffers, etc. + ) + + $(P If pointers to D garbage collector allocated memory are passed to + C functions, it's critical to ensure that the memory will not be + collected by the garbage collector before the C function is done with + it. This is accomplished by: + ) + + $(UL + + $(LI Making a copy of the data using core.stdc.stdlib.malloc() and passing + the copy instead.) + + $(LI Leaving a pointer to it on the stack (as a parameter or + automatic variable), as the garbage collector will scan the stack.) + + $(LI Leaving a pointer to it in the static data segment, as the + garbage collector will scan the static data segment.) + + $(LI Registering the pointer with the garbage collector with the + + $(DPLLINK phobos/core_memory.html#addRoot, std.gc.addRoot()) + or + + $(DPLLINK phobos/core_memory.html#addRange, std.gc.addRange()) + calls.) + + ) + + $(P An interior pointer to the allocated memory block is sufficient + to let the GC + know the object is in use; i.e. it is not necessary to maintain + a pointer to the beginning of the allocated memory. + ) + + $(P The garbage collector does not scan the stacks of threads not + created by the D Thread interface. Nor does it scan the data + segments of other DLLs, etc. + ) + +$(H2 $(LNAME2 data_type_compat, Data Type Compatibility)) + + $(TABLE2 D And C Type Equivalence, + $(ELABORATE_HEADER) + $(TROW2 void, void) + $(TROW2 byte, signed char) + $(TROW2 ubyte, unsigned char) + $(TROW2 char, char, (chars are unsigned in D)) + $(TROW2 wchar, wchar_t, (when $(D sizeof(wchar_t)) is 2)) + $(TROW2 dchar, wchar_t, (when $(D sizeof(wchar_t)) is 4)) + $(TROW2 short, short) + $(TROW2 ushort, unsigned short) + $(TROW2 int, int) + $(TROW2 uint, unsigned) + + $(TROW3 core.stdc.config.c_long, long, long) + $(TROW3 core.stdc.config.c_ulong, unsigned long, unsigned long) + $(TROW3 core.stdc.stdint.intptr_t, intptr_t, intptr_t) + $(TROW3 core.stdc.stdint.uintptr_t, uintptr_t, uintptr_t) + + $(TROW3PLUS long, long long, long, (or $(D long long))) + $(TROW3PLUS ulong, unsigned long long, unsigned long, (or $(D unsigned long long))) + + $(TROW2 float, float) + $(TROW2 double, double) + $(TROW2 real, long double) + + $(TROW2 cdouble, double _Complex) + $(TROW2 creal, long double _Complex) + $(TROW2 struct, struct) + $(TROW2 union, union) + $(TROW2 enum, enum) + $(TROW2 class, ,no equivalent) + $(TROW2 type *, type *) + $(TROW2 type[dim], type[dim]) + $(TROW2 type[dim]*, type(*)[dim]) + $(TROW2 type[], ,no equivalent) + $(TROW2 type1[type2], , no equivalent) + $(TROW2 type function(params), type(*)(params)) + $(TROW2 type delegate(params), , no equivalent) + $(TROW2 size_t, size_t) + $(TROW2 ptrdiff_t, ptrdiff_t) + ) + + $(P These equivalents hold for most C compilers. The C standard + does not pin down the sizes of the types, so some care is needed. + ) + +$(H2 $(LNAME2 passing_d_array, Passing D Array Arguments to C Functions)) + + $(P In C, arrays are passed to functions as pointers even if the function + prototype says its an array. In D, static arrays are passed by value, + not by reference. Thus, the function prototype must be adjusted to match + what C expects.) + + $(TABLE2 D And C Function Prototype Equivalence, + $(THEAD D type, C type) + $(TROW $(I T)$(B *) , $(I T)$(B [])) + $(TROW $(B ref) $(I T)$(B [)$(I dim)$(B ]) , $(I T)$(B [)$(I dim)$(B ]))) + + $(P For example:) + +$(CCODE void foo(int a[3]) { ... } // C code) +--- +extern (C) +{ + void foo(ref int[3] a); // D prototype +} +--- + + +$(H2 $(LNAME2 calling_printf, Calling `printf()`)) + + $(P `printf` can be directly called from D code:) +--- +import core.stdc.stdio; + +int main() +{ + printf("hello world\n"); + return 0; +} +--- + + $(P Printing values works as it does in C:) +--- +int apples; +printf("there are %d apples\n", apples); +--- + $(P Correctly matching the format specifier to the D type is necessary. + The D compiler recognizes the printf formats and diagnoses mismatches + with the supplied arguments. The specification for the formats + used by D is the C99 specification 7.19.6.1. + ) + + $(P A generous interpretation of what is a match between the argument + and format specifier is taken, for example, an unsigned type can + be printed with a signed format specifier. Diagnosed incompatibilites + are: + ) + + $(UL + $(LI incompatible sizes which may cause argument misalignment) + $(LI dereferencing arguments that are not pointers) + $(LI insufficient number of arguments) + $(LI struct, array and slice arguments are not allowed) + $(LI non-pointer arguments to `s` specifier) + $(LI non-Standard formats) + $(LI undefined behavior per C99) + ) + +$(H3 Strings) + + $(P A string cannot be printed directly. But `%.*s` can be used: + ) +--- +string s = "betty"; +printf("hello %.*s\n", cast(int) s.length, s.ptr); +--- + $(P The cast to `int` is required. + ) + +$(H3 `size_t` and `ptrdiff_t`) + + $(P These use the `zu` and `td` format specifiers respectively: + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +import core.stdc.stdio : printf; +int* p = new int, q = new int; +printf("size of an int is %zu, pointer difference is %td\n", int.sizeof, p - q); +--- +) + +$(H3 Non-Standard Format Specifiers) + + $(P Non-Standard format specifiers will be rejected by the compiler. + Since the checking is only done for formats as string literals, + non-Standard ones can be used: + ) +--- +const char* format = "value: %K\n"; +printf(format, value); +--- + +$(H3 Modern Formatted Writing) + + $(P An improved D function for formatted output is + $(CODE std.stdio.writef()). + ) + +$(H2 $(LNAME2 structs_and_unions, Structs and Unions)) + + $(P D structs and unions are analogous to C's. + ) + + $(P C code often adjusts the alignment and packing of struct members + with a command line switch or with various implementation specific + $(HASH)pragmas. D supports explicit alignment attributes that correspond + to the C compiler's rules. Check what alignment the C code is using, + and explicitly set it for the D struct declaration. + ) + + $(P D does not support bit fields. If needed, they can be emulated + with shift and mask operations, + or use the $(LINK2 $(ROOT_DIR)phobos/std_bitmanip.html#bitfields, std.bitmanip.bitfields) + library type. + $(DPLLINK htod.html, htod) will convert bit fields to inline + functions that + do the right shift and masks. + ) + + $(P D does not support declaring variables of anonymous struct types. In such a case, define a named struct in D and make it private:) + +$(CCODE +union Info // C code +{ + struct + { + char *name; + } file; +}; +) +--- +union Info // D code +{ + private struct File + { + char* name; + } + File file; +} +--- + +$(H2 $(LNAME2 callbacks, Callbacks)) + + $(P D can easily call C callbacks (function pointers), and C can call + callbacks provided by D code if the callback is an $(D extern(C)) function, + or some other linkage that both sides have agreed to (e.g. $(D extern(Windows))).) + + $(P Here's an example of C code providing a callback to D code:) + +$(CCODE +void someFunc(void *arg) { printf("Called someFunc!\n"); } // C code +typedef void (*Callback)(void *); +extern "C" Callback getCallback(void) +{ + return someFunc; +} +) + +--- +extern(C) alias Callback = int function(int, int); // D code +extern(C) Callback getCallback(); +void main() +{ + Callback cb = getCallback(); + cb(); // invokes the callback +} +--- + + $(P And an example of D code providing a callback to C code:) + +$(CCODE +extern "C" void printer(int (*callback)(int, int)) // C code +{ + printf("calling callback with 2 and 4 returns: %d\n", callback(2, 4)); +} +) + +--- +extern(C) alias Callback = int function(int, int); // D code +extern(C) void printer(Callback callback); +extern(C) int sum(int x, int y) { return x + y; } +void main() +{ + printer(&sum); +} +--- + + $(P For more info about callbacks read the $(LINK2 function.html#closures, closures) section.) + +$(H2 $(LEGACY_LNAME2 Using C Libraries, using-c-libraries, Using Existing C Libraries)) + + $(P Since D can call C code directly, it can also call any C library + functions, giving D access to the smorgasbord of existing C libraries. + To do so, however, one needs to write a D interface (.di) file, which + is a translation of the C .h header file for the C library into D. + ) + + $(P For popular C libraries, the first place to look for the corresponding + D interface file is the $(LINK2 https://github.com/D-Programming-Deimos/, Deimos Project). + If it isn't there already, please write and contribute one + to the Deimos Project. + ) + +$(H2 $(LEGACY_LNAME2 C Globals, c-globals, Accessing C Globals)) + + $(P C globals can be accessed directly from D. C globals have the C naming + convention, and so must be in an $(D extern (C)) block. + Use the $(D extern) storage class to indicate that the global is allocated + in the C code, not the D code. + C globals default to being in global, not thread local, storage. + To reference global storage + from D, use the $(D __gshared) storage class. + ) + +--- +extern (C) extern __gshared int x; +--- + +$(SPEC_SUBNAV_PREV_NEXT ddoc, Embedded Documentation, cpp_interface, Interfacing to C++) +) + +Macros: + CHAPTER=33 + TROW2=$(TR2 $(TD $(D $1)), $(TD2 $(D $2) $(TAIL $+))) + TROW3=$(TR3 $(TD $(D $1)), $(TD $(D $2)), $(TD $(D $3))) + TROW3PLUS=$(TR3 $(TD $(D $1)), $(TD $(D $2)), $(TD $(D $3) $4)) + TD2=$(MULTICOL_CELL 2, $0) + TITLE=Interfacing to C diff --git a/spec/intro.dd b/spec/intro.dd new file mode 100644 index 0000000000..e1f4ee0861 --- /dev/null +++ b/spec/intro.dd @@ -0,0 +1,164 @@ +Ddoc + +$(SPEC_S Introduction, + +$(HEADERNAV_TOC) + +$(P D is a general-purpose systems programming language with a C-like syntax that compiles to native code. +It is statically typed and supports both automatic $(LPAREN)garbage collected$(RPAREN) and manual memory management. +D programs are structured as modules that can be compiled separately and linked with external libraries +to create native libraries or executables.) + +$(P This document is the reference manual for the D Programming Language. For more information and +other documents$(COMMA) see $(LINK2 https://dlang.org/, The D Language Website).) + +$(H2 $(LNAME2 phases-of-compilation, Phases of Compilation)) + +$(P The process of compiling is divided into multiple phases. Each phase is +independent of subsequent phases. For example, the scanner is not affected by +the semantic analyzer. This separation of passes makes language tools like +syntax-directed editors relatively easy to create.) + +$(OL + $(LI $(B source character set)$(BR) + + The source file is checked to determine its encoding + and the appropriate scanner is loaded. 7-bit ASCII and UTF + encodings are accepted. + ) + + $(LI $(B script line) $(BR) + + If the first line starts with "$(HASH)!", then that line + is ignored. + ) + + $(LI $(B lexical analysis)$(BR) + + The source file is divided into a sequence of tokens. + $(DDSUBLINK spec/lex, specialtokens, Special tokens) + are replaced with other tokens. + $(GLINK_LEX SpecialTokenSequence)s + are processed and removed. + ) + + $(LI $(B syntax analysis)$(BR) + + The sequence of tokens is parsed to form syntax trees. + ) + + $(LI $(B semantic analysis)$(BR) + + The syntax trees are traversed to declare variables, load symbol tables, assign + types, and determine the meaning of the program. + ) + + $(LI $(B optimization)$(BR) + + Optimization is an optional pass that attempts to rewrite the program + in a semantically equivalent, more performant, version. + ) + + $(LI $(B code generation)$(BR) + + Instructions are selected from the target architecture to implement + the semantics of the program. The typical result will be + an object file suitable for input to a linker. + ) +) + + +$(H2 $(LNAME2 memory-model, Memory Model)) + + $(P The $(I byte) is the fundamental unit of storage. Each byte has 8 bits and is stored at + a unique address. A $(I memory location) is a sequence of one or more bytes of the exact size + required to hold a scalar type. Multiple threads can access separate memory locations + without interference. + ) + + $(P Memory locations come in three groups:) + + $(OL + $(LI $(I Thread-local memory locations) are accessible from only one thread at a time.) + $(LI $(I Immutable memory locations) cannot be written to during their lifetime. Immutable + memory locations can be read from by multiple threads without synchronization.) + $(LI $(I Shared memory locations) are accessible from multiple threads.) + ) + + $(UNDEFINED_BEHAVIOR Allowing multiple threads to access a thread-local memory + location results in undefined behavior.) + + $(UNDEFINED_BEHAVIOR Writing to an immutable memory location during its lifetime + results in undefined behavior.) + + $(UNDEFINED_BEHAVIOR Writing to a shared memory location in + one thread while one or more additional threads read from or write to the same location is + undefined behavior unless all of the reads and writes are synchronized.) + + $(P Execution of a single thread on thread-local and immutable memory locations + is $(I sequentially consistent). This means the collective result of the operations + is the same as if they were executed in the same order that the operations appear in the program. + ) + + $(P A memory location can be transferred from thread-local to immutable or shared + if there is only one reference to the location.) + + $(P A memory location can be transferred from shared to immutable or thread-local + if there is only one reference to the location.) + + $(P A memory location can be temporarily transferred from shared to local if + synchronization is used to prevent any other threads from accessing the memory + location during the operation.) + + +$(H2 $(LNAME2 object-model, Object Model)) + + $(P An $(I object) is created in the following circumstances: + ) + + $(UL + $(LI a definition) + $(LI a $(GLINK2 expression, NewExpression)) + $(LI a temporary is created) + $(LI changing which field of a union is active) + ) + + $(P An object spans a sequence of memory locations which may or may not + be contiguous. Its lifetime encompasses construction, destruction, and the period in between. + Each object has a type which is determined either statically or by runtime + type information. + The object's memory locations may include any combination of thread-local, immutable, or + shared. + ) + + $(P Objects can be composed into a $(I composed object). Objects that make up + a composed object are $(I subobjects). An object that is not the subobject + of another object is a $(I complete object). The lifetime of a subobject + is always within the lifetime of the complete object to which it belongs. + ) + + $(P An object's address is the address of the first byte of the first memory + location for that object. Object addresses are distinct unless one + object is nested within the other. + ) + +$(H2 $(LNAME2 arithmetic, Arithmetic)) + + $(H3 Integer Arithmetic) + + $(P Integer arithmetic is performed using + $(LINK2 https://en.wikipedia.org/wiki/Two%27s_complement, two's complement) math. + Integer overflow is not checked for. + ) + + $(H3 Floating Point Arithmetic) + + $(P Floating point arithmetic is performed using + $(LINK2 https://en.wikipedia.org/wiki/IEEE_754, IEEE-754 floating point math).) + +$(SPEC_SUBNAV_NEXT lex, Lexical) +) + +Macros: +TITLE = Introduction +CHAPTER = 1 diff --git a/spec/istring.dd b/spec/istring.dd new file mode 100644 index 0000000000..040e67e0e0 --- /dev/null +++ b/spec/istring.dd @@ -0,0 +1,228 @@ +Ddoc + +$(SPEC_S Interpolation Expression Sequence, + +$(HEADERNAV_TOC) + +$(P Interpolation Expression Sequences (IES) are expressions that intersperse +string literal data and values. An interpolation expression is written like a +string, but can contain values that are passed directly to a function that is +able to accept them. It is transformed into a $(I Sequence) of expressions that +can be overloaded or handled by template functions.) + +$(H2 $(LNAME2 ies, IES Literals)) + +$(GRAMMAR_LEX +$(GNAME InterpolationExpressionSequence): + $(GLINK InterpolatedDoubleQuotedLiteral) + $(GLINK InterpolatedWysiwygLiteral) + $(GLINK InterpolatedTokenLiteral) +) + +$(P An Interpolation Expression sequence can be either wysiwyg quoted, double +quoted, or a token literal. Only double quoted literals can have escapes in +them.) + +$(P Unlike string literals, IES literals cannot have a suffix defining the +width of the character type for the string expressions.) + +$(H3 $(LNAME2 ies_doublequoted, Double Quoted IES Literals)) + +$(GRAMMAR_LEX +$(GNAME InterpolatedDoubleQuotedLiteral): + $(B i") $(GLINK InterpolatedDoubleQuotedCharacters)$(OPT) $(B ") + +$(GNAME InterpolatedDoubleQuotedCharacters): + $(GLINK InterpolatedDoubleQuotedCharacter) + $(GLINK InterpolatedDoubleQuotedCharacter) $(GSELF InterpolatedDoubleQuotedCharacters) + +$(GNAME InterpolatedDoubleQuotedCharacter): + $(GLINK2 lex, DoubleQuotedCharacter) + $(GLINK InterpolationEscapeSequence) + $(GLINK InterpolationExpression) + +$(GNAME InterpolationEscapeSequence): + $(GLINK EscapeSequence) + $(B \\\$) + +$(GNAME InterpolationExpression): + $(B \$$(LPAREN)) $(GLINK AssignExpression) $(B $(RPAREN)) +) + +$(P Like $(GLINK2 lex, DoubleQuotedString), double-quoted IES literals can +have escape characters in them. Added to the normal escapes is the ability to +escape a literal $) + +$(P A $ followed by any character other than a left parenthesis is treated as a +literal $ in the expression, there is no need to escape it.) + +$(P The expression inside an $(GLINK InterpolationExpression) is a full D +expression, and escapes are not needed inside that part of the expression.) + +$(H3 $(LNAME2 ies_wysiwyg, Wysiwyg IES Literals)) + +$(GRAMMAR_LEX +$(GNAME InterpolatedWysiwygLiteral): + $(B i$(BACKTICK)) $(GLINK InterpolatedWysiwygCharacters)$(OPT) $(B $(BACKTICK)) + +$(GNAME InterpolatedWysiwygCharacters): + $(GLINK InterpolatedWysiwygCharacter) + $(GLINK InterpolatedWysiwygCharacter) $(GSELF InterpolatedWysiwygCharacters) + +$(GNAME InterpolatedWysiwygCharacter): + $(GLINK2 lex, WysiwygCharacter) + $(GLINK InterpolationExpression) +) + +$(P Wysiwyg ("what you see is what you get") IES literals are defined like +$(GLINK2 lex, WysiwygString) strings, but only support backquote syntax. No +escapes are recognized inside these literals.) + +$(H3 $(LNAME2 ies_token, Token IES Literals)) + +$(GRAMMAR_LEX +$(GNAME InterpolatedTokenLiteral): + $(D iq{) $(GLINK InterpolatedTokenStringTokens)$(OPT) $(D }) + +$(GNAME InterpolatedTokenStringTokens): + $(GLINK InterpolatedTokenStringToken) + $(GLINK InterpolatedTokenStringToken) $(GSELF InterpolatedTokenStringTokens) + +$(GNAME InterpolatedTokenStringToken): + $(GLINK InterpolatedTokenNoBraces) + $(B {) $(GSELF InterpolatedTokenStringTokens)$(OPT) $(B }) + +$(GNAME InterpolatedTokenNoBraces): + $(GLINK2 lex, TokenNoBraces) + $(GLINK InterpolationExpression) +) + +$(P Like $(GLINK2 lex, TokenString), IES Token literals must contain only +valid D tokens, with the exception of $(GLINK InterpolationExpression). No +escapes are recognized.) + +$(H2 $(LNAME2 expression_translation, Expression Translation)) + +$(P When the lexer encounters an Interpolation Expression Sequence, the token +is translated into a sequence of expressions, which replaces the single token. +The sequence always starts with the expression +$(D core.interpolation.InterpolationHeader()) and always ends with +$(D core.interpolation.InterpolationFooter())) + +$(P Each part $(D str) of the token which is literal string data is translated +into the expression $(D core.interpolation.InterpolatedLiteral!(str))) + +$(P Each part $(D \$$(LPAREN)expr$(RPAREN)) of the token which is an $(GLINK +InterpolationExpression) is translated into the sequence $(D +core.interpolation.InterpolatedExpression!(expr)$(COMMA) expr).) + +------ +// simple version of std.typecons.Tuple +struct Tuple(T...) { T value; } +Tuple!T tuple(T...)(T value) { return Tuple!T(value); } + +import core.interpolation; +string name = "John Doe"; +auto items = tuple(i"Hello, $(name), how are you?"); +assert(items == tuple( + InterpolationHeader(), // denotes the start of an IES + InterpolatedLiteral!("Hello, ")(), // literal string data + InterpolatedExpression!("name")(), // expression literal data + name, // expression passed directly + InterpolatedLiteral!(", how are you?")(), // literal string data + InterpolationFooter())); // denotes the end of an IES +------ + +$(H2 $(LNAME2 core_interpolation, core.interpolation Types)) + +$(P Types defined in $(D core.interpolation) need not be imported to use IES. +These are automatically imported when an IES is used. The types are defined so +as to make it easy to introspect the IES for processing at compile-time.) + +$(H3 $(LNAME2 interp_header, InterpolationHeader and InterpolationFooter)) + +$(P The $(D InterpolationHeader) and $(D InterpolationFooter) type are empty +structs that allow easy overloading of functions to handle IES. They also can +be used to understand which parts of a expression list were passed via IES.) + +$(P These types have a $(D toString) definition that returns an empty string, +to allow for processing by functions which intend to convert IES to text, such +as $(REF writeln, std,stdio) or $(REF text, std,conv).) + +$(H3 $(LNAME2 interp_literal, InterpolatedLiteral)) + +$(P The $(D InterpolatedLiteral) type is an empty struct that provides +compile-time access to the string literal portion of an IES. This type also +provides a $(D toString) member function which returns the part of the +sequence that this value replaced.) + +$(H3 $(LNAME2 interp_literal, InterpolatedExpression)) + +$(P The $(D InterpolatedExpression) type is an empty struct that provides +compile-time access to the literal that was used to form the following +expression. It provides a $(D toString) member function which returns the empty +string. It also has an $(D enum expression) member, which is equal to the +template parameter used to construct the type.) + +------ +string name = "John Doe"; +auto ies = i"Hello, $(name)"; +static assert(is(typeof(ies[0]) == InterpolationHeader)); +static assert(ies[1].toString() == "Hello, "); +static assert(ies[2].expression == "name"); +assert(ies[3] == name); +static assert(is(typeof(ies[4]) == InterpolationFooter)); +------ + +$(H2 $(LNAME2 accepting, Accepting and Processing IES)) + +$(P The recommended mechanism to accept IES is to provide a variadic template +function to match the various parameters inside the sequence, surrounded by +explicit $(D InterpolationHeader) and $(D InterpolationFooter) parameters.) + +------- +void processIES(Sequence...)(InterpolationHeader, Sequence data, InterpolationFooter) +{ + // process `data` here +} +------- + +$(P An IES can also contain types as interpolation expressions. This can be +used by passing to a variadic template parameter.) + +------- +template processIESAtCompileTime(InterpolationHeader header, Sequence...) +{ + static assert(Sequence[$-1] == InterpolationFooter()); +} + +alias result = processIES!i"Here is a type: $(int)"; +------- + +$(H2 $(LNAME2 tostring, Converting to a String)) + +$(P In many cases, it is desirable to convert an IES to a $(D string). The +Phobos function $(REF text, std,conv) can convert the IES to a $(D string) for use +in any context where a string is needed, for instance to assign to a string +variable, or call a function that accepts a string.) + +------- +import std.conv : text; +string name = "John Doe"; + +string badgreeting = i"Hello, $(name)"; // Error +string greeting = i"Hello, $(name)".text; // OK +assert(greeting == "Hello, John Doe"); +------- + +$(P It is highly recommended for library authors who wish to accept IES to +provide an overload that accepts them, rather than rely on $(D std.conv), as +this incurs unnecessary allocations. This is especially important where certain +types of injection attacks are possible from malicious user-provided data.) + +$(SPEC_SUBNAV_PREV_NEXT lex, Lexical, grammar, Grammar) +) + +Macros: +CHAPTER = 3 +TITLE = Interpolation Expression Sequence diff --git a/spec/legacy.dd b/spec/legacy.dd new file mode 100644 index 0000000000..c9f1829623 --- /dev/null +++ b/spec/legacy.dd @@ -0,0 +1,95 @@ +Ddoc + +$(SPEC_S Legacy Code, + +$(HEADERNAV_TOC) + + $(P To maintain compatibility with older D code, many legacy features remain supported. +$(COMMENT + If the $(TT -wo) compiler command line switch is used, the compiler will give warning messages + for each use of a legacy feature. +) + This page describes each legacy feature that is supported, with a suggestion of how to + modernize the code. + ) + + $(TABLE2 Legacy Features, + $(THEAD Feature, Summary) + $(TROW $(RELATIVE_LINK2 body, `body` keyword), $(D body) after a contract statement - + use $(D do) instead) + $(TROW `alias` target first syntax, use `alias name = target` instead.) + $(TROW Struct/union postblit, use a $(DDSUBLINK spec/struct, struct-copy-constructor, + copy constructor) instead.) + $(TROW $(RELATIVE_LINK2 alias-instance-member, Aliasing an instance member), + use `typeof(instance).member` instead.) + ) + +$(H2 $(LNAME2 body, `body` keyword)) + $(P `body` was a keyword used to specify a function/method's body after a contract statement:) + --- + class Foo + { + void bar(int i) + in { assert(i >= 42); } + body { /* Do something interesting */ } + + string method(string s) + out(v) { assert(v.length == s.length); } + body { /* Do something even more interesting */ } + + void noBody() { /* No contracts, no body */ } + } + --- + +$(H3 Corrective Action) + + $(P Use the `do` keyword instead (introduced in v2.075.0):) + --- + void bar(int i) + in { assert(i >= 42); } + do { /* Look ma, no body! */ } + --- + + $(RATIONALE The `body` keyword was only used for this single purpose. + Since D grammar aims to be context free, this common word was reserved, + which led to frequent trouble for people interfacing with other languages + (e.g. javascript) or auto-generating code. + ) + +$(H2 $(LNAME2 alias-instance-member, Aliasing an instance member)) + + $(P E.g. `alias a = instance.field;`. + Such an alias actually aliases a member of the instance's *type*, not + the instance member itself. That could be confusing. + Instead, alias a member of the type.) + + $(NOTE Aliasing `this.member` and `super.member` are valid inside + methods.) + +--- +struct Bar +{ + Foo f; + alias v = f.v; // Error, use `typeof(f).v` +} + +struct Foo +{ + int v; + void test(Foo that) const + { + alias a = this.v; // OK + alias b = that.v; // Error, use `typeof(that).v` instead + assert(&a is &b); // passes + assert(&b !is &that.v); + } +} +--- + + +$(SPEC_SUBNAV_PREV glossary, Glossary) +) + +Macros: + CHAPTER=46 + TITLE=Legacy Code diff --git a/spec/lex.dd b/spec/lex.dd new file mode 100644 index 0000000000..8475cd4122 --- /dev/null +++ b/spec/lex.dd @@ -0,0 +1,1224 @@ +Ddoc + +$(SPEC_S Lexical, + +$(HEADERNAV_TOC) + +$(P The lexical analysis is independent of the syntax parsing and the semantic +analysis. The lexical analyzer splits the source text into tokens. The +lexical grammar describes the syntax of these tokens. The grammar is designed to +be suitable for high-speed scanning and to facilitate the implementation of a correct +scanner. It has a minimum of special case rules and there is only one +phase of translation.) + +$(H2 $(LNAME2 source_text, Source Text)) + +$(GRAMMAR +$(GNAME SourceFile): + $(GLINK ByteOrderMark) $(GLINK2 module, Module)$(OPT) + $(GLINK Shebang) $(GLINK2 module, Module)$(OPT) + $(GLINK2 module, Module)$(OPT) +) +$(GRAMMAR_LEX +$(GNAME ByteOrderMark): + $(B \uFEFF) + +$(GNAME Shebang): + $(B #!) $(GLINK Characters)$(OPT) $(GLINK EndOfShebang) + +$(GNAME EndOfShebang): + $(B \u000A) + $(GLINK EndOfFile) +) + +$(P Source text can be encoded as any one of the following:) + + $(LIST + ASCII (strictly, 7-bit ASCII), + UTF-8, + UTF-16BE, + UTF-16LE, + UTF-32BE, + UTF-32LE + ) + +$(P One of the following UTF +BOMs (Byte Order Marks) can be present at the beginning of the source text:) + +$(TABLE2 UTF Byte Order Marks, + $(THEAD Format, BOM) + $(TROW UTF-8, EF BB BF) + $(TROW UTF-16BE, FE FF) + $(TROW UTF-16LE, FF FE) + $(TROW UTF-32BE, 00 00 FE FF) + $(TROW UTF-32LE, FF FE 00 00) + $(TROW ASCII, no BOM) +) + +$(P If the source file does not begin with a BOM, then the first character must +be less than or equal to U+0000007F.) + +$(P The source text is decoded from its source representation into Unicode +$(GLINK Character)s. The $(GLINK Character)s are further divided into: $(GLINK +WhiteSpace), $(GLINK EndOfLine), $(GLINK Comment)s, $(GLINK +SpecialTokenSequence)s, and $(GLINK Token)s, with the source terminated by an $(GLINK EndOfFile).) + +$(P The source text is split into tokens using the maximal munch algorithm, +i.e., the lexical analyzer assumes the longest possible token. For example, +$(D >>) is a right-shift token rather than two greater-than tokens. There are two +exceptions to this rule:) + +$(UL + $(LI A $(D ..) embedded between what appear to be two floating point + literals, as in $(D 1..2), is interpreted as if the $(D ..) were + separated by a space from the first integer.) + $(LI A `1.a` is interpreted as the three tokens `1`, `.`, and `a`, + whereas `1. a` is interpreted as the two tokens `1.` and `a`.) +) + +$(H2 $(LNAME2 character_set, Character Set)) + +$(GRAMMAR_LEX +$(GNAME Character): + $(I any Unicode character) +) + +$(H2 $(LNAME2 end_of_file, End of File)) + +$(GRAMMAR_LEX +$(GNAME EndOfFile): + $(I physical end of the file) + $(B \u0000) + $(B \u001A) +) + +$(P The source text is terminated by whichever comes first.) + +$(H2 $(LNAME2 end_of_line, End of Line)) + +$(GRAMMAR_LEX +$(GNAME EndOfLine): + $(B \u000D) + $(B \u000A) + $(B \u000D) $(B \u000A) + $(B \u2028) + $(B \u2029) + $(GLINK EndOfFile) +) + + +$(H2 $(LNAME2 white_space, White Space)) + +$(GRAMMAR_LEX +$(GNAME WhiteSpace): + $(GLINK Space) + $(GLINK Space) $(GSELF WhiteSpace) + +$(GNAME Space): + $(B \u0020) + $(B \u0009) + $(B \u000B) + $(B \u000C) +) + + +$(H2 $(LNAME2 comment, Comments)) + +$(GRAMMAR_LEX +$(GNAME Comment): + $(GLINK BlockComment) + $(GLINK LineComment) + $(GLINK NestingBlockComment) + +$(GNAME BlockComment): + $(B /*) $(GLINK Characters)$(OPT) $(B */) + +$(GNAME LineComment): + $(B //) $(GLINK Characters)$(OPT) $(GLINK EndOfLine) + +$(GNAME NestingBlockComment): + $(B /+) $(GLINK NestingBlockCommentCharacters)$(OPT) $(B +/) + +$(GNAME NestingBlockCommentCharacters): + $(GLINK NestingBlockCommentCharacter) + $(GLINK NestingBlockCommentCharacter) $(GSELF NestingBlockCommentCharacters) + +$(GNAME NestingBlockCommentCharacter): + $(GLINK Character) + $(GLINK NestingBlockComment) + +$(GNAME Characters): + $(GLINK Character) + $(GLINK Character) $(GSELF Characters) +) + + $(P There are three kinds of comments:) + + $(OL + $(LI Block comments can span multiple lines, but do not nest.) + $(LI Line comments terminate at the end of the line.) + $(LI Nesting block comments can span multiple lines and can nest.) + ) + + $(P + The contents of strings and comments are not tokenized. Consequently, + comment openings occurring within a string do not begin a comment, and + string delimiters within a comment do not affect the recognition of + comment closings and nested `/+` comment openings. With the exception + of `/+` occurring within a `/+` comment, comment openings within a + comment are ignored. + ) + +------------- +a = /+ // +/ 1; // parses as if 'a = 1;' +a = /+ "+/" +/ 1"; // parses as if 'a = " +/ 1";' +a = /+ /* +/ */ 3; // parses as if 'a = */ 3;' +------------- + +$(P Comments cannot be used as token concatenators, for example, $(D abc/**/def) +is two tokens, $(D abc) and $(D def), not one $(D abcdef) token.) + +$(H2 $(LNAME2 tokens, Tokens)) + +$(GRAMMAR +$(GNAME Tokens): + $(GLINK Token) + $(GLINK Token) $(GSELF Tokens) + +$(GNAME Token): + $(D {) + $(D }) + $(GLINK TokenNoBraces) + +$(GNAME TokenNoBraces): +$(MULTICOLS 4, $(GLINK Identifier) + $(GLINK StringLiteral) + $(GLINK2 istring, InterpolationExpressionSequence) + $(GLINK CharacterLiteral) + $(GLINK IntegerLiteral) + $(GLINK FloatLiteral) + $(GLINK Keyword) + $(D /) + $(D /=) + $(D .) + $(D ..) + $(D ...) + $(D $(AMP)) + $(D $(AMP)=) + $(D $(AMP)$(AMP)) + $(D |) + $(D |=) + $(D ||) + $(D -) + $(D -=) + $(D --) + $(D +) + $(D +=) + $(D ++) + $(D <) + $(D <=) + $(D <<) + $(D <<=) + $(D >) + $(D >=) + $(D >>=) + $(D >>>=) + $(D >>) + $(D >>>) + $(D !) + $(D !=) + $(D $(LPAREN)) + $(D $(RPAREN)) + $(D [) + $(D ]) + $(D ?) + $(D ,) + $(D ;) + $(D :) + $(D $) + $(D =) + $(D ==) + $(D *) + $(D *=) + $(D %) + $(D %=) + $(D ^) + $(D ^=) + $(D ^^) + $(D ^^=) + $(D ~) + $(D ~=) + $(D @) + $(D =>) +) +) + +$(H2 $(LNAME2 identifiers, Identifiers)) + +$(GRAMMAR_LEX +$(GNAME Identifier): + $(GLINK IdentifierStart) + $(GLINK IdentifierStart) $(GLINK IdentifierChars) + +$(GNAME IdentifierChars): + $(GLINK IdentifierChar) + $(GLINK IdentifierChar) $(GSELF IdentifierChars) + +$(GNAME IdentifierStart): + $(B _) + $(I Letter) + $(I UniversalAlpha) + +$(GNAME IdentifierChar): + $(GLINK IdentifierStart) + $(B 0) + $(GLINK NonZeroDigit) +) + + +$(P Identifiers start with a letter, $(D _), or universal alpha, and are +followed by any number of letters, $(D _), digits, or universal alphas. +Universal alphas are as defined in ISO/IEC 9899:1999(E) Appendix D of the C99 Standard. +Identifiers can be arbitrarily long, and are case sensitive.) + +$(IMPLEMENTATION_DEFINED Identifiers starting with $(D __) (two underscores) are reserved.) + +$(H2 $(LNAME2 string_literals, String Literals)) + +$(GRAMMAR +$(GNAME StringLiteral): + $(GLINK WysiwygString) + $(GLINK AlternateWysiwygString) + $(GLINK DoubleQuotedString) + $(GLINK DelimitedString) + $(GLINK TokenString) + $(GLINK HexString) +) +$(P +A string literal is either a wysiwyg quoted string, a double quoted +string, a delimited string, a token string, or a hex string. +) + +$(P In all string literal forms, an $(GLINK EndOfLine) is regarded as a single +$(D \n) character.) + +$(H3 $(LNAME2 wysiwyg, Wysiwyg Strings)) +$(GRAMMAR_LEX +$(GNAME WysiwygString): + $(B r") $(GLINK WysiwygCharacters)$(OPT) $(B ") $(GLINK StringPostfix)$(OPT) + +$(GNAME AlternateWysiwygString): + $(B $(BACKTICK)) $(GLINK WysiwygCharacters)$(OPT) $(B $(BACKTICK)) $(GLINK StringPostfix)$(OPT) + +$(GNAME WysiwygCharacters): + $(GLINK WysiwygCharacter) + $(GLINK WysiwygCharacter) $(GSELF WysiwygCharacters) + +$(GNAME WysiwygCharacter): + $(GLINK Character) + $(GLINK EndOfLine) +) + $(P + Wysiwyg ("what you see is what you get") quoted strings can be defined + using either of two syntaxes. + ) + + $(P + In the first form, they are enclosed between `r"` and `"`. + All characters between + the `r"` and `"` are part of the string. + There are no escape sequences inside wysiwyg strings. + ) + + --- + r"I am Oz" + r"c:\games\Sudoku.exe" + r"ab\n" // string is 4 characters, + // 'a', 'b', '\', 'n' + --- + + $(P + Alternatively, wysiwyg strings can be enclosed by backquotes, + using the $(BACKTICK) character. + ) + + --- + `the Great and Powerful.` + `c:\games\Empire.exe` + `The "lazy" dog` + `a"b\n` // string is 5 characters, + // 'a', '"', 'b', '\', 'n' + --- + +$(P See also $(GLINK2 istring, InterpolatedWysiwygLiteral)) + +$(H3 $(LNAME2 double_quoted_strings, Double Quoted Strings)) +$(GRAMMAR_LEX +$(GNAME DoubleQuotedString): + $(B ") $(GLINK DoubleQuotedCharacters)$(OPT) $(B ") $(GLINK StringPostfix)$(OPT) + +$(GNAME DoubleQuotedCharacters): + $(GLINK DoubleQuotedCharacter) + $(GLINK DoubleQuotedCharacter) $(GSELF DoubleQuotedCharacters) + +$(GNAME DoubleQuotedCharacter): + $(GLINK Character) + $(GLINK EscapeSequence) + $(GLINK EndOfLine) +) + + $(P Double quoted strings are enclosed by "". $(GLINK EscapeSequence)s can be + embedded in them.) + + --- + "Who are you?" + "c:\\games\\Doom.exe" + "ab\n" // string is 3 characters, + // 'a', 'b', and a linefeed + "ab + " // string is 3 characters, + // 'a', 'b', and a linefeed + --- + +$(P See also $(GLINK2 istring, InterpolatedDoubleQuotedLiteral)) + +$(H3 $(LNAME2 delimited_strings, Delimited Strings)) +$(GRAMMAR_LEX +$(GNAME DelimitedString): + $(B q") $(GLINK Delimiter) $(GLINK WysiwygCharacters)$(OPT) $(GLINK MatchingDelimiter) $(B ") $(GLINK StringPostfix)$(OPT) + $(B q"$(LPAREN)) $(GLINK ParenDelimitedCharacters)$(OPT) $(B $(RPAREN)") $(GLINK StringPostfix)$(OPT) + $(B q"[) $(GLINK BracketDelimitedCharacters)$(OPT) $(B ]") $(GLINK StringPostfix)$(OPT) + $(B q"{) $(GLINK BraceDelimitedCharacters)$(OPT) $(B }") $(GLINK StringPostfix)$(OPT) + $(B q"<) $(GLINK AngleDelimitedCharacters)$(OPT) $(B >") $(GLINK StringPostfix)$(OPT) + +$(GNAME Delimiter): + $(GLINK Identifier) + +$(GNAME MatchingDelimiter): + $(GLINK Identifier) + +$(GNAME ParenDelimitedCharacters): + $(GLINK WysiwygCharacter) + $(GLINK WysiwygCharacter) $(GSELF ParenDelimitedCharacters) + $(B $(LPAREN)) $(GSELF ParenDelimitedCharacters)$(OPT) $(B $(RPAREN)) + +$(GNAME BracketDelimitedCharacters): + $(GLINK WysiwygCharacter) + $(GLINK WysiwygCharacter) $(GSELF BracketDelimitedCharacters) + $(B [) $(GSELF BracketDelimitedCharacters)$(OPT) $(B ]) + +$(GNAME BraceDelimitedCharacters): + $(GLINK WysiwygCharacter) + $(GLINK WysiwygCharacter) $(GSELF BraceDelimitedCharacters) + $(B {) $(GSELF BraceDelimitedCharacters)$(OPT) $(B }) + +$(GNAME AngleDelimitedCharacters): + $(GLINK WysiwygCharacter) + $(GLINK WysiwygCharacter) $(GSELF AngleDelimitedCharacters) + $(B <) $(GSELF AngleDelimitedCharacters)$(OPT) $(B >) +) + + $(P Delimited strings use various forms of delimiters. + The delimiter, whether a character or identifier, + must immediately follow the " without any intervening whitespace. + The terminating delimiter must immediately precede the closing " + without any intervening whitespace. + A $(I nesting delimiter) nests, and is one of the + following characters: + ) + + $(TABLE2 Nesting Delimiters, + $(THEAD Delimiter, Matching Delimiter) + $(TROW $(D [), $(D ])) + $(TROW $(LPAREN), $(RPAREN)) + $(TROW $(D <), $(D >)) + $(TROW $(CODE_LCURL), $(CODE_RCURL)) + ) + +--- +q"(foo(xxx))" // "foo(xxx)" +q"[foo{]" // "foo{" +--- + + $(P If the delimiter is an identifier, the identifier must + be immediately followed by a newline, and the matching + delimiter must be the same identifier starting at the beginning + of the line: + ) +--- +writeln(q"EOS +This +is a multi-line +heredoc string +EOS" +); +--- + $(P The newline following the opening identifier is not part + of the string, but the last newline before the closing + identifier is part of the string. The closing identifier + must be placed on its own line at the leftmost column. + ) + + $(P Otherwise, the matching delimiter is the same as + the delimiter character:) + +--- +q"/foo]/" // "foo]" +// q"/abc/def/" // error +--- + +$(H3 $(LNAME2 token_strings, Token Strings)) +$(GRAMMAR +$(GNAME TokenString): + $(D q{) $(GLINK TokenStringTokens)$(OPT) $(D }) $(GLINK StringPostfix)$(OPT) + +$(GNAME TokenStringTokens): + $(GLINK TokenStringToken) + $(GLINK TokenStringToken) $(GSELF TokenStringTokens) + +$(GNAME TokenStringToken): + $(GLINK TokenNoBraces) + $(D {) $(GLINK TokenStringTokens)$(OPT) $(D }) +) + + $(P Token strings open with the characters $(D q)$(CODE_LCURL) and close with + the token $(CODE_RCURL). In between must be valid D tokens. + The $(CODE_LCURL) and $(CODE_RCURL) tokens nest. + The string is formed of all the characters between the opening + and closing of the token string, including comments. + ) + + --- + q{this is the voice of} // "this is the voice of" + q{/*}*/ } // "/*}*/ " + q{ world(q{control}); } // " world(q{control}); " + q{ __TIME__ } // " __TIME__ " + // i.e. it is not replaced with the time + // q{ __EOF__ } // error + // __EOF__ is not a token, it's end of file + --- + +$(P See also $(GLINK2 istring, InterpolatedTokenLiteral)) + +$(H3 $(LNAME2 hex_strings, Hex Strings)) +$(GRAMMAR +$(GNAME HexString): + $(B x") $(GLINK HexStringChars)$(OPT) $(B ") $(GLINK StringPostfix)$(OPT) + +$(GNAME HexStringChars): + $(GLINK HexStringChar) + $(GLINK HexStringChar) $(GSELF HexStringChars) + +$(GNAME HexStringChar): + $(GLINK HexDigit) + $(GLINK WhiteSpace) + $(GLINK EndOfLine) +) + + $(P Hex strings allow string literals to be created using hex data. + The hex data need not form valid UTF characters. + ) + + --- + x"0A" // same as "\x0A" + x"00 FBCD 32FD 0A" // same as "\x00\xFB\xCD\x32\xFD\x0A" + --- + + $(P Whitespace and newlines are ignored, so the hex data can be easily + formatted. The number of hex characters must be a multiple of 2.) + +$(H3 $(LNAME2 string_postfix, String Postfix)) + +$(GRAMMAR_LEX +$(GNAME StringPostfix): + $(B c) + $(B w) + $(B d) +) + + $(P The optional $(I StringPostfix) character gives a specific type + to the string, rather than it being inferred from the context. + The types corresponding to the postfix characters are: + ) + + + $(TABLE2 String Literal Postfix Characters, + $(THEAD Postfix, Type, Alias) + $(TROW $(B c), $(D immutable(char)[]), $(D string)) + $(TROW $(B w), $(D immutable(wchar)[]), $(D wstring)) + $(TROW $(B d), $(D immutable(dchar)[]), $(D dstring)) + ) + +--- +"hello"c // string +"hello"w // wstring +"hello"d // dstring +--- + + $(P The string literals are assembled as UTF-8 char arrays, + and the postfix is applied + to convert to wchar or dchar as necessary as a final step.) + +$(H2 $(LNAME2 escape_sequences, Escape Sequences)) + +$(GRAMMAR_LEX +$(GNAME EscapeSequence): + $(B \\') + $(B \\") + $(B \\?) + $(B \\\\) + $(B \0) + $(B \a) + $(B \b) + $(B \f) + $(B \n) + $(B \r) + $(B \t) + $(B \v) + $(B \x) $(GLINK HexDigit) $(GLINK HexDigit) + $(B \\) $(GLINK OctalDigit) + $(B \\) $(GLINK OctalDigit) $(GLINK OctalDigit) + $(B \\) $(GLINK OctalDigit) $(GLINK OctalDigit) $(GLINK OctalDigit) + $(B \u) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) + $(B \U) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) $(GLINK HexDigit) + $(B \\) $(GLINK2 entity, NamedCharacterEntity) + +$(GNAME OctalDigit): + $(B 0) + $(B 1) + $(B 2) + $(B 3) + $(B 4) + $(B 5) + $(B 6) + $(B 7) +) + + $(LONGTABLE_2COLS 0.8, Escape Sequences, + $(THEAD Sequence, Meaning), + $(TROW `\'`, Literal single-quote: $(D ')) + $(TROW `\"`, Literal double-quote: $(D ")) + $(TROW `\?`, Literal question mark: $(D ?)) + $(TROW `\\`, Literal backslash: `\`) + $(TROW `\0`, Binary zero (NUL, U+0000).) + $(TROW `\a`, BEL (alarm) character (U+0007).) + $(TROW `\b`, Backspace (U+0008).) + $(TROW `\f`, Form feed (FF) (U+000C).) + $(TROW `\n`, End-of-line (U+000A).) + $(TROW `\r`, Carriage return (U+000D).) + $(TROW `\t`, Horizontal tab (U+0009).) + $(TROW `\v`, Vertical tab (U+000B).) + $(TROW `\x`$(I nn), Byte value in hexadecimal$(COMMA) where $(I nn) is + specified as two hexadecimal digits.$(BR)For example: `\xFF` + represents the character with the value 255.$(BR) + See also: $(REF hexString, std,conv).) + $(TROW `\`$(I n)$(BR)`\`$(I nn)$(BR)`\`$(I nnn), Byte value in + octal.$(BR)For example: `\101` represents the character with the + value 65 ($(D 'A')). Analogous to hexadecimal characters$(COMMA) + the largest byte value is `\377` (= `\xFF` in hexadecimal + or $(D 255) in decimal)$(BR) + See also: $(REF octal, std,conv).) + $(TROW `\u`$(I nnnn), Unicode character U+$(I nnnn)$(COMMA) where + $(I nnnn) are four hexadecimal digits.$(BR)For example$(COMMA) + `\u03B3` represents the Unicode character $(GAMMA) (U+03B3 - GREEK SMALL LETTER GAMMA).) + $(TROW `\U`$(I nnnnnnnn), Unicode character U+$(I nnnnnnnn)$(COMMA) + where $(I nnnnnnnn) are 8 hexadecimal digits.$(BR)For example$(COMMA) + `\U0001F603` represents the Unicode character U+1F603 (SMILING FACE + WITH OPEN MOUTH).) + $(TROW `\`$(I name), $(ARGS Named character entity from the HTML5 + specification. $(BR) + These names begin with $(CODE_AMP) and end with $(D ;), e.g.$(COMMA) $(D $(AMP)euro;). + See $(GLINK2 entity, NamedCharacterEntity).)) + ) + +$(H2 $(LNAME2 characterliteral, Character Literals)) + +$(GRAMMAR_LEX +$(GNAME CharacterLiteral): + $(B ') $(GLINK SingleQuotedCharacter) $(B ') + +$(GNAME SingleQuotedCharacter): + $(GLINK Character) + $(GLINK EscapeSequence) +) + +$(P Character literals are a single character or escape sequence enclosed by +single quotes.) + + --- + 'h' // the letter h + '\n' // newline + '\\' // the backslash character + --- + +$(P A character literal resolves to one + of type $(D char), $(D wchar), or $(D dchar) + (see $(DDSUBLINK spec/type, basic-data-types, Basic Data Types)).) + +$(UL + $(LI If the literal is a $(D \u) escape sequence, it resolves to type $(D wchar).) + $(LI If the literal is a $(D \U) escape sequence, it resolves to type $(D dchar).) +) +$(P Otherwise, it resolves to the type with the smallest size it + will fit into.) + +$(H2 $(LNAME2 integerliteral, Integer Literals)) + +$(GRAMMAR_LEX +$(GNAME IntegerLiteral): + $(GLINK Integer) + $(GLINK Integer) $(GLINK IntegerSuffix) + +$(GNAME Integer): + $(GLINK DecimalInteger) + $(GLINK BinaryInteger) + $(GLINK HexadecimalInteger) + +$(GNAME IntegerSuffix): + $(B L) + $(B u) + $(B U) + $(B Lu) + $(B LU) + $(B uL) + $(B UL) +) + +$(GRAMMAR_LEX +$(GNAME DecimalInteger): + $(B 0) $(GLINK Underscores)$(OPT) + $(GLINK NonZeroDigit) + $(GLINK NonZeroDigit) $(GLINK DecimalDigitsUS) + +$(GNAME Underscores): + $(B _) + $(GLINK Underscores) $(B _) + +$(GNAME NonZeroDigit): + $(B 1) + $(B 2) + $(B 3) + $(B 4) + $(B 5) + $(B 6) + $(B 7) + $(B 8) + $(B 9) + +$(GNAME DecimalDigits): + $(GLINK DecimalDigit) + $(GLINK DecimalDigit) $(GSELF DecimalDigits) + +$(GNAME DecimalDigitsUS): + $(GLINK DecimalDigitUS) + $(GLINK DecimalDigitUS) $(GSELF DecimalDigitsUS) + +$(GNAME DecimalDigitsNoSingleUS): + $(GLINK DecimalDigitsUS)$(OPT) $(GLINK DecimalDigit) $(GLINK DecimalDigitsUS)$(OPT) + +$(GNAME DecimalDigitsNoStartingUS): + $(GLINK DecimalDigit) + $(GLINK DecimalDigit) $(GLINK DecimalDigitsUS) + +$(GNAME DecimalDigit): + $(B 0) + $(GLINK NonZeroDigit) + +$(GNAME DecimalDigitUS): + $(GLINK DecimalDigit) + $(B _) +) + +$(GRAMMAR_LEX +$(GNAME BinaryInteger): + $(GLINK BinPrefix) $(GLINK BinaryDigitsNoSingleUS) + +$(GNAME BinPrefix): + $(B 0b) + $(B 0B) + +$(GNAME BinaryDigitsNoSingleUS): + $(GLINK BinaryDigitsUS)$(OPT) $(GLINK BinaryDigit) $(GLINK BinaryDigitsUS)$(OPT) + +$(GNAME BinaryDigitsUS): + $(GLINK BinaryDigitUS) + $(GLINK BinaryDigitUS) $(GSELF BinaryDigitsUS) + +$(GNAME BinaryDigit): + $(B 0) + $(B 1) + +$(GNAME BinaryDigitUS): + $(GLINK BinaryDigit) + $(B _) +) + +$(GRAMMAR_LEX +$(GNAME HexadecimalInteger): + $(GLINK HexPrefix) $(GLINK HexDigitsNoSingleUS) + +$(GNAME HexDigits): + $(GLINK HexDigit) + $(GLINK HexDigit) $(GSELF HexDigits) + +$(GNAME HexDigitsUS): + $(GLINK HexDigitUS) + $(GLINK HexDigitUS) $(GSELF HexDigitsUS) + +$(GNAME HexDigitsNoSingleUS): + $(GLINK HexDigitsUS)$(OPT) $(GLINK HexDigit) $(GLINK HexDigitsUS)$(OPT) + +$(GNAME HexDigitsNoStartingUS): + $(GLINK HexDigit) + $(GLINK HexDigit) $(GLINK HexDigitsUS) + +$(GNAME HexDigit): + $(GLINK DecimalDigit) + $(GLINK HexLetter) + +$(GNAME HexDigitUS): + $(GLINK HexDigit) + $(B _) + +$(GNAME HexLetter): + $(B a) + $(B b) + $(B c) + $(B d) + $(B e) + $(B f) + $(B A) + $(B B) + $(B C) + $(B D) + $(B E) + $(B F) +) + + $(P Integers can be specified in decimal, binary, or hexadecimal.) + + $(UL + $(LI Decimal integers are a sequence of decimal digits.) + + $(LI $(LNAME2 binary-literals, Binary integers) are a sequence of binary digits preceded + by a $(SINGLEQUOTE 0b) or $(SINGLEQUOTE 0B). + ) + + $(LI C-style octal integer notation (e.g. `0167`) was deemed too easy to mix up with decimal notation; + it is only fully supported in string literals. + D still supports octal integer literals interpreted at compile time through the $(REF octal, std,conv) + template, as in $(D octal!167).) + + $(LI Hexadecimal integers are a sequence of hexadecimal digits preceded + by a $(SINGLEQUOTE 0x) or $(SINGLEQUOTE 0X). + ) + ) + +--- +10 // decimal +0b1010 // binary +0xA // hex +--- + + $(P Integers can have embedded $(SINGLEQUOTE $(UNDERSCORE)) characters after a digit to improve readability, which are ignored. + ) + + --- + 20_000 // leagues under the sea + 867_5309 // number on the wall + 1_522_000 // thrust of F1 engine (lbf sea level) + 0xBAAD_F00D // magic number for debugging + --- + + $(P Integers can be immediately followed by one $(SINGLEQUOTE L) or one of + $(SINGLEQUOTE u) or $(SINGLEQUOTE U) or both. + Note that there is no $(SINGLEQUOTE l) suffix. + ) + + $(P The type of the integer is resolved as follows:) + + $(TABLE2 Decimal Literal Types, + $(THEAD Literal, Type) + $(TROW_EXPLANATORY $(I Usual decimal notation)) + $(TROW $(D 0 .. 2_147_483_647), $(D int)) + $(TROW $(D 2_147_483_648 .. 9_223_372_036_854_775_807), $(D long)) + $(TROW $(D 9_223_372_036_854_775_808 .. 18_446_744_073_709_551_615), $(D ulong)) + $(MIDRULE) + $(TROW_EXPLANATORY $(I Explicit suffixes)) + $(TROW $(D 0L .. 9_223_372_036_854_775_807L), $(D long)) + $(TROW $(D 0U .. 4_294_967_295U), $(D uint)) + $(TROW $(D 4_294_967_296U .. 18_446_744_073_709_551_615U), `ulong`) + $(TROW $(D 0UL .. 18_446_744_073_709_551_615UL), $(D ulong)) + $(MIDRULE) + $(TROW_EXPLANATORY $(I Hexadecimal notation)) + $(TROW $(D 0x0 .. 0x7FFF_FFFF), $(D int)) + $(TROW $(D 0x8000_0000 .. 0xFFFF_FFFF), $(D uint)) + $(TROW $(D 0x1_0000_0000 .. 0x7FFF_FFFF_FFFF_FFFF), $(D long)) + $(TROW $(D 0x8000_0000_0000_0000 .. 0xFFFF_FFFF_FFFF_FFFF), `ulong`) + $(MIDRULE) + $(TROW_EXPLANATORY $(I Hexadecimal notation with explicit suffixes)) + $(TROW $(D 0x0L .. 0x7FFF_FFFF_FFFF_FFFFL), $(D long)) + $(TROW $(D 0x8000_0000_0000_0000L .. 0xFFFF_FFFF_FFFF_FFFFL), `ulong`) + $(TROW $(D 0x0U .. 0xFFFF_FFFFU), $(D uint)) + $(TROW $(D 0x1_0000_0000U .. 0xFFFF_FFFF_FFFF_FFFFU), `ulong`) + $(TROW $(D 0x0UL .. 0xFFFF_FFFF_FFFF_FFFFUL), $(D ulong)) + ) + + $(P An integer literal may not exceed these values.) + + $(BEST_PRACTICE Octal integer notation is not supported for integer literals. + However, octal integer literals can be interpreted at compile time through + the $(REF octal, std,conv) template, as in $(D octal!167).) + + + +$(H2 $(LNAME2 floatliteral, Floating Point Literals)) + +$(GRAMMAR_LEX +$(GNAME FloatLiteral): + $(GLINK Float) $(GLINK Suffix)$(OPT) + $(GLINK Integer) $(GLINK FloatSuffix) $(GLINK ImaginarySuffix)$(OPT) + $(GLINK Integer) $(GLINK RealSuffix)$(OPT) $(GLINK ImaginarySuffix) + +$(GNAME Float): + $(GLINK DecimalFloat) + $(GLINK HexFloat) + +$(GNAME DecimalFloat): + $(GLINK LeadingDecimal) $(B .) $(GLINK DecimalDigitsNoStartingUS)$(OPT) + $(GLINK LeadingDecimal) $(B .) $(GLINK DecimalDigitsNoStartingUS) $(GLINK DecimalExponent) + $(B .) $(GLINK DecimalDigitsNoStartingUS) $(GLINK DecimalExponent)$(OPT) + $(GLINK LeadingDecimal) $(GLINK DecimalExponent) + +$(GNAME DecimalExponent): + $(GLINK DecimalExponentStart) $(GLINK DecimalDigitsNoSingleUS) + +$(GNAME DecimalExponentStart): + $(B e) + $(B E) + $(B e+) + $(B E+) + $(B e-) + $(B E-) + +$(GNAME HexFloat): + $(GLINK HexPrefix) $(GLINK HexDigitsNoSingleUS) $(B .) $(GLINK HexDigitsNoStartingUS) $(GLINK HexExponent) + $(GLINK HexPrefix) $(B .) $(GLINK HexDigitsNoStartingUS) $(GLINK HexExponent) + $(GLINK HexPrefix) $(GLINK HexDigitsNoSingleUS) $(GLINK HexExponent) + $(GLINK HexPrefix) $(GLINK HexExponent) + +$(GNAME HexPrefix): + $(B 0x) + $(B 0X) + +$(GNAME HexExponent): + $(GLINK HexExponentStart) $(GLINK DecimalDigitsNoSingleUS) + +$(GNAME HexExponentStart): + $(B p) + $(B P) + $(B p+) + $(B P+) + $(B p-) + $(B P-) + + +$(GNAME Suffix): + $(GLINK FloatSuffix) $(GLINK ImaginarySuffix)$(OPT) + $(GLINK RealSuffix) $(GLINK ImaginarySuffix)$(OPT) + $(GLINK ImaginarySuffix) + +$(GNAME FloatSuffix): + $(B f) + $(B F) + +$(GNAME RealSuffix): + $(B L) + +$(GDEPRECATED $(GNAME ImaginarySuffix)): + $(B i) + +$(GNAME LeadingDecimal): + $(GLINK DecimalInteger) + $(B 0) $(GLINK DecimalDigitsNoSingleUS) +) + + $(P Floats can be in decimal or hexadecimal format, and must have + at least one digit and either a decimal point, an exponent, or + a *FloatSuffix*.) + + $(P Decimal floats can have an exponent which is `e` or `E` followed + by a decimal number serving as the exponent of 10.) + +--- +-1.0 +1e2 // 100.0 +1e-2 // 0.01 +-1.175494351e-38F // float.min +--- + + $(P Hexadecimal floats are preceded by a $(B 0x) or $(B 0X) and the + exponent is a $(B p) or $(B P) followed by a decimal number serving as + the exponent of 2. + ) + +--- +0xAp0 // 10.0 +0x1p2 // 4.0 +0x1.FFFFFFFFFFFFFp1023 // double.max +0x1p-52 // double.epsilon +--- + + $(P Floating literals can have embedded $(D $(UNDERSCORE)) characters + after a digit to improve readability, which are ignored. + ) + + --- + 2.645_751 + 6.022140857E+23 + 6_022.140857E+20 + 6_022_.140_857E+20_ + --- + + * Floating literals with no suffix are of type `double`. + * Floating literals followed by $(B f) or $(B F) are of type `float`. + * Floating literals followed by $(B L) are of type `real`. + +--------- +0.0 // double +0F // float +0.0L // real +--------- + + $(P The literal may not exceed the range of the type. + The literal is rounded to fit into + the significant digits of the type. + ) + $(P If a floating literal has a $(D .) and a type suffix, at least one + digit must be in-between:) + + --- + 1f; // OK, float + 1.f; // error + 1.; // OK, double + --- + + $(NOTE Floating literals followed by $(B i) to denote imaginary + floating point values have been deprecated.) + + +$(H2 $(LNAME2 keywords, Keywords)) + + $(P Keywords are reserved identifiers.) + + +$(GRAMMAR +$(GNAME Keyword): +$(MULTICOLS 4, + $(LINK2 attribute.html#abstract, $(D abstract)) + $(LINK2 declaration.html#alias, $(D alias)) + $(LINK2 attribute.html#align, $(D align)) + $(LINK2 statement.html#AsmStatement, $(D asm)) + $(LINK2 expression.html#AssertExpression, $(D assert)) + $(LINK2 attribute.html#auto, $(D auto)) + + $(GDEPRECATED $(LINK2 function.html#BodyStatement, $(D body))) + $(LINK2 type.html, $(D bool)) + $(LINK2 statement.html#BreakStatement, $(D break)) + $(LINK2 type.html, $(D byte)) + + $(LINK2 statement.html#SwitchStatement, $(D case)) + $(LINK2 expression.html#CastExpression, $(D cast)) + $(LINK2 statement.html#TryStatement, $(D catch)) + $(GDEPRECATED $(LINK2 type.html, $(D cdouble))) + $(GDEPRECATED $(LINK2 type.html, $(D cent))) + $(GDEPRECATED $(LINK2 type.html, $(D cfloat))) + $(LINK2 type.html, $(D char)) + $(LINK2 class.html, $(D class)) + $(LINK2 attribute.html#const, $(D const)) + $(LINK2 statement.html#ContinueStatement, $(D continue)) + $(GDEPRECATED $(LINK2 type.html, $(D creal))) + + $(LINK2 type.html, $(D dchar)) + $(LINK2 version.html#debug, $(D debug)) + $(LINK2 statement.html#SwitchStatement, $(D default)) + $(LINK2 type.html#delegates, $(D delegate)) + $(GDEPRECATED $(LINK2 expression.html#DeleteExpression, $(D delete))) + $(LINK2 attribute.html#deprecated, $(D deprecated)) + $(LINK2 statement.html#DoStatement, $(D do)) + $(LINK2 type.html, $(D double)) + + $(LINK2 statement.html#IfStatement, $(D else)) + $(LINK2 enum.html, $(D enum)) + $(LINK2 attribute.html#visibility_attributes, $(D export)) + $(LINK2 attribute.html#linkage, $(D extern)) + + $(LINK2 type.html, $(D false)) + $(LINK2 class.html#final, $(D final)) + $(LINK2 statement.html#TryStatement, $(D finally)) + $(LINK2 type.html, $(D float)) + $(LINK2 statement.html#ForStatement, $(D for)) + $(LINK2 statement.html#ForeachStatement, $(D foreach)) + $(LINK2 statement.html#ForeachStatement, $(D foreach_reverse)) + $(LINK2 expression.html#FunctionLiteral, $(D function)) + + $(LINK2 statement.html#GotoStatement, $(D goto)) + + $(GDEPRECATED $(LINK2 type.html, $(D idouble))) + $(LINK2 statement.html#IfStatement, $(D if)) + $(GDEPRECATED $(LINK2 type.html, $(D ifloat))) + $(LINK2 attribute.html#immutable, $(D immutable)) + $(LINK2 expression.html#ImportExpression, $(D import)) + $(LINK2 expression.html#InExpression, $(D in)) + $(LINK2 function.html#inout-functions, $(D inout)) + $(LINK2 type.html, $(D int)) + $(LINK2 interface.html, $(D interface)) + $(LINK2 contracts.html, $(D invariant)) + $(GDEPRECATED $(LINK2 type.html, $(D ireal))) + $(LINK2 expression.html#IsExpression, $(D is)) + + $(LINK2 function.html#overload-sets, $(D lazy)) + $(LINK2 type.html, $(D long)) + + $(GRESERVED $(D macro)) + $(LINK2 expression.html#MixinExpression, $(D mixin)) + $(LINK2 module.html#ModuleDeclaration, $(D module)) + + $(LINK2 expression.html#NewExpression, $(D new)) + $(LINK2 function.html#nothrow-functions, $(D nothrow)) + $(LINK2 expression.html#null, $(D null)) + + $(LINK2 function.html#OutStatement, $(D out)) + $(LINK2 attribute.html#override, $(D override)) + + $(LINK2 attribute.html#visibility_attributes, $(D package)) + $(LINK2 pragma.html, $(D pragma)) + $(LINK2 attribute.html#visibility_attributes, $(D private)) + $(LINK2 attribute.html#visibility_attributes, $(D protected)) + $(LINK2 attribute.html#visibility_attributes, $(D public)) + $(LINK2 function.html#pure-functions, $(D pure)) + + $(LINK2 type.html, $(D real)) + $(LINK2 function.html#ref-functions, $(D ref)) + $(LINK2 statement.html#ReturnStatement, $(D return)) + + $(LINK2 statement.html#ScopeGuardStatement, $(D scope)) + $(LINK2 attribute.html#shared, $(D shared)) + $(LINK2 type.html, $(D short)) + $(LINK2 version.html#staticif, $(D static)) + $(LINK2 struct.html, $(D struct)) + $(LINK2 expression.html#super, $(D super)) + $(LINK2 statement.html#SwitchStatement, $(D switch)) + $(LINK2 statement.html#SynchronizedStatement, $(D synchronized)) + + $(LINK2 template.html, $(D template)) + $(LINK2 expression.html#this, $(D this)) + $(LINK2 statement.html#ThrowStatement, $(D throw)) + $(LINK2 type.html, $(D true)) + $(LINK2 statement.html#TryStatement, $(D try)) + $(LINK2 expression.html#TypeidExpression, $(D typeid)) + $(LINK2 type.html#Typeof, $(D typeof)) + + $(LINK2 type.html, $(D ubyte)) + $(GDEPRECATED $(LINK2 type.html, $(D ucent))) + $(LINK2 type.html, $(D uint)) + $(LINK2 type.html, $(D ulong)) + $(LINK2 struct.html, $(D union)) + $(LINK2 unittest.html, $(D unittest)) + $(LINK2 type.html, $(D ushort)) + + $(LINK2 version.html#version, $(D version)) + $(LINK2 declaration.html#VoidInitializer, $(D void)) + + $(LINK2 type.html, $(D wchar)) + $(LINK2 statement.html#WhileStatement, $(D while)) + $(LINK2 statement.html#WithStatement, $(D with)) + + $(LINK2 expression.html#specialkeywords, $(D __FILE__)) + $(LINK2 expression.html#specialkeywords, $(D __FILE_FULL_PATH__)) + $(LINK2 expression.html#specialkeywords, $(D __FUNCTION__)) + $(LINK2 expression.html#specialkeywords, $(D __LINE__)) + $(LINK2 expression.html#specialkeywords, $(D __MODULE__)) + $(LINK2 expression.html#specialkeywords, $(D __PRETTY_FUNCTION__)) + + $(LINK2 attribute.html#gshared, $(D __gshared)) + $(LINK2 expression.html#IsExpression, $(D __parameters)) + $(LINK2 expression.html#RvalueExpression, $(D __rvalue)) + $(LINK2 traits.html, $(D __traits)) + $(LINK2 $(ROOT_DIR)phobos/core_simd.html#.Vector, $(D __vector)) +) +) + + +$(H2 $(LNAME2 specialtokens, Special Tokens)) + + $(P + These tokens are replaced with other tokens according to the following + table: + ) + + $(TABLE_2COLS Special Tokens, + $(THEAD Special Token, Replaced with) + + $(TROW $(D __DATE__), string literal of the date of compilation "$(I mmm dd yyyy)") + $(TROW $(D __EOF__), tells the scanner to ignore everything after this token) + + $(TROW $(D __TIME__), string literal of the time of compilation "$(I hh:mm:ss)") + $(TROW $(D __TIMESTAMP__), string literal of the date and time of compilation "$(I www mmm dd hh:mm:ss yyyy)") + $(TROW $(D __VENDOR__), $(ARGS Compiler vendor string)) + $(TROW $(D __VERSION__), $(ARGS Compiler version as an integer)) + ) + + $(IMPLEMENTATION_DEFINED + The replacement string literal for `__VENDOR__` and the replacement integer value for `__VERSION__`. + ) + +$(H2 $(LEGACY_LNAME2 Special Token Sequence, special-token-sequence, Special Token Sequences)) + +$(GRAMMAR +$(GNAME SpecialTokenSequence): + $(D # line) $(GLINK IntegerLiteral) $(GLINK Filespec)$(OPT) $(GLINK EndOfLine) + $(D # line) $(D __LINE__) $(GLINK Filespec)$(OPT) $(GLINK EndOfLine) +) +$(GRAMMAR_LEX +$(GNAME Filespec): + $(B ") $(GLINK DoubleQuotedCharacters)$(OPT) $(B ") +) + + $(P Special token sequences are processed by the lexical analyzer, may + appear between any other tokens, and do not affect the syntax + parsing. + ) + + $(P Special token sequences are terminated by the first newline that + follows the first $(D #) token at the beginning of the sequence. + ) + + $(P There is currently only one special token sequence, $(D #line). + ) + + $(P This sets the line number of the next source line to $(GLINK IntegerLiteral), + and optionally the current source file name to $(GLINK Filespec), + beginning with the next line of source text. + ) + + $(P For example: + ) + +----------------- +int #line 6 "pkg/mod.d" +x; // this is now line 6 of file pkg/mod.d +----------------- + + $(IMPLEMENTATION_DEFINED + The source file and line number is typically used for printing error messages + and for mapping generated code back to the source for the symbolic + debugging output. + ) + +$(SPEC_SUBNAV_PREV_NEXT intro, Introduction, istring, Interpolation Expression Sequence) +) + +Macros: +CHAPTER = 2 +TITLE = Lexical diff --git a/spec/memory-safe-d.dd b/spec/memory-safe-d.dd new file mode 100644 index 0000000000..627cdf0563 --- /dev/null +++ b/spec/memory-safe-d.dd @@ -0,0 +1,107 @@ +Ddoc + +$(SPEC_S Memory Safety, + +$(HEADERNAV_TOC) + + $(HTMLTAG3 img, src="https://github.com/$(ROOT_DIR)images/dman-rain.jpg" align="right" alt="D-Man in rain" height="200") + + $(P $(I Memory Safety) for a program is defined as it being + impossible for the program to corrupt memory. + Therefore, the safe subset of D consists only of programming + language features that are guaranteed to never result in memory + corruption. See $(LINK2 $(ROOT_DIR)safed.html, this article) for a + rationale. + ) + + $(P Memory-safe code $(DDSUBLINK spec/function, function-safety, cannot + use certain language features), such as:) + $(UL + $(LI Casts that break the type system.) + $(LI Modification of pointer values.) + $(LI Taking the address of a local variable or function parameter.) + ) + +$(H2 $(LNAME2 usage, Usage)) + + $(P There are three categories of functions from the perspective of memory safety:) + $(UL + $(LI $(DDSUBLINK spec/function, safe-functions, `@safe`) functions) + $(LI $(DDSUBLINK spec/function, trusted-functions, `@trusted`) functions) + $(LI $(DDSUBLINK spec/function, system-functions, `@system`) functions) + ) + + $(P `@system` functions may perform any operation legal from the perspective of the language, + including inherently memory unsafe operations such as pointer casts or pointer arithmetic. + However, compile-time known memory-corrupting operations, such as indexing a static array + out of bounds or returning a pointer to an expired stack frame, can still raise an error. + `@system` functions may not be called directly from `@safe` functions.) + + $(P `@trusted` functions must have a $(DDSUBLINK spec/function, safe-interfaces, safe interface), + as they can be called from `@safe` functions. + Internally they have all the capabilities of `@system` functions. + For this reason they should be very limited in the scope of their use. Typical uses of + `@trusted` functions include wrapping system calls that take buffer pointer and length arguments separately so that + `@safe` functions may call them with arrays.) + + $(P `@safe` functions have a number of restrictions on what they may do and are intended to disallow operations that + may cause memory corruption. See $(DDSUBLINK spec/function, safe-functions, `@safe` functions).) + + $(P The `@safe` attribute $(DDSUBLINK spec/function, function-attribute-inference, can be inferred) when the compiler has the function body available, such as with templates.) + + $(P Array bounds checks are necessary to enforce memory safety, so + these are enabled (by default) for `@safe` code even in $(B -release) mode. + ) + + $(H3 $(LNAME2 scope-return-params, Scope and Return Parameters)) + + $(P The function parameter attributes `return` and `scope` are used to track what happens to low-level pointers + passed to functions. Such pointers include: raw pointers, arrays, `this`, classes, `ref` parameters, delegate/lazy parameters, + and aggregates containing a pointer.) + + $(P The $(DDSUBLINK spec/function, return-ref-parameters, `return ref`) attributes on a parameter indicate:) + + * A pointer derived from the parameter's address may be returned from the function + (e.g. returning the parameter by reference). + * A pointer derived from the parameter's address may be stored in the first parameter of + a function returning `void`, *iff* the first parameter is `ref`. + The `this` reference is considered the first parameter of a method. + + $(P $(D scope) ensures that no references to the pointed-to object are retained, in global variables or pointers passed to the + function (and recursively to other functions called in the function), as a result of calling the function. + Variables in the function body and parameter list that are `scope` may have their allocations elided as a result.) + + $(P The $(DDSUBLINK spec/function, return-scope-parameters, `return scope`) attributes on a parameter indicate:) + + * A pointer derived from that parameter may be returned from the function. + * A pointer derived from that parameter may be stored in the first parameter of + a function returning `void`, *iff* the first parameter is `ref`. + The `this` reference is considered the first parameter of a method. + + $(RATIONALE The second case is to support UFCS, + property setters and non-member functions (e.g. `put` used like `put(dest, source)`).) + + $(P These attributes may appear after the formal parameter list of a method, + in which case they apply to the `this` reference. + For constructors, `return` applies to the (implicitly returned) `this` reference.) + + $(P `return` or `scope` is ignored when applied to a type that is not a low-level pointer.) + + $(P $(B Note:) Checks for `scope` parameters are currently enabled + only for `@safe` code compiled with the `-dip1000` command-line flag.) + + +$(H2 $(LNAME2 limitations, Limitations)) + + $(P Memory safety does not imply that code is portable, uses only + sound programming practices, is free of byte order dependencies, + or other bugs. It is focussed only on eliminating memory corruption + possibilities. + ) + +$(SPEC_SUBNAV_PREV_NEXT entity, Named Character Entities, abi, Application Binary Interface) +) + +Macros: + CHAPTER=38 + TITLE=Memory-Safe-D-Spec diff --git a/spec/module.dd b/spec/module.dd new file mode 100644 index 0000000000..8d7ceebbd8 --- /dev/null +++ b/spec/module.dd @@ -0,0 +1,743 @@ +Ddoc + +$(SPEC_S Modules, + +$(HEADERNAV_TOC) + +$(GRAMMAR +$(GNAME Module): + $(GLINK ModuleDeclaration) + $(GLINK ModuleDeclaration) $(GLINK DeclDefs) + $(GLINK DeclDefs) + +$(GNAME DeclDefs): + $(GLINK DeclDef) + $(GLINK DeclDef) $(GSELF DeclDefs) + +$(GNAME DeclDef): + $(GLINK2 attribute, AttributeSpecifier) + $(GLINK2 declaration, Declaration) + $(GLINK2 class, Constructor) + $(GLINK2 class, Destructor) + $(GLINK2 struct, Postblit) + $(GLINK2 class, Invariant) + $(GLINK2 unittest, UnitTest) + $(GLINK2 class, AliasThis) + $(GLINK2 class, StaticConstructor) + $(GLINK2 class, StaticDestructor) + $(GLINK2 class, SharedStaticConstructor) + $(GLINK2 class, SharedStaticDestructor) + $(GLINK2 version, ConditionalDeclaration) + $(GLINK2 version, DebugSpecification) + $(GLINK2 version, VersionSpecification) + $(GLINK MixinDeclaration) + $(GLINK EmptyDeclaration) + +$(GNAME EmptyDeclaration): + $(D ;) +) + +$(P Modules have a one-to-one correspondence with source files. When not +explicitly set via a $(GLINK ModuleDeclaration), a module's name defaults +to the name of the file stripped of its path and extension.) + +$(P A module's name automatically acts as a namespace scope for its contents. Modules +superficially resemble classes, but differ in that:) + +$(UL + $(LI Only one instance of a module exists, and it is + statically allocated.) + + $(LI Modules do not have virtual tables.) + + $(LI Modules do not inherit, do not have super modules, etc.) + + $(LI A source file may contain only one module.) + + $(LI Symbols in a module can be imported.) + + $(LI Modules are always compiled at global scope and are unaffected + by surrounding attributes or other modifiers.) +) + +$(P Modules can be grouped into hierarchies called $(I packages).) + +$(P Modules offer several guarantees:) + +$(UL + + $(LI The order in which modules are imported does not affect their + semantics.) + + $(LI The semantics of a module are not affected by the scope in which + it is imported.) + + $(LI If a module $(D C) imports modules $(D A) and $(D B), any modifications + to $(D B) will not silently change code in $(D C) that is dependent on $(D A).) +) + +$(H2 $(LNAME2 module_declaration, Module Declaration)) + +$(P The $(I ModuleDeclaration) sets the name of the module and what package it +belongs to. If absent, the module name is taken to be the same name (stripped of +path and extension) of the source file name.) + +$(GRAMMAR +$(GNAME ModuleDeclaration): + $(GLINK ModuleAttributes)$(OPT) $(D module) $(GLINK ModuleFullyQualifiedName) $(D ;) + +$(GNAME ModuleAttributes): + $(GLINK ModuleAttribute) + $(GLINK ModuleAttribute) $(GSELF ModuleAttributes) + +$(GNAME ModuleAttribute): + $(GLINK2 attribute, DeprecatedAttribute) + $(GLINK2 attribute, UserDefinedAttribute) + +$(GNAME ModuleFullyQualifiedName): + $(GLINK ModuleName) + $(GLINK Packages) $(D .) $(GLINK ModuleName) + +$(GNAME ModuleName): + $(GLINK_LEX Identifier) +) +$(GRAMMAR +$(GNAME Packages): + $(GLINK PackageName) + $(GSELF Packages) $(D .) $(GLINK PackageName) + +$(GNAME PackageName): + $(GLINK_LEX Identifier) +) + +$(P The $(I Identifier)s preceding the rightmost $(I Identifier) are the $(I Packages) that the +module is in. The packages correspond to directory names in the source file +path. Package and module names cannot be $(GLINK_LEX Keyword)s.) + +$(P If present, the $(I ModuleDeclaration) must be the first and only such declaration +in the source file, and may be preceded only by comments and $(D #line) directives.) + +$(P Example:) + +--------- +module c.stdio; // module stdio in the c package +--------- + +$(P By convention, package and module names are all lower case. This is because +these names have a one-to-one correspondence with the operating system's +directory and file names, and many file systems are not case sensitive. Using all +lower case package and module names will avoid or minimize problems when moving projects +between dissimilar file systems.) + +$(P If the file name of a module is an invalid module name (e.g. +`foo-bar.d`), use a module declaration to set a valid module name:) + +--------- +module foo_bar; +--------- + + $(IMPLEMENTATION_DEFINED + $(OL + $(LI The mapping of package and module identifiers to directory and file names.) + )) + + $(BEST_PRACTICE + $(OL + $(LI $(GLINK PackageName)s and $(GLINK ModuleName)s should be composed of the ASCII + characters lower case letters, digits or `_` to ensure maximum portability and compatibility with + various file systems.) + $(LI The file names for packages and modules should be composed only of + the ASCII lower case letters, digits, and `_`s, and should not be a $(GLINK_LEX Keyword).) + )) + +$(H3 $(LNAME2 deprecated_modules, Deprecated modules)) + +$(P A $(I ModuleDeclaration) can have an optional $(GLINK2 attribute, +DeprecatedAttribute). The compiler will produce a message when the deprecated +module is imported.) + +--------- +deprecated module foo; +--------- + +--------- +module bar; +import foo; // Deprecated: module foo is deprecated +--------- + +$(P A $(I DeprecatedAttribute) can have an optional $(ASSIGNEXPRESSION) argument to provide a +more informative message. The $(I AssignExpression) must evaluate to a string at compile time. +) + +--------- +deprecated("Please use foo2 instead.") +module foo; +--------- + +--------- +module bar; +import foo; // Deprecated: module foo is deprecated - Please use foo2 instead. +--------- + + $(IMPLEMENTATION_DEFINED + $(OL + $(LI How the deprecation messages are presented to the user.) + )) + + +$(H2 $(LEGACY_LNAME2 ImportDeclaration, import-declaration, Import Declaration)) + +$(P Symbols from one module are made available in another module by using the +$(I ImportDeclaration):) + +$(GRAMMAR +$(GNAME ImportDeclaration): + $(D import) $(GLINK ImportList) $(D ;) + $(D static import) $(GLINK ImportList) $(D ;) + +$(GNAME ImportList): + $(GLINK Import) + $(GLINK ImportBindings) + $(GLINK Import) $(D ,) $(GSELF ImportList) + +$(GNAME Import): + $(GLINK ModuleFullyQualifiedName) + $(GLINK ModuleAliasIdentifier) $(D =) $(GLINK ModuleFullyQualifiedName) + +$(GNAME ImportBindings): + $(GLINK Import) $(D :) $(GLINK ImportBindList) + +$(GNAME ImportBindList): + $(GLINK ImportBind) + $(GLINK ImportBind) $(D ,) $(GSELF ImportBindList) + +$(GNAME ImportBind): + $(GLINK_LEX Identifier) + $(GLINK_LEX Identifier) $(D =) $(GLINK_LEX Identifier) + +$(GNAME ModuleAliasIdentifier): + $(GLINK_LEX Identifier) +) + +$(P There are several forms of the $(I ImportDeclaration), from generalized to +fine-grained importing.) + +$(P The order in which $(I ImportDeclaration)s occur has no significance.) + +$(P $(I ModuleFullyQualifiedName)s in the $(I ImportDeclaration) must be fully +qualified with whatever packages they are in. They are not considered to be +relative to the module that imports them.) + + $(IMPLEMENTATION_DEFINED + $(OL + $(LI How the compiler resolves the package and module identifiers in an + import declaration to its corresponding source files.) + )) + +$(H3 $(LNAME2 name_lookup, Symbol Name Lookup)) + +$(P The simplest form of importing is to just list the modules being imported:) + +--------- +module myapp.main; + +import std.stdio; // import module stdio from package std + +class Foo : BaseClass +{ + import myapp.foo; // import module myapp.foo in this class' scope + void bar () + { + import myapp.bar; // import module myapp.bar in this function' scope + writeln("hello!"); // calls std.stdio.writeln + } +} +--------- + +$(P When a symbol name is used unqualified, a two-phase lookup is used. +First, the module scope is searched, starting from the innermost scope. +For example, in the previous example, while looking for `writeln`, +the order will be:) + +$(UL + $(LI Declarations inside `bar`.) + $(LI Declarations inside `Foo`.) + $(LI Declarations inside `BaseClass`.) + $(LI Declarations at module scope.) +) + +$(P If the first lookup isn't successful, a second one is performed on imports. +In the second lookup phase inherited scopes are ignored. This includes the scope of +base classes and interfaces (in this example, `BaseClass`'s imports +would be ignored), as well as imports in mixed-in $(D template).) + +$(P Symbol lookup stops as soon as a matching symbol is found. If two symbols with the +same name are found at the same lookup phase, this ambiguity will result in a +compilation error.) + +--- +module A; +void foo(); +void bar(); +--- + +--- +module B; +void foo(); +void bar(); +--- + +--- +module C; +import A; +void foo(); +void test() +{ + foo(); // C.foo() is called, it is found before imports are searched + bar(); // A.bar() is called, since imports are searched +} +--- + +--- +module D; +import A; +import B; +void test() +{ + foo(); // error, A.foo() or B.foo() ? + A.foo(); // ok, call A.foo() + B.foo(); // ok, call B.foo() +} +--- + +--- +module E; +import A; +import B; +alias foo = B.foo; +void test() +{ + foo(); // call B.foo() + A.foo(); // call A.foo() + B.foo(); // call B.foo() +} +--- + +$(H3 $(LNAME2 public_imports, Public Imports)) + +$(P By default, imports are $(I private). This means that if module A imports +module B, and module B imports module C, then names inside C are visible only inside +B and not inside A.) + +$(P An import can be explicitly declared $(I public), which will cause +names from the imported module to be visible to further imports. So in the above +example where module A imports module B, if module B $(I publicly) imports +module C, names from C will be visible in A as well.) + +$(P All symbols from a publicly imported module are also aliased in the +importing module. Thus in the above example if C contains the name foo, it will +be accessible in A as $(D foo), $(D B.foo) and $(D C.foo).) + +$(P For another example:) + +--- +module W; +void foo() { } +--- + +--- +module X; +void bar() { } +--- + +--- +module Y; +import W; +public import X; +... +foo(); // calls W.foo() +bar(); // calls X.bar() +--- + +--- +module Z; +import Y; +... +foo(); // error, foo() is undefined +bar(); // ok, calls X.bar() +X.bar(); // ditto +Y.bar(); // ok, Y.bar() is an alias to X.bar() +--- + +$(H3 $(LNAME2 static_imports, Static Imports)) + +$(P A static import requires the use of a fully qualified name +to reference the module's names:) + +--- +static import std.stdio; + +void main() +{ + writeln("hello!"); // error, writeln is undefined + std.stdio.writeln("hello!"); // ok, writeln is fully qualified +} +--- + +$(H3 $(LNAME2 renamed_imports, Renamed Imports)) + +$(P A local name for an import can be given, through which all references to the +module's symbols must be qualified with:) + +$(RUNNABLE_EXAMPLE +--- +import io = std.stdio; + +void main() +{ + io.writeln("hello!"); // ok, calls std.stdio.writeln + std.stdio.writeln("hello!"); // error, std is undefined + writeln("hello!"); // error, writeln is undefined +} +--- +) + + $(BEST_PRACTICE Renamed imports are handy when dealing with very long import names.) + +$(H3 $(LNAME2 selective_imports, Selective Imports)) + +$(P Specific symbols can be exclusively imported from a module and bound into +the current namespace:) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +import std.stdio : writeln, foo = write; + +void main() +{ + std.stdio.writeln("hello!"); // error, std is undefined + writeln("hello!"); // ok, writeln bound into current namespace + write("world"); // error, write is undefined + foo("world"); // ok, calls std.stdio.write() + fwritefln(stdout, "abc"); // error, fwritefln undefined +} +--- +) + +$(P $(D static) cannot be used with selective imports.) + +$(H3 $(LNAME2 renamed_selective_imports, Renamed and Selective Imports)) + +$(P When renaming and selective importing are combined:) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +------------ +import io = std.stdio : foo = writeln; + +void main() +{ + writeln("bar"); // error, writeln is undefined + std.stdio.foo("bar"); // error, foo is bound into current namespace + std.stdio.writeln("bar"); // error, std is undefined + foo("bar"); // ok, foo is bound into current namespace, + // FQN not required + io.writeln("bar"); // ok, io=std.stdio bound the name io in + // the current namespace to refer to the entire + // module + io.foo("bar"); // error, foo is bound into current namespace, + // foo is not a member of io +} +-------------- +) + +$(H3 $(LNAME2 scoped_imports, Scoped Imports)) + +$(P Import declarations may be used at any scope. For example:) + +$(RUNNABLE_EXAMPLE +-------------- +void main() +{ + import std.stdio; + writeln("bar"); +} +-------------- +) + +$(P The imports are looked up to satisfy any unresolved symbols at that scope. +Imported symbols may hide symbols from outer scopes.) + +$(P In function scopes, imported symbols only become visible after the import +declaration lexically appears in the function body. In other words, imported +symbols at function scope cannot be forward referenced.) + +$(RUNNABLE_EXAMPLE +-------------- +void main() +{ + void writeln(string) {} + void foo() + { + writeln("bar"); // calls main.writeln + import std.stdio; + writeln("bar"); // calls std.stdio.writeln + void writeln(string) {} + writeln("bar"); // calls main.foo.writeln + } + writeln("bar"); // calls main.writeln + std.stdio.writeln("bar"); // error, std is undefined +} +-------------- +) + +$(H2 $(LNAME2 module_scope_operators, Module Scope Operator)) + + $(P A leading dot (`.`) causes the + identifier to be looked up in the module scope.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +const int x = 1; + +void main() +{ + int x = 5; + assert(x == 5); // main.x, not global x + assert(.x == 1); // global x +} +--------- +) + + +$(H2 $(LNAME2 staticorder, Static Construction and Destruction)) + + $(P Static constructors are executed to initialize a module's state. + Static destructors terminate a module's state. + ) + + $(P A module may have multiple static constructors and static destructors. + The static constructors are run in lexical order, the static destructors + are run in reverse lexical order.) + + $(P Non-shared static constructors and destructors are + run whenever threads are created or destroyed, including the main thread.) + + $(P Shared static constructors are run once before `main()` is called. + Shared static destructors are run after the `main()` function returns. + ) + + --- + import resource; + + Resource x; + shared Resource y; + __gshared Resource z; + + static this() // non-shared static constructor + { + x = acquireResource(); + } + + shared static this() // shared static constructor + { + y = acquireSharedResource(); + z = acquireSharedResource(); + } + + static ~this() // non-shared static destructor + { + releaseResource(x); + } + + shared static ~this() // shared static destructor + { + releaseSharedResource(y); + releaseSharedResource(z); + } + --- + + $(BEST_PRACTICE + $(OL + $(LI Shared static constructors and destructors are used to initialize and terminate + shared global data.) + $(LI Non-shared static constructors and destructors are used to initialize and terminate + thread local data.) + )) + +$(H3 $(LNAME2 order_of_static_ctor, Order of Static Construction)) + +$(P Shared static constructors on all modules are run before any non-shared static +constructors.) + +$(P The order of static initialization is implicitly determined by the $(I +import) declarations in each module. Each module is assumed to depend on any +imported modules being statically constructed first. +There is no other order imposed on the execution of module static constructors.) + +$(P Cycles (circular dependencies) in the import declarations are allowed so +long as neither, or one, but not both, of the modules, contains static constructors or static +destructors. Violation of this rule will result in a runtime exception.) + + $(IMPLEMENTATION_DEFINED + $(OL + $(LI An implementation may provide a means of overriding the cycle detection abort. + A typical method uses the D Runtime switch + `--DRT-oncycle=...` where the following behaviors are supported: + $(OL + $(LI `abort` The default behavior. The normal behavior as described + in the previous section.) + $(LI `print` Print all cycles detected, but do not abort execution. + When cycles are present, the order of static construction is + implementation defined, and not guaranteed to be valid.) + $(LI `ignore` Do not abort execution or print any cycles. When + cycles are present, the order of static construction is implementation + defined, and not guaranteed to be valid.) + ) + )) + ) + + $(BEST_PRACTICE + $(OL + $(LI Avoid cyclical imports where practical. They can be an indication of poor + decomposition of a program's structure into independent modules. Two modules + that import each other can often be reorganized into three modules without + cycles, where the third contains the declarations needed by the other two.) + ) + ) + +$(H3 $(LNAME2 order_of_static_ctors, Order of Static Construction within a Module)) + +$(P Within a module, static construction occurs in the lexical order in +which they appear.) + +$(H3 $(LNAME2 order_static_dtor, Order of Static Destruction)) + +$(P This is defined to be in exactly the reverse order of static construction. +Static destructors for individual modules will only be run if the +corresponding static constructor successfully completed.) + +$(P Shared static destructors are executed after static destructors.) + +$(H2 $(LNAME2 order_of_unittests, Order of Unit tests)) + +$(P Unit tests are run in the lexical order in which they appear within a +module.) + +$(H2 $(LEGACY_LNAME2 MixinDeclaration, mixin-declaration, Mixin Declaration)) + +$(GRAMMAR +$(GNAME MixinDeclaration): + $(D mixin) $(D $(LPAREN)) $(GLINK2 expression, ArgumentList) $(D $(RPAREN)) $(D ;) +) + +$(P Each $(GLINK2 expression, AssignExpression) in the $(I ArgumentList) is + evaluated at compile time, and the result must be representable + as a string. + The resulting strings are concatenated to form a string. + The text contents of the string must be compilable as valid + $(GLINK DeclDefs), and is compiled as such.) + +$(P The content of a mixin cannot be forward referenced by other *DeclDefs* of + the same scope because it is not yet pulled into the AST.) + +--------- +class B : A {} // Error: undefined identifier `A` +mixin ("class A {}"); +--------- + +$(P Forward references may only work in function bodies because they + are processed after the declarations:) + +--------- +void v() +{ + class B : A {} +} +mixin ("class A {}"); +--------- + +$(H2 $(LEGACY_LNAME2 PackageModule, package-module, Package Module)) + +$(P A package module can be used to publicly import other modules, while +providing a simpler import syntax. This enables the conversion of a module into a package +of modules, without breaking existing code which uses that module. Example of a +set of library modules:) + +$(B libweb/client.d:) + +--------- +module libweb.client; + +void runClient() { } +--------- + +$(B libweb/server.d:) + +--------- +module libweb.server; + +void runServer() { } +--------- + +$(B libweb/package.d:) + +--------- +module libweb; + +public import libweb.client; +public import libweb.server; +--------- + +$(P The package module's file name must be $(D package.d). The module name +is declared to be the fully qualified name of the package. Package modules can +be imported just like any other modules:) + +$(B test.d:) + +--------- +module test; + +// import the package module +import libweb; + +void main() +{ + runClient(); + runServer(); +} +--------- + +$(P A package module can be nested inside of a sub-package:) + +$(B libweb/utils/package.d:) + +--------- +// must be declared as the fully qualified name of the package, not just 'utils' +module libweb.utils; + +// publicly import modules from within the 'libweb.utils' package. +public import libweb.utils.conv; +public import libweb.utils.text; +--------- + +$(P The package module can then be imported with the standard module import +declaration:) + +$(B test.d:) + +--------- +module test; + +// import the package module +import libweb.utils; + +void main() { } +--------- + +$(SPEC_SUBNAV_PREV_NEXT grammar, Grammar, declaration, Declarations) +) + +Macros: + CHAPTER=5 + TITLE=Modules + _= diff --git a/spec/ob.dd b/spec/ob.dd new file mode 100644 index 0000000000..5d49975618 --- /dev/null +++ b/spec/ob.dd @@ -0,0 +1,382 @@ +Ddoc + +$(SPEC_S Live Functions, + +$(HEADERNAV_TOC) + +$(B Experimental, Subject to Change, use `-preview=dip1021` to activate) + +$(H2 $(LNAME2 ownership, Ownership)) + +$(P If a memory object has only one pointer to it, that pointer is the $(I owner) +of the memory object. With the single owner, it becomes straightforward to +manage the memory for the object. It also becomes trivial to synchronize access +to that memory object among multiple threads, because it can only be accessed +by the thread that controls that single pointer. +) + +$(P This can be generalized to a graph of memory objects interconnected by pointers, +where only a single pointer connects to that graph from elsewhere. That single +pointer becomes the $(I owner) of all the memory objects in that graph. +) + +$(P When the owner of the graph is no longer needed, then the graph of memory +objects it points to is no longer needed and can be safely disposed of. If the owner +itself is no longer in use (i.e. is no longer $(I live)) and the owned memory +objects are not disposed of, an error can be diagnosed. +) + +$(P Hence, the following errors can be statically detected: +) + +--- +int* allocate(); // allocate a memory object +void release(int*); // deallocate a memory object + +@live void test() +{ + auto p = allocate(); +} // error: p is not disposed of + +@live void test() +{ + auto p = allocate(); + release(p); + release(p); // error: p was already disposed of +} + +@live void test() +{ + int* p = void; + release(p); // error, p does not have a defined value +} + +@live void test() +{ + auto p = allocate(); + p = allocate(); // error: p was not disposed of + release(p); +} +--- + +$(P Functions with the `@live` attribute enable diagnosing these sorts of errors by +tracking the status of owner pointers. +) + + +$(H2 $(LNAME2 ob, Borrowing)) + +$(P Tracking the ownership status of a pointer can be safely extended by adding the +capability of temporarilly $(I borrowing) ownership of a pointer from the $(I owner). +The $(I owner) can no longer use the pointer as long as the $(I borrower) is still +using the pointer value (i.e. it is $(I live)). Once the $(I borrower) is no longer +$(I live), the $(I owner) can resume using it. Only one $(I borrower) can be live +at any point. +) + +$(P Multiple $(I borrower) pointers can simultaneously exist if all of them are +pointers to read only (`const` or `immutable`) data, i.e. none of them can modify the memory +object(s) pointed to. +) + +$(P This is collectively called an $(I Ownership/Borrowing) system. It can be stated as: +) + +$(BLOCKQUOTE At any point in the program, for each memory object, +there is exactly one live mutable pointer to it or all the live pointers to +it are read-only.) + + +$(H2 $(LNAME2 live, `@live` attribute)) + +$(P Function declarations annotated with the `@live` attribute are checked for compliance with +the Ownership/Borrowing rules. The checks are run after other semantic processing is complete. +The checking does not influence code generation. +) + +$(P Whether a pointer is allocated memory using the GC or some other +storage allocator is immaterial to OB, they are not distinguished and are +handled identically. +) + +$(P Class references are assumed to be allocated using either the GC or are allocated +on the stack as `scope` classes, and are not tracked. +) + +$(P If `@live` functions +call non-`@live` functions, those called functions are expected to present +an `@live` compatible interface, although it is not checked. +if non-`@live` functions call `@live` functions, arguments passed are +expected to follow `@live` conventions. +) + +$(P It will not detect attempts to dereference `null` pointers or possibly +`null` pointers. This is unworkable because there is no current method +of annotating a type as a non-`null` pointer. +) + +$(H3 $(LNAME2 tracked, Tracked Pointers)) + +$(P The only pointers that are tracked are those declared in the `@live` function +as `this`, function parameters or local variables. Variables from other +functions are not tracked, even `@live` ones, as the analysis of interactions +with other functions depends +entirely on that function signature, not its internals. +Parameters that are `const` are not tracked. +) + + +$(H3 $(LNAME2 state, Pointer States)) + +$(P Each tracked pointer is in one of the following states: +) + +$(DL +$(DT Undefined) + +$(DD The pointer is in an invalid state. Dereferencing such a pointer is +an error.) + +$(DT Owner) + +$(DD The owner is the sole pointer to a memory object graph. +An Owner pointer normally does not have a `scope` attribute. +If a pointer with the `scope` attribute is initialized +with an expression not derived from a tracked pointer, it is an Owner. + +If an Owner pointer is assigned to another Owner pointer, the +former enters the Undefined state. + +--- +void consume(int* o); // o is owner + +@live int* f(int* p) // p is owner +{ + writeln(*p); + // transfer ownership to `consume` + consume(p); + // p is now undefined + //writeln(*p); // error + + int* q = new int; // q is owner + writeln(*q); + p = q; // transfer ownership + // q is now undefined + //writeln(*q); // error + writeln(*p); + return p; +} +--- +) + +$(DT Borrowed) + +$(DD A Borrowed pointer is one that temporarily becomes the sole live pointer +to a memory object graph. It enters that state via assignment +from an owner pointer or another borrowed pointer, and stays in that state +until its last use. + +A Borrowed pointer must be `scope` and must +be a pointer to mutable. +A mutable `scope` pointer function parameter is a Borrowed pointer. + +--- +void consume(int* o); // o is owner +void borrow(scope int* b); // b is borrowed + +@live void g(scope int* p) // p is borrowed +{ + //consume(p); // error, p is not owner + borrow(p); + + // lend p to q + int* q = p; // q is inferred as scope + // <-- using p here would end q's lifetime + writeln(*q); + // lifetime of q ends before p is used + writeln(*p); // OK +} +--- +) + +$(DT Readonly) + +$(DD A Readonly pointer acquires its value from an Owner or Borrowed pointer. +While the Readonly pointer is live, only Readonly pointers can +be acquired from that Owner. +A Readonly pointer must be `scope` and also +must not be a pointer to mutable. + +--- +@live void h(scope int* p) +{ + // acquire 2 read only pointers + const q = p; + const r = q; + // <-- borrowing or using p here would end q and r's lifetime + + // both q and r are live + writeln(*q); + writeln(*r); + // using p ends all its read only pointer lifetimes + writeln(*p); + //writeln(*q); // error +} +--- +) +) + +$(H3 $(LNAME2 lifetime, Lifetimes)) + +$(P The lifetime of a Borrowed or Readonly pointer value starts when it is +assigned a value from an Owner or another Borrowed pointer, and ends at +the last read of that value. +) + +$(P This is also known as $(I Non-Lexical Lifetimes). +) + + +$(H3 $(LNAME2 transition, Pointer State Transitions)) + +$(P A pointer changes its state when one of these operations is done to it: +) + +$(UL +$(LI storage is allocated for it (such as a local variable on the stack), +which places the pointer in the Undefined state) + +$(LI initialization (treated as assignment)) + +$(LI assignment - the source and target pointers change state based on what +states they are in and their types and storage classes) + +$(LI passed to an `out` function parameter (changes state after the function returns), +treated the same as initialization) + +$(LI passed by `ref` to a function parameter, treated as an assignment to a Borrow or a Readonly +depending on the storage class and type of the parameter) + +$(LI returned from a function) + +$(LI it is passed by value to a function parameter, which is +treated as an assignment to that parameter.) + +$(LI it is implicitly passed by ref as a closure variable to a nested function) + +$(LI the address of the pointer is taken, which is treated as assignment to whoever +receives the address) + +$(LI the address of any part of the memory object graph is taken, which is +treated as assignment to whoever receives that address) + +$(LI a pointer value is read from any part of the memory object graph, +which is treated as assignment to whoever receives that pointer) + +$(LI merging of control flow reconciles the state of each variable based on the +states they have from each edge) +) + +$(H3 $(LNAME2 borrower, Borrowers can be Owners)) + +$(P Borrowers are considered Owners if they are initialized from other than +a pointer. +) + +--- +@live void uhoh() +{ + scope p = malloc(); // p is considered an Owner + scope const pc = malloc(); // pc is not considered an Owner +} // dangling pointer pc is not detected on exit + +--- + +$(H3 $(LNAME2 exception, Exceptions)) + +$(P The analysis assumes no exceptions are thrown. +) + +--- +@live void leaky() +{ + auto p = malloc(); + pitcher(); // throws exception, p leaks + free(p); +} +--- + +$(P One solution is to use `scope(exit)`: +) + +--- +@live void waterTight() +{ + auto p = malloc(); + scope(exit) free(p); + pitcher(); +} +--- + +$(P or use RAII objects or call only `nothrow` functions. +) + +$(H3 $(LNAME2 lazy, Lazy Parameters)) + +$(P Lazy parameters are not considered. +) + +$(H3 $(LNAME2 mempool, Mixing Memory Pools)) + +$(P Conflation of different memory pools: +) + +--- +void* xmalloc(size_t); +void xfree(void*); + +void* ymalloc(size_t); +void yfree(void*); + +auto p = xmalloc(20); +yfree(p); // should call xfree() instead +--- +$(P is not detected. +) + +$(P This can be mitigated by using type-specific pools: +) + +--- +U* umalloc(); +void ufree(U*); + +V* vmalloc(); +void vfree(V*); + +auto p = umalloc(); +vfree(p); // type mismatch +--- + +$(P and perhaps disabling implicit conversions to `void*` in `@live` functions. +) + +$(H3 $(LNAME2 vargs, Variadic Function Arguments)) + +$(P Arguments to variadic functions (such as `printf`) are considered to be consumed. +) + + +$(H2 $(LNAME2 references, References)) + +$(OL +$(LI $(LINK2 https://bartoszmilewski.com/2009/06/02/race-free-multithreading-ownership, Race-free Multithreading: Ownership)) +) + + +$(SPEC_SUBNAV_PREV_NEXT importc, ImportC, windows, Windows Programming) +) + +Macros: + CHAPTER=43 + TITLE=Live Functions diff --git a/spec/objc_interface.dd b/spec/objc_interface.dd new file mode 100644 index 0000000000..407611247c --- /dev/null +++ b/spec/objc_interface.dd @@ -0,0 +1,600 @@ +Ddoc + +$(SPEC_S Interfacing to Objective-C, + +$(HEADERNAV_TOC) + + $(P + D supports interfacing with Objective-C. It supports protocols, classes, + subclasses, instance variables, instance methods and class methods. + Platform support might vary between different compilers. + ) + + $(P + Fully working example is available at + $(LINK2 #usage-example, the bottom). + ) + + $(SECTION2 $(LNAME2 classes, Classes)) + + $(SECTION3 $(LNAME2 external-class, Declaring an External Class)) + + --- + import core.attribute : selector; + + extern (Objective-C) + extern class NSString + { + const(char)* UTF8String() @selector("UTF8String"); + } + --- + + $(P + All Objective-C classes that should be accessible from within D need to + be declared with the $(LINK2 #objc-linkage, Objective-C linkage). If the + class is declared as `extern` (in addition to `extern (Objective-C)`) it + is expected to be defined externally. + ) + + $(P + The $(LINK2 #selector-attribute, `@selector`) attribute indicates which + Objective-C selector should be used when calling this method. + This attribute needs to be attached to all methods with the + `Objective-C` linkage. + ) + + $(SECTION3 $(LNAME2 external-class, Binding to a @property (Accessor Methods))) + + --- + import core.attribute : selector; + + extern (Objective-C) + extern class MTLRenderPipelineDescriptor : NSObject + { + NSString label() @selector("label"); + NSString label(NSString) @selector("setLabel:"); + } + --- + + $(P + Whenever needing to bind to Objective-C classes `@property`, one must be aware + that it generates both a getter and setter. The method to get its value (getter) + is the same name as the property's name. The method to set its value (setter) + starts with the word "set" and then uses the capitalized property name. + The setter for the property `label` is `setLabel:`. + ) + + $(SECTION3 $(LNAME2 defining-class, Defining a Class)) + + --- + import core.attribute : selector; + + // externally defined + extern (Objective-C) + extern class NSObject + { + static NSObject alloc() @selector("alloc"); + NSObject init() @selector("init"); + } + + extern (Objective-C) + class Foo : NSObject + { + override static Foo alloc() @selector("alloc"); + override Foo init() @selector("init"); + + final int bar(int a) @selector("bar:") + { + return a; + } + } + + void main() + { + assert(Foo.alloc.init.bar(3) == 3); + } + --- + + $(P + Defining an Objective-C class is exactly the same as declaring an + external class but it should not be declared as `extern`. + ) + + $(P + To match the Objective-C semantics, `static` and `final` methods are + virtual. `static` methods are overridable as well. + ) + + $(SECTION2 $(LNAME2 protocols, Protocols)) + + $(SECTION3 $(LNAME2 declaring-protocol, Declaring a Protocol)) + + --- + import core.attribute : selector; + import core.stdc.stdio : printf; + + extern (Objective-C) + interface Foo + { + static void foo() @selector("foo"); + void bar() @selector("bar"); + } + + extern (Objective-C) + class Bar : Foo + { + static void foo() @selector("foo") + { + printf("foo\n"); + } + + void bar() @selector("bar") + { + printf("bar\n"); + } + } + --- + + $(P + Objective-C protocols are represented as interfaces in D and are + declared using the `interface` keyword. + ) + + $(P + All Objective-C protocols that should be accessible from within D need + to be declared with the [Objective-C linkage](#objc-linkage). + ) + + $(P + Objective-C protocols support virtual class (static) methods. These + methods must be implemented by the class that implements the protocol + (unless they are [optional](#optional-methods)). To match these + semantics, `static` methods are virtual. That also means that static + methods with Objective-C linkage, inside an interface cannot have a body. + ) + + $(SECTION3 $(LNAME2 optional-methods, Optional Methods)) + + --- + import core.attribute : optional, selector; + import core.stdc.stdio : printf; + + struct objc_selector; + alias SEL = objc_selector*; + + extern (C) SEL sel_registerName(in char* str); + + extern (Objective-C) + extern class NSObject + { + static NSObject alloc() @selector("alloc"); + NSObject init() @selector("init"); + } + + extern (Objective-C) + interface Foo + { + bool respondsToSelector(SEL sel) @selector("respondsToSelector:"); + void foo() @selector("foo"); + + // this is an optional method + @optional void bar() @selector("bar"); + } + + extern (Objective-C) + class Bar : NSObject, Foo + { + override static Bar alloc() @selector("alloc"); + override Bar init() @selector("init"); + + bool respondsToSelector(SEL sel) @selector("respondsToSelector:"); + + void foo() @selector("foo") + { + printf("foo\n"); + } + } + + void main() + { + Foo f = Bar.alloc.init; + + // check, at runtime, if the instance `f` implements the method `bar` + if (f.respondsToSelector(sel_registerName("bar"))) + f.bar(); + else + f.foo(); + } + --- + $(P + Objective-C protocols support optional methods. Optional methods are + **not** required to be implemented by the class that implements the + protocol. To safely call an optional method, a runtime check should be + performed to make sure the receiver implements the method. + ) + + $(P + In D, optional methods are represented using the + [`@optional`](#optional-attribute) attribute. + ) + + $(SECTION2 $(LNAME2 instance-variables, Instance Variables)) + + --- + import core.attribute : selector; + + // externally defined + extern (Objective-C) + extern class NSObject + { + static NSObject alloc() @selector("alloc"); + NSObject init() @selector("init"); + } + + extern (Objective-C) + class Foo : NSObject + { + int bar_; + + override static Foo alloc() @selector("alloc"); + override Foo init() @selector("init"); + + int bar() @selector("bar") + { + return bar_; + } + } + + void main() + { + auto foo = Foo.alloc.init; + foo.bar_ = 3; + assert(foo.bar == 3); + } + --- + + $(P + Declaring an instance variable looks exactly the same as for a regular + D class. + ) + + $(P + To solve the fragile base class problem, instance variables in + Objective-C has a dynamic offset. That means that the base class can + change (add or remove instance variables) without the subclasses needing + to recompile or relink. Thanks to this feature it's not necessary to + declare instance variables when creating bindings to Objective-C classes. + ) + + $(SECTION2 $(LNAME2 instance-method, Calling an Instance Method)) + + $(P + Calling an Objective-C instance method uses the same syntax as calling + regular D methods: + ) + + --- + const(char)* result = object.UTF8String(); + --- + + $(P + When the compiler sees a call to a method with Objective-C linkage it + will generate a call similar to how an Objective-C compiler would call + the method. + ) + + $(SECTION2 $(LNAME2 selector-attribute, The `@selector` Attribute)) + + $(P + The `@selector` attribute is a compiler recognized + $(LINK2 attribute.html#uda, UDA). It is used to tell the compiler which + selector to use when calling an Objective-C method. + ) + + $(P + Selectors in Objective-C can contain the colon character, which is not valid in D + identifiers. D supports method overloading while Objective-C + achieves something similar by using different selectors. For these two + reasons it is better to be able to specify the selectors manually in D, + instead of trying to infer it. This allows to have a more natural names + for the methods in D. Example: + ) + + --- + import core.attribute : selector; + + extern (Objective-C) + extern class NSString + { + NSString initWith(in char*) @selector("initWithUTF8String:"); + NSString initWith(NSString) @selector("initWithString:"); + } + --- + + $(P + Here the method `initWith` is overloaded with two versions, one + accepting `in char*`, the other one `NSString`. These two methods are + mapped to two different Objective-C selectors, `initWithUTF8String:` + and `initWithString:`. + ) + + $(P + The attribute is defined in druntime in + $(DPLLINK phobos/core_attribute.html, `core.attribute`). The attribute + is only defined when the version identifier + $(LINK2 #objc-version-identifier, `D_ObjectiveC`) is enabled. + ) + + $(SECTION3 $(LNAME2 compiler-checks, Compiler Checks)) + + $(P + The compiler performs the following checks to enforce the correct usage + of the `@selector` attribute: + ) + + $(UL + $(LI + The attribute can only be attached to methods with Objective-C + linkage + ) + + $(LI The attribute can only be attached once to a method) + $(LI The attribute cannot be attached to a template method) + + $(LI + The number of colons in the selector needs to match the number of + parameters the method is declared with + ) + ) + + $(P If any of the checks fail, a compile error will occur.) + + $(SECTION2 $(LNAME2 optional-attribute, The `@optional` Attribute)) + + $(P + The `@optional` attribute is a compiler recognized + $(LINK2 attribute.html#uda, UDA). It is used to tell the compiler that a + method, with Objective-C linkage, declared inside an interface is + optional. That means that the class that implements the interface does + **not** have to implement the method. + ) + + $(P + To safely call an optional method, a runtime check should be performed + to make sure the receiver implements the method. + ) + + $(P + The attribute is defined in druntime in + $(DPLLINK phobos/core_attribute.html, `core.attribute`). The attribute + is only defined when the version identifier + [`D_ObjectiveC`](#objc-version-identifier) is enabled. + ) + + $(SECTION3 $(LNAME2 compiler-checks, Compiler Checks)) + + $(P + The compiler performs the following checks to enforce the correct usage + of the `@optional` attribute: + ) + + * The attribute can only be attached to methods with Objective-C linkage + * The attribute can only be attached to a method inside an interface + * The attribute can only be attached once to a method + * The attribute cannot be attached to a template method + + $(P If any of the checks fail, a compile error will occur.) + + $(SECTION2 + $(LNAME2 objc-version-identifier, The `D_ObjectiveC` Version Identifier) + ) + + $(P + The `D_ObjectiveC` version identifier is a predefined version + identifier. It is enabled if Objective-C support is available for the + target. + ) + + $(SECTION2 $(LNAME2 objc-linkage, Objective-C Linkage)) + + $(P + Objective-C linkage is achieved by attaching the `extern (Objective-C)` + attribute to a class. Example: + ) + + --- + import core.attribute : selector; + + extern (Objective-C) + extern class NSObject + { + NSObject init() @selector("init"); + } + --- + + $(P + All methods inside a class declared as `extern (Objective-C)` will + get implicit Objective-C linkage. + ) + + $(P + The linkage is recognized on all platforms but will issue a compile + error if it is used on a platform where Objective-C support is not + available. This allows to easily hide Objective-C declarations from + platforms where it is not available using the + $(LINK2 version.html#version, `version`) statement, without resorting to + string mixins or other workarounds. + ) + + $(SECTION2 $(LNAME2 memory-management, Memory Management)) + + $(P + The preferred way to do memory management in Objective-C is to use + Automatic Reference Counting, $(LINK2 https://developer.apple.com/library/mac/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html, ARC). + This is not supported in D, therefore manual memory management is + required to be used instead. This is achieved by calling $(LINK2 https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/index.html#//apple_ref/occ/intfm/NSObject/release, `release`) + on an Objective-C instance, like in the old days of Objective-C. + ) + + $(SECTION2 $(LNAME2 frameworks, Frameworks)) + + $(P + Most Objective-C code is bundled in something called a "Framework". + This is basically a regular directory, with the `.framework` extension + and a specific directory layout. A framework contains a dynamic + library, all public header files and any resources (images, sounds and + so on) required by the framework. + ) + + $(P + These directories are recognized by some tools, like the Objective-C + compiler and linker, to be frameworks. To link with a framework from + DMD, use the following flags: + ) + + --- + -L-framework -L<Framework> + --- + + where `<Framework>` is the name of the framework to link with, without + the `.framework` extension. The two `-L` flags are required because the + linker expects a space between the `-framework` flag and the name of + the framework. DMD cannot handle this and will instead interpret the + name of the framework as a separate flag. + + $(SECTION3 $(LNAME2 framework-paths, Framework Paths)) + + $(P + Using the above flag, the linker will search in the standard framework + paths. The standard search paths for frameworks are: + ) + + $(UL + $(LI `/System/Library/Frameworks`) + $(LI `/Library/Frameworks`) + ) + + $(P + The following flag from DMD can be used to add a new path in which to + search for frameworks: + ) + + --- + -L-F<framework_path> + --- + + $(P + For more information see the $(LINK2 https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPFrameworks/Tasks/IncludingFrameworks.html, reference documentation) + and the `ld` man page. + ) + + $(SECTION2 $(LNAME2 usage-example, Full Usage Example)) + + $(P + This example will create an Objective-C string, `NSString`, and log the + message using `NSLog` to stderr. + ) + + --- + import core.attribute : selector; + + extern (Objective-C) + extern class NSString + { + static NSString alloc() @selector("alloc"); + NSString initWithUTF8String(in char* str) @selector("initWithUTF8String:"); + void release() @selector("release"); + } + --- + + $(P + This is a simplified declaration of the $(LINK2 https://developer.apple.com/documentation/foundation/nsstring?language=objc, `NSString`) + class. The $(LINK2 https://developer.apple.com/documentation/objectivec/nsobject/1571958-alloc?language=objc, `alloc`) + method allocates an instance of the class. The $(LINK2 https://developer.apple.com/documentation/foundation/nsstring/1412128-initwithutf8string?language=objc, `initWithUTF8String:`) + method will be used to convert a C string in UTF-8 to an Objective-C + string, `NSString`. The $(LINK2 https://developer.apple.com/documentation/objectivec/1418956-nsobject/1571957-release?language=objc, `release`) + method is used to release an deallocate the string. Since D doesn't + support $(LINK2 https://developer.apple.com/library/mac/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html, ARC) + it's needed to manually release Objective-C instances. + ) + + --- + extern (C) void NSLog(NSString, ...); + --- + + $(P + This $(LINK2 https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/index.html#//apple_ref/c/func/NSLog, `NSLog`) + function prints a message to the System Log facility, i.e. to stderr + and Console. + ) + + --- + auto str = NSString.alloc(); + --- + + $(P Allocate an instance of the class, `NSString`.) + + --- + str = str.initWithUTF8String("Hello World!") + --- + + $(P Initialize the Objective-C string using a C string.) + + --- + NSLog(str); + --- + + $(P + Log the string to stderr, this will print something like this in the + terminal: + ) + + --- + 2015-07-18 13:14:27.978 main[11045:2934950] Hello World! + --- + + --- + str.release(); + --- + + $(P Release and deallocate the string.) + + $(P All steps combined look like this:) + + --- + module main; + + import core.attribute : selector; + + extern (Objective-C) + extern class NSString + { + static NSString alloc() @selector("alloc"); + NSString initWithUTF8String(in char* str) @selector("initWithUTF8String:"); + void release() @selector("release"); + } + + extern (C) void NSLog(NSString, ...); + + void main() + { + auto str = NSString.alloc().initWithUTF8String("Hello World!"); + NSLog(str); + str.release(); + } + --- + + $(P + When compiling the application remember to link with the required + libraries, in this case the Foundation framework. Example: + ) + + --- + dmd -L-framework -LFoundation main.d + --- +$(SPEC_SUBNAV_PREV_NEXT cpp_interface, Interfacing to C++, portability, Portability Guide) +) + +Macros: + CHAPTER=35 + TITLE=Interfacing to Objective-C diff --git a/spec/operatoroverloading.dd b/spec/operatoroverloading.dd new file mode 100644 index 0000000000..bce7b886be --- /dev/null +++ b/spec/operatoroverloading.dd @@ -0,0 +1,1307 @@ +Ddoc + +$(SPEC_S Operator Overloading, + +$(HEADERNAV_TOC) + + $(P Operator overloading is accomplished by rewriting operators whose + operands are class or struct objects into calls to specially named + members. No additional syntax is used. + ) + +$(H2 $(LEGACY_LNAME2 Unary, unary, Unary Operator Overloading)) + + $(TABLE2 Overloadable Unary Operators, + $(THEAD $(I op), $(I rewrite)) + $(TROW + $(ARGS $(D -)$(I e)), + $(ARGS $(I e)$(D .opUnary!("-")())) + ) + $(TROW + $(ARGS $(D +)$(I e)), + $(ARGS $(I e)$(D .opUnary!("+")())) + ) + $(TROW + $(ARGS $(D ~)$(I e)), + $(ARGS $(I e)$(D .opUnary!("~")())) + ) + + $(TROW + $(ARGS $(D *)$(I e)), + $(ARGS $(I e)$(D .opUnary!("*")())) + ) + + $(TROW + $(ARGS $(D ++)$(I e)), + $(ARGS $(I e)$(D .opUnary!("++")())) + ) + + $(TROW + $(ARGS $(D --)$(I e)), + $(ARGS $(I e)$(D .opUnary!("--")())) + ) + ) + + $(P For example, in order to overload the $(D -) (negation) operator for struct S, and + no other operator:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + int m; + + int opUnary(string s)() if (s == "-") + { + return -m; + } +} + +void main() +{ + S s = {2}; + assert(-s == -2); +} +--- +) + +$(NOTE *opUnary* above can also be declared using a template parameter specialization:) +--- + int opUnary(string s : "-")() +--- + +$(H3 $(LNAME2 postincrement_postdecrement_operators, Postincrement $(I e)$(D ++) and Postdecrement $(I e)$(D --) Operators)) + + $(P These are not directly overloadable, but instead are rewritten + in terms of the ++$(I e) and --$(I e) prefix operators: + ) + + $(TABLE2 Postfix Operator Rewrites, + $(THEAD $(I op), $(I rewrite)) + $(TROW + $(ARGS $(I e)$(D --)), + $(ARGS $(D $(LPAREN)auto t =) $(I e)$(D , )$(I e)`.opUnary!"--"`$(D , t$(RPAREN)))) + $(TROW + $(ARGS $(I e)$(D ++)), + $(ARGS $(D $(LPAREN)auto t =) $(I e)$(D , )$(I e)`.opUnary!"++"`$(D , t$(RPAREN)))) + ) + +$(H3 $(LNAME2 index_unary_operators, Overloading Index Unary Operators)) + + $(P Indexing can be $(RELATIVE_LINK2 array, overloaded). + A unary operation on an index expression can also be overloaded independently. + This works for multidimensional indexing.) + + $(TABLE2 Overloadable Index Unary Operators, + $(THEAD $(I op), $(I rewrite)) + $(TROW + $(D -)$(I a)`[`$(ARGUMENTS)`]`, + $(ARGS $(I a)`.opIndexUnary!("-")$(LPAREN)`$(ARGUMENTS)`$(RPAREN)`)) + $(TROW + $(D +)$(I a)`[`$(ARGUMENTS)`]`, + $(I a)$(D .opIndexUnary!("+")$(LPAREN))$(ARGUMENTS)`$(RPAREN)` + ) + $(TROW + `~`$(I a)`[`$(ARGUMENTS)`]`, + $(I a)$(D .opIndexUnary!("~")$(LPAREN))$(ARGUMENTS)`$(RPAREN)` + ) + $(TROW + `*`$(I a)`[`$(ARGUMENTS)`]`, + $(I a)$(D .opIndexUnary!("*")$(LPAREN))$(ARGUMENTS)`$(RPAREN)` + ) + $(TROW + `++`$(I a)`[`$(ARGUMENTS)`]`, + $(I a)`.opIndexUnary!("++")$(LPAREN)`$(ARGUMENTS)`$(RPAREN)` + ) + $(TROW + `--`$(I a)`[`$(ARGUMENTS)`]`, + $(I a)`.opIndexUnary!("--")$(LPAREN)`$(ARGUMENTS)`$(RPAREN)` + ) + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + private int[] a; + + void opIndexUnary(string s: "++")(size_t i) { ++a[i]; } +} + +S s = {[4]}; +++s[0]; +assert(s.a[0] == 5); +--- +) + +$(H3 $(LNAME2 slice_unary_operators, Overloading Slice Unary Operators)) + + $(P Slicing can be $(RELATIVE_LINK2 slice, overloaded). + A unary operation on a slice can also be overloaded independently. + `opIndexUnary` is defined either with no function arguments for a full slice, + or with two arguments for the start and end indices of the slice.) + + $(TABLE2 Overloadable Slice Unary Operators, + $(THEAD $(I op), $(I rewrite)) + $(TROW + $(D -)$(I a)$(D [)$(SLICE)$(D ]), + $(I a)$(D .opIndexUnary!("-")$(LPAREN))$(I a)$(D .opSlice$(LPAREN))$(SLICE2)$(D $(RPAREN)$(RPAREN)) + ) + + $(TROW + $(D +)$(I a)$(D [)$(SLICE)$(D ]), + $(I a)$(D .opIndexUnary!("+")$(LPAREN))$(I a)$(D .opSlice$(LPAREN))$(SLICE2)$(D $(RPAREN)$(RPAREN)) + ) + + $(TROW + $(D ~)$(I a)$(D [)$(SLICE)$(D ]), + $(I a)$(D .opIndexUnary!("~")$(LPAREN))$(I a)$(D .opSlice$(LPAREN))$(SLICE2)$(D $(RPAREN)$(RPAREN)) + ) + + $(TROW + $(D *)$(I a)$(D [)$(SLICE)$(D ]), + $(I a)$(D .opIndexUnary!("*")$(LPAREN))$(I a)$(D .opSlice$(LPAREN))$(SLICE2)$(D $(RPAREN)$(RPAREN)) + ) + + $(TROW + $(D ++)$(I a)$(D [)$(SLICE)$(D ]), + $(I a)$(D .opIndexUnary!("++")$(LPAREN))$(I a)$(D .opSlice$(LPAREN))$(SLICE2)$(D $(RPAREN)$(RPAREN)) + ) + + $(TROW + $(D --)$(I a)$(D [)$(SLICE)$(D ]), + $(I a)$(D .opIndexUnary!("--")$(LPAREN))$(I a)$(D .opSlice$(LPAREN))$(SLICE2)$(D $(RPAREN)$(RPAREN)) + ) + + $(TROW + $(D -)$(I a)$(D [ ]), + $(I a)$(D .opIndexUnary!("-")()) + ) + + $(TROW + $(D +)$(I a)$(D [ ]), + $(I a)$(D .opIndexUnary!("+")()) + ) + + $(TROW + $(D ~)$(I a)$(D [ ]), + $(I a)$(D .opIndexUnary!("~")()) + ) + + $(TROW + $(D *)$(I a)$(D [ ]), + $(I a)$(D .opIndexUnary!("*")()) + ) + + $(TROW + $(D ++)$(I a)$(D [ ]), + $(I a)$(D .opIndexUnary!("++")()) + ) + + $(TROW + $(D --)$(I a)$(D [ ]), + $(I a)$(D .opIndexUnary!("--")()) + ) + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + private int[] a; + + void opIndexUnary(string s: "--")() { --a[]; } +} + +S s = {[1, 2]}; +--s[]; +assert(s.a == [0, 1]); +--- +) + + $(NOTE For backward compatibility, if the above rewrites fail to compile and + $(D opSliceUnary) is defined, then the rewrites + $(D a.opSliceUnary!(op)(i, j)) and + $(D a.opSliceUnary!(op)) are tried instead, respectively.) + +$(H2 $(LEGACY_LNAME2 Cast, cast, Cast Operator Overloading)) + + $(P To define how one type can be cast to another, define the + `opCast` template method, which is used as follows:) + $(TABLE2 Cast Operators, + $(THEAD $(I op), $(I rewrite)) + $(TROW + `cast$(LPAREN)`$(I type)`$(RPAREN)` $(I e), + $(I e)`.opCast!$(LPAREN)`$(I type)`$(RPAREN)()` + ) + ) + + $(P Note that `opCast` is only ever used with an explicit `cast` + expression, except in the case of boolean operations (see next + section).) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + void* mem; + + bool opCast(T)() + if (is(T == bool)) => mem !is null; +} + +S s = S(new int); +auto b = cast(bool) s; +assert(b); +//b = s; // error +--- +) + $(P If the return type of `opCast` differs from the *type* parameter of + the `cast`, then the result is implicitly converted to *type*.) + +$(H3 $(LNAME2 boolean_operators, Boolean Operations)) + + $(P Notably absent from the list of overloaded unary operators is the `!` + logical negation operator. More obscurely absent is a unary operator + to convert to a `bool` result. + Instead, for structs these are covered by a rewrite to: + ) +--- +opCast!(bool)(e) +--- + + $(P So,) + +--- +if (e) => if (e.opCast!(bool)) +if (!e) => if (!e.opCast!(bool)) +--- + + $(P and similarly for other boolean conditional expressions and + $(DDSUBLINK spec/expression, logical_expressions, logical operators) used + on the struct instance.) + + $(P This only happens, however, for + instances of structs. Class references are converted to `bool` by checking to + see if the class reference is null or not. + ) + + +$(H2 $(LEGACY_LNAME2 Binary, binary, Binary Operator Overloading)) + + $(P The following binary operators are overloadable:) + + $(TABLE2 Overloadable Binary Operators, + $(TROW $(D +), $(D -), $(D *), $(D /), $(CODE_PERCENT), $(D ^^), $(CODE_AMP)) + $(TROW $(CODE_PIPE), $(D ^), $(D <)$(D <), $(D >)$(D >), $(D >)$(D >)$(D >), $(D ~), $(DDSUBLINK spec/expression, InExpression, $(D in))) + ) + + $(P The expression:) +--- +a $(METACODE op) b +--- + $(P is rewritten as one of:) +--- +a.opBinary!($(METACODE "op"))(b) +b.opBinaryRight!($(METACODE "op"))(a) +--- + + $(P and the one with the $(SINGLEQUOTE better) match is selected. + It is an error for both to equally match. Example: + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + int[] data; + + // this ~ rhs + int[] opBinary(string op : "~")(int rhs) + { + return data ~ rhs; + } + // lhs ~ this + int[] opBinaryRight(string op : "~")(int lhs) + { + return lhs ~ data; + } +} + +void main() +{ + auto s = S([2,3]); + assert(s ~ 4 == [2,3,4]); // opBinary + assert(1 ~ s == [1,2,3]); // opBinaryRight +} +--- +) + + $(P Operator overloading for a number of operators can be done at the same time. + For example, if only the + or - operators are supported:) + +--- +T opBinary(string op)(T rhs) +{ + static if (op == "+") return data + rhs.data; + else static if (op == "-") return data - rhs.data; + else static assert(0, "Operator " ~ op ~ " not implemented"); +} +--- + + $(P To do them all en masse:) + +--- +T opBinary(string op)(T rhs) +{ + return mixin("data " ~ op ~ " rhs.data"); +} +--- + + $(P Note that `opIn` and `opIn_r` have been deprecated in favor of + `opBinary!"in"` and `opBinaryRight!"in"` respectively.) + +$(H2 $(LNAME2 eqcmp, Overloading the Comparison Operators)) + + $(P D allows overloading of the comparison operators $(D ==), $(D !=), + $(D <), $(D <=), $(D >=), $(D >) via two functions, $(D opEquals) and + $(D opCmp).) + + $(P The equality and inequality operators are treated separately + from comparison operators + because while practically all user-defined types can be compared for + equality, only a subset of types have a meaningful ordering. For + example, while it makes sense to determine if two RGB color vectors are + equal, it is not meaningful to say that one color is greater than + another, because colors do not have an ordering. Thus, one would define + $(D opEquals) for a $(D Color) type, but not $(D opCmp).) + + $(P Furthermore, even with orderable types, the order relation may not + be linear. For example, one may define an ordering on sets via the + subset relation, such that $(D x < y) is true if $(D x) is a (strict) + subset of $(D y). If $(D x) and $(D y) are disjoint sets, then neither + $(D x < y) nor $(D y < x) holds, but that does not imply that + $(D x == y). Thus, it is insufficient to determine equality purely based on + $(D opCmp) alone. For this reason, $(D opCmp) is only used for the + $(GLINK2 RelExpression) operators $(D <), $(D <=), $(D >=), and $(D >). The equality + operators $(D ==) and $(D !=) always employ $(D opEquals) instead.) + + $(P Therefore, it is the programmer's responsibility to ensure that + `opCmp` and $(D opEquals) are consistent with each other. If + `opEquals` is not specified for a struct, the compiler provides a + $(DDSUBLINK spec/expression, struct_equality, default version) of it + that does member-wise comparison. If this suffices, one may define only + $(D opCmp) to customize the behaviour of the *RelExpression* operators. But + if not, then a custom version of $(D opEquals) should be defined as + well, in order to preserve consistent semantics between the two kinds + of comparison operators.) + + $(P Finally, if a user-defined type is to be used as a key in the + built-in associative arrays, then the programmer must ensure that the + semantics of $(D opEquals) and $(D toHash) are consistent. If not, the + associative array may not work in the expected manner.) + +$(H3 $(LNAME2 equals, Overloading $(D ==) and $(D !=))) + + $(P Expressions of the form $(CODE a != b) are rewritten as $(CODE !(a == b)).) + + $(P Given $(CODE a == b) :) + +$(OL + $(LI If a and b are both class objects, then the expression is rewritten as: + --- + .object.opEquals(a, b) + --- + $(P and that function is similar to:) + --- + bool opEquals(Object a, Object b) + { + if (a is b) return true; + if (a is null || b is null) return false; + if (typeid(a) == typeid(b)) return a.opEquals(b); + return a.opEquals(b) && b.opEquals(a); + } + --- + ) + $(LI Otherwise the expressions `a.opEquals(b)` and + `b.opEquals(a)` are tried. If both resolve to the same `opEquals` function, then the expression is rewritten to be `a.opEquals(b)`. + ) + $(LI If one is a better match than the other, or one compiles and the other + does not, the first is selected.) + $(LI Otherwise, an error results.) +) + + $(P If overriding $(D Object.opEquals()) for classes, the class member + function should take an `Object` parameter and dynamically check + that it is a compatible class, e.g.:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + class C + { + int i; + + this(int i) { this.i = i; } + + override bool opEquals(Object o) + { + if (auto c = cast(C) o) + return c.i == i; + else + assert(0, __FUNCTION__ ~ ": Cannot compare a " ~ typeid(o).toString); + } + } + + static assert(new C(2) == new C(2)); + static assert(new C(2) != new C(3)); + --- + ) + + $(P If structs declare an $(D opEquals) member function for the + identity comparison, it could have several forms, such as:) + --- + struct S + { + // lhs should be mutable object + bool opEquals(const S s) { ... } // for r-values (e.g. temporaries) + bool opEquals(ref const S s) { ... } // for l-values (e.g. variables) + + // both hand side can be const object + bool opEquals(const S s) const { ... } // for r-values (e.g. temporaries) + } + --- + + $(P Alternatively, declare a single templated $(D opEquals) + function with an $(DDSUBLINK spec/template, auto-ref-parameters, auto ref) + parameter:) + --- + struct S + { + // for l-values and r-values, + // with converting both hand side implicitly to const + bool opEquals()(auto ref const S s) const { ... } + } + --- + $(NOTE See $(DDSUBLINK spec/expression, struct_equality, Struct Equality) + for best practices on implementing `opEquals` for structs.) + + +$(H3 $(LNAME2 compare, Overloading $(D <), $(D <)$(D =), $(D >), and $(D >)$(D =))) + + $(P Class references are first $(DDSUBLINK spec/expression, class-comparisons, + compared by reference). If they refer to different objects and neither is `null`, + they are then compared by calling a matching `opCmp` method, as for structs.) + + $(P Struct comparison operations are rewritten as follows:) + + $(TABLE2 Rewriting of comparison operations, + $(THEAD comparison, rewrite 1, rewrite 2) + $(TROW $(D a) $(D <) $(D b), $(D a.opCmp(b)) $(D <) + $(D 0), $(ARGS $(D b.opCmp(a)) $(D >) $(D 0))) + $(TROW $(D a) $(D <)$(D= b), $(ARGS $(D a.opCmp(b)) + $(D <)$(D= 0)), $(ARGS $(D b.opCmp(a)) $(D >)$(D = 0))) + $(TROW $(D a) $(D >) $(D b), $(ARGS $(D a.opCmp(b)) + $(D >) $(D 0)), $(ARGS $(D b.opCmp(a)) $(D <) $(D 0))) + $(TROW $(D a) $(D >)$(D = b), $(ARGS $(D a.opCmp(b)) + $(D >)$(D = 0)), $(ARGS $(D b.opCmp(a)) $(D <)$(D= 0))) + ) + + $(P Both rewrites are tried. If only one compiles, that one is taken. + If they both resolve to the same function, the first rewrite is done. + If they resolve to different functions, the best matching one is used. + If they both match the same, but are different functions, an ambiguity + error results.) +--- +struct B +{ + int opCmp(int) { return -1; } + int opCmp(ref const S) { return -1; } + int opCmp(ref const C) { return -1; } +} + +struct S +{ + int opCmp(ref const S) { return 1; } + int opCmp(ref B) { return 0; } +} + +struct C +{ + int opCmp(ref const B) { return 0; } +} + +void main() +{ + S s; + const S cs; + B b; + C c; + assert(s > s); // s.opCmp(s) > 0 + assert(!(s < b)); // s.opCmp(b) > 0 - S.opCmp(ref B) is exact match + assert(!(b < s)); // s.opCmp(b) < 0 - S.opCmp(ref B) is exact match + assert(b < cs); // b.opCmp(s) < 0 - B.opCmp(ref const S) is exact match + static assert(!__traits(compiles, b < c)); // both C.opCmp and B.opcmp match exactly +} +--- + $(P If overriding $(D Object.opCmp()) for classes, the class member + function should take an `Object` parameter and dynamically check + that it is a compatible class for the comparison (like when overriding + $(RELATIVE_LINK2 equals, `opEquals`)).) + +--- +class C +{ + override int opCmp(Object o) { ... } +} +--- + + $(P If structs declare an $(D opCmp) member function, it should have + the following form:) +--- +struct S +{ + int opCmp(ref const S s) const { ... } +} +--- + + $(P Note that $(D opCmp) is only used for + $(GLINK2 expression, RelExpression) operators; + expressions like $(D a == b) always use $(RELATIVE_LINK2 equals, `opEquals`).) + + $(P For structs, if $(D opCmp) is defined but $(D opEquals) isn't, + the compiler will supply $(DDSUBLINK spec/expression, struct_equality, a default + version) of $(D opEquals) that performs member-wise comparison. However, the + member-wise comparison may not be consistent with the user-defined + `opCmp`.) + + $(P It is up to the programmer to also supply a + version of $(D opEquals) when appropriate. Otherwise, + a *RelExpression* like $(D a <= b) + will behave inconsistently with equalities like $(D a == b).) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + int i, j; + int opCmp(ref const S s) const { return (i > s.i) - (i < s.i); } // ignore j +} + +S a = {2, 3}; +S b = {2, 1}; +S c = {3, 0}; +assert(a < c); +assert(a <= b); +assert(!(a < b)); // opCmp ignores j +assert(a != b); // generated opEquals tests both i and j members +--- +) + +$(BEST_PRACTICE Using `(i > s.i) - (i < s.i)` instead of `i - s.i` to +compare integers avoids overflow.) + + +$(H2 $(LEGACY_LNAME2 FunctionCall, function-call, Function Call Operator Overloading)) + + $(P The function call operator, $(D ()), can be overloaded by + declaring a function named $(CODE opCall): + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------- + struct F + { + int opCall(); + int opCall(int x, int y, int z); + } + + void main() + { + F f; + int i; + + i = f(); // same as i = f.opCall(); + i = f(3,4,5); // same as i = f.opCall(3,4,5); + } + ------- + ) + + $(P In this way a struct or class object can behave as if it + were a function. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------- + struct Multiplier + { + int factor; + this(int num) { factor = num; } + int opCall(int value) { return value * factor; } + } + + void main() + { + Multiplier m = Multiplier(10); // invoke constructor + assert(m.factor == 10); + int result = m(5); // invoke opCall + assert(result == 50); + } + ------- + ) + +$(H3 $(LNAME2 static-opcall, Static opCall)) + + $(P $(CODE static opCall) also works as expected for a function call operator with + type names. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------- + struct Double + { + static int opCall(int x) { return x * 2; } + } + + void main() + { + int i = Double(2); + assert(i == 4); + } + ------- + ) + + $(P Note that merely declaring a $(D static opCall) automatically disables + $(DDSUBLINK spec/struct, StructLiteral, struct literal) syntax. + ) + + $(P Mixing struct constructors and $(D static opCall) is not allowed.) + + --- + struct S + { + this(int i) {} + static S opCall() // disallowed due to constructor + { + return S.init; + } + } + --- + + $(P Note: $(D static opCall) can be used to simulate struct + constructors with no arguments, but this is not recommended + practice. Instead, the preferred solution is to use a factory + function to create struct instances. + ) + +$(H2 $(LEGACY_LNAME2 Assignment, assignment, Assignment Operator Overloading)) + + $(P The assignment operator $(CODE =) can be overloaded if the + left hand side is a struct aggregate, and $(CODE opAssign) + is a member function of that aggregate.) + + For struct types, operator overloading for the identity assignment + is allowed. + + --- + struct S + { + // identity assignment, allowed. + void $(CODE_HIGHLIGHT opAssign)(S rhs); + + // not identity assignment, also allowed. + void $(CODE_HIGHLIGHT opAssign)(int); + } + S s; + s = S(); // Rewritten to s.opAssign(S()); + s = 1; // Rewritten to s.opAssign(1); + --- + + However for class types, identity assignment is not allowed. All class + types have reference semantics, so identity assignment by default rebinds + the left-hand-side to the argument at the right, and this is not overridable. + + --- + class C + { + // If X is the same type as C or the type which is + // implicitly convertible to C, then opAssign would + // accept identity assignment, which is disallowed. + // C opAssign(...); + // C opAssign(X); + // C opAssign(X, ...); + // C opAssign(X ...); + // C opAssign(X, U = defaultValue, etc.); + + // not an identity assignment - allowed + void $(CODE_HIGHLIGHT opAssign)(int); + } + C c = new C(); + c = new C(); // Rebinding referencee + c = 1; // Rewritten to c.opAssign(1); + --- + +$(H3 $(LNAME2 index_assignment_operator, Index Assignment Operator Overloading)) + + $(P If the left hand side of an assignment is an index operation + on a struct or class instance, + it can be overloaded by providing an $(D opIndexAssign) member function. + Expressions of the form `a[`$(ARGUMENTS)`] = c` are rewritten + as `a.opIndexAssign$(LPAREN)c,` $(ARGUMENTS)`$(RPAREN)`. + ) + +------- +struct A +{ + int $(CODE_HIGHLIGHT opIndexAssign)(int value, size_t i1, size_t i2); +} + +void test() +{ + A a; + a$(CODE_HIGHLIGHT [)i,3$(CODE_HIGHLIGHT ]) = 7; // same as a.opIndexAssign(7,i,3); +} +------- + +$(H3 $(LNAME2 slice_assignment_operator, Slice Assignment Operator Overloading)) + + $(P If the left hand side of an assignment is a slice operation on a + struct or class instance, it can be overloaded by implementing an + `opIndexAssign` member function that takes the return value of the + `opSlice` function as parameter(s). + Expressions of the form $(CODE a[)$(SLICE)$(D ] = c) are rewritten as + $(CODE a.opIndexAssign$(LPAREN)c,) $(D a.opSlice!0$(LPAREN))$(SLICE2)$(D $(RPAREN)$(RPAREN)), + and $(CODE a[] = c) as $(CODE a.opIndexAssign(c)). + ) + + $(P See $(RELATIVE_LINK2 array-ops, Array + Indexing and Slicing Operators Overloading) for more details. + ) + +------- +struct A +{ + int opIndexAssign(int v); // overloads a[] = v + int opIndexAssign(int v, size_t[2] slice); // overloads a[i .. j] = v + size_t[2] opSlice(size_t dim)(size_t i, size_t j); // overloads i .. j +} + +void test() +{ + A a; + int v; + + a[] = v; // same as a.opIndexAssign(v); + a[3..4] = v; // same as a.opIndexAssign(v, a.opSlice!0(3,4)); +} +------- + + $(P For backward compatibility, if rewriting $(D a[)$(SLICE)$(D ]) as + $(D a.opIndexAssign$(LPAREN)a.opSlice!0$(LPAREN))$(SLICE2)$(D $(RPAREN)$(RPAREN)) + fails to compile, the legacy rewrite + $(D opSliceAssign$(LPAREN)c,) $(SLICE2)$(D $(RPAREN)) is used instead. + ) + +$(H2 $(LEGACY_LNAME2 OpAssign, op-assign, Op Assignment Operator Overloading)) + + $(P The following op assignment operators are overloadable:) + + $(TABLE2 Overloadable Op Assignment Operators, + $(TROW $(D +=), $(D -=), $(D *=), $(D /=), $(CODE_PERCENT)$(D =), $(D ^^=), $(CODE_AMP)$(D =)) + $(TROW $(CODE_PIPE)$(D =), $(D ^=), $(D <)$(D <)$(D =), + $(D >)$(D >)$(D =), $(D >)$(D >)$(D >)$(D =), $(D ~=), $(NBSP)) + ) + + $(P The expression:) +--- +a $(METACODE op)= b +--- + + $(P is rewritten as:) + +--- +a.opOpAssign!($(METACODE "op"))(b) +--- + +Example: +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + int i; + void opOpAssign(string op: "+")(int rhs) { i += rhs; } +} + +S s = {2}; +s += 3; +assert(s.i == 5); +--- +) + +$(H3 $(LNAME2 index_op_assignment, Index Op Assignment Operator Overloading)) + + $(P If the left hand side of an $(I op)= is an index expression on + a struct or class instance and $(D opIndexOpAssign) is a member:) + +--- +a[$(METACODE $(ARGUMENTS))] $(METACODE op)= c +--- + + $(P it is rewritten as:) + +--- +a.opIndexOpAssign!($(METACODE "op"))(c, $(METACODE $(ARGUMENTS))) +--- + +$(H3 $(LNAME2 slice_op_assignment, Slice Op Assignment Operator Overloading)) + + $(P If the left hand side of an $(I op)= is a slice expression on + a struct or class instance and $(D opIndexOpAssign) is a member:) + +--- +a[$(METACODE $(SLICE))] $(METACODE op)= c +--- + + $(P it is rewritten as:) + +--- +a.opIndexOpAssign!($(METACODE "op"))(c, a.opSlice($(METACODE $(SLICE2)))) +--- + + $(P and) + +--- +a[] $(METACODE op)= c +--- + + $(P it is rewritten as:) + +--- +a.opIndexOpAssign!($(METACODE "op"))(c) +--- + + $(P For backward compatibility, if the above rewrites fail and + `opSliceOpAssign` is defined, then the rewrites + $(D a.opSliceOpAssign(c, i, j)) and $(D a.opSliceOpAssign(c)) are + tried, respectively. + ) + + +$(H2 $(LEGACY_LNAME2 ArrayOps, array-ops, Array Indexing and Slicing Operators Overloading)) + + $(P The array indexing and slicing operators are overloaded by + implementing the $(D opIndex), $(D opSlice), and $(D opDollar) methods. + These may be combined to implement multidimensional arrays. + ) + +$(H3 $(LEGACY_LNAME2 Array, array, Index Operator Overloading)) + + $(P Expressions of the form $(D arr[)$(ARGUMENTS)$(D ]) are translated + into $(D arr.opIndex$(LPAREN))$(ARGUMENTS)$(D $(RPAREN)). For example: + ) + +------- +struct A +{ + int $(CODE_HIGHLIGHT opIndex)(size_t i1, size_t i2, size_t i3); +} + +void test() +{ + A a; + int i; + i = a[5,6,7]; // same as i = a.opIndex(5,6,7); +} +------- + + $(P In this way a struct or class object can behave as if it + were an array. + ) + + $(P If an index expression can be rewritten using $(D opIndexAssign) or + $(D opIndexOpAssign), those are preferred over $(D opIndex). + ) + +$(H3 $(LEGACY_LNAME2 Slice, slice, Slice Operator Overloading)) + + $(P Overloading the slicing operator means overloading expressions + like $(D a[]) or $(D a[)$(SLICE)$(D ]), where the expressions inside + the square brackets contain slice expressions of the form $(SLICE). + ) + + $(P To overload $(D a[]), simply define $(D opIndex) with no parameters: + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +----- +struct S +{ + int[] impl; + int[] opIndex() + { + return impl[]; + } +} + +void main() +{ + auto s = S([1,2,3]); + int[] t = s[]; // calls s.opIndex() + assert(t == [1,2,3]); +} +----- +) + + $(P To overload array slicing of the form $(D a[)$(SLICE)$(D ]), + two steps are needed. First, the expressions of the form $(SLICE) are + translated via $(D opSlice!0) into objects that encapsulate + the endpoints $(I i) and $(I j). Then these objects are + passed to $(D opIndex) to perform the actual slicing.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + int[] impl; + + int[] opSlice(size_t dim: 0)(size_t i, size_t j) + { + return impl[i..j]; + } + int[] opIndex()(int[] slice) { return slice; } +} + +void main() +{ + auto s = S([1, 2, 3]); + int[] t = s[0..2]; // calls s.opIndex(s.opSlice!0(0, 2)) + assert(t == [1, 2]); +} +--- +) + + $(P This design was + chosen in order to support mixed indexing and slicing in + multidimensional arrays; for example, in translating expressions like + $(D arr[1, 2..3, 4]). + More precisely, an expression of the form $(D arr[)$(ARGUMENTS)$(D ]) + is translated into $(D arr.opIndex$(LPAREN))$(ARGUMENTS2)$(D $(RPAREN)). + Each argument $(I b)$(SUBSCRIPT i) can be either a single expression, + in which case it is passed directly as the corresponding argument $(I + c)$(SUBSCRIPT i) to $(D opIndex); or it can be a slice expression of + the form $(I x)$(SUBSCRIPT i)$(D ..)$(I y)$(SUBSCRIPT i), in which case + the corresponding argument $(I c)$(SUBSCRIPT i) to $(D opIndex) is + $(D arr.opSlice!i$(LPAREN))$(I x)$(SUBSCRIPT i)$(D , )$(I y)$(SUBSCRIPT i)$(D $(RPAREN)). Namely: + ) + + $(TABLE2 , + $(THEAD $(I op), $(I rewrite)) + $(TROW + $(D arr[1, 2, 3]), + $(D arr.opIndex(1, 2, 3)) + ) + $(TROW + $(D arr[1..2, 3..4, 5..6]), + $(D arr.opIndex(arr.opSlice!0(1,2), arr.opSlice!1(3,4), arr.opSlice!2(5,6))) + ) + $(TROW + $(D arr[1, 2..3, 4]), + $(D arr.opIndex(1, arr.opSlice!1(2,3), 4)) + ) + ) + + $(P Similar translations are done for assignment operators involving + slicing, for example: + ) + + $(TABLE2 , + $(THEAD $(I op), $(I rewrite)) + $(TROW + $(D arr[1, 2..3, 4] = c), + $(D arr.opIndexAssign(c, 1, arr.opSlice!1(2, 3), 4)) + ) + $(TROW + $(D arr[2, 3..4] += c), + $(D arr.opIndexOpAssign!"+"(c, 2, arr.opSlice!1(2, 3))) + ) + ) + + $(P The intention is that $(D opSlice!i) should return a user-defined + object that represents an interval of indices along the $(D i)'th + dimension of the array. This object is then passed to $(D opIndex) to + perform the actual slicing operation. If only one-dimensional slicing + is desired, $(D opSlice) may be declared without the compile-time + parameter $(D i). + ) + + $(P Note that in all cases, $(D arr) is only evaluated once. Thus, an + expression like $(D getArray()[1, 2..3, $-1]=c) has the effect of:) + +------ +auto __tmp = getArray(); +__tmp.opIndexAssign(c, 1, __tmp.opSlice!1(2,3), __tmp.opDollar!2 - 1); +------ + $(P where the initial function call to $(D getArray) is only executed + once. + ) + + $(NOTE For backward compatibility, $(D a[]) and $(D a[)$(SLICE)$(D ]) can + also be overloaded by implementing $(D opSlice()) with no arguments and + $(D opSlice$(LPAREN))$(SLICE2)$(D $(RPAREN)) with two arguments, + respectively. This only applies for one-dimensional slicing, and dates + from when D did not have full support for multidimensional arrays. This + usage of $(D opSlice) is discouraged. + ) + +$(H3 $(LEGACY_LNAME2 Dollar, dollar, Dollar Operator Overloading)) + + $(P Within the arguments to array index and slicing operators, $(D $) + gets translated to $(D opDollar!i), where $(D i) is the position of the + expression $(D $) appears in. For example: + ) + + $(TABLE2 , + $(THEAD $(I op), $(I rewrite)) + $(TROW + $(D arr[$-1, $-2, 3]), + $(D arr.opIndex(arr.opDollar!0 - 1, arr.opDollar!1 - 2, 3)) + ) + $(TROW + $(D arr[1, 2, 3..$]), + $(D arr.opIndex(1, 2, arr.opSlice!2(3, arr.opDollar!2))) + ) + ) + + $(P The intention is that $(D opDollar!i) should return the length of + the array along its $(D i)'th dimension, or a user-defined object + representing the end of the array along that dimension, that is + understood by $(D opSlice) and $(D opIndex). + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +struct Rectangle +{ + int width, height; + int[][] impl; + + this(int w, int h) + { + width = w; + height = h; + impl = new int[][](w, h); + } + int opIndex(size_t i1, size_t i2) + { + return impl[i1][i2]; + } + int opDollar(size_t pos)() + { + static if (pos==0) + return width; + else + return height; + } +} + +void main() +{ + auto r = Rectangle(10,20); + int i = r[$-1, 0]; // same as: r.opIndex(r.opDollar!0, 0), + // which is r.opIndex(r.width-1, 0) + int j = r[0, $-1]; // same as: r.opIndex(0, r.opDollar!1) + // which is r.opIndex(0, r.height-1) +} +------ +) + + $(P As the above example shows, a different compile-time argument is + passed to $(D opDollar) depending on which argument it appears in. A + $(D $) appearing in the first argument gets translated to `opDollar!0`, + a $(D $) appearing in the second argument gets translated + to $(D opDollar!1), and so on. Thus, the appropriate value for $(D $) + can be returned to implement multidimensional arrays. + ) + + $(P Note that $(D opDollar!i) is only evaluated once for each $(D i) + where $(D $) occurs in the corresponding position in the indexing + operation. Thus, an expression like $(D arr[$-sqrt($), 0, $-1]) has + the effect of: + ) +------ +auto __tmp1 = arr.opDollar!0; +auto __tmp2 = arr.opDollar!2; +arr.opIndex(__tmp1 - sqrt(__tmp1), 0, __tmp2 - 1); +------ + + $(P If $(D opIndex) is declared with only one argument, the + compile-time argument to $(D opDollar) may be omitted. In this case, it + is illegal to use $(D $) inside an array indexing expression with more + than one argument. + ) + +$(H3 $(LNAME2 index-slicing-example, Complete Example)) + + $(P The code example below shows a simple implementation of a + 2-dimensional array with overloaded indexing and slicing operators. The + explanations of the various constructs employed are given in the + sections following.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------- +struct Array2D(E) +{ + E[] impl; + int stride; + int width, height; + + this(int width, int height, E[] initialData = []) + { + impl = initialData; + this.stride = this.width = width; + this.height = height; + impl.length = width * height; + } + + // Index a single element, e.g., arr[0, 1] + ref E opIndex(int i, int j) { return impl[i + stride*j]; } + + // Array slicing, e.g., arr[1..2, 1..2], arr[2, 0..$], arr[0..$, 1]. + Array2D opIndex(int[2] r1, int[2] r2) + { + Array2D result; + + auto startOffset = r1[0] + r2[0]*stride; + auto endOffset = r1[1] + (r2[1] - 1)*stride; + result.impl = this.impl[startOffset .. endOffset]; + + result.stride = this.stride; + result.width = r1[1] - r1[0]; + result.height = r2[1] - r2[0]; + + return result; + } + auto opIndex(int[2] r1, int j) { return opIndex(r1, [j, j+1]); } + auto opIndex(int i, int[2] r2) { return opIndex([i, i+1], r2); } + + // Support for `x..y` notation in slicing operator for the given dimension. + int[2] opSlice(size_t dim)(int start, int end) + if (dim >= 0 && dim < 2) + in { assert(start >= 0 && end <= this.opDollar!dim); } + do + { + return [start, end]; + } + + // Support `$` in slicing notation, e.g., arr[1..$, 0..$-1]. + @property int opDollar(size_t dim : 0)() { return width; } + @property int opDollar(size_t dim : 1)() { return height; } +} + +void main() +{ + auto arr = Array2D!int(4, 3, [ + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11 + ]); + + // Basic indexing + assert(arr[0, 0] == 0); + assert(arr[1, 0] == 1); + assert(arr[0, 1] == 4); + + // Use of opDollar + assert(arr[$-1, 0] == 3); + assert(arr[0, $-1] == 8); // Note the value of $ differs by dimension + assert(arr[$-1, $-1] == 11); + + // Slicing + auto slice1 = arr[1..$, 0..$]; + assert(slice1[0, 0] == 1 && slice1[1, 0] == 2 && slice1[2, 0] == 3 && + slice1[0, 1] == 5 && slice1[1, 1] == 6 && slice1[2, 1] == 7 && + slice1[0, 2] == 9 && slice1[1, 2] == 10 && slice1[2, 2] == 11); + + auto slice2 = slice1[0..2, 1..$]; + assert(slice2[0, 0] == 5 && slice2[1, 0] == 6 && + slice2[0, 1] == 9 && slice2[1, 1] == 10); + + // Thin slices + auto slice3 = arr[2, 0..$]; + assert(slice3[0, 0] == 2 && + slice3[0, 1] == 6 && + slice3[0, 2] == 10); + + auto slice4 = arr[0..3, 2]; + assert(slice4[0, 0] == 8 && slice4[1, 0] == 9 && slice4[2, 0] == 10); +} +------- +) + + +$(H2 $(LEGACY_LNAME2 Dispatch, dispatch, Forwarding)) + + $(P Member names not found in a class or struct can be forwarded + to a template function named $(CODE opDispatch) for resolution. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +import std.stdio; + +struct S +{ + void opDispatch(string s, T)(T i) + { + writefln("S.opDispatch('%s', %s)", s, i); + } +} + +class C +{ + void opDispatch(string s)(int i) + { + writefln("C.opDispatch('%s', %s)", s, i); + } +} + +struct D +{ + template opDispatch(string s) + { + enum int opDispatch = 8; + } +} + +void main() +{ + S s; + s.opDispatch!("hello")(7); + s.foo(7); + + auto c = new C(); + c.foo(8); + + D d; + writefln("d.foo = %s", d.foo); + assert(d.foo == 8); +} +--- +) + +$(H2 $(LEGACY_LNAME2 Old-Style, old-style, D1 style operator overloading)) + + $(P + The $(LINK2 http://digitalmars.com/d/1.0/operatoroverloading.html, D1 operator overload mechanisms) + are deprecated. + ) +$(SPEC_SUBNAV_PREV_NEXT function, Functions, template, Templates) +) + +Macros: + CHAPTER=21 + TITLE=Operator Overloading + ARGUMENTS=$(I b)$(SUBSCRIPT 1), $(I b)$(SUBSCRIPT 2), ... $(I b)$(SUBSCRIPT n) + ARGUMENTS2=$(I c)$(SUBSCRIPT 1), $(I c)$(SUBSCRIPT 2), ... $(I c)$(SUBSCRIPT n) + SLICE=$(I i)..$(I j) + SLICE2=$(I i), $(I j) + _= diff --git a/spec/portability.dd b/spec/portability.dd new file mode 100644 index 0000000000..7b99bc0319 --- /dev/null +++ b/spec/portability.dd @@ -0,0 +1,122 @@ +Ddoc + +$(SPEC_S Portability Guide, + +$(HEADERNAV_TOC) + + $(P It's good software engineering practice to minimize gratuitous + portability problems in the code. + Techniques to minimize potential portability problems are: + ) + + $(UL + + $(LI The integral and floating type sizes should be considered as + minimums. + Algorithms should be designed to continue to work properly if the + type size increases.) + + $(LI Floating point computations can be carried out at a higher + precision than the size of the floating point variable can hold. + Floating point algorithms should continue to work properly if + precision is arbitrarily increased.) + + $(LI Avoid depending on the order of side effects in a computation + that may get reordered by the compiler. For example: + +------- +a + b + c +------- + + $(P can be evaluated as (a + b) + c, a + (b + c), (a + c) + b, (c + b) + a, + etc. Parentheses control operator precedence, parentheses do not + control order of evaluation. + ) + + $(P If the operands of an associative operator + or * are floating + point values, the expression is not reordered. + ) + ) + + $(LI Avoid dependence on byte order; i.e. whether the CPU + is big-endian or little-endian.) + + $(LI Avoid dependence on the size of a pointer or reference being + the same size as a particular integral type.) + + $(LI If size dependencies are inevitable, put a $(D static assert) in + the code to verify it: + +------- +static assert(int.sizeof == (int*).sizeof); +------- + ) + ) + +$(H2 $(LNAME2 32_to_64bit, 32 to 64 Bit Portability)) + + $(P 32 bit processors and operating systems are still out there. + With that in mind: + ) + + $(UL + + $(LI Integral types will remain the same sizes between + 32 and 64 bit code.) + + $(LI Pointers and object references will increase in size + from 4 bytes to 8 bytes going from 32 to 64 bit code.) + + $(LI Use $(D size_t) as an alias for an unsigned integral + type that can span the address space. + Array indices should be of type $(D size_t).) + + $(LI Use $(D ptrdiff_t) as an alias for a signed integral + type that can span the address space. + A type representing the difference between two pointers + should be of type $(D ptrdiff_t).) + + $(LI The $(D .length), $(D .size), $(D .sizeof), $(D .offsetof) + and $(D .alignof) + properties will be of type $(D size_t).) + + ) + +$(H2 $(LNAME2 endianness, Endianness)) + + $(P Endianness refers to the order in which multibyte types + are stored. The two main orders are $(I big endian) and + $(I little endian). + The compiler predefines the version identifier + $(D BigEndian) or $(D LittleEndian) depending on the order + of the target system. + The x86 systems are all little endian. + ) + + $(P The times when endianness matters are:) + + $(UL + $(LI When reading data from an external source (like a file) + written in a different + endian format.) + $(LI When reading or writing individual bytes of a multibyte + type like $(D long)s or $(D double)s.) + ) + +$(H2 $(LNAME2 os_specific_code, OS Specific Code)) + + $(P System specific code is handled by isolating the differences into + separate modules. At compile time, the correct system specific + module is imported. + ) + + $(P Minor differences can be handled by constant defined in a system + specific import, and then using that constant in an + $(I IfStatement) or $(I StaticIfStatement). + ) +$(SPEC_SUBNAV_PREV_NEXT objc_interface, Interfacing to Objective-C, entity, Named Character Entities) +) + +Macros: + CHAPTER=36 + TITLE=Portability diff --git a/spec/pragma.dd b/spec/pragma.dd new file mode 100644 index 0000000000..985ecaf33e --- /dev/null +++ b/spec/pragma.dd @@ -0,0 +1,497 @@ +Ddoc + +$(SPEC_S Pragmas, + +$(HEADERNAV_TOC) + +$(GRAMMAR +$(GNAME PragmaDeclaration): + $(GLINK Pragma) $(D ;) + $(GLINK Pragma) $(GLINK2 attribute, DeclarationBlock) + +$(GNAME PragmaStatement): + $(GLINK Pragma) $(D ;) + $(GLINK Pragma) $(GLINK2 statement, NoScopeStatement) + +$(GNAME Pragma): + $(D pragma) $(D $(LPAREN)) $(GLINK_LEX Identifier) $(D $(RPAREN)) + $(D pragma) $(D $(LPAREN)) $(GLINK_LEX Identifier) $(D ,) $(GLINK2 expression, ArgumentList) $(D $(RPAREN)) +) + + + $(P Pragmas pass special information to the implementation + and can add vendor specific extensions. + Pragmas can be used by themselves terminated with a $(TT ;), + and can apply to a statement, a block of statements, a declaration, or + a block of declarations. + ) + + $(P Pragmas can be either a $(GLINK PragmaDeclaration) + or a $(GLINK PragmaStatement). + ) + +----------------- +pragma(ident); // just by itself + +pragma(ident) declaration; // influence one declaration + +pragma(ident): // influence subsequent declarations + declaration; + declaration; + +pragma(ident) // influence block of declarations +{ + declaration; + declaration; +} + +pragma(ident) statement; // influence one statement + +pragma(ident) // influence block of statements +{ + statement; + statement; +} +----------------- + + $(P The kind of pragma it is determined by the $(I Identifier). + $(GLINK2 expression, ArgumentList) is a comma-separated list of + $(ASSIGNEXPRESSION)s. The $(ASSIGNEXPRESSION)s must be + parsable as expressions, but their meaning + is up to the individual pragma semantics. + ) + +$(H2 $(LEGACY_LNAME2 Predefined-Pragmas, predefined-pragmas, Predefined Pragmas)) + +$(P All implementations must support these, even if by just ignoring them:) + +$(UL + $(LI $(LINK2 #crtctor, pragma crt$(UNDERSCORE)constructor)) + $(LI $(LINK2 #crtdtor, pragma crt$(UNDERSCORE)destructor)) + $(LI $(LINK2 #inline, pragma inline)) + $(LI $(LINK2 #lib, pragma lib)) + $(LI $(LINK2 #linkerDirective, pragma linkerDirective)) + $(LI $(LINK2 #mangle, pragma mangle)) + $(LI $(LINK2 #msg, pragma msg)) + $(LI $(LINK2 #printf, pragma printf)) + $(LI $(LINK2 #scanf, pragma scanf)) + $(LI $(LINK2 #startaddress, pragma startaddress)) +) + + $(IMPLEMENTATION_DEFINED An implementation may ignore these pragmas.) + +$(H3 $(LNAME2 crtctor, $(D pragma crt_constructor))) + + $(P Annotates a function so it is run after the C runtime library is initialized + and before the D runtime library is initialized. + ) + + $(P The function must:) + + $(OL + $(LI be `extern (C)`) + $(LI not have any parameters) + $(LI not be a non-static member function) + $(LI be a function definition, not a declaration (i.e. it must have a function body)) + $(LI not return a type that has a destructor) + $(LI not be a nested function) + ) + + --- + __gshared int initCount; + + pragma(crt_constructor) + extern(C) void initializer() { initCount += 1; } + --- + + $(P No arguments to the pragma are allowed.) + + $(P A function may be annotated with both `pragma(crt_constructor)` + and `pragma(crt_destructor)`. + ) + + $(P Annotating declarations other than function definitions has no effect.) + + $(P Annotating a struct or class definition does not affect the members of + the aggregate.) + + $(P A function that is annotated with `pragma(crt_constructor)` may initialize + `const` or `immutable` variables.) + + $(BEST_PRACTICE Use for system programming and interfacing with C/C++, + for example to allow for initialization of the runtime when loading a DSO, + or as a simple replacement for `shared static this` in + $(DDLINK spec/betterc, betterC mode, betterC mode). + ) + + $(IMPLEMENTATION_DEFINED The order in which functions annotated with `pragma(crt_constructor)` + are run is implementation defined. + ) + + $(BEST_PRACTICE to control the order in which the functions are called within one module, write + a single function that calls them in the desired order, and only annotate that function. + ) + + $(IMPLEMENTATION_DEFINED This uses the mechanism C compilers use to run + code before `main()` is called. C++ compilers use it to run static + constructors and destructors. + For example, GCC's $(LINK2 https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html, `__attribute__((constructor))`) + is equivalent. + Digital Mars C uses $(TT _STI) and $(TT _STD) identifier prefixes to mark crt_constructor and crt_destructor functions. + ) + + $(IMPLEMENTATION_DEFINED + A reference to the annotated function will be inserted in + the $(TT .init_array) section for Elf systems, + the $(TT XI) section for Win32 OMF systems, + the $(TT .CRT$XCU) section for Windows MSCOFF systems, + and the $(TT __mod_init_func) section for OSX systems. + ) + + $(NOTE `crt_constructor` and `crt_destructor` were implemented in + $(LINK2 $(ROOT_DIR)changelog/2.078.0.html, v2.078.0 (2018-01-01)). + Some compilers exposed non-standard, compiler-specific mechanism before. + ) + +$(H3 $(LNAME2 crtdtor, $(D pragma crt_destructor))) + + $(P `pragma(crt_destructor)` works the same as `pragma(crt_constructor)` except:) + + $(OL + $(LI Annotates a function so it is run after the D runtime library is terminated + and before the C runtime library is terminated. + Calling C's `exit()` function also causes the annotated functions to run.) + $(LI The order in which the annotated functions are run is the reverse of those functions + annotated with `pragma(crt_constructor)`.) + ) + + $(IMPLEMENTATION_DEFINED This uses the mechanism C compilers use to run + code after `main()` returns or `exit()` is called. C++ compilers use it to run static + destructors. + For example, GCC's $(LINK2 https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html, `__attribute__((destructor))`) + is equivalent. + Digital Mars C uses $(TT _STI) and $(TT _STD) identifier prefixes to mark crt_constructor and crt_destructor functions. + ) + + $(IMPLEMENTATION_DEFINED + A reference to the annotated function will be inserted in + the $(TT .fini_array) section for Elf systems, + the $(TT XC) section for Win32 OMF systems, + the $(TT .CRT$XPU) section for Windows MSCOFF systems, + and the $(TT __mod_term_func) section for OSX systems. + ) + +--- +__gshared int initCount; + +pragma(crt_constructor) +extern(C) void initialize() { initCount += 1; } + +pragma(crt_destructor) +extern(C) void deinitialize() { initCount -= 1; } + +pragma(crt_constructor) +pragma(crt_destructor) +extern(C) void innuendo() { printf("Inside a constructor... Or destructor?\n"); } +--- + + +$(H3 $(LNAME2 inline, $(D pragma inline))) + + $(P Affects whether functions are inlined or not. If at the declaration level, it + affects the functions declared in the block it controls. If inside a function, it + affects the function it is enclosed by.) + + $(P It takes two forms:) + $(OL + $(LI +--- +pragma(inline) +--- + Sets the behavior to match the implementation's default behavior. + ) + $(LI +--- +pragma(inline, AssignExpression) +--- + The $(GLINK2 expression, AssignExpression) is evaluated and must have a type that can be converted + to a boolean. + If the result is false the functions are never inlined, otherwise they are always inlined. + ) + ) + + $(P More than one $(I AssignExpression) is not allowed.) + + $(P If there are multiple pragma inlines in a function, + the lexically last one takes effect.) +--- +pragma(inline): +int foo(int x) // foo() is never inlined +{ + pragma(inline, true); + ++x; + pragma(inline, false); // supercedes the others + return x + 3; +} +--- + + $(IMPLEMENTATION_DEFINED + $(OL + $(LI The default inline behavior is typically selectable with a compiler switch + such as $(DDSUBLINK dmd, switch-inline, $(TT -inline).)) + $(LI Whether a particular function can be inlined or not is implementation defined.) + $(LI What happens for `pragma(inline, true)` if the function cannot be inlined. + An error message is typical.) + )) + +$(H3 $(LNAME2 lib, $(D pragma lib))) + + $(P There must be one $(ASSIGNEXPRESSION) and it must evaluate at compile time to a string literal. + ) +----------------- +pragma(lib, "foo.lib"); +----------------- + + $(IMPLEMENTATION_DEFINED + The string literal specifies the file name of a library file. This name + is inserted into the generated object file, or otherwise passed to the linker, + so the linker automatically links in that library. + ) + +$(H3 $(LNAME2 linkerDirective, $(D pragma linkerDirective))) + + $(P There must be one $(ASSIGNEXPRESSION) and it must evaluate at compile time to a string literal. + ) +----------------- +pragma(linkerDirective, "/FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=2"); +----------------- + + $(IMPLEMENTATION_DEFINED + The string literal specifies a linker directive to be embedded in the generated object file. + Linker directives are only supported for MS-COFF output. + ) + +$(H3 $(LNAME2 mangle, $(D pragma mangle))) + + $(P Overrides the default mangling for a symbol.) + + $(P For variables and functions there must be one $(ASSIGNEXPRESSION) and it must evaluate at compile time to a string literal. + For aggregates there may be one or two $(ASSIGNEXPRESSION)s, one of which must evaluate at compile time to a string literal and + one which must evaluate to a symbol. If that symbol is a $(I TemplateInstance), the aggregate is treated as a template + that has the signature and arguments of the $(I TemplateInstance). The identifier of the symbol is used when no string is supplied. + Both arguments may be used used when an aggregate's name is a D keyword. + ) + + $(P It only applies to function and variable symbols. Other symbols are ignored.) + + $(IMPLEMENTATION_DEFINED On macOS and Win32, an extra underscore (`_`) is prepended to the string + since 2.079, as is done by the C/C++ toolchain. This allows using the same `pragma(mangle)` + for all compatible (POSIX in one case, win64 in another) platforms instead of having to special-case. + ) + + $(RATIONALE + $(UL + $(LI Enables linking to symbol names that D cannot represent.) + $(LI Enables linking to a symbol which is a D keyword, since an $(GLINK_LEX Identifier) + cannot be a keyword.) + ) + --- + pragma(mangle, "body") + extern(C) void body_func(); + pragma(mangle, "function") + extern(C++) struct _function {} + template ScopeClass(C) + { + pragma(mangle, C.stringof, C) + struct ScopeClass { align(__traits(classInstanceAlignment, C)) void[__traits(classInstanceSize, C)] buffer; } + } + extern(C++) + { + class MyClassA(T) {} + void func(ref ScopeClass!(MyClassA!int)); // mangles as MyClass<int>& + } + --- + ) + + +$(H3 $(LNAME2 msg, $(D pragma msg))) + + $(P Each $(ASSIGNEXPRESSION) is evaluated at compile time and then all are combined into a message.) + + --- + pragma(msg, "compiling...", 6, 1.0); // prints "compiling...61.0" at compile time + --- + + $(IMPLEMENTATION_DEFINED The form the message takes and how it is presented to the user. + One way is by printing them to the standard error stream.) + + $(RATIONALE Analogously to how `writeln()` performs a role of writing informational messages during runtime, + `pragma(msg)` performs the equivalent role at compile time. + For example, + --- + static if (kilroy) + pragma(msg, "Kilroy was here"); + else + pragma(msg, "Kilroy got lost"); + --- + ) + +$(H3 $(LNAME2 printf, $(D pragma printf))) + + $(P `pragma(printf)` specifies that a function declaration is a printf-like function, meaning + it is an `extern (C)` or `extern (C++)` function with a `format` parameter accepting a + pointer to a 0-terminated `char` string conforming to the C99 Standard 7.19.6.1, immediately followed + by either a `...` variadic argument list or a parameter of type `va_list` as the last parameter. + ) + + $(P If the `format` argument is a string literal, it is verified to be a valid format string + per the C99 Standard. If the `format` parameter is followed by `...`, the number and types + of the variadic arguments are checked against the format string.) + + $(P Diagnosed incompatibilities are:) + + $(UL + $(LI incompatible sizes which may cause argument misalignment) + $(LI deferencing arguments that are not pointers) + $(LI insufficient number of arguments) + $(LI struct arguments) + $(LI array and slice arguments) + $(LI non-pointer arguments to `s` specifier) + $(LI non-standard formats) + $(LI undefined behavior per C99) + ) + + $(P Per the C99 Standard, extra arguments are ignored.) + + $(P Ignored mismatches are:) + + $(UL + $(LI sign mismatches, such as printing an `int` with a `%u` format) + $(LI integral promotion mismatches, where the format specifies a smaller integral + type than `int` or `uint`, such as printing a `short` with the `%d` format rather than `%hd`) + ) + + --- + printf("%k\n", value); // error: non-Standard format k + printf("%d\n"); // error: not enough arguments + printf("%d\n", 1, 2); // ok, extra arguments ignored + --- + + $(BEST_PRACTICE + In order to use non-Standard printf/scanf formats, an easy workaround is: + --- + const format = "%k\n"; + printf(format.ptr, value); // no error + --- + ) + + $(BEST_PRACTICE + Most of the errors detected are portability issues. For instance, + + --- + string s; + printf("%.*s\n", s.length, s.ptr); + printf("%d\n", s.sizeof); + ulong u; + scanf("%lld%*c\n", &u); + --- + should be replaced with: + --- + string s; + printf("%.*s\n", cast(int) s.length, s.ptr); + printf("%zd\n", s.sizeof); + ulong u; + scanf("%llu%*c\n", &u); + --- + ) + + $(P `pragma(printf)` applied to declarations that are not functions are ignored. + In particular, it has no effect on the declaration of a pointer to function type. + ) + + +$(H3 $(LNAME2 scanf, $(D pragma scanf))) + + $(P `pragma(scanf)` specifies that a function declaration is a scanf-like function, meaning + it is an `extern (C)` or `extern (C++)` function with a `format` parameter accepting a + pointer to a 0-terminated `char` string conforming to the C99 Standard 7.19.6.2, immediately followed + by either a `...` variadic argument list or a parameter of type `va_list` as the last parameter. + ) + + $(P If the `format` argument is a string literal, it is verified to be a valid format string + per the C99 Standard. If the `format` parameter is followed by `...`, the number and types + of the variadic arguments are checked against the format string.) + + $(P Diagnosed incompatibilities are:) + + $(UL + $(LI argument is not a pointer to the format specified type) + $(LI insufficient number of arguments) + $(LI non-standard formats) + $(LI undefined behavior per C99) + ) + + $(P Per the C99 Standard, extra arguments are ignored.) + + $(P `pragma(scanf)` applied to declarations that are not functions are ignored. + In particular, it has no effect on the declaration of a pointer to function type. + ) + + + + +$(H3 $(LNAME2 startaddress, $(D pragma startaddress))) + + $(P There must be one $(ASSIGNEXPRESSION) and it must evaluate at compile time to a function symbol.) + + $(IMPLEMENTATION_DEFINED The function symbol specifies the start address for the program. + The symbol is inserted into the object file or is otherwise presented to the linker to + set the start address. + This is not normally used for application level programming, + but is for specialized systems work. + For applications code, the start address is taken care of + by the runtime library. + +----------------- +void foo() { ... } +pragma(startaddress, foo); +----------------- + + ) + +$(H2 $(LNAME2 vendor_specific_pragmas, Vendor Specific Pragmas)) + + $(P Vendor specific pragma $(I Identifier)s can be defined if they + are prefixed by the vendor's trademarked name, in a similar manner + to version identifiers: + ) + + --- + pragma(DigitalMars_extension) { ... } + --- + + $(P Implementations must diagnose an error for unrecognized $(I Pragma)s, + even if they are vendor specific ones. + ) + + $(IMPLEMENTATION_DEFINED Vendor specific pragmas.) + + + $(BEST_PRACTICE vendor + specific pragmas should be wrapped in version statements + + --- + version (DigitalMars) + { + pragma(DigitalMars_extension) + { ... } + } + --- + ) + +$(SPEC_SUBNAV_PREV_NEXT attribute, Attributes, expression, Expressions) +) + +Macros: + CHAPTER=10 + TITLE=Pragmas diff --git a/spec/property.dd b/spec/property.dd new file mode 100644 index 0000000000..2ca0e2e095 --- /dev/null +++ b/spec/property.dd @@ -0,0 +1,347 @@ +Ddoc + +$(SPEC_S Properties, + +$(HEADERNAV_TOC) + +$(H2 $(LNAME2 common, Common Properties)) + + $(P Every symbol, type, and expression has properties that can be queried:) + +$(TABLE +$(THEAD Property, Description) +$(TROW $(RELATIVE_LINK2 mangleof, $(D .mangleof)), string representing the $(SINGLEQUOTE mangled) representation of the type) +$(TROW $(RELATIVE_LINK2 stringof, $(D .stringof)), string representing the source representation of the type) +) + +$(TABLE2 Examples, +$(THEAD Expression, Value) +$(TROW $(D int.mangleof), yields the string "i") +$(TROW $(D int.stringof), yields the string "int") +$(TROW $(D (1+2).stringof), yields the string "1 + 2") +) + +$(H2 $(LNAME2 type, Type Properties)) + + $(P Every type has properties that can be queried. Every expression also + has these properties, which are equivalent to the properties of the + expression's type. These properties are:) + +$(TABLE +$(THEAD Property, Description) +$(TROW $(RELATIVE_LINK2 init, $(D .init)), initializer) +$(TROW $(RELATIVE_LINK2 sizeof, $(D .sizeof)), size in bytes) +$(TROW $(RELATIVE_LINK2 alignof, $(D .alignof)), alignment size) +) + +$(TABLE2 Examples, +$(THEAD Expression, Value) +$(TROW $(D int.init), yields 0) +$(TROW $(D int.sizeof), yields 4) +$(TROW $(D (3).sizeof), yields 4 (because 3 is an int)) +) + +$(H2 $(LNAME2 numeric, Numeric Properties)) + +$(TABLE2 Properties for Integral Types, +$(THEAD Property, Description) +$(TROW $(D .max), maximum value) +$(TROW $(D .min), minimum value) +) + +$(BR) + +$(TABLE_2COLS Properties for Floating Point Types, +$(THEAD Property, Description) +$(TROW $(D .infinity), infinity value) +$(TROW $(D .nan), NaN - $(HTTPS en.wikipedia.org/wiki/NaN, Not a Number) value + (other NaN values can be produced)) +$(TROW $(D .dig), number of decimal digits of precision) +$(TROW $(D .epsilon), smallest increment to the value 1) +$(TROW $(D .mant_dig), number of bits in mantissa) +$(TROW $(D .max_10_exp), maximum int value such that 10$(SUPERSCRIPT $(D max_10_exp)) is representable) +$(TROW $(D .max_exp), maximum int value such that 2$(SUPERSCRIPT $(D max_exp-1)) is representable) +$(TROW $(D .min_10_exp), minimum int value such that 10$(SUPERSCRIPT $(D min_10_exp)) is representable as a normalized value) +$(TROW $(D .min_exp), minimum int value such that 2$(SUPERSCRIPT $(D min_exp-1)) is representable as a normalized value) +$(TROW $(D .max), largest representable value that's not infinity) + +$(TROW $(D .min_normal), smallest representable normalized value that's not 0) +$(TROW $(D .re), real part) +$(TROW $(D .im), imaginary part) +) + +$(TABLE2 Floating Point Examples, +$(THEAD Expression, Value) +$(TROW $(D float.nan), yields the floating point NaN value) +$(TROW $(D (2.5F).nan), yields the floating point NaN value) +) + +$(H2 $(LNAME2 derived-type, Derived Type Properties)) + + $(P See:) + + * $(DDSUBLINK spec/arrays, array-properties, Array Properties) + * $(DDSUBLINK spec/hash-map, properties, Associative Array Properties) + * $(DDSUBLINK spec/simd, properties, Vector Properties) + + +$(H2 $(LNAME2 user-defined-type, User-Defined Type Properties)) + + $(P See:) + + * $(DDSUBLINK spec/class, class_properties, Class Properties) + * $(DDSUBLINK spec/enum, enum_properties, Enum Properties) + * $(DDSUBLINK spec/struct, struct_properties, Struct Properties) + + +$(H2 $(LNAME2 init, .init Property)) + + $(P $(D .init) produces a constant expression that is the default + initializer. If applied to a type, it is the default initializer + for that type. If applied to a variable or field, it is the + default initializer for that variable or field's type. + The default values for different kinds of types are described below: + ) + +$(TABLE +$(THEAD Type, `.init` Value) +$(TROW `char`, `'\xff'`) +$(TROW `dchar`, `'\xffff'`) +$(TROW `wchar`, `'\xffff'`) +$(TROW Enum, first member value) +$(TROW Integers, `0`) +$(TROW Floating Point, NaN) +$(TROW Reference Types, `null`) +$(TROW Structs, each $(DDSUBLINK spec/struct, default_struct_init, field's default value)) +$(TROW Unions, first member value) +) + + $(RATIONALE Where possible, the default value for a type is an invalid value.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +---------------- +int a; +int b = 1; + +static assert(int.init == 0); +static assert(a.init == 0); +static assert(b.init == 0); + +struct Foo +{ + int a; + int b = 7; +} + +static assert(Foo.init.a == 0); +static assert(Foo.init.b == 7); +---------------- +) + +$(H3 $(LNAME2 init-vs-construction, `.init` vs Default Construction)) + + $(P Note that $(D .init) produces a default initialized object, not a + default constructed one. If there is a default constructor for an object, + it may produce a different value.) + + $(OL + $(LI If $(D T) is a nested struct, the context pointer in $(D T.init) + is $(D null).) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +---------------- +void main() +{ + int x; + struct S + { + void foo() { x = 1; } // access x in enclosing scope via context pointer + } + S s1; // OK. S() correctly initialize its context pointer. + S s2 = S(); // OK. same as s1 + s1.foo(); // OK + + S s3 = S.init; // Bad. the context pointer in s3 is null + s3.foo(); // Access violation +} +---------------- +) + $(LI If $(D T) is a struct which has $(CODE @disable this();), $(D T.init) + might return a logically incorrect object.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +---------------- +struct S +{ + int x; + @disable this(); + this(int n) { x = n; } + invariant { assert(x > 0); } + void check() {} +} + +void main() +{ + //S s1; // Error: variable s1 initializer required for type S + //S s2 = S(); // Error: constructor S.this is not callable + // because it is annotated with @disable + S s3 = S.init; // Bad. s3.x == 0, and it violates the invariant of S + s3.check(); // Assertion failure +} +---------------- +) + ) + + +$(H2 $(LNAME2 stringof, .stringof Property)) + + $(P $(D .stringof) produces a constant string that is the + source representation of its prefix. + If applied to a type, it is the string for that type. + If applied to an expression, it is the source representation + of that expression. The expression will not be evaluated. + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + module test; + import std.stdio; + + struct Dog { } + + enum Color { Red } + + int i = 4; + + void main() + { + writeln((1+2).stringof); // "1 + 2" + writeln(test.stringof); // "module test" + writeln(Dog.stringof); // "Dog" + writeln(int.stringof); // "int" + writeln((int*[5][]).stringof); // "int*[5][]" + writeln(Color.Red.stringof); // "Red" + writeln((5).stringof); // "5" + + writeln((++i).stringof); // "i += 1" + assert(i == 4); // `++i` was not evaluated + } + --- + ) + + $(IMPLEMENTATION_DEFINED The string representation for a type or expression + can vary.) + + $(BEST_PRACTICE Do not use `.stringof` for code generation. + Instead use the + $(DDSUBLINK spec/traits, identifier, identifier) trait, + or one of the Phobos helper functions such as $(REF fullyQualifiedName, std,traits).) + +$(H2 $(LNAME2 sizeof, .sizeof Property)) + + $(P $(CODE e.sizeof) gives the size in bytes of the expression + $(D e). + ) + + $(P When getting the size of a member, it is not necessary for + there to be a $(I this) object: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct S +{ + int a; +} + +static assert(S.a.sizeof == 4); +static assert(Object.sizeof == (void*).sizeof); +--- +) + + $(P $(CODE .sizeof) applied to a class object returns the size of + the class reference, not the class instantiation.) + + $(P See also: $(DDSUBLINK spec/traits, classInstanceSize, `__traits(classInstanceSize)`).) + +$(H2 $(LNAME2 alignof, .alignof Property)) + + $(P $(CODE .alignof) gives the aligned size of an expression or type. + For example, an aligned size of 1 means that it is aligned on + a byte boundary, 4 means it is aligned on a 32 bit boundary. + ) + + $(P See $(DDSUBLINK spec/attribute, align, the `align` attribute) for an example.) + + $(IMPLEMENTATION_DEFINED the actual aligned size.) + + $(BEST_PRACTICE Be particularly careful when laying out an object that must + line up with an externally imposed layout. Data misalignment can result in + particularly pernicious bugs. It's often worth putting in an `assert` to assure + it is correct.) + +$(H2 $(LNAME2 mangleof, .mangleof Property)) + + $(P Mangling refers to how a symbol is represented in text form in the + generated object file. $(CODE .mangleof) returns a string literal + of the representation of the type or symbol it is applied to. + The mangling of types and symbols with D linkage is defined by + $(DDSUBLINK spec/abi, name_mangling, Name Mangling). + ) + + $(IMPLEMENTATION_DEFINED + $(OL + $(LI whether a leading underscore is added to a symbol) + $(LI the mangling of types and symbols with non-D linkage. + For C and C++ linkage, this will typically + match what the associated C or C++ compiler does.) + ) + ) + +$(H2 $(LNAME2 classinfo, .classinfo Property)) + +$(P $(CODE .classinfo) provides information about the dynamic type of a class +object. It returns a reference to type $(DDLINK phobos/object, TypeInfo_Class, +$(D object.TypeInfo_Class)).) + +$(P $(CODE .classinfo) applied to an interface gives the information for the +interface, not the class it might be an instance of.) + +$(H2 $(LNAME2 tupleof, .tupleof Property)) + +$(P $(CODE .tupleof) provides a symbol sequence of all the non-static fields in a struct or class. +The order of the fields in the tuple matches the order in which the fields are declared. + +For classes, hidden fields and fields of the bass class are excluded. + +A common use case is to iterate over the fields with a $(CODE foreach) loop.) + +--- +struct Vector3 +{ + int x, y, z; +} + +void test() +{ + Vector3 v = Vector3(5, 10, 15); + float sum = 0; + foreach(num; v.tupleof) + { + sum+= num; + } + writeln(sum); //30 +} +--- + + +$(H2 $(LNAME2 classproperties, User-Defined Properties)) + + $(P User-defined properties can be created using $(LINK2 function.html#property-functions, Property Functions).) + +$(SPEC_SUBNAV_PREV_NEXT type, Types, attribute, Attributes) +) + +Macros: + CHAPTER=8 + TITLE=Properties diff --git a/spec/simd.dd b/spec/simd.dd new file mode 100644 index 0000000000..7698debcc0 --- /dev/null +++ b/spec/simd.dd @@ -0,0 +1,282 @@ +Ddoc + +$(SPEC_S Vector Extensions, + +$(HEADERNAV_TOC) + + $(P CPUs often support specialized vector types and vector + operations (a.k.a. $(I media instructions)). + Vector types are a fixed array of floating or integer types, and + vector operations operate simultaneously on them.) + + $(P Specialized $(GLINK2 type, Vector) types provide access to them.) + + $(P The $(GLINK2 type, VectorBaseType) must be a $(DDSUBLINK spec/arrays, static-arrays, Static Array). + The $(GNAME VectorElementType) is the unqualified element type of the + static array. + The dimension of the static array is the number + of elements in the vector. + ) + + $(IMPLEMENTATION_DEFINED Which vector types are supported depends + on the target. The implementation is expected to only support + the vector types and operations that are implemented in the target's hardware. + ) + + $(RATIONALE Emulating unsupported vector types and operations can exhibit + such poor performance that the user is likely better off selecting a different + algorithm than relying on emulation.) + + $(BEST_PRACTICE Use the declarations in $(CORE_SIMD) instead of + the language $(GLINK2 type, Vector) grammar. + ) + +$(H2 $(LNAME2 core_simd, $(D core.simd))) + + $(P Vector types and operations are introduced by importing + $(CORE_SIMD):) + +--- +import core.simd; +--- + + $(IMPLEMENTATION_DEFINED + These types and operations will be the ones defined for the architecture + the compiler is targeting. If a particular CPU family has varying + support for vector types, an additional runtime check may be necessary. + The compiler does not emit runtime checks; those must be done by the + programmer. + ) + + $(IMPLEMENTATION_DEFINED Depending on the target architecture, compiler flags + may be required to + activate support for SIMD types. + ) + + $(P The types defined will all follow the naming convention:) + +$(GRAMMAR_INFORMATIVE +$(I typeNN) +) + where $(I type) is the vector element type and $(I NN) is the number + of those elements in the vector type. + The type names will not be keywords. + +$(H3 $(LNAME2 properties, Properties)) + + $(P Vector types have the property:) + + $(TABLE2 Vector Type Properties, + $(THEAD Property, Description) + $(TROW .array, Returns static array representation) + ) + + $(P Vectors support the following properties based + on the vector element type. + The value produced is that of a + vector of the same type with each element set to the + value corresponding to the property value for the element + type.) + + $(TABLE2 Integral Vector Type Properties, + $(THEAD Property, Description) + $(TROW .min, minimum value) + $(TROW .max, maximum value) + ) + + $(TABLE2 Floating Point Vector Type Properties, + $(THEAD Property, Description) + $(TROW .epsilon, smallest increment to the value 1) + $(TROW .infinity, infinity value) + $(TROW .max, largest representable value that is not infinity) + $(TROW .min_normal, smallest representable value that is not 0) + $(TROW .nan, NaN value) + ) + +$(H3 $(LNAME2 conversions, Conversions)) + + $(P Vector types of the same size (number_of_elements * size_of_element) + can be implicitly converted among + each other, this is done as a reinterpret cast (a type paint). + Vector types can be cast to their $(GLINK2 type, VectorBaseType).) + + $(P Integers and floating point values can be implicitly converted + to their vector equivalents:) + +--- +int4 v = 7; +v = 3 + v; // add 3 to each element in v +--- + +$(H3 $(LNAME2 accessing_individual_elems, Accessing Individual Vector Elements)) + + $(P They cannot be accessed directly, but can be when converted to + an array type:) + +---- +int4 v; +(cast(int*)&v)[3] = 2; // set 3rd element of the 4 int vector +(cast(int[4])v)[3] = 2; // set 3rd element of the 4 int vector +v.array[3] = 2; // set 3rd element of the 4 int vector +v.ptr[3] = 2; // set 3rd element of the 4 int vector +---- + + +$(H3 $(LNAME2 conditional_compilation, Conditional Compilation)) + + $(P If vector extensions are implemented, the + $(DDSUBLINK spec/version, PredefinedVersions, version identifier) + $(D D_SIMD) is set.) + + $(P Whether a type exists or not can be tested at compile time with + an $(DDSUBLINK spec/expression, IsExpression, $(I IsExpression)): + ) + +--- +static if (is(typeNN)) + ... yes, it is supported ... +else + ... nope, use workaround ... +--- + + $(P Whether a particular operation on a type is supported can be tested + at compile time with: + ) + +--- +float4 a,b; +static if (__traits(compiles, a+b)) + ... yes, add is supported for float4 ... +else + ... nope, use workaround ... +--- + + $(P For runtime testing to see if certain vector instructions are + available, see the functions in + $(LINK2 $(ROOT_DIR)phobos/core_cpuid.html, core.cpuid). + ) + + $(P A typical workaround for unsupported vector operations would be to + use array operations instead:) + +--- +float4 a,b; +static if (__traits(compiles, a/b)) + c = a / b; +else + c[] = a[] / b[]; +--- + +$(H2 $(LNAME2 x86_64_vec, X86 And X86$(UNDERSCORE)64 Vector Extension Implementation)) + + $(IMPLEMENTATION_DEFINED + + $(P The following describes the specific implementation of the + vector types for the X86 and X86$(UNDERSCORE)64 architectures. + ) + + $(P The vector extensions are currently implemented for the OS X 32 + bit target, and all 64 bit targets.) + + $(P $(CORE_SIMD) defines the following types: ) + + $(TABLE2 Vector Types, + $(THEAD Type Name, Description, gcc Equivalent) + $(TROW void16, 16 bytes of untyped data, $(I no equivalent)) + $(TROW byte16, 16 $(D byte)s, $(D signed char __attribute__((vector_size(16))))) + $(TROW ubyte16, 16 $(D ubyte)s, $(D unsigned char __attribute__((vector_size(16))))) + $(TROW short8, 8 $(D short)s, $(D short __attribute__((vector_size(16))))) + $(TROW ushort8, 8 $(D ushort)s, $(D ushort __attribute__((vector_size(16))))) + $(TROW int4, 4 $(D int)s, $(D int __attribute__((vector_size(16))))) + $(TROW uint4, 4 $(D uint)s, $(D unsigned __attribute__((vector_size(16))))) + $(TROW long2, 2 $(D long)s, $(D long __attribute__((vector_size(16))))) + $(TROW ulong2, 2 $(D ulong)s, $(D unsigned long __attribute__((vector_size(16))))) + $(TROW float4, 4 $(D float)s, $(D float __attribute__((vector_size(16))))) + $(TROW double2, 2 $(D double)s, $(D double __attribute__((vector_size(16))))) + $(TROW void32, 32 bytes of untyped data, $(I no equivalent)) + $(TROW byte32, 32 $(D byte)s, $(D signed char __attribute__((vector_size(32))))) + $(TROW ubyte32, 32 $(D ubyte)s, $(D unsigned char __attribute__((vector_size(32))))) + $(TROW short16, 16 $(D short)s, $(D short __attribute__((vector_size(32))))) + $(TROW ushort16, 16 $(D ushort)s, $(D ushort __attribute__((vector_size(32))))) + $(TROW int8, 8 $(D int)s, $(D int __attribute__((vector_size(32))))) + $(TROW uint8, 8 $(D uint)s, $(D unsigned __attribute__((vector_size(32))))) + $(TROW long4, 4 $(D long)s, $(D long __attribute__((vector_size(32))))) + $(TROW ulong4, 4 $(D ulong)s, $(D unsigned long __attribute__((vector_size(32))))) + $(TROW float8, 8 $(D float)s, $(D float __attribute__((vector_size(32))))) + $(TROW double4, 4 $(D double)s, $(D double __attribute__((vector_size(32))))) + ) + + $(NOTE for 32 bit gcc and clang, it's $(D long long) instead of $(D long).) + + $(TABLE2 Supported 128-bit Vector Operators, + $(THEAD Operator,void16,byte16,ubyte16,short8,ushort8,int4,uint4,long2,ulong2,float4,double2) + $(TROW =,$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW +,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW -,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW *,$(N),$(N),$(N),$(Y),$(Y),$(N),$(N),$(N),$(N),$(Y),$(Y)) + $(TROW /,$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(Y),$(Y)) + $(TROW $(CODE_AMP),$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW |,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW $(D ^),$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW +=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW -=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW *=,$(N),$(N),$(N),$(Y),$(Y),$(N),$(N),$(N),$(N),$(Y),$(Y)) + $(TROW /=,$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(Y),$(Y)) + $(TROW $(CODE_AMP)=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW |=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW $(D ^=),$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW ==,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW !=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW <, $(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW <=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW >=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW >, $(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW $(I unary)$(D ~),$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW $(I unary)+,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW $(I unary)-,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + ) + + $(TABLE2 Supported 256-bit Vector Operators, + $(THEAD Operator,void32,byte32,ubyte32,short16,ushort16,int8,uint8,long4,ulong4,float8,double4) + $(TROW =,$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW +,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW -,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW *,$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(Y),$(Y)) + $(TROW /,$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(Y),$(Y)) + $(TROW $(CODE_AMP),$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW |,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW $(D ^),$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW +=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW -=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW *=,$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(Y),$(Y)) + $(TROW /=,$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(N),$(Y),$(Y)) + $(TROW $(CODE_AMP)=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW |=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW $(D ^=),$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW ==,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW !=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW <, $(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW <=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW >=,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW >, $(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW $(I unary)$(D ~),$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(N),$(N)) + $(TROW $(I unary)+,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + $(TROW $(I unary)-,$(N),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y),$(Y)) + ) + + $(P Operators not listed are not supported at all.) + + ) + +$(H3 $(LNAME2 vector_op_intrinsics, Vector Operation Intrinsics)) + + $(P See $(CORE_SIMD) for the supported intrinsics.) +$(SPEC_SUBNAV_PREV_NEXT abi, Application Binary Interface, betterc, Better C) +) + +Macros: + CHAPTER=40 + TITLE=Vector Extensions + Y=$(TIMES) + N=$(NDASH) + CORE_SIMD=$(LINK2 $(ROOT_DIR)phobos/core_simd.html, $(D core.simd)) diff --git a/spec/spec.dd b/spec/spec.dd new file mode 100644 index 0000000000..13bf3f6423 --- /dev/null +++ b/spec/spec.dd @@ -0,0 +1,67 @@ +Ddoc + +$(TOC Table of Contents, + $(P This is the specification for the D Programming Language. + For more information see $(AHTTP dlang.org, dlang.org).) + + $(NOT_EBOOK $(P This is also available as a + $(LINK2 $(ROOT_DIR)dlangspec.mobi, Mobi ebook). + $(COMMENT uncomment this once the Kindle ebook has been updated + or as a + $(AMAZONLINK B005CCQPKK, Kindle ebook). + ) + )) + + $(TOC_LISTING $(ITEMIZE + $(A intro.html, Introduction), + $(A lex.html, Lexical), + $(A istring.html, Interpolation Expression Sequence), + $(A grammar.html, Grammar), + $(A module.html, Modules), + $(A declaration.html, Declarations), + $(A type.html, Types), + $(A property.html, Properties), + $(A attribute.html, Attributes), + $(A pragma.html, Pragmas), + $(A expression.html, Expressions), + $(A statement.html, Statements), + $(A arrays.html, Arrays), + $(A hash-map.html, Associative Arrays), + $(A struct.html, Structs and Unions), + $(A class.html, Classes), + $(A interface.html, Interfaces), + $(A enum.html, Enums), + $(A const3.html, Type Qualifiers), + $(A function.html, Functions), + $(A operatoroverloading.html, Operator Overloading), + $(A template.html, Templates), + $(A template-mixin.html, Template Mixins), + $(A contracts.html, Contract Programming), + $(A version.html, Conditional Compilation), + $(A traits.html, Traits), + $(A errors.html, Error Handling), + $(A unittest.html, Unit Tests), + $(A garbage.html, Garbage Collection), + $(A float.html, Floating Point), + $(A iasm.html, D x86 Inline Assembler), + $(A ddoc.html, Embedded Documentation), + $(A interfaceToC.html, Interfacing to C), + $(A cpp_interface.html, Interfacing to C++), + $(A objc_interface.html, Interfacing to Objective-C), + $(A portability.html, Portability Guide), + $(A entity.html, Named Character Entities), + $(A memory-safe-d.html, Memory Safety), + $(A abi.html, Application Binary Interface), + $(A simd.html, Vector Extensions), + $(A betterc.html, Better C), + $(A importc.html, Import C), + $(A ob.html, Live Functions), + $(A windows.html, Windows Programming), + $(A glossary.html, Glossary), + $(A legacy.html, Legacy Code) + )) +) + +Macros: + TITLE=Table of Contents + BODY_PREFIX=$(COMMENT Suppress numbering in this page) diff --git a/spec/spec.ddoc b/spec/spec.ddoc new file mode 100644 index 0000000000..77dcba7155 --- /dev/null +++ b/spec/spec.ddoc @@ -0,0 +1,144 @@ +ROOT_DIR = ../ +ROOT = .. +SEARCHDEFAULT_SPEC = selected +DDOC_BLANKLINE = $(DIVC blankline) + + +_ = special specification boxes +$(COMMENT While not part of the spec, best practices offers advice on how to best use a feature) +BEST_PRACTICE= $(DIVC spec-boxes best-practice, $(B Best Practices:) $0) + +$(COMMENT Identifies implementation-defined behavior in the spec) +IMPLEMENTATION_DEFINED=$(DIVC spec-boxes implementation-defined, $(B Implementation Defined:) $0) + +$(COMMENT Identifies undefined-defined behavior in the spec) +UNDEFINED_BEHAVIOR=$(DIVC spec-boxes undefined-behavior, $(B Undefined Behavior:) $0) + +$(COMMENT While not part of the spec, an explanation for something unexpected) +RATIONALE= $(DIVC spec-boxes rationale, $(B Rationale:) $0) + +$(COMMENT While not part of the spec, provides additional relevant information) +NOTE= $(DIVC spec-boxes note, $(B Note:) $0) + +_ = + +BODY_PREFIX = +$(T style, + body { counter-reset: h1 $(CHAPTER); counter-increment: h1 -1; } + h1 { counter-reset: h2 h3 p; } + h2 { counter-reset: h3 h4 p; } + h3 { counter-reset: h4 p; } + h4 { counter-reset: p; } + h1::before { + counter-increment: h1; + content: counter(h1) ". "; + } + .hyphenate h2::before { + counter-increment: h2; + content: counter(h1) "." counter(h2) " "; + } + h3::before { + counter-increment: h3; + content: counter(h1) "." counter(h2) "." counter(h3) " "; + } + h4::before { + counter-increment: h4; + content: counter(h1) "." counter(h2) "." counter(h3) "." counter(h4) " "; + } + p::before, .spec-boxes::before { + counter-increment: p; + content: counter(p) ". "; + } + h1::before, h2::before, h3::before, h4::before, p::before, .spec-boxes::before + { + color: #999; + font-size: 80%; + margin-right: 0.25em; + } +) + +SUBNAV_HEAD = $(DIVC head, $(H2 $1) $(TC p, $4, $(LINK2 $2, $3))) +SUBNAV=$(SUBNAV_SPEC) +SUBNAV_SPEC= +$(SUBNAV_TEMPLATE + $(SUBNAV_HEAD Language Reference, $(ROOT_DIR)spec/spec.html, table of contents, subnav-duplicate) + $(UL + $(SUBMENU2 + $(ROOT_DIR)spec/intro.html, Introduction, + $(ROOT_DIR)spec/lex.html, Lexical, + $(ROOT_DIR)spec/istring.html, Interpolation Expression Sequence, + $(ROOT_DIR)spec/grammar.html, Grammar, + $(ROOT_DIR)spec/module.html, Modules, + $(ROOT_DIR)spec/declaration.html, Declarations, + $(ROOT_DIR)spec/type.html, Types, + $(ROOT_DIR)spec/property.html, Properties, + $(ROOT_DIR)spec/attribute.html, Attributes, + $(ROOT_DIR)spec/pragma.html, Pragmas, + $(ROOT_DIR)spec/expression.html, Expressions, + $(ROOT_DIR)spec/statement.html, Statements, + $(ROOT_DIR)spec/arrays.html, Arrays, + $(ROOT_DIR)spec/hash-map.html, Associative Arrays, + $(ROOT_DIR)spec/struct.html, Structs and Unions, + $(ROOT_DIR)spec/class.html, Classes, + $(ROOT_DIR)spec/interface.html, Interfaces, + $(ROOT_DIR)spec/enum.html, Enums, + $(ROOT_DIR)spec/const3.html, Type Qualifiers, + $(ROOT_DIR)spec/function.html, Functions, + $(ROOT_DIR)spec/operatoroverloading.html, Operator Overloading, + $(ROOT_DIR)spec/template.html, Templates, + $(ROOT_DIR)spec/template-mixin.html, Template Mixins, + $(ROOT_DIR)spec/contracts.html, Contract Programming, + $(ROOT_DIR)spec/version.html, Conditional Compilation, + $(ROOT_DIR)spec/traits.html, Traits, + $(ROOT_DIR)spec/errors.html, Error Handling, + $(ROOT_DIR)spec/unittest.html, Unit Tests, + $(ROOT_DIR)spec/garbage.html, Garbage Collection, + $(ROOT_DIR)spec/float.html, Floating Point, + $(ROOT_DIR)spec/iasm.html, D x86 Inline Assembler, + $(ROOT_DIR)spec/ddoc.html, Embedded Documentation, + $(ROOT_DIR)spec/interfaceToC.html, Interfacing to C, + $(ROOT_DIR)spec/cpp_interface.html, Interfacing to C++, + $(ROOT_DIR)spec/objc_interface.html, Interfacing to Objective-C, + $(ROOT_DIR)spec/portability.html, Portability Guide, + $(ROOT_DIR)spec/entity.html, Named Character Entities, + $(ROOT_DIR)spec/memory-safe-d.html, Memory Safety, + $(ROOT_DIR)spec/abi.html, Application Binary Interface, + $(ROOT_DIR)spec/simd.html, Vector Extensions, + $(ROOT_DIR)spec/betterc.html, Better C, + $(ROOT_DIR)spec/importc.html, ImportC, + $(ROOT_DIR)spec/ob.html, Live Functions, + $(ROOT_DIR)spec/windows.html, Windows Programming, + $(ROOT_DIR)spec/glossary.html, Glossary, + $(ROOT_DIR)spec/legacy.html, Legacy Code + ) + ) +) +SPEC_RUNNABLE_EXAMPLE=$(RUNNABLE_EXAMPLE $0) +SPEC_RUNNABLE_EXAMPLE_COMPILE=$(RUNNABLE_EXAMPLE_COMPILE $0) +SPEC_RUNNABLE_EXAMPLE_FAIL=$(RUNNABLE_EXAMPLE $0) +SPEC_RUNNABLE_EXAMPLE_RUN=$(RUNNABLE_EXAMPLE $0) +SPEC_SUBNAV_NEXT= +$(SPEC_NEXT $(LINK2 $(ROOT_DIR)spec/$1.html, $2)) +$(CLEAR) + +SPEC_SUBNAV_PREV_NEXT= +$(SPEC_PREV $(LINK2 $(ROOT_DIR)spec/$1.html, $2)) +$(SPEC_NEXT $(LINK2 $(ROOT_DIR)spec/$3.html, $4)) +$(CLEAR) + +SPEC_SUBNAV_PREV= +$(SPEC_PREV $(LINK2 $(ROOT_DIR)spec/$1.html, $2)) +$(CLEAR) + +SPEC_NEXT=<div style="float: right">$1 $(FA_ICON angle-right)</div> +SPEC_PREV=<div style="float: left">$(FA_ICON angle-left) $1</div> + +_= + +CLEAR=<div style="clear:both"></div> +RAWHTML=$0 +_= +LAYOUT_SUFFIX = +$(SCRIPTLOAD ../js/listanchors.js) +$(SCRIPT jQuery(document).ready(addVersionSelector);) +_= diff --git a/spec/statement.dd b/spec/statement.dd new file mode 100644 index 0000000000..34f5f645f2 --- /dev/null +++ b/spec/statement.dd @@ -0,0 +1,2474 @@ +Ddoc + +$(SPEC_S Statements, + +$(HEADERNAV_TOC) + + $(P The order of execution within a function is controlled by $(GLINK Statement)s. + A function's body consists of a sequence of zero or more $(I Statement)s. + Execution occurs in lexical order, though certain statements may have deferred effects. + A $(I Statement) has no value; it is executed for its effects. + ) + +$(GRAMMAR +$(GNAME Statement): + $(GLINK EmptyStatement) + $(GLINK NonEmptyStatement) + $(GLINK ScopeBlockStatement) + +$(GNAME EmptyStatement): + $(D ;) + +$(GNAME NoScopeNonEmptyStatement): + $(GLINK NonEmptyStatement) + $(GLINK BlockStatement) + +$(GNAME NoScopeStatement): + $(GLINK EmptyStatement) + $(GLINK NonEmptyStatement) + $(GLINK BlockStatement) + +$(GNAME NonEmptyOrScopeBlockStatement): + $(GLINK NonEmptyStatement) + $(GLINK ScopeBlockStatement) + +$(GNAME NonEmptyStatement): + $(GLINK NonEmptyStatementNoCaseNoDefault) + $(GLINK CaseStatement) + $(GLINK CaseRangeStatement) + $(GLINK DefaultStatement) + +$(GNAME NonEmptyStatementNoCaseNoDefault): + $(GLINK LabeledStatement) + $(GLINK ExpressionStatement) + $(GLINK DeclarationStatement) + $(GLINK IfStatement) + $(GLINK WhileStatement) + $(GLINK DoStatement) + $(GLINK ForStatement) + $(GLINK ForeachStatement) + $(GLINK SwitchStatement) + $(GLINK FinalSwitchStatement) + $(GLINK ContinueStatement) + $(GLINK BreakStatement) + $(GLINK ReturnStatement) + $(GLINK GotoStatement) + $(GLINK WithStatement) + $(GLINK SynchronizedStatement) + $(GLINK TryStatement) + $(GLINK ScopeGuardStatement) + $(GLINK AsmStatement) + $(GLINK MixinStatement) + $(GLINK ForeachRangeStatement) + $(GLINK2 pragma, PragmaStatement) + $(GLINK2 version, ConditionalStatement) + $(GLINK2 version, StaticForeachStatement) + $(GLINK2 module, ImportDeclaration) +) + + $(P Any ambiguities in the grammar between $(I Statement)s and + $(GLINK2 declaration, Declaration)s are + resolved by the declarations taking precedence. + Wrapping such a statement in parentheses will + disambiguate it in favor of being a $(I Statement). + ) + +$(H2 $(LEGACY_LNAME2 ScopeStatement, scope-statement, Scope Statements)) + +$(GRAMMAR +$(GNAME ScopeStatement): + $(GLINK NonEmptyStatement) + $(GLINK BlockStatement) +) + + $(P A new scope for local symbols + is introduced for the $(I NonEmptyStatement) + or $(GLINK BlockStatement). + ) + + $(P Even though a new scope is introduced, + local symbol declarations cannot shadow (hide) other + local symbol declarations in the same function. + ) + +-------------- +void func1(int x) +{ + int x; // illegal, x shadows parameter x + + int y; + + { int y; } // illegal, y shadows enclosing scope's y + + void delegate() dg; + dg = { int y; }; // ok, this y is not in the same function + + struct S + { + int y; // ok, this y is a member, not a local + } + + { int z; } + { int z; } // ok, this z is not shadowing the other z + + { int t; } + { t++; } // illegal, t is undefined +} +-------------- + + $(BEST_PRACTICE Local declarations within a function should + all have unique names, even if they are in non-overlapping scopes. + ) + + +$(H2 $(LEGACY_LNAME2 ScopeBlockStatement, scope-block-statement, Scope Block Statements)) + +$(GRAMMAR +$(GNAME ScopeBlockStatement): + $(GLINK BlockStatement) +) + + $(P A scope block statement introduces a new scope for the + $(GLINK BlockStatement). + ) + +$(H2 $(LEGACY_LNAME2 LabeledStatement, labeled-statement, Labeled Statements)) + +$(P Statements can be labeled. A label is an identifier that + precedes a statement. +) + +$(GRAMMAR +$(GNAME LabeledStatement): + $(GLINK_LEX Identifier) $(D :) + $(GLINK_LEX Identifier) $(D :) $(PSSEMI_PSCURLYSCOPE) +) + +$(P + Any statement can be labeled, including empty statements, + and so can serve as the target of a $(RELATIVE_LINK2 goto-statement, goto statement). + Labeled statements can also serve as the + target of a $(RELATIVE_LINK2 break-statement, break) or + $(RELATIVE_LINK2 continue-statement, continue) statement. +) +$(P + A label can appear without a following statement at the end of + a block. +) +$(P + Labels are in a name space independent of declarations, variables, + types, etc. + Even so, labels cannot have the same name as local declarations. + The label name space is the body of the function + they appear in. Label name spaces do not nest, i.e. a label + inside a block statement is accessible from outside that block. +) + + $(P Labels in one function cannot be referenced from another function.) + + +$(H2 $(LEGACY_LNAME2 BlockStatement, block-statement, Block Statement)) + +$(GRAMMAR +$(GNAME BlockStatement): + $(D { }) + $(D {) $(GLINK StatementList) $(D }) + +$(GNAME StatementList): + $(PSSEMI_PSCURLYSCOPE) + $(PSSEMI_PSCURLYSCOPE) $(GSELF StatementList) +) + + $(P A block statement is a sequence of statements enclosed by `{ }`. + The statements are executed in lexical order, + until the end of the block is reached or + a statement transfers control elsewhere. + ) + + +$(H2 $(LEGACY_LNAME2 ExpressionStatement, expression-statement, Expression Statement)) + +$(GRAMMAR +$(GNAME ExpressionStatement): + $(EXPRESSION) $(D ;) +) + + $(P The expression is evaluated.) + + $(P Expressions that have no effect, like $(D (x + x)), + are illegal as expression statements unless they are cast + to $(D_KEYWORD void).) + + ---- + int x; + x++; // ok + x; // illegal + 1+1; // illegal + cast(void)(x + x); // ok + ---- + + +$(H2 $(LEGACY_LNAME2 DeclarationStatement, declaration-statement, Declaration Statement)) + + $(P Declaration statements define variables, + and declare types, templates, functions, imports, + conditionals, static foreaches, and static asserts. + ) + +$(GRAMMAR +$(GNAME DeclarationStatement): + $(GLINK2 declaration, StorageClasses)$(OPT) $(GLINK2 declaration, Declaration) +) + + $(P Some declaration statements:) + +---- +int a; // declare a as type int and initialize it to 0 +struct S { } // declare struct s +alias myint = int; +---- + +$(H2 $(LEGACY_LNAME2 IfStatement, if-statement, If Statement)) + +$(P If statements provide simple conditional execution of statements.) + +$(GRAMMAR +$(GNAME IfStatement): + $(D if $(LPAREN)) $(GLINK IfCondition) $(D $(RPAREN)) $(GLINK ThenStatement) + $(D if $(LPAREN)) $(GLINK IfCondition) $(D $(RPAREN)) $(GLINK ThenStatement) $(D else) $(GLINK ElseStatement) + +$(GNAME IfCondition): + $(EXPRESSION) + $(GLINK IfConditionStorageClasses) $(GLINK_LEX Identifier) $(D =) $(EXPRESSION) + $(GLINK IfConditionStorageClasses)$(OPT) $(GLINK2 type, BasicType) $(GLINK2 declaration, Declarator) $(D =) $(EXPRESSION) + +$(GNAME IfConditionStorageClasses): + $(GLINK IfConditionStorageClass) + $(GLINK IfConditionStorageClass) $(GSELF IfConditionStorageClasses) + +$(GNAME IfConditionStorageClass): + $(D scope) + $(D auto) + $(D ref) + $(GLINK2 type, TypeCtor) + +$(GNAME ThenStatement): + $(PSSCOPE) + +$(GNAME ElseStatement): + $(PSSCOPE) +) + + $(P If there is a declared *Identifier* variable, + $(RELATIVE_LINK2 condition-variables, it is evaluated). + Otherwise, *Expression* is evaluated. The result is converted to a + boolean.) + + $(P If the boolean is `true`, the $(I ThenStatement) is transferred + to, otherwise the $(I ElseStatement) is transferred to.) + + $(P The $(I ElseStatement) is associated with the innermost `if` + statement which does not already have an associated $(I ElseStatement).) + +$(H3 $(LNAME2 boolean-conditions, Boolean Conversion)) + + $(P The following type instances are supported in a condition:) + + $(UL + $(LI $(DDSUBLINK spec/type, FundamentalType, Fundamental types) are `true` when non-zero) + $(LI Pointers are `true` when non-null) + $(LI Reference types are `true` when non-null) + $(LI A user-defined type with a valid $(DDSUBLINK spec/operatoroverloading, cast, `opCast!bool()`) method will be called for the result. Otherwise, any + $(DDSUBLINK spec/struct, alias-this, `alias this`) member declaration + will be used if its target type itself matches one of these rules.) + $(LI An enum type is `true` if its base type matches one of these rules.) + ) + $(P If none of these are valid, it is an error to use the value in a condition.) + + $(NOTE A dynamic array `a` can be used in a condition, which is `true` when + `a !is []`. + However, using an array as a boolean condition should be avoided as it can be bug-prone. + This may be disallowed in a future edition.) + +$(H3 $(LNAME2 condition-variables, Condition Variables)) + + $(P + When an $(I Identifier) form of *IfCondition* is used, a + variable is declared with that name and initialized to the + value of the $(I Expression). + ) + + * If both `auto` and `ref` are present among $(I IfConditionStorageClasses), + the variable is a reference + if and only if the $(I Expression) is an lvalue; + + * If `ref` is present without `auto`, + the variable is a reference and $(I Expression) must be an lvalue. + + * If `auto` is present without `ref`, the type of the variable + is the same as $(I Expression). + The presence of `auto` in combination with any $(I IfConditionStorageClasses) + except `ref` (cf. first bullet point) + has no effect. + Only if no other $(I IfConditionStorageClasses) are meaningful, + `auto` provides an option to declare a variable. + Using `auto` without `ref` when $(I BasicType) is given is not allowed. + + * If $(I TypeCtors) are provided and possibly the $(I BasicType) is given, + the variable is declared as it would for a normal + $(DDSUBLINK spec/declaration, variable-declarations, variable declaration). + + $(P The scope of the variable is the *ThenStatement* only.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +import std.regex; + +if (auto m = matchFirst("abcdef", "b(c)d")) +{ + writefln("[%s]", m.pre); // prints [a] + writefln("[%s]", m.post); // prints [ef] + writefln("[%s]", m[0]); // prints [bcd] + writefln("[%s]", m[1]); // prints [c] +} +else +{ + writeln("no match"); + //writeln(m.post); // Error: undefined identifier 'm' +} +//writeln(m.pre); // Error: undefined identifier 'm' +--- +) + ) + +$(H2 $(LEGACY_LNAME2 WhileStatement, while-statement, While Statement)) + +$(GRAMMAR +$(GNAME WhileStatement): + $(D while $(LPAREN)) $(GLINK IfCondition) $(D $(RPAREN)) $(PSSCOPE) +) + +$(P A $(I While Statement) implements a simple loop.) + +$(P If the $(I IfCondition) is an *Expression*, it is evaluated and must have a type +that can be $(DDSUBLINK spec/statement, boolean-conditions, converted to a boolean). +If it's `true` the *ScopeStatement* is executed. +After the *ScopeStatement* is executed, the *Expression* is evaluated again, and +if `true` the *ScopeStatement* is executed again. This continues until the *Expression* +evaluates to `false`.) + +--- +int i = 0; +while (i < 10) +{ + foo(i); + ++i; +} +--- + +$(P If the $(I IfCondition) declares a variable, $(RELATIVE_LINK2 condition-variables, it is initialized and evaluated) on every loop iteration.) + +$(P A $(GLINK BreakStatement) will exit the loop.) + +$(P A $(GLINK ContinueStatement) will transfer directly to evaluating $(I IfCondition) again.) + +$(H2 $(LEGACY_LNAME2 DoStatement, do-statement, Do Statement)) + +$(GRAMMAR +$(GNAME DoStatement): + $(D do) $(PSSCOPE) $(D while $(LPAREN)) $(EXPRESSION) $(D $(RPAREN)) $(D ;) +) + + +$(P Do while statements implement simple loops.) + +$(P *ScopeStatement* is executed. Then *Expression* is evaluated and must have a +type that can be $(DDSUBLINK spec/statement, boolean-conditions, converted to a boolean). +If it's `true` the loop is iterated +again. This continues until the *Expression* evaluates to `false`.) + +--- +int i = 0; +do +{ + foo(i); +} while (++i < 10); +--- + +$(P A $(GLINK BreakStatement) will exit the loop. A $(GLINK ContinueStatement) +will transfer directly to evaluating *Expression* again.) + +$(H2 $(LEGACY_LNAME2 ForStatement, for-statement, For Statement)) + +$(P For statements implement loops with initialization, test, and increment +clauses.) + +$(GRAMMAR +$(GNAME ForStatement): + $(D for $(LPAREN)) $(GLINK Initialize) $(GLINK Test)$(OPT) $(D ;) $(GLINK Increment)$(OPT) $(D $(RPAREN)) $(PSSCOPE) + +$(GNAME Initialize): + $(D ;) + $(GLINK NoScopeNonEmptyStatement) + +$(GNAME Test): + $(EXPRESSION) + +$(GNAME Increment): + $(EXPRESSION) +) + + $(P $(I Initialize) is executed. + $(I Test) is evaluated and must have a type that + can be $(DDSUBLINK spec/statement, boolean-conditions, converted to a boolean). + If *Test* is `true` the *ScopeStatement* is executed. After execution, + $(I Increment) is executed. + Then $(I Test) is evaluated again, and if `true` the + *ScopeStatement* is executed again. This continues until the + $(I Test) evaluates to `false`. + ) + + $(P A $(GLINK BreakStatement) will exit the loop. + A $(GLINK ContinueStatement) + will transfer directly to the $(I Increment). + ) + + $(P A $(I ForStatement) creates a new scope. + If $(I Initialize) declares a variable, that variable's scope + extends through *ScopeStatement*. For example: + ) + +-------------- +for (int i = 0; i < 10; i++) + foo(i); +-------------- + + is equivalent to: + +-------------- +{ + int i; + for (i = 0; i < 10; i++) + foo(i); +} +-------------- + +$(P *ScopeStatement* cannot be an empty statement:) + +-------------- +for (int i = 0; i < 10; i++) + ; // illegal +-------------- + + Use instead: + +-------------- +for (int i = 0; i < 10; i++) +{ +} +-------------- + + $(P $(I Initialize) may be just $(D ;). + $(I Test) may be omitted, and if + so, it is treated as if it evaluated to `true`.) + + $(BEST_PRACTICE Consider replacing $(I ForStatements) with + $(DDSUBLINK spec/statement, foreach-statement, Foreach Statements) or + $(DDSUBLINK spec/statement, ForeachRangeStatement, Foreach Range Statements). + Foreach loops are easier to understand, less prone to error, and easier to refactor. + ) + +$(H2 $(LEGACY_LNAME2 ForeachStatement, foreach-statement, Foreach Statement)) + +$(P A `foreach` statement iterates a series of values.) + +$(GRAMMAR +$(GNAME AggregateForeach): + $(GLINK Foreach) $(D $(LPAREN)) $(GLINK ForeachTypeList) $(D ;) $(GLINK ForeachAggregate) $(D $(RPAREN)) + +$(GNAME ForeachStatement): + $(GLINK AggregateForeach) $(GLINK NoScopeNonEmptyStatement) + +$(GNAME Foreach): + $(D foreach) + $(D foreach_reverse) + +$(GNAME ForeachTypeList): + $(GLINK ForeachType) + $(GLINK ForeachType) $(D ,) $(GSELF ForeachTypeList) + +$(GNAME ForeachType): + $(GLINK ForeachTypeAttributes)$(OPT) $(GLINK2 type, BasicType) $(GLINK2 declaration, Declarator) + $(GLINK ForeachTypeAttributes)$(OPT) $(GLINK_LEX Identifier) + $(GLINK ForeachTypeAttributes)$(OPT) $(D alias) $(GLINK_LEX Identifier) + +$(GNAME ForeachTypeAttributes): + $(GLINK ForeachTypeAttribute) + $(GLINK ForeachTypeAttribute) $(GSELF ForeachTypeAttributes) + +$(GNAME ForeachTypeAttribute): + $(D enum) + $(D ref) + $(D scope) + $(GLINK2 type, TypeCtor) + +$(GNAME ForeachAggregate): + $(EXPRESSION) +) + +$(P + $(I ForeachAggregate) is evaluated. It must evaluate to an expression + which is a static array, dynamic array, associative array, + struct, class, delegate, or sequence. + The *NoScopeNonEmptyStatement* is executed, once for each element of the + aggregate. +) +$(P + The number of variables declared in $(I ForeachTypeList) + depends on the kind of aggregate. The declared variables are + set at the start of each iteration. +) +$(UL + $(LI By default a single declared variable is a copy of the current element.) + $(LI If the $(I ForeachTypeAttribute) is $(D ref), that variable will + be a reference to the current element of the aggregate.) + $(LI If the $(I ForeachTypeAttribute) is $(D scope), the variable + will have $(DDSUBLINK spec/function, scope-parameters, `scope`) semantics.) +) +$(P + If not specified, the type of a $(I ForeachType) variable + can be inferred from the type of the $(I ForeachAggregate). + Note that `auto` is not a valid $(I ForeachTypeAttribute). + The two `foreach` statements below are equivalent: +) +$(SPEC_RUNNABLE_EXAMPLE_RUN +-------------- +int[] arr = [1, 2, 3]; + +foreach (int n; arr) + writeln(n); + +foreach (n; arr) // ok, n is an int + writeln(n); +-------------- +) +$(P + The aggregate must be $(RELATIVE_LINK2 foreach_restrictions, loop invariant), + meaning that elements cannot be added or removed from it + in the *NoScopeNonEmptyStatement*. +) + + $(P A $(GLINK BreakStatement) in the body of the foreach will exit the + loop. A $(GLINK ContinueStatement) will immediately start the + next iteration. + ) + +$(H3 $(LNAME2 foreach_over_arrays, Foreach over Arrays)) + +$(P + If the aggregate is a static or dynamic array, there + can be one or two variables declared. If one, then the variable + is said to be the $(I value), which is set successively to each + element of the array. The type of the variable, if specified, + must be compatible with the array element type (except for the + special handling of character elements outlined below). + The *value* variable can modify array elements when + $(RELATIVE_LINK2 foreach_ref_parameters, declared with `ref`). +) +$(P + If there are + two variables declared, the first is said to be the $(I index) + and the second is said to be the $(I value) as above. + $(I index) cannot be declared with `ref`. + It is set to the index of the array element on each iteration. + The index type can be inferred: +) +$(SPEC_RUNNABLE_EXAMPLE_RUN +-------------- +char[] a = ['h', 'i']; + +foreach (i, char c; a) +{ + writefln("a[%d] = '%c'", i, c); +} +-------------- +) + $(P For a dynamic array, the $(I index) type must be compatible + with `size_t`, unless the array length is statically known to fit + in a smaller integer type. + Static arrays may use any integral type that spans the length + of the array.) + + $(P For $(D foreach), the + elements for the array are iterated over starting at index 0 + and continuing to the last element of the array. + For $(D foreach_reverse), the array elements are visited in the reverse + order. + ) + +$(H3 $(LNAME2 foreach_over_arrays_of_characters, Foreach over Arrays of Characters)) + + $(P If the aggregate expression is a static or dynamic array of + $(D char)s, $(D wchar)s, or $(D dchar)s, then the type of + the $(I value) variable + can be any of $(D char), $(D wchar), or $(D dchar). + In this manner any UTF array + can be decoded into any UTF type: + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +-------------- +char[] a = "\xE2\x89\xA0".dup; // \u2260 encoded as 3 UTF-8 bytes + +foreach (dchar c; a) +{ + writefln("a[] = %x", c); // prints 'a[] = 2260' +} + +dchar[] b = "\u2260"d.dup; + +foreach (char c; b) +{ + writef("%x, ", c); // prints 'e2, 89, a0, ' +} +-------------- +) + + $(P Aggregates can be string literals, which can be accessed + as `char`, `wchar`, or `dchar` arrays: + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + -------------- + foreach (char c; "ab") + { + writefln("'%s'", c); + } + foreach (wchar w; "xy") + { + writefln("'%s'", w); + } + -------------- + ) + + $(P which would print: + ) + +$(CONSOLE +'a' +'b' +'x' +'y' +) + +$(H3 $(LNAME2 foreach_over_associative_arrays, Foreach over Associative Arrays)) + + $(P If the aggregate expression is an $(DDLINK spec/hash-map, Associative Arrays, associative array), there + can be one or two variables declared. If one, then the variable + is said to be the $(I value), which is set to each value in the array, + one by one. If the type of the + variable is provided, it must implicitly convert from the associative + array value type.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +-------------- +// value type is int +int[string] userAges = ["john":30, "sue":32]; + +foreach (ref age; userAges) +{ + age++; +} +assert(userAges == ["john":31, "sue":33]); +-------------- +) + + $(P If there are + two variables declared, the first is said to be the $(I index) + and the second is said to be the $(I value). The index variable type + (if given) must be implicitly convertible from the key type of the associative + array. The index variable is set to the key corresponding to each value + in the associative array.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +-------------- +// index type is string, value type is double +double[string] aa = ["pi":3.14, "e":2.72]; + +foreach (string s, double d; aa) +{ + writefln("aa['%s'] = %g", s, d); +} +-------------- +) + + $(IMPLEMENTATION_DEFINED The order in which the elements of the + array are iterated over is unspecified for $(D foreach). + This is why $(D foreach_reverse) for associative arrays is illegal.) + + $(P If an index or value variable is declared as `ref`, then any type given + must match the associative array key or value type respectively, or + $(DDSUBLINK spec/const3, implicit_qualifier_conversions, `const`-convert) + from it. A `ref` index variable must be (inferred as) `const`, as keys must + not be mutated.) + + +$(H3 $(LNAME2 foreach_over_struct_and_classes, Foreach over Structs and Classes with `opApply`)) + + $(P If the aggregate expression is a struct or class object, + the $(D foreach) is defined by the + special $(LEGACY_LNAME2 opApply, op-apply, $(D opApply)) member function, and the + `foreach_reverse` behavior is defined by the special + $(LEGACY_LNAME2 opApplyReverse, op-apply-reverse, $(D opApplyReverse)) member function. + These functions must each have the signature below: + ) + +$(GRAMMAR_INFORMATIVE +$(GNAME OpApplyDeclaration): + `int opApply` `(` `scope` `int delegate` `(` $(I OpApplyParameters) `)` `dg` `)` `;` + +$(GNAME OpApplyParameters): + *OpApplyParameter* + *OpApplyParameter*, *OpApplyParameters* + +$(GNAME OpApplyParameter): + $(GLINK ForeachTypeAttributes)$(OPT) $(GLINK2 type, BasicType) $(GLINK2 declaration, Declarator) +) + + $(P where each $(I OpApplyParameter) of `dg` must match a $(GLINK ForeachType) + in a $(GLINK ForeachStatement), + otherwise the *ForeachStatement* will cause an error.) + + $(P Any *ForeachTypeAttribute* cannot be `enum`.) + + $(PANEL + To support a `ref` iteration variable, the delegate must take a `ref` parameter: + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S + { + int opApply(scope int delegate(ref uint n) dg); + } + void f(S s) + { + foreach (ref uint i; s) + i++; + } + --- + ) + Above, `opApply` is still matched when `i` is not `ref`, so by using + a `ref` delegate parameter both forms are supported. + ) + + $(P There can be multiple $(D opApply) and $(D opApplyReverse) functions - + one is selected + by matching each parameter of `dg` to each $(I ForeachType) + declared in the $(I ForeachStatement).) + + $(P The body of the apply + function iterates over the elements it aggregates, passing each one + in successive calls to the `dg` delegate. The delegate return value + determines whether to interrupt iteration:) + + $(UL + $(LI If the result is nonzero, apply must cease + iterating and return that value.) + $(LI If the result is 0, then iteration should continue. + If there are no more elements to iterate, + apply must return 0.) + ) + + $(P The result of calling the delegate will be nonzero if the *ForeachStatement* + body executes a matching $(GLINK BreakStatement), $(GLINK ReturnStatement), or + $(GLINK GotoStatement) whose matching label is outside the *ForeachStatement*. + ) + + $(P For example, consider a class that is a container for two elements:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + -------------- + class Foo + { + uint[] array; + + int opApply(scope int delegate(ref uint) dg) + { + foreach (e; array) + { + int result = dg(e); + if (result) + return result; + } + return 0; + } + } + + void main() + { + import std.stdio; + + Foo a = new Foo(); + a.array = [73, 82, 2, 9]; + + foreach (uint u; a) + { + if (u < 5) + break; + + writeln(u); + } + } + -------------- + ) + + $(P This would print:) + +$(CONSOLE +73 +82 +) + $(PANEL + The `scope` storage class on the $(D dg) parameter means that the delegate does + not escape the scope of the $(D opApply) function (an example would be assigning $(D dg) to a + global variable). If it cannot be statically guaranteed that $(D dg) does not escape, a closure may + be allocated for it on the heap instead of the stack. + + $(BEST_PRACTICE Annotate delegate parameters to `opApply` functions with `scope` when possible.) + ) + + $(P $(B Important:) If $(D opApply) catches any exceptions, ensure that those + exceptions did not originate from the delegate passed to $(D opApply). The user would expect + exceptions thrown from a `foreach` body to both terminate the loop, and propagate outside + the `foreach` body. + ) + +$(H4 $(LNAME2 template-op-apply, Template `opApply`)) + + $(P $(D opApply) can also be a templated function, + which will infer the types of parameters based on the $(I ForeachStatement). + For example:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + -------------- + struct S + { + import std.traits : ParameterTypeTuple; // introspection template + import std.stdio; + + int opApply(Dg)(scope Dg dg) + if (ParameterTypeTuple!Dg.length == 2) // foreach with 2 parameters + { + writeln(2); + return 0; + } + + int opApply(Dg)(scope Dg dg) + if (ParameterTypeTuple!Dg.length == 3) // foreach with 3 parameters + { + writeln(3); + return 0; + } + } + + void main() + { + foreach (int a, int b; S()) { } // calls first opApply function + foreach (int a, int b, float c; S()) { } // calls second opApply function + } + -------------- + ) + +$(H3 $(LEGACY_LNAME2 foreach_with_ranges, foreach-with-ranges, Foreach over Structs and Classes with Ranges)) + + $(P If the $(GLINK ForeachAggregate) is a struct or class object, but + $(RELATIVE_LINK2 foreach_over_struct_and_classes, `opApply`) does not exist, + then $(D foreach) iteration will use $(LINK2 $(ROOT_DIR)phobos/std_range.html, range) + primitives. These primitives produce a series of elements. + ) + $(P The following properties and methods must + be defined for the $(I ForeachAggregate): + ) + + $(TABLE2 Foreach Range Properties, + $(THEAD Property, Purpose) + $(TROW $(ARGS $(D .empty)), $(ARGS returns `true` if no more elements)) + $(TROW $(ARGS $(D .front)), $(ARGS return the leftmost element of the range)) + ) + + $(TABLE2 Foreach Range Methods, + $(THEAD Method, Purpose) + $(TROW $(ARGS $(D .popFront())), $(ARGS move the left edge of the range + right by one)) + ) + + $(P A temporary variable is used for iteration, which is initialized from the + *ForeachAggregate*. The statement:) + + --- + foreach (e; range) { ... } + --- + + $(P translates to:) + + --- + for (auto __r = range; !__r.empty; __r.popFront()) + { + auto e = __r.front; + ... + } + --- + + $(P Similarly, for $(D foreach_reverse) when $(D opApplyReverse) is not defined, + range primitives will be used. The following properties and methods + must be defined for the $(I ForeachAggregate): + ) + + $(TABLE2 Foreach$(UNDERSCORE)reverse Range Properties, + $(THEAD Property, Purpose) + $(TROW $(ARGS $(D .empty)), $(ARGS returns `true` if no more elements)) + $(TROW $(ARGS $(D .back)), $(ARGS return the rightmost element of the range)) + ) + + $(TABLE2 Foreach$(UNDERSCORE)reverse Range Methods, + $(THEAD Method, Purpose) + $(TROW $(ARGS $(D .popBack())), $(ARGS move the right edge of the range + left by one)) + ) + + $(P The statement:) + + --- + foreach_reverse (e; range) { ... } + --- + + $(P translates to:) + + --- + for (auto __r = range; !__r.empty; __r.popBack()) + { + auto e = __r.back; + ... + } + --- + + $(P The $(GLINK ForeachType) variable may be declared with `ref` when `front` + (or `back` for `foreach_reverse`) is a + $(DDSUBLINK spec/function, ref-functions, Ref Function):) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct R +{ + int[] a; + // range primitives: + bool empty() => a.length == 0; + ref front() => a[0]; + void popFront() { a = a[1..$]; } +} + +R r = R([1, 2, 3]); +foreach (ref e; r) + e *= 2; + +assert(r.a == [2, 4, 6]); +--- +) + $(P Example with a linked list:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct Node +{ + int i; + Node* next; +} + +// range +struct List +{ + Node* node; + bool empty() { return node == null; } + ref int front() { return node.i; } + void popFront() { node = node.next; } +} + +void main() +{ + import std.stdio; + auto n = new Node(1, new Node(2, null)); + auto r = List(n); + + foreach (e; r) + { + writeln(e); + } +} +--- +) + +$(H4 $(LNAME2 front-seq, Multiple Element Values)) + + $(P Multiple loop variables are allowed if the `front` property returns a type that + expands to a $(DDSUBLINK spec/template, homogeneous_sequences, value sequence) + whose length matches the number of variables. Each variable is assigned + to the corresponding value in the sequence. + If there is only one variable, it will be a value sequence. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + import std.stdio; + + // simple version of std.typecons.Tuple + struct Tuple(Types...) // takes a TypeSeq + { + Types items; // ValueSeq + alias items this; // decay to a value sequence + } + + string s = "hello"; + + struct TupleRange + { + size_t i; + auto front() => Tuple!(size_t, char)(i, s[i]); + bool empty() => i >= s.length; + void popFront() { i++; } + } + + void main() + { + // Tuple destructuring + foreach (i, c; TupleRange()) + { + writeln(i, ": ", c); + } + writeln(); + // Tuple variable + foreach (tup; TupleRange()) + { + writefln("(%s, %s)", tup[0], tup[1]); + } + } + --- + ) + $(P See also: $(REF Tuple, std,typecons).) + +$(H3 $(LNAME2 foreach_over_delegates, Foreach over Delegates)) + + $(P If $(I ForeachAggregate) is a delegate, the type signature and + behavior of the delegate is the same as for + $(RELATIVE_LINK2 foreach_over_struct_and_classes, opApply). This enables + many different named looping strategies to coexist in the same + class or struct.) + + $(P The delegate can generate the elements on the fly:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN + -------------- + // Custom loop implementation, that iterates over powers of 2 with + // alternating sign. The foreach loop body is passed in dg. + int myLoop(scope int delegate(int) dg) + { + for (int z = 1; z < 128; z *= -2) + { + auto ret = dg(z); + + // If the loop body contains a break, ret will be non-zero. + if (ret != 0) + return ret; + } + return 0; + } + + // Append each value in the iteration to an array + int[] result; + foreach (x; &myLoop) + { + result ~= x; + } + assert(result == [1, -2, 4, -8, 16, -32, 64, -128]); + -------------- +) + + $(P $(D foreach_reverse) with a delegate is an error.) + + +$(H3 $(LNAME2 foreach_over_tuples, Foreach over Sequences)) + +$(P + If the aggregate expression is a + $(DDSUBLINK spec/template, variadic-templates, sequence), + the loop body is statically expanded once for each element. This is + similar to a $(DDSUBLINK spec/version, staticforeach, *StaticForeachStatement*) + on a sequence, though there is a separate scope for each expansion. +) + $(P There + can be one or two iteration symbols declared. If one, then it's + an $(I element symbol) representing each element in the sequence in turn. +) +$(UL +$(LI + If the sequence is a $(I TypeSeq), the element symbol is set to each + type in turn. +)$(LI + If the sequence is a $(I ValueSeq), the element symbol + is set to each value in turn. If the type of the element symbol + is given, it must be compatible with the type of every sequence element. + If no type is given, the type of the element symbol will match the type + of each sequence element, which may change between elements. +)) +$(P + If there are + two symbols declared, the first is the $(I index) + and the second is the $(I element). The index symbol + must be of `int`, `uint`, `long` or `ulong` type (if specified), + it cannot be `ref`, + and it is set to the index of each sequence element. +) + $(P Example:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +----- +import std.meta : AliasSeq; + +void main() +{ + alias Seq = AliasSeq!(int, "literal", main); + + foreach (int i, sym; Seq) + { + pragma(msg, i, ": ", sym.stringof); + } +} +----- +) + $(P Output:) + +$(CONSOLE +0: int +1: "literal" +2: main() +) + + $(P Example:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +----- +void fun() +{ + import std.meta : AliasSeq; + + alias values = AliasSeq!(7.4, "hi", [2,5]); + + foreach (sym; values) + { + pragma(msg, sym, " has type ", typeof(sym)); + } +} +----- +) + + $(P Output:) + +$(CONSOLE +7.4 has type double +hi has type string +[2, 5] has type int[] +) + +$(H4 $(LNAME2 foreach_sequence_kinds, Symbol Kinds)) + + $(P Each $(GLINK ForeachType) declaration (without `alias`/`enum`) + will attempt to generate:) + + * Compile-time symbols for values known at compile-time + * Runtime variables for elements with values not known at compile-time + * Symbolic aliases for elements that don't have values (e.g types) + + $(P `alias` or `enum` can be specified in a *ForeachType*:) + + * The `alias` storage class will create a symbolic alias + * The `enum` storage class will create a compile-time constant + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +void main() +{ + import std.meta : AliasSeq; + + int i = 1; + + // without `alias`, `a` would be a separate variable initialized from `i` + foreach (alias a; AliasSeq!(i, i)) + { + a++; + } + assert(i == 3); + + foreach (e; AliasSeq!(i, 1)) + { + static if (__traits(compiles, &e)) + assert(e == 3); // first e is a runtime variable + else + static assert(e == 1); // second e is a compile-time constant + } +} +--- +) + +$(H3 $(LNAME2 foreach_ref_parameters, Foreach Ref Parameters)) + + $(P $(D ref) can be used to modify the elements of the *ForeachAggregate*. + This works for containers that expose lvalue elements, and + $(DDSUBLINK spec/template, lvalue-sequences, lvalue sequences). + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + -------------- + uint[2] a = [7, 8]; + + foreach (ref u; a) + { + u++; + } + foreach (u; a) + { + writeln(u); + } + -------------- + ) + + which would print: + +$(CONSOLE +8 +9 +) + $(P $(D ref) cannot be applied to an array index variable.) + +$(H3 $(LNAME2 foreach_restrictions, Foreach Restrictions)) + + $(P The aggregate itself must not be resized, reallocated, free'd, + reassigned or destructed + while `foreach` is iterating over the elements. + ) + +-------------- +int[] a = [1, 2, 3]; +auto fun = { a ~= 4; }; + +foreach (int v; a) +{ + // resizing is unspecified! + fun(); + a ~= 4; + a.length += 10; + + // reallocating is unspecified! + a.reserve(10); + + // reassigning is unspecified! + a = null; + a = [5, 6]; +} +a ~= 4; // OK +a = null; // OK +-------------- +--- +auto aa = [1: 1, 2: 2]; + +foreach (v; aa) +{ + aa[3] = 3; // unspecified resize + aa.rehash; // unspecified reallocation + aa = [4: 4]; // unspecified reassign +} +aa[3] = 3; // OK +aa = null; // OK +--- + + $(NOTE Resizing or reassigning a dynamic or associative array during + `foreach` is still `@safe`. + ) + +$(H3 $(LEGACY_LNAME2 ForeachRangeStatement, foreach-range-statement, Foreach Range Statement)) + +$(P A foreach range statement loops over the specified range.) + +$(GRAMMAR +$(GNAME RangeForeach): + $(GLINK Foreach) $(D $(LPAREN)) $(GLINK ForeachType) $(D ;) $(GLINK LwrExpression) $(D ..) $(GLINK UprExpression) $(D $(RPAREN)) + +$(GNAME LwrExpression): + $(EXPRESSION) + +$(GNAME UprExpression): + $(EXPRESSION) + +$(GNAME ForeachRangeStatement): + $(GLINK RangeForeach) $(PSSCOPE) +) + + $(P + $(I ForeachType) declares a variable with either an explicit type, + or a common type inferred from $(I LwrExpression) and $(I UprExpression). + The $(I ScopeStatement) is then executed $(I n) times, where $(I n) + is the result of $(I UprExpression) `-` $(I LwrExpression). + If $(I UprExpression) is less than or equal to $(I LwrExpression), + the $(I ScopeStatement) is not executed.) + + $(P + If $(I Foreach) is $(D foreach), then the variable is set to + $(I LwrExpression), then incremented at the end of each iteration. + If $(I Foreach) is $(D foreach_reverse), then the variable is set to + $(I UprExpression), then decremented before each iteration. + $(I LwrExpression) and $(I UprExpression) are each evaluated + exactly once, regardless of how many times the $(I ScopeStatement) + is executed. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +import std.stdio; + +int foo() +{ + write("foo"); + return 10; +} + +void main() +{ + foreach (i; 0 .. foo()) + { + write(i); + } +} +--- +) + +prints: + +$(CONSOLE +foo0123456789 +) + + +$(H2 $(LEGACY_LNAME2 SwitchStatement, switch-statement, Switch Statement)) + + A switch statement goes to one of a collection of case + statements depending on the value of the switch + expression. + +$(GRAMMAR +$(GNAME SwitchStatement): + $(D switch $(LPAREN)) $(GLINK IfCondition) $(D $(RPAREN)) $(PSSCOPE) + +$(GNAME CaseStatement): + $(D case) $(GLINK2 expression, ArgumentList) $(D :) $(PSSEMI_PSCURLYSCOPE_LIST)$(OPT) + +$(GNAME DefaultStatement): + $(D default :) $(PSSEMI_PSCURLYSCOPE_LIST)$(OPT) + +$(GNAME ScopeStatementList): + $(GLINK StatementListNoCaseNoDefault) + +$(GNAME StatementListNoCaseNoDefault): + $(GLINK StatementNoCaseNoDefault) + $(GLINK StatementNoCaseNoDefault) $(GSELF StatementListNoCaseNoDefault) + +$(GNAME StatementNoCaseNoDefault): + $(GLINK EmptyStatement) + $(GLINK NonEmptyStatementNoCaseNoDefault) + $(GLINK ScopeBlockStatement) +) + + $(P The *Expression* from the $(I IfCondition) is evaluated. + If the type of the *Expression* is an `enum`, it is + (recursively) converted to its $(GLINK2 enum, EnumBaseType). + Then, if the type is an integral, the *Expression* undergoes + $(DDSUBLINK spec/type, integer-promotions, Integer Promotions). + Then, the type of the *Expression* must be either an integral or + a static or dynamic array of $(CODE char), $(CODE wchar), or $(CODE dchar). + ) + + $(P If an $(I Identifier) `=` prefix is provided, a variable is declared with that + name, initialized to the value and type of the *Expression*. Its scope + extends from when it is initialized to the end of the *ScopeStatement*.) + + $(P If $(I TypeCtors) and/or a specific type is provided for *Identifier*, those + are used for the variable declaration which is initialized by an implicit + conversion from the value of the *Expression*.) + + $(P The resulting value is + compared against each of the case expressions. If there is + a match, the corresponding case statement is transferred to. + ) + + $(P The case expressions in $(I ArgumentList) + are a comma separated list of expressions. + Each expression must evaluate to a compile-time value or array, + or a runtime initialized const or immutable variable of integral type. + Each expression must be implicitly convertible to the type of the switch + *Expression*.) + + $(P Compile-time case values must all be distinct. Const or + immutable runtime variables must all have different names. + If two case expressions share a + value, the first case statement with that value gets control.) + + $(P The $(GLINK ScopeStatementList) introduces a new scope. + ) + + $(P A matching `break` statement will exit the switch $(I BlockStatement).) + + $(P A switch statement must have exactly one *DefaultStatement*. + If none of the case expressions match, control is transferred + to the default statement. + ) + + $(RATIONALE This makes it clear that all possible cases are intentionally handled. + See also: $(RELATIVE_LINK2 final-switch-statement, `final switch`).) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +-------------- +foreach (i; 2 .. 10) +{ + bool prime; + + switch (i) + { + case 2, 3, 5, 7: + prime = true; + break; + default: + prime = false; + } + writeln(i, ": ", prime); +} +-------------- +) + $(P Case statements and default statements associated with the switch + can be nested within block statements; they do not have to be in + the outermost block. For example, this is allowed: + ) + +-------------- +switch (i) +{ + case 1: + { + case 2: + } + i++; + break; + default: +} +-------------- + + $(P $(B Implementation Note:) The compiler's code generator may + assume that the case + statements are sorted by frequency of use, with the most frequent + appearing first and the least frequent last. Although this is + irrelevant as far as program correctness is concerned, it is of + performance interest. + ) + +$(H3 $(LNAME2 case-range, Case Range Statement)) + +$(GRAMMAR +$(GNAME CaseRangeStatement): + $(D case) $(GLINK FirstExp) $(D : .. case) $(GLINK LastExp) $(D :) $(PSSEMI_PSCURLYSCOPE_LIST)$(OPT) + +$(GNAME FirstExp): + $(ASSIGNEXPRESSION) + +$(GNAME LastExp): + $(ASSIGNEXPRESSION) +) + + $(P A $(I CaseRangeStatement) is a shorthand for listing a series + of case statements from $(I FirstExp) to $(I LastExp), inclusive.) + + --- + case 1: .. case 3: + --- + + $(P The above is equivalent to:) + + --- + case 1, 2, 3: + --- + +$(H3 $(LNAME2 no-implicit-fallthrough, No Implicit Fall-Through)) + + + $(P A $(GLINK ScopeStatementList) must either be empty, the last one in the `switch`, + or be ended by:) + + * A $(GLINK ContinueStatement), $(GLINK BreakStatement), + $(GLINK ReturnStatement), or $(GLINK GotoStatement) + * Evaluating an $(DDSUBLINK spec/expression, assert-ct, `assert(0)` expression) + * Evaluating an expression of type $(DDSUBLINK spec/type, noreturn, `noreturn`) + + $(P Simple forms of the last 2 cases above can be recognized by the compiler, but not all.) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +-------------- +uint i; +string message; + +switch (i) +{ + case 1: + message = "one"; + // ERROR: implicit fall-through + case 2: + // valid: the body is empty + default: + message = "2 or more"; + // valid: no more case statements +} +-------------- +) + $(P $(D goto case;) can be used for explicit fall-through to the next + *CaseStatement*:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +-------------- +string message; + +foreach (i; 1..5) +{ + switch (i) + { + default: // valid: ends with `noreturn` expression evaluation + throw new Exception("unknown number"); + + case 3: // valid: ends with 'break' (break out of the 'switch' only) + message ~= "three"; + break; + + case 4: // valid: ends with 'continue' (continue the enclosing loop) + message ~= "four"; + continue; // don't append a comma + + case 1: // valid: ends with 'goto' (explicit fall-through to next case.) + message ~= ">"; + goto case; + + case 2: // valid: this is the last case in the switch statement. + message ~= "one or two"; + } + message ~= ", "; +} +writeln(message); +-------------- +) + $(P $(RELATIVE_LINK2 goto-statement, `goto`) also supports jumping to + a specific case or to the default case statement.) + +$(H3 $(LNAME2 string-switch, String Switch)) + + $(P Strings can be used in switch expressions. + For example: + ) + +-------------- +string name; +... +switch (name) +{ + case "fred": + case "sally": + ... +} +-------------- + + $(P For applications like command line switch processing, this + can lead to much more straightforward code, being clearer and + less error prone. `char`, `wchar` and `dchar` strings are allowed. + ) + + +$(H2 $(LEGACY_LNAME2 FinalSwitchStatement, final-switch-statement, Final Switch Statement)) + +$(GRAMMAR +$(GNAME FinalSwitchStatement): + $(D final switch $(LPAREN)) $(GLINK IfCondition) $(D $(RPAREN)) $(PSSCOPE) +) + + $(P A final switch statement is just like a switch statement, + except that:) + + $(UL + $(LI No $(GLINK DefaultStatement) is allowed.) + $(LI No $(GLINK CaseRangeStatement)s are allowed.) + $(LI If the switch *Expression* is of enum type, all + the enum members must appear in the $(GLINK CaseStatement)s.) + $(LI The case expressions cannot evaluate to a run time + initialized value.) + ) + + $(IMPLEMENTATION_DEFINED If the *Expression* value does not match any + of the $(I CaseRangeStatements), whether that is diagnosed at compile + time or at runtime.) + + +$(H2 $(LEGACY_LNAME2 ContinueStatement, continue-statement, Continue Statement)) + +$(GRAMMAR +$(GNAME ContinueStatement): + $(D continue) $(GLINK_LEX Identifier)$(OPT) $(D ;) +) + + $(P `continue` aborts the current iteration of its innermost enclosing + loop statement, and starts the next iteration. + If the enclosing loop is a `for` statement, + its $(GLINK Increment) clause is executed.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +string[] words = ["OK", "just", "longer", "words", "now"]; + +foreach (w; words) +{ + if (w.length < 4) + continue; // skip writeln + + writeln(w); +} +--- +) + $(P Output:) + +$(CONSOLE +just +longer +words +) + + $(P If `continue` is followed by $(I Identifier), the $(I Identifier) + must be the label of an enclosing loop statement, + and the next iteration of that loop is executed. + It is an error if + there is no such statement.) + +--- +outer: +foreach (item; list) +{ + // try 3 times + foreach (i; 0 .. 3) + { + if (item.buy()) + continue outer; // skip to next item + + log("attempt failed"); + } +} +--- + + $(P Any intervening $(RELATIVE_LINK2 try-statement, `finally`) clauses are executed, + and any intervening synchronization objects are released.) + + $(P $(D Note:) If a `finally` clause executes a `throw` out of the finally + clause, the continue target is never reached.) + +$(H2 $(LEGACY_LNAME2 BreakStatement, break-statement, Break Statement)) + +$(GRAMMAR +$(GNAME BreakStatement): + $(D break) $(GLINK_LEX Identifier)$(OPT) $(D ;) +) + +$(P `break` exits the innermost enclosing loop or $(RELATIVE_LINK2 switch-statement, `switch`) +statement, resuming execution at the statement following it.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +const n = 55; + +// find the smallest factor of n +foreach (i; 2 .. n) +{ + writeln("Trying: ", i); + if (n % i == 0) + { + writeln("smallest factor is ", i); + break; // stop looking + } +} +writeln("finished"); +--- +) + $(P Output:) + +$(CONSOLE +Trying: 2 +Trying: 3 +Trying: 4 +Trying: 5 +smallest factor is 5 +finished +) + + $(P If `break` is followed by $(I Identifier), the $(I Identifier) + must be the label of an enclosing loop or `switch` + statement, and that statement is exited. It is an error if + there is no such statement.) + +--- +// display messages cyclically until the shop is closed +outer: +while (true) +{ + foreach (msg; messages) + { + if (shop.isClosed()) + break outer; // end the while loop + + display(msg); + } +} +display("opens at 9am"); +--- + + $(P Any intervening $(RELATIVE_LINK2 try-statement, `finally`) clauses are executed, + and any intervening synchronization objects are released.) + + $(P $(D Note:) If a `finally` clause executes a `throw` out of the finally + clause, the break target is never reached.) + +$(H2 $(LEGACY_LNAME2 ReturnStatement, return-statement, Return Statement)) + +$(GRAMMAR +$(GNAME ReturnStatement): + $(D return) $(EXPRESSION)$(OPT) $(D ;) +) + +$(P `return` exits the current function and supplies its +$(DDSUBLINK spec/function, function-return-values, return value).) + +$(P *Expression* is required if the function specifies a return type that is +not void. The *Expression* is implicitly converted to the function return +type.) + +$(P + An *Expression* of type void is allowed if the function specifies + a void return type. The *Expression* will be evaluated, + but nothing will be returned. This is useful in generic programming. +) + $(P Before the function actually returns, + any objects with `scope` storage duration are destroyed, + any enclosing `finally` clauses are executed, + any `scope(exit)` statements are executed, + any `scope(success)` statements are executed, + and any enclosing synchronization + objects are released.) + + $(P The function will not return if any enclosing `finally` clause + does a return, goto or throw that exits the `finally` clause.) + + $(P If there is an $(DDSUBLINK spec/function, postconditions, `out` postcondition), + that postcondition is executed + after the *Expression* is evaluated and before the function + actually returns.) + +--- +int foo(int x) +{ + return x + 3; +} +--- + +$(H2 $(LEGACY_LNAME2 GotoStatement, goto-statement, Goto Statement)) + +$(GRAMMAR +$(GNAME GotoStatement): + $(D goto) $(GLINK_LEX Identifier) $(D ;) + $(D goto) $(D default) $(D ;) + $(D goto) $(D case) $(D ;) + $(D goto) $(D case) $(EXPRESSION) $(D ;) +) + +$(P `goto` transfers to the statement labeled with $(I Identifier).) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- + int x = 1; + if (x) + goto L1; + + x = 3; +L1: + assert(x == 1); +--- +) + +$(P The second form, $(CODE goto default;), transfers to the innermost $(GLINK +DefaultStatement) of an enclosing $(GLINK SwitchStatement).) + + $(P The third form, $(CODE goto case;), transfers to the + next $(GLINK CaseStatement) of the innermost enclosing + $(GLINK SwitchStatement).) + + $(P The fourth form, $(CODE goto case) *Expression*$(D ;), transfers to the + $(GLINK CaseStatement) of the innermost enclosing + $(GLINK SwitchStatement) + with a matching *Expression*.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +int x = 5; + +switch (x) +{ + case 3: + writeln("case 3"); + goto case; + case 4: + writeln("case 4"); + goto default; + case 5: + writeln("case 5"); + goto case 4; + default: + writeln("default"); + break; +} +--- +) + +$(P Any intervening finally clauses are executed, along with releasing any +intervening synchronization mutexes.) + + $(P It is illegal for a $(I GotoStatement) to be used to skip + initializations within its containing scope.) + + $(BEST_PRACTICE Prefer using a higher-level control-flow construct + or a labelled $(GLINK BreakStatement)/$(GLINK ContinueStatement) + rather than the $(GRAMMAR_INLINE *`goto` Identifier;*) form.) + + +$(H2 $(LEGACY_LNAME2 WithStatement, with-statement, With Statement)) + +$(P The `with` statement is a way to simplify repeated references to the same +object.) + +$(GRAMMAR +$(GNAME WithStatement): + $(D with) $(D $(LPAREN)) $(EXPRESSION) $(D $(RPAREN)) $(PSSCOPE) + $(D with) $(D $(LPAREN)) $(GLINK2 template, Symbol) $(D $(RPAREN)) $(PSSCOPE) + $(D with) $(D $(LPAREN)) $(GLINK2 template, TemplateInstance) $(D $(RPAREN)) $(PSSCOPE) +) + + where *Expression* evaluates to one of: + + $(UL + $(LI a class reference) + $(LI a struct instance) + $(LI an enum instance) + $(LI a pointer to one of the above) + ) + + Within the with body the referenced object is searched first for + identifier symbols. + +--- +enum E { A, B } + +void test(E e) +{ + with (e) // affects the switch statement + switch (e) + { + case A: // no need for E.A + case B: + default: + break; + } +} +--- + +$(P Below, if `ident` is a member of the type of `expression`, the $(I WithStatement):) + +--- +with (expression) +{ + ... + ident; +} +--- + + is semantically equivalent to: + +-------------- +(auto ref tmp) +{ + ... + tmp.ident; +}(expression); +-------------- + + $(P Note that *Expression* only gets evaluated once and is not copied. + The with statement does not change what $(D this) or + $(D super) refer to. + ) + + $(P For $(I Symbol) which is a scope or $(I TemplateInstance), + the corresponding scope is searched when looking up symbols. + For example: + ) + +-------------- +struct Foo +{ + alias Y = int; +} +... +Y y; // error, Y undefined +with (Foo) +{ + Y y; // same as Foo.Y y; +} +-------------- + + $(P Use of `with` object symbols that shadow local symbols with + the same identifier are not allowed. + This is to reduce the risk of inadvertent breakage of with + statements when new members are added to the object declaration. + ) +--- +struct S +{ + float x; +} + +void main() +{ + int x; + S s; + with (s) + { + x++; // error, shadows the int x declaration + } +} +--- + + $(P In nested $(I WithStatement)s, the inner-most scope takes precedence. If + a symbol cannot be resolved at the inner-most scope, resolution is forwarded + incrementally up the scope hierarchy.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +import std.stdio; + +struct Foo +{ + void f() { writeln("Foo.f"); } +} + +struct Bar +{ + void f() { writeln("Bar.f"); } +} + +struct Baz +{ + // f() is not implemented +} + +void f() +{ + writeln("f"); +} + +void main() +{ + Foo foo; + Bar bar; + Baz baz; + + f(); // prints "f" + + with(foo) + { + f(); // prints "Foo.f" + + with(bar) + { + f(); // prints "Bar.f" + + with(baz) + { + f(); // prints "Bar.f". `Baz` does not implement `f()` so + // resolution is forwarded to `with(bar)`'s scope + } + } + with(baz) + { + f(); // prints "Foo.f". `Baz` does not implement `f()` so + // resolution is forwarded to `with(foo)`'s scope + } + } + with(baz) + { + f(); // prints "f". `Baz` does not implement `f()` so + // resolution is forwarded to `main`'s scope. `f()` is + // not implemented in `main`'s scope, so resolution is + // subsequently forward to module scope. + } +} +--- +) + +$(H2 $(LEGACY_LNAME2 SynchronizedStatement, synchronized-statement, Synchronized Statement)) + + $(P The synchronized statement wraps a statement with + mutex locking and unlocking to synchronize access among multiple threads. + ) + +$(GRAMMAR +$(GNAME SynchronizedStatement): + $(D synchronized) $(PSSCOPE) + $(D synchronized $(LPAREN)) $(EXPRESSION) $(D $(RPAREN)) $(PSSCOPE) +) + + $(P A synchronized statement without *Expression* allows only one thread + at a time to execute $(I ScopeStatement) by locking a mutex. + A global mutex is created, one per synchronized statement. + Different synchronized statements will have different global mutexes. + ) + + $(P If there is an *Expression*, it must evaluate to either an + Object or an instance of an $(DDLINK spec/interface, Interfaces, interface), + in which case it + is cast to the Object instance that implemented that interface. + The mutex used is specific to that Object instance, and + is shared by all synchronized statements referring to that instance. + If the object's mutex is already locked when reaching the synchronized + statement, it will block every thread until that mutex is unlocked by + other code. + ) + +$(PANEL +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +void work(); + +void f(Object o) +{ + synchronized (o) work(); +} + +void g(Object o) +{ + synchronized (o) work(); +} +--- +) + $(P If `f` and `g` are called by different threads but with the same + argument, the `work` calls cannot execute simultaneously. If the + `(o)` part of the `synchronized` statements is removed in one + or both functions, then both `work` calls could execute + simultaneously, because they would be protected by different mutexes.) +) + $(P The synchronization gets released even if $(I ScopeStatement) + terminates with an exception, goto, or return. + ) + + $(P This implements a standard critical section. + ) + + $(P Synchronized statements support recursive locking; that is, a + function wrapped in synchronized is allowed to recursively call + itself and the behavior will be as expected: The mutex will be + locked and unlocked as many times as there is recursion. + ) + + $(P See also $(DDSUBLINK spec/class, synchronized-classes, synchronized classes).) + +$(H2 $(LEGACY_LNAME2 TryStatement, try-statement, Try Statement)) + +$(P Exception handling is done with the try-catch-finally statement.) + +$(GRAMMAR +$(GNAME TryStatement): + $(D try) $(PSSCOPE) $(GLINK Catches) + $(D try) $(PSSCOPE) $(GLINK Catches) $(GLINK FinallyStatement) + $(D try) $(PSSCOPE) $(GLINK FinallyStatement) + +$(GNAME Catches): + $(GLINK Catch) + $(GLINK Catch) $(GSELF Catches) + +$(GNAME Catch): + $(D catch $(LPAREN)) $(GLINK CatchParameter) $(D $(RPAREN)) $(GLINK NoScopeNonEmptyStatement) + +$(GNAME CatchParameter): + $(GLINK2 type, BasicType) $(GLINK_LEX Identifier)$(OPT) + +$(GNAME FinallyStatement): + $(D finally) $(GLINK NoScopeNonEmptyStatement) +) + + $(P $(I CatchParameter) declares a variable v of type T, where T is + Throwable or derived from Throwable. v is initialized by the throw + expression if T is of the same type or a base class of the throw + expression. The catch clause will be executed if the exception object is + of type T or derived from T.) + + $(P If just type T is given and no variable v, then the catch clause + is still executed. + ) + + $(P It is an error if any $(I CatchParameter) type T1 hides + a subsequent $(I Catch) with type T2, i.e. it is an error if + T1 is the same type as or a base class of T2. + ) + + $(P The $(I FinallyStatement) is always executed, whether + the $(D try) $(I ScopeStatement) exits with a goto, break, + continue, return, exception, or fall-through. + ) + + $(P If an exception is raised in the $(I FinallyStatement) and is not + caught before the original exception is caught, it is chained to the + previous exception via the $(I next) member of $(I Throwable). + Note that, in contrast to most other programming languages, the new + exception does not replace the original exception. Instead, later + exceptions are regarded as 'collateral damage' caused by the first + exception. The original exception must be caught, and this results in + the capture of the entire chain. + ) + + $(P Thrown objects derived from the $(LINK2 https://dlang.org/phobos/object.html#.Error, $(D Error)) class are treated differently. They + bypass the normal chaining mechanism, such that the chain can only be + caught by catching the first $(D Error). In addition to the list of + subsequent exceptions, $(D Error) also contains a pointer that points + to the original exception (the head of the chain) if a bypass occurred, + so that the entire exception history is retained.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +-------------- +import std.stdio; + +int main() +{ + try + { + try + { + throw new Exception("first"); + } + finally + { + writeln("finally"); + throw new Exception("second"); + } + } + catch (Exception e) + { + writefln("catch %s", e.msg); + } + writeln("done"); + return 0; +} +-------------- +) + + prints: + +$(CONSOLE +finally +catch first +done +) + + + $(P A $(I FinallyStatement) may not exit with a goto, break, + continue, or return; nor may it be entered with a goto. + ) + + $(P A $(I FinallyStatement) may not contain any $(I Catches). + This restriction may be relaxed in future versions. + ) + +$(H2 $(LEGACY_LNAME2 ScopeGuardStatement, scope-guard-statement, Scope Guard Statement)) + +$(GRAMMAR +$(GNAME ScopeGuardStatement): + $(D scope ( exit )) $(GLINK NonEmptyOrScopeBlockStatement) + $(D scope ( success )) $(GLINK NonEmptyOrScopeBlockStatement) + $(D scope ( failure )) $(GLINK NonEmptyOrScopeBlockStatement) +) + +$(P The $(I ScopeGuardStatement) executes *NonEmptyOrScopeBlockStatement* at the close of the +current scope, rather than at the point where the $(I ScopeGuardStatement) +appears. $(D scope(exit)) executes *NonEmptyOrScopeBlockStatement* when the scope exits normally +or when it exits due to exception unwinding. $(D scope(failure)) executes +*NonEmptyOrScopeBlockStatement* when the scope exits due to exception unwinding. +`scope(success)` executes *NonEmptyOrScopeBlockStatement* when the scope exits normally.) + + $(P If there are multiple $(I ScopeGuardStatement)s in a scope, they + will be executed in the reverse lexical order in which they appear. + If any scope instances are to be destroyed upon the close of the + scope, their destructions will be interleaved with the $(I ScopeGuardStatement)s + in the reverse lexical order in which they appear.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +---- +write("1"); +{ + write("2"); + scope(exit) write("3"); + scope(exit) write("4"); + write("5"); +} +writeln(); +---- +) + + writes: + +$(CONSOLE +12543 +) + + +$(SPEC_RUNNABLE_EXAMPLE_RUN +---- +{ + scope(exit) write("1"); + scope(success) write("2"); + scope(exit) write("3"); + scope(success) write("4"); +} +writeln(); +---- +) + + writes: + +$(CONSOLE +4321 +) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +---- +struct Foo +{ + this(string s) { write(s); } + ~this() { write("1"); } +} + +try +{ + scope(exit) write("2"); + scope(success) write("3"); + Foo f = Foo("0"); + scope(failure) write("4"); + throw new Exception("msg"); + scope(exit) write("5"); + scope(success) write("6"); + scope(failure) write("7"); +} +catch (Exception e) +{ +} +writeln(); +---- +) + + writes: + +$(CONSOLE +0412 +) + + A $(D scope(exit)) or $(D scope(success)) statement + may not exit with a throw, goto, break, continue, or + return; nor may it be entered with a goto. A $(D scope(failure)) + statement may not exit with a return. + +$(SPEC_RUNNABLE_EXAMPLE_RUN +-------------- +import std.stdio; + +int foo() +{ + scope(exit) writeln("Inside foo()"); + return bar(); +} + +int bar() +{ + writeln("Inside bar()"); + return 0; +} + +int main() +{ + foo(); + return 0; +} +-------------- +) + + writes: + +$(CONSOLE +Inside bar() +Inside foo() +) + +$(H3 $(LNAME2 catching_cpp_class_objects, Catching C++ Class Objects)) + + $(P + On many platforms, catching C++ class objects is supported. + Catching C++ objects and D objects cannot both be done + in the same $(I TryStatement). + Upon exit from the $(I Catch), any destructors for the C++ + object will be run and the storage used for it reclaimed. + C++ objects cannot be caught in $(D @safe) code. + ) + +$(H2 $(LNAME2 asm, Asm Statement)) + +$(P Inline assembler is supported with the asm statement:) + +$(GRAMMAR +$(GNAME AsmStatement): + $(D asm) $(GLINK2 function, FunctionAttributes)$(OPT) $(D {) $(GLINK AsmInstructionList)$(OPT) $(D }) + +$(GNAME AsmInstructionList): + $(GLINK2 iasm, AsmInstruction) $(D ;) + $(GLINK2 iasm, AsmInstruction) $(D ;) $(GSELF AsmInstructionList) +) + +$(P An asm statement enables the direct use of assembly language instructions. +This makes it easy to obtain direct access to special CPU features without +resorting to an external assembler. The D compiler will take care of the +function calling conventions, stack setup, etc.) + + $(P The format of the instructions is, of course, highly dependent + on the native instruction set of the target CPU, and so is + $(DDLINK spec/iasm, Inline Assembler, implementation defined). + But, the format will follow the following + conventions:) + + $(UL + $(LI It must use the same tokens as the D language uses.) + $(LI The comment form must match the D language comments.) + $(LI Asm instructions are terminated by a ;, not by an + end of line.) + ) + + These rules exist to ensure that D source code can be tokenized + independently of syntactic or semantic analysis. + + $(P For example, for the Intel Pentium:) + +-------------- +int x = 3; +asm +{ + mov EAX,x; // load x and put it in register EAX +} +-------------- + +$(P Inline assembler can be used to access hardware directly:) + +-------------- +int gethardware() +{ + asm + { + mov EAX, dword ptr 0x1234; + } +} +-------------- + +$(P For some D implementations, such as a translator from D to C, an inline +assembler makes no sense, and need not be implemented. The version statement can +be used to account for this:) + +-------------- +version (D_InlineAsm_X86) +{ + asm + { + ... + } +} +else +{ + /* ... some workaround ... */ +} +-------------- + + $(P Semantically consecutive $(I AsmStatement)s shall not have + any other instructions (such as register save or restores) inserted + between them by the compiler. + ) + +$(H2 $(LEGACY_LNAME2 PragmaStatement, pragma-statement, Pragma Statement)) + +$(P See $(GLINK2 pragma, PragmaStatement)). + +$(H2 $(LEGACY_LNAME2 MixinStatement, mixin-statement, Mixin Statement)) + +$(GRAMMAR +$(GNAME MixinStatement): + $(D mixin) $(D $(LPAREN)) $(GLINK2 expression, ArgumentList) $(D $(RPAREN)) $(D ;) +) + + $(P Each $(GLINK2 expression, AssignExpression) in the $(I ArgumentList) is + evaluated at compile time, and the result must be representable + as a string. + The resulting strings are concatenated to form a string. + The text contents of the string must be compilable as a valid + $(GLINK StatementList), and is compiled as such. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +import std.stdio; + +void main() +{ + int i = 0; + mixin(" + int x = 3; + for (; i < 3; i++) + writeln(x + i, i); + "); // ok + + enum s = "int y;"; + mixin(s); // ok + y = 4; // ok, mixin declared y + + string t = "y = 3;"; + //mixin(t); // error, t is not evaluatable at compile time + //mixin("y =") 4; // error, string must be complete statement + + mixin("y =" ~ "4;"); // ok + mixin("y =", 2+2, ";"); // ok +} +--- +) + +$(SPEC_SUBNAV_PREV_NEXT expression, Expressions, arrays, Arrays) +) + +Macros: + CHAPTER=12 + TITLE=Statements + EXPRESSION=$(GLINK2 expression, Expression) + PSSEMI_PSCURLYSCOPE=$(GLINK Statement) + PSSEMI_PSCURLYSCOPE_LIST=$(GLINK ScopeStatementList) + PSSCOPE=$(GLINK ScopeStatement) + _= diff --git a/spec/struct.dd b/spec/struct.dd new file mode 100644 index 0000000000..a96b10d2bf --- /dev/null +++ b/spec/struct.dd @@ -0,0 +1,2717 @@ +Ddoc + +$(SPEC_S Structs and Unions, + +$(HEADERNAV_TOC) + +$(H2 $(LNAME2 intro, Introduction)) + + $(P Whereas $(DDLINK spec/class, Classes, classes) are reference types, + structs and unions are value types. + Structs are simple aggregations of data and their + associated operations on that data. + ) + +$(GRAMMAR +$(GNAME StructDeclaration): + $(D struct) $(GLINK_LEX Identifier) $(D ;) + $(D struct) $(GLINK_LEX Identifier) $(GLINK AggregateBody) + $(GLINK2 template, StructTemplateDeclaration) + $(I AnonStructDeclaration) + +$(GNAME AnonStructDeclaration): + $(D struct) $(GLINK AggregateBody) +) +$(GRAMMAR +$(GNAME UnionDeclaration): + $(D union) $(GLINK_LEX Identifier) $(D ;) + $(D union) $(GLINK_LEX Identifier) $(GLINK AggregateBody) + $(GLINK2 template, UnionTemplateDeclaration) + $(I AnonUnionDeclaration) + +$(GNAME AnonUnionDeclaration): + $(D union) $(GLINK AggregateBody) +) +$(GRAMMAR +$(GNAME AggregateBody): + $(D {) $(GLINK2 module, DeclDefs)$(OPT) $(D }) +) + + $(P The following example declares a struct type with a single integer field:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + int i; +} + +void main() +{ + S a; + a.i = 3; + + S b = a; // copy a + a.i++; + assert(a.i == 4); + assert(b.i == 3); +} +--- +) + + $(P For local variables, a struct/union instance is allocated on the stack + by default. To allocate on the heap, use $(DDSUBLINK spec/expression, new_expressions, + `new`), which gives a pointer.) + + $(PANEL + A $(LNAME2 struct-pointer, pointer to a struct) or union is automatically + dereferenced when using the `.` operator to access members. + --- + S* p = new S; + assert(p.i == 0); // `p.i` is the same as `(*p).i` + --- + $(NOTE There is no `->` operator as in C.) + ) + + $(P A struct can contain multiple fields which are stored sequentially. + Conversely, multiple fields in a union use overlapping storage.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +union U +{ + ubyte i; + char c; +} + +void main() +{ + U u; + u.i = 3; + assert(u.c == '\x03'); + u.c++; + assert(u.i == 4); +} +--- +) + +$(H2 $(LNAME2 members, Members)) + +$(H3 $(LNAME2 struct-members, Struct Members)) + + $(P A struct definition can contain:) + $(UL + $(LI Fields) + $(LI $(DDSUBLINK spec/attribute, static, Static) fields) + $(LI $(RELATIVE_LINK2 anonymous, Anonymous Structs and Unions)) + $(LI $(RELATIVE_LINK2 member-functions, Member Functions) + $(UL + $(LI $(DDSUBLINK spec/attribute, static, Static) member functions) + $(LI $(RELATIVE_LINK2 struct-constructor, Constructors)) + $(LI $(RELATIVE_LINK2 struct-destructor, Destructors)) + $(LI $(RELATIVE_LINK2 Invariant, Invariants)) + $(LI $(DDLINK spec/operatoroverloading, Operator Overloading, Operator Overloading)) + ) + $(LI $(RELATIVE_LINK2 alias-this, Alias This)) + $(LI Other declarations (see $(GLINK2 module, DeclDef))) + ) + ) + + $(P A struct is defined to not have an identity; that is, + the implementation is free to make bit copies of the struct + as convenient.) + + $(BEST_PRACTICE + $(OL + $(LI Bit fields are supported with the + $(LINK2 https://dlang.org/phobos/std_bitmanip.html#bitfields, bitfields) template.) + )) + +$(H3 $(LNAME2 union-members, Union Members)) + + $(P A union definition can contain:) + $(UL + $(LI Fields) + $(LI $(DDSUBLINK spec/attribute, static, Static) fields) + $(LI $(RELATIVE_LINK2 anonymous, Anonymous Structs and Unions)) + $(LI $(DDSUBLINK spec/class, member-functions, member functions) + $(UL + $(LI static member functions) + $(LI $(RELATIVE_LINK2 UnionConstructor, Constructors)) + $(LI $(DDLINK spec/operatoroverloading, Operator Overloading, Operator Overloading)) + ) + $(LI $(RELATIVE_LINK2 alias-this, Alias This)) + $(LI Other declarations (see $(GLINK2 module, DeclDef))) + ) + ) + +$(H3 $(LNAME2 recursive-types, Recursive Structs and Unions)) + + $(P Structs and unions may not contain a non-static instance of themselves, + however, they may contain a pointer to the same type. + ) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S + { + S* ptr; // OK + S[] slice; // OK + + S s; // error + S[2] array; // error + + static S global; // OK + } + --- + ) + + +$(H2 $(LNAME2 struct_layout, Struct Layout)) + + $(P The non-static data members of a struct are called $(I fields). Fields are laid + out in lexical order. Fields are aligned according to the $(DDSUBLINK spec/attribute, align, Align Attribute) + in effect. + Unnamed padding is inserted between fields to align fields. There is no padding between + the first field and the start of the object. + ) + + $(P $(DDSUBLINK spec/attribute, linkage, `extern(D)`) structs with no fields of non-zero + size (aka $(I Empty Structs)) have a size of one byte.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + extern(C) struct C {} + struct D {} + + static assert(C.sizeof == 0); + static assert(D.sizeof == 1); + --- + ) + + $(P Non-static $(RELATIVE_LINK2 nested, function-nested D structs), which access the context of + their enclosing scope, have an extra field. + ) + + $(IMPLEMENTATION_DEFINED + $(OL + $(LI The default layout of the fields of a struct is an exact + match with the $(I associated C compiler).) + $(LI g++ and clang++ differ in how empty structs are handled. Both return `1` from `sizeof`, + however, clang++ does not push them onto the parameter stack while g++ does. This is a + binary incompatibility between g++ and clang++. + dmd follows clang++ behavior for OSX and FreeBSD, and g++ behavior for Linux and other + Posix platforms. + ) + $(LI clang and gcc both return `0` from `sizeof` for empty structs. Using `extern "C++"` + in clang++ and g++ does not cause them to conform to the behavior of their respective C compilers.) + )) + + $(UNDEFINED_BEHAVIOR + $(OL + $(LI The padding data can be accessed, but its contents are undefined.) + $(LI Do not pass or return structs with no fields of non-zero size to `extern (C)` functions. + According to C11 6.7.2.1p8 this is undefined behavior.) + )) + + $(BEST_PRACTICE + $(OL + $(LI When laying out a struct to match an externally defined layout, use align + attributes to describe an exact match. Using a $(DDSUBLINK spec/version, static-assert, Static Assert) + to ensure the result is as expected.) + $(LI Although the contents of the padding are often zero, do not rely on that.) + $(LI Avoid using empty structs when interfacing with C and C++ code.) + $(LI Avoid using empty structs as parameters or arguments to variadic functions.) + )) + +$(H2 $(LNAME2 POD, Plain Old Data)) + + $(P A struct or union is $(I Plain Old Data) (POD) if it meets the following criteria:) + + $(OL + $(LI it is static, or not nested) + $(LI it has no postblits, copy constructors, destructors, or assignment operators) + $(LI it has no fields that are themselves non-POD) + ) + + $(BEST_PRACTICE Structs or unions that interface with C code should be POD.) + + +$(H2 $(LNAME2 opaque_struct_unions, Opaque Structs and Unions)) + + $(P Opaque struct and union declarations do not have an $(GLINK AggregateBody):) + +--- +struct S; +union U; +struct V(T); +union W(T); +--- + + $(P The members are completely hidden to the user, and so the only operations + on those types are ones that do not require any knowledge of the contents + of those types. For example:) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +struct S; +S.sizeof; // error, size is not known +S s; // error, cannot initialize unknown contents +S* p; // ok, knowledge of members is not necessary +--- +) + + $(BEST_PRACTICE They can be used to implement the + $(LINK2 https://en.wikipedia.org/wiki/Opaque_pointer, PIMPL idiom).) + + +$(H2 $(LNAME2 initialization, Initialization)) + +$(H3 $(LNAME2 default_struct_init, Default Initialization of Structs)) + + $(P Struct fields are by default initialized to whatever the + $(GLINK2 declaration, Initializer) for the field is, and if none is supplied, to + the $(DDSUBLINK spec/property, init, default initializer) for the field's type. + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S { int a = 4; int b; } + S x; // x.a is set to 4, x.b to 0 + --- + ) + + $(P The default initializers are evaluated at compile time.) + +$(H3 $(LNAME2 static_struct_init, Static Initialization of Structs)) + +$(GRAMMAR +$(GNAME StructInitializer): + $(D {) $(I StructMemberInitializers)$(OPT) $(D }) + +$(GNAME StructMemberInitializers): + $(I StructMemberInitializer) + $(I StructMemberInitializer) $(D ,) + $(I StructMemberInitializer) $(D ,) $(GSELF StructMemberInitializers) + +$(GNAME StructMemberInitializer): + $(GLINK2 declaration, NonVoidInitializer) + $(GLINK_LEX Identifier) $(D :) $(GLINK2 declaration, NonVoidInitializer) +) + + $(P If a $(I StructInitializer) is supplied, + each $(I StructMemberInitializer) initializes a matching field:) + + * A $(I StructMemberInitializer) using the $(I Identifier : NonVoidInitializer) syntax + may appear in any order. The identifier must match a field name. + * If the first $(I StructMemberInitializer) does not specify an *Identifier*, + it refers to the first field in the $(GLINK StructDeclaration). + * A subsequent *NonVoidInitializer* without an *Identifier* refers to the next field + (in lexical order) after the one referred to in the previous *StructMemberInitializer*. + + $(P Any field not covered by a $(I StructMemberInitializer) is default initialized.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S { int a, b, c, d = 7; } + + S r; // r.a = 0, r.b = 0, r.c = 0, r.d = 7 + S s = { a:1, b:2 }; // s.a = 1, s.b = 2, s.c = 0, s.d = 7 + S t = { c:4, b:5, a:2, d:5 }; // t.a = 2, t.b = 5, t.c = 4, t.d = 5 + S u = { 1, 2 }; // u.a = 1, u.b = 2, u.c = 0, u.d = 7 + S v = { 1, d:3 }; // v.a = 1, v.b = 0, v.c = 0, v.d = 3 + S w = { b:1, 3 }; // w.a = 0, w.b = 1, w.c = 3, w.d = 7 + --- + ) + + $(P Initializing a field more than once is an error:) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + S x = { 1, a:2 }; // error: duplicate initializer for field `a` + --- + ) + +$(H3 $(LNAME2 default_union_init, Default Initialization of Unions)) + + $(P Unions are by default initialized to whatever the + $(GLINK2 declaration, Initializer) for the first field is, and if none is supplied, to + the default initializer for the first field's type. + If the union is larger than the first field, the remaining bits + are set to 0.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + union U { int a = 4; long b; } + U x; // x.a is set to 4, x.b to an implementation-defined value + --- + ) + + $(P It is an error to supply initializers for members other than the first one.) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + union V { int a; long b = 4; } // error: union field `b` with default initialization `4` must be before field `a` + union W { int a = 4; long b = 5; } // error: overlapping default initialization for `a` and `b` + --- + ) + + $(P The default initializer is evaluated at compile time.) + + $(IMPLEMENTATION_DEFINED The values the fields other than the + default initialized field are set to.) + +$(H3 $(LNAME2 static_union_init, Static Initialization of Unions)) + + $(P Unions are initialized + $(RELATIVE_LINK2 static_struct_init, similarly to structs), except that only + one member initializer is allowed. If the member initializer does not specify + an identifier, it will initialize the first member of the union.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + union U { int a; double b; } + U u = { 2 }; // u.a = 2 + U v = { b : 5.0 }; // v.b = 5.0 + --- + ) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + U w = { 2, 3 }; // error: overlapping initialization for field `a` and `b` + --- + ) + + $(P If the union is larger than the initialized field, the remaining bits + are set to 0.) + + $(IMPLEMENTATION_DEFINED The values the fields other than the + initialized field are set to.) + +$(H3 $(LNAME2 dynamic_struct_init, Dynamic Initialization of Structs)) + + $(P The $(RELATIVE_LINK2 static_struct_init, static initializer syntax) + can also be used to initialize non-static variables. + The initializer need not be evaluable at compile time.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +---- +struct S { int a, b, c, d = 7; } + +void test(int i) +{ + S q = { 1, b:i }; // q.a = 1, q.b = i, q.c = 0, q.d = 7 +} +---- +) + + $(P Structs can be dynamically initialized from another + value of the same type:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +---- +struct S { int a; } +S t; // default initialized +t.a = 3; +S s = t; // s.a is set to 3 +---- +) + + $(P If the struct has a $(RELATIVE_LINK2 struct-constructor, constructor), and + the struct is initialized with a value that is of a different type, + then the constructor is called:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +---- +struct S +{ + int a; + + this(int v) + { + this.a = v; + } +} + +S s = 3; // sets s.a to 3 using S's constructor +---- +) + + $(P If the struct does not have a constructor but + $(DDSUBLINK spec/operatoroverloading, FunctionCall, `opCall`) is + overridden for the struct, and the struct is initialized with a value + that is of a different type, then the $(D opCall) operator is called:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +---- +struct S +{ + int a; + + static S opCall(int v) + { + S s; + s.a = v; + return s; + } + + static S opCall(S v) + { + assert(0); + } +} + +S s = 3; // sets s.a to 3 using S.opCall(int) +S t = s; // sets t.a to 3, S.opCall(S) is not called +---- +) + +$(H3 $(LNAME2 dynamic_union_init, Dynamic Initialization of Unions)) + + $(P The $(RELATIVE_LINK2 static_union_init, static initializer syntax) + can also be used to initialize non-static variables. + The initializer need not be evaluable at compile time.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +union U { int a; double b; } + +void test(int i) +{ + U u = { a : i }; // u.a = i + U v = { b : 5.0 }; // v.b = 5.0 +} +--- +) + +$(H2 $(LEGACY_LNAME2 StructLiteral, struct-literal, Struct Literals)) + + $(P A struct literal consists of the name of the struct followed + by a parenthesized named argument list:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + struct S { int x; float y; } + + S s1 = S(1, 2); // set field x to 1, field y to 2 + S s2 = S(y: 2, x: 1); // same as above + assert(s1 == s2); + --- + ) + + $(P + If a struct has a $(RELATIVE_LINK2 struct-constructor, constructor) + or a member function named `opCall`, then + struct literals for that struct are not possible. See also + $(DDSUBLINK spec/operatoroverloading, FunctionCall, opCall operator overloading) + for the issue workaround.) + + $(P Struct literals are syntactically like function calls.) + + $(PANEL + Arguments are assigned to fields as follows: + + 1. If the first argument has no name, it will be assigned to the struct field that is defined first lexically. + 1. A named argument is assigned to the struct field with the same name. + It is an error if no such field exists. + 1. Any other argument is assigned to the next lexically defined struct field relative to the preceding argument's struct field. + It is an error if no such field exists, i.e. when the preceding argument assigns to the last struct field. + 1. It is also an error to assign a field more than once. + 1. Any fields not assigned a value are initialized with their respective default initializers. + + **Note:** + These rules are consistent with function calls, see $(DDSUBLINK spec/function, argument-parameter-matching, Matching Arguments to Parameters). + ) + $(P + If there is a union field in the struct, only one + member of the union can be initialized inside a + struct literal. This matches the behaviour for union literals. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + struct S { int x = 1, y = 2, z = 3; } + + S s0 = S(y: 5, 6, x: 4); // `6` is assigned to field `z`, which comes after `y` + assert(s0.z == 6); + + S s1 = S(y: 5, z: 6); // Field x is not assigned, set to default initializer `1` + assert(s1.x == 1); + + //S s2 = S(y: 5, x: 4, 5); // Error: field `y` is assigned twice + //S s3 = S(z: 2, 3); // Error: no field beyond `z` + --- + ) + +$(H2 $(LNAME2 union-literal, Union Literals)) + + $(P A union literal is like a struct literal, but only one field can + be initialized with an initializer expression. + The remainder of the union's memory is initialized to zero. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +union U +{ + byte a; + char[2] b; +} + +U u = U(2); +assert(u.a == 2); +assert(u.b == [2, 0]); +--- +) + +$(H2 $(LNAME2 anonymous, Anonymous Structs and Unions)) + + $(P An anonymous struct or union can be declared as a member of a + parent class, struct or union by omitting the identifier after `struct` or `union`. + An anonymous struct declares sequentially stored fields in the + parent type. An anonymous union declares overlapping fields in + the parent type.) + + $(P An anonymous union is useful inside a class or struct to share + memory for fields, without having to name a parent field with a + separate union type.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + int a; + union + { + byte b; + char c; + } +} + +S s = S(1, 2); +assert(s.a == 1); +assert(s.b == 2); +assert(s.c == 2); // overlaps with `b` +--- +) + + $(P Conversely, an anonymous struct is useful inside a union to + declare multiple fields that are stored sequentially.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +union U +{ + int a; + struct + { + uint b; + bool c; + } +} + +U u = U(1); +assert(u.a == 1); +assert(u.b == 1); // overlaps with `a` +assert(u.c == false); // no overlap +--- +) + +$(H2 $(LEGACY_LNAME2 struct_instance_properties, struct_properties, Struct Properties)) + +$(TABLE +$(THEAD Name, Description) +$(TROW $(D .alignof), Size boundary struct needs to be aligned on) +$(TROW $(D .tupleof), A $(DDSUBLINK spec/template, variadic-templates, symbol sequence) + of all struct fields - see + $(DDSUBLINK spec/class, tupleof, class `.tupleof`) for more details.) +) + +$(H3 $(LNAME2 struct_field_properties, Struct Field Properties)) + +$(TABLE2 Struct Field Properties, +$(THEAD Name, Description) +$(TROW $(D .offsetof), Offset in bytes of field from beginning of struct. + See $(DDSUBLINK spec/attribute, align, the `align` attribute) for an example. +) +) + +$(H2 $(LEGACY_LNAME2 ConstStruct, const-struct, Const, Immutable and Shared Structs)) + + $(P A struct declaration can have a storage class of + $(CODE const), $(CODE immutable) or $(CODE shared). It has an equivalent + effect as declaring each member of the struct as + $(CODE const), $(CODE immutable) or $(CODE shared). + ) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + ---- + const struct S { int a; int b = 2; } + void main() + { + S s = S(3); // initializes s.a to 3 + S t; // initializes t.a to 0 + t = s; // error, t.a and t.b are const, so cannot modify them. + t.a = 4; // error, t.a is const + } + ---- + ) + + +$(H2 $(LNAME2 UnionConstructor, Union Constructors)) + + $(P Unions are constructed in the same way as structs.) + + +$(H2 $(LEGACY_LNAME2 Struct-Constructor, struct-constructor, Struct Constructors)) + + $(P Struct constructors are used to initialize an instance of a struct when a more + complex construction is needed than is allowed by + $(RELATIVE_LINK2 static_struct_init, static initialization) or a + $(RELATIVE_LINK2 struct-literal, struct literal). + ) + + $(P Constructors are defined with a function name of `this` and have no return value. + The grammar is the same as for the class $(GLINK2 class, Constructor). + ) + + $(P A struct constructor is called by the name of the struct followed by + $(GLINK2 function, Parameters). + ) + $(P If the $(GLINK2 function, ParameterList) is empty, + the struct instance is default initialized.) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S + { + int x, y = 4, z = 6; + this(int a, int b) + { + x = a; + y = b; + } + } + + void main() + { + S a = S(4, 5); // calls S.this(4, 5): a.x = 4, a.y = 5, a.z = 6 + S b = S(); // default initialized: b.x = 0, b.y = 4, b.z = 6 + S c = S(1); // error, matching this(int) not found + } + --- + ) + + $(P Named arguments will be forwarded to the constructor and match parameter names, not struct field names.) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S + { + int x; + int y; + this(int y, int z) { this.x = y; this.y = z; } + } + S a = S(x: 3, y: 4); // Error: constructor has no parameter named `x` + S b = S(y: 3, 4); // `y: 3` will set field `x` through parameter `y` + --- + ) + + $(P A $(I default constructor) (i.e. one with an empty $(GLINK2 function, ParameterList)) + is not allowed.) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S + { + int x; + this() { } // error, struct default constructor not allowed + } + --- + ) + +$(H3 $(LNAME2 delegating-constructor, Delegating Constructors)) + + $(P A constructor can call another constructor for the same struct + in order to share common initializations. This is called a + $(I delegating constructor): + ) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S + { + int j = 1; + long k = 2; + this(long k) + { + this.k = k; + } + this(int i) + { + // At this point: j=1, k=2 + $(CODE_HIGHLIGHT this)(6); // delegating constructor call + // At this point: j=1, k=6 + j = i; + // At this point: j=i, k=6 + } + } + --- + ) + + $(P The following restrictions apply:) + + $(OL + $(LI If a constructor's code contains a delegating constructor call, all + possible execution paths through the constructor must make exactly one + delegating constructor call: + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S + { + int a; + this(int i) { } + + this(char c) + { + c || this(1); // error, not on all paths + } + + this(wchar w) + { + (w) ? this(1) : this('c'); // ok + } + + this(byte b) + { + foreach (i; 0 .. b) + { + this(1); // error, inside loop + } + } + } + --- + ) + ) + + $(LI It is illegal to refer to $(D this) implicitly or explicitly + prior to making a delegating constructor call.) + + $(LI Once the delegating constructor returns, all fields are considered + constructed.) + + $(LI Delegating constructor calls cannot appear after labels.) + ) + + $(P See also: $(DDSUBLINK spec/class, delegating-constructors, delegating class constructors).) + + +$(H3 $(LNAME2 struct-instantiation, Struct Instantiation)) + + $(P When an instance of a struct is created, the following steps happen:) + + $(OL + $(LI The raw data is statically initialized using the values provided + in the struct definition. + This operation is equivalent to doing a memory copy of a static + version of the object onto the newly allocated one. + ) + + $(LI If there is a constructor defined for the struct, + the constructor matching the argument list is called. + ) + + $(LI If struct invariant checking is turned on, the struct invariant + is called at the end of the constructor. + ) + ) + + +$(H3 $(LNAME2 constructor-attributes, Constructor Attributes)) + + $(P A constructor qualifier (`const`, `immutable` or `shared`) constructs the object instance + with that specific qualifier. + ) + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S1 + { + int[] a; + this(int n) { a = new int[](n); } + } + struct S2 + { + int[] a; + this(int n) immutable { a = new int[](n); } + } + void main() + { + // Mutable constructor creates mutable object. + S1 m1 = S1(1); + + // Constructed mutable object is implicitly convertible to const. + const S1 c1 = S1(1); + + // Constructed mutable object is not implicitly convertible to immutable. + immutable i1 = S1(1); // error + + // Mutable constructor cannot construct immutable object. + auto x1 = immutable S1(1); // error + + + // Immutable constructor creates immutable object. + immutable i2 = immutable S2(1); + + // Immutable constructor cannot construct mutable object. + auto x2 = S2(1); // error + + // Constructed immutable object is not implicitly convertible to mutable. + S2 m2 = immutable S2(1); // error + + // Constructed immutable object is implicitly convertible to const. + const S2 c2 = immutable S2(1); + } + --- + ) + + $(P Constructors can be overloaded with different attributes.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S + { + this(int); // non-shared mutable constructor + this(int) shared; // shared mutable constructor + this(int) immutable; // immutable constructor + } + + void fun() + { + S m = S(1); + shared s = shared S(2); + immutable i = immutable S(3); + } + --- + ) + +$(H4 $(LNAME2 pure-constructors, Pure Constructors)) + + $(P If the constructor can create a unique object (i.e. if it is `pure`), + the object is implicitly convertible to any qualifiers. + ) + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S + { + this(int) pure; + // Based on the definition, this creates a mutable object. But the + // created object cannot contain any mutable global data. + // Therefore the created object is unique. + + this(int[] arr) immutable pure; + // Based on the definition, this creates an immutable object. But + // the argument int[] never appears in the created object so it + // isn't implicitly convertible to immutable. Also, it cannot store + // any immutable global data. + // Therefore the created object is unique. + } + + void fun() + { + immutable i = immutable S(1); // this(int) pure is called + shared s = shared S(1); // this(int) pure is called + S m = S([1,2,3]); // this(int[]) immutable pure is called + } + --- + ) + + + +$(H3 $(LNAME2 disable_default_construction, Disabling Default Struct Construction)) + + $(P If a struct constructor is annotated with $(D @disable) and has + an empty $(GLINK2 function, ParameterList), the struct has disabled default construction. + The only way it can be constructed is via a call to another constructor with a non-empty + $(I ParameterList). + ) + + $(P A struct with a disabled default constructor, and no other constructors, cannot + be instantiated other than via a $(GLINK2 declaration, VoidInitializer).) + + $(P A disabled default constructor may not have a $(GLINK2 function, FunctionBody).) + + $(P If any fields have disabled default construction, struct default construction is + also disabled.) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S + { + int x; + + // Disables default construction + @disable this(); + + this(int v) { x = v; } + } + struct T + { + int y; + S s; + } + void main() + { + S s; // error: default construction is disabled + S t = S(); // error: also disabled + S u = S(1); // constructed by calling `S.this(1)` + S v = void; // not initialized, but allowed + S w = { 1 }; // error: cannot use { } since constructor exists + S[3] a; // error: default construction is disabled + S[3] b = [S(1), S(20), S(-2)]; // ok + T t; // error: default construction is disabled + } + --- + ) + + $(BEST_PRACTICE Disabling default construction is useful when the default value, + such as `null`, is not acceptable.) + + +$(H3 $(LNAME2 field-init, Field initialization inside a constructor)) + + $(P In a constructor body, if a delegating constructor is called, + all field assignments are considered assignments. + Otherwise, the first instance of field assignment is + its initialization, and assignments of the form `field = expression` + are treated as equivalent to `typeof(field)(expression)`. + The values of fields may be read before initialization or construction + with a delegating constructor. + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S + { + int num; + int ber; + this(int i) + { + num = i + 1; // initialization + num = i + 2; // assignment + ber = ber + 1; // ok to read before initialization + } + this(int i, int j) + { + this(i); + num = i + 1; // assignment + } + } + --- + ) + + $(P If the field type has an $(DDSUBLINK spec/operatoroverloading, assignment, `opAssign`) + method, it will not be used for initialization.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct A + { + this(int n) {} + void opAssign(A rhs) {} + } + struct S + { + A val; + this(int i) + { + val = A(i); // val is initialized to the value of A(i) + val = A(2); // rewritten to val.opAssign(A(2)) + } + } + --- + ) + + $(P If the field type is not mutable, multiple initialization will be rejected.) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S + { + immutable int num; + this(int) + { + num = 1; // OK + num = 2; // Error: assignment to immutable + } + } + --- + ) + + $(P If the field is initialized on one path, it must be initialized on all paths.) + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S + { + immutable int num; + immutable int ber; + this(int i) + { + if (i) + num = 3; // initialization + else + num = 4; // initialization + } + this(long j) + { + j ? (num = 3) : (num = 4); // ok + j || (ber = 3); // Error: initialized on only one path + j && (ber = 3); // Error: initialized on only one path + } + } + --- + ) + + $(P A field initialization may not appear in a loop or after + a label.) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S + { + immutable int num; + immutable string str; + this(int j) + { + foreach (i; 0..j) + { + num = 1; // Error: field initialization not allowed in loops + } + size_t i = 0; + Label: + str = "hello"; // Error: field initialization not allowed after labels + if (i++ < 2) + goto Label; + } + this(int j, int k) + { + switch (j) + { + case 1: ++j; break; + default: break; + } + num = j; // Error: `case` and `default` are also labels + } + } + --- + ) + + $(P If a field's type has disabled default construction, then it must be initialized + in the constructor.) + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S { int y; @disable this(); } + + struct T + { + S s; + this(S t) { s = t; } // ok + this(int i) { this('c'); } // ok + this(char) { } // Error: s not initialized + } + --- + ) + +$(H2 $(LEGACY_LNAME2 StructCopyConstructor, struct-copy-constructor, Struct Copy Constructors)) + + $(PANEL + $(P $(RED Warning:) The plan is for + $(RELATIVE_LINK2 struct-copy-constructor, copy constructors) to replace + $(RELATIVE_LINK2 struct-postblit, postblit constructors), leaving + postblit constructors only in legacy code. However, because the + compiler hooks in druntime which deal with dynamic arrays and + associative arrays have not yet all been updated to support copy + constructors properly + ($(HTTPS github.com/dlang/dmd/issues/20970, issue #20970)), any type + that might be used in a dynamic array or associative array should use a + postblit constructor rather than a copy constructor. The copy + constructor will not be called in all the cases where it should be for + the elements of a dynamic array or the keys or values in an associative + array. Postblit constructors do not have this problem.) + + $(P For backward compatibility reasons, a `struct` that explicitly + defines both a copy constructor and a postblit will only use the + postblit for implicit copying. However, if the postblit is disabled, + the copy constructor will be used. If a struct defines a copy + constructor (user-defined or generated) and has fields that define + postblits, a deprecation will be issued, informing that the postblit + will have priority over the copy constructor.)) + + $(P Copy constructors are used to initialize a `struct` instance from + another instance of the same type. A `struct` that defines a copy constructor + is not $(RELATIVE_LINK2 POD, POD).) + + $(P A constructor declaration is a copy constructor declaration if it meets + the following requirements:) + + $(UL + $(LI It takes exactly one parameter without a + $(DDSUBLINK spec/function, function-default-args, default argument), + followed by any number of parameters with default arguments.) + + $(LI Its first parameter is a + $(DDSUBLINK spec/function, ref-params, `ref` parameter).) + + $(LI The type of its first parameter is the same type as + $(DDSUBLINK spec/type, typeof, `typeof(this)`), optionally with one or more + $(DDLINK spec/const3, Type Qualifiers, type qualifiers) applied to it.) + + $(LI It is not a + $(DDSUBLINK spec/template, template_ctors, template constructor declaration).) + ) + + --- + struct A + { + this(ref return scope A rhs) {} // copy constructor + this(ref return scope const A rhs, int b = 7) {} // copy constructor with default parameter + } + --- + + $(P The copy constructor is type checked as a normal constructor.) + + $(P If a copy constructor is defined, implicit calls to it will be inserted + in the following situations:) + + $(OL + $(LI When a variable is explicitly initialized:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + struct A + { + int[] arr; + this(ref return scope A rhs) { arr = rhs.arr.dup; } + } + + void main() + { + A a; + a.arr = [1, 2]; + + A b = a; // copy constructor gets called + b.arr[] += 1; + assert(a.arr == [1, 2]); // a is unchanged + assert(b.arr == [2, 3]); + } + --- + ) + + $(LI When a parameter is passed by value to a function:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct A + { + this(ref return scope A another) {} + } + + void fun(A a) {} + + void main() + { + A a; + fun(a); // copy constructor gets called + } + --- + ) + + $(LI When a parameter is returned by value from a function and Named Returned Value Optimization (NRVO) + cannot be performed:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct A + { + this(ref return scope A another) {} + } + + A fun() + { + A a; + return a; // NRVO, no copy constructor call + } + + A a; + A gun() + { + return a; // cannot perform NRVO, rewrite to: return (A __tmp; __tmp.copyCtor(a)); + } + + void main() + { + A a = fun(); + A b = gun(); + } + --- + ) + ) + +$(H3 $(LNAME2 disable-copy, Disabled Copying)) + + $(P When a copy constructor is defined for a `struct` (or marked `@disable`), the compiler no + longer implicitly generates default copy/blitting constructors for that `struct`: + ) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct A + { + int[] a; + this(ref return scope A rhs) {} + } + + void fun(immutable A) {} + + void main() + { + immutable A a; + fun(a); // error: copy constructor cannot be called with types (immutable) immutable + } + --- + ) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct A + { + @disable this(ref A); + } + + void main() + { + A a; + A b = a; // error: copy constructor is disabled + } + --- + ) + + $(P If a `union U` has fields that define a copy constructor, whenever an object of type `U` + is initialized by copy, an error will be issued. The same rule applies to overlapped fields + (anonymous unions).) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S + { + this(ref S); + } + + union U + { + S s; + } + + void main() + { + U a; + U b = a; // error, could not generate copy constructor for U + } + --- + ) + +$(H3 $(LNAME2 copy-constructor-attributes, Copy Constructor Attributes)) + + $(P The copy constructor can be overloaded with different qualifiers applied + to the parameter (copying from a qualified source) or to the copy constructor + itself (copying to a qualified destination): + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct A + { + this(ref return scope A another) {} // 1 - mutable source, mutable destination + this(ref return scope immutable A another) {} // 2 - immutable source, mutable destination + this(ref return scope A another) immutable {} // 3 - mutable source, immutable destination + this(ref return scope immutable A another) immutable {} // 4 - immutable source, immutable destination + } + + void main() + { + A a; + immutable A ia; + + A a2 = a; // calls 1 + A a3 = ia; // calls 2 + immutable A a4 = a; // calls 3 + immutable A a5 = ia; // calls 4 + } + --- + ) + + $(P The `inout` qualifier may be applied to the copy constructor parameter in + order to specify that mutable, `const`, or `immutable` types are treated the same: + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct A + { + this(ref return scope inout A rhs) immutable {} + } + + void main() + { + A r1; + const(A) r2; + immutable(A) r3; + + // All call the same copy constructor because `inout` acts like a wildcard + immutable(A) a = r1; + immutable(A) b = r2; + immutable(A) c = r3; + } + --- + ) + +$(H3 $(LNAME2 implicit-copy-constructors, Implicit Copy Constructors)) + + $(P A copy constructor is generated implicitly by the compiler for a `struct S` + if all of the following conditions are met:) + + $(OL + $(LI `S` does not explicitly declare any copy constructors;) + $(LI `S` defines at least one direct member that has a copy constructor, and that + member is not overlapped (by means of `union`) with any other member.) + ) + + $(P If the restrictions above are met, the following copy constructor is generated:) + + --- + this(ref return scope inout(S) src) inout + { + foreach (i, ref inout field; src.tupleof) + this.tupleof[i] = field; + } + --- + + $(P If the generated copy constructor fails to type check, it will receive the `@disable` attribute.) + +$(H2 $(LEGACY_LNAME2 StructMoveConstructor, struct-move-constructor, Struct Move Constructors)) + + $(P Move constructors are very much like copy constructors. The difference is that copy + constructors make a copy of the original, while move constructors move the contents of + the original, and the lifetime of the original ends.) + + $(NOTE Do not use postblits in the same struct with move constructors.) + + $(COMMENT $(P A `struct` that defines a move constructor + is not $(RELATIVE_LINK2 POD, POD).)) + $(P If a move constructor is declared, also declare a copy constructor.) + + $(P A constructor declaration is a move constructor declaration if it meets + the following requirements:) + + $(UL + $(LI It takes exactly one parameter without a + $(DDSUBLINK spec/function, function-default-args, default argument), + followed by any number of parameters with default arguments.) + + $(LI Its first parameter is not a + $(DDSUBLINK spec/function, ref-params, `ref` parameter).) + + $(LI The type of its first parameter is the same type as + $(DDSUBLINK spec/type, typeof, `typeof(this)`), optionally with one or more + $(DDLINK spec/const3, Type Qualifiers, type qualifiers) applied to it.) + + $(LI It is not a + $(DDSUBLINK spec/template, template_ctors, template constructor declaration).) + ) + + --- + struct A + { + this(ref return scope A rhs) {} // copy constructor + this(return scope A rhs) {} // move constructor + this(return scope const A rhs, int b = 7) {} // move constructor with default parameter + } + --- + + $(P The move constructor is type checked as a normal constructor.) + + $(P The move constructor's first parameter only accepts rvalues. An + lvalue can be coerced into being an rvalue using + $(DDSUBLINK spec/expression, RvalueExpression, `__rvalue(Expression)`).) + + $(P If a move constructor is defined, implicit calls to it will be inserted + in the following situations:) + + $(OL + $(LI When a variable is explicitly initialized:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + struct A + { + int[] arr; + this(return scope A rhs) // move constructor + { + arr = rhs.arr; + rhs.arr = null; // do not leave dangling reference to array + } + this(ref return scope A rhs) { assert(0); } + } + + void main() + { + A a; + a.arr = [1, 2]; + + A b = __rvalue(a); // move constructor gets called + b.arr[] += 1; + assert(a.arr is null); // a.arr is gone + assert(b.arr == [2, 3]); + } + --- + ) + + $(LI When a parameter is passed by value to a function:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct A + { + this(return scope A another) {} // move constructor + this(ref return scope A rhs) { assert(0); } + } + + void fun(A a) {} + + void main() + { + A a; + fun(__rvalue(a)); // move constructor gets called + // `a` is no longer a valid object + } + --- + ) +) + +$(H3 $(LNAME2 disable-move, Disabled Moving)) + + $(P When a move constructor is defined for a `struct` (or marked `@disable`), the compiler no + longer $(RELATIVE_LINK2 implicit-move-constructors, implicitly generates) default move constructors for that `struct`: + ) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct A + { + this(ref A); + @disable this(A); + } + + void main() + { + A a; + A b = __rvalue(a); // error: move constructor is disabled + } + --- + ) + + $(P If a `union U` has fields that define a move constructor, whenever an object of type `U` + is initialized by move, an error will be issued. The same rule applies to overlapped fields + (anonymous unions).) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct S + { + this(ref S); + this(S); + } + + union U + { + S s; + } + + void main() + { + U a; + U b = __rvalue(a); // error, could not generate move constructor for U + } + --- + ) + +$(H3 $(LNAME2 move-constructor-attributes, Move Constructor Attributes)) + + $(P The move constructor can be overloaded with different qualifiers applied + to the parameter (moving from a qualified source) or to the move constructor + itself (moving to a qualified destination): + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct A + { + this(ref return scope A another) { assert(0); } // copy constructor + this(return scope A another) {} // 1 - mutable source, mutable destination + this(return scope immutable A another) {} // 2 - immutable source, mutable destination + this(return scope A another) immutable {} // 3 - mutable source, immutable destination + this(return scope immutable A another) immutable {} // 4 - immutable source, immutable destination + } + + void main() + { + A a; + immutable A ia; + + A a2 = __rvalue(a); // calls 1 + A a3 = __rvalue(ia); // calls 2 + + A b; + immutable A ib; + + immutable A b4 = __rvalue(b); // calls 3 + immutable A b5 = __rvalue(ib); // calls 4 + } + --- + ) + + $(P The `inout` qualifier may be applied to the move constructor parameter in + order to specify that mutable, `const`, or `immutable` types are treated the same: + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct A + { + this(ref return scope inout A rhs) immutable { assert(0); } + this(return scope inout A rhs) immutable {} + } + + void main() + { + A r1; + const(A) r2; + immutable(A) r3; + + // All call the same move constructor because `inout` acts like a wildcard + immutable(A) a = __rvalue(r1); + immutable(A) b = __rvalue(r2); + immutable(A) c = __rvalue(r3); + } + --- + ) + +$(H3 $(LNAME2 implicit-move-constructors, Implicit Move Constructors)) + + $(P A move constructor is generated implicitly by the compiler for a `struct S` + if all of the following conditions are met:) + + $(OL + $(LI `S` does not explicitly declare any move constructors;) + $(LI `S` defines at least one direct member that has a move constructor, and that + member is not overlapped (by means of `union`) with any other member.) + ) + + $(P If the restrictions above are met, the following move constructor is generated:) + + --- + this(return scope inout(S) src) inout + { + foreach (i, ref inout field; src.tupleof) + this.tupleof[i] = __rvalue(field); + } + --- + + $(P If the generated move constructor fails to type check, it will receive the `@disable` attribute.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + import core.stdc.stdio; + + struct T + { + int i; + inout this(ref inout T t) { this.i = t.i - 1; printf("this(ref T)\n"); } + inout this(inout T t) { this.i = t.i + 1; printf("this(T)\n"); } + } + + struct S + { + T t; + } + + void main() + { + S s; + s.t.i = 3; + S u = s; + printf("u.t.i = %d\n", u.t.i); + assert(u.t.i == 2); + + S v = __rvalue(u); + printf("v.t.i = %d\n", v.t.i); + assert(v.t.i == 3); + } + --- + ) + + +$(H2 $(LEGACY_LNAME2 StructPostblit, struct-postblit, Struct Postblits)) + +$(GRAMMAR +$(GNAME Postblit): + $(D this $(LPAREN) this $(RPAREN)) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK2 function, FunctionBody) + $(D this $(LPAREN) this $(RPAREN)) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK2 function, MissingFunctionBody) +) + + $(PANEL + $(P $(RED Warning:) The plan is for + $(RELATIVE_LINK2 struct-copy-constructor, copy constructors) to replace + $(RELATIVE_LINK2 struct-postblit, postblit constructors), leaving + postblit constructors only in legacy code. However, because the + compiler hooks in druntime which deal with dynamic arrays and + associative arrays have not yet all been updated to support copy + constructors properly + ($(HTTPS github.com/dlang/dmd/issues/20970, issue #20970)), any type + that might be used in a dynamic array or associative array should use a + postblit constructor rather than a copy constructor. The copy + constructor will not be called in all the cases where it should be for + the elements of a dynamic array or the keys or values in an associative + array. Postblit constructors do not have this problem.) + + $(P For backward compatibility reasons, a `struct` that explicitly + defines both a copy constructor and a postblit will only use the + postblit for implicit copying. However, if the postblit is disabled, + the copy constructor will be used. If a struct defines a copy + constructor (user-defined or generated) and has fields that define + postblits, a deprecation will be issued, informing that the postblit + will have priority over the copy constructor.)) + + $(P $(I Copy construction) is defined as initializing + a struct instance from another instance of the same type. + Copy construction is divided into two parts:) + + $(OL + $(LI blitting the fields, i.e. copying the bits) + $(LI running $(I postblit) on the result) + ) + + $(P The first part is done automatically by the language, + the second part is done if a postblit function is defined + for the struct. + The postblit has access only to the destination struct object, + not the source. + Its job is to $(SINGLEQUOTE fix up) the destination as necessary, such as + making copies of referenced data, incrementing reference counts, + etc. For example: + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S + { + int[] a; // array is privately owned by this instance + this(this) + { + a = a.dup; + } + } + --- + ) + + $(P Disabling struct postblit makes the object not copyable. + ) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct T + { + @disable this(this); // disabling makes T not copyable + } + struct S + { + T t; // uncopyable member makes S also not copyable + } + + void main() + { + S s; + S t = s; // error, S is not copyable + } + --- + ) + + $(P Depending on the struct layout, the compiler may generate the following + internal postblit functions:) + + $(OL + $(LI `void __postblit()`. The compiler assigns this name to the explicitly + defined postblit `this(this)` so that it can be treated exactly as + a normal function. Note that if a struct defines a postblit, it cannot + define a function named `__postblit` - no matter the signature - + as this would result in a compilation error due to the name conflict.) + $(LI `void __fieldPostblit()`. If a struct `X` has at least one `struct` + member that in turn defines (explicitly or implicitly) a postblit, then a field + postblit is generated for `X` that calls all the underlying postblits + of the struct fields in declaration order.) + $(LI `void __aggrPostblit()`. If a struct has an explicitly defined postblit + and at least 1 struct member that has a postblit (explicit or implicit) + an aggregated postblit is generated which calls `__fieldPostblit` first + and then `__postblit`.) + $(LI `void __xpostblit()`. The field and aggregated postblits, although + generated for a struct, are not actual struct members. In order to be able + to call them, the compiler internally creates an alias, called `__xpostblit` + which is a member of the struct and which points to the generated postblit that + is the most inclusive.) + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +// struct with alias __xpostblit = __postblit +struct X +{ + this(this) {} +} + +// struct with alias __xpostblit = __fieldPostblit +// which contains a call to X.__xpostblit +struct Y +{ + X a; +} + +// struct with alias __xpostblit = __aggrPostblit which contains +// a call to Y.__xpostblit and a call to Z.__postblit +struct Z +{ + Y a; + this(this) {} +} + +void main() +{ + // X has __postblit and __xpostblit (pointing to __postblit) + static assert(__traits(hasMember, X, "__postblit")); + static assert(__traits(hasMember, X, "__xpostblit")); + + // Y does not have __postblit, but has __xpostblit (pointing to __fieldPostblit) + static assert(!__traits(hasMember, Y, "__postblit")); + static assert(__traits(hasMember, Y, "__xpostblit")); + // __fieldPostblit is not a member of the struct + static assert(!__traits(hasMember, Y, "__fieldPostblit")); + + // Z has __postblit and __xpostblit (pointing to __aggrPostblit) + static assert(__traits(hasMember, Z, "__postblit")); + static assert(__traits(hasMember, Z, "__xpostblit")); + // __aggrPostblit is not a member of the struct + static assert(!__traits(hasMember, Z, "__aggrPostblit")); +} +--- +) + + $(P Neither of the above postblits is defined for structs that don't + define `this(this)` and don't have fields that transitively define it. + If a struct does not define a postblit (implicit or explicit) but + defines functions that use the same name/signature as the internally + generated postblits, the compiler is able to identify that the functions + are not actual postblits and does not insert calls to them when the + struct is copied. Example:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct X +{} + +int a; + +struct Y +{ + int a; + X b; + void __fieldPostPostblit() + { + a = 42; + } +} + +void main() +{ + static assert(!__traits(hasMember, X, "__postblit")); + static assert(!__traits(hasMember, X, "__xpostblit")); + + static assert(!__traits(hasMember, Y, "__postblit")); + static assert(!__traits(hasMember, Y, "__xpostblit")); + + Y y; + auto y2 = y; + assert(a == 0); // __fieldPostBlit does not get called +} +--- +) + + $(P Postblits cannot be overloaded. If two or more postblits are defined, + even if the signatures differ, the compiler assigns the + `__postblit` name to both and later issues a conflicting function + name error:) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +struct X +{ + this(this) {} + this(this) const {} // error: function X.__postblit conflicts with function X.__postblit +} +--- +) + + $(P The following describes the behavior of the + qualified postblit definitions:) + + $(OL + $(LI `const`. When a postblit is qualified with `const` as in + $(D this(this) const;) or $(D const this(this);) then the postblit + is successfully called on mutable (unqualified), `const`, + and `immutable` objects, but the postblit cannot modify the object + because it regards it as `const`; hence `const` postblits are of + limited usefulness. Example:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct S +{ + int n; + this(this) const + { + import std.stdio : writeln; + writeln("postblit called"); + //++n; // error: cannot modify this.n in `const` function + } +} + +void main() +{ + S s1; + auto s2 = s1; + const S s3; + auto s4 = s3; + immutable S s5; + auto s6 = s5; +} +--- +) + $(LI `immutable`. When a postblit is qualified with `immutable` + as in $(D this(this) immutable) or $(D immutable this(this)) + the code is ill-formed. The `immutable` postblit passes the + compilation phase but cannot be invoked. Example:) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +struct Y +{ + // not invoked anywhere, no error is issued + this(this) immutable + { } +} + +struct S +{ + this(this) immutable + { } +} + +void main() +{ + S s1; + auto s2 = s1; // error: immutable method `__postblit` is not callable using a mutable object + const S s3; + auto s4 = s3; // error: immutable method `__postblit` is not callable using a mutable object + immutable S s5; + auto s6 = s5; // error: immutable method `__postblit` is not callable using a mutable object +} +--- +) + + $(LI `shared`. When a postblit is qualified with `shared` as in + $(D this(this) shared) or $(D shared this(this)) solely `shared` + objects may invoke the postblit; attempts of postbliting unshared + objects will result in compile time errors:) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +struct S +{ + this(this) shared + { } +} + +void main() +{ + S s1; + auto s2 = s1; // error: shared method `__postblit` is not callable using a non-shared object + const S s3; + auto s4 = s3; // error: shared method `__postblit` is not callable using a non-shared object + immutable S s5; + auto s6 = s5; // error: shared method `__postblit` is not callable using a non-shared object + + // calling the shared postblit on a shared object is accepted + shared S s7; + auto s8 = s7; +} +--- +) + ) + + $(P An unqualified postblit will get called even if the + struct is instantiated as `immutable` or `const`, but + the compiler issues an error if the struct is instantiated + as `shared`:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct S +{ + int n; + this(this) { ++n; } +} + +void main() +{ + immutable S a; // shared S a; => error : non-shared method is not callable using a shared object + auto a2 = a; + import std.stdio: writeln; + writeln(a2.n); // prints 1 +} +--- +) + + $(P From a postblit perspective, qualifiying the struct definition + yields the same result as explicitly qualifying the postblit.) + + $(P The following table lists all the possibilities of grouping + qualifiers for a postblit associated with the type of object that + needs to be used in order to successfully invoke the postblit:) + + $(TABLE_10 $(ARGS Qualifier Groups), + $(VERTROW object type to be invoked on, $(D const), $(D immutable), $(D shared)), + $(TROW any object type, $(YES), $(NO), $(NO) ) + $(TROW uncallable, $(NO), $(YES), $(NO) ) + $(TROW shared object, $(NO), $(NO), $(YES)) + $(TROW uncallable, $(YES), $(YES), $(NO) ) + $(TROW shared object, $(YES), $(NO), $(YES)) + $(TROW uncallable, $(NO), $(YES), $(YES)) + $(TROW uncallable, $(YES), $(YES), $(YES)) + ) + + $(P Note that when `const` and `immutable` are used to explicitly + qualify a postblit as in `this(this) const immutable;` or + `const immutable this(this);` - the order in which the qualifiers + are declared does not matter - the compiler generates a conflicting + attribute error, however declaring the struct as `const`/`immutable` + and the postblit as `immutable`/`const` achieves the effect of applying + both qualifiers to the postblit. In both cases the postblit is + qualified with the more restrictive qualifier, which is `immutable`. + ) + + $(P The postblits `__fieldPostblit` and `__aggrPostblit` + are generated without any implicit qualifiers and are not considered + struct members. This leads to the situation where qualifying an + entire struct declaration with `const` or `immutable` does not have + any impact on the above-mentioned postblits. However, since `__xpostblit` + is a member of the struct and an alias of one of the other postblits, + the qualifiers applied to the struct will affect the aliased postblit.) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +struct S +{ + this(this) + { } +} + +// `__xpostblit` aliases the aggregated postblit so the `const` applies to it. +// However, the aggregated postblit calls the field postblit which does not have +// any qualifier applied, resulting in a qualifier mismatch error +const struct B +{ + S a; // error : mutable method B.__fieldPostblit is not callable using a const object + this(this) + { } +} + +// `__xpostblit` aliases the field postblit; no error +const struct B2 +{ + S a; +} + +// Similar to B +immutable struct C +{ + S a; // error : mutable method C.__fieldPostblit is not callable using a immutable object + this(this) + { } +} + +// Similar to B2, compiles +immutable struct C2 +{ + S a; +} +--- +) + + $(P In the above situations the errors do not contain line numbers because + the errors are regarding generated code. + ) + + $(P Qualifying an entire struct as `shared` correctly propagates the attribute + to the generated postblits:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +shared struct A +{ + this(this) + { + import std.stdio : writeln; + writeln("the shared postblit was called"); + } +} + +struct B +{ + A a; +} + +void main() +{ + shared B b1; + auto b2 = b1; +} +--- +) + + $(P Unions may have fields that have postblits. However, a union itself never has + a postblit. Copying a union does not result in postblit calls for any fields. + If those calls are desired, they must be inserted explicitly by the programmer:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct S +{ + int count; + this(this) + { + ++count; + } +} + +union U +{ + S s; +} + +void main() +{ + U a = U.init; + U b = a; + assert(b.s.count == 0); + b.s.__postblit; + assert(b.s.count == 1); +} +--- +) + + +$(H2 $(LNAME2 member-functions, Member Functions (a.k.a. Methods))) + + $(P A struct/union can have non-static member functions, + $(DDSUBLINK spec/class, member-functions, like classes). + Such functions (called instance methods) have a hidden + $(DDSUBLINK spec/expression, this, `this` parameter) which is a reference + to the struct instance. + However, an instance method can still be called on an rvalue struct instance, + even if the method is not const:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct S +{ + int i; + int f() => ++i; +} + +void main() +{ + //S().i++; // cannot modify, `S().i` is not an lvalue + assert(S().f() == 1); // OK +} +--- +) + + $(RATIONALE An instance method may have other side effects besides mutating a field, + or it may produce a useful return value. In the general case, throwing + away changes to a field after the method returns does not necessarily indicate + a logic error.) + + +$(H2 $(LEGACY_LNAME2 StructDestructor, struct-destructor, Struct Destructors)) + + $(P Destructors are called implicitly when an object goes out of scope, or + $(RELATIVE_LINK2 assign-overload, before an assignment) (by default). + Their purpose is to free up resources owned by the struct + object. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + int i; + + ~this() + { + import std.stdio; + writeln("S(", i, ") is being destructed"); + } +} + +void main() +{ + auto s1 = S(1); + { + auto s2 = S(2); + // s2 destructor called + } + S(3); // s3 destructor called + // s1 destructor called +} +--- +) + $(P If the struct has a field of another struct type which itself has a destructor, + that destructor will be called at the end of the parent destructor. If there is no + parent destructor, the compiler will generate one. Similarly, a + static array of a struct type with a destructor will have the destructor + called for each element when the array goes out of scope.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + char c; + + ~this() + { + import std.stdio; + writeln("S(", c, ") is being destructed"); + } +} + +struct Q +{ + S a; + S b; +} + +void main() +{ + Q q = Q(S('a'), S('b')); + S[2] arr = [S('0'), S('1')]; + // destructor called for arr[1], arr[0], q.b, q.a +} +--- +) + + $(P A destructor for a struct instance can also be called early using + $(REF1 destroy, object). Note that the destructor will still + be called again when the instance goes out of scope.) + + $(P Struct destructors are used for $(DDSUBLINK spec/glossary, raii, RAII).) + + +$(H2 $(LNAME2 union-field-destruction, Union Field Destruction)) + + $(P Unions may have fields that have destructors. However, a union itself never has + a destructor. When a union goes out of scope, destructors for its fields *are not called*. + If those calls are desired, they must be inserted explicitly by the programmer:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + ~this() + { + import std.stdio; + writeln("S is being destructed"); + } +} + +union U +{ + S s; +} + +void main() +{ + import std.stdio; + { + writeln("entering first scope"); + U u = U.init; + scope (exit) writeln("exiting first scope"); + } + { + writeln("entering second scope"); + U u = U.init; + scope (exit) + { + writeln("exiting second scope"); + destroy(u.s); + } + } +} +--- +) + +$(H2 $(LNAME2 Invariant, Struct Invariants)) + +$(GRAMMAR +$(GNAME Invariant): + $(D invariant $(LPAREN) $(RPAREN)) $(GLINK2 statement, BlockStatement) + $(D invariant) $(GLINK2 statement, BlockStatement) + $(D invariant $(LPAREN)) $(GLINK2 expression, AssertArguments) $(D $(RPAREN) ;) +) + + $(P Struct $(I Invariant)s specify the relationships among the members of a struct instance. + Those relationships must hold for any interactions with the instance from its + public interface. + ) + + $(P The invariant is in the form of a $(D const) member function. The invariant is defined + to $(I hold) if all the $(GLINK2 expression, AssertExpression)s within the invariant that are executed + succeed. + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct Date + { + this(int d, int h) + { + day = d; // days are 1..31 + hour = h; // hours are 0..23 + } + + invariant + { + assert(1 <= day && day <= 31); + assert(0 <= hour && hour < 24); + } + + private: + int day; + int hour; + } + --- + ) + + $(P There may be multiple invariants in a struct. They are applied in lexical order.) + + $(P Struct $(I Invariant)s must hold at the exit of the struct constructor (if any), + and at the entry of the struct destructor (if any).) + + $(P Struct $(I Invariant)s must hold + at the entry and exit of all public or exported non-static member functions. + The order of application of invariants is: + ) + $(OL + $(LI preconditions) + $(LI invariant) + $(LI function body) + $(LI invariant) + $(LI postconditions) + ) + + $(P The invariant need not hold if the struct instance is implicitly constructed using + the default $(D .init) value.) + + $(P If the invariant does not hold, then the program enters an invalid state.) + + $(IMPLEMENTATION_DEFINED + $(OL + $(LI Whether the struct $(I Invariant) is executed at runtime or not. This is typically + controlled with a compiler switch.) + $(LI The behavior when the invariant does not hold is typically the same as + for when $(GLINK2 expression, AssertExpression)s fail.) + ) + ) + + $(UNDEFINED_BEHAVIOR happens if the invariant does not hold and execution continues.) + + $(P Public or exported non-static member functions cannot be called from within an invariant.) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + struct Foo + { + public void f() { } + private void g() { } + + invariant + { + f(); // error, cannot call public member function from invariant + g(); // ok, g() is not public + } + } + --- + ) + + $(BEST_PRACTICE + $(OL + $(LI Do not indirectly call exported or public member functions within a struct invariant, + as this can result in infinite recursion.) + $(LI Avoid reliance on side effects in the invariant. as the invariant may or may not + be executed.) + $(LI Avoid having mutable public fields of structs with invariants, + as then the invariant cannot verify the public interface.) + ) + ) + + + +$(H2 $(LEGACY_LNAME2 AssignOverload, assign-overload, Identity Assignment Overload)) + + $(P While copy construction takes care of initializing + an object from another object of the same type, + assignment is defined as copying the contents of a source + object over those of a destination object, calling the + destination object's destructor if it has one in the process: + ) + + --- + struct S { ... } // S has postblit or destructor + S s; // default construction of s + S t = s; // t is copy-constructed from s + t = s; // t is assigned from s + --- + + $(P Struct assignment $(CODE t=s) is defined to be semantically + equivalent to: + ) + + --- + t.opAssign(s); + --- + + $(P where $(CODE opAssign) is a member function of S:) + + --- + ref S opAssign(ref S s) + { + S tmp = this; // bitcopy this into tmp + this = s; // bitcopy s into this + tmp.__dtor(); // call destructor on tmp + return this; + } + --- + + $(P An identity assignment overload is required for a struct if one or more of + these conditions hold:) + + $(UL + $(LI it has a $(RELATIVE_LINK2 struct-destructor, destructor)) + $(LI it has a $(RELATIVE_LINK2 struct-postblit, postblit)) + $(LI it has a field with an identity assignment overload) + ) + + $(P If an identity assignment overload is required and does not + exist, an identity assignment overload function of the type + $(CODE ref S opAssign(ref S)) will be automatically generated.) + + $(P A user-defined one can implement the equivalent semantics, but can + be more efficient. + ) + + $(P One reason a custom $(CODE opAssign) might be more efficient + is if the struct has a reference to a local buffer: + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S + { + int[] buf; + int a; + + ref S opAssign(ref const S s) return + { + a = s.a; + return this; + } + + this(this) + { + buf = buf.dup; + } + } + --- + ) + + $(P Here, $(CODE S) has a temporary workspace $(CODE buf[]). + The normal postblit + will pointlessly free and reallocate it. The custom $(CODE opAssign) + will reuse the existing storage. + ) + +$(H2 $(LEGACY_LNAME2 AliasThis, alias-this, Alias This)) + +$(GRAMMAR +$(GNAME AliasThis): + $(D alias) $(GLINK_LEX Identifier) $(D this ;) + $(D alias) $(D this) $(D =) $(GLINK_LEX Identifier) $(D ;) +) + + $(P An $(I AliasThis) declaration names a member to subtype. + The $(I Identifier) names that member. + ) + + $(P A struct or union instance can be implicitly converted to the $(I AliasThis) + member. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + int x; + alias x this; +} + +int foo(int i) { return i * 2; } + +void main() +{ + S s; + s.x = 7; + int i = -s; + assert(i == -7); + i = s + 8; + assert(i == 15); + i = s + s; + assert(i == 14); + i = 9 + s; + assert(i == 16); + i = foo(s); // implicit conversion to int + assert(i == 14); +} +--- +) + + $(P If the member is a class or struct, undefined lookups will + be forwarded to the $(I AliasThis) member. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +class Foo +{ + int baz = 4; + int get() { return 7; } +} + +struct Bar +{ + Foo foo; + alias foo this; +} + +void main() +{ + Bar bar = Bar(new Foo()); + int i = bar.baz; + assert(i == 4); + i = bar.get(); + assert(i == 7); +} +--- +) + + $(P If the $(I Identifier) refers to a property member + function with no parameters then conversions and undefined + lookups are forwarded to the return value of the function. + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + int x; + @property int get() + { + return x * 2; + } + alias get this; +} + +void main() +{ + S s; + s.x = 2; + int i = s; + assert(i == 4); +} +--- +) + + $(P If a struct declaration defines an + $(DDSUBLINK spec/operatoroverloading, compare, `opCmp`) or + $(DDSUBLINK spec/operatoroverloading, equals, `opEquals`) + method, it will take precedence to that of the *AliasThis* member. Note + that, unlike an $(D opCmp) method, an $(D opEquals) method is implicitly + defined for a $(D struct) declaration if a user-defined one isn't provided. + This means that if the *AliasThis* member's $(D opEquals) should be used, it + must be explicitly defined: + ) +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct S +{ + int a; + bool opEquals(S rhs) const + { + return this.a == rhs.a; + } +} + +struct T +{ + int b; + S s; + alias s this; +} + +void main() +{ + S s1, s2; + T t1, t2; + + assert(s1 == s2); // calls S.opEquals + assert(t1 == t2); // calls compiler generated T.opEquals that implements member-wise equality + + assert(s1 == t1); // calls s1.opEquals(t1.s); + assert(t1 == s1); // calls t1.s.opEquals(s1); +} +--- +) +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +struct U +{ + int a; + bool opCmp(U rhs) const + { + return this.a < rhs.a; + } +} + +struct V +{ + int b; + U u; + alias u this; +} + +void main() +{ + U u1, u2; + V v1, v2; + + assert(!(u1 < u2)); // calls U.opCmp + assert(!(v1 < v2)); // calls U.opCmp because V does not define an opCmp method + // so the alias this of v1 is employed; U.opCmp expects a + // paramter of type U, so alias this of v2 is used + + assert(!(u1 < v1)); // calls u1.opCmp(v1.u); + assert(!(v1 < u1)); // calls v1.u.opCmp(v1); +} +--- +) + $(P $(GLINK2 attribute, Attribute)s are ignored for $(D AliasThis). + ) + + $(P A struct/union may only have a single $(I AliasThis) member.) + + + +$(H2 $(LNAME2 nested, Nested Structs)) + + $(P A struct is a $(I nested struct) if) + + $(OL + $(LI it is declared inside the scope of a function, or) + $(LI it is a templated struct with one or more template arguments + that alias local functions.) + ) + + $(P A nested struct can have member functions. + It has access to the context of its enclosing scope + via a hidden field.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + void foo() + { + int i = 7; + struct SS + { + int x,y; + int bar() { return x + i + 1; } + } + SS s; + s.x = 3; + s.bar(); // returns 11 + } + --- + ) + + $(P The `static` attribute will prevent a struct from being nested. As such, + the struct will not have access to its enclosing scope.) + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + void foo() + { + int i = 7; + static struct SS + { + int x, y; + int bar() + { + return i; // error, SS is not a nested struct + } + } + } + --- + ) + + $(P $(B Warning): For nested structs, $(DDSUBLINK spec/property, init-vs-construction, + `.init` is not the same as default construction).) + + +$(H2 $(LNAME2 unions_and_special_memb_funct, Unions and Special Member Functions)) + + $(P Unions may not have postblits, destructors, or invariants.) + +$(SPEC_SUBNAV_PREV_NEXT hash-map, Associative Arrays, class, Classes) +) + +Macros: + CHAPTER=15 + TITLE=Structs, Unions + UNCHECK= + CHECK=$(CHECKMARK) + _= diff --git a/spec/template-mixin.dd b/spec/template-mixin.dd new file mode 100644 index 0000000000..1dc3ad620b --- /dev/null +++ b/spec/template-mixin.dd @@ -0,0 +1,420 @@ +Ddoc + +$(SPEC_S Template Mixins, + +$(HEADERNAV_TOC) + + $(P A $(I TemplateMixin) takes an arbitrary set of declarations from + the body of a $(GLINK2 template, TemplateDeclaration) and inserts them + into the current context.) + +$(GRAMMAR +$(GNAME TemplateMixinDeclaration): + $(D mixin) $(D template) $(GLINK_LEX Identifier) $(GLINK2 template, TemplateParameters) $(GLINK2 template, Constraint)$(OPT) $(D {) $(GLINK2 module, DeclDefs)$(OPT) $(D }) + +$(GNAME TemplateMixin): + $(D mixin) $(GLINK MixinTemplateName) $(GLINK2 template, TemplateArguments)$(OPT) $(GLINK_LEX Identifier)$(OPT) $(D ;) + $(D mixin) $(GLINK_LEX Identifier) `=` $(GLINK MixinTemplateName) $(GLINK2 template, TemplateArguments)$(OPT) $(D ;) + +$(GNAME MixinTemplateName): + $(D .) $(GLINK MixinQualifiedIdentifier) + $(GLINK MixinQualifiedIdentifier) + $(GLINK2 type, Typeof) $(D .) $(GLINK MixinQualifiedIdentifier) + +$(GNAME MixinQualifiedIdentifier): + $(GLINK_LEX Identifier) + $(GLINK_LEX Identifier) $(D .) $(GSELF MixinQualifiedIdentifier) + $(GLINK2 template, TemplateInstance) $(D .) $(GSELF MixinQualifiedIdentifier) +) + + $(P A $(I TemplateMixin) can occur in declaration lists of modules, + classes, structs, unions, or as a statement. + $(I MixinTemplateName) must refer to a $(I TemplateDeclaration) or + $(I TemplateMixinDeclaration). + If the $(I TemplateDeclaration) requires no parameters, $(I TemplateArguments) + can be omitted. + ) + + $(P Unlike a $(DDSUBLINK spec/template, instantiation_scope, template instantiation), + a template mixin's body is evaluated + within the scope where the mixin appears, not where the template declaration + is defined. It is analogous to cutting and pasting the body of + the template into the location of the mixin into a $(LINK2 #mixin_scope, nested scope). It is useful for injecting + parameterized $(SINGLEQUOTE boilerplate) code, as well as for creating + templated nested functions, which is not always possible with + template instantiations. + ) + + $(P A $(I TemplateMixinDeclaration) is the same as a $(I TemplateDeclaration), + but can not be instantiated outside of a $(I TemplateMixin). + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------ +int y = 3; + +mixin template Foo() +{ + int abc() { return y; } +} + +void test() +{ + int y = 8; + mixin Foo; // local y is picked up, not global y + assert(abc() == 8); +} +------ +) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------ +import std.stdio : writeln; + +mixin template Foo() +{ + int x = 5; +} + +mixin Foo; + +struct Bar +{ + mixin Foo; +} + +void main() +{ + writeln("x = ", x); // prints 5 + { + Bar b; + int x = 3; + + writeln("b.x = ", b.x); // prints 5 + writeln("x = ", x); // prints 3 + { + mixin Foo; + writeln("x = ", x); // prints 5 + x = 4; + writeln("x = ", x); // prints 4 + } + writeln("x = ", x); // prints 3 + } + writeln("x = ", x); // prints 5 +} +------ +) + +$(H2 $(LNAME2 parameters, Mixin Parameters)) + + $(P Mixins can be + $(DDSUBLINK spec/template, parameters, parameterized):) + +------ +mixin template Foo(T) +{ + T x = 5; +} + +mixin Foo!(int); // create x of type int +------ + + $(P Mixins can parameterize symbols using + $(DDSUBLINK spec/template, aliasparameters, alias parameters):) + +------ +mixin template Foo(alias b) +{ + int abc() { return b; } +} + +void test() +{ + int y = 8; + mixin Foo!(y); + assert(abc() == 8); +} +------ + +$(H3 $(LNAME2 example, Example)) + + $(P This example uses a mixin to implement a generic Duff's device + for an arbitrary statement (in this case, the arbitrary statement + is in bold). A nested function is generated as well as a + delegate literal, these can be inlined by the compiler:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------ +import std.stdio : writeln; + +mixin template duffs_device(alias low, alias high, alias fun) +{ + void duff_loop() + { + if (low < high) + { + auto n = (high - low + 7) / 8; + switch ((high - low) % 8) + { + case 0: do { fun(); goto case; + case 7: fun(); goto case; + case 6: fun(); goto case; + case 5: fun(); goto case; + case 4: fun(); goto case; + case 3: fun(); goto case; + case 2: fun(); goto case; + case 1: fun(); continue; + default: assert(0, "Impossible"); + } while (--n > 0); + } + } + } +} + +void main() +{ + int i = 1; + int j = 11; + + mixin duffs_device!(i, j, delegate { writeln("foo"); }); + duff_loop(); // executes foo() 10 times +} +------ +) + +$(H2 $(LNAME2 mixin_scope, Mixin Scope)) + + $(P The declarations in a mixin are placed in a nested scope and then + $(SINGLEQUOTE imported) into the surrounding + scope. If the name of a declaration in a mixin is the same + as a declaration in the surrounding scope, the surrounding declaration + overrides the mixin one:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------ +import std.stdio : writeln; + +int x = 3; + +mixin template Foo() +{ + int x = 5; + int y = 5; +} + +mixin Foo; +int y = 3; + +void main() +{ + writeln("x = ", x); // prints 3 + writeln("y = ", y); // prints 3 +} +------ +) + + $(P A mixin has its own scope, even if a declaration is overridden + by the enclosing one:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------ +import std.stdio : writeln; + +int x = 4; + +mixin template Foo() +{ + int x = 5; + int bar() { return x; } +} + +mixin Foo; + +void main() +{ + writeln("x = ", x); // prints 4 + writeln("bar() = ", bar()); // prints 5 +} +------ +) + + $(P If two different mixins are put in the same scope, and each + define a declaration with the same name, there is an ambiguity + error when the declaration is referenced:) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +------ +import std.stdio : writeln; + +mixin template Foo() +{ + int x = 5; + void func(int x) { } +} + +mixin template Bar() +{ + int x = 4; + void func(long x) { } +} + +mixin Foo; +mixin Bar; + +void main() +{ + writeln("x = ", x); // error, x is ambiguous + func(1); // error, func is ambiguous +} +------ +) + $(P The call to $(D func()) is ambiguous because + `Foo.func` and `Bar.func` are in different scopes. + ) + +$(H3 $(LNAME2 resolving_ambiguities, Resolving Ambiguities)) + + $(P If a mixin has an $(I Identifier), it can be used to + disambiguate between conflicting symbols: + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------ +import std.stdio : writeln; + +int x = 6; + +mixin template Foo() +{ + int x = 5; + int y = 7; + void func() { } +} + +mixin template Bar() +{ + int x = 4; + void func() { } +} + +mixin Foo F; +mixin Bar B; + +void main() +{ + writeln("y = ", y); // prints 7 + writeln("x = ", x); // prints 6 + writeln("F.x = ", F.x); // prints 5 + writeln("B.x = ", B.x); // prints 4 + F.func(); // calls Foo.func + B.func(); // calls Bar.func +} +------ +) + $(P Alias declarations can be used to form an + $(DDSUBLINK spec/function, overload-sets, overload set) of + functions declared in different mixins:) + +----- +mixin template Foo() +{ + void func(int x) { } +} + +mixin template Bar() +{ + void func(long x) { } +} + +mixin Foo!() F; +mixin Bar!() B; + +alias func = F.func; +alias func = B.func; + +void main() +{ + func(1); // calls B.func + func(1L); // calls F.func +} +----- + +$(H2 $(LNAME2 aggregate_types, Aggregate Type Mixins)) + +$(H3 $(LNAME2 virtual_functions, Mixin Virtual Functions)) + + $(P Mixins can add virtual functions to a class:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------ +import std.stdio : writeln; + +mixin template Foo() +{ + void func() { writeln("Foo.func()"); } +} + +class Bar +{ + mixin Foo; +} + +class Code : Bar +{ + override void func() { writeln("Code.func()"); } +} + +void main() +{ + Bar b = new Bar(); + b.func(); // calls Foo.func() + + b = new Code(); + b.func(); // calls Code.func() +} +------ +) + +$(H3 $(LNAME2 destructors, Mixin Destructors)) + + $(P An aggregate type can mixin additional destructors. + Destructors are run in the opposite order to declaration order.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +import std.stdio; + +mixin template addNewDtor() +{ + ~this() + { + writeln("Mixin dtor"); + } +} + +struct S +{ + ~this() + { + writeln("Struct dtor"); + } + + mixin addNewDtor; +} + +void main() +{ + S s; + // prints `Mixin dtor` + // prints `Struct dtor` +} +--- +) + +$(SPEC_SUBNAV_PREV_NEXT template, Templates, contracts, Contract Programming) +) + +Macros: + CHAPTER=23 + TITLE=Template Mixins + _= diff --git a/spec/template.dd b/spec/template.dd new file mode 100644 index 0000000000..bc33728b80 --- /dev/null +++ b/spec/template.dd @@ -0,0 +1,1926 @@ +Ddoc + +$(SPEC_S Templates, + +$(HEADERNAV_TOC) + +$(H2 $(LNAME2 declarations, Template Declarations)) + + $(P Templates are D's approach to generic programming. + Templates can be defined with a $(I TemplateDeclaration): + ) + +$(GRAMMAR +$(GNAME TemplateDeclaration): + $(D template) $(GLINK_LEX Identifier) $(GLINK TemplateParameters) $(GLINK Constraint)$(OPT) $(D {) $(GLINK2 module, DeclDefs)$(OPT) $(D }) + +$(GNAME TemplateParameters): + $(D $(LPAREN)) $(GLINK TemplateParameterList)$(OPT) $(D $(RPAREN)) + +$(GNAME TemplateParameterList): + $(GLINK TemplateParameter) + $(GLINK TemplateParameter) $(D ,) + $(GLINK TemplateParameter) $(D ,) $(GSELF TemplateParameterList) +) + + $(P The *DeclDefs* body of the template must be syntactically correct + even if never instantiated. Semantic analysis is not done until + instantiation. A template forms its own scope, and the template + body can contain declarations such as classes, structs, types, + enums, variables, functions, and other templates. + ) + + $(P $(RELATIVE_LINK2 parameters, Template parameters) can take types, + values, symbols, or sequences.) + + --- + template t(T) // declare type parameter T + { + T v; // declare a member variable of type T within template t + } + --- + + $(P A template parameter can have a *specialization* which + constrains an argument the $(I TemplateParameter) can + accept.) + + --- + template t(T : int) // type T must implicitly convert to int + { + ... + } + --- + + $(P If multiple templates with the same $(I Identifier) are + declared, they are distinct if they have different parameters + or are differently specialized. + ) + + $(P If a template has a member which has the same identifier as the + template, the template is an + $(RELATIVE_LINK2 implicit_template_properties, Eponymous Template). + `template` declarations with one eponymous member are usually + written as specific $(RELATIVE_LINK2 aggregate_templates, short syntax) + template declarations instead.) + + +$(H2 $(LNAME2 template_instantiation, Template Instantiation)) + + $(P A template must be instantiated before use. This means + passing an argument list to the template. + Those arguments are typically then substituted + into the template body, which becomes a new scoped entity.) + + $(P $(RELATIVE_LINK2 function-templates, Function templates) can + be implicitly instantiated if the compiler can infer the template + arguments from a function call. Otherwise the template must be + instantiated explicitly.) + +$(H3 $(LNAME2 explicit_tmp_instantiation, Explicit Template Instantiation)) + + $(P Templates are explicitly instantiated using a `!` after the + template name, then either an argument list or a single token + argument.) + +$(GRAMMAR +$(GNAME TemplateInstance): + $(GLINK_LEX Identifier) $(GLINK TemplateArguments) + +$(GNAME TemplateArguments): + $(D ! $(LPAREN)) $(GLINK TemplateArgumentList)$(OPT) $(D $(RPAREN)) + $(D !) $(GLINK TemplateSingleArgument) + +$(GNAME TemplateArgumentList): + $(GLINK TemplateArgument) + $(GLINK TemplateArgument) $(D ,) + $(GLINK TemplateArgument) $(D ,) $(GSELF TemplateArgumentList) + +$(GNAME TemplateSingleArgument): + $(GLINK_LEX Identifier) + $(GLINK2 type, FundamentalType) + $(GLINK_LEX CharacterLiteral) + $(GLINK_LEX StringLiteral) + $(GLINK2 istring, InterpolationExpressionSequence) + $(GLINK_LEX IntegerLiteral) + $(GLINK_LEX FloatLiteral) + $(D true) + $(D false) + $(D null) + $(D this) + $(GLINK2 expression, SpecialKeyword) +) + + $(P A template argument can be a type, compile-time expression + or a symbol.) + +$(GRAMMAR +$(GNAME TemplateArgument): + $(GLINK2 type, Type) + $(ASSIGNEXPRESSION) + $(GLINK Symbol) + +$(GNAME Symbol): + $(GLINK SymbolTail) + $(D .) $(GLINK SymbolTail) + +$(GNAME SymbolTail): + $(GLINK_LEX Identifier) + $(GLINK_LEX Identifier) $(D .) $(GSELF SymbolTail) + $(GLINK TemplateInstance) + $(GLINK TemplateInstance) $(D .) $(GSELF SymbolTail) +) + + $(P Once instantiated, the declarations inside the template, called + the template members, are in the scope + of the $(I TemplateInstance):) + + ------ + template TFoo(T) { alias Ptr = T*; } + ... + TFoo!(int).Ptr x; // declare x to be of type int* + ------ + + $(P If the $(GLINK TemplateArgument) is one token long, the parentheses can be omitted:) + + --- + TFoo!int.Ptr x; // same as TFoo!(int).Ptr x; + --- + + $(P A template instantiation can be aliased:) + + ------ + template TFoo(T) { alias Ptr = T*; } + alias foo = TFoo!(int); + foo.Ptr x; // declare x to be of type int* + ------ + +$(H3 $(LNAME2 common_instantiation, Common Instantiation)) + + $(P Multiple instantiations of a $(I TemplateDeclaration) with the same + $(I TemplateArgumentList) will all refer to the same instantiation. + For example:) + + ------ + template TFoo(T) { T f; } + alias a = TFoo!(int); + alias b = TFoo!(int); + ... + a.f = 3; + assert(b.f == 3); // a and b refer to the same instance of TFoo + ------ + + $(P This is true even if the $(I TemplateInstance)s are done in + different modules. + ) + + $(P Even if template arguments are implicitly converted to the same + template parameter type, they still refer to the same instance. + This example uses a $(GLINK TemplateValueParameter) and a + $(RELATIVE_LINK2 aggregate_templates, `struct` template):) + + ----- + struct TFoo(int x) { } + + // Different template parameters create different struct types + static assert(!is(TFoo!(3) == TFoo!(2))); + // 3 and 2+1 are both 3 of type int - same TFoo instance + static assert(is(TFoo!(3) == TFoo!(2 + 1))); + + // 3u is implicitly converted to 3 to match int parameter, + // and refers to exactly the same instance as TFoo!(3) + static assert(is(TFoo!(3) == TFoo!(3u))); + ----- + + $(H3 $(LNAME2 copy_example, Practical Example)) + + $(P A simple generic copy template would be:) + + ------ + template TCopy(T) + { + void copy(out T to, T from) + { + to = from; + } + } + ------ + + $(P To use this template, it must first be instantiated with a specific + type:) + + ------ + int i; + TCopy!(int).copy(i, 3); + ------ + $(P See also $(RELATIVE_LINK2 function-templates, function templates).) + +$(H3 $(LNAME2 instantiation_scope, Instantiation Scope)) + + $(P $(I TemplateInstance)s are always instantiated in the scope of where + the $(I TemplateDeclaration) is declared, with the addition of the + template parameters being declared as aliases for their deduced types. + ) + $(P $(B Example:)) + + $(U module a:) + ------ + template TFoo(T) { void bar() { func(); } } + ------ + + $(U module b:) + ------ + import a; + + void func() { } + alias f = TFoo!(int); // error: func not defined in module a + ------ + + $(P $(B Example:)) + + $(U module a:) + ------ + template TFoo(T) { void bar() { func(1); } } + void func(double d) { } + ------ + + $(U module b:) + ------ + import a; + + void func(int i) { } + alias f = TFoo!(int); + ... + f.bar(); // will call a.func(double) + ------ + + $(P $(I TemplateParameter) specializations and default + arguments are evaluated in the scope of the $(I TemplateDeclaration). + ) + + +$(H2 $(LNAME2 parameters, Template Parameters)) + +$(GRAMMAR +$(GNAME TemplateParameter): + $(GLINK TemplateTypeParameter) + $(GLINK TemplateValueParameter) + $(GLINK TemplateAliasParameter) + $(GLINK TemplateSequenceParameter) + $(GLINK TemplateThisParameter) +) + + $(P Template parameters can take types, values, symbols, or sequences.) + + $(UL + $(LI Type parameters can take any type.) + $(LI Value parameters can take any expression which can be statically + evaluated at compile time.) + $(LI Alias parameters can take almost any symbol.) + $(LI Sequence parameters can take zero or more types, values or symbols.) + ) + + $(P $(RELATIVE_LINK2 template_parameter_def_values, A default argument) + specifies the type, value or symbol to use for the + $(I TemplateParameter) when a matching argument is not supplied. + ) + +$(H3 $(LNAME2 template_type_parameters, Type Parameters)) + +$(GRAMMAR +$(GNAME TemplateTypeParameter): + $(GLINK_LEX Identifier) $(GLINK TemplateTypeParameterSpecialization)$(OPT) $(GLINK TemplateTypeParameterDefault)$(OPT) + +$(GNAME TemplateTypeParameterSpecialization): + $(D :) $(GLINK2 type, Type) + +$(GNAME TemplateTypeParameterDefault): + $(D =) $(GLINK2 type, Type) +) + +$(H4 $(LNAME2 parameters_specialization, Specialization and Pattern Matching)) + + $(P Templates may be specialized for particular types of arguments + by following the template parameter identifier with a `:` and the + pattern for the specialized type. + For example:) + + ------ + template TFoo(T) { ... } // #1 + template TFoo(T : T[]) { ... } // #2 + template TFoo(T : char) { ... } // #3 + template TFoo(T, U, V) { ... } // #4 + + alias foo1 = TFoo!(int); // instantiates #1 + alias foo2 = TFoo!(double[]); // instantiates #2 matching pattern T[] with T being double + alias foo3 = TFoo!(char); // instantiates #3 + alias fooe = TFoo!(char, int); // error, number of arguments mismatch + alias foo4 = TFoo!(char, int, int); // instantiates #4 + ------ + + $(P The template picked to instantiate is the one that is most specialized + that fits the types of the $(I TemplateArgumentList). + If the result is ambiguous, it is an error. + ) + +$(H4 $(LNAME2 argument_deduction, Type Parameter Deduction)) + + $(P The types of template parameters are deduced for a particular + template instantiation by comparing the template argument with + the corresponding template parameter. + ) + + $(P For each template parameter, the following rules are applied in + order until a type is deduced for each parameter: + ) + + $(OL + $(LI If there is no type specialization for the parameter, + the type of the parameter is set to the template argument.) + + $(LI If the type specialization is dependent on a type parameter, + the type of that parameter is set to be the corresponding part + of the type argument.) + + $(LI If after all the type arguments are examined, there are any + type parameters left with no type assigned, they are assigned + types corresponding to the template argument in the same position + in the $(I TemplateArgumentList).) + + $(LI If applying the above rules does not result in exactly one + type for each template parameter, then it is an error.) + ) + + $(P For example:) + + ------ + template TFoo(T) { } + alias foo1 = TFoo!(int); // (1) T is deduced to be int + alias foo2 = TFoo!(char*); // (1) T is deduced to be char* + + template TBar(T : T*) { } // match template argument against T* pattern + alias bar = TBar!(char*); // (2) T is deduced to be char + + template TAbc(D, U : D[]) { } // D[] is pattern to be matched + alias abc1 = TAbc!(int, int[]); // (2) D is deduced to be int, U is int[] + alias abc2 = TAbc!(char, int[]); // (4) error, D is both char and int + + template TDef(D : E*, E) { } // E* is pattern to be matched + alias def = TDef!(int*, int); // (1) E is int + // (3) D is int* + ------ + + $(P Deduction from a specialization can provide values + for more than one parameter:) + + --- + template Foo(T: T[U], U) + { + ... + } + + Foo!(int[long]) // instantiates Foo with T set to int, U set to long + --- + + $(P When considering matches, a class is + considered to be a match for any super classes or interfaces:) + + ------ + class A { } + class B : A { } + + template TFoo(T : A) { } + alias foo = TFoo!(B); // (3) T is B + + template TBar(T : U*, U : A) { } + alias bar = TBar!(B*, B); // (2) T is B* + // (3) U is B + ------ + + +$(H3 $(LNAME2 template_this_parameter, This Parameters)) + +$(GRAMMAR +$(GNAME TemplateThisParameter): + $(D this) $(GLINK TemplateTypeParameter) +) + + $(P $(I TemplateThisParameter)s are used in member function templates + to pick up the type of the $(I this) reference. It also will + infer the mutability of the `this` reference. For example, if + `this` is `const`, then the function is marked `const`.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S + { + void foo(this T)() const + { + pragma(msg, T); + } + } + + void main() + { + const(S) s; + (&s).foo(); + S s2; + s2.foo(); + immutable(S) s3; + s3.foo(); + } + --- + ) + + Prints: + +$(CONSOLE +const(S) +S +immutable(S) +) + +$(H4 $(LNAME2 this_rtti, Avoiding Runtime Type Checks)) + + $(P *TemplateThisParameter* is especially useful when used with inheritance. For example, + consider the implementation of a final base method which returns a derived + class type. Typically this would return a base type, but that would prohibit + calling or accessing derived properties of the type:) + + --- + interface Addable(T) + { + final auto add(T t) + { + return this; + } + } + + class List(T) : Addable!T + { + List remove(T t) + { + return this; + } + } + + void main() + { + auto list = new List!int; + list.add(1).remove(1); // error: no 'remove' method for Addable!int + } + --- + + $(P Here the method $(D add) returns the base type, which doesn't implement the + $(D remove) method. The template `this` parameter can be used for this purpose:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + interface Addable(T) + { + final R add(this R)(T t) + { + return cast(R)this; // cast is necessary, but safe + } + } + + class List(T) : Addable!T + { + List remove(T t) + { + return this; + } + } + + void main() + { + auto list = new List!int; + static assert(is(typeof(list.add(1)) == List!int)); + list.add(1).remove(1); // ok, List.add + + Addable!int a = list; + // a.add calls Addable.add + static assert(is(typeof(a.add(1)) == Addable!int)); + } + --- + ) + +$(H3 $(LNAME2 template_value_parameter, Value Parameters)) + +$(GRAMMAR +$(GNAME TemplateValueParameter): + $(GLINK2 type, BasicType) $(GLINK2 declaration, Declarator) $(GLINK TemplateValueParameterSpecialization)$(OPT) $(GLINK TemplateValueParameterDefault)$(OPT) + +$(GNAME TemplateValueParameterSpecialization): + $(D :) $(GLINK2 expression, ConditionalExpression) + +$(GNAME TemplateValueParameterDefault): + $(D =) $(ASSIGNEXPRESSION) + $(D =) $(GLINK2 expression, SpecialKeyword) +) + + $(P A template value parameter can take an argument of any expression which can + be statically evaluated at compile time as one of the following:) + + * A `bool`, character, integer, floating point or string value + * `null` + * An array literal whose elements could be valid template value arguments + * An associative array literal whose keys and values could each be valid + template value arguments + * A struct literal whose arguments could be valid template value arguments + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ----- + template foo(string s) + { + enum string bar = s ~ " betty"; + } + + void main() + { + import std.stdio; + writeln(foo!("hello").bar); // prints: hello betty + } + ----- + ) + +$(H4 $(LNAME2 value_specialization, Specialization)) + + $(P Any specialization or default expression provided must be evaluatable + at compile-time.) + + $(P In this example, template `foo` has a value parameter that + is specialized for `10`:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------ + template foo(U : int, int v : 10) + { + U x = v; + } + + void main() + { + assert(foo!(int, 10).x == 10); + static assert(!__traits(compiles, foo!(int, 11))); + } + ------ + ) + + $(P This can be useful when a different template body is required for a specific value. + Another template overload would be defined to take other integer literal values.) + +$(H3 $(LNAME2 aliasparameters, Alias Parameters)) + +$(GRAMMAR +$(GNAME TemplateAliasParameter): + $(D alias) $(GLINK_LEX Identifier) $(GLINK TemplateAliasParameterSpecialization)$(OPT) $(GLINK TemplateAliasParameterDefault)$(OPT) + $(D alias) $(GLINK2 type, BasicType) $(GLINK2 declaration, Declarator) $(GLINK TemplateAliasParameterSpecialization)$(OPT) $(GLINK TemplateAliasParameterDefault)$(OPT) + +$(GNAME TemplateAliasParameterSpecialization): + $(D :) $(GLINK2 type, Type) + $(D :) $(GLINK2 expression, ConditionalExpression) + +$(GNAME TemplateAliasParameterDefault): + $(D =) $(GLINK2 type, Type) + $(D =) $(GLINK2 expression, ConditionalExpression) +) + + $(P Alias parameters enable templates to be parameterized with + symbol names or values computed at compile-time. + Almost any kind of D symbol can be used, including type names, + global names, local names, module names, template names, and + template instances. + ) + +$(H4 $(LNAME2 alias_symbol, Symbol Aliases)) + + $(UL + $(LI Type names + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------ + class Foo + { + static int x; + } + + template Bar(alias a) + { + alias sym = a.x; + } + + void main() + { + alias bar = Bar!(Foo); + bar.sym = 3; // sets Foo.x to 3 + assert(Foo.x == 3); + } + ------ + ) + ) + + $(LI Global names + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------ + shared int x; + + template Foo(alias var) + { + auto ptr = &var; + } + + void main() + { + alias bar = Foo!(x); + *bar.ptr = 3; // set x to 3 + assert(x == 3); + + static shared int y; + alias abc = Foo!(y); + *abc.ptr = 3; // set y to 3 + assert(y == 3); + } + ------ + ) + ) + + $(LI Local names + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + template Foo(alias var) + { + void inc() { var++; } + } + + void main() + { + int v = 4; + alias foo = Foo!v; + foo.inc(); + assert(v == 5); + } + --- + ) + See also $(RELATIVE_LINK2 implicit-nesting, Implicit Template Nesting). + ) + + $(LI Module names + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------ + import std.conv; + + template Foo(alias a) + { + alias sym = a.text; + } + + void main() + { + alias bar = Foo!(std.conv); + string s = bar.sym(3); // calls std.conv.text(3) + assert(s == "3"); + } + ------ + ) + ) + + $(LI Template names + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------ + shared int x; + + template Foo(alias var) + { + auto ptr = &var; + } + + template Bar(alias Tem) + { + alias instance = Tem!(x); + } + + void main() + { + alias bar = Bar!(Foo); + *bar.instance.ptr = 3; // sets x to 3 + assert(x == 3); + } + ------ + ) + ) + + $(LI Template instance names + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------ + shared int x; + + template Foo(alias var) + { + auto ptr = &var; + } + + template Bar(alias sym) + { + alias p = sym.ptr; + } + + void main() + { + alias foo = Foo!(x); + alias bar = Bar!(foo); + *bar.p = 3; // sets x to 3 + assert(x == 3); + } + ------ + ) + ) + ) + +$(H4 $(LNAME2 alias_value, Value Aliases)) + + $(UL + + $(LI Literals + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------ + template Foo(alias x, alias y) + { + static int i = x; + static string s = y; + } + + void main() + { + import std.stdio; + alias foo = Foo!(3, "bar"); + writeln(foo.i, foo.s); // prints 3bar + } + ------ + )) + + $(LI Compile-time values + $(SPEC_RUNNABLE_EXAMPLE_RUN + ------ + template Foo(alias x) + { + static int i = x; + } + + void main() + { + // compile-time argument evaluation + enum two = 1 + 1; + alias foo = Foo!(5 * two); + assert(foo.i == 10); + static assert(foo.stringof == "Foo!10"); + + // compile-time function evaluation + int get10() { return 10; } + alias bar = Foo!(get10()); + // bar is the same template instance as foo + assert(&bar.i is &foo.i); + } + ------ + )) + + $(LI Function Literals + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------ + template Foo(alias fun) + { + enum val = fun(2); + } + + alias foo = Foo!((int x) => x * x); + static assert(foo.val == 4); + ------ + )) + ) + +$(H4 $(LNAME2 typed_alias_op, Typed Alias Parameters)) + + $(P Alias parameters can also be typed. + These parameters will accept symbols of that type:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------ + template Foo(alias int p) { alias a = p; } + + void fun() + { + int i = 0; + Foo!i.a++; // ok + assert(i == 1); + + float f; + //Foo!f; // fails to instantiate + } + ------ + ) + +$(H4 $(LNAME2 alias_parameter_specialization, Specialization)) + + $(P Alias parameters can accept both literals and user-defined type symbols, + but they are less specialized than the matches to type parameters and + value parameters:) + + ------ + template Foo(T) { ... } // #1 + template Foo(int n) { ... } // #2 + template Foo(alias sym) { ... } // #3 + + struct S {} + int var; + + alias foo1 = Foo!(S); // instantiates #1 + alias foo2 = Foo!(1); // instantiates #2 + alias foo3a = Foo!([1,2]); // instantiates #3 + alias foo3b = Foo!(var); // instantiates #3 + ------ + + ------ + template Bar(alias A) { ... } // #4 + template Bar(T : U!V, alias U, V...) { ... } // #5 + + class C(T) {} + alias bar = Bar!(C!int); // instantiates #5 + ------ + +$(H3 $(LNAME2 variadic-templates, Sequence Parameters)) + +$(GRAMMAR +$(GNAME TemplateSequenceParameter): + $(GLINK_LEX Identifier) $(D ...) +) + + $(P If the last template parameter in the $(I TemplateParameterList) + is declared as a $(I TemplateSequenceParameter), + it is a match with zero or more trailing template arguments. + Any argument that can be passed to a $(GLINK TemplateAliasParameter) + can be passed to a sequence parameter. + ) + $(P Such a sequence of arguments can itself be aliased for use outside + a template. The $(REF AliasSeq, std,meta) template simply + aliases its sequence parameter:) + --- + alias AliasSeq(Args...) = Args; + --- + $(P A *TemplateSequenceParameter* will thus henceforth + be referred to by that name for clarity. + An $(I AliasSeq) is not itself a type, value, or symbol. It is a + $(DDLINK articles/ctarguments, Compile-time Sequences, compile-time sequence) + of any mix of types, values or symbols, or none. + ) + + $(P The elements of an $(I AliasSeq) are automatically expanded + when it is referenced in a declaration or expression. + An $(I AliasSeq) can be + $(DDSUBLINK articles/ctarguments, auto-expansion, used as arguments) + to instantiate a template. + ) + +$(H4 $(LNAME2 homogeneous_sequences, Homogeneous Sequences)) + + $(UL + $(LI An $(I AliasSeq) whose elements consist entirely of types is + called a type sequence or $(I TypeSeq).) + $(LI An $(I AliasSeq) whose elements consist entirely of values is + called a value sequence or $(I ValueSeq).) + $(LI `typeof` can be used on a *ValueSeq* to obtain a *TypeSeq*.) + ) + + $(P A *ValueSeq* can be used as arguments to call a + function:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + import std.stdio : writeln; + + template print(args...) // args must be a ValueSeq + { + void print() + { + writeln("args are ", args); + } + } + + void main() + { + print!(1, 'a', 6.8)(); // prints: args are 1a6.8 + } + --- + ) + + $(P A *TypeSeq* can be used to declare a parameter sequence for a function:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + import std.stdio : writeln; + + template print(Types...) // Types must be a TypeSeq + { + void print(Types args) // args is a ValueSeq + { + writeln("args are ", args); + } + } + + void main() + { + print!(int, char, double)(1, 'a', 6.8); // prints: args are 1a6.8 + } + --- + ) + + $(P A value sequence:) + * Can be copied + * Cannot have its address taken + * Cannot be returned from a function - instead, return a + $(REF Tuple, std,typecons) + +$(H4 $(LNAME2 lvalue-sequences, Lvalue Sequences)) + + $(P A *TypeSeq* can similarly be used to + $(DDSUBLINK articles/ctarguments, type-seq-instantiation, declare variables). + A variable whose type is a *TypeSeq* is called an + *lvalue sequence*.) + + - An element of an lvalue sequence may be modifiable. + - An lvalue sequence can be initialized from, assigned to, and compared with + a value sequence whose elements are compatible.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + import std.meta: AliasSeq; + // use a type alias just for convenience + alias TS = AliasSeq!(string, int); + + TS tup; // lvalue sequence + assert(tup == AliasSeq!("", 0)); // TS.init + // elements can be modified + tup[1]++; + assert(tup[1] == 1); + + byte i = 5; + // initialize another lvalue sequence from a sequence of a value and a symbol + auto tup2 = AliasSeq!("hi", i); // value of i is copied + i++; + assert(tup2[1] == 5); // unchanged + + enum hi5 = AliasSeq!("hi", 5); // rvalue sequence + static assert(is(typeof(hi5) == TS)); + // compare elements + assert(tup2 == hi5); // OK, byte and int have a common type + + // lvalue sequence can be assigned to a ValueSeq + tup = tup2; + assert(tup == hi5); + --- + ) + + $(UL + $(LI `.tupleof` can be $(DDSUBLINK spec/class, tupleof, used on a class) + or struct instance to obtain an lvalue sequence of its fields.) + $(LI `.tupleof` can be $(DDSUBLINK spec/arrays, array-properties, used on a static array) + instance to obtain an lvalue sequence of its elements.) + ) + + $(P An lvalue sequence can be initialized from a single expression. + Each element is initialized from the given expression.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + import std.meta: AliasSeq; + AliasSeq!(int, int, int) vs = 4; + assert(vs == AliasSeq!(4, 4, 4)); + + int[3] sa = [1, 2, 3]; + vs = sa.tupleof; + assert(vs == AliasSeq!(1, 2, 3)); + --- + ) + +$(H4 $(LNAME2 seq-ops, Sequence Operations)) + + $(UL + $(LI The number of elements in an $(I AliasSeq) can be retrieved with + the $(D .length) property.) + $(LI The $(I n)th element can be retrieved by + $(DDSUBLINK spec/expression, index_operations, indexing) an + $(I AliasSeq) with `Seq[n]`. Indexes must be known at compile-time. + The result is an lvalue when the element is a symbol which resolves to a variable, + or when the sequence is an lvalue sequence.) + $(LI $(DDSUBLINK spec/expression, slice_operations, Slicing) + produces a new sequence with a subset of the elements of the original sequence.) + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + import std.meta : AliasSeq; + + int v = 4; + // alias a sequence of 3 values and one symbol + alias nums = AliasSeq!(1, 2, 3, v); + static assert(nums.length == 4); + static assert(nums[1] == 2); + + //nums[0]++; // Error, nums[0] is an rvalue + nums[3]++; // OK, nums[3] is bound to v, an lvalue + assert(v == 5); + + // slice first 3 elements + alias trio = nums[0 .. $-1]; + // expand into an array literal + static assert([trio] == [1, 2, 3]); + --- + ) + + $(P $(I AliasSeq)s are static compile-time entities, there is no way + to dynamically change, add, or remove elements either at compile-time or run-time. + Instead, either:) + $(UL + $(LI Construct a new sequence using the original sequence (or a slice of it) and additional elements before or after it.) + $(LI Use $(DDSUBLINK spec/declaration, AliasAssign, Alias Assignment) + to build new sequences iteratively.) + ) + $(P Sequences can 'unroll' code for each element using a + $(DDSUBLINK spec/statement, foreach_over_tuples, `foreach` statement).) + +$(H4 $(LNAME2 typeseq_deduction, Type Sequence Deduction)) + + $(P Type sequences can be deduced from the trailing parameters + of an $(RELATIVE_LINK2 ifti, implicitly instantiated) function template:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + import std.stdio; + + template print(T, Args...) + { + void print(T first, Args args) + { + writeln(first); + static if (args.length) // if more arguments + print(args); // recurse for remaining arguments + } + } + + void main() + { + // Calls `print` with: + // T = int, Args = (char, double) + // T = char, Args = (double) + // T = double, Args = () + print(1, 'a', 6.8); + } + --- + ) + + prints: + +$(CONSOLE +1 +a +6.8 +) + + $(P Type sequences can also be deduced from the parameter list of a + $(DDSUBLINK spec/function, function-pointers-delegates, function pointer or delegate) passed as a function argument:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + size_t arity(R, Args...)(R function(Args) fp) => Args.length; + + int f(int); + void g(string, Object); + + static assert(arity((){}) == 0); // R = void, Args = () + static assert(arity(&f) == 1); // R = int, Args = (int) + static assert(arity(&g) == 2); // R = void, Args = (string, Object) + --- + ) + $(P Deduction can partially match a parameter list:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ---- + /* Partially applies a delegate by tying its first argument to a particular value. + * R = return type + * T = first argument type + * Args = TypeSeq of remaining argument types + */ + R delegate(Args) partial(R, T, Args...)(R function(T, Args) dg, T first) + { + // return a closure + return (Args args) => dg(first, args); + } + + int plus(int x, int y, int z) => x + y + z; + + void main() + { + auto plus_two = partial(&plus, 2); // R = int, T = int, Args = (int, int) + assert(plus_two(6, 8) == 16); + } + ---- + ) + $(P See also: $(REF partial, std,functional).) + +$(H4 $(LNAME2 variadic_template_specialization, Specialization)) + + $(P If both a template with a sequence parameter and a template + without a sequence parameter exactly match a template instantiation, + the template without a $(I TemplateSequenceParameter) is selected.) + + ---- + template Foo(T) { pragma(msg, "1"); } // #1 + template Foo(int n) { pragma(msg, "2"); } // #2 + template Foo(alias sym) { pragma(msg, "3"); } // #3 + template Foo(Args...) { pragma(msg, "4"); } // #4 + + import std.stdio; + + // Any sole template argument will never match to #4 + alias foo1 = Foo!(int); // instantiates #1 + alias foo2 = Foo!(3); // instantiates #2 + alias foo3 = Foo!(std); // instantiates #3 + + alias foo4 = Foo!(int, 3, std); // instantiates #4 + ---- + +$(H3 $(LNAME2 template_parameter_def_values, Default Arguments)) + + $(P Trailing template parameters can be given default arguments:) + + ------ + template Foo(T, U = int) { ... } + Foo!(uint,long); // instantiate Foo with T as uint, and U as long + Foo!(uint); // instantiate Foo with T as uint, and U as int + + template Foo(T, U = T*) { ... } + Foo!(uint); // instantiate Foo with T as uint, and U as uint* + ------ + + $(P See also: $(RELATIVE_LINK2 function-default, Function Template Default Arguments).) + +$(H2 $(LNAME2 implicit_template_properties, Eponymous Templates)) + + $(P If a template contains members whose name is the same as the + template identifier then these members are assumed to be referred + to in a template instantiation:) + + ------ + template foo(T) + { + T foo; // declare variable foo of type T + } + + void main() + { + foo!(int) = 6; // instead of foo!(int).foo + } + ------ + + $(P The following example has more than one eponymous member and uses + $(RELATIVE_LINK2 ifti, Implicit Function Template Instantiation):) + + ------ + template foo(S, T) + { + // each member contains all the template parameters + void foo(S s, T t) {} + void foo(S s, T t, string) {} + } + + void main() + { + foo(1, 2, "test"); // foo!(int, int).foo(1, 2, "test") + foo(1, 2); // foo!(int, int).foo(1, 2) + } + ------ + +$(H2 $(LNAME2 aggregate_templates, Aggregate Type Templates)) + +$(GRAMMAR +$(GNAME ClassTemplateDeclaration): + $(D class) $(GLINK_LEX Identifier) $(GLINK TemplateParameters) $(D ;) + $(D class) $(GLINK_LEX Identifier) $(GLINK TemplateParameters) $(GLINK Constraint)$(OPT) $(GLINK2 class, BaseClassList)$(OPT) $(GLINK2 struct, AggregateBody) + $(D class) $(GLINK_LEX Identifier) $(GLINK TemplateParameters) $(GLINK2 class, BaseClassList)$(OPT) $(GLINK Constraint)$(OPT) $(GLINK2 struct, AggregateBody) + +$(GNAME InterfaceTemplateDeclaration): + $(D interface) $(GLINK_LEX Identifier) $(GLINK TemplateParameters) $(D ;) + $(D interface) $(GLINK_LEX Identifier) $(GLINK TemplateParameters) $(GLINK Constraint)$(OPT) $(GLINK2 interface, BaseInterfaceList)$(OPT) $(GLINK2 struct, AggregateBody) + $(D interface) $(GLINK_LEX Identifier) $(GLINK TemplateParameters) $(GLINK2 interface, BaseInterfaceList) $(GLINK Constraint) $(GLINK2 struct, AggregateBody) + +$(GNAME StructTemplateDeclaration): + $(D struct) $(GLINK_LEX Identifier) $(GLINK TemplateParameters) $(D ;) + $(D struct) $(GLINK_LEX Identifier) $(GLINK TemplateParameters) $(GLINK Constraint)$(OPT) $(GLINK2 struct, AggregateBody) + +$(GNAME UnionTemplateDeclaration): + $(D union) $(GLINK_LEX Identifier) $(GLINK TemplateParameters) $(D ;) + $(D union) $(GLINK_LEX Identifier) $(GLINK TemplateParameters) $(GLINK Constraint)$(OPT) $(GLINK2 struct, AggregateBody) +) + + $(P If a template declares exactly one member, and that member is a class + with the same name as the template (see + $(RELATIVE_LINK2 implicit_template_properties, Eponymous Templates):)) + + ------ + template $(CODE_HIGHLIGHT Bar)(T) + { + class $(CODE_HIGHLIGHT Bar) + { + T member; + } + } + ------ + + then the semantic equivalent, called a $(I ClassTemplateDeclaration) + can be written as: + + ------ + class Bar(T) + { + T member; + } + ------ + + $(P See also: $(RELATIVE_LINK2 template_this_parameter, This Parameters). + ) + + $(P Analogously to class templates, struct, union and interfaces + can be transformed into templates by supplying a template parameter list. + ) + +$(H2 $(LNAME2 function-templates, Function Templates)) + + $(P If a template declares exactly one member, and that member is a function + with the same name as the template, it is a function template declaration. + Alternatively, a function template declaration is a function declaration + with a $(GLINK TemplateParameterList) immediately preceding the + $(GLINK2 function, Parameters). + ) + + $(P A function template to compute the square of type $(I T) is:) + + ------ + T $(CODE_HIGHLIGHT square)(T)(T t) + { + return t * t; + } + ------ + + $(P It is lowered to:) + + ------ + template $(CODE_HIGHLIGHT square)(T) + { + T $(CODE_HIGHLIGHT square)(T t) + { + return t * t; + } + } + ------ + + $(P Function templates can be explicitly instantiated with + *Identifier*`!(`*TemplateArgumentList*`)`:) + + ---- + writefln("The square of %s is %s", 3, square!(int)(3)); + ---- + +$(H3 $(LNAME2 ifti, Implicit Function Template Instantiation (IFTI))) + + $(P Function templates can be $(I implicitly) instantiated if the + $(I TemplateArgumentList) is deducible from the types of the + function arguments:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ---- + T square(T)(T t) + { + return t * t; + } + + writefln("The square of %s is %s", 3, square(3)); // T is deduced to be int + ---- + ) + + $(P Type parameter deduction is not influenced by the order of function + arguments. + ) + + $(P If there are fewer arguments supplied in the $(I TemplateArgumentList) + than parameters in the $(I TemplateParameterList), the arguments fill + parameters from left to right, and the rest of the parameters are then deduced + from the function arguments. + ) + +$(H4 $(LNAME2 ifti-restrictions, Restrictions)) + + $(P Function template type parameters that are to be implicitly + deduced must appear in the type of at least one function parameter:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------ + void foo(T : U*, U)(U t) {} + + void main() + { + int x; + foo!(int*)(x); // ok, U is deduced and T is specified explicitly + //foo(x); // error, only U can be deduced, not T + } + ------ + ) + + $(P When the template parameters must be deduced, the + $(RELATIVE_LINK2 implicit_template_properties, eponymous members) + can't rely on a $(LINK2 version.html#StaticIfCondition, `static if`) + condition since the deduction relies on how the members are used:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------ + template foo(T) + { + static if (is(T)) // T is not yet known... + void foo(T t) {} // T is deduced from the member usage + } + + void main() + { + //foo(0); // Error: cannot deduce function from argument types + foo!int(0); // Ok since no deduction necessary + } + ------ + ) + + $(P IFTI does not work when the parameter type is an + $(RELATIVE_LINK2 alias-template, alias template) instance: + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S(T) {} + alias A(T) = S!T; + void f(T)(A!T) {} + + void main() + { + A!int v; + //f(v); // error + f!int(v); // OK + } + --- + ) + + $(P A *TypeSeq* template parameter $(RELATIVE_LINK2 typeseq_deduction, can be deduced) + from function arguments.) + +$(H4 $(LNAME2 ifti-conversions, Type Conversions)) + + $(P If template type parameters match the literal expressions on function arguments, + the deduced types may consider narrowing conversions of them. + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------ + void foo(T)(T v) { pragma(msg, "in foo, T = ", T); } + void bar(T)(T v, T[] a) { pragma(msg, "in bar, T = ", T); } + + void main() + { + foo(1); + // an integer literal type is analyzed as int by default + // then T is deduced to int + + short[] arr; + bar(1, arr); + // arr is short[], and the integer literal 1 is + // implicitly convertible to short. + // then T will be deduced to short. + + bar(1, [2.0, 3.0]); + // the array literal is analyzed as double[], + // and the integer literal 1 is implicitly convertible to double. + // then T will be deduced to double. + } + ------ + ) + + $(P The deduced type parameter for dynamic array and pointer arguments + has an unqualified head:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------ + void foo(T)(T arg) { pragma(msg, T); } + + void test() + { + int[] marr; + const(int[]) carr; + immutable(int[]) iarr; + foo(marr); // T == int[] + foo(carr); // T == const(int)[] + foo(iarr); // T == immutable(int)[] + + int* mptr; + const(int*) cptr; + immutable(int*) iptr; + foo(mptr); // T == int* + foo(cptr); // T == const(int)* + foo(iptr); // T == immutable(int)* + } + ------ + ) + +$(H3 $(LNAME2 return-deduction, Return Type Deduction)) + + $(P Function templates can have their return types deduced based on the + $(GLINK2 statement, ReturnStatement)s in the function, just as with + normal functions. + See $(DDSUBLINK spec/function, auto-functions, Auto Functions). + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + auto square(T)(T t) + { + return t * t; + } + + auto i = square(2); + static assert(is(typeof(i) == int)); + --- + ) + +$(H3 $(LNAME2 auto-ref-parameters, Auto Ref Parameters)) + + $(P Template functions can have auto ref parameters. + An auto ref parameter becomes a ref parameter + if its corresponding argument is an lvalue, otherwise it becomes + a value parameter:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + int countRefs(Args...)(auto ref Args args) + { + int result; + + foreach (i, _; args) + { + if (__traits(isRef, args[i])) + result++; + } + return result; + } + + void main() + { + int y; + assert(countRefs(3, 4) == 0); + assert(countRefs(3, y, 4) == 1); + assert(countRefs(y, 6, y) == 2); + } + --- + ) + + $(P Auto ref parameters can be combined with auto ref return + attributes:) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + auto ref min(T, U)(auto ref T lhs, auto ref U rhs) + { + return lhs > rhs ? rhs : lhs; + } + + void main() + { + int i; + i = min(4, 3); + assert(i == 3); + + int x = 7, y = 8; + i = min(x, y); + assert(i == 7); + // result is an lvalue + min(x, y) = 10; // sets x to 10 + assert(x == 10 && y == 8); + + static assert(!__traits(compiles, min(3, y) = 10)); + static assert(!__traits(compiles, min(y, 3) = 10)); + } + --- + ) + +$(H3 $(LNAME2 function-default, Default Arguments)) + + $(P Template arguments not implicitly deduced can have default values:) + + ------ + void $(CODE_HIGHLIGHT foo)(T, U=T*)(T t) { U p; ... } + + int x; + foo(x); // T is int, U is int* + ------ + + $(P Variadic Function Templates can have parameters with default values. + These parameters are always set to their default value in case of IFTI. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + size_t fun(T...)(T t, string file = __FILE__) + { + import std.stdio; + writeln(file, " ", t); + return T.length; + } + + assert(fun(1, "foo") == 2); // uses IFTI + assert(fun!int(1, "filename") == 1); // no IFTI + --- + ) + +$(H2 $(LNAME2 template_ctors, Template Constructors)) + +$(GRAMMAR +$(GNAME ConstructorTemplate): + $(D this) $(GLINK TemplateParameters) $(GLINK2 function, Parameters) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK Constraint)$(OPT) $(GLINK2 function, FunctionBody) + $(D this) $(GLINK TemplateParameters) $(GLINK2 function, Parameters) $(GLINK2 function, MemberFunctionAttributes)$(OPT) $(GLINK Constraint)$(OPT) $(GLINK2 function, MissingFunctionBody) +) + + $(P Templates can be used to form constructors for classes and structs. + ) + +$(H2 $(LNAME2 variable-template, Enum & Variable Templates)) + + $(P Like aggregates and functions, $(DDSUBLINK spec/declaration, variable-declarations, variable + declarations) and manifest constants can have template parameters, providing there is + an $(GLINK2 declaration, Initializer):) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------ + enum bool within(alias v, T) = v <= T.max && v >= T.min; + ubyte[T.sizeof] storage(T) = 0; + const triplet(alias v) = [v, v+1, v+2]; + + static assert(within!(-128F, byte)); + static assert(storage!(int[2]).length == 8); + static assert(triplet!3 == [3, 4, 5]); + ------ + ) + + $(P Those declarations are transformed into these *TemplateDeclaration*s:) + + ------ + template within(alias v, T) + { + enum bool within = v <= T.max && v >= T.min; + } + template storage(T) + { + ubyte[T.sizeof] storage = 0; + } + template triplet(alias v) + { + const triplet = [v, v+1, v+2]; + } + ------ + +$(H2 $(LNAME2 alias-template, Alias Templates)) + + $(P $(GLINK2 declaration, AliasDeclaration) can also have optional template + parameters:) + + ------ + alias ElementType(T : T[]) = T; + alias Sequence(TL...) = TL; + ------ + + It is lowered to: + + ------ + template ElementType(T : T[]) + { + alias ElementType = T; + } + template Sequence(TL...) + { + alias Sequence = TL; + } + ------ + +$(H2 $(LNAME2 nested-templates, Nested Templates)) + + $(P If a template is declared in aggregate or function local scope, the + instantiated functions will implicitly capture the context of the + enclosing scope.) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + ---- + class C + { + int num; + + this(int n) { num = n; } + + template Foo() + { + // 'foo' can access 'this' reference of class C object. + void foo(int n) { this.num = n; } + } + } + + void main() + { + auto c = new C(1); + assert(c.num == 1); + + c.Foo!().foo(5); + assert(c.num == 5); + + template Bar() + { + // 'bar' can access local variable of 'main' function. + void bar(int n) { c.num = n; } + } + Bar!().bar(10); + assert(c.num == 10); + } + ---- + ) + + $(P Above, $(D Foo!().foo) will work just the same as a `final` member function + of class $(D C), and $(D Bar!().bar) will work just the same as a nested + function within function $(D main$(LPAREN)$(RPAREN)).) + +$(H3 $(LNAME2 limitations, Aggregate Type Limitations)) + + $(P A nested template cannot add non-static fields to an aggregate type. + Fields declared in a nested template will be implicitly `static`.) + $(P A nested template cannot add virtual functions to a class or interface. + Methods inside a nested template will be implicitly `final`.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------ + class Foo + { + template TBar(T) + { + T xx; // becomes a static field of Foo + void func(T) {} // implicitly final + //abstract void baz(); // error, final functions cannot be abstract + + static T yy; // Ok + static void func(T t, int y) {} // Ok + } + } + + void main() + { + alias bar = Foo.TBar!int; + bar.xx++; + //bar.func(1); // error, no this + + auto o = new Foo; + o.TBar!int.func(1); // OK + } + ------ + ) + +$(H3 $(LNAME2 implicit-nesting, Implicit Nesting)) + + $(P If a template has a $(RELATIVE_LINK2 aliasparameters, template alias parameter), + and is instantiated with a local symbol, the instantiated function will + implicitly become nested in order to access runtime data of the given + local symbol.) + + ---- + template Foo(alias sym) + { + void foo() { sym = 10; } + } + + class C + { + int num; + + this(int n) { num = n; } + + void main() + { + assert(this.num == 1); + + alias fooX = Foo!(C.num).foo; + + // fooX will become member function implicitly, so &fooX + // returns a delegate object. + static assert(is(typeof(&fooX) == delegate)); + + fooX(); // called by using valid 'this' reference. + assert(this.num == 10); // OK + } + } + + void main() + { + new C(1).main(); + + int num; + alias fooX = Foo!num.foo; + + // fooX will become nested function implicitly, so &fooX + // returns a delegate object. + static assert(is(typeof(&fooX) == delegate)); + + fooX(); + assert(num == 10); // OK + } + ---- + + $(P Not only functions, but also instantiated class and struct types can + become nested via implicitly captured context.) + + ---- + class C + { + int num; + this(int n) { num = n; } + + class N(T) + { + // instantiated class N!T can become nested in C + T foo() { return num * 2; } + } + } + + void main() + { + auto c = new C(10); + auto n = c.new N!int(); + assert(n.foo() == 20); + } + ---- + + $(P See also: $(DDSUBLINK spec/class, nested-explicit, Nested Class Instantiation).) + + ---- + void main() + { + int num = 10; + struct S(T) + { + // instantiated struct S!T can become nested in main() + T foo() { return num * 2; } + } + S!int s; + assert(s.foo() == 20); + } + ---- + + $(P A templated $(D struct) can become a nested $(D struct) if it + is instantiated with a local symbol passed as an aliased argument:) + + --- + struct A(alias F) + { + int fun(int i) { return F(i); } + } + + A!F makeA(alias F)() { return A!F(); } + + void main() + { + int x = 40; + int fun(int i) { return x + i; } + A!fun a = makeA!fun(); + assert(a.fun(2) == 42); + } + --- + + $(H3 $(LNAME2 nested_template_limitation, Context Limitation)) + + $(P Currently nested templates can capture at most one context. As a typical + example, non-static template member functions cannot take local symbol + by using template alias parameter.) + + ---- + class C + { + int num; + void foo(alias sym)() { num = sym * 2; } + } + + void main() + { + auto c = new C(); + int var = 10; + c.foo!var(); // NG, foo!var requires two contexts, 'this' and 'main()' + } + ---- + + $(P But, if one context is indirectly accessible from other context, it is allowed.) + + ---- + int sum(alias x, alias y)() { return x + y; } + + void main() + { + int a = 10; + void nested() + { + int b = 20; + assert(sum!(a, b)() == 30); + } + nested(); + } + ---- + + $(P Two local variables $(D a) and $(D b) are in different contexts, but + outer context is indirectly accessible from innter context, so nested + template instance $(D sum!$(LPAREN)a, b$(RPAREN)) will capture only + inner context.) + +$(H2 $(LNAME2 recursive_templates, Recursive Templates)) + + $(P Template features can be combined to produce some interesting + effects, such as compile time evaluation of non-trivial functions. + For example, a factorial template can be written:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------ + template factorial(int n) + { + static if (n == 1) + enum factorial = 1; + else + enum factorial = n * factorial!(n - 1); + } + + static assert(factorial!(4) == 24); + ------ + ) + $(P For more information and a $(ACRONYM CTFE, Compile-time Function Execution) + factorial alternative, see: + $(DDSUBLINK articles/templates-revisited, template-recursion, Template Recursion). + ) + +$(H2 $(LNAME2 template_constraints, Template Constraints)) + +$(GRAMMAR +$(GNAME Constraint): + $(D if) $(D $(LPAREN)) $(GLINK2 expression, Expression) $(D $(RPAREN)) +) + + $(P $(I Constraint)s are used to impose additional constraints + on matching arguments to a template beyond what is possible + in the $(GLINK TemplateParameterList). + The $(I Expression) is computed at compile time + and returns a result that is converted to a boolean value. + If that value is true, then the template is matched, + otherwise the template is not matched. + ) + + $(P For example, the following function template only + matches with odd values of $(CODE N):) + + --- + void foo(int N)() + if (N & 1) + { + ... + } + ... + foo!(3)(); // OK, matches + foo!(4)(); // Error, no match + --- + + $(P Template constraints can be used with aggregate types (structs, classes, unions). + Constraints are effectively used with library module $(MREF std, traits):) + + --- + import std.traits; + + struct Bar(T) + if (isIntegral!T) + { + ... + } + ... + auto x = Bar!int; // OK, int is an integral type + auto y = Bar!double; // Error, double does not satisfy constraint + --- + +$(SPEC_SUBNAV_PREV_NEXT operatoroverloading, Operator Overloading, template-mixin, Template Mixins) +) + +Macros: + CHAPTER=22 + TITLE=Templates + _= diff --git a/spec/traits.dd b/spec/traits.dd new file mode 100644 index 0000000000..b7c100e6d7 --- /dev/null +++ b/spec/traits.dd @@ -0,0 +1,2124 @@ +Ddoc + +$(SPEC_S Traits, + +$(HEADERNAV_TOC) + +$(H2 $(LNAME2 grammar, Grammar)) + + $(P Traits are extensions to the language to enable + programs, at compile time, to get at information + internal to the compiler. This is also known as + compile time reflection. + It is done as a special, easily extended syntax (similar + to Pragmas) so that new capabilities can be added + as required. + ) + +$(GRAMMAR +$(GNAME TraitsExpression): + $(D __traits) $(D $(LPAREN)) $(GLINK TraitsKeyword) $(D ,) $(GLINK TraitsArguments) $(D $(RPAREN)) + +$(GNAME TraitsKeyword): + $(RELATIVE_LINK2 isAbstractClass, $(D isAbstractClass)) + $(RELATIVE_LINK2 isArithmetic, $(D isArithmetic)) + $(RELATIVE_LINK2 isAssociativeArray, $(D isAssociativeArray)) + $(RELATIVE_LINK2 isFinalClass, $(D isFinalClass)) + $(RELATIVE_LINK2 isPOD, $(D isPOD)) + $(RELATIVE_LINK2 isNested, $(D isNested)) + $(RELATIVE_LINK2 isFuture, $(D isFuture)) + $(RELATIVE_LINK2 isDeprecated, $(D isDeprecated)) + $(RELATIVE_LINK2 isFloating, $(D isFloating)) + $(RELATIVE_LINK2 isIntegral, $(D isIntegral)) + $(RELATIVE_LINK2 isScalar, $(D isScalar)) + $(RELATIVE_LINK2 isStaticArray, $(D isStaticArray)) + $(RELATIVE_LINK2 isUnsigned, $(D isUnsigned)) + $(RELATIVE_LINK2 isDisabled, $(D isDisabled)) + $(RELATIVE_LINK2 isVirtualFunction, $(D isVirtualFunction)) + $(RELATIVE_LINK2 isVirtualMethod, $(D isVirtualMethod)) + $(RELATIVE_LINK2 isAbstractFunction, $(D isAbstractFunction)) + $(RELATIVE_LINK2 isFinalFunction, $(D isFinalFunction)) + $(RELATIVE_LINK2 isStaticFunction, $(D isStaticFunction)) + $(RELATIVE_LINK2 isOverrideFunction, $(D isOverrideFunction)) + $(RELATIVE_LINK2 isTemplate, $(D isTemplate)) + $(RELATIVE_LINK2 isRef, $(D isRef)) + $(RELATIVE_LINK2 isOut, $(D isOut)) + $(RELATIVE_LINK2 isLazy, $(D isLazy)) + $(RELATIVE_LINK2 isReturnOnStack, $(D isReturnOnStack)) + $(RELATIVE_LINK2 isCopyable, $(D isCopyable)) + $(RELATIVE_LINK2 isZeroInit, $(D isZeroInit)) + $(RELATIVE_LINK2 isModule, $(D isModule)) + $(RELATIVE_LINK2 isPackage, $(D isPackage)) + $(RELATIVE_LINK2 isCOMClass, $(D isCOMClass)) + $(RELATIVE_LINK2 hasMember, $(D hasMember)) + $(RELATIVE_LINK2 hasCopyConstructor, $(D hasCopyConstructor)) + $(RELATIVE_LINK2 hasMoveConstructor, $(D hasMoveConstructor)) + $(RELATIVE_LINK2 hasPostblit, $(D hasPostblit)) + $(RELATIVE_LINK2 identifier, $(D identifier)) + $(RELATIVE_LINK2 fullyQualifiedName, $(D fullyQualifiedName)) + $(RELATIVE_LINK2 getAliasThis, $(D getAliasThis)) + $(RELATIVE_LINK2 getAttributes, $(D getAttributes)) + $(RELATIVE_LINK2 getBitfieldOffset, $(D getBitfieldOffset)) + $(RELATIVE_LINK2 getBitfieldWidth, $(D getBitfieldWidth)) + $(RELATIVE_LINK2 getFunctionAttributes, $(D getFunctionAttributes)) + $(RELATIVE_LINK2 getFunctionVariadicStyle, $(D getFunctionVariadicStyle)) + $(RELATIVE_LINK2 getLinkage, $(D getLinkage)) + $(RELATIVE_LINK2 getLocation, $(D getLocation)) + $(RELATIVE_LINK2 getMember, $(D getMember)) + $(RELATIVE_LINK2 getOverloads, $(D getOverloads)) + $(RELATIVE_LINK2 getParameterStorageClasses, $(D getParameterStorageClasses)) + $(RELATIVE_LINK2 getPointerBitmap, $(D getPointerBitmap)) + $(RELATIVE_LINK2 getCppNamespaces, $(D getCppNamespaces)) + $(RELATIVE_LINK2 getVisibility, $(D getVisibility)) + $(RELATIVE_LINK2 getProtection, $(D getProtection)) + $(RELATIVE_LINK2 getTargetInfo, $(D getTargetInfo)) + $(RELATIVE_LINK2 getVirtualFunctions, $(D getVirtualFunctions)) + $(RELATIVE_LINK2 getVirtualMethods, $(D getVirtualMethods)) + $(RELATIVE_LINK2 getUnitTests, $(D getUnitTests)) + $(RELATIVE_LINK2 parent, $(D parent)) + $(RELATIVE_LINK2 child, $(D child)) + $(RELATIVE_LINK2 classInstanceSize, $(D classInstanceSize)) + $(RELATIVE_LINK2 classInstanceAlignment, $(D classInstanceAlignment)) + $(RELATIVE_LINK2 getVirtualIndex, $(D getVirtualIndex)) + $(RELATIVE_LINK2 allMembers, $(D allMembers)) + $(RELATIVE_LINK2 derivedMembers, $(D derivedMembers)) + $(RELATIVE_LINK2 isSame, $(D isSame)) + $(RELATIVE_LINK2 compiles, $(D compiles)) + $(RELATIVE_LINK2 toType, $(D toType)) + $(RELATIVE_LINK2 initSymbol, $(D initSymbol)) + $(RELATIVE_LINK2 parameters, $(D parameters)) + $(RELATIVE_LINK2 fullyQualifiedName, $(D fullyQualifiedName)) + +$(GNAME TraitsArguments): + $(GLINK TraitsArgument) + $(GLINK TraitsArgument) $(D ,) $(GSELF TraitsArguments) + +$(GNAME TraitsArgument): + $(GLINK2 expression, AssignExpression) + $(GLINK2 type, Type) +) + + +$(H2 $(LNAME2 types, Type Traits)) + +$(H3 $(GNAME isArithmetic)) + + $(P If the arguments are all either types that are arithmetic types, + or expressions that are typed as arithmetic types, then $(D true) + is returned. + Otherwise, $(D false) is returned. + If there are no arguments, $(D false) is returned.) + + $(P Arithmetic types are integral types and floating point types.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +void main() +{ + int i; + writeln(__traits(isArithmetic, int)); + writeln(__traits(isArithmetic, i, i+1, int)); + writeln(__traits(isArithmetic)); + writeln(__traits(isArithmetic, int*)); +} +--- +) + + Prints: + +$(CONSOLE +true +true +false +false +) + +$(H3 $(GNAME isFloating)) + + $(P If the arguments are all either types that are floating point types, + or expressions that are typed as floating point types, then $(D true) + is returned. + Otherwise, $(D false) is returned. + If there are no arguments, $(D false) is returned.) + + $(P The floating point types are: + `float`, `double`, `real`, + `ifloat`, `idouble`, `ireal`, + `cfloat`, `cdouble`, `creal`, + vectors of floating point types, and enums with a floating point base type.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import core.simd : float4; + +enum E : float { a, b } + +static assert(__traits(isFloating, float)); +static assert(__traits(isFloating, E)); +static assert(__traits(isFloating, float4)); + +static assert(!__traits(isFloating, float[4])); +--- +) + +$(H3 $(GNAME isIntegral)) + + $(P If the arguments are all either types that are integral types, + or expressions that are typed as integral types, then $(D true) + is returned. + Otherwise, $(D false) is returned. + If there are no arguments, $(D false) is returned.) + + $(P The integral types are: + `byte`, `ubyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `cent`, `ucent`, + `bool`, `char`, `wchar`, `dchar`, + vectors of integral types, and enums with an integral base type.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import core.simd : int4; + +enum E { a, b } + +static assert(__traits(isIntegral, bool)); +static assert(__traits(isIntegral, char)); +static assert(__traits(isIntegral, int)); +static assert(__traits(isIntegral, E)); +static assert(__traits(isIntegral, int4)); + +static assert(!__traits(isIntegral, float)); +static assert(!__traits(isIntegral, int[4])); +static assert(!__traits(isIntegral, void*)); +--- +) + +$(H3 $(GNAME isScalar)) + + $(P If the arguments are all either types that are scalar types, + or expressions that are typed as scalar types, then $(D true) + is returned. + Otherwise, $(D false) is returned. + If there are no arguments, $(D false) is returned.) + + $(P Scalar types are integral types, + floating point types, + pointer types, + vectors of scalar types, + and enums with a scalar base type.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import core.simd : int4, void16; + +enum E { a, b } + +static assert(__traits(isScalar, bool)); +static assert(__traits(isScalar, char)); +static assert(__traits(isScalar, int)); +static assert(__traits(isScalar, float)); +static assert(__traits(isScalar, E)); +static assert(__traits(isScalar, int4)); +static assert(__traits(isScalar, void*)); // Includes pointers! + +static assert(!__traits(isScalar, int[4])); +static assert(!__traits(isScalar, void16)); +static assert(!__traits(isScalar, void)); +static assert(!__traits(isScalar, typeof(null))); +static assert(!__traits(isScalar, Object)); +--- +) + +$(H3 $(GNAME isUnsigned)) + + $(P If the arguments are all either types that are unsigned types, + or expressions that are typed as unsigned types, then $(D true) + is returned. + Otherwise, $(D false) is returned. + If there are no arguments, $(D false) is returned.) + + $(P The unsigned types are: + `ubyte`, `ushort`, `uint`, `ulong`, `ucent`, + `bool`, `char`, `wchar`, `dchar`, + vectors of unsigned types, and enums with an unsigned base type.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import core.simd : uint4; + +enum SignedEnum { a, b } +enum UnsignedEnum : uint { a, b } + +static assert(__traits(isUnsigned, bool)); +static assert(__traits(isUnsigned, char)); +static assert(__traits(isUnsigned, uint)); +static assert(__traits(isUnsigned, UnsignedEnum)); +static assert(__traits(isUnsigned, uint4)); + +static assert(!__traits(isUnsigned, int)); +static assert(!__traits(isUnsigned, float)); +static assert(!__traits(isUnsigned, SignedEnum)); +static assert(!__traits(isUnsigned, uint[4])); +static assert(!__traits(isUnsigned, void*)); +--- +) + +$(H3 $(GNAME isStaticArray)) + + $(P Works like $(D isArithmetic), except it's for static array + types.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import core.simd : int4; + +enum E : int[4] { a = [1, 2, 3, 4] } + +static array = [1, 2, 3]; // Not a static array: the type is inferred as int[] not int[3]. + +static assert(__traits(isStaticArray, void[0])); +static assert(__traits(isStaticArray, E)); +static assert(!__traits(isStaticArray, int4)); +static assert(!__traits(isStaticArray, array)); +--- +) + +$(H3 $(GNAME isAssociativeArray)) + + $(P Works like $(D isArithmetic), except it's for associative array + types.) + +$(H3 $(GNAME isAbstractClass)) + + $(P If the arguments are all either types that are abstract classes, + or expressions that are typed as abstract classes, then $(D true) + is returned. + Otherwise, $(D false) is returned. + If there are no arguments, $(D false) is returned.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +abstract class C { int foo(); } + +void main() +{ + C c; + writeln(__traits(isAbstractClass, C)); + writeln(__traits(isAbstractClass, c, C)); + writeln(__traits(isAbstractClass)); + writeln(__traits(isAbstractClass, int*)); +} +--- +) + + Prints: + +$(CONSOLE +true +true +false +false +) + +$(H3 $(GNAME isFinalClass)) + + $(P Works like $(D isAbstractClass), except it's for final + classes.) + +$(H3 $(GNAME isCopyable)) + +$(P Takes one argument. If that argument is a copyable type then $(D true) is returned, +otherwise $(D false). +) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct S +{ +} +static assert( __traits(isCopyable, S)); + +struct T +{ + @disable this(this); // disable copy construction +} +static assert(!__traits(isCopyable, T)); +--- +) + +$(H3 $(GNAME isPOD)) + + $(P Takes one argument, which must be a type. It returns + $(D true) if the type is a $(DDSUBLINK spec/glossary, pod, POD) type, otherwise $(D false).) + +$(H3 $(GNAME toType)) + + $(P Takes a single argument, which must evaluate to an expression of type `string`. + The contents of the string must correspond to the $(DDSUBLINK spec/abi, name_mangling, mangled contents of a type) + that has been seen by the implementation.) + + $(P Only D mangling is supported. Other manglings, such as C++ mangling, are not.) + + $(P The value returned is a type.) + + --- + template Type(T) { alias Type = T; } + + Type!(__traits(toType, "i")) j = 3; // j is declared as type `int` + + static assert(is(Type!(__traits(toType, (int*).mangleof)) == int*)); + + __traits(toType, "i") x = 4; // x is also declared as type `int` + --- + + $(RATIONALE Provides the inverse operation of the $(DDSUBLINK spec/property, mangleof, `.mangleof`) property.) + +$(H3 $(GNAME isZeroInit)) + + $(P Takes one argument which must be a type. If the type's + $(DDSUBLINK spec/property, init, default initializer) is all zero + bits then `true` is returned, otherwise `false`.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct S1 { int x; } +struct S2 { int x = -1; } + +static assert(__traits(isZeroInit, S1)); +static assert(!__traits(isZeroInit, S2)); + +void test() +{ + int x = 3; + static assert(__traits(isZeroInit, typeof(x))); +} + +// `isZeroInit` will always return true for a class C +// because `C.init` is null reference. + +class C { int x = -1; } + +static assert(__traits(isZeroInit, C)); + +// For initializing arrays of element type `void`. +static assert(__traits(isZeroInit, void)); +--- +) + +$(H3 $(GNAME hasCopyConstructor)) + + $(P The argument is a type. + If it is a struct with a copy constructor, returns $(D true). Otherwise, return $(D false). + A copy constructor is distinct from a move constructor or a postblit. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- + +import std.stdio; + +struct S { } + +class C { } + +struct P +{ + this(ref P rhs) {} // copy constructor +} + +struct B +{ + this(this) {} // postblit +} + +void main() +{ + writeln(__traits(hasCopyConstructor, S)); // false + writeln(__traits(hasCopyConstructor, C)); // false + writeln(__traits(hasCopyConstructor, P)); // true + writeln(__traits(hasCopyConstructor, B)); // false, this is a postblit +} +--- +) + +$(H3 $(GNAME hasMoveConstructor)) + + $(P The argument is a type. + If it is a struct with a move constructor, returns $(D true). Otherwise, return $(D false). + A move constructor is distinct from a copy constructor or a postblit. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- + +import std.stdio; + +struct S +{ + this(S rhs) {} // move constructor +} + +class C { } + +struct P +{ + this(ref P rhs) {} // copy constructor +} + +struct B +{ + this(this) {} // postblit +} + +void main() +{ + writeln(__traits(hasMoveConstructor, S)); // true + writeln(__traits(hasMoveConstructor, C)); // false + writeln(__traits(hasMoveConstructor, P)); // false + writeln(__traits(hasMoveConstructor, B)); // false, this is a postblit +} +--- +) + +$(H3 $(GNAME hasPostblit)) + + $(P The argument is a type. If it is a struct with a postblit, returns $(D true). Otherwise, return $(D false). Note a postblit is distinct from a copy constructor. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- + +import std.stdio; + +struct S +{ +} + +class C +{ +} + +struct P +{ + this(ref P rhs) {} +} + +struct B +{ + this(this) {} +} + + +void main() +{ + writeln(__traits(hasPostblit, S)); // false + writeln(__traits(hasPostblit, C)); // false + writeln(__traits(hasPostblit, P)); // false, this is a copy ctor + writeln(__traits(hasPostblit, B)); // true +} +--- +) + +$(H3 $(GNAME getAliasThis)) + + $(P Takes one argument, a type. If the type has `alias this` declarations, + returns a *ValueSeq* of the names (as `string`s) of the members used in + those declarations. Otherwise returns an empty sequence. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +alias AliasSeq(T...) = T; + +struct S1 +{ + string var; + alias var this; +} +static assert(__traits(getAliasThis, S1) == AliasSeq!("var")); +static assert(__traits(getAliasThis, int).length == 0); + +pragma(msg, __traits(getAliasThis, S1)); +pragma(msg, __traits(getAliasThis, int)); +--- +) + + Prints: + +$(CONSOLE +tuple("var") +tuple() +) + +$(H3 $(GNAME getPointerBitmap)) + + $(P The argument is a type. + The result is an array of $(D size_t) describing the memory used by an instance of the given type. + ) + $(P The first element of the array is the size of the type (for classes it is + the $(GLINK classInstanceSize)).) + $(P The following elements describe the locations of GC managed pointers within the + memory occupied by an instance of the type. + For type T, there are $(D T.sizeof / size_t.sizeof) possible pointers represented + by the bits of the array values.) + $(P This array can be used by a precise GC to avoid false pointers.) +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +void main() +{ + static class C + { + // implicit virtual function table pointer not marked + // implicit monitor field not marked, usually managed manually + C next; + size_t sz; + void* p; + void function () fn; // not a GC managed pointer + } + + static struct S + { + size_t val1; + void* p; + C c; + byte[] arr; // { length, ptr } + void delegate () dg; // { context, func } + } + + static assert (__traits(getPointerBitmap, C) == [6*size_t.sizeof, 0b010100]); + static assert (__traits(getPointerBitmap, S) == [7*size_t.sizeof, 0b0110110]); +} +--- +) + +$(H3 $(GNAME getVirtualFunctions)) + + $(P The same as $(GLINK getVirtualMethods), except that + final functions that do not override anything are included. + ) + +$(H3 $(GNAME getVirtualMethods)) + + $(P The first argument is a class type or an expression of + class type. + The second argument is a string that matches the name of + one of the functions of that class. + The result is a symbol sequence of the virtual overloads of that function. + It does not include final functions that do not override anything. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +class D +{ + this() { } + ~this() { } + void foo() { } + int foo(int) { return 2; } +} + +void main() +{ + D d = new D(); + + foreach (t; __traits(getVirtualMethods, D, "foo")) + writeln(typeid(typeof(t))); + + alias b = typeof(__traits(getVirtualMethods, D, "foo")); + foreach (t; b) + writeln(typeid(t)); + + auto i = __traits(getVirtualMethods, d, "foo")[1](1); + writeln(i); +} +--- +) + + Prints: + +$(CONSOLE +void() +int() +void() +int() +2 +) + +$(H3 $(GNAME classInstanceSize)) + + $(P Takes a single argument, which must evaluate to either + a class type or an expression of class type. + The result + is of type $(CODE size_t), and the value is the number of + bytes in the runtime instance of the class type. + It is based on the static type of a class, not the + polymorphic type. + ) + +$(H3 $(GNAME classInstanceAlignment)) + + $(P Takes a single argument, which must evaluate to either + a class type or an expression of class type. + The result + is of type $(CODE size_t), and the value is the alignment + of a runtime instance of the class type. + It is based on the static type of a class, not the + polymorphic type. + ) + +$(H3 $(GNAME initSymbol)) + + $(P Takes a single argument, which must evaluate to a `class`, `struct` or `union` type. + Returns a `const(void)[]` that holds the initial state of any instance of the supplied type. + The slice is constructed for any type `T` as follows: + ) + + - `ptr` points to either the initializer symbol of `T` + or `null` if `T` is a $(RELATIVE_LINK2 isZeroInit, zero-initialized) struct/union. + + - `length` is equal to the size of an instance, i.e. `T.sizeof` for a struct/union and + $(RELATIVE_LINK2 classInstanceSize, $(D __traits(classInstanceSize, T))) for a class. + + $(P + This trait matches the behaviour of `TypeInfo.initializer()` but can also be used when + `TypeInfo` is not available. + ) + + $(P + This trait is not available during $(DDSUBLINK spec/glossary, ctfe, CTFE) because the actual address + of the initializer symbol will be set by the linker and hence is not available at compile time. + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + --- + import core.stdc.stdlib; + + class C + { + int i = 4; + } + + /// Initializes a malloc'ed instance of `C` + void main() + { + const void[] initSym = __traits(initSymbol, C); + + void* ptr = malloc(initSym.length); + scope (exit) free(ptr); + + // Note: allocated memory will only be written to through `c`, so cast is safe + ptr[0..initSym.length] = cast(void[]) initSym[]; + + C c = cast(C) ptr; + assert(c.i == 4); + } + --- + ) + + +$(H2 $(LNAME2 functions, Function Traits)) + +$(H3 $(GNAME isDisabled)) + + $(P Takes one argument and returns `true` if it's a function declaration + marked with `@disable`.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct Foo +{ + @disable void foo(); + void bar(){} +} + +static assert(__traits(isDisabled, Foo.foo)); +static assert(!__traits(isDisabled, Foo.bar)); +--- +) + + $(P For any other declaration, even if `@disable` is a syntactically valid + attribute, `false` is returned because the annotation has no effect.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +@disable struct Bar{} + +static assert(!__traits(isDisabled, Bar)); +--- +) + +$(H3 $(GNAME getVirtualIndex)) + + $(P Takes a single argument which must evaluate to a function. + The result is a $(CODE ptrdiff_t) containing the index + of that function within the vtable of the parent type. + If the function passed in is final and does not override + a virtual function, $(D -1) is returned instead. + ) + +$(H3 $(GNAME isVirtualFunction)) + + $(P The same as $(GLINK isVirtualMethod), except + that final functions that don't override anything return true. + ) + +$(H3 $(GNAME isVirtualMethod)) + + $(P Takes one argument. If that argument is a virtual function, + $(D true) is returned, otherwise $(D false). + Final functions that don't override anything return false. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +struct S +{ + void bar() { } +} + +class C +{ + void bar() { } +} + +void main() +{ + writeln(__traits(isVirtualMethod, C.bar)); // true + writeln(__traits(isVirtualMethod, S.bar)); // false +} +--- +) + +$(H3 $(GNAME isAbstractFunction)) + + $(P Takes one argument. If that argument is an abstract function, + $(D true) is returned, otherwise $(D false). + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +struct S +{ + void bar() { } +} + +class C +{ + void bar() { } +} + +class AC +{ + abstract void foo(); +} + +void main() +{ + writeln(__traits(isAbstractFunction, C.bar)); // false + writeln(__traits(isAbstractFunction, S.bar)); // false + writeln(__traits(isAbstractFunction, AC.foo)); // true +} +--- +) + +$(H3 $(GNAME isFinalFunction)) + + $(P Takes one argument. If that argument is a final function, + $(D true) is returned, otherwise $(D false). + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +struct S +{ + void bar() { } +} + +class C +{ + void bar() { } + final void foo(); +} + +final class FC +{ + void foo(); +} + +void main() +{ + writeln(__traits(isFinalFunction, C.bar)); // false + writeln(__traits(isFinalFunction, S.bar)); // false + writeln(__traits(isFinalFunction, C.foo)); // true + writeln(__traits(isFinalFunction, FC.foo)); // true +} +--- +) + +$(H3 $(GNAME isOverrideFunction)) + + $(P Takes one argument. If that argument is a function marked with + $(D_KEYWORD override), $(D true) is returned, otherwise $(D false). + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +class Base +{ + void foo() { } +} + +class Foo : Base +{ + override void foo() { } + void bar() { } +} + +void main() +{ + writeln(__traits(isOverrideFunction, Base.foo)); // false + writeln(__traits(isOverrideFunction, Foo.foo)); // true + writeln(__traits(isOverrideFunction, Foo.bar)); // false +} +--- +) + +$(H3 $(GNAME isStaticFunction)) + + $(P Takes one argument. If that argument is a static function, + meaning it has no context pointer, + $(D true) is returned, otherwise $(D false). + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct A +{ + int foo() { return 3; } + static int boo(int a) { return a; } +} + +void main() +{ + assert(__traits(isStaticFunction, A.boo)); + assert(!__traits(isStaticFunction, A.foo)); + assert(__traits(isStaticFunction, main)); +} +--- +) + +$(H3 $(GNAME isReturnOnStack)) + + $(P + Takes one argument which must either be a function symbol, function literal, + a delegate, or a function pointer. + It returns a `bool` which is `true` if the return value of the function is + returned on the stack via a pointer to it passed as a hidden extra + parameter to the function. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + struct S { int[20] a; } + int test1(); + S test2(); + + static assert(__traits(isReturnOnStack, test1) == false); + static assert(__traits(isReturnOnStack, test2) == true); + --- +) + + $(IMPLEMENTATION_DEFINED + This is determined by the function ABI calling convention in use, + which is often complex. + ) + + $(BEST_PRACTICE This has applications in: + $(OL + $(LI Returning values in registers is often faster, so this can be used as + a check on a hot function to ensure it is using the fastest method.) + $(LI When using inline assembly to correctly call a function.) + $(LI Testing that the compiler does this correctly is normally hackish and awkward, + this enables efficient, direct, and simple testing.) + )) + +$(SECTION3 $(GNAME getFunctionVariadicStyle), + $(P + Takes one argument which must either be a function symbol, or a type + that is a function, delegate or a function pointer. + It returns a string identifying the kind of + $(LINK2 function.html#variadic, variadic arguments) that are supported. + ) + + $(TABLE2 getFunctionVariadicStyle, + $(THEAD result, kind, access, example) + $(TROW $(D "none"), not a variadic function, $(NBSP), $(D void foo();)) + $(TROW $(D "argptr"), D style variadic function, $(D _argptr) and $(D _arguments), $(D void bar(...))) + $(TROW $(D "stdarg"), C style variadic function, $(LINK2 $(ROOT_DIR)phobos/core_stdc_stdarg.html, $(D core.stdc.stdarg)), $(D extern (C) void abc(int, ...))) + $(TROW $(D "typesafe"), typesafe variadic function, array on stack, $(D void def(int[] ...))) + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import core.stdc.stdarg; + +void novar() {} +extern(C) void cstyle(int, ...) {} +extern(C++) void cppstyle(int, ...) {} +void dstyle(...) {} +void typesafe(int[]...) {} + +static assert(__traits(getFunctionVariadicStyle, novar) == "none"); +static assert(__traits(getFunctionVariadicStyle, cstyle) == "stdarg"); +static assert(__traits(getFunctionVariadicStyle, cppstyle) == "stdarg"); +static assert(__traits(getFunctionVariadicStyle, dstyle) == "argptr"); +static assert(__traits(getFunctionVariadicStyle, typesafe) == "typesafe"); + +static assert(__traits(getFunctionVariadicStyle, (int[] a...) {}) == "typesafe"); +static assert(__traits(getFunctionVariadicStyle, typeof(cstyle)) == "stdarg"); +--- +) +) + +$(SECTION3 $(GNAME getFunctionAttributes), + $(P + Takes one argument which must either be a function symbol, function literal, + or a function pointer. It returns a string *ValueSeq* of all the attributes of + that function $(B excluding) any user-defined attributes (UDAs can be + retrieved with the $(GLINK getAttributes) trait). + If no attributes exist it will return an empty sequence. + ) + + + $(B Note:) The order of the attributes in the returned sequence is + implementation-defined and should not be relied upon. + + $(P + A list of currently supported attributes are:) + $(UL $(LI $(D pure), $(D nothrow), $(D @nogc), $(D @property), $(D @system), $(D @trusted), $(D @safe), $(D ref) and $(D @live))) + $(B Note:) $(D ref) is a function attribute even though it applies to the return type. + + $(P + Additionally the following attributes are only valid for non-static member functions:) + $(UL $(LI $(D const), $(D immutable), $(D inout), $(D shared))) + + For example: + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +int sum(int x, int y) pure nothrow { return x + y; } + +pragma(msg, __traits(getFunctionAttributes, sum)); + +struct S +{ + void test() const @system { } +} + +pragma(msg, __traits(getFunctionAttributes, S.test)); +--- +) + + Prints: + +$(CONSOLE +tuple("pure", "nothrow", "@system") +tuple("const", "@system") +) + + $(P Note that some attributes can be inferred. For example:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +pragma(msg, __traits(getFunctionAttributes, (int x) @trusted { return x * 2; })); +--- +) + + Prints: + +$(CONSOLE +tuple("pure", "nothrow", "@nogc", "@trusted") +) +) +) + + +$(H2 $(LNAME2 function-parameters, Function Parameter Traits)) + +$(H3 $(GNAME isRef), $(GNAME isOut), $(GNAME isLazy)) + + $(P Takes one argument. If that argument is a declaration, + $(D true) is returned if it is $(D_KEYWORD ref), $(D_KEYWORD out), + or $(D_KEYWORD lazy), otherwise $(D false). + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +void fooref(ref int x) +{ + static assert(__traits(isRef, x)); + static assert(!__traits(isOut, x)); + static assert(!__traits(isLazy, x)); +} + +void fooout(out int x) +{ + static assert(!__traits(isRef, x)); + static assert(__traits(isOut, x)); + static assert(!__traits(isLazy, x)); +} + +void foolazy(lazy int x) +{ + static assert(!__traits(isRef, x)); + static assert(!__traits(isOut, x)); + static assert(__traits(isLazy, x)); +} +--- +) + +$(H3 $(GNAME getParameterStorageClasses)) + + $(P + Takes two arguments. + The first must either be a function symbol, a function call, or a type + that is a function, delegate or a function pointer. + The second is an integer identifying which parameter, where the first parameter is + 0. + It returns a *ValueSeq* of strings representing the storage classes of that parameter. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +ref int foo(return ref const int* p, scope int* a, out int b, lazy int c); + +static assert(__traits(getParameterStorageClasses, foo, 0)[0] == "return"); +static assert(__traits(getParameterStorageClasses, foo, 0)[1] == "ref"); + +static assert(__traits(getParameterStorageClasses, foo, 1)[0] == "scope"); +static assert(__traits(getParameterStorageClasses, foo, 2)[0] == "out"); +static assert(__traits(getParameterStorageClasses, typeof(&foo), 3)[0] == "lazy"); + +int* p, a; +int b, c; + +static assert(__traits(getParameterStorageClasses, foo(p, a, b, c), 1)[0] == "scope"); +static assert(__traits(getParameterStorageClasses, foo(p, a, b, c), 2)[0] == "out"); +static assert(__traits(getParameterStorageClasses, foo(p, a, b, c), 3)[0] == "lazy"); +--- +) + +$(H3 $(GNAME parameters)) + + $(P May only be used inside a function. Takes no arguments, and returns + an $(DDSUBLINK spec/template, lvalue-sequences, lvalue sequence) of the + enclosing function's parameters.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + alias AliasSeq(A...) = A; + + void f(int n, char c) + { + alias PS = __traits(parameters); + PS[0]++; // increment n + static assert(is(typeof(PS) == AliasSeq!(int, char))); + + // output parameter names + static foreach (i, p; PS) + { + pragma(msg, __traits(identifier, p)); + } + } + + int add(int x, int y) + { + return x + y; + } + + int forwardToAdd(int x, int y) + { + return add(__traits(parameters)); + // equivalent to; + //return add(x, y); + } + --- + ) + + $(P If the function is nested, the parameters returned are those of the + inner function, not the outer one.) + + --- + int nestedExample(int x) + { + // outer function's parameters + static assert(typeof(__traits(parameters)).length == 1); + + int add(int x, int y) + { + // inner function's parameters + static assert(typeof(__traits(parameters)).length == 2); + return x + y; + } + + return add(x, x); + } + --- + --- + class C + { + int opApply(int delegate(size_t, C) dg) + { + if (dg(0, this)) return 1; + return 0; + } + } + + void foreachExample(C c, int x) + { + foreach(idx; 0..5) + { + static assert(is(typeof(__traits(parameters)) == AliasSeq!(C, int))); + } + foreach(idx, elem; c) + { + // __traits(parameters) sees past the delegate passed to opApply + static assert(is(typeof(__traits(parameters)) == AliasSeq!(C, int))); + } + } + --- + + +$(H2 $(LNAME2 symbols, Symbol Traits)) + +$(H3 $(GNAME fullyQualifiedName)) + + $(P Gets the fully qualified name of a type or symbol.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +----------------- +module myModule; + +int i; +static assert(__traits(fullyQualifiedName, i) == "myModule.i"); + +struct MyStruct {} +static assert(__traits(fullyQualifiedName, const MyStruct[]) == "const(myModule.MyStruct[])"); +----------------- +) + +$(H3 $(GNAME isNested)) + + $(P Takes one argument. + It returns $(D true) if the argument is a nested type which internally + stores a context pointer, otherwise it returns $(D false). + Nested types can be $(DDSUBLINK spec/class, nested, classes), + $(DDSUBLINK spec/struct, nested, structs), and + $(DDSUBLINK spec/function, variadicnested, functions).) + +$(H3 $(GNAME isFuture)) + + $(P Takes one argument. It returns `true` if the argument is a symbol + marked with the $(DDSUBLINK spec/attribute, future, `@__future` attribute), + otherwise `false`. Currently, only + functions and variable declarations have support for the `@__future` keyword.) + +$(H3 $(GNAME isDeprecated)) + + $(P Takes one argument. It returns `true` if the argument is a symbol + marked with the `deprecated` keyword, otherwise `false`.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +deprecated("No longer supported") +int i; + +struct A +{ + int foo() { return 1; } + + deprecated("please use foo") + int bar() { return 1; } +} + +static assert(__traits(isDeprecated, i)); +static assert(!__traits(isDeprecated, A.foo)); +static assert(__traits(isDeprecated, A.bar)); +--- +) + +$(H3 $(GNAME isTemplate)) + + $(P Takes one argument. If that argument or any of its overloads is a template + then $(D true) is returned, otherwise $(D false). + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +void foo(T)(){} +static assert(__traits(isTemplate, foo)); +static assert(!__traits(isTemplate, foo!int())); +static assert(!__traits(isTemplate, "string")); +--- +) + +$(H3 $(GNAME isModule)) + + $(P Takes one argument. If that argument is a symbol that refers to a + $(DDLINK spec/module, Modules, module) then $(D true) is returned, otherwise $(D false). + $(DDSUBLINK spec/module, package-module, Package modules) are considered to be + modules even if they have not been directly imported as modules. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import core.thread; +import std.algorithm.sorting; + +// A regular package (no package.d) +static assert(!__traits(isModule, core)); +// A package module (has a package.d file) +// Note that we haven't imported std.algorithm directly. +// (In other words, we don't have an "import std.algorithm;" directive.) +static assert(__traits(isModule, std.algorithm)); +// A regular module +static assert(__traits(isModule, std.algorithm.sorting)); +--- +) + +$(H3 $(GNAME isPackage)) + + $(P Takes one argument. If that argument is a symbol that refers to a + $(DDSUBLINK spec/module, PackageName, package) then $(D true) is returned, + otherwise $(D false). + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.algorithm.sorting; +static assert(__traits(isPackage, std)); +static assert(__traits(isPackage, std.algorithm)); +static assert(!__traits(isPackage, std.algorithm.sorting)); +--- +) + +$(H3 $(GNAME isCOMClass)) + $(P Takes one argument. If that argument is a symbol that refers to a + $(DDSUBLINK spec/class, ClassDeclaration, class declaration) and is a COM class then $(D true) is retuned, + otherwise $(D false). + ) + +$(H3 $(GNAME hasMember)) + + $(P The first argument is a type that has members, or + is an expression of a type that has members. + The second argument is a string. + If the string is a valid property of the type, + $(D true) is returned, otherwise $(D false). + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +struct S +{ + int m; +} + +void main() +{ + S s; + + static assert(__traits(hasMember, S, "m")); + static assert(__traits(hasMember, s, "m")); + static assert(!__traits(hasMember, S, "y")); + static assert(!__traits(hasMember, S, "write")); // false, but callable like a member via UFCS + static assert(__traits(hasMember, int, "sizeof")); + static assert(__traits(hasMember, 5, "sizeof")); +} +--- +) + +$(H3 $(GNAME identifier)) + + $(P Takes one argument, a symbol. Returns the identifier + for that symbol as a string literal. + ) +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +int var = 123; +static assert(__traits(identifier, var) == "var"); +--- +) + +$(SECTION3 $(GNAME getAttributes), + $(P + Takes one argument, a symbol. Returns a sequence of all attached user-defined attributes. + If no UDAs exist it will return an empty sequence + ) + + $(P + For more information, see: $(DDSUBLINK spec/attribute, uda, User-Defined Attributes) + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +@(3) int a; +@("string", 7) int b; + +enum Foo; +@Foo int c; + +pragma(msg, __traits(getAttributes, a)); +pragma(msg, __traits(getAttributes, b)); +pragma(msg, __traits(getAttributes, c)); +--- +) + + Prints: + +$(CONSOLE +tuple(3) +tuple("string", 7) +tuple((Foo)) +) +) + +$(SECTION3 $(GNAME getBitfieldOffset), + $(P Takes one argument, a qualified name that resolve to a field in a struct or class. + ) + $(P If the field is a bitfield, it returns as a `uint` the bit number of the least significant + bit in the field. The rightmost bit is at offset 0, the leftmost bit is at offset 31 (for + 32 bit int fields). + ) + $(P If the field is a not bitfield, it returns as a `uint` the number 0. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct S +{ + int a,b; + int :2, c:3; +} + +static assert(__traits(getBitfieldOffset, S.b) == 0); +static assert(__traits(getBitfieldOffset, S.c) == 2); +--- +) + +) + +$(SECTION3 $(GNAME getBitfieldWidth), + $(P Takes one argument, a qualified name that resolve to a field in a struct or class. + ) + $(P If the field is a bitfield, it returns as a `uint` the width of the bit field as + a number of bits. + ) + $(P If the field is a not bitfield, it returns the number of bits in the type. + ) +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct S +{ + int a,b; + int :2, c:3; +} + +static assert(__traits(getBitfieldWidth, S.b) == 32); +static assert(__traits(getBitfieldWidth, S.c) == 3); +--- +) +) + +$(H3 $(GNAME getLinkage)) + + $(P Takes one argument, which is a declaration symbol, or the type of a function, delegate, + pointer to function, struct, class, or interface. + Returns a string representing the $(LINK2 attribute.html#LinkageAttribute, LinkageAttribute) + of the declaration. + The string is one of: + ) + + $(UL + $(LI $(D "D")) + $(LI $(D "C")) + $(LI $(D "C++")) + $(LI $(D "Windows")) + $(LI $(D "Objective-C")) + $(LI $(D "System")) + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +extern (C) int fooc(); +alias aliasc = fooc; + +static assert(__traits(getLinkage, fooc) == "C"); +static assert(__traits(getLinkage, aliasc) == "C"); + +extern (C++) struct FooCPPStruct {} +extern (C++) class FooCPPClass {} +extern (C++) interface FooCPPInterface {} + +static assert(__traits(getLinkage, FooCPPStruct) == "C++"); +static assert(__traits(getLinkage, FooCPPClass) == "C++"); +static assert(__traits(getLinkage, FooCPPInterface) == "C++"); +--- +) + +$(H3 $(GNAME getLocation)) + $(P Takes one argument which is a symbol. + To disambiguate between overloads, pass the result of $(GLINK getOverloads) with the desired index, to `getLocation`. + Returns a *ValueSeq* of a string and two `int`s which correspond to the filename, line number and column number where the argument + was declared. + ) + +$(H3 $(GNAME getMember)) + + $(P Takes two arguments, the second must be a string. + The result is an expression formed from the first + argument, followed by a $(SINGLEQUOTE .), followed by the second + argument as an identifier. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +struct S +{ + int mx; + static int my; +} + +void main() +{ + S s; + + __traits(getMember, s, "mx") = 1; // same as s.mx=1; + writeln(__traits(getMember, s, "m" ~ "x")); // 1 + + // __traits(getMember, S, "mx") = 1; // error, no this for S.mx + __traits(getMember, S, "my") = 2; // ok +} +--- +) + +$(H3 $(GNAME getOverloads)) + + * The first argument is an aggregate type or instance, or a module. + * The second argument is a `string` that matches the name of + the member(s) to return. + * The third argument is a `bool`, and is optional. If `true`, the + result will also include template overloads. + * The result is a $(DDSUBLINK spec/template, homogeneous_sequences, symbol sequence) + of all the overloads of the supplied name. + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +class D +{ + void foo() { } + int foo(int) { return 2; } + void bar(T)() { return T.init; } + class bar(int n) {} +} + +void main() +{ + D d = new D(); + + alias fooOverloads = __traits(getOverloads, D, "foo"); + foreach (o; fooOverloads) + writeln(typeid(typeof(o))); + + // typeof on a symbol sequence gives a type sequence + foreach (T; typeof(fooOverloads)) + writeln(typeid(T)); + + // calls d.foo(3) + auto i = __traits(getOverloads, d, "foo")[1](3); + assert(i == 2); + + // pass true to include templates + // calls std.stdio.writeln(i) + __traits(getOverloads, std.stdio, "writeln", true)[0](i); + + foreach (o; __traits(getOverloads, D, "bar", true)) + writeln(o.stringof); +} +--- +) + + Prints: + +$(CONSOLE +void function() +int function(int) +void function() +int function(int) +2 +bar(T)() +bar(int n) +) + +$(H3 $(GNAME getCppNamespaces)) + $(P The argument is a symbol. + The result is a *ValueSeq* of strings, possibly empty, that correspond to the namespaces the symbol resides in. + ) +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +extern(C++, "ns") +struct Foo {} +struct Bar {} +extern(C++, __traits(getCppNamespaces, Foo)) struct Baz {} +static assert(__traits(getCppNamespaces, Foo) == __traits(getCppNamespaces, Baz)); +void main() +{ + static assert(__traits(getCppNamespaces, Foo)[0] == "ns"); + static assert(!__traits(getCppNamespaces, Bar).length); + static assert(__traits(getCppNamespaces, Foo) == __traits(getCppNamespaces, Baz)); +} +--- +) + +$(H3 $(GNAME getVisibility)) + + $(P The argument is a symbol. + The result is a string giving its visibility level: "public", "private", "protected", "export", or "package". + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +class D +{ + export void foo() { } + public int bar; +} + +void main() +{ + D d = new D(); + + auto i = __traits(getVisibility, d.foo); + writeln(i); + + auto j = __traits(getVisibility, d.bar); + writeln(j); +} +--- +) + + Prints: + +$(CONSOLE +export +public +) + +$(H3 $(GNAME fullyQualifiedName)) + + $(P Takes one argument, which can be a type, expression, or symbol, and returns a string.) + + $(UL + $(LI A $(D type) returns a string representing the type.) + $(LI A $(D expression) returns a string representing the type of the expression.) + $(LI A $(D symbol) returns a string representing the fully qualified name of the symbol.) + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +module plugh; +import std.stdio; + +void main() +{ + auto s = __traits(fullyQualifiedName, int); + writeln(s); + + auto t = __traits(fullyQualifiedName, 1.0); + writeln(t); + + auto u = __traits(fullyQualifiedName, t); + writeln(u); +} +--- +) + + Prints: + +$(CONSOLE +int +double +plugh.main.t +) + +$(H3 $(GNAME getProtection)) + + $(P A backward-compatible alias for $(GLINK getVisibility).) + +$(H3 $(GNAME getTargetInfo)) + + $(P Receives a string key as argument. + The result is an expression describing the requested target information. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +version (CppRuntime_Microsoft) + static assert(__traits(getTargetInfo, "cppRuntimeLibrary") == "libcmt"); +--- +) + + $(P Keys are implementation defined, allowing relevant data for exotic targets. + A reliable subset exists which are always available: + ) + + $(UL + $(LI $(D "cppRuntimeLibrary") - The C++ runtime library affinity for this toolchain) + $(LI $(D "cppStd") - The version of the C++ standard supported by $(D extern$(LPAREN)C++$(RPAREN)) code, equivalent to the `__cplusplus` macro in a C++ compiler) + $(LI $(D "floatAbi") - Floating point ABI; may be $(D "hard"), $(D "soft"), or $(D "softfp")) + $(LI $(D "objectFormat") - Target object format) + ) + +$(H3 $(GNAME getUnitTests)) + + $(P + Takes one argument, a symbol of an aggregate (e.g. struct/class/module). + The result is a symbol sequence of all the unit test functions of that aggregate. + The functions returned are like normal nested static functions, + $(DDSUBLINK spec/glossary, ctfe, CTFE) will work and + $(DDSUBLINK spec/attribute, uda, UDAs) will be accessible. + ) + + $(NOTE + The `-unittest` flag needs to be passed to the compiler. If the flag + is not passed, $(CODE __traits(getUnitTests)) will always return an + empty sequence. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +module foo; + +import core.runtime; +import std.stdio; + +struct name { string name; } + +class Foo +{ + unittest + { + writeln("foo.Foo.unittest"); + } +} + +@name("foo") unittest +{ + writeln("foo.unittest"); +} + +template Tuple (T...) +{ + alias Tuple = T; +} + +shared static this() +{ + // Override the default unit test runner to do nothing. After that, "main" will + // be called. + Runtime.moduleUnitTester = { return true; }; +} + +void main() +{ + writeln("start main"); + + alias tests = Tuple!(__traits(getUnitTests, foo)); + static assert(tests.length == 1); + + alias attributes = Tuple!(__traits(getAttributes, tests[0])); + static assert(attributes.length == 1); + + foreach (test; tests) + test(); + + foreach (test; __traits(getUnitTests, Foo)) + test(); +} +--- +) + + $(P By default, the above will print:) + +$(CONSOLE +start main +foo.unittest +foo.Foo.unittest +) + +$(H3 $(GNAME parent)) + + $(P Takes a single argument which must evaluate to a symbol. + The result is the symbol that is the parent of it. + ) + +$(H3 $(GNAME child)) + + $(P Takes two arguments. + The first must be a symbol or expression. + The second is a symbol, such as an alias to a member of the first + argument. + The result is the second argument interpreted with its $(D this) + context set to the value of the first argument. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +struct A +{ + int i; + int foo(int j) { + return i * j; + } + T bar(T)(T t) { + return i + t; + } +} + +alias Ai = A.i; +alias Abar = A.bar!int; + +void main() +{ + A a; + + __traits(child, a, Ai) = 3; + writeln(a.i); + writeln(__traits(child, a, A.foo)(2)); + writeln(__traits(child, a, Abar)(5)); +} +--- +) + + Prints: + +$(CONSOLE +3 +6 +8 +) + +$(H3 $(GNAME allMembers)) + + $(P Takes a single argument, which must evaluate to either + a module, a struct, a union, a class, an interface, an enum, or a + template instantiation. + ) + $(P + A sequence of string literals is returned, each of which + is the name of a member of that argument combined with all + of the members of its base classes (if the argument is a class). + No name is repeated. + Builtin properties are not included. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +class D +{ + this() { } + ~this() { } + void foo() { } + int foo(int) { return 0; } +} + +void main() +{ + auto b = [ __traits(allMembers, D) ]; + writeln(b); + // ["__ctor", "__dtor", "foo", "toString", "toHash", "opCmp", "opEquals", + // "Monitor", "factory"] +} +--- +) + + $(P The order in which the strings appear in the result + is not defined.) + +$(H3 $(GNAME derivedMembers)) + + $(P Takes a single argument, which must evaluate to either + a type or an expression of type. + A sequence of string literals is returned, each of which + is the name of a member of that type. + No name is repeated. + Base class member names are not included. + Builtin properties are not included. + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; + +class D +{ + this() { } + ~this() { } + void foo() { } + int foo(int) { return 0; } +} + +void main() +{ + auto a = [__traits(derivedMembers, D)]; + writeln(a); // ["__ctor", "__dtor", "foo"] +} +--- +) + + $(P The order in which the strings appear in the result + is not defined.) + +$(H3 $(GNAME isSame)) + + $(P Compares two arguments and evaluates to `bool`.) + + $(P The result is `true` if the two arguments are the same symbol + (once aliases are resolved).) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct S { } + +int foo(); +int bar(); + +static assert(__traits(isSame, foo, foo)); +static assert(!__traits(isSame, foo, bar)); +static assert(!__traits(isSame, foo, S)); +static assert(__traits(isSame, S, S)); +static assert(!__traits(isSame, object, S)); +static assert(__traits(isSame, object, object)); + +alias daz = foo; +static assert(__traits(isSame, foo, daz)); +--- +) + $(P isSame matches against non-instantiated templates.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +struct Foo(T){ + T x; +} + +struct Bar(T){ + T x; +} + +struct Point(T){ + T x; + T y; +} + +enum isFooOrBar(alias FB) = __traits(isSame, FB, Foo) || __traits(isSame, FB, Bar); + +static assert(isFooOrBar!(Foo)); +static assert(isFooOrBar!(Bar)); +static assert(!isFooOrBar!(Point)); +--- +) + + $(P The result is `true` if the two arguments are expressions + made up of literals or enums that evaluate to the same value.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +enum e = 3; +static assert(__traits(isSame, (e), 3)); +static assert(__traits(isSame, 5, 2 + e)); +--- +) + $(P If the two arguments are both + $(DDSUBLINK spec/expression, function_literals, lambda functions) (or aliases + to lambda functions), then they are compared for equality. For + the comparison to be computed correctly, the following conditions + must be met for both lambda functions:) + + $(OL + $(LI The lambda function arguments must not have a template + instantiation as an explicit argument type. Any other argument + types (basic, user-defined, template) are supported.) + $(LI The lambda function body must contain a single expression + (no return statement) which contains only numeric values, + manifest constants, enum values, function arguments and function + calls. If the expression contains local variables or return + statements, the function is considered incomparable.) + ) + + $(P If these constraints aren't fulfilled, the function is considered + incomparable and the result is $(D false).) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + static assert(__traits(isSame, (a, b) => a + b, (c, d) => c + d)); + static assert(__traits(isSame, a => ++a, b => ++b)); + static assert(!__traits(isSame, (int a, int b) => a + b, (a, b) => a + b)); + static assert(__traits(isSame, (a, b) => a + b + 10, (c, d) => c + d + 10)); + --- + ) +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +int f() { return 2; } + +void test(alias pred)() +{ + // f() from main is a different function from top-level f() + static assert(!__traits(isSame, (int a) => a + f(), pred)); +} + +void main() +{ + // lambdas accessing local variables are considered incomparable + int b; + static assert(!__traits(isSame, a => a + b, a => a + b)); + + // lambdas calling other functions are comparable + int f() { return 3;} + static assert(__traits(isSame, a => a + f(), a => a + f())); + test!((int a) => a + f())(); +} +--- +) + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + class A + { + int a; + this(int a) + { + this.a = a; + } + } + + class B + { + int a; + this(int a) + { + this.a = a; + } + } + + static assert(__traits(isSame, (A a) => ++a.a, (A b) => ++b.a)); + // lambdas with different data types are considered incomparable, + // even if the memory layout is the same + static assert(!__traits(isSame, (A a) => ++a.a, (B a) => ++a.a)); + --- + ) + + $(P If the two arguments are tuples then the result is `true` if the + two tuples, after expansion, have the same length and if each pair + of nth argument respects the constraints previously specified.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.meta; + +struct S { } + +// like __traits(isSame,0,0) && __traits(isSame,1,1) +static assert(__traits(isSame, AliasSeq!(0,1), AliasSeq!(0,1))); +// like __traits(isSame,S,std.meta) && __traits(isSame,1,1) +static assert(!__traits(isSame, AliasSeq!(S,1), AliasSeq!(std.meta,1))); +// the length of the sequences is different +static assert(!__traits(isSame, AliasSeq!(1), AliasSeq!(1,2))); +--- +) + +$(H3 $(GNAME compiles)) + + $(P Returns a bool $(D true) if all of the arguments + compile (are semantically correct). + The arguments can be symbols, types, or expressions that + are syntactically correct. + The arguments cannot be statements or declarations - instead + these can be wrapped in a $(DDSUBLINK spec/expression, function_literals, + function literal) expression. + ) + + $(P If there are no arguments, the result is $(D false).) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +static assert(!__traits(compiles)); +static assert(__traits(compiles, 1 + 1)); // expression +static assert(__traits(compiles, typeof(1))); // type +static assert(__traits(compiles, object)); // symbol +static assert(__traits(compiles, 1, 2, 3, int, long)); +static assert(!__traits(compiles, 3[1])); // semantic error +static assert(!__traits(compiles, 1, 2, 3, int, long, 3[1])); + +enum n = 3; +// wrap a declaration/statement in a function literal +static assert(__traits(compiles, { int[n] arr; })); +static assert(!__traits(compiles, { foreach (e; n) {} })); + +struct S +{ + static int s1; + int s2; +} + +static assert(__traits(compiles, S.s1 = 0)); +static assert(!__traits(compiles, S.s2 = 0)); +static assert(!__traits(compiles, S.s3)); + +int foo(); + +static assert(__traits(compiles, foo)); +static assert(__traits(compiles, foo + 1)); // call foo with optional parens +static assert(!__traits(compiles, &foo + 1)); +--- +) + + $(P This is useful for:) + + $(UL + $(LI Giving better error messages (using $(DDSUBLINK spec/version, static-assert, + `static assert`)) inside generic code than + the sometimes hard to follow compiler ones.) + $(LI Doing a finer grained specialization than template + partial specialization allows for.) + ) + +$(SPEC_SUBNAV_PREV_NEXT version, Conditional Compilation, errors, Error Handling) + +Macros: + CHAPTER=26 + TITLE=Traits diff --git a/spec/type.dd b/spec/type.dd new file mode 100644 index 0000000000..1dbef6d3bb --- /dev/null +++ b/spec/type.dd @@ -0,0 +1,984 @@ +Ddoc + +$(SPEC_S Types, + +$(HEADERNAV_TOC) + +$(H2 $(LNAME2 grammar, Grammar)) + + $(P D is statically typed. Every expression has a type. Types constrain the values + an expression can hold, and determine the semantics of operations on those values. + ) + +$(GRAMMAR +$(GNAME Type): + $(GLINK TypeCtors)$(OPT) $(GLINK BasicType) $(GLINK TypeSuffixes)$(OPT) + +$(GNAME TypeCtors): + $(GLINK TypeCtor) + $(GLINK TypeCtor) $(GSELF TypeCtors) + +$(GNAME TypeCtor): + $(D const) + $(D immutable) + $(D inout) + $(D shared) + +$(GNAME BasicType): + $(GLINK FundamentalType) + $(D .) $(GLINK QualifiedIdentifier) + $(GLINK QualifiedIdentifier) + $(GLINK Typeof) + $(GLINK Typeof) $(D .) $(GLINK QualifiedIdentifier) + $(GLINK TypeCtor) $(D $(LPAREN)) $(GLINK Type) $(D $(RPAREN)) + $(GLINK Vector) + $(GLINK2 traits, TraitsExpression) + $(GLINK MixinType) + +$(GNAME Vector): + $(D __vector) $(D $(LPAREN)) $(GLINK VectorBaseType) $(D $(RPAREN)) + +$(GNAME VectorBaseType): + $(GLINK Type) + +$(GNAME FundamentalType): +$(MULTICOLS 5, + $(D bool) + $(D byte) + $(D ubyte) + $(D short) + $(D ushort) + $(D int) + $(D uint) + $(D long) + $(D ulong) + $(D cent) + $(D ucent) + $(D char) + $(D wchar) + $(D dchar) + $(D float) + $(D double) + $(D real) + $(D ifloat) + $(D idouble) + $(D ireal) + $(D cfloat) + $(D cdouble) + $(D creal) + $(D void)) + +$(GNAME TypeSuffixes): + $(GLINK TypeSuffix) $(GSELF TypeSuffixes)$(OPT) + +$(GNAME TypeSuffix): + $(D *) + $(D [ ]) + $(D [) $(GLINK2 expression, AssignExpression) $(D ]) + $(D [) $(GLINK2 expression, AssignExpression) $(D ..) $(GLINK2 expression, AssignExpression) $(D ]) + $(D [) $(GLINK Type) $(D ]) + $(D delegate) $(GLINK2 function, Parameters) $(GLINK2 function, MemberFunctionAttributes)$(OPT) + $(D function) $(GLINK2 function, Parameters) $(GLINK2 function, FunctionAttributes)$(OPT) + +$(GNAME QualifiedIdentifier): + $(GLINK_LEX Identifier) + $(GLINK_LEX Identifier) $(D .) $(GSELF QualifiedIdentifier) + $(GLINK2 template, TemplateInstance) + $(GLINK2 template, TemplateInstance) $(D .) $(GSELF QualifiedIdentifier) + $(GLINK_LEX Identifier) $(D [) $(GLINK2 expression, AssignExpression) $(D]) + $(GLINK_LEX Identifier) $(D [) $(GLINK2 expression, AssignExpression) $(D] .) $(GSELF QualifiedIdentifier) +) + + * $(RELATIVE_LINK2 basic-data-types, Basic Data Types) are leaf types. + * $(RELATIVE_LINK2 derived-data-types, Derived Data Types) build on leaf types. + * $(RELATIVE_LINK2 user-defined-types, User-Defined Types) are aggregates of basic and derived types. + +$(H2 $(LEGACY_LNAME2 Basic Data Types, basic-data-types, Basic Data Types)) + + $(TABLE_3COLS Basic Data Types, + $(THEAD Keyword, Default Initializer ($(D .init)), Description) + $(TROW $(RELATIVE_LINK2 void, $(D void)), no default initializer, `void` has no value) + $(TROW $(RELATIVE_LINK2 bool, $(D bool)), $(D false), boolean value) + $(TROW $(D byte), $(D 0), signed 8 bits) + $(TROW $(D ubyte), $(D 0u), unsigned 8 bits) + $(TROW $(D short), $(D 0), signed 16 bits) + $(TROW $(D ushort), $(D 0u), unsigned 16 bits) + $(TROW $(D int), $(D 0), signed 32 bits) + $(TROW $(D uint), $(D 0u), unsigned 32 bits) + $(TROW $(D long), $(D 0L), signed 64 bits) + $(TROW $(D ulong), $(D 0uL), unsigned 64 bits) + $(TROW $(GDEPRECATED $(D cent)), $(D 0), signed 128 bits) + $(TROW $(GDEPRECATED $(D ucent)), $(D 0u), unsigned 128 bits) + $(TROW $(D float), $(D float.nan), 32 bit floating point) + $(TROW $(D double), $(D double.nan), 64 bit floating point) + $(TROW $(D real), $(D real.nan), largest floating point size available) + $(TROW $(GDEPRECATED $(D ifloat)), $(D float.nan*1.0i), imaginary float) + $(TROW $(GDEPRECATED $(D idouble)), $(D double.nan*1.0i), imaginary double) + $(TROW $(GDEPRECATED $(D ireal)), $(D real.nan*1.0i), imaginary real) + $(TROW $(GDEPRECATED $(D cfloat)), $(D float.nan+float.nan*1.0i), a complex number of two float values) + $(TROW $(GDEPRECATED $(D cdouble)), $(D double.nan+double.nan*1.0i), complex double) + $(TROW $(GDEPRECATED $(D creal)), $(D real.nan+real.nan*1.0i), complex real) + $(TROW $(D char), $(D '\xFF'), unsigned 8 bit (UTF-8 code unit)) + $(TROW $(D wchar), $(D '\uFFFF'), unsigned 16 bit (UTF-16 code unit)) + $(TROW $(D dchar), $(D '\U0000FFFF'), unsigned 32 bit (UTF-32 code unit)) + ) + + $(P Endianness of basic types is part of the $(DDSUBLINK spec/abi, endianness, ABI)) + + $(IMPLEMENTATION_DEFINED The real floating point type has at least the range and precision + of the `double` type. On x86 CPUs it is often implemented as the 80 bit Extended Real + type supported by the x86 FPU. + ) + + $(NOTE 128-bit integer types `cent` and `ucent` + $(DDSUBLINK deprecate, 128-bit integer types, have been deprecated).) + + $(NOTE Complex and imaginary types `ifloat`, `idouble`, `ireal`, `cfloat`, `cdouble`, + and `creal` $(DDSUBLINK deprecate, Imaginary and complex types, + have been deprecated) in favor of `std.complex.Complex`.) + +$(H2 $(LEGACY_LNAME2 Derived Data Types, derived-data-types, Derived Data Types)) + + $(UL + $(LI Pointers) + $(LI $(DDSUBLINK spec/arrays, static-arrays, Static Arrays)) + $(LI $(DDSUBLINK spec/arrays, dynamic-arrays, Dynamic Arrays)) + $(LI $(DDLINK spec/hash-map, Associative Array, Associative Arrays)) + $(LI $(RELATIVE_LINK2 functions, Function Types)) + $(LI $(RELATIVE_LINK2 delegates, Delegate Types)) + $(LI $(DDSUBLINK spec/template, homogeneous_sequences, Type Sequences)) + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +int* p; // pointer +int[2] sa; // static array +int[] da; // dynamic array/slice + +int[string] aa; // associative array +void function() fp; // function pointer + +import std.meta : AliasSeq; +AliasSeq!(int, string) tsi; // type sequence instance +--- +) + +$(H3 $(LNAME2 pointers, Pointers)) + + $(P A pointer value is a memory address. + A pointer to type $(D T) has a value which is a reference to an + instance of type $(D T). It is commonly called a $(I pointer to T) and its type is + `T*`. To access the pointed-to value, use the `*` dereference operator: + ) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int* p; + +assert(p == null); +p = new int(5); +assert(p != null); + +assert(*p == 5); +(*p)++; +assert(*p == 6); +--------- +) + + $(P If a pointer has a $(I null) value, it is not pointing to valid data.) + + $(P When a pointer to $(I T) is dereferenced, it must either have a $(I null) value, + or point to a valid instance of type $(I T).) + + $(IMPLEMENTATION_DEFINED + $(OL + $(LI The behavior when a $(I null) pointer is dereferenced. Typically the program + will be aborted - $(DDSUBLINK spec/function, null-dereferences, that is required) + in `@safe` code.) + )) + + $(UNDEFINED_BEHAVIOR dereferencing a pointer that is not $(I null) and does not point + to a valid instance of type $(I T).) + + $(P To set a pointer to point at an existing $(DDSUBLINK spec/expression, .define-lvalue, lvalue), use the + `&` *address of* operator:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--------- +int i = 2; +int* p = &i; + +assert(p == &i); +assert(*p == 2); +*p = 4; +assert(i == 4); +--------- +) + $(P See also:) + * $(DDSUBLINK spec/expression, pointer_arithmetic, Pointer Arithmetic) + * $(DDSUBLINK spec/expression, slice_expressions, Pointer Slicing) + * $(RELATIVE_LINK2 pointer-conversions, Pointer Conversions) + + $(BEST_PRACTICE Use a $(DDSUBLINK spec/function, ref-params, + `ref` function parameter) or a $(DDSUBLINK spec/declaration, ref-variables, + `ref` local variable) when the address doesn't escape.) + + +$(H2 $(LEGACY_LNAME2 User Defined Types, user-defined-types, User-Defined Types)) + + $(UL + $(LI $(DDLINK spec/enum, Enums, Enums)) + $(LI $(DDLINK spec/struct, Structs and Unions, Structs and Unions)) + $(LI $(DDLINK spec/class, Classes, Classes)) + $(LI $(DDLINK spec/interface, Interfaces, Interfaces)) + ) + +$(H2 $(LNAME2 type-conversions, Type Conversions)) + + See also: $(GLINK2 expression, CastExpression). + +$(H3 $(LEGACY_LNAME2 Pointer Conversions, pointer-conversions, Pointer Conversions)) + + $(P Any $(RELATIVE_LINK2 pointers, pointer) implicitly converts to a `void` pointer - + see below.) + + $(P Casting between pointers and non-pointers is allowed. Some pointer casts + are disallowed in $(DDLINK spec/memory-safe-d, Memory-Safe-D-Spec, `@safe` code).) + + $(BEST_PRACTICE do not cast any pointer to a non-pointer type that points to data + allocated by the garbage collector. + ) + +$(H3 $(LEGACY_LNAME2 Implicit Conversions, implicit-conversions, Implicit Conversions)) + + $(P Implicit conversions are used to automatically convert + types as required. The rules for integers are detailed in the next sections. + ) + + $(UL + $(LI An enum can be $(DDSUBLINK spec/enum, named_enums, implicitly converted) to its base + type (but going the other way requires an explicit conversion).) + $(LI $(RELATIVE_LINK2 noreturn, `noreturn`) implicitly converts to any type.) + $(LI Static and dynamic arrays implicitly convert to $(DDSUBLINK spec/arrays, void_arrays, `void` arrays). + The `void` element type for the array may need a + $(DDLINK spec/const3, Type Qualifiers, type qualifier), depending on the source + element type: + ) + * An array with non-mutable elements will implicitly convert to `const(void)[]`, but not `void[]`. + * An array with `shared` elements will implicitly convert to `shared(void)[]`, but not `void[]`. + $(LI Any pointer implicitly converts to a void pointer. As for void arrays, the + `void` element type may need a type qualifier.) + $(LI $(DDSUBLINK spec/function, function-pointers-delegates, Function pointers and delegates) + can convert to covariant types.) + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +void main() +{ + noreturn n; + int i = n; + void* p = &i; + + const int[] a; + const(void)[] cv = a; + //void[] va = a; // error +} + +void f(int x) pure; +void function(int) fp = &f; // pure is covariant with non-pure +--- +) + $(P See also $(DDSUBLINK spec/const3, implicit_qualifier_conversions, + Implicit Qualifier Conversions).) + +$(H4 $(LNAME2 class-conversions, Class Conversions)) + + $(P A derived class can be implicitly converted to its base class, but going + the other way requires an explicit cast. For example:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------------------- +class Base {} +class Derived : Base {} +Base bd = new Derived(); // implicit conversion +Derived db = cast(Derived)new Base(); // explicit conversion +------------------- +) + + $(P A dynamic array, say `x`, of a derived class can be implicitly converted + to a dynamic array, say `y`, of a base class iff elements of `x` and `y` are + qualified as being either both `const` or both `immutable`.) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------------------- +class Base {} +class Derived : Base {} +const(Base)[] ca = (const(Derived)[]).init; // `const` elements +immutable(Base)[] ia = (immutable(Derived)[]).init; // `immutable` elements +------------------- +) + + $(P A static array, say `x`, of a derived class can be implicitly converted + to a static array, say `y`, of a base class iff elements of `x` and `y` are + qualified as being either both `const` or both `immutable` or both mutable + (neither `const` nor `immutable`).) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------------------- +class Base {} +class Derived : Base {} +Base[3] ma = (Derived[3]).init; // mutable elements +const(Base)[3] ca = (const(Derived)[3]).init; // `const` elements +immutable(Base)[3] ia = (immutable(Derived)[3]).init; // `immutable` elements +------------------- +) + +$(H3 $(LEGACY_LNAME2 Integer Promotions, integer-promotions, Integer Promotions)) + + $(P Integer Promotions are conversions of the following types: + ) + + $(TABLE2 Integer Promotions, + $(THEAD from, to) + $(TROW + $(ARGS $(D bool)), + $(ARGS $(D int)) + ) + $(TROW + $(ARGS $(D byte)), + $(ARGS $(D int)) + ) + $(TROW + $(ARGS $(D ubyte)), + $(ARGS $(D int)) + ) + $(TROW + $(ARGS $(D short)), + $(ARGS $(D int)) + ) + $(TROW + $(ARGS $(D ushort)), + $(ARGS $(D int)) + ) + $(TROW + $(ARGS $(D char)), + $(ARGS $(D int)) + ) + $(TROW + $(ARGS $(D wchar)), + $(ARGS $(D int)) + ) + $(TROW + $(ARGS $(D dchar)), + $(ARGS $(D uint)) + ) + ) + + $(P If an enum has as a base type one of the types + in the left column, it is converted to the type in the right + column. + ) + + $(P Integer promotion applies to each operand of a binary expression:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + void fun() + { + byte a; + auto b = a + a; + static assert(is(typeof(b) == int)); + // error: can't implicitly convert expression of type int to byte: + //byte c = a + a; + + ushort d; + // error: can't implicitly convert expression of type int to ushort: + //d = d * d; + int e = d * d; // OK + static assert(is(typeof(int() * d) == int)); + + dchar f; + static assert(is(typeof(f - f) == uint)); + } + --- + ) + + $(RATIONALE + * 32-bit integer operations are often faster than smaller integer types + for single variables on modern architectures. + * Promotion helps avoid accidental overflow which is more common with small integer types. + ) + +$(H3 $(LEGACY_LNAME2 Usual Arithmetic Conversions, usual-arithmetic-conversions, Usual Arithmetic Conversions)) + + $(P The usual arithmetic conversions convert operands of binary + operators to a common type. The operands must already be + of arithmetic types. + The following rules are applied + in order, looking at the base type: + ) + + $(OL + $(LI If either operand is `real`, the other operand is + converted to `real`.) + + $(LI Else if either operand is `double`, the other operand is + converted to `double`.) + + $(LI Else if either operand is `float`, the other operand is + converted to `float`.) + + $(LI Else the integer promotions above are done on each operand, + followed by: + + $(OL + $(LI If both are the same type, no more conversions are done.) + + $(LI If both are signed or both are unsigned, the + smaller type is converted to the larger.) + + $(LI If the signed type is larger than the unsigned + type, the unsigned type is converted to the signed type.) + + $(LI The signed type is converted to the unsigned type.) + ) + ) + ) + + $(RATIONALE The above rules follow C99, which makes porting code from C easier.) + + $(P $(B Example:) Signed and unsigned conversions:) + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + int i; + uint u; + static assert(is(typeof(i + u) == uint)); + static assert(is(typeof(short() + u) == uint)); + static assert(is(typeof(ulong() + i) == ulong)); + static assert(is(typeof(long() - u) == long)); + static assert(is(typeof(long() * ulong()) == ulong)); + --- + ) + + $(P $(B Example:) Floating point:) + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + float f; + static assert(is(typeof(f + ulong()) == float)); + + double d; + static assert(is(typeof(f * d) == double)); + static assert(is(typeof(real() / d) == real)); + --- + ) + +$(H4 $(LNAME2 enum-ops, Enum Operations)) + + $(P If one or both of the operand types is an $(DDLINK spec/enum, Enums, enum) after + undergoing the above conversions, the result type is determined as follows:) + + $(OL + $(LI If the operands are the same type, the result will be of + that type.) + $(LI If one operand is an enum and the other is the base type + of that enum, the result is the base type.) + $(LI If the two operands are different enums, + the result is the closest base type common to both. A base type being closer + means there is a shorter sequence of conversions to base type to get there from the + original type.) + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +enum E { a, b, c } +enum F { x, y } + +void test() +{ + E e = E.a; + e = e | E.c; + //e = e + 4; // error, can't assign int to E + int i = e + 4; + e += 4; // OK, see below + + F f; + //f = e | f; // error, can't assign int to F + i = e | f; +} +--- +) + + $(NOTE Above, `e += 4` compiles because the + $(DDSUBLINK spec/expression, assignment_operator_expressions, operator assignment) + is equivalent to `e = cast(E)(e + 4)`.) + +$(H3 $(LEGACY_LNAME2 disallowed-conversions, integer-conversions, Integer Type Conversions)) + + $(P An integer of type `I` implicitly converts to another integer type `J` when + `J.sizeof >= I.sizeof`.) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +void f(byte b, ubyte ub, short s) +{ + b = ub; // OK, bit pattern same + ub = b; // OK, bit pattern same + s = b; // OK, widening conversion + b = s; // error, implicit narrowing +} +--- +) + + $(P Integer values cannot be implicitly converted to another + type that cannot represent the integer bit pattern after + $(RELATIVE_LINK2 integer-promotions, integral promotion). For example:) + +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +ubyte u1 = -1; // error, -1 cannot be represented in a ubyte +ushort u2 = -1; // error, -1 cannot be represented in a ushort +uint u3 = -1; // ok, -1 can be represented in an int, which can be converted to a uint +ulong u4 = -1; // ok, -1 can be represented in a long, which can be converted to a ulong +--- +) + +$(H3 $(LNAME2 floating-point-conversions, Floating Point Type Conversions)) + + * Integral types implicitly convert to floating point types. + * Floating point types cannot be implicitly converted to integral types. + + $(SPEC_RUNNABLE_EXAMPLE_FAIL + --- + void f(int i, float f) + { + f = i; // OK + i = f; // error + } + --- + ) + + * Complex or imaginary floating point types cannot be implicitly converted + to non-complex floating point types. + * Non-complex floating point types cannot be implicitly converted to imaginary floating + point types. + +$(H3 $(LNAME2 vrp, Value Range Propagation)) + + $(P Besides type-based implicit conversions, D allows certain integer + expressions to implicitly convert to a narrower type after + integer promotion. This works by analysing the minimum and + maximum possible range of values for each expression. + If that range of values matches or is a subset of a narrower + target type's value range, implicit + conversion is allowed. If a subexpression is known at compile-time, + that can further narrow the range of values.) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + void fun(char c, int i, ubyte b) + { + // min is c.min + 100 > short.min + // max is c.max + 100 < short.max + short s = c + 100; // OK + + ubyte j = i & 0x3F; // OK, 0 ... 0x3F + //ubyte k = i & 0x14A; // error, 0x14A > ubyte.max + ushort k = i & 0x14A; // OK + + k = i & b; // OK, 0 ... b.max + //b = b + b; // error, b.max + b.max > b.max + s = b + b; // OK, 0 ... b.max + b.max + } + --- + ) + $(P Note the implementation does not track the range of possible values for + mutable variables:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + void fun(int i) + { + ushort s = i & 0xff; // OK + // s is now assumed to be s.min ... s.max, not 0 ... 0xff + //ubyte b = s; // error + ubyte b = s & 0xff; // OK + + const int c = i & 0xff; + // c's range is fixed and known + b = c; // OK + } + --- + ) + * For more information, see $(LINK2 https://digitalmars.com/articles/b62.html, the dmc article). + * See also: $(LINK https://en.wikipedia.org/wiki/Value_range_analysis). + + +$(H2 $(LNAME2 void, $(D void))) + + $(P A `void` value cannot be accessed directly. The `void` type is notably used for:) + + * The return type of a function that doesn't have a result. + * The base type for an untyped pointer - + see $(RELATIVE_LINK2 pointer-conversions, Pointer Conversions). + * $(DDSUBLINK spec/arrays, void_arrays, Void arrays). + * $(DDSUBLINK spec/expression, cast_void, Ignoring a value) by casting to `void`. + + $(P `void.sizeof` is 1 (not 0).) + + $(RATIONALE The size must be 1 to make `void*` arithmetic work like it does in C. + It also makes the length of a void array equivalent to the number of + bytes in the array.) + + +$(H2 $(LNAME2 bool, $(D bool))) + +$(P The bool type is a byte-size type that can only hold the value `true` or +`false`.) + +$(P The only operators that can accept operands of type bool are: $(CODE_AMP) +$(CODE_PIPE), $(D ^), $(CODE_AMP)$(D =), $(CODE_PIPE)$(D =), $(D ^=), !, +$(CODE_AMP)$(CODE_AMP), $(CODE_PIPE)$(CODE_PIPE), and $(D ?:).) + +$(P A `bool` value can be implicitly converted to any integral type, with +`false` becoming 0 and `true` becoming 1.) + +$(P The numeric literals `0` and `1` can be implicitly converted to the `bool` +values `false` and `true`, respectively. Casting an expression to `bool` means +testing `!=0` for arithmetic types, and `!=null` for +pointers or references.) + +$(UNDEFINED_BEHAVIOR) +* Interpreting a value with a byte representation + other than 0 or 1 as `bool` (e.g. an overlapped union field). +* Reading a `void`-initialized `bool`. + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +byte i = 2; +bool b = cast(bool) i; // OK, same as `i != 0` +assert(b); + +bool* p = cast(bool*) &i; // unsafe cast +// `*p` holds 0x2, an invalid bool value +// reading `*p` is undefined behavior +--- +) + +$(H2 $(LNAME2 functions, Function Types)) + +$(P A function type has the form:) + +$(GRAMMAR_INFORMATIVE +$(GLINK2 declaration, StorageClasses)$(OPT) $(GLINK Type) $(GLINK2 function, Parameters) $(GLINK2 function, FunctionAttributes)$(OPT) +) + +$(P Function types are not included in the $(GLINK Type) grammar. +A function type e.g. `int(int)` $(DDSUBLINK spec/declaration, alias-function, can be aliased). +A function type is only used for type tests or as the target type of a pointer.) + +$(P Instantiating a function type is illegal. Instead, a pointer to function +or delegate can be used. Those have these type forms respectively:) + +$(GRAMMAR_INFORMATIVE +$(GLINK Type) `function` $(GLINK2 function, Parameters) $(GLINK2 function, FunctionAttributes)$(OPT) +$(GLINK Type) `delegate` $(GLINK2 function, Parameters) $(GLINK2 function, MemberFunctionAttributes)$(OPT) +) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +void f(int); +alias Fun = void(int); +static assert(is(typeof(f) == Fun)); +static assert(is(Fun* == void function(int))); +--- +) + +$(P See $(DDSUBLINK spec/function, function-pointers, Function Pointers).) + +$(H3 $(LNAME2 delegates, Delegates)) + +$(P Delegates are an aggregate of two pieces of data, a *context pointer* and +a *function pointer*. A valid delegate holds either:) + +* An object reference and a pointer to a non-static + $(DDSUBLINK spec/class, member-functions, member function). + The object reference forms the `this` pointer when the function is called. +* A pointer to a $(DDSUBLINK spec/function, closures, closure) + and a pointer to a $(DDSUBLINK spec/function, nested, nested function). + +$(P The $(D .ptr) property of a delegate will return the +$(I context pointer) value as a $(D void*). +) + +$(P The $(D .funcptr) property of a delegate will return the +$(I function pointer) value as a function type. +) + +$(P Delegates are declared and initialized similarly to function pointers:) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +------------------- +void func(int) {} +void function(int) fp; // fp is a function pointer +void delegate(int) dg; // dg is a delegate to a function + +class OB +{ + void member(int) {} +} + +void main() +{ + OB o = new OB; + + fp = &func; // fp points to function `func` + + dg = &o.member; // dg is a delegate to object `o` and member function `member` + assert(dg.ptr == cast(void*) o); + assert(dg.funcptr == &OB.member); + + dg = (int i) { o.member(i); }; // dg holds a delegate literal with main's execution context +} +------------------- +) + + $(P Delegates cannot be initialized with static member functions + or non-member functions. + ) + + $(P Delegates are called analogously to function pointers: + ) + +------------------- +fp(3); // call func(3) +dg(3); // call o.member(3) +------------------- + + $(P See:) + + * $(DDSUBLINK spec/function, closures, Delegates and Closures) + * $(DDSUBLINK spec/function, method-delegates, Method Delegates) + + $(P The equivalent of member function pointers can be constructed + using $(DDSUBLINK spec/expression, function_literals, anonymous lambda functions):) + +$(SPEC_RUNNABLE_EXAMPLE_RUN +--- +class C +{ + int a; + int foo(int i) { return i + a; } +} + +// mfp is the member function pointer +auto mfp = function(C self, int i) { return self.foo(i); }; +auto c = new C(); // create an instance of C +mfp(c, 1); // and call c.foo(1) +--- +) + +$(H2 $(LNAME2 typeof, $(D typeof))) + +$(GRAMMAR +$(GNAME Typeof): + $(D typeof $(LPAREN)) $(GLINK2 expression, Expression) $(D $(RPAREN)) + $(D typeof $(LPAREN)) $(D return) $(D $(RPAREN)) +) + + $(P + The first form gives the type of an expression. + It can be used anywhere a $(GLINK BasicType) is expected, such as in a + declaration. It is also useful as a $(GLINK2 expression, PrimaryExpression) + in a sub-expression. For example: + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + -------------------- + void func(int i) + { + typeof(i) j; // j is of type int + typeof(3 + 6.0) x; // x is of type double + + // as part of a derived type: + typeof(1)* p; + static assert(is(typeof(p) == int*)); + typeof(p)[int] aa; + static assert(is(typeof(aa) == int*[int])); + + auto d = cast(typeof(1.0)) i; // cast i to double + static assert(is(typeof(d) == double)); + + // as a sub-expression: + static assert(typeof('c').sizeof == 1); // char.sizeof + Exception[2] sa; + Exception ex = new typeof(sa[0])("message"); // new Exception("message") + } + -------------------- + ) + + $(P + $(I Expression) is not evaluated, it is used purely to + generate the type: + ) + + $(SPEC_RUNNABLE_EXAMPLE_RUN + -------------------- + void main() + { + int i = 1; + typeof(++i) j; // j is declared to be an int, i is not incremented + assert(i == 1); + } + -------------------- + ) + + $(P If *Expression* is a + $(DDSUBLINK spec/template, variadic-templates, $(I ValueSeq)), `typeof` + will produce a *TypeSeq* containing the types of each element.) + + $(P `typeof(null)` is useful to get the type of the + $(DDSUBLINK spec/expression, null, `null`) literal.) + + $(BEST_PRACTICE $(I Typeof) is most useful in writing generic + template code.) + +$(H3 $(LNAME2 typeof-special, Special Cases)) + + $(OL + $(LI $(D typeof(return)) will, when inside a function scope, + give the return type of that function. + ) + $(LI $(LNAME2 typeof-this, $(D typeof(this))) will generate the type of what $(D this) + would be in a non-static member function, even if not in a member + function. + ) + $(LI Analogously, $(D typeof(super)) will generate the type of what + $(D super) would be in a non-static member function. + ) + + -------------------- + class A { } + + class B : A + { + typeof(this) x; // x is declared to be a B + typeof(super) y; // y is declared to be an A + } + + struct C + { + static typeof(this) z; // z is declared to be a C + + typeof(super) q; // error, no super struct for C + } + + typeof(this) r; // error, no enclosing struct or class + -------------------- + ) + + $(P If the expression is a $(DDSUBLINK spec/function, property-functions, + Property Function), $(D typeof) gives its return type. + ) + + -------------------- + struct S + { + @property int foo() { return 1; } + } + typeof(S.foo) n; // n is declared to be an int + -------------------- + + $(P If the expression is a $(DDLINK spec/template, Template, Template), + $(D typeof) gives the type $(D void). + ) + + -------------------- + template t {} + static assert(is(typeof(t) == void)); + -------------------- + + +$(H2 $(LNAME2 mixin_types, Mixin Types)) + +$(GRAMMAR +$(GNAME MixinType): + $(D mixin $(LPAREN)) $(GLINK2 expression, ArgumentList) $(D $(RPAREN)) +) + + $(P Each $(GLINK2 expression, AssignExpression) in the $(I ArgumentList) is + evaluated at compile time, and the result must be representable + as a string. + The resulting strings are concatenated to form a string. + The text contents of the string must be compilable as a valid + $(GLINK2 type, Type), and is compiled as such.) + + --- + void test(mixin("int")* p) // int* p + { + mixin("int")[] a; // int[] a; + mixin("int[]") b; // int[] b; + } + --- + + +$(H2 $(LNAME2 aliased-types, Aliased Types)) + +$(H3 $(LNAME2 size_t, $(D size_t))) + + $(P $(D size_t) is an alias to one of the unsigned integral basic types, + and represents a type that is large enough to represent an offset into + all addressable memory.) + +$(H3 $(LNAME2 ptrdiff_t, $(D ptrdiff_t))) + $(P $(D ptrdiff_t) is an alias to the signed integral basic type the same size as $(D size_t).) + +$(H3 $(LNAME2 string, $(D string))) + + $(P A $(DDSUBLINK spec/arrays, strings, $(I string) is a special case of an array.)) + +$(H3 $(LNAME2 noreturn, $(D noreturn))) + + $(P `noreturn` is the $(LINK2 https://en.wikipedia.org/wiki/Bottom_type, bottom type) + which can implicitly convert to any type, including `void`. + A value of type `noreturn` will never be produced and the compiler can + optimize such code accordingly.) + + $(P `noreturn.init` lowers to $(DDSUBLINK spec/expression, assert-ct, `assert(0)`).) + + $(P A function that $(DDSUBLINK spec/function, function-return-values, never returns) + has the return type `noreturn`. This can + occur due to e.g. an infinite loop or always throwing an exception. + A function returning type `noreturn` is covariant with a function returning any other type.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +noreturn abort(string message); + +int function(string) fp = &abort; // OK + +int example(int i) +{ + if (i < 0) + { + // abort does not return, so it doesn't need to produce an int + int val = abort("less than zero"); + } + // ternary expression's common type is still int + return i != 0 ? 1024 / i : abort("calculation went awry."); +} +--- +) + + $(P `noreturn` is defined as $(D typeof(*null)). This is because + dereferencing a null literal (typically) halts execution.) + + $(P See also: $(GLINK2 expression, ThrowExpression)) + + +$(SPEC_SUBNAV_PREV_NEXT declaration, Declarations, property, Properties) +) + +Macros: + CHAPTER=7 + TITLE=Types diff --git a/spec/unittest.dd b/spec/unittest.dd new file mode 100644 index 0000000000..a26f8e2232 --- /dev/null +++ b/spec/unittest.dd @@ -0,0 +1,237 @@ +Ddoc + +$(SPEC_S Unit Tests, + +$(HEADERNAV_TOC) + +$(GRAMMAR +$(GNAME UnitTest): + $(D unittest) $(GLINK2 statement, BlockStatement) +) + $(P Unit tests are a builtin framework of test cases + applied to a module to determine if it is working properly. + A D program can be run with unit tests enabled or disabled. + ) + + $(P Unit tests are a special function defined like:) + + --- + unittest + { + ...test code... + } + --- + + $(P Individual tests are specified in the unit test using $(DDSUBLINK spec/expression, AssertExpression, AssertExpressions). + Unlike $(I AssertExpression)s used elsewhere, the assert is not assumed to hold, and upon assert + failure the program is still in a defined state. + ) + + $(P There can be any number of unit test functions in a module, + including within struct, union and class declarations. + They are executed in lexical order. + ) + + $(P Unit tests, when enabled, are run after all static initialization is + complete and before the $(D main()) function is called. + ) + + $(P For example, given a class $(D Sum) that is used to add two values, a unit + test can be given:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + class Sum + { + int add(int x, int y) { return x + y; } + + unittest + { + Sum sum = new Sum; + assert(sum.add(3,4) == 7); + assert(sum.add(-2,0) == -2); + } + } + --- + ) + + $(P When unit tests are enabled, the $(DDSUBLINK spec/version, PredefinedVersions, version identifier) + $(D unittest) is predefined. + ) + + +$(H2 $(LNAME2 attributes_unittest, Attributed Unittests)) + + $(P A unittest may be attributed with any of the global function attributes. + Such unittests are useful in verifying the given attribute(s) on a template + function:) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + --- + void myFunc(T)(T[] data) + { + if (data.length > 2) + data[0] = data[1]; + } + + @safe nothrow unittest + { + auto arr = [1,2,3]; + myFunc(arr); + assert(arr == [2,2,3]); + } + --- + ) + + $(P This unittest verifies that $(D myFunc) contains only $(D @safe), + `nothrow` code. Although this can also be accomplished by attaching these + attributes to $(D myFunc) itself, that would prevent $(D myFunc) from being + instantiated with types $(D T) that have $(D @system) or throwing code in their + $(D opAssign) method, or other methods that $(D myFunc) may call. The above + idiom allows $(D myFunc) to be instantiated with such types, yet at the same + time verify that the $(D @system) and throwing behavior is not introduced by + the code within $(D myFunc) itself.) + + $(IMPLEMENTATION_DEFINED + $(OL + $(LI If unit tests are not enabled, the implementation is not required to + check the $(GLINK UnitTest) for syntactic or semantic correctness. + This is to reduce the compile time impact of larger unit test sections. + The tokens must still be valid, and the implementation can merely count + $(D {) and $(D }) tokens to find the end of the $(GLINK UnitTest)'s $(GLINK2 statement, BlockStatement). + ) + $(LI The presentation of unit test results to the user.) + $(LI The method used to enable or disable the unit tests. Use of a compiler + switch such as $(DDSUBLINK dmd, switch-unittest, $(B -unittest)) to enable + them is suggested.) + $(LI The order in which modules are called to run their unit tests.) + $(LI Whether the program stops on the first unit test failure, or continues running the unit tests.) + ) + ) + + $(BEST_PRACTICE + $(OL + $(LI Using unit tests in conjunction with coverage testing + (such as $(DDSUBLINK dmd, switch-cov, $(B -cov))) + is effective.) + $(LI A unit test for a function should appear immediately + following it.) + ) + ) + + +$(H2 $(LNAME2 documented-unittests, Documented Unittests)) + +$(P Documented unittests allow the developer to deliver code examples to the user, + while at the same time automatically verifying that the examples are valid. This + avoids the frequent problem of having outdated documentation for some piece of code.) + +$(P If a declaration is followed by a documented unittest, the code in + the unittest will be inserted in the $(B example) section of the declaration:) + +------ +/// Math class +class Math +{ + /// add function + static int add(int x, int y) { return x + y; } + + /// + unittest + { + assert(add(2, 2) == 4); + } +} + +/// +unittest +{ + auto math = new Math(); + auto result = math.add(2, 2); +} +------ + +$(P The above will generate the following documentation:) + +$(RAWHTML +<dl><dt><big><a name="Math"></a>class <u>Math</u>; +</big></dt> +<dd><u>Math</u> class<br><br> +<b>Example:</b><pre class="d_code"><font color="blue">auto</font> math = <font color="blue">new</font> <u>Math</u>; +<font color="blue">auto</font> result = math.add(2, 2); +</pre><br> +<dl><dt><big><a name="Math.add"></a>int <u>add</u>(int <i>x</i>, int <i>y</i>); +</big></dt> +<dd><u>add</u> function<br><br> +<b>Example:</b><pre class="d_code"><font color="blue">assert</font>(<u>add</u>(2, 2) == 4); +</pre> +</dd> +</dl> +</dd> +</dl> +) + +$(P A unittest which is not documented, or is marked as private will not be + used to generate code samples.) + +$(P There can be multiple documented unittests and they can appear + in any order. They will be attached to the last non-unittest declaration:) + +------ +/// add function +int add(int x, int y) { return x + y; } + +/// code sample generated +unittest +{ + assert(add(1, 1) == 2); +} + +/// code sample not generated because the unittest is private +private unittest +{ + assert(add(2, 2) == 4); +} + +unittest +{ + /// code sample not generated because the unittest isn't documented + assert(add(3, 3) == 6); +} + +/// code sample generated, even if it only includes comments (or is empty) +unittest +{ + /** assert(add(4, 4) == 8); */ +} +------ + +$(P The above will generate the following documentation:) + +$(RAWHTML +<dl><dt><big><a name="add"></a>int <u>add</u>(int <i>x</i>, int <i>y</i>); +</big></dt> +<dd><u>add</u> function<br><br> +<b>Examples:</b><br> +code sample generated +<pre class="d_code"> +<font color="blue">assert</font>(<u>add</u>(1, 1) == 2); +</pre> +<br><br><b>Examples:</b><br> +code sample generated, even if it is empty or only includes comments +<pre class="d_code"> +<font color="green">/** assert(add(4, 4) == 8); */</font> +</pre> +<br><br> +</dd> +</dl> +) + + +$(SPEC_SUBNAV_PREV_NEXT errors, Error Handling, garbage, Garbage Collection) +) + +Macros: + CHAPTER=28 + TITLE=Unit Tests + _= diff --git a/spec/version.dd b/spec/version.dd new file mode 100644 index 0000000000..baaddfdef8 --- /dev/null +++ b/spec/version.dd @@ -0,0 +1,812 @@ +Ddoc + +$(SPEC_S Conditional Compilation, + +$(HEADERNAV_TOC) + + $(P $(I Conditional compilation) is the process of selecting which + code to compile and which code to not compile. + ) + +$(GRAMMAR +$(GNAME ConditionalDeclaration): + $(GLINK Condition) $(GLINK2 attribute, DeclarationBlock) + $(GLINK Condition) $(GLINK2 attribute, DeclarationBlock) $(D else) $(GLINK2 attribute, DeclarationBlock) + $(GLINK Condition) $(D :) $(GLINK2 module, DeclDefs)$(OPT) + $(GLINK Condition) $(GLINK2 attribute, DeclarationBlock) $(D else) $(D :) $(GLINK2 module, DeclDefs)$(OPT) + +$(GNAME ConditionalStatement): + $(GLINK Condition) $(GLINK2 statement, NoScopeNonEmptyStatement) + $(GLINK Condition) $(GLINK2 statement, NoScopeNonEmptyStatement) $(D else) $(GLINK2 statement, NoScopeNonEmptyStatement) +) + + $(P If the $(GLINK Condition) is satisfied, then the following + $(I DeclarationBlock) or $(I Statement) is compiled in. + If it is not satisfied, the $(I DeclarationBlock) or $(I Statement) + after the optional $(CODE else) is compiled in. + ) + + $(P Any $(I DeclarationBlock) or $(I Statement) that is not + compiled in still must be syntactically correct. + ) + + $(P No new scope is introduced, even if the + $(I DeclarationBlock) or $(I Statement) + is enclosed by $(CODE { }). + ) + + $(P $(I ConditionalDeclaration)s and $(I ConditionalStatement)s + can be nested. + ) + + $(P The $(GLINK StaticAssert) can be used + to issue errors at compilation time for branches of the conditional + compilation that are errors. + ) + + $(P $(I Condition) comes in the following forms: + ) + +$(GRAMMAR +$(GNAME Condition): + $(GLINK VersionCondition) + $(GLINK DebugCondition) + $(GLINK StaticIfCondition) +) + +$(H2 $(LNAME2 version, Version Condition)) + +$(GRAMMAR +$(GNAME VersionCondition): + $(D version $(LPAREN)) $(GLINK_LEX Identifier) $(D $(RPAREN)) + $(D version $(LPAREN)) $(D unittest) $(D $(RPAREN)) + $(D version $(LPAREN)) $(D assert) $(D $(RPAREN)) +) + + $(P Versions enable multiple versions of a module to be implemented + with a single source file. + ) + + $(P The $(I VersionCondition) is satisfied if $(I Identifier) + matches a $(I version identifier). + ) + + $(P The $(I version identifier) can be set on the command line + by the $(D -version) switch or in the module itself with a + $(GLINK VersionSpecification), or they can be predefined + by the compiler. + ) + + $(P Version identifiers are in their own unique name space, they do + not conflict with debug identifiers or other symbols in the module. + Version identifiers defined in one module have no influence + over other imported modules. + ) + +------ +int k; +version (Demo) // compile in this code block for the demo version +{ + int i; + int k; // error, k already defined + + i = 3; +} +x = i; // uses the i declared above +------ + +------ +version (X86) +{ + ... // implement custom inline assembler version +} +else +{ + ... // use default, but slow, version +} +------ + + $(P The $(D version(unittest)) is satisfied if and only if the code is + compiled with unit tests enabled (the $(DDSUBLINK dmd, switch-unittest, $(TT -unittest)) option on $(TT dmd)). + ) + + +$(H2 $(LEGACY_LNAME2 VersionSpecification, version-specification, Version Specification)) + +$(GRAMMAR +$(GNAME VersionSpecification): + $(D version =) $(GLINK_LEX Identifier) $(D ;) +) + + $(P The version specification makes it straightforward to group + a set of features under one major version, for example: + ) + +------ +version (ProfessionalEdition) +{ + version = FeatureA; + version = FeatureB; + version = FeatureC; +} +version (HomeEdition) +{ + version = FeatureA; +} +... +version (FeatureB) +{ + ... implement Feature B ... +} +------ + + $(P Version identifiers or levels may not be forward referenced: + ) + +------ +version (Foo) +{ + int x; +} +version = Foo; // error, Foo already used +------ + $(P $(I VersionSpecification)s may only appear at module scope.) + + $(P While the debug and version conditions superficially behave the + same, + they are intended for very different purposes. Debug statements + are for adding debug code that is removed for the release version. + Version statements are to aid in portability and multiple release + versions. + ) + + $(P Here's an example of a $(I full) version as opposed to + a $(I demo) version:) + +------ +class Foo +{ + int a, b; + + version(full) + { + int extrafunctionality() + { + ... + return 1; // extra functionality is supported + } + } + else // demo + { + int extrafunctionality() + { + return 0; // extra functionality is not supported + } + } +} +------ + + $(P Various different version builds can be built with a parameter + to version: + ) + +------ + +version($(CODE_HIGHLIGHT identifier)) // add in version code if version + // keyword is identifier +{ + ... version code ... +} +------ + + $(P This is presumably set by the command line as + $(D -version=identifier). + ) + + +$(H3 $(LEGACY_LNAME2 PredefinedVersions, predefined-versions, Predefined Versions)) + + $(P Several environmental version identifiers and identifier + name spaces are predefined for consistent usage. + Version identifiers do not conflict + with other identifiers in the code, they are in a separate name space. + Predefined version identifiers are global, i.e. they apply to + all modules being compiled and imported. + ) + + $(LONGTABLE_2COLS 0.6, Predefined Version Identifiers, + $(THEAD Version Identifier, Description), + + $(TROW *Host Compiler*) + $(TROW $(ARGS $(D DigitalMars)) , $(ARGS DMD (Digital Mars D))) + $(TROW $(ARGS $(D GNU)) , $(ARGS GDC (GNU D Compiler))) + $(TROW $(ARGS $(D LDC)) , $(ARGS LDC (LLVM D Compiler))) + $(TROW $(ARGS $(D SDC)) , $(ARGS SDC (Snazzy D Compiler))) + + $(TROW *Target Operating System*) + $(TROW $(ARGS $(D Windows)) , $(ARGS Microsoft Windows systems Win32 and Win64)) + $(TROW $(ARGS $(D Win32)) , $(ARGS Microsoft 32-bit Windows systems)) + $(TROW $(ARGS $(D Win64)) , $(ARGS Microsoft 64-bit Windows systems)) + $(TROW $(ARGS $(D linux)) , $(ARGS All Linux systems)) + $(TROW $(ARGS $(D Apple)) , $(ARGS Apple systems OSX, iOS, TVOS, WatchOS and VisionOS)) + $(TROW $(ARGS $(D OSX)) , $(ARGS macOS)) + $(TROW $(ARGS $(D iOS)) , $(ARGS iOS)) + $(TROW $(ARGS $(D TVOS)) , $(ARGS tvOS)) + $(TROW $(ARGS $(D WatchOS)) , $(ARGS watchOS)) + $(TROW $(ARGS $(D VisionOS)) , $(ARGS visionOS)) + $(TROW $(ARGS $(D FreeBSD)) , $(ARGS FreeBSD)) + $(TROW $(ARGS $(D OpenBSD)) , $(ARGS OpenBSD)) + $(TROW $(ARGS $(D NetBSD)) , $(ARGS NetBSD)) + $(TROW $(ARGS $(D DragonFlyBSD)) , $(ARGS DragonFlyBSD)) + $(TROW $(ARGS $(D BSD)) , $(ARGS All other BSDs)) + $(TROW $(ARGS $(D Solaris)) , $(ARGS Solaris)) + $(TROW $(ARGS $(D Posix)) , $(ARGS All POSIX systems (includes Linux, FreeBSD, OS X, Solaris, etc.))) + $(TROW $(ARGS $(D AIX)) , $(ARGS IBM Advanced Interactive eXecutive OS)) + $(TROW $(ARGS $(D Haiku)) , $(ARGS The Haiku operating system)) + $(TROW $(ARGS $(D SkyOS)) , $(ARGS The SkyOS operating system)) + $(TROW $(ARGS $(D SysV3)) , $(ARGS System V Release 3)) + $(TROW $(ARGS $(D SysV4)) , $(ARGS System V Release 4)) + $(TROW $(ARGS $(D Hurd)) , $(ARGS GNU Hurd)) + $(TROW $(ARGS $(D Android)) , $(ARGS The Android platform)) + $(TROW $(ARGS $(D Emscripten)) , $(ARGS The Emscripten platform)) + $(TROW $(ARGS $(D PlayStation)) , $(ARGS The PlayStation platform)) + $(TROW $(ARGS $(D PlayStation4)) , $(ARGS The PlayStation 4 platform)) + $(TROW $(ARGS $(D FreeStanding)) , $(ARGS An environment without an operating system (such as Bare-metal targets))) + + $(TROW *Target Environment*) + $(TROW $(ARGS $(D Cygwin)) , $(ARGS The Cygwin environment)) + $(TROW $(ARGS $(D MinGW)) , $(ARGS The MinGW environment)) + $(TROW $(ARGS $(D CRuntime_Bionic)) , $(ARGS Bionic C runtime)) + $(TROW $(ARGS $(D CRuntime_DigitalMars)) , $(ARGS DigitalMars C runtime)) + $(TROW $(ARGS $(D CRuntime_Glibc)) , $(ARGS Glibc C runtime)) + $(TROW $(ARGS $(D CRuntime_Microsoft)) , $(ARGS Microsoft C runtime)) + $(TROW $(ARGS $(D CRuntime_Musl)) , $(ARGS musl C runtime)) + $(TROW $(ARGS $(D CRuntime_Newlib)) , $(ARGS newlib C runtime)) + $(TROW $(ARGS $(D CRuntime_UClibc)) , $(ARGS uClibc C runtime)) + $(TROW $(ARGS $(D CRuntime_WASI)) , $(ARGS WASI C runtime)) + $(TROW $(ARGS $(D CppRuntime_Clang)) , $(ARGS Deprecated, use $(D CppRuntime_LLVM) instead)) + $(TROW $(ARGS $(D CppRuntime_DigitalMars)) , $(ARGS DigitalMars C++ runtime)) + $(TROW $(ARGS $(D CppRuntime_Gcc)) , $(ARGS Deprecated, use $(D CppRuntime_GNU) instead)) + $(TROW $(ARGS $(D CppRuntime_LLVM)) , $(ARGS LLVM libc++ C++ runtime)) + $(TROW $(ARGS $(D CppRuntime_GNU)) , $(ARGS GNU libstdc++ C++ runtime)) + $(TROW $(ARGS $(D CppRuntime_Microsoft)) , $(ARGS Microsoft C++ runtime)) + $(TROW $(ARGS $(D CppRuntime_Sun)) , $(ARGS Sun C++ runtime)) + + $(TROW *Target CPU and Instruction Set*) + $(TROW $(ARGS $(D X86)) , $(ARGS Intel and AMD 32-bit processors)) + $(TROW $(ARGS $(D X86_64)) , $(ARGS Intel and AMD 64-bit processors)) + $(TROW $(ARGS $(D ARM)) , $(ARGS The ARM architecture (32-bit) (AArch32 et al))) + $(TROW $(ARGS $(D ARM_Thumb)) , $(ARGS ARM in any Thumb mode)) + $(TROW $(ARGS $(D ARM_SoftFloat)) , $(ARGS The ARM $(D soft) floating point ABI)) + $(TROW $(ARGS $(D ARM_SoftFP)) , $(ARGS The ARM $(D softfp) floating point ABI)) + $(TROW $(ARGS $(D ARM_HardFloat)) , $(ARGS The ARM $(D hardfp) floating point ABI)) + $(TROW $(ARGS $(D AArch64)) , $(ARGS The Advanced RISC Machine architecture (64-bit))) + $(TROW $(ARGS $(D AsmJS)) , $(ARGS The asm.js intermediate programming language)) + $(TROW $(ARGS $(D AVR)) , $(ARGS 8-bit Atmel AVR Microcontrollers)) + $(TROW $(ARGS $(D Epiphany)) , $(ARGS The Epiphany architecture)) + $(TROW $(ARGS $(D PPC)) , $(ARGS The PowerPC architecture, 32-bit)) + $(TROW $(ARGS $(D PPC_SoftFloat)) , $(ARGS The PowerPC soft float ABI)) + $(TROW $(ARGS $(D PPC_HardFloat)) , $(ARGS The PowerPC hard float ABI)) + $(TROW $(ARGS $(D PPC64)) , $(ARGS The PowerPC architecture, 64-bit)) + $(TROW $(ARGS $(D IA64)) , $(ARGS The Itanium architecture (64-bit))) + $(TROW $(ARGS $(D MIPS32)) , $(ARGS The MIPS architecture, 32-bit)) + $(TROW $(ARGS $(D MIPS64)) , $(ARGS The MIPS architecture, 64-bit)) + $(TROW $(ARGS $(D MIPS_O32)) , $(ARGS The MIPS O32 ABI)) + $(TROW $(ARGS $(D MIPS_N32)) , $(ARGS The MIPS N32 ABI)) + $(TROW $(ARGS $(D MIPS_O64)) , $(ARGS The MIPS O64 ABI)) + $(TROW $(ARGS $(D MIPS_N64)) , $(ARGS The MIPS N64 ABI)) + $(TROW $(ARGS $(D MIPS_EABI)) , $(ARGS The MIPS EABI)) + $(TROW $(ARGS $(D MIPS_SoftFloat)) , $(ARGS The MIPS $(D soft-float) ABI)) + $(TROW $(ARGS $(D MIPS_HardFloat)) , $(ARGS The MIPS $(D hard-float) ABI)) + $(TROW $(ARGS $(D MSP430)) , $(ARGS The MSP430 architecture)) + $(TROW $(ARGS $(D NVPTX)) , $(ARGS The Nvidia Parallel Thread Execution (PTX) architecture, 32-bit)) + $(TROW $(ARGS $(D NVPTX64)) , $(ARGS The Nvidia Parallel Thread Execution (PTX) architecture, 64-bit)) + $(TROW $(ARGS $(D RISCV32)) , $(ARGS The RISC-V architecture, 32-bit)) + $(TROW $(ARGS $(D RISCV64)) , $(ARGS The RISC-V architecture, 64-bit)) + $(TROW $(ARGS $(D SPARC)) , $(ARGS The SPARC architecture, 32-bit)) + $(TROW $(ARGS $(D SPARC_V8Plus)) , $(ARGS The SPARC v8+ ABI)) + $(TROW $(ARGS $(D SPARC_SoftFloat)) , $(ARGS The SPARC soft float ABI)) + $(TROW $(ARGS $(D SPARC_HardFloat)) , $(ARGS The SPARC hard float ABI)) + $(TROW $(ARGS $(D SPARC64)) , $(ARGS The SPARC architecture, 64-bit)) + $(TROW $(ARGS $(D S390)) , $(ARGS The System/390 architecture, 32-bit)) + $(TROW $(ARGS $(D SystemZ)) , $(ARGS The System Z architecture, 64-bit)) + $(TROW $(ARGS $(D HPPA)) , $(ARGS The HP PA-RISC architecture, 32-bit)) + $(TROW $(ARGS $(D HPPA64)) , $(ARGS The HP PA-RISC architecture, 64-bit)) + $(TROW $(ARGS $(D SH)) , $(ARGS The SuperH architecture, 32-bit)) + $(TROW $(ARGS $(D WebAssembly)) , $(ARGS The WebAssembly virtual ISA $(LPAREN)instruction set architecture$(RPAREN), 32-bit)) + $(TROW $(ARGS $(D WASI)) , $(ARGS The WebAssembly System Interface)) + $(TROW $(ARGS $(D Xtensa)) , $(ARGS The Xtensa Architecture, 32-bit)) + $(TROW $(ARGS $(D Alpha)) , $(ARGS The Alpha architecture)) + $(TROW $(ARGS $(D Alpha_SoftFloat)) , $(ARGS The Alpha soft float ABI)) + $(TROW $(ARGS $(D Alpha_HardFloat)) , $(ARGS The Alpha hard float ABI)) + + $(TROW *Byte Order (endianess)*) + $(TROW $(ARGS $(D LittleEndian)) , $(ARGS Byte order, least significant first)) + $(TROW $(ARGS $(D BigEndian)) , $(ARGS Byte order, most significant first)) + + $(TROW *Executable and Link Format*) + $(TROW $(ARGS $(D ELFv1)) , $(ARGS Elf version 1)) + $(TROW $(ARGS $(D ELFv2)) , $(ARGS Elf version 2)) + + $(TROW *Miscellaneous*) + $(TROW $(ARGS $(D D_BetterC)) , $(ARGS $(DDLINK spec/betterc, D as Better C, D as Better C) code + (command line switch $(DDSUBLINK dmd, switch-betterC, $(TT -betterC))) is being generated)) + $(TROW $(ARGS $(D D_Exceptions)) , $(ARGS Exception handling is supported. Evaluates to `false` when compiling with + command line switch $(DDSUBLINK dmd, switch-betterC, $(TT -betterC)))) + $(TROW $(ARGS $(D D_ModuleInfo)) , $(ARGS $(DDSUBLINK abi, ModuleInfo, $(TT ModuleInfo)) is supported. Evaluates to `false` when compiling with + command line switch $(DDSUBLINK dmd, switch-betterC, $(TT -betterC)))) + $(TROW $(ARGS $(D D_TypeInfo)) , $(ARGS Runtime type information (a.k.a `TypeInfo`) is supported. Evaluates to `false` when compiling with + command line switch $(DDSUBLINK dmd, switch-betterC, $(TT -betterC)))) + $(TROW $(ARGS $(D D_Coverage)) , $(ARGS $(DDLINK articles/code_coverage, Code coverage analysis, Code coverage analysis) instrumentation + (command line switch $(DDSUBLINK dmd, switch-cov, $(TT -cov))) is being generated)) + $(TROW $(ARGS $(D D_Ddoc)) , $(ARGS $(DDLINK spec/ddoc, Embedded Documentation, Ddoc) documentation + (command line switch $(DDSUBLINK dmd, switch-D, $(TT -D))) is being generated)) + $(TROW $(ARGS $(D D_InlineAsm_X86)) , $(ARGS $(DDLINK spec/iasm, Inline Assembler, Inline assembler) for X86 is implemented)) + $(TROW $(ARGS $(D D_InlineAsm_X86_64)) , $(ARGS $(DDLINK spec/iasm, Inline Assembler, Inline assembler) for X86-64 is implemented)) + $(TROW $(ARGS $(D D_LP64)) , $(ARGS $(B Pointers) are 64 bits + (command line switch $(DDSUBLINK dmd, switch-m64, $(TT -m64))). (Do not confuse this with C's LP64 model))) + $(TROW $(ARGS $(D D_X32)) , $(ARGS Pointers are 32 bits, but words are still 64 bits (x32 ABI) (This can be defined in parallel to $(D X86_64)))) + $(TROW $(ARGS $(D D_HardFloat)) , $(ARGS The target hardware has a floating-point unit)) + $(TROW $(ARGS $(D D_SoftFloat)) , $(ARGS The target hardware does not have a floating-point unit)) + $(TROW $(ARGS $(D D_PIC)) , $(ARGS Position Independent Code + (command line switch $(DDSUBLINK dmd-linux, switch-fPIC, $(TT -fPIC))) is being generated)) + $(TROW $(ARGS $(D D_PIE)) , $(ARGS Position Independent Executable + (command line switch $(DDSUBLINK dmd-linux, switch-fPIE, $(TT -fPIE))) is being generated)) + $(TROW $(ARGS $(D D_SIMD)) , $(ARGS $(DDLINK spec/simd, simd, Vector extensions) (via $(D __simd)) are supported)) + $(TROW $(ARGS $(D D_AVX)) , $(ARGS AVX Vector instructions are supported)) + $(TROW $(ARGS $(D D_AVX2)) , $(ARGS AVX2 Vector instructions are supported)) + $(TROW $(ARGS $(D D_Version2)) , $(ARGS This is a D version 2 compiler)) + $(TROW $(ARGS $(D D_NoBoundsChecks)) , $(ARGS Array bounds checks are disabled + (command line switch $(DDSUBLINK dmd, switch-boundscheck, $(TT -boundscheck=off))))) + $(TROW $(ARGS $(D D_ObjectiveC)) , $(ARGS The target supports interfacing with Objective-C)) + $(TROW $(ARGS $(D D_ProfileGC)) , $(ARGS GC allocations being profiled + (command line switch $(DDSUBLINK dmd, switch-profile, $(TT -profile=gc))))) + $(TROW $(ARGS $(D D_Optimized)) , $(ARGS Compiling with enabled optimizations + (command line switch $(DDSUBLINK dmd, switch-O, $(TT -O))))) + $(TROW $(ARGS $(D Core)) , $(ARGS Defined when building the standard runtime)) + $(TROW $(ARGS $(D Std)) , $(ARGS Defined when building the standard library)) + $(TROW $(ARGS $(D unittest)) , $(ARGS $(DDLINK spec/unittest, Unit Tests, Unit tests) are enabled + (command line switch $(DDSUBLINK dmd, switch-unittest, $(TT -unittest))))) + $(TROW $(ARGS $(D assert)) , $(ARGS Checks are being emitted for $(GLINK2 expression, AssertExpression)s)) + $(TROW $(ARGS $(D D_PreConditions)) , $(ARGS Checks are being emitted for $(DDSUBLINK spec/function, contracts, in contracts))) + $(TROW $(ARGS $(D D_PostConditions)) , $(ARGS Checks are being emitted for $(DDSUBLINK spec/function, contracts, out contracts))) + $(TROW $(ARGS $(D D_Invariants)) , $(ARGS Checks are being emitted for $(DDSUBLINK spec/class, invariants, class invariants) and $(DDSUBLINK spec/struct, Invariant, struct invariants))) + + $(TROW *Special Cases*) + $(TROW $(ARGS $(D none)) , $(ARGS Never defined; used to just disable a section of code)) + $(TROW $(ARGS $(D all)) , $(ARGS Always defined; used as the opposite of $(D none))) + ) + + $(P The following identifiers are defined, but are deprecated: + ) + + $(TABLE2 Predefined Version Identifiers (deprecated), + $(THEAD Version Identifier, Description) + $(TROW $(D darwin), The Darwin operating system; use $(D OSX) instead) + $(TROW $(D Thumb), ARM in Thumb mode; use $(D ARM_Thumb) instead) + $(TROW $(D S390X), The System/390X architecture$(COMMA) 64-bit; use $(D SystemZ) instead) + ) + + $(P Others will be added as they make sense and new implementations appear. + ) + + $(P To allow for future growth of the language, + the version identifier namespace beginning with "D$(UNDERSCORE)" + is reserved for identifiers indicating D language specification + or new feature conformance. Further, all identifiers derived from + the ones listed above by appending any character(s) are reserved. This + means that e.g. $(D ARM_foo) and $(D Windows_bar) are reserved while + $(D foo_ARM) and $(D bar_Windows) are not. + ) + + $(P Predefined version identifiers from this list cannot + be set from the command line or from version statements. + (This prevents things like both $(D Windows) and $(D linux) + being simultaneously set.) + ) + + $(P Compiler vendor specific versions can be predefined if the + trademarked vendor identifier prefixes it, as in: + ) + +------ +version(DigitalMars_funky_extension) +{ + ... +} +------ + + $(P It is important to use the right version identifier for the right + purpose. For example, use the vendor identifier when using a vendor + specific feature. Use the operating system identifier when using + an operating system specific feature, etc. + ) + + +$(H2 $(LNAME2 debug, Debug Condition)) + +$(GRAMMAR +$(GNAME DebugCondition): + $(D debug) + $(D debug $(LPAREN)) $(GLINK_LEX Identifier) $(D $(RPAREN)) +) + + $(P Two versions of programs are commonly built, + a release build and a debug build. + The debug build includes extra error checking code, + test harnesses, pretty-printing code, etc. + The debug statement conditionally compiles in its + statement body. + It is D's way of what in C is done + with $(CODE #ifdef DEBUG) / $(CODE #endif) pairs. + ) + + $(P The $(D debug) condition is satisfied when the $(D -debug) switch is + passed to the compiler. + ) + + $(P The $(D debug $(LPAREN)) $(I Identifier) $(D $(RPAREN)) condition is satisfied + when the debug identifier matches $(I Identifier). + ) + +------ +class Foo +{ + int a, b; +debug: + int flag; +} +------ + +$(H3 $(LNAME2 DebugStatement, Debug Statement)) + + $(P A $(GLINK ConditionalStatement) that has a $(GLINK DebugCondition) is called + a $(I DebugStatement). $(I DebugStatements) have relaxed semantic checks in that + `pure`, `@nogc`, `nothrow` and `@safe` checks are not done. + Neither do $(I DebugStatements) influence the inference of `pure`, `@nogc`, `nothrow` + and `@safe` attributes.) + + $(UNDEFINED_BEHAVIOR Since these checks are bypassed, it is up to the programmer + to ensure the code is correct. For example, throwing an exception in a `nothrow` + function is undefined behavior. + ) + + $(BEST_PRACTICE This enables the easy insertion of code to provide debugging help, + by bypassing the otherwise stringent attribute checks. + Never ship release code that has $(I DebugStatements) enabled. + ) + +$(H2 $(LNAME2 debug_specification, Debug Specification)) + +$(GRAMMAR +$(GNAME DebugSpecification): + $(D debug =) $(GLINK_LEX Identifier) $(D ;) +) + + $(P Debug identifiers are set either by the command line switch + $(D -debug) or by a $(I DebugSpecification). + ) + + $(P Debug specifications only affect the module they appear in, they + do not affect any imported modules. Debug identifiers are in their + own namespace, independent from version identifiers and other + symbols. + ) + + $(P It is illegal to forward reference a debug specification: + ) + +------ +debug(foo) writeln("Foo"); +debug = foo; // error, foo used before set +------ + + $(P $(I DebugSpecification)s may only appear at module scope.) + + $(P Various different debug builds can be built with a parameter to + debug: + ) + +------ +debug(identifier) { } // add in debug code if debug keyword is identifier +------ + + $(P These are presumably set by the command line as + and $(D -debug=)$(I identifier). + ) + +$(H2 $(LNAME2 staticif, Static If Condition)) + +$(GRAMMAR +$(GNAME StaticIfCondition): + $(D static if $(LPAREN)) $(ASSIGNEXPRESSION) $(D $(RPAREN)) +) + + $(P $(ASSIGNEXPRESSION) is implicitly converted to a boolean type, + and is evaluated at compile time. + The condition is satisfied if it evaluates to $(D true). + It is not satisfied if it evaluates to $(D false). + ) + + $(P It is an error if $(ASSIGNEXPRESSION) cannot be implicitly converted + to a boolean type or if it cannot be evaluated at compile time. + ) + + $(P $(I StaticIfCondition)s + can appear in module, class, template, struct, union, or function scope. + In function scope, the symbols referred to in the + $(ASSIGNEXPRESSION) can be any that can normally be referenced + by an expression at that point. + ) + +------ +const int i = 3; +int j = 4; + +$(CODE_HIGHLIGHT static if) (i == 3) // ok, at module scope + int x; + +class C +{ + const int k = 5; + + $(CODE_HIGHLIGHT static if) (i == 3) // ok + int x; + $(ARGS else) + long x; + + $(CODE_HIGHLIGHT static if) (j == 3) // error, j is not a constant + int y; + + $(CODE_HIGHLIGHT static if) (k == 5) // ok, k is in current scope + int z; +} +--- +$(SPEC_RUNNABLE_EXAMPLE_FAIL +--- +template Int(int i) +{ + $(ARGS static if) (i == 32) + alias Int = int; + $(ARGS else static if) (i == 16) + alias Int = short; + $(ARGS else) + static assert(0); // not supported +} + +Int!(32) a; // a is an int +Int!(16) b; // b is a short +Int!(17) c; // error, static assert trips +------ +) + + $(P A $(I StaticIfCondition) differs from an + $(I IfStatement) in the following ways: + ) + + $(OL + $(LI It can be used to conditionally compile declarations, + not just statements. + ) + $(LI It does not introduce a new scope even if $(D { }) + are used for conditionally compiled statements. + ) + $(LI For unsatisfied conditions, the conditionally compiled code + need only be syntactically correct. It does not have to be + semantically correct. + ) + $(LI It must be evaluatable at compile time. + ) + ) + +$(H2 $(LNAME2 staticforeach, Static Foreach)) + +$(GRAMMAR +$(GNAME StaticForeachDeclaration): + $(GLINK StaticForeach) $(GLINK2 attribute, DeclarationBlock) + $(GLINK StaticForeach) $(D :) $(GLINK2 module, DeclDefs)$(OPT) + +$(GNAME StaticForeachStatement): + $(GLINK StaticForeach) $(GLINK2 statement, NoScopeNonEmptyStatement) + +$(GNAME StaticForeach): + $(D static) $(GLINK2 statement, AggregateForeach) + $(D static) $(GLINK2 statement, RangeForeach) +) + + $(P `static foreach` expands its *DeclarationBlock* or *DeclDefs* into a + series of declarations, each of which may reference any + $(GLINK2 statement, ForeachType) symbols declared.) + + - The aggregate/range bounds are evaluated at compile time and + turned into a sequence of compile-time entities by evaluating + corresponding code with a $(GLINK2 statement, ForeachStatement)/$(GLINK2 statement, ForeachRangeStatement) + at compile time. + - The body of the $(D static foreach) is then copied a + number of times that corresponds to the number of elements of the + sequence. + - Within the i-th copy, the name of the $(D static foreach) element + 'variable' is bound to the i-th entry of the sequence, either as an $(D enum) + variable declaration (for constants) or an $(D alias) + declaration (for symbols). (In particular, $(D static foreach) + variables are never runtime variables.) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +static foreach (i; [0, 1, 2, 3]) +{ + pragma(msg, i); +} +------ +) + + $(P $(D static foreach) supports multiple $(GLINK2 statement, ForeachType) + variables in cases where the + corresponding $(D foreach) statement supports them. (In this case, + $(D static foreach) generates a compile-time sequence of tuples, and the + tuples are subsequently unpacked during iteration). + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +static foreach (i, v; ['a', 'b', 'c', 'd']) +{ + static assert(i + 'a' == v); +} +------ +) + + $(P Like bodies of $(GLINK ConditionalDeclaration)s, a $(D static foreach) + body does not introduce a new scope. Therefore, it can be + used to add declarations to an existing scope: + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------ +import std.range : iota; + +static foreach (i; iota(0, 3)) +{ + mixin(`enum x`, i, ` = i;`); +} + +pragma(msg, x0, " ", x1," ", x2); // 0 1 2 +------ +) + + $(P Inside a function, if a new scope is desired for each expansion, + use another set of braces:) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +void fun() +{ + static foreach (s; ["hi", "hey", "hello"]) + {{ + enum len = s.length; // local to each iteration + static assert(len <= 5); + }} + + static assert(!is(typeof(len))); +} +--- +) + + $(P `static foreach` supports sequence expansion + $(DDSUBLINK spec/statement, foreach_over_tuples, like `foreach`).) + +$(H3 $(LNAME2 break-continue, `break` and `continue`)) + + $(P As $(D static foreach) is a code generation construct and not a + loop, $(D break) and $(D continue) cannot be used to change control + flow within it. Instead of breaking or continuing a suitable enclosing + statement, such an usage yields an error (this is to prevent + misunderstandings). + ) + +------- +int test(int x) +{ + int r = -1; + switch(x) + { + static foreach (i; 0 .. 5) + { + case i: + r = i; + break; // error + } + default: break; + } + return r; +} + +static foreach (i; 0 .. 10) +{ + static assert(test(i) == (i < 5 ? i : -1)); +} +------- + + $(P An explicit $(D break)/$(D continue) label can be used to + avoid this limitation. (Note that $(D static foreach) itself + cannot be broken nor continued even if it is explicitly + labeled.) + ) + +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +------- +int test(int x) +{ + int r = -1; + Lswitch: switch(x) + { + static foreach (i; 0 .. 5) + { + case i: + r = i; + break Lswitch; + } + default: break; + } + return r; +} + +static foreach (i; 0 .. 10) +{ + static assert(test(i) == (i < 5 ? i : -1)); +} +------- +) + + +$(H2 $(LEGACY_LNAME2 StaticAssert, static-assert, Static Assert)) + +$(GRAMMAR +$(GNAME StaticAssert): + $(D static assert $(LPAREN)) $(GLINK2 expression, ArgumentList) $(D $(RPAREN) ;) +) + + $(P The first $(ASSIGNEXPRESSION) is evaluated at compile time, and converted + to a boolean value. If the value is true, the static assert + is ignored. If the value is false, an error diagnostic is issued + and the compile fails. + ) + + $(P On failure, any subsequent $(I AssignExpression)s will each be + converted to string and then concatenated. The resulting string will + be printed out along with the error diagnostic. + ) + + $(P Unlike $(GLINK2 expression, AssertExpression)s, $(I StaticAssert)s are always + checked and evaluated by the compiler unless they appear in an + unsatisfied conditional. + ) + +------ +void foo() +{ + if (0) + { + assert(0); // never trips + static assert(0); // always trips + } + version (BAR) + { + } + else + { + static assert(0); // trips when version BAR is not defined + } +} +------ + + $(P $(I StaticAssert) is useful tool for drawing attention to conditional + configurations not supported in the code. + ) + +$(SPEC_SUBNAV_PREV_NEXT contracts, Contract Programming, traits, Traits) +) + +Macros: + CHAPTER=25 + TITLE=Conditional Compilation diff --git a/spec/windows.dd b/spec/windows.dd new file mode 100644 index 0000000000..d144606938 --- /dev/null +++ b/spec/windows.dd @@ -0,0 +1,79 @@ +Ddoc + +$(SPEC_S Windows Programming, + +$(HEADERNAV_TOC) + +$(P This covers Windows programming with 32 bit MSCOFF, +64 bit MSCOFF, console programs, GUI programs, and DLLs. +) + +$(H2 All Console Programs) + + $(P A D console program is specified by having a function with D linkage at module level called `main`. + When the compiler sees this, it triggers the mixin template `core.internal.entrypoint._d_cmain` + to be added. The `_d_cmain` template looks like: + ) + --- + template _d_cmain() + { + extern(C) + { + int _d_run_main(int argc, char **argv, void* mainFunc); + + int _Dmain(char[][] args); + + int main(int argc, char **argv) + { + return _d_run_main(argc, argv, &_Dmain); + } + + // Solaris, for unknown reasons, requires both a main() and an _main() + version (Solaris) + { + int _main(int argc, char** argv) + { + return main(argc, argv); + } + } + } + } + --- + $(P The `main` function in it, because it is marked as `extern(C)`, is the entry point of a + C console program. The executable starts up as a C executable, with the C runtime library + initialization and then the C main() function is called.) + $(P The C runtime library runs any D functions tagged with `pragma(crt_constructor)` as + part of its initialization, and before it calls C `main()`. The order in which these + are run is not specified.) + $(P The C `main` function then calls the D runtime library function `_d_run_main`, passing it + `argc` and `argv`, and the address of `_Dmain`. The compiler renames the D `main` function in + the source code to `_Dmain`.) + $(P `_d_run_main` then initializes the D runtime library, converts `argc` and `argv` to `args`, + and calls the D `main` function.) + $(P When the D `main` function returns, control is back in `_d_run_main` which shuts down the + D runtime library, and then returns to the C `main`, which then returns to the C library + which shuts down the C runtime library, then exits the program.) + $(P The C runtime library runs any D functions tagged with `pragma(crt_destructor)` as + part of its shutdown, in the reverse order that the `pragma(crt_constructor)`s were run. + ) + +$(H2 $(LNAME2 mscoff, Windows 32 and 64 bit MSCOFF Programs)) + + $(P 32 bit and 64 bit MSCOFF programs use the Microsoft Visual C/C++ compiler as the $(ACC), + generate object files in the MSCOFF format, and use the Microsoft linker + to link them. + ) + +$(H3 $(LNAME2 mscoff-console, Console Programs)) + +$(H3 $(LNAME2 mscoff-windows, Windows GUI Programs)) + +$(H3 $(LNAME2 mscoff-dlls, DLLs)) + +$(SPEC_SUBNAV_PREV ob, Live Functions) +) + +Macros: + CHAPTER=44 + TITLE=Windows Programming + CATEGORY_SPEC=$0 diff --git a/statement.dd b/statement.dd deleted file mode 100644 index 6394faa228..0000000000 --- a/statement.dd +++ /dev/null @@ -1,1842 +0,0 @@ -Ddoc - -$(SPEC_S Statements, - -C and C++ programmers will find the D statements very familiar, with a few -interesting additions. - -$(GRAMMAR -$(GNAME Statement): - $(B ;) - $(GLINK NonEmptyStatement) - $(GLINK ScopeBlockStatement) - -$(GNAME NoScopeNonEmptyStatement): - $(GLINK NonEmptyStatement) - $(GLINK BlockStatement) - -$(GNAME NoScopeStatement): - $(B ;) - $(GLINK NonEmptyStatement) - $(GLINK BlockStatement) - -$(GNAME NonEmptyOrScopeBlockStatement): - $(GLINK NonEmptyStatement) - $(GLINK ScopeBlockStatement) - -$(GNAME NonEmptyStatement): - $(GLINK NonEmptyStatementNoCaseNoDefault) - $(GLINK CaseStatement) -$(V2 $(GLINK CaseRangeStatement) -) $(GLINK DefaultStatement) - -$(GNAME NonEmptyStatementNoCaseNoDefault): - $(GLINK LabeledStatement) - $(GLINK ExpressionStatement) - $(GLINK DeclarationStatement) - $(GLINK IfStatement) - $(GLINK WhileStatement) - $(GLINK DoStatement) - $(GLINK ForStatement) - $(GLINK ForeachStatement) - $(GLINK SwitchStatement) -$(V2 $(GLINK FinalSwitchStatement) -) $(GLINK ContinueStatement) - $(GLINK BreakStatement) - $(GLINK ReturnStatement) - $(GLINK GotoStatement) - $(GLINK WithStatement) - $(GLINK SynchronizedStatement) - $(GLINK TryStatement) - $(GLINK ScopeGuardStatement) - $(GLINK ThrowStatement) -$(V1 $(GLINK VolatileStatement) -) $(GLINK AsmStatement) - $(GLINK PragmaStatement) - $(GLINK MixinStatement) -$(V2 $(GLINK ForeachRangeStatement)) - $(GLINK2 version, ConditionalStatement) - $(GLINK2 version, StaticAssert) - $(GLINK2 template-mixin, TemplateMixin) - $(GLINK2 module, ImportDeclaration) -) - - - $(P Any ambiguities in the grammar between $(I Statement)s and - $(GLINK2 declaration, Declaration)s are - resolved by the declarations taking precedence. - If a $(I Statement) is desired instead, wrapping it in parentheses will - disambiguate it in favor of being a $(I Statement). - ) - -<h2>$(LNAME2 ScopeStatement, Scope Statements)</h2> - -$(GRAMMAR -$(I ScopeStatement): - $(GLINK NonEmptyStatement) - $(GLINK BlockStatement) -) - - $(P A new scope for local symbols - is introduced for the $(I NonEmptyStatement) - or $(GLINK BlockStatement). - ) - - $(P Even though a new scope is introduced, - local symbol declarations cannot shadow (hide) other - local symbol declarations in the same function. - ) - --------------- -void func1(int x) { - int x; // illegal, x shadows parameter x - - int y; - - { int y; } // illegal, y shadows enclosing scope's y - - void delegate() dg; - dg = { int y; }; // ok, this y is not in the same function - - struct S { - int y; // ok, this y is a member, not a local - } - - { int z; } - { int z; } // ok, this z is not shadowing the other z - - { int t; } - { t++; } // illegal, t is undefined -} --------------- - -$(P - The idea is to avoid bugs in complex functions caused by - scoped declarations inadvertently hiding previous ones. - Local names should all be unique within a function. -) - - -<h2>$(LNAME2 ScopeBlockStatement, Scope Block Statements)</h2> - -$(GRAMMAR -$(I ScopeBlockStatement): - $(GLINK BlockStatement) -) - - $(P A scope block statement introduces a new scope for the - $(GLINK BlockStatement). - ) - -<h2>$(LNAME2 LabeledStatement, Labeled Statements)</h2> - -$(P Statements can be labeled. A label is an identifier that - precedes a statement. -) - -$(GRAMMAR -$(I LabeledStatement): - $(I Identifier) : $(PSSEMI) -) - -$(P - Any statement can be labeled, including empty statements, - and so can serve as the target - of a goto statement. Labeled statements can also serve as the - target of a break or continue statement. -) -$(P - Labels are in a name space independent of declarations, variables, - types, etc. - Even so, labels cannot have the same name as local declarations. - The label name space is the body of the function - they appear in. Label name spaces do not nest, i.e. a label - inside a block statement is accessible from outside that block. -) - -<h2>$(LNAME2 BlockStatement, Block Statement)</h2> - -$(GRAMMAR -$(I BlockStatement): - $(B { }) - $(B {) $(GLINK StatementList) $(B }) - -$(GNAME StatementList): - $(PSSEMI_PSCURLYSCOPE) - $(PSSEMI_PSCURLYSCOPE) $(I StatementList) -) - -$(P - A block statement is a sequence of statements enclosed - by { }. The statements are executed in lexical order. -) -<h2>$(LNAME2 ExpressionStatement, Expression Statement)</h2> - -$(GRAMMAR -$(I ExpressionStatement): - $(EXPRESSION) $(B ;) -) - - The expression is evaluated. - <p> - - Expressions that have no effect, like $(D (x + x)), - are illegal - in expression statements. - If such an expression is needed, casting it to $(D_KEYWORD void) will - make it legal. - ----- -int x; -x++; // ok -x; // illegal -1+1; // illegal -cast(void)(x + x); // ok ----- - -<h2>$(LNAME2 DeclarationStatement, Declaration Statement)</h2> - - Declaration statements declare variables and types. - -$(GRAMMAR -$(I DeclarationStatement): - $(I Declaration) -) - - $(P Some declaration statements:) - ----- -int a; // declare a as type int and initialize it to 0 -struct S { } // declare struct s -alias int myint; ----- - -<h2>$(LNAME2 IfStatement, If Statement)</h2> - - If statements provide simple conditional execution of statements. - -$(GRAMMAR -$(I IfStatement): - $(B if $(LPAREN)) $(GLINK IfCondition) $(B $(RPAREN)) $(GLINK ThenStatement) - $(B if $(LPAREN)) $(GLINK IfCondition) $(B $(RPAREN)) $(GLINK ThenStatement) $(B else) $(GLINK ElseStatement) - -$(GNAME IfCondition): - $(EXPRESSION) - $(B auto) $(I Identifier) $(B =) $(EXPRESSION) - $(GLINK2 declaration, BasicType) $(GLINK2 declaration, Declarator) $(B =) $(EXPRESSION) - -$(GNAME ThenStatement): - $(PSSCOPE) - -$(GNAME ElseStatement): - $(PSSCOPE) -) - - $(EXPRESSION) is evaluated and must have a type that - can be converted to a boolean. If it's true the - $(I ThenStatement) is transferred to, else the $(I ElseStatement) - is transferred to. - <p> - - The 'dangling else' parsing problem is solved by associating the - else with the nearest if statement. - <p> - - If an $(B auto) $(I Identifier) is provided, it is declared and - initialized - to the value - and type of the $(EXPRESSION). Its scope extends from when it is - initialized to the end of the $(I ThenStatement). - <p> - - If a $(I Declarator) is provided, it is declared and - initialized - to the value - of the $(EXPRESSION). Its scope extends from when it is - initialized to the end of the $(I ThenStatement). - ---- -import std.regexp; -... -if (auto m = std.regexp.search("abcdef", "b(c)d")) -{ - writefln("[%s]", m.pre); // prints [a] - writefln("[%s]", m.post); // prints [ef] - writefln("[%s]", m.match(0)); // prints [bcd] - writefln("[%s]", m.match(1)); // prints [c] - writefln("[%s]", m.match(2)); // prints [] -} -else -{ - writefln(m.post); // error, m undefined -} -writefln(m.pre); // error, m undefined ---- - -<h2>$(LNAME2 WhileStatement, While Statement)</h2> - -$(GRAMMAR -$(I WhileStatement): - $(B while $(LPAREN)) $(EXPRESSION) $(B $(RPAREN)) $(PSSCOPE) -) - - While statements implement simple loops. - - $(EXPRESSION) is evaluated and must have a type that - can be converted to a boolean. If it's true the - $(PSSCOPE) is executed. After the $(PSSCOPE) is executed, - the $(EXPRESSION) is evaluated again, and if true the - $(PSSCOPE) is executed again. This continues until the - $(EXPRESSION) evaluates to false. - ---- -int i = 0; -while (i < 10) { - foo(i); - i++; -} ---- - - A $(GLINK BreakStatement) will exit the loop. - A $(GLINK ContinueStatement) - will transfer directly to evaluating $(EXPRESSION) again. - -<h2>$(LNAME2 DoStatement, Do Statement)</h2> - -$(V1 -$(GRAMMAR -$(I DoStatement): - $(B do) $(PSSCOPE) $(B while $(LPAREN)) $(EXPRESSION) $(B $(RPAREN)) -) -) -$(V2 -$(GRAMMAR -$(I DoStatement): - $(B do) $(PSSCOPE) $(B while $(LPAREN)) $(EXPRESSION) $(B $(RPAREN)) $(B ;) -) -) - - Do while statements implement simple loops. - - $(PSSCOPE) is executed. Then - $(EXPRESSION) is evaluated and must have a type that - can be converted to a boolean. If it's true the - loop is iterated again. - This continues until the - $(EXPRESSION) evaluates to false. - ---- -int i = 0; -do { - foo(i); -} while (++i < 10); ---- - - A $(GLINK BreakStatement) will exit the loop. - A $(GLINK ContinueStatement) - will transfer directly to evaluating $(EXPRESSION) again. - -<h2>$(LNAME2 ForStatement, For Statement)</h2> - - For statements implement loops with initialization, - test, and increment clauses. - -$(GRAMMAR -$(I ForStatement): - $(B for $(LPAREN))$(GLINK Initialize) $(I Test)$(OPT) $(B ;) $(GLINK Increment)$(OPT)$(B $(RPAREN)) $(PSSCOPE) - -$(GNAME Initialize): - $(B ;) - $(PS0) - -$(GNAME Test): - $(EXPRESSION) - -$(GNAME Increment): - $(EXPRESSION) -) - - $(P $(I Initialize) is executed. - $(I Test) is evaluated and must have a type that - can be converted to a boolean. If it's true the - statement is executed. After the statement is executed, - the $(I Increment) is executed. - Then $(I Test) is evaluated again, and if true the - statement is executed again. This continues until the - $(I Test) evaluates to false. - ) - - $(P A $(GLINK BreakStatement) will exit the loop. - A $(GLINK ContinueStatement) - will transfer directly to the $(I Increment). - ) - - $(P A $(I ForStatement) creates a new scope. - If $(I Initialize) declares a variable, that variable's scope - extends through the end of the for statement. For example: - ) - --------------- -for (int i = 0; i < 10; i++) - foo(i); --------------- - - is equivalent to: - --------------- -{ - int i; - for (i = 0; i < 10; i++) - foo(i); -} --------------- - - Function bodies cannot be empty: - --------------- -for (int i = 0; i < 10; i++) - ; // illegal --------------- - - Use instead: - --------------- -for (int i = 0; i < 10; i++) -{ -} --------------- - - The $(I Initialize) may be omitted. $(I Test) may also be - omitted, and if so, it is treated as if it evaluated to true. - -<h2>$(LNAME2 ForeachStatement, Foreach Statement)</h2> - - A foreach statement loops over the contents of an aggregate. - -$(GRAMMAR -$(I ForeachStatement): - $(I Foreach) $(B $(LPAREN))$(GLINK ForeachTypeList) $(B ;) $(GLINK Aggregate)$(B $(RPAREN)) $(PS0) - -$(GNAME Foreach): - $(B foreach) - $(B foreach_reverse) - -$(GNAME ForeachTypeList): - $(GLINK ForeachType) - $(GLINK ForeachType) , $(I ForeachTypeList) - -$(GNAME ForeachType): - $(B ref)$(OPT) $(GLINK2 declaration, BasicType) $(GLINK2 declaration, Declarator) - $(B ref)$(OPT) $(I Identifier) - -$(GNAME Aggregate): - $(EXPRESSION) -) - -$(P - $(I Aggregate) is evaluated. It must evaluate to an expression - of type static array, dynamic array, associative array, - struct, class, delegate, or tuple. - The $(PS0) is executed, once for each element of the - aggregate. - At the start of each iteration, the variables declared by - the $(I ForeachTypeList) - are set to be a copy of the elements of the aggregate. - If the variable is $(B ref), it is a reference to the - contents of that aggregate. -) -$(P - The aggregate must be loop invariant, meaning that - elements to the aggregate cannot be added or removed from it - in the $(PS0). -) - -<h3>Foreach over Arrays</h3> - -$(P - If the aggregate is a static or dynamic array, there - can be one or two variables declared. If one, then the variable - is said to be the $(I value) set to the elements of the array, - one by one. The type of the - variable must match the type of the array contents, except for the - special cases outlined below. - If there are - two variables declared, the first is said to be the $(I index) - and the second is said to be the $(I value). The $(I index) - must be of $(B int), $(B uint) or $(B size_t) type, - it cannot be $(I ref), - and it is set to be the index of the array element. -) --------------- -char[] a; -... -foreach (int i, char c; a) -{ - writefln("a[%d] = '%c'", i, c); -} --------------- - - $(P For $(B foreach), the - elements for the array are iterated over starting at index 0 - and continuing to the maximum of the array. - For $(B foreach_reverse), the array elements are visited in the reverse - order. - ) - -<h3>Foreach over Arrays of Characters</h3> - - $(P If the aggregate expression is a static or dynamic array of - $(B char)s, $(B wchar)s, or $(B dchar)s, then the $(I Type) of - the $(I value) - can be any of $(B char), $(B wchar), or $(B dchar). - In this manner any UTF array - can be decoded into any UTF type: - ) - --------------- -char[] a = "\xE2\x89\xA0"$(V2 .dup); // \u2260 encoded as 3 UTF-8 bytes - -foreach (dchar c; a) -{ - writefln("a[] = %x", c); // prints 'a[] = 2260' -} - -dchar[] b = "\u2260"d$(V2 .dup); - -foreach (char c; b) -{ - writef("%x, ", c); // prints 'e2, 89, a0, ' -} --------------- - - - $(P Aggregates can be string literals, which can be accessed - as char, wchar, or dchar arrays: - ) - --------------- -void test() { - foreach (char c; "ab") { - writefln("'%s'", c); - } - foreach (wchar w; "xy") { - writefln("'%s'", w); - } -} --------------- - - $(P which would print: - ) - -$(CONSOLE -'a' -'b' -'x' -'y' -) - -<h3>Foreach over Associative Arrays</h3> - - $(P If the aggregate expression is an associative array, there - can be one or two variables declared. If one, then the variable - is said to be the $(I value) set to the elements of the array, - one by one. The type of the - variable must match the type of the array contents. If there are - two variables declared, the first is said to be the $(I index) - and the second is said to be the $(I value). The $(I index) - must be of the same type as the indexing type of the associative - array. It cannot be $(I ref), - and it is set to be the index of the array element. - The order in which the elements of the array is unspecified - for $(B foreach). $(B foreach_reverse) for associative arrays - is illegal. - ) - --------------- -double[$(V1 char[])$(V2 string)] a; // $(I index) type is $(V1 char[])$(V2 string), $(I value) type is double -... -foreach ($(V1 char[])$(V2 string) s, double d; a) -{ - writefln("a['%s'] = %g", s, d); -} --------------- - -$(V2 -<h3>$(LNAME2 foreach_with_ranges, Foreach over Structs and Classes with Ranges)</h3> - - $(P Iteration over struct and class objects can be done with - ranges, which means the following properties and methods must be defined: - ) - - $(TABLE2 Foreach Range Properties, - $(TR $(TH Property) $(TH Purpose )) - $(TR $(TD $(D .empty)) $(TD returns true if no more elements)) - $(TR $(TD $(D .front)) $(TD return the leftmost element of the range)) - $(TR $(TD $(D .back)) $(TD return the rightmost element of the range)) - ) - - $(TABLE2 Foreach Range Methods, - $(TR $(TH Method) $(TH Purpose )) - $(TR $(TD $(D .popFront())) $(TD move the left edge of the range right one)) - $(TR $(TD $(D .popBack())) $(TD move the right edge of the range left one)) - ) - - $(P Meaning:) - ---- -foreach (e; range) { ... } ---- - - $(P translates to:) - ---- -for (auto __r = range; !__r.empty; __r.popFront()) -{ - auto e = __r.front; - ... -} ---- - - $(P Similarly:) - ---- -foreach_reverse (e; range) { ... } ---- - - $(P translates to:) - ---- -for (auto __r = range; !__r.empty; __r.popBack()) -{ - auto e = __r.back; - ... -} ---- - - $(P If the foreach range properties do not exist, the $(D opApply) - method will be used instead. - ) -) - -<h3>Foreach over Structs and Classes with opApply</h3> - - $(P - If it is a struct or class object, the $(B foreach) is defined by - the special $(LNAME2 opApply, $(I opApply)) member function. - The $(B foreach_reverse) behavior is defined by the special - $(LNAME2 opApplyReverse, $(I opApplyReverse)) member function. - These special functions must be defined by the type in order - to use the corresponding foreach statement. - The functions have the type: - ) - --------------- -int $(B opApply)(int delegate(ref $(I Type) [, ...]) $(I dg)); - -int $(B opApplyReverse)(int delegate(ref $(I Type) [, ...]) $(I dg)); --------------- - - $(P where $(I Type) matches the $(I Type) used in the $(I ForeachType) - declaration of $(I Identifier). Multiple $(I ForeachType)s - correspond with multiple $(I Type)'s in the delegate type - passed to $(B opApply) or $(B opApplyReverse). - There can be multiple $(B opApply) and $(B opApplyReverse) functions, - one is selected - by matching the type of $(I dg) to the $(I ForeachType)s - of the $(I ForeachStatement). - The body of the apply - function iterates over the elements it aggregates, passing them - each to the $(I dg) function. If the $(I dg) returns 0, then - apply goes on to the next element. - If the $(I dg) returns a nonzero value, apply must cease - iterating and return that value. Otherwise, after done iterating - across all the elements, apply will return 0. - ) - - $(P For example, consider a class that is a container for two elements: - ) - --------------- -class Foo { - uint[2] array; - - int $(B opApply)(int delegate(ref uint) $(I dg)) - { - int result = 0; - - for (int i = 0; i < array.length; i++) - { - result = $(I dg)(array[i]); - if (result) - break; - } - return result; - } -} --------------- - - An example using this might be: - --------------- -void test() { - Foo a = new Foo(); - - a.array[0] = 73; - a.array[1] = 82; - - foreach (uint u; a) - { - writefln("%d", u); - } -} --------------- - - which would print: - -$(CONSOLE -73 -82 -) - -<h3>Foreach over Delegates</h3> - - $(P If $(I Aggregate) is a delegate, the type signature of - the delegate is of the same as for $(B opApply). This enables - many different named looping strategies to coexist in the same - class or struct.) - -<h3>Foreach over Tuples</h3> - -$(P - If the aggregate expression is a tuple, there - can be one or two variables declared. If one, then the variable - is said to be the $(I value) set to the elements of the tuple, - one by one. If the type of the - variable is given, it must match the type of the tuple contents. - If it is not given, the type of the variable is set to the type - of the tuple element, which may change from iteration to iteration. - If there are - two variables declared, the first is said to be the $(I index) - and the second is said to be the $(I value). The $(I index) - must be of $(B int) or $(B uint) type, it cannot be $(I ref), - and it is set to be the index of the tuple element. -) - -$(P - If the tuple is a list of types, then the foreach statement - is executed once for each type, and the value is aliased to that - type. -) - ------ -import std.stdio; -import std.typetuple; // for TypeTuple - -void main() { - alias TypeTuple!(int, long, double) TL; - - foreach (T; TL) - { - write$(V1 f)ln(typeid(T)); - } -} ------ - - $(P Prints:) - -$(CONSOLE -int -long -double -) - -<h3>Foreach Ref Parameters</h3> - - $(P $(B ref) can be used to update the original elements: - ) - --------------- -void test() { - static uint[2] a = [7, 8]; - - foreach (ref uint u; a) - { - u++; - } - foreach (uint u; a) - { - writefln("%d", u); - } -} --------------- - - which would print: - -$(CONSOLE -8 -9 -) - $(P $(B ref) can not be applied to the index values.) - - $(P If not specified, the $(I Type)s in the $(I ForeachType) can be - inferred from - the type of the $(I Aggregate). - ) - -<h3>Foreach Restrictions</h3> - - $(P The aggregate itself must not be resized, reallocated, free'd, - reassigned or destructed - while the foreach is iterating over the elements. - ) - --------------- -int[] a; -int[] b; -foreach (int i; a) -{ - a = null; $(V1 )// error - $(V2 a.length += 10;)$(V1 a.length = a.length + 10;) // error - a = b; $(V1 )// error -} -a = null; $(V1 )// ok --------------- - -$(V2 -<h2>$(LNAME2 ForeachRangeStatement, Foreach Range Statement)</h2> - - A foreach range statement loops over the specified range. - -$(GRAMMAR -$(I ForeachRangeStatement): - $(GLINK Foreach) $(LPAREN)$(GLINK ForeachType) $(B ;) $(GLINK LwrExpression) $(B ..) $(GLINK UprExpression) $(B $(RPAREN)) $(PSSCOPE) - -$(GNAME LwrExpression): - $(EXPRESSION) - -$(GNAME UprExpression): - $(EXPRESSION) -) - - $(P - $(I ForeachType) declares a variable with either an explicit type, - or a type inferred from $(I LwrExpression) and $(I UprExpression). - The $(I ScopeStatement) is then executed $(I n) times, where $(I n) - is the result of $(I UprExpression) - $(I LwrExpression). - If $(I UprExpression) is less than or equal to $(I LwrExpression), - the $(I ScopeStatement) is executed zero times. - If $(I Foreach) is $(B foreach), then the variable is set to - $(I LwrExpression), then incremented at the end of each iteration. - If $(I Foreach) is $(B foreach_reverse), then the variable is set to - $(I UprExpression), then decremented before each iteration. - $(I LwrExpression) and $(I UprExpression) are each evaluated - exactly once, regardless of how many times the $(I ScopeStatement) - is executed. - ) - ---- -import std.stdio; - -int foo() { - write("foo"); - return 10; -} - -void main() { - foreach (i; 0 .. foo()) - { - write(i); - } -} ---- - - $(P Prints:) - -$(CONSOLE -foo0123456789 -) -) - -<h3>Break and Continue out of Foreach</h3> - - - $(P A $(GLINK BreakStatement) in the body of the foreach will exit the - foreach, a $(GLINK ContinueStatement) will immediately start the - next iteration. - ) - -<h2>$(LNAME2 SwitchStatement, Switch Statement)</h2> - - A switch statement goes to one of a collection of case - statements depending on the value of the switch - expression. - -$(GRAMMAR -$(I SwitchStatement): - $(B switch $(LPAREN)) $(EXPRESSION) $(B $(RPAREN)) $(PSSCOPE) - -$(GNAME CaseStatement): - $(B case) $(GLINK2 expression, ArgumentList) $(B :) $(PSSEMI_PSCURLYSCOPE_LIST) - -$(V2 $(GNAME CaseRangeStatement): - $(B case) $(GLINK FirstExp) $(B : .. case) $(GLINK LastExp) $(B :) $(PSSEMI_PSCURLYSCOPE_LIST) - -$(GNAME FirstExp): - $(ASSIGNEXPRESSION) - -$(GNAME LastExp): - $(ASSIGNEXPRESSION) -) -$(GNAME DefaultStatement): - $(B default :) $(PSSEMI_PSCURLYSCOPE_LIST) - -$(GNAME ScopeStatementList): - $(GLINK StatementListNoCaseNoDefault) - -$(GNAME StatementListNoCaseNoDefault): - $(GLINK StatementNoCaseNoDefault) - $(GLINK StatementNoCaseNoDefault) $(I StatementListNoCaseNoDefault) - -$(GNAME StatementNoCaseNoDefault): - $(B ;) - $(GLINK NonEmptyStatementNoCaseNoDefault) - $(GLINK ScopeBlockStatement) -) - - $(P $(EXPRESSION) is evaluated. The result type T must be - of integral type or $(CODE char[]), $(CODE wchar[]) or $(CODE dchar[]). - The result is - compared against each of the case expressions. If there is - a match, the corresponding case statement is transferred to. - ) - - $(P The case expressions, $(GLINK2 expression, ArgumentList), - are a comma separated list of expressions. - ) - -$(V2 - $(P A $(I CaseRangeStatement) is a shorthand for listing a series - of case statements from $(I FirstExp) to $(I LastExp). - ) -) - - $(P If none of the case expressions match, and there is a default - statement, the default statement is transferred to. - ) - -$(V1 - $(P If none of the case expressions match, and there is not a default - statement, a -$(V1 - $(LINK2 phobos/std_switcherr.html, $(CODE std.switcherr.SwitchError)) -) -$(V2 - $(LINK2 core_exception.html, $(CODE core.exception.SwitchError)) -) - is thrown. - ) -) -$(V2 - $(P A switch statement must have a default statement.) -) - - $(P -$(V1 - The case expressions must all evaluate to a constant value - or array. -) -$(V2 - The case expressions must all evaluate to a constant value - or array, or a runtime initialized const or immutable variable of - integral type. -) - They must be implicitly convertible to the type of the - switch $(EXPRESSION). - ) - - $(P Case expressions must all evaluate to distinct values. -$(V2 - Const or immutable variables must all have different names. - If they share a value, the first case statement with that value - gets control. - There must be exactly one default statement. -) -$(V1 - There may not be two or more default statements. -) - ) - - $(P The $(GLINK ScopeStatementList) introduces a new scope. - ) - - $(P Case statements and default statements associated with the switch - can be nested within block statements; they do not have to be in - the outermost block. For example, this is allowed: - ) - --------------- -switch (i) { - case 1: - { - case 2: - } - break; -} --------------- - -$(V1 - $(P Case statements 'fall through' to subsequent - case values. A break statement will exit the switch $(I BlockStatement). - For example: - ) - --------------- -switch (i) { - case 1: - x = 3; - case 2: - x = 4; - break; - - case 3,4,5: - x = 5; - break; -} --------------- - - $(P will set $(CODE x) to $(CODE 4) if $(CODE i) is $(CODE 1). - ) -) - -$(V2 - $(P A $(GLINK ScopeStatementList) must either be empty, or be ended with - a $(GLINK ContinueStatement), $(GLINK BreakStatement), - $(GLINK ReturnStatement), $(GLINK GotoStatement), $(GLINK ThrowStatement) - or assert(0) expression unless this is the last case. This is to - set apart with C's error-prone implicit fall-through behavior. - $(B goto case;) could be used for explicit fall-through: - ) - --------------- -int number; -string message; -switch (number) -{ - default: // valid: ends with 'throw' - throw new Exception("unknown number"); - - case 3: // valid: ends with 'break' (break out of the 'switch' only) - message ~= "three "; - break; - - case 4: // valid: ends with 'continue' (continue the enclosing loop) - message ~= "four "; - continue; - - case 5: // valid: ends with 'goto' (explicit fall-through to next case.) - message ~= "five "; - goto case; - - case 6: // $(B ERROR): implicit fall-through - message ~= "six "; - - case 1: // valid: the body is empty - case 2: // valid: this is the last case in the switch statement. - message = "one or two"; -} --------------- - - $(P A break statement will exit the switch $(I BlockStatement).) -) - - $(P $(LNAME2 string-switch, Strings can be used in switch expressions). - For example: - ) - --------------- -char[] name; -... -switch (name) { - case "fred": - case "sally": - ... -} --------------- - - $(P For applications like command line switch processing, this - can lead to much more straightforward code, being clearer and - less error prone. char, wchar and dchar strings are allowed. - ) - - $(P $(B Implementation Note:) The compiler's code generator may - assume that the case - statements are sorted by frequency of use, with the most frequent - appearing first and the least frequent last. Although this is - irrelevant as far as program correctness is concerned, it is of - performance interest. - ) - -$(V2 -<h2>$(LNAME2 FinalSwitchStatement, Final Switch Statement)</h2> - -$(GRAMMAR -$(I FinalSwitchStatement): - $(B final switch $(LPAREN)) $(EXPRESSION) $(B $(RPAREN)) $(PSSCOPE) -) - - $(P A final switch statement is just like a switch statement, - except that:) - - $(UL - $(LI No $(GLINK DefaultStatement) is allowed.) - $(LI No $(GLINK CaseRangeStatement)s are allowed.) - $(LI If the switch $(EXPRESSION) is of enum type, all - the enum members must appear in the $(GLINK CaseStatement)s.) - $(LI The case expressions cannot evaluate to a run time - initialized value.) - ) - -) - -<h2>$(LNAME2 ContinueStatement, Continue Statement)</h2> - -$(GRAMMAR -$(I ContinueStatement): - $(B continue) $(I Identifier)$(OPT) $(B ;) -) - - A continue aborts the current iteration of its enclosing loop - statement, and starts the next iteration. - - continue executes the next iteration of its innermost enclosing - while, for, foreach, or do loop. The increment clause is executed. - <p> - - If continue is followed by $(I Identifier), the $(I Identifier) - must be the label of an enclosing while, for, or do - loop, and the next iteration of that loop is executed. - It is an error if - there is no such statement. - <p> - - Any intervening finally clauses are executed, and any intervening - synchronization objects are released. - <p> - - $(B Note:) If a finally clause executes a return, throw, or goto - out of the finally clause, - the continue target is never reached. - ---- -for (i = 0; i < 10; i++) -{ - if (foo(i)) - continue; - bar(); -} ---- - -<h2>$(LNAME2 BreakStatement, Break Statement)</h2> - -$(GRAMMAR -$(I BreakStatement): - $(B break) $(I Identifier)$(OPT) $(B ;) -) - - A break exits the enclosing statement. - - break exits the innermost enclosing while, for, foreach, do, or switch - statement, resuming execution at the statement following it. - <p> - - If break is followed by $(I Identifier), the $(I Identifier) - must be the label of an enclosing while, for, do or switch - statement, and that statement is exited. It is an error if - there is no such statement. - <p> - - Any intervening finally clauses are executed, and any intervening - synchronization objects are released. - <p> - - $(B Note:) If a finally clause executes a return, throw, or goto - out of the finally clause, - the break target is never reached. - ---- -for (i = 0; i < 10; i++) -{ - if (foo(i)) - break; -} ---- - -<h2>$(LNAME2 ReturnStatement, Return Statement)</h2> - -$(GRAMMAR -$(I ReturnStatement): - $(B return) $(EXPRESSION)$(OPT) $(B ;) -) - - A return exits the current function and supplies its return - value. - - $(EXPRESSION) is required if the function specifies - a return type that is not void. - The $(EXPRESSION) is implicitly converted to the - function return type. - <p> - - At least one return statement, throw statement, or assert(0) expression - is required if the function specifies a return type that is not void, - unless the function contains inline assembler code. - <p> - -$(COMMENT - $(EXPRESSION) is allowed even if the function specifies - a $(D_KEYWORD void) return type. The $(EXPRESSION) will be evaluated, - but nothing will be returned. - If the $(EXPRESSION) has no side effects, and the return - type is $(D_KEYWORD void), then it is illegal. - <p> -) - Before the function actually returns, - any objects with scope storage duration are destroyed, - any enclosing finally clauses are executed, - any scope(exit) statements are executed, - any scope(success) statements are executed, - and any enclosing synchronization - objects are released. - <p> - - The function will not return if any enclosing finally clause - does a return, goto or throw that exits the finally clause. - <p> - - If there is an out postcondition - (see $(DDLINK dbc, Contract Programming, Contract Programming)), - that postcondition is executed - after the $(EXPRESSION) is evaluated and before the function - actually returns. - ---- -int foo(int x) -{ - return x + 3; -} ---- - -<h2>$(LNAME2 GotoStatement, Goto Statement)</h2> - -$(GRAMMAR -$(I GotoStatement): - $(B goto) $(I Identifier) $(B ;) - $(B goto) $(B default) $(B ;) - $(B goto) $(B case) $(B ;) - $(B goto) $(B case) $(EXPRESSION) $(B ;) -) - - A goto transfers to the statement labeled with - $(I Identifier). - ---- - if (foo) - goto L1; - x = 3; -L1: - x++; ---- - - The second form, $(CODE goto default;), transfers to the - innermost $(GLINK DefaultStatement) of an enclosing - $(GLINK SwitchStatement). - <p> - - The third form, $(CODE goto case;), transfers to the - next $(GLINK CaseStatement) of the innermost enclosing - $(GLINK SwitchStatement). - <p> - - The fourth form, $(CODE goto case $(EXPRESSION);), transfers to the - $(GLINK CaseStatement) of the innermost enclosing - $(GLINK SwitchStatement) - with a matching $(EXPRESSION). - ---- -switch (x) -{ - case 3: - goto case; - case 4: - goto default; - case 5: - goto case 4; - default: - x = 4; - break; -} ---- - Any intervening finally clauses are executed, along with - releasing any intervening synchronization mutexes. - <p> - - It is illegal for a $(I GotoStatement) to be used to skip - initializations. - -<h2>$(LNAME2 WithStatement, With Statement)</h2> - - The with statement is a way to simplify repeated references - to the same object. - -$(GRAMMAR -$(I WithStatement): - $(B with) $(B $(LPAREN)) $(EXPRESSION) $(B $(RPAREN)) $(PSSCOPE) - $(B with) $(B $(LPAREN)) $(GLINK2 template, Symbol) $(B $(RPAREN)) $(PSSCOPE) - $(B with) $(B $(LPAREN)) $(GLINK2 template, TemplateInstance) $(B $(RPAREN)) $(PSSCOPE) -) - - where $(EXPRESSION) evaluates to a class reference or struct - instance. - Within the with body the referenced object is searched first for - identifier symbols. The $(I WithStatement) - --------------- -$(B with) (expression) -{ - ... - ident; -} --------------- - - is semantically equivalent to: - --------------- -{ - Object tmp; - tmp = expression; - ... - tmp.ident; -} --------------- - - $(P Note that $(EXPRESSION) only gets evaluated once. - The with statement does not change what $(B this) or - $(B super) refer to. - ) - - $(P For $(I Symbol) which is a scope or $(I TemplateInstance), - the corresponding scope is searched when looking up symbols. - For example: - ) - --------------- -struct Foo { - alias int Y; -} -... -Y y; // error, Y undefined -with (Foo) { - Y y; // same as Foo.Y y; -} --------------- - -$(V2 - $(P Use of with object symbols that shadow local symbols with - the same identifier are not allowed. - This is to reduce the risk of inadvertant breakage of with - statements when new members are added to the object declaration. - ) ---- -struct S { - float x; -} - -void main() { - int x; - S s; - with (s) { - x++; // error, shadows the int x declaration - } -} ---- -) - -<h2>$(LNAME2 SynchronizedStatement, Synchronized Statement)</h2> - - $(P The synchronized statement wraps a statement with - a mutex to synchronize access among multiple threads. - ) - -$(GRAMMAR -$(I SynchronizedStatement): - $(B synchronized) $(PSSCOPE) - $(B synchronized $(LPAREN)) $(EXPRESSION) $(B $(RPAREN)) $(PSSCOPE) -) - - $(P Synchronized allows only one thread at a time to execute - $(I ScopeStatement) by using a mutex. - ) - - $(P What mutex is used is determined by the $(EXPRESSION). - If there is no $(EXPRESSION), then a global mutex is created, - one per such synchronized statement. - Different synchronized statements will have different global mutexes. - ) - - $(P If there is an $(EXPRESSION), it must evaluate to either an - Object or an instance of an $(I Interface), in which case it - is cast to the Object instance that implemented that $(I Interface). - The mutex used is specific to that Object instance, and - is shared by all synchronized statements referring to that instance. - ) - - $(P The synchronization gets released even if $(I ScopeStatement) - terminates with an exception, goto, or return. - ) - - $(P Example: - ) - --------------- -synchronized { ... } --------------- - - $(P This implements a standard critical section. - ) - -<h2>$(LNAME2 TryStatement, Try Statement)</h2> - - Exception handling is done with the try-catch-finally statement. - -$(GRAMMAR -$(I TryStatement): - $(B try) $(PSSCOPE) $(GLINK Catches) - $(B try) $(PSSCOPE) $(GLINK Catches) $(GLINK FinallyStatement) - $(B try) $(PSSCOPE) $(GLINK FinallyStatement) - -$(GNAME Catches): - $(GLINK LastCatch) - $(GLINK Catch) - $(GLINK Catch) $(I Catches) - -$(GNAME LastCatch): - $(B catch) $(PS0) - -$(GNAME Catch): - $(B catch $(LPAREN)) $(GLINK CatchParameter) $(B $(RPAREN)) $(PS0) - -$(GNAME CatchParameter): - $(GLINK2 declaration, BasicType) $(I Identifier) - -$(GNAME FinallyStatement): - $(B finally) $(PS0) -) - - $(P $(I CatchParameter) declares a variable v of type T, where T is - $(V1 Object or derived from Object.) - $(V2 Throwable or derived from Throwable.) - v is initialized by the throw expression if T is of the same type or a - base class of the throw expression. The catch clause will be executed - if the exception object is of type T or derived from T. - ) - - $(P If just type T is given and no variable v, then the catch clause - is still executed. - ) - - $(P It is an error if any $(I CatchParameter) type T1 hides - a subsequent $(I Catch) with type T2, i.e. it is an error if - T1 is the same type as or a base class of T2. - ) - - $(P $(I LastCatch) catches all exceptions. - ) - - $(P The $(I FinallyStatement) is always executed, whether - the $(B try) $(I ScopeStatement) exits with a goto, break, - continue, return, exception, or fall-through. - ) -$(V1 - $(P If an exception is raised in the $(I FinallyStatement) and - is not caught before the $(I FinallyStatement) is executed, - the new exception replaces any existing exception: - ) -) -$(V2 - $(P If an exception is raised in the $(I FinallyStatement) and is not - caught before the original exception is caught, it is chained to the - previous exception via the $(I next) member of $(I Throwable). - Note that, in contrast to most other programming languages, the new - exception does not replace the original exception. Instead, later - exceptions are regarded as 'collateral damage' caused by the first - exception. The original exception must be caught, and this results in - the capture of the entire chain. - ) - - $(P Thrown objects derived from $(I Error) are treated differently. They - bypass the normal chaining mechanism, such that the chain can only be - caught by catching the first $(I Error). In addition to the list of - subsequent exceptions, $(I Error) also contains a pointer that points - to the original exception (the head of the chain) if a bypass occurred, - so that the entire exception history is retained. - ) -) --------------- -import std.stdio; - -int main() { - try { - try { - throw new Exception("first"); - } - finally { - writefln("finally"); - throw new Exception("second"); - } - } - catch(Exception e) { - writefln("catch %s", e.msg); - } - writefln("done"); - return 0; -} --------------- - - prints: -$(V1 -$(CONSOLE -finally -catch second -done -) -) -$(V2 -$(CONSOLE -finally -catch first -done -) -) - - $(P A $(I FinallyStatement) may not exit with a goto, break, - continue, or return; nor may it be entered with a goto. - ) - - $(P A $(I FinallyStatement) may not contain any $(I Catches). - This restriction may be relaxed in future versions. - ) - -<h2>$(LNAME2 ThrowStatement, Throw Statement)</h2> - - Throw an exception. - -$(GRAMMAR -$(I ThrowStatement): - $(B throw) $(EXPRESSION) $(B ;) -) - - $(EXPRESSION) is evaluated and must be $(V1 an Object) $(V2 a Throwable) reference. - The $(V1 Object) $(V2 Throwable) reference is thrown as an exception. - ---- -throw new Exception("message"); ---- - -<h2>$(LNAME2 ScopeGuardStatement, Scope Guard Statement)</h2> - -$(GRAMMAR -$(I ScopeGuardStatement): - $(B scope(exit)) $(PSCURLYSCOPE) - $(B scope(success)) $(PSCURLYSCOPE) - $(B scope(failure)) $(PSCURLYSCOPE) -) - - The $(I ScopeGuardStatement) executes $(PSCURLYSCOPE) at the close - of the current scope, rather than at the point where the - $(I ScopeGuardStatement) appears. - $(B scope(exit)) executes $(PSCURLYSCOPE) when the scope - exits normally or when it exits due to exception unwinding. - $(B scope(failure)) executes $(PSCURLYSCOPE) when the scope - exits due to exception unwinding. - $(B scope(success)) executes $(PSCURLYSCOPE) when the scope - exits normally. - <p> - - If there are multiple $(I ScopeGuardStatement)s in a scope, they - are executed in the reverse lexical order in which they appear. - If any scope instances are to be destructed upon the close of the - scope, they also are interleaved with the $(I ScopeGuardStatement)s - in the reverse lexical order in which they appear. - -$(V1 ----- -writef("1"); { - writef("2"); - scope(exit) writef("3"); - scope(exit) writef("4"); - writef("5"); -} -writefln(); ----- -) -$(V2 ----- -write("1"); { - write("2"); - scope(exit) write("3"); - scope(exit) write("4"); - write("5"); -} -writeln(); ----- -) - writes: - -$(CONSOLE -12543 -) - -$(V1 ----- -{ - scope(exit) writef("1"); - scope(success) writef("2"); - scope(exit) writef("3"); - scope(success) writef("4"); -} -writefln(); ----- -) -$(V2 ----- -{ - scope(exit) write("1"); - scope(success) write("2"); - scope(exit) write("3"); - scope(success) write("4"); -} -writeln(); ----- -) - writes: - -$(CONSOLE -4321 -) - -$(V1 ----- -class Foo { - this() { writef("0"); } - ~this() { writef("1"); } -} - -try { - scope(exit) writef("2"); - scope(success) writef("3"); - scope Foo f = new Foo(); - scope(failure) writef("4"); - throw new Exception("msg"); - scope(exit) writef("5"); - scope(success) writef("6"); - scope(failure) writef("7"); -} -catch (Exception e) { -} -writefln(); ----- -) -$(V2 ----- -class Foo { - this() { write("0"); } - ~this() { write("1"); } -} - -try { - scope(exit) write("2"); - scope(success) write("3"); - scope Foo f = new Foo(); - scope(failure) write("4"); - throw new Exception("msg"); - scope(exit) write("5"); - scope(success) write("6"); - scope(failure) write("7"); -} -catch (Exception e) { -} -writeln(); ----- -) - writes: - -$(CONSOLE -0412 -) - - A $(B scope(exit)) or $(B scope(success)) statement - may not exit with a throw, goto, break, continue, or - return; nor may it be entered with a goto. - -$(V1 -<h2>$(LNAME2 VolatileStatement, Volatile Statement)</h2> - - No code motion occurs across volatile statement boundaries. - -$(GRAMMAR -$(I VolatileStatement): - $(B volatile) $(PSSEMI_PSCURLYSCOPE) - $(B volatile) $(B ;) -) - - $(PSSEMI_PSCURLYSCOPE) is evaluated. - Memory writes occurring before the $(PSSEMI_PSCURLYSCOPE) are - performed before any reads within or after the $(PSSEMI_PSCURLYSCOPE). - Memory reads occurring after the $(PSSEMI_PSCURLYSCOPE) occur after - any writes before or within $(PSSEMI_PSCURLYSCOPE) are completed. - <p> - - A volatile statement does not guarantee atomicity. For that, - use synchronized statements. -) - -<h2>$(LNAME2 asm, Asm Statement)</h2> - - Inline assembler is supported with the asm statement: - -$(GRAMMAR -$(GNAME AsmStatement): - $(B asm { }) - $(B asm {) $(GLINK AsmInstructionList) $(B }) - -$(GNAME AsmInstructionList): - $(GLINK2 iasm, AsmInstruction) $(B ;) - $(GLINK2 iasm, AsmInstruction) $(B ;) $(I AsmInstructionList) -) - - An asm statement enables the direct use of assembly language - instructions. This makes it easy to obtain direct access to special - CPU features without resorting to an external assembler. The - D compiler will take care of the function calling conventions, - stack setup, etc. - <p> - - The format of the instructions is, of course, highly dependent - on the native instruction set of the target CPU, and so is - $(DDLINK iasm, Inline Assembler, implementation defined). - But, the format will follow the following - conventions: - - $(UL - $(LI It must use the same tokens as the D language uses.) - $(LI The comment form must match the D language comments.) - $(LI Asm instructions are terminated by a ;, not by an - end of line.) - ) - - These rules exist to ensure that D source code can be tokenized - independently of syntactic or semantic analysis. - <p> - - For example, for the Intel Pentium: - --------------- -int x = 3; -asm { - mov EAX,x; // load x and put it in register EAX -} --------------- - - Inline assembler can be used to access hardware directly: - --------------- -int gethardware() { - asm { - mov EAX, dword ptr 0x1234; - } -} --------------- - - For some D implementations, such as a translator from D to C, an - inline assembler makes no sense, and need not be implemented. - The version statement can be used to account for this: - --------------- -version (D_InlineAsm_X86) -{ - asm { - ... - } -} -else -{ - /* ... some workaround ... */ -} --------------- - - $(P Semantically consecutive $(I AsmStatement)s shall not have - any other instructions (such as register save or restores) inserted - between them by the compiler. - ) - -<h2>$(LNAME2 PragmaStatement, Pragma Statement)</h2> - -$(GRAMMAR -$(I PragmaStatement): - $(GLINK2 pragma, Pragma) $(PSSEMI) -) - -<h2>$(LNAME2 MixinStatement, Mixin Statement)</h2> - -$(GRAMMAR -$(I MixinStatement): - $(B mixin) $(B $(LPAREN)) $(ASSIGNEXPRESSION) $(B $(RPAREN)) $(B ;) -) - - $(P The $(ASSIGNEXPRESSION) must evaluate at compile time - to a constant string. - The text contents of the string must be compilable as a valid - $(GLINK StatementList), and is compiled as such. - ) - ---- -import std.stdio; - -void main() { - int j; - mixin(" - int x = 3; - for (int i = 0; i < 3; i++) - writefln(x + i, ++j); - "); // ok - - const char[] s = "int y;"; - mixin(s); // ok - y = 4; // ok, mixin declared y - - char[] t = "y = 3;"; - mixin(t); // error, t is not evaluatable at compile time - - mixin("y =") 4; // error, string must be complete statement - - mixin("y =" ~ "4;"); // ok -} ---- - -) - -Macros: - TITLE=Statements - WIKI=Statement - CATEGORY_SPEC=$0 - EXPRESSION=$(GLINK2 expression, Expression) - PSSEMI_PSCURLYSCOPE=$(GLINK Statement) - PSSEMI_PSCURLYSCOPE_LIST=$(GLINK ScopeStatementList) - PS0=$(GLINK NoScopeNonEmptyStatement) - PSSCOPE=$(GLINK ScopeStatement) - PSCURLY=$(GLINK BlockStatement) - PSSEMI=$(GLINK NoScopeStatement) - PSCURLY_PSSCOPE=$(GLINK ScopeBlockStatement) - PSCURLYSCOPE=$(GLINK NonEmptyOrScopeBlockStatement) - FOO= - diff --git a/std-ddox-override.ddoc b/std-ddox-override.ddoc new file mode 100644 index 0000000000..d4546a659f --- /dev/null +++ b/std-ddox-override.ddoc @@ -0,0 +1,2 @@ +MYREF = $(D $1) +_= diff --git a/std-ddox.ddoc b/std-ddox.ddoc new file mode 100644 index 0000000000..f191eddb39 --- /dev/null +++ b/std-ddox.ddoc @@ -0,0 +1,16 @@ +D = <code class="lang-d">$0</code> +LREF = $(D $1) +ROOT_DIR=/ +_= + +REF_HELPER=$2$(DOT_PREFIXED_SKIP $+).$1 +REF=$(D $(REF_HELPER $1, $+)) +REF1=$(D $2.$1) +REF_ALTTEXT=$(DDOX_NAMED_REF $(REF_HELPER $+), $1) +REF1_ALTTEXT=$(D $3.$2, $1) +MREF_HELPER=$1$(DOT_PREFIXED $+) +MREF=$(D $(MREF_HELPER $1, $+)) +MREF_ALTTEXT=$(DDOX_NAMED_REF $(MREF_HELPER $+), $1) +MREF1=$(D $1) +DDOX_UNITTEST_HEADER=<span class="dlang_runnable"></span> +_= diff --git a/std.ddoc b/std.ddoc index 41d97545a0..9ce7c58412 100644 --- a/std.ddoc +++ b/std.ddoc @@ -1,308 +1,48 @@ -BR = <br> -DDOC_DITTO = $(BR)$0 -DDOC_SUMMARY = $0$(P) -DDOC_DESCRIPTION = $0$(P) -DDOC_AUTHORS = $(B Authors:)$(BR)$0$(P) -DDOC_BUGS = $(RED BUGS:)$(BR)$0$(P) -DDOC_COPYRIGHT = $(B Copyright:)$(BR)$0$(P) -DDOC_DATE = $(B Date:)$(BR)$0$(P) -DDOC_DEPRECATED = $(RED Deprecated:)$(BR)$0$(P) -DDOC_EXAMPLES = $(B Examples:)$(BR)$0$(P) -DDOC_HISTORY = $(B History:)$(BR)$0$(P) -DDOC_LICENSE = $(B License:)$(BR)$0$(P) -DDOC_RETURNS = $(B Returns:)$(BR)$0$(P) -DDOC_SEE_ALSO = $(B See Also:)$(BR)$0$(P) -DDOC_STANDARDS = $(B Standards:)$(BR)$0$(P) -DDOC_THROWS = $(B Throws:)$(BR)$0$(P) -DDOC_VERSION = $(B Version:)$(BR)$0$(P) -DDOC_SECTION_H = $(B $0)$(BR) -DDOC_SECTION = $0$(P) -DDOC_PARAMS = $(B Parameters:)<table class=parms>$0</table>$(P) -DDOC_BLANKLINE = $(P) +ROOT_DIR = ../ +ROOT = .. +SELF_PATH = phobos/ +BODYCLASS = std +SEARCHDEFAULT_PHOBOS = selected +BODY_PREFIX = $(DIVCID quickindex, quickindex, ) +LAYOUT_SUFFIX = +$(SCRIPTLOAD ../js/listanchors.js) +$(SCRIPTLOAD ../js/show_contributors.js) +$(SCRIPT jQuery(document).ready(listanchors);) +LAYOUT_TITLE=$(H1 $(D_TITLE $(TITLE))) +_= -DDOC = <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" - "http://www.w3.org/TR/html4/loose.dtd"> -<html lang='en'> - -<!-- - Copyright (c) 1999-2010 by Digital Mars - All Rights Reserved Written by Walter Bright - http://www.digitalmars.com - --> - -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8" > -<title>$(TITLE) - D Programming Language - Digital Mars - - - - - - - - - - -
    - - -
    - - -
    -

    $(TITLE)

    -
    - $(BODY) - $(GOOGLE_FOOTER) -
    - - - - - - - -GOOGLE_FOOTER= -

    -

    - - - - -TOP= - - -NAVIGATION_PHOBOS= - - -RED = $0 -GREEN = $0 -BLUE = $0 -YELLOW = $0 -BLACK = $0 -WHITE = $0 - -D_COMMENT = $0 -D_STRING = $0 -D_KEYWORD = $0 -D_PSYMBOL = $0 -D_PARAM = $0 -RPAREN = ) -LPAREN = ( -LESS = < -GREATER = > -WEB = $(LINK2 http://$1,$2) -LUCKY = $(WEB -google.com/search?btnI=I%27m+Feeling+Lucky&ie=UTF-8&oe=UTF-8&q=$0,$0) -D = $0 -BIGOH = Ο($(D $0)) -GLOSSARY = $(LINK2 ../glossary.html#$0, $0) - -DDOC_PSYMBOL = $0 -DDOC_DECL =
    $0
    -XREF = $(D std.$1.$2) -CXREF = $(D core.$1.$2) -ECXREF = $(D etc.c.$1.$2) LREF = $(D $1) -BUGZILLA = $(LINK2 http://d.puremagic.com/issues/show_bug.cgi?id=$0, Bugzilla $0) -PRE =
    $0
    -PHOBOSSRC=$(LINK2 https://github.com/D-Programming-Language/phobos/blob/master/$0, $0) -DRUNTIMESRC=$(LINK2 https://github.com/D-Programming-Language/druntime/blob/master/src/$0, $0) -SAMPLESRC=$(LINK2 https://github.com/D-Programming-Language/dmd/blob/master/samples/$0, /dmd/samples/d/$0) - -BOOKTABLE =
    $1$1
    $2
    $1
    -LEADINGROW =     $0 -TABLE = $2
    $1
    -TD = $0 -TDNW = $0 -SUB = $0 - -COPYRIGHT= Copyright © 1999-$(YEAR) by Digital Mars, All Rights Reserved - +_= + +_=Override PHOBOS_PATH to use relative paths in Phobos module and symbol links +PHOBOS_PATH= +_= + +LEADINGROW = $(NBSP)$(NBSP)$(NBSP)$(NBSP)$0 +LEADINGROWN = $(NBSP)$(NBSP)$(NBSP)$(NBSP)$+ +TABLE = $+
    $1
    +TD = $0 +TDNW = $0 +SUB_IS_DEPRECATED=kept for compatibility, but collides with SUB=⊂ use SUBSCRIPT instead (this is a comment and can be changed into one if ddoc files ever start supporting comments) +MYREF = $(TT $1)$(NBSP) +_= + +MODULE=$(D $1) +MODULE2=$(MODULE $2, $1, $+) +MODULE3=$(MODULE $3, $1, $+) +MODULE4=$(MODULE $4, $1, $+) +MODULE5=$(MODULE $5, $1, $+) +MODULE6=$(MODULE $6, $1, $+) +MODULE7=$(MODULE $7, $1, $+) +MODULE8=$(MODULE $8, $1, $+) +PACKAGE=$1$(ITEMIZE $+) +PACKAGE_NAME=$(T h7,$(D $1)) +JOIN_LINE_TAIL=$(JOIN_LINE $+) +JOIN_LINE=_$1$(JOIN_LINE $+) +JOIN_DOT_TAIL=$(JOIN_DOT $+) +JOIN_DOT=.$1$(JOIN_DOT $+) +TAIL=$+ +_= + +DDOC_BLANKLINE = $(DIVC blankline)$(LF) +_= diff --git a/std_consolidated.ddoc b/std_consolidated.ddoc index b9ad291840..d732aa3388 100644 --- a/std_consolidated.ddoc +++ b/std_consolidated.ddoc @@ -1,27 +1,29 @@ BR =
    DDOC_DITTO = $(BR)$0 -DDOC_SUMMARY = $0$(P) -DDOC_DESCRIPTION = $0$(P) -DDOC_AUTHORS = $(B Authors:)$(BR)$0$(P) -DDOC_BUGS = $(RED BUGS:)$(BR)$0$(P) -DDOC_COPYRIGHT = $(B Copyright:)$(BR)$0$(P) -DDOC_DATE = $(B Date:)$(BR)$0$(P) -DDOC_DEPRECATED = $(RED Deprecated:)$(BR)$0$(P) -DDOC_EXAMPLES = $(B Examples:)$(BR)$0$(P) -DDOC_HISTORY = $(B History:)$(BR)$0$(P) -DDOC_LICENSE = $(B License:)$(BR)$0$(P) -DDOC_RETURNS = $(B Returns:)$(BR)$0$(P) -DDOC_SEE_ALSO = $(B See Also:)$(BR)$0$(P) -DDOC_STANDARDS = $(B Standards:)$(BR)$0$(P) -DDOC_THROWS = $(B Throws:)$(BR)$0$(P) -DDOC_VERSION = $(B Version:)$(BR)$0$(P) -DDOC_SECTION_H = $(B $0)$(BR) -DDOC_SECTION = $0$(P) -DDOC_PARAMS = $(B Parameters:)$0
    $(P) +DDOC_SUMMARY = $0$(P)$(LF) +DDOC_DESCRIPTION = $0$(P)$(LF) +DDOC_AUTHORS = $(B Authors:)$(BR)$0$(P)$(LF) +DDOC_BUGS = $(RED BUGS:)$(BR)$0$(P)$(LF) +DDOC_COPYRIGHT = $(B Copyright:)$(BR)$0$(P)$(LF) +DDOC_DATE = $(B Date:)$(BR)$0$(P)$(LF) +DDOC_DEPRECATED = $(RED Deprecated:)$(BR)$0$(P)$(LF) +DDOC_EXAMPLES = $(B Examples:)$(BR)$0$(P)$(LF) +DDOC_HISTORY = $(B History:)$(BR)$0$(P)$(LF) +DDOC_LICENSE = $(B License:)$(BR)$0$(P)$(LF) +DDOC_RETURNS = $(B Returns:)$(BR)$0$(P)$(LF) +DDOC_SEE_ALSO = $(B See Also:)$(BR)$0$(P)$(LF) +DDOC_STANDARDS = $(B Standards:)$(BR)$0$(P)$(LF) +DDOC_THROWS = $(B Throws:)$(BR)$0$(P)$(LF) +DDOC_VERSION = $(B Version:)$(BR)$0$(P)$(LF) +DDOC_SECTION_H = $(B $0)$(BR)$(LF) +DDOC_SECTION = $0$(P)$(LF) +DDOC_PARAMS = $(B Parameters:)$0
    $(P)$(LF) DDOC_BLANKLINE = $(P) +_= DDOC =

    $(TITLE)

    $(BODY) -

    [top]
    +

    [top]
    $(LF) +_= RED = $0 GREEN = $0 @@ -29,6 +31,7 @@ BLUE = $0 YELLOW = $0 BLACK = $0 WHITE = $0 +_= D_COMMENT = $0 D_STRING = $0 @@ -39,30 +42,30 @@ RPAREN = ) LPAREN = ( LESS = < GREATER = > -WEB = $(LINK2 http://$1,$2) -LUCKY = $(WEB +HTTP = $(LINK2 http://$1,$2) +HTTPS = $(LINK2 https://$1,$2) +WEB = $(HTTP $1,$2) +LUCKY = $(HTTP google.com/search?btnI=I%27m+Feeling+Lucky&ie=UTF-8&oe=UTF-8&q=$0,$0) -D = $0 +D = $0 D = $0 BIGOH = Ο($(D $0)) -GLOSSARY = $(LINK2 ../glossary.html#$0, $0) +GLOSSARY = $(LINK2 ../spec/glossary.html#$0, $0) +_= DDOC_PSYMBOL = $0 DDOC_DECL =
    $0
    -XREF = $(D std.$1.$2) -CXREF = $(D core.$1.$2) LREF = $(D $1) -BUGZILLA = $(LINK2 http://d.puremagic.com/issues/show_bug.cgi?id=$0, Bugzilla $0) +BUGZILLA = $(LINK2 https://issues.dlang.org/show_bug.cgi?id=$0, Bugzilla $0) PRE =
    $0
    -PHOBOSSRC=$(LINK2 https://github.com/D-Programming-Language/phobos/blob/master/$0, $0) -DRUNTIMESRC=$(LINK2 https://github.com/D-Programming-Language/druntime/blob/master/src/$0, $0) -SAMPLESRC=$(LINK2 https://github.com/D-Programming-Language/dmd/blob/master/samples/$0, /dmd/samples/d/$0) +PHOBOSSRC=$(LINK2 https://github.com/dlang/phobos/blob/master/$0, $0) +DRUNTIMESRC=$(LINK2 https://github.com/dlang/druntime/blob/master/src/$0, $0) +_= -BOOKTABLE =
    $2
    $1
    -LEADINGROW =     $0 -TABLE = $2
    $1
    -TD = $0 -TDNW = $0 +BOOKTABLE =
    $2
    $1
    +LEADINGROW =     $0 +TABLE = $2
    $1
    +TD = $0 +TDNW = $0 SUB = $0 - - +_= diff --git a/std_consolidated_footer.dd b/std_consolidated_footer.dd deleted file mode 100644 index 1beef9eec8..0000000000 --- a/std_consolidated_footer.dd +++ /dev/null @@ -1,27 +0,0 @@ -Ddoc -

    -

    - - - - - - - - - - - - - - - - - - - -Macros: -DDOC = $(BODY) diff --git a/std_consolidated_header.dd b/std_consolidated_header.dd deleted file mode 100644 index 520a4248b9..0000000000 --- a/std_consolidated_header.dd +++ /dev/null @@ -1,159 +0,0 @@ -Ddoc - - - -D Programming Language Standard Library - - - - - - - - -$(DIVID top, - - -) - - -
    -
    - - -Macros: -DIVID =
    $+
    -DDOC = - -$(BODY) diff --git a/std_navbar-prerelease.ddoc b/std_navbar-prerelease.ddoc new file mode 100644 index 0000000000..582112fc3d --- /dev/null +++ b/std_navbar-prerelease.ddoc @@ -0,0 +1,13 @@ +SUBNAV= +$(SUBNAV_TEMPLATE + $(DIVC head, + $(H2 Library Reference) + $(P $(SPANC smallprint, version $(LATEST) (prerelease) $(SPANC separator, $(BR)) + ) + ) + $(P $(LINK2 index.html, overview)) + ) + $(UL $(MODULE_MENU)) +) +_= +EXTRA_FOOTERS=$(SCRIPTLOAD $(STATIC js/run_examples.js)) diff --git a/std_navbar-release.ddoc b/std_navbar-release.ddoc new file mode 100644 index 0000000000..d7b101ebe2 --- /dev/null +++ b/std_navbar-release.ddoc @@ -0,0 +1,13 @@ +SUBNAV= +$(SUBNAV_TEMPLATE + $(DIVC head, + $(H2 Library Reference) + $(P $(SPANC smallprint, version $(LATEST) $(SPANC separator, $(BR)) + ) + ) + $(P $(LINK2 index.html, overview)) + ) + $(UL $(MODULE_MENU)) +) +_= +EXTRA_FOOTERS=$(SCRIPTLOAD $(STATIC js/run_examples.js)) diff --git a/struct.dd b/struct.dd deleted file mode 100644 index 1c4733fad8..0000000000 --- a/struct.dd +++ /dev/null @@ -1,837 +0,0 @@ -Ddoc - -$(SPEC_S Structs & Unions, - - $(P Whereas classes are reference types, structs are value types. - Any C struct can be exactly represented as a D struct. - In C++ parlance, a D struct is a - $(DPLLINK glossary.html#pod, POD (Plain Old Data)) type, - with a trivial constructors and destructors. - Structs and unions are meant as simple aggregations of data, or as a way - to paint a data structure over hardware or an external type. External - types can be defined by the operating system API, or by a file format. - Object oriented features are provided with the class data type. - ) - - $(P A struct is defined to not have an identity; that is, - the implementation is free to make bit copies of the struct - as convenient.) - - $(TABLE2 Struct$(COMMA) Class Comparison Table, - - $(TR - $(TH Feature) - $(TH struct) - $(TH class) - $(TH C struct) - $(TH C++ struct) - $(TH C++ class) - ) - - $(TR - $(TD value type) - $(YES) - $(NO) - $(YES) - $(YES) - $(YES) - ) - - $(TR - $(TD reference type) - $(NO) - $(YES) - $(NO) - $(NO) - $(NO) - ) - - $(TR - $(TD data members) - $(YES) - $(YES) - $(YES) - $(YES) - $(YES) - ) - - $(TR - $(TD hidden members) -$(V1 $(NO)) -$(V2 $(YES)) - $(YES) - $(NO) - $(YES) - $(YES) - ) - - $(TR - $(TD static members) - $(YES) - $(YES) - $(NO) - $(YES) - $(YES) - ) - - $(TR - $(TD default member initializers) - $(YES) - $(YES) - $(NO) - $(NO) - $(NO) - ) - - $(TR - $(TD bit fields) - $(NO) - $(NO) - $(YES) - $(YES) - $(YES) - ) - - $(TR - $(TD non-virtual member functions) - $(YES) - $(YES) - $(NO) - $(YES) - $(YES) - ) - - $(TR - $(TD virtual member functions) - $(NO) - $(YES) - $(NO) - $(YES) - $(YES) - ) - -$(V1 - $(TR - $(TD constructors) - $(NO) - $(YES) - $(NO) - $(YES) - $(YES) - ) - $(TR - $(TD destructors) - $(NO) - $(YES) - $(NO) - $(YES) - $(YES) - ) - $(TR - $(TD RAII) - $(NO) - $(YES) - $(NO) - $(YES) - $(YES) - ) - $(TR - $(TD assign overload) - $(NO) - $(NO) - $(NO) - $(YES) - $(YES) - ) -) -$(V2 - $(TR - $(TD $(LINK2 #Struct-Constructor, constructors)) - $(YES) - $(YES) - $(NO) - $(YES) - $(YES) - ) - $(TR - $(TD $(LINK2 #StructPostblit, postblit)/copy constructors) - $(YES) - $(NO) - $(NO) - $(YES) - $(YES) - ) - $(TR - $(TD $(LINK2 #StructDestructor, destructors)) - $(YES) - $(YES) - $(NO) - $(YES) - $(YES) - ) - $(TR - $(TD $(GLINK2 class, SharedStaticConstructor)s) - $(YES) - $(YES) - $(NO) - $(NO) - $(NO) - ) - $(TR - $(TD $(GLINK2 class, SharedStaticDestructor)s) - $(YES) - $(YES) - $(NO) - $(NO) - $(NO) - ) - $(TR - $(TD RAII) - $(YES) - $(YES) - $(NO) - $(YES) - $(YES) - ) - $(TR - $(TD $(LINK2 #AssignOverload, assign overload)) - $(YES) - $(NO) - $(NO) - $(YES) - $(YES) - ) -) - - $(TR - $(TD $(LINK2 #StructLiteral, literals)) - $(YES) - $(NO) - $(NO) - $(NO) - $(NO) - ) - - $(TR - $(TD operator overloading) - $(YES) - $(YES) - $(NO) - $(YES) - $(YES) - ) - - $(TR - $(TD inheritance) - $(NO) - $(YES) - $(NO) - $(YES) - $(YES) - ) - - $(TR - $(TD invariants) - $(YES) - $(YES) - $(NO) - $(NO) - $(NO) - ) - - $(TR - $(TD unit tests) - $(YES) - $(YES) - $(NO) - $(NO) - $(NO) - ) - - $(TR - $(TD synchronizable) - $(NO) - $(YES) - $(NO) - $(NO) - $(NO) - ) - - $(TR - $(TD parameterizable) - $(YES) - $(YES) - $(NO) - $(YES) - $(YES) - ) - - $(TR - $(TD alignment control) - $(YES) - $(YES) - $(NO) - $(NO) - $(NO) - ) - - $(TR - $(TD member protection) - $(YES) - $(YES) - $(NO) - $(YES) - $(YES) - ) - - $(TR - $(TD default public) - $(YES) - $(YES) - $(YES) - $(YES) - $(NO) - ) - - $(TR - $(TD tag name space) - $(NO) - $(NO) - $(YES) - $(YES) - $(YES) - ) - - $(TR - $(TD anonymous) - $(YES) - $(NO) - $(YES) - $(YES) - $(YES) - ) - - $(TR - $(TD static constructor) - $(YES) - $(YES) - $(NO) - $(NO) - $(NO) - ) - - $(TR - $(TD static destructor) - $(YES) - $(YES) - $(NO) - $(NO) - $(NO) - ) - -$(V2 - $(TR - $(TD const/immutable/shared) - $(YES) - $(YES) - $(NO) - $(NO) - $(NO) - ) - - $(TR - $(TD inner nesting) - $(TD $(LINK2 #nested, YES)) - $(TD $(DDSUBLINK class, nested, YES)) - $(NO) - $(NO) - $(NO) - ) -) - ) - -$(GRAMMAR -$(GNAME AggregateDeclaration): - $(B struct) $(I Identifier) $(GLINK StructBody) - $(B union) $(I Identifier) $(GLINK StructBody) - $(B struct) $(I Identifier) $(B ;) - $(B union) $(I Identifier) $(B ;) - $(GLINK2 template, StructTemplateDeclaration) - $(GLINK2 template, UnionTemplateDeclaration) - -$(GNAME StructBody): - $(B {) $(B }) - $(B {) $(GLINK StructBodyDeclarations) $(B }) - -$(GNAME StructBodyDeclarations): - $(GLINK StructBodyDeclaration) - $(GLINK StructBodyDeclaration) $(I StructBodyDeclarations) - -$(GNAME StructBodyDeclaration): - $(GLINK2 module, DeclDef) - $(GLINK StructAllocator) - $(GLINK StructDeallocator) -$(V2 $(GLINK StructPostblit) - $(GLINK2 class, AliasThis)) - -$(GNAME StructAllocator): - $(GLINK2 class, ClassAllocator) - -$(GNAME StructDeallocator): - $(GLINK2 class, ClassDeallocator) -) - -$(P They work like they do in C, with the following exceptions:) - -$(UL - $(LI no bit fields) - $(LI alignment can be explicitly specified) - $(LI no separate tag name space - tag names go into the current scope) - $(LI declarations like: - ------- -struct ABC x; ------- - are not allowed, replace with: - ------- -ABC x; ------- - ) - $(LI anonymous structs/unions are allowed as members of other structs/unions) - $(LI Default initializers for members can be supplied.) - $(LI Member functions and static members are allowed.) -) - - -

    Opaque Structs and Unions

    - - $(P Opaque struct and union declarations do not have a $(GLINK StructBody):) - ---- -struct S; -union U; ---- - - $(P The members are completely hidden to the user, and so the only operations - on those types are ones that do not require any knowledge of the contents - of those types. For example:) - ---- -struct S; -S.sizeof; // error, size is not known -S s; // error, cannot initialize unknown contents -S* p; // ok, knowledge of members is not necessary ---- - - $(P They can be used to implement the - $(LINK2 http://en.wikipedia.org/wiki/Opaque_pointer, PIMPL idiom).) - - -

    Static Initialization of Structs

    - - Static struct members are by default initialized to whatever the - default initializer for the member is, and if none supplied, to - the default initializer for the member's type. - If a static initializer is supplied, the - members are initialized by the member name, - colon, expression syntax. The members may be initialized in any order. - Initializers for statics must be evaluatable at compile time. - Members not specified in the initializer list are default initialized. - ------- -struct S { int a; int b; int c; int d = 7;} -static S x = { a:1, b:2}; // c is set to 0, d to 7 -static S z = { c:4, b:5, a:2 , d:5}; // z.a = 2, z.b = 5, z.c = 4, z.d = 5 ------- - - C-style initialization, based on the order of the members in the - struct declaration, is also supported: - ------- -static S q = { 1, 2 }; // q.a = 1, q.b = 2, q.c = 0, q.d = 7 ------- - - $(P Struct literals can also be used to initialize statics, but - they must be evaluable at compile time.) - ------ -static S q = S( 1, 2+3 ); // q.a = 1, q.b = 5, q.c = 0, q.d = 7 ------ - - $(P The static initializer syntax can also be used to initialize - non-static variables, provided that the member names are not given. - The initializer need not be evaluatable at compile time.) - ----- -void test(int i) { - S q = { 1, i }; // q.a = 1, q.b = i, q.c = 0, q.d = 7 -} ----- - - -

    Static Initialization of Unions

    - - Unions are initialized explicitly. - ------- -union U { int a; double b; } -static U u = { b : 5.0 }; // u.b = 5.0 ------- - - Other members of the union that overlay the initializer, - but occupy more storage, have - the extra storage initialized to zero. - -

    Dynamic Initialization of Structs

    - - $(P Structs can be dynamically initialized from another - value of the same type:) - ----- -struct S { int a; } -S t; // default initialized -t.a = 3; -S s = t; // s.a is set to 3 ----- - - $(P If $(D opCall) is overridden for the struct, and the struct - is initialized with a value that is of a different type, - then the $(D opCall) operator is called:) - ----- -struct S { - int a; - - static S $(B opCall)(int v) - { S s; - s.a = v; - return s; - } - - static S $(B opCall)(S v) - { S s; - s.a = v.a + 1; - return s; - } -} - -S s = 3; // sets s.a to 3 -S t = s; // sets t.a to 3, S.$(B opCall)(s) is not called ----- - -

    $(LNAME2 StructLiteral, Struct Literals)

    - - $(P Struct literals consist of the name of the struct followed - by a parenthesized argument list:) - ---- -struct S { int x; float y; } - -int foo(S s) { return s.x; } - -foo( S(1, 2) ); // set field x to 1, field y to 2 ---- - - $(P Struct literals are syntactically like function calls. - If a struct has a member function named $(CODE opCall), then - struct literals for that struct are not possible. - It is an error if there are more arguments than fields of - the struct. - If there are fewer arguments than fields, the remaining - fields are initialized with their respective default - initializers. - If there are anonymous unions in the struct, only the first - member of the anonymous union can be initialized with a - struct literal, and all subsequent non-overlapping fields are default - initialized. - ) - -

    Struct Properties

    - -$(TABLE2 Struct Properties, -$(TR $(TD .sizeof) $(TD Size in bytes of struct)) -$(TR $(TD .alignof) $(TD Size boundary struct needs to be aligned on)) -$(TR $(TD .tupleof) $(TD Gets type tuple of fields)) -) - -

    Struct Field Properties

    - -$(TABLE2 Struct Field Properties, -$(TR $(TD .offsetof) $(TD Offset in bytes of field from beginning of struct)) -) - -$(V2 -$(SECTION3 Const and Immutable Structs, - - $(P A struct declaration can have a storage class of - $(CODE const), $(CODE immutable) or $(CODE shared). It has an equivalent - effect as declaring each member of the struct as - $(CODE const), $(CODE immutable) or $(CODE shared). - ) - ----- -const struct S { int a; int b = 2; } - -void main() { - S s = S(3); // initializes s.a to 3 - S t; // initializes t.a to 0 - t = s; // error, t is const - t.a = 4; // error, t.a is const -} ----- -) -) - -$(V2 -$(SECTION3 Struct Constructors, - - $(P Struct constructors are used to initialize an instance - of a struct. - The $(I ParameterList) may not be empty. - Struct instances that are not instantiated with a constructor - are default initialized to their $(CODE .init) value. - ) - ------- -struct S { - int x, y; - - this() // error, cannot implement default ctor for structs - { - } - - this(int a, int b) - { - x = a; - y = b; - } -} - -void main() -{ - S a = S(4, 5); - auto b = S(); // same as auto b = S.init; -} ------- -) -) - -$(V2 -$(SECTION3 Struct Postblits, - -$(GRAMMAR -$(GNAME StructPostblit): - $(B this(this)) $(GLINK2 function, FunctionBody) -) - - $(P $(I Copy construction) is defined as initializing - a struct instance from another struct of the same type. - Copy construction is divided into two parts:) - - $(OL - $(LI blitting the fields, i.e. copying the bits) - $(LI running $(I postblit) on the result) - ) - - $(P The first part is done automatically by the language, - the second part is done if a postblit function is defined - for the struct. - The postblit has access only to the destination struct object, - not the source. - Its job is to $(SINGLEQUOTE fix up) the destination as necessary, such as - making copies of referenced data, incrementing reference counts, - etc. For example: - ) - ---- -struct S { - int[] a; // array is privately owned by this instance - this(this) { - a = a.dup; - } - ~this() { - delete a; - } -} ---- - - $(P Unions may not have fields that have postblits.) -) -) - -$(V2 -$(SECTION3 Struct Destructors, - - $(P Destructors are called when an object goes out of scope. - Their purpose is to free up resources owned by the struct - object. - ) - - $(P Unions may not have fields that have destructors.) -) -) - -$(V2 -$(SECTION3 Assignment Overload, - - $(P While copy construction takes care of initializing - an object from another object of the same type, - assignment is defined as copying the contents of one - object over another, already initialized, type: - ) - ---- -struct S { ... } -S s; // default construction of s -S t = s; // t is copy-constructed from s -t = s; // t is assigned from s ---- - - $(P Struct assignment $(CODE t=s) is defined to be semantically - equivalent to: - ) - ---- -t.opAssign(s); ---- - - $(P where $(CODE opAssign) is a member function of S:) - ---- -S* opAssign(ref const S s) -{ ... bitcopy *this into tmp ... - ... bitcopy s into *this ... - ... call destructor on tmp ... - return this; -} ---- - - $(P While the compiler will generate a default $(CODE opAssign) - as needed, a user-defined one can be supplied. The user-defined - one must still implement the equivalent semantics, but can - be more efficient. - ) - - $(P One reason a custom $(CODE opAssign) might be more efficient - is if the struct has a reference to a local buffer: - ) - ---- -struct S { - int[] buf; - int a; - - S* opAssign(ref const S s) { - a = s.a; - return this; - } - - this(this) { - buf = buf.dup; - } - - ~this() { - delete buf; - } -} ---- - - $(P Here, $(CODE S) has a temporary workspace $(CODE buf[]). - The normal postblit - will pointlessly free and reallocate it. The custom $(CODE opAssign) - will reuse the existing storage. - ) - -) -) - -$(V2 -

    $(LNAME2 nested, Nested Structs)

    - - $(P A $(I nested struct) is a struct that is declared inside the scope - of a function or a templated struct that has aliases to local - functions as a template argument. - Nested structs have member functions. - It has access to the context of its enclosing scope - (via an added hidden field). - ) - ---- -void foo() { - int i = 7; - struct SS { - int x,y; - int bar() { return x + i + 1; } - } - SS s; - s.x = 3; - s.bar(); // returns 11 -} ---- - - $(P Nested structs cannot be used as fields or as the - element type of an array: - ) - ---- -void foo() { - int i = 7; - struct SS { - int x,y; - int bar() { return x + i + 1; } - } - struct DD { - SS s; // error, cannot be field - } - SS[3] a; // error, cannot be array element - SS[] a; // error, cannot be array element -} ---- - - $(P A struct can be prevented from being nested by - using the static attribute, but then of course it - will not be able to access variables from its enclosing - scope.) - ---- -void foo() { - int i = 7; - $(B static) struct SS { - int x,y; - int bar() { - return i; // error, SS is not a nested struct - } - } -} ---- - - $(P A templated struct can become a nested struct if it - has a local function passed as an aliased argument: - ) - ---- -struct A(alias F) { - int fun(int i) { return F(i); } -} - -A!(F) makeA(alias F)() {return A!(F)(); } - -void main() { - int x = 40; - int fun(int i) { return x + i; } - A!(fun) a = makeA!(fun)(); - a.fun(2); -} ---- -) - -) - -Macros: - TITLE=Structs, Unions - WIKI=Struct - CATEGORY_SPEC=$0 - NO=$(TD  ) - YES=$(TD X) - FOO= diff --git a/template-comparison.dd b/template-comparison.dd deleted file mode 100644 index 7e345febb7..0000000000 --- a/template-comparison.dd +++ /dev/null @@ -1,879 +0,0 @@ -Ddoc - -$(COMMUNITY Template Comparison, - -$(P C++ pioneered templates and template metaprogramming, and continues -to improve on it with C++0x. -The D programming language is the first to comprehensively reengineer -templates based on the C++ experience. -Since C++0x is not a ratified standard yet, proposed changes to C++ -are subject to change.) - - - - - - $(TR - $(TH Feature) - $(TH D) - $(TH C++98) - $(TH C++0x) - ) - - - - - $(TR - $(TD Argument list delineation) - $(TD Uses !( ), as in Foo!(int)) - $(TD Uses < > as in Foo<int>) - $(TD No change) - ) - - $(TR - $(TD Class Templates) - $(TD Yes: ---- -class Foo(T) -{ - T x; -} ---- -) - $(TD Yes: -$(CPPCODE2 -template<class T> - class Foo -{ - T x; -}; -) -) - $(TD No change) - ) - - $(TR - $(TD Function Templates) - $(TD Yes: ---- -T foo(T)(T i) -{ - ... -} ---- -) - $(TD Yes: -$(CPPCODE2 -template<class T> - T foo(T i) -{ - ... -} -) -) - $(TD No change) - ) - - $(TR - $(TD Member Templates) - $(TD Yes) - $(TD Yes) - $(TD No change) - ) - - $(TR - $(TD Constructor Templates) - $(TD No) - $(TD Yes) - $(TD No change) - ) - - $(TR - $(TD Parameterize any Declaration) - $(TD Yes, classes, functions, typedefs, - variables, enums, etc. can be parameterized, - such as this variable: ---- -template Foo(T) -{ - static T* p; -} ---- -) - $(TD No, only classes and functions) - $(TD No change) - ) - - $(TR - $(TD Template Typedefs: Create an alias that binds to some but not all - of the template parameters) - $(TD Yes: ---- -class Foo(T, U) { } -template MyFoo(T) -{ - alias Foo!(T, int) MyFoo; -} -MyFoo!(uint) f; ---- -) - $(TD No) - $(TD Yes: -$(CPPCODE2 -template<class T, class U> class Foo { }; -template<class T> using MyFoo = Foo<T, int>; -MyFoo<unsigned> f; -) -) - ) - - - $(TR - $(TD Sequence Constructors) - $(TD No) - $(TD No) - $(TD Yes: -$(CPPCODE2 -Foo<double> f = { 1.2, 3, 6.8 }; -) -) - ) - - $(TR - $(TD Concepts) -$(V1 - $(TD No, but much the same effect can be achieved with - $(GLINK2 version, StaticIfCondition) and - $(LINK2 version.html#StaticAssert, static asserts)) -) -$(V2 - $(TD Yes: $(LINK2 cpp0x.html#concepts, Constraints)) -) - $(TD No) - $(TD Yes: $(LINK2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1849.pdf, Concepts for C++0x N1849)) - ) - - - $(TR - $(TD Recursive Templates) - $(TD Yes: ---- -template factorial(int n) -{ - const factorial = - n * factorial!(n-1); -} -template factorial(int n : 1) -{ - const factorial = 1; -} ---- -) - $(TD Yes: -$(CPPCODE2 -template<int n> class factorial -{ - public: - enum - { - result = - n * factorial<n-1>::result - }; -}; -template<> class factorial<1> -{ - public: - enum { result = 1 }; -}; -) -) - $(TD No change) - ) - - $(TR - $(TD Conditional Compilation based on - Template Arguments) - $(TD Yes: ---- -template factorial(int n) -{ - static if (n == 1) - const factorial = 1; - else - const factorial = - n * factorial!(n-1); -} ---- -) - $(TD No: -$(CPPCODE2 -template<int n> class factorial -{ - public: - enum - { -#if (n == 1) // $(ERROR) - result = 1; -#else - result = - n * factorial<n-1>::result -#endif - }; -}; -) -) - $(TD No change) - ) - - $(TR - $(TD Template Declarations (with no definition)) - $(TD No) - $(TD Yes: -$(CPPCODE2 -template<class T> - class Foo; -) -) - $(TD No change) - ) - - $(TR - $(TD Grouping templates with the same parameters together) - $(TD Yes: ---- -template Foo(T, U) -{ - class Bar { ... } - T foo(T t, U u) { ... } -} -Foo!(int,long).Bar b; -return Foo!(char,int).foo('c',3); ---- -) - $(TD No, each must be separate: -$(CPPCODE2 -template<class T, class U> - class Foo_Bar { ... }; -template<class T, class U> - T Foo_foo(T t, U u) { ... }; -Foo_Bar<int,long> b; -return Foo_foo<char,int>('c',3); -) -) - $(TD No change) - ) - - $(TR - $(TD Compile time execution of functions) - $(TD $(DDSUBLINK function, interpretation, Yes): ---- -int factorial(int i) -{ if (i == 0) - return 1; - else - return i * factorial(i - 1); -} -static f = factorial(6); ---- - ) - $(TD No) - $(TD Named constant expressions with parameters: - $(LINK2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1972.pdf, Generalized Constant Expressions N1972)) - ) - - $(TR - $(TH Parameters) - $(TH D) - $(TH C++98) - $(TH C++0x) - ) - - $(TR - $(TD Type Parameters) - $(TD Yes: ---- -class Foo(T) -{ - T x; -} -Foo!(int) f; ---- -) - $(TD Yes: -$(CPPCODE2 -template<class T> - class Foo -{ - T x; -}; -Foo<int> f; -) -) - $(TD No change) - ) - - $(TR - $(TD Integral Parameters) - $(TD Yes: ---- -void foo(int i)() -{ - int v = i; -} ---- -) - $(TD Yes: -$(CPPCODE2 -template<int i> - void foo() -{ - int v = i; -} -) -) - $(TD No change) - ) - - $(TR - $(TD Pointer Parameters) - $(TD Yes, a pointer to object or function) - $(TD Yes, a pointer to object or function) - $(TD No change) - ) - - $(TR - $(TD Reference Parameters) - $(TD No, D does not have a general reference type) - $(TD Yes: -$(CPPCODE2 -template<double& D> - void foo() -{ - double y = D; -} -) -) - $(TD No change) - ) - - $(TR - $(TD Pointer to Member Parameters) - $(TD No, D does not have pointers to members, it has - $(LINK2 type.html#delegates, delegates), - which can be used as parameters) - $(TD Yes) - $(TD No change) - ) - - $(TR - $(TD Template Template Parameters) - $(TD Yes: ---- -class Foo(T, alias C) -{ - C!(T) x; -} ---- -) - $(TD Yes: -$(CPPCODE2 -template<class T, - template<class U> class C> - class Foo -{ - C<T> x; -}; -) -) - $(TD No change) - ) - - $(TR - $(TD Alias Parameters) - $(TD Yes, any symbol can be passed to a template as an alias: ---- -void bar(int); -void bar(double); -void foo(T, alias S)(T t) -{ - S(t); -} -// calls bar(double) -foo!(double, bar)(1); ---- -) - $(TD No) - $(TD No change) - ) - - $(TR - $(TD Floating Point Parameters) - $(TD Yes: ---- -class Foo(double D) -{ - double x = D; -} -... -Foo!(1.6) F; ---- -) - $(TD No) - $(TD No change) - ) - - $(TR - $(TD String Parameters) - $(TD Yes: ---- -void foo(char[] format)(int i) -{ - writefln(format, i); -} -... -foo!("i = %s")(3); ---- -) - $(TD No) - $(TD No change) - ) - - $(TR - $(TD Local Class Parameters) - $(TD Yes) - $(TD No) - $(TD Issue N1945) - ) - - $(TR - $(TD Local Variable Parameters) - $(TD Yes) - $(TD No) - $(TD No change) - ) - - $(TR - $(TD Parameter Default Values) - $(TD Yes: ---- -class Foo(T = int) -{ - T x; -} ---- -) - $(TD Yes: -$(CPPCODE2 -template<class T = int> - class Foo -{ - T x; -}; -) -) - $(TD No change) - ) - - $(TR - $(TD Variadic Parameters) - $(TD Yes, $(LINK2 variadic-function-templates.html, Variadic Templates): ---- -void print(A...)(A a) -{ - foreach(t; a) - writefln(t); -} ---- -) - $(TD No) - $(TD $(LINK2 http://www.osl.iu.edu/~dgregor/cpp/variadic-templates.pdf, Variadic Templates N2080)) - ) - - $(TR - $(TH Specializations) - $(TH D) - $(TH C++98) - $(TH C++0x) - ) - - $(TR - $(TD Explicit Specialization) - $(TD Yes: ---- -class Foo(T : int) -{ - T x; -} ---- -) - $(TD Yes: -$(CPPCODE2 -template<> - class Foo<int> -{ - int x; -}; -) -) - $(TD No change) - ) - - $(TR - $(TD Partial Specialization) - $(TD Yes: ---- -class Foo(T : T*, U) -{ - T x; -} ---- -) - $(TD Yes: -$(CPPCODE2 -template<class T, class U> - class Foo<T*, U> -{ - T x; -}; -) -) - $(TD No change) - ) - - $(TR - $(TD Partial specialization derived from multiple parameters) - $(TD Yes: ---- -class Foo(T : Bar!(T, U), U) -{ - ... -} ---- -) - $(TD Yes: -$(CPPCODE2 -template<class T, class U> - class Foo< Bar<T,U> > -{ - ... -}; -) -) - $(TD No change) - ) - - $(TR - $(TD Can specializations exist without a primary template?) - $(TD Yes) - $(TD No) - $(TD No change) - ) - - $(TR - $(TH Other) - $(TH D) - $(TH C++98) - $(TH C++0x) - ) - - $(TR - $(TD Exported Templates) - $(TD Yes, it falls out as a natural consequence of modules) - $(TD Yes, though only in compilers based on EDG's front end) - $(TD No change) - ) - - $(TR - $(TD $(SFINAE)) - $(TD Yes) - $(TD Yes) - $(TD No change) - ) - - $(TR - $(TD Parse Template Definition Bodies before Instantiation) - $(TD Yes) - $(TD Not required by Standard, but some implementations do) - $(TD No change) - ) - - $(TR - $(TD Overloading Function Templates with Functions) - $(TD No, but the equivalent can be done with explicitly specialized - templates: ---- -void foo(T)(T t) { } -void foo(T:int)(int t) { } ---- -) - $(TD Yes: -$(CPPCODE2 -template<class T> - void foo(T i) { } -void foo(int t) { } -) -) - $(TD No change) - ) - - $(TR - $(TD Implicit Function Template Instantiation) - $(TD Yes) - $(TD Yes) - $(TD No change) - ) - - $(TR - $(TD Templates can be evaluated in scope - of instantiation rather than definition) - $(TD Yes, $(LINK2 mixin.html, Mixins)) - $(TD No, but can be faked using macros) - $(TD No change) - ) - - $(TR - $(TH Parsing Idiosyncracies) - $(TH D) - $(TH C++98) - $(TH C++0x) - ) - - - - $(TR - $(TD Context-Free Grammar) - $(TD Yes: ---- -class Foo!(int i) -{ - ... -} -Foo!(3 $(B >) 4) f; ---- -) - $(TD No: -$(CPPCODE2 -template<int i> class Foo -{ - ... -}; -Foo<3 $(B >) 4> f; // $(ERROR) -) -) - $(TD No change) - ) - - - $(TR - $(TD Distinguish template arguments from other operators) - $(TD Yes: ---- -class Foo!(T) -{ - ... -} -class Bar!(int i) -{ - ... -} -Foo!(Bar!(1)) x1; ---- -) - $(TD No: -$(CPPCODE2 -template<class T> class Foo -{ - ... -}; -template<int i> class Bar -{ - ... -}; -Foo<Bar<1>> x1; // $(ERROR) -Foo<Bar<1> > x2; -) -) - $(TD Partially fixed by - $(LINK2 http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1757.html, Right Angle Brackets N1757) - ) - - ) - - - $(TR - $(TD Redeclaration of Template Parameter) - $(TD Yes: ---- -class Foo(T) -{ - int T; - void foo() - { - int T; - } -} ---- -) - $(TD No: -$(CPPCODE2 -template<class T> - class Foo -{ - int T; // $(ERROR) - void foo() - { - int T; // $(ERROR) - } -}; -) -) - $(TD No change) - ) - - $(TR - $(TD Dependent Base Class Lookup) - $(TD Yes: ---- -class Foo(T) -{ - typedef int $(B A); -} -class Bar(T) : Foo(T) -{ - $(B A) x; -} ---- -) - $(TD No: -$(CPPCODE2 -template<class T> - class Foo -{ - public: - typedef int $(B A); -}; -template<class T> - class Bar : Foo<T> -{ - public: - $(B A) x; // $(ERROR) -}; -) -) - $(TD No change) - ) - - - - - $(TR - $(TD Forward Referencing) - $(TD Yes: ---- -int $(B g)(void *); - -class Foo(T) -{ - int foo() - { - return $(B g)(1); - } -} - -int $(B g)(int i); ---- -) - $(TD No: -$(CPPCODE2 -int $(B g)(void *); - -template<class T> - class Foo -{ - int foo() - { - return $(B g)(1); // $(ERROR) - } -}; - -int $(B g)(int i); -) -) - $(TD No change) - ) - - - $(TR - $(TD Member templates parseable without hints) - $(TD Yes: ---- -class Foo -{ - Foo bar!(int I)(); -} -void abd(T)(T f) -{ - T f1 = f.bar!(3)(); -} ---- -) - $(TD No: -$(CPPCODE2 -class Foo -{ - public: - template<int> Foo *bar(); -}; -template<class T> void abc(T *f) -{ - T *f1 = f->bar<3>(); // $(ERROR) - T *f2 = f->$(B template) bar<3>(); -} -) -) - $(TD No change) - ) - - - $(TR - $(TD Dependent type members parseable without hints) - $(TD Yes: ---- -class Foo(T) -{ - T.A* a1; -} ---- -) - $(TD No: -$(CPPCODE2 -template class Foo -{ - public: - T::A *a1; // $(ERROR) - $(B typename) T::A *a2; -}; -) -) - $(TD No change) - ) - - -
    Template Comparison Table
    - -) - -Macros: - TITLE=Template Comparison - WIKI=TemplateComparison - NO=No - NO1=No - YES=Yes - YES1=Yes - D_CODE =
    $0
    - CPPCODE2 =
    $0
    - ERROR = $(RED $(B error)) -META_KEYWORDS=D Programming Language, template metaprogramming, -variadic templates, type deduction, dependent base class -META_DESCRIPTION=Comparison of templates between the -D programming language, C++, and C++0x diff --git a/template-mixin.dd b/template-mixin.dd deleted file mode 100644 index 4bf830bd16..0000000000 --- a/template-mixin.dd +++ /dev/null @@ -1,310 +0,0 @@ -Ddoc - -$(SPEC_S Template Mixins, - - A $(I TemplateMixin) takes an arbitrary set of declarations from - the body of a $(I TemplateDeclaration) and inserts them - into the current context. - -$(GRAMMAR -$(GNAME TemplateMixinDeclaration): - $(V2 $(B mixin)) $(B template) $(TEMPLATEIDENTIFIER) $(B $(LPAREN)) $(TEMPLATEPARAMETERLIST) $(B $(RPAREN)) $(V2 $(GLINK2 template, Constraint)$(SUB $(I opt))) - $(B {) $(GLINK2 module, DeclDefs) $(B }) - -$(GNAME TemplateMixin): - $(B mixin) $(TEMPLATEIDENTIFIER) $(B ;) - $(B mixin) $(TEMPLATEIDENTIFIER) $(GLINK MixinIdentifier) $(B ;) - $(B mixin) $(TEMPLATEIDENTIFIER) $(B !$(LPAREN)) $(TEMPLATEARGUMENTLIST) $(B $(RPAREN)) $(B ;) - $(B mixin) $(TEMPLATEIDENTIFIER) $(B !$(LPAREN)) $(TEMPLATEARGUMENTLIST) $(B $(RPAREN)) $(GLINK MixinIdentifier) $(B ;) - -$(GNAME MixinIdentifier): - $(I Identifier) -) - - $(P A $(I TemplateMixin) can occur in declaration lists of modules, - classes, structs, unions, and as a statement. - The $(I TemplateIdentifier) refers to a $(I TemplateDeclaration). - If the $(I TemplateDeclaration) has no parameters, the mixin - form that has no !($(I TemplateArgumentList)) - can be used. - ) - - $(P Unlike a template instantiation, a template mixin's body is evaluated - within the scope where the mixin appears, not where the template declaration - is defined. It is analogous to cutting and pasting the body of - the template into the location of the mixin. It is useful for injecting - parameterized $(SINGLEQUOTE boilerplate) code, as well as for creating - templated nested functions, which is not possible with - template instantiations. - ) - ------- -$(V2 mixin) template Foo() { - int x = 5; -} - -$(B mixin Foo;) - -struct Bar { - $(B mixin Foo;) -} - -void test() { - writefln("x = %d", x); // prints 5 - { - Bar b; - int x = 3; - - writefln("b.x = %d", b.x); // prints 5 - writefln("x = %d", x); // prints 3 - { - $(B mixin Foo;) - writefln("x = %d", x); // prints 5 - x = 4; - writefln("x = %d", x); // prints 4 - } - writefln("x = %d", x); // prints 3 - } - writefln("x = %d", x); // prints 5 -} ------- - - Mixins can be parameterized: - ------- -$(V2 mixin) template Foo(T) { - T x = 5; -} - -$(B mixin Foo!(int);) // create x of type int ------- - - Mixins can add virtual functions to a class: - ------- -$(V2 mixin) template Foo() { - void func() { writefln("Foo.func()"); } -} - -class Bar { - $(B mixin Foo); -} - -class Code : Bar { - void func() { writefln("Code.func()"); } -} - -void test() { - Bar b = new Bar(); - b.func(); // calls Foo.func() - - b = new Code(); - b.func(); // calls Code.func() -} ------- - - Mixins are evaluated in the scope of where they appear, not the scope - of the template declaration: - ------- -int y = 3; - -$(V2 mixin) template Foo() { - int abc() { return y; } -} - -void test() { - int y = 8; - $(B mixin Foo;) // local y is picked up, not global y - assert(abc() == 8); -} ------- - - Mixins can parameterize symbols using alias parameters: - ------- -$(V2 mixin) template Foo(alias b) { - int abc() { return b; } -} - -void test() { - int y = 8; - $(B mixin Foo!(y);) - assert(abc() == 8); -} ------- - - This example uses a mixin to implement a generic Duff's device - for an arbitrary statement (in this case, the arbitrary statement - is in bold). A nested function is generated as well as a - delegate literal, these can be inlined by the compiler: - ------- -$(V2 mixin) template duffs_device(alias id1, alias id2, alias s) -{ - void duff_loop() - { - if (id1 < id2) - { - typeof(id1) n = (id2 - id1 + 7) / 8; - switch ((id2 - id1) % 8) - { - case 0: do { s(); $(V2 goto case;) - case 7: s(); $(V2 goto case;) - case 6: s(); $(V2 goto case;) - case 5: s(); $(V2 goto case;) - case 4: s(); $(V2 goto case;) - case 3: s(); $(V2 goto case;) - case 2: s(); $(V2 goto case;) - case 1: s(); - } while (--n > 0); - } - } - } -} - -void foo() { writefln("foo"); } - -void test() { - int i = 1; - int j = 11; - - mixin duffs_device!(i, j, $(B delegate { foo(); }) ); - duff_loop(); // executes foo() 10 times -} ------- - -

    Mixin Scope

    - - The declarations in a mixin are $(SINGLEQUOTE imported) into the surrounding - scope. If the name of a declaration in a mixin is the same - as a declaration in the surrounding scope, the surrounding declaration - overrides the mixin one: - ------- -int x = 3; - -$(V2 mixin) template Foo() { - int x = 5; - int y = 5; -} - -$(B mixin Foo;) -int y = 3; - -void test() { - writefln("x = %d", x); // prints 3 - writefln("y = %d", y); // prints 3 -} ------- - - If two different mixins are put in the same scope, and each - define a declaration with the same name, there is an ambiguity - error when the declaration is referenced: - ------- -$(V2 mixin) template Foo() { - int x = 5; - void func(int x) { } -} - -$(V2 mixin) template Bar() { - int x = 4; - void func() { } -} - -$(B mixin Foo;) -$(B mixin Bar;) - -void test() { - writefln("x = %d", x); // error, x is ambiguous - func(); // error, func is ambiguous -} ------- - $(P The call to $(B func()) is ambiguous because - Foo.func and Bar.func are in different scopes. - ) - - $(P If a mixin has a $(I MixinIdentifier), it can be used to - disambiguate: - ) ------- -int x = 6; - -$(V2 mixin) template Foo() { - int x = 5; - int y = 7; - void func() { } -} - -$(V2 mixin) template Bar() { - int x = 4; - void func() { } -} - -$(B mixin Foo F;) -$(B mixin Bar B;) - -void test() { - writefln("y = %d", y); // prints 7 - writefln("x = %d", x); // prints 6 - writefln("F.x = %d", F.x); // prints 5 - writefln("B.x = %d", B.x); // prints 4 - F.func(); // calls Foo.func - B.func(); // calls Bar.func -} ------- - $(P Alias declarations can be used to overload together - functions declared in different mixins:) - ------ -$(V2 mixin) template Foo() { - void func(int x) { } -} - -$(V2 mixin) template Bar() { - void func() { } -} - -mixin Foo!() F; -mixin Bar!() B; - -$(B alias F.func func;) -$(B alias B.func func;) - -void main() { - func(); // calls B.func - func(1); // calls F.func -} ------ - - - $(P A mixin has its own scope, even if a declaration is overridden - by the enclosing one:) - ------- -int x = 4; - -$(V2 mixin) template Foo() { - int x = 5; - int bar() { return x; } -} - -$(B mixin Foo;) - -void test() { - writefln("x = %d", x); // prints 4 - writefln("bar() = %d", bar()); // prints 5 -} ------- - -) - -Macros: - TITLE=Mixins - WIKI=Mixin - CATEGORY_SPEC=$0 - TEMPLATEIDENTIFIER=$(GLINK2 template, TemplateIdentifier) - TEMPLATEPARAMETERLIST=$(GLINK2 template, TemplateParameterList) - TEMPLATEARGUMENTLIST=$(GLINK2 template, TemplateArgumentList) - FOO= diff --git a/template.dd b/template.dd deleted file mode 100644 index aecf267c75..0000000000 --- a/template.dd +++ /dev/null @@ -1,1030 +0,0 @@ -Ddoc - -$(SPEC_S Templates, - -$(BLOCKQUOTE -I think that I can safely say that nobody understands template mechanics. -- Richard Deyman -) - -$(P Templates are D's approach to generic programming. - Templates are defined with a $(I TemplateDeclaration): -) - -$(GRAMMAR -$(GNAME TemplateDeclaration): - $(B template) $(GLINK TemplateIdentifier) $(B $(LPAREN)) $(GLINK TemplateParameterList) $(B $(RPAREN)) $(V2 $(GLINK Constraint)$(SUB $(I opt))) - $(B {) $(GLINK2 module, DeclDefs) $(B }) - -$(GNAME TemplateIdentifier): - $(I Identifier) - -$(GNAME TemplateParameterList): - $(GLINK TemplateParameter) -$(V2 $(GLINK TemplateParameter) , -) $(GLINK TemplateParameter) , $(I TemplateParameterList) - -$(GNAME TemplateParameter): - $(GLINK TemplateTypeParameter) - $(GLINK TemplateValueParameter) - $(GLINK TemplateAliasParameter) - $(GLINK TemplateTupleParameter) -$(V2 $(GLINK TemplateThisParameter)) -) - -$(P The body of the $(I TemplateDeclaration) must be syntactically correct - even if never instantiated. Semantic analysis is not done until - instantiated. A template forms its own scope, and the template - body can contain classes, structs, types, enums, variables, - functions, and other templates. -) -$(P - Template parameters can be types, values, symbols, or tuples. - Types can be any type. - Value parameters must be of an integral type, floating point - type, or string type and - specializations for them must resolve to an integral constant, - floating point constant, null, or a string literal. - Symbols can be any non-local symbol. - Tuples are a sequence of 0 or more types, values or symbols. -) -$(P - Template parameter specializations - constrain the values or types the $(I TemplateParameter) can - accept. -) -$(P - Template parameter defaults are the value or type to use for the - $(I TemplateParameter) in case one is not supplied. -) - -

    Explicit Template Instantiation

    - -$(P - Templates are explicitly instantiated with: -) - -$(GRAMMAR -$(GNAME TemplateInstance): - $(GLINK TemplateIdentifier) $(B !$(LPAREN)) $(GLINK TemplateArgumentList) $(B $(RPAREN)) -$(V2 $(GLINK TemplateIdentifier) $(B !) $(GLINK TemplateSingleArgument)) - -$(GNAME TemplateArgumentList): - $(GLINK TemplateArgument) -$(V2 $(GLINK TemplateArgument) , -) $(GLINK TemplateArgument) , $(I TemplateArgumentList) - -$(GNAME TemplateArgument): - $(GLINK2 declaration, Type) - $(ASSIGNEXPRESSION) - $(GLINK Symbol) - -$(GNAME Symbol): - $(GLINK SymbolTail) - $(B .) $(GLINK SymbolTail) - -$(GNAME SymbolTail): - $(I Identifier) - $(I Identifier) $(B .) $(I SymbolTail) - $(GLINK TemplateInstance) - $(GLINK TemplateInstance) $(B .) $(I SymbolTail) - -$(V2 -$(GNAME TemplateSingleArgument): - $(I Identifier) - $(GLINK2 declaration, BasicTypeX) - $(GLINK2 lex, CharacterLiteral) - $(GLINK2 lex, StringLiteral) - $(GLINK2 lex, IntegerLiteral) - $(GLINK2 lex, FloatLiteral) - $(B true) - $(B false) - $(B null) - $(B __FILE__) - $(B __LINE__) -) -) - -$(P - Once instantiated, the declarations inside the template, called - the template members, are in the scope - of the $(I TemplateInstance): -) - ------- -template TFoo(T) { alias T* t; } -... -TFoo!(int).t x; // declare x to be of type int* ------- - -$(V2 - $(P If the $(GLINK TemplateArgument) is one token long, the parentheses can be omitted: - ) ---- -TFoo!int.t x; // same as TFoo!(int).t x; ---- -) - -$(P - A template instantiation can be aliased: -) - ------- -template TFoo(T) { alias T* t; } -alias TFoo!(int) abc; -abc.t x; // declare x to be of type int* ------- - -$(P - Multiple instantiations of a $(I TemplateDeclaration) with the same - $(I TemplateArgumentList), before implicit conversions, - all will refer to the same instantiation. - For example: -) - ------- -template TFoo(T) { T f; } -alias TFoo!(int) a; -alias TFoo!(int) b; -... -a.f = 3; -assert(b.f == 3); // a and b refer to the same instance of TFoo ------- - -$(P - This is true even if the $(I TemplateInstance)s are done in - different modules. -) - -$(P - Even if template arguments are implicitly converted to the same - template parameter type, they still refer to different instances: -) - ------ -struct TFoo(int x) { } -static assert(is(TFoo!(3) == TFoo!(2 + 1))); // 3 and 2+1 are both 3 of type int -static assert(!is(TFoo!(3) == TFoo!(3u))); // 3u and 3 are different types ------ -$(P - If multiple templates with the same $(I TemplateIdentifier) are - declared, they are distinct if they have a different number of - arguments or are differently specialized. -) -$(P - For example, a simple generic copy template would be: -) - ------- -template TCopy(T) { - void copy(out T to, T from) { - to = from; - } -} ------- - -$(P - To use the template, it must first be instantiated with a specific - type: -) - ------- -int i; -TCopy!(int).copy(i, 3); ------- - -

    Instantiation Scope

    - -$(P - $(I TemplateInstantance)s are always performed in the scope of where - the $(I TemplateDeclaration) is declared, with the addition of the - template parameters being declared as aliases for their deduced types. -) -$(P - For example: -) - -$(BR)$(BR) -$(U module a) ------- -template TFoo(T) { void bar() { func(); } } ------- - -$(U module b) ------- -import a; - -void func() { } -alias TFoo!(int) f; // error: func not defined in module a ------- - -$(P - and: -) - -$(BR)$(BR) -$(U module a) ------- -template TFoo(T) { void bar() { func(1); } } -void func(double d) { } ------- - -$(U module b) ------- -import a; - -void func(int i) { } -alias TFoo!(int) f; -... -f.bar(); // will call a.func(double) ------- - -$(P - $(I TemplateParameter) specializations and default - values are evaluated in the scope of the $(I TemplateDeclaration). -) - -

    Argument Deduction

    - - $(P The types of template parameters are deduced for a particular - template instantiation by comparing the template argument with - the corresponding template parameter. - ) - - $(P For each template parameter, the following rules are applied in - order until a type is deduced for each parameter: - ) - - $(OL - $(LI If there is no type specialization for the parameter, - the type of the parameter is set to the template argument.) - - $(LI If the type specialization is dependent on a type parameter, - the type of that parameter is set to be the corresponding part - of the type argument.) - - $(LI If after all the type arguments are examined there are any - type parameters left with no type assigned, they are assigned - types corresponding to the template argument in the same position - in the $(I TemplateArgumentList).) - - $(LI If applying the above rules does not result in exactly one - type for each template parameter, then it is an error.) - ) - - $(P For example:) - ------- -template TFoo(T) { } -alias TFoo!(int) Foo1; // (1) T is deduced to be int -alias TFoo!(char*) Foo2; // (1) T is deduced to be char* - -template TBar(T : T*) { } -alias TBar!(char*) Foo3; // (2) T is deduced to be char - -template TAbc(D, U : D[]) { } -alias TAbc!(int, int[]) Bar1; // (2) D is deduced to be int, U is int[] -alias TAbc!(char, int[]) Bar2; // (4) error, D is both char and int - -template TDef(D : E*, E) { } -alias TDef!(int*, int) Bar3; // (1) E is int - // (3) D is int* ------- - - $(P Deduction from a specialization can provide values - for more than one parameter: - ) - ---- -template Foo(T: T[U], U) { - ... -} - -Foo!(int[long]) // instantiates Foo with T set to int, U set to long ---- - - $(P When considering matches, a class is - considered to be a match for any super classes or interfaces: - ) - ------- -class A { } -class B : A { } - -template TFoo(T : A) { } -alias TFoo!(B) Foo4; // (3) T is B - -template TBar(T : U*, U : A) { } -alias TBar!(B*, B) Foo5; // (2) T is B* - // (3) U is B ------- - -

    Template Type Parameters

    - -$(GRAMMAR -$(GNAME TemplateTypeParameter): - $(I Identifier) - $(I Identifier) $(GLINK TemplateTypeParameterSpecialization) - $(I Identifier) $(GLINK TemplateTypeParameterDefault) - $(I Identifier) $(GLINK TemplateTypeParameterSpecialization) $(GLINK TemplateTypeParameterDefault) - -$(GNAME TemplateTypeParameterSpecialization): - $(B :) $(GLINK2 declaration, Type) - -$(GNAME TemplateTypeParameterDefault): - $(B =) $(GLINK2 declaration, Type) -) - -

    Specialization

    - - $(P Templates may be specialized for particular types of arguments - by following the template parameter identifier with a : and the - specialized type. - For example: - ) - ------- -template TFoo(T) { ... } // #1 -template TFoo(T : T[]) { ... } // #2 -template TFoo(T : char) { ... } // #3 -template TFoo(T,U,V) { ... } // #4 - -alias TFoo!(int) foo1; // instantiates #1 -alias TFoo!(double[]) foo2; // instantiates #2 with T being double -alias TFoo!(char) foo3; // instantiates #3 -alias TFoo!(char, int) fooe; // error, number of arguments mismatch -alias TFoo!(char, int, int) foo4; // instantiates #4 ------- - - $(P The template picked to instantiate is the one that is most specialized - that fits the types of the $(I TemplateArgumentList). - Determine which is more specialized is done the same way as the - C++ partial ordering rules. - If the result is ambiguous, it is an error. - ) - - -$(V2 -

    Template This Parameters

    - -$(GRAMMAR -$(GNAME TemplateThisParameter): - $(B this) $(I TemplateTypeParameter) -) - - $(P $(I TemplateThisParameter)s are used in member function templates - to pick up the type of the $(I this) reference. - ) ---- -import std.stdio; - -struct S { - const void foo(this T)(int i) { - writeln(typeid(T)); - } -} - -void main() { - const(S) s; - (&s).foo(1); - S s2; - s2.foo(2); - immutable(S) s3; - s3.foo(3); -} ---- - $(P Prints:) - -$(CONSOLE -const(S) -S -immutable(S) -) -) - -

    Template Value Parameters

    - -$(GRAMMAR -$(GNAME TemplateValueParameter): - $(GLINK2 declaration, BasicType) $(GLINK2 declaration, Declarator) - $(GLINK2 declaration, BasicType) $(GLINK2 declaration, Declarator) $(GLINK TemplateValueParameterSpecialization) - $(GLINK2 declaration, BasicType) $(GLINK2 declaration, Declarator) $(GLINK TemplateValueParameterDefault) - $(GLINK2 declaration, BasicType) $(GLINK2 declaration, Declarator) $(GLINK TemplateValueParameterSpecialization) $(GLINK TemplateValueParameterDefault) - -$(GNAME TemplateValueParameterSpecialization): - $(B :) $(GLINK2 expression, ConditionalExpression) - -$(GNAME TemplateValueParameterDefault): -$(V2 $(B = __FILE__) - $(B = __LINE__)) - $(B =) $(ASSIGNEXPRESSION) -) - -$(V2 - $(P The $(CODE __FILE__) and $(CODE __LINE__) expand to the source - file name and line number at the point of instantiation.) -) - - $(P Template value parameter types can be any type which can - be statically initialized at compile time. - Template value arguments can be integer values, floating point values, - nulls, string values, array literals of template value arguments, - associative array literals of template value arguments, - or struct literals of template value arguments. - ) - ------ -template foo(string s) { - string bar() { return s ~ " betty"; } -} - -void main() { - writefln("%s", foo!("hello").bar()); // prints: hello betty -} ------ - - $(P This example of template foo has a value parameter that - is specialized for 10: - ) - ------- -template foo(U : int, int T : 10) { - U x = T; -} - -void main() { - assert(foo!(int, 10).x == 10); -} ------- - - -

    $(LNAME2 aliasparameters, Template Alias Parameters)

    - -$(GRAMMAR -$(GNAME TemplateAliasParameter): - $(B alias) $(I Identifier) $(GLINK TemplateAliasParameterSpecialization)$(OPT) $(GLINK TemplateAliasParameterDefault)$(OPT) - $(B alias) $(GLINK2 declaration, BasicType) $(GLINK2 declaration, Declarator) $(GLINK TemplateAliasParameterSpecialization)$(OPT) $(GLINK TemplateAliasParameterDefault)$(OPT) - -$(GNAME TemplateAliasParameterSpecialization): - $(B :) $(GLINK2 declaration, Type) - $(B :) $(GLINK2 expression, ConditionalExpression) - -$(GNAME TemplateAliasParameterDefault): - $(B =) $(GLINK2 declaration, Type) - $(B =) $(GLINK2 expression, ConditionalExpression) -) - - $(P Alias parameters enable templates to be parameterized with - any type of D symbol, including global names, local names, typedef - names, module names, template names, and template instance names. - $(V2 Literals can also be used as arguments to alias parameters.) - ) - - $(UL - $(LI Global names - ------- -int x; - -template Foo(alias X) { - static int* p = &X; -} - -void test() { - alias Foo!(x) bar; - *bar.p = 3; // set x to 3 - static int y; - alias Foo!(y) abc; - *abc.p = 3; // set y to 3 -} ------- - ) - - $(LI Type names - ------- -class Foo { - static int p; -} - -template Bar(alias T) { - alias T.p q; -} - -void test() { - alias Bar!(Foo) bar; - bar.q = 3; // sets Foo.p to 3 -} ------- - ) - - $(LI Module names - ------- -import std.string; - -template Foo(alias X) { - alias X.toString y; -} - -void test() { - alias Foo!(std.string) bar; - bar.y(3); // calls std.string.toString(3) -} ------- - ) - - $(LI Template names - ------- -int x; - -template Foo(alias X) { - static int* p = &X; -} - -template Bar(alias T) { - alias T!(x) abc; -} - -void test() { - alias Bar!(Foo) bar; - *bar.abc.p = 3; // sets x to 3 -} ------- - ) - - $(LI Template alias names - ------- -int x; - -template Foo(alias X) { - static int* p = &X; -} - -template Bar(alias T) { - alias T.p q; -} - -void test() { - alias Foo!(x) foo; - alias Bar!(foo) bar; - *bar.q = 3; // sets x to 3 -} ------- - ) - - $(V2 $(LI Literals ------- - -template Foo(alias X, alias Y) { - static int i = X; - static string s = Y; -} - -void test() { - alias Foo!(3, "bar") foo; - writeln(foo.i, foo.s); // prints 3bar -} ------- - )) - ) - -

    $(LNAME2 variadic-templates, Template Tuple Parameters)

    - -$(GRAMMAR -$(GNAME TemplateTupleParameter): - $(I Identifier) $(B ...) -) - - $(P If the last template parameter in the $(I TemplateParameterList) - is declared as a $(I TemplateTupleParameter), - it is a match with any trailing template arguments. - The sequence of arguments form a $(I Tuple). - A $(I Tuple) is not a type, an expression, or a symbol. - It is a sequence of any mix of types, expressions or symbols. - ) - - $(P A $(I Tuple) whose elements consist entirely of types is - called a $(I TypeTuple). - A $(I Tuple) whose elements consist entirely of expressions is - called an $(I ExpressionTuple). - ) - - $(P A $(I Tuple) can be used as an argument list to instantiate - another template, or as the list of parameters for a function. - ) - ---- -template Print(A ...) { - void print() { - writefln("args are ", A); - } -} - -template Write(A ...) { - void write(A a) // A is a $(I TypeTuple) - // a is an $(I ExpressionTuple) - { - writefln("args are ", a); - } -} - -void main() { - Print!(1,'a',6.8).print(); // prints: args are 1a6.8 - Write!(int, char, double).write(1, 'a', 6.8); // prints: args are 1a6.8 -} ---- - - $(P Template tuples can be deduced from the types of - the trailing parameters - of an implicitly instantiated function template:) - ---- -template Foo(T, R...) { - void Foo(T t, R r) { - writefln(t); - static if (r.length) // if more arguments - Foo(r); // do the rest of the arguments - } -} - -void main() { - Foo(1, 'a', 6.8); -} ---- - $(P prints:) - -$(CONSOLE -1 -a -6.8 -) - $(P The tuple can also be deduced from the type of a delegate - or function parameter list passed as a function argument:) - ----- -import std.stdio; - -/* R is return type - * A is first argument type - * U is $(I TypeTuple) of rest of argument types - */ -R delegate(U) Curry(R, A, U...)(R delegate(A, U) dg, A arg) -{ - struct Foo - { - typeof(dg) dg_m; - typeof(arg) arg_m; - - R bar(U u) - { - return dg_m(arg_m, u); - } - } - - Foo* f = new Foo; - f.dg_m = dg; - f.arg_m = arg; - return &f.bar; -} - -void main() -{ - int plus(int x, int y, int z) - { - return x + y + z; - } - - auto plus_two = Curry(&plus, 2); - writefln("%d", plus_two(6, 8)); // prints 16 -} ----- - - $(P The number of elements in a $(I Tuple) can be retrieved with - the $(B .length) property. The $(I n)th element can be retrieved - by indexing the $(I Tuple) with [$(I n)], - and sub tuples can be created - with the slicing syntax. - ) - - $(P $(I Tuple)s are static compile time entities, there is no way - to dynamically change, add, or remove elements.) - - $(P If both a template with a tuple parameter and a template - without a tuple parameter exactly match a template instantiation, - the template without a $(I TemplateTupleParameter) is selected.) - -

    Template Parameter Default Values

    - - $(P Trailing template parameters can be given default values: - ) - ------- -template Foo(T, U = int) { ... } -Foo!(uint,long); // instantiate Foo with T as uint, and U as long -Foo!(uint); // instantiate Foo with T as uint, and U as int - -template Foo(T, U = T*) { ... } -Foo!(uint); // instantiate Foo with T as uint, and U as uint* ------- - -

    Implicit Template Properties

    - - $(P If a template has exactly one member in it, and the name of that - member is the same as the template name, that member is assumed - to be referred to in a template instantiation: - ) - ------- -template $(B Foo)(T) { - T $(B Foo); // declare variable Foo of type T -} - -void test() { - $(B Foo)!(int) = 6; // instead of Foo!(int).Foo -} ------- - -

    Template Constructors

    - -$(GRAMMAR -$(GNAME TemplatedConstructor): - $(B this) $(B $(LPAREN)) $(GLINK2 template, TemplateParameterList) $(B $(RPAREN)) $(GLINK2 declaration, Parameters) $(GLINK Constraint)$(OPT) $(GLINK2 function, FunctionBody) -) - - $(P Templates can be used to form constructors for classes$(V2 and structs). - ) - -

    Class Templates

    - -$(GRAMMAR -$(GNAME ClassTemplateDeclaration): - $(B class) $(I Identifier) $(B $(LPAREN)) $(GLINK TemplateParameterList) $(B $(RPAREN)) $(GLINK Constraint)$(OPT) $(GLINK2 class, BaseClassList)$(OPT) $(GLINK2 class, ClassBody) -) - - $(P If a template declares exactly one member, and that member is a class - with the same name as the template: - ) - ------- -template $(B Bar)(T) { - class $(B Bar) { - T member; - } -} ------- - - $(P then the semantic equivalent, called a $(I ClassTemplateDeclaration) - can be written as: - ) - ------- -class $(B Bar)(T) { - T member; -} ------- - -

    Struct, Union, and Interface Templates

    - -$(GRAMMAR -$(GNAME StructTemplateDeclaration): - $(B struct) $(I Identifier) $(B $(LPAREN)) $(GLINK TemplateParameterList) $(B $(RPAREN)) $(V2 $(GLINK Constraint)$(OPT)) $(GLINK2 struct, StructBody) - -$(GNAME UnionTemplateDeclaration): - $(B union) $(I Identifier) $(B $(LPAREN)) $(GLINK TemplateParameterList) $(B $(RPAREN)) $(V2 $(GLINK Constraint)$(OPT)) $(GLINK2 struct, StructBody) - -$(GNAME InterfaceTemplateDeclaration): - $(B interface) $(I Identifier) $(B $(LPAREN)) $(GLINK TemplateParameterList) $(B $(RPAREN)) $(V2 $(GLINK Constraint)$(OPT)) $(GLINK2 interface, BaseInterfaceList)$(OPT) $(GLINK2 interface, InterfaceBody) -) - - $(P Analogously to class templates, struct, union and interfaces - can be transformed into templates by supplying a template parameter list. - ) - -

    $(LNAME2 function-templates, Function Templates)

    - - $(P If a template declares exactly one member, and that member is a function - with the same name as the template, it is a function template declaration. - Alternatively, a function template declaration is a function declaration - with a $(GLINK TemplateParameterList) immediately preceding the - $(GLINK2 declaration, Parameters). - ) - - $(P A function template to compute the square of type $(I T) is: - ) ------- -T $(B Square)(T)(T t) { - return t * t; -} ------- - - $(P Function templates can be explicitly instantiated with a - !($(I TemplateArgumentList)): - ) - ----- -writefln("The square of %s is %s", 3, Square!(int)(3)); ----- - - $(P or implicitly, where the $(I TemplateArgumentList) is deduced - from the types of the function arguments: - ) - ----- -writefln("The square of %s is %s", 3, Square(3)); // T is deduced to be int ----- - - $(P If there are fewer arguments supplied in the $(I TemplateArgumentList) - than parameters in the $(I TemplateParameterList), the arguments fulfill - parameters from left to right, and the rest of the parameters are then deduced - from the function arguments. - ) - - $(P Function template type parameters that are to be implicitly - deduced may not have specializations: - ) - ------- -void $(B Foo)(T : T*)(T t) { ... } - -int x,y; -Foo!(int*)(x); // ok, T is not deduced from function argument -Foo(&y); // error, T has specialization ------- - - $(P Template arguments not implicitly deduced can have default values: - ) - ------- -void $(B Foo)(T, U=T*)(T t) { U p; ... } - -int x; -Foo(&x); // T is int, U is int* ------- - -$(V2 $(P Function templates can have their return types deduced based - on the first - $(GLINK2 statement, ReturnStatement) - in the function: - ) - ---- -auto $(B Square)(T)(T t) { - return t * t; -} ---- - $(P If there is more than one return statement, then the - types of the return statement expressions must match. - If there are no return statements, then the return type of the - function template is $(CODE void). - ) -) - -

    $(LNAME2 auto-ref-parameters, Function Templates with Auto Ref Parameters)

    - - $(P An auto ref function template parameter becomes a ref parameter - if its corresponding argument is an lvalue, otherwise it becomes - a value parameter: - ) - ---- -int foo(T...)(auto ref T x) { - int result; - - foreach (i, v; x) - { - if (v == 10) - assert(__traits(isRef, x[i])); - else - assert(!__traits(isRef, x[i])); - result += v; - } - return result; -} - -void main() { - int y = 10; - int r; - r = foo(8); // returns 8 - r = foo(y); // returns 10 - r = foo(3, 4, y); // returns 17 - r = foo(4, 5, y); // returns 19 - r = foo(y, 6, y); // returns 26 -} ---- - - $(P Auto ref parameters can be combined with auto ref return - attributes: - ) - ---- -auto ref min(T, U)(auto ref T lhs, auto ref U rhs) -{ - return lhs > rhs ? rhs : lhs; -} - -void main() -{ - int x = 7, y = 8; - int i; - - i = min(4, 3); // returns 3 - i = min(x, y); // returns 7 - min(x, y) = 10; // sets x to 10 - static assert(!__traits(compiles, min(3, y) = 10)); - static assert(!__traits(compiles, min(y, 3) = 10)); -} ---- - -

    Recursive Templates

    - - $(P Template features can be combined to produce some interesting - effects, such as compile time evaluation of non-trivial functions. - For example, a factorial template can be written: - ) - ------- -template factorial(int n : 1) { - enum { factorial = 1 } -} - -template factorial(int n) { - enum { factorial = n* factorial!(n-1) } -} - -void test() { - writefln("%s", factorial!(4)); // prints 24 -} ------- - -$(V2 -

    Template Constraints

    - -$(GRAMMAR -$(GNAME Constraint): - $(B if) $(B $(LPAREN)) $(I ConstraintExpression) $(B $(RPAREN)) - -$(I ConstraintExpression): - $(I $(GLINK2 expression, Expression)) -) - - $(P $(I Constraint)s are used to impose additional constraints - on matching arguments to a template beyond what is possible - in the $(GLINK TemplateParameterList). - The $(I ConstraintExpression) is computed at compile time - and returns a result that is converted to a boolean value. - If that value is true, then the template is matched, - otherwise the template is not matched. - ) - - $(P For example, the following function template only - matches with odd values of $(CODE N): - ) - ---- -void foo(int N)() - if (N & 1) -{ - ... -} -... -foo!(3)(); // ok, matches -foo!(4)(); // error, no match ---- -) - -

    Limitations

    - - $(P Templates cannot be used to add non-static members or - virtual functions to classes. - For example: - ) - ------- -class Foo { - template TBar(T) { - T xx; // becomes a static member of Foo - int func(T) { ... } // non-virtual - - static T yy; // Ok - static int func(T t, int y) { ... } // Ok - } -} ------- - - $(P Templates cannot be declared inside functions. - ) - - $(P Templates cannot add functions to interfaces:) ---- -interface TestInterface { void tpl(T)(); } // error ---- -) - -Macros: - TITLE=Templates - WIKI=Template - CATEGORY_SPEC=$0 - FOO= - diff --git a/test/next_version.sh b/test/next_version.sh new file mode 100755 index 0000000000..0c077396db --- /dev/null +++ b/test/next_version.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# Test changelog/next_version.sh + +set -ueo pipefail + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +NV="$DIR/../changelog/next_version.sh" + +TMPFILE=$(mktemp deleteme.XXXXXXXX) +cleanup() { + rm -rf "$TMPFILE"; +} +trap cleanup EXIT + +versions=( \ + "2.077.0|2.078.0" + "2.077.1|2.078.0" + "2.077.1-beta|2.078.0" + "2.077.1-master.abcdefg|2.078.0" + "3.81.1|3.082.0" +) + +for version in "${versions[@]}" ; do + version_latest="$(echo "$version" | cut -d'|' -f 1)" + version_next="$(echo "$version" | cut -d'|' -f 2)" + echo "v$version_latest" > "$TMPFILE" + echo "Testing: $version_latest (expecting: $version_next)" + version_real=$("$NV" "$TMPFILE") + if [ "$version_real" != "$version_next" ] ; then + echo "Comparison failed. Received $version_real (expected $version_next)" + exit 1 + fi +done diff --git a/todo.dd b/todo.dd deleted file mode 100644 index 8caca14137..0000000000 --- a/todo.dd +++ /dev/null @@ -1,40 +0,0 @@ -Ddoc - -$(D_S TODO, - -$(P Want to contribute to D? You're in the right place. This is a list containing items that have already been decided as important for D's future, but on which work hasn't started yet.) - -$(P You are of course gladly invited to contribute with any suggestions, bug reports, bug fixes, and proposals you might have—anything that pushes forward the language. The list below is an attempt at structuring and focusing potential contributions. If you work on an item of this list, you can be sure it will be integrated within the reference compiler and/or standard library, assuming of course work is of good quality.) - -$(SECTION2 $(D gdc)) - -$(P $(WEB bitbucket.org/goshawk/gdc/wiki/Home, gdc) is a project that integrates the front-end of the D reference compiler with gcc's backend. The goal of the project is to fully integrate D in the GNU compiler suite version 4.7. All legal documents have been completed, which leaves things to "a small matter of programming". - -$(P If you are interested in contributing, contact $(WEB bitbucket.org/ibuclaw, Iain Buclaw), the leader of the project.) -) - -$(SECTION2 On-Demand RTTI) - -$(P D offers compile-time introspection, leaving it to libraries to define -run-time type information and reflection. That promise has not yet been fulfilled.) - -$(P The high-level idea is to allow the programmer to enable RTTI by only inserting one line of code in the target class:) - ----- -class Widget { - mixin(enableReflection()); - ... -} ----- - -$(P Details may vary (e.g. $(D enableReflection()) may take the name of -the class as a string), but essentially the language should provide -everything necessary for achieving full runtime reflection. That -includes inspecting a class' data members and methods, creating -instances of the class, and dynamically invoking methods.) - -) - -Macros: - TITLE=The D Programming Language official TODO list - WEB=$(LINK2 http://$1,$2) diff --git a/tools/check_ddoc.d b/tools/check_ddoc.d new file mode 100755 index 0000000000..eb796c6d1a --- /dev/null +++ b/tools/check_ddoc.d @@ -0,0 +1,81 @@ +#!/usr/bin/env rdmd +/** +Search HTML output for errors: +- for undefined Ddoc macros +- raw macro leakage +- trailing parenthesis +*/ +import std.algorithm, std.file, std.functional, std.range, std.stdio; + +shared int errors = 0; + +void error(string name, string file, size_t lineNr, const(char)[] line) +{ + import core.atomic; + errors.atomicOp!"+="(1); + synchronized + { + stderr.writefln("%s:%d: [%s] %s", file, lineNr, name, line); + } +} + +enum ErrorMessages +{ + undefinedMacro = "UNDEFINED MACRO", + rawMacroLeakage = "RAW MACRO LEAKAGE", + trailingParenthesis = "TRAILING PARENTHESIS", +} + +void checkLine(alias errorFun)(string file, size_t lineNr, const(char)[] line) +{ + if (line.canFind("UNDEFINED MACRO")) + errorFun(ErrorMessages.undefinedMacro, file, lineNr, line); + + if (line.findSplitAfter("$(") + .pipe!(a => !a.expand.only.any!empty && a[1].front != '\'')) + errorFun(ErrorMessages.rawMacroLeakage, file, lineNr, line); + + if (line.equal(")")) + errorFun(ErrorMessages.trailingParenthesis, file, lineNr, line); +} + +version(unittest) {} else +int main(string[] args) +{ + import std.parallelism : parallel; + + auto files = args[1 .. $]; + foreach (file; files.parallel(1)) + foreach (nr, line; File(file, "r").byLine.enumerate) + checkLine!error(file, nr, line); + + if (errors > 0) + stderr.writefln("%s error%s found. Exiting.", errors, errors > 1 ? "s" : ""); + + return errors != 0; +} + +unittest +{ + string lastSeenError; + void errorStub(string name, string file, size_t lineNr, const(char)[] line) + { + lastSeenError = name; + } + auto check(string line) + { + lastSeenError = null; + checkLine!errorStub(null, 0, line); + return lastSeenError; + } + + assert(check(` `) == ErrorMessages.undefinedMacro); + + assert(check(" $('") is null); + assert(check(" $(") is null); + assert(check(" $(FOO)") == ErrorMessages.rawMacroLeakage); + + assert(check(" )") is null); + assert(check(") ") is null); + assert(check(")") == ErrorMessages.trailingParenthesis); +} diff --git a/tools/chmgen.d b/tools/chmgen.d new file mode 100644 index 0000000000..87013501ae --- /dev/null +++ b/tools/chmgen.d @@ -0,0 +1,608 @@ +// D HTML to CHM converter/generator +// By Vladimir Panteleev (2007-2015) +// Placed in the Public Domain +// Written in the D Programming Language, version 2 + +import std.algorithm; +import std.exception; +import std.file; +import std.getopt; +import std.range; +import std.stdio : File, stderr; +import std.string; +import std.regex; +import std.path; + +// ******************************************************************** + +// List of files to completely exclude from parsing. +string[] excludes = [ + "404.html", + "forum-template.html", +]; + +// List of broken links to ignore. +string[] brokenLinks = [ + "d-keyring.gpg", + "dlangspec.mobi", + "dlangspec.pdf", + "library-prerelease/index.html", +]; + +// ******************************************************************** + +string docRoot = `.`; +string chmDir = "chm"; +bool prerelease; +string target; + +// ******************************************************************** + +struct KeyLink +{ + /// Anchor identifier (fragment part of URL) + string anchor; + + /// Same as the addKeyword parameter. + int confidence; + + /// Source files that the link was observed from. + string[] sources; +} + +/// Hashmap of keywords (for the CHM keyword tab); +/// for each keyword, a hashmap of pages it appears on. +/// Keys are: keywords[keyword][original url w/o anchor] = anchor/confidence +KeyLink[string][string] keywords; + +/// List of all keywords, sorted alphabetically, case-insensitive +string[] keywordList; + +/// Index of all seen anchors. +/// Key is the file name and fragment part. +/// Value is true if we saw a definition of the anchor, +/// false if we only saw a link to it (so far). +bool[string] sawAnchor; + +/** + Register an anchor. + Params: + keyword = Some human-readable text associated with the anchor + (section title, link text) + link = The URL including the filename and any fragment part + source = The source file the link was observed from + confidence = A number indicating the preference of using the given anchor text + (higher numbers take preference over lower ones) + isAnchor = true (default) if this is the definition of an anchor, + false if it is a link to it +*/ +void addKeyword(string keyword, string link, string source, int confidence, bool isAnchor = true) +{ + keyword = keyword.strip(); + if (!keyword.length) + return; + link = link.strip(); + + while (link.skipOver("./")) {} + if (link.endsWith("/")) + link ~= "index.html"; + + if (prerelease && link.skipOver("phobos/")) + link = "phobos-prerelease/" ~ link; + + string file = link.stripAnchor(); + string anchor = link.getAnchor(); + + if (keyword !in keywords + || file !in keywords[keyword]) + keywords[keyword][file] = KeyLink.init; + + auto pkeyLink = file in keywords[keyword]; + if (pkeyLink.confidence < confidence) + { + pkeyLink.anchor = anchor; + pkeyLink.confidence = confidence; + } + pkeyLink.sources ~= source; + + if (anchor.length) + { + if (link !in sawAnchor) + sawAnchor[link] = false; + if (isAnchor) + sawAnchor[link] = true; + } +} + +/// Information about a particular page. +struct Page +{ + /// Page title (as in HTML). + string title; +} +/// Mapping of page file names to page information (title). +Page*[string] pages; + +// ******************************************************************** + +void main(string[] args) +{ + bool onlyTags; + + getopt(args, + "only-tags", &onlyTags, + "root", &docRoot, + "dir", &chmDir, + "target", &target, + ); + prerelease = target == "prerelease"; + + bool chm = !onlyTags; + + if (chm) + { + if (exists(chmDir)) + rmdirRecurse(chmDir); + mkdirRecurse(chmDir ~ `/files`); + } + + string phobosDir = prerelease ? "/phobos-prerelease/" : "/phobos/"; + + enforce(exists(docRoot ~ phobosDir ~ `index.html`), + `Phobos documentation not present. Please place Phobos documentation HTML files into the "phobos" subdirectory.`); + + string[] files = chain( + dirEntries(docRoot ~ `/` , "*.html", SpanMode.shallow), + dirEntries(docRoot ~ phobosDir , "*.html", SpanMode.shallow), + dirEntries(docRoot ~ `/spec/` , "*.html", SpanMode.shallow), + dirEntries(docRoot ~ `/changelog/`, "*.html", SpanMode.shallow), + // dirEntries(docRoot ~ `/js/` , SpanMode.shallow), + dirEntries(docRoot ~ `/css/` , SpanMode.shallow), + dirEntries(docRoot ~ `/images/` , "*.*" , SpanMode.shallow), + only(docRoot ~ `/favicon.ico`) + ).array(); + + foreach (filePath; files) + { + scope(failure) stderr.writeln("Error while processing file: ", filePath); + + auto page = new Page; + auto fileName = filePath[docRoot.length+1 .. $].forwardSlashes(); + + pages[fileName] = page; + + auto outPath = chmDir ~ `/files/` ~ fileName; + if (chm) + outPath.dirName().mkdirRecurse(); + + if (fileName.endsWith(`.html`)) + { + if (excludes.canFind(fileName)) + continue; + + stderr.writeln("Processing ", fileName); + auto src = filePath.readText(); + + // Find title + + foreach (m; src.match(re!`(.*?) - D Programming Language`)) + page.title = m.captures[1]; + + // Add document CSS class + + src = src.replaceAll(re!`()`, `$1 chm$2`); + + // Fix links + + enum attrs = `(?:(?:\w+=\"[^"]*\")?\s*)*`; + + src = src.replaceAll(re!(`((.*?)`))) + addKeyword(m.captures[2].replaceAll(re!`<.*?>`, ``), fileName ~ "#" ~ m.captures[1], fileName, 5); + + foreach (m; src.matchAll(re!(``))) + addKeyword(m.captures[2], fileName ~ "#" ~ m.captures[1], fileName, 1); + + foreach (m; src.matchAll(re!(`
    `))) + addKeyword(m.captures[2], fileName ~ "#" ~ m.captures[1], fileName, 1); + + foreach (m; src.matchAll(re!(`
    (.*?)`))) + if (!m.captures[1].isAbsoluteURL()) + addKeyword(m.captures[2].replaceAll(re!`<.*?>`, ``), absoluteUrl(fileName, m.captures[1].strip()), fileName, 4, false); + + // Disable scripts + + src = src.replaceAll(re!``, ``); + src = src.replaceAll(re!``, ``); + + // Remove external stylesheets + + src = src.replaceAll(re!`` ~ + `` ~ + `` ~ + ``); + if (nav.children.length) + { + f.writeln(t, `
      `); + foreach (child; nav.children) + dumpNav(child, level+1); + f.writeln(t, `
    `); + } + } + else + foreach (child; nav.children) + dumpNav(child, level); + } + + f.open(chmDir ~ `/d.hhc`, "wt"); + f.writeln( +` + +
      `); + dumpNav(nav); + f.writeln(`
    +`); + f.close(); + + // ************************************************************ + + stderr.writeln("Writing index file"); + + f.open(chmDir ~ `/d.hhk`, "wt"); + f.writeln( +` +
      `); + foreach (keyword; keywordList) + { + f.writeln( +`
    • + `); + foreach (url; keywords[keyword].keys.sort()) + if (url in pages) + { + f.writeln( +` + `); + } + f.writeln( +` `); + } + f.writeln( +`
    +`); + f.close(); +} + +// ************************************************************ + +void writeTags() +{ + stderr.writeln("Writing tags file"); + + // D syntax + File f; + f.open("d-" ~ target ~ ".tag", "wt"); + f.writeln("["); + foreach (keyword; keywordList) + { + static struct IndexEntry { string keyword; string[] urls; } + IndexEntry entry; + entry.keyword = keyword; + foreach (url, link; keywords[keyword]) + if (url in pages) + entry.urls ~= `http://dlang.org/` ~ url ~ link.anchor; + f.writeln(entry, ","); + } + f.writeln("]"); + f.close(); + + // JSON syntax + import std.json; + auto j = JSONValue((JSONValue[string]).init); + foreach (keyword; keywordList) + j[keyword] = JSONValue(keywords[keyword] + .byKeyValue + .map!(kv => JSONValue(`http://dlang.org/` ~ kv.key ~ kv.value.anchor)) + .array); + std.file.write("d-tags-" ~ target ~ ".json", j.toString()); +} + +// ******************************************************************** + +string forwardSlashes(string s) +{ + return s.replace(`\`, `/`); +} + +// ' * ' +string backSlashes(string s) +{ + return s.replace(`/`, `\`); +} + +string getAnchor(string s) +{ + return s.findSplitBefore("#")[1]; +} + +string stripAnchor(string s) +{ + return s.findSplit("#")[0]; +} + +string absoluteUrl(string base, string url) +{ + if (url.canFind("://")) + return url; + + assert(!base.canFind('\\'), format("%s", [base, url])); + assert(!url .canFind('\\')); + enforce(url.length, "Empty URL"); + + if (url[0]=='#') + return base ~ url; + + auto pathSegments = base.length ? base.split(`/`)[0..$-1] : null; + auto urlSegments = url.split(`/`); + + while (urlSegments.startsWith([`..`])) + { + urlSegments = urlSegments[1..$]; + enforce(pathSegments.length, + "Attempting to escape site root (dereferencing %s from %s)" + .format(url, base)); + pathSegments = pathSegments[0..$-1]; + } + return (pathSegments ~ urlSegments).join(`/`); +} + +bool isAbsoluteURL(string s) +{ + return s.canFind("://") + || s.startsWith("//") + || s.startsWith("mailto:"); +} + +Regex!char re(string pattern, alias flags = [])() +{ + static Regex!char r; + if (r.empty) + r = regex(pattern, flags); + return r; +} diff --git a/tools/ddoc_xml_extractor.d b/tools/ddoc_xml_extractor.d new file mode 100755 index 0000000000..1748c14b38 --- /dev/null +++ b/tools/ddoc_xml_extractor.d @@ -0,0 +1,101 @@ +#!/usr/bin/env rdmd +/* + * Extracts the newest articles from dlang.org's XML site and + * converts them to Ddoc macros. + * + * Copyright (C) 2018 by D Language Foundation + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) +*/ +// Written in the D programming language. + +import std.format : format; +import std.datetime; + +// crude representation of an article at the DBlog +struct Article +{ + string title; + string link; + SysTime date; + string author; +} + +auto toDdoc(const ref Article article, string suffix) +{ + import std.xml : encode; + string text; +with(article) +{ + auto prettyMonth = ["January", "February", "March", "April", "May", "June", "July", + "August", "September", "October", "November", "December"][date.month - 1]; + auto prettyDate = "%s %d, %d".format(prettyMonth, date.day, date.year); + text = +`DBLOG_LATEST_TITLE%5$s=%1$s +DBLOG_LATEST_LINK%5$s=%2$s +DBLOG_LATEST_DATE%5$s=%3$s +DBLOG_LATEST_AUTHOR%5$s=%4$s`.format(title.encode, link, prettyDate, author.encode, suffix); +} + return text; +} + +int main(string[] args) +{ + import std.algorithm, std.exception, std.file, std.getopt, std.range, std.stdio, std.xml; + + string inputFile, outputFile; + auto help = getopt(args, + config.required, + "i|input", &inputFile, + config.required, + "o|output", &outputFile, + ); + if (help.helpWanted || !inputFile.exists) + { + defaultGetoptPrinter("./dblog_xml_extractor", help.options); + return 1; + } + + auto text = inputFile.readText; + + Article[] articles; + + // check and parse XML + text.check; + auto doc = new DocumentParser(text); + doc.onStartTag["item"] = (ElementParser xml) + { + Article article; + scope(exit) + { + xml.parse; + articles ~= article; + } + + xml.onEndTag["title"] = (const Element e) { article.title = e.text; }; + xml.onEndTag["link"] = (const Element e) { article.link = e.text; }; + + // Wed, 07 Feb 2018 13:07:26 +0000 + // -> Wed, 07 Feb 2018 + xml.onEndTag["pubDate"] = (const Element e) { article.date = e.text.parseRFC822DateTime; }; + + // ugly std.xml way to extract CData + string lastCData; + xml.onEndTag["dc:creator"] = (const Element e) { + article.author = lastCData; + }; + xml.onCData = (string s){ + lastCData = s; + }; + }; + doc.parse; + + // output the latest two article in Ddoc + with(File(outputFile, "w")) + foreach (i, el; articles.take(2).enumerate(1)) + writeln(el.toDdoc("_%s".format(i))); + + return 0; +} diff --git a/tools/dspec_tester.d b/tools/dspec_tester.d new file mode 100644 index 0000000000..7593cee81b --- /dev/null +++ b/tools/dspec_tester.d @@ -0,0 +1,276 @@ +#!/usr/bin/env rdmd +/** +Checks the validity of examples in the D Language Specification. + +Copyright: D Language Foundation 2017. + +License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). + +Example usage: + +--- +./dspec_tester +--- + +Author: Sebastian Wilzbach +*/ + +import std.algorithm; +import std.stdio; +import std.range; +import std.regex; + +struct Config { + string dmdBinPath = "dmd"; + bool printLineNumbers; // whether line numbers should be shown on errors +} +shared Config config; + +// a range until the next ')', nested () are ignored +auto untilClosingParentheses(R)(R rs) +{ + struct State + { + uint rightParensCount = 1; + bool inCodeBlock; + uint dashCount; + } + return rs.cumulativeFold!((state, r){ + if (r == '-') + { + state.dashCount++; + } + else + { + if (state.dashCount >= 3) + state.inCodeBlock = !state.inCodeBlock; + state.dashCount = 0; + } + switch(r) + { + case '-': + break; + case '(': + if (!state.inCodeBlock) + state.rightParensCount++; + break; + case ')': + if (!state.inCodeBlock) + state.rightParensCount--; + break; + default: + } + return state; + })(State()).zip(rs).until!(e => e[0].rightParensCount == 0).map!(e => e[1]); +} + +unittest +{ + import std.algorithm.comparison : equal; + assert("aa $(foo $(bar)foobar)".untilClosingParentheses.equal("aa $(foo $(bar)foobar)")); +} + +auto findDdocMacro(R)(R text, string ddocKey) +{ + auto sr = text.splitter(ddocKey); + // don't let RUNNABLE_EXAMPLE match RUNNABLE_EXAMPLE_FOO + auto fr = sr.filter!(s => s.length ? s[0] != '_' : true); + return fr.map!untilClosingParentheses.dropOne; +} + +auto ddocMacroToCode(R)(R text) +{ + import std.ascii : newline; + import std.conv : to; + return text.find("---") + .findSplitAfter(newline)[1] + .findSplitBefore("---")[0] + .to!string; +} + +int main(string[] args) +{ + import std.file, std.getopt; + import std.parallelism : parallel; + import std.path; + import std.process : environment; + import std.typecons : Tuple; + + const rootDir = __FILE_FULL_PATH__.dirName.dirName; + const specDir = rootDir.buildPath("spec"); + const articlesDir = rootDir.buildPath("articles"); + const stdDir = rootDir.buildPath("..", "phobos", "std"); + + config.dmdBinPath = environment.get("DMD", "dmd"); + auto helpInformation = getopt( + args, + "l|lines", "Show the line numbers on errors", cast(bool*) &config.printLineNumbers, + "compiler", "D compiler to use", cast(string*) &config.dmdBinPath, + ); + + if (helpInformation.helpWanted) + { +`D Specification tester +./dspec_tester +`.defaultGetoptPrinter(helpInformation.options); + return 1; + } + + alias SpecType = Tuple!(string, "key", CompileConfig.TestMode, "mode"); + auto specTypes = [ + SpecType("$(SPEC_RUNNABLE_EXAMPLE_COMPILE", CompileConfig.TestMode.compile), + SpecType("$(SPEC_RUNNABLE_EXAMPLE_RUN", CompileConfig.TestMode.run), + SpecType("$(SPEC_RUNNABLE_EXAMPLE_FAIL", CompileConfig.TestMode.fail), + SpecType("$(RUNNABLE_EXAMPLE_COMPILE", CompileConfig.TestMode.compile), + SpecType("$(RUNNABLE_EXAMPLE", CompileConfig.TestMode.run), + SpecType("$(RUNNABLE_EXAMPLE_FAIL", CompileConfig.TestMode.fail), + ]; + auto files = chain(specDir.dirEntries("*.dd", SpanMode.depth), + articlesDir.dirEntries("*.dd", SpanMode.depth), + stdDir.dirEntries("*.d", SpanMode.depth)); + shared bool hasFailed; + foreach (file; files.parallel(1)) + { + // auto-import current module if in phobos + string modImport = file.name.find(stdDir); + if (modImport.length) + { + modImport = "std" ~ modImport[stdDir.length..$]; + modImport = modImport.stripExtension(); + modImport = modImport.findSplitBefore(dirSeparator ~ "package")[0]; + modImport = modImport.replace(dirSeparator, "."); + } + const text = file.readText; + // Lazy range of matching examples code contents + alias findExamples = (ddocKey) => text + .findDdocMacro(ddocKey) + .map!ddocMacroToCode; + auto allTests = specTypes.map!(c => findExamples(c.key) + .map!((e) { + auto code = compileAndCheck(e, CompileConfig(c.mode), modImport); + if (code) + writefln("%s: Error testing above example", file[rootDir.length+1..$]); + return code; + })) + .joiner; + if (!allTests.empty) + { + import core.atomic; + writefln("%s: %d examples found", file[rootDir.length+1..$], allTests.walkLength); + if (allTests.any!(a => a != 0)) + atomicStore(hasFailed, true); + } + } + return hasFailed; +} + +struct CompileConfig +{ + enum TestMode { run, compile, fail } + TestMode mode; + string[] args; + string expectedStdout; + string expectedStderr; +} + +/** +Executes source code with a D compiler (compile-only) + +Params: + buffer = example to check + +Returns: the exit code of the compiler invocation. +*/ +auto compileAndCheck(R)(R buffer, CompileConfig config, string modImport) +{ + import std.process; + import std.uni : isWhite; + + string[] args = [.config.dmdBinPath]; + args ~= config.args; + args ~= "-unittest"; + with (CompileConfig.TestMode) + final switch (config.mode) + { + case run: + args ~= ["-run"]; + break; + case compile: + args ~= ["-c", "-o-"]; + break; + case fail: + args ~= ["-c", "-o-"]; + break; + } + args ~= "-"; + + auto pipes = pipeProcess(args, Redirect.all); + + static mainRegex = regex(`(void|int)\s+main`); + const hasMain = !buffer.matchFirst(mainRegex).empty; + + // don't change standalone module + if (!buffer.find!(a => !a.isWhite).startsWith("module")) + { + if (config.mode == CompileConfig.TestMode.run) + buffer = "import std.stdio;\n" ~ buffer; // used too often + if (modImport.length) + buffer = "import " ~ modImport ~ ";" ~ buffer; + if (!hasMain && config.mode == CompileConfig.TestMode.run) + buffer = "void main() {\n" ~ buffer ~ "\n}"; + } + pipes.stdin.write(buffer); + pipes.stdin.close; + auto ret = wait(pipes.pid); + if (config.mode == CompileConfig.TestMode.fail) + { + if (ret == 0) + { + stderr.writeln("Compilation should have failed for:"); + stderr.writeln("---"); + stderr.writeln(buffer); + stderr.writeln("---"); + ret = 1; + } + else + { + ret = 0; + } + } + else if (ret != 0) + { + stderr.writeln("---"); + int lineNumber = 1; + buffer + .splitter("\n") + .each!((a) { + const indent = hasMain ? " " : ""; + if (.config.printLineNumbers) + stderr.writefln("%3d: %s%s", lineNumber++, indent, a); + else + stderr.writefln("%s%s", indent, a); + }); + + stderr.writeln("---"); + pipes.stderr.byLine.each!(e => stderr.writeln(e)); + } + // check stdout or stderr + static foreach (stream; ["stdout", "stderr"]) + {{ + import std.ascii : toUpper; + import std.conv : to; + mixin("auto expected = config.expected" ~ stream.front.toUpper.to!string ~ stream.dropOne~ ";"); + if (expected) + { + mixin("auto stream = pipes." ~ stream ~ ";"); + auto obs = appender!string; + stream.byChunk(4096).each!(c => obs.put(c)); + scope(failure) { + stderr.writefln("Expected: %s", expected); + stderr.writefln("Observed: %s", obs.data); + } + assert(obs.data == expected); + } + }} + return ret; +} diff --git a/tools/modlist.d b/tools/modlist.d new file mode 100644 index 0000000000..d41c3f0e19 --- /dev/null +++ b/tools/modlist.d @@ -0,0 +1,158 @@ +#!/usr/bin/env rdmd +/** + * Copyright: Martin Nowak 2015-. + * License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). + * Authors: $(HTTP code.dawg.eu, Martin Nowak) + */ +import std.algorithm, std.exception, std.file, std.getopt, std.path, std.range, std.stdio, std.string, std.typecons; + +alias I(alias X) = X; + +int main(string[] args) +{ + string[] excludes, packages, internal; + + auto prog = getopt(args, + "ex", &excludes, + "dump", &packages, // specifies order and inclusions (negations of exclusions) + "internal", &internal, + ); + + if (prog.helpWanted || args.length <= 1) + { + defaultGetoptPrinter("./modlist ... ", prog.options); + return 64; // EX_USAGE + } + + auto dirs = args[1 .. $]; + + static struct Tree + { + bool exists; + Tree[string] children; + } + Tree root; + + foreach (dir; dirs) + { + dirEntries(dir, "*.d", SpanMode.depth) + .filter!(de => de.isFile) + .map!(de => de.name.chompPrefix(dir).chompPrefix(dirSeparator)) // relative to path + .map!(n => n.chomp(".d").replace(dirSeparator, ".")) // std/digest/sha.d => std.digest.sha + .each!(mod => mod // convert to prefix tree + .chomp(".package") + .splitter(".") + .fold!((subtree, name) => &subtree.children.require(name))(&root) + .exists = true + ); + } + + static struct TreeWriter + { + private string[] lastPackage; + private bool firstChild = true; + + private void needPackage(string[] pkg) + { + while (!pkg.startsWith(lastPackage)) + { + lastPackage = lastPackage[0 .. $-1]; + if (lastPackage.length == 0) // top-level + { + writeln("\n)"); + writeln("$(MENU_W_SUBMENU_END)"); + } + else + writef("\n%s)", indent(lastPackage.length)); + } + while (lastPackage.length < pkg.length) + { + lastPackage = pkg[0 .. lastPackage.length + 1]; + if (lastPackage.length == 1) // top-level + { + writeln(); + writefln("$(MENU_W_SUBMENU %s)", lastPackage[0]); + writef("$(ITEMIZE"); + } + else + writef("%s\n%s$(PACKAGE $(PACKAGE_NAME %s),", + firstChild ? "" : ",", indent(lastPackage.length - 1), lastPackage[$-1]); + firstChild = true; + } + } + + void put(string[] mod, bool hasChildren) + { + needPackage(mod[0 .. $-1]); + writef("%s\n", firstChild ? "" : ","); + firstChild = false; + if (hasChildren) + { + writef("%s$(PACKAGE $(MODULE%s %-(%s, %))", + indent(mod.length - 1), mod.length, mod); + lastPackage = mod; + } + else if (mod.length == 1) // top-level + writefln("$(MENU %s.html, $(TT %1$s))", mod[0]); + else + writef("%s$(MODULE%s %-(%s, %))", + indent(mod.length - 1), mod.length, mod); + } + + private static string indent(size_t len) + { + static immutable spaces = " "; + return spaces[0 .. 2 * len]; + } + + @disable this(this); + ~this() { needPackage(null); } + } + + auto includedSet = packages.map!(pkg => tuple(pkg.split(".").assumeUnique, true)).assocArray; + auto excludedSet = excludes.map!(pkg => tuple(pkg.split(".").assumeUnique, true)).assocArray; + auto internalSet = internal.map!(pkg => tuple(pkg.split(".").assumeUnique, true)).assocArray; + + writeln("MODULE_MENU="); + + foreach (dumpingInternal; [false, true]) + { + if (dumpingInternal) + writeln("$(MENU_INTERNAL_SEPARATOR)"); + + foreach (pkg; packages) + { + Tree modules; // filtered copy of tree + + void scan(ref Tree tree, string[] mod, bool inInternal, bool inIncluded) + { + inInternal = inInternal || mod in internalSet; + inIncluded = mod in includedSet ? true : mod in excludedSet ? false : inIncluded; + if (tree.exists && inInternal == dumpingInternal && inIncluded) + if (mod.length > 1 || !tree.children) // std/package.d is currently unreachable! + mod.fold!((subtree, name) => &subtree.children.require(name))(&modules).exists = true; + foreach (child; tree.children.keys.sort) + scan(tree.children[child], mod ~ child, inInternal, inIncluded); + } + + TreeWriter writer; + void dump(ref Tree tree, string[] mod) + { + if (tree.exists) + writer.put(mod, tree.children !is null); + foreach (child; tree.children.keys.sort) + dump(tree.children[child], mod ~ child); + } + + auto subTree = pkg in root.children; + if (subTree) + { + scan(*subTree, [pkg], false, false); + dump(modules, null); + } + } + } + + writeln("_="); + return 0; +} diff --git a/traits.dd b/traits.dd deleted file mode 100644 index cf084552e8..0000000000 --- a/traits.dd +++ /dev/null @@ -1,587 +0,0 @@ -Ddoc - -$(SPEC_S Traits, - - $(P Traits are extensions to the language to enable - programs, at compile time, to get at information - internal to the compiler. This is also known as - compile time reflection. - It is done as a special, easily extended syntax (similar - to Pragmas) so that new capabilities can be added - as required. - ) - -$(GRAMMAR -$(GNAME TraitsExpression): - $(B __traits) $(B $(LPAREN)) $(GLINK TraitsKeyword) $(B ,) $(GLINK TraitsArguments) $(B $(RPAREN)) - -$(GNAME TraitsKeyword): - $(GBLINK isAbstractClass) - $(GBLINK isArithmetic) - $(GBLINK isAssociativeArray) - $(GBLINK isFinalClass) - $(GBLINK isFloating) - $(GBLINK isIntegral) - $(GBLINK isScalar) - $(GBLINK isStaticArray) - $(GBLINK isUnsigned) - $(GBLINK isVirtualFunction) - $(GBLINK isVirtualMethod) - $(GBLINK isAbstractFunction) - $(GBLINK isFinalFunction) - $(GBLINK isStaticFunction) - $(GBLINK isRef) - $(GBLINK isOut) - $(GBLINK isLazy) - $(GBLINK hasMember) - $(GBLINK identifier) - $(GBLINK getMember) - $(GBLINK getOverloads) - $(GBLINK getVirtualFunctions) - $(GBLINK getVirtualMethods) - $(GBLINK parent) - $(GBLINK classInstanceSize) - $(GBLINK allMembers) - $(GBLINK derivedMembers) - $(GBLINK isSame) - $(GBLINK compiles) - -$(GNAME TraitsArguments): - $(GLINK TraitsArgument) - $(GLINK TraitsArgument) $(B ,) $(I TraitsArguments) - -$(GNAME TraitsArgument): - $(GLINK2 expression, AssignExpression) - $(GLINK2 declaration, Type) -) - -$(H2 $(GNAME isArithmetic)) - - $(P If the arguments are all either types that are arithmetic types, - or expressions that are typed as arithmetic types, then $(B true) - is returned. - Otherwise, $(B false) is returned. - If there are no arguments, $(B false) is returned.) - ---- -import std.stdio; - -void main() { - int i; - writeln(__traits(isArithmetic, int)); - writeln(__traits(isArithmetic, i, i+1, int)); - writeln(__traits(isArithmetic)); - writeln(__traits(isArithmetic, int*)); -} ---- - - $(P Prints:) - -$(CONSOLE -true -true -false -false -) - -$(H2 $(GNAME isFloating)) - - $(P Works like $(B isArithmetic), except it's for floating - point types (including imaginary and complex types).) - -$(H2 $(GNAME isIntegral)) - - $(P Works like $(B isArithmetic), except it's for integral - types (including character types).) - -$(H2 $(GNAME isScalar)) - - $(P Works like $(B isArithmetic), except it's for scalar - types.) - -$(H2 $(GNAME isUnsigned)) - - $(P Works like $(B isArithmetic), except it's for unsigned - types.) - -$(H2 $(GNAME isStaticArray)) - - $(P Works like $(B isArithmetic), except it's for static array - types.) - -$(H2 $(GNAME isAssociativeArray)) - - $(P Works like $(B isArithmetic), except it's for associative array - types.) - -$(H2 $(GNAME isAbstractClass)) - - $(P If the arguments are all either types that are abstract classes, - or expressions that are typed as abstract classes, then $(B true) - is returned. - Otherwise, $(B false) is returned. - If there are no arguments, $(B false) is returned.) - ---- -import std.stdio; - -abstract class C { int foo(); } - -void main() { - C c; - writeln(__traits(isAbstractClass, C)); - writeln(__traits(isAbstractClass, c, C)); - writeln(__traits(isAbstractClass)); - writeln(__traits(isAbstractClass, int*)); -} ---- - - $(P Prints:) - -$(CONSOLE -true -true -false -false -) - -$(H2 $(GNAME isFinalClass)) - - $(P Works like $(B isAbstractClass), except it's for final - classes.) - -$(H2 $(GNAME isVirtualFunction)) - - $(P The same as $(GLINK isVirtualMethod), except - that final functions that don't override anything return true. - ) - -$(H2 $(GNAME isVirtualMethod)) - - $(P Takes one argument. If that argument is a virtual function, - $(B true) is returned, otherwise $(B false). - Final functions that don't override anything return false. - ) - ---- -import std.stdio; - -struct S { - void bar() { } -} - -class C { - void bar() { } -} - -void main() { - writeln(__traits(isVirtualMethod, C.bar)); // true - writeln(__traits(isVirtualMethod, S.bar)); // false -} ---- - -$(H2 $(GNAME isAbstractFunction)) - - $(P Takes one argument. If that argument is an abstract function, - $(B true) is returned, otherwise $(B false). - ) - ---- -import std.stdio; - -struct S { - void bar() { } -} - -class C { - void bar() { } -} - -class AC { - abstract void foo(); -} - -void main() { - writeln(__traits(isAbstractFunction, C.bar)); // false - writeln(__traits(isAbstractFunction, S.bar)); // false - writeln(__traits(isAbstractFunction, AC.foo)); // true -} ---- - -$(H2 $(GNAME isFinalFunction)) - - $(P Takes one argument. If that argument is a final function, - $(B true) is returned, otherwise $(B false). - ) - ---- -import std.stdio; - -struct S { - void bar() { } -} - -class C { - void bar() { } - final void foo(); -} - -final class FC { - void foo(); -} - -void main() { - writeln(__traits(isFinalFunction, C.bar)); // false - writeln(__traits(isFinalFunction, S.bar)); // false - writeln(__traits(isFinalFunction, C.foo)); // true - writeln(__traits(isFinalFunction, FC.foo)); // true -} ---- - -$(H2 $(GNAME isStaticFunction)) - - $(P Takes one argument. If that argument is a static function, - meaning it has no context pointer, - $(B true) is returned, otherwise $(B false). - ) - - -$(H2 $(GNAME isRef), $(GNAME isOut), $(GNAME isLazy)) - - $(P Takes one argument. If that argument is a declaration, - $(B true) is returned if it is $(D_KEYWORD ref), $(D_KEYWORD out), - or $(D_KEYWORD lazy), otherwise $(B false). - ) - ---- -void fooref(ref int x) { - static assert(__traits(isRef, x)); - static assert(!__traits(isOut, x)); - static assert(!__traits(isLazy, x)); -} - -void fooout(out int x) { - static assert(!__traits(isRef, x)); - static assert(__traits(isOut, x)); - static assert(!__traits(isLazy, x)); -} - -void foolazy(lazy int x) { - static assert(!__traits(isRef, x)); - static assert(!__traits(isOut, x)); - static assert(__traits(isLazy, x)); -} ---- - -$(H2 $(GNAME hasMember)) - - $(P The first argument is a type that has members, or - is an expression of a type that has members. - The second argument is a string. - If the string is a valid property of the type, - $(B true) is returned, otherwise $(B false). - ) - ---- -import std.stdio; - -struct S { - int m; -} - -void main() { - S s; - - writeln(__traits(hasMember, S, "m")); // true - writeln(__traits(hasMember, s, "m")); // true - writeln(__traits(hasMember, S, "y")); // false - writeln(__traits(hasMember, int, "sizeof")); // true -} ---- - -$(H2 $(GNAME identifier)) - - $(P Takes one argument, a symbol. Returns the identifier - for that symbol as a string literal. - ) - - -$(H2 $(GNAME getMember)) - - $(P Takes two arguments, the second must be a string. - The result is an expression formed from the first - argument, followed by a $(SINGLEQUOTE .), followed by the second - argument as an identifier. - ) - ---- -import std.stdio; - -struct S { - int mx; - static int my; -} - -void main() { - S s; - - __traits(getMember, s, "mx") = 1; // same as s.mx=1; - writeln(__traits(getMember, s, "m" ~ "x")); // 1 - - __traits(getMember, S, "mx") = 1; // error, no this for S.mx - __traits(getMember, S, "my") = 2; // ok -} ---- - -$(H2 $(GNAME getOverloads)) - - $(P The first argument is a class type or an expression of - class type. - The second argument is a string that matches the name of - one of the functions of that class. - The result is a tuple of all the overloads of that function. - ) - ---- -import std.stdio; - -class D { - this() { } - ~this() { } - void foo() { } - int foo(int) { return 2; } -} - -void main() { - D d = new D(); - - foreach (t; __traits(getOverloads, D, "foo")) - writeln(typeid(typeof(t))); - - alias typeof(__traits(getOverloads, D, "foo")) b; - foreach (t; b) - writeln(typeid(t)); - - auto i = __traits(getOverloads, d, "foo")[1](1); - writeln(i); -} ---- - - $(P Prints:) - -$(CONSOLE -void() -int() -void() -int() -2 -) - -$(H2 $(GNAME getVirtualFunctions)) - - $(P The same as $(GLINK getVirtualMethods), except that - final functions that do not override anything are included. - ) - -$(H2 $(GNAME getVirtualMethods)) - - $(P The first argument is a class type or an expression of - class type. - The second argument is a string that matches the name of - one of the functions of that class. - The result is a tuple of the virtual overloads of that function. - It does not include final functions that do not override anything. - ) - ---- -import std.stdio; - -class D { - this() { } - ~this() { } - void foo() { } - int foo(int) { return 2; } -} - -void main() { - D d = new D(); - - foreach (t; __traits(getVirtualMethods, D, "foo")) - writeln(typeid(typeof(t))); - - alias typeof(__traits(getVirtualMethods, D, "foo")) b; - foreach (t; b) - writeln(typeid(t)); - - auto i = __traits(getVirtualMethods, d, "foo")[1](1); - writeln(i); -} ---- - - $(P Prints:) - -$(CONSOLE -void() -int() -void() -int() -2 -) - -$(H2 $(GNAME parent)) - - $(P Takes a single argument which must evaluate to a symbol. - The result is the symbol that is the parent of it. - ) - -$(H2 $(GNAME classInstanceSize)) - - $(P Takes a single argument, which must evaluate to either - a class type or an expression of class type. - The result - is of type $(CODE size_t), and the value is the number of - bytes in the runtime instance of the class type. - It is based on the static type of a class, not the - polymorphic type. - ) - -$(H2 $(GNAME allMembers)) - - $(P Takes a single argument, which must evaluate to either - a type or an expression of type. - A tuple of string literals is returned, each of which - is the name of a member of that type combined with all - of the members of the base classes (if the type is a class). - No name is repeated. - Builtin properties are not included. - ) - ---- -import std.stdio; - -class D { - this() { } - ~this() { } - void foo() { } - int foo(int) { return 0; } -} - -void main() { - auto b = [ __traits(allMembers, D) ]; - writeln(b); - // ["__ctor", "__dtor", "foo", "toString", "toHash", "opCmp", "opEquals", "Monitor", "factory"] -} ---- - - $(P The order in which the strings appear in the result - is not defined.) - -$(H2 $(GNAME derivedMembers)) - - $(P Takes a single argument, which must evaluate to either - a type or an expression of type. - A tuple of string literals is returned, each of which - is the name of a member of that type. - No name is repeated. - Base class member names are not included. - Builtin properties are not included. - ) - ---- -import std.stdio; - -class D { - this() { } - ~this() { } - void foo() { } - int foo(int) { return 0; } -} - -void main() { - auto a = [__traits(derivedMembers, D)]; - writeln(a); // ["__ctor", "__dtor", "foo"] -} ---- - - $(P The order in which the strings appear in the result - is not defined.) - -$(H2 $(GNAME isSame)) - - $(P Takes two arguments and returns bool $(B true) if they - are the same symbol, $(B false) if not.) - ---- -import std.stdio; - -struct S { } - -int foo(); -int bar(); - -void main() { - writeln(__traits(isSame, foo, foo)); // true - writeln(__traits(isSame, foo, bar)); // false - writeln(__traits(isSame, foo, S)); // false - writeln(__traits(isSame, S, S)); // true - writeln(__traits(isSame, std, S)); // false - writeln(__traits(isSame, std, std)); // true -} ---- - - $(P If the two arguments are expressions made up of literals - or enums that evaluate to the same value, true is returned.) - -$(H2 $(GNAME compiles)) - - $(P Returns a bool $(B true) if all of the arguments - compile (are semantically correct). - The arguments can be symbols, types, or expressions that - are syntactically correct. - The arguments cannot be statements or declarations. - ) - - $(P If there are no arguments, the result is $(B false).) - ---- -import std.stdio; - -struct S { - static int s1; - int s2; -} - -int foo(); -int bar(); - -void main() { - writeln(__traits(compiles)); // false - writeln(__traits(compiles, foo)); // true - writeln(__traits(compiles, foo + 1)); // true - writeln(__traits(compiles, &foo + 1)); // false - writeln(__traits(compiles, typeof(1))); // true - writeln(__traits(compiles, S.s1)); // true - writeln(__traits(compiles, S.s3)); // false - writeln(__traits(compiles, 1,2,3,int,long,std)); // true - writeln(__traits(compiles, 3[1])); // false - writeln(__traits(compiles, 1,2,3,int,long,3[1])); // false -} ---- - - $(P This is useful for:) - - $(UL - $(LI Giving better error messages inside generic code than - the sometimes hard to follow compiler ones.) - $(LI Doing a finer grained specialization than template - partial specialization allows for.) - ) - -) - -Macros: - TITLE=Traits - WIKI=Traits - CATEGORY_SPEC=$0 - GBLINK=$(LINK2 #$0, $(B $0)) - H2=

    $0

    diff --git a/tuple.dd b/tuple.dd index 59ed7cc941..ebdaed4b9b 100644 --- a/tuple.dd +++ b/tuple.dd @@ -1,391 +1,11 @@ Ddoc -$(D_S Tuples, +For documentation on tuples that are commonly present in other languages (anonymous runtime entity that groups +different values) refer to $(LINK2 phobos/std_typecons.html#tuple, Phobos documentation on std.typecons.tuple) - $(P A tuple is a sequence of elements. Those elements can - be types, expressions, or aliases. - The number and elements of a tuple are fixed at compile time; - they cannot be changed at run time. - ) - - $(P Tuples have characteristics of both - structs and arrays. Like structs, the tuple - elements can be of different types. Like arrays, - the elements can be accessed via indexing. - ) - - $(P So how does one construct a tuple? There isn't a specific - tuple literal syntax. But since variadic template parameters - create tuples, we can define a template to create one: - ) - ---- -template Tuple(E...) -{ - alias E Tuple; -} ---- - - $(P and it's used like:) - ---- -Tuple!(int, long, float) // create a tuple of 3 types -Tuple!(3, 7, 'c') // create a tuple of 3 expressions -Tuple!(int, 8) // create a tuple of a type and an expression ---- - - $(P In order to symbolically refer to a tuple, use an alias:) - ---- -alias Tuple!(float, float, 3) TP; // TP is now a tuple of two floats and 3 ---- - - $(P Tuples can be used as arguments to templates, and if so - they are $(SINGLEQUOTE flattened) out into a list of arguments. - This makes it straightforward to append a new element to - an existing tuple or concatenate tuples:) - ---- -alias Tuple!(TP, 8) TR; // TR is now float,float,3,8 -alias Tuple!(TP, TP) TS; // TS is float,float,3,float,float,3 ---- - - $(P Tuples share many characteristics with arrays. - For starters, the number of elements in a tuple can - be retrieved with the $(B .length) property:) - ---- -TP.length // evaluates to 3 ---- - - $(P Tuples can be indexed:) - ---- -TP[1] f = TP[2]; // f is declared as a float and initialized to 3 ---- - - $(P and even sliced:) - ---- -alias TP[0..length-1] TQ; // TQ is now the same as Tuple!(float, float) ---- - - $(P Yes, $(B length) is defined within the [ ]s. - There is one restriction: the indices for indexing and slicing - must be evaluatable at compile time.) - ---- -void foo(int i) -{ - TQ[i] x; // error, i is not constant -} ---- - - $(P These make it simple to produce the $(SINGLEQUOTE head) and $(SINGLEQUOTE tail) - of a tuple. The head is just TP[0], the tail - is TP[1 .. length]. - Given the head and tail, mix with a little conditional - compilation, and we can implement some classic recursive - algorithms with templates. - For example, this template returns a tuple consisting - of the trailing type arguments $(I TL) with the first occurrence - of the first type argument $(I T) removed: - ) ---- -template Erase(T, TL...) -{ - static if (TL.length == 0) - // 0 length tuple, return self - alias TL Erase; - else static if (is(T == TL[0])) - // match with first in tuple, return tail - alias TL[1 .. length] Erase; - else - // no match, return head concatenated with recursive tail operation - alias Tuple!(TL[0], Erase!(T, TL[1 .. length])) Erase; -} ---- - -

    Type Tuples

    - - $(P If a tuple's elements are solely types, - it is called a $(I TypeTuple) - (sometimes called a type list). - Since function parameter lists are a list of types, - a type tuple can be retrieved from them. - One way is using an $(ISEXPRESSION): - ) - ---- -int foo(int x, long y); - -... -static if (is(foo P == function)) - alias P TP; -// TP is now the same as Tuple!(int, long) ---- - - $(P This is generalized in the template - $(LINK2 phobos/std_traits.html, std.traits).ParameterTypeTuple: - ) - ---- -import std.traits; - -... -alias ParameterTypeTuple!(foo) TP; // TP is the tuple (int, long) ---- - - $(P $(I TypeTuple)s can be used to declare a function:) - ---- -float bar(TP); // same as float bar(int, long) ---- - - $(P If implicit function template instantiation is being done, - the type tuple representing the parameter types can be deduced: - ) ---- -int foo(int x, long y); - -void Bar(R, P...)(R function(P)) -{ - writefln("return type is ", typeid(R)); - writefln("parameter types are ", typeid(P)); -} - -... -Bar(&foo); ---- - - $(P Prints:) - -$(CONSOLE -return type is int -parameter types are (int,long) -) - - $(P Type deduction can be used to create a function that - takes an arbitrary number and type of arguments:) - ---- -void Abc(P...)(P p) -{ - writefln("parameter types are ", typeid(P)); -} - -Abc(3, 7L, 6.8); ---- - - $(P Prints:) - -$(CONSOLE -parameter types are (int,long,double) -) - - $(P For a more comprehensive treatment of this aspect, see - $(LINK2 variadic-function-templates.html, Variadic Templates). - ) - - -

    Expression Tuples

    - - $(P If a tuple's elements are solely expressions, - it is called an $(I ExpressionTuple). - The Tuple template can be used to create one: - ) - ---- -alias Tuple!(3, 7L, 6.8) ET; - -... -writefln(ET); // prints 376.8 -writefln(ET[1]); // prints 7 -writefln(ET[1..length]); // prints 76.8 ---- - - $(P It can be used to create an array literal:) - ---- -alias Tuple!(3, 7, 6) AT; - -... -int[] a = [AT]; // same as [3,7,6] ---- - - $(P The data fields of a struct or class can be - turned into an expression tuple using the $(B .tupleof) - property:) - ---- -struct S { int x; long y; } - -void foo(int a, long b) -{ - writefln(a, b); -} - -... -S s; -s.x = 7; -s.y = 8; -foo(s.x, s.y); // prints 78 -foo(s.tupleof); // prints 78 -s.tupleof[1] = 9; -s.tupleof[0] = 10; -foo(s.tupleof); // prints 109 -s.tupleof[2] = 11; // error, no third field of S ---- - - $(P A type tuple can be created from the data fields - of a struct using $(B typeof):) - ---- -writefln(typeid(typeof(S.tupleof))); // prints (int,long) ---- - - $(P This is encapsulated in the template - $(LINK2 phobos/std_traits.html, std.traits).FieldTypeTuple. - ) - -

    Looping

    - - $(P While the head-tail style of functional programming works - with tuples, it's often more convenient to use a loop. - The $(I ForeachStatement) can loop over either $(I TypeTuple)s - or $(I ExpressionTuple)s. - ) - ---- -alias Tuple!(int, long, float) TL; -foreach (i, T; TL) - writefln("TL[%d] = ", i, typeid(T)); - -alias Tuple!(3, 7L, 6.8) ET; -foreach (i, E; ET) - writefln("ET[%d] = ", i, E); ---- - - $(P Prints:) - -$(CONSOLE -TL[0] = int -TL[1] = long -TL[2] = float -ET[0] = 3 -ET[1] = 7 -ET[2] = 6.8 -) - -

    Tuple Declarations

    - - $(P A variable declared with a $(I TypeTuple) becomes an - $(I ExpressionTuple):) - ---- -alias Tuple!(int, long) TL; - -void foo(TL tl) -{ - writefln(tl, tl[1]); -} - -foo(1, 6L); // prints 166 ---- - -

    Putting It All Together

    - - $(P These capabilities can be put together to implement - a template that will encapsulate all the arguments to - a function, and return a delegate that will call the function - with those arguments.) - ---- -import std.stdio; - -R delegate() CurryAll(Dummy=void, R, U...)(R function(U) dg, U args) -{ - struct Foo - { - typeof(dg) dg_m; - U args_m; - - R bar() - { - return dg_m(args_m); - } - } - - Foo* f = new Foo; - f.dg_m = dg; - foreach (i, arg; args) - f.args_m[i] = arg; - return &f.bar; -} - -R delegate() CurryAll(R, U...)(R delegate(U) dg, U args) -{ - struct Foo - { - typeof(dg) dg_m; - U args_m; - - R bar() - { - return dg_m(args_m); - } - } - - Foo* f = new Foo; - f.dg_m = dg; - foreach (i, arg; args) - f.args_m[i] = arg; - return &f.bar; -} - - -void main() -{ - static int plus(int x, int y, int z) - { - return x + y + z; - } - - auto plus_two = CurryAll(&plus, 2, 3, 4); - writefln("%d", plus_two()); - assert(plus_two() == 9); - - int minus(int x, int y, int z) - { - return x + y + z; - } - - auto minus_two = CurryAll(&minus, 7, 8, 9); - writefln("%d", minus_two()); - assert(minus_two() == 24); -} ---- - - $(P The reason for the $(I Dummy) parameter is that one - cannot overload two templates with the same parameter list. - So we make them different by giving one a dummy parameter. - ) - -

    Future Directions

    - - $(UL - $(LI Return tuples from functions.) - $(LI Use operators on tuples, like =, +=, etc.) - $(LI Have tuple properties like $(B .init) which will apply - the property to each of the tuple members.) - ) - -) +You may be also looking for documentation for built-in $(LINK2 ctarguments.html, compile-time sequences) +which can be sometimes referred as "tuples" too (though it is discouraged). Macros: - TITLE=Tuples - WIKI=Tuples - CATEGORY_ARTICLES=$0 -META_KEYWORDS=D Programming Language, template metaprogramming, -variadic templates, tuples, currying -META_DESCRIPTION=Tuples in the D programming language + TITLE=Tuples + SUBNAV=$(SUBNAV_ARTICLES) diff --git a/type.dd b/type.dd deleted file mode 100644 index b147c3bf61..0000000000 --- a/type.dd +++ /dev/null @@ -1,453 +0,0 @@ -Ddoc - -$(SPEC_S Types, - -$(SECTION2 Basic Data Types, - - $(TABLE2 Basic Data Types, - $(THEAD Keyword, Description, Default Initializer ($(D .init))) - $(TROW - $(D void), - no type, - $(D -) - ) - $(TROW - $(D bool), - boolean value, - $(D false) - ) - $(TROW - $(D byte), - signed 8 bits, - $(D 0) - ) - $(TROW - $(D ubyte), - unsigned 8 bits, - $(D 0) - ) - $(TROW - $(D short), - signed 16 bits, - $(D 0) - ) - $(TROW - $(D ushort), - unsigned 16 bits, - $(D 0) - ) - $(TROW - $(D int), - signed 32 bits, - $(D 0) - ) - $(TROW - $(D uint), - unsigned 32 bits, - $(D 0) - ) - $(TROW - $(D long), - signed 64 bits, - $(D 0L) - ) - $(TROW - $(D ulong), - unsigned 64 bits, - $(D 0L) - ) - $(TROW - $(D cent), - signed 128 bits (reserved for future use), - $(D 0) - ) - $(TROW - $(D ucent), - unsigned 128 bits (reserved for future use), - $(D 0) - ) - $(TROW - $(D float), - 32 bit floating point, - $(D float.nan) - ) - $(TROW - $(D double), - 64 bit floating point, - $(D double.nan) - ) - $(TROW - $(D real), - largest hardware implemented floating - point size ($(B Implementation Note:) 80 bits for x86 CPUs) - or double size$(COMMA) whichever is larger, - $(D real.nan) - ) - $(TROW - $(D ifloat), - imaginary float, - $(D float.nan * 1.0i) - ) - $(TROW - $(D idouble), - imaginary double, - $(D double.nan * 1.0i) - ) - $(TROW - $(D ireal), - imaginary real, - $(D real.nan * 1.0i) - ) - $(TROW - $(D cfloat), - a complex number of two float values, - $(D float.nan + float.nan * 1.0i) - ) - $(TROW - $(D cdouble), - complex double, - $(D double.nan + double.nan * 1.0i) - ) - $(TROW - $(D creal), - complex real, - $(D real.nan + real.nan * 1.0i) - ) - $(TROW - $(D char), - unsigned 8 bit UTF-8, - $(D 0xFF) - ) - $(TROW - $(D wchar), - unsigned 16 bit UTF-16, - $(D 0xFFFF) - ) - $(TROW - $(D dchar), - unsigned 32 bit UTF-32, - $(D 0x0000FFFF) - ) - ) -) - - -$(SECTION2 Derived Data Types, - - $(UL - $(LI pointer) - $(LI array) - $(LI associative array) - $(LI function) - $(LI delegate) - ) - - $(P $(DDSUBLINK arrays, strings, $(I Strings)) are a special case of arrays.) -) - -$(SECTION2 User Defined Types, - - $(UL - $(LI alias) - $(LI enum) - $(LI struct) - $(LI union) - $(LI class) - $(V1 $(LI typedef)) - ) -) - - -$(SECTION2 Base Types, - - $(P The $(I base type) of an enum is the type it is based on:) - ---- -enum E : T { ... } // T is the $(I base type) of E ---- - -$(V1 - $(P The $(I base type) of a typedef is the type it is formed from:) - ---- -typedef T U; // T is the $(I base type) of U ---- -) -) - - -$(SECTION2 Pointer Conversions, - - $(P Casting pointers to non-pointers and vice versa is allowed in D, - however, do not do this for any pointers that point to data - allocated by the garbage collector. - ) -) - -$(SECTION2 Implicit Conversions, - - $(P Implicit conversions are used to automatically convert - types as required. - ) - - $(P A $(V1 typedef or) enum can be implicitly converted to its base - type, but going the other way requires an explicit - conversion. - A literal can be implicitly converted to a typedef. - For example: - ) - -------------------- -int i; -$(V1 typedef int myint; -myint m; -i = m; // OK -m = i; // error -m = cast(myint)i; // OK -m = 3; // OK) -enum Foo { E } -Foo f; -i = f; // OK -f = i; // error -f = cast(Foo)i; // OK -f = 0; // error -f = Foo.E; // OK -------------------- -) - - -$(SECTION2 Integer Promotions, - - $(P Integer Promotions are conversions of the following types: - ) - - $(TABLE2 Integer Promotions, - $(TR - $(TH from) - $(TH to) - ) - $(TR - $(TD bool) - $(TD int) - ) - $(TR - $(TD byte) - $(TD int) - ) - $(TR - $(TD ubyte) - $(TD int) - ) - $(TR - $(TD short) - $(TD int) - ) - $(TR - $(TD ushort) - $(TD int) - ) - $(TR - $(TD char) - $(TD int) - ) - $(TR - $(TD wchar) - $(TD int) - ) - $(TR - $(TD dchar) - $(TD uint) - ) - ) - - $(P If a $(V1 typedef or) enum has as a base type one of the types - in the left column, it is converted to the type in the right - column. - ) -) - - -$(SECTION2 Usual Arithmetic Conversions, - - $(P The usual arithmetic conversions convert operands of binary - operators to a common type. The operands must already be - of arithmetic types. - The following rules are applied - in order, looking at the base type: - ) - - $(OL - $(LI If either operand is real, the other operand is - converted to real.) - - $(LI Else if either operand is double, the other operand is - converted to double.) - - $(LI Else if either operand is float, the other operand is - converted to float.) - - $(LI Else the integer promotions are done on each operand, - followed by: - - $(OL - $(LI If both are the same type, no more conversions are done.) - - $(LI If both are signed or both are unsigned, the - smaller type is converted to the larger.) - - $(LI If the signed type is larger than the unsigned - type, the unsigned type is converted to the signed type.) - - $(LI The signed type is converted to the unsigned type.) - ) - ) - ) - - $(P If one or both of the operand types is an enum $(V1 or typedef) after - undergoing the above conversions, the result type is:) - - $(OL - $(LI If the operands are the same type, the result will be the - that type.) - $(LI If one operand is an enum $(V1 or typedef) and the other is the base type - of that $(V1 typedef or) enum, the result is the base type.) - $(LI If the two operands are different $(V1 typedefs or) enums, - the result is the closest base type common to both. A base type being closer - means there is a shorter sequence of conversions to base type to get there from the - original type.) - ) - - $(P Integer values cannot be implicitly converted to another - type that cannot represent the integer bit pattern after integral - promotion. For example:) - ---- -ubyte u1 = cast(byte)-1; // error, -1 cannot be represented in a ubyte -ushort u2 = cast(short)-1; // error, -1 cannot be represented in a ushort -uint u3 = cast(int)-1; // ok, -1 can be represented in a uint -ulong u4 = cast(long)-1; // ok, -1 can be represented in a ulong ---- - - $(P Floating point types cannot be implicitly converted to - integral types. - ) - - $(P Complex floating point types cannot be implicitly converted - to non-complex floating point types. - ) - - $(P Imaginary floating point types cannot be implicitly converted to - float, double, or real types. Float, double, or real types - cannot be implicitly converted to imaginary floating - point types. - ) -) - - -$(SECTION2 bool, - - $(P The bool type is a 1 byte size type that can only hold the - value $(D_KEYWORD true) or $(D_KEYWORD false). - The only operators that can accept operands of type bool are: - & | ^ &= |= ^= ! && || ?:. - A bool value can be implicitly converted to any integral type, - with $(D_KEYWORD false) becoming 0 and $(D_KEYWORD true) becoming 1. - The numeric literals 0 and 1 can be implicitly - converted to the bool values $(D_KEYWORD false) and $(D_KEYWORD true), - respectively. - Casting an expression to bool means testing for 0 or !=0 for - arithmetic types, and $(D_KEYWORD null) or !=$(D_KEYWORD null) - for pointers or references. - ) -) - - -$(SECTION2 Delegates, - - $(P There are no pointers-to-members in D, but a more useful - concept called $(I delegates) are supported. - Delegates are an aggregate of two pieces of data: an - object reference and a pointer to a non-static member function, - or a pointer to a closure and a pointer to a nested function. - The object reference - forms the $(I this) pointer when the function is called. - ) - - $(P Delegates are declared similarly to function pointers, - except that the keyword $(B delegate) takes the place - of (*), and the identifier occurs afterwards: - ) - -------------------- -int function(int) fp; // fp is pointer to a function -int delegate(int) dg; // dg is a delegate to a function -------------------- - - $(P The C style syntax for declaring pointers to functions is -$(V1 also supported:) -$(V2 deprecated:) - ) - -------------------- -int (*fp)(int); // fp is pointer to a function -------------------- - - $(P A delegate is initialized analogously to function pointers: - ) - -------------------- -int func(int); -fp = &func; // fp points to func - -class OB { - int member(int); -} -OB o; -dg = &o.member; // dg is a delegate to object $(I o) and - // member function $(I member) -------------------- - - $(P Delegates cannot be initialized with static member functions - or non-member functions. - ) - - $(P Delegates are called analogously to function pointers: - ) - -------------------- -fp(3); // call func(3) -dg(3); // call o.member(3) -------------------- - - $(P The equivalent of member function pointers can be constructed - using anonymous lambda functions:) - ---- -class C { - int a; - int foo(int i) { return i + a; } -} - -// mfp is the member function pointer -auto mfp = function(C self, int i) { return self.foo(i); }; -auto c = new C(); // create an instance of C -mfp(c, 1); // and call c.foo(1) ---- -) - -$(SECTION2 $(D size_t) And $(D ptrdiff_t), - - $(P $(D size_t) is an alias to one of the unsigned integral basic types, - and represents a type that is large enough to represent an offset into - all addressible memory.) - - $(P $(D ptrdiff_t) is an alias to the signed basic type the same size as $(D size_t).) -) - -) - -Macros: - TITLE=Types - WIKI=Type - CATEGORY_SPEC=$0 - diff --git a/unittest.dd b/unittest.dd deleted file mode 100644 index dfba0877c2..0000000000 --- a/unittest.dd +++ /dev/null @@ -1,67 +0,0 @@ -Ddoc - -$(SPEC_S Unit Tests, - -$(GRAMMAR -$(GNAME UnitTest): - $(B unittest) $(GLINK2 function, FunctionBody) -) - - $(P Unit tests are a series of test cases applied to a module to determine - if it is working properly. Ideally, unit tests should be run every - time a program is compiled. - ) - - $(P Unit tests are a special function defined like:) - ------- -unittest { - ...test code... -} ------- - - $(P There can be any number of unit test functions in a module, - including within struct, union and class declarations. - They are executed in lexical order. - Stylistically, a unit test for a function should appear immediately - following it. - ) - - $(P A compiler switch, such as $(DPLLINK dmd-windows.html#switches, $(B -unittest)) - for $(B dmd), will - cause the unittest test code to be compiled and incorporated into - the resulting executable. The unittest code gets run after - static initialization is run and before the $(D main()) - function is called. - ) - - $(P For example, given a class Sum that is used to add two values:) - ------- -class Sum { - int add(int x, int y) { return x + y; } - - unittest - { - Sum sum = new Sum; - assert(sum.add(3,4) == 7); - assert(sum.add(-2,0) == -2); - } -} ------- - -

    Versioning

    - - $(P The $(DDSUBLINK version, PredefinedVersions, version identifier) - $(B unittest) is predefined if the compilation - is done with unit tests enabled. - ) - -) - -Macros: - TITLE=Unit Tests - WIKI=UnitTests - CATEGORY_SPEC=$0 - FOO= - diff --git a/variadic-function-templates.dd b/variadic-function-templates.dd deleted file mode 100644 index 0550b372af..0000000000 --- a/variadic-function-templates.dd +++ /dev/null @@ -1,271 +0,0 @@ -Ddoc - -$(D_S Variadic Templates, - - $(P The problem statement is simple: write a function that - takes an arbitrary number of values of arbitrary types, - and print those values out one per line in a manner - appropriate to the type. For example, the code: - ) - ----- -print(7, 'a', 6.8); ----- - - $(P should output: - ) - -$(CONSOLE -7 -'a' -6.8 -) - - $(P We'll explore how this can - be done in standard C++, followed by doing it using - the proposed variadic template C++ extension. - Then, we'll do it the various ways the D programming - language makes possible. - ) - -

    C++ Solutions

    - -

    The Standard C++ Solution

    - - $(P The straightforward way to do this in standard C++ - is to use a series of function templates, one for - each number of arguments: - ) - -$(CCODE -#include <iostream> -using namespace::std; - -void print() -{ -} - -template<class T1> void print(T1 a1) -{ - cout << a1 << endl; -} - -template<class T1, class T2> void print(T1 a1, T2 a2) -{ - cout << a1 << endl; - cout << a2 << endl; -} - -template<class T1, class T2, class T3> void print(T1 a1, T2 a2, T3 a3) -{ - cout << a1 << endl; - cout << a2 << endl; - cout << a3 << endl; -} - -... etc ... -) - - $(P This poses significant problems: - ) - - $(P One, the function - implementor must decide in advance what the maximum number - of arguments the function will have. The implementor will - usually err on the side of excess, and ten, or even twenty - overloads of print() will be written. Yet inevitably, some - user somewhere will require just one more argument. - So this solution is never quite thoroughly right. - ) - - $(P Two, the logic of the function template body must be - cut and paste duplicated, then carefully modified, - for every one of those function templates. If the logic - needs to be adjusted, all of those function templates must - receive the same adjustment, which is tedious and error - prone. - ) - - $(P Three, as is typical for function overloads, there is no - obvious visual connection between them, they stand independently. - This makes it more difficult to understand the code, - especially if the implementor isn't careful to place them - and format them in a consistent style. - ) - - $(P Four, it leads to source code bloat which slows down - compilation. - ) - -

    The C++ Extension Solution

    - - $(P Douglas Gregor has proposed a - variadic template scheme [1] - for C++ that solves these problems. - The result looks like: - ) - -$(CCODE -void print() -{ -} - -template<class T, class... U> void print(T a1, U... an) -{ - cout << a1 << newline; - print(an...); -} -) - - $(P It uses recursive function template instantiation - to pick off the arguments one by one. - A specialization with no arguments ends the recursion. - It's a neat and tidy solution, but with one glaring problem: - it's a proposed extension, which means it isn't part - of the C++ standard, may not get into the C++ standard - in its current form, may not get into the standard - in any form, and even if it does, it may be many, many - years before the feature is commonly implemented. - ) - -

    D Programming Language Solutions

    - -

    The D Look Ma No Templates Solution

    - - $(P It is not practical to solve this problem in C++ without - using templates. In D, one can because D supports typesafe - variadic function parameters. - ) - ------- -import std.stdio; - -void print(...) -{ - foreach (arg; _arguments) - { - writefx(stdout, (&arg)[0 .. 1], _argptr, 1); - auto size = arg.tsize(); - _argptr += ((size + size_t.sizeof - 1) & ~(size_t.sizeof - 1)); - } -} ------- - - $(P It isn't elegant or the most efficient, - but it does work, and it is neatly - encapsulated into a single function. - (It relies on the predefined parameters _argptr and _arguments - which give a pointer to the values and their types, respectively.) - ) - -

    Translating the Variadic C++ Solution into D

    - - $(P Variadic templates in D enable a straightforward translation - of the proposed C++ variadic syntax: - ) - ---- -void print()() -{ -} - -void print(T, A...)(T t, A a) -{ - writefln(t); - print(a); -} ---- - - $(P There are two function templates. The first provides the - degenerate case of no arguments, and a terminus for the - recursion of the second. The second has two arguments: - t for the first value and a for the rest of the values. - A... says the parameter is a tuple, and implicit function - template instantiation will fill in A with the list of - all the types following t. So, print(7, 'a', 6.8) will - fill in int for T, and a tuple (char, double) for A. - The parameter a becomes an expression tuple of the arguments. - ) - - $(P The function works by printing the first parameter t, - and then recursively calling itself with the remaining arguments - a. The recursion terminates when there are no longer any - arguments by calling print()(). - ) - -

    The Static If Solution

    - - $(P It would be nice to encapsulate all the logic into a - single function. One way to do that is by using - static if's, which provide for conditional compilation: - ) - ---- -void print(A...)(A a) -{ - static if (a.length) - { - writefln(a[0]); - static if (a.length > 1) - print(a[1 .. length]); - } -} ---- - - $(P Tuples can be manipulated much like arrays. - So a.length resolves to the number of expressions - in the tuple a. a[0] gives the first expression - in the tuple. a[1 .. length] creates a new tuple - by slicing the original tuple. - ) - -

    The Foreach Solution

    - - $(P But since tuples can be manipulated like arrays, - we can use a foreach statement to 'loop' over - the tuple's expressions: - ) - ---- -void print(A...)(A a) -{ - foreach(t; a) - writefln(t); -} ---- - - $(P The end result is remarkably simple, self-contained, compact - and efficient. - ) - -

    Acknowledgments

    - - $(OL - - $(LI Thanks to Andrei Alexandrescu for explaining to me how - variadic templates need to work and why they are so important. - ) - - $(LI Thanks to Douglas Gregor, Jaakko Jaervi, and Gary Powell - for their inspirational work - on C++ variadic templates. - ) - - ) - -

    References

    - - $(OL - - $(LI $(LINK2 http://www.osl.iu.edu/~dgregor/cpp/variadic-templates.pdf, Variadic Templates N2080)) - - ) - -) - -Macros: - TITLE=Variadic Templates - WIKI=VariadicTemplates - CATEGORY_ARTICLES=$0 - - diff --git a/verbatim.ddoc b/verbatim.ddoc new file mode 100644 index 0000000000..37c8a7e329 --- /dev/null +++ b/verbatim.ddoc @@ -0,0 +1,89 @@ +_=****************************************************************************** +_=Macros that generate a verbatim (unexpanded) document. These are useful for +_=expanding later, visualizing the expansion process, or debugging ddoc files. +_=****************************************************************************** + +B = $(DOLLAR)(B $0) +BIG = $(DOLLAR)(BIG $0) +BLACK = $(DOLLAR)(BLACK $0) +BLUE = $(DOLLAR)(BLUE $0) +BR = $(DOLLAR)(BR $0) +DD = $(DOLLAR)(DD $0) +DL = $(DOLLAR)(DL $0) +DT = $(DOLLAR)(DT $0) +GREEN = $(DOLLAR)(GREEN $0) +I = $(DOLLAR)(I $0) +LI = $(DOLLAR)(LI $0) +LINK = $(DOLLAR)(LINK $0) +LINK2 = $(DOLLAR)(LINK2 $0) +LPAREN = $(DOLLAR)(LPAREN) +OL = $(DOLLAR)(OL $0) +P = $(DOLLAR)(P $0) +RPAREN = $(DOLLAR)(RPAREN $0) +RED = $(DOLLAR)(RED $0) +SMALL = $(DOLLAR)(SMALL $0) +TABLE = $(DOLLAR)(TABLE $0) +TD = $(DOLLAR)(TD $0) +TH = $(DOLLAR)(TH $0) +TR = $(DOLLAR)(TR $0) +U = $(DOLLAR)(U $0) +UL = $(DOLLAR)(UL $0) +WHITE = $(DOLLAR)(WHITE $0) +YELLOW = $(DOLLAR)(YELLOW $0) +_= + +D_CODE = $(DOLLAR)(D_CODE $0) +OTHER_CODE = $(DOLLAR)(OTHER_CODE $0) +D_COMMENT = $(DOLLAR)(D_COMMENT $0) +D_STRING = $(DOLLAR)(D_STRING $0) +D_KEYWORD = $(DOLLAR)(D_KEYWORD $0) +D_PSYMBOL = $(DOLLAR)(D_PSYMBOL $0) +D_PARAM = $(DOLLAR)(D_PARAM $0) +_= + +_=DDOC is a bit special - doesn't take the body as an argument, but +instead uses the predefined macro $(BODY) + +DDOC = $(DOLLAR)(DDOC $(BODY)) +DDOC_ANCHOR = $(DOLLAR)(DDOC_ANCHOR $0) +DDOC_AUTHORS = $(DOLLAR)(DDOC_AUTHORS $0) +DDOC_BLANKLINE = $(DOLLAR)(DDOC_BLANKLINE $0) +DDOC_BUGS = $(DOLLAR)(DDOC_BUGS $0) +DDOC_CLASS_MEMBERS = $(DOLLAR)(DDOC_CLASS_MEMBERS $0) +DDOC_COMMENT = $(DOLLAR)(DDOC_COMMENT $0) +DDOC_COPYRIGHT = $(DOLLAR)(DDOC_COPYRIGHT $0) +DDOC_DATE = $(DOLLAR)(DDOC_DATE $0) +DDOC_DECL = $(DOLLAR)(DDOC_DECL $0) +DDOC_DECL_DD = $(DOLLAR)(DDOC_DECL_DD $0) +DDOC_DEPRECATED = $(DOLLAR)(DDOC_DEPRECATED $0) +DDOC_DESCRIPTION = $(DOLLAR)(DDOC_DESCRIPTION $0) +DDOC_DITTO = $(DOLLAR)(DDOC_DITTO $0) +DDOC_ENUM_MEMBERS = $(DOLLAR)(DDOC_ENUM_MEMBERS $0) +DDOC_EXAMPLES = $(DOLLAR)(DDOC_EXAMPLES $0) +DDOC_HEADER_ANCHOR = $(DOLLAR)(DDOC_HEADER_ANCHOR $0) +DDOC_HISTORY = $(DOLLAR)(DDOC_HISTORY $0) +DDOC_KEYWORD = $(DOLLAR)(DDOC_KEYWORD $0) +DDOC_LICENSE = $(DOLLAR)(DDOC_LICENSE $0) +DDOC_MEMBERS = $(DOLLAR)(DDOC_MEMBERS $0) +DDOC_MEMBER = $(DOLLAR)(DDOC_MEMBER $0) +DDOC_MEMBER_HEADER = $(DOLLAR)(DDOC_MEMBER_HEADER $0) +DDOC_MODULE_MEMBERS = $(DOLLAR)(DDOC_MODULE_MEMBERS $0) +DDOC_PARAM_DESC = $(DOLLAR)(DDOC_PARAM_DESC $0) +DDOC_PARAM = $(DOLLAR)(DDOC_PARAM $0) +DDOC_PARAM_ID = $(DOLLAR)(DDOC_PARAM_ID $0) +DDOC_PARAM_ROW = $(DOLLAR)(DDOC_PARAM_ROW $0) +DDOC_PARAMS = $(DOLLAR)(DDOC_PARAMS $0) +DDOC_PSYMBOL = $(DOLLAR)(DDOC_PSYMBOL $0) +DDOC_RETURNS = $(DOLLAR)(DDOC_RETURNS $0) +DDOC_SECTION = $(DOLLAR)(DDOC_SECTION $0) +DDOC_SECTION_H = $(DOLLAR)(DDOC_SECTION_H $0) +DDOC_SECTIONS = $(DOLLAR)(DDOC_SECTIONS $0) +DDOC_SEE_ALSO = $(DOLLAR)(DDOC_SEE_ALSO $0) +DDOC_STRUCT_MEMBERS = $(DOLLAR)(DDOC_STRUCT_MEMBERS $0) +DDOC_SUMMARY = $(DOLLAR)(DDOC_SUMMARY $0) +DDOC_STANDARDS = $(DOLLAR)(DDOC_STANDARDS $0) +DDOC_TEMPLATE_MEMBERS = $(DOLLAR)(DDOC_TEMPLATE_MEMBERS $0) +DDOC_THROWS = $(DOLLAR)(DDOC_THROWS $0) +DDOC_UNDEFINED_MACRO = $(DOLLAR)($1 $+) +DDOC_VERSION = $(DOLLAR)(DDOC_VERSION $0) +_ = diff --git a/version.dd b/version.dd deleted file mode 100644 index d51cc7b014..0000000000 --- a/version.dd +++ /dev/null @@ -1,539 +0,0 @@ -Ddoc - -$(SPEC_S Conditional Compilation, - - $(P $(I Conditional compilation) is the process of selecting which - code to compile and which code to not compile. - (In C and C++, conditional compilation is done with the preprocessor - directives $(CODE #if) / $(CODE #else) / $(CODE #endif).) - ) - -$(GRAMMAR -$(GNAME ConditionalDeclaration): - $(GLINK Condition) $(GLINK CCDeclarationBlock) - $(GLINK Condition) $(GLINK CCDeclarationBlock) $(B else) $(GLINK CCDeclarationBlock) - $(GLINK Condition) $(B :) $(GLINK Declarations) - -$(GNAME CCDeclarationBlock): - $(GLINK2 declaration, Declaration) - $(B {) $(GLINK Declarations) $(B }) - $(B { }) - -$(GNAME Declarations): - $(GLINK2 declaration, Declaration) - $(GLINK2 declaration, Declaration) $(I Declarations) - -$(GNAME ConditionalStatement): - $(GLINK Condition) $(GLINK2 statement, NoScopeNonEmptyStatement) - $(GLINK Condition) $(GLINK2 statement, NoScopeNonEmptyStatement) $(B else) $(GLINK2 statement, NoScopeNonEmptyStatement) -) - - $(P If the $(GLINK Condition) is satisfied, then the following - $(I CCDeclarationBlock) or $(I Statement) is compiled in. - If it is not satisfied, the $(I CCDeclarationBlock) or $(I Statement) - after the optional $(CODE else) is compiled in. - ) - - $(P Any $(I CCDeclarationBlock) or $(I Statement) that is not - compiled in still must be syntactically correct. - ) - - $(P No new scope is introduced, even if the - $(I CCDeclarationBlock) or $(I Statement) - is enclosed by $(CODE { }). - ) - - $(P $(I ConditionalDeclaration)s and $(I ConditionalStatement)s - can be nested. - ) - - $(P The $(GLINK StaticAssert) can be used - to issue errors at compilation time for branches of the conditional - compilation that are errors. - ) - - $(P $(I Condition) comes in the following forms: - ) - -$(GRAMMAR -$(GNAME Condition): - $(GLINK VersionCondition) - $(GLINK DebugCondition) - $(GLINK StaticIfCondition) -) - -

    $(LNAME2 version, Version Condition)

    - -$(GRAMMAR -$(GNAME VersionCondition): - $(B version $(LPAREN)) $(GLINK2 lex, IntegerLiteral) $(B $(RPAREN)) - $(B version $(LPAREN)) $(I Identifier) $(B $(RPAREN)) -$(V2 - $(B version $(LPAREN)) $(B unittest) $(B $(RPAREN))) -) - - $(P Versions enable multiple versions of a module to be implemented - with a single source file. - ) - - $(P The $(I VersionCondition) is satisfied if the $(I IntegerLiteral) - is greater than or equal to the current $(I version level), - or if $(I Identifier) matches a $(I version identifier). - ) - - $(P The $(I version level) and $(I version identifier) can - be set on the command line by the $(B -version) switch - or in the module itself with a $(GLINK VersionSpecification), - or they can be predefined by the compiler. - ) - - $(P Version identifiers are in their own unique name space, they do - not conflict with debug identifiers or other symbols in the module. - Version identifiers defined in one module have no influence - over other imported modules. - ) - ------- -int k; -version (Demo) // compile in this code block for the demo version -{ int i; - int k; // error, k already defined - - i = 3; -} -x = i; // uses the i declared above ------- - ------- -version (X86) -{ - ... // implement custom inline assembler version -} -else -{ - ... // use default, but slow, version -} ------- - -$(V2 $(P The $(B version(unittest)) is satisfied if and only if the code is - compiled with unit tests enabled (the $(D -unittest) option on $(B dmd)). - ) -) - -

    $(LNAME2 VersionSpecification, Version Specification)

    - -$(GRAMMAR -$(GNAME VersionSpecification): - $(B version =) $(I Identifier) $(B ;) - $(B version =) $(GLINK2 lex, IntegerLiteral) $(B ;) -) - - $(P The version specification makes it straightforward to group - a set of features under one major version, for example: - ) - ------- -version (ProfessionalEdition) -{ - version = FeatureA; - version = FeatureB; - version = FeatureC; -} -version (HomeEdition) -{ - version = FeatureA; -} -... -version (FeatureB) -{ - ... implement Feature B ... -} ------- - - $(P Version identifiers or levels may not be forward referenced: - ) - ------- -version (Foo) -{ - int x; -} -version = Foo; // error, Foo already used ------- - $(P $(I VersionSpecification)s may only appear at module scope.) - - $(P While the debug and version conditions superficially behave the - same, - they are intended for very different purposes. Debug statements - are for adding debug code that is removed for the release version. - Version statements are to aid in portability and multiple release - versions. - ) - - $(P Here's an example of a $(I full) version as opposed to - a $(I demo) version:) - ------- -class Foo { - int a, b; - - version(full) - { - int extrafunctionality() - { - ... - return 1; // extra functionality is supported - } - } - else // demo - { - int extrafunctionality() - { - return 0; // extra functionality is not supported - } - } -} ------- - - Various different version builds can be built with a parameter - to version: - ------- -version($(I n)) // add in version code if version level is >= $(I n) -{ - ... version code ... -} - -version($(I identifier)) // add in version code if version - // keyword is $(I identifier) -{ - ... version code ... -} ------- - - $(P These are presumably set by the command line as - $(D -version=$(I n)) and $(D -version=$(I identifier)). - ) - - -

    Predefined Versions

    - - $(P Several environmental version identifiers and identifier - name spaces are predefined for consistent usage. - Version identifiers do not conflict - with other identifiers in the code, they are in a separate name space. - Predefined version identifiers are global, i.e. they apply to - all modules being compiled and imported. - ) - - $(TABLE2 Predefined Version Identifiers, - $(TR $(TH Version Identifier) $(TH Description)) - $(TR $(TD $(B DigitalMars)) $(TD DMD (Digital Mars D) is the compiler)) - $(TR $(TD $(B GNU)) $(TD GDC (GNU D Compiler) is the compiler)) - $(TR $(TD $(B LDC)) $(TD LDC (LLVM D Compiler) is the compiler)) - $(TR $(TD $(B SDC)) $(TD SDC (Stupid D Compiler) is the compiler)) - $(TR $(TD $(B D_NET)) $(TD D.NET is the compiler)) - $(TR $(TD $(B Windows)) $(TD Microsoft Windows systems)) - $(TR $(TD $(B Win32)) $(TD Microsoft 32-bit Windows systems)) - $(TR $(TD $(B Win64)) $(TD Microsoft 64-bit Windows systems)) - $(TR $(TD $(B linux)) $(TD All Linux systems)) - $(TR $(TD $(B OSX)) $(TD Mac OS X)) - $(TR $(TD $(B FreeBSD)) $(TD FreeBSD)) - $(TR $(TD $(B OpenBSD)) $(TD OpenBSD)) - $(TR $(TD $(B BSD)) $(TD All other BSDs)) - $(TR $(TD $(B Solaris)) $(TD Solaris)) - $(TR $(TD $(B Posix)) $(TD All POSIX systems (includes Linux, FreeBSD, OS X, Solaris, etc.))) - $(TR $(TD $(B AIX)) $(TD IBM Advanced Interactive eXecutive OS)) - $(TR $(TD $(B SkyOS)) $(TD The SkyOS operating system)) - $(TR $(TD $(B SysV3)) $(TD System V Release 3)) - $(TR $(TD $(B SysV4)) $(TD System V Release 4)) - $(TR $(TD $(B Hurd)) $(TD GNU Hurd)) - $(TR $(TD $(B Cygwin)) $(TD The Cygwin environment)) - $(TR $(TD $(B MinGW)) $(TD The MinGW environment)) - $(TR $(TD $(B X86)) $(TD Intel and AMD 32-bit processors)) - $(TR $(TD $(B X86_64)) $(TD AMD and Intel 64-bit processors)) - $(TR $(TD $(B ARM)) $(TD The Advanced RISC Machine architecture (32-bit))) - $(TR $(TD $(B PPC)) $(TD The PowerPC architecture, 32-bit)) - $(TR $(TD $(B PPC64)) $(TD The PowerPC architecture, 64-bit)) - $(TR $(TD $(B IA64)) $(TD The Itanium architecture (64-bit))) - $(TR $(TD $(B MIPS)) $(TD The MIPS architecture, 32-bit)) - $(TR $(TD $(B MIPS64)) $(TD The MIPS architecture, 64-bit)) - $(TR $(TD $(B SPARC)) $(TD The SPARC architecture, 32-bit)) - $(TR $(TD $(B SPARC64)) $(TD The SPARC architecture, 64-bit)) - $(TR $(TD $(B S390)) $(TD The System/390 architecture, 32-bit)) - $(TR $(TD $(B S390X)) $(TD The System/390X architecture, 64-bit)) - $(TR $(TD $(B HPPA)) $(TD The HP PA-RISC architecture, 32-bit)) - $(TR $(TD $(B HPPA64)) $(TD The HP PA-RISC architecture, 64-bit)) - $(TR $(TD $(B SH)) $(TD The SuperH architecture, 32-bit)) - $(TR $(TD $(B SH64)) $(TD The SuperH architecture, 64-bit)) - $(TR $(TD $(B Alpha)) $(TD The Alpha architecture)) - $(TR $(TD $(B LittleEndian)) $(TD Byte order, least significant first)) - $(TR $(TD $(B BigEndian)) $(TD Byte order, most significant first)) - $(TR $(TD $(B D_Coverage)) $(TD $(DPLLINK code_coverage.html, Code coverage analysis) instrumentation (command line $(DPLLINK dmd-windows.html#switches, switch) $(B -cov)) is being generated)) - $(TR $(TD $(B D_Ddoc)) $(TD $(DDLINK ddoc, Embedded Documentation, Ddoc) documentation (command line $(DPLLINK dmd-windows.html#switches, switch) $(B -D)) is being generated)) - $(TR $(TD $(B D_InlineAsm_X86)) $(TD $(DDLINK iasm, Inline Assembler, Inline assembler) for X86 is implemented)) - $(TR $(TD $(B D_InlineAsm_X86_64)) $(TD $(DDLINK iasm, Inline Assembler, Inline assembler) for X86-64 is implemented)) - $(TR $(TD $(B D_LP64)) $(TD Pointers are 64 bits (command line $(DPLLINK dmd-windows.html#switches, switch) $(B -m64)))) - $(TR $(TD $(B D_PIC)) $(TD Position Independent Code (command line $(DPLLINK dmd-windows.html#switches, switch) $(B -fPIC)) is being generated)) - $(V2 $(TR $(TD $(B D_SIMD)) $(TD $(LINK2 $(WEB simd.html)$(EBOOK #simd), Vector extensions) (__vector and __simd) are supported))) - $(V2 $(TR $(TD $(B D_Version2)) $(TD This is a D version 2 compiler))) - $(V2 $(TR $(TD $(B unittest)) $(TD $(DDLINK unittest, Unit Tests, Unit tests) are enabled (command line $(DPLLINK dmd-windows.html#switches, switch) $(B -unittest))))) - $(TR $(TD $(B none)) $(TD Never defined; used to just disable a section of code)) - $(TR $(TD $(B all)) $(TD Always defined; used as the opposite of $(B none))) - ) - - $(P The following identifiers are defined, but are deprecated: - ) - - $(TABLE2 Predefined Version Identifiers, - $(TR $(TH Version Identifier) $(TH Description)) - $(TR $(TD $(B darwin)) $(TD The Darwin operating system; use $(B OSX) instead)) - ) - - $(P Others will be added as they make sense and new implementations appear. - ) - - $(P It is inevitable that the D language will evolve over time. - Therefore, the version identifier namespace beginning with "D_" - is reserved for identifiers indicating D language specification - or new feature conformance. - ) - - $(P Furthermore, predefined version identifiers from this list cannot - be set from the command line or from version statements. - (This prevents things like both $(B Windows) and $(B linux) - being simultaneously set.) - ) - - $(P Compiler vendor specific versions can be predefined if the - trademarked vendor - identifier prefixes it, as in: - ) - ------- -version(DigitalMars_funky_extension) -{ - ... -} ------- - - $(P It is important to use the right version identifier for the right - purpose. For example, use the vendor identifier when using a vendor - specific feature. Use the operating system identifier when using - an operating system specific feature, etc. - ) - - -

    $(LNAME2 debug, Debug Condition)

    - -$(GRAMMAR -$(GNAME DebugCondition): - $(B debug) - $(B debug $(LPAREN)) $(GLINK2 lex, IntegerLiteral) $(B $(RPAREN)) - $(B debug $(LPAREN)) $(I Identifier) $(B $(RPAREN)) -) - - $(P Two versions of programs are commonly built, - a release build and a debug build. - The debug build includes extra error checking code, - test harnesses, pretty-printing code, etc. - The debug statement conditionally compiles in its - statement body. - It is D's way of what in C is done - with $(CODE #ifdef DEBUG) / $(CODE #endif) pairs. - ) - - $(P The $(B debug) condition is satisfied when the $(B -debug) switch is - thrown on the compiler. - ) - - $(P The $(B debug $(LPAREN)) $(I IntegerLiteral) $(B $(RPAREN)) condition is satisfied - when the debug - level is >= $(I IntegerLiteral). - ) - - $(P The $(B debug $(LPAREN)) $(I Identifier) $(B $(RPAREN)) condition is satisfied - when the debug identifier matches $(I Identifier). - ) - ------- -class Foo { - int a, b; - debug: - int flag; -} ------- - - -

    Debug Specification

    - -$(GRAMMAR -$(GNAME DebugSpecification): - $(B debug =) $(I Identifier) $(B ;) - $(B debug =) $(GLINK2 lex, IntegerLiteral) $(B ;) -) - - $(P Debug identifiers and levels are set either by the command line switch - $(B -debug) or by a $(I DebugSpecification). - ) - - $(P Debug specifications only affect the module they appear in, they - do not affect any imported modules. Debug identifiers are in their - own namespace, independent from version identifiers and other - symbols. - ) - - $(P It is illegal to forward reference a debug specification: - ) - ------- -debug (foo) writefln("Foo"); -debug = foo; // error, foo used before set ------- - - $(P $(I DebugSpecification)s may only appear at module scope.) - - $(P Various different debug builds can be built with a parameter to - debug: - ) - ------- -debug($(GLINK2 lex, IntegerLiteral)) { } // add in debug code if debug level is >= $(GLINK2 lex, IntegerLiteral) -debug($(I identifier)) { } // add in debug code if debug keyword is $(I identifier) ------- - - $(P These are presumably set by the command line as - $(D -debug=$(I n)) and $(D -debug=$(I identifier)). - ) - -

    $(LNAME2 staticif, Static If Condition)

    - -$(GRAMMAR -$(GNAME StaticIfCondition): - $(B static if $(LPAREN)) $(ASSIGNEXPRESSION) $(B $(RPAREN)) -) - - $(P $(ASSIGNEXPRESSION) is implicitly converted to a boolean type, - and is evaluated at compile time. - The condition is satisfied if it evaluates to $(B true). - It is not satisfied if it evaluates to $(B false). - ) - - $(P It is an error if $(ASSIGNEXPRESSION) cannot be implicitly converted - to a boolean type or if it cannot be evaluated at compile time. - ) - - $(P $(I StaticIfCondition)s - can appear in module, class, template, struct, union, or function scope. - In function scope, the symbols referred to in the - $(ASSIGNEXPRESSION) can be any that can normally be referenced - by an expression at that point. - ) - ------- -const int i = 3; -int j = 4; - -$(B static if) (i == 3) // ok, at module scope - int x; - -class C { - const int k = 5; - - $(B static if) (i == 3) // ok - int x; - $(B else) - long x; - - $(B static if) (j == 3) // error, j is not a constant - int y; - - $(B static if) (k == 5) // ok, k is in current scope - int z; -} - -template INT(int i) { - $(B static if) (i == 32) - alias int INT; - $(B else static if) (i == 16) - alias short INT; - $(B else) - static assert(0); // not supported -} - -INT!(32) a; // a is an int -INT!(16) b; // b is a short -INT!(17) c; // error, static assert trips ------- - - $(P A $(I StaticIfConditional) condition differs from an - $(I IfStatement) in the following ways: - ) - - $(OL - $(LI It can be used to conditionally compile declarations, - not just statements. - ) - $(LI It does not introduce a new scope even if $(B { }) - are used for conditionally compiled statements. - ) - $(LI For unsatisfied conditions, the conditionally compiled code - need only be syntactically correct. It does not have to be - semantically correct. - ) - $(LI It must be evaluatable at compile time. - ) - ) - - -

    $(LNAME2 static-assert, $(LNAME2 StaticAssert, Static Assert))

    - -$(GRAMMAR -$(GNAME StaticAssert): - $(B static assert $(LPAREN)) $(ASSIGNEXPRESSION) $(B $(RPAREN);) - $(B static assert $(LPAREN)) $(ASSIGNEXPRESSION) $(B ,) $(ASSIGNEXPRESSION) $(B $(RPAREN);) -) - - $(P $(ASSIGNEXPRESSION) is evaluated at compile time, and converted - to a boolean value. If the value is true, the static assert - is ignored. If the value is false, an error diagnostic is issued - and the compile fails. - ) - - $(P Unlike $(GLINK2 expression, AssertExpression)s, $(I StaticAssert)s are always - checked and evaluted by the compiler unless they appear in an - unsatisfied conditional. - ) - ------- -void foo() { - if (0) - { - assert(0); // never trips - static assert(0); // always trips - } - version (BAR) - { - } - else - { - static assert(0); // trips when version BAR is not defined - } -} ------- - - $(P $(I StaticAssert) is useful tool for drawing attention to conditional - configurations not supported in the code. - ) - - $(P The optional second $(ASSIGNEXPRESSION) can be used to supply - additional information, such as a text string, that will be - printed out along with the error diagnostic. - ) -) - -Macros: - TITLE=Conditional Compilation - WIKI=Version - CATEGORY_SPEC=$0 - diff --git a/warnings.dd b/warnings.dd deleted file mode 100644 index f165de0d4d..0000000000 --- a/warnings.dd +++ /dev/null @@ -1,391 +0,0 @@ -Ddoc - -$(D_S Warnings, - - $(P Depending on one's point of view, warnings are either a symptom - of broken language design or a useful $(SINGLEQUOTE lint) like tool to analyze - code and look for potential trouble spots. - Most of the time, those trouble spots will be legitimate code - intended to be that way. More rarely, it may indicate an - unintentional error on the part of the programmer. - ) - - $(P Warnings are not a defined part of the D Programming Language. - They exist at the discretion of the compiler vendor, and - will most likely vary from vendor to vendor. - All constructs for which an implementation may generate a warning - message are legal D code. - ) - - $(P These are the warnings generated by the Digital Mars D compiler - when the $(B -w) switch is thrown. - Most have generated some spirited debate as to whether it should - be a warning, an error, and what the correct way to write D code - in these situations should be. Since no consensus emerged, - they appear as optional warnings, with alternatives on how to - write correct code. - ) - -

    warning - implicit conversion of expression $(I expr) of type $(I type) to $(I type) can cause loss of data

    - - $(P D follows the C and C++ rules regarding default integral promotion - in expressions. This is done for both compatibility reasons - and because modern CPUs are designed to execute such semantics - efficiently. These rules also include implicit narrowing rules, - where the result of such can be cast back into a smaller type, - perhaps losing significant bits in the process: - ) - ---- -byte a,b,c; -... -a = b + c; ---- - - $(P The $(I b) and $(I c) are both promoted to type $(B int) using - the default integral promotion rules. The result of the add is then - also $(B int). To be assigned to $(I a), that $(B int) gets - implicitly converted to a $(B byte). - ) - - $(P Whether it is a bug or not in the program depends on if the values - for $(I b) and $(I c) can possibly cause an overflow, and - if that overflow matters or not to the algorithm. - The warning can be resolved by: - ) - - $(OL - $(LI Inserting a cast: ---- -a = cast(byte)(b + c); ---- - This eliminates the warning, but since casting is a blunt instrument - that bypasses type checking, this can mask another bug that could - be introduced if the types of $(I a), $(I b) or $(I c) - change in the future, or if their types are set by a template - instantiation. (In generic code, the $(D cast(byte)) would - probably be $(D cast(typeof(a)))). - ) - - $(LI Changing the type of $(I a) to $(B int). - This is generally a better solution, but of course may not work - if it must be a smaller type, which leads us to: - ) - - $(LI Doing a runtime check for overflow: ---- -byte a,b,c; -int tmp; -... -tmp = b + c; -assert(cast(byte)tmp == tmp); -a = cast(byte)tmp; ---- - This ensures that no significant bits get lost. - ) - ) - - $(P Some proposed language solutions are:) - - $(OL - $(LI Having the compiler automatically insert the equivalent of - the option 3 runtime check. - ) - - $(LI Add a new construct, - $(D $(B implicit_cast)($(I type))$(I expression)) - that is a restricted form of the general cast, and will only - work where implicit casts would normally be allowed. - ) - - $(LI Implement the $(B implicit_cast) as a template. - ) - - ) - -

    warning - array 'length' hides other 'length' name in outer scope

    - - $(P Inside the [ ] of an array indexing expression or slice, the - variable $(I length) gets defined and set to be the length - of that array. The scope of the $(I length) is from the opening - $(SINGLEQUOTE [) to the closing $(SINGLEQUOTE ]). - ) - - $(P If $(I length) was declared as a variable name - in an outer scope, that version may have been intended for - use between the [ ]. For example: - ) - ---- -char[10] a; -int length = 4; -... -return a[length - 1]; // returns a[9], not a[3] ---- - - $(P The warning can be resolved by:) - - $(OL - $(LI Renaming the outer $(I length) to another name. - ) - - $(LI Replacing the use of $(I length) within the [ ] - with $(I a.length). - ) - - $(LI If $(I length) is at global or class scope, and that was the - one intended to be used, use $(I .length) or $(I this.length) - to disambiguate. - ) - ) - - $(P Some proposed language solutions are:) - - $(OL - $(LI Make the $(I length) a special symbol or a keyword instead - of an implicitly declared variable. - ) - ) - -

    warning - no return at end of function

    - - $(P Consider the following:) - ---- -int foo(int k, Collection c) -{ - foreach (int x; c) - { - if (x == k) - return x + 1; - } -} ---- - - $(P and assume that the nature of the algorithm is that $(I x) will - always be found in $(I c), so the $(B foreach) never falls - through the bottom of the code. - There is no $(B return) at the close of the function, because - that point is not reachable and any return statement would - be dead code. - This is perfectly legitimate code. - The D compiler, to help with ensuring the robustness of such - code, will ensure it is correct by automatically inserting - an $(I assert(0);) statement at the close of the function. - Then, if there's an error in the assumption that the $(B foreach) will - never fall through, it will be caught at runtime with - an obvious assertion failure, which is better than the code just - falling off the end causing erratic, arbitrary failures. - ) - - $(P D's behavior on this, however, is not common to other languages, - and some programmers will be acutely uncomfortable with relying - on this, or they wish to see the error at compile time rather - than runtime. They wish to see something explicit expressed in the - source code that the $(B foreach) cannot fall through. - Hence the warning. - ) - - $(P The warning can be resolved by: - ) - - $(OL - $(LI Putting a return statement at the close of the function, - returning some arbitrary value (after all, it will never be - executed): - ---- -int foo(int k, Collection c) -{ - foreach (int x; c) - { - if (x == k) - return x + 1; - } - return 0; // suppress warning about no return statement -} ---- - - While doing this is surprisingly common, and happens when - the programmer is inexperienced or in a hurry, it is a - spectacularly bad solution. - The trouble happens when the $(B foreach) does fall through - due to a bug, then instead of the bug being detected, now - the function returns an unexpected value, which may cause other - problems or go undetected. - There's another issue with the maintenance programmer who - sees this, and upon analyzing the code's behavior, wonders why - there's a return statement that will never be executed. - (This can be resolved with comments, but comments are always - missing, out of date, or just plain wrong.) - Dead code is always a confusing problem to maintenance programming, - so deliberately inserting it is a bad idea. - ) - - $(LI A better solution is to make explicit what the D language - does implicitly - put an assert there: - ---- -int foo(int k, Collection c) -{ - foreach (int x; c) - { - if (x == k) - return x + 1; - } - assert(0); -} ---- - - Now, if the $(B foreach) does fall through, the error will be - detected. Furthermore, it is self-documenting. - ) - - $(LI Another alternative is to do a $(B throw) with a custom - error class and a more user friendly message: - ---- -int foo(int k, Collection c) -{ - foreach (int x; c) - { - if (x == k) - return x + 1; - } - $(B throw) new MyErrorClass("fell off the end of foo()"); -} ---- - ) - ) - -$(V1 -

    warning - switch statement has no default

    - - $(P Similar to the no return statement warning is the no default - in a switch warning. Consider: - ) - ---- -switch (i) -{ - case 1: dothis(); break; - case 2: dothat(); break; -} ---- - - $(P According to the D language semantics, this means the only possible - values for $(I i) are 1 and 2. Any other values represent a bug - in the program. To detect this bug, the compiler implements the - switch as if it were written: - ) - ---- -switch (i) -{ - case 1: dothis(); break; - case 2: dothat(); break; - $(B default: throw new SwitchError();) -} ---- - - $(P This is quite different from C and C++ behavior, which is as if - the switch were written: - ) - ---- -switch (i) -{ - case 1: dothis(); break; - case 2: dothat(); break; - $(B default: break;) -} ---- - - $(P The potential for bugs with that is high, as it is a common error - to accidentally omit a case, or to add a new value in one part of - the program and overlook adding a case for it in another part. - Although D will catch this error at runtime by throwing - an instance of $(D std.switcherr.SwitchError), some prefer at least - a warning so such errors can be caught at compile time. - ) - - $(P The warning can be resolved by: - ) - - $(OL - $(LI Inserting an explict default of the form: - ---- -switch (i) -{ - case 1: dothis(); break; - case 2: dothat(); break; - $(B default: assert(0);) -} ---- - ) - - $(LI As in the missing return, a default with a throw of a custom - error class can be used. - ) - ) -) - -

    warning - statement is not reachable

    - - $(P Consider the following code:) - ---- -int foo(int i) -{ - return i; - $(B return i + 1;) -} ---- - - $(P The second return statement is not reachable, i.e. it is dead - code. While dead code is poor style in released code, it can - legitimately - happen a lot when rapidly trying to isolate down a bug or experiment - with different bits of code. - ) - - $(P The warning can be resolved by: - ) - - $(OL - $(LI Commenting out the dead code with /+ ... +/ comments: ---- -int foo(int i) -{ - return i; - /+ - return i + 1; - +/ -} ---- - ) - - $(LI Putting the dead code inside a $(D version(none)) conditional: ---- -int foo(int i) -{ - return i; - $(B version (none)) - { - return i + 1; - } -} ---- - ) - - $(LI Only compile with warnings enabled when doing release builds. - ) - ) - -) - -Macros: - TITLE=Warnings - WIKI=Warnings - CATEGORY_OVERVIEW=$0 diff --git a/wc.dd b/wc.dd index d06f9a8934..c2314fd880 100644 --- a/wc.dd +++ b/wc.dd @@ -2,132 +2,74 @@ Ddoc $(D_S Example: wc, - $(P This program is the D version of the classic wc (wordcount) C - program. - It serves to demonstrate how to read files, slice arrays, - and simple symbol table management with associative arrays. - It has two main code paths, one for smaller files that will fit - in memory, and one using buffered file I/O for files that are larger. - ) - ------------- + $(P This program is the D version of the classic `wc` (wordcount) C + program. + It serves to demonstrate how to read files, slice arrays, + and simple symbol table management with associative arrays. + ) + +$(RUNNABLE_EXAMPLE +---- import std.stdio; -import std.stream; +import std.algorithm; -int main (string[] args) +void main(string[] args) { - int w_total; - int l_total; - ulong c_total; + ulong wordCount; + ulong lineCount; + ulong charCount; + int[string] dictionary; + writeln(" lines words bytes file"); - writefln(" lines words bytes file"); - foreach (arg; args[1 .. args.length]) + foreach (arg; args[1 .. $]) { - int w_cnt, l_cnt; - bool inword; - - auto c_cnt = std.file.getSize(arg); - if (c_cnt < 10_000_000) - { - size_t wstart; - auto input = cast(string)std.file.read(arg); - - foreach (j, c; input) - { - if (c == '\n') - ++l_cnt; - if (c >= '0' && c <= '9') - { - } - else if (c >= 'a' && c <= 'z' || - c >= 'A' && c <= 'Z') - { - if (!inword) - { - wstart = j; - inword = true; - ++w_cnt; - } - } - else if (inword) - { auto word = input[wstart .. j]; - - dictionary[word]++; - inword = false; - } - } - if (inword) - { auto w = input[wstart .. input.length]; - dictionary[w]++; - } - } - else - { - auto f = new BufferedFile(arg); - string buf; - - while (!f.eof()) - { char c; - - f.read(c); - if (c == '\n') - ++l_cnt; - if (c >= '0' && c <= '9') - { - if (inword) - buf ~= c; - } - else if (c >= 'a' && c <= 'z' || - c >= 'A' && c <= 'Z') - { - if (!inword) - { - buf.length = 0; - buf ~= c; - inword = 1; - ++w_cnt; - } - else - buf ~= c; - } - else if (inword) - { - if (++dictionary[buf] == 1) - buf = null; - inword = 0; - } - } - if (inword) - { - dictionary[buf]++; - } - } - writefln("%8s%8s%8s %s\n", l_cnt, w_cnt, c_cnt, arg); - l_total += l_cnt; - w_total += w_cnt; - c_total += c_cnt; + ulong lWordCount; + ulong lCharCount; + ulong lLineCount; + + auto file = File(arg); + foreach (line; file.byLine(KeepTerminator.yes)) + { + lCharCount += line.length; + foreach (word; splitter(line)) + { + lWordCount += 1; + if (auto count = word in dictionary) + *count += 1; + else + dictionary[word.idup] = 1; + } + + lLineCount += 1; + } + + writefln("%8s%8s%8s %s\n", lLineCount, lWordCount, lCharCount, arg); + + wordCount += lWordCount; + lineCount += lLineCount; + charCount += lCharCount; } + const char[37] hr = '-'; + if (args.length > 2) { - writefln("--------------------------------------\n%8s%8s%8s total", - l_total, w_total, c_total); + writeln(hr); + writefln("%8s%8s%8s total", lineCount, wordCount, charCount); } - writefln("--------------------------------------"); + writeln(hr); - foreach (word1; dictionary.keys.sort) + foreach (word; sort(dictionary.keys)) { - writefln("%3s %s", dictionary[word1], word1); + writefln("%3s %s", dictionary[word], word); } - return 0; } -------------- +---- +) ) Macros: - TITLE=Word Count - WIKI=WC - CATEGORY_OVERVIEW=$0 + TITLE=Word Count diff --git a/win32.mak b/win32.mak index b7012f9591..6f0629d67a 100644 --- a/win32.mak +++ b/win32.mak @@ -1,338 +1,42 @@ -# makefile to build html files for DMD +# Building dlang.org on Windows is no longer supported. +# Please use a Posix-like System, Bash under Windows or +# simply use the dlang.org preview DAutoTest automatically adds to every PR -DMD=dmd - -SRC= $(SPECSRC) cpptod.dd ctod.dd pretod.dd cppdbc.dd index.dd \ - overview.dd mixin.dd memory.dd interface.dd windows.dd \ - dll.dd htomodule.dd faq.dd dstyle.dd wc.dd changelog.dd \ - glossary.dd acknowledgements.dd dcompiler.dd builtin.dd \ - comparison.dd rationale.dd code_coverage.dd exception-safe.dd \ - rdmd.dd templates-revisited.dd warnings.dd ascii-table.dd \ - windbg.dd htod.dd regular-expression.dd lazy-evaluation.dd \ - variadic-function-templates.dd howto-promote.dd tuple.dd \ - template-comparison.dd COM.dd hijack.dd features2.dd safed.dd \ - const-faq.dd concepts.dd d-floating-point.dd migrate-to-shared.dd \ - D1toD2.dd pdf-intro-cover.dd pdf-spec-cover.dd pdf-tools-cover.dd \ - intro-to-datetime.dd simd.dd - -SPECSRC=spec.dd lex.dd module.dd declaration.dd type.dd property.dd \ - attribute.dd pragma.dd expression.dd statement.dd arrays.dd \ - hash-map.dd struct.dd class.dd interface.dd enum.dd const3.dd \ - function.dd operatoroverloading.dd template.dd template-mixin.dd \ - dbc.dd version.dd traits.dd errors.dd unittest.dd garbage.dd \ - float.dd iasm.dd ddoc.dd interfaceToC.dd cpp_interface.dd \ - portability.dd entity.dd memory-safe-d.dd abi.dd simd.dd - -DDOC=macros.ddoc windows.ddoc doc.ddoc - -ASSETS=images\*.* css\*.* -IMG=dmlogo.gif cpp1.gif d002.ico c1.gif d3.gif d4.gif d5.gif favicon.gif - -PREMADE=download.html dcompiler.html language-reference.html appendices.html howtos.html articles.html - -TARGETS=cpptod.html ctod.html pretod.html cppdbc.html index.html \ - overview.html lex.html module.html declaration.html \ - type.html property.html attribute.html pragma.html \ - expression.html statement.html arrays.html struct.html class.html \ - enum.html function.html operatoroverloading.html template.html \ - mixin.html dbc.html version.html errors.html garbage.html \ - memory.html float.html iasm.html interface.html portability.html \ - entity.html abi.html windows.html dll.html htomodule.html \ - faq.html dstyle.html wc.html changelog.html glossary.html \ - acknowledgements.html builtin.html interfaceToC.html \ - comparison.html rationale.html ddoc.html code_coverage.html \ - exception-safe.html rdmd.html templates-revisited.html \ - warnings.html ascii-table.html windbg.html htod.html \ - regular-expression.html lazy-evaluation.html \ - variadic-function-templates.html howto-promote.html tuple.html \ - template-comparison.html template-mixin.html traits.html COM.html \ - cpp_interface.html hijack.html const3.html features2.html \ - safed.html const-faq.html dmd-windows.html dmd-linux.html \ - dmd-osx.html dmd-freebsd.html concepts.html memory-safe-d.html \ - d-floating-point.html migrate-to-shared.html D1toD2.html \ - unittest.html hash-map.html pdf-intro-cover.html \ - pdf-spec-cover.html pdf-tools-cover.html intro-to-datetime.html \ - simd.html - - -PDFINTRO=index.html overview.html wc.html warnings.html builtin.html \ - ctod.html cpptod.html pretod.html template-comparison.html \ - cppdbc.html - -PDFFEATURES=comparison.html features2.html - -PDFFAQ=faq.html const-faq.html rationale.html - -PDFSPEC=lex.html module.html declaration.html type.html property.html \ - attribute.html pragma.html expression.html statement.html \ - arrays.html hash-map.html struct.html class.html interface.html \ - enum.html const3.html function.html operatoroverloading.html \ - template.html template-mixin.html dbc.html version.html \ - traits.html errors.html unittest.html garbage.html float.html \ - iasm.html ddoc.html interfaceToC.html cpp_interface.html \ - portability.html entity.html memory-safe-d.html abi.html simd.html - -PDFHOWTOS=windows.html dll.html COM.html htomodule.html - -PDFARTICLES=d-floating-point.html migrate-to-shared.html hijack.html const3.html \ - memory.html exception-safe.html templates-revisited.html regular-expression.html \ - lazy-evaluation.html variadic-function-templates.html tuple.html mixin.html \ - safed.html intro-to-datetime.html - -PDFTOOLS=dmd-linux.html dmd-freebsd.html dmd-osx.html dmd-windows.html \ - http://www.digitalmars.com/ctg/optlink.html http://www.digitalmars.com/ctg/trace.html \ - code_coverage.html rdmd.html windbg.html htod.html - -PDFAPPENDICES=dstyle.html glossary.html ascii-table.html acknowledgements.html +LATEST=prerelease -PDFOPTIONS=--header-left [section] --header-right [page] --header-spacing 3 --header-font-name Georgia --print-media-type --outline - -PDFTARGETS=d-intro.pdf d-spec.pdf d-tools.pdf +DMD=dmd +DDOC=macros.ddoc html.ddoc dlang.org.ddoc windows.ddoc doc.ddoc $(NODATETIME) +W=web CHMTARGETS=d.hhp d.hhc d.hhk d.chm - HHC=$(ProgramFiles)\HTML Help Workshop\hhc.exe -target: $(TARGETS) - -.dd.html: - $(DMD) -o- -c -D $(DDOC) $*.dd - -.d.html: - $(DMD) -o- -c -D $(DDOC) $*.d - -dmd-linux.html : $(DDOC) linux.ddoc dcompiler.dd - $(DMD) -o- -c -D $(DDOC) linux.ddoc dcompiler.dd -Dfdmd-linux.html - -dmd-freebsd.html : $(DDOC) freebsd.ddoc dcompiler.dd - $(DMD) -o- -c -D $(DDOC) freebsd.ddoc dcompiler.dd -Dfdmd-freebsd.html - -dmd-osx.html : $(DDOC) osx.ddoc dcompiler.dd - $(DMD) -o- -c -D $(DDOC) osx.ddoc dcompiler.dd -Dfdmd-osx.html - -dmd-windows.html : $(DDOC) windows.ddoc dcompiler.dd - $(DMD) -o- -c -D $(DDOC) windows.ddoc dcompiler.dd -Dfdmd-windows.html - -abi.html : $(DDOC) abi.dd - -acknowledgements.html : $(DDOC) acknowledgements.dd - -arrays.html : $(DDOC) arrays.dd - -ascii-table.html : $(DDOC) ascii-table.dd - -attribute.html : $(DDOC) attribute.dd - -builtin.html : $(DDOC) builtin.dd - -changelog.html : $(DDOC) changelog.dd - -class.html : $(DDOC) class.dd - -code_coverage.html : $(DDOC) code_coverage.dd - -COM.html : $(DDOC) COM.dd - -comparison.html : $(DDOC) comparison.dd - -concepts.html : $(DDOC) concepts.dd - -const3.html : $(DDOC) const3.dd - -const-faq.html : $(DDOC) const-faq.dd - -cpp_interface.html : $(DDOC) cpp_interface.dd - -cppdbc.html : $(DDOC) cppdbc.dd - -cpptod.html : $(DDOC) cpptod.dd - -ctod.html : $(DDOC) ctod.dd - -D1toD2.html : $(DDOC) D1toD2.dd - -d-floating-point.html : $(DDOC) d-floating-point.dd - -dbc.html : $(DDOC) dbc.dd - -ddoc.html : $(DDOC) ddoc.dd - -declaration.html : $(DDOC) declaration.dd - -dll.html : $(DDOC) dll.dd - -dstyle.html : $(DDOC) dstyle.dd - -entity.html : $(DDOC) entity.dd - -enum.html : $(DDOC) enum.dd - -errors.html : $(DDOC) errors.dd - -exception-safe.html : $(DDOC) exception-safe.dd - -expression.html : $(DDOC) expression.dd - -faq.html : $(DDOC) faq.dd - -features2.html : $(DDOC) features2.dd - -float.html : $(DDOC) float.dd - -function.html : $(DDOC) function.dd - -garbage.html : $(DDOC) garbage.dd - -glossary.html : $(DDOC) glossary.dd - -hash-map.html : $(DDOC) hash-map.dd - -hijack.html : $(DDOC) hijack.dd - -howto-promote.html : $(DDOC) howto-promote.dd - -htod.html : $(DDOC) htod.dd - -htomodule.html : $(DDOC) htomodule.dd - -iasm.html : $(DDOC) iasm.dd - -interface.html : $(DDOC) interface.dd - -interfaceToC.html : $(DDOC) interfaceToC.dd - -index.html : $(DDOC) index.dd - -intro-to-datetime.html : $(DDOC) intro-to-datetime.dd - -lazy-evaluation.html : $(DDOC) lazy-evaluation.dd - -lex.html : $(DDOC) lex.dd - -memory.html : $(DDOC) memory.dd - -memory-safe-d.html : $(DDOC) memory-safe-d.dd - -migrate-to-shared.html : $(DDOC) migrate-to-shared.dd - -mixin.html : $(DDOC) mixin.dd - -module.html : $(DDOC) module.dd - -operatoroverloading.html : $(DDOC) operatoroverloading.dd - -overview.html : $(DDOC) overview.dd - -pdf-intro-cover.html : $(DDOC) pdf-intro-cover.dd - -pdf-spec-cover.html : $(DDOC) pdf-spec-cover.dd - -pdf-tools-cover.html : $(DDOC) pdf-tools-cover.dd - -portability.html : $(DDOC) portability.dd - -pragma.html : $(DDOC) pragma.dd - -pretod.html : $(DDOC) pretod.dd - -property.html : $(DDOC) property.dd - -rationale.html : $(DDOC) rationale.dd - -rdmd.html : $(DDOC) rdmd.dd - -regular-expression.html : $(DDOC) regular-expression.dd - -safed.html : $(DDOC) safed.dd - -simd.html : $(DDOC) simd.dd - -statement.html : $(DDOC) statement.dd - -struct.html : $(DDOC) struct.dd - -template.html : $(DDOC) template.dd - -template-comparison.html : $(DDOC) template-comparison.dd - -template-mixin.html : $(DDOC) template-mixin.dd - -templates-revisited.html : $(DDOC) templates-revisited.dd - -traits.html : $(DDOC) traits.dd - -tuple.html : $(DDOC) tuple.dd - -type.html : $(DDOC) type.dd - -unittest.html : $(DDOC) unittest.dd - -variadic-function-templates.html : $(DDOC) variadic-function-templates.dd - -version.html : $(DDOC) version.dd - -warnings.html : $(DDOC) warnings.dd - -wc.html : $(DDOC) wc.dd - -windbg.html : $(DDOC) windows.ddoc windbg.dd - -windows.html : $(DDOC) windows.ddoc windows.dd - -################ Ebook ######################## - -dlangspec.d : $(SPECSRC) win32.mak - catdoc -o=dlangspec.d $(SPECSRC) - -dlangspec.html : $(DDOC) ebook.ddoc dlangspec.d - $(DMD) $(DDOC) ebook.ddoc dlangspec.d - -dlangspec.zip : dlangspec.html ebook.css win32.mak - del dlangspec.zip - zip32 dlangspec dlangspec.html ebook.css - -dlangspec.mobi : dlangspec.opf dlangspec.html dlangspec.png dlangspec.ncx ebook.css win32.mak - del dlangspec.mobi - \kindlegen\kindlegen dlangspec.opf - -################# Pdf ######################### - -pdf : $(PDFTARGETS) - -d-intro.pdf: - wkhtmltopdf $(PDFOPTIONS) cover pdf-intro-cover.html toc $(PDFINTRO) $(PDFFEATURES) $(PDFFAQ) $(PDFAPPENDICES) d-intro.pdf +################# CHM ######################### -d-spec.pdf: - wkhtmltopdf $(PDFOPTIONS) cover pdf-spec-cover.html toc $(PDFSPEC) $(PDFAPPENDICES) d-spec.pdf +chm : d.chm -d-tools.pdf: - wkhtmltopdf $(PDFOPTIONS) cover pdf-tools-cover.html toc $(PDFTOOLS) $(PDFHOWTOS) $(PDFARTICLES) $(PDFAPPENDICES) d-tools.pdf +chmgen.exe : tools\chmgen.d + $(DMD) -g chmgen -################# CHM ######################### +chm\d.hhp chm\d.hhc chm\d.hhk : chmgen.exe chm-nav-release.json $(TARGETS) + chmgen --root=$W --target release -chm : d.chm +chm\d.chm : chm\d.hhp chm\d.hhc chm\d.hhk + -cmd /C "cd chm && "$(HHC)" d.hhp" -chmgen.exe : chmgen.d - $(DMD) chmgen +d.chm : chm\d.chm + copy /Y chm\d.chm d.chm -d.hhp d.hhc d.hhk : chmgen.exe $(TARGETS) - chmgen +chm-nav-release.json : $(DDOC) std.ddoc spec\spec.ddoc modlist-release.ddoc changelog\changelog.ddoc chm-nav.dd + $(DMD) -o- -c -Df$@ $** -d.chm : d.hhp d.hhc d.hhk - cmd /C ""$(HHC)" d.hhp" +modlist-release.ddoc : tools\modlist.d +# need + to run as sub-cmd, redirect doesn't work otherwise + +$(DMD) -run modlist.d ..\druntime ..\phobos $(MOD_EXCLUDES_RELEASE) >$@ ################# Other ######################### -zip: - del doc.zip - zip32 doc win32.mak $(DDOC) windows.ddoc linux.ddoc osx.ddoc freebsd.ddoc ebook.ddoc - zip32 doc $(SRC) $(PREMADE) - zip32 doc $(ASSETS) - zip32 doc ebook.css dlangspec.opf dlangspec.ncx dlangspec.png - clean: - del $(TARGETS) - del $(PDFTARGETS) del $(CHMTARGETS) - - + del chmgen.obj chmgen.exe + if exist chm rmdir /S /Q chm diff --git a/windbg.dd b/windbg.dd index 9a5856940f..1003ba1a63 100644 --- a/windbg.dd +++ b/windbg.dd @@ -1,183 +1,59 @@ Ddoc -$(D_S Debugging D on Windows, - -$(P The Microsoft Windows debugger $(D $(DMDDIR)\windows\bin\windbg.exe) can be used to -symbolically debug D programs, even though it is a C++ debugger. -Versions of $(D windbg.exe) other than the one supplied may not work with D. -(Jascha Wetzel's $(LINK2 http://ddbg.mainia.de/releases.html, Ddbg for Windows) -is also available.) -) +The D reference compiler DMD and the LLVM-based LDC compiler can both output symbolic +debug information that can be used by most Windows debuggers. With the exception of +generating OMF object files when using -m32 with dmd, the linker will generate a PDB file +containing the debug information of the executable. $(P To prepare a program for symbolic debugging, compile -with the $(B -gc) switch: +with the $(B -gf) switch: ) $(CONSOLE -dmd myprogram -gc +dmd -gf -m64 myprogram.d ) -$(P To invoke the debugger on it: +$(P How to start debugging the program depends on debugger being used. For example debugging with Visual Studio +can be invoked by opening the "Developer Command Prompt for VS" and executing: ) $(CONSOLE -windbg myprogram args... +devenv myprogram.exe ) -$(P -where $(D args...) are the command line arguments to myprogram.exe. +$(P If you want to pass arguments to the debuggee you have to use the /debugexe switch: ) -$(P When the debugger comes up, entering the command in the command window:) - $(CONSOLE -g _Dmain +devenv /debugexe myprogram.exe args... ) -$(P will execute the program up until the entry into $(D main()). -From thence, pressing the $(B F10) key will single step each line -of code.) - -$(P Basic Commands:) - -$(DL - -$(DT F5) -$(DD Go until breakpoint, an exception is thrown, or the end of the program.) - -$(DT F7) -$(DD Continue until cursor.) - -$(DT F8) -$(DD Single step, stepping into function calls.) - -$(DT F10) -$(DD Single step, stepping over function calls.) +$(P where $(D args...) are the command line arguments to myprogram.exe. ) -$(P For more comprehensive information on $(B windbg), consult the -file $(D $(DMDDIR)\windows\bin\windbg.hlp). +$(P When the debugger comes up, load myprogram.d and set a breakpoint at the beginning of your $(D main()) function. +Running the program will stop at your breakpoint in $(D main()). +The debugger should then allow you to step through the program, show local variables and watch expressions. ) -$(COMMENT -

    Sample Debug Session

    - -$(P This is a walkthrough of a typical debugging session. Given the program:) - ----------- -import std.stdio; - -class Foo -{ - int x; -} - -int main() -{ - Foo p; - bar(p); -} - -void bar(Foo p) -{ - abc(p); -} - -void abc(Foo p) -{ - p.x++; -} ---------- - -$(P It is compiled and run with the following commands:) - -$(CONSOLE -C:\bug>dmd bug -g -\dm\bin\link bug,,,user32+kernel32/co/noi; - -C:\bug>bug -Error: Access Violation - -C:\bug> +$(P If you have $(LINK2 $(VISUALD), Visual D) installed as an extension to Visual Studio, the debugger understands D expressions +in watch expressions and is able to inspect D-specific language constructs like dynamic and associative arrays. +This functionality might also be available in other debuggers if they support it through +$(LINK2 https://github.com/rainers/mago/tree/master/MagoMI/mago-mi, mago-mi). ) -$(P It's obviously got a bug, so fire up the debugger with:) - -$(CONSOLE -C:\bug>windbg bug.exe -) - -$(P and the debugger window comes up:) - - - -$(P Advance to the beginning of $(D main()) by entering $(D g _Dmain):) - - - -$(P now were at the beginning of main(). The upper left black window shows -the console output so far, the middle window shows the current location -and next instruction (the $(D xor)), The lower right window shows the -current location in the source code, highlighted in yellow.) - -$(P In order to run until the exception happens, use the $(D g) command:) - - - -$(P The $(D First chance exception) says an exception was thrown. The -lower right window now shows the line on which the exception happened -highlighted in yellow.) - -$(P Now click on the [Window] menu and Select [Calls]:) - - - -$(P and a window will appear showing the call stack:) - - - -$(P Clicking on the [Disassembly] command brings up -the Disassembly window where the instruction that faulted is highlighted -in yellow. Clicking on the [Registers] command brings up -the register window, where EAX holds the value 00000000.) - - - -$(P The trouble is clearly that $(D p) is $(D null). Fix it by allocating -an instance for $(D p):) - ----------- -import std.stdio; - -class Foo -{ - int x; -} - -int main() -{ - Foo p = new Foo; // the fix - bar(p); -} - -void bar(Foo p) -{ - abc(p); -} - -void abc(Foo p) -{ - p.x++; -} ---------- - -$(P and it should now compile and run without error.) +$(P Debuggers without these extensions will interpret your code as C/C++. Most debug information maps naturally +to C data structures, but the respective syntax has to be used, e.g. `->` must be used instead of `.` to display +a class member in a watch expression. ) +$(P When compiling the program with dmd without specifying an architecture (i.e. using the default -m32), the +Digital Mars linker optlink.exe is used to produce the executable. The debug information format used is an +ancient version of CodeView that is only partially supported by more recent debuggers. You can use +$(LINK2 https://github.com/rainers/cv2pdb, cv2pdb) +to convert the debug information to the ubiquitous PDB format. ) Macros: - TITLE=windbg Debugger - WIKI=Windbg - CATEGORY_DOWNLOAD=$0 - + TITLE=Debugging D on Windows + _= diff --git a/windows.dd b/windows.dd deleted file mode 100644 index c0f80584ea..0000000000 --- a/windows.dd +++ /dev/null @@ -1,148 +0,0 @@ -Ddoc - -$(D_S D for Win32, - - $(P This describes the D implementation for 32 bit Windows systems. - Naturally, - Windows specific D features are not portable to other platforms. - ) - - $(P Instead of the:) - -$(CCODE -#include <windows.h> -) - $(P of C, in D there is:) - --------------------- -import std.c.windows.windows; --------------------- - - -

    Calling Conventions

    - - $(P In C, the Windows API calling conventions are $(CODE __stdcall). - In D, it is simply: - ) - --------------------- -extern (Windows) -{ - /* ... function declarations ... */ -} --------------------- - - - $(P The Windows linkage attribute sets both the calling convention - and the name mangling scheme to be compatible with Windows. - ) - - $(P For functions that in C would be $(CODE __declspec(dllimport)) or - $(CODE __declspec(dllexport)), use the $(CODE export) attribute: - ) - --------------------- -export void func(int foo); --------------------- - - $(P If no function body is given, it's imported. If a function body - is given, it's exported. - ) - -

    Windows Executables

    - - $(P Windows GUI applications can be written with D. - A sample such can be found in $(D $(DMDDIR)\samples\d\winsamp.d) - ) - - $(P These are required:) - - $(OL - - $(LI Instead of a $(CODE main) function serving as the entry point, - a $(CODE WinMain) function is needed. - ) - - $(LI $(CODE WinMain) must follow this form: --------------------- -import core.runtime; -import std.c.windows.windows; -import std.string; - -extern (Windows) -int WinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPSTR lpCmdLine, - int nCmdShow) -{ - int result; - - void exceptionHandler(Throwable e) { - throw e; - } - - try { - Runtime.initialize(&exceptionHandler); - result = myWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); - Runtime.terminate(&exceptionHandler); - } - - catch (Throwable e) { // catch any uncaught exceptions - MessageBoxA(null, e.toString().toStringz, "Error", - MB_OK | MB_ICONEXCLAMATION); - result = 0; // failed - } - - return result; -} - -int myWinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPSTR lpCmdLine, - int nCmdShow) -{ - // ... insert user code here ... - return 0; -} --------------------- - - The $(D myWinMain()) function is where the user code goes, the - rest of $(D WinMain) is boilerplate to initialize and shut down - the D runtime system. - ) - - $(LI A $(CODE .def) - ($(LINK2 http://www.digitalmars.com/ctg/ctgDefFiles.html, Module Definition File)) - with at least the following - two lines in it: - -$(MODDEFFILE -EXETYPE NT -SUBSYSTEM WINDOWS -) - - Without those, Win32 will open a text console window whenever - the application is run. - ) - - $(LI The presence of $(D WinMain()) is recognized by the compiler - causing it to emit a reference to - $(LINK2 http://www.digitalmars.com/ctg/acrtused.html, __acrtused_dll) - and the phobos.lib runtime library. - ) - - ) - -

    Windows Programming Examples

    - -A collection of over 140 Windows D programming code examples is available at -$(LINK2 https://github.com/AndrejMitrovic/DWindowsProgramming, this Github repository.) - -) - - - -Macros: - TITLE=Windows - WIKI=Windows - CATEGORY_HOWTOS=$0 diff --git a/windows.ddoc b/windows.ddoc index b86a293a60..252e450952 100644 --- a/windows.ddoc +++ b/windows.ddoc @@ -3,8 +3,11 @@ OS=windows WINDOWS=$0 LINUX= FREEBSD= +OSX= +UNIX= SEP=\ OBJEXT=obj LIBEXT=lib +BINEXT=.exe DMDDIR=\dmd2 -FOO= +_=