Current section

Files

Jump to
mazurka lib mazurka compiler kernel.ex
Raw

lib/mazurka/compiler/kernel.ex

defmodule Mazurka.Compiler.Kernel do
def imports do
[
{:import, [],
[{:__aliases__, [alias: false], [:Kernel]}, [only: [..: 2,
<>: 2,
alias!: 1,
binding: 0,
binding: 1,
destructure: 2,
def: 1,
def: 2,
defdelegate: 2,
defp: 1,
defp: 2,
defmacro: 1,
defmacro: 2,
defmacrop: 1,
defmacrop: 2,
defstruct: 1,
defexception: 1,
defprotocol: 2,
defimpl: 2,
defimpl: 3,
defoverridable: 1,
is_nil: 1,
match?: 2,
sigil_S: 2,
sigil_s: 2,
sigil_C: 2,
sigil_R: 2,
sigil_w: 2,
var!: 2,
unless: 2,
use: 1,
use: 2,], warn: false]]},
{:import, [],
[{:__aliases__, [alias: false], [:Mazurka, :Compiler, :Kernel]}, [warn: false]]}
]
end
def wrap(block) do
{:__block__, [], Kernel."++"(imports, [block])}
end
defmacro prop(name) when Kernel.is_atom(name) do
{:etude_prop, [], [name]}
end
defmacro prop({name, _, _}) when Kernel.is_atom(name) do
{:etude_prop, [], [name]}
end
defmacro load(dict) do
{:etude_dict_load, [], [dict]}
end
defmacro load(dict, keys) do
{:etude_dict_load, [], [dict, keys]}
end
defmacro link_to(resource, params \\ nil, query \\ nil, fragment \\ nil) do
link(__CALLER__, :link_to, resource, params, query, fragment)
end
defmacro transition_to(resource, params \\ nil, query \\ nil, fragment \\ nil) do
link(__CALLER__, :transition_to, resource, params, query, fragment)
end
defmacro invalidates(resource, params \\ nil, query \\ nil, fragment \\ nil) do
link(__CALLER__, :invalidates, resource, params, query, fragment)
end
defp link(caller, function, resource, params, query, fragment) do
[parent_module | _] = caller.context_modules
parent = %{caller | module: parent_module}
resource_name = Macro.expand(resource, parent)
Mazurka.Compiler.Utils.put(parent, nil, Mazurka.Resource.Link, resource_name, params)
params = Mazurka.Resource.Link.format_params(params)
quote do
^^Mazurka.Resource.Link.unquote(function)(unquote(resource_name), unquote(params), unquote(query), unquote(fragment))
end
end
defmacro status(code) do
quote do
^^Mazurka.Runtime.put_status(unquote(code))
end
end
defmacro if(expression, arms) do
{:etude_cond, [], [expression, arms]}
end
defmacro raise(expression) do
quote do
^^Mazurka.Runtime.raise(unquote(expression))
end
end
defmacro left |> right do
[{h, _}|t] = Macro.unpipe({:|>, [], [left, right]})
:lists.foldl(fn
({{:^, meta, [x]}, pos}, acc) ->
{:^, meta, [Macro.pipe(acc, x, pos)]}
({x, pos}, acc) ->
Macro.pipe(acc, x, pos)
end, h, t)
end
defmacro lhs || rhs do
{:etude_cond, [], [lhs, [do: lhs, else: rhs]]}
end
defmacro lhs or rhs do
{:etude_cond, [], [lhs, [do: lhs, else: rhs]]}
end
defmacro lhs && rhs do
{:etude_cond, [], [lhs, [do: rhs, else: false]]}
end
defmacro lhs and rhs do
{:etude_cond, [], [lhs, [do: rhs, else: false]]}
end
defmacro lhs &&& rhs do
{:etude_cond, [], [lhs, [do: rhs, else: :undefined]]}
end
defmacro left in right do
quote do
^Enum.member?(unquote(right), unquote(left))
end
end
defmacro elem(tuple, index) when Kernel.is_integer(index) do
index = Kernel.+(index, 1)
quote do
^:erlang.element(unquote(index), unquote(tuple))
end
end
defmacro elem(tuple, index) do
quote do
^:erlang.element(unquote(index) + 1, unquote(tuple))
end
end
defmacro put_elem(tuple, index, value) when Kernel.is_integer(index) do
index = Kernel.+(index, 1)
quote do
^:erlang.setelement(unquote(index), unquote(tuple), unquote(value))
end
end
defmacro put_elem(tuple, index, value) do
quote do
^:erlang.setelement(unquote(index) + 1, unquote(tuple), unquote(value))
end
end
defmacro !({:!, _, [arg]}) do
{:etude_cond, [], [arg, [do: true, else: false]]}
end
defmacro !(arg) do
{:etude_cond, [], [arg, [do: false, else: true]]}
end
defmacro left =~ _right when Kernel.is_binary(left) do
true
end
defmacro left =~ right when Kernel.is_binary(right) do
quote do
^:binary.match(unquote(left), unquote(right)) != :nomatch
end
end
defmacro left =~ right do
quote do
^Kernel.=~(unquote(left), unquote(right))
end
end
defmacro inspect(arg, opts \\ []) do
quote do
^Kernel.inspect(unquote(arg), unquote(opts))
end
end
defmacro struct(struct, kv \\ []) do
quote do
^Kernel.struct(unquote(struct), unquote(kv))
end
end
defmacro get_in(data, keys) do
quote do
^Kernel.get_in(unquote(data), unquote(keys))
end
end
defmacro put_in(path, value) do
quote do
^Kernel.put_in(unquote(path), unquote(value))
end
end
defmacro put_in(data, keys, value) do
quote do
^Kernel.put_in(unquote(data), unquote(keys), unquote(value))
end
end
defmacro update_in(path, fun) do
quote do
^Kernel.update_in(unquote(path), unquote(fun))
end
end
defmacro update_in(data, keys, fun) do
quote do
^Kernel.update_in(unquote(data), unquote(keys), unquote(fun))
end
end
defmacro get_and_update_in(path, fun) do
quote do
^Kernel.get_and_update_in(unquote(path), unquote(fun))
end
end
defmacro get_and_update_in(data, keys, fun) do
quote do
^Kernel.get_and_update_in(unquote(data), unquote(keys), unquote(fun))
end
end
defmacro to_string(arg) do
quote do
^String.Chars.to_string(unquote(arg))
end
end
defmacro to_char_list(arg) do
quote do
^List.Chars.to_char_list(unquote(arg))
end
end
defmacro is_nil(arg) do
quote do
unquote(arg) == nil
end
end
defmacro sigil_c({:<<>>, _line, [string]}, []) when Kernel.is_binary(string) do
String.to_char_list(Macro.unescape_string(string))
end
defmacro sigil_c({:<<>>, line, pieces}, []) do
binary = {:<<>>, line, Macro.unescape_tokens(pieces)}
quote do: ^String.to_char_list(unquote(binary))
end
defmacro sigil_r({:<<>>, _line, [string]}, options) when Kernel.is_binary(string) do
binary = Macro.unescape_string(string, fn(x) -> Regex.unescape_map(x) end)
regex = Regex.compile!(binary, :binary.list_to_bin(options))
Macro.escape(regex)
end
defmacro sigil_r({:<<>>, line, pieces}, options) do
binary = {:<<>>, line, Macro.unescape_tokens(pieces, fn(x) -> Regex.unescape_map(x) end)}
quote do: ^Regex.compile!(unquote(binary), unquote(:binary.list_to_bin(options)))
end
defmacro @({:doc, _, [doc]}) do
## TODO figure out how to get the following functions name
name = :todo
quote do
Module.add_doc(__MODULE__, __ENV__.line + 1, :def, {unquote(name), 0}, [], unquote(doc))
end
end
defmacro @(attribute) do
quote do
Elixir.Kernel.@(unquote(attribute))
end
end
e_macros = [abs: [:number],
apply: [:fun, :args],
apply: [:module, :fun, :args],
binary_part: [:binary, :start, :length],
bit_size: [:bitstring],
byte_size: [:binary],
div: [:left, :right],
function_exported?: [:module, :function, :arity],
hd: [:list],
is_atom: [:term],
is_binary: [:term],
is_bitstring: [:term],
is_boolean: [:term],
is_float: [:term],
is_function: [:term],
is_integer: [:term],
is_list: [:term],
is_map: [:term],
is_number: [:term],
is_pid: [:term],
is_port: [:term],
is_reference: [:term],
is_tuple: [:term],
length: [:list],
make_ref: [],
map_size: [:map],
max: [:first, :second],
min: [:first, :second],
node: [],
node: [:arg],
rem: [:left, :right],
round: [:number],
send: [:dest, :msg],
self: [],
spawn: [:fun],
spawn: [:module, :fun, :args],
spawn_link: [:fun],
spawn_link: [:module, :fun, :args],
spawn_monitor: [:fun],
spawn_monitor: [:module, :fun, :args],
throw: [:term],
tl: [:list],
trunc: [:number],
tuple_size: [:tuple],
not: [:arg]
]
for {name, args} <- e_macros do
args = Enum.map(args, &(Macro.var(&1, nil)))
defmacro unquote(name)(unquote_splicing(args)) do
{:^, [], [{{:., [], [:erlang, unquote(name)]}, [], unquote(args)}]}
end
end
e_infix_macros = [:+,
:-,
:*,
:/,
:++,
:--,
:<,
:>,
{:<=, :"=<"},
:>=,
:==,
{:!=, :"/="},
{:===, :"=:="},
{:!==, :"=/="}
]
for conf <- e_infix_macros do
{source, target} = case conf do
t when is_atom(t) ->
{t, t}
t ->
t
end
defmacro unquote(source)(left, right) do
{:^, [], [{{:., [], [:erlang, unquote(target)]}, [], [left, right]}]}
end
end
end