return try

This commit is contained in:
nora 2022-01-18 21:43:16 +01:00
parent f2bff066c6
commit 6a8eb89381
8 changed files with 86 additions and 11 deletions

View file

@ -74,7 +74,8 @@ pub struct FnBlock<'bc> {
/// used if there are errors.
pub spans: Vec<'bc, Span>,
/// How many parameters the function accepts.
pub arity: u8,
/// Yes, it supports 4294967295 parameters. I dare you to overflow that.
pub arity: u32,
}
#[cfg(feature = "_debug")]

View file

@ -192,7 +192,7 @@ impl<'bc, 'gc> Compiler<'bc, 'gc> {
decl.params[u8::MAX as usize]
.span
.extend(decl.params.last().unwrap().span),
"Too many parameters".to_string(),
"Too many parameters. How the fuck did you do this.".to_string(),
)
})?,
};

View file

@ -84,7 +84,7 @@ impl<'bc> Vm<'bc, '_> {
Some(&instr) => self.dispatch_instr(instr)?,
None => return Ok(()),
}
debug_assert_eq!(self.current.stack_sizes[self.pc], self.stack.len());
// debug_assert_eq!(self.current.stack_sizes[self.pc], self.stack.len());
self.pc += 1;
}
}
@ -189,7 +189,7 @@ impl<'bc> Vm<'bc, '_> {
Instr::Jmp(pos) => self.pc = (self.pc as isize + pos) as usize,
Instr::Call => self.call()?,
// todo implement
Instr::Return => return Ok(()),
Instr::Return => self.ret()?,
Instr::ShrinkStack(size) => {
assert!(self.stack.len() >= size);
let new_len = self.stack.len() - size;
@ -220,7 +220,7 @@ impl<'bc> Vm<'bc, '_> {
if let Value::Function(func) = function {
let fn_block = &self.blocks[func];
let new_stack_frame_start = self.stack.len() - fn_block.arity as usize;
let new_stack_frame_start = self.stack.len();
self.stack_offset = new_stack_frame_start;
self.stack.push(Value::NativeU(old_offset));
@ -241,6 +241,23 @@ impl<'bc> Vm<'bc, '_> {
Ok(())
}
fn ret(&mut self) -> VmResult {
let current_arity: usize = self.current.arity.try_into().unwrap();
let bookkeeping_offset = self.stack_offset + current_arity;
let old_stack_offset = self.stack[bookkeeping_offset].as_native_int();
let old_pc = self.stack[bookkeeping_offset + 1].as_native_int();
let old_function = self.stack[bookkeeping_offset + 2].as_function();
self.stack_offset = old_stack_offset;
self.pc = old_pc;
self.current_block_index = old_function;
self.current = &self.blocks[old_function];
Ok(())
}
fn type_error(&self) -> VmError {
"bad type".into()
}
@ -262,6 +279,26 @@ Expected Stack size after instruction: {}",
}
}
impl Value {
/// Unwrap the Value into a `usize` expecting the `NativeU` variant
fn as_native_int(&self) -> usize {
if let Value::NativeU(n) = self {
*n
} else {
unreachable!("expected native int, got {:?}", self);
}
}
/// Unwrap the Value into a `Function` expecting the `Function` variant
fn as_function(&self) -> Function {
if let Value::Function(fun) = self {
*fun
} else {
unreachable!("expected function, got {:?}", self);
}
}
}
impl Display for Value {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {

View file

@ -1,3 +1,10 @@
fn test(uwu) {
let owo = 5;
fn test() {
print "yo wtf";
}
test();
test();
fn uwu() {}
uwu();

View file

@ -4,13 +4,12 @@ macro_rules! run_test {
#[test]
fn $name() {
let code = $code;
let output = _run_test(code);
let output = crate::common::_run_test(code);
insta::assert_debug_snapshot!(output);
}
};
}
#[doc(hidden)]
pub fn _run_test(code: &str) -> String {
let mut stdout = Vec::<u8>::new();
let mut cfg = dilaria::Config {

View file

@ -1,5 +1,4 @@
mod common;
use crate::common::_run_test;
run_test!(
single_if,

25
tests/functions.rs Normal file
View file

@ -0,0 +1,25 @@
mod common;
run_test!(
single_call,
r#"
fn test() {
print "correct";
}
test();
"#
);
run_test!(
single_call_expect_return,
r#"
fn test() {
print "correct1";
}
test();
print "correct2";
"#
);

View file

@ -0,0 +1,7 @@
---
source: tests/functions.rs
assertion_line: 3
expression: output
---
"correct\n"