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