--- /dev/null
+# minfp: a minimal pure lazy functional language
+
+`minfp` is a functional programming language that aims to be as small as
+possible while still being feature rich.
+Most of the code is taken up by type checking.
+
+```
+$ wc -l *.[id]cl
+ 23 ast.dcl
+ 25 ast.icl
+ 5 builtin.dcl
+ 13 builtin.icl
+ 12 check.dcl
+ 168 check.icl
+ 6 gen.dcl
+ 39 gen.icl
+ 7 int.dcl
+ 49 int.icl
+ 59 main.icl
+ 10 parse.dcl
+ 124 parse.icl
+ 13 scc.dcl
+ 41 scc.icl
+ 594 total
+```
+
+### Features
+
+- Polymorphic type inference for the Hindley-Milner type system
+- Support for let polymorfism
+- Reasonable interpreter
+
+### CFG
+
+```
+minfp := function+
+function := (op+ ['infixr' | 'infixl'] digit+ | id) id* '=' expr ';'
+expr := expr op expr
+ | '\' id '.' expr
+ | '(' op+ ')'
+ | '\' id '.' expr
+ | '-'? digit*
+ | 'True' | 'False'
+ | 'code' id
+ | id
+id := alpha (alnum)*
+op := '!' | '|' | '@' | '#' | '$' | '%' | '^' | '&' | '*' | '=' | '+'
+ | '/' | '?' | '-' | '_' | '|' | ''' | '"' | '\' | ''' | '<' | '>'
+ | '.' | ':'
+alpha := a | b | .. | z | A | B | .. | Z
+digit := 0 | 1 | .. | 9
+alnum := alpha | digit
+```
+
+A program always has to have a `start` function that takes no arguments.
+
+### Code instructions
+
+See `builtin.icl` for all builtin instructions that you can use with `code`
+
+### Todo
+
+- Code generation
+- ADTs
--- /dev/null
+implementation module builtin
+
+import Data.Func
+import check
+
+builtin :: [([Char], Scheme)]
+builtin =
+ [(['_if'], Forall [['_ift']] $ TBool --> TVar ['_ift'] --> TVar ['_ift'] --> TVar ['_ift'])
+ ,(['_eq'], Forall [['_eq']] $ TInt --> TInt --> TBool)
+ ,(['_mul'], Forall [['_mul']] $ TInt --> TInt --> TInt)
+ ,(['_add'], Forall [['_add']] $ TInt --> TInt --> TInt)
+ ,(['_sub'], Forall [['_sub']] $ TInt --> TInt --> TInt)
+ ]
import Data.Maybe
import Text
-import ast, scc
+import ast, scc, builtin
check :: [Function] -> Either [String] (Expression, [([Char], Scheme)])
check fs
| length dups > 0 = Left ["Duplicate functions: ":[toString n\\[(Function n _ _):_]<-dups]]
= case partition (\a->a=:(Function ['start'] _ _)) fs of
([], _) = Left ["No start function defined"]
- ([Function _ [] e:_], fs) = (\x->(e, x)) <$> runInfer (infer preamble (makeExpression fs e))
+ ([Function _ [] e:_], fs) = (\x->(e, x)) <$> runInfer (infer (fromList builtin) $ makeExpression fs e)
([Function _ _ _:_], _) = Left ["Start cannot have arguments"]
makeExpression :: [Function] Expression -> Expression
toString (a --> b) = concat ["(", toString a, " -> ", toString b, ")"]
:: TypeEnv :== Map [Char] Scheme
-preamble :: TypeEnv
-preamble = fromList
- [(['_if'], Forall [['_ift']]
- $ TBool --> TVar ['_ift'] --> TVar ['_ift'] --> TVar ['_ift'])
- ,(['_eq'], Forall [['_eq']] $ TInt --> TInt --> TBool)
- ,(['_mul'], Forall [['_mul']] $ TInt --> TInt --> TInt)
- ,(['_add'], Forall [['_add']] $ TInt --> TInt --> TInt)
- ,(['_sub'], Forall [['_sub']] $ TInt --> TInt --> TInt)
- ]
:: Subst :== Map [Char] Type
:: Infer a :== StateT [Int] (WriterT [([Char], Scheme)] (Either [String])) a