INSPIRED BY TSODING ON YOUTUBE:
-https://www.youtube.com/c/TsodingDaily
CHANGE LOG:
- Complete Rework
- ADIL (A Dumb Intermediate Language)
- Returns
- New 'const' keyword
- Arrays
- Address Minipulation
- Compiler Commands
- Lots of syscall wrappers
- And much more!
PATCH 1 (Flags Rework) CHANGE LOG:
- Flag system rework for actually dynamic flags
- More flags :3
PATCH 2 (Static Linking) CHANGE LOG:
- Static linking (;;include static)
- dead code elimintation
- asm function
- unsafe keyword (gets rid of enviroment for functions)
- started stdlib
- print functions are in stdlib
Also incase it wasn't obvious this language is MEGA UNSAFE. So use this thing recreationly for now, change whatever you'd like, and please give suggestions and issues with the language. I know about a lot of the bugs and I am and will work to fix them, but if you do give this litte project the time of day I'd love it if you'd help with bug reporting or ways to fix very unorganized and faulty systems (aka this thing as a whole). Anyway have fun fiddling with this little project and thank you for checking out my work!!!
Copy the shell commands in the file ADPL.sh into your bash profile file to use the ADPL commands and put these files in the directory /home/$USR/ADPL/.
usr@penguin:~$ adpl --help
usr@penguin:~$ adpl -f <file>.adpl
usr@penguin:~$ ./<file>
For more information on the adpl command use the help flag. Note that the build and debug flags are for development.
The entry point is the main function and additional documentation is in the file FUNCTIONS.txt.
To define a function you put the keyword 'fn', the function name, and then the arguments.
fn foo(UINT x UINT y BOOL z)
# code
end
Currently you can only have 6 arguments and you need to specify the types of the arguments. To close a block you need to put the end keyword.
To call a function you put the name of the function and then the args wrapped in parentheses.
;;include static 'stdlib'
fn main()
const x 'Hello ADPL!'
writeln(x)
end
You simply put the keyword ret, then the variable/value you'd like to return, the return type after the function arguments!!!
;;include static 'stdlib'
fn foo() UINT
ret 69
end
fn main()
let a foo()
writeln(a)
end
Function descriptors go infront of the 'fn' keyword and modifies properties of the function. Currently the only function descriptor is 'unsafe' and is mainly used to write purely asm functions as you can see in the standard library. USE AT YOUR OWN RISK.
unsafe fn add() UINT
asm(' mov eax, edi\n add eax, esi\n ret\n')
end
Variables are defined with the keyword 'let' and then the to value assign to the vaiable. This value can be a literal value or another variable.
let a 69
let b 420
Variables can also have the value of expressions and function calls by putting the expression after the vaiable, reassigning is putting the value after the variable.
let a 34
let b 35
let c 34 + 35
a c
They are stored within the function scope, which means that a variable defined in an if or loop can be acessed anywhere the function, this is subject to change though. This maybe considered a feature or a lazy design choice of which it's both... either way it's how variables work in this language. Also be aware that variables of the same name have to hav ethe same type, this will be patched out soon!
These are stored gloablly in the .data and .bss sections of the asm.
;;include static 'stdlib'
const string 'Hello World!'
fn main()
writeln(string)
new_line()
end
Note constants can also be a way of memory allocation. To allocate memory with a constant use the const key word with the amount of bytes you want to allocate in square brackets. Like this.
const[100] buffer
fn main()
let buffer.ptr ptr(buffer)
end
And then you can get the begining of the memory allocated with taking that name and making it a pointer.
A hash tag is the comment symbol, no multi-line comments yet because of the lack of a need for them.
fn bar()
let x 69 # nice
let y 420 # dank
end
They have the type keyword of 'UINT'. They are just postive whole numbers, currently they are the most supported type. They are 32-bit intergers; nothing special.
let x 69
let y 420
let z 13
Name | OP Symbol | Use |
---|---|---|
Add | + | Adds two uints. (a + b) |
Subtract | - | Subracts two uints. (a - b) |
Multiply | * | Multiplies two uints. (a * b) |
Divide | / | Divides two uints. (a / b) |
Mod | % | Outputs the remainder of two uints. (a % b) |
Decrement | -- | Subracts by 1. (a--) |
Increment | ++ | Adds by 1. (a++) |
Equal | == | True if a equals b. (a == b) |
Less Eql. | <= | True if a is less than or equal to b. (a <= b) |
Great Eql. | >= | True if a is greater than or equal to b. (a >=b) |
Greater | > | True if a is greater than b. (a > b) |
Less | < | True if a is less than b. (a < b) |
Not Equal | != | True if a does not equal b. (a != b) |
Stored in a 8-bit register, have the type keyword of 'BOOL', and can be true or false. They are the output of all comparison operators and are also a standalone type. The kewords 'true' and 'false' are also used to set their value.
let a true
let b false
Name | OP Symbol | Use |
---|---|---|
And | && | True if both are true. (a && b) |
Or | || | True if one or both of them are true. (a || b) |
Xor | -| | True if ONLY one of them is true. (a -| b) |
Not | ! | Flips the value of a boolen. (a!) |
These are ascii chacters, use the type keyword of 'CHAR', and they are stored in an 8-bit register. The are inbetween single quotes and are only a single character.
;;include static 'stdlib'
fn main()
write('H')
write('e')
write('l')
write('l')
write('o')
write(' ')
write('W')
write('o')
write('r')
write('l')
write('d')
writeln('!')
end
Name | OP Symbol | Use |
---|---|---|
Equal | == | True if a equals b. (a == b) |
Not Equal | != | True if a does not equal b. (a != b) |
Uses the 'PTR' type keyword and stored in a 64-bit register. These are from using the 'ptr()' function. The current use is in syscalls and memory accessing.
fn main()
let NR 1 # Write ID
let stdout 1 # Stdout directory
let size 1 # String size
let char 'H' # String
let char_ptr(ptr(char)) # Pointer to String
syscall(NR stdout char size) # Write String to stdout
end
This is a mock-up of the internal write function using a syscall and a pointer.
Name | OP Symbol | Use |
---|---|---|
Decrement | -- | Subracts by 1. (a--) |
Increment | ++ | Adds by 1. (a++) |
Add | + | Adds a uint to a pointer (a+b) |
Sub | - | Subtracts uint from pointer (a-b) |
At Pointer | @ | Used to get the value at the address of a pointer (@TYPE a) |
These can only be constants and cannot be literals or reassigned, right now they are simply used to write to the terminal easier. Despite this I am planning to expand upon this type by making a dynamic string or a char array.
;;include static 'stdlib'
const string0 'Hello World!'
const string1 'Okay, this is a bit more normal...'
fn main()
let string_ptr ptr(string0)
write(string_ptr string0.len)
new_line()
string_ptr ptr(string1)
write(string_ptr string1.len)
end
An array is defined with as a const and cannot be initialized with any data. To define one type const, the amount of bits that you want to allocate in square brackets, and then the variable name. Once you do this you can make it a pointer and it can be interfaced with as an address!
fn main()
# allocate 4x the length because UINT is 4 bytes
const[100] fibnumbers
let array_length 25
let pointer ptr(fibnumbers)
let current pointer
let index 2
let bytes_per 4
# Fill first two values with ones
@UINT current 1
current pointer + bytes_per
@UINT current 1
loop(index < array_length)
# get value 1 element back
let pos index - 1
pos pos * bytes_per
current pointer + pos
let a @UINT current
# get value 2 elements back
pos index - 2
pos pos * bytes_per
current pointer + pos
let b @UINT current
# save value
let c a + b
pos index * bytes_per
current pointer + pos
@UINT current c
index++
end
end
Using arrays is very verbose for now, but that will change soon!
If only runs the code within its block if the condition within the parentheses is met.
;;include static 'stdlib'
let x 10
let y 10
if(x==y)
const msg 'X equals Y'
writeln(msg)
end
Else only activates if the previous ifs and else ifs were not met.
;;include static 'stdlib'
let x 49
if(x>50)
x++
else
writeln(69)
end
Else if only activates if the previous ifs and else ifs were not met and the condition in the else if is met.
;;include static 'stdlib'
if(false)
x++
end
else if(true)
writeln(69)
end
Loop reruns the code within the loop until the condition is false.
Here is a program that writes the nth fibonacci number.
;;include static 'stdlib'
fn main()
let n 10
let x 1
let y 1
let i 0
loop(i<n)
let z x + y
x y
y z
i++
end
writeln(x)
end
These are just like pre-processor directives in C. The current cones are more for the asm compilation than anything, but in the future I hope to expand upon them more.
Name | Use |
---|---|
global | Used to make functions (and possibly consts) available in dynamically linked files. NO USE CASE CURRENTLY |
include | Links an .adpl file to the current file. Has two include types, static and dynamic. Only static is implemeted right now. |
extern | Tells the compiler a function was called that was from a dynamically linked file. NO USE CASE CURRENTLY |
define | Replaces as all instances of the defined var with the value. EX: ;;define STDOUT 1 |
Currently you can only link statically. Files with .adpl are user files in the cwd or in a specified path. Files without an extension are library files from ADPL/include.
;;include static 'stdlib'
This language is built for Debian Linux and compiles to NASM.
Sorry for any inconvenience this may cause.
These are goals for this language, the long and short term. I can't promise these things because of life and school, but these are my hopes and aspirations for this project.
- Make strings more dynamic instead of just a constant.
- Add structs (maybe).
- Bug fix and refactor how types are handled.
- Give bools, chars, pointers, and strings more operations.
- Linking.
- Self-Hosting.
- A standard library.
- Examples other than Hello_World.adpl:
- Game of Life
- Simple Web Server
- MAYBE A graphical interface and window library
- Additional libraries.
- Deadcode removal and Optimization step.