Skip to content

Commit 4385a59

Browse files
committed
Implement stub of receive functionality
1 parent 1c64205 commit 4385a59

3 files changed

Lines changed: 67 additions & 17 deletions

File tree

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,48 @@
11
defmodule ElixirScript.Translate.Forms.Receive do
22
@moduledoc false
33
alias ESTree.Tools.Builder, as: J
4-
alias ElixirScript.Translate.Helpers
4+
alias ElixirScript.Translate.{Helpers, Form, Function, Clause}
55

66
@doc """
77
receive is not supported just yet, but we compile it
88
to a stub function for now
99
"""
1010
def compile(blocks, state) do
11-
_receive_block = Keyword.get(blocks, :do)
12-
_after_block = Keyword.get(blocks, :after, nil)
11+
receive_block = Keyword.get(blocks, :do)
12+
after_block = Keyword.get(blocks, :after, nil)
13+
14+
receive_block = Enum.map(receive_block, fn x -> Clause.compile(x, state) |> elem(0) end)
15+
|> List.flatten
16+
|> J.array_expression()
1317

1418
receive_function = J.member_expression(
1519
Helpers.special_forms(),
1620
J.identifier("receive")
1721
)
1822

23+
args = [receive_block] ++ process_after(after_block, state)
24+
1925
ast = Helpers.call(
2026
receive_function,
21-
[]
27+
args
2228
)
2329

2430
{ ast, state }
2531
end
32+
33+
defp process_after(nil, _) do
34+
[]
35+
end
36+
37+
defp process_after([{:->, _, [[timeout], body]}], state) do
38+
timeout = Form.compile!(timeout, state)
39+
{body, _state} = Function.compile_block(body, state)
40+
41+
function = Helpers.arrow_function(
42+
[],
43+
J.block_statement(List.wrap(body))
44+
)
45+
46+
[timeout, function]
47+
end
2648
end

src/javascript/lib/core/special_forms.js

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function cond(...clauses) {
1616

1717
function run_list_generators(generator, generators) {
1818
if (generators.length === 0) {
19-
return generator.map((x) => {
19+
return generator.map(x => {
2020
if (Array.isArray(x)) {
2121
return x;
2222
}
@@ -42,14 +42,23 @@ function _for(expression, generators, collectable_protocol, into = []) {
4242

4343
for (const value of generatedValues) {
4444
if (expression.guard.apply(this, value)) {
45-
result = fun(result, new Core.Tuple(Symbol.for('cont'), expression.fn.apply(this, value)));
45+
result = fun(
46+
result,
47+
new Core.Tuple(Symbol.for('cont'), expression.fn.apply(this, value))
48+
);
4649
}
4750
}
4851

4952
return fun(result, Symbol.for('done'));
5053
}
5154

52-
function _try(do_fun, rescue_function, catch_fun, else_function, after_function) {
55+
function _try(
56+
do_fun,
57+
rescue_function,
58+
catch_fun,
59+
else_function,
60+
after_function
61+
) {
5362
let result = null;
5463

5564
try {
@@ -132,8 +141,29 @@ function _with(...args) {
132141
return successFunction(...argsToPass);
133142
}
134143

135-
function receive() {
144+
function receive(clauses, timeout = 0, timeoutFn = () => true) {
136145
console.warn('Receive not supported');
146+
147+
const messages = []; //this.mailbox.get();
148+
const NOMATCH = Symbol();
149+
150+
for (let i = 0; i < messages.length; i++) {
151+
for (const clause of clauses) {
152+
const value = Patterns.match_or_default(
153+
clause.pattern,
154+
messages[i],
155+
clause.guard,
156+
NOMATCH
157+
);
158+
159+
if (value !== NOMATCH) {
160+
this.mailbox.removeAt(i);
161+
return clause.fn.apply(null, value);
162+
}
163+
}
164+
}
165+
166+
return null;
137167
}
138168

139169
export default {
@@ -142,5 +172,5 @@ export default {
142172
_for,
143173
_try,
144174
_with,
145-
receive,
175+
receive
146176
};

test/passes/translate/forms/receive_test.exs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@ defmodule ElixirScript.Translate.Forms.Receive.Test do
44
alias ESTree.Tools.Builder, as: J
55

66
test "receive translation" do
7-
ast = {:receive, [line: 644], [[do: 1, after: 2]]}
8-
state = %{function: {:each, nil}, module: __MODULE__}
7+
clause = {:->, [line: 644], [[], [{:__block__, [], [1]}]]}
8+
ast = {:receive, [line: 644], [[do: [clause], after: nil]]}
9+
state = %{function: {:each, nil}, module: __MODULE__, anonymous_fn: false}
910

1011
{js_ast, _} = Form.compile(ast, state)
11-
assert js_ast == J.call_expression(
12-
J.member_expression(
13-
Helpers.special_forms(),
14-
J.identifier("receive")
15-
),
16-
[]
12+
assert js_ast.callee == J.member_expression(
13+
Helpers.special_forms(),
14+
J.identifier("receive")
1715
)
1816
end
1917

0 commit comments

Comments
 (0)