liphe / delisp Goto Github PK
View Code? Open in Web Editor NEWA statically typed Lisp dialect with algebraic effect system compiling to Javascript
Home Page: https://delisp.org
License: MIT License
A statically typed Lisp dialect with algebraic effect system compiling to Javascript
Home Page: https://delisp.org
License: MIT License
To remove ambiguities, we should remove type aliases from the normalized type.
We could apply some heuristics to recover them for error reporting.
This logic is duplicated with the compiler.
It would be better if we could keep the runtime representation of Delisp functions in a single place.
Should it be a separate package @delisp/require
or just a separate entry-point into @delisp/core?
It's nice to have multiple packages but most likely they should always require exactly the same version across all packages.
This library makes hooking into require easier:
https://www.npmjs.com/package/pirates
It is too hard to add new functions / values because the different pieces of information are too spread through the codebase.
Support for row types have been implemented by c81ad6b, 7448c2c and 07827cd.
However, we are still missing:
tail(r ) ∈/ dom(θ)
to the uni-row rule.{ | r}
of the syntax appears the last in the map.The self-type of unknown variables is a fresh type varaible, which is not very useful.
However, the resultingType have been exposed to the constraints of the code so it gives nicer information.
For instance, for
(lambda (x) (f 10))
where f
is a free variable, the selfType
is t1
, but the resultingType is (-> ctx number e b)
The resultingType can be used for autocompletion for instance.
The pretty printer rewrites an at-expression like @doc{Hello World}
into (doc "Hello World")
, but the original notation should be maintained.
λ (define id (lambda (x) x))
{}
Instead of
λ (lambda (x) x)
{ value: [Function], type: '(-> α α)' }
Then using id
leads to:
λ (id 1)
{ value: 1, type: 'α' }
It could make the output more readable than those $$star$foo$star$$
Use an id
to compare types instead of name
. We would still have a name for types provided by the user, but id
would be used for comparison.
That way we can prevent _
and __t1
from being the same type variable.
It constraints the nodes version too much and the warning is annoying.
The arrow syntax for function types gets complicated with too many positional arguments.
It would be nice to support this more readable syntax:
(fn :from [...] :to ... :with ... :context ...)
and make the arrow function an alias for when there are no effects or context.
Right now the identifier estree-util will not escape its arguments. This is sometimes what we want, but not always. We should refactor it to avoid bugs mixing JS names and Delisp names.
It is too easy to make mistakes between when or not a Delisp name should be converted to JS, and there are also differences between when the output is used as an identifier or as an identifier names.
Improve the situation!
The pretty printer rewrites partial type annotations like _
into __t1
.
A test for this is available (but skipped): https://github.com/ams-hackers/delisp/blob/c0b03065e7f1e2192024eb640f304acca82a905f/packages/delisp-core/__tests__/printer.ts#L56-L60
NB: Named type holes like _a
are printed properly.
Right now is too easy for the compiler to think that a variable is a primitive, but for the type checker to think it is a local variable instead.
Example:
(let ((:x 5))
:x)
As of now (1ffcc66), the compiler will think the :x
is an inline primitive. But the type checker will treat it as local variable.
A possible way to do this is to add a transformation phase to the AST before compiling/type checking where we do name resolution. Linking references to their definitions.
(Blocked by #58)
A good starting point:
https://code.visualstudio.com/api/language-extensions/language-server-extension-guide
Add a --cursor-offset
option and integrate it into the emacs delisp-mode.
We can accept both some ascii combination as a single unicode character for them, and normalize them to unicode with the pretty printer.
Add a module id to each symbol: module:name
. Modules can be implemented as extensions to the compiler. The basic method could be
lookupSymbol (name: string): JS.Expression
But more specific customizations like generating specific code for funcalls and others is possible.
Ability to compile multiple files.
Each file should have dependencies explicit so they can be processed in parallel, and only files that need changes. Store the output in a cache directory.
Currently, we do not implement delete
on records in Delisp as it would imply keeping scoped labels at runtime.
I found an interesting problem today in JS/Typescript that scoped labels would help with.
I'll write the examples in JS.
Consider you have a react-like web component which take some "props" as inputs.
For example,
function User (props) {
// props.name
// props.userId
}
is a component like this one would take as props name
and userId
.
Now, consider "high-order components" (HOC). That is, functions that transform a component into another one. A common use case of HOC is wrapping a component to take some extra properties. In this case, you may want to delete the custom labels from the record before you pass them through to the wrapped component. For instance:
function abTest (Component){
return (props) => {
const {currentVariation, ...innerProps} = props
// do someting with currentVariation
return <Component {...innerProps} />
}
}
This HOC will take a component, and wraps it so it takes an additional currentVariation
prop. This prop gets removed and the rest if forwarded to the inner component.
There is a problem though. What happens if your inner component takes a currentVariation
component itself? Then the HOC component will remove it and the inner component will fail.
Scoped labels would allow the caller to pass currentVariation
label both for the HOC and for the inner component if needed. Making abTest
work for every component.
If this is probably something you want to warn against probably, it is still nice to be able to create abstractions that work for every component!
I may be missing something, but common practice like in this blog post
https://medium.com/@jrwebdev/react-higher-order-component-patterns-in-typescript-42278f7590fb
seems to suffer from this issue.
Support for variables in type aliases
(type (Lens a b)
{:get (-> a b)
:set (-> b a a)})
To reproduce it:
npx delisp compile --unknown-arg
Something simple like a todo app, either just backend code, or state-management related.
The (vector 1 2 3)
syntax was removed in cb49761 because it was equivalent (and equally powerful) as the [1 2 3]
syntax.
If we have variable arity functions, it could make sense to implement vector
again (but as a function, not a special syntax like before).
It seems it was introduced by 6582da8. yargs
is quite buggy so I think it would be better to switch and use something else.
(Blocked by #58)
(f)
=> (f )
And use the already entered information to help to narrow down the options in the other ones.
As tslint will become deprecated and efforts are to move to eslint-typescript instead.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.