langatator/README.md

4.8 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 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:

  • 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 '%'
  • add support for multiple characters operators
  • add inclusive operators like '!=', '>=', '<='
  • add support for priority operators
  • add input_number() std function
  • add type() std function
  • add ceil() and floor() std functions
  • base of the CLI
  • evaluate expression from stdin
  • read a file
  • if statements
  • 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 with code examples
  • add Web Assembly support and publish a demo website
  • 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_int(var)
is_float(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...