mirror of
https://github.com/Dummi26/mers.git
synced 2025-12-15 03:36:16 +01:00
added := for initialization/declaration
This commit is contained in:
@@ -40,8 +40,8 @@ impl SStatementEnum {
|
||||
pub struct SStatement {
|
||||
/// if the statement is a Variable that doesn't exist yet, it will be initialized.
|
||||
/// if it's a variable that exists, but is_ref is false, an error may show up: cannot dereference
|
||||
/// NOTE: Maybe add a bool that indicates a variable should be newly declared, shadowing old ones with the same name.
|
||||
pub output_to: Option<(Box<SStatement>, usize)>,
|
||||
/// if the third value is true, the variable will always be initialized, shadowing previous mentions of the same name.
|
||||
pub output_to: Option<(Box<SStatement>, usize, bool)>,
|
||||
pub statement: Box<SStatementEnum>,
|
||||
pub force_output_type: Option<VType>,
|
||||
}
|
||||
@@ -55,7 +55,12 @@ impl SStatement {
|
||||
}
|
||||
}
|
||||
pub fn output_to(mut self, statement: SStatement, derefs: usize) -> Self {
|
||||
self.output_to = Some((Box::new(statement), derefs));
|
||||
self.output_to = Some((Box::new(statement), derefs, false));
|
||||
self
|
||||
}
|
||||
/// like output_to, but always initializes the variable (shadows previous variables of the same name)
|
||||
pub fn initialize_to(mut self, statement: SStatement, derefs: usize) -> Self {
|
||||
self.output_to = Some((Box::new(statement), derefs, true));
|
||||
self
|
||||
}
|
||||
// forces the statement's output to fit in a certain type.
|
||||
@@ -248,7 +253,7 @@ impl FormatGs for SStatement {
|
||||
form: &mut super::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
if let Some((opt, derefs)) = &self.output_to {
|
||||
if let Some((opt, derefs, is_init)) = &self.output_to {
|
||||
// TODO!
|
||||
match opt.statement.as_ref() {
|
||||
// SStatementEnum::Variable(name, is_ref) => {
|
||||
@@ -261,7 +266,13 @@ impl FormatGs for SStatement {
|
||||
// )?;
|
||||
// }
|
||||
_ => {
|
||||
write!(f, "{}{} = ", "*".repeat(*derefs), opt.with(info, file))?;
|
||||
write!(
|
||||
f,
|
||||
"{}{} {} ",
|
||||
"*".repeat(*derefs),
|
||||
opt.with(info, file),
|
||||
if *is_init { ":=" } else { "=" }
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,11 @@ pub struct GlobalScriptInfo {
|
||||
pub custom_type_names: HashMap<String, usize>,
|
||||
pub custom_types: Vec<VType>,
|
||||
|
||||
/// if true, trying to assign to the reference of a variable that doesn't exist yet will create and initialize that variable.
|
||||
/// if false, variables will only be initialized if this is explicitly stated.
|
||||
/// settings this to true is useful for "x = 2; x = 5;" syntax in parser implementations that don't differenciate initialization and assignment syntactically.
|
||||
pub to_runnable_automatic_initialization: bool,
|
||||
|
||||
pub formatter: ColorFormatter,
|
||||
|
||||
pub log: Logger,
|
||||
@@ -94,6 +99,7 @@ impl Default for GlobalScriptInfo {
|
||||
enum_variants: Self::default_enum_variants(),
|
||||
custom_type_names: HashMap::new(),
|
||||
custom_types: vec![],
|
||||
to_runnable_automatic_initialization: false,
|
||||
formatter: Default::default(),
|
||||
log: Logger::new(),
|
||||
}
|
||||
|
||||
@@ -371,8 +371,9 @@ fn statement_adv(
|
||||
}
|
||||
SStatementEnum::Variable(v, is_ref) => {
|
||||
let existing_var = linfo.vars.get(v);
|
||||
let is_init_force = if let Some(v) = &to_be_assigned_to { *v.1 } else { false };
|
||||
// we can't assign to a variable that doesn't exist yet -> create a new one
|
||||
if existing_var.is_none() {
|
||||
if is_init_force || (existing_var.is_none() && ginfo.to_runnable_automatic_initialization) {
|
||||
// if to_be_assigned_to is some (-> this is on the left side of an assignment), create a new variable. else, return an error.
|
||||
if let Some((t, is_init)) = to_be_assigned_to {
|
||||
*is_init = true;
|
||||
@@ -401,7 +402,7 @@ fn statement_adv(
|
||||
*is_ref
|
||||
)
|
||||
} else {
|
||||
unreachable!()
|
||||
return Err(ToRunnableError::UseOfUndefinedVariable(v.clone()));
|
||||
}
|
||||
}
|
||||
SStatementEnum::FunctionCall(v, args) => {
|
||||
@@ -678,8 +679,9 @@ fn statement_adv(
|
||||
return Err(ToRunnableError::StatementRequiresOutputTypeToBeAButItActuallyOutputsBWhichDoesNotFitInA(force_opt.clone(), real_output_type, VType { types: problematic_types }));
|
||||
}
|
||||
}
|
||||
if let Some((opt, derefs)) = &s.output_to {
|
||||
let mut is_init = false;
|
||||
if let Some((opt, derefs, is_init)) = &s.output_to {
|
||||
// if false, may be changed to true by statement_adv
|
||||
let mut is_init = *is_init;
|
||||
let optr = statement_adv(
|
||||
opt,
|
||||
ginfo,
|
||||
|
||||
@@ -1005,23 +1005,21 @@ pub mod implementation {
|
||||
)
|
||||
.to()
|
||||
}
|
||||
// 000 =
|
||||
// 000 = :=
|
||||
(0..=0, Some('=')) => {
|
||||
file.next();
|
||||
// NOTE: Old code to change `x = 10` to `&x = 10`
|
||||
// match out.statement.as_mut() {
|
||||
// SStatementEnum::Variable(name, r) => {
|
||||
// if name.starts_with("*") {
|
||||
// *name = name[1..].to_owned();
|
||||
// } else {
|
||||
// *r = true
|
||||
// }
|
||||
// }
|
||||
// _ => {}
|
||||
// }
|
||||
// NOTE: Set this 0 to 1 to prevent a = b = c from being valid
|
||||
parse_statement(file)?.output_to(out, 0)
|
||||
}
|
||||
(0..=0, Some(':'))
|
||||
if matches!(
|
||||
file.get_char(file.get_pos().current_char_index + 1),
|
||||
Some('=')
|
||||
) =>
|
||||
{
|
||||
file.next();
|
||||
file.next();
|
||||
parse_statement(file)?.initialize_to(out, 0)
|
||||
}
|
||||
_ => break,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user