clean up old samples; mark md_c_helpers with an error; remove c helper tests

This commit is contained in:
Allen Webster
2021-09-01 19:01:27 -07:00
parent 4452663046
commit a2766a2e0c
20 changed files with 30 additions and 1467 deletions
-2
View File
@@ -10,8 +10,6 @@ echo "~~~ Build All Samples ~~~"
bin/bld_core.sh show_ctx
bin/bld_core.sh unit old_style_custom_layer samples/old_style_custom_layer.c
bin/bld_core.sh unit toy_language samples/toy_language/toy_language.c
bin/bld_core.sh unit static_site_generator samples/static_site_generator/static_site_generator.c
bin/bld_core.sh unit output_parse samples/output_parse/output_parse.c
bin/bld_core.sh unit c_code_generation samples/c_code_generation.c
bin/bld_core.sh unit node_errors samples/node_errors/node_errors.c
-10
View File
@@ -8,16 +8,6 @@ cd ..
build_path=$root_path/build
samples_path=$root_path/samples
echo ~~~ Running Static Site Generator Sample ~~~
cd $samples_path
if [ -d "static_site_generator/example_site" ]; then
cd static_site_generator/example_site
mkdir -p generated
cd generated
$build_path/static_site_generator.exe --siteinfo:../site_info.mdesk --pagedir:../
fi
echo
echo ~~~ Running Output Parse Sample ~~~
cd $samples_path
if [ -d "output_parse/examples" ]; then
+28 -23
View File
@@ -28,28 +28,6 @@ load_paths =
command_list =
{
{
.name = "build",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
.cmd =
{
{ "build.bat", .os = "win" },
},
},
{
.name = "build_with_clang",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
.cmd =
{
{ "build_with_clang.bat", .os = "win" },
},
},
{
.name = "all_dev_checks",
.out = "*compilation*",
@@ -63,9 +41,36 @@ command_list =
{ "bin/all_dev_checks.sh", .os = "mac" },
},
},
{
.name = "build_tests",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
.cmd =
{
{ "git_bash bin\\build_tests.sh", .os = "win" },
{ "bin/build_tests.sh", .os = "linux" },
{ "bin/build_tests.sh", .os = "mac" },
},
},
{
.name = "run_tests",
.out = "*run*",
.footer_panel = false,
.save_dirty_files = true,
.cursor_at_end = false,
.cmd =
{
{ "git_bash bin\\run_tests.sh", .os = "win" },
{ "bin/run_tests.sh", .os = "linux" },
{ "bin/run_tests.sh", .os = "mac" },
},
},
};
fkey_command[1] = "all_dev_checks";
fkey_command[1] = "build_tests";
fkey_command[2] = "run_tests";
fkey_command[8] = "build";
fkey_command[9] = "build_with_clang";
@@ -1,62 +0,0 @@
title: "Test Blog #1"
desc: "This is my test blog."
date: (2020/11/30)
index: {"blog"}
parent: "blog_main"
@subtitle "Section 1"
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ut ornare neque, vitae finibus leo. Praesent pulvinar, urna id lobortis iaculis, velit turpis luctus tortor, quis malesuada neque neque vitae turpis. Phasellus id molestie elit. Sed elementum ipsum a ligula semper, at varius augue rutrum. Pellentesque fringilla, orci nec fringilla finibus, turpis lacus vehicula elit, nec bibendum magna est quis massa. Aliquam efficitur facilisis nibh, ut sodales sapien scelerisque nec. Integer justo sem, pellentesque et ante imperdiet, interdum placerat sem.
Nunc hendrerit lobortis commodo. Morbi felis quam, fermentum vitae libero vitae, fermentum sodales quam. Nulla bibendum tellus quis lorem sollicitudin pretium. Etiam commodo ex eget aliquet porta. In sit amet dui eleifend, mattis sem nec, tristique erat. Morbi malesuada fringilla bibendum. Integer odio ex, cursus a sodales quis, vehicula non dolor.
Praesent vitae pharetra felis. Curabitur non ex non nunc pretium feugiat eu sit amet turpis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean blandit ante leo. Vivamus iaculis mi vel sem tincidunt maximus. Aenean elementum ipsum non laoreet semper. Morbi non felis interdum lectus pulvinar mollis id non purus. Nullam eu ipsum ut turpis aliquam feugiat at non tellus. Suspendisse ornare erat quis enim ullamcorper, at rhoncus nulla suscipit.
"""
@img {"test.png", "My funny image."}
@subtitle "Section 2"
"""
Aliquam quis diam at sem interdum imperdiet. Nunc imperdiet ligula tempus nibh semper mattis. Suspendisse fringilla molestie semper. Sed felis dolor, vehicula et tempus sed, porttitor finibus lacus. Pellentesque egestas ex finibus, facilisis tellus suscipit, accumsan turpis. Ut imperdiet vitae nisl eget vestibulum. Donec eu bibendum erat, id maximus magna. Vivamus quis rhoncus justo. Morbi eget commodo lorem, vulputate varius ipsum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Integer accumsan, sem vel rutrum cursus, odio enim sodales leo, sit amet rutrum odio purus at nisi. Fusce iaculis ante id nunc volutpat tincidunt. Duis nec tincidunt ipsum. Fusce vitae odio ac velit sollicitudin maximus. Vestibulum ante dui, varius auctor ante eu, gravida laoreet justo.
Vivamus dignissim mauris nec turpis convallis, vitae pellentesque sapien faucibus. Phasellus eu euismod elit, sit amet vehicula diam. Curabitur sit amet leo magna. In est erat, congue vel euismod id, venenatis vitae mauris. Vestibulum sit amet leo eget leo ornare feugiat. Interdum et malesuada fames ac ante ipsum primis in faucibus. Vivamus at efficitur ex, a mattis lorem. Maecenas blandit tincidunt tortor vel cursus. In in purus a nisi pretium venenatis in ut lacus. Maecenas venenatis rutrum laoreet. Donec aliquam leo vel risus cursus, placerat pretium lacus fringilla. Suspendisse ut porttitor mauris.
"""
@youtube {"BjdY1eXB6cY"}
@subtitle "Section 3"
@list
{
"hello",
"world",
"foo",
@list
{
"a",
"b",
"c",
},
"another list item",
}
@subtitle "Section 4"
@code
"""
char *html_tag = "p";
if(DD_NodeHasTag(node, DD_S8Lit("title")))
{
html_tag = "h1";
}
else if(DD_NodeHasTag(node, DD_S8Lit("subtitle")))
{
html_tag = "h2";
}
else if(DD_NodeHasTag(node, DD_S8Lit("code")))
{
html_tag = "pre";
}
"""
@@ -1,17 +0,0 @@
title: "Hello, Again!"
desc: "This is another test blog."
date: (2020/11/28)
index: {"blog"}
parent: "blog_main"
@subtitle "Section 1"
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ut ornare neque, vitae finibus leo. Praesent pulvinar, urna id lobortis iaculis, velit turpis luctus tortor, quis malesuada neque neque vitae turpis. Phasellus id molestie elit. Sed elementum ipsum a ligula semper, at varius augue rutrum. Pellentesque fringilla, orci nec fringilla finibus, turpis lacus vehicula elit, nec bibendum magna est quis massa. Aliquam efficitur facilisis nibh, ut sodales sapien scelerisque nec. Integer justo sem, pellentesque et ante imperdiet, interdum placerat sem.
Nunc hendrerit lobortis commodo. Morbi felis quam, fermentum vitae libero vitae, fermentum sodales quam. Nulla bibendum tellus quis lorem sollicitudin pretium. Etiam commodo ex eget aliquet porta. In sit amet dui eleifend, mattis sem nec, tristique erat. Morbi malesuada fringilla bibendum. Integer odio ex, cursus a sodales quis, vehicula non dolor.
Praesent vitae pharetra felis. Curabitur non ex non nunc pretium feugiat eu sit amet turpis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean blandit ante leo. Vivamus iaculis mi vel sem tincidunt maximus. Aenean elementum ipsum non laoreet semper. Morbi non felis interdum lectus pulvinar mollis id non purus. Nullam eu ipsum ut turpis aliquam feugiat at non tellus. Suspendisse ornare erat quis enim ullamcorper, at rhoncus nulla suscipit.
"""
@img {"test.png", "My funny image."}
@@ -1,3 +0,0 @@
title: "Blog"
@lister {"blog"}
@@ -1,5 +0,0 @@
@echo off
if not exist generated mkdir generated
pushd generated
..\..\..\build\static_site_generator.exe --siteinfo ..\site_info.mdesk --pagedir ..\
popd
@@ -1,36 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"><meta name="author" content="Ryan Fleury">
<meta property="og:title" content="">
<meta name="twitter:title" content="">
<link rel="canonical" href="https://example.site">
<meta property="og:type" content="website">
<meta property="og:url" content="https://example.site">
<meta property="og:site_name" content="Example Site">
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@ryanjfleury">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="site.js"></script>
<title>Example Site</title>
</head>
<body>
<div class="header">
<h1>Example Site</h1>
<a href="#">Test Link 1</a>
<a href="#">Test Link 2</a>
<a href="#">Test Link 3</a>
</div>
<div class="page_content">
</div>
<div class="footer">
<h4>Example Site Footer</h4>
<a href="#">Test Link 1</a>
<a href="#">Test Link 2</a>
<a href="#">Test Link 3</a>
</div>
</body>
</html>
@@ -1,91 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"><meta name="author" content="Ryan Fleury">
<meta property="og:title" content="Test Blog #1">
<meta name="twitter:title" content="Test Blog #1">
<link rel="canonical" href="https://example.site">
<meta property="og:type" content="website">
<meta property="og:url" content="https://example.site">
<meta property="og:site_name" content="Example Site">
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@ryanjfleury">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="site.js"></script>
<title>Test Blog #1 | Example Site</title>
</head>
<body>
<div class="header">
<h1>Example Site</h1>
<a href="#">Test Link 1</a>
<a href="#">Test Link 2</a>
<a href="#">Test Link 3</a>
</div>
<div class="page_content">
<div class="standalone_link_container"><a class="link" href="blog_main.html">← Back</a></div><h1 class="title">Test Blog #1</h1><h2 class="subtitle">This is my test blog.</h2><h3 class="date">30 November 2020</h3><h2 class="subtitle">Section 1</h2>
<p class="paragraph">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ut ornare neque, vitae finibus leo. Praesent pulvinar, urna id lobortis iaculis, velit turpis luctus tortor, quis malesuada neque neque vitae turpis. Phasellus id molestie elit. Sed elementum ipsum a ligula semper, at varius augue rutrum. Pellentesque fringilla, orci nec fringilla finibus, turpis lacus vehicula elit, nec bibendum magna est quis massa. Aliquam efficitur facilisis nibh, ut sodales sapien scelerisque nec. Integer justo sem, pellentesque et ante imperdiet, interdum placerat sem.</p>
<p class="paragraph">Nunc hendrerit lobortis commodo. Morbi felis quam, fermentum vitae libero vitae, fermentum sodales quam. Nulla bibendum tellus quis lorem sollicitudin pretium. Etiam commodo ex eget aliquet porta. In sit amet dui eleifend, mattis sem nec, tristique erat. Morbi malesuada fringilla bibendum. Integer odio ex, cursus a sodales quis, vehicula non dolor.</p>
<p class="paragraph">Praesent vitae pharetra felis. Curabitur non ex non nunc pretium feugiat eu sit amet turpis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean blandit ante leo. Vivamus iaculis mi vel sem tincidunt maximus. Aenean elementum ipsum non laoreet semper. Morbi non felis interdum lectus pulvinar mollis id non purus. Nullam eu ipsum ut turpis aliquam feugiat at non tellus. Suspendisse ornare erat quis enim ullamcorper, at rhoncus nulla suscipit.
</p>
<div class="img_container"><img class="img" src="test.png"></img></div>
<h2 class="subtitle">Section 2</h2>
<p class="paragraph">
Aliquam quis diam at sem interdum imperdiet. Nunc imperdiet ligula tempus nibh semper mattis. Suspendisse fringilla molestie semper. Sed felis dolor, vehicula et tempus sed, porttitor finibus lacus. Pellentesque egestas ex finibus, facilisis tellus suscipit, accumsan turpis. Ut imperdiet vitae nisl eget vestibulum. Donec eu bibendum erat, id maximus magna. Vivamus quis rhoncus justo. Morbi eget commodo lorem, vulputate varius ipsum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Integer accumsan, sem vel rutrum cursus, odio enim sodales leo, sit amet rutrum odio purus at nisi. Fusce iaculis ante id nunc volutpat tincidunt. Duis nec tincidunt ipsum. Fusce vitae odio ac velit sollicitudin maximus. Vestibulum ante dui, varius auctor ante eu, gravida laoreet justo.</p>
<p class="paragraph">Vivamus dignissim mauris nec turpis convallis, vitae pellentesque sapien faucibus. Phasellus eu euismod elit, sit amet vehicula diam. Curabitur sit amet leo magna. In est erat, congue vel euismod id, venenatis vitae mauris. Vestibulum sit amet leo eget leo ornare feugiat. Interdum et malesuada fames ac ante ipsum primis in faucibus. Vivamus at efficitur ex, a mattis lorem. Maecenas blandit tincidunt tortor vel cursus. In in purus a nisi pretium venenatis in ut lacus. Maecenas venenatis rutrum laoreet. Donec aliquam leo vel risus cursus, placerat pretium lacus fringilla. Suspendisse ut porttitor mauris.
</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/BjdY1eXB6cY" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<h2 class="subtitle">Section 3</h2>
<ul class="list">
<li class="list_item">
<p class="paragraph">hello</p>
</li>
<li class="list_item">
<p class="paragraph">world</p>
</li>
<li class="list_item">
<p class="paragraph">foo</p>
</li>
<ul class="list">
<li class="list_item">
<p class="paragraph">a</p>
</li>
<li class="list_item">
<p class="paragraph">b</p>
</li>
<li class="list_item">
<p class="paragraph">c</p>
</li>
</ul>
<li class="list_item">
<p class="paragraph">another list item</p>
</li>
</ul>
<h2 class="subtitle">Section 4</h2>
<pre class="code">
char *html_tag = "p";
if(DD_NodeHasTag(node, DD_S8Lit("title")))
{
html_tag = "h1";
}
else if(DD_NodeHasTag(node, DD_S8Lit("subtitle")))
{
html_tag = "h2";
}
else if(DD_NodeHasTag(node, DD_S8Lit("code")))
{
html_tag = "pre";
}
</pre>
</div>
<div class="footer">
<h4>Example Site Footer</h4>
<a href="#">Test Link 1</a>
<a href="#">Test Link 2</a>
<a href="#">Test Link 3</a>
</div>
</body>
</html>
@@ -1,43 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"><meta name="author" content="Ryan Fleury">
<meta property="og:title" content="Hello, Again!">
<meta name="twitter:title" content="Hello, Again!">
<link rel="canonical" href="https://example.site">
<meta property="og:type" content="website">
<meta property="og:url" content="https://example.site">
<meta property="og:site_name" content="Example Site">
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@ryanjfleury">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="site.js"></script>
<title>Hello, Again! | Example Site</title>
</head>
<body>
<div class="header">
<h1>Example Site</h1>
<a href="#">Test Link 1</a>
<a href="#">Test Link 2</a>
<a href="#">Test Link 3</a>
</div>
<div class="page_content">
<div class="standalone_link_container"><a class="link" href="blog_main.html">← Back</a></div><h1 class="title">Hello, Again!</h1><h2 class="subtitle">This is another test blog.</h2><h3 class="date">28 November 2020</h3><h2 class="subtitle">Section 1</h2>
<p class="paragraph">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ut ornare neque, vitae finibus leo. Praesent pulvinar, urna id lobortis iaculis, velit turpis luctus tortor, quis malesuada neque neque vitae turpis. Phasellus id molestie elit. Sed elementum ipsum a ligula semper, at varius augue rutrum. Pellentesque fringilla, orci nec fringilla finibus, turpis lacus vehicula elit, nec bibendum magna est quis massa. Aliquam efficitur facilisis nibh, ut sodales sapien scelerisque nec. Integer justo sem, pellentesque et ante imperdiet, interdum placerat sem.</p>
<p class="paragraph">Nunc hendrerit lobortis commodo. Morbi felis quam, fermentum vitae libero vitae, fermentum sodales quam. Nulla bibendum tellus quis lorem sollicitudin pretium. Etiam commodo ex eget aliquet porta. In sit amet dui eleifend, mattis sem nec, tristique erat. Morbi malesuada fringilla bibendum. Integer odio ex, cursus a sodales quis, vehicula non dolor.</p>
<p class="paragraph">Praesent vitae pharetra felis. Curabitur non ex non nunc pretium feugiat eu sit amet turpis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean blandit ante leo. Vivamus iaculis mi vel sem tincidunt maximus. Aenean elementum ipsum non laoreet semper. Morbi non felis interdum lectus pulvinar mollis id non purus. Nullam eu ipsum ut turpis aliquam feugiat at non tellus. Suspendisse ornare erat quis enim ullamcorper, at rhoncus nulla suscipit.
</p>
<div class="img_container"><img class="img" src="test.png"></img></div>
</div>
<div class="footer">
<h4>Example Site Footer</h4>
<a href="#">Test Link 1</a>
<a href="#">Test Link 2</a>
<a href="#">Test Link 3</a>
</div>
</body>
</html>
@@ -1,38 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"><meta name="author" content="Ryan Fleury">
<meta property="og:title" content="Blog">
<meta name="twitter:title" content="Blog">
<link rel="canonical" href="https://example.site">
<meta property="og:type" content="website">
<meta property="og:url" content="https://example.site">
<meta property="og:site_name" content="Example Site">
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@ryanjfleury">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="site.js"></script>
<title>Blog | Example Site</title>
</head>
<body>
<div class="header">
<h1>Example Site</h1>
<a href="#">Test Link 1</a>
<a href="#">Test Link 2</a>
<a href="#">Test Link 3</a>
</div>
<div class="page_content">
<h1 class="title">Blog</h1><input autofocus id="lister_search_0" class="lister_search" oninput="SearchInput(event, 0)" onkeydown="SearchKeyDown(event, 0)" placeholder="Filter..."></input><ul id="lister_0" class="lister">
</ul>
</div>
<div class="footer">
<h4>Example Site Footer</h4>
<a href="#">Test Link 1</a>
<a href="#">Test Link 2</a>
<a href="#">Test Link 3</a>
</div>
</body>
</html>
@@ -1,61 +0,0 @@
function StringFitsFilter(str, filter)
{
let match = true;
let filter_upper = filter.toUpperCase();
let filter_substrings = filter_upper.split(/[ _*]+/);
let str_upper = str.toUpperCase();
let minimum_index = 0;
for(let i = 0; i < filter_substrings.length; ++i)
{
if(filter_substrings[i].length > 0)
{
let index_of_substring = str_upper.indexOf(filter_substrings[i], minimum_index);
if(index_of_substring < 0 || index_of_substring < minimum_index)
{
match = false;
break;
}
minimum_index = index_of_substring + filter_substrings[i].length - 1;
}
}
return match;
}
function UpdateListByFilter(menu_id, filter_id)
{
let ul = document.getElementById(menu_id);
let li = ul.getElementsByTagName("li");
let input = document.getElementById(filter_id);
let filter = input.value.toUpperCase();
for(let i = 0; i < li.length; i++)
{
if(filter.length > 0)
{
let a = li[i].getElementsByTagName("a")[0];
if(StringFitsFilter(a.innerHTML, filter))
{
li[i].style.display = "";
}
else
{
li[i].style.display = "none";
}
}
else
{
li[i].style.display = "";
}
}
}
function SearchInput(event, lister_idx)
{
UpdateListByFilter("lister_"+lister_idx, "lister_search_"+lister_idx);
}
function SearchKeyDown(event, lister_idx)
{
UpdateListByFilter("lister_"+lister_idx, "lister_search_"+lister_idx);
}
@@ -1,6 +0,0 @@
*
{
padding: 0;
margins: 0;
}
@@ -1,61 +0,0 @@
function StringFitsFilter(str, filter)
{
let match = true;
let filter_upper = filter.toUpperCase();
let filter_substrings = filter_upper.split(/[ _*]+/);
let str_upper = str.toUpperCase();
let minimum_index = 0;
for(let i = 0; i < filter_substrings.length; ++i)
{
if(filter_substrings[i].length > 0)
{
let index_of_substring = str_upper.indexOf(filter_substrings[i], minimum_index);
if(index_of_substring < 0 || index_of_substring < minimum_index)
{
match = false;
break;
}
minimum_index = index_of_substring + filter_substrings[i].length - 1;
}
}
return match;
}
function UpdateListByFilter(menu_id, filter_id)
{
let ul = document.getElementById(menu_id);
let li = ul.getElementsByTagName("li");
let input = document.getElementById(filter_id);
let filter = input.value.toUpperCase();
for(let i = 0; i < li.length; i++)
{
if(filter.length > 0)
{
let a = li[i].getElementsByTagName("a")[0];
if(StringFitsFilter(a.innerHTML, filter))
{
li[i].style.display = "";
}
else
{
li[i].style.display = "none";
}
}
else
{
li[i].style.display = "";
}
}
}
function SearchInput(event, lister_idx)
{
UpdateListByFilter("lister_"+lister_idx, "lister_search_"+lister_idx);
}
function SearchKeyDown(event, lister_idx)
{
UpdateListByFilter("lister_"+lister_idx, "lister_search_"+lister_idx);
}
@@ -1,34 +0,0 @@
title: "Example Site"
desc: "My example site, used to demonstrate the static site generator example for Data Desk."
canonical_url: "https://example.site"
author: "Ryan Fleury"
twitter_handle: "@ryanjfleury"
header:
"""
<div class="header">
<h1>Example Site</h1>
<a href="#">Test Link 1</a>
<a href="#">Test Link 2</a>
<a href="#">Test Link 3</a>
</div>
"""
footer:
"""
<div class="footer">
<h4>Example Site Footer</h4>
<a href="#">Test Link 1</a>
<a href="#">Test Link 2</a>
<a href="#">Test Link 3</a>
</div>
"""
style:
"""
*
{
padding: 0;
margins: 0;
}
"""
@@ -1,594 +0,0 @@
#include "md.h"
#include "md.c"
typedef struct SiteInfo SiteInfo;
struct SiteInfo
{
MD_Node *title;
MD_Node *desc;
MD_Node *canonical_url;
MD_Node *author;
MD_Node *twitter_handle;
MD_Node *link_dictionary;
MD_Node *header;
MD_Node *footer;
MD_Node *style;
};
typedef struct PageInfo PageInfo;
struct PageInfo
{
MD_Node *title;
MD_Node *desc;
MD_Node *date;
MD_Node *parent;
MD_Node *header_image;
};
static PageInfo ParsePageInfo(MD_Node *page);
static SiteInfo ParseSiteInfo(MD_Node *site);
static MD_String8 MakeDateString(MD_Node *date);
static void GeneratePageContent(MD_Map *index_table, SiteInfo *site_info, PageInfo *page_info, FILE *file, MD_Node *node);
static MD_Arena *arena = 0;
int main(int argument_count, char **arguments)
{
arena = MD_ArenaAlloc(1ull << 40);
//~ NOTE(rjf): Parse command line arguments.
MD_String8List arg_list = MD_StringListFromArgCV(arena, argument_count, arguments);
MD_CmdLine cmdln = MD_MakeCmdLineFromOptions(arena, arg_list);
MD_String8List siteinfo_values = MD_CmdLineValuesFromString(cmdln, MD_S8Lit("siteinfo"));
MD_String8 site_info_path = MD_S8ListJoin(arena, siteinfo_values, 0);
MD_String8List pagedir_values = MD_CmdLineValuesFromString(cmdln, MD_S8Lit("pagedir"));
MD_String8 page_dir_path = MD_S8ListJoin(arena, pagedir_values, 0);
if(!MD_CmdLineB32FromString(cmdln, MD_S8Lit("siteinfo")) ||
!MD_CmdLineB32FromString(cmdln, MD_S8Lit("pagedir")))
{
fprintf(stderr, "USAGE: %s --siteinfo <path to site info file> --pagedir <path to directory with pages> ...\n", arguments[0]);
goto end;
}
//~ NOTE(rjf): Load JS.
MD_String8 js_path = MD_S8Fmt(arena, "%.*s/site.js", MD_S8VArg(page_dir_path));
MD_String8 js_string = MD_LoadEntireFile(arena, js_path);
//~ NOTE(rjf): Parse site info.
SiteInfo site_info = {0};
{
printf("Parsing site metadata at \"%.*s\"...\n", MD_S8VArg(site_info_path));
MD_Node *site_info_file = MD_ParseWholeFile(arena, site_info_path).node;
site_info = ParseSiteInfo(site_info_file);
}
//~ NOTE(rjf): Parse pages.
MD_Node *root_list = MD_MakeList(arena);
{
printf("Searching for site pages at \"%.*s\"...\n", MD_S8VArg(page_dir_path));
MD_FileIter it = {0};
if (MD_FileIterBegin(&it, page_dir_path))
{
for(;;)
{
MD_FileInfo file_info = MD_FileIterNext(arena, &it);
if (file_info.filename.size == 0)
{
break;
}
if(MD_S8Match(MD_PathSkipLastPeriod(file_info.filename), MD_S8Lit("md"), MD_StringMatchFlag_CaseInsensitive) &&
!MD_S8Match(MD_PathSkipLastSlash(MD_PathChopLastPeriod(file_info.filename)),
MD_PathSkipLastSlash(MD_PathChopLastPeriod(site_info_path)),
MD_StringMatchFlag_CaseInsensitive |
MD_StringMatchFlag_SlashInsensitive))
{
printf("Processing site page at \"%.*s\"...\n", MD_S8VArg(file_info.filename));
MD_String8 folder = MD_PathChopLastSlash(page_dir_path);
MD_String8 path = MD_S8Fmt(arena, "%.*s/%.*s",
MD_S8VArg(folder), MD_S8VArg(file_info.filename));
MD_Node *node = MD_ParseWholeFile(arena, path).node;
MD_PushNewReference(arena, root_list, node);
}
}
MD_FileIterEnd(&it);
}
}
//~ NOTE(rjf): Generate index table.
MD_Map index_table = {0};
{
for(MD_EachNode(ref, root_list->first_child))
{
MD_Node *root = MD_NodeFromReference(ref);
for(MD_EachNode(node, root->first_child))
{
if(!MD_NodeIsNil(node->first_child) && MD_S8Match(node->string, MD_S8Lit("index"), MD_StringMatchFlag_CaseInsensitive))
{
for(MD_EachNode(index_string, node->first_child))
{
MD_MapInsert(arena, &index_table, MD_MapKeyStr(index_string->string), root);
}
goto end_index_build;
}
}
end_index_build:;
}
}
//~ NOTE(rjf): Generate stylesheet.
if(site_info.style)
{
FILE *file = fopen("style.css", "wb");
if(file)
{
fprintf(file, "%.*s", MD_S8VArg(site_info.style->string));
fclose(file);
}
}
//~ NOTE(rjf): Generate JS.
{
FILE *file = fopen("site.js", "wb");
if(file)
{
fprintf(file, "%.*s", MD_S8VArg(js_string));
fclose(file);
}
}
//~ NOTE(rjf): Generate files for all roots.
for(MD_EachNode(ref, root_list->first_child))
{
MD_Node *root = MD_NodeFromReference(ref);
PageInfo page_info = ParsePageInfo(root);
MD_String8 name_without_extension = MD_PathSkipLastSlash(MD_PathChopLastPeriod(root->string));
MD_String8 file_name = MD_S8Fmt(arena, "%.*s.html", MD_S8VArg(name_without_extension));
FILE *file = fopen(file_name.str, "wb");
if(file)
{
fprintf(file, "<!DOCTYPE html>\n");
fprintf(file, "<html lang=\"en\">\n");
MD_String8 site_title = !MD_NodeIsNil(site_info.title) ? site_info.title->string : MD_S8Lit("");
MD_String8 title = !MD_NodeIsNil(page_info.title) ? page_info.title->string : MD_S8Lit("");
MD_String8 url = !MD_NodeIsNil(site_info.canonical_url) ? site_info.canonical_url->string : MD_S8Lit("");
MD_String8 author = !MD_NodeIsNil(site_info.author) ? site_info.author->string : MD_S8Lit("");
MD_String8 twitter_handle = !MD_NodeIsNil(site_info.twitter_handle) ? site_info.twitter_handle->string : MD_S8Lit("");
// NOTE(rjf): Generate heading.
{
fprintf(file, "<head>\n");
fprintf(file, "<meta charset=\"utf-8\">\n");
fprintf(file, "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><meta name=\"author\" content=\"%.*s\">\n", MD_S8VArg(author));
fprintf(file, "<meta property=\"og:title\" content=\"%.*s\">\n", MD_S8VArg(title));
fprintf(file, "<meta name=\"twitter:title\" content=\"%.*s\">\n", MD_S8VArg(title));
fprintf(file, "<link rel=\"canonical\" href=\"%.*s\">\n", MD_S8VArg(url));
fprintf(file, "<meta property=\"og:type\" content=\"website\">\n");
fprintf(file, "<meta property=\"og:url\" content=\"%.*s\">\n", MD_S8VArg(url));
fprintf(file, "<meta property=\"og:site_name\" content=\"%.*s\">\n", MD_S8VArg(site_title));
fprintf(file, "<meta name=\"twitter:card\" content=\"summary\">\n");
fprintf(file, "<meta name=\"twitter:site\" content=\"%.*s\">\n", MD_S8VArg(twitter_handle));
fprintf(file, "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n");
fprintf(file, "<script src=\"site.js\"></script>\n");
if(title.size > 0)
{
if(site_title.size > 0)
{
fprintf(file, "<title>%.*s | %.*s</title>\n", MD_S8VArg(title), MD_S8VArg(site_title));
}
else
{
fprintf(file, "<title>%.*s</title>\n", MD_S8VArg(title));
}
}
else if(site_title.size > 0)
{
fprintf(file, "<title>%.*s</title>\n", MD_S8VArg(site_title));
}
fprintf(file, "</head>\n");
}
// NOTE(rjf): Generate body.
{
fprintf(file, "<body>\n");
// NOTE(rjf): Generate header.
if(site_info.header)
{
fprintf(file, "%.*s", MD_S8VArg(site_info.header->string));
}
fprintf(file, "<div class=\"page_content\">\n");
// NOTE(rjf): Parent page back button.
if(page_info.parent)
{
fprintf(file, "<div class=\"standalone_link_container\"><a class=\"link\" href=\"%.*s.html\">← Back</a></div>", MD_S8VArg(page_info.parent->string));
}
// NOTE(rjf): Banner.
if(page_info.header_image)
{
fprintf(file, "<div class=\"page_banner\" style=\"background-image: url('%.*s');\"></div>",
MD_S8VArg(page_info.header_image->string));
}
// NOTE(rjf): Title.
if(title.size > 0)
{
fprintf(file, "<h1 class=\"title\">%.*s</h1>", MD_S8VArg(title));
}
// NOTE(rjf): Main description/subtitle.
if(page_info.desc)
{
fprintf(file, "<h2 class=\"subtitle\">%.*s</h2>", MD_S8VArg(page_info.desc->string));
}
// NOTE(rjf): Date.
if(page_info.date)
{
MD_String8 date_string = MakeDateString(page_info.date);
if(date_string.size > 0)
{
fprintf(file, "<h3 class=\"date\">%.*s</h3>", MD_S8VArg(date_string));
}
}
// NOTE(rjf): The rest of the page content should be generated from the page nodes.
for(MD_EachNode(node, root->first_child))
{
GeneratePageContent(&index_table, &site_info, &page_info, file, node);
}
fprintf(file, "</div>\n");
// NOTE(rjf): Generate footer.
if(site_info.footer)
{
fprintf(file, "%.*s", MD_S8VArg(site_info.footer->string));
}
fprintf(file, "</body>\n");
}
fprintf(file, "</html>\n");
fclose(file);
}
}
end:;
return 0;
}
static PageInfo
ParsePageInfo(MD_Node *page)
{
PageInfo info = {0};
for(MD_EachNode(node, page->first_child))
{
if(!MD_NodeIsNil(node->first_child))
{
if(MD_S8Match(node->string, MD_S8Lit("title"), MD_StringMatchFlag_CaseInsensitive))
{
info.title = node->first_child;
}
else if(MD_S8Match(node->string, MD_S8Lit("desc"), MD_StringMatchFlag_CaseInsensitive))
{
info.desc = node->first_child;
}
else if(MD_S8Match(node->string, MD_S8Lit("date"), MD_StringMatchFlag_CaseInsensitive))
{
info.date = node;
}
else if(MD_S8Match(node->string, MD_S8Lit("parent"), MD_StringMatchFlag_CaseInsensitive))
{
info.parent = node->first_child;
}
else if(MD_S8Match(node->string, MD_S8Lit("header_image"), MD_StringMatchFlag_CaseInsensitive))
{
info.header_image = node->first_child;
}
}
}
return info;
}
static SiteInfo
ParseSiteInfo(MD_Node *site)
{
SiteInfo info = {0};
for(MD_EachNode(node, site->first_child))
{
if(!MD_NodeIsNil(node->first_child))
{
if(MD_S8Match(node->string, MD_S8Lit("title"), MD_StringMatchFlag_CaseInsensitive))
{
info.title = node->first_child;
}
else if(MD_S8Match(node->string, MD_S8Lit("desc"), MD_StringMatchFlag_CaseInsensitive))
{
info.desc = node->first_child;
}
else if(MD_S8Match(node->string, MD_S8Lit("canonical_url"), MD_StringMatchFlag_CaseInsensitive))
{
info.canonical_url = node->first_child;
}
else if(MD_S8Match(node->string, MD_S8Lit("author"), MD_StringMatchFlag_CaseInsensitive))
{
info.author = node->first_child;
}
else if(MD_S8Match(node->string, MD_S8Lit("twitter_handle"), MD_StringMatchFlag_CaseInsensitive))
{
info.twitter_handle = node->first_child;
}
else if(MD_S8Match(node->string, MD_S8Lit("link_dictionary"), MD_StringMatchFlag_CaseInsensitive))
{
info.link_dictionary = node;
}
else if(MD_S8Match(node->string, MD_S8Lit("header"), MD_StringMatchFlag_CaseInsensitive))
{
info.header = node->first_child;
}
else if(MD_S8Match(node->string, MD_S8Lit("footer"), MD_StringMatchFlag_CaseInsensitive))
{
info.footer = node->first_child;
}
else if(MD_S8Match(node->string, MD_S8Lit("style"), MD_StringMatchFlag_CaseInsensitive))
{
info.style = node->first_child;
}
}
}
return info;
}
static MD_String8
MakeDateString(MD_Node *date)
{
MD_String8 result = {0};
if(date)
{
MD_Node *year = 0;
MD_Node *month = 0;
MD_Node *day = 0;
for(MD_EachNode(child, date->first_child))
{
if(child->flags & MD_NodeFlag_Numeric)
{
if (year == 0) year = child;
else if (month == 0) month = child;
else if (day == 0) day = child;
else
{
break;
}
}
}
if(!MD_NodeIsNil(year) && !MD_NodeIsNil(month) && !MD_NodeIsNil(day))
{
char *month_names[] =
{
"January", "February", "March", "April", "May", "June", "July", "August",
"September", "October", "November", "December",
};
MD_u64 month_idx = MD_U64FromString(month->string, 10) - 1;
if(month_idx >= 0 && month_idx < sizeof(month_names)/sizeof(month_names[0]))
{
result = MD_S8Fmt(arena, "%.*s %s %.*s",
MD_S8VArg(day->string),
month_names[month_idx],
MD_S8VArg(year->string));
}
}
}
return result;
}
static void
GeneratePageContent(MD_Map *index_table, SiteInfo *site_info, PageInfo *page_info, FILE *file, MD_Node *node)
{
//~ NOTE(rjf): Text blobs
if(MD_NodeIsNil(node->first_child) && (node->flags & MD_NodeFlag_StringLiteral))
{
char *html_tag = "p";
char *style = "paragraph";
if(MD_NodeHasTag(node, MD_S8Lit("title"), 0))
{
html_tag = "h1";
style = "title";
}
else if(MD_NodeHasTag(node, MD_S8Lit("subtitle"), 0))
{
html_tag = "h2";
style = "subtitle";
}
else if(MD_NodeHasTag(node, MD_S8Lit("code"), 0))
{
html_tag = "pre";
style = "code";
}
MD_String8 splits[] =
{
MD_S8Lit("\n\n"),
};
MD_String8List strlist = MD_S8Split(arena, node->string, sizeof(splits)/sizeof(splits[0]),
splits);
for(MD_String8Node *strnode = strlist.first; strnode; strnode = strnode->next)
{
fprintf(file, "<%s class=\"%s\">", html_tag, style);
for(MD_u64 i = 0; i < strnode->string.size; i += 1)
{
if(strnode->string.str[i] == '@')
{
MD_String8 string_tail = MD_S8Skip(strnode->string, i);
MD_ParseResult parse = MD_ParseOneNode(arena, string_tail, 0);
if(!MD_NodeIsNil(parse.node))
{
if(MD_NodeHasTag(node, MD_S8Lit("i"), 0))
{
fprintf(file, "<i>%.*s</i>", MD_S8VArg(parse.node->string));
}
else if(MD_NodeHasTag(node, MD_S8Lit("b"), 0))
{
fprintf(file, "<strong>%.*s</strong>", MD_S8VArg(parse.node->string));
}
else if(MD_NodeHasTag(node, MD_S8Lit("code"), 0))
{
fprintf(file, "<span class=\"inline_code\">%.*s</span>", MD_S8VArg(parse.node->string));
}
else if(MD_NodeHasTag(node, MD_S8Lit("link"), 0))
{
MD_Node *text = MD_ChildFromIndex(parse.node, 0);
MD_Node *link = MD_ChildFromIndex(parse.node, 1);
fprintf(file, "<a class=\"link\" href=\"%.*s\">%.*s</a>",
MD_S8VArg(link->string),
MD_S8VArg(text->string));
}
}
i += parse.string_advance - 1;
}
else
{
MD_b32 dict_word = 0;
if(site_info->link_dictionary)
{
MD_Node *text = MD_NilNode();
MD_Node *link = MD_NilNode();
for(MD_EachNode(dict_link, site_info->link_dictionary->first_child))
{
text = MD_ChildFromIndex(dict_link, 0);
link = MD_ChildFromIndex(dict_link, 1);
MD_String8 substring = MD_S8Substring(strnode->string, i, i+text->string.size);
if(MD_S8Match(substring, text->string, 0))
{
fprintf(file, "<a class=\"link\" href=\"%.*s\">%.*s</a>",
MD_S8VArg(link->string),
MD_S8VArg(text->string));
dict_word = 1;
i += text->string.size-1;
break;
}
}
}
if(!dict_word)
{
fprintf(file, "%c", strnode->string.str[i]);
}
}
}
fprintf(file, "</%s>\n", html_tag);
}
}
if(!MD_NodeIsNil(node->first_child))
{
if(MD_NodeHasTag(node, MD_S8Lit("list"), 0))
{
fprintf(file, "<ul class=\"list\">\n");
for(MD_EachNode(child, node->first_child))
{
if(MD_NodeIsNil(child->first_child))
{
fprintf(file, "<li class=\"list_item\">\n");
}
GeneratePageContent(index_table, site_info, page_info, file, child);
if(MD_NodeIsNil(child->first_child))
{
fprintf(file, "</li>\n");
}
}
fprintf(file, "</ul>\n");
}
else if(MD_NodeHasTag(node, MD_S8Lit("img"), 0))
{
MD_Node *src = MD_ChildFromIndex(node, 0);
MD_Node *alt = MD_ChildFromIndex(node, 1);
fprintf(file, "<div class=\"img_container\"><img class=\"img\" src=\"%.*s\"></img></div>\n", MD_S8VArg(src->string));
}
else if(MD_NodeHasTag(node, MD_S8Lit("youtube"), 0))
{
MD_Node *id = MD_ChildFromIndex(node, 0);
fprintf(file, "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/%.*s\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n",
MD_S8VArg(id->string));
}
else if(MD_NodeHasTag(node, MD_S8Lit("lister"), 0))
{
static int lister_idx = 0;
fprintf(file, "<input autofocus id=\"lister_search_%i\" class=\"lister_search\" oninput=\"SearchInput(event, %i)\" onkeydown=\"SearchKeyDown(event, %i)\" placeholder=\"Filter...\"></input>", lister_idx, lister_idx, lister_idx);
fprintf(file, "<ul id=\"lister_%i\" class=\"lister\">\n", lister_idx);
lister_idx += 1;
MD_Node *index_string = 0;
for(MD_u64 idx = 0; !MD_NodeIsNil(index_string = MD_ChildFromIndex(node, idx)); idx += 1)
{
for(MD_MapSlot *slot = MD_MapLookup(index_table, MD_MapKeyStr(index_string->string));
slot; slot = slot->next)
{
if(slot->val)
{
MD_Node *node = slot->val;
MD_Node *root = MD_RootFromNode(node);
PageInfo info = ParsePageInfo(node);
MD_String8 filename = root->string;
MD_String8 filename_no_ext = MD_PathChopLastPeriod(MD_PathSkipLastSlash(filename));
MD_String8 link = MD_S8Fmt(arena, "%.*s.html", MD_S8VArg(filename_no_ext));
MD_String8 name = info.title->string;
MD_String8 date = MakeDateString(info.date);
fprintf(file, "<a class=\"lister_item_link\" href=\"%.*s\">\n", MD_S8VArg(link));
fprintf(file, "<li class=\"lister_item\">\n");
if(info.header_image)
{
fprintf(file, "<div class=\"lister_item_img\" style=\"background-image:url('%.*s');\">",
MD_S8VArg(info.header_image->string));
}
fprintf(file, "<div class=\"lister_item_text\">\n");
fprintf(file, "<div class=\"lister_item_title\">\n");
fprintf(file, "%.*s\n", MD_S8VArg(name));
fprintf(file, "</div>\n");
if(date.size > 0)
{
fprintf(file, "<div class=\"lister_item_date\">\n");
fprintf(file, "%.*s\n", MD_S8VArg(date));
fprintf(file, "</div>\n");
}
if(info.desc)
{
fprintf(file, "<div class=\"lister_item_desc\">\n");
fprintf(file, "%.*s\n", MD_S8VArg(info.desc->string));
fprintf(file, "</div>\n");
}
if(info.header_image)
{
fprintf(file, "</div>\n");
}
fprintf(file, "</div>\n");
fprintf(file, "</a>\n");
fprintf(file, "</li>\n");
}
}
}
fprintf(file, "</ul>\n");
}
}
}
-10
View File
@@ -1,10 +0,0 @@
@proc foo:(x, y, z)
{
(x + y) * z
}
@proc main:()
{
foo(10, 20, 30);
}
-252
View File
@@ -1,252 +0,0 @@
#include "md.h"
#include "md_c_helpers.h"
#include "md.c"
#include "md_c_helpers.c"
typedef struct NamespaceNode NamespaceNode;
struct NamespaceNode
{
NamespaceNode *parent;
MD_Map symbol_map;
};
typedef enum ValueKind
{
ValueKind_Null,
ValueKind_Number,
ValueKind_Procedure,
}
ValueKind;
typedef struct Value Value;
struct Value
{
ValueKind kind;
MD_f64 number;
MD_Node *node;
};
static MD_Arena *arena = 0;
static Value
MakeValue_Number(MD_f64 v)
{
Value value = {0};
value.kind = ValueKind_Number;
value.number = v;
return value;
}
static Value
MakeValue_Procedure(MD_Node *node)
{
Value value = {0};
value.kind = ValueKind_Procedure;
value.node = node;
return value;
}
static void
InsertValueToNamespace(NamespaceNode *ns, MD_String8 string, Value v)
{
Value *v_store = malloc(sizeof(*v_store));
*v_store = v;
MD_MapInsert(arena, &ns->symbol_map, MD_MapKeyStr(string), v_store);
}
static Value
ValueFromString(NamespaceNode *ns, MD_String8 string)
{
Value v = {0};
for(NamespaceNode *n = ns; n; n = n->parent)
{
MD_MapSlot *slot = MD_MapLookup(&n->symbol_map, MD_MapKeyStr(string));
if(slot && slot->val)
{
v = *(Value *)slot->val;
break;
}
}
return v;
}
static Value EvaluateScope(NamespaceNode *ns, MD_Node *code);
static Value EvaluateExpr(NamespaceNode *ns, MD_C_Expr *expr);
static Value
EvaluateExpr(NamespaceNode *ns, MD_C_Expr *expr)
{
Value result = {0};
switch(expr->kind)
{
#define BinaryOp(name, op) \
case MD_C_ExprKind_##name:\
{\
Value left = EvaluateExpr(ns, expr->sub[0]);\
Value right = EvaluateExpr(ns, expr->sub[1]);\
result = MakeValue_Number(left.number op right.number);\
}break
BinaryOp(Add, +);
BinaryOp(Subtract, -);
BinaryOp(Multiply, *);
BinaryOp(Divide, /);
#undef BinaryOp
case MD_C_ExprKind_Call:
{
MD_Node *call = expr->node;
Value callee = ValueFromString(ns, expr->sub[0]->node->string);
if(!MD_NodeIsNil(callee.node))
{
//- rjf: find top-level namespace
NamespaceNode *top_level_ns = ns;
for(NamespaceNode *n = ns; n; n = n->parent)
{
top_level_ns = n;
}
//- rjf: build namespace for function
NamespaceNode args_ns = {0};
MD_Node *param = callee.node->first_child;
for(MD_Node *arg_first = call->first_child; !MD_NodeIsNil(arg_first); param = param->next)
{
#if 0
MD_Node *arg_last = MD_SeekNodeWithFlags(arg_first, MD_NodeFlag_IsAfterComma|MD_NodeFlag_IsAfterSemicolon);
MD_C_Expr *expr = MD_C_ParseAsExpr(arg_first, arg_last);
InsertValueToNamespace(&args_ns, param->string, EvaluateExpr(ns, expr));
arg_first = arg_last->next;
#endif
}
args_ns.parent = top_level_ns;
result = EvaluateScope(&args_ns, callee.node->next);
}
}break;
case MD_C_ExprKind_Atom:
{
if(expr->node->flags & MD_NodeFlag_Identifier)
{
result = ValueFromString(ns, expr->node->string);
}
else if(expr->node->flags & MD_NodeFlag_Numeric)
{
result = MakeValue_Number(MD_F64FromString(expr->node->string));
}
}break;
default: break;
}
return result;
}
static Value
EvaluateScope(NamespaceNode *ns, MD_Node *code)
{
Value result = {0};
NamespaceNode local_namespace = {0};
local_namespace.parent = ns;
// TODO(rjf): fix this, using last instead of opl
for(MD_Node *first = code->first_child; !MD_NodeIsNil(first);)
{
MD_Node *opl = MD_NodeFromFlags(first->next, MD_NilNode(), MD_NodeFlag_IsAfterSemicolon|MD_NodeFlag_IsAfterComma);
//- rjf: declaration
if(first->next == opl && first->string.size != 0 && !MD_NodeIsNil(first->first_child))
{
MD_C_Expr *expr = MD_C_ParseAsExpr(arena, first->first_child, first->last_child);
InsertValueToNamespace(&local_namespace, first->string, EvaluateExpr(&local_namespace, expr));
}
//- rjf: expr
else
{
MD_C_Expr *expr = MD_C_ParseAsExpr(arena, first, opl);
if(!MD_C_ExprIsNil(expr))
{
result = EvaluateExpr(&local_namespace, expr);
}
}
//- rjf: bump
first = opl;
}
return result;
}
int main(int argument_count, char **arguments)
{
arena = MD_ArenaAlloc(1ull << 40);
//- rjf: parse command line
MD_String8List arg_list = MD_StringListFromArgCV(arena, argument_count, arguments);
MD_CmdLine cmdln = MD_MakeCmdLineFromOptions(arena, arg_list);
//- rjf: parse all input files
MD_Node *file_list = MD_MakeList(arena);
for(MD_String8Node *n = cmdln.inputs.first; n; n = n->next)
{
MD_ParseResult parse = MD_ParseWholeFile(arena, n->string);
MD_PushNewReference(arena, file_list, parse.node);
}
//- rjf: gather top-level symbol map
NamespaceNode global_ns_node = {0};
for(MD_EachNode(file_ref, file_list->first_child))
{
MD_Node *file = MD_NodeFromReference(file_ref);
for(MD_EachNode(top_level, file->first_child))
{
if(MD_NodeHasTag(top_level, MD_S8Lit("proc"), 0))
{
InsertValueToNamespace(&global_ns_node, top_level->string, MakeValue_Procedure(top_level));
}
}
}
//- rjf: find `main` procedure
Value main_proc = ValueFromString(&global_ns_node, MD_S8Lit("main"));
MD_Node *main_code = main_proc.node->next;
if(MD_NodeIsNil(main_proc.node))
{
fprintf(stderr, "no `main` procedure found");
goto end;
}
//- rjf: validate that we got `main` code
if(MD_NodeIsNil(main_code))
{
fprintf(stderr, "`main` requires an implementation");
goto end;
}
//- rjf: start interpreting at `main`
Value result = EvaluateScope(&global_ns_node, main_code);
switch(result.kind)
{
default:
case ValueKind_Null:
{
printf("[null]\n");
}break;
case ValueKind_Number:
{
printf("[number] %f\n", result.number);
}break;
case ValueKind_Procedure:
{
printf("[proc] %.*s\n", MD_S8VArg(result.node->string));
}break;
}
end:;
return 0;
}
+2
View File
@@ -1,5 +1,7 @@
/* date = April 16th 2021 6:05 pm */
#error foo
#ifndef MD_C_HELPERS_H
#define MD_C_HELPERS_H
-119
View File
@@ -1,10 +1,7 @@
//$ exe //
#include "md.h"
#include "md_c_helpers.h"
#include "md.c"
#include "md_c_helpers.c"
MD_Arena *arena = 0;
@@ -72,25 +69,6 @@ MakeTestNode(MD_NodeKind kind, MD_String8 string)
return MD_MakeNode(arena, kind, string, string, 0);
}
static MD_C_Expr *
AtomExpr(char *str)
{
return MD_C_MakeExpr(arena, MakeTestNode(MD_NodeKind_Main, MD_S8CString(str)),
MD_C_ExprKind_Atom, MD_C_NilExpr(), MD_C_NilExpr());
}
static MD_C_Expr *
BinOpExpr(MD_C_ExprKind kind, MD_C_Expr *left, MD_C_Expr *right)
{
return MD_C_MakeExpr(arena, MD_NilNode(), kind, left, right);
}
static MD_C_Expr *
TypeExpr(MD_C_ExprKind kind, MD_C_Expr *sub)
{
return MD_C_MakeExpr(arena, MD_NilNode(), kind, sub, MD_C_NilExpr());
}
static MD_b32
MatchParsedWithNode(MD_String8 string, MD_Node *tree)
{
@@ -98,22 +76,6 @@ MatchParsedWithNode(MD_String8 string, MD_Node *tree)
return MD_NodeDeepMatch(tree, parse.node, MD_NodeMatchFlag_Tags | MD_NodeMatchFlag_TagArguments);
}
static MD_b32
MatchParsedWithExpr(MD_String8 string, MD_C_Expr *expr)
{
MD_ParseResult parse = MD_ParseOneNode(arena, string, 0);
MD_C_Expr *parse_expr = MD_C_ParseAsExpr(arena, parse.node->first_child, parse.node->last_child);
return MD_C_ExprDeepMatch(expr, parse_expr, 0);
}
static MD_b32
MatchParsedWithType(MD_String8 string, MD_C_Expr *expr)
{
MD_ParseResult parse = MD_ParseOneNode(arena, string, 0);
MD_C_Expr *parse_expr = MD_C_ParseAsType(arena, parse.node->first_child, parse.node->last_child);
return MD_C_ExprDeepMatch(expr, parse_expr, 0);
}
static MD_b32
TokenMatch(MD_Token token, MD_String8 string, MD_TokenKind kind)
{
@@ -334,87 +296,6 @@ int main(void)
}
}
Test("Expression Evaluation")
{
// NOTE(rjf): 5 + 3
{
MD_C_Expr *expr = BinOpExpr(MD_C_ExprKind_Add, AtomExpr("5"), AtomExpr("3"));
TestResult(MD_C_EvaluateExpr_I64(expr) == 8);
}
// NOTE(rjf): 5 - 3
{
MD_C_Expr *expr = BinOpExpr(MD_C_ExprKind_Subtract, AtomExpr("5"), AtomExpr("3"));
TestResult(MD_C_EvaluateExpr_I64(expr) == 2);
}
// NOTE(rjf): 5 * 3
{
MD_C_Expr *expr = BinOpExpr(MD_C_ExprKind_Multiply, AtomExpr("5"), AtomExpr("3"));
TestResult(MD_C_EvaluateExpr_I64(expr) == 15);
}
// NOTE(rjf): 10 / 2
{
MD_C_Expr *expr = BinOpExpr(MD_C_ExprKind_Divide, AtomExpr("10"), AtomExpr("2"));
TestResult(MD_C_EvaluateExpr_I64(expr) == 5);
}
// NOTE(rjf): (3 + 4) * (2 + 6)
{
MD_C_Expr *left = BinOpExpr(MD_C_ExprKind_Add, AtomExpr("3"), AtomExpr("4"));
MD_C_Expr *right = BinOpExpr(MD_C_ExprKind_Add, AtomExpr("2"), AtomExpr("6"));
MD_C_Expr *expr = BinOpExpr(MD_C_ExprKind_Multiply, left, right);
TestResult(MD_C_EvaluateExpr_I64(expr) == 56);
}
}
Test("Expression Parsing")
{
{
MD_String8 string = MD_S8Lit("(1 + 2)");
MD_C_Expr *expr = BinOpExpr(MD_C_ExprKind_Add, AtomExpr("1"), AtomExpr("2"));
TestResult(MatchParsedWithExpr(string, expr));
}
{
MD_String8 string = MD_S8Lit("((3 + 4) * (2 + 6))");
MD_C_Expr *left = BinOpExpr(MD_C_ExprKind_Add, AtomExpr("3"), AtomExpr("4"));
MD_C_Expr *right = BinOpExpr(MD_C_ExprKind_Add, AtomExpr("2"), AtomExpr("6"));
MD_C_Expr *expr = BinOpExpr(MD_C_ExprKind_Multiply, left, right);
TestResult(MatchParsedWithExpr(string, expr));
}
{
MD_String8 string = MD_S8Lit("(1*2+3)");
MD_C_Expr *left = BinOpExpr(MD_C_ExprKind_Multiply, AtomExpr("1"), AtomExpr("2"));
MD_C_Expr *expr = BinOpExpr(MD_C_ExprKind_Add, left, AtomExpr("3"));
TestResult(MatchParsedWithExpr(string, expr));
}
}
Test("Type Parsing")
{
{
MD_String8 string = MD_S8Lit("(i32)");
MD_C_Expr *expr = AtomExpr("i32");
TestResult(MatchParsedWithType(string, expr));
}
{
MD_String8 string = MD_S8Lit("(*i32)");
MD_C_Expr *expr = TypeExpr(MD_C_ExprKind_Pointer, AtomExpr("i32"));
TestResult(MatchParsedWithType(string, expr));
}
{
MD_String8 string = MD_S8Lit("(**i32)");
MD_C_Expr *expr = TypeExpr(MD_C_ExprKind_Pointer, TypeExpr(MD_C_ExprKind_Pointer, AtomExpr("i32")));
TestResult(MatchParsedWithType(string, expr));
}
{
MD_String8 string = MD_S8Lit("(*void)");
MD_C_Expr *expr = TypeExpr(MD_C_ExprKind_Pointer, AtomExpr("void"));
TestResult(MatchParsedWithType(string, expr));
}
}
Test("Style Strings")
{
{