Skip to content

Commit

Permalink
Merge pull request #5 from ricglz/second_delivery
Browse files Browse the repository at this point in the history
Second delivery
  • Loading branch information
ricglz authored Apr 23, 2022
2 parents b2d2d2d + 582a021 commit 1eb2717
Show file tree
Hide file tree
Showing 21 changed files with 772 additions and 80 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/test-and-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
on: [push]

jobs:
build_and_test:
name: Rust project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
- uses: actions-rs/cargo@v1
with:
command: test
- uses: actions-rs/cargo@v1
with:
command: build
args: --release --all-features
7 changes: 7 additions & 0 deletions examples/invalid/syntax-error.ra
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn myFunction(v: integer): void {
f = 1
}

func main(): void {
myFunction(1);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
func main(): void {
a = 1;
print(a);
a = b;
c = d;
}
9 changes: 9 additions & 0 deletions examples/valid/assignment.ra
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
func my_function(): void {
b = 2;
}

func main(): void {
a = 1;
global c = 2;
print(a, c);
}
9 changes: 9 additions & 0 deletions examples/valid/assignment_every_type.ra
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
func helper(a: int, b: float, c: string, d: bool): void {}

func main(): void {
a = 1;
b = 1.0;
c = "my string";
d = false;
print(a, b, c, d);
}
File renamed without changes.
88 changes: 88 additions & 0 deletions src/ast/ast_kind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use super::AstNode;
use crate::enums::{Operations, Types};
use std::fmt;

#[derive(PartialEq, Clone)]
pub enum AstNodeKind<'a> {
Id(String),
Integer(i64),
Float(f64),
String(String),
Bool(bool),
Assignment {
global: bool,
name: String,
value: Box<AstNode<'a>>,
},
UnaryOperation {
operation: Operations,
operand: Box<AstNode<'a>>,
},
Main {
functions: Vec<AstNode<'a>>,
body: Vec<AstNode<'a>>,
},
Argument {
arg_type: Types,
name: String,
},
Function {
arguments: Vec<AstNode<'a>>,
body: Vec<AstNode<'a>>,
name: String,
return_type: Types,
},
Write {
exprs: Vec<AstNode<'a>>,
},
}

impl<'a> From<AstNodeKind<'a>> for String {
fn from(val: AstNodeKind) -> Self {
match val {
AstNodeKind::Integer(n) => n.to_string(),
AstNodeKind::Id(s) => s.to_string(),
AstNodeKind::String(s) => s.to_string(),
node => unreachable!("Node {:?}, cannot be a string", node),
}
}
}

impl fmt::Debug for AstNodeKind<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self {
AstNodeKind::Id(s) => write!(f, "Id({})", s),
AstNodeKind::Integer(n) => write!(f, "Integer({})", n),
AstNodeKind::Float(n) => write!(f, "Float({})", n),
AstNodeKind::String(s) => write!(f, "String({})", s),
AstNodeKind::Bool(s) => write!(f, "Bool({})", s),
AstNodeKind::Assignment {
global,
name,
value,
} => write!(f, "Assignment({}, {}, {:?})", global, name, value),
AstNodeKind::UnaryOperation { operation, operand } => {
write!(f, "Unary({:?}, {:?})", operation, operand)
}
AstNodeKind::Main { functions, body } => {
write!(f, "Main(({:?}, {:#?}))", functions, body)
}
AstNodeKind::Argument { arg_type, name } => {
write!(f, "Argument({:?}, {})", arg_type, name)
}
AstNodeKind::Function {
arguments,
body,
name,
return_type,
} => {
write!(
f,
"Function({}, {:#?}, {:#?}, {:?})",
name, arguments, return_type, body
)
}
AstNodeKind::Write { exprs } => write!(f, "Write({:?})", exprs),
}
}
}
23 changes: 23 additions & 0 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
pub mod ast_kind;

use self::ast_kind::AstNodeKind;
use pest::Span;
use std::fmt;

#[derive(PartialEq, Clone)]
pub struct AstNode<'a> {
pub kind: AstNodeKind<'a>,
pub span: Span<'a>,
}

impl<'a> From<AstNode<'a>> for String {
fn from(val: AstNode) -> Self {
val.kind.into()
}
}

impl fmt::Debug for AstNode<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.kind)
}
}
89 changes: 89 additions & 0 deletions src/dir_func/function.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use std::collections::HashMap;

use crate::{
ast::ast_kind::AstNodeKind,
ast::AstNode,
enums::Types,
error::{RaoulError, Result, Results},
};

use super::variable::{build_variable, Variable};

pub type VariablesTable = HashMap<String, Variable>;

#[derive(PartialEq, Clone, Debug)]
pub struct Function {
pub name: String,
pub return_type: Types,
variables: VariablesTable,
}

impl Function {
pub fn new(name: String, return_type: Types) -> Self {
Self {
name,
return_type,
variables: HashMap::new(),
}
}

pub fn insert_variable(&mut self, variable: Variable) {
self.variables.insert(variable.name.clone(), variable);
}

fn insert_variable_from_node<'a>(
&mut self,
node: AstNode<'a>,
global_fn: &mut Function,
) -> Result<'a, ()> {
match build_variable(node, &self.variables) {
Ok((variable, global)) => Ok(match global {
true => global_fn.insert_variable(variable),
false => self.insert_variable(variable),
}),
Err(error) => match error.is_invalid() {
true => Ok(()),
false => Err(error),
},
}
}

fn insert_variable_from_nodes<'a>(
&mut self,
nodes: Vec<AstNode<'a>>,
global_fn: &mut Function,
) -> Results<'a, Self> {
let errors: Vec<RaoulError> = nodes
.into_iter()
.filter_map(|node| self.insert_variable_from_node(node, global_fn).err())
.collect();
if errors.is_empty() {
Ok(self.to_owned())
} else {
Err(errors)
}
}

pub fn try_create<'a>(tuple: (AstNode<'a>, &mut Function)) -> Results<'a, Function> {
let (v, global_fn) = tuple;
match v.kind {
AstNodeKind::Function {
name,
return_type,
body,
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)
}
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)
}
_ => unreachable!(),
}
}
}
62 changes: 62 additions & 0 deletions src/dir_func/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use std::collections::HashMap;

use crate::{
ast::ast_kind::AstNodeKind,
ast::AstNode,
enums::Types,
error::{RaoulError, Results},
};

use self::{function::Function, variable::Variable};

mod function;
mod variable;
mod variable_value;

#[derive(PartialEq, Debug)]
pub struct DirFunc {
functions: HashMap<String, Function>,
global_fn: Function,
}

impl DirFunc {
pub fn new() -> Self {
Self {
global_fn: Function::new("global".to_string(), crate::enums::Types::VOID),
functions: HashMap::new(),
}
}

fn insert_function(&mut self, function: Function) {
self.functions.insert(function.name.clone(), function);
}

fn insert_function_from_node<'a>(&mut self, node: AstNode<'a>) -> Results<'a, ()> {
let function = Function::try_create((node, &mut self.global_fn))?;
if function.return_type != Types::VOID {
self.global_fn
.insert_variable(Variable::from(function.clone()))
}
Ok(self.insert_function(function))
}

pub fn build_dir_func<'a>(&mut self, node: AstNode<'a>) -> Results<'a, ()> {
let clone = node.clone();
match node.kind {
AstNodeKind::Main { functions, .. } => {
let errors: Vec<RaoulError> = functions
.into_iter()
.chain(Some(clone))
.filter_map(|node| self.insert_function_from_node(node).err())
.flatten()
.collect();
if errors.is_empty() {
Ok(())
} else {
Err(errors)
}
}
_ => unreachable!(),
}
}
}
64 changes: 64 additions & 0 deletions src/dir_func/variable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::{
ast::ast_kind::AstNodeKind,
ast::AstNode,
enums::Types,
error::error_kind::RaoulErrorKind,
error::{RaoulError, Result},
};

use super::{
function::{Function, VariablesTable},
variable_value::{build_variable_value, VariableValue},
};

#[derive(Clone, PartialEq, Debug)]
pub struct Variable {
data_type: Types,
pub name: String,
pub value: Option<VariableValue>,
}

impl From<Function> for Variable {
fn from(function: Function) -> Self {
Variable {
data_type: function.return_type,
name: function.name,
value: None,
}
}
}

pub fn build_variable<'a>(
v: AstNode<'a>,
variables: &VariablesTable,
) -> Result<'a, (Variable, bool)> {
match v.kind {
AstNodeKind::Assignment {
name,
value: node_value,
global,
} => {
let value = build_variable_value(*node_value, variables)?;
Ok((
Variable {
data_type: Types::from(value.clone()),
name,
value: Some(value),
},
global,
))
}
AstNodeKind::Argument {
arg_type: data_type,
name,
} => Ok((
Variable {
data_type,
name,
value: None,
},
false,
)),
_ => Err(RaoulError::new(v, RaoulErrorKind::Invalid)),
}
}
Loading

0 comments on commit 1eb2717

Please sign in to comment.