-
Notifications
You must be signed in to change notification settings - Fork 119
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
Reimplement Parser #2149
Open
idavis
wants to merge
99
commits into
main
Choose a base branch
from
feature/qasm3
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Reimplement Parser #2149
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80a46cc
to
348680f
Compare
dced819
to
cec25d5
Compare
eb82b24
to
b803573
Compare
1ad7321
to
313b7af
Compare
This PR adds our own implementation of an OpenQASM3 parser to the `compiler/qsc_qasm3` directory.
Co-authored-by: Oscar Puente <[email protected]>
This PR adds cyclic and multiple include errors to the qasm parser.
Remove TODO comments from code and add them as Postponed items to the tracking PR.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
An intro to the PR with some useful links for the relevant sections:
This PR has two major components. A custom QASM3 parser, which replaces the IBM parser. And a refactored version of the compiler.
The custom QASM3 parser has three components:
The refactored compiler has two components:
4. Lowerer.
5. Compiler.
Below is more detailed overview of the purpose of each component:
The OpenQASM 3.0 grammar will be useful while reviewing sections 1-2
https://openqasm.com/grammar/index.html
The raw lexer:
Takes the source code as input and returns a stream of "raw tokens". You can think of these mostly as characters like '(' and type literals.
The cooked lexer:
Takes the raw token stream and returns a stream of cooked tokens. Cooked tokens have more knowledge about QASM3 syntax, and they make parsing easier.
Parser:
Takes the stream of cooked tokens as input and returns an AST. We call it the syntax AST, to differentiate it from the semantic AST, which will be introduced later.
The grammar and specification of QASM3 don't fully agree. We had to take some decissions while implementing the parser. They are documented in the rust code. If you want to double check anything, the language spec will come in handy:
https://openqasm.com/language/index.html
Lowerer:
Takes the AST returned by the parser and performs semantic analysis on it. This is where we report any QASM3 related errors, like "functions can only be defined on the global scope." The lowerer returns a semantic AST. You will want to use the language spec to verify that the errors that we are checking for are actually on the spec, or that we are not missing any checks.
https://openqasm.com/language/index.html
Compiler:
Takes the semantic AST and compiles it to a Q# AST. This is where we report any Q# related errors, like unsupported QASM3 features because they don't make sense in Q#. The compiler is a very straighforward mapping from the semantic AST to the Q# AST, since most of the heavy lifting is done during lowering.
Recomended Sections for reviewers:
qsc_qasm3/src/lib.rs (Entry point and general structure)
Mine, Stefan
qsc_qasm3/src/parser/completion.rs (Completion)
qsc_qasm3/src/io.rs (IO)
Mine
qsc_qasm3/src/lex.rs (Raw and Cooked lexer)
Scott
qsc_qasm3/src/parser.rs (Parser)
qsc_qasm3/src/parser/ast.rs (QASM3 AST, double check against grammar & Spec)
Scott
qsc_qasm3/src/oqasm_helpers.rs
qsc_qasm3/src/semantic/types.rs (QASM3 types)
qsc_qasm3/src/semantic.rs (Lowerer entry point)
qsc_qasm3/src/lowerer.rs
This requires QASM3 specific knowledge. We can use as many eyes as possible.
Dmitry, Scott
qsc_qasm3/src/stdlib.rs
qsc_qasm3/src/stdlib/angle.rs
qsc_qasm3/src/stdlib/QasmStdrs
Dmitry
qsc_qasm3/src/types.rs (Types)
qsc_qasm3/src/ast_builder.rs
qsc_qasm3/src/compiler.rs (Compiler)
qsc_qasm3/src/runtime.rs (Runtime Features)
Stefan
fuzz/ (Testing)
Mine, Stefan
pip/src/ (Interop)
qsc/src/
qsc_codegen/src/
Mine, Stefan
.github/fuzz (GitHub pipeline)
Ian, Stefan
Tracking items
Lexing
Parsing
Lowering
Compiling
EntryPoint()
attr on operation when compiling in file modeFit and Finish
&mut Lowerer
as an argument so that it can push semantic errors. Better error messages for const evaluator #2277Postponed
bit x = 0; bit y = ~x;
is valid QASM3, but it gets compiled tolet x = Zero; let y = ~~~x;
which is invalid Q# code, since theResult
type in Q# doesn't support unary bitwise negation. This is the same for all other operations that bit should support, Q# Result only supports equality.uint
types must be positive, since they are compiled to Q#Int
which are signed. We might need aUInt
type similar to theAngle
type introduced in Add angle support to the new compiler #2267 to be able to enforce this constraint.Ident
asRc<Symbol>
and not asSymbolId
to avoid an unnecessarySymbolTable
lookup? In that way we don't even need to pass the symbol table to the compiler.SymbolId
s when creating the function type, so that we can give the user a better error message when they pass an argument that fails implicit casting to a function. There is a catch: we need to insert the function symbol into the symbol table before pushing the scope where the formal parameters live, but we need theSymbolId
s of the formal parameters to construct the function symbol.compiler/qsc_qasm3/src/semantic/ast/const_eval.rs
we need to issue the same lint in Q#.int
touint
and cast fromuint
toint
in const evaluator. Both types are represented asi64
so there is nothing to do, which is confusing.Box<[Box<T>]>
with iai-callgrind in a large OpenQASM3 sample to verify that is actually faster than using Vec. Even though Box uses less stack space, it reduces cache locality, because now you need to be jumping around in memory to read contiguous elements of a list. I suspect that what we really want to use ifBox<[T]>
.compiler/qsc_qasm3/src/compiler.rs::QasmCompiler::compile_output_decl_stmt
.compiler/qsc_qasm3/src/compiler.rs::QasmCompiler::create_entry_item
saying "This can create a collision on multiple compiles when interactive. We also have issues with the new entry point inference logic."fuzzer_issue_2294
. The one valuable error there is the one saying "undefined symbol _`.