Can we (Is it possible to) make a compiler for any dynamic/script/interpreter language,
Yes, it is.
Note that there is no such thing as an "interpreter" language. An interpreter is a strategy for implementing a language, it is not a property of the language itself. It is a property of … well … the interpreter.
Also note that the Second Futamura Projection actually gives a way of automatically deriving a compiler from an interpreter, so in a theoretical sense, once you have an interpreter, you also have a compiler as well.
- LuaVM compiles Lua to LuaVM byte code,
- LuaJIT compiles LuaVM byte code to native machine code,
- CPython compiles Python to CPython byte code,
- Jython compiles Python to JVM byte code,
- IronPython compiles Python to DLR Trees,
- GraalPython is a strange one, it parses Python into Truffle ASTs, and then interprets the Truffle ASTs with a specializing interpreter, which is essentially equivalent to compiling the Truffle ASTs (it's related to Partial Evaluation and Abstract Interpretation (aka Supercompilation)),
- PyPy is another strange one, it compiles Python to RPython byte code, interprets that RPython byte code, and uses a tracing compiler to compile a specialized version of the interpreter which can only interpret that one program, which is essentially equivalent to compiling the RPython byte code (it's related to Partial Evaluation and Abstract Interpretation (aka Supercompilation)),
to compile it to native machine code,
That is an extremely narrow definition of "compile". Compilation only means translating from one language to another language while preserving the meaning of the program. There is no requirement that the target language be native machine code.
And what does "native machine code" mean, anyway? I am writing this on a MacBook Air M1 with an ARM processor, running the AMD64 version of my browser in the Rosetta 2 emulator. So, is the AMD64 code of the browser native machine code or not? What if you run Linux in an x86 emulator on a Java Virtual Machine running on a MIPS emulator running on a SPARC workstation? What if you run Linux in an x86 emulator running on a Java Virtual Machine running natively on a Java CPU?
Or there is a special case/feature make it impossible to write compiler for it?
No. Some people say that a feature like
eval makes it impossible, but that is not true: you could write an interpreter, and compile calls to
eval into calls to that interpreter. Or, much simpler, since you already have a compiler anyway: compile calls to
eval into a call to the compiler followed by a call to the output of the compiler.
Other people say that macros make it impossible, but that is not true either. In fact, it is just the dual to the problem with
eval: instead of making the compiler a part of the program, you make the program a part of the compiler.
In fact, problems like these are not unique to dynamic languages. C++ Templates are Turing-complete, which means that compiling them is equivalent to running a potentially infinite program. Similarly, some extensions to Haskell's type system are Turing-complete, as is Scala 2's type system. Overload resolution in C# is famously NP-complete, so while it is guaranteed that compiling a C# program always terminates, I can easily write a program that takes longer than the heat death of the universe to compile.
Does the fact that compiling some legal C++ programs takes an infinite amount of time mean that you can't have a compiler for C++? Does the fact that compiling some legal C# programs takes longer than the lifetime of the universe mean that you can't have a compiler for C#?