Implement functions
This commit is contained in:
parent
fc50632a6f
commit
7c327beaa1
@ -1 +1,5 @@
|
||||
global c = print(5, 7)
|
||||
function test()
|
||||
return 5
|
||||
end
|
||||
|
||||
global c = print(test())
|
||||
@ -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))
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
20
src/main.rs
20
src/main.rs
@ -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);
|
||||
}
|
||||
|
||||
65
src/vm.rs
65
src/vm.rs
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user