Skip to content

Commit

Permalink
Get 'var.fnname()' method syntax working
Browse files Browse the repository at this point in the history
  • Loading branch information
dfellis committed Mar 12, 2024
1 parent f2dd92d commit da6c226
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ test!(error_exit_code => r#"
test!(non_global_memory_exit_code => r#"
export fn main(): ExitCode {
let x: i64 = 0;
return ExitCode(x);
return x.ExitCode();
}"#;
status 0;
);
Expand Down
4 changes: 2 additions & 2 deletions src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,11 +503,11 @@ test!(strn =>
pass "'str\\'3'";
pass "\"str\\\"4\"";
);
build!(arrayaccess: Vec<WithOperators>, delimited(and!(openarr, optwhitespace), assignables, and!(optwhitespace, closearr)));
build!(arrayaccess: Vec<Vec<WithOperators>>, delimited(and!(openarr, optwhitespace), assignablelist, and!(optwhitespace, closearr)));
named_or!(varsegment: VarSegment =>
Variable: String as variable,
MethodSep: String as and!(optwhitespace, dot, optwhitespace),
ArrayAccess: Vec<WithOperators> as arrayaccess,
ArrayAccess: Vec<Vec<WithOperators>> as arrayaccess,
);
impl VarSegment {
pub fn to_string(&self) -> String {
Expand Down
48 changes: 47 additions & 1 deletion src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,9 @@ fn baseassignablelist_to_microstatements(
}
// TODO: Support more than direct method access in the future, probably
// with a separate resolving function
let fn_name = if let parse::VarSegment::MethodSep(_) = var[0] {
let fn_name = if var.len() == 1 {
var[0].to_string()
} else if let parse::VarSegment::MethodSep(_) = var[0] {
let mut out = "".to_string();
for (i, segment) in var.iter().enumerate() {
if i == 0 {
Expand All @@ -553,6 +555,50 @@ fn baseassignablelist_to_microstatements(
out = format!("{}{}", out, segment.to_string()).to_string();
}
out
} else if let parse::VarSegment::MethodSep(_) = var[1] {
if var.len() != 3 {
var.iter()
.map(|segment| segment.to_string())
.collect::<Vec<String>>()
.join("")
.to_string() // TODO: Support method/property/array access eventually
} else {
let first_var = match &var[0] {
parse::VarSegment::Variable(v) => v.clone(),
_ => unreachable!(),
};
// Scan microstatements backwards for an Assignment or Arg with the
// same name, early exiting with that record.
let mut first_microstatement = None;
for microstatement in microstatements.iter().rev() {
match &microstatement {
Microstatement::Assignment { name, value } if name == &first_var.to_string() => {
first_microstatement = Some(Microstatement::Value {
typen: value.get_type(scope, program)?,
representation: first_var.to_string(),
});
break;
},
Microstatement::Arg { name, typen } if name == &first_var.to_string() => {
first_microstatement = Some(Microstatement::Value {
typen: typen.clone(),
representation: first_var.to_string(),
});
break;
},
_ => continue,
}
}
// Put this argument at the beginning
if let Some(ms) = first_microstatement {
args.insert(0, ms);
}
// TODO Currently assuming it's only something.else()
match &var[2] {
parse::VarSegment::Variable(v) => v.clone(),
_ => unreachable!(),
}
}
} else {
var.iter()
.map(|segment| segment.to_string())
Expand Down

0 comments on commit da6c226

Please sign in to comment.