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, } } } } }