Skip to content
Snippets Groups Projects
chunk_builder.rs 4.43 KiB
Newer Older
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();
Louis's avatar
Louis committed
		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::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")),
		}
	}

	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(())
	}
}