Many interpreters, including the official PHP interpreter, actually translate the code to a byte code format before executing it for performance (and I suppose flexibility) reasons, but at its simplest, an interpreter simply goes through the code and performs the corresponding action for each statement. An extremely simple interpreter for a PHP-like language might look like this for example:
def execute_program(prog)
for statement in prog.toplevel_statements:
execute_statement(statement)
def execute_statement(statement):
if statement is an echo statement:
print( evaluate_expression(statement.argument) )
else if statement is a for loop:
execute_statement(statement.init)
while evaluate_expression(statement.condition).is_truthy():
for inner_statement in statement.body:
execute_statement(inner_statement)
execute_statement(statement.increment)
else if ...
Note that a big if-else-if statement is not actually the cleanest way to go through an AST and a real interpreter would also need to keep track of scopes and a call stack to implement function calls and returns.
But at its most basic, this is what it boils down to: "If we see this kind of statement, perform this kind of action etc.".
Except for being much more complex, it isn't really any different from writing a program that responds to user commands where the user could for example type "rectangle" and then you draw a rectangle. Here the CPU also doesn't understand what "rectangle" means, but your code contains something like if user_input == rectangle: [code to draw a rectangle]
and that's all you need.
echo
-like instruction, it might cause the interpreter to call a function it its own program that writes the output. – Bloodline