Add possibility to execute code at any stage
This commit is contained in:
parent
1091f341b9
commit
093e96f8b2
@ -1,4 +1,4 @@
|
||||
local b = 5
|
||||
global b = 5
|
||||
|
||||
function add(x)
|
||||
return function (y)
|
||||
|
||||
@ -73,8 +73,8 @@ impl LocalCounter {
|
||||
}
|
||||
|
||||
impl Block {
|
||||
pub fn find_constants(&self, scope: &mut Scope) -> HashSet<Constant> {
|
||||
let mut constants = HashSet::new();
|
||||
pub fn find_constants(&self, scope: &mut Scope, constants: Vec<Constant>) -> HashSet<Constant> {
|
||||
let mut constants = constants.iter().cloned().collect::<HashSet<_>>();
|
||||
|
||||
let mut inner_scope = scope.clone();
|
||||
|
||||
@ -132,7 +132,7 @@ impl Statement {
|
||||
Statement::If(cond, then) => {
|
||||
let mut constants = HashSet::new();
|
||||
constants.extend(cond.kind.find_constants(scope));
|
||||
constants.extend(then.find_constants(scope));
|
||||
constants.extend(then.find_constants(scope, Vec::new()));
|
||||
constants
|
||||
}
|
||||
Statement::Expression(expr) => expr.kind.find_constants(scope),
|
||||
@ -303,7 +303,7 @@ impl Expression {
|
||||
constants
|
||||
}
|
||||
Expression::UnOp(_, expr) => expr.kind.find_constants(scope),
|
||||
Expression::FunctionDefinition(_, block) => block.find_constants(scope),
|
||||
Expression::FunctionDefinition(_, block) => block.find_constants(scope, Vec::new()),
|
||||
Expression::FunctionCall(expr, params) => {
|
||||
let mut constants = HashSet::new();
|
||||
constants.extend(expr.kind.find_constants(scope));
|
||||
|
||||
52
src/main.rs
52
src/main.rs
@ -40,40 +40,53 @@ impl RustFunction for Print {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
fn compile(
|
||||
text: &str,
|
||||
constants: Vec<vm::Constant>,
|
||||
prototypes: Vec<Vec<vm::Instruction>>,
|
||||
) -> (Vec<vm::Instruction>, compile::State, Vec<vm::Constant>) {
|
||||
let file_path = PathBuf::from("../examples/test.lua");
|
||||
let tokens = tokenize(TEST).unwrap();
|
||||
let tokens = tokenize(text).unwrap();
|
||||
let mut stream = TokenStream::from(&file_path, &tokens);
|
||||
|
||||
dbg!(&tokens);
|
||||
// dbg!(&tokens);
|
||||
|
||||
let chunk = stream.parse::<Block>().unwrap();
|
||||
stream.expect(Token::Eof).unwrap();
|
||||
|
||||
dbg!(&chunk);
|
||||
// dbg!(&chunk);
|
||||
|
||||
let constants = chunk
|
||||
.find_constants(&mut Default::default())
|
||||
.find_constants(&mut Default::default(), constants)
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>();
|
||||
dbg!(&constants);
|
||||
|
||||
let mut state = compile::State {
|
||||
constants: constants.clone(),
|
||||
prototypes: Vec::new(),
|
||||
prototypes,
|
||||
};
|
||||
let mut scope = Default::default();
|
||||
let instructions = chunk.compile(&mut state, &mut scope);
|
||||
|
||||
(instructions, state, constants)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (instructions, state, constants) = compile(TEST, Vec::new(), Vec::new());
|
||||
|
||||
dbg!(&instructions);
|
||||
|
||||
dbg!(&constants);
|
||||
|
||||
let mut vm = VirtualMachine {
|
||||
environment: Default::default(),
|
||||
constants,
|
||||
constants: constants.clone(),
|
||||
prototypes: Default::default(),
|
||||
proto_counter: 0,
|
||||
};
|
||||
let chunk_id = vm.new_prototype(instructions);
|
||||
for prototype in state.prototypes {
|
||||
vm.new_prototype(prototype);
|
||||
for prototype in &state.prototypes {
|
||||
vm.new_prototype(prototype.clone());
|
||||
}
|
||||
dbg!(&vm.prototypes);
|
||||
|
||||
@ -90,7 +103,24 @@ fn main() {
|
||||
|
||||
let mut run = closure.run(Vec::new());
|
||||
|
||||
while run.next().unwrap().is_none() {}
|
||||
while run.next().unwrap().is_none() {
|
||||
let (instructions, state, constants) =
|
||||
compile("print(b)", constants.clone(), state.prototypes.clone());
|
||||
|
||||
// dbg!(&instructions);
|
||||
|
||||
let mut new_run = run.execute(instructions, state, constants);
|
||||
while {
|
||||
match new_run.next() {
|
||||
Ok(Some(_)) => false,
|
||||
Ok(None) => true,
|
||||
Err(e) => {
|
||||
print!("Error: {}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
} {}
|
||||
}
|
||||
|
||||
dbg!(&vm.environment.borrow().globals);
|
||||
}
|
||||
|
||||
64
src/vm.rs
64
src/vm.rs
@ -2,7 +2,10 @@ use thiserror::Error;
|
||||
|
||||
use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};
|
||||
|
||||
use crate::ast::{BinaryOperator, LuaNumber, UnaryOperator};
|
||||
use crate::{
|
||||
ast::{BinaryOperator, LuaNumber, UnaryOperator},
|
||||
compile,
|
||||
};
|
||||
|
||||
pub type VMNumber = u64;
|
||||
|
||||
@ -106,6 +109,8 @@ pub enum RuntimeError {
|
||||
InvalidOperand(UnaryOperator, Value),
|
||||
#[error("Tried calling a non-function: {0:?}")]
|
||||
TriedCallingNonFunction(Value),
|
||||
#[error("Global not found: {0:?}")]
|
||||
GlobalNotFound(Option<Constant>),
|
||||
#[error("{0}")]
|
||||
Custom(String),
|
||||
}
|
||||
@ -321,6 +326,44 @@ impl ClosureRunner {
|
||||
}
|
||||
}
|
||||
|
||||
fn close_upvalues(&self) -> HashMap<u16, Rc<RefCell<Value>>> {
|
||||
let highest_upvalue = self
|
||||
.closure
|
||||
.upvalues
|
||||
.iter()
|
||||
.map(|(v, _)| *v)
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
|
||||
let mut upvalues = self.closure.upvalues.clone();
|
||||
for (reg, value) in &self.stack {
|
||||
upvalues.insert(reg + highest_upvalue + 1, value.clone());
|
||||
}
|
||||
upvalues
|
||||
}
|
||||
|
||||
pub fn execute(
|
||||
&mut self,
|
||||
instructions: Vec<Instruction>,
|
||||
state: compile::State,
|
||||
constants: Vec<Constant>,
|
||||
) -> ClosureRunner {
|
||||
let mut vm = self.closure.vm.clone();
|
||||
vm.constants = constants;
|
||||
let proto_id = vm.new_prototype(instructions);
|
||||
for prototype in state.prototypes {
|
||||
vm.new_prototype(prototype);
|
||||
}
|
||||
|
||||
let closure = Closure {
|
||||
vm,
|
||||
prototype: proto_id,
|
||||
environment: self.closure.environment.clone(),
|
||||
upvalues: self.close_upvalues(),
|
||||
};
|
||||
closure.run(Vec::new())
|
||||
}
|
||||
|
||||
pub fn next(&mut self) -> Result<Option<Vec<Value>>, RuntimeError> {
|
||||
if let Some(inner) = &mut self.inner {
|
||||
match inner.next() {
|
||||
@ -408,7 +451,9 @@ impl ClosureRunner {
|
||||
if let Some(global) = glob {
|
||||
self.set_stack(*reg, global.clone());
|
||||
} else {
|
||||
todo!("Global not found: {:?}", constants.get(*global as usize))
|
||||
return Err(RuntimeError::GlobalNotFound(
|
||||
constants.get(*global as usize).cloned(),
|
||||
));
|
||||
}
|
||||
}
|
||||
Instruction::GetUpVal(reg, upvalreg) => {
|
||||
@ -514,26 +559,13 @@ impl ClosureRunner {
|
||||
}
|
||||
Instruction::Close(_) => {}
|
||||
Instruction::Closure(reg, protok) => {
|
||||
let highest_upvalue = self
|
||||
.closure
|
||||
.upvalues
|
||||
.iter()
|
||||
.map(|(v, _)| *v)
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
|
||||
let mut upvalues = self.closure.upvalues.clone();
|
||||
for (reg, value) in &self.stack {
|
||||
upvalues.insert(reg + highest_upvalue + 1, value.clone());
|
||||
}
|
||||
|
||||
self.set_stack(
|
||||
*reg,
|
||||
Value::Function(Closure {
|
||||
vm: self.closure.vm.clone(),
|
||||
prototype: *protok,
|
||||
environment: self.closure.environment.clone(),
|
||||
upvalues,
|
||||
upvalues: self.close_upvalues(),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user