Monkey Interpreter & Compiler

· Technology

Code

Interpreter

写法优化

一开始用 Box+dyn trait 来表示实现了 statement

pub struct Program {
    pub statements: Vec<Box<dyn Statement>>,
}

然后当想要向上转型成具体的类型时,就是需要使用 any + downcast_ref 去做判断,感觉有点不是很 Rustcaean,思考有没有别的办法

    #[test]
    fn test_integer_literal_expression() {
        let input = "5;";
        let mut l = Lexer::new(input.to_string());
        let mut p = Parser::new(&mut l);
        let program = p.parse_program();
        check_parser_errors(&p);
 
        assert_eq!(
            program.statements.len(),
            1,
            "program has not enough statements."
        );
 
        let stmt = program.statements[0]
            .as_any()
            .downcast_ref::<ExpressionStatement>()
            .expect("Expected statement to be ExpressionStatement");
 
        let ex = stmt
            .expression
            .as_ref()
            .expect("Expression should not be None");
        let literal = ex
            .as_any()
            .downcast_ref::<IntegerLiteral>()
            .expect("Expression is not an Identifier");
 
        assert_eq!(literal.value, 5, "Literal value mismatch");
        assert_eq!(
            literal.token_literal(),
            "5",
            "Literal token_literal mismatch"
        );
    }
 
 

是不是可以用泛型Statement<T>代替 dyn Statement? 或者用 Enum match pattern 代替类型判断

后续就用了 Enum,稍微方便了点,顺带性能肯定比 Box+dyn trait 高。

pub enum Statement {
    Let(LetStatement),
    Return(ReturnStatement),
    Expression(ExpressionStatement),
}
if let Statement::Expression(stmt) = &program.statements[0] {
            let ex = stmt
                .expression
                .as_ref()
                .expect("Expression should not be None");
            if let Expression::IntegerLiteral(literal) = ex {
                assert_eq!(literal.value, 5, "Literal value mismatch");
                assert_eq!(
                    literal.token_literal(),
                    "5",
                    "Literal token_literal mismatch"
                );
            } else {
                panic!("Expected IntegerLiteral")
            }
        } else {
            panic!("Expected ExpressionStatement")
        }
}

后续写 marco 时不知道咋写了,思维还是够 Rustcaean,只能又加上 as_any 先试试看能不能写下去,可能等后面有实力了再重构吧。

编译 和 解释

两则之间的界限很模糊。有些情况下更加模糊,比如某些编程语言的实现会解析源代码,构建 AST 并将其转换为字节码。在执行之前,虚拟机会即时将字节码编译为机器代码,而不是直接在
虚拟机中执行字节码指定的操作。这就是所谓的 JIT(Just in Time)解释器/编译器。

Compiler

Comments (0)

    Send comment

    Markdown supported. Please keep comments clean.