From b0a4f9dc7e934e5d595162f33f4b48d00f219686 Mon Sep 17 00:00:00 2001 From: Teascade Date: Mon, 22 Jun 2020 21:49:21 +0300 Subject: [PATCH] Get basic compiler working --- src/compiler.rs | 183 ++++++++++++++++++++++++++++++++++++++ src/errors.rs | 48 +++++++--- src/main.rs | 22 +++-- src/parser/mod.rs | 8 +- src/parser/parsed_reid.rs | 36 ++++---- 5 files changed, 256 insertions(+), 41 deletions(-) create mode 100644 src/compiler.rs diff --git a/src/compiler.rs b/src/compiler.rs new file mode 100644 index 0000000..1648889 --- /dev/null +++ b/src/compiler.rs @@ -0,0 +1,183 @@ +use std::collections::HashMap; + +use super::errors::CompilerError; +use super::parser::{Expression, LiteralPattern, ParsedReid, Pattern, Position, Statement}; + +type Variable = (VariableID, VariableType); +type VariableID = u32; + +#[derive(Debug)] +pub enum Command { + InitializeVariable(VariableID, VariableType), + BeginScope, + EndScope, + Pop(u32), // Pop into registery u32 + Push(u32), // Push out of registery 32 + AssignVariable(VariableID, u32), // Assign variable from registery u32 + VarToReg(VariableID, u32), // Bring Variable to registery u32 + StringLit(String), // Bring String Literal to Heap +} + +#[derive(Debug, Copy, Clone)] +pub enum VariableType { + TypeString, +} + +pub struct Compiler { + parsed: ParsedReid, + root_scope: Scope, + list: Vec, +} + +#[derive(Debug)] +pub struct CompiledReid { + pub list: Vec, +} + +impl Compiler { + pub fn from(parsed: ParsedReid) -> Compiler { + Compiler { + parsed, + root_scope: Scope::default(), + list: Vec::new(), + } + } + + pub fn compile(mut self) -> Result { + self.handle_expression(self.parsed.0.clone())?; + Ok(CompiledReid { list: self.list }) + } + + fn handle_expression( + &mut self, + exp: Expression, + ) -> Result, CompilerError> { + match exp { + Expression::BlockExpr(pos, list) => { + self.list.push(Command::BeginScope); + self.root_scope.begin_scope(); + + for statement in list { + self.handle_statement(statement)?; + } + + self.root_scope.end_scope(pos)?; + self.list.push(Command::EndScope); + Ok(None) + } + Expression::ValueRef(_, val) => match val { + Pattern::IdentPattern(pos, ident) => { + if let Some(var) = self.root_scope.get(ident.clone()) { + self.list.push(Command::VarToReg(var.0, 0)); + self.list.push(Command::Push(0)); + Ok(Some(var.1)) + } else { + Err(CompilerError::VariableNotExists(pos, ident)) + } + } + Pattern::LiteralPattern(_, literal) => { + let vtype = self.handle_literal(literal)?; + Ok(Some(vtype)) + } + }, + } + } + + fn handle_statement( + &mut self, + statement: Statement, + ) -> Result, CompilerError> { + match statement { + Statement::LetStatement(pos, ident, val) => { + let res = self.handle_expression(*val); + match res { + Ok(vtype) => { + if let Some(vtype) = vtype { + self.root_scope.add_var(pos, ident.clone(), vtype)?; + let var = self.root_scope.get(ident).unwrap(); + self.list.push(Command::InitializeVariable(var.0, var.1)); + self.list.push(Command::Pop(0)); + self.list.push(Command::AssignVariable(var.0, 0)); + Ok(None) + } else { + Err(CompilerError::LetFailed( + pos, + Box::new(CompilerError::CanNotAssignVoidType), + )) + } + } + Err(err) => Err(CompilerError::LetFailed(pos, Box::new(err))), + } + } + Statement::ExprStatement(pos, expr) => self.handle_expression(expr), + } + } + + fn handle_literal(&mut self, pattern: LiteralPattern) -> Result { + match pattern { + LiteralPattern::StringLit(string) => self.list.push(Command::StringLit(string)), + } + Ok(VariableType::TypeString) + } +} + +#[derive(Default)] +pub struct Scope { + counter: VariableID, + variables: HashMap, + innerScope: Option>, +} + +impl Scope { + fn get(&self, variable: String) -> Option { + if let Some(val) = self.variables.get(&variable) { + Some(*val) + } else if let Some(inner) = &self.innerScope { + if let Some(val) = inner.get(variable) { + Some((val.0 + self.counter, val.1)) + } else { + None + } + } else { + None + } + } + + fn add_var( + &mut self, + pos: Position, + variable: String, + vtype: VariableType, + ) -> Result<(), CompilerError> { + if self.variables.contains_key(&variable) { + Err(CompilerError::VariableExists(pos, variable)) + } else if let Some(inner) = &mut self.innerScope { + inner.add_var(pos, variable, vtype) + } else { + self.variables.insert(variable, (self.counter, vtype)); + self.counter += 1; + Ok(()) + } + } + + fn begin_scope(&mut self) { + if let Some(inner) = &mut self.innerScope { + inner.begin_scope(); + } else { + self.innerScope = Some(Box::default()); + } + } + + fn end_scope(&mut self, pos: Position) -> Result<(), CompilerError> { + if let Some(inner) = &mut self.innerScope { + if inner.innerScope.is_some() { + inner.end_scope(pos)?; + } else { + self.innerScope = None; + } + Ok(()) + } else { + Err(CompilerError::InvalidScopeExit(pos)) + } + } +} diff --git a/src/errors.rs b/src/errors.rs index dc1e60d..cdb8808 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -15,17 +15,17 @@ impl From for GenericError { } #[derive(Debug)] -pub enum CompilerError { +pub enum SyntaxError { Fatal, ExpectedToken(Position, char), - ExpectedExpression(Position, Option>), + ExpectedExpression(Position, Option>), ExpectedIdent(Position), - ExpectedStatement(Position, Option>), + ExpectedStatement(Position, Option>), ExpectedPattern(Position), } -impl CompilerError { - fn from_opt(from: &Option>) -> String { +impl SyntaxError { + fn from_opt(from: &Option>) -> String { if let Some(err) = from { format!("\n {}", err) } else { @@ -34,24 +34,44 @@ impl CompilerError { } } -impl Display for CompilerError { +impl Display for SyntaxError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let text = match self { - CompilerError::Fatal => "Fatal error".to_string(), - CompilerError::ExpectedToken(pos, c) => format!("Expected token '{}' at {}", c, pos), - CompilerError::ExpectedExpression(pos, err) => format!( + SyntaxError::Fatal => "Fatal error".to_string(), + SyntaxError::ExpectedToken(pos, c) => format!("Expected token '{}' at {}", c, pos), + SyntaxError::ExpectedExpression(pos, err) => format!( "Expected expression at {}{}", pos, - CompilerError::from_opt(err) + SyntaxError::from_opt(err) ), - CompilerError::ExpectedIdent(pos) => format!("Expected ident at {}", pos), - CompilerError::ExpectedStatement(pos, err) => format!( + SyntaxError::ExpectedIdent(pos) => format!("Expected ident at {}", pos), + SyntaxError::ExpectedStatement(pos, err) => format!( "Expected statement at {}{}", pos, - CompilerError::from_opt(err) + SyntaxError::from_opt(err) ), - CompilerError::ExpectedPattern(pos) => format!("Expected pattern at {}", pos), + SyntaxError::ExpectedPattern(pos) => format!("Expected pattern at {}", pos), }; write!(f, "{}", text) } } + +#[derive(Debug)] +pub enum CompilerError { + Fatal, + VariableExists(Position, String), + VariableNotExists(Position, String), + InvalidScopeExit(Position), + LetFailed(Position, Box), + CanNotAssignVoidType, +} + +impl CompilerError { + fn from_opt(from: &Option>) -> String { + if let Some(err) = from { + format!("\n {}", err) + } else { + String::new() + } + } +} diff --git a/src/main.rs b/src/main.rs index 7b1478e..7c430cb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,29 @@ +mod compiler; mod errors; mod file_io; mod parser; +use compiler::Compiler; use file_io::open_file; use parser::Parser; use std::path::Path; fn main() { let path = Path::new("reid_src/test.reid"); - let reid = Parser::from(open_file(&path).ok().unwrap()).parse(); - if let Err(error) = reid { - eprintln!("Syntax error: {}", error); - std::process::exit(1); + let parsed = Parser::from(open_file(&path).ok().unwrap()).parse(); + match parsed { + Err(error) => { + eprintln!("Syntax error: {}", error); + std::process::exit(1); + } + Ok(parsed) => { + dbg!(&parsed); + let compiled = Compiler::from(parsed).compile(); + if let Err(error) = compiled { + eprintln!("Compilation error: {:#?}", error); + std::process::exit(1); + } + dbg!(compiled); + } } - dbg!(reid); } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 2c55f3a..27d4d7b 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,7 +1,7 @@ mod parsed_reid; -use super::errors::CompilerError; -use parsed_reid::{Expression, ParsedReid, Statement}; +use super::errors::SyntaxError; +pub use parsed_reid::*; use std::fmt; use std::fmt::Display; @@ -31,7 +31,7 @@ impl Parser { } } - pub fn parse(mut self) -> Result { + pub fn parse(mut self) -> Result { let mut statement_list = Vec::new(); let mut error = None; @@ -211,7 +211,7 @@ impl Expect<'_> { } self.text } - pub fn get_or(self, error: CompilerError) -> Result { + pub fn get_or(self, error: SyntaxError) -> Result { match self.get() { Some(text) => Ok(text), None => Err(error), diff --git a/src/parser/parsed_reid.rs b/src/parser/parsed_reid.rs index 5c6fc02..a0e2d8e 100644 --- a/src/parser/parsed_reid.rs +++ b/src/parser/parsed_reid.rs @@ -1,35 +1,35 @@ -use super::{CompilerError, Parser, Position}; +use super::{Parser, Position, SyntaxError}; type Ident = String; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ParsedReid(pub Expression); -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Statement { LetStatement(Position, Ident, Box), ExprStatement(Position, Expression), } impl Statement { - pub fn parse(parser: &mut Parser) -> Result { + pub fn parse(parser: &mut Parser) -> Result { let pos = parser.pos(); if let Some(_) = parser.expect("let").get() { let ident = parser .expect_ident() - .get_or(CompilerError::ExpectedIdent(pos))?; + .get_or(SyntaxError::ExpectedIdent(pos))?; parser .expect("=") - .get_or(CompilerError::ExpectedToken(pos, '='))?; + .get_or(SyntaxError::ExpectedToken(pos, '='))?; match Expression::parse(parser) { Ok(expr) => { parser .expect(";") - .get_or(CompilerError::ExpectedToken(pos, ';'))?; + .get_or(SyntaxError::ExpectedToken(pos, ';'))?; Ok(Statement::LetStatement(pos, ident, Box::new(expr))) } - Err(err) => Err(CompilerError::ExpectedExpression(pos, Some(Box::new(err)))), + Err(err) => Err(SyntaxError::ExpectedExpression(pos, Some(Box::new(err)))), } } else { match Expression::parse(parser) { @@ -37,23 +37,23 @@ impl Statement { let statement = Statement::ExprStatement(pos, expr); parser .expect(";") - .get_or(CompilerError::ExpectedToken(pos, ';'))?; + .get_or(SyntaxError::ExpectedToken(pos, ';'))?; Ok(statement) } - Err(err) => Err(CompilerError::ExpectedStatement(pos, Some(Box::new(err)))), + Err(err) => Err(SyntaxError::ExpectedStatement(pos, Some(Box::new(err)))), } } } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Expression { BlockExpr(Position, Vec), ValueRef(Position, Pattern), } impl Expression { - pub fn parse(parser: &mut Parser) -> Result { + pub fn parse(parser: &mut Parser) -> Result { let begin_pos = parser.pos(); let expect = parser.expect("{"); @@ -71,24 +71,24 @@ impl Expression { if let Some(_) = parser.expect("}").get() { Ok(Expression::BlockExpr(begin_pos, statement_list)) } else { - Err(CompilerError::ExpectedToken(parser.pos(), '}')) + Err(SyntaxError::ExpectedToken(parser.pos(), '}')) } } else if let Ok(pattern) = Pattern::parse(parser) { Ok(Expression::ValueRef(begin_pos, pattern)) } else { - Err(CompilerError::ExpectedExpression(begin_pos, None)) + Err(SyntaxError::ExpectedExpression(begin_pos, None)) } } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Pattern { IdentPattern(Position, Ident), LiteralPattern(Position, LiteralPattern), } impl Pattern { - fn parse(parser: &mut Parser) -> Result { + fn parse(parser: &mut Parser) -> Result { let pos = parser.pos(); if let Some(string) = parser.expect_string_lit().get() { Ok(Pattern::LiteralPattern( @@ -98,12 +98,12 @@ impl Pattern { } else if let Some(ident) = parser.expect_ident().get() { Ok(Pattern::IdentPattern(pos, ident)) } else { - Err(CompilerError::ExpectedPattern(pos)) + Err(SyntaxError::ExpectedPattern(pos)) } } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum LiteralPattern { StringLit(String), }