diff --git a/changelog b/changelog index 1cdfa9d..8eadf40 100644 --- a/changelog +++ b/changelog @@ -1,17 +1,17 @@ -2024-02-18: Cleaned up header css, added changelog. -2024-02-24: Made dir_index.html slightly less cursed server side -2024-04-10: Fix albert hacking my website by rewriting the entire backend (lol) -2024-04-12: Add "natalie-sightings.html" -2024-04-14: Add "cool-sites.html", update home.html to actually be html compliant, updated comment system, add 88x31 collection, minor modification to "natalie-info.html". -2024-04-25: Move hosting to server taken from school basement, (somewhat notable) -2024-04-26: Updated server-migration.html, site-info.html. -2024-05-03: Added link to blog page in home.html, added random statement to home page upon each load -2024-05-11: Rewrote the webserver code, again. Fixed a few things in home.html. +2024-02-18: cleaned up header css, added changelog. +2024-02-24: made dir_index.html slightly less cursed server side +2024-04-10: fix albert hacking my website by rewriting the entire backend (lol) +2024-04-12: add "natalie-sightings.html" +2024-04-14: add "cool-sites.html", update home.html to actually be html compliant, updated comment system, add 88x31 collection, minor modification to "natalie-info.html". +2024-04-25: move hosting to server taken from school basement, (somewhat notable) +2024-04-26: updated server-migration.html, site-info.html. +2024-05-03: added link to blog page in home.html, added random statement to home page upon each load +2024-05-11: rewrote the webserver code, again. Fixed a few things in home.html. 2024-05-19: update theme to be in compliance with new laptop. depricate laptop page -2024-07-06: Now supports http and https. This creates a race condition in theory. Don't care +2024-07-06: now supports http and https. this creates a race condition in theory. don't care 2024-07-09: updated natalie-info.html at the request of cinnabar, who was annoyed at the small number of incorrect things 2024-07-18: create & add header to all pages, changes to css so as to scale with vw -2024-07-24: Append to list of interesting sights, add page complaining about discord +2024-07-24: append to list of interesting sights, add page complaining about discord 2024-07-24: add thoughts page in /html/, update natalie info page 2024-07-24: updated wording in site-info.html, add /stats/ routes, update home.html to make filetree hidden by default because it is big 2024-07-25: rewrite css because winter told me to. Now has dark mode based on a media query. @@ -19,7 +19,7 @@ 2024-07-26: add git.natalieee.net 2024-07-26: update site-info.html 2024-07-26: I have a dns server now. oops. there go my sleeping plans. email me if you want to use it for some insane reason. -2024-07-27: Update style on non blog posts +2024-07-27: update style on non blog posts 2024-07-27: modernize /html/site-info.html, finally 2024-07-27: improve image accessibility, update blog posts to be compliant with new style 2024-07-28: add support for planned footer in all relevant html documents, simplify inclusion of other documents in a document using include script @@ -36,3 +36,4 @@ 2024-09-05: hopefully? fix issue with natalie-info.html, update home.html 2024-09-07: add additional random homepage statements 2024-09-07: add license, finally; edit site-info +2024-09-12: update style.css to support syntax highlighting diff --git a/html/thoughts/python-goto b/html/thoughts/python-goto new file mode 100644 index 0000000..29b0fa8 --- /dev/null +++ b/html/thoughts/python-goto @@ -0,0 +1,170 @@ + + +python is extremely extensible, though I'm not sure that is intentional. +
+firstly, here is the end product of this venture: +
+from goto_label import *
+count = 0 
+#LABEL lol
+print('this prints twice')
+count += 1 
+goto &lol if (count <= 1) else goto &goto_statements_are_a_perfectly_reasonable_thing_to_have_in_python
+
+#LABEL last_print
+print('this prints last')
+goto &stop
+
+#LABEL ellipsis
+print('at least Ellipsis() has some use now, for normal reasons that make sense')
+goto &last_print
+
+#LABEL goto_statements_are_a_perfectly_reasonable_thing_to_have_in_python
+print('I am sure this is how the variety of language features I am abusing were intended to be used')
+goto &ellipsis
+#LABEL stop
+...
+
+
+its beautiful.
+this outputs the following: +
+this prints twice
+this prints twice
+I am sure this is how the variety of language features I am abusing were intended to be used
+at least Ellipsis() has some use now, for normal reasons that make sense
+this prints last
+
+
+now then, how does it work? +

design decisions

+given that evidence suggests python programs can be edited, I decided not to use line number based gotos and instead define labels that could be jumped to. +this makes things less annoying to edit and maintain, and developer experience is obviously a very important consideration with this project.
+additionally, to maximize ease with which this ""library"" can be utilized, one must only import the file to experience the wonder of python with goto statements. +

technical implementation

+firstly, labels:
+goto_label.py has a function prepare_labels(fp, scope). +this function looks for any labels (defined via /^#LABEL labelname/) in the file at fp, and defines them under the scope scope. +each label is defined as a label object. I resent using an object for this (which you can see by my not using the class keyword), but python is python and you cannot override operators without having a class. +I could just not override the operators, but I want goto to be called in a unique way that is separate from how a function would be called. +label objects have only one attribute: lineno, which is determined by an extremely rudimentary parser and then offset by 2 to account for the fact that lines are 0 indexed in the "parser" but not in real life and the fact that the label definition comment takes its own line. +

+the actual goto implementation:
+I don't remember how this works because I wrote most of the _goto function like 3 months ago after reading the sys and inspect module docs. +my projects have this fun property where they are in one of three states: done; not touched or thought about for 2-36 months; and done. +oh well, the goto function is vaguely self explanatory anyways. +
+there is some weirdness with operator overloading and how every goto statement is actually just calling what would normally be the bitwise and operator on an instance of the class _goto (not to be confused with the function _goto) and a label object, but that is both very simple and not required to understand this.
+also, I don't want to explain it because I am tired. +

+automatically parsing the importing file on import:
+normally, globals are not shared between modules, but python has this cool feature where if there is a general statement to be made about it then this statement can be invalidated using either the sys, inspect, or ctypes library. +this is easily the simplest part as we just grab the filename and global scope of the importing file via the inspect library and pass them to prepare_labels(). +
+

goto_label.py

+
+import sys, inspect
+
+debug = False
+
+def prepare_labels(fp, scope):
+    with open(fp, 'r') as f:
+        lines = f.readlines()
+
+    for lineno, line in enumerate(lines):
+        if line.startswith('#LABEL'):
+            # 1 + 1, first to account for 0 index then to account for comment line
+            scope.__setitem__(line.split(' ')[1].strip(), type(
+                'label',
+                (object,),
+                dict(line=lineno+2)
+            )())
+
+_goto = type('goto', (object,), dict(__and__=lambda _, other: _goto(other.line)))
+
+goto = _goto()
+
+def _goto(lineno):
+    if debug: print(lineno)
+    frame = sys._getframe().f_back.f_back
+    called_from = frame
+
+    def hook(frame, event, arg):
+        if event == 'line' and frame == called_from:
+            try:
+                frame.f_lineno = lineno
+            except ValueError as e:
+                print("jump failed:", e)
+            while frame:
+                frame.f_trace = None
+                frame = frame.f_back
+            return None
+        return hook
+
+    while frame:
+        frame.f_trace = hook
+        frame = frame.f_back
+    sys.settrace(hook)
+
+prepare_labels(inspect.stack()[-1].frame.f_code.co_filename, inspect.stack()[-1].frame.f_globals)
+
+
+
+I find much enjoyment in the syntax for calling a goto statement being goto &label. it looks like something that thoroughly does not belong in python. +

+ideas for future improvement: +making label names override builtin function names (unreasonably possible) and making a __call__ method on label objects that jumps to that label. +hopefully no one creates any labels named "print". +
+random other programs I (badly) implemented using if conditions only for goto statements out of boredom: +

fibonacci

+
+from goto_label import *
+
+def fib(n):
+    depth = 0 
+    a = 1
+    b = 0
+#LABEL fib_start
+    print(a)
+    a, b, depth = b, b + a, depth + 1
+    if depth > n+1: goto &fib_end
+    goto &fib_start
+#LABEL fib_end
+    ...
+
+fib(20)
+
+
+

fizzbuzz

+
+from goto_label import *
+
+def fizzbuzz(n):
+    count = 0
+#LABEL fizz_start
+    str = ''
+    if n == count: goto &fizz_end;
+    count += 1 
+    if count % 3 == 0: goto &fizz; 
+#LABEL buzz_check
+    if count % 5 == 0: goto &buzz;
+    goto &output;
+
+#LABEL fizz
+    str += 'fizz'
+    goto &buzz_check;
+#LABEL buzz 
+    str += 'buzz'
+#LABEL output
+    print(str if str else count)
+    goto &fizz_start;
+#LABEL fizz_end 
+    ...
+
+fizzbuzz(100)
+
+
+
+number of times the python interpreter segfaulted today: 7
+syntax highlighting here is done via :TOhtml in vim. it should work? diff --git a/style.css b/style.css index 1b3b065..818fa96 100644 --- a/style.css +++ b/style.css @@ -45,6 +45,23 @@ align-items: center; } +.-punctuation-bracket {color: #ff7eb6} +.-keyword-function {color: #ff7eb6} +.Number {color: #ffab91} +.-variable {color: #37474f} +.-variable-builtin {color: #37474f} +.-keyword {color: #ee5396} +.Operator {color: #ee5396} +.-constant-builtin {color: #08bdba} +.-function-builtin {color: #673ab7} +.Type {color: #ee5396} +.-function {font-weight: bold; color: #673ab7} +.String {color: #be95ff} +.Comment {font-style: italic; color: #161616} +.Boolean {color: #ee5396} +.-keyword-operator {color: #ff7eb6} +.-punctuation-delimiter {color: #ff7eb6} + @media (prefers-color-scheme: dark) { :root { --bg: #161616; @@ -56,6 +73,23 @@ --highlight: #33b1ff; --gray: #202020; } + + .-punctuation-bracket {color: #3ddbd9} + .-keyword-function {color: #3ddbd9} + .Number {color: #82cfff} + .-variable {color: #d0d0d0} + .-variable-builtin {color: #d0d0d0} + .-keyword {color: #78a9ff} + .Operator {color: #78a9ff} + .-constant-builtin {color: #08bdba} + .-function-builtin {color: #ff7eb6} + .Type {color: #78a9ff} + .-function {font-weight: bold; color: #ff7eb6} + .String {color: #be95ff} + .Comment {font-style: italic; color: #525252} + .Boolean {color: #78a9ff} + .-keyword-operator {color: #3ddbd9} + .-punctuation-delimiter {color: #3ddbd9} } .rainbow-text {