Interpreter in Rust
sergey shishkinЛаборатория проекта
- https://craftinginterpreters.com/contents.html
- https://kentavr.tiddlyhost.com/#Интерпретаторы%20в%20Rust
- Язык программирования
Calc, который поддерживает простое сложение и вычитание целых чисел ... Использование PEG для определения нашей грамматики, pest для созданияCalcParserи объяснения того, что такое AST и что означает интерпретация AST. Далее мы представим JIT-компиляцию и используем inkwell для JIT-компиляции нашегоCalcязыка из его AST. Чтобы показать альтернативный подход к компиляции, мы создадим виртуальную машину и среду выполнения и обсудим их функции. Простой REPL для нашегоCalcязыка и протестируем различные пути выполнения ... СоздадимFirstlangязык со статической типизацией, постепенно продвигаясь от нашегоCalc ...Объектная система ... Библиотека ... - IR - промежуточное представление ... Stack Machine — модель вычислительной машины с двумя основными компонентами: массив памяти (стек), содержащий инструкции байт-кода, которые поддерживают инструкции push и pop; указатель инструкции (IP) и указатель стека (SP), указывающие, какая инструкция была выполнена и что будет дальше ... Байт-код — эмуляция набора инструкций с новой (удобной для человека) кодировкой (возможно, более простой, чем ассемблер), промежуточный язык/представление , которое находится на более низком уровне, чем фактический язык программирования, который был переведен с него, и на более высоком уровне, чем язык ассемблера ... VM - виртуальная машина абстрагируется от деталей базового оборудования или операционной системы, поэтому программы, переведенные/скомпилированные на язык виртуальной машины, становятся независимыми от платформы.
- Read-Eval-Print Loop (REPL)
fn main() {
let mut rl = Editor::<()>::new();
println!("Calculator prompt. Expressions are line evaluated.");
loop {
let readline = rl.readline(">> ");
match readline {
Ok(line) => {
cfg_if! {
if #[cfg(any(feature = "jit", feature = "interpreter"))] {
match Engine::from_source(&line) {
Ok(result) => println!("{}", result),
Err(e) => eprintln!("{}", e),
};
}
else if #[cfg(feature = "vm")] {
let byte_code = Engine::from_source(&line);
println!("byte code: {:?}", byte_code);
let mut vm = VM::new(byte_code);
vm.run();
println!("{}", vm.pop_last());
}
}
}
Err(ReadlineError::Interrupted) => {
println!("CTRL-C");
break;
}
Err(ReadlineError::Eof) => {
println!("CTRL-D");
break;
}
Err(err) => {
println!("Error: {:?}", err);
break;
}
}
}
struct Eval;
impl Eval {
pub fn new() -> Self {
Self
}
pub fn eval(&self, node: &Node) -> i32 {
match node {
Node::Int(n) => *n,
Node::UnaryExpr { op, child } => {
let child = self.eval(child);
match op {
Operator::Plus => child,
Operator::Minus => -child,
}
}
Node::BinaryExpr { op, lhs, rhs } => {
let lhs_ret = self.eval(lhs);
let rhs_ret = self.eval(rhs);
match op {
Operator::Plus => lhs_ret + rhs_ret,
Operator::Minus => lhs_ret - rhs_ret,
}
}
}
}
}