Published for review but still needs some doc and examples. Works with most small examples but not yet with the naive_interpreter (but it's not clear why).
Usage:
apt-get emscripten
nitg -m emscripten examples/hello_world.nit
nodejs hello_wold.js
Pull-Request: #506
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
--- /dev/null
+# Hello world
+
+Minimal example using the standard Nit hello world program. The Nit code will be evaluated and executed once as soon as it is loaded. Standard output is redirected to the `console` element.
+
+# Fibonacci
+
+The Nit program is executed only when an input is supplied. The input is passed as the main arguments.
+
+This is not ideal, the whole Nit program is executed at each call.
--- /dev/null
+emscripten:
+ ../../../bin/nitg -o www/fibonacci.js ../../fibonacci.nit -m emscripten
--- /dev/null
+<!DOCTYPE html>
+<!-- This file is part of NIT ( http://www.nitlanguage.org )
+
+ Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html>
+<head>
+ <title>Fibonacci</title>
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
+ <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
+ <script>
+ // Redirect print to HTML
+ var Module = {
+ 'print': function(text) {
+ $("#console").append(text + "<br>");
+ },
+ 'noInitialRun': true,
+ };
+
+ $(document).ready(function() {
+ // Report full loading
+ $("#loading").text( "Loaded." );
+
+ // Callback
+ $("#in").keyup(function(){
+ if(event.keyCode == 13){
+ fib();
+ }
+ });
+ });
+
+ function fib() {
+ var input = $("#in").val();
+
+ // Invoke the full Nit program
+ ret = Module['callMain']([input]);
+ }
+ </script>
+</head>
+<body>
+
+<div class="container">
+ <h1>Fibonacci calculator</h1>
+ <a href="https://github.com/privat/nit/blob/master/examples/fibonacci.nit">Nit source</a><br>
+ <a href="https://github.com/privat/nit/blob/master/examples/emscripten/fibonacci/www/index.html">HTML source</a>
+
+ <h2>Status</h2>
+ <p id="loading">Loading...</p>
+
+ <h2>Program Input</h2>
+ <input id="in" type="text" placeholder="12 (or any integer)"/><input type="button" value="Execute" onclick="fib();"/>
+
+ <h2>Program Output</h2>
+ <samp id="console"></samp>
+
+ <script src="fibonacci.js"></script>
+</div>
+
+</body>
+</html>
--- /dev/null
+emscripten:
+ ../../../bin/nitg -o www/hello_world.js ../../hello_world.nit -m emscripten
--- /dev/null
+<!DOCTYPE html>
+<!-- This file is part of NIT ( http://www.nitlanguage.org )
+
+ Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html>
+<head>
+ <title></title>
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
+ <script>
+ // Redirect print to HTML
+ var Module = {
+ 'print': function(text) {
+ $("#console").append(text + "\n");
+ $(document).title = text;
+ }
+ };
+
+ // Report full loading
+ $(document).ready(function() {
+ $("#loading").text( "Loaded and executed." );
+ });
+ </script>
+</head>
+<body>
+
+ <h1>Status</h1>
+ <p id="loading">Loading...</p>
+
+ <h1>Program output</h1>
+ <samp id="console"></samp>
+
+ <script src="hello_world.js"></script>
+
+</body>
+</html>
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module emscripten is platform
+
+`{
+ #include <emscripten.h>
+`}
+
+redef class String
+ fun run_js do run_js_native(self.escape_to_js.to_cstring)
+ private fun run_js_native(script: NativeString) `{ emscripten_run_script(script); `}
+
+ fun escape_to_js: String do return self.replace('\n', "\\n")
+
+ fun alert do "alert('{self.escape_to_js}')".run_js
+end
#include <poll.h>
#include <errno.h>
#include <string.h>
+ #include <signal.h>
`}
# Abstract stream class
do
if self.toolcontext.opt_stacktrace.value == "nitstack" then compiler.build_c_to_nit_bindings
+ var platform = compiler.mainmodule.target_platform
+ var cc_opt_with_libgc = "-DWITH_LIBGC"
+ if platform != null and not platform.supports_libgc then cc_opt_with_libgc = ""
+
# Add gc_choser.h to aditionnal bodies
- var gc_chooser = new ExternCFile("gc_chooser.c", "-DWITH_LIBGC")
+ var gc_chooser = new ExternCFile("gc_chooser.c", cc_opt_with_libgc)
compiler.extern_bodies.add(gc_chooser)
compiler.files_to_copy.add "{cc_paths.first}/gc_chooser.c"
compiler.files_to_copy.add "{cc_paths.first}/gc_chooser.h"
self.toolcontext.info("Total C source files to compile: {cfiles.length}", 2)
end
+ fun makefile_name(mainmodule: MModule): String do return "{mainmodule.name}.mk"
+
+ fun default_outname(mainmodule: MModule): String do return mainmodule.name
+
fun write_makefile(compiler: AbstractCompiler, compile_dir: String, cfiles: Array[String])
do
var mainmodule = compiler.mainmodule
- var outname = self.toolcontext.opt_output.value
- if outname == null then
- outname = "{mainmodule.name}"
- end
+ var outname = self.toolcontext.opt_output.value or else default_outname(mainmodule)
var orig_dir=".." # FIXME only works if `compile_dir` is a subdirectory of cwd
var outpath = orig_dir.join_path(outname).simplify_path
- var makename = "{mainmodule.name}.mk"
+ var makename = makefile_name(mainmodule)
var makepath = "{compile_dir}/{makename}"
var makefile = new OFStream.open(makepath)
fun compile_c_code(compiler: AbstractCompiler, compile_dir: String)
do
- var makename = "{compiler.mainmodule.name}.mk" # FIXME duplicated from write_makefile
+ var makename = makefile_name(compiler.mainmodule)
var makeflags = self.toolcontext.opt_make_flags.value
if makeflags == null then makeflags = ""
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org )
+#
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Compile to JavaScript using the Emscripten SDK
+module emscripten_platform
+
+import platform
+import abstract_compiler
+
+redef class ToolContext
+ redef fun platform_from_name(name)
+ do
+ if name == "emscripten" then return new EmscriptenPlatform
+ return super
+ end
+end
+
+class EmscriptenPlatform
+ super Platform
+
+ redef fun supports_libunwind do return false
+ redef fun supports_libgc do return false
+ redef fun toolchain(toolcontext) do return new EnscriptenToolchain(toolcontext)
+end
+
+class EnscriptenToolchain
+ super MakefileToolchain
+
+ redef fun makefile_name(mainmodule) do return "{mainmodule.name}.js.mk"
+
+ redef fun default_outname(mainmodule) do return "{super}.js"
+
+ redef fun write_makefile(compiler, compile_dir, cfiles)
+ do
+ super
+
+ var emcc_make_flags = "CC=emcc CFLAGS='-g -Wno-unused-value -Wno-switch -Qunused-arguments'"
+
+ var make_flags = self.toolcontext.opt_make_flags.value or else ""
+ make_flags += emcc_make_flags
+ self.toolcontext.opt_make_flags.value = make_flags
+ end
+end
import android_platform
import compiler_ffi
import pnacl_platform
+import emscripten_platform
redef class ToolContext
redef fun process_options(args)
abstract class Platform
fun supports_libunwind: Bool do return true
+ fun supports_libgc: Bool do return true
+
# Does this platform declare its own main function? If so, we won't generate one in Nit.
fun no_main: Bool do return false
end
android
nitcc_parser_gen
mnit
+emscripten
--- /dev/null
+Not executable (platform?)