Skip to content

Commit

Permalink
feat: correct lua call expression bytecode generate
Browse files Browse the repository at this point in the history
  • Loading branch information
sbwtw committed Dec 10, 2023
1 parent d39e473 commit 28e0287
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 29 deletions.
4 changes: 4 additions & 0 deletions lib/src/ast/call_expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ impl CallExpression {
&self.callee
}

pub fn callee_mut(&mut self) -> &mut Expression {
&mut self.callee
}

pub fn arguments(&self) -> &[Expression] {
self.arguments.as_slice()
}
Expand Down
79 changes: 58 additions & 21 deletions lib/src/backend/lua/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::backend::lua::encoding::LuaOpCode;
use crate::backend::TargetCode;

use indexmap::IndexSet;
use std::fmt::{Display, Formatter};
use std::fmt::{Display, Formatter, Write};

pub struct LuaExecState {}

Expand All @@ -14,6 +14,15 @@ pub enum LuaConstants {
Function(fn(&mut LuaExecState) -> i32),
}

impl Display for LuaConstants {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match *self {
LuaConstants::String(ref s) => write!(f, "{s}"),
_ => unreachable!(),
}
}
}

#[derive(Debug)]
pub enum LuaByteCode {
/// Call k, v: k is callee symbol position, v is argument count, return value not included
Expand All @@ -23,33 +32,26 @@ pub enum LuaByteCode {
GetTabUp(u8, u8, u8),
/// A B C: UpValue[A][K[B]:string] := RK(C)
SetTabUp(u8, u8, u8),
/// A B: R[A] := K[Bx]
LoadK(u8, u32),
}

impl LuaByteCode {
fn mnemonic(&self) -> &'static str {
match self {
LuaByteCode::Call(_, _, _) => "CALL",
LuaByteCode::GetTabUp(_, _, _) => "GETTABUP",
LuaByteCode::SetTabUp(_, _, _) => "SETTABUP",
LuaByteCode::Call(..) => "CALL",
LuaByteCode::GetTabUp(..) => "GETTABUP",
LuaByteCode::SetTabUp(..) => "SETTABUP",
LuaByteCode::LoadK(..) => "LOADK",
}
}

fn opcode(&self) -> LuaOpCode {
match self {
LuaByteCode::Call(_, _, _) => LuaOpCode::OP_CALL,
LuaByteCode::GetTabUp(_, _, _) => LuaOpCode::OP_GETTABUP,
LuaByteCode::SetTabUp(_, _, _) => LuaOpCode::OP_SETTABUP,
}
}
}

impl Display for LuaByteCode {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
LuaByteCode::Call(a, b, c) | LuaByteCode::GetTabUp(a, b, c) => {
write!(f, "{:<10} {a} {b} {c}", self.mnemonic())
}
LuaByteCode::SetTabUp(a, b, c) => write!(f, "{:<10} {a} {b} {c}k", self.mnemonic()),
LuaByteCode::Call(..) => LuaOpCode::OP_CALL,
LuaByteCode::GetTabUp(..) => LuaOpCode::OP_GETTABUP,
LuaByteCode::SetTabUp(..) => LuaOpCode::OP_SETTABUP,
LuaByteCode::LoadK(..) => LuaOpCode::OP_LOADK,
}
}
}
Expand All @@ -60,20 +62,55 @@ pub struct LuaCode {
pub constants: IndexSet<LuaConstants>,
}

impl LuaCode {
pub fn disassembly_code(&self, code: &LuaByteCode) -> String {
let mut s = String::with_capacity(16);
write!(s, "{:<10} ", code.mnemonic()).unwrap();

match code {
// ABC
LuaByteCode::Call(a, b, c)
| LuaByteCode::GetTabUp(a, b, c)
| LuaByteCode::SetTabUp(a, b, c) => {
write!(s, "{a} {b} {c}").unwrap();
}
// ABx
LuaByteCode::LoadK(a, bx) => {
write!(s, "{a} {bx}").unwrap();
}
}

match code {
LuaByteCode::LoadK(a, bx) => {
write!(s, " ; {}", self.constants[*bx as usize]).unwrap();
}
LuaByteCode::GetTabUp(a, b, c) => {
write!(s, " ; _ENV \"{}\"", self.constants[*b as usize]).unwrap();
}
LuaByteCode::Call(a, b, c) => {
write!(s, " ; {b} in {c} out").unwrap();
}
_ => {}
}

s
}
}

impl Display for LuaCode {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
// constants
writeln!(f, "Constants:")?;
for constant in self.constants.iter() {
writeln!(f, "{:?}", constant)?
for (idx, constant) in self.constants.iter().enumerate() {
writeln!(f, "{:<3} {:?}", idx, constant)?
}

writeln!(f)?;

// constants
writeln!(f, "ByteCodes:")?;
for (idx, bc) in self.byte_codes.iter().enumerate() {
writeln!(f, "{idx:<6} {:<20}", bc)?
writeln!(f, "{:<6} {:<20}", idx + 1, self.disassembly_code(bc))?
}

Ok(())
Expand Down
24 changes: 16 additions & 8 deletions lib/src/backend/lua/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,32 +171,40 @@ impl AstVisitorMut for LuaBackend {
fn visit_variable_expression_mut(&mut self, variable: &mut VariableExpression) {
trace!("LuaGen: variable expression: {}", variable);

let scope = self.top_attribute().scope.as_ref().unwrap();
self.top_attribute().variable = scope.find_variable(variable.name());
if self.top_attribute().access_mode == AccessModeFlags::CALL {
self.top_attribute().constant_index =
Some(self.add_string_constant(variable.org_name()));
} else {
let scope = self.top_attribute().scope.as_ref().unwrap();
self.top_attribute().variable = scope.find_variable(variable.name());
}
}

fn visit_call_expression_mut(&mut self, call: &mut CallExpression) {
trace!("LuaGen: call expression: {}", call);

self.push_access_attribute(AccessModeFlags::CALL);
self.visit_expression_mut(call.callee_mut());
let callee_index = self.top_attribute().constant_index;
self.pop_attribute();
self.byte_codes.push(LuaByteCode::GetTabUp(0, 0, 0));

// visit all arguments
for arg in call.arguments_mut() {
self.push_access_attribute(AccessModeFlags::PARAMETER);
self.visit_expression_mut(arg);
let arg_value_index = self.top_attribute().constant_index;
self.pop_attribute();

// Load argument
if let Some(idx) = arg_value_index {
let load = LuaByteCode::GetTabUp(0, idx as u8, 0);
let load = LuaByteCode::LoadK(0, idx as u32);
self.byte_codes.push(load);
}
}

let callee_name = call.callee().to_string();
// the index of callee name
let callee_up_k = self.add_string_constant(&callee_name);

self.byte_codes.push(LuaByteCode::Call(
callee_up_k as u8,
callee_index.unwrap() as u8,
call.arguments().len() as u8,
0,
))
Expand Down
1 change: 1 addition & 0 deletions lib/src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ bitflags! {
const READ = 0b0000_0000_0000_0001;
const WRITE = 0b0000_0000_0000_0010;
const PARAMETER = 0b0000_0000_0000_0100;
const CALL = 0b0000_0000_0000_1000;
}
}

Expand Down
6 changes: 6 additions & 0 deletions lib/src/parser/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ pub enum Tok {
Assign,
/// '=>'
AssignRight,
/// 'R='
AssignReset,
/// 'S='
AssignSet,
/// '='
Equal,
/// '<>'
Expand Down Expand Up @@ -198,6 +202,8 @@ impl From<&Tok> for String {
Tok::Colon => ":",
Tok::Assign => ":=",
Tok::AssignRight => "=>",
Tok::AssignSet => "S=",
Tok::AssignReset => "R=",
Tok::Equal => "=",
Tok::NotEqual => "<>",
Tok::Greater => ">",
Expand Down

0 comments on commit 28e0287

Please sign in to comment.