Every program in the compiler's own examples/ directory.
Copied verbatim from examples/ in the Voxlang repo, from a one-line hello to a shell-free process supervisor.
Checked against vox 0.4.10 on 2026-08-23: 33 of 33 examples passed.
The language reference has more, with the rules behind them.
The smallest complete Voxlang program: one sentence, compiled straight to a working binary.
Print "Hello, World!".
A simple greeter that demonstrates command-line arguments and environment variables
(A simple greeter that demonstrates command-line arguments and environment variables) (Uses the 's property syntax for accessing argument and environment properties) Print "=== Argument Properties Demo ===". a number called argc is arguments's count. Print "Argument count: ". Print the argc. a text called program is arguments's name. Print "Program name: ". Print the program. (Greet using argument or default) a text called name is "World". If arguments's count is greater than 1 then, the name is arguments's first. Print "Hello, {name}!". Print the name. Print "!". (Check if arguments were provided) If arguments's empty then, Print "(No user arguments provided)". Print "". Print "=== Environment Properties Demo ===". a number called 'env count' is environment's count. Print "Environment variable count: ". Print the env count. (Access environment variable by name using 's syntax) a text called user is environment's "USER". Print "Current user: ". Print the user. a text called home is environment's "HOME". Print "Home directory: ". Print the home. (Show first environment variable) a text called env1 is environment's first. Print "First env var: ". Print the env1. open a file for writing called output at "/dev/stdout". open a file for reading called stdinput at "/dev/stdin". a buffer called userbuf. print "What's your name? ". read from stdinput into userbuf. a text called username is userbuf. print "". write "Hi, {username}!" to output. (write userbuf to output. write "!" to output.)
Set the counter to -2.0.
Set the counter to -2.0. While the counter is less than 10.0, print the counter, the counter is the counter plus 1.
FizzBuzz over 1–15, with a defined function and chained "but if" conditions.
To 'check divisibility' with a number called x and a number called y. Return a boolean, x modulo y is 0. For each number from 1 to 15, print the number, but if 'check divisibility' of the number and 6 is true print "fizzbuzz", but if 'check divisibility' of the number and 2 is true print "fizz", but if 'check divisibility' of the number and 3 is true print "buzz".
Print "=== Integer Arithmetic ===".
Print "=== Integer Arithmetic ===". Set num1 to 10. Set num2 to 3. Print "num1 = 10, num2 = 3". Print "". Print "Addition: num1 add num2 =". Print num1 add num2. Print "Subtraction: num1 subtract num2 =". Print num1 subtract num2. Print "Multiplication: num1 multiply num2 =". Print num1 multiply num2. Print "Division: num1 divide num2 =". Print num1 divide num2. Print "Modulo: num1 modulo num2 =". Print num1 modulo num2. Print "". Print "=== Float Arithmetic ===". Set val1 to 10.5. Set val2 to 3.2. Print "val1 = 10.5, val2 = 3.2". Print "(Note: floats currently display as truncated integers)". Print "". Print "Addition: val1 add val2 =". Print val1 add val2. Print "Subtraction: val1 subtract val2 =". Print val1 subtract val2. Print "Multiplication: val1 multiply val2 =". Print val1 multiply val2. Print "Division: val1 divide val2 =". Print val1 divide val2. Print "". Print "=== Mixed Operations ===". Set result to 5.0. Print "Starting with 5.0". Set result to result add 2.5. Print "After adding 2.5:". Print result. Set result to result multiply 2.0. Print "After multiplying by 2.0:". Print result. Set result to result subtract 3.0. Print "After subtracting 3.0:". Print result. Set result to result divide 2.0. Print "After dividing by 2.0:". Print result. Print "". Print "=== Comparisons ===". If 10.5 is greater than 10.0 then, print "10.5 > 10.0: true", Otherwise, print "ERROR in comparison". If 3.0 is less than 3.5 then, print "3.0 < 3.5: true", Otherwise, print "ERROR in comparison". If 5.0 is equal to 5.0 then, print "5.0 == 5.0: true", Otherwise, print "ERROR in comparison". Print "". Print "=== Loop with Float Counter ===". Print "You should see a sequence of numbers from 0.0 to 4.0". Set counter to 0.0. While counter is less than 5.0, Print counter, Set counter to counter add 1.0. Print "". Print "Done!".
Type Casting Examples - using 'as' keyword
(Type Casting Examples - using 'as' keyword) (The 'as' keyword converts a value to a different type) Print "=== Number and Float Conversions ===". (Float to number - truncates decimal part) a float called pi is 3.14159. a number called piInt is the pi as a number. Print "3.14159 as number: ". Print the piInt. (Number to float) a number called qty is 42. a float called qtyF is the qty as a float. Print "42 as float: ". Print the qtyF. (Rounding - explicit cast after adding 0.5) a float called val is 3.7. a number called rounded is the val add 0.5 as a number. Print "3.7 rounded: ". Print the rounded. Print "". Print "=== Number and Text Conversions ===". (Number to text) a number called age is 25. Print "Age: ". Print the age. Print "". Print "=== Boolean and Number Conversions ===". (Boolean to number) a boolean called bval is true. a number called bvalN is the bval as a number. Print "true as number: ". Print the bvalN. a boolean called boff is false. a number called boffN is the boff as a number. Print "false as number: ". Print the boffN. Print "". Print "=== Inline Casting ===". (Cast within print statement) Print "Direct cast 3.99 as number: ". Print 3.99 as a number. Print "". Print "=== Done ===".
Format Strings in English
(Format Strings in English) (This example demonstrates all the ways to use formatted output) Print "=== Basic String Interpolation ===". (Variables can be embedded in strings using curly braces) a text called name is "Alice". a number called age is 25. Print "Hello, {name}! You are {age} years old.". (Multiple variables in one string) a text called city is "London". Print "{name} lives in {city} and is {age}.". Print "". Print "=== Number Formatting ===". (Floating point precision - specify decimal places) a float called pi is 3.14159265358979. Print "Pi to 2 decimals: {pi:.2}". Print "Pi to 4 decimals: {pi:.4}". Print "Pi to 0 decimals: {pi:.0}". (Padding and alignment) a number called small is 42. Print "Padded to 6 chars: [{small:6}]". Print "Zero-padded: [{small:06}]". Print "Left aligned: [{small:<6}]". Print "Right aligned: [{small:>6}]". Print "Center aligned: [{small:^6}]". Print "". Print "=== Different Number Bases ===". a number called value is 255. Print "Decimal: {value}". Print "Hexadecimal: {value:x}". Print "Hex uppercase: {value:X}". Print "Binary: {value:b}". Print "Octal: {value:o}". (Hex with 0x prefix) Print "With prefix: {value:x}"(outputs: 0xff). Print "Padded hex: {value:04x}"(outputs: 0x00ff). Print "". Print "=== Escape Sequences ===". (Literal braces using double braces) Print "Use {{braces}} for literal braces.". (Common escape sequences in strings) Print "Tab:\there". Print "Newline in string:\nSecond line". Print "". Print "=== Formatting Expressions ===". (Format inline calculations) a number called x is 10. a number called y is 3. Print "x + y = {x add y}". Print "x * y = {x multiply y}". (Property access in format strings) Print "Argument count: {arguments's count}". Print "". Print "=== Practical Examples ===". (Currency formatting) a float called price is 19.99. Print "Total: ${price:.2}". (Percentage) a float called ratio is 0.756. Print "Progress: {ratio multiply 100:.1}%". Print "". Print "=== Done ===".
All seven uses of the 'and' keyword in one file: the boolean operator, parameter and argument separators, loop-clause joins, and the subject list before 'are'.
print "==============================================". print "The 'and' Keyword - All Uses Demonstrated" print "==============================================" To 'add numbers' with a number called x and a number called y. Return a number, the x add the y. To 'multiply three' with a number called p and a number called q and a number called r. Return a number, p multiply q multiply r. To 'show the sum' with a number called first and a number called second. print 'add numbers' of first and second. print "--- 1. LOGICAL AND (boolean operator) ---" a boolean called sunny is true. a boolean called warm is true. a boolean called raining is false. If sunny and warm then, print "Perfect weather for a picnic!". If sunny and raining then, print "Sun shower!". Otherwise, print "No sun shower today.". print "--- 2. FUNCTION PARAMETERS (separator) ---" print "add numbers of 3 and 5:" print 'add numbers' of 3 and 5. print "multiply three of 2 and 3 and 4:" print 'multiply three' of 2 and 3 and 4. print "--- 3. FUNCTION ARGUMENTS (separator) ---" a number called var1 is 10. a number called var2 is 20. print "Adding first and second:" print 'add numbers' with var1 and var2. print "--- 4. SUBJECT LIST TERMINATOR (before 'are') ---" a boolean called engine_on is false. a boolean called doors_locked is false. a boolean called seatbelt_on is false. print "Checking if all are false:" if engine_on, doors_locked, and seatbelt_on are not true then, print "All systems are OFF - safe to exit vehicle.". Set engine_on to true. Set doors_locked to true. Set seatbelt_on to true. print "Now all are true:" if engine_on, doors_locked, and seatbelt_on are true then, print "All systems are ON - ready to drive.". print "--- 5. COMBINING USES ---" a number called num1 is 5. a number called num2 is 10. a boolean called valid is true. a boolean called ready is true. If valid and ready then, print "Conditions met, calculating...". print 'add numbers' of num1 and num2. print "--- 6. TWO-ITEM LIST WITH 'are' ---" a boolean called left is true. a boolean called right is true. if left, and right are true then, print "Both left and right are true.". print "--- 7. JOINING LOOP CLAUSES (one call per combination) ---" print "show the sum of each first from [1, 2] and each second from [10, 20]:" 'show the sum' of each first from [1, 2] and each second from [10, 20]. print "Done! All 'and' keyword uses demonstrated."
To 'add numbers' with a number called x and a number called y. Return a number, the x add y.
To 'add numbers' with a number called x and a number called y. Return a number, the x add y. a number called x is 3. a number called y is 5. Print 'add numbers' of x and y.
Print "=== Lists Demo ===".
Print "=== Lists Demo ===". Print "Integer list [10, 20, 30]:". a list called 'number list' is [10, 20, 30]. For each n in 'number list', print the n. print "". (Access specific elements by index - 1-indexed like natural English) Print "Second element of numbers: ". Print element 100 of 'number list'. Print "Boolean list [true, false, true]:". a list called bools is [true, true, false]. For each b in bools, print the b. print "". Print "First element: ". Print bools's first. Print "Last element: ". Print bools's last. print bools's size. print "You should see an error below" a boolean called bad is element 100 of bools. On error print "Cannot access element 100 - out of bounds!". Print "Word list [\"hello\", \"world\"]:". a list called words is ["hello", "world"]. For each w in words, print the w. print "". Print "Done!".
Key/value maps: literals, reading and setting by key, iterating keys and values, and a list and another map nested inside one.
(Example: map.vox — key/value collections (stage 1e2, tag 5). A map is a JSON-style object: text keys, any-typed values, insertion- ordered. Literals use {"key": value, ...}; `map's "key"` reads a value; `set map's "key" to value` inserts or replaces; `map's keys`/`values` yield fresh lists for iteration; `map's length`/`empty` report the live entry count; `is a map` classifies at runtime. Missing keys set the error flag (observable via `on error`) rather than crashing. This example builds a small record, mutates it, iterates its keys and values, nests a list and another map, and round-trips the map through a `value` parameter to show the tag survives the call.) To 'show' with a value called v. print v. a map called person is {"name": "Ada", "age": 36, "city": "London"}. print "record:" print person. print "name is:" print person's "name". set person's "age" to 37. print "after birthday:" print person's "age". print person's length. print "keys:" for each key in person's keys print key. print "values:" for each v in person's values print v. a map called nested is {"tags": ["a", "b"], "meta": {"id": 1}}. print "nested:" print nested. a list called taglist is nested's "tags". print "tags:" print taglist. a map called meta is nested's "meta". print "meta id:" print meta's "id". print "round-trip through a value param:" 'show' of person. print person's "nope". on error print "looked up a missing key".
Nested lists - a small walker that builds a nested list, prints it, extracts a child, and classifies elements with `is a list`.
(Nested lists - a small walker that builds a nested list, prints it, extracts a child, and classifies elements with `is a list`. Demonstrates Collections stage 1e1: a list element may be a list.) a list called data is [1, [2, 3], "four", [5, [6, 7]]]. print data. (Extract a child list and use it as a list.) a list called child is element 2 of data. print child. print child's length. for each y in child, print y. (Walk the top level, classifying each element.) for each item in data if item is a list print "list" otherwise print "scalar"
A mixed list of a number, a text and a decimal, classified by type and round-tripped through a value-returning function.
(Example: walker.vox — the first end-to-end mixed-data program. A `value` parameter carries a runtime type tag alongside its payload, so a single function can accept a number, a text, or a decimal and ask `is a ...` to find out which at runtime. A `value` return carries that tag back out, so forwarding and re-collecting preserve the type. This example feeds each element of a flat mixed list through a classifier, then round-trips them through a value-returning function to show the tag survives the call in both directions.) To describe with a value called item. If item is a number, print "number". Otherwise if item is a text, print "text". Otherwise print "decimal". To echo with a value called v. Return a value, v. a list called data is [42, "hello", 3.14]. print "Classifying each element:" For each item in data, describe of item. a list called echoed is []. For each item in data, append echo of item to echoed. print "After round-trip through echo, still:" For each e in echoed, describe of e.
A morning's deliveries, written with types of the program's own making.
(A morning's deliveries, written with types of the program's own making. A stop is a corner of the town grid; a leg is one drive between two stops. Kept as loose numbers this would be four variables per leg, held in step by hand and easy to get wrong. Kept as things, a stop travels as one value: it copies whole, it prints itself, and two stops compare corner for corner.) A thing called stop has a function called 'at the corner of', a number called street is 0, a number called avenue is 0. A thing called leg has a stop called start, a stop called end. (A stop comes into being at a crossing, so the maker is named for the way it is called: a stop's 'at the corner of' with 4 and 1.) To do the stop's 'at the corner of', with a number called street and a number called avenue. a stop called corner. Set corner's street to street. Set corner's avenue to avenue. Return a stop, corner. (The van drives along the streets and never through the buildings, so a leg is as long as the blocks crossed one way plus the blocks crossed the other. Its first parameter is a whole leg, which is what lets a leg be asked for its own length: drive's 'the blocks driven'.) To 'the blocks driven' with a leg called drive. a number called 'streets crossed' is drive's end's street subtract drive's start's street. If 'streets crossed' is less than 0 then, Set 'streets crossed' to 0 subtract 'streets crossed'. a number called 'avenues crossed' is drive's end's avenue subtract drive's start's avenue. If 'avenues crossed' is less than 0 then, Set 'avenues crossed' to 0 subtract 'avenues crossed'. Return a number, 'streets crossed' add 'avenues crossed'. The depot is a stop's 'at the corner of' with 1 and 1. The bakery is a stop's 'at the corner of' with 4 and 1. The school is a stop's 'at the corner of' with 4 and 5. Print "The depot stands at {depot}.". (Each leg begins where the last one ended, so the whole round is one leg moved along, not a fresh pair of corners every time.) a leg called drive. a number called 'blocks driven today' is 0. Set drive's start to depot. Set drive's end to bakery. Print "The first leg is {drive}.". Set 'blocks driven today' to 'blocks driven today' add drive's 'the blocks driven'. Print "The bakery is {drive's 'the blocks driven'} blocks from the depot.". Set drive's start to drive's end. Set drive's end to school. Set 'blocks driven today' to 'blocks driven today' add drive's 'the blocks driven'. Print "Then {drive's 'the blocks driven'} blocks on to the school.". Set drive's start to drive's end. Set drive's end to depot. Set 'blocks driven today' to 'blocks driven today' add drive's 'the blocks driven'. Print "And {drive's 'the blocks driven'} blocks home again.". Print "The round comes to {blocks driven today} blocks.". (A thing is a value, so the van parked at the school holds a copy of that corner. Sending the van on cannot move the school.) a stop called 'the van' is school. Set 'the van''s avenue to 9. Print "The van has gone on to {'the van'}, and the school is still at {school}.". (Two stops are equal when they are the same corner, field for field.) If drive's end is depot then, Print "The van is home for the day.".
Binary and Hex Operations in English
(Binary and Hex Operations in English) (This example demonstrates working with binary data, hex values, and buffer manipulation) Print "=== Hexadecimal Literals ===". (Numbers can be written in hex using 0x prefix) a number called red is 0xFF. a number called green is 0x80. a number called blue is 0x40. Print "Red component: {red} ({red:02X})". Print "Green component: {green} ({green:02X})". Print "Blue component: {blue} ({blue:02X})". (Combine into RGB value) a number called rgb is red multiply 65536 add green multiply 256 add blue. Print "Combined RGB: {rgb:06X}". Print "". Print "=== Binary Literals ===". (Numbers can be written in binary using 0b prefix) a number called flags is 0b10110100. Print "Flags: {flags} (binary: {flags:b})". Print "Flags padded: {flags:08b}". Print "". Print "=== Buffer Byte Manipulation ===". (Create a buffer for binary data) Create a buffer called data of size 16. (Set individual bytes by position - 1-indexed like natural English) Set byte 1 of data to 0x48. Set byte 2 of data to 0x65. Set byte 3 of data to 0x6C. Set byte 4 of data to 0x6C. Set byte 5 of data to 0x6F. (Read individual bytes) a number called first_byte is byte 1 of data. Print "First byte: {first_byte:02X}". (Print buffer as string - shows "Hello") Print "Buffer contents: ". Print data. Print "". Print "=== Modifying Bytes ===". (Change a specific byte) Set byte 5 of data to 0x21. Print "After changing byte 5 to '!':". Print data. (Zero out remaining bytes explicitly) Set byte 6 of data to 0. Print "". Print "=== Bitwise Operations ===". a number called val_a is 0b11110000. a number called val_b is 0b10101010. (Bitwise AND) a number called result is val_a bit-and val_b. Print "{val_a:08b} AND {val_b:08b} = {result:08b}". (Bitwise OR) Set result to val_a bit-or val_b. Print "{val_a:08b} OR {val_b:08b} = {result:08b}". (Bitwise XOR) Set result to val_a bit-xor val_b. Print "{val_a:08b} XOR {val_b:08b} = {result:08b}". (Bitwise NOT - using XOR with all 1s) Set result to val_a bit-xor 0xFF. Print "NOT {val_a:08b} = {result:08b}". (Bit shifting) Set result to val_a bit-shift-left 2. Print "{val_a:08b} << 2 = {result:08b}". Set result to val_a bit-shift-right 2. Print "{val_a:08b} >> 2 = {result:08b}". Print "". Print "=== Practical: Simple Hex Dump ===". (Write some test data) Set byte 1 of data to 0xDE. Set byte 2 of data to 0xAD. Set byte 3 of data to 0xBE. Set byte 4 of data to 0xEF. Set byte 5 of data to 0xCA. Set byte 6 of data to 0xFE. Set byte 7 of data to 0xBA. Set byte 8 of data to 0xBE. Print "Hex dump of first 8 bytes:". a number called i is 1. While i is less than or equal to 8, a number called byte_val is byte i of data, Print "{byte_val:02X} " without newline, increment i. Print "". Print "". Print "=== Practical: Patching a Binary Value ===". (Read a 32-bit value from buffer - little endian) a number called b0 is byte 1 of data. a number called b1 is byte 2 of data. a number called b2 is byte 3 of data. a number called b3 is byte 4 of data. a number called value32 is b0 add b1 multiply 256 add b2 multiply 65536 add b3 multiply 16777216. Print "32-bit value at offset 0: {value32:08X}". (Write a new 32-bit value - little endian) a number called newval is 0x12345678. Set byte 1 of data to newval bit-and 0xFF. Set byte 2 of data to newval bit-shift-right 8 bit-and 0xFF. Set byte 3 of data to newval bit-shift-right 16 bit-and 0xFF. Set byte 4 of data to newval bit-shift-right 24 bit-and 0xFF. Print "After patching with 0x12345678:". Set i to 1. While i is less than or equal to 4, Set byte_val to byte i of data, Print "{byte_val:02X} " without newline, increment i. Print "". a buffer called buf is data. Print "Buffer contents: ". Print buf. set byte 1 of buf to 'A'. (Add security restraints, CANNOT access out of bounds, should be impossible) (If the user tries to access out of bounds, throw an error to be caught by 'on error') Print "After setting byte 1 to 'A':". Print buf. (should be Aata, not 0 indexed) Print "". Print "=== Done ===".
A working reimplementation of Unix cat: flags, multiple files, and a stdin fallback.
(reimplementation of core utils CAT command in vox) A text called 'Program Version' is "0.1.10". (Parse the flags now) A flag called 'wants help' is "--help" or "-h", it is a boolean. A flag called 'wants version' is "--version" or "-v", it is a boolean. A flag called 'we are numbering lines' is "--number" or "-n", it is a boolean. A text called Program is arguments's name. To 'show version'. Print "{Program} (vox) {Program Version} by Josjuar Lister". Exit 0. If 'wants help' then, Print "{Program} - concatenate files and print to standard output", Print "Usage: {Program} [OPTION]... [FILE]...", Print "With no FILE, or when FILE is -, read standard input.", Print "\nOptions:", Print " -h, --help display this help and exit", Print " -n, --number number all output lines", Print " -v, --version output version information and exit", Print "\nExamples:", Print "\t{Program} f - g\tOutput f's contents, then standard input, then g's contents", Print "\t{Program}\t\tCopy standard input to standard output", Print "See https://github.com/vox-lang/vox for more information.", Exit 0. If 'wants version' then, 'show version'. (Prepare to cat) a boolean called 'failed to open a file' is false. Open a file for writing called output at 1(fd - stdout). On error print "{Program}: /dev/stdout: Could not open pipe", exit 1. A number called 'Line Number' is 1. To 'read the file' with a file called source. Create a buffer called staged_output. Create a buffer called content. On error print "{Program}: failed to create buffer". Read line from source into content. While content is not empty, if 'we are numbering lines' then, Append "{Line Number:6}\t{content}" to staged_output, increment the 'Line Number'. Otherwise, Append content to staged_output. if staged_output's size is greater than 65535 then, Write staged_output to output, Clear staged_output. read line from the source into content. Close source. Return staged_output. If arguments's empty then, Open a file for reading called source at 0(fd - stdin), On error print "{Program}: /dev/stdin: Could not open pipe", exit 1. a buffer called staged_output is 'read the file' with source, Write staged_output to output, Clear staged_output, Exit 0. (Loop expansion: open a file for each filename in arguments's all) Open a file called source for reading at each filename from arguments's all treating "-" as "/dev/stdin", On error print "{Program}: {filename}: No such file or directory", set 'failed to open a file' to true, continue. a buffer called staged_output is 'read the file' with source, Write staged_output to output, Clear staged_output. If 'failed to open a file' then, Exit 1. Otherwise, Exit 0.
print "Writing to file...".
print "Writing to file...". open a file for writing called out at "./hello.txt". Write "Hello World!" to out. Close the out. print "Done! Check hello.txt".
print "=== Simple File Test ===".
print "=== Simple File Test ===". a buffer called data is 256 bytes in size. print "Creating and writing to file...". open a file for writing called output at "./test_output.txt". Write "Hello from Vox!" to output. Write a newline to output. Write "This is line 2." to output. Close the output. print "Reading from file...". open a file for reading called input at "./test_output.txt". Read from input into data. Close the input. print "File contents:". print data. print "Cleaning up...". Delete the file "./test_output.txt". print "Done!".
print "=== Secure File I/O Demo ===".
print "=== Secure File I/O Demo ===". print "Creating a dynamic buffer (no size needed!)". a buffer called data. print "Writing to file...". open a file for writing called out at "./secure_test.txt". Write "Line 1: Hello from secure file I/O!" to out. Write a newline to out. Write "Line 2: Buffers grow automatically." to out. Write a newline to out. Write "Line 3: Files auto-close on exit if forgotten." to out. Close the out. print "Reading back...". open a file for reading called src at "./secure_test.txt". Read from src into data. Close the src. print "Contents:". print data. print "Cleaning up...". Delete the file "./secure_test.txt". print "Done! All resources auto-cleaned.".
Command-line arguments and environment variables read through the 's property syntax, plus a proposed flag-schema design sketched in comments.
( Example: Accessing Command-Line Arguments and Environment Variables This file demonstrates the 's property syntax for accessing: 1. Command-line arguments passed to the program 2. Environment variables from the shell Usage: ./args_and_env Alice 42 ) (========================================================================) ( PROPOSED FEATURE: FLAG SCHEMA ) (========================================================================) ( IDEA: Declarative flag definitions that automatically parse arguments Syntax examples: a flag called "numbering" is "-n" or "--number", it is a boolean. a flag called "iterations" is "-i" or "--iterations", it is a number and is required. a flag called "output" is "-o" or "--output", it is a text with default "out.txt". a flag called "verbose" is "-v" or "--verbose", it is a boolean with default false. a flag called "config" is "-c" or "--config", it is a text. a flag called "threads" is "-t" or "--threads", it is a number with default 4. Benefits: - Flags are automatically parsed from arguments - arguments's all returns only positional arguments (flags removed) - Type validation happens automatically - Required flags cause error if missing - Boolean flags don't consume next argument - Default values are used when flag is not provided ======================================================================== COMPREHENSIVE USAGE EXAMPLES ======================================================================== Example 1: Simple boolean flag ------------------------------ Command: ./program -n file.txt ) (a flag called "numbering" is "-n" or "--number", it is a boolean. If the numbering then, Print "Numbering is enabled.".) ( Result: numbering = true, arguments's all = ["file.txt"] Example 2: Flag with required value ------------------------------------ Command: ./program --iterations 10 input.txt output.txt ) (a flag called "iterations" is "-i" or "--iterations", it is a number and is required. Print "Running {iterations} iterations".) ( Result: iterations = 10, arguments's all = ["input.txt", "output.txt"] Error case: ./program input.txt (missing required --iterations, program exits with error) Example 3: Flag with default value ----------------------------------- Command: ./program process data.csv ) (a flag called "output" is "-o" or "--output", it is a text with default "out.txt". a flag called "threads" is "-t" or "--threads", it is a number with default 4. Print "Output file: {output}". Print "Using threads: {threads}".) ( Result: output = "out.txt", threads = 4, arguments's all = ["process", "data.csv"] Example 4: Mixed flags and positional arguments ------------------------------------------------- Command: ./program -v --config settings.json -t 8 build src/ dist/ ) (a flag called "verbose" is "-v" or "--verbose", it is a boolean with default false. a flag called "config" is "-c" or "--config", it is a text. a flag called "threads" is "-t" or "--threads", it is a number with default 4. If the verbose then, Print "Verbose mode enabled.". If the config is not empty then, Print "Loading config from: {config}". a list called "positional" is arguments's all. Print "Command: {positional's first}". Print "Source: {positional's at 2}". Print "Destination: {positional's at 3}".) ( Result: verbose = true, config = "settings.json", threads = 8 arguments's all = ["build", "src/", "dist/"] Example 5: Combining short flags --------------------------------- Command: ./program -nv file.txt ) (a flag called "numbering" is "-n" or "--number", it is a boolean. a flag called "verbose" is "-v" or "--verbose", it is a boolean.) ( Result: numbering = true, verbose = true, arguments's all = ["file.txt"] Example 6: Flag appearing multiple times (last wins) ----------------------------------------------------- Command: ./program -o first.txt -o second.txt data.csv ) (a flag called "output" is "-o" or "--output", it is a text.) ( Result: output = "second.txt", arguments's all = ["data.csv"] Example 7: Using -- to stop flag parsing ----------------------------------------- Command: ./program -v -- -n --help file.txt ) (a flag called "verbose" is "-v" or "--verbose", it is a boolean. a flag called "numbering" is "-n" or "--number", it is a boolean.) ( Result: verbose = true, numbering = false arguments's all = ["-n", "--help", "file.txt"] Example 8: Complete CLI application ------------------------------------ Command: ./compiler --optimize -o output.bin -j 16 main.en lib.en ) a flag called optimize is "-O" or "--optimize", it is a boolean with default false. a flag called output is "-o" or "--output", it is a text with default "a.out". a flag called jobs is "-j" or "--jobs", it is a number with default 1. a flag called verbose is "-v" or "--verbose", it is a boolean with default false. a flag called debug is "-g" or "--debug", it is a boolean with default false. Parse flags. a list called source_files is arguments's all. If source_files's empty then, Print "Error: No source files provided.", Exit with 1. If the verbose then, Print "Compiling with optimization: {the optimize}", Print "Output: {the output}", Print "Parallel jobs: {the jobs}". For each source_file in the source_files, Print "Compiling: {source_file}". ( Result: optimize = true, output = "output.bin", jobs = 16 verbose = false, debug = false arguments's all = ["main.en", "lib.en"] ) (========================================================================) ( COMMAND-LINE ARGUMENTS ) (========================================================================) Print "=== Arguments Properties Demo ===". (Access argument count) a number called argc is arguments's count. Print "Number of arguments: ". Print the argc. (The program name is arguments's name) a text called program is arguments's name. Print "Program name: ". Print the program. (Access first user argument with arguments's first) If arguments's count is greater than 1 then, a text called arg1 is arguments's first, Print "First user argument: {arg1}". (Check if arguments were provided) Print "". If arguments's empty then, Print "No user arguments provided.". Otherwise, Print "User arguments were provided.". (Access last argument) a text called lastarg is arguments's last. Print "Last argument: ". Print the lastarg. (========================================================================) ( ENVIRONMENT VARIABLES ) (========================================================================) Print "". Print "=== Environment Properties Demo ===". (Access environment variable by name using 's syntax) a text called home is environment's "HOME". Print "Home directory: ". Print the home. a text called user is environment's "USER". Print "Current user: ". Print the user. a text called shell is environment's "SHELL". Print "Shell: ". Print the shell. (Check if variable exists) If the environment variable "DEBUG" exists then, Print "Debug mode is enabled via environment.". Otherwise, Print "DEBUG environment variable not set.". (Environment variable count) Print "". a number called envcount is environment's count. Print "Total environment variables: ". Print the envcount. (First environment variable) a text called env1 is environment's first. Print "First env var: ". Print the env1. (========================================================================) ( PRACTICAL EXAMPLE: A GREETER ) (========================================================================) Print "". Print "=== Practical Example ===". (A program that greets the user, using argument or environment variable) a text called greetname is "World". (Priority: 1. Command line argument, 2. Environment variable, 3. Default) If arguments's count is greater than 1 then, the greetname is arguments's first. But if the environment variable "GREET_NAME" exists then, the greetname is environment's "GREET_NAME". Print "Hello, ". Print the greetname. Print "!".
Timer example - measuring job duration
(Timer example - measuring job duration) Print "Starting job...". Create a timer called 'job timer'. Start the 'job timer'. (... do work ...) Wait 1 second. Print "Seconds elapsed so far: ". Print the 'job timer''s elapsed seconds. Wait 500 milliseconds. Stop the 'job timer'. Print "Finished the job in: ". Print the 'job timer''s duration in seconds. Print " seconds". (Access raw timestamps) Print "Started at unix time: ". Print the 'job timer''s 'start time'. Print "Stopped at unix time: ". Print the 'job timer''s 'end time'. (Get current date/time components) Print "Current date and time:". Get current time into now. Print " Hour: ". Print the now's hour. Print " Minute: ". Print the now's minute. Print " Second: ". Print the now's second. Print " Day: ". Print the now's day. Print " Month: ". Print the now's month. Print " Year: ". Print the now's year. (Alternative: inline current time) Print "It is currently hour ". Print current time's hour. Print " of the day.".
Calculating Pi using the Nilakantha Series
(Calculating Pi using the Nilakantha Series) (A beautiful infinite series that converges to π) (π = 3 + 4/(2×3×4) - 4/(4×5×6) + 4/(6×7×8) - ...) Print "The Quest for Pi". Print "================". Print "". Print "Using the Nilakantha series, we shall approximate". Print "the most famous constant in mathematics...". Print "". (Our approximation begins with three) a float pi is 3.0. (The denominator starts at two and grows by two each step) a float denominator is 2.0. (We alternate between adding and subtracting) a float direction is 1.0. (Count our iterations) a int steps is 0. (The beautiful dance of convergence) While steps is less than 500000, (Calculate the three consecutive numbers for this term) a float called Ist is the denominator, a float called IInd is the denominator add 1.0, a float called IIIrd is the denominator add 2.0, (The denominator is their product) a float called product is the Ist times the IInd, the product is the product times the IIIrd, (Calculate this term of the series) a float term is 4.0 divide product, the term is term times direction, (Add this term to our approximation) the pi is pi add term, (Flip the direction for the next term) the direction is 0.0 subtract direction, (Move to the next triple of numbers) the denominator is denominator add 2.0, increment the steps. Print "". Print "After 500,000 terms of the series:". Print "". Print " Calculated pi:". Print pi. Print "". Print " Actual pi:". Print " 3.14159265358979323846...". Print "". Print "(64-bit floats give us about 15 digits of precision)".
Conway's Game of Life on a 40x20 toroidal grid, the entire generation loop driven by a single loop-expansion statement and timed with a timer.
(======================================================================) ( VOX // CONWAY'S GAME OF LIFE -- written as English sentences, ) (======================================================================) a number called WIDTH is 40. a number called HEIGHT is 20. a number called GENERATIONS is 14. a buffer called grid is 800 bytes in size. a buffer called grid2 is 800 bytes in size. To wrap with a number called c and a number called d and a number called m. Return a number, {{{c subtract 1} add d add m} modulo m} add 1. To 'cell index' with a number called r and a number called c. Return a number, {{r subtract 1} multiply WIDTH} add c. To 'alive neighbors' with a number called r and a number called c. a number called tally is 0. a number called nr is 0. a number called nc is 0. a number called v is 0. a number called idx is 0. the nr is wrap of r and -1 and HEIGHT. the nc is wrap of c and -1 and WIDTH. the idx is 'cell index' of nr and nc. the v is byte idx of grid. If v is equal to 1 then, the tally is tally add 1. the nr is wrap of r and -1 and HEIGHT. the nc is wrap of c and 0 and WIDTH. the idx is 'cell index' of nr and nc. the v is byte idx of grid. If v is equal to 1 then, the tally is tally add 1. the nr is wrap of r and -1 and HEIGHT. the nc is wrap of c and 1 and WIDTH. the idx is 'cell index' of nr and nc. the v is byte idx of grid. If v is equal to 1 then, the tally is tally add 1. the nr is wrap of r and 0 and HEIGHT. the nc is wrap of c and -1 and WIDTH. the idx is 'cell index' of nr and nc. the v is byte idx of grid. If v is equal to 1 then, the tally is tally add 1. the nr is wrap of r and 0 and HEIGHT. the nc is wrap of c and 1 and WIDTH. the idx is 'cell index' of nr and nc. the v is byte idx of grid. If v is equal to 1 then, the tally is tally add 1. the nr is wrap of r and 1 and HEIGHT. the nc is wrap of c and -1 and WIDTH. the idx is 'cell index' of nr and nc. the v is byte idx of grid. If v is equal to 1 then, the tally is tally add 1. the nr is wrap of r and 1 and HEIGHT. the nc is wrap of c and 0 and WIDTH. the idx is 'cell index' of nr and nc. the v is byte idx of grid. If v is equal to 1 then, the tally is tally add 1. the nr is wrap of r and 1 and HEIGHT. the nc is wrap of c and 1 and WIDTH. the idx is 'cell index' of nr and nc. the v is byte idx of grid. If v is equal to 1 then, the tally is tally add 1. Return a number, tally. (print row is single-argument (row) -- a loop-expansion candidate.) (Each cell is appended straight into a line buffer rather than printed) (character-by-character: "but if" is print-only -- confirmed by testing,) (it rejects "append" -- and printing per-character can't suppress the) (newline inside a but-if chain either, so building the row as one buffer) (and printing it once sidesteps both limits at once.) To 'print row' with a number called row. a buffer called line is 64 bytes in size. For each col from 1 to WIDTH, a number called idx is 'cell index' of row and col, a number called v is byte idx of grid, If v is equal to 1 then, Append "#" to line. Otherwise, Append "." to line. the v is v add 0. Print line. (step cell takes a row and a column, because no cell's fate depends on) (any other cell in its row. One chained expansion then walks the whole) (grid: the row clause is the outer loop, the column clause the inner.) To 'step cell' with a number called row and a number called col. a number called idx is 'cell index' of row and col. a number called n is 'alive neighbors' of row and col. a number called cur is byte idx of grid. a number called nextval is 0. If cur is equal to 1 and n is equal to 2 then, the nextval is 1. If cur is equal to 1 and n is equal to 3 then, the nextval is 1. If cur is equal to 0 and n is equal to 3 then, the nextval is 1. Set byte idx of grid2 to nextval. (run generation is single-argument (gen) -- folds header/render/step/copy) (into one homemade function, which is what lets the entire simulation) (drive loop collapse into a single loop-expansion statement below.) To 'run generation' with a number called gen. Print "-- Generation {gen} of {GENERATIONS} --". 'print row' of each row from 1 to HEIGHT. 'step cell' of each row from 1 to HEIGHT and each col from 1 to WIDTH. copy grid2 to grid. a number called seedIdx is 0. (--- Seed: an R-pentomino (chaotic for ~1100 gens in an infinite grid) ---) the seedIdx is 'cell index' of 9 and 20. Set byte seedIdx of grid to 1. the seedIdx is 'cell index' of 9 and 21. Set byte seedIdx of grid to 1. the seedIdx is 'cell index' of 10 and 19. Set byte seedIdx of grid to 1. the seedIdx is 'cell index' of 10 and 20. Set byte seedIdx of grid to 1. the seedIdx is 'cell index' of 11 and 20. Set byte seedIdx of grid to 1. (--- Seed: a glider drifting diagonally in the corner ---) the seedIdx is 'cell index' of 2 and 3. Set byte seedIdx of grid to 1. the seedIdx is 'cell index' of 3 and 4. Set byte seedIdx of grid to 1. the seedIdx is 'cell index' of 4 and 2. Set byte seedIdx of grid to 1. the seedIdx is 'cell index' of 4 and 3. Set byte seedIdx of grid to 1. the seedIdx is 'cell index' of 4 and 4. Set byte seedIdx of grid to 1. Print "========================================". Print " VOX -- Conway's Game of Life". Print " 40x20 toroidal grid, R-pentomino + glider". Print "========================================". Create a timer called clock. Start the clock. (The entire simulation drive loop, collapsed to one line: loop expansion) (calling a homemade function once per generation, no manual counter.) 'run generation' of each gen from 1 to GENERATIONS. Stop the clock. Print "========================================". Print "Ran {GENERATIONS} generations on an 800-cell grid in:". Print the clock's duration in milliseconds. Print "milliseconds -- native assembly, no VM, no GC, no interpreter.".
A process supervisor with no shell and no coreutils: fork, poll-reap, signal, and decode the exit status.
(A supervisor for child processes, written entirely in Vox - no shell, no coreutils, and no guessing. The parent starts two jobs. The first does a scrap of work and finishes on its own; the second hangs, so the supervisor runs out of patience, kills it, and reports how it died. Every step is a syscall the language makes a sentence: `fork the process`, `reap ... without waiting`, `Send signal`, and `the reaped status`.) (The kernel packs how a child ended into one status word. The compiler knows nothing about that encoding and does not need to: decoding it is ordinary Vox, kept in a small library in this repo.) (Decode the status inline with the kernel's own encoding - the low seven bits are the terminating signal, the next eight the exit code. Deliberately no `see`: `the reaped status` is a complete compiler feature, and this test must pass with nothing installed at all.) To 'exit code of' with a number called status. Return a number, status divide 256 modulo 256. To 'signal of' with a number called status. Return a number, status bit-and 127. To crashed with a number called status. a number called 'terminating signal' is status bit-and 127. Return a boolean, 'terminating signal' is not 0. To 'exited normally' with a number called status. a number called 'terminating signal' is status bit-and 127. Return a boolean, 'terminating signal' is 0. (A job that has not finished within this long is a job that never will.) a number called 'the patience in milliseconds' is 300. (Poll the child instead of blocking on it, so the clock is still being read while the child runs. One non-blocking reap answers all three questions at once: the child's own pid means it has finished, a zero means it is still running, and a negative means there was never such a child.) To supervise with a number called pid. a timer called clock. Start the clock. a boolean called 'the child is still running' is true. a boolean called 'the child ran out of time' is false. While 'the child is still running', a number called 'the reaped child' is reap child pid without waiting, If 'the reaped child' is pid then, Set 'the child is still running' to false. If 'the child is still running' then, a number called 'the milliseconds waited' is the clock's elapsed in milliseconds, If 'the milliseconds waited' is greater than 'the patience in milliseconds' then, Send signal 9 to child pid, Set 'the reaped child' to reap child pid, Set 'the child is still running' to false, Set 'the child ran out of time' to true. If 'the child is still running' then, Wait 5 milliseconds. Stop the clock. a number called status is the reaped status. If 'the child ran out of time' then, Print " it outstayed its welcome, so it was sent signal 9". If crashed of status then, Print " it died by signal {'signal of' of status}". If 'exited normally' of status then, Print " it finished on its own with exit code {'exit code of' of status}". Print "The tidy job:". a number called 'the tidy child' is fork the process. If 'the tidy child' is 0 then, (In the child: a scrap of work, then an exit code for the parent to read back.) Wait 20 milliseconds, Exit 3. supervise with 'the tidy child'. Print "The stuck job:". a number called 'the stuck child' is fork the process. If 'the stuck child' is 0 then, (In the child: hang for far longer than the supervisor will allow.) Wait 30 seconds, Exit 0. supervise with 'the stuck child'. (Signal 0 delivers nothing and only asks whether a process is there at all, which is the safe way to find out that a pid is gone.) Send signal 0 to process 'the stuck child'. On error print "The stuck job is gone: no process answers to its pid.".
vsh - a minimal interactive shell
(vsh - a minimal interactive shell) (Reads a command line, splits it into whitespace-separated tokens, forks, and executes the command with its arguments. Commands are tried as given, then under /bin and /usr/bin. Type "exit" to quit. Tokens are collected byte-by-byte into a scratch buffer, then turned into an argv-ready text with a format-string initializer - "{word}" materializes the buffer's bytes as a fresh NUL-terminated string, so every token owns its own memory and the scratch buffer can be reused.) A text called 'Program Version' is "0.1.0". Open a file at 0 for reading called stdin. Create a buffer called line. a buffer called word is 256 bytes in size. While true, print "vsh $ " without newline, clear line, read line from stdin into line, if line is empty then, exit 0. (A trailing separator guarantees the last token is flushed even if the line arrived without a newline) append " " to line, a list called argv is [], a text called cmd is "", a text called tok is "", a number called have_cmd is 0, a number called n is line's size, a number called i is 1, a number called b is 0, a number called sep is 0, a number called flush is 0, clear word, (Scan the line. Non-separator bytes accumulate into word; hitting a separator with a non-empty word finishes one token. The first token is the command, the rest become its arguments.) While i is less than or equal to n, set b to byte i of line, set sep to 0, if b is 32 then, set sep to 1. if b is 10 then, set sep to 1. if b is 9 then, set sep to 1. if sep is 0 then, set byte {word's size add 1} of word to b. set flush to 0, if sep is 1 and word's size is greater than 0 then, set flush to 1. if flush is 1 then, a text called tok is "{word}". (Order matters: append while have_cmd is already 1, THEN claim the first token as the command - reversing these would also append the command itself to its argument list) if flush is 1 and have_cmd is 1 then, append tok to argv. if flush is 1 and have_cmd is 0 then, set cmd to tok, set have_cmd to 1. if flush is 1 then, clear word. increment i. a number called pid is 0, if cmd is "exit" then, exit 0. if have_cmd is 1 then, set pid to fork the process. (Child: execve only returns on failure, so falling through to the next Execute IS the search order: as given, /bin, /usr/bin) if pid is 0 and have_cmd is 1 then, Execute cmd with arguments argv, a text called binpath is "/bin/{cmd}", Execute binpath with arguments argv, a text called usrpath is "/usr/bin/{cmd}", Execute usrpath with arguments argv, print "vsh: {cmd}: command not found", exit 127. (Parent: wait for the child so the prompt returns in order) if pid is greater than 0 then, set reaped to reap process pid. set flush to 0.
A door-and-elevator control system: three booleans, combined with 'and' and 'not', decide whether it is safe to open the door.
print "=================================================================================" Print "This program demonstrates how a simple control system can be written in English.". Print "The door will open if: door is not open, elevator not moving, and lift is not full.". print "" print "================================== Conditions ===================================" a boolean called door_open is true. a boolean called lift_moving is true. a boolean called lift_full is true. If the door_open is true then, Print "Door is open.". Otherwise, Print "Door is closed.". If lift_moving is true then, Print "Elevator is moving.". Otherwise, Print "Elevator is not moving.". If lift_full then, Print "Elevator is full.". Otherwise, Print "Elevator is not full.". print "" print "==================================== Action =====================================" if door_open, lift_moving, and lift_full are not true then, Print "Opening the Door.". Otherwise, Print "Not opening the Door.". if door_open and lift_moving then, Print "EMERGENCY STOP".
Initramfs Setup Example
(Initramfs Setup Example) (Demonstrates proposed mount and related syscalls for initramfs operations) A text called 'Program Version' is "0.1.0". (Setup script for early userspace initialization) Print "Initramfs setup starting...". (Create essential directories) Create a directory called "/proc". Create a directory called "/sys". Create a directory called "/dev". Create a directory called "/dev/pts". Create a directory called "/dev/shm". Create a directory called "/run". Create a directory called "/tmp". Create a directory called "/newroot". (Mount virtual filesystems) Mount "proc" at "/proc" with type "proc". On error print "Failed to mount /proc", exit 1. Mount "sysfs" at "/sys" with type "sysfs". On error print "Failed to mount /sys", exit 1. Mount "devtmpfs" at "/dev" with type "devtmpfs". On error print "Failed to mount /dev", exit 1. Mount "devpts" at "/dev/pts" with type "devpts" with options "gid=5,mode=620". On error print "Failed to mount /dev/pts", exit 1. Mount "tmpfs" at "/dev/shm" with type "tmpfs". On error print "Failed to mount /dev/shm", exit 1. Mount "tmpfs" at "/run" with type "tmpfs". On error print "Failed to mount /run", exit 1. Mount "tmpfs" at "/tmp" with type "tmpfs". On error print "Failed to mount /tmp", exit 1. (Create device nodes if needed) Create a device node called "/dev/null" with type "c" major 1 minor 3. Create a device node called "/dev/zero" with type "c" major 1 minor 5. Create a device node called "/dev/random" with type "c" major 1 minor 8. Create a device node called "/dev/urandom" with type "c" major 1 minor 9. (Set up symlinks for compatibility) Create symbolic link from "/proc/self/fd" to "/dev/fd". Create symbolic link from "/proc/self/fd/0" to "/dev/stdin". Create symbolic link from "/proc/self/fd/1" to "/dev/stdout". Create symbolic link from "/proc/self/fd/2" to "/dev/stderr". (Wait for root device) Print "Waiting for root device...". a text called root_device is "/dev/sda1". (Check if root device exists) While the root_device is not available, Sleep for 100 milliseconds. Print "." without newline. Print "". (Mount the real root filesystem) Print "Mounting root filesystem...". Mount the root_device at "/newroot" with type "ext4". On error print "Failed to mount root filesystem", exit 1. (pivot_root requires put_old to exist INSIDE the new root - it lives on the freshly mounted filesystem, so it can only be created now) Create a directory called "/newroot/oldroot". On error print "Failed to create /newroot/oldroot", exit 1. (Move virtual filesystems to new root) Mount "/proc" at "/newroot/proc" with type "none" with options "move". Mount "/sys" at "/newroot/sys" with type "none" with options "move". Mount "/dev" at "/newroot/dev" with type "none" with options "move". Mount "/run" at "/newroot/run" with type "none" with options "move". (Switch to new root using pivot_root) Print "Switching to new root...". Pivot root to "/newroot" with old root "/newroot/oldroot". On error print "Failed to pivot_root", exit 1. (Change to new root directory) Change directory to "/". On error print "Failed to chdir to new root", exit 1. (Release the old initramfs root. Lazy detach: the mount is still busy while this program runs from it, so MNT_DETACH defers the release until the last user - this process - is gone.) Unmount "/oldroot" lazily. On error print "Failed to detach old root", exit 1. (Execute init) Print "Executing init...". Execute "/sbin/init" with arguments []. On error print "Failed to execute init", exit 1. (Should never reach here) Print "Initramfs setup complete. Exiting.". Exit 0.
Test exit code
(Test exit code) exit 42.
Test universal loop expansion: each...from works with any action
(Test universal loop expansion: each...from works with any action) To double of a number called x. Return a number, x multiply 2. a list called nums is [1, 2, 3]. print "=== Print each ===". print each n from nums. print "=== Function each ===". print double of each number from nums. print "=== Done ===".
Print "test".
Print "test".
A small shared library, built with vox --shared, exporting an addition function and a greeter.
(A small shared library, built with `vox --shared`. Its companions are mathkit_consumer.vox, which consumes it from Vox through `see` of a `.lib`, and mathkit_driver.asm, which calls it from a foreign host. See LANGUAGE.md, "Shared libraries". vox examples/mathkit_lib.vox --shared -o examples/libmathkit.so) Library mathkit version "1.0". To 'add two numbers' with a number called aa and a number called b. Return a number, aa add b. To greet. Print "hello from mathkit".
Consumes the mathkit shared library through its .lib file: 'see' resolves it, and the call links against the compiled .so.
(Consumes the mathkit library through its `.lib` — the Vox consumption path. Builds and runs against the finished compiler: `see` of a `.lib` resolves the library, `add two numbers` is type-checked against the `.lib` table of contents, and the call links against the `.so`. See LANGUAGE.md, "Consuming a library". vox examples/mathkit_lib.vox --shared -o examples/libmathkit.so vox examples/mathkit_consumer.vox -o examples/mathkit_consumer ./examples/mathkit_consumer -> 7) see mathkit version "1.0" from "./libmathkit.lib". a number called sum is 'add two numbers' of 3 and 4. Print the sum.