ReefVM/examples/add-with-dicts.ts
2025-10-29 15:28:34 -07:00

159 lines
3.6 KiB
TypeScript

/**
* Demonstrates the ADD opcode working with dicts
*
* ADD now handles dict merging:
* - {a: 1} + {b: 2} === {a: 1, b: 2}
* - If both operands are dicts, they are merged
* - Keys from the second dict overwrite keys from the first on conflict
*/
import { toBytecode, run } from "#reef"
// Basic dict merge
const basicMerge = toBytecode([
["PUSH", "a"],
["PUSH", 1],
["MAKE_DICT", 1],
["PUSH", "b"],
["PUSH", 2],
["MAKE_DICT", 1],
["ADD"],
["HALT"]
])
console.log('Basic dict merge ({a: 1} + {b: 2}):')
const result1 = await run(basicMerge)
console.log(result1)
// Output: { type: 'dict', value: Map { a: 1, b: 2 } }
// Merge with overlapping keys
const overlapMerge = toBytecode([
["PUSH", "a"],
["PUSH", 1],
["PUSH", "b"],
["PUSH", 2],
["MAKE_DICT", 2],
["PUSH", "b"],
["PUSH", 99],
["PUSH", "c"],
["PUSH", 3],
["MAKE_DICT", 2],
["ADD"],
["HALT"]
])
console.log('\nMerge with overlapping keys ({a: 1, b: 2} + {b: 99, c: 3}):')
const result2 = await run(overlapMerge)
console.log(result2)
console.log('Note: b is overwritten from 2 to 99')
// Output: { type: 'dict', value: Map { a: 1, b: 99, c: 3 } }
// Merge multiple dicts in sequence
const multipleMerge = toBytecode([
["PUSH", "a"],
["PUSH", 1],
["MAKE_DICT", 1],
["PUSH", "b"],
["PUSH", 2],
["MAKE_DICT", 1],
["ADD"],
["PUSH", "c"],
["PUSH", 3],
["MAKE_DICT", 1],
["ADD"],
["PUSH", "d"],
["PUSH", 4],
["MAKE_DICT", 1],
["ADD"],
["HALT"]
])
console.log('\nMultiple merges ({a: 1} + {b: 2} + {c: 3} + {d: 4}):')
const result3 = await run(multipleMerge)
console.log(result3)
// Output: { type: 'dict', value: Map { a: 1, b: 2, c: 3, d: 4 } }
// Merge dicts with different value types
const mixedTypes = toBytecode([
["PUSH", "num"],
["PUSH", 42],
["PUSH", "str"],
["PUSH", "hello"],
["MAKE_DICT", 2],
["PUSH", "bool"],
["PUSH", true],
["PUSH", "null"],
["PUSH", null],
["MAKE_DICT", 2],
["ADD"],
["HALT"]
])
console.log('\nMerge dicts with different types ({num: 42, str: "hello"} + {bool: true, null: null}):')
const result4 = await run(mixedTypes)
console.log(result4)
// Output: { type: 'dict', value: Map { num: 42, str: 'hello', bool: true, null: null } }
// Merge empty dict with non-empty
const emptyMerge = toBytecode([
["MAKE_DICT", 0],
["PUSH", "x"],
["PUSH", 100],
["PUSH", "y"],
["PUSH", 200],
["MAKE_DICT", 2],
["ADD"],
["HALT"]
])
console.log('\nMerge empty dict with {x: 100, y: 200} ({} + {x: 100, y: 200}):')
const result5 = await run(emptyMerge)
console.log(result5)
// Output: { type: 'dict', value: Map { x: 100, y: 200 } }
// Merge dicts with nested structures
const nestedMerge = toBytecode([
["PUSH", "data"],
["PUSH", 1],
["PUSH", 2],
["MAKE_ARRAY", 2],
["MAKE_DICT", 1],
["PUSH", "config"],
["PUSH", "debug"],
["PUSH", true],
["MAKE_DICT", 1],
["MAKE_DICT", 1],
["ADD"],
["HALT"]
])
console.log('\nMerge dicts with nested structures:')
const result6 = await run(nestedMerge)
console.log(result6)
// Output: { type: 'dict', value: Map { data: [1, 2], config: { debug: true } } }
// Building configuration objects
const configBuild = toBytecode([
// Default config
["PUSH", "debug"],
["PUSH", false],
["PUSH", "port"],
["PUSH", 3000],
["PUSH", "host"],
["PUSH", "localhost"],
["MAKE_DICT", 3],
// Override with user config
["PUSH", "debug"],
["PUSH", true],
["PUSH", "port"],
["PUSH", 8080],
["MAKE_DICT", 2],
["ADD"],
["HALT"]
])
console.log('\nBuilding config (defaults + overrides):')
const result7 = await run(configBuild)
console.log(result7)
// Output: { type: 'dict', value: Map { debug: true, port: 8080, host: 'localhost' } }