{"id":18448806,"url":"https://github.com/synrc/shen","last_synced_at":"2025-08-20T02:32:12.559Z","repository":{"id":9614538,"uuid":"11539925","full_name":"synrc/shen","owner":"synrc","description":"🐉 SHEN: Erlang JavaScript Compiler","archived":false,"fork":false,"pushed_at":"2021-02-04T16:20:54.000Z","size":75,"stargazers_count":234,"open_issues_count":2,"forks_count":29,"subscribers_count":28,"default_branch":"master","last_synced_at":"2024-04-14T04:22:45.213Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/synrc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-07-20T00:48:24.000Z","updated_at":"2024-04-03T10:41:41.000Z","dependencies_parsed_at":"2022-09-22T17:41:30.738Z","dependency_job_id":null,"html_url":"https://github.com/synrc/shen","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synrc%2Fshen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synrc%2Fshen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synrc%2Fshen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synrc%2Fshen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/synrc","download_url":"https://codeload.github.com/synrc/shen/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230039467,"owners_count":18163414,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T07:17:17.835Z","updated_at":"2025-08-20T02:32:12.540Z","avatar_url":"https://github.com/synrc.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"SHEN: Erlang JavaScript Compiler\n================================\n\nSimple\n\nLibraries\n---------\n\nWe support following stack by Erlang JavaScript compiler:\n\n* matches.js -- Erlang-like matching syntax\n* tailrec.js -- optimize tail calls\n* beacon.js -- FRP event streaming\n\nThe only real practical fast solution is to translate Erlang AST into JavaScript\nusing JavaScript helpers like matches.js and tailrec.js.\n\nUsage\n-----\n\n* Compilation to JavaScript, node.js, Browser, Client-Side FRP\n* Macros, String Templates, Embedding Mode, Server-Side, N2O\n\nCompilation to Pure JavaScript\n------------------------------\n\nIn case of Client-Logic, Off-line clients, Client-side FRP Event System\nuse can export you functions in module with -js attribute.\nAll function will be stored to the same filename with js extension.\n\nfac.erl:\n\n```erlang\n    -module(fac).\n    -compile({parse_transform, shen}).\n    -compile(export_all).\n\n    -js([start/0,fac/1]).\n\n    start() -\u003e\n        N = fac(5),\n        console:log(\"factorial ~p\", [J, N]).\n\n    fac(0) -\u003e 1;\n    fac(N) -\u003e N * fac(N-1).\n```\n\nCompile with Erlang:\n\n    $ erlc shen.erl\n    $ erlc -pa . fac.erl\n\nAnd you will get fac.js:\n\n```javascript\n    var pattern = require(\"matches\").pattern;\n    var start = pattern({\n        '': function() {\n            j = 5;\n            n = fac(j);\n            return console.log('factorial ~p',[j,[n,[]]]);\n    }});\n    var fac = pattern({\n        '0': function(x1) {\n            return 1;\n        },\n        'n': function(n) {\n            return n * fac(n - 1);\n    }});\n    start();\n```\n\nNow you can check:\n\n    $ node fac.js\n    factorial ~p [ 5, [ 120, [] ] ]\n\nJavaScript Macros\n-----------------\n\nLet say we want to generate JavaScript in our Erlang code which is very useful\nfor Server-Logic Event System, so you can write programs in Erlang and expand\nthem into JavaScript using -jsmacro attribute. Specified functions will be\nexpanded to JavaScript during compilation.\n\n```erlang\n    -module(fac).\n    -compile({parse_transform, shen}).\n    -compile(export_all).\n\n    -jsmacro([macro/3]).\n\n    macro(A,B,C) -\u003e\n        ws:send('Bert':encodebuf(\n            [{source,'Bert':binary(A)},\n             {x,C},\n             {pickle,'Bert':binary(B)},\n             {linked,C}])).\n\n    main() -\u003e\n        A = \"1\",\n        B = \"2\",\n        Script = macro(A,B,\"3\"),\n        io:format(\"JS Macro: ~s\",[Script]).\n```\n\nLets try it:\n\n    7\u003e fac:main().\n    JS Macro: ws.send(Bert.encodebuf({source:Bert.binary(1),x:3,pickle:Bert.binary(2),linked:3}));\n    ok\n\nRoadmap\n-------\n\n1. multiple clauses for lambdas\n2. list comprehensions\n3. more JavaScript/OTP mappings\n4. if statement :-)\n\nCredits\n-------\n\n    * Maxim Sokhatsky\n    * Andrew Zadorozhny\n\nOM A HUM\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsynrc%2Fshen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsynrc%2Fshen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsynrc%2Fshen/lists"}