Skip to content

Commit 26d9dcf

Browse files
committed
Add module to handle JS function calls
1 parent 1189826 commit 26d9dcf

File tree

15 files changed

+315
-127
lines changed

15 files changed

+315
-127
lines changed

GettingStarted.md

Lines changed: 7 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,16 @@
11
# Getting Started with ElixirScript
22

3-
The intent of this guide is to get you started with ElixirScript. It will give you instructions on using ElixirScript. I will go over the two ways you can use Elixirscript:
4-
5-
* As a CLI
6-
* As a mix dependency
7-
8-
### CLI
9-
10-
**macOS**: Elixirscript is available via homebrew `brew install elixirscript`. For everyone else, please read below
11-
12-
Step 1: Get CLI
13-
14-
You can download the elixirscript CLI from the [releases page on github](https://github.com/bryanjos/elixirscript/releases). It is a tar file named elixirscript.tar.gz.
15-
16-
Step 2: Untar
17-
18-
Next, untar elixirscript.tar.gz
19-
20-
tar -xvzf elixirscript.tar.gz
21-
22-
You will want to put the bin folder from the uncompressed folder into your path. This should allow you to use the elixirscript CLI.
23-
24-
Step 3: Use
25-
26-
This is the help output of elixirscript
27-
28-
usage: elixirscript <input> [options]
29-
<input> path to elixir files or
30-
the elixir code string if passed the -e flag
31-
options:
32-
--js-module [<identifer>:<path>] A js module used in your code. ex: React:react
33-
Multiple can be defined
34-
-f --format [format] module format of output. options: es (default), common, umd
35-
-o --output [path] places output at the given path.
36-
Can be a directory or filename.
37-
-e --elixir read input as elixir code string
38-
--full-build informs the compiler to do a full build instead of an incremental one
39-
-v --version the current version number
40-
-h --help this message
41-
42-
the `<input>` is the elixir code string or file path you want to convert from elixir to javascript. Below is an example of using a code string and turning it into JavaScript
43-
44-
$ elixirscript ":atom" -e
45-
46-
elixirscript also takes a path to your `.ex` files as well:
47-
48-
$ elixirscript "src" -o "dist"
49-
50-
If you look in the dist folder you'll see a file called `Elixir.App.js`
51-
52-
To start your application import the bundle according to whichever module format was selected and
53-
then call start giving it the module and the initial args.
54-
55-
Ex. If you have a module like so
56-
```elixir
57-
defmodule Example do
58-
start(type, args) do
59-
:console.log("Hello, world")
60-
end
61-
end
62-
```
63-
64-
You would start it like so
65-
66-
```javascript
67-
//ES module example
68-
import Elixir from './Elixir.App'
69-
Elixir.start(Elixir.Example, [])
70-
```
71-
72-
### Mix dependency
3+
The intent of this guide is to get you started with ElixirScript. It will give you instructions on using ElixirScript.
734

745
Adding Elixirscript to your mix project gives you the ability to add it to your list of mix compilers. This means when you `mix compile`, Elixirscript will compile your code as well.
756

767
Add dependency to your deps in mix.exs:
778

789
``` elixir
79-
{:elixir_script, "~> 0.26"}
10+
{:elixir_script, "~> 0.29"}
8011
```
8112

82-
Elixirscript uses default input, output and module formats if options are not given. If you wish to change any or all options, add an `elixir_script` key to your project configuration.
13+
Elixirscript uses default output and module formats if options are not given. If you wish to change any or all options, add an `elixir_script` key to your project configuration.
8314

8415
``` elixir
8516
def project do
@@ -89,7 +20,7 @@ Elixirscript uses default input, output and module formats if options are not gi
8920
elixir: "~> 1.0",
9021
deps: deps,
9122
elixir_script: [
92-
input: "lib/elixirscript",
23+
input: MyEntryModule,
9324
output: "priv/elixirscript/Elixir.App.js",
9425
format: :es,
9526
js_modules: [
@@ -98,14 +29,14 @@ Elixirscript uses default input, output and module formats if options are not gi
9829
{Phoenix, "phoenix", default: false}
9930
]
10031
],
101-
compilers: [:elixir_script] ++ Mix.compilers
32+
compilers: Mix.compilers ++ [:elixir_script]
10233
]
10334
end
10435
```
10536

10637
Available options are:
10738

108-
* `input`: The folder to look for Elixirscript files in. (defaults to `lib/elixirscript`)
39+
* `input`: The entry module(s) for your application or library
10940

11041
* `output`: The path of the generated JavaScript file. (defaults to `priv/elixirscript`)
11142

@@ -126,20 +57,8 @@ Available options are:
12657

12758
### Macros
12859

129-
Elixirscript supports public macros. Private macros are currently unsupported.
60+
Elixirscript supports all macros
13061

13162
### JavaScript Interop
13263

13364
Check out the [JavaScript Interoperability](JavaScriptInterop.html) documentation
134-
135-
#### Frontend Project Boilerplate
136-
137-
There is an [elixirscript frontend boilerplate project](https://github.com/elixirscript/elixirscript-project-boilerplate). This setup uses gulp and webpack to build and bundle assets.
138-
139-
#### elixirscript-brunch
140-
141-
There is an Brunch plugin, [elixirscript-brunch](https://www.npmjs.com/package/elixirscript-brunch).
142-
143-
#### elixirscript-loader
144-
145-
There is also a webpack loader, [elixirscript-loader](https://www.npmjs.com/package/elixirscript-loader).

JavascriptInterop.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,6 @@ If using ElixirScript in a mix project, you can do so inside of the ElixirScript
5858
end
5959
```
6060

61-
Or if using the CLI, you can do so by passing each module via the `js-module` flag
62-
63-
```
64-
elixirscript "app/elixirscript" -o dist --js-module React:react --js-module ReactDOM:react-dom
65-
```
66-
6761
Interacting with these modules works the same as interacting with an ElixirScript module
6862

6963
```elixir

lib/elixir_script/next/passes/output.ex

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,13 @@ defmodule ElixirScript.Output do
2323
end
2424

2525
defp bundle(modules, opts) do
26-
ElixirScript.Passes.CreateJSModules.compile(modules, opts)
27-
28-
js_code = modules
29-
|> ElixirScript.Passes.CreateJSModules.compile(opts)
26+
modules
27+
|> ElixirScript.Output.JSModule.compile(opts)
3028
|> List.wrap
3129
|> Builder.program
3230
|> prepare_js_ast
3331
|> Generator.generate
34-
35-
concat(js_code)
32+
|> concat
3633
end
3734

3835
defp concat(code) do
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
defmodule ElixirScript.Output.JSModule do
2+
@moduledoc false
3+
4+
alias ESTree.Tools.Builder, as: J
5+
6+
def compile(body, opts) do
7+
declarator = J.variable_declarator(
8+
J.identifier("Elixir"),
9+
J.object_expression([])
10+
)
11+
12+
elixir = J.variable_declaration([declarator], :const)
13+
14+
table_additions = Enum.map(opts.js_modules, fn
15+
{module, path} -> add_import_to_table(module)
16+
{module, path, _} -> add_import_to_table(module)
17+
end)
18+
19+
ast = opts.module_formatter.build(
20+
[],
21+
opts.js_modules,
22+
[elixir, create_atom_table(), start, load] ++ table_additions ++ body,
23+
J.identifier("Elixir")
24+
)
25+
26+
ast
27+
end
28+
29+
def start do
30+
J.assignment_expression(
31+
:=,
32+
J.member_expression(
33+
J.identifier("Elixir"),
34+
J.identifier("start")
35+
),
36+
J.function_expression(
37+
[J.identifier(:app), J.identifier(:args)],
38+
[],
39+
J.block_statement([
40+
J.call_expression(
41+
J.member_expression(
42+
J.call_expression(
43+
J.member_expression(
44+
J.identifier(:app),
45+
J.identifier("__load")
46+
),
47+
[J.identifier("Elixir")]
48+
),
49+
J.identifier("start")
50+
),
51+
[ElixirScript.Translator.Primitive.make_atom(:normal), J.identifier(:args)]
52+
)
53+
])
54+
)
55+
)
56+
end
57+
58+
def load do
59+
J.assignment_expression(
60+
:=,
61+
J.member_expression(
62+
J.identifier("Elixir"),
63+
J.identifier("load")
64+
),
65+
J.function_expression(
66+
[J.identifier(:module)],
67+
[],
68+
J.block_statement([
69+
J.return_statement(
70+
J.call_expression(
71+
J.member_expression(
72+
J.identifier(:module),
73+
J.identifier("__load")
74+
),
75+
[J.identifier("Elixir")]
76+
)
77+
)
78+
])
79+
)
80+
)
81+
end
82+
83+
defp create_atom_table() do
84+
J.assignment_expression(
85+
:=,
86+
J.member_expression(
87+
J.identifier("Elixir"),
88+
J.identifier("__table__")
89+
),
90+
J.object_expression([])
91+
)
92+
end
93+
94+
defp add_import_to_table(module_name) do
95+
ref = ElixirScript.Translate.Identifier.make_namespace_members(module_name)
96+
J.assignment_expression(
97+
:=,
98+
J.member_expression(
99+
J.member_expression(
100+
J.identifier("Elixir"),
101+
J.identifier("__table__")
102+
),
103+
J.call_expression(
104+
J.member_expression(
105+
J.identifier("Symbol"),
106+
J.identifier("for")
107+
),
108+
[J.literal(ref.name)]
109+
),
110+
true
111+
),
112+
ref
113+
)
114+
end
115+
116+
end

lib/elixir_script/next/passes/translate/form.ex

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule ElixirScript.Translate.Form do
22
alias ESTree.Tools.Builder, as: J
33
alias ElixirScript.Translate.Forms.{Bitstring, Match, Try, For, Receive, Remote, Pattern}
44
alias ElixirScript.Translate.Functions.{Erlang, Lists, Maps}
5-
alias ElixirScript.Translator.Identifier
5+
alias ElixirScript.Translate.Identifier
66
alias ElixirScript.Translate.Clause
77
require Logger
88

@@ -185,6 +185,10 @@ defmodule ElixirScript.Translate.Form do
185185
{ast, state}
186186
end
187187

188+
def compile({{:., _, [JS, _]}, _, _} = ast, state) do
189+
ElixirScript.Translate.Forms.JS.compile(ast, state)
190+
end
191+
188192
def compile({:., _, call} = ast, state) when is_list(call) do
189193
Remote.compile(ast, state)
190194
end
@@ -193,7 +197,7 @@ defmodule ElixirScript.Translate.Form do
193197
{function_name, _} = Map.get(state, :function)
194198

195199
ast = J.call_expression(
196-
ElixirScript.Translator.Identifier.make_function_name(function_name),
200+
ElixirScript.Translate.Identifier.make_function_name(function_name),
197201
Enum.map(params, &compile!(&1, state)) |> List.flatten
198202
)
199203

@@ -202,7 +206,7 @@ defmodule ElixirScript.Translate.Form do
202206

203207
def compile({var, _, params}, state) when is_list(params) and is_atom(var) do
204208
ast = J.call_expression(
205-
ElixirScript.Translator.Identifier.make_function_name(var),
209+
ElixirScript.Translate.Identifier.make_function_name(var),
206210
Enum.map(params, &compile!(&1, state)) |> List.flatten
207211
)
208212

@@ -220,7 +224,7 @@ defmodule ElixirScript.Translate.Form do
220224

221225
def compile({var, _, _}, state) do
222226
var = Pattern.get_variable_name(to_string(var), state)
223-
{ ElixirScript.Translator.Identifier.make_identifier(var), state }
227+
{ ElixirScript.Translate.Identifier.make_identifier(var), state }
224228
end
225229

226230
end

0 commit comments

Comments
 (0)