Giter VIP home page Giter VIP logo

roy's Introduction

Roy Build Status

Roy is a small functional language that compiles to JavaScript. It has a few main features:

  • Damas-Hindley-Milner type inference
  • Whitespace significant syntax
  • Simple tagged unions
  • Pattern matching
  • Structural typing
  • Monad syntax
  • Not-horrible JS output

Usage

To compile:

make deps
make

To enter a REPL:

./roy

To compile and run a .roy file:

./roy -r examples/helloworld.roy

To compile a .roy file to .js:

./roy examples/helloworld.roy
cat examples/helloworld.js

Example

Input (test.roy):

let addTwo n =
    n + 2

console.log (addTwo 40)

Output (test.js):

var addTwo = function(n) {
    return n + 2;
}
console.log(addTwo(40))

Calling addTwo "test" will result in a compile-time error (addTwo can only take a Number).

See the examples directory for more.

License

MIT

Editor Support

Resources

roy's People

Contributors

alsonkemp avatar alvivi avatar brow avatar cassiemeharry avatar constellation avatar dbousamra avatar esehara avatar gregwebs avatar i80and avatar istathar avatar jameshfisher avatar jb55 avatar joneshf avatar joseanpg avatar kasperlanger avatar kennknowles avatar miikka avatar mpenet avatar non avatar paulmillr avatar piranha avatar puffnfresh avatar raimohanska avatar rehno-lindeque avatar silvanshade avatar stew avatar taku0 avatar tokland avatar twopoint718 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

roy's Issues

Write "Introduction of Roy".

I love the concept of Roy and I try to write some code with Roy.
However, when I write the code, I need to read the example code.

I've seen no documentation about the syntax of the Roy.
I think, Need "Introdcution of Roy",or any Document about the syntax of Roy.

Can't compile do construct without bind statement

Here's an example of what I'm trying to do

let deferred = {
  return: \x -> $.when(x)
  bind: \x f -> x.done(f)
}

let v = (do deferred
  return "hello world"
)

(do deferred
  val <- v
  console.log val
)

I get the error TypeError: Cannot set property 'rest' of undefined in the second do

Better monad example

Maybe it's worth it to have something better as an example for monad, to show why would you want them in JS. Something like this maybe:

type Request = {url: String, payload: String}

let ajaxRequest = {
  return: fn x = x
  bind: fn (x : Request) f =
    $.ajax x.url x.payload f
}

let v = (do ajaxRequest
  bind value = {url: '/url/', payload: 'stuff'}
  console.log value
  return value
)

Declare externals

To inter-operate with other JS in a typesafe way there needs to be some way of declaring external functions/objects. Does this ability exist?

Fix Roy Repl to use multi-line or ";".

Example Python:

>>> def test():
...         pass
... 
>>> 

ghci (Haskell):

Prelude> let test x = do{if x == 1 then 0 else x * 2}
Prelude> test 2
4

but, Roy:

roy> let gcd a b =
Error: Parse error on line 2: Unexpected 'EOF'

roy> let gcd a b = if b == 0 then
Error: Parse error on line 2: Unexpected 'EOF'

roy> let gcd a b = if b == 0 then a else gcd b (a % b)
Error: Parse error on line 2: Unexpected 'IDENTIFIER'

roy> let gcd a b = ;if b == 0 then;a;else;gcd b (a % b)
Couldn't tokenise: 

It should be able to use multi-line or ";".

Option monad and deep matching tests are broken

Commit 8f31ad8 brokes tests option_monad and deep_matching:


Error: test/option_monad.roy Command failed: 
node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
TypeError: Cannot read property '0' of undefined
    at roy/src/typeinference.js:425:76
    at Array.forEach (native)
    at Function.<anonymous> (roy/node_modules/underscore/underscore.js:81:11)
    at roy/src/typeinference.js:424:23
    at roy/src/typeinference.js:451:17
    at Array.forEach (native)
    at Function.<anonymous> (roy/node_modules/underscore/underscore.js:81:11)
    at Object.visitMatch (roy/src/typeinference.js:417:15)
    at [object Object].accept (roy/src/nodes.js:106:26)
    at roy/src/typeinference.js:141:17

Error: test/deep_matching.roy Command failed: 
node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
TypeError: Cannot read property '0' of undefined
    at roy/src/typeinference.js:425:76
    at Array.forEach (native)
    at Function.<anonymous> (roy/node_modules/underscore/underscore.js:81:11)
    at roy/src/typeinference.js:424:23
    at roy/src/typeinference.js:451:17
    at Array.forEach (native)
    at Function.<anonymous> (roy/node_modules/underscore/underscore.js:81:11)
    at Object.visitMatch (roy/src/typeinference.js:417:15)
    at [object Object].accept (roy/src/nodes.js:106:26)
    at roy/src/typeinference.js:141:17

Change lambda syntax to haskell's

What do you think about changing lambda syntax to haskell's?

someLambda = \a b c -> a * b * c

This would allow to remove fn keyword.

Need more whitespace significant syntax

OK:

let tests = files.filter (λx →
  (x.lastIndexOf '.roy') == (x.length - 4)
)

console.log (do traceMonad
  w ← 1
  let x = 2
  y ← 3
  z ← 4
  return w + x + y + z
)

Type error:

let tests = files.filter λx →
  (x.lastIndexOf '.roy') == (x.length - 4)

console.log do traceMonad
  w ← 1
  let x = 2
  y ← 3
  z ← 4
  return w + x + y + z

Make functions curried

Given

let f a b c = a + b + c

let g = f 1 2

I get the error

Error: Type error: Function(Number,Number,'bnj) is not Function(Number,Number,Number,Number)

from which I gather functions are not curried. I suggest that they should be; i.e. an unoptimized compilation of the above would give something like

var f = function(a) {
  return function(b) {
    return function (c) {
      return a + b + c;
    }
  }
}
var g = f(1)(2);

Add effect tracking

Effect tracking is awesome and useful.

Requires type-classes and monads.

DOM, network, mutable actions, console.log would all be in IO.

Finding the right place to call unsafePerformIO could be tricky. On browsers, you'd probably want it on anything where the browser event loop enters code, e.g. on DOM event handlers, setTimeouts, script load completion.

The IO monad in Scalaz could be a good reference.

Implement lists

As I see, recursive data types are supported now. So I guess we need to implement in-language support for lists?

For example, [1, 2, 3] needs to be automatically converted to Roy list.

Remove top-level expressions

Roy currently allows expressions, eg. console.log, at the top level of a module. This is lax and un-functional. Expressions should be restricted to inside functions (and at some point hopefully within an IO monad). A single main function should be allowed per module.

JS output would not pass lint

Just looking over roy.

JS output would not pass lint, it should produce clean JS.

like the type casting, offers nothing for async processing (at least what I saw.)

Add support for calling roy from any place

Would like to do such a thing:
I add an env variable $ROY_HOME, pointing to the directory, where roy is compiled and add it to $PATH. If I then execute roy from it's directory, it starts fine. If I do it from any other directory:

$  roy
node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
Error: ENOENT, no such file or directory 'package.json'
    at Object.openSync (fs.js:228:18)
    at Object.readFileSync (fs.js:119:15)
    at Object.main (/home/georgii/workspace/roy/src/compile.js:462:23)
    at Object.<anonymous> (/home/georgii/workspace/roy/roy:2:26)
    at Module._compile (module.js:432:26)
    at Object..js (module.js:450:10)
    at Module.load (module.js:351:31)
    at Function._load (module.js:310:12)
    at Array.0 (module.js:470:10)
    at EventEmitter._tickCallback (node.js:192:40)

Use intermediate representation like Haskell "Core"

It would be useful to define a minimal simple functional intermediate language to which Roy can be compiled, analogous to Haskell Core. This would:

  • clearly separate work on syntax and sugar from work on semantics.
  • simplify the task of defining Roy's semantics.
  • provide a language on which optimizations can be done.

State that Roy uses strict evaluation

I assume this is the intention. Consider:

  • What would compiled JS with thunks look like?
  • What issues would arise in interaction between lazy JS and external strict JS?

Another take on the ajax monad example

To me it makes more sense if "return" returns a jquery promise like this...

let deferred = {
  return: \x -> $.when(x)
  bind: \x f -> x.done(f)
}

let v = (do deferred
  value <- $.ajax {url: '/examples/helloworld.roy', payload: 'stuff'}
  console.log value
)

This is also more in sync with the monadic laws.

Update:
The above example is broken - I believe this is better:

let deferred = {
  return: \x -> $.when(x)
  bind: \x f ->
    let dfd = $.Deferred()
    x.done(\val -> 
        (f val).done(\val2 -> dfd.resolve val2)
    )
    dfd
}

let v = (do deferred
  val <- $.ajax '/examples/helloworld.roy'
  val2 <- $.ajax '/examples/alias.roy'
  return val ++ val2
)

(do deferred
  text <- v
  console.log text
)

Add roy to pygments

Pygments is a generic syntax highlighter that GitHub uses. It's hard to read code in browser without proper formatting.

So we need to create a patch and send a pull request to main pygments repo with roy's support.

Recursive datatypes not allowed (?)

Given

data List a = Cons a (List a) | Nil

or

data Tree a = Tree (Tree a) a (Tree a) | Nil

etc., I get the (syntactic) error

Error: Parse error on line 2: Unexpected 'IDENTIFIER'

Not sure what this is referring to; line 2 does not exist.

Haskell accepts these declarations.

Unnable to invoke function called 'then'

Is there a way to invoke methods called then like in the following example

($.when "foo").then(\x ->
  console.log x
)

I was hoping it would compile to something like

$.when("foo").then(function(x){console.log(x);});

but I get the following error

Error: Parse error on line 2: Unexpected 'THEN'

Unicode keywords

Scala / Haskell support unicode keywords as an alternative to default ones.

\ λ
<-
->
=>

What do you think about this idea?

Override "eval()" function.

Source :

roy> eval("var i = 0")
roy> i
0 : Native
roy> eval("let hoge = 0")
SyntaxError: Unexpected identifier

I think eval function should be the function to interpret "String" in its own language.It should be able to interpret JavaScript and Roy,or only Roy.

Text editor plugins

It is very hard to write some code without proper syntax highlighting. I could start work on TextMate bundle as it's my everyday editor.

As a temporary solution, we could use color highlighting of some other language. @pufuwozu syntax of which language, in your opinion, is the most similar to roy's?

Meta-command to show Roy-syntax source code in REPL.

label : wishlist ?

If there is Meta-Command which can show the code of Roy, a developer will help to write a code.

example:

roy > let plusone x = x + 1
roy > plusone
function (x) {
    return x + 1;
} : Function(Number,Number)
roy > :source plusone
plusone x = x + 1

and

roy > let three = 1 + 2
roy > three
3 : Number
roy > :source three
three = 1 + 2

Can't write map function

Given

data List a = Empty | Cons a (List a)

let map f l = match l
  case (Cons x xs) = Cons (f x) (map f xs)
  case Empty = Empty

I get the error

Error: Type error: Native is not List 'jqq

Demo page is missing "tracing monad" example

Just noticed the tracing monad example at http://roy.brianmckenna.org/ is broken. Here's the output shown at "Roy input" when that example is selected:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /examples/tracemonad.roy was not found on this server.</p>
<p>Additionally, a 404 Not Found
error was encountered while trying to use an ErrorDocument to handle the request.</p>
</body></html>

Can't define implicit pattern match by using data constructors as function parameters

Given

data Maybe a =
  Just a | Nothing

data List a = Empty | Cons a (List a)

I can then write

let head l = match l
  case Empty = Nothing
  case (Cons x xs) = Just x

However I can't write

let head Empty = Nothing
let head (Cons x xs) = Just x

as this produces

Error: Parse error on line 8: Unexpected 'IDENTIFIER'

I can't remember what the latter style is called, but some might find it nicer.

(Though as it can just be reduced to the first example, it's just syntactic convenience and I would put this under "wishlist".)

Rewrite roy in roy

What do you think about rewriting roy source from JS to roy itself (self-hosting)?

I think CoffeeScript showed that this works greatly.

Haskell's "bind" operator

Should we provide value <- expr operator as an alternative to bind val = expr? Or maybe value <- expr should be only valid syntax? Or maybe no <- operator at all?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.