Skip to content

ggVGc/TerseJS

Repository files navigation

TerseJS

This project has a few main goals

  • Read/Write less code.

  • Generate code that looks hand-written, so it is easy to work on even without the original input.

  • Stay a superset of standard ES5 JavaScript, with a few mostly non-intrusive breaks.

To get a first glimpse of output, try running tersejs examples.tjs in this repository.

Currently only runs on linux 64bit. Other platforms should work, if you manage to compile indentation_to_braces.hs and put it in bin.

Main features:

  • Indentation sensitivity: Each level of indentation gets transformed into a block between { }

  • Easier object creation, based on lexical scoping rather than hacking classes into javascript.

  • Anonymous functions - Courtesy of lambda_chop macros

  • Piping

  • Constructs for reducing line noise and allow minimum use of parentheses.

Incompatibilities with javascript

  • Some bit-shifting operators are used for other language features.

Usage:

bin/tersejs [-o outFile -s <sweet.js options>] infile
If no output file is specified with -o, result is printed to stdout.

Examples:

// Object/module definition
// @ is just shorthand for 'self', which is an object returned by the end of a @@-block
// @foo and self.foo are equivalent and both can be used
module Foo
constructor start
  c = start;// lexically scoped within Foo. var keyword not needed
  @printOnInc = true; // Object property, equivalent to self.printOnInc
  endvars // Finish variable declarations

// Lexically scoped function within Foo
private reset
  c = 0

// Public method of Foo
public next
  ++c // can access local variable within Foo
  if @printOnInc
    console.log! c
  if c > 10
    reset!

endmodule

var f = makeFoo! 2; // Create foo with start=2
f.next!;            // prints 3
f.printOnInc=false
f.next!;          // nothing
f.printOnInc=true
f.next!;          // prints 5


// Pipes
10 >> triple >> console.log; // console.log(triple(10))

// Reverse pipe, function application
// This just surrounds everything that follows in parens
foo | bar | 10, baz | 30; // foo(bar(10, baz(30)));


// Lift-Execute
// Applies each tuple to a given function
foo <-
  1,2
  3,4
//Output:
//foo(1,2);
//foo(3,4);


//Function invocation (call with no arguments)
foo!; // foo();

//Object cascading
foo.bar..
  .num = .memFoo!; // foo.bar.num = foo.bar.memFoo();
  var posX = .pos.x; // var x = foo.bar.pos.x;

//Property copying
foo.bar{a b c} := bab.zoo; // Assigns properties a,b and c from bab.zoo to foo.bar
// Output:
//foo.bar.a = bab.zoo.a;
//foo.bar.b = bab.zoo.b;
//foo.bar.c = bab.zoo.c;

// Partial application
var bar = foo~42; // bar = function(b,c){ return foo(42, b, c); }

// Named functions
fn foo a b
  console.log| 'Foo with a='+a+' b='+b;

//Function names can be object properties
fn foo.bar x
  console.log("I am foo.bar with value "+x);

// Anonymous functions
var f = λ x y
  return x + y; // function(x,y){return x+y;}/

//use arrow for automatic return
var f = λ x y -> x+y

//lam is a synonym for λ, this also works
var triple = lam x -> x*3;

// Curry by wrapping arguments in parens
var always = λ(x y) -> x
always(42)(12) === 42;

// Placeholders using square brackets and `#`. Automatic return
var str = λ[#.toString()];
var sub = λ[# - #];
sub(2, 1) === 1;

// Shorthand property lambdas
var names = arr.map| λ.name;

//do-block, wraps block in (function(){}())
var someGlobalState;
do
  var tmp = 41;
  var tmp2 = tmp+1;
  someGlobalState.update| tmp2;
// tmp and tmp2 not in scope outside of do-block

// Bound functions.
// => arrow makes sure the anonymous function is bound to the current 'this'-value
this.num = 42;
DB.getResource| 'important_thing', λ resp =>
  console.log| "DB responded with "+resp;
  console.log| this.num+" is still 42";

Thanks:

  • natefaubion for writing lambda_chop, and helping me a lot in learning sweet.js.

About

Preprocessor for terser javascript

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages