Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Contributing to Perk

Welcome to the Perk contribution guide!

---

## Finding what to contribute on
A good starting point is to check [issues tagged with "good first issue"](https://github.com/Alex23087/Perk/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22). These should be simple tasks that we left behind specifically for people who want to contribute but don't know where to start.

If you have issues with those issues, or want to contribute in a different way, you can either open a new issue or reach out to us on [Discord](https://discord.com/invite/DgDDV6xPQe).

---

## Pull Request Process
We don't have a strict pull request process, but here are some guidelines to follow:
1. Fork the repository and create your branch from `main`.
2. If you've added code that should be tested, add tests.
3. :warning: **Ensure the test suite passes.** :warning:
- Ideally, all tests should pass before you submit your pull request. See [Tests](#tests) for more information. If you can't get them to pass, you can still submit your PR, but please explain why the tests are failing in the PR description. We will absolutely help fix the tests, but it will likely delay the merging of your PR.
5. Issue that pull request!

:warning: **If you open a pull request to change a big part of the language, such as adding an entirely new construct, or changing how something is compiled, please get in touch with us first, either by opening an issue or reaching out on Discord. This will help us ensure that your changes align with the project's goals and avoid unnecessary work.** :warning:

---

## Tests
:warning: All references to the static tests only currently apply to the [`devel`](https://github.com/Alex23087/Perk/tree/devel) branch, and will be merged to `main` in the (near) future. :warning:

### Directory structure
Our current test setup consists in a number of Perk programs that should test small parts of the language. These programs are located in the `tests/` directory. The structure of this directory is as follows:
```
tests/
├── pass/ # Should compile and run successfully (dynamic)
├── fail/ # Should fail to compile (dynamic)
├── pass_static/ # Should compile and run successfully (static)
├── fail_static/ # Should fail to compile (static)
└── future/ # Tests for future features (not run)
```
In more detail:
- `pass/` and `fail/` test features of the full language, with support to features that require dynamic memory allocation (or in general runtime support)
- `pass_static/` and `fail_static/` test the subset of the language that can be compiled to C without any runtime support (i.e. no heap allocation, no garbage collection, no standard library)
- `future/` contains tests for features that are not yet implemented, and are more of a concept for what we want to implement in the future. These tests are not run.

### File structure
Each test is a `.perk` file, with a name starting with an increasing number (for example `01-hello_world.perk`). This number is used to order the tests when they are run, and should be unique in each directory.

Every **passing** test (i.e., a test in `pass/` or `pass_static/`) also has a corresponding `.expected` file, which contains the expected output of the test. The make target checks that the output of the test matches the expected output. **If there is no `.expected` file, or the output differs, the test is considered to fail.**

### Running the tests
To run the tests, simply run:
```bash
make test
```
This will run all the tests in `pass/`, `fail/`, `pass_static/` and `fail_static/`

You can also run a specific set of tests by running one of:
```bash
make test_pass
make test_fail
make test_pass_static
make test_fail_static
```

All test commands support passing a specific test file as an argument. For example:
```bash
make test_pass FILE=42
```
will only run the test that matches `test/pass/42*.perk`.

All the tests should pass. If you add a new feature, please add tests for it in the appropriate directory.
103 changes: 94 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,43 @@
# Perk

Perk is a modern low level programming language, compiled to C. It builds on C's simplicity, adding features such as option types, lambdas and typeclasses. Its current goal is to replace C in the implementation of the MellOS operating system.
Perk is a modern low level programming language, compiled to C. It builds on C's simplicity, adding features such as option types, lambdas, typeclasses and algebraic data types. Its current goal is to replace C in the implementation of the [MellOS](https://github.com/mell-o-tron/MellOs) operating system.

---

## Run Perk with nix
## Join us!
If you want to join Perk development, discussions, or just want to see what's going on, join our [Discord server](https://discord.com/invite/DgDDV6xPQe)!
We love new people joining the community, and are always happy to help out new contributors, so don't hesitate!

```bash
nix run github:Alex23087/Perk -- [files]
```
---

This will build the `perkc` compiler and run it directly (you can pass any arguments after `--`).
## Table of Contents
- [Documentation](#documentation)
- [Integration with C](#integration-with-c)
- [Features](#features)
- [Running Perk](#running-perk)
- [Nix](#nix)
- [Arch Linux](#arch-linux)
- [Extensions](#extensions)
- [VSCode](#vscode)
- [Vim](#vim)
- **[Contributing](CONTRIBUTING.md)**

---

## Documentation

We are using `ocamldoc` to generate the documentation. Use the command `make docs` to generate the documentation.

You can view the latest documentation automatically built from this repository on [the Perk website](https://perklang.org/).

---

## Integration with C

Import C libraries using `import "libname.h"`. The compiler will automatically add most of the prototypes from the C source to the typechecker. This is not yet perfect, and does not yet work for custom include paths [(check out this issue)](https://github.com/Alex23087/Perk/issues/12), nor does it currently include macros.

---

## Features

- Simple **type inference**
Expand All @@ -41,8 +59,8 @@ let position: (float * float) = (200.,200.)
- **Option types**, with implicit boxing at assignment

```
let z : (int*)? = nothing;
z = just &x;
let z : (int*)? = nothing;
z = just &x;
```

- **Typeclass system** (*Archetypes and Models*)
Expand Down Expand Up @@ -89,4 +107,71 @@ fun streq (s1 : char*) : char* => int {
}
```

- Static subset (only uses the stack, only allows non-capturing lambdas)
- Static subset (only uses the stack, only allows non-capturing lambdas)

- Algebraic data types (ADTs) :warning: currently in `devel` :warning:

```
type IntList = | Empty | Cons (int, IntList)

fun sum (l : IntList) : int {
let res := 0;
match (l) {
Empty {res = 0},
Cons(var x : int, var l1 : IntList) {res = x + sum(l1)}
};
return res
}
```

---

## Running Perk
### Nix

```bash
nix run github:Alex23087/Perk -- [files]
```

This will build the `perkc` compiler and run it directly (you can pass any arguments after `--`).

### Arch Linux
[![AUR](https://img.shields.io/aur/version/perk-opam-git?style=flat)](https://aur.archlinux.org/packages/perk-opam-git)

Perk is on the AUR!\
You can install `perk-opam-git` from your favourite AUR helper.

This package pulls the latest Perk version from the main branch of this repository and builds `perkc` using `opam` and `dune`. All required dependencies are automatically installed. It then installs the compiler in `/usr/local/bin/perkc`

---

# Extensions

## VSCode

We have two extensions for VSCode, located in `tools/vscode-extensions/`:
- `perk-syntax`: provides syntax highlighting for Perk files;
- `perk-lsp`: provides error checking using `perkc --check`.

To install them, you should build them using `make extensions` and then install them in VSCode using the "Install from VSIX..." option.

## Vim

An extension is available for Vim (or NeoVim), located in `tools/vim-extensions/`:

- `perk-syntax`: provides syntax highlighting for Perk files;

To install it, copy the content of the `tools/vim-extensions/perk-syntax/` in your Vim pack directory:
```
mkdir -p ~/.vim/pack/perk/start/perk
cp -R ./tools/vim-extensions/perk-syntax/* ~/.vim/pack/perk/start/perk/
```

For vim-plug:
```
call plug#begin()
Plug '~/{path-to-perk}/tools/vim-extensions/perk-syntax'
call plug#end()
```

For more details refer to the [README.md](./tools/vim-extensions/perk-syntax/README.md) of the extension.
38 changes: 38 additions & 0 deletions tools/vim-extensions/perk-syntax/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Perk Vim Syntax Plugin

This directory provides a minimal Vim plugin for Perk syntax highlighting and filetype detection.

## Installation
Copy (or symlink) the contents into your vim (or nvim) runtime path, e.g.:

```
mkdir -p ~/.vim/pack/perk/start/perk
cp -R ./* ~/.vim/pack/perk/start/perk/
```

For vim-plug:
```
call plug#begin()
Plug '~/{path-to-perk}/tools/vim-extensions/perk-syntax'
call plug#end()
```

## Features
- Highlights Perk keywords, types, numbers, strings (with escapes), comments and TODOs.
- Highlights function names after `fun` and variable names declared via `let`.
- Marks embedded C delimiters `BEGIN_C` / `END_C`.

## Extending
You can add more highlighting by editing `syntax/perk.vim`:
- Add new keywords to the `perkKeyword` group.
- Add additional types to `perkType`.
- Create new regions for multi-line constructs.

## Filetype Detection
`ftdetect/perk.vim` sets the filetype for any `*.perk` file automatically.

## Troubleshooting
If highlighting does not appear:
1. Run `:echo &filetype` to verify it reports `perk`.
2. Ensure the plugin directories are correctly placed in your runtime path.
3. Check for conflicting plugins defining `perk`.
5 changes: 5 additions & 0 deletions tools/vim-extensions/perk-syntax/ftdetect/perk.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
" Filetype detection for Perk
augroup perk_filetype
autocmd!
autocmd BufNewFile,BufRead *.perk setfiletype perk
augroup END
54 changes: 54 additions & 0 deletions tools/vim-extensions/perk-syntax/syntax/perk.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
" Vim syntax file for Perk language
" Derived from VSCode grammar
" Maintainer: axdelafuen

if exists("b:current_syntax")
finish
endif

" Keywords
syn keyword perkKeyword let import open extern archetype model struct private public fun for while do if then else return summon banish make cast of just nothing

" Types
syn keyword perkType int void uint8_t uint16_t uint32_t uint64_t float double bool char

" Comments
syn match perkComment "//.*" contains=perkTodo
syn region perkComment start="/\*" end="\*/" contains=perkTodo
syn match perkTodo "\<TODO\>" contained

" Strings
syn region perkString start=+"+ skip=+\\\\.+ end=+"+ contains=perkEscape
syn region perkString start=+'+ skip=+\\\\.+ end=+'+ contains=perkEscape
syn match perkEscape "\\\\." contained

" Numbers
syn match perkNumber "\<0x[0-9A-Fa-f]\+\>"
syn match perkNumber "\<0o[0-7]\+\>"
syn match perkNumber "\<0b[01]\+\>"
syn match perkFloat "\<[0-9]\+\.[0-9]\+\>"
syn match perkNumber "\<[0-9]\+\>"

" Function names after 'fun'
syn match perkFunctionName /\<fun\s\+\zs\w\+/ containedin=perkKeyword

" Variable names after 'let'
syn match perkLetName /\<let\s\+\zs\w\+\ze\s*:/ containedin=perkKeyword

" Embedded C markers
syn keyword perkCMarker BEGIN_C END_C

" Default highlight links (can be overridden later)
hi def link perkComment Comment
hi def link perkTodo Todo
hi def link perkKeyword Keyword
hi def link perkType Type
hi def link perkString String
hi def link perkEscape SpecialChar
hi def link perkNumber Number
hi def link perkFloat Float
hi def link perkFunctionName Function
hi def link perkLetName Identifier
hi def link perkCMarker PreProc

let b:current_syntax = "perk"