3.6 KiB
Langatator
A very basic interpreted programming language.
Background
The goal of this project is to create a simple implementation of a BASIC-like language just to learn a few things along the way and practice my C programming skills.
No need to do complex thing, just to create a simple interpreted language that can be used to do some arithmetics and create for example a number guessing game.
I didn't really study how others languages works beforehand, I'm just guessing how I'm implementing things so that I can make mistakes to learn from.
Progress
- 2022-04-29 : Implementation of a basic evaluator engine to evaluate arithmetic expressions and call functions
ToDo List:
- pow operator
- binary operators
- implement basic math functions
- implement random_int(min, max)
- implement print_number(message)
- add unit tests
- allow to set variables
- read line comments
- add modulus operator '%'
- implement input_number()
- base of the CLI
- evaluate expression from stdin
- read a file
- if statements
- while statements (with break)
- add functions support
- add config header file
- ability to modify keywords and customize the lang
- add strings support
- add list support
The language
You would be able to use the lang directly via CLI, via a REPL or by writing in a file (file ext .ltor
).
To begin with and order to simplify things we would only have numbers as datatypes (so an abstraction with int or float under the hood).
One instruction set per line.
Comments
Can only use single line comments with #
# this is a comment
Expression evaluation
can only operate on integer
function calls: func(arg_a, arg_b) operators: +, *, /, ^
Set a variable
set {VARNAME} to {EXPRESSION}
Eval an expression without using the result
eval print_number(42)
function definition
function {NAME}
begin
...
end
Conditional structure
if {EXPRESSION} then
begin
...
end
Conditional loop
while {EXPRESSION} do
begin
...
end
Unconditional loop
repeat {EXPRESSION THAT EVALUATE TO INT}
begin
end
std functions
abs(nb)
sqrt,sin,cos,exp,ln,log etc.
print_number(data)
input_number()
random_int(min, max)
Evaluator (draft)
EDIT: that's not actually quite how I implemented the evaluator.
Map
componentList: bytes steam first byte is a uint8 representing the type of the component then depending on the type of the component there is 0 or N bytes
components types:
- name: integer size: 4 bytes (for int)
- name: open parenthesis size: 0 bytes
- name: close parenthesis size: 0 bytes
- name: float size: 32 bytes (IEEE 754)
- name: operator size: 1 byte (255 operators are possible)
- name: function designator desc: id of a function size: 2 bytes (65536 functions are possibles)
Example map of 9+(5*(8+6))
lexed stream -TYPE:NUMERAL VALUE:9 -TYPE:OPERATOR VALUE:PLUS -TYPE:OPEN_PARENTHESIS VALUE:NULL -TYPE:NUMERAL VALUE:5 -TYPE:OPERATOR VALUE:TIMES -TYPE:OPEN_PARENTHESIS VALUE:NULL -TYPE:NUMERAL VALUE:8 -TYPE:OPERATOR VALUE:PLUS -TYPE:NUMERAL VALUE:6 -TYPE:CLOSE_P VALUE:NULL -TYPE:CLOSE_P VALUE:NULL
scan the whole lexed stream
So there will be a kind of time line with reference, a list of reference
in the begining we allocate two lists, one for the component type, one for the component values
Dynamics lists
we allocate N bytes (uint_8 list[2048])
methods:
list_length() list_assign_int(int index, int value) list_assign_float(int index, float value) list_assign_uint_8(int index, uint_8 value) list_get_int(int index)
etc...