Implement functions

This commit is contained in:
Sofia 2026-03-14 23:02:28 +02:00
parent fc50632a6f
commit 7c327beaa1
5 changed files with 111 additions and 29 deletions

View File

@ -1 +1,5 @@
global c = print(5, 7)
function test()
return 5
end
global c = print(test())

View File

@ -295,11 +295,13 @@ pub struct ExpressionList(pub Vec<Node<Expression>>);
impl Parse for ExpressionList {
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
let mut list = Vec::new();
list.push(stream.parse()?);
if let Ok(value) = stream.parse() {
list.push(value);
while stream.peek() == Some(Token::Symbol(',')) {
stream.next();
list.push(stream.parse()?);
}
}
Ok(ExpressionList(list))
}

View File

@ -7,6 +7,7 @@ use crate::{
pub struct State {
pub constants: Vec<Constant>,
pub prototypes: Vec<Vec<Instruction>>,
}
impl State {
@ -94,9 +95,9 @@ impl Statement {
instructions.extend(instr);
match access_modifier {
AccessModifier::Local => {
let reg = scope.register_counter.next();
scope.locals.insert(name.kind.clone(), reg);
instructions.push(Instruction::Move(reg, *regs.get(0).unwrap()));
scope
.locals
.insert(name.kind.clone(), *regs.get(0).unwrap());
}
AccessModifier::Global => {
let global = state.get_constant(&Constant::String(name.kind.clone()));
@ -104,7 +105,14 @@ impl Statement {
}
}
}
Statement::Return(node) => todo!(),
Statement::Return(expr) => {
let (instr, registers) = expr.kind.compile(state, scope, 1);
instructions.extend(instr);
instructions.push(Instruction::Return(
*registers.first().unwrap(),
*registers.last().unwrap(),
));
}
Statement::If(node, block) => todo!(),
}
@ -168,7 +176,24 @@ impl Expression {
}
}
Expression::BinOp(binary_operator, node, node1) => todo!(),
Expression::FunctionDefinition(nodes, block) => todo!(),
Expression::FunctionDefinition(params, block) => {
let mut inner_scope = Scope::default();
for param in params {
inner_scope
.locals
.insert(param.kind.clone(), inner_scope.register_counter.next());
}
let instructions = block.compile(state, &mut inner_scope);
state.prototypes.push(instructions);
let mut instructions = Vec::new();
instructions.push(Instruction::Close(scope.register_counter.0));
let local = scope.register_counter.next();
instructions.push(Instruction::Closure(local, state.prototypes.len() as u32));
(instructions, vec![local])
}
Expression::FunctionCall(expr, params) => {
let mut instructions = Vec::new();
let (instr, registers) = expr.kind.compile(state, scope, 1);
@ -183,7 +208,7 @@ impl Expression {
param_regs.extend(registers);
}
let last_param_reg = param_regs.last().unwrap();
let last_param_reg = param_regs.last().unwrap_or(function_register);
let mut return_regs = Vec::new();
for i in 0..expected_values {

View File

@ -58,13 +58,12 @@ fn main() {
.collect::<Vec<_>>();
dbg!(&constants);
let instructions = chunk.compile(
&mut compile::State {
let mut state = compile::State {
constants: constants.clone(),
},
&mut Default::default(),
);
dbg!(&instructions);
prototypes: Vec::new(),
};
let mut scope = Default::default();
let instructions = chunk.compile(&mut state, &mut scope);
let mut vm = VirtualMachine {
environment: Default::default(),
@ -72,6 +71,11 @@ fn main() {
prototypes: Default::default(),
};
vm.prototypes.insert(0, instructions);
for (i, prototype) in state.prototypes.into_iter().enumerate() {
vm.prototypes.insert((i + 1) as u32, prototype);
}
dbg!(&vm.prototypes);
vm.environment.borrow_mut().globals.insert(
vm::Constant::String("max".to_owned()),
vm::Value::RustFunction(Rc::new(RefCell::new(Max))),
@ -85,7 +89,7 @@ fn main() {
let mut run = closure.run();
while run.next() {}
while run.next().is_none() {}
dbg!(vm.environment.borrow());
// dbg!(&vm.environment.borrow().globals);
}

View File

@ -35,16 +35,22 @@ pub enum Instruction {
/// [func] [params.len()] [ret_regs.len()]
/// R(A), ... R(A+C-2) := R(A)(R(A+1), ... R(A+B-1))
Call(u16, u16, u16),
Return(u16, u16),
Close(u16),
Closure(u16, u32),
}
impl Debug for Instruction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Move(arg0, arg1) => write!(f, "MOVE {} {}", arg0, arg1),
Self::LoadK(arg0, arg1) => write!(f, "LOADK {} {}", arg0, arg1),
Self::SetGlobal(arg0, arg1) => write!(f, "SETGLOBAL {} {}", arg0, arg1),
Self::GetGlobal(arg0, arg1) => write!(f, "GETGLOBAL {} {}", arg0, arg1),
Self::Call(arg0, arg1, arg2) => write!(f, "CALL {} {} {}", arg0, arg1, arg2),
Instruction::Move(arg0, arg1) => write!(f, "MOVE {} {}", arg0, arg1),
Instruction::LoadK(arg0, arg1) => write!(f, "LOADK {} {}", arg0, arg1),
Instruction::SetGlobal(arg0, arg1) => write!(f, "SETGLOBAL {} {}", arg0, arg1),
Instruction::GetGlobal(arg0, arg1) => write!(f, "GETGLOBAL {} {}", arg0, arg1),
Instruction::Call(arg0, arg1, arg2) => write!(f, "CALL {} {} {}", arg0, arg1, arg2),
Instruction::Close(arg0) => write!(f, "CLOSE {}", arg0),
Instruction::Closure(arg0, arg1) => write!(f, "CLOSURE {} {}", arg0, arg1),
Instruction::Return(arg0, arg1) => write!(f, "RETURN {} {}", arg0, arg1),
}
}
}
@ -134,6 +140,8 @@ impl Closure {
closure: self.clone(),
program_counter: 0,
stack: HashMap::new(),
inner: None,
return_registers: Vec::new(),
}
}
}
@ -142,10 +150,23 @@ pub struct ClosureRunner {
pub closure: Closure,
pub program_counter: usize,
pub stack: HashMap<u16, Value>,
pub inner: Option<Box<ClosureRunner>>,
pub return_registers: Vec<u16>,
}
impl ClosureRunner {
pub fn next(&mut self) -> bool {
pub fn next(&mut self) -> Option<Vec<Value>> {
if let Some(inner) = &mut self.inner {
if let Some(ret_values) = inner.next() {
self.inner = None;
for (value, reg) in ret_values.iter().zip(&self.return_registers) {
self.stack.insert(*reg, value.clone());
}
} else {
return None;
}
}
let instructions = self
.closure
.vm
@ -202,17 +223,43 @@ impl ClosureRunner {
);
}
}
Value::Function(_) => todo!(),
Value::Function(closure) => {
self.return_registers = Vec::new();
for i in 0..=(*ret_len - 2) {
self.return_registers.push(*func_reg + i);
}
self.inner = Some(Box::new(closure.run()));
}
_ => panic!(),
}
}
Instruction::Close(_) => {}
Instruction::Closure(reg, protok) => {
self.stack.insert(
*reg,
Value::Function(Closure {
vm: self.closure.vm.clone(),
prototype: *protok,
environment: self.closure.environment.clone(),
upvalues: HashMap::new(),
}),
);
}
Instruction::Return(reg_start, reg_end) => {
self.program_counter += 1;
let mut ret_values = Vec::new();
for i in *reg_start..=*reg_end {
ret_values.push(self.stack.get(&i).cloned().unwrap_or(Value::Nil));
}
return Some(ret_values);
}
};
self.program_counter += 1;
true
None
} else {
false
Some(Vec::new())
}
}
}