added: titles and favicon
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 2 May 2023 03:17:02 +0000 (22:17 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 2 May 2023 03:17:02 +0000 (22:17 -0500)
15 files changed:
build.onyx
onyx-pkg.ini
src/app.onyx
src/cached_resource.onyx [new file with mode: 0644]
www/news-articles/index.json
www/news-articles/memory_model.html [new file with mode: 0644]
www/static/css/new_style.css
www/static/images/favicon.ico [new file with mode: 0644]
www/templates/pages/404.html
www/templates/pages/base.html
www/templates/pages/docs.html
www/templates/pages/docs/install.html
www/templates/pages/homepage.html
www/templates/pages/news.html
www/templates/pages/news_article.html

index e56f8a26a0539659a0841992fc178367f83a64d6..09be220b73862b53bc72770d63373d3e53e669fa 100644 (file)
@@ -1,8 +1,4 @@
-#load "./lib/http-server/module"
-#load "./lib/postgres/module"
-#load "./lib/postgres-orm/module"
-#load "./lib/otmp/module"
-#library_path "./bin"
+#load "./lib/packages"
 
 #load_all "./src"
 
index 2e4b2e0f342c7fc3531879dfea608b47b9888e4d..9ba7f06fd9d587e8908dd45f7529a081ee2e50a1 100644 (file)
@@ -20,6 +20,7 @@ library=
 git://onyxlang.io/repo/http-server=0.1.26
 git://onyxlang.io/repo/postgres-orm=0.0.25
 git://onyxlang.io/repo/otmp=0.0.7
+git://onyxlang.io/repo/postgres=0.0.10
 
 [dependency_folders]
 git://onyxlang.io/repo/http-server=http-server
index 10812c4353e1fc6b8b84f8cb824ea7bf25a61ac7..ec3d3c30654d63fee0f5474d5c0726dfeccdf037 100644 (file)
@@ -14,43 +14,45 @@ reg: otmp.TemplateRegistry;
 #inject Res {
     render :: (r: &Res, template: str, vars: any) {
         s := reg->render_template(template, &r.writer, .{ vars.data, vars.type });
+
+        if s != .None {
+            log(.Warning, "Template Renderer", tprintf("{}", s));
+        }
+
         r->status(200 if s == .None else 400);
         r->end();
     }
 }
 
 @route.{.GET, "/"}
-(req: &Req, res: &Res) {
-    res->render("pages/homepage", null);
-}
-
+(req: &Req, res: &Res) => res->render("pages/homepage", null);
 
 @route.{.GET, "/ovmwasm"}
-(req: &Req, res: &Res) {
-    res->render("pages/ovmwasm", null);
-}
+(req: &Req, res: &Res) => res->render("pages/ovmwasm", null);
 
 @route.{.GET, "/docs"}
-(req: &Req, res: &Res) {
-    res->render("pages/docs", null);
-}
+(req: &Req, res: &Res) => res->render("pages/docs", null);
 
 @route.{.GET, "/docs/install"}
-(req: &Req, res: &Res) {
-    res->render("pages/docs/install", null);
-}
+(req: &Req, res: &Res) => res->render("pages/docs/install", null);
+
+
+Article :: struct { name, description, path, date: str }
+news_articles: Cached_Resource([] Article);
 
 @route.{.GET, "/news/:article"}
 (req: &Req, res: &Res) {
-    // TODO: Safety / error checking here
-    filename := tprintf("www/news-articles/{}.html", req.url_params["article"]);
+    article := array.first(news_articles->get() ?? .[], #(it.path == req.url_params["article"]));
+    if !article do return;
+
+    filename := tprintf("www/news-articles/{}.html", article.path);
 
     if os.file_exists(filename) {
-        article := os.get_contents(filename);
-        defer delete(&article);
+        contents := os.get_contents(filename);
+        defer delete(&contents);
 
         res->render("pages/news_article", &.{
-            article = article
+            article = .{ contents = contents, name = article.name }
         });
 
     } else {
@@ -60,17 +62,7 @@ reg: otmp.TemplateRegistry;
 
 @route.{.GET, "/news"}
 (req: &Req, res: &Res) {
-    Article :: struct { name, description, path, date: str }
-    articles: [] Article;
-
-    article_file := os.get_contents("www/news-articles/index.json");
-    article_index, json_err := json.decode_with_error(article_file);
-    if json_err->has_error() {
-        res->status(500);
-        return;
-    }
-
-    json.as_any(article_index.root, &articles);
+    articles := news_articles->get() ?? .[];
 
     res->render("pages/news", &.{
         articles = articles
@@ -81,6 +73,30 @@ main :: () {
     reg = otmp.registry();
     reg->load_directory("./www/templates", ".html");
 
+    news_articles = .{
+        resource = .{},
+        max_age = 60 * 60, // 1 hour
+
+        fetch_resource = () -> ? [] Article {
+            article_file := os.get_contents("www/news-articles/index.json");
+            article_index, json_err := json.decode_with_error(article_file);
+            if json_err->has_error() {
+                return .{};
+            }
+
+            articles: [] Article;
+            #context_scope {
+                context.allocator = alloc.heap_allocator;
+                json.as_any(article_index.root, &articles);
+            }
+            return articles;
+        },
+
+        release_resource = (articles: &[] Article) {
+            delete(articles, allocator=alloc.heap_allocator);
+        }
+    };
+
     app := http.server.application();
 
     http.server.set_mime_type("svg", "image/svg+xml");
diff --git a/src/cached_resource.onyx b/src/cached_resource.onyx
new file mode 100644 (file)
index 0000000..33ad52f
--- /dev/null
@@ -0,0 +1,49 @@
+package main
+
+use core {package, tprintf}
+use core.time
+
+Cached_Resource :: struct (Res: type_expr) {
+    last_retrieved: time.Timestamp;
+    max_age: i32; // In seconds
+
+    resource: ? Res;
+    fetch_resource: () -> ? Res;
+    release_resource: (res: &Res) -> void;
+}
+
+#inject Cached_Resource {
+    get :: (use self: &#Self) -> ? self.Res {
+        if !resource {
+            update_resource(self);
+        }
+
+        if time.duration(time.now(), last_retrieved) > max_age {
+            update_resource(self);
+        }
+
+        return self.resource;
+    }
+}
+
+#local
+update_resource :: (self: &Cached_Resource($T)) {
+    if self.resource {
+        self.release_resource(&self.resource.value);
+        self.resource->reset();
+    }
+
+    self.resource = self.fetch_resource();
+    self.last_retrieved = time.now();
+}
+
+
+
+#inject time {
+    duration :: (t2, t1: time.Timestamp) -> i32 {
+        t1_ := t1;
+        t2_ := t2;
+        return ~~(t2_->to_epoch() - t1_->to_epoch());
+    }
+}
+
index 192714a1ed32ac1a9d9817838476d4ce6f919eb6..3a5d45a6753c2fdb6d9b5929b38793b1385fbb8e 100644 (file)
@@ -1,8 +1,14 @@
 [
+    {
+        "name": "Onyx's Memory Model",
+        "path": "memory_model",
+        "date": "29th April 2023",
+        "description": "A explanation of the memory model employed by Onyx."
+    },
     {
         "name": "Onyx's Custom Runtime",
         "path": "ovmwasm",
         "date": "5th April 2023",
-        "description": "Something about a brief introduction to the OVM-Wasm system."
+        "description": "A brief introduction to OVM-Wasm, Onyx's custom WASM runtime for debugging and portability."
     }
 ]
diff --git a/www/news-articles/memory_model.html b/www/news-articles/memory_model.html
new file mode 100644 (file)
index 0000000..472436a
--- /dev/null
@@ -0,0 +1,91 @@
+<h1>Onyx's Memory Model</h1>
+
+<p>
+When choosing and/or learning a programming language, the memory model is one of the first things you will have to understand to successfully use the language.
+In broad terms, there are three memory models employed in programming languages used today: <i>manual, manual with assistance, and automatic.</i>
+</p>
+
+<p>
+In a <i>manual</i> memory model, almost all memory allocations and deallocations are done, well, manually.
+You, the programmer, are responsible for diligently freeing <i>every</i> piece of memory you allocate; otherwise, over time, your program's memory usage will increase and start consuming a lot of system resources.
+</p>
+<blockquote>
+    Do note, that this only applies to programs that run for a long time, or need to work with a lot of resources.
+    Forgetting to free a 100 element array in your small 10 line program is not going to be the end of the world.
+    The operating system is responsible for reclaiming all resources your program used when your program exits.
+</blockquote>
+
+<p>
+In an <i>automatic</i> memory model, you are not responsible for managing any allocation made by your program.
+Programming languages with this memory model generally employ a garbage collector or reference counted pointers.
+</p>
+
+<p>
+The third and final memory model is <i>manual with assistance</i>, which is the memory model that Onyx uses.
+This model trusts the programmer to understand their memory needs, allowing total control over memory.
+However, it also offers core library support for describing the memory model.
+</p>
+
+<h2>Allocators</h2>
+
+<p>
+Onyx abstracts the notion of memory management into an <i>Allocator</i>.
+Anything that requires allocating memory should consume an Allocator as a parameter.
+This is the pattern followed by everything in the core library; all memory allocations are configurable.
+Also as a convience, the default allocator used by the core library is <code>context.allocator</code>.
+This is a thread-local variable that is a general purpose heap allocator by default, but can be changed.
+This allows for changing the allocator used by a library even if the library does not take an allocator as a paramter.
+</p>
+
+<p>
+Most programmers will not have to write their own allocator.
+Instead they will use one of half-dozen provided out of the box by the core libraries.
+</p>
+
+<h3>Heap Allocator</h3>
+<p>
+In every Onyx program, there is a single general purpose heap allocator.
+It can be accessed in <code>core.alloc.heap_allocator</code>.
+It is automatically setup before your program reaches <code>main</code>.
+It is also the default allocator used by <code>context.allocator</code>, meaning functions like <code>new</code>, <code>make</code>, and <code>calloc</code> will use it by default.
+</p>
+
+<blockquote>
+While Onyx has its own heap allocation procedures, the heap allocator is effectively equivalent to C's <code>malloc</code> and <code>free</code>.
+You are responsible for manually freeing the memory allocated from it.
+</blockquote>
+
+<p>
+Here is an example of using the heap allocator directly.
+</p>
+
+<pre class="hljs"><code class="language-onyx">use core {*}
+
+main :: () {
+    // Directly allocate an array of 10 u32's.
+    data := cast([&] u32) alloc.heap_allocator->alloc(sizeof u32 * 10);
+
+    // Ensure the memory is freed when the function returns.
+    defer alloc.heap_allocator->free(data);
+
+    // Fill the array with squares
+    for 10 {
+        data[it] = it * it;
+    }
+
+    // Print out the array
+    for 10 {
+        println(data[it]);
+    }
+}
+</code></pre>
+
+
+<h3>Arena Allocator</h3>
+
+<p>
+While the general purpose heap allocator will work in any situation, it is not the fastest.
+Also, it requires you to correctly manage the memory allocated from it, which can be error prone.
+</p>
+
+
index 58600cca26da7b94ed96fc058515064e56c89791..b7de5d8f8685757c03b9adcf37a25b7403add478 100644 (file)
@@ -111,6 +111,10 @@ h1, h2, h3, h4, h5, h6 {
     font-weight: 200;
 }
 
+.container h2 {
+    margin-top: 16px;
+}
+
 .container h3 {
     margin-top: 12px;
 }
@@ -228,6 +232,13 @@ main pre {
     display: block;
 }
 
+main blockquote {
+    border-left: 4px solid var(--dark-background-color);
+    background-color: var(--light-background-color);
+    margin-top: 12px;
+    padding: 8px;
+}
+
 main li {
     margin-top: 8px;
 }
diff --git a/www/static/images/favicon.ico b/www/static/images/favicon.ico
new file mode 100644 (file)
index 0000000..dab3947
Binary files /dev/null and b/www/static/images/favicon.ico differ
index 42b205672c959a515333620ea40aaf310e390080..80dd35e86a72aade1de4975939da54c315011eee 100644 (file)
@@ -1,3 +1,5 @@
+{{block "title"}}Onyx - Page not found{{endblock}}
+
 {{block "content"}}
 
 <main>
index bd6037762c0987663ca8039a7ccf83664918757e..2af2bf6916f298dc861589d8c823cc0c42fae142 100644 (file)
@@ -7,6 +7,7 @@
         <meta name="viewport" content="width=device-width, initial-scale=1">
         <meta name="description" content="The Onyx programming language, by Brendan Hansen.">
 
+        <link rel="icon" type="image/x-icon" href="/static/images/favicon.ico">
         <link rel="stylesheet" href="/static/css/new_style.css">
 
         <!-- Including this on every page because why not -->
index a17d95e3980854699570dd20ea8b9c8441520a17..566a4dc2a051e872605cacb037220e8d2f82260a 100644 (file)
@@ -1,3 +1,5 @@
+{{block "title"}}Onyx Documentation{{endblock}}
+
 {{block "page_content"}}
 
 <div class="container">
index e7b0da048556a5768a1cc0e33d1ab29c784250d7..d626fd6fbfcc9d75552399f968db8815014bb319 100644 (file)
@@ -1,3 +1,5 @@
+{{block "title"}}Onyx Installation{{endblock}}
+
 {{ block "page_content" }}
 
 <div class="container">
index 222b1b84b2614e4d9198ffdb3c4ebd7ece264cba..2e18fdcb69218f15c3de3bfb71ca09dc69f4054c 100644 (file)
@@ -1,3 +1,5 @@
+{{block "title"}}The Onyx Programming Language{{endblock}}
+
 {{block "page_content"}}
 
 <div class="container center" style="margin: 0 auto">
index 3ee0613e76b233da1c5a8cf2923242f2ebb43916..1f7ba152594b098677f994c6a9b3d7b35d2ce89a 100644 (file)
@@ -1,3 +1,5 @@
+{{block "title"}}Onyx News{{endblock}}
+
 {{block "page_content"}}
 
 <div class="container">
index db9362fa159c0e804512dd4d393c99970cf29edc..a19f0f238ccfc195221b033d26165c01bd350d1f 100644 (file)
@@ -1,10 +1,12 @@
+{{block "title"}}Onyx News - {% $article.name %}{{endblock}}
+
 {{block "content"}}
 
 <main>
     {% partial "partials/navbar" %}
 
     <div class="container">
-        {% $article %}
+        {% $article.contents %}
     </div>
 
     {% partial "partials/footer" %}