Project P170

Eligibility rules

300 made-up applicants and three rules written two ways: a negation distributed by hand keeps 56 it should skip, one clause of member-or-referred never decides, and a guard moved behind its test divides by zero.

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

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

300 made-up applicants for a benefit and three rules, each written two ways: who the difference reaches.

  • main.eml - the menu, the applicants, the skip rule, which clause decides an approval, the means test, and an applicant of your own
  • rules.eml - the applicants, drawn from a fixed seed, and each rule in its two forms

How each part works:

  • An applicant is skipped unless a resident adult, approved as a member or a referred applicant, and paid only if the average income on record is under 2,000.00 a month.
  • As in the corpus case the-negation-was-distributed-by-hand, not (resident and adult) rewritten as (not resident) and (not adult) agrees where both clauses hold or both fail, and keeps the applicants who fail exactly one: 56 of the 300, 11 residents under 18 and 45 adults from elsewhere.
  • As in which-clause-actually-decided, "member or referred" is right for every applicant, and of the 101 approvals 76 are carried by membership alone, 25 by both and none by the referral alone: every referred applicant here is a member. That is a fact about who applies.
  • As in the-guard-was-moved-for-readability, the means test with the months checked first answers for all 101; with the average first it gives the same answer on the 94 with months on record and divides by zero on the 7 without.

What is checked: menu choices 1 to 6; y or n (or yes or no) for resident, member and referred; an age from 0 to 120; 0 to 24 months on record; a whole income from 0 to 999999. An empty answer cancels.

Sessions: sessions/basic.in gives: - the applicants, the skip rule, the clauses and the means test; - your own: a 17-year-old resident member (the hand-written rule keeps them), a referred adult from elsewhere with no months on record, and a resident member referred as well, over the income limit.

sessions/bad-input.in gives: - menu choices 0 and x; - a cancel and "maybe" for resident; ages: a cancel, 121 and x; member: a cancel and k; referred: a cancel and q; months: a cancel, 25 and x; income: a cancel, 1000000 and 1.5; - a 16-year-old from elsewhere, neither member nor referred, with 12 months and no income.

Built on the verified corpus cases the-negation-was-distributed-by-hand (a skip condition inverted with the negation distributed as an and), which-clause-actually-decided (administrator or owner, scored by which clause carried each request) and the-guard-was-moved-for-readability (two clauses swapped so the meaningful one reads first).

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
== Eligibility rules ==
Three rules for a benefit, each written two ways, and who the difference reaches.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 0
Pick a number from 1 to 6.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> x
Pick a number from 1 to 6.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> 
Cancelled.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> maybe
Type y or n.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 
Cancelled.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 121
Type a whole number from 0 to 120.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> x
Type a whole number from 0 to 120.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 30
member (y/n)> 
Cancelled.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 30
member (y/n)> k
Type y or n.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 30
member (y/n)> y
referred (y/n)> 
Cancelled.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 30
member (y/n)> y
referred (y/n)> q
Type y or n.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 30
member (y/n)> y
referred (y/n)> n
months of income on record (0 to 24)> 
Cancelled.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 30
member (y/n)> y
referred (y/n)> n
months of income on record (0 to 24)> 25
Type a whole number from 0 to 24.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 30
member (y/n)> y
referred (y/n)> n
months of income on record (0 to 24)> x
Type a whole number from 0 to 24.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 30
member (y/n)> y
referred (y/n)> n
months of income on record (0 to 24)> 4
income over those months, whole units (0 to 999999)> 
Cancelled.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 30
member (y/n)> y
referred (y/n)> n
months of income on record (0 to 24)> 4
income over those months, whole units (0 to 999999)> 1000000
Type a whole number from 0 to 999999.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 30
member (y/n)> y
referred (y/n)> n
months of income on record (0 to 24)> 4
income over those months, whole units (0 to 999999)> 1.5
Type a whole number from 0 to 999999.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> no
age (0 to 120)> 16
member (y/n)> no
referred (y/n)> no
months of income on record (0 to 24)> 12
income over those months, whole units (0 to 999999)> 0
The skip rule: as meant it skips them; written by hand it skips them.
Member or referred: not approved.
The means test: 0.00 a month on average, under 2,000.00, so it passes either way.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 6
Bye.
What was typed (80 lines)
0
x
5

5
maybe
5
y

5
y
121
5
y
x
5
y
30

5
y
30
k
5
y
30
y

5
y
30
y
q
5
y
30
y
n

5
y
30
y
n
25
5
y
30
y
n
x
5
y
30
y
n
4

5
y
30
y
n
4
1000000
5
y
30
y
n
4
1.5
5
no
16
no
no
12
0
6

basic

interpreter: byte-equal
== Eligibility rules ==
Three rules for a benefit, each written two ways, and who the difference reaches.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 1
300 applicants for a benefit; the first eight:
      resident   age  member  referred   months  income on record
  1   yes         34  yes     yes             9         27,900.00
  2   yes         43  no      no              9         16,650.00
  3   no          46  no      no              0              0.00
  4   yes         35  yes     yes             6         14,700.00
  5   yes         60  no      no             10         30,000.00
  6   yes         43  yes     yes             2          6,800.00
  7   yes         61  yes     yes             7         22,400.00
  8   yes         27  yes     no              8         15,200.00
The rules: skip anyone who is not a resident adult; approve a member or a referred applicant; pay only if the average income on record is under 2,000.00 a month.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 2
Skip unless resident and adult, written two ways:
  resident  adult  not (r and a)  not r and not a  applicants
  yes       yes    no             no                      242
  yes       no     yes            no                       11
  no        yes    yes            no                       45
  no        no     yes            yes                       2
The two agree where both clauses hold or both fail. Where exactly one fails, the hand-written form keeps the applicant: 56 of 300 here, the residents under 18 and the adults from elsewhere.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 3
Of the 242 resident adults, 101 are approved, as member or referred. Which clause carried each:
  membership alone     76
  referral alone        0
  both                 25
The referral clause decided 0 approvals: every referred applicant here is a member. The rule is right every time, and half of it has never been the reason - a fact about who applies, not about the code.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 4
The means test on the 101 approved applicants: income on record / months under 2,000.00, and months on record above 0.
Guard first, months checked before the division: an answer for all 101.
Meaning first, the average before the months: the same answer on 94, and a division by zero on the 7 with no months on record.
Moving the guard behind the test it protects reads better and is no longer a guard.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 17
member (y/n)> y
referred (y/n)> n
months of income on record (0 to 24)> 3
income over those months, whole units (0 to 999999)> 4500
The skip rule: as meant it skips them; written by hand it keeps them.
Member or referred: approved, by membership alone.
The means test: 1,500.00 a month on average, under 2,000.00, so it passes either way.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> n
age (0 to 120)> 30
member (y/n)> n
referred (y/n)> y
months of income on record (0 to 24)> 0
The skip rule: as meant it skips them; written by hand it keeps them.
Member or referred: approved, by referral alone.
The means test: guard first, no months on record, so no; meaning first, a division by zero before the guard is read.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 5
resident (y/n)> y
age (0 to 120)> 40
member (y/n)> y
referred (y/n)> y
months of income on record (0 to 24)> 6
income over those months, whole units (0 to 999999)> 15000
The skip rule: as meant it keeps them; written by hand it keeps them.
Member or referred: approved, by both.
The means test: 2,500.00 a month on average, not under 2,000.00, so it fails either way.

1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit
choice> 6
Bye.
What was typed (25 lines)
1
2
3
4
5
y
17
y
n
3
4500
5
n
30
n
y
0
5
y
40
y
y
6
15000
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
# P170 eligibility rules: 300 applicants and three rules written two ways -
# the applicants, the skip rule, which clause decides an approval, the
# means test with its guard moved, and an applicant of your own.
import rules

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 digits(t):
    for c in t:
        if c < "0" or c > "9":
            return False
    return len(t) > 0

def commas(n):
    str(n) => s
    "" => out
    0 => k
    len(s) => i
    while i > 0:
        if k == 3:
            "," + out => out
            0 => k
        s[i - 1] + out => out
        k + 1 => k
        i - 1 => i
    return out

def money(c):
    c % 100 => r
    if r < 10:
        return commas(int((c - r) / 100)) + ".0" + str(r)
    return commas(int((c - r) / 100)) + "." + str(r)

def yn(b):
    if b:
        return "yes"
    return "no"

def show_applicants():
    rules.applicants() => aps
    ("300 applicants for a benefit; the first eight:") ^0
    ("  " + pad("", 4) + pad("resident", 10) + lpad("age", 4) + "  " + pad("member", 8) + pad("referred", 10) + lpad("months", 7) + lpad("income on record", 18)) ^0
    0 => i
    while i < 8:
        aps[i] => a
        ("  " + pad(str(i + 1), 4) + pad(yn(a[0]), 10) + lpad(str(a[1]), 4) + "  " + pad(yn(a[2]), 8) + pad(yn(a[3]), 10) + lpad(str(a[4]), 7) + lpad(money(a[5]), 18)) ^0
        i + 1 => i
    "The rules: skip anyone who is not a resident adult; approve a member or a referred applicant; pay only if the average income on record is under 2,000.00 a month." ^0

def show_skip():
    rules.applicants() => aps
    "Skip unless resident and adult, written two ways:" ^0
    ("  " + pad("resident", 10) + pad("adult", 7) + pad("not (r and a)", 15) + pad("not r and not a", 17) + "applicants") ^0
    [[True, True], [True, False], [False, True], [False, False]] => combos
    0 => differ
    for c in combos:
        0 => n
        for a in aps:
            if a[0] == c[0] and rules.adult(a) == c[1]:
                n + 1 => n
        [c[0], 18] => probe
        if not c[1]:
            [c[0], 17] => probe
        rules.skip_meant(probe) => s1
        rules.skip_by_hand(probe) => s2
        if s1 != s2:
            differ + n => differ
        ("  " + pad(yn(c[0]), 10) + pad(yn(c[1]), 7) + pad(yn(s1), 15) + pad(yn(s2), 17) + lpad(str(n), 10)) ^0
    ("The two agree where both clauses hold or both fail. Where exactly one fails, the hand-written form keeps the applicant: " + str(differ) + " of 300 here, the residents under 18 and the adults from elsewhere.") ^0

def show_clause():
    rules.applicants() => aps
    0 => kept
    0 => yes
    0 => m
    0 => r
    0 => b
    for a in aps:
        if not rules.skip_meant(a):
            kept + 1 => kept
            if rules.approved(a):
                yes + 1 => yes
                rules.decided(a) => d
                if d == "member":
                    m + 1 => m
                if d == "referral":
                    r + 1 => r
                if d == "both":
                    b + 1 => b
    ("Of the " + str(kept) + " resident adults, " + str(yes) + " are approved, as member or referred. Which clause carried each:") ^0
    ("  membership alone   " + lpad(str(m), 4)) ^0
    ("  referral alone     " + lpad(str(r), 4)) ^0
    ("  both               " + lpad(str(b), 4)) ^0
    ("The referral clause decided " + str(r) + " approvals: every referred applicant here is a member. The rule is right every time, and half of it has never been the reason - a fact about who applies, not about the code.") ^0

def show_income():
    rules.applicants() => aps
    0 => zero
    0 => agree
    0 => n
    for a in aps:
        if not rules.skip_meant(a) and rules.approved(a):
            n + 1 => n
            rules.income_guard_first(a) => g
            rules.income_meaning_first(a) => f
            if f == "divides by zero":
                zero + 1 => zero
            elif f == g:
                agree + 1 => agree
    ("The means test on the " + str(n) + " approved applicants: income on record / months under 2,000.00, and months on record above 0.") ^0
    ("Guard first, months checked before the division: an answer for all " + str(n) + ".") ^0
    ("Meaning first, the average before the months: the same answer on " + str(agree) + ", and a division by zero on the " + str(zero) + " with no months on record.") ^0
    "Moving the guard behind the test it protects reads better and is no longer a guard." ^0

def ask_yes(prompt):
    # True, False, or "" when cancelled, "bad" when neither
    plain(input(prompt + " (y/n)> ")) => t
    if t == "":
        return ""
    if t == "y" or t == "yes":
        return True
    if t == "n" or t == "no":
        return False
    return "bad"

def own():
    ask_yes("resident") => res
    if res == "":
        "Cancelled." ^0
        return
    if res == "bad":
        "Type y or n." ^0
        return
    plain(input("age (0 to 120)> ")) => t
    if t == "":
        "Cancelled." ^0
        return
    if len(t) > 3 or not digits(t) or int(t) > 120:
        "Type a whole number from 0 to 120." ^0
        return
    int(t) => age
    ask_yes("member") => mem
    if mem == "":
        "Cancelled." ^0
        return
    if mem == "bad":
        "Type y or n." ^0
        return
    ask_yes("referred") => ref
    if ref == "":
        "Cancelled." ^0
        return
    if ref == "bad":
        "Type y or n." ^0
        return
    plain(input("months of income on record (0 to 24)> ")) => t
    if t == "":
        "Cancelled." ^0
        return
    if len(t) > 2 or not digits(t) or int(t) > 24:
        "Type a whole number from 0 to 24." ^0
        return
    int(t) => months
    0 => total
    if months > 0:
        plain(input("income over those months, whole units (0 to 999999)> ")) => t
        if t == "":
            "Cancelled." ^0
            return
        if len(t) > 6 or not digits(t):
            "Type a whole number from 0 to 999999." ^0
            return
        int(t) * 100 => total
    [res, age, mem, ref, months, total] => a
    ("The skip rule: as meant it " + skipped(rules.skip_meant(a)) + " them; written by hand it " + skipped(rules.skip_by_hand(a)) + " them.") ^0
    if rules.approved(a):
        ("Member or referred: approved, by " + ["membership alone", "referral alone", "both"][index(rules.decided(a))] + ".") ^0
    else:
        "Member or referred: not approved." ^0
    rules.income_guard_first(a) => g
    rules.income_meaning_first(a) => f
    if months == 0:
        "The means test: guard first, no months on record, so no; meaning first, a division by zero before the guard is read." ^0
    else:
        ("The means test: " + money(int(total / months)) + " a month on average, " + verdict(g) + " either way.") ^0

def skipped(b):
    if b:
        return "skips"
    return "keeps"

def index(d):
    if d == "member":
        return 0
    if d == "referral":
        return 1
    return 2

def verdict(g):
    if g:
        return "under 2,000.00, so it passes"
    return "not under 2,000.00, so it fails"

"== Eligibility rules ==" ^0
"Three rules for a benefit, each written two ways, and who the difference reaches." ^0
True => running
while running:
    "" ^0
    "1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit" ^0
    plain(input("choice> ")) => choice
    if choice == "1":
        show_applicants()
    elif choice == "2":
        show_skip()
    elif choice == "3":
        show_clause()
    elif choice == "4":
        show_income()
    elif choice == "5":
        own()
    elif choice == "6":
        False => running
    else:
        "Pick a number from 1 to 6." ^0
"Bye." ^0
Python projection (main.py)
import rules

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 digits(t):
    for c in t:
        if c < "0" or c > "9":
            return False
    return len(t) > 0

def commas(n):
    s = str(n)
    out = ""
    k = 0
    i = len(s)
    while i > 0:
        if k == 3:
            out = "," + out
            k = 0
        out = s[i - 1] + out
        k = k + 1
        i = i - 1
    return out

def money(c):
    r = c % 100
    if r < 10:
        return commas(int((c - r) / 100)) + ".0" + str(r)
    return commas(int((c - r) / 100)) + "." + str(r)

def yn(b):
    if b:
        return "yes"
    return "no"

def show_applicants():
    aps = rules.applicants()
    print("300 applicants for a benefit; the first eight:")
    print("  " + pad("", 4) + pad("resident", 10) + lpad("age", 4) + "  " + pad("member", 8) + pad("referred", 10) + lpad("months", 7) + lpad("income on record", 18))
    i = 0
    while i < 8:
        a = aps[i]
        print("  " + pad(str(i + 1), 4) + pad(yn(a[0]), 10) + lpad(str(a[1]), 4) + "  " + pad(yn(a[2]), 8) + pad(yn(a[3]), 10) + lpad(str(a[4]), 7) + lpad(money(a[5]), 18))
        i = i + 1
    print("The rules: skip anyone who is not a resident adult; approve a member or a referred applicant; pay only if the average income on record is under 2,000.00 a month.")

def show_skip():
    aps = rules.applicants()
    print("Skip unless resident and adult, written two ways:")
    print("  " + pad("resident", 10) + pad("adult", 7) + pad("not (r and a)", 15) + pad("not r and not a", 17) + "applicants")
    combos = [[True, True], [True, False], [False, True], [False, False]]
    differ = 0
    for c in combos:
        n = 0
        for a in aps:
            if a[0] == c[0] and rules.adult(a) == c[1]:
                n = n + 1
        probe = [c[0], 18]
        if not c[1]:
            probe = [c[0], 17]
        s1 = rules.skip_meant(probe)
        s2 = rules.skip_by_hand(probe)
        if s1 != s2:
            differ = differ + n
        print("  " + pad(yn(c[0]), 10) + pad(yn(c[1]), 7) + pad(yn(s1), 15) + pad(yn(s2), 17) + lpad(str(n), 10))
    print("The two agree where both clauses hold or both fail. Where exactly one fails, the hand-written form keeps the applicant: " + str(differ) + " of 300 here, the residents under 18 and the adults from elsewhere.")

def show_clause():
    aps = rules.applicants()
    kept = 0
    yes = 0
    m = 0
    r = 0
    b = 0
    for a in aps:
        if not rules.skip_meant(a):
            kept = kept + 1
            if rules.approved(a):
                yes = yes + 1
                d = rules.decided(a)
                if d == "member":
                    m = m + 1
                if d == "referral":
                    r = r + 1
                if d == "both":
                    b = b + 1
    print("Of the " + str(kept) + " resident adults, " + str(yes) + " are approved, as member or referred. Which clause carried each:")
    print("  membership alone   " + lpad(str(m), 4))
    print("  referral alone     " + lpad(str(r), 4))
    print("  both               " + lpad(str(b), 4))
    print("The referral clause decided " + str(r) + " approvals: every referred applicant here is a member. The rule is right every time, and half of it has never been the reason - a fact about who applies, not about the code.")

def show_income():
    aps = rules.applicants()
    zero = 0
    agree = 0
    n = 0
    for a in aps:
        if not rules.skip_meant(a) and rules.approved(a):
            n = n + 1
            g = rules.income_guard_first(a)
            f = rules.income_meaning_first(a)
            if f == "divides by zero":
                zero = zero + 1
            elif f == g:
                agree = agree + 1
    print("The means test on the " + str(n) + " approved applicants: income on record / months under 2,000.00, and months on record above 0.")
    print("Guard first, months checked before the division: an answer for all " + str(n) + ".")
    print("Meaning first, the average before the months: the same answer on " + str(agree) + ", and a division by zero on the " + str(zero) + " with no months on record.")
    print("Moving the guard behind the test it protects reads better and is no longer a guard.")

def ask_yes(prompt):
    t = plain(input(prompt + " (y/n)> "))
    if t == "":
        return ""
    if t == "y" or t == "yes":
        return True
    if t == "n" or t == "no":
        return False
    return "bad"

def own():
    res = ask_yes("resident")
    if res == "":
        print("Cancelled.")
        return
    if res == "bad":
        print("Type y or n.")
        return
    t = plain(input("age (0 to 120)> "))
    if t == "":
        print("Cancelled.")
        return
    if len(t) > 3 or not digits(t) or int(t) > 120:
        print("Type a whole number from 0 to 120.")
        return
    age = int(t)
    mem = ask_yes("member")
    if mem == "":
        print("Cancelled.")
        return
    if mem == "bad":
        print("Type y or n.")
        return
    ref = ask_yes("referred")
    if ref == "":
        print("Cancelled.")
        return
    if ref == "bad":
        print("Type y or n.")
        return
    t = plain(input("months of income on record (0 to 24)> "))
    if t == "":
        print("Cancelled.")
        return
    if len(t) > 2 or not digits(t) or int(t) > 24:
        print("Type a whole number from 0 to 24.")
        return
    months = int(t)
    total = 0
    if months > 0:
        t = plain(input("income over those months, whole units (0 to 999999)> "))
        if t == "":
            print("Cancelled.")
            return
        if len(t) > 6 or not digits(t):
            print("Type a whole number from 0 to 999999.")
            return
        total = int(t) * 100
    a = [res, age, mem, ref, months, total]
    print("The skip rule: as meant it " + skipped(rules.skip_meant(a)) + " them; written by hand it " + skipped(rules.skip_by_hand(a)) + " them.")
    if rules.approved(a):
        print("Member or referred: approved, by " + ["membership alone", "referral alone", "both"][index(rules.decided(a))] + ".")
    else:
        print("Member or referred: not approved.")
    g = rules.income_guard_first(a)
    f = rules.income_meaning_first(a)
    if months == 0:
        print("The means test: guard first, no months on record, so no; meaning first, a division by zero before the guard is read.")
    else:
        print("The means test: " + money(int(total / months)) + " a month on average, " + verdict(g) + " either way.")

def skipped(b):
    if b:
        return "skips"
    return "keeps"

def index(d):
    if d == "member":
        return 0
    if d == "referral":
        return 1
    return 2

def verdict(g):
    if g:
        return "under 2,000.00, so it passes"
    return "not under 2,000.00, so it fails"

print("== Eligibility rules ==")
print("Three rules for a benefit, each written two ways, and who the difference reaches.")
running = True
while running:
    print("")
    print("1) the applicants  2) the skip rule  3) which clause decides  4) the means test  5) an applicant of your own  6) quit")
    choice = plain(input("choice> "))
    if choice == "1":
        show_applicants()
    elif choice == "2":
        show_skip()
    elif choice == "3":
        show_clause()
    elif choice == "4":
        show_income()
    elif choice == "5":
        own()
    elif choice == "6":
        running = False
    else:
        print("Pick a number from 1 to 6.")
print("Bye.")

rules.eml

eml
# P170 eligibility rules - 300 made-up applicants for a benefit, and three
# rules each written two ways. As in the corpus case
# the-negation-was-distributed-by-hand, "skip unless resident and adult"
# rewritten as "skip if not resident and not adult" skips only those who
# fail both. As in which-clause-actually-decided, "member or referred" is
# right every time, and in this population the referral clause never
# decides. And as in the-guard-was-moved-for-readability, an average
# income test reads better with the average first, and then divides by
# zero for anyone with no months on record.

def limit():
    # average monthly income below which the benefit is paid, in cents
    return 200000

def step(x):
    return (x * 48271) % 2147483647

def applicants():
    # [resident, age, member, referred, months on record, total income in cents]
    [0] * 300 => out
    424242 => x
    0 => k
    while k < 300:
        step(x) => x
        x % 100 < 85 => resident
        step(x) => x
        14 + x % 67 => age
        step(x) => x
        x % 100 < 40 => member
        step(x) => x
        member and x % 100 < 30 => referred
        step(x) => x
        x % 13 => months
        step(x) => x
        months * (50000 + 5000 * (x % 71)) => total
        [resident, age, member, referred, months, total] => out[k]
        k + 1 => k
    return out

def adult(a):
    return a[1] >= 18

def skip_meant(a):
    # skip unless a resident adult
    return not (a[0] and adult(a))

def skip_by_hand(a):
    # the negation distributed by hand
    return not a[0] and not adult(a)

def approved(a):
    return a[2] or a[3]

def decided(a):
    # which clause carried an approval: "member", "referral" or "both"
    if a[2] and a[3]:
        return "both"
    if a[2]:
        return "member"
    if a[3]:
        return "referral"
    return "neither"

def income_guard_first(a):
    # True, False: the applicant passes the means test, guard read first
    if a[4] > 0:
        if a[5] < limit() * a[4]:
            return True
    return False

def income_meaning_first(a):
    # the average first: "divides by zero" when there are no months
    if a[4] == 0:
        return "divides by zero"
    if a[5] / a[4] < limit():
        if a[4] > 0:
            return True
    return False
Python projection (rules.py)
def limit():
    return 200000

def step(x):
    return x * 48271 % 2147483647

def applicants():
    out = [0] * 300
    x = 424242
    k = 0
    while k < 300:
        x = step(x)
        resident = x % 100 < 85
        x = step(x)
        age = 14 + x % 67
        x = step(x)
        member = x % 100 < 40
        x = step(x)
        referred = member and x % 100 < 30
        x = step(x)
        months = x % 13
        x = step(x)
        total = months * (50000 + 5000 * (x % 71))
        out[k] = [resident, age, member, referred, months, total]
        k = k + 1
    return out

def adult(a):
    return a[1] >= 18

def skip_meant(a):
    return not (a[0] and adult(a))

def skip_by_hand(a):
    return not a[0] and not adult(a)

def approved(a):
    return a[2] or a[3]

def decided(a):
    if a[2] and a[3]:
        return "both"
    if a[2]:
        return "member"
    if a[3]:
        return "referral"
    return "neither"

def income_guard_first(a):
    if a[4] > 0:
        if a[5] < limit() * a[4]:
            return True
    return False

def income_meaning_first(a):
    if a[4] == 0:
        return "divides by zero"
    if a[5] / a[4] < limit():
        if a[4] > 0:
            return True
    return False

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.