Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions dev_tests/lib_test.ipl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# This requires ILI with the example library
# This requires ILI with the examplelib library

use examplelib

Expand All @@ -17,4 +17,10 @@ out("Adding a and c")
a_c = examplelib.add(example_a, example_c) # Should be 16

out("a_c")
out(a_c)
out(a_c)

test = examplelib.Test()

number = test.number # Should be 10
out("test number")
out(number)
71 changes: 60 additions & 11 deletions src/evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::debug::EvaluatioError;
use crate::library::get_library_entry_path;
use crate::state;
use crate::tokenizer::Tokenizer;
use crate::value::Value;
use crate::value::{Value, ClassStr};

// Define Class, Instance, and Value types for the evaluator

Expand All @@ -20,13 +20,14 @@ pub struct Class {

#[derive(Debug, Clone)]
pub struct Instance {
pub class: String,
pub class: ClassStr,
variables: HashMap<String, Value>,
}

#[allow(non_camel_case_types)] // For readability
#[derive(Debug, Clone)]
pub struct IPL_Library {
pub lib_name: String,
pub variables: HashMap<String, Value>,
pub functions: HashMap<String, HashMap<String, Value>>,
pub classes: HashMap<String, Class>,
Expand Down Expand Up @@ -171,6 +172,7 @@ impl Evaluator {
evaluator.ev_file(&lib_path);
}
let ipl_lib = IPL_Library {
lib_name: lib_name.to_string(),
functions: self.evaluators[&lib_path].functions.clone(),
variables: self.evaluators[&lib_path].variables.clone(),
classes: self.evaluators[&lib_path].classes.clone(),
Expand Down Expand Up @@ -587,7 +589,7 @@ impl Evaluator {
) -> Value {
// println!("ev_class_func called with instance: {}, function: {}, args: {:?}, instance_opt:{:?}", instance_str, function_name, args, instance_opt);
let mut instance: Instance = Instance {
class: "".to_string(),
class: ClassStr { class_name: "".to_string(), lib_name: "".to_string()},
variables: HashMap::new(),
};
if !static_func {
Expand All @@ -612,13 +614,13 @@ impl Evaluator {
};
if class_opt.is_some() {
class = class_opt.unwrap();
self.classes.insert(instance.class.clone(), class.clone());
} else if !self.classes.contains_key(&instance.class) {
self.classes.insert(instance.class.class_name.clone(), class.clone());
} else if !self.classes.contains_key(&instance.class.class_name) {
EvaluatioError::new("Class not in classes".to_string()).raise();
} else {
class = self
.classes
.get(&instance.class)
.get(&instance.class.class_name)
.expect("Class not found")
.clone();
}
Expand Down Expand Up @@ -774,7 +776,7 @@ impl Evaluator {
self.ev_func(function_name, args)
} else if self.classes.contains_key(function_name) {
let instance = Instance {
class: function_name.to_string(),
class: ClassStr { class_name: function_name.to_string(), lib_name: "".to_string() },
variables: self.classes[function_name].variables.clone(),
};
self.ev_class_func(
Expand Down Expand Up @@ -807,8 +809,8 @@ impl Evaluator {
Value::Instance(inst) => {
if inst.variables.contains_key(&attribute.to_string_value()) {
stack.push(inst.variables[&attribute.to_string_value()].clone());
} else if self.classes.contains_key(&inst.class) {
let class = &self.classes[&inst.class];
} else if self.classes.contains_key(&inst.class.class_name) {
let class = &self.classes[&inst.class.class_name];
if class.functions.contains_key(&attribute.to_string_value()) {
let function_name = &attribute.to_string_value();
let mut args: Vec<Value> = vec![];
Expand Down Expand Up @@ -850,6 +852,8 @@ impl Evaluator {
let attribute_str = attribute.to_string_value();
if lib.variables.contains_key(&attribute_str) {
stack.push(lib.variables[&attribute_str].clone());
} else if lib.classes.contains_key(&attribute_str){
stack.push(Value::ClassStr(ClassStr { class_name: attribute_str, lib_name: lib.lib_name }));
} else if lib.functions.contains_key(&attribute_str) {
let function_name = &attribute.to_string_value();
let mut args: Vec<Value> = vec![];
Expand All @@ -875,8 +879,6 @@ impl Evaluator {
);
stack.push(result);
i += 1; // Skip the next token which is the argument list
} else if lib.classes.contains_key(&attribute_str) {
stack.push(Value::Str(attribute_str));
} else {
EvaluatioError::new("No valid attribute on library".to_string())
.raise();
Expand Down Expand Up @@ -928,6 +930,53 @@ impl Evaluator {
i += 1; // Skip the next token which is the argument list
}
}
Value::ClassStr(class_str) =>{
let lib_name = class_str.lib_name;
if !self.ipl_libraries[&lib_name].classes.contains_key(&class_str.class_name) {
EvaluatioError::new("Left side of '.' is not a class".to_string())
.raise();
}
if self.ipl_libraries[&lib_name].classes[&class_str.class_name]
.variables
.contains_key(&attribute.to_string_value())
{
stack.push(
self.ipl_libraries[&lib_name].classes[&class_str.class_name].variables[&attribute.to_string_value()]
.clone(),
);
} else if self.ipl_libraries[&lib_name].classes[&class_str.class_name]
.functions
.contains_key(&attribute.to_string_value())
{
let function_name = &attribute.to_string_value();
let mut args: Vec<Value> = vec![];
let function_args = tokens.get(i + 2);
for arg in function_args.unwrap_or(&Value::None).iter() {
if let Value::Str(s) = arg {
let evaluated_arg = self.ev_expr(s);
args.push(evaluated_arg);
} else {
args.push(arg.clone());
}
}
if args.len() == 1
&& args[0].to_string_value() == Value::None.to_string_value()
{
args = vec![];
}
// println!("Class function {} called with arguments: {:?}", function_name, args);
let result = self.ev_class_func(
tokens[i - 1].to_string_value(),
function_name,
args,
None,
Some(self.ipl_libraries[&lib_name].classes[&class_str.class_name].clone()),
true,
);
stack.push(result);
i += 1; // Skip the next token which is the argument list
}
}
_ => EvaluatioError::new("Left side of '.' is not an instance".to_string())
.raise(),
}
Expand Down
8 changes: 7 additions & 1 deletion src/library.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use directories::BaseDirs;

use crate::debug::EvaluatioError;

fn get_ili_path() -> PathBuf {
match std::env::var("ILI_PATH"){
Ok(path) => PathBuf::from(path),
Err(_) => get_hardcoded_ili_path(),
}
}

fn get_hardcoded_ili_path() -> PathBuf {
#[cfg(target_os = "windows")]
{
PathBuf::from(std::env::var("PROGRAMDATA").unwrap()).join("ILI")
Expand Down
7 changes: 7 additions & 0 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ use std::ops::Index;
use std::ops::{Add, Div, Mul, Sub};
use std::path::PathBuf;

#[derive(Debug, Clone)]
pub struct ClassStr{
pub class_name: String,
pub lib_name: String,
}

#[derive(Debug, Clone)]
pub enum Value {
Number(f64),
Expand All @@ -14,6 +20,7 @@ pub enum Value {
Instance(Instance),
#[allow(non_camel_case_types)] // For readability
IPL_Library(IPL_Library),
ClassStr(ClassStr),
None,
}

Expand Down