All Projects → soegaard → Urlang

soegaard / Urlang

Urlang is JavaScript with a sane syntax

Programming Languages

javascript
184084 projects - #8 most used programming language
racket
414 projects

Labels

Projects that are alternatives of or similar to Urlang

Ape
Ape Programming Language
Stars: ✭ 195 (-9.3%)
Mutual labels:  compiler
Binaryen.js
A buildbot for binaryen.js, a port of Binaryen to the Web, with TypeScript support.
Stars: ✭ 201 (-6.51%)
Mutual labels:  compiler
Ichbins
A tiny self-hosting Lisp-to-C compiler
Stars: ✭ 210 (-2.33%)
Mutual labels:  compiler
He Transformer
nGraph-HE: Deep learning with Homomorphic Encryption (HE) through Intel nGraph
Stars: ✭ 195 (-9.3%)
Mutual labels:  compiler
Xdpw
XD Pascal: A small embeddable self-hosting Pascal compiler for Windows. Supports Go-style methods and interfaces
Stars: ✭ 199 (-7.44%)
Mutual labels:  compiler
8cc.vim
C Compiler written in Vim script
Stars: ✭ 205 (-4.65%)
Mutual labels:  compiler
Lhc
The LLVM LHC Haskell Optimization System
Stars: ✭ 188 (-12.56%)
Mutual labels:  compiler
Dmd
dmd D Programming Language compiler
Stars: ✭ 2,498 (+1061.86%)
Mutual labels:  compiler
Nxdk
The cross-platform, open-source SDK to develop for original Xbox: *new* xdk
Stars: ✭ 200 (-6.98%)
Mutual labels:  compiler
Cparser
C99 parser and frontend for libfirm
Stars: ✭ 209 (-2.79%)
Mutual labels:  compiler
Tengo
A fast script language for Go
Stars: ✭ 2,528 (+1075.81%)
Mutual labels:  compiler
Cub
The Cub Programming Language
Stars: ✭ 198 (-7.91%)
Mutual labels:  compiler
Transcrypt
Python 3.7 to JavaScript compiler - Lean, fast, open! -
Stars: ✭ 2,502 (+1063.72%)
Mutual labels:  compiler
Fast
Find in AST - Search and refactor code directly in Abstract Syntax Tree as you do with grep for strings
Stars: ✭ 194 (-9.77%)
Mutual labels:  compiler
Ppci
A compiler for ARM, X86, MSP430, xtensa and more implemented in pure Python
Stars: ✭ 210 (-2.33%)
Mutual labels:  compiler
Splash
Simple Programming LAnguage for SHortcuts
Stars: ✭ 192 (-10.7%)
Mutual labels:  compiler
Interim
Low-level Lisp with compile-time memory management
Stars: ✭ 204 (-5.12%)
Mutual labels:  compiler
Mimium
mimium (MInimal Musical medIUM) a programming language as an infrastructure for sound and music.
Stars: ✭ 212 (-1.4%)
Mutual labels:  compiler
Customasm
💻 An assembler for custom, user-defined instruction sets! https://hlorenzi.github.io/customasm/web/
Stars: ✭ 211 (-1.86%)
Mutual labels:  compiler
Compiler
Pawn compiler for SA-MP with bug fixes and new features - runs on Windows, Linux, macOS
Stars: ✭ 209 (-2.79%)
Mutual labels:  compiler

URLANG

Urlang is JavaScript with a sane syntax

Urlang is a language designed to allow straightforward translation to JavaScript. Think of Urlang as JavaScript with sane syntax and JavaScript semantics. JavaScript in this context is short for ECMAScript 5 in strict mode.

Although the constructs of Urlang and JavaScript map almost one-to-one, a little sugar was added:

  • function definitions allow default arguments
  • let expressions

Even though the syntax of Urlang is Racket-like, remember that the semantics is standard JavaScript. This means in particular that tail calls build context.

Examples

The following examples are compiled using the urlang form.

(urlang <module> ...)

The urlang form compiles the modules. The result of compiling a module is saved a file whose path is the module-name with .js added.

The urlang form is controlled by the following parameters:

(current-urlang-run?                           #t)  ; compile and run (using node)
(current-urlang-echo?                          #t)  ; print JavaScript to screen
(current-urlang-console.log-module-level-expr? #t)  ; use conole.log to print module-level exprs

Example (factorial)

 > (urlang
     (urmodule fact                                           ; module name
       (export fact)                                          ; fact is exported
       (import + - * = displayln ref console)
       (define (fact n) (if (= n 0) 1 (* n (fact (- n 1)))))
       (fact 5)))

The generated JavaScript:

 "use strict";
 function fact(n){return (((n===0)===false)?(n*(fact((n-1)))):1);};
 console.log((fact(5)));
 exports.fact=fact;

The output from Node:

 "120\n"

Example (cond-macro and array)

Urlang macro transformers receive and produce standard Racket syntax objects. This implies that standard tools such as syntax-parse are available.

Consider an Urlang version of cond:

SYNTAX (cond [e0 e1 e2 ...] ... [else en]), 
   like Racket cond except there is no new scope 

The urlang macro transformer is an standard (phase 0) Racket function.

  (define-urlang-macro cond
    (λ (stx)   
      (syntax-parse stx
        [(_cond [else e0:Expr e:Expr ...])
         #'(begin e0 e ...)]
        [(_cond [e0 e1 e2 ...] clause ...)
         (syntax/loc stx
           (if e0 (begin e1 e2 ...) (cond clause ...)))]
        [(_cond)
         (raise-syntax-error 'cond "expected an else clause" stx)])))

The macro can now we be used:

> (urlang
    (urmodule sum-example
      (define (even? x) (=== (% x 2) 0))
      (var (sum 0) x (a (array 1 2 3 4 5)) (i 0) (n a.length))
      (while (< i n)
        (:= x (ref a i))
        (cond
          [(even? x)  (+= sum (ref a i))]
          [else       "skip"])
        (+= i 1))
      sum))

The generated JavaScript:

"use strict";
function even_p(x){return ((x%2)===0);};
var sum=0,x,a=[1,2,3,4,5],i=0,n=a.length;
while((i<n)){(x=a[i]);(((even_p(x))===false)?"skip":(sum+=a[i]));(i+=1);};
console.log(sum);

The output from Node:

"6\n"

Overview

The heart of the system is a compiler written using the Nanopass compiler Framework. The compiler is exported as a function

compile : urlang-module -> JavaScript

that compiles an urlang module and produces JavaScript, that can be evaluated by the Node.js platform (or be embedded in a web page).

The Urlang module to be compiled can be represented

  1. as a syntax object
  2. as a Nanopass structure (representing an Lurlang program)

Use 1) to program in Urlang directly.

Use 2) if you intend to use Urlang as a compiler backend.

[Note: Nanopass is a framework for implementing compilers.]

The intended use of Urlang is to use 1) to write (generate) a Racket runtime in JavaScript. The middle-end of the Racket-to-JavaScript compiler will produce output as Nanopass structures, so 2) will be used as the backend for the Racket-to-JavaScript compiler.

Internally the function expand

expand : syntax -> LUrlang

will parse and expand its input and produce an LUrlang representation.

Note that expand allows the user to extend the input language using define-urlang-macro. An Urlang macro is a syntax to syntax transformation implemented as a normal Racket function. This allow you to use all of the standard Racket macro machinery.

Main functions:

expand : syntax -> Lurlang
    expand the input and produce a fully expanded Urlang program
    represented as a Lurlang structure
    
compile : syntax ->
    Expand and compile. The output is written to standard out.
    
eval : syntax -> value
    expand, compile and run the input (an Urlang module represented as a syntax object)
    Running means that `node` is used to run the generated JavaScript.

Having Urlang as a #lang language allows

  • macros (using full Racket at compile time)
  • export of defined names
  • easier testing

In the grammar below:

  • x stands for a non-keyword identifier
  • f stands for an identifier defined as a function
 <module>            ::= (urmodule <module-name> <module-path> <module-level-form> ...)

 <module-level-form> ::= <export> | <import> | <definition> | <statement> 
 <export>            ::= (export x ...)
 <import>            ::= (import x ...)
 <definition>        ::= (define (f <formal> ...) <body>)
                      |  (define x <expr>)
 <formal>           ::= x | [x <expr>]

 <statement>         ::= <var-decl> | <block> | <while> | <do-while> | <if> | <break> | <expr> 
 <var-decl>          ::= (var <var-binding> ...)
 <block>             ::= (block <statement> ...)
 <var-binding>       ::= x | (x e)
 <while>             ::= (while <expr> <statement> ...)
 <do-while>          ::= (do-while <expr> <statement> ...)
 <if>                ::= (sif <expr> <statement> <statement>)
 <break>             ::= (break) | (break label)

 <body>              ::= <statement> ... <expr>

 <expr>              ::= <datum>   | <reference> | <application> | <sequence>
                      |  <ternary> | <assignment> | <let> | <lambda> | <dot>
 <ternary>           ::= (if <expr> <expr> <expr>)
 <reference>         ::= x
 <application>       ::= (<expr> <expr> ...)
 <sequence>          ::= (begin <expr> ...)
 <assignment>        ::= (:= x <expr>)
 <let>               ::= (let ((x <expr>) ...) <statement> ... <expr>)
 <lambda>            ::= (lambda (<formal> ...) <body>)

 <keyword>           ::= define | begin | urmodule | if | := | ...se code...

 <datum>             ::= <fixnum> | <string> | #t | #f

 <identifier>     an identifier that is not a keyword
 <fixnum>         an integer between -2^53 and 2^53
 <module-name>    a symbol or string

NOTES

Some application are special cases:

(ref e0 e1)     becomes  e0[e1]
(ref e0 "str")  becomes  e0.str    
(array e ...)   becomes  [e,...]

Property access with dot notation is rewritten to use bracket syntax in the parser.

Example: object.property becomes object["property"]

SEMANTICS

(if e0 e1 e2)

If e0 evaluates to value strictly equal to false, then e2 otherwise e1. Note: The JavaScript becomes ((e0===false) ? e2 : e1)

(var x (y 3))

Binds x to undefined and y to 3.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].