Skip to content

Commit

Permalink
Add tests of the example code in the OQ3 spec (#212)
Browse files Browse the repository at this point in the history
This is the start of a big project. Especially becaue a good amount of the
code fails. This is in part because we have been increasing the amount of
semantic analysis. This is good because less incorrect code is silently
allowed. However the are many false positives.

This exercise is a good way to identify and organize features that
are not supported or that have bugs.

This commit covers all of "comments.rst" and 16 percent of the file
"types.rst".
  • Loading branch information
jlapeyre committed Mar 28, 2024
1 parent f672259 commit 59cc778
Showing 1 changed file with 174 additions and 0 deletions.
174 changes: 174 additions & 0 deletions crates/oq3_semantics/tests/spec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
use oq3_semantics::asg;
use oq3_semantics::semantic_error::SemanticErrorList;
use oq3_semantics::symbols::SymbolTable;
use oq3_semantics::syntax_to_semantics::parse_source_string;

// This file tests code in the written OpenQASM 3 spec.
//
// The commit from which the example code was taken is written above each test.
//
// Tests that cause the parser to panic are commented out.
//
// Tests of unimplemented features are marked "Not supported". Note that if possible
// these tests are designed to pass. The

fn parse_string(code: &str) -> (asg::Program, SemanticErrorList, SymbolTable) {
parse_source_string(code, None, None::<&[&std::path::Path]>)
.take_context()
.as_tuple()
}

//
// comments.rst
//

// 17dedf
#[test]
fn test_spec_comments_1() {
let code = r#"
// A comment line
/*
A comment block
*/
"#;
let (program, errors, _symbol_table) = parse_string(code);
assert!(errors.is_empty());
assert!(program.is_empty());
}

// 17dedf
// NOTE! Two problems here. One: In this version of the spec,
// the file is stdgates.qasm rather than the correct stdgates.inc
// Two: This parser panics rather than gracefully recording an error
// if an included file is not found.
// There is a PR open to fix the spec https://github.com/openqasm/openqasm/pull/523
// In the meantime, I took the liberty of changing the code in the spec and testing that
// instead.
// Note that neither of the non-comment lines is translated to a statement, so the
// program is still empty.
#[test]
fn test_spec_comments_2() {
let code = r#"
// First non-comment is a version string
OPENQASM 3.0;
include "stdgates.inc";
// Rest of QASM program
"#;
let (program, errors, _symbol_table) = parse_string(code);
assert!(errors.is_empty());
assert!(program.is_empty());
}

//
// types.rst
//

// 17dedf
#[test]
fn test_spec_types_1() {
let code = r#"
qubit q0;
qubit q1;
qubit q2;
// and to declare a set of classical variables
int[32] a;
float[32] b = 5.5;
bit[3] c;
bool my_bool = false;
"#;
let (program, errors, _symbol_table) = parse_string(code);
assert!(errors.is_empty());
assert_eq!(program.len(), 7);
}

// 17dedf
// Not supported
// Issue #211
// #[test]
// fn test_spec_types_2() {
// let code = r#"
// // Valid statements

// include "stdgates.inc";

// qubit[5] q1;
// const uint SIZE = 4;
// uint runtime_u = 2;
// qubit[SIZE] q2; // Declare a 4-qubit register.

// x q1[0];
// z q2[SIZE - 2]; // The index operand is of type `const uint`.

// // Validity is implementation-defined.

// x q1[runtime_u];
// // Indexing with a value with a non-`const` type (`uint`, in this case) is
// // not guaranteed to be supported.
// "#;
// let (_program, errors, _symbol_table) = parse_string(code);
// assert_eq!(errors.len(), 0);
// }

// 17dedf
#[test]
fn test_spec_types_3() {
let code = r#"
// Declare a qubit
qubit gamma;
// Declare a qubit with a Unicode name
qubit γ;
// Declare a qubit register with 20 qubits
qubit[20] qubit_array;
"#;
let (program, errors, _symbol_table) = parse_string(code);
assert!(errors.is_empty());
assert_eq!(program.len(), 3);
}

// 17dedf
#[test]
fn test_spec_types_4() {
let code = r#"
// Not in spec code block
include "stdgates.inc";
// CNOT gate between physical qubits 0 and 1
CX $0, $1;
"#;
let (program, errors, _symbol_table) = parse_string(code);
assert!(errors.is_empty());
assert_eq!(program.len(), 1);
}

// 17dedf
// Bug
// Incorrect syntax error recorded.
// Not supported in the semantic analysis.
// Issue #210
#[test]
fn test_spec_types_5() {
let code = r#"
defcal h $0 { }
"#;
let (program, errors, _symbol_table) = parse_string(code);
assert!(errors.is_empty());
assert_eq!(program.len(), 0);
}

#[test]
fn test_spec_types_6() {
let code = r#"
// Declare a register of 20 bits
bit[20] bit_array;
// Declare and assign a register of bits with decimal value of 15
bit[8] name = "00001111";
"#;
let (program, errors, _symbol_table) = parse_string(code);
assert!(errors.is_empty());
assert_eq!(program.len(), 2);
}

0 comments on commit 59cc778

Please sign in to comment.