Skip to content

Commit b8f2478

Browse files
authored
Merge pull request elixirscript#399 from elixirscript/implement_receive_stub
Implement stub of receive functionality
2 parents 8018ebe + 448e9c4 commit b8f2478

5 files changed

Lines changed: 73 additions & 22 deletions

File tree

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,51 @@
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 = blocks
12+
|> Keyword.get(:do)
13+
|> Enum.map(fn x ->
14+
Clause.compile(x, state)
15+
|> elem(0)
16+
end)
17+
|> List.flatten
18+
|> J.array_expression()
1319

1420
receive_function = J.member_expression(
1521
Helpers.special_forms(),
1622
J.identifier("receive")
1723
)
1824

25+
after_block = Keyword.get(blocks, :after, nil)
26+
args = [receive_block] ++ process_after(after_block, state)
27+
1928
ast = Helpers.call(
2029
receive_function,
21-
[]
30+
args
2231
)
2332

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

rollup.config.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ export default {
99
plugins: [
1010
nodeResolve({
1111
jsnext: true,
12-
main: true
12+
main: true,
1313
}),
1414
commonjs(),
1515
babel({
16-
babelrc: false
16+
babelrc: false,
1717
}),
1818
minify({
1919
keepFnName: true,
20-
keepClassName: true
21-
})
20+
keepClassName: true,
21+
}),
2222
],
23-
output: [{ file: 'priv/build/iife/ElixirScript.Core.js', format: 'iife' }]
23+
output: [{ file: 'priv/build/iife/ElixirScript.Core.js', format: 'iife' }],
2424
};

src/javascript/lib/core/functions.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,10 @@ function map_to_object(map, options = []) {
9595

9696
const object = {};
9797

98-
for (let [key, value] of map.entries()) {
98+
for (const entry of map.entries()) {
99+
let key = entry[0];
100+
const value = entry[1];
101+
99102
if (opt_keys === Symbol.for('string') && typeof key === 'number') {
100103
key = key.toString();
101104
} else if (

src/javascript/lib/core/special_forms.js

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,21 @@ function run_list_generators(generator, generators) {
3636
}
3737

3838
function _for(expression, generators, collectable_protocol, into = []) {
39-
let [result, fun] = collectable_protocol.into(into);
39+
const [result, fun] = collectable_protocol.into(into);
40+
let accumulatingResult = result;
4041

4142
const generatedValues = run_list_generators(generators.pop()(), generators);
4243

4344
for (const value of generatedValues) {
4445
if (expression.guard.apply(this, value)) {
45-
result = fun(result, new Core.Tuple(Symbol.for('cont'), expression.fn.apply(this, value)));
46+
accumulatingResult = fun(
47+
accumulatingResult,
48+
new Core.Tuple(Symbol.for('cont'), expression.fn.apply(this, value)),
49+
);
4650
}
4751
}
4852

49-
return fun(result, Symbol.for('done'));
53+
return fun(accumulatingResult, Symbol.for('done'));
5054
}
5155

5256
function _try(do_fun, rescue_function, catch_fun, else_function, after_function) {
@@ -132,8 +136,29 @@ function _with(...args) {
132136
return successFunction(...argsToPass);
133137
}
134138

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

139164
export default {

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)