Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KernelDeimos/1c0effe5ede3a8e6e1eee094c6963522 to your computer and use it in GitHub Desktop.
Save KernelDeimos/1c0effe5ede3a8e6e1eee094c6963522 to your computer and use it in GitHub Desktop.
Behaviour of arithmetic operand evaluation order as seen under different C compilers, imitated in a `.js` script.
const cases = [
['-', ['incr_post', 'c'], ['get', 'c']],
['-', ['incr_pre', 'c'], ['get', 'c']],
['-', ['get', 'c'], ['incr_post', 'c']],
['-', ['get', 'c'], ['incr_pre', 'c']],
];
const incr_post = (ctx, v) => {
const v_ = ctx.scope[v];
ctx.scope[v] += 1;
return v_;
}
const incr_pre = (ctx, v) => {
const v_ = ctx.scope[v];
ctx.scope[v] += 1;
return ctx.scope[v];
}
const get = (ctx, k) => {
return ctx.scope[k];
}
class TinyEmulator {
constructor (fn_map, scope = {}) {
this.scope = { ...scope };
this.fn_map = fn_map;
}
eval (ins) {
ins = [...ins];
const fn_name = ins.shift();
return this.fn_map[fn_name](this, ...ins);
}
}
// === EMULATE CLANG BEHAVIOUR ===
const minus_clang = (ctx, a, b) => {
const a_ = ctx.eval(a);
const b_ = ctx.eval(b);
return a_ - b_;
}
const emu_clang = new TinyEmulator({
incr_post,
incr_pre,
get,
'-': minus_clang,
}, { c: 0 });
for ( const case_ of cases ) {
console.log(emu_clang.eval(case_));
}
// === EMULATE GCC BEHAVIOUR ===
const minus_gcc = (ctx, a, b) => {
let a_, b_;
if ( a[0] !== 'get' ) {
a_ = ctx.eval(a);
b_ = ctx.eval(b);
} else {
b_ = ctx.eval(b);
a_ = ctx.eval(a);
}
return a_ - b_;
}
const emu_gcc = new TinyEmulator({
incr_post,
incr_pre,
get,
'-': minus_gcc,
}, { c: 0 });
for ( const case_ of cases ) {
console.log(emu_gcc.eval(case_));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment