Get basic compiler working

This commit is contained in:
Sofia 2020-06-22 21:49:21 +03:00
parent 3414aaee9b
commit b0a4f9dc7e
5 changed files with 256 additions and 41 deletions

183
src/compiler.rs Normal file
View File

@ -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<Command>,
}
#[derive(Debug)]
pub struct CompiledReid {
pub list: Vec<Command>,
}
impl Compiler {
pub fn from(parsed: ParsedReid) -> Compiler {
Compiler {
parsed,
root_scope: Scope::default(),
list: Vec::new(),
}
}
pub fn compile(mut self) -> Result<CompiledReid, CompilerError> {
self.handle_expression(self.parsed.0.clone())?;
Ok(CompiledReid { list: self.list })
}
fn handle_expression(
&mut self,
exp: Expression,
) -> Result<Option<VariableType>, 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<Option<VariableType>, 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<VariableType, CompilerError> {
match pattern {
LiteralPattern::StringLit(string) => self.list.push(Command::StringLit(string)),
}
Ok(VariableType::TypeString)
}
}
#[derive(Default)]
pub struct Scope {
counter: VariableID,
variables: HashMap<String, Variable>,
innerScope: Option<Box<Scope>>,
}
impl Scope {
fn get(&self, variable: String) -> Option<Variable> {
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))
}
}
}

View File

@ -15,17 +15,17 @@ impl From<io::Error> for GenericError {
} }
#[derive(Debug)] #[derive(Debug)]
pub enum CompilerError { pub enum SyntaxError {
Fatal, Fatal,
ExpectedToken(Position, char), ExpectedToken(Position, char),
ExpectedExpression(Position, Option<Box<CompilerError>>), ExpectedExpression(Position, Option<Box<SyntaxError>>),
ExpectedIdent(Position), ExpectedIdent(Position),
ExpectedStatement(Position, Option<Box<CompilerError>>), ExpectedStatement(Position, Option<Box<SyntaxError>>),
ExpectedPattern(Position), ExpectedPattern(Position),
} }
impl CompilerError { impl SyntaxError {
fn from_opt(from: &Option<Box<CompilerError>>) -> String { fn from_opt(from: &Option<Box<SyntaxError>>) -> String {
if let Some(err) = from { if let Some(err) = from {
format!("\n {}", err) format!("\n {}", err)
} else { } else {
@ -34,24 +34,44 @@ impl CompilerError {
} }
} }
impl Display for CompilerError { impl Display for SyntaxError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let text = match self { let text = match self {
CompilerError::Fatal => "Fatal error".to_string(), SyntaxError::Fatal => "Fatal error".to_string(),
CompilerError::ExpectedToken(pos, c) => format!("Expected token '{}' at {}", c, pos), SyntaxError::ExpectedToken(pos, c) => format!("Expected token '{}' at {}", c, pos),
CompilerError::ExpectedExpression(pos, err) => format!( SyntaxError::ExpectedExpression(pos, err) => format!(
"Expected expression at {}{}", "Expected expression at {}{}",
pos, pos,
CompilerError::from_opt(err) SyntaxError::from_opt(err)
), ),
CompilerError::ExpectedIdent(pos) => format!("Expected ident at {}", pos), SyntaxError::ExpectedIdent(pos) => format!("Expected ident at {}", pos),
CompilerError::ExpectedStatement(pos, err) => format!( SyntaxError::ExpectedStatement(pos, err) => format!(
"Expected statement at {}{}", "Expected statement at {}{}",
pos, 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) write!(f, "{}", text)
} }
} }
#[derive(Debug)]
pub enum CompilerError {
Fatal,
VariableExists(Position, String),
VariableNotExists(Position, String),
InvalidScopeExit(Position),
LetFailed(Position, Box<CompilerError>),
CanNotAssignVoidType,
}
impl CompilerError {
fn from_opt(from: &Option<Box<SyntaxError>>) -> String {
if let Some(err) = from {
format!("\n {}", err)
} else {
String::new()
}
}
}

View File

@ -1,17 +1,29 @@
mod compiler;
mod errors; mod errors;
mod file_io; mod file_io;
mod parser; mod parser;
use compiler::Compiler;
use file_io::open_file; use file_io::open_file;
use parser::Parser; use parser::Parser;
use std::path::Path; use std::path::Path;
fn main() { fn main() {
let path = Path::new("reid_src/test.reid"); let path = Path::new("reid_src/test.reid");
let reid = Parser::from(open_file(&path).ok().unwrap()).parse(); let parsed = Parser::from(open_file(&path).ok().unwrap()).parse();
if let Err(error) = reid { match parsed {
eprintln!("Syntax error: {}", error); Err(error) => {
std::process::exit(1); 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);
} }

View File

@ -1,7 +1,7 @@
mod parsed_reid; mod parsed_reid;
use super::errors::CompilerError; use super::errors::SyntaxError;
use parsed_reid::{Expression, ParsedReid, Statement}; pub use parsed_reid::*;
use std::fmt; use std::fmt;
use std::fmt::Display; use std::fmt::Display;
@ -31,7 +31,7 @@ impl Parser {
} }
} }
pub fn parse(mut self) -> Result<ParsedReid, CompilerError> { pub fn parse(mut self) -> Result<ParsedReid, SyntaxError> {
let mut statement_list = Vec::new(); let mut statement_list = Vec::new();
let mut error = None; let mut error = None;
@ -211,7 +211,7 @@ impl Expect<'_> {
} }
self.text self.text
} }
pub fn get_or(self, error: CompilerError) -> Result<String, CompilerError> { pub fn get_or(self, error: SyntaxError) -> Result<String, SyntaxError> {
match self.get() { match self.get() {
Some(text) => Ok(text), Some(text) => Ok(text),
None => Err(error), None => Err(error),

View File

@ -1,35 +1,35 @@
use super::{CompilerError, Parser, Position}; use super::{Parser, Position, SyntaxError};
type Ident = String; type Ident = String;
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct ParsedReid(pub Expression); pub struct ParsedReid(pub Expression);
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum Statement { pub enum Statement {
LetStatement(Position, Ident, Box<Expression>), LetStatement(Position, Ident, Box<Expression>),
ExprStatement(Position, Expression), ExprStatement(Position, Expression),
} }
impl Statement { impl Statement {
pub fn parse(parser: &mut Parser) -> Result<Statement, CompilerError> { pub fn parse(parser: &mut Parser) -> Result<Statement, SyntaxError> {
let pos = parser.pos(); let pos = parser.pos();
if let Some(_) = parser.expect("let").get() { if let Some(_) = parser.expect("let").get() {
let ident = parser let ident = parser
.expect_ident() .expect_ident()
.get_or(CompilerError::ExpectedIdent(pos))?; .get_or(SyntaxError::ExpectedIdent(pos))?;
parser parser
.expect("=") .expect("=")
.get_or(CompilerError::ExpectedToken(pos, '='))?; .get_or(SyntaxError::ExpectedToken(pos, '='))?;
match Expression::parse(parser) { match Expression::parse(parser) {
Ok(expr) => { Ok(expr) => {
parser parser
.expect(";") .expect(";")
.get_or(CompilerError::ExpectedToken(pos, ';'))?; .get_or(SyntaxError::ExpectedToken(pos, ';'))?;
Ok(Statement::LetStatement(pos, ident, Box::new(expr))) 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 { } else {
match Expression::parse(parser) { match Expression::parse(parser) {
@ -37,23 +37,23 @@ impl Statement {
let statement = Statement::ExprStatement(pos, expr); let statement = Statement::ExprStatement(pos, expr);
parser parser
.expect(";") .expect(";")
.get_or(CompilerError::ExpectedToken(pos, ';'))?; .get_or(SyntaxError::ExpectedToken(pos, ';'))?;
Ok(statement) 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 { pub enum Expression {
BlockExpr(Position, Vec<Statement>), BlockExpr(Position, Vec<Statement>),
ValueRef(Position, Pattern), ValueRef(Position, Pattern),
} }
impl Expression { impl Expression {
pub fn parse(parser: &mut Parser) -> Result<Expression, CompilerError> { pub fn parse(parser: &mut Parser) -> Result<Expression, SyntaxError> {
let begin_pos = parser.pos(); let begin_pos = parser.pos();
let expect = parser.expect("{"); let expect = parser.expect("{");
@ -71,24 +71,24 @@ impl Expression {
if let Some(_) = parser.expect("}").get() { if let Some(_) = parser.expect("}").get() {
Ok(Expression::BlockExpr(begin_pos, statement_list)) Ok(Expression::BlockExpr(begin_pos, statement_list))
} else { } else {
Err(CompilerError::ExpectedToken(parser.pos(), '}')) Err(SyntaxError::ExpectedToken(parser.pos(), '}'))
} }
} else if let Ok(pattern) = Pattern::parse(parser) { } else if let Ok(pattern) = Pattern::parse(parser) {
Ok(Expression::ValueRef(begin_pos, pattern)) Ok(Expression::ValueRef(begin_pos, pattern))
} else { } else {
Err(CompilerError::ExpectedExpression(begin_pos, None)) Err(SyntaxError::ExpectedExpression(begin_pos, None))
} }
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum Pattern { pub enum Pattern {
IdentPattern(Position, Ident), IdentPattern(Position, Ident),
LiteralPattern(Position, LiteralPattern), LiteralPattern(Position, LiteralPattern),
} }
impl Pattern { impl Pattern {
fn parse(parser: &mut Parser) -> Result<Pattern, CompilerError> { fn parse(parser: &mut Parser) -> Result<Pattern, SyntaxError> {
let pos = parser.pos(); let pos = parser.pos();
if let Some(string) = parser.expect_string_lit().get() { if let Some(string) = parser.expect_string_lit().get() {
Ok(Pattern::LiteralPattern( Ok(Pattern::LiteralPattern(
@ -98,12 +98,12 @@ impl Pattern {
} else if let Some(ident) = parser.expect_ident().get() { } else if let Some(ident) = parser.expect_ident().get() {
Ok(Pattern::IdentPattern(pos, ident)) Ok(Pattern::IdentPattern(pos, ident))
} else { } else {
Err(CompilerError::ExpectedPattern(pos)) Err(SyntaxError::ExpectedPattern(pos))
} }
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum LiteralPattern { pub enum LiteralPattern {
StringLit(String), StringLit(String),
} }