Skip to content

Commit

Permalink
0.4.0 [release]
Browse files Browse the repository at this point in the history
  • Loading branch information
alihsaas committed May 26, 2021
1 parent 6d794df commit d1d3da0
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 58 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "neko"
version = "0.3.1"
version = "0.4.0"
authors = ["alihsaas <alihsaas2@gmail.com>"]
build = "build.rs"
edition = "2018"
Expand Down
33 changes: 16 additions & 17 deletions src/enviroment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ pub enum Value {
NoValue,
}


pub type Env = Rc<RefCell<Enviroment>>;

#[derive(Debug)]
Expand All @@ -20,40 +19,40 @@ pub struct Enviroment {
}

impl Enviroment {

pub fn new(enclosing_enviroment: Option<Env>) -> Self {
Self {
values: HashMap::new(),
enclosing_enviroment
enclosing_enviroment,
}
}

pub fn look_up(&self, name: &str, current_env_only: bool) -> Option<Value> {
self.values
.get(name)
.map(|value| value.clone())
.or_else(|| if current_env_only { None } else {
self.enclosing_enviroment.as_ref()
.and_then(|env| env.borrow().look_up(name, false))
.map(|value| value.clone())
.cloned()
.or_else(|| {
if current_env_only {
None
} else {
self.enclosing_enviroment
.as_ref()
.and_then(|env| env.borrow().look_up(name, false))
}
})
}


pub fn assign(&mut self, name: &str, value: Value) -> Result<(), String> {
if let Some(val) = self.values.get_mut(name) {
*val = value;
Ok(())
} else {
if let Some(env) = &self.enclosing_enviroment {
env.borrow_mut().assign(name, value)
} else {
Err(format!("Attempt to assign to undefined variable {}", name))
}
}
} else if let Some(env) = &self.enclosing_enviroment {
env.borrow_mut().assign(name, value)
} else {
Err(format!("Attempt to assign to undefined variable {}", name))
}
}

pub fn define(&mut self, name: &str, value: Value) {
self.values.insert(name.to_string(), value);
}
}
}
19 changes: 11 additions & 8 deletions src/interpreter.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{ast::*, parser::Parser, semantic_analyzer::SemanticAnalyzer, token::*, enviroment::*};
use crate::{ast::*, enviroment::*, parser::Parser, semantic_analyzer::SemanticAnalyzer, token::*};
use std::{cell::RefCell, rc::Rc};

#[derive(Debug)]
Expand Down Expand Up @@ -202,12 +202,13 @@ impl Interpreter {
match current_env {
Some(value) => match value {
Value::Function(function) => {
self.env = Rc::new(RefCell::new(Enviroment::new(Some(Rc::clone(&self.env)))));
self.env =
Rc::new(RefCell::new(Enviroment::new(Some(Rc::clone(&self.env)))));

for (index, param) in function.params.iter().enumerate() {
let value = match node.arguments.get(index) {
Some(node) => self.visit(node)?,
None => Value::NoValue
None => Value::NoValue,
};
self.env.borrow_mut().define(&param, value)
}
Expand All @@ -223,12 +224,12 @@ impl Interpreter {
);

Ok(result)
},
value => Err(format!("{:?} is not a function", value))
}
value => Err(format!("{:?} is not a function", value)),
},
None => Err(format!("{} is not defined", identifier))
None => Err(format!("{} is not defined", identifier)),
}
},
}
node => Err(format!("{} is not a function", node)),
}
}
Expand All @@ -253,7 +254,9 @@ impl Interpreter {

fn visit_assignment(&mut self, node: &AssignmentExpr) -> IResult {
let value = self.visit_expression(&node.value)?;
self.env.borrow_mut().assign(&node.identifier, value.clone())?;
self.env
.borrow_mut()
.assign(&node.identifier, value.clone())?;
Ok(value)
}

Expand Down
5 changes: 4 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ fn log_result(result: IResult) {
Value::Number(num) => println!("{}", Colour::Yellow.paint(num.to_string())),
Value::Boolean(boolean) => println!("{}", Colour::Yellow.paint(boolean.to_string())),
Value::String(string) => println!("{}", Colour::Green.paint(format!("{:?}", string))),
Value::Function(function) => println!("{}", Colour::Green.paint(format!("[Function: {}]", function.name))),
Value::Function(function) => println!(
"{}",
Colour::Green.paint(format!("[Function: {}]", function.name))
),
Value::NoValue => (),
},
Err(err) => eprintln!("{}", err),
Expand Down
31 changes: 15 additions & 16 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,18 @@ impl<'a> Parser<'a> {
_ => Err(format!("Expected closing ')', got {}", current_token)),
}
}
_ => Err(format!("Expected number got {:?}", token)),
_ => Err(String::from("Invalid Syntax")),
}
}

fn call_expression(&mut self) -> PResult {
let mut node = self.value()?;

loop {
if let Token::LParen = self.lexer.peek() {
let arguments = self.argument_list()?;
node = Node::FunctionCall(Box::new(FunctionCall {
function: node,
arguments,
}))
} else {
break
}
while let Token::LParen = self.lexer.peek() {
let arguments = self.argument_list()?;
node = Node::FunctionCall(Box::new(FunctionCall {
function: node,
arguments,
}))
}

Ok(node)
Expand All @@ -68,7 +63,7 @@ impl<'a> Parser<'a> {
| Token::Operator(Operator::Minus)
| Token::Operator(Operator::Not) => {
self.lexer.next();
Node::UnaryOperator(Box::new(UnaryOperator {
Node::UnaryOperator(Box::new(UnaryOperator {
operator: extract_op(token)?,
expression: self.unary_expression()?,
}))
Expand Down Expand Up @@ -400,14 +395,18 @@ impl<'a> Parser<'a> {

loop {
match self.lexer.peek() {
Token::Comma => {self.lexer.next();},
Token::Comma => {
self.lexer.next();
}
Token::RParen => break,
_ => {args.push(self.expression()?); },
_ => {
args.push(self.expression()?);
}
};
}

self.eat(Token::RParen)?;
Ok(args)
Ok(args)
}

fn parameter_list(&mut self) -> Result<Vec<String>, String> {
Expand Down
34 changes: 25 additions & 9 deletions src/semantic_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ impl SemanticAnalyzer {
}

fn visit_assignment(&mut self, node: &AssignmentExpr) -> SResult {
if self.scope.borrow().look_up(&node.identifier, false).is_some() {
if self
.scope
.borrow()
.look_up(&node.identifier, false)
.is_some()
{
self.visit(&node.value)?;
Ok(())
} else {
Expand All @@ -45,7 +50,12 @@ impl SemanticAnalyzer {
}

fn visit_variable_decleration(&mut self, node: &VariabeDecleration) -> SResult {
if self.scope.borrow().look_up(&node.identifier, true).is_some() {
if self
.scope
.borrow()
.look_up(&node.identifier, true)
.is_some()
{
Err(format!("Duplicate variable {}", &node.identifier))
} else {
self.scope.borrow_mut().insert(
Expand Down Expand Up @@ -75,7 +85,11 @@ impl SemanticAnalyzer {
if let Some(symbol) = self.scope.borrow().look_up(identifier, false) {
if let Symbol::FunctionSymbol(symbol) = symbol {
if symbol.param.len() != node.arguments.len() {
Err(format!("Expected {} number of arguments got {}", symbol.param.len(), node.arguments.len()))
Err(format!(
"Expected {} number of arguments got {}",
symbol.param.len(),
node.arguments.len()
))
} else {
Ok(())
}
Expand Down Expand Up @@ -112,10 +126,13 @@ impl SemanticAnalyzer {
fn visit_function_decleration(&mut self, node: &FunctionDecleration) -> SResult {
let function_name = &node.name;
if self.scope.borrow().look_up(function_name, true).is_none() {
self.scope.borrow_mut().insert(&function_name, Symbol::FunctionSymbol(FunctionSymbol {
name: function_name.clone(),
param: node.params.clone(),
}));
self.scope.borrow_mut().insert(
&function_name,
Symbol::FunctionSymbol(FunctionSymbol {
name: function_name.clone(),
param: node.params.clone(),
}),
);
let level = self.scope.borrow().scope_level + 1;
self.scope = Rc::new(RefCell::new(SymbolTable::new(
&function_name,
Expand Down Expand Up @@ -161,8 +178,7 @@ impl SemanticAnalyzer {
}

pub fn analyze(&mut self, node: &Node) -> SResult {
let result = self.visit(node);
result
self.visit(node)
}
}

Expand Down
15 changes: 10 additions & 5 deletions src/symbol_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,16 @@ impl SymbolTable {
pub fn look_up(&self, name: &str, current_scope_only: bool) -> Option<Symbol> {
self.symbols
.get(name)
.map(|symbol| symbol.clone())
.or_else(|| if current_scope_only { None } else {
self.enclosing_scope.as_ref()
.and_then(|scope| scope.borrow().look_up(name, false))
.map(|symbol| symbol.clone())
.cloned()
.or_else(|| {
if current_scope_only {
None
} else {
self.enclosing_scope
.as_ref()
.and_then(|scope| scope.borrow().look_up(name, false))
.clone()
}
})
}

Expand Down

0 comments on commit d1d3da0

Please sign in to comment.