local { local def extend promote{arith} = { def arith{a:T,b & match{'number',kind{b}}} = arith{a , cast{T,b}} def arith{a,b:T & match{'number',kind{a}}} = arith{cast{T,a} , b} } def arith{op} = { def extend _{arith} = { def arith{a:T,b:T & match{'primitive',typekind{T}}} = emit{T, op, a, b} extend promote{arith} }} def arith1{op} = { def extend _{arith} = { def arith{a:T & match{'primitive',typekind{T}}} = emit{T, op, a} arith }} def sh{op} = { def extend _{arith} = { def arith{a:T,b:I & isint{T} & isint{I}} = emit{T, op, a, b} extend promote{arith} }} def pk{T} = { def k=typekind{T} if (match{'primitive',k} or match{'pointer',k}) 1; else 0 } def compare{op} = { def extend _{arith} = { def arith{a:T,b:T & pk{T}} = emit{u1, op, a, b} extend promote{arith} }} def logic = arith def logic1 = arith1 } extend (arith1{'-'}){__neg} extend (arith{'op +'}){__add} extend (arith{'op -'}){__sub} extend (arith{'op *'}){__mul} extend (arith{'op /'}){__div} extend (arith{'op %'}){__mod} local { def isptr{T} = match{'pointer',typekind{T}} def ptrwidth = width{__pnt{void}} def isize = primtype{'i',ptrwidth} def ptrdiff{a} = cast{isize, a} def ptrdiff{a:T} = promote{ptrwidth, a} } def __pnt{a:T & isptr{T}} = load{a,0} def __add{a ,b:P & isptr{P}} = emit{P, 'op +', ptrdiff{a}, b} def __add{a:P,b & isptr{P}} = emit{P, 'op +', a, ptrdiff{b}} def __sub{a:P,b & isptr{P}} = emit{P, 'op -', a, ptrdiff{b}} def __sub{a:P,b:P & isptr{P}} = emit{isize, 'op -', a, b} extend (compare{'op =='}){__eq} extend (compare{'op !='}){__ne} extend (compare{'op >' }){__gt} extend (compare{'op >='}){__ge} extend (compare{'op <' }){__lt} extend (compare{'op <='}){__le} extend (logic{'op &'}){__and} extend (logic{'op |'}){__or } extend (logic{'op ^'}){__xor} extend (logic1{'~'}){__not} def __not{a:u1} = emit{u1, '!', a} extend (sh{'op <<'}){__shl} extend (sh{'op >>'}){__shr} def cast_i{T, x} = emit{T, '', x}