> would traditionally be called an expression evaluator
It is not an evaluator, evaluators are included (the different eval functions).
> the 150 lines doesn't include the parser or lexer either
This is just wrong:
$ cat *.ml{,l,y} *.c | sed '/^\s*$/d' | wc -l
149
and these 149 lines (okay, 169 if you count blank lines which are removed using sed in the count above) include the two `eval` and the `run` functions which are not actually part of the compiler but here for clarity (they help understanding how the successive intermediate representations of the boolean expressions work — without them the entire project is less than 130 lines).> Not a bad attempt for what is presumably a first try
It's not ;). It is however targeted at beginner compsci students who have absolutely no idea how compilers are built yet :).
> but I think "complete compiler" is overselling it.
It does lexing & parsing to produce an AST of a boolean expression, then a traversal of this AST to transform it into a second intermediate representation (an AST of NAND-only expression), then compiles the expression into a list of instructions (and this paradigm shift is a big step that is tough to teach to some students, believe me ^^), and then emits the corresponding bytecode (which here is 1:1 with the imperative instructions), and then the VM interprets this bytecode. I don't think I'm overselling it :).
The only way it is not complete — and that's written in the README — is that it has absolutely no semantics analysis (there is only one type, and no names, so there is nothing to analyze ^^), but that is not mandatory to be called a compiler.
Then again, this is only the first hour of a semester long compiler class (which covers semantic analysis, don't worry) ;).