all repos — hex @ 962d30572dded1d47be20f603a7ca8ba447c223a

A tiny, minimalist, slightly-esoteric concatenative programming lannguage.

Renamed some core symbols, updated docs, scripts, and styles.
h3rald h3rald@h3rald.com
Fri, 06 Dec 2024 11:29:26 +0100
commit

962d30572dded1d47be20f603a7ca8ba447c223a

parent

033f211f0c1b498f6f57752b760d58d496a52d81

M hex.chex.c

@@ -435,40 +435,66 @@ }

void hex_create_docs(hex_doc_dictionary_t *docs) { - hex_doc(docs, "store", "a s", "", "Stores 'a' as symbol 's'."); - hex_doc(docs, "free", "s", "", "Deletes user symbol 's'."); - hex_doc(docs, "type", "a", "s", "Pushes the data type of 'a' on the stack."); - hex_doc(docs, "i", "q", "*", "Pushes each item of 'q' on the stack."); - hex_doc(docs, "eval", "s", "", "Evaluates 's' as a hex program."); - hex_doc(docs, "puts", "a", "", "Prints 'a' and a new line to standard output."); - hex_doc(docs, "warn", "a", "", "Prints 'a' and a new line to standard error."); - hex_doc(docs, "print", "a", "", "Prints 'a' to standard output."); - hex_doc(docs, "gets", "", "s", "Gets a string from standard input."); + // Memory + hex_doc(docs, ":", "a s", "", "Stores 'a' as symbol 's'."); + hex_doc(docs, "#", "s", "", "Deletes user symbol 's'."); + + // Control flow + hex_doc(docs, "if", "q q q", "*", "If 'q1' is not 0x0, executes 'q2', else 'q3'."); + hex_doc(docs, "when", "q1 q2", "*", "If 'q1' is not 0x0, executes 'q2'."); + hex_doc(docs, "while", "q1 q2", "*", "While 'q1' is not 0x0, executes 'q2'."); + hex_doc(docs, "error", "", "s", "Returns the last error message."); + hex_doc(docs, "try", "q1 q2", "*", "If 'q1' fails, executes 'q2'."); + + // Stack + hex_doc(docs, "dup", "a", "a a", "Duplicates 'a'."); + hex_doc(docs, "pop", "a", "", "Removes the top item from the stack."); + hex_doc(docs, "swap", "a1 a2", "a2 a1", "Swaps 'a2' with 'a1'."); + hex_doc(docs, "stack", "", "q", "Returns the contents of the stack."); + hex_doc(docs, "clear", "", "", "Clears the stack."); + + // Evaluation + hex_doc(docs, ".", "q", "*", "Pushes each item of 'q' on the stack."); + hex_doc(docs, "!", "s", "", "Evaluates 's' as a hex program."); + hex_doc(docs, "'", "a", "q", "Wraps 'a' in a quotation."); + + // Arithmetic hex_doc(docs, "+", "i1 12", "i", "Adds two integers."); hex_doc(docs, "-", "i1 12", "i", "Subtracts 'i2' from 'i1'."); hex_doc(docs, "*", "i1 12", "i", "Multiplies two integers."); hex_doc(docs, "/", "i1 12", "i", "Divides 'i1' by 'i2'."); hex_doc(docs, "%", "i1 12", "i", "Calculates the modulo of 'i1' divided by 'i2'."); + + // Bitwise hex_doc(docs, "&", "i1 12", "i", "Calculates the bitwise AND of two integers."); hex_doc(docs, "|", "i1 12", "i", "Calculates the bitwise OR of two integers."); hex_doc(docs, "^", "i1 12", "i", "Calculates the bitwise XOR of two integers."); hex_doc(docs, "~", "i", "i", "Calculates the bitwise NOT of an integer."); hex_doc(docs, "<<", "i1 12", "i", "Shifts 'i1' by 'i2' bytes to the left."); hex_doc(docs, ">>", "i1 12", "i", "Shifts 'i1' by 'i2' bytes to the right."); - hex_doc(docs, "int", "(i|s)", "i", "Converts a string to a hex integer."); - hex_doc(docs, "str", "(i|s)", "s", "Converts a hex integer to a string."); - hex_doc(docs, "dec", "i", "s", "Converts a hex integer to a decimal string."); - hex_doc(docs, "hex", "s", "i", "Converter a decimal string to a hex integer."); + + // Comparison hex_doc(docs, "==", "i1 12", "i", "Returns 0x1 if 'i1' == 'i2', 0x0 otherwise."); hex_doc(docs, "!=", "i1 12", "i", "Returns 0x1 if 'i1' != 'i2', 0x0 otherwise."); hex_doc(docs, ">", "i1 12", "i", "Returns 0x1 if 'i1' > 'i2', 0x0 otherwise."); hex_doc(docs, "<", "i1 12", "i", "Returns 0x1 if 'i1' < 'i2', 0x0 otherwise."); hex_doc(docs, ">=", "i1 12", "i", "Returns 0x1 if 'i1' >= 'i2', 0x0 otherwise."); hex_doc(docs, "<=", "i1 i2", "i", "Returns 0x1 if 'i1' <= 'i2', 0x0 otherwise."); + + // Logical hex_doc(docs, "and", "i1 i2", "i", "Returns 0x1 if both 'i1' and 'i2' are not 0x0."); hex_doc(docs, "or", "i1 i2", "i", "Returns 0x1 if either 'i1' or 'i2' are not 0x0."); hex_doc(docs, "not", "i", "i", "Returns 0x1 if 'i' is 0x0, 0x0 otherwise."); hex_doc(docs, "xor", "i1 i2", "i", "Returns 0x1 if only one item is not 0x0."); + + // Type + hex_doc(docs, "int", "(i|s)", "i", "Converts a string to a hex integer."); + hex_doc(docs, "str", "(i|s)", "s", "Converts a hex integer to a string."); + hex_doc(docs, "dec", "i", "s", "Converts a hex integer to a decimal string."); + hex_doc(docs, "hex", "s", "i", "Converter a decimal string to a hex integer."); + hex_doc(docs, "type", "a", "s", "Pushes the data type of 'a' on the stack."); + + // List hex_doc(docs, "cat", "(s s|q q) ", "(s|q)", "Concatenates two quotations or two strings."); hex_doc(docs, "slice", "(s i1 i2|q i1 i2)", "(s|q)", "Removes 'i2' items 's' or 'q' at index 'i1'."); hex_doc(docs, "len", "(s|q)", "i ", "Returns the length of 's' or 'q'.");

@@ -476,29 +502,32 @@ hex_doc(docs, "get", "(s|q)", "a", "Gets the item at position 'i' in 's' or 'q'.");

hex_doc(docs, "insert", "(s a i|q a i)", "(s|q)", "Inserts 'a' at position 'i'."); hex_doc(docs, "index", "(s a|q a)", "i", "Returns the index of 'a' within 's' or 'q'."); hex_doc(docs, "join", "q s", "s", "Joins the strings in 'q' using separator 's'."); + + // String hex_doc(docs, "split", "s1 s2", "q", "Splits 's1' using separator 's2'."); hex_doc(docs, "replace", "s1 s2 s3", "s", "Replaces 's2' with 's3' within 's1'."); + + // Quotation + hex_doc(docs, "each", "q1 q2", "*", "Executes 'q2' for each item of 'q1'."); + hex_doc(docs, "map", "q1 q2", "q", "Applies 'q2' to 'q1' items and returns results."); + hex_doc(docs, "filter", "q1 q2", "q", "Filters 'q2' by applying 'q1'."); + + // I/O + hex_doc(docs, "puts", "a", "", "Prints 'a' and a new line to standard output."); + hex_doc(docs, "warn", "a", "", "Prints 'a' and a new line to standard error."); + hex_doc(docs, "print", "a", "", "Prints 'a' to standard output."); + hex_doc(docs, "gets", "", "s", "Gets a string from standard input."); + + // File hex_doc(docs, "read", "s", "s", "Returns the contents of the specified file."); hex_doc(docs, "write", "s1 s2", "s", "Writes 's2' to the file 's1'."); hex_doc(docs, "append", "s1 s2", "s", "Appends 's2' to the file 's1'."); + + // Shell hex_doc(docs, "args", "", "q", "Returns the program arguments."); hex_doc(docs, "exit", "i", "", "Exits the program with exit code 'i'."); hex_doc(docs, "exec", "s", "", "Executes the command 's'."); hex_doc(docs, "run", "s", "q", "Executes 's' and returns code, stdout, stderr."); - hex_doc(docs, "if", "q q q", "*", "If 'q1' is not 0x0, executes 'q2', else 'q3'."); - hex_doc(docs, "when", "q1 q2", "*", "If 'q1' is not 0x0, executes 'q2'."); - hex_doc(docs, "while", "q1 q2", "*", "While 'q1' is not 0x0, executes 'q2'."); - hex_doc(docs, "each", "q1 q2", "*", "Executes 'q2' for each item of 'q1'."); - hex_doc(docs, "error", "", "s", "Returns the last error message."); - hex_doc(docs, "try", "q1 q2", "*", "If 'q1' fails, executes 'q2'."); - hex_doc(docs, "q", "a", "q", "Wraps 'a' in a quotation."); - hex_doc(docs, "map", "q1 q2", "q", "Applies 'q2' to 'q1' items and returns results."); - hex_doc(docs, "filter", "q1 q2", "q", "Filters 'q2' by applying 'q1'."); - hex_doc(docs, "swap", "a1 a2", "a2 a1", "Swaps 'a2' with 'a1'."); - hex_doc(docs, "dup", "a", "a a", "Duplicates 'a'."); - hex_doc(docs, "stack", "", "q", "Returns the contents of the stack."); - hex_doc(docs, "clear", "", "", "Clears the stack."); - hex_doc(docs, "pop", "a", "", "Removes the top item from the stack."); } ////////////////////////////////////////

@@ -1160,7 +1189,7 @@ return 1;

} if (item.type != HEX_TYPE_QUOTATION) { - hex_error(ctx, "Symbol 'i' requires a quotation"); + hex_error(ctx, "Symbol '.' requires a quotation"); FREE(ctx, item); return 1; }

@@ -1187,11 +1216,11 @@ return 1;

} if (item.type != HEX_TYPE_STRING) { - hex_error(ctx, "Symbol 'eval' requires a string"); + hex_error(ctx, "Symbol '!' requires a string"); FREE(ctx, item); return 1; } - return hex_interpret(ctx, item.data.str_value, "<eval>", 1, 1); + return hex_interpret(ctx, item.data.str_value, "<!>", 1, 1); } // IO Symbols

@@ -3637,11 +3666,11 @@ ////////////////////////////////////////

void hex_register_symbols(hex_context_t *ctx) { - hex_set_native_symbol(ctx, "store", hex_symbol_store); - hex_set_native_symbol(ctx, "free", hex_symbol_free); + hex_set_native_symbol(ctx, ":", hex_symbol_store); + hex_set_native_symbol(ctx, "#", hex_symbol_free); hex_set_native_symbol(ctx, "type", hex_symbol_type); - hex_set_native_symbol(ctx, "i", hex_symbol_i); - hex_set_native_symbol(ctx, "eval", hex_symbol_eval); + hex_set_native_symbol(ctx, ".", hex_symbol_i); + hex_set_native_symbol(ctx, "!", hex_symbol_eval); hex_set_native_symbol(ctx, "puts", hex_symbol_puts); hex_set_native_symbol(ctx, "warn", hex_symbol_warn); hex_set_native_symbol(ctx, "print", hex_symbol_print);

@@ -3693,7 +3722,7 @@ hex_set_native_symbol(ctx, "while", hex_symbol_while);

hex_set_native_symbol(ctx, "each", hex_symbol_each); hex_set_native_symbol(ctx, "error", hex_symbol_error); hex_set_native_symbol(ctx, "try", hex_symbol_try); - hex_set_native_symbol(ctx, "q", hex_symbol_q); + hex_set_native_symbol(ctx, "'", hex_symbol_q); hex_set_native_symbol(ctx, "map", hex_symbol_map); hex_set_native_symbol(ctx, "filter", hex_symbol_filter); hex_set_native_symbol(ctx, "swap", hex_symbol_swap);
M test.hextest.hex

@@ -1,47 +1,47 @@

-0x0 "test-count" store -0x0 "successes" store -0x0 "failures" store -() "errors" store -() "fails" store +0x0 "test-count" : +0x0 "successes" : +0x0 "failures" : +() "errors" : +() "fails" : -(dup puts) "pp" store +(dup puts) "pp" : ( - "current-test" store - test-count 0x1 + "test-count" store + "current-test" : + test-count 0x1 + "test-count" : ( - (current-test i) + (current-test .) ( "." print - successes 0x1 + "successes" store + successes 0x1 + "successes" : ) ( "x" print - failures 0x1 + "failures" store - fails test-count dec q cat "fails" store + failures 0x1 + "failures" : + fails test-count dec ' cat "fails" : ) if ) ( ; Store error - errors " - Test #" test-count dec cat ": " cat error cat q cat "errors" store + errors " - Test #" test-count dec cat ": " cat error cat ' cat "errors" : "x" print - failures 0x1 + "failures" store - fails test-count dec q cat "fails" store + failures 0x1 + "failures" : + fails test-count dec ' cat "fails" : ) try -) "test" store +) "test" : ; --- Define tests ( - (0x1 "a" store a 0x1 ==) - ("a" free 0x1) + (0x1 "a" : a 0x1 ==) + ("a" # 0x1) ("aaa" type "string" == 0x1 type "integer" == () type "quotation" == and and) - ((0x1 0x2 +) i 0x3 ==) + ((0x1 0x2 +) . 0x3 ==) ;4 - ("0x2 0x2 -" eval 0x0 ==) + ("0x2 0x2 -" ! 0x0 ==) (0x4 0x5 + 0x9 ==) (0x5 0x3 - 0x2 ==) (0x5 0x2 * 0xa ==)

@@ -122,13 +122,13 @@ ;56

((args len 0x2 ==) ("two") ("no") if "two" ==) ((args len 0x3 !=) ("yes") when "yes" ==) - (0x1 "tmp_a" store (tmp_a 0x3 <) (tmp_a 0x1 + "tmp_a" store) while tmp_a 0x3 ==) - (0x0 "tmp_b" store (0x1 0x2 0x3) (tmp_b + "tmp_b" store) each tmp_b 0x6 ==) + (0x1 "tmp_a" : (tmp_a 0x3 <) (tmp_a 0x1 + "tmp_a" :) while tmp_a 0x3 ==) + (0x0 "tmp_b" : (0x1 0x2 0x3) (tmp_b + "tmp_b" :) each tmp_b 0x6 ==) ;60 ((0x2 0x0 /) (error "Division by zero" ==) try) (error "" ==) - ("a" q q q ((("a"))) ==) + ("a" ' ' ' ((("a"))) ==) ((0x1 0x2 0x3) (dup dup * *) map (0x1 0x8 0x1b) ==) ;64

@@ -138,26 +138,26 @@ (clear stack () ==)

(0x1 0x2 swap pop stack (0x2) ==) ;68 - (("aaa" "puts" store) (error) try "Failed to store symbol 'puts'" ==) - (("puts" free) (error) try "Cannot free native symbol 'puts'" ==) - (("aaa" 0x2 store) (error) try "Symbol name must be a string" ==) - ((0x2 free) (error) try "Symbol name must be a string" ==) + (("aaa" "puts" :) (error) try "Failed to store symbol 'puts'" ==) + (("puts" #) (error) try "Cannot free native symbol 'puts'" ==) + (("aaa" 0x2 :) (error) try "Symbol name must be a string" ==) + ((0x2 #) (error) try "Symbol name must be a string" ==) ;72 - (("puts" i) (error) try "Symbol 'i' requires a quotation" ==) - (((puts) eval) (error) try "Symbol 'eval' requires a string" ==) + (("puts" .) (error) try "Symbol '.' requires a quotation" ==) + (((puts) !) (error) try "Symbol '!' requires a string" ==) (("3" 0x3 +) (error) try "Symbol '+' requires two integers" ==) (("3" 0x3 -) (error) try "Symbol '-' requires two integers" ==) ;76 -) "tests" store +) "tests" : ; Cleanup clear ; --- Run tests -tests (test i) each +tests (test .) each ; --- Report
M web.hexweb.hex

@@ -1,56 +1,56 @@

-"2024" "meta_year" store -"0.1.0" "meta_release" store -"web/assets" "d_assets" store -"web/templates" "d_templates" store -"web/contents" "d_contents" store -"web/out" "d_out" store +"2024" "meta_year" : +"0.1.0" "meta_release" : +"web/assets" "d_assets" : +"web/templates" "d_templates" : +"web/contents" "d_contents" : +"web/out" "d_out" : ; Get all files from a directory -("ls " swap cat run 0x1 get "\n" split) "ls" store +("ls " swap cat run 0x1 get "\n" split) "ls" : ; Get relevant files -d_contents ls i "contents" store -d_assets ls i "assets" store -d_templates "/page.html" cat "t_page" store +d_contents ls . "contents" : +d_assets ls . "assets" : +d_templates "/page.html" cat "t_page" : ; Convenience symbol for debugging -(dup puts) "_" store +(dup puts) "_" : ; Generate tag placeholder ( "{{" swap "}}" cat cat -) "tag" store +) "tag" : ; Replace tag ( - "pt_repl" store - "pt_tag" store - "pt_content" store - (pt_content pt_tag tag i index 0x0 >) - (pt_content pt_tag tag i pt_repl replace "pt_content" store) + "pt_repl" : + "pt_tag" : + "pt_content" : + (pt_content pt_tag tag . index 0x0 >) + (pt_content pt_tag tag . pt_repl replace "pt_content" :) while pt_content -) "process-tag" store +) "process-tag" : "*** Generating hex web site..." puts ; Write contents contents ( - "fn_content" store - fn_content ".html" "" replace "id_content" store - d_contents "/" fn_content cat cat read "content" store + "fn_content" : + fn_content ".html" "" replace "id_content" : + d_contents "/" fn_content cat cat read "content" : t_page read ; Replace tags - "content" content process-tag i - "title" id_content process-tag i - "release" meta_release process-tag i - "year" meta_year process-tag i - "new_content" store + "content" content process-tag . + "title" id_content process-tag . + "release" meta_release process-tag . + "year" meta_year process-tag . + "new_content" : (fn_content "home.html" ==) - (d_out "/index.html" cat "dst_file" store) + (d_out "/index.html" cat "dst_file" :) ( ("sh -c \"mkdir -p " d_out "/" id_content "\"") () map "" join exec - (d_out id_content "index.html") () map "/" join "dst_file" store + (d_out id_content "index.html") () map "/" join "dst_file" : ) if " - Writing: " dst_file cat puts

@@ -61,12 +61,12 @@ ; Write assets

("sh -c \"mkdir -p " d_out "/assets\"") () map "" join exec assets ( - "fn_asset" store - (d_out "assets" fn_asset) () map "/" join "dst_file" store + "fn_asset" : + (d_out "assets" fn_asset) () map "/" join "dst_file" : (fn_asset "robots.txt" ==) - ((d_out fn_asset) () map "/" join "dst_file" store) + ((d_out fn_asset) () map "/" join "dst_file" :) when - (d_assets fn_asset) () map "/" join "src_file" store + (d_assets fn_asset) () map "/" join "src_file" : " - Writing: " dst_file cat puts ("cp" src_file dst_file) () map " " join exec ) each
M web/assets/styles.cssweb/assets/styles.css

@@ -18,9 +18,13 @@ h1,

h2, h3 { margin: 1rem 0 0.5rem 0; - font-size: 1rem; + font-size: 1.1rem; font-weight: 700; color: gold; +} + +h3 { + font-size: 1rem; } header {
M web/contents/about.htmlweb/contents/about.html

@@ -1,13 +1,31 @@

<article> -<h2>About</h2> -<p>The core idea behind <strong>hex</strong> is to be a really small language for experimenting with the <a href="https://concatenative.org" target="_blank">concatenative</a> programming paradigm and at the same time being somewhat useful for practical things like creating short scripts or be used as glue code for automating common tasks.</p> -<p>When I first implemented <a href="https://min-lang.org" target="_blank">min</a>, the intent was to create a minimal language, hence the name. The reality however turned out to be very different: in no time, I found myself adding a lot of syntactic sugar, complex data types, support for XML processing and HTTP client and server... it became more of a batteries-included language with a somewhat spartan syntax than anything else. </p> -<p>The second attempt was to essentially fork part of the min codebase and create <a href="https://h3rald.com/mn" target="_blank">mn</a>, which was a lot more limited, but still not minimal <em>enough</em>. The one thing that was bothering me the most was, in the end, the fact that it was implemented in Nim. Not that Nim is a bad language (quite the opposite!), but I really wanted to keep things simple, and implement something in C.</p> -<p>And that&#39;s how <strong>hex</strong> was born! Actually... I started off asking ChatGPT to implement a tokenizer for a small stack-based language able to process integers, then an interpreter, then I asked for string support, and then... well, the boilerplate wasn&#39;t too bad. A few tweaks here and there and I was able to improve a few things, and in a few days I realized that I had re-learnt some C programming skills I hadn&#39;t been using in the past 20 years!</p> -<p>So there you have it. A language that is purely concatenative, truly minimalist and yet powerful enough, limited to 64 native symbols and yet manage to be somewhat useful, hopefully. The fact that I could get it to compile to WASM with just a few hours worth of extra work (mainly to manage stdin properly) also meant that this little thing also has its own browser-based <a href="/play">playground</a>!</p> -<p>The only annoying thing is that it only understands hexadecimal integers. Well... I figured I could take a little <em>poetic license</em>, and introduce a small quirk that would justify its nice, almost magical, three letter name!</p> -<p>Happy hexxing!</p> -<p><em>-- Fabio aka H3RALD</em></p> + <h2>About</h2> + <p>The core idea behind <strong>hex</strong> is to be a really small language for experimenting with the <a + href="https://concatenative.org" target="_blank">concatenative</a> programming paradigm and at the same time + being somewhat useful for practical things like creating short scripts or be used as glue code for automating + common tasks.</p> + <p>When I first implemented <a href="https://min-lang.org" target="_blank">min</a>, the intent was to create a + minimal language, hence the name. The reality however turned out to be very different: in no time, I found + myself adding a lot of syntactic sugar, complex data types, support for XML processing and HTTP client and + server... it became more of a batteries-included language with a somewhat spartan syntax than anything else. + </p> + <p>The second attempt was to essentially fork part of the min codebase and create <a href="https://h3rald.com/mn" + target="_blank">mn</a>, which was a lot more limited, but still not minimal <em>enough</em>. The one thing + that was bothering me the most was, in the end, the fact that it was implemented in Nim. Not that Nim is a bad + language (quite the opposite!), but I really wanted to keep things simple, and implement something in C.</p> + <p>And that&#39;s how <strong>hex</strong> was born! Actually... I started off asking ChatGPT to implement a + tokenizer for a small stack-based language able to process integers, then an interpreter, then I asked for + string support, and then... well, the boilerplate wasn&#39;t too bad. A few tweaks here and there and I was able + to improve a few things, and in a few days I realized that I had re-learnt some C programming skills I + hadn&#39;t been using in the past 20 years!</p> + <p>So there you have it. A language that is purely concatenative, truly minimalist and yet powerful enough, limited + to 64 native symbols and yet manage to be somewhat useful, hopefully. The fact that I could get it to compile to + WASM with just a few hours worth of extra work (mainly to manage stdin properly) also meant that this little + thing also has its own browser-based <a href="/play">playground</a>!</p> + <p>The only annoying thing is that it only understands hexadecimal integers. Well... I figured I could take a little + <em>poetic license</em>, and introduce a small quirk that would justify its nice, almost magical, three letter + name!</p> + <p>Happy hexxing!</p> + <p><em>-- Fabio</em></p> </article> -
M web/contents/get.htmlweb/contents/get.html

@@ -4,10 +4,10 @@

<p>At present there are no pre-built binaries available for download, because hex has not been officially released yet. However, when it is, the following pre-built binaries will be available for download:</p> <ul> - <li>hex v{{release}} for Windows (x86_64)</li> <li>hex v{{release}} for Linux (x86_64)</li> <li>hex v{{release}} for MacOS (x86_64)</li> <li>hex v{{release}} for MacOS (ARM64)</li> + <li>hex v{{release}} for Windows (x86_64)</li> <li>hex v{{release}} (<a href="https://justine.lol/ape.html" target="_blank">αcτµαlly pδrταblε εxεcµταblε</a>) </li> <li>hex v{{release}} (<a href="https://webassembly.org" target="_blank">WebAssembly</a>)</li>

@@ -28,7 +28,7 @@ <li>Run <code>make wasm</code> to generate a <code>hex.js</code> and a <code>hex.wasm</code> (WebAssembly) file.

</li> </ul> - <h3>Command line options</h3> + <h3>Command Line Options</h3> <p>Running <code>hex -h</code> will print the following list of all the available command line options for the hex executable:</p>
M web/contents/home.htmlweb/contents/home.html

@@ -6,7 +6,7 @@ language, to create shell scripts, or simply to learn more about concatenative programming.</p>

<p>Its syntax is heavily inspired by the <a href="https://min-lang.org" target="_blank">min</a> programming language, and features space-separated tokens, no unnecessary punctuation characters, and round brackets to delimit lists.</p> - <h2>Features</h2> + <h3>Features</h3> <ul> <li>Support <strong>32bit integers</strong>, <em>written only in hexadecimal format</em>, both positive and negative (represented via <a href="https://en.wikipedia.org/wiki/Two%27s_complement" target="_blank">two's

@@ -27,7 +27,7 @@ making it easier

to embed in other programs and port to different platforms.</li> </ul> - <h2>Example</h2> + <h3>Example</h3> <p> The following code executes the <em>ls</em> command, retrieves the files returned in standard output, and stores them inside a quotation that is then printed:</p>