Compare commits
	
		
			No commits in common. "6dde4b41c1fd4c8d2832fe928223dd621df98706" and "7290806a2bc8eb059a102a68042d6246ee3a0e21" have entirely different histories.
		
	
	
		
			6dde4b41c1
			...
			7290806a2b
		
	
		| 
						 | 
					@ -10,8 +10,8 @@ mod enabled {
 | 
				
			||||||
        base::{self, source_file::SourceElement, Handler},
 | 
					        base::{self, source_file::SourceElement, Handler},
 | 
				
			||||||
        syntax::syntax_tree::expression::LuaCode,
 | 
					        syntax::syntax_tree::expression::LuaCode,
 | 
				
			||||||
        transpile::{
 | 
					        transpile::{
 | 
				
			||||||
            error::{LuaRuntimeError, MismatchedTypes, TranspileError, TranspileResult},
 | 
					            error::{LuaRuntimeError, TranspileError, TranspileResult},
 | 
				
			||||||
            expression::{ComptimeValue, ExpectedType},
 | 
					            expression::ComptimeValue,
 | 
				
			||||||
            Scope, VariableData,
 | 
					            Scope, VariableData,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
| 
						 | 
					@ -124,7 +124,7 @@ mod enabled {
 | 
				
			||||||
                            table.set("path", lua.create_string(path)?)?;
 | 
					                            table.set("path", lua.create_string(path)?)?;
 | 
				
			||||||
                            Value::Table(table)
 | 
					                            Value::Table(table)
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        Some(_) => todo!("allow other variable types"),
 | 
					                        Some(_) => todo!("allow other types"),
 | 
				
			||||||
                        None => todo!("throw correct error"),
 | 
					                        None => todo!("throw correct error"),
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
                    globals.set(name, value)?;
 | 
					                    globals.set(name, value)?;
 | 
				
			||||||
| 
						 | 
					@ -155,68 +155,8 @@ mod enabled {
 | 
				
			||||||
                    handler,
 | 
					                    handler,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                Value::Boolean(boolean) => Ok(Some(ComptimeValue::Boolean(boolean))),
 | 
					                Value::Boolean(boolean) => Ok(Some(ComptimeValue::Boolean(boolean))),
 | 
				
			||||||
                Value::Table(table) => match table.get::<Value>("value") {
 | 
					 | 
				
			||||||
                    Ok(Value::Nil) => {
 | 
					 | 
				
			||||||
                        let err = TranspileError::LuaRuntimeError(LuaRuntimeError {
 | 
					 | 
				
			||||||
                            code_block: self.span(),
 | 
					 | 
				
			||||||
                            error_message: "return table must contain non-nil 'value'".to_string(),
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                        handler.receive(err.clone());
 | 
					 | 
				
			||||||
                        Err(err)
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    Ok(value) => {
 | 
					 | 
				
			||||||
                        let value = match self.handle_lua_result(value, handler)? {
 | 
					 | 
				
			||||||
                            Some(ComptimeValue::String(s)) => {
 | 
					 | 
				
			||||||
                                let contains_macro = match table.get::<Value>("contains_macro") {
 | 
					 | 
				
			||||||
                                    Ok(Value::Boolean(boolean)) => Ok(boolean),
 | 
					 | 
				
			||||||
                                    Ok(value) => {
 | 
					 | 
				
			||||||
                                        if let Some(ComptimeValue::Boolean(boolean)) =
 | 
					 | 
				
			||||||
                                            self.handle_lua_result(value, handler)?
 | 
					 | 
				
			||||||
                                        {
 | 
					 | 
				
			||||||
                                            Ok(boolean)
 | 
					 | 
				
			||||||
                                        } else {
 | 
					 | 
				
			||||||
                                            let err =
 | 
					 | 
				
			||||||
                                                TranspileError::MismatchedTypes(MismatchedTypes {
 | 
					 | 
				
			||||||
                                                    expression: self.span(),
 | 
					 | 
				
			||||||
                                                    expected_type: ExpectedType::Boolean,
 | 
					 | 
				
			||||||
                                                });
 | 
					 | 
				
			||||||
                                            handler.receive(err.clone());
 | 
					 | 
				
			||||||
                                            Err(err)
 | 
					 | 
				
			||||||
                                        }
 | 
					 | 
				
			||||||
                                    }
 | 
					 | 
				
			||||||
                                    _ => {
 | 
					 | 
				
			||||||
                                        let err =
 | 
					 | 
				
			||||||
                                            TranspileError::MismatchedTypes(MismatchedTypes {
 | 
					 | 
				
			||||||
                                                expression: self.span(),
 | 
					 | 
				
			||||||
                                                expected_type: ExpectedType::Boolean,
 | 
					 | 
				
			||||||
                                            });
 | 
					 | 
				
			||||||
                                        handler.receive(err.clone());
 | 
					 | 
				
			||||||
                                        Err(err)
 | 
					 | 
				
			||||||
                                    }
 | 
					 | 
				
			||||||
                                }?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                if contains_macro {
 | 
					 | 
				
			||||||
                                    Some(ComptimeValue::MacroString(
 | 
					 | 
				
			||||||
                                        s.parse().expect("parsing cannot fail"),
 | 
					 | 
				
			||||||
                                    ))
 | 
					 | 
				
			||||||
                                } else {
 | 
					 | 
				
			||||||
                                    Some(ComptimeValue::String(s))
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                            value => value,
 | 
					 | 
				
			||||||
                        };
 | 
					 | 
				
			||||||
                        Ok(value)
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    Err(err) => {
 | 
					 | 
				
			||||||
                        let err = TranspileError::LuaRuntimeError(LuaRuntimeError::from_lua_err(
 | 
					 | 
				
			||||||
                            &err,
 | 
					 | 
				
			||||||
                            self.span(),
 | 
					 | 
				
			||||||
                        ));
 | 
					 | 
				
			||||||
                        handler.receive(err.clone());
 | 
					 | 
				
			||||||
                        Err(err)
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                Value::Error(_)
 | 
					                Value::Error(_)
 | 
				
			||||||
 | 
					                | Value::Table(_)
 | 
				
			||||||
                | Value::Thread(_)
 | 
					                | Value::Thread(_)
 | 
				
			||||||
                | Value::UserData(_)
 | 
					                | Value::UserData(_)
 | 
				
			||||||
                | Value::LightUserData(_)
 | 
					                | Value::LightUserData(_)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -334,6 +334,9 @@ impl Transpiler {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let statements = function_data.statements.clone();
 | 
					            let statements = function_data.statements.clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let commands =
 | 
				
			||||||
 | 
					                self.transpile_function(&statements, program_identifier, &function_scope, handler)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let modified_name = function_data.annotations.get("deobfuscate").map_or_else(
 | 
					            let modified_name = function_data.annotations.get("deobfuscate").map_or_else(
 | 
				
			||||||
                || {
 | 
					                || {
 | 
				
			||||||
                    let hash_data = program_identifier.to_string() + "\0" + identifier_span.str();
 | 
					                    let hash_data = program_identifier.to_string() + "\0" + identifier_span.str();
 | 
				
			||||||
| 
						 | 
					@ -367,16 +370,6 @@ impl Transpiler {
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
            )?;
 | 
					            )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let function_location = format!(
 | 
					 | 
				
			||||||
                "{namespace}:{modified_name}",
 | 
					 | 
				
			||||||
                namespace = function_data.namespace
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            function_path.set(function_location.clone()).unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let commands =
 | 
					 | 
				
			||||||
                self.transpile_function(&statements, program_identifier, &function_scope, handler)?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let namespace = self.datapack.namespace_mut(&function_data.namespace);
 | 
					            let namespace = self.datapack.namespace_mut(&function_data.namespace);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if namespace.function(&modified_name).is_some() {
 | 
					            if namespace.function(&modified_name).is_some() {
 | 
				
			||||||
| 
						 | 
					@ -391,12 +384,19 @@ impl Transpiler {
 | 
				
			||||||
            let function = namespace.function_mut(&modified_name);
 | 
					            let function = namespace.function_mut(&modified_name);
 | 
				
			||||||
            function.get_commands_mut().extend(commands);
 | 
					            function.get_commands_mut().extend(commands);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let function_location = format!(
 | 
				
			||||||
 | 
					                "{namespace}:{modified_name}",
 | 
				
			||||||
 | 
					                namespace = function_data.namespace
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if function_data.annotations.contains_key("tick") {
 | 
					            if function_data.annotations.contains_key("tick") {
 | 
				
			||||||
                self.datapack.add_tick(&function_location);
 | 
					                self.datapack.add_tick(&function_location);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if function_data.annotations.contains_key("load") {
 | 
					            if function_data.annotations.contains_key("load") {
 | 
				
			||||||
                self.datapack.add_load(&function_location);
 | 
					                self.datapack.add_load(&function_location);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            function_path.set(function_location.clone()).unwrap();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let parameters = &function_data.parameters;
 | 
					        let parameters = &function_data.parameters;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
//! Utility methods for transpiling
 | 
					//! Utility methods for transpiling
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::{fmt::Display, str::FromStr};
 | 
					use std::fmt::Display;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    lexical::token::{MacroStringLiteral, MacroStringLiteralPart},
 | 
					    lexical::token::{MacroStringLiteral, MacroStringLiteralPart},
 | 
				
			||||||
| 
						 | 
					@ -114,61 +114,6 @@ where
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl FromStr for MacroString {
 | 
					 | 
				
			||||||
    type Err = ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn from_str(s: &str) -> Result<Self, Self::Err> {
 | 
					 | 
				
			||||||
        let pos = s.find("$(");
 | 
					 | 
				
			||||||
        if pos.is_some_and(|pos| s[pos..].contains(')')) {
 | 
					 | 
				
			||||||
            let mut parts = Vec::new();
 | 
					 | 
				
			||||||
            let mut s = s;
 | 
					 | 
				
			||||||
            while let Some(pos) = s.find("$(") {
 | 
					 | 
				
			||||||
                let (before, after) = s.split_at(pos);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let last_macro_index = after
 | 
					 | 
				
			||||||
                    .char_indices()
 | 
					 | 
				
			||||||
                    .skip(2)
 | 
					 | 
				
			||||||
                    .take_while(|&(_, c)| c.is_ascii_alphanumeric() || c == '_')
 | 
					 | 
				
			||||||
                    .map(|(i, _)| i)
 | 
					 | 
				
			||||||
                    .last();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                match last_macro_index {
 | 
					 | 
				
			||||||
                    Some(last_macro_index) if after[last_macro_index + 1..].starts_with(')') => {
 | 
					 | 
				
			||||||
                        if !before.is_empty() {
 | 
					 | 
				
			||||||
                            parts.push(MacroStringPart::String(before.to_string()));
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        parts.push(MacroStringPart::MacroUsage(
 | 
					 | 
				
			||||||
                            after[2..=last_macro_index].to_string(),
 | 
					 | 
				
			||||||
                        ));
 | 
					 | 
				
			||||||
                        s = &after[last_macro_index + 2..];
 | 
					 | 
				
			||||||
                        if s.is_empty() {
 | 
					 | 
				
			||||||
                            break;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    _ => {
 | 
					 | 
				
			||||||
                        parts.push(MacroStringPart::String(s.to_string()));
 | 
					 | 
				
			||||||
                        s = "";
 | 
					 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if !s.is_empty() {
 | 
					 | 
				
			||||||
                parts.push(MacroStringPart::String(s.to_string()));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if parts
 | 
					 | 
				
			||||||
                .iter()
 | 
					 | 
				
			||||||
                .any(|p| matches!(p, MacroStringPart::MacroUsage(_)))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                Ok(Self::MacroString(parts))
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                Ok(Self::String(s.to_string()))
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Ok(Self::String(s.to_string()))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<S> From<S> for MacroString
 | 
					impl<S> From<S> for MacroString
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
    S: Into<String>,
 | 
					    S: Into<String>,
 | 
				
			||||||
| 
						 | 
					@ -227,39 +172,3 @@ impl From<MacroStringLiteral> for MacroString {
 | 
				
			||||||
        Self::from(&value)
 | 
					        Self::from(&value)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#[cfg(test)]
 | 
					 | 
				
			||||||
mod tests {
 | 
					 | 
				
			||||||
    use super::*;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[test]
 | 
					 | 
				
			||||||
    fn test_parse_macro_string() {
 | 
					 | 
				
			||||||
        assert_eq!(
 | 
					 | 
				
			||||||
            MacroString::from_str("Hello, $(world)!").unwrap(),
 | 
					 | 
				
			||||||
            MacroString::MacroString(vec![
 | 
					 | 
				
			||||||
                MacroStringPart::String("Hello, ".to_string()),
 | 
					 | 
				
			||||||
                MacroStringPart::MacroUsage("world".to_string()),
 | 
					 | 
				
			||||||
                MacroStringPart::String("!".to_string())
 | 
					 | 
				
			||||||
            ])
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        assert_eq!(
 | 
					 | 
				
			||||||
            MacroString::from_str("Hello, $(world)! $(world").unwrap(),
 | 
					 | 
				
			||||||
            MacroString::MacroString(vec![
 | 
					 | 
				
			||||||
                MacroStringPart::String("Hello, ".to_string()),
 | 
					 | 
				
			||||||
                MacroStringPart::MacroUsage("world".to_string()),
 | 
					 | 
				
			||||||
                MacroStringPart::String("! $(world".to_string()),
 | 
					 | 
				
			||||||
            ])
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        assert_eq!(
 | 
					 | 
				
			||||||
            MacroString::from_str("Hello $(a) from $(b) and $(c)").unwrap(),
 | 
					 | 
				
			||||||
            MacroString::MacroString(vec![
 | 
					 | 
				
			||||||
                MacroStringPart::String("Hello ".to_string()),
 | 
					 | 
				
			||||||
                MacroStringPart::MacroUsage("a".to_string()),
 | 
					 | 
				
			||||||
                MacroStringPart::String(" from ".to_string()),
 | 
					 | 
				
			||||||
                MacroStringPart::MacroUsage("b".to_string()),
 | 
					 | 
				
			||||||
                MacroStringPart::String(" and ".to_string()),
 | 
					 | 
				
			||||||
                MacroStringPart::MacroUsage("c".to_string()),
 | 
					 | 
				
			||||||
            ])
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -129,8 +129,6 @@ impl<'a> Scope<'a> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Gets the number of times a variable has been shadowed.
 | 
					    /// Gets the number of times a variable has been shadowed.
 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    pub fn get_variable_shadow_count(&self, name: &str) -> usize {
 | 
					    pub fn get_variable_shadow_count(&self, name: &str) -> usize {
 | 
				
			||||||
        let count = self
 | 
					        let count = self
 | 
				
			||||||
            .shadowed
 | 
					            .shadowed
 | 
				
			||||||
| 
						 | 
					@ -140,7 +138,9 @@ impl<'a> Scope<'a> {
 | 
				
			||||||
            .copied()
 | 
					            .copied()
 | 
				
			||||||
            .unwrap_or(0);
 | 
					            .unwrap_or(0);
 | 
				
			||||||
        self.parent.as_ref().map_or(count, |parent| {
 | 
					        self.parent.as_ref().map_or(count, |parent| {
 | 
				
			||||||
            count.saturating_sub(1) + parent.get_variable_shadow_count(name)
 | 
					            count
 | 
				
			||||||
 | 
					                + parent.get_variable_shadow_count(name)
 | 
				
			||||||
 | 
					                + usize::from(parent.get_variable(name).is_some())
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue