Project P143

Member accounts

Sign-ups and soft deletes kept four ways - plain, partial, nulled and compound uniqueness - each decision set against the rule meant, one active account per address.

2 modules · 2 recorded sessionstext-menu UI in the terminalupdated 2026-10-18

Every screen below was recorded under CPython. When this page was built, the EML interpreter replayed each session from the same input and printed the same bytes.

About

Sign-ups and soft deletes kept four ways, each decision set against the rule meant: at most one active account per address.

  • main.eml - the menu, the accounts in each scheme, signing up, deleting, the clock, and the checks
  • accounts.eml - the four schemes, the key each unique index compares, signing up, deleting, and counting the deleted rows and the addresses they keep

How each part works:

  • A soft delete marks the row with the second it was deleted instead of removing it. Ana, Bob and Cy have accounts; the clock is at second 2 and moves on only when asked.
  • As in the corpus case soft-delete-and-uniqueness, the four schemes: plain is unique on the address over every row; partial is unique among active rows; nulled takes the address off a deleted row; compound is unique on the address and the second it was deleted.
  • Plain refuses every sign-up of an address that only deleted accounts have: its index still counts them. Partial makes every decision the rule meant. Nulled decides the same but keeps no deleted address, so the history no longer says whose the accounts were.
  • Compound decides right until one address is deleted twice in the same second: the second deletion has the key of the first and fails, the account stays active there, and the next sign-up of that address is wrongly refused. A second later the deletion goes through.
  • No scheme ever lets two accounts with one address be active at once; with no deletions all four decide the same, which is why a test that never deletes and signs up again cannot tell them apart.

What is checked: menu choices 1 to 6; an address of 3 to 12 characters, letters a to z with one @ not at either end; a deletion only of an address with an active account. An empty answer cancels.

Sessions: sessions/basic.in gives: - the accounts; Bob deleted and signing up again; the checks; - in second 2: Ana's sign-up refused while active, then Ana deleted, signing up, deleted again (compound fails) and signing up again; - in second 3: Ana deleted and signing up; the checks and the accounts.

sessions/bad-input.in gives: - menu choices 0, x and 7; - addresses: a cancel, Ana@x, ab, a@b@c, @ab and one of 16 characters; - deleting: a cancel, zed@x (no active account) and x; - the next second, Dan signing up, and the checks with no deletions.

Built on the verified corpus case soft-delete-and-uniqueness (four uniqueness schemes over sign-ups, deletions and re-sign-ups, wrong refusals and duplicates counted apart).

Recorded sessions

What the screen shows while someone uses the program. Each typed line appears after its prompt, the way a terminal shows it.

bad-input

interpreter: byte-equal
== Member accounts ==
Sign-ups and soft deletes kept four ways, against the rule meant: one active account per address.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 0
Pick a number from 1 to 6.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> x
Pick a number from 1 to 6.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 7
Pick a number from 1 to 6.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 2
address> 
Cancelled.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 2
address> Ana@x
Type an address like ana@x: letters a to z with one @, 3 to 12 characters.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 2
address> ab
Type an address like ana@x: letters a to z with one @, 3 to 12 characters.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 2
address> a@b@c
Type an address like ana@x: letters a to z with one @, 3 to 12 characters.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 2
address> @ab
Type an address like ana@x: letters a to z with one @, 3 to 12 characters.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 2
address> toolongaddress@x
Type an address like ana@x: letters a to z with one @, 3 to 12 characters.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 3
address> 
Cancelled.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 3
address> zed@x
No account with the address zed@x is active.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 3
address> x
Type an address like ana@x: letters a to z with one @, 3 to 12 characters.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 4
It is second 3.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 2
address> dan@x
Sign-up for dan@x in second 3 - the rule meant: accept, no active account has it.
  plain     accepted
  partial   accepted
  nulled    accepted
  compound  accepted

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 5
                wrongly   two active   deletions   deleted rows
                refused   allowed      failed      keeping the address
  plain            0          0            0      0 of 0
  partial          0          0            0      0 of 0
  nulled           0          0            0      0 of 0
  compound         0          0            0      0 of 0
The rule meant: at most one active account per address.
Right on every count so far: plain, partial, nulled, compound.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 6
Bye.
What was typed (26 lines)
0
x
7
2

2
Ana@x
2
ab
2
a@b@c
2
@ab
2
toolongaddress@x
3

3
zed@x
3
x
4
2
dan@x
5
6

basic

interpreter: byte-equal
== Member accounts ==
Sign-ups and soft deletes kept four ways, against the rule meant: one active account per address.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 1
It is second 2.
plain (unique on the address over every row):
  ana@x         active
  bob@x         active
  cy@x          active
partial (unique on the address among active rows):
  ana@x         active
  bob@x         active
  cy@x          active
nulled (a deleted row loses its address):
  ana@x         active
  bob@x         active
  cy@x          active
compound (unique on the address and the second it was deleted):
  ana@x         active
  bob@x         active
  cy@x          active

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 3
address> bob@x
Deleting bob@x in second 2:
  plain     deleted
  partial   deleted
  nulled    deleted
  compound  deleted

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 2
address> bob@x
Sign-up for bob@x in second 2 - the rule meant: accept, no active account has it.
  plain     refused: a deleted account still has the address   <- wrong
  partial   accepted
  nulled    accepted
  compound  accepted

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 5
                wrongly   two active   deletions   deleted rows
                refused   allowed      failed      keeping the address
  plain            1          0            0      1 of 1
  partial          0          0            0      1 of 1
  nulled           0          0            0      0 of 1
  compound         0          0            0      1 of 1
The rule meant: at most one active account per address.
Right on every count so far: partial, compound.
plain refused 1 sign-up the rule allows: its index still counts the deleted rows.
nulled decides right, and kept the address of 0 of 1 deleted account: the history no longer says whose they were.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 2
address> ana@x
Sign-up for ana@x in second 2 - the rule meant: refuse, an active account has it.
  plain     refused: an active account has the address
  partial   refused: an active account has the address
  nulled    refused: an active account has the address
  compound  refused: an active account has the address

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 3
address> ana@x
Deleting ana@x in second 2:
  plain     deleted
  partial   deleted
  nulled    deleted
  compound  deleted

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 2
address> ana@x
Sign-up for ana@x in second 2 - the rule meant: accept, no active account has it.
  plain     refused: a deleted account still has the address   <- wrong
  partial   accepted
  nulled    accepted
  compound  accepted

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 3
address> ana@x
Deleting ana@x in second 2:
  plain     nothing to delete: no active account has the address here
  partial   deleted
  nulled    deleted
  compound  the deletion fails: a row deleted in second 2 already has the key ana@x@2

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 2
address> ana@x
Sign-up for ana@x in second 2 - the rule meant: accept, no active account has it.
  plain     refused: a deleted account still has the address   <- wrong
  partial   accepted
  nulled    accepted
  compound  refused: an active account has the address   <- wrong

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 4
It is second 3.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 3
address> ana@x
Deleting ana@x in second 3:
  plain     nothing to delete: no active account has the address here
  partial   deleted
  nulled    deleted
  compound  deleted

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 2
address> ana@x
Sign-up for ana@x in second 3 - the rule meant: accept, no active account has it.
  plain     refused: a deleted account still has the address   <- wrong
  partial   accepted
  nulled    accepted
  compound  accepted

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 5
                wrongly   two active   deletions   deleted rows
                refused   allowed      failed      keeping the address
  plain            4          0            0      2 of 2
  partial          0          0            0      4 of 4
  nulled           0          0            0      0 of 4
  compound         1          0            1      3 of 3
The rule meant: at most one active account per address.
Right on every count so far: partial.
plain refused 4 sign-ups the rule allows: its index still counts the deleted rows.
nulled decides right, and kept the address of 0 of 4 deleted accounts: the history no longer says whose they were.
compound failed 1 deletion: two deletions of one address in the same second have the same key.
compound refused 1 sign-up the rule allows: an account whose deletion failed is still active there.

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 1
It is second 3.
plain (unique on the address over every row):
  ana@x         deleted in second 2
  bob@x         deleted in second 2
  cy@x          active
partial (unique on the address among active rows):
  ana@x         deleted in second 2
  bob@x         deleted in second 2
  cy@x          active
  bob@x         active
  ana@x         deleted in second 2
  ana@x         deleted in second 3
  ana@x         active
nulled (a deleted row loses its address):
  (no address)  deleted in second 2
  (no address)  deleted in second 2
  cy@x          active
  bob@x         active
  (no address)  deleted in second 2
  (no address)  deleted in second 3
  ana@x         active
compound (unique on the address and the second it was deleted):
  ana@x         deleted in second 2
  bob@x         deleted in second 2
  cy@x          active
  bob@x         active
  ana@x         deleted in second 3
  ana@x         active

1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit
choice> 6
Bye.
What was typed (24 lines)
1
3
bob@x
2
bob@x
5
2
ana@x
3
ana@x
2
ana@x
3
ana@x
2
ana@x
4
3
ana@x
2
ana@x
5
1
6

Modules

The program as written, entry module first. Each module transpiles to its own Python file, which is what eml project run executes.

main.eml(entry)

eml
# P143 member accounts: the same sign-ups and deletions kept four ways,
# each decision set against the rule meant - at most one active account per
# address - and the counts of what each way gets wrong.
import accounts

def plain(s):
    0 => i
    len(s) => j
    while i < j and s[i] == " ":
        i + 1 => i
    while j > i and s[j - 1] == " ":
        j - 1 => j
    return s[i:j]

def pad(s, n):
    s => out
    while len(out) < n:
        out + " " => out
    return out

def lpad(s, n):
    s => out
    while len(out) < n:
        " " + out => out
    return out

def address_ok(t):
    # a to z with one @, not at either end, 3 to 12 characters
    if len(t) < 3 or len(t) > 12:
        return False
    0 => ats
    for c in t:
        if c == "@":
            ats + 1 => ats
        elif c < "a" or c > "z":
            return False
    return ats == 1 and t[0] != "@" and t[len(t) - 1] != "@"

def times(n, one, many):
    if n == 1:
        return "1 " + one
    return str(n) + " " + many

def show(rows, truth, t):
    ("It is second " + str(t) + ".") ^0
    0 => i
    for s in accounts.schemes():
        (s + " (" + accounts.what()[i] + "):") ^0
        for r in rows[s]:
            if r[0] == "":
                "(no address)" => a
            else:
                r[0] => a
            if r[1] == 0:
                ("  " + pad(a, 14) + "active") ^0
            else:
                ("  " + pad(a, 14) + "deleted in second " + str(r[1])) ^0
        i + 1 => i

def signup(rows, truth, counts, t):
    plain(input("address> ")) => a
    if a == "":
        "Cancelled." ^0
        return [rows, truth, counts]
    if not address_ok(a):
        "Type an address like ana@x: letters a to z with one @, 3 to 12 characters." ^0
        return [rows, truth, counts]
    accounts.active(truth, a) < 0 => meant
    if meant:
        ("Sign-up for " + a + " in second " + str(t) + " - the rule meant: accept, no active account has it.") ^0
    else:
        ("Sign-up for " + a + " in second " + str(t) + " - the rule meant: refuse, an active account has it.") ^0
    {} => out
    for s in accounts.schemes():
        accounts.signup(s, rows[s], a) => r
        r[0] => out[s]
        if r[1] == "ok":
            "accepted" => said
        elif r[1] == "active":
            "refused: an active account has the address" => said
        else:
            "refused: a deleted account still has the address" => said
        if meant and r[1] != "ok":
            said + "   <- wrong" => said
            counts[s + " wrong"] + 1 => counts[s + " wrong"]
        if not meant and r[1] == "ok":
            said + "   <- wrong: two active accounts" => said
            counts[s + " dup"] + 1 => counts[s + " dup"]
        ("  " + pad(s, 10) + said) ^0
    if meant:
        truth + [[a, 0]] => truth
    return [out, truth, counts]

def delete(rows, truth, counts, t):
    plain(input("address> ")) => a
    if a == "":
        "Cancelled." ^0
        return [rows, truth, counts]
    if not address_ok(a):
        "Type an address like ana@x: letters a to z with one @, 3 to 12 characters." ^0
        return [rows, truth, counts]
    if accounts.active(truth, a) < 0:
        ("No account with the address " + a + " is active.") ^0
        return [rows, truth, counts]
    ("Deleting " + a + " in second " + str(t) + ":") ^0
    {} => out
    for s in accounts.schemes():
        accounts.delete(s, rows[s], a, t) => r
        r[0] => out[s]
        if r[1] == "ok":
            "deleted" => said
        elif r[1] == "none":
            "nothing to delete: no active account has the address here" => said
        else:
            "the deletion fails: a row deleted in second " + str(t) + " already has the key " + accounts.key(s, [a, t]) => said
            counts[s + " failed"] + 1 => counts[s + " failed"]
        ("  " + pad(s, 10) + said) ^0
    accounts.delete("partial", truth, a, t)[0] => truth
    return [out, truth, counts]

def checks(rows, counts):
    "                wrongly   two active   deletions   deleted rows" ^0
    "                refused   allowed      failed      keeping the address" ^0
    [] => right
    for s in accounts.schemes():
        [counts[s + " wrong"], counts[s + " dup"], counts[s + " failed"]] => c
        accounts.kept(rows[s]) => k
        accounts.deleted(rows[s]) => d
        ("  " + pad(s, 12) + lpad(str(c[0]), 6) + lpad(str(c[1]), 11) + lpad(str(c[2]), 13) + "      " + str(k) + " of " + str(d)) ^0
        if c[0] == 0 and c[1] == 0 and c[2] == 0 and k == d:
            right + [s] => right
    "The rule meant: at most one active account per address." ^0
    if len(right) > 0:
        "" => names
        for s in right:
            if names == "":
                s => names
            else:
                names + ", " + s => names
        ("Right on every count so far: " + names + ".") ^0
    counts["plain wrong"] => c
    if c > 0:
        ("plain refused " + times(c, "sign-up", "sign-ups") + " the rule allows: its index still counts the deleted rows.") ^0
    accounts.kept(rows["nulled"]) => k
    accounts.deleted(rows["nulled"]) => d
    if k < d:
        ("nulled decides right, and kept the address of " + str(k) + " of " + times(d, "deleted account", "deleted accounts") + ": the history no longer says whose they were.") ^0
    if counts["compound failed"] > 0:
        ("compound failed " + times(counts["compound failed"], "deletion", "deletions") + ": two deletions of one address in the same second have the same key.") ^0
    if counts["compound wrong"] > 0:
        ("compound refused " + times(counts["compound wrong"], "sign-up", "sign-ups") + " the rule allows: an account whose deletion failed is still active there.") ^0

{} => rows
{} => counts
[] => truth
for s in accounts.schemes():
    [] => rows[s]
    0 => counts[s + " wrong"]
    0 => counts[s + " dup"]
    0 => counts[s + " failed"]
for a in accounts.opening():
    for s in accounts.schemes():
        accounts.signup(s, rows[s], a)[0] => rows[s]
    truth + [[a, 0]] => truth
2 => t

"== Member accounts ==" ^0
"Sign-ups and soft deletes kept four ways, against the rule meant: one active account per address." ^0
True => running
while running:
    "" ^0
    "1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit" ^0
    plain(input("choice> ")) => choice
    if choice == "1":
        show(rows, truth, t)
    elif choice == "2":
        signup(rows, truth, counts, t) => r
        r[0] => rows
        r[1] => truth
        r[2] => counts
    elif choice == "3":
        delete(rows, truth, counts, t) => r
        r[0] => rows
        r[1] => truth
        r[2] => counts
    elif choice == "4":
        t + 1 => t
        ("It is second " + str(t) + ".") ^0
    elif choice == "5":
        checks(rows, counts)
    elif choice == "6":
        False => running
    else:
        "Pick a number from 1 to 6." ^0
"Bye." ^0
Python projection (main.py)
import accounts

def plain(s):
    i = 0
    j = len(s)
    while i < j and s[i] == " ":
        i = i + 1
    while j > i and s[j - 1] == " ":
        j = j - 1
    return s[i:j]

def pad(s, n):
    out = s
    while len(out) < n:
        out = out + " "
    return out

def lpad(s, n):
    out = s
    while len(out) < n:
        out = " " + out
    return out

def address_ok(t):
    if len(t) < 3 or len(t) > 12:
        return False
    ats = 0
    for c in t:
        if c == "@":
            ats = ats + 1
        elif c < "a" or c > "z":
            return False
    return ats == 1 and t[0] != "@" and t[len(t) - 1] != "@"

def times(n, one, many):
    if n == 1:
        return "1 " + one
    return str(n) + " " + many

def show(rows, truth, t):
    print("It is second " + str(t) + ".")
    i = 0
    for s in accounts.schemes():
        print(s + " (" + accounts.what()[i] + "):")
        for r in rows[s]:
            if r[0] == "":
                a = "(no address)"
            else:
                a = r[0]
            if r[1] == 0:
                print("  " + pad(a, 14) + "active")
            else:
                print("  " + pad(a, 14) + "deleted in second " + str(r[1]))
        i = i + 1

def signup(rows, truth, counts, t):
    a = plain(input("address> "))
    if a == "":
        print("Cancelled.")
        return [rows, truth, counts]
    if not address_ok(a):
        print("Type an address like ana@x: letters a to z with one @, 3 to 12 characters.")
        return [rows, truth, counts]
    meant = accounts.active(truth, a) < 0
    if meant:
        print("Sign-up for " + a + " in second " + str(t) + " - the rule meant: accept, no active account has it.")
    else:
        print("Sign-up for " + a + " in second " + str(t) + " - the rule meant: refuse, an active account has it.")
    out = {}
    for s in accounts.schemes():
        r = accounts.signup(s, rows[s], a)
        out[s] = r[0]
        if r[1] == "ok":
            said = "accepted"
        elif r[1] == "active":
            said = "refused: an active account has the address"
        else:
            said = "refused: a deleted account still has the address"
        if meant and r[1] != "ok":
            said = said + "   <- wrong"
            counts[s + " wrong"] = counts[s + " wrong"] + 1
        if not meant and r[1] == "ok":
            said = said + "   <- wrong: two active accounts"
            counts[s + " dup"] = counts[s + " dup"] + 1
        print("  " + pad(s, 10) + said)
    if meant:
        truth = truth + [[a, 0]]
    return [out, truth, counts]

def delete(rows, truth, counts, t):
    a = plain(input("address> "))
    if a == "":
        print("Cancelled.")
        return [rows, truth, counts]
    if not address_ok(a):
        print("Type an address like ana@x: letters a to z with one @, 3 to 12 characters.")
        return [rows, truth, counts]
    if accounts.active(truth, a) < 0:
        print("No account with the address " + a + " is active.")
        return [rows, truth, counts]
    print("Deleting " + a + " in second " + str(t) + ":")
    out = {}
    for s in accounts.schemes():
        r = accounts.delete(s, rows[s], a, t)
        out[s] = r[0]
        if r[1] == "ok":
            said = "deleted"
        elif r[1] == "none":
            said = "nothing to delete: no active account has the address here"
        else:
            said = "the deletion fails: a row deleted in second " + str(t) + " already has the key " + accounts.key(s, [a, t])
            counts[s + " failed"] = counts[s + " failed"] + 1
        print("  " + pad(s, 10) + said)
    truth = accounts.delete("partial", truth, a, t)[0]
    return [out, truth, counts]

def checks(rows, counts):
    print("                wrongly   two active   deletions   deleted rows")
    print("                refused   allowed      failed      keeping the address")
    right = []
    for s in accounts.schemes():
        c = [counts[s + " wrong"], counts[s + " dup"], counts[s + " failed"]]
        k = accounts.kept(rows[s])
        d = accounts.deleted(rows[s])
        print("  " + pad(s, 12) + lpad(str(c[0]), 6) + lpad(str(c[1]), 11) + lpad(str(c[2]), 13) + "      " + str(k) + " of " + str(d))
        if c[0] == 0 and c[1] == 0 and c[2] == 0 and k == d:
            right = right + [s]
    print("The rule meant: at most one active account per address.")
    if len(right) > 0:
        names = ""
        for s in right:
            if names == "":
                names = s
            else:
                names = names + ", " + s
        print("Right on every count so far: " + names + ".")
    c = counts["plain wrong"]
    if c > 0:
        print("plain refused " + times(c, "sign-up", "sign-ups") + " the rule allows: its index still counts the deleted rows.")
    k = accounts.kept(rows["nulled"])
    d = accounts.deleted(rows["nulled"])
    if k < d:
        print("nulled decides right, and kept the address of " + str(k) + " of " + times(d, "deleted account", "deleted accounts") + ": the history no longer says whose they were.")
    if counts["compound failed"] > 0:
        print("compound failed " + times(counts["compound failed"], "deletion", "deletions") + ": two deletions of one address in the same second have the same key.")
    if counts["compound wrong"] > 0:
        print("compound refused " + times(counts["compound wrong"], "sign-up", "sign-ups") + " the rule allows: an account whose deletion failed is still active there.")

rows = {}
counts = {}
truth = []
for s in accounts.schemes():
    rows[s] = []
    counts[s + " wrong"] = 0
    counts[s + " dup"] = 0
    counts[s + " failed"] = 0
for a in accounts.opening():
    for s in accounts.schemes():
        rows[s] = accounts.signup(s, rows[s], a)[0]
    truth = truth + [[a, 0]]
t = 2
print("== Member accounts ==")
print("Sign-ups and soft deletes kept four ways, against the rule meant: one active account per address.")
running = True
while running:
    print("")
    print("1) accounts  2) sign up  3) delete  4) next second  5) checks  6) quit")
    choice = plain(input("choice> "))
    if choice == "1":
        show(rows, truth, t)
    elif choice == "2":
        r = signup(rows, truth, counts, t)
        rows = r[0]
        truth = r[1]
        counts = r[2]
    elif choice == "3":
        r = delete(rows, truth, counts, t)
        rows = r[0]
        truth = r[1]
        counts = r[2]
    elif choice == "4":
        t = t + 1
        print("It is second " + str(t) + ".")
    elif choice == "5":
        checks(rows, counts)
    elif choice == "6":
        running = False
    else:
        print("Pick a number from 1 to 6.")
print("Bye.")

accounts.eml

eml
# P143 member accounts - one table of accounts kept four ways. As in the
# corpus case soft-delete-and-uniqueness, a soft delete marks a row instead
# of removing it, and a unique index on the address still counts the
# deleted rows: the rule meant is "at most one ACTIVE account per address".
# A row is [address, second it was deleted]; 0 means active.
#   plain     unique on the address over every row
#   partial   unique on the address among active rows
#   nulled    a deleted row loses its address; unique over the rest
#   compound  unique on the address and the second it was deleted

def schemes():
    return ["plain", "partial", "nulled", "compound"]

def what():
    return ["unique on the address over every row", "unique on the address among active rows", "a deleted row loses its address", "unique on the address and the second it was deleted"]

def key(scheme, row):
    # what the unique index compares; "" is not compared at all
    if scheme == "partial":
        if row[1] > 0:
            return ""
        return row[0]
    if scheme == "compound":
        return row[0] + "@" + str(row[1])
    return row[0]

def clash(scheme, rows, k, skip):
    # another row, not the one at position skip, with the same key
    if k == "":
        return False
    0 => i
    for r in rows:
        if i != skip and key(scheme, r) == k:
            return True
        i + 1 => i
    return False

def active(rows, address):
    0 => i
    for r in rows:
        if r[0] == address and r[1] == 0:
            return i
        i + 1 => i
    return 0 - 1

def signup(scheme, rows, address):
    # [rows, "ok"], or the rows unchanged with "active" or "taken"
    [address, 0] => row
    if clash(scheme, rows, key(scheme, row), 0 - 1):
        if active(rows, address) >= 0:
            return [rows, "active"]
        return [rows, "taken"]
    return [rows + [row], "ok"]

def delete(scheme, rows, address, t):
    # [rows, "ok"], or the rows unchanged with "none" or "clash"
    active(rows, address) => i
    if i < 0:
        return [rows, "none"]
    if scheme == "nulled":
        ["", t] => row
    else:
        [address, t] => row
    if clash(scheme, rows, key(scheme, row), i):
        return [rows, "clash"]
    [] => out
    0 => j
    for r in rows:
        if j == i:
            out + [row] => out
        else:
            out + [r] => out
        j + 1 => j
    return [out, "ok"]

def kept(rows):
    # deleted rows that still record their address
    0 => n
    for r in rows:
        if r[1] > 0 and r[0] != "":
            n + 1 => n
    return n

def deleted(rows):
    0 => n
    for r in rows:
        if r[1] > 0:
            n + 1 => n
    return n

def opening():
    return ["ana@x", "bob@x", "cy@x"]
Python projection (accounts.py)
def schemes():
    return ["plain", "partial", "nulled", "compound"]

def what():
    return ["unique on the address over every row", "unique on the address among active rows", "a deleted row loses its address", "unique on the address and the second it was deleted"]

def key(scheme, row):
    if scheme == "partial":
        if row[1] > 0:
            return ""
        return row[0]
    if scheme == "compound":
        return row[0] + "@" + str(row[1])
    return row[0]

def clash(scheme, rows, k, skip):
    if k == "":
        return False
    i = 0
    for r in rows:
        if i != skip and key(scheme, r) == k:
            return True
        i = i + 1
    return False

def active(rows, address):
    i = 0
    for r in rows:
        if r[0] == address and r[1] == 0:
            return i
        i = i + 1
    return 0 - 1

def signup(scheme, rows, address):
    row = [address, 0]
    if clash(scheme, rows, key(scheme, row), 0 - 1):
        if active(rows, address) >= 0:
            return [rows, "active"]
        return [rows, "taken"]
    return [rows + [row], "ok"]

def delete(scheme, rows, address, t):
    i = active(rows, address)
    if i < 0:
        return [rows, "none"]
    if scheme == "nulled":
        row = ["", t]
    else:
        row = [address, t]
    if clash(scheme, rows, key(scheme, row), i):
        return [rows, "clash"]
    out = []
    j = 0
    for r in rows:
        if j == i:
            out = out + [row]
        else:
            out = out + [r]
        j = j + 1
    return [out, "ok"]

def kept(rows):
    n = 0
    for r in rows:
        if r[1] > 0 and r[0] != "":
            n = n + 1
    return n

def deleted(rows):
    n = 0
    for r in rows:
        if r[1] > 0:
            n = n + 1
    return n

def opening():
    return ["ana@x", "bob@x", "cy@x"]

Built on these corpus cases

ΣEML 2026

Efficient New Language — a high-density semantic overlay for humans and AI agents.

This site’s demos run on the real EML toolchain, in your browser.

© 2026 EveMissLab (一言諾科技有限公司) / Neo.K. All rights reserved.