XMLang
Overview
XMLang is a programming language created by Balt (talk), made to be written entirely within an XML document.
It's made to be easily programmable using Emmet snippets, as this can heavily speed up development.
Tags
As the program is written as an XML document, all elements are done with tags.
Each of these tags can have:
- Child tags
- An ID
- Inner text
Any tags that link to a section aren't actually tag name, but act the same way for any tags under that section.
The included tags are below:
Name | Requirements | Description | ||
---|---|---|---|---|
ID | Text | Children | ||
program
|
✗ | ✗ | ✓ | The root node of the program. Should always be at the root, and have only one. |
access
|
? | ✗ | ? | Access a variable or part of one. If given a variable id, it accesses that variable. If not, it accesses the first child. If given another child, this is used to index into the value. An error is raised if the value isn't indexable. |
assign
|
✓ | ✗ | ? | Assign a variable. If this doesn't have children, the variable is initialized to null .If this does have children, the inner value is evaluated and the variable is set to that, again defaulting to null if it doesn't return a value.Like access, if given another child, this is used to index into the value. An error is raised if the value isn't indexable. A dictionary is indexable by key. |
block
|
? | ✗ | ✓ | Evaluates its children lazily, returning the first value returned from a child. An empty block (<block /> ) is a no-op.
|
func
|
? | ✗ | 2 | Requires an args and another child to create a function.If given an ID, this is the same as <assign id="<id>"><func> .If not, creates a function type variable. When called, the arguments are added to a duplicate of the current interpreter state and the inner block is evaluated. |
pair
|
✗ | ✗ | 2 | Is only valid as a child of a dict . Denotes a key-value pair.
|
import
|
✓ | ✗ | ✗ | Imports a file, or a built-in library if preceded with a ! . Files are imported relative to the root of the program.As there are no namespaces, all public variables are added to the scope with their respective name. |
public
|
✓ | ✗ | ✗ | Publicizes a variable, making it available if this file is imported from another file. |
delete
|
✓ | ✗ | ✗ | Deletes a variable. Raises an error if the variable is public. |
return
|
✗ | ✗ | 1 | Explicitly returns a value. Never actually needed, but may make code slightly easier to understand. |
binop
|
✗ | ✗ | 2 | Executes a binary operator on two values and returns the result. |
unop
|
✗ | ✗ | 1 | Executes a unary operator on a value and returns the result. |
try
|
✗ | ✗ | 2 | If the first child evaluates without error, its value is returned. Otherwise, the second child is evaluated and returned. |
args
|
✗ | ✗ | ✓ | All children must be of type arg . Is only valid as the first child of a func .
|
arg
|
✓ | ✗ | ✗ | Denotes an argument for a function. Is only valid as a child of an args .
|
call
|
? | ✗ | ? | Calls the variable with the passed ID, or if not given one, the first child. Any other children are passed as arguments. Raises an error if it's not a function. |
if
|
✗ | ✗ | ✓ | For every 2 children, calls the second and returns if the first one evaluates to a true .If there's an odd number of children, the last one is called if none of the above ones are. |
for
|
✓ | ✗ | 2 | Iterates through an indexable object. If given an integer, it iterates from 0 to that number. A variable with the set ID is set for each iteration, and is not deleted when the loop concludes. |
while
|
✓ | ✗ | 2 | Keeps looping the second child until the first child returns false .
|
type
|
✗ | ✓ | ? | Casts the child to the given type if it has one (except for arr/set/dict/func, as these already have children for their definition), or if it has no children, creates a literal value from its text. |
Types
XMLang has static typing, and only a few types. There are:
Name | Children | Description |
---|---|---|
int
|
✗ | Signed 64-bit integer. |
float
|
✗ | Double-precision floating-point number, as per IEEE 754 specification. |
bool
|
✗ | A 1-bit boolean value. |
str
|
✗ | An arbitrary length string. Multi-byte characters should be represented correctly. Immutable. |
arr
|
✓ | An array of any type of variable. All children are evaluated and added in order of declaration. |
dict
|
✓ | A mapping of keys to values. In implementation, every variable type should be able to be both a key and a value. Expects pair for children while defining.
|
set
|
✓ | A unique, unordered set of elements. All children are evaluated and added. |
func
|
✓ | A function, with args and an element to evaluate when called.These can be either defined by the user or imported from a built-in library. When evaluating the inner block with call , the arguments are added to scope respective to their order in args .
|
null
|
✗ | A null value. |
break
|
✗ | Breaking constant. Return this inside a loop to break out. |
continue
|
✗ | Continuing constant. Return this inside of a loop to jump to the next iteration. |
Binary Operators
XMLang has many binary operators. There are:
Name | Description |
---|---|
add
|
Adds two numbers together, casting to float if needed. If an array or set is given, the second value is appended. If two strings are given, they're concatenated. |
sub
|
Subtracts two numbers, casting to float if needed. If an array and integer is given, the value at the given index is removed, and all sequential variables are moved left. If a set is given, the second value is removed from the set. If a dictionary is given, the key-value pair is removed with the second value as the key. |
mul
|
Multiplies two numbers, casting to float if needed. |
div
|
Divides two numbers, casting to float if needed. Errors if the right-hand value is 0. |
mod
|
Divides two numbers, returning the remainder, and casting to float if needed. Errors if the right-hand value is 0. |
pow
|
Raises a number to the power of another number. If two integers are supplied but the right hand is negative, returns a float. |
and
|
Takes the bitwise and of an integer/boolean. If two sets are supplied, returns the intersection. |
or
|
Takes the bitwise or of an integer/boolean. If two sets are supplied, returns the union. |
xor
|
Takes the bitwise xor of an integer/boolean. If two sets are supplied, returns where they don't intersect. |
or
|
Takes the bitwise or of an integer/boolean. If two sets are supplied, returns the union. |
shl
|
Shifts an integer's bits to the left by another integer. |
shr
|
Shifts an integer's bits to the right by another integer. |
eq
|
Returns whether or not two values are equal. |
ne
|
Returns whether or not two values aren't equal. |
lt
|
Returns whether or not a value is less than another. |
gt
|
Returns whether or not a value is greater than another. |
leq
|
Returns whether or not a value is less than or equal to another. |
geq
|
Returns whether or not a value is greater than or equal to another. |
Unary Operators
XMLang has a few unary operators. There are:
Name | Description |
---|---|
neg
|
Returns the numeric value * -1. |
not
|
Returns the bitwise not of a value. |
abs
|
Returns the absolute value of a value. |
Libraries
There are a few built-in libraries in XMLang, made to help with things that the language itself can't do.
These need to be implemented into an interpreter to make it a complete implementation, as these are a necessary part of the language.
Standard lib (std
)
Name | Args | Description |
---|---|---|
print
|
1 | Prints out the given value, without flushing stdout. |
println
|
1 | Prints out the given value, and a newline after, flushing stdout. |
flush
|
0 | Flushes stdout. |
range
|
3 | Creates an array holding a range of integers, over [a, b), stepping by c. Errors if c is 0, and steps backwards (still from a to b) if c is negative. If the range never ends, this returns empty. |
join
|
1 | Joins an array of strings, and gives the output as a string. Casts non-string values to strings. |
len
|
1 | Gets the length of an indexable value (arr , dict , set , or str ).
|
input
|
0 | Gets one line of input from stdin. Errors if it can't read from stdin. |
chr
|
1 | Converts an integer to its corresponding unicode character. Errors if it's invalid. |
ord
|
1 | Converts a one-length string to its corresponding unicode codepoint. |
radix
|
2 | Converts a number to a string with a base if given two integers, or the reverse if given an integer and a string. Errors if invalid. |
sleep
|
1 | Waits for the supplied amount of seconds. |
time
|
0 | Gets the current Unix timestamp, as a float. Errors if the current time is before 1/1/1970. |
type
|
1 | Returns the type of the supplied value, as a string. |
hash
|
1 | Returns the hash of the value. All values are hashable, and the implementation of the hashing algorithm is left to the interpreter. |
Math lib (math
)
Name | Type | Description |
---|---|---|
pi
|
float
|
Archimedes's constant. The ratio of a circle's circumference to its diameter. |
e
|
float
|
Euler's number. Defined as the derivative of e^x being e^x. |
inf
|
float
|
Infinity. Larger than any number. Can be negated. |
nan
|
float
|
Not a number. Given when the answer isn't representable by IEEE-754, or where the answer is indeterminate or undefined. |
Name | Args | Description |
---|---|---|
sin
|
1 | Trigonometric functions. Susceptible to floating point imprecision. |
cos
| ||
tan
| ||
asin
| ||
acos
| ||
atan
| ||
sinh
| ||
cosh
| ||
tanh
| ||
asinh
| ||
acosh
| ||
atanh
| ||
exp
|
1 | Raise a value to the power of e. More precise than doing it manually. |
ln
|
1 | Takes the natural log of a value. More precise than doing it manually. Negative values have their absolute value calculated, then the sign is flipped. |
log2
|
1 | Takes the log of a value with base 2. More precise than doing it manually. Negative values have their absolute value calculated, then the sign is flipped. |
log10
|
1 | Takes the log of a value with base 10. More precise than doing it manually. Negative values have their absolute value calculated, then the sign is flipped. |
log
|
2 | Takes the log of a value with a given base. Negative values have their absolute value calculated, then the sign is flipped. |
sqrt
|
1 | Gets the square root of a value. More precise than doing it manually. |
ceil
|
1 | Gets the ceiling of a value, i.e. rounding up. |
floor
|
1 | Gets the floor of a value, i.e. rounding down. |
round
|
1 | Rounds to the nearest integer. |
trunc
|
1 | Removes the fractional part of a decimal. This acts like floor for >0, and ceil for <0. |
fract
|
1 | Returns the fractional part of a decimal. |
sign
|
1 | Returns the sign of a number, or NaN for NaN. 0 is positive. |
deg
|
1 | Converts from radians to degrees. More precise than doing it manually. |
rad
|
1 | Converts from degrees to radians. More precise than doing it manually. |
atan2
|
2 | Two-argument arc-tangent. |
hypot
|
2 | Returns the length of a hypotenuse of a right triangle with the given legs. Pythagoras's theorem. |
max
|
2 | Returns the largest of two values. |
min
|
2 | Returns the smallest of two values. |
lerp
|
3 | Linear interpolation between two values, with a third being a factor of interpolation. |
Random lib (rand
)
Name | Args | Description |
---|---|---|
rand
|
1 | Returns a random value, from 0 to 1. |
shuffle
|
1 | Randomly shuffles an array. |
choice
|
1 | Returns a random choice from an array. |
sample
|
1 | Returns a given amount of random values from 0 to 1, in an array. |
File IO lib (io
)
Name | Args | Description |
---|---|---|
read
|
1 | Reads the given filepath and returns its contents as a string. Errors if unable to read. |
read-bin
|
1 | Reads the given filepath and returns its contents as an array of integers. Errors if unable to read. |
write
|
1 | Overwrites or creates a given file with a string. Errors if unable to write. |
write-bin
|
1 | Overwrites or creates a given file with an array of integers. Errors if unable to write. Integers not in the 0x00 to 0xFF range are under/overflown. |
Examples
Hello world
<program> <import id="!std" /> <call id="println"> <str>Hello, world!</str> </call> </program>
Cat
<program> <import id="!std" /> <call id="println"> <call id="input"> </call> </program>
Truth machine
<program> <import id="!std" /> <while> <bool>true</bool> <try> <block> <assign id="n"> <int> <call id="input" /> </int> </assign> <break /> </block> <continue /> </try> </while> <if> <eq> <access id="n" /> <int>0</int> </eq> <call id="println"> <str>0</str> </call> <eq> <access id="n" /> <int>1</int> </eq> <while> <bool>true</bool> <call id="println"> <str>1</str> </call> </while> <call id="println"> <str>Not 0 or 1</str> </call> </if> </program>