@@ -370,6 +370,8 @@ Result<typename Ctx::LabelIdxT> labelidx(Ctx&, bool inDelegate = false);
370370template <typename Ctx> Result<typename Ctx::TagIdxT> tagidx (Ctx&);
371371template <typename Ctx>
372372Result<typename Ctx::TypeUseT> typeuse (Ctx&, bool allowNames = true );
373+ template <typename Ctx>
374+ Result<std::pair<typename Ctx::TypeUse, Exactness>> exacttypeuse (Ctx&);
373375MaybeResult<ImportNames> inlineImport (Lexer&);
374376Result<std::vector<Name>> inlineExports (Lexer&);
375377template <typename Ctx> Result<> comptype (Ctx&);
@@ -3007,6 +3009,24 @@ Result<typename Ctx::TypeUseT> typeuse(Ctx& ctx, bool allowNames) {
30073009 return ctx.makeTypeUse (pos, type, namedParams.getPtr (), resultTypes.getPtr ());
30083010}
30093011
3012+ // exacttypeuse ::= typeuse |
3013+ // '(' 'exact' typeuse ')'
3014+ template <typename Ctx>
3015+ Result<std::pair<typename Ctx::TypeUseT, Exactness>> exacttypeuse (Ctx& ctx) {
3016+ auto exact = Inexact;
3017+ if (ctx.in .takeSExprStart (" exact" sv)) {
3018+ exact = Exact;
3019+ }
3020+ auto type = typeuse (ctx, true );
3021+ CHECK_ERR (type);
3022+ if (exact == Exact) {
3023+ if (!ctx.in .takeRParen ()) {
3024+ return ctx.in .err (" expected end of exact type use" );
3025+ }
3026+ }
3027+ return std::make_pair (*type, exact);
3028+ }
3029+
30103030// ('(' 'import' mod:name nm:name ')')?
30113031inline MaybeResult<ImportNames> inlineImport (Lexer& in) {
30123032 if (!in.takeSExprStart (" import" sv)) {
@@ -3221,7 +3241,7 @@ template<typename Ctx> MaybeResult<typename Ctx::LocalsT> locals(Ctx& ctx) {
32213241}
32223242
32233243// import ::= '(' 'import' mod:name nm:name importdesc ')'
3224- // importdesc ::= '(' 'func' id? typeuse ')'
3244+ // importdesc ::= '(' 'func' id? exacttypeuse ')'
32253245// | '(' 'table' id? tabletype ')'
32263246// | '(' 'memory' id? memtype ')'
32273247// | '(' 'global' id? globaltype ')'
@@ -3246,11 +3266,12 @@ template<typename Ctx> MaybeResult<> import_(Ctx& ctx) {
32463266
32473267 if (ctx.in .takeSExprStart (" func" sv)) {
32483268 auto name = ctx.in .takeID ();
3249- auto type = typeuse (ctx);
3250- CHECK_ERR (type);
3269+ auto use = exacttypeuse (ctx);
3270+ CHECK_ERR (use);
3271+ auto [type, exact] = *use;
32513272 // TODO: function import annotations
32523273 CHECK_ERR (ctx.addFunc (
3253- name ? *name : Name{}, {}, &names, * type, std::nullopt , {}, pos));
3274+ name ? *name : Name{}, {}, &names, type, exact , std::nullopt , {}, pos));
32543275 } else if (ctx.in .takeSExprStart (" table" sv)) {
32553276 auto name = ctx.in .takeID ();
32563277 auto type = tabletype (ctx);
@@ -3289,7 +3310,7 @@ template<typename Ctx> MaybeResult<> import_(Ctx& ctx) {
32893310// func ::= '(' 'func' id? ('(' 'export' name ')')*
32903311// x,I:typeuse t*:vec(local) (in:instr)* ')'
32913312// | '(' 'func' id? ('(' 'export' name ')')*
3292- // '(' 'import' mod:name nm:name ')' typeuse ')'
3313+ // '(' 'import' mod:name nm:name ')' exacttypeuse ')'
32933314template <typename Ctx> MaybeResult<> func (Ctx& ctx) {
32943315 auto pos = ctx.in .getPos ();
32953316 auto annotations = ctx.in .getAnnotations ();
@@ -3309,11 +3330,19 @@ template<typename Ctx> MaybeResult<> func(Ctx& ctx) {
33093330 auto import = inlineImport (ctx.in );
33103331 CHECK_ERR (import );
33113332
3312- auto type = typeuse (ctx);
3313- CHECK_ERR (type);
3314-
3333+ typename Ctx::TypeUseT type;
3334+ Exactness exact = Exact;
33153335 std::optional<typename Ctx::LocalsT> localVars;
3316- if (!import ) {
3336+
3337+ if (import ) {
3338+ auto use = exacttypeuse (ctx);
3339+ CHECK_ERR (use);
3340+ type = use->first ;
3341+ exact = use->second ;
3342+ } else {
3343+ auto use = typeuse (ctx);
3344+ CHECK_ERR (use);
3345+ type = *use;
33173346 if (auto l = locals (ctx)) {
33183347 CHECK_ERR (l);
33193348 localVars = *l;
@@ -3331,7 +3360,8 @@ template<typename Ctx> MaybeResult<> func(Ctx& ctx) {
33313360 CHECK_ERR (ctx.addFunc (name,
33323361 *exports,
33333362 import .getPtr (),
3334- *type,
3363+ type,
3364+ exact,
33353365 localVars,
33363366 std::move (annotations),
33373367 pos));
0 commit comments