elfu
v0.0.40
Published
Programming language that elves use
Downloads
161
Maintainers
Readme
#Elfu - hosti lammen
Elfu is highly experimental symbolic language. UNICODE contains thousands and thousands of symbols, why not use them?
- Elfu stands for elvish functional language or elvish numeric gongfu.
- Elfu in elvish is called hosti lammen, or computing language.
- Elfu is Javascript compatible, you mix Javascript and Elfu in Elfu file.
- Elfu file extension is .yy (this is elvish)
- Elfu is written in Javascript itself.
- To type symbols we use TAB completion feature of the editor.
- Most of symbols are just replaced with their Javascript counterparts.
- Some symbols are parsed in a special way, like
➮
or⬌
. - Editors known to be Elfu-friendly are Sublime Text, Geany, Deodar.
- If your computer does not show all symbols, there is a font file [elfu.ttf][100].
- Elfu only uses Unicode standard symbols.
- Elfu is mostly reversable, in other words you can convert
.yy->.js
and.js->.yy
. Mostly. - Read this document in better font here. [100]: http://exebook.github.io/fonts/elfu.ttf
Contents
- Screenshot
- Syntax
- function definition
➮
- return statement
$
- while and for statements
⧖
and⧗
- break and continue statements
@
- each looping
⬌
,'►' and⬍
- console.log
ロ
- if, else, elseif
⌥
⎇
⥹
- var and def
∇
∆
≜
- stack operations
⬊
⬈
⬋
⬉
- superscript indexing
Xⁱ
- this and undefined are
⚫
⚪
∅
- comparison operators
≟
and≠
- clean and visible semicolon
⦙
- delete and new are
⏀
and⟡
- length of an array or a string
↥
- require directive
≣
- Math functions
⍽
⬠
⚂
- infinite loop
∞
- time operations
⌛
⌚
⚡
- node.js fs functions
⛁
,⛃
- str serialization with
⌶
⫴
≂
- booleans
⦿
and⦾
- last item of a string or an array
ꕉ
↟
- finding occurence in a string or array with
≀
≀≀
- array utilities
⋃
⨄
ꔬ
⧉
ꗚ
❄
, string and character utilities△
◬
⩪
- symbolic variables
- is defined
⟑
- multi line strings with
'''
- tuples with
ꔪ
- object keys as an array with
⚷
- namespace utility with
➮|
- new syntax for branching with
❰
❱
◇
⁋
- Usage
- Dotcall syntax
- Feedback
/* TODO: ∼◬ String.fromCharCode() - auto arg ꘉ bind - auto arg - mini functions f = ➮ a + b ⦙ ロ f(2, 3)
*/
#Screenshot Here is how Elfu looks in author's editor:
#Syntax
#####function definition ➮
typed as
fu|TAB
.Elfu translator will replace
➮
withfunction
.you can avoid
(
,)
and,
in argument declaration.if you omit any arguments, arguments
a
b
c
are default.use
➮f(){}
or➮{}
syntax to declare an anomymous function without arguments.➮ {}
is a lambda with default arguments a, b, c.➮ a + b ;
becomes((➮ { $a+b }).bind(this))
- aka "arrow function"anonymous function with arguments
a,b
:➮ - a b {}
➮ compare (a, b) { console.log(a == b) }
➮ compare a b { console.log(a == b) }
➮ compare { console.log(a == b) }
[1,2,3].forEach(➮ { console.log(a) })
n = 2
a ∆ [1,2,3,4,5] ꔬ ➮ a > n ; // 'this' is bound to a caller
ロ a // prints [3,4,5]
Math.sum = ➮ - x y {
$ x+y
}
return statement $
$
is replaced withreturn
.
➮ four { $ 2 + 2 }
while and for statements ⧖
and ⧗
⧖
is replaced withwhile
.⧗
is replaced withfor
.- typed as
wh|TAB
,fo|TAB
. - parens () can be avoided if you have braces {}
⧖ (true) step()
⧗ (var i = 0; i < 3; i++) step()
break and continue statements @
@
is replaced withbreak
.♻
is replaced withcontinue
.
⧖ (true) {
step()
if (again()) ♻
if (finished()) @
}
n ∆ 5
⧖ n > 0 { // parens, ( and ) are not needed
ロ n--
}
each looping ⬌
and ⬍
⬌
typed asea|TAB
.- compiles to
for (var i = 0; i < obj.length; i++)
. - just type
i ⬌ obj
, it converts to the above. ►
(iterator) typed asit|TAB
.- ► is similar to ⬌, but the 'i' is an array item rather than an index.
⬍
typed asfe|TAB
.`- simply converts to
.forEach
.
var a = [1,2,3]
i ⬌ a { console.log(a[i]) }
a ∆ [1,2,3]
i ⬌ a ロ aⁱ
a ∆ [1,2,3]
i ► a ロ i
// index still can be accessed with `_` + name, in this case `_i`.
The `i` will be replaced with `a[i]`. Operator `►` either requires `{}` or the expression must be on a single line. (Otherwise Elfu would need to use the full blown expression parser, which is beyond the scope of the current version).
A ∆ [1,2,3,4]
A ⬍ (➮ { ロ a ; })
console.log ロ
- typed as
lo|TAB
ロ
is Chinese/Japanese character for mouth.- tired typing console.log hundreds times a day?
ロ
takes everything until the end of line or;
as arguments.- make sure you add ';' if your code continues on this line.
ロ 'hello world!'
ロ 'numbers are:', 1, 2, 3
if (true) ロ 'here'
➮ compare { ロ a == b; }
Automatic +
insertion. You can avoid +
for brevity, because inside ロ
all string literals can be automatically glued to identifiers and some obvious expressions with '+'.
x ∆ 12345
a ∆ [1,2,3]
ロ 'x = ' x
ロ 'four means ' (2+2)
ロ 'a = ' a ' and length is ' a↥
Elfu allows you to mix with ${}
style of strings.
a ∆ 5678
ロ `a = ${a}`
if, else, elseif ⌥ ⎇ ⥹
typed as
if|TAB
,el|TAB
,ei|TAB
.⌥
is replaced withif
.⎇
is replaced withelse
.⥹
is replaced withelse if
.if the conditional statement is enclosed in
{}
, then()
are optional()
are optional when the conditional statement starts with one of@
,$
,♻
,ロ
,⧖
,⧗
, '∞', ';', '⌥'.
⌥ (x == 1) ロ 'GREAT'
⥹ (x == 2) ロ 'OK'
⎇ ロ 'WRONG'
⌥ x == 2 { ロ 'x equals to two' ⦙ }
var and def ∇ ∆ ≜
- typed as
va|TAB
,de|TAB
,df|TAB
. ∇
is replaced withvar
.x ∆
is translated tovar x =
.∆
reads as is defined as or just define.∆
used to be delta, but in fact it is a simplified form of a math symbol≜
-- definition or is defined as.x ≜ y
is replaced withif (typeof x == 'undefined') x = y
.
x ∆ 100
⧗ (∇ i = 0; i < x; i++)
a ∆ 1 b ∆ 'string' c ∆ {} d ∆ []
➮ countIt {
a.count ≜ 0
a.count++
}
state ∆ {}
countIt(state)
countIt(state)
ロ state
stack operations ⬊
⬈
⬋
⬉
⬊
⬈
are typed aspu|TAB
andpo|TAB
.⬊
is for.push
and⬈
is for.pop
.- you can omit
(
and)
. ⬋
⬉
are typed asPu|TAB
andPo|TAB
.⬋
is for.shift
and⬉
is for.unshift
.- mnemonically
shift()
ispop()
from the other side. - mnemonically
unshift()
ispush()
from the other side. - add
(
and)
if you push an expression.
A ∆ []
A ⬊ 1
A ⬊ (2 + 2)
// A = [1, 4]
ロ A ⬈ ; // 4
superscript indexing Xⁱ
aⁱ
translates toa[i]
.a⁰
translates toa[0]
.aⁱ⁰
translates toa[i][0]
.- typed as
.i|TAB
or.1|TAB
. - super-script index can only be single character.
- supported are all lowercase latin characters and digits
0
-9
. - do not try to use UPPERCASE characters.
- do not try to use multicharacter variables like
count
.
A = [1,2,3]
i ⬌ A ロ Aⁱ
B = [[1,111],[2,222],[3,333]]
i ⬌ B ロ Bⁱ¹
this
and undefined
are ⚫
⚪
∅
⚫
is translated tothis.
.⚪
is translated tothis
.∅
is translated toundefined
.⚫
typed asth|TAB
.⚪
typed asthis|TAB
.∅
typed asun|TAB
.
➮ f {
⌥ (⚫name == ∅) ロ 'no name'
⎇ ロ ⚫name
}
f()
⚫name = 'f1'
f.bind(⚪)()
comparison operators ≟
and ≠
- typed as
eq|TAB
andne|TAB
. ≟
converts to==
.≠
converts to!=
.
⌥ (x ≟ 2) ロ 'two'
⌥ (x ≠ 2) ロ 'not two'
clean and visible semicolon ⦙
- since elfu code is so condensed, many expressions fit on the same line, to improve readability of such dense code, cleaner version of semicolon
⦙
was introduced. - typed as
sc|TAB
. ⦙
and;
both can be used.
ロ 2+2 ⦙ ロ 3+3 ⦙ ロ 4+4 ; ロ 5+5
delete
and new
are ⏀
and ⟡
⏀
typed asdl|TAB
.⟡
typed asnew|TAB
.
➮ f { ⚫name = 'f1' }
a ∆ ⟡ f
ロ 'name =', a.name
⏀ a ⦙ a = ∅
length of an array or a string ↥
- typed as
.le|TAB
. ↥
is translated to.length
.- do not type '.' before
↥
, it is implied.
A ∆ [1,2,3]
s ∆ 'hello'
ロ s↥, A↥
x ∆ 0
⧖ (x < s↥) { ロ sˣ ⦙ x++ }
require directive ≣
- typed as
re|TAB
. ≣
is replaced withrequire
.- you can use
(
and)
or avoid them.
fs ∆ ≣ 'fs'
spawn ∆ ≣ ('child_process').spawn
#####Math functions ⍽
⬠
⚂
⚂
is typed asra|TAB
.⚂
is converted toMath.random()
⬠
is typed asro|TAB
.⬠
is converted toMath.round()
⍽
is typed asfl|TAB
.⍽
is converted toMath.floor()
⬠
and⍽
can omit(
and)
for simple expressions.
⧗ (i ∆ 0 ⦙ i < 20; i++) ロ ⬠ (⚂ * 1000000)
∇ a = 0.5
ロ ⬠ a, ⍽ a
infinite loop ∞
- typed as
in|TAB
. - '∞' is replaced with
while(true)
. - sometimes you just need an infinite loop.
- or you need a loop whose logic is more complex than
for
orwhile
.
∞ step() // infinite
x ∆ 0
∞ {
x += ⚂ * 2
⌥ (x ≟ 5) @
⌥ (x ≟ 7) @
⌥ (x > 10) @
ロ x
}
time operations ⌛
⌚
⚡
⌛
is converted tosetTimeout
.⌚
is converted tosetInterval
.⌿⌛
is converted toclearTimeout
.⌿⌚
is converted toclearInterval
.⚡
is converted to(new Date().getTime())
.⚡
gives you millisecond tick.⌛
is typed asst|TAB
.⌚
is typed assi|TAB
.⚡
is typed astt|TAB
(mnemonic: time tick).⌿⌛
is typed asct|TAB
.⌿⌚
is typed asci|TAB
.
ロ 'please wait two seconds'
⌛(➮ {ロ 'ready';}, 2000)
T ∆ ⚡ ⦙ s ∆ ''
⧖ (s↥ < 1000000) s += 'a'
ロ 'benchmark: ', ⚡ - T, 'ms'
node.js fs
functions ⛁
, ⛃
⛁
is replaced withfs.readFileSync
.⛃
is replaced withfs.writeFileSync
.⛁
is typedfsrs|TAB
.⛃
is typedfsws|TAB
.- you can omit
(
and)
for ⛁ with a single argument.
fs ∆ ≣ 'fs'
A ∆ ⛁'readme.txt' ≂ ⌶ '\n'
ロ A ↥, 'lines loaded'
str serialization with ⌶
⫴
≂
.
⌶
is typed assp|TAB
.⫴
is typed asjo|TAB
.≂
is typed asts|TAB
.⌶
is compiled as.split
⫴
is compiled as.join
- you can omit
(
and)
for simple expressions with⌶
,⫴
and≂
. ≂
is converted to.toString
// replace all occurences of "-" with "+"
ロ '1-2-3-4-5' ⌶ '-' ⫴ '+'
// same with ( and )
s ∆ '-+'
ロ '1-2-3-4-5' ⌶ (s⁰) ⫴ (s¹)
x ∆ 123.456
ロ 'length of string representation of number', x, 'is', x≂↥
fs ∆ ≣ 'fs'
ロ 'Readme contains: ' + ⛁ ('README.md') ≂ ⌶ '\n' ↥ + ' lines'
booleans ⦿
and ⦾
⦿
is replaced withtrue
.⦾
is replaced withfalse
.⦿
is typed astr|TAB
.⦾
is typed asfa|TAB
.
a ∆ ⦿
⌥ (a) a = ⦾
b ∆ { initialized: ⦾ }
last item of a string or an array ꕉ
↟
ꕉ
is typed as.la|TAB
.↟
is typed as.lx|TAB
.ꕉ
is used to access the last item of an array or a string.ꕉ
is compiled to[x.length - 1]
, soxꕉ
becomesx[x.length - 1]
.x↟
is compiled to(x.length - 1)
.
A ∆ ['X','Y']
➮ appendAndReturnIndex { A ⬊ a ⦙ $ A↟ }
z ∆ appendAndReturnIndex('Z')
ロ 'inserted', Aᶻ, 'at:', z
A ∆ ['hey', 'there', '.', '.', 'how', 'are', 'are', 'you', '.']
➮ removeDoubles {
R ∆ []
i ⬌ a {
⌥ (aⁱ ≟ Rꕉ) ♻
R ⬊ (aⁱ)
}
$ R
}
ロ removeDoubles(A) ⫴ ' '
// hey there . how are you .
finding occurence in a string or array with ≀
≀≀
≀
is typed asio|TAB
.≀≀
is typed aslio|TAB
orio|TABio|TAB
.≀
is replaced with.indexOf
.≀≀
is replaced with.lastIndexOf
.(
and)
can be used or omited.
s ∆ 'hello world!'
ロ s ≀ 'world', s ≀ ('o'), s ≀≀ 'o'
// 6 4 7
array utilities ⋃
⨄
ꔬ
⧉
ꗚ
❄
, string and character utilities △
◬
⩪
⋃
is typed assl|TAB
.⨄
is typed aspl|TAB
.ꔬ
is typed asfi|TAB
.⧉
is typed asma|TAB
.ꗚ
is typed asaa|TAB
.❄
is typed asso|TAB
.⋃
is replaced with.slice
.⨄
is replaced with.splice
.ꔬ
is replaced with.filter
.⧉
is replaced with.map
.ꗚ
is replaced with.concat
.❄
is replaced with.sort
.◬
is typed ascc|TAB
.△
is typed asca|TAB
.⩪
is typed assu|TAB
.◬
is replaced with.charCodeAt
.△
is replaced with.charAt
.⩪
is replaced with.substr
.
➮ numbersOnly { $ a ⌶ '' ꔬ (➮ { $ a◬(0) <= 57 }) }
ロ numbersOnly('a1b2c4d8q11')
// same as above. but sorted
➮ numbersOnly { $ a ⌶ '' ꔬ (➮ { $ a◬(0) <= 57 }) }
ロ numbersOnly('a1b2c4d8q11')❄ (➮ { $a - b })
symbolic variables
- there are three types of symbolic variables.
- the goal is to provide more condense, formula-like notation.
α
γ
β
...ζ
are greek letters.- Javascript supports greek letters, no translation is needed.
- Typing in greek: alf=α bet=β gam=γ del=δ eps=ε zet=ζ eta=η tet=θ iot=ι kap=κ lam=λ muu=μ nuu=ν xii=ξ pii=π roo=ρ sig=σ tau=τ ups=υ fii=φ chi=χ psi=ψ ome=ω.
∇ α = 10, δ = 5
α += δ
ロ 'alfa plus delta is:', α
ⓐ
ⓑ
ⓒ
...ⓩ
are encircled letters.- encircled letters are typed
ooa|TAB
,oob|TAB
,ooz|TAB
etc. - they are useful if you are out of latin letters.
- internally they are represented as
_oo_0
to_oo_26
.
∇ ⓐ = 0, ⓩ = 26
ロ ⓐ, ⓩ
❶
❷
①
②
aretags
orlabels
, they have special syntax.❶
is a label definition,❶ 5
equals to;var var0 = 5
.①
is a label reference, or usage,ロ ①
will convert toconsole.log(var0)
.
❶ 'hello' ❷ 'world'
ロ ①, ②
is defined
⟑
is typed asid|TAB
.⟑ <expr>
is replaced with(typeof <expr> != undefined)
.
s ∆ {x:123}
⌥ (⟑s.x) ロ 's.x is not undefined'
multi line strings
Elfu supports multi line strings enclosed with opening '''\n
and closing '''
.
console.log('''
Hello, multi line
strings world
''')
str ∆ '''
Hello, multi line
strings world'''
(GitHub markdown does highlight with red background for some reason.)
tuples
ꔪ
is typed astu|TAB
.a,b ꔪ <expr>
is replaced withtmp=<expr>;a=tmp[0],b=tmp[1]
.
➮ repl { $a.replace(b, c) }
➮ half {
$[a, a/2]
}
A ∆ {whole:∅, part:∅}
☛ A { whole, part ꔪ half(200) }
∇ a,b,c ꔪ [33,44,55]
ロ A,a,b,c
//{ whole: 200, part: 100 } 33 44 55
TODO: add support for simple name matching with ꔪ, like this:
obj ∆ { a:1, b:2 }
b,a ꔪ obj
//b = obj['b'], a = obj['a']
ロ a, b
// 1, 2
object keys as an array with '⚷'
obj ∆ {a:1, b:2, c:3}
ロ ⚷ obj // ['a', 'b', 'c']
namespace utility with ➮|
and ➮]
If your elfu source file has ➮]
anywhere in it, then all top level declared functions of this file will be automatically exported to module.exports
. If you use ➮|
, the functions will be exported as global variables.
######main.yy
➮|
≣'lib'
➮ load {
ロ 'loaded...'
}
scan()
######lib.yy
➮ scan {
load()
ロ 'processing...'
}
➮|
new syntax for branching with ❰
❱
◇
⁋
]232
❰
is typed asq|TAB
or[|TAB
.❱
is typed asw|TAB
or]|TAB
.◇
is typed ase|TAB
.- replace '❱' with ')', or '){' when the next token is on the same line.
- replace '◇' with: a. '} else if(' if followed by the next non-space character '❰'; b. '} else {' if the next token is on the same line; c. 'else'. -- not possible, ◇ cannot be used with the oneliners.
- replace '⁋' with '}'.
- replace '❰' with 'if ('.
There is no if
keyword or it's analog if you use this notation, the test condition is enclosed in ❰
and ❱
. The conditional statement is a one liner if it goes on the same line, otherwise end it with the ⁋
. Same is true with else
which is ◇
.
This syntax does not replace original JavaScript or original Elfu if
else
and ⌥
⎇
, but coexist.
/*
Nested conditional expressions.
You cannot use ◇ with one-liners. But ◇ itself could have a oneliner expression.
*/
❰1❱
❰2❱
b = 3
◇
b = 4
⁋
◇
❰5❱
b = 6
◇
b = 7
⁋
⁋
❰a ≟ 5❱ a = c
◇ b = 1
❰a == 5❱ b = 4
❰a == 5❱
b = 4
◇
b = 6
⁋
❰a == 5❱ b = 4 ◇ b = 6
❰a == 5❱ b = 4 ◇ ❰a == 5❱ b = 6
❰a == 5❱ b = 4 ◇ ❰a == 5❱
b = 6
⁋
You can combine syntaxes like this:
❰1❱
{ 2 }
⎇ { 3 }
...or like this:
❰1❱
{ 2 }
else
{ 3 }
#####String array literals
ロ [@ dormouse hare hatter]
// [ 'dormouse', 'hare', 'hatter']
extras
`__arrarr` - get the function arguments as an array.
`__elfuver` - return a string specifying current elfu version. This is read from `package.json`.
#Usage
- install with npm,
[sudo] npm i -g elfu
. yy <program>
run the.yy
program.yyj program.yy
convertprogram.yy
to Javascript. Data is written to standart outout.jyy program.js
convert Javascript to Elfu.require('elfu'); require('example.yy')
you can require modules written in Elfu.
#Dotcall syntax
- Elfu supports dotcall syntax.
- dotcall is callback hell remedy.
- read dotcall README for details.
#Feedback
- post your ideas and other feedback in issues on github page.
- Github page is https://github.com/exebook/elfu.
- author's email:
exebook gmail com
- author's VK page: http://vk.com/chucknorrisgriboedov