Project P160

Upload limits

One upload endpoint limited by files, by bytes and by both: 100 files lets in anywhere from under a megabyte to hundreds, and a byte limit bounds the most any upload gets in.

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

One upload endpoint limited three ways - by files, by bytes and by both - and the most each lets in.

  • main.eml - the menu, the uploads, the uploads under each limit, and an upload of your own
  • limits.eml - the two limits, the uploads and the sizes of their files, and what a limit lets in

How each part works:

  • Four uploads: 150 thumbnails of about 8 kB, 60 receipts of about 120 kB, 100 photos of about 3.5 MB and 40 scans of about 9 MB.
  • As in the corpus case cost-model-mismatch, a limit of 100 files is written in the unit that is easy to count, and what runs out is memory and bytes on the wire. Under it an upload gets anywhere from 0.9 MB to 432.0 MB in.
  • A limit is judged by the most it lets in, not by making uploads alike: at 20.0 MB the byte limit lets the small uploads through whole and stops every upload at 20.0 MB, 19.6 MB at most here. Both limits together never let in more than either alone.

What is checked: menu choices 1 to 4; for an upload of your own, 1 to 999 files of about 1 to 99999 kB each. An empty answer cancels.

Sessions: sessions/basic.in gives: - the uploads and the limits; - 300 files of about 9000 kB, and 20 files of about 5 kB.

sessions/bad-input.in gives: - menu choices 0 and x; - files: a cancel, 0, 1000 and x; then 10 files with a cancel, 0, 100000 and x for the size; - 150 files of about 8 kB, where the file limit lets in less than the byte limit.

Built on the verified corpus case cost-model-mismatch (the same workloads through a count limit, a size limit and both, judged by the maximum each admits).

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
== Upload limits ==
One upload endpoint limited by files, by bytes and by both, and what each lets in.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 0
Pick a number from 1 to 4.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> x
Pick a number from 1 to 4.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 3
how many files (1 to 999)> 
Cancelled.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 3
how many files (1 to 999)> 0
Type a whole number from 1 to 999.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 3
how many files (1 to 999)> 1000
Type a whole number from 1 to 999.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 3
how many files (1 to 999)> x
Type a whole number from 1 to 999.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 3
how many files (1 to 999)> 10
about how many kB each (1 to 99999)> 
Cancelled.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 3
how many files (1 to 999)> 10
about how many kB each (1 to 99999)> 0
Type a whole number from 1 to 99999.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 3
how many files (1 to 999)> 10
about how many kB each (1 to 99999)> 100000
Type a whole number from 1 to 99999.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 3
how many files (1 to 999)> 10
about how many kB each (1 to 99999)> x
Type a whole number from 1 to 99999.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 3
how many files (1 to 999)> 150
about how many kB each (1 to 99999)> 8
  upload      100 files             20.0 MB               both
  yours       100 files, 0.9 MB     150 files, 1.4 MB     100 files, 0.9 MB
The file limit lets in 0.9 MB of it, the byte limit 1.4 MB, both 0.9 MB.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 4
Bye.
What was typed (26 lines)
0
x
3

3
0
3
1000
3
x
3
10

3
10
0
3
10
100000
3
10
x
3
150
8
4

basic

interpreter: byte-equal
== Upload limits ==
One upload endpoint limited by files, by bytes and by both, and what each lets in.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 1
The uploads, as their files come in:
  thumbnails   150 files of about    8 kB,    1.4 MB in all
  receipts      60 files of about  120 kB,    8.6 MB in all
  photos       100 files of about 3500 kB,  420.0 MB in all
  scans         40 files of about 9000 kB,  432.0 MB in all
The limits: at most 100 files; at most 20.0 MB; or both.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 2
  upload      100 files             20.0 MB               both
  thumbnails  100 files, 0.9 MB     150 files, 1.4 MB     100 files, 0.9 MB
  receipts    60 files, 8.6 MB      60 files, 8.6 MB      60 files, 8.6 MB
  photos      100 files, 420.0 MB   5 files, 19.6 MB      5 files, 19.6 MB
  scans       40 files, 432.0 MB    2 files, 18.9 MB      2 files, 18.9 MB
The most let in: 432.0 MB under the file limit, 19.6 MB under the byte limit, 19.6 MB under both.
Under the 100-file limit an upload gets anywhere from 0.9 MB to 432.0 MB in: the limit counts what is easy to count, not what runs out.
The byte limit lets small uploads through whole and stops every upload at 20.0 MB: a limit bounds the most, it does not make uploads alike.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 3
how many files (1 to 999)> 300
about how many kB each (1 to 99999)> 9000
  upload      100 files             20.0 MB               both
  yours       100 files, 1080.0 MB  2 files, 18.9 MB      2 files, 18.9 MB
The file limit lets in 1080.0 MB of it, the byte limit 18.9 MB, both 18.9 MB.
Counted in files, the limit does not hold back the bytes that run out.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 3
how many files (1 to 999)> 20
about how many kB each (1 to 99999)> 5
  upload      100 files             20.0 MB               both
  yours       20 files, 0.1 MB      20 files, 0.1 MB      20 files, 0.1 MB
The file limit lets in 0.1 MB of it, the byte limit 0.1 MB, both 0.1 MB.

1) the uploads  2) the limits  3) an upload of your own  4) quit
choice> 4
Bye.
What was typed (9 lines)
1
2
3
300
9000
3
20
5
4

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
# P160 upload limits: the uploads, each one under a limit on files, on
# bytes and on both, and an upload of your own.
import limits

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 mb(kb):
    # kilobytes as megabytes to one place, rounded half up
    int((kb + 50) / 100) => t
    t % 10 => d
    return str(int((t - d) / 10)) + "." + str(d) + " MB"

def total(sizes):
    0 => t
    for s in sizes:
        t + s => t
    return t

def show_uploads():
    "The uploads, as their files come in:" ^0
    for u in limits.uploads():
        limits.files(u) => fs
        ("  " + pad(u[0], 12) + lpad(str(len(fs)), 4) + " files of about " + lpad(str(u[2]), 4) + " kB, " + lpad(mb(total(fs)), 9) + " in all") ^0
    ("The limits: at most " + str(limits.count_limit()) + " files; at most " + mb(limits.byte_limit()) + "; or both.") ^0

def cell(r):
    return str(r[0]) + " files, " + mb(r[1])

def compare(us):
    ("  " + pad("upload", 12) + pad("100 files", 22) + pad("20.0 MB", 22) + "both") ^0
    [0, 0, 0] => most
    [0, 0, 0] => least
    0 => first
    for u in us:
        limits.files(u) => fs
        [limits.admit(fs, "count"), limits.admit(fs, "bytes"), limits.admit(fs, "both")] => rs
        ("  " + pad(u[0], 12) + pad(cell(rs[0]), 22) + pad(cell(rs[1]), 22) + cell(rs[2])) ^0
        0 => k
        while k < 3:
            if rs[k][1] > most[k]:
                rs[k][1] => most[k]
            if first == 0 or rs[k][1] < least[k]:
                rs[k][1] => least[k]
            k + 1 => k
        1 => first
    if len(us) == 1:
        ("The file limit lets in " + mb(most[0]) + " of it, the byte limit " + mb(most[1]) + ", both " + mb(most[2]) + ".") ^0
        if most[0] > limits.byte_limit():
            "Counted in files, the limit does not hold back the bytes that run out." ^0
    else:
        ("The most let in: " + mb(most[0]) + " under the file limit, " + mb(most[1]) + " under the byte limit, " + mb(most[2]) + " under both.") ^0
        if most[0] > limits.byte_limit():
            ("Under the 100-file limit an upload gets anywhere from " + mb(least[0]) + " to " + mb(most[0]) + " in: the limit counts what is easy to count, not what runs out.") ^0
        "The byte limit lets small uploads through whole and stops every upload at 20.0 MB: a limit bounds the most, it does not make uploads alike." ^0

def own():
    plain(input("how many files (1 to 999)> ")) => t
    if t == "":
        "Cancelled." ^0
        return
    if len(t) > 3 or not digits(t) or int(t) < 1:
        "Type a whole number from 1 to 999." ^0
        return
    plain(input("about how many kB each (1 to 99999)> ")) => k
    if k == "":
        "Cancelled." ^0
        return
    if len(k) > 5 or not digits(k) or int(k) < 1:
        "Type a whole number from 1 to 99999." ^0
        return
    ["yours", int(t), int(k)] => u
    compare([u])

def digits(t):
    for c in t:
        if c < "0" or c > "9":
            return False
    return len(t) > 0

"== Upload limits ==" ^0
"One upload endpoint limited by files, by bytes and by both, and what each lets in." ^0
True => running
while running:
    "" ^0
    "1) the uploads  2) the limits  3) an upload of your own  4) quit" ^0
    plain(input("choice> ")) => choice
    if choice == "1":
        show_uploads()
    elif choice == "2":
        compare(limits.uploads())
    elif choice == "3":
        own()
    elif choice == "4":
        False => running
    else:
        "Pick a number from 1 to 4." ^0
"Bye." ^0
Python projection (main.py)
import limits

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 mb(kb):
    t = int((kb + 50) / 100)
    d = t % 10
    return str(int((t - d) / 10)) + "." + str(d) + " MB"

def total(sizes):
    t = 0
    for s in sizes:
        t = t + s
    return t

def show_uploads():
    print("The uploads, as their files come in:")
    for u in limits.uploads():
        fs = limits.files(u)
        print("  " + pad(u[0], 12) + lpad(str(len(fs)), 4) + " files of about " + lpad(str(u[2]), 4) + " kB, " + lpad(mb(total(fs)), 9) + " in all")
    print("The limits: at most " + str(limits.count_limit()) + " files; at most " + mb(limits.byte_limit()) + "; or both.")

def cell(r):
    return str(r[0]) + " files, " + mb(r[1])

def compare(us):
    print("  " + pad("upload", 12) + pad("100 files", 22) + pad("20.0 MB", 22) + "both")
    most = [0, 0, 0]
    least = [0, 0, 0]
    first = 0
    for u in us:
        fs = limits.files(u)
        rs = [limits.admit(fs, "count"), limits.admit(fs, "bytes"), limits.admit(fs, "both")]
        print("  " + pad(u[0], 12) + pad(cell(rs[0]), 22) + pad(cell(rs[1]), 22) + cell(rs[2]))
        k = 0
        while k < 3:
            if rs[k][1] > most[k]:
                most[k] = rs[k][1]
            if first == 0 or rs[k][1] < least[k]:
                least[k] = rs[k][1]
            k = k + 1
        first = 1
    if len(us) == 1:
        print("The file limit lets in " + mb(most[0]) + " of it, the byte limit " + mb(most[1]) + ", both " + mb(most[2]) + ".")
        if most[0] > limits.byte_limit():
            print("Counted in files, the limit does not hold back the bytes that run out.")
    else:
        print("The most let in: " + mb(most[0]) + " under the file limit, " + mb(most[1]) + " under the byte limit, " + mb(most[2]) + " under both.")
        if most[0] > limits.byte_limit():
            print("Under the 100-file limit an upload gets anywhere from " + mb(least[0]) + " to " + mb(most[0]) + " in: the limit counts what is easy to count, not what runs out.")
        print("The byte limit lets small uploads through whole and stops every upload at 20.0 MB: a limit bounds the most, it does not make uploads alike.")

def own():
    t = plain(input("how many files (1 to 999)> "))
    if t == "":
        print("Cancelled.")
        return
    if len(t) > 3 or not digits(t) or int(t) < 1:
        print("Type a whole number from 1 to 999.")
        return
    k = plain(input("about how many kB each (1 to 99999)> "))
    if k == "":
        print("Cancelled.")
        return
    if len(k) > 5 or not digits(k) or int(k) < 1:
        print("Type a whole number from 1 to 99999.")
        return
    u = ["yours", int(t), int(k)]
    compare([u])

def digits(t):
    for c in t:
        if c < "0" or c > "9":
            return False
    return len(t) > 0

print("== Upload limits ==")
print("One upload endpoint limited by files, by bytes and by both, and what each lets in.")
running = True
while running:
    print("")
    print("1) the uploads  2) the limits  3) an upload of your own  4) quit")
    choice = plain(input("choice> "))
    if choice == "1":
        show_uploads()
    elif choice == "2":
        compare(limits.uploads())
    elif choice == "3":
        own()
    elif choice == "4":
        running = False
    else:
        print("Pick a number from 1 to 4.")
print("Bye.")

limits.eml

eml
# P160 upload limits - one upload endpoint, limited three ways. As in the
# corpus case cost-model-mismatch, a limit of 100 files is written in the
# unit that is easy to count, and what runs out is memory and bytes on the
# wire: 100 files is anywhere from a few kilobytes to many megabytes,
# depending on who is uploading. A limit's job is to bound the most it lets
# in, not to make every upload the same size, so each limit is judged by the
# largest upload it admits. Sizes are in kilobytes.

def count_limit():
    return 100

def byte_limit():
    # 20 megabytes, in kilobytes
    return 20000

def uploads():
    # [name, the sizes of its files in kilobytes, in the order they come]
    return [["thumbnails", 150, 8], ["receipts", 60, 120], ["photos", 100, 3500], ["scans", 40, 9000]]

def files(u):
    # the sizes of upload u's files: u[1] of them, sizes around u[2]
    [] => out
    0 => i
    while i < u[1]:
        out + [u[2] + int((i % 5) * u[2] / 10)] => out
        i + 1 => i
    return out

def admit(sizes, mode):
    # [files let in, kilobytes let in, files refused]
    0 => n
    0 => kb
    0 => refused
    for s in sizes:
        True => ok
        if mode == "count" or mode == "both":
            if n >= count_limit():
                False => ok
        if mode == "bytes" or mode == "both":
            if kb + s > byte_limit():
                False => ok
        if ok:
            n + 1 => n
            kb + s => kb
        else:
            refused + 1 => refused
    return [n, kb, refused]
Python projection (limits.py)
def count_limit():
    return 100

def byte_limit():
    return 20000

def uploads():
    return [["thumbnails", 150, 8], ["receipts", 60, 120], ["photos", 100, 3500], ["scans", 40, 9000]]

def files(u):
    out = []
    i = 0
    while i < u[1]:
        out = out + [u[2] + int(i % 5 * u[2] / 10)]
        i = i + 1
    return out

def admit(sizes, mode):
    n = 0
    kb = 0
    refused = 0
    for s in sizes:
        ok = True
        if mode == "count" or mode == "both":
            if n >= count_limit():
                ok = False
        if mode == "bytes" or mode == "both":
            if kb + s > byte_limit():
                ok = False
        if ok:
            n = n + 1
            kb = kb + s
        else:
            refused = refused + 1
    return [n, kb, refused]

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.