Implement returning expression lists
This commit is contained in:
parent
3305d3c162
commit
05da3db5e6
@ -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())
|
||||||
@ -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,11 +307,14 @@ impl Expression {
|
|||||||
instructions.push(Instruction::Move(*new_reg, *param_reg));
|
instructions.push(Instruction::Move(*new_reg, *param_reg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if function_reg != *old_function_reg {
|
||||||
instructions.push(Instruction::Move(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();
|
||||||
|
if let Some(expected_values) = expected_values {
|
||||||
for i in 0..expected_values {
|
for i in 0..expected_values {
|
||||||
let return_reg = i as u16 + function_reg;
|
let return_reg = i as u16 + function_reg;
|
||||||
if return_reg > *last_param_reg {
|
if return_reg > *last_param_reg {
|
||||||
@ -284,11 +323,16 @@ impl Expression {
|
|||||||
return_regs.push(return_reg);
|
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)
|
||||||
|
|||||||
42
src/vm.rs
42
src/vm.rs
@ -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,9 +273,11 @@ impl ClosureRunner {
|
|||||||
}
|
}
|
||||||
Value::Function(closure) => {
|
Value::Function(closure) => {
|
||||||
self.return_registers = Vec::new();
|
self.return_registers = Vec::new();
|
||||||
|
if *ret_len != 0 {
|
||||||
for i in 0..=(*ret_len - 2) {
|
for i in 0..=(*ret_len - 2) {
|
||||||
self.return_registers.push(*func_reg + i);
|
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);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user