Minimal ML like language written in C11
Go to file
Francesco Magliocca 430e9ca140 Improve parser errors 2022-05-18 11:50:36 +02:00
examples Fix some parser errors 2022-05-18 00:18:31 +02:00
extra Rename project 2022-05-18 08:53:45 +02:00
include Fix some parser errors 2022-05-17 21:33:36 +02:00
ref_parser Rename project 2022-05-18 08:53:45 +02:00
src Improve parser errors 2022-05-18 11:50:36 +02:00
.gitignore Rename project 2022-05-18 08:53:45 +02:00
Makefile Rename project 2022-05-18 08:53:45 +02:00
README.md Rename project 2022-05-18 08:53:45 +02:00

README.md

inf

inf is an hobby, and should not be taken seriously.

Interpreter for a Minimal ML-like language whose ideal goal is to be used for bootstrapping compilers and interpreters.

How to build

inf's interpreter is written in portable ISO C11, sources are in src/ and header files are in include/.

If your system happens to have a make implementation compatible with GNU Make, you can just run:

make

Otherwise, something like this should work:

$(CC) -std=c11 -o inf -Iinclude/ src/*.c

The language

inf is a minimal dialect of Standard ML and Haskell, here is a list of the features (or better, limitations) I want to introduce:

  • Keep the implementation <5000 LOC
  • Eager evaluation (call by value)
  • Algebraic Datatypes (pretty useful for representing syntax trees)
  • First class functions
  • Pattern patching (pretty useful for analyzing syntax trees)
  • Integers, booleans, strings
  • Mutable ref cell
  • FFI to C
  • Polymorphic types à la Hindley Milner (probably unfeasible)
  • Automatic currying of functions, with optimised partial evaluation (unfeasible)
  • Delimited continuations (this is an overkill)
  • Easy syntax allowing easy kakoune support

inf's full grammar is specified as a pair of lex and yacc files in ref_parser/.

kakoune plugin for inf is in extra/inf.kak.

Here is a small example of the syntax:

# Helpers
datatype 'a list {
  Cons of ('a, 'a list),
  Empty
}

datatype 'a maybe {
  Just of 'a,
  Nothing
}

# Lambda calculus term, nameless representation
datatype term {
  Var of int,
  Int of int,
  Abs of term,
  App of (term, term)
}

# Result of the evaluation
datatype value {
  Int     of int,
  Closure of (env, term)
}

alias env = value list

typecheck add_binding : value -> env -> env
def add_binding v env = Cons v env

typecheck lookup : int -> env -> value maybe
def lookup _ <Empty> = Nothing
  | lookup 0 <Cons x xs> = Just x
  | lookup n <Cons x xs> = lookup (subtract n 1) xs

typecheck eval : env -> term -> value
def eval e <Var idx> = 
        match lookup idx e {
          case <Just v>   -> v
          case <Nothing>  -> abort "Variable out of scope"
        }

  | eval e <Int x> = Int x
  | eval e <Abs t> = Closure e t
  | eval e <App t1 t2> =
      let def new_env = add_binding (eval e t2) e
      in eval new_env t1