Giter VIP home page Giter VIP logo

lurk-lab / lurk-rs Goto Github PK

View Code? Open in Web Editor NEW
400.0 15.0 51.0 123.23 MB

Lurk is a Turing-complete programming language for recursive zk-SNARKs. It is a statically scoped dialect of Lisp, influenced by Scheme and Common Lisp.

Home Page: https://lurk-lang.org/

License: Apache License 2.0

Rust 99.84% Nix 0.08% Just 0.09%
rust zk-snarks compiler cryptography programming-language zero-knowledge

lurk-rs's Introduction

Lurk

lurk-rs minimum rustc 1.70 dependency status crates.io

Status (Beta)

Lurk is currently in Beta, which is backwards compatible with code that ran in Lurk Alpha and is expected to be compatible with Lurk 1.0. However, some low-level data representations are anticipated to change, and we will be refactoring the evaluation model (and consequently its circuit) for efficiency purposes. Also note that since Lurk inherits some security properties from the underlying proving system, those who would rely on Lurk should investigate the security and status of Nova/SuperNova itself. We encourage early adopters to begin writing real applications taking advantage of Lurk so you can begin to familiarize yourself with the programming model. Likewise, we welcome your feedback -- which will help ensure ongoing development meets user need.

For support and discussions, please visit our Zulip forum.

Overview

Lurk is a statically scoped dialect of Lisp, influenced by Scheme and Common Lisp. A reference implementation focused on describing and developing the core language can be found in the lurk repo.

Lurk's distinguishing feature relative to most programming languages is that correct execution of Lurk programs can be directly proved using zk-SNARKs. The resulting proofs are succinct: they are relatively small, can be verified quickly, and they reveal only the information explicitly contained in the statement to be proved.

For more detailed information, refer to the paper: https://eprint.iacr.org/2023/369

Lurk's distinguishing feature relative to most zk-SNARK authoring languages is that Lurk is Turing complete, so arbitrary computational claims can be made and proved (subject to resource limitations, obviously). Because Lurk is a Lisp, its code is simply Lurk data, and any Lurk data can be directly evaluated as a Lurk program. Lurk constructs compound data using SNARK-friendly Poseidon hashes (provided by Neptune), so its data is naturally content-addressable.

Proofs

Integration with backend proving systems and tooling for proof generation are both still very early. Performance and user experience still have room for significant optimization and improvement, but simple examples can be found in the demo example directory.

Backends

It is an explicit design goal that statements about the evaluation of Lurk programs have identical semantic meaning across backends, with the qualification that Lurk language instances are themselves parameterized on scalar field and hash function. When backends use the same scalar field and hash function, they can be used to generate equivalent proofs. This is because the concrete representation of content-addressed data is fixed.

Performance

Lurk backend integration is still immature, so current performance is not representative. As a rough approximation, we estimate that for entirely general computation using Lurk's universal circuit, Nova proving throughput will be on the order of 1,000 iterations per second per GPU. We expect that most compute-heavy applications will use optimized 'coprocessor' circuits, which will dramatically improve performance. Planned improvements to Nova will allow for smaller inner circuits, further improving throughput -- and for full parallelization of reduction proofs.

Specs

Security Audit

Lurk's Alpha release has undergone a security audit as of 03/29/2023, performed by Inference.

Versioning

Please note that the Lurk language and spec will be versioned independently from the crates that implement the spec. This is necessary because semantic versioning implies different requirements for the language and its implementation. For example, Lurk Alpha is released as crate lurk 0.2.0 and Lurk Beta is released as crate lurk 0.3.0. It is our intention for these two versioning systems to coincide at 1.0.


Build

Submodules

Lurk source files used in tests are in the lurk-lib submodule. You must initialize and update submodules before test will pass:

git submodule update --init --recursive

Wasm

Prerequisites

Lurk can be compiled to Wasm with

cargo build --target wasm32-unknown-unknown

If using Nix without a system-wide clang install (e.g. NixOS):

CC=clang cargo build --target wasm32-unknown-unknown

Repl

cargo run --release

Or use the wrapper script:

bin/lurk

Set the environment variable LURK_FIELD to specify the scalar field of the Lurk language instance:

  • LURK_FIELD=PALLAS (default): scalar field of Pallas
  • LURK_FIELD=VESTA: scalar field of Vesta
  lurk-rs  bin/lurk
    Finished release [optimized] target(s) in 0.06s
     Running `target/release/lurk`
Lurk REPL welcomes you.
> (let ((square (lambda (x) (* x x)))) (square 8))
[9 iterations] => 64
>

Or enable info log-level for a trace of reduction frames:

  lurk-rs  RUST_LOG=lurk::lem::eval=info bin/lurk
    Finished release [optimized] target(s) in 0.05s
     Running `target/release/lurk`
Lurk REPL welcomes you.
user> (let ((square (lambda (x) (* x x)))) (square 8))
  2023-12-10T15:58:21.902414Z  INFO lurk::lem::eval: Frame: 0
	Expr: (let ((.lurk.user.square (lambda (.lurk.user.x) (* .lurk.user.x .lurk.user.x)))) (.lurk.user.square 8))
	Env:  nil
	Cont: Outermost
    at src/lem/eval.rs:99

  2023-12-10T15:58:21.902943Z  INFO lurk::lem::eval: Frame: 1
	Expr: (lambda (.lurk.user.x) (* .lurk.user.x .lurk.user.x))
	Env:  nil
	Cont: Let{ var: .lurk.user.square, saved_env: nil, body: (.lurk.user.square 8), continuation: Outermost }
    at src/lem/eval.rs:107

  2023-12-10T15:58:21.903170Z  INFO lurk::lem::eval: Frame: 2
	Expr: (.lurk.user.square 8)
	Env:  ((.lurk.user.square . <FUNCTION (.lurk.user.x) (* .lurk.user.x .lurk.user.x)>))
	Cont: Tail{ saved_env: nil, continuation: Outermost }
    at src/lem/eval.rs:107

  2023-12-10T15:58:21.903649Z  INFO lurk::lem::eval: Frame: 3
	Expr: .lurk.user.square
	Env:  ((.lurk.user.square . <FUNCTION (.lurk.user.x) (* .lurk.user.x .lurk.user.x)>))
	Cont: Call{ unevaled_arg: 8, saved_env: ((.lurk.user.square . <FUNCTION (.lurk.user.x) (* .lurk.user.x .lurk.user.x)>)), continuation: Tail{ saved_env: nil, continuation: Outermost } }
    at src/lem/eval.rs:107

  2023-12-10T15:58:21.903678Z  INFO lurk::lem::eval: Frame: 4
	Expr: 8
	Env:  ((.lurk.user.square . <FUNCTION (.lurk.user.x) (* .lurk.user.x .lurk.user.x)>))
	Cont: Call2{ function: <FUNCTION (.lurk.user.x) (* .lurk.user.x .lurk.user.x)>, saved_env: ((.lurk.user.square . <FUNCTION (.lurk.user.x) (* .lurk.user.x .lurk.user.x)>)), continuation: Tail{ saved_env: nil, continuation: Outermost } }
    at src/lem/eval.rs:107

  2023-12-10T15:58:21.903696Z  INFO lurk::lem::eval: Frame: 5
	Expr: (* .lurk.user.x .lurk.user.x)
	Env:  ((.lurk.user.x . 8))
	Cont: Tail{ saved_env: nil, continuation: Outermost }
    at src/lem/eval.rs:107

  2023-12-10T15:58:21.903772Z  INFO lurk::lem::eval: Frame: 6
	Expr: .lurk.user.x
	Env:  ((.lurk.user.x . 8))
	Cont: Binop{ operator: product#, saved_env: ((.lurk.user.x . 8)), unevaled_args: (.lurk.user.x), continuation: Tail{ saved_env: nil, continuation: Outermost } }
    at src/lem/eval.rs:107

  2023-12-10T15:58:21.903844Z  INFO lurk::lem::eval: Frame: 7
	Expr: .lurk.user.x
	Env:  ((.lurk.user.x . 8))
	Cont: Binop2{ operator: product#, evaled_arg: 8, continuation: Tail{ saved_env: nil, continuation: Outermost } }
    at src/lem/eval.rs:107

  2023-12-10T15:58:21.903866Z  INFO lurk::lem::eval: Frame: 8
	Expr: Thunk{ value: 64 => cont: Outermost }
	Env:  nil
	Cont: Dummy
    at src/lem/eval.rs:107

  2023-12-10T15:58:21.903878Z  INFO lurk::lem::eval: Frame: 9
	Expr: 64
	Env:  nil
	Cont: Terminal
    at src/lem/eval.rs:107

[9 iterations] => 64
user> 

Install

You can install the lurk Repl on your machine with

$ cargo install --path .

Nix

Install Nix and enable Nix flakes. Then, you can enter into a Nix devshell with the appropriate dependencies for Lurk with

$ nix develop

or

$ direnv allow

And then build with Cargo as usual:

$ cargo build

License

MIT or Apache 2.0

lurk-rs's People

Contributors

anderssorby avatar arajasek avatar arthurpaulino avatar borkborked avatar cognivore avatar cpacia avatar dependabot[bot] avatar dignifiedquire avatar emmorais avatar gabriel-barrett avatar github-actions[bot] avatar hnfgns avatar huitseeker avatar jobez avatar johnchandlerburnham avatar jpeg07 avatar larskuhtz avatar mpenciak avatar namin avatar porcuquine avatar samuelburnham avatar storojs72 avatar tchataigner avatar thabokani avatar vmx avatar vuvoth avatar weissjeffm avatar winston-h-zhang avatar wwared avatar ynx0 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

lurk-rs's Issues

makefile for fibonacci proof erroring on master branch

Currently, running make fibonacci-proof.json on master causes the following error:

➜  examples git:(master) ✗ make fibonacci-proof
cargo run --release -- prove --expression fibonacci.lurk --proof fibonacci-proof.json
    Finished release [optimized] target(s) in 0.09s
     Running `/Users/jonat/lurk-rs/target/release/fcomm prove --expression fibonacci.lurk --proof fibonacci-proof.json`
thread 'main' panicked at 'failed to read file: Error("expected value", line: 1, column: 1)', /Users/jonat/lurk-rs/fcomm/src/lib.rs:413:44
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
make: *** [fibonacci-proof.json] Error 101

README instructions are here.

The above command does work on the fcomm-commitment branch. On master, you have to run the cargo command with --lurk added to make it work (cargo run --release -- prove --expression fibonacci.lurk --proof fibonacci-proof.json --lurk).

It seems like either the JSON needs to be fixed to work as it does on fcomm-commitment branch or the makefile on master needs to update to include --lurk.

Create dummy pointers

In some situations we are returning nil instead of proper dummy pointers. We need to take care because sometimes eval can be adapted to generate corrupted frames that lead to invalid proofs (breaking soundness). Moreover, using dummy pointers would improve readability of the code. We need to add:

  • bogus dummy, for parts of the circuits that are not being exercised depending on some condition like a continuation tag or the head of an expression.
  • blank dummy, for the initial phase of the circuit construction.

Parsing issues between quoted and hierarchical symbols?

Run the following:

 ~/ lurkrs
Lurk REPL welcomes you.
>  (lambda (|α|) nil)
thread 'main' panicked at 'assertion failed: !path.is_empty()', src/sym.rs:181:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
[1 iterations] => <FUNCTION (%
 ~/

Allow unicode identifiers

Hi from Yatima. For the Yatima to Lurk transpiler, we would like to be able to use unicode characters so the translated names can be preserved.

We would like at least the greek alphabet α, β, ..., superscripts , and subscripts a₁. Perhaps some math notation such as ∧ ∨ ∑, although these have much less priority. Let us know how much flexibility there is in the parser for these. Thanks!

From our discussion in discord: We would also like to have case sensitivity when symbol escaping.

Add error-handling to REPL

Now that evaluation returns a Result (#144), we should update the REPL to fail gracefully rather than continue to panic because of unwrapping any errors which result.

handle out-of-range char coercions

As noted in #203, coercion to char with (char …) doesn't do any typechecking, which means its possible to create a proof of an evaluation whose output is a malformed Char.

For example:

(char (- 0 1))

This won't work in lurk-rs out of the box, since the evaluation will result in an error, but if the frame input were created 'maliciously', such a proof could still be generated.

Attempting to do this should either result in an explicit, provable error — or a truncated result guaranteed to be in range. The latter is probably preferable, by analogy to u64.

> (u64 (- 0 1))
[5 iterations] => 10108024940646105088u64

Inconsistent u64. division by zero failure (error vs panic)

Example:

> (/ (u64 5) (u64 0))
[7 iterations] => ERROR!
> (% (u64 5) (u64 0))
thread 'main' panicked at 'attempt to calculate the remainder with a divisor of zero', src/uint.rs:80:55
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Bring Circuit to 100% correctness

This is a tracking issue which should not be closed until all known circuit issues have been resolved.

Known issues:

  • (fib 100) proofs fail to verify. [verified fixed in #113]
  • test_create_open_and_verify_complicated_higher_order_functional_commitment2 fails (fcomm).
  • Error handling: in some cases either eval or circuit synthesis panics in error cases. Both should return explicit error.
  • FIXME: There are some cases in the circuit marked with FIXME because some known implementation detail has been deferred.

CI performance regression (mac and arm64)

CI seems to have become very slow for mac and arm64 — so much so that we are seeing failures due to timeouts. Even without that, it's taking too long…

Prior to merging #143, master was performing well (at least status quo didn't exhibit this problem).

Previous:
b57acd5
https://app.circleci.com/pipelines/github/lurk-lang/lurk-rs/593/workflows/9e8547a0-f9ed-4859-8a05-ce620907496a

After #143 merged, we see the problem on master (and saw it on the branch, so it's not a surprise).

Slow:
00242f1
https://app.circleci.com/pipelines/github/lurk-lang/lurk-rs/613/workflows/0a04e249-c65e-49f1-b665-fc99a1001bf3

However, the same problem seems to have been affecting #152 — even before it was rebased to include the work from #143. This suggests maybe something else is going on, but it's not clear what.

I've seemingly ruled out the possibility that this is strictly due to some CI configuration or anything else entirely external, because I reran CI on the previous 'good' commit, and that did not display the problem:
https://app.circleci.com/pipelines/github/lurk-lang/lurk-rs/593/workflows/1ee45b5f-fd19-4081-9653-03e677ccd1ed

Implement web code component in Hugo

We want to be able to embed Lurk code in our blog posts for the lurk-lang blog on Hugo.

Here are the desired features:

  • In Hugo, blog post writer can use some kind of markup to create a runnable code block in the blog post. (runs with a button click in the REPL)
  • Additional markup should be able to designate whether the reader is able to edit the code (if so, there should be a 'reset') feature
  • While we will want to embed runnable code blocks in posts, we will also likely want to highlight specific lines of code for more specific discussion/explainer. As such, we'll want a markup feature that lets us hide the other lines of code from view, while still retaining them so that the code will run at the click of a button. A great example of this is in the Rust book. You can see whole blocks of runnable code, as well as a few lines of code (in the latter half of the page) that have a 'show/hide' button (as an eyeball icon) that does what I'm talking about in this bullet point.

@alvin-reyes is going to work on this August 1-5, minimally, but it would be ideal to have someone else who can support this work since his attention is notably split between this and other things.

(Just a note that whoever does this will need access to the lurk-lang-blog repo, which is currently private.)

Create Lurk errors

Solve the following items:

  • Refactor reduce_witness() to return Result<...>
  • Create Lurk errors
  • Replace panics by Lurk errors where applicable
  • Review remaining panics in car_cdr_mut()
  • Refactor car_cdr() as car_cdr_mut()

Evaluating cons literal causes panic

Trying to evaluate a cons pair like (1 . 1) causes panic.

~/workspace/lurk-rs $ lurkrs
Lurk REPL welcomes you.
> (1 . 1)
thread 'main' panicked at 'Can only extract car_cdr from Cons', /home/user/workspace/lurk-rs/src/store.rs:1943:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Create CI test for functional commitments

Since the fcomm examples and readme are likely to change and develop, it would be great to have CI test(s) to ensure the entire process from committing to verifying works as intended.

"double booked: found InnerBody when getting ClosedEnv"

(letrec ((fold (lambda (op acc l)
                 (if l
                     (fold op (op acc (car l)) (cdr l))
                     acc))))
  (fold (lambda (x y) (+ x y)) 0 '(1 2 3)))
thread 'main' panicked at 'double booked: found InnerBody when getting ClosedEnv', /home/user/workspace/lurk-rs/src/hash_witness.rs:190:13

This seems to be a regression, this version of fold worked before. Akosh (who's trying out our onboarding challenge) ran into this. Version I'm testing is bb98c334fed9b329cc3d1d35284ba986961948fb

Rethink dummy var.

#7 implements a dummy var with name "_" for zero-arg functions. That works fine for now, but if/when _ becomes a legal symbol character (which it probably should), it will be possible to create bogus programs depending on the sugar. Like ((lambda () (+ _ 1)) 1).

This needs more thought if we stay with the dummy var approach.

One-arg cons should return an error

As an example, the expression '(cons "")' should return an error, but instead it evaluates successfully because second argument is treated as NIL. We should not default the second argument to NIL. We must return an error instead.

Implement range check

Now that we have the unop char, we have another reason to implement range checks, because we currently we have no mechanism to constrain (in the circuit) the input of char has 32 bits.

For instance, we have that (char 5000000000) is going to fail, which obviously must be fixed. In particular, in this situation, if the input doesn't belong to the range, we must have an error.

Range checks will also be important for implementation of other types in Lurk.

file path merging not working correctly from Lurk REPL

!(:load...) command in the REPL not finding corresponding .lurk file (see error message below).

Lurk REPL welcomes you.
> !(:load “../lurk-lib/test.lurk”)
Loading from /Users/../lurk-rs/target/release/../lurk-lib/test.lurk.
Error: No such file or directory (os error 2)

Pending Circuit Support

This is a tracking issue for pending circuit support issues. Our current workflow is to first add non-circuit support for new features, then update the circuit accordingly (in a separate PR). Whenever such new functionality is added, we should create a corresponding circuit issue and add a link to the list below. When the issue is closed, the box in the checkbox-list below should be checked.

Let's keep this issue open as a master list to be done and historically completed.

Nix run example broken

The Nix build works, but when running the example you get:

~/lurk-rs master
❄ λ nix run .#lurk-example
error: builder for '/nix/store/na18s2l4c2vqf8nk5gvmxkgwbxnphw3z-lurk-deps-0.1.0.drv' failed with exit code 101;
       last 10 log lines:
       >   failed to clone into: /build/dummy-src/.cargo-home/git/db/bellperson-2a76e4554f04bda6
       >
       > Caused by:
       >   network failure seems to have happened
       >   if a proxy or similar is necessary `net.git-fetch-with-cli` may help here
       >   https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli
       >
       > Caused by:
       >   failed to resolve address for github.com: Name or service not known; class=Net (12)
       > [naersk] cargo returned with exit code 101, exiting
       For full logs, run 'nix log /nix/store/na18s2l4c2vqf8nk5gvmxkgwbxnphw3z-lurk-deps-0.1.0.drv'.
error: 1 dependencies of derivation '/nix/store/4hfs7wjgyhp0mi778vfd1rvadjqp7y0p-lurk-0.1.0.drv' failed to build

Is this because of

[patch.crates-io]
bellperson = { git = "https://github.com/filecoin-project/bellperson", branch = "instance-aggregation" }
nova = { git = "https://github.com/porcuquine/nova", package = "nova-snark" }

in the Cargo.toml?

Lambdas print with unbalanced parens

 (lambda () 1)

: Lurk REPL welcomes you.
: > [1 iterations] => <FUNCTION () 1)>
: > Exiting...

Note the last closing paren doesn't have an opening paren. Should probably look like this:

<(FUNCTION () 1)>

Improve error messages for failing Lurk tests

I modified a Lurk test to produce an intentional failure. Running the Lurk test caused a panic as expected but the message was uninformative.

thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `Ptr(Num, RawPtr(5, PhantomData))`,
 right: `Ptr(Num, RawPtr(4, PhantomData))`', src/repl.rs:278:33
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

implement BEGIN

Because EMIT effectively produces order-dependent side effects, we 'need' BEGIN. This is not strictly true, since we can use IF (or LET, LAMBDA, etc.) for sequencing, but an explicit sequencing operator is very convenient. Moreover, it's in the spec and as implemented in api.lisp: https://github.com/lurk-lang/lurk/blob/master/spec/v0-1.md#begin

We should add a spec test in lurk-lib, then implement here and in circuit.

This relatedly suggests we should:

  • synthesize and check circuits for spec tests
  • add a mechanism for testing emitted values during evaluation

The above might best be treated discretely, in which case they can be broken into new issues.

Clean up possibly orphaned functions

During code coverage exploration, I noticed that some functions with no coverage also have nothing referring to them in the lurkrs project (including fcomm).

Here is an example, in hash_witness.rs:

    pub fn get_named_cons(&self, name: &ConsName) -> HashStub<F> {
        for (slot_name, p) in &self.slots {
            if slot_name == name {
                return *p;
            }
        }

        Stub::Dummy
    }

The compiler is not flagging them as unused because of this (in lib.rs):

pub mod hash_witness;

I am not sure if the intention here is for consumers of lurkrs as a library to call this function (even though nothing in the fcomm examples does). Or it could be that this function is actually not needed.

The fact that all the modules have the pub modifier is a bit suspect. As long as that's the case, we can potentially leak unused functions without knowing it.

Only non-keyword symbols should be bindable

Lurk currently allows binding any form at all as the 'variable' on the left-hand-side of a binding in let or letrec.

However, only symbols are ever looked up when evaluating.

It should be an evaluation-time syntax error to perform these useless bindings. Allowing them is confusing, can mask actual errors, and also has a performance cost (in other lookups).

Some example of the behavior we should eliminate follow. All of these should be explicit errors.

Lurk REPL welcomes you.
> (let (((a b) 123)) 1)
[3 iterations] => 1
> (let ((:a 123)) :a)
[3 iterations] => :A
> (let ((9 123)) 9)
[3 iterations] => 9

Reader does not ignore braces in string

I have the following error:

Lurk REPL welcomes you.
> "}"
Mismatched brackets: '}' is unpaired
> "\} "
Mismatched brackets: '}' is unpaired

Also happens with () and []. There's also an error with . interactions within strings too, but I haven't been able to minimize the example yet.

Implement Circuit for Relational Operators

#133 Implements relational operators outside the circuit. We need to support these in the circuit so they can be used in proofs. The tests in #133 cover the most important cases and should also be included when testing the circuit.

Optimize function calls

Currently, zero-arg functions are implemented using a dummy argument while multi-arg functions are implemented by auto-currying. Both of these representations have a bit of inefficiencies in number of iterations.

We could change the representation of call continuations for efficiency.

Refactor reduce_sym

circuit_frame::reduce_sym() needs careful attention. Naming could stand to be more principled and normalized. There may be latent bugs. A complete refactor might be in order, especially if that reduces (or at least doesn't increase) constraints.

Allow underscores in identifiers

We from Yatima are working in the Yatima IR to Lurk transpiler and we'd like to be able to map underscores in Lean identifiers to underscores in Lurk identifiers because we're reserving dashes for Lean's dots.

Our previous solutions used colons, but that's not a good solution in terms of semantics for Lurk code.

check lambda form body structure more strictly

As noted in a comment on #183, we currently allow lambda forms that don't have exactly one body element. It would be better if this led to an error.

Examples:

Lurk REPL welcomes you.
> (lambda (x))
[1 iterations] => <FUNCTION (X) )>
> (lambda (x) 1)
[1 iterations] => <FUNCTION (X) 1)>
> (lambda (x) 1 2)
[1 iterations] => <FUNCTION (X) 1 2)>
> ((lambda (x) 1 2) 9)
[4 iterations] => 1

Since we want to avoid extra destructuring (car_cdr()), which incurs hashing costs in the circuit, the check should not come at the time of creating the function, but later (probably when handling Continuation::Call2 in apply_continuation().), when the body is being inspected.

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.