[video output=day518 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Displaying Import Errors" vod_platform=youtube id=sGmiIyWx8Gs annotator=Miblo]
[0:00][Recap and set the stage for the day][:speech]
[2:17][Fix ParseTopLevelBlock() to correctly consume a semicolon only once, and remove the redundant check for Context->HHTOut, as per @frostyninja's suggestion][:"asset system" :parsing]
[6:34][Loading alignment points from .hht and applying them to the live assets][:"asset system" :speech :ui]
[7:31][Rename the "IMPORT" and "IMPORT & SAVE" asset editor buttons to "RELOAD HHTs" and "SAVE HHTs"][:"asset system" :ui]
[10:54][Fix compile errors, introducing a version of IsValid() that takes a  buffer]
[13:41][Try out our "RELOAD HHTs" button to see that nothing happens][:"asset system" :run :ui]
[14:49][Delete base_game.hha and intro_cutscene.hha, and let the game regenerate them to find that we must have a bug, but do not know where][:"asset system" :parsing :run]
[16:48][Displaying import errors in our asset editor panel][:"asset system" :"error handling" :parsing :speech :ui]
[20:17][Add an ErrorStream to the htt_context for ParseHHT() to write into][:"asset system" :"error handling" :parsing :ui]
[25:38][Set up AssetEditor() to print out our ErrorStream][:"asset system" :"error handling" :ui]
[30:10][Upgrade TextOp() to operate on a length-string rather than a char *][:"string manipulation"]
[37:51][Find that everything remains intact][:run :"string manipulation"]
[38:30][Further set up AssetEditor() to print out our ErrorStream, upgrading our text printing functions to work on a length-string][:"asset system" :"error handling" :"string manipulation" :ui]
[55:08][Find that everything remains working][:run :"string manipulation"]
[55:34][Enable AssetEditor() to print the actual error stream contents][:"asset system" :"error handling" :"string manipulation" :ui]
[55:53][Check out our asset import errors in-game][:"asset system" :"error handling" :parsing :run :ui]
[56:50][Make Error() colourise its printout][:ui]
[57:31][Check out our colourised errors in-game][:"asset system" :"error handling" :parsing :run :ui]
[57:49][Try to address our syntax errors in base_game.hht][:admin :"asset system"]
[59:46][Enable GetTokenRaw() to track newlines within block comments][:"error handling" :parsing]
[1:03:01][Find that our line numbers are now correct][:"error handling" :parsing :run]
[1:03:13][Enable RequireToken() to report its expected token][:"error handling" :parsing]
[1:07:34][Check out our more informative errors in-game][:"asset system" :"error handling" :parsing :run :ui]
[1:07:51][Fix ParseTopLevelBlock() to output alignment points using the correct syntax][:"asset system" :parsing]
[1:09:02][Find that the asset importer now runs, and loads our .hht alignment points correctly][:"asset system" :parsing :run]
[1:10:24][Backup our .hht files, trigger our asset editor to save out new files, and find that the original and new ones match][:admin :"asset system"]
[1:11:24][Edit alignment points in-game][:"asset system" :run :ui]
[1:14:45][Find that our hero's head :art asset is incorrect][:admin]
[1:17:23][Try to save our edited alignment points, and find that we did not save the file][:"asset system" :"file io" :run]
[1:18:14][Enable SynchronizeAssetFileChanges() to report "Load" or "Save" to our :UI][:"asset system" :"file io"]
[1:21:37][See our "Load" / "Save" report in-game, and again try to save][:"asset system" :"file io" :run]
[1:23:12][Enable ParseTopLevelBlock() to correctly merge alignment point changes, introducing OutPoint()][:"asset system" :parsing]
[1:28:18][Edit and re-save alignment points, to find that our new .hht now (correctly) differs][:"asset system" :"file io" :run]
[1:29:09][Make the caller of OutPoint() responsible for aligning the output][:"asset system" :parsing]
[1:30:40][Try again to edit and re-save alignment points, to find that the .hht does not change][:"asset system" :run :ui]
[1:32:38][Fix the compile error in the calls to Outf()]
[1:33:21][Find that the .hht now (correctly) differs after saving][:"asset system" :run :ui]
[1:33:43][Try again to edit and re-save alignment points, to find that the .hht correctly changes][:"asset system" :run :ui]
[1:35:53][Manually modify our base_game.hht, edit alignment points and re-save them in-game, and find that the .hht file does not get updated reliably][:"asset system" :"file io" :run :ui]
[1:37:24][Enable ParseHHT() to report atomic replace failure or success][:"asset system" :"error handling" :"file io"]
[1:39:20][Reproduce our save bug][:"asset system" :"file io" :run]
[1:40:17][Make ParseHHT() report the .hht filename][:"asset system" :"error handling" :"file io"]
[1:42:31][Try to reproduce our save bug, crash in StringLength() and investigate why][:"asset system" :run]
[1:46:19][Rebuild in -Od, reproduce the StringLength() bug and step through it to see that we unexpectedly get to the va_list version of Outf()][:language :run]
[1:49:16][Verify the fact that a va_list is defined as a char *, which can throw off function overloading][:language :research]
[1:51:28][Rename the va_list overload of Outf() to OutfArgList()][:language]
[1:52:08][Find that we have fixed our va_list induced bug, and that the .hht files now appear to reliably get saved][:"asset system" :"file io" :run :ui]
[1:54:04][Q&A][:speech]
[1:54:39][@teamrandb][And this is why I don't use overloading functions...][:language]
[1:54:55][@frostyninja][Q: Wouldn't it be nice to move the old file to a <filename>.bak in the atomic file replace?][:"file io"]
[1:56:10][@garryjohanson][Q: How awesome would it be if windbg preview had trace diffs?]
[1:56:33][@frostyninja][Q: Read this in Game Engine Architecture by Naughty Dog's guy I can't remember the name of, but they use C++11 user-defined literals to do compile-time hashes on strings. "At Naughty Dog, we permit runtime hashing of strings, but we also use C++11’s user-defined literals feature to transform the syntax "any_string"_sid directly into a hashed integer value at compile time."][:language]
[1:59:40][@Brian][Q: What happens when RequireToken fails? I realize it appends an error, but what does it return? An empty / invalid token? I ask because near the top of the while(Parsing(Tokens)) (or something) where you get the filename and require strings, you did not check the result. So curious if something went wrong, would it just be null?][:parsing]
[2:00:20][@quickshift_][Q: Off-topic, just an idea: In ~4coder, you could do the block re-indentation after exiting the insert mode, instead of live. Then there would be no "jumpy" code while typing]
[2:01:35][@ejgremlin][Q: What are your thoughts on persistent structures like used in Clojure?][:"data structure" :language]
[2:01:57][@aidsjorb][Q: Off-topic: This probably isn't relevant to you working in a small / solo company but as you get "older" any thoughts on aging as a programmer? In a large company it seems many become "managers" but irrespective of large organizations / teams anything you find noteworthy / interesting about your day-to-day as you get older?][:experience]
[2:06:20][@aidsjorb][Q: I asked on the pre-stream yesterday about aspects of programming you didn't enjoy and you mentioned no spec or under spec'd problem domains often being annoying. I was thinking that may well be a young man's game, at least doing it multiple projects in a row]
[2:08:33][@ejgremlin][Q: The structures are like lists in lisp where old versions are kept around because new ones reference the old with only sub-parts containing the new data appended on][:"data structure" :language]
[2:09:29][@y2kiah][Q: It's building up diffs][:"data structure" :language]
[2:09:52][@rippinwaffles][Q: Hey [@cmuratori Casey], I just started working on a super OOP open-source project in C++, and one thing I'm noticing is that it's so hard to find the code that actually does the thing I'm looking for. Can I expect this with modern C++, because it blows? Literally all I'm trying to do is add a menu option, but my exploration is so far looking at eight different files, none of which actually contains the thing that I want, which is, from what I understand, literally just adding a boolean flag in the metadata][:language]
[2:12:30][@ginger_bill][I am working on codegen because LLVM has too many issues: It is slow, it has numerous bugs, it's weirdly / badly designed][:language]
[2:13:36][@level5hm][Q: About splitting code into microscopic files: My coworkers love it because it makes the code "easier to read" for them. It seems like they get lost if a file has > 200 lines]
[2:13:54][@ivereadthesequel][Q: Will moving away from modal in ~4coder affect your wrists? Or have you found that it won't?][:health :ui]
[2:15:29][@nsaibot][Q: The other day I heard someone make the claim that programming without syntax highlighting is more error prone. What would you say?][:ui]
[2:22:00][Wrap it up][:speech]
[/video]
