Code Monkey home page Code Monkey logo

luna's Introduction

Luna programming language

Luna is an expressive, minimalistic, elegant programming language implemented in C. With cooperative thread concurrency at its core, async I/O, and influences derived from languages such as Lua, io, Rust, Ruby, and C. Luna favours unification and minimalism over minor obscure conveniences, providing the true convenience of a simple effective language. This includes omitting features which facilitate magic such as getters/setters, method_missing-style delegation etc. This project is very much a work in progress, as I explore the wonderful world of VMs! feel free to join.

Goals

  • fast!
  • small (~2000 SLOC)
  • simple, elegant, explicit
  • small learning curve
  • statically typed with inference
  • high concurrency out of the box via coroutines
  • small embeddable / hackable core
  • ...

Build

To build Luna, simply run:

$ make

Check out the help:

$ ./luna --help

Status

Generalized status:

  • ✔ lexer
  • ✔ parser
  • ✔ test suite
  • ✔ ast
  • ✔ linenoise integration for REPL
  • ◦ register machine
  • ◦ C public/internal apis
  • ◦ garbage collection
  • ◦ continuations
  • ◦ optimizations (TCO etc)
  • ◦ portability
  • ◦ closures
  • ◦ VIM / TM / syntaxes
  • ◦ website
  • ◦ context threading

Note: Luna doesn't run any code yet, it only parses the code and builds an AST. There are still some decisions to be made about certain aspects of the language. If you would like to join and finish designing Luna with the community, check out the issue tracker and share your thoughts.

Typing

Luna is statically typed, however mostly optional thanks to type inference. Some declarations such as function parameters must specify a type:

def greet(name:string)
  return "Hello " + name
end

Types that can be properly inferred may be, for example function return types as seen above. When fully-qualified the same function would look like this:

def greet(name:string): string
  return "Hello " + name
end

Function overloading

Luna plans to provide multiple dispatch support. This will drastically cut down on verbosity and fragmentation. For example suppose you have a vec_sum(v) function, in Luna you would simply create a sum(v) function:

def sum(v:vec): int
  ...
end

Thanks to the typing system Luna can choose the correct function to invoke for the given parameters. This technique addresses another fundamental problem of many languages, fragmentation and delocalization. For example it is often tempting to extend native prototypes or classes provided by the host language, such as Array#sum().

Because no such construct exists in Luna you're free to "extend" these types elsewhere simply by defining functions that act on those types, without polluting "global" classes or objects, removing a layer of indirection, as it's often not clear where these additions came from, and they regularly conflict.

Method syntactic sugar

As previously mention Luna has no concept of classes, methods, or prototypes. To increase readability you may invoke functions as if they were methods. For example the following would be equivalent:

cat('urls.txt').grep('https://').print()
print(grep(cat('urls.txt'), 'https://'))

Fork / join

More often than not you want to perform several tasks in parallel, and "join" their results. For this luna provides the & postfix operator, which is syntax sugar for wrapping the expression in a fork() function call:

a = get('http://google.com').grep('<title>') &
b = get('http://likeaboss.com').grep('<title>') &
c = get('http://cuteoverload.com').grep('<title>') &
res = join(a, b, c)

This wraps each statement in a coroutine which may run independently.

Operator precedence

Operator precedence from highest to lowest:

operator                |  associativity
------------------------|---------------
[ ] ( ) .               |  left
++ --                   |  right
! ~ + -                 |  right
* / %                   |  left
+ -                     |  left
<< >>                   |  left
< <= > >=               |  left
== !=                   |  left
&                       |  left
^                       |  left
|                       |  left
&&                      |  left
||                      |  left
?:                      |  right
= += -= /= *= ||= &&=   |  right
not                     |  right
,                       |  left

luna(1)


  Usage: luna [options] [file]

  Options:

    -A, --ast       output ast to stdout
    -T, --tokens    output tokens to stdout
    -h, --help      output help information
    -V, --version   output luna version

  Examples:

    $ luna < some.luna
    $ luna some.luna
    $ luna some
    $ luna

Community

  • irc: #luna-lang on irc.freenode.net

License

MIT

luna's People

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  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

luna's Issues

member as sugar

def first(v:vec, n:int) {
  ret vec.slice(0, n)
}

as sugar for:

def first(v:vec, n:int) {
  ret slice(vec, 0, n)
}

types will still use " " for fields, or change the above to and use. for fields

oop?

what's your position regarding OOP in luna?

i currently am very much in love with Go's solution which basically is methods dispatching on structs

function calls with multiple args and a final callback

I was looking at your example :

person pets select: pet
  pet species == 'ferret' && pet age > 4

I wondered what it would look like if there was more arguments. I would seem that you'd need the brackets in this case?

person.pets.eat("quickly", :
  print("im done"))

Is that correct ?

high precedence and / or

maybe add these.

or:

if foo or bar == baz

equivalent to:

if foo == baz || bar == baz

and:

if foo and bar == baz

equivalent to:

if foo == baz && bar == baz

prevent single-line blocks

no if foo bar() end crap, looks disgusting, same with functions:

def add(a:int, b:int) ret a + b end

force the newline

module support

even in core I want these to be explicit. Need to think deeper about scenarios however something like:

import sum, length from "vector"
import length from "set"

[1,2,3].length()
[1,2,3].sum()

in general I don't like this because it makes it extremely non-obvious where things came from, however it can still be handy for "throw-away" scripts and executables etc:

import "vector"
import "set"

[1,2,3].length()
[1,2,3].sum()

from local files etc:

import sum from "./my/awesome/vector"

[1,2,3].sum()

looks nicer with idents after, however doesn't read nice:

import "vector": length, sum
import "set": length

Similar to Go they'll be auto-exported, however instead of making you use capitalization, we'll just make you not prefix with _, if it's private use _ (or just expose a bunch of junk, whichever you want). This would be public:

def length(v:vec) {

}

private:

def _length(v:vec) {

}

for implementation sake we'll probably just treat them the same as exports for now, not a big deal really who cares. The only thing it may be useful for explicitly omitting these is some sort of tool that outputs the functions a module exports.

another nice thing with node's style is you can name functions whatever you like, and avoid poor choices that people might make

perhaps "use", short and sweet:

use "vector"
use "set"

[1,2,3].length()
[1,2,3].sum()

explicit self

pros and cons here but just as a note for later, it might be worth going the approach of an explicit "self" arg:

User.name =: self
  self first + ' ' + self last

user name()
// => "tj holowaychuk"

User name({ first: 'tj', last: 'holowaychuk' })
// => "tj holowaychuk"

this has several pros:

  • no need for .apply() or .call() like javascript (just need a spread operator User name(obj, ...args))
  • less magical
  • available to closures

significant whitespace

can look nice, but I've seen so much shit now, that I don't think this is
worth it. Even in Stylus we have this problem and it's mostly declarative. I need
to think on this some more since I have some other more functional plans but
over-all it's looking like significant whitespace sucks

method?!

what about allowing ? And ! In function names like ruby does? I find that useful for array methods like pop

Abstraction

once a reasonable amount of implementation is complete, it might be worth abstracting so that the language itself is not bound to the concurrency model, nor many of the dependencies, making it easier to embed, though for the meantime adoption and interest will be greater to have things bundled.

multiple assignment

I'm a fan of a, b = [1, 2] but not really in love with ruby's a = 1,2,3, looks great for small things but gets kinda lost without the brackets but for swapping it's nice a, b = b, a

def or fun ?

Honestly I prefer def in OO, I see better fun in luna especially for anonymous stuff (if you'll ever want to support it):

a=fun(a:int, b:string){}

or

fun bar() do
   a = fun(){ long_job }
   promise = async(a)
end

but here I see the js problem where:

a = func(){} or func a(){} ?

luna-create

as separate executable for project boilerplate

roadmap

ok, i figured out i definitely don't have the time ATM to work on my project.. but i might as well randomly contribute to this one because why not

tl;dr we should have a roadmap, some place where to discuss features, something more specific than what's currently in the readme.. so i can pick up an item from there, push da code and PR it :D

add pipes back #maybe #low-priority

I removed them because the following looks perfectly fine:

cat('something').grep('whatever').print()

however when arguments are not present pipes are nicer:

tree.archy().indent().highlight('blue')
tree | archy | indent | highlight('blue')

get('http://google.com').grep('tobi').print()
get('http://google.com') | grep('tobi') | print

tough call, supporting both is a little lame, though they do have slightly different use-cases, and with pipes we can assume calls vs slots

this isn't an issue just a note.

you should really investigate pypy and rpython they implemented php with it and it's a lot faster than hiphop for php, they also implemented python with rpython wich is a lot faster than cpython.

pypy

you might want to look at it, that way more programmers can contribute to luna.

cheers :)

generics support

need to think about this some more, we get some major wins from typed functions so the implications of allowing untyped and variadic may be a little weird

remove slot space syntax

don't think I like it anymore, too much visual ambiguity introduced by whitespace. use . for fields as well (user.name > user name).

Anonymous functions & Design

things like:

a = def(int:a, int:b) { ret some }
a(1, 2)

can like in julia everything be considered as a function itself ? In that case def(a:int) can have sense.

ditch braces for blocks

def sub(a:vec_t, b:vec_t) {
  ret vec_t:{
    x: a x - b x
    y: a y - b y
  }
}

vs

def sub(a:vec_t, b:vec_t)
  ret vec_t:{
    x: a x - b x
    y: a y - b y
  }
end

I like braces better in general however if {} are used for anything else, hashes, structs etc it's more noise

use case: pubsub

Here's a PubSub implementation in luna.

  • How do you consider the param-feature?
  • Is Array#each(str) possible as a shortcut?
  • How will the dictionary-syntax be?
  • Are there other mistakes?
PubSub = Object clone()
PubSub channels = []

PubSub param: channel
  channels[channel] ?= []

PubSub subscribe := channel fn
  channels[channel] push(fn)

PubSub publish := channel msg
  channels[channel] each(msg)

PubSub unsubscribe := channel fn
  channels[channel] remove(fn)

exports = PubSub

or more experimental:

PubSub = Object clone()
PubSub channels = []

PubSub param: channel
  channels[channel] ?= []
  channel = channels[channel]

PubSub subscribe := {channel} fn
  channel push(fn)

PubSub publish := {channel} msg
  channel each(msg)

PubSub unsubscribe := {channel} fn
  channel remove(fn)

exports = PubSub

Seed-up this project

@visionmedia this project seems your best work, I'm not a c expert but I wanna see more!!!

I wanna join this maybe I could help writing the std-lib ? Are we ready for that?

Let me know!

expose core's parser

might as well! saves a lot re-implementation work for anyone looking to parse docs etc

irc chan?

i see nowhere infos about an irc chan or a Ggroup so.. is there one?

i really like some ideas from luna btw, keep up the good job :D

luna-docs

as separate executable from markdown files

composite structures

similar to lua: [1,2,3], [foo:bar, bar: baz]. we could maybe then use {} as a Hash, these hashes could then of course be typed and expose helpful methods like hash.keys(), hash.values(), hash.each: key, val etc

interpolation

not a huge fan of ruby-style foo #{bar} etc, if you have complex expressions you might as well use concatenation, and for smaller simple expressions it's noisy. I'd rather do some simpler substitution or perhaps python style %

decide on typing

really prefer lowercase c-style vec_t, user_t etc, but it can be a bit ambiguous without _t, also core types would be very common so shorter rust-style may be nice:

def greet(name:String) {
  ret "hello " + name
}

vs

def greet(name:string) {
  ret "hello " + name
}

vs

def greet(name:str) {
  ret "hello " + name
}

u8, i8, u16 etc from rust are sexy too

new lambda syntax

currently:

users map(:user | user pet) select(:pet | pet age > 10)

is equivalent to the following, but allows for implicit returns

user
  map: user
    ret user pet
  select: pet
    ret pet age > 10

or equivalent to the following javascript:

users.map(function(user){
  return user.pet
}).select(function(pet){
  return pet.age > 10
})

I dont like the current syntax, but I dont want lookahead like dart's (foo, bar) { } syntax or (foo, bar) ->, it makes you scan further ahead than you should have to in order to disambiguate. We could do some special-casing but I dont want to get too deep into that either.

Alternatively or as a compliment it would be nice to quote and provide something like:

users map(.pet) select(.age > 10)

Tests failing

I cloned the project and having trouble running the tests.

After I do rake test, the linker complains that the following symbols are missing _luna_object_get, _luna_object_set, and _luna_object_size. I noticed these were macros but were deleted in this commit: e579e51

I guess the tests were not updated.

Anyways, I'm curious about luna and would love to get my hands dirty in VM development. Cheers.

differentiate single and double quoted strings for regexps

need to think on this. generally i prefer them to be equal, like in javascript, however, I would also like to avoid a regular expression literal, so we will need a string literal that does not require double escaping. tough call, a regexp literal is not much worse than this change

function composition construct

for example the following js:

[1,2,3].map(function(n){ return n * 2 }).reduce(function(sum, n){ return sum + n })

would be equivalent to:

[1,2,3] | map * 2 | reduce +

This would be great because we would have no Array prototype, no prototypes anywhere ideally. map, reduce, first, last and friends would all be separate functions accepting an array. This would have great composition benefits and avoid obscure global manipulations that you see in ruby, js etc. Need to think about how to get something like this in.

Some other implications of this would include potential issues with these identifiers becoming effectively reserved. It would be lame to have list | enum.unique | enum.map * 2 ..., however they would be very easy to bundle up into modules that you explicitly import, however still dumping into that scope.

Perhaps treat . as the composition operator and ` to quote, making it look a lot like regular class or prototype style invocation.

oldest_pet = users.map(`pets).sort(`age).last()
[2,4,6,2,3,8].unique().select(`even).sort().last()

perhaps | could compliment . in that it would imply invocation and quoting:

[2,4,6,2,3,8] | unique | select even | sort | last

if this were the case you would only really use . when intermediary member access is necessary. Luna would effectively treat this as sugar for:

last(sort(select(unique([2,4,6,2,3,8]), even)))

libuv

not really an issue ... more of a thought. are you going to use it?

no whitespace before (

right now cat ('foo') is valid, I dont want this, no jquery syntax cat ( 'foo' ) crap

rust style return type notation

currently:

def greet(str:string): string {
  return "hello " + str
}

could be:

def greet(str:string) string {
  return "hello " + str
}

or like rust:

def greet(str:string) -> string {
  return "hello " + str
}

the first two are easier to type, however the extra whitespace introduced by -> makes things a little easier to read IMO

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.