constants need 16 bits

This commit is contained in:
Scott Richmond 2025-06-20 15:56:13 -04:00
parent 121861cc8e
commit b3e0af41bb
3 changed files with 34 additions and 27 deletions

View File

@ -272,9 +272,11 @@ impl Chunk {
println!("{i:04}: {op}") println!("{i:04}: {op}")
} }
Constant | MatchConstant => { Constant | MatchConstant => {
let next = self.bytecode[*i + 1]; let high = self.bytecode[*i + 1];
let value = &self.constants[next as usize].show(); let low = self.bytecode[*i + 2];
println!("{i:04}: {:16} {next:03}: {value}", op.to_string()); let idx = ((high as usize) << 8) + low as usize;
let value = &self.constants[idx].show();
println!("{i:04}: {:16} {idx:05}: {value}", op.to_string());
*i += 1; *i += 1;
} }
PushBinding | MatchTuple | MatchSplattedTuple | LoadSplattedTuple | MatchList PushBinding | MatchTuple | MatchSplattedTuple | LoadSplattedTuple | MatchList
@ -381,6 +383,12 @@ fn has_placeholder(args: &[Spanned<Ast>]) -> bool {
args.iter().any(|arg| matches!(arg, (Ast::Placeholder, _))) args.iter().any(|arg| matches!(arg, (Ast::Placeholder, _)))
} }
fn as_two_bytes(x: usize) -> (u8, u8) {
let low = x as u8;
let high = (x >> 8) as u8;
(high, low)
}
impl<'a> Compiler<'a> { impl<'a> Compiler<'a> {
pub fn new( pub fn new(
ast: &'static Spanned<Ast>, ast: &'static Spanned<Ast>,
@ -457,33 +465,39 @@ impl<'a> Compiler<'a> {
self.chunk.constants.len() - 1 self.chunk.constants.len() - 1
}; };
if const_idx > u8::MAX as usize { if const_idx > u16::MAX as usize {
panic!( panic!(
"internal Ludus compiler error: too many constants in chunk:{}:: {}", "internal Ludus compiler error: too many constants in chunk:{}:: {}",
self.span, self.ast self.span, self.ast
) )
} }
self.emit_op(Op::Constant); self.emit_op(Op::Constant);
self.emit_byte(const_idx); let low = const_idx as u8;
let high = (const_idx >> 8) as u8;
self.chunk.bytecode.push(high);
self.chunk.bytecode.push(low);
self.stack_depth += 1; self.stack_depth += 1;
} }
fn match_constant(&mut self, val: Value) { fn match_constant(&mut self, val: Value) {
let constant_index = match self.chunk.constants.iter().position(|v| *v == val) { let const_idx = match self.chunk.constants.iter().position(|v| *v == val) {
Some(idx) => idx, Some(idx) => idx,
None => { None => {
self.chunk.constants.push(val); self.chunk.constants.push(val);
self.chunk.constants.len() - 1 self.chunk.constants.len() - 1
} }
}; };
if constant_index > u8::MAX as usize { if const_idx > u16::MAX as usize {
panic!( panic!(
"internal Ludus compiler error: too many constants in chunk:{}:: {}", "internal Ludus compiler error: too many constants in chunk:{}:: {}",
self.span, self.ast self.span, self.ast
) )
} }
self.emit_op(Op::MatchConstant); self.emit_op(Op::MatchConstant);
self.emit_byte(constant_index); let low = const_idx as u8;
let high = (const_idx >> 8) as u8;
self.chunk.bytecode.push(high);
self.chunk.bytecode.push(low);
} }
fn emit_op(&mut self, op: Op) { fn emit_op(&mut self, op: Op) {
@ -1500,7 +1514,7 @@ impl<'a> Compiler<'a> {
self.tail_pos = tail_pos; self.tail_pos = tail_pos;
self.visit(body); self.visit(body);
self.emit_op(Op::Store); self.emit_op(Op::Store);
self.scope_depth -= 1; // self.scope_depth -= 1;
while let Some(binding) = self.bindings.last() { while let Some(binding) = self.bindings.last() {
if binding.depth > self.scope_depth { if binding.depth > self.scope_depth {
self.bindings.pop(); self.bindings.pop();

View File

@ -114,18 +114,7 @@ pub fn run(src: &'static str) {
pub fn main() { pub fn main() {
env::set_var("RUST_BACKTRACE", "1"); env::set_var("RUST_BACKTRACE", "1");
let src = " let src = "
fn one { let (1, 2, 3) = (1, 2, 3)
(x as :number) -> {
fn two () -> :number
two
}
(x as :bool) -> {
fn two () -> :bool
two
}
}
one (true) ()
"; ";
run(src); run(src);
} }

View File

@ -220,10 +220,12 @@ impl Vm {
self.ip += 1; self.ip += 1;
} }
Constant => { Constant => {
let const_idx = self.chunk().bytecode[self.ip + 1]; let high = self.chunk().bytecode[self.ip + 1];
let value = self.chunk().constants[const_idx as usize].clone(); let low = self.chunk().bytecode[self.ip + 2];
let const_idx = combine_bytes(high, low);
let value = self.chunk().constants[const_idx].clone();
self.push(value); self.push(value);
self.ip += 2; self.ip += 3;
} }
Jump => { Jump => {
let high = self.chunk().bytecode[self.ip + 1]; let high = self.chunk().bytecode[self.ip + 1];
@ -382,10 +384,12 @@ impl Vm {
} }
} }
MatchConstant => { MatchConstant => {
let const_idx = self.chunk().bytecode[self.ip + 1]; let high = self.chunk().bytecode[self.ip + 1];
let low = self.chunk().bytecode[self.ip + 2];
let const_idx = combine_bytes(high, low);
let idx = self.stack.len() - self.match_depth as usize - 1; let idx = self.stack.len() - self.match_depth as usize - 1;
self.matches = self.stack[idx] == self.chunk().constants[const_idx as usize]; self.matches = self.stack[idx] == self.chunk().constants[const_idx];
self.ip += 2; self.ip += 3;
} }
MatchString => { MatchString => {
let pattern_idx = self.chunk().bytecode[self.ip + 1]; let pattern_idx = self.chunk().bytecode[self.ip + 1];