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 '[
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]]]
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]]
]
]
]
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]
]
]
myeval:[lambda '[prgm:1 env:env]
'[if [isName? prgm]
then:/env/prgm
else:[apply /prgm/0 prgm env]
]
]
evaluate:[lambda '[pgrm:1] '[dataDeltaR pgrm env:m-environment delta:0]]
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]]]]
}
]