Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion library/std/src/Std/Diagnostics.qs
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,30 @@ operation PostSelectZ(res : Result, qubit : Qubit) : Unit {
body intrinsic;
}

/// # Summary
/// Returns a value from the host-provided configuration map.
///
/// # Description
/// Looks up `name` in a read-only configuration map provided by the host runtime.
/// If the key does not exist, returns `defaultValue`.
///
/// # Input
/// ## name
/// The configuration key.
/// ## defaultValue
/// The value to return when `name` is not present.
///
/// # Output
/// The configured value for `name`, or `defaultValue` if the key is absent.
///
/// # Example
/// ```qsharp
/// let experimentName = Std.Diagnostics.GetConfig("experiment_name", "");
/// ```
operation GetConfig<'T>(name : String, defaultValue : 'T) : 'T {
body intrinsic;
}

export
DumpMachine,
DumpRegister,
Expand All @@ -501,4 +525,5 @@ export
PhaseFlipNoise,
DepolarizingNoise,
NoNoise,
PostSelectZ;
PostSelectZ,
GetConfig;
4 changes: 2 additions & 2 deletions source/compiler/qsc/src/codegen/tests/adaptive_profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2283,11 +2283,11 @@ fn value_returning_ir_function_rir_reloads_after_same_block_store() {
dbg_scopes:
0 = SubProgram name=Main location=(2-282)
1 = SubProgram name=Foo location=(2-29)
2 = SubProgram name=MResetZ location=(1-182278)
2 = SubProgram name=MResetZ location=(1-182953)
dbg_locations:
[1]: scope=0 location=(2-363)
[2]: scope=1 location=(2-112) inlined_at=1
[3]: scope=2 location=(1-182327) inlined_at=2
[3]: scope=2 location=(1-183002) inlined_at=2
[4]: scope=1 location=(2-109) inlined_at=1
tags:
[0]: 0_i
Expand Down
24 changes: 21 additions & 3 deletions source/compiler/qsc/src/interpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ pub struct Interpreter {
/// The classical seed, if any. This needs to be passed to the evaluator for use in intrinsic
/// calls that produce classical random numbers.
classical_seed: Option<u64>,
/// Read-only config values exposed to Q# via Std.Diagnostics.GetConfig.
config_map: FxHashMap<Rc<str>, Value>,
/// The evaluator environment.
env: Env,
/// The execution graph configuration to use for evaluation.
Expand Down Expand Up @@ -432,6 +434,7 @@ impl Interpreter {
}),
quantum_seed: None,
classical_seed: None,
config_map: FxHashMap::default(),
package,
source_package: map_hir_package_to_fir(source_package_id),
eval_config,
Expand Down Expand Up @@ -705,6 +708,10 @@ impl Interpreter {
self.classical_seed = seed;
}

pub fn set_config(&mut self, key: &str, value: Value) {
self.config_map.insert(Rc::from(key), value);
}

pub fn check_source_lints(&self) -> Vec<Lint> {
if let Some(compile_unit) = self
.compiler
Expand Down Expand Up @@ -737,6 +744,7 @@ impl Interpreter {
eval(
self.source_package,
self.classical_seed,
&self.config_map,
graph,
self.eval_config,
self.compiler.package_store(),
Expand All @@ -762,6 +770,7 @@ impl Interpreter {
eval(
self.source_package,
self.classical_seed,
&self.config_map,
graph,
self.eval_config,
self.compiler.package_store(),
Expand Down Expand Up @@ -844,6 +853,7 @@ impl Interpreter {
eval(
self.package,
self.classical_seed,
&self.config_map,
graph,
self.eval_config,
self.compiler.package_store(),
Expand All @@ -861,7 +871,7 @@ impl Interpreter {
callable: Value,
args: Value,
) -> InterpretResult {
qsc_eval::invoke(
qsc_eval::invoke_with_config(
self.package,
self.classical_seed,
&self.fir_store,
Expand All @@ -871,6 +881,7 @@ impl Interpreter {
receiver,
callable,
args,
&self.config_map,
)
.map_err(|(error, call_stack)| {
eval_error(
Expand Down Expand Up @@ -1564,6 +1575,7 @@ impl Interpreter {
eval(
self.package,
classical_seed,
&self.config_map,
graph,
self.eval_config,
self.compiler.package_store(),
Expand Down Expand Up @@ -1595,6 +1607,7 @@ impl Interpreter {
eval(
package_id,
self.classical_seed,
&self.config_map,
graph,
config,
self.compiler.package_store(),
Expand Down Expand Up @@ -1638,7 +1651,7 @@ impl Interpreter {
Some(seed) => Some(seed),
None => self.classical_seed,
};
qsc_eval::invoke(
qsc_eval::invoke_with_config(
self.package,
classical_seed,
&self.fir_store,
Expand All @@ -1648,6 +1661,7 @@ impl Interpreter {
receiver,
callable,
args,
&self.config_map,
)
.map_err(|(error, call_stack)| {
eval_error(
Expand Down Expand Up @@ -1851,6 +1865,7 @@ impl Debugger {
entry_exec_graph,
ExecGraphConfig::Debug,
None,
FxHashMap::default(),
ErrorBehavior::StopOnError,
),
})
Expand All @@ -1868,6 +1883,7 @@ impl Debugger {
entry_exec_graph,
ExecGraphConfig::Debug,
None,
FxHashMap::default(),
ErrorBehavior::StopOnError,
),
}
Expand Down Expand Up @@ -2004,6 +2020,7 @@ impl Debugger {
fn eval<B: Backend>(
package: PackageId,
classical_seed: Option<u64>,
config_map: &FxHashMap<Rc<str>, Value>,
exec_graph: ExecGraph,
exec_graph_config: ExecGraphConfig,
package_store: &PackageStore,
Expand All @@ -2012,7 +2029,7 @@ fn eval<B: Backend>(
tracing_backend: &mut TracingBackend<'_, B>,
receiver: &mut impl Receiver,
) -> InterpretResult {
qsc_eval::eval(
qsc_eval::eval_with_config(
package,
classical_seed,
exec_graph,
Expand All @@ -2021,6 +2038,7 @@ fn eval<B: Backend>(
env,
tracing_backend,
receiver,
config_map,
)
.map_err(|(error, call_stack)| eval_error(package_store, fir_store, call_stack, error))
}
Expand Down
52 changes: 52 additions & 0 deletions source/compiler/qsc/src/interpret/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,58 @@ mod given_interpreter {
is_only_value(&result, &output, &Value::Int(3));
}

#[test]
fn config_values_are_available_via_get_config() {
let mut interpreter = get_interpreter();

// Integer config.
interpreter.set_config("int_config", Value::Int(123));
let (result, output) = line(
&mut interpreter,
"Std.Diagnostics.GetConfig(\"int_config\", 0)",
);
is_only_value(&result, &output, &Value::Int(123));

// Boolean config.
interpreter.set_config("bool_config", Value::Bool(true));
let (result, output) = line(
&mut interpreter,
"Std.Diagnostics.GetConfig(\"bool_config\", false)",
);
is_only_value(&result, &output, &Value::Bool(true));

// String config.
interpreter.set_config("string_config", Value::String("value".into()));
let (result, output) = line(
&mut interpreter,
"Std.Diagnostics.GetConfig(\"string_config\", \"\")",
);
is_only_value(&result, &output, &Value::String("value".into()));

// Double config.
interpreter.set_config("double_config", Value::Double(124.1));
let (result, output) = line(
&mut interpreter,
"Std.Diagnostics.GetConfig(\"double_config\", 0.0)",
);
is_only_value(&result, &output, &Value::Double(124.1));

// Default value.
let (result, output) = line(
&mut interpreter,
"Std.Diagnostics.GetConfig(\"unknown\", 15)",
);
is_only_value(&result, &output, &Value::Int(15));

// Can overwrite an existing value.
interpreter.set_config("int_config", Value::Int(100));
let (result, output) = line(
&mut interpreter,
"Std.Diagnostics.GetConfig(\"int_config\", 0)",
);
is_only_value(&result, &output, &Value::Int(100));
}

#[test]
fn let_bindings_update_interpreter() {
let mut interpreter = get_interpreter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use qsc_fir::fir::{self, ExecGraphConfig};
use qsc_frontend::compile::{self, PackageStore, compile};
use qsc_lowerer::map_hir_package_to_fir;
use qsc_passes::{PackageType, run_core_passes, run_default_passes};
use rustc_hash::FxHashMap;

use crate::builder::{LogicalStack, LogicalStackWithSourceLookup};

Expand Down Expand Up @@ -147,6 +148,7 @@ fn check_trace(file: &str, expr: &str, exec_graph_config: ExecGraphConfig, expec
entry,
exec_graph_config,
None,
FxHashMap::default(),
ErrorBehavior::FailOnError,
);

Expand Down
9 changes: 9 additions & 0 deletions source/compiler/qsc_eval/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub(crate) fn call<B: Backend>(
call_stack: &[Frame],
sim: &mut TracingBackend<'_, B>,
rng: &mut StdRng,
config_map: &FxHashMap<Rc<str>, Value>,
out: &mut dyn Receiver,
) -> Result<Value, Error> {
match name {
Expand Down Expand Up @@ -166,6 +167,14 @@ pub(crate) fn call<B: Backend>(
let p = arg.unwrap_double();
Ok(Value::Bool(rng.random_bool(p)))
}
"GetConfig" => {
let [name, default_value] = unwrap_tuple(arg);
let name = name.unwrap_string();
Ok(config_map
.get(name.as_ref())
.cloned()
.unwrap_or(default_value))
}
#[allow(clippy::cast_possible_truncation)]
"Truncate" => Ok(Value::Int(arg.unwrap_double() as i64)),
"__quantum__qis__ccx__body" => three_qubit_gate(
Expand Down
Loading
Loading