Get basic compiler working
This commit is contained in:
parent
3414aaee9b
commit
b0a4f9dc7e
183
src/compiler.rs
Normal file
183
src/compiler.rs
Normal 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))
|
||||
}
|
||||
}
|
||||
}
|
@ -15,17 +15,17 @@ impl From<io::Error> for GenericError {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CompilerError {
|
||||
pub enum SyntaxError {
|
||||
Fatal,
|
||||
ExpectedToken(Position, char),
|
||||
ExpectedExpression(Position, Option<Box<CompilerError>>),
|
||||
ExpectedExpression(Position, Option<Box<SyntaxError>>),
|
||||
ExpectedIdent(Position),
|
||||
ExpectedStatement(Position, Option<Box<CompilerError>>),
|
||||
ExpectedStatement(Position, Option<Box<SyntaxError>>),
|
||||
ExpectedPattern(Position),
|
||||
}
|
||||
|
||||
impl CompilerError {
|
||||
fn from_opt(from: &Option<Box<CompilerError>>) -> String {
|
||||
impl SyntaxError {
|
||||
fn from_opt(from: &Option<Box<SyntaxError>>) -> 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<CompilerError>),
|
||||
CanNotAssignVoidType,
|
||||
}
|
||||
|
||||
impl CompilerError {
|
||||
fn from_opt(from: &Option<Box<SyntaxError>>) -> String {
|
||||
if let Some(err) = from {
|
||||
format!("\n {}", err)
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
22
src/main.rs
22
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);
|
||||
}
|
||||
|
@ -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<ParsedReid, CompilerError> {
|
||||
pub fn parse(mut self) -> Result<ParsedReid, SyntaxError> {
|
||||
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<String, CompilerError> {
|
||||
pub fn get_or(self, error: SyntaxError) -> Result<String, SyntaxError> {
|
||||
match self.get() {
|
||||
Some(text) => Ok(text),
|
||||
None => Err(error),
|
||||
|
@ -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<Expression>),
|
||||
ExprStatement(Position, Expression),
|
||||
}
|
||||
|
||||
impl Statement {
|
||||
pub fn parse(parser: &mut Parser) -> Result<Statement, CompilerError> {
|
||||
pub fn parse(parser: &mut Parser) -> Result<Statement, SyntaxError> {
|
||||
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<Statement>),
|
||||
ValueRef(Position, Pattern),
|
||||
}
|
||||
|
||||
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 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<Pattern, CompilerError> {
|
||||
fn parse(parser: &mut Parser) -> Result<Pattern, SyntaxError> {
|
||||
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),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user