Point of sale (events + OO + logic)

A checkout session as a stream of scan/pay events: the product catalog lives in the object store, and a dairy fact drives the discount rule.

PatLang source
# =============================================================================
# Point-of-sale library (Stage 1 dialect): event-driven checkout combining
# events (scan/pay), OO (product catalog in the object store), and logic
# (dairy facts drive a discount rule). Prices are integer pence.
# =============================================================================

make a function called pos_setup returns done
  new("Product", "apple")
  send("apple", "set", "price", 30)
  new("Product", "banana")
  send("banana", "set", "price", 25)
  new("Product", "milk")
  send("milk", "set", "price", 120)
  fact("dairy", "milk", "yes")
  fact("dairy", "cheese", "yes")
  set_var("total", 0)
  set_var("items", 0)
  set_var("receipt", "")
  goal("serve_customer", "till-1")
  return true
end

make a function called pos_scan takes item returns price
  let price = get(item, "price")
  if not price then
    print("  unknown item: " + item)
    return 0
  end
  if query("dairy", item, 0) > 0 then
    # dairy discount: 10% off
    let price = price * 9 / 10
  end
  set_var("total", get("__vars", "total") + price)
  set_var("items", get("__vars", "items") + 1)
  set_var("receipt", get("__vars", "receipt") + "  " + item + "  " + price + "p\n")
  return price
end

make a function called pos_total returns t
  return get("__vars", "total")
end

make a function called pos_pay takes tendered returns change
  let total = get("__vars", "total")
  let change = tendered - total
  print("--- RECEIPT ---")
  print(get("__vars", "receipt") + "  items: " + get("__vars", "items"))
  print("  total: " + total + "p, tendered: " + tendered + "p, change: " + change + "p")
  return change
end

when scan do
  pos_scan(event_data)
end

when pay do
  pos_pay(event_data)
end

# Point-of-sale demo driver (concatenate after lib/pos.patlang).
# A checkout session as a stream of events.

pos_setup()
print("scanning...")
emit("scan", "apple")
emit("scan", "apple")
emit("scan", "banana")
emit("scan", "milk")
emit("scan", "unobtainium")
emit("pay", 500)
print("till session complete")

(not run yet)

Native run on the build machine:

scanning...
  unknown item: unobtainium
--- RECEIPT ---
  apple  30p
  apple  30p
  banana  25p
  milk  108p
  items: 4
  total: 193p, tendered: 500p, change: 307p
till session complete