Lever is a loosely specified general purpose programming language, and a runtime implementation of that language. Many tradeoffs have been made to obtain high plasticity worthy of pride. To make use of this every feature is tried in practice to level out prickly details in the language before a major release.
Very handsome payouts of our approach have already appeared. For example. We have tools in place to minimize the labour involved in using external C libraries from our language, to the point where none other language implementation does it. All of this has happened with handful of people, although many important ideas that make up Lever originate from external sources such as academic papers and open source communities. Lever runtime is entirely open source in order to give back to those communities as thanks for what they have brought.
In the design there's a focus to support interactive programming of multimedia programs.
Using C libraries in your Lever code is so clean that it is optional to write wrappers for them.
sdl = api.library("libSDL2") sdl.Init(sdl.INIT_EVERYTHING) sdl.Quit()
Lever has semi-automatic utilities to parse C files, clean them and translate them into .json -formatted headers that provide you with everything to use the libraries you need.
It also has headers for OpenGL4, although they have been generated directly from Khronos specifications.
blen = ffi.automem(ffi.uint) gl.getObjectParameterivARB(obj, gl.OBJECT_INFO_LOG_LENGTH_ARB, blen) gl.getShaderiv(obj, gl.INFO_LOG_LENGTH, blen) log = ffi.automem(ffi.ubyte, blen.to) gl.getInfoLogARB(obj, blen.to, null, log) print(log.str)
Combine this with rest of the features, and you get so incredibly simple programs that do incredibly complex things. For example, check this implementation of Logo out.
There's no global object in lever that holds all the loaded modules. Instead the loaded modules are kept in module scopes. It is first-class loaded-modules handling! You can stack module scopes over others. There's 15 lines to plugin system or live coding from here:
plugins = ModuleScope(dir ++ "path/to/plugins", %"import".scope) plugins_importer = Import(plugins.local, plugins)
And you can get rid of your scope when you like, to get all your modules to reload.
Async code looks so ugly, were you using callbacks, async/await or promises to do it. Except in Lever. In lever it looks prettier than your sync code.
If you call it with a function, it calls the function after a while.
test = (): print("5 second hello!") sleep(5, test) sleep(1) print("1 second hello")
But you can also call it with...
test = (parent): parent.switch() # switches back print("4 second hello!") dat = greenlet(test) dat.switch(getcurrent()) # goes to run test. # now we have a greenlet that hasn't returned. sleep(4, dat) # that inserted it into an event loop, cool?
That's right, greenlets! This is how any event emitter works in lever. You don't need to worry whether it should be callbacks or greenlets. You can either wait for event or pass a callback and things keep working.
What if you stuck your app to wait for an event, but the event source is removed and the waiting code should release file handle? No problem. The event source schedules 'Discard' -exception thrown to the greenlet, that makes your waiting code to gracefully exit.
There is more in-depth documentation in the repository, including internal documentation for the runtime.
Author knows by initial tests, that Lever is slightly slower than Python. There's performance.text detailing out how it is intended to achieve better performance out of Lever.
Lever is licensed under the MIT license.
Website maintained by Lever community.