Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Epic: Metaprogramming #4594

Open
16 of 25 tasks
jfecher opened this issue Mar 19, 2024 · 1 comment
Open
16 of 25 tasks

Epic: Metaprogramming #4594

jfecher opened this issue Mar 19, 2024 · 1 comment
Assignees
Labels
aztec.nr Helpful for development of Aztec.nr the smart contract framework enhancement New feature or request
Milestone

Comments

@jfecher
Copy link
Contributor

jfecher commented Mar 19, 2024

Proposal: https://hackmd.io/Tkzo_ryvTsWMPESmWHPiZw?view

Core Tasks for Noir 1.0

  1. enhancement
  2. enhancement
  3. enhancement
  4. enhancement
  5. enhancement
  6. enhancement
  7. enhancement
  8. enhancement
  9. enhancement
  10. enhancement
  11. enhancement
  12. enhancement
    jfecher
  13. enhancement
    jfecher
  14. enhancement
    jfecher
  15. enhancement
    michaeljklein
  16. enhancement
  17. enhancement
    jfecher
  18. enhancement
  19. enhancement

Bugs for Noir 1.0

  1. bug
  2. bug
  3. bug
  4. enhancement

Nice-to-haves for Noir 1.0+

  1. 0 of 1
    aztec.nr enhancement
  2. enhancement
@jfecher jfecher self-assigned this Mar 19, 2024
github-merge-queue bot pushed a commit that referenced this issue Mar 20, 2024
# Description

## Problem\*

Resolves #4586

Part of #4594

## Summary\*

Adds a `quote { ... }` expression to the parser along with a new builtin
`Code` type which it is the only method of creating.

## Additional Context

The quote expression can only currently quote expressions and
statements. It cannot yet quote top-level statements - we'd need more
parser changes for this. In particular the top level statement parser
would now need to be recursive and passed down all the way to the
expression level...

Trying to use `quote` in a program gives you an `experimental feature`
warning. Indeed, the only thing you can do with it currently is panic
once it gets to monomorphization without being removed from the runtime
program yet.

## Documentation\*

Check one:
- [x] No documentation needed.
- I'm following the pattern with other experimental features and waiting
to document them until they're stable. For this, it means quote won't be
documented until the base for metaprogramming is completed.
- [ ] Documentation included in this PR.
- [ ] **[Exceptional Case]** Documentation to be submitted in a separate
PR.

# PR Checklist\*

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
@Savio-Sou Savio-Sou added enhancement New feature or request aztec.nr Helpful for development of Aztec.nr the smart contract framework labels Mar 28, 2024
TomAFrench pushed a commit that referenced this issue Apr 3, 2024
# Description

## Problem\*

Resolves #4586

Part of #4594

## Summary\*

Adds a `quote { ... }` expression to the parser along with a new builtin
`Code` type which it is the only method of creating.

## Additional Context

The quote expression can only currently quote expressions and
statements. It cannot yet quote top-level statements - we'd need more
parser changes for this. In particular the top level statement parser
would now need to be recursive and passed down all the way to the
expression level...

Trying to use `quote` in a program gives you an `experimental feature`
warning. Indeed, the only thing you can do with it currently is panic
once it gets to monomorphization without being removed from the runtime
program yet.

## Documentation\*

Check one:
- [x] No documentation needed.
- I'm following the pattern with other experimental features and waiting
to document them until they're stable. For this, it means quote won't be
documented until the base for metaprogramming is completed.
- [ ] Documentation included in this PR.
- [ ] **[Exceptional Case]** Documentation to be submitted in a separate
PR.

# PR Checklist\*

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
@TomAFrench TomAFrench added this to the 1.0 milestone Apr 20, 2024
github-merge-queue bot pushed a commit that referenced this issue May 9, 2024
)

# Description

## Problem\*

Working towards #4594 

## Summary\*

Adds a hidden compiler option `--use-elaborator` to enable the
experimental elaborator code to be run on a codebase.

This also connects the elaborator with `dc_crate` (and thus the cli flag
above) by filling in the stub for elaborating functions. Filling in the
stub required quite a bit of code but it was as usual just copied from
name resolution and type checking.

## Additional Context

Originally I wanted to connect the elaborator to more of the frontend
(e.g. resolve globals, types, traits, etc) but this already ballooned to
a large line count. To review I'd recommend reviewing the non-elaborator
portions first then just skimming through the elaborator portions since
they are copied from `Resolver::resolve_function`,
`Resolver::extract_meta`, `Resolver::intern_function`, and
`type_check_func`.

## Documentation\*

Check one:
- [x] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.

# PR Checklist\*

- [x] I have tested the changes locally.
- [ ] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
github-merge-queue bot pushed a commit that referenced this issue May 21, 2024
# Description

## Problem\*

Working towards #4594 

## Summary\*

Adds support for impls and trait impls to the elaborator.

This was somewhat satisfying to add since the existing code for this in
`dc_crate.rs` is very messy & long winded due to our current design of
creating a new `NameResolver` for every resolution. Keeping everything
in the same elaborator and not needing to keep setting the interner, def
maps, current crate, module, generics, append errors, etc saved many
lines. I think this implementation is roughly half the size as a result.

## Additional Context

Still need types, type aliases, and globals after this. The pass is
testable after that but is expected to fail the comptime tests at least.
So I'll need to inline the comptime scanning pass in the elaborator as
well. After that the pass is theoretically done but realistically there
will be bugs to fix before we can make it the default.

## Documentation\*

Check one:
- [x] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.

# PR Checklist\*

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
github-merge-queue bot pushed a commit that referenced this issue May 22, 2024
# Description

## Problem\*

Working towards #4594 

## Summary\*

Adds support for resolving top-level traits and type definitions to the
elaborator.

## Additional Context

After this PR only globals will need to be resolved in the elaborator.

## Documentation\*

Check one:
- [x] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.

# PR Checklist\*

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
github-merge-queue bot pushed a commit that referenced this issue May 28, 2024
# Description

## Problem\*

Working towards #4594 

## Summary\*

When run on a program the elaborator would always panic previously due
to `FuncMeta`s not yet being set for other functions while one function
was being elaborated. This is because we used to set them during name
resolution and only check them during type checking, but now that these
two passes are merged we'll need to set them all before elaboration
instead.

This PR creates a new `define_function_metas` function to create the
`FuncMeta`s beforehand. I imagine there are more changes required here
related to scoping / generics / parameters but this at least stops the
panic.

## Additional Context

This is the first of the elaborator PRs to feature only new changes
rather than largely copied code, so feel free to critique as usual if
you think a different approach would be better, notice an issue, etc.

After this PR the elaborator will run on a small example program, only
producing 1052 errors in the standard library 🙂.
Most of these errors appear to be variants of "no method named '...'
found for ..." and "no matching impl found for ..."

## Documentation\*

Check one:
- [x] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.

# PR Checklist\*

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.

---------

Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
Co-authored-by: Maxim Vezenov <mvezenov@gmail.com>
@jfecher
Copy link
Contributor Author

jfecher commented Jun 18, 2024

Current goal is to get a vertical slice of metaprogramming working to support deriving a trait impl of a simple type on a simple trait like Default:

comptime fn derive_default(typ: TypeDefinition) -> Quoted {
    let generics: [Quoted] = typ.generics();
    assert(generics.is_empty(), "derive_default: Deriving Default on generic types is currently unimplemented");

    let type_name: Type = typ.as_type();
    let fields: [(Quoted, Type)] = typ.fields();
    
    let fields: Quoted = fields.map(|(name, _)| quote { $name : Default::default(), })
        .join();

    quote {
        impl Default for $type_name {
            fn default() -> Self {
                Self { $fields }
            }
        }
    }
}

#[derive_default]
struct Foo {
    x: Field
}

// Expected output:
//
// impl Default for Foo {
//     fn default(this: Self) -> Self {
//         Foo {
//             x: Default::default(),
//         }
//     }
// }

Required unimplemented features:

  • Query functions on TypeDefinition: generics, as_type, and fields
  • Quoted type for quoted, unparsed raw token streams. I think this is necessary to quote code fragments like quote { $name : Default::default(), } which is only valid in the context of struct initialization. I've chosen this name to avoid confusion with crypto tokens that Tokens or TokenStream may cause.
    • Additionally, to support this and make unquoting easier into arbitrary locations of quoted values, I'd like to move from an AST representation of quoted values to a token stream. This will ensure we can combine values like quote { $name : Default::default(), } where $name is spliced in despite us not knowing what grammar rule it should be part of (is it an identifier? an expression?).
    • Quoted token streams will be the new default type of quoted values with alternate types like quote Type { ... } or quote TopLevelItem { ... } only being used to force a quoted value into a particular shape so that specific methods can be called on it. TypeDefinition is the only type with methods on it above but we can imagine similar methods on a Type value which would be meaningless on unparsed Quoted values.
    • Notably, quoting the impl as a token stream avoids us needing to rework the parser to make our top level statement parser recursive since at parse time we'd only be parsing a token stream here.
    • The token stream ends when the matching } is found.
    • We avoid actually parsing Quoted values until they're expanded into a macro's call site: either a top level statement or an expression. When this happens, we parse the token stream and issue an error if we cannot parse into a top level statement or an expression.
  • Some helper functions like join to join a slice of quoted values into one:
fn join(slice: [Quoted]) -> Quoted {
    let mut ret = quote {};
    for element in slice {
        // Since quoted values are token streams, we do not need (or want) a `;` separator.
        ret = quote { $ret $element };
    }
    ret
}
  • Finally, it is optional but would be very useful to get generic functions like map working in the interpreter. The work around for this is writing a monomorphic version of map for Quoted values.

Edit: We used to have a Code type for quoted code. Maybe we should use that name over Quoted?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
aztec.nr Helpful for development of Aztec.nr the smart contract framework enhancement New feature or request
Projects
Status: 🏗 In progress
Development

No branches or pull requests

3 participants