For a compiled language, the compiler could know that `foo` and `bar` are 32-bit integers, and thus compile `foo + bar` to call the addition function for 32-bit integers. In an interpreted language, the interpreter could do the same thing.
Without that typing information, both would have to invoke a generic addition function that detects the types of its arguments at runtime, notices they're both 32-bit integers, and delegates to the corresponding addition function.
Of course there are tricks that can be played in the weakly-typed case, like assuming the same call site will always have the same types, so that there can be a short path that assumes that and only branches rarely. That way the first or first few executions might be slow, but eventually they get almost as fast as the statically-typed case. JS engines in particular and JITted runtimes in general usually do this.
>I guess assembly would be the language you would use if you really need to squeeze out the maximum amount of performance of a single CPU, and as far as I know, it does not have types.
Assembly absolutely does have types. The addition function for 32-bit ints only operates on 32-bit ints, and is distinct from the addition function for 64-bit ints.
You can add any bits that will fit in the relevant registers. Assembly cares not whether the programmer thinks they are ints.
[0]: https://github.com/php/php-src/blob/3709e74b5e495e210ada8039...
You mean slower as in performance? I'm having a hard time understanding how types == performance, so you have to mean something else.
I guess assembly would be the language you would use if you really need to squeeze out the maximum amount of performance of a single CPU, and as far as I know, it does not have types.
Also languages built on top of LLVM could get by with trading compile times for run time performance. Maybe you meant compiling gets slower without types?