Changelog
All notable changes to NME are recorded here.
Unreleased
0.9.1
- Compiling is 2.9× faster, and produces exactly the same Python. The
largest bundled example,
examples/peace.ko.nmeat 4,337 lines, took 2,254 ms and now takes 780 ms. Every one of the 68 bundled examples was compiled before and after and compared byte for byte; all 68 are identical, and the 786 tests are unchanged. Nothing about the language moved.- The compiler is what the site runs, in WebAssembly, as you type. At 2.2 seconds a program of that size froze the browser tab for four seconds on every keystroke, and on a phone it was unusable. Speed here is not a nicety; it is whether the page works at all.
- Repairing a typo no longer allocates before it knows there is anything to
repair.
one_typo_awaycollected both words intoVec<char>before looking at their lengths — 5.3 million calls for that one file, so 10.5 million heap allocations, 21% of the time. It walks the characters instead and allocates nothing.action_typo_awaycloned a whole vector once per character position, twice over, 7.1 million times; it now reads around the dropped position without building the shortened word. - The questions that do not depend on the candidate are asked once per table instead of once per spelling. Whether a written word can be repaired at all — its length, whether it is a word the compiler already knows, whether it is ordinary English — and its lower-case form were being worked out again for every entry in tables that hold hundreds.
- The same question is no longer asked six times over. On that file
913,265 fuzzy word-match queries resolve to 148,289 distinct ones, because
forty matchers walk the same line and several are worked out three and four
times.
best_action_rankis a pure function of the word, the table and the mode, so its answers are remembered for the length of one parse and thrown away after it. A table is named by its address, which is a name for it only because the type says'static: a temporary list will not compile there. - One quadratic is gone.
count_remaining_endsre-walked the rest of the file for every line. It cost little on a 4,000-line program and 3.5 seconds on a 32,000-line one; a single backward pass now answers it for every line at once.
0.9.0
- A comparison that can never be true is refused, not compiled (
E0606). A word that matches a name filled further up is read as that name's value. So in a program that says수호룬은 거짓, the line만약에 선택이 수호룬과 같으면after선택을 물어봐 수호룬, 폭약weighs what the reader typed againstFalse, and that branch runs for no input at all. Neither compiling nor running said a word, so the program was quietly wrong for ever. Now it stops there and says what each side holds.- An answer taken with
askand weighed against a number is caught in the same place —ask reply Type a numberfollowed byif reply equals 7. That one is told aboutask numberas well. - A menu word that is also the name of a job is caught too: with
job attack:further up,if action equals attackweighs typed text against the job itself. - Looking something up in a list is read the same way. Under
set sword to false,if bag contains swordsearches a list of words for true-or-false and never finds it. Only a list written out in one go and never added to is read this way. - A condition written as Python at the middle level —
만약 선택 == 수호룬:— gets the same check. Onename == valueshape only; brackets, arithmetic and calls are left to Python. - The pairs it catches are those among text, a number, true/false, a list, a
record and a job that cannot meet. A number against true/false is not one
of them: Python answers
True == 1withTrue, so those two really can. - What a name holds is decided by reading the whole program. A name given two different kinds, or one that a line of plain Python so much as mentions, is dropped from the check — it speaks only when it is certain.
- None of the 158 examples that ship with NME, and none of the 1,011 programs in the documentation, is caught by it.
- ⚠What it reaches today: a name's kind is read from two statements only,
setandask. One line ofadd 1 to scoredropsscorefrom the check for that whole file, and a counter is almost always written that way — so what this release catches is mostly names set once and left alone. Reading the kind through an update (a number stays a number, text stays text) would widen it a long way; it is left for later so this release carries one rule and not two. - ⚠A loop condition can have no
else, so an always-true one is never reported: a loop that leaves only throughbreakis ordinary.
- An answer taken with
- The Korean side of guide 31 (the bank) was teaching output it did not
produce. With
잔액은 50above it,잔액이 모자랍니다 말해줘printed50이 모자랍니다, because잔액was already a name; the guide said잔액이 모자랍니다came out. The sentence is now돈이 모자랍니다. The English side always saidshow there is not enoughand never had this. - The Korean language reference showed a question with the previous answer
inside it. Right under
이름을 물어봐 …, the line물어봐 이름, 이름이 뭐예요?put what had just been typed into the question, because이름was a name by then. The second line is now물어봐 별명, 별명이 뭐예요?. - The output check could not see any of that.
check-guide-output.pydropped every promised span that also appeared in the program, on the grounds that a guide quoting its own code is not promising output. On a line that shows something, those words are the output. It no longer drops them there, and the bank guide turned red the moment it stopped. - A job can hand an answer back.
give back <value>oranswer with <value>inside it, andset answer to the result of double with 5outside (결과로 <값> 돌려줘and답은 5에게 두배 한 결과). Until now the only way to get one value out of a job was to make it change a list that lived outside it: a list built, appended to and read back, to carry one number.give backand돌려줘only mean that inside a job.give back the bookoutside one is the sentence it looks like and prints.the result ofcarries the same kind of gate — the name has to be one this program has already made a job — soshow the result of yesterdaystays a sentence.- It is a value, so it works in output, in a saved name, and in a condition, and it is written the same way in all six cells.
0.8.0
- A
면that a name merely happens to end in no longer eats the assignment.적이름은 황금가면 도적왕 레마르compiled toif (적이름 == "황금가"): print("도적왕 레마르")— the assignment gone, the name never made — and the compiler, the checker and the tidier all said nothing. Korean names end in that syllable all the time (장면,측면,수면), so a connector found only inside a word is now treated as the weakest evidence of a comparison there is.- With nothing to do after it, the line is not a comparison. The block form
이름이 철수면has its work on the lines underneath and still compares. - With something to do after it, an opening
은/는wins. Those are how Korean spells this name is given this value; a comparison spells its subject with이/가. A number or an already-made name on the left keeps comparing, so나이는 20이면 어른 말해줘reads as it always did.
- With nothing to do after it, the line is not a comparison. The block form
- Sentences can ask for the whole number of a division.
set rows to the whole number of score divided by people(줄수는 점수를 인원으로 나눈 몫).divideis Python's/, so its answer is a fraction, and a fraction cannot be a position in a list, a number of repeats, or a score saved as digits — the program stops where one is used as any of those. Until now the only way to write it in sentences was to count down by repeated subtraction: a loop to say one thing. It pairs withthe remainder of. - Text written in digits can be read back as a number.
set level to levelText as a number(레벨은 레벨글을 숫자로 바꾼 것).ask numberalready does this at the moment the answer is typed; text the program already holds — a piece cut out of a saved line, an item taken from a list, a line read out of a file — had no sentence for it at all. Text that is not a number stops the program where it stands rather than standing in for zero. - A joined list can be given a name.
set line to friends joined by comma(한줄은 친구들을 쉼표로 이은 것).show friends joined by commaonly ever put it on the screen, and the documentation had no sentence for keeping it. - The tidier writes Korean particles onto the word they mark.
친구들 개수 가and인원 로came back with a space in them; they are now친구들 개수가and인원으로, which is both what the syntax reference shows and what a Korean writer types. - The syntax reference now says that a name a job reads has to exist above
the job.
docs/syntax.md§23. A word given its value further down the file is read as text, which compiles and then stops the program at run time.
0.7.1
- Everything between two separators is one choice, however many words it
is.
pick from stone golem or black knightcame apart into four choices and said nothing about it: the program fought agolemsome rounds and astoneothers. A list already readslist of stone golem, black knightas two things, and a pick now reads the same way.
0.7.0
- The tidier lands one program in one place, whichever of the six it came
from. A file written as sentences, at beginner level, in Korean, in
English, or as ordinary Python now converts into any of the other five and
comes back written the way that one writes it. Before,
advanced → sentencemoved almost nothing: the converter knew a dozen shapes of Python and the tidier knew a hundred and fifty statements, and the two halves had never been put together. A line of Python is now read back into the statement that would have written it, and the words come from the same place they come from for a line that was already NME.- Nothing is guessed. Every reading is lowered again and kept only when the Python that comes back is the line that went in, and the whole file is transpiled once more before any of it is handed over.
- A statement now offers more than one spelling — the same line written
plainly, or at the other level — and the file takes the best one it can:
show HellowhereHellois also a name comes out as말해 "Hello"rather than staying in English. - Blocks keep the way they close. A
:on a header whose block is closed byendleaves theendclosing nothing, so the mark the writer used is the mark that comes back. 30% chance:and아니면:are read, the waysay: helloalready was.- A Korean particle is now the one the word takes, including for a name that
is one letter (
p는, notp은), so tidying makes them uniform instead of leaving each as it was found. scripts/check-tidy-parity.pyproves it: 3225 conversions, every ordered pair of the six cells, every capability in the reference.
- A Korean line that ends on an output word is telling something.
foeName goes down 말해줘was refused, becausedownwas read as the word for taking a number away. Korean puts its verb at the end, so everything in front of the output word is what the line says. - A question keeps its own name.
ask number age 몇 살이에요?askedage 몇 살이에요?: the Korean question forms read the word in front of them as the name they answer, and the name the writer had already given was swallowed. A Korean question is about a Korean word, so a name in Latin letters in front of one is the writer's own. save friends to ["Mina", "Ada"]makes a list. Only the sentence spelling used to, soappend Bo to friendsunder a beginner line was refused for a list nobody had made.- A word typed with its space missing comes apart and reads.
sayhello,showhello,안녕말하기,setscore to 0,점수는0,wait3 seconds,2초대기해,점수에1더해and3번반복해서 안녕 말해줘all do what they say. NME had always worked out where the space goes — that is what the old message handed over — so it now puts the space back and reads the line instead of describing it. A split is only taken when one of its pieces is a word NME knows and the whole reads as a statement, which is whystory of a small town doctor,Nearly finishedanda story worth tellingare still sentences, and whywait3 applesis still named. - Writing into a record and reading out of one are told apart by the shape
of the value.
set Mina to 90 in agesandset best to Mina in agesare the same six words in the same order and mean opposite things. The first is somebody writing 90 down under Mina, and it used to becomeMina = ages[90]and die when it ran. What followstonow decides: a number or a quoted string is a value being written, a word is a name being read. Both stay, and a record kept under numbers is still readable by putting the number in a name first. - A full stop stays punctuation when the action word is written last.
Hello. Goodbyealready printed, butHello. Goodbye show— and every Korean line, where the verb goes last — went to Python as an attribute lookup, compiled without a word in a browser and died when it ran. - The first guide explains a line that starts with
#. Beginners read the comments at the top of an example as part of the program. One step now shows that they are notes left for a person and that deleting every one of them changes nothing.
0.6.0
- A program written one step in is read, and its Python comes back without
the margin.
say hellois what a block of text copied out of a page looks like, and CPython answers it withIndentationErrorbefore anything else is read. The first line of a file has nothing above it to be indented under, so its indentation is the file's own left margin. Only whitespace every line shares is taken off, so nothing inside the program moves, and a program holding a triple-quoted string is left exactly as it is. A line indented further down with nothing opening a block is still named. - A
:written where Python puts one is read past.say: hello,말해줘: 안녕,3번 반복해:,if score is greater than 10: show wonand만약에 점수가 10보다 크면: 성공 말해줘all work. Every Python page ends a header with the mark, so a reader who has seen one writes it; NME does not need it and no longer refuses a line for carrying it. A story block's own:and a Python annotation (x: int = 5) are untouched, and안녕 말해줘:keeps the mark out of what it prints. - A comparison written with a mark ends where the mark's value ends.
if score > 10 show wonand만약 점수 > 10 성공 말해줘say everything the comparison needs before the body starts, so the words after the value are what to do. Only a written mark counts: the comparing words carry their own connector, soif name is Mina Leestill keeps both of her names. - A verb NME does not have is read as the action word it stands for.
log hello,2초 멈춰줘,출력하기 안녕,3번 돌려서 안녕 말해줘,이름을 입력해 이름이 뭐예요?and친구들에 민수 집어넣어all work now. Every one of them already had to be a command to reach the message naming the word to write instead, so the line is read with that word in it rather than handed back. The message is still written whenever the corrected line is not a whole statement —wait3 secondsrepairs towait seconds, which says no amount — and ordinary writing is untouched:그는 이렇게 말합니다,조금만 기다립니다,log the miles you walked this weekandoutput of the factory fell againall still print themselves. - A verb NME does not have is read as the action word it stands for.
log hello,2초 멈춰줘,출력하기 안녕,3번 돌려서 안녕 말해줘,이름을 입력해 이름이 뭐예요?and친구들에 민수 집어넣어all work now. Every one of them already had to be a command to reach the message naming the word to write instead, so the line is read with that word in it rather than handed back. The message is still written whenever the corrected line is not a whole statement —wait3 secondsrepairs towait seconds, which says no amount — and ordinary writing is untouched:그는 이렇게 말합니다,조금만 기다립니다,log the miles you walked this weekandoutput of the factory fell againall still print themselves. - A module tool with nothing to work on has its own code, E0410. It was borrowing E0406, whose title is about an unreadable module line — so the code a reader looked up said something else than the message they were reading.
점수는 빈 목록, not점수은 빈 목록. The hint under E0240 wrote the Korean topic mark by hand instead of choosing it from the name.yesterday,2 days agoand3 days from noware sentences. Korean writes어제,2일 전,3일 뒤. They mean a date only afteruse date latestis above them, because that line is what binds what they lower to — so3 days ago I saw herand약속은 3일 전이었습니다are ordinary sentences and print. Guide 33 is written in sentences from end to end now.
0.5.0
- The sentence-level AI prompt now covers the date toolbox. It is the one
thing a sentence program cannot say without a
useline, and guides 33 and 36 use it, so an assistant handed that prompt could not write them. show todayshows today's date. The date module bindstoday,weekday,yearand their Korean twins as functions, so a line that wrote one without brackets printed<function <lambda>>— a program that runs, says nothing anybody wanted, and never says why. Those six names now answer when they stand on their own, which is also what makes guides 33 and 36 writable in sentences. Names that need something written after them (days_after,개수) are unchanged: what is missing there is the writer's.- A module tool written with nothing to work on is named.
show countand개수 말해줘compiled toprint(<function <lambda>>). The new message says which name is a tool and that the line does not say what it works on. Fixed values —pi,원주율, the version strings — are shown as they stand. 이름은 물어봐saves the answer in이름. The topic mark was kept as part of the name, so the program bound이름은and every later line that said이름was talking about something that was never made.이름님 안녕하세요puts the answer where이름is.님is not a particle but it is written like one, and a greeting reaches for it first.씨is deliberately absent:날씨would become the name날plus씨in any program that has one.for eachfriend in friendsloops overfriend. With the space left out, the loop used to bind a name calledeachfriendand every line under it that saidfriendprinted the word.- Tidying keeps the language the program is written in.
nme tidyon a Korean program used to hand it back in English, which is a translation nobody asked for. Without--languagethe program now keeps its own language, decided by the words the program is made of — text inside quotation marks and comments do not count, soprint("안녕")stays an English program. - A Korean line that shows one piece of text puts its verb at the end.
"안녕하세요" 말해줘, not보여줘 "안녕하세요". Both tidying and converting Python wrote the second, so a tidied Korean program had one line in English word order while every line around it read the other way. Anything with an operator in it —보여줘 1 + 2— keeps the verb in front, where it belongs.
0.4.0
- The corpus of "ways a beginner writes the same thing" is more than twice
the size. It covered twelve intentions and now covers twenty-six — value
changes, waiting, taking one thing back out of a list, writing into a
record, looping over a list,
else, andwhile, in both languages. That is 211 spellings measured instead of 103, and it is what the entries below were found by. - Putting something into a name that is not a list is named, not left to run
time.
점수는 0followed by점수에 1 추가해compiled to점수.append(1), which reads perfectly and dies withAttributeError. The new E0240 says which name and what is in it. 친구들에서 민수를 빼줘takes out민수, not민수를. The object mark was being kept as part of the word, so the item taken out was one nobody put in.- Four more ways to take one thing out of a list.
delete,eraseanddropin English;삭제해,제거해,지워and없애in Korean. They are everyday verbs, so they only make a statement when the name is one the program already made a list:delete the fileand기록을 지워 주세요stay sentences. - Four more ways to write one named value into a record.
store Mina as 90 in ages,save Mina as 90 in ages,record Mina as 90 in agesandadd Mina at 90 to ages, plus Korean나이표에 민수를 90으로 저장해,기억해,적어and넣기.set X to Y in Ris deliberately left alone: it already means readYout ofR. - Six more ways to wait.
hold,delayandrestin English;대기해and대기in Korean. - Fifteen Python-level error explanations rewritten in plain words
(E0106–E0120), and the two places NME called itself
Inow sayNME. - Twenty-five more ways of writing the same thing now do it. Over the
211-variant corpus, 163 worked when it was first measured and 203 do now,
with nothing printing itself instead of running. Among them:
for name in namesandfor each name of names;이름들의 이름마다with the lines to repeat written underneath, and이름들의 각 이름마다;otherwise,or else,그렇지 않으면,안 그러면,그 외에는,아니라면;as long as n < 3,repeat while n < 3,keep going while n < 3and수가 3보다 작은동안with the space left out;민수를 90으로 나이표에 넣어and나이표에 민수 90 넣어;in ages put Mina at 90andput Mina 90 in ages;민수를 친구들에서 빼;take Mina out of friends; andgrow/bump/up score by 1. 점수에 1 추가해adds one to the score. The word puts an item into a list, and the name says which is meant: a list takes an item, a number takes arithmetic. Something the program never made is refused rather than guessed.- Eight spellings are deliberately still refused, each for a reason
written down beside the corpus:
name is 5is a comparison in Python,set Mina to 90 in agesalready means reading a value out, and한and계속are too common in Korean to claim. - Narrower carets. A value change that could not be read underlines the
amount rather than the whole line; a list line underlines what was to go in;
a loop over a list underlines the part that could not be read, and says when
the missing word is
in.
0.3.0
- Five more ways of writing the same thing now do it. Measured against the
103-variant corpus, 96 of them worked; 102 do now.
5를 이름에 저장해says the value first,이름을 5로 두어uses the everyday verb for putting something down,친구들에 민수 넣기uses the naming form of the verb,do it 3 timesand그거 3번 반복해say out loud what is being repeated,수가 3보다 클 때closes the condition with때, and Englishask for nameasks for something.name is 5is still refused: in Python that line is a comparison, and reading it as a save would change what valid Python means. 사진을 폴더에 저장해no longer becomes사진 = "폴더에". Korean marks where something goes with에, so that is the name being saved into — and a line whose value is not a value is a sentence about saving, which prints itself.
0.2.0
- Errors say what is wrong, where, and why. Twenty of the messages a
beginner meets most often were rewritten.
I don't know what \echo` does` now says that the word is standing where the action word goes, and the hint hands back the reader's own line with the word put right — but only when that line really compiles, so following the hint cannot fail again. An unclosed block points at the line that opened it instead of at the end of the file; an unclosed quotation mark points at the mark that was opened, not one column past the end of the line; and the lines that could not be read quote the part they could not read. - Eight programs that used to compile into something else now say so.
set x.count to 3saved the words.count to 3intox;show a; show bbecame one message readinga; show b;item -1 of friendsandwait -3 secondswent through to a run-time failure;put Mina in ageson a record printed itself; loading the same module twice was reported as ten names colliding. Each of them is now refused with the line named. - A semicolon is punctuation in writing.
It was late; nobody spokewas handed to Python, which answered with a syntax error, and the Korean그는 웃었다; 나는 울었다compiled into an assignment that meant something else. Both now print themselves. doopens a job as well as a repeat.do greet with Minawas answered with "the repeat count is missing" on a line that repeats nothing. Running a job with the wrong number of things is now named as that, anddo the washing upprints itself.- Five file and module problems have codes of their own —
E0238,E0239,E0407,E0408— instead of borrowing the code for a line with no action on it, plusE0409for a module loaded twice. Looking a code up no longer explains something else. - Each language keeps its own examples. A hint written in English no
longer offers a Korean line to copy, or the other way round, and a hint that
names your own name writes it the way your program writes it. Korean
particles now follow the name they attach to, in tidied programs as well as
in messages:
score는,name을,table은. - CPython's own error is said in plain words first. A build that fails CPython's check now opens with the line number and what is wrong with it, in both languages, and keeps the original report underneath as evidence.
- A reading may stand inside a sentence.
how many,the total of,the biggest ofand their Korean twins only worked as the whole of a line, soshow You carry how many bag thingsprintedYou carry how many ['a', 'b'] things— the list itself, dropped into the middle of the words. It now readsYou carry 2 things. The words the writer typed are kept, so tidying a program into the other language leaves the sentence saying what it said.
0.1.0
A word English already has is never read as a misspelling. NME repairs one typo, and one typo is all that separates most short words:
shop milkprintedmilk,well doneprinteddone,bell ringsprintedrings. The compiler now carries the 3,030 real English words that sit one typo away from a word of its own, generated from the system spelling dictionary byscripts/build-common-english-words.pyand checked on every build. Repair still catches what it is for —shwo,tel,syaandpirntare not English words.A sentence that ends in an output word keeps its verb. English tolerates the message-first order (
Hello world show), and read without care it claimed the last word of every sentence that ends in one:time will tellprintedtime will,what did she sayprintedwhat did she, andI have nothing to saylost its verb. A subject, a modal,toor a conjunction in front of the word settles which one it is.A line that opens with
in,is,and,ororasis a sentence. It used to be handed to Python, soin the beginning there was lightcame back as CPython'sSyntaxErrorwith a caret under the first two letters. None of those five can begin a Python statement, so a line that starts with one is not Python that went wrong.사과is not사and과. Korean picks its joining particle from the sound before it —과after a consonant,와after a vowel — and reading every trailing과as and cut the word for apple in half:가방은 목록 사과built a bag holding사.감과 배is still two items.점수에 1counts, and no longer wipes the score.에says into and에서says out of, so everyday Korean drops the verb when the marks already carry the direction. It was read as a save —점수 = 1— and the count being kept was gone with nothing on screen to show it.A number added to a list goes into it.
add 1 to bagcompiled tobag = bag + 1, which is aTypeErrorin every Python there has ever been. Two lists still join, because that is what Python does and what the words say.score+1is refused. Python works out the answer and drops it, so the program ran, printed nothing and leftscoreexactly as it was — the one shape where doing nothing is indistinguishable from working.E0604now says so and points atadd 1 to score.A job can count something made outside it. Python decides for a whole function at once whether a name is local, so
to tally: add 1 to total endbuilt a function that readtotalbefore it had one and died withUnboundLocalError— a word the reader has never met, on a line that looks right. The declaration now rides on the same physical line as the change, because one NME statement is one line of Python and a line of its own would move every traceback number after it. Reading the name before changing it cannot be written at all, andE0236says why.save entry to the file "diary.txt"writes the file.saveis both NME's saving word and the everyday English for writing a file, and the two collided in silence: the diary was never written andentryquietly became the textdiary.txt. Sayingfilesettles it, exactly as파일에does in Korean. The baresave entry to "diary.txt"still saves the file name into the name, which is a real thing to do.The joining words between a header and the line under it are not the message.
repeat 3 times after that show Againprintedafter that show Again,3번 반복: 다시 말해줘printed: 다시, and만약에 점수가 1보다 크면, 좋아 말해줘printed, 좋아. Nothing is dropped unless what is left still reads as a command, sorepeat 3 times next weekkeeps saying it.A Korean loop written on one line loops.
점수가 5보다 작은 동안 안녕 말해줘was claimed by the condition matcher, which then failed on a condition ending in작은; with동안에it came out as anifwhose message began with the loop word.동안after the verb is still part of what gets said (커서가 깜빡이는 동안 말해줘).A name written as two words is named.
set full name to Minamade a name calledfullholding the wordsname to Mina, and printing it showed all of them. The connector standing further along is the evidence, soE0230now fires and offersfull_name.set greeting Hello world, which has no connector anywhere, still saves the greeting.A name the language itself needs is refused (
E0237).the total of marksis Python'ssum(...)andhow many friendsislen(...), soset sum to 3took the reading away from every later line — and the error landed on one of those lines as'int' object is not callable. Python written as Python is left alone: whoever writessum = 0in Python has said what they mean.이번is a word, not the number two and a counter.이번 달 예산 말해줘looped twice and printed달 예산, the writer's first word gone.두번and3번are still counts.The remainder can be taken by a name.
총점을 인원으로 나눈 나머지came out as writing: only a number was read, because a number has its particle cut off where a name keeps it attached.docs/syntax.ko.md§15 had promised both.A name cannot take a loaded module's word away.
use dateand thenset today to Mondayreplaced the module'stoday, andshow today()died with'str' object is not callable. The other order was refused from the start; this is that rule from the other side. A question that happens to end on one of those words is still a question —use datemay not change what a line means.show Today is today()is a sentence. It is valid Python —iscompares — so it came out as one and printed the words back unevaluated after dying onToday, a name nothing ever made.isis an English verb far more often than it is Python's identity test.More ways to say the same thing.
rep 3 times,go round 2 times,run through 2 times;should n be greater than 3,whenever,incase; and Korean친구들마다 반복해, which loops over친구들with친구as the name for each one.A date module. One line —
use date latest/날짜 사용 최신— bringstoday(),now(),year(),month(),day_of_month(),weekday()anddays_after(7). It is the seventh bundled module, and it replaces thefrom datetime import datethat the diary, log, habit and report guides all used to open with. It runs on the site too — only themonotonicfamily of clocks kills the browser engine, anddatetimewas checked in the shipped one. That clock is UTC.The weekday name is the one thing the two languages answer differently.
weekday()givesWednesdayand요일()gives수요일. Every other helper binds one value to both names; a weekday is a word, so it has to be in some language. It is the only place in any bundled module where the name you write chooses the language of the answer.The bare names
dateand날짜are not bound. They are what people call their own values, and binding them would make the module collide with exactly the programs that want it.날짜는 5and날짜 사용 최신live together.No date has been set for the repairs.prints again. A module name that is also an ordinary word —date,list— was counted anywhere on the line when recovering a mistyped module line, so that sentence was refused withE0305. It now counts only beside theuse/사용word. The defect predates this module;No list has been set.had it too.A job's body may be indented. Indenting under
to greet:and closing withendis the shape every guide in this repository teaches, and it was the one shape refused — withE0101pointing at a header that was already correct. A job now closes the wayrepeat 3 timesandstory:do: an indented body ends where its indentation ends, a flat one waits forend.A Korean amount no longer keeps its particle.
결과를 둘째수로 나눠produced결과 = 결과 / 둘째수로and died at run time withNameError.둘째수로is a valid Python expression too — a name nothing ever set — so "does Python read it" cannot tell the two apart. Which one the program actually made is asked first now. A written number (2로 나눠) is unchanged.A list line written on a record is refused.
표에 사과 넣어andappend apple to agescompiled to표.append("사과")and died at run time withAttributeError: 'dict' object has no attribute 'append'on a line that reads perfectly. The opposite direction was refused from the start (E0234); this one was not. It now says to write the name to put it under.A record — one name holding many named values.
set ages to an empty record/나이표는 빈 표, thenput Mina at 90 in ages/나이표에 민수를 90으로 넣어,show Mina in ages/나이표의 민수 말해줘, andremove Mina from ages/나이표에서 민수 빼, which is Python'sdelbecause a dictionary has no.remove. Python calls it a dictionary; the twenty guides of Part 2 use one eighty-seven times, and there was no way to write one at all.The list spellings mean the record thing when the name holds a record.
how many/개수,contains/…에 …가 있으면,for each/…마다 반복해andremove/빼are the same words for both, and the compiler decides from the kind the name holds, never from the wording. A reader should not have to remember which spelling belongs to which container, and that was the whole argument for building it this way. Looping over a record hands back its names, exactly as Python does, soshow name in agesreads the value back inside the loop.A record line written on a list is refused (
E0234). Left alone,친구들에 민수를 90으로 넣어appended the whole of민수를 90to the list as one piece of text — a program that runs, looks right, and is not what anybody wrote.the total of,the biggest of,the first ofandsortstay list-only: a record has no order and nothing to add up, and refusing says so.A record is only a record where a value is being saved. Everywhere else
record,tableand표are words somebody wrote, soI keep a record of everything I readand표는 두 장 남았습니다still print. A name ordinary Python wrote asages = {}is a record to every one of these statements; a set literal such as{1, 2}is not.A named job — a piece of program with a name.
to greet:/인사하기라는 일:, a block,end/끝, and thendo greet/인사하기 해줘runs it. It becomes an ordinarydef.to,do,일,하기and해줘are among the most ordinary words either language has, so a job is recognized by structure and never by a word: the openingto, or the라는on the name and the일after it, and the closing colon, and a block underneath. Without the block there is no job, soTo do:,오늘의 할 일:andto be honestprint as the lines they are. There is no one-line form either, so a colon in the middle of a sentence cannot open one.The line that runs a job is gated on the job existing.
doand해줘decide nothing on their own; the name has to be one this program already made. A Pythondefthat takes no arguments counts, so the three levels mix. A name saved inside a job stays inside it and a Pythonreturnwritten in there is accepted, because the body is a real function scope.A job may be given one thing.
to greet someone:/이름에게 인사하기라는 일:, and thendo greet with Mina/민수에게 인사하기 해줘. How many things a job takes is remembered with its name, so running it the other way round is refused withE0235instead of becoming a PythonTypeErrorat run time on a line that looks right.Not yet: a job that takes two things, and a job that hands something back. Write a Python
deffor either; advanced NME is ordinary Python.A repaired list word no longer invents the container as well.
너에게 하고 싶은 말이 있어became너.append("하고 싶은 말이"), because있어is one character from넣어; so did창고에 상자를 세로로 두어. A guess at the verb may not also invent the name it puts something in, so a repaired list word now needs a name the program already made. The exact spellings are untouched.그릇에 설탕을 한 스푼으로 넣어prints again. A Korean line that marks a name and a value is the record shape, and when the container is something the program never made, the list statement used to take the whole of설탕을 한 스푼으로and append it as one piece of text. Somebody cooking now keeps their sentence.Text can be cut into a list.
set names to memo split by line/이름들은 메모를 줄마다 나눈 것, and the same withby comma,by spaceandby newline(쉼표로,빈칸으로,줄바꿈으로).joinlanded in round 2 and its opposite did not, which is where the whole of Part 3 stopped: reading a file gives you one piece of text, and every next step needs a list.by lineis Python'ssplitlines(). A comma splits on","and joins with", ", and that difference is deliberate — a line read back out of a file saysMina,Ada, and looking for", "there would find nothing. What a split saves is a list, sohow many namesworks on it at once. It is gated on a name the program has already saved, so이야기를 둘로 나눈 것이 좋겠습니다andThe vote split by party.stay sentences.Joining with nothing between the items.
show friends joined together,friends joined by nothing,친구들을 붙여,친구들을 그대로 이어. Drawing a row of stars needed it and there was no way to say it.A join that does not say what goes between is refused (
E0233).show stars joinedused to printstars joinedback at you and별들을 이어 말해줘printed별들을 이어, both of which look like success. The refusal is gated on the list name and on nothing else being left on the line, sofriends join us at noonand별들을 이어 갔습니다still print.friends joined with commaalso works now;withis a Python keyword, so it had never reached the separator it named, although the reference said it did.One piece of text, that many times over.
set bar to star repeated 5 times/막대는 별표를 5개 붙인 것, which is what draws ASCII art, a progress bar and a chart. An earlier round left this out because별표를 5번 이어cannot be told from the counted loop, where5번already means five times. It is safe now because it is a noun phrase and not a command: a name the program saved, then a count, then a counting word, then붙인 것, which no loop ever says. So5번may be written here after all. The text is wrapped instr(...)first, so a name holding3gives"33333"and not15.A list loop that knows which turn it is on.
for each friend in friends with place/친구들의 친구마다 순서와 함께 반복해becomesfor place, friend in enumerate(friends, 1):. Counting starts at one, because친구들 3번째already means the third. The name is the writer's to choose — the word afterwith, and the word before와 함께. Comparing two lists position by position is what mastermind and tic-tac-toe are made of, and there was no way to hold the position at all.Three more bundled modules:
use list,use textanduse math. One line each, and both languages of every name are ready at once —말해 개수(친구들)andsay count(friends)are the same program.listbindscount/개수,sort/정렬,reverse/뒤집기,remove/빼기,first/첫번째,last/마지막,sum/합계,largest/최대,smallest/최소;textbindsupper/대문자,lower/소문자,trim/공백없애기,split/나누기,join/합치기,replace/바꾸기,starts_with/로시작,length/길이;mathbindsroot/제곱근,round_to/반올림,pi/원주율,power/거듭제곱,absolute/절댓값,floor/내림,ceil/올림. Each has the same version story asuse random:use list latest,목록 사용 버전 "0.0.1". Everything inside them is a plain Python builtin or one call intomath, so a program that uses them runs in the browser unchanged.list,textandmathstill print when they are just words. They are the first module names that are also ordinary words, in both languages, so they name a module only when they stand directly besideuse/사용and no other word is left over on the line.get the list of names,I use text messages every dayand장 볼 목록을 사용해 보세요are sentences, and they print. They are also never repaired from a typo, becauselistis one letter fromlastandmathone frompath.A name a bundled module bound is never shown inside a sentence. A sentence shows the value of a name the program made — that is what the text form is for — but the writer never wrote
flooror길이, and mostly does not know they exist. Afteruse math,the floor is coldprintedthe <built-in function floor> is cold; after글자 사용,길이가 조금 짧습니다showed a function where the length should have been. This was true ofuse randomtoo —shuffle the cards— and is fixed for every bundled module at once. The names still work as values:show pi,말해줘 원주율andsay count(friends)are unchanged.sort,reverseandremovefromuse listhand back a new list. The sentence statementssort friends/친구들 정렬해still change the list itself. Both exist because both are things people mean, and a helper that answeredNonewhile quietly reordering your names would be the worse surprise.Ordinary Korean sentences print themselves far more often. Measured over 353 sentences a person really types — a line of a story, a note to self, a message in a game — 294 printed themselves character for character and 38 compiled into a different program. It is now 350 and 3. The measurement is
scripts/mistake-probes/korean_prose.pyand it is a checked number.A polite
… 주세요request is a sentence again. All twenty-three of them were wrong:물 좀 주세요printed물,설탕을 조금만 넣어 주세요printed설탕을 조금만 넣어, and물어봐 주셔서 감사합니다stopped the program at a question nobody wrote.주세요attaches to any Korean verb, so it is no longer repaired into an output word, and it is glued to the word before it only when that word is already an action word:말해 주세요,보여 주세요and2초 기다려 주세요are unchanged.A line that ends the way a written Korean sentence ends keeps its own meaning.
이유는 저도 잘 모릅니다became이유 = "저도 잘 모릅니다", a program that runs and says nothing;3층에서 내리면 됩니다became a comparison cut inside a word;1번 출구에서 만납시다became a loop; and카드를 잘 섞어 나눠 주세요became a division by a name nothing ever set. The list of endings that close a Korean sentence now covers the-ㅂ니다family (모릅니다,나옵니다),-ㅂ시다,-니까and the-요endings, and every shape of assignment, loop, comparison and value change asks it — not only the one after a은/는.정답은 7입니다still saves the number seven and인사는 안녕하세요still saves the greeting.A helper verb after an action word is part of that verb.
말해 봐야 소용없는 일이었습니다printed only its second half and저장해 둔 사진을 다시 봤습니다made a value called둔.말해줘 비가 쏟아졌습니다still prints the rain.A helper verb inside a question belongs to the question. The rule above reached one line too far.
주문을 물어봐 마법의 주문을 말해 보세요names what it is asking for before it asks, so everything after물어봐is the text shown while it waits —말해 보세요included. Read as a sentence, the line printed itself instead of asking, and the loop written around it in the site'sko/passwordexample never got an answer and never ended.물어봐 주셔서 감사합니다is still a thank-you: no name stands in front of the asking word there, so the helper verb is the line's own.A Korean sentence with a hyphen, a slash, a wave dash or a bracket in it prints.
K-POP을 좋아합니다,A/S 센터에 맡겼습니다,오전 9시~오후 6시까지 문을 엽니다and(괄호 안은 나중에 지우겠습니다)were handed to Python, which answered a Korean sentence with an EnglishSyntaxErrorwhose caret landed inside a Hangul syllable. Valid Python still wins; this is asked only of a line Python has already refused.A program written in Korean is explained in Korean. Error messages followed the spelling of the command, so
nme buildon a Hangul file answered in English only. The Korean half is now printed whenever the program itself holds Korean, and the English half stays.Ordinary English sentences print themselves far more often. Measured over 302 sentences a person really types — a line of a story, a note to somebody, a message in a game — 184 printed themselves word for word and 44 compiled into a different program. It is now 249 and 12. The measurement is
scripts/mistake-probes/english_prose.pyand it is a checked number.A sentence is no longer read as a command because one of its words is one letter from one.
Today is a good daylost its last word tosay,Clear a path through the snow.lostsnowtoshow, andend of the roadwas told to choose a module version becauseroadis one letter fromload. A repaired English output word now claims a single word of message, which is what a real misspelling looks like (shwo hello,hello sya); a module line must name a module; and a word NME already refuses and explains, such aslet, is never repaired into the action it is refused in favour of.A number in a sentence no longer switches the sentence off.
The soup needs cream.printed andThe soup needs 250 ml of cream.did not. Prices, ages, times, dates, room and chapter numbers now stay in the sentence they were written in. A number written beside a command word is still a command, sowait 3 secondsandset score to 0are unchanged.A line holding one word prints it.
Helloon its own was left as a bare Python name, and the program said nothing and then died with aNameErrorpointing at a line that is not the mistake. A name the program set earlier, and a word NME spells out itself (say,end,skip,목록), keep their Python meaning.A command word at the start of a line does not make the rest of the line its argument.
set the table for four peoplemade a value calledtheand printed nothing at all;ask me anything you likestopped the program at a question nobody wrote;List the ingredients on the back.was wrapped in Python list brackets. All three are sentences and print.set then to 1,ask your "hi"andlist of Mina, Adastill mean what they say, because ato, a pair of quotes, or a comma says a name or a list was meant.A random pick needs its choices marked off from each other.
마음에 드는 것을 골라 보세요printed one word of itself at random, a different one every run, and nothing in the line ever named a choice; so did여러 개 중에서 뽑아andpick a flower from the garden. A pick now needs또는/oror a comma between the choices. The documented spellings색은 빨강 또는 초록 중에서 골라andset color to pick from red or greenare unchanged.A word is only taken apart into words.
doctorwas read asdo ctor,finishedasfinish ed,friendasfri endandtellingastell ing, sostory of a small town doctorwas refused with a suggestion nobody could act on. A space really left out is still named:sayhelloand안녕말해줘.Lists can be built and read entirely in sentences. An empty list (
set friends to an empty list/친구들은 빈 목록), how many items it holds (show how many friends/친구들 개수 말해줘), one item by its position (the first of friends,the last of friends,item 3 of friends/친구들 첫 번째,친구들 마지막,친구들 3번째), the total, the biggest and the smallest (the total of scores/점수들 합), putting the list in order (sort friends,reverse friends,shuffle friends/친구들 정렬해,친구들 거꾸로 해,친구들 섞어), taking an item back out (remove Mina from friends/친구들에서 민수 빼), joining every item into one piece of text (show friends joined by comma/친구들을 쉼표로 이어 말해줘), and asking whether a list holds something or holds nothing (if friends contains Mina,if friends is empty/만약에 친구들에 민수가 있으면,만약에 친구들이 비었으면).Positions are counted from one.
the first of friendsisitem 1 of friends, and both becomefriends[0].item 0 of friendsis refused withE0229instead of quietly handing back the last item.remove Mina from friendsno longer compiles tofriends = friends - Mina. That line looked right, compiled, and then died at run time. Subtracting from a name the program made a list is now the removal it plainly means, and subtracting a word that was never saved from a name that is not a list is refused with the reason.Every list statement is gated on a name that was already made a list.
sort out your things,the first of many,count me inand친구들 이야기를 들었습니다therefore stay ordinary sentences and print themselves; using one of the statements on a name that is not a list is refused withE0231rather than guessed at.A loop with no counter:
repeat forever/계속 반복해, closed byend/끝and left withbreak/멈춰.Text has a length and a case:
the length of name/이름 길이,name in capitals/이름 대문자로,name in small letters/이름 소문자로. All three read any saved name and are values, so they work in output, in a saved name, and in a condition.The five missing English zero-knowledge sentence forms exist.
challenge different zero knowledge challenge make,nonce secret challenge zero knowledge response make,public commitment challenge response zero knowledge verify,zero knowledge simulated response makeandpublic challenge response zero knowledge simulated commitment make. Until now an attempt at one of them was saved as a sentence:set ok to p c e z zero knowledge verifystored a string, so the program ran, verified nothing, and said nothing.skipand멈춰work inside an indented3 times:block. They used to be left there as bare Python names, so the program compiled and then raisedNameError; Python's owncontinuewas refused in the same place even thoughbreakwas accepted.아니면:and아니면 만약에 …:work inside an indented block, the way English gotelse:andelif …:for free from Python.else if …:now works there too.Another
.nmeprogram can be imported in a sentence, in both languages:use greet from "helper.nme"/"helper.nme"에서 greet 가져와. The quoted path ending in.nmeis what makes the line an import, souse randomstill loads the bundled module.askfollowed by a question needs no name in between.ask what is your name,ask how old are you,물어봐 이름이 뭐예요?and물어봐 몇 살이에요?now save into the name those questions already answer (name,age,이름,나이). The Korean forms used to keep the particle and save into이름이, or into몇. A question with no name to save into, such asask who is there, is still refused.할 일은 목록is refused instead of printed. A name is one word, so할 일is two and the line quietly became its own sentence — guide 05 taught exactly that. The refusal names the spelling that works (할일).The mistake corpus grew from 587 short programs to 723: the list and text grammar, the parity holes this release closes, and the ordinary prose that contains each new word. The number that matters — accepted but compiled to something the writer did not mean — is still 11, and all thirty prose sentences still print themselves.
What is left over after a division has a spelling:
the remainder of pile divided by 4/쌓인돌을 4로 나눈 나머지. It is a value, so it works in output, in a saved name, and in a condition — which is what a counting game such as Nim is decided by.set left to score divided by 4no longer becomesset = set / 4. A line that opens with a saving word is a save, not arithmetic on a name calledset.A story that opens with nothing in it says so.
story:alone used to becomeif True:with no body, and the reader met CPython's ownSyntaxErrorpointing into generated code;얘기: 그만하자was a valid Python annotation that compiled, did nothing, and said nothing. Both are now named, with the two readings spelled out.목록을 보여 주세요no longer prints[]. A bare목록/listis an empty list only where a value is being saved into a name; given to an output word the same words are the ones somebody wrote, so목록 보여줘prints목록andshow listprintslist.친구들은 목록,친구들은 빈 목록andset friends to an empty listare unchanged.Two ordinary words stopped being read as misspelled commands.
가장("most") is one keystroke from저장("save"), so가장 좋은 하루였습니다quietly became좋 = "하루였습니다";howisshowwithout itss, sohow are youprintedare you. A word the sentence grammar spells out itself is no longer read as a misspelling of something else.Far more of what a beginner actually types is accepted, and what cannot be read is said out loud instead of guessed at. Measured against a 566-mistake corpus (
scripts/mistake-probes/), the number that compiled to something the writer plainly did not mean fell from 141 to 11. Raw CPython syntax errors reaching the reader fell from 27 to 2, and all thirty sentences in the prose corpus now print themselves.Ordinary Korean sentences no longer become variable assignments in silence.
좋은 아침입니다("good morning") compiled to좋 = "아침입니다"and said nothing. A value that ends in a Korean sentence ending is now read as prose.이름은 민수,점수는 0and점수는 0이다still assign, as before.One-character typo repair now covers waiting, appending, break, skip and the list loop. Number words (
three times,세 번,일초) and counters (times,번,회,차례) are understood, Korean has as many ways to store a value as English, word order may vary (to score add 1), and politeness words are ignored wherever they appear.Loop-control synonyms (
stop,quit,keep going,그만해,계속해) and block-closing words (finish,done,종료,마침) are accepted.add Mina to friendsbecomes an append whenfriendsis a list, and is refused pointing atappendwhen it is not.A word the compiler does not understand never reaches
range(). A line that opens with a word no one writes in prose (output hello) is refused with the action it probably meant; ordinary prose keeps printing.An
endwith nothing to close names the header it could not read.A middle dot, an em dash, full-width punctuation and emoji are ordinary characters in a message. Curly quotes are refused, naming the straight quote to use instead.
A random pick no longer accepts a typo, which is what turned
강을 따라 집으로 갑니다into a random choice.Sentence syntax gained story, screen and time statements:
say slowly(one letter at a time),say very slowly,say slowly every 0.2 seconds,clear the screen,draw a line,say in a box,say in the middle,start the timerwith the valueelapsed, and named cooldowns (put attack on cooldown for 3 seconds,when attack is ready/is on cooldown,wait for attack). Korean has all of them too. One NME statement is still exactly one line of Python.Reading
elapsedbefore starting the timer is now refused at compile time withE0226.The box and the centred line count a Korean letter as two columns wide, so neither comes out crooked.
Three new guides. The reordering below made them 03 (letters one at a time), 14 (screen) and 15 (time), all inside Part 1.
The guides were reordered from scratch for a beginner. Eight parts, and all 88 guides renumbered and renamed. The old order carried the repository README's shape — files at 13, a cryptocurrency ledger at 17, writing a story at 86. Every cross-guide link, title and prerequisite was rewritten, and no prerequisite points forward any more. Part 1 (01–16) is sentences only: its 296 lines of code contain no quote, no bracket and no equals sign.
Two guides were written: 02 (story blocks) and 13 (chance). Ninety in all.
Part 1 no longer assumes an installation. It used to open with "create a file and run
nme run hello"; it now opens in the writing box on needmoreeasy.com. The command line is kept, marked "skip this for now", at the end of guides 01 and 16. The five-minute guide and the tutorial match.A list example guide 05 taught was really being printed as words. A name cannot contain a space, so
할 일은 목록came out as its own sentence. It is할일now, and the rule is stated.Three new checks.
scripts/check-guide-silent.pyfinds a line meant as a command that quietly became text, across every guide;scripts/report-guide-tier.pymeasures how much of each part is really sentence grammar;scripts/check-tier-parity.pycompiles 480 cells across 80 capabilities (sentence/beginner/advanced × English/Korean) and compares them, including whether a refusal carries the same code in both languages.The three prompts for an AI now carry story blocks and chance.
The five-minute guide and the tutorial no longer teach beginner syntax or Python in their early sections; a sentence-level project on lists and waiting takes that place.
Sentence syntax gained a story block.
story:/이야기:opens a block in which every line is text, so a page of prose needs no output word on every line. Nothing inside it is a command —wait 3 secondsprints those words, and so doesif ready— because a line of a story that quietly became a statement is the worst mistake this compiler can make. A blank line prints an empty line, names saved earlier are still put into the text, andslow story:,very slow story:andslow story every 0.2 seconds:tell the whole block one character at a time. The block closes atend/끝, or where its indentation ends. Korean writes천천히 이야기:,아주 천천히 이야기:and0.2초씩 천천히 이야기:, and the colon may be the full-width:a Korean keyboard produces.Sentence syntax gained a chance in percent:
30% chance show You win/30% 확률로 말해줘 당첨, the same words alone opening a block, andluck is a 30% chance/운은 30% 확률saving a true/false value that the ordinary conditions can ask about (if luck then ...).with a 30% chance,a 30% chance,30 percent chance,30% of the time,30%의 확률로,확률 30%로and30퍼센트 확률로all mean the same thing.A chance is counted in thousandths, so
30.5%is exactly 305 out of 1000 and nothing is decided by comparing two nearly equal decimal numbers. One decimal place is the finest anyone may write:30.25%is refused asE0227rather than rounded, because a program must never quietly mean something its writer did not write. Outside0%to100%isE0228.A percentage on its own is still not a chance and a sentence about a story is still a sentence:
I am 100% sure,전체의 30%가 왔습니다,story time,tell me a storyand옛날 이야기are unchanged.A sentence with a percentage in it is a sentence.
%is Python's modulo operator and a Korean word is a valid Python name, so100% 확신합니다really is a valid Python expression: it was handed to Python and answered with aNameErrorat run time.전체의 30%가 왔습니다reached CPython as a syntax error, and나는 100% 동의합니다was quietly saved under the name나. All three print now, and합니다and됩니다joined the Korean sentence endings the compiler knows.The words after a chance have to be a command.
a 30% chance of rainand확률 30%는 낮습니다no longer run their own tail three times in ten, anda 20% chance remainsno longer compiles toif …: remains. The word-first Korean spelling needs its particle —확률 30%로— which is the whole difference between a command and a remark about a percentage.A label and the words after it prints.
재미있는 이야기: 시작was being saved under the name재미있, because its first word ends in the Korean topic particle. A value NME cannot read that carries a colon is writing, not a value; a colon Python can read (a dict, a slice, a lambda) is still a value.A number with a unit after it is a sentence, not a value.
할인율은 30%입니다was saved as할인율 = 30%입니다, which Python reads as30 % 입니다: a modulo against a name nothing ever bound. It compiled and then raisedNameErrorthe moment it ran.점수는 30점입니다,가격은 1000원입니다and거리는 3km입니다print for the same reason. A bare number still saves:정답은 7입니다is the number seven, spoken as a sentence.One Korean noun one edit away from the file-reading word —
경고,참고,보고— crashed the compiler outright. It no longer does; those lines are ordinary writing and print.scripts/check-prose-blocks.pynow compiles a documented line together with the story block it is shown inside, which is the program the document actually shows. The mistake-probe corpus gained twenty-one lines about percentages, labels, and units (566 → 587); the count of programs that compile to something their writer plainly did not mean is unchanged at 11.
0.0.1-beta.160 — 2026-08-12
- Fetch the pull-request parent commit before checking changed Rust files, so the platform Format jobs can run their scoped rustfmt gate in a shallow CI checkout.
0.0.1-beta.159 — 2026-08-12
- Keep full-tree formatting checks on branch pushes while pull-request checks format only Rust files changed by the PR, avoiding failures from pre-existing formatting drift on the base branch.
0.0.1-beta.158 — 2026-08-12
- Detect star imports and
except*control-flow statements after earlier semicolon-separated statements, preserving the sharedE0114andE0115diagnostics in one-line Python suites.
0.0.1-beta.157 — 2026-08-12
- Detect
return,break, andcontinueafter earlier semicolon-separated statements in one-line Python suites, preserving the shared scope diagnostics.
0.0.1-beta.156 — 2026-08-12
- Extend Python control-flow diagnostics to one-line function and class suites,
so
return,break, andcontinuedo not inherit invalid outer contexts.
0.0.1-beta.155 — 2026-08-12
- Extend shared Python scope diagnostics to one-line function and class suites,
including
global/nonlocalconflicts, annotated targets,nonlocalplacement, and star imports.
0.0.1-beta.154 — 2026-08-12
- Preserve valid contextual keywords in one-line Python function suites and
report async-generator value returns there with the shared
E0118diagnostic.
0.0.1-beta.153 — 2026-08-12
- Correct
E0119handling for names used in Python annotations while keeping f-string validation with the CPython backend.
0.0.1-beta.152 — 2026-08-12
- Add shared bilingual
E0119/E0120for conflictingglobalandnonlocaldeclarations, while preserving declarations placed before valid uses.
0.0.1-beta.151 — 2026-08-12
- Add shared bilingual
E0118for return values inside async generators, while preserving bare returns and nested function scopes.
0.0.1-beta.150 — 2026-08-12
- Add shared bilingual
E0117for asynchronous comprehensions outside anasync deffunction, while preserving valid async-comprehension bodies.
0.0.1-beta.149 — 2026-08-12
- Add shared bilingual
E0116foryieldinside Python comprehensions, while preserving ordinaryyieldexpressions and generator lambdas where Python permits them.
0.0.1-beta.148 — 2026-08-12
- Add shared bilingual
E0115forbreak,continue, andreturninside Pythonexcept*blocks, while preserving nested function bodies and control flow after the handler suite.
0.0.1-beta.147 — 2026-08-12
- Add shared bilingual
E0114forfrom ... import *inside Python functions and classes, while preserving valid module-level star imports.
0.0.1-beta.146 — 2026-08-12
- Add shared bilingual
E0113for Pythonnonlocalwithout an enclosing function, while preserving valid nested function/class uses and leaving missing outer-name binding validation to CPython.
0.0.1-beta.145 — 2026-08-12
- Add shared bilingual
E0111/E0112diagnostics forasync forandasync withoutsideasync deffunctions.
0.0.1-beta.144 — 2026-08-12
- Keep generator lambdas byte-identical while Python-context diagnostics inspect
their own function scope, including normal lambdas nested in
async def.
0.0.1-beta.143 — 2026-08-12
- Diagnose
yield frominsideasync defwith shared bilingualE0110, while preserving it unchanged in ordinary generator functions.
0.0.1-beta.142 — 2026-08-12
- Add shared bilingual
E0108/E0109diagnostics foryieldoutside a function andawaitoutside anasync def, and keepreturn/yieldfrom inheriting an outer function context through nested class bodies.
0.0.1-beta.141 — 2026-08-12
- Extend the shared inline-branch
E0103guard to sentence-repeat bodies and keep Korean repeat shapes ahead of subject-first condition recovery.
0.0.1-beta.140 — 2026-08-12
- Reject inline
else/elifbodies without an open condition with the shared bilingualE0103diagnostic instead of lowering invalid Python.
0.0.1-beta.139 — 2026-08-12
- Report top-level and inline Python
continueoutside a loop with the shared bilingualE0107diagnostic while preserving valid loop bodies.
0.0.1-beta.138 — 2026-08-12
- Report top-level and inline
returnoutside a Python function with the shared bilingualE0106diagnostic while preserving valid function bodies.
0.0.1-beta.137 — 2026-08-12
- Clarify bilingual
E0102recovery guidance so it covers NMErepeatand valid Python loops alongside NMEwhile.
0.0.1-beta.136 — 2026-08-12
- Report one-line
breakoutside a loop with the stable bilingualE0102diagnostic in the shared parser while preserving valid Python loop bodies.
0.0.1-beta.135 — 2026-08-12
- Extend documentation parity checks to validate local example and directory links, not only Markdown targets.
0.0.1-beta.134 — 2026-08-12
- Add six-surface native regression coverage for one-line
else ifbranches that terminate withbreak.
0.0.1-beta.133 — 2026-08-12
- Add six-surface native regression coverage for one-line
whilebodies that terminate withbreak.
0.0.1-beta.132 — 2026-08-12
- Recognize sentence-repeat
break here/여기서 멈춰bodies in the shared parser and cover them through the native backend's six-surface break tests.
0.0.1-beta.131 — 2026-08-12
- Support one-line native
breakbodies inside loops, with six-surface coverage and bilingual rejection outside native loops.
0.0.1-beta.130 — 2026-08-12
- Document native one-line NME output bodies for sentence repeats alongside
times:/번:loops, and add six-surface support/boundary regression coverage.
0.0.1-beta.129 — 2026-08-12
- Add native six-surface regression coverage for one-line
sayoutput bodies, alongside the existingshowand말해spellings.
0.0.1-beta.128 — 2026-08-12
- Add a Python-wins regression for the valid Korean call shape
만약 (준비). - Clarify in the English and Korean language, native-reference, and AI guides how to select an NME block when a Korean keyword-like identifier is bound.
0.0.1-beta.127 — 2026-08-12
- Add native regression coverage for one-line NME
else if/elsebodies across sentence, beginner, and advanced syntax in both English and Korean. - Exercise both branch outcomes while keeping the Python-wins boundary explicit for the advanced Korean condition fixture.
0.0.1-beta.126 — 2026-08-12
- Add native regression coverage for one-line NME
whileoutput bodies across sentence, beginner, and advanced syntax in both English and Korean. - Include the spoken Korean comparison ending alongside symbolic and natural English conditions so all six surfaces exercise the same native path.
0.0.1-beta.125 — 2026-08-12
- Teach the native one-line NME output-body form in the English and Korean native learning guides, including its CPython-only boundary.
0.0.1-beta.124 — 2026-08-12
- Document beta123's native one-line NME control bodies in the backend design memo so the architecture notes match the implemented subset.
0.0.1-beta.123 — 2026-08-12
- Extend the native backend to lower one-line NME
say/showbodies afterthen/그러면forif/whileand branch chains. - Preserve native branch-flow tracking across inline
elif/elsebodies while keeping unsupported Python inline statements rejected.
0.0.1-beta.122 — 2026-08-12
- Add shared-parser and native regression coverage for Korean comparison endings
before mixed-language
and/orconnectors inside wrapped conditions.
0.0.1-beta.121 — 2026-08-12
- Fix parenthesized Korean
whileconditions when a comparison ending comes before an innerand/그리고oror/또는connector. - Keep the spoken
동안ending inside the shared condition tree and preserve the actual loop-body boundary after the wrapper.
0.0.1-beta.120 — 2026-08-12
- Add explicit core and native regression coverage for parenthesized Korean
comparison endings before the
또는/orconnector.
0.0.1-beta.119 — 2026-08-12
- Fix parenthesized Korean logical conditions where a comparison ending comes
before an inner
and/그리고oror/또는connector. - Scan fully wrapped conditions at their effective logical depth while keeping nested operand parentheses opaque, with core and native regression coverage.
0.0.1-beta.118 — 2026-08-12
- Extend regression coverage for Korean comparison endings inside parenthesized
elifconditions, including exact core lowering and native execution. - Keep the branch case on the same shared condition-span path as
ifandwhile; no separate English/Korean implementation is introduced.
0.0.1-beta.117 — 2026-08-12
- Preserve the closing parenthesis and body boundary when Korean sentence
comparison endings appear inside parenthesized
if/elif/whileconditions. - Cover the corrected form in core transpilation and native execution while keeping the shared English/Korean condition path.
0.0.1-beta.116 — 2026-08-12
- Fix Korean sentence
while/동안headers whose natural ending appears inside a parenthesized logical condition, preserving the matching closing bracket and the real body span. - Cover parenthesized logical
whileconditions across English and Korean sentence, beginner, and advanced native surfaces. - Keep the shared condition grammar and valid-Python boundary documented in both language references, native references, and AI guidance.
0.0.1-beta.115 — 2026-08-12
- Accept parentheses around a whole colon-free NME logical condition, such as
if (ready and score > 2), while preserving the shared English/Korean condition tree. - Keep valid Python calls such as
when(ready and score > 2)byte-identical instead of treating them as NME headers. - Cover the English/Korean sentence, beginner, and advanced surfaces in the native matrix and synchronize the language, native-reference, and AI guides.
0.0.1-beta.114 — 2026-08-12
- Extend native logical-condition regression coverage to
whileblocks across English and Korean sentence, beginner, and advanced surfaces. - Document that the native reference covers logical conditions in both
ifandwhilecontrol flow.
0.0.1-beta.113 — 2026-08-12
- Align the native-backend status summary with the implemented logical
and/orcondition support and its Python precedence and short-circuit behavior. - Keep the English and Korean backend overview banners synchronized with the detailed native capability list.
0.0.1-beta.112 — 2026-08-12
- Add native logical conditions with
and/orand the Korean spellings그리고/또는, preserving Python precedence and short-circuit evaluation. - Lower the shared condition tree recursively while keeping unsupported Python-colon conditions and native operands outside the restricted subset.
- Cover the six English/Korean sentence, beginner, and advanced surfaces with short-circuit regression tests, paired examples, and synchronized native documentation.
0.0.1-beta.111 — 2026-08-12
- Fix native fall-through analysis for a terminating nested conditional, so a name assigned on every path that can actually reach a later return is not rejected as conditionally initialized.
- Preserve conservative loop analysis and the required top-level integer return for native functions.
- Cover English and Korean sentence, beginner, and mixed advanced native forms, with synchronized native references, guides, and language docs.
0.0.1-beta.110 — 2026-08-12
- Add real native boolean bindings as a static type distinct from integers;
True/Falseand sentencetrue/false/참/거짓values can be assigned, compared, used as conditions, and shown asTrueorFalse. - Reject boolean arithmetic, value changes, and integer-only native function
arguments or returns instead of relying on their C
intrepresentation. - Cover the behavior across English and Korean sentence, beginner, and advanced surfaces, with synchronized native references, guides, AI guidance, and installation/version documentation.
0.0.1-beta.109 — 2026-08-12
- Exclude a branch that breaks out of its enclosing native loop from fall-through binding analysis, matching the existing early-return behavior.
- Cover the shared English and Korean behavior across sentence, beginner, and mixed advanced native surfaces, and align the native documentation.
0.0.1-beta.108 — 2026-08-12
- Allow a native
if/elsebranch that returns early to be excluded from fall-through binding analysis, so a later return can use a name assigned on every path that reaches it. - Cover the behavior across English and Korean sentence, beginner, and mixed advanced native surfaces, and align the native reference and guides.
0.0.1-beta.107 — 2026-08-12
- Upgrade a previously conditional binding when every arm of a later
if/elseassigns it, without weakening the conservative loop and one-sided-branch checks. - Extend the English and Korean native branch-merge regression coverage.
0.0.1-beta.106 — 2026-08-12
- Treat a name assigned in every
if/elsebranch as definitely initialized after the block while keeping one-sided and possibly skipped loop bindings conditional. - Cover the shared English and Korean branch-merge behavior in native tests and references.
0.0.1-beta.105 — 2026-08-12
- Fix native comparisons of two string concatenations so each operand keeps its own checked runtime buffer instead of comparing the second result with itself.
- Cover the corrected behavior in English and Korean native sentence syntax.
0.0.1-beta.104 — 2026-08-12
- Correct the native-backend contract to document that
breakworks inside anifnested in a native loop and is rejected only outside loops. - Clarify the native expression-lowering comment for checked integer and finite-float helpers.
0.0.1-beta.103 — 2026-08-12
- Reject non-finite results from native finite-float arithmetic with a bilingual
runtime error instead of allowing C
doubleoverflow to produceinf. - Cover the runtime boundary across sentence, beginner, and advanced English and Korean native surfaces.
- Align native reference, guide, language-reference, and backend comments with the checked finite-float result policy.
0.0.1-beta.102 — 2026-08-12
- Add a dedicated English/Korean native-core reference and link it from the README, language reference, native guide, and backend memo.
- Cover equivalent sentence, beginner, and advanced native programs in both languages with one end-to-end six-case acceptance test.
0.0.1-beta.101 — 2026-08-12
- Include finite-float values in the generic native-backend recovery hint and cover the English and Korean hints with a regression test.
0.0.1-beta.100 — 2026-08-12
- Align the native-backend opening summary with the implemented function
subset: integer scalar parameters and an unconditional integer
return.
0.0.1-beta.99 — 2026-08-12
- Make Korean-first CLI diagnostics use Korean command spellings in their recovery examples and code explanations, while keeping English invocations English-only.
0.0.1-beta.98 — 2026-08-12
- Align the language reference with the native function subset: integer scalar
parameters and an unconditional integer
return.
0.0.1-beta.97 — 2026-08-12
- Document finite-float truthiness in the native subset and cover its English and Korean behavior with an end-to-end native regression test.
0.0.1-beta.96 — 2026-08-12
- Align Korean reference, installation, and native-backend workflows with the Korean CLI commands, while labeling intentional English command spellings.
0.0.1-beta.95 — 2026-08-12
- Align Korean example-authoring, example-template, and calculator verification
instructions with
nme 검사andnme 실행.
0.0.1-beta.94 — 2026-08-12
- Align Korean file, project, HTTP, terminal-menu, and native guide workflows with their Korean CLI commands while retaining labeled English companions.
0.0.1-beta.93 — 2026-08-12
- Align the Korean index and first two beginner guides with the Korean CLI
path, using
nme 실행andnme 검사from the first run.
0.0.1-beta.92 — 2026-08-12
- Align the Korean file and JSON guide workflows with Korean CLI commands and give their try-it examples Korean primary paths.
0.0.1-beta.91 — 2026-08-12
- Align the Korean check/build and conversion guide commands with the Korean CLI paths, and document the Korean-first bilingual diagnostic output.
0.0.1-beta.90 — 2026-08-12
- Align the English and Korean condition/random guide examples with their named language paths, while retaining explicit mixed-language examples.
0.0.1-beta.89 — 2026-08-12
- Align the English and Korean break-loop guide examples with their named language paths, while retaining a separate mixed-language example.
0.0.1-beta.88 — 2026-08-12
- Align the English and Korean while-loop guide examples with their named language paths, while retaining a separate mixed-language example.
0.0.1-beta.87 — 2026-08-12
- Align the Korean Python-packages guide with
birthday.ko.nme, Korean beginner spellings, and the equivalent English learning path.
0.0.1-beta.86 — 2026-08-12
- Run the Windows CLI install smoke test under PowerShell so Git Bash's
link.execannot shadow the MSVC linker configured by CI.
0.0.1-beta.85 — 2026-08-12
- Teach the Python-packages guide to install third-party libraries through the
bilingual
nme install/nme 설치wrapper and explain its E9025 failure path.
0.0.1-beta.84 — 2026-08-12
- Keep MSVC compiler banners out of successful
nme nativeoutput and preserve.c/.kosource stems in Windows default executable names (.c.exeand.ko.exe). - Align native-backend documentation with the corrected cross-platform names.
0.0.1-beta.83 — 2026-08-12
- Configure the Windows CI job with a Visual Studio developer environment so
native C tests can find
cl.exeand exercise the real MSVC path.
0.0.1-beta.82 — 2026-08-12
- Reject blank package names before invoking pip so
nme installcannot report a successful no-op when a newer pip ignores an empty requirement. - Apply the stable Rust formatter used by CI to the workspace.
- Keep the native backend and its tests clean under the current Clippy gate.
0.0.1-beta.81 — 2026-08-12
- Pass MSVC
/utf-8for Windows native builds and tests so generated Korean and English C strings retain their intended text.
0.0.1-beta.80 — 2026-08-12
- Make generated native C runtime helpers warning-safe for GCC, Clang, and
MSVC, and reserve the generated
NME_UNUSEDmacro from user identifiers.
0.0.1-beta.79 — 2026-08-12
- Select MSVC
clwith Windows-compatible flags fornme native, keepccon macOS/Linux, and document the required Windows developer shell.
0.0.1-beta.78 — 2026-08-12
- Allow default native builds for source stems ending in
.c, while keeping the explicit-o <path>.ccollision guard.
0.0.1-beta.77 — 2026-08-12
- Keep default native artifact names distinct for English and
.kosibling programs, add.exeto implicit Windows outputs even for.kostems, and preserve explicit-onaming behavior.
0.0.1-beta.76 — 2026-08-12
- Emit C prototypes before native function definitions so forward calls and mutual recursion compile correctly, including zero-argument functions.
0.0.1-beta.75 — 2026-08-12
- Update both README compiler descriptions to identify the implemented v0 native C backend and its roadmap, rather than describing it as only a plan.
0.0.1-beta.74 — 2026-08-12
- Update the native-backend memo to separate the implemented v0 baseline from future milestones and measured extensions.
0.0.1-beta.73 — 2026-08-12
- Correct the native-backend memo so its description matches the implemented restricted NME-to-C path and the separate Python/Nuitka path.
- Cover blank-line and comment layouts between native function headers and bodies in the backend regression suite.
0.0.1-beta.72 — 2026-08-12
- Make the documentation parity check verify that both sequential guide indexes list every numbered English/Korean guide exactly once and in order.
0.0.1-beta.71 — 2026-08-12
- Reject repeated
run/buildaction words innme nativewith stable bilingual diagnostic E9032, and make native CLI test directories unique.
0.0.1-beta.70 — 2026-08-12
- Reject
-oonnme native runwith stable bilingual diagnostic E9031; keep-ofornme native build.
0.0.1-beta.69 — 2026-08-12
- Enforce English/Korean twin files for every numbered learning guide in the documentation parity check.
0.0.1-beta.68 — 2026-08-12
- Extend the documentation parity check to validate local Markdown fragment links against their target headings as well as checking target files.
0.0.1-beta.67 — 2026-08-12
- Make the documentation parity check fail when a local Markdown link points to a missing file.
0.0.1-beta.66 — 2026-08-12
- Use overlap-safe copying for native string assignment so valid self-assignment
cannot invoke undefined
memcpybehavior.
0.0.1-beta.65 — 2026-08-12
- Reject C implementation-reserved identifier forms in native bindings and file-scope functions before they can produce non-portable or invalid C.
0.0.1-beta.64 — 2026-08-12
- Reject top-level native
returnwith the stableE0106diagnostic instead of emitting it as a return frommain.
0.0.1-beta.63 — 2026-08-12
- Reject native
breakstatements outside a loop with the stableE0102diagnostic before generating invalid C.
0.0.1-beta.62 — 2026-08-12
- Reserve macros, typedefs, and declarations exposed by generated C headers so native identifiers cannot be changed by preprocessing or C library clashes.
0.0.1-beta.61 — 2026-08-12
- Make native
lencount UTF-8 Unicode characters rather than storage bytes, matching Python behavior for non-ASCII text while retaining the byte buffer limit.
0.0.1-beta.60 — 2026-08-12
- Isolate native binding analysis between sibling branches so a read in one branch cannot use a name assigned only in another branch.
- Preserve C declaration reuse and conservative maybe-initialized tracking after uncertain control blocks.
0.0.1-beta.59 — 2026-08-12
- Keep bindings from unreachable
else/else ifalternatives afterif trueout of the definite native scope, preventing reads of uninitialized C values.
0.0.1-beta.58 — 2026-08-12
- Reject unresolved native names, bare native function values, duplicate parameters, and bindings that shadow native function names before C emission.
0.0.1-beta.57 — 2026-08-12
- Emit Python comments as inert C comments during native lowering so comment text cannot become a C preprocessor directive or confuse function hoisting.
0.0.1-beta.56 — 2026-08-12
- Reject non-finite native float literals before C emission and normalize finite
whole-number literals as C
doublevalues, preserving signed zero.
0.0.1-beta.55 — 2026-08-12
- Escape native string literals for valid C output, including control characters, and reject embedded NUL strings that C APIs cannot preserve.
0.0.1-beta.54 — 2026-08-12
- Reject nested native function definitions before C emission; the native function surface is explicitly file-scope only.
0.0.1-beta.53 — 2026-08-12
- Reject duplicate native function definitions and unsupported default or varargs headers before C generation.
- Reject keyword arguments in native calls so no AST arguments are silently dropped.
0.0.1-beta.52 — 2026-08-12
- Validate native function calls against integer function definitions and their declared arity before emitting C, with bilingual diagnostics for unknown or mismatched calls.
0.0.1-beta.51 — 2026-08-12
- Reject native functions that can fall through without an unconditional integer return, preventing undefined C return values after conditional-only branches.
0.0.1-beta.50 — 2026-08-12
- Check native signed 32-bit integer literals and arithmetic instead of allowing undefined C overflow or zero-divisor behavior.
- Report bilingual native runtime errors for integer overflow and modulo by zero, while documenting the bounded native integer range.
- Reject float arguments and return values in native functions instead of
silently converting them through C
intparameters and returns.
0.0.1-beta.49 — 2026-08-12
- Track conditional native bindings and reject reads or value changes after a possibly skipped block unless the name was initialized beforehand.
- Keep statically true
if trueblocks usable while reporting a precise bilingual diagnostic for uncertain initialization.
0.0.1-beta.48 — 2026-08-12
- Reject native assignments that change a binding from integer, float, or string to another type before generating incompatible C.
- Require a prior numeric binding for
add/subtractvalue changes and report a bilingual diagnostic for uninitialized or string targets.
0.0.1-beta.47 — 2026-08-12
- Hoist native scalar and string declarations to the active function scope when assignments occur inside control blocks, while preserving source control flow and later binding use.
- Prevent nested-block assignments from producing out-of-scope C declarations.
0.0.1-beta.46 — 2026-08-12
- Keep native function-local scalar bindings separate from main-program bindings, so names can be reused without generating invalid C.
- Document the scope behavior in both native backend references.
0.0.1-beta.45 — 2026-08-12
- Reject generated native-runtime names in function parameters before emitting C, including unused parameters that would otherwise shadow runtime helpers.
- Keep the same precise bilingual diagnostic used for native variables and function names.
0.0.1-beta.44 — 2026-08-12
- Reject C keywords and generated native-runtime names before C lowering, with precise bilingual diagnostics instead of allowing namespace collisions.
- Reserve helper names such as
nme_copy,nme_cat,len, and_nme_iwithout silently renaming user identifiers.
0.0.1-beta.43 — 2026-08-12
- Replace unbounded native string copies and concatenation with checked helpers.
- Stop oversized stored or concatenated strings with a bilingual runtime error instead of allowing fixed-buffer overflow.
- Document the native string capacity and keep the CPython path available for unrestricted text.
0.0.1-beta.42 — 2026-08-12
- Make
nme build -orefuse to overwrite an existing Python output with E9009. - Keep the existing artifact unchanged for English and Korean build commands,
matching
nme compileandnme native build.
0.0.1-beta.41 — 2026-08-12
- Own imported-module, native, and Nuitka staging directories for the whole operation and remove them on both success and early failure.
- Prevent partial Python or C staging files from being left behind when a write fails.
0.0.1-beta.40 — 2026-08-12
- Use fresh per-invocation temporary directories for imported-module, native, and Nuitka staging instead of reusing process-ID-only folders.
- Prevent stale Python files left by a crashed run or PID reuse from shadowing ordinary imports in a later program.
0.0.1-beta.39 — 2026-08-12
- Make
nme native buildrefuse to overwrite an existing executable or companion C source with E9009, matching the other build commands. - Reject
.coutput paths with E9003 so the executable and generated C source cannot target the same file. - Extend the E9009 English/Korean lookup explanation to cover native artifacts.
0.0.1-beta.38 — 2026-08-12
- Make
nme nativeclassify directory arguments as E9014 instead of reporting them as unreadable files E9007, matching the CPython-backed commands. - Add English/Korean native-command coverage for the shared folder diagnostic.
0.0.1-beta.37 — 2026-08-12
- Keep existing but unreadable program files on E9007 instead of reporting them
as missing programs E9015 for
nme runandnme native. - Preserve E9015 for paths that actually cannot be found.
0.0.1-beta.36 — 2026-08-12
- Keep
nme compiletemporary-folder failures on E9027 instead of reporting them as native compiler startup failures E9011. - Classify temporary Python-source write failures as E9008 while preserving E9011 for failures to start the external compiler process.
0.0.1-beta.35 — 2026-08-12
- Report unreadable imported
.nmemodules with the existing file-read diagnostic E9007 instead of the top-level program-resolution code E9015. - Expand E9007’s bilingual explanation to cover imported module files.
0.0.1-beta.34 — 2026-08-12
- Give
nme installwithout a package name its own stable diagnostic, E9030, instead of reusing the option-value code E9003. - Add English/Korean lookup coverage for the missing-package argument path.
0.0.1-beta.33 — 2026-08-12
- Give imported module-name collisions their own stable diagnostic, E9028, instead of reporting them as invalid option values.
- Give the current
nme compilemodule-import limitation its own stable diagnostic, E9029, with bilingual lookup and CLI regression coverage.
0.0.1-beta.32 — 2026-08-12
- Add E9027 for temporary working-folder creation failures instead of labeling them as current-folder read errors.
- Preserve Korean-first bilingual diagnostics when imported modules are staged for execution.
0.0.1-beta.31 — 2026-08-12
- Give native executable startup failures their own stable diagnostic, E9026, instead of reporting them as Python startup errors.
- Add a deterministic Unix CLI regression and bilingual public lookup coverage for the native-program startup path.
0.0.1-beta.30 — 2026-08-12
- Clarify E9010 and E9011 in both languages so their recovery guidance covers
the Nuitka
compilepath and the system-C-compilernativepath. - Add public lookup regressions that keep the two backend toolchains visible to beginners.
0.0.1-beta.29 — 2026-08-12
- Give failed Python package installs their own appended diagnostic code, E9025, instead of reusing the native-compiler code E9010.
- Add bilingual lookup and network-independent CLI regression coverage for the package-install failure path.
0.0.1-beta.28 — 2026-08-12
- Route the Korean
네이티브and설치command aliases through the same Korean-first bilingual diagnostics as the other Korean CLI commands. - Add regression coverage for both failure paths while preserving English-only output for the English commands.
0.0.1-beta.27 — 2026-08-12
- Fix the English beginner skeleton in both example-template twins so its loop stops at three instead of becoming an accidental infinite loop.
- Add a parity regression guard for the bounded English and Korean template loops.
0.0.1-beta.26 — 2026-08-12
- Fill the remaining English code examples in the main NeedMoreCoin guide and the example-authoring guide so paired guides expose equivalent teaching material.
- Extend the documentation parity check to every guide pair, not only numbered guides, and require matching code-block coverage.
0.0.1-beta.25 — 2026-08-12
- Complete the missing Topic metadata in the four NeedMoreCoin sequence guides in both languages.
- Add equivalent English sentence-level proof-of-work and transaction-proof snippets, and enforce numbered-guide code-block parity in CI.
0.0.1-beta.24 — 2026-08-12
- Repair Korean documentation links so local pages lead to their Korean twins, while deliberate English comparison links remain available.
- Complete consistent bilingual navigation for the guide sequence and add a CI parity check that catches wrong-language links and missing navigation rows.
0.0.1-beta.23 — 2026-08-12
- Keep the proof-of-work difficulty labels consistent across the six NeedMoreCoin examples (Korean/English sentence, beginner, and advanced surfaces), with a regression test for the shared learning contract.
0.0.1-beta.22 — 2026-08-12
- Make the six-way NeedMoreCoin learning matrix fast and deterministic enough for regular example validation, and keep the sentence examples genuinely punctuation-free where their surface promises that progression.
- Add parser and regression coverage for the pure English sentence proof expressions and validate the Korean and English sentence sources separately.
0.0.1-beta.21 — 2026-08-12
- Repair the locked release metadata and keep CLI and cryptocurrency example regression checks aligned with the current beta package versions.
0.0.1-beta.20 — 2026-08-12
- Replace the earlier standalone blockchain demonstrations with the NeedMoreCoin learning project: complete Korean/English sentence, beginner, and advanced examples, a shared construction guide, and an authoring standard for six-way examples.
- Add automated coverage that checks all six examples, their intended syntax surfaces, and their shared observable behavior.
0.0.1-beta.19 — 2026-08-12
- Converge the public beta Git topology with
main: the final beta.19 release commit keeps beta.18 as its first parent and records the current main tip as its second parent. The beta first-parent release line still advances exactly one version per public commit, whilemainbecomes an actual ancestor of the next-generationbetabranch. - Keep the beta.17 release guard, locked Cargo validation, three-OS gate, and CPython 3.10/3.12/3.14 compatibility matrix unchanged.
0.0.1-beta.18 — 2026-08-12
- Extend the bundled Schnorr adapter to version
0.0.2with context-bound Fiat-Shamir non-interactive proofs. The SHA-256 challenge binds the Group 15 generator, commitment, public key, and a length-prefixed explicit context under an NME domain tag. - Add
zk_nizk_challenge,zk_nizk_prove, andzk_nizk_verifyplus Korean sentence forms. Proofs are JSON-friendly[commitment, response]values and cross-context reuse is rejected. - Add Korean/English executable examples, parser/lowering and CLI end-to-end coverage, and explicit documentation that context binding does not replace same-context freshness/replay controls.
0.0.1-beta.17 — 2026-08-12
- Make
betathe enforced next-generation release line. Every public beta push must advance the workspace beta number by exactly one, name that version in the commit subject, and keep the workspace package versions inCargo.locksynchronized. - Upgrade CI to
actions/checkout@v6andactions/setup-python@v6, and run Cargo checks and tests with--locked. - Add CPython 3.10, 3.12, and 3.14 compatibility jobs for beta and pull requests while retaining the full Ubuntu, Windows, and macOS quality gate.
0.0.1-beta.16 — 2026-08-11
Add the bundled
zero_knowledge/영지식adapter (version0.0.1) with a finite-field Schnorr proof-of-knowledge reference implementation: secure randomness from Pythonsecrets, RFC 3526 3072-bit MODP Group 15 subgroup parameters, 256-bit verifier challenges, subgroup/range checks, transcript simulation helpers, helper-name collision protection, and Korean sentence-only proof expressions. Add matching Korean/English A→B examples with malicious relay C showing saved-transcript replay failure, transcript simulation, and the separate live-relay case. Document the security scope: mathematically faithful learning/reference code, not a side-channel-hardened production cryptography library.Extend the NME-native core: integer
%modulo in arithmetic (float modulo is rejected honestly); conditions using%are a frontend follow-up.Fix the native backend so the very first string assignment can be a concatenation (
greeting = "hello" + " world"): a C array cannot be initialized from a function call, so the emitter declares the buffer first and copies with strcpy.Extend the NME-native core: float literals, float variables, float arithmetic (mixed int/float promotes to double), and float comparisons.
Extend the NME-native core: the beginner
times:loop (block and inline forms) lowers to a C for-loop.Extend the NME-native core: boolean literals in truthy conditions (
if true/if falselower to 1/0), alongside integer truthiness.Extend the NME-native core: truthy conditions (
if ready,while turns) over integer values, so counters and flags work natively without comparisons.Add the natural-language
<=/>=connectors:if x is less than or equal to 3and Korean만약에 점수가 10보다 작거나 같으면lower to<=/>=on both backends. Theor equalphrase is kept out of logical-orsplitting and typo recovery.Extend the NME-native core:
+concatenation into string variables (fixed buffers viastrcpy), so strings can be built up step by step; nested concatenation stays rejected.Extend the NME-native core: string
==/!=comparisons throughstrcmp(both the Python condition form and the natural Korean form), alenbuiltin mapped tostrlen, and string equality in sentence conditions.Extend the NME-native core: string variables (literals), string output, and one binary
+concatenation through a small runtime helper, with nested concatenation honestly rejected; expressions now carry static types (int vs string) through lowering.Extend the NME-native core: functions over scalar parameters with
return(recursion works),else/else ifbranches, calls insay, and honest rejection of C-keyword identifiers; the compiler now builds with-O2. Measured on this machine: a 50M-iteration integer loop is ~60x faster natively than on CPython (one micro-benchmark, documented in the memo).Implement the first slice of the NME-native AOT backend (
nme-nativecrate +nme native run/nme native build): a restricted, statically typed core subset (integer values, sentencewhile/ifover comparisons,break,say) lowers to C and compiles to a native executable with the system C compiler; anything outside the core is rejected with a clear bilingual diagnostic and still runs on CPython. Korean spellings work; end-to-end tests compile, run, and compare output.Add the bootstrap example (an NME program that transpiles a tiny language to Python and runs it) with a Korean twin, guide 29 on bootstrapping/self-hosting, and a CLI test that runs both.
Add guide 25 (native compilation): teaches
nme native run/nme native build, the documented core subset, functions and recursion, the C artifact, and the honest measured benchmark.Teach
nme installin the READMEs and getting-started (guide 24).Add
nme install/nme 설치as a friendly pip wrapper: it installs a Python package and tells the beginner theimportline to use in an.nmefile, with clear bilingual messages when pip is missing.Add the native-backend research memo (
docs/native-backend.md): an honest evaluation of a C backend vs LLVM vs Cranelift vs direct codegen, recommending C for the first NME-native AOT compiler targeting a restricted statically-typed core subset, explicitly separated from the Python compatibility backend and from Nuitka.Add a
birthday.nmecountdown example that uses thedatetimestandard package from inside NME (with a Korean twin) and guide 24 on the standard library and pip-installed packages.Add
.nmemodule imports:from "helper.nme" import greet, scoreimports only the listed names from a sibling.nmefile, so a project can split into several files with an explicit interface and no shared global state.nme run/check/buildtranspile imported modules transitively and make them importable at runtime (via a temporary module folder onsys.path); module errors report the module's file name. File names must be Python identifiers, two modules may not share a name, andnme compiledefers module support. Includes a two-file example pair (examples/modules/).Add an
http-client.nmeexample that fetches a page from a local server withurllib, and aterminal-menu.nmeTUI menu loop (both with Korean twins); a CLI test runs the menu with scripted input.Teach
nme convertthe file sentence forms:x = open("f").read()andx = Path("f").read_text()convert toread "f" into x, andopen("f", "w").write(v)/Path("f").write_text(v)towrite v to "f"(Korean spellings for Korean output). Beginner conversion keeps file IO as Python since the beginner file surface isuse file; the converted sentence source round-trips through the compiler.Add four educational blockchain learning projects (learning only, never investment advice), each with a Korean twin:
blockchain-ledger.nme(beginner, blocks linked by hashes),proof-of-work.nme(intermediate, mining with difficulty and a chain-integrity check),signatures.nme(advanced, HMAC signing and verification), andconsensus.nme(expert, a two-node fork and longest-chain rule simulation).Add sentence-level file forms:
read "notes.txt" into memo,memo read "notes.txt",memo에 "notes.txt" 읽어서 (저장해),write "hello" to "out.txt", and"out.txt" 파일에 "hello"를 저장해lower topathliblines without theuse filemodule. Read targets become known names for sentence interpolation, and weak matches likeread the bookorwrite hellostay plain sentence output.Bundle a
use file/파일 사용module (version0.0.1) for reading, writing, and JSON, next touse random. One import exposes both vocabularies:file_read/파일읽기,file_write/파일쓰기,json_load/json읽기,json_save/json저장, plus version names. Theuseline parser is now shared by both modules (same latest/version forms, same collision protection, same diagnostics), andnme moduleslists both. Sentence-level file wrappers are the next step.Extend stable error codes to command-line diagnostics:
nme ko <CODE>andnme en <CODE>now also explain CLI errors (E9001unknown command,E9015missing program,E9013Python startup, ...). Compiler codes stayE0001+; CLI codes use theE9xxxrange and render the same way (error[E9015]:). Everyfail()path in the CLI now carries a code.Fix explicit
end/끝block parsing when an indented sentence block is followed by a flat block: an indented body that cannot be closed by the remainingendlines now closes at the dedent, so만약 ...with an indented body followed by a flatif ... endblock no longer reports a missingend. Every previously valid program keeps its exact output; nested headers with enough closingends still stay nested, and a flat block still requires its ownend.Give every compiler diagnostic a stable error code printed next to the message, e.g.
error[E0102]:.nme ko <CODE>reads the long Korean explanation with an English translation,nme en <CODE>the English one, andnme ko(ornme 에러/nme error) with no code lists every code. Each code documents what went wrong, why, and the recovery steps; the code list and lookup pages are also taught in the help text, both READMEs, and both language references.Split the installation guide into independent per-OS sections (Windows 11, Windows 10, older Windows, macOS, Debian/Ubuntu, Fedora, Arch Linux), each with copy-paste install commands, PATH, version check, first run, and common errors.
Start the 100-guide curriculum:
docs/guides/now has an index (difficulty legend, learn-in-order path, topic lookup, full table) and the first twelve beginner guides (hello → ask → set → update → repeat → if → while → break → and/or → random → check/build → convert), each labeled with difficulty, prerequisites, topic, and result in both languages; every code block is verified withnme check.Accept shortened unique program names everywhere:
nme r guerunsguessing-game.nme, and the same prefix rule works forrun/실행,check/검사,build/빌드,compile,convert, the bare run shortcut (nme gue), and the numbered pick (bare names and prefixes answer the "Which one?" question). Case-insensitive exact stems win, then a unique prefix; when several programs match, NME lists the candidates and asks for more of the name instead of guessing.Long outputs (help, error-code lists) no longer panic when the reader closes the pipe early, e.g.
nme ko | head.
0.0.1-beta.15 — 2026-08-11
- Accept the Korean
!=sentence comparison같지 않으면,같지 않다면,같지 않을(also written같지않으면and friends), matching the existing Englishis not equal to. - Fix
while+ Korean sentence condition +동안endings (for examplewhile 점수가 3보다 작을 동안): the ending is now consumed as a block marker instead of being lowered as the loop's inline body, and every logical operand may carry its own ending (while 점수가 10과 같지 않을 동안 그리고 점수가 3보다 클 동안). - Fix Korean logical conditions: comparison endings may now combine with
그리고/또는(점수가 0보다 크면 그리고 점수가 3보다 작으면), and malformed conditions report a diagnostic instead of crashing the parser. - Fix the English roulette companion to use
ask numberfor numeric menus, bets, and wheel picks. - Add command shortcuts (
nme r/c/b/m/v/h,nme comp/nme conv) and bare-file discovery:nme rruns the single.nmeprogram in the current folder, lists and asks for a numbered pick when several exist, and explains what to do when none do. - Add an English and Korean twin for every beginner example.
- Fix beginner-path documentation in both languages, close English/Korean parity gaps, and link the new examples from the tutorials.
- Teach the new shortcuts and show friendlier file hints in the CLI and both language guides.
0.0.1-beta.14 — 2026-08-11
- Track Python import bindings so the random adapter also protects names
imported before
use random.
0.0.1-beta.13 — 2026-08-11
- Refuse to load the bundled random adapter when its generated helper names would overwrite an existing value.
0.0.1-beta.12 — 2026-08-11
- Fix the indentation of the Korean beginner time-loop example so every
published example passes
nme check.
0.0.1-beta.11 — 2026-08-11
- Let compact
3 times:/3번:beginner repeat blocks close withend/끝without requiring physical indentation. - Accept the natural beginner spelling
repeat 3 times:and keep ordinary colon-bearing Python suites on Python's indentation rules. - Infer common age questions (
How old are you?,몇 살이에요?) and accept spoken Korean loop endings such as준비하는동안. - Treat polite show requests such as
Please show me helloas the same simple output sentence instead of printing the request word. - Document the sentence-to-beginner path with matching English and Korean flat-block examples.
0.0.1-beta.10 — 2026-08-11
- Recover common Korean condition-starter typos (
만악에), spaced Korean particles/endings (이름 이 철수 면), and the spoken그러면connector without turning the right-hand value into text. - Recover clear module typos such as
use random latesand랜덤 사요 최신. - Natural questions accept bare or separated targets (
나이 몇 살이에요,이름 은 뭐예요) while preserving noun names that end in이. - Korean
nme 버전now prints Korean and English version information.
0.0.1-beta.9 — 2026-08-11
- Let a first program ask naturally with
What is your name?,What's your city?,이름이 뭐예요?, or나이는 몇 살이에요?withoutask, commas, or quotes; the final question mark is optional and내 이름은 뭐예요?is also understood. - Accept target-first saves such as
name save Minaand이름 저장 민수, and virtual-indent an ordinary Pythonif/forsuite inside a flat NME block. - Accept short Korean equality endings such as
이름이 철수면,이라면, and준비가 거짓이면, plus bounded spoken typos such as있으먄and철수먄. - Rewrite the first-run examples and tutorials around the sentence-to-Python learning bridge.
0.0.1-beta.8 — 2026-08-11
- Accept subject-first conversational conditions such as
color equals red then show yesand their natural Korean equivalents, including flatendblocks. - Recover common logical connector typos (
그리거,an) and spoken Korean condition endings such as같먄without hijacking ordinary output sentences. - Preserve future Python shapes that the bundled parser does not know yet, including CPython 3.14 t-strings, and add a Windows/macOS/Linux CI matrix.
0.0.1-beta.7 — 2026-08-11
- Make ordinary multiword sentences and contractions such as
Hello world!andI'm readyprint naturally without an output keyword. - Recover common transposed action and condition typos, including
shwoeandthne, while keeping ambiguous Python-shaped input untouched. - Accept an unquoted comma prompt such as
ask name, What is your name?.
0.0.1-beta.6 — 2026-08-11
- Add an easier sentence bridge for value changes (
add 1 to score,점수에 1 더해) and repeat plain words without a colon or output marker. - Accept spaced and attached Korean condition endings, polite sentence fillers,
and explicit Korean beginner save words such as
저장and설정. - Refresh the first-run examples and tutorials so learners can move from sentences through beginner control flow into ordinary Python without a forced indentation jump.
0.0.1-beta.5 — 2026-08-11
- Make the three learning levels easier to mix inside one flat block, with regression coverage for Korean beginner spellings and ordinary Python.
- Accept attached Korean condition endings such as
이름있으면and the natural아니면만약에branch spelling, plus small polite sentence fillers. - Keep top-level Python identifiers such as
endand끝untouched and avoid accidentally opening a colon-based Python block merely because a later NME block has anend. - Refresh the bilingual language reference and local continuation handoff.
0.0.1-beta.4 — 2026-08-11
- Add an indentation-free control-flow bridge:
while,break,and/or,elif/else, andend/끝can be mixed with sentence, beginner, and ordinary Python lines. - Add Korean spellings for the new control-flow forms, virtual indentation for flat blocks, structural diagnostics, and regression examples.
- Expand the English/Korean learning path and AI handoff around growing from the easiest sentences into Python.
0.0.1-beta.3 — 2026-08-11
- Center NME on growing from ordinary sentences, through compact beginner syntax, into Python inside the same project.
- Add extensionless
nme run program,nme 실행 program, andnme programcommands with automatic platform Python selection. - Make Korean CLI flows substantively bilingual while English flows remain English-only, including syntax messages, hints, and command failures.
- Make
checkandbuildvalidate generated source with CPython; failed builds never create an output file. - Fix ambiguous action recovery, condition negation and literals, lexical scope leakage, Korean particles/actions, module validation, apostrophes in English sentences, and physical-line preservation.
- Make Python conversion conservative around calls, multiline statements,
aliases, scopes, prompts, expressions, and ordinary
import random. - Fix Cargo PATH instructions for Fedora and package-manager installations.
0.0.1-beta.2 — 2026-08-10
- Add freely mixable advanced Python, compact beginner, and conversational sentence syntax in English and Korean.
- Add punctuation-light sentence input, output, assignment, repetition, conditions, numeric input, random integers, and random choices.
- Recover bounded one-character action-word typos and report ambiguous prose with a caret and repair hint.
- Add the locally versioned bilingual random adapter and module listing.
- Add safe Python-to-NME conversion for a chosen level and output language.
- Add optional standalone native compilation through an installed Nuitka.
- Add runnable greeting, number-guessing, three-level, and tiny-compiler examples plus matching bilingual tutorials and platform/editor guides.
- Preserve the Python-wins and line-preserving compiler contracts across the new syntax.
0.0.1-beta.1 — 2026-08-10
- Establish the first public beta version line.
- Add bilingual output, text input, repetition, and conditional syntax.
- Keep all valid Python source compatible and byte-identical.
- Provide ready-to-use English and Korean helpers backed by Python's bundled
randommodule. - Add matching English/Korean tutorials, exact language references, examples, and release policy documentation.