mod code; mod expr_parser; mod expression; mod func_state; pub mod parse_literal; mod parser; mod statement;
pub use code::*;
pub use expression::*;
pub use func_state::*;
pub use parse_literal::*;
use crate::LuaVM;
pub use crate::compiler::parser::LuaLanguageLevel;
use crate::compiler::parser::{LuaLexer, LuaTokenKind, LuaTokenize, Reader, TokensizeConfig};
use crate::lua_value::{Chunk, UpvalueDesc};
use crate::lua_vm::OpCode;
pub fn compile_code(source: &str, vm: &mut LuaVM) -> Result<Chunk, String> {
compile_code_with_name(source, vm, "@chunk")
}
pub fn compile_code_with_name(
source: &str,
vm: &mut LuaVM,
chunk_name: &str,
) -> Result<Chunk, String> {
let level = vm.version;
let tokenize_result = {
let mut lexer = LuaTokenize::new(
Reader::new(source),
TokensizeConfig {
language_level: level,
},
);
lexer.tokenize()
};
let tokens = match tokenize_result {
Ok(tokens) => tokens,
Err(err) => {
return Err(format!("{}:{}", func_state::format_source(chunk_name), err));
}
};
let mut parser = LuaLexer::new(source, tokens, level);
let mut compiler_state = CompilerState::new();
let mut fs = FuncState::new(
&mut parser,
vm,
&mut compiler_state,
true,
chunk_name.to_string(),
);
fs.chunk.use_hidden_vararg = true;
if fs.is_vararg {
let saved_line = fs.lexer.line;
fs.lexer.line = 1;
code::code_abc(&mut fs, OpCode::VarargPrep, 0, 0, 0);
fs.lexer.line = saved_line;
}
fs.upvalues.push(Upvaldesc {
name: "_ENV".to_string(),
in_stack: true,
idx: 0,
kind: VarKind::VDKREG,
});
fs.nups = 1;
let bl = BlockCnt {
previous: None,
first_label: 0,
first_goto: 0,
nactvar: 0,
upval: false,
is_loop: 0,
in_scope: false, };
let block_id = fs.compiler_state.alloc_blockcnt(bl);
fs.block_cnt_id = Some(block_id);
statement::statlist(&mut fs)?;
if fs.lexer.current_token() != LuaTokenKind::TkEof {
return Err(fs.token_error("expected end of file"));
}
let first_reg = fs.nvarstack();
code::ret(&mut fs, first_reg, 0);
statement::leaveblock(&mut fs)?;
code::finish(&mut fs);
fs.chunk.is_vararg = fs.is_vararg;
for upval in &fs.upvalues {
fs.chunk.upvalue_descs.push(UpvalueDesc {
name: upval.name.clone(),
is_local: upval.in_stack,
index: upval.idx as u32,
});
}
fs.chunk.upvalue_count = fs.upvalues.len();
fs.chunk.source_name = Some(chunk_name.to_string());
fs.chunk.linedefined = 0; fs.chunk.lastlinedefined = 0;
fs.chunk.compute_proto_data_size();
Ok(fs.chunk)
}