From b9fa8429a6ee3795132cfca0289278f76beb41af Mon Sep 17 00:00:00 2001 From: MeexReay Date: Wed, 8 Jan 2025 19:55:44 +0300 Subject: [PATCH] var value parse and some --- README.md | 68 ++++++++- src/lib.rs | 423 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/tests.rs | 0 test.emc | 0 4 files changed, 490 insertions(+), 1 deletion(-) create mode 100644 src/lib.rs create mode 100644 src/tests.rs create mode 100644 test.emc diff --git a/README.md b/README.md index 4f7b693..90e05b6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,69 @@ # Emcode -Embeddable code compiler \ No newline at end of file +Embeddable code compiler + +``` +// comment + +var a = 0 // create var (you can not create var without initial value) +a = 1 // int, set var +a = "123" // string, dynamic var type +a = {"11": "11"} // map (map) + +a."11" = "44" // set value to map item + +a = {"11", "12"} // list (map) + +a.0 = "55" // set value to list element + +a = 0.41 // float + +var c = 10 + +c = c + a // addition (works with string+string=string) +c = c - a // subtraction +c = c * a // multiplication (works with string*int=string) +c = c / a // division +c = c % a // module + +// + +// var types: +// int, float, map[key, value], string, null, function, bool + +{ + var b = 0 + + // this is scope + + // <- here local vars for scope +} + +// <- here global vars for scope + +// global scope cant see local vars (var b in this case) + +if a == 0.42 { + // works totally like scope +} else { + // has no else if or elif +} + +// logical operations: +// a == b a equals b +// a >= b a greater than or equals b +// a <= b a less than or equals b +// a > b a greater than b +// a < b a less than b +// a != b a not equals b +// a || b a or b +// a && b a and b +// !a not a + +var func = [arg, arg2] { // create function. also work like scope + return "123" +} + +func ["arg1", "arg2"] // run function + +``` \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..eb6c0bb --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,423 @@ +use std::{collections::HashMap, fmt::{self, write}, hash::{Hash, Hasher}, sync::Arc}; + +mod tests; + +pub trait Func { + fn args(&self) -> Vec; + fn run(&self, globals: &mut VarList, args: VarList) -> Var; +} + +#[derive(Clone)] +pub enum Var { + Null, + Bool(bool), + Int(isize), + Float(f64), + String(String), + Map(HashMap), + Func(Arc), +} + +impl fmt::Debug for Var { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Var::Null => write!(f, "Null"), + Var::Bool(value) => write!(f, "Bool({})", value), + Var::Int(value) => write!(f, "Int({})", value), + Var::Float(value) => write!(f, "Float({})", value), + Var::String(value) => write!(f, "String({:?})", value), + Var::Map(map) => { + f.write_str("Map(")?; + let mut entries = map.iter(); + if let Some((key, value)) = entries.next() { + write!(f, "{:?}: {:?}", key, value)?; + for (key, value) in entries { + write!(f, ", {:?}: {:?}", key, value)?; + } + } + f.write_str(")") + } + Var::Func(_) => write!(f, "Func()"), + } + } +} + +impl PartialEq for Var { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Var::Null, Var::Null) => true, + (Var::Bool(a), Var::Bool(b)) => a == b, + (Var::Int(a), Var::Int(b)) => a == b, + (Var::Float(a), Var::Float(b)) => a == b, + (Var::String(a), Var::String(b)) => a == b, + (Var::Map(a), Var::Map(b)) => a.len() == b.len() && a.iter().all(|(k, v)| b.get(k) == Some(v)), + (Var::Func(a), Var::Func(b)) => Arc::ptr_eq(a, b), + _ => false, + } + } +} + +impl Eq for Var {} + +impl Hash for Var { + fn hash(&self, state: &mut H) { + match self { + Var::Null => state.write_u8(0), + Var::Bool(a) => state.write_u8(if *a { 1 } else { 0 }), + Var::Int(a) => state.write_isize(*a), + Var::Float(a) => state.write(&a.to_be_bytes()), + Var::String(a) => state.write(a.as_bytes()), + Var::Map(a) => a.iter().for_each(|o| o.hash(state)), + Var::Func(a) => Arc::as_ptr(a).hash(state), + } + } +} + +impl fmt::Display for Var { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Var::Null => write!(f, "null"), + Var::Bool(value) => write!(f, "{}", value), + Var::Int(value) => write!(f, "{}", value), + Var::Float(value) => write!(f, "{}", value), + Var::String(value) => write!(f, "\"{}\"", value), + Var::Map(map) => { + write!(f, "{}", "{")?; + let mut entries = map.iter(); + if let Some((key, value)) = entries.next() { + write!(f, "{}: {}", key.to_string(), value.to_string())?; + for (key, value) in entries { + write!(f, ", {}: {}", key.to_string(), value.to_string())?; + } + } + write!(f, "{}", "}") + } + Var::Func(_) => write!(f, "[] {}", "{}"), + } + } +} + +pub enum ErrorType { + IntParse, + FloatParse, + UnknownVar, + FunctionArgs, + FunctionCode, + VarAlreadyInit, + VarDidntInit +} + +impl ErrorType { + pub fn with_line(self, line: usize) -> Error { + Error { error_type: self, line } + } +} + +pub struct Error { + error_type: ErrorType, + line: usize, +} + +impl Var { + fn replace_operation(a: &str, op: &str, b: &str, vars: &mut VarList) -> Result { + todo!() + } + + pub fn parse_operation(text: &str, vars: &mut VarList) -> Result { + let mut tokens = Vec::new(); + let mut current_token = String::new(); + let mut stack = Vec::new(); + + for c in text.chars() { + match c { + '(' | ')' | '!' | '+' | '-' | '*' | '/' | '%' | '<' | '>' | '=' | '|' | '&' => { + if !current_token.is_empty() { + tokens.push(current_token.clone()); + current_token.clear(); + } + if c == '(' { + stack.push(c.to_string()); + } else if c == ')' { + while let Some(op) = stack.pop() { + if op == "(" { + break; + } + tokens.push(op); + } + } else { + while let Some(top) = stack.last() { + let precedence_top = match top.as_str() { + "!" => 4, + "*" | "/" | "%" => 3, + "+" | "-" => 2, + "<" | "<=" | ">" | ">=" | "==" | "!=" => 1, + "&&" | "||" => 0, + _ => -1, + }; + let precedence_current = match c { + '!' => 4, + '*' | '/' | '%' => 3, + '+' | '-' => 2, + '<' | '>' | '=' => 1, + '&' | '|' => 0, + _ => -1, + }; + if precedence_top >= precedence_current { + tokens.push(stack.pop().unwrap()); + } else { + break; + } + } + stack.push(c.to_string()); + } + } + _ => { + if c.is_whitespace() { + if !current_token.is_empty() { + tokens.push(current_token.clone()); + current_token.clear(); + } + } else { + current_token.push(c); + } + } + } + } + + if !current_token.is_empty() { + tokens.push(current_token); + } + + while let Some(op) = stack.pop() { + tokens.push(op); + } + + let mut rpn_stack: Vec = Vec::new(); + + for token in tokens { + match token.as_str() { + "!" => { + let a = rpn_stack.pop().ok_or(ErrorType::UnknownVar)?; + let result = Self::replace_operation("false", "==", &a, vars)?; + rpn_stack.push(result); + } + "+" | "-" | "*" | "/" | "%" | "<" | "<=" | ">" | ">=" | "==" | "!=" | "&&" | "||" => { + let b = rpn_stack.pop().ok_or(ErrorType::UnknownVar)?; + let a = rpn_stack.pop().ok_or(ErrorType::UnknownVar)?; + let result = Self::replace_operation(&a, &token, &b, vars)?; + rpn_stack.push(result); + } + _ => rpn_stack.push(token), + } + } + + if let Some(final_result) = rpn_stack.pop() { + Self::parse_value(&final_result, vars) + } else { + Err(ErrorType::UnknownVar) + } + } + + pub fn parse_value(text: &str, vars: &mut VarList) -> Result { + if let Ok(v) = vars.get(text) { + return Ok(v); + } + + if let Some((func, args)) = text[..text.len()-1].split_once("[") { + if text.ends_with("]") { + let mut args_vars = Vec::new(); + for e in args.split(",").map(|o| o.trim().to_string()).collect::>() { + args_vars.push(Self::parse_value(&e, vars)?); + } + if let Ok(Var::Func(v)) = vars.get(func) { + return Ok(v.run(vars, + VarList::new( + HashMap::from_iter( + v.args().iter() + .enumerate() + .map(|(i, o)| (o.to_string(), args_vars[i].clone())) + ) + ) + )); + } + } + } + + if text.starts_with("{") && text.ends_with("}") { + let text = text[1..text.len()-1].to_string(); + + let mut map = HashMap::new(); + let mut stack = Vec::new(); + let mut is_key = true; + let mut key = String::new(); + let mut value = String::new(); + let mut index = 0usize; + + for char in text.chars() { + if char == '{' { + stack.push('{'); + } else if char == '}' { + if let Some('{') = stack.last() { + stack.remove(stack.len()-1); + } + } else if stack.is_empty() { + if char == ':' { + is_key = false; + continue; + } else if char == ',' { + if is_key == true { + map.insert(Var::Int(index as isize), Var::parse_value(&key, vars)?); + index += 1; + } else { + map.insert(Var::parse_value(&key, vars)?, Var::parse_value(&value, vars)?); + } + is_key = true; + continue; + } + } + + if is_key { + key.push(char); + } else { + value.push(char); + } + } + + return Ok(Var::Map(map)) + } else if text.starts_with("[") { + let (args, scope) = text[1..].split_once("]").ok_or(ErrorType::FunctionArgs)?; + let args = args.split(",").map(|o| o.trim().to_string()).collect::>(); + let code = scope[..scope.len()-1].split_once("{").ok_or(ErrorType::FunctionCode)?.1.to_string(); + + return Ok(Var::Func(Arc::new(CodeFunc::new(args, code)))) + } + + Self::parse_raw_value(text) + } + + pub fn parse_raw_value(text: &str) -> Result { + if text.starts_with("\"") && text.ends_with("\"") { + Ok(Var::String(text[1..text.len()-1].to_string())) + } else if text == "null" { + Ok(Var::Null) + } else if text == "true" { + Ok(Var::Bool(true)) + } else if text == "false" { + Ok(Var::Bool(false)) + } else if text.contains(".") { + Ok(Var::Float(text.parse().or(Err(ErrorType::FloatParse))?)) + } else { + Ok(Var::Int(text.parse().or(Err(ErrorType::IntParse))?)) + } + } +} + +#[derive(Clone)] +pub struct VarList { + vars: HashMap +} + +impl VarList { + pub fn new(vars: HashMap) -> VarList { + VarList { vars } + } + + pub fn init(&mut self, name: String, value: Var) -> Result<(), ErrorType> { + if self.has(&name) { + return Err(ErrorType::VarAlreadyInit) + } + + self._set(name, value) + } + + pub fn set(&mut self, name: String, value: Var) -> Result<(), ErrorType> { + if !self.has(&name) { + return Err(ErrorType::VarDidntInit) + } + + self._set(name, value) + } + + pub fn del(&mut self, name: &str) -> Result<(), ErrorType> { + if name.contains(".") { + let mut parts = name.split("."); + + if let Some(var) = parts.next() { + if let Some(Var::Map(map)) = self.vars.get_mut(var) { + let parts_len = parts.clone().count() - 1; + let mut now_map = map; + let mut key; + + for (i, part) in parts.enumerate() { + key = Var::parse_raw_value(part)?; + + if i == parts_len - 1 { + break + } else { + if let Some(Var::Map(next_map)) = now_map.get_mut(&key) { + now_map = next_map; + } + } + } + + now_map.remove(&key); + + Ok(()) + } else { + Err(ErrorType::UnknownVar) + } + } else { + Err(ErrorType::UnknownVar) + } + } else { + self.vars.remove(name).ok_or(ErrorType::UnknownVar).map(|_| ()) + } + } + + fn _set(&mut self, name: String, value: Var) -> Result<(), ErrorType> { + todo!() + } + + pub fn has(&self, name: &str) -> bool { + todo!() + } + + pub fn get(&self, name: &str) -> Result { + todo!() + } + + pub fn list(&self) -> HashMap { + self.vars.clone() + } + + pub fn merge(&self, list: VarList) -> VarList { + let mut map = self.vars.clone(); + for (k, v) in list.list() { + map.insert(k, v); + } + VarList::new(map) + } +} + +pub struct CodeFunc { + args: Vec, + code: String +} + +impl CodeFunc { + pub fn new(args: Vec, code: String) -> CodeFunc { + CodeFunc { args, code } + } +} + +impl Func for CodeFunc { + fn args(&self) -> Vec { + self.args.clone() + } + + fn run(&self, globals: &mut VarList, args: VarList) -> Var { + let mut locals = args; + + todo!() + } +} \ No newline at end of file diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 0000000..e69de29 diff --git a/test.emc b/test.emc new file mode 100644 index 0000000..e69de29