Skip to content
Closed
23 changes: 12 additions & 11 deletions src/environment/environment.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use crate::ir::ast::Function;
use crate::ir::ast::Name;
use crate::ir::ast::ValueConstructor;
use crate::ir::ast::Type;
use std::collections::HashMap;
use std::collections::LinkedList;
use std::sync::Arc;

#[derive(Clone)]
pub struct Scope<A> {
pub variables: HashMap<Name, (bool, A)>,
pub functions: HashMap<Name, Function>,
pub adts: HashMap<Name, Vec<ValueConstructor>>,
pub adts: HashMap<Name, Arc<HashMap<Name, Vec<Type>>>>,
}

impl<A: Clone> Scope<A> {
Expand All @@ -30,8 +31,8 @@ impl<A: Clone> Scope<A> {
return ();
}

fn map_adt(&mut self, name: Name, adt: Vec<ValueConstructor>) -> () {
self.adts.insert(name.clone(), adt);
fn map_adt(&mut self, name: Name, adt: HashMap<Name, Vec<Type>>) -> () {
self.adts.insert(name.clone(), Arc::new(adt));
return ();
}

Expand All @@ -45,7 +46,7 @@ impl<A: Clone> Scope<A> {
self.functions.get(name)
}

fn lookup_adt(&self, name: &Name) -> Option<&Vec<ValueConstructor>> {
fn lookup_adt(&self, name: &Name) -> Option<&Arc<HashMap<Name, Vec<Type>>>> {
self.adts.get(name)
}
}
Expand Down Expand Up @@ -78,15 +79,15 @@ impl<A: Clone> Environment<A> {
}
}

pub fn map_adt(&mut self, name: Name, cons: Vec<ValueConstructor>) -> () {
pub fn map_adt(&mut self, name: Name, cons: HashMap<Name, Vec<Type>>) -> () {
match self.stack.front_mut() {
None => self.globals.map_adt(name, cons),
Some(top) => top.map_adt(name, cons),
}
}

pub fn lookup(&self, var: &Name) -> Option<(bool, A)> {
for scope in self.stack.iter() {
for scope in &self.stack {
if let Some(value) = scope.lookup_var(var) {
return Some(value);
}
Expand All @@ -95,16 +96,16 @@ impl<A: Clone> Environment<A> {
}

pub fn lookup_function(&self, name: &Name) -> Option<&Function> {
for scope in self.stack.iter() {
for scope in &self.stack {
if let Some(func) = scope.lookup_function(name) {
return Some(func);
}
}
self.globals.lookup_function(name)
}

pub fn lookup_adt(&self, name: &Name) -> Option<&Vec<ValueConstructor>> {
for scope in self.stack.iter() {
pub fn lookup_adt(&self, name: &Name) -> Option<&Arc<HashMap<Name, Vec<Type>>>> {
for scope in &self.stack {
if let Some(cons) = scope.lookup_adt(name) {
return Some(cons);
}
Expand All @@ -128,7 +129,7 @@ impl<A: Clone> Environment<A> {
let mut vars = Vec::new();

// First get variables from local scopes (in reverse order to respect shadowing)
for scope in self.stack.iter() {
for scope in &self.stack {
for (name, value) in &scope.variables {
if !vars.iter().any(|(n, _)| n == name) {
vars.push((name.clone(), value.clone()));
Expand Down
11 changes: 10 additions & 1 deletion src/interpreter/expression_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ fn eval_propagate_expression(
Expression::COk(e) => Ok(ExpressionResult::Value(*e)),
Expression::CErr(e) => Ok(ExpressionResult::Propagate(*e)),
Expression::CNothing => Ok(ExpressionResult::Propagate(Expression::CString(
"Couldn't unwrap Nothing".to_string(),
"Couldn't unwrap Anything".to_string(),
))),
_ => Err(String::from("'propagate' expects a Just or Ok.")),
}
Expand Down Expand Up @@ -535,6 +535,15 @@ fn eval_list_value(
Ok(ExpressionResult::Value(Expression::ListValue(values)))
}

/*
fn eval_match_expression(
expr: Expression,
arms: Vec<Expression>,
env: &Environment<Expression>
) -> Result<ExpressionResult, String> {

}*/

#[cfg(test)]
mod tests {
use super::*;
Expand Down
22 changes: 6 additions & 16 deletions src/ir/ast.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashMap;

// Type alias for variable and function names
pub type Name = String;

Expand Down Expand Up @@ -52,22 +54,9 @@ pub enum Type {
TTuple(Vec<Type>),
TMaybe(Box<Type>),
TResult(Box<Type>, Box<Type>), // Ok, Error
TUnion(Vec<Type>), // Union type for propagate
TAny,
TAlgebraicData(Name, Vec<ValueConstructor>),
}

// Represents a value constructor for an algebraic data type
#[derive(Debug, PartialEq, Clone)]
pub struct ValueConstructor {
pub name: Name,
pub types: Vec<Type>,
}

impl ValueConstructor {
// Creates a new value constructor
pub fn new(name: Name, types: Vec<Type>) -> Self {
ValueConstructor { name, types }
}
TAlgebraicData(Name, HashMap<Name, Vec<Type>>),
}

// Represents expressions in the AST
Expand Down Expand Up @@ -144,5 +133,6 @@ pub enum Statement {
AssertFails(String),
FuncDef(Function),
Return(Box<Expression>),
TypeDeclaration(Name, Vec<ValueConstructor>),
TypeDeclaration(Name, HashMap<Name, Vec<Type>>),
Match(Box<Expression>, Vec<(Expression, Statement)>),
}
1 change: 1 addition & 0 deletions src/parser/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub const KEYWORDS: &[&str] = &[
"val",
"var",
"return",
"match",
"Ok",
"Err",
"Just",
Expand Down
2 changes: 2 additions & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod parser_common;
pub mod parser_expr;
pub mod parser_stmt;
pub mod parser_type;
pub mod parse_pattern;
use nom::{
character::complete::{char, multispace0},
combinator::{map, opt},
Expand All @@ -17,6 +18,7 @@ use crate::parser::parser_common::SEMICOLON_CHAR;
pub use parser_expr::parse_expression;
pub use parser_stmt::parse_statement;
pub use parser_type::parse_type;
pub use parse_pattern::parse_pattern_argument;

pub fn parse(input: &str) -> IResult<&str, Vec<Statement>> {
map(
Expand Down
15 changes: 15 additions & 0 deletions src/parser/parse_pattern.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use nom::{IResult, branch::alt, combinator::map};
use crate::ir::ast::Expression;
use crate::parser::parser_expr::parse_literal_expression;
use crate::parser::parser_common::identifier;

pub fn parse_literal_pattern(input: &str) -> IResult<&str, Expression> {
parse_literal_expression(input)
}

pub fn parse_pattern_argument(input: &str) -> IResult<&str, Expression> {
alt((
parse_literal_pattern, // para números, strings, booleanos, etc.
map(identifier, |name| Expression::Var(name.to_string())),
))(input)
}
12 changes: 11 additions & 1 deletion src/parser/parser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ pub const ASSERT_KEYWORD: &str = "assert";
pub const VAR_KEYWORD: &str = "var";
pub const VAL_KEYWORD: &str = "val";
pub const DEF_KEYWORD: &str = "def";
pub const MATCH_KEYWORD: &str = "match";

// Operator and symbol constants
pub const FUNCTION_ARROW: &str = "->";
pub const MATCH_ARM_ARROW: &str = "=>";
pub const PIPE_SYMBOL: &str = "|";
pub const COLON_SYMBOL: &str = ":";
pub const COMMA_SYMBOL: &str = ",";
Expand All @@ -49,6 +51,8 @@ pub const LEFT_BRACKET: char = '[';
pub const RIGHT_BRACKET: char = ']';
pub const LEFT_PAREN: char = '(';
pub const RIGHT_PAREN: char = ')';
pub const LEFT_BRACE: char = '{';
pub const RIGHT_BRACE: char = '}';

// Other character constants
pub const COMMA_CHAR: char = ',';
Expand All @@ -75,6 +79,12 @@ pub fn keyword<'a>(kw: &'static str) -> impl FnMut(&'a str) -> IResult<&'a str,
)
}

/// Parses a keyword that can be followed by expressions or identifiers
/// This is more flexible than the standard keyword parser
pub fn flexible_keyword<'a>(kw: &'static str) -> impl FnMut(&'a str) -> IResult<&'a str, &'a str> {
delimited(multispace0, tag(kw), multispace0)
}

/// Parsers for identifiers.
pub fn identifier(input: &str) -> IResult<&str, &str> {
let (input, _) = multispace0(input)?;
Expand Down Expand Up @@ -105,6 +115,6 @@ fn identifier_continue(input: &str) -> IResult<&str, &str> {
}

/// A single identifier character: alphanumeric or underscore
fn identifier_start_or_continue(input: &str) -> IResult<&str, &str> {
pub fn identifier_start_or_continue(input: &str) -> IResult<&str, &str> {
recognize(alt((alpha1, tag("_"), nom::character::complete::digit1)))(input)
}
32 changes: 31 additions & 1 deletion src/parser/parser_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use nom::{

use std::str::FromStr;

use crate::ir::ast::Expression;
use crate::{ir::ast::{Expression}};
use crate::parser::parser_common::{
identifier,
is_string_char,
Expand Down Expand Up @@ -117,6 +117,7 @@ fn parse_factor(input: &str) -> IResult<&str, Expression> {
parse_list,
parse_function_call,
parse_var,
//parse_match_expression,
delimited(
char::<&str, Error<&str>>(LEFT_PAREN),
parse_expression,
Expand All @@ -125,6 +126,10 @@ fn parse_factor(input: &str) -> IResult<&str, Expression> {
))(input)
}

pub fn parse_literal_expression(input: &str) -> IResult<&str, Expression> {
alt((parse_bool, parse_number, parse_string))(input)
}

fn parse_bool(input: &str) -> IResult<&str, Expression> {
alt((
value(Expression::CTrue, keyword("True")),
Expand Down Expand Up @@ -396,4 +401,29 @@ mod tests {
panic!("Expected ListValue expression");
}
}

#[test]
fn test_parse_literal_expression_bool() {
assert_eq!(parse_literal_expression("True"), Ok(("", Expression::CTrue)));
assert_eq!(parse_literal_expression("False"), Ok(("", Expression::CFalse)));
}

#[test]
fn test_parse_literal_expression_int() {
assert_eq!(parse_literal_expression("42"), Ok(("", Expression::CInt(42))));
assert_eq!(parse_literal_expression("-7"), Ok(("", Expression::CInt(-7))));
}

#[test]
fn test_parse_literal_expression_real() {
assert_eq!(parse_literal_expression("3.14"), Ok(("", Expression::CReal(3.14))));
assert_eq!(parse_literal_expression("-0.5"), Ok(("", Expression::CReal(-0.5))));
}

#[test]
fn test_parse_literal_expression_string() {
assert_eq!(parse_literal_expression("\"abc\""), Ok(("", Expression::CString("abc".to_string()))));
assert_eq!(parse_literal_expression("\"\""), Ok(("", Expression::CString("".to_string()))));
}
}

Loading