Metacircular evaluator

A self-interpreter is an programming language interpreter that can interpret the language it is written in. A metacircular evaluator is a self-interpreter that is directly applied to the source code without any additional parsing. Thus it is only possible in langagues where the code is a data structure (homoiconicity).

LISP provides perhaps the most famous example. A metacircular evaluator provides the ability to alter the semantics of the language.

MISC is perhaps suited to building interpreters because it naturally handles environments because they are just maps. Below is a 55 line metacircular MISC evaluator and a few test examples.

[let [let '[original-env:[environment]] '[letrec '[ #:"Data is determined by the 'data metadata value." isName?:[lambda '[v:1] '/[meta v]/'is-name] isStatic?:[lambda '[v:1] '[or [lambda? v] [not /[meta v]/'data]]] isData?:[lambda '[v:1] '[or [isStatic? v] [> /[meta v]/'data 1]]] #:"Changes the data metadata attribute, any item that is then not data is evaluated further." dataDelta:[lambda '[o:1 dd:delta env:env] '[if [isStatic? o] then:o else:[let '[no:[meta+ o {data:[+ /[meta o]/'data dd]}]] '[if [isData? no] then:no else:[myeval no env:env]] ] ] ] #:"Recursively changes the data metadata value." dataDeltaR:[lambda '[o:1 env:env dd:delta] '[if [and [map? o] [not [string? o]]] then:[dataDelta [meta= [mapm o [lambda '[v:1] '[dataDeltaR v delta:dd env:env]]] [meta o]] delta:dd env:env] else:[dataDelta o delta:dd env:env] ] ] #:"Runs a program." myeval:[lambda '[prgm:1 env:env] '[if [isName? prgm] then:/env/prgm else:[apply /prgm/0 prgm env] ] ] #:"The main function that evaluates a program passed in as data." evaluate:[lambda '[pgrm:1] '[dataDeltaR pgrm env:m-environment delta:0]] #:"The environment is composed of all the standard functions, plus replacements for let and lambda." m-environment:[union { let:[sub '[,dataDeltaR /args/2 env:[,union [,mapm /args/1 [,lambda '[v:1] '[,,dataDeltaR v env:call-env delta:-1]]] call-env] delta:-1] ] letrec:[sub '[,letrec '[new-env:[,,union [,,mapm /args/1 [,,lambda '[v:1] '[,,,dataDeltaR v env:new-env delta:-1]]] call-env]] '[,,dataDeltaR /args/2 env:new-env delta:-1] ] ] lambda:[sub '[,sub '[,,dataDeltaR /def-env/'args/2 env:[,,union [,,mapm /def-env/'args/1 [,,lambda '[v:1] '/args/v]] /def-env/'call-env] delta:-1] ]] sub:[sub '[,sub '[,,dataDeltaR /def-env/'args/1 env:{args:args def-env:/def-env/'call-env call-env:call-env} delta:-1] ]] } original-env ]] '{evaluate:evaluate} ]] '{ [evaluate '[+ 2 3]] [evaluate '[+ 2 [* 3 5]]] [evaluate '{[+ 4 5] [+ 2 [* 3 5]]}] [evaluate '[* 2 [[if true then:* else:+] 2 5]]] [evaluate '[let '[x:[+ 2 3]] '[* x x]]] [evaluate '[[lambda '[n:1] '[* n n]] 16]] [evaluate '[[lambda '[fac:0 n:1] '[if [= n 1] then:n else:[* n [fac [- n 1]]]]] 10]] [evaluate '[mapm '[1 2 3 4 5] [lambda '[x:1] '[* x 2]]]] } ]