var value parse and some

This commit is contained in:
MeexReay 2025-01-08 19:55:44 +03:00
parent f0d129b3e3
commit b9fa8429a6
4 changed files with 490 additions and 1 deletions

View File

@ -1,3 +1,69 @@
# Emcode # Emcode
Embeddable code compiler 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<string, string>)
a."11" = "44" // set value to map item
a = {"11", "12"} // list (map<int, string>)
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
```

423
src/lib.rs Normal file
View File

@ -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<String>;
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<Var, Var>),
Func(Arc<dyn Func>),
}
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(<function>)"),
}
}
}
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<H: std::hash::Hasher>(&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<String, ErrorType> {
todo!()
}
pub fn parse_operation(text: &str, vars: &mut VarList) -> Result<Var, ErrorType> {
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<String> = 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<Var, ErrorType> {
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::<Vec<String>>() {
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::<Vec<String>>();
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<Var, ErrorType> {
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<String, Var>
}
impl VarList {
pub fn new(vars: HashMap<String, Var>) -> 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<Var, ErrorType> {
todo!()
}
pub fn list(&self) -> HashMap<String, Var> {
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<String>,
code: String
}
impl CodeFunc {
pub fn new(args: Vec<String>, code: String) -> CodeFunc {
CodeFunc { args, code }
}
}
impl Func for CodeFunc {
fn args(&self) -> Vec<String> {
self.args.clone()
}
fn run(&self, globals: &mut VarList, args: VarList) -> Var {
let mut locals = args;
todo!()
}
}

0
src/tests.rs Normal file
View File

0
test.emc Normal file
View File