use crate::error::*;
use crate::object::*;
use crate::value::*;
use crate::literals::*;
use crate::table::Table;
#[derive(Debug, Clone, PartialEq)]
pub struct Pair<A, B> {
first: A,
second: B
}
#[derive(Debug, Clone, PartialEq)]
pub struct Scope {
table: Table<Pair<Value, Scope>>,
outer_scope: Option<Box<Scope>>
}
impl Scope {
pub fn new(outer_scope: Option<Box<Scope>>) -> Self {
return Self {
table: Table::new(),
outer_scope
}
}
fn define(&mut self, name: String, object: Pair<Value, Scope>) {
self.table.set(name, object)
}
fn get(&mut self, name: String) -> Pair<Value, Scope> {
let value_scope = match self.table.get(name.clone()) {
Some(v) => return v,
None => {
match &mut self.outer_scope {
Some(v) => (*v).get(name),
None => Pair{first: Value::from_nothing(), second: Scope::new(None)}
}
}
};
match value_scope.first.get_type() {
Type::Function => value_scope,
_ => Pair{first: value_scope.first, second: Scope::new(None)}
}
}
}
#[derive(Clone, Debug)]
pub struct StackFrame {
scope: Scope,
contents: Vec<Pair<Value, Scope>>,
instructions: Value,
number_of_args_taken: i32,
outer_stack: Option<Box<StackFrame>>
}
impl StackFrame {
pub fn new(outer_stack: Option<Box<StackFrame>>, scope: Scope, instructions: Value) -> Self {
return Self {
scope,
contents: vec![],
instructions,
number_of_args_taken: 0,
outer_stack
}
}
pub fn from_instructions(instructions: Value) -> Self {
Self {
scope: Scope::new(None),
contents: vec![],
instructions,
number_of_args_taken: 0,
outer_stack: None
}
}
pub fn return_value(&mut self) -> Value {
self.pop_value()
}
pub fn run(&mut self) {
for instruction in self.instructions.as_list() {
self.step(instruction)
}
}
fn step(&mut self, instruction: Value) {
match instruction.as_instruction() {
Instruction::Print => self.pop_value().print(),
Instruction::Println => self.pop_value().println(),
Instruction::While => {
let condition = self.pop_value();
let body = self.pop_value();
self.while_function(condition, body);
},
Instruction::If => {
let c = self.pop_value();
let a = self.pop();
let b = self.pop();
if c != num("0") && c != none() {
self.push(a);
} else {
self.push(b);
}
},
Instruction::ListFromStack => {
let mut l = list(&[]);
for _ in 0..self.contents.len() {
l.list_push(self.pop_value());
}
self.push_value(l);
},
Instruction::Append => {
let mut list = self.pop_value();
let value = self.pop_value();
list.list_push(value);
self.push_value(list);
},
Instruction::Pop => {
let mut list = self.pop_value();
let value = list.list_pop();
self.push_value(value);
},
Instruction::Index => {
let mut list = self.pop_value();
let index = self.pop_value();
self.push_value(list.index(index));
},
Instruction::Equal => {
let a = self.pop_value();
let b = self.pop_value();
if a == b {
self.push_value(num("1"));
} else {
self.push_value(num("0"));
}
},
Instruction::Greater => {
let a = self.pop_value();
let b = self.pop_value();
if a.as_number() > b.as_number() {
self.push_value(num("1"));
} else {
self.push_value(num("0"));
}
},
Instruction::Less => {
let a = self.pop_value();
let b = self.pop_value();
if a.as_number() < b.as_number() {
self.push_value(num("1"));
} else {
self.push_value(num("0"));
}
},
Instruction::Not => {
let a = self.pop_value();
self.push_value(!a);
},
Instruction::Add => {
let a = self.pop_value();
let b = self.pop_value();
self.push_value(a + b);
},
Instruction::Mul => {
let a = self.pop_value();
let b = self.pop_value();
self.push_value(a * b);
},
Instruction::Sub => {
let a = self.pop_value();
let b = self.pop_value();
self.push_value(a - b);
},
Instruction::Div => {
let a = self.pop_value();
let b = self.pop_value();
self.push_value(a / b);
},
Instruction::Mod => {
let a = self.pop_value();
let b = self.pop_value();
self.push_value(a % b);
},
Instruction::Call => {
let f = self.pop();
self.call(f);
},
Instruction::Load => {
let name = self.pop_value().as_string();
let value = self.load(name);
self.push(value);
},
Instruction::Store => {
let name = self.pop_value().as_string();
let value = self.pop();
self.store(name, value);
},
Instruction::GetAttr => {
let mut names: Vec<String> = vec![];
loop {
if !self.contents.iter().any(|v| v.first.get_type() == Type::Instance) {
throw("No instance to set attribute of", self.contents.clone());
}
let back = match self.contents.last() {
Some(k) => k.first.clone(),
None => {
throw("Could not get back item from stack", self.contents.clone());
Value::from_nothing()
}
};
if back.get_type() == Type::Instance {
break;
}
names.push(
self.pop_value().as_string()
);
if self.contents.len() < 1 {
throw("Too few items on stack to set attribute", self.contents.clone());
}
}
if names.len() < 1 {
throw("Could not set attribute of object without the attribute name", self.contents.clone());
}
names.reverse();
let mut object = self.pop_value();
self.push_value(object.get_attr_recursive(names));
},
Instruction::SetAttr => {
let mut names: Vec<String> = vec![];
loop {
if !self.contents.iter().any(|v| v.first.get_type() == Type::Instance) {
throw("No instance to set attribute of", self.contents.clone());
}
let back = match self.contents.last() {
Some(k) => k.first.clone(),
None => {
throw("Could not get back item from stack", self.contents.clone());
Value::from_nothing()
}
};
if back.get_type() == Type::Instance {
break;
}
names.push(
self.pop_value().as_string()
);
if self.contents.len() < 2 {
throw("Too few items on stack to set attribute", self.contents.clone());
}
}
if names.len() < 1 {
throw("Could not set attribute of object without the attribute name", self.contents.clone());
}
names.reverse();
let mut object = self.pop_value();
let data = self.pop_value();
self.push_value(object.set_attr_recursive(names, data));
},
Instruction::Execute => {
let mut foreign_function = self.pop_value();
let argument = self.pop_value();
self.push_value(
foreign_function.call_foreign_function(argument)
);
},
Instruction::Pass => self.push_value(instruction)
}
}
fn is_empty(&self) -> bool {
self.contents.len() == 0
}
fn has_outer_stack(&self) -> bool {
match self.outer_stack {
Some(_) => true,
None => false
}
}
fn while_function(&mut self, condition: Value, body: Value) {
loop {
for instruction in condition.as_list() {
self.step(instruction)
}
let result = self.pop_value();
if result == num("0") || result == none() {
break;
}
for instruction in body.as_list() {
self.step(instruction)
}
}
}
fn call(&mut self, object_and_scope: Pair<Value, Scope>) {
let mut s = StackFrame::new(
Some(Box::new(self.clone())),
object_and_scope.second,
object_and_scope.first
);
s.run();
for _ in 0..s.number_of_args_taken {
self.pop();
}
s.contents.reverse();
while !s.is_empty() {
self.push(s.pop());
}
}
fn load(&mut self, name: String) -> Pair<Value, Scope> {
let result = self.scope.get(name.clone());
let empty = Pair{first: Value::from_nothing(), second: Scope::new(None)};
if result.first == empty.first && result.second == empty.second {
return match &mut self.outer_stack {
Some(s) => {
s.load(name.clone())
},
None => {
let v = self.pop();
self.store(name.clone(), v);
self.load(name.clone())
}
};
} else {
return result;
}
}
fn store(&mut self, name: String, object: Pair<Value, Scope>) {
if object.second != self.scope {
self.scope.define(name, object);
} else {
self.scope.define(name, Pair{first: object.first, second: Scope::new(None)});
}
}
fn push(&mut self, object_and_scope: Pair<Value, Scope>) {
self.contents.push(object_and_scope);
}
fn push_value(&mut self, object: Value) {
self.contents.push(Pair {
first: object,
second: self.scope.clone()
});
}
fn pop(&mut self) -> Pair<Value, Scope> {
if self.is_empty() && self.has_outer_stack() {
match &mut self.outer_stack {
Some(s) => {
self.number_of_args_taken += 1;
s.pop()
},
None => {
throw("Could not pop off of stack", self.contents.clone());
return Pair{first: Value::from_nothing(), second: Scope::new(None)}
}
}
} else {
let back: Pair<Value, Scope> = match self.contents.last() {
Some(v) => v.clone(),
None => {
throw("Could not pop off of stack", self.contents.clone());
Pair{first: Value::from_nothing(), second: Scope::new(None)}
}
};
self.contents.pop();
back.clone()
}
}
fn pop_value(&mut self) -> Value {
if self.is_empty() && self.has_outer_stack() {
match &mut self.outer_stack {
Some(s) => {
self.number_of_args_taken += 1;
s.pop().first
},
None => {
throw("Could not pop off of stack", self.contents.clone());
return Value::from_nothing();
}
}
} else {
let back: Value = match self.contents.last() {
Some(v) => v.first.clone(),
None => {
throw("Could not pop off of stack", self.contents.clone());
Value::from_nothing()
}
};
self.contents.pop();
back.clone()
}
}
}