diff --git a/docs/3_modules.md b/docs/3_modules.md index 79ca91082f..66b3367d6b 100644 --- a/docs/3_modules.md +++ b/docs/3_modules.md @@ -69,16 +69,14 @@ The file will be compiled in memory and executed, printing 3 as result. No byte- ## 3.3 Functions and private functions -Inside a module, we can define functions using `def`: +Inside a module, we can define functions (with `def`) and private function (with `defp`). A function defined with `def` is available to be invoked from other modules while a private function can only be invoked locally. defmodule Math do def sum(a, b) do do_sum(a, b) end - @visibility :private - - def do_sum(a, b) do + defp do_sum(a, b) do a + b end end @@ -86,8 +84,6 @@ Inside a module, we can define functions using `def`: Math.sum(1, 2) #=> 3 Math.do_sum(1, 2) #=> error :undef -In the example above, we define a function called `sum`, then we changed the visibility of functions to private and defined a function called `do_sum`. As we can see in the following lines, `sum` can be called from external, but the private function `do_sum` cannot. - Function declarations also supports guards and multiple clauses. If a function has several clauses, Elixir will try each clause until find one that matches. For example, here is the implementation for a function that checks if the given number is zero or not: defmodule Math do @@ -211,23 +207,16 @@ By calling `use`, a hook called `__using__` will be invoked in `ExUnit::Case` wh ## 3.5 Module data -Elixir also allows module to store their own data. The canonical example for such data is annotating the function visibility as we did above: +Elixir also allows module to store their own data. The canonical example for such data is annotating that a module implements the OTP behavior called `gen_server`: - defmodule Math do - def sum(a, b) do - do_sum(a, b) - end - - @visibility :private - - def do_sum(a, b) do - a + b - end + defmodule MyServer do + @behavior :gen_server + # ... callbacks ... end -Another data used internally by Elixir is is the `@vsn`: +Now if the module above does not implement any of the callbacks required by `gen_server`, a warning will be raised. Another data used internally by Elixir is is the `@vsn`: - defmodule Math do + defmodule MyServer do @vsn 2 end @@ -247,14 +236,14 @@ The following are also reserved by Elixir (as they have special semantics to the Besides the built-in data above, any developer can also add custom data: - defmodule Math do + defmodule MyServer do @my_data 13 IO.puts @my_data #=> 13 end After the module is compiled, the stored custom data can be accessed via `__info__(:data)` and it will return an `Orddict`: - Math.__info__(:data) #=> [my_data: 13] + MyServer.__info__(:data) #=> [my_data: 13] Setting a data to nil automatically discards it from the `Orddict`. diff --git a/lib/code.ex b/lib/code.ex index 862afc3513..84ed141c29 100644 --- a/lib/code.ex +++ b/lib/code.ex @@ -64,9 +64,9 @@ defmodule Code do Erlang.erlang.get_stacktrace end - @visibility :private + ## Helpers - def load_and_push_file(file) do + defp load_and_push_file(file) do server_call { :loaded, file } Erlang.elixir.file to_list(file) file @@ -74,7 +74,7 @@ defmodule Code do # Finds the file given the relative_to path. # If the file is found, returns its path in binary, fails otherwise. - def find_file(file, relative_to) do + defp find_file(file, relative_to) do file = to_binary(file) file = if relative_to do @@ -95,7 +95,7 @@ defmodule Code do end end - def server_call(args) do + defp server_call(args) do Erlang.gen_server.call(:elixir_code_server, args) end end \ No newline at end of file diff --git a/lib/elixir/cli.ex b/lib/elixir/cli.ex index 2603924151..8ad374539d 100644 --- a/lib/elixir/cli.ex +++ b/lib/elixir/cli.ex @@ -33,14 +33,13 @@ defmodule Elixir::CLI do end ## Private - @visibility :private - def invalid_option(option) do + defp invalid_option(option) do IO.puts(:standard_error, "Unknown option #{list_to_binary(option)}") halt(1) end - def shared_option?(list, config, callback) do + defp shared_option?(list, config, callback) do case process_shared(list, config) do match: { [h|t], _ } when h == hd(list) invalid_option h @@ -49,54 +48,54 @@ defmodule Elixir::CLI do end end - def print_stacktrace(stacktrace) do + defp print_stacktrace(stacktrace) do Enum.each stacktrace, fn(s) { IO.puts :standard_error, " #{format_stacktrace(s)}" } end # Process shared options - def process_shared(['-v'|t], config) do + defp process_shared(['-v'|t], config) do IO.puts "Elixir #{Code.version}" process_shared t, config end - def process_shared(['-e',h|t], config) do + defp process_shared(['-e',h|t], config) do process_shared t, config.prepend_commands [{:eval,h}] end - def process_shared(['-pa',h|t], config) do + defp process_shared(['-pa',h|t], config) do Erlang.code.add_patha(h) process_shared t, config end - def process_shared(['-pz',h|t], config) do + defp process_shared(['-pz',h|t], config) do Erlang.code.add_pathz(h) process_shared t, config end - def process_shared(['-f',h|t], config) do + defp process_shared(['-f',h|t], config) do process_shared t, config.prepend_close [{:eval,h}] end - def process_shared(list, config) do + defp process_shared(list, config) do { list, config } end # Process init options - def process_options(['--no-halt'|t], config) do + defp process_options(['--no-halt'|t], config) do process_options t, config.halt(false) end - def process_options(['--'|t], config) do + defp process_options(['--'|t], config) do { config, t } end - def process_options(['+compile'|t], config) do + defp process_options(['+compile'|t], config) do process_compiler t, config.compile(true) end - def process_options([h|t] = list, config) do + defp process_options([h|t] = list, config) do case h do match: '-' ++ _ shared_option? list, config, process_options(_, _) @@ -105,21 +104,21 @@ defmodule Elixir::CLI do end end - def process_options([], config) do + defp process_options([], config) do { config, [] } end # Process compiler options - def process_compiler(['--'|t], config) do + defp process_compiler(['--'|t], config) do { config, t } end - def process_compiler(['-o',h|t], config) do + defp process_compiler(['-o',h|t], config) do process_compiler t, config.output(h) end - def process_compiler([h|t] = list, config) do + defp process_compiler([h|t] = list, config) do case h do match: '-' ++ _ shared_option? list, config, process_compiler(_, _) @@ -128,25 +127,25 @@ defmodule Elixir::CLI do end end - def process_compiler([], config) do + defp process_compiler([], config) do { config, [] } end # Process commands - def process_command({:eval, expr}, _config) do + defp process_command({:eval, expr}, _config) do Erlang.elixir.eval(expr, []) end - def process_command({:load, file}, _config) do + defp process_command({:load, file}, _config) do Code.require_file file end - def process_command({:compile, pattern}, config) do + defp process_command({:compile, pattern}, config) do compile_patterns [pattern], config end - def compile_patterns(lines, config) do + defp compile_patterns(lines, config) do lines = Enum.map lines, File.wildcard(_) concat = List.uniq(List.append(lines)) diff --git a/lib/elixir/formatter.ex b/lib/elixir/formatter.ex index 541fdfd3a7..86aaf4c0ff 100644 --- a/lib/elixir/formatter.ex +++ b/lib/elixir/formatter.ex @@ -23,12 +23,11 @@ defmodule Elixir::Formatter do end ## Private - @visibility :private - def format_token([]), do: "" - def format_token(token), do: list_to_binary(token) + defp format_token([]), do: "" + defp format_token(token), do: list_to_binary(token) - def format_file_line(file_line) do + defp format_file_line(file_line) do if file = Orddict.get(file_line, :file) do file = list_to_binary(file) if line = Orddict.get(file_line, :line) do @@ -41,7 +40,7 @@ defmodule Elixir::Formatter do end end - def format_module_fun_arity(module, fun, arity) do + defp format_module_fun_arity(module, fun, arity) do separator = case atom_to_list(module) do match: '::' ++ _ diff --git a/lib/elixir/macros.ex b/lib/elixir/macros.ex index 2acc9ca5a2..4f12b0b378 100644 --- a/lib/elixir/macros.ex +++ b/lib/elixir/macros.ex @@ -94,6 +94,25 @@ defmodule Elixir::Macros do # defmacro def(name, do: contents) + # Defines a function that is private. Private functions + # can only be accessible from the same module it is defined. + # + # Check `def/2` for more information + # + # ## Examples + # + # defmodule Foo do + # def bar do + # sum(1, 2) + # end + # + # defp sum(a, b), do: a + b + # end + # + # In the example above, `sum` is private and accessing it + # through `Foo.sum` will raise an error. + defmacro defp(name, do: contents) + # Define a record given by name and values. # # ## Examples @@ -1029,7 +1048,6 @@ defmodule Elixir::Macros do end ## Private functions - :elixir_module.set_visibility __MODULE__, :private # Build if clauses by nesting them recursively. # For instance, the following clause: @@ -1056,7 +1074,7 @@ defmodule Elixir::Macros do # end # end # - def build_if_clauses([{ :match, [condition], clause }|t], acc) do + defp build_if_clauses([{ :match, [condition], clause }|t], acc) do new_acc = quote { case !unquote(condition) do match: false @@ -1069,9 +1087,9 @@ defmodule Elixir::Macros do build_if_clauses(t, new_acc) end - def build_if_clauses([{ :match, [], _clause }|_], _) do + defp build_if_clauses([{ :match, [], _clause }|_], _) do error { :badarg, "No conditions given to elsif clause" } end - def build_if_clauses([], acc), do: acc + defp build_if_clauses([], acc), do: acc end \ No newline at end of file diff --git a/lib/enum.ex b/lib/enum.ex index 3a59a35f19..81ab91fcd9 100644 --- a/lib/enum.ex +++ b/lib/enum.ex @@ -25,11 +25,11 @@ defprotocol Enum::Iterator, [iterator(collection)], only: [List, Tuple], as: I # defimpl Enum::Iterator, for: List do # def iterator(_), do: iterate(_) # -# def iterate([h|t]) do +# defp iterate([h|t]) do # { h, t } # end # -# def iterate([]) do +# defp iterate([]) do # __STOP_ITERATOR__ # end # end @@ -314,11 +314,10 @@ defmodule Enum do end ## Implementations - @visibility :private ## all? - def do_all?({ h, next }, iterator, fun) do + defp do_all?({ h, next }, iterator, fun) do case fun.(h) do match: false false @@ -329,13 +328,13 @@ defmodule Enum do end end - def do_all?(__STOP_ITERATOR__, _, _) do + defp do_all?(__STOP_ITERATOR__, _, _) do true end ## any? - def do_any?({ h, next }, iterator, fun) do + defp do_any?({ h, next }, iterator, fun) do case fun.(h) do match: false do_any?(iterator.(next), iterator, fun) @@ -346,13 +345,13 @@ defmodule Enum do end end - def do_any?(__STOP_ITERATOR__, _, _) do + defp do_any?(__STOP_ITERATOR__, _, _) do false end ## detect - def do_detect({ h, next }, iterator, ifnone, fun) do + defp do_detect({ h, next }, iterator, ifnone, fun) do case fun.(h) do match: false do_detect(iterator.(next), iterator, ifnone, fun) @@ -363,13 +362,13 @@ defmodule Enum do end end - def do_detect(__STOP_ITERATOR__, _, ifnone, _) do + defp do_detect(__STOP_ITERATOR__, _, ifnone, _) do ifnone end ## detect_value - def do_detect_value({ h, next }, iterator, ifnone, fun) do + defp do_detect_value({ h, next }, iterator, ifnone, fun) do case fun.(h) do match: false do_detect_value(iterator.(next), iterator, ifnone, fun) @@ -380,24 +379,24 @@ defmodule Enum do end end - def do_detect_value(__STOP_ITERATOR__, _, ifnone, _) do + defp do_detect_value(__STOP_ITERATOR__, _, ifnone, _) do ifnone end ## each - def do_each({ h, next }, iterator, fun) do + defp do_each({ h, next }, iterator, fun) do fun.(h) do_each(iterator.(next), iterator, fun) end - def do_each(__STOP_ITERATOR__, _, _) do + defp do_each(__STOP_ITERATOR__, _, _) do [] end ## filter - def do_filter({ h, next }, iterator, fun) do + defp do_filter({ h, next }, iterator, fun) do case fun.(h) do match: false do_filter(iterator.(next), iterator, fun) @@ -408,115 +407,115 @@ defmodule Enum do end end - def do_filter(__STOP_ITERATOR__, _, _) do + defp do_filter(__STOP_ITERATOR__, _, _) do [] end ## foldl - def do_foldl({ h, next }, iterator, acc, fun) do + defp do_foldl({ h, next }, iterator, acc, fun) do do_foldl(iterator.(next), iterator, fun.(h, acc), fun) end - def do_foldl(__STOP_ITERATOR__, _, acc, _) do + defp do_foldl(__STOP_ITERATOR__, _, acc, _) do acc end ## join # The first item is simply stringified unless ... - def do_join({ h, next }, iterator, joiner, nil) do + defp do_join({ h, next }, iterator, joiner, nil) do do_join(iterator.(next), iterator, joiner, to_binary(h)) end # The first item is __STOP_ITERATOR__, then we return an empty string; - def do_join(__STOP_ITERATOR__, _, _joiner, nil) do + defp do_join(__STOP_ITERATOR__, _, _joiner, nil) do "" end # All other items are concatenated to acc, by first adding the joiner; - def do_join({ h, next }, iterator, joiner, acc) do + defp do_join({ h, next }, iterator, joiner, acc) do acc = << acc | :binary, joiner | :binary, to_binary(h) | :binary >> do_join(iterator.(next), iterator, joiner, acc) end # Until we have to stop iteration, then we return acc. - def do_join(__STOP_ITERATOR__, _, _joiner, acc) do + defp do_join(__STOP_ITERATOR__, _, _joiner, acc) do acc end ## map - def do_map({ h, next }, iterator, fun) do + defp do_map({ h, next }, iterator, fun) do [fun.(h)|do_map(iterator.(next), iterator, fun)] end - def do_map(__STOP_ITERATOR__, _, _) do + defp do_map(__STOP_ITERATOR__, _, _) do [] end ## mapfoldl - def do_mapfoldl({ h, next }, iterator, acc, f) do + defp do_mapfoldl({ h, next }, iterator, acc, f) do { result, acc } = f.(h, acc) { rest, acc } = do_mapfoldl(iterator.(next), iterator, acc, f) { [result|rest], acc } end - def do_mapfoldl(__STOP_ITERATOR__, _, acc, _f) do + defp do_mapfoldl(__STOP_ITERATOR__, _, acc, _f) do { [], acc } end ## times - def do_times_0(limit, limit, _function) do + defp do_times_0(limit, limit, _function) do end - def do_times_0(limit, counter, function) do + defp do_times_0(limit, counter, function) do function.() do_times_0(limit, 1 + counter, function) end - def do_times_1(limit, limit, _function) do + defp do_times_1(limit, limit, _function) do end - def do_times_1(limit, counter, function) do + defp do_times_1(limit, counter, function) do function.(counter) do_times_1(limit, 1 + counter, function) end - def do_times_2(limit, limit, _function, acc) do + defp do_times_2(limit, limit, _function, acc) do acc end - def do_times_2(limit, counter, function, acc) do + defp do_times_2(limit, counter, function, acc) do new_acc = function.(counter, acc) do_times_2(limit, 1 + counter, function, new_acc) end ## comprehensions - def first_comprehension_each(iterator, { h, next }, t, acc, fun) do + defp first_comprehension_each(iterator, { h, next }, t, acc, fun) do first_comprehension_each iterator, iterator.(next), t, next_comprehension(t, acc, fun, [h]), fun end - def first_comprehension_each(_iterator, __STOP_ITERATOR__, _t, acc, _fun) do + defp first_comprehension_each(_iterator, __STOP_ITERATOR__, _t, acc, _fun) do List.reverse(acc) end - def next_comprehension([{h,iterator}|t], acc, fun, args) do + defp next_comprehension([{h,iterator}|t], acc, fun, args) do next_comprehension_each iterator, iterator.(h), t, acc, fun, args end - def next_comprehension([], acc, fun, args) do + defp next_comprehension([], acc, fun, args) do apply fun, [acc|args] end - def next_comprehension_each(iterator, { h, next }, t, acc, fun, args) do + defp next_comprehension_each(iterator, { h, next }, t, acc, fun, args) do next_comprehension_each iterator, iterator.(next), t, next_comprehension(t, acc, fun, [h|args]), fun, args end - def next_comprehension_each(_iterator, __STOP_ITERATOR__, _t, acc, _fun, _args) do + defp next_comprehension_each(_iterator, __STOP_ITERATOR__, _t, acc, _fun, _args) do acc end end @@ -524,13 +523,11 @@ end defimpl Enum::Iterator, for: List do def iterator(_), do: iterate(_) - @visibility :private - - def iterate([h|t]) do + defp iterate([h|t]) do { h, t } end - def iterate([]) do + defp iterate([]) do __STOP_ITERATOR__ end end \ No newline at end of file diff --git a/lib/ex_unit/case.ex b/lib/ex_unit/case.ex index 79ad8d757b..6c43eca3f8 100644 --- a/lib/ex_unit/case.ex +++ b/lib/ex_unit/case.ex @@ -21,9 +21,8 @@ defmodule ExUnit::Case do end ## Private - @visibility :private - def tests_for([{function,0}|t], acc) do + defp tests_for([{function,0}|t], acc) do list = atom_to_list(function) case list do match: 'test_' ++ _ @@ -33,6 +32,6 @@ defmodule ExUnit::Case do end end - def tests_for([_|t], acc), do: tests_for t, acc - def tests_for([], acc), do: List.reverse(acc) + defp tests_for([_|t], acc), do: tests_for t, acc + defp tests_for([], acc), do: List.reverse(acc) end \ No newline at end of file diff --git a/lib/ex_unit/formatter.ex b/lib/ex_unit/formatter.ex index 039218f5fe..a5f2974327 100644 --- a/lib/ex_unit/formatter.ex +++ b/lib/ex_unit/formatter.ex @@ -57,9 +57,7 @@ defmodule ExUnit::Formatter do { :ok, config } end - @visibility :private - - def print_failure({test_case, test, { kind, reason, stacktrace }}, acc) do + defp print_failure({test_case, test, { kind, reason, stacktrace }}, acc) do IO.puts "#{acc}) #{test} (#{test_case})" IO.puts " #{kind} #{format_catch(kind, reason)}\n stacktrace:" Enum.each stacktrace, fn(s){ IO.puts " #{format_stacktrace(s)}" } diff --git a/lib/ex_unit/runner.ex b/lib/ex_unit/runner.ex index a0e7d7e413..dd15e79a45 100644 --- a/lib/ex_unit/runner.ex +++ b/lib/ex_unit/runner.ex @@ -60,20 +60,19 @@ defmodule ExUnit::Runner do end ## Private - @visibility :private - def call_formatter(config, message) do + defp call_formatter(config, message) do Erlang.gen_server.call(config.formatter, message) end # Run each test case in its own process. - def spawn_case(test_case) do + defp spawn_case(test_case) do pid = self() spawn_link fn { run_tests(pid, test_case, test_case.__tests__) } end # For each instanciated object, dispatch each test in it. - def run_tests(pid, test_case, [test|t]) do + defp run_tests(pid, test_case, [test|t]) do final = try do # test_case.setup(test) @@ -95,7 +94,7 @@ defmodule ExUnit::Runner do end # When all tests in a testcase were run, notify the runner. - def run_tests(pid, test_case, []) do + defp run_tests(pid, test_case, []) do pid <- { self(), :each_case, test_case } end end \ No newline at end of file diff --git a/lib/ex_unit/server.ex b/lib/ex_unit/server.ex index 332ec5bb7c..81e1d47eda 100644 --- a/lib/ex_unit/server.ex +++ b/lib/ex_unit/server.ex @@ -70,9 +70,7 @@ defmodule ExUnit::Server do { :ok, config } end - @visibility :private - - def check(function) do + defp check(function) do try do function.() catch: :exit, { :noproc, _ } diff --git a/lib/file.ex b/lib/file.ex index b146a83a79..87ed302f9f 100644 --- a/lib/file.ex +++ b/lib/file.ex @@ -20,20 +20,19 @@ defmodule File do end ## Helpers - @visibility :private # Normalize the given path by removing "..". - def normalize(path), do: normalize(FN.split(path), []) + defp normalize(path), do: normalize(FN.split(path), []) - def normalize([top|t], [_|acc]) when top == ".." | top == '..' do + defp normalize([top|t], [_|acc]) when top == ".." | top == '..' do normalize t, acc end - def normalize([h|t], acc) do + defp normalize([h|t], acc) do normalize t, [h|acc] end - def normalize([], acc) do + defp normalize([], acc) do FN.join List.reverse(acc) end end \ No newline at end of file diff --git a/lib/list.ex b/lib/list.ex index 7bd59bd431..a61d9903ef 100644 --- a/lib/list.ex +++ b/lib/list.ex @@ -100,43 +100,42 @@ defmodule List do end ## Private - @visibility :private # flatten - def do_flatten([h|t], tail) when is_list(h) do + defp do_flatten([h|t], tail) when is_list(h) do do_flatten(h, do_flatten(t, tail)) end - def do_flatten([h|t], tail) do + defp do_flatten([h|t], tail) do [h|do_flatten(t, tail)] end - def do_flatten([], tail) do + defp do_flatten([], tail) do tail end # seq - def do_seq(n, x, l) when n >= 4 do + defp do_seq(n, x, l) when n >= 4 do do_seq(n-4, x-4, [x-3,x-2,x-1,x|l]) end - def do_seq(n, x, l) when n >= 2 do + defp do_seq(n, x, l) when n >= 2 do do_seq(n-2, x-2, [x-1,x|l]) end - def do_seq(1, x, l) do + defp do_seq(1, x, l) do [x|l] end - def do_seq(0, _, l) do + defp do_seq(0, _, l) do l end # uniq - def do_uniq([h|t], acc) do + defp do_uniq([h|t], acc) do case Erlang.lists.member(h, acc) do match: true do_uniq(t, acc) @@ -145,7 +144,7 @@ defmodule List do end end - def do_uniq([], _acc) do + defp do_uniq([], _acc) do [] end end \ No newline at end of file diff --git a/lib/module.ex b/lib/module.ex index 7addc1a522..f6003d095d 100644 --- a/lib/module.ex +++ b/lib/module.ex @@ -108,14 +108,14 @@ defmodule Module do end # Checks if a function was defined and also for its `kind`. - # `kind` can be either :def, :def or :defmacro. + # `kind` can be either :def, :defp or :defmacro. # # ## Examples # # defmodule Example do - # Module.function_defined? __MODULE__, version: 0, :def #=> false + # Module.function_defined? __MODULE__, version: 0, :defp #=> false # def version, do: 1 - # Module.function_defined? __MODULE__, version: 0, :def #=> false + # Module.function_defined? __MODULE__, version: 0, :defp #=> false # end # def function_defined?(module, tuple, kind) do @@ -167,25 +167,24 @@ defmodule Module do new end - # Private - :elixir_module.set_visibility __MODULE__, :private + ## Helpers - def kind_to_entry(:public), do: :public - def kind_to_entry(:private), do: :private - def kind_to_entry(:macro), do: :macros + defp kind_to_entry(:def), do: :public + defp kind_to_entry(:defp), do: :private + defp kind_to_entry(:defmacro), do: :macros - def to_list(list) when is_list(list), do: list - def to_list(bin) when is_binary(bin), do: binary_to_list(bin) + defp to_list(list) when is_list(list), do: list + defp to_list(bin) when is_binary(bin), do: binary_to_list(bin) - def attribute_table_for(module) do + defp attribute_table_for(module) do list_to_atom Erlang.lists.concat([:a, module]) end - def function_table_for(module) do + defp function_table_for(module) do list_to_atom Erlang.lists.concat([:f, module]) end - def assert_already_compiled!(fun, module) do + defp assert_already_compiled!(fun, module) do compiled?(module) || error { :module_already_compiled, "could not call #{fun} on module #{module} because it was already compiled" } diff --git a/lib/protocol.ex b/lib/protocol.ex index d33885edbc..d2ff0c9da5 100644 --- a/lib/protocol.ex +++ b/lib/protocol.ex @@ -78,11 +78,11 @@ defmodule Protocol do lc kind in conversions_for(opts), do: each_protocol_for(module, kind) end - @visibility :private + ## Helpers # Specially handle tuples as they can also be record. # If this is the case, module::Record will be returned. - def each_protocol_for(module, { Tuple, :is_tuple }) do + defp each_protocol_for(module, { Tuple, :is_tuple }) do contents = quote do def __protocol_for__({}) do unquote(module)::Tuple @@ -102,7 +102,7 @@ defmodule Protocol do end # Special case any as we don't need to generate a guard. - def each_protocol_for(module, { _, :is_any }) do + defp each_protocol_for(module, { _, :is_any }) do contents = quote do def __protocol_for__(_) do unquote(module)::Any @@ -113,7 +113,7 @@ defmodule Protocol do end # Generate all others protocols. - def each_protocol_for(module, { kind, fun }) do + defp each_protocol_for(module, { kind, fun }) do contents = quote do def __protocol_for__(arg) when unquote(fun).(arg) do unquote(module)::unquote(kind) @@ -124,7 +124,7 @@ defmodule Protocol do end # Implement the protocol invocation callbacks for each function. - def each_function(module, { name, arity }) do + defp each_function(module, { name, arity }) do # Generate arguments according the arity. The arguments # are named xa, xb and so forth. We cannot use string # interpolation to generate the arguments because of compile @@ -162,7 +162,7 @@ defmodule Protocol do # Converts the protocol expressions as [each(collection), length(collection)] # to an ordered dictionary [each: 1, length: 1] also checking for invalid args - def to_kv(args) do + defp to_kv(args) do :orddict.from_list lc(x in args) { case x do match: { _, _, args } when args == [] or args == false @@ -176,7 +176,7 @@ defmodule Protocol do end # Returns the default conversions according to the given only/except options. - def conversions_for(opts) do + defp conversions_for(opts) do kinds = [ { Tuple, :is_tuple }, { Atom, :is_atom }, diff --git a/lib/string.ex b/lib/string.ex index f16f3571cd..a670e24a42 100644 --- a/lib/string.ex +++ b/lib/string.ex @@ -5,35 +5,35 @@ defmodule String do [char|do_escape(other, char)] end - @visibility :private + ## Helpers - def do_escape([char|t], char) do + defp do_escape([char|t], char) do [?\\,char|do_escape(t, char)] end - def do_escape([h|t], char) when + defp do_escape([h|t], char) when h == ?# | h == ?\b | h == ?\d | h == ?\e | h == ?\f | h == ?\n | h == ?\r | h == ?\\ | h == ?\t | h == ?\v do [?\\,escape_map(h)|do_escape(t, char)] end - def do_escape([h|t], char) do + defp do_escape([h|t], char) do [h|do_escape(t,char)] end - def do_escape([], char) do + defp do_escape([], char) do [char] end - def escape_map(?#), do: ?# - def escape_map(?\b), do: ?b - def escape_map(?\d), do: ?d - def escape_map(?\e), do: ?e - def escape_map(?\f), do: ?f - def escape_map(?\n), do: ?n - def escape_map(?\r), do: ?r - def escape_map(?\\), do: ?\\ - def escape_map(?\t), do: ?t - def escape_map(?\v), do: ?v + defp escape_map(?#), do: ?# + defp escape_map(?\b), do: ?b + defp escape_map(?\d), do: ?d + defp escape_map(?\e), do: ?e + defp escape_map(?\f), do: ?f + defp escape_map(?\n), do: ?n + defp escape_map(?\r), do: ?r + defp escape_map(?\\), do: ?\\ + defp escape_map(?\t), do: ?t + defp escape_map(?\v), do: ?v end \ No newline at end of file diff --git a/lib/string/inspect.ex b/lib/string/inspect.ex index 2682a0dd8f..aa16809a1c 100644 --- a/lib/string/inspect.ex +++ b/lib/string/inspect.ex @@ -29,24 +29,22 @@ defimpl String::Inspect, for: Atom do atom_to_binary(atom, :utf8) end - @visibility :private - # Detect if atom is a module reference (::Foo::Bar::Baz) - def valid_const_identifier?([?:,?:,h|t]) when h >= ?A & h <= ?Z do + defp valid_const_identifier?([?:,?:,h|t]) when h >= ?A & h <= ?Z do valid_const_identifier? valid_identifier?(t) end - def valid_const_identifier?(else), do: else + defp valid_const_identifier?(else), do: else # Detect if atom is :letter_or_underscore - def valid_identifier?([h|t]) when + defp valid_identifier?([h|t]) when (h >= ?a & h <= ?z) | (h >= ?A & h <= ?Z) | (h == ?_) do valid_identifier? t end - def valid_identifier?(else), do: else + defp valid_identifier?(else), do: else end defimpl String::Inspect, for: BitString do @@ -71,17 +69,17 @@ defimpl String::Inspect, for: BitString do as_bitstring(thing) end - @visibility :private + ## Helpers - def as_bitstring(thing) do + defp as_bitstring(thing) do erlang = Erlang.io_lib.format('~p', [thing]) list_to_binary List.reverse(replace(erlang, [])) end - def replace([?:|t], acc), do: replace(t, [?||acc]) - def replace([h|t], acc) when is_list(h), do: replace(t, replace(h, acc)) - def replace([h|t], acc), do: replace(t, [h|acc]) - def replace([], acc), do: acc + defp replace([?:|t], acc), do: replace(t, [?||acc]) + defp replace([h|t], acc) when is_list(h), do: replace(t, replace(h, acc)) + defp replace([h|t], acc), do: replace(t, [h|acc]) + defp replace([], acc), do: acc end defimpl String::Inspect, for: List do diff --git a/src/elixir_def.erl b/src/elixir_def.erl index 5e1f87de7d..e5822879da 100644 --- a/src/elixir_def.erl +++ b/src/elixir_def.erl @@ -1,4 +1,4 @@ -% Holds the logic responsible for functions definition (def and defmacro). +% Holds the logic responsible for functions definition (def, defp and defmacro). -module(elixir_def). -export([build_table/1, delete_table/1, @@ -79,13 +79,19 @@ store_definition(Kind, Line, Module, Name, Args, Guards, Expr, RawS) -> Filename = S#elixir_scope.filename, FunctionTable = table(Module), FunctionName = element(3, Function), - Visibility = elixir_module:visibility(Module), + + %% Normalize visibility and kind + { Final, Visibility } = case Kind of + defmacro -> { defmacro, public }; + defp -> { def, private }; + def -> { def, public } + end, %% Store function - store_each(true, Kind, FunctionTable, Visibility, Filename, Function), + store_each(true, Final, FunctionTable, Visibility, Filename, Function), %% Store defaults - [store_each(false, Kind, FunctionTable, Visibility, Filename, + [store_each(false, Final, FunctionTable, Visibility, Filename, function_for_clause(FunctionName, Default)) || Default <- Defaults], %% Return stored function name and its arity diff --git a/src/elixir_import.erl b/src/elixir_import.erl index 809e3ade40..8ca105a7bd 100644 --- a/src/elixir_import.erl +++ b/src/elixir_import.erl @@ -196,7 +196,6 @@ in_elixir_macros() -> macros_for('::Elixir::Macros'). in_erlang_macros() -> orddict:from_list([ {'=',2}, - {'@',1}, {'+',1}, {'+',2}, {'-',1}, @@ -241,6 +240,7 @@ in_erlang_macros() -> {'module_ref',1}, {'::','*'}, {'def','*'}, + {'defp','*'}, {'defmacro','*'}, {'quote',1}, {'unquote',1}, diff --git a/src/elixir_macros.erl b/src/elixir_macros.erl index 3354458e7b..b6f6774461 100644 --- a/src/elixir_macros.erl +++ b/src/elixir_macros.erl @@ -134,18 +134,18 @@ translate_macro({defmodule, Line, [Ref, [{do,Block}]]}, S) -> { elixir_module:translate(Line, TRef, Block, S), NS }; -translate_macro({Kind, Line, [Call]}, S) when Kind == def; Kind == defmacro -> +translate_macro({Kind, Line, [Call]}, S) when Kind == def; Kind == defmacro; Kind == defp -> record(Kind, S), assert_module_scope(Line, Kind, S), { Name, Args } = elixir_clauses:extract_args(Call), { { tuple, Line, [{ atom, Line, Name }, { integer, Line, length(Args) }] }, S }; -translate_macro({Kind, Line, [Call, KV]}, S) when Kind == def; Kind == defmacro -> +translate_macro({Kind, Line, [Call, KV]}, S) when Kind == def; Kind == defp; Kind == defmacro -> { TCall, Guards } = elixir_clauses:extract_guards(Call), { Name, Args } = elixir_clauses:extract_args(TCall), translate_macro({ Kind, Line, [ Name, Args, Guards, KV ] }, S); -translate_macro({Kind, Line, [Name, Args, Guards, KV]}, S) when Kind == def; Kind == defmacro -> +translate_macro({Kind, Line, [Name, Args, Guards, KV]}, S) when Kind == def; Kind == defp; Kind == defmacro -> record(Kind, S), assert_module_scope(Line, Kind, S), case KV of @@ -155,7 +155,7 @@ translate_macro({Kind, Line, [Name, Args, Guards, KV]}, S) when Kind == def; Kin { TName, TS } = translate_each(Name, S), { elixir_def:wrap_definition(Kind, Line, TName, Args, Guards, Expr, TS), TS }; -translate_macro({Kind, Line, Args}, S) when is_list(Args), Kind == def; Kind == defmacro -> +translate_macro({Kind, Line, Args}, S) when is_list(Args), Kind == def; Kind == defmacro; Kind == defp -> syntax_error(Line, S#elixir_scope.filename, "invalid args for: ", atom_to_list(Kind)); %% Functions diff --git a/src/elixir_module.erl b/src/elixir_module.erl index 472a5803f7..3b751b5aea 100644 --- a/src/elixir_module.erl +++ b/src/elixir_module.erl @@ -1,5 +1,5 @@ -module(elixir_module). --export([translate/4, compile/4, visibility/1, set_visibility/2, +-export([translate/4, compile/4, format_error/1, binding_and_scope_for_eval/4]). -include("elixir.hrl"). @@ -20,22 +20,6 @@ scope_for_eval(Module, S) -> S#elixir_scope{module=Module}. table(Module) -> ?ELIXIR_ATOM_CONCAT([a, Module]). -%% Visibility convenience - -visibility(Module) -> - Table = ?ELIXIR_ATOM_CONCAT([a, Module]), - Data = ets:lookup_element(Table, data, 2), - case orddict:find(visibility, Data) of - { ok, Value } -> Value; - _ -> public - end. - -set_visibility(Module, New) -> - Table = ?ELIXIR_ATOM_CONCAT([a, Module]), - Data = ets:lookup_element(Table, data, 2), - Final = orddict:store(visibility, New, Data), - ets:insert(Table, { data, Final }). - %% TRANSFORMATION METHODS %% Transformation of args and scope into a compiled erlang call. @@ -86,7 +70,7 @@ build(Module) -> %% Attribute table with defaults Table = table(Module), ets:new(Table, [set, named_table, private]), - ets:insert(Table, { data, [{ visibility, public }] }), + ets:insert(Table, { data, [] }), ets:insert(Table, { compile_callbacks, [] }), %% Function and imports table diff --git a/test/elixir/elixir/errors_test.exs b/test/elixir/elixir/errors_test.exs index c685e4e3d0..3d8087a44d 100644 --- a/test/elixir/elixir/errors_test.exs +++ b/test/elixir/elixir/errors_test.exs @@ -79,8 +79,8 @@ defmodule Elixir::ErrorsTest do end def test_visibility_clause_change do - "nofile:4: function foo/1 already defined with visibility public" = - format_catch 'defmodule Foo do\ndef foo(1), do: 1\n@visibility :private\ndef foo(x), do: x\nend' + "nofile:3: function foo/1 already defined with visibility public" = + format_catch 'defmodule Foo do\ndef foo(1), do: 1\ndefp foo(x), do: x\nend' end def test_clause_change do @@ -155,9 +155,8 @@ defmodule Elixir::ErrorsTest do end ## Helpers - @visibility :private - def format_catch(expr) do + defp format_catch(expr) do try do Erlang.elixir.eval(expr) error { :bad_assertion, "Expected function given to format_catch to fail" } diff --git a/test/elixir/kernel/comprehension_test.exs b/test/elixir/kernel/comprehension_test.exs index 310d8f0f03..47891cf76f 100644 --- a/test/elixir/kernel/comprehension_test.exs +++ b/test/elixir/kernel/comprehension_test.exs @@ -79,7 +79,5 @@ defmodule Kernel::ComprehensionTest do end end - @visibility :private - - def nilly, do: nil + defp nilly, do: nil end \ No newline at end of file diff --git a/test/elixir/kernel/partial_application_test.exs b/test/elixir/kernel/partial_application_test.exs index 82cb187caf..2f4ed3e54c 100644 --- a/test/elixir/kernel/partial_application_test.exs +++ b/test/elixir/kernel/partial_application_test.exs @@ -55,9 +55,7 @@ defmodule Kernel::PartialApplicationTest do ::Foo::Bar = fun.(Bar) end - @visibility :private - - def minus(x, y) do + defp minus(x, y) do x - y end end \ No newline at end of file diff --git a/test/elixir/module_test.exs b/test/elixir/module_test.exs index 447d6b1afb..8d1ea07e2d 100644 --- a/test/elixir/module_test.exs +++ b/test/elixir/module_test.exs @@ -33,17 +33,17 @@ defmodule ModuleTest do use ExUnit::Case false = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 } - false = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 }, :public - false = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 }, :private - false = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 }, :macro + false = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 }, :def + false = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 }, :defp + false = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 }, :defmacro contents = quote { def eval_quoted_info, do: { __MODULE__, __FILE__, __LINE__ } } Module.eval_quoted __MODULE__, contents, [], "sample.ex", 13 true = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 } - true = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 }, :public - false = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 }, :private - false = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 }, :macro + true = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 }, :def + false = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 }, :defp + false = Module.function_defined? __MODULE__, { :eval_quoted_info, 0 }, :defmacro Module.merge_data __MODULE__, value: 1 Module.merge_data __MODULE__, other_value: 1 diff --git a/test/elixir/orddict_test.exs b/test/elixir/orddict_test.exs index 58a5464fb9..442dfa3f94 100644 --- a/test/elixir/orddict_test.exs +++ b/test/elixir/orddict_test.exs @@ -42,8 +42,6 @@ defmodule OrddictTest do [] = Orddict.merge(create_empty_dict, create_empty_dict) end - @visibility :private - - def create_empty_dict, do: create_dict([]) - def create_dict(list // [first_key: 1, second_key: 2]), do: Orddict.from_enum(list) + defp create_empty_dict, do: create_dict([]) + defp create_dict(list // [first_key: 1, second_key: 2]), do: Orddict.from_enum(list) end \ No newline at end of file diff --git a/test/elixir/protocol_test.exs b/test/elixir/protocol_test.exs index 4b102123f0..e609c097f3 100644 --- a/test/elixir/protocol_test.exs +++ b/test/elixir/protocol_test.exs @@ -70,10 +70,8 @@ defmodule ProtocolTest do assert_protocol_for(ProtocolTest::WithAll, Reference, make_ref) end - @visibility :private - # Assert that the given protocol is going to be dispatched. - def assert_protocol_for(target, impl, thing) do + defp assert_protocol_for(target, impl, thing) do joined = target::impl ^joined = target.__protocol_for__ thing end @@ -81,7 +79,7 @@ defmodule ProtocolTest do # Dispatch `blank(thing)` to the given `target` # and check if it will dispatch (and successfully fail) # to the proper implementation `impl`. - def assert_undef(target, impl, thing) do + defp assert_undef(target, impl, thing) do try do target.blank(thing) error("Expected invocation to fail") diff --git a/test/erlang/module_test.erl b/test/erlang/module_test.erl index 2a349bd18e..3f13718a11 100644 --- a/test/erlang/module_test.erl +++ b/test/erlang/module_test.erl @@ -82,7 +82,7 @@ macro_file_test() -> private_test() -> F = fun() -> - elixir:eval("defmodule Foo do\n@visibility :private\ndef version, do: __MODULE__\nend"), + elixir:eval("defmodule Foo do\ndefp version, do: __MODULE__\nend"), ?assertError(undef, elixir:eval("Foo.version")) end, test_helper:run_and_remove(F, ['::Foo']).