use crate::format_forge_error; use crate::parse::ast::{BinaryOp, Program, UnaryOp, ValueExpression, VoidExpression}; use crate::parser::ast::GroupedExpression; use crate::parser::parse_program; use crate::runtime::executor::Visitor; use crate::runtime::value::ForgeValue; use crate::runtime::vm::{Chunk, ChunkRef, OpCode, VmError}; pub struct ChunkBuilder { current_chunk: Chunk, } impl ChunkBuilder { pub fn new() -> Self { Self { current_chunk: Chunk::default(), } } pub fn parse(code: &str) -> Result<Chunk, VmError> { let mut builder = ChunkBuilder::new(); let program = parse_program(code)?; //.map_err(|fe| VmError::ast_parser(format_forge_error(code, &fe)))?; builder.evaluate_program(&program)?; Ok(builder.take_chunk()) } pub fn chunk_ref(&self) -> ChunkRef { self.current_chunk.as_ref() } pub fn take_chunk(&mut self) -> Chunk { std::mem::take(&mut self.current_chunk) } } impl Visitor for ChunkBuilder { type Output = (); type Error = VmError; fn evaluate_value_expression( &mut self, expression: &ValueExpression, ) -> Result<Self::Output, Self::Error> { match expression { ValueExpression::Unary { operator, operand } => { self.evaluate_value_expression(operand.as_ref())?; match operator { UnaryOp::Not => Err(VmError::chunk_parser("Unsupported expression")), UnaryOp::Negate => { self.current_chunk.push_op(OpCode::Invert); Ok(()) } } } ValueExpression::Binary { lhs, rhs, operator } => { self.evaluate_value_expression(lhs.as_ref())?; self.evaluate_value_expression(rhs.as_ref())?; match operator { BinaryOp::Add => { self.current_chunk.push_op(OpCode::Add); Ok(()) } BinaryOp::Subtract => { self.current_chunk.push_op(OpCode::Subtract); Ok(()) } BinaryOp::Multiply => { self.current_chunk.push_op(OpCode::Multiply); Ok(()) } BinaryOp::Divide => { self.current_chunk.push_op(OpCode::Divide); Ok(()) } BinaryOp::Modulo => Err(VmError::chunk_parser("Unsupported expression")), BinaryOp::Equals => Err(VmError::chunk_parser("Unsupported expression")), BinaryOp::BoolAnd => Err(VmError::chunk_parser("Unsupported expression")), BinaryOp::BoolOr => Err(VmError::chunk_parser("Unsupported expression")), BinaryOp::NotEquals => Err(VmError::chunk_parser("Unsupported expression")), BinaryOp::LessThan => Err(VmError::chunk_parser("Unsupported expression")), BinaryOp::GreaterThan => Err(VmError::chunk_parser("Unsupported expression")), BinaryOp::LessThanEqual => Err(VmError::chunk_parser("Unsupported expression")), BinaryOp::GreaterThanEqual => { Err(VmError::chunk_parser("Unsupported expression")) } } } ValueExpression::Grouped(GroupedExpression { inner }) => { self.evaluate_value_expression(inner.as_ref()) } ValueExpression::Block(_) => Err(VmError::chunk_parser("Unsupported expression")), ValueExpression::Literal(val) => { self.current_chunk .op_constant(ForgeValue::from(val.clone())); Ok(()) } ValueExpression::DeclareIdentifier(_) => { Err(VmError::chunk_parser("Unsupported expression")) } ValueExpression::Assignment(_) => Err(VmError::chunk_parser("Unsupported expression")), ValueExpression::ConditionalBlock(_) => { Err(VmError::chunk_parser("Unsupported expression")) } ValueExpression::Identifier(_) => Err(VmError::chunk_parser("Unsupported expression")), ValueExpression::Accessor(_) => Err(VmError::chunk_parser("Unsupported expression")), ValueExpression::FunctionCall(_) => { Err(VmError::chunk_parser("Unsupported expression")) } ValueExpression::DeclareFunction(_) => { Err(VmError::chunk_parser("Unsupported expression")) } ValueExpression::Typeof(_) => Err(VmError::chunk_parser("Unsupported expression")), } } fn evaluate_void_expression( &mut self, expression: &VoidExpression, ) -> Result<Self::Output, Self::Error> { match expression { VoidExpression::ConditionLoop(_) => { Err(VmError::chunk_parser("Unsupported expression")) } VoidExpression::Import(_) => Err(VmError::chunk_parser("Unsupported expression")), VoidExpression::Export(_) => Err(VmError::chunk_parser("Unsupported expression")), VoidExpression::Print(_) => Err(VmError::chunk_parser("Unsupported expression")), VoidExpression::Return(_) => Err(VmError::chunk_parser("Unsupported expression")), } } fn evaluate_program(&mut self, program: &Program) -> Result<Self::Output, Self::Error> { for expr in program.0.iter() { self.evaluate_expression(expr)?; } self.current_chunk.push_op(OpCode::Return); Ok(()) } }