Code Monkey home page Code Monkey logo

lambda's Introduction

Lambda

An effort to create the perfect programming language. Currently in alpha stage.

Technical Description

Lambda is an eagerly evaluated lambda calculus with static Hindley-Milner type system and a few additions.

The most relevant additions are:

  • a fixed point combinator suitable for eager languages (a.k.a. Z combinator);
  • if-then-else;
  • infix operators (e.g. x + y * z);
  • exceptions;
  • an expressive value domain that includes closures, booleans, strings, several numeric sets (naturals, integers, reals, complex), lists, and objects;
  • all JavaScript APIs exposed by the underlying environment, whether it's Node.js, the browser, or anything else.

Recall that Hindley-Milner also requires a let statement.

Example

The following Fibonacci implementation gives an idea of several implementation choices:

let fibonacci = fix fn f, n ->
  if n < 2
  then 1
  else f (n - 1) + f (n - 2) in

{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}.map fibonacci

The above outputs {1, 1, 2, 3, 5, 8, 13, 21, 34, 55}.

For more information see the Wiki.

Prerequisites

Node.js.

Installing

$ npm i -g lambda

Getting Started

$ lambda
> 'Hello, world!'
'Hello, world!'
>

More Information

See the Wiki.

lambda's People

Contributors

71104 avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar

lambda's Issues

Fix operators

The current implementation of operators doesn't allow to type expressions with operators.

Implement the correct typing and possibly overload resolution so as to make them more efficient and not test RTTI at runtime.

Syntax ambiguity

In this case:

{ x, y }

x, is started being parsed as a lambda.

Undesirable workaround:

{ (x), y }

Memory management

This:

console.dir let x.x = 5 in x

Prints {}, while it should definitely print the same as this:

let x.x = 5 in console.dir x

Which is { x: 5 }.

Use prototype inheritance instead of cloning entire contexts

Example implementation of Context.add:

Context.prototype.add = function (name, value) {
    function Hash() {}
    Hash.prototype = this.hash;
    var hash = new Hash();
    hash[Context.PREFIX + name] = value;
    var context = new Context();
    context.hash = hash;
    return context;
};

But this requires that existence checks are not based on hasOwnProperty any more. This won't cause collision problems because now all the keys have the prefix.

Array literals often confused with subscripts

When writing this intuitive expression:

console.log [1, 2, 3]

A syntax error is produced because the parser interprets it as a subscript node with a weird index. Even worse, this is successfully mistaken for a subscript node:

console.log [1]

For now it is necessary to disambiguate the syntax using parens:

console.log ([1, 2, 3])

But a better solution would probably use curly brackets instead of square brackets for array literals, e.g.:

console.log { 1, 2, 3 }

JavaScript errors aren't caught

Try this:

try x.x catch 5  # x is not defined

Only user errors (those thrown by throw) are currently caught by the try statements, but the user should be able to catch any exception.

Coerce complex numbers to strings

The binary plus operator (+) must coerce complex numbers to string when adding to strings.

Example:

+ 3i 'hello'

must type to string and produce the string value 0+3ihello.

Try statements catch internal errors

Try statements must only catch user errors thrown by a Lambda throw statement or errors thrown by native code.

Programming errors of the interpreter often result in JavaScript exceptions that must not be caught by try/catch statements.

Lexer improvement

At the current state of the project, the asterisk lexical symbol can be merged to symbol.

Lazy terms

Possible implementation as no-arg functions.

Example:

let greet = () -> console.log "hello" in greet

The body of the let statement prints hello to the console.

Unmarshalling floating point numbers

JavaScript numbers are always unmarshalled to FloatValues, even though an IntegerValue is sometimes expected.

This bug is irrelevant for now because the implementations of IntegerValue and FloatValue are structurally identical (although the problem may still be detected through the use of is / instanceof).

Passing objects

Objects must be managed by contexts and sub-contexts during evaluation because we need a stack for each field, otherwise we would not be able to execute the following correctly:

let x.x = 'a' in + (let x.x = 'b' in x.x) x.x # must return 'ab', not 'bb'

This means we cannot pass native JavaScript values around. But we still have to pass native JavaScript values when applying to an unknown and wrap their result back to managed values. Major complexity arises when the passed value is a function accepting other parameters.

An analogous solution is also needed for compilation.

Parser bug

The current parser won't work with this:

x x -> x

`then` keyword and promises

then is a keyword in Lambda, which prevents support for promises and thenables.

Maybe we could introduce a loose policy on keyword usage and allow them as field names.

Parse hex and octal literals

Example hex literal: 0x0a1B2c3D

Example octal literal: 0123

Invalid octal literal: 089

They will all produce integer values.

Syntax error

The following valid code produces a syntax error:

console.dir []

`module` and `require` not available

They should be available when running from the REPL, but they aren't (not sure why).

This is secondary if the main use of the language is to transpile to JavaScript.

TypeError when a user exception is thrown

Run on bash:

$ echo "throw 0" | lambda

Output:

net.js:633
    throw new TypeError('invalid data');
          ^
TypeError: invalid data
    at WriteStream.Socket.write (net.js:633:11)
    at Socket.<anonymous> (/usr/lib/node_modules/lambda/bin/Main.js:32:19)
    at Socket.emit (events.js:129:20)
    at _stream_readable.js:908:16
    at process._tickCallback (node.js:355:11)

The expected output is a string representation of the thrown exception.

Contexts don't allow `hasOwnProperty` and possibly other predefined names

The expression hasOwnProperty produces a closure (the hasOwnProperty method of the context's hash, unmarshalled), but this is wrong.

Moreover, this crashes the interpreter:

let hasOwnProperty = 0 in hasOwnProperty

Because the interpreter becomes unable to use the hasOwnProperty method of the context's hash since it has been redefined.

This problem only occurs in interpreted code, not compiled code, and may extend to other names if Object's prototype is extended.

Unmarshal of variadic functions?

Native functions are currently unmarshalled based on their length.

This is weak because the native code may still use the arguments array to receive extra arguments.

Also, there is no solution for calling variadic functions except reflection, e.g. f.apply null {x1, x2, ...}.

The latter is a syntax limitation of the language and I don't think it's going to be fixed.

Implement `typeof`

Even though Lambda will be strictly typed, typeof might still be useful, e.g. to analyze values returned by native APIs.

Implement `reverse` and `sort` in array prototype

Examples:

{1, 2, 3, 4, 5}.reverse
# { 5, 4, 3, 2, 1 }

{3, 2, 5, 1, 4}.sort <=
# { 1, 2, 3, 4, 5 }

Notes:

  • reverse is evaluated lazily.
  • sort accepts one argument, a partial order relationship. This differs from JavaScript.

Some native objects are unavailable again

For some braindead reason, unmarshalling native Node objects such as process causes exceptions in getters.

Not worth fixing, as the problem only happens in the interpreter and the main goal of the project is the compiler.

Compilation of literal nodes may fail with cyclic objects

Current implementation:

LiteralNode.prototype.compileExpression = function () {
    return JSON.stringify(this.value.marshal());
};

LiteralNode.prototype.compileStatement = function () {
    return 'return ' + JSON.stringify(this.value.marshal()) + ';';
};

The JSON.stringify cannot encode cyclic objects.

global command `lambda` doesn't work

The following errors are shown after installing the package lambda globally and running it using the lambda command:

/usr/bin/lambda: line 1: syntax error near unexpected token `('
/usr/bin/lambda: line 1: `var Lambda = require('./lambda.js');'

Implement native objects

Extend the domain with a new type of value, the "native object", which is basically a wrapper for an object that comes from native JavaScript rather than being generated by Lambda code.

This type of value makes sense only in the interpreter, while the compiler will generate code that just accesses objects.

There are two important use cases for this feature:

  1. avoiding to unmarshal and re-marshal the this parameter of native methods, and
  2. avoiding marshaling operations on native objects altogether, which fixes #27.
    #27 was already fixed by using a dictionary that prevents visiting objects more than once when unmarshaling, but the code is complicated and this new feature will let us get rid of the dictionary.

Allow expandos?

What are the effects of the following?

let console.expando = "lol" in console.log console.expando

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.