⭐ add OP_LEN and allow telling luac a file name
This make debugging easier, since the bytecodes will match between a terminal and lunar_wavemain
parent
565fd19e66
commit
5649f38698
|
@ -31,6 +31,8 @@ pub enum Instruction {
|
|||
// Jump
|
||||
Jmp (i32),
|
||||
|
||||
Len (u8, u8),
|
||||
|
||||
// Load F (Float?)
|
||||
LoadF (u8, i32),
|
||||
|
||||
|
|
|
@ -8,12 +8,35 @@ use crate::{
|
|||
}
|
||||
};
|
||||
|
||||
pub (crate) fn compile_bytecode_from_file (path: &str) -> Vec <u8> {
|
||||
use std::{
|
||||
process::{
|
||||
Command,
|
||||
Stdio,
|
||||
},
|
||||
};
|
||||
|
||||
let child = Command::new ("luac5.4")
|
||||
.arg ("-o") // Output to...
|
||||
.arg ("-") // Standard output
|
||||
.arg (path)
|
||||
.stdout (Stdio::piped ())
|
||||
.spawn ()
|
||||
.expect ("failed to execute `luac5.4`. Is Lua installed?");
|
||||
|
||||
let output = child
|
||||
.wait_with_output ()
|
||||
.expect ("failed to wait on child");
|
||||
|
||||
output.stdout.as_slice ().to_vec ()
|
||||
}
|
||||
|
||||
/// Invoke `luac` as a subprocess
|
||||
/// Luckily luac is single-pass, so we can just pipe in and out
|
||||
///
|
||||
/// `source` is a Vec because we move it to a worker thread
|
||||
|
||||
pub (crate) fn compile_bytecode (source: Vec <u8>) -> Vec <u8> {
|
||||
pub (crate) fn compile_bytecode_from_stdin (source: Vec <u8>) -> Vec <u8> {
|
||||
use std::{
|
||||
io::Write,
|
||||
process::{
|
||||
|
@ -87,6 +110,7 @@ pub fn parse_inst (buf: [u8; 4]) -> Option <Inst>
|
|||
0x2e => Inst::MmBin (a, b, c),
|
||||
0x30 => Inst::MmBinK (a, b, c, k),
|
||||
0x33 => Inst::Not (a, b),
|
||||
0x34 => Inst::Len (a, b),
|
||||
0x3c => Inst::EqK (a, b, k),
|
||||
0x3d => Inst::EqI (a, i_sb (buf)?, k),
|
||||
0x38 => Inst::Jmp (s_j),
|
||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -11,6 +11,7 @@ mod tests;
|
|||
fn main () {
|
||||
use state::State;
|
||||
|
||||
let mut list_bytecode = false;
|
||||
let mut pipe_bytecode = false;
|
||||
let mut script = None;
|
||||
|
||||
|
@ -19,6 +20,7 @@ fn main () {
|
|||
|
||||
while let Some (arg) = args.next () {
|
||||
match arg.as_str () {
|
||||
"--list-bytecode" => list_bytecode = true,
|
||||
"--pipe-bytecode" => pipe_bytecode = true,
|
||||
"--script" => script = Some (args.next ().unwrap ()),
|
||||
"--" => break,
|
||||
|
@ -26,9 +28,9 @@ fn main () {
|
|||
}
|
||||
}
|
||||
|
||||
let lua_file = if let Some (script) = script {
|
||||
let source = std::fs::read (script).expect ("couldn't load Lua source code");
|
||||
let bytecode = loader::compile_bytecode(source);
|
||||
let chunk = if let Some (script) = script {
|
||||
let bytecode = loader::compile_bytecode_from_file (&script);
|
||||
dbg! (&bytecode [0..48]);
|
||||
let mut rdr = std::io::Cursor::new (bytecode);
|
||||
loader::parse_chunk (&mut rdr).unwrap ()
|
||||
}
|
||||
|
@ -40,6 +42,10 @@ fn main () {
|
|||
unimplemented!();
|
||||
};
|
||||
|
||||
if list_bytecode {
|
||||
dbg! (&chunk);
|
||||
}
|
||||
|
||||
let mut vm = State::default ();
|
||||
if std::env::var("LUA_DEBUG").is_ok() {
|
||||
vm.debug_print = true;
|
||||
|
@ -52,5 +58,5 @@ fn main () {
|
|||
program_counter: 0,
|
||||
});
|
||||
|
||||
vm.execute_chunk (&lua_file, &upvalues);
|
||||
vm.execute_chunk (&chunk, &upvalues);
|
||||
}
|
||||
|
|
10
src/state.rs
10
src/state.rs
|
@ -8,12 +8,14 @@ use crate::{
|
|||
},
|
||||
};
|
||||
|
||||
#[derive (Debug)]
|
||||
pub struct Block {
|
||||
pub instructions: Vec <Instruction>,
|
||||
pub constants: Vec <Value>,
|
||||
pub upvalue_count: usize,
|
||||
}
|
||||
|
||||
#[derive (Debug)]
|
||||
pub struct Chunk {
|
||||
pub blocks: Vec <Block>,
|
||||
}
|
||||
|
@ -338,6 +340,14 @@ impl State {
|
|||
*self.reg_mut (*a) = upvalues [b].clone ();
|
||||
},
|
||||
Instruction::Jmp (s_j) => next_pc += s_j,
|
||||
Instruction::Len (a, b) => {
|
||||
let len = match self.reg (*b) {
|
||||
Value::String (s) => s.len (),
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
*self.reg_mut (*a) = len.into ();
|
||||
}
|
||||
Instruction::LoadF (a, sbx) => {
|
||||
*self.reg_mut (*a) = Value::Float (*sbx as f64);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ fn run_bytecode (args: &[&str], bc: &[u8]) -> Vec <Value> {
|
|||
/// and returns the output
|
||||
|
||||
fn run_source (args: &[&str], s: &str) -> Vec <Value> {
|
||||
let bc = loader::compile_bytecode (s.as_bytes ().to_vec ());
|
||||
let bc = loader::compile_bytecode_from_stdin (s.as_bytes ().to_vec ());
|
||||
run_bytecode (args, &bc)
|
||||
}
|
||||
|
||||
|
@ -289,7 +289,7 @@ fn is_93 () {
|
|||
end
|
||||
"#;
|
||||
|
||||
let bc = loader::compile_bytecode (src.as_bytes ().to_vec ());
|
||||
let bc = loader::compile_bytecode_from_stdin (src.as_bytes ().to_vec ());
|
||||
let chunk = loader::parse_chunk_from_bytes (&bc).unwrap ();
|
||||
|
||||
assert_eq! (chunk.blocks [0].instructions [3], Inst::EqK (0, 1, false));
|
||||
|
|
Loading…
Reference in New Issue