Implement returning expression lists

This commit is contained in:
Sofia 2026-03-15 17:54:48 +02:00
parent 3305d3c162
commit 05da3db5e6
3 changed files with 111 additions and 25 deletions

View File

@ -1,5 +1,11 @@
function add(x) function add(x)
return x return function (y)
return x + y, 1, 2
end
end end
global c = print(add(5)) function test()
return add(10)(15)
end
global c = print(test())

View File

@ -98,7 +98,7 @@ impl Statement {
match self { match self {
Statement::Assignment(access_modifier, name, expr) => { Statement::Assignment(access_modifier, name, expr) => {
let (instr, regs) = expr.kind.compile(state, scope, 1); let (instr, regs) = expr.kind.compile(state, scope, Some(1));
instructions.extend(instr); instructions.extend(instr);
match access_modifier { match access_modifier {
AccessModifier::Local => { AccessModifier::Local => {
@ -115,13 +115,36 @@ impl Statement {
Statement::Return(expr_list) => { Statement::Return(expr_list) => {
let mut ret_registers = Vec::new(); let mut ret_registers = Vec::new();
for expr in &expr_list.0 { for expr in &expr_list.0 {
let (instr, registers) = expr.kind.compile(state, scope, 1); let (instr, registers) = expr.kind.compile(
state,
scope,
if expr_list.0.len() == 1 {
None
} else {
Some(1)
},
);
instructions.extend(instr); instructions.extend(instr);
ret_registers.extend(registers); ret_registers.extend(registers);
} }
let first_ret_register = ret_registers
.iter()
.cloned()
.next()
.unwrap_or(scope.register_counter.0);
for (i, ret_register) in ret_registers.iter_mut().enumerate() {
let new_reg = first_ret_register + i as u16;
if *ret_register != new_reg {
instructions.push(Instruction::Move(new_reg, *ret_register));
}
*ret_register = new_reg;
}
dbg!(&ret_registers);
instructions.push(Instruction::Return( instructions.push(Instruction::Return(
*ret_registers.first().unwrap(), *ret_registers.first().unwrap_or(&scope.register_counter.0),
*ret_registers.last().unwrap(), *ret_registers.last().unwrap_or(&0),
)); ));
} }
Statement::If(node, block) => todo!(), Statement::If(node, block) => todo!(),
@ -170,7 +193,7 @@ impl Expression {
&self, &self,
state: &mut State, state: &mut State,
scope: &mut Scope, scope: &mut Scope,
expected_values: usize, expected_values: Option<usize>,
) -> (Vec<Instruction>, Vec<u16>) { ) -> (Vec<Instruction>, Vec<u16>) {
match self { match self {
Expression::ValueRef(name) => { Expression::ValueRef(name) => {
@ -191,9 +214,9 @@ impl Expression {
} }
Expression::BinOp(binary_operator, lhs, rhs) => { Expression::BinOp(binary_operator, lhs, rhs) => {
let mut instructions = Vec::new(); let mut instructions = Vec::new();
let (instr, lhs) = lhs.kind.compile(state, scope, 1); let (instr, lhs) = lhs.kind.compile(state, scope, Some(1));
instructions.extend(instr); instructions.extend(instr);
let (instr, rhs) = rhs.kind.compile(state, scope, 1); let (instr, rhs) = rhs.kind.compile(state, scope, Some(1));
instructions.extend(instr); instructions.extend(instr);
let reg = scope.register_counter.next(); let reg = scope.register_counter.next();
match binary_operator { match binary_operator {
@ -233,7 +256,9 @@ impl Expression {
inner_scope.upvalues = scope.upvalues.clone(); inner_scope.upvalues = scope.upvalues.clone();
for (name, reg) in &scope.locals { for (name, reg) in &scope.locals {
inner_scope.upvalues.insert(name.clone(), *reg + 1); inner_scope
.upvalues
.insert(name.clone(), *reg + highest_upvalue + 1);
} }
let instructions = block.compile(state, &mut inner_scope); let instructions = block.compile(state, &mut inner_scope);
@ -248,17 +273,28 @@ impl Expression {
} }
Expression::FunctionCall(expr, params) => { Expression::FunctionCall(expr, params) => {
let mut instructions = Vec::new(); let mut instructions = Vec::new();
let (instr, registers) = expr.kind.compile(state, scope, 1);
let (instr, registers) = expr.kind.compile(state, scope, Some(1));
instructions.extend(instr); instructions.extend(instr);
let old_function_reg = registers.first().unwrap(); let old_function_reg = registers.first().unwrap();
let mut param_scope = scope.clone();
let mut original_param_regs = Vec::new(); let mut original_param_regs = Vec::new();
for param in params.kind.0.iter() { for param in params.kind.0.iter() {
let (instr, registers) = param.kind.compile(state, &mut scope.clone(), 1); let (instr, registers) = param.kind.compile(
state,
&mut param_scope,
if params.kind.0.len() == 1 {
None
} else {
Some(1)
},
);
instructions.extend(instr); instructions.extend(instr);
original_param_regs.extend(registers); original_param_regs.extend(registers);
} }
let function_reg = scope.register_counter.next(); let function_reg = scope.register_counter.next();
let mut param_regs = Vec::new(); let mut param_regs = Vec::new();
for _ in &original_param_regs { for _ in &original_param_regs {
@ -271,24 +307,32 @@ impl Expression {
instructions.push(Instruction::Move(*new_reg, *param_reg)); instructions.push(Instruction::Move(*new_reg, *param_reg));
} }
} }
instructions.push(Instruction::Move(function_reg, *old_function_reg)); if function_reg != *old_function_reg {
instructions.push(Instruction::Move(function_reg, *old_function_reg));
}
let last_param_reg = param_regs.last().unwrap_or(&function_reg); let last_param_reg = param_regs.last().unwrap_or(&function_reg);
let mut return_regs = Vec::new(); let mut return_regs = Vec::new();
for i in 0..expected_values { if let Some(expected_values) = expected_values {
let return_reg = i as u16 + function_reg; for i in 0..expected_values {
if return_reg > *last_param_reg { let return_reg = i as u16 + function_reg;
return_regs.push(scope.register_counter.next()); if return_reg > *last_param_reg {
} else { return_regs.push(scope.register_counter.next());
return_regs.push(return_reg); } else {
return_regs.push(return_reg);
}
} }
} }
instructions.push(Instruction::Call( instructions.push(Instruction::Call(
*&function_reg, *&function_reg,
param_regs.len() as u16, param_regs.len() as u16,
return_regs.len() as u16 + 1, if return_regs.len() == 0 {
0
} else {
return_regs.len() as u16 + 1
},
)); ));
(instructions, return_regs) (instructions, return_regs)

View File

@ -157,7 +157,9 @@ impl Closure {
program_counter: 0, program_counter: 0,
stack, stack,
inner: None, inner: None,
function_register: 0,
return_registers: Vec::new(), return_registers: Vec::new(),
top: 0,
} }
} }
} }
@ -167,7 +169,9 @@ pub struct ClosureRunner {
pub program_counter: usize, pub program_counter: usize,
pub stack: HashMap<u16, Value>, pub stack: HashMap<u16, Value>,
pub inner: Option<Box<ClosureRunner>>, pub inner: Option<Box<ClosureRunner>>,
pub function_register: u16,
pub return_registers: Vec<u16>, pub return_registers: Vec<u16>,
pub top: u16,
} }
impl ClosureRunner { impl ClosureRunner {
@ -175,6 +179,13 @@ impl ClosureRunner {
if let Some(inner) = &mut self.inner { if let Some(inner) = &mut self.inner {
if let Some(ret_values) = inner.next() { if let Some(ret_values) = inner.next() {
self.inner = None; self.inner = None;
if self.return_registers.len() == 0 {
for (i, value) in ret_values.iter().enumerate() {
self.stack
.insert(self.function_register + i as u16 + 1, value.clone());
}
self.top = self.function_register + ret_values.len() as u16;
}
for (i, reg) in self.return_registers.iter().enumerate() { for (i, reg) in self.return_registers.iter().enumerate() {
self.stack self.stack
.insert(*reg, ret_values.get(i).cloned().unwrap_or(Value::Nil)); .insert(*reg, ret_values.get(i).cloned().unwrap_or(Value::Nil));
@ -226,15 +237,29 @@ impl ClosureRunner {
} }
} }
Instruction::Call(func_reg, param_len, ret_len) => { Instruction::Call(func_reg, param_len, ret_len) => {
let param_start_func_reg = if *param_len == 0 {
self.function_register
} else {
*func_reg
};
let param_len = if *param_len == 0 {
self.top - self.top.min(param_start_func_reg)
} else {
*param_len
};
self.function_register = *func_reg;
let mut params = Vec::new(); let mut params = Vec::new();
for i in 0..*param_len { for i in 0..param_len {
params.push( params.push(
self.stack self.stack
.get(&(func_reg + i + 1)) .get(&(param_start_func_reg + i + 1))
.unwrap_or(&Value::Nil) .unwrap_or(&Value::Nil)
.clone(), .clone(),
); );
} }
let value = self.stack.get(func_reg).unwrap_or(&Value::Nil); let value = self.stack.get(func_reg).unwrap_or(&Value::Nil);
match value { match value {
Value::RustFunction(func) => { Value::RustFunction(func) => {
@ -248,8 +273,10 @@ impl ClosureRunner {
} }
Value::Function(closure) => { Value::Function(closure) => {
self.return_registers = Vec::new(); self.return_registers = Vec::new();
for i in 0..=(*ret_len - 2) { if *ret_len != 0 {
self.return_registers.push(*func_reg + i); for i in 0..=(*ret_len - 2) {
self.return_registers.push(*func_reg + i);
}
} }
self.inner = Some(Box::new(closure.run(params))); self.inner = Some(Box::new(closure.run(params)));
} }
@ -292,7 +319,16 @@ impl ClosureRunner {
Instruction::Return(reg_start, reg_end) => { Instruction::Return(reg_start, reg_end) => {
self.program_counter += 1; self.program_counter += 1;
let mut ret_values = Vec::new(); let mut ret_values = Vec::new();
for i in *reg_start..=*reg_end { let (reg_start, reg_end) = if *reg_end == 0 {
if self.function_register > 0 && self.top > 0 {
(self.function_register + 1, self.top)
} else {
(*reg_start, *reg_end)
}
} else {
(*reg_start, *reg_end)
};
for i in reg_start..=reg_end {
ret_values.push(self.stack.get(&i).cloned().unwrap_or(Value::Nil)); ret_values.push(self.stack.get(&i).cloned().unwrap_or(Value::Nil));
} }
dbg!(&self.closure.upvalues); dbg!(&self.closure.upvalues);