Skip to content

lmeller-git/mini_compiler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

87 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mini_compiler

A minimal example compiler

Quickstart

Clone this repository and run:

 cargo run --release -- examples/hello_world.lang
 ./target/a.out

Usage

Write your code into some file, then call

cargo run --release -- <file>

this will create target/ in your wd and fill it with <file_name>.asm, <file_name>.o and a.out.

To run the binary simply call target/a.out

For more options refer to

cargo run --release -- --help

The compiler accepts a list of files and directories. Passed assembly files will not be compiled, but directly assembled and included. Passed object files will not be compiled or assembled, but included. All children of directories with extension ext will be compiled.

Run tests easily with cargo run --release -- <files> --test

To call functions via FFI, use c_call or c_call_arr in lib/std/ffi.asm

LSP

A basic LSP implementation for mini_compiler may be found in https://github.com/lmeller-git/mini_compiler_lsp.

Treesitter

A basic treesitter implementation for mini_compiler may be found in https://github.com/lmeller-git/mini_compiler_treesitter.

Syntax

A simple hello world with mini_compiler could look like this:

extern_def print_str;

public begin_def main argc, argv;
 name = *argv;
 print_str "hello world from ";
 print_str name;
 print_str "\n";
end_def

Declare a variable with:

<lvalue> = <expr>;

A lvalue is just an optionally dereferenced ident:

('*')*<ident>

All variables are qwords.

Define a function with:

begin_def <ident> [ <ident> ( ',' <ident> )* ] ;
 <line>*
end_def

Values may be returned from functions using builting function return.

Referance an external function with:

 extern_def <ident> [ <ident> ( ',' <ident> )* ] ;

Call a function with:

<ident> [ <expr> ( ',' <expr> )* ] [ ':' <lvalue> ];

Execute some code conditionally with:

if <expr>; <line>

A line is any valid line of code ending in a semicolon. This inculdes if stmts:

if <expr>; if <expr>; <line>

To create a loop use builtin functions

label <ident>;
goto <ident>;

Everything else are exprs.

Valid exprs use basic math operators, parentheses, strlits and pointer derefs/refs:

(<expr> + <expr>) - (<expr> + <expr>);

ptr = &0;
print_qword *ptr + 42;

Inline assembly may be written with

 asm "
 <asm here>
 ";

Linker attributes for functions may be defined with

 link_attr <attribute1>;
 link_attr <attribute2>;
 <function def / extern def>

Linker section tests is used for test functions, i.e. functions annotated with

 link_attr section tests;

will be run in a test run.

Condtional compilation of function declarations or lines can be achieved with

 cfg <expr>;
 <func/line>

Test runs will automatically inject --cfg test, thus functions annotated with cfg test; will only be compiled in test runs (unless explicilty added).

Builtin functions

The current supported builtin functions are

  • label
  • goto
  • addr_of
  • return

Supported targets

Currently only x86_64 linux is supported.

All targets depend on gcc and nasm.

About

A VERY minimal compiler built for fun

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors