Skip to content

Commit 0693913

Browse files
committed
custom impl Debug for Instruction, CallArgs
1 parent 67911cd commit 0693913

File tree

5 files changed

+119
-84
lines changed

5 files changed

+119
-84
lines changed

script/examples/vec2.bs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
fn main()
2-
#for _ in 10_000_000
2+
for _ in 10_000_000
33
#empty()
44
#args(1, 2)
5-
#length(0.5, 0.7)
5+
length(0.5, 0.7)
66
print(length(0.5, 0.7))
77
pass
88

script/src/bin.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub fn main() -> Result<(), io::Error> {
1111
Ok(source) => match ballscript::parse(&source) {
1212
Ok(script) => {
1313
let mut script = script.instance();
14+
dbg!(&script);
1415
match script.call("main", &[]) {
1516
Ok(_) => Ok(()),
1617
Err(e) => todo!("{:?}", e),

script/src/bytecode.rs

+111-77
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,50 @@ use crate::script::CallError;
33
use crate::tokenizer::Op;
44
use crate::{ScriptIter, ScriptType};
55
use core::convert::TryInto;
6+
use core::fmt::{self, Debug, Formatter};
67
use rustc_hash::FxHashMap;
78
use std::collections::hash_map::Entry;
89
use std::rc::Rc;
910

10-
#[derive(Debug)]
1111
pub(crate) struct CallArgs {
1212
store_in: Option<u16>,
1313
func: Box<str>,
1414
args: Box<[u16]>,
1515
}
1616

17-
#[derive(Debug)]
1817
pub(crate) enum Instruction {
1918
Call(Box<(u16, CallArgs)>),
2019
CallSelf(Box<CallArgs>),
2120
CallGlobal(Box<CallArgs>),
2221
//Iter(Box<dyn Iterator<Item = Rc<dyn ScriptType>>>),
2322
//Jmp(u32),
2423
//JmpIf(u16, u32),
25-
2624
RetSome,
2725
RetNone,
2826

2927
IterConst(Box<(u16, u32, Box<dyn ScriptIter>)>),
3028
IterJmp(u16, u32),
3129

32-
/*
30+
/*
3331
AndJmp(u16, u16, u32),
3432
OrJmp(u16, u16, u32),
3533
Xor(u16, u16, u32),
3634
Eq,
3735
Neq,
38-
*/
39-
36+
*/
4037
Add(u16, u16, u16),
4138
//Sub(u16, u16, u16),
4239
Mul(u16, u16, u16),
4340
//Div(u16, u16, u16),
4441
//Rem(u16, u16, u16),
45-
4642
Move(u16, u16),
47-
48-
/*
43+
/*
4944
AddConst,
5045
SubConst,
5146
MulConst,
5247
DivConst,
5348
RemConst,
54-
*/
49+
*/
5550
}
5651

5752
#[derive(Debug)]
@@ -66,7 +61,7 @@ pub(crate) struct ByteCode {
6661
code: Vec<Instruction>,
6762
param_count: u16,
6863
var_count: u16,
69-
consts: Vec<Rc<dyn ScriptType>>,
64+
consts: Vec<Rc<dyn ScriptType>>,
7065
}
7166

7267
#[derive(Debug)]
@@ -97,12 +92,12 @@ pub enum EnvironmentError {
9792
impl ByteCode {
9893
pub(crate) fn parse(
9994
function: Function,
100-
methods: &FxHashMap<&str, ()>,
95+
methods: &FxHashMap<&str, ()>,
10196
locals: &FxHashMap<Box<str>, u16>,
10297
) -> Result<Self, ByteCodeError> {
10398
let mut instr = Vec::new();
10499
let mut vars = FxHashMap::with_hasher(Default::default());
105-
let mut consts = Vec::new();
100+
let mut consts = Vec::new();
106101
let param_count = function.parameters.len() as u16;
107102
for p in function.parameters {
108103
if vars.insert(p, vars.len() as u16).is_some() {
@@ -112,11 +107,11 @@ impl ByteCode {
112107
let mut var_count = vars.len() as u16;
113108
let vars = Self::parse_block(
114109
&function.lines,
115-
methods,
110+
methods,
116111
locals,
117112
&mut instr,
118113
&mut vars,
119-
&mut consts,
114+
&mut consts,
120115
&mut var_count,
121116
0,
122117
)?;
@@ -125,43 +120,47 @@ impl ByteCode {
125120
_ => instr.push(Instruction::RetNone),
126121
}
127122

128-
if consts.len() > 0 {
129-
// All consts are using the upper-most registers, move them downwards
130-
let offset = (u16::MAX - consts.len() as u16).wrapping_add(1);
131-
for i in instr.iter_mut() {
132-
use Instruction::*;
133-
let conv = |c: &mut u16| if *c >= offset { *c = u16::MAX - *c + vars };
134-
match i {
135-
Call(box (_, ca)) | CallSelf(box ca) | CallGlobal(box ca) => {
136-
for a in ca.args.iter_mut() {
137-
conv(a);
138-
}
139-
}
140-
Move(_, a) => conv(a),
141-
Add(_, a, b) | Mul(_, a, b) => {
142-
conv(a);
143-
conv(b);
144-
}
145-
IterConst(_) | IterJmp(_, _) | RetSome | RetNone => (),
146-
}
147-
}
148-
}
123+
if consts.len() > 0 {
124+
// All consts are using the upper-most registers, move them downwards
125+
let offset = (u16::MAX - consts.len() as u16).wrapping_add(1);
126+
for i in instr.iter_mut() {
127+
use Instruction::*;
128+
let conv = |c: &mut u16| {
129+
if *c >= offset {
130+
*c = u16::MAX - *c + vars
131+
}
132+
};
133+
match i {
134+
Call(box (_, ca)) | CallSelf(box ca) | CallGlobal(box ca) => {
135+
for a in ca.args.iter_mut() {
136+
conv(a);
137+
}
138+
}
139+
Move(_, a) => conv(a),
140+
Add(_, a, b) | Mul(_, a, b) => {
141+
conv(a);
142+
conv(b);
143+
}
144+
IterConst(_) | IterJmp(_, _) | RetSome | RetNone => (),
145+
}
146+
}
147+
}
149148

150149
Ok(Self {
151150
code: instr,
152151
var_count: vars,
153152
param_count,
154-
consts,
153+
consts,
155154
})
156155
}
157156

158157
fn parse_block<'a>(
159158
lines: &Lines<'a>,
160-
methods: &FxHashMap<&str, ()>,
159+
methods: &FxHashMap<&str, ()>,
161160
locals: &FxHashMap<Box<str>, u16>,
162161
instr: &mut Vec<Instruction>,
163162
vars: &mut FxHashMap<&'a str, u16>,
164-
consts: &mut Vec<Rc<dyn ScriptType>>,
163+
consts: &mut Vec<Rc<dyn ScriptType>>,
165164
curr_var_count: &mut u16,
166165
mut min_var_count: u16,
167166
) -> Result<u16, ByteCodeError> {
@@ -176,13 +175,15 @@ impl ByteCode {
176175
let mut args = Vec::with_capacity(arguments.len());
177176
// TODO move this to `parse_expression`
178177
for a in arguments {
179-
let mut add_const = |v| {
180-
consts.push(v);
181-
u16::MAX - consts.len() as u16 + 1
182-
};
178+
let mut add_const = |v| {
179+
consts.push(v);
180+
u16::MAX - consts.len() as u16 + 1
181+
};
183182
args.push(match a {
184183
Expression::Atom(a) => match a {
185-
Atom::String(a) => add_const(Rc::new(a.to_string().into_boxed_str())),
184+
Atom::String(a) => {
185+
add_const(Rc::new(a.to_string().into_boxed_str()))
186+
}
186187
Atom::Integer(a) => add_const(Rc::new(*a)),
187188
Atom::Real(a) => add_const(Rc::new(*a)),
188189
Atom::Name(a) => todo!("call {:?}", a),
@@ -200,9 +201,11 @@ impl ByteCode {
200201
match a {
201202
Expression::Atom(a) => {
202203
args.push(match a {
203-
Atom::String(a) => add_const(Rc::new(a.to_string().into_boxed_str())),
204-
Atom::Integer(a) => add_const(Rc::new(*a)),
205-
Atom::Real(a) => add_const(Rc::new(*a)),
204+
Atom::String(a) => add_const(Rc::new(
205+
a.to_string().into_boxed_str(),
206+
)),
207+
Atom::Integer(a) => add_const(Rc::new(*a)),
208+
Atom::Real(a) => add_const(Rc::new(*a)),
206209
Atom::Name(a) => todo!("call {:?}", a),
207210
});
208211
}
@@ -229,11 +232,11 @@ impl ByteCode {
229232
func: (*func).into(),
230233
args: args.into_boxed_slice(),
231234
});
232-
instr.push(if methods.contains_key(func) {
233-
Instruction::CallSelf(args)
234-
} else {
235-
Instruction::CallGlobal(args)
236-
});
235+
instr.push(if methods.contains_key(func) {
236+
Instruction::CallSelf(args)
237+
} else {
238+
Instruction::CallGlobal(args)
239+
});
237240
}
238241
Statement::For { var, expr, lines } => {
239242
let reg = vars.len().try_into().expect("Too many variables");
@@ -261,11 +264,11 @@ impl ByteCode {
261264
let ip = instr.len() as u32;
262265
min_var_count = Self::parse_block(
263266
lines,
264-
methods,
267+
methods,
265268
locals,
266269
instr,
267270
vars,
268-
consts,
271+
consts,
269272
curr_var_count,
270273
min_var_count,
271274
)?;
@@ -440,10 +443,10 @@ impl ByteCode {
440443
vars.resize_with(self.var_count as usize, || {
441444
Rc::new(()) as Rc<dyn ScriptType>
442445
});
443-
vars.extend(self.consts.iter().cloned());
446+
vars.extend(self.consts.iter().cloned());
444447
let mut ip = 0;
445448
let mut iterators = Vec::new();
446-
let mut call_args = Vec::new();
449+
let mut call_args = Vec::new();
447450
loop {
448451
let err_roob = || RunError::RegisterOutOfBounds;
449452
let err_uf = || RunError::UndefinedFunction;
@@ -461,12 +464,12 @@ impl ByteCode {
461464
args,
462465
},
463466
)) => {
464-
for &a in args.iter() {
465-
call_args.push(vars.get(a as usize).ok_or(err_roob())?.clone());
466-
}
467-
let obj = vars.get(*reg as usize).ok_or(err_roob())?.as_ref();
468-
let r = obj.call(func, &call_args[..]).map_err(err_call)?;
469-
call_args.clear();
467+
for &a in args.iter() {
468+
call_args.push(vars.get(a as usize).ok_or(err_roob())?.clone());
469+
}
470+
let obj = vars.get(*reg as usize).ok_or(err_roob())?.as_ref();
471+
let r = obj.call(func, &call_args[..]).map_err(err_call)?;
472+
call_args.clear();
470473
if let Some(reg) = store_in {
471474
*vars.get_mut(*reg as usize).ok_or(err_roob())? = r;
472475
}
@@ -476,11 +479,11 @@ impl ByteCode {
476479
func,
477480
args,
478481
}) => {
479-
for &a in args.iter() {
480-
call_args.push(vars.get(a as usize).ok_or(err_roob())?.clone());
481-
}
482-
let r = env.call(func, &call_args[..]).map_err(err_env)?;
483-
call_args.clear();
482+
for &a in args.iter() {
483+
call_args.push(vars.get(a as usize).ok_or(err_roob())?.clone());
484+
}
485+
let r = env.call(func, &call_args[..]).map_err(err_env)?;
486+
call_args.clear();
484487
if let Some(reg) = store_in {
485488
*vars.get_mut(*reg as usize).ok_or(err_roob())? = r;
486489
}
@@ -490,18 +493,20 @@ impl ByteCode {
490493
func,
491494
args,
492495
}) => {
493-
for &a in args.iter() {
494-
call_args.push(vars.get(a as usize).ok_or(err_roob())?.clone());
495-
}
496-
let r = functions.get(func).ok_or(RunError::UndefinedFunction)?;
497-
let r = r.run(functions, locals, &call_args[..], env)?;
498-
call_args.clear();
499-
// SAFETY: ditto
496+
for &a in args.iter() {
497+
call_args.push(vars.get(a as usize).ok_or(err_roob())?.clone());
498+
}
499+
let r = functions.get(func).ok_or(RunError::UndefinedFunction)?;
500+
let r = r.run(functions, locals, &call_args[..], env)?;
501+
call_args.clear();
502+
// SAFETY: ditto
500503
if let Some(reg) = store_in {
501504
*vars.get_mut(*reg as usize).ok_or(err_roob())? = r;
502505
}
503506
}
504-
RetSome => break Ok(vars.first().ok_or(RunError::RegisterOutOfBounds)?.clone()),
507+
RetSome => {
508+
break Ok(vars.first().ok_or(RunError::RegisterOutOfBounds)?.clone())
509+
}
505510
RetNone => break Ok(Rc::new(())),
506511
IterConst(box (reg, jmp_ip, iter)) => {
507512
let mut iter = iter.iter();
@@ -542,11 +547,11 @@ impl ByteCode {
542547
.get_mut(*r as usize)
543548
.ok_or(RunError::RegisterOutOfBounds)? = e;
544549
}
545-
/*
550+
/*
546551
DupConst(r, c) => {
547552
*vars.get_mut(*r as usize).ok_or(err_roob())? = c.clone();
548553
}
549-
*/
554+
*/
550555
_ => todo!("{:?}", instr),
551556
}
552557
} else {
@@ -585,3 +590,32 @@ impl Environment {
585590
.unwrap())
586591
}
587592
}
593+
594+
/// This returns each instruction on oneline instead of 5+ with the default Debug
595+
impl Debug for Instruction {
596+
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
597+
use Instruction::*;
598+
match self {
599+
Call(box (r, a)) => write!(f, "call {}, {:?}", r, a),
600+
CallSelf(a) => write!(f, "call self, {:?}", a),
601+
CallGlobal(a) => write!(f, "call env, {:?}", a),
602+
Move(a, b) => write!(f, "move {:?}, {:?}", a, b),
603+
RetSome => write!(f, "ret 0"),
604+
RetNone => write!(f, "ret none"),
605+
IterConst(box (r, p, i)) => write!(f, "iter {}, {}, {:?}", r, p, i),
606+
IterJmp(r, p) => write!(f, "iterjmp {}, {}", r, p),
607+
Add(r, a, b) => write!(f, "add {}, {}, {}", r, a, b),
608+
Mul(r, a, b) => write!(f, "mul {}, {}, {}", r, a, b),
609+
}
610+
}
611+
}
612+
613+
impl Debug for CallArgs {
614+
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
615+
if let Some(n) = self.store_in {
616+
write!(f, "{}, \"{}\", {:?}", n, self.func, self.args)
617+
} else {
618+
write!(f, "none, \"{}\", {:?}", self.func, self.args)
619+
}
620+
}
621+
}

script/src/lib.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ pub fn parse(source: &str) -> Result<Class, ()> {
3333

3434
let mut script = Script::new(locals);
3535

36-
let mut methods = FxHashMap::with_capacity_and_hasher(ast.functions.len(), Default::default());
37-
for f in ast.functions.iter() {
38-
methods.insert(f.name, ()).expect_none("Duplicate function");
39-
}
36+
let mut methods = FxHashMap::with_capacity_and_hasher(ast.functions.len(), Default::default());
37+
for f in ast.functions.iter() {
38+
methods.insert(f.name, ()).expect_none("Duplicate function");
39+
}
4040
for f in ast.functions {
4141
let name = f.name.into();
4242
match ByteCode::parse(f, &methods, &script.locals) {

0 commit comments

Comments
 (0)