Skip to content
Browse files

Implement unicode identifiers & new bind.

Implements unicode identifiers:

λ: \
←: <- (replaces `bind` keyword)
→: ->
⇒: =>
∀: for all
∈: elem
∉: not elem
∘: function composition
  • Loading branch information...
1 parent c091ae4 commit dcbd2e2f84438eb9e106f2fcde48dad583d013fa @paulmillr paulmillr committed Dec 4, 2011
Showing with 91 additions and 24 deletions.
  1. +1 −1 examples/data.roy
  2. +1 −1 examples/types.roy
  3. +8 −4 lib/std.roy
  4. +3 −3 run-tests.roy
  5. +3 −3 src/grammar.js
  6. +31 −1 src/lexer.js
  7. +2 −2 test/functions.roy
  8. +4 −4 test/option_monad.roy
  9. +5 −5 test/trace_monad.roy
  10. +7 −0 test/unicode.out
  11. +26 −0 test/unicode.roy
View
2 examples/data.roy
@@ -11,7 +11,7 @@ printSomething None
data Either a b =
Left a | Right b
-let printString (s : String) =
+let printString (s: String) =
console.log s
let printResult e = match e
View
2 examples/types.roy
@@ -5,7 +5,7 @@ console.log 40 + 2
// console.log "40" + 2
// Explicit
-let f x : Number = x
+let f x: Number = x
console.log (f 100)
View
12 lib/std.roy
@@ -69,13 +69,17 @@ let maybe n f o = match o
case None = n
let optionMonad = {
- return: \x ->
+ return: λx →
Some x
- bind: \x f -> match x
+ bind: λx f match x
case (Some a) = f a
case None = None
}
-// Either type
-
+// Either type.
data Either a b = Left a | Right b
+
+// Math constants.
+//let π = Math.PI
+//let π2 = π * 2
+//let τ = π2 // tauday.com
View
6 run-tests.roy
@@ -5,14 +5,14 @@ let child_process = require 'child_process'
let dir = "test"
let files = fs.readdirSync dir
-let tests = files.filter (\x ->
+let tests = files.filter (λx →
(x.lastIndexOf '.roy') == (x.length - 4)
)
-tests.forEach (\t ->
+tests.forEach (λt →
let name = path.join dir t
let outFile = (path.join dir (path.basename t '.roy')) ++ '.out'
- child_process.exec './roy -r ' ++ name (\error stdout stderr ->
+ child_process.exec './roy -r ' ++ name (λerror stdout stderr
if error then
console.log "Error:" name error.message
else
View
6 src/grammar.js
@@ -5,8 +5,9 @@ var grammar = {
"startSymbol": "program",
"operators": [
+ ["left", "RIGHTARROW", "LEFTARROW", "RIGHTFATARROW", "ELEM", "NOTELEM",
+ "FORALL", "COMPOSE"],
["left", "BOOLOP"],
- ["left", "RIGHTARROW"],
["left", "COMPARE", "WITH"],
["left", "+", "-"],
["left", "MATH", "CONCAT"],
@@ -39,7 +40,7 @@ var grammar = {
],
"doLine": [
["line", "$$ = $1;"],
- ["BIND IDENTIFIER = expression", "$$ = new yy.Bind($2, $4);"],
+ ["IDENTIFIER LEFTARROW expression", "$$ = new yy.Bind($1, $3);"],
["RETURN expression", "$$ = new yy.Return($2);"]
],
"doBlock": [
@@ -216,7 +217,6 @@ var grammar = {
],
"keywordOrIdentifier": [
["RETURN", "$$ = $1;"],
- ["BIND", "$$ = $1;"],
["IDENTIFIER", "$$ = $1;"]
],
"identifier": [
View
32 src/lexer.js
@@ -31,7 +31,6 @@ var identifierToken = function() {
case 'match':
case 'case':
case 'do':
- case 'bind':
case 'return':
case 'macro':
case 'with':
@@ -127,6 +126,13 @@ var literalToken = function() {
var next;
switch(tag) {
case '<':
+ next = chunk.slice(0, 2);
+ if(next == '<-') {
+ tokens.push(['LEFTARROW', next, lineno]);
+ return 2;
+ }
+ tokens.push(['COMPARE', tag, lineno]);
+ return 1;
case '>':
tokens.push(['COMPARE', tag, lineno]);
return 1;
@@ -200,9 +206,33 @@ var literalToken = function() {
}
tokens.push([tag, tag, lineno]);
return 1;
+ case 'λ':
case '\\':
tokens.push(['LAMBDA', tag, lineno]);
return 1;
+ case '':
+ tokens.push(['LEFTARROW', tag, lineno]);
+ return 1;
+ case '':
+ tokens.push(['RIGHTARROW', tag, lineno]);
+ return 1;
+ case '':
+ tokens.push(['RIGHTFATARROW', tag, lineno]);
+ return 1;
+ case '':
+ tokens.push(['FORALL', tag, lineno]);
+ return 1;
+ // Called so because of Haskell's function elem.
+ case '':
+ tokens.push(['ELEM', tag, lineno]);
+ return 1;
+ case '':
+ tokens.push(['NOTELEM', tag, lineno]);
+ return 1;
+ // Function composition.
+ case '':
+ tokens.push(['COMPOSE', tag, lineno]);
+ return 1;
case ']':
case ':':
case '.':
View
4 test/functions.roy
@@ -1,8 +1,8 @@
let named x = x
-let anon = \x -> x
+let anon = λx → x
let multiArgs x y z = x
-let anonMultiArgs = \x y z -> x
+let anonMultiArgs = λx y z -> x
console.log (named "Hello") (anon "world")
console.log (multiArgs "Hello" "world" "!") (anonMultiArgs "world" "!" "Hello")
View
8 test/option_monad.roy
@@ -1,17 +1,17 @@
// Uses `Option a` from stdlib
let optionMonad = {
- return: \x ->
+ return: λx →
Some x
- bind: \x f -> match x
+ bind: λx f match x
case (Some a) = f a
case None = None
}
let m = (do optionMonad
- bind x = Some 1
+ x ← Some 1
let y = 2
- bind z = Some 3
+ z ← Some 3
return x + y + z
)
View
10 test/trace_monad.roy
@@ -1,16 +1,16 @@
let traceMonad = {
- return: \x ->
+ return: λx →
console.log "Return:" x
x
- bind: \x f ->
+ bind: λx f
console.log "Binding:" x
f x
}
console.log (do traceMonad
- bind w = 1
+ w ← 1
let x = 2
- bind y = 3
- bind z = 4
+ y ← 3
+ z ← 4
return w + x + y + z
)
View
7 test/unicode.out
@@ -0,0 +1,7 @@
+Hello world
+Hello world
+Binding: 1
+Binding: 3
+Binding: 4
+Return: 10
+10
View
26 test/unicode.roy
@@ -0,0 +1,26 @@
+let named x = x
+let anon = \x -> x
+
+let multiArgs x y z = x
+let anonMultiArgs = \x y z -> x
+
+console.log (named "Hello") (anon "world")
+console.log (multiArgs "Hello" "world" "!") (anonMultiArgs "world" "!" "Hello")
+
+
+let traceMonad = {
+ return: \x ->
+ console.log "Return:" x
+ x
+ bind: \x f ->
+ console.log "Binding:" x
+ f x
+}
+
+console.log (do traceMonad
+ w <- 1
+ let x = 2
+ y <- 3
+ z <- 4
+ return w + x + y + z
+)

0 comments on commit dcbd2e2

Please sign in to comment.
Something went wrong with that request. Please try again.