diff --git a/DISTRIBUTING.md b/DISTRIBUTING.md index dbbb6fc57c765..9322f2db23fcf 100644 --- a/DISTRIBUTING.md +++ b/DISTRIBUTING.md @@ -10,7 +10,7 @@ order to create a portable, working Julia distribution, we have separated most of the notes by OS. Note that while the code for Julia is -[MIT-licensed](https://github.com/JuliaLang/julia/blob/master/LICENSE.md), +[MIT-licensed, with a few exceptions](https://github.com/JuliaLang/julia/blob/master/LICENSE.md), the distribution created by the techniques described herein will be GPL licensed, as various dependent libraries such as `FFTW`, `Rmath`, `SuiteSparse`, and `git` are GPL licensed. We do hope to have a @@ -26,7 +26,7 @@ pregenerate the `base/version_git.jl` file with: make -C base version_git.jl.phony -Juila has lots of build dependencies where we use patched versions that has not +Julia has lots of build dependencies where we use patched versions that has not yet been included by the popular package managers. These dependencies will usually be automatically downloaded when you build, but if you want to be able to build Julia on a computer without internet access you should create a source-dist archive @@ -43,6 +43,25 @@ to create a Make.user file containing: override TAGGED_RELEASE_BANNER = "my-package-repository build" +Target Architectures +-------------------- + +By default, Julia optimizes its system image to the native architecture of +the build machine. This is usually not what you want when building packages, +as it will make Julia fail at startup on any machine with incompatible CPUs +(in particular older ones with more restricted instruction sets). + +We therefore recommend that you pass the `MARCH` variable when calling `make`, +setting it to the baseline target you intend to support. This will determine +the target CPU for both the Julia executable and libraries, and the system +image (the latter can also be set using `JULIA_CPU_TARGET`). Typically useful +values for x86 CPUs are `x86-64` and `core2` (for 64-bit builds) and +`pentium4` (for 32-bit builds). Unfortunately, CPUs older than Pentium 4 +are currently not supported (see +[this issue](https://github.com/JuliaLang/julia/issues/7185)). + +The full list of CPU targets supported by LLVM can be obtained by running +`llc -mattr=help`. Linux ----- @@ -52,10 +71,17 @@ installation. If you wish to create a distribution package such as a `.deb`, or `.rpm`, some extra effort is needed. See the [julia-debian](http://github.com/staticfloat/julia-debian) repository for an example of what metadata is needed for creating `.deb` packages -for Debian and Ubuntu-based systems. Although we have not yet experimented +for Debian and Ubuntu-based systems. See the +[Fedora package](https://admin.fedoraproject.org/pkgdb/package/julia/) +for RPM-based distributions. Although we have not yet experimented with it, [Alien](https://wiki.debian.org/Alien) could be used to generate Julia packages for various Linux distributions. +Julia supports overriding standard installation directories via `prefix` +and other environment variables you can pass when calling `make` and +`make install`. See Make.inc for their list. `DESTDIR` can also be used +to force the installation into a temporary directory. + By default, Julia loads `$prefix/etc/julia/juliarc.jl` as an installation-wide initialization file. This file can be used by distribution managers to provide paths to various binaries such as a @@ -102,8 +128,8 @@ Notes on BLAS and LAPACK Julia builds OpenBLAS by default, which includes the BLAS and LAPACK libraries. On 32-bit architectures, Julia builds OpenBLAS to use 32-bit integers, while on 64-bit architectuers, Julia builds OpenBLAS -to use 64-bit integers. It is essential that all Julia functions that -call BLAS and LAPACK API routines use integers of the correct width. +to use 64-bit integers (ILP64). It is essential that all Julia functions +that call BLAS and LAPACK API routines use integers of the correct width. Most BLAS and LAPACK distributions provided on linux distributions, and even commercial implementations ship libraries that use 32-bit @@ -120,6 +146,22 @@ all libraries that depend on BLAS and LAPACK. The Julia build process will build all these libraries correctly, but when overriding defaults and using system provided libraries, this consistency must be ensured. +Also note that Linux distributions sometimes ship several versions of +OpenBLAS, some of which enable multithreading, and others only working +in a serial fashion. For example, in Fedora, `libopenblasp.so` is threaded, +but `libopenblas.so` is not. We recommend using the former for optimal +performance. To choose an OpenBLAS library whose name is different from +the default `libopenblas.so`, pass `LIBBLAS=-l$(YOURBLAS)` and +`LIBBLASNAME=lib$(YOURBLAS)` to `make`, replacing `$(YOURBLAS)` with the +name of your library. You can also add `.so.0` to the name of the library +if you want your package to work without requiring the unversioned `.so` +symlink. + +Finally, OpenBLAS includes its own optimized version of LAPACK. If you +set `USE_SYSTEM_BLAS=1` and `USE_SYSTEM_LAPACK=1`, you should also set +`LIBLAPACK=-l$(YOURBLAS)` and `LIBLAPACKNAME=lib$(YOURBLAS)`. Else, the +reference LAPACK will be used and performance will typically be much lower. + Notes on Rmath ============== @@ -136,7 +178,8 @@ used. Compilation scripts =================== -The [julia-nightly-packaging](https://github.com/staticfloat/julia-nightly-packaging) repository contains multiple example scripts to ease the creation of +The [julia-nightly-packaging](https://github.com/staticfloat/julia-nightly-packaging) +repository contains multiple example scripts to ease the creation of binary packages. It also includes miscellaneous tools to do things such as fetching the last good commit that passed the [Travis](https://travis-ci.org/JuliaLang/julia/builds) tests. diff --git a/Make.inc b/Make.inc index 600b4f24639c8..60a9be3938c68 100644 --- a/Make.inc +++ b/Make.inc @@ -294,7 +294,7 @@ CXX = icpc JCFLAGS = -std=gnu99 -pipe $(fPIC) -fno-strict-aliasing -D_FILE_OFFSET_BITS=64 -fp-model precise -fp-model except -no-ftz JCPPFLAGS = JCXXFLAGS = -pipe $(fPIC) -fno-rtti -DEBUGFLAGS = -O0 -ggdb3 -DJL_DEBUG_BUILD -fstack-protector-all +DEBUGFLAGS = -O0 -g -DJL_DEBUG_BUILD -fstack-protector-all SHIPFLAGS = -O3 -g -falign-functions endif diff --git a/Makefile b/Makefile index 9d5da7f18db27..9b03c1e54d5ae 100644 --- a/Makefile +++ b/Makefile @@ -256,6 +256,13 @@ endif -rm -f $(DESTDIR)$(datarootdir)/julia/doc/juliadoc/.gitignore # Copy in beautiful new man page! $(INSTALL_F) $(build_datarootdir)/man/man1/julia.1 $(DESTDIR)$(datarootdir)/man/man1/ + # Copy icon and .desktop file + mkdir -p $(DESTDIR)$(datarootdir)/icons/hicolor/scalable/apps/ + $(INSTALL_F) contrib/julia.svg $(DESTDIR)$(datarootdir)/icons/hicolor/scalable/apps/ + -touch --no-create $(DESTDIR)$(datarootdir)/icons/hicolor/ + -gtk-update-icon-cache $(DESTDIR)$(datarootdir)/icons/hicolor/ + mkdir -p $(DESTDIR)$(datarootdir)/applications/ + $(INSTALL_F) contrib/julia.desktop $(DESTDIR)$(datarootdir)/applications/ # Update RPATH entries of Julia if $(private_libdir_rel) != $(build_private_libdir_rel) ifneq ($(private_libdir_rel),$(build_private_libdir_rel)) diff --git a/README.md b/README.md index ccec6c8f3a39b..3176dd0533c66 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Once it is built, you can run the `julia` executable using its full path in the - add a soft link to the `julia` executable in the `julia` directory to `/usr/local/bin` (or any suitable directory already in your path), or -- add the `julia` directory to your executable path for this shell session (in bash: `export PATH="$(pwd):$PATH"` ; in csh or tcsh: +- add the `julia` directory to your executable path for this shell session (in `bash`: `export PATH="$(pwd):$PATH"` ; in `csh` or `tcsh`: `set path= ( $path $cwd )` ), or - add the `julia` directory to your executable path permanently (e.g. in `.bash_profile`), or @@ -91,7 +91,7 @@ If everything works correctly, you will see a Julia banner and an interactive pr Your first test of Julia should be to determine whether your build is working properly. From the UNIX/Windows command prompt inside -the julia source directory, type `make testall`. You should see output +the `julia` source directory, type `make testall`. You should see output that lists a series of tests being run; if they complete without error, you should be in good shape to start using Julia. @@ -101,6 +101,57 @@ If you are building a Julia package for distribution on Linux, OS X, or Windows, take a look at the detailed notes in [DISTRIBUTING.md](https://github.com/JuliaLang/julia/blob/master/DISTRIBUTING.md). +### Updating an existing source tree + +If you have previously downloaded `julia` using `git clone`, you can update the +existing source tree using `git pull` rather than starting anew: + + cd julia + git pull && make + +Assuming that you had made no changes to the source tree that will conflict +with upstream updates, these commands will trigger a build to update to the +latest version. + +#### General troubleshooting + +1. Over time, the base library may accumulate enough changes such that the + bootstrapping process in building the system image will fail. If this + happens, the build may fail with an error like + + ```sh + *** This error is usually fixed by running 'make clean'. If the error persists, try 'make cleanall' *** + ``` + + As described, running `make clean && make` is usually sufficient. + Occasionally, the stronger cleanup done by `make cleanall` is needed. + +2. New versions of external dependencies may be introduced which may + occasionally cause conflicts with existing builds of older versions. + + a. Special `make` targets exist to help wipe the existing build of a + dependency. For example, `make -C deps clean-llvm` will clean out the + existing build of `llvm` so that `llvm` will be rebuilt from the + downloaded source distribution the next time `make` is called. + `make -C deps distclean-llvm` is a stronger wipe which will also delete + the downloaded source distribution, ensuring that a fresh copy of the + source distribution will be downloaded and that any new patches will be + applied the next time `make` is called. + + b. To delete existing binaries of `julia` and all its dependencies, + delete the `./usr` directory _in the source tree_. + +3. In extreme cases, you may wish to reset the source tree to a pristine state. + The following git commands may be helpful: + + ```sh + git reset --hard #Forcibly remove any changes to any files under version control + git clean -x -f -d #Forcibly remove any file or directory not under version control + ``` + + _To avoid losing work, make sure you know what these commands do before you + run them. `git` will not be able to undo these changes!_ + ## Uninstalling Julia @@ -122,7 +173,7 @@ Julia does not install anything outside the directory it was cloned into. Julia Julia can be built for a non-generic architecture by configuring the `ARCH` Makefile variable. See the appropriate section of `Make.inc` for additional customization options, such as `MARCH` and `JULIA_CPU_TARGET`. -For example, to build for i486, set `ARCH=i486` and install the necessary system libraries for linking. On Ubuntu, these may include lib32gfortran3 (also manually call `ln -s /usr/lib32/libgfortran3.so.0 /usr/lib32/libgfortran3.so`) and lib32gcc1, lib32stdc++6, among others. +For example, to build for Pentium 4, set `MARCH=pentium4` and install the necessary system libraries for linking. On Ubuntu, these may include lib32gfortran3 (also manually call `ln -s /usr/lib32/libgfortran3.so.0 /usr/lib32/libgfortran3.so`) and lib32gcc1, lib32stdc++6, among others. You can also set `MARCH=native` for a maximum-performance build customized for the current machine CPU. @@ -265,12 +316,15 @@ SuiteSparse is a special case, since it is typically only installed as a static ### Intel compilers and Math Kernel Libraries -To use the Intel [MKL] BLAS and LAPACK libraries, make sure that MKL version 10.3.6 or higher is installed. For a 64-bit architecture, the MKL environment should be set up as follows: +To use the Intel [MKL] BLAS and LAPACK libraries, make sure that MKL version 10.3.6 or higher is installed. +For a 64-bit architecture, the environment should be set up as follows: + # bash source /path/to/mkl/bin/mklvars.sh intel64 ilp64 export MKL_INTERFACE_LAYER=ILP64 -Julia can be built with the Intel compilers and MKL using the following flags. +It is recommended that Intel compilers be used to build julia when using MKL. +Add the following to the `Make.user` file: USEICC = 1 USEIFC = 1 @@ -278,7 +332,7 @@ Julia can be built with the Intel compilers and MKL using the following flags. USE_INTEL_MKL_FFT = 1 USE_INTEL_LIBM = 1 -It is highly recommended to use a fresh clone of the Julia repository. Also, it is recommended that Intel compilers be used to build julia when using MKL. +It is highly recommended to start with a fresh clone of the Julia repository. ## Source Code Organization @@ -332,6 +386,14 @@ The following distributions include julia, but the versions may be out of date d ## Editor and Terminal Setup -Currently, Julia editing mode support is available for Emacs, Vim, Textmate, Sublime Text, Notepad++, and Kate, in `contrib/`. There is early support for IDEs such as [Lighttable](https://github.com/one-more-minute/Jewel), [QTCreator based JuliaStudio](http://forio.com/labs/julia-studio/), and [Eclipse (LiClipse)](http://brainwy.github.io/liclipse/). A notebook interface is available through [IJulia](https://github.com/JuliaLang/IJulia.jl), which adds Julia support to the iPython notebook. - -In the terminal, Julia makes great use of both control-key and meta-key bindings. To make the meta-key bindings more accessible, many terminal emulator programs (e.g., `Terminal`, `iTerm`, `xterm`, etc) allow you to use the alt or option key as meta. See the section in the manual on [interacting with Julia](http://docs.julialang.org/en/latest/manual/interacting-with-julia/) for more details. +Currently, Julia editing mode support is available for Emacs, Vim, Textmate, +Sublime Text, Notepad++, and Kate, in `contrib/`. There is early support for +IDEs such as [Light Table](https://github.com/one-more-minute/Julia-LT), +[QTCreator based Julia Studio](http://forio.com/labs/julia-studio), and +[Eclipse (LiClipse)](http://brainwy.github.io/liclipse/). A notebook interface +is available through [IJulia](https://github.com/JuliaLang/IJulia.jl), which +adds Julia support to [IPython](http://ipython.org). The +[Sublime-IJulia](https://github.com/quinnj/Sublime-IJulia) plugin enables +interaction between IJulia and Sublime Text. + +In the terminal, Julia makes great use of both control-key and meta-key bindings. To make the meta-key bindings more accessible, many terminal emulator programs (e.g., `Terminal`, `iTerm`, `xterm`, etc.) allow you to use the alt or option key as meta. See the section in the manual on [interacting with Julia](http://docs.julialang.org/en/latest/manual/interacting-with-julia/) for more details. diff --git a/base/LineEdit.jl b/base/LineEdit.jl index be777b487e24e..8b3ae98afcb0a 100644 --- a/base/LineEdit.jl +++ b/base/LineEdit.jl @@ -9,7 +9,7 @@ import Base: ensureroom, peek, show abstract TextInterface -export run_interface, Prompt, ModalInterface, transition, reset_state, edit_insert +export run_interface, Prompt, ModalInterface, transition, reset_state, edit_insert, keymap immutable ModalInterface <: TextInterface modes @@ -82,7 +82,7 @@ end reset_state(::EmptyHistoryProvider) = nothing -complete_line(c::EmptyCompletionProvider, s) = [] +complete_line(c::EmptyCompletionProvider, s) = [], true, true terminal(s::IO) = s terminal(s::PromptState) = s.terminal @@ -684,90 +684,67 @@ function normalize_key(key::String) return takebuf_string(buf) end +function normalize_keys(keymap::Dict) + return [normalize_key(k) => v for (k,v) in keymap] +end + +function add_nested_key!(keymap::Dict, key, value) + i = start(key) + while !done(key, i) + c, i = next(key, i) + if c in keys(keymap) + if !isa(keymap[c], Dict) + error("Conflicting Definitions for keyseq " * escape_string(key) * " within one keymap") + end + elseif done(key, i) + keymap[c] = value + break + else + keymap[c] = Dict{Char,Any}() + end + keymap = keymap[c] + end +end + # Turn a Dict{Any,Any} into a Dict{Char,Any} # For now we use \0 to represent unknown chars so that they are sorted before everything else # If we ever actually want to match \0 in input, this will have to be reworked function normalize_keymap(keymap::Dict) ret = Dict{Char,Any}() - for key in keys(keymap) - newkey = normalize_key(key) - current = ret - i = start(newkey) - while !done(newkey, i) - c, i = next(newkey, i) - if haskey(current, c) - if !isa(current[c], Dict) - println(ret) - error("Conflicting Definitions for keyseq " * escape_string(newkey) * " within one keymap") - end - elseif done(newkey, i) - if isa(keymap[key], String) - current[c] = normalize_key(keymap[key]) - else - current[c] = keymap[key] - end - break - else - current[c] = Dict{Char,Any}() - end - current = current[c] - end + direct_keys = filter((k,v) -> isa(v, Union(Function, Void)), keymap) + # first direct entries + for key in keys(direct_keys) + add_nested_key!(ret, key, keymap[key]) + end + # then redirected entries + for key in setdiff(keys(keymap), keys(direct_keys)) + value = normalize_key(keymap[key]) + haskey(keymap, value) || error("Could not find redirected value " * escape_string(keymap[key])) + add_nested_key!(ret, key, keymap[value]) end ret end -keymap_gen_body(keymaps, body::Expr, level) = body -keymap_gen_body(keymaps, body::Function, level) = keymap_gen_body(keymaps, :($(body)(s))) -keymap_gen_body(keymaps, body::Char, level) = keymap_gen_body(keymaps, keymaps[body]) -keymap_gen_body(keymaps, body::Nothing, level) = nothing -function keymap_gen_body(keymaps, body::String, level) - if length(body) == 1 - return keymap_gen_body(keymaps, body[1], level) - end - current = keymaps - for c in body - if haskey(current, c) - if isa(current[c], Dict) - current = current[c] - else - return keymap_gen_body(keymaps, current[c], level) - end - elseif haskey(current, '\0') - return keymap_gen_body(keymaps, current['\0'], level) +match_input(k::Function, s, cs) = (update_key_repeats(s, cs); return keymap_fcn(k, s, last(cs))) +match_input(k::Void, s, cs) = (s,p) -> return :ok +function match_input(keymap::Dict, s, cs=Char[]) + c = read(terminal(s), Char) + push!(cs, c) + k = haskey(keymap, c) ? c : '\0' + # if we don't match on the key, look for a default action then fallback on 'nothing' to ignore + return match_input(get(keymap, k, nothing), s, cs) +end + +keymap_fcn(f::Void, s, c) = (s, p) -> return :ok +function keymap_fcn(f::Function, s, c::Char) + return (s, p) -> begin + r = f(s, p, c) + if isa(r, Symbol) + return r else - error("No match for redirected key $body") - end - end - error("No exact match for redirected key $body") -end - -keymap_gen_body(a, b) = keymap_gen_body(a, b, 1) -function keymap_gen_body(dict, subdict::Dict, level) - block = Expr(:block) - bc = symbol("c" * string(level)) - push!(block.args, :($bc = read(LineEdit.terminal(s), Char))) - - last_if = Expr(:block) - haskey(subdict, '\0') && push!(last_if.args, keymap_gen_body(dict, subdict['\0'], level+1)) - level == 1 && push!(last_if.args, :(LineEdit.update_key_repeats(s, [$bc]))) - - for c in keys(subdict) - c == '\0' && continue - cblock = Expr(:if, :($bc == $c)) - cthen = Expr(:block) - if !isa(subdict[c], Dict) - cs = [symbol("c" * string(i)) for i=1:level] - push!(cthen.args, :(LineEdit.update_key_repeats(s, [$(cs...)]))) + return :ok end - push!(cthen.args, keymap_gen_body(dict, subdict[c], level+1)) - - push!(cblock.args, cthen) - push!(cblock.args, last_if) - last_if = cblock end - - push!(block.args, last_if) - return block end update_key_repeats(s, keystroke) = nothing @@ -777,8 +754,6 @@ function update_key_repeats(s::MIState, keystroke) return end -export @keymap - # deep merge where target has higher precedence function keymap_merge!(target::Dict, source::Dict) for k in keys(source) @@ -795,8 +770,8 @@ end fixup_keymaps!(d, l, s, sk) = nothing function fixup_keymaps!(dict::Dict, level, s, subkeymap) if level > 1 - for d in dict - fixup_keymaps!(d[2], level-1, s, subkeymap) + for d in values(dict) + fixup_keymaps!(d, level-1, s, subkeymap) end else if haskey(dict, s) @@ -826,19 +801,19 @@ function fix_conflicts!(dict::Dict, level) if haskey(dict, '\0') add_specialisations(dict, dict, level) end - for d in dict - d[1] == '\0' && continue - fix_conflicts!(d[2], level+1) + for (k,v) in dict + k == '\0' && continue + fix_conflicts!(v, level+1) end end -keymap_prepare(keymaps::Expr) = keymap_prepare(eval(keymaps)) -keymap_prepare(keymaps::Dict) = keymap_prepare([keymaps]) -function keymap_prepare{D<:Dict}(keymaps::Array{D}) - push!(keymaps, {"*"=>:(error("Unrecognized input"))}) - keymaps = map(normalize_keymap, keymaps) - map(fix_conflicts!, keymaps) - keymaps +function keymap_prepare(keymap::Dict) + if !haskey(keymap, "\0") + keymap["\0"] = (o...)->error("Unrecognized input") + end + keymap = normalize_keymap(keymap) + fix_conflicts!(keymap) + keymap end function keymap_unify(keymaps) @@ -851,19 +826,15 @@ function keymap_unify(keymaps) return ret end -macro keymap(keymaps) - dict = keymap_unify(keymap_prepare(keymaps)) - body = keymap_gen_body(dict, dict) - esc(quote - (s, data) -> begin - $body - return :ok - end - end) +function keymap{D<:Dict}(keymaps::Array{D}) + # keymaps is a vector of prioritized keymaps, with highest priority first + dict = map(normalize_keys, keymaps) + dict = keymap_prepare(merge(reverse(dict)...)) + return (s,p)->match_input(dict, s)(s,p) end const escape_defaults = merge!( - {i => nothing for i=1:31}, # Ignore control characters by default + {char(i) => nothing for i=[1:26, 28:31]}, # Ignore control characters by default { # And ignore other escape sequences by default "\e*" => nothing, "\e[*" => nothing, @@ -1027,88 +998,81 @@ end function setup_search_keymap(hp) p = HistoryPrompt(hp) pkeymap = { - "^R" => :(LineEdit.history_set_backward(data, true); LineEdit.history_next_result(s, data)), - "^S" => :(LineEdit.history_set_backward(data, false); LineEdit.history_next_result(s, data)), - '\r' => s->accept_result(s, p), + "^R" => (s,data,c)->(history_set_backward(data, true); history_next_result(s, data)), + "^S" => (s,data,c)->(history_set_backward(data, false); history_next_result(s, data)), + '\r' => (s,o...)->accept_result(s, p), '\n' => '\r', # Limited form of tab completions - '\t' => :(LineEdit.complete_line(s); LineEdit.update_display_buffer(s, data)), - "^L" => :(Terminals.clear(LineEdit.terminal(s)); LineEdit.update_display_buffer(s, data)), + '\t' => (s,data,c)->(complete_line(s); update_display_buffer(s, data)), + "^L" => (s,data,c)->(Terminals.clear(terminal(s)); update_display_buffer(s, data)), # Backspace/^H - '\b' => :(LineEdit.edit_backspace(data.query_buffer) ? - LineEdit.update_display_buffer(s, data) : beep(LineEdit.terminal(s))), + '\b' => (s,data,c)->(edit_backspace(data.query_buffer) ? + update_display_buffer(s, data) : beep(terminal(s))), 127 => '\b', # Meta Backspace - "\e\b" => :(LineEdit.edit_delete_prev_word(data.query_buffer) ? - LineEdit.update_display_buffer(s, data) : beep(LineEdit.terminal(s))), + "\e\b" => (s,data,c)->(edit_delete_prev_word(data.query_buffer) ? + update_display_buffer(s, data) : beep(terminal(s))), "\e\x7f" => "\e\b", # Word erase to whitespace - "^W" => :(LineEdit.edit_werase(data.query_buffer) ? - LineEdit.update_display_buffer(s, data) : beep(LineEdit.terminal(s))), + "^W" => (s,data,c)->(edit_werase(data.query_buffer) ? + update_display_buffer(s, data) : beep(terminal(s))), # ^C and ^D - "^C" => :(LineEdit.edit_clear(data.query_buffer); - LineEdit.edit_clear(data.response_buffer); - LineEdit.update_display_buffer(s, data); - LineEdit.reset_state(data.histprompt.hp); - LineEdit.transition(s, data.parent)), + "^C" => (s,data,c)->(edit_clear(data.query_buffer); + edit_clear(data.response_buffer); + update_display_buffer(s, data); + reset_state(data.histprompt.hp); + transition(s, data.parent)), "^D" => "^C", # Other ways to cancel search mode (it's difficult to bind \e itself) "^G" => "^C", "\e\e" => "^C", - # ^K - 11 => s->transition(s, state(s, p).parent), - # ^Y - 25 => :(LineEdit.edit_yank(s); LineEdit.update_display_buffer(s, data)), - # ^U - 21 => :(LineEdit.edit_clear(data.query_buffer); - LineEdit.edit_clear(data.response_buffer); - LineEdit.update_display_buffer(s, data)), + "^K" => (s,o...)->transition(s, state(s, p).parent), + "^Y" => (s,data,c)->(edit_yank(s); update_display_buffer(s, data)), + "^U" => (s,data,c)->(edit_clear(data.query_buffer); + edit_clear(data.response_buffer); + update_display_buffer(s, data)), # Right Arrow - "\e[C" => s->(accept_result(s, p); edit_move_right(s)), + "\e[C" => (s,o...)->(accept_result(s, p); edit_move_right(s)), # Left Arrow - "\e[D" => s->(accept_result(s, p); edit_move_left(s)), + "\e[D" => (s,o...)->(accept_result(s, p); edit_move_left(s)), # Up Arrow - "\e[A" => s->(accept_result(s, p); edit_move_up(s)), + "\e[A" => (s,o...)->(accept_result(s, p); edit_move_up(s)), # Down Arrow - "\e[B" => s->(accept_result(s, p); edit_move_down(s)), - # ^B - 2 => s->(accept_result(s, p); edit_move_left(s)), - # ^F - 6 => s->(accept_result(s, p); edit_move_right(s)), + "\e[B" => (s,o...)->(accept_result(s, p); edit_move_down(s)), + "^B" => (s,o...)->(accept_result(s, p); edit_move_left(s)), + "^F" => (s,o...)->(accept_result(s, p); edit_move_right(s)), # Meta B - "\eb" => s->(accept_result(s, p); edit_move_word_left(s)), + "\eb" => (s,o...)->(accept_result(s, p); edit_move_word_left(s)), # Meta F - "\ef" => s->(accept_result(s, p); edit_move_word_right(s)), + "\ef" => (s,o...)->(accept_result(s, p); edit_move_word_right(s)), # Ctrl-Left Arrow "\e[1;5D" => "\eb", # Ctrl-Right Arrow "\e[1;5C" => "\ef", - # ^A - 1 => s->(accept_result(s, p); move_line_start(s); refresh_line(s)), - # ^E - 5 => s->(accept_result(s, p); move_line_end(s); refresh_line(s)), - "^Z" => :(return :suspend), + "^A" => (s,o...)->(accept_result(s, p); move_line_start(s); refresh_line(s)), + "^E" => (s,o...)->(accept_result(s, p); move_line_end(s); refresh_line(s)), + "^Z" => (s,o...)->(return :suspend), # Try to catch all Home/End keys - "\e[H" => s->(accept_result(s, p); move_input_start(s); refresh_line(s)), - "\e[F" => s->(accept_result(s, p); move_input_end(s); refresh_line(s)), + "\e[H" => (s,o...)->(accept_result(s, p); move_input_start(s); refresh_line(s)), + "\e[F" => (s,o...)->(accept_result(s, p); move_input_end(s); refresh_line(s)), # Use ^N and ^P to change search directions and iterate through results - "^N" => :(LineEdit.history_set_backward(data, false); LineEdit.history_next_result(s, data)), - "^P" => :(LineEdit.history_set_backward(data, true); LineEdit.history_next_result(s, data)), + "^N" => (s,data,c)->(history_set_backward(data, false); history_next_result(s, data)), + "^P" => (s,data,c)->(history_set_backward(data, true); history_next_result(s, data)), # Bracketed paste mode - "\e[200~" => quote - ps = LineEdit.state(s, LineEdit.mode(s)) + "\e[200~" => (s,data,c)-> begin + ps = state(s, mode(s)) input = readuntil(ps.terminal, "\e[201~")[1:(end-6)] - LineEdit.edit_insert(data.query_buffer, input); LineEdit.update_display_buffer(s, data) + edit_insert(data.query_buffer, input); update_display_buffer(s, data) end, - "*" => :(LineEdit.edit_insert(data.query_buffer, c1); LineEdit.update_display_buffer(s, data)) + "*" => (s,data,c)->(edit_insert(data.query_buffer, c); update_display_buffer(s, data)) } - p.keymap_func = @eval @LineEdit.keymap $([pkeymap, escape_defaults]) - keymap = { - "^R" => s->(enter_search(s, p, true)), - "^S" => s->(enter_search(s, p, false)), + p.keymap_func = keymap([pkeymap, escape_defaults]) + skeymap = { + "^R" => (s,o...)->(enter_search(s, p, true)), + "^S" => (s,o...)->(enter_search(s, p, false)), } - (p, keymap) + (p, skeymap) end keymap(state, p::HistoryPrompt) = p.keymap_func @@ -1156,7 +1120,7 @@ end const default_keymap = { # Tab - '\t' => s->begin + '\t' => (s,o...)->begin buf = buffer(s) # Yes, we are ignoring the possiblity # the we could be in the middle of a multi-byte @@ -1178,68 +1142,58 @@ const default_keymap = refresh_line(s) end, # Enter - '\r' => quote - if LineEdit.on_enter(s) || (eof(LineEdit.buffer(s)) && s.key_repeats > 1) - LineEdit.commit_line(s) + '\r' => (s,o...)->begin + if on_enter(s) || (eof(buffer(s)) && s.key_repeats > 1) + commit_line(s) return :done else - LineEdit.edit_insert(s, '\n') + edit_insert(s, '\n') end end, '\n' => '\r', # Backspace/^H - '\b' => edit_backspace, + '\b' => (s,o...)->edit_backspace(s), 127 => '\b', # Meta Backspace - "\e\b" => edit_delete_prev_word, + "\e\b" => (s,o...)->edit_delete_prev_word(s), "\e\x7f" => "\e\b", # ^D - 4 => quote - if LineEdit.buffer(s).size > 0 - LineEdit.edit_delete(s) + "^D" => (s,o...)->begin + if buffer(s).size > 0 + edit_delete(s) else - println(LineEdit.terminal(s)) + println(terminal(s)) return :abort end end, - # ^B - 2 => edit_move_left, - # ^F - 6 => edit_move_right, + "^B" => (s,o...)->edit_move_left(s), + "^F" => (s,o...)->edit_move_right(s), # Meta B - "\eb" => edit_move_word_left, + "\eb" => (s,o...)->edit_move_word_left(s), # Meta F - "\ef" => edit_move_word_right, + "\ef" => (s,o...)->edit_move_word_right(s), # Ctrl-Left Arrow "\e[1;5D" => "\eb", # Ctrl-Right Arrow "\e[1;5C" => "\ef", # Meta Enter - "\e\r" => :(LineEdit.edit_insert(s, '\n')), + "\e\r" => (s,o...)->(edit_insert(s, '\n')), "\e\n" => "\e\r", # Simply insert it into the buffer by default - "*" => :(LineEdit.edit_insert(s, c1)), - # ^U - 21 => edit_clear, - # ^K - 11 => edit_kill_line, - # ^Y - 25 => edit_yank, - # ^A - 1 => :(LineEdit.move_line_start(s); LineEdit.refresh_line(s)), - # ^E - 5 => :(LineEdit.move_line_end(s); LineEdit.refresh_line(s)), + "*" => (s,data,c)->(edit_insert(s, c)), + "^U" => (s,o...)->edit_clear(s), + "^K" => (s,o...)->edit_kill_line(s), + "^Y" => (s,o...)->edit_yank(s), + "^A" => (s,o...)->(move_line_start(s); refresh_line(s)), + "^E" => (s,o...)->(move_line_end(s); refresh_line(s)), # Try to catch all Home/End keys - "\e[H" => :(LineEdit.move_input_start(s); LineEdit.refresh_line(s)), - "\e[F" => :(LineEdit.move_input_end(s); LineEdit.refresh_line(s)), - # ^L - 12 => :(Terminals.clear(LineEdit.terminal(s)); LineEdit.refresh_line(s)), - # ^W - 23 => edit_werase, + "\e[H" => (s,o...)->(move_input_start(s); refresh_line(s)), + "\e[F" => (s,o...)->(move_input_end(s); refresh_line(s)), + "^L" => (s,o...)->(Terminals.clear(terminal(s)); refresh_line(s)), + "^W" => (s,o...)->edit_werase(s), # Meta D - "\ed" => edit_delete_next_word, - # ^C - "^C" => s->begin + "\ed" => (s,o...)->edit_delete_next_word(s), + "^C" => (s,o...)->begin try # raise the debugger if present ccall(:jl_raise_debugger, Int, ()) end @@ -1249,19 +1203,19 @@ const default_keymap = transition(s, :reset) refresh_line(s) end, - "^Z" => :(return :suspend), + "^Z" => (s,o...)->(return :suspend), # Right Arrow - "\e[C" => edit_move_right, + "\e[C" => (s,o...)->edit_move_right(s), # Left Arrow - "\e[D" => edit_move_left, + "\e[D" => (s,o...)->edit_move_left(s), # Up Arrow - "\e[A" => edit_move_up, + "\e[A" => (s,o...)->edit_move_up(s), # Down Arrow - "\e[B" => edit_move_down, + "\e[B" => (s,o...)->edit_move_down(s), # Delete - "\e[3~" => edit_delete, + "\e[3~" => (s,o...)->edit_delete(s), # Bracketed Paste Mode - "\e[200~" => s->begin + "\e[200~" => (s,o...)->begin ps = state(s, mode(s)) input = readuntil(ps.terminal, "\e[201~")[1:(end-6)] input = replace(input, '\r', '\n') @@ -1271,25 +1225,21 @@ const default_keymap = end edit_insert(s, input) end, - "^T" => edit_transpose, + "^T" => (s,o...)->edit_transpose(s), } -function history_keymap(hist) - return { - # ^P - 16 => :(LineEdit.history_prev(s, $hist)), - # ^N - 14 => :(LineEdit.history_next(s, $hist)), - # Up Arrow - "\e[A" => :(LineEdit.edit_move_up(s) || LineEdit.history_prev(s, $hist)), - # Down Arrow - "\e[B" => :(LineEdit.edit_move_down(s) || LineEdit.history_next(s, $hist)), - # Page Up - "\e[5~" => :(LineEdit.history_prev_prefix(s, $hist)), - # Page Down - "\e[6~" => :(LineEdit.history_next_prefix(s, $hist)) - } -end +const history_keymap = { + "^P" => (s,o...)->(history_prev(s, mode(s).hist)), + "^N" => (s,o...)->(history_next(s, mode(s).hist)), + # Up Arrow + "\e[A" => (s,o...)->(edit_move_up(s) || history_prev_prefix(s, mode(s).hist)), + # Down Arrow + "\e[B" => (s,o...)->(edit_move_down(s) || history_next_prefix(s, mode(s).hist)), + # Page Up + "\e[5~" => (s,o...)->(history_prev(s, mode(s).hist)), + # Page Down + "\e[6~" => (s,o...)->(history_next(s, mode(s).hist)) +} function deactivate(p::Union(Prompt,HistoryPrompt), s::Union(SearchState,PromptState), termbuf) clear_input_area(termbuf, s) @@ -1337,7 +1287,7 @@ function reset_state(s::MIState) end end -const default_keymap_func = @LineEdit.keymap [LineEdit.default_keymap, LineEdit.escape_defaults] +const default_keymap_func = keymap([default_keymap, escape_defaults]) function Prompt(prompt; first_prompt = prompt, diff --git a/base/REPL.jl b/base/REPL.jl index 4a4f7a9085a98..5c08b7650af36 100644 --- a/base/REPL.jl +++ b/base/REPL.jl @@ -700,7 +700,7 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep end const repl_keymap = { - ';' => function (s) + ';' => function (s,o...) if isempty(s) || position(LineEdit.buffer(s)) == 0 buf = copy(LineEdit.buffer(s)) transition(s, shell_mode) @@ -710,7 +710,7 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep edit_insert(s, ';') end end, - '?' => function (s) + '?' => function (s,o...) if isempty(s) || position(LineEdit.buffer(s)) == 0 buf = copy(LineEdit.buffer(s)) transition(s, help_mode) @@ -722,7 +722,7 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep end, # Bracketed Paste Mode - "\e[200~" => s->begin + "\e[200~" => (s,o...)->begin ps = LineEdit.state(s, LineEdit.mode(s)) input = readuntil(ps.terminal, "\e[201~")[1:(end-6)] input = replace(input, '\r', '\n') @@ -772,13 +772,13 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep end, } - a = Dict{Any,Any}[hkeymap, repl_keymap, LineEdit.history_keymap(hp), LineEdit.default_keymap, LineEdit.escape_defaults] + a = Dict{Any,Any}[hkeymap, repl_keymap, LineEdit.history_keymap, LineEdit.default_keymap, LineEdit.escape_defaults] prepend!(a, extra_repl_keymap) - julia_prompt.keymap_func = @eval @LineEdit.keymap $(a) + julia_prompt.keymap_func = LineEdit.keymap(a) const mode_keymap = { - '\b' => function (s) + '\b' => function (s,o...) if isempty(s) || position(LineEdit.buffer(s)) == 0 buf = copy(LineEdit.buffer(s)) transition(s, julia_prompt) @@ -788,7 +788,7 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep LineEdit.edit_backspace(s) end end, - "^C" => function (s) + "^C" => function (s,o...) LineEdit.move_input_end(s) LineEdit.refresh_line(s) print(LineEdit.terminal(s), "^C\n\n") @@ -798,9 +798,9 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep end } - b = Dict{Any,Any}[hkeymap, mode_keymap, LineEdit.history_keymap(hp), LineEdit.default_keymap, LineEdit.escape_defaults] + b = Dict{Any,Any}[hkeymap, mode_keymap, LineEdit.history_keymap, LineEdit.default_keymap, LineEdit.escape_defaults] - shell_mode.keymap_func = help_mode.keymap_func = @eval @LineEdit.keymap $(b) + shell_mode.keymap_func = help_mode.keymap_func = LineEdit.keymap(b) ModalInterface([julia_prompt, shell_mode, help_mode,hkp]) end diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index 360dad860063d..af2d146049afd 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -24,7 +24,7 @@ function complete_symbol(sym, ffunc) mod = context_module lookup_module = true - t = None + t = Union() for name in strs[1:(end-1)] s = symbol(name) if lookup_module diff --git a/base/abstractarray.jl b/base/abstractarray.jl index fbf860299bee9..dc6f37a6ec8ab 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -200,7 +200,6 @@ function copy!(dest::AbstractArray, doffs::Integer, src::AbstractArray, soffs::I end copy(a::AbstractArray) = copy!(similar(a), a) -copy(a::AbstractArray{None}) = a # cannot be assigned into so is immutable function copy!{R,S}(B::AbstractMatrix{R}, ir_dest::Range{Int}, jr_dest::Range{Int}, A::AbstractMatrix{S}, ir_src::Range{Int}, jr_src::Range{Int}) if length(ir_dest) != length(ir_src) || length(jr_dest) != length(jr_src) @@ -502,14 +501,14 @@ get(A::AbstractArray, I::RangeVecIntList, default) = get!(similar(A, typeof(defa ## Concatenation ## -promote_eltype() = None +promote_eltype() = Bottom promote_eltype(v1, vs...) = promote_type(eltype(v1), promote_eltype(vs...)) #TODO: ERROR CHECK -cat(catdim::Integer) = Array(None, 0) +cat(catdim::Integer) = Array(Bottom, 0) -vcat() = Array(None, 0) -hcat() = Array(None, 0) +vcat() = Array(Bottom, 0) +hcat() = Array(Bottom, 0) ## cat: special cases hcat{T}(X::T...) = T[ X[j] for i=1, j=1:length(X) ] @@ -518,7 +517,7 @@ vcat{T}(X::T...) = T[ X[i] for i=1:length(X) ] vcat{T<:Number}(X::T...) = T[ X[i] for i=1:length(X) ] function vcat(X::Number...) - T = None + T = Bottom for x in X T = promote_type(T,typeof(x)) end @@ -526,7 +525,7 @@ function vcat(X::Number...) end function hcat(X::Number...) - T = None + T = Bottom for x in X T = promote_type(T,typeof(x)) end @@ -941,7 +940,7 @@ end function ipermutedims(A::AbstractArray,perm) iperm = Array(Int,length(perm)) for i = 1:length(perm) - iperm[perm[i]] = i + iperm[perm[i]] = i end return permutedims(A,iperm) end @@ -1287,7 +1286,7 @@ function promote_to!{T}(f::Callable, offs, dest::AbstractArray{T}, A::AbstractAr end function map_promote(f::Callable, A::AbstractArray) - if isempty(A); return similar(A, None); end + if isempty(A); return similar(A, Bottom); end first = f(A[1]) dest = similar(A, typeof(first)) dest[1] = first diff --git a/base/array.jl b/base/array.jl index 8fe621e97ee6e..e4adfea0efa49 100644 --- a/base/array.jl +++ b/base/array.jl @@ -450,7 +450,7 @@ const _grow_none_errmsg = "[] cannot grow. Instead, initialize the array with \"T[]\", where T is the desired element type." function push!{T}(a::Array{T,1}, item) - if is(T,None) + if is(T,Bottom) error(_grow_none_errmsg) end # convert first so we don't grow the array if the assignment won't work @@ -467,7 +467,7 @@ function push!(a::Array{Any,1}, item::ANY) end function append!{T}(a::Array{T,1}, items::AbstractVector) - if is(T,None) + if is(T,Bottom) error(_grow_none_errmsg) end n = length(items) @@ -477,7 +477,7 @@ function append!{T}(a::Array{T,1}, items::AbstractVector) end function prepend!{T}(a::Array{T,1}, items::AbstractVector) - if is(T,None) + if is(T,Bottom) error(_grow_none_errmsg) end n = length(items) @@ -518,7 +518,7 @@ function pop!(a::Vector) end function unshift!{T}(a::Array{T,1}, item) - if is(T,None) + if is(T,Bottom) error(_grow_none_errmsg) end item = convert(T, item) @@ -600,8 +600,10 @@ function splice!(a::Vector, i::Integer, ins=_default_splice) a[i] = ins[1] else _growat!(a, i, m-1) - for k = 1:m - a[i+k-1] = ins[k] + k = 1 + for x in ins + a[i+k-1] = x + k += 1 end end return v @@ -636,8 +638,10 @@ function splice!{T<:Integer}(a::Vector, r::UnitRange{T}, ins=_default_splice) end end - for k = 1:m - a[f+k-1] = ins[k] + k = 1 + for x in ins + a[f+k-1] = x + k += 1 end return v end diff --git a/base/base.jl b/base/base.jl index 05b8c2a9e20ed..d9c3f498bf1d0 100644 --- a/base/base.jl +++ b/base/base.jl @@ -10,6 +10,8 @@ const NonTupleType = Union(DataType,UnionType,TypeConstructor) typealias Callable Union(Function,DataType) +const Bottom = Union() + convert(T, x) = convert_default(T, x, convert) convert(::(), ::()) = () @@ -31,13 +33,6 @@ ptr_arg_convert(::Type{Ptr{Void}}, x) = x # conversion used by ccall cconvert(T, x) = convert(T, x) -# the following 3 definitions implement a 0.3 deprecation -cconvert{T}(::Type{Ptr{T}}, x::Array{T}) = convert(Ptr{T}, x) -cconvert(::Type{Ptr{None}}, x::Array) = convert(Ptr{None}, x) -function cconvert{T}(::Type{Ptr{T}}, x::Array) - depwarn("ccall Ptr argument types must now match exactly, or be Ptr{Void}.", :cconvert) - convert(Ptr{T}, pointer(x)) -end # use the code in ccall.cpp to safely allocate temporary pointer arrays cconvert{T}(::Type{Ptr{Ptr{T}}}, a::Array) = a # convert strings to ByteString to pass as pointers diff --git a/base/bitarray.jl b/base/bitarray.jl index 0c5dfbf6e6198..5a70c49605ca4 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -731,7 +731,7 @@ end const _default_bit_splice = BitVector(0) -function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::BitVector = _default_bit_splice) +function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::AbstractArray = _default_bit_splice) n = length(B) i_f = first(r) i_l = last(r) @@ -739,8 +739,10 @@ function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::BitVector 1 <= i_f <= n+1 || throw(BoundsError()) i_l <= n || throw(BoundsError()) + Bins = convert(BitArray, ins) + if (i_f > n) - append!(B, ins) + append!(B, Bins) return BitVector(0) end @@ -748,7 +750,7 @@ function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::BitVector Bc = B.chunks - lins = length(ins) + lins = length(Bins) ldel = length(r) new_l = length(B) + lins - ldel @@ -757,7 +759,7 @@ function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::BitVector delta_k > 0 && ccall(:jl_array_grow_end, Void, (Any, Uint), Bc, delta_k) copy_chunks!(Bc, i_f+lins, Bc, i_l+1, n-i_l) - copy_chunks!(Bc, i_f, ins.chunks, 1, lins) + copy_chunks!(Bc, i_f, Bins.chunks, 1, lins) delta_k < 0 && ccall(:jl_array_del_end, Void, (Any, Uint), Bc, -delta_k) @@ -769,7 +771,17 @@ function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::BitVector return v end -splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::AbstractVector{Bool}) = splice!(B, r, bitpack(ins)) + +function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins) + Bins = BitArray(length(ins)) + i = 1 + for x in ins + Bins[i] = bool(x) + i += 1 + end + return splice!(B, r, Bins) +end + function empty!(B::BitVector) ccall(:jl_array_del_end, Void, (Any, Uint), B.chunks, length(B.chunks)) diff --git a/base/boot.jl b/base/boot.jl index e34d15354e379..0503e5ec50055 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -32,8 +32,6 @@ # types::Tuple #end -#None = Union() - #type TypeVar # name::Symbol # lb::Type @@ -45,6 +43,10 @@ # body #end +#immutable Void +#end +#const nothing = Void() + #abstract AbstractArray{T,N} #abstract DenseArray{T,N} <: AbstractArray{T,N} @@ -115,12 +117,12 @@ import Core.Intrinsics.ccall export # key types - Any, DataType, Vararg, ANY, NTuple, None, Top, + Any, DataType, Vararg, ANY, NTuple, Top, Tuple, Type, TypeConstructor, TypeName, TypeVar, Union, UnionType, Void, AbstractArray, DenseArray, # special objects Box, Function, IntrinsicFunction, LambdaStaticData, Method, MethodTable, - Module, Nothing, Symbol, Task, Array, + Module, Symbol, Task, Array, # numeric types Bool, FloatingPoint, Float16, Float32, Float64, Number, Integer, Int, Int8, Int16, Int32, Int64, Int128, Ptr, Real, Signed, Uint, Uint8, Uint16, Uint32, @@ -164,9 +166,6 @@ export #ule_int, ult_int, unbox, urem_int, xor_int, sext_int, zext_int -immutable Nothing; end -const nothing = Nothing() - const (===) = is abstract Number diff --git a/base/c.jl b/base/c.jl index fee4a98d61a28..c07e3526340a5 100644 --- a/base/c.jl +++ b/base/c.jl @@ -67,8 +67,6 @@ typealias Clonglong Int64 typealias Culonglong Uint64 typealias Cfloat Float32 typealias Cdouble Float64 -#typealias Ccomplex_float Complex64 -#typealias Ccomplex_double Complex128 const sizeof_off_t = ccall(:jl_sizeof_off_t, Cint, ()) diff --git a/base/cartesian.jl b/base/cartesian.jl index 9fd9abd0ef382..b376365678387 100644 --- a/base/cartesian.jl +++ b/base/cartesian.jl @@ -30,6 +30,9 @@ const CARTESIAN_DIMS = 4 # myfunction(A::AbstractArray, I::Int...N) # where N can be an integer or symbol. Currently T...N generates a parser error. macro ngenerate(itersym, returntypeexpr, funcexpr) + if isa(funcexpr, Expr) && funcexpr.head == :macrocall && funcexpr.args[1] == symbol("@inline") + funcexpr = Base._inline(funcexpr.args[2]) + end isfuncexpr(funcexpr) || error("Requires a function expression") esc(ngenerate(itersym, returntypeexpr, funcexpr.args[1], N->sreplace!(copy(funcexpr.args[2]), itersym, N))) end @@ -57,6 +60,9 @@ macro nsplat(itersym, args...) else error("Wrong number of arguments") end + if isa(funcexpr, Expr) && funcexpr.head == :macrocall && funcexpr.args[1] == symbol("@inline") + funcexpr = Base._inline(funcexpr.args[2]) + end isfuncexpr(funcexpr) || error("Second argument must be a function expression") prototype = funcexpr.args[1] body = funcexpr.args[2] @@ -146,7 +152,7 @@ function get_splatinfo(ex::Expr, itersym::Symbol) end end end - "", Nothing + "", Void end # Replace splatted with desplatted for a specific number of arguments @@ -443,14 +449,37 @@ function poplinenum(ex::Expr) ex end +## Resolve expressions at parsing time ## + +const exprresolve_arith_dict = (Symbol=>Function)[:+ => +, + :- => -, :* => *, :/ => /, :^ => ^, :div => div] +const exprresolve_cond_dict = (Symbol=>Function)[:(==) => ==, + :(<) => <, :(>) => >, :(<=) => <=, :(>=) => >=] + +function exprresolve_arith(ex::Expr) + if ex.head == :call && haskey(exprresolve_arith_dict, ex.args[1]) && all([isa(ex.args[i], Number) for i = 2:length(ex.args)]) + return true, exprresolve_arith_dict[ex.args[1]](ex.args[2:end]...) + end + false, 0 +end + +exprresolve_conditional(b::Bool) = true, b +function exprresolve_conditional(ex::Expr) + if ex.head == :comparison && isa(ex.args[1], Number) && isa(ex.args[3], Number) + return true, exprresolve_cond_dict[ex.args[2]](ex.args[1], ex.args[3]) + end + false, false +end + exprresolve(arg) = arg function exprresolve(ex::Expr) for i = 1:length(ex.args) ex.args[i] = exprresolve(ex.args[i]) end # Handle simple arithmetic - if ex.head == :call && in(ex.args[1], (:+, :-, :*, :/)) && all([isa(ex.args[i], Number) for i = 2:length(ex.args)]) - return eval(ex) + can_eval, result = exprresolve_arith(ex) + if can_eval + return result elseif ex.head == :call && (ex.args[1] == :+ || ex.args[1] == :-) && length(ex.args) == 3 && ex.args[3] == 0 # simplify x+0 and x-0 return ex.args[2] @@ -466,10 +495,9 @@ function exprresolve(ex::Expr) end # Resolve conditionals if ex.head == :if - try - tf = eval(ex.args[1]) + can_eval, tf = exprresolve_conditional(ex.args[1]) + if can_eval ex = tf?ex.args[2]:ex.args[3] - catch end end ex diff --git a/base/combinatorics.jl b/base/combinatorics.jl index 146a46c151349..dba483b35393e 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -115,7 +115,7 @@ shuffle(a::AbstractVector) = shuffle!(copy(a)) function randperm(n::Integer) a = Array(typeof(n), n) a[1] = 1 - for i = 2:n + @inbounds for i = 2:n j = rand(1:i) a[i] = a[j] a[j] = i @@ -126,7 +126,7 @@ end function randcycle(n::Integer) a = Array(typeof(n), n) a[1] = 1 - for i = 2:n + @inbounds for i = 2:n j = rand(1:i-1) a[i] = a[j] a[j] = i diff --git a/base/complex.jl b/base/complex.jl index 1253a721814d7..50957e4d5fc56 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -61,7 +61,7 @@ end function complex_show(io::IO, z::Complex, compact::Bool) r, i = reim(z) compact ? showcompact(io,r) : show(io,r) - if signbit(i)==1 && !isnan(i) + if signbit(i) && !isnan(i) i = -i print(io, compact ? "-" : " - ") else diff --git a/base/deprecated.jl b/base/deprecated.jl index 357b6dbe3737c..466e270d5b389 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -38,7 +38,7 @@ function depwarn(msg, funcsym) warn(msg, once=(caller!=C_NULL), key=caller, bt=bt) end -function firstcaller(bt::Array{Ptr{None},1}, funcsym::Symbol) +function firstcaller(bt::Array{Ptr{Void},1}, funcsym::Symbol) # Identify the calling line i = 1 while i <= length(bt) @@ -179,3 +179,9 @@ const IpAddr = IPAddr @deprecate isblank(s::String) all(c -> c == ' ' || c == '\t', s) @deprecate randbool! rand! + +export Nothing +const Nothing = Void + +export None +const None = Union() diff --git a/base/error.jl b/base/error.jl index d5007eb558757..8f502e03b68ca 100644 --- a/base/error.jl +++ b/base/error.jl @@ -25,8 +25,8 @@ macro unexpected() :(error("unexpected branch reached")) end -rethrow() = ccall(:jl_rethrow, Void, ())::None -rethrow(e) = ccall(:jl_rethrow_other, Void, (Any,), e)::None +rethrow() = ccall(:jl_rethrow, Void, ())::Bottom +rethrow(e) = ccall(:jl_rethrow_other, Void, (Any,), e)::Bottom backtrace() = ccall(:jl_backtrace_from_here, Array{Ptr{Void},1}, ()) catch_backtrace() = ccall(:jl_get_backtrace, Array{Ptr{Void},1}, ()) diff --git a/base/exports.jl b/base/exports.jl index 093583b5620c3..d46ceecaba98c 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -61,6 +61,7 @@ export MathConst, Matrix, MergeSort, + Nullable, ObjectIdDict, OrdinalRange, PollingFileWatcher, @@ -134,8 +135,6 @@ export Culonglong, Cushort, Cwchar_t, - #Ccomplex_float, - #Ccomplex_double, # Exceptions ArgumentError, @@ -145,6 +144,7 @@ export KeyError, LoadError, MethodError, + NullException, ParseError, ProcessExitedException, SystemError, @@ -197,7 +197,7 @@ export ≠, !==, ≡, - ≢, + ≢, $, %, &, @@ -964,7 +964,7 @@ export rfft, xcorr, -# numerical integration +# numerical integration quadgk, # iteration @@ -1010,7 +1010,7 @@ export toc, toq, -#dates +# dates Date, DateTime, now, @@ -1229,7 +1229,7 @@ export # shared arrays sdata, indexpids, - + # paths and file names abspath, basename, @@ -1323,6 +1323,9 @@ export unsafe_pointer_to_objref, unsafe_store!, +# nullable types + isnull, + # Macros @__FILE__, @b_str, @@ -1381,4 +1384,5 @@ export @inbounds, @simd, @label, - @goto + @goto, + @inline diff --git a/base/expr.jl b/base/expr.jl index f5c297ab9f468..0f716b7d928e1 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -43,7 +43,7 @@ astcopy(x) = x ==(x::QuoteNode, y::QuoteNode) = x.value == y.value function show(io::IO, tv::TypeVar) - if !is(tv.lb, None) + if !is(tv.lb, Bottom) show(io, tv.lb) print(io, "<:") end @@ -63,6 +63,13 @@ macro eval(x) :($(esc(:eval))($(Expr(:quote,x)))) end +macro inline(ex) + esc(_inline(ex)) +end + +_inline(ex::Expr) = pushmeta!(ex, :inline) +_inline(arg) = arg + ## some macro utilities ## find_vars(e) = find_vars(e, {}) @@ -95,3 +102,37 @@ function localize_vars(expr, esca) end Expr(:localize, :(()->($expr)), v...) end + +function pushmeta!(ex::Expr, sym::Symbol) + if ex.head == :function + body::Expr = ex.args[2] + if !isempty(body.args) && isa(body.args[1], Expr) && (body.args[1]::Expr).head == :meta + push!((body.args[1]::Expr).args, sym) + else + unshift!(body.args, Expr(:meta, sym)) + end + elseif (ex.head == :(=) && typeof(ex.args[1]) == Expr && ex.args[1].head == :call) + ex = Expr(:function, ex.args[1], Expr(:block, Expr(:meta, sym), ex.args[2])) +# else +# ex = Expr(:withmeta, ex, sym) + end + ex +end + +function popmeta!(body::Expr, sym::Symbol) + if isa(body.args[1],Expr) && (body.args[1]::Expr).head === :meta + metaargs = (body.args[1]::Expr).args + for i = 1:length(metaargs) + if metaargs[i] == sym + if length(metaargs) == 1 + shift!(body.args) # get rid of :meta Expr + else + deleteat!(metaargs, i) # delete this portion of the metadata + end + return true + end + end + end + false +end +popmeta!(arg, sym) = false diff --git a/base/gmp.jl b/base/gmp.jl index 17626a56eecc6..e29f375f3dd02 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -429,6 +429,7 @@ function base(b::Integer, n::BigInt) end function ndigits0z(x::BigInt, b::Integer=10) + b < 0 && throw(DomainError()) # TODO: make this work correctly. # mpz_sizeinbase might return an answer 1 too big n = int(ccall((:__gmpz_sizeinbase,:libgmp), Culong, (Ptr{BigInt}, Int32), &x, b)) abs(x) < big(b)^(n-1) ? n-1 : n diff --git a/base/grisu.jl b/base/grisu.jl index 1bd1ce03cc1aa..9e1b61d078c1a 100644 --- a/base/grisu.jl +++ b/base/grisu.jl @@ -109,6 +109,9 @@ end Base.show(io::IO, x::FloatingPoint) = _show(io, x, SHORTEST, 0, true) +Base.print(io::IO, x::Float32) = _show(io, x, SHORTEST, 0, false) +Base.print(io::IO, x::Float16) = _show(io, x, SHORTEST, 0, false) + Base.showcompact(io::IO, x::Float64) = _show(io, x, PRECISION, 6, false) Base.showcompact(io::IO, x::Float32) = _show(io, x, PRECISION, 6, false) Base.showcompact(io::IO, x::Float16) = _show(io, x, PRECISION, 5, false) diff --git a/base/hashing2.jl b/base/hashing2.jl index 251ec78faf371..6387095422908 100644 --- a/base/hashing2.jl +++ b/base/hashing2.jl @@ -101,7 +101,7 @@ function decompose(x::Float32) s = int32(n & 0x007fffff) e = int32(n & 0x7f800000 >> 23) s |= int32(e != 0) << 23 - d = ifelse(signbit(n) == 1, -1, 1) + d = ifelse(signbit(n), -1, 1) int(s), int(e - 150 + (e == 0)), d end @@ -112,7 +112,7 @@ function decompose(x::Float64) s = int64(n & 0x000fffffffffffff) e = int64(n & 0x7ff0000000000000 >> 52) s |= int64(e != 0) << 52 - d = ifelse(signbit(n) == 1, -1, 1) + d = ifelse(signbit(n), -1, 1) int(s), int(e - 1075 + (e == 0)), d end diff --git a/base/inference.jl b/base/inference.jl index b589538e8c976..0ecb096029962 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -29,7 +29,7 @@ type CallStack prev::Union(EmptyCallStack,CallStack) sv::StaticVarInfo - CallStack(ast, mod, types, prev) = new(ast, mod, types, false, 0, None, prev) + CallStack(ast, mod, types, prev) = new(ast, mod, types, false, 0, Bottom, prev) end inference_stack = EmptyCallStack() @@ -89,7 +89,7 @@ isvarargtype(t::ANY) = isa(t,DataType)&&is((t::DataType).name,Vararg.name) const t_func = ObjectIdDict() #t_func[tuple] = (0, Inf, (args...)->limit_tuple_depth(args)) -t_func[throw] = (1, 1, x->None) +t_func[throw] = (1, 1, x->Bottom) t_func[box] = (2, 2, (t,v)->(isType(t) ? t.parameters[1] : Any)) t_func[eq_int] = (2, 2, cmp_tfunc) t_func[ne_int] = (2, 2, cmp_tfunc) @@ -115,17 +115,15 @@ t_func[fpiseq] = (2, 2, cmp_tfunc) t_func[fpislt] = (2, 2, cmp_tfunc) t_func[nan_dom_err] = (2, 2, (a, b)->a) t_func[eval(Core.Intrinsics,:ccall)] = - (3, Inf, (fptr, rt, at, a...)->(is(rt,Type{Void}) ? Nothing : - isType(rt) ? rt.parameters[1] : Any)) + (3, Inf, (fptr, rt, at, a...)->(isType(rt) ? rt.parameters[1] : Any)) t_func[eval(Core.Intrinsics,:llvmcall)] = - (3, Inf, (fptr, rt, at, a...)->(is(rt,Type{Void}) ? Nothing : - isType(rt) ? rt.parameters[1] : + (3, Inf, (fptr, rt, at, a...)->(isType(rt) ? rt.parameters[1] : isa(rt,Tuple) ? map(x->x.parameters[1],rt) : Any)) t_func[eval(Core.Intrinsics,:cglobal)] = (1, 2, (fptr, t...)->(isempty(t) ? Ptr{Void} : isType(t[1]) ? Ptr{t[1].parameters[1]} : Ptr)) t_func[eval(Core.Intrinsics,:select_value)] = - # TODO: return None if cnd is definitely not a Bool + # TODO: return Bottom if cnd is definitely not a Bool (3, 3, (cnd, x, y)->Union(x,y)) t_func[is] = (2, 2, cmp_tfunc) t_func[issubtype] = (2, 2, cmp_tfunc) @@ -225,7 +223,7 @@ const tupleref_tfunc = function (A, t, i) return Any end if is(t,()) - return None + return Bottom end n = length(t) last = tupleref(t,n) @@ -237,12 +235,12 @@ const tupleref_tfunc = function (A, t, i) if vararg T = last.parameters[1] else - return None + return Bottom end elseif i == n && vararg T = last.parameters[1] elseif i <= 0 - return None + return Bottom else T = tupleref(t,i) end @@ -256,7 +254,7 @@ const tupleref_tfunc = function (A, t, i) if !isa(types, Type) return Any end - T = reduce(tmerge, None, types) + T = reduce(tmerge, Bottom, types) if wrapType return isleaftype(T) || isa(T,TypeVar) ? Type{T} : Type{TypeVar(:_,T)} else @@ -288,7 +286,7 @@ function limit_type_depth(t::ANY, d::Int, cov::Bool, vars) end end elseif isa(t,UnionType) - t === None && return t + t === Bottom && return t if d > MAX_TYPE_DEPTH R = Any else @@ -334,7 +332,7 @@ const getfield_tfunc = function (A, s0, name) end end if isa(s,UnionType) - return reduce(tmerge, None, map(t->getfield_tfunc(A, t, name), s.types)) + return reduce(tmerge, Bottom, map(t->getfield_tfunc(A, t, name), s.types)) end if !isa(s,DataType) || s.abstract return Any @@ -373,18 +371,18 @@ const getfield_tfunc = function (A, s0, name) end end end - return None + return Bottom elseif isa(A[2],Int) if isa(A[1],Module) || s === Module - return None + return Bottom end i::Int = A[2] if i < 1 || i > length(s.names) - return None + return Bottom end return s.types[i] else - return reduce(tmerge, None, s.types)#Union(s.types...) + return reduce(tmerge, Bottom, s.types)#Union(s.types...) end end t_func[getfield] = (2, 2, getfield_tfunc) @@ -400,7 +398,7 @@ const fieldtype_tfunc = function (A, s, name) return Type end t = getfield_tfunc(A, s, name) - if is(t,None) + if is(t,Bottom) return t end Type{isleaftype(t) || isa(t,TypeVar) ? t : TypeVar(:_, t)} @@ -455,7 +453,7 @@ const apply_type_tfunc = function (A, args...) end if i-1 > length(headtype.parameters) # too many parameters for type - return None + return Bottom end uncertain = true tparams = tuple(tparams..., headtype.parameters[i-1]) @@ -498,7 +496,7 @@ function builtin_tfunction(f::ANY, args::ANY, argtypes::ANY) return tuple_tfunc(argtypes, true) elseif is(f,arrayset) if length(argtypes) < 3 && !isva - return None + return Bottom end a1 = argtypes[1] if isvarargtype(a1) @@ -507,14 +505,14 @@ function builtin_tfunction(f::ANY, args::ANY, argtypes::ANY) return a1 elseif is(f,arrayref) if length(argtypes) < 2 && !isva - return None + return Bottom end a = argtypes[1] return (isa(a,DataType) && a<:Array ? a.parameters[1] : Any) elseif is(f,Expr) if length(argtypes) < 1 && !isva - return None + return Bottom end return Expr end @@ -536,7 +534,7 @@ function builtin_tfunction(f::ANY, args::ANY, argtypes::ANY) end elseif !(tf[1] <= length(argtypes) <= tf[2]) # wrong # of args - return None + return Bottom end if is(f,typeassert) || is(f,tupleref) || is(f,getfield) || is(f,apply_type) || is(f,fieldtype) @@ -627,12 +625,19 @@ const limit_tuple_type_n = function (t::Tuple, lim::Int) last = last.parameters[1] end tail = tuple(t[lim:(n-1)]..., last) - tail = typeintersect(reduce(tmerge, None, tail), Any) + tail = typeintersect(reduce(tmerge, Bottom, tail), Any) return tuple(t[1:(lim-1)]..., Vararg{tail}) end return t end +function func_for_method(m::Method, tt) + if !m.isstaged + return m.func.code + end + (ccall(:jl_instantiate_staged,Any,(Any,Any),m,tt)).code +end + function abstract_call_gf(f, fargs, argtypes, e) if length(argtypes)>1 && (argtypes[1] <: Tuple) && argtypes[2]===Int # allow tuple indexing functions to take advantage of constant @@ -677,11 +682,11 @@ function abstract_call_gf(f, fargs, argtypes, e) # typically, considering many methods means spending lots of time # obtaining poor type information. # It is important for N to be >= the number of methods in the error() - # function, so we can still know that error() is always None. + # function, so we can still know that error() is always Bottom. # here I picked 4. argtypes = limit_tuple_type(argtypes) applicable = _methods(f, argtypes, 4) - rettype = None + rettype = Bottom if is(applicable,false) # this means too many methods matched isa(e,Expr) && (e.head = :call) @@ -690,7 +695,7 @@ function abstract_call_gf(f, fargs, argtypes, e) x::Array{Any,1} = applicable if isempty(x) # no methods match - # TODO: it would be nice to return None here, but during bootstrap we + # TODO: it would be nice to return Bottom here, but during bootstrap we # often compile code that calls methods not defined yet, so it is much # safer just to fall back on dynamic dispatch. return Any @@ -704,7 +709,13 @@ function abstract_call_gf(f, fargs, argtypes, e) end end for (m::Tuple) in x - linfo = m[3].func.code + local linfo + try + linfo = func_for_method(m[3],argtypes) + catch + rettype = Any + break + end sig = m[1] lsig = length(m[3].sig) # limit argument type tuple based on size of definition signature. @@ -734,22 +745,27 @@ function abstract_call_gf(f, fargs, argtypes, e) break end end - # if rettype is None we've found a method not found error + # if rettype is Bottom we've found a method not found error #print("=> ", rettype, "\n") return rettype end function invoke_tfunc(f, types, argtypes) argtypes = typeintersect(types,limit_tuple_type(argtypes)) - if is(argtypes,None) - return None + if is(argtypes,Bottom) + return Bottom end applicable = _methods(f, types, -1) if isempty(applicable) return Any end for (m::Tuple) in applicable - linfo = m[3].func.code + local linfo + try + linfo = func_for_method(m[3],types) + catch + return Any + end if typeseq(m[1],types) tvars = m[2][1:2:end] (ti, env) = ccall(:jl_match_method, Any, (Any,Any,Any), @@ -844,7 +860,7 @@ function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e) end if is(f,kwcall) if length(argtypes) < 3 - return None + return Bottom end if length(fargs) < 2 return Any @@ -872,7 +888,7 @@ function abstract_eval_arg(a::ANY, vtypes::ANY, sv::StaticVarInfo) if isa(a,Symbol) || isa(a,SymbolNode) t = typeintersect(t,Any) # remove Undef end - if isa(t,TypeVar) && t.lb == None && isleaftype(t.ub) + if isa(t,TypeVar) && t.lb == Bottom && isleaftype(t.ub) t = t.ub end return t @@ -881,8 +897,8 @@ end function abstract_eval_call(e, vtypes, sv::StaticVarInfo) fargs = e.args[2:end] argtypes = tuple([abstract_eval_arg(a, vtypes, sv) for a in fargs]...) - if any(x->is(x,None), argtypes) - return None + if any(x->is(x,Bottom), argtypes) + return Bottom end called = e.args[1] func = isconstantfunc(called, sv) @@ -939,7 +955,7 @@ function abstract_eval(e::ANY, vtypes, sv::StaticVarInfo) if is(e.head,:call) || is(e.head,:call1) t = abstract_eval_call(e, vtypes, sv) elseif is(e.head,:null) - t = Nothing + t = Void elseif is(e.head,:new) t = abstract_eval(e.args[1], vtypes, sv) if isType(t) @@ -961,12 +977,12 @@ function abstract_eval(e::ANY, vtypes, sv::StaticVarInfo) # remove unnecessary typevars t = t.name.primary end - if is(t,None) && Undef<:t0 + if is(t,Bottom) && Undef<:t0 # the first time we see this statement the variable will probably - # be Undef; return None so this doesn't contribute to the type + # be Undef; return Bottom so this doesn't contribute to the type # we eventually pick. - elseif is(t,None) - t = Type{None} + elseif is(t,Bottom) + t = Type{Bottom} elseif isleaftype(t) t = Type{t} elseif isleaftype(inference_stack.types) @@ -995,7 +1011,7 @@ function abstract_eval(e::ANY, vtypes, sv::StaticVarInfo) else t = Any end - if isa(t,TypeVar) && t.lb === None + if isa(t,TypeVar) && t.lb === Bottom # no need to use a typevar as the type of an expression t = t.ub end @@ -1019,9 +1035,9 @@ function abstract_eval_constant(x::ANY) end # Undef is the static type of a value location (e.g. variable) that is -# undefined. The corresponding run-time type is None, since accessing an +# undefined. The corresponding run-time type is Bottom, since accessing an # undefined location is an error. A non-lvalue expression cannot have -# type Undef, only None. +# type Undef, only Bottom. # typealias Top Union(Any,Undef) abstract_eval_global(s::Symbol) = @@ -1237,7 +1253,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) #dbg = #dotrace = true local ast::Expr, tfunc_idx - curtype = None + curtype = Bottom redo = false # check cached t-functions tf = def.tfunc @@ -1346,7 +1362,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) if la > 0 lastarg = ast.args[1][la] if is_rest_arg(lastarg) - if atypes === Tuple + if atypes === Tuple if la > 1 atypes = tuple(NTuple{la-1,Any}..., Tuple[1]) end @@ -1651,7 +1667,7 @@ function eval_annotate(e::ANY, vtypes::ANY, sv::StaticVarInfo, decls, clo) e.args[2] = eval_annotate(e.args[2], vtypes, sv, decls, clo) # TODO: if this def does not reach any uses, maybe don't do this rhstype = exprtype(e.args[2]) - if !is(rhstype,None) + if !is(rhstype,Bottom) record_var_type(s, rhstype, decls) end return e @@ -2072,7 +2088,13 @@ function inlineable(f, e::Expr, atypes, sv, enclosing_ast) return NF end meth = meth[1]::Tuple - linfo = meth[3].func.code + + local linfo + try + linfo = func_for_method(meth[3],atypes) + catch + return NF + end ## This code tries to limit the argument list length only when it is ## growing due to recursion. @@ -2285,7 +2307,7 @@ function inlineable(f, e::Expr, atypes, sv, enclosing_ast) icall = LabelNode(label_counter(body.args)+1) partmatch = Expr(:gotoifnot, false, icall.label) thrw = Expr(:call, :throw, Expr(:call, Main.Base.MethodError, (f, :inline), t)) - thrw.typ = None + thrw.typ = Bottom end for i=na:-1:1 # stmts_free needs to be calculated in reverse-argument order @@ -2389,7 +2411,7 @@ function inlineable(f, e::Expr, atypes, sv, enclosing_ast) end end free = effect_free(aei,sv,true) - if ((occ==0 && is(aeitype,None)) || islocal || (occ > 1 && !inline_worthy(aei, occ*2)) || + if ((occ==0 && is(aeitype,Bottom)) || islocal || (occ > 1 && !inline_worthy(aei, occ*2)) || (affect_free && !free) || (!affect_free && !effect_free(aei,sv,false))) if occ != 0 # islocal=true is implied by occ!=0 vnew = unique_name(enclosing_ast, ast) @@ -2496,10 +2518,9 @@ const inline_incompletematch_allowed = false inline_worthy(body, cost::Real) = true function inline_worthy(body::Expr, cost::Real=1.0) # precondition: 0>2) - b == 10 && return ndigits0z(n) +function ndigits0znb(n::Int, b::Int) d = 0 - while ndigits_max_mul < n - n = div(n,b) + while n != 0 + n = cld(n,b) d += 1 end - m = 1 - while m <= n - m *= b - d += 1 + return d +end + +function ndigits0z(n::Unsigned, b::Int) + d = 0 + if b < 0 + d = ndigits0znb(signed(n), b) + else + b == 2 && return (sizeof(n)<<3-leading_zeros(n)) + b == 8 && return div((sizeof(n)<<3)-leading_zeros(n)+2,3) + b == 16 && return (sizeof(n)<<1)-(leading_zeros(n)>>2) + b == 10 && return ndigits0z(n) + while ndigits_max_mul < n + n = div(n,b) + d += 1 + end + m = 1 + while m <= n + m *= b + d += 1 + end end return d end -ndigits0z(x::Integer, b::Integer) = ndigits0z(asunsigned(abs(x)),int(b)) +ndigits0z(x::Integer, b::Integer) = ndigits0z(unsigned(abs(x)),int(b)) + +ndigitsnb(x::Integer, b::Integer) = x==0 ? 1 : ndigits0znb(x, b) ndigits(x::Unsigned, b::Integer) = x==0 ? 1 : ndigits0z(x,int(b)) ndigits(x::Unsigned) = x==0 ? 1 : ndigits0z(x) -ndigits(x::Integer, b::Integer) = ndigits(asunsigned(abs(x)),int(b)) -ndigits(x::Integer) = ndigits(asunsigned(abs(x))) +ndigits(x::Integer, b::Integer) = b >= 0 ? ndigits(unsigned(abs(x)),int(b)) : ndigitsnb(x, b) +ndigits(x::Integer) = ndigits(unsigned(abs(x))) ## integer to string functions ## @@ -252,7 +267,7 @@ function base(b::Int, x::Unsigned, pad::Int, neg::Bool) if neg; a[1]='-'; end ASCIIString(a) end -base(b::Integer, n::Integer, pad::Integer=1) = base(int(b), asunsigned(abs(n)), pad, n<0) +base(b::Integer, n::Integer, pad::Integer=1) = base(int(b), unsigned(abs(n)), pad, n<0) for sym in (:bin, :oct, :dec, :hex) @eval begin @@ -260,8 +275,8 @@ for sym in (:bin, :oct, :dec, :hex) ($sym)(x::Unsigned) = ($sym)(x,1,false) ($sym)(x::Char, p::Int) = ($sym)(unsigned(x),p,false) ($sym)(x::Char) = ($sym)(unsigned(x),1,false) - ($sym)(x::Integer, p::Int) = ($sym)(asunsigned(abs(x)),p,x<0) - ($sym)(x::Integer) = ($sym)(asunsigned(abs(x)),1,x<0) + ($sym)(x::Integer, p::Int) = ($sym)(unsigned(abs(x)),p,x<0) + ($sym)(x::Integer) = ($sym)(unsigned(abs(x)),1,x<0) end end diff --git a/base/linalg/arpack.jl b/base/linalg/arpack.jl index 6bdfd1dcfa947..1e60e4274a6a0 100644 --- a/base/linalg/arpack.jl +++ b/base/linalg/arpack.jl @@ -20,11 +20,11 @@ function aupd_wrapper(T, matvecA::Function, matvecB::Function, solveSI::Function rwork = cmplx ? Array(TR, ncv) : Array(TR, 0) if isempty(v0) - resid = Array(T, n) - info = zeros(BlasInt, 1) + resid = Array(T, n) + info = zeros(BlasInt, 1) else - resid = deepcopy(v0) - info = ones(BlasInt, 1) + resid = deepcopy(v0) + info = ones(BlasInt, 1) end iparam = zeros(BlasInt, 11) ipntr = zeros(BlasInt, (sym && !cmplx) ? 11 : 14) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index c8ef8f11860c0..0960c65468f3a 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -269,7 +269,7 @@ function expm!{T<:BlasFloat}(A::StridedMatrix{T}) end end - # Undo the balancing + # Undo the balancing for j = ilo:ihi scj = scale[j] for i = 1:n diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index 0102bd743e7e1..2a13b311a1add 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -11,7 +11,15 @@ end scale{R<:Real}(s::Complex, X::AbstractArray{R}) = scale(X, s) -generic_scale!(X::AbstractArray, s::Number) = generic_scale!(X, X, s) +# For better performance when input and output are the same array +# See https://github.com/JuliaLang/julia/issues/8415#issuecomment-56608729 +function generic_scale!(X::AbstractArray, s::Number) + for i = 1:length(X) + @inbounds X[i] *= s + end + X +end + function generic_scale!(C::AbstractArray, X::AbstractArray, s::Number) length(C) == length(X) || error("C must be the same length as X") for i = 1:length(X) @@ -21,8 +29,8 @@ function generic_scale!(C::AbstractArray, X::AbstractArray, s::Number) end scale!(C::AbstractArray, s::Number, X::AbstractArray) = generic_scale!(C, X, s) scale!(C::AbstractArray, X::AbstractArray, s::Number) = generic_scale!(C, X, s) -scale!(X::AbstractArray, s::Number) = generic_scale!(X, X, s) -scale!(s::Number, X::AbstractArray) = generic_scale!(X, X, s) +scale!(X::AbstractArray, s::Number) = generic_scale!(X, s) +scale!(s::Number, X::AbstractArray) = generic_scale!(X, s) cross(a::AbstractVector, b::AbstractVector) = [a[2]*b[3]-a[3]*b[2], a[3]*b[1]-a[1]*b[3], a[1]*b[2]-a[2]*b[1]] diff --git a/base/linalg/ldlt.jl b/base/linalg/ldlt.jl index 117f4a034bee2..2d5016c82bd2f 100644 --- a/base/linalg/ldlt.jl +++ b/base/linalg/ldlt.jl @@ -14,44 +14,44 @@ convert{T,S,U}(::Type{Factorization{T}}, F::LDLt{S,U}) = convert(LDLt{T,U}, F) # SymTridiagonal function ldltfact!{T<:Real}(S::SymTridiagonal{T}) - n = size(S,1) - d = S.dv - e = S.ev - @inbounds for i = 1:n-1 - e[i] /= d[i] - d[i+1] -= abs2(e[i])*d[i] - d[i+1] > 0 || throw(PosDefException(i+1)) - end - return LDLt{T,SymTridiagonal{T}}(S) + n = size(S,1) + d = S.dv + e = S.ev + @inbounds for i = 1:n-1 + e[i] /= d[i] + d[i+1] -= abs2(e[i])*d[i] + d[i+1] > 0 || throw(PosDefException(i+1)) + end + return LDLt{T,SymTridiagonal{T}}(S) end function ldltfact{T}(M::SymTridiagonal{T}) - S = typeof(zero(T)/one(T)) - return S == T ? ldltfact!(copy(M)) : ldltfact!(convert(SymTridiagonal{S}, M)) + S = typeof(zero(T)/one(T)) + return S == T ? ldltfact!(copy(M)) : ldltfact!(convert(SymTridiagonal{S}, M)) end function A_ldiv_B!{T}(S::LDLt{T,SymTridiagonal{T}}, B::AbstractVecOrMat{T}) - n, nrhs = size(B, 1), size(B, 2) - size(S,1) == n || throw(DimensionMismatch("")) - d = S.data.dv - l = S.data.ev - @inbounds begin - for i = 2:n - li1 = l[i-1] - for j = 1:nrhs - B[i,j] -= li1*B[i-1,j] - end - end - dn = d[n] - for j = 1:nrhs - B[n,j] /= dn - end - for i = n-1:-1:1 - di = d[i] - li = l[i] - for j = 1:nrhs - B[i,j] /= di - B[i,j] -= li*B[i+1,j] - end - end - end - return B + n, nrhs = size(B, 1), size(B, 2) + size(S,1) == n || throw(DimensionMismatch("")) + d = S.data.dv + l = S.data.ev + @inbounds begin + for i = 2:n + li1 = l[i-1] + for j = 1:nrhs + B[i,j] -= li1*B[i-1,j] + end + end + dn = d[n] + for j = 1:nrhs + B[n,j] /= dn + end + for i = n-1:-1:1 + di = d[i] + li = l[i] + for j = 1:nrhs + B[i,j] /= di + B[i,j] -= li*B[i+1,j] + end + end + end + return B end diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index 7de0ffad84423..021c59cd3d43e 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -112,50 +112,50 @@ Ac_mul_B!(y::StridedVector, A::StridedMatrix, x::StridedVector) = generic_matvec # Matrix-matrix multiplication -function (*){T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T),arithtype(S)) - A_mul_B!(similar(B,TS,(size(A,1),size(B,2))),A,B) +function (*){T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) + TS = promote_type(arithtype(T), arithtype(S)) + A_mul_B!(similar(B, TS, (size(A,1), size(B,2))), A, B) end A_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper!(C, 'N', 'N', A, B) for elty in (Float32,Float64) @eval begin function A_mul_B!(C::StridedMatrix{Complex{$elty}}, A::StridedMatrix{Complex{$elty}}, B::StridedMatrix{$elty}) - Afl = reinterpret($elty,A,(2size(A,1),size(A,2))) - Cfl = reinterpret($elty,C,(2size(C,1),size(C,2))) - gemm_wrapper!(Cfl,'N','N',Afl,B) + Afl = reinterpret($elty, A, (2size(A,1), size(A,2))) + Cfl = reinterpret($elty, C, (2size(C,1), size(C,2))) + gemm_wrapper!(Cfl, 'N', 'N', Afl, B) return C end end end A_mul_B!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'N', 'N', A, B) -function At_mul_B{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T),arithtype(S)) - At_mul_B!(similar(B,TS,(size(A,2),size(B,2))),A,B) +function At_mul_B{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) + TS = promote_type(arithtype(T), arithtype(S)) + At_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) end At_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = is(A,B) ? syrk_wrapper!(C, 'T', A) : gemm_wrapper!(C, 'T', 'N', A, B) At_mul_B!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'T', 'N', A, B) -function A_mul_Bt{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T),arithtype(S)) - A_mul_Bt!(similar(B,TS,(size(A,1),size(B,1))),A,B) +function A_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) + TS = promote_type(arithtype(T), arithtype(S)) + A_mul_Bt!(similar(B, TS, (size(A,1), size(B,1))), A, B) end A_mul_Bt!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = is(A,B) ? syrk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'T', A, B) for elty in (Float32,Float64) @eval begin function A_mul_Bt!(C::StridedMatrix{Complex{$elty}}, A::StridedMatrix{Complex{$elty}}, B::StridedMatrix{$elty}) - Afl = reinterpret($elty,A,(2size(A,1),size(A,2))) - Cfl = reinterpret($elty,C,(2size(C,1),size(C,2))) - gemm_wrapper!(Cfl,'N','T',Afl,B) + Afl = reinterpret($elty, A, (2size(A,1), size(A,2))) + Cfl = reinterpret($elty, C, (2size(C,1), size(C,2))) + gemm_wrapper!(Cfl, 'N', 'T', Afl, B) return C end end end A_mul_Bt!(C::StridedVecOrMat, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'N', 'T', A, B) -function At_mul_Bt{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T),arithtype(S)) - At_mul_Bt!(similar(B,TS,(size(A,2),size(B,1))),A,B) +function At_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) + TS = promote_type(arithtype(T), arithtype(S)) + At_mul_Bt!(similar(B, TS, (size(A,2), size(B,1))), A, B) end At_mul_Bt!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper!(C, 'T', 'T', A, B) At_mul_Bt!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'T', 'T', A, B) @@ -163,8 +163,8 @@ At_mul_Bt!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matma Ac_mul_B{T<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{T}) = At_mul_B(A, B) Ac_mul_B!{T<:BlasReal}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = At_mul_B!(C, A, B) function Ac_mul_B{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T),arithtype(S)) - Ac_mul_B!(similar(B,TS,(size(A,2),size(B,2))),A,B) + TS = promote_type(arithtype(T), arithtype(S)) + Ac_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) end Ac_mul_B!{T<:BlasComplex}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = is(A,B) ? herk_wrapper!(C,'C',A) : gemm_wrapper!(C,'C', 'N', A, B) Ac_mul_B!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'C', 'N', A, B) @@ -178,10 +178,10 @@ end A_mul_Bc!{T<:BlasComplex}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = is(A,B) ? herk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'C', A, B) A_mul_Bc!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'N', 'C', A, B) -Ac_mul_Bc{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bc!(similar(B,promote_type(arithtype(T),arithtype(S)), (size(A,2), size(B,1))), A, B) +Ac_mul_Bc{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bc!(similar(B, promote_type(arithtype(T), arithtype(S)), (size(A,2), size(B,1))), A, B) Ac_mul_Bc!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper!(C, 'C', 'C', A, B) Ac_mul_Bc!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'C', 'C', A, B) -Ac_mul_Bt{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bt(similar(B, promote_type(arithtype(A),arithtype(B)), (size(A,2), size(B,1))), A, B) +Ac_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bt(similar(B, promote_type(arithtype(A), arithtype(B)), (size(A,2), size(B,1))), A, B) Ac_mul_Bt!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'C', 'T', A, B) # Supporting functions for matrix multiplication diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index 02f6fe7221a3c..4c9fe6b58261b 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -49,6 +49,30 @@ end /(A::SymTridiagonal, B::Number) = SymTridiagonal(A.dv/B, A.ev/B) ==(A::SymTridiagonal, B::SymTridiagonal) = (A.dv==B.dv) && (A.ev==B.ev) +function A_mul_B!(C::StridedVecOrMat, S::SymTridiagonal, B::StridedVecOrMat) + m, n = size(B, 1), size(B, 2) + m == size(S, 1) == size(C, 1) || throw(DimensionMismatch("")) + n == size(C, 2) || throw(DimensionMismatch("")) + + α = S.dv + β = S.ev + @inbounds begin + for j = 1:n + x₀, x₊ = B[1, j], B[2, j] + β₀ = β[1] + C[1, j] = α[1]*x₀ + x₊*β₀ + for i = 2:m - 1 + x₋, x₀, x₊ = x₀, x₊, B[i + 1, j] + β₋, β₀ = β₀, β[i] + C[i, j] = β₋*x₋ + α[i]*x₀ + β₀*x₊ + end + C[m, j] = β₀*x₀ + α[m]*x₊ + end + end + + return C +end + ## Solver function \{T<:BlasFloat}(M::SymTridiagonal{T}, rhs::StridedVecOrMat{T}) if stride(rhs, 1) == 1 @@ -239,16 +263,17 @@ function A_mul_B!(C::AbstractVecOrMat, A::Tridiagonal, B::AbstractVecOrMat) u = A.du @inbounds begin for j = 1:nB - C[1,j] = d[1]*B[1,j] + u[1]*B[2,j] - for i = 2:nA-1 - C[i,j] = l[i-1]*B[i-1,j] + d[i]*B[i,j] + u[i]*B[i+1,j] + b₀, b₊ = B[1, j], B[2, j] + C[1, j] = d[1]*b₀ + u[1]*b₊ + for i = 2:nA - 1 + b₋, b₀, b₊ = b₀, b₊, B[i + 1, j] + C[i, j] = l[i - 1]*b₋ + d[i]*b₀ + u[i]*b₊ end - C[nA,j] = l[nA-1]*B[nA-1,j] + d[nA]*B[nA,j] + C[nA, j] = l[nA - 1]*b₀ + d[nA]*b₊ end end C end -*(A::Tridiagonal, B::AbstractVecOrMat) = A_mul_B!(similar(B), A, B) A_ldiv_B!(A::Tridiagonal,B::AbstractVecOrMat) = A_ldiv_B!(lufact!(A), B) At_ldiv_B!(A::Tridiagonal,B::AbstractVecOrMat) = At_ldiv_B!(lufact!(A), B) diff --git a/base/loading.jl b/base/loading.jl index f45b1ae4171bc..760370c512e5a 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -99,7 +99,7 @@ include_string(txt::String, fname::String) = include_string(txt::String) = include_string(txt, "string") -function source_path(default::Union(String,Nothing)="") +function source_path(default::Union(String,Void)="") t = current_task() while true s = t.storage diff --git a/base/methodshow.jl b/base/methodshow.jl index 6ba1e201d5ea1..e591b24a2d4a9 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -12,7 +12,7 @@ function argtype_decl(n, t) # -> (argname, argtype) if t === Any && !isempty(s) return s, "" end - if t <: Vararg && t !== None && t.parameters[1] === Any + if t <: Vararg && t !== Union() && t.parameters[1] === Any return string(s, "..."), "" end return s, string(t) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 3c1f0238fd638..4a6f6c22276cf 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1,6 +1,6 @@ ### From array.jl -@ngenerate N Nothing function checksize(A::AbstractArray, I::NTuple{N, Any}...) +@ngenerate N Void function checksize(A::AbstractArray, I::NTuple{N, Any}...) @nexprs N d->(size(A, d) == length(I_d) || throw(DimensionMismatch("index $d has length $(length(I_d)), but size(A, $d) = $(size(A,d))"))) nothing end diff --git a/base/nullable.jl b/base/nullable.jl new file mode 100644 index 0000000000000..40e38f20fb545 --- /dev/null +++ b/base/nullable.jl @@ -0,0 +1,50 @@ +immutable Nullable{T} + isnull::Bool + value::T + + Nullable() = new(true) + Nullable(value::T) = new(false, value) +end + +immutable NullException <: Exception +end + +Nullable{T}(value::T) = Nullable{T}(value) + +function convert{S, T}(::Type{Nullable{T}}, x::Nullable{S}) + return isnull(x) ? Nullable{T}() : Nullable(convert(T, get(x))) +end + +function show{T}(io::IO, x::Nullable{T}) + if x.isnull + @printf(io, "Nullable{%s}()", repr(T)) + else + @printf(io, "Nullable(%s)", repr(x.value)) + end +end + +get(x::Nullable) = x.isnull ? throw(NullException()) : x.value + +get{S, T}(x::Nullable{S}, y::T) = x.isnull ? convert(S, y) : x.value + +isnull(x::Nullable) = x.isnull + +function isequal{S, T}(x::Nullable{S}, y::Nullable{T}) + if x.isnull && y.isnull + return true + elseif x.isnull || y.isnull + return false + else + return isequal(x.value, y.value) + end +end + +=={S, T}(x::Nullable{S}, y::Nullable{T}) = throw(NullException()) + +function hash(x::Nullable, h::Uint) + if x.isnull + return h + uint(0x932e0143e51d0171) + else + return hash(x.value, h + uint(0x932e0143e51d0171)) + end +end diff --git a/base/pkg.jl b/base/pkg.jl index e53c0aff261ca..7bef424bbbb07 100644 --- a/base/pkg.jl +++ b/base/pkg.jl @@ -50,7 +50,7 @@ tag(pkg::String, sym::Symbol, commit::String) = cd(Entry.tag,pkg,sym,false,commi tag(pkg::String, ver::VersionNumber; force::Bool=false) = cd(Entry.tag,pkg,ver,force) tag(pkg::String, ver::VersionNumber, commit::String; force::Bool=false) = - cd(Entry.tag,pkg,ver,force,commit) + cd(Entry.tag,pkg,ver,force,commit) submit(pkg::String) = cd(Entry.submit,pkg) submit(pkg::String, commit::String) = cd(Entry.submit,pkg,commit) @@ -61,7 +61,7 @@ build() = cd(Entry.build) build(pkgs::String...) = cd(Entry.build,[pkgs...]) generate(pkg::String, license::String; force::Bool=false, authors::Union(String,Array) = [], config::Dict=Dict()) = - cd(Generate.package,pkg,license,force=force,authors=authors,config=config) + cd(Generate.package,pkg,license,force=force,authors=authors,config=config) test(;coverage::Bool=false) = cd(Entry.test; coverage=coverage) diff --git a/base/pkg/cache.jl b/base/pkg/cache.jl index b0d7bc4d4e9c1..23d0c44a9a327 100644 --- a/base/pkg/cache.jl +++ b/base/pkg/cache.jl @@ -40,9 +40,9 @@ function prefetch{S<:String}(pkg::String, url::String, sha1s::Vector{S}) Git.set_remote_url(url, dir=cache) if !all(sha1->Git.iscommit(sha1, dir=cache), sha1s) info("Updating cache of $pkg...") - Git.success(`remote update`, dir=cache) || - error("couldn't update $cache using `git remote update`") - end + Git.success(`remote update`, dir=cache) || + error("couldn't update $cache using `git remote update`") + end filter(sha1->!Git.iscommit(sha1, dir=cache), sha1s) end prefetch(pkg::String, url::String, sha1::String...) = prefetch(pkg, url, String[sha1...]) diff --git a/base/pkg/generate.jl b/base/pkg/generate.jl index 5cae4130b8d2d..56f1047755894 100644 --- a/base/pkg/generate.jl +++ b/base/pkg/generate.jl @@ -152,7 +152,7 @@ function travis(pkg::String; force::Bool=false) - sudo apt-get install libpcre3-dev julia -y - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi script: - - julia -e 'Pkg.init(); Pkg.clone(pwd()); Pkg.test("$pkg")' + - julia -e 'versioninfo(); Pkg.init(); Pkg.clone(pwd()); Pkg.test("$pkg")' """) end end diff --git a/base/pkg/github.jl b/base/pkg/github.jl index 8b6bcef435a23..cc32239a366f2 100644 --- a/base/pkg/github.jl +++ b/base/pkg/github.jl @@ -47,7 +47,7 @@ function curl(url::String, opts::Cmd=``) end error("strangely formatted HTTP response") end -curl(url::String, data::Nothing, opts::Cmd=``) = curl(url,opts) +curl(url::String, data::Void, opts::Cmd=``) = curl(url,opts) curl(url::String, data, opts::Cmd=``) = curl(url,`--data $(sprint(io->json().print(io,data))) $opts`) diff --git a/base/pkg/query.jl b/base/pkg/query.jl index b908e365b0cef..ad0cfe8e119c8 100644 --- a/base/pkg/query.jl +++ b/base/pkg/query.jl @@ -64,7 +64,7 @@ function dependencies(avail::Dict, fix::Dict = (ByteString=>Fixed)["julia"=>Fixe avail, conflicts end -typealias PackageState Union(Nothing,VersionNumber) +typealias PackageState Union(Void,VersionNumber) function diff(have::Dict, want::Dict, avail::Dict, fixed::Dict) change = Array((ByteString,(PackageState,PackageState)),0) diff --git a/base/pointer.jl b/base/pointer.jl index 654a896e004a6..78a8370938ffd 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -20,7 +20,7 @@ convert(::Type{Ptr{Uint8}}, s::ByteString) = convert(Ptr{Uint8}, s.data) convert(::Type{Ptr{Int8}}, s::ByteString) = convert(Ptr{Int8}, s.data) convert{T}(::Type{Ptr{T}}, a::Array{T}) = ccall(:jl_array_ptr, Ptr{T}, (Any,), a) -convert(::Type{Ptr{None}}, a::Array) = ccall(:jl_array_ptr, Ptr{None}, (Any,), a) +convert(::Type{Ptr{Void}}, a::Array) = ccall(:jl_array_ptr, Ptr{Void}, (Any,), a) # note: these definitions don't mean any AbstractArray is convertible to # pointer. they just map the array element type to the pointer type for diff --git a/base/precompile.jl b/base/precompile.jl index 4dd248140a678..2166388c89f71 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -87,7 +87,7 @@ precompile(abstract_interpret, (Bool, ObjectIdDict, StaticVarInfo)) precompile(eval_annotate, (LambdaStaticData, ObjectIdDict, StaticVarInfo, ObjectIdDict, Array{Any,1})) precompile(occurs_more, (Bool, Function, Int)) precompile(isconstantfunc, (SymbolNode, StaticVarInfo)) -precompile(CallStack, (Expr, Module, (Nothing,), EmptyCallStack)) +precompile(CallStack, (Expr, Module, (Void,), EmptyCallStack)) precompile(convert, (Type{Module}, Module)) precompile(effect_free, (Expr,)) precompile(effect_free, (TopNode,)) @@ -125,7 +125,7 @@ precompile(==, (Bool,Bool)) precompile(try_include, (ASCIIString,)) precompile(isfile, (ASCIIString,)) precompile(include_from_node1, (ASCIIString,)) -precompile(source_path, (Nothing,)) +precompile(source_path, (Void,)) precompile(task_local_storage, ()) precompile(atexit, (Function,)) precompile(print, (TTY, ASCIIString)) @@ -156,7 +156,7 @@ precompile(!=, (SubString{ASCIIString}, ASCIIString)) precompile(print_joined, (IOBuffer, Array{SubString{ASCIIString}, 1}, ASCIIString)) precompile(push!, (Array{Union(ASCIIString, UTF8String), 1}, ASCIIString)) precompile(Terminals.TTYTerminal, (ASCIIString, TTY, TTY, TTY)) -precompile(isequal, (Nothing, Nothing)) +precompile(isequal, (Void, Void)) precompile(banner, (Terminals.TTYTerminal, Terminals.TTYTerminal)) precompile(banner, (Terminals.TTYTerminal,)) precompile(print, (IOBuffer, VersionNumber)) @@ -220,7 +220,7 @@ precompile(keys, (Dict{Uint8, Any},)) precompile(in, (Uint8, KeyIterator{Dict{Uint8, Any}})) precompile(ht_keyindex, (Dict{Uint8, Any}, Uint8)) precompile(push!, (Array{String, 1}, ASCIIString)) -precompile(LineEdit.fix_conflicts!, (Nothing, Int)) +precompile(LineEdit.fix_conflicts!, (Void, Int)) precompile(convert, (Type{Function}, Function)) precompile(convert, (Type{Any}, Function)) precompile(similar, (Array{LineEdit.Prompt, 1}, Type{LineEdit.TextInterface}, (Int,))) diff --git a/base/printf.jl b/base/printf.jl index 44783afa62f1f..9d717deeb9238 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -749,7 +749,7 @@ end function ini_dec(x::SmallFloatingPoint, n::Int) if x == 0.0 ccall(:memset, Ptr{Void}, (Ptr{Void}, Cint, Csize_t), DIGITS, '0', n) - return int32(1), int32(1), bool(signbit(x)) + return int32(1), int32(1), signbit(x) else len,pt,neg,buffer = grisu(x,Grisu.PRECISION,n) end diff --git a/base/process.jl b/base/process.jl index 261074142a2d7..28cb13e1ceb6a 100644 --- a/base/process.jl +++ b/base/process.jl @@ -4,7 +4,7 @@ type Cmd <: AbstractCmd exec::Vector{ByteString} ignorestatus::Bool detach::Bool - env::Union(Array{ByteString},Nothing) + env::Union(Array{ByteString},Void) dir::UTF8String Cmd(exec::Vector{ByteString}) = new(exec, false, false, nothing, "") end diff --git a/base/profile.jl b/base/profile.jl index b3676606526d0..9f2a5a8bfd8ec 100644 --- a/base/profile.jl +++ b/base/profile.jl @@ -21,7 +21,7 @@ end #### #### User-level functions #### -function init(; n::Union(Nothing,Integer) = nothing, delay::Union(Nothing,Float64) = nothing) +function init(; n::Union(Void,Integer) = nothing, delay::Union(Void,Float64) = nothing) n_cur = ccall(:jl_profile_maxlen_data, Csize_t, ()) delay_cur = ccall(:jl_profile_delay_nsec, Uint64, ())/10^9 if n == nothing && delay == nothing diff --git a/base/promotion.jl b/base/promotion.jl index a3879cd1cb311..5e5395402ba1e 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -1,6 +1,6 @@ ## type join (closest common ancestor, or least upper bound) ## -typejoin() = None +typejoin() = Bottom typejoin(t::ANY) = t typejoin(t::ANY, ts...) = typejoin(t, typejoin(ts...)) function typejoin(a::ANY, b::ANY) @@ -22,7 +22,7 @@ function typejoin(a::ANY, b::ANY) if !isa(u,UnionType) return u end - return reduce(typejoin, None, u.types) + return reduce(typejoin, Bottom, u.types) end if isa(a,Tuple) if !isa(b,Tuple) @@ -82,7 +82,7 @@ end # reduce typejoin over tup[i:end] function tailjoin(tup, i) - t = None + t = Bottom for j = i:length(tup) tj = tup[j] t = typejoin(t, isvarargtype(tj)?tj.parameters[1]:tj) @@ -92,30 +92,30 @@ end ## promotion mechanism ## -promote_type() = None +promote_type() = Bottom promote_type(T) = T promote_type(T, S ) = typejoin(T, S) promote_type(T, S...) = promote_type(T, promote_type(S...)) -promote_type(::Type{None}, ::Type{None}) = None +promote_type(::Type{Bottom}, ::Type{Bottom}) = Bottom promote_type{T}(::Type{T}, ::Type{T}) = T -promote_type{T}(::Type{T}, ::Type{None}) = T -promote_type{T}(::Type{None}, ::Type{T}) = T +promote_type{T}(::Type{T}, ::Type{Bottom}) = T +promote_type{T}(::Type{Bottom}, ::Type{T}) = T # Try promote_rule in both orders. Typically only one is defined, -# and there is a fallback returning None below, so the common case is +# and there is a fallback returning Bottom below, so the common case is # promote_type(T, S) => -# promote_result(T, S, result, None) => -# typejoin(result, None) => result +# promote_result(T, S, result, Bottom) => +# typejoin(result, Bottom) => result promote_type{T,S}(::Type{T}, ::Type{S}) = promote_result(T, S, promote_rule(T,S), promote_rule(S,T)) -promote_rule(T, S) = None +promote_rule(T, S) = Bottom promote_result(t,s,T,S) = promote_type(T,S) -# If no promote_rule is defined, both directions give None. In that +# If no promote_rule is defined, both directions give Bottom. In that # case use typejoin on the original types instead. -promote_result{T,S}(::Type{T},::Type{S},::Type{None},::Type{None}) = typejoin(T, S) +promote_result{T,S}(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) = typejoin(T, S) promote() = () promote(x) = (x,) @@ -143,7 +143,7 @@ end # Otherwise, typejoin(T,S) is called (returning Number) so no conversion # happens, and +(promote(x,y)...) is called again, causing a stack # overflow. -promote_result{T<:Number,S<:Number}(::Type{T},::Type{S},::Type{None},::Type{None}) = +promote_result{T<:Number,S<:Number}(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) = promote_to_super(T, S, typejoin(T,S)) # promote numeric types T and S to typejoin(T,S) if T<:S or S<:T diff --git a/base/reflection.jl b/base/reflection.jl index 5ce427b9f87b9..2317722a480ed 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -73,7 +73,7 @@ function _subtypes(m::Module, x::DataType, sts=Set(), visited=Set()) t = eval(m,s) if isa(t, DataType) && t.name.name == s && super(t).name == x.name ti = typeintersect(t, x) - ti != None && push!(sts, ti) + ti != Bottom && push!(sts, ti) elseif isa(t, Module) && !in(t, visited) _subtypes(t, x, sts, visited) end diff --git a/base/regex.jl b/base/regex.jl index 04d108fc77b4a..a71c07632b938 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -80,7 +80,7 @@ end immutable RegexMatch match::SubString{UTF8String} - captures::Vector{Union(Nothing,SubString{UTF8String})} + captures::Vector{Union(Void,SubString{UTF8String})} offset::Int offsets::Vector{Int} end @@ -121,7 +121,7 @@ function match(re::Regex, str::UTF8String, idx::Integer, add_opts::Uint32=uint32 end n = length(re.ovec)/3 - 1 mat = SubString(str, re.ovec[1]+1, re.ovec[2]) - cap = Union(Nothing,SubString{UTF8String})[ + cap = Union(Void,SubString{UTF8String})[ re.ovec[2i+1] < 0 ? nothing : SubString(str, re.ovec[2i+1]+1, re.ovec[2i+2]) for i=1:n ] off = Int[ re.ovec[2i+1]::Int32+1 for i=1:n ] RegexMatch(mat, cap, re.ovec[1]+1, off) diff --git a/base/serialize.jl b/base/serialize.jl index 48962ae7a38f5..5345cea80ab11 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -21,7 +21,7 @@ let i = 2 UTF16String, UTF32String, Float16, :reserved9, :reserved10, :reserved11, :reserved12, - (), Bool, Any, :Any, None, Top, Undef, Type, + (), Bool, Any, :Any, Bottom, Top, Undef, Type, :Array, :TypeVar, :Box, :lambda, :body, :return, :call, symbol("::"), :(=), :null, :gotoifnot, :A, :B, :C, :M, :N, :T, :S, :X, :Y, diff --git a/base/set.jl b/base/set.jl index b7a9a474707a2..abc2a9a7cef74 100644 --- a/base/set.jl +++ b/base/set.jl @@ -1,8 +1,8 @@ type Set{T} - dict::Dict{T,Nothing} + dict::Dict{T,Void} - Set() = new(Dict{T,Nothing}()) - Set(itr) = union!(new(Dict{T,Nothing}()), itr) + Set() = new(Dict{T,Void}()) + Set(itr) = union!(new(Dict{T,Void}()), itr) end Set() = Set{Any}() Set(itr) = Set{eltype(itr)}(itr) @@ -37,7 +37,7 @@ next(s::Set, i) = (s.dict.keys[i], skip_deleted(s.dict,i+1)) # TODO: simplify me? pop!(s::Set) = (val = s.dict.keys[start(s.dict)]; delete!(s.dict, val); val) -join_eltype() = None +join_eltype() = Bottom join_eltype(v1, vs...) = typejoin(eltype(v1), join_eltype(vs...)) union() = Set() diff --git a/base/show.jl b/base/show.jl index 6138d6d864a37..cd2f426491eab 100644 --- a/base/show.jl +++ b/base/show.jl @@ -68,9 +68,7 @@ function show(io::IO, x::IntrinsicFunction) end function show(io::IO, x::UnionType) - if is(x,None) - print(io, "None") - elseif is(x,Top) + if is(x,Top) print(io, "Top") else print(io, "Union", x.types) @@ -107,14 +105,13 @@ macro show(exs...) end show(io::IO, tn::TypeName) = print(io, tn.name) -show(io::IO, ::Nothing) = print(io, "nothing") +show(io::IO, ::Void) = print(io, "nothing") show(io::IO, b::Bool) = print(io, b ? "true" : "false") show(io::IO, n::Signed) = (write(io, dec(n)); nothing) show(io::IO, n::Unsigned) = print(io, "0x", hex(n,sizeof(n)<<1)) print(io::IO, n::Unsigned) = print(io, dec(n)) -show{T}(io::IO, p::Ptr{T}) = - print(io, is(T,None) ? "Ptr{Void}" : typeof(p), " @0x$(hex(unsigned(p), WORD_SIZE>>2))") +show{T}(io::IO, p::Ptr{T}) = print(io, typeof(p), " @0x$(hex(unsigned(p), WORD_SIZE>>2))") function show(io::IO, m::Module) if is(m,Main) @@ -197,12 +194,6 @@ show_comma_array(io::IO, itr, o, c) = show_delim_array(io, itr, o, ',', c, false show(io::IO, t::Tuple) = show_delim_array(io, t, '(', ',', ')', true) show(io::IO, s::Symbol) = show_unquoted(io, QuoteNode(s)) -show(io::IO, tn::TypeName) = print(io, tn.name) -show(io::IO, ::Nothing) = print(io, "nothing") -show(io::IO, b::Bool) = print(io, b ? "true" : "false") -show(io::IO, n::Signed) = (write(io, dec(n)); nothing) -show(io::IO, n::Unsigned) = print(io, "0x", hex(n,sizeof(n)<<1)) -print(io::IO, n::Unsigned) = print(io, dec(n)) ## Abstract Syntax Tree (AST) printing ## @@ -618,6 +609,11 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) print(io, '&') show_unquoted(io, args[1]) + # transpose + elseif is(head, symbol('\'')) && length(args) == 1 + show_unquoted(io, args[1]) + print(io, '\'') + # print anything else as "Expr(head, args...)" else print(io, "\$(Expr(") diff --git a/base/socket.jl b/base/socket.jl index 18059a5f5429b..515e057b9e2eb 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -666,7 +666,7 @@ function listenany(default_port) return (addr.port,sock) end close(sock) - addr.port += 1 + addr.port += 1 if addr.port==default_port error("no ports available") end diff --git a/base/sparse/csparse.jl b/base/sparse/csparse.jl index e59f988b8b00b..a22a3f9b98364 100644 --- a/base/sparse/csparse.jl +++ b/base/sparse/csparse.jl @@ -123,22 +123,27 @@ end # Based on Direct Methods for Sparse Linear Systems, T. A. Davis, SIAM, Philadelphia, Sept. 2006. # Section 2.5: Transpose # http://www.cise.ufl.edu/research/sparse/CSparse/ - -# NOTE: When calling transpose!(S,T), the colptr in the result matrix T must be set up -# by counting the nonzeros in every row of S. function transpose!{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, T::SparseMatrixCSC{Tv,Ti}) + (mS, nS) = size(S) + nnzS = nnz(S) + colptr_S = S.colptr + rowval_S = S.rowval + nzval_S = S.nzval + (mT, nT) = size(T) colptr_T = T.colptr rowval_T = T.rowval nzval_T = T.nzval - nnzS = nnz(S) - colptr_S = S.colptr - rowval_S = S.rowval - nzval_S = S.nzval + fill!(colptr_T, 0) + colptr_T[1] = 1 + for i=1:nnzS + @inbounds colptr_T[rowval_S[i]+1] += 1 + end + cumsum!(colptr_T, colptr_T) w = copy(colptr_T) - @inbounds for j = 1:mT, p = colptr_S[j]:(colptr_S[j+1]-1) + @inbounds for j = 1:nS, p = colptr_S[j]:(colptr_S[j+1]-1) ind = rowval_S[p] q = w[ind] w[ind] += 1 @@ -146,43 +151,41 @@ function transpose!{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, T::SparseMatrixCSC{Tv,Ti}) nzval_T[q] = nzval_S[p] end - return SparseMatrixCSC(mT, nT, colptr_T, rowval_T, nzval_T) + return T end function transpose{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) (nT, mT) = size(S) - nnzS = nnz(S) - rowval_S = S.rowval - + nnzS = nnz(S) + colptr_T = Array(Ti, nT+1) rowval_T = Array(Ti, nnzS) nzval_T = Array(Tv, nnzS) - colptr_T = zeros(Ti, nT+1) - colptr_T[1] = 1 - @simd for i=1:nnz(S) - @inbounds colptr_T[rowval_S[i]+1] += 1 - end - colptr_T = cumsum(colptr_T) - T = SparseMatrixCSC(mT, nT, colptr_T, rowval_T, nzval_T) return transpose!(S, T) end -# NOTE: When calling ctranspose!(S,T), the colptr in the result matrix T must be set up -# by counting the nonzeros in every row of S. function ctranspose!{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, T::SparseMatrixCSC{Tv,Ti}) + (mS, nS) = size(S) + nnzS = nnz(S) + colptr_S = S.colptr + rowval_S = S.rowval + nzval_S = S.nzval + (mT, nT) = size(T) colptr_T = T.colptr rowval_T = T.rowval nzval_T = T.nzval - nnzS = nnz(S) - colptr_S = S.colptr - rowval_S = S.rowval - nzval_S = S.nzval + fill!(colptr_T, 0) + colptr_T[1] = 1 + for i=1:nnzS + @inbounds colptr_T[rowval_S[i]+1] += 1 + end + cumsum!(colptr_T, colptr_T) w = copy(colptr_T) - @inbounds for j = 1:mT, p = colptr_S[j]:(colptr_S[j+1]-1) + @inbounds for j = 1:nS, p = colptr_S[j]:(colptr_S[j+1]-1) ind = rowval_S[p] q = w[ind] w[ind] += 1 @@ -190,24 +193,16 @@ function ctranspose!{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, T::SparseMatrixCSC{Tv,Ti} nzval_T[q] = conj(nzval_S[p]) end - return SparseMatrixCSC(mT, nT, colptr_T, rowval_T, nzval_T) + return T end function ctranspose{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) (nT, mT) = size(S) nnzS = nnz(S) - rowval_S = S.rowval - + colptr_T = Array(Ti, nT+1) rowval_T = Array(Ti, nnzS) nzval_T = Array(Tv, nnzS) - colptr_T = zeros(Ti, nT+1) - colptr_T[1] = 1 - @inbounds for i=1:nnz(S) - colptr_T[rowval_S[i]+1] += 1 - end - colptr_T = cumsum(colptr_T) - T = SparseMatrixCSC(mT, nT, colptr_T, rowval_T, nzval_T) return ctranspose!(S, T) end @@ -363,8 +358,8 @@ function fkeep!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, f, other) end droptol!(A::SparseMatrixCSC, tol) = fkeep!(A, (i,j,x,other)->abs(x)>other, tol) -dropzeros!(A::SparseMatrixCSC) = fkeep!(A, (i,j,x,other)->x!=0, None) -triu!(A::SparseMatrixCSC) = fkeep!(A, (i,j,x,other)->(j>=i), None) +dropzeros!(A::SparseMatrixCSC) = fkeep!(A, (i,j,x,other)->x!=0, nothing) +triu!(A::SparseMatrixCSC) = fkeep!(A, (i,j,x,other)->(j>=i), nothing) triu(A::SparseMatrixCSC) = triu!(copy(A)) -tril!(A::SparseMatrixCSC) = fkeep!(A, (i,j,x,other)->(i>=j), None) +tril!(A::SparseMatrixCSC) = fkeep!(A, (i,j,x,other)->(i>=j), nothing) tril(A::SparseMatrixCSC) = tril!(copy(A)) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index b3e40799aef4a..e65a4353addf2 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -431,24 +431,24 @@ end # Operations that may map nonzeros to zero, and zero to zero # Result is sparse -for (op, restype) in ((:iceil, Int), (:ceil, Nothing), - (:ifloor, Int), (:floor, Nothing), - (:itrunc, Int), (:trunc, Nothing), - (:iround, Int), (:round, Nothing), - (:sin, Nothing), (:tan, Nothing), - (:sinh, Nothing), (:tanh, Nothing), - (:asin, Nothing), (:atan, Nothing), - (:asinh, Nothing), (:atanh, Nothing), - (:sinpi, Nothing), (:cosc, Nothing), - (:sind, Nothing), (:tand, Nothing), - (:asind, Nothing), (:atand, Nothing) ) +for (op, restype) in ((:iceil, Int), (:ceil, Void), + (:ifloor, Int), (:floor, Void), + (:itrunc, Int), (:trunc, Void), + (:iround, Int), (:round, Void), + (:sin, Void), (:tan, Void), + (:sinh, Void), (:tanh, Void), + (:asin, Void), (:atan, Void), + (:asinh, Void), (:atanh, Void), + (:sinpi, Void), (:cosc, Void), + (:sind, Void), (:tand, Void), + (:asind, Void), (:atand, Void) ) @eval begin function ($op){Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}) nfilledA = nnz(A) colptrB = Array(Ti, A.n+1) rowvalB = Array(Ti, nfilledA) - nzvalB = Array($(restype==Nothing ? (:Tv) : restype), nfilledA) + nzvalB = Array($(restype==Void ? (:Tv) : restype), nfilledA) k = 0 # number of additional zeros introduced by op(A) @inbounds for i = 1 : A.n @@ -515,7 +515,7 @@ end ## Binary arithmetic and boolean operators -for (op, restype) in ( (:+, Nothing), (:-, Nothing), (:.*, Nothing), +for (op, restype) in ( (:+, Void), (:-, Void), (:.*, Void), (:(.<), Bool) ) @eval begin @@ -538,7 +538,7 @@ for (op, restype) in ( (:+, Nothing), (:-, Nothing), (:.*, Nothing), nnzS = nnz(A) + nnz(B) colptrS = Array(Ti, A.n+1) rowvalS = Array(Ti, nnzS) - nzvalS = Array($(restype==Nothing ? (:Tv) : restype), nnzS) + nzvalS = Array($(restype==Void ? (:Tv) : restype), nnzS) z = zero(Tv) diff --git a/base/special/trig.jl b/base/special/trig.jl index 0ca23285c70ce..7fc56ddd20ba0 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -1,3 +1,101 @@ +immutable DoubleFloat64 + hi::Float64 + lo::Float64 +end +immutable DoubleFloat32 + hi::Float64 +end + +# kernel_* functions are only valid for |x| < pi/4 = 0.7854 +# translated from openlibm code: k_sin.c, k_cos.c, k_sinf.c, k_cosf.c +# which are made available under the following licence: + +## Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +## +## Developed at SunPro, a Sun Microsystems, Inc. business. +## Permission to use, copy, modify, and distribute this +## software is freely granted, provided that this notice +## is preserved. + +function sin_kernel(x::DoubleFloat64) + S1 = -1.66666666666666324348e-01 + S2 = 8.33333333332248946124e-03 + S3 = -1.98412698298579493134e-04 + S4 = 2.75573137070700676789e-06 + S5 = -2.50507602534068634195e-08 + S6 = 1.58969099521155010221e-10 + + z = x.hi*x.hi + w = z*z + r = S2+z*(S3+z*S4) + z*w*(S5+z*S6) + v = z*x.hi + x.hi-((z*(0.5*x.lo-v*r)-x.lo)-v*S1) +end + +function cos_kernel(x::DoubleFloat64) + C1 = 4.16666666666666019037e-02 + C2 = -1.38888888888741095749e-03 + C3 = 2.48015872894767294178e-05 + C4 = -2.75573143513906633035e-07 + C5 = 2.08757232129817482790e-09 + C6 = -1.13596475577881948265e-11 + + z = x.hi*x.hi + w = z*z + r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6)) + hz = 0.5*z + w = 1.0-hz + w + (((1.0-w)-hz) + (z*r-x.hi*x.lo)) +end + +function sin_kernel(x::DoubleFloat32) + S1 = -0x15555554cbac77.0p-55 + S2 = 0x111110896efbb2.0p-59 + S3 = -0x1a00f9e2cae774.0p-65 + S4 = 0x16cd878c3b46a7.0p-71 + + z = x.hi*x.hi + w = z*z + r = S3+z*S4 + s = z*x.hi + float32((x.hi + s*(S1+z*S2)) + s*w*r) +end + +function cos_kernel(x::DoubleFloat32) + C0 = -0x1ffffffd0c5e81.0p-54 + C1 = 0x155553e1053a42.0p-57 + C2 = -0x16c087e80f1e27.0p-62 + C3 = 0x199342e0ee5069.0p-68 + + z = x.hi*x.hi + w = z*z + r = C2+z*C3 + float32(((1.0+z*C0) + w*C1) + (w*z)*r) +end + +# fallback methods +sin_kernel(x::Real) = sin(x) +cos_kernel(x::Real) = cos(x) + +# multiply in extended precision +function mulpi_ext(x::Float64) + m = 3.141592653589793 + m_hi = 3.1415926218032837 + m_lo = 3.178650954705639e-8 + + u = 134217729.0*x # 0x1p27 + 1 + x_hi = u-(u-x) + x_lo = x-x_hi + + y_hi = m*x + y_lo = x_hi * m_lo + (x_lo* m_hi + ((x_hi*m_hi-y_hi) + x_lo*m_lo)) + + DoubleFloat64(y_hi,y_lo) +end +mulpi_ext(x::Float32) = DoubleFloat32(pi*float64(x)) +mulpi_ext(x::Rational) = mulpi_ext(float(x)) +mulpi_ext(x::Real) = pi*x # Fallback + function sinpi(x::Real) if isinf(x) return throw(DomainError()) @@ -5,23 +103,27 @@ function sinpi(x::Real) return nan(x) end - rx = copysign(float(rem(x,2)),x) + rx = copysign(rem(x,2),x) arx = abs(rx) - if arx < oftype(rx,0.25) - return sin(pi*rx) + if rx == zero(rx) + return copysign(float(zero(rx)),x) + elseif arx < oftype(rx,0.25) + return sin_kernel(mulpi_ext(rx)) elseif arx <= oftype(rx,0.75) - arx = oftype(rx,0.5) - arx - return copysign(cos(pi*arx),rx) + y = mulpi_ext(oftype(rx,0.5) - arx) + return copysign(cos_kernel(y),rx) + elseif arx == one(x) + return copysign(float(zero(rx)),rx) elseif arx < oftype(rx,1.25) - rx = (one(rx) - arx)*sign(rx) - return sin(pi*rx) + y = mulpi_ext((one(rx) - arx)*sign(rx)) + return sin_kernel(y) elseif arx <= oftype(rx,1.75) - arx = oftype(rx,1.5) - arx - return -copysign(cos(pi*arx),rx) + y = mulpi_ext(oftype(rx,1.5) - arx) + return -copysign(cos_kernel(y),rx) else - rx = rx - copysign(oftype(rx,2.0),rx) - return sin(pi*rx) + y = mulpi_ext(rx - copysign(oftype(rx,2.0),rx)) + return sin_kernel(y) end end @@ -35,24 +137,24 @@ function cospi(x::Real) rx = abs(float(rem(x,2))) if rx <= oftype(rx,0.25) - return cos(pi*rx) + return cos_kernel(mulpi_ext(rx)) elseif rx < oftype(rx,0.75) - rx = oftype(rx,0.5) - rx - return sin(pi*rx) + y = mulpi_ext(oftype(rx,0.5) - rx) + return sin_kernel(y) elseif rx <= oftype(rx,1.25) - rx = one(rx) - rx - return -cos(pi*rx) + y = mulpi_ext(one(rx) - rx) + return -cos_kernel(y) elseif rx < oftype(rx,1.75) - rx = rx - oftype(rx,1.5) - return sin(pi*rx) + y = mulpi_ext(rx - oftype(rx,1.5)) + return sin_kernel(y) else - rx = oftype(rx,2.0) - rx - return cos(pi*rx) + y = mulpi_ext(oftype(rx,2.0) - rx) + return cos_kernel(y) end end -sinpi(x::Integer) = zero(x) -cospi(x::Integer) = isodd(x) ? -one(x) : one(x) +sinpi(x::Integer) = x >= 0 ? zero(float(x)) : -zero(float(x)) +cospi(x::Integer) = isodd(x) ? -one(float(x)) : one(float(x)) function sinpi(z::Complex) zr, zi = reim(z) @@ -111,6 +213,25 @@ for (fa, fainv) in ((:asec, :acos), (:acsc, :asin), (:acot, :atan), end end + +# multiply in extended precision +function deg2rad_ext(x::Float64) + m = 0.017453292519943295 + m_hi = 0.01745329238474369 + m_lo = 1.3519960527851425e-10 + + u = 134217729.0*x # 0x1p27 + 1 + x_hi = u-(u-x) + x_lo = x-x_hi + + y_hi = m*x + y_lo = x_hi * m_lo + (x_lo* m_hi + ((x_hi*m_hi-y_hi) + x_lo*m_lo)) + + DoubleFloat64(y_hi,y_lo) +end +deg2rad_ext(x::Float32) = DoubleFloat32(deg2rad(float64(x))) +deg2rad_ext(x::Real) = deg2rad(x) # Fallback + function sind(x::Real) if isinf(x) return throw(DomainError()) @@ -121,20 +242,24 @@ function sind(x::Real) rx = copysign(float(rem(x,360)),x) arx = abs(rx) - if arx < oftype(rx,45.0) - return sin(deg2rad(rx)) - elseif arx <= oftype(rx,135.0) - arx = oftype(rx,90.0) - arx - return copysign(cos(deg2rad(arx)),rx) - elseif arx < oftype(rx,225.0) - rx = (oftype(rx,180.0) - arx)*sign(rx) - return sin(deg2rad(rx)) - elseif arx <= 315.0 - arx = oftype(rx,270.0) - arx - return -copysign(cos(deg2rad(arx)),rx) + if rx == zero(rx) + return rx + elseif arx < oftype(rx,45) + return sin_kernel(deg2rad_ext(rx)) + elseif arx <= oftype(rx,135) + y = deg2rad_ext(oftype(rx,90) - arx) + return copysign(cos_kernel(y),rx) + elseif arx == oftype(rx,180) + return copysign(zero(rx),rx) + elseif arx < oftype(rx,225) + y = deg2rad_ext((oftype(rx,180) - arx)*sign(rx)) + return sin_kernel(y) + elseif arx <= oftype(rx,315) + y = deg2rad_ext(oftype(rx,270) - arx) + return -copysign(cos_kernel(y),rx) else - rx = rx - copysign(oftype(rx,360.0),rx) - return sin(deg2rad(rx)) + y = deg2rad_ext(rx - copysign(oftype(rx,360),rx)) + return sin_kernel(y) end end @vectorize_1arg Real sind @@ -148,20 +273,20 @@ function cosd(x::Real) rx = abs(float(rem(x,360))) - if rx <= oftype(rx,45.0) - return cos(deg2rad(rx)) - elseif rx < oftype(rx,135.0) - rx = oftype(rx,90.0) - rx - return sin(deg2rad(rx)) - elseif rx <= oftype(rx,225.0) - rx = oftype(rx,180.0) - rx - return -cos(deg2rad(rx)) - elseif rx < oftype(rx,315.0) - rx = rx - oftype(rx,270.0) - return sin(deg2rad(rx)) + if rx <= oftype(rx,45) + return cos_kernel(deg2rad_ext(rx)) + elseif rx < oftype(rx,135) + y = deg2rad_ext(oftype(rx,90) - rx) + return sin_kernel(y) + elseif rx <= oftype(rx,225) + y = deg2rad_ext(oftype(rx,180) - rx) + return -cos_kernel(y) + elseif rx < oftype(rx,315) + y = deg2rad_ext(rx - oftype(rx,270)) + return sin_kernel(y) else - rx = oftype(rx,360.0) - rx - return cos(deg2rad(rx)) + y = deg2rad_ext(oftype(rx,360) - rx) + return cos_kernel(y) end end @vectorize_1arg Real cosd diff --git a/base/subarray.jl b/base/subarray.jl index 9eaf962fa11a2..139ffb18850b7 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -400,7 +400,7 @@ stride(s::SubArray, i::Integer) = i <= length(s.strides) ? s.strides[i] : s.stri convert{T}(::Type{Ptr{T}}, x::SubArray{T}) = pointer(x.parent) + (x.first_index-1)*sizeof(T) -convert{T}(::Type{Ptr{None}}, x::SubArray{T}) = convert(Ptr{None}, convert(Ptr{T},x)) +convert{T}(::Type{Ptr{Void}}, x::SubArray{T}) = convert(Ptr{Void}, convert(Ptr{T},x)) convert{T,S,N}(::Type{Array{T,N}},A::SubArray{S,N}) = copy!(Array(T,size(A)), A) pointer(s::SubArray, i::Int) = pointer(s, ind2sub(size(s), i)) diff --git a/base/sysimg.jl b/base/sysimg.jl index 3c69dbc01fea1..2c96e8ac5d835 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -270,6 +270,9 @@ importall .Profile include("Dates.jl") import .Dates: Date, DateTime, now +# nullable types +include("nullable.jl") + function __init__() # Base library init reinit_stdio() diff --git a/contrib/Julia_Notepad++.xml b/contrib/Julia_Notepad++.xml index 990e86ad50af8..7dbb125adb3b0 100644 --- a/contrib/Julia_Notepad++.xml +++ b/contrib/Julia_Notepad++.xml @@ -12,7 +12,7 @@ end "00"00 abstract bitstype break ccall const continue export global import importall in local macro module baremodule return typealias using - AbstractArray AbstractMatrix AbstractSparseMatrix AbstractVector Any Array ASCIIString Associative AsyncStream BitArray BigFloat BigInt BitMatrix BitVector Bool ByteString Char CharString Colon Complex Complex64 Complex128 ComplexPair DArray Dict Dims EachLine EnvHash Exception Expr FileOffset Filter Float Float32 Float64 Function ObjectIdDict Int Int8 Int16 Int32 Int64 Int128 Integer IntSet ImaginaryUnit IO IOBuffer IOStream LocalProcess Matrix Nothing None NTuple Number ObjectIdDict OrdinalRange PipeBuffer ProcessGroup Ptr Range Range1 RangeIndex Ranges Rational Real Regex RegexMatch RegexMatchIterator RemoteRef RepString RevString Reverse RopeString Set Signed SparseMatrixCSC SpawnNullStream StridedArray StridedMatrix StridedVecOrMat StridedVector String SubArray SubDArray SubOrDArray SubString Symbol SymTridiagonal Task TcpSocket Tridiagonal Tuple Type Uint Uint8 Uint16 Uint32 Uint64 Uint128 Union Unsigned UTF8String UVError VecOrMat Vector VersionNumber Void WeakKeyDict WeakRef Woodbury Zip Stat Factorization BunchKaufman CholeskyDense CholeskyPivotedDense LUDense LUTridiagonal LDLTTridiagonal QRDense QRPivotedDense SVDDense GSVDDense InsertionSort QuickSort MergeSort TimSort Cchar Cuchar Cshort Cushort Cint Cuint Clong Culong Cptrdiff_t Csize_t Clonglong Culonglong Cintmax_t Cuintmax_t Cfloat Cdouble ArgumentError DisconnectException EOFError ErrorException KeyError LoadError MethodError ParseError SystemError TypeError + AbstractArray AbstractMatrix AbstractSparseMatrix AbstractVector Any Array ASCIIString Associative AsyncStream BitArray BigFloat BigInt BitMatrix BitVector Bool ByteString Char CharString Colon Complex Complex64 Complex128 ComplexPair DArray Dict Dims EachLine EnvHash Exception Expr FileOffset Filter Float Float32 Float64 Function ObjectIdDict Int Int8 Int16 Int32 Int64 Int128 Integer IntSet ImaginaryUnit IO IOBuffer IOStream LocalProcess Matrix NTuple Number ObjectIdDict OrdinalRange PipeBuffer ProcessGroup Ptr Range Range1 RangeIndex Ranges Rational Real Regex RegexMatch RegexMatchIterator RemoteRef RepString RevString Reverse RopeString Set Signed SparseMatrixCSC SpawnNullStream StridedArray StridedMatrix StridedVecOrMat StridedVector String SubArray SubDArray SubOrDArray SubString Symbol SymTridiagonal Task TcpSocket Tridiagonal Tuple Type Uint Uint8 Uint16 Uint32 Uint64 Uint128 Union Unsigned UTF8String UVError VecOrMat Vector VersionNumber Void WeakKeyDict WeakRef Woodbury Zip Stat Factorization BunchKaufman CholeskyDense CholeskyPivotedDense LUDense LUTridiagonal LDLTTridiagonal QRDense QRPivotedDense SVDDense GSVDDense InsertionSort QuickSort MergeSort TimSort Cchar Cuchar Cshort Cushort Cint Cuint Clong Culong Cptrdiff_t Csize_t Clonglong Culonglong Cintmax_t Cuintmax_t Cfloat Cdouble ArgumentError DisconnectException EOFError ErrorException KeyError LoadError MethodError ParseError SystemError TypeError diff --git a/contrib/julia-mode.el b/contrib/julia-mode.el index 1ba68006108ed..59c14e040660e 100644 --- a/contrib/julia-mode.el +++ b/contrib/julia-mode.el @@ -145,7 +145,7 @@ (defconst julia-font-lock-keywords (list - '("\\<\\(\\|Uint\\(8\\|16\\|32\\|64\\|128\\)\\|Int\\(8\\|16\\|32\\|64\\|128\\)\\|BigInt\\|Integer\\|BigFloat\\|FloatingPoint\\|Float16\\|Float32\\|Float64\\|Complex128\\|Complex64\\|ComplexPair\\|Bool\\|Char\\|DataType\\|Number\\|Real\\|Int\\|Uint\\|Array\\|DArray\\|AbstractArray\\|AbstractVector\\|AbstractMatrix\\|AbstractSparseMatrix\\|SubArray\\|StridedArray\\|StridedVector\\|StridedMatrix\\|VecOrMat\\|StridedVecOrMat\\|DenseArray\\|Range\\|OrdinalRange\\|StepRange\\|UnitRange\\|FloatRange\\|SparseMatrixCSC\\|Tuple\\|NTuple\\|Symbol\\|Function\\|Vector\\|Matrix\\|Union\\|Type\\|Any\\|Complex\\|None\\|String\\|Ptr\\|Void\\|Exception\\|Task\\|Signed\\|Unsigned\\|Associative\\|Dict\\|IO\\|IOStream\\|Rational\\|Regex\\|RegexMatch\\|Set\\|IntSet\\|ASCIIString\\|UTF8String\\|ByteString\\|Expr\\|WeakRef\\|Nothing\\|ObjectIdDict\\|SubString\\)\\>" . + '("\\<\\(\\|Uint\\(8\\|16\\|32\\|64\\|128\\)\\|Int\\(8\\|16\\|32\\|64\\|128\\)\\|BigInt\\|Integer\\|BigFloat\\|FloatingPoint\\|Float16\\|Float32\\|Float64\\|Complex128\\|Complex64\\|ComplexPair\\|Bool\\|Char\\|DataType\\|Number\\|Real\\|Int\\|Uint\\|Array\\|DArray\\|AbstractArray\\|AbstractVector\\|AbstractMatrix\\|AbstractSparseMatrix\\|SubArray\\|StridedArray\\|StridedVector\\|StridedMatrix\\|VecOrMat\\|StridedVecOrMat\\|DenseArray\\|Range\\|OrdinalRange\\|StepRange\\|UnitRange\\|FloatRange\\|SparseMatrixCSC\\|Tuple\\|NTuple\\|Symbol\\|Function\\|Vector\\|Matrix\\|Union\\|Type\\|Any\\|Complex\\|String\\|Ptr\\|Void\\|Exception\\|Task\\|Signed\\|Unsigned\\|Associative\\|Dict\\|IO\\|IOStream\\|Rational\\|Regex\\|RegexMatch\\|Set\\|IntSet\\|ASCIIString\\|UTF8String\\|ByteString\\|Expr\\|WeakRef\\|ObjectIdDict\\|SubString\\)\\>" . font-lock-type-face) (cons julia-keyword-regex 'font-lock-keyword-face) (cons julia-macro-regex 'font-lock-keyword-face) diff --git a/contrib/julia.desktop b/contrib/julia.desktop new file mode 100644 index 0000000000000..6b41981354769 --- /dev/null +++ b/contrib/julia.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=Julia +Comment=High-level, high-performance dynamic language for technical computing +Exec=julia +Icon=julia +Terminal=true +Type=Application +Categories=Development;ComputerScience;Building;Science;Math;NumericalAnalysis;ParallelComputing;DataVisualization;ConsoleOnly; diff --git a/contrib/julia.lang b/contrib/julia.lang index cd0730d86a281..56eb971640cd9 100644 --- a/contrib/julia.lang +++ b/contrib/julia.lang @@ -232,7 +232,7 @@ - Any|None|Nothing|Void + Any|Void Type(Constructor|Name|Var|_Array)?|(Union|Data|NonTuple)Type (Abstract|Strided|Bit)?(Array|Matrix|Vector) Abstract(Cmd|RNG|SparseMatrix) diff --git a/contrib/julia.svg b/contrib/julia.svg new file mode 100644 index 0000000000000..b0b03de8a1f09 --- /dev/null +++ b/contrib/julia.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/julia.xml b/contrib/julia.xml index 78286dcd70110..4d538c2aa3376 100644 --- a/contrib/julia.xml +++ b/contrib/julia.xml @@ -37,6 +37,7 @@ do for function + stagedfunction if immutable let @@ -141,8 +142,6 @@ LU MathConst Matrix - Nothing - None NTuple Number ObjectIdDict diff --git a/deps/Makefile b/deps/Makefile index 4eecda4ccd2c7..84bbd40e15fbf 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -194,6 +194,9 @@ LLVM_COMPILER_RT_TAR= else ifeq ($(LLVM_VER), 3.3) LLVM_CLANG_TAR=cfe-$(LLVM_VER).src.tar.gz LLVM_COMPILER_RT_TAR=compiler-rt-$(LLVM_VER).src.tar.gz +else ifeq ($(LLVM_VER), 3.5.0) +LLVM_CLANG_TAR=cfe-$(LLVM_VER).src.tar.xz +LLVM_COMPILER_RT_TAR=compiler-rt-$(LLVM_VER).src.tar.xz else LLVM_CLANG_TAR=clang-$(LLVM_VER).src.tar.gz LLVM_COMPILER_RT_TAR=compiler-rt-$(LLVM_VER).src.tar.gz @@ -1466,7 +1469,7 @@ GMP_SRC_TARGET = gmp-$(GMP_VER)/.libs/libgmp.$(SHLIB_EXT) GMP_OBJ_TARGET = $(build_shlibdir)/libgmp.$(SHLIB_EXT) gmp-$(GMP_VER).tar.bz2: - $(JLDOWNLOAD) $@ ftp://ftp.gmplib.org/pub/gmp-$(GMP_VER)/$@ + $(JLDOWNLOAD) $@ https://gmplib.org/download/gmp/$@ gmp-$(GMP_VER)/configure: gmp-$(GMP_VER).tar.bz2 $(JLCHECKSUM) $< $(TAR) jxf $< diff --git a/doc/devdocs/index.rst b/doc/devdocs/index.rst index eb8a544b061d5..7e35f83c195d9 100644 --- a/doc/devdocs/index.rst +++ b/doc/devdocs/index.rst @@ -10,3 +10,4 @@ :maxdepth: 1 cartesian + meta diff --git a/doc/devdocs/meta.rst b/doc/devdocs/meta.rst new file mode 100644 index 0000000000000..279b5d51f5e19 --- /dev/null +++ b/doc/devdocs/meta.rst @@ -0,0 +1,55 @@ +.. currentmodule:: Base + +.. _devdocs-meta: + +Talking to the compiler (the ``:meta`` mechanism) +================================================= + +In some circumstances, one might wish to provide hints or instructions +that a given block of code has special properties: you might always +want to inline it, or you might want to turn on special compiler +optimization passes. Starting with version 0.4, julia has a +convention that these instructions can be placed inside a ``:meta`` +expression, which must be the first expression in the body of a +function. + +``:meta`` expressions are created with macros. As an example, consider +the implementation of the ``@inline`` macro:: + + macro inline(ex) + esc(_inline(ex)) + end + + _inline(ex::Expr) = pushmeta!(ex, :inline) + _inline(arg) = arg + +Here, ``ex`` is expected to be an expression defining a function. +A statement like this:: + + @inline function myfunction(x) + x*(x+3) + end + +gets turned into an expression like this:: + + quote + function myfunction(x) + Expr(:meta, :inline) + x*(x+3) + end + end + +``pushmeta!(ex, :symbol)`` appends ``:symbol`` to the end of the +``:meta`` expression, creating a new ``:meta`` expression if +necessary. + +To use the metadata, you have to parse these ``:meta`` expressions. +If your implementation can be performed within Julia, ``popmeta!`` is +very handy: ``popmeta!(body, :symbol)`` will scan a function *body* +expression (one without the function signature) for a ``:meta`` +expression; if ``:symbol`` is present, it will return ``true`` and +remove ``:symbol`` from the arguments of the ``:meta`` expression +(deleting the expression altogether if there are no more arguments). + +Not yet provided is a convenient infrastructure for parsing ``:meta`` +expressions from C++. diff --git a/doc/helpdb.jl b/doc/helpdb.jl index 5df537f887e7b..26b22e64b31ca 100644 --- a/doc/helpdb.jl +++ b/doc/helpdb.jl @@ -30,8 +30,8 @@ ("Base","whos","whos([Module,] [pattern::Regex]) - Print information about exported global variables in a module, optionally - restricted to those matching \"pattern\". + Print information about exported global variables in a module, + optionally restricted to those matching \"pattern\". "), @@ -1611,7 +1611,7 @@ spliced in place of the removed item. To insert \"replacement\" before an index \"n\" without removing - any items, use \"splice(collection, n-1:n, replacement)\". + any items, use \"splice!(collection, n:n-1, replacement)\". "), @@ -1623,7 +1623,7 @@ ordered collection will be spliced in place of the removed items. To insert \"replacement\" before an index \"n\" without removing - any items, use \"splice(collection, n-1:n, replacement)\". + any items, use \"splice!(collection, n:n-1, replacement)\". "), @@ -4516,8 +4516,8 @@ popdisplay(d::Display) ("Base","signbit","signbit(x) - Returns \"1\" if the value of the sign of \"x\" is negative, - otherwise \"0\". + Returns \"true\" if the value of the sign of \"x\" is negative, + otherwise \"false\". "), @@ -5715,17 +5715,17 @@ popdisplay(d::Display) "), -("Base","rand","rand(Int32|Uint32|Int64|Uint64|Int128|Uint128[, dims...]) +("Base","rand","rand(t::Type[, dims...]) - Generate a random integer of the given type. Optionally, generate - an array of random integers of the given type by specifying dims. + Generate a random number or array of random numbes of the given + type. "), ("Base","rand","rand(r[, dims...]) - Generate a random integer in the range \"r\" (for example, \"1:n\" - or \"0:2:10\"). Optionally, generate a random integer array. + Pick a random element or array of random elements from range \"r\" + (for example, \"1:n\" or \"0:2:10\"). "), @@ -5736,13 +5736,6 @@ popdisplay(d::Display) "), -("Base","randbool!","randbool!(A) - - Fill an array with random boolean values. A may be an \"Array\" or - a \"BitArray\". - -"), - ("Base","randn","randn([rng], dims or [dims...]) Generate a normally-distributed random number with mean 0 and @@ -5851,13 +5844,29 @@ popdisplay(d::Display) ("Base","zeros","zeros(type, dims) - Create an array of all zeros of specified type + Create an array of all zeros of specified type. The type defaults + to Float64 if not specified. + +"), + +("Base","zeros","zeros(A) + + Create an array of all zeros with the same element type and shape + as A. "), ("Base","ones","ones(type, dims) - Create an array of all ones of specified type + Create an array of all ones of specified type. The type defaults to + Float64 if not specified. + +"), + +("Base","ones","ones(A) + + Create an array of all ones with the same element type and shape as + A. "), @@ -5873,15 +5882,15 @@ popdisplay(d::Display) "), -("Base","fill","fill(v, dims) +("Base","fill","fill(x, dims) - Create an array filled with \"v\" + Create an array filled with the value \"x\" "), ("Base","fill!","fill!(A, x) - Fill array \"A\" with value \"x\" + Fill the array \"A\" with the value \"x\" "), @@ -9812,15 +9821,15 @@ Millisecond(v) \"Complex{Float64}\" the return type is \"UmfpackLU\". Some examples are shown in the table below. - +-------------------------+---------------------------+------------------------------------------+ - | Type of input \\\"A\\\" | Type of output \\\"F\\\" | Relationship between \\\"F\\\" and \\\"A\\\" | - +-------------------------+---------------------------+------------------------------------------+ - | \\\"Matrix()\\\" | \\\"LU\\\" | \\\"F[:L]*F[:U] == A[F[:p], :]\\\" | - +-------------------------+---------------------------+------------------------------------------+ - | \\\"Tridiagonal()\\\" | \\\"LU{T,Tridiagonal{T}}\\\" | N/A | - +-------------------------+---------------------------+------------------------------------------+ - | \\\"SparseMatrixCSC()\\\" | \\\"UmfpackLU\\\" | \\\"F[:L]*F[:U] == Rs .* A[F[:p], F[:q]]\\\" | - +-------------------------+---------------------------+------------------------------------------+ + +-------------------------+---------------------------+----------------------------------------------+ + | Type of input \\\"A\\\" | Type of output \\\"F\\\" | Relationship between \\\"F\\\" and \\\"A\\\" | + +-------------------------+---------------------------+----------------------------------------------+ + | \\\"Matrix()\\\" | \\\"LU\\\" | \\\"F[:L]*F[:U] == A[F[:p], :]\\\" | + +-------------------------+---------------------------+----------------------------------------------+ + | \\\"Tridiagonal()\\\" | \\\"LU{T,Tridiagonal{T}}\\\" | N/A | + +-------------------------+---------------------------+----------------------------------------------+ + | \\\"SparseMatrixCSC()\\\" | \\\"UmfpackLU\\\" | \\\"F[:L]*F[:U] == F[:Rs] .* A[F[:p], F[:q]]\\\" | + +-------------------------+---------------------------+----------------------------------------------+ The individual components of the factorization \"F\" can be accessed by indexing: @@ -10044,7 +10053,7 @@ Millisecond(v) ("Base","eig","eig(A,[irange,][vl,][vu,][permute=true,][scale=true]) -> D, V - Compute eigenvalues and eigenvectors of \"A\". See \"eigfact()\" + Computes eigenvalues and eigenvectors of \"A\". See \"eigfact()\" for details on the \"balance\" keyword argument. julia> eig([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0]) @@ -10101,10 +10110,12 @@ Millisecond(v) "), -("Base","eigvecs","eigvecs(A, [eigvals,][permute=true,][scale=true]) +("Base","eigvecs","eigvecs(A, [eigvals,][permute=true,][scale=true]) -> Matrix - Returns the eigenvectors of \"A\". The \"permute\" and \"scale\" - keywords are the same as for \"eigfact()\". + Returns a matrix \"M\" whose columns are the eigenvectors of \"A\". + (The \"k``th eigenvector can be obtained from the slice ``M[:, + k]\".) The \"permute\" and \"scale\" keywords are the same as for + \"eigfact()\". For \"SymTridiagonal()\" matrices, if the optional vector of eigenvalues \"eigvals\" is specified, returns the specific @@ -10112,42 +10123,47 @@ Millisecond(v) "), -("Base","eigfact","eigfact(A,[il,][iu,][vl,][vu,][permute=true,][scale=true]) +("Base","eigfact","eigfact(A,[irange,][vl,][vu,][permute=true,][scale=true]) -> Eigen - Compute the eigenvalue decomposition of \"A\" and return an - \"Eigen\" object. If \"F\" is the factorization object, the - eigenvalues can be accessed with \"F[:values]\" and the - eigenvectors with \"F[:vectors]\". The following functions are - available for \"Eigen\" objects: \"inv\", \"det\". + Computes the eigenvalue decomposition of \"A\", returning an + \"Eigen\" factorization object \"F\" which contains the eigenvalues + in \"F[:values]\" and the eigenvectors in the columns of the matrix + \"F[:vectors]\". (The \"k``th eigenvector can be obtained from the + slice ``F[:vectors][:, k]\".) - If \"A\" is \"Symmetric\", \"Hermitian\" or \"SymTridiagonal\", it - is possible to calculate only a subset of the eigenvalues by - specifying either a *UnitRange`* \"irange\" covering indices of the - sorted eigenvalues or a pair \"vl\" and \"vu\" for the lower and - upper boundaries of the eigenvalues. + The following functions are available for \"Eigen\" objects: + \"inv\", \"det\". - For general non-symmetric matrices it is possible to specify how - the matrix is balanced before the eigenvector calculation. The - option \"permute=true\" permutes the matrix to become closer to - upper triangular, and \"scale=true\" scales the matrix by its - diagonal elements to make rows and columns more equal in norm. The - default is \"true\" for both options. + If \"A\" is \"Symmetric()\", \"Hermitian()\" or + \"SymTridiagonal()\", it is possible to calculate only a subset of + the eigenvalues by specifying either a \"UnitRange()\" \"irange\" + covering indices of the sorted eigenvalues or a pair \"vl\" and + \"vu\" for the lower and upper boundaries of the eigenvalues. + + For general nonsymmetric matrices it is possible to specify how the + matrix is balanced before the eigenvector calculation. The option + \"permute=true\" permutes the matrix to become closer to upper + triangular, and \"scale=true\" scales the matrix by its diagonal + elements to make rows and columns more equal in norm. The default + is \"true\" for both options. "), -("Base","eigfact","eigfact(A, B) +("Base","eigfact","eigfact(A, B) -> GeneralizedEigen - Compute the generalized eigenvalue decomposition of \"A\" and \"B\" - and return an \"GeneralizedEigen\" object. If \"F\" is the - factorization object, the eigenvalues can be accessed with - \"F[:values]\" and the eigenvectors with \"F[:vectors]\". + Computes the generalized eigenvalue decomposition of \"A\" and + \"B\", returning a \"GeneralizedEigen\" factorization object \"F\" + which contains the generalized eigenvalues in \"F[:values]\" and + the generalized eigenvectors in the columns of the matrix + \"F[:vectors]\". (The \"k``th generalized eigenvector can be + obtained from the slice ``F[:vectors][:, k]\".) "), ("Base","eigfact!","eigfact!(A[, B]) - \"eigfact!\" is the same as \"eigfact()\", but saves space by - overwriting the input A (and B), instead of creating a copy. + Same as \"eigfact()\", but saves space by overwriting the input + \"A\" (and \"B\"), instead of creating a copy. "), @@ -11052,11 +11068,15 @@ Millisecond(v) "), -("Base.Pkg","init","init() +("Base.Pkg","init","init(meta::String=DEFAULT_META, branch::String=META_BRANCH) Initialize \"Pkg.dir()\" as a package directory. This will be done automatically when the \"JULIA_PKGDIR\" is not set and - \"Pkg.dir()\" uses its default value. + \"Pkg.dir()\" uses its default value. As part of this process, + clones a local METADATA git repository from the site and branch + specified by its arguments, which are typically not provided. + Explicit (non-default) arguments can be used to support a custom + METADATA setup. "), diff --git a/doc/index.rst b/doc/index.rst index 27b3a23ab0bf9..be43ea4f9f90a 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -80,3 +80,4 @@ Developer Documentation :maxdepth: 1 devdocs/cartesian + devdocs/meta diff --git a/doc/manual/arrays.rst b/doc/manual/arrays.rst index cbcc3c67e71bb..ed4bae108ae71 100644 --- a/doc/manual/arrays.rst +++ b/doc/manual/arrays.rst @@ -330,8 +330,8 @@ operator should be used for elementwise operations. 5. Binary Boolean or bitwise — ``&``, ``|``, ``$`` Some operators without dots operate elementwise anyway when one argument is a -scalar. These operators are ``*``, ``/``, ``\``, and the bitwise -operators. +scalar. These operators are ``*``, ``+``, ``-``, and the bitwise operators. The +operators ``/`` and ``\`` operate elementwise when the denominator is a scalar. Note that comparisons such as ``==`` operate on whole arrays, giving a single boolean answer. Use dot operators for elementwise comparisons. diff --git a/doc/manual/calling-c-and-fortran-code.rst b/doc/manual/calling-c-and-fortran-code.rst index 76ba33df4a540..597c518bd55f8 100644 --- a/doc/manual/calling-c-and-fortran-code.rst +++ b/doc/manual/calling-c-and-fortran-code.rst @@ -245,10 +245,6 @@ Julia type with the same name, prefixed by C. This can help for writing portable +------------------------+-------------------+--------------------------------+ | ``size_t`` | ``Csize_t`` | ``Uint`` | +------------------------+-------------------+--------------------------------+ -| ``complex float`` | ``Ccomplex_float`` (future addition) | -+------------------------+-------------------+--------------------------------+ -| ``complex double`` | ``Ccomplex_double`` (future addition) | -+------------------------+-------------------+--------------------------------+ | ``void`` | | ``Void`` | +------------------------+-------------------+--------------------------------+ | ``void*`` | | ``Ptr{Void}`` | diff --git a/doc/manual/faq.rst b/doc/manual/faq.rst index 4cf8927c40458..f69bf40a07737 100644 --- a/doc/manual/faq.rst +++ b/doc/manual/faq.rst @@ -721,7 +721,7 @@ Do I want to use a release, beta, or nightly version of Julia? You may prefer the release version of Julia if you are looking for a stable code base. Releases generally occur every 6 months, giving you a stable platform for writing code. -You may prefer the beta version of Julia if you don't mind being slightly behind the latest bugfixes and changes, but find the slightly slower rate of changes more appealing. Additionally, these binaries are tested before they are published to ensure they are fully functional. +You may prefer the beta version of Julia if you don't mind being slightly behind the latest bugfixes and changes, but find the slightly faster rate of changes more appealing. Additionally, these binaries are tested before they are published to ensure they are fully functional. You may prefer the nightly version of Julia if you want to take advantage of the latest updates to the language, and don't mind if the version available today occasionally doesn't actually work. diff --git a/doc/manual/index.rst b/doc/manual/index.rst index 389b8b8eea3ba..7143b505296ad 100644 --- a/doc/manual/index.rst +++ b/doc/manual/index.rst @@ -28,6 +28,7 @@ linear-algebra networking-and-streams parallel-computing + nullable-types interacting-with-julia running-external-programs calling-c-and-fortran-code diff --git a/doc/manual/mathematical-operations.rst b/doc/manual/mathematical-operations.rst index 987f813dc412f..c6ce1c6446653 100644 --- a/doc/manual/mathematical-operations.rst +++ b/doc/manual/mathematical-operations.rst @@ -377,7 +377,7 @@ Function Description ``abs(x)`` a positive value with the magnitude of ``x`` ``abs2(x)`` the squared magnitude of ``x`` ``sign(x)`` indicates the sign of ``x``, returning -1, 0, or +1 -``signbit(x)`` indicates whether the sign bit is on (1) or off (0) +``signbit(x)`` indicates whether the sign bit is on (true) or off (false) ``copysign(x,y)`` a value with the magnitude of ``x`` and the sign of ``y`` ``flipsign(x,y)`` a value with the magnitude of ``x`` and the sign of ``x*y`` ================= =========================================================== diff --git a/doc/manual/nullable-types.rst b/doc/manual/nullable-types.rst new file mode 100644 index 0000000000000..fb8efcab97401 --- /dev/null +++ b/doc/manual/nullable-types.rst @@ -0,0 +1,87 @@ +.. _man-nullable-types: + +******************************************* +Nullable Types: Representing Missing Values +******************************************* + +In many settings, you need to interact with a value of type ``T`` that may or +may not exist. To handle these settings, Julia provides a parametric type +called ``Nullable{T}``, which can be thought of as a specialized container +type that can contain either zero or one values. ``Nullable{T}`` provides a +minimal interface designed to ensure that interactions with missing values +are safe. At present, the interface consists of four possible interactions: + +- Construct a ``Nullable`` object. +- Check if an ``Nullable`` object has a missing value. +- Access the value of a ``Nullable`` object with a guarantee that a + ``NullException`` will be thrown if the object's value is missing. +- Access the value of a ``Nullable`` object with a guarantee that a default + value of type ``T`` will be returned if the object's value is missing. + +Constructing ``Nullable`` objects +--------------------------------- + +To construct an object representing a missing value of type ``T``, use the +``Nullable{T}()`` function: + +.. doctest:: + + x1 = Nullable{Int}() + x2 = Nullable{Float64}() + x3 = Nullable{Vector{Int}}() + +To construct an object representing a non-missing value of type ``T``, use the +``Nullable(x::T)`` function: + +.. doctest:: + + x1 = Nullable(1) + x2 = Nullable(1.0) + x3 = Nullable([1, 2, 3]) + +Note the core distinction between these two ways of constructing a ``Nullable`` +object: in one style, you provide a type, ``T``, as a function parameter; in +the other style, you provide a single value of type ``T`` as an argument. + +Checking if an ``Nullable`` object has a value +---------------------------------------------- + +You can check if a ``Nullable`` object has any value using the ``isnull`` +function: + +.. doctest:: + + isnull(Nullable{Float64}()) + isnull(Nullable(0.0)) + +Safely accessing the value of an ``Nullable`` object +---------------------------------------------------- + +You can safely access the value of an ``Nullable`` object using the ``get`` +function: + +.. doctest:: + + get(Nullable{Float64}()) + get(Nullable(1.0)) + +If the value is not present, as it would be for ``Nullable{Float64}``, a +``NullException`` error will be thrown. The error-throwing nature of the +``get`` function ensures that any attempt to access a missing value immediately +fails. + +In cases for which a reasonable default value exists that could be used +when a ``Nullable`` object's value turns out to be missing, you can provide this +default value as a second argument to ``get``: + +.. doctest:: + + get(Nullable{Float64}(), 0) + get(Nullable(1.0), 0) + +Note that this default value will automatically be converted to the type of +the ``Nullable`` object that you attempt to access using the ``get`` function. +For example, in the code shown above the value ``0`` would be automatically +converted to a ``Float64`` value before being returned. The presence of default +replacement values makes it easy to use the ``get`` function to write +type-stable code that interacts with sources of potentially missing values. diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index d4fc26c6f3e79..e96964a9a8861 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -1158,7 +1158,7 @@ Dequeues are shifted down to fill the resulting gap. If specified, replacement values from an ordered collection will be spliced in place of the removed item. - To insert ``replacement`` before an index ``n`` without removing any items, use ``splice(collection, n-1:n, replacement)``. + To insert ``replacement`` before an index ``n`` without removing any items, use ``splice!(collection, n:n-1, replacement)``. .. function:: splice!(collection, range, [replacement]) -> items @@ -1167,7 +1167,7 @@ Dequeues If specified, replacement values from an ordered collection will be spliced in place of the removed items. - To insert ``replacement`` before an index ``n`` without removing any items, use ``splice(collection, n-1:n, replacement)``. + To insert ``replacement`` before an index ``n`` without removing any items, use ``splice!(collection, n:n-1, replacement)``. .. function:: resize!(collection, n) -> collection @@ -3145,7 +3145,7 @@ Mathematical Functions .. function:: signbit(x) - Returns ``1`` if the value of the sign of ``x`` is negative, otherwise ``0``. + Returns ``true`` if the value of the sign of ``x`` is negative, otherwise ``false``. .. function:: flipsign(x, y) @@ -4676,8 +4676,11 @@ Statistics Signal Processing ----------------- -Fast Fourier transform (FFT) functions in Julia are largely implemented by -calling functions from `FFTW `_. +Fast Fourier transform (FFT) functions in Julia are largely +implemented by calling functions from `FFTW +`_. By default, Julia does not use multi-threaded +FFTW. Higher performance may be obtained by experimenting with +multi-threading. Use `FFTW.set_num_threads(np)` to use `np` threads. .. function:: fft(A [, dims]) @@ -4700,6 +4703,10 @@ calling functions from `FFTW `_. A multidimensional FFT simply performs this operation along each transformed dimension of ``A``. + Higher performance is usually possible with multi-threading. Use + `FFTW.set_num_threads(np)` to use `np` threads, if you have `np` + processors. + .. function:: fft!(A [, dims]) Same as :func:`fft`, but operates in-place on ``A``, diff --git a/doc/stdlib/linalg.rst b/doc/stdlib/linalg.rst index 974901ec65e7c..372784952b6a7 100644 --- a/doc/stdlib/linalg.rst +++ b/doc/stdlib/linalg.rst @@ -17,7 +17,7 @@ Linear algebra functions in Julia are largely implemented by calling functions f .. function:: \\(A, B) :noindex: - Matrix division using a polyalgorithm. For input matrices ``A`` and ``B``, the result ``X`` is such that ``A*X == B`` when ``A`` is square. The solver that is used depends upon the structure of ``A``. A direct solver is used for upper- or lower triangular ``A``. For Hermitian ``A`` (equivalent to symmetric ``A`` for non-complex ``A``) the ``BunchKaufman`` factorization is used. Otherwise an LU factorization is used. For rectangular ``A`` the result is the minimum-norm least squares solution computed by reducing ``A`` to bidiagonal form and solving the bidiagonal least squares problem. For sparse, square ``A`` the LU factorization (from UMFPACK) is used. + Matrix division using a polyalgorithm. For input matrices ``A`` and ``B``, the result ``X`` is such that ``A*X == B`` when ``A`` is square. The solver that is used depends upon the structure of ``A``. A direct solver is used for upper- or lower triangular ``A``. For Hermitian ``A`` (equivalent to symmetric ``A`` for non-complex ``A``) the ``BunchKaufman`` factorization is used. Otherwise an LU factorization is used. For rectangular ``A`` the result is the minimum-norm least squares solution computed by a pivoted QR factorization of ``A`` and a rank estimate of A based on the R factor. For sparse, square ``A`` the LU factorization (from UMFPACK) is used. .. function:: dot(x, y) ⋅(x,y) @@ -54,7 +54,7 @@ Linear algebra functions in Julia are largely implemented by calling functions f ----------------------- ------------------------- ---------------------------------------- :func:`Matrix` ``LU`` ``F[:L]*F[:U] == A[F[:p], :]`` :func:`Tridiagonal` ``LU{T,Tridiagonal{T}}`` N/A - :func:`SparseMatrixCSC` ``UmfpackLU`` ``F[:L]*F[:U] == Rs .* A[F[:p], F[:q]]`` + :func:`SparseMatrixCSC` ``UmfpackLU`` ``F[:L]*F[:U] == F[:Rs] .* A[F[:p], F[:q]]`` ======================= ========================= ======================================== The individual components of the factorization ``F`` can be accessed by indexing: @@ -183,7 +183,8 @@ Linear algebra functions in Julia are largely implemented by calling functions f .. function:: eig(A,[irange,][vl,][vu,][permute=true,][scale=true]) -> D, V - Compute eigenvalues and eigenvectors of ``A``. See :func:`eigfact` for details on the ``balance`` keyword argument. + Computes eigenvalues and eigenvectors of ``A``. See :func:`eigfact` for + details on the ``balance`` keyword argument. .. doctest:: @@ -194,19 +195,31 @@ Linear algebra functions in Julia are largely implemented by calling functions f 0.0 1.0 0.0 0.0 0.0 1.0) - ``eig`` is a wrapper around :func:`eigfact`, extracting all parts of the factorization to a tuple; where possible, using :func:`eigfact` is recommended. + ``eig`` is a wrapper around :func:`eigfact`, extracting all parts of the + factorization to a tuple; where possible, using :func:`eigfact` is + recommended. .. function:: eig(A, B) -> D, V Computes generalized eigenvalues and vectors of ``A`` with respect to ``B``. - ``eig`` is a wrapper around :func:`eigfact`, extracting all parts of the factorization to a tuple; where possible, using :func:`eigfact` is recommended. + ``eig`` is a wrapper around :func:`eigfact`, extracting all parts of the + factorization to a tuple; where possible, using :func:`eigfact` is + recommended. .. function:: eigvals(A,[irange,][vl,][vu]) - Returns the eigenvalues of ``A``. If ``A`` is :func:`Symmetric`, :func:`Hermitian` or :func:`SymTridiagonal`, it is possible to calculate only a subset of the eigenvalues by specifying either a :func:`UnitRange` ``irange`` covering indices of the sorted eigenvalues, or a pair ``vl`` and ``vu`` for the lower and upper boundaries of the eigenvalues. + Returns the eigenvalues of ``A``. If ``A`` is :func:`Symmetric`, + :func:`Hermitian` or :func:`SymTridiagonal`, it is possible to calculate + only a subset of the eigenvalues by specifying either a :func:`UnitRange` + ``irange`` covering indices of the sorted eigenvalues, or a pair ``vl`` and + ``vu`` for the lower and upper boundaries of the eigenvalues. - For general non-symmetric matrices it is possible to specify how the matrix is balanced before the eigenvector calculation. The option ``permute=true`` permutes the matrix to become closer to upper triangular, and ``scale=true`` scales the matrix by its diagonal elements to make rows and columns more equal in norm. The default is ``true`` for both options. + For general non-symmetric matrices it is possible to specify how the matrix + is balanced before the eigenvector calculation. The option ``permute=true`` + permutes the matrix to become closer to upper triangular, and ``scale=true`` + scales the matrix by its diagonal elements to make rows and columns more + equal in norm. The default is ``true`` for both options. .. function:: eigmax(A) @@ -216,28 +229,50 @@ Linear algebra functions in Julia are largely implemented by calling functions f Returns the smallest eigenvalue of ``A``. -.. function:: eigvecs(A, [eigvals,][permute=true,][scale=true]) +.. function:: eigvecs(A, [eigvals,][permute=true,][scale=true]) -> Matrix - Returns the eigenvectors of ``A``. + Returns a matrix ``M`` whose columns are the eigenvectors of ``A``. + (The ``k``th eigenvector can be obtained from the slice ``M[:, k]``.) The ``permute`` and ``scale`` keywords are the same as for :func:`eigfact`. - For :func:`SymTridiagonal` matrices, if the optional vector of eigenvalues ``eigvals`` is specified, returns the specific corresponding eigenvectors. + For :func:`SymTridiagonal` matrices, if the optional vector of eigenvalues + ``eigvals`` is specified, returns the specific corresponding eigenvectors. -.. function:: eigfact(A,[irange,][vl,][vu,][permute=true,][scale=true]) +.. function:: eigfact(A,[irange,][vl,][vu,][permute=true,][scale=true]) -> Eigen - Compute the eigenvalue decomposition of ``A`` and return an ``Eigen`` object. If ``F`` is the factorization object, the eigenvalues can be accessed with ``F[:values]`` and the eigenvectors with ``F[:vectors]``. The following functions are available for ``Eigen`` objects: ``inv``, ``det``. + Computes the eigenvalue decomposition of ``A``, returning an ``Eigen`` + factorization object ``F`` which contains the eigenvalues in ``F[:values]`` + and the eigenvectors in the columns of the matrix ``F[:vectors]``. (The + ``k``th eigenvector can be obtained from the slice ``F[:vectors][:, k]``.) + + The following functions are available for ``Eigen`` objects: ``inv``, + ``det``. - If ``A`` is :func:`Symmetric`, :func:`Hermitian` or :func:`SymTridiagonal`, it is possible to calculate only a subset of the eigenvalues by specifying either a :func:`UnitRange` ``irange`` covering indices of the sorted eigenvalues or a pair ``vl`` and ``vu`` for the lower and upper boundaries of the eigenvalues. + If ``A`` is :func:`Symmetric`, :func:`Hermitian` or :func:`SymTridiagonal`, + it is possible to calculate only a subset of the eigenvalues by specifying + either a :func:`UnitRange` ``irange`` covering indices of the sorted + eigenvalues or a pair ``vl`` and ``vu`` for the lower and upper boundaries + of the eigenvalues. - For general non-symmetric matrices it is possible to specify how the matrix is balanced before the eigenvector calculation. The option ``permute=true`` permutes the matrix to become closer to upper triangular, and ``scale=true`` scales the matrix by its diagonal elements to make rows and columns more equal in norm. The default is ``true`` for both options. + For general nonsymmetric matrices it is possible to specify how the matrix + is balanced before the eigenvector calculation. The option ``permute=true`` + permutes the matrix to become closer to upper triangular, and ``scale=true`` + scales the matrix by its diagonal elements to make rows and columns more + equal in norm. The default is ``true`` for both options. -.. function:: eigfact(A, B) +.. function:: eigfact(A, B) -> GeneralizedEigen - Compute the generalized eigenvalue decomposition of ``A`` and ``B`` and return an ``GeneralizedEigen`` object. If ``F`` is the factorization object, the eigenvalues can be accessed with ``F[:values]`` and the eigenvectors with ``F[:vectors]``. + Computes the generalized eigenvalue decomposition of ``A`` and ``B``, + returning a ``GeneralizedEigen`` factorization object ``F`` which contains + the generalized eigenvalues in ``F[:values]`` and the generalized + eigenvectors in the columns of the matrix ``F[:vectors]``. (The ``k``th + generalized eigenvector can be obtained from the slice ``F[:vectors][:, + k]``.) .. function:: eigfact!(A, [B]) - ``eigfact!`` is the same as :func:`eigfact`, but saves space by overwriting the input A (and B), instead of creating a copy. + Same as :func:`eigfact`, but saves space by overwriting the input ``A`` (and + ``B``), instead of creating a copy. .. function:: hessfact(A) diff --git a/doc/stdlib/pkg.rst b/doc/stdlib/pkg.rst index d784d192b808a..13ebb6266852e 100644 --- a/doc/stdlib/pkg.rst +++ b/doc/stdlib/pkg.rst @@ -18,10 +18,12 @@ to use them, you'll need to prefix each function call with an explicit ``Pkg.``, Equivalent to ``normpath(Pkg.dir(),names...)`` – i.e. it appends path components to the package directory and normalizes the resulting path. In particular, ``Pkg.dir(pkg)`` returns the path to the package ``pkg``. -.. function:: init() +.. function:: init(meta::String=DEFAULT_META, branch::String=META_BRANCH) - Initialize ``Pkg.dir()`` as a package directory. + Initialize ``Pkg.dir()`` as a package directory. This will be done automatically when the ``JULIA_PKGDIR`` is not set and ``Pkg.dir()`` uses its default value. + As part of this process, clones a local METADATA git repository from the site and branch specified by its arguments, which + are typically not provided. Explicit (non-default) arguments can be used to support a custom METADATA setup. .. function:: resolve() diff --git a/src/alloc.c b/src/alloc.c index fe0b02a6c2013..df9392a775520 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -55,6 +55,7 @@ jl_datatype_t *jl_methoderror_type; jl_datatype_t *jl_loaderror_type; jl_datatype_t *jl_undefvarerror_type; jl_datatype_t *jl_pointer_type; +jl_datatype_t *jl_void_type; jl_datatype_t *jl_voidpointer_type; jl_value_t *jl_an_empty_cell=NULL; jl_value_t *jl_stackovf_exception; @@ -91,7 +92,8 @@ jl_sym_t *compositetype_sym; jl_sym_t *type_goto_sym; jl_sym_t *global_sym; jl_sym_t *tuple_sym; jl_sym_t *dot_sym; jl_sym_t *newvar_sym; jl_sym_t *boundscheck_sym; jl_sym_t *copyast_sym; -jl_sym_t *simdloop_sym; +jl_sym_t *simdloop_sym; jl_sym_t *meta_sym; +jl_sym_t *arrow_sym; jl_sym_t *ldots_sym; typedef struct { int64_t a; diff --git a/src/builtins.c b/src/builtins.c index a2b9fa767f331..03de05f1ff3a3 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1058,9 +1058,9 @@ void jl_init_primitives(void) // builtin types add_builtin("Any", (jl_value_t*)jl_any_type); - add_builtin("None", (jl_value_t*)jl_bottom_type); - add_builtin("Void", (jl_value_t*)jl_bottom_type); add_builtin("Top", (jl_value_t*)jl_top_type); + add_builtin("Void", (jl_value_t*)jl_void_type); + add_builtin("nothing", (jl_value_t*)jl_nothing); add_builtin("TypeVar", (jl_value_t*)jl_tvar_type); add_builtin("TypeName", (jl_value_t*)jl_typename_type); add_builtin("TypeConstructor", (jl_value_t*)jl_typector_type); @@ -1223,12 +1223,12 @@ DLLEXPORT size_t jl_static_show(JL_STREAM *out, jl_value_t *v) else if (v == jl_false) { n += JL_PRINTF(out, "false"); } + else if (v == jl_nothing) { + n += JL_PRINTF(out, "nothing"); + } else if (jl_is_byte_string(v)) { n += JL_PRINTF(out, "\"%s\"", jl_iostr_data(v)); } - else if (v == jl_bottom_type) { - n += JL_PRINTF(out, "Void"); - } else if (jl_is_uniontype(v)) { n += JL_PRINTF(out, "Union"); n += jl_static_show(out, (jl_value_t*)((jl_uniontype_t*)v)->types); diff --git a/src/ccall.cpp b/src/ccall.cpp index c3543132a5fb2..ea32513241323 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -302,8 +302,10 @@ extern "C" DLLEXPORT void *jl_value_to_pointer(jl_value_t *jt, jl_value_t *v, in return jl_string_data(v); } if (jl_is_array_type(jvt)) { - if (jl_tparam0(jl_typeof(v)) == jt || jt==(jl_value_t*)jl_bottom_type) + if (jl_tparam0(jl_typeof(v)) == jt || jt == (jl_value_t*)jl_bottom_type || + jt == (jl_value_t*)jl_void_type) { return ((jl_array_t*)v)->data; + } if (jl_is_cpointer_type(jt)) { jl_array_t *ar = (jl_array_t*)v; void **temp=(void**)alloc_temp_arg_space((1+jl_array_len(ar))*sizeof(void*)); @@ -375,8 +377,8 @@ static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv, assert(ty->isPointerTy()); jl_value_t *aty = expr_type(argex, ctx); if (jl_is_array_type(aty) && - (jl_tparam0(jt) == jl_tparam0(aty) || - jl_tparam0(jt) == (jl_value_t*)jl_bottom_type)) { + (jl_tparam0(jt) == jl_tparam0(aty) || jl_tparam0(jt) == (jl_value_t*)jl_bottom_type || + jl_tparam0(jt) == (jl_value_t*)jl_void_type)) { // array to pointer return builder.CreateBitCast(emit_arrayptr(jv), ty); } diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 68979c5393081..e24ac239884de 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -529,8 +529,8 @@ static jl_value_t *llvm_type_to_julia(Type *t, bool throw_error) if (t == T_int64) return (jl_value_t*)jl_int64_type; if (t == T_float32) return (jl_value_t*)jl_float32_type; if (t == T_float64) return (jl_value_t*)jl_float64_type; - if (t == T_void) return (jl_value_t*)jl_bottom_type; - if (t->isEmptyTy()) return (jl_value_t*)jl_nothing->type; + if (t == T_void) return (jl_value_t*)jl_void_type; + if (t->isEmptyTy()) return (jl_value_t*)jl_void_type; if (t == jl_pvalue_llvmt) return (jl_value_t*)jl_any_type; if (t->isPointerTy()) { @@ -1289,7 +1289,8 @@ static Value *emit_arraylen_prim(Value *t, jl_value_t *ty) { #ifdef STORE_ARRAY_LEN (void)ty; - return emit_nthptr_recast(t, 2, tbaa_arraylen, T_psize); + Value* addr = builder.CreateStructGEP(builder.CreateBitCast(t,jl_parray_llvmt), 2); + return tbaa_decorate(tbaa_arraylen, builder.CreateLoad(addr, false)); #else jl_value_t *p1 = jl_tparam1(ty); if (jl_is_long(p1)) { @@ -1320,7 +1321,8 @@ static Value *emit_arraylen(Value *t, jl_value_t *ex, jl_codectx_t *ctx) static Value *emit_arrayptr(Value *t) { - return emit_nthptr(t, 1, tbaa_arrayptr); + Value* addr = builder.CreateStructGEP(builder.CreateBitCast(t,jl_parray_llvmt), 1); + return tbaa_decorate(tbaa_arrayptr, builder.CreateLoad(addr, false)); } static Value *emit_arrayptr(Value *t, jl_value_t *ex, jl_codectx_t *ctx) @@ -1455,7 +1457,7 @@ static jl_value_t *static_void_instance(jl_value_t *jt) //assert(jb->instance != NULL); return (jl_value_t*)jb->instance; } - else if (jt == jl_typeof(jl_nothing) || jt == jl_bottom_type) { + else if (jt == (jl_value_t*)jl_void_type) { return (jl_value_t*)jl_nothing; } assert(jl_is_tuple(jt)); @@ -1496,6 +1498,14 @@ static jl_value_t *static_constant_instance(Constant *constant, jl_value_t *jt) return jl_new_bits(jt,&val); } + // issue #8464 + ConstantExpr *ce = dyn_cast(constant); + if (ce != NULL) { + if (ce->isCast()) { + return static_constant_instance(dyn_cast(ce->getOperand(0)), jt); + } + } + assert(jl_is_tuple(jt)); size_t nargs = 0; @@ -1539,8 +1549,10 @@ static Value *boxed(Value *v, jl_codectx_t *ctx, jl_value_t *jt) if (jl_subtype(jt2, jt, 0)) jt = jt2; } + if (jt == jl_bottom_type) + return UndefValue::get(jl_pvalue_llvmt); UndefValue *uv = NULL; - if (jt == jl_bottom_type || v == NULL || (uv = dyn_cast(v)) != 0 || t == NoopType) { + if (v == NULL || (uv = dyn_cast(v)) != 0 || t == NoopType) { if (uv != NULL && jl_is_datatype(jt)) { jl_datatype_t *jb = (jl_datatype_t*)jt; // We have an undef value on a hopefully dead branch diff --git a/src/codegen.cpp b/src/codegen.cpp index 01712675e995c..5c06649be6839 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -24,7 +24,6 @@ #endif #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/JITEventListener.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/PassManager.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Support/TargetRegistry.h" @@ -38,6 +37,8 @@ #endif #if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 6 #define LLVM36 1 +#else +#include "llvm/ExecutionEngine/JITMemoryManager.h" #endif #if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5 #define LLVM35 1 @@ -211,6 +212,7 @@ static bool imaging_mode = false; static Type *jl_value_llvmt; static Type *jl_pvalue_llvmt; static Type *jl_ppvalue_llvmt; +static Type* jl_parray_llvmt; static FunctionType *jl_func_sig; static Type *jl_pfptr_llvmt; static Type *T_int1; @@ -716,8 +718,7 @@ static Function *jl_cfunction_object(jl_function_t *f, jl_value_t *rt, jl_value_ } JL_TYPECHK(jl_function_ptr, tuple, argt); JL_TYPECHK(jl_function_ptr, type, argt); - if (jl_is_gf(f) && (rt == NULL || jl_is_leaf_type(rt) || rt == (jl_value_t*)jl_bottom_type) && - jl_is_leaf_type(argt)) { + if (jl_is_gf(f) && (rt == NULL || jl_is_leaf_type(rt)) && jl_is_leaf_type(argt)) { jl_function_t *ff = jl_get_specialization(f, (jl_tuple_t*)argt); if (ff != NULL && ff->env==(jl_value_t*)jl_null && ff->linfo != NULL) { if (ff->linfo->cFunctionObject == NULL) { @@ -731,8 +732,7 @@ static Function *jl_cfunction_object(jl_function_t *f, jl_value_t *rt, jl_value_ } if (rt != NULL) { jl_value_t *astrt = jl_ast_rettype(li, li->ast); - if (!jl_types_equal(astrt, rt) && - !(astrt==(jl_value_t*)jl_nothing->type && rt==(jl_value_t*)jl_bottom_type)) { + if (!jl_types_equal(astrt, rt)) { if (astrt == (jl_value_t*)jl_bottom_type) { jl_errorf("cfunction: %s does not return", li->name->name); } @@ -2549,7 +2549,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) jl_varinfo_t &vi = ctx->vars[s]; jl_value_t *rt = expr_type(r,ctx); if ((jl_is_symbol(r) || jl_is_symbolnode(r)) && rt == jl_bottom_type) { - // sometimes x = y::None occurs + // sometimes x = y::Union() occurs if (builder.GetInsertBlock()->getTerminator() != NULL) return; } @@ -2799,9 +2799,9 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, make_gcroot(a1, ctx); Value *a2 = boxed(emit_expr(args[2], ctx),ctx); make_gcroot(a2, ctx); - Value *mdargs[5] = { name, bp, literal_pointer_val(bnd), a1, a2 }; + Value *mdargs[6] = { name, bp, literal_pointer_val(bnd), a1, a2, literal_pointer_val(args[3]) }; ctx->argDepth = last_depth; - return builder.CreateCall(prepare_call(jlmethod_func), ArrayRef(&mdargs[0], 5)); + return builder.CreateCall(prepare_call(jlmethod_func), ArrayRef(&mdargs[0], 6)); } else if (head == const_sym) { jl_sym_t *sym = (jl_sym_t*)args[0]; @@ -3006,6 +3006,9 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, "Warning: could not attach metadata for @simd loop.\n"); return NULL; } + else if (head == meta_sym) { + return literal_pointer_val((jl_value_t*)jl_nothing); // will change as new metadata gets added + } else { if (!strcmp(head->name, "$")) jl_error("syntax: prefix $ in non-quoted expression"); @@ -3457,7 +3460,7 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) fsig.push_back(ty); } } - Type *rt = (jlrettype == (jl_value_t*)jl_nothing->type ? T_void : julia_type_to_llvm(jlrettype)); + Type *rt = (jlrettype == (jl_value_t*)jl_void_type ? T_void : julia_type_to_llvm(jlrettype)); f = Function::Create(FunctionType::get(rt, fsig, false), Function::ExternalLinkage, funcName.str(), m); if (lam->cFunctionObject == NULL) { @@ -4039,7 +4042,7 @@ extern "C" void jl_fptr_to_llvm(void *fptr, jl_lambda_info_t *lam, int specsig) if (ty != T_void && !ty->isEmptyTy()) fsig.push_back(ty); } - Type *rt = (jlrettype == (jl_value_t*)jl_nothing->type ? T_void : julia_type_to_llvm(jlrettype)); + Type *rt = (jlrettype == (jl_value_t*)jl_void_type ? T_void : julia_type_to_llvm(jlrettype)); Function *f = Function::Create(FunctionType::get(rt, fsig, false), #ifdef USE_MCJIT Function::ExternalLinkage, funcName, shadow_module); @@ -4152,6 +4155,17 @@ static void init_julia_llvm_env(Module *m) assert(jl_func_sig != NULL); jl_pfptr_llvmt = PointerType::get(PointerType::get(jl_func_sig, 0), 0); + Type* vaelts[] = {valueStructElts[0], T_pint8 +#ifdef STORE_ARRAY_LEN + , T_size +#endif + }; + Type* jl_array_llvmt = + StructType::create(jl_LLVMContext, + ArrayRef(vaelts,sizeof(vaelts)/sizeof(vaelts[0])), + "jl_array_t"); + jl_parray_llvmt = PointerType::get(jl_array_llvmt,0); + #ifdef JL_GC_MARKSWEEP jlpgcstack_var = new GlobalVariable(*m, jl_ppvalue_llvmt, @@ -4353,6 +4367,7 @@ static void init_julia_llvm_env(Module *m) mdargs.push_back(jl_pvalue_llvmt); mdargs.push_back(jl_pvalue_llvmt); mdargs.push_back(jl_pvalue_llvmt); + mdargs.push_back(jl_pvalue_llvmt); jlmethod_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, mdargs, false), Function::ExternalLinkage, diff --git a/src/dump.c b/src/dump.c index ecd33116b607e..d79b35f15f93c 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1201,8 +1201,8 @@ void jl_init_serializer(void) (void*)Int32_tag, (void*)Array1d_tag, (void*)Singleton_tag, jl_module_type, jl_tvar_type, jl_lambda_info_type, - jl_null, jl_false, jl_true, jl_any_type, jl_symbol("Any"), - jl_symbol("Array"), jl_symbol("TypeVar"), + jl_null, jl_false, jl_true, jl_nothing, jl_any_type, + jl_symbol("Any"), jl_symbol("Array"), jl_symbol("TypeVar"), jl_symbol("Box"), jl_symbol("apply"), lambda_sym, body_sym, return_sym, call_sym, colons_sym, null_sym, goto_ifnot_sym, assign_sym, @@ -1255,7 +1255,6 @@ void jl_init_serializer(void) jl_box_int32(51), jl_box_int32(52), jl_box_int32(53), jl_box_int32(54), jl_box_int32(55), jl_box_int32(56), jl_box_int32(57), jl_box_int32(58), jl_box_int32(59), - jl_box_int32(60), jl_box_int32(61), #endif jl_box_int64(0), jl_box_int64(1), jl_box_int64(2), jl_box_int64(3), jl_box_int64(4), jl_box_int64(5), @@ -1278,13 +1277,12 @@ void jl_init_serializer(void) jl_box_int64(51), jl_box_int64(52), jl_box_int64(53), jl_box_int64(54), jl_box_int64(55), jl_box_int64(56), jl_box_int64(57), jl_box_int64(58), jl_box_int64(59), - jl_box_int64(60), jl_box_int64(61), #endif jl_labelnode_type, jl_linenumbernode_type, jl_gotonode_type, jl_quotenode_type, jl_topnode_type, jl_type_type, jl_bottom_type, jl_pointer_type, jl_vararg_type, jl_ntuple_type, jl_abstractarray_type, - jl_densearray_type, jl_box_type, + jl_densearray_type, jl_box_type, jl_void_type, jl_typector_type, jl_undef_type, jl_top_type, jl_typename_type, jl_task_type, jl_uniontype_type, jl_typetype_type, jl_typetype_tvar, jl_ANY_flag, jl_array_any_type, jl_intrinsic_type, jl_method_type, @@ -1296,7 +1294,7 @@ void jl_init_serializer(void) jl_typename_type->name, jl_type_type->name, jl_methtable_type->name, jl_method_type->name, jl_tvar_type->name, jl_vararg_type->name, jl_ntuple_type->name, jl_abstractarray_type->name, - jl_densearray_type->name, + jl_densearray_type->name, jl_void_type->name, jl_lambda_info_type->name, jl_module_type->name, jl_box_type->name, jl_function_type->name, jl_typector_type->name, jl_intrinsic_type->name, jl_undef_type->name, jl_task_type->name, diff --git a/src/gf.c b/src/gf.c index 38c3b95acf780..576461d94c570 100644 --- a/src/gf.c +++ b/src/gf.c @@ -274,8 +274,7 @@ static jl_function_t *jl_method_table_assoc_exact(jl_methtable_t *mt, mt_assoc_lkup: while (ml != JL_NULL) { size_t lensig = jl_tuple_len(ml->sig); - if ((lensig == n || ml->va) && - !(lensig > n && n != lensig-1)) { + if (lensig == n || (ml->va && lensig <= n+1)) { if (cache_match(args, n, (jl_tuple_t*)ml->sig, ml->va, lensig)) { return ml->func; } @@ -323,7 +322,7 @@ jl_function_t *jl_reinstantiate_method(jl_function_t *f, jl_lambda_info_t *li) static jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tuple_t *type, jl_function_t *method, jl_tuple_t *tvars, - int check_amb); + int check_amb, int8_t isstaged); static jl_function_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tuple_t *type, @@ -356,7 +355,7 @@ jl_function_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tuple_t *type, } } ml_do_insert: - return jl_method_list_insert(pml, type, method, jl_null, 0)->func; + return jl_method_list_insert(pml, type, method, jl_null, 0, 0)->func; } extern jl_function_t *jl_typeinf_func; @@ -454,7 +453,7 @@ static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type, static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, jl_function_t *method, jl_tuple_t *decl, - jl_tuple_t *sparams) + jl_tuple_t *sparams, int isstaged) { size_t i; int need_guard_entries = 0; @@ -705,7 +704,7 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, // in general, here we want to find the biggest type that's not a // supertype of any other method signatures. so far we are conservative // and the types we find should be bigger. - if (jl_tuple_len(type) > mt->max_args && + if (!isstaged && jl_tuple_len(type) > mt->max_args && jl_is_vararg_type(jl_tupleref(decl,jl_tuple_len(decl)-1))) { size_t nspec = mt->max_args + 2; jl_tuple_t *limited = jl_alloc_tuple(nspec); @@ -906,10 +905,10 @@ static jl_value_t *lookup_match(jl_value_t *a, jl_value_t *b, jl_tuple_t **penv, ee[n++] = val; /* since "a" is a concrete type, we assume that - (a∩b != None) => a<:b. However if a static parameter is - forced to equal None, then part of "b" might become None, + (a∩b != Union()) => a<:b. However if a static parameter is + forced to equal Union(), then part of "b" might become Union(), and therefore a subtype of "a". For example - (Type{None},Int) ∩ (Type{T},T) + (Type{Union()},Int) ∩ (Type{T},T) issue #5254 */ if (val == (jl_value_t*)jl_bottom_type) { @@ -930,6 +929,44 @@ static jl_value_t *lookup_match(jl_value_t *a, jl_value_t *b, jl_tuple_t **penv, return ti; } +DLLEXPORT jl_function_t *jl_instantiate_staged(jl_methlist_t *m, jl_tuple_t *tt) +{ + jl_lambda_info_t *newlinfo = NULL; + jl_value_t *code = NULL; + jl_expr_t *ex = NULL; + jl_expr_t *oldast = NULL; + jl_function_t *func = NULL; + JL_GC_PUSH4(&code, &newlinfo, &ex, &oldast); + if (jl_is_expr(m->func->linfo->ast)) + oldast = (jl_expr_t*)m->func->linfo; + else + oldast = (jl_expr_t*)jl_uncompress_ast(m->func->linfo, m->func->linfo->ast); + assert(oldast->head == lambda_sym); + ex = jl_exprn(arrow_sym, 2); + jl_array_t *oldargnames = (jl_array_t*)jl_cellref(oldast->args,0); + jl_expr_t *argnames = jl_exprn(tuple_sym, jl_array_len(oldargnames)); + jl_cellset(ex->args, 0, argnames); + for (size_t i = 0; i < jl_array_len(oldargnames); ++i) { + jl_value_t *arg = jl_cellref(oldargnames,i); + if (jl_is_expr(arg)) { + assert(((jl_expr_t*)arg)->head == colons_sym); + arg = jl_cellref(((jl_expr_t*)arg)->args,0); + assert(jl_is_symbol(arg)); + jl_expr_t *dd_expr = jl_exprn(ldots_sym,1); + jl_cellset(dd_expr->args,0,arg); + jl_cellset(argnames->args,i,dd_expr); + } else { + assert(jl_is_symbol(arg)); + jl_cellset(argnames->args,i,arg); + } + } + jl_cellset(ex->args, 1, jl_apply(m->func, tt->data, jl_tuple_len(tt))); + code = jl_expand((jl_value_t*)ex); + func = (jl_function_t*)jl_toplevel_eval(code); + JL_GC_POP(); + return func; +} + static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, int cache, int inexact) { jl_methlist_t *m = mt->defs; @@ -937,7 +974,8 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in size_t i; jl_value_t *ti=(jl_value_t*)jl_bottom_type; jl_tuple_t *newsig=NULL, *env = jl_null; - JL_GC_PUSH2(&env, &newsig); + jl_function_t *func = NULL; + JL_GC_PUSH3(&env, &newsig, &func); while (m != JL_NULL) { if (m->tvars!=jl_null) { @@ -973,16 +1011,25 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in } if (ti == (jl_value_t*)jl_bottom_type) { - JL_GC_POP(); if (m != JL_NULL) { + func = m->func; + if (m->isstaged) + func = jl_instantiate_staged(m,tt); + JL_GC_POP(); if (!cache) - return m->func; - return cache_method(mt, tt, m->func, (jl_tuple_t*)m->sig, jl_null); + return func; + return cache_method(mt, tt, func, (jl_tuple_t*)m->sig, jl_null, m->isstaged); } + JL_GC_POP(); return jl_bottom_func; } assert(jl_is_tuple(env)); + func = m->func; + + if (m->isstaged) + func = jl_instantiate_staged(m,tt); + // don't bother computing this if no arguments are tuples for(i=0; i < jl_tuple_len(tt); i++) { if (jl_is_tuple(jl_tupleref(tt,i))) @@ -999,9 +1046,9 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in assert(jl_is_tuple(newsig)); jl_function_t *nf; if (!cache) - nf = m->func; + nf = func; else - nf = cache_method(mt, tt, m->func, newsig, env); + nf = cache_method(mt, tt, func, newsig, env, 0); JL_GC_POP(); return nf; } @@ -1138,7 +1185,7 @@ static int has_unions(jl_tuple_t *type) static jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tuple_t *type, jl_function_t *method, jl_tuple_t *tvars, - int check_amb) + int check_amb, int8_t isstaged) { jl_methlist_t *l, **pl; @@ -1170,6 +1217,7 @@ jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tuple_t *type, l->va = (jl_tuple_len(type) > 0 && jl_is_vararg_type(jl_tupleref(type,jl_tuple_len(type)-1))) ? 1 : 0; + l->isstaged = isstaged; l->invokes = (struct _jl_methtable_t *)JL_NULL; l->func = method; JL_SIGATOMIC_END(); @@ -1197,6 +1245,7 @@ jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tuple_t *type, newrec->va = (jl_tuple_len(type) > 0 && jl_is_vararg_type(jl_tupleref(type,jl_tuple_len(type)-1))) ? 1 : 0; + newrec->isstaged = isstaged; newrec->func = method; newrec->invokes = (struct _jl_methtable_t*)JL_NULL; newrec->next = l; @@ -1249,12 +1298,13 @@ static void remove_conflicting(jl_methlist_t **pl, jl_value_t *type) } jl_methlist_t *jl_method_table_insert(jl_methtable_t *mt, jl_tuple_t *type, - jl_function_t *method, jl_tuple_t *tvars) + jl_function_t *method, jl_tuple_t *tvars, + int8_t isstaged) { if (jl_tuple_len(tvars) == 1) tvars = (jl_tuple_t*)jl_t0(tvars); JL_SIGATOMIC_BEGIN(); - jl_methlist_t *ml = jl_method_list_insert(&mt->defs,type,method,tvars,1); + jl_methlist_t *ml = jl_method_list_insert(&mt->defs,type,method,tvars,1,isstaged); // invalidate cached methods that overlap this definition remove_conflicting(&mt->cache, (jl_value_t*)type); if (mt->cache_arg1 != JL_NULL) { @@ -1660,7 +1710,7 @@ jl_value_t *jl_gf_invoke(jl_function_t *gf, jl_tuple_t *types, if (m->invokes == JL_NULL) { m->invokes = new_method_table(mt->name); // this private method table has just this one definition - jl_method_list_insert(&m->invokes->defs,m->sig,m->func,m->tvars,0); + jl_method_list_insert(&m->invokes->defs,m->sig,m->func,m->tvars,0,0); } tt = arg_type_tuple(args, nargs); @@ -1684,7 +1734,7 @@ jl_value_t *jl_gf_invoke(jl_function_t *gf, jl_tuple_t *types, jl_tuple_len(tpenv)/2); } } - mfunc = cache_method(m->invokes, tt, m->func, newsig, tpenv); + mfunc = cache_method(m->invokes, tt, m->func, newsig, tpenv, 0); JL_GC_POP(); } @@ -1721,7 +1771,7 @@ DLLEXPORT jl_function_t *jl_new_gf_internal(jl_value_t *env) } void jl_add_method(jl_function_t *gf, jl_tuple_t *types, jl_function_t *meth, - jl_tuple_t *tvars) + jl_tuple_t *tvars, int8_t isstaged) { assert(jl_is_function(gf)); assert(jl_is_tuple(types)); @@ -1729,7 +1779,7 @@ void jl_add_method(jl_function_t *gf, jl_tuple_t *types, jl_function_t *meth, assert(jl_is_mtable(jl_gf_mtable(gf))); if (meth->linfo != NULL) meth->linfo->name = jl_gf_name(gf); - (void)jl_method_table_insert(jl_gf_mtable(gf), types, meth, tvars); + (void)jl_method_table_insert(jl_gf_mtable(gf), types, meth, tvars, isstaged); } DLLEXPORT jl_tuple_t *jl_match_method(jl_value_t *type, jl_value_t *sig, diff --git a/src/init.c b/src/init.c index e91cff2ad2de0..2b943f70e59a3 100644 --- a/src/init.c +++ b/src/init.c @@ -1068,7 +1068,6 @@ static jl_value_t *basemod(char *name) // fetch references to things defined in boot.jl void jl_get_builtin_hooks(void) { - jl_nothing = core("nothing"); jl_root_task->tls = jl_nothing; jl_root_task->consumers = jl_nothing; jl_root_task->donenotify = jl_nothing; diff --git a/src/interpreter.c b/src/interpreter.c index 0d445d107e2b7..0f412890e27e9 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -285,7 +285,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) jl_check_static_parameter_conflicts((jl_lambda_info_t*)args[2], (jl_tuple_t*)jl_t1(atypes), fname); } meth = eval(args[2], locals, nl); - jl_method_def(fname, bp, b, (jl_tuple_t*)atypes, (jl_function_t*)meth); + jl_method_def(fname, bp, b, (jl_tuple_t*)atypes, (jl_function_t*)meth, args[3]); JL_GC_POP(); return *bp; } @@ -455,6 +455,9 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) else if (ex->head == simdloop_sym) { return (jl_value_t*)jl_nothing; } + else if (ex->head == meta_sym) { + return (jl_value_t*)jl_nothing; + } jl_errorf("unsupported or misplaced expression %s", ex->head->name); return (jl_value_t*)jl_nothing; } diff --git a/src/jltypes.c b/src/jltypes.c index 26d6226d811aa..745d18e865098 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -395,7 +395,7 @@ static jl_value_t *intersect_union(jl_uniontype_t *a, jl_value_t *b, return tu; } -// if returns with *bot!=0, then intersection is None +// if returns with *bot!=0, then intersection is Union() static size_t tuple_intersect_size(jl_tuple_t *a, jl_tuple_t *b, int *bot) { size_t al = jl_tuple_len(a); @@ -524,7 +524,7 @@ static jl_value_t *intersect_tag(jl_datatype_t *a, jl_datatype_t *b, ti = jl_type_intersect(ap,bp,penv,eqc,invariant); if (bp == (jl_value_t*)jl_bottom_type && !((jl_tvar_t*)ap)->bound) { - // "None" as a type parameter + // "Union()" as a type parameter jl_tupleset(p, i, ti); continue; } @@ -533,7 +533,7 @@ static jl_value_t *intersect_tag(jl_datatype_t *a, jl_datatype_t *b, ti = jl_type_intersect(ap,bp,penv,eqc,invariant); if (ap == (jl_value_t*)jl_bottom_type && !((jl_tvar_t*)bp)->bound) { - // "None" as a type parameter + // "Union()" as a type parameter jl_tupleset(p, i, ti); continue; } @@ -553,7 +553,7 @@ static jl_value_t *intersect_tag(jl_datatype_t *a, jl_datatype_t *b, else if (type_eqv_(ap,bp)) { ti = ap; if (ti == (jl_value_t*)jl_bottom_type) { - // "None" as a type parameter + // "Union()" as a type parameter jl_tupleset(p, i, ti); continue; } @@ -1017,7 +1017,7 @@ static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, // uses to instantiate its supertype. this tells us what subtype parameter // values are implied by the intersected supertype, or that the // intersected supertype cannot come from this subtype (in which case - // our final answer is None). + // our final answer is Union()). size_t i; // hack: we need type_match to find assignments for all typevars int prev_mim = match_intersection_mode; @@ -1064,7 +1064,7 @@ static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, if (jl_tupleref(env, e) == tp) { elt = jl_type_intersect(elt, jl_tupleref(env, e+1), penv, eqc, invariant); - // note: elt might be None if "None" was the type parameter + // note: elt might be Union() if "Union()" was the type parameter break; } } @@ -2086,7 +2086,7 @@ static int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int invariant) } } else if (a == b) { - // None <: None + // Union() <: Union() return 1; } size_t i; @@ -2857,7 +2857,6 @@ void jl_init_types(void) jl_null = (jl_tuple_t*)newobj((jl_value_t*)jl_tuple_type, 1); jl_tuple_set_len_unsafe(jl_null, 0); - jl_nothing = (jl_value_t*)jl_null; // for bootstrapping jl_any_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Any"), NULL, jl_null); jl_any_type->super = jl_any_type; @@ -2937,6 +2936,11 @@ void jl_init_types(void) jl_sym_type->mutabl = 1; // now they can be used to create the remaining base kinds and types + jl_void_type = jl_new_datatype(jl_symbol("Void"), jl_any_type, jl_null, + jl_null, jl_null, 0, 0); + jl_nothing = newstruct(jl_void_type); + jl_void_type->instance = jl_nothing; + jl_uniontype_type = jl_new_datatype(jl_symbol("UnionType"), jl_type_type, jl_null, jl_tuple(1, jl_symbol("types")), @@ -3001,10 +3005,10 @@ void jl_init_types(void) jl_method_type = jl_new_datatype(jl_symbol("Method"), jl_any_type, jl_null, - jl_tuple(6, jl_symbol("sig"), jl_symbol("va"), + jl_tuple(7, jl_symbol("sig"), jl_symbol("va"), jl_symbol("isstaged"), jl_symbol("tvars"), jl_symbol("func"), jl_symbol("invokes"), jl_symbol("next")), - jl_tuple(6, jl_tuple_type, jl_bool_type, + jl_tuple(7, jl_tuple_type, jl_bool_type, jl_bool_type, jl_tuple_type, jl_any_type, jl_any_type, jl_any_type), 0, 1); @@ -3187,7 +3191,7 @@ void jl_init_types(void) // complete builtin type metadata jl_value_t *pointer_void = jl_apply_type((jl_value_t*)jl_pointer_type, - jl_tuple(1,jl_bottom_type)); + jl_tuple(1,jl_void_type)); jl_voidpointer_type = (jl_datatype_t*)pointer_void; jl_tupleset(jl_datatype_type->types, 0, pointer_void); jl_tupleset(jl_datatype_type->types, 9, jl_int32_type); @@ -3261,6 +3265,9 @@ void jl_init_types(void) newvar_sym = jl_symbol("newvar"); copyast_sym = jl_symbol("copyast"); simdloop_sym = jl_symbol("simdloop"); + meta_sym = jl_symbol("meta"); + arrow_sym = jl_symbol("->"); + ldots_sym = jl_symbol("..."); } #ifdef __cplusplus diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 32999aacc3d91..5b9459aef8edf 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -90,7 +90,7 @@ (define operator? (Set operators)) (define reserved-words '(begin while if for try return break continue - function macro quote let local global const + stagedfunction function macro quote let local global const abstract typealias type bitstype immutable ccall do module baremodule using import export importall)) @@ -1074,7 +1074,7 @@ (if const `(const ,expr) expr))) - ((function macro) + ((stagedfunction function macro) (let* ((paren (eqv? (require-token s) #\()) (sig (parse-call s)) (def (if (or (symbol? sig) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 44201134d8228..35e8c351fa34e 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -437,7 +437,7 @@ (pair? (caddr e)) (eq? (car (caddr e)) 'quote) (symbol? (cadr (caddr e)))))) -(define (method-def-expr- name sparams argl body) +(define (method-def-expr- name sparams argl body isstaged) (receive (names bounds) (sparam-name-bounds sparams '() '()) (begin @@ -455,12 +455,12 @@ (let* ((types (llist-types argl)) (body (method-lambda-expr argl body))) (if (null? sparams) - `(method ,name (tuple (tuple ,@types) (tuple)) ,body) + `(method ,name (tuple (tuple ,@types) (tuple)) ,body ,isstaged) `(method ,name (call (lambda ,names (tuple (tuple ,@types) (tuple ,@names))) ,@(symbols->typevars names bounds #t)) - ,body)))))) + ,body ,isstaged)))))) (define (vararg? x) (and (pair? x) (eq? (car x) '...))) (define (trans? x) (and (pair? x) (eq? (car x) '|.'|))) @@ -469,7 +469,7 @@ (define (const-default? x) (or (number? x) (string? x) (char? x) (and (pair? x) (eq? (car x) 'quote)))) -(define (keywords-method-def-expr name sparams argl body) +(define (keywords-method-def-expr name sparams argl body isstaged) (let* ((kargl (cdar argl)) ;; keyword expressions (= k v) (pargl (cdr argl)) ;; positional args (body (if (and (pair? body) (eq? (car body) 'block)) @@ -533,7 +533,7 @@ `(block ,@(if (null? lno) '() (list (append (car lno) (list (undot-name name))))) - ,@stmts)) + ,@stmts) isstaged) ;; call with no keyword args ,(method-def-expr- @@ -551,7 +551,7 @@ ,@(if (null? restkw) '() '((cell1d))) ,@(map arg-name pargl) ,@(if (null? vararg) '() - (list `(... ,(arg-name (car vararg))))))))) + (list `(... ,(arg-name (car vararg)))))))) isstaged) ;; call with unsorted keyword args. this sorts and re-dispatches. ,(method-def-expr- @@ -628,11 +628,12 @@ ,@(if (null? restkw) '() (list rkw)) ,@(map arg-name pargl) ,@(if (null? vararg) '() - (list `(... ,(arg-name (car vararg))))))))) + (list `(... ,(arg-name (car vararg)))))))) + isstaged) ;; return primary function ,name)))) -(define (optional-positional-defs name sparams req opt dfl body overall-argl . kw) +(define (optional-positional-defs name sparams req opt dfl body isstaged overall-argl . kw) (let ((lno (if (and (pair? body) (pair? (cdr body)) (pair? (cadr body)) (eq? (caadr body) 'line)) (list (cadr body)) @@ -668,11 +669,11 @@ `(block ,@lno (call ,name ,@kw ,@(map arg-name passed) ,@vals))))) - (method-def-expr name sp (append kw passed) body))) + (method-def-expr name sp (append kw passed) body isstaged))) (iota (length opt))) - ,(method-def-expr name sparams overall-argl body)))) + ,(method-def-expr name sparams overall-argl body isstaged)))) -(define (method-def-expr name sparams argl body) +(define (method-def-expr name sparams argl body isstaged) (if (any kwarg? argl) ;; has optional positional args (begin @@ -697,20 +698,20 @@ (check-kw-args (cdr kw)) (receive (vararg req) (separate vararg? argl) - (optional-positional-defs name sparams req opt dfl body + (optional-positional-defs name sparams req opt dfl body isstaged (cons kw (append req opt vararg)) `(parameters (... ,(gensy)))))) ;; optional positional only (receive (vararg req) (separate vararg? argl) - (optional-positional-defs name sparams req opt dfl body + (optional-positional-defs name sparams req opt dfl body isstaged (append req opt vararg))))))) (if (has-parameters? argl) ;; keywords only (begin (check-kw-args (cdar argl)) - (keywords-method-def-expr name sparams argl body)) + (keywords-method-def-expr name sparams argl body isstaged)) ;; neither - (method-def-expr- name sparams argl body)))) + (method-def-expr- name sparams argl body isstaged)))) (define (struct-def-expr name params super fields mut) (receive @@ -796,9 +797,15 @@ (pattern-lambda (function (call (curly name . p) . sig) body) `(function (call (curly ,(if (eq? name Tname) iname name) ,@p) ,@sig) ,(ctor-body body))) + (pattern-lambda (stagedfunction (call (curly name . p) . sig) body) + `(stagedfunction (call (curly ,(if (eq? name Tname) iname name) ,@p) ,@sig) + ,(ctor-body body))) (pattern-lambda (function (call name . sig) body) `(function (call ,(if (eq? name Tname) iname name) ,@sig) ,(ctor-body body))) + (pattern-lambda (stagedfunction (call name . sig) body) + `(stagedfunction (call ,(if (eq? name Tname) iname name) ,@sig) + ,(ctor-body body))) (pattern-lambda (= (call (curly name . p) . sig) body) `(= (call (curly ,(if (eq? name Tname) iname name) ,@p) ,@sig) ,(ctor-body body))) @@ -985,6 +992,7 @@ (cond ((or (atom? e) (quoted? e)) e) ((or (eq? (car e) 'lambda) (eq? (car e) 'function) + (eq? (car e) 'stagedfunction) (eq? (car e) '->)) e) ((eq? (car e) 'return) `(block ,@(if ret `((= ,ret true)) '()) @@ -998,7 +1006,7 @@ ((quoted? e) e) (else (case (car e) - ((function) + ((function stagedfunction) (let ((name (cadr e))) (if (pair? name) (if (eq? (car name) 'call) @@ -1008,11 +1016,11 @@ (method-def-expr (cadr (cadr name)) (cddr (cadr name)) (fix-arglist (cddr name)) - (caddr e)) + (caddr e) (eq? (car e) 'stagedfunction)) (method-def-expr (cadr name) '() (fix-arglist (cddr name)) - (caddr e)))) + (caddr e) (eq? (car e) 'stagedfunction)))) (if (eq? (car name) 'tuple) (expand-binding-forms `(-> ,name ,(caddr e))) @@ -2848,6 +2856,7 @@ So far only the second case can actually occur. (define (free-vars e) (table.keys (free-vars- e (table) *free-vars-secret-value*))) +(define (caddddr x) (car (cdr (cdr (cdr (cdr x)))))) ; convert each lambda's (locals ...) to ; ((localvars...) var-info-lst captured-var-infos) ; where var-info-lst is a list of var-info records @@ -2951,7 +2960,8 @@ So far only the second case can actually occur. (vinfo:set-iasg! vi #t))))) `(method ,(cadr e) ,(analyze-vars (caddr e) env captvars) - ,(analyze-vars (cadddr e) env captvars))) + ,(analyze-vars (cadddr e) env captvars) + ,(caddddr e))) (else (cons (car e) (map (lambda (x) (analyze-vars x env captvars)) (cdr e))))))) diff --git a/src/julia.h b/src/julia.h index b95c9e91d2c1a..826b0c9798451 100644 --- a/src/julia.h +++ b/src/julia.h @@ -261,6 +261,7 @@ typedef struct _jl_methlist_t { JL_DATA_TYPE jl_tuple_t *sig; int8_t va; + int8_t isstaged; jl_tuple_t *tvars; jl_function_t *func; // cache of specializations of this method for invoke(), i.e. @@ -358,6 +359,7 @@ extern DLLEXPORT jl_datatype_t *jl_float32_type; extern DLLEXPORT jl_datatype_t *jl_float64_type; extern DLLEXPORT jl_datatype_t *jl_floatingpoint_type; extern DLLEXPORT jl_datatype_t *jl_number_type; +extern DLLEXPORT jl_datatype_t *jl_void_type; extern DLLEXPORT jl_datatype_t *jl_voidpointer_type; extern DLLEXPORT jl_datatype_t *jl_pointer_type; @@ -421,8 +423,8 @@ extern jl_sym_t *abstracttype_sym; extern jl_sym_t *bitstype_sym; extern jl_sym_t *compositetype_sym; extern jl_sym_t *type_goto_sym; extern jl_sym_t *global_sym; extern jl_sym_t *tuple_sym; extern jl_sym_t *boundscheck_sym; extern jl_sym_t *copyast_sym; -extern jl_sym_t *simdloop_sym; - +extern jl_sym_t *simdloop_sym; extern jl_sym_t *meta_sym; +extern jl_sym_t *arrow_sym; extern jl_sym_t *ldots_sym; // object accessors ----------------------------------------------------------- @@ -639,11 +641,11 @@ jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super, jl_tuple_t *parameters); DLLEXPORT jl_datatype_t *jl_new_uninitialized_datatype(size_t nfields); DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super, - jl_tuple_t *parameters, - jl_tuple_t *fnames, jl_tuple_t *ftypes, - int abstract, int mutabl); + jl_tuple_t *parameters, + jl_tuple_t *fnames, jl_tuple_t *ftypes, + int abstract, int mutabl); DLLEXPORT jl_datatype_t *jl_new_bitstype(jl_value_t *name, jl_datatype_t *super, - jl_tuple_t *parameters, size_t nbits); + jl_tuple_t *parameters, size_t nbits); jl_datatype_t *jl_wrap_Type(jl_value_t *t); // x -> Type{x} jl_datatype_t *jl_wrap_vararg(jl_value_t *t); // x -> x... @@ -672,9 +674,9 @@ DLLEXPORT jl_sym_t *jl_get_root_symbol(void); jl_expr_t *jl_exprn(jl_sym_t *head, size_t n); jl_function_t *jl_new_generic_function(jl_sym_t *name); void jl_add_method(jl_function_t *gf, jl_tuple_t *types, jl_function_t *meth, - jl_tuple_t *tvars); + jl_tuple_t *tvars, int8_t isstaged); DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd, - jl_tuple_t *argtypes, jl_function_t *f); + jl_tuple_t *argtypes, jl_function_t *f, jl_value_t *isstaged); DLLEXPORT jl_value_t *jl_box_bool(int8_t x); DLLEXPORT jl_value_t *jl_box_int8(int32_t x); DLLEXPORT jl_value_t *jl_box_uint8(uint32_t x); diff --git a/src/toplevel.c b/src/toplevel.c index 4662a78837fba..600609d2b1a39 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -642,7 +642,7 @@ static int type_contains(jl_value_t *ty, jl_value_t *x) void print_func_loc(JL_STREAM *s, jl_lambda_info_t *li); DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd, - jl_tuple_t *argtypes, jl_function_t *f) + jl_tuple_t *argtypes, jl_function_t *f, jl_value_t *isstaged) { // argtypes is a tuple ((types...), (typevars...)) jl_tuple_t *t = (jl_tuple_t*)jl_t1(argtypes); @@ -702,7 +702,7 @@ DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_ assert(jl_is_tuple(argtypes)); assert(jl_is_tuple(t)); - jl_add_method((jl_function_t*)gf, argtypes, f, t); + jl_add_method((jl_function_t*)gf, argtypes, f, t, isstaged == jl_true); if (jl_boot_file_loaded && f->linfo && f->linfo->ast && jl_is_expr(f->linfo->ast)) { jl_lambda_info_t *li = f->linfo; diff --git a/test/Makefile b/test/Makefile index 53dfe075b9397..2fe67f6e0ca40 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,14 +1,7 @@ JULIAHOME = $(abspath ..) include ../Make.inc -TESTS = all core keywordargs numbers strings unicode collections hashing \ - remote iobuffer arrayops reduce reducedim \ - simdloop linalg blas fft dsp sparse bitarray random math functional \ - bigint sorting statistics spawn parallel arpack file git pkg resolve \ - suitesparse complex version pollfd mpfr broadcast socket floatapprox \ - priorityqueue readdlm reflection regex float16 combinatorics dates \ - sysinfo rounding ranges mod2pi euler show lineedit replcompletions \ - backtrace repl test examples goto llvmcall grisu +TESTS = all linalg $(filter-out TestHelpers runtests testdefs,$(subst .jl,,$(wildcard *.jl))) default: all diff --git a/test/arrayops.jl b/test/arrayops.jl index abf073de17f05..2c16074ad6c0b 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -881,7 +881,7 @@ let end # issue #6977 -@test []' == Array(None,1,0) +@test size([]') == (1,0) # issue #6996 @test { 1 2; 3 4 }' == { 1 2; 3 4 }.' diff --git a/test/bitarray.jl b/test/bitarray.jl index 9d28d1718f4c3..6795a0b031b9c 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -478,6 +478,20 @@ for m1 = 1 : v1 + 1 i = splice!(i2, m1:m2, i3) @test isequal(bitunpack(b2), i2) @test b == i + b2 = copy(b1) + i2 = copy(i1) + i3 = int(randbool(v2)) + b = splice!(b2, m1:m2, i3) + i = splice!(i2, m1:m2, i3) + @test isequal(bitunpack(b2), i2) + @test b == i + b2 = copy(b1) + i2 = copy(i1) + i3 = [j => rand(0:3) for j = 1:v2] + b = splice!(b2, m1:m2, values(i3)) + i = splice!(i2, m1:m2, values(i3)) + @test isequal(bitunpack(b2), i2) + @test b == i end end end @@ -494,6 +508,20 @@ for m1 = 1 : v1 i = splice!(i2, m1, i3) @test isequal(bitunpack(b2), i2) @test b == i + b2 = copy(b1) + i2 = copy(i1) + i3 = int(randbool(v2)) + b = splice!(b2, m1:m2, i3) + i = splice!(i2, m1:m2, i3) + @test isequal(bitunpack(b2), i2) + @test b == i + b2 = copy(b1) + i2 = copy(i1) + i3 = [j => rand(0:3) for j = 1:v2] + b = splice!(b2, m1:m2, values(i3)) + i = splice!(i2, m1:m2, values(i3)) + @test isequal(bitunpack(b2), i2) + @test b == i end end diff --git a/test/core.jl b/test/core.jl index d545b222be4d5..6f18edfaa3e89 100644 --- a/test/core.jl +++ b/test/core.jl @@ -1,5 +1,7 @@ # test core language features +const Bottom = Union() + # basic type relationships @test Int8 <: Integer @test Int32 <: Integer @@ -17,18 +19,18 @@ @test !(Array{Int8,1} <: Array{Any,1}) @test !(Array{Any,1} <: Array{Int8,1}) @test Array{Int8,1} <: Array{Int8,1} -@test !(Type{None} <: Type{Int32}) +@test !(Type{Bottom} <: Type{Int32}) @test !(Vector{Float64} <: Vector{Union(Float64,Float32)}) -@test is(None, typeintersect(Vector{Float64},Vector{Union(Float64,Float32)})) +@test is(Bottom, typeintersect(Vector{Float64},Vector{Union(Float64,Float32)})) @test !isa(Array,Type{Any}) @test Type{Complex} <: DataType @test isa(Complex,Type{Complex}) -@test !(Type{Ptr{None}} <: Type{Ptr}) +@test !(Type{Ptr{Bottom}} <: Type{Ptr}) @test !(Type{Rational{Int}} <: Type{Rational}) let T = TypeVar(:T,true) - @test !is(None, typeintersect(Array{None},AbstractArray{T})) - @test is(None, typeintersect((Type{Ptr{Uint8}},Ptr{None}), + @test !is(Bottom, typeintersect(Array{Bottom},AbstractArray{T})) + @test is(Bottom, typeintersect((Type{Ptr{Uint8}},Ptr{Bottom}), (Type{Ptr{T}},Ptr{T}))) @test !(Type{T} <: TypeVar) @@ -39,11 +41,11 @@ let T = TypeVar(:T,true) (Int, Array{Int,1})) @test isequal(typeintersect((T, AbstractArray{T}),(Int, Array{Number,1})), - None) + Bottom) @test isequal(typeintersect((T, AbstractArray{T}),(Any, Array{Number,1})), (Number, Array{Number,1})) - @test !is(None, typeintersect((Array{T}, Array{T}), (Array, Array{Any}))) + @test !is(Bottom, typeintersect((Array{T}, Array{T}), (Array, Array{Any}))) f47{T}(x::Vector{Vector{T}}) = 0 @test_throws MethodError f47(Array(Vector,0)) @test f47(Array(Vector{Int},0)) == 0 @@ -55,17 +57,17 @@ let T = TypeVar(:T,true) @test typeintersect(Type{TypeVar(:T,Array{TT,1})},Type{Array{S,N}}) == Type{Array{S,1}} # issue #5359 @test typeintersect((Type{Array{T,1}},Array{T,1}), - (Type{AbstractVector},Vector{Int})) === None + (Type{AbstractVector},Vector{Int})) === Bottom # issue #5559 @test typeintersect((Type{Vector{Complex128}}, AbstractVector), (Type{Array{T,N}}, Array{S,N})) == (Type{Vector{Complex128}},Vector) @test typeintersect((Type{Vector{Complex128}}, AbstractArray), (Type{Array{T,N}}, Array{S,N})) == (Type{Vector{Complex128}},Vector) - @test typeintersect(Type{Array{T}}, Type{AbstractArray{T}}) === None + @test typeintersect(Type{Array{T}}, Type{AbstractArray{T}}) === Bottom - @test typeintersect(Type{(Bool,Int...)}, Type{(T...)}) === None - @test typeintersect(Type{(Bool,Int...)}, Type{(T,T...)}) === None + @test typeintersect(Type{(Bool,Int...)}, Type{(T...)}) === Bottom + @test typeintersect(Type{(Bool,Int...)}, Type{(T,T...)}) === Bottom end let N = TypeVar(:N,true) @test isequal(typeintersect((NTuple{N,Integer},NTuple{N,Integer}), @@ -82,24 +84,24 @@ let N = TypeVar(:N,true) ((Int,Int...),Array{Int,2})), ((Int,Int), Array{Int,2})) - @test isequal(typeintersect((Type{Nothing},Type{Nothing}), Type{NTuple{N,Nothing}}), - Type{(Nothing,Nothing)}) + @test isequal(typeintersect((Type{Void},Type{Void}), Type{NTuple{N,Void}}), + Type{(Void,Void)}) end -@test is(None, typeintersect(Type{Any},Type{Complex})) -@test is(None, typeintersect(Type{Any},Type{TypeVar(:T,Real)})) +@test is(Bottom, typeintersect(Type{Any},Type{Complex})) +@test is(Bottom, typeintersect(Type{Any},Type{TypeVar(:T,Real)})) @test !(Type{Array{Integer}} <: Type{AbstractArray{Integer}}) @test !(Type{Array{Integer}} <: Type{Array{TypeVar(:T,Integer)}}) -@test is(None, typeintersect(Type{Function},UnionType)) +@test is(Bottom, typeintersect(Type{Function},UnionType)) @test is(Type{Int32}, typeintersect(Type{Int32},DataType)) @test !(Type <: TypeVar) -@test !is(None, typeintersect(DataType, Type)) -@test !is(None, typeintersect(UnionType, Type)) -@test !is(None, typeintersect(DataType, Type{Int})) -@test !is(None, typeintersect(DataType, Type{TypeVar(:T,Int)})) -@test !is(None, typeintersect(DataType, Type{TypeVar(:T,Integer)})) +@test !is(Bottom, typeintersect(DataType, Type)) +@test !is(Bottom, typeintersect(UnionType, Type)) +@test !is(Bottom, typeintersect(DataType, Type{Int})) +@test !is(Bottom, typeintersect(DataType, Type{TypeVar(:T,Int)})) +@test !is(Bottom, typeintersect(DataType, Type{TypeVar(:T,Integer)})) @test typeintersect((Int...), (Bool...)) === () -@test typeintersect(Type{(Int...)}, Type{(Bool...)}) === None +@test typeintersect(Type{(Int...)}, Type{(Bool...)}) === Bottom @test typeintersect((Bool,Int...), (Bool...)) === (Bool,) let T = TypeVar(:T,Union(Float32,Float64)) @@ -129,8 +131,8 @@ end @test issubtype(Array{(Any...)}, Array{NTuple}) @test !issubtype(Array{(Int...)}, Array{NTuple}) @test !issubtype(Array{(Int,Int)}, Array{NTuple}) -@test issubtype(Type{(Nothing,)}, (Type{Nothing},)) -@test issubtype((Type{Nothing},),Type{(Nothing,)}) +@test issubtype(Type{(Void,)}, (Type{Void},)) +@test issubtype((Type{Void},),Type{(Void,)}) # this is fancy: know that any type T<:Number must be either a DataType or a UnionType @test Type{TypeVar(:T,Number)} <: Union(DataType,UnionType) @@ -138,8 +140,8 @@ end @test Type{TypeVar(:T,Tuple)} <: Union(Tuple,UnionType) @test !(Type{TypeVar(:T,Tuple)} <: Union(DataType,UnionType)) -@test !is(None, typeintersect((DataType,DataType),Type{TypeVar(:T,(Number,Number))})) -@test !is(None, typeintersect((DataType,UnionType),Type{(Number,None)})) +@test !is(Bottom, typeintersect((DataType,DataType),Type{TypeVar(:T,(Number,Number))})) +@test !is(Bottom, typeintersect((DataType,UnionType),Type{(Number,Bottom)})) # issue #2997 let T = TypeVar(:T,Union(Float64,Array{Float64,1}),true) @@ -164,7 +166,7 @@ end @test Base.typeseq(typejoin(Union(Int,String),Int), Union(Int,String)) @test Base.typeseq(typejoin(Union(Int,String),Int8), Any) -@test promote_type(Bool,None) === Bool +@test promote_type(Bool,Bottom) === Bool # ntuples nttest1{n}(x::NTuple{n,Int}) = n @@ -613,12 +615,11 @@ end # sufficient information # issue #814 begin - local MatOrNothing, my_func, M - typealias MatOrNothing{T} Union(AbstractMatrix{T}, Vector{None}) - my_func{T<:Real}(A::MatOrNothing{T}, B::MatOrNothing{T}, - C::MatOrNothing{T}) = 0 + local MatOrNot, my_func, M + typealias MatOrNot{T} Union(AbstractMatrix{T}, Vector{Union()}) + my_func{T<:Real}(A::MatOrNot{T}, B::MatOrNot{T}, C::MatOrNot{T}) = 0 M = [ 2. 1. ; 1. 1. ] - @test my_func([], M, M) == 0 + @test my_func(Union()[], M, M) == 0 end begin @@ -866,7 +867,7 @@ end # issue #2365 type B2365{T} - v::Union(T, Nothing) + v::Union(T, Void) end @test B2365{Int}(nothing).v === nothing @test B2365{Int}(0).v === 0 @@ -1036,7 +1037,7 @@ function foo(x) end return ret end -x = Array(Union(Dict{Int64,String},Array{Int64,3},Number,String,Nothing), 3) +x = Array(Union(Dict{Int64,String},Array{Int64,3},Number,String,Void), 3) x[1] = 1.0 x[2] = 2.0 x[3] = 3.0 @@ -1153,7 +1154,7 @@ try end # issue #4526 -f4526(x) = isa(x.a, Nothing) +f4526(x) = isa(x.a, Void) @test_throws ErrorException f4526(1) @test_throws ErrorException f4526(im) @test_throws ErrorException f4526(1+2im) @@ -1261,7 +1262,7 @@ abstract IT4805{N, T} let T = TypeVar(:T,Int,true) N = TypeVar(:N,true) - @test typeintersect(Type{IT4805{1,T}}, Type{TypeVar(:_,IT4805{N,Int})}) != None + @test typeintersect(Type{IT4805{1,T}}, Type{TypeVar(:_,IT4805{N,Int})}) != Bottom end let @@ -1301,7 +1302,7 @@ f5150(T) = Array(Rational{T},1) # issue #5165 bitstype 64 T5165{S} -make_t(x::Int64) = Base.box(T5165{Nothing}, Base.unbox(Int64, x)) +make_t(x::Int64) = Base.box(T5165{Void}, Base.unbox(Int64, x)) xs5165 = T5165[make_t(int64(1))] b5165 = IOBuffer() for x in xs5165 @@ -1334,7 +1335,7 @@ end # issue #5254 f5254{T}(::Type{T}, b::T) = 0 f5254(a, b) = 1 -@test f5254(None, 1) == 1 +@test f5254(Bottom, 1) == 1 # evaluate arguments left-to-right, including assignments. issue #4990 let @@ -1360,7 +1361,7 @@ cnvt(T, x) = convert_default(T, x, cnvt) cnvt{S, T, N}(::Type{Array{S, N}}, x::Array{T, N}) = convert(Array{S}, x) function tighttypes!(adf) - T = None + T = Bottom tt = {Int} for t in tt T = typejoin(T, t) @@ -1737,7 +1738,7 @@ f6980(::Union(Int, Float64), ::B6980) = true @test f6980(1, B6980()) # issue #7049 -typealias Maybe7049{T} Union(T,Nothing) +typealias Maybe7049{T} Union(T,Void) function ttt7049(;init::Maybe7049{Union(String,(Int,Char))} = nothing) string("init=", init) end @@ -1842,8 +1843,8 @@ end # issue #8184 immutable Foo8184 - x::Nothing - y::Nothing + x::Void + y::Void z::Float64 end let f = Foo8184(nothing,nothing,1.0) diff --git a/test/float16.jl b/test/float16.jl index c6cdd3a08581b..76897b685d88e 100644 --- a/test/float16.jl +++ b/test/float16.jl @@ -94,4 +94,4 @@ let end # issue #5948 -@test string(reinterpret(Float16, 0x7bff)) == "float16(65500.0)" +@test string(reinterpret(Float16, 0x7bff)) == "65500.0" diff --git a/test/functional.jl b/test/functional.jl index 0c222b45666d5..4afe89609bce9 100644 --- a/test/functional.jl +++ b/test/functional.jl @@ -13,9 +13,9 @@ let io=IOBuffer(3) @test takebuf_string(io)=="12" end -# map over [] should return [] +# map over Bottom[] should return Bottom[] # issue #6719 -@test isequal(typeof(map(x -> x, [])), Array{None,1}) +@test isequal(typeof(map(x -> x, Array(Union(),0))), Array{Union(),1}) # maps of tuples (formerly in test/core.jl) -- tuple.jl @test map((x,y)->x+y,(1,2,3),(4,5,6)) == (5,7,9) diff --git a/test/intfuncs.jl b/test/intfuncs.jl new file mode 100644 index 0000000000000..8700b6088aa7f --- /dev/null +++ b/test/intfuncs.jl @@ -0,0 +1,16 @@ +# issue #8266 + +@test ndigits(-15, 10) == 2 +@test ndigits(-15, -10) == 2 +@test ndigits(-1, 10) == 1 +@test ndigits(-1, -10) == 2 +@test ndigits(2, 10) == 1 +@test ndigits(2, -10) == 1 +@test ndigits(10, 10) == 2 +@test ndigits(10, -10) == 3 +@test ndigits(17, 10) == 2 +@test ndigits(17, -10) == 3 +@test ndigits(unsigned(17), -10) == 3 + +@test ndigits(146, -3) == 5 + diff --git a/test/linalg/tridiag.jl b/test/linalg/tridiag.jl new file mode 100644 index 0000000000000..45445546606f7 --- /dev/null +++ b/test/linalg/tridiag.jl @@ -0,0 +1,124 @@ +debug = false + +using Base.Test + +#Test equivalence of eigenvectors/singular vectors taking into account possible phase (sign) differences +function test_approx_eq_vecs{S<:Real,T<:Real}(a::StridedVecOrMat{S}, b::StridedVecOrMat{T}, error=nothing) + n = size(a, 1) + @test n==size(b,1) && size(a,2)==size(b,2) + error==nothing && (error=n^3*(eps(S)+eps(T))) + for i=1:n + ev1, ev2 = a[:,i], b[:,i] + deviation = min(abs(norm(ev1-ev2)),abs(norm(ev1+ev2))) + if !isnan(deviation) + @test_approx_eq_eps deviation 0.0 error + end + end +end + +n = 12 #Size of matrix problem to test + +debug && println("SymTridiagonal (symmetric tridiagonal) matrices") +for relty in (Float32, Float64), elty in (relty, )#XXX Complex{relty}) doesn't work + debug && println("elty is $(elty), relty is $(relty)") + a = convert(Vector{elty}, randn(n)) + b = convert(Vector{elty}, randn(n-1)) + if elty <: Complex + a += im*convert(Vector{elty}, randn(n)) + b += im*convert(Vector{elty}, randn(n-1)) + end + + A = SymTridiagonal(a, b) + fA = (elty <: Complex ? complex128:float64)(full(A)) + + debug && println("Idempotent tests") + for func in (conj, transpose, ctranspose) + @test func(func(A)) == A + end + + debug && println("Simple unary functions") + for func in (det, inv) + @test_approx_eq_eps func(A) func(fA) n^2*sqrt(eps(relty)) + end + + debug && println("Multiplication with strided vector") + @test_approx_eq A*ones(n) full(A)*ones(n) + + debug && println("Multiplication with strided matrix") + @test_approx_eq A*ones(n, 2) full(A)*ones(n, 2) + + debug && println("Eigensystems") + zero, infinity = convert(elty, 0), convert(elty, Inf) + debug && println("This tests eigenvalue and eigenvector computations using stebz! and stein!") + w, iblock, isplit = LAPACK.stebz!('V', 'B', -infinity, infinity, 0, 0, zero, a, b) + evecs = LAPACK.stein!(a, b, w) + + (e, v) = eig(SymTridiagonal(a, b)) + @test_approx_eq e w + test_approx_eq_vecs(v, evecs) + + debug && println("stein! call using iblock and isplit") + w, iblock, isplit = LAPACK.stebz!('V', 'B', -infinity, infinity, 0, 0, zero, a, b) + evecs = LAPACK.stein!(a, b, w, iblock, isplit) + test_approx_eq_vecs(v, evecs) + + debug && println("Binary operations") + a = convert(Vector{elty}, randn(n)) + b = convert(Vector{elty}, randn(n - 1)) + if elty <: Complex + a += im*convert(Vector{elty}, randn(n - 1)) + b += im*convert(Vector{elty}, randn(n)) + end + + B = SymTridiagonal(a, b) + fB = (elty <: Complex ? complex128:float64)(full(B)) + + for op in (+, -, *) + @test_approx_eq full(op(A, B)) op(fA, fB) + end +end + +debug && println("Tridiagonal matrices") +for relty in (Float32, Float64), elty in (relty, Complex{relty}) + debug && println("relty is $(relty), elty is $(elty)") + a = convert(Vector{elty}, randn(n - 1)) + b = convert(Vector{elty}, randn(n)) + c = convert(Vector{elty}, randn(n - 1)) + if elty <: Complex + a += im*convert(Vector{elty}, randn(n - 1)) + b += im*convert(Vector{elty}, randn(n)) + c += im*convert(Vector{elty}, randn(n - 1)) + end + + A = Tridiagonal(a, b, c) + fA = (elty <: Complex ? complex128:float64)(full(A)) + + debug && println("Simple unary functions") + for func in (det, inv) + @test_approx_eq_eps func(A) func(fA) n^2*sqrt(eps(relty)) + end + + debug && println("Binary operations") + a = convert(Vector{elty}, randn(n - 1)) + b = convert(Vector{elty}, randn(n)) + c = convert(Vector{elty}, randn(n - 1)) + if elty <: Complex + a += im*convert(Vector{elty}, randn(n - 1)) + b += im*convert(Vector{elty}, randn(n)) + c += im*convert(Vector{elty}, randn(n - 1)) + end + + debug && println("Multiplication with strided vector") + @test_approx_eq A*ones(n) full(A)*ones(n) + + debug && println("Multiplication with strided matrix") + @test_approx_eq A*ones(n, 2) full(A)*ones(n, 2) + + + B = Tridiagonal(a, b, c) + fB = (elty <: Complex ? complex128:float64)(full(B)) + + for op in (+, -, *) + @test_approx_eq full(op(A, B)) op(fA, fB) + end +end \ No newline at end of file diff --git a/test/linalg4.jl b/test/linalg4.jl index fe1928298ce9d..8580b715cad05 100644 --- a/test/linalg4.jl +++ b/test/linalg4.jl @@ -25,98 +25,6 @@ end n=12 #Size of matrix problem to test -debug && println("Tridiagonal matrices") -for relty in (Float32, Float64), elty in (relty, Complex{relty}) - debug && println("relty is $(relty), elty is $(elty)") - a = convert(Vector{elty}, randn(n-1)) - b = convert(Vector{elty}, randn(n)) - c = convert(Vector{elty}, randn(n-1)) - if elty <: Complex - a += im*convert(Vector{elty}, randn(n-1)) - b += im*convert(Vector{elty}, randn(n)) - c += im*convert(Vector{elty}, randn(n-1)) - end - - A=Tridiagonal(a, b, c) - fA=(elty<:Complex?complex128:float64)(full(A)) - - debug && println("Simple unary functions") - for func in (det, inv) - @test_approx_eq_eps func(A) func(fA) n^2*sqrt(eps(relty)) - end - - debug && println("Binary operations") - a = convert(Vector{elty}, randn(n-1)) - b = convert(Vector{elty}, randn(n)) - c = convert(Vector{elty}, randn(n-1)) - if elty <: Complex - a += im*convert(Vector{elty}, randn(n-1)) - b += im*convert(Vector{elty}, randn(n)) - c += im*convert(Vector{elty}, randn(n-1)) - end - - B=Tridiagonal(a, b, c) - fB=(elty<:Complex?complex128:float64)(full(B)) - - for op in (+, -, *) - @test_approx_eq full(op(A, B)) op(fA, fB) - end -end - -debug && println("SymTridiagonal (symmetric tridiagonal) matrices") -for relty in (Float32, Float64), elty in (relty, )#XXX Complex{relty}) doesn't work - debug && println("elty is $(elty), relty is $(relty)") - a = convert(Vector{elty}, randn(n)) - b = convert(Vector{elty}, randn(n-1)) - if elty <: Complex - a += im*convert(Vector{elty}, randn(n)) - b += im*convert(Vector{elty}, randn(n-1)) - end - - A=SymTridiagonal(a, b) - fA=(elty<:Complex?complex128:float64)(full(A)) - - debug && println("Idempotent tests") - for func in (conj, transpose, ctranspose) - @test func(func(A)) == A - end - - debug && println("Simple unary functions") - for func in (det, inv) - @test_approx_eq_eps func(A) func(fA) n^2*sqrt(eps(relty)) - end - - debug && println("Eigensystems") - zero, infinity = convert(elty, 0), convert(elty, Inf) - debug && println("This tests eigenvalue and eigenvector computations using stebz! and stein!") - w, iblock, isplit = LinAlg.LAPACK.stebz!('V','B',-infinity,infinity,0,0,zero,a,b) - evecs = LinAlg.LAPACK.stein!(a,b,w) - - (e, v)=eig(SymTridiagonal(a,b)) - @test_approx_eq e w - test_approx_eq_vecs(v, evecs) - - debug && println("stein! call using iblock and isplit") - w, iblock, isplit = LinAlg.LAPACK.stebz!('V','B',-infinity,infinity,0,0,zero,a,b) - evecs = LinAlg.LAPACK.stein!(a,b,w,iblock,isplit) - test_approx_eq_vecs(v, evecs) - - debug && println("Binary operations") - a = convert(Vector{elty}, randn(n)) - b = convert(Vector{elty}, randn(n-1)) - if elty <: Complex - a += im*convert(Vector{elty}, randn(n-1)) - b += im*convert(Vector{elty}, randn(n)) - end - - B=SymTridiagonal(a, b) - fB=(elty<:Complex?complex128:float64)(full(B)) - - for op in (+, -, *) - @test_approx_eq full(op(A, B)) op(fA, fB) - end -end - #Issue #7647: test xsyevr, xheevr, xstevr drivers for Mi7647 in {Symmetric(diagm([1.0:3.0])), Hermitian(diagm([1.0:3.0])), Hermitian(diagm(complex([1.0:3.0]))), SymTridiagonal([1.0:3.0], zeros(2))} diff --git a/test/lineedit.jl b/test/lineedit.jl index 01a7241198abc..60efd42db265f 100644 --- a/test/lineedit.jl +++ b/test/lineedit.jl @@ -4,24 +4,24 @@ using TestHelpers a_foo = 0 const foo_keymap = { - 'a' => :( global a_foo; a_foo += 1) + 'a' => (o...)->(global a_foo; a_foo += 1) } b_foo = 0 const foo2_keymap = { - 'b' => :( global b_foo; b_foo += 1) + 'b' => (o...)->(global b_foo; b_foo += 1) } a_bar = 0 b_bar = 0 const bar_keymap = { - 'a' => :( global a_bar; a_bar += 1), - 'b' => :( global b_bar; b_bar += 1) + 'a' => (o...)->(global a_bar; a_bar += 1), + 'b' => (o...)->(global b_bar; b_bar += 1) } -test1_func = @eval @LineEdit.keymap $foo_keymap +test1_func = LineEdit.keymap([foo_keymap]) function run_test(f,buf) global a_foo, a_bar, b_bar @@ -34,13 +34,13 @@ end run_test(test1_func,IOBuffer("aa")) @test a_foo == 2 -test2_func = @eval @LineEdit.keymap $([foo2_keymap, foo_keymap]) +test2_func = LineEdit.keymap([foo2_keymap, foo_keymap]) run_test(test2_func,IOBuffer("aaabb")) @test a_foo == 3 @test b_foo == 2 -test3_func = @eval @LineEdit.keymap $([bar_keymap, foo_keymap]) +test3_func = LineEdit.keymap([bar_keymap, foo_keymap]) run_test(test3_func,IOBuffer("aab")) @test a_bar == 2 @@ -186,7 +186,7 @@ end let term = TestHelpers.FakeTerminal(IOBuffer(), IOBuffer(), IOBuffer()) - s = LineEdit.init_state(term, Base.REPL.ModalInterface([Base.REPL.Prompt("test> ")])) + s = LineEdit.init_state(term, ModalInterface([Prompt("test> ")])) buf = LineEdit.buffer(s) LineEdit.edit_insert(s,"first line\nsecond line\nthird line") diff --git a/test/math.jl b/test/math.jl index bcb187ad43713..b9ac1ff5404c8 100644 --- a/test/math.jl +++ b/test/math.jl @@ -5,26 +5,53 @@ @test exponent(12.8) == 3 # degree-based trig functions -for T = (Float32,Float64) +for T = (Float32,Float64,Rational{Int}) + fT = typeof(float(one(T))) for x = -400:40:400 - @test_approx_eq_eps sind(convert(T,x))::T convert(T,sin(pi/180*x)) eps(deg2rad(convert(T,x))) - @test_approx_eq_eps cosd(convert(T,x))::T convert(T,cos(pi/180*x)) eps(deg2rad(convert(T,x))) - end - for x = 0.0:180:720 - @test sind(convert(T,x)) === zero(T) - @test sind(-convert(T,x)) === -zero(T) + @test_approx_eq_eps sind(convert(T,x))::fT convert(fT,sin(pi/180*x)) eps(deg2rad(convert(fT,x))) + @test_approx_eq_eps cosd(convert(T,x))::fT convert(fT,cos(pi/180*x)) eps(deg2rad(convert(fT,x))) end + + @test sind(convert(T,0.0))::fT === zero(fT) + @test sind(convert(T,180.0))::fT === zero(fT) + @test sind(convert(T,360.0))::fT === zero(fT) + T != Rational{Int} && @test sind(convert(T,-0.0))::fT === -zero(fT) + @test sind(convert(T,-180.0))::fT === -zero(fT) + @test sind(convert(T,-360.0))::fT === -zero(fT) + + @test cosd(convert(T,90))::fT === zero(fT) + @test cosd(convert(T,270))::fT === zero(fT) + @test cosd(convert(T,-90))::fT === zero(fT) + @test cosd(convert(T,-270))::fT === zero(fT) + for x = -3:0.3:3 - @test_approx_eq_eps sinpi(convert(T,x))::T convert(T,sin(pi*x)) eps(pi*convert(T,x)) - @test_approx_eq_eps cospi(convert(T,x))::T convert(T,cos(pi*x)) eps(pi*convert(T,x)) - end - for x = 0.0:1.0:4.0 - @test sinpi(convert(T,x)) === zero(T) - @test sinpi(-convert(T,x)) === -zero(T) + @test_approx_eq_eps sinpi(convert(T,x))::fT convert(fT,sin(pi*x)) eps(pi*convert(fT,x)) + @test_approx_eq_eps cospi(convert(T,x))::fT convert(fT,cos(pi*x)) eps(pi*convert(fT,x)) end + + @test sinpi(convert(T,0.0))::fT === zero(fT) + @test sinpi(convert(T,1.0))::fT === zero(fT) + @test sinpi(convert(T,2.0))::fT === zero(fT) + T != Rational{Int} && @test sinpi(convert(T,-0.0))::fT === -zero(fT) + @test sinpi(convert(T,-1.0))::fT === -zero(fT) + @test sinpi(convert(T,-2.0))::fT === -zero(fT) + + @test cospi(convert(T,0.5))::fT === zero(fT) + @test cospi(convert(T,1.5))::fT === zero(fT) + @test cospi(convert(T,-0.5))::fT === zero(fT) + @test cospi(convert(T,-1.5))::fT === zero(fT) + + # check exact values + @test sind(convert(T,30)) == 0.5 + @test cosd(convert(T,60)) == 0.5 + @test sind(convert(T,150)) == 0.5 + @test sinpi(one(T)/convert(T,6)) == 0.5 + T != Float32 && @test cospi(one(T)/convert(T,3)) == 0.5 + T == Rational{Int} && @test sinpi(5//6) == 0.5 end + # check type stability for T = (Float32,Float64,BigFloat) for f = (sind,cosd,sinpi,cospi) diff --git a/test/meta.jl b/test/meta.jl new file mode 100644 index 0000000000000..0958567bea071 --- /dev/null +++ b/test/meta.jl @@ -0,0 +1,27 @@ +# test meta-expressions that annotate blocks of code + +module MetaTest + +using Base.Test + +function f(x) + y = x+5 + z = y*y + q = z/y + m = q-3 +end + +@inline function f_inlined(x) + y = x+5 + z = y*y + q = z/y + m = q-3 +end + +g(x) = f(2x) +g_inlined(x) = f_inlined(2x) + +@test g(3) == g_inlined(3) +@test f(3) == f_inlined(3) + +end diff --git a/test/nullable.jl b/test/nullable.jl new file mode 100644 index 0000000000000..b46a26c339c5d --- /dev/null +++ b/test/nullable.jl @@ -0,0 +1,230 @@ +types = [ + Bool, + Char, + Float16, + Float32, + Float64, + Int128, + Int16, + Int32, + Int64, + Int8, + Uint16, + Uint32, + Uint64, + Uint8, +] + +# Nullable{T}() = new(true) +for T in types + x = Nullable{T}() + @test x.isnull === true + @test isa(x.value, T) +end + +# Nullable{T}(value::T) = new(false, value) +for T in types + x = Nullable{T}(zero(T)) + @test x.isnull === false + @test isa(x.value, T) + @test x.value === zero(T) + + x = Nullable{T}(one(T)) + @test x.isnull === false + @test isa(x.value, T) + @test x.value === one(T) +end + +# immutable NullException <: Exception +@test isa(NullException(), NullException) +@test_throws NullException throw(NullException()) + +# Nullable{T}(value::T) = Nullable{T}(value) +for T in types + v = zero(T) + x = Nullable(v) + @test x.isnull === false + @test isa(x.value, T) + @test x.value === v + + v = one(T) + x = Nullable(v) + @test x.isnull === false + @test isa(x.value, T) + @test x.value === v +end + +p1s = [ + "Nullable{Bool}()", + "Nullable{Char}()", + "Nullable{Float16}()", + "Nullable{Float32}()", + "Nullable{Float64}()", + "Nullable{Int128}()", + "Nullable{Int16}()", + "Nullable{Int32}()", + "Nullable{Int64}()", + "Nullable{Int8}()", + "Nullable{Uint16}()", + "Nullable{Uint32}()", + "Nullable{Uint64}()", + "Nullable{Uint8}()", +] + +p2s = [ + "Nullable(false)", + "Nullable('\0')", + "Nullable(float16(0.0))", + "Nullable(0.0f0)", + "Nullable(0.0)", + "Nullable(0)", + "Nullable(0)", + "Nullable(0)", + "Nullable(0)", + "Nullable(0)", + "Nullable(0x0000)", + "Nullable(0x00000000)", + "Nullable(0x0000000000000000)", + "Nullable(0x00)", +] + +p3s = [ + "Nullable(true)", + "Nullable('\x01')", + "Nullable(float16(1.0))", + "Nullable(1.0f0)", + "Nullable(1.0)", + "Nullable(1)", + "Nullable(1)", + "Nullable(1)", + "Nullable(1)", + "Nullable(1)", + "Nullable(0x0001)", + "Nullable(0x00000001)", + "Nullable(0x0000000000000001)", + "Nullable(0x01)", +] + +# show{T}(io::IO, x::Nullable{T}) +io = IOBuffer() +for (i, T) in enumerate(types) + x1 = Nullable{T}() + x2 = Nullable(zero(T)) + x3 = Nullable(one(T)) + show(io, x1) + takebuf_string(io) == p1s[i] + show(io, x2) + takebuf_string(io) == p2s[i] + show(io, x3) + takebuf_string(io) == p3s[i] +end + +# get(x::Nullable) +for T in types + x1 = Nullable{T}() + x2 = Nullable(zero(T)) + x3 = Nullable(one(T)) + + @test_throws NullException get(x1) + @test get(x2) === zero(T) + @test get(x3) === one(T) +end + +# get{S, T}(x::Nullable{S}, y::T) +for T in types + x1 = Nullable{T}() + x2 = Nullable(zero(T)) + x3 = Nullable(one(T)) + + @test get(x1, zero(T)) === zero(T) + @test get(x1, one(T)) === one(T) + @test get(x2, one(T)) === zero(T) + @test get(x3, zero(T)) === one(T) +end + +# isnull(x::Nullable) +for T in types + x1 = Nullable{T}() + x2 = Nullable(zero(T)) + x3 = Nullable(one(T)) + + @test isnull(x1) === true + @test isnull(x2) === false + @test isnull(x3) === false +end + +# function isequal{S, T}(x::Nullable{S}, y::Nullable{T}) +for T in types + x1 = Nullable{T}() + x2 = Nullable{T}() + x3 = Nullable(zero(T)) + x4 = Nullable(one(T)) + + @test isequal(x1, x1) === true + @test isequal(x1, x2) === true + @test isequal(x1, x3) === false + @test isequal(x1, x4) === false + + @test isequal(x2, x1) === true + @test isequal(x2, x2) === true + @test isequal(x2, x3) === false + @test isequal(x2, x4) === false + + @test isequal(x3, x1) === false + @test isequal(x3, x2) === false + @test isequal(x3, x3) === true + @test isequal(x3, x4) === false + + @test isequal(x4, x1) === false + @test isequal(x4, x2) === false + @test isequal(x4, x3) === false + @test isequal(x4, x4) === true +end + +# function =={S, T}(x::Nullable{S}, y::Nullable{T}) +for T in types + x1 = Nullable{T}() + x2 = Nullable{T}() + x3 = Nullable(zero(T)) + x4 = Nullable(one(T)) + + @test_throws NullException (x1 == x1) + @test_throws NullException (x1 == x2) + @test_throws NullException (x1 == x3) + @test_throws NullException (x1 == x4) + + @test_throws NullException (x2 == x1) + @test_throws NullException (x2 == x2) + @test_throws NullException (x2 == x3) + @test_throws NullException (x2 == x4) + + @test_throws NullException (x3 == x1) + @test_throws NullException (x3 == x2) + @test_throws NullException (x3 == x3) + @test_throws NullException (x3 == x4) + + @test_throws NullException (x4 == x1) + @test_throws NullException (x4 == x2) + @test_throws NullException (x4 == x3) + @test_throws NullException (x4 == x4) +end + +# function hash(x::Nullable, h::Uint) +for T in types + x1 = Nullable{T}() + x2 = Nullable{T}() + x3 = Nullable(zero(T)) + x4 = Nullable(one(T)) + + @test isa(hash(x1), Uint) + @test isa(hash(x2), Uint) + @test isa(hash(x3), Uint) + @test isa(hash(x4), Uint) + + @test hash(x1) == hash(x2) + @test hash(x1) != hash(x3) + @test hash(x1) != hash(x4) + @test hash(x2) != hash(x3) + @test hash(x2) != hash(x4) + @test hash(x3) != hash(x4) +end diff --git a/test/runtests.jl b/test/runtests.jl index 49798ce055db7..6d51abeaf638c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,9 +8,13 @@ testnames = [ "resolve", "pollfd", "mpfr", "broadcast", "complex", "socket", "floatapprox", "readdlm", "reflection", "regex", "float16", "combinatorics", "sysinfo", "rounding", "ranges", "mod2pi", "euler", "show", - "lineedit", "replcompletions", "repl", "test", "examples", "goto", - "llvmcall", "grisu" + "lineedit", "replcompletions", "repl", "test", "goto", + "llvmcall", "grisu", "nullable", "meta", "staged" ] + +if isdir(joinpath(dirname(@__FILE__), "..", "examples")) + push!(testnames, "examples") +end @unix_only push!(testnames, "unicode") # parallel tests depend on other workers - do them last @@ -21,7 +25,7 @@ tests = (ARGS==["all"] || isempty(ARGS)) ? testnames : ARGS if "linalg" in tests # specifically selected case filter!(x -> x != "linalg", tests) - prepend!(tests, ["linalg1", "linalg2", "linalg3", "linalg4", "linalg/triangular"]) + prepend!(tests, ["linalg1", "linalg2", "linalg3", "linalg4", "linalg/triangular", "linalg/tridiag"]) end net_required_for = ["socket", "parallel"] @@ -35,7 +39,7 @@ end cd(dirname(@__FILE__)) do n = 1 - if net_on + if net_on n = min(8, CPU_CORES, length(tests)) n > 1 && addprocs(n; exeflags=`--check-bounds=yes`) blas_set_num_threads(1) diff --git a/test/show.jl b/test/show.jl index 499c85cf2ec6a..5ad5ad63c101f 100644 --- a/test/show.jl +++ b/test/show.jl @@ -171,3 +171,5 @@ end""" @test_repr "Int[i for i=1:10]" @test_repr "Int[(i, j) for (i, j) in zip(1:10,1:0)]" + +@test_repr "[1 2 3; 4 5 6; 7 8 9]'" diff --git a/test/staged.jl b/test/staged.jl new file mode 100644 index 0000000000000..85e8c4c049f7d --- /dev/null +++ b/test/staged.jl @@ -0,0 +1,78 @@ +stagedfunction staged_t1(a,b) + if a == Int + return :(a+b) + else + return :(a*b) + end +end + +@test staged_t1(1,2) == 3 +@test staged_t1(1.0,0.5) == 0.5 +@test staged_t1(1,0.5) == 1.5 + +tinline(a,b) = staged_t1(a,b) + +@test !isa(tinline(1,2),Expr) +@test tinline(1,0.5) == 1.5 + +stagedfunction splat(a,b...) + :( ($a,$b,a,b) ) +end + +@test splat(1,2,3) == (Int,(Int,Int),1,(2,3)) + +stagediobuf = IOBuffer() +stagedfunction splat2(a...) + print(stagediobuf, a) + :(nothing) +end + +const intstr = @sprintf("%s", Int) +splat2(1) +@test takebuf_string(stagediobuf) == "($intstr,)" +splat2(1,3) +@test takebuf_string(stagediobuf) == "($intstr,$intstr)" +splat2(5,2) +@test takebuf_string(stagediobuf) == "" +splat2(1:3,5.2) +@test takebuf_string(stagediobuf) == "(UnitRange{$intstr},Float64)" +splat2(3,5:2:7) +@test takebuf_string(stagediobuf) == "($intstr,StepRange{$intstr,$intstr})" +splat2(1,2,3,4) +@test takebuf_string(stagediobuf) == "($intstr,$intstr,$intstr,$intstr)" +splat2(1,2,3) +@test takebuf_string(stagediobuf) == "($intstr,$intstr,$intstr)" +splat2(1:5, 3, 3:3) +@test takebuf_string(stagediobuf) == "(UnitRange{$intstr},$intstr,UnitRange{$intstr})" +splat2(1:5, 3, 3:3) +@test takebuf_string(stagediobuf) == "" +splat2(1:5, 3:3, 3) +@test takebuf_string(stagediobuf) == "(UnitRange{$intstr},UnitRange{$intstr},$intstr)" +splat2(1:5, 3:3) +@test takebuf_string(stagediobuf) == "(UnitRange{$intstr},UnitRange{$intstr})" +splat2(3, 3:5) +@test takebuf_string(stagediobuf) == "($intstr,UnitRange{$intstr})" + + +A = rand(5,5,3); +B = slice(A, 1:3, 2, 1:3); +stagedfunction mygetindex(S::SubArray, indexes::Real...) + T, N, A, I = S.parameters + if N != length(indexes) + error("Wrong number of indexes supplied") + end + NP = length(I) + indexexprs = Array(Expr, NP) + j = 1 + for i = 1:NP + if I[i] == Int + indexexprs[i] = :(S.indexes[$i]) + else + indexexprs[i] = :(S.indexes[$i][indexes[$j]]) + j += 1 + end + end + ex = :(S.parent[$(indexexprs...)]) + ex +end +@test mygetindex(B,2,2) == A[2,2,2]