Giter VIP home page Giter VIP logo

radicle-alpha's Introduction

🚨 THIS PROJECT IS NOT ACTIVELY MAINTAINED 🚨

We are still developing Radicle, the main repositories are:

Join us on discourse for updates, and if you want to get involved!


Radicle

A peer-to-peer stack for code collaboration.

  • peer-to-peer : The Radicle stack builds on IPFS, and works without a centralized server. No hassle with setting up your own hosting, and no need to trust companies with your data.
  • terminal-first : A Radicle project contains a git repository, plus the associated issues and proposals. Access all the issues and proposals associated with your codebase right from your terminal.
  • programmable : Ever wanted to tweak your code collaboration service? With Radicle each unit of functionality –a machine– is its own litte P2P program, written in the Radicle language. You can change them to suit your needs, or create entirely new ones.

Radicle has a webpage which contains a lot more information on Radicle.

Installation

To build Radicle from source you will need stack.

And make sure the location at which stack installs executables is in your PATH: export PATH=$HOME/.local/bin:$PATH.

stack build
stack install :rad :radicle

Note: stack will need about 4GB of memory to compile successfully.

To use Radicle you will also need to install ipfs and git-remote-ipfs. Running Radicle requires you to keep both the Radicle daemon and Radicle IPFS daemon running.

rad daemon-ipfs
rad daemon-radicle

Debian/Ubuntu

We provide .deb packages for Debian-based systems.

wget https://storage.googleapis.com/static.radicle.xyz/releases/radicle_latest_amd64.deb
sudo apt install ./radicle_latest_amd64.deb

To use Radicle you need to start the Radicle daemon

systemctl --user start radicle-daemon
systemctl --user status radicle-daemon

Issues

We are currently using Radicle itself to manage issues (but you can still submit issues on Github). You can create and see issues with rad issues list in the project repo. To checkout the project, run:

rad project checkout 12D3KooWPS3UXcvSZSXfi7P4J9Ut8MMVNvN63HHiCSP8rxj3RmtC

If you cloned the project from Github, you can instead, from the repo, run:

git config radicle.project-id 12D3KooWPS3UXcvSZSXfi7P4J9Ut8MMVNvN63HHiCSP8rxj3RmtC

You can also reach us on the radicle IRC channel on #freenode, or via the mailing list.

Development

The script ./scripts/ci-tests.sh runs all tests that are run on CI. The script requires docker and docker-compose to be installed for end-to-end tests.

The documentation is build with make -C docs html. Reference documentation for Radicle code must be regenerated with stack run radicle-doc-ref and checked into version control.

End-to-end Tests

The end-to-end test suite is run with

RAD_IPFS_API_URL=http://localhost:19301 \
  RAD_BIN="$(stack path --docker --local-install-root)/bin" stack test :e2e

It requires you to first start up an IPFS test network and the Radicle daemon.

docker-compose -f test/docker-compose.yaml up -d ipfs-test-network
RAD_IPFS_API_URL=http://localhost:19301 stack exec -- \
  rad-daemon-radicle --machine-config /tmp/radicle-machines.json

And to build the project with stack's docker support:

stack build --docker

If you use docker-compose up for the first time you will also need to initialize the IPFS test network with

echo '{"radicle": true}' | \
  docker-compose -f test/docker-compose.yaml exec -T ipfs-test-network ipfs dag put

If you are using docker-machine, replace localhost in RAD_IPFS_API_URL with the output of docker-machine ip.

You can reset the test daemon’s machine configuration by removing the file /tmp/radicle-machines.json.

Packaging

Packages can be built with the ./packaging/build-package.sh script. Run it with -h for more information. The script requires fpm.

On CI a Debian package is built for every commit and uploaded to http://static.radicle.xyz/releases. The package uses the commit hash as the version.

Troubleshooting

Your local machine might build binaries that are incompatible with the debian:stretch container image. In that case building the docker images fails. You can build compatible binaries using stack’s docker integration. This is enabled by passing the STACK_DOCKER=1 environment to ./scripts/ci-tests.sh.

Code of conduct

Please read our code of conduct when thinking of contributing.

radicle-alpha's People

Contributors

0xflotus avatar asymmetric avatar cloudhead avatar curiousleo avatar dependabot[bot] avatar fintanh avatar hxrts avatar jameshaydon avatar jkarni avatar juanmanual avatar juliendonck avatar kim avatar luqui avatar maxhallinan avatar mebrei avatar stephengroat avatar tsenart avatar xla avatar

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

radicle-alpha's Issues

pretty . parse = id

On occasion this test fails.

The test cases are invariably large so I don't have any immediate insight into what's happening.

Generic conversion from Value to other Haskell values

@cloudhead is implementing CLIs that need to communicate via Values, but use other datatypes. One thought that came up in discussion is that we could have two classes:

class FromValue a where
   fromValue :: Value -> Either Text a

class ToValue a where
   toValue :: a -> Value

With generic instances.

This would simplify a lot of our codebase as well. Already it's a bit painful to convert Bindings to Value, but perhaps more significantly, all our pattern matching on primop arguments could be simpler.

instance (FromValue a, FromValue b) => FromValue (a, b) where
   fromValue (List [a,b]) = (,) <$> fromValue a <*> fromValue b
   fromValue (List xs) = Left $ "expecting list with two elements, got " <> show (length xs)
   fromValue _ = Left $ "expecting list"

-- etc.

And then we can just pattern match on what we expect with fromValue.

eval-with-env

Right now you can't see what would be the result of evaluating an expression in a particular chain (without submitting it) since eval doesn't take an Env/Bindings/Dict as a parameter.

Add an eval that does take such a param.

Split server into CentralChain, and ChainApi

  • CentralChain is a centralised radicle chain (what we have now, but will be replaced by a decentralised version)
  • ChainApi is a server that connects to a chain and provides a nice API to interact with it, including viewing input, viewing outputs, submitting expressions, etc.

Dictionary literals

Clojure:

{:a 1 :b 2}

Racket:

#hash((1 . 1) (2 . 2))

Note that in Clojure commas are whitespace, so {:a 1, :b 2} is also valid.

Config file not found when not using XDG_*

; l ~/.config/rad 
total 4.0K
-rw-r--r-- 1 cloudhead 282 Aug 31 17:34 config.rad

; repl                                                                                                                                                                                                                                                                                 
repl: $HOME/.config/rad/config.rad: openFile: does not exist (No such file or directory)

`ref` and `deref-all` primops

We have so far a hyperstatic environment. This is probably the right default, but it should be possible to also query the environment at the call site with a get primop. #2 does most of the work - after that, I think it's really just a question of exposing the primop.

Parse as datum first

This is how Scheme works, and allows for more power over metaprogramming (e.g., lambda syntax may be redefined).

Relatedly, there's a bug currently where (list? x) gets parsed as (list ? x) because of the the listP parser, which would be fixed by this.

Errors, Exceptions and stack traces

  • Informative error messages.
  • Informative, well formatted stack traces.
  • Ability to throw and catch exceptions.

Currently (or rather, after #30), throwing and catching exceptions is possible, but somewhat limited - they can only be handled on the basis of a label (and a special any label). It would be good to have a better story for this.

JSON serialisation

  • All Values should have a JSON representation.
  • Prelude should have a to-json function.

Refs again again

Refs now work correctly, but they're very tricky to work with, since evaluation and values are all tagged with a state thread type. This is fine for traditional use cases, but oscoin needs to run multiple chains with common prefixes and those need different state threads (and keep old states in case in the future there's a fork). So moving to a State monad might be better.

Primop improvements

Rename:

  • car to head
  • cdr to tail
  • deref to read-ref
  • Maybe sorted-map to dict?

Add:

  • string?
  • list?
  • dict?
  • type
  • apply

Should send! resolve vars?

We wrote some eval functions for different chains. Currently, if we (send! "chain" 'my-custom-eval), that only works if the other chain knows what my-custom-eval is (and what the variables it uses are). This makes it an annoyance to send things, since you can't really abstract over the process.

If we resolved everything down to primops (plus maybe prelude), this wouldn't be a problem.

Will the real eval please stand up

We still have a fixed eval/fold, and so the language is not reflective. This should be fixed.

(#2 changes the way state is handled, allowing definition of a get primop. This in turn allows a reflective meta-interpreter, though we still have to change the Haskell definition of eval)

Cleaner REPL story

With #2 the repl works by just picking the InputT monad opaquely. Instead, config.rad should be picking whether to start in repl mode or not.

Possibly the best way to do this is have subscribe-to! take an extra initialization argument.

Import

It'd be useful to have a basic import mechanism.

Syntax

(import <module> [<bindings>])
(module <module> <bindings> <body>)

Semantics

The imported module is evaluated in an initially empty environment.

The intersection of the imported and exported bindings is shared between environments.

Any non-static reference in the imported module is always resolved to the current version of the environment in which it was originally evaluated. (If later we want to allow variation, semantically we can conceive of each variable as implicitly statically namespaced, and can allow syntax for variation.) Static references are resolve immediately in the module environment as one would expect.

Module-like mechanisms could be used for data abstraction and information hiding, so it's worth thinking about

RSA primitives

Add a means of signing and verifying data.

For this to be useful in the REPL, it may be that a way of dealing with the shell or with files will be needed.

Overevaluation in folds

And likely in map:

rad> (foldr (lambda (x acc) (+ (head x) acc)) 0 (list (list 1)))
Type error: Trying to apply a non-function

(both evalArgs and $$ evaluate.)

Fix 'ref'

I believe ref doesn't always work as intended. While resolving the identifier is delayed, the surrounding computation isn't. So applying a function to a ref will generally result in a type error.

The fix, I think, is simple - for any application, evaluate all arguments. If any of them is a ref, don't try evaluating the application itself. deref-all already evaluates it's argument after substitutions, so this should do the right thing.

Parsing not tokenizing properly

E.g. if:@Y parses as Primop "if" rather than Atom "if:@Y" (says quickcheck). Looks like tokenization isn't being done properly.

In-language documentation

  • There should be a doc function which, given an identifier, returns the documentation for that identifier (if it exists).
  • There should be a way of documenting new functions that integrates with that doc function.
  • Existing primops should be documented.

I initially imagined there was good reason to have doc work only in the impure environment (since we want to maintain referential transparency). But I now realize doc can work on quoted identifiers and maintain referential transparency. (Note that quote is not a function, and in typed settings at least for subtle and profound reasons that I only half-remember, so there's no function from an unquoted value to it's documentation.)

Recursion

Currently this is only possible with the y combinator.

Mutations to refs are not persisted beyond the scope of a lambda

E.g.:

In prelude:

(define inc (lambda (x) (+ x 1)))

(define modify-ref
  (lambda (r fn)
    (define temp (read-ref r))
    (write-ref r (fn temp))
    ))

Repl:

(define t (ref 0))
()
rad> (modify-ref t inc)
()
rad> (read-ref t)
0.0

The problem (I think) is that mutations to refs modify the env, and the env is restored to the original after the lambda has finished executing.

Show context of error

Currently only parse errors show the context (line, etc.) of the error. Other errors should too.

Add `read` function

It would be nice to be able to read in and eval code from various sources, e.g. version-control.

Handling Env modifications

Currently env state is not managed by the effects system.

A few things to consider:

  • On the one hand it would be nice to unify the env modifications with the rest of the effects system
  • On the other this means we need continuations to handle local gets and sets.
  • Persistence will probably eventually just be a subscriber

Better should-be

A few things could be improved about should-be:

  • Should store test results (or just test cases) in a ref, so we (a) don't have to see them printed to the console, and (b) don't have to check strings for '"succeeded"'/'"failed"'.
  • Should take quoted arguments so we can print out the exact test case in case of failure and so we can selectively run them.
  • Should run with a mocked send/receive
  • Should take an identifier rather than string as first argument. This way we can figure out what tests are associated with a particular identifier, and can e.g. use them in documentation as examples.

Fix list vs quote story

Right now ' creates a list (and differs in behavior to quote). Either rename this to list, or add list and make it an alias for quote.

Implement 'show'

A slight annoyance here is that the Pretty instance is in another module right now, which will likely have to move.

List as function/lambda argument

Currently a lambda has to be explicit about the arguments:

(lambda (x y) (+ x y))

Unparenthesized lambda arguments should also be allowed, in which case the lambda receives a list as argument (where the list contains all arguments actually given). This allows varargs, and kwargs.

Update autocomplete

Currently autocomplete gathers identifiers only once, at the beginning of the session. This means it has nothing but primops to go on.

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.