198 lines
3.6 KiB
Markdown
198 lines
3.6 KiB
Markdown
# 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:
|
|
|
|
- [X] pow operator
|
|
- [X] binary operators
|
|
- [X] implement basic math functions
|
|
- [X] implement random_int(min, max)
|
|
- [X] implement print_number(message)
|
|
- [X] add unit tests
|
|
- [X] allow to set variables
|
|
- [X] 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...
|
|
|
|
|
|
|
|
|