// ============================================================================
// keywords.mbt - Keyword Hash Table
// ============================================================================

// Keyword hash table using a Map

///|
pub struct KeywordTable {
  map : @hashmap.HashMap[String, TokenType]
}

///|
fn KeywordTable::new() -> KeywordTable {
  let map = @hashmap.new(capacity=512)

  // Module structure
  map.set("module", TokenType::Module)
  map.set("type", Type)
  map.set("func", Func)
  map.set("param", Param)
  map.set("result", Result)
  map.set("local", Local)
  map.set("global", Global)
  map.set("tag", Tag)
  map.set("table", Table)
  map.set("memory", Memory)
  map.set("elem", Elem)
  map.set("data", Data)
  map.set("start", Start)
  map.set("import", Import)
  map.set("export", Export)
  map.set("mut", Mut)
  map.set("offset", Offset)
  map.set("item", Item)
  map.set("declare", Declare)
  map.set("quote", Quote)
  map.set("register", Register)
  map.set("invoke", Invoke)
  map.set("get", Get)
  map.set("binary", Binary)
  map.set("input", Input)
  map.set("output", Output)

  // Assertions
  map.set("assert_malformed", AssertMalformed)
  map.set("assert_invalid", AssertInvalid)
  map.set("assert_unlinkable", AssertUnlinkable)
  map.set("assert_return", AssertReturn)
  map.set("assert_trap", AssertTrap)
  map.set("assert_exception", AssertException)
  map.set("assert_exhaustion", AssertExhaustion)

  // Control keywords
  map.set("block", Block)
  map.set("loop", Loop)
  map.set("if", If)
  map.set("try", Try)
  map.set("do", Do)
  map.set("then", Then)
  map.set("else", Else)
  map.set("end", End)
  map.set("catch", Catch)
  map.set("catch_ref", CatchRef)
  map.set("catch_all", CatchAll)
  map.set("catch_all_ref", CatchAllRef)
  map.set("delegate", Delegate)
  map.set("rethrow", Rethrow)

  // Value types
  map.set("i32", ValueType(I32))
  map.set("i64", ValueType(I64))
  map.set("f32", ValueType(F32))
  map.set("f64", ValueType(F64))
  map.set("v128", ValueType(V128))
  map.set("funcref", ValueType(FuncRef))
  map.set("externref", ValueType(ExternRef))
  map.set("exnref", ValueType(ExnRef))

  // Control instructions
  map.set("unreachable", Opcode(Unreachable))
  map.set("nop", Opcode(Nop))
  map.set("br", Opcode(Br))
  map.set("br_if", Opcode(BrIf))
  map.set("br_on_null", Opcode(BrOnNull))
  map.set("br_on_non_null", Opcode(BrOnNonNull))
  map.set("br_on_cast_desc_eq", Opcode(BrOnCastDescEq))
  map.set("br_on_cast_desc_eq_fail", Opcode(BrOnCastDescEqFail))
  map.set("br_table", Opcode(BrTable))
  map.set("return", Opcode(Return))
  map.set("call", Opcode(Call))
  map.set("call_indirect", Opcode(CallIndirect))
  map.set("return_call", Opcode(ReturnCall))
  map.set("return_call_indirect", Opcode(ReturnCallIndirect))
  map.set("call_ref", Opcode(CallRef))
  map.set("return_call_ref", Opcode(ReturnCallRef))
  map.set("throw", Opcode(Throw))
  map.set("throw_ref", Opcode(ThrowRef))
  map.set("try_table", Opcode(TryTable))

  // Reference instructions
  map.set("ref.null", Opcode(RefNull))
  map.set("ref.is_null", Opcode(RefIsNull))
  map.set("ref.func", Opcode(RefFunc))
  map.set("ref.eq", Opcode(RefEq))
  map.set("ref.as_non_null", Opcode(RefAsNonNull))
  map.set("string.const", Opcode(StringConst))
  map.set("string.measure_wtf16", Opcode(StringMeasureWtf16))
  map.set("string.concat", Opcode(StringConcat))
  map.set("string.eq", Opcode(StringEq))
  map.set("string.as_wtf16", Opcode(StringAsWtf16))
  map.set("stringview_wtf16.get_codeunit", Opcode(StringViewWtf16GetCodeunit))
  map.set("stringview_wtf16.slice", Opcode(StringViewWtf16Slice))
  map.set("string.new_utf8_array", Opcode(StringNewUtf8Array))
  map.set("string.new_wtf16_array", Opcode(StringNewWtf16Array))
  map.set("string.encode_utf8_array", Opcode(StringEncodeUtf8Array))
  map.set("string.encode_wtf16_array", Opcode(StringEncodeWtf16Array))
  map.set("string.new_lossy_utf8_array", Opcode(StringNewLossyUtf8Array))
  map.set("string.new_wtf8_array", Opcode(StringNewWtf8Array))
  map.set("string.encode_lossy_utf8_array", Opcode(StringEncodeLossyUtf8Array))
  map.set("string.encode_wtf8_array", Opcode(StringEncodeWtf8Array))
  map.set("any.convert_extern", Opcode(AnyConvertExtern))
  map.set("extern.convert_any", Opcode(ExternConvertAny))
  map.set("ref.i31", Opcode(RefI31))
  map.set("ref.i31_shared", Opcode(RefI31Shared))
  map.set("i31.get_s", Opcode(I31GetS))
  map.set("i31.get_u", Opcode(I31GetU))
  map.set("struct.new", Opcode(StructNew))
  map.set("struct.new_default", Opcode(StructNewDefault))
  map.set("struct.get", Opcode(StructGet))
  map.set("struct.get_s", Opcode(StructGetS))
  map.set("struct.get_u", Opcode(StructGetU))
  map.set("waitqueue.new", Opcode(WaitqueueNew))
  map.set("waitqueue.notify", Opcode(WaitqueueNotify))
  map.set("struct.wait", Opcode(StructWait))
  map.set("publish", Opcode(Publish))
  map.set("array.atomic.get", Opcode(ArrayAtomicGet))
  map.set("array.atomic.get_s", Opcode(ArrayAtomicGetS))
  map.set("array.atomic.get_u", Opcode(ArrayAtomicGetU))
  map.set("struct.atomic.set", Opcode(StructAtomicSet))
  map.set("array.atomic.set", Opcode(ArrayAtomicSet))
  register_memory_atomic_keywords(map)
  map.set("struct.atomic.get", Opcode(StructAtomicGet))
  map.set("struct.atomic.get_s", Opcode(StructAtomicGetS))
  map.set("struct.atomic.get_u", Opcode(StructAtomicGetU))
  map.set("struct.atomic.rmw.add", Opcode(StructAtomicRmwAdd))
  map.set("struct.atomic.rmw.sub", Opcode(StructAtomicRmwSub))
  map.set("struct.atomic.rmw.and", Opcode(StructAtomicRmwAnd))
  map.set("struct.atomic.rmw.or", Opcode(StructAtomicRmwOr))
  map.set("struct.atomic.rmw.xor", Opcode(StructAtomicRmwXor))
  map.set("struct.atomic.rmw.xchg", Opcode(StructAtomicRmwXchg))
  map.set("struct.atomic.rmw.cmpxchg", Opcode(StructAtomicRmwCmpxchg))
  map.set("array.atomic.rmw.add", Opcode(ArrayAtomicRmwAdd))
  map.set("array.atomic.rmw.sub", Opcode(ArrayAtomicRmwSub))
  map.set("array.atomic.rmw.and", Opcode(ArrayAtomicRmwAnd))
  map.set("array.atomic.rmw.or", Opcode(ArrayAtomicRmwOr))
  map.set("array.atomic.rmw.xor", Opcode(ArrayAtomicRmwXor))
  map.set("array.atomic.rmw.xchg", Opcode(ArrayAtomicRmwXchg))
  map.set("array.atomic.rmw.cmpxchg", Opcode(ArrayAtomicRmwCmpxchg))
  map.set("struct.new_desc", Opcode(StructNewDesc))
  map.set("array.new", Opcode(ArrayNew))
  map.set("array.new_default", Opcode(ArrayNewDefault))
  map.set("array.new_fixed", Opcode(ArrayNewFixed))
  map.set("array.new_data", Opcode(ArrayNewData))
  map.set("array.new_elem", Opcode(ArrayNewElem))
  map.set("struct.new_default_desc", Opcode(StructNewDefaultDesc))
  map.set("ref.get_desc", Opcode(RefGetDesc))
  map.set("ref.test_desc", Opcode(RefTestDesc))
  map.set("ref.test_desc_null", Opcode(RefTestDescNull))
  map.set("ref.cast_desc_eq", Opcode(RefCastDescEq))
  map.set("ref.cast_desc_eq_null", Opcode(RefCastDescEqNull))

  // Parametric instructions
  map.set("drop", Opcode(Drop))
  map.set("select", Opcode(Select))

  // Variable instructions
  map.set("local.get", Opcode(LocalGet))
  map.set("local.set", Opcode(LocalSet))
  map.set("local.tee", Opcode(LocalTee))
  map.set("global.get", Opcode(GlobalGet))
  map.set("global.set", Opcode(GlobalSet))

  // Table instructions
  map.set("table.get", Opcode(TableGet))
  map.set("table.set", Opcode(TableSet))
  map.set("table.size", Opcode(TableSize))
  map.set("table.grow", Opcode(TableGrow))
  map.set("table.fill", Opcode(TableFill))
  map.set("table.copy", Opcode(TableCopy))
  map.set("table.init", Opcode(TableInit))
  map.set("elem.drop", Opcode(ElemDrop))

  // Memory instructions
  map.set("i32.load", Opcode(I32Load))
  map.set("i64.load", Opcode(I64Load))
  map.set("f32.load", Opcode(F32Load))
  map.set("f64.load", Opcode(F64Load))
  map.set("i32.load8_s", Opcode(I32Load8S))
  map.set("i32.load8_u", Opcode(I32Load8U))
  map.set("i32.load16_s", Opcode(I32Load16S))
  map.set("i32.load16_u", Opcode(I32Load16U))
  map.set("i64.load8_s", Opcode(I64Load8S))
  map.set("i64.load8_u", Opcode(I64Load8U))
  map.set("i64.load16_s", Opcode(I64Load16S))
  map.set("i64.load16_u", Opcode(I64Load16U))
  map.set("i64.load32_s", Opcode(I64Load32S))
  map.set("i64.load32_u", Opcode(I64Load32U))
  map.set("i32.store", Opcode(I32Store))
  map.set("i64.store", Opcode(I64Store))
  map.set("f32.store", Opcode(F32Store))
  map.set("f64.store", Opcode(F64Store))
  map.set("i32.store8", Opcode(I32Store8))
  map.set("i32.store16", Opcode(I32Store16))
  map.set("i64.store8", Opcode(I64Store8))
  map.set("i64.store16", Opcode(I64Store16))
  map.set("i64.store32", Opcode(I64Store32))
  map.set("memory.size", Opcode(MemorySize))
  map.set("memory.grow", Opcode(MemoryGrow))
  map.set("memory.fill", Opcode(MemoryFill))
  map.set("memory.copy", Opcode(MemoryCopy))
  map.set("memory.init", Opcode(MemoryInit))
  map.set("data.drop", Opcode(DataDrop))

  // Numeric - Constants
  map.set("i32.const", Opcode(I32Const))
  map.set("i64.const", Opcode(I64Const))
  map.set("f32.const", Opcode(F32Const))
  map.set("f64.const", Opcode(F64Const))

  // i32 comparison
  map.set("i32.eqz", Opcode(I32Eqz))
  map.set("i32.eq", Opcode(I32Eq))
  map.set("i32.ne", Opcode(I32Ne))
  map.set("i32.lt_s", Opcode(I32LtS))
  map.set("i32.lt_u", Opcode(I32LtU))
  map.set("i32.gt_s", Opcode(I32GtS))
  map.set("i32.gt_u", Opcode(I32GtU))
  map.set("i32.le_s", Opcode(I32LeS))
  map.set("i32.le_u", Opcode(I32LeU))
  map.set("i32.ge_s", Opcode(I32GeS))
  map.set("i32.ge_u", Opcode(I32GeU))

  // i32 arithmetic
  map.set("i32.clz", Opcode(I32Clz))
  map.set("i32.ctz", Opcode(I32Ctz))
  map.set("i32.popcnt", Opcode(I32Popcnt))
  map.set("i32.add", Opcode(I32Add))
  map.set("i32.sub", Opcode(I32Sub))
  map.set("i32.mul", Opcode(I32Mul))
  map.set("i32.div_s", Opcode(I32DivS))
  map.set("i32.div_u", Opcode(I32DivU))
  map.set("i32.rem_s", Opcode(I32RemS))
  map.set("i32.rem_u", Opcode(I32RemU))
  map.set("i32.and", Opcode(I32And))
  map.set("i32.or", Opcode(I32Or))
  map.set("i32.xor", Opcode(I32Xor))
  map.set("i32.shl", Opcode(I32Shl))
  map.set("i32.shr_s", Opcode(I32ShrS))
  map.set("i32.shr_u", Opcode(I32ShrU))
  map.set("i32.rotl", Opcode(I32Rotl))
  map.set("i32.rotr", Opcode(I32Rotr))

  // i64 comparison
  map.set("i64.eqz", Opcode(I64Eqz))
  map.set("i64.eq", Opcode(I64Eq))
  map.set("i64.ne", Opcode(I64Ne))
  map.set("i64.lt_s", Opcode(I64LtS))
  map.set("i64.lt_u", Opcode(I64LtU))
  map.set("i64.gt_s", Opcode(I64GtS))
  map.set("i64.gt_u", Opcode(I64GtU))
  map.set("i64.le_s", Opcode(I64LeS))
  map.set("i64.le_u", Opcode(I64LeU))
  map.set("i64.ge_s", Opcode(I64GeS))
  map.set("i64.ge_u", Opcode(I64GeU))

  // i64 arithmetic
  map.set("i64.clz", Opcode(I64Clz))
  map.set("i64.ctz", Opcode(I64Ctz))
  map.set("i64.popcnt", Opcode(I64Popcnt))
  map.set("i64.add", Opcode(I64Add))
  map.set("i64.sub", Opcode(I64Sub))
  map.set("i64.mul", Opcode(I64Mul))
  map.set("i64.div_s", Opcode(I64DivS))
  map.set("i64.div_u", Opcode(I64DivU))
  map.set("i64.rem_s", Opcode(I64RemS))
  map.set("i64.rem_u", Opcode(I64RemU))
  map.set("i64.and", Opcode(I64And))
  map.set("i64.or", Opcode(I64Or))
  map.set("i64.xor", Opcode(I64Xor))
  map.set("i64.shl", Opcode(I64Shl))
  map.set("i64.shr_s", Opcode(I64ShrS))
  map.set("i64.shr_u", Opcode(I64ShrU))
  map.set("i64.rotl", Opcode(I64Rotl))
  map.set("i64.rotr", Opcode(I64Rotr))

  // f32 comparison
  map.set("f32.eq", Opcode(F32Eq))
  map.set("f32.ne", Opcode(F32Ne))
  map.set("f32.lt", Opcode(F32Lt))
  map.set("f32.gt", Opcode(F32Gt))
  map.set("f32.le", Opcode(F32Le))
  map.set("f32.ge", Opcode(F32Ge))

  // f32 arithmetic
  map.set("f32.abs", Opcode(F32Abs))
  map.set("f32.neg", Opcode(F32Neg))
  map.set("f32.ceil", Opcode(F32Ceil))
  map.set("f32.floor", Opcode(F32Floor))
  map.set("f32.trunc", Opcode(F32Trunc))
  map.set("f32.nearest", Opcode(F32Nearest))
  map.set("f32.sqrt", Opcode(F32Sqrt))
  map.set("f32.add", Opcode(F32Add))
  map.set("f32.sub", Opcode(F32Sub))
  map.set("f32.mul", Opcode(F32Mul))
  map.set("f32.div", Opcode(F32Div))
  map.set("f32.min", Opcode(F32Min))
  map.set("f32.max", Opcode(F32Max))
  map.set("f32.copysign", Opcode(F32Copysign))

  // f64 comparison
  map.set("f64.eq", Opcode(F64Eq))
  map.set("f64.ne", Opcode(F64Ne))
  map.set("f64.lt", Opcode(F64Lt))
  map.set("f64.gt", Opcode(F64Gt))
  map.set("f64.le", Opcode(F64Le))
  map.set("f64.ge", Opcode(F64Ge))

  // f64 arithmetic
  map.set("f64.abs", Opcode(F64Abs))
  map.set("f64.neg", Opcode(F64Neg))
  map.set("f64.ceil", Opcode(F64Ceil))
  map.set("f64.floor", Opcode(F64Floor))
  map.set("f64.trunc", Opcode(F64Trunc))
  map.set("f64.nearest", Opcode(F64Nearest))
  map.set("f64.sqrt", Opcode(F64Sqrt))
  map.set("f64.add", Opcode(F64Add))
  map.set("f64.sub", Opcode(F64Sub))
  map.set("f64.mul", Opcode(F64Mul))
  map.set("f64.div", Opcode(F64Div))
  map.set("f64.min", Opcode(F64Min))
  map.set("f64.max", Opcode(F64Max))
  map.set("f64.copysign", Opcode(F64Copysign))

  // Conversions
  map.set("i32.wrap_i64", Opcode(I32WrapI64))
  map.set("i32.trunc_f32_s", Opcode(I32TruncF32S))
  map.set("i32.trunc_f32_u", Opcode(I32TruncF32U))
  map.set("i32.trunc_f64_s", Opcode(I32TruncF64S))
  map.set("i32.trunc_f64_u", Opcode(I32TruncF64U))
  map.set("i64.extend_i32_s", Opcode(I64ExtendI32S))
  map.set("i64.extend_i32_u", Opcode(I64ExtendI32U))
  map.set("i64.trunc_f32_s", Opcode(I64TruncF32S))
  map.set("i64.trunc_f32_u", Opcode(I64TruncF32U))
  map.set("i64.trunc_f64_s", Opcode(I64TruncF64S))
  map.set("i64.trunc_f64_u", Opcode(I64TruncF64U))
  map.set("f32.convert_i32_s", Opcode(F32ConvertI32S))
  map.set("f32.convert_i32_u", Opcode(F32ConvertI32U))
  map.set("f32.convert_i64_s", Opcode(F32ConvertI64S))
  map.set("f32.convert_i64_u", Opcode(F32ConvertI64U))
  map.set("f32.demote_f64", Opcode(F32DemoteF64))
  map.set("f64.convert_i32_s", Opcode(F64ConvertI32S))
  map.set("f64.convert_i32_u", Opcode(F64ConvertI32U))
  map.set("f64.convert_i64_s", Opcode(F64ConvertI64S))
  map.set("f64.convert_i64_u", Opcode(F64ConvertI64U))
  map.set("f64.promote_f32", Opcode(F64PromoteF32))
  map.set("i32.reinterpret_f32", Opcode(I32ReinterpretF32))
  map.set("i64.reinterpret_f64", Opcode(I64ReinterpretF64))
  map.set("f32.reinterpret_i32", Opcode(F32ReinterpretI32))
  map.set("f64.reinterpret_i64", Opcode(F64ReinterpretI64))

  // Sign extension
  map.set("i32.extend8_s", Opcode(I32Extend8S))
  map.set("i32.extend16_s", Opcode(I32Extend16S))
  map.set("i64.extend8_s", Opcode(I64Extend8S))
  map.set("i64.extend16_s", Opcode(I64Extend16S))
  map.set("i64.extend32_s", Opcode(I64Extend32S))

  // Saturating truncation
  map.set("i32.trunc_sat_f32_s", Opcode(I32TruncSatF32S))
  map.set("i32.trunc_sat_f32_u", Opcode(I32TruncSatF32U))
  map.set("i32.trunc_sat_f64_s", Opcode(I32TruncSatF64S))
  map.set("i32.trunc_sat_f64_u", Opcode(I32TruncSatF64U))
  map.set("i64.trunc_sat_f32_s", Opcode(I64TruncSatF32S))
  map.set("i64.trunc_sat_f32_u", Opcode(I64TruncSatF32U))
  map.set("i64.trunc_sat_f64_s", Opcode(I64TruncSatF64S))
  map.set("i64.trunc_sat_f64_u", Opcode(I64TruncSatF64U))

  // Additional keywords that may be missing
  map.set("nan:canonical", NanCanonical) // Add to TokenType enum
  map.set("nan:arithmetic", NanArithmetic) // Add to TokenType enum
  map.set("ref.extern", Opcode(RefExtern)) // Add RefExtern to Opcode enum
  map.set("extern", ValueType(ExternRef)) // Alias for externref

  // ==========================================================================
  // SIMD Shapes
  // ==========================================================================
  map.set("i8x16", SimdShapeToken(I8x16))
  map.set("i16x8", SimdShapeToken(I16x8))
  map.set("i32x4", SimdShapeToken(I32x4))
  map.set("i64x2", SimdShapeToken(I64x2))
  map.set("f32x4", SimdShapeToken(F32x4))
  map.set("f64x2", SimdShapeToken(F64x2))

  // ==========================================================================
  // v128 Const & Memory
  // ==========================================================================
  map.set("v128.const", Opcode(V128Const))
  map.set("v128.load", Opcode(V128Load))
  map.set("v128.store", Opcode(V128Store))
  map.set("v128.load8x8_s", Opcode(V128Load8x8S))
  map.set("v128.load8x8_u", Opcode(V128Load8x8U))
  map.set("v128.load16x4_s", Opcode(V128Load16x4S))
  map.set("v128.load16x4_u", Opcode(V128Load16x4U))
  map.set("v128.load32x2_s", Opcode(V128Load32x2S))
  map.set("v128.load32x2_u", Opcode(V128Load32x2U))
  map.set("v128.load8_splat", Opcode(V128Load8Splat))
  map.set("v128.load16_splat", Opcode(V128Load16Splat))
  map.set("v128.load32_splat", Opcode(V128Load32Splat))
  map.set("v128.load64_splat", Opcode(V128Load64Splat))
  map.set("v128.load32_zero", Opcode(V128Load32Zero))
  map.set("v128.load64_zero", Opcode(V128Load64Zero))

  // Lane loads/stores
  map.set("v128.load8_lane", Opcode(V128Load8Lane))
  map.set("v128.load16_lane", Opcode(V128Load16Lane))
  map.set("v128.load32_lane", Opcode(V128Load32Lane))
  map.set("v128.load64_lane", Opcode(V128Load64Lane))
  map.set("v128.store8_lane", Opcode(V128Store8Lane))
  map.set("v128.store16_lane", Opcode(V128Store16Lane))
  map.set("v128.store32_lane", Opcode(V128Store32Lane))
  map.set("v128.store64_lane", Opcode(V128Store64Lane))

  // ==========================================================================
  // v128 Bitwise / Test
  // ==========================================================================
  map.set("v128.not", Opcode(V128Not))
  map.set("v128.and", Opcode(V128And))
  map.set("v128.andnot", Opcode(V128AndNot))
  map.set("v128.or", Opcode(V128Or))
  map.set("v128.xor", Opcode(V128Xor))
  map.set("v128.bitselect", Opcode(V128Bitselect))
  map.set("v128.any_true", Opcode(V128AnyTrue))

  // ==========================================================================
  // i8x16
  // ==========================================================================
  map.set("i8x16.shuffle", Opcode(I8x16Shuffle))
  map.set("i8x16.swizzle", Opcode(I8x16Swizzle))
  map.set("i8x16.splat", Opcode(I8x16Splat))
  map.set("i8x16.extract_lane_s", Opcode(I8x16ExtractLaneS))
  map.set("i8x16.extract_lane_u", Opcode(I8x16ExtractLaneU))
  map.set("i8x16.replace_lane", Opcode(I8x16ReplaceLane))
  map.set("i8x16.eq", Opcode(I8x16Eq))
  map.set("i8x16.ne", Opcode(I8x16Ne))
  map.set("i8x16.lt_s", Opcode(I8x16LtS))
  map.set("i8x16.lt_u", Opcode(I8x16LtU))
  map.set("i8x16.gt_s", Opcode(I8x16GtS))
  map.set("i8x16.gt_u", Opcode(I8x16GtU))
  map.set("i8x16.le_s", Opcode(I8x16LeS))
  map.set("i8x16.le_u", Opcode(I8x16LeU))
  map.set("i8x16.ge_s", Opcode(I8x16GeS))
  map.set("i8x16.ge_u", Opcode(I8x16GeU))
  map.set("i8x16.abs", Opcode(I8x16Abs))
  map.set("i8x16.neg", Opcode(I8x16Neg))
  map.set("i8x16.popcnt", Opcode(I8x16Popcnt))
  map.set("i8x16.all_true", Opcode(I8x16AllTrue))
  map.set("i8x16.bitmask", Opcode(I8x16Bitmask))
  map.set("i8x16.narrow_i16x8_s", Opcode(I8x16NarrowI16x8S))
  map.set("i8x16.narrow_i16x8_u", Opcode(I8x16NarrowI16x8U))
  map.set("i8x16.shl", Opcode(I8x16Shl))
  map.set("i8x16.shr_s", Opcode(I8x16ShrS))
  map.set("i8x16.shr_u", Opcode(I8x16ShrU))
  map.set("i8x16.add", Opcode(I8x16Add))
  map.set("i8x16.add_sat_s", Opcode(I8x16AddSatS))
  map.set("i8x16.add_sat_u", Opcode(I8x16AddSatU))
  map.set("i8x16.sub", Opcode(I8x16Sub))
  map.set("i8x16.sub_sat_s", Opcode(I8x16SubSatS))
  map.set("i8x16.sub_sat_u", Opcode(I8x16SubSatU))
  map.set("i8x16.min_s", Opcode(I8x16MinS))
  map.set("i8x16.min_u", Opcode(I8x16MinU))
  map.set("i8x16.max_s", Opcode(I8x16MaxS))
  map.set("i8x16.max_u", Opcode(I8x16MaxU))
  map.set("i8x16.avgr_u", Opcode(I8x16AvgrU))
  map.set("i8x16.relaxed_swizzle", Opcode(I8x16RelaxedSwizzle))
  map.set("i8x16.relaxed_laneselect", Opcode(I8x16RelaxedLaneselect))
  map.set("i16x8.relaxed_laneselect", Opcode(I16x8RelaxedLaneselect))
  map.set("i32x4.relaxed_laneselect", Opcode(I32x4RelaxedLaneselect))
  map.set("i64x2.relaxed_laneselect", Opcode(I64x2RelaxedLaneselect))
  map.set("i32x4.relaxed_trunc_f32x4_s", Opcode(I32x4RelaxedTruncF32x4S))
  map.set("i32x4.relaxed_trunc_f32x4_u", Opcode(I32x4RelaxedTruncF32x4U))
  map.set(
    "i32x4.relaxed_trunc_f64x2_s_zero",
    Opcode(I32x4RelaxedTruncF64x2SZero),
  )
  map.set(
    "i32x4.relaxed_trunc_f64x2_u_zero",
    Opcode(I32x4RelaxedTruncF64x2UZero),
  )
  map.set("f32x4.relaxed_madd", Opcode(F32x4RelaxedMadd))
  map.set("f32x4.relaxed_nmadd", Opcode(F32x4RelaxedNmadd))
  map.set("f64x2.relaxed_madd", Opcode(F64x2RelaxedMadd))
  map.set("f64x2.relaxed_nmadd", Opcode(F64x2RelaxedNmadd))
  map.set("f32x4.relaxed_min", Opcode(F32x4RelaxedMin))
  map.set("f32x4.relaxed_max", Opcode(F32x4RelaxedMax))
  map.set("f64x2.relaxed_min", Opcode(F64x2RelaxedMin))
  map.set("f64x2.relaxed_max", Opcode(F64x2RelaxedMax))
  map.set("i16x8.relaxed_q15mulr_s", Opcode(I16x8RelaxedQ15mulrS))
  map.set("i16x8.relaxed_dot_i8x16_i7x16_s", Opcode(I16x8RelaxedDotI8x16I7x16S))
  map.set(
    "i32x4.relaxed_dot_i8x16_i7x16_add_s",
    Opcode(I32x4RelaxedDotI8x16I7x16AddS),
  )

  // ========== SIMD - i16x8 Operations ==========
  map.set("i16x8.splat", Opcode(I16x8Splat))
  map.set("i16x8.extract_lane_s", Opcode(I16x8ExtractLaneS))
  map.set("i16x8.extract_lane_u", Opcode(I16x8ExtractLaneU))
  map.set("i16x8.replace_lane", Opcode(I16x8ReplaceLane))
  map.set("i16x8.eq", Opcode(I16x8Eq))
  map.set("i16x8.ne", Opcode(I16x8Ne))
  map.set("i16x8.lt_s", Opcode(I16x8LtS))
  map.set("i16x8.lt_u", Opcode(I16x8LtU))
  map.set("i16x8.gt_s", Opcode(I16x8GtS))
  map.set("i16x8.gt_u", Opcode(I16x8GtU))
  map.set("i16x8.le_s", Opcode(I16x8LeS))
  map.set("i16x8.le_u", Opcode(I16x8LeU))
  map.set("i16x8.ge_s", Opcode(I16x8GeS))
  map.set("i16x8.ge_u", Opcode(I16x8GeU))
  map.set("i16x8.abs", Opcode(I16x8Abs))
  map.set("i16x8.neg", Opcode(I16x8Neg))
  map.set("i16x8.q15mulr_sat_s", Opcode(I16x8Q15mulrSatS))
  map.set("i16x8.all_true", Opcode(I16x8AllTrue))
  map.set("i16x8.bitmask", Opcode(I16x8Bitmask))
  map.set("i16x8.narrow_i32x4_s", Opcode(I16x8NarrowI32x4S))
  map.set("i16x8.narrow_i32x4_u", Opcode(I16x8NarrowI32x4U))
  map.set("i16x8.extend_low_i8x16_s", Opcode(I16x8ExtendLowI8x16S))
  map.set("i16x8.extend_high_i8x16_s", Opcode(I16x8ExtendHighI8x16S))
  map.set("i16x8.extend_low_i8x16_u", Opcode(I16x8ExtendLowI8x16U))
  map.set("i16x8.extend_high_i8x16_u", Opcode(I16x8ExtendHighI8x16U))
  map.set("i16x8.shl", Opcode(I16x8Shl))
  map.set("i16x8.shr_s", Opcode(I16x8ShrS))
  map.set("i16x8.shr_u", Opcode(I16x8ShrU))
  map.set("i16x8.add", Opcode(I16x8Add))
  map.set("i16x8.add_sat_s", Opcode(I16x8AddSatS))
  map.set("i16x8.add_sat_u", Opcode(I16x8AddSatU))
  map.set("i16x8.sub", Opcode(I16x8Sub))
  map.set("i16x8.sub_sat_s", Opcode(I16x8SubSatS))
  map.set("i16x8.sub_sat_u", Opcode(I16x8SubSatU))
  map.set("i16x8.mul", Opcode(I16x8Mul))
  map.set("i16x8.min_s", Opcode(I16x8MinS))
  map.set("i16x8.min_u", Opcode(I16x8MinU))
  map.set("i16x8.max_s", Opcode(I16x8MaxS))
  map.set("i16x8.max_u", Opcode(I16x8MaxU))
  map.set("i16x8.avgr_u", Opcode(I16x8AvgrU))
  map.set("i16x8.extmul_low_i8x16_s", Opcode(I16x8ExtmulLowI8x16S))
  map.set("i16x8.extmul_high_i8x16_s", Opcode(I16x8ExtmulHighI8x16S))
  map.set("i16x8.extmul_low_i8x16_u", Opcode(I16x8ExtmulLowI8x16U))
  map.set("i16x8.extmul_high_i8x16_u", Opcode(I16x8ExtmulHighI8x16U))

  // ========== SIMD - i32x4 Operations ==========
  map.set("i32x4.splat", Opcode(I32x4Splat))
  map.set("i32x4.extract_lane", Opcode(I32x4ExtractLane))
  map.set("i32x4.replace_lane", Opcode(I32x4ReplaceLane))
  map.set("i32x4.eq", Opcode(I32x4Eq))
  map.set("i32x4.ne", Opcode(I32x4Ne))
  map.set("i32x4.lt_s", Opcode(I32x4LtS))
  map.set("i32x4.lt_u", Opcode(I32x4LtU))
  map.set("i32x4.gt_s", Opcode(I32x4GtS))
  map.set("i32x4.gt_u", Opcode(I32x4GtU))
  map.set("i32x4.le_s", Opcode(I32x4LeS))
  map.set("i32x4.le_u", Opcode(I32x4LeU))
  map.set("i32x4.ge_s", Opcode(I32x4GeS))
  map.set("i32x4.ge_u", Opcode(I32x4GeU))
  map.set("i32x4.abs", Opcode(I32x4Abs))
  map.set("i32x4.neg", Opcode(I32x4Neg))
  map.set("i32x4.all_true", Opcode(I32x4AllTrue))
  map.set("i32x4.bitmask", Opcode(I32x4Bitmask))
  map.set("i32x4.extend_low_i16x8_s", Opcode(I32x4ExtendLowI16x8S))
  map.set("i32x4.extend_high_i16x8_s", Opcode(I32x4ExtendHighI16x8S))
  map.set("i32x4.extend_low_i16x8_u", Opcode(I32x4ExtendLowI16x8U))
  map.set("i32x4.extend_high_i16x8_u", Opcode(I32x4ExtendHighI16x8U))
  map.set("i32x4.shl", Opcode(I32x4Shl))
  map.set("i32x4.shr_s", Opcode(I32x4ShrS))
  map.set("i32x4.shr_u", Opcode(I32x4ShrU))
  map.set("i32x4.add", Opcode(I32x4Add))
  map.set("i32x4.sub", Opcode(I32x4Sub))
  map.set("i32x4.mul", Opcode(I32x4Mul))
  map.set("i32x4.min_s", Opcode(I32x4MinS))
  map.set("i32x4.min_u", Opcode(I32x4MinU))
  map.set("i32x4.max_s", Opcode(I32x4MaxS))
  map.set("i32x4.max_u", Opcode(I32x4MaxU))
  map.set("i32x4.dot_i16x8_s", Opcode(I32x4DotI16x8S))
  map.set("i32x4.extmul_low_i16x8_s", Opcode(I32x4ExtmulLowI16x8S))
  map.set("i32x4.extmul_high_i16x8_s", Opcode(I32x4ExtmulHighI16x8S))
  map.set("i32x4.extmul_low_i16x8_u", Opcode(I32x4ExtmulLowI16x8U))
  map.set("i32x4.extmul_high_i16x8_u", Opcode(I32x4ExtmulHighI16x8U))
  map.set("i32x4.trunc_sat_f32x4_s", Opcode(I32x4TruncSatF32x4S))
  map.set("i32x4.trunc_sat_f32x4_u", Opcode(I32x4TruncSatF32x4U))
  map.set("i32x4.trunc_sat_f64x2_s_zero", Opcode(I32x4TruncSatF64x2SZero))
  map.set("i32x4.trunc_sat_f64x2_u_zero", Opcode(I32x4TruncSatF64x2UZero))

  // ========== SIMD - i64x2 Operations ==========
  map.set("i64x2.splat", Opcode(I64x2Splat))
  map.set("i64x2.extract_lane", Opcode(I64x2ExtractLane))
  map.set("i64x2.replace_lane", Opcode(I64x2ReplaceLane))
  map.set("i64x2.eq", Opcode(I64x2Eq))
  map.set("i64x2.ne", Opcode(I64x2Ne))
  map.set("i64x2.lt_s", Opcode(I64x2LtS))
  map.set("i64x2.gt_s", Opcode(I64x2GtS))
  map.set("i64x2.le_s", Opcode(I64x2LeS))
  map.set("i64x2.ge_s", Opcode(I64x2GeS))
  map.set("i64x2.abs", Opcode(I64x2Abs))
  map.set("i64x2.neg", Opcode(I64x2Neg))
  map.set("i64x2.all_true", Opcode(I64x2AllTrue))
  map.set("i64x2.bitmask", Opcode(I64x2Bitmask))
  map.set("i64x2.extend_low_i32x4_s", Opcode(I64x2ExtendLowI32x4S))
  map.set("i64x2.extend_high_i32x4_s", Opcode(I64x2ExtendHighI32x4S))
  map.set("i64x2.extend_low_i32x4_u", Opcode(I64x2ExtendLowI32x4U))
  map.set("i64x2.extend_high_i32x4_u", Opcode(I64x2ExtendHighI32x4U))
  map.set("i64x2.shl", Opcode(I64x2Shl))
  map.set("i64x2.shr_s", Opcode(I64x2ShrS))
  map.set("i64x2.shr_u", Opcode(I64x2ShrU))
  map.set("i64x2.add", Opcode(I64x2Add))
  map.set("i64x2.sub", Opcode(I64x2Sub))
  map.set("i64x2.mul", Opcode(I64x2Mul))
  map.set("i64x2.extmul_low_i32x4_s", Opcode(I64x2ExtmulLowI32x4S))
  map.set("i64x2.extmul_high_i32x4_s", Opcode(I64x2ExtmulHighI32x4S))
  map.set("i64x2.extmul_low_i32x4_u", Opcode(I64x2ExtmulLowI32x4U))
  map.set("i64x2.extmul_high_i32x4_u", Opcode(I64x2ExtmulHighI32x4U))

  // ========== SIMD - f32x4 Operations ==========
  map.set("f32x4.splat", Opcode(F32x4Splat))
  map.set("f32x4.extract_lane", Opcode(F32x4ExtractLane))
  map.set("f32x4.replace_lane", Opcode(F32x4ReplaceLane))
  map.set("f32x4.eq", Opcode(F32x4Eq))
  map.set("f32x4.ne", Opcode(F32x4Ne))
  map.set("f32x4.lt", Opcode(F32x4Lt))
  map.set("f32x4.gt", Opcode(F32x4Gt))
  map.set("f32x4.le", Opcode(F32x4Le))
  map.set("f32x4.ge", Opcode(F32x4Ge))
  map.set("f32x4.abs", Opcode(F32x4Abs))
  map.set("f32x4.neg", Opcode(F32x4Neg))
  map.set("f32x4.sqrt", Opcode(F32x4Sqrt))
  map.set("f32x4.add", Opcode(F32x4Add))
  map.set("f32x4.sub", Opcode(F32x4Sub))
  map.set("f32x4.mul", Opcode(F32x4Mul))
  map.set("f32x4.div", Opcode(F32x4Div))
  map.set("f32x4.min", Opcode(F32x4Min))
  map.set("f32x4.max", Opcode(F32x4Max))
  map.set("f32x4.pmin", Opcode(F32x4Pmin))
  map.set("f32x4.pmax", Opcode(F32x4Pmax))
  map.set("f32x4.ceil", Opcode(F32x4Ceil))
  map.set("f32x4.floor", Opcode(F32x4Floor))
  map.set("f32x4.trunc", Opcode(F32x4Trunc))
  map.set("f32x4.nearest", Opcode(F32x4Nearest))
  map.set("f32x4.convert_i32x4_s", Opcode(F32x4ConvertI32x4S))
  map.set("f32x4.convert_i32x4_u", Opcode(F32x4ConvertI32x4U))
  map.set("f32x4.demote_f64x2_zero", Opcode(F32x4DemoteF64x2Zero))

  // ========== SIMD - f64x2 Operations ==========
  map.set("f64x2.splat", Opcode(F64x2Splat))
  map.set("f64x2.extract_lane", Opcode(F64x2ExtractLane))
  map.set("f64x2.replace_lane", Opcode(F64x2ReplaceLane))
  map.set("f64x2.eq", Opcode(F64x2Eq))
  map.set("f64x2.ne", Opcode(F64x2Ne))
  map.set("f64x2.lt", Opcode(F64x2Lt))
  map.set("f64x2.gt", Opcode(F64x2Gt))
  map.set("f64x2.le", Opcode(F64x2Le))
  map.set("f64x2.ge", Opcode(F64x2Ge))
  map.set("f64x2.abs", Opcode(F64x2Abs))
  map.set("f64x2.neg", Opcode(F64x2Neg))
  map.set("f64x2.sqrt", Opcode(F64x2Sqrt))
  map.set("f64x2.add", Opcode(F64x2Add))
  map.set("f64x2.sub", Opcode(F64x2Sub))
  map.set("f64x2.mul", Opcode(F64x2Mul))
  map.set("f64x2.div", Opcode(F64x2Div))
  map.set("f64x2.min", Opcode(F64x2Min))
  map.set("f64x2.max", Opcode(F64x2Max))
  map.set("f64x2.pmin", Opcode(F64x2Pmin))
  map.set("f64x2.pmax", Opcode(F64x2Pmax))
  map.set("f64x2.ceil", Opcode(F64x2Ceil))
  map.set("f64x2.floor", Opcode(F64x2Floor))
  map.set("f64x2.trunc", Opcode(F64x2Trunc))
  map.set("f64x2.nearest", Opcode(F64x2Nearest))
  map.set("f64x2.convert_low_i32x4_s", Opcode(F64x2ConvertLowI32x4S))
  map.set("f64x2.convert_low_i32x4_u", Opcode(F64x2ConvertLowI32x4U))
  map.set("f64x2.promote_low_f32x4", Opcode(F64x2PromoteLowF32x4))
  { map, }
}

// Use a lazy-initialized global

///|
let keyword_table : KeywordTable = KeywordTable::new()

///|
pub fn lookup_keyword(s : String) -> TokenType? {
  keyword_table.lookup(s)
}

///|
pub fn KeywordTable::lookup(self : KeywordTable, s : String) -> TokenType? {
  self.map.get(s)
}