Skip to content

Commit 2c90dea

Browse files
committed
Started adding enum implementation
1 parent fe9950e commit 2c90dea

File tree

8 files changed

+311
-5
lines changed

8 files changed

+311
-5
lines changed

lib/elixir_script/translator.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ defmodule ElixirScript.Translator do
8383
JSLib.translate_js_function({:__aliases__, context, rest}, function_name, params, env)
8484
end
8585

86+
defp do_translate({:__aliases__, context, [:JS | rest]}, env) do
87+
JSLib.translate_js_module({:__aliases__, context, rest}, env)
88+
end
89+
8690
defp do_translate(ast, env) when is_number(ast) or is_binary(ast) or is_boolean(ast) or is_nil(ast) do
8791
{ Primitive.make_literal(ast), env }
8892
end

lib/elixir_script/translator/kernel/js.ex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ defmodule ElixirScript.Translator.JS do
4242
{ do_translate({name, [], params}, env), env }
4343
end
4444

45+
def translate_js_module(module, env) do
46+
{ do_translate(module, env), env }
47+
end
48+
49+
defp do_translate({:__aliases__, _, module}, env) do
50+
Identifier.make_namespace_members(module)
51+
end
52+
4553
defp do_translate({op, _, [param]}, env) when op in [:typeof, :delete, :void, :-, :+, :!, :"~"] do
4654
Builder.unary_expression(
4755
op,

lib/elixir_script/translator/state.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ defmodule ElixirScript.Translator.State do
2323
|> Map.put(Collectable, ElixirScript.Collectable)
2424
|> Map.put(String.Chars, ElixirScript.String.Chars)
2525
|> Map.put(Enumerable, ElixirScript.Enumerable)
26+
|> Map.put(Enum, ElixirScript.Enum)
27+
|> Map.put(Enum.OutOfBoundsError, ElixirScript.Enum.OutOfBoundsError)
2628
|> Map.put(Integer, ElixirScript.Integer)
2729
|> Map.put(Macro.Env, ElixirScript.Macro.Env)
2830
|> Map.put(View, ElixirScript.View)

priv/std_lib/base.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule ElixirScript.Base do
22
@moduledoc false
33

44
def encode64(data) do
5-
ElixirScript.Bootstrap.b64EncodeUnicode(data)
5+
ElixirScript.Bootstrap.Functions.b64EncodeUnicode(data)
66
end
77

88
defp can_decode64(data) do

priv/std_lib/bootstrap/functions.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ defmodule ElixirScript.Bootstrap.Functions do
3636
end
3737

3838
def b64EncodeUnicode(str) do
39-
{:ok, regex} = Regex.compile("%([0-9A-F]{2})", "g")
39+
regex = Regex.compile!("%([0-9A-F]{2})", "g")
4040

4141
JS.btoa(
42-
JS.encodeURIComponent(str).replace(regex, fn (match, p1) ->
42+
JS.encodeURIComponent(str).replace(regex, fn (match, p1, _, _) ->
4343
JS.String.fromCharCode("0x#{p1}")
4444
end)
4545
)

priv/std_lib/enum.ex

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
defmodule ElixirScript.Enum do
2+
3+
def all?(enumerable, fun \\ fn(x) -> x end) do
4+
{_, acc} = Enumerable.reduce(enumerable, {:cont, true}, fn(item, _) ->
5+
if fun.(item) do
6+
{:cont, true}
7+
else
8+
{:halt, false}
9+
end
10+
end)
11+
12+
acc
13+
end
14+
15+
def any?(enumerable, fun \\ fn(x) -> x end) do
16+
{_, acc} = Enumerable.reduce(enumerable, {:cont, true}, fn(item, _) ->
17+
if fun.(item) do
18+
{:halt, true}
19+
else
20+
{:cont, false}
21+
end
22+
end)
23+
24+
acc
25+
end
26+
27+
def at(enumerable, n, default \\ nil) do
28+
cond do
29+
n > Enumerable.count(enumerable) ->
30+
default
31+
true ->
32+
result = Enumerable.reduce(enumerable, {:cont, 0}, fn(item, acc) ->
33+
if n == acc do
34+
{:halt, item}
35+
else
36+
{:cont, acc + 1}
37+
end
38+
end)
39+
40+
case result do
41+
{:cont, _} ->
42+
default
43+
{:halt, item} ->
44+
item
45+
end
46+
end
47+
end
48+
49+
def concat([enumerable]) do
50+
enumerable
51+
end
52+
53+
def concat([h | t]) do
54+
h.concat(t)
55+
end
56+
57+
def count(enumerable) do
58+
{:ok, num} = Enumerable.count(enumerable)
59+
num
60+
end
61+
62+
def count(enumerable, fun) do
63+
{_, acc} = Enumerable.reduce(enumerable, {:cont, 0}, fn(item, acc) ->
64+
if fun.(item) do
65+
{:cont, acc + 1}
66+
else
67+
{:cont, acc}
68+
end
69+
end)
70+
71+
acc
72+
end
73+
74+
def reduce(enumerable, fun) do
75+
{_, result} = Enumerable.reduce(enumerable, {:cont, nil}, fn
76+
item, nil ->
77+
{:cont, {:acc, item}}
78+
item, {:acc, acc} ->
79+
{:cont, {:acc, fun.(item, acc)}}
80+
end)
81+
82+
result
83+
end
84+
85+
def reduce(enumerable, acc, fun) do
86+
{_, result} = Enumerable.reduce(enumerable, {:cont, acc}, fn
87+
item, acc ->
88+
{:cont, fun.(item, acc)}
89+
end)
90+
91+
result
92+
end
93+
94+
95+
def map(enumerable, fun) do
96+
reduce(enumerable, [], fn(x, acc) ->
97+
acc ++ fun.(x)
98+
end)
99+
end
100+
101+
def map_reduce(enumerable, acc, fun) do
102+
reduce(enumerable, {[], acc}, fn(x, {m, acc}) ->
103+
{v, new_acc} = fun.(x, acc)
104+
{m ++ [v], new_acc}
105+
end)
106+
end
107+
108+
def each(enumerable, fun) do
109+
map(enumerable, fun)
110+
:ok
111+
end
112+
113+
def empty?(enumerable) do
114+
{:ok, count} = Enumerable.count(enumerable)
115+
count == 0
116+
end
117+
118+
def fetch(enumerable, index) do
119+
result = Enumerable.reduce(enumerable, {:cont, 0}, fn(item, acc) ->
120+
if index == acc do
121+
{:halt, {:ok, item}}
122+
else
123+
{:cont, acc + 1}
124+
end
125+
end)
126+
127+
case result do
128+
{:cont, _} ->
129+
:error
130+
{:halt, item} ->
131+
item
132+
end
133+
end
134+
135+
def fetch!(enumerable, index) do
136+
case fetch(enumerable, index) do
137+
{:ok, item} ->
138+
item
139+
:error ->
140+
raise Enum.OutOfBoundsError
141+
end
142+
end
143+
144+
def filter(enumerable, fun) do
145+
reduce(enumerable, [], fn(x, acc) ->
146+
if fun.(x) do
147+
acc ++ [x]
148+
else
149+
acc
150+
end
151+
end)
152+
end
153+
154+
def filter_map(enumerable, filter, mapper) do
155+
reduce(enumerable, [], fn(x, acc) ->
156+
if filter.(x) do
157+
acc ++ [mapper.(x)]
158+
else
159+
acc
160+
end
161+
end)
162+
end
163+
164+
def find(enumerable, default \\ nil, fun) do
165+
{_, result} = Enumerable.reduce(enumerable, {:cont, default}, fn(item, acc) ->
166+
if fun.(item) do
167+
{:halt, item}
168+
else
169+
{:cont, default}
170+
end
171+
end)
172+
173+
result
174+
end
175+
176+
def member?(enumerable, value) do
177+
{_, result} = Enumerable.reduce(enumerable, {:cont, false}, fn(item, acc) ->
178+
if item == value do
179+
{:halt, true}
180+
else
181+
{:cont, false}
182+
end
183+
end)
184+
185+
result
186+
end
187+
188+
def drop(enumerable, count) do
189+
{_, result} = Enumerable.reduce(enumerable, {:cont, {[], 0}}, fn
190+
(item, {taken, drop_count}) ->
191+
if drop_count < count do
192+
{:cont, {[], drop_count + 1 }}
193+
else
194+
{:cont, taken ++ [item]}
195+
end
196+
end)
197+
198+
result
199+
end
200+
201+
def drop_while(enumerable, fun) do
202+
{_, result} = Enumerable.reduce(enumerable, {:cont, []}, fn
203+
(item, taken) ->
204+
if fun.(item) do
205+
{:cont, {taken}}
206+
else
207+
{:cont, taken ++ [item]}
208+
end
209+
end)
210+
211+
result
212+
end
213+
214+
215+
def take(enumerable, count) do
216+
if Enumerable.count(enumerable) < count do
217+
enumerable
218+
else
219+
{_, result} = Enumerable.reduce(enumerable, {:cont, {[], 0}}, fn
220+
(item, {taken, taken_count}) ->
221+
if taken_count == count do
222+
{:halt, taken}
223+
else
224+
{:cont, {taken ++ [item], taken_count + 1}}
225+
end
226+
end)
227+
228+
result
229+
end
230+
end
231+
232+
def take_every(enumerable, nth) do
233+
{_, {result, _count}} = Enumerable.reduce(enumerable, {:cont, {[], 0}}, fn
234+
(item, {taken, count}) ->
235+
if rem(count, nth) == 0 do
236+
{:cont, {taken ++ [item], count + 1}}
237+
else
238+
{:cont, {taken, count + 1}}
239+
end
240+
end)
241+
242+
result
243+
end
244+
245+
def take_while(enumerable, fun) do
246+
{_, result} = Enumerable.reduce(enumerable, {:cont, []}, fn
247+
(item, taken) ->
248+
if fun.(item) do
249+
{:cont, {taken ++ [item]}}
250+
else
251+
{:halt, taken}
252+
end
253+
end)
254+
255+
result
256+
end
257+
258+
259+
def to_list(enumerable) when is_list(enumerable) do
260+
enumerable
261+
end
262+
263+
def to_list(enumerable) do
264+
map(enumerable, fn x -> x end)
265+
end
266+
267+
def reverse(enumerable) when is_list(enumerable) do
268+
enumerable.concat([]).reverse()
269+
end
270+
271+
def reverse(enumerable) do
272+
reduce(enumerable, [], fn(item, acc) ->
273+
[item] ++ acc
274+
end)
275+
end
276+
277+
def reverse(enumerable, tail) when is_list(enumerable) do
278+
enumerable.concat([]).reverse() ++ tail
279+
end
280+
281+
def reverse(enumerable, tail) do
282+
result = reduce(enumerable, [], fn(item, acc) ->
283+
[item] ++ acc
284+
end)
285+
286+
result ++ tail
287+
end
288+
289+
end
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
defmodule ElixirScript.Enum.OutOfBoundsError do
2+
defexception message: "out of bounds error"
3+
end

priv/std_lib/enumerable.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ end
77

88
defimpl ElixirScript.Enumerable, for: List do
99
def count(list),
10-
do: length(list)
10+
do: {:ok, length(list) }
1111

1212
def member?(list, value),
13-
do: value in list
13+
do: {:ok, value in list }
1414

1515
def reduce(_, {:halt, acc}, _fun), do: {:halted, acc}
1616
def reduce(list, {:suspend, acc}, fun), do: {:suspended, acc, &reduce(list, &1, fun)}

0 commit comments

Comments
 (0)