Skip to content

Commit

Permalink
Merge pull request #20 from ricglz/fifth-delivery
Browse files Browse the repository at this point in the history
fifth delivery
  • Loading branch information
ricglz authored May 16, 2022
2 parents 9e6abca + 8d4e19a commit 8166c98
Show file tree
Hide file tree
Showing 15 changed files with 425 additions and 116 deletions.
7 changes: 7 additions & 0 deletions examples/invalid/assign-to-void.ra
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
func test(): void {
a = 1;
}

func main(): void {
a = test();
}
3 changes: 3 additions & 0 deletions examples/invalid/undeclared-function.ra
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
func main(): void {
a = test();
}
7 changes: 7 additions & 0 deletions examples/invalid/wrong-arg-type.ra
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
func test(a: string): void {
print(a);
}

func main(): void {
test(false);
}
7 changes: 7 additions & 0 deletions examples/invalid/wrong-args-amount.ra
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
func test(a: string): void {
print(a);
}

func main(): void {
test();
}
13 changes: 13 additions & 0 deletions examples/valid/functions.ra
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
func test(): void {
a = 1;
}

func test2(a: int): int {
return a;
}

func main(): void {
test();
a = test2(2);
print(a);
}
12 changes: 12 additions & 0 deletions src/address/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ fn get_type_base(data_type: &Types) -> usize {

pub trait GenericAddressManager {
fn get_address(&mut self, data_type: &Types) -> Option<usize>;
fn size(&self) -> usize;
}

#[derive(PartialEq, Clone)]
Expand Down Expand Up @@ -74,6 +75,14 @@ impl GenericAddressManager for AddressManager {
let type_base = get_type_base(&data_type);
Some(self.base + type_counter_clone + type_base)
}
fn size(&self) -> usize {
self.counter
.to_owned()
.into_iter()
.map(|v| v.1)
.reduce(|a, v| a + v)
.unwrap_or(0)
}
}

impl fmt::Debug for AddressManager {
Expand Down Expand Up @@ -142,6 +151,9 @@ impl GenericAddressManager for TempAddressManager {
.pop()
.or(self.address_manager.get_address(data_type))
}
fn size(&self) -> usize {
self.address_manager.size()
}
}

impl fmt::Debug for TempAddressManager {
Expand Down
15 changes: 12 additions & 3 deletions src/ast/ast_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ pub enum AstNodeKind<'a> {
expr: Box<AstNode<'a>>,
statements: Vec<AstNode<'a>>,
},
FuncCall {
name: String,
exprs: Vec<AstNode<'a>>,
},
Return(Box<AstNode<'a>>),
}

impl<'a> From<AstNodeKind<'a>> for String {
Expand Down Expand Up @@ -92,7 +97,7 @@ impl fmt::Debug for AstNodeKind<'_> {
write!(f, "Unary({:?}, {:?})", operation, operand)
}
AstNodeKind::Main { functions, body } => {
write!(f, "Main(({:?}, {:#?}))", functions, body)
write!(f, "Main(({:#?}, {:#?}))", functions, body)
}
AstNodeKind::Argument { arg_type, name } => {
write!(f, "Argument({:?}, {})", arg_type, name)
Expand All @@ -105,8 +110,8 @@ impl fmt::Debug for AstNodeKind<'_> {
} => {
write!(
f,
"Function({}, {:#?}, {:#?}, {:?})",
name, arguments, return_type, body
"Function({}, {:?}, {:?}, {:#?})",
name, return_type, arguments, body
)
}
AstNodeKind::Write { exprs } => write!(f, "Write({:?})", exprs),
Expand Down Expand Up @@ -134,6 +139,10 @@ impl fmt::Debug for AstNodeKind<'_> {
} => {
write!(f, "For({expr:?}, {statements:?}, {assignment:?})")
}
AstNodeKind::FuncCall { name, exprs } => {
write!(f, "FunctionCall({name}, {exprs:?})")
}
AstNodeKind::Return(expr) => write!(f, "Return({expr:?})"),
}
}
}
61 changes: 50 additions & 11 deletions src/dir_func/function.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashMap;

use crate::{
address::{AddressManager, TempAddressManager, TOTAL_SIZE},
address::{AddressManager, GenericAddressManager, TempAddressManager, TOTAL_SIZE},
ast::ast_kind::AstNodeKind,
ast::AstNode,
enums::Types,
Expand Down Expand Up @@ -34,38 +34,49 @@ pub trait Scope {

#[derive(PartialEq, Clone, Debug)]
pub struct Function {
pub args: Vec<Variable>,
pub local_addresses: AddressManager,
pub name: String,
pub return_type: Types,
pub local_addresses: AddressManager,
pub temp_addresses: TempAddressManager,
pub variables: VariablesTable,
pub first_quad: usize,
}

impl Function {
fn new(name: String, return_type: Types) -> Self {
Self {
args: Vec::new(),
local_addresses: AddressManager::new(TOTAL_SIZE),
name,
return_type,
temp_addresses: TempAddressManager::new(),
variables: HashMap::new(),
first_quad: 0,
}
}

fn insert_variable_from_node<'a>(
&mut self,
node: AstNode<'a>,
global_fn: &mut GlobalScope,
argument: bool,
) -> Result<'a, ()> {
let clone = node.clone();
match Variable::from_node(node, self, global_fn) {
Ok((variable, global)) => {
let variable_clone = variable.clone();
let result = match global {
true => global_fn.insert_variable(variable),
false => self.insert_variable(variable),
};
match result {
Ok(_) => Ok(()),
Ok(_) => {
if argument {
self.args.push(variable_clone);
}
Ok(())
}
Err(kind) => Err(RaoulError::new(clone, kind)),
}
}
Expand All @@ -80,17 +91,37 @@ impl Function {
&mut self,
nodes: Vec<AstNode<'a>>,
global_fn: &mut GlobalScope,
) -> Results<'a, Self> {
) -> Results<'a, ()> {
let errors: Vec<RaoulError> = nodes
.into_iter()
.flat_map(AstNode::expand_node)
.filter_map(|node| {
self.insert_variable_from_node(node.to_owned(), global_fn, false)
.err()
})
.collect();
if errors.is_empty() {
Ok(())
} else {
Err(errors)
}
}

fn insert_args_from_nodes<'a>(
&mut self,
nodes: Vec<AstNode<'a>>,
global_fn: &mut GlobalScope,
) -> Results<'a, ()> {
let errors: Vec<RaoulError> = nodes
.into_iter()
.flat_map(AstNode::expand_node)
.filter_map(|node| {
self.insert_variable_from_node(node.to_owned(), global_fn)
self.insert_variable_from_node(node.to_owned(), global_fn, true)
.err()
})
.collect();
if errors.is_empty() {
Ok(self.to_owned())
Ok(())
} else {
Err(errors)
}
Expand All @@ -105,18 +136,26 @@ impl Function {
arguments,
} => {
let mut function = Function::new(name, return_type);
let args_iter = arguments.clone().into_iter();
let body_iter = body.clone().into_iter();
function.insert_variable_from_nodes(args_iter.chain(body_iter).collect(), global_fn)
function.insert_args_from_nodes(arguments, global_fn)?;
function.insert_variable_from_nodes(body, global_fn)?;
Ok(function)
}
AstNodeKind::Main { body, .. } => {
let mut function = Function::new("main".to_string(), Types::VOID);
let body_iter = body.clone().into_iter();
function.insert_variable_from_nodes(body_iter.collect(), global_fn)
function.insert_variable_from_nodes(body, global_fn)?;
Ok(function)
}
_ => unreachable!(),
}
}

pub fn size(&self) -> usize {
self.local_addresses.size() + self.temp_addresses.size()
}

pub fn update_quad(&mut self, first_quad: usize) {
self.first_quad = first_quad;
}
}

impl Scope for Function {
Expand Down
2 changes: 1 addition & 1 deletion src/dir_func/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use self::{
};

pub mod function;
mod variable;
pub mod variable;
pub mod variable_value;

#[derive(PartialEq, Debug)]
Expand Down
37 changes: 30 additions & 7 deletions src/enums/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use core::fmt;
use crate::ast::ast_kind::AstNodeKind;
use crate::ast::AstNode;
use crate::dir_func::function::VariablesTable;
use crate::dir_func::variable::Variable;
use crate::error::error_kind::RaoulErrorKind;
use crate::error::{RaoulError, Result};

Expand Down Expand Up @@ -100,6 +101,14 @@ impl Types {
}
}

fn get_variable<'a>(
name: &str,
variables: &'a VariablesTable,
global: &'a VariablesTable,
) -> Option<&'a Variable> {
variables.get(name).or(global.get(name))
}

pub fn from_node<'a>(
v: AstNode<'a>,
variables: &VariablesTable,
Expand All @@ -111,16 +120,23 @@ impl Types {
AstNodeKind::Float(_) => Ok(Types::FLOAT),
AstNodeKind::String(_) => Ok(Types::STRING),
AstNodeKind::Bool(_) => Ok(Types::BOOL),
AstNodeKind::Id(name) => {
if let Some(variable) = variables.get(&name).or(global.get(&name)) {
Ok(variable.data_type)
} else {
Err(RaoulError::new(
AstNodeKind::Id(name) => match Types::get_variable(&name, variables, global) {
Some(variable) => Ok(variable.data_type),
None => Err(RaoulError::new(
clone,
RaoulErrorKind::UndeclaredVar { name },
)),
},
AstNodeKind::FuncCall { name, .. } => {
match Types::get_variable(&name, variables, global) {
Some(variable) => Ok(variable.data_type),
None => Err(RaoulError::new(
clone,
RaoulErrorKind::UndeclaredVar { name },
))
RaoulErrorKind::UndeclaredFunction { name },
)),
}
}

AstNodeKind::Read => Ok(Types::STRING),
AstNodeKind::BinaryOperation { operator, lhs, rhs } => {
let lhs_type = Types::from_node(*lhs, variables, global)?;
Expand Down Expand Up @@ -178,6 +194,13 @@ pub enum Operator {
Read,
Goto,
GotoF,
End,
// Functions
Return,
EndProc,
Era,
GoSub,
Param,
}

impl Operator {
Expand Down
35 changes: 31 additions & 4 deletions src/error/error_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,29 @@ use crate::enums::Types;
#[derive(PartialEq, Eq, Clone)]
pub enum RaoulErrorKind {
Invalid,
UndeclaredVar { name: String },
RedeclaredFunction { name: String },
RedefinedType { name: String, from: Types, to: Types },
InvalidCast { from: Types, to: Types },
UndeclaredVar {
name: String,
},
UndeclaredFunction {
name: String,
},
RedeclaredFunction {
name: String,
},
RedefinedType {
name: String,
from: Types,
to: Types,
},
InvalidCast {
from: Types,
to: Types,
},
MemoryExceded,
UnmatchArgsAmount {
expected: usize,
given: usize,
},
}

impl fmt::Debug for RaoulErrorKind {
Expand All @@ -19,6 +37,9 @@ impl fmt::Debug for RaoulErrorKind {
RaoulErrorKind::UndeclaredVar { name } => {
write!(f, "Variable \"{}\" was not declared", name)
}
RaoulErrorKind::UndeclaredFunction { name } => {
write!(f, "Function \"{}\" was not declared", name)
}
RaoulErrorKind::RedeclaredFunction { name } => {
write!(f, "Function \"{}\" was already declared before", name)
}
Expand All @@ -37,6 +58,12 @@ impl fmt::Debug for RaoulErrorKind {
RaoulErrorKind::MemoryExceded => {
write!(f, "Memory was exceded")
}
RaoulErrorKind::UnmatchArgsAmount { expected, given } => {
write!(
f,
"Wrong args amount: Expected {expected}, but were given {given}"
)
}
}
}
}
Loading

0 comments on commit 8166c98

Please sign in to comment.