{"id":13683342,"url":"https://github.com/soegaard/urlang","last_synced_at":"2025-05-16T12:12:19.850Z","repository":{"id":36100920,"uuid":"40402158","full_name":"soegaard/urlang","owner":"soegaard","description":"Urlang is JavaScript with a sane syntax","archived":false,"fork":false,"pushed_at":"2025-01-11T14:12:21.000Z","size":810,"stargazers_count":302,"open_issues_count":7,"forks_count":16,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-04-09T10:04:09.306Z","etag":null,"topics":["compiler","javascript","nanopass","racket"],"latest_commit_sha":null,"homepage":null,"language":"Racket","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/soegaard.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-08-08T12:27:06.000Z","updated_at":"2025-03-14T13:01:28.000Z","dependencies_parsed_at":"2024-06-18T10:59:39.206Z","dependency_job_id":"72948803-7402-4666-bb3b-9d7b78a32d15","html_url":"https://github.com/soegaard/urlang","commit_stats":{"total_commits":287,"total_committers":8,"mean_commits":35.875,"dds":0.08710801393728218,"last_synced_commit":"e9f83509d6f1a7cdc91ba1ad5a0ecaa76e573996"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soegaard%2Furlang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soegaard%2Furlang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soegaard%2Furlang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soegaard%2Furlang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/soegaard","download_url":"https://codeload.github.com/soegaard/urlang/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254527099,"owners_count":22085919,"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":["compiler","javascript","nanopass","racket"],"created_at":"2024-08-02T13:02:08.008Z","updated_at":"2025-05-16T12:12:19.821Z","avatar_url":"https://github.com/soegaard.png","language":"Racket","funding_links":[],"categories":["Racket","Compilers"],"sub_categories":[],"readme":"# URLANG\n\n\u003e Urlang is JavaScript with a sane syntax\n\nUrlang is a language designed to allow straightforward translation to JavaScript.\nThink of Urlang as JavaScript with sane syntax and JavaScript semantics.\nJavaScript in this context is short for ECMAScript 5 in strict mode.\n\nAlthough the constructs of Urlang and JavaScript map almost one-to-one,\na little sugar was added:\n  * function definitions allow default arguments\n  * let expressions\n\nEven though the syntax of Urlang is Racket-like, remember that the\nsemantics is standard JavaScript. This means in particular that tail calls\nbuild context.\n\n\n## Examples\n\nThe following examples are compiled using the `urlang` form.\n\n    (urlang \u003cmodule\u003e ...)\n\nThe urlang form compiles the modules. The result of compiling\na module is saved a file whose path is the module-name with `.js`\nadded.\n\nThe `urlang` form is controlled by the following parameters:\n\n    (current-urlang-run?                           #t)  ; compile and run (using node)\n    (current-urlang-echo?                          #t)  ; print JavaScript to screen\n    (current-urlang-console.log-module-level-expr? #t)  ; use conole.log to print module-level exprs\n\n\n### Example (factorial)\n\n     \u003e (urlang\n         (urmodule fact                                           ; module name\n           (export fact)                                          ; fact is exported\n           (import + - * = displayln ref console)\n           (define (fact n) (if (= n 0) 1 (* n (fact (- n 1)))))\n           (fact 5)))\n\nThe generated JavaScript:\n\n     \"use strict\";\n     function fact(n){return (((n===0)===false)?(n*(fact((n-1)))):1);};\n     console.log((fact(5)));\n     exports.fact=fact;\n\nThe output from Node:\n\n     \"120\\n\"\n\n\n### Example (`cond`-macro and `array`)\n\nUrlang macro transformers receive and produce standard Racket syntax objects.\nThis implies that standard tools such as syntax-parse are available.\n\nConsider an Urlang version of `cond`:\n\n    SYNTAX (cond [e0 e1 e2 ...] ... [else en]), \n       like Racket cond except there is no new scope \n\n The urlang macro transformer is an standard (phase 0) Racket function.\n\n      (define-urlang-macro cond\n        (λ (stx)   \n          (syntax-parse stx\n            [(_cond [else e0:Expr e:Expr ...])\n             #'(begin e0 e ...)]\n            [(_cond [e0 e1 e2 ...] clause ...)\n             (syntax/loc stx\n               (if e0 (begin e1 e2 ...) (cond clause ...)))]\n            [(_cond)\n             (raise-syntax-error 'cond \"expected an else clause\" stx)])))\n             \n The macro can now we be used:\n             \n    \u003e (urlang\n        (urmodule sum-example\n          (define (even? x) (=== (% x 2) 0))\n          (var (sum 0) x (a (array 1 2 3 4 5)) (i 0) (n a.length))\n          (while (\u003c i n)\n            (:= x (ref a i))\n            (cond\n              [(even? x)  (+= sum (ref a i))]\n              [else       \"skip\"])\n            (+= i 1))\n          sum))\n\nThe generated JavaScript:\n\n    \"use strict\";\n    function even_p(x){return ((x%2)===0);};\n    var sum=0,x,a=[1,2,3,4,5],i=0,n=a.length;\n    while((i\u003cn)){(x=a[i]);(((even_p(x))===false)?\"skip\":(sum+=a[i]));(i+=1);};\n    console.log(sum);\n\nThe output from Node:\n\n    \"6\\n\"\n\n# Overview\n\nThe heart of the system is a compiler written using the Nanopass\ncompiler Framework. The compiler is exported as a function\n\n    compile : urlang-module -\u003e JavaScript\n\nthat compiles an urlang module and produces JavaScript,\nthat can be evaluated by the Node.js platform (or be embedded in a web page).\n\nThe Urlang module to be compiled can be represented \n\n   1. as a syntax object\n   2. as a Nanopass structure (representing an Lurlang program)\n\nUse 1) to program in Urlang directly.\n\nUse 2) if you intend to use Urlang as a compiler backend.\n\n[Note: Nanopass is a framework for implementing compilers.]\n\nThe intended use of Urlang is to use 1) to write (generate) a Racket runtime in JavaScript.\nThe middle-end of the Racket-to-JavaScript compiler will produce output as Nanopass\nstructures, so 2) will be used as the backend for the Racket-to-JavaScript compiler.\n\nInternally the function expand\n\n    expand : syntax -\u003e LUrlang\n\nwill parse and expand its input and produce an LUrlang representation.\n\nNote that `expand` allows the user to extend the input language\nusing define-urlang-macro. An Urlang macro is a syntax to syntax\ntransformation implemented as a normal Racket function.\nThis allow you to use all of the standard Racket macro machinery.\n\nMain functions:\n\n    expand : syntax -\u003e Lurlang\n        expand the input and produce a fully expanded Urlang program\n        represented as a Lurlang structure\n        \n    compile : syntax -\u003e\n        Expand and compile. The output is written to standard out.\n        \n    eval : syntax -\u003e value\n        expand, compile and run the input (an Urlang module represented as a syntax object)\n        Running means that `node` is used to run the generated JavaScript.\n\nHaving Urlang as a `#lang` language allows\n\n * macros (using full Racket at compile time)\n * export of defined names\n * easier testing\n\nIn the grammar below:\n\n  - `x` stands for a non-keyword identifier\n  - `f` stands for an identifier defined as a function\n\n````\n \u003cmodule\u003e            ::= (urmodule \u003cmodule-name\u003e \u003cmodule-path\u003e \u003cmodule-level-form\u003e ...)\n\n \u003cmodule-level-form\u003e ::= \u003cexport\u003e | \u003cimport\u003e | \u003cdefinition\u003e | \u003cstatement\u003e \n \u003cexport\u003e            ::= (export x ...)\n \u003cimport\u003e            ::= (import x ...)\n \u003cdefinition\u003e        ::= (define (f \u003cformal\u003e ...) \u003cbody\u003e)\n                      |  (define x \u003cexpr\u003e)\n \u003cformal\u003e           ::= x | [x \u003cexpr\u003e]\n\n \u003cstatement\u003e         ::= \u003cvar-decl\u003e | \u003cblock\u003e | \u003cwhile\u003e | \u003cdo-while\u003e | \u003cif\u003e | \u003cbreak\u003e | \u003cexpr\u003e \n \u003cvar-decl\u003e          ::= (var \u003cvar-binding\u003e ...)\n \u003cblock\u003e             ::= (block \u003cstatement\u003e ...)\n \u003cvar-binding\u003e       ::= x | (x e)\n \u003cwhile\u003e             ::= (while \u003cexpr\u003e \u003cstatement\u003e ...)\n \u003cdo-while\u003e          ::= (do-while \u003cexpr\u003e \u003cstatement\u003e ...)\n \u003cif\u003e                ::= (sif \u003cexpr\u003e \u003cstatement\u003e \u003cstatement\u003e)\n \u003cbreak\u003e             ::= (break) | (break label)\n\n \u003cbody\u003e              ::= \u003cstatement\u003e ... \u003cexpr\u003e\n\n \u003cexpr\u003e              ::= \u003cdatum\u003e   | \u003creference\u003e | \u003capplication\u003e | \u003csequence\u003e\n                      |  \u003cternary\u003e | \u003cassignment\u003e | \u003clet\u003e | \u003clambda\u003e | \u003cdot\u003e\n \u003cternary\u003e           ::= (if \u003cexpr\u003e \u003cexpr\u003e \u003cexpr\u003e)\n \u003creference\u003e         ::= x\n \u003capplication\u003e       ::= (\u003cexpr\u003e \u003cexpr\u003e ...)\n \u003csequence\u003e          ::= (begin \u003cexpr\u003e ...)\n \u003cassignment\u003e        ::= (:= x \u003cexpr\u003e)\n \u003clet\u003e               ::= (let ((x \u003cexpr\u003e) ...) \u003cstatement\u003e ... \u003cexpr\u003e)\n \u003clambda\u003e            ::= (lambda (\u003cformal\u003e ...) \u003cbody\u003e)\n\n \u003ckeyword\u003e           ::= define | begin | urmodule | if | := | ...se code...\n\n \u003cdatum\u003e             ::= \u003cfixnum\u003e | \u003cstring\u003e | #t | #f\n\n \u003cidentifier\u003e     an identifier that is not a keyword\n \u003cfixnum\u003e         an integer between -2^53 and 2^53\n \u003cmodule-name\u003e    a symbol or string\n````\n\n# NOTES\n\nSome application are special cases:\n\n    (ref e0 e1)     becomes  e0[e1]\n    (ref e0 \"str\")  becomes  e0.str    \n    (array e ...)   becomes  [e,...]\n\nProperty access with dot notation is rewritten to use bracket syntax in the parser.\n\nExample:  `object.property` becomes `object[\"property\"]`\n\n\n# SEMANTICS\n\n### `(if e0 e1 e2)`\nIf `e0` evaluates to value strictly equal to false, then `e2` otherwise `e1`.\nNote: The JavaScript becomes  `((e0===false) ? e2 : e1)`\n\n### `(var x (y 3))`\nBinds `x` to undefined and `y` to `3`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoegaard%2Furlang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoegaard%2Furlang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoegaard%2Furlang/lists"}