#!/usr/bin/python3 """A remote data server implementing a simple software transactional memory. Commands are sent one per line: - {: start a (possibly nested) transaction; other commands are valid only inside a transaction. - }: terminate the innermost transaction; this will commit it if possible, but if it fails, discard it. - lvalue =: read the value of a given lvalue - lvalue = expr: set lvalue to expression expr Expressions are one of the following: - $name: a global variable called name; this is also an lvalue - name: a connection-local variable called name, used to avoid redundant data transmission; this is also an lvalue - expr.name: the variable called name in the namespace identified by expr; this is also an lvalue - "text": a byte string; it contains no variables - 37: an integer; it contains no variables - nil: the value of nonexistent variables, which can be assigned to delete them; it contains no variables - <>: a newly created namespace; it initially contains no variables Results, sent one per line, are one of the following: - oops: your transaction has failed because of a read/write conflict. Issued exactly once per failure, and not necessarily in reply to a command. - no: you are currently in a failed transaction, which you ought to terminate and retry once you notice that is what has happened. This will be issued once for every command inside the failed transaction, including the } that terminates it. - ok: tells you that your } has committed. - lvalue = expr: tells you that lvalue (which you requested to read) has value expr. If the lvalue’s value is a namespace, the expr will be <>, regardless of whether there are names in the namespace. Transaction terminations and reads will always produce either a single success response (lvalue = expr or ok) or a “no”. Attempts to set values produce no output. If some other top-level transaction (on another connection) commits and changes a value your transaction had read, that transaction will fail. All the settings of failed transactions are rolled back. XXX hmm, there probably needs to be a way to report syntax errors """ import asyncio