Parameteric function with full specialization fails to compile
fn array_subnormals_to_zero_using_map<N:u32, EXP_SZ:u32, FRAC_SZ:u32>(
terms : apfloat::APFloat<EXP_SZ, FRAC_SZ>[N])
-> apfloat::APFloat<EXP_SZ, FRAC_SZ>[N] {
map(terms, apfloat::subnormals_to_zero<EXP_SZ, FRAC_SZ>)
}
fails with
0019: terms : apfloat::APFloat<EXP_SZ, FRAC_SZ>[N])
0020: -> apfloat::APFloat<EXP_SZ, FRAC_SZ>[N] {
0021: map(terms, apfloat::subnormals_to_zero<EXP_SZ, FRAC_SZ>)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ ParseError: Expected '(', got ')': Expected a '(' after parametrics for function invocation.
0022: }
0023:
however
fn array_subnormals_to_zero_using_map<N:u32, EXP_SZ:u32, FRAC_SZ:u32>(
terms : apfloat::APFloat<EXP_SZ, FRAC_SZ>[N])
-> apfloat::APFloat<EXP_SZ, FRAC_SZ>[N] {
map(terms, apfloat::subnormals_to_zero)
}
compiles fine.
Just to note what's going on, the parser doesn't support reference to an instantiated parametric function like that, so as a workaround you'd need to make a wrapper that has the full instantiation. It seems fortunate that the implicit instantiation works right though, so that probably is what you want here and the bug is filed more for completeness? LMK if I'm getting that wrong.
I believe I have a case where automatic deduction of parameters is not going to work.
Here is variant one, where the parser complains about the parametrics
import apfloat
import std
fn foo<N:u32, K:u32,
IN_EXP_SZ:u32, IN_FRAC_SZ:u32,
OUT_FRAC_SZ:u32, OUT_SZ:u32 = {OUT_FRAC_SZ + u32:1 + K + u32:1 + std::clog2(N)}>(
x : apfloat::APFloat<IN_EXP_SZ, IN_FRAC_SZ>) -> sN[OUT_SZ] {
sN[OUT_SZ] : [sN[OUT_SZ]:0, ...]
}
fn bar<N:u32, K:u32,
IN_EXP_SZ:u32, IN_FRAC_SZ:u32,
OUT_EXP_SZ:u32, OUT_FRAC_SZ:u32>(
terms : apfloat::APFloat<IN_EXP_SZ, IN_FRAC_SZ>[N]) -> bool {
let x = map(terms, foo<N, K, IN_EXP_SZ, IN_FRAC_SZ, OUT_FRAC_SZ>)
//let x = map(terms, foo);
false
}
pub fn main() -> bool{
const N = u32:10;
const K = u32:5;
const IN_EXP_SZ = u32:1;
const IN_FRAC_SZ = u32:2;
const OUT_FRAC_SZ = u32:3;
const OUT_SZ = u32:3;
type Float = apfloat::APFloat<IN_EXP_SZ, IN_FRAC_SZ>;
let one = apfloat::one<IN_EXP_SZ, IN_FRAC_SZ>(u1:1);
let terms = Float[N] : [one, ...];
bar(terms)
}
with
0014: OUT_EXP_SZ:u32, OUT_FRAC_SZ:u32>(
0015: terms : apfloat::APFloat<IN_EXP_SZ, IN_FRAC_SZ>[N]) -> bool {
0016: let x = map(terms, foo<N, K, IN_EXP_SZ, IN_FRAC_SZ, OUT_FRAC_SZ>)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ ParseError: Expected '(', got ')': Expected a '(' after parametrics for function invocation.
0017: //let x = map(terms, foo);
0018: false
and here is variant 2
mport apfloat
import std
fn foo<N:u32, K:u32,
IN_EXP_SZ:u32, IN_FRAC_SZ:u32,
OUT_FRAC_SZ:u32, OUT_SZ:u32 = {OUT_FRAC_SZ + u32:1 + K + u32:1 + std::clog2(N)}>(
x : apfloat::APFloat<IN_EXP_SZ, IN_FRAC_SZ>) -> sN[OUT_SZ] {
sN[OUT_SZ] : [sN[OUT_SZ]:0, ...]
}
fn bar<N:u32, K:u32,
IN_EXP_SZ:u32, IN_FRAC_SZ:u32,
OUT_EXP_SZ:u32, OUT_FRAC_SZ:u32>(
terms : apfloat::APFloat<IN_EXP_SZ, IN_FRAC_SZ>[N]) -> bool {
// let x = map(terms, foo<N, K, IN_EXP_SZ, IN_FRAC_SZ, OUT_FRAC_SZ>)
let x = map(terms, foo);
false
}
pub fn main() -> bool{
const N = u32:10;
const K = u32:5;
const IN_EXP_SZ = u32:1;
const IN_FRAC_SZ = u32:2;
const OUT_FRAC_SZ = u32:3;
const OUT_SZ = u32:3;
type Float = apfloat::APFloat<IN_EXP_SZ, IN_FRAC_SZ>;
let one = apfloat::one<IN_EXP_SZ, IN_FRAC_SZ>(u1:1);
let terms = Float[N] : [one, ...];
bar(terms)
}
where the parser now complains that not all the parameters were specified.
0015: terms : apfloat::APFloat<IN_EXP_SZ, IN_FRAC_SZ>[N]) -> bool {
0016: // let x = map(terms, foo<N, K, IN_EXP_SZ, IN_FRAC_SZ, OUT_FRAC_SZ>)
0017: let x = map(terms, foo);
~~~~~~~~~~~~~~~~~~~~~^----------^ TypeInferenceError: sN[OUT_SZ] Instantiated return type did not have all parametrics resolved.
0018: false
0019: }
Is there a way to :heavy_plus_sign: 1 an issue ? I just ran into the same thing.
I had to make a number of changes to the example in variant 1 due to valid compile errors but the following does now work after https://github.com/google/xls/commit/28b4476ed8712f4e31a43898cde0274a7b4ac81f:
import apfloat;
import std;
fn foo
<N: u32, K: u32, IN_EXP_SZ: u32, IN_FRAC_SZ: u32, OUT_FRAC_SZ: u32,
OUT_SZ: u32 = {OUT_FRAC_SZ + u32:1 + K + u32:1 + std::clog2(N)}>
(x: apfloat::APFloat<IN_EXP_SZ, IN_FRAC_SZ>) -> sN[OUT_SZ] {
sN[OUT_SZ]:0
}
fn bar<N: u32, K: u32, IN_EXP_SZ: u32, IN_FRAC_SZ: u32, OUT_EXP_SZ: u32, OUT_FRAC_SZ: u32>
(terms: apfloat::APFloat<IN_EXP_SZ, IN_FRAC_SZ>[N]) -> () {
let x = map(terms, foo<N, K, IN_EXP_SZ, IN_FRAC_SZ, OUT_FRAC_SZ>);
// let x = map(terms, foo);
}
pub fn main() -> () {
const N = u32:10;
const K = u32:5;
const IN_EXP_SZ = u32:1;
const IN_FRAC_SZ = u32:2;
const OUT_EXP_SZ = u32:2;
const OUT_FRAC_SZ = u32:3;
const OUT_SZ = u32:3;
type Float = apfloat::APFloat<IN_EXP_SZ, IN_FRAC_SZ>;
let one = apfloat::one<IN_EXP_SZ, IN_FRAC_SZ>(u1:1);
let terms = Float[N]:[one, ...];
bar<N, K, IN_EXP_SZ, IN_FRAC_SZ, OUT_EXP_SZ, OUT_FRAC_SZ>(terms)
}