# 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 things, 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 - 2022-05-15 Clear progress being able to use simple while and if though thre are many glitches 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 - [X] add modulus operator '%' - [ ] add support for multiple characters operators - [ ] add inclusive operators like '!=', '>=', '<=' - [ ] add support for priority operators - [X] add input_number() std function - [X] add NULL type (dirty way to handle no returns and some errors) - [X] add type() std function and others type checking functions - [X] add ceil() and floor() std functions - [X] base of the CLI - [ ] evaluate expression from stdin - [X] read a file - [X] if statements - [X] while statements (with break and continue) - [ ] repeat statement - [ ] add functions support - [ ] add config header file - [ ] ability to modify keywords and customize the lang - [ ] add static string support (just for ui) - [ ] add print_string function - [ ] add basic number list support - [ ] add fully features strings support - [ ] add [classic problem solving](https://rosettacode.org) with code examples - [ ] add Web Assembly support and publish a demo website - [ ] refactor: use malloc for list - [ ] refactor: remove inconsistency on how functions returns error codes ## Installation You will need to compile the code from source. - Clone this repository - Then compile (eg. with `make`) I use GNU Make with GCC, but I'm sure you can use any C compilers though you may need to edit some part of the code to cope with other compilers (eg. binary constants). ## 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`). One instruction set per line. ### Comments Can only use single line comments with `#` ``` # this is a comment ``` ### Data types To begin with and order to simplify things we would only have numbers as datatypes. When a variable is declared it can be 32 bit integer or 32 bit float. The language may support strings literals in the future. ### Expression evaluation function calls: func(arg_a, arg_b) operators: +, *, /, ^, %, =, <, >, &, |, ! ### Set a variable ``` set {VARNAME} to {EXPRESSION} ``` ### Evaluate an expression without using the result ``` print_number(42) ``` ### function definition ``` function {NAME} do ... end ``` ### Conditional structure ``` if {EXPRESSION} then ... end ``` ### Conditional loop ``` while {EXPRESSION} do ... end ``` ### Unconditional loop ``` repeat {INT EXPRESSION} do ... end ``` ``` repeat i from {INT EXPRESSION} to {INT EXPRESSION} do ... end ``` ### std functions ``` abs(nb) sqrt,sin,cos,exp,ln,log etc. print_number(nb) input_number() ceil(nb) floor(nb) random_int(min, max) random_float(min, max) type(var) -> return the type of a var as int is_null(var) is_number(var) print_string(str) print_newline() print_ascii(nb) ``` # 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...