Skip to content

Commit ce4ff3b

Browse files
authored
Unify compilation and error propagation. (#2247)
1 parent b803573 commit ce4ff3b

File tree

15 files changed

+107
-125
lines changed

15 files changed

+107
-125
lines changed

compiler/qsc_qasm3/src/compile.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,6 @@ pub fn qasm_to_program(
6868
source_map: SourceMap,
6969
config: CompilerConfig,
7070
) -> QasmCompileUnit {
71-
assert!(!source.has_errors(), "Source has errors");
72-
assert!(
73-
source.parse_result().have_parse(),
74-
"Source has not been successfully parsed"
75-
);
7671
let compiler = QasmCompiler {
7772
source,
7873
source_map,

compiler/qsc_qasm3/src/compile/tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ fn programs_with_includes_with_includes_can_be_compiled() -> miette::Result<(),
1818
("source2.qasm".into(), source2.into()),
1919
];
2020

21-
let unit = compile_all_fragments("source0.qasm", all_sources)?;
21+
let unit = compile_all_fragments("source0.qasm", all_sources).map_err(|e| vec![e])?;
2222
print_compilation_errors(&unit);
2323
assert!(!unit.has_errors());
2424
Ok(())
@@ -39,7 +39,7 @@ fn including_stdgates_multiple_times_causes_symbol_redifintion_errors(
3939
("source2.qasm".into(), source2.into()),
4040
];
4141

42-
let unit = compile_all_fragments("source0.qasm", all_sources)?;
42+
let unit = compile_all_fragments("source0.qasm", all_sources).map_err(|e| vec![e])?;
4343
assert!(unit.has_errors());
4444
for error in unit.errors() {
4545
assert!(error.to_string().contains("Redefined symbol: "));

compiler/qsc_qasm3/src/compiler.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4-
use std::rc::Rc;
4+
use std::{path::Path, rc::Rc, sync::Arc};
55

66
use num_bigint::BigInt;
77
use qsc_data_structures::span::Span;
@@ -19,6 +19,7 @@ use crate::{
1919
build_top_level_ns_with_item, build_tuple_expr, build_unary_op_expr, build_while_stmt,
2020
build_wrapped_block_expr, map_qsharp_type_to_ast_ty, wrap_expr_in_parens,
2121
},
22+
io::{InMemorySourceResolver, SourceResolver},
2223
parser::ast::{list_from_iter, List},
2324
runtime::{get_runtime_function_decls, RuntimeFunctions},
2425
semantic::{
@@ -36,6 +37,62 @@ use crate::{
3637
use crate::semantic::ast as semast;
3738
use qsc_ast::ast::{self as qsast, NodeId, Package};
3839

40+
pub fn compile_anon_with_config<S>(
41+
source: S,
42+
config: CompilerConfig,
43+
) -> miette::Result<QasmCompileUnit>
44+
where
45+
S: AsRef<str>,
46+
{
47+
let path = std::path::PathBuf::from("Test.qasm");
48+
let sources = [(
49+
Arc::from(path.display().to_string().as_str()),
50+
Arc::from(source.as_ref()),
51+
)];
52+
let resolver = InMemorySourceResolver::from_iter(sources);
53+
let source = resolver.resolve(&path)?.1;
54+
compile_with_config(source, &path, &resolver, config)
55+
}
56+
57+
pub fn compile_all_with_config<P>(
58+
path: P,
59+
sources: impl IntoIterator<Item = (Arc<str>, Arc<str>)>,
60+
config: CompilerConfig,
61+
) -> miette::Result<QasmCompileUnit>
62+
where
63+
P: AsRef<Path>,
64+
{
65+
let resolver = InMemorySourceResolver::from_iter(sources);
66+
let source = resolver.resolve(path.as_ref())?.1;
67+
compile_with_config(source, path, &resolver, config)
68+
}
69+
70+
pub fn compile_with_config<S, P, R>(
71+
source: S,
72+
path: P,
73+
resolver: &R,
74+
config: CompilerConfig,
75+
) -> miette::Result<QasmCompileUnit>
76+
where
77+
S: AsRef<str>,
78+
P: AsRef<Path>,
79+
R: SourceResolver,
80+
{
81+
let res = crate::semantic::parse_source(source, path, resolver)?;
82+
let program = res.program;
83+
84+
let compiler = crate::compiler::QasmCompiler {
85+
source_map: res.source_map,
86+
config,
87+
stmts: vec![],
88+
runtime: RuntimeFunctions::empty(),
89+
symbols: res.symbols,
90+
errors: res.errors,
91+
};
92+
93+
Ok(compiler.compile(&program))
94+
}
95+
3996
pub struct QasmCompiler {
4097
/// The source map of QASM sources for error reporting.
4198
pub source_map: SourceMap,

compiler/qsc_qasm3/src/parse.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,7 @@ fn create_source_map(source: &QasmSource) -> SourceMap {
9191
for include in source.includes() {
9292
collect_source_files(include, &mut files);
9393
}
94-
// Map the main source file to the entry point expression
95-
// This may be incorrect, but it's the best we can do for now.
96-
SourceMap::new(files, Some(Arc::from(source.source())))
94+
SourceMap::new(files, None)
9795
}
9896

9997
/// Recursively collect all source files from the includes

compiler/qsc_qasm3/src/parser/completion/word_kinds.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ impl WordKinds {
125125
self.iter().filter_map(|p| match p {
126126
WordKinds::PathExpr => Some(NameKind::Path(PathKind::Expr)),
127127
WordKinds::PathSegment => Some(NameKind::PathSegment),
128-
WordKinds::PrimitiveClass => Some(NameKind::PrimitiveClass),
129128
_ => None,
130129
})
131130
}
@@ -163,8 +162,6 @@ pub enum NameKind {
163162
/// A path segment that follows a `.`
164163
/// A more specific name kind can only be inferred from a recovered AST.
165164
PathSegment,
166-
/// A primitive class, like Eq, Exp, or Add.
167-
PrimitiveClass,
168165
}
169166

170167
/// A path (see: [`Predictions`])

compiler/qsc_qasm3/src/semantic.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use crate::parser::QasmSource;
77
use lowerer::Lowerer;
88
use qsc_frontend::compile::SourceMap;
99
use qsc_frontend::error::WithSource;
10-
use symbols::SymbolTable;
1110

1211
use std::path::Path;
1312

@@ -26,7 +25,7 @@ pub struct QasmSemanticParseResult {
2625
pub source: QasmSource,
2726
pub source_map: SourceMap,
2827
pub symbols: self::symbols::SymbolTable,
29-
pub program: Option<self::ast::Program>,
28+
pub program: self::ast::Program,
3029
pub errors: Vec<WithSource<crate::Error>>,
3130
}
3231

@@ -106,25 +105,14 @@ where
106105
R: SourceResolver,
107106
{
108107
let res = crate::parser::parse_source(source, path, resolver)?;
109-
let errors = res.all_errors();
110-
// If there are syntax errors, return early
111-
if res.source.has_errors() {
112-
return Ok(QasmSemanticParseResult {
113-
source: res.source,
114-
source_map: res.source_map,
115-
symbols: SymbolTable::default(),
116-
program: None,
117-
errors,
118-
});
119-
}
120-
121108
let analyzer = Lowerer::new(res.source, res.source_map);
122109
let sem_res = analyzer.lower();
110+
let errors = sem_res.all_errors();
123111
Ok(QasmSemanticParseResult {
124112
source: sem_res.source,
125113
source_map: sem_res.source_map,
126114
symbols: sem_res.symbols,
127115
program: sem_res.program,
128-
errors: sem_res.errors,
116+
errors,
129117
})
130118
}

compiler/qsc_qasm3/src/semantic/lowerer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl Lowerer {
108108
source: self.source,
109109
source_map: self.source_map,
110110
symbols: self.symbols,
111-
program: Some(program),
111+
program,
112112
errors: self.errors,
113113
}
114114
}

compiler/qsc_qasm3/src/semantic/tests.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ pub(super) fn check_stmt_kinds(input: &str, expect: &Expect) {
133133
fn check_map<S>(
134134
input: S,
135135
expect: &Expect,
136-
selector: impl FnOnce(&super::ast::Program, &super::SymbolTable) -> String,
136+
selector: impl FnOnce(&super::ast::Program, &super::symbols::SymbolTable) -> String,
137137
) where
138138
S: AsRef<str>,
139139
{
@@ -150,14 +150,12 @@ fn check_map<S>(
150150
res.sytax_errors()
151151
);
152152

153-
let program = res.program.expect("no program");
154-
155153
if errors.is_empty() {
156-
expect.assert_eq(&selector(&program, &res.symbols));
154+
expect.assert_eq(&selector(&res.program, &res.symbols));
157155
} else {
158156
expect.assert_eq(&format!(
159157
"{}\n\n{:?}",
160-
program,
158+
res.program,
161159
errors
162160
.iter()
163161
.map(|e| Report::new(e.clone()))
@@ -180,7 +178,7 @@ fn check_map_all<P>(
180178
path: P,
181179
sources: impl IntoIterator<Item = (Arc<str>, Arc<str>)>,
182180
expect: &Expect,
183-
selector: impl FnOnce(&super::ast::Program, &super::SymbolTable) -> String,
181+
selector: impl FnOnce(&super::ast::Program, &super::symbols::SymbolTable) -> String,
184182
) where
185183
P: AsRef<Path>,
186184
{
@@ -201,14 +199,13 @@ fn check_map_all<P>(
201199
"syntax errors: {:?}",
202200
res.sytax_errors()
203201
);
204-
let program = res.program.expect("no program");
205202

206203
if errors.is_empty() {
207-
expect.assert_eq(&selector(&program, &res.symbols));
204+
expect.assert_eq(&selector(&res.program, &res.symbols));
208205
} else {
209206
expect.assert_eq(&format!(
210207
"{}\n\n{:?}",
211-
program,
208+
res.program,
212209
errors
213210
.iter()
214211
.map(|e| Report::new(e.clone()))

0 commit comments

Comments
 (0)