Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' into date-time-records

  • Loading branch information...
commit 56844858d2561a806410a7029e26094e4772330d 2 parents 453fc87 + 91b43f2
Devin Torres authored
4 CHANGELOG.md
View
@@ -1,5 +1,7 @@
* enhancements
- * [String] Support String.downcase and String.upcase according to Unicode 6.2.0
+ * [IEx] Only show documented functions and also show docs for default generated functions
+ * [String] Support `String.downcase` and `String.upcase` according to Unicode 6.2.0
+ * [String] Add support for graphemes in `String.length`, `String.at` and others
* bug fix
* [Kernel] Fix an issue where variables inside clauses remained unassigned
2  Makefile
View
@@ -36,7 +36,7 @@ lib/elixir/src/elixir.app.src: src/elixir.app.src
erlang:
@ cd lib/elixir && $(REBAR) compile
-lib/elixir/ebin/Elixir-String-Unicode.beam: lib/elixir/priv/unicode.ex lib/elixir/priv/UnicodeData.txt
+lib/elixir/ebin/Elixir-String-Unicode.beam: lib/elixir/priv/unicode.ex lib/elixir/priv/UnicodeData.txt lib/elixir/priv/NamedSequences.txt
@ echo "==> unicode (compile)";
@ echo "This step can take up to a minute to compile in order to embed the Unicode database"
@ bin/elixirc --ignore-module-conflict lib/elixir/priv/unicode.ex -o lib/elixir/ebin;
1  lib/elixir/include/elixir.hrl
View
@@ -14,7 +14,6 @@
super=false, %% when true, it means super was invoked
caller=false, %% when true, it means caller was invoked
name_args=false, %% when true, it means arguments should be named
- macro=[], %% a stack with macros nesting
module=nil, %% the current module
function=nil, %% the current function
recur=nil, %% the current loop function to be recurred
2  lib/elixir/lib/kernel.ex
View
@@ -2872,7 +2872,7 @@ defmodule Kernel do
defdelegate other_reverse(list), to: :lists, as: :reverse
end
- My:lists.reverse([1,2,3])
+ MyList.reverse([1,2,3])
#=> [3,2,1]
MyList.other_reverse([1,2,3])
34 lib/elixir/lib/kernel/special_forms.ex
View
@@ -139,8 +139,8 @@ defmodule Kernel.SpecialForms do
import :all, List
- It can also be customized to import only functions or only
- macros:
+ It can also be customized to import only all functions or
+ all macros:
import :functions, List
import :macros, List
@@ -448,11 +448,39 @@ defmodule Kernel.SpecialForms do
@doc """
This is the special form used to hold aliases information.
- At compilation time, it is usually compiled to an atom:
+ It is usually compiled to an atom:
quote do: Foo.Bar
{ :__aliases__, 0, [:Foo,:Bar] }
+ Elixir represents `Foo.Bar` as `__aliases__` so calls can be
+ unambiguously identified by the operator `:.`. For example:
+
+ quote do: Foo.bar
+ {{:.,0,[{:__aliases__,0,[:Foo]},:bar]},0,[]}
+
+ Whenever an expression iterator sees a `:.` as the tuple key,
+ it can be sure that it represents a call and the second element
+ of the arguments list is an atom.
+
+ On the other hand, aliases holds some properties:
+
+ 1) The head element of aliases can be any term;
+
+ 2) The tail elements of aliases are guaranteed to always be atoms;
+
+ 3) When the head element of aliases is the atom :Elixir, no expansion happen;
+
+ 4) When the head element of aliases is not an atom, it is expanded at runtime:
+
+ quote do: some_var.Foo
+ {:__aliases__,0,[{:some_var,0,:quoted},:Bar]}
+
+ Since `some_var` is not available at compilation time, the compiler
+ expands such expression to:
+
+ Module.concat [some_var, Foo]
+
"""
defmacro __aliases__(args)
end
6 lib/elixir/lib/module.ex
View
@@ -316,7 +316,7 @@ defmodule Module do
assert_not_compiled!(:defines?, module)
table = function_table_for(module)
case ETS.lookup(table, tuple) do
- [{ _, ^kind, _, _, _, _, _, _ }] -> true
+ [{ _, ^kind, _, _, _, _, _ }] -> true
_ -> false
end
end
@@ -335,7 +335,7 @@ defmodule Module do
def definitions_in(module) do
assert_not_compiled!(:definitions_in, module)
table = function_table_for(module)
- lc { tuple, _, _, _, _, _, _, _ } inlist ETS.tab2list(table), do: tuple
+ lc { tuple, _, _, _, _, _, _ } inlist ETS.tab2list(table), do: tuple
end
@doc """
@@ -354,7 +354,7 @@ defmodule Module do
def definitions_in(module, kind) do
assert_not_compiled!(:definitions_in, module)
table = function_table_for(module)
- lc { tuple, stored_kind, _, _, _, _, _, _ } inlist ETS.tab2list(table), stored_kind == kind, do: tuple
+ lc { tuple, stored_kind, _, _, _, _, _ } inlist ETS.tab2list(table), stored_kind == kind, do: tuple
end
@doc """
113 lib/elixir/lib/string.ex
View
@@ -1,8 +1,14 @@
defmodule String do
@moduledoc """
A string in Elixir is a utf-8 binary. This module
- contains function to work with utf-8 data and its
- codepoints.
+ contains function to work with utf-8 data, its
+ codepoints and graphemes.
+
+ Notice that graphemes is a superset of UTF-8 codepoints
+ which also contains named sequences as defined per
+ http://www.unicode.org/reports/tr34/. In short, graphemes
+ also contain multiple characters that are "perceived as
+ a single character" by readers.
For working with raw binaries, use Erlang's :binary
module.
@@ -90,7 +96,6 @@ defmodule String do
def printable?(<<>>), do: true
def printable?(_), do: false
-
@doc """
Divides a string into sub string based on a pattern,
returning a list of these sub string. The pattern can
@@ -285,18 +290,47 @@ defmodule String do
String.codepoints("ἅἪῼ") #=> ["ἅ","Ἢ","ῼ"]
"""
- def codepoints(string) do
- do_codepoints(codepoint(string))
- end
+ defdelegate codepoints(string), to: String.Unicode
- defp do_codepoints({char, rest}) do
- [char|do_codepoints(codepoint(rest))]
- end
+ @doc """
+ Returns the next codepoint in a String.
+
+ The result is a tuple with the codepoint and the
+ remaining of the string or `:no_codepoint` in case
+ the String reached its end.
+
+ ## Examples
+
+ String.next_codepoint("josé") #=> { "j", "osé" }
+
+ """
+ defdelegate next_codepoint(string), to: String.Unicode
+
+ @doc """
+ Returns unicode graphemes in the string
+
+ ## Examples
+ String.graphemes("Ā̀stute") # => ["Ā̀","s","t","u","t","e"]
- defp do_codepoints(:no_codepoint), do: []
+ """
+ defdelegate graphemes(string), to: String.Unicode
@doc """
- Returns the first codepoint from an utf8 string.
+ Returns the next grapheme in a String.
+
+ The result is a tuple with the grapheme and the
+ remaining of the string or `:no_grapheme` in case
+ the String reached its end.
+
+ ## Examples
+
+ String.next_grapheme("josé") #=> { "j", "osé" }
+
+ """
+ defdelegate next_grapheme(string), to: String.Unicode
+
+ @doc """
+ Returns the first grapheme from an utf8 string.
## Examples
@@ -305,14 +339,14 @@ defmodule String do
"""
def first(string) do
- case codepoint(string) do
+ case next_grapheme(string) do
{ char, _ } -> char
- :no_codepoint -> ""
+ :no_grapheme -> ""
end
end
@doc """
- Returns the last codepoint from an utf8 string.
+ Returns the last grapheme from an utf8 string.
## Examples
@@ -321,17 +355,17 @@ defmodule String do
"""
def last(string) do
- do_last(codepoint(string), "")
+ do_last(next_grapheme(string), "")
end
defp do_last({char, rest}, _) do
- do_last(codepoint(rest), char)
+ do_last(next_grapheme(rest), char)
end
- defp do_last(:no_codepoint, last_char), do: last_char
+ defp do_last(:no_grapheme, last_char), do: last_char
@doc """
- Returns the number of codepoint in an utf8 string.
+ Returns the number of unicode graphemes in an utf8 string.
## Examples
@@ -340,17 +374,17 @@ defmodule String do
"""
def length(string) do
- do_length(codepoint(string))
+ do_length(next_grapheme(string))
end
defp do_length({_, rest}) do
- 1 + do_length(codepoint(rest))
+ 1 + do_length(next_grapheme(rest))
end
- defp do_length(:no_codepoint), do: 0
+ defp do_length(:no_grapheme), do: 0
@doc """
- Returns the codepoint in the `position` of the given utf8 `string`.
+ Returns the grapheme in the `position` of the given utf8 `string`.
If `position` is greater than `string` length, than it returns `nil`.
## Examples
@@ -359,51 +393,28 @@ defmodule String do
String.at("elixir", 1) #=> "l"
String.at("elixir", 10) #=> nil
String.at("elixir", -1) #=> "r"
- String.at("elixir", -10) #=> "nil"
+ String.at("elixir", -10) #=> nil
"""
def at(string, position) when position >= 0 do
- do_at(codepoint(string), position, 0)
+ do_at(next_grapheme(string), position, 0)
end
def at(string, position) when position < 0 do
- real_pos = do_length(codepoint(string)) - abs(position)
+ real_pos = do_length(next_grapheme(string)) - abs(position)
case real_pos >= 0 do
- true -> do_at(codepoint(string), real_pos, 0)
+ true -> do_at(next_grapheme(string), real_pos, 0)
false -> ""
end
end
defp do_at({_ , rest}, desired_pos, current_pos) when desired_pos > current_pos do
- do_at(codepoint(rest), desired_pos, current_pos + 1)
+ do_at(next_grapheme(rest), desired_pos, current_pos + 1)
end
defp do_at({char, _}, desired_pos, current_pos) when desired_pos == current_pos do
char
end
- defp do_at(:no_codepoint, _, _), do: ""
-
- # Private implementation which returns the first codepoint
- # of any given utf8 string and the rest of it
- # If an empty string is given, :no_codepoint is returned.
- defp codepoint(<<194, char, rest :: binary>>)
- when char in 161..191,
- do: { <<194, char>>, rest }
-
- defp codepoint(<<first, char, rest :: binary>>)
- when first in 195..223 and char in 128..191,
- do: { <<first, char>>, rest }
-
- defp codepoint(<<first, second, char, rest :: binary>>)
- when first == 224 and second in 160..191 and char in 128..191,
- do: { <<first, second, char>>, rest }
-
- defp codepoint(<<first, second, char, rest :: binary>>)
- when first in 225..239 and second in 128..191 and char in 128..191,
- do: { <<first, second, char>>, rest }
-
- defp codepoint(<<other, rest :: binary>>), do: { <<other>>, rest }
-
- defp codepoint(<<>>), do: :no_codepoint
+ defp do_at(:no_grapheme, _, _), do: nil
end
420 lib/elixir/priv/NamedSequences.txt
View
@@ -0,0 +1,420 @@
+LATIN CAPITAL LETTER A WITH MACRON AND GRAVE;0100 0300
+LATIN SMALL LETTER A WITH MACRON AND GRAVE;0101 0300
+LATIN CAPITAL LETTER E WITH VERTICAL LINE BELOW;0045 0329
+LATIN SMALL LETTER E WITH VERTICAL LINE BELOW;0065 0329
+LATIN CAPITAL LETTER E WITH VERTICAL LINE BELOW AND GRAVE;00C8 0329
+LATIN SMALL LETTER E WITH VERTICAL LINE BELOW AND GRAVE;00E8 0329
+LATIN CAPITAL LETTER E WITH VERTICAL LINE BELOW AND ACUTE;00C9 0329
+LATIN SMALL LETTER E WITH VERTICAL LINE BELOW AND ACUTE;00E9 0329
+LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND MACRON;00CA 0304
+LATIN SMALL LETTER E WITH CIRCUMFLEX AND MACRON;00EA 0304
+LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND CARON;00CA 030C
+LATIN SMALL LETTER E WITH CIRCUMFLEX AND CARON;00EA 030C
+LATIN CAPITAL LETTER I WITH MACRON AND GRAVE;012A 0300
+LATIN SMALL LETTER I WITH MACRON AND GRAVE;012B 0300
+LATIN SMALL LETTER I WITH DOT ABOVE AND ACUTE;0069 0307 0301
+LATIN SMALL LETTER NG WITH TILDE ABOVE;006E 0360 0067
+LATIN CAPITAL LETTER O WITH VERTICAL LINE BELOW;004F 0329
+LATIN SMALL LETTER O WITH VERTICAL LINE BELOW;006F 0329
+LATIN CAPITAL LETTER O WITH VERTICAL LINE BELOW AND GRAVE;00D2 0329
+LATIN SMALL LETTER O WITH VERTICAL LINE BELOW AND GRAVE;00F2 0329
+LATIN CAPITAL LETTER O WITH VERTICAL LINE BELOW AND ACUTE;00D3 0329
+LATIN SMALL LETTER O WITH VERTICAL LINE BELOW AND ACUTE;00F3 0329
+LATIN CAPITAL LETTER S WITH VERTICAL LINE BELOW;0053 0329
+LATIN SMALL LETTER S WITH VERTICAL LINE BELOW;0073 0329
+LATIN CAPITAL LETTER U WITH MACRON AND GRAVE;016A 0300
+LATIN SMALL LETTER U WITH MACRON AND GRAVE;016B 0300
+LATIN CAPITAL LETTER A WITH OGONEK AND ACUTE;0104 0301
+LATIN SMALL LETTER A WITH OGONEK AND ACUTE;0105 0301
+LATIN CAPITAL LETTER A WITH OGONEK AND TILDE;0104 0303
+LATIN SMALL LETTER A WITH OGONEK AND TILDE;0105 0303
+LATIN CAPITAL LETTER E WITH OGONEK AND ACUTE;0118 0301
+LATIN SMALL LETTER E WITH OGONEK AND ACUTE;0119 0301
+LATIN CAPITAL LETTER E WITH OGONEK AND TILDE;0118 0303
+LATIN SMALL LETTER E WITH OGONEK AND TILDE;0119 0303
+LATIN CAPITAL LETTER E WITH DOT ABOVE AND ACUTE;0116 0301
+LATIN SMALL LETTER E WITH DOT ABOVE AND ACUTE;0117 0301
+LATIN CAPITAL LETTER E WITH DOT ABOVE AND TILDE;0116 0303
+LATIN SMALL LETTER E WITH DOT ABOVE AND TILDE;0117 0303
+LATIN SMALL LETTER I WITH DOT ABOVE AND GRAVE;0069 0307 0300
+LATIN SMALL LETTER I WITH DOT ABOVE AND TILDE;0069 0307 0303
+LATIN CAPITAL LETTER I WITH OGONEK AND ACUTE;012E 0301
+LATIN SMALL LETTER I WITH OGONEK AND DOT ABOVE AND ACUTE;012F 0307 0301
+LATIN CAPITAL LETTER I WITH OGONEK AND TILDE;012E 0303
+LATIN SMALL LETTER I WITH OGONEK AND DOT ABOVE AND TILDE;012F 0307 0303
+LATIN CAPITAL LETTER J WITH TILDE;004A 0303
+LATIN SMALL LETTER J WITH DOT ABOVE AND TILDE;006A 0307 0303
+LATIN CAPITAL LETTER L WITH TILDE;004C 0303
+LATIN SMALL LETTER L WITH TILDE;006C 0303
+LATIN CAPITAL LETTER M WITH TILDE;004D 0303
+LATIN SMALL LETTER M WITH TILDE;006D 0303
+LATIN CAPITAL LETTER R WITH TILDE;0052 0303
+LATIN SMALL LETTER R WITH TILDE;0072 0303
+LATIN CAPITAL LETTER U WITH OGONEK AND ACUTE;0172 0301
+LATIN SMALL LETTER U WITH OGONEK AND ACUTE;0173 0301
+LATIN CAPITAL LETTER U WITH OGONEK AND TILDE;0172 0303
+LATIN SMALL LETTER U WITH OGONEK AND TILDE;0173 0303
+LATIN CAPITAL LETTER U WITH MACRON AND ACUTE;016A 0301
+LATIN SMALL LETTER U WITH MACRON AND ACUTE;016B 0301
+LATIN CAPITAL LETTER U WITH MACRON AND TILDE;016A 0303
+LATIN SMALL LETTER U WITH MACRON AND TILDE;016B 0303
+LATIN SMALL LETTER AE WITH GRAVE;00E6 0300
+LATIN SMALL LETTER OPEN O WITH GRAVE;0254 0300
+LATIN SMALL LETTER OPEN O WITH ACUTE;0254 0301
+LATIN SMALL LETTER TURNED V WITH GRAVE;028C 0300
+LATIN SMALL LETTER TURNED V WITH ACUTE;028C 0301
+LATIN SMALL LETTER SCHWA WITH GRAVE;0259 0300
+LATIN SMALL LETTER SCHWA WITH ACUTE;0259 0301
+LATIN SMALL LETTER HOOKED SCHWA WITH GRAVE;025A 0300
+LATIN SMALL LETTER HOOKED SCHWA WITH ACUTE;025A 0301
+BENGALI LETTER KHINYA;0995 09CD 09B7
+TAMIL CONSONANT K; 0B95 0BCD
+TAMIL CONSONANT NG; 0B99 0BCD
+TAMIL CONSONANT C; 0B9A 0BCD
+TAMIL CONSONANT NY; 0B9E 0BCD
+TAMIL CONSONANT TT; 0B9F 0BCD
+TAMIL CONSONANT NN; 0BA3 0BCD
+TAMIL CONSONANT T; 0BA4 0BCD
+TAMIL CONSONANT N; 0BA8 0BCD
+TAMIL CONSONANT P; 0BAA 0BCD
+TAMIL CONSONANT M; 0BAE 0BCD
+TAMIL CONSONANT Y; 0BAF 0BCD
+TAMIL CONSONANT R; 0BB0 0BCD
+TAMIL CONSONANT L; 0BB2 0BCD
+TAMIL CONSONANT V; 0BB5 0BCD
+TAMIL CONSONANT LLL;0BB4 0BCD
+TAMIL CONSONANT LL; 0BB3 0BCD
+TAMIL CONSONANT RR; 0BB1 0BCD
+TAMIL CONSONANT NNN;0BA9 0BCD
+TAMIL CONSONANT J; 0B9C 0BCD
+TAMIL CONSONANT SH; 0BB6 0BCD
+TAMIL CONSONANT SS; 0BB7 0BCD
+TAMIL CONSONANT S; 0BB8 0BCD
+TAMIL CONSONANT H; 0BB9 0BCD
+TAMIL CONSONANT KSS;0B95 0BCD 0BB7 0BCD
+TAMIL SYLLABLE KAA; 0B95 0BBE
+TAMIL SYLLABLE KI; 0B95 0BBF
+TAMIL SYLLABLE KII; 0B95 0BC0
+TAMIL SYLLABLE KU; 0B95 0BC1
+TAMIL SYLLABLE KUU; 0B95 0BC2
+TAMIL SYLLABLE KE; 0B95 0BC6
+TAMIL SYLLABLE KEE; 0B95 0BC7
+TAMIL SYLLABLE KAI; 0B95 0BC8
+TAMIL SYLLABLE KO; 0B95 0BCA
+TAMIL SYLLABLE KOO; 0B95 0BCB
+TAMIL SYLLABLE KAU; 0B95 0BCC
+TAMIL SYLLABLE NGAA; 0B99 0BBE
+TAMIL SYLLABLE NGI; 0B99 0BBF
+TAMIL SYLLABLE NGII; 0B99 0BC0
+TAMIL SYLLABLE NGU; 0B99 0BC1
+TAMIL SYLLABLE NGUU; 0B99 0BC2
+TAMIL SYLLABLE NGE; 0B99 0BC6
+TAMIL SYLLABLE NGEE; 0B99 0BC7
+TAMIL SYLLABLE NGAI; 0B99 0BC8
+TAMIL SYLLABLE NGO; 0B99 0BCA
+TAMIL SYLLABLE NGOO; 0B99 0BCB
+TAMIL SYLLABLE NGAU; 0B99 0BCC
+TAMIL SYLLABLE CI; 0B9A 0BBF
+TAMIL SYLLABLE CII; 0B9A 0BC0
+TAMIL SYLLABLE CU; 0B9A 0BC1
+TAMIL SYLLABLE CUU; 0B9A 0BC2
+TAMIL SYLLABLE CE; 0B9A 0BC6
+TAMIL SYLLABLE CEE; 0B9A 0BC7
+TAMIL SYLLABLE CAI; 0B9A 0BC8
+TAMIL SYLLABLE CO; 0B9A 0BCA
+TAMIL SYLLABLE COO; 0B9A 0BCB
+TAMIL SYLLABLE CAU; 0B9A 0BCC
+TAMIL SYLLABLE NYAA; 0B9E 0BBE
+TAMIL SYLLABLE NYI; 0B9E 0BBF
+TAMIL SYLLABLE NYII; 0B9E 0BC0
+TAMIL SYLLABLE NYU; 0B9E 0BC1
+TAMIL SYLLABLE NYUU; 0B9E 0BC2
+TAMIL SYLLABLE NYE; 0B9E 0BC6
+TAMIL SYLLABLE NYEE; 0B9E 0BC7
+TAMIL SYLLABLE NYAI; 0B9E 0BC8
+TAMIL SYLLABLE NYO; 0B9E 0BCA
+TAMIL SYLLABLE NYOO; 0B9E 0BCB
+TAMIL SYLLABLE NYAU; 0B9E 0BCC
+TAMIL SYLLABLE TTAA; 0B9F 0BBE
+TAMIL SYLLABLE TTI; 0B9F 0BBF
+TAMIL SYLLABLE TTII; 0B9F 0BC0
+TAMIL SYLLABLE TTU; 0B9F 0BC1
+TAMIL SYLLABLE TTUU; 0B9F 0BC2
+TAMIL SYLLABLE TTE; 0B9F 0BC6
+TAMIL SYLLABLE TTEE; 0B9F 0BC7
+TAMIL SYLLABLE TTAI; 0B9F 0BC8
+TAMIL SYLLABLE TTO; 0B9F 0BCA
+TAMIL SYLLABLE TTOO; 0B9F 0BCB
+TAMIL SYLLABLE TTAU; 0B9F 0BCC
+TAMIL SYLLABLE NNAA; 0BA3 0BBE
+TAMIL SYLLABLE NNI; 0BA3 0BBF
+TAMIL SYLLABLE NNII; 0BA3 0BC0
+TAMIL SYLLABLE NNU; 0BA3 0BC1
+TAMIL SYLLABLE NNUU; 0BA3 0BC2
+TAMIL SYLLABLE NNE; 0BA3 0BC6
+TAMIL SYLLABLE NNEE; 0BA3 0BC7
+TAMIL SYLLABLE NNAI; 0BA3 0BC8
+TAMIL SYLLABLE NNO; 0BA3 0BCA
+TAMIL SYLLABLE NNOO; 0BA3 0BCB
+TAMIL SYLLABLE NNAU; 0BA3 0BCC
+TAMIL SYLLABLE TAA; 0BA4 0BBE
+TAMIL SYLLABLE TI; 0BA4 0BBF
+TAMIL SYLLABLE TII; 0BA4 0BC0
+TAMIL SYLLABLE TU; 0BA4 0BC1
+TAMIL SYLLABLE TUU; 0BA4 0BC2
+TAMIL SYLLABLE TE; 0BA4 0BC6
+TAMIL SYLLABLE TEE; 0BA4 0BC7
+TAMIL SYLLABLE TAI; 0BA4 0BC8
+TAMIL SYLLABLE TO; 0BA4 0BCA
+TAMIL SYLLABLE TOO; 0BA4 0BCB
+TAMIL SYLLABLE TAU; 0BA4 0BCC
+TAMIL SYLLABLE NAA; 0BA8 0BBE
+TAMIL SYLLABLE NI; 0BA8 0BBF
+TAMIL SYLLABLE NII; 0BA8 0BC0
+TAMIL SYLLABLE NU; 0BA8 0BC1
+TAMIL SYLLABLE NUU; 0BA8 0BC2
+TAMIL SYLLABLE NE; 0BA8 0BC6
+TAMIL SYLLABLE NEE; 0BA8 0BC7
+TAMIL SYLLABLE NAI; 0BA8 0BC8
+TAMIL SYLLABLE NO; 0BA8 0BCA
+TAMIL SYLLABLE NOO; 0BA8 0BCB
+TAMIL SYLLABLE NAU; 0BA8 0BCC
+TAMIL SYLLABLE PAA; 0BAA 0BBE
+TAMIL SYLLABLE PI; 0BAA 0BBF
+TAMIL SYLLABLE PII; 0BAA 0BC0
+TAMIL SYLLABLE PU; 0BAA 0BC1
+TAMIL SYLLABLE PUU; 0BAA 0BC2
+TAMIL SYLLABLE PE; 0BAA 0BC6
+TAMIL SYLLABLE PEE; 0BAA 0BC7
+TAMIL SYLLABLE PAI; 0BAA 0BC8
+TAMIL SYLLABLE PO; 0BAA 0BCA
+TAMIL SYLLABLE POO; 0BAA 0BCB
+TAMIL SYLLABLE PAU; 0BAA 0BCC
+TAMIL SYLLABLE MAA; 0BAE 0BBE
+TAMIL SYLLABLE MI; 0BAE 0BBF
+TAMIL SYLLABLE MII; 0BAE 0BC0
+TAMIL SYLLABLE MU; 0BAE 0BC1
+TAMIL SYLLABLE MUU; 0BAE 0BC2
+TAMIL SYLLABLE ME; 0BAE 0BC6
+TAMIL SYLLABLE MEE; 0BAE 0BC7
+TAMIL SYLLABLE MAI; 0BAE 0BC8
+TAMIL SYLLABLE MO; 0BAE 0BCA
+TAMIL SYLLABLE MOO; 0BAE 0BCB
+TAMIL SYLLABLE MAU; 0BAE 0BCC
+TAMIL SYLLABLE YAA; 0BAF 0BBE
+TAMIL SYLLABLE YI; 0BAF 0BBF
+TAMIL SYLLABLE YII; 0BAF 0BC0
+TAMIL SYLLABLE YU; 0BAF 0BC1
+TAMIL SYLLABLE YUU; 0BAF 0BC2
+TAMIL SYLLABLE YE; 0BAF 0BC6
+TAMIL SYLLABLE YEE; 0BAF 0BC7
+TAMIL SYLLABLE YAI; 0BAF 0BC8
+TAMIL SYLLABLE YO; 0BAF 0BCA
+TAMIL SYLLABLE YOO; 0BAF 0BCB
+TAMIL SYLLABLE YAU; 0BAF 0BCC
+TAMIL SYLLABLE RAA; 0BB0 0BBE
+TAMIL SYLLABLE RI; 0BB0 0BBF
+TAMIL SYLLABLE RII; 0BB0 0BC0
+TAMIL SYLLABLE RU; 0BB0 0BC1
+TAMIL SYLLABLE RUU; 0BB0 0BC2
+TAMIL SYLLABLE RE; 0BB0 0BC6
+TAMIL SYLLABLE REE; 0BB0 0BC7
+TAMIL SYLLABLE RAI; 0BB0 0BC8
+TAMIL SYLLABLE RO; 0BB0 0BCA
+TAMIL SYLLABLE ROO; 0BB0 0BCB
+TAMIL SYLLABLE RAU; 0BB0 0BCC
+TAMIL SYLLABLE LAA; 0BB2 0BBE
+TAMIL SYLLABLE LI; 0BB2 0BBF
+TAMIL SYLLABLE LII; 0BB2 0BC0
+TAMIL SYLLABLE LU; 0BB2 0BC1
+TAMIL SYLLABLE LUU; 0BB2 0BC2
+TAMIL SYLLABLE LE; 0BB2 0BC6
+TAMIL SYLLABLE LEE; 0BB2 0BC7
+TAMIL SYLLABLE LAI; 0BB2 0BC8
+TAMIL SYLLABLE LO; 0BB2 0BCA
+TAMIL SYLLABLE LOO; 0BB2 0BCB
+TAMIL SYLLABLE LAU; 0BB2 0BCC
+TAMIL SYLLABLE VAA; 0BB5 0BBE
+TAMIL SYLLABLE VI; 0BB5 0BBF
+TAMIL SYLLABLE VII; 0BB5 0BC0
+TAMIL SYLLABLE VU; 0BB5 0BC1
+TAMIL SYLLABLE VUU; 0BB5 0BC2
+TAMIL SYLLABLE VE; 0BB5 0BC6
+TAMIL SYLLABLE VEE; 0BB5 0BC7
+TAMIL SYLLABLE VAI; 0BB5 0BC8
+TAMIL SYLLABLE VO; 0BB5 0BCA
+TAMIL SYLLABLE VOO; 0BB5 0BCB
+TAMIL SYLLABLE VAU; 0BB5 0BCC
+TAMIL SYLLABLE LLLAA; 0BB4 0BBE
+TAMIL SYLLABLE LLLI; 0BB4 0BBF
+TAMIL SYLLABLE LLLII; 0BB4 0BC0
+TAMIL SYLLABLE LLLU; 0BB4 0BC1
+TAMIL SYLLABLE LLLUU; 0BB4 0BC2
+TAMIL SYLLABLE LLLE; 0BB4 0BC6
+TAMIL SYLLABLE LLLEE; 0BB4 0BC7
+TAMIL SYLLABLE LLLAI; 0BB4 0BC8
+TAMIL SYLLABLE LLLO; 0BB4 0BCA
+TAMIL SYLLABLE LLLOO; 0BB4 0BCB
+TAMIL SYLLABLE LLLAU; 0BB4 0BCC
+TAMIL SYLLABLE LLAA; 0BB3 0BBE
+TAMIL SYLLABLE LLI; 0BB3 0BBF
+TAMIL SYLLABLE LLII; 0BB3 0BC0
+TAMIL SYLLABLE LLU; 0BB3 0BC1
+TAMIL SYLLABLE LLUU; 0BB3 0BC2
+TAMIL SYLLABLE LLE; 0BB3 0BC6
+TAMIL SYLLABLE LLEE; 0BB3 0BC7
+TAMIL SYLLABLE LLAI; 0BB3 0BC8
+TAMIL SYLLABLE LLO; 0BB3 0BCA
+TAMIL SYLLABLE LLOO; 0BB3 0BCB
+TAMIL SYLLABLE LLAU; 0BB3 0BCC
+TAMIL SYLLABLE RRAA; 0BB1 0BBE
+TAMIL SYLLABLE RRI; 0BB1 0BBF
+TAMIL SYLLABLE RRII; 0BB1 0BC0
+TAMIL SYLLABLE RRU; 0BB1 0BC1
+TAMIL SYLLABLE RRUU; 0BB1 0BC2
+TAMIL SYLLABLE RRE; 0BB1 0BC6
+TAMIL SYLLABLE RREE; 0BB1 0BC7
+TAMIL SYLLABLE RRAI; 0BB1 0BC8
+TAMIL SYLLABLE RRO; 0BB1 0BCA
+TAMIL SYLLABLE RROO; 0BB1 0BCB
+TAMIL SYLLABLE RRAU; 0BB1 0BCC
+TAMIL SYLLABLE NNNAA; 0BA9 0BBE
+TAMIL SYLLABLE NNNI; 0BA9 0BBF
+TAMIL SYLLABLE NNNII; 0BA9 0BC0
+TAMIL SYLLABLE NNNU; 0BA9 0BC1
+TAMIL SYLLABLE NNNUU; 0BA9 0BC2
+TAMIL SYLLABLE NNNE; 0BA9 0BC6
+TAMIL SYLLABLE NNNEE; 0BA9 0BC7
+TAMIL SYLLABLE NNNAI; 0BA9 0BC8
+TAMIL SYLLABLE NNNO; 0BA9 0BCA
+TAMIL SYLLABLE NNNOO; 0BA9 0BCB
+TAMIL SYLLABLE NNNAU; 0BA9 0BCC
+TAMIL SYLLABLE JAA; 0B9C 0BBE
+TAMIL SYLLABLE JI; 0B9C 0BBF
+TAMIL SYLLABLE JII; 0B9C 0BC0
+TAMIL SYLLABLE JU; 0B9C 0BC1
+TAMIL SYLLABLE JUU; 0B9C 0BC2
+TAMIL SYLLABLE JE; 0B9C 0BC6
+TAMIL SYLLABLE JEE; 0B9C 0BC7
+TAMIL SYLLABLE JAI; 0B9C 0BC8
+TAMIL SYLLABLE JO; 0B9C 0BCA
+TAMIL SYLLABLE JOO; 0B9C 0BCB
+TAMIL SYLLABLE JAU; 0B9C 0BCC
+TAMIL SYLLABLE SHAA; 0BB6 0BBE
+TAMIL SYLLABLE SHI; 0BB6 0BBF
+TAMIL SYLLABLE SHII; 0BB6 0BC0
+TAMIL SYLLABLE SHU; 0BB6 0BC1
+TAMIL SYLLABLE SHUU; 0BB6 0BC2
+TAMIL SYLLABLE SHE; 0BB6 0BC6
+TAMIL SYLLABLE SHEE; 0BB6 0BC7
+TAMIL SYLLABLE SHAI; 0BB6 0BC8
+TAMIL SYLLABLE SHO; 0BB6 0BCA
+TAMIL SYLLABLE SHOO; 0BB6 0BCB
+TAMIL SYLLABLE SHAU; 0BB6 0BCC
+TAMIL SYLLABLE SSAA; 0BB7 0BBE
+TAMIL SYLLABLE SSI; 0BB7 0BBF
+TAMIL SYLLABLE SSII; 0BB7 0BC0
+TAMIL SYLLABLE SSU; 0BB7 0BC1
+TAMIL SYLLABLE SSUU; 0BB7 0BC2
+TAMIL SYLLABLE SSE; 0BB7 0BC6
+TAMIL SYLLABLE SSEE; 0BB7 0BC7
+TAMIL SYLLABLE SSAI; 0BB7 0BC8
+TAMIL SYLLABLE SSO; 0BB7 0BCA
+TAMIL SYLLABLE SSOO; 0BB7 0BCB
+TAMIL SYLLABLE SSAU; 0BB7 0BCC
+TAMIL SYLLABLE SAA; 0BB8 0BBE
+TAMIL SYLLABLE SI; 0BB8 0BBF
+TAMIL SYLLABLE SII; 0BB8 0BC0
+TAMIL SYLLABLE SU; 0BB8 0BC1
+TAMIL SYLLABLE SUU; 0BB8 0BC2
+TAMIL SYLLABLE SE; 0BB8 0BC6
+TAMIL SYLLABLE SEE; 0BB8 0BC7
+TAMIL SYLLABLE SAI; 0BB8 0BC8
+TAMIL SYLLABLE SO; 0BB8 0BCA
+TAMIL SYLLABLE SOO; 0BB8 0BCB
+TAMIL SYLLABLE SAU; 0BB8 0BCC
+TAMIL SYLLABLE HAA; 0BB9 0BBE
+TAMIL SYLLABLE HI; 0BB9 0BBF
+TAMIL SYLLABLE HII; 0BB9 0BC0
+TAMIL SYLLABLE HU; 0BB9 0BC1
+TAMIL SYLLABLE HUU; 0BB9 0BC2
+TAMIL SYLLABLE HE; 0BB9 0BC6
+TAMIL SYLLABLE HEE; 0BB9 0BC7
+TAMIL SYLLABLE HAI; 0BB9 0BC8
+TAMIL SYLLABLE HO; 0BB9 0BCA
+TAMIL SYLLABLE HOO; 0BB9 0BCB
+TAMIL SYLLABLE HAU; 0BB9 0BCC
+TAMIL SYLLABLE KSSA; 0B95 0BCD 0BB7
+TAMIL SYLLABLE KSSAA; 0B95 0BCD 0BB7 0BBE
+TAMIL SYLLABLE KSSI; 0B95 0BCD 0BB7 0BBF
+TAMIL SYLLABLE KSSII; 0B95 0BCD 0BB7 0BC0
+TAMIL SYLLABLE KSSU; 0B95 0BCD 0BB7 0BC1
+TAMIL SYLLABLE KSSUU; 0B95 0BCD 0BB7 0BC2
+TAMIL SYLLABLE KSSE; 0B95 0BCD 0BB7 0BC6
+TAMIL SYLLABLE KSSEE; 0B95 0BCD 0BB7 0BC7
+TAMIL SYLLABLE KSSAI; 0B95 0BCD 0BB7 0BC8
+TAMIL SYLLABLE KSSO; 0B95 0BCD 0BB7 0BCA
+TAMIL SYLLABLE KSSOO; 0B95 0BCD 0BB7 0BCB
+TAMIL SYLLABLE KSSAU; 0B95 0BCD 0BB7 0BCC
+TAMIL SYLLABLE SHRII; 0BB6 0BCD 0BB0 0BC0
+SINHALA CONSONANT SIGN YANSAYA;0DCA 200D 0DBA
+SINHALA CONSONANT SIGN RAKAARAANSAYA;0DCA 200D 0DBB
+SINHALA CONSONANT SIGN REPAYA;0DBB 0DCA 200D
+GEORGIAN LETTER U-BRJGU;10E3 0302
+KHMER CONSONANT SIGN COENG KA;17D2 1780
+KHMER CONSONANT SIGN COENG KHA;17D2 1781
+KHMER CONSONANT SIGN COENG KO;17D2 1782
+KHMER CONSONANT SIGN COENG KHO;17D2 1783
+KHMER CONSONANT SIGN COENG NGO;17D2 1784
+KHMER CONSONANT SIGN COENG CA;17D2 1785
+KHMER CONSONANT SIGN COENG CHA;17D2 1786
+KHMER CONSONANT SIGN COENG CO;17D2 1787
+KHMER CONSONANT SIGN COENG CHO;17D2 1788
+KHMER CONSONANT SIGN COENG NYO;17D2 1789
+KHMER CONSONANT SIGN COENG DA;17D2 178A
+KHMER CONSONANT SIGN COENG TTHA;17D2 178B
+KHMER CONSONANT SIGN COENG DO;17D2 178C
+KHMER CONSONANT SIGN COENG TTHO;17D2 178D
+KHMER CONSONANT SIGN COENG NA;17D2 178E
+KHMER CONSONANT SIGN COENG TA;17D2 178F
+KHMER CONSONANT SIGN COENG THA;17D2 1790
+KHMER CONSONANT SIGN COENG TO;17D2 1791
+KHMER CONSONANT SIGN COENG THO;17D2 1792
+KHMER CONSONANT SIGN COENG NO;17D2 1793
+KHMER CONSONANT SIGN COENG BA;17D2 1794
+KHMER CONSONANT SIGN COENG PHA;17D2 1795
+KHMER CONSONANT SIGN COENG PO;17D2 1796
+KHMER CONSONANT SIGN COENG PHO;17D2 1797
+KHMER CONSONANT SIGN COENG MO;17D2 1798
+KHMER CONSONANT SIGN COENG YO;17D2 1799
+KHMER CONSONANT SIGN COENG RO;17D2 179A
+KHMER CONSONANT SIGN COENG LO;17D2 179B
+KHMER CONSONANT SIGN COENG VO;17D2 179C
+KHMER CONSONANT SIGN COENG SHA;17D2 179D
+KHMER CONSONANT SIGN COENG SSA;17D2 179E
+KHMER CONSONANT SIGN COENG SA;17D2 179F
+KHMER CONSONANT SIGN COENG HA;17D2 17A0
+KHMER CONSONANT SIGN COENG LA;17D2 17A1
+KHMER VOWEL SIGN COENG QA;17D2 17A2
+KHMER INDEPENDENT VOWEL SIGN COENG QU;17D2 17A7
+KHMER INDEPENDENT VOWEL SIGN COENG RY;17D2 17AB
+KHMER INDEPENDENT VOWEL SIGN COENG RYY;17D2 17AC
+KHMER INDEPENDENT VOWEL SIGN COENG QE;17D2 17AF
+KHMER VOWEL SIGN OM;17BB 17C6
+KHMER VOWEL SIGN AAM;17B6 17C6
+HIRAGANA LETTER BIDAKUON NGA;304B 309A
+HIRAGANA LETTER BIDAKUON NGI;304D 309A
+HIRAGANA LETTER BIDAKUON NGU;304F 309A
+HIRAGANA LETTER BIDAKUON NGE;3051 309A
+HIRAGANA LETTER BIDAKUON NGO;3053 309A
+KATAKANA LETTER BIDAKUON NGA;30AB 309A
+KATAKANA LETTER BIDAKUON NGI;30AD 309A
+KATAKANA LETTER BIDAKUON NGU;30AF 309A
+KATAKANA LETTER BIDAKUON NGE;30B1 309A
+KATAKANA LETTER BIDAKUON NGO;30B3 309A
+KATAKANA LETTER AINU CE;30BB 309A
+KATAKANA LETTER AINU TU;30C4 309A
+KATAKANA LETTER AINU TO;30C8 309A
+KATAKANA LETTER AINU P;31F7 309A
+MODIFIER LETTER EXTRA-HIGH EXTRA-LOW CONTOUR TONE BAR;02E5 02E9
+MODIFIER LETTER EXTRA-LOW EXTRA-HIGH CONTOUR TONE BAR;02E9 02E5
78 lib/elixir/priv/unicode.ex
View
@@ -10,9 +10,9 @@ defmodule String.Unicode do
:unicode.characters_to_binary([binary_to_integer(codepoint, 16)])
end
- path = File.expand_path("../UnicodeData.txt", __FILE__)
+ data_path = File.expand_path("../UnicodeData.txt", __FILE__)
- codes = Enum.reduce File.iterator!(path), [], fn(line, acc) ->
+ codes = Enum.reduce File.iterator!(data_path), [], fn(line, acc) ->
[ codepoint, _name, _category,
_class, _bidi, _decomposition,
_numeric_1, _numeric_2, _numeric_3,
@@ -26,6 +26,15 @@ defmodule String.Unicode do
end
end
+ seqs_path = File.expand_path("../NamedSequences.txt", __FILE__)
+
+ seqs = Enum.map(File.iterator!(seqs_path), fn(line) ->
+ [ _name, codepoints ] = :binary.split(line, ";", [:global])
+ codepoints = Enum.filter(:binary.split(codepoints, " ", [:global, :trim]),
+ fn(x) -> size(x) > 0 end)
+ Enum.map(codepoints, fn(x) -> to_binary.(x) end)
+ end)
+
# Downcase
lc { codepoint, _upper, lower } inlist codes, lower != "" do
@@ -59,4 +68,69 @@ defmodule String.Unicode do
def upcase(<< >>) do
<< >>
end
+
+ # Graphemes
+
+ lc codepoints inlist seqs do
+ seq_args = quote do: [<< unquote_splicing(codepoints), t :: binary >>]
+ seq_code = quote do: {<< unquote_splicing(codepoints) >>, t}
+ def :next_grapheme, seq_args, [], do: seq_code
+ end
+
+ def next_grapheme(<<>>) do
+ :no_grapheme
+ end
+
+ def next_grapheme(binary) when is_binary(binary) do
+ case next_codepoint(binary) do
+ :no_codepoint -> :no_grapheme
+ other -> other
+ end
+ end
+
+ def graphemes(binary) when is_binary(binary) do
+ do_graphemes(next_grapheme(binary))
+ end
+
+ defp do_graphemes({ c, rest }) do
+ [c|do_graphemes(next_grapheme(rest))]
+ end
+
+ defp do_graphemes(:no_grapheme) do
+ []
+ end
+
+ # Codepoints
+
+ def next_codepoint(<<194, char, rest :: binary>>)
+ when char in 161..191,
+ do: { <<194, char>>, rest }
+
+ def next_codepoint(<<first, char, rest :: binary>>)
+ when first in 195..223 and char in 128..191,
+ do: { <<first, char>>, rest }
+
+ def next_codepoint(<<first, second, char, rest :: binary>>)
+ when first == 224 and second in 160..191 and char in 128..191,
+ do: { <<first, second, char>>, rest }
+
+ def next_codepoint(<<first, second, char, rest :: binary>>)
+ when first in 225..239 and second in 128..191 and char in 128..191,
+ do: { <<first, second, char>>, rest }
+
+ def next_codepoint(<<other, rest :: binary>>), do: { <<other>>, rest }
+
+ def next_codepoint(<<>>), do: :no_codepoint
+
+ def codepoints(binary) when is_binary(binary) do
+ do_codepoints(next_codepoint(binary))
+ end
+
+ defp do_codepoints({ c, rest }) do
+ [c|do_codepoints(next_codepoint(rest))]
+ end
+
+ defp do_codepoints(:no_codepoint) do
+ []
+ end
end
21 lib/elixir/src/elixir_def.erl
View
@@ -6,7 +6,7 @@
reset_last/1,
wrap_definition/7,
store_definition/8,
- store_each/8,
+ store_each/7,
unwrap_stored_definitions/1,
format_error/1]).
-include("elixir.hrl").
@@ -19,7 +19,7 @@ table(Module) -> ?ELIXIR_ATOM_CONCAT([f, Module]).
build_table(Module) ->
FunctionTable = table(Module),
ets:new(FunctionTable, [set, named_table, public]),
- ets:insert(FunctionTable, { last, [] }),
+ reset_last(Module),
FunctionTable.
delete_table(Module) ->
@@ -81,7 +81,6 @@ store_definition(Kind, Line, Module, Name, Args, Guards, Body, RawS) ->
File = TS#elixir_scope.file,
Table = table(Module),
- Stack = TS#elixir_scope.macro,
%% Store function
if
@@ -90,10 +89,10 @@ store_definition(Kind, Line, Module, Name, Args, Guards, Body, RawS) ->
compile_super(Module, TS),
CheckClauses = S#elixir_scope.check_clauses,
store_each(CheckClauses, Kind, File, Location,
- Stack, Table, length(Defaults), Function)
+ Table, length(Defaults), Function)
end,
- [store_each(false, Kind, File, Location, Stack, Table, 0,
+ [store_each(false, Kind, File, Location, Table, 0,
function_for_default(Kind, Name, Default)) || Default <- Defaults],
{ Name, Arity }.
@@ -226,13 +225,13 @@ unwrap_stored_definition([], Exports, Private, Def, Defmacro, Defmacrop, {Functi
%% Helpers
-function_for_stored_definition({{Name, Arity}, _, Line, _, [], _, _, Clauses}, {Functions,Tail}) ->
+function_for_stored_definition({{Name, Arity}, _, Line, _, [], _, Clauses}, {Functions,Tail}) ->
{
[{ function, Line, Name, Arity, lists:reverse(Clauses) }|Functions],
Tail
};
-function_for_stored_definition({{Name, Arity}, _, Line, _, Location, _, _, Clauses}, {Functions,Tail}) ->
+function_for_stored_definition({{Name, Arity}, _, Line, _, Location, _, Clauses}, {Functions,Tail}) ->
{
Functions,
[
@@ -252,22 +251,22 @@ function_for_default(_, Name, { clause, Line, Args, _Guards, _Exprs } = Clause)
%% This function also checks and emit warnings in case
%% the kind, of the visibility of the function changes.
-store_each(Check, Kind, File, Location, Stack, Table, Defaults, {function, Line, Name, Arity, Clauses}) ->
+store_each(Check, Kind, File, Location, Table, Defaults, {function, Line, Name, Arity, Clauses}) ->
case ets:lookup(Table, {Name, Arity}) of
- [{{Name, Arity}, StoredKind, _, _, StoredLocation, StoredStack, StoredDefaults, StoredClauses}] ->
+ [{{Name, Arity}, StoredKind, _, _, StoredLocation, StoredDefaults, StoredClauses}] ->
FinalLocation = StoredLocation,
FinalDefaults = Defaults + StoredDefaults,
FinalClauses = Clauses ++ StoredClauses,
check_valid_kind(Line, File, Name, Arity, Kind, StoredKind),
check_valid_defaults(Line, File, Name, Arity, FinalDefaults),
- Check andalso (Stack == StoredStack) andalso check_valid_clause(Line, File, Name, Arity, Table);
+ Check andalso check_valid_clause(Line, File, Name, Arity, Table);
[] ->
FinalLocation = Location,
FinalDefaults = Defaults,
FinalClauses = Clauses,
Check andalso ets:insert(Table, { last, { Name, Arity } })
end,
- ets:insert(Table, {{Name, Arity}, Kind, Line, File, FinalLocation, Stack, FinalDefaults, FinalClauses}).
+ ets:insert(Table, {{Name, Arity}, Kind, Line, File, FinalLocation, FinalDefaults, FinalClauses}).
%% Validations
4 lib/elixir/src/elixir_def_local.erl
View
@@ -13,7 +13,7 @@ macro_for(_Tuple, _All, nil) -> false;
macro_for(Tuple, All, Module) ->
try ets:lookup(elixir_def:table(Module), Tuple) of
- [{Tuple, Kind, Line, _, _, _, _, Clauses}] when Kind == defmacro; All, Kind == defmacrop ->
+ [{Tuple, Kind, Line, _, _, _, Clauses}] when Kind == defmacro; All, Kind == defmacrop ->
get_function(Line, Module, Clauses);
_ ->
false
@@ -25,7 +25,7 @@ macro_for(Tuple, All, Module) ->
function_for(Module, Name, Arity) ->
Tuple = { Name, Arity },
case ets:lookup(elixir_def:table(Module), Tuple) of
- [{Tuple, _, Line, _, _, _, _, Clauses}] ->
+ [{Tuple, _, Line, _, _, _, Clauses}] ->
get_function(Line, Module, Clauses);
_ ->
[_|T] = erlang:get_stacktrace(),
4 lib/elixir/src/elixir_def_overridable.erl
View
@@ -63,7 +63,7 @@ store(Module, Function, GenerateName) ->
{ Count, [H|T] } = orddict:fetch(Function, Overridable),
overridable(Module, orddict:store(Function, { Count, T }, Overridable)),
- { { Name, Arity }, Kind, Line, File, Location, Stack, Defaults, Clauses } = H,
+ { { Name, Arity }, Kind, Line, File, Location, Defaults, Clauses } = H,
{ FinalKind, FinalName } = case GenerateName of
true -> { defp, name(Module, Function, Overridable) };
@@ -72,7 +72,7 @@ store(Module, Function, GenerateName) ->
Def = { function, Line, FinalName, Arity, Clauses },
elixir_def:store_each(false, FinalKind, File, Location,
- Stack, elixir_def:table(Module), Defaults, Def).
+ elixir_def:table(Module), Defaults, Def).
%% Store pending declarations that were not manually made concrete.
16 lib/elixir/src/elixir_dispatch.erl
View
@@ -59,8 +59,8 @@ dispatch_import(Line, Name, Args, S, Callback) ->
{ error, internal } ->
elixir_import:record(import, Tuple, ?BUILTIN, Module),
elixir_macros:translate({ Name, Line, Args }, S);
- { ok, Receiver, Tree } ->
- translate_expansion(Line, Tree, Receiver, Name, Arity, S)
+ { ok, _Receiver, Tree } ->
+ translate_expansion(Line, Tree, S)
end;
Receiver ->
elixir_import:record(import, Tuple, Receiver, Module),
@@ -87,7 +87,7 @@ dispatch_require(Line, Receiver, Name, Args, S, Callback) ->
{ error, internal } ->
elixir_macros:translate({ Name, Line, Args }, S);
{ ok, Tree } ->
- translate_expansion(Line, Tree, Receiver, Name, Arity, S)
+ translate_expansion(Line, Tree, S)
end
end.
@@ -167,10 +167,12 @@ expand_macro_named(Line, Receiver, Name, Arity, Args, Module, Requires, SEnv) ->
Fun = fun Receiver:ProperName/ProperArity,
expand_macro_fun(Line, Fun, Receiver, Name, Args, Module, Requires, SEnv).
-translate_expansion(Line, Tree, Receiver, Name, Arity, S) ->
- NewS = S#elixir_scope{macro=[{Line,Receiver,Name,Arity}|S#elixir_scope.macro]},
- { TTree, TS } = elixir_translator:translate_each(elixir_quote:linify(Line, Tree), NewS),
- { TTree, TS#elixir_scope{macro=S#elixir_scope.macro} }.
+translate_expansion(Line, Tree, S) ->
+ { TR, TS } = elixir_translator:translate_each(
+ elixir_quote:linify(Line, Tree),
+ S#elixir_scope{check_clauses=false}
+ ),
+ { TR, TS#elixir_scope{check_clauses=S#elixir_scope.check_clauses} }.
%% Helpers
2  lib/elixir/src/elixir_macros.erl
View
@@ -207,7 +207,7 @@ translate({defmodule, Line, [Ref, KV]}, S) ->
{ TRef, S }
end,
- { elixir_module:translate(Line, FRef, Block, S), FS };
+ { elixir_module:translate(Line, FRef, Block, S#elixir_scope{check_clauses=true}), FS };
translate({Kind, Line, [Call]}, S) when ?FUNS(Kind) ->
translate({Kind, Line, [Call, nil]}, S);
2  lib/elixir/src/elixir_module.erl
View
@@ -25,7 +25,6 @@ scope_for_eval(Module, Opts) ->
binding_for_eval(Module, Binding) -> [{'_@MODULE',Module}|Binding].
-
%% TABLE METHODS
data_table(Module) ->
@@ -150,6 +149,7 @@ eval_form(Line, Module, Block, Vars, RawS) ->
{ Value, NewS } = elixir_compiler:eval_forms([Block], Line, Temp, Vars, S),
elixir_def_overridable:store_pending(Module),
eval_callbacks(Line, Module, before_compile, [Module], NewS),
+ elixir_def_overridable:store_pending(Module),
Value.
%% Return the form with exports and function declarations.
5 lib/elixir/src/elixir_scope.erl
View
@@ -79,7 +79,7 @@ filename(Other) -> element(3, Other).
serialize(S) ->
elixir_tree_helpers:abstract_syntax(
- { S#elixir_scope.file, S#elixir_scope.functions, S#elixir_scope.check_clauses, S#elixir_scope.macro,
+ { S#elixir_scope.file, S#elixir_scope.functions, S#elixir_scope.check_clauses,
S#elixir_scope.requires, S#elixir_scope.macros, S#elixir_scope.aliases, S#elixir_scope.scheduled }
).
@@ -87,12 +87,11 @@ serialize(S) ->
deserialize(Tuple) -> deserialize(Tuple, []).
-deserialize({ File, Functions, CheckClauses, Macro, Requires, Macros, Aliases, Scheduled }, Vars) ->
+deserialize({ File, Functions, CheckClauses, Requires, Macros, Aliases, Scheduled }, Vars) ->
#elixir_scope{
file=File,
functions=Functions,
check_clauses=CheckClauses,
- macro=Macro,
requires=Requires,
macros=Macros,
aliases=Aliases,
34 lib/elixir/test/elixir/module_test.exs
View
@@ -170,6 +170,16 @@ defmodule ModuleTest do
end)
end
+ def __on_definition__(env, kind, name, args, guards, expr) do
+ Process.put(env.module, :called)
+ assert env.module == ModuleTest.OnDefinition
+ assert kind == :def
+ assert name == :hello
+ assert [{ :foo, _, _ }, { :bar, _ ,_ }] = args
+ assert [] = guards
+ assert [do: { :+, _, [{ :foo, _, _ }, { :bar, _, _ }] }] = expr
+ end
+
test :on_definition do
defmodule OnDefinition do
@on_definition ModuleTest
@@ -182,16 +192,6 @@ defmodule ModuleTest do
assert Process.get(ModuleTest.OnDefinition) == :called
end
- def __on_definition__(env, kind, name, args, guards, expr) do
- Process.put(env.module, :called)
- assert env.module == ModuleTest.OnDefinition
- assert kind == :def
- assert name == :hello
- assert [{ :foo, _, _ }, { :bar, _ ,_ }] = args
- assert [] = guards
- assert [do: { :+, _, [{ :foo, _, _ }, { :bar, _, _ }] }] = expr
- end
-
test :create do
contents =
quote do
@@ -201,4 +201,18 @@ defmodule ModuleTest do
Module.create(ModuleCreateSample, contents, __ENV__)
assert ModuleCreateSample.world
end
+
+ defmacro __before_compile__(_) do
+ quote do
+ def constant, do: 1
+ defoverridable constant: 0
+ end
+ end
+
+ test :overridable_inside_before_compile do
+ defmodule OverridableWithBeforeCompile do
+ @before_compile ModuleTest
+ end
+ assert OverridableWithBeforeCompile.constant == 1
+ end
end
16 lib/elixir/test/elixir/string_test.exs
View
@@ -97,6 +97,15 @@ defmodule StringTest do
assert String.codepoints("ϖͲϥЫݎߟΈټϘለДШव׆ש؇؊صلټܗݎޥޘ߉ऌ૫ሏᶆ℆ℙℱ ⅚Ⅷ↠∈⌘①ffi") == ["ϖ","Ͳ","ϥ","Ы","ݎ","ߟ","Έ","ټ","Ϙ","","Д","Ш","","׆","ש","؇","؊","ص","ل","ټ","ܗ","ݎ","ޥ","ޘ","߉","","","","","","",""," ","","","","","","",""]
end
+ test :graphemes do
+ assert String.graphemes("Ā̀stute") == ["Ā̀","s","t","u","t","e"]
+ end
+
+ test :next_grapheme do
+ assert String.next_grapheme("Ā̀stute") == {"Ā̀","stute"}
+ assert String.next_grapheme("") == :no_grapheme
+ end
+
test :first do
assert String.first("elixir") == "e"
assert String.first("íelixr") == "í"
@@ -105,6 +114,7 @@ defmodule StringTest do
assert String.first("ελιξήριο") == "ε"
assert String.first("סם חיים") == "ס"
assert String.first("がガちゃ") == ""
+ assert String.first("Ā̀stute") == "Ā̀"
assert String.first("") == ""
end
@@ -117,6 +127,7 @@ defmodule StringTest do
assert String.last("סם ייםח") == "ח"
assert String.last("がガちゃ") == ""
assert String.last("") == ""
+ assert String.last("Ā̀") == "Ā̀"
end
test :length do
@@ -127,6 +138,7 @@ defmodule StringTest do
assert String.length("ειξήριολ") == 8
assert String.length("סם ייםח") == 7
assert String.length("がガちゃ") == 4
+ assert String.length("Ā̀stute") == 6
assert String.length("") == 0
end
@@ -134,10 +146,12 @@ defmodule StringTest do
assert String.at("л", 0) == "л"
assert String.at("elixir", 1) == "l"
assert String.at("がガちゃ", 2) == ""
- assert String.at("л", 10) == ""
+ assert String.at("л", 10) == nil
assert String.at("elixir", -1) == "r"
assert String.at("がガちゃ", -2) == ""
assert String.at("л", -3) == ""
+ assert String.at("Ā̀stute", 1) == "s"
+ assert String.at("elixir",6) == nil
end
end
43 lib/iex/lib/iex/autocomplete.ex
View
@@ -9,6 +9,7 @@ defmodule IEx.Autocomplete do
defprotocol Entry do
@moduledoc false
def to_entries(entry)
+ def to_uniq_entries(entry)
def to_hint(entry, hint)
end
@@ -19,6 +20,10 @@ defmodule IEx.Autocomplete do
[mod.name]
end
+ def to_uniq_entries(_fun) do
+ []
+ end
+
def to_hint(Mod[name: name], hint) do
:lists.nthtail(length(hint), name) ++ '.'
end
@@ -31,6 +36,10 @@ defmodule IEx.Autocomplete do
lc a inlist fun.arities, do: '#{fun.name}/#{a}'
end
+ def to_uniq_entries(fun) do
+ to_entries(fun)
+ end
+
def to_hint(Fun[name: name], hint) do
:lists.nthtail(length(hint), name)
end
@@ -48,8 +57,10 @@ defmodule IEx.Autocomplete do
expand_dot reduce(t)
h === ?: ->
expand_erlang_modules
- (h in ?a..?z) or (h in ?A..?Z) or h === ?_ ->
+ identifier?(h) ->
expand_expr reduce(expr)
+ (h == ?/) and t != [] and identifier?(hd(t)) ->
+ expand_expr reduce(t)
h in '(+[' ->
expand ''
true ->
@@ -57,10 +68,14 @@ defmodule IEx.Autocomplete do
end
end
+ defp identifier?(h) do
+ (h in ?a..?z) or (h in ?A..?Z) or h in [?_, ??, ?!]
+ end
+
defp expand_dot(expr) do
case Code.string_to_ast expr do
{:ok, atom} when is_atom(atom) ->
- expand_module_funs atom
+ expand_call atom, ''
{:ok, {:__aliases__,_,list}} ->
expand_elixir_modules list
_ ->
@@ -73,7 +88,7 @@ defmodule IEx.Autocomplete do
{:ok, atom} when is_atom(atom) ->
expand_erlang_modules atom_to_list(atom)
{:ok, { atom, _, nil }} when is_atom(atom) ->
- expand_module_funs Kernel, atom_to_list(atom)
+ expand_call Kernel, atom_to_list(atom)
{:ok, {:__aliases__,_,[root]}} ->
expand_elixir_modules [], atom_to_list(root)
{:ok, {:__aliases__,_,[h|_] = list}} when is_atom(h) ->
@@ -109,7 +124,9 @@ defmodule IEx.Autocomplete do
end
defp format_expansion([uniq], hint) do
- { :yes, Entry.to_hint(uniq, hint), [] }
+ hint = Entry.to_hint(uniq, hint)
+ uniq = if hint == '', do: Entry.to_uniq_entries(uniq), else: []
+ { :yes, hint, uniq }
end
defp format_expansion([first|_]=entries, hint) do
@@ -159,6 +176,10 @@ defmodule IEx.Autocomplete do
no_match
end
+ defp expand_module_funs(mod, hint) do
+ format_expansion module_funs(mod, hint), hint
+ end
+
## Erlang modules
defp expand_erlang_modules(hint // '') do
@@ -208,11 +229,7 @@ defmodule IEx.Autocomplete do
Enum.map(:code.all_loaded, fn({ m, _ }) -> atom_to_list(m) end)
end
- ## Functions
-
- defp expand_module_funs(mod, hint // '') do
- format_expansion module_funs(mod, hint), hint
- end
+ ## Helpers
defp module_funs(mod, hint // '') do
case ensure_loaded(mod) do
@@ -234,11 +251,13 @@ defmodule IEx.Autocomplete do
end
end
- ## Generic Helpers
-
defp get_funs(mod) do
if function_exported?(mod, :__info__, 1) do
- (mod.__info__(:functions) -- [__info__: 1]) ++ mod.__info__(:macros)
+ if docs = mod.__info__(:docs) do
+ lc { tuple, _line, _kind, _sign, doc } inlist docs, doc != false, do: tuple
+ else
+ (mod.__info__(:functions) -- [__info__: 1]) ++ mod.__info__(:macros)
+ end
else
mod.module_info(:exports)
end
30 lib/iex/lib/iex/helpers.ex
View
@@ -77,7 +77,7 @@ defmodule IEx.Helpers do
Shows the documentation for IEx.Helpers.
"""
def h() do
- h(IEx.Helpers, :all)
+ h(IEx.Helpers, :moduledoc)
end
@doc """
@@ -110,7 +110,7 @@ defmodule IEx.Helpers do
defmacro h(other) do
quote do
- h(unquote(other), :all)
+ h(unquote(other), :moduledoc)
end
end
@@ -139,7 +139,7 @@ defmodule IEx.Helpers do
end
end
- def h(module, :all) when is_atom(module) do
+ def h(module, :moduledoc) when is_atom(module) do
case Code.ensure_loaded(module) do
{ :module, _ } ->
case module.__info__(:moduledoc) do
@@ -162,12 +162,14 @@ defmodule IEx.Helpers do
def h(module, function, arity) when is_atom(module) and is_atom(function) and is_integer(arity) do
if docs = module.__info__(:docs) do
doc =
- if tuple = List.keyfind(docs, { function, arity }, 0) do
- print_signature(tuple)
+ cond do
+ d = find_doc(docs, function, arity) -> d
+ d = find_default_doc(docs, function, arity) -> d
+ true -> nil
end
if doc do
- IO.write "\n" <> doc
+ IO.write "\n" <> print_signature(doc)
else
IO.puts "No docs for #{function}/#{arity}"
end
@@ -176,6 +178,22 @@ defmodule IEx.Helpers do
end
end
+ defp find_doc(docs, function, arity) do
+ List.keyfind(docs, { function, arity }, 0)
+ end
+
+ defp find_default_doc(docs, function, min) do
+ Enum.find docs, fn(doc) ->
+ case elem(doc, 0) do
+ { ^function, max } when max > min ->
+ defaults = Enum.count elem(doc, 3), match?({ ://, _, _ }, &1)
+ min + defaults >= max
+ _ ->
+ false
+ end
+ end
+ end
+
# Get the full signature from a function.
defp print_signature({ _info, _line, _kind, _args, false }) do
false
5 lib/iex/test/iex/autocomplete_test.exs
View
@@ -54,6 +54,11 @@ defmodule IEx.AutocompleteTest do
assert expand('System.ve') == {:yes, 'rsion', []}
end
+ test :elixir_function_completion_with_arity do
+ assert expand('Enum.all?') == {:yes, '', ['all?/2']}
+ assert expand('Enum.all?/') == {:yes, '', ['all?/2']}
+ end
+
test :elixir_macro_completion do
{:yes, '', list} = expand('Kernel.is_')
assert is_list(list)
Please sign in to comment.
Something went wrong with that request. Please try again.